diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt index 22601b643..694fe3e28 100644 --- a/.ci/dependencies_msys.txt +++ b/.ci/dependencies_msys.txt @@ -12,3 +12,4 @@ libslirp fluidsynth qt5-static qt5-translations +vulkan-headers diff --git a/.editorconfig b/.editorconfig index 29d9ac0ba..fa7defd57 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,34 +5,11 @@ 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 = 4 - -# [Makefile.*] -# indent_style = space -# indent_size = 4 -# tab_width = 4 - [*.manifest] -indent_style = space indent_size = 2 [*.yml] -indent_style = space indent_size = 2 -[**/CMakeLists.txt] -indent_style = space -indent_size = 4 - -[*.cmake] -indent_style = space -indent_size = 4 - -[*.json] -indent_style = space -indent_size = 4 +[*.ui] +indent_size = 1 diff --git a/.gitattributes b/.gitattributes index 32eb262c9..9b39a29c0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,12 +3,28 @@ # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. +# Code *.c text *.cc text *.cpp text *.h text *.hpp text + +# CMake scripts +CMakeLists.txt text +*.cmake text + +# Windows resource scripts and manifests *.rc text +*.manifest text + +# Translation files +*.po text + +# Qt XML files +*.ui text +*.ts text +*.qrc text # Declare files that will always have CRLF line endings on checkout. diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml deleted file mode 100644 index 79f350f4f..000000000 --- a/.github/workflows/c-cpp.yml +++ /dev/null @@ -1,114 +0,0 @@ -name: MSYS2 Makefile - -on: - - push: - paths: - - src/** - - .github/workflows/c-cpp.yml - - "!**/CMakeLists.txt" - - pull_request: - paths: - - src/** - - .github/workflows/c-cpp.yml - - "!**/CMakeLists.txt" - -jobs: - msys2: - name: "Windows MSYS2 Makefile (Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})" - - runs-on: windows-2022 - - defaults: - run: - shell: msys2 {0} - - strategy: - fail-fast: true - matrix: - 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: - - 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 deleted file mode 100644 index bde200b6b..000000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,483 +0,0 @@ -name: CMake - -on: - - push: - paths: - - src/** - - cmake/** - - "**/CMakeLists.txt" - - "CMakePresets.json" - - .github/workflows/cmake.yml - - vcpkg.json - - "!**/Makefile*" - - pull_request: - paths: - - src/** - - cmake/** - - "**/CMakeLists.txt" - - "CMakePresets.json" - - .github/workflows/** - - .github/workflows/cmake.yml - - vcpkg.json - - "!**/Makefile*" - -jobs: - - 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: - shell: msys2 {0} - - strategy: - fail-fast: true - matrix: - 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: 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 - 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 - 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.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 -# 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: 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: - - dynarec: - new: off - target: - name: ARM64 - - steps: - - name: Prepare VS environment - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: ${{ matrix.target.vcvars }} - - - 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.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)" - - 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 -# 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: - - 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 - 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 ./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: | - 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 - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - 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.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 -# 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: - - name: Install source dependencies - run: >- - brew reinstall -s - ${{ matrix.ui.src-packages }} - - - 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 - 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 ./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: | - 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 - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - 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/cmake_linux.yml b/.github/workflows/cmake_linux.yml new file mode 100644 index 000000000..04238ece0 --- /dev/null +++ b/.github/workflows/cmake_linux.yml @@ -0,0 +1,121 @@ +name: CMake (Linux) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/cmake_linux.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake_linux.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + linux: + name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64" + + 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 +# 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: + - 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 + ${{ 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 ./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: | + 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 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}' + path: build/artifacts/** diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml new file mode 100644 index 000000000..5a9f31a01 --- /dev/null +++ b/.github/workflows/cmake_macos.yml @@ -0,0 +1,126 @@ +name: CMake (macos) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/cmake_macos.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake_macos.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + macos12: + name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64" + + runs-on: macos-12 + + 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 +# 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: + - name: Install source dependencies + run: >- + brew reinstall -s + ${{ matrix.ui.src-packages }} + + - name: Install dependencies + run: >- + brew install + ninja + freetype + sdl2 + libpng + rtmidi + openal-soft + fluidsynth + ${{ 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 ./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: | + 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 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + 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/cmake_windows_llvm.yml b/.github/workflows/cmake_windows_llvm.yml new file mode 100644 index 000000000..93f4db241 --- /dev/null +++ b/.github/workflows/cmake_windows_llvm.yml @@ -0,0 +1,163 @@ +name: CMake (Windows, vcpkg/LLVM) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/cmake_windows_llvm.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake_windows_llvm.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + llvm-windows: + name: "${{ 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 +# 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: 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: + - dynarec: + new: off + target: + name: ARM64 + + steps: + - name: Prepare VS environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.target.vcvars }} + + - 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@v4 + with: + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}' + path: build/artifacts/** diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml new file mode 100644 index 000000000..d3f679a78 --- /dev/null +++ b/.github/workflows/cmake_windows_msys2.yml @@ -0,0 +1,144 @@ +name: CMake (Windows, msys2) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/cmake_windows_msys2.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake_windows_msys2.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + msys2: + name: "${{ 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: + shell: msys2 {0} + + strategy: + fail-fast: true + matrix: + 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: Qt GUI + qt: on + static: on + slug: -Qt + packages: >- + qt5-static:p + vulkan-headers: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 + ${{ 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@v4 + with: + name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}' + path: build/artifacts/** diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 5c23961d5..000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,309 +0,0 @@ -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/.github/workflows/codeql_linux.yml b/.github/workflows/codeql_linux.yml new file mode 100644 index 000000000..73ccfb214 --- /dev/null +++ b/.github/workflows/codeql_linux.yml @@ -0,0 +1,111 @@ +name: CodeQL Analysis (Linux) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/codeql_linux.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/codeql_linux.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + 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 + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + 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@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml new file mode 100644 index 000000000..6d2c3861f --- /dev/null +++ b/.github/workflows/codeql_macos.yml @@ -0,0 +1,107 @@ +name: CodeQL Analysis (macos) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/codeql_macos.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/codeql_macos.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + analyze-macos12: + + name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64" + + runs-on: macos-12 + + 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 + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + 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@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml new file mode 100644 index 000000000..2b468f996 --- /dev/null +++ b/.github/workflows/codeql_windows_msys2.yml @@ -0,0 +1,138 @@ +name: CodeQL Analysis (Windows, msys2) + +on: + + push: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/codeql_windows_msys2.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/codeql_windows_msys2.yml + - vcpkg.json + - "!**/Makefile*" + +jobs: + + analyze-msys2: + + name: "${{ 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: Qt GUI + qt: on + static: off + slug: -Qt + packages: >- + qt5-base:p + qt5-tools:p + vulkan-headers: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 + ${{ matrix.ui.packages }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + 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@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.gitignore b/.gitignore index 48a5950b9..5a43dffdb 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,6 @@ CMakeLists.txt.user # MacOS Finder stuff .DS_Store + +# clangd +.cache diff --git a/CMakeLists.txt b/CMakeLists.txt index d9f92add3..c0066e04a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 4.1 + VERSION 4.2 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) @@ -131,15 +131,19 @@ option(RTMIDI "RtMidi" 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) -option(QT "Qt GUI" ON) option(DISCORD "Discord Rich Presence support" ON) +if(WIN32) + set(QT ON) +else() + option(QT "Qt GUI" ON) +endif() + # Development branch features # # Option Description Def. Condition Otherwise @@ -147,18 +151,15 @@ option(DISCORD "Discord Rich Presence support" 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(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" ON "DEV_BRANCH" OFF) +cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) -cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF) cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) # Ditto but for Qt @@ -197,7 +198,7 @@ if(NOT EMU_BUILD_NUM) set(EMU_BUILD_NUM 0) endif() if(NOT EMU_COPYRIGHT_YEAR) - set(EMU_COPYRIGHT_YEAR 2023) + set(EMU_COPYRIGHT_YEAR 2024) endif() add_subdirectory(src) diff --git a/README.md b/README.md index 370bc940e..b4b4142be 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ Performance may vary depending on both host and guest configuration. Most emulat It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines. * [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) +* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia) +* [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python) +* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/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. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..fe8394883 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,18 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| --------- | ------------------ | +| >= master | :white_check_mark: | +| < master | :x: | + +Each version is supported in the form of patch releases until the next version is merged into master. + +## Reporting a Vulnerability + +To report a vulnerability, either open an issue here on GitHub or join our Discord server. If it is +accepted, that means we have begun working on it and it will be fixed if it is at all possible. If it +is declined, then that means we have either determined it to not actually be a vulnerability or we +have determined it is not feasible to fix it. On GitHub, we are going to notify you when a decision +taken, and if accepted, when it is fixed. On Discord, you get live updates. diff --git a/bumpversion.sh b/bumpversion.sh index 4681e72be..6e2536cbe 100644 --- a/bumpversion.sh +++ b/bumpversion.sh @@ -26,12 +26,6 @@ then 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" | @@ -62,12 +56,6 @@ patch_file() { } 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'/' diff --git a/debian/changelog b/debian/changelog index 29ec6d3af..fe8aa6821 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (4.1) UNRELEASED; urgency=medium +86box (4.2) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Mon, 16 Oct 2023 20:24:46 +0200 + -- Jasmine Iwanek Sat, 23 Mar 2024 17:19:08 +0100 diff --git a/debian/control b/debian/control index 78a92bf8f..d67f5965b 100644 --- a/debian/control +++ b/debian/control @@ -1,18 +1,21 @@ Source: 86box Section: otherosfs Priority: optional -Maintainer: Mariusz Kurek +Maintainer: Jasmine Iwanek Build-Depends: cmake (>= 3.21), debhelper-compat (= 13), libevdev-dev, + libfluidsynth-dev, libfreetype-dev, libopenal-dev, libqt5opengl5-dev, librtmidi-dev, libsdl2-dev, libslirp-dev, + libxkbcommon-x11-dev, ninja-build, - qttools5-dev + qttools5-dev, + qtbase5-private-dev Standards-Version: 4.6.0 Homepage: https://86box.net/ #Vcs-Browser: https://salsa.debian.org/debian/86box @@ -26,4 +29,6 @@ Depends: ${shlibs:Depends}, sse2-support [i386] Recommends: libpcap0.8-dev Description: An emulator for classic IBM PC clones -#TODO: insert long description, indented with spaces + 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. \ No newline at end of file diff --git a/debian/copyright b/debian/copyright index 22817edc5..58c9077fa 100644 --- a/debian/copyright +++ b/debian/copyright @@ -8,7 +8,8 @@ Copyright: License: GPL-2.0+ Files: debian/* -Copyright: 2022 Mariusz Kurek +Copyright: 2023 Jasmine Iwanek + 2022 Lili Kurek License: GPL-2.0+ License: GPL-2.0+ diff --git a/debian/rules b/debian/rules index 7b0605e72..1ee4be4ed 100644 --- a/debian/rules +++ b/debian/rules @@ -25,7 +25,10 @@ endif dh $@ --buildsystem cmake+ninja override_dh_auto_configure: - dh_auto_configure --buildsystem cmake+ninja -- --preset regular --toolchain $(TOOLCHAIN) -DNEW_DYNAREC=$(NDR) + dh_auto_configure --buildsystem cmake+ninja -- --preset regular --toolchain $(TOOLCHAIN) -DNEW_DYNAREC=$(NDR) -B . + +override_dh_auto_build: + dh_auto_build --buildsystem cmake+ninja override_dh_auto_test: diff --git a/debian/source/format b/debian/source/format index 163aaf8d8..89ae9db8f 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff --git a/doc/specifications/86box-unit-tester.md b/doc/specifications/86box-unit-tester.md new file mode 100644 index 000000000..48817b27c --- /dev/null +++ b/doc/specifications/86box-unit-tester.md @@ -0,0 +1,267 @@ +# 86Box Unit Tester device specification v1.0.0 + +By GreaseMonkey + other 86Box contributors, 2024. +This specification, including any code samples included, has been released into the Public Domain under the Creative Commons CC0 licence version 1.0 or later, as described here: + +The 86Box Unit Tester is a facility for allowing one to unit-test various parts of 86Box's emulation which would otherwise not be exposed to the emulated system. + +The original purpose of this was to make it possible to analyse and verify aspects of the monitor framebuffers in order to detect and prevent regressions in certain pieces of video hardware. + +---------------------------------------------------------------------------- + +## Versioning + +This specification follows the rules of Semantic Versioning 2.0.0 as documented here: + +The format is `major.minor.patch`. + +- Before you mess with this specification, talk to the other contributors first! +- Any changes need to be tracked in the Version History below, mostly in the event that this document escapes into the wild and doesn't have the Git history attached to it. +- If it clarifies something without introducing any behaviour changes (e.g. formatting changes, spelling fixes), increment the patch version. +- If it introduces a backwards-compatible change, increment the minor version and reset the patch version to 0. +- If it introduces a backwards-incompatible change, increment the major version and reset the minor and patch versions to 0. + - If you make a mistake and accidentally introduce a backward-incompatible change, fix the mistake and increment the minor version. + - To clarify, modifications to *this* section are to be classified as a *patch* version update. +- If you understand SemVer 2.0.0, you may also do other things to the version number according to the specification. + +And lastly, the 3 golden rules of protocol specifications: + +1. If it's not documented, it doesn't exist. +2. If it's not documented but somehow exists, it's a bug. +3. If it's a bug, it needs to be fixed. (Yes, I'm talking to you. You who introduced the bug. Go fix it.) + +The checklist: + +- Work out what kind of version number this document needs. +- Update the version number at the top of the file. +- Add an entry to the "Version History" section below describing roughly what was changed. + +---------------------------------------------------------------------------- + +## Version History + +Dates are based on what day it was in UTC at the time of publication. + +New entries are placed at the top. That is, immediately following this paragraph. + +### v1.0.0 (2024-01-08) +Initial release. Authored by GreaseMonkey. + +---------------------------------------------------------------------------- + +## Conventions + +### Integer types + +- `i8` denotes a signed 8-bit value. +- `u8` denotes an unsigned 8-bit value. +- `w8` denotes an 8-bit value which wraps around. +- `x8` denotes an 8-bit value where the signedness is irrelevant. +- `e8` ("either") denotes an 8-bit value where the most significant bit is clear - in effect, this is a 7-bit unsigned value, and can be interepreted identically as a signed 8-bit value. +- `u16L` denotes a little-endian unsigned 16-bit value. +- `u16B` would denote a big-endian unsigned 16-bit value if we had any big-endian values. +- `[N]T` denotes an array of `N` values of type `T`, whatever `N` and `T` are. + +---------------------------------------------------------------------------- + +## Usage + +### Accessing the device and configuring the I/O base address + +Find an area in I/O space where 2 addresses are confirmed (or assumed) to be unused. +There is no need for the 2 addresses to be 2-byte-aligned. + +Send the following sequence of bytes to port 0x80 with INTERRUPTS DISABLED: + + '8', '6', 'B', 'o', 'x', (IOBASE & 0xFF), (IOBASE >> 8) + +Alternatively denoted in hex: + + 38 36 42 6F 78 yy xx + +There are no timing constraints. This is an emulator, after all. + +To confirm that this has happened, read the status port at IOBASE+0x00. +If it's 0xFF, then the device is most likely not present. +Otherwise, one can potentially assume that it exists and has been configured successfully. +(You *did* make sure that the space was unused *before* doing this, right?) + +IOBASE is allowed to overlap the trigger port, but please don't do this! + +### Hiding the device + +Set the I/O base address to 0xFFFF using the above method. + +### Executing commands + +The ports at IOBASE+0x00 and IOBASE+0x01 are all 8 bits wide. + +Writing to IOBASE+0x00 cancels any in-flight commands and sends a new command. + +Reading from IOBASE+0x00 reads the status: + +- bit 0: There is data to be read from this device + - If one reads with this bit clear, the returned data will be 0xFF. +- bit 1: The device is expecting data to be sent to it + - If one writes with this bit clear, the data will be ignored. +- bit 2: There is no command in flight + - If this is set, then bits 0 and 1 will be clear. +- bit 3: The previously-sent command does not exist. +- bits 4 .. 7: Reserved, should be 0. + +Writing to IOBASE+0x01 provides data to the device if said data is needed. + +Reading from IOBASE+0x01 fetches the next byte data to the device if said data is needed. + +### General flow of executing a command: + +This is how most commands will work. + +- Write the command to IOBASE+0x00. +- If data needs to be written or read: + - Read the status from IOBASE+0x00 and confirm that bit 2 is clear. + If it is set, then the command may not exist. + Check bit 3 if that's the case. +- If data needs to be written: + - Write all the data one needs to write. +- If data needs to be read: + - Read the status from IOBASE+0x00 and wait until bit 0 is set. + If it is set, then the command may not exist. + Check bit 3 if that's the case. + - Keep reading bytes until one is satisfied. +- Otherwise: + - Read the status from IOBASE+0x00 and wait until any of the bottom 3 bits are set. + +---------------------------------------------------------------------------- + +## Command reference + +### 0x00: No-op + +This does nothing, takes no input, and gives no output. + +This is an easy way to reset the status to 0x04 (no command in flight, not waiting for reads or writes, and no errors). + +### 0x01: Capture Screen Snapshot + +Captures a snapshot of the current screen state and stores it in the current snapshot buffer. + +The initial state of the screen snapshot buffer has an image area of 0x0, an overscanned area of 0x0, and an image start offset of (0,0). + +Input: + +* u8 monitor + - 0x00 = no monitor - clear the screen snapshot + - 0x01 = primary monitor + - 0x02 = secondary monitor + - Any monitor which is not available is treated as 0x00, and clears the screen snapshot. + +Output: + +* `e16L` image width in pixels +* `e16L` image height in pixels +* `e16L` overscanned width in pixels +* `e16L` overscanned height in pixels +* `e16L` X offset of image start +* `e16L` Y offset of image start + +If there is no screen snapshot, then all values will be 0 as per the initial screen snapshot buffer state. + +### 0x02: Read Screen Snapshot Rectangle + +Returns a rectangular snapshot of the screen snapshot buffer as an array of 32bpp 8:8:8:8 B:G:R:X pixels. + +Input: + +* `e16L` w: rectangle width in pixels +* `e16L` h: rectangle height in pixels +* `i16L` x: X offset relative to image start +* `i16L` y: Y offset relative to image start + +Output: + +* `[h][w][4]u8`: image data + - `[y][x][0]` is the blue component, or 0x00 if the pixel is outside the snapshot area. + - `[y][x][1]` is the green component, or 0x00 if the pixel is outside the snapshot area. + - `[y][x][2]` is the red component, or 0x00 if the pixel is outside the snapshot area. + - `[y][x][3]` is 0x00, or 0xFF if the pixel is outside the snapshot area. + +### 0x03: Verify Screen Snapshot Rectangle + +As per 0x02 "Read Screen Snapshot Rectangle", except instead of returning the pixel data, it returns a CRC-32 of the data. + +The CRC is as per zlib's `crc32()` function. Specifically, one uses a right-shifting Galois LFSR with a polynomial of 0xEDB88320, bytes XORed against the least significant byte, the initial seed is 0xFFFFFFFF, and all bits of the output are inverted. + +(Rationale: There are better CRCs, but this one is ubiquitous and still really good... and we don't need to protect against deliberate tampering.) + +Input: + +* `e16L` w: rectangle width in pixels +* `e16L` h: rectangle height in pixels +* `i16L` x: X offset relative to image start +* `i16L` y: Y offset relative to image start + +Output: + +* `u32L` crc: CRC-32 of rectangle data + +### 0x04: Exit 86Box + +Exits 86Box, unless this command is disabled. + +- If the command is enabled, then program execution terminates immediately. +- If the command is disabled, it still counts as having executed correctly, but program execution continues. This makes it useful to show a "results" screen for a unit test. + +Input: + +* u8 exit code: + - The actual exit code is clamped to no greater than the maximum valid exit code. + - In practice, this is probably going to be 0x7F. + +---------------------------------------------------------------------------- + +## Implementation notes + +### Port 0x80 sequence detection + +In order to ensure that one can always trigger the activation sequence, there are effectively two finite state machines in action. + +FSM1: +- Wait for 8. +- Wait for 6. +- Wait for B. +- Wait for o. +- Wait for x. + Once received, set FSM2 to "Wait for low byte", + then go back to "Wait for 8". + +If at any point an 8 arrives, jump to the "Wait for 6" step. + +Otherwise, if any other unexpected byte arrives, jump to the "Wait for 8" step. + +FSM2: +- Idle. +- Wait for low byte. Once received, store this in a temporary location. +- Wait for high byte. + Once received, replace IOBASE with this byte in the high byte and the temporary value in the low byte, + then go back to "Idle". + +---------------------------------------------------------------------------- + +## Extending the protocol + +### Adding new commands + +Commands 0x01 through 0x7F accept a single command byte. + +Command bytes 0x80 through 0xFB are reserved for 16-bit command IDs, to be written in a similar way to this: + +- Write the first command byte (0x80 through 0xFF) to the command register. +- If this block of commands does not exist, then the command is cancelled and the status is set to 0x0C. +- Otherwise, the status is set to 0x0 +- Write the next command byte (0x00 through 0xFF) to the data register. +- If this block of commands does not exist, then the command is cancelled and the status is set to 0x0C. +- Otherwise, the command exists and the status is set according to the command. + +Command bytes 0xFC through 0xFF are reserved for if we somehow need more than 16 bits worth of command ID. + diff --git a/src/86box.c b/src/86box.c index bf9be5086..61b81bbf3 100644 --- a/src/86box.c +++ b/src/86box.c @@ -30,10 +30,10 @@ #include #include #include +#include #ifndef _WIN32 # include -# include #endif #ifdef __APPLE__ # include @@ -65,6 +65,8 @@ #include <86box/machine.h> #include <86box/bugger.h> #include <86box/postcard.h> +#include <86box/unittester.h> +#include <86box/novell_cardkey.h> #include <86box/isamem.h> #include <86box/isartc.h> #include <86box/lpt.h> @@ -111,7 +113,7 @@ /* Stuff that used to be globally declared in plat.h but is now extern there and declared here instead. */ -int dopause; /* system is paused */ +int dopause = 1; /* system is paused */ atomic_flag doresize; /* screen resize requested */ volatile int is_quit; /* system exit requested */ uint64_t timer_freq; @@ -172,13 +174,16 @@ 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 novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */ int postcard_enabled = 0; /* (C) enable POST card */ +int unittester_enabled = 0; /* (C) enable unit tester device */ 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 lba_enhancer_enabled = 0; /* (C) enable Vision Systems LBA Enhancer */ 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 @@ -201,6 +206,12 @@ int video_fullscreen_scale_maximized = 0; /* (C) Whether also apply when maximized. */ int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus loss */ +char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ + +int other_ide_present = 0; /* IDE controllers from non-IDE cards are + present */ +int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are + present */ /* Statistics. */ extern int mmuflush; @@ -236,8 +247,8 @@ int efscrnsz_y = SCREEN_RES_Y; static wchar_t mouse_msg[3][200]; -static int do_pause_ack = 0; -static volatile int pause_ack = 0; +static volatile atomic_int do_pause_ack = 0; +static volatile atomic_int pause_ack = 0; #ifndef RELEASE_BUILD static char buff[1024]; @@ -542,7 +553,9 @@ usage: 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"); +#ifndef USE_SDL_UI printf("-S or --settings - show only the settings dialog\n"); +#endif 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"); @@ -609,8 +622,10 @@ usage: goto usage; strcpy(vm_name, argv[++c]); +#ifndef USE_SDL_UI } else if (!strcasecmp(argv[c], "--settings") || !strcasecmp(argv[c], "-S")) { settings_only = 1; +#endif } else if (!strcasecmp(argv[c], "--noconfirm") || !strcasecmp(argv[c], "-N")) { confirm_exit_cmdl = 0; } else if (!strcasecmp(argv[c], "--missing") || !strcasecmp(argv[c], "-M")) { @@ -945,12 +960,12 @@ pc_init_modules(void) /* Load the ROMs for the selected machine. */ if (!machine_available(machine)) { - swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2063), machine_getname()); + swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_MACHINE), 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); + ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp); machine = c; config_save(); break; @@ -967,12 +982,12 @@ pc_init_modules(void) 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); + swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_VIDEO), 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); + ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp); gfxcard[0] = c; config_save(); break; @@ -988,8 +1003,8 @@ pc_init_modules(void) 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); + swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_VIDEO2), tempc); + ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp); gfxcard[1] = 0; } @@ -1042,6 +1057,7 @@ pc_send_ca(uint16_t sc) keyboard_input(1, 0x1D); /* Ctrl key pressed */ keyboard_input(1, 0x38); /* Alt key pressed */ keyboard_input(1, sc); + usleep(50000); keyboard_input(0, sc); keyboard_input(0, 0x38); /* Alt key released */ keyboard_input(0, 0x1D); /* Ctrl key released */ @@ -1069,18 +1085,22 @@ pc_reset_hard_close(void) /* Close all the memory mappings. */ mem_close(); + suppress_overscan = 0; + /* Turn off timer processing to avoid potential segmentation faults. */ timer_close(); - suppress_overscan = 0; + lpt_devices_close(); + +#ifdef UNCOMMENT_LATER + lpt_close(); +#endif nvr_save(); nvr_close(); mouse_close(); - lpt_devices_close(); - device_close_all(); scsi_device_close_all(); @@ -1121,6 +1141,9 @@ pc_reset_hard_init(void) * modules that are. */ + /* Reset the IDE and SCSI presences */ + other_ide_present = other_scsi_present = 0; + /* Mark ACPI as unavailable */ acpi_enabled = 0; @@ -1153,9 +1176,6 @@ pc_reset_hard_init(void) * that will be a call to device_reset_all() later ! */ - if (joystick_type) - gameport_update_joystick_type(); - /* Reset and reconfigure the Sound Card layer. */ sound_card_reset(); @@ -1163,13 +1183,14 @@ pc_reset_hard_init(void) /* note: PLIP LPT side has to be initialized before the network side */ lpt_devices_init(); - /* Reset and reconfigure the Network Card layer. */ - network_reset(); - /* Reset and reconfigure the serial ports. */ + /* note: SLIP COM side has to be initialized before the network side */ serial_standalone_init(); serial_passthrough_init(); + /* Reset and reconfigure the Network Card layer. */ + network_reset(); + /* * Reset the mouse, this will attach it to any port needed. */ @@ -1199,10 +1220,13 @@ pc_reset_hard_init(void) /* Reset any ISA RTC cards. */ isartc_reset(); - /* Initialize the Voodoo cards here inorder to minmize + /* Initialize the Voodoo cards here inorder to minimize the chances of the SCSI controller ending up on the bridge. */ video_voodoo_init(); + if (joystick_type) + gameport_update_joystick_type(); /* installs game port if no device provides one, must be late */ + ui_sb_update_panes(); if (config_changed) { @@ -1217,12 +1241,24 @@ pc_reset_hard_init(void) device_add(&bugger_device); if (postcard_enabled) device_add(&postcard_device); + if (unittester_enabled) + device_add(&unittester_device); + + if (lba_enhancer_enabled) + device_add(&lba_enhancer_device); + + if (novell_keycard_enabled) + device_add(&novell_keycard_device); if (IS_ARCH(machine, MACHINE_BUS_PCI)) { pci_register_cards(); device_reset_all(DEVICE_PCI); } + /* Mark IDE shadow drives (slaves with a present master) as such in case + the IDE controllers present are not some form of PCI. */ + ide_drives_set_shadow(); + /* Reset the CPU module. */ resetx86(); dma_reset(); @@ -1266,17 +1302,17 @@ update_mouse_msg(void) 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)); + plat_get_string(STRING_MOUSE_CAPTURE)); 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)); + (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); 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)); + plat_get_string(STRING_MOUSE_CAPTURE)); 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)); + (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); 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 @@ -1359,9 +1395,9 @@ _ui_window_title(void *s) void ack_pause(void) { - if (do_pause_ack) { - do_pause_ack = 0; - pause_ack = 1; + if (atomic_load(&do_pause_ack)) { + atomic_store(&do_pause_ack, 0); + atomic_store(&pause_ack, 1); } } @@ -1579,12 +1615,14 @@ get_actual_size_y(void) void do_pause(int p) { - if (p) + int old_p = dopause; + + if ((p == 1) && !old_p) do_pause_ack = p; - dopause = p; - if (p) { - while (!pause_ack) + dopause = !!p; + if ((p == 1) && !old_p) { + while (!atomic_load(&pause_ack)) ; } - pause_ack = 0; + atomic_store(&pause_ack, 0); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bfa582e33..7030e9f63 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -226,8 +226,7 @@ endif() if (QT) add_subdirectory(qt) -elseif(WIN32) - add_subdirectory(win) else() + add_compile_definitions(USE_SDL_UI) add_subdirectory(unix) endif() diff --git a/src/Makefile.local b/src/Makefile.local deleted file mode 100644 index fdb2dcab3..000000000 --- a/src/Makefile.local +++ /dev/null @@ -1,200 +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. -# -# Prefix for localizing the general Makefile.mingw for local -# settings, so we can avoid changing the main one for all of -# our local setups. -# -# Authors: Fred N. van Kempen, -# - -######################################################################### -# Anything here will override defaults in Makefile.MinGW. # -######################################################################### - - -# Name of the executable. -#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 := - -# Add feature selections here. -# -DANSI_CFG forces the config file to ANSI encoding. -# Root logging: -# -DENABLE_ACPI_LOG=N sets logging level at N. -# -DENABLE_APM_LOG=N sets logging level at N. -# -DENABLE_BUGGER_LOG=N sets logging level at N. -# -DENABLE_CONFIG_LOG=N sets logging level at N. -# -DENABLE_DDMA_LOG=N sets logging level at N. -# -DENABLE_DEVICE_LOG=N sets logging level at N. -# -DENABLE_DMA_LOG=N sets logging level at N. -# -DENABLE_IO_LOG=N sets logging level at N. -# -DENABLE_IOAPIC_LOG=N sets logging level at N. -# -DENABLE_ISAMEM_LOG=N sets logging level at N. -# -DENABLE_ISARTC_LOG=N sets logging level at N. -# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N. -# -DENABLE_KEYBOARD_XT_LOG=N sets logging level at N. -# -DENABLE_LM75_LOG=N sets logging level at N. -# -DENABLE_LM78_LOG=N sets logging level at N. -# -DENABLE_MEM_LOG=N sets logging level at N. -# -DENABLE_MOUSE_LOG=N sets logging level at N. -# -DENABLE_MOUSE_BUS_LOG=N sets logging level at N. -# -DENABLE_MOUSE_PS2_LOG=N sets logging level at N. -# -DENABLE_MOUSE_SERIAL_LOG=N sets logging level at N. -# -DENABLE_NVR_LOG=N sets logging level at N. -# -DENABLE_PC_LOG=N sets logging level at N. -# -DENABLE_PCI_LOG=N sets logging level at N. -# -DENABLE_PIC_LOG=N sets logging level at N. -# -DENABLE_PIT_LOG=N sets logging level at N. -# -DENABLE_POSTCARD_LOG=N sets logging level at N. -# -DENABLE_ROM_LOG=N sets logging level at N. -# -DENABLE_SERIAL_LOG=N sets logging level at N. -# -DENABLE_SMBUS_LOG=N sets logging level at N. -# -DENABLE_SMBUS_PIIX4_LOG=N sets logging level at N. -# -DENABLE_SPD_LOG=N sets logging level at N. -# -DENABLE_USB_LOG=N sets logging level at N. -# -DENABLE_VNC_LOG=N sets logging level at N. -# -DENABLE_VNC_KEYMAP_LOG=N sets logging level at N. -# cdrom/ logging: -# -DENABLE_CDROM_LOG=N sets logging level at N. -# -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N. -# -DENABLE_CDROM_IMAGE_BACKEND_LOG=N sets logging level at N. -# chipset/ logging: -# -DENABLE_I420EX_LOG=N sets logging level at N. -# -DENABLE_NEAT_LOG=N sets logging level at N. -# -DENABLE_OPTI495_LOG=N sets logging level at N. -# -DENABLE_OPTI895_LOG=N sets logging level at N. -# -DENABLE_PIIX_LOG=N sets logging level at N. -# -DENABLE_SIO_LOG=N sets logging level at N. -# -DENABLE_SIS_85C496_LOG=N sets logging level at N. -# codegen/, codegen_new/, cpu/ logging: -# -DENABLE_X86SEG_LOG=N sets logging level at N. -# cpu/ logging: -# -DENABLE_386_LOG=N sets logging level at N. -# -DENABLE_386_COMMON_LOG=N sets logging level at N. -# -DENABLE_386_DYNAREC_LOG=N sets logging level at N. -# -DENABLE_808X_LOG=N sets logging level at N. -# -DENABLE_CPU_LOG=N sets logging level at N. -# -DENABLE_FPU_LOG=N sets logging level at N. -# disk/ logging: -# -DENABLE_ESDI_AT_LOG=N sets logging level at N. -# -DENABLE_ESDI_MCA_LOG=N sets logging level at N. -# -DENABLE_HDC_LOG=N sets logging level at N. -# -DENABLE_HDD_IMAGE_LOG=N sets logging level at N. -# -DENABLE_IDE_LOG=N sets logging level at N. -# -DENABLE_MO_LOG=N sets logging level at N. -# -DENABLE_SFF_LOG=N sets logging level at N. -# -DENABLE_ST506_AT_LOG=N sets logging level at N. -# -DENABLE_ST506_XT_LOG=N sets logging level at N. -# -DENABLE_XTA_LOG=N sets logging level at N. -# -DENABLE_ZIP_LOG=N sets logging level at N. -# floppy/ logging: -# -DENABLE_D86F_LOG=N sets logging level at N. -# -DENABLE_FDC_LOG=N sets logging level at N. -# -DENABLE_FDD_LOG=N sets logging level at N. -# -DENABLE_FDI_LOG=N sets logging level at N. -# -DENABLE_FDI2RAW_LOG=N sets logging level at N. -# -DENABLE_IMD_LOG=N sets logging level at N. -# -DENABLE_IMG_LOG=N sets logging level at N. -# -DENABLE_JSON_LOG=N sets logging level at N. -# -DENABLE_MFM_LOG=N sets logging level at N. -# -DENABLE_TD0_LOG=N sets logging level at N. -# machine/ logging: -# -DENABLE_AMSTRAD_LOG=N sets logging level at N. -# -DENABLE_EUROPC_LOG=N sets logging level at N. -# -DENABLE_M24VID_LOG=N sets logging level at N. -# -DENABLE_MACHINE_LOG=N sets logging level at N. -# -DENABLE_PS1_HDC_LOG=N sets logging level at N. -# -DENABLE_PS2_MCA_LOG=N sets logging level at N. -# -DENABLE_TANDY_LOG=N sets logging level at N. -# -DENABLE_T1000_LOG=N sets logging level at N. -# -DENABLE_T3100E_LOG=N sets logging level at N. -# network/ logging: -# -DENABLE_3COM503_LOG=N sets logging level at N. -# -DENABLE_DP8390_LOG=N sets logging level at N. -# -DENABLE_NETWORK_LOG=N sets logging level at N. -# -DENABLE_NE2K_LOG=N sets logging level at N. -# -DENABLE_PCAP_LOG=N sets logging level at N. -# -DENABLE_PCNET_LOG=N sets logging level at N. -# -DENABLE_SLIRP_LOG=N sets logging level at N. -# -DENABLE_WD_LOG=N sets logging level at N. -# printer/ logging: -# -DENABLE_ESCP_LOG=N sets logging level at N. -# scsi/ logging: -# -DENABLE_AHA154X_LOG=N sets logging level at N. -# -DENABLE_BUSLOGIC_LOG=N sets logging level at N. -# -DENABLE_NCR5380_LOG=N sets logging level at N. -# -DENABLE_NCR53C8XX_LOG=N sets logging level at N. -# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N. -# -DENABLE_SCSI_DISK_LOG=N sets logging level at N. -# -DENABLE_SPOCK_LOG=N sets logging level at N. -# -DENABLE_X54X_LOG=N sets logging level at N. -# sound/ logging: -# -DENABLE_ADLIB_LOG=N sets logging level at N. -# -DENABLE_AUDIOPCI_LOG=N sets logging level at N. -# -DENABLE_EMU8K_LOG=N sets logging level at N. -# -DENABLE_MPU401_LOG=N sets logging level at N. -# -DENABLE_PAS16_LOG=N sets logging level at N. -# -DENABLE_SB_LOG=N sets logging level at N. -# -DENABLE_SB_DSP_LOG=N sets logging level at N. -# -DENABLE_SOUND_LOG=N sets logging level at N. -# video/ logging: -# -DENABLE_ATI28800_LOG=N sets logging level at N. -# -DENABLE_MACH64_LOG=N sets logging level at N. -# -DENABLE_COMPAQ_CGA_LOG=N sets logging level at N. -# -DENABLE_ET4000W32_LOG=N sets logging level at N. -# -DENABLE_HT216_LOG=N sets logging level at N. -# -DENABLE_ICD2061_LOG=N sets logging level at N. -# -DENABLE_IM1024_LOG=N sets logging level at N. -# -DENABLE_PGC_LOG=N sets logging level at N. -# -DENABLE_S3_VIRGE_LOG=N sets logging level at N. -# -DENABLE_VID_TABLE_LOG=N sets logging level at N. -# -DENABLE_VIDEO_LOG=N sets logging level at N. -# -DENABLE_VOODOO_LOG=N sets logging level at N. -# win/ logging: -# -DENABLE_WIN_LOG=N sets logging level at N. -# -DENABLE_DISCORD_LOG=N sets logging level at N. -# -DENABLE_DYNLD_LOG=N sets logging level at N. -# -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 := - - -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 win/Makefile.mingw - - -# End of Makefile.local. diff --git a/src/acpi.c b/src/acpi.c index 5672fb135..339ea7dcf 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -39,6 +39,10 @@ #include <86box/machine.h> #include <86box/i2c.h> #include <86box/video.h> +#include <86box/smbus.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/sis_55xx.h> int acpi_rtc_status = 0; atomic_int acpi_pwrbut_pressed = 0; @@ -46,7 +50,9 @@ int acpi_enabled = 0; static double cpu_to_acpi; -static int acpi_power_on = 0; +static int acpi_power_on = 0; +static uint64_t acpi_last_clock = 0ULL; +static int acpi_count = 0; #ifdef ENABLE_ACPI_LOG int acpi_do_log = ENABLE_ACPI_LOG; @@ -82,65 +88,152 @@ acpi_timer_get(acpi_t *dev) return clock & 0xffffff; } +static uint8_t +acpi_gp_timer_get(acpi_t *dev) +{ + uint64_t clock = acpi_clock_get(); + clock -= acpi_last_clock; + if (clock >= acpi_count) + clock = 0x00; + else + clock &= 0xff; + return clock; +} + static double acpi_get_overflow_period(acpi_t *dev) { uint64_t timer = acpi_clock_get(); uint64_t overflow_time; - if (dev->regs.timer32) { + if (dev->regs.timer32) overflow_time = (timer + 0x80000000LL) & ~0x7fffffffLL; - } else { + 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_update(acpi_t *dev, bool enable) +{ + if (enable) + timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); + else + timer_stop(&dev->timer); +} + static void acpi_timer_overflow(void *priv) { acpi_t *dev = (acpi_t *) priv; dev->regs.pmsts |= TMROF_STS; acpi_update_irq(dev); + acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); } static void -acpi_timer_update(acpi_t *dev, bool enable) +acpi_gp_timer_update(acpi_t *dev, bool enable, int count) { if (enable) { - timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); - } else { + acpi_last_clock = acpi_clock_get(); + acpi_count = count; + timer_on_auto(&dev->gp_timer, (1000000.0 / (double) ACPI_TIMER_FREQ) * ((double) count)); + } else timer_stop(&dev->timer); +} + +void +acpi_sis5595_smi_raise(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->regs.leg_en & 0x20) { + dev->regs.leg_sts |= 0x20; + smi_raise(); } } +static void +acpi_gp_timer(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->vendor == VEN_SIS_5595_1997) { + dev->regs.gpe_sts |= 0x20000000; + dev->regs.leg_sts |= 0x20; + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count); + acpi_sis5595_smi_raise(dev); + } else if (dev->vendor == VEN_SIS_5595) { + dev->regs.gpe_sts |= 0x00000400; + dev->regs.leg_sts |= 0x20; + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count); + acpi_sis5595_smi_raise(dev); + } else { + dev->regs.reg_14 |= 0x2000; + acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count); + smi_raise(); + } +} + +static void +acpi_per_timer(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->vendor >= VEN_SIS_5595_1997) { + dev->regs.leg_sts |= 0x04; + acpi_sis5595_smi_raise(dev); + } else { + dev->regs.reg_25 |= 0x04; + smi_raise(); + } + timer_on_auto(&dev->per_timer, 16000000.0); +} + 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); + sis_55xx_common_t *sis = (sis_55xx_common_t *) dev->priv; - 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, &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); + switch (dev->vendor) { + case VEN_SMC: + sci_level |= (dev->regs.pmsts & BM_STS); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + if ((sis != NULL) && (sis->pmu_regs != NULL)) { + sci_level |= (sis->pmu_regs[0x80] | sis->pmu_regs[0x81] | + sis->pmu_regs[0x82] | sis->pmu_regs[0x83]); + } + break; } - acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); + if ((dev->regs.pmcntrl & 0x01) && sci_level) switch (dev->irq_mode) { + default: + picintlevel(1 << dev->irq_line, &dev->irq_state); + break; + case 1: + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); + break; + case 2: + pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state); + break; + case -1: + break; + } else switch (dev->irq_mode) { + default: + picintclevel(1 << dev->irq_line, &dev->irq_state); + break; + case 1: + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); + break; + case 2: + pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state); + break; + case -1: + break; + } } void @@ -652,6 +745,230 @@ acpi_aux_reg_read_smc(UNUSED(int size), uint16_t addr, void *priv) return ret; } +static uint32_t +acpi_reg_read_sis_5582(int size, uint16_t addr, void *priv) +{ + 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: + case 0x0e: + case 0x0f: + ret = (dev->regs.reg_0c >> shift32) & 0xff; + break; + case 0x10: + ret = dev->regs.enter_c2_ps; + break; + case 0x11: + ret = dev->regs.enter_c3_ps; + break; + case 0x12: + ret = dev->regs.reg_12; + break; + case 0x13: + ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff; +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + break; + case 0x14: + case 0x15: + ret = (dev->regs.reg_14 >> shift16) & 0xff; + break; + case 0x16: + case 0x17: + ret = (dev->regs.reg_16 >> shift16) & 0xff; + break; + case 0x18: + case 0x19: + ret = (dev->regs.reg_18 >> shift16) & 0xff; + break; + case 0x1a: + case 0x1b: + ret = (dev->regs.reg_18 >> shift16) & 0xff; + break; + case 0x1c: + case 0x1d: + ret = (dev->regs.reg_1c >> shift16) & 0xff; + break; + case 0x20: + ret = dev->regs.smi_cmd; + break; + case 0x24: + ret = dev->regs.reg_24; + break; + case 0x25: + ret = dev->regs.reg_25; + break; + case 0x26: + ret = dev->regs.reg_26; + break; + case 0x28: + ret = dev->regs.smi_en_val; + break; + case 0x29: + ret = dev->regs.smi_dis_val; + break; + case 0x2a: + ret = dev->regs.mail_box; + break; + case 0x2b: + ret = dev->regs.reg_2b; + 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); +#endif + return ret; +} + +static uint32_t +acpi_reg_read_sis_5595(int size, uint16_t addr, void *priv) +{ + 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: + case 0x0e: + case 0x0f: + ret = (dev->regs.reg_0c >> shift32) & 0xff; + break; + case 0x10: + ret = dev->regs.enter_c2_ps; + break; + case 0x11: + ret = dev->regs.enter_c3_ps; + break; + case 0x12: + ret = dev->regs.reg_12; + break; + case 0x13: + ret = dev->regs.reg_13; + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + ret = (dev->regs.gpe_sts >> shift32) & 0xff; + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + ret = (dev->regs.gpe_en >> shift32) & 0xff; + break; + case 0x1c: + case 0x1d: + case 0x1e: + ret = (dev->regs.gpe_pin >> shift32) & 0xff; + break; + case 0x1f: + ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff; +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + break; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + ret = (dev->regs.gpe_io >> shift32) & 0xff; + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + ret = (dev->regs.gpe_pol >> shift32) & 0xff; + break; + case 0x28: + case 0x29: + ret = (dev->regs.gpe_mul >> shift16) & 0xff; + break; + case 0x2a: + case 0x2b: + ret = (dev->regs.gpe_ctl >> shift16) & 0xff; + break; + case 0x2c: + case 0x2d: + ret = (dev->regs.gpe_smi >> shift16) & 0xff; + break; + case 0x2e: + case 0x2f: + ret = (dev->regs.gpe_rl >> shift16) & 0xff; + break; + case 0x30: + ret = dev->regs.leg_sts; + break; + case 0x31: + ret = dev->regs.leg_en; + break; + case 0x32: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_cmd; + else + ret = 0x00; + break; + case 0x33: + ret = dev->regs.tst_ctl; + break; + case 0x34: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_en_val; + else + ret = dev->regs.reg_34; + break; + case 0x35: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_dis_val; + else + ret = dev->regs.smi_cmd; + break; + case 0x36: + ret = dev->regs.mail_box; + break; + case 0x38: + if (dev->vendor == VEN_SIS_5595) + ret = smbus_sis5595_read_index(dev->smbus); + break; + case 0x39: + if (dev->vendor == VEN_SIS_5595) + ret = smbus_sis5595_read_data(dev->smbus); + 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); +#endif + return ret; +} + static void acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) { @@ -723,7 +1040,8 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p /* 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); + plat_pause(2); /* 2 means do not wait for pause as + we're already in the CPU thread. */ timer_set_delay_u64(&dev->resume_timer, 50 * TIMER_USEC); } } @@ -1192,22 +1510,408 @@ acpi_aux_reg_write_smc(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) } } +void +acpi_sis5582_pmu_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + dev->regs.reg_25 |= 0x02; + if (dev->regs.reg_26 & 0x02) + smi_raise(); +} + +static void +acpi_reg_write_sis_5582(int size, uint16_t addr, uint8_t val, void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; + 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); +#endif + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->regs.reg_0c &= ~((val << shift32) & 0x007e); + break; + case 0x10: + dev->regs.enter_c2_ps = val; + break; + case 0x11: + dev->regs.enter_c3_ps = val; + break; + case 0x12: + dev->regs.reg_12 = val & 0x01; + break; + case 0x13: + dev->regs.reg_13 = val; + acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.reg_16 & 0x2000), val); + break; + case 0x14: + case 0x15: + dev->regs.reg_14 &= ~((val << shift32) & 0xff9f); + break; + case 0x16: + case 0x17: + dev->regs.reg_16 = ((dev->regs.reg_16 & ~(0xff << shift16)) | (val << shift16)) & 0xff1f; + break; + case 0x18: + case 0x19: + dev->regs.reg_18 = ((dev->regs.reg_18 & ~(0xff << shift16)) | (val << shift16)) & 0x07ff; + break; + case 0x1a: + case 0x1b: + dev->regs.reg_1a = ((dev->regs.reg_1a & ~(0xff << shift16)) | (val << shift16)) & 0x0387; + break; + case 0x1c: + case 0x1d: + dev->regs.reg_1c = ((dev->regs.reg_1c & ~(0xff << shift16)) | (val << shift16)) & 0x3f7f; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.reg_1c & 0x0400) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x20: + /* SMI Command Port */ + dev->regs.smi_cmd = val; + if (val == dev->regs.smi_en_val) { + dev->regs.reg_25 |= 0x08; + if (dev->regs.reg_26 & 0x08) + smi_raise(); + } else if (val == dev->regs.smi_dis_val) { + dev->regs.reg_25 |= 0x10; + if (dev->regs.reg_26 & 0x10) + smi_raise(); + } + break; + case 0x24: + dev->regs.reg_24 = val & 0x43; + break; + case 0x25: + dev->regs.reg_25 &= ~(val & 0x1f); + break; + case 0x26: + old = dev->regs.reg_26; + dev->regs.reg_26 = val & 0x3f; + if (!(old & 0x04) && (val & 0x04)) + timer_on_auto(&dev->per_timer, 16000000.0); + else if ((old & 0x04) && !(val & 0x04)) + timer_stop(&dev->per_timer); + break; + case 0x28: + dev->regs.smi_en_val = val; + break; + case 0x29: + dev->regs.smi_dis_val = val; + break; + case 0x2a: + dev->regs.mail_box = val; + break; + case 0x2b: + dev->regs.reg_2b = val & 0x01; + 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.reg_1c &= ~0x0400; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.reg_25 |= 0x01; + if (dev->regs.reg_26 & 0x01) + acpi_raise_smi(dev, 1); + } + break; + } +} + +void +acpi_sis5595_pmu_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->vendor == VEN_SIS_5595_1997) + acpi_sis5595_smi_raise(dev); + else if (dev->regs.gpe_en & 0x00001000) { + dev->regs.gpe_sts |= 0x00001000; + acpi_sis5595_smi_raise(dev); + } +} + +void +acpi_sis5595_smbus_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->regs.gpe_en & 0x00000800) { + dev->regs.gpe_sts |= 0x00000800; + acpi_sis5595_smi_raise(dev); + } +} + +void +acpi_sis5595_software_smi(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->regs.leg_en & 0x01) { + dev->regs.leg_sts |= 0x01; + acpi_sis5595_smi_raise(dev); + } +} + +static void +acpi_reg_write_sis_5595(int size, uint16_t addr, uint8_t val, void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; + uint8_t old; + uint8_t do_smi = 0; + + 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.reg_0c &= ~((val << shift32) & 0x001e); + break; + case 0x10: + dev->regs.enter_c2_ps = val; + break; + case 0x11: + dev->regs.enter_c3_ps = val; + break; + case 0x12: + dev->regs.reg_12 = val & 0x01; + break; + case 0x13: + dev->regs.reg_13 = val; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.reg_13 & 0x02) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.gpe_sts &= ~((val << shift32) & 0xff03ffbf); + else + dev->regs.gpe_sts &= ~((val << shift32) & 0xff83ffff); + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) | (val << shift32)); + else + dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) | + (val << shift32)) & 0xff83ffff; + break; + case 0x1c: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0xff << shift32)) | ((val & 0xff) << shift32)); + if (!strcmp(machine_get_internal_name(), "m747") && (val & 0x10) && + !(dev->regs.gpe_io & 0x00000010)) + resetx86(); + break; + case 0x1d: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x1e: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x1f: + dev->regs.gp_tmr = val; + acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.gpe_en & 0x00000400), val); + break; + case 0x20: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x9f << shift32)) | ((val & 0x9f) << shift32)); + break; + case 0x21: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x22: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x24: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0xbf << shift32)) | ((val & 0xbf) << shift32)); + break; + case 0x25: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x26: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x27: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x10 << shift32)) | ((val & 0x10) << shift32)); + break; + case 0x28: + dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0xf9 << shift16)) | ((val & 0xf9) << shift16)); + break; + case 0x29: + dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0x13 << shift16)) | ((val & 0x13) << shift16)); + break; + case 0x2a: + case 0x2b: + dev->regs.gpe_ctl = ((dev->regs.gpe_ctl & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x2c: + case 0x2d: + dev->regs.gpe_smi = ((dev->regs.gpe_smi & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x2e: + case 0x2f: + dev->regs.gpe_rl = ((dev->regs.gpe_rl & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x30: + dev->regs.leg_sts &= ~val; + break; + case 0x31: + old = dev->regs.leg_en; + dev->regs.leg_en = val; + if (!(old & 0x04) && (val & 0x04)) + timer_on_auto(&dev->per_timer, 16000000.0); + else if ((old & 0x04) && !(val & 0x04)) + timer_stop(&dev->per_timer); + break; + case 0x32: + if (dev->vendor == VEN_SIS_5595_1997) { + /* SMI Command Port */ + dev->regs.smi_cmd = val; + if (val == dev->regs.smi_en_val) { + dev->regs.leg_sts |= 0x08; + if (dev->regs.leg_en & 0x08) + acpi_sis5595_smi_raise(dev); + } else if (val == dev->regs.smi_dis_val) { + dev->regs.leg_sts |= 0x10; + if (dev->regs.leg_en & 0x10) + acpi_sis5595_smi_raise(dev); + } + } + break; + case 0x33: + dev->regs.tst_ctl = val & 0x01; + break; + case 0x34: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.smi_en_val = val; + else + dev->regs.reg_34 = val; + break; + case 0x35: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.smi_dis_val = val; + else { + /* SMI Command Port */ + dev->regs.smi_cmd = val; + dev->regs.leg_sts |= 0x10; + if (dev->regs.leg_en & 0x10) + acpi_sis5595_smi_raise(dev); + } + break; + case 0x36: + dev->regs.mail_box = val; + break; + case 0x38: + if (dev->vendor == VEN_SIS_5595) { + dev->regs.index = val; + smbus_sis5595_write_index(dev->smbus, val); + } + break; + case 0x39: + if (dev->vendor == VEN_SIS_5595) { + dev->regs.reg_ff = val & 0x3f; + smbus_sis5595_write_data(dev->smbus, val); + if (val & 0x20) { /* Set GPIO5_STS of GPE_STS */ + dev->regs.gpe_sts |= 0x00000008; + do_smi |= (dev->regs.gpe_en & 0x00000004); + } else if (val & 0x10) { /* Set GPIO10_STS of GPE_STS */ + dev->regs.gpe_sts |= 0x00000004; + do_smi |= (dev->regs.gpe_en & 0x00000008); + } else if (val & 0x08) { /* Set RI_STS in GPE_STS */ + dev->regs.gpe_sts |= 0x00000002; + do_smi |= (dev->regs.gpe_en & 0x00000002); + } else if (val & 0x04) /* Set WAK_STS of PM1_STS */ + dev->regs.pmsts |= 0x8000; + else if (val & 0x02) { /* Set RTC_STS of PM1_STS */ + dev->regs.pmsts |= 0x0400; + do_smi |= (dev->regs.pmen & 0x0400); + } else if (val & 0x01) { /* Set PWRBTN_STS of PM1_STS */ + dev->regs.pmsts |= 0x0100; + do_smi |= (dev->regs.pmen & 0x0100); + } + + if (do_smi) + acpi_sis5595_smi_raise(dev); + } + 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.reg_13 &= ~0x02; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.leg_sts |= 0x01; + if (dev->regs.leg_en & 0x01) + acpi_sis5595_smi_raise(dev); + } + break; + } +} + static uint32_t acpi_reg_read_common(int size, uint16_t addr, void *priv) { const acpi_t *dev = (acpi_t *) priv; uint8_t ret = 0xff; - if (dev->vendor == VEN_ALI) - ret = acpi_reg_read_ali(size, addr, priv); - else if (dev->vendor == VEN_VIA) - ret = acpi_reg_read_via(size, addr, priv); - else if (dev->vendor == VEN_VIA_596B) - ret = acpi_reg_read_via_596b(size, addr, priv); - else if (dev->vendor == VEN_INTEL) - ret = acpi_reg_read_intel(size, addr, priv); - else if (dev->vendor == VEN_SMC) - ret = acpi_reg_read_smc(size, addr, priv); + switch (dev->vendor) { + case VEN_ALI: + ret = acpi_reg_read_ali(size, addr, priv); + break; + case VEN_VIA: + ret = acpi_reg_read_via(size, addr, priv); + break; + case VEN_VIA_596B: + ret = acpi_reg_read_via_596b(size, addr, priv); + break; + case VEN_INTEL: + ret = acpi_reg_read_intel(size, addr, priv); + break; + case VEN_SMC: + ret = acpi_reg_read_smc(size, addr, priv); + break; + case VEN_SIS_5582: + ret = acpi_reg_read_sis_5582(size, addr, priv); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + ret = acpi_reg_read_sis_5595(size, addr, priv); + break; + } return ret; } @@ -1217,16 +1921,30 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv) { const acpi_t *dev = (acpi_t *) priv; - if (dev->vendor == VEN_ALI) - acpi_reg_write_ali(size, addr, val, priv); - else if (dev->vendor == VEN_VIA) - acpi_reg_write_via(size, addr, val, priv); - else if (dev->vendor == VEN_VIA_596B) - acpi_reg_write_via_596b(size, addr, val, priv); - else if (dev->vendor == VEN_INTEL) - acpi_reg_write_intel(size, addr, val, priv); - else if (dev->vendor == VEN_SMC) - acpi_reg_write_smc(size, addr, val, priv); + switch (dev->vendor) { + case VEN_ALI: + acpi_reg_write_ali(size, addr, val, priv); + break; + case VEN_VIA: + acpi_reg_write_via(size, addr, val, priv); + break; + case VEN_VIA_596B: + acpi_reg_write_via_596b(size, addr, val, priv); + break; + case VEN_INTEL: + acpi_reg_write_intel(size, addr, val, priv); + break; + case VEN_SMC: + acpi_reg_write_smc(size, addr, val, priv); + break; + case VEN_SIS_5582: + acpi_reg_write_sis_5582(size, addr, val, priv); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + acpi_reg_write_sis_5595(size, addr, val, priv); + break; + } } static uint32_t @@ -1395,6 +2113,9 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) default: case VEN_ALI: case VEN_INTEL: + case VEN_SIS_5582: + case VEN_SIS_5595_1997: + case VEN_SIS_5595: size = 0x040; break; case VEN_SMC: @@ -1668,10 +2389,28 @@ acpi_reset(void *priv) acpi_power_on = 0; } + /* The Gateway Tomahawk requires the LID polarity bit to be set. */ + if (!strcmp(machine_get_internal_name(), "tomahawk")) + dev->regs.glbctl |= 0x02000000; + acpi_rtc_status = 0; acpi_update_irq(dev); dev->irq_state = 0; + + timer_disable(&dev->gp_timer); + + acpi_last_clock = 0ULL; + acpi_count = 0; + + timer_disable(&dev->per_timer); + + if ((dev->vendor == VEN_SIS_5595_1997) || (dev->vendor == VEN_SIS_5595)) { + dev->regs.reg_13 = 0x20; + dev->regs.gp_tmr = 0xff; + dev->regs.gpe_io = 0x00030b9f; + dev->regs.gpe_mul = 0x1001; + } } static void @@ -1684,6 +2423,33 @@ acpi_speed_changed(void *priv) if (timer_enabled) timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); + + if ((dev->vendor & 0xffff) == 0x1039) { + if (timer_is_on(&dev->gp_timer)) { + timer_stop(&dev->gp_timer); + + if (dev->vendor == VEN_SIS_5595_1997) + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count); + else if (dev->vendor == VEN_SIS_5595) + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count); + else + acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count); + } + + if (timer_is_on(&dev->per_timer)) { + timer_stop(&dev->per_timer); + + timer_on_auto(&dev->per_timer, 16000000.0); + } + } +} + +void * +acpi_get_smbus(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + return dev->smbus; } static void @@ -1762,6 +2528,28 @@ acpi_init(const device_t *info) dev->suspend_types[4] = SUS_SUSPEND; break; + case VEN_SIS_5582: + dev->suspend_types[0] = SUS_SUSPEND; /* S1 */ + dev->suspend_types[4] = SUS_POWER_OFF; /* S5 */ + + timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0); + timer_add(&dev->per_timer, acpi_per_timer, dev, 0); + break; + + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + dev->suspend_types[1] = SUS_SUSPEND; + dev->suspend_types[2] = SUS_SUSPEND; + dev->suspend_types[3] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; + dev->suspend_types[4] = SUS_POWER_OFF; + dev->suspend_types[5] = SUS_POWER_OFF; + + timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0); + timer_add(&dev->per_timer, acpi_per_timer, dev, 0); + + dev->smbus = device_add(&sis5595_smbus_device); + break; + default: break; } @@ -1849,3 +2637,45 @@ const device_t acpi_smc_device = { .force_redraw = NULL, .config = NULL }; + +const device_t acpi_sis_5582_device = { + .name = "SiS 5582 ACPI", + .internal_name = "acpi_sis_5582", + .flags = DEVICE_PCI, + .local = VEN_SIS_5582, + .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_5595_1997_device = { + .name = "SiS 5595 (1997) ACPI", + .internal_name = "acpi_sis_5595_1997", + .flags = DEVICE_PCI, + .local = VEN_SIS_5595_1997, + .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_5595_device = { + .name = "SiS 5595 ACPI", + .internal_name = "acpi_sis_5595", + .flags = DEVICE_PCI, + .local = VEN_SIS_5595, + .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/cdrom/cdrom.c b/src/cdrom/cdrom.c index 40686f14a..e4e76ea66 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -442,7 +442,7 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) { int ret = 1; - if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) { + if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) { 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); @@ -557,6 +557,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) len += pos; } + dev->audio_muted_soft = 0; /* 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)) { @@ -578,6 +579,7 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) int m = 0; int s = 0; int f = 0; + uint32_t pos2 = 0; if (dev->cd_status == CD_STATUS_DATA_ONLY) return 0; @@ -614,8 +616,21 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) break; } - /* 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). */ + pos2 = pos - 1; + if (pos2 == 0xffffffff) + pos2 = pos + 1; + + /* 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, pos2) & CD_TRACK_AUDIO)) { + cdrom_log("CD-ROM %i: Track Search: LBA %08X not on an audio track\n", dev->id, pos); + dev->audio_muted_soft = 1; + if (dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO) + dev->audio_muted_soft = 0; + } else + dev->audio_muted_soft = 0; + + cdrom_log("Track Search Toshiba: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos); dev->cd_buflen = 0; dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; return 1; @@ -641,6 +656,15 @@ cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit) dev->seek_pos = pos; + dev->audio_muted_soft = 0; + /* 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_buflen = 0; dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; return 1; @@ -662,6 +686,7 @@ cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos) pos = MSFtoLBA(m, s, f) - 150; dev->cd_end = pos; + dev->audio_muted_soft = 0; dev->cd_buflen = 0; dev->cd_status = CD_STATUS_PLAYING; return 1; @@ -703,10 +728,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type) 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). */ + cdrom_log("Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos); dev->cd_buflen = 0; dev->cd_status = CD_STATUS_PLAYING; return 1; @@ -750,6 +772,7 @@ cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type) break; } + dev->audio_muted_soft = 0; /* 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)) { @@ -987,6 +1010,11 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) else ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; + /*If a valid audio track is detected with audio on, unmute it.*/ + if (dev->ops->track_type(dev, dev->seek_pos) & CD_TRACK_AUDIO) + dev->audio_muted_soft = 0; + + cdrom_log("SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", dev->seek_pos, dev->cd_end, dev->audio_muted_soft); b[0] = subc.attr; b[1] = bin2bcd(subc.track); b[2] = bin2bcd(subc.index); @@ -1496,8 +1524,9 @@ static void read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len) { uint8_t *bb = rbuf; + const int offset = (!!(mode2 & 0x03)) ? 24 : 16; - dev->ops->read_sector(dev, CD_READ_DATA, rbuf + 16, lba); + dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba); /* Sync bytes */ bb[0] = 0; @@ -1932,8 +1961,18 @@ cdrom_hard_reset(void) dev->cd_status = CD_STATUS_EMPTY; - if (dev->host_drive == 200) + if (dev->host_drive == 200) { +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && + (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); + } } } @@ -2022,6 +2061,15 @@ cdrom_reload(uint8_t id) if (dev->prev_host_drive == 200) { /* Reload a previous image. */ strcpy(dev->image_path, dev->prev_image_path); + +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); cdrom_insert(id); diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 151ddfe9f..482769799 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -70,12 +70,12 @@ cdrom_image_backend_log(const char *fmt, ...) static int bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) { - track_file_t *tf = (track_file_t *) priv; + track_file_t *tf; cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", tf->fp, seek, count); - if (tf->fp == NULL) + if ((tf = (track_file_t *) priv)->fp == NULL) return 0; if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { @@ -98,16 +98,15 @@ bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) static uint64_t bin_get_length(void *priv) { - off64_t len; - track_file_t *tf = (track_file_t *) priv; + track_file_t *tf; cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->fp); - if (tf->fp == NULL) + if ((tf = (track_file_t *) priv)->fp == NULL) return 0; fseeko64(tf->fp, 0, SEEK_END); - len = ftello64(tf->fp); + const off64_t len = ftello64(tf->fp); cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->fp, len); return len; @@ -248,26 +247,20 @@ cdi_set_device(cd_img_t *cdi, const char *path) return 0; } -/* TODO: This never returns anything other than 1, should it even be an int? */ -int +void cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) { *st_track = 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 +void 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; *lead_out = cdi->tracks[*end].start; - - return 1; } int @@ -286,12 +279,11 @@ int cdi_get_audio_track_info(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) { const track_t *trk = &cdi->tracks[track - 1]; - int pos = trk->start + 150; if ((track < 1) || (track > cdi->tracks_num)) return 0; - pos = trk->start + 150; + const int pos = trk->start + 150; FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); @@ -320,9 +312,6 @@ cdi_get_audio_track_info_lba(cd_img_t *cdi, UNUSED(int end), int track, int *tra int cdi_get_track(cd_img_t *cdi, uint32_t sector) { - 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; @@ -330,8 +319,8 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector) /* This has a problem - the code skips the last track, which is lead out - is that correct? */ for (int i = 0; i < (cdi->tracks_num - 1); i++) { - cur = &cdi->tracks[i]; - next = &cdi->tracks[i + 1]; + const track_t *cur = &cdi->tracks[i]; + const track_t *next = &cdi->tracks[i + 1]; /* Take into account cue sheets that do not start on sector 0. */ if ((i == 0) && (sector < cur->start)) @@ -348,16 +337,15 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector) 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); - const track_t *trk; + const int cur_track = cdi_get_track(cdi, sector); if (cur_track < 1) return 0; - *track = (uint8_t) cur_track; - trk = &cdi->tracks[*track - 1]; - *attr = trk->attr; - *index = 1; + *track = (uint8_t) cur_track; + const track_t *trk = &cdi->tracks[*track - 1]; + *attr = trk->attr; + *index = 1; FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); @@ -370,16 +358,11 @@ cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, 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; - uint64_t seek; - track_t *trk; - int track_is_raw; - int ret; + const int track = cdi_get_track(cdi, sector) - 1; + const uint64_t sect = (uint64_t) sector; int raw_size; int cooked_size; - uint64_t offset = 0ULL; + uint64_t offset; int m = 0; int s = 0; int f = 0; @@ -387,10 +370,10 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) if (track < 0) return 0; - trk = &cdi->tracks[track]; - track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); + const track_t *trk = &cdi->tracks[track]; + const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - seek = trk->skip + ((sect - trk->start) * trk->sector_size); + const uint64_t seek = trk->skip + ((sect - trk->start) * trk->sector_size); if (track_is_raw) raw_size = trk->sector_size; @@ -405,7 +388,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) } else cooked_size = COOKED_SECTOR_SIZE; - length = (raw ? raw_size : cooked_size); + const size_t length = (raw ? raw_size : cooked_size); if (trk->mode2 && (trk->form >= 1)) offset = 24ULL; @@ -414,7 +397,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) if (raw && !track_is_raw) { memset(buffer, 0x00, 2448); - ret = trk->file->read(trk->file, buffer + offset, seek, length); + const int ret = trk->file->read(trk->file, buffer + offset, seek, length); if (!ret) return 0; /* Construct the rest of the raw sector. */ @@ -422,32 +405,28 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) 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[0] = CDROM_BCD(m & 0xff); + buffer[1] = CDROM_BCD(s & 0xff); + buffer[2] = CDROM_BCD(f & 0xff); /* Data, should reflect the actual sector type. */ - buffer[15] = trk->mode2 ? 2 : 1; + buffer[3] = trk->mode2 ? 2 : 1; return 1; } else if (!raw && track_is_raw) return trk->file->read(trk->file, buffer, seek + offset, length); - else { + 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; int success = 1; - uint8_t *buf; - uint32_t buf_len; /* 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)); + const int sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; + const uint32_t buf_len = num * sector_size; + uint8_t *buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); for (uint32_t i = 0; i < num; i++) { success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); @@ -455,7 +434,9 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3 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])) + 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; } @@ -470,16 +451,13 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3 int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - track_t *trk; - uint64_t s = (uint64_t) sector; - uint64_t seek; + const int track = cdi_get_track(cdi, sector) - 1; if (track < 0) return 0; - trk = &cdi->tracks[track]; - seek = trk->skip + ((s - trk->start) * trk->sector_size); + const track_t *trk = &cdi->tracks[track]; + const uint64_t seek = trk->skip + (((uint64_t) sector - trk->start) * trk->sector_size); if (trk->sector_size != 2448) return 0; @@ -489,26 +467,24 @@ cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - const track_t *trk; + const int track = cdi_get_track(cdi, sector) - 1; if (track < 0) return 0; - trk = &cdi->tracks[track]; + const track_t *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; - const track_t *trk; + const int track = cdi_get_track(cdi, sector) - 1; if (track < 0) return 0; - trk = &cdi->tracks[track]; + const track_t *trk = &cdi->tracks[track]; return !!(trk->mode2); } @@ -516,13 +492,12 @@ cdi_is_mode2(cd_img_t *cdi, uint32_t sector) int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) { - int track = cdi_get_track(cdi, sector) - 1; - const track_t *trk; + const int track = cdi_get_track(cdi, sector) - 1; if (track < 0) return 0; - trk = &cdi->tracks[track]; + const track_t *trk = &cdi->tracks[track]; return trk->form; } @@ -533,10 +508,12 @@ 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. */ - if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) - seek += 16; - if (mode2 && (form >= 1)) - seek += 24; + if (sector_size == RAW_SECTOR_SIZE) { + if (!mode2 || (form == 0)) + seek += 16; + else + seek += 24; + } file->read(file, pvd, seek, COOKED_SECTOR_SIZE); @@ -591,7 +568,7 @@ cdi_load_iso(cd_img_t *cdi, const char *filename) /* Try to detect ISO type. */ 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; else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { @@ -601,9 +578,17 @@ cdi_load_iso(cd_img_t *cdi, const char *filename) trk.sector_size = 2324; trk.mode2 = 1; trk.form = 2; + } else if (cdi_can_read_pvd(trk.file, 2328, 1, 2)) { + trk.sector_size = 2328; + 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; + } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 1)) { + trk.sector_size = RAW_SECTOR_SIZE; + trk.mode2 = 1; + trk.form = 1; } else { /* We use 2048 mode 1 as the default. */ trk.sector_size = COOKED_SECTOR_SIZE; @@ -754,17 +739,12 @@ 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; - 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; - } else - skip = 0ULL; + if (prestart > cur->start) + return 0; + const uint64_t skip = cur->start - prestart; if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) prev = &cdi->tracks[cdi->tracks_num - 1]; @@ -793,7 +773,7 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u *total_pregap += cur_pregap; cur->start += *total_pregap; } else { - temp = prev->file->get_length(prev->file) - (prev->skip); + const uint64_t 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++; @@ -823,8 +803,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) { 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; @@ -836,7 +814,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) int can_add_track = 0; FILE *fp; char buf[MAX_LINE_LENGTH]; - char ansi[MAX_FILENAME_LENGTH]; char *line; char *command; char *type; @@ -877,7 +854,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) } } - success = cdi_cue_get_keyword(&command, &line); + (void) cdi_cue_get_keyword(&command, &line); if (!strcmp(command, "TRACK")) { if (can_add_track) @@ -980,6 +957,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) break; } } else if (!strcmp(command, "FILE")) { + char filename[MAX_FILENAME_LENGTH]; + char ansi[MAX_FILENAME_LENGTH]; + if (can_add_track) success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap); else @@ -1002,7 +982,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) error = 1; 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); } diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 0f3c78c84..0406ea0b8 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -18,9 +18,11 @@ add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali14 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) + sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5581.c sis_5591.c sis_5600.c + sis_5511_h2p.c sis_5571_h2p.c sis_5581_h2p.c sis_5591_h2p.c sis_5600_h2p.c + sis_5513_p2i.c sis_5513_ide.c sis_5572_usb.c sis_5595_pmu.c sis_55xx.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 umc_8890.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c) if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 822ab7baf..3550f1da6 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -41,7 +41,8 @@ #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 DEFINE_SHADOW_PROCEDURE (((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | \ + ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) #define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) #ifdef ENABLE_ALI1489_LOG @@ -64,19 +65,14 @@ ali1489_log(const char *fmt, ...) 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]; port_92_t *port_92; smram_t *smram; } ali1489_t; -static void ali1489_ide_handler(ali1489_t *dev); - static void ali1489_shadow_recalc(ali1489_t *dev) { @@ -85,7 +81,8 @@ ali1489_shadow_recalc(ali1489_t *dev) 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)); + 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)); @@ -96,7 +93,8 @@ ali1489_shadow_recalc(ali1489_t *dev) 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)); + 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); @@ -142,25 +140,9 @@ ali1489_smram_recalc(ali1489_t *dev) static void ali1489_defaults(ali1489_t *dev) { - memset(dev->ide_regs, 0x00, 256); memset(dev->pci_conf, 0x00, 256); memset(dev->regs, 0x00, 256); - ide_pri_disable(); - ide_sec_disable(); - - /* IDE registers */ - dev->ide_regs[0x00] = 0x57; - dev->ide_regs[0x01] = 0x02; - dev->ide_regs[0x08] = 0xff; - dev->ide_regs[0x09] = 0x41; - dev->ide_regs[0x0c] = 0x02; - dev->ide_regs[0x0e] = 0x02; - dev->ide_regs[0x10] = 0x02; - dev->ide_regs[0x12] = 0x02; - dev->ide_regs[0x34] = 0xff; - dev->ide_regs[0x35] = 0x01; - /* PCI registers */ dev->pci_conf[0x00] = 0xb9; dev->pci_conf[0x01] = 0x10; @@ -203,8 +185,6 @@ ali1489_defaults(ali1489_t *dev) 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); - - ali1489_ide_handler(dev); } static void @@ -385,7 +365,8 @@ ali1489_write(uint16_t addr, uint8_t val, void *priv) break; case 0x44: /* PCI INTx Sensitivity Register */ - /* TODO: When doing the IRQ and PCI IRQ rewrite, bits 0 to 3 toggle edge/level output. */ + /* TODO: When doing the IRQ and PCI IRQ rewrite, + bits 0 to 3 toggle edge/level output. */ dev->regs[dev->index] = val; break; default: @@ -464,121 +445,6 @@ ali1489_pci_read(UNUSED(int func), int addr, void *priv) 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(); - } -} - -static void -ali1489_ide_write(uint16_t addr, uint8_t val, void *priv) -{ - ali1489_t *dev = (ali1489_t *) priv; - - switch (addr) { - case 0xf4: /* Usually it writes 30h here */ - dev->ide_chip_id = val; - break; - - case 0xf8: - dev->ide_index = val; - 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; - - default: - break; - } - break; - - default: - break; - } -} - -static uint8_t -ali1489_ide_read(uint16_t addr, void *priv) -{ - 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; - - default: - break; - } - - return ret; -} - static void ali1489_reset(void *priv) { @@ -612,19 +478,10 @@ ali1489_init(UNUSED(const device_t *info)) 23h Data Port */ io_sethandler(0x0022, 0x0002, ali1489_read, NULL, NULL, ali1489_write, NULL, NULL, dev); - /* M1489 IDE controller - F4h Chip ID we write always 30h onto it - F8h Index Port - FCh Data Port - */ - io_sethandler(0x0f4, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); - io_sethandler(0x0f8, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); - io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); - /* Dummy M1489 PCI device */ pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev, &dev->pci_slot); - device_add(&ide_pci_2ch_device); + device_add(&ide_ali1489_device); dev->port_92 = device_add(&port_92_pci_device); dev->smram = smram_add(); diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 4d8dea3ce..5598f30fb 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -197,6 +197,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) 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_MIRQ0, !(val & 0x10)); 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]); @@ -417,6 +418,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) 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_MIRQ1, !(val & 0x10)); 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]); @@ -489,12 +491,10 @@ static void ali5229_ide_irq_handler(ali1543_t *dev) { int ctl = 0; - int ch = 0; int bit = 0; if (dev->ide_conf[0x52] & 0x10) { ctl ^= 1; - ch ^= 1; bit ^= 5; } @@ -706,7 +706,7 @@ ali5229_chip_reset(ali1543_t *dev) ali5229_write(0, 0x09, 0xfa, dev); ali5229_write(0, 0x52, 0x00, dev); - ali5229_write(0, 0x50, 0x00, dev); + ali5229_write(0, 0x50, 0x02, dev); sff_set_slot(dev->ide_controller[0], dev->ide_slot); sff_set_slot(dev->ide_controller[1], dev->ide_slot); @@ -719,7 +719,7 @@ static void ali5229_write(int func, int addr, uint8_t val, void *priv) { ali1543_t *dev = (ali1543_t *) priv; - ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val); + ali1543_log("M5229: [W] dev->ide_conf[%02x] = %02x\n", addr, val); if (func > 0) return; @@ -758,6 +758,10 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) ali5229_ide_irq_handler(dev); break; + case 0x0d: /* LT - Latency Timer */ + dev->ide_conf[addr] = val; + break; + /* Primary Base Address */ case 0x10: case 0x11: @@ -778,9 +782,9 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) /* 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) + else if ((addr & 0x07) == 0x00) dev->ide_conf[addr] = (val & 0xf8) | 0x01; - else if ((addr & 0x43) == 0x40) + else if ((addr & 0x07) == 0x04) dev->ide_conf[addr] = (val & 0xfc) | 0x01; else dev->ide_conf[addr] = val; @@ -889,13 +893,15 @@ ali5229_read(int func, int addr, void *priv) if (dev->ide_dev_enable && (func == 0)) { ret = dev->ide_conf[addr]; if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02)) - ret &= 0x0f; + ret = (ret & 0x0f) | 0x80; 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(); + + ali1543_log("M5229: [R] dev->ide_conf[%02x] = %02x\n", addr, ret); } return ret; @@ -984,7 +990,7 @@ static void ali7101_write(int func, int addr, uint8_t val, void *priv) { ali1543_t *dev = (ali1543_t *) priv; - ali1543_log("M7101: dev->pmu_conf[%02x] = %02x\n", addr, val); + ali1543_log("M7101: [W] dev->pmu_conf[%02x] = %02x\n", addr, val); if (func > 0) return; @@ -1408,65 +1414,78 @@ ali7101_read(int func, int addr, void *priv) uint8_t ret = 0xff; if (dev->pmu_dev_enable && (func == 0)) { - if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) - return 0xff; - - /* 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) { + if (!(dev->pmu_conf[0xc9] & 0x01) || (addr < 0x40) || (addr == 0xc9)) { + /* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */ switch (addr) { + default: + ret = dev->pmu_conf[addr]; + break; + case 0x10 ... 0x13: + if (dev->pmu_conf[0x5b] & 0x02) + ret = 0x00; + else + ret = dev->pmu_conf[addr]; + break; + case 0x14 ... 0x17: + if (dev->pmu_conf[0x5b] & 0x04) + ret = 0x00; + else + ret = dev->pmu_conf[addr]; + break; case 0x42: - dev->pmu_conf[addr] &= 0xe0; + ret = (dev->pmu_conf[addr] & 0xf7) | (nvr_smi_status(dev->nvr) ? 0x08 : 0x00); break; case 0x43: - dev->pmu_conf[addr] &= 0xef; - acpi_ali_soft_smi_status_write(dev->acpi, 0); + ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; break; + case 0x7f: + ret = 0x80; + break; + case 0xbc: + ret = inb(0x70); + 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; + 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 0x4e: - dev->pmu_conf[addr] &= 0xfa; - break; - case 0x4f: - dev->pmu_conf[addr] &= 0xfe; - 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 0x74: - dev->pmu_conf[addr] &= 0xcc; - break; + case 0x4e: + dev->pmu_conf[addr] &= 0xfa; + break; + case 0x4f: + dev->pmu_conf[addr] &= 0xfe; + break; - default: - break; + case 0x74: + dev->pmu_conf[addr] &= 0xcc; + break; + + default: + break; + } } } } + ali1543_log("M7101: [R] dev->pmu_conf[%02x] = %02x\n", addr, ret); + return ret; } diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index c7ada4bc6..cc2e465a2 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -471,7 +471,8 @@ ali6117_init(const device_t *info) dev->local = info->local; - device_add(&ide_isa_device); + if (!(dev->local & 0x08)) + device_add(&ide_isa_device); ali6117_setup(dev); diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index ec7050b1e..5c2910227 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -311,8 +311,10 @@ contaq_82c59x_close(void *priv) { contaq_82c59x_t *dev = (contaq_82c59x_t *) priv; - smram_del(dev->smram[1]); - smram_del(dev->smram[0]); + if (dev->green) { + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); + } free(dev); } diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 1e4158b94..2f6afa940 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -493,16 +493,40 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) case 0x52: /* Cache Control Register */ switch (dev->type) { default: + /* + 420TX/ZX: + Bit 7-6: 0, 0 = 64 kB, + 0, 1 = 128 kB, + 1, 0 = 256 kB, + 1, 1 = 512 kB. + Bit 5: 1 = L2 cache present, 0 = L2 cache absent. + Bit 1: 1 = Write back cache, 0 = write through cache. + Bit 0: 1 = L2 cache enable, 0 = L2 cache disable. + */ case INTEL_420TX: case INTEL_420ZX: + case INTEL_430NX: + regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1f); + cpu_cache_ext_enabled = val & 0x01; + cpu_update_waitstates(); + break; case INTEL_430LX: + regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1b); + cpu_cache_ext_enabled = val & 0x01; + cpu_update_waitstates(); + break; case INTEL_430FX: case INTEL_430VX: case INTEL_430TX: - regs[0x52] = (val & 0xfb); + regs[0x52] = (regs[0x52] & 0x04) | (val & 0xfb); + cpu_cache_ext_enabled = ((val & 0x03) == 0x01); + cpu_update_waitstates(); break; - case INTEL_430NX: case INTEL_430HX: + regs[0x52] = val; + cpu_cache_ext_enabled = ((val & 0x03) == 0x01); + cpu_update_waitstates(); + break; case INTEL_440FX: regs[0x52] = val; break; @@ -1522,6 +1546,8 @@ i4x0_read(int func, int addr, void *priv) 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); + else if ((func == 0) && (addr == 0x52) && (dev->type == INTEL_430TX) && !strcmp(machine_get_internal_name(), "tomahawk")) + ret = 0xb2; } return ret; @@ -1628,7 +1654,7 @@ i4x0_init(const device_t *info) 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[0x52] = 0xe0; /* 512 kB writeback cache */ regs[0x57] = 0x31; regs[0x59] = 0x0f; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 90b807a6d..2f6547309 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -8,19 +8,14 @@ * * Implementation of the Intel 450KX Mars Chipset. * + * i450GX is way more popular of an option but needs more stuff. * + * Authors: Miran Grca, + * Tiseno100, * - * Authors: Tiseno100 - * + * Copyright 2021-2024 Miran Grca. * Copyright 2021 Tiseno100. */ - -/* -Note: i450KX PB manages PCI memory access with MC manages DRAM memory access. -Due to 86Box limitations we can't manage them seperately thus it is dev branch till then. - -i450GX is way more popular of an option but needs more stuff. -*/ #include #include #include @@ -97,17 +92,18 @@ i450kx_smram_recalc(i450kx_t *dev, int bus) const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; uint32_t addr; uint32_t size; + int enable = bus ? !(regs[0x57] & 0x08) : (regs[0x57] & 0x08); 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 ((addr != 0x00000000) && enable) { if (bus) - smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1); + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, 0, enable); else - smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0); + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, enable, 0); } flushmmucache(); @@ -118,10 +114,8 @@ i450kx_vid_buf_recalc(i450kx_t *dev, int bus) { 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); + 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); @@ -136,10 +130,10 @@ pb_write(int func, int addr, uint8_t val, void *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) { + i450kx_log("[%04X:%08X] i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, val); - if (func == 0) switch (addr) { case 0x04: dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53); @@ -373,6 +367,7 @@ pb_write(int func, int addr, uint8_t val, void *priv) default: break; } + } } static uint8_t @@ -381,10 +376,12 @@ pb_read(int func, int addr, void *priv) const i450kx_t *dev = (i450kx_t *) priv; uint8_t ret = 0xff; - if (func == 0) + if (func == 0) { ret = dev->pb_pci_conf[addr]; - // pclog("i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); + i450kx_log("[%04X:%08X] i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, ret); + } return ret; } @@ -407,10 +404,10 @@ mc_write(int func, int addr, uint8_t val, void *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) { + i450kx_log("[%04X:%08X] i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, val); - if (func == 0) switch (addr) { case 0x4c: dev->mc_pci_conf[addr] = val & 0xdf; @@ -600,6 +597,7 @@ mc_write(int func, int addr, uint8_t val, void *priv) default: break; } + } } static uint8_t @@ -608,10 +606,12 @@ mc_read(int func, int addr, void *priv) const i450kx_t *dev = (i450kx_t *) priv; uint8_t ret = 0xff; - if (func == 0) + if (func == 0) { ret = dev->mc_pci_conf[addr]; - // pclog("i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); + i450kx_log("[%04X:%08X] i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, ret); + } return ret; } @@ -622,10 +622,6 @@ i450kx_reset(void *priv) 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; dev->pb_pci_conf[0x01] = 0x80; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 2094eefcf..1f95c28b3 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -597,6 +597,12 @@ piix_write(int func, int addr, uint8_t val, void *priv) pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); else pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); + if (dev->type == 3) { + if (val & 0x20) + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + } piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); } break; @@ -1006,11 +1012,11 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; case 0xc0: if (dev->type <= 4) - fregs[0xc0] = (fregs[0xc0] & ~(val & 0xbf)) | (val & 0x20); + fregs[0xc0] = (fregs[0xc0] & 0x40) | (val & 0xbf); break; case 0xc1: if (dev->type <= 4) - fregs[0xc1] &= ~val; + fregs[0xc1] = (fregs[0xc0] & ~(val & 0x8f)) | (val & 0x20); break; case 0xff: if (dev->type == 4) { @@ -1572,7 +1578,16 @@ piix_init(const device_t *info) 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); + /* + TriGem Richmond: + - Bit 5: Manufacturing jumper, must be set; + - Bit 4: CMOS clear jumper, must be clear; + - Bit 0: Password switch, must be clear. + */ + if (!strcmp(machine_get_internal_name(), "richmond")) + acpi_set_gpireg2_default(dev->acpi, 0xee); + else + 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); diff --git a/src/chipset/neat.c b/src/chipset/neat.c index a54fc312e..97c4b8f1a 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -646,7 +646,8 @@ neat_read(uint16_t port, void *priv) break; case 0x23: - ret = dev->regs[dev->indx]; + if ((dev->indx >= 0x60) && (dev->indx <= 0x6f)) + ret = dev->regs[dev->indx]; break; default: @@ -673,13 +674,14 @@ neat_init(UNUSED(const device_t *info)) { neat_t *dev; uint8_t dram_mode = 0; + uint8_t i; /* Create an instance. */ dev = (neat_t *) malloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); /* Initialize some of the registers to specific defaults. */ - for (uint8_t i = REG_RA0; i <= REG_RB11; i++) { + for (i = REG_RA0; i <= REG_RB11; i++) { dev->indx = i; neat_write(0x0023, 0x00, dev); } diff --git a/src/chipset/scat.c b/src/chipset/scat.c index aa0c5511a..02610efa2 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -66,15 +66,17 @@ typedef struct ems_page_t { } ems_page_t; typedef struct scat_t { - int type; + uint8_t max_reg; + uint8_t reg_2xA; - int indx; - uint8_t regs[256]; - uint8_t reg_2xA; + uint8_t regs[256]; uint32_t xms_bound; - int external_is_RAS; + int type; + int indx; + + int external_is_RAS; ems_page_t null_page; ems_page_t page[32]; @@ -1233,7 +1235,8 @@ scat_in(uint16_t port, void *priv) break; default: - ret = dev->regs[dev->indx]; + if (dev->indx <= dev->max_reg) + ret = dev->regs[dev->indx]; break; } break; @@ -1393,6 +1396,8 @@ scat_init(const device_t *info) sx = (dev->type == 32) ? 1 : 0; + dev->max_reg = sx ? 0x64 : 0x4f; + for (uint32_t i = 0; i < sizeof(dev->regs); i++) dev->regs[i] = 0xff; diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index f2ee01ebb..aa841ed9c 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -25,9 +25,10 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - #include <86box/mem.h> #include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -41,7 +42,7 @@ #include <86box/port_92.h> #include <86box/smram.h> #include <86box/spd.h> - +#include <86box/sis_55xx.h> #include <86box/chipset.h> #ifdef ENABLE_SIS_5511_LOG @@ -63,570 +64,53 @@ sis_5511_log(const char *fmt, ...) #endif typedef struct sis_5511_t { - uint8_t index; - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; + uint8_t nb_slot; + uint8_t sb_slot; - uint8_t regs[16]; - uint8_t states[7]; + void *h2p; - uint8_t slic_regs[4096]; + void *p2i; + void *ide; - 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_55xx_common_t *sis; } sis_5511_t; static void -sis_5511_shadow_recalc(sis_5511_t *dev) +sis_5511_write(int func, int addr, uint8_t val, void *priv) { - int state; - uint32_t base; - - 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; - - 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); - } - - 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(); -} - -static void -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; - - default: - break; - } - - flushmmucache(); -} - -static void -sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; + const 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 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; - } + if (func == 0x00) + sis_5511_host_to_pci_write(addr, val, dev->h2p); } static uint8_t -sis_5511_read(UNUSED(int func), int addr, void *priv) +sis_5511_read(int func, int addr, void *priv) { const sis_5511_t *dev = (sis_5511_t *) priv; uint8_t ret = 0xff; if (func == 0x00) - ret = dev->pci_conf[addr]; + ret = sis_5511_host_to_pci_read(addr, dev->h2p); sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); return ret; } -static uint8_t -sis_5511_slic_read(uint32_t addr, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; - uint8_t ret = 0xff; - - addr &= 0x00000fff; - - switch (addr) { - case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ - ret = dev->slic_regs[addr]; - break; - } - - return ret; -} - -void -sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) -{ - sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val); - - switch (addr) { - case 0x04: /* Command */ - dev->pci_conf_sb[0][addr] = val & 0x0f; - break; - - case 0x07: /* Status */ - dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30); - 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) ? PCI_IRQ_DISABLED : (val & 0x0f)); - 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 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 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; + const 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; - } + sis_5511_log("SiS 5513: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); } static uint8_t @@ -635,258 +119,21 @@ sis_5513_read(int func, int addr, void *priv) const sis_5511_t *dev = (sis_5511_t *) priv; uint8_t ret = 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; - } + if (func == 0x00) + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); - 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); - } + sis_5511_log("SiS 5513: [R] dev->pci_conf[%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; - - 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) -{ - const sis_5511_t *dev = (sis_5511_t *) priv; - uint8_t ret = 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 */ - dev->pci_conf[0x00] = 0x39; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x11; - 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[0x09] = dev->pci_conf[0x0a] = 0x00; - dev->pci_conf[0x0b] = 0x06; - dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; - 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; - dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; - dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00; - 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[0x64] = dev->pci_conf[0x65] = 0x00; - dev->pci_conf[0x66] = 0x00; - dev->pci_conf[0x67] = 0xff; - dev->pci_conf[0x68] = dev->pci_conf[0x69] = 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(); - - sis_5511_smram_recalc(dev); - sis_5511_shadow_recalc(dev); - - flushmmucache(); - - 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; - smram_del(dev->smram); free(dev); } @@ -894,55 +141,18 @@ static void * sis_5511_init(UNUSED(const device_t *info)) { 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)); - - memset(dev, 0, sizeof(sis_5511_t)); /* 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); - /* 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); + dev->sis = device_add(&sis_55xx_common_device); - /* Ports 22h-23h: SiS 5513 ISA */ - io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); + dev->h2p = device_add_linked(&sis_5511_h2p_device, dev->sis); - /* MIRQ */ - pci_enable_mirq(0); - pci_enable_mirq(1); - - /* IDEIRQ */ - pci_enable_mirq(2); - - /* 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); + dev->p2i = device_add_linked(&sis_5513_p2i_device, dev->sis); + dev->ide = device_add_linked(&sis_5513_ide_device, dev->sis); return dev; } @@ -954,7 +164,7 @@ const device_t sis_5511_device = { .local = 0, .init = sis_5511_init, .close = sis_5511_close, - .reset = sis_5511_reset, + .reset = NULL, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c new file mode 100644 index 000000000..7916d6ae2 --- /dev/null +++ b/src/chipset/sis_5511_h2p.c @@ -0,0 +1,461 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5511 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5511_HOST_TO_PCI_LOG +int sis_5511_host_to_pci_do_log = ENABLE_SIS_5511_HOST_TO_PCI_LOG; + +static void +sis_5511_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5511_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5511_host_to_pci_log(fmt, ...) +#endif + +typedef struct sis_5511_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + uint8_t slic_regs[4096]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + mem_mapping_t slic_mapping; +} sis_5511_host_to_pci_t; + +static void +sis_5511_shadow_recalc(sis_5511_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + 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_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + 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_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + 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_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5511_smram_recalc(sis_5511_host_to_pci_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; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + sis_5511_host_to_pci_log("SiS 5511 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + 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->pci_conf, 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; + } +} + +uint8_t +sis_5511_host_to_pci_read(int addr, void *priv) +{ + const sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5511_host_to_pci_log("SiS 5511 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + addr &= 0x00000fff; + + switch (addr) { + 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_slic_read(uint32_t addr, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + ret = dev->slic_regs[addr]; + break; + } + + return ret; +} + +static void +sis_5511_host_to_pci_reset(void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x11; + 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[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + 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; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00; + 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[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = 0xff; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 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[0x71] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80; + dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00; + 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(); + + sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); + + flushmmucache(); + + memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t)); + dev->slic_regs[0x18] = 0x0f; + + mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000); +} + +static void +sis_5511_host_to_pci_close(void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5511_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) calloc(1, sizeof(sis_5511_host_to_pci_t)); + + dev->sis = device_get_common_priv(); + + /* 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); + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5511_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5511_h2p_device = { + .name = "SiS 5511 Host to PCI bridge", + .internal_name = "sis_5511_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5511_host_to_pci_init, + .close = sis_5511_host_to_pci_close, + .reset = sis_5511_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5513_ide.c b/src/chipset/sis_5513_ide.c new file mode 100644 index 000000000..5cbfbdea8 --- /dev/null +++ b/src/chipset/sis_5513_ide.c @@ -0,0 +1,505 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5513 IDE controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5513_IDE_LOG +int sis_5513_ide_do_log = ENABLE_SIS_5513_IDE_LOG; + +static void +sis_5513_ide_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5513_ide_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5513_ide_log(fmt, ...) +#endif + +typedef struct sis_5513_ide_t { + uint8_t rev; + + uint8_t pci_conf[256]; + + sis_55xx_common_t *sis; +} sis_5513_ide_t; + +static void +sis_5513_ide_irq_handler(sis_5513_ide_t *dev) +{ + if (dev->pci_conf[0x09] & 0x01) { + /* Primary IDE is native. */ + sis_5513_ide_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_SIS_551X); + } else { + /* Primary IDE is legacy. */ + sis_5513_ide_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_LEGACY); + } + + if (dev->pci_conf[0x09] & 0x04) { + /* Secondary IDE is native. */ + sis_5513_ide_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_SIS_551X); + } else { + /* Secondary IDE is legacy. */ + sis_5513_ide_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_LEGACY); + } +} + +static void +sis_5513_ide_handler(sis_5513_ide_t *dev) +{ + uint8_t ide_io_on = dev->pci_conf[0x04] & 0x01; + + uint16_t native_base_pri_addr = (dev->pci_conf[0x11] | dev->pci_conf[0x10] << 8) & 0xfffe; + uint16_t native_side_pri_addr = (dev->pci_conf[0x15] | dev->pci_conf[0x14] << 8) & 0xfffe; + uint16_t native_base_sec_addr = (dev->pci_conf[0x19] | dev->pci_conf[0x18] << 8) & 0xfffe; + uint16_t native_side_sec_addr = (dev->pci_conf[0x1c] | dev->pci_conf[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[0x09] & 1)) ? 0x01f0 : native_base_pri_addr; + current_pri_side = (!(dev->pci_conf[0x09] & 1)) ? 0x03f6 : native_side_pri_addr; + + /* Secondary Channel Programming */ + current_sec_base = (!(dev->pci_conf[0x09] & 4)) ? 0x0170 : native_base_sec_addr; + current_sec_side = (!(dev->pci_conf[0x09] & 4)) ? 0x0376 : native_side_sec_addr; + + sis_5513_ide_log("sis_5513_ide_handler(): Disabling primary IDE...\n"); + ide_pri_disable(); + sis_5513_ide_log("sis_5513_ide_handler(): Disabling secondary IDE...\n"); + ide_sec_disable(); + + if (ide_io_on) { + /* Primary Channel Setup */ + if (dev->pci_conf[0x4a] & 0x02) { + sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); + + sis_5513_ide_log("sis_5513_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); + + sis_5513_ide_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->pci_conf[0x4a] & 0x04) { + sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); + + sis_5513_ide_log("sis_5513_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); + + sis_5513_ide_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } + + sff_bus_master_handler(dev->sis->bm[0], ide_io_on, + ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 0); + sff_bus_master_handler(dev->sis->bm[1], ide_io_on, + ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 8); +} + +void +sis_5513_ide_write(int addr, uint8_t val, void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + sis_5513_ide_log("SiS 5513 IDE: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + case 0x04: /* Command low byte */ + dev->pci_conf[addr] = val & 0x05; + sis_5513_ide_handler(dev); + break; + case 0x06: /* Status low byte */ + dev->pci_conf[addr] = val & 0x20; + break; + case 0x07: /* Status high byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x38); + break; + case 0x09: /* Programming Interface Byte */ + switch (dev->rev) { + case 0xd0: + if (dev->sis->ide_bits_1_3_writable) + val |= 0x0a; + fallthrough; + case 0x00: + case 0xd1: + val &= 0xbf; + fallthrough; + case 0xc0: + switch (val & 0x0a) { + case 0x00: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x85) | (val & 0x4a); + break; + case 0x02: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x84) | (val & 0x4b); + break; + case 0x08: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x81) | (val & 0x4e); + break; + case 0x0a: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x80) | (val & 0x4f); + break; + } + break; + } + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + break; + case 0x0d: /* Latency Timer */ + dev->pci_conf[addr] = val; + break; + + /* Primary Base Address */ + case 0x10 ... 0x11: + case 0x14 ... 0x15: + fallthrough; + + /* Secondary Base Address */ + case 0x18 ... 0x19: + case 0x1c ... 0x1d: + fallthrough; + + /* Bus Mastering Base Address */ + case 0x20 ... 0x21: + if (addr == 0x20) + dev->pci_conf[addr] = (val & 0xe0) | 0x01; + else if ((addr & 0x07) == 0x00) + dev->pci_conf[addr] = (val & 0xf8) | 0x01; + else if ((addr & 0x07) == 0x04) + dev->pci_conf[addr] = (val & 0xfc) | 0x01; + else + dev->pci_conf[addr] = val; + sis_5513_ide_handler(dev); + break; + + case 0x2c ... 0x2f: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val; + break; + + case 0x30 ... 0x33: /* Expansion ROM Base Address */ +#ifdef DATASHEET + dev->pci_conf[addr] = val; +#else + if (dev->rev == 0x00) + dev->pci_conf[addr] = val; +#endif + break; + + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0xcf; + else + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ + case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ + case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ + case 0x48: /* IDE Command Recovery Time Control */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ + case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ + case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ + case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0xe7; + else + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x4a: /* IDE General Control Register 0 */ + switch (dev->rev) { + case 0x00: + dev->pci_conf[addr] = val & 0x9e; + break; + case 0xc0: + dev->pci_conf[addr] = val & 0xaf; + break; + case 0xd0: + dev->pci_conf[addr] = val; + break; + } + sis_5513_ide_handler(dev); + break; + + case 0x4b: /* IDE General Control Register 1 */ + if (dev->rev >= 0xc0) + dev->pci_conf[addr] = val; + else + dev->pci_conf[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[addr] = val; + break; + + case 0x50: + case 0x51: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val; + break; + + case 0x52: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0x0f; + break; + + default: + break; + } +} + +uint8_t +sis_5513_ide_read(int addr, void *priv) +{ + const sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + default: + ret = dev->pci_conf[addr]; + break; + case 0x09: + ret = dev->pci_conf[addr]; + if (dev->rev >= 0xc0) { + if (dev->pci_conf[0x09] & 0x40) + ret |= ((dev->pci_conf[0x4a] & 0x06) << 3); + if ((dev->rev == 0xd0) && dev->sis->ide_bits_1_3_writable) + ret |= 0x0a; + } + break; + case 0x3d: + if (dev->rev >= 0xc0) + ret = (dev->pci_conf[0x09] & 0x05) ? PCI_INTA : 0x00; + else + ret = (((dev->pci_conf[0x4b] & 0xc0) == 0xc0) || + (dev->pci_conf[0x09] & 0x05)) ? PCI_INTA : 0x00; + break; + } + + sis_5513_ide_log("SiS 5513 IDE: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5513_ide_reset(void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x13; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = dev->pci_conf[0x07] = 0x00; + dev->pci_conf[0x08] = (dev->rev == 0xd1) ? 0xd0 : dev->rev; + dev->pci_conf[0x09] = 0x8a; + dev->pci_conf[0x0a] = dev->pci_conf[0x0b] = 0x01; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = 0xf1; + dev->pci_conf[0x11] = 0x01; + dev->pci_conf[0x14] = 0xf5; + dev->pci_conf[0x15] = 0x03; + dev->pci_conf[0x18] = 0x71; + dev->pci_conf[0x19] = 0x01; + dev->pci_conf[0x1c] = 0x75; + dev->pci_conf[0x1d] = 0x03; + dev->pci_conf[0x20] = 0x01; + dev->pci_conf[0x21] = 0xf0; + dev->pci_conf[0x22] = dev->pci_conf[0x23] = 0x00; + dev->pci_conf[0x24] = dev->pci_conf[0x25] = 0x00; + dev->pci_conf[0x26] = dev->pci_conf[0x27] = 0x00; + dev->pci_conf[0x28] = dev->pci_conf[0x29] = 0x00; + dev->pci_conf[0x2a] = dev->pci_conf[0x2b] = 0x00; + switch (dev->rev) { + case 0x00: + case 0xd0: + case 0xd1: + dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00; + break; + case 0xc0: +#ifdef DATASHEET + dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00; +#else + /* The only Linux lspci listing I could find of this chipset, + shows a subsystem of 0058:0000. */ + dev->pci_conf[0x2c] = 0x58; + dev->pci_conf[0x2d] = 0x00; +#endif + break; + } + dev->pci_conf[0x2e] = dev->pci_conf[0x2f] = 0x00; + dev->pci_conf[0x30] = dev->pci_conf[0x31] = 0x00; + dev->pci_conf[0x32] = dev->pci_conf[0x33] = 0x00; + dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00; + dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00; + dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00; + dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = 0x06; + dev->pci_conf[0x4b] = 0x00; + dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00; + dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00; + + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + + sff_bus_master_reset(dev->sis->bm[0]); + sff_bus_master_reset(dev->sis->bm[1]); +} + +static void +sis_5513_ide_close(void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + free(dev); +} + +static void * +sis_5513_ide_init(UNUSED(const device_t *info)) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) calloc(1, sizeof(sis_5513_ide_t)); + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* SFF IDE */ + dev->sis->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->sis->bm[1] = device_add_inst(&sff8038i_device, 2); + + sis_5513_ide_reset(dev); + + return dev; +} + +const device_t sis_5513_ide_device = { + .name = "SiS 5513 IDE controller", + .internal_name = "sis_5513_ide", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5572_ide_device = { + .name = "SiS 5572 IDE controller", + .internal_name = "sis_5572_ide", + .flags = DEVICE_PCI, + .local = 0xc0, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_ide_device = { + .name = "SiS 5582 IDE controller", + .internal_name = "sis_5582_ide", + .flags = DEVICE_PCI, + .local = 0xd0, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5591_5600_ide_device = { + .name = "SiS 5591/(5)600 IDE controller", + .internal_name = "sis_5591_5600_ide", + .flags = DEVICE_PCI, + .local = 0xd1, /* D0, but we need to distinguish them. */ + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c new file mode 100644 index 000000000..ef9a6746d --- /dev/null +++ b/src/chipset/sis_5513_p2i.c @@ -0,0 +1,1383 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5513 PCI to ISA bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> + +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5513_PCI_TO_ISA_LOG +int sis_5513_pci_to_isa_do_log = ENABLE_SIS_5513_PCI_TO_ISA_LOG; + +static void +sis_5513_pci_to_isa_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5513_pci_to_isa_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5513_pci_to_isa_log(fmt, ...) +#endif + +typedef struct sis_5513_pci_to_isa_t { + uint8_t rev; + uint8_t index; + uint8_t dam_index; + uint8_t irq_state; + uint8_t dam_enable; + uint8_t dam_irq_enable; + uint8_t ddma_enable; + uint8_t pci_conf[256]; + uint8_t regs[16]; + uint8_t dam_regs[256]; + uint8_t apc_regs[256]; + + uint16_t dam_base; + uint16_t ddma_base; + uint16_t acpi_io_base; + + sis_55xx_common_t *sis; + port_92_t *port_92; + void *pit; + nvr_t *nvr; + char *fn; + ddma_t *ddma; + acpi_t *acpi; + void *smbus; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); +} sis_5513_pci_to_isa_t; + +static void +sis_5595_acpi_recalc(sis_5513_pci_to_isa_t *dev) +{ + dev->acpi_io_base = (dev->pci_conf[0x91] << 8) | (dev->pci_conf[0x90] & 0xc0); + acpi_update_io_mapping(dev->sis->acpi, dev->acpi_io_base, (dev->pci_conf[0x40] & 0x80)); +} + +static void +sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev) +{ + memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs)); + + if (dev->rev == 0b0) { + dev->apc_regs[0x03] = 0x80; + dev->apc_regs[0x04] = 0x38; + dev->apc_regs[0x07] = 0x01; + } else + dev->apc_regs[0x04] = 0x08; +} + +static void +sis_5513_apc_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t nvr_index = nvr_get_index(dev->nvr, 0); + + sis_5513_pci_to_isa_log("SiS 5595 APC: [W] %04X = %02X\n", addr, val); + + switch (nvr_index) { + case 0x02 ... 0x04: + dev->apc_regs[nvr_index] = val; + break; + case 0x05: + case 0x07 ... 0x08: + if (dev->rev == 0xb0) + dev->apc_regs[nvr_index] = val; + break; + } +} + +static uint8_t +sis_5513_apc_read(uint16_t addr, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t nvr_index = nvr_get_index(dev->nvr, 0); + uint8_t ret = 0xff; + + ret = dev->apc_regs[nvr_index]; + + if (nvr_index == 0x06) + dev->apc_regs[nvr_index] = 0x00; + + sis_5513_pci_to_isa_log("SiS 5595 APC: [R] %04X = %02X\n", addr, ret); + + return ret; +} + +void +sis_5513_apc_recalc(sis_5513_pci_to_isa_t *dev, uint8_t apc_on) +{ + nvr_at_data_port(!apc_on, dev->nvr); + io_removehandler(0x0071, 0x0001, + sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev); + + if (apc_on) + io_removehandler(0x0071, 0x0001, + sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev); +} + +static void +sis_5595_do_nmi(sis_5513_pci_to_isa_t *dev, int set) +{ + if (set) + nmi_raise(); + + dev->irq_state = set; +} + +static void +sis_5595_dam_reset(sis_5513_pci_to_isa_t *dev) +{ + if (dev->irq_state) { + if (dev->dam_regs[0x40] & 0x20) + sis_5595_do_nmi(dev, 0); + else if (dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + } + + memset(dev->dam_regs, 0x00, sizeof(dev->dam_regs)); + + dev->dam_regs[0x40] = 0x08; + dev->dam_regs[0x47] = 0x50; +} + +static void +sis_5595_dam_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint16_t reg = addr - dev->dam_base; + uint8_t old; + + sis_5513_pci_to_isa_log("SiS 5595 DAM: [W] %04X = %02X\n", addr, val); + + switch (reg) { + case 0x05: + dev->dam_index = (dev->index & 0x80) | (val & 0x7f); + break; + case 0x06: + switch (dev->dam_index) { + case 0x40: + old = dev->dam_regs[0x40]; + dev->dam_regs[0x40] = val & 0xef; + if (val & 0x80) { + sis_5595_dam_reset(dev); + return; + } + if (dev->irq_state) { + if (!(old & 0x20) && (val & 0x20)) { + if (dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + sis_5595_do_nmi(dev, 1); + } else if ((old & 0x20) && !(val & 0x20)) { + sis_5595_do_nmi(dev, 0); + if (dev->dam_irq_enable) + pci_set_mirq(6, 1, &dev->irq_state); + } + } + if ((val & 0x08) && dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + break; + case 0x43 ... 0x47: + dev->dam_regs[dev->dam_index] = val; + break; + case 0x2b ... 0x34: + case 0x6b ... 0x74: + case 0x3b ... 0x3c: + case 0x7b ... 0x7c: + dev->dam_regs[dev->dam_index & 0x3f] = val; + break; + } + break; + } +} + +static uint8_t +sis_5595_dam_read(uint16_t addr, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint16_t reg = addr - dev->dam_base; + uint8_t ret = 0xff; + + switch (reg) { + case 0x05: + ret = dev->dam_index; + break; + case 0x06: + switch (dev->dam_index) { + default: + ret = dev->dam_regs[dev->dam_index]; + break; + case 0x20 ... 0x29: + case 0x2b ... 0x3f: + ret = dev->dam_regs[dev->dam_index & 0x3f]; + break; + case 0x2a: + case 0x6a: + ret = dev->pci_conf[0x78]; + break; + } + break; + } + + sis_5513_pci_to_isa_log("SiS 5595 DAM: [R] %04X = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_dam_recalc(sis_5513_pci_to_isa_t *dev) +{ + if (dev->dam_enable && (dev->dam_base != 0x0000)) + io_removehandler(dev->dam_base, 0x0008, + sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev); + + dev->dam_base = dev->pci_conf[0x68] | (dev->pci_conf[0x69] << 16); + dev->dam_enable = !!(dev->pci_conf[0x7b] & 0x80); + + if (dev->dam_enable && (dev->dam_base != 0x0000)) + io_sethandler(dev->dam_base, 0x0008, + sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev); +} + +static void +sis_5595_ddma_recalc(sis_5513_pci_to_isa_t *dev) +{ + uint16_t ch_base; + + dev->ddma_base = (dev->pci_conf[0x80] & 0xf0) | (dev->pci_conf[0x81] << 16); + dev->ddma_enable = !!(dev->pci_conf[0x80] & 0x01); + + for (uint8_t i = 0; i < 8; i++) { + ch_base = dev->ddma_base + (i << 4); + ddma_update_io_mapping(dev->ddma, i, ch_base & 0xff, (ch_base >> 8), + dev->ddma_enable && (dev->pci_conf[0x84] & (1 << i)) && + (dev->ddma_base != 0x0000)); + } +} + +static void +sis_5513_00_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + switch (addr) { + case 0x60: /* MIRQ0 Remapping Control Register */ + case 0x61: /* MIRQ1 Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + dev->pci_conf[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 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[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[addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0x80; + break; + + case 0x66: /* GPIO0 Output Mode Control Register */ + case 0x67: /* GPIO0 Output Mode Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x6a: /* GPIO Status Register */ + dev->pci_conf[addr] |= (val & 0x10); + dev->pci_conf[addr] &= ~(val & 0x01); + break; + + default: + break; + } +} + +static void +sis_5513_01_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */ + case 0x61: /* MIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + dev->pci_conf[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 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[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: /* GPIO Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0x1b; + break; + + case 0x66: /* GPIO Output Mode Control Register */ + case 0x67: /* GPIO Output Mode Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x68: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x69: + dev->pci_conf[addr] = val; + break; + + case 0x6a: + dev->pci_conf[addr] = val & 0xfc; + break; + + case 0x6b: + dev->pci_conf[addr] = val; + break; + + case 0x6c: + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x02) | (val & 0xdc); + break; + + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x72: /* SMI Triggered By IRQ/GPIO Control */ + case 0x73: /* SMI Triggered By IRQ/GPIO Control */ + dev->pci_conf[addr] = val; + 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[addr] = val; + break; + + default: + break; + } +} + +static void +sis_5513_11_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + case 0x61: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xcf; + dev->sis->ide_bits_1_3_writable = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x62: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + dev->sis->usb_enabled = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x63: /* GPCS0 Control Register */ + case 0x64: /* GPCS1 Control Register */ + case 0x65: /* GPCS0 Output Mode Control Register */ + case 0x66: /* GPCS0 Output Mode Control Register */ + case 0x67: /* GPCS1 Output Mode Control Register */ + case 0x68: /* GPCS1 Output Mode Control Register */ + case 0x6b: + case 0x6c: + dev->pci_conf[addr] = val; + break; + + case 0x69: /* GPCS0/1 De-Bounce Control Register */ + dev->pci_conf[addr] = val & 0xdf; + if ((dev->apc_regs[0x03] & 0x40) && (val & 0x10)) { + plat_power_off(); + return; + } + break; + + case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, val & 0xf); + break; + + case 0x6d: /* I2C Bus Control Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard/mouse swapping and keyboard hot key. */ + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: /* Misc. Controller Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard Lock Enable/Disable. */ + break; + + case 0x71: /* Type F DMA Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x72: /* SMI Triggered By IRQ Control */ + dev->pci_conf[addr] = val & 0xfa; + break; + case 0x73: /* SMI Triggered By IRQ Control */ + case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */ + case 0x77: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */ + dev->pci_conf[addr] = val; + break; + + case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */ + case 0x76: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */ + dev->pci_conf[addr] = val & 0xfb; + break; + dev->pci_conf[addr] = val; + break; + + case 0x80: /* Distributed DMA Master Configuration Register */ + case 0x81: /* Distributed DMA Master Configuration Register */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x84: /* Individual Distributed DMA Channel Enable */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x88: /* Serial Interrupt Control Register */ + case 0x89: /* Serial Interrupt Enable Register 1 */ + case 0x8a: /* Serial Interrupt Enable Register 2 */ + dev->pci_conf[addr] = val; + break; + + case 0x90: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val & 0xc0; + sis_5595_acpi_recalc(dev); + break; + case 0x91: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + break; + + default: + break; + } +} + +static void +sis_5513_b0_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + case 0x61: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xdf; + sff_set_mirq(dev->sis->bm[0], (val & 0x10) ? 7 : 2); + sff_set_mirq(dev->sis->bm[1], (val & 0x10) ? 2 : 7); + pci_set_mirq_routing(PCI_MIRQ7, 14 + (!!(val & 0x10))); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x62: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + dev->sis->usb_enabled = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x63: /* PCI OutputBuffer Current Strength Register */ + dev->pci_conf[addr] = val; + if ((dev->apc_regs[0x03] & 0x40) && (val & 0x04)) { + plat_power_off(); + return; + } + if ((val & 0x18) == 0x18) { + dma_reset(); + dma_set_at(1); + + device_reset_all(DEVICE_ALL); + + cpu_alt_reset = 0; + + pci_reset(); + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); + } + break; + + case 0x64: /* INIT Enable Register */ + dev->pci_conf[addr] = val; + cpu_cpurst_on_sr = !(val & 0x20); + break; + + case 0x65: /* PHOLD# Timer */ + case 0x66: /* Priority Timer */ + case 0x67: /* Respond to C/D Segments Register */ + case 0x6b: /* Test Mode Register I */ + case 0x6c: /* Test Mode Register II */ + case 0x71: /* Reserved */ + case 0x72: /* Individual PC/PCI DMA Channel Enable */ + case 0x7c: /* Data Acquisition Module ADC Calibration */ + case 0x7d: /* Data Acquisition Module ADC Calibration */ + case 0x88: /* Serial Interrupt Control Register */ + case 0x89: /* Serial Interrupt Enable Register 1 */ + case 0x8a: /* Serial Interrupt Enable Register 2 */ + case 0x8c: /* Serial Interrupt Enable Register 3 */ + dev->pci_conf[addr] = val; + break; + + case 0x68: /* Data Acquistion Module Base Address */ + dev->pci_conf[addr] = val & 0xf8; + sis_5595_dam_recalc(dev); + break; + + case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0x8f; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, val & 0xf); + break; + + case 0x6d: /* I2C Bus Control Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard/mouse swapping and keyboard hot key. */ + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: /* Misc. Controller Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard Lock Enable/Disable. */ + break; + + case 0x73: + case 0x75 ... 0x79: + if (dev->rev == 0x81) + dev->pci_conf[addr] = val; + break; + + case 0x7a: /* Data Acquisition Module Function Selection Register */ + if (dev->rev == 0x81) + dev->pci_conf[addr] = val; + else + dev->pci_conf[addr] = val & 0x90; + break; + + case 0x7b: /* Data Acquisition Module Control Register */ + dev->pci_conf[addr] = val; + sis_5595_dam_recalc(dev); + break; + + case 0x7e: /* Data Acquisition Module and SMBUS IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: DAM/SMBUS IRQ -> %02X\n", val); + if (dev->rev == 0x81) + dev->pci_conf[addr] = val & 0x8f; + else { + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x10) | (val & 0xef); + + dev->dam_irq_enable = ((val & 0xc0) == 0x40); + smbus_sis5595_irq_enable(dev->smbus, (val & 0xa0) == 0x20); + } + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ6, val & 0xf); + break; + + case 0x80: /* Distributed DMA Master Configuration Register */ + case 0x81: /* Distributed DMA Master Configuration Register */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x84: /* Individual Distributed DMA Channel Enable */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x90: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val & 0xc0; + sis_5595_acpi_recalc(dev); + break; + case 0x91: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + break; + + default: + break; + } +} + +void +sis_5513_pci_to_isa_write(int addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + sis_5513_pci_to_isa_log("SiS 5513 P2I: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x07: /* Status */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x30); + break; + + case 0x0d: /* Master Latency Timer */ + if (dev->rev >= 0x11) + dev->pci_conf[addr] = val; + break; + + case 0x40: /* BIOS Control Register */ + if (dev->rev >= 0x11) { + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + } else + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x41: /* INTA# Remapping Control Register */ + case 0x42: /* INTB# Remapping Control Register */ + case 0x43: /* INTC# Remapping Control Register */ + dev->pci_conf[addr] = val & 0x8f; + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); + break; + case 0x44: /* INTD# Remapping Control Register */ + if (dev->rev == 0x11) { + dev->pci_conf[addr] = val & 0xcf; + sis_5513_apc_recalc(dev, val & 0x10); + } else + dev->pci_conf[addr] = val & 0x8f; + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); + break; + + case 0x45: /* ISA Bus Control Register I */ + if (dev->rev >= 0x01) { + if (dev->rev == 0x01) + dev->pci_conf[addr] = val & 0xec; + else + dev->pci_conf[addr] = val; + 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); + if (dev->rev == 0xb0) + sis_5513_apc_recalc(dev, val & 0x02); + } + break; + case 0x46: /* ISA Bus Control Register II */ + if (dev->rev >= 0x11) + dev->pci_conf[addr] = val; + else if (dev->rev == 0x00) + dev->pci_conf[addr] = val & 0xec; + break; + case 0x47: /* DMA Clock and Wait State Control Register */ + switch (dev->rev) { + case 0x01: + dev->pci_conf[addr] = val & 0x3e; + break; + case 0x11: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0xb0: + dev->pci_conf[addr] = val & 0xfd; + break; + } + 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[addr] = val; + break; + + default: + switch (dev->rev) { + case 0x00: + sis_5513_00_pci_to_isa_write(addr, val, priv); + break; + case 0x01: + sis_5513_01_pci_to_isa_write(addr, val, priv); + break; + case 0x11: + sis_5513_11_pci_to_isa_write(addr, val, priv); + break; + case 0x81: + case 0xb0: + sis_5513_b0_pci_to_isa_write(addr, val, priv); + break; + } + break; + } +} + +uint8_t +sis_5513_pci_to_isa_read(int addr, void *priv) +{ + const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + default: + ret = dev->pci_conf[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; + case 0x60: + if (dev->rev >= 0x01) + ret = inb(0x0070); + else + ret = dev->pci_conf[addr]; + break; + } + + sis_5513_pci_to_isa_log("SiS 5513 P2I: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + switch (addr) { + case 0x22: + dev->index = val - 0x50; + break; + case 0x23: + sis_5513_pci_to_isa_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) +{ + const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t ret = 0xff; + + if (addr == 0x23) { + if (dev->index == 0x05) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + + sis_5513_pci_to_isa_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret); + } + + return ret; +} + +static void +sis_5513_00_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x80; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0x80; + dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = 0x04; + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, 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; +} + +static void +sis_5513_01_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = 0x80; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0x80; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = 0x80; + dev->pci_conf[0x69] = dev->pci_conf[0x6a] = 0x00; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x02; + dev->pci_conf[0x6d] = 0x00; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); +} + +static void +sis_5513_11_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80; + dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = dev->pci_conf[0x68] = 0x00; + dev->pci_conf[0x69] = 0x01; + dev->pci_conf[0x6a] = 0x80; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x20; + dev->pci_conf[0x6d] = 0x19; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = 0x12; + dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x73] = dev->pci_conf[0x74] = 0x00; + dev->pci_conf[0x75] = dev->pci_conf[0x76] = 0x00; + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00; + dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + + picint_common(0xffff, 0, 0, NULL); + + sis_5595_ddma_recalc(dev); + sis_5595_acpi_recalc(dev); + + dev->sis->ide_bits_1_3_writable = 0; + dev->sis->usb_enabled = 0; + + sis_5513_apc_recalc(dev, 0); +} + +static void +sis_5513_b0_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80; + dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x01; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = 0x90; + dev->pci_conf[0x69] = 0x02; + dev->pci_conf[0x6a] = 0x80; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x20; + dev->pci_conf[0x6d] = 0x19; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = 0x12; + dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = 0x80; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00; + dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00; + dev->pci_conf[0x8b] = dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ7, 15); + + sff_set_mirq(dev->sis->bm[0], 2); + sff_set_mirq(dev->sis->bm[1], 7); + + picint_common(0xffff, 0, 0, NULL); + + sis_5595_ddma_recalc(dev); + sis_5595_acpi_recalc(dev); + + /* SiS 5595 Data Acquisition Module */ + sis_5595_dam_recalc(dev); + sis_5595_dam_reset(dev); + + dev->dam_irq_enable = 0; + + cpu_cpurst_on_sr = 1; + + dev->sis->usb_enabled = 0; + + sis_5513_apc_recalc(dev, 0); + + if (dev->rev == 0x81) + dev->dam_irq_enable = 1; +} + +static void +sis_5513_pci_to_isa_reset(void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x08; + dev->pci_conf[0x03] = 0x00; + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + if ((dev->rev == 0x11) || (dev->rev == 0x81)) + dev->pci_conf[0x08] = 0x01; + else + dev->pci_conf[0x08] = dev->rev; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x01; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x40] = 0x00; + dev->pci_conf[0x41] = dev->pci_conf[0x42] = 0x80; + dev->pci_conf[0x43] = dev->pci_conf[0x44] = 0x80; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00; + + switch (dev->rev) { + case 0x00: + sis_5513_00_pci_to_isa_reset(dev); + break; + case 0x01: + sis_5513_01_pci_to_isa_reset(dev); + break; + case 0x11: + sis_5513_11_pci_to_isa_reset(dev); + break; + case 0x81: + case 0xb0: + sis_5513_b0_pci_to_isa_reset(dev); + break; + } + + 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_MIRQ2, PCI_IRQ_DISABLED); + + cpu_set_isa_speed(7159091); + nvr_bank_set(0, 0, dev->nvr); +} + +static void +sis_5513_pci_to_isa_close(void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + FILE *fp = NULL; + + if (dev->fn != NULL) + fp = nvr_fopen(dev->fn, "wb"); + + if (fp != NULL) { + (void) fwrite(dev->apc_regs, 256, 1, fp); + fclose(fp); + } + + if (dev->fn != NULL) + free(dev->fn); + + free(dev); +} + +static void * +sis_5513_pci_to_isa_init(UNUSED(const device_t *info)) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) calloc(1, sizeof(sis_5513_pci_to_isa_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); + FILE *fp = NULL; + int c; + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* IDEIRQ */ + pci_enable_mirq(2); + + /* Port 92h */ + dev->port_92 = device_add(&port_92_device); + + /* 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); + + switch (dev->rev) { + case 0x00: + /* MIRQ */ + pci_enable_mirq(0); + pci_enable_mirq(1); + + /* Ports 22h-23h: SiS 5513 ISA */ + io_sethandler(0x0022, 0x0002, + sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); + break; + case 0x01: + /* MIRQ */ + pci_enable_mirq(1); + break; + case 0x11: + case 0x81: + case 0xb0: + /* USBIRQ */ + pci_enable_mirq(3); + + /* ACPI/SCI IRQ */ + pci_enable_mirq(5); + + if (dev->rev == 0xb0) { + /* Data Acquisition Module and SMBUS IRQ */ + pci_enable_mirq(6); + + /* Non-remapped native IDE IRQ */ + pci_enable_mirq(7); + } + + dev->ddma = device_add(&ddma_device); + + switch (dev->rev) { + case 0x11: + dev->sis->acpi = device_add(&acpi_sis_5582_device); + break; + case 0x81: + dev->sis->acpi = device_add(&acpi_sis_5595_1997_device); + break; + case 0xb0: + dev->sis->acpi = device_add(&acpi_sis_5595_device); + dev->smbus = acpi_get_smbus(dev->sis->acpi); + break; + } + + dev->sis->acpi->priv = dev->sis; + acpi_set_slot(dev->sis->acpi, dev->sis->sb_pci_slot); + acpi_set_nvr(dev->sis->acpi, dev->nvr); + + /* Set up the NVR file's name. */ + c = strlen(machine_get_internal_name()) + 9; + dev->fn = (char *) malloc(c + 1); + sprintf(dev->fn, "%s_apc.nvr", machine_get_internal_name()); + + fp = nvr_fopen(dev->fn, "rb"); + + memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs)); + sis_5513_apc_reset(dev); + if (fp != NULL) { + if (fread(dev->apc_regs, 1, 256, fp) != 256) + fatal("sis_5513_pci_to_isa_init(): Error reading APC data\n"); + fclose(fp); + } + + acpi_set_irq_mode(dev->sis->acpi, 2); + break; + } + + sis_5513_pci_to_isa_reset(dev); + + return dev; +} + +const device_t sis_5513_p2i_device = { + .name = "SiS 5513 PCI to ISA bridge", + .internal_name = "sis_5513_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5572_p2i_device = { + .name = "SiS 5572 PCI to ISA bridge", + .internal_name = "sis_5572_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x01, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_p2i_device = { + .name = "SiS 5582 PCI to ISA bridge", + .internal_name = "sis_5582_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x11, /* Actually, 0x01, but we need to somehow distinguish it + from SiS 5572 and SiS 5595 1997, which are also revision 0x01. */ + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_1997_p2i_device = { + .name = "SiS 5595 (1997) PCI to ISA bridge", + .internal_name = "sis_5595_1997_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x81, /* Actually, 0x01, but we need to somehow distinguish it + from SiS 5572 and SiS 5582, which are also revision 0x01. */ + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_p2i_device = { + .name = "SiS 5595 PCI to ISA bridge", + .internal_name = "sis_5595_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0xb0, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_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 f130ecd8a..3fb111978 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -6,13 +6,11 @@ * * This file is part of the 86Box distribution. * - * Implementation of the SiS 5571 Chipset. + * Implementation of the SiS 5571/5572 Pentium PCI/ISA Chipset. * + * Authors: Miran Grca, * - * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Copyright 2021-2023 Miran Grca. */ #include #include @@ -25,37 +23,26 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - -#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/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.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/usb.h> - +#include <86box/spd.h> +#include <86box/sis_55xx.h> #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 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 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_5571_LOG int sis_5571_do_log = ENABLE_SIS_5571_LOG; @@ -75,649 +62,83 @@ sis_5571_log(const char *fmt, ...) #endif typedef struct sis_5571_t { - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; - uint8_t usb_irq_state; + uint8_t nb_slot; + uint8_t sb_slot; - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[3][256]; + void *h2p; + void *p2i; + void *ide; + void *usb; - port_92_t *port_92; - sff8038i_t *ide_drive[2]; - smram_t *smram; - usb_t *usb; + sis_55xx_common_t *sis; } sis_5571_t; static void -sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev) +sis_5571_write(int func, int addr, uint8_t val, void *priv) { - 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); + const sis_5571_t *dev = (sis_5571_t *) priv; - flushmmucache_nopc(); + sis_5571_log("SiS 5571: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5571_host_to_pci_write(addr, val, dev->h2p); +} + +static uint8_t +sis_5571_read(int func, int addr, void *priv) +{ + const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5571_host_to_pci_read(addr, dev->h2p); + + sis_5571_log("SiS 5571: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; } static void -sis_5571_smm_recalc(sis_5571_t *dev) +sis_5572_write(int func, int addr, uint8_t val, void *priv) { - smram_disable_all(); + const sis_5571_t *dev = (sis_5571_t *) priv; - switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) { + sis_5571_log("SiS 5572: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { case 0x00: - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + sis_5513_pci_to_isa_write(addr, val, dev->p2i); break; case 0x01: - smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + sis_5513_ide_write(addr, val, dev->ide); 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; - - default: - break; - } - - flushmmucache(); -} - -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(); - } - } -} - -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); -} - -static void -memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *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; - - case 0x06: /* Status - Low Byte */ - dev->pci_conf[addr] &= val; - 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 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 0x52: - dev->pci_conf[addr] = val & 0xd0; - break; - - case 0x53: /* DRAM */ - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x54: /* FP/EDO */ - dev->pci_conf[addr] = val; - 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 0x59: /* Buffer strength and current rating */ - dev->pci_conf[addr] = val; - 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 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 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 0x81: - dev->pci_conf[addr] = val & 0xcc; - 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 0x84: - case 0x85: - case 0x86: - dev->pci_conf[addr] = val; - 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 0x93: /* STPCLK# and APM SMI control */ - dev->pci_conf[addr] = val; - - 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 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 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 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(UNUSED(int func), int addr, void *priv) -{ - 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; - - 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 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; - - default: - break; - } - break; - - case 0x46: - dev->pci_conf_sb[0][addr] = val & 0xec; - break; - - case 0x47: /* DMA Clock and Wait State Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3e; - 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 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 0x5f: - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; - - case 0x60: - dev->pci_conf_sb[0][addr] = val; - 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 0x62: /* On-board Device DMA Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x0f; - dma_set_drq((val & 0x07), 1); - 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 0x64: /* GPIO Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; - - case 0x65: - 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 0x68: /* USBIRQ Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x1b; - break; - - case 0x69: - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6a: - dev->pci_conf_sb[0][addr] = val & 0xfc; - break; - - case 0x6b: - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6c: - dev->pci_conf_sb[0][addr] = val & 0x03; - 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 0x70: - dev->pci_conf_sb[0][addr] = val & 0xde; - break; - - case 0x71: /* Type-F DMA Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xfe; - 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 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; - - default: - break; - } - sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, 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 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] &= val; - break; - - case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = val & 0xcf; - sis_5571_ide_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 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 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 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0xaf; - sis_5571_ide_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; - - default: - break; - } - sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", 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 0x05: /* Command - High Byte */ - dev->pci_conf_sb[2][addr] = val & 0x03; - break; - - 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: + sis_5572_usb_write(addr, val, dev->usb); break; } } static uint8_t -pci_isa_bridge_read(int func, int addr, void *priv) +sis_5572_read(int func, int addr, void *priv) { const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 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; + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5513_ide_read(addr, dev->ide); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; } -} -static void -sis_5571_reset(void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; + sis_5571_log("SiS 5572: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); - /* 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; - - /* 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; + return ret; } static void @@ -725,34 +146,25 @@ sis_5571_close(void *priv) { sis_5571_t *dev = (sis_5571_t *) priv; - smram_del(dev->smram); free(dev); } static void * 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 *) calloc(1, sizeof(sis_5571_t)); - 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); + /* Device 0: SiS 5571 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5571_read, sis_5571_write, dev, &dev->nb_slot); + /* Device 1: SiS 5572 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5572_read, sis_5572_write, dev, &dev->sb_slot); - /* MIRQ */ - pci_enable_mirq(0); + dev->sis = device_add(&sis_55xx_common_device); - /* 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); - - /* USB */ - dev->usb = device_add(&usb_device); - - sis_5571_reset(dev); + dev->h2p = device_add_linked(&sis_5571_h2p_device, dev->sis); + dev->p2i = device_add_linked(&sis_5572_p2i_device, dev->sis); + dev->ide = device_add_linked(&sis_5572_ide_device, dev->sis); + dev->usb = device_add_linked(&sis_5572_usb_device, dev->sis); return dev; } @@ -764,7 +176,7 @@ const device_t sis_5571_device = { .local = 0, .init = sis_5571_init, .close = sis_5571_close, - .reset = sis_5571_reset, + .reset = NULL, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c new file mode 100644 index 000000000..4a4ee9b83 --- /dev/null +++ b/src/chipset/sis_5571_h2p.c @@ -0,0 +1,458 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5571 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5571_HOST_TO_PCI_LOG +int sis_5571_host_to_pci_do_log = ENABLE_SIS_5571_HOST_TO_PCI_LOG; + +static void +sis_5571_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5571_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5571_host_to_pci_log(fmt, ...) +#endif + +typedef struct sis_5571_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + sis_55xx_common_t *sis; + + smram_t *smram; +} sis_5571_host_to_pci_t; + +static void +sis_5571_shadow_recalc(sis_5571_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + 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_5571_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + 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_5571_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + 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_5571_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5571_smram_recalc(sis_5571_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0xa3] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + sis_5571_host_to_pci_log("SiS 5571 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - low byte */ + case 0x05: /* Command - high byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xb8); + 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 0x51: /* CACHE */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; + + case 0x53: /* DRAM */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x54: /* FP/EDO */ + dev->pci_conf[addr] = val; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x56: /* MDLE delay */ + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x57: /* SDRAM */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x59: /* Buffer strength and current rating */ + dev->pci_conf[addr] = val; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + /* Undocumented - DRAM bank registers, the exact layout is currently unknown. */ + case 0x60 ... 0x6b: + dev->pci_conf[addr] = val; + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5571_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5571_shadow_recalc(dev); + 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 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xcc; + break; + + case 0x82: + dev->pci_conf[addr] = val; + break; + + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */ + break; + + case 0x84 ... 0x86: + dev->pci_conf[addr] = val; + 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 0x93: /* STPCLK# and APM SMI control */ + dev->pci_conf[addr] = val; + + if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) { + smi_raise(); + dev->pci_conf[0x9d] |= 0x01; + } + 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 0x97: /* programmable 10-bit I/O port address */ + case 0x98: /* Programmable 16-bit I/O port */ + case 0x99 ... 0x9c: + 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 ... 0xa2: + dev->pci_conf[addr] = val; + break; + + case 0xa3: /* SMRAM access control and Power supply control */ + dev->pci_conf[addr] = val & 0xd0; + sis_5571_smram_recalc(dev); + break; + } +} + +uint8_t +sis_5571_host_to_pci_read(int addr, void *priv) +{ + const sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5571_host_to_pci_log("SiS 5571 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5571_host_to_pci_reset(void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x00; + dev->pci_conf[0x0f] = 0x00; + + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x00; + dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = 0x54; + dev->pci_conf[0x55] = 0x54; + dev->pci_conf[0x56] = 0x03; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x00; + + /* Undocumented DRAM bank registers. */ + dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04; + dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04; + dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04; + dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80; + dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6b] = 0x80; + + dev->pci_conf[0x70] = 0x00; + dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = 0x00; + dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = 0x00; + + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = 0x00; + dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = 0x00; + dev->pci_conf[0x7b] = 0x00; + + 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; + dev->pci_conf[0x87] = 0x00; + + dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x8d] = 0x00; + dev->pci_conf[0x8e] = 0x00; + dev->pci_conf[0x8f] = 0x00; + + dev->pci_conf[0x90] = 0x00; + dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = 0x00; + dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = 0x00; + dev->pci_conf[0x95] = 0x00; + dev->pci_conf[0x96] = 0x00; + dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = 0x00; + dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = 0x00; + dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = 0x00; + dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = 0xff; + dev->pci_conf[0x9f] = 0xff; + + dev->pci_conf[0xa0] = 0xff; + dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = 0xff; + dev->pci_conf[0xa3] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5571_smram_recalc(dev); + sis_5571_shadow_recalc(dev); + + flushmmucache(); +} + +static void +sis_5571_host_to_pci_close(void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5571_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) calloc(1, sizeof(sis_5571_host_to_pci_t)); + + dev->sis = device_get_common_priv(); + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5571_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5571_h2p_device = { + .name = "SiS 5571 Host to PCI bridge", + .internal_name = "sis_5571_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5571_host_to_pci_init, + .close = sis_5571_host_to_pci_close, + .reset = sis_5571_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5571_old.c b/src/chipset/sis_5571_old.c new file mode 100644 index 000000000..f130ecd8a --- /dev/null +++ b/src/chipset/sis_5571_old.c @@ -0,0 +1,772 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5571 Chipset. + * + * + * + * Authors: Tiseno100, + * + * Copyright 2021 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/timer.h> + +#include <86box/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> +#include <86box/smram.h> +#include <86box/usb.h> + +#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 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 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_5571_LOG +int sis_5571_do_log = ENABLE_SIS_5571_LOG; + +static void +sis_5571_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5571_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5571_log(fmt, ...) +#endif + +typedef struct sis_5571_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t usb_irq_state; + + 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); + + flushmmucache_nopc(); +} + +static void +sis_5571_smm_recalc(sis_5571_t *dev) +{ + 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; + + default: + break; + } + + flushmmucache(); +} + +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(); + } + } +} + +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); +} + +static void +memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *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; + + case 0x06: /* Status - Low Byte */ + dev->pci_conf[addr] &= val; + 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 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 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; + + case 0x53: /* DRAM */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x54: /* FP/EDO */ + dev->pci_conf[addr] = val; + 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 0x59: /* Buffer strength and current rating */ + dev->pci_conf[addr] = val; + 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 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 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 0x81: + dev->pci_conf[addr] = val & 0xcc; + 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 0x84: + case 0x85: + case 0x86: + dev->pci_conf[addr] = val; + 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 0x93: /* STPCLK# and APM SMI control */ + dev->pci_conf[addr] = val; + + 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 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 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 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(UNUSED(int func), int addr, void *priv) +{ + 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; + + 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 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; + + default: + break; + } + break; + + case 0x46: + dev->pci_conf_sb[0][addr] = val & 0xec; + break; + + case 0x47: /* DMA Clock and Wait State Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3e; + 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 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 0x5f: + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; + + case 0x60: + dev->pci_conf_sb[0][addr] = val; + 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 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x0f; + dma_set_drq((val & 0x07), 1); + 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 0x64: /* GPIO Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xef; + break; + + case 0x65: + 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 0x68: /* USBIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; + + case 0x69: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6a: + dev->pci_conf_sb[0][addr] = val & 0xfc; + break; + + case 0x6b: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6c: + dev->pci_conf_sb[0][addr] = val & 0x03; + 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 0x70: + dev->pci_conf_sb[0][addr] = val & 0xde; + break; + + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xfe; + 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 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; + + default: + break; + } + sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, 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 0x07: /* Status high byte */ + dev->pci_conf_sb[1][addr] &= val; + break; + + case 0x09: /* Programming Interface Byte */ + dev->pci_conf_sb[1][addr] = val & 0xcf; + sis_5571_ide_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 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 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 0x4a: /* IDE General Control Register 0 */ + dev->pci_conf_sb[1][addr] = val & 0xaf; + sis_5571_ide_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; + + default: + break; + } + sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", 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 0x05: /* Command - High Byte */ + dev->pci_conf_sb[2][addr] = val & 0x03; + break; + + 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) +{ + 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; + } +} + +static void +sis_5571_reset(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + /* Memory/PCI Bridge */ + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0xfd; + dev->pci_conf[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; + + /* 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; +} + +static void +sis_5571_close(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5571_init(UNUSED(const device_t *info)) +{ + sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t)); + memset(dev, 0x00, sizeof(sis_5571_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->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); + + /* 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); + + /* USB */ + dev->usb = device_add(&usb_device); + + sis_5571_reset(dev); + + return dev; +} + +const device_t sis_5571_device = { + .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_5572_usb.c b/src/chipset/sis_5572_usb.c new file mode 100644 index 000000000..250c32587 --- /dev/null +++ b/src/chipset/sis_5572_usb.c @@ -0,0 +1,323 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5572 USB controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5572_USB_LOG +int sis_5572_usb_do_log = ENABLE_SIS_5572_USB_LOG; + +static void +sis_5572_usb_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5572_usb_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5572_usb_log(fmt, ...) +#endif + +typedef struct sis_5572_usb_t { + uint8_t rev; + + uint8_t usb_unk_regs[256]; + uint8_t pci_conf[256]; + + uint16_t usb_unk_base; + + usb_t *usb; + + sis_55xx_common_t *sis; +} sis_5572_usb_t; + +/* SiS 5572 unknown I/O port (second USB PCI BAR). */ +static void +sis_5572_usb_unk_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + addr = (addr - dev->usb_unk_base) & 0x07; + + sis_5572_usb_log("SiS 5572 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val); + + dev->usb_unk_regs[addr] = val; +} + +static uint8_t +sis_5572_usb_unk_read(uint16_t addr, void *priv) +{ + const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->usb_unk_base) & 0x07; + + ret = dev->usb_unk_regs[addr & 0x07]; + + sis_5572_usb_log("SiS 5572 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret); + + return ret; +} + +void +sis_5572_usb_write(int addr, uint8_t val, void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + sis_5572_usb_log("SiS 5572 USB: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (dev->sis->usb_enabled) switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + if (dev->rev == 0xb0) + dev->pci_conf[addr] = val & 0x47; + else + dev->pci_conf[addr] = val & 0x57; + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + if (dev->pci_conf[0x04] & 0x01) + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02); + break; + + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xf9); + break; + + case 0x0d: /* Latency Timer */ + dev->pci_conf[addr] = val; + break; + + case 0x11 ... 0x13: /* Memory Space Base Address Register */ + dev->pci_conf[addr] = val & ((addr == 0x11) ? 0xf0 : 0xff); + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[4] & 0x02); + break; + + case 0x14 ... 0x15: /* IO Space Base Address Register */ + if (dev->rev == 0xb0) { + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + dev->pci_conf[addr] = val; + dev->usb_unk_base = (dev->pci_conf[0x14] & 0xf8) | + (dev->pci_conf[0x15] << 8); + if (dev->usb_unk_base != 0x0000) { + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + } + break; + + case 0x2c ... 0x2f: + if (dev->rev == 0x11) + dev->pci_conf[addr] = val; + break; + + case 0x3c: /* Interrupt Line */ + dev->pci_conf[addr] = val; + break; + } +} + +uint8_t +sis_5572_usb_read(int addr, void *priv) +{ + const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + uint8_t ret = 0xff; + + if (dev->sis->usb_enabled) { + ret = dev->pci_conf[addr]; + + sis_5572_usb_log("SiS 5572 USB: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + } + + return ret; +} + +static void +sis_5572_usb_reset(void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x01; + dev->pci_conf[0x03] = 0x70; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = (dev->rev == 0xb0) ? 0x00 : 0x80; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = dev->rev; + dev->pci_conf[0x09] = 0x10; + dev->pci_conf[0x0a] = 0x03; + dev->pci_conf[0x0b] = 0x0c; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = 0x00; + dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = 0x00; + dev->pci_conf[0x13] = 0x00; + if (dev->rev == 0xb0) { + dev->pci_conf[0x14] = 0x01; + dev->pci_conf[0x15] = 0x00; + dev->pci_conf[0x16] = 0x00; + dev->pci_conf[0x17] = 0x00; + } else if (dev->rev == 0x11) { + dev->pci_conf[0x2c] = 0x00; + dev->pci_conf[0x2d] = 0x00; + dev->pci_conf[0x2e] = 0x00; + dev->pci_conf[0x2f] = 0x00; + } + dev->pci_conf[0x3c] = 0x00; + dev->pci_conf[0x3d] = PCI_INTA; + dev->pci_conf[0x3e] = 0x00; + dev->pci_conf[0x3f] = 0x00; + + if (dev->rev == 0xb0) { + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02); + + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + + dev->usb_unk_base = 0x0000; + + memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs)); + } +} + +static void +sis_5572_usb_close(void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + free(dev); +} + +static void * +sis_5572_usb_init(UNUSED(const device_t *info)) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) calloc(1, sizeof(sis_5572_usb_t)); + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* USB */ + dev->usb = device_add(&usb_device); + + sis_5572_usb_reset(dev); + + return dev; +} + +const device_t sis_5572_usb_device = { + .name = "SiS 5572 USB controller", + .internal_name = "sis_5572_usb", + .flags = DEVICE_PCI, + .local = 0xb0, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_usb_device = { + .name = "SiS 5582 USB controller", + .internal_name = "sis_5582_usb", + .flags = DEVICE_PCI, + .local = 0xe0, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_usb_device = { + .name = "SiS 5595 USB controller", + .internal_name = "sis_5595_usb", + .flags = DEVICE_PCI, + .local = 0x11, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5581.c b/src/chipset/sis_5581.c new file mode 100644 index 000000000..e2308c2d9 --- /dev/null +++ b/src/chipset/sis_5581.c @@ -0,0 +1,184 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5581/5582 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.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/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5581_LOG +int sis_5581_do_log = ENABLE_SIS_5581_LOG; + +static void +sis_5581_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5581_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5581_log(fmt, ...) +#endif + +typedef struct sis_5581_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + + sis_55xx_common_t *sis; +} sis_5581_t; + +static void +sis_5581_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + + sis_5581_log("SiS 5581: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5581_host_to_pci_write(addr, val, dev->h2p); +} + +static uint8_t +sis_5581_read(int func, int addr, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5581_host_to_pci_read(addr, dev->h2p); + + sis_5581_log("SiS 5581: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5582_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + + sis_5581_log("SiS 5582: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5513_ide_write(addr, val, dev->ide); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5582_read(int func, int addr, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5513_ide_read(addr, dev->ide); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5581_log("SiS 5582: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5581_close(void *priv) +{ + sis_5581_t *dev = (sis_5581_t *) priv; + + free(dev); +} + +static void * +sis_5581_init(UNUSED(const device_t *info)) +{ + sis_5581_t *dev = (sis_5581_t *) calloc(1, sizeof(sis_5581_t)); + + /* Device 0: SiS 5581 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5581_read, sis_5581_write, dev, &dev->nb_slot); + /* Device 1: SiS 5582 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5582_read, sis_5582_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->p2i = device_add_linked(&sis_5582_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5581_h2p_device, dev->sis); + dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis); + dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis); + + return dev; +} + +const device_t sis_5581_device = { + .name = "SiS 5581", + .internal_name = "sis_5581", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5581_init, + .close = sis_5581_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c new file mode 100644 index 000000000..30bd70bfe --- /dev/null +++ b/src/chipset/sis_5581_h2p.c @@ -0,0 +1,552 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5581 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5581_HOST_TO_PCI_LOG +int sis_5581_host_to_pci_do_log = ENABLE_SIS_5581_HOST_TO_PCI_LOG; + +static void +sis_5581_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5581_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5581_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5581_io_trap_t { + void *priv; + void *trap; + uint8_t flags, mask; + uint8_t *sts_reg, sts_mask; + uint16_t addr; +} sis_5581_io_trap_t; + +typedef struct sis_5581_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + ram_bank_t ram_banks[3]; + + sis_5581_io_trap_t io_traps[10]; + + sis_55xx_common_t *sis; + + smram_t *smram; +} sis_5581_host_to_pci_t; + +static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b }; + +static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000, /* 256 MB */ + 0x20000000 }; /* 512 MB */ + +static void +sis_5581_shadow_recalc(sis_5581_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + 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_5581_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + 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_5581_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + 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_5581_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5581_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), + void *priv) +{ + sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv; + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) trap->priv; + + trap->sts_reg[0x04] |= trap->sts_mask; + + if (trap->sts_reg[0x00] & trap->sts_mask) + acpi_sis5582_pmu_event(dev->sis->acpi); +} + +static void +sis_5581_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv; + + if ((addr & trap->mask) == (trap->addr & trap->mask)) + sis_5581_trap_io(size, addr, write, val, priv); +} + +static void +sis_5581_trap_update_devctl(sis_5581_host_to_pci_t *dev, uint8_t trap_id, uint8_t enable, + uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask, + uint16_t addr, uint16_t size) +{ + sis_5581_io_trap_t *trap = &dev->io_traps[trap_id]; + + /* Set up Device I/O traps dynamically. */ + if (enable && !trap->trap) { + trap->priv = (void *) dev; + trap->flags = flags; + trap->mask = mask; + trap->addr = addr; + if (flags & 0x08) + trap->trap = io_trap_add(sis_5581_trap_io_mask, trap); + else + trap->trap = io_trap_add(sis_5581_trap_io, trap); + trap->sts_reg = sts_reg; + trap->sts_mask = sts_mask; + } + + /* Remap I/O trap. */ + io_trap_remap(trap->trap, enable, addr, size); +} + +static void +sis_5581_trap_update(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + uint8_t trap_id = 0; + uint8_t *fregs = dev->pci_conf; + uint16_t temp; + uint8_t mask; + uint8_t on; + + on = fregs[0x9a]; + + temp = ((fregs[0x96] & 0x02) | (fregs[0x97] << 2)) & 0x03ff; + mask = ~((1 << ((fregs[0x96] >> 3) & 0x07)) - 1); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x08, mask, &(fregs[0x9c]), 0x40, temp, 0x80); + + temp = fregs[0x98] | (fregs[0x99] << 8); + mask = 0xff; + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x08, mask, &(fregs[0x9c]), 0x20, temp, 0x80); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x378, 0x08); + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x278, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9c]), 0x08, 0x3f8, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x00, 0xff, &(fregs[0x9c]), 0x04, 0x2f8, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x9c]), 0x02, 0x1f0, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x01, 0x00, 0xff, &(fregs[0x9c]), 0x01, 0x170, 0x08); + + on = fregs[0x9b]; + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x064, 0x01); + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x060, 0x01); +} + +static void +sis_5581_smram_recalc(sis_5581_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0xa3] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + sis_5581_host_to_pci_log("SiS 5581 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfc) | (val & 0x03); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xb8); + break; + + case 0x0d: /* Master latency timer */ + case 0x50: + case 0x54: + case 0x56 ... 0x57: + case 0x59: + dev->pci_conf[addr] = val; + break; + + case 0x51: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xeb; + break; + + case 0x53: + case 0x55: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x58: + dev->pci_conf[addr] = val & 0xfc; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5581_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5581_shadow_recalc(dev); + 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 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xde; + break; + + case 0x82: + dev->pci_conf[addr] = val; + break; + + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */ + break; + + case 0x84 ... 0x86: + case 0x88 ... 0x8b: + dev->pci_conf[addr] = val; + break; + + case 0x87: /* Miscellanea */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x8c ... 0x92: + case 0x9e ... 0xa2: + dev->pci_conf[addr] = val; + break; + + case 0x93: + dev->pci_conf[addr] = val; + if (val & 0x02) { + dev->pci_conf[0x9d] |= 0x01; + if (dev->pci_conf[0x9b] & 0x01) + acpi_sis5582_pmu_event(dev->sis->acpi); + } + break; + + case 0x94: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x95: + dev->pci_conf[addr] = val & 0xfb; + break; + + case 0x96: + dev->pci_conf[addr] = val & 0xfb; + sis_5581_trap_update(dev); + break; + case 0x97 ... 0x9b: + dev->pci_conf[addr] = val; + sis_5581_trap_update(dev); + break; + + case 0x9c ... 0x9d: + dev->pci_conf[addr] &= ~val; + break; + + case 0xa3: + dev->pci_conf[addr] = val; + sis_5581_smram_recalc(dev); + break; + } +} + +uint8_t +sis_5581_host_to_pci_read(int addr, void *priv) +{ + const sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5581_host_to_pci_log("SiS 5581 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5581_host_to_pci_reset(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x97; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x02; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x00; + dev->pci_conf[0x53] = 0x38; + dev->pci_conf[0x54] = 0x54; + dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = 0x80; + dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + 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] = dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x95] = 0x00; + dev->pci_conf[0x96] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0xff; + dev->pci_conf[0xa0] = 0xff; + dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = 0xff; + dev->pci_conf[0xa3] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5581_shadow_recalc(dev); + + sis_5581_trap_update(dev); + + sis_5581_smram_recalc(dev); +} + +static void +sis_5581_host_to_pci_close(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5581_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) calloc(1, sizeof(sis_5581_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 6; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5581_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5581_h2p_device = { + .name = "SiS 5581 Host to PCI bridge", + .internal_name = "sis_5581_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5581_host_to_pci_init, + .close = sis_5581_host_to_pci_close, + .reset = sis_5581_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5591.c b/src/chipset/sis_5591.c new file mode 100644 index 000000000..969fcb8dd --- /dev/null +++ b/src/chipset/sis_5591.c @@ -0,0 +1,210 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5591/5592 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.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/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5591_LOG +int sis_5591_do_log = ENABLE_SIS_5591_LOG; + +static void +sis_5591_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5591_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5591_log(fmt, ...) +#endif + +typedef struct sis_5591_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + void *pmu; + + sis_55xx_common_t *sis; +} sis_5591_t; + +static void +sis_5591_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + + sis_5591_log("SiS 5591: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5591_host_to_pci_write(addr, val, dev->h2p); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); +} + +static uint8_t +sis_5591_read(int func, int addr, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5591_host_to_pci_read(addr, dev->h2p); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); + + sis_5591_log("SiS 5591: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + + sis_5591_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5595_pmu_write(addr, val, dev->pmu); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5595_read(int func, int addr, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5595_pmu_read(addr, dev->pmu); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5591_log("SiS 5592: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5591_close(void *priv) +{ + sis_5591_t *dev = (sis_5591_t *) priv; + + free(dev); +} + +static void * +sis_5591_init(UNUSED(const device_t *info)) +{ + sis_5591_t *dev = (sis_5591_t *) calloc(1, sizeof(sis_5591_t)); + + /* Device 0: SiS 5591 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5591_read, sis_5591_write, dev, &dev->nb_slot); + /* Device 1: SiS 5595 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis); + if (info->local) + dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis); + else + dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5591_h2p_device, dev->sis); + dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis); + if (info->local) + dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis); + else + dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis); + + return dev; +} + +const device_t sis_5591_1997_device = { + .name = "SiS 5591 (1997)", + .internal_name = "sis_5591_1997", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_5591_init, + .close = sis_5591_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5591_device = { + .name = "SiS 5591", + .internal_name = "sis_5591", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5591_init, + .close = sis_5591_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c new file mode 100644 index 000000000..8fcbeeb6f --- /dev/null +++ b/src/chipset/sis_5591_h2p.c @@ -0,0 +1,493 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5591 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5591_HOST_TO_PCI_LOG +int sis_5591_host_to_pci_do_log = ENABLE_SIS_5591_HOST_TO_PCI_LOG; + +static void +sis_5591_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5591_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5591_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5591_host_to_pci_t { + uint8_t pci_conf[256]; + + uint8_t states[7]; + uint8_t states_bus[7]; + + ram_bank_t ram_banks[3]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + agpgart_t *agpgart; +} sis_5591_host_to_pci_t; + +static uint8_t bank_codes[6] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a }; + +static uint32_t bank_sizes[6] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000 }; /* 256 MB */ + +static void +sis_5591_shadow_recalc(sis_5591_host_to_pci_t *dev) +{ + uint32_t base; + uint32_t state; + uint8_t val; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + val = dev->pci_conf[i]; + if ((dev->states[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(0xf0000, 0x10000, state); + sis_5591_host_to_pci_log("000F0000-000FFFFF\n"); + + dev->states[i & 0x0f] = val; + } + + if (!(dev->pci_conf[0x76] & 0x08)) + val &= 0x5f; + if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(0xf0000, 0x10000, state); + sis_5591_host_to_pci_log("000F0000-000FFFFF\n"); + + dev->states_bus[i & 0x0f] = val; + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + val = dev->pci_conf[i]; + if ((dev->states[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(base, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + + dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0x0f) | (val & 0xf0); + } + if ((dev->states[i & 0x0f] ^ val) & 0x0a) { + state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(base + 0x4000, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + + dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0xf0) | (val & 0x0f); + } + + if (!(dev->pci_conf[0x76] & 0x08)) + val &= 0x55; + if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(base, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + + dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0x0f) | (val & 0xf0); + } + if ((dev->states_bus[i & 0x0f] ^ val) & 0x0a) { + state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(base + 0x4000, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + + dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0xf0) | (val & 0x0f); + } + } + } + + flushmmucache_nopc(); +} + +static void +sis_5591_smram_recalc(sis_5591_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x68] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +static void +sis_5591_mask_bar(uint8_t *regs, void *agpgart) +{ + uint32_t bar; + uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x00000000 } ; + + /* Make sure the aperture's base is aligned to its size. */ + bar = (regs[0x13] << 24) | (regs[0x12] << 16); + bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000); + regs[0x12] = (bar >> 16) & 0xff; + regs[0x13] = (bar >> 24) & 0xff; + + if (!agpgart) + return; + + /* Map aperture and GART. */ + agpgart_set_aperture(agpgart, + bar, + sizes[(regs[0x94] >> 4) & 0x07], + !!(regs[0x94] & 0x02)); + if (regs[0x94] & 0x01) + agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24)); + else + agpgart_set_gart(agpgart, 0x00000000); +} + +void +sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + sis_5591_host_to_pci_log("SiS 5591 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xf0); + break; + + case 0x12: + dev->pci_conf[addr] = val & 0xc0; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x13: + dev->pci_conf[addr] = val; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0x51: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x80); + cpu_update_waitstates(); + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x68: + dev->pci_conf[addr] = val; + sis_5591_smram_recalc(dev); + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5591_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5591_shadow_recalc(dev); + break; + + case 0x0d: /* Master latency timer */ + case 0x50: + case 0x52: + case 0x54 ... 0x5a: + case 0x5c ... 0x5f: + case 0x64 ... 0x65: + case 0x69 ... 0x6c: + case 0x77 ... 0x7b: + case 0x80 ... 0x8d: + case 0x90: + case 0x97 ... 0xab: + case 0xb0: + case 0xc8 ... 0xcb: + case 0xd4 ... 0xda: + case 0xe0 ... 0xe3: + case 0xef: + dev->pci_conf[addr] = val; + break; + + case 0x91 ... 0x93: + dev->pci_conf[addr] = val; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x94: + dev->pci_conf[addr] = val & 0x7f; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0xb2: + dev->pci_conf[addr] &= ~(val & 0x01); + break; + } +} + +uint8_t +sis_5591_host_to_pci_read(int addr, void *priv) +{ + const sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5591_host_to_pci_log("SiS 5591 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5591_host_to_pci_reset(void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x91; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x02; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00; + dev->pci_conf[0x34] = 0xc0; + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x18; + dev->pci_conf[0x52] = dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = 0x0e; + dev->pci_conf[0x56] = 0x40; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x50; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + 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] = 0xff; + dev->pci_conf[0x86] = 0xff; + dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x8c] = dev->pci_conf[0x8d] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0x00; + dev->pci_conf[0xa0] = dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = dev->pci_conf[0xa3] = 0x00; + dev->pci_conf[0xa4] = dev->pci_conf[0xa5] = 0x00; + dev->pci_conf[0xa6] = dev->pci_conf[0xa7] = 0x00; + dev->pci_conf[0xa8] = dev->pci_conf[0xa9] = 0x00; + dev->pci_conf[0xaa] = dev->pci_conf[0xab] = 0x00; + dev->pci_conf[0xb0] = dev->pci_conf[0xb2] = 0x00; + dev->pci_conf[0xc0] = 0x02; + dev->pci_conf[0xc1] = 0x00; + dev->pci_conf[0xc2] = 0x10; + dev->pci_conf[0xc3] = 0x00; + dev->pci_conf[0xc4] = 0x03; + dev->pci_conf[0xc5] = 0x02; + dev->pci_conf[0xc6] = 0x00; + dev->pci_conf[0xc7] = 0x1f; + dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00; + dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00; + dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00; + dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00; + dev->pci_conf[0xd8] = dev->pci_conf[0xd9] = 0x00; + dev->pci_conf[0xda] = 0x00; + dev->pci_conf[0xe0] = dev->pci_conf[0xe1] = 0x00; + dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00; + dev->pci_conf[0xef] = 0x00; + + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5591_shadow_recalc(dev); + + sis_5591_smram_recalc(dev); +} + +static void +sis_5591_host_to_pci_close(void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5591_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) calloc(1, sizeof(sis_5591_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 5; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + device_add(&sis_5xxx_agp_device); + dev->agpgart = device_add(&agpgart_device); + + sis_5591_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5591_h2p_device = { + .name = "SiS 5591 Host to PCI bridge", + .internal_name = "sis_5591_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5591_host_to_pci_init, + .close = sis_5591_host_to_pci_close, + .reset = sis_5591_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5595_pmu.c b/src/chipset/sis_5595_pmu.c new file mode 100644 index 000000000..de351ad7c --- /dev/null +++ b/src/chipset/sis_5595_pmu.c @@ -0,0 +1,454 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 5572 USB controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5595_PMU_LOG +int sis_5595_pmu_do_log = ENABLE_SIS_5595_PMU_LOG; + +static void +sis_5595_pmu_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5595_pmu_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5595_pmu_log(fmt, ...) +#endif + +typedef struct sis_5595_pmu_io_trap_t { + void *priv; + void *trap; + uint8_t flags, mask; + uint8_t *sts_reg, sts_mask; + uint16_t addr; +} sis_5595_pmu_io_trap_t; + +typedef struct sis_5595_pmu_t { + uint8_t is_1997; + + uint8_t pci_conf[256]; + + sis_5595_pmu_io_trap_t io_traps[22]; + + sis_55xx_common_t *sis; +} sis_5595_pmu_t; + +static void +sis_5595_pmu_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), + void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv; + + trap->sts_reg[0x04] |= trap->sts_mask; + + if (trap->sts_reg[0x00] & trap->sts_mask) + acpi_sis5595_pmu_event(dev->sis->acpi); + + if (trap->sts_reg[0x20] & trap->sts_mask) + acpi_update_irq(dev->sis->acpi); +} + +static void +sis_5595_pmu_trap_io_ide(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + + /* IDE traps are per drive, not per channel. */ + if (ide_drives[trap->flags & 0x03]->selected) + sis_5595_pmu_trap_io(size, addr, write, val, priv); +} + +static void +sis_5595_pmu_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + + if ((addr & trap->mask) == (trap->addr & trap->mask)) + sis_5595_pmu_trap_io(size, addr, write, val, priv); +} + +static void +sis_5595_pmu_trap_io_ide_bm(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv; + + if (trap->flags & 0x01) { + dev->pci_conf[0x67] |= 0x01; + dev->pci_conf[0x64] |= 0x08; + } else { + dev->pci_conf[0x67] |= 0x02; + dev->pci_conf[0x64] |= 0x10; + } + acpi_sis5595_pmu_event(dev->sis->acpi); +} + +static void +sis_5595_pmu_trap_update_devctl(sis_5595_pmu_t *dev, uint8_t trap_id, uint8_t enable, + uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask, + uint16_t addr, uint16_t size) +{ + sis_5595_pmu_io_trap_t *trap = &dev->io_traps[trap_id]; + + /* Set up Device I/O traps dynamically. */ + if (enable && !trap->trap) { + trap->priv = (void *) dev; + trap->flags = flags; + trap->mask = mask; + trap->addr = addr; + if (flags & 0x10) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide_bm, trap); + else if (flags & 0x08) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_mask, trap); + else if (flags & 0x04) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide, trap); + else + trap->trap = io_trap_add(sis_5595_pmu_trap_io, trap); + trap->sts_reg = sts_reg; + trap->sts_mask = sts_mask; + } + + /* Remap I/O trap. */ + io_trap_remap(trap->trap, enable, addr, size); +} + +static void +sis_5595_pmu_trap_update(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + uint8_t trap_id = 0; + uint8_t *fregs = dev->pci_conf; + uint16_t temp; + uint8_t mask; + uint8_t on; + + temp = (fregs[0x7e] | (fregs[0x7f] << 8)) & 0xffe0; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + fregs[0x7e] & 0x08, 0x10, 0xff, NULL, 0xff, temp, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + fregs[0x7e] & 0x04, 0x10, 0xff, NULL, 0xff, temp + 8, 0x08); + + on = fregs[0x63] | fregs[0x83]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x04, 0xff, &(fregs[0x63]), 0x02, 0x1f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x01, 0x06, 0xff, &(fregs[0x63]), 0x01, 0x170, 0x08); + + on = fregs[0x62] | fregs[0x82]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x064, 0x01); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x060, 0x01); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x00, 0xff, &(fregs[0x62]), 0x40, 0x3f8, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x62]), 0x20, 0x2f8, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x378, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x278, 0x08); + + temp = (fregs[0x5c] | (fregs[0x5d] << 8)) & 0x03ff; + mask = fregs[0x5d] >> 2; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x08, mask, &(fregs[0x62]), 0x04, temp, 0x40); + + temp = fregs[0x5e] | (fregs[0x5f] << 8); + + if (dev->is_1997) { + mask = fregs[0x4d] & 0x1f; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x20); + } else { + mask = fregs[0x4d]; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x100); + } + + on = fregs[0x61] | fregs[0x81]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x00, 0xff, &(fregs[0x61]), 0x40, 0x3b0, 0x30); + + switch ((fregs[0x4c] >> 6) & 0x03) { + case 0x00: + temp = 0xf40; + break; + case 0x01: + temp = 0xe80; + break; + case 0x02: + temp = 0x604; + break; + default: + temp = 0x530; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x61]), 0x10, temp, 0x08); + + switch ((fregs[0x4c] >> 4) & 0x03) { + case 0x00: + temp = 0x280; + break; + case 0x01: + temp = 0x260; + break; + case 0x02: + temp = 0x240; + break; + default: + temp = 0x220; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x61]), 0x08, temp, 0x14); + + switch ((fregs[0x4c] >> 2) & 0x03) { + case 0x00: + temp = 0x330; + break; + case 0x01: + temp = 0x320; + break; + case 0x02: + temp = 0x310; + break; + default: + temp = 0x300; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x00, 0xff, &(fregs[0x61]), 0x04, temp, 0x04); + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x200, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x388, 0x04); + + on = fregs[0x60] | fregs[0x80]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x3f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x370, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x05, 0xff, &(fregs[0x60]), 0x10, 0x1f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x07, 0xff, &(fregs[0x60]), 0x08, 0x170, 0x08); +} + +void +sis_5595_pmu_write(int addr, uint8_t val, void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + sis_5595_pmu_log("SiS 5595 PMU: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (dev->sis->usb_enabled) switch (addr) { + default: + break; + + case 0x40 ... 0x4b: + case 0x50 ... 0x5b: + case 0x68 ... 0x7b: + case 0x7d: + dev->pci_conf[addr] = val; + break; + case 0x4c ... 0x4d: + case 0x5c ... 0x63: + case 0x7e ... 0x7f: + case 0x80 ... 0x83: + dev->pci_conf[addr] = val; + sis_5595_pmu_trap_update(dev); + break; + case 0x64 ... 0x67: + dev->pci_conf[addr] &= ~val; + break; + case 0x7c: + dev->pci_conf[addr] = val; + if (val & 0x02) { + dev->pci_conf[0x64] |= 0x04; + if (dev->pci_conf[0x60] & 0x04) + acpi_sis5595_pmu_event(dev->sis->acpi); + } + break; + } +} + +uint8_t +sis_5595_pmu_read(int addr, void *priv) +{ + const sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5595_pmu_log("SiS 5595 PMU: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_pmu_reset(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x09; + dev->pci_conf[0x03] = 0x00; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0xff; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00; + dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00; + dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00; + dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00; + dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00; + dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = dev->pci_conf[0x5b] = 0x00; + dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = dev->pci_conf[0x63] = 0x00; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + 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[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + + sis_5595_pmu_trap_update(dev); + acpi_update_irq(dev->sis->acpi); +} + +static void +sis_5595_pmu_close(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + free(dev); +} + +static void * +sis_5595_pmu_init(UNUSED(const device_t *info)) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) calloc(1, sizeof(sis_5595_pmu_t)); + + dev->sis = device_get_common_priv(); + dev->sis->pmu_regs = dev->pci_conf; + + dev->is_1997 = info->local; + + sis_5595_pmu_reset(dev); + + return dev; +} + +const device_t sis_5595_1997_pmu_device = { + .name = "SiS 5595 (1997) PMU", + .internal_name = "sis_5595_1997_pmu", + .flags = DEVICE_PCI, + .local = 0x01, + .init = sis_5595_pmu_init, + .close = sis_5595_pmu_close, + .reset = sis_5595_pmu_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_pmu_device = { + .name = "SiS 5595 PMU", + .internal_name = "sis_5595_pmu", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5595_pmu_init, + .close = sis_5595_pmu_close, + .reset = sis_5595_pmu_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_55xx.c b/src/chipset/sis_55xx.c new file mode 100644 index 000000000..2cad21f22 --- /dev/null +++ b/src/chipset/sis_55xx.c @@ -0,0 +1,96 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS 55xx common structure. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_55XX_COMMON_LOG +int sis_55xx_common_do_log = ENABLE_SIS_55XX_COMMON_LOG; + +static void +sis_55xx_common_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_55xx_common_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_55xx_common_log(fmt, ...) +#endif + +static void +sis_55xx_common_close(void *priv) +{ + sis_55xx_common_t *dev = (sis_55xx_common_t *) priv; + + free(dev); +} + +static void * +sis_55xx_common_init(UNUSED(const device_t *info)) +{ + sis_55xx_common_t *dev = (sis_55xx_common_t *) calloc(1, sizeof(sis_55xx_common_t)); + + return dev; +} + +const device_t sis_55xx_common_device = { + .name = "SiS 55xx Common Structure", + .internal_name = "sis_55xx_common", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_55xx_common_init, + .close = sis_55xx_common_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5600.c b/src/chipset/sis_5600.c new file mode 100644 index 000000000..ed7384740 --- /dev/null +++ b/src/chipset/sis_5600.c @@ -0,0 +1,210 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS (5)600 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.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/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5600_LOG +int sis_5600_do_log = ENABLE_SIS_5600_LOG; + +static void +sis_5600_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5600_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5600_log(fmt, ...) +#endif + +typedef struct sis_5600_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + void *pmu; + + sis_55xx_common_t *sis; +} sis_5600_t; + +static void +sis_5600_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + + sis_5600_log("SiS 5600: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5600_host_to_pci_write(addr, val, dev->h2p); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); +} + +static uint8_t +sis_5600_read(int func, int addr, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5600_host_to_pci_read(addr, dev->h2p); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); + + sis_5600_log("SiS 5600: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + + sis_5600_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5595_pmu_write(addr, val, dev->pmu); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5595_read(int func, int addr, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5595_pmu_read(addr, dev->pmu); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5600_log("SiS 5602: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5600_close(void *priv) +{ + sis_5600_t *dev = (sis_5600_t *) priv; + + free(dev); +} + +static void * +sis_5600_init(UNUSED(const device_t *info)) +{ + sis_5600_t *dev = (sis_5600_t *) calloc(1, sizeof(sis_5600_t)); + + /* Device 0: SiS 5600 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5600_read, sis_5600_write, dev, &dev->nb_slot); + /* Device 1: SiS 5595 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis); + if (info->local) + dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis); + else + dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5600_h2p_device, dev->sis); + dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis); + if (info->local) + dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis); + else + dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis); + + return dev; +} + +const device_t sis_5600_1997_device = { + .name = "SiS (5)600 (1997)", + .internal_name = "sis_5600_1997", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_5600_init, + .close = sis_5600_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5600_device = { + .name = "SiS (5)600", + .internal_name = "sis_5600", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5600_init, + .close = sis_5600_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c new file mode 100644 index 000000000..f6ee926da --- /dev/null +++ b/src/chipset/sis_5600_h2p.c @@ -0,0 +1,434 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the SiS (5)600 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/dma.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/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5600_HOST_TO_PCI_LOG +int sis_5600_host_to_pci_do_log = ENABLE_SIS_5600_HOST_TO_PCI_LOG; + +static void +sis_5600_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5600_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5600_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5600_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + ram_bank_t ram_banks[3]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + agpgart_t *agpgart; +} sis_5600_host_to_pci_t; + +static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b }; + +static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000, /* 256 MB */ + 0x20000000 }; /* 512 MB */ + +static void +sis_5600_shadow_recalc(sis_5600_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0; i < 8; i++) { + base = 0x000c0000 + (i << 14); + state = (dev->pci_conf[0x70] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x72] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x70] ^ dev->states[0]) & (1 << i)) || + ((dev->pci_conf[0x72] ^ dev->states[2]) & (1 << i))) { + mem_set_mem_state_both(base, 0x4000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + } + + for (uint8_t i = 0; i < 4; i++) { + base = 0x000e0000 + (i << 14); + state = (dev->pci_conf[0x71] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x73] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << i)) || + ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << i))) { + mem_set_mem_state_both(base, 0x4000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + } + + base = 0x000f0000; + state = (dev->pci_conf[0x71] & (1 << 4)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x73] & (1 << 4)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << 4)) || + ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << 4))) { + mem_set_mem_state_both(base, 0x10000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0xffff); + } + + for (uint8_t i = 0; i < 4; i++) + dev->states[i] = dev->pci_conf[0x70 + i]; + + flushmmucache_nopc(); +} + +static void +sis_5600_smram_recalc(sis_5600_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x6a] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x6a] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +static void +sis_5600_mask_bar(uint8_t *regs, void *agpgart) +{ + uint32_t bar; + uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x00000000 } ; + + /* Make sure the aperture's base is aligned to its size. */ + bar = (regs[0x13] << 24) | (regs[0x12] << 16); + bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000); + regs[0x12] = (bar >> 16) & 0xff; + regs[0x13] = (bar >> 24) & 0xff; + + if (!agpgart) + return; + + /* Map aperture and GART. */ + agpgart_set_aperture(agpgart, + bar, + sizes[(regs[0x94] >> 4) & 0x07], + !!(regs[0x94] & 0x02)); + if (regs[0x94] & 0x01) + agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24)); + else + agpgart_set_gart(agpgart, 0x00000000); +} + +void +sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + sis_5600_host_to_pci_log("SiS 5600 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & ~(val & 0x70)) | (val & 0x01); + break; + + case 0x0d: /* Master latency timer */ + case 0x50 ... 0x5a: + case 0x64 ... 0x69: + case 0x6b ... 0x6c: + case 0x74 ... 0x75: + case 0x77 ... 0x80: + case 0x82 ... 0x8f: + case 0x97 ... 0x9b: + case 0xc8 ... 0xcb: + case 0xd4 ... 0xd8: + case 0xda: + case 0xe0: + case 0xe2 ... 0xe3: + dev->pci_conf[addr] = val; + break; + + case 0x12: + dev->pci_conf[addr] = val & 0xc0; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x13: + dev->pci_conf[addr] = val; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x6a: + dev->pci_conf[addr] = val; + sis_5600_smram_recalc(dev); + break; + + case 0x70 ... 0x73: + dev->pci_conf[addr] = val; + sis_5600_shadow_recalc(dev); + break; + + case 0x91 ... 0x93: + dev->pci_conf[addr] = val; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x94: + dev->pci_conf[addr] = val & 0x7f; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + } +} + +uint8_t +sis_5600_host_to_pci_read(int addr, void *priv) +{ + const sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5600_host_to_pci_log("SiS 5600 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5600_host_to_pci_reset(void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x00; + dev->pci_conf[0x03] = 0x56; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x10; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00; + dev->pci_conf[0x34] = 0xc0; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x02; + dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00; + dev->pci_conf[0x80] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff; + dev->pci_conf[0x86] = 0xff; + dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x8d] = 0x62; + dev->pci_conf[0x8e] = dev->pci_conf[0x8f] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0xc0] = 0x02; + dev->pci_conf[0xc1] = 0x00; + dev->pci_conf[0xc2] = 0x10; + dev->pci_conf[0xc3] = 0x00; + dev->pci_conf[0xc4] = 0x03; + dev->pci_conf[0xc5] = 0x02; + dev->pci_conf[0xc6] = 0x00; + dev->pci_conf[0xc7] = 0x1f; + dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00; + dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00; + dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00; + dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00; + dev->pci_conf[0xd8] = dev->pci_conf[0xda] = 0x00; + dev->pci_conf[0xe0] = 0x00; + dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00; + + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); + + sis_5600_shadow_recalc(dev); + + sis_5600_smram_recalc(dev); +} + +static void +sis_5600_host_to_pci_close(void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5600_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) calloc(1, sizeof(sis_5600_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 6; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + device_add(&sis_5xxx_agp_device); + dev->agpgart = device_add(&agpgart_device); + + sis_5600_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5600_h2p_device = { + .name = "SiS (5)600 Host to PCI bridge", + .internal_name = "sis_5600_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5600_host_to_pci_init, + .close = sis_5600_host_to_pci_close, + .reset = sis_5600_host_to_pci_reset, + { .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 4d1db2d9e..3c3d5bd8c 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -123,7 +123,7 @@ sis_85c497_isa_read(uint16_t port, void *priv) const sis_85c496_t *dev = (sis_85c496_t *) priv; uint8_t ret = 0xff; - if (port == 0x23) + if ((port == 0x23) && (dev->cur_reg < 0xc0)) ret = dev->regs[dev->cur_reg]; else if (port == 0x33) ret = 0x3c /*random_generate()*/; @@ -388,8 +388,7 @@ sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) 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)); + cpu_cpurst_on_sr = ((val & 0xa0) == 0x80) && !(dev->pci_conf[0xc6] & 0x08); break; /* 86C497 Specific Registers (80h ~ FFh) */ @@ -480,6 +479,8 @@ sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0xc6: /* 85C497 Post / INIT Configuration */ dev->pci_conf[addr] = val & 0x0f; + cpu_cpurst_on_sr = ((dev->pci_conf[0x67] & 0xa0) == 0x80) && !(val & 0x08); + soft_reset_pci = !!(val & 0x04); break; case 0xc8: case 0xc9: @@ -608,12 +609,18 @@ sis_85c496_reset(void *priv) sis_85c49x_pci_write(0, 0xd0, 0x78, dev); sis_85c49x_pci_write(0, 0xd4, 0x00, dev); + dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0xc6] = 0x00; + ide_pri_disable(); ide_sec_disable(); nvr_bank_set(0, 0, dev->nvr); sis_85c497_isa_reset(dev); + + cpu_cpurst_on_sr = 0; + soft_reset_pci = 0; } static void diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index cf4ff42d7..f80ecf99e 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -174,9 +174,7 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) 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) + if (rel_reg == 0x00) dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0); else dev->regs[rel_reg] = val; diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 7f4aebb7c..137ddb5cf 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -6,15 +6,13 @@ * * This file is part of the 86Box distribution. * - * Implementation of the SiS 85C50x Chipset. + * Implementation of the SiS 85C50x and 550x Chipsets. * + * Authors: Miran Grca, + * Tiseno100, * - * - * Authors: Tiseno100, - * Miran Grca, - * - * Copyright 2020-2021 Tiseno100. - * Copyright 2020-2021 Miran Grca. + * Copyright 2020-2024 Miran Grca. + * Copyright 2020-2024 Tiseno100. */ #include #include @@ -27,16 +25,21 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - #include <86box/apm.h> #include <86box/machine.h> #include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> #include <86box/plat_unused.h> #include <86box/mem.h> +#include <86box/nvr.h> #include <86box/smram.h> #include <86box/pci.h> #include <86box/port_92.h> - +#include <86box/spd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> #include <86box/chipset.h> #ifdef ENABLE_SIS_85C50X_LOG @@ -58,17 +61,23 @@ sis_85c50x_log(const char *fmt, ...) #endif typedef struct sis_85c50x_t { - uint8_t index; - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; + uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t type; - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[256]; - uint8_t regs[256]; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[256]; + uint8_t pci_conf_ide[256]; + uint8_t regs[256]; + uint32_t states[13]; smram_t *smram[2]; port_92_t *port_92; + void *pit; + nvr_t *nvr; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); } sis_85c50x_t; static void @@ -77,23 +86,59 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev) uint32_t base; uint32_t can_read; uint32_t can_write; + uint32_t state; 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; - mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write); - shadowbios = 1; - shadowbios_write = 1; + state = can_read | can_write; + if (dev->states[12] != state) { + mem_set_mem_state_both(0x000f0000, 0x00010000, state); + sis_85c50x_log("F0000-FFFFF: R%c, W%c\n", + (dev->pci_conf[0x53] & 0x40) ? 'I' : 'E', + (dev->pci_conf[0x53] & 0x20) ? 'P' : 'I'); + dev->states[12] = state; + } 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)); + base = 0x000e0000 + (i << 14); + state = (dev->pci_conf[0x54] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[8 + i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x543 & (0x80 >> i)) ? + ((dev->pci_conf[0x54] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x54] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[8 + i] = state; + } + + base = 0x000d0000 + (i << 14); + state = (dev->pci_conf[0x55] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[4 + i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x55] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x55] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[4 + i] = state; + } + + base = 0x000c0000 + (i << 14); + state = (dev->pci_conf[0x56] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x56] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x56] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[i] = state; + } } flushmmucache_nopc(); @@ -117,27 +162,35 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev) break; case 0x01: host_base |= 0x000b0000; - sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, + 0x8000, (dev->pci_conf[0x65] & 0x10), 1); break; default: break; @@ -160,7 +213,10 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06); break; case 0x50: - dev->pci_conf[addr] = val; + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xf7; + else + dev->pci_conf[addr] = val; break; case 0x51: /* Cache */ dev->pci_conf[addr] = val; @@ -176,8 +232,6 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) 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: @@ -204,6 +258,7 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) break; case 0x5b: dev->pci_conf[addr] = val; + kbc_at_set_fast_reset(!!(val & 0x40)); break; case 0x60: /* SMI */ if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) { @@ -223,6 +278,31 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) case 0x69: dev->pci_conf[addr] &= ~val; break; + case 0x70 ... 0x77: + if (dev->type & 1) + spd_write_drbs(dev->pci_conf, 0x70, 0x77, 2); + break; + case 0x78: + case 0x7c ... 0x7e: + if (dev->type & 1) + dev->pci_conf[addr] = val; + break; + case 0x79: + if (dev->type & 1) { + spd_write_drbs(dev->pci_conf, 0xf8, 0xff, 4); + dev->pci_conf[addr] = 0x00; + for (uint8_t i = 0; i < 8; i++) + if (dev->pci_conf[0xf8 + i] & 0x80) dev->pci_conf[addr] |= (1 << i); + } + break; + case 0x7a: + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xfe; + break; + case 0x7b: + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xe0; + break; default: break; @@ -235,14 +315,33 @@ sis_85c50x_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[addr]; + if (func == 0x00) { + if (addr >= 0xf8) + ret = 0x00; + else + ret = dev->pci_conf[addr]; + } sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret); return ret; } +static void +sis_85c50x_ide_recalc(sis_85c50x_t *dev) +{ + ide_pri_disable(); + ide_set_base(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0170 : 0x01f0); + ide_set_side(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0376 : 0x03f6); + ide_pri_enable(); + + ide_sec_disable(); + ide_set_base(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x01f0 : 0x0170); + ide_set_side(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x03f6 : 0x0376); + if (dev->pci_conf_ide[0x41] & 0x01) + ide_sec_enable(); +} + static void sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv) { @@ -250,38 +349,46 @@ sis_85c50x_sb_write(int func, int addr, uint8_t val, void *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; + 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; - } + default: + break; + } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) switch (addr) { + case 0x40: + case 0x41: + dev->pci_conf_ide[addr] = val; + sis_85c50x_ide_recalc(dev); + break; + + default: + break; + } } static uint8_t @@ -290,8 +397,42 @@ 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]; + if (func == 0x00) switch (addr) { + default: + ret = dev->pci_conf_sb[addr]; + break; + case 0x4c ... 0x4f: + if (dev->type & 2) + ret = pic_read_icw(0, addr & 0x03); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x50 ... 0x53: + if (dev->type & 2) + ret = pic_read_icw(1, addr & 0x03); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x54 ... 0x55: + if (dev->type & 2) + ret = pic_read_ocw(0, addr & 0x01); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x56 ... 0x57: + if (dev->type & 2) + ret = pic_read_ocw(1, addr & 0x01); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x58 ... 0x5f: + if (dev->type & 2) + ret = dev->pit_read_reg(dev->pit, addr & 0x07); + else + ret = dev->pci_conf_sb[addr]; + break; + } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) + ret = dev->pci_conf_ide[addr]; sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret); @@ -313,10 +454,39 @@ sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv) case 0x23: switch (dev->index) { case 0x80: - dev->regs[dev->index] = val & 0xe7; + if (dev->type & 2) { + dev->regs[dev->index] = val; + nvr_bank_set(0, !!(val & 0x08), dev->nvr); + } else + dev->regs[dev->index] = val & 0xe7; + 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; + } break; case 0x81: - dev->regs[dev->index] = val & 0xf4; + if (dev->type & 2) + dev->regs[dev->index] = val & 0xf6; + else + dev->regs[dev->index] = val & 0xf4; + break; + case 0x82: + if (dev->type & 2) + dev->regs[dev->index] = val; + break; + case 0x83: + if (dev->type & 2) + dev->regs[dev->index] = val & 0x03; break; case 0x84: case 0x88: @@ -394,6 +564,12 @@ sis_85c50x_reset(void *priv) sis_85c50x_write(0, 0x68, 0x00, dev); sis_85c50x_write(0, 0x69, 0xff, dev); + if (dev->type & 1) { + for (uint8_t i = 0; i < 8; i++) + dev->pci_conf[0x70 + i] = 0x00; + dev->pci_conf[0x79] = 0x00; + } + /* South Bridge (SiS 85C503) */ dev->pci_conf_sb[0x00] = 0x39; dev->pci_conf_sb[0x01] = 0x10; @@ -407,10 +583,51 @@ sis_85c50x_reset(void *priv) dev->pci_conf_sb[0x09] = 0x00; dev->pci_conf_sb[0x0a] = 0x01; dev->pci_conf_sb[0x0b] = 0x06; + if (dev->type & 2) + dev->pci_conf_sb[0x0e] = 0x80; 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); + + if (dev->type & 2) { + /* IDE (SiS 5503) */ + dev->pci_conf_ide[0x00] = 0x39; + dev->pci_conf_ide[0x01] = 0x10; + dev->pci_conf_ide[0x02] = 0x01; + dev->pci_conf_ide[0x03] = 0x06; + dev->pci_conf_ide[0x04] = 0x89; + dev->pci_conf_ide[0x05] = 0x00; + dev->pci_conf_ide[0x06] = 0x00; + dev->pci_conf_ide[0x07] = 0x00; + dev->pci_conf_ide[0x08] = 0x00; + dev->pci_conf_ide[0x09] = 0x00; + dev->pci_conf_ide[0x0a] = 0x01; + dev->pci_conf_ide[0x0b] = 0x01; + dev->pci_conf_ide[0x0c] = 0x00; + dev->pci_conf_ide[0x0d] = 0x00; + dev->pci_conf_ide[0x0e] = 0x80; + dev->pci_conf_ide[0x0f] = 0x00; + dev->pci_conf_ide[0x10] = 0x71; + dev->pci_conf_ide[0x11] = 0x01; + dev->pci_conf_ide[0x14] = 0xf1; + dev->pci_conf_ide[0x15] = 0x01; + dev->pci_conf_ide[0x18] = 0x71; + dev->pci_conf_ide[0x19] = 0x03; + dev->pci_conf_ide[0x1c] = 0xf1; + dev->pci_conf_ide[0x1d] = 0x03; + dev->pci_conf_ide[0x20] = 0x01; + dev->pci_conf_ide[0x24] = 0x01; + dev->pci_conf_ide[0x40] = 0x00; + dev->pci_conf_ide[0x41] = 0x40; + + sis_85c50x_ide_recalc(dev); + } + + cpu_set_isa_speed(7159091); + + if (dev->type & 2) + nvr_bank_set(0, 0, dev->nvr); } static void @@ -426,8 +643,10 @@ sis_85c50x_close(void *priv) static void * sis_85c50x_init(UNUSED(const device_t *info)) { - sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t)); - memset(dev, 0x00, sizeof(sis_85c50x_t)); + sis_85c50x_t *dev = (sis_85c50x_t *) calloc(1, sizeof(sis_85c50x_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); + + dev->type = info->local; /* 501/502 (Northbridge) */ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot); @@ -441,6 +660,17 @@ sis_85c50x_init(UNUSED(const device_t *info)) dev->port_92 = device_add(&port_92_device); + if (dev->type & 2) { + /* 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); + + device_add(&ide_pci_2ch_device); + } + sis_85c50x_reset(dev); return dev; @@ -459,3 +689,45 @@ const device_t sis_85c50x_device = { .force_redraw = NULL, .config = NULL }; + +const device_t sis_550x_85c503_device = { + .name = "SiS 550x", + .internal_name = "sis_550x", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_85c50x_5503_device = { + .name = "SiS 85C50x", + .internal_name = "sis_85c50x", + .flags = DEVICE_PCI, + .local = 2, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_550x_device = { + .name = "SiS 550x", + .internal_name = "sis_550x", + .flags = DEVICE_PCI, + .local = 3, + .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/umc_8886.c b/src/chipset/umc_8886.c index f6a923346..7a049b1cb 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -79,17 +79,14 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> - #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/pic.h> #include <86box/pci.h> - +#include <86box/port_92.h> #include <86box/chipset.h> -#define IDE_BIT 0x01 - #ifdef ENABLE_UMC_8886_LOG int umc_8886_do_log = ENABLE_UMC_8886_LOG; @@ -108,18 +105,6 @@ umc_8886_log(const char *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) - -/* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */ -#define HAS_IDE dev->has_ide - -/* Southbridge Revision */ -#define SB_ID dev->sb_id - typedef struct umc_8886_t { uint8_t max_func; /* Last function number */ uint8_t pci_slot; @@ -128,19 +113,24 @@ typedef struct umc_8886_t { 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 */ + uint16_t sb_id; /* Southbridge Revision */ + uint16_t ide_id; /* IDE Revision */ + + int has_ide; /* Check if Southbridge Revision is F, AF, or BF */ } umc_8886_t; static void -umc_8886_ide_handler(int status) +umc_8886_ide_handler(umc_8886_t *dev) { ide_pri_disable(); ide_sec_disable(); - if (status) { - ide_pri_enable(); - ide_sec_enable(); + if (dev->pci_conf_sb[1][0x04] & 0x01) { + if (dev->pci_conf_sb[1][0x40] & 0x80) + ide_pri_enable(); + + if (dev->pci_conf_sb[1][0x40] & 0x40) + ide_sec_enable(); } } @@ -148,6 +138,7 @@ static void umc_8886_write(int func, int addr, uint8_t val, void *priv) { umc_8886_t *dev = (umc_8886_t *) priv; + int irq_routing; if (func <= dev->max_func) switch (func) { @@ -155,8 +146,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); switch (addr) { - case 0x04: - case 0x05: + case 0x04 ... 0x05: + case 0x0c ... 0x0d: + case 0x40 ... 0x42: + case 0x45: + case 0x50 ... 0x55: + case 0x57: + case 0x70 ... 0x76: + case 0x80 ... 0x82: + case 0x90 ... 0x92: + case 0xa0 ... 0xa1: + case 0xa5 ... 0xa8: dev->pci_conf_sb[func][addr] = val; break; @@ -164,46 +164,31 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); 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 0x43: + dev->pci_conf_sb[func][addr] = val; + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x01) ? (val >> 8) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTA, irq_routing); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x02) ? (val & 0x0f) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTB, irq_routing); + break; case 0x44: dev->pci_conf_sb[func][addr] = val; - pci_set_irq_routing(INTA, IRQRECALCA); - pci_set_irq_routing(INTB, IRQRECALCB); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x04) ? (val >> 8) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTC, irq_routing); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x08) ? (val & 0x0f) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTD, irq_routing); break; - case 0x45: - dev->pci_conf_sb[func][addr] = val; - break; - - case 0x46: + case 0x46: /* Bits 3-0 = 0 = IRQ disabled, 1 = IRQ enabled. */ + case 0x47: /* Bits 3-0 = 0 = IRQ edge-triggered, 1 = IRQ level-triggered. */ /* 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 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; @@ -220,16 +205,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) default: 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 0xa2: @@ -243,7 +218,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) 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; @@ -254,10 +228,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2)); break; - case 0xa5 ... 0xa8: - dev->pci_conf_sb[func][addr] = val; - break; - default: break; } @@ -269,7 +239,8 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x04: dev->pci_conf_sb[func][addr] = val; - umc_8886_ide_handler(val & 1); + if (dev->ide_id == 0x673a) + umc_8886_ide_handler(dev); break; case 0x07: @@ -277,9 +248,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x3c: + case 0x41 ... 0x4b: + case 0x54 ... 0x59: + if (dev->ide_id == 0x673a) + dev->pci_conf_sb[func][addr] = val; + break; + case 0x40: - case 0x41: - dev->pci_conf_sb[func][addr] = val; + if (dev->ide_id == 0x673a) { + dev->pci_conf_sb[func][addr] = val; + umc_8886_ide_handler(dev); + } break; default: @@ -311,47 +290,73 @@ umc_8886_reset(void *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][1] = 0x10; - - 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; - dev->pci_conf_sb[0][7] = 2; - - dev->pci_conf_sb[0][8] = 0x0e; - + dev->pci_conf_sb[0][0x00] = 0x60; /* UMC */ + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = (dev->sb_id & 0xff); /* 8886xx */ + dev->pci_conf_sb[0][0x03] = ((dev->sb_id >> 8) & 0xff); + dev->pci_conf_sb[0][0x04] = 0x0f; + dev->pci_conf_sb[0][0x07] = 0x02; + dev->pci_conf_sb[0][0x08] = 0x0e; 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][0x40] = 1; - dev->pci_conf_sb[0][0x41] = 6; - dev->pci_conf_sb[0][0x42] = 8; - dev->pci_conf_sb[0][0x43] = 0x9a; - dev->pci_conf_sb[0][0x44] = 0xbc; - dev->pci_conf_sb[0][0x45] = 4; + dev->pci_conf_sb[0][0x40] = 0x01; + dev->pci_conf_sb[0][0x41] = 0x06; + dev->pci_conf_sb[0][0x42] = 0x08; + dev->pci_conf_sb[0][0x43] = 0x00; + dev->pci_conf_sb[0][0x44] = 0x00; + dev->pci_conf_sb[0][0x45] = 0x04; + dev->pci_conf_sb[0][0x46] = 0x00; dev->pci_conf_sb[0][0x47] = 0x40; - dev->pci_conf_sb[0][0x50] = 1; - dev->pci_conf_sb[0][0x51] = 3; + dev->pci_conf_sb[0][0x50] = 0x01; + dev->pci_conf_sb[0][0x51] = 0x03; + dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00; + dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00; + dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00; + dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00; + dev->pci_conf_sb[0][0x82] = 0x00; + dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00; + dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00; + dev->pci_conf_sb[0][0xa4] = 0x00; 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; + if (dev->has_ide) { + dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */ + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = (dev->ide_id & 0xff); /* 8886xx IDE */ + dev->pci_conf_sb[1][0x03] = ((dev->ide_id >> 8) & 0xff); + dev->pci_conf_sb[1][0x04] = 0x05; /* Start with Internal IDE Enabled */ + dev->pci_conf_sb[1][0x08] = 0x10; + dev->pci_conf_sb[1][0x09] = 0x8f; + dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; + 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] = 0x10; - dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */ - dev->pci_conf_sb[1][3] = 0x67; + if (dev->ide_id == 0x673a) { + dev->pci_conf_sb[1][0x40] = 0xc0; + dev->pci_conf_sb[1][0x41] = 0x00; + dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; + dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; + dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; + dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; + dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00; + dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00; + dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00; - dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */ + umc_8886_ide_handler(dev); - 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; - - umc_8886_ide_handler(1); + picintc(1 << 14); + picintc(1 << 15); + } } for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */ @@ -375,17 +380,28 @@ umc_8886_init(const device_t *info) 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, &dev->pci_slot); /* Device 12: UMC 8886xx */ - - /* Add IDE if UM8886AF variant */ - if (HAS_IDE) - device_add(&ide_pci_2ch_device); - - dev->max_func = (HAS_IDE) ? 1 : 0; + /* Device 12: UMC 8886xx */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Get the Southbridge Revision */ - SB_ID = info->local; + dev->sb_id = info->local & 0xffff; + + /* IDE Revision */ + dev->ide_id = info->local >> 16; + + dev->has_ide = (dev->ide_id != 0x0000); + + dev->max_func = 0; + + /* Add IDE if this is the UM8886AF or UM8886BF. */ + if (dev->ide_id == 0x673a) { + /* UM8886BF */ + device_add(&ide_pci_2ch_device); + dev->max_func = 1; + } else if (dev->ide_id == 0x1001) { + /* UM8886AF */ + device_add(&ide_um8673f_device); + } umc_8886_reset(dev); @@ -396,7 +412,7 @@ const device_t umc_8886f_device = { .name = "UMC 8886F", .internal_name = "umc_8886f", .flags = DEVICE_PCI, - .local = 0x8886, + .local = 0x00008886, .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, @@ -407,10 +423,24 @@ const device_t umc_8886f_device = { }; const device_t umc_8886af_device = { - .name = "UMC 8886AF/8886BF", + .name = "UMC 8886AF", .internal_name = "umc_8886af", .flags = DEVICE_PCI, - .local = 0x886a, + .local = 0x1001886a, + .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_8886bf_device = { + .name = "UMC 8886BF", + .internal_name = "umc_8886bf", + .flags = DEVICE_PCI, + .local = 0x673a888a, .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c new file mode 100644 index 000000000..7de2ca1d0 --- /dev/null +++ b/src/chipset/umc_8890.c @@ -0,0 +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. + * + * This file is part of the 86Box distribution. + * + * Implementation of the UMC 8890 Chipset. + * + * 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-2024 Miran Grca. + */ + +#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/apm.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/smram.h> + +#include <86box/chipset.h> + +#ifdef ENABLE_UMC_8890_LOG +int umc_8890_do_log = ENABLE_UMC_8890_LOG; + +static void +umc_8890_log(const char *fmt, ...) +{ + va_list ap; + + if (umc_8890_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define umc_8890_log(fmt, ...) +#endif + +typedef struct umc_8890_t { + uint8_t pci_slot; + + uint8_t pci_conf[256]; /* PCI Registers */ + + int mem_state[2]; + + uint32_t smram_base; + + smram_t *smram; /* SMRAM Handler */ +} umc_8890_t; + +static void +um8890_shadow(umc_8890_t *dev) +{ + uint8_t flag; + uint16_t state; + + flag = (dev->pci_conf[0x5f] & 0x0c) >> 2; + state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0x0c) { + mem_set_mem_state_both(0xe0000, 0x10000, state); + dev->mem_state[1] = (dev->mem_state[1] & 0xf0) | (dev->pci_conf[0x5f] & 0x0f); + } + + flag = (dev->pci_conf[0x5f] & 0xc0) >> 6; + state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0xc0) { + mem_set_mem_state_both(0xf0000, 0x10000, state); + dev->mem_state[1] = (dev->mem_state[1] & 0x0f) | (dev->pci_conf[0x5f] & 0xf0); + } + + for (uint8_t i = 0; i < 8; i++) { + state = (dev->pci_conf[0x5d] & (1 << i)) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[0] ^ dev->pci_conf[0x5d]) & (1 << i)) { + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, state); + dev->mem_state[0] = (dev->mem_state[0] & ~(1 << i)) | (dev->pci_conf[0x5d] & (1 << i)); + } + } + + flushmmucache_nopc(); +} + + +static void +um8890_smram(umc_8890_t *dev) +{ + smram_disable_all(); + + /* Bit 4, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled + in SMM, and is always set to A0000-BFFFF. */ + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x65] & 0x10, 1); +} + +static void +um8890_write(int func, int addr, uint8_t val, void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + if (func == 0) switch (addr) { + case 0x04 ... 0x05: + case 0x0c ... 0x0d: + case 0x40 ... 0x5b: + case 0x60 ... 0x63: + case 0x66 ... 0xff: + dev->pci_conf[addr] = val; + break; + + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf9); + break; + + case 0x5c ... 0x5f: + dev->pci_conf[addr] = val; + um8890_shadow(dev); + break; + + /* Register 64h, 16-bit: + Bit 12: SMRAM enabled outside SMM (1 = yes, 0 = no); + Bit 10: ???? (set by Award BIOS); + Bits 7- 0: SMM handler offset to SMBASE, shifted to the right by 14. + */ + case 0x64: case 0x65: + dev->pci_conf[addr] = val; + if (addr == 0x65) + um8890_smram(dev); + break; + } + + umc_8890_log("UM8890: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80)); +} + + +static uint8_t +um8890_read(int func, int addr, void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + uint8_t ret = 0xff; + + if (func == 0) + ret = dev->pci_conf[addr]; + + return ret; +} + +static void +umc_8890_reset(void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); + + /* Defaults */ + dev->pci_conf[0x00] = 0x60; /* UMC */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x91; /* 8891F */ + dev->pci_conf[0x03] = 0x88; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x01; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x5c] = 0x00; + dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = 0x00; + dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x00; + + um8890_shadow(dev); + + um8890_smram(dev); +} + + +static void +umc_8890_close(void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + smram_del(dev->smram); + free(dev); +} + + +static void * +umc_8890_init(const device_t *info) +{ + umc_8890_t *dev = (umc_8890_t *) calloc(1, sizeof(umc_8890_t)); + + /* Device 0: UMC 8890 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev, &dev->pci_slot); + + /* Port 92 */ + device_add(&port_92_pci_device); + + dev->smram = smram_add(); + + umc_8890_reset(dev); + + return dev; +} + +const device_t umc_8890_device = { + .name = "UMC 8890(8891BF/8892BF)", + .internal_name = "umc_8890", + .flags = DEVICE_PCI, + .local = 0x886a, + .init = umc_8890_init, + .close = umc_8890_close, + .reset = umc_8890_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 d5cce0fca..a7ed0b880 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -14,13 +14,11 @@ * Note 2: Additional information were also used from all * around the web. * - * - * * Authors: Tiseno100, * Miran Grca, * * Copyright 2021 Tiseno100. - * Copyright 2021 Miran Grca. + * Copyright 2021-2024 Miran Grca. */ /* @@ -75,15 +73,24 @@ Bit 3: CC000-CFFFF Read Enable Bit 2: C8000-CBFFF Read Enable Bit 1: C0000-C7FFF Read Enable - Bit 0: Enable C0000-DFFFF Shadow Segment Bits + Bit 0: E0000-EFFFF Read Enable Register 55: - Bit 7: E0000-FFFF Read Enable + Bit 7: F0000-FFFF Read Enable Bit 6: Shadow Write Status (1: Write Protect/0: Write) Register 56h & 57h: DRAM Bank 0 Configuration Register 58h & 59h: DRAM Bank 1 Configuration + Register 5A: + Bit 2: Detrubo + + Register 5C: + Bits 7-0: SMRAM base A27-A20 + + Register 5D: + Bits 3-0: SMRAM base A31-A28 + 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 @@ -129,14 +136,15 @@ hb4_log(const char *fmt, ...) #endif typedef struct hb4_t { - uint8_t shadow; - uint8_t shadow_read; - uint8_t shadow_write; uint8_t pci_slot; uint8_t pci_conf[256]; /* PCI Registers */ + int mem_state[9]; - smram_t *smram[3]; /* SMRAM Handlers */ + + uint32_t smram_base; + + smram_t *smram; /* SMRAM Handler */ } hb4_t; static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY), @@ -167,7 +175,8 @@ hb4_shadow_bios_low(hb4_t *dev) { int state; - state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)]; + /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */ + state = shadow_bios[dev->pci_conf[0x55] >> 6]; if (state != dev->mem_state[7]) { mem_set_mem_state_both(0xe0000, 0x10000, state); @@ -185,7 +194,8 @@ hb4_shadow_main(hb4_t *dev) int n = 0; 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]; + state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] | + shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[i + 1]) { n++; @@ -202,7 +212,8 @@ 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->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); @@ -232,22 +243,26 @@ static void hb4_smram(hb4_t *dev) { smram_disable_all(); + if (dev->smram_base != 0x00000000) + umc_smram_recalc(dev->smram_base >> 12, 0); + + dev->smram_base = ((uint32_t) dev->pci_conf[0x5c]) << 20; + dev->smram_base |= ((uint32_t) (dev->pci_conf[0x5d] & 0x0f)) << 28; + dev->smram_base |= 0x000a0000; /* Bit 0, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled in SMM, and is always set to A0000-BFFFF. */ - smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); - /* There's a mirror of the SMRAM at 0E0A0000, mapped to A0000. */ - smram_enable(dev->smram[1], 0x0e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); - /* There's another mirror of the SMRAM at 4E0A0000, mapped to A0000. */ - smram_enable(dev->smram[2], 0x4e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); + smram_enable(dev->smram, dev->smram_base, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); /* 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); + mem_set_mem_state_smram_ex(0, dev->smram_base, 0x20000, 0x02); + mem_set_mem_state_smram_ex(1, dev->smram_base, 0x20000, 0x02); } + + umc_smram_recalc(dev->smram_base >> 12, 1); } static void @@ -278,38 +293,27 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) cpu_update_waitstates(); break; - case 0x51: - case 0x52: + case 0x51 ... 0x53: dev->pci_conf[addr] = 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; + case 0x54 ... 0x55: dev->pci_conf[addr] = val; hb4_shadow(dev); break; - case 0x56 ... 0x5f: + case 0x56 ... 0x5b: + case 0x5e ... 0x5f: dev->pci_conf[addr] = val; break; + case 0x5c ... 0x5d: case 0x60: dev->pci_conf[addr] = val; hb4_smram(dev); break; - case 0x61: + case 0x61 ... 0x62: dev->pci_conf[addr] = val; break; @@ -336,30 +340,35 @@ hb4_reset(void *priv) hb4_t *dev = (hb4_t *) priv; memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); - dev->pci_conf[0] = 0x60; /* UMC */ - dev->pci_conf[1] = 0x10; - - dev->pci_conf[2] = 0x81; /* 8881x */ - dev->pci_conf[3] = 0x88; - - dev->pci_conf[7] = 2; - - dev->pci_conf[8] = 4; - + dev->pci_conf[0x00] = 0x60; /* UMC */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x81; /* 8881x */ + dev->pci_conf[0x03] = 0x88; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x04; dev->pci_conf[0x09] = 0x00; dev->pci_conf[0x0a] = 0x00; dev->pci_conf[0x0b] = 0x06; - - dev->pci_conf[0x51] = 1; - dev->pci_conf[0x52] = 1; - dev->pci_conf[0x5a] = 4; - dev->pci_conf[0x5c] = 0xc0; + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x01; + dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = 0x00; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x04; + dev->pci_conf[0x5c] = 0x00; dev->pci_conf[0x5d] = 0x20; dev->pci_conf[0x5f] = 0xff; + dev->pci_conf[0x60] = 0x00; + dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; - hb4_write(0, 0x54, 0x00, dev); - hb4_write(0, 0x55, 0x00, dev); - hb4_write(0, 0x60, 0x80, dev); + hb4_shadow(dev); + hb4_smram(dev); cpu_cache_ext_enabled = 0; cpu_update_waitstates(); @@ -372,6 +381,7 @@ hb4_close(void *priv) { hb4_t *dev = (hb4_t *) priv; + smram_del(dev->smram); free(dev); } @@ -387,10 +397,9 @@ hb4_init(UNUSED(const device_t *info)) device_add(&port_92_pci_device); /* SMRAM */ - dev->smram[0] = smram_add(); - dev->smram[1] = smram_add(); - dev->smram[2] = smram_add(); + dev->smram = smram_add(); + dev->smram_base = 0x000a0000; hb4_reset(dev); return dev; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index ae4b30228..df8558b05 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -8,14 +8,10 @@ * * 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. + * Authors: Miran Grca, * + * Copyright 2024 Miran Grca. * - * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 */ #include #include @@ -37,112 +33,513 @@ #include <86box/hdc_ide.h> #include <86box/lpt.h> #include <86box/mem.h> -#include <86box/plat_unused.h> +#include <86box/nvr.h> #include <86box/port_92.h> #include <86box/serial.h> +#include <86box/plat_fallthrough.h> #include <86box/chipset.h> /* Lock/Unlock Procedures */ -#define LOCK dev->lock -#define UNLOCKED !dev->lock +#define LOCK dev->locked +#define UNLOCKED !dev->locked + +#define WD76C10_ADDR_INVALID 0x80000000 #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 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; +typedef struct { + uint32_t enable; + uint32_t virt_addr, phys_addr; + uint32_t virt_size, phys_size; +} ram_bank_t; - int lock; +typedef struct { + uint8_t enabled; - fdc_t *fdc_controller; - mem_mapping_t *mem_mapping; - serial_t *uart[2]; + uint32_t virt, phys; + uint32_t size; +} ems_page_t; + +typedef struct +{ + uint8_t ep, p92; + + uint8_t vbios_states[4]; + uint8_t bios_states[8]; + uint8_t high_bios_states[8]; + uint8_t mem_pages[1024]; + uint8_t ram_state[4192]; + + uint16_t toggle, cpuclk, fpu_ctl, mem_ctl, + split_sa, sh_wp, hmwpb, npmdmt, + ems_ctl, ems_pp, ser_par_cs, rtc_disk_cs, + prog_cs, pmc_in; + + union + { + uint16_t bank_base_regs[2]; + uint8_t bank_bases[4]; + }; + + uint16_t ems_page_regs[40]; + + int locked; + + uint32_t mem_top, hmwp_base; + + ram_bank_t ram_banks[5]; + + ems_page_t ems_pages[40]; + + mem_mapping_t ram_mapping; + + nvr_t *nvr; + + fdc_t *fdc; + serial_t *uart[2]; } wd76c10_t; -static void -wd76c10_refresh_control(wd76c10_t *dev) +static uint32_t bank_sizes[4] = { 0x00020000, /* 64 Kbit X 16 = 1024 Kbit = 128 kB, 8x 8 */ + 0x00080000, /* 256 Kbit X 16 = 4096 Kbit = 512 kB, 9x 9 */ + 0x00200000, /* 1 Mbit X 16 = 16 Mbit = 2 MB, 10x10 */ + 0x00800000 }; /* 4 Mbit X 16 = 64 Mbit = 8 MB, 11x11 */ + +static uint32_t +wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr) +{ + uint32_t ret; + uint8_t ems_page; + uint8_t ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + ems_page_t *ep; + uint8_t en_res = (uint8_t) ((dev->ems_ctl >> 7) & 0x01); + uint32_t low_boundary = (((uint32_t) (dev->ems_ctl & 0x007f)) << 17) + 131072; + ram_bank_t *rb = &(dev->ram_banks[4]); + + addr &= 0x00ffffff; + ems_page = dev->mem_pages[addr >> 14]; + + ep = &dev->ems_pages[ems_page]; + + ret = addr; + + /* First, do any address translation (EMS, low boundary filtering). */ + if ((ems_page < 0x20) && (ems_en == 0x03)) + /* Low EMS pages. */ + ret = addr - ep->virt + ep->phys; + else if ((ems_page >= 0x20) && (ems_page < 0x2a) && (ems_en >= 0x02) && ep->enabled) + /* High EMS pages. */ + ret = addr - ep->virt + ep->phys; + else if (en_res && (addr >= low_boundary)) + /* EMS low boundary. */ + ret = WD76C10_ADDR_INVALID; + + /* Then, do the split. */ + if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) + ret = ret - rb->virt_addr + rb->phys_addr; + + /* Then, disable the required amount of on-board memory between 128k and 640k if so requested. */ + if ((ret >= dev->mem_top) && (ret < 0x000a0000)) + ret = WD76C10_ADDR_INVALID; + + /* Then, handle the physical memory banks. */ + if (ret >= (mem_size << 10)) + /* The physical memory address is too high or disabled, which is invalid. */ + ret = WD76C10_ADDR_INVALID; + /* Otherwise, map it to the correct bank so the BIOS can auto-size it correctly. */ + else for (uint8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) { + if (rb->phys_size == 0x00000000) + ret = WD76C10_ADDR_INVALID; + else + ret = ((ret - rb->virt_addr) % rb->phys_size) + rb->phys_addr; + break; + } + } + + return ret; +} + +static uint8_t +wd76c10_read_ram(uint32_t addr, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + uint8_t ret = 0xff; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + ret = mem_read_ram(addr, priv); + + return ret; +} + +static uint16_t +wd76c10_read_ramw(uint32_t addr, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + uint16_t ret = 0xffff; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + ret = mem_read_ramw(addr, priv); + + return ret; +} + +static void +wd76c10_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + mem_write_ram(addr, val, priv); +} + +static void +wd76c10_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + mem_write_ramw(addr, val, priv); +} + +static void +wd76c10_set_mem_state(wd76c10_t *dev, uint32_t base, uint32_t size, uint32_t access, uint8_t present) +{ + mem_set_mem_state_both(base, size, access); + + for (uint32_t i = base; i < (base + size); i += 4096) + dev->ram_state[i >> 12] = present; +} + +static void +wd76c10_recalc_exec(wd76c10_t *dev, uint32_t base, uint32_t size) +{ + uint32_t logical_addr = wd76c10_calc_addr(dev, base); + void *exec; + + if (logical_addr != WD76C10_ADDR_INVALID) + exec = &(ram[logical_addr]); + else + exec = NULL; + + for (uint32_t i = base; i < (base + size); i += 4096) + if (dev->ram_state[i >> 12]) + _mem_exec[i >> 12] = exec; + + if (cpu_use_exec) + flushmmucache_nopc(); +} + +static void +wd76c10_banks_recalc(wd76c10_t *dev) +{ + for (uint8_t i = 0; i < 4; i++) { + ram_bank_t *rb = &(dev->ram_banks[i]); + uint8_t bit = i << 1; + rb->virt_size = bank_sizes[(dev->mem_ctl >> bit) & 0x03]; + bit = i + 12; + rb->enable = (dev->split_sa >> bit) & 0x01; + rb->virt_addr = ((uint32_t) dev->bank_bases[i]) << 17; + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size); + } +} + +static void +wd76c10_split_recalc(wd76c10_t *dev) +{ + uint32_t sp_size = (dev->split_sa >> 8) & 0x03; + uint32_t split_size = ((sp_size - 1) * 65536); + ram_bank_t *rb = &(dev->ram_banks[4]); + + if (rb->enable && (rb->virt_size != 0x00000000)) { + wd76c10_set_mem_state(dev, rb->virt_addr, rb->virt_size, MEM_READ_EXTANY | MEM_WRITE_EXTANY, 0); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size); + } + rb->virt_addr = ((uint32_t) ((dev->split_sa >> 2) & 0x3f)) << 19; + switch (sp_size) { + case 0x00: + rb->virt_size = 0x00000000; + break; + default: + rb->virt_size = 256 * 1024 + split_size; + break; + } + rb->enable = !!sp_size; + if (rb->enable && (rb->virt_size != 0x00000000)) { + wd76c10_set_mem_state(dev, rb->virt_addr, rb->virt_size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL, 1); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size); + } +} + +static void +wd76c10_dis_mem_recalc(wd76c10_t *dev) +{ + uint8_t dis_mem = (uint8_t) ((dev->sh_wp >> 14) & 0x03); + uint32_t mem_top; + + switch (dis_mem) { + case 0x00: + default: + mem_top = 640 * 1024; + break; + case 0x01: + mem_top = 512 * 1024; + break; + case 0x02: + mem_top = 256 * 1024; + break; + case 0x03: + mem_top = 128 * 1024; + break; + } + + dev->mem_top = mem_top; + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, 128 * 1024, (640 - 128) * 1024); +} + +static void +wd76c10_shadow_ram_do_recalc(wd76c10_t *dev, uint8_t *new_st, uint8_t *old_st, uint8_t min, uint8_t max, uint32_t addr) +{ + uint32_t base = 0x00000000; + int flags = 0; + + for (uint8_t i = min; i < max; i++) { + if (new_st[i] != old_st[i]) { + old_st[i] = new_st[i]; + base = addr + ((uint32_t) i) * 0x00004000; + flags = (new_st[i] & 0x01) ? MEM_READ_INTERNAL : + ((new_st[i] & 0x04) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL); + flags |= (new_st[i] & 0x02) ? MEM_WRITE_INTERNAL : + ((new_st[i] & 0x04) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL); + wd76c10_set_mem_state(dev, base, 0x00004000, flags, new_st[i] & 0x01); + if (cpu_use_exec) + wd76c10_recalc_exec(dev, base, 0x000040000); + } + } +} + + +static void +wd76c10_shadow_ram_recalc(wd76c10_t *dev) +{ + uint8_t vbios_states[4] = { 0 }; + uint8_t bios_states[8] = { 0 }; + uint8_t high_bios_states[8] = { 0 }; + uint8_t wp = (uint8_t) ((dev->sh_wp >> 12) & 0x01); + uint8_t shd = (uint8_t) ((dev->sh_wp >> 8) & 0x03); + uint8_t x_mem = (uint8_t) ((dev->sh_wp >> 7) & 0x01); + uint8_t vb_siz = (uint8_t) ((dev->sh_wp >> 4) & 0x03); + uint8_t vb_top = vb_siz + 1; + uint8_t rom_typ = (uint8_t) ((dev->sh_wp >> 2) & 0x03); + + switch (shd) { + case 0x03: + for (uint8_t i = 0; i < vb_top; i++) { + vbios_states[i] |= 0x01; /* Read. */ + if (!wp) + vbios_states[i] |= 0x02; /* Write. */ + } + if (x_mem) { + for (uint8_t i = 2; i < 4; i++) + bios_states[i] |= 0x03; /* Read/write. */ + } + fallthrough; + case 0x01: + for (uint8_t i = 4; i < 8; i++) { + bios_states[i] |= 0x01; /* Read. */ + if (!wp) + bios_states[i] |= 0x02; /* Write. */ + } + break; + case 0x02: + for (uint8_t i = 0; i < 8; i++) { + bios_states[i] |= 0x01; /* Read. */ + if (!wp) + bios_states[i] |= 0x02; /* Write. */ + } + break; + } + + switch (rom_typ) { + case 0x00: + for (uint8_t i = 0; i < 8; i++) { + bios_states[i] |= 0x04; /* CSPROM#. */ + high_bios_states[i] |= 0x04; /* CSPROM#. */ + } + break; + case 0x02: + for (uint8_t i = 0; i < vb_top; i++) + vbios_states[i] |= 0x04; /* CSPROM#. */ + fallthrough; + case 0x01: + for (uint8_t i = 4; i < 8; i++) { + bios_states[i] |= 0x04; /* CSPROM#. */ + high_bios_states[i] |= 0x04; /* CSPROM#. */ + } + break; + } + + wd76c10_shadow_ram_do_recalc(dev, vbios_states, dev->vbios_states, 0, 4, 0x000c0000); + wd76c10_shadow_ram_do_recalc(dev, bios_states, dev->bios_states, 0, 8, 0x000e0000); + + /* This is not shadowed, but there is a CSPROM# (= ROMCS#) toggle. */ + wd76c10_shadow_ram_do_recalc(dev, high_bios_states, dev->high_bios_states, 0, 8, 0x00fe0000); + + flushmmucache_nopc(); +} + +static void +wd76c10_high_mem_wp_recalc(wd76c10_t *dev) +{ + uint8_t hm_wp = (uint8_t) ((dev->sh_wp >> 13) & 0x01); + uint32_t base = ((uint32_t) (dev->hmwpb & 0x00f0)) << 17; + uint32_t size = 0x01000000 - dev->hmwp_base; + + /* ACCESS_NORMAL means both ACCESS_BUS and ACCESS_CPU are set. */ + mem_set_wp(dev->hmwp_base, size, ACCESS_NORMAL, 0); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, dev->hmwp_base, size); + + size = 0x01000000 - base; + mem_set_wp(base, size, ACCESS_NORMAL, hm_wp); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, base, size); + + dev->hmwp_base = base; +} + +static void +wd76c10_pf_loc_reset(wd76c10_t *dev) +{ + uint32_t base; + + for (uint8_t i = 0x031; i <= 0x03b; i++) { + dev->mem_pages[i] = 0xff; + base = ((uint32_t) i) << 14; + wd76c10_set_mem_state(dev, base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY, 0); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, base, 0x00004000); + } + + /* Re-apply any ROMCS#, etc. flags. */ + wd76c10_shadow_ram_recalc(dev); +} + +static void +wd76c10_pf_loc_recalc(wd76c10_t *dev) +{ + uint8_t pf_loc = (uint8_t) ((dev->ems_ctl >> 13) & 0x03); + uint8_t ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + uint8_t ems_page; + uint32_t base; + + for (uint8_t i = (0x031 + pf_loc); i <= (0x037 + pf_loc); i++) { + ems_page = (i - 0x10) & 0xf7; + dev->mem_pages[i] = ems_page; + base = ((uint32_t) i) << 14; + dev->ems_pages[ems_page].virt = base; + if ((ems_en >= 0x02) && dev->ems_pages[ems_page].enabled) { + wd76c10_set_mem_state(dev, dev->ems_pages[ems_page].virt, + 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL, 1); + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, dev->ems_pages[ems_page].virt, 0x00004000); + } + } +} + +static void +wd76c10_low_pages_recalc(wd76c10_t *dev) +{ + uint8_t ems_page; + uint32_t base; + + for (uint8_t i = 0x008; i <= 0x027; i++) { + ems_page = i & 0x1f; + dev->mem_pages[i] = ems_page; + base = ((uint32_t) i) << 14; + dev->ems_pages[ems_page].virt = base; + + if (cpu_use_exec) + wd76c10_recalc_exec(dev, dev->ems_pages[ems_page].virt, 0x00004000); + } +} + +static void +wd76c10_ser_par_cs_recalc(wd76c10_t *dev) { - serial_remove(dev->uart[1]); /* Serial B */ - switch ((dev->refresh_control >> 1) & 7) { - case 1: + serial_remove(dev->uart[1]); + switch ((dev->ser_par_cs >> 1) & 0x07) { + case 0x01: serial_setup(dev->uart[1], 0x3f8, 3); break; - case 2: + case 0x02: serial_setup(dev->uart[1], 0x2f8, 3); break; - case 3: + case 0x03: serial_setup(dev->uart[1], 0x3e8, 3); break; - case 4: + case 0x04: 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_remove(dev->uart[0]); + switch ((dev->ser_par_cs >> 5) & 0x07) { + case 0x01: serial_setup(dev->uart[0], 0x3f8, 4); break; - case 2: + case 0x02: serial_setup(dev->uart[0], 0x2f8, 4); break; - case 3: + case 0x03: serial_setup(dev->uart[0], 0x3e8, 4); break; - case 4: + case 0x04: serial_setup(dev->uart[0], 0x2e8, 4); break; - default: - break; } - lpt1_remove(); /* LPT */ - switch ((dev->refresh_control >> 9) & 3) { + lpt1_remove(); + switch ((dev->ser_par_cs >> 9) & 0x03) { case 1: lpt1_init(0x3bc); lpt1_irq(7); @@ -155,413 +552,465 @@ wd76c10_refresh_control(wd76c10_t *dev) lpt1_init(0x278); lpt1_irq(7); break; - - default: - break; } } 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; - default: - break; - } -} - -static void -wd76c10_disk_chip_select(wd76c10_t *dev) +wd76c10_disk_cs_recalc(wd76c10_t *dev) { ide_pri_disable(); - 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); - } - ide_pri_enable(); + ide_set_base(0, (dev->rtc_disk_cs & 0x0010) ? 0x0170 : 0x01f0); + ide_set_side(0, (dev->rtc_disk_cs & 0x0010) ? 0x0376 : 0x03f6); + if (!(dev->rtc_disk_cs & 0x0002)) + ide_pri_enable(); - fdc_remove(dev->fdc_controller); - if (!(dev->disk_chip_select & 2)) - fdc_set_base(dev->fdc_controller, !(dev->disk_chip_select & 0x0010) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); + fdc_remove(dev->fdc); + if (!(dev->rtc_disk_cs & 0x0001)) + fdc_set_base(dev->fdc, (dev->rtc_disk_cs & 0x0010) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } static void -wd76c10_shadow_recalc(wd76c10_t *dev) +wd76c10_outb(uint16_t port, uint8_t val, void *priv) { - 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; - } + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t lk_psw = (uint8_t) ((dev->rtc_disk_cs >> 2) & 0x01); + uint8_t valxor; - 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: + switch (port) { + case 0x0092: + if ((lk_psw && (val & 0x08)) || ((dev->p92 & 0x08) && !(val & 0x08))) + val = (val & 0xf7) | (dev->p92 & 0x08); + + valxor = (dev->p92 ^ val) & 0x08; + dev->p92 = (val & 0x08) | 0xf7; + + if (valxor) + nvr_lock_set(0x38, 0x08, (val & 0x08) ? 0x03 : 0x00, dev->nvr); break; } } static void -wd76c10_write(uint16_t addr, uint16_t val, void *priv) +wd76c10_outw(uint16_t port, uint16_t val, void *priv) { - wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t inc = (uint8_t) ((dev->ems_ctl >> 15) & 0x01); + uint8_t ems_en; - if (UNLOCKED) { - switch (addr) { - case 0x1072: - dev->clk_control = val; - break; + if (!dev->locked || (port < 0x1072) || (port > 0xf872) || + (port == 0xe072) || (port == 0xe872) || (port == 0xf073)) switch (port) { + case 0x1072: + dev->cpuclk = val; + break; - case 0x1872: - dev->bus_timing_power_down_ctl = val; - break; + case 0x1872: + dev->fpu_ctl = val; + break; - case 0x2072: - dev->refresh_control = val; - wd76c10_refresh_control(dev); - break; + case 0x2072: + dev->ser_par_cs = val; + wd76c10_ser_par_cs_recalc(dev); + break; - case 0x2872: - dev->disk_chip_select = val; - wd76c10_disk_chip_select(dev); - break; + case 0x2872: + dev->rtc_disk_cs = val; + wd76c10_disk_cs_recalc(dev); + break; - case 0x3072: - dev->prog_chip_sel_addr = val; - break; + case 0x3072: + dev->prog_cs = val; + break; - case 0x3872: - dev->non_page_mode_dram_timing = val; - break; + /* TODO: Log this to determine how the BIOS does bank sizing. */ + case 0x3872: + dev->mem_ctl = val; + wd76c10_banks_recalc(dev); + break; - case 0x4072: - dev->mem_control = val; - break; + case 0x4072: + dev->npmdmt = val; + break; - case 0x4872: - dev->bank10staddr = val; - break; + /* A17-A24 */ + case 0x4872: + dev->bank_base_regs[0] = val; + wd76c10_banks_recalc(dev); + break; - case 0x5072: - dev->bank32staddr = val; - break; + /* A17-A24 */ + case 0x5072: + dev->bank_base_regs[1] = val; + wd76c10_banks_recalc(dev); + break; - case 0x5872: - dev->split_addr = val; - wd76c10_split_addr(dev); - break; + case 0x5872: + dev->split_sa = val; + wd76c10_banks_recalc(dev); + wd76c10_split_recalc(dev); + break; - case 0x6072: - dev->shadow_ram = val & 0xffbf; - wd76c10_shadow_recalc(dev); - break; + case 0x6072: + dev->sh_wp = val; + wd76c10_dis_mem_recalc(dev); + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + wd76c10_high_mem_wp_recalc(dev); + break; - case 0x6872: - dev->ems_control_low_address_boundry = val & 0xecff; - break; + case 0x6872: + dev->ems_ctl = val; + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + break; - case 0x7072: - dev->pmc_output = (val >> 8) & 0x00ff; - break; + case 0x8872: + dev->pmc_in = val; + break; - case 0x7872: - dev->pmc_output = val & 0xff00; - break; + case 0xc072: + dev->hmwpb = val; + wd76c10_high_mem_wp_recalc(dev); + break; - case 0x8072: - dev->pmc_timer = val; - break; - - case 0x8872: - dev->pmc_input = val; - break; - - case 0x9072: - dev->nmi_status = val & 0x00fc; - break; - - case 0x9872: - dev->diagnostic = val & 0xfdff; - break; - - case 0xa072: - dev->delay_line = val; - break; - - case 0xc872: - dev->pmc_interrupt = val & 0xfcfc; - break; - - case 0xf072: - dev->oscillator_40mhz = 0; - break; - - case 0xf472: - dev->oscillator_40mhz = 1; - 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; + dev->ems_pp = val; + dev->ep = (val & 0x3f) % 40; break; case 0xe872: - dev->ems_page_reg = val & 0x8fff; + ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + if (ems_en) { + dev->ems_page_regs[dev->ep] = val; + dev->ems_pages[dev->ep].phys = ((uint32_t) (val & 0x0fff)) << 14; + if (dev->ep >= 32) { + dev->ems_pages[dev->ep].enabled = !!(val & 0x8000); + if (ems_en >= 0x02) { + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + } + } else { + dev->ems_pages[dev->ep].enabled = (ems_en == 0x03); + if (ems_en == 0x03) + wd76c10_low_pages_recalc(dev); + } + } + if (inc) + dev->ep = (dev->ep + 1) % 40; break; case 0xf073: - dev->lock_reg = val & 0x00ff; - LOCK = !(val & 0x00da); + dev->locked = ((val & 0x00ff) != 0x00da); break; - default: + case 0xf872: + flushmmucache(); break; } } -static uint16_t -wd76c10_read(uint16_t addr, void *priv) +static uint8_t +wd76c10_inb(uint16_t port, void *priv) { - const wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t ret = 0xff; - wd76c10_log("WD76C10: R dev->regs[%04x]\n", addr); - switch (addr) { + switch (port) { + case 0x0092: + ret = (dev->p92 & 0x08) | 0xf7; + break; + } + + return ret; +} + +static uint16_t +wd76c10_inw(uint16_t port, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t inc = (uint8_t) ((dev->ems_ctl >> 15) & 0x01); + uint16_t ret = 0xffff; + + wd76c10_log("WD76C10: R dev->regs[%04x]\n", port); + + if (!dev->locked || (port < 0x1072) || (port > 0xf872) || + (port == 0xe072) || (port == 0xe872) || (port == 0xf073)) switch (port) { case 0x1072: - return dev->clk_control; + ret = dev->cpuclk; + break; case 0x1872: - return dev->bus_timing_power_down_ctl; + ret = dev->fpu_ctl; + break; case 0x2072: - return dev->refresh_control; + ret = dev->ser_par_cs; + break; case 0x2872: - return dev->disk_chip_select; + ret = dev->rtc_disk_cs; + break; case 0x3072: - return dev->prog_chip_sel_addr; + ret = dev->prog_cs; + break; case 0x3872: - return dev->non_page_mode_dram_timing; + ret = dev->mem_ctl; + break; case 0x4072: - return dev->mem_control; + ret = dev->npmdmt; + break; case 0x4872: - return dev->bank10staddr; + ret = dev->bank_base_regs[0]; + break; case 0x5072: - return dev->bank32staddr; + ret = dev->bank_base_regs[1]; + break; case 0x5872: - return dev->split_addr; + ret = dev->split_sa; + break; case 0x6072: - return dev->shadow_ram; + ret = dev->sh_wp; + break; case 0x6872: - return dev->ems_control_low_address_boundry; - - case 0x7072: - return (dev->pmc_output << 8) & 0xff00; - - case 0x7872: - return (dev->pmc_output) & 0xff00; - - case 0x8072: - return dev->pmc_timer; + ret = dev->ems_ctl; + break; case 0x8872: - return dev->pmc_input; - - case 0x9072: - return dev->nmi_status; - - case 0x9872: - return dev->diagnostic; - - case 0xa072: - return dev->delay_line; + ret = dev->pmc_in; + break; case 0xb872: - return (inb(0x040b) << 8) | inb(0x04d6); + ret = dma[0].mode; + ret |= (((uint16_t) dma[1].mode) << 8); + break; - case 0xc872: - return dev->pmc_interrupt; + case 0xc072: + ret = dev->hmwpb; + break; case 0xd072: - return dev->port_shadow; + ret = (serial_read(0x0002, dev->uart[0]) & 0xc0) << 8; + ret |= (serial_read(0x0002, dev->uart[1]) & 0xc0) << 6; + ret |= (lpt_read_port(0, 0x0002) & 0x0f) << 8; + ret |= lpt_read_port(0, 0x0000); + break; case 0xe072: - return dev->ems_page_reg_pointer; + ret = (dev->ems_pp & 0xffc0) | dev->ep; + break; case 0xe872: - return dev->ems_page_reg; + ret = dev->ems_page_regs[dev->ep]; + if (inc) + dev->ep = (dev->ep + 1) % 40; + break; case 0xfc72: - return 0x0ff0; - - default: - return 0xffff; + ret = ((lpt_read_status(0) & 0x20) >> 2); + ret |= (((uint16_t) dma_m) << 4); + ret |= dev->toggle; + dev->toggle ^= 0x8000; + break; } + + return ret; } static void wd76c10_close(void *priv) { - wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; free(dev); } -static void * -wd76c10_init(UNUSED(const device_t *info)) + +static void +wd76c10_reset(void *priv) { - wd76c10_t *dev = (wd76c10_t *) malloc(sizeof(wd76c10_t)); - memset(dev, 0, sizeof(wd76c10_t)); + wd76c10_t *dev = (wd76c10_t *)priv; + + dev->locked = 1; + dev->toggle = 0; + + dev->p92 = 0xf7; + + dev->cpuclk = 0x1000; + dev->fpu_ctl = 0x00ca; + dev->mem_ctl = 0x0000; + dev->bank_base_regs[0] = 0x0000; + dev->bank_base_regs[1] = 0x0000; + dev->split_sa = 0x0000; + dev->sh_wp = 0x0000; + dev->hmwpb = 0x0000; + dev->npmdmt = 0x0000; + dev->ems_ctl = 0x0000; + dev->ems_pp = 0x0000; + dev->ser_par_cs = 0x0000; + dev->rtc_disk_cs = 0x0000; + + for (uint8_t i = 0; i < 40; i++) { + dev->ems_page_regs[i] = 0x0000; + dev->ems_pages[i].enabled = 0; + dev->ems_pages[i].phys = 0x00000000; + } + + nvr_lock_set(0x38, 0x08, 0x00, dev->nvr); + + wd76c10_banks_recalc(dev); + wd76c10_split_recalc(dev); + wd76c10_dis_mem_recalc(dev); + wd76c10_high_mem_wp_recalc(dev); + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + wd76c10_ser_par_cs_recalc(dev); + wd76c10_disk_cs_recalc(dev); +} + + +static void * +wd76c10_init(const device_t *info) +{ + wd76c10_t *dev = (wd76c10_t *) calloc(1, sizeof(wd76c10_t)); + uint32_t total_mem = mem_size << 10; + uint32_t accum_mem = 0x00000000; + ram_bank_t *rb; + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + for (int8_t j = 3; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + break; + } + } + if (size != 0x00000000) { + rb->phys_addr = accum_mem; + rb->phys_size = size; + total_mem -= size; + accum_mem += size; + } + } + + rb = &(dev->ram_banks[4]); + rb->phys_addr = 0x000a0000; + rb->phys_size = 0x00060000; + + memset(dev->mem_pages, 0xff, sizeof(dev->mem_pages)); + for (uint8_t i = 0x008; i < 0x01f; i++) + dev->mem_pages[i] = i; + for (uint8_t i = 0x020; i < 0x027; i++) + dev->mem_pages[i] = i - 0x20; 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->fdc_controller = device_add(&fdc_at_device); + dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->fdc = device_add(&fdc_at_device); device_add(&ide_isa_device); - /* Lock Configuration */ - LOCK = 1; + wd76c10_reset(dev); + + /* Password Lock */ + io_sethandler(0x0092, 1, wd76c10_inb, NULL, NULL, wd76c10_outb, NULL, NULL, dev); /* Clock Control */ - io_sethandler(0x1072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x1072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Bus Timing & Power Down Control */ - io_sethandler(0x1872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* FPU Bus Timing & Power Down Control */ + io_sethandler(0x1872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Refresh Control(Serial & Parallel) */ - io_sethandler(0x2072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* Refresh Control, Serial and Parallel Chip Selects */ + io_sethandler(0x2072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Disk Chip Select */ - io_sethandler(0x2872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* RTC, PVGA, 80287 Timing, and Disk Chip Selects */ + io_sethandler(0x2872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Programmable Chip Select Address(Needs more further examination!) */ - io_sethandler(0x3072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* Programmable Chip Select Address */ + io_sethandler(0x3072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Memory Control */ + io_sethandler(0x3872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Non-page Mode DRAM Memory Timing */ + io_sethandler(0x4072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Bank 1 & 0 Start Address */ - io_sethandler(0x4872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x4872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Bank 3 & 2 Start Address */ - io_sethandler(0x5072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x5072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Split Address */ - io_sethandler(0x5872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x5872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* EMS Control & EMS Low level boundry */ - io_sethandler(0x6072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* RAM Shadow And Write Protect */ + io_sethandler(0x6072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* EMS Control & EMS Low level boundry */ - io_sethandler(0x6872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* EMS Control And Lower EMS Boundary */ + io_sethandler(0x6872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* PMC Output */ - io_sethandler(0x7072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* PMC Inputs */ + io_sethandler(0x8872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* PMC Output */ - io_sethandler(0x7872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* DMA Mode Shadow Register */ + io_sethandler(0xb872, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); - /* PMC Status */ - io_sethandler(0x8072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* High Memory Write Protect Boundry */ + io_sethandler(0xc072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* PMC Status */ - io_sethandler(0x8872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - - /* NMI Status (Needs further checkup) */ - io_sethandler(0x9072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - - /* Diagnostics */ - io_sethandler(0x9872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - - /* Delay Line */ - io_sethandler(0xa072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - - /* DMA Mode Shadow(Needs Involvement on the DMA code) */ - io_sethandler(0xb872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); - - /* High Memory Protection Boundry */ - io_sethandler(0xc072, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); - - /* PMC Interrupt Enable */ - io_sethandler(0xc872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); - - /* Port Shadow (Needs further lookup) */ - io_sethandler(0xd072, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + /* Shadow Register */ + io_sethandler(0xd072, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); /* EMS Page Register Pointer */ - io_sethandler(0xe072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0xe072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* EMS Page Register */ - io_sethandler(0xe872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0xe872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Lock/Unlock Configuration */ - io_sethandler(0xf073, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); - - /* 40Mhz Oscillator Enable Disable */ - io_sethandler(0xf072, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); - io_sethandler(0xf472, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); - - /* Lock Status */ - io_sethandler(0xfc72, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + io_sethandler(0xf073, 1, NULL, NULL, NULL, NULL, wd76c10_outw, NULL, dev); /* Cache Flush */ - io_sethandler(0xf872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + io_sethandler(0xf872, 1, NULL, NULL, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Lock Status */ + io_sethandler(0xfc72, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); dma_ext_mode_init(); - wd76c10_shadow_recalc(dev); - wd76c10_refresh_control(dev); - wd76c10_disk_chip_select(dev); + mem_mapping_add(&dev->ram_mapping, + 0x00000000, + (mem_size + 384) << 10, + wd76c10_read_ram, + wd76c10_read_ramw, + NULL, + wd76c10_write_ram, + wd76c10_write_ramw, + NULL, + ram, + MEM_MAPPING_INTERNAL, + dev); + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); + mem_mapping_enable(&dev->ram_mapping); + + memset(dev->ram_state, 0x00, sizeof(dev->ram_state)); + return dev; } diff --git a/src/codegen/codegen_ops_fpu.h b/src/codegen/codegen_ops_fpu.h index 1021cc742..242743dee 100644 --- a/src/codegen/codegen_ops_fpu.h +++ b/src/codegen/codegen_ops_fpu.h @@ -671,9 +671,10 @@ ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ { \ static double fp_imm = v; \ + static uint64_t *fptr = (uint64_t *) &fp_imm; \ \ FP_ENTER(); \ - FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \ + FP_LOAD_IMM_Q(*fptr); \ \ return op_pc; \ } diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index 67355539b..3cbca28f8 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -73,7 +73,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *misaligned_offset = NULL; /*In - ESI = address Out - ECX = data, ESI = abrt*/ @@ -161,7 +161,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float) { uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *misaligned_offset = NULL; /*In - ECX = data, ESI = address Out - ESI = abrt diff --git a/src/config.c b/src/config.c index b1ed7094f..02c1d276a 100644 --- a/src/config.c +++ b/src/config.c @@ -77,6 +77,7 @@ #include <86box/plat_dir.h> #include <86box/ui.h> #include <86box/snd_opl.h> +#include <86box/version.h> static int cx; static int cy; @@ -139,8 +140,6 @@ load_general(void) rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0); update_icons = ini_section_get_int(cat, "update_icons", 1); - status_icons_fullscreen = !!ini_section_get_int(cat, "status_icons_fullscreen", 0); - window_remember = ini_section_get_int(cat, "window_remember", 0); if (!window_remember && !(vid_resize & 2)) @@ -211,6 +210,12 @@ load_general(void) ini_section_delete_var(cat, "window_coordinates"); do_auto_pause = ini_section_get_int(cat, "do_auto_pause", 0); + + p = ini_section_get_string(cat, "uuid", NULL); + if (p != NULL) + strncpy(uuid, p, sizeof(uuid) - 1); + else + strncpy(uuid, "", sizeof(uuid) - 1); } /* Load monitor section. */ @@ -244,25 +249,82 @@ load_machine(void) { ini_section_t cat = ini_find_section(config, "Machine"); const char *p; + const char *migrate_from = NULL; int c; int i; + int j; int speed; double multi; p = ini_section_get_string(cat, "machine", NULL); - if (p != NULL) - machine = machine_get_machine_from_internal_name(p); - else + if (p != NULL) { + migrate_from = p; + /* Migrate renamed machines. */ + if (!strcmp(p, "430nx")) + machine = machine_get_machine_from_internal_name("586ip"); + else if (!strcmp(p, "586mc1")) + machine = machine_get_machine_from_internal_name("586is"); + else { + machine = machine_get_machine_from_internal_name(p); + migrate_from = NULL; + } + } else machine = 0; if (machine >= machine_count()) machine = machine_count() - 1; - cpu_override = ini_section_get_int(cat, "cpu_override", 0); - cpu_f = NULL; - p = ini_section_get_string(cat, "cpu_family", NULL); + /* 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 = ini_section_get_int(cat, "cpu_override", 0); + cpu_override_interpreter = ini_section_get_int(cat, "cpu_override_interpreter", 0); + cpu_f = NULL; + p = ini_section_get_string(cat, "cpu_family", NULL); if (p) { - cpu_f = cpu_get_family(p); + /* Migrate CPU family changes. */ + if ((!strcmp(machines[machine].internal_name, "deskpro386") || + !strcmp(machines[machine].internal_name, "deskpro386_05_1988"))) + cpu_f = cpu_get_family("i386dx_deskpro386"); + else + cpu_f = cpu_get_family(p); if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */ cpu_f = NULL; @@ -609,9 +671,9 @@ load_network(void) 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); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_NO_DEVICES), plat_get_string(STRING_PCAP_ERROR_DESC)); else if (network_dev_to_id(p) == -1) - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_INVALID_DEVICE), plat_get_string(STRING_PCAP_ERROR_DESC)); strcpy(nc->host_dev_name, "none"); } else strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); @@ -656,9 +718,9 @@ load_network(void) 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); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_NO_DEVICES), plat_get_string(STRING_PCAP_ERROR_DESC)); else if (network_dev_to_id(p) == -1) - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_INVALID_DEVICE), plat_get_string(STRING_PCAP_ERROR_DESC)); strcpy(nc->host_dev_name, "none"); } else strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1); @@ -683,7 +745,6 @@ load_ports(void) char *p; char temp[512]; int c; - int d; memset(temp, 0, sizeof(temp)); @@ -706,14 +767,6 @@ load_ports(void) p = ini_section_get_string(cat, temp, "none"); lpt_ports[c].device = lpt_device_get_from_internal_name(p); } - - /* Legacy config compatibility. */ - d = ini_section_get_int(cat, "lpt_enabled", 2); - if (d < 2) { - for (c = 0; c < PARALLEL_MAX; c++) - lpt_ports[c].enabled = d; - } - ini_section_delete_var(cat, "lpt_enabled"); } /* Load "Storage Controllers" section. */ @@ -721,13 +774,14 @@ static void load_storage_controllers(void) { ini_section_t cat = ini_find_section(config, "Storage controllers"); + ini_section_t migration_cat; char *p; char temp[512]; int c; int min = 0; int free_p = 0; - for (c = min; c < SCSI_BUS_MAX; c++) { + for (c = min; c < SCSI_CARD_MAX; c++) { sprintf(temp, "scsicard_%d", c + 1); p = ini_section_get_string(cat, temp, NULL); @@ -754,17 +808,16 @@ load_storage_controllers(void) } 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 + /* Migrate renamed and merged cards. */ + if (!strcmp(p, "xtide_plus")) { + hdc_current = hdc_get_from_internal_name("xtide"); + migration_cat = ini_find_or_create_section(config, "PC/XT XTIDE"); + ini_section_set_string(migration_cat, "bios", "xt_plus"); + } else if (!strcmp(p, "xtide_at_386")) { + hdc_current = hdc_get_from_internal_name("xtide_at"); + migration_cat = ini_find_or_create_section(config, "PC/AT XTIDE"); + ini_section_set_string(migration_cat, "bios", "at_386"); + } else hdc_current = hdc_get_from_internal_name(p); if (free_p) { @@ -822,6 +875,8 @@ load_storage_controllers(void) path_normalize(cart_fns[c]); } } + + lba_enhancer_enabled = !!ini_section_get_int(cat, "lba_enhancer_enabled", 0); } /* Load "Hard Disks" section. */ @@ -1104,13 +1159,13 @@ load_floppy_and_cdrom_drives(void) 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 " + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 2047 " "(fdd_image_history[%i][%i])\n", c, i); else - snprintf(fdd_image_history[c][i], 255, "%s", p); + snprintf(fdd_image_history[c][i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); } else - snprintf(fdd_image_history[c][i], 255, "%s%s%s", usr_path, + snprintf(fdd_image_history[c][i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, path_get_slash(usr_path), p); path_normalize(fdd_image_history[c][i]); } @@ -1220,13 +1275,13 @@ load_floppy_and_cdrom_drives(void) 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 " + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_floppy_and_cdrom_drives(): strlen(p) > 2047 " "(cdrom[%i].image_history[%i])\n", c, i); else - snprintf(cdrom[c].image_history[i], 511, "%s", p); + snprintf(cdrom[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); } else - snprintf(cdrom[c].image_history[i], 511, "%s%s%s", usr_path, + snprintf(cdrom[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, path_get_slash(usr_path), p); path_normalize(cdrom[c].image_history[i]); } @@ -1353,13 +1408,13 @@ load_other_removable_devices(void) 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 " + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_other_removable_devices(): strlen(p) > 2047 " "(zip_drives[%i].image_history[%i])\n", c, i); else - snprintf(zip_drives[c].image_history[i], 511, "%s", p); + snprintf(zip_drives[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); } else - snprintf(zip_drives[c].image_history[i], 511, "%s%s%s", usr_path, + snprintf(zip_drives[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, path_get_slash(usr_path), p); path_normalize(zip_drives[c].image_history[i]); } @@ -1469,13 +1524,13 @@ load_other_removable_devices(void) 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 " + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_other_removable_devices(): strlen(p) > 2047 " "(mo_drives[%i].image_history[%i])\n", c, i); else - snprintf(mo_drives[c].image_history[i], 511, "%s", p); + snprintf(mo_drives[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); } else - snprintf(mo_drives[c].image_history[i], 511, "%s%s%s", usr_path, + snprintf(mo_drives[c].image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, path_get_slash(usr_path), p); path_normalize(mo_drives[c].image_history[i]); } @@ -1514,8 +1569,10 @@ load_other_peripherals(void) char *p; char temp[512]; - bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0); - postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0); + bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0); + postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0); + unittester_enabled = !!ini_section_get_int(cat, "unittester_enabled", 0); + novell_keycard_enabled = !!ini_section_get_int(cat, "novell_keycard_enabled", 0); for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); @@ -1532,7 +1589,8 @@ load_other_peripherals(void) void config_load(void) { - int i; + int i; + ini_section_t c; config_log("Loading config file '%s'..\n", cfg_path); @@ -1560,6 +1618,8 @@ config_load(void) dpi_scale = 1; do_auto_pause = 0; + cpu_override_interpreter = 0; + fpu_type = fpu_get_type(cpu_f, cpu, "none"); gfxcard[0] = video_get_video_from_internal_name("cga"); vid_api = plat_vidapi("default"); @@ -1622,6 +1682,23 @@ config_load(void) load_other_removable_devices(); /* Other removable devices */ load_other_peripherals(); /* Other peripherals */ + /* Migrate renamed device configurations. */ + c = ini_find_section(config, "MDA"); + if (c != NULL) + ini_rename_section(c, "IBM MDA"); + c = ini_find_section(config, "CGA"); + if (c != NULL) + ini_rename_section(c, "IBM CGA"); + c = ini_find_section(config, "EGA"); + if (c != NULL) + ini_rename_section(c, "IBM EGA"); + c = ini_find_section(config, "3DFX Voodoo Graphics"); + if (c != NULL) + ini_rename_section(c, "3Dfx Voodoo Graphics"); + c = ini_find_section(config, "3dfx Voodoo Banshee"); + if (c != NULL) + ini_rename_section(c, "3Dfx Voodoo Banshee"); + /* Mark the configuration as changed. */ config_changed = 1; @@ -1784,11 +1861,6 @@ save_general(void) else ini_section_delete_var(cat, "open_dir_usr_path"); - if (status_icons_fullscreen) - ini_section_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); - else - ini_section_delete_var(cat, "status_icons_fullscreen"); - if (video_framerate != -1) ini_section_set_int(cat, "video_gl_framerate", video_framerate); else @@ -1807,6 +1879,20 @@ save_general(void) else ini_section_delete_var(cat, "do_auto_pause"); + char cpu_buf[128] = { 0 }; + plat_get_cpu_string(cpu_buf, 128); + ini_section_set_string(cat, "host_cpu", cpu_buf); + + if (EMU_BUILD_NUM != 0) + ini_section_set_int(cat, "emu_build_num", EMU_BUILD_NUM); + else + ini_section_delete_var(cat, "emu_build_num"); + + if (strnlen(uuid, sizeof(uuid) - 1) > 0) + ini_section_set_string(cat, "uuid", uuid); + else + ini_section_delete_var(cat, "uuid"); + ini_delete_section_if_empty(config, cat); } @@ -1845,11 +1931,6 @@ save_machine(void) { 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(); ini_section_set_string(cat, "machine", p); @@ -1861,62 +1942,15 @@ save_machine(void) ini_section_set_int(cat, "cpu_override", cpu_override); else ini_section_delete_var(cat, "cpu_override"); + if (cpu_override_interpreter) + ini_section_set_int(cat, "cpu_override_interpreter", cpu_override); + else + ini_section_delete_var(cat, "cpu_override_interpreter"); /* 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 (cpu_legacy_table[c].machine) { - /* 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[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; - } - - 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; - } - - /* 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) ini_section_delete_var(cat, "cpu_waitstates"); else @@ -2245,7 +2279,7 @@ save_storage_controllers(void) ini_section_delete_var(cat, "scsicard"); - for (c = 0; c < SCSI_BUS_MAX; c++) { + for (c = 0; c < SCSI_CARD_MAX; c++) { sprintf(temp, "scsicard_%d", c + 1); if (scsi_card_current[c] == 0) @@ -2329,6 +2363,11 @@ save_storage_controllers(void) else ini_section_set_string(cat, temp, cart_fns[c]); } + + if (lba_enhancer_enabled == 0) + ini_section_delete_var(cat, "lba_enhancer_enabled"); + else + ini_section_set_int(cat, "lba_enhancer_enabled", 1); } /* Save "Other Peripherals" section. */ @@ -2348,6 +2387,16 @@ save_other_peripherals(void) else ini_section_set_int(cat, "postcard_enabled", postcard_enabled); + if (unittester_enabled == 0) + ini_section_delete_var(cat, "unittester_enabled"); + else + ini_section_set_int(cat, "unittester_enabled", unittester_enabled); + + if (novell_keycard_enabled == 0) + ini_section_delete_var(cat, "novell_keycard_enabled"); + else + ini_section_set_int(cat, "novell_keycard_enabled", novell_keycard_enabled); + for (uint8_t c = 0; c < ISAMEM_MAX; c++) { sprintf(temp, "isamem%d_type", c); if (isamem_type[c] == 0) diff --git a/src/cpu/386.c b/src/cpu/386.c index f89a8dc96..5379dccf9 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -25,6 +25,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> +#include <86box/plat_fallthrough.h> #include <86box/gdbstub.h> #ifndef OPS_286_386 # define OPS_286_386 @@ -240,6 +241,7 @@ exec386_2386(int32_t cycs) cycdiff = 0; oldcyc = cycles; while (cycdiff < cycle_period) { + int ins_fetch_fault = 0; ins_cycles = cycles; #ifndef USE_NEW_DYNAREC @@ -259,6 +261,13 @@ exec386_2386(int32_t cycs) fetchdat = fastreadl_fetch(cs + cpu_state.pc); ol = opcode_length[fetchdat & 0xff]; CHECK_READ_CS(MIN(ol, 4)); + ins_fetch_fault = cpu_386_check_instruction_fault(); + + /* Breakpoint fault has priority over other faults. */ + if (ins_fetch_fault) { + ins_fetch_fault = 0; + cpu_state.abrt = 1; + } if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG @@ -267,10 +276,14 @@ exec386_2386(int32_t cycs) #endif 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.eflags &= ~(RF_FLAG); + if (opcode == 0xf0) + in_lock = 1; + x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + in_lock = 0; if (x86_was_reset) break; } @@ -311,12 +324,13 @@ exec386_2386(int32_t cycs) } } else if (trap) { flags_rebuild(); + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; - dr[6] |= 0x4000; x86_int(1); } diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 60ecd8954..f3926f170 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -80,6 +80,7 @@ int smm_in_hlt = 0; int smi_block = 0; int prefetch_prefixes = 0; +int rf_flag_no_clear = 0; int tempc; int oldcpl; @@ -119,6 +120,53 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 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 */ +/* 0 = no, 1 = always, 2 = depends on second opcode, 3 = depends on mod/rm */ +int lock_legal[256] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 2, /* 0x0x */ + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x1x */ + 1, 1, 1, 1, 1, 1, 4, 0, 1, 1, 1, 1, 1, 1, 4, 0, /* 0x2x */ + 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, /* 0x3x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */ + 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */ + 3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xax */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xbx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */ + 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3 }; /* 0xfx */ + +int lock_legal_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0xax */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, /* 0xbx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 0xfx */ + +/* (modrm >> 3) & 0x07 */ +int lock_legal_ba[8] = { 0, 0, 0, 0, 1, 1, 1, 1 }; + +/* Also applies to 81, 82, and 83 */ +int lock_legal_80[8] = { 1, 1, 1, 1, 1, 1, 1, 0 }; + +/* Also applies to F7 */ +int lock_legal_f6[8] = { 0, 0, 1, 1, 0, 0, 0, 0 }; + +/* Also applies to FF */ +int lock_legal_fe[8] = { 1, 1, 0, 0, 0, 0, 0, 0 }; + uint32_t addr64; uint32_t addr64_2; uint32_t addr64a[8]; @@ -127,9 +175,9 @@ 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) +#define AMD_SYSCALL_EIP (msr.amd_star & 0xFFFFFFFF) +#define AMD_SYSCALL_SB ((msr.amd_star >> 32) & 0xFFFF) +#define AMD_SYSRET_SB ((msr.amd_star >> 48) & 0xFFFF) /* These #define's and enum have been borrowed from Bochs. */ /* SMM feature masks */ @@ -375,6 +423,50 @@ x386_common_log(const char *fmt, ...) # define x386_common_log(fmt, ...) #endif +int +is_lock_legal(uint32_t fetchdat) +{ + int legal; + fetch_dat_t fetch_dat; + + fetch_dat.fd = fetchdat; + + legal = lock_legal[fetch_dat.b[0]]; + if (legal == 1) + legal = 1; // ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + else if (legal == 2) { + legal = lock_legal_0f[fetch_dat.b[1]]; + if (legal == 1) + legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,reg is illegal */ + else if (legal == 3) { + legal = lock_legal_ba[(fetch_dat.b[2] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,imm is illegal */ + } + } else if (legal == 3) switch(fetch_dat.b[0]) { + case 0x80 ... 0x83: + legal = lock_legal_80[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + case 0xf6 ... 0xf7: + legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + case 0xfe ... 0xff: + legal = lock_legal_fe[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + default: + legal = 0; + break; + } + + return legal; +} + /*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 @@ -1411,7 +1503,7 @@ x86_int(int num) cpu_state.pc = cpu_state.oldpc; if (msw & 1) - is486 ? pmodeint(num, 0) : pmodeint_2386(num, 0); + cpu_use_exec ? pmodeint(num, 0) : pmodeint_2386(num, 0); else { addr = (num << 2) + idt.base; @@ -1444,7 +1536,7 @@ x86_int(int num) oxpc = cpu_state.pc; #endif cpu_state.pc = readmemw(0, addr); - is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); } } @@ -1461,7 +1553,7 @@ x86_int_sw(int num) cycles -= timing_int; if (msw & 1) - is486 ? pmodeint(num, 1) : pmodeint_2386(num, 1); + cpu_use_exec ? pmodeint(num, 1) : pmodeint_2386(num, 1); else { addr = (num << 2) + idt.base; @@ -1486,12 +1578,15 @@ x86_int_sw(int num) oxpc = cpu_state.pc; #endif cpu_state.pc = readmemw(0, addr); - is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); cycles -= timing_int_rm; } } - trap = 0; + if (cpu_use_exec) + trap = 0; + else + trap &= ~1; CPU_BLOCK_END(); } @@ -1528,13 +1623,16 @@ x86_int_sw_rm(int num) cpu_state.eflags &= ~VIF_FLAG; cpu_state.flags &= ~T_FLAG; cpu_state.pc = new_pc; - is486 ? loadcs(new_cs) : loadcs_2386(new_cs); + cpu_use_exec ? loadcs(new_cs) : loadcs_2386(new_cs); #ifndef USE_NEW_DYNAREC oxpc = cpu_state.pc; #endif cycles -= timing_int_rm; - trap = 0; + if (cpu_use_exec) + trap = 0; + else + trap &= ~1; CPU_BLOCK_END(); return 0; @@ -1551,6 +1649,13 @@ checkio(uint32_t port, int mask) { uint32_t t; + if (!(tr.access & 0x08)) { + if ((CPL) > (IOPL)) + return 1; + + return 0; + } + cpl_override = 1; t = readmemw(tr.base, 0x66); @@ -1655,6 +1760,37 @@ cpu_386_flags_rebuild(void) flags_rebuild(); } +extern uint64_t mmutranslate_noabrt_2386(uint32_t addr, int rw); +int +cpu_386_check_instruction_fault(void) +{ + int i = 0; + int fault = 0; + /* Report no fault if RF is set. */ + if (cpu_state.eflags & RF_FLAG) + return 0; + + /* Make sure breakpoints are enabled. */ + if (!(dr[7] & 0xFF)) + return 0; + + for (i = 0; i < 4; i++) { + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i))); + uint32_t translated_addr = 0xffffffff; + if (!breakpoint_enabled) + continue; + + translated_addr = dr[i]; + + if ((cs + cpu_state.pc) == (uint32_t)translated_addr) { + dr[6] |= (1 << i); + fault = 1; + } + } + + return fault; +} + int sysenter(uint32_t fetchdat) { diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 22fbd4bff..a98a3e930 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -225,19 +225,37 @@ int checkio(uint32_t port, int mask); static __inline uint8_t fastreadb(uint32_t a) { - return readmembl_2386(a); + uint8_t ret; + read_type = 1; + ret = readmembl_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } static __inline uint16_t fastreadw(uint32_t a) { - return readmemwl_2386(a); + uint16_t ret; + read_type = 1; + ret = readmemwl_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } static __inline uint32_t fastreadl(uint32_t a) { - return readmemll_2386(a); + uint32_t ret; + read_type = 1; + ret = readmemll_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } #else static __inline uint8_t @@ -342,31 +360,41 @@ extern int opcode_length[256]; static __inline uint16_t fastreadw_fetch(uint32_t a) { - uint16_t val; + uint16_t ret; if ((a & 0xFFF) > 0xFFE) { - val = fastreadb(a); - if (opcode_length[val & 0xff] > 1) - val |= ((uint16_t) fastreadb(a + 1) << 8); - return val; + ret = fastreadb(a); + if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 1)) + ret |= ((uint16_t) fastreadb(a + 1) << 8); + } else if (cpu_state.abrt) + ret = 0; + else { + read_type = 1; + ret = readmemwl_2386(a); + read_type = 4; } - return readmemwl_2386(a); + return ret; } static __inline uint32_t fastreadl_fetch(uint32_t a) { - uint32_t val; + uint32_t ret; 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; + ret = fastreadw_fetch(a); + if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 2)) + ret |= ((uint32_t) fastreadw(a + 2) << 16); + } else if (cpu_state.abrt) + ret = 0; + else { + read_type = 1; + ret = readmemll_2386(a); + read_type = 4; } - return readmemll_2386(a); + return ret; } #else static __inline uint16_t @@ -674,3 +702,8 @@ seteaq(uint64_t v) cpu_state.pc += 2 #endif + +/* Resume Flag handling. */ +extern int rf_flag_no_clear; + +int cpu_386_check_instruction_fault(void); \ No newline at end of file diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index e4caa8a1b..c96e3420d 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -48,6 +48,7 @@ #define CPU_BLOCK_END() cpu_block_end = 1 +int cpu_override_dynarec = 0; int inrecomp = 0; int cpu_block_end = 0; int cpu_end_block_after_ins = 0; @@ -268,6 +269,12 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; + if (trap == 2) { + /* Handle the T bit in the new TSS first. */ + CPU_BLOCK_END(); + goto block_ended; + } + while (!cpu_block_end) { # ifndef USE_NEW_DYNAREC oldcs = CS; @@ -321,13 +328,14 @@ exec386_dynarec_int(void) CPU_BLOCK_END(); } +block_ended: if (!cpu_state.abrt && trap) { + dr[6] |= (trap == 2) ? 0x8000 : 0x4000; trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; # endif cpu_state.oldpc = cpu_state.pc; - dr[6] |= 0x4000; x86_int(1); } @@ -542,7 +550,7 @@ exec386_dynarec_dyn(void) # endif CPU_BLOCK_END(); - if (cpu_state.flags & T_FLAG) + if ((cpu_state.flags & T_FLAG) || (trap == 2)) CPU_BLOCK_END(); if (smi_line) CPU_BLOCK_END(); @@ -711,7 +719,7 @@ exec386_dynarec(int32_t cycs) cycles_old = cycles; oldtsc = tsc; tsc_old = tsc; - if (!CACHE_ON()) /*Interpret block*/ + if ((!CACHE_ON()) || cpu_override_dynarec) /*Interpret block*/ { exec386_dynarec_int(); } else { diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 8a0f4cd5a..3e0d191f2 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -181,8 +181,16 @@ extern void x386_dynarec_log(const char *fmt, ...); #ifndef OPS_286_386 # include "x86_ops_cyrix.h" #endif -#include "x86_ops_flag.h" -#include "x86_ops_fpu.h" +#ifdef OPS_286_386 +# include "x86_ops_flag_2386.h" +#else +# include "x86_ops_flag.h" +#endif +#ifdef OPS_286_386 +# include "x86_ops_fpu_2386.h" +#else +# include "x86_ops_fpu.h" +#endif #include "x86_ops_inc_dec.h" #include "x86_ops_int.h" #include "x86_ops_io.h" @@ -200,7 +208,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_mmx_shift.h" #endif #include "x86_ops_mov.h" -#include "x86_ops_mov_ctrl.h" +#ifdef OPS_286_386 +# include "x86_ops_mov_ctrl_2386.h" +#else +# include "x86_ops_mov_ctrl.h" +#endif #include "x86_ops_mov_seg.h" #include "x86_ops_movx.h" #ifndef OPS_286_386 @@ -208,7 +220,11 @@ extern void x386_dynarec_log(const char *fmt, ...); #endif #include "x86_ops_mul.h" #include "x86_ops_pmode.h" -#include "x86_ops_prefix.h" +#ifdef OPS_286_386 +# include "x86_ops_prefix_2386.h" +#else +# include "x86_ops_prefix.h" +#endif #ifdef IS_DYNAREC # include "x86_ops_rep_dyn.h" #else @@ -218,7 +234,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_rep.h" # endif #endif -#include "x86_ops_ret.h" +#ifdef OPS_286_386 +# include "x86_ops_ret_2386.h" +#else +# include "x86_ops_ret.h" +#endif #include "x86_ops_set.h" #include "x86_ops_stack.h" #ifdef OPS_286_386 @@ -629,7 +649,7 @@ 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*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, 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, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -644,14 +664,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, -/*c0*/ opXADD_b_a16, opXADD_w_a16, 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*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, 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, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -666,14 +686,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, -/*c0*/ opXADD_b_a16, opXADD_l_a16, 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*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, 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, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -688,14 +708,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, -/*c0*/ opXADD_b_a32, opXADD_w_a32, 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*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, 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, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -710,7 +730,7 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, -/*c0*/ opXADD_b_a32, opXADD_l_a32, 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, diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 3572f2c9f..5b411dd66 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -56,7 +56,6 @@ static uint32_t *opseg[4]; static x86seg *_opseg[4]; static int noint = 0; -static int in_lock = 0; static int cpu_alu_op, pfq_size; static uint32_t cpu_src = 0, cpu_dest = 0; @@ -545,7 +544,6 @@ reset_808x(int hard) { biu_cycles = 0; in_rep = 0; - in_lock = 0; completed = 1; repeating = 0; clear_lock = 0; @@ -563,9 +561,10 @@ reset_808x(int hard) _opseg[3] = &cpu_state.seg_ds; pfq_size = (is8086) ? 6 : 4; - pfq_clear(); } + pfq_clear(); + load_cs(0xFFFF); cpu_state.pc = 0; if (is_nec) @@ -1222,34 +1221,48 @@ static void add(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest + cpu_src; + if ((cpu_alu_op == 2) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_add(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)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); + set_cf((temp_src & size_mask) > (cpu_data & size_mask)); } static void sub(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest - cpu_src; + if ((cpu_alu_op == 3) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_sub(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)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); + set_cf((temp_src & size_mask) > (cpu_dest & size_mask)); } static void @@ -3183,31 +3196,66 @@ execx86(int cycs) 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; + if (fpu_softfloat) { + switch (opcode) { + case 0xD8: + ops_sf_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); + break; + case 0xD9: + ops_sf_fpu_8087_d9[rmdat & 0xff](rmdat); + break; + case 0xDA: + ops_sf_fpu_8087_da[rmdat & 0xff](rmdat); + break; + case 0xDB: + ops_sf_fpu_8087_db[rmdat & 0xff](rmdat); + break; + case 0xDC: + ops_sf_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); + break; + case 0xDD: + ops_sf_fpu_8087_dd[rmdat & 0xff](rmdat); + break; + case 0xDE: + ops_sf_fpu_8087_de[rmdat & 0xff](rmdat); + break; + case 0xDF: + ops_sf_fpu_8087_df[rmdat & 0xff](rmdat); + break; + + default: + break; + } + } else { + switch (opcode) { + case 0xD8: + ops_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); + break; + case 0xD9: + ops_fpu_8087_d9[rmdat & 0xff](rmdat); + break; + case 0xDA: + ops_fpu_8087_da[rmdat & 0xff](rmdat); + break; + case 0xDB: + ops_fpu_8087_db[rmdat & 0xff](rmdat); + break; + case 0xDC: + ops_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); + break; + case 0xDD: + ops_fpu_8087_dd[rmdat & 0xff](rmdat); + break; + case 0xDE: + ops_fpu_8087_de[rmdat & 0xff](rmdat); + break; + case 0xDF: + ops_fpu_8087_df[rmdat & 0xff](rmdat); + break; + + default: + break; + } } cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on the 286+ core, but not here. */ diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 47e64a275..0f83a5e4b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -55,27 +55,31 @@ #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_PGE = (1 << 13), - CPUID_MCA = (1 << 14), - CPUID_CMOV = (1 << 15), - CPUID_MMX = (1 << 23), - CPUID_FXSR = (1 << 24) + CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */ + CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */ + CPUID_DE = (1 << 2), /* Debugging extensions */ + CPUID_PSE = (1 << 3), /* Page Size Extension */ + CPUID_TSC = (1 << 4), /* Time Stamp Counter */ + CPUID_MSR = (1 << 5), /* Model-specific registers */ + CPUID_PAE = (1 << 6), /* Physical Address Extension */ + CPUID_MCE = (1 << 7), /* Machine Check Exception */ + CPUID_CMPXCHG8B = (1 << 8), /* CMPXCHG8B instruction */ + CPUID_APIC = (1 << 9), /* On-chip APIC */ + CPUID_AMDPGE = (1 << 9), /* Global Page Enable (AMD K5 Model 0 only) */ + CPUID_AMDSEP = (1 << 10), /* SYSCALL and SYSRET instructions (AMD K6 only) */ + CPUID_SEP = (1 << 11), /* SYSENTER and SYSEXIT instructions (SYSCALL and SYSRET if EAX=80000001h) */ + CPUID_MTRR = (1 << 12), /* Memory type range registers */ + CPUID_PGE = (1 << 13), /* Page Global Enable */ + CPUID_MCA = (1 << 14), /* Machine Check Architecture */ + CPUID_CMOV = (1 << 15), /* Conditional move instructions */ + CPUID_PAT = (1 << 16), /* Page Attribute Table */ + CPUID_MMX = (1 << 23), /* MMX technology */ + CPUID_FXSR = (1 << 24) /* FXSAVE and FXRSTOR instructions */ }; -/*Addition flags returned by CPUID function 0x80000001*/ -#define CPUID_3DNOW (1UL << 31UL) -#define CPUID_3DNOWE (1UL << 30UL) +/* Additional flags returned by CPUID function 0x80000001 */ +#define CPUID_3DNOWE (1UL << 30UL) /* Extended 3DNow! instructions */ +#define CPUID_3DNOW (1UL << 31UL) /* 3DNow! instructions */ /* Make sure this is as low as possible. */ cpu_state_t cpu_state; @@ -181,6 +185,9 @@ int cpu_multi; int cpu_16bitbus; int cpu_64bitbus; int cpu_cyrix_alignment; +int cpu_cpurst_on_sr; +int cpu_use_exec = 0; +int cpu_override_interpreter; int CPUID; int is186; @@ -242,8 +249,7 @@ uint32_t cache_index = 0; uint8_t _cache[2048]; uint64_t cpu_CR4_mask; -uint64_t tsc = 0; -uint64_t pmc[2] = { 0, 0 }; +uint64_t tsc = 0; double cpu_dmulti; double cpu_busspeed; @@ -742,6 +748,7 @@ cpu_set(void) timing_misaligned = 0; cpu_cyrix_alignment = 0; + cpu_cpurst_on_sr = 0; cpu_CR4_mask = 0; switch (cpu_s->cpu_type) { @@ -1602,11 +1609,16 @@ cpu_set(void) cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE); if (cpu_s->cpu_type <= CPU_K6) cpu_CR4_mask |= CR4_PCE; - } + else if (cpu_s->cpu_type >= CPU_K6_2C) + cpu_CR4_mask |= CR4_PGE; + } else + cpu_CR4_mask |= CR4_PGE; #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; + else if (cpu_s->cpu_type >= CPU_K6_2C) + cpu_CR4_mask |= CR4_PGE; #endif #ifdef USE_DYNAREC @@ -1782,16 +1794,21 @@ cpu_set(void) x87_concurrency = x87_concurrency_486; } + cpu_use_exec = 0; + if (is386) { #if defined(USE_DYNAREC) && !defined(USE_GDBSTUB) - if (cpu_use_dynarec) + if (cpu_use_dynarec) { cpu_exec = exec386_dynarec; - else + cpu_use_exec = 1; + } else #endif /* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */ - if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC)) + if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL) || + cpu_iscyrix || (cpu_s->cpu_type > CPU_486DLC) || cpu_override_interpreter) { cpu_exec = exec386; - else + cpu_use_exec = 1; + } else cpu_exec = exec386_2386; } else if (cpu_s->cpu_type >= CPU_286) cpu_exec = exec386_2386; @@ -1899,7 +1916,7 @@ cpu_CPUID(void) case CPU_i486SX_SLENH: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -1913,7 +1930,7 @@ cpu_CPUID(void) case CPU_i486DX_SLENH: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -1929,21 +1946,21 @@ cpu_CPUID(void) case CPU_ENH_Am486DX: if (!EAX) { - EAX = 1; - EBX = 0x68747541; + EAX = 0x00000001; + EBX = 0x68747541;/* AuthenticAMD */ ECX = 0x444D4163; EDX = 0x69746E65; } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU; /*FPU*/ + EDX = CPUID_FPU; } else EAX = EBX = ECX = EDX = 0; break; case CPU_WINCHIP: if (!EAX) { - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -1954,7 +1971,7 @@ cpu_CPUID(void) EDX = 0x48727561; } } else if (EAX == 1) { - EAX = 0x540; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -1968,7 +1985,7 @@ cpu_CPUID(void) case CPU_WINCHIP2: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -1980,7 +1997,7 @@ cpu_CPUID(void) } break; case 1: - EAX = CPUID; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -2025,13 +2042,15 @@ cpu_CPUID(void) case CPU_PENTIUM: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ 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; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; + if (cpu_s->cpu_type != CPU_P24T) + EDX |= CPUID_MCE; } else EAX = EBX = ECX = EDX = 0; break; @@ -2040,106 +2059,69 @@ cpu_CPUID(void) case CPU_K5: if (!EAX) { EAX = 0x00000001; - EBX = 0x68747541; + EBX = 0x68747541; /* AuthenticAMD */ EDX = 0x69746E65; ECX = 0x444D4163; } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE; } 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; + switch (EAX) { + case 0: + EAX = 0x00000001; + EBX = 0x68747541; /* AuthenticAMD */ + EDX = 0x69746E65; + ECX = 0x444D4163; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + break; + case 0x80000000: + EAX = 0x80000005; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2D444D41; /* AMD-K5(tm) Proce */ + EBX = 0x7428354B; + ECX = 0x5020296D; + EDX = 0x65636F72; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x726F7373; /* ssor */ + EBX = ECX = EDX = 0; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x04800000; /* TLBs */ + ECX = 0x08040120; /* L1 data cache */ + EDX = 0x10040120; /* L1 instruction cache */ + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } 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_2: - case CPU_K6_2C: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ - ECX = 0x444d4163; - EDX = 0x69746e65; + EDX = 0x69746E65; + ECX = 0x444D4163; break; case 1: EAX = CPUID; @@ -2153,7 +2135,68 @@ cpu_CPUID(void) 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; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2D444D41; /* AMD-K6tm w/ mult */ + EBX = 0x6D74364B; + ECX = 0x202F7720; + EDX = 0x746C756D; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x64656D69; /* imedia extension */ + EBX = 0x65206169; + ECX = 0x6E657478; + EDX = 0x6E6F6973; + break; + case 0x80000004: /* Processor name string */ + EAX = 0x73; /* s */ + EBX = ECX = EDX = 0; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ + break; + case 0x8FFFFFFF: /* Easter egg */ + EAX = 0x4778654E; /* NexGenerationAMD */ + EBX = 0x72656E65; + ECX = 0x6F697461; + EDX = 0x444D416E; + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_K6_2: + case CPU_K6_2C: + switch (EAX) { + case 0: + EAX = 0x00000001; + 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; + if (cpu_s->cpu_type == CPU_K6_2C) + EDX |= CPUID_PGE; + 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_SEP | CPUID_MMX | CPUID_3DNOW; + if (cpu_s->cpu_type == CPU_K6_2C) + EDX |= CPUID_PGE; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */ @@ -2167,11 +2210,11 @@ cpu_CPUID(void) ECX = 0x00000000; EDX = 0x00000000; break; - case 0x80000005: /*Cache information*/ + case 0x80000005: /* Cache information */ EAX = 0; - EBX = 0x02800140; /*TLBs*/ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ break; default: EAX = EBX = ECX = EDX = 0; @@ -2182,7 +2225,7 @@ cpu_CPUID(void) case CPU_K6_3: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ ECX = 0x444d4163; EDX = 0x69746e65; @@ -2190,7 +2233,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000006; @@ -2199,7 +2242,7 @@ cpu_CPUID(void) 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; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */ @@ -2216,8 +2259,8 @@ cpu_CPUID(void) case 0x80000005: /* Cache information */ EAX = 0; EBX = 0x02800140; /* TLBs */ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ break; case 0x80000006: /* L2 Cache information */ EAX = EBX = EDX = 0; @@ -2233,7 +2276,7 @@ cpu_CPUID(void) case CPU_K6_3P: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ ECX = 0x444d4163; EDX = 0x69746e65; @@ -2241,7 +2284,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000007; @@ -2250,7 +2293,7 @@ cpu_CPUID(void) 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; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm)-III P */ @@ -2290,7 +2333,7 @@ cpu_CPUID(void) case CPU_PENTIUMMMX: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2305,7 +2348,7 @@ cpu_CPUID(void) case CPU_Cx6x86: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2319,7 +2362,7 @@ cpu_CPUID(void) case CPU_Cx6x86L: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2333,7 +2376,7 @@ cpu_CPUID(void) case CPU_CxGX1: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2347,7 +2390,7 @@ cpu_CPUID(void) case CPU_Cx6x86MX: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2362,7 +2405,7 @@ cpu_CPUID(void) case CPU_PENTIUMPRO: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2377,7 +2420,7 @@ cpu_CPUID(void) EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size Data TLB: 4 MB pages, 4-way set associative, 8 entries - 1st-level instruction cache:8 KB, 4-way set associative, 32-byte line size */ + 1st-level instruction cache: 8 KB, 4-way set associative, 32-byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2385,7 +2428,7 @@ cpu_CPUID(void) case CPU_PENTIUM2: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2408,7 +2451,7 @@ cpu_CPUID(void) case CPU_PENTIUM2D: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2439,7 +2482,7 @@ cpu_CPUID(void) case CPU_CYRIX3S: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -2451,7 +2494,7 @@ cpu_CPUID(void) } break; case 1: - EAX = CPUID; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -2497,9 +2540,12 @@ cpu_ven_reset(void) switch (cpu_s->cpu_type) { 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); + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + msr.mcr_ctrl = 0xf8000000; + if (cpu_s->cpu_type == CPU_WINCHIP2) { + msr.fcr |= (1 << 18) | (1 << 20); + msr.mcr_ctrl |= (1 << 17); + } break; case CPU_K6_2P: @@ -2539,18 +2585,28 @@ cpu_RDMSR(void) case CPU_IBM486BL: EAX = EDX = 0; switch (ECX) { + /* Processor Operation Register */ case 0x1000: EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); break; + /* Cache Region Control Register */ case 0x1001: - EAX = msr.ibm_crcr & 0xffffffffff; + EAX = msr.ibm_crcr & 0xffffffff; + EDX = (msr.ibm_crcr >> 32) & 0x0000ffff; break; + /* Processor Operation Register */ case 0x1002: if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) EAX = msr.ibm_por2 & 0x3f000000; break; + + /* Processor Control Register */ + case 0x1004: + if (cpu_s->cpu_type > CPU_IBM486SLC) + EAX = msr.ibm_pcr & 0x00d6001a; + break; } break; @@ -2558,42 +2614,74 @@ cpu_RDMSR(void) case CPU_WINCHIP2: EAX = EDX = 0; switch (ECX) { + /* Pentium Processor Parity Reversal Register */ case 0x02: EAX = msr.tr1; break; + /* Pentium Processor New Feature Control */ case 0x0e: EAX = msr.tr12; break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ case 0x11: EAX = msr.cesr; break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + /* Feature Control Register */ case 0x107: EAX = msr.fcr; break; + /* Feature Control Register 2 */ case 0x108: EAX = msr.fcr2 & 0xffffffff; EDX = msr.fcr2 >> 32; break; + /* Feature Control Register 4 */ case 0x10a: EAX = cpu_multi & 3; break; + /* Memory Configuration Register Control */ + case 0x120: + EAX = msr.mcr_ctrl; + break; + /* Unknown */ + case 0x131: + case 0x142 ... 0x145: + case 0x147: + case 0x150: + case 0x151: + break; } break; case CPU_CYRIX3S: EAX = EDX = 0; switch (ECX) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: EAX = 0xc4000000; EDX = 0; @@ -2620,29 +2708,41 @@ cpu_RDMSR(void) if (cpu_busspeed >= 84000000) EAX |= (1 << 19); break; + /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */ + case 0xc1: + EAX = tsc & 0xffffffff; + EDX = (tsc >> 32) & 0xff; + break; + /* PERFCTR1 - Performance Counter Register 1 */ + case 0xc2: + EAX = msr.perfctr[1] & 0xffffffff; + EDX = msr.perfctr[1] >> 32; + break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ + case 0x11e: + EAX = 0x800000; /* L2 cache disabled */ + break; + /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */ + case 0x186: + EAX = 0x470079; + break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ + case 0x187: + EAX = msr.evntsel[1] & 0xffffffff; + EDX = msr.evntsel[1] >> 32; + break; + /* Feature Control Register */ case 0x1107: EAX = msr.fcr; break; + /* Feature Control Register 2 */ 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: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) { EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; @@ -2651,29 +2751,27 @@ cpu_RDMSR(void) EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; } break; + /* MTRRfix64K_00000 */ case 0x250: EAX = msr.mtrr_fix64k_8000 & 0xffffffff; EDX = msr.mtrr_fix64k_8000 >> 32; break; + /* MTRRfix16K_80000 */ case 0x258: EAX = msr.mtrr_fix16k_8000 & 0xffffffff; EDX = msr.mtrr_fix16k_8000 >> 32; break; + /* MTRRfix16K_A0000 */ 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: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; break; + /* MTRRdefType */ case 0x2ff: EAX = msr.mtrr_deftype & 0xffffffff; EDX = msr.mtrr_deftype >> 32; @@ -2691,37 +2789,75 @@ cpu_RDMSR(void) case CPU_K6_3: case CPU_K6_2P: case CPU_K6_3P: - EAX = EDX = 0; + EAX = 0; + /* EDX is left unchanged when reading this MSR! */ + if (ECX != 0x82) + EDX = 0; switch (ECX) { + /* Machine Check Address Register */ case 0x00000000: - case 0x00000001: + EAX = msr.mcar & 0xffffffff; + EDX = msr.mcar >> 32; break; + /* Machine Check Type Register */ + case 0x00000001: + EAX = msr.mctr & 0xffffffff; + EDX = msr.mctr >> 32; + break; + /* Test Register 12 */ case 0x0000000e: EAX = msr.tr12; break; + /* Time Stamp Counter */ case 0x00000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; - case 0x00000083: - EAX = msr.ecx83 & 0xffffffff; - EDX = msr.ecx83 >> 32; + /* Array Access Register */ + case 0x00000082: + if (cpu_s->cpu_type > CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_aar & 0xffffffff; + /* EDX is left unchanged! */ break; + /* Hardware Configuration Register */ + case 0x00000083: + EAX = msr.amd_hwcr & 0xffffffff; + EDX = msr.amd_hwcr >> 32; + break; + /* Write Allocate Top-of-Memory and Control Register */ + case 0x00000085: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_watmcr & 0xffffffff; + EDX = msr.amd_watmcr >> 32; + break; + /* Write Allocate Programmable Memory Range Register */ + case 0x00000086: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_wapmrr & 0xffffffff; + EDX = msr.amd_wapmrr >> 32; + break; + /* Extended Feature Enable Register */ case 0xc0000080: EAX = msr.amd_efer & 0xffffffff; EDX = msr.amd_efer >> 32; break; + /* SYSCALL Target Address Register */ case 0xc0000081: if (cpu_s->cpu_type < CPU_K6_2) goto amd_k_invalid_rdmsr; - EAX = msr.star & 0xffffffff; - EDX = msr.star >> 32; + EAX = msr.amd_star & 0xffffffff; + EDX = msr.amd_star >> 32; break; + /* Write-Handling Control Register */ case 0xc0000082: EAX = msr.amd_whcr & 0xffffffff; EDX = msr.amd_whcr >> 32; break; + /* UC/WC Cacheability Control Register */ case 0xc0000085: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2729,6 +2865,7 @@ cpu_RDMSR(void) EAX = msr.amd_uwccr & 0xffffffff; EDX = msr.amd_uwccr >> 32; break; + /* Enhanced Power Management Register */ case 0xc0000086: if (cpu_s->cpu_type < CPU_K6_2P) goto amd_k_invalid_rdmsr; @@ -2736,6 +2873,7 @@ cpu_RDMSR(void) EAX = msr.amd_epmr & 0xffffffff; EDX = msr.amd_epmr >> 32; break; + /* Processor State Observability Register */ case 0xc0000087: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2743,6 +2881,7 @@ cpu_RDMSR(void) EAX = msr.amd_psor & 0xffffffff; EDX = msr.amd_psor >> 32; break; + /* Page Flush/Invalidate Register */ case 0xc0000088: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2750,6 +2889,7 @@ cpu_RDMSR(void) EAX = msr.amd_pfir & 0xffffffff; EDX = msr.amd_pfir >> 32; break; + /* Level-2 Cache Array Access Register */ case 0xc0000089: if (cpu_s->cpu_type < CPU_K6_3) goto amd_k_invalid_rdmsr; @@ -2767,52 +2907,253 @@ amd_k_invalid_rdmsr: 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) -#endif - EAX = EDX = 0; - switch (ECX) { - case 0x00: - case 0x01: + EAX = EDX = 0; + /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per: + Ralf Brown, Pentium Model-Specific Registers and What They Reveal. + https://www.cs.cmu.edu/~ralf/papers/highmsr.html + But leave the bit 31 intact to be able to handle both low and high + MSRs in a single switch block. */ + switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) { + /* Machine Check Exception Address */ + case 0x00000000: + case 0x80000000: + EAX = msr.mcar & 0xffffffff; + EDX = msr.mcar >> 32; break; - case 0x10: + /* Machine Check Exception Type */ + case 0x00000001: + case 0x80000001: + EAX = msr.mctr & 0xffffffff; + EDX = msr.mctr >> 32; + msr.mctr &= ~0x1; /* clear the machine check pending bit */ + break; + /* TR1 - Parity Reversal Test Register */ + case 0x00000002: + case 0x80000002: + EAX = msr.tr1; + break; + /* TR2 - Instruction Cache End Bit */ + case 0x00000004: + case 0x80000004: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + goto pentium_invalid_rdmsr; + EAX = msr.tr2; + break; + /* TR3 - Cache Test Data */ + case 0x00000005: + case 0x80000005: + EAX = msr.tr3; + break; + /* TR4 - Cache Test Tag */ + case 0x00000006: + case 0x80000006: + EAX = msr.tr4; + break; + /* TR5 - Cache Test Control */ + case 0x00000007: + case 0x80000007: + EAX = msr.tr5; + break; + /* TR6 - TLB Test Command */ + case 0x00000008: + case 0x80000008: + EAX = msr.tr6; + break; + /* TR7 - TLB Test Data */ + case 0x00000009: + case 0x80000009: + EAX = msr.tr7; + break; + /* TR9 - Branch Target Buffer Tag */ + case 0x0000000b: + case 0x8000000b: + EAX = msr.tr9; + break; + /* TR10 - Branch Target Buffer Target */ + case 0x0000000c: + case 0x8000000c: + EAX = msr.tr10; + break; + /* TR11 - Branch Target Buffer Control */ + case 0x0000000d: + case 0x8000000d: + EAX = msr.tr11; + break; + /* TR12 - New Feature Control */ + case 0x0000000e: + case 0x8000000e: + EAX = msr.tr12; + break; + /* Time Stamp Counter */ + case 0x00000010: + case 0x80000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ + case 0x00000011: + case 0x80000011: + EAX = msr.cesr; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x00000012: + case 0x80000012: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x00000013: + case 0x80000013: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + /* Unknown */ + case 0x00000014: + case 0x80000014: + if ((CPUID & 0xfff) <= 0x520) + goto pentium_invalid_rdmsr; + break; + /* Unknown, possibly paging-related; initial value is 0004h, + becomes 0008h once paging is enabled */ + case 0x80000018: + EAX = ((cr0 & (1 << 31)) ? 0x00000008 : 0x00000004); + break; + /* Floating point - last prefetched opcode + bits 10-8: low three bits of first byte of FP instruction + bits 7-0: second byte of floating-point instruction */ + case 0x80000019: + EAX = 0; + break; + /* Floating point - last executed non-control opcode */ + case 0x8000001a: + EAX = 0; + break; + /* Floating point - last non-control exception opcode - part + of FSTENV/FSAVE'd environment */ + case 0x8000001b: + EAX = msr.fp_last_xcpt; + break; + /* Unknown */ + case 0x8000001c: + EAX = 0x00000004; + break; + /* Probe Mode Control */ + case 0x8000001d: + EAX = msr.probe_ctl; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001e: + EAX = msr.ecx8000001e; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001f: + EAX = msr.ecx8000001f; + break; + /* Reserved/Unimplemented */ + case 0x80000003: + case 0x8000000a: + case 0x8000000f: + case 0x80000015 ... 0x80000017: + EAX = (ECX & 0x1f) * 2; + break; + default: +pentium_invalid_rdmsr: + cpu_log("RDMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + 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; +#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: switch (ECX) { - case 0x00: - case 0x01: + /* Test Data */ + case 0x03: + EAX = msr.tr3; break; + /* Test Address */ + case 0x04: + EAX = msr.tr4; + break; + /* Test Command/Status */ + case 0x05: + EAX = msr.tr5; + break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ + case 0x11: + EAX = msr.cesr; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + } + cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + break; +#endif + + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: + EAX = EDX = 0; + /* Per RichardG's probing of a real Deschutes using my RDMSR tool, + we have discovered that the top 18 bits are filtered out. */ + switch (ECX & 0x00003fff) { + /* Machine Check Exception Address */ + case 0x00: + /* Machine Check Exception Type */ + case 0x01: + break; + /* Time Stamp Counter */ + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + /* IA32_PLATFORM_ID - Platform ID */ case 0x17: - if (cpu_s->cpu_type != CPU_PENTIUM2D) + if (cpu_s->cpu_type < CPU_PENTIUM2D) goto i686_invalid_rdmsr; if (cpu_f->package == CPU_PKG_SLOT2) - EDX |= 0x80000; + EDX |= (1 << 19); else if (cpu_f->package == CPU_PKG_SOCKET370) - EDX |= 0x100000; + EDX |= (1 << 20); break; + /* Unknown */ + case 0x18: + break; + /* IA32_APIC_BASE - APIC Base Address */ case 0x1B: EAX = msr.apic_base & 0xffffffff; EDX = msr.apic_base >> 32; cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX); break; + /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */ + case 0x20: + EAX = msr.ecx20 & 0xffffffff; + EDX = msr.ecx20 >> 32; + break; + /* Unknown */ + case 0x21: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: EAX = 0xc4000000; EDX = 0; @@ -2847,47 +3188,85 @@ amd_k_invalid_rdmsr: EAX |= (1 << 19); } break; + /* Unknown */ + case 0x32: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* TEST_CTL - Test Control Register */ + case 0x33: + EAX = msr.test_ctl; + break; + /* Unknown */ + case 0x34: + case 0x3a: + case 0x3b: + case 0x50 ... 0x54: + break; + /* BIOS_UPDT_TRIG - BIOS Update Trigger */ case 0x79: - EAX = msr.ecx79 & 0xffffffff; - EDX = msr.ecx79 >> 32; + EAX = msr.bios_updt & 0xffffffff; + EDX = msr.bios_updt >> 32; break; - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff; - EDX = msr.ecx8x[ECX - 0x88] >> 32; + /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register + 8Bh: BIOS_SIGN - BIOS Update Signature */ + case 0x88 ... 0x8b: + EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff; + EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32; break; + /* Unknown */ + case 0xae: + break; + /* PERFCTR0 - Performance Counter Register 0 */ case 0xc1: + /* PERFCTR1 - Performance Counter Register 1 */ 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; + EAX = msr.perfctr[ECX - 0xC1] & 0xffffffff; + EDX = msr.perfctr[ECX - 0xC1] >> 32; break; + /* MTRRcap */ case 0xfe: EAX = msr.mtrr_cap & 0xffffffff; EDX = msr.mtrr_cap >> 32; break; + /* BBL_CR_ADDR - L2 Cache Address Register */ case 0x116: - EAX = msr.ecx116 & 0xffffffff; - EDX = msr.ecx116 >> 32; + EAX = msr.bbl_cr_addr & 0xffffffff; + EDX = msr.bbl_cr_addr >> 32; break; + /* BBL_CR_DECC - L2 Cache Date ECC Register */ case 0x118: + EAX = msr.bbl_cr_decc & 0xffffffff; + EDX = msr.bbl_cr_decc >> 32; + break; + /* BBL_CR_CTL - L2 Cache Control Register */ case 0x119: + EAX = msr.bbl_cr_ctl & 0xffffffff; + EDX = msr.bbl_cr_ctl >> 32; + break; + /* BBL_CR_TRIG - L2 Cache Trigger Register */ case 0x11a: + EAX = msr.bbl_cr_trig & 0xffffffff; + EDX = msr.bbl_cr_trig >> 32; + break; + /* BBL_CR_BUSY - L2 Cache Busy Register */ case 0x11b: - EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff; - EDX = msr.ecx11x[ECX - 0x118] >> 32; + EAX = msr.bbl_cr_busy & 0xffffffff; + EDX = msr.bbl_cr_busy >> 32; break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ case 0x11e: - EAX = msr.ecx11e & 0xffffffff; - EDX = msr.ecx11e >> 32; + EAX = msr.bbl_cr_ctl3 & 0xffffffff; + EDX = msr.bbl_cr_ctl3 >> 32; break; + /* Unknown */ + case 0x131: + case 0x14e ... 0x151: + case 0x154: + case 0x15b: + case 0x15f: + break; + /* SYSENTER_CS - SYSENTER target CS */ case 0x174: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2896,6 +3275,7 @@ amd_k_invalid_rdmsr: EAX |= msr.sysenter_cs; EDX = 0x00000000; break; + /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2903,6 +3283,7 @@ amd_k_invalid_rdmsr: EAX = msr.sysenter_esp; EDX = 0x00000000; break; + /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2910,48 +3291,49 @@ amd_k_invalid_rdmsr: EAX = msr.sysenter_eip; EDX = 0x00000000; break; + /* MCG_CAP - Machine Check Global Capability */ case 0x179: EAX = 0x00000105; EDX = 0x00000000; break; + /* MCG_STATUS - Machine Check Global Status */ case 0x17a: break; + /* MCG_CTL - Machine Check Global Control */ case 0x17b: EAX = msr.mcg_ctl & 0xffffffff; EDX = msr.mcg_ctl >> 32; break; + /* EVNTSEL0 - Performance Counter Event Select 0 */ case 0x186: - EAX = msr.ecx186 & 0xffffffff; - EDX = msr.ecx186 >> 32; - break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ case 0x187: - EAX = msr.ecx187 & 0xffffffff; - EDX = msr.ecx187 >> 32; + EAX = msr.evntsel[ECX - 0x186] & 0xffffffff; + EDX = msr.evntsel[ECX - 0x186] >> 32; break; + /* Unknown */ + case 0x1d3: + break; + /* DEBUGCTLMSR - Debugging Control Register */ case 0x1d9: - EAX = msr.debug_ctl & 0xffffffff; - EDX = msr.debug_ctl >> 32; + EAX = msr.debug_ctl; break; + /* LASTBRANCHFROMIP - address from which a branch was last taken */ + case 0x1db: + /* LASTBRANCHTOIP - destination address of the last taken branch instruction */ + case 0x1dc: + /* LASTINTFROMIP - address at which an interrupt last occurred */ + case 0x1dd: + /* LASTINTTOIP - address to which the last interrupt caused a branch */ + case 0x1de: + break; + /* ROB_CR_BKUPTMPDR6 */ case 0x1e0: - EAX = msr.ecx1e0 & 0xffffffff; - EDX = msr.ecx1e0 >> 32; + EAX = msr.rob_cr_bkuptmpdr6; 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: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) { EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; @@ -2960,75 +3342,87 @@ amd_k_invalid_rdmsr: EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; } break; + /* MTRRfix64K_00000 */ case 0x250: EAX = msr.mtrr_fix64k_8000 & 0xffffffff; EDX = msr.mtrr_fix64k_8000 >> 32; break; + /* MTRRfix16K_80000 */ case 0x258: EAX = msr.mtrr_fix16k_8000 & 0xffffffff; EDX = msr.mtrr_fix16k_8000 >> 32; break; + /* MTRRfix16K_A0000 */ 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: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; break; + /* Page Attribute Table */ case 0x277: + if (cpu_s->cpu_type < CPU_PENTIUM2D) + goto i686_invalid_rdmsr; EAX = msr.pat & 0xffffffff; EDX = msr.pat >> 32; break; + /* Unknown */ + case 0x280: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* MTRRdefType */ case 0x2ff: EAX = msr.mtrr_deftype & 0xffffffff; EDX = msr.mtrr_deftype >> 32; break; + /* MC0_CTL - Machine Check 0 Control */ case 0x400: + /* MC1_CTL - Machine Check 1 Control */ case 0x404: + /* MC2_CTL - Machine Check 2 Control */ case 0x408: + /* MC4_CTL - Machine Check 4 Control */ case 0x40c: + /* MC3_CTL - Machine Check 3 Control */ case 0x410: EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff; EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32; break; + /* MC0_STATUS - Machine Check 0 Status */ case 0x401: + /* MC0_ADDR - Machine Check 0 Address */ case 0x402: + /* MC1_STATUS - Machine Check 1 Status */ case 0x405: + /* MC1_ADDR - Machine Check 1 Address */ case 0x406: - case 0x407: + /* MC2_STATUS - Machine Check 2 Status */ case 0x409: + /* MC2_ADDR - Machine Check 2 Address */ + case 0x40a: + /* MC4_STATUS - Machine Check 4 Status */ case 0x40d: + /* MC4_ADDR - Machine Check 4 Address */ case 0x40e: + /* MC3_STATUS - Machine Check 3 Status */ case 0x411: + /* MC3_ADDR - Machine Check 3 Address */ case 0x412: break; + /* Unknown */ 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; + /* Unknown, possibly debug registers? */ + case 0x1000 ... 0x1007: + /* Unknown, possibly control registers? */ + case 0x2000: + case 0x2002 ... 0x2004: break; default: i686_invalid_rdmsr: @@ -3051,38 +3445,59 @@ cpu_WRMSR(void) switch (cpu_s->cpu_type) { case CPU_IBM386SLC: - case CPU_IBM486BL: case CPU_IBM486SLC: + case CPU_IBM486BL: switch (ECX) { + /* Processor Operation Register */ case 0x1000: msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); cpu_cache_int_enabled = (EAX & (1 << 7)); break; + /* Cache Region Control Register */ case 0x1001: - msr.ibm_crcr = EAX & 0xffffffffff; + msr.ibm_crcr = EAX | ((uint64_t) (EDX & 0x0000ffff) << 32); break; + /* Processor Operation Register */ case 0x1002: if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) msr.ibm_por2 = EAX & 0x3f000000; break; + /* Processor Control Register */ + case 0x1004: + if (cpu_s->cpu_type > CPU_IBM486SLC) + msr.ibm_pcr = EAX & 0x00d6001a; + break; } break; case CPU_WINCHIP: case CPU_WINCHIP2: switch (ECX) { + /* Pentium Processor Parity Reversal Register */ case 0x02: msr.tr1 = EAX & 2; break; + /* Pentium Processor New Feature Control */ case 0x0e: - msr.tr12 = EAX & 0x228; + msr.tr12 = EAX & 0x248; break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* Performance Monitor - Control and Event Select */ case 0x11: msr.cesr = EAX & 0xff00ff; break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Feature Control Register */ case 0x107: msr.fcr = EAX; if (EAX & (1 << 9)) @@ -3102,23 +3517,67 @@ cpu_WRMSR(void) else CPUID = cpu_s->cpuid_model; break; + /* Feature Control Register 2 */ case 0x108: msr.fcr2 = EAX | ((uint64_t) EDX << 32); break; + /* Feature Control Register 3 */ case 0x109: msr.fcr3 = EAX | ((uint64_t) EDX << 32); break; + /* Memory Configuration Register 0..7 */ + case 0x110 ... 0x117: + temp = ECX - 0x110; + if (cpu_s->cpu_type == CPU_WINCHIP2) { + if (EAX & 0x1f) + msr.mcr_ctrl |= (1 << (temp + 9)); + else + msr.mcr_ctrl &= ~(1 << (temp + 9)); + } + msr.mcr[temp] = EAX | ((uint64_t) EDX << 32); + break; + /* Memory Configuration Register Control */ + case 0x120: + msr.mcr_ctrl = EAX & ((cpu_s->cpu_type == CPU_WINCHIP2) ? 0x1df : 0x1f); + break; + /* Unknown */ + case 0x131: + case 0x142 ... 0x145: + case 0x147: + case 0x150: + case 0x151: + break; } break; case CPU_CYRIX3S: switch (ECX) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */ + case 0xc1: + break; + /* PERFCTR0 - Performance Counter Register 1 */ + case 0xc2: + msr.perfctr[1] = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ + case 0x11e: + /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */ + case 0x186: + break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ + case 0x187: + msr.evntsel[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Feature Control Register */ case 0x1107: msr.fcr = EAX; if (EAX & (1 << 1)) @@ -3130,52 +3589,39 @@ cpu_WRMSR(void) else cpu_CR4_mask &= ~CR4_PGE; break; + /* Feature Control Register 2 */ case 0x1108: msr.fcr2 = EAX | ((uint64_t) EDX << 32); break; + /* Feature Control Register 3 */ 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: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 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; + /* MTRRfix64K_00000 */ case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_80000 */ case 0x258: msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_A0000 */ 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: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRdefType */ case 0x2ff: msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); break; @@ -3193,18 +3639,47 @@ cpu_WRMSR(void) case CPU_K6_2P: case CPU_K6_3P: switch (ECX) { - case 0x00: - case 0x01: + /* Machine Check Address Register */ + case 0x00000000: + if (cpu_s->cpu_type > CPU_5K86) + msr.mcar = EAX | ((uint64_t) EDX << 32); break; - case 0x0e: - msr.tr12 = EAX & 0x228; + /* Machine Check Type Register */ + case 0x00000001: + if (cpu_s->cpu_type > CPU_5K86) + msr.mctr = EAX | ((uint64_t) EDX << 32); break; - case 0x10: + /* Test Register 12 */ + case 0x0000000e: + msr.tr12 = EAX & 0x8; + break; + /* Time Stamp Counter */ + case 0x00000010: tsc = EAX | ((uint64_t) EDX << 32); break; - case 0x83: - msr.ecx83 = EAX | ((uint64_t) EDX << 32); + /* Array Access Register */ + case 0x00000082: + if (cpu_s->cpu_type > CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_aar = EAX | ((uint64_t) EDX << 32); break; + /* Hardware Configuration Register */ + case 0x00000083: + msr.amd_hwcr = EAX | ((uint64_t) EDX << 32); + break; + /* Write Allocate Top-of-Memory and Control Register */ + case 0x00000085: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_watmcr = EAX | ((uint64_t) EDX << 32); + break; + /* Write Allocate Programmable Memory Range Register */ + case 0x00000086: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_wapmrr = EAX | ((uint64_t) EDX << 32); + break; + /* Extended Feature Enable Register */ case 0xc0000080: temp = EAX | ((uint64_t) EDX << 32); if (temp & ~1ULL) @@ -3212,39 +3687,46 @@ cpu_WRMSR(void) else msr.amd_efer = temp; break; + /* SYSCALL Target Address Register */ case 0xc0000081: if (cpu_s->cpu_type < CPU_K6_2) goto amd_k_invalid_wrmsr; - msr.star = EAX | ((uint64_t) EDX << 32); + msr.amd_star = EAX | ((uint64_t) EDX << 32); break; + /* Write-Handling Control Register */ case 0xc0000082: msr.amd_whcr = EAX | ((uint64_t) EDX << 32); break; + /* UC/WC Cacheability Control Register */ case 0xc0000085: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_uwccr = EAX | ((uint64_t) EDX << 32); break; + /* Enhanced Power Management Register */ case 0xc0000086: if (cpu_s->cpu_type < CPU_K6_2P) goto amd_k_invalid_wrmsr; msr.amd_epmr = EAX | ((uint64_t) EDX << 32); break; + /* Processor State Observability Register */ case 0xc0000087: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_psor = EAX | ((uint64_t) EDX << 32); break; + /* Page Flush/Invalidate Register */ case 0xc0000088: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_pfir = EAX | ((uint64_t) EDX << 32); break; + /* Level-2 Cache Array Access Register */ case 0xc0000089: if (cpu_s->cpu_type < CPU_K6_3) goto amd_k_invalid_wrmsr; @@ -3261,206 +3743,430 @@ amd_k_invalid_wrmsr: case CPU_P24T: case CPU_PENTIUM: case CPU_PENTIUMMMX: + cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per: + Ralf Brown, Pentium Model-Specific Registers and What They Reveal. + https://www.cs.cmu.edu/~ralf/papers/highmsr.html + But leave the bit 31 intact to be able to handle both low and high + MSRs in a single switch block. */ + switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) { + /* Machine Check Exception Address */ + case 0x00000000: + case 0x80000000: + /* Machine Check Exception Type */ + case 0x00000001: + case 0x80000001: + break; + /* TR1 - Parity Reversal Test Register */ + case 0x00000002: + case 0x80000002: + msr.tr1 = EAX & 0x3fff; + break; + /* TR2 - Instruction Cache End Bit */ + case 0x00000004: + case 0x80000004: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + goto pentium_invalid_wrmsr; + msr.tr2 = EAX & 0xf; + break; + /* TR3 - Cache Test Data */ + case 0x00000005: + case 0x80000005: + msr.tr3 = EAX; + break; + /* TR4 - Cache Test Tag */ + case 0x00000006: + case 0x80000006: + msr.tr4 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffff1f : 0xffffff07); + break; + /* TR5 - Cache Test Control */ + case 0x00000007: + case 0x80000007: + msr.tr5 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0x87fff : 0x7fff); + break; + /* TR6 - TLB Test Command */ + case 0x00000008: + case 0x80000008: + msr.tr6 = EAX & 0xffffff07; + break; + /* TR7 - TLB Test Data */ + case 0x00000009: + case 0x80000009: + msr.tr7 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xfffffc7f : 0xffffff9c); + break; + /* TR9 - Branch Target Buffer Tag */ + case 0x0000000b: + case 0x8000000b: + msr.tr9 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffffff : 0xffffffc3); + break; + /* TR10 - Branch Target Buffer Target */ + case 0x0000000c: + case 0x8000000c: + msr.tr10 = EAX; + break; + /* TR11 - Branch Target Buffer Control */ + case 0x0000000d: + case 0x8000000d: + msr.tr11 = EAX & ((cpu_s->cpu_type >= CPU_PENTIUMMMX) ? 0x3001fcf : 0xfcf); + break; + /* TR12 - New Feature Control */ + case 0x0000000e: + case 0x8000000e: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + temp = EAX & 0x38034f; + else if ((CPUID & 0xfff) >= 0x52b) + temp = EAX & 0x20435f; + else if ((CPUID & 0xfff) >= 0x520) + temp = EAX & 0x20035f; + else + temp = EAX & 0x20030f; + msr.tr12 = temp; + break; + /* Time Stamp Counter */ + case 0x00000010: + case 0x80000010: + tsc = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Control and Event Select */ + case 0x00000011: + case 0x80000011: + msr.cesr = EAX & 0x3ff03ff; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x00000012: + case 0x80000012: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x00000013: + case 0x80000013: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Unknown */ + case 0x00000014: + case 0x80000014: + if ((CPUID & 0xfff) <= 0x520) + goto pentium_invalid_wrmsr; + break; + /* Unknown, possibly paging-related; initial value is 0004h, + becomes 0008h once paging is enabled */ + case 0x80000018: + /* Floating point - last prefetched opcode + bits 10-8: low three bits of first byte of FP instruction + bits 7-0: second byte of floating-point instruction */ + case 0x80000019: + /* Floating point - last executed non-control opcode */ + case 0x8000001a: + break; + /* Floating point - last non-control exception opcode - part + of FSTENV/FSAVE'd environment */ + case 0x8000001b: + EAX = msr.fp_last_xcpt & 0x7ff; + break; + /* Unknown */ + case 0x8000001c: + break; + /* Probe Mode Control */ + case 0x8000001d: + EAX = msr.probe_ctl & 0x7; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001e: + msr.ecx8000001e = EAX; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001f: + msr.ecx8000001f = EAX; + break; + /* Reserved/Unimplemented */ + case 0x80000003: + case 0x8000000a: + case 0x8000000f: + case 0x80000015 ... 0x80000017: + break; + default: +pentium_invalid_wrmsr: + cpu_log("WRMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + break; + } + break; + #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) 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; + /* Test Data */ + case 0x03: + msr.tr3 = EAX; + /* Test Address */ + case 0x04: + msr.tr4 = EAX; + /* Test Command/Status */ + case 0x05: + msr.tr5 = EAX & 0x008f0f3b; + /* Time Stamp Counter */ 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) { -#endif - 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 + /* Performance Monitor - Control and Event Select */ + case 0x11: + msr.cesr = EAX & 0x7ff07ff; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); break; } break; +#endif case CPU_PENTIUMPRO: case CPU_PENTIUM2: case CPU_PENTIUM2D: - switch (ECX) { + /* Per RichardG's probing of a real Deschutes using my RDMSR tool, + we have discovered that the top 18 bits are filtered out. */ + switch (ECX & 0x00003fff) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: if (EAX || EDX) x86gpf(NULL, 0); break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x18: + break; + /* IA32_APIC_BASE - APIC Base Address */ case 0x1b: cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX); #if 0 msr.apic_base = EAX | ((uint64_t) EDX << 32); #endif break; + /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */ + case 0x20: + msr.ecx20 = EAX | ((uint64_t) EDX << 32); + break; + /* Unknown */ + case 0x21: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: break; + /* Unknown */ + case 0x32: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* TEST_CTL - Test Control Register */ + case 0x33: + msr.test_ctl = EAX; + break; + /* Unknown */ + case 0x34: + case 0x3a: + case 0x3b: + case 0x50 ... 0x54: + break; + /* BIOS_UPDT_TRIG - BIOS Update Trigger */ case 0x79: - msr.ecx79 = EAX | ((uint64_t) EDX << 32); + msr.bios_updt = EAX | ((uint64_t) EDX << 32); break; - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t) EDX << 32); + /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register + 8Bh: BIOS_SIGN - BIOS Update Signature */ + case 0x88 ... 0x8b: + msr.bbl_cr_dx[ECX - 0x88] = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0xae: + break; + /* PERFCTR0 - Performance Counter Register 0 */ case 0xc1: + /* PERFCTR1 - Performance Counter Register 1 */ case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32); + msr.perfctr[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRcap */ case 0xfe: msr.mtrr_cap = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_ADDR - L2 Cache Address Register */ case 0x116: - msr.ecx116 = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_addr = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_DECC - L2 Cache Date ECC Register */ case 0x118: + msr.bbl_cr_decc = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_CTL - L2 Cache Control Register */ case 0x119: + msr.bbl_cr_ctl = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_TRIG - L2 Cache Trigger Register */ case 0x11a: + msr.bbl_cr_trig = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_BUSY - L2 Cache Busy Register */ case 0x11b: - msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_busy = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ case 0x11e: - msr.ecx11e = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x131: + case 0x14e ... 0x151: + case 0x154: + case 0x15b: + case 0x15f: + break; + /* SYSENTER_CS - SYSENTER target CS */ case 0x174: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_cs = EAX & 0xFFFF; break; + /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_esp = EAX; break; + /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_eip = EAX; break; + /* MCG_CAP - Machine Check Global Capability */ case 0x179: break; + /* MCG_STATUS - Machine Check Global Status */ case 0x17a: if (EAX || EDX) x86gpf(NULL, 0); break; + /* MCG_CTL - Machine Check Global Control */ case 0x17b: msr.mcg_ctl = EAX | ((uint64_t) EDX << 32); break; + /* EVNTSEL0 - Performance Counter Event Select 0 */ case 0x186: - msr.ecx186 = EAX | ((uint64_t) EDX << 32); - break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ case 0x187: - msr.ecx187 = EAX | ((uint64_t) EDX << 32); + msr.evntsel[ECX - 0x186] = EAX | ((uint64_t) EDX << 32); break; + case 0x1d3: + break; + /* DEBUGCTLMSR - Debugging Control Register */ case 0x1d9: - msr.debug_ctl = EAX | ((uint64_t) EDX << 32); + msr.debug_ctl = EAX; break; + /* ROB_CR_BKUPTMPDR6 */ case 0x1e0: - msr.ecx1e0 = EAX | ((uint64_t) EDX << 32); + msr.rob_cr_bkuptmpdr6 = EAX; 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: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 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; + /* MTRRfix64K_00000 */ case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_80000 */ case 0x258: msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_A0000 */ 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: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); break; + /* Page Attribute Table */ case 0x277: + if (cpu_s->cpu_type < CPU_PENTIUM2D) + goto i686_invalid_wrmsr; msr.pat = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x280: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* MTRRdefType */ case 0x2ff: msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); break; + /* MC0_CTL - Machine Check 0 Control */ case 0x400: + /* MC1_CTL - Machine Check 1 Control */ case 0x404: + /* MC2_CTL - Machine Check 2 Control */ case 0x408: + /* MC4_CTL - Machine Check 4 Control */ case 0x40c: + /* MC3_CTL - Machine Check 3 Control */ case 0x410: msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t) EDX << 32); break; + /* MC0_STATUS - Machine Check 0 Status */ case 0x401: + /* MC0_ADDR - Machine Check 0 Address */ case 0x402: + /* MC1_STATUS - Machine Check 1 Status */ case 0x405: + /* MC1_ADDR - Machine Check 1 Address */ case 0x406: - case 0x407: + /* MC2_STATUS - Machine Check 2 Status */ case 0x409: + /* MC2_ADDR - Machine Check 2 Address */ + case 0x40a: + /* MC4_STATUS - Machine Check 4 Status */ case 0x40d: + /* MC4_ADDR - Machine Check 4 Address */ case 0x40e: + /* MC3_STATUS - Machine Check 3 Status */ case 0x411: + /* MC3_ADDR - Machine Check 3 Address */ case 0x412: if (EAX || EDX) x86gpf(NULL, 0); break; + /* Unknown */ 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); + /* Unknown, possibly debug registers? */ + case 0x1000 ... 0x1007: + /* Unknown, possibly control registers? */ + case 0x2000: + case 0x2002 ... 0x2004: break; default: i686_invalid_wrmsr: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9bdcca84c..900d3d7e1 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -86,42 +86,33 @@ enum { }; enum { - 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) + 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_386DX_DESKPRO386 = (1 << 8), + CPU_PKG_M6117 = (1 << 9), + CPU_PKG_386SLC_IBM = (1 << 10), + CPU_PKG_486SLC = (1 << 11), + CPU_PKG_486SLC_IBM = (1 << 12), + CPU_PKG_486BL = (1 << 13), + CPU_PKG_486DLC = (1 << 14), + CPU_PKG_SOCKET1 = (1 << 15), + CPU_PKG_SOCKET3 = (1 << 16), + CPU_PKG_SOCKET3_PC330 = (1 << 17), + CPU_PKG_STPC = (1 << 18), + CPU_PKG_SOCKET4 = (1 << 19), + CPU_PKG_SOCKET5_7 = (1 << 20), + CPU_PKG_SOCKET8 = (1 << 21), + CPU_PKG_SLOT1 = (1 << 22), + CPU_PKG_SLOT2 = (1 << 23), + CPU_PKG_SOCKET370 = (1 << 24) }; -#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 #define CPU_ALTERNATE_XTAL 4 @@ -165,17 +156,6 @@ typedef struct { const CPU *cpus; } cpu_family_t; -typedef struct { - const char *family; - const uint32_t rspeed; - const double multi; -} cpu_legacy_table_t; - -typedef struct { - 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 @@ -194,6 +174,7 @@ typedef struct { #define VIP_FLAG 0x0010 /* in EFLAGS */ #define VID_FLAG 0x0020 /* in EFLAGS */ +#define EM_FLAG 0x00004 /* in CR0 */ #define WP_FLAG 0x10000 /* in CR0 */ #define CR4_VME (1 << 0) /* Virtual 8086 Mode Extensions */ @@ -246,103 +227,97 @@ typedef union { } MMX_REG; typedef struct { - /* IDT WinChip and WinChip 2 MSR's */ - uint32_t tr1; /* 0x00000002, 0x0000000e */ - uint32_t tr12; /* 0x00000002, 0x0000000e */ - uint32_t cesr; /* 0x00000011 */ + /* IBM 386SLC/486SLC/486BL MSRs */ + uint64_t ibm_por; /* 0x00001000 - 386SLC and later */ + uint64_t ibm_crcr; /* 0x00001001 - 386SLC and later */ + uint64_t ibm_por2; /* 0x00001002 - 486SLC and later */ + uint64_t ibm_pcr; /* 0x00001004 - 486BL3 */ - /* 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 */ + /* IDT WinChip C6/2/VIA Cyrix III MSRs */ + uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */ + uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint64_t mcr[8]; /* 0x00000110 - 0x00000117 (IDT) */ + uint32_t mcr_ctrl; /* 0x00000120 (IDT) */ - /* 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. */ + /* AMD K5/K6 MSRs */ + uint64_t amd_aar; /* 0x00000082 - all K5 */ + uint64_t amd_hwcr; /* 0x00000083 - all K5 and all K6 */ + uint64_t amd_watmcr; /* 0x00000085 - K5 Model 1 and later */ + uint64_t amd_wapmrr; /* 0x00000086 - K5 Model 1 and later */ - /* 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 amd_efer; /* 0xc0000080 - all K5 and all K6 */ + uint64_t amd_star; /* 0xc0000081 - K6-2 and later */ + uint64_t amd_whcr; /* 0xc0000082 - all K5 and all K6 */ + uint64_t amd_uwccr; /* 0xc0000085 - K6-2C and later */ + uint64_t amd_epmr; /* 0xc0000086 - K6-III+/2+ only */ + uint64_t amd_psor; /* 0xc0000087 - K6-2C and later */ + uint64_t amd_pfir; /* 0xc0000088 - K6-2C and later */ + uint64_t amd_l2aar; /* 0xc0000089 - K6-III and later */ - /* 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; /* 0x00000108 (IDT), 0x00001108 (VIA) */ - uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + /* Pentium/Pentium MMX MSRs */ + uint64_t mcar; /* 0x00000000 - also on K5 and (R/W) K6 */ + uint64_t mctr; /* 0x00000001 - also on K5 and (R/W) K6 */ + uint32_t tr1; /* 0x00000002 - also on WinChip C6/2 */ + uint32_t tr2; /* 0x00000004 - reserved on PMMX */ + uint32_t tr3; /* 0x00000005 */ + uint32_t tr4; /* 0x00000006 */ + uint32_t tr5; /* 0x00000007 */ + uint32_t tr6; /* 0x00000008 */ + uint32_t tr7; /* 0x00000009 */ + uint32_t tr9; /* 0x0000000b */ + uint32_t tr10; /* 0x0000000c */ + uint32_t tr11; /* 0x0000000d */ + uint32_t tr12; /* 0x0000000e - also on WinChip C6/2 and K6 */ + uint32_t cesr; /* 0x00000011 - also on WinChip C6/2 and Cx6x86MX */ + uint64_t pmc[2]; /* 0x00000012, 0x00000013 - also on WinChip C6/2 and Cx6x86MX */ + uint32_t fp_last_xcpt; /* 0x8000001b - undocumented */ + uint32_t probe_ctl; /* 0x8000001d - undocumented */ + uint32_t ecx8000001e; /* 0x8000001e - undocumented */ + uint32_t ecx8000001f; /* 0x8000001f - undocumented */ - /* 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 */ + /* Pentium Pro/II MSRs */ + uint64_t apic_base; /* 0x0000001b */ + uint32_t test_ctl; /* 0x00000033 */ + uint64_t bios_updt; /* 0x00000079 */ - /* 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 */ + uint64_t bbl_cr_dx[4]; /* 0x00000088 - 0x0000008b */ + uint64_t perfctr[2]; /* 0x000000c1, 0x000000c2 */ + uint64_t mtrr_cap; /* 0x000000fe */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */ - uint64_t ecx186; /* 0x00000186, 0x00000187 */ - uint64_t ecx187; /* 0x00000186, 0x00000187 */ + uint64_t bbl_cr_addr; /* 0x00000116 */ + uint64_t bbl_cr_decc; /* 0x00000118 */ + uint64_t bbl_cr_ctl; /* 0x00000119 */ + uint64_t bbl_cr_trig; /* 0x0000011a */ + uint64_t bbl_cr_busy; /* 0x0000011b */ + uint64_t bbl_cr_ctl3; /* 0x0000011e */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */ - uint64_t ecx1e0; /* 0x000001e0 */ + uint16_t sysenter_cs; /* 0x00000174 - Pentium II and later */ + uint32_t sysenter_esp; /* 0x00000175 - Pentium II and later */ + uint32_t sysenter_eip; /* 0x00000176 - Pentium II and later */ - /* 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 mcg_ctl; /* 0x0000017b */ + uint64_t evntsel[2]; /* 0x00000186, 0x00000187 */ + + uint32_t debug_ctl; /* 0x000001d9 */ + uint32_t rob_cr_bkuptmpdr6; /* 0x000001e0 */ + + /* MTTR-related MSRs also present on the VIA Cyrix III */ + uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f (ECX & 0) */ 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_deftype; /* 0x000002ff */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - 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 */ - - /* 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 pat; /* 0x00000277 - Pentium II Deschutes and later */ + uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 */ 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 */ - - /* IBM 486SLC and 486BL MSR's */ - 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 */ - - /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_efer; /* 0xc0000080 */ - - /* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - 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 */ - - /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_uwccr; /* 0xc0000085 */ - - /* AMD K6-2P and K6-3P MSR's */ - uint64_t amd_epmr; /* 0xc0000086 */ - - /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - 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 */ - - /* 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 */ + /* Other/Unclassified MSRs */ + uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits + like a real Deschutes does. */ } msr_t; typedef struct { @@ -530,7 +505,6 @@ extern cpu_state_t cpu_state; extern fpu_state_t fpu_state; 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; @@ -544,8 +518,9 @@ 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 cpu_cyrix_alignment; /* Cyrix 5x86/6x86 only has data misalignment + penalties when crossing 8-byte boundaries. */ +extern int cpu_cpurst_on_sr; /* SiS 551x and 5571: Issue CPURST on soft reset. */ extern int is8086; extern int is186; @@ -608,7 +583,6 @@ 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; @@ -789,6 +763,11 @@ void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); #define SMHR_VALID (1 << 0) #define SMHR_ADDR_MASK (0xfffffffc) +typedef union { + uint32_t fd; + uint8_t b[4]; +} fetch_dat_t; + typedef struct { struct { uint32_t base; @@ -810,6 +789,7 @@ extern int hlt_reset_pending; extern cyrix_t cyrix; extern int prefetch_prefixes; +extern int cpu_use_exec; extern uint8_t use_custom_nmi_vector; extern uint32_t custom_nmi_vector; @@ -834,9 +814,24 @@ extern void nmi_raise(void); extern MMX_REG *MMP[8]; extern uint16_t *MMEP[8]; +extern int cpu_block_end; +extern int cpu_override_dynarec; + 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); +extern int lock_legal[256]; +extern int lock_legal_0f[256]; +extern int lock_legal_ba[8]; +extern int lock_legal_80[8]; +extern int lock_legal_f6[8]; +extern int lock_legal_fe[8]; + +extern int in_lock; +extern int cpu_override_interpreter; + +extern int is_lock_legal(uint32_t fetchdat); + #endif /*EMU_CPU_H*/ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 947804014..502b2c86e 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -1043,6 +1043,17 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { + .package = CPU_PKG_386DX_DESKPRO386, + .manufacturer = "Intel", + .name = "i386DX", + .internal_name = "i386dx_deskpro386", + .cpus = (const CPU[]) { + {"16", CPU_386DX, fpus_80286, 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}, + {"", 0} + } + }, { .package = CPU_PKG_386DX, .manufacturer = "Intel", .name = "RapidCAD", @@ -1070,8 +1081,8 @@ const cpu_family_t cpu_families[] = { .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}, + {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2309, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2309, 0, 0, 0, 7,7,3,3, 5}, {"", 0} } }, { @@ -1387,9 +1398,9 @@ const cpu_family_t cpu_families[] = { .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*/ + {"133 (P75)", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, + {"150 (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*/ + {"160 (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} } }, { @@ -1604,23 +1615,7 @@ const cpu_family_t cpu_families[] = { { .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)", + .name = "K5 (Model 0)", .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}, @@ -1628,6 +1623,19 @@ const cpu_family_t cpu_families[] = { {"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 (Model 1/2/3)", + .internal_name = "k5_5k86", + .cpus = (const CPU[]) { + {"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.7 (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} + } }, #endif { @@ -1763,12 +1771,12 @@ const cpu_family_t cpu_families[] = { .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}, + {"80 (PR90+)", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"100 (PR120+)", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"110 (PR133+)", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"120 (PR150+)", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"133 (PR166+)", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"150 (PR200+)", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, {"", 0} } }, { @@ -1777,10 +1785,10 @@ const cpu_family_t cpu_families[] = { .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}, + {"110 (PR133+)", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"120 (PR150+)", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"133 (PR166+)", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"150 (PR200+)", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, {"", 0} } }, { @@ -1789,10 +1797,10 @@ const cpu_family_t cpu_families[] = { .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}, + {"133 (PR166)", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"166 (PR200)", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"187.5 (PR233)", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"208.3 (PR266)", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, {"", 0} } }, { @@ -1801,11 +1809,11 @@ const cpu_family_t cpu_families[] = { .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}, + {"233 (PR300)", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"250/83 (PR333)", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, + {"250/100 (PR366)", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, + {"285 (PR400)", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, + {"300 (PR433)", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, {"", 0} } }, @@ -1972,957 +1980,3 @@ const cpu_family_t cpu_families[] = { } // 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} -}; - -static const cpu_legacy_table_t cpus_pcjr[] = { - {"8088", 4772728, 1}, - { 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} -}; - -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} -}; - -static const cpu_legacy_table_t cpus_pc1512[] = { - {"8086", 8000000, 1}, - { 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} -}; - -static const cpu_legacy_table_t cpus_ibmat[] = { - {"286", 6000000, 1}, - { "286", 8000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ibmxt286[] = { - {"286", 6000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ps1_m2011[] = { - {"286", 10000000, 1}, - { 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} -}; - -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} -}; - -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} -}; - -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} -}; - -static const cpu_legacy_table_t cpus_Am386DX[] = { - {"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} -}; - -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} -}; - -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} -}; - -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} -}; - -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} -}; - -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} -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -static const cpu_legacy_table_t cpus_STPCDX[] = { - {"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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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} -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 } -}; - -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 }, - { "super286c", 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/softfloat/softfloatx80.cc b/src/cpu/softfloat/softfloatx80.cc index 3ac3e61b3..fc2409601 100644 --- a/src/cpu/softfloat/softfloatx80.cc +++ b/src/cpu/softfloat/softfloatx80.cc @@ -23,6 +23,11 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ +#include +#include +#include <86box/86box.h> +#include "../cpu.h" + #include "softfloatx80.h" #include "softfloat-round-pack.h" #include "softfloat-macros.h" @@ -305,6 +310,18 @@ int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *s float_class_t aClass = floatx80_class(a); float_class_t bClass = floatx80_class(b); + if (fpu_type < FPU_287XL) { + if ((aClass == float_positive_inf) && (bClass == float_negative_inf)) + { + return float_relation_equal; + } + + if ((aClass == float_negative_inf) && (bClass == float_positive_inf)) + { + return float_relation_equal; + } + } + if (aClass == float_SNaN || bClass == float_SNaN) { /* unsupported reported as SNaN */ diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 93674ae5c..cf2867182 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -80,6 +80,8 @@ int hlt_reset_pending; int fpu_cycles = 0; +int in_lock = 0; + #ifdef ENABLE_X86_LOG void dumpregs(int); @@ -270,11 +272,19 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; + if (is386 && !is486 && (fpu_type == FPU_387)) + cr0 |= 0x10; cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; cgate32 = 0; + if (is386 && !is486) { + for (uint8_t i = 0; i < 4; i++) + dr[i] = 0x00000000; + dr[6] = 0xffff1ff0; + dr[7] = 0x00000400; + } if (is286) { if (is486) loadcs(0xF000); @@ -342,6 +352,10 @@ reset_common(int hard) if (!is286) reset_808x(hard); + + in_lock = 0; + + cpu_cpurst_on_sr = 0; } /* Hard reset. */ diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h new file mode 100644 index 000000000..ba34ae5e7 --- /dev/null +++ b/src/cpu/x86_ops_flag_2386.h @@ -0,0 +1,323 @@ +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; +} + +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; +} +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; +} +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; + } + } 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) +{ + 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) +{ + 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) +{ + 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)) { + 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_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; + + 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(); + rf_flag_no_clear = 1; + + 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_286(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; + + 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(); + rf_flag_no_clear = 1; + + 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 + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } + flags_extract(); + rf_flag_no_clear = 1; + + 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 +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; + + 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(); + rf_flag_no_clear = 1; + + 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; +#endif + + return 0; +} diff --git a/src/cpu/x86_ops_fpu_2386.h b/src/cpu/x86_ops_fpu_2386.h new file mode 100644 index 000000000..52c24d995 --- /dev/null +++ b/src/cpu/x86_ops_fpu_2386.h @@ -0,0 +1,113 @@ +/* Copyright holders: Sarah Walker + see COPYING for more details +*/ +static int +opESCAPE_d8_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int +opESCAPE_d8_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} + +static int +opESCAPE_d9_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_d9_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_d9_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_d9_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_da_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_da_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_da_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_da_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_db_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_db_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_db_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_db_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_dc_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int +opESCAPE_dc_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} + +static int +opESCAPE_dd_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_dd_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_dd_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_dd_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_de_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_de_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_de_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_de_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_df_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_df_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_df_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_df_a32[fetchdat & 0xff](fetchdat); +} + +static int +opWAIT(uint32_t fetchdat) +{ + 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; +} diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index e36fa4800..073327c9c 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -129,7 +129,7 @@ opF6_a16(uint32_t fetchdat) if (dst && !(tempw & 0xff00)) { AH = src16 % dst; AL = (src16 / dst) & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -149,7 +149,7 @@ opF6_a16(uint32_t fetchdat) if (dst && ((int) temps == tempws2)) { AH = (tempws % (int) ((int8_t) dst)) & 0xff; AL = tempws2 & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -246,7 +246,7 @@ opF6_a32(uint32_t fetchdat) if (dst && !(tempw & 0xff00)) { AH = src16 % dst; AL = (src16 / dst) & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -266,7 +266,7 @@ opF6_a32(uint32_t fetchdat) if (dst && ((int) temps == tempws2)) { AH = (tempws % (int) ((int8_t) dst)) & 0xff; AL = tempws2 & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -366,7 +366,7 @@ opF7_w_a16(uint32_t fetchdat) if (dst && !(templ2 & 0xffff0000)) { DX = templ % dst; AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -383,7 +383,7 @@ opF7_w_a16(uint32_t fetchdat) if ((dst != 0) && ((int) temps16 == tempws2)) { DX = tempws % (int) ((int16_t) dst); AX = tempws2 & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -479,7 +479,7 @@ opF7_w_a32(uint32_t fetchdat) if (dst && !(templ2 & 0xffff0000)) { DX = templ % dst; AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { // fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); @@ -497,7 +497,7 @@ opF7_w_a32(uint32_t fetchdat) if ((dst != 0) && ((int) temps16 == tempws2)) { DX = tempws % (int) ((int16_t) dst); AX = tempws2 & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -587,7 +587,7 @@ opF7_l_a16(uint32_t fetchdat) case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) 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); @@ -595,7 +595,7 @@ opF7_l_a16(uint32_t fetchdat) case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t) dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); @@ -680,7 +680,7 @@ opF7_l_a32(uint32_t fetchdat) case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) 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); @@ -688,7 +688,7 @@ opF7_l_a32(uint32_t fetchdat) case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t) dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); @@ -726,6 +726,25 @@ opHLT(uint32_t fetchdat) return 0; } +#ifdef OPS_286_386 +static int +opLOCK(uint32_t fetchdat) +{ + int legal; + fetchdat = fastreadl_fetch(cs + cpu_state.pc); + if (cpu_state.abrt) + return 0; + cpu_state.pc++; + + legal = is_lock_legal(fetchdat); + + ILLEGAL_ON(legal == 0); + + CLOCK_CYCLES(4); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +#else static int opLOCK(uint32_t fetchdat) { @@ -740,6 +759,7 @@ opLOCK(uint32_t fetchdat) PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } +#endif static int opBOUND_w_a16(uint32_t fetchdat) diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h new file mode 100644 index 000000000..cae6c9957 --- /dev/null +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -0,0 +1,500 @@ +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 > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } + 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 > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } + 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; + } + + 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) +{ + 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; + } + + 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 > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + CPU_BLOCK_END(); + return 0; +} +static int +opMOV_DRx_r_a32(uint32_t fetchdat) +{ + if ((CPL > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + CPU_BLOCK_END(); + 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; + } + } + 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 2a798db5c..7fcc92312 100644 --- a/src/cpu/x86_ops_mov_seg.h +++ b/src/cpu/x86_ops_mov_seg.h @@ -195,7 +195,11 @@ opMOV_seg_w_a16(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; case 0x20: /*FS*/ op_loadseg(new_seg, &cpu_state.seg_fs); @@ -240,7 +244,11 @@ opMOV_seg_w_a32(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; case 0x20: /*FS*/ op_loadseg(new_seg, &cpu_state.seg_fs); diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index 1254d7289..e84847a7b 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -367,6 +367,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) switch (rmdat & 0x38) { case 0x00: /*SGDT*/ + ILLEGAL_ON(cpu_mod == 3); if (cpu_mod != 3) SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(gdt.limit); @@ -389,6 +390,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(7, 2, rmdat, 0, 0, 1, 1, ea32); break; case 0x10: /*LGDT*/ + ILLEGAL_ON(cpu_mod == 3); if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { x86gpf(NULL, 0); break; diff --git a/src/cpu/x86_ops_prefix_2386.h b/src/cpu/x86_ops_prefix_2386.h new file mode 100644 index 000000000..87d114944 --- /dev/null +++ b/src/cpu/x86_ops_prefix_2386.h @@ -0,0 +1,292 @@ +#define op_seg(name, seg, opcode_table, normal_opcode_table) \ + static int op##name##_w_a16(uint32_t fetchdat) \ + { \ + int legal; \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + if (in_lock) { \ + legal = is_lock_legal(fetchdat); \ + \ + ILLEGAL_ON(legal == 0); \ + } \ + \ + 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) \ + { \ + int legal; \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + if (in_lock) { \ + legal = is_lock_legal(fetchdat); \ + \ + ILLEGAL_ON(legal == 0); \ + } \ + \ + 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) \ + { \ + int legal; \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + if (in_lock) { \ + legal = is_lock_legal(fetchdat); \ + \ + ILLEGAL_ON(legal == 0); \ + } \ + \ + 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) \ + { \ + int legal; \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + if (in_lock) { \ + legal = is_lock_legal(fetchdat); \ + \ + ILLEGAL_ON(legal == 0); \ + } \ + \ + 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_2386_opcodes, x86_2386_opcodes) +op_seg(DS, cpu_state.seg_ds, x86_2386_opcodes, x86_2386_opcodes) +op_seg(ES, cpu_state.seg_es, x86_2386_opcodes, x86_2386_opcodes) +op_seg(FS, cpu_state.seg_fs, x86_2386_opcodes, x86_2386_opcodes) +op_seg(GS, cpu_state.seg_gs, x86_2386_opcodes, x86_2386_opcodes) +op_seg(SS, cpu_state.seg_ss, x86_2386_opcodes, x86_2386_opcodes) + // clang-format on + +#define op_srp(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); \ + 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); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + } + +// clang-format off +op_srp(CS_REPE, cpu_state.seg_cs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_srp(DS_REPE, cpu_state.seg_ds, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_srp(ES_REPE, cpu_state.seg_es, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_srp(FS_REPE, cpu_state.seg_fs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_srp(GS_REPE, cpu_state.seg_gs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_srp(SS_REPE, cpu_state.seg_ss, x86_2386_opcodes_REPE, x86_2386_opcodes) + +op_srp(CS_REPNE, cpu_state.seg_cs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_srp(DS_REPNE, cpu_state.seg_ds, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_srp(ES_REPNE, cpu_state.seg_es, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_srp(FS_REPNE, cpu_state.seg_fs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_srp(GS_REPNE, cpu_state.seg_gs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_srp(SS_REPNE, cpu_state.seg_ss, x86_2386_opcodes_REPNE, x86_2386_opcodes) + // clang-format on + +static int +op_66(uint32_t fetchdat) /*Data size select*/ +{ + int legal; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + if (in_lock) { + legal = is_lock_legal(fetchdat); + + ILLEGAL_ON(legal == 0); + } + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +op_67(uint32_t fetchdat) /*Address size select*/ +{ + int legal; + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + if (in_lock) { + legal = is_lock_legal(fetchdat); + + ILLEGAL_ON(legal == 0); + } + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} + +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++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + 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); +} +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++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + 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); +} +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++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + 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 +op_67_REPNE(uint32_t fetchdat) /*Address size select*/ +{ + 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_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); +} diff --git a/src/cpu/x86_ops_rep_2386.h b/src/cpu/x86_ops_rep_2386.h index b6f64e90d..fe5048340 100644 --- a/src/cpu/x86_ops_rep_2386.h +++ b/src/cpu/x86_ops_rep_2386.h @@ -836,7 +836,7 @@ REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) static int opREPNE(uint32_t fetchdat) { - fetchdat = fastreadl(cs + cpu_state.pc); + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc++; @@ -850,7 +850,7 @@ opREPNE(uint32_t fetchdat) static int opREPE(uint32_t fetchdat) { - fetchdat = fastreadl(cs + cpu_state.pc); + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc++; diff --git a/src/cpu/x86_ops_ret_2386.h b/src/cpu/x86_ops_ret_2386.h new file mode 100644 index 000000000..ca85bf2b0 --- /dev/null +++ b/src/cpu/x86_ops_ret_2386.h @@ -0,0 +1,297 @@ +#ifdef USE_NEW_DYNAREC +# define CPU_SET_OXPC +#else +# define CPU_SET_OXPC oxpc = cpu_state.pc; +#endif + +#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)) { \ + 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) +{ + 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) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + 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) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRETF_a32_imm(uint32_t fetchdat) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a32(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; +} + +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); + 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; + rf_flag_no_clear = 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; + rf_flag_no_clear = 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 ((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; + op_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; + 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; + rf_flag_no_clear = 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; + rf_flag_no_clear = 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_stack.h b/src/cpu/x86_ops_stack.h index 13eb883d3..fbf603ddb 100644 --- a/src/cpu/x86_ops_stack.h +++ b/src/cpu/x86_ops_stack.h @@ -667,7 +667,11 @@ opPOP_SS_w(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; } @@ -695,7 +699,11 @@ opPOP_SS_l(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; } diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 96061d3fa..d912a755b 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -78,6 +78,10 @@ x86seg_log(const char *fmt, ...) # define x86seg_log(fmt, ...) #endif +#ifdef USE_DYNAREC +extern int cpu_block_end; +#endif + void #ifdef OPS_286_386 x86_doabrt_2386(int x86_abrt) @@ -2088,6 +2092,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) uint32_t new_edi; uint32_t new_pc; uint32_t new_flags; + uint32_t t_bit; uint32_t addr; uint32_t *segdat232 = (uint32_t *) segdat2; const x86seg *dt; @@ -2189,6 +2194,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) new_fs = readmemw(base, 0x58); new_gs = readmemw(base, 0x5C); new_ldt = readmemw(base, 0x60); + t_bit = readmemb(base, 0x64) & 1; cr0 |= 8; @@ -2279,6 +2285,19 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) op_loadseg(new_ds, &cpu_state.seg_ds); op_loadseg(new_fs, &cpu_state.seg_fs); op_loadseg(new_gs, &cpu_state.seg_gs); + + if (!cpu_use_exec) + rf_flag_no_clear = 1; + + if (t_bit) { + if (cpu_use_exec) + trap = 2; + else + trap |= 2; +#ifdef USE_DYNAREC + cpu_block_end = 1; +#endif + } } else { if (limit < 43) { x86ts(NULL, seg); @@ -2382,7 +2401,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) ldt.base |= (readmemb(0, templ + 7) << 24); } - if (!(new_cs & 0xfff8)) { + if (!(new_cs & 0xfff8) && !(new_cs & 0x0004)) { x86ts(NULL, 0); return; } @@ -2454,6 +2473,8 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.limit = limit; tr.access = segdat[2] >> 8; tr.ar_high = segdat[3] & 0xff; + if (!cpu_use_exec) + dr[7] &= 0xFFFFFFAA; } void diff --git a/src/cpu/x86seg_common.c b/src/cpu/x86seg_common.c index 8926af0d7..12b698b1a 100644 --- a/src/cpu/x86seg_common.c +++ b/src/cpu/x86seg_common.c @@ -87,6 +87,12 @@ x86de(UNUSED(char *s), UNUSED(uint16_t error)) #endif } +void +x86gen(void) +{ + x86_int(1); +} + void x86gpf(UNUSED(char *s), uint16_t error) { diff --git a/src/cpu/x86seg_common.h b/src/cpu/x86seg_common.h index f4bffed40..9f9049322 100644 --- a/src/cpu/x86seg_common.h +++ b/src/cpu/x86seg_common.h @@ -41,6 +41,7 @@ extern int cgate32; extern int intgatesize; extern void x86seg_reset(void); +extern void x86gen(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); diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 1d9220255..aef9289e7 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -797,7 +797,7 @@ const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -806,7 +806,7 @@ const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -815,7 +815,7 @@ const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -1055,7 +1055,7 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -1064,7 +1064,7 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -1073,7 +1073,7 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -2114,7 +2114,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2123,7 +2123,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2132,7 +2132,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2154,7 +2154,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2163,7 +2163,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2172,7 +2172,7 @@ const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2194,7 +2194,7 @@ const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2203,7 +2203,7 @@ const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2212,7 +2212,7 @@ const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2234,7 +2234,7 @@ const OpFn OP_TABLE(sf_fpu_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2243,7 +2243,7 @@ const OpFn OP_TABLE(sf_fpu_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2252,7 +2252,7 @@ const OpFn OP_TABLE(sf_fpu_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2275,7 +2275,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2284,7 +2284,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2293,7 +2293,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = { 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_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_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, @@ -2315,7 +2315,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2324,7 +2324,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -2333,7 +2333,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { 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_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_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, @@ -3373,7 +3373,7 @@ 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, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3382,7 +3382,7 @@ 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, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3391,7 +3391,7 @@ 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, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3413,7 +3413,7 @@ 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, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3422,7 +3422,7 @@ 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, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3431,7 +3431,7 @@ 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, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3453,7 +3453,7 @@ const OpFn OP_TABLE(fpu_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3462,7 +3462,7 @@ const OpFn OP_TABLE(fpu_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3471,7 +3471,7 @@ const OpFn OP_TABLE(fpu_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3493,7 +3493,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3502,7 +3502,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3511,7 +3511,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3534,7 +3534,7 @@ const OpFn OP_TABLE(fpu_686_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3543,7 +3543,7 @@ const OpFn OP_TABLE(fpu_686_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3552,7 +3552,7 @@ const OpFn OP_TABLE(fpu_686_df_a16)[256] = { 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, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, @@ -3574,7 +3574,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3583,7 +3583,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, @@ -3592,7 +3592,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = { 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, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, - ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index d77c0ca2b..0936f325b 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -144,6 +144,89 @@ opFILDiq_a32(uint32_t fetchdat) } #endif +static int +FBLD_a16(uint32_t fetchdat) +{ + uint16_t load_reg_hi = 0xffff; + uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); + int64_t load_val = 0ULL; + uint64_t power; + int sign; + + FP_ENTER(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_lo = readmemq(easeg, cpu_state.eaaddr); + load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + sign = (load_reg_hi & 0x8000) != 0; + load_val = 0ULL; + power = 1; + for (int i = 0; i < 16; i++) { + load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + load_reg_lo >>= 4; + power *= 10; + } + for (int i = 0; i < 2; i++) { + load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; + load_reg_hi >>= 4; + power *= 10; + } + if (sign) + load_val = -load_val; + x87_push((double) load_val); + cpu_state.MM[cpu_state.TOP & 7].q = load_val; + 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; +} +#ifndef FPU_8087 +static int +FBLD_a32(uint32_t fetchdat) +{ + uint16_t load_reg_hi = 0xffff; + uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); + int64_t load_val = 0ULL; + uint64_t power; + int sign; + + FP_ENTER(); + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_lo = readmemq(easeg, cpu_state.eaaddr); + load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + sign = (load_reg_hi & 0x8000) != 0; + load_val = 0ULL; + power = 1; + for (int i = 0; i < 16; i++) { + load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + load_reg_lo >>= 4; + power *= 10; + } + for (int i = 0; i < 2; i++) { + load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; + load_reg_hi >>= 4; + power *= 10; + } + if (sign) + load_val = -load_val; + x87_push((double) load_val); + cpu_state.MM[cpu_state.TOP & 7].q = load_val; + 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; +} +#endif + static int FBSTP_a16(uint32_t fetchdat) { diff --git a/src/cpu/x87_ops_sf_load_store.h b/src/cpu/x87_ops_sf_load_store.h index 383a7ee52..228d9fc06 100644 --- a/src/cpu/x87_ops_sf_load_store.h +++ b/src/cpu/x87_ops_sf_load_store.h @@ -183,6 +183,99 @@ sf_FILDiq_a32(uint32_t fetchdat) } #endif +static int +sf_FBLD_PACKED_BCD_a16(uint32_t fetchdat) +{ + floatx80 result; + uint16_t load_reg_hi = 0xffff; + uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); + int64_t load_val = 0ULL; + uint64_t power; + int sign; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_lo = readmemq(easeg, cpu_state.eaaddr); + load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + sign = (load_reg_hi & 0x8000) != 0; + load_val = 0ULL; + power = 1; + for (int i = 0; i < 16; i++) { + load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + load_reg_lo >>= 4; + power *= 10; + } + for (int i = 0; i < 2; i++) { + load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; + load_reg_hi >>= 4; + power *= 10; + } + if (sign) + load_val = -load_val; + result = int64_to_floatx80(load_val); + 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_FBLD_PACKED_BCD_a32(uint32_t fetchdat) +{ + floatx80 result; + uint16_t load_reg_hi = 0xffff; + uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); + int64_t load_val = 0ULL; + uint64_t power; + int sign; + + FP_ENTER(); + FPU_check_pending_exceptions(); + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_lo = readmemq(easeg, cpu_state.eaaddr); + load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); + if (cpu_state.abrt) + return 1; + clear_C1(); + if (!IS_TAG_EMPTY(-1)) { + FPU_stack_overflow(fetchdat); + } else { + sign = (load_reg_hi & 0x8000) != 0; + load_val = 0ULL; + power = 1; + for (int i = 0; i < 16; i++) { + load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + load_reg_lo >>= 4; + power *= 10; + } + for (int i = 0; i < 2; i++) { + load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; + load_reg_hi >>= 4; + power *= 10; + } + if (sign) + load_val = -load_val; + result = int64_to_floatx80(load_val); + 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) { diff --git a/src/cpu/x886seg_2386.c b/src/cpu/x886seg_2386.c deleted file mode 100644 index 335c757e4..000000000 --- a/src/cpu/x886seg_2386.c +++ /dev/null @@ -1,22 +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. - * - * 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/device.c b/src/device.c index c517f98e9..5e3b394c2 100644 --- a/src/device.c +++ b/src/device.c @@ -51,6 +51,8 @@ #include <86box/ini.h> #include <86box/config.h> #include <86box/device.h> +#include <86box/timer.h> +#include <86box/lpt.h> #include <86box/machine.h> #include <86box/mem.h> #include <86box/rom.h> @@ -62,6 +64,7 @@ static device_t *devices[DEVICE_MAX]; static void *device_priv[DEVICE_MAX]; static device_context_t device_current; static device_context_t device_prev; +static void *device_common_priv; #ifdef ENABLE_DEVICE_LOG int device_do_log = ENABLE_DEVICE_LOG; @@ -209,6 +212,16 @@ device_add(const device_t *dev) return device_add_common(dev, dev, NULL, NULL, 0); } +void * +device_add_linked(const device_t *dev, void *priv) +{ + void *ret; + device_common_priv = priv; + ret = device_add_common(dev, dev, NULL, NULL, 0); + device_common_priv = NULL; + return ret; +} + void * device_add_parameters(const device_t *dev, void *params) { @@ -305,6 +318,12 @@ device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *pr device_add_common(dev, cd, priv, params, inst); } +void * +device_get_common_priv(void) +{ + return device_common_priv; +} + void device_close_all(void) { @@ -328,6 +347,12 @@ device_reset_all(uint32_t match_flags) devices[c]->reset(device_priv[c]); } } + +#ifdef UNCOMMENT_LATER + /* TODO: Actually convert the LPT devices to device_t's. */ + if ((match_flags == DEVICE_ALL) || (match_flags == DEVICE_PCI)) + lpt_reset(); +#endif } void * @@ -450,8 +475,7 @@ device_has_config(const device_t *dev) config = dev->config; while (config->type != -1) { - if (config->type != CONFIG_MAC) - c++; + c++; config++; } @@ -849,3 +873,9 @@ machine_get_config_string(char *s) return NULL; } + +const device_t* +device_context_get_device(void) +{ + return device_current.dev; +} diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 2988152c1..c0719af2a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -17,12 +17,13 @@ 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 + postcard.c serial.c unittester.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c + smbus_piix4.c smbus_ali7101.c smbus_sis5595.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) + mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c + serial_passthrough.c + novell_cardkey.c) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_link_libraries(86Box atomic) diff --git a/src/device/ibm_5161.c b/src/device/ibm_5161.c index 07083873e..762a379a1 100644 --- a/src/device/ibm_5161.c +++ b/src/device/ibm_5161.c @@ -73,8 +73,8 @@ ibm_5161_in(uint16_t port, void *priv) 02-03 = not used 04-07 = switch position 1 = Off - 0 =On */ - ret = dev->regs[3] & 0x01; + 0 = On */ + ret = (dev->regs[3] & 0x01) | (((~(0xf - ((mem_size + isa_mem_size) >> 6))) & 0xf) << 4); break; default: @@ -95,8 +95,7 @@ ibm_5161_close(void *priv) static void * 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)); + ibm_5161_t *dev = (ibm_5161_t *) calloc(1, sizeof(ibm_5161_t)); /* Extender Card Registers */ io_sethandler(0x0210, 0x0004, diff --git a/src/device/isamem.c b/src/device/isamem.c index 5b880d6eb..70f51ce8d 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -97,6 +97,7 @@ #define ISAMEM_RAMPAGEXT_CARD 11 #define ISAMEM_ABOVEBOARD_CARD 12 #define ISAMEM_BRAT_CARD 13 +#define ISAMEM_EV165A_CARD 14 #define ISAMEM_DEBUG 0 @@ -452,6 +453,16 @@ isamem_init(const device_t *info) dev->frame_addr = 0xE0000; break; + case ISAMEM_EV165A_CARD: /* Everex Maxi Magic EV-165A */ + 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("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 */ @@ -1238,6 +1249,101 @@ static const device_t ev159_device = { .config = ev159_config }; +static const device_config_t ev165a_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 2048, + .step = 512 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 896, + .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 = "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 ev165a_device = { + .name = "Everex Magi Magic EV-165A", + .internal_name = "ev165a", + .flags = DEVICE_ISA, + .local = ISAMEM_EV165A_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ev165a_config +}; + #if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) static const device_config_t brat_config[] = { // clang-format off @@ -1560,6 +1666,7 @@ static const struct { { &a6pak_device }, { &ems5150_device }, { &ev159_device }, + { &ev165a_device }, #if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) { &brat_device }, #endif diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 7b9d570bb..da9e623c1 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -124,7 +124,7 @@ 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) + if ((card == NULL) || !card->config_changed) return; /* Populate config structure, performing endianness conversion as needed. */ @@ -737,7 +737,7 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) 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_transfer[] = { "8-bit", "8/16-bit", "16-bit", "Reserved" }; const char *dma_speed[] = { "compatibility", "Type A", "Type B", "Type F" }; #endif uint16_t i = 9; @@ -937,9 +937,9 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) 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 " : "", + (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 @@ -1004,6 +1004,29 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) break; + case 0x09: /* Fixed I/O port */ + if (!ld) { + isapnp_log("ISAPnP: >>%s Fixed I/O descriptor with no logical device\n", in_df ? ">" : ""); + break; + } + + if (io > 7) { + isapnp_log("ISAPnP: >>%s Fixed I/O descriptor overflow (%d)\n", in_df ? ">" : "", io++); + break; + } + + isapnp_log("ISAPnP: >>%s Fixed I/O range %d with %d ports at %04X\n", in_df ? ">" : "", io, card->rom[i + 3], *((uint16_t *) &card->rom[i + 1])); + + /* Fixed I/O port ranges of this kind are always 10-bit. */ + ld->io_16bit &= ~(1 << io); + + if (card->rom[i + 3] > ld->io_len[io]) + ld->io_len[io] = card->rom[i + 3]; + + io++; + + break; + case 0x0f: /* end tag */ /* Calculate checksum. */ res = 0x00; diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 8045ea1df..74ade4cd3 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -44,6 +44,9 @@ #include <86box/video.h> #include <86box/keyboard.h> +#include <86box/dma.h> +#include <86box/pci.h> + #define STAT_PARITY 0x80 #define STAT_RTIMEOUT 0x40 #define STAT_TTIMEOUT 0x20 @@ -85,8 +88,11 @@ #define KBC_VEN_ALI 0x28 #define KBC_VEN_SIEMENS 0x2c #define KBC_VEN_COMPAQ 0x30 +#define KBC_VEN_IBM 0x34 #define KBC_VEN_MASK 0x7c +#define KBC_FLAG_IS_ASIC 0x80000000 + #define FLAG_CLOCK 0x01 #define FLAG_CACHE 0x02 #define FLAG_PS2 0x04 @@ -130,9 +136,9 @@ typedef struct atkbc_t { uint8_t stat_hi; uint8_t pending; uint8_t irq_state; + uint8_t do_irq; + uint8_t is_asic; uint8_t pad; - uint8_t pad0; - uint8_t pad1; uint8_t mem[0x100]; @@ -141,8 +147,9 @@ typedef struct atkbc_t { uint32_t flags; - /* Main timer. */ - pc_timer_t send_delay_timer; + /* Main timers. */ + pc_timer_t kbc_poll_timer; + pc_timer_t kbc_dev_poll_timer; /* P2 pulse callback timer. */ pc_timer_t pulse_cb; @@ -160,6 +167,8 @@ 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 uint8_t kbc_handler_set = 0; + static void (*kbc_at_do_poll)(atkbc_t *dev); /* Non-translated to translated scan codes. */ @@ -198,6 +207,19 @@ static const uint8_t nont_to_t[256] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; +static const uint8_t multikey_vars[0x0b] = { + 0x0a, + 0x03, 0x1e, 0x27, 0x28, 0x29, 0x38, 0x39, 0x18, 0x19, 0x35 +}; + +static uint8_t fast_reset = 0x00; + +void +kbc_at_set_fast_reset(const uint8_t new_fast_reset) +{ + fast_reset = new_fast_reset; +} + #ifdef ENABLE_KBC_AT_LOG int kbc_at_do_log = ENABLE_KBC_AT_LOG; @@ -327,6 +349,30 @@ kbc_translate(atkbc_t *dev, uint8_t val) return ret; } +static void +kbc_set_do_irq(atkbc_t *dev, uint8_t channel) +{ + dev->channel = channel; + dev->do_irq = 1; +} + +static void +kbc_do_irq(atkbc_t *dev) +{ + if (dev->do_irq) { + /* 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. */ + picint_common(1 << 1, 0, 0, NULL); + picint_common(1 << 12, 0, 0, NULL); + if (dev->channel >= 2) + picint_common(1 << 12, 0, 1, NULL); + else + picint_common(1 << 1, 0, 1, NULL); + + dev->do_irq = 0; + } +} + static void kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { @@ -345,6 +391,8 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) 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; + dev->do_irq = 0; + /* 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) { @@ -352,16 +400,15 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) 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); - } + kbc_set_do_irq(dev, channel); + } else if (dev->mem[0x20] & 0x01) + kbc_set_do_irq(dev, channel); } 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. */ + if (dev->is_asic || (kbc_ven == KBC_VEN_IBM_PS1) || (kbc_ven == KBC_VEN_IBM)) + kbc_do_irq(dev); + dev->ob = temp; } @@ -580,6 +627,8 @@ kbc_scan_aux_ps2(atkbc_t *dev) static void kbc_at_poll_ps2(atkbc_t *dev) { + kbc_do_irq(dev); + switch (dev->state) { case STATE_RESET: if (dev->status & STAT_IFULL) { @@ -594,7 +643,6 @@ kbc_at_poll_ps2(atkbc_t *dev) fallthrough; case STATE_MAIN_IBF: default: -ps2_main_ibf: if (dev->status & STAT_IFULL) kbc_ibf_process(dev); else if (!(dev->status & STAT_OFULL)) { @@ -645,7 +693,8 @@ ps2_main_ibf: #endif dev->state = STATE_MAIN_IBF; dev->pending = 0; - goto ps2_main_ibf; + // goto ps2_main_ibf; + break; case STATE_KBC_OUT: /* Keyboard controller command want to output multiple bytes. */ if (dev->status & STAT_IFULL) { @@ -695,10 +744,18 @@ kbc_at_poll(void *priv) { atkbc_t *dev = (atkbc_t *) priv; - timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); + timer_advance_u64(&dev->kbc_poll_timer, (100ULL * TIMER_USEC)); /* TODO: Implement the password security state. */ kbc_at_do_poll(dev); +} + +static void +kbc_at_dev_poll(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + + timer_advance_u64(&dev->kbc_dev_poll_timer, (100ULL * TIMER_USEC)); if ((kbc_at_ports[0] != NULL) && (kbc_at_ports[0]->priv != NULL)) kbc_at_ports[0]->poll(kbc_at_ports[0]->priv); @@ -736,7 +793,10 @@ write_p2(atkbc_t *dev, uint8_t val) /* 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*/ + /* TODO: The fast reset flag's condition should be reversed - the BCM SQ-588 + enables the flag and the CPURST on soft reset flag but expects this + to still soft reset instead. */ + if ((fast_reset || !cpu_cpurst_on_sr) && ((old ^ val) & 0x01)) { /*Reset*/ if (!(val & 0x01)) { /* Pin 0 selected. */ /* Pin 0 selected. */ kbc_at_log("write_p2(): Pulse reset!\n"); @@ -753,11 +813,12 @@ write_p2(atkbc_t *dev, uint8_t val) 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) + if (kbc_ven == KBC_VEN_SIEMENS) is486 ? loadcs(0xf000) : loadcs_2386(0xf000); } } @@ -765,6 +826,28 @@ write_p2(atkbc_t *dev, uint8_t val) /* Do this here to avoid an infinite reset loop. */ dev->p2 = val; + + if (!fast_reset && cpu_cpurst_on_sr && ((old ^ val) & 0x01)) { /*Reset*/ + if (!(val & 0x01)) { /* Pin 0 selected. */ + /* Pin 0 selected. */ + kbc_at_log("write_p2(): Pulse reset!\n"); + dma_reset(); + dma_set_at(1); + + device_reset_all(DEVICE_ALL); + + cpu_alt_reset = 0; + + pci_reset(); + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); + } + } } static void @@ -1302,6 +1385,204 @@ write64_ami(void *priv, uint8_t val) return write64_generic(dev, val); } +static uint8_t +write60_phoenix(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (dev->command) { + /* TODO: Make this actually load the password. */ + case 0xa3: /* Load Extended Password */ + kbc_at_log("ATkbc: Phoenix - Load Extended Password\n"); + if (val == 0x00) + dev->command_phase = 0; + else { + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + } + return 0; + + case 0xaf: /* Set Inactivity Timer */ + kbc_at_log("ATkbc: Phoenix - Set Inactivity Timer\n"); + dev->mem[0x3a] = val; + dev->command_phase = 0; + return 0; + + case 0xb8: /* Set Extended Memory Access Index */ + kbc_at_log("ATkbc: Phoenix - Set Extended Memory Access Index\n"); + dev->mem_addr = val; + dev->command_phase = 0; + return 0; + + case 0xbb: /* Set Extended Memory */ + kbc_at_log("ATkbc: Phoenix - Set Extended Memory\n"); + dev->mem[dev->mem_addr] = val; + dev->command_phase = 0; + return 0; + + case 0xbd: /* Set MultiKey Variable */ + kbc_at_log("ATkbc: Phoenix - Set MultiKey Variable\n"); + if ((dev->mem_addr > 0) && (dev->mem_addr <= multikey_vars[0x00])) + dev->mem[multikey_vars[dev->mem_addr]] = val; + dev->command_phase = 0; + return 0; + + case 0xc7: /* Set Port1 bits */ + kbc_at_log("ATkbc: Phoenix - Set Port1 bits\n"); + dev->p1 |= val; + dev->command_phase = 0; + return 0; + + case 0xc8: /* Clear Port1 bits */ + kbc_at_log("ATkbc: Phoenix - Clear Port1 bits\n"); + dev->p1 &= ~val; + dev->command_phase = 0; + return 0; + + case 0xc9: /* Set Port2 bits */ + kbc_at_log("ATkbc: Phoenix - Set Port2 bits\n"); + write_p2(dev, dev->p2 | val); + dev->command_phase = 0; + return 0; + + case 0xca: /* Clear Port2 bits */ + kbc_at_log("ATkbc: Phoenix - Clear Port2 bits\n"); + write_p2(dev, dev->p2 & ~val); + dev->command_phase = 0; + return 0; + + default: + break; + } + + return 1; +} + +static uint8_t +write64_phoenix(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *) priv; + + switch (val) { + case 0x00 ... 0x1f: + kbc_at_log("ATkbc: Phoenix - 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: Phoenix - alias write to %08X\n", dev->command); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xa2: /* Test Extended Password */ + kbc_at_log("ATkbc: Phoenix - Test Extended Password\n"); + kbc_at_queue_add(dev, 0xf1); /* Extended Password not loaded */ + return 0; + + /* TODO: Make this actually load the password. */ + case 0xa3: /* Load Extended Password */ + kbc_at_log("ATkbc: Phoenix - Load Extended Password\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xaf: /* Set Inactivity Timer */ + kbc_at_log("ATkbc: Phoenix - Set Inactivity Timer\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xb8: /* Set Extended Memory Access Index */ + kbc_at_log("ATkbc: Phoenix - Set Extended Memory Access Index\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xb9: /* Get Extended Memory Access Index */ + kbc_at_log("ATkbc: Phoenix - Get Extended Memory Access Index\n"); + kbc_at_queue_add(dev, dev->mem_addr); + return 0; + + case 0xba: /* Get Extended Memory */ + kbc_at_log("ATkbc: Phoenix - Get Extended Memory\n"); + kbc_at_queue_add(dev, dev->mem[dev->mem_addr]); + return 0; + + case 0xbb: /* Set Extended Memory */ + kbc_at_log("ATkbc: Phoenix - Set Extended Memory\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xbc: /* Get MultiKey Variable */ + kbc_at_log("ATkbc: Phoenix - Get MultiKey Variable\n"); + if (dev->mem_addr == 0) + kbc_at_queue_add(dev, multikey_vars[dev->mem_addr]); + else if (dev->mem_addr <= multikey_vars[dev->mem_addr]) + kbc_at_queue_add(dev, dev->mem[multikey_vars[dev->mem_addr]]); + else + kbc_at_queue_add(dev, 0xff); + return 0; + + case 0xbd: /* Set MultiKey Variable */ + kbc_at_log("ATkbc: Phoenix - Set MultiKey Variable\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xc7: /* Set Port1 bits */ + kbc_at_log("ATkbc: Phoenix - Set Port1 bits\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xc8: /* Clear Port1 bits */ + kbc_at_log("ATkbc: Phoenix - Clear Port1 bits\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xc9: /* Set Port2 bits */ + kbc_at_log("ATkbc: Phoenix - Set Port2 bits\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + case 0xca: /* Clear Port2 bits */ + kbc_at_log("ATkbc: Phoenix - Clear Port2 bits\n"); + dev->wantdata = 1; + dev->state = STATE_KBC_PARAM; + return 0; + + /* TODO: Handle these three commands properly - configurable + revision level and proper CPU bits. */ + case 0xd5: /* Read MultiKey code revision level */ + kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n"); + kbc_at_queue_add(dev, 0x04); + kbc_at_queue_add(dev, 0x16); + return 0; + + case 0xd6: /* Read Version Information */ + kbc_at_log("ATkbc: Phoenix - Read Version Information\n"); + kbc_at_queue_add(dev, 0x81); + kbc_at_queue_add(dev, 0xac); + return 0; + + case 0xd7: /* Read MultiKey model numbers */ + kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n"); + kbc_at_queue_add(dev, 0x02); + kbc_at_queue_add(dev, 0x87); + kbc_at_queue_add(dev, 0x02); + return 0; + + default: + break; + } + + return write64_generic(dev, val); +} + static uint8_t write64_siemens(void *priv, uint8_t val) { @@ -1753,6 +2034,9 @@ kbc_at_process_cmd(void *priv) if (dev->ib == 0xbb) break; + if (strstr(machine_get_internal_name(), "pb41") != NULL) + cpu_override_dynarec = 1; + if (dev->misc_flags & FLAG_PS2) { set_enable_aux(dev, 1); if ((dev->ports[1] != NULL) && (dev->ports[1]->priv != NULL)) { @@ -1796,26 +2080,10 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) 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->wantdata = 0; dev->state = STATE_MAIN_IBF; return; } @@ -1829,6 +2097,11 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->state = STATE_KBC_PARAM; dev->command = 0xd1; return; + } else if (fast_reset && ((val & 0xf0) == 0xf0)) { + pulse_output(dev, val & 0x0f); + + dev->state = STATE_MAIN_IBF; + return; } break; @@ -1857,6 +2130,8 @@ kbc_at_read(uint16_t port, void *priv) This also means that in AT mode, the IRQ is level-triggered. */ if (!(dev->misc_flags & FLAG_PS2)) picintclevel(1 << 1, &dev->irq_state); + if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1)) + cpu_override_dynarec = 0; break; case 0x64: @@ -1934,7 +2209,8 @@ kbc_at_close(void *priv) int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; /* Stop timers. */ - timer_disable(&dev->send_delay_timer); + timer_disable(&dev->kbc_dev_poll_timer); + timer_disable(&dev->kbc_poll_timer); for (int i = 0; i < max_ports; i++) { if (kbc_at_ports[i] != NULL) { @@ -1946,6 +2222,22 @@ kbc_at_close(void *priv) free(dev); } +void +kbc_at_handler(int set, void *priv) +{ + if (kbc_handler_set) { + io_removehandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + io_removehandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + } + + kbc_handler_set = set; + + if (kbc_handler_set) { + io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv); + } +} + static void * kbc_at_init(const device_t *info) { @@ -1957,18 +2249,22 @@ kbc_at_init(const device_t *info) dev->flags = info->local; + dev->is_asic = !!(info->local & KBC_FLAG_IS_ASIC); + 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); + kbc_handler_set = 0; + kbc_at_handler(1, dev); - timer_add(&dev->send_delay_timer, kbc_at_poll, dev, 1); + timer_add(&dev->kbc_poll_timer, kbc_at_poll, dev, 1); timer_add(&dev->pulse_cb, pulse_poll, dev, 0); + timer_add(&dev->kbc_dev_poll_timer, kbc_at_dev_poll, dev, 1); + dev->write60_ven = NULL; dev->write64_ven = NULL; @@ -1987,6 +2283,7 @@ kbc_at_init(const device_t *info) case KBC_VEN_GENERIC: case KBC_VEN_NCR: case KBC_VEN_IBM_PS1: + case KBC_VEN_IBM: case KBC_VEN_COMPAQ: dev->write64_ven = write64_generic; break; @@ -2032,6 +2329,11 @@ kbc_at_init(const device_t *info) dev->write64_ven = write64_ami; break; + case KBC_VEN_PHOENIX: + dev->write60_ven = write60_phoenix; + dev->write64_ven = write64_phoenix; + break; + case KBC_VEN_QUADTEL: dev->write60_ven = write60_quadtel; dev->write64_ven = write64_quadtel; @@ -2060,6 +2362,8 @@ kbc_at_init(const device_t *info) /* The actual keyboard. */ device_add(&keyboard_at_generic_device); + fast_reset = 0x00; + return dev; } @@ -2245,6 +2549,34 @@ const device_t keyboard_ps2_ami_device = { .config = NULL }; +const device_t keyboard_ps2_holtek_device = { + .name = "PS/2 Keyboard (Holtek)", + .internal_name = "keyboard_ps2_holtek", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_AMI | KBC_FLAG_IS_ASIC, + .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_phoenix_device = { + .name = "PS/2 Keyboard (Phoenix)", + .internal_name = "keyboard_ps2_phoenix", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_PHOENIX, + .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", @@ -2259,11 +2591,25 @@ const device_t keyboard_ps2_tg_ami_device = { .config = NULL }; +const device_t keyboard_ps2_mca_1_device = { + .name = "PS/2 Keyboard (IBM PS/2 MCA Type 1)", + .internal_name = "keyboard_ps2_mca_1", + .flags = DEVICE_KBC, + .local = KBC_TYPE_PS2_1 | KBC_VEN_IBM, + .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", + .name = "PS/2 Keyboard (IBM PS/2 MCA Type 2)", .internal_name = "keyboard_ps2_mca_2", .flags = DEVICE_KBC, - .local = KBC_TYPE_PS2_2 | KBC_VEN_GENERIC, + .local = KBC_TYPE_PS2_2 | KBC_VEN_IBM, .init = kbc_at_init, .close = kbc_at_close, .reset = kbc_at_reset, diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index 1c1a0e91a..c1041e6e1 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -119,12 +119,13 @@ kbc_at_dev_poll(void *priv) 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)) { + if (!dev->ignore && *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) + if (dev->ignore || !(*dev->scan) || dev->port->wantcmd) dev->state = DEV_STATE_MAIN_1; break; case DEV_STATE_MAIN_OUT: @@ -199,8 +200,7 @@ 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 = (atkbc_dev_t *) calloc(1, sizeof(atkbc_dev_t)); dev->port = kbc_at_ports[inst]; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 21c4884b7..7accb2fd6 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -32,6 +32,8 @@ #define FIFO_SIZE 16 +#define BAT_COUNT 1000 + enum { KBD_84_KEY = 0, KBD_101_KEY, @@ -75,6 +77,8 @@ static atkbc_dev_t *SavedKbd = NULL; static uint8_t inv_cmd_response = 0xfa; +static uint16_t bat_counter = 0; + static const scancode scancode_set1[512] = { // clang-format off { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ @@ -519,10 +523,12 @@ static void add_data_kbd(uint16_t val) { atkbc_dev_t *dev = SavedKbd; - uint8_t fake_shift[4]; + uint8_t fake_shift[4] = { 0 }; uint8_t num_lock = 0; uint8_t shift_states = 0; + dev->ignore = 1; + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; @@ -537,12 +543,14 @@ add_data_kbd(uint16_t val) /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 2A\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x12; add_data_vals(dev, fake_shift, 2); @@ -558,12 +566,14 @@ add_data_kbd(uint16_t val) /* Num lock off and left shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 AA\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; @@ -579,12 +589,14 @@ add_data_kbd(uint16_t val) /* Num lock off and right shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 B6\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xb6; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 59\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x59; @@ -610,12 +622,14 @@ add_data_kbd(uint16_t val) /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 AA\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; @@ -632,12 +646,14 @@ add_data_kbd(uint16_t val) /* Num lock off and left shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 2A\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x12; add_data_vals(dev, fake_shift, 2); @@ -652,12 +668,14 @@ add_data_kbd(uint16_t val) /* Num lock off and right shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 36\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x36; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 59\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x59; add_data_vals(dev, fake_shift, 2); @@ -676,6 +694,8 @@ add_data_kbd(uint16_t val) kbc_at_dev_queue_add(dev, val, 1); break; } + + dev->ignore = 0; } void @@ -704,11 +724,16 @@ keyboard_at_bat(void *priv) { atkbc_dev_t *dev = (atkbc_dev_t *) priv; - keyboard_at_set_defaults(dev); + if (bat_counter == 0x0000) { + keyboard_at_set_defaults(dev); - keyboard_scan = 1; + keyboard_scan = 1; - kbc_at_dev_queue_add(dev, 0xaa, 0); + kbc_at_dev_queue_add(dev, 0xaa, 0); + } else { + bat_counter--; + dev->state = DEV_STATE_EXECUTE_BAT; + } } static void @@ -851,7 +876,8 @@ keyboard_at_write(void *priv) 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_at_log("%s: set defaults%s\n", + dev->name, (val == 0xf6) ? "" : " and disable keyboard"); keyboard_scan = !(val & 0x01); keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", dev->name, val, keyboard_scan); @@ -926,6 +952,7 @@ keyboard_at_write(void *priv) case 0xff: /* reset */ kbc_at_dev_reset(dev, 1); + bat_counter = 1000; break; default: @@ -965,8 +992,10 @@ keyboard_at_init(const device_t *info) dev->fifo_mask = FIFO_SIZE - 1; - if (dev->port != NULL) + if (dev->port != NULL) { kbc_at_dev_reset(dev, 0); + bat_counter = 0x0000; + } keyboard_send = add_data_kbd; SavedKbd = dev; diff --git a/src/device/mouse.c b/src/device/mouse.c index 193149bc8..da4ed1c04 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -454,6 +454,15 @@ mouse_scale(int x, int y) mouse_scale_y(y); } +void +mouse_scale_axis(int axis, int val) +{ + if (axis == 1) + mouse_scale_y(val); + else if (axis == 0) + mouse_scale_x(val); +} + void mouse_set_z(int z) { diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 35f0cd9e8..c3a7310f0 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -21,6 +21,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/device.h> #include <86box/keyboard.h> #include <86box/mouse.h> @@ -276,6 +277,7 @@ ps2_write(void *priv) break; default: + mouse_ps2_log("%s: Bad command: %02X\n", dev->name, val); kbc_at_dev_queue_add(dev, 0xfe, 0); } } diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 9e4556a88..08aee09d8 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -28,6 +28,7 @@ #include <86box/serial.h> #include <86box/mouse.h> #include <86box/plat.h> +#include <86box/version.h> #define SERMOUSE_PORT 0 /* attach to Serial0 */ @@ -537,7 +538,7 @@ ltsermouse_process_command(mouse_t *dev) [FORMAT_HEX] = 0x04, [FORMAT_MS_4BYTE] = 0x08, /* Guess */ [FORMAT_MS_WHEEL] = 0x08 }; /* Guess */ - const char *copr = "\r\n(C) 2023 86Box, Revision 3.0"; + const char *copr = "\r\n(C) " COPYRIGHT_YEAR " 86Box, Revision 3.0"; mouse_serial_log("ltsermouse_process_command(): %02X\n", dev->ib); dev->command = dev->ib; @@ -674,7 +675,6 @@ ltsermouse_process_data(mouse_t *dev) 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; diff --git a/src/device/nec_mate_unk.c b/src/device/nec_mate_unk.c new file mode 100644 index 000000000..165962f30 --- /dev/null +++ b/src/device/nec_mate_unk.c @@ -0,0 +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. + * + * This file is part of the 86Box distribution. + * + * Implementation of the NEC Mate NX MA30D/23D Unknown Readout. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020-2023 Miran Grca. + */ +#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> + +static uint8_t +nec_mate_unk_read(UNUSED(uint16_t addr), void *priv) +{ + /* Expected by this NEC machine. + + It writes something on ports 3D6C, 3D6D, and 3D6E, then expects to read + 2Ah from port 3D6D. Then it repeats this with ports 6A, 6B, and 6C. + */ + return 0x2a; +} + +static void +nec_mate_unk_close(void *priv) +{ + uint8_t *dev = (uint8_t *) priv; + + free(dev); +} + +static void * +nec_mate_unk_init(const device_t *info) +{ + /* We have to return something non-NULL. */ + uint8_t *dev = (uint8_t *) calloc(1, sizeof(uint8_t)); + + io_sethandler(0x006b, 0x0001, nec_mate_unk_read, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x3d6d, 0x0001, nec_mate_unk_read, NULL, NULL, NULL, NULL, NULL, NULL); + + return dev; +} + +const device_t nec_mate_unk_device = { + .name = "NEC Mate NX MA30D/23D Unknown Readout", + .internal_name = "nec_mate_unk", + .flags = 0, + .local = 0, + .init = nec_mate_unk_init, + .close = nec_mate_unk_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c new file mode 100644 index 000000000..4730b6bb4 --- /dev/null +++ b/src/device/novell_cardkey.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. + * + * Implementation of the Novell NetWare 2.x Key Card, which + * was used for anti-piracy protection. + * + * + * Authors: Cacodemon345 + * + * Copyright 2024 Cacodemon345. + */ + +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/novell_cardkey.h> + +typedef struct novell_cardkey_t +{ + char serial_number_str[13]; +} novell_cardkey_t; + +static uint8_t +novell_cardkey_read(uint16_t port, void *priv) +{ + novell_cardkey_t* cardkey = (novell_cardkey_t*)priv; + uint8_t val = 0x00; + switch (port) { + case 0x23A: + val = (((cardkey->serial_number_str[11] > 'A') ? ((cardkey->serial_number_str[11] - 'A') + 10) : (cardkey->serial_number_str[11] - '0')) << 4) | (((cardkey->serial_number_str[9] > 'A') ? ((cardkey->serial_number_str[9] - 'A') + 10) : (cardkey->serial_number_str[9] - '0')) << 4); + break; + case 0x23B: + val = (((cardkey->serial_number_str[10] > 'A') ? ((cardkey->serial_number_str[10] - 'A') + 10) : (cardkey->serial_number_str[10] - '0')) << 4) | (((cardkey->serial_number_str[8] > 'A') ? ((cardkey->serial_number_str[8] - 'A') + 10) : (cardkey->serial_number_str[8] - '0')) << 4); + break; + + case 0x23C: + val = ((cardkey->serial_number_str[4] - '0') << 4) | ((cardkey->serial_number_str[2] - '0')); + break; + case 0x23D: + val = ((cardkey->serial_number_str[1] - '0') << 4) | ((cardkey->serial_number_str[6] - '0')); + break; + case 0x23E: + val = ((cardkey->serial_number_str[0] - '0') << 4) | ((cardkey->serial_number_str[7] - '0')); + break; + case 0x23F: + val = ((cardkey->serial_number_str[3] - '0') << 4) | ((cardkey->serial_number_str[5] - '0')); + break; + } + return val ^ 0xFF; +} + +void* novell_cardkey_init(const device_t* info) +{ + char sernumstr[13] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0 }; + int i = 0; + novell_cardkey_t* cardkey = calloc(1, sizeof(novell_cardkey_t)); + + strncpy(sernumstr, device_get_config_string("serial_number"), sizeof(sernumstr) - 1); + + for (i = 0; i < sizeof(sernumstr) - 4; i++) { + if (sernumstr[i] > '8' || sernumstr[i] < '0') + sernumstr[i] = '0'; + } + if (sernumstr[8] > 'F' || sernumstr[8] < '0') + sernumstr[8] = '0'; + if (sernumstr[9] > 'F' || sernumstr[9] < '0') + sernumstr[9] = '0'; + if (sernumstr[10] > 'F' || sernumstr[10] < '0') + sernumstr[10] = '0'; + if (sernumstr[11] > 'F' || sernumstr[11] < '0') + sernumstr[11] = '0'; + sernumstr[12] = 0; + strncpy(cardkey->serial_number_str, sernumstr, sizeof(sernumstr)); + io_sethandler(NOVELL_KEYCARD_ADDR, NOVELL_KEYCARD_ADDRLEN, novell_cardkey_read, NULL, NULL, NULL, NULL, NULL, cardkey); + return cardkey; +} + +void novell_cardkey_close(void* priv) +{ + free(priv); +} + +static const device_config_t keycard_config[] = { + // clang-format off + { + .name = "serial_number", + .description = "Serial Number", + .type = CONFIG_STRING, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t novell_keycard_device = { + .name = "Novell Netware 2.x Key Card", + .internal_name = "mssystems", + .flags = DEVICE_ISA, + .local = 0, + .init = novell_cardkey_init, + .close = novell_cardkey_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = keycard_config +}; diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 8183f8afa..c1f551162 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -41,11 +41,13 @@ #define AGP_BRIDGE_VIA_598 0x11068598 #define AGP_BRIDGE_VIA_691 0x11068691 #define AGP_BRIDGE_VIA_8601 0x11068601 +#define AGP_BRIDGE_SIS_5XXX 0x10390001 #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_SIS(x) (((x) >> 16) == 0x1039) +#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_SIS_5XXX) typedef struct pci_bridge_t { uint32_t local; @@ -134,6 +136,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) val |= 0x02; else if (dev->local == AGP_BRIDGE_ALI_M5247) val &= 0xc3; + else if (AGP_BRIDGE_SIS(dev->local)) + val &= 0x27; else val &= 0x67; break; @@ -194,7 +198,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x22: case 0x24: case 0x26: - val &= 0xf0; + val &= 0xf0; /* SiS datasheets say 0Fh for 1Ch but that's clearly an erratum since the + definition of the bits is identical to the other vendors' AGP bridges. */ break; case 0x3c: @@ -205,6 +210,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x3e: if (AGP_BRIDGE_VIA(dev->local)) val &= 0x0c; + else if (AGP_BRIDGE_SIS(dev->local)) + val &= 0x0e; else if (dev->local == AGP_BRIDGE_ALI_M5247) val &= 0x0f; else if (dev->local == AGP_BRIDGE_ALI_M5243) @@ -668,3 +675,17 @@ const device_t via_vt8601_agp_device = { .force_redraw = NULL, .config = NULL }; + +const device_t sis_5xxx_agp_device = { + .name = "SiS 5591/(5)600 AGP Bridge", + .internal_name = "via_5xxx_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_SIS_5XXX, + .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/serial.c b/src/device/serial.c index 37aadf8fe..ab26fc622 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -432,6 +432,31 @@ serial_set_dcd(serial_t *dev, uint8_t enabled) } } +void +serial_set_ri(serial_t *dev, uint8_t enabled) +{ + uint8_t prev_state = !!(dev->msr & 0x40); + if (dev->mctrl & 0x10) + return; + + dev->msr &= ~0x40; + dev->msr |= (!!enabled) << 6; + dev->msr_set &= ~0x40; + dev->msr_set |= (!!enabled) << 6; + + if (prev_state == 0 && (!!enabled) == 1) { + dev->msr |= 0x4; + dev->int_status |= SERIAL_INT_MSR; + serial_update_ints(dev); + } +} + +int +serial_get_ri(serial_t *dev) +{ + return !!(dev->msr & (1 << 6)); +} + void serial_set_clock_src(serial_t *dev, double clock_src) { @@ -570,6 +595,8 @@ serial_write(uint16_t addr, uint8_t val, void *priv) serial_do_irq(dev, 0); if ((val ^ dev->mctrl) & 0x10) serial_reset_fifo(dev); + if (dev->sd && dev->sd->dtr_callback && (val ^ dev->mctrl) & 1) + dev->sd->dtr_callback(dev, val & 1, dev->sd->priv); dev->mctrl = val; if (val & 0x10) { new_msr = (val & 0x0c) << 4; @@ -686,7 +713,10 @@ serial_read(uint16_t addr, void *priv) serial_update_ints(dev); break; case 6: - ret = dev->msr | dev->msr_set; + if (dev->mctrl & 0x10) + ret = dev->msr; + else + ret = dev->msr | dev->msr_set; dev->msr &= ~0x0f; dev->int_status &= ~SERIAL_INT_MSR; serial_update_ints(dev); @@ -794,6 +824,25 @@ serial_attach_ex(int port, return sd->serial; } +serial_t * +serial_attach_ex_2(int port, + void (*rcr_callback)(struct serial_s *serial, void *priv), + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data), + void (*dtr_callback)(struct serial_s *serial, int status, void *priv), + void *priv) +{ + serial_device_t *sd = &serial_devices[port]; + + sd->rcr_callback = rcr_callback; + sd->dtr_callback = dtr_callback; + sd->dev_write = dev_write; + sd->transmit_period_callback = NULL; + sd->lcr_callback = NULL; + sd->priv = priv; + + return sd->serial; +} + static void serial_speed_changed(void *priv) { diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index 1b1c5e3bf..eec9fa62a 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -370,12 +370,12 @@ static const device_config_t serial_passthrough_config[] = { // 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, + .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, diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c new file mode 100644 index 000000000..b76b38e17 --- /dev/null +++ b/src/device/smbus_sis5595.c @@ -0,0 +1,386 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 a generic SiS 5595-compatible SMBus host + * controller. + * + * Authors: RichardG, + * Miran Grca, + * + * Copyright 2020-2021 RichardG. + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/i2c.h> +#include <86box/pci.h> +#include <86box/smbus.h> +#include <86box/plat_fallthrough.h> + +#ifdef ENABLE_SMBUS_SIS5595_LOG +int smbus_sis5595_do_log = ENABLE_SMBUS_SIS5595_LOG; + +static void +smbus_sis5595_log(const char *fmt, ...) +{ + va_list ap; + + if (smbus_sis5595_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define smbus_sis5595_log(fmt, ...) +#endif + +static void +smbus_sis5595_irq(smbus_sis5595_t *dev, int raise) +{ + if (dev->irq_enable) { + if (raise) + pci_set_mirq(6, 1, &dev->irq_state); + else + pci_clear_mirq(6, 1, &dev->irq_state); + } +} + +void +smbus_sis5595_irq_enable(void *priv, uint8_t enable) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + if (!enable && dev->irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + + dev->irq_enable = enable; +} + +uint8_t +smbus_sis5595_read_index(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + return dev->index; +} + +uint8_t +smbus_sis5595_read_data(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + uint8_t ret = 0x00; + + switch (dev->index) { + case 0x00: + ret = dev->stat & 0xff; + break; + case 0x01: + ret = dev->stat >> 8; + break; + + case 0x02: + ret = dev->ctl & 0xff; + break; + case 0x03: + ret = dev->ctl >> 8; + break; + + case 0x04: + ret = dev->addr; + break; + + case 0x05: + ret = dev->cmd; + break; + + case 0x06: + ret = dev->block_ptr; + break; + + case 0x07: + ret = dev->count; + break; + + case 0x08 ... 0x0f: + ret = dev->data[(dev->index & 0x07) + (dev->block_ptr << 3)]; + if (dev->index == 0x0f) { + dev->block_ptr = (dev->block_ptr + 1) & 3; + smbus_sis5595_irq(dev, dev->block_ptr != 0x00); + } + break; + + case 0x10: + ret = dev->saved_addr; + break; + + case 0x11: + ret = dev->data0; + break; + + case 0x12: + ret = dev->data1; + break; + + case 0x13: + ret = dev->alias; + break; + + case 0xff: + ret = dev->reg_ff & 0xc0; + break; + + default: + break; + } + + smbus_sis5595_log("SMBus SIS5595: read(%02X) = %02x\n", addr, ret); + + return ret; +} + +void +smbus_sis5595_write_index(void *priv, uint8_t val) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + dev->index = val; +} + +void +smbus_sis5595_write_data(void *priv, uint8_t val) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + uint8_t smbus_addr; + uint8_t cmd; + uint8_t read; + uint16_t prev_stat; + uint16_t timer_bytes = 0; + + smbus_sis5595_log("SMBus SIS5595: write(%02X, %02X)\n", addr, val); + + prev_stat = dev->next_stat; + dev->next_stat = 0x0000; + switch (dev->index) { + case 0x00: + dev->stat &= ~(val & 0xf0); + /* Make sure IDLE is set if we're not busy or errored. */ + if (dev->stat == 0x04) + dev->stat = 0x00; + break; + case 0x01: + dev->stat &= ~(val & 0x07); + break; + + case 0x02: + dev->ctl = (dev->ctl & 0xff00) | val; + if (val & 0x20) { /* 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 & 0x10) { + /* dispatch command if START is set */ + timer_bytes++; /* address */ + + smbus_addr = (dev->addr >> 1); + read = dev->addr & 0x01; + + cmd = (dev->ctl >> 1) & 0x7; + smbus_sis5595_log("SMBus SIS5595: 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 = 0x0020; + break; + } + + dev->next_stat = 0x0040; /* raise INTER (command completed) by default */ + + /* Decode the command protocol. */ + dev->block_ptr = 0x01; + switch (cmd) { + case 0x0: /* quick R/W */ + break; + + case 0x1: /* byte R/W */ + if (read) /* byte read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + timer_bytes++; + + break; + + case 0x2: /* byte data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + + if (read) /* byte read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + timer_bytes++; + + break; + + case 0x3: /* word data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + + if (read) { /* word read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + dev->data[1] = i2c_read(i2c_smbus, smbus_addr); + } else { /* word write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + i2c_write(i2c_smbus, smbus_addr, dev->data[1]); + } + timer_bytes += 2; + + break; + + case 0x5: /* block R/W */ + dev->block_ptr = 0x00; + timer_bytes++; /* count the SMBus length byte now */ + fallthrough; + + default: /* unknown */ + dev->next_stat = 0x0010; /* raise DEV_ERR */ + timer_bytes = 0; + break; + } + + /* Finish transfer. */ + i2c_stop(i2c_smbus, smbus_addr); + } + break; + case 0x03: + dev->ctl = (dev->ctl & 0x00ff) | (val << 8); + break; + + case 0x04: + dev->addr = val; + break; + + case 0x05: + dev->cmd = val; + break; + + case 0x08 ... 0x0f: + dev->data[dev->index & 0x07] = val; + break; + + case 0x10: + dev->saved_addr = val; + break; + + case 0x11: + dev->data0 = val; + break; + + case 0x12: + dev->data1 = val; + break; + + case 0x13: + dev->alias = val & 0xfe; + break; + + case 0xff: + dev->reg_ff = val & 0x3f; + 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); + } +} + +static void +smbus_sis5595_response(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + /* Dispatch the status register update. */ + dev->stat = dev->next_stat; +} + +static void +smbus_sis5595_reset(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + timer_disable(&dev->response_timer); + dev->stat = 0x0000; + dev->block_ptr = 0x01; +} + +static void * +smbus_sis5595_init(const device_t *info) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) malloc(sizeof(smbus_sis5595_t)); + memset(dev, 0, sizeof(smbus_sis5595_t)); + + dev->local = info->local; + + /* 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_sis5595"); + + timer_add(&dev->response_timer, smbus_sis5595_response, dev, 0); + + smbus_sis5595_reset(dev); + + return dev; +} + +static void +smbus_sis5595_close(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + if (i2c_smbus == dev->i2c) + i2c_smbus = NULL; + i2c_removebus(dev->i2c); + + free(dev); +} + +const device_t sis5595_smbus_device = { + .name = "SiS 5595-compatible SMBus Host Controller", + .internal_name = "sis5595_smbus", + .flags = DEVICE_AT, + .local = 0, + .init = smbus_sis5595_init, + .close = smbus_sis5595_close, + .reset = smbus_sis5595_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/unittester.c b/src/device/unittester.c new file mode 100644 index 000000000..e52f3b56f --- /dev/null +++ b/src/device/unittester.c @@ -0,0 +1,635 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Debug device for assisting in unit testing. + * See doc/specifications/86box-unit-tester.md for more info. + * If modifying the protocol, you MUST modify the specification + * and increment the version number. + * + * + * + * Authors: GreaseMonkey, + * + * Copyright 2024 GreaseMonkey. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/plat.h> +#include <86box/unittester.h> +#include <86box/video.h> + +enum fsm1_value { + UT_FSM1_WAIT_8, + UT_FSM1_WAIT_6, + UT_FSM1_WAIT_B, + UT_FSM1_WAIT_o, + UT_FSM1_WAIT_x, +}; +enum fsm2_value { + UT_FSM2_IDLE, + UT_FSM2_WAIT_IOBASE_0, + UT_FSM2_WAIT_IOBASE_1, +}; + +/* Status bit mask */ +#define UT_STATUS_AWAITING_READ (1 << 0) +#define UT_STATUS_AWAITING_WRITE (1 << 1) +#define UT_STATUS_IDLE (1 << 2) +#define UT_STATUS_UNSUPPORTED_CMD (1 << 3) + +/* Command list */ +enum unittester_cmd { + UT_CMD_NOOP = 0x00, + UT_CMD_CAPTURE_SCREEN_SNAPSHOT = 0x01, + UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE = 0x02, + UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE = 0x03, + UT_CMD_EXIT = 0x04, +}; + +struct unittester_state { + /* I/O port settings */ + uint16_t trigger_port; + uint16_t iobase_port; + + /* Trigger port finite state machines */ + /* FSM1: "86Box" string detection */ + enum fsm1_value fsm1; + /* FSM2: IOBASE port selection, once trigger is activated */ + enum fsm2_value fsm2; + uint16_t fsm2_new_iobase; + + /* Command and data handling state */ + uint8_t status; + enum unittester_cmd cmd_id; + uint32_t write_offs; + uint32_t write_len; + uint64_t read_offs; + uint64_t read_len; + + /* Screen snapshot state */ + /* Monitor to take snapshot on */ + uint8_t snap_monitor; + /* Main image width + height */ + uint16_t snap_img_width; + uint16_t snap_img_height; + /* Fully overscanned image width + height */ + uint16_t snap_overscan_width; + uint16_t snap_overscan_height; + /* Offset of actual image within overscanned area */ + uint16_t snap_img_xoffs; + uint16_t snap_img_yoffs; + + /* Command-specific state */ + /* 0x02: Read Screen Snapshot Rectangle */ + /* 0x03: Verify Screen Snapshot Rectangle */ + uint16_t read_snap_width; + uint16_t read_snap_height; + int16_t read_snap_xoffs; + int16_t read_snap_yoffs; + uint32_t read_snap_crc; + + /* 0x04: Exit */ + uint8_t exit_code; +}; +static struct unittester_state unittester; +static const struct unittester_state unittester_defaults = { + .trigger_port = 0x0080, + .iobase_port = 0xFFFF, + .fsm1 = UT_FSM1_WAIT_8, + .fsm2 = UT_FSM2_IDLE, + .status = UT_STATUS_IDLE, + .cmd_id = UT_CMD_NOOP, +}; + +static const device_config_t unittester_config[] = { + { .name = "exit_enabled", + .description = "Enable 0x04 \"Exit 86Box\" command", + .type = CONFIG_BINARY, + .default_int = 1, + .default_string = "" }, + { .type = CONFIG_END } +}; + +/* Kept separate, as we will be reusing this object */ +static bitmap_t *unittester_screen_buffer = NULL; + +static bool unittester_exit_enabled = true; + +#ifdef ENABLE_UNITTESTER_LOG +int unittester_do_log = ENABLE_UNITTESTER_LOG; + +static void +unittester_log(const char *fmt, ...) +{ + va_list ap; + + if (unittester_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define unittester_log(fmt, ...) +#endif + +static uint8_t +unittester_read_snap_rect_idx(uint64_t offs) +{ + /* WARNING: If the width is somehow 0 and wasn't caught earlier, you'll probably get a divide by zero crash. */ + uint32_t idx = (offs & 0x3); + int64_t x = (offs >> 2) % unittester.read_snap_width; + int64_t y = (offs >> 2) / unittester.read_snap_width; + x += unittester.read_snap_xoffs; + y += unittester.read_snap_yoffs; + + if (x < 0 || y < 0 || x >= unittester.snap_overscan_width || y >= unittester.snap_overscan_height) { + /* Out of range! */ + return (idx == 3 ? 0xFF : 0x00); + } else { + /* In range */ + return (unittester_screen_buffer->line[y][x] & 0x00FFFFFF) >> (idx * 8); + } +} + +static void +unittester_write(uint16_t port, uint8_t val, UNUSED(void *priv)) +{ + if (port == unittester.iobase_port + 0x00) { + /* Command port */ + /* unittester_log("[UT] W %02X Command\n", val); */ + + unittester.write_offs = 0; + unittester.write_len = 0; + unittester.read_offs = 0; + unittester.read_len = 0; + + switch (val) { + /* 0x00: No-op */ + case UT_CMD_NOOP: + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE; + break; + + /* 0x01: Capture Screen Snapshot */ + case UT_CMD_CAPTURE_SCREEN_SNAPSHOT: + unittester.cmd_id = UT_CMD_CAPTURE_SCREEN_SNAPSHOT; + unittester.status = UT_STATUS_AWAITING_WRITE; + unittester.write_len = 1; + break; + + /* 0x02: Read Screen Snapshot Rectangle */ + case UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE: + unittester.cmd_id = UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE; + unittester.status = UT_STATUS_AWAITING_WRITE; + unittester.write_len = 8; + break; + + /* 0x03: Verify Screen Snapshot Rectangle */ + case UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE: + unittester.cmd_id = UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE; + unittester.status = UT_STATUS_AWAITING_WRITE; + unittester.write_len = 8; + break; + + /* 0x04: Exit */ + case UT_CMD_EXIT: + unittester.cmd_id = UT_CMD_EXIT; + unittester.status = UT_STATUS_AWAITING_WRITE; + unittester.write_len = 1; + break; + + /* Unsupported command - terminate here */ + default: + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE | UT_STATUS_UNSUPPORTED_CMD; + break; + } + + } else if (port == unittester.iobase_port + 0x01) { + /* Data port */ + /* unittester_log("[UT] W %02X Data\n", val); */ + + /* Skip if not awaiting */ + if ((unittester.status & UT_STATUS_AWAITING_WRITE) == 0) + return; + + switch (unittester.cmd_id) { + case UT_CMD_EXIT: + switch (unittester.write_offs) { + case 0: + unittester.exit_code = val; + break; + default: + break; + } + break; + + case UT_CMD_CAPTURE_SCREEN_SNAPSHOT: + switch (unittester.write_offs) { + case 0: + unittester.snap_monitor = val; + break; + default: + break; + } + break; + + case UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE: + case UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE: + switch (unittester.write_offs) { + case 0: + unittester.read_snap_width = (uint16_t) val; + break; + case 1: + unittester.read_snap_width |= ((uint16_t) val) << 8; + break; + case 2: + unittester.read_snap_height = (uint16_t) val; + break; + case 3: + unittester.read_snap_height |= ((uint16_t) val) << 8; + break; + case 4: + unittester.read_snap_xoffs = (uint16_t) val; + break; + case 5: + unittester.read_snap_xoffs |= ((uint16_t) val) << 8; + break; + case 6: + unittester.read_snap_yoffs = (uint16_t) val; + break; + case 7: + unittester.read_snap_yoffs |= ((uint16_t) val) << 8; + break; + default: + break; + } + break; + + /* This should not be reachable, but just in case... */ + default: + break; + } + + /* Advance write buffer */ + unittester.write_offs += 1; + if (unittester.write_offs >= unittester.write_len) { + unittester.status &= ~UT_STATUS_AWAITING_WRITE; + /* Determine what we're doing here based on the command. */ + switch (unittester.cmd_id) { + case UT_CMD_EXIT: + unittester_log("[UT] Exit received - code = %02X\n", unittester.exit_code); + + /* CHECK: Do we actually exit? */ + if (unittester_exit_enabled) { + /* Yes - call exit! */ + /* Clamp exit code */ + if (unittester.exit_code > 0x7F) + unittester.exit_code = 0x7F; + + /* Exit somewhat quickly! */ + unittester_log("[UT] Exit enabled, exiting with code %02X\n", unittester.exit_code); + exit(unittester.exit_code); + + } else { + /* No - report successful command completion and continue program execution */ + unittester_log("[UT] Exit disabled, continuing execution\n"); + } + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE; + break; + + case UT_CMD_CAPTURE_SCREEN_SNAPSHOT: + /* Recompute screen */ + unittester.snap_img_width = 0; + unittester.snap_img_height = 0; + unittester.snap_img_xoffs = 0; + unittester.snap_img_yoffs = 0; + unittester.snap_overscan_width = 0; + unittester.snap_overscan_height = 0; + if (unittester.snap_monitor < 0x01 || (unittester.snap_monitor - 1) > MONITORS_NUM) { + /* No monitor here - clear snapshot */ + unittester.snap_monitor = 0x00; + } else if (video_get_type_monitor(unittester.snap_monitor - 1) == VIDEO_FLAG_TYPE_NONE) { + /* Monitor disabled - clear snapshot */ + unittester.snap_monitor = 0x00; + } else { + /* Compute bounds for snapshot */ + const monitor_t *m = &monitors[unittester.snap_monitor - 1]; + unittester.snap_img_width = m->mon_xsize; + unittester.snap_img_height = m->mon_ysize; + unittester.snap_overscan_width = m->mon_xsize + m->mon_overscan_x; + unittester.snap_overscan_height = m->mon_ysize + m->mon_overscan_y; + unittester.snap_img_xoffs = (m->mon_overscan_x >> 1); + unittester.snap_img_yoffs = (m->mon_overscan_y >> 1); + /* Take snapshot */ + for (size_t y = 0; y < unittester.snap_overscan_height; y++) { + for (size_t x = 0; x < unittester.snap_overscan_width; x++) { + unittester_screen_buffer->line[y][x] = m->target_buffer->line[y][x]; + } + } + } + + /* We have 12 bytes to read. */ + unittester_log("[UT] Screen snapshot - image %d x %d @ (%d, %d) in overscan %d x %d\n", + unittester.snap_img_width, + unittester.snap_img_height, + unittester.snap_img_xoffs, + unittester.snap_img_yoffs, + unittester.snap_overscan_width, + unittester.snap_overscan_height); + unittester.status = UT_STATUS_AWAITING_READ; + unittester.read_len = 12; + break; + + case UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE: + case UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE: + /* Offset the X,Y offsets by the overscan offsets. */ + unittester.read_snap_xoffs += (int16_t) unittester.snap_img_xoffs; + unittester.read_snap_yoffs += (int16_t) unittester.snap_img_yoffs; + /* NOTE: Width * Height * 4 can potentially exceed a 32-bit number. + So, we use 64-bit numbers instead. + In practice, this will only happen if someone decides to request e.g. a 65535 x 65535 image, + of which most of the pixels will be out of range anyway. + */ + unittester.read_len = ((uint64_t) unittester.read_snap_width) * ((uint64_t) unittester.read_snap_height) * 4; + unittester.read_snap_crc = 0xFFFFFFFF; + + unittester_log("[UT] Screen rectangle analysis - %d x %d @ (%d, %d)\n", + unittester.read_snap_width, + unittester.read_snap_height, + unittester.read_snap_xoffs - (int16_t) unittester.snap_img_xoffs, + unittester.read_snap_yoffs - (int16_t) unittester.snap_img_yoffs); + + if (unittester.cmd_id == UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE) { + /* Read everything and compute CRC */ + uint32_t crc = 0xFFFFFFFF; + for (uint64_t i = 0; i < unittester.read_len; i++) { + crc ^= 0xFF & (uint32_t) unittester_read_snap_rect_idx(i); + /* Use some bit twiddling until we have a table-based fast CRC-32 implementation */ + for (uint32_t j = 0; j < 8; j++) { + crc = (crc >> 1) ^ ((-(crc & 0x1)) & 0xEDB88320); + } + } + unittester.read_snap_crc = crc ^ 0xFFFFFFFF; + + unittester_log("[UT] Screen rectangle analysis CRC = %08X\n", + unittester.read_snap_crc); + + /* Set actual read length for CRC result */ + unittester.read_len = 4; + unittester.status = UT_STATUS_AWAITING_READ; + + } else { + /* Do we have anything to read? */ + if (unittester.read_len >= 1) { + /* Yes - start reads! */ + unittester.status = UT_STATUS_AWAITING_READ; + } else { + /* No - stop here. */ + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE; + } + } + break; + + default: + /* Nothing to write? Stop here. */ + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE; + break; + } + } + + } else { + /* Not handled here - possibly open bus! */ + } +} + +static uint8_t +unittester_read(uint16_t port, UNUSED(void *priv)) +{ + uint8_t outval = 0xFF; + + if (port == unittester.iobase_port + 0x00) { + /* Status port */ + /* unittester_log("[UT] R -- Status = %02X\n", unittester.status); */ + return unittester.status; + } else if (port == unittester.iobase_port + 0x01) { + /* Data port */ + /* unittester_log("[UT] R -- Data\n"); */ + + /* Skip if not awaiting */ + if ((unittester.status & UT_STATUS_AWAITING_READ) == 0) + return 0xFF; + + switch (unittester.cmd_id) { + case UT_CMD_CAPTURE_SCREEN_SNAPSHOT: + switch (unittester.read_offs) { + case 0: + outval = (uint8_t) (unittester.snap_img_width); + break; + case 1: + outval = (uint8_t) (unittester.snap_img_width >> 8); + break; + case 2: + outval = (uint8_t) (unittester.snap_img_height); + break; + case 3: + outval = (uint8_t) (unittester.snap_img_height >> 8); + break; + case 4: + outval = (uint8_t) (unittester.snap_overscan_width); + break; + case 5: + outval = (uint8_t) (unittester.snap_overscan_width >> 8); + break; + case 6: + outval = (uint8_t) (unittester.snap_overscan_height); + break; + case 7: + outval = (uint8_t) (unittester.snap_overscan_height >> 8); + break; + case 8: + outval = (uint8_t) (unittester.snap_img_xoffs); + break; + case 9: + outval = (uint8_t) (unittester.snap_img_xoffs >> 8); + break; + case 10: + outval = (uint8_t) (unittester.snap_img_yoffs); + break; + case 11: + outval = (uint8_t) (unittester.snap_img_yoffs >> 8); + break; + default: + break; + } + break; + + case UT_CMD_READ_SCREEN_SNAPSHOT_RECTANGLE: + outval = unittester_read_snap_rect_idx(unittester.read_offs); + break; + + case UT_CMD_VERIFY_SCREEN_SNAPSHOT_RECTANGLE: + outval = (uint8_t) (unittester.read_snap_crc >> (8 * unittester.read_offs)); + break; + + /* This should not be reachable, but just in case... */ + default: + break; + } + + /* Advance read buffer */ + unittester.read_offs += 1; + if (unittester.read_offs >= unittester.read_len) { + /* Once fully read, we stop here. */ + unittester.cmd_id = UT_CMD_NOOP; + unittester.status = UT_STATUS_IDLE; + } + + return outval; + } else { + /* Not handled here - possibly open bus! */ + return 0xFF; + } +} + +static void +unittester_trigger_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) +{ + /* This one gets quite spammy. */ + /* unittester_log("[UT] Trigger value %02X -> FSM1 = %02X, FSM2 = %02X, IOBASE = %04X\n", val, unittester.fsm1, unittester.fsm2, unittester.iobase_port); */ + + /* Update FSM2 */ + switch (unittester.fsm2) { + /* IDLE: Do nothing - FSM1 will put us in the right state. */ + case UT_FSM2_IDLE: + unittester.fsm2 = UT_FSM2_IDLE; + break; + + /* WAIT IOBASE 0: Set low byte of temporary IOBASE. */ + case UT_FSM2_WAIT_IOBASE_0: + unittester.fsm2_new_iobase = ((uint16_t) val); + unittester.fsm2 = UT_FSM2_WAIT_IOBASE_1; + break; + + /* WAIT IOBASE 0: Set high byte of temporary IOBASE and commit to the real IOBASE. */ + case UT_FSM2_WAIT_IOBASE_1: + unittester.fsm2_new_iobase |= ((uint16_t) val) << 8; + + unittester_log("[UT] Remapping IOBASE: %04X -> %04X\n", unittester.iobase_port, unittester.fsm2_new_iobase); + + /* Unmap old IOBASE */ + if (unittester.iobase_port != 0xFFFF) + io_removehandler(unittester.iobase_port, 2, unittester_read, NULL, NULL, unittester_write, NULL, NULL, NULL); + unittester.iobase_port = 0xFFFF; + + /* Map new IOBASE */ + unittester.iobase_port = unittester.fsm2_new_iobase; + if (unittester.iobase_port != 0xFFFF) + io_sethandler(unittester.iobase_port, 2, unittester_read, NULL, NULL, unittester_write, NULL, NULL, NULL); + + /* Reset FSM2 to IDLE */ + unittester.fsm2 = UT_FSM2_IDLE; + break; + } + + /* Update FSM1 */ + switch (val) { + case '8': + unittester.fsm1 = UT_FSM1_WAIT_6; + break; + case '6': + if (unittester.fsm1 == UT_FSM1_WAIT_6) + unittester.fsm1 = UT_FSM1_WAIT_B; + else + unittester.fsm1 = UT_FSM1_WAIT_8; + break; + case 'B': + if (unittester.fsm1 == UT_FSM1_WAIT_B) + unittester.fsm1 = UT_FSM1_WAIT_o; + else + unittester.fsm1 = UT_FSM1_WAIT_8; + break; + case 'o': + if (unittester.fsm1 == UT_FSM1_WAIT_o) + unittester.fsm1 = UT_FSM1_WAIT_x; + else + unittester.fsm1 = UT_FSM1_WAIT_8; + break; + case 'x': + if (unittester.fsm1 == UT_FSM1_WAIT_x) { + unittester_log("[UT] Config activated, awaiting new IOBASE\n"); + unittester.fsm2 = UT_FSM2_WAIT_IOBASE_0; + } + unittester.fsm1 = UT_FSM1_WAIT_8; + break; + + default: + unittester.fsm1 = UT_FSM1_WAIT_8; + break; + } +} + +static void * +unittester_init(UNUSED(const device_t *info)) +{ + unittester = (struct unittester_state) unittester_defaults; + + unittester_exit_enabled = !!device_get_config_int("exit_enabled"); + + if (unittester_screen_buffer == NULL) + unittester_screen_buffer = create_bitmap(2048, 2048); + + io_sethandler(unittester.trigger_port, 1, NULL, NULL, NULL, unittester_trigger_write, NULL, NULL, NULL); + + unittester_log("[UT] 86Box Unit Tester initialised\n"); + + return &unittester; /* Dummy non-NULL value */ +} + +static void +unittester_close(UNUSED(void *priv)) +{ + io_removehandler(unittester.trigger_port, 1, NULL, NULL, NULL, unittester_trigger_write, NULL, NULL, NULL); + + if (unittester.iobase_port != 0xFFFF) + io_removehandler(unittester.iobase_port, 2, unittester_read, NULL, NULL, unittester_write, NULL, NULL, NULL); + unittester.iobase_port = 0xFFFF; + + if (unittester_screen_buffer != NULL) { + destroy_bitmap(unittester_screen_buffer); + unittester_screen_buffer = NULL; + } + + unittester_log("[UT] 86Box Unit Tester closed\n"); +} + +const device_t unittester_device = { + .name = "86Box Unit Tester", + .internal_name = "unittester", + .flags = DEVICE_ISA, + .local = 0, + .init = unittester_init, + .close = unittester_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = unittester_config, +}; diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index 7771a0b72..87b9593fa 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -15,7 +15,8 @@ add_library(hdd OBJECT hdd.c hdd_image.c hdd_table.c hdc.c hdc_st506_xt.c hdc_st506_at.c hdc_xta.c hdc_esdi_at.c hdc_esdi_mca.c hdc_xtide.c - hdc_ide.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c hdc_ide_sff8038i.c) + hdc_ide.c hdc_ide_ali5213.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c + hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c lba_enhancer.c) add_library(zip OBJECT zip.c) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 07df9d0e6..034b8890e 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -100,17 +100,16 @@ static const struct { { &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 }, + { &mcide_device }, { NULL } // clang-format on }; diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 65184094a..e16d4d729 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -129,23 +129,24 @@ esdi_at_log(const char *fmt, ...) static __inline void irq_raise(esdi_t *esdi) { - if (!(esdi->fdisk & 2)) - picint(1 << 14); - esdi->irqstat = 1; + if (!(esdi->fdisk & 2)) + picint_common(1 << 14, PIC_IRQ_EDGE, 1, NULL); } static __inline void -irq_lower(UNUSED(esdi_t *esdi)) +irq_lower(esdi_t *esdi) { - picintc(1 << 14); + esdi->irqstat = 0; + if (!(esdi->fdisk & 2)) + picint_common(1 << 14, PIC_IRQ_EDGE, 0, NULL); } static __inline void -irq_update(UNUSED(esdi_t *esdi)) +irq_update(esdi_t *esdi) { - if (esdi->irqstat && !((pic2.irr | pic2.isr) & 0x40) && !(esdi->fdisk & 2)) - picint(1 << 14); + uint8_t set = !(esdi->fdisk & 2) && esdi->irqstat; + picint_common(1 << 14, PIC_IRQ_EDGE, set, NULL); } static void @@ -213,6 +214,41 @@ get_sector(esdi_t *esdi, off64_t *addr) return 0; } +static int +get_sector_format(esdi_t *esdi, off64_t *addr) +{ + 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; + + if (esdi->head > heads) { + esdi_at_log("esdi_get_sector: past end of configured heads\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); + } else { + /* + * When performing translation, the firmware seems to leave 1 + * sector per track inaccessible (spare sector) + */ + + *addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) * sectors); + + 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; + } + + return 0; +} + /* Move to the next sector using CHS addressing. */ static void next_sector(esdi_t *esdi) @@ -263,6 +299,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) double seek_time; double xfer_time; off64_t addr; + uint8_t old; esdi_at_log("WD1007 write(%04x, %02x)\n", port, val); @@ -411,15 +448,15 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi_set_callback(esdi, 500 * HDC_TIME); esdi->reset = 1; esdi->status = STAT_BUSY; - } - - if (val & 0x04) { + } else if (!(esdi->fdisk & 0x04) && (val & 0x04)) { /* Drive held in reset. */ esdi_set_callback(esdi, 0); esdi->status = STAT_BUSY; } + old = esdi->fdisk; esdi->fdisk = val; - irq_update(esdi); + if (!(val & 0x02) && (old & 0x02)) + irq_update(esdi); break; default: @@ -653,7 +690,7 @@ esdi_callback(void *priv) irq_raise(esdi); break; } else { - if (get_sector(esdi, &addr)) { + if (get_sector_format(esdi, &addr)) { esdi->error = ERR_ID_NOT_FOUND; esdi->status = STAT_READY | STAT_DSC | STAT_ERR; irq_raise(esdi); diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 02f054ca2..c906c7ca1 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -92,7 +92,7 @@ #define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin" #define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin" -#define ESDI_TIME 512.0 +#define ESDI_TIME 500.0 #define CMD_ADAPTER 0 typedef struct esdi_drive_t { @@ -113,6 +113,7 @@ typedef struct esdi_t { uint8_t basic_ctrl; uint8_t status; uint8_t irq_status; + int irq_ena_disable; int irq_in_progress; int cmd_req_in_progress; int cmd_pos; @@ -218,14 +219,26 @@ esdi_mca_log(const char *fmt, ...) static __inline void set_irq(esdi_t *dev) { + dev->irq_ena_disable = 1; + esdi_mca_log("Set IRQ 14: bit=%x, cmd=%02x.\n", dev->basic_ctrl & CTRL_IRQ_ENA, dev->command); if (dev->basic_ctrl & CTRL_IRQ_ENA) - picint(1 << 14); + picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, 1, NULL); } static __inline void -clear_irq(UNUSED(esdi_t *dev)) +clear_irq(esdi_t *dev) { - picintc(1 << 14); + dev->irq_ena_disable = 0; + esdi_mca_log("Clear IRQ 14: bit=%x, cmd=%02x.\n", dev->basic_ctrl & CTRL_IRQ_ENA, dev->command); + if (dev->basic_ctrl & CTRL_IRQ_ENA) + picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, 0, NULL); +} + +static __inline void +update_irq(esdi_t *dev) +{ + uint8_t set = (dev->basic_ctrl & CTRL_IRQ_ENA) && dev->irq_ena_disable; + picint_common(1 << ESDI_IRQCHAN, PIC_IRQ_EDGE, set, NULL); } static void @@ -235,10 +248,11 @@ esdi_mca_set_callback(esdi_t *dev, double callback) return; } - if (callback) { - timer_on_auto(&dev->timer, callback); - } else { + if (callback == 0.0) { + esdi_mca_log("Callback Stopped.\n"); timer_stop(&dev->timer); + } else { + timer_on_auto(&dev->timer, callback); } } @@ -317,9 +331,9 @@ 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] = dev->command | STATUS_LEN(7) | STATUS_DEVICE(0); else - dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1); + dev->status_data[0] = dev->command | 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*/ @@ -330,15 +344,12 @@ complete_command_status(esdi_t *dev) } #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; \ @@ -346,8 +357,7 @@ complete_command_status(esdi_t *dev) if (dev->cmd_dev == ATTN_DEVICE_0) \ drive = &dev->drives[0]; \ else \ - drive = &dev->drives[1]; \ - } while (0) + drive = &dev->drives[1]; static void esdi_callback(void *priv) @@ -357,19 +367,19 @@ esdi_callback(void *priv) 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) { + esdi_mca_log("ESDI reset.\n"); dev->in_reset = 0; dev->status = STATUS_IRQ; dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE; - return; } + esdi_mca_log("Command=%02x.\n", dev->command); switch (dev->command) { case CMD_READ: + case 0x15: ESDI_DRIVE_ONLY(); if (!drive->present) { @@ -379,7 +389,8 @@ esdi_callback(void *priv) switch (dev->cmd_state) { case 0: - dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + if (dev->command == CMD_READ) + dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; dev->sector_pos = 0; dev->sector_count = dev->cmd_data[1]; @@ -820,14 +831,12 @@ esdi_callback(void *priv) switch (dev->cmd_state) { case 0: - dev->rba = (dev->cmd_data[2] | (dev->cmd_data[3] << 16)) & 0x0fffffff; + dev->rba = hdd_image_get_last_sector(drive->hdd_num); - 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 (dev->command == CMD_FORMAT_UNIT) + dev->sector_count = dev->cmd_data[1]; + else + dev->sector_count = 0; dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ; dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY; @@ -844,7 +853,8 @@ esdi_callback(void *priv) return; } - hdd_image_zero(drive->hdd_num, dev->rba, dev->sector_count); + if (dev->command == CMD_FORMAT_UNIT) + hdd_image_zero(drive->hdd_num, 0, hdd_image_get_last_sector(drive->hdd_num) + 1); dev->status = STATUS_CMD_IN_PROGRESS; dev->cmd_state = 2; @@ -873,7 +883,7 @@ static uint8_t esdi_read(uint16_t port, void *priv) { esdi_t *dev = (esdi_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0x00; switch (port & 7) { case 2: /*Basic status register*/ @@ -890,6 +900,7 @@ esdi_read(uint16_t port, void *priv) break; } + esdi_mca_log("ESDI: rr(%04x, %02x)\n", port & 7, ret); return ret; } @@ -897,6 +908,7 @@ static void esdi_write(uint16_t port, uint8_t val, void *priv) { esdi_t *dev = (esdi_t *) priv; + uint8_t old; esdi_mca_log("ESDI: wr(%04x, %02x)\n", port & 7, val); @@ -906,11 +918,14 @@ esdi_write(uint16_t port, uint8_t val, void *priv) dev->in_reset = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); dev->status = STATUS_BUSY; + } else if (!(dev->basic_ctrl & CTRL_RESET) && (val & CTRL_RESET)) { + esdi_mca_set_callback(dev, 0.0); + dev->status = STATUS_BUSY; } + old = dev->basic_ctrl; dev->basic_ctrl = val; - - if (!(dev->basic_ctrl & CTRL_IRQ_ENA)) - picintc(1 << 14); + if ((val & CTRL_IRQ_ENA) && !(old & CTRL_IRQ_ENA)) + update_irq(dev); break; case 3: /*Attention register*/ @@ -945,6 +960,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) break; case ATTN_DEVICE_0: + esdi_mca_log("ATTN Device 0.\n"); switch (val & ATTN_REQ_MASK) { case ATTN_CMD_REQ: if (dev->cmd_req_in_progress) @@ -957,6 +973,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) break; case ATTN_EOI: + esdi_mca_log("EOI.\n"); dev->irq_in_progress = 0; dev->status &= ~STATUS_IRQ; clear_irq(dev); @@ -1112,15 +1129,40 @@ esdi_mca_write(int port, uint8_t val, void *priv) break; } + if (!(dev->pos_regs[3] & 8)) { + switch (dev->pos_regs[3] & 7) { + case 2: + dev->bios = 0xc8000; + break; + case 3: + dev->bios = 0xcc000; + break; + case 4: + dev->bios = 0xd0000; + break; + case 5: + dev->bios = 0xd4000; + break; + case 6: + dev->bios = 0xd8000; + break; + case 7: + dev->bios = 0xdc000; + break; + default: + break; + } + } else + dev->bios = 0; + if (dev->pos_regs[2] & 1) { io_sethandler(ESDI_IOADDR_PRI, 8, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, dev); - if (!(dev->pos_regs[3] & 8)) { + if (dev->bios) { mem_mapping_enable(&dev->bios_rom.mapping); - mem_mapping_set_addr(&dev->bios_rom.mapping, - ((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000); + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->bios, 0x4000); } /* Say hello. */ diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 2bb83b4ab..3793f778b 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -30,8 +30,10 @@ #include "cpu.h" #include <86box/machine.h> #include <86box/io.h> +#include <86box/mca.h> #include <86box/mem.h> #include <86box/pic.h> +#include <86box/rom.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/timer.h> @@ -89,15 +91,15 @@ #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_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_IDENTIFY 0xec /* Ask drive to identify itself */ +#define WIN_SET_FEATURES 0xef #define WIN_READ_NATIVE_MAX 0xf8 #define FEATURE_SET_TRANSFER_MODE 0x03 @@ -112,6 +114,8 @@ #define IDE_ATAPI_IS_EARLY ide->sc->pad0 +#define ROM_PATH_MCIDE "roms/hdd/xtide/ide_ps2 R1.1.bin" + 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); @@ -135,6 +139,12 @@ typedef struct ide_board_t { ide_bm_t *bm; } ide_board_t; +typedef struct mcide_t { + uint8_t pos_regs[8]; + uint32_t bios_addr; + rom_t bios_rom; +} mcide_t; + ide_board_t *ide_boards[IDE_BUS_MAX]; static uint8_t ide_ter_pnp_rom[] = { @@ -367,7 +377,7 @@ ide_atapi_get_period(uint8_t channel) ide_log("ide_atapi_get_period(%i)\n", channel); - if (!ide) { + if (ide == NULL) { ide_log("Get period failed\n"); return -1.0; } @@ -401,7 +411,7 @@ ide_irq_update(ide_board_t *dev, int log) void ide_irq(ide_t *ide, int set, int log) { - if (!ide_boards[ide->board]) + if (ide_boards[ide->board] == NULL) return; #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) @@ -427,7 +437,7 @@ ide_irq(ide_t *ide, int set, int log) * this length will be padded with spaces. */ void -ide_padstr(char *str, const char *src, int len) +ide_padstr(char *str, const char *src, const int len) { int v; @@ -461,37 +471,39 @@ ide_padstr8(uint8_t *buf, int buf_size, const char *src) } static int -ide_get_max(ide_t *ide, int type) +ide_is_ata4(const ide_board_t *board) { - 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 } }; + const ide_bm_t *bm = board->bm; + + return (!board->force_ata3 && (bm != NULL)); +} + +static int +ide_get_max(const ide_t *ide, const int type) +{ + const int ata_4 = ide_is_ata4(ide_boards[ide->board]); + const int max[2][4] = { { 0, -1, -1, -1 }, { 4, 2, 2, 5 } }; + int ret; if (ide->type == IDE_ATAPI) 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); + ret = max[ata_4][type]; return ret; } static int -ide_get_timings(ide_t *ide, int type) +ide_get_timings(const ide_t *ide, const 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 } }; + const int ata_4 = ide_is_ata4(ide_boards[ide->board]); + const int timings[2][3] = { { 0, 0, 0 }, { 120, 120, 0 } }; + int ret; if (ide->type == IDE_ATAPI) 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); + ret = timings[ata_4][type]; return ret; } @@ -500,30 +512,33 @@ ide_get_timings(ide_t *ide, int type) * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command */ static void -ide_hd_identify(ide_t *ide) +ide_hd_identify(const 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; - 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); + const ide_bm_t *bm = ide_boards[ide->board]->bm; + 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; ide_log("IDE Identify: %s\n", device_identify); - d_spt = ide->spt; - if (ide->hpc <= 16) { + uint32_t d_hpc = ide->hpc; + uint32_t d_spt = ide->spt; + uint32_t d_tracks; + + if ((ide->hpc <= 16) && (ide->spt <= 63)) { /* 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; + if (ide->hpc > 16) + d_hpc = 16; + if (ide->spt > 63) + d_spt = 63; + d_tracks = (ide->tracks * ide->hpc * ide->spt) / (16 * 63); + if (d_tracks > 16383) + d_tracks = 16383; } /* Specify default CHS translation */ @@ -569,7 +584,7 @@ ide_hd_identify(ide_t *ide) */ ide->buffer[53] = 1; - if (ide->cfg_spt != 0) { + if (ide->params_specified) { ide->buffer[54] = (full_size / ide->cfg_hpc) / ide->cfg_spt; ide->buffer[55] = ide->cfg_hpc; ide->buffer[56] = ide->cfg_spt; @@ -728,25 +743,47 @@ ide_get_sector(ide_t *ide) } } +static off64_t +ide_get_sector_format(ide_t *ide) +{ + uint32_t heads; + uint32_t sectors; + + if (ide->tf->lba) + return (off64_t) ide->lba_addr; + else { + heads = ide->cfg_hpc; + sectors = ide->cfg_spt; + + return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->tf->head) * sectors); + } +} + /** * Move to the next sector using CHS addressing */ static void ide_next_sector(ide_t *ide) { + uint32_t sector = ide->tf->sector; + uint32_t head = ide->tf->head; + if (ide->tf->lba) ide->lba_addr++; else { - 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; + sector++; + if ((sector == 0) || (sector == (ide->cfg_spt + 1))) { + sector = 1; + head++; + if (head == ide->cfg_hpc) { + head = 0; ide->tf->cylinder++; } } } + + ide->tf->sector = sector & 0xff; + ide->tf->head = head & 0x0f; } static void @@ -941,7 +978,7 @@ ide_atapi_attach(ide_t *ide) void ide_set_callback(ide_t *ide, double callback) { - if (!ide) { + if (ide == NULL) { ide_log("ide_set_callback(NULL): Set callback failed\n"); return; } @@ -961,7 +998,7 @@ ide_set_board_callback(uint8_t board, double callback) ide_log("ide_set_board_callback(%i)\n", board); - if (!dev) { + if (dev == NULL) { ide_log("Set board callback failed\n"); return; } @@ -1054,13 +1091,15 @@ ide_atapi_callback(ide_t *ide) /* Else, DMA command without a bus master, ret = 0 (default). */ switch (ret) { + default: + break; 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); + (void) ide->phase_data_out(ide->sc); else if (!out && ide->command_stop) ide->command_stop(ide->sc); @@ -1122,7 +1161,7 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) } static uint16_t -ide_atapi_packet_read(ide_t *ide, int length) +ide_atapi_packet_read(ide_t *ide) { scsi_common_t *dev = ide->sc; const uint16_t *bufferw; @@ -1138,15 +1177,10 @@ ide_atapi_packet_read(ide_t *ide, int length) 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++; - } + ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0; + ide->tf->pos += 2; + + dev->request_pos += 2; if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ @@ -1158,7 +1192,7 @@ ide_atapi_packet_read(ide_t *ide, int length) } static void -ide_atapi_packet_write(ide_t *ide, uint16_t val, int length) +ide_atapi_packet_write(ide_t *ide, const uint16_t val) { scsi_common_t *dev = ide->sc; @@ -1175,15 +1209,10 @@ ide_atapi_packet_write(ide_t *ide, uint16_t val, int length) } 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++; - } + bufferw[ide->tf->pos >> 1] = val & 0xffff; + + ide->tf->pos += 2; + dev->request_pos += 2; if (dev->packet_status == PHASE_DATA_OUT) { if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { @@ -1202,32 +1231,26 @@ ide_atapi_packet_write(ide_t *ide, uint16_t val, int length) } static void -ide_write_data(ide_t *ide, uint16_t val, int length) +ide_write_data(ide_t *ide, const uint16_t val) { - uint8_t *idebufferb = (uint8_t *) ide->buffer; uint16_t *idebufferw = ide->buffer; 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); + ide_atapi_packet_write(ide, val); 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++; - } + idebufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; 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; + const double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + const double xfer_time = ide_get_xfer_time(ide, 512); + const 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); @@ -1265,7 +1288,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) switch (addr) { case 0x0: /* Data */ - ide_write_data(ide, val, 2); + ide_write_data(ide, val); break; case 0x7: ide_writeb(addr, val & 0xff, priv); @@ -1299,9 +1322,9 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) switch (addr) { case 0x0: /* Data */ - ide_write_data(ide, val & 0xffff, 2); + ide_write_data(ide, val & 0xffff); if (dev->bit32) - ide_write_data(ide, val >> 16, 2); + ide_write_data(ide, val >> 16); else ide_writew(addr + 2, (val >> 16) & 0xffff, priv); break; @@ -1389,8 +1412,15 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) } else { /* Currently active device is 1, simply reset the status and the active device. */ dev_reset(ide); - ide->tf->atastat = DRDY_STAT | DSC_STAT; + if (ide->type == IDE_ATAPI) { + /* Non-early ATAPI devices have DRDY clear after SRST. */ + ide->tf->atastat = 0; + if (IDE_ATAPI_IS_EARLY) + ide->tf->atastat |= DRDY_STAT; + } else + ide->tf->atastat = DRDY_STAT | DSC_STAT; ide->tf->error = 1; + ide_other->tf->error = 1; /* Assert PDIAG-. */ dev->cur_dev &= ~1; ch = dev->cur_dev; @@ -1448,7 +1478,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) if ((ide->type != IDE_NONE) || ((addr != 0x0) && (addr != 0x7))) switch (addr) { case 0x0: /* Data */ - ide_write_data(ide, val | (val << 8), 2); + ide_write_data(ide, val | (val << 8)); break; /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ @@ -1566,8 +1596,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->tf->error = 0; switch (val) { - case WIN_RECAL ... 0x1F: - case WIN_SEEK ... 0x7F: + case WIN_RECAL ... 0x1f: + case WIN_SEEK ... 0x7f: if (ide->type == IDE_ATAPI) ide->tf->atastat = DRDY_STAT; else @@ -1616,7 +1646,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) uint32_t sec_count; double wait_time; if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { - /* TODO make DMA timing more accurate */ + /* 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); @@ -1771,7 +1801,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->tf->error = ABRT_ERR; ide_irq_raise(ide); } - return; + break; default: break; @@ -1779,39 +1809,28 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) } static uint16_t -ide_read_data(ide_t *ide, int length) +ide_read_data(ide_t *ide) { - const uint8_t *idebufferb = (uint8_t *) ide->buffer; const uint16_t *idebufferw = ide->buffer; - uint16_t ret = 0; - double seek_us; - double xfer_us; + uint16_t ret = 0x0000; #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) - ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ch, + ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ide->channel, ide->board, ide->type); #endif - 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_NONE) || (ide->type & IDE_SHADOW) || (ide->buffer == NULL)) + ret = 0xff7f; + else if (ide->command == WIN_PACKETCMD) { if (ide->type == IDE_ATAPI) - ret = ide_atapi_packet_read(ide, length); + ret = ide_atapi_packet_read(ide); else { ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos); ide->tf->pos = 0; } } else { - if (length == 2) { - ret = idebufferw[ide->tf->pos >> 1]; - ide->tf->pos += 2; - } else { - ret = idebufferb[ide->tf->pos]; - ide->tf->pos++; - } + ret = idebufferw[ide->tf->pos >> 1]; + ide->tf->pos += 2; if (ide->tf->pos >= 512) { ide->tf->pos = 0; @@ -1822,6 +1841,7 @@ ide_read_data(ide_t *ide, int length) if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || (ide->command == WIN_READ_MULTIPLE)) { + ide->tf->secount--; if (ide->tf->secount) { @@ -1833,16 +1853,16 @@ ide_read_data(ide_t *ide, int length) 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); + const double seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), cnt); + const double 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); + const double seek_us = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), 1); + const double xfer_us = ide_get_xfer_time(ide, 512); ide_set_callback(ide, seek_us + xfer_us); } } else @@ -1868,7 +1888,8 @@ ide_status(ide_t *ide, ide_t *ide_other, int ch) /* 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; + // ret = 0x00; + ret = 0x01; } else { ret = ide->tf->atastat; if (ide->type == IDE_ATAPI) @@ -1891,7 +1912,7 @@ ide_readb(uint16_t addr, void *priv) switch (addr & 0x7) { case 0x0: /* Data */ - ret = ide_read_data(ide, 2) & 0xff; + ret = ide_read_data(ide) & 0xff; break; /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), @@ -1948,8 +1969,8 @@ ide_readb(uint16_t addr, void *priv) 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); + ide_log("Cylinder high @ board %i, channel %i: ide->type = %i, " + "ret = %02X\n", ide->board, ide->channel, ide->type, ret); #endif break; @@ -1972,53 +1993,45 @@ ide_readb(uint16_t addr, void *priv) } ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret); + return ret; } uint8_t -ide_read_alt_status(UNUSED(uint16_t addr), void *priv) +ide_read_alt_status(UNUSED(const uint16_t addr), void *priv) { - uint8_t ret = 0xff; - const ide_board_t *dev = (ide_board_t *) priv; - ide_t *ide; - int ch; - - ch = dev->cur_dev; - ide = ide_drives[ch]; + const int ch = dev->cur_dev; + ide_t * ide = ide_drives[ch]; /* Per the Seagate ATA-3 specification: Reading the alternate status does *NOT* clear the IRQ. */ - ret = ide_status(ide, ide_drives[ch ^ 1], ch); + const uint8_t ret = ide_status(ide, ide_drives[ch ^ 1], ch); 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 ret = 0xffff; - const ide_board_t *dev = (ide_board_t *) priv; - - ide_t *ide; - int ch; - - ch = dev->cur_dev; - ide = ide_drives[ch]; + const int ch = dev->cur_dev; + ide_t * ide = ide_drives[ch]; + uint16_t ret; switch (addr & 0x7) { + default: + ret = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); + break; case 0x0: /* Data */ - ret = ide_read_data(ide, 2); + ret = ide_read_data(ide); break; case 0x7: ret = ide_readb(addr, priv) | 0xff00; break; - default: - ret = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); - break; } #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) @@ -2030,20 +2043,16 @@ ide_readw(uint16_t addr, void *priv) static uint32_t ide_readl(uint16_t addr, void *priv) { - ide_t *ide; - int ch; - uint32_t ret = 0xffffffff; - const ide_board_t *dev = (ide_board_t *) priv; - - ch = dev->cur_dev; - ide = ide_drives[ch]; + const int ch = dev->cur_dev; + ide_t * ide = ide_drives[ch]; + uint32_t ret; switch (addr & 0x7) { case 0x0: /* Data */ - ret = ide_read_data(ide, 2); + ret = ide_read_data(ide); if (dev->bit32) - ret |= (ide_read_data(ide, 2) << 16); + ret |= (ide_read_data(ide) << 16); else ret |= (ide_readw(addr + 2, priv) << 16); break; @@ -2070,7 +2079,11 @@ ide_board_callback(void *priv) ide_log("ide_board_callback(%i)\n", dev->cur_dev >> 1); - for (uint8_t i = 0; i < 2; i++) { + dev->cur_dev &= ~1; + + /* Reset the devices in reverse so if there's a slave without a master, + its copy of the master's task file gets reset first. */ + for (int8_t i = 1; i >= 0; i--) { ide = dev->ide[i]; if (ide->type == IDE_ATAPI) { ide->tf->atastat = 0; @@ -2078,9 +2091,9 @@ ide_board_callback(void *priv) ide->tf->atastat |= DRDY_STAT | DSC_STAT; } else ide->tf->atastat = DRDY_STAT | DSC_STAT; - } - dev->cur_dev &= ~1; + ide->reset = 0; + } ide = dev->ide[0]; if (dev->diag) { @@ -2104,12 +2117,11 @@ atapi_error_no_ready(ide_t *ide) static void ide_callback(void *priv) { - 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_t * ide = (ide_t *) priv; + const ide_bm_t *bm = ide_boards[ide->board]->bm; + int chk_chs; + int ret; + uint8_t err = 0x00; ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command); @@ -2119,8 +2131,9 @@ ide_callback(void *priv) 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))) + /* The J-Bond PCI400C-A Phoenix BIOS implies that this command is supposed to + ignore the sector number. */ + if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->tf->head >= ide->hpc))) err = IDNF_ERR; else { ide->tf->atastat = DRDY_STAT | DSC_STAT; @@ -2142,7 +2155,7 @@ ide_callback(void *priv) 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->tf->error = 1; /*Device passed*/ ide->tf->secount = 1; ide->tf->sector = 1; @@ -2224,7 +2237,7 @@ ide_callback(void *priv) ide->tf->pos = 0; - if (!ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { + if (!ide_boards[ide->board]->force_ata3 && 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) { @@ -2287,6 +2300,9 @@ ide_callback(void *priv) case WIN_WRITE: case WIN_WRITE_NORETRY: +#ifdef ENABLE_IDE_LOG + off64_t sector = ide_get_sector(ide); +#endif if (ide->type == IDE_ATAPI) err = ABRT_ERR; else if (!ide->tf->lba && (ide->cfg_spt == 0)) @@ -2305,6 +2321,7 @@ ide_callback(void *priv) ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } } + ide_log("Write: %02X, %i, %08X, %" PRIi64 "\n", err, ide->hdd_num, ide->lba_addr, sector); break; case WIN_WRITE_DMA: @@ -2316,7 +2333,7 @@ ide_callback(void *priv) 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_boards[ide->board]->force_ata3 && bm->dma) { if (ide->tf->secount) ide->sector_pos = ide->tf->secount; else @@ -2402,7 +2419,7 @@ ide_callback(void *priv) 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); + hdd_image_zero(ide->hdd_num, ide_get_sector_format(ide), ide->tf->secount); ide->tf->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); @@ -2415,10 +2432,12 @@ ide_callback(void *priv) if (ide->type == IDE_ATAPI) err = ABRT_ERR; else { - if (ide->cfg_spt == 0) { - /* Only accept after RESET or DIAG. */ + /* Only accept after RESET or DIAG. */ + if (ide->params_specified) { ide->cfg_spt = ide->tf->secount; ide->cfg_hpc = ide->tf->head + 1; + + ide->params_specified = 1; } ide->command = 0x00; ide->tf->atastat = DRDY_STAT | DSC_STAT; @@ -2446,6 +2465,7 @@ ide_callback(void *priv) else { ide->blocksize = ide->tf->secount; ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); } break; @@ -2465,7 +2485,7 @@ ide_callback(void *priv) case WIN_READ_NATIVE_MAX: if (ide->type == IDE_HDD) { - snum = hdd[ide->hdd_num].spt; + int snum = hdd[ide->hdd_num].spt; snum *= hdd[ide->hdd_num].hpc; snum *= hdd[ide->hdd_num].tracks; ide_set_sector(ide, snum - 1); @@ -2595,6 +2615,15 @@ ide_set_base_addr(int board, int base, uint16_t port) ide_boards[board]->base[base] = port; } +void +ide_set_irq(int board, int irq) +{ + ide_log("ide_set_irq(%i, %i)\n", board, irq); + + if (ide_boards[board] != NULL) + ide_boards[board]->irq = irq; +} + static void ide_clear_bus_master(int board) { @@ -2666,10 +2695,8 @@ ide_board_close(int board) dev->buffer = NULL; } - if (dev) { - free(dev); - ide_drives[c] = NULL; - } + free(dev); + ide_drives[c] = NULL; } } @@ -2678,19 +2705,12 @@ ide_board_close(int board) } static void -ide_board_setup(int board) +ide_board_setup(const int board) { - ide_t *dev; - 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; + const int min_ch = (board << 1); + const int max_ch = min_ch + 1; + int c; + int d; ide_log("IDE: board %i: loading disks...\n", board); for (d = 0; d < 2; d++) { @@ -2700,14 +2720,10 @@ ide_board_setup(int board) c = 0; for (d = 0; d < HDD_NUM; d++) { - is_ide = (hdd[d].bus == HDD_BUS_IDE); - ch = hdd[d].ide_channel; + const int is_ide = (hdd[d].bus == HDD_BUS_IDE); + const int 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)); + const int valid_ch = ((ch >= min_ch) && (ch <= max_ch)); if (is_ide && valid_ch) { ide_log("Found IDE hard disk on channel %i\n", ch); @@ -2721,8 +2737,8 @@ ide_board_setup(int board) 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; + ide_t *dev = ide_drives[c]; if (dev->type == IDE_NONE) continue; @@ -2735,15 +2751,33 @@ ide_board_setup(int board) dev->tf->error = 1; if (dev->type != IDE_HDD) dev->cfg_spt = dev->cfg_hpc = 0; - if (dev->type == IDE_HDD) + if (dev->type == IDE_HDD) { dev->blocksize = hdd[dev->hdd_num].max_multiple_block; + + /* Calculate the default heads and sectors. */ + uint32_t d_hpc = dev->hpc; + uint32_t d_spt = dev->spt; + + if ((dev->hpc > 16) || (dev->spt > 63)) { + /* HPC > 16, convert to 16 HPC. */ + if (dev->hpc > 16) + d_hpc = 16; + if (dev->spt > 63) + d_spt = 63; + } + + dev->cfg_spt = d_spt; + dev->cfg_hpc = d_hpc; + } + + dev->params_specified = 0; } } static void -ide_board_init(int board, int irq, int base_main, int side_main, int type) +ide_board_init(int board, int irq, int base_main, int side_main, int type, int bus) { - ide_log("ide_board_init(%i, %i, %04X, %04X, %i)\n", board, irq, base_main, side_main, type); + ide_log("ide_board_init(%i, %i, %04X, %04X, %i, %i)\n", board, irq, base_main, side_main, type, bus); if ((ide_boards[board] != NULL) && ide_boards[board]->inited) return; @@ -2759,7 +2793,9 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->bit32 = 1; ide_boards[board]->base[0] = base_main; ide_boards[board]->base[1] = side_main; - ide_set_handlers(board); + + if (!(bus & DEVICE_MCA)) + ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_board_callback, ide_boards[board], 0); @@ -2768,6 +2804,36 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->inited = 1; } +/* Needed for ESS ES1688/968 PnP. */ +void +ide_pnp_config_changed_1addr(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + intptr_t board = (intptr_t) priv; + + 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[0] = (config->io[0].base != ISAPNP_IO_DISABLED) ? + config->io[0].base : 0x0000; + ide_boards[board]->base[1] = (config->io[0].base != ISAPNP_IO_DISABLED) ? + (config->io[0].base + 0x0206) : 0x0000; + + 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; + } +} + void ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { @@ -2811,12 +2877,12 @@ ide_ter_init(const device_t *info) irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(2, -1, 0, 0, 0); + ide_board_init(2, -1, 0, 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, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0); + ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0, 0); } return (ide_boards[2]); @@ -2843,12 +2909,12 @@ ide_qua_init(const device_t *info) irq = device_get_config_int("irq"); if (irq < 0) { - ide_board_init(3, -1, 0, 0, 0); + ide_board_init(3, -1, 0, 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); + ide_board_init(3, irq, HDC_QUATERNARY_BASE, HDC_QUATERNARY_SIDE, 0, 0); return (ide_boards[3]); } @@ -2863,7 +2929,7 @@ ide_qua_close(UNUSED(void *priv)) void * ide_xtide_init(void) { - ide_board_init(0, -1, 0, 0, 0); + ide_board_init(0, -1, 0, 0, 0, 0); return ide_boards[0]; } @@ -2899,10 +2965,10 @@ ide_init(const device_t *info) switch (info->local) { case 0 ... 5: - ide_board_init(0, 14, 0x1f0, 0x3f6, info->local); + ide_board_init(0, 14, 0x1f0, 0x3f6, info->local, info->flags); if (info->local & 1) - ide_board_init(1, 15, 0x170, 0x376, info->local); + ide_board_init(1, 15, 0x170, 0x376, info->local, info->flags); break; default: @@ -2961,6 +3027,22 @@ ide_board_reset(int board) ide_drive_reset(d); } +void +ide_drives_set_shadow(void) +{ + for (uint8_t d = 0; d < IDE_NUM; d++) { + if (ide_drives[d] == NULL) + continue; + + 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; + if (ide_drives[d]->tf != NULL) + free(ide_drives[d]->tf); + ide_drives[d]->tf = ide_drives[d ^ 1]->tf; + } + } +} + /* Reset a standalone IDE unit. */ static void ide_reset(UNUSED(void *priv)) @@ -2987,6 +3069,159 @@ ide_close(UNUSED(void *priv)) } } +static uint8_t +mcide_mca_read(const int port, void *priv) +{ + const mcide_t *dev = (mcide_t *) priv; + + ide_log("IDE: mcard(%04x)\n", port); + + return (dev->pos_regs[port & 7]); +} + +static void +mcide_mca_write(const int port, const uint8_t val, void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + uint16_t bases[4] = { 0x01f0, 0x0170, 0x01e8, 0x0168 }; + int irqs[4] = { 10, 11, 14, 15 }; + + if ((port >= 0x102) && (dev->pos_regs[port & 7] != val)) { + ide_log("IDE: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + port, val, dev->pos_regs[2], dev->pos_regs[3]); + + /* Save the new value. */ + dev->pos_regs[port & 7] = val; + + mem_mapping_disable(&dev->bios_rom.mapping); + dev->bios_addr = 0x00000000; + + ide_remove_handlers(0); + ide_boards[0]->base[0] = ide_boards[0]->base[1] = 0x0000; + + ide_boards[0]->irq = -1; + + ide_remove_handlers(1); + ide_boards[1]->base[0] = ide_boards[1]->base[1] = 0x0000; + + ide_boards[1]->irq = -1; + + if (dev->pos_regs[2] & 1) { + if (dev->pos_regs[2] & 0x80) + dev->bios_addr = 0x000c0000 + (0x00004000 * (uint32_t) ((dev->pos_regs[2] >> 4) & 0x07)); + + if (dev->pos_regs[3] & 0x08) { + ide_boards[0]->base[0] = bases[dev->pos_regs[3] & 0x03]; + ide_boards[0]->base[1] = bases[dev->pos_regs[3] & 0x03] + 0x0206; + } + + if (dev->pos_regs[3] & 0x80) + ide_boards[0]->irq = irqs[(dev->pos_regs[3] >> 4) & 0x03]; + + if (dev->pos_regs[4] & 0x08) { + ide_boards[1]->base[0] = bases[dev->pos_regs[4] & 0x03]; + ide_boards[1]->base[1] = bases[dev->pos_regs[4] & 0x03] + 0x0206; + } + + if (dev->pos_regs[4] & 0x80) + ide_boards[1]->irq = irqs[(dev->pos_regs[4] >> 4) & 0x03]; + + ide_set_handlers(0); + + ide_set_handlers(1); + + if (dev->bios_addr) + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->bios_addr, 0x00004000); + + /* Say hello. */ + ide_log("McIDE: Primary Master I/O=%03X, Primary IRQ=%02i, " + "Secondary Master I/O=%03X, Secondary IRQ=%02i, " + "BIOS @%05X\n", + ide_boards[0]->base[0], ide_boards[0]->irq, + ide_boards[1]->base[0], ide_boards[1]->irq, + dev->bios_addr); + } + } +} + +static uint8_t +mcide_mca_feedb(void *priv) +{ + const mcide_t *dev = (mcide_t *) priv; + + return (dev->pos_regs[2] & 1); +} + +static void +mcide_mca_reset(void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } + + ide_log("McIDE: MCA Reset.\n"); + mem_mapping_disable(&dev->bios_rom.mapping); + mcide_mca_write(0x102, 0, dev); +} + +static void +mcide_reset(void *priv) +{ + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } + + ide_log("McIDE: Reset.\n"); +} + +static void * +mcide_init(const device_t *info) +{ + ide_log("Initializing McIDE...\n"); + mcide_t *dev = (mcide_t *) calloc(1, sizeof(mcide_t)); + + ide_board_init(0, -1, 0, 0, info->local, info->flags); + ide_board_init(1, -1, 0, 0, info->local, info->flags); + + rom_init(&dev->bios_rom, ROM_PATH_MCIDE, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + + /* Set the MCA ID for this controller, 0xF171. */ + dev->pos_regs[0] = 0xf1; + dev->pos_regs[1] = 0x71; + + /* Enable the device. */ + mca_add(mcide_mca_read, mcide_mca_write, mcide_mca_feedb, mcide_mca_reset, dev); + + return dev; +} + +static int +mcide_available(void) +{ + return (rom_present(ROM_PATH_MCIDE)); +} + +static void +mcide_close(void *priv) +{ + mcide_t *dev = (mcide_t *) priv; + + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) { + ide_board_close(i); + ide_boards[i] = NULL; + } + } + + free(dev); +} + const device_t ide_isa_device = { .name = "ISA PC/AT IDE Controller", .internal_name = "ide_isa", @@ -3071,6 +3306,21 @@ const device_t ide_pci_2ch_device = { .config = NULL }; +const device_t mcide_device = { + .name = "MCA McIDE Controller", + .internal_name = "ide_mcide", + .flags = DEVICE_MCA, + .local = 3, + .init = mcide_init, + .close = mcide_close, + .reset = mcide_reset, + { .available = mcide_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + + // clang-format off static const device_config_t ide_ter_config[] = { { @@ -3178,5 +3428,5 @@ const device_t ide_qua_pnp_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = ide_qua_config + .config = NULL }; diff --git a/src/disk/hdc_ide_ali5213.c b/src/disk/hdc_ide_ali5213.c new file mode 100644 index 000000000..eee3844c4 --- /dev/null +++ b/src/disk/hdc_ide_ali5213.c @@ -0,0 +1,267 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 M1489 chipset. + * + * + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2020-2021 Tiseno100. + * Copyright 2020-2021 Miran Grca. + */ +#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/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/mem.h> +#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> + +#ifdef ENABLE_ALI5213_LOG +int ali5213_do_log = ENABLE_ALI5213_LOG; + +static void +ali5213_log(const char *fmt, ...) +{ + va_list ap; + + if (ali5213_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ali5213_log(fmt, ...) +#endif + +typedef struct ali5213_t { + uint8_t index; + uint8_t chip_id; + + uint8_t regs[256]; +} ali5213_t; + +static void +ali5213_ide_handler(ali5213_t *dev) +{ + ide_pri_disable(); + ide_sec_disable(); + if (dev->regs[0x01] & 0x01) { + ide_pri_enable(); + if (!(dev->regs[0x35] & 0x40)) + ide_sec_enable(); + } +} + +static void +ali5213_write(uint16_t addr, uint8_t val, void *priv) +{ + ali5213_t *dev = (ali5213_t *) priv; + + ali5213_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); + + switch (addr) { + case 0xf4: /* Usually it writes 30h here */ + dev->chip_id = val; + break; + + case 0xf8: + dev->index = val; + break; + + case 0xfc: + if (dev->chip_id != 0x30) + break; + + switch (dev->index) { + case 0x01: /* IDE Configuration Register */ + dev->regs[dev->index] = val & 0x8f; + ali5213_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->regs[dev->index] = val & 0x1f; + break; + case 0x07: /* Buffer Mode Register 1 */ + dev->regs[dev->index] = val; + break; + case 0x09: /* IDEPE1 IDE Port Enable Register 1 */ + dev->regs[dev->index] = val & 0xc3; + break; + case 0x0a: /* Buffer Mode Register 2 */ + dev->regs[dev->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->regs[dev->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->regs[dev->index] = val & 0x1f; + break; + case 0x35: /* IDEPE3 IDE Port Enable Register 3 */ + dev->regs[dev->index] = val; + ali5213_ide_handler(dev); + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +ali5213_read(uint16_t addr, void *priv) +{ + const ali5213_t *dev = (ali5213_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0xf4: + ret = dev->chip_id; + break; + case 0xfc: + ret = dev->regs[dev->index]; + break; + + default: + break; + } + + ali5213_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); + + return ret; +} + +static void +ali5213_reset(void *priv) +{ + ali5213_t *dev = (ali5213_t *) priv; + + memset(dev->regs, 0x00, 256); + + ide_pri_disable(); + ide_sec_disable(); + + /* IDE registers */ + dev->regs[0x00] = 0x57; + dev->regs[0x01] = 0x02; + dev->regs[0x08] = 0xff; + dev->regs[0x09] = 0x41; + dev->regs[0x0c] = 0x02; + dev->regs[0x0e] = 0x02; + dev->regs[0x10] = 0x02; + dev->regs[0x12] = 0x02; + dev->regs[0x34] = 0xff; + dev->regs[0x35] = 0x01; + + ali5213_ide_handler(dev); +} + +static void +ali5213_close(void *priv) +{ + ali5213_t *dev = (ali5213_t *) priv; + + free(dev); +} + +static void * +ali5213_init(UNUSED(const device_t *info)) +{ + ali5213_t *dev = (ali5213_t *) calloc(1, sizeof(ali5213_t)); + + /* M5213/M1489 IDE controller + F4h Chip ID we write always 30h onto it + F8h Index Port + FCh Data Port + */ + io_sethandler(0x0f4, 0x0001, ali5213_read, NULL, NULL, ali5213_write, NULL, NULL, dev); + io_sethandler(0x0f8, 0x0001, ali5213_read, NULL, NULL, ali5213_write, NULL, NULL, dev); + io_sethandler(0x0fc, 0x0001, ali5213_read, NULL, NULL, ali5213_write, NULL, NULL, dev); + + device_add(info->local ? &ide_pci_2ch_device : &ide_vlb_2ch_device); + + ali5213_reset(dev); + + return dev; +} + +const device_t ide_ali1489_device = { + .name = "ALi M1489 IDE", + .internal_name = "ali1489_ide", + .flags = 0, + .local = 1, + .init = ali5213_init, + .close = ali5213_close, + .reset = ali5213_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_ali5213_device = { + .name = "ALi M5213", + .internal_name = "ali5213", + .flags = 0, + .local = 0, + .init = ali5213_init, + .close = ali5213_close, + .reset = ali5213_reset, + { .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 3f43f80e6..631afa931 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -436,9 +436,9 @@ sff_bus_master_set_irq(uint8_t status, void *priv) case IRQ_MODE_SIS_551X: /* SiS 551x mode. */ if (irq) - pci_set_mirq(2, 1, &dev->irq_state); + pci_set_mirq(dev->mirq, 1, &dev->irq_state); else - pci_clear_mirq(2, 1, &dev->irq_state); + pci_clear_mirq(dev->mirq, 1, &dev->irq_state); break; } } @@ -554,6 +554,12 @@ sff_set_irq_pin(sff8038i_t *dev, int irq_pin) dev->irq_pin = irq_pin; } +void +sff_set_mirq(sff8038i_t *dev, uint8_t mirq) +{ + dev->mirq = mirq; +} + static void sff_close(void *priv) { @@ -586,6 +592,7 @@ sff_init(UNUSED(const device_t *info)) dev->pci_irq_line = 14; dev->irq_level = 0; dev->irq_state = 0; + dev->mirq = 2; dev->channel = next_id; next_id++; diff --git a/src/disk/hdc_ide_um8673f.c b/src/disk/hdc_ide_um8673f.c new file mode 100644 index 000000000..9ee149c7f --- /dev/null +++ b/src/disk/hdc_ide_um8673f.c @@ -0,0 +1,212 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 UMC UMF8673F IDE controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/mem.h> +#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> + +#ifdef ENABLE_UM8673F_LOG +int um8673f_do_log = ENABLE_UM8673F_LOG; + +static void +um8673f_log(const char *fmt, ...) +{ + va_list ap; + + if (um8673f_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define um8673f_log(fmt, ...) +#endif + +typedef struct um8673f_t { + uint8_t index; + uint8_t tries; + uint8_t unlocked; + + uint8_t regs[256]; +} um8673f_t; + +static void +um8673f_ide_handler(um8673f_t *dev) +{ + ide_pri_disable(); + ide_sec_disable(); + if (dev->regs[0xb0] & 0x80) + ide_pri_enable(); + if (dev->regs[0xb0] & 0x40) + ide_sec_enable(); +} + +static void +um8673f_write(uint16_t addr, uint8_t val, void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + um8673f_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); + + switch (addr) { + case 0x108: + if (dev->unlocked) { + if (dev->index == 0x34) { + dev->unlocked = 0; + dev->tries = 0; + } else + dev->index = val; + } else if (((dev->tries == 0) && (val == 0x4a)) || + ((dev->tries == 1) && (val == 0x6c))) { + dev->tries++; + if (dev->tries == 2) + dev->unlocked = 1; + } else + dev->tries = 0; + break; + + case 0x109: + switch (dev->index) { + case 0xb0: + dev->regs[dev->index] = val; + um8673f_ide_handler(dev); + break; + case 0xb1 ... 0xb8: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +um8673f_read(uint16_t addr, void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x108: + if (dev->unlocked) + ret = dev->index; + else + dev->tries = 0; + break; + case 0x109: + if ((dev->index >= 0xb0) && (dev->index <= 0xb8)) + ret = dev->regs[dev->index]; + break; + + default: + break; + } + + um8673f_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); + + return ret; +} + +static void +um8673f_reset(void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + memset(dev->regs, 0x00, 256); + + ide_pri_disable(); + ide_sec_disable(); + + /* IDE registers */ + dev->regs[0xb0] = 0xc0; + + um8673f_ide_handler(dev); +} + +static void +um8673f_close(void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + free(dev); +} + +static void * +um8673f_init(UNUSED(const device_t *info)) +{ + um8673f_t *dev = (um8673f_t *) calloc(1, sizeof(um8673f_t)); + + io_sethandler(0x0108, 0x0002, um8673f_read, NULL, NULL, um8673f_write, NULL, NULL, dev); + + device_add(info->local ? &ide_pci_2ch_device : &ide_vlb_2ch_device); + + um8673f_reset(dev); + + return dev; +} + +const device_t ide_um8886af_device = { + .name = "UMC UM8886F IDE", + .internal_name = "um8886af_ide", + .flags = 0, + .local = 1, + .init = um8673f_init, + .close = um8673f_close, + .reset = um8673f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_um8673f_device = { + .name = "UMC UM8673F", + .internal_name = "um8673f", + .flags = 0, + .local = 0, + .init = um8673f_init, + .close = um8673f_close, + .reset = um8673f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c new file mode 100644 index 000000000..ed34bc9fc --- /dev/null +++ b/src/disk/hdc_ide_w83769f.c @@ -0,0 +1,460 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 Winbond W83769F controller. + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/cdrom.h> +#include <86box/scsi_device.h> +#include <86box/scsi_cdrom.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/zip.h> +#include <86box/mo.h> + +typedef struct w83769f_t { + uint8_t vlb_idx; + uint8_t id; + uint8_t in_cfg; + uint8_t channels; + uint8_t pci; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t regs[256]; +} w83769f_t; + +static int next_id = 0; + +#ifdef ENABLE_W83769F_LOG +int w83769f_do_log = ENABLE_W83769F_LOG; + +static void +w83769f_log(const char *fmt, ...) +{ + va_list ap; + + if (cmd640_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define w83769f_log(fmt, ...) +#endif + +void +w83769f_set_irq_0(uint8_t status, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + if (!(dev->channels & 1)) + return; + + if (irq) + picint(1 << 14); + else + picintc(1 << 14); +} + +void +w83769f_set_irq_1(uint8_t status, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + if (!(dev->channels & 2)) + return; + + if (irq) + picint(1 << 15); + else + picintc(1 << 15); +} + +static void +w83769f_ide_handlers(w83769f_t *dev) +{ + if (dev->channels & 0x01) { + ide_pri_disable(); + + if (!dev->pci || (dev->regs[0x04] & 0x01)) + ide_pri_enable(); + } + + if (dev->channels & 0x02) { + ide_sec_disable(); + + if ((!dev->pci || (dev->regs[0x04] & 0x01)) && (dev->regs[0x57] & 0x01)) + ide_sec_enable(); + } +} + +static void +w83769f_common_write(int addr, uint8_t val, w83769f_t *dev) +{ + switch (addr) { + case 0x50: + case 0x57: + dev->regs[0x57] = val & 0x01; + w83769f_ide_handlers(dev); + break; + case 0x51: + dev->regs[addr] = val & 0x7f; + break; + case 0x52: + case 0x54: + case 0x56: + case 0x58 ... 0x59: + dev->regs[addr] = val; + break; + case 0x53: + case 0x55: + dev->regs[addr] = val & 0xcf; + break; + + default: + break; + } +} + +static void +w83769f_vlb_write(uint16_t addr, uint8_t val, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + switch (addr) { + case 0x0034: + case 0x00b4: + dev->vlb_idx = val; + break; + case 0x0038: + case 0x00b8: + w83769f_common_write(dev->vlb_idx, val, dev); + break; + + default: + break; + } +} + +static void +w83769f_vlb_writew(uint16_t addr, uint16_t val, void *priv) +{ + w83769f_vlb_write(addr, val & 0xff, priv); + w83769f_vlb_write(addr + 1, val >> 8, priv); +} + +static void +w83769f_vlb_writel(uint16_t addr, uint32_t val, void *priv) +{ + w83769f_vlb_writew(addr, val & 0xffff, priv); + w83769f_vlb_writew(addr + 2, val >> 16, priv); +} + +static uint8_t +w83769f_vlb_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + w83769f_t *dev = (w83769f_t *) priv; + + switch (addr) { + case 0x0034: + case 0x00b4: + ret = dev->vlb_idx; + break; + case 0x0038: + case 0x00b8: + ret = dev->regs[dev->vlb_idx]; + if (dev->vlb_idx == 0x50) + dev->regs[0x50] &= ~0x04; + break; + + default: + break; + } + + return ret; +} + +static uint16_t +w83769f_vlb_readw(uint16_t addr, void *priv) +{ + uint16_t ret = 0xffff; + + ret = w83769f_vlb_read(addr, priv); + ret |= (w83769f_vlb_read(addr + 1, priv) << 8); + + return ret; +} + +static uint32_t +w83769f_vlb_readl(uint16_t addr, void *priv) +{ + uint32_t ret = 0xffffffff; + + ret = w83769f_vlb_readw(addr, priv); + ret |= (w83769f_vlb_readw(addr + 2, priv) << 16); + + return ret; +} + +static void +w83769f_pci_write(int func, int addr, uint8_t val, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + w83769f_log("w83769f_pci_write(%i, %02X, %02X)\n", func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: + dev->regs[addr] = (dev->regs[addr] & 0xbf) | (val & 0x40); + w83769f_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0x80); + break; + } +} + +static uint8_t +w83769f_pci_read(int func, int addr, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = dev->regs[addr]; + + w83769f_log("w83769f_pci_read(%i, %02X, %02X)\n", func, addr, ret); + + return ret; +} + +static void +w83769f_reset(void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + 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 >= 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 >= 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); + } + + if (dev->channels & 0x01) + w83769f_set_irq_0(0x00, priv); + + if (dev->channels & 0x02) + w83769f_set_irq_1(0x00, priv); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x50] = (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ + dev->regs[0x51] = 0x40; + dev->regs[0x57] = 0x01; /* Required by the MSI MS-5109 */ + dev->regs[0x59] = 0x40; + + if (dev->pci) { + dev->regs[0x00] = 0xad; /* Winbond */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x01; /* W83769 */ + dev->regs[0x03] = 0x00; + dev->regs[0x04] = 0x01; + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x08] = 0x02; /* 00h for Rev BB, 02h for Rev A3C */ + dev->regs[0x09] = 0x00; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ + dev->regs[0x3c] = 0x0e; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + } else + dev->regs[0x04] = 0x01; /* To make sure the two channels get enabled. */ + + w83769f_ide_handlers(dev); +} + +static void +w83769f_close(void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + free(dev); + + next_id = 0; +} + +static void * +w83769f_init(const device_t *info) +{ + w83769f_t *dev = (w83769f_t *) malloc(sizeof(w83769f_t)); + memset(dev, 0x00, sizeof(w83769f_t)); + + dev->id = next_id | 0x60; + + dev->pci = !!(info->flags & DEVICE_PCI); + + dev->channels = ((info->local & 0x60000) >> 17) & 0x03; + + if (info->flags & DEVICE_PCI) { + device_add(&ide_pci_2ch_device); + + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot); + } else if (info->flags & DEVICE_VLB) + device_add(&ide_vlb_2ch_device); + + if (dev->channels & 0x01) + ide_set_bus_master(0, NULL, w83769f_set_irq_0, dev); + + if (dev->channels & 0x02) + ide_set_bus_master(1, NULL, w83769f_set_irq_1, dev); + + /* 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); + + io_sethandler(info->local & 0xffff, 0x0001, + w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl, + w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel, + dev); + io_sethandler((info->local & 0xffff) + 0x0004, 0x0001, + w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl, + w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel, + dev); + + next_id++; + + w83769f_reset(dev); + + return dev; +} + +const device_t ide_w83769f_vlb_device = { + .name = "Winbond W83769F VLB", + .internal_name = "ide_w83769f_vlb", + .flags = DEVICE_VLB, + .local = 0x600b4, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_vlb_34_device = { + .name = "Winbond W83769F VLB (Port 34h)", + .internal_name = "ide_w83769f_vlb_34", + .flags = DEVICE_VLB, + .local = 0x60034, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_pci_device = { + .name = "Winbond W83769F PCI", + .internal_name = "ide_w83769f_pci", + .flags = DEVICE_PCI, + .local = 0x600b4, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_pci_34_device = { + .name = "Winbond W83769F PCI (Port 34h)", + .internal_name = "ide_w83769f_pci_34", + .flags = DEVICE_PCI, + .local = 0x60034, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_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 41499591d..d5bbf24d0 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -134,26 +134,27 @@ st506_at_log(const char *fmt, ...) # define st506_at_log(fmt, ...) #endif -static inline void +static __inline void irq_raise(mfm_t *mfm) { - if (!(mfm->fdisk & 2)) - picint(1 << 14); - mfm->irqstat = 1; + if (!(mfm->fdisk & 2)) + picint_common(1 << 14, PIC_IRQ_EDGE, 1, NULL); } -static inline void -irq_lower(UNUSED(mfm_t *mfm)) +static __inline void +irq_lower(mfm_t *mfm) { - picintc(1 << 14); + mfm->irqstat = 0; + if (!(mfm->fdisk & 2)) + picint_common(1 << 14, PIC_IRQ_EDGE, 0, NULL); } -static void +static __inline void irq_update(mfm_t *mfm) { - if (mfm->irqstat && !((pic2.irr | pic2.isr) & 0x40) && !(mfm->fdisk & 2)) - picint(1 << 14); + uint8_t set = !(mfm->fdisk & 2) && mfm->irqstat; + picint_common(1 << 14, PIC_IRQ_EDGE, set, NULL); } /* @@ -186,7 +187,7 @@ get_sector(mfm_t *mfm, off64_t *addr) return 1; } - if (mfm->sector >= drive->cfg_spt + 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; @@ -198,7 +199,7 @@ get_sector(mfm_t *mfm, off64_t *addr) return 1; } - if (mfm->sector >= drive->spt + 1) { + if (mfm->sector >= (drive->spt + 1)) { st506_at_log("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); return 1; } @@ -208,6 +209,35 @@ get_sector(mfm_t *mfm, off64_t *addr) return 0; } +static int +get_sector_format(mfm_t *mfm, off64_t *addr) +{ + 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. */ + if (drive->curcyl != mfm->cylinder) { + 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; + } + + /* 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; + } + + *addr = ((((off64_t) mfm->cylinder * drive->cfg_hpc) + mfm->head) * drive->cfg_spt); + + return 0; +} + /* Move to the next sector using CHS addressing. */ static void next_sector(mfm_t *mfm) @@ -247,13 +277,9 @@ mfm_cmd(mfm_t *mfm, uint8_t val) 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); + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); break; case CMD_SEEK: @@ -310,38 +336,8 @@ mfm_cmd(mfm_t *mfm, uint8_t val) 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); + mfm->status = STAT_BUSY; + timer_set_delay_u64(&mfm->callback_timer, 200 * MFM_TIME); break; default: @@ -378,6 +374,7 @@ static void mfm_write(uint16_t port, uint8_t val, void *priv) { mfm_t *mfm = (mfm_t *) priv; + uint8_t old; st506_at_log("WD1003 write(%04x, %02x)\n", port, val); @@ -408,7 +405,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv) case 0x01f6: /* drive/head */ mfm->head = val & 0xF; - mfm->drvsel = (val & 0x10) ? 1 : 0; + mfm->drvsel = !!(val & 0x10); if (mfm->drives[mfm->drvsel].present) mfm->status = STAT_READY | STAT_DSC; else @@ -425,15 +422,15 @@ mfm_write(uint16_t port, uint8_t val, void *priv) timer_set_delay_u64(&mfm->callback_timer, 500 * MFM_TIME); mfm->reset = 1; mfm->status = STAT_BUSY; - } - - if (val & 0x04) { + } else if (!(mfm->fdisk & 0x04) && (val & 0x04)) { /* Drive held in reset. */ timer_disable(&mfm->callback_timer); mfm->status = STAT_BUSY; } + old = mfm->fdisk; mfm->fdisk = val; - irq_update(mfm); + if (!(val & 0x02) && (old & 0x02)) + irq_update(mfm); break; default: @@ -565,6 +562,15 @@ do_callback(void *priv) } switch (mfm->command) { + case CMD_RESTORE: + 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; + irq_raise(mfm); + break; + case CMD_SEEK: st506_at_log("WD1003(%d) seek, step=%d\n", mfm->drvsel, drive->steprate); @@ -632,7 +638,7 @@ do_callback(void *priv) st506_at_log("WD1003(%d) format(%d,%d)\n", mfm->drvsel, mfm->cylinder, mfm->head); do_seek(mfm); - if (get_sector(mfm, &addr)) { + if (get_sector_format(mfm, &addr)) { mfm->error = ERR_ID_NOT_FOUND; mfm->status = STAT_READY | STAT_DSC | STAT_ERR; irq_raise(mfm); @@ -660,6 +666,41 @@ do_callback(void *priv) 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(%d) callback on unknown command %02x\n", mfm->drvsel, mfm->command); diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 40709d307..f3ac48a36 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -107,7 +107,7 @@ #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" +#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.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. */ @@ -457,6 +457,37 @@ get_chs(hdc_t *dev, drive_t *drive) return 1; } +static int +get_chs_format(hdc_t *dev, drive_t *drive) +{ + dev->err_bv = 0x80; + + dev->head = dev->command[1] & 0x1f; + /* 6 bits are used for the sector number even on the IBM PC controller. */ + dev->sector = 1; + 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 */ + } + + 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; + } + + drive->cylinder = dev->cylinder; + + return 1; +} + static void st506_callback(void *priv) { @@ -628,7 +659,7 @@ st506_callback(void *priv) case CMD_FORMAT_BAD_TRACK: switch (dev->state) { case STATE_START_COMMAND: - (void) get_chs(dev, drive); + (void) get_chs_format(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); @@ -1533,6 +1564,7 @@ static void set_switches(hdc_t *dev, hd_type_t *hdt, int num) { const drive_t *drive; + int c; int e; dev->switches = 0x00; @@ -1546,7 +1578,7 @@ set_switches(hdc_t *dev, hd_type_t *hdt, int num) continue; } - for (int c = 0; c < num; c++) { + for (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 @@ -1666,7 +1698,7 @@ st506_init(const device_t *info) 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->switches = 0x30; /* autobios */ dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index dfe5931f1..057d4f0ed 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -49,9 +49,9 @@ #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_AT_386 "roms/hdd/xtide/ide_386.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 xtide_t { void *ide_board; @@ -136,13 +136,9 @@ xtide_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); - if (info->local == 1) { - rom_init(&xtide->bios_rom, ROM_PATH_XTP, + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), 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(); @@ -153,18 +149,6 @@ xtide_init(const device_t *info) return xtide; } -static int -xtide_available(void) -{ - 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) { @@ -172,31 +156,15 @@ 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, + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } else { - rom_init(&xtide->bios_rom, ROM_PATH_AT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } device_add(&ide_isa_2ch_device); return xtide; } -static int -xtide_at_available(void) -{ - return (rom_present(ROM_PATH_AT)); -} - -static int -xtide_at_386_available(void) -{ - return (rom_present(ROM_PATH_AT_386)); -} - static void * xtide_acculogic_init(UNUSED(const device_t *info)) { @@ -261,6 +229,50 @@ xtide_at_close(void *priv) free(xtide); } +static const device_config_t xtide_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS", + .type = CONFIG_BIOS, + .default_string = "xt", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } }, + { .name = "XT+ (V20/V30/8018x)", .internal_name = "xt_plus", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XTP, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_config_t xtide_at_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS", + .type = CONFIG_BIOS, + .default_string = "at", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } }, + { .name = "386", .internal_name = "at_386", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT_386, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t xtide_device = { .name = "PC/XT XTIDE", .internal_name = "xtide", @@ -269,24 +281,10 @@ const device_t xtide_device = { .init = xtide_init, .close = xtide_close, .reset = NULL, - { .available = xtide_available }, + { .available = NULL }, .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 + .config = xtide_config }; const device_t xtide_at_device = { @@ -297,24 +295,10 @@ const device_t xtide_at_device = { .init = xtide_at_init, .close = xtide_at_close, .reset = NULL, - { .available = xtide_at_available }, + { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL -}; - -const device_t xtide_at_386_device = { - .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 + .config = xtide_at_config }; const device_t xtide_acculogic_device = { diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 3bb15c241..7acfc82be 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -50,51 +50,32 @@ hdd_string_to_bus(char *str, int cdrom) if (!strcmp(str, "none")) return HDD_BUS_DISABLED; - if (!strcmp(str, "mfm") || !strcmp(str, "rll")) { + if (!strcmp(str, "mfm")) { if (cdrom) { no_cdrom: - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2131, (wchar_t *) IDS_4099); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_INVALID_CONFIG), plat_get_string(STRING_NO_ST506_ESDI_CDROM)); return 0; } return HDD_BUS_MFM; } - /* FIXME: delete 'rll' in a year or so.. --FvK */ - if (!strcmp(str, "esdi") || !strcmp(str, "rll")) { + if (!strcmp(str, "esdi")) { if (cdrom) goto no_cdrom; return HDD_BUS_ESDI; } - if (!strcmp(str, "ide_pio_only")) - 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")) return HDD_BUS_ATAPI; - if (!strcmp(str, "eide")) - return HDD_BUS_IDE; - if (!strcmp(str, "xta")) return HDD_BUS_XTA; - if (!strcmp(str, "atide")) - 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, "scsi")) return HDD_BUS_SCSI; diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index df473d7d9..db56d5b78 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -327,7 +327,7 @@ hdd_image_load(int id) hdd_images[id].type = HDD_IMAGE_HDX; } else if (is_vhd[0]) { fclose(hdd_images[id].file); - MVHDGeom geometry; + MVHDGeom geometry = { 0 }; geometry.cyl = hdd[id].tracks; geometry.heads = hdd[id].hpc; geometry.spt = hdd[id].spt; @@ -335,7 +335,7 @@ hdd_image_load(int id) hdd_images[id].last_sector = (full_size >> 9LL) - 1; if (hdd[id].vhd_blocksize || hdd[id].vhd_parent[0]) { - MVHDCreationOptions options; + MVHDCreationOptions options = { 0 }; retry_vhd: options.block_size_in_sectors = hdd[id].vhd_blocksize; options.path = fn; diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c new file mode 100644 index 000000000..35c845c16 --- /dev/null +++ b/src/disk/lba_enhancer.c @@ -0,0 +1,99 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Vision Systems LBA Enhancer emulation. + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2024 Cacodemon345 + */ + +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/plat_unused.h> + +typedef struct lba_enhancer_t +{ + rom_t rom; +} lba_enhancer_t; + +#define BIOS_LBA_ENHANCER "roms/hdd/misc/lbaenhancer.bin" + +void +lba_enhancer_close(void* priv) +{ + free(priv); + + return; +} + +void * +lba_enhancer_init(const device_t *info) +{ + lba_enhancer_t *dev = (lba_enhancer_t *) calloc(1, sizeof(lba_enhancer_t)); + + rom_init(&dev->rom, BIOS_LBA_ENHANCER, + device_get_config_hex20("bios_addr"), 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + return dev; +} + +static int +lba_enhancer_available(void) +{ + return rom_present(BIOS_LBA_ENHANCER); +} + +// clang-format off +static const device_config_t lba_enhancer_config[] = { + { + .name = "bios_addr", + .description = "BIOS Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .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 = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t lba_enhancer_device = { + .name = "Vision Systems LBA Enhancer", + .internal_name = "lba_enhancer", + .flags = DEVICE_AT, + .local = 0, + .init = lba_enhancer_init, + .close = lba_enhancer_close, + .reset = NULL, + { .available = lba_enhancer_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = lba_enhancer_config +}; diff --git a/src/disk/minivhd/create.c b/src/disk/minivhd/create.c index d06382ef9..1fcfc8682 100644 --- a/src/disk/minivhd/create.c +++ b/src/disk/minivhd/create.c @@ -315,7 +315,7 @@ create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_byte { uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0}; uint8_t sparse_buff[MVHD_SPARSE_SIZE] = {0}; - uint8_t bat_sect[MVHD_SECTOR_SIZE]; + uint8_t bat_sect[MVHD_SECTOR_SIZE] = {0}; MVHDGeom par_geom = {0}; memset(bat_sect, 0xffffffff, sizeof bat_sect); MVHDMeta* vhdm = NULL; diff --git a/src/disk/minivhd/manage.c b/src/disk/minivhd/manage.c index 7ac3989e6..fdf3d8e79 100644 --- a/src/disk/minivhd/manage.c +++ b/src/disk/minivhd/manage.c @@ -92,7 +92,7 @@ read_footer(MVHDMeta* vhdm) static void read_sparse_header(MVHDMeta* vhdm) { - uint8_t buffer[MVHD_SPARSE_SIZE]; + uint8_t buffer[MVHD_SPARSE_SIZE] = { 0 }; mvhd_fseeko64(vhdm->f, vhdm->footer.data_offset, SEEK_SET); (void) !fread(buffer, sizeof buffer, 1, vhdm->f); @@ -438,17 +438,15 @@ mvhd_version_id(void) MVHDAPI int mvhd_file_is_vhd(FILE* f) { - uint8_t con_str[8]; + uint8_t con_str[8] = { 0 }; - if (f == NULL) { + 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)) { + if (mvhd_is_conectix_str(con_str)) return 1; - } return 0; } @@ -457,13 +455,12 @@ mvhd_file_is_vhd(FILE* f) MVHDAPI MVHDGeom mvhd_calculate_geometry(uint64_t size) { - MVHDGeom chs; + MVHDGeom chs = { 0 }; uint32_t ts = (uint32_t)(size / MVHD_SECTOR_SIZE); uint32_t spt, heads, cyl, cth; - if (ts > 65535 * 16 * 255) { + if (ts > 65535 * 16 * 255) ts = 65535 * 16 * 255; - } if (ts >= 65535 * 16 * 63) { spt = 255; @@ -473,9 +470,8 @@ mvhd_calculate_geometry(uint64_t size) spt = 17; cth = ts / spt; heads = (cth + 1023) / 1024; - if (heads < 4) { + if (heads < 4) heads = 4; - } if (cth >= (heads * 1024) || heads > 16) { spt = 31; heads = 16; @@ -500,7 +496,7 @@ mvhd_calculate_geometry(uint64_t size) MVHDAPI MVHDMeta* mvhd_open(const char* path, int readonly, int* err) { - MVHDError open_err; + MVHDError open_err = { 0 }; MVHDMeta *vhdm = calloc(sizeof *vhdm, 1); if (vhdm == NULL) { @@ -516,11 +512,10 @@ mvhd_open(const char* path, int readonly, int* err) //This is safe, as we've just checked for potential overflow above strcpy(vhdm->filename, path); - if (readonly) { + if (readonly) vhdm->f = mvhd_fopen((const char*)vhdm->filename, "rb", err); - } else { + 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; @@ -567,14 +562,12 @@ mvhd_open(const char* path, int readonly, int* err) vhdm->format_buffer.sector_count = 64; if (vhdm->footer.disk_type == MVHD_TYPE_DIFF) { char* par_path = get_diff_parent_path(vhdm, err); - if (par_path == NULL) { + if (par_path == NULL) goto cleanup_format_buff; - } uint32_t par_mod_ts = mvhd_file_mod_timestamp(par_path, err); - if (*err != 0) { + 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. @@ -582,9 +575,8 @@ mvhd_open(const char* path, int readonly, int* err) *err = MVHD_ERR_TIMESTAMP; } vhdm->parent = mvhd_open(par_path, true, err); - if (vhdm->parent == NULL) { + 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; @@ -629,9 +621,8 @@ mvhd_close(MVHDMeta* vhdm) if (vhdm == NULL) return; - if (vhdm->parent != NULL) { + if (vhdm->parent != NULL) mvhd_close(vhdm->parent); - } fclose(vhdm->f); @@ -655,7 +646,7 @@ mvhd_close(MVHDMeta* vhdm) MVHDAPI int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) { - uint8_t sparse_buff[1024]; + uint8_t sparse_buff[1024] = { 0 }; if (vhdm == NULL || err == NULL) { *err = MVHD_ERR_INVALID_PARAMS; diff --git a/src/disk/minivhd/minivhd_io.c b/src/disk/minivhd/minivhd_io.c index ff86a8337..2912cf5b2 100644 --- a/src/disk/minivhd/minivhd_io.c +++ b/src/disk/minivhd/minivhd_io.c @@ -46,7 +46,6 @@ #include "minivhd.h" #include "internal.h" - /* * The following bit array macros adapted from: * @@ -56,7 +55,6 @@ #define VHD_CLEARBIT(A,k) ( A[(k>>3)] &= ~(0x80 >> (k&7)) ) #define VHD_TESTBIT(A,k) ( A[(k>>3)] & (0x80 >> (k&7)) ) - /** * \brief Check that we will not be overflowing buffers * @@ -68,29 +66,26 @@ * \param [out] trunc_sectors The number of sectors truncated if transfer_sectors < num_sectors */ static inline void -check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect) +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) { + 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) +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++) { + for (int i = 0; i < sector_count; i++) fwrite(zero_bytes, sizeof zero_bytes, 1, f); - } } - /** * \brief Read the sector bitmap for a block. * @@ -101,19 +96,17 @@ mvhd_write_empty_sectors(FILE* f, int sector_count) * \param [in] blk The block for which to read the sector bitmap from */ static void -read_sect_bitmap(MVHDMeta* vhdm, int blk) +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); (void) !fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f); - } else { + } 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 * @@ -129,7 +122,6 @@ write_curr_sect_bitmap(MVHDMeta* vhdm) } } - /** * \brief Write block offset from memory into file * @@ -137,7 +129,7 @@ write_curr_sect_bitmap(MVHDMeta* vhdm) * \param [in] blk The block for which to write the offset for */ static void -write_bat_entry(MVHDMeta* vhdm, int blk) +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]); @@ -146,7 +138,6 @@ write_bat_entry(MVHDMeta* vhdm, int blk) fwrite(&offset, sizeof offset, 1, vhdm->f); } - /** * \brief Create an empty block in a sparse or differencing VHD image * @@ -162,9 +153,9 @@ write_bat_entry(MVHDMeta* vhdm, int blk) * \param [in] blk The block number to create */ static void -create_block(MVHDMeta* vhdm, int blk) +create_block(MVHDMeta *vhdm, int blk) { - uint8_t footer[MVHD_FOOTER_SIZE]; + uint8_t footer[MVHD_FOOTER_SIZE] = { 0 }; /* Seek to where the footer SHOULD be */ mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END); @@ -179,13 +170,12 @@ create_block(MVHDMeta* vhdm, int blk) } int64_t abs_offset = mvhd_ftello64(vhdm->f); - if (abs_offset % MVHD_SECTOR_SIZE != 0) { + if ((abs_offset % MVHD_SECTOR_SIZE) != 0) { /* Yikes! We're supposed to be on a sector boundary. Add some padding */ - int64_t padding_amount = (int64_t)MVHD_SECTOR_SIZE - (abs_offset % MVHD_SECTOR_SIZE); + int64_t padding_amount = ((int64_t) MVHD_SECTOR_SIZE) - (abs_offset % MVHD_SECTOR_SIZE); uint8_t zero_byte = 0; - for (int i = 0; i < padding_amount; i++) { + for (int i = 0; i < padding_amount; i++) fwrite(&zero_byte, sizeof zero_byte, 1, vhdm->f); - } abs_offset += padding_amount; } @@ -204,37 +194,39 @@ create_block(MVHDMeta* vhdm, int blk) write_bat_entry(vhdm, blk); } - int -mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { - int64_t addr; - int transfer_sectors, truncated_sectors; +mvhd_fixed_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buff) { + int64_t addr = 0ULL; + int transfer_sectors = 0; + int truncated_sectors = 0; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); - addr = (int64_t)offset * MVHD_SECTOR_SIZE; + addr = ((int64_t) offset) * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); - (void) !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) +mvhd_sparse_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buff) { - int transfer_sectors, truncated_sectors; + int transfer_sectors = 0; + int truncated_sectors; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); 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; + int64_t addr = 0ULL; + uint32_t s = 0; + uint32_t ls = 0; + int blk = 0; + int prev_blk = -1; + int sib = 0; ls = offset + transfer_sectors; - prev_blk = -1; for (s = offset; s < ls; s++) { blk = s / vhdm->sect_per_block; @@ -245,14 +237,15 @@ mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buf 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; + 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)) { + if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) (void) !fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); - } else { + else { memset(buff, 0, MVHD_SECTOR_SIZE); mvhd_fseeko64(vhdm->f, MVHD_SECTOR_SIZE, SEEK_CUR); } @@ -262,19 +255,21 @@ mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buf return truncated_sectors; } - int -mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) +mvhd_diff_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buff) { - int transfer_sectors, truncated_sectors; + int transfer_sectors = 0; + int truncated_sectors = 0; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); 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; + uint8_t *buff = (uint8_t*)out_buff; + MVHDMeta *curr_vhdm = vhdm; + uint32_t s = 0; + uint32_t ls = 0; + int blk = 0; + int sib = 0; ls = offset + transfer_sectors; for (s = offset; s < ls; s++) { @@ -291,11 +286,11 @@ mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) /* 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) { + if ((curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF) || + (curr_vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC)) mvhd_sparse_read(curr_vhdm, s, 1, buff); - } else { + else mvhd_fixed_read(curr_vhdm, s, 1, buff); - } curr_vhdm = vhdm; buff += MVHD_SECTOR_SIZE; @@ -304,38 +299,40 @@ mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) return truncated_sectors; } - int -mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +mvhd_fixed_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff) { - int64_t addr; - int transfer_sectors, truncated_sectors; + int64_t addr = 0ULL; + int transfer_sectors = 0; + int truncated_sectors = 0; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); 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); + 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) +mvhd_sparse_diff_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff) { - int transfer_sectors, truncated_sectors; + int transfer_sectors = 0; + int truncated_sectors = 0; uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); 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; + uint8_t* buff = (uint8_t *) in_buff; + int64_t addr = 0ULL; + uint32_t s = 0; + uint32_t ls = 0; + int blk = 0; + int prev_blk = -1; + int sib = 0; ls = offset + transfer_sectors; - prev_blk = -1; for (s = offset; s < ls; s++) { blk = s / vhdm->sect_per_block; @@ -357,7 +354,8 @@ mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* i 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; + addr = (((int64_t) vhdm->block_offset[blk]) + vhdm->bitmap.sector_count + sib) * + MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); } prev_blk = blk; @@ -374,14 +372,13 @@ mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* i return truncated_sectors; } - int -mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) +mvhd_noop_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff) { - (void)vhdm; - (void)offset; - (void)num_sectors; - (void)in_buff; + (void) vhdm; + (void) offset; + (void) num_sectors; + (void) in_buff; return 0; } diff --git a/src/disk/minivhd/minivhd_util.c b/src/disk/minivhd/minivhd_util.c index dd3244322..4901e5841 100644 --- a/src/disk/minivhd/minivhd_util.c +++ b/src/disk/minivhd/minivhd_util.c @@ -462,7 +462,7 @@ mvhd_file_mod_timestamp(const char* path, int *err) { *err = 0; #ifdef _WIN32 - struct _stat file_stat; + struct _stat file_stat = { 0 }; size_t path_len = strlen(path); mvhd_utf16 new_path[260] = {0}; int new_path_len = (sizeof new_path) - 2; @@ -485,7 +485,7 @@ mvhd_file_mod_timestamp(const char* path, int *err) return 0; } #else - struct stat file_stat; + struct stat file_stat = { 0 }; int stat_res = stat(path, &file_stat); if (stat_res != 0) { diff --git a/src/disk/mo.c b/src/disk/mo.c index c93f4b055..e90267b95 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1677,8 +1677,8 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) size_idx = 4; memset(dev->buffer, 0, 8); - if (cdb[1] & 0xe0) - dev->buffer[0] = 0x60; /*No physical device on this LUN*/ + if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) + dev->buffer[0] = 0x7f; /*No physical device on this LUN*/ else dev->buffer[0] = 0x07; /*Optical disk*/ dev->buffer[1] = 0x80; /*Removable*/ diff --git a/src/disk/zip.c b/src/disk/zip.c index 7045b1e41..d4cbd0b41 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -532,6 +532,11 @@ zip_load(zip_t *dev, char *fn) fatal("zip_load(): Error seeking to the beginning of the file\n"); strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); + // After using strncpy, dev->drv->image_path needs to be explicitly null terminated to make gcc happy. + // In the event strlen(dev->drv->image_path) == sizeof(dev->drv->image_path) (no null terminator) + // it is placed at the very end. Otherwise, it is placed right after the string. + const size_t term = strlen(dev->drv->image_path) == sizeof(dev->drv->image_path) ? sizeof(dev->drv->image_path) - 1 : strlen(dev->drv->image_path); + dev->drv->image_path[term] = '\0'; return 1; } @@ -1860,8 +1865,8 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) size_idx = 4; memset(dev->buffer, 0, 8); - if (cdb[1] & 0xe0) - dev->buffer[0] = 0x60; /*No physical device on this LUN*/ + if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) + dev->buffer[0] = 0x7f; /*No physical device on this LUN*/ else dev->buffer[0] = 0x00; /*Hard disk*/ dev->buffer[1] = 0x80; /*Removable*/ diff --git a/src/dma.c b/src/dma.c index 55cf31236..318c6cda2 100644 --- a/src/dma.c +++ b/src/dma.c @@ -22,6 +22,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include "x86.h" @@ -42,6 +43,7 @@ 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_stat_adv_pend; static uint8_t dma_command[2]; static uint8_t dma_req_is_soft; static uint8_t dma_advanced; @@ -457,6 +459,7 @@ dma_read(uint16_t addr, UNUSED(void *priv)) { int channel = (addr >> 1) & 3; uint8_t temp; + int count; switch (addr & 0xf) { case 0: @@ -473,10 +476,13 @@ dma_read(uint16_t addr, UNUSED(void *priv)) case 5: case 7: /*Count registers*/ dma_wp[0] ^= 1; + count = dma[channel].cc/* + 1*/; + // if (count > dma[channel].cb) + // count = 0x0000; if (dma_wp[0]) - temp = dma[channel].cc & 0xff; + temp = count & 0xff; else - temp = dma[channel].cc >> 8; + temp = count >> 8; return temp; case 8: /*Status register*/ @@ -529,8 +535,10 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) case 8: /*Control register*/ dma_command[0] = val; +#ifdef ENABLE_DMA_LOG if (val & 0x01) pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc); +#endif return; case 9: /*Request register */ @@ -538,7 +546,9 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) if (val & 4) { dma_stat_rq_pc |= (1 << channel); if ((channel == 0) && (dma_command[0] & 0x01)) { +#ifdef ENABLE_DMA_LOG pclog("Memory to memory transfer start\n"); +#endif dma_mem_to_mem_transfer(); } else dma_block_transfer(channel); @@ -767,9 +777,16 @@ static uint8_t dma16_read(uint16_t addr, UNUSED(void *priv)) { int channel = ((addr >> 2) & 3) + 4; - uint8_t temp; +#ifdef ENABLE_DMA_LOG + uint16_t port = addr; +#endif + uint8_t ret; + int count; addr >>= 1; + + ret = dmaregs[1][addr & 0xf]; + switch (addr & 0xf) { case 0: case 2: @@ -778,41 +795,53 @@ dma16_read(uint16_t addr, UNUSED(void *priv)) 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); + ret = (dma[channel].ac); + else + ret = ((dma[channel].ac >> 8) & 0xff); + } else if (dma_wp[1]) + ret = ((dma[channel].ac >> 1) & 0xff); + else + ret = ((dma[channel].ac >> 9) & 0xff); + break; case 1: case 3: case 5: case 7: /*Count registers*/ dma_wp[1] ^= 1; + count = dma[channel].cc/* + 1*/; + // if (count > dma[channel].cb) + // count = 0x0000; if (dma_wp[1]) - temp = dma[channel].cc & 0xff; + ret = count & 0xff; else - temp = dma[channel].cc >> 8; - return temp; + ret = count >> 8; + break; case 8: /*Status register*/ - temp = (dma_stat_rq_pc & 0xf0); - temp |= dma_stat >> 4; + ret = (dma_stat_rq_pc & 0xf0); + ret |= dma_stat >> 4; dma_stat &= ~0xf0; - return temp; + break; default: break; } - return (dmaregs[1][addr & 0xf]); +#ifdef ENABLE_DMA_LOG + pclog("dma16_read(%08X) = %02X\n", port, ret); +#endif + + return ret; } static void dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) { int channel = ((addr >> 2) & 3) + 4; +#ifdef ENABLE_DMA_LOG + pclog("dma16_write(%08X, %02X)\n", addr, val); +#endif addr >>= 1; dmaregs[1][addr & 0xf] = val; @@ -949,16 +978,47 @@ dma_page_read(uint16_t addr, UNUSED(void *priv)) uint8_t convert[8] = CHANNELS; uint8_t ret = 0xff; - addr &= 0x0f; - ret = dmaregs[2][addr]; + if (((addr & 0xfffc) == 0x80) && (CS == 0xf000) && + ((cpu_state.pc & 0xfffffff8) == 0x00007278) && + !strcmp(machine_get_internal_name(), "megapc")) switch (addr) { + /* The Amstrad MegaPC Quadtel BIOS times a sequence of: + mov ax,di + div bx + And expects this value to be at least 0x06e0 for 20 MHz, + and at least 0x0898 for 25 MHz, everything below 0x06e0 + is assumed to be 16 MHz. Given that for some reason, this + does not occur on 86Box, we have to work around it here, + we return 0x0580 for 16 MHz, because it logically follows + in the sequence (0x06e0 = 0x0898 * (20 / 25), and + 0x0580 = 0x06e0 * (16 / 20)). */ + case 0x0081: + if (cpu_busspeed >= 25000000) + ret = 0x98; + else if (cpu_busspeed >= 20000000) + ret = 0xe0; + else + ret = 0x80; + break; + case 0x0082: + if (cpu_busspeed >= 25000000) + ret = 0x08; + else if (cpu_busspeed >= 20000000) + ret = 0x06; + else + ret = 0x05; + break; + } else { + addr &= 0x0f; + ret = dmaregs[2][addr]; - if (addr >= 8) - addr = convert[addr & 0x07] | 4; - else - addr = convert[addr & 0x07]; + if (addr >= 8) + addr = convert[addr & 0x07] | 4; + else + addr = convert[addr & 0x07]; - if (addr < 8) - ret = dma[addr].page_l; + if (addr < 8) + ret = dma[addr].page_l; + } return ret; } @@ -1045,11 +1105,12 @@ dma_reset(void) dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101; } - dma_stat = 0x00; - dma_stat_rq = 0x00; - dma_stat_rq_pc = 0x00; - dma_req_is_soft = 0; - dma_advanced = 0; + dma_stat = 0x00; + dma_stat_rq = 0x00; + dma_stat_rq_pc = 0x00; + dma_stat_adv_pend = 0x00; + dma_req_is_soft = 0; + dma_advanced = 0; memset(dma_buffer, 0x00, sizeof(dma_buffer)); memset(dma16_buffer, 0x00, sizeof(dma16_buffer)); @@ -1366,6 +1427,136 @@ dma_advance(dma_t *dma_c) dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); } +int +dma_channel_readable(int channel) +{ + dma_t *dma_c = &dma[channel]; + int ret = 1; + + if (channel < 4) { + if (dma_command[0] & 0x04) + ret = 0; + } else { + if (dma_command[1] & 0x04) + ret = 0; + } + + if (!(dma_e & (1 << channel))) + ret = 0; + if ((dma_m & (1 << channel)) && !dma_req_is_soft) + ret = 0; + if ((dma_c->mode & 0xC) != 8) + ret = 0; + + return ret; +} + +int +dma_channel_read_only(int channel) +{ + dma_t *dma_c = &dma[channel]; + uint16_t temp; + + if (channel < 4) { + if (dma_command[0] & 0x04) + return (DMA_NODATA); + } else { + if (dma_command[1] & 0x04) + return (DMA_NODATA); + } + + if (!(dma_e & (1 << channel))) + return (DMA_NODATA); + if ((dma_m & (1 << channel)) && !dma_req_is_soft) + return (DMA_NODATA); + if ((dma_c->mode & 0xC) != 8) + return (DMA_NODATA); + + dma_channel_advance(channel); + + if (!dma_at && !channel) + refreshread(); + + 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); + } + } else { + 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); + } + } + + dma_stat_rq |= (1 << channel); + + dma_stat_adv_pend |= (1 << channel); + + return temp; +} + +int +dma_channel_advance(int channel) +{ + dma_t *dma_c = &dma[channel]; + int tc = 0; + + if (dma_stat_adv_pend & (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 (tc) { + if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) { + picint(1 << 13); + dma_c->sg_status |= 8; + } + } + + dma_stat_adv_pend &= ~(1 << channel); + } + + return tc; +} + int dma_channel_read(int channel) { @@ -1388,6 +1579,9 @@ dma_channel_read(int channel) if ((dma_c->mode & 0xC) != 8) return (DMA_NODATA); + if (dma_stat_adv_pend & (1 << channel)) + dma_channel_advance(channel); + if (!dma_at && !channel) refreshread(); @@ -1519,6 +1713,8 @@ dma_channel_write(int channel, uint16_t val) dma_stat_rq |= (1 << channel); + dma_stat_adv_pend &= ~(1 << channel); + dma_c->cc--; if (dma_c->cc < 0) { if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6)) diff --git a/src/fifo.c b/src/fifo.c index 72084e11b..f51809fd8 100644 --- a/src/fifo.c +++ b/src/fifo.c @@ -72,7 +72,7 @@ fifo_write(uint8_t val, void *priv) fifo->overrun = 1; else { fifo->buf[fifo->end] = val; - fifo->end = (fifo->end + 1) & 0x0f; + fifo->end = (fifo->end + 1) % fifo->len; if (fifo->end == fifo->start) fifo->full = 1; @@ -99,7 +99,7 @@ fifo_write_evt(uint8_t val, void *priv) fifo->d_overrun_evt(fifo->priv); } else { fifo->buf[fifo->end] = val; - fifo->end = (fifo->end + 1) & 0x0f; + fifo->end = (fifo->end + 1) % fifo->len; if (fifo->end == fifo->start) { fifo->d_full = (fifo->full != 1); @@ -131,7 +131,7 @@ fifo_read(void *priv) if (!fifo->empty) { ret = fifo->buf[fifo->start]; - fifo->start = (fifo->start + 1) & 0x0f; + fifo->start = (fifo->start + 1) % fifo->len; fifo->full = 0; @@ -160,7 +160,7 @@ fifo_read_evt(void *priv) if (!fifo->empty) { ret = fifo->buf[fifo->start]; - fifo->start = (fifo->start + 1) & 0x0f; + fifo->start = (fifo->start + 1) % fifo->len; fifo->d_full = (fifo->full != 0); fifo->full = 0; diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 88948aed9..1a0aa2f10 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -38,6 +38,7 @@ #include <86box/fdc_ext.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#include <86box/fifo.h> extern uint64_t motoron[FDD_NUM]; @@ -212,6 +213,7 @@ fdc_ctrl_reset(void *priv) fdc->lock = 0; fdc->head = 0; fdc->step = 0; + fdc->power_down = 0; if (!(fdc->flags & FDC_FLAG_AT)) fdc->rate = 2; } @@ -257,7 +259,7 @@ fdc_set_wrong_am(fdc_t *fdc) int fdc_get_drive(fdc_t *fdc) { - return fdc->drive; + return (int) fdc->drive; } int fdc_get_bitcell_period(fdc_t *fdc); @@ -270,7 +272,7 @@ fdc_get_perp(fdc_t *fdc) if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) return 0; - return fdc->perp; + return (int) fdc->perp; } int @@ -292,7 +294,7 @@ fdc_get_gap2(fdc_t *fdc, int drive) int fdc_get_format_n(fdc_t *fdc) { - return fdc->format_n; + return (int) fdc->format_n; } int @@ -308,7 +310,7 @@ fdc_request_next_sector_id(fdc_t *fdc) fdc->stat = 0xf0; else { dma_set_drq(fdc->dma_ch, 1); - fdc->stat = 0xd0; + fdc->stat = 0x50; } } @@ -321,7 +323,7 @@ fdc_stop_id_request(fdc_t *fdc) int fdc_get_gap(fdc_t *fdc) { - return fdc->gap; + return (int) fdc->gap; } int @@ -333,40 +335,7 @@ fdc_get_dtl(fdc_t *fdc) int fdc_get_format_sectors(fdc_t *fdc) { - return fdc->format_sectors; -} - -static void -fdc_reset_fifo_buf(fdc_t *fdc) -{ - memset(fdc->fifobuf, 0, 16); - fdc->fifobufpos = 0; -} - -static void -fdc_fifo_buf_advance(fdc_t *fdc) -{ - if (fdc->fifobufpos == fdc->tfifo) - fdc->fifobufpos = 0; - else - fdc->fifobufpos++; -} - -static void -fdc_fifo_buf_write(fdc_t *fdc, uint8_t val) -{ - fdc->fifobuf[fdc->fifobufpos] = 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; - return temp; + return (int) fdc->format_sectors; } static void @@ -418,6 +387,12 @@ fdc_update_rates(fdc_t *fdc) fdc_rate(fdc, 3); } +void +fdc_set_power_down(fdc_t *fdc, uint8_t power_down) +{ + fdc->power_down = power_down; +} + void fdc_update_max_track(fdc_t *fdc, int max_track) { @@ -427,7 +402,7 @@ fdc_update_max_track(fdc_t *fdc, int max_track) void fdc_update_enh_mode(fdc_t *fdc, int enh_mode) { - fdc->enh_mode = enh_mode; + fdc->enh_mode = !!enh_mode; fdc_update_rates(fdc); } @@ -490,7 +465,7 @@ fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate) void fdc_update_drv2en(fdc_t *fdc, int drv2en) { - fdc->drv2en = drv2en; + fdc->drv2en = !!drv2en; } void @@ -500,37 +475,34 @@ fdc_update_rate(fdc_t *fdc, int drive) 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; - - default: - break; - } - break; - case 2: /*Double density*/ - fdc->bit_rate = 250; - break; - case 3: /*Extended density*/ - fdc->bit_rate = 1000; - break; - - default: - break; - } + else switch (fdc->rate) { + default: + break; + case 0: /*High density*/ + fdc->bit_rate = 500; + break; + case 1: /*Double density (360 rpm)*/ + switch (fdc->drvrate[drive]) { + default: + break; + 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->bitcell_period = (1000000 / fdc->bit_rate) * 2; /*Bitcell period in ns*/ } @@ -665,7 +637,7 @@ fdc_io_command_phase1(fdc_t *fdc, int out) pclog_toggle_suppr(); #endif - fdc_reset_fifo_buf(fdc); + fifo_reset(fdc->fifo_p); fdc_rate(fdc, fdc->drive); fdc->head = fdc->params[2]; fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); @@ -683,15 +655,11 @@ fdc_io_command_phase1(fdc_t *fdc, int out) } ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); - fdc->stat = out ? 0x90 : 0x50; + fdc->stat = out ? 0x10 : 0x50; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) fdc->stat |= 0x20; else dma_set_drq(fdc->dma_ch, 1); - if (out) - fdc->pos = 0; - else - fdc->inread = 1; } static void @@ -741,7 +709,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) cycles -= ISA_CYCLES(8); - switch (addr & 7) { + if (!fdc->power_down || ((addr & 7) == 2) || ((addr & 7) == 4)) switch (addr & 7) { case 0: return; case 1: @@ -776,14 +744,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) 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; + if (fdc->power_down) { + timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); + fdc->interrupt = -5; + } else { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -1; - for (i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); + fdc->perp &= 0xfc; - fdc_ctrl_reset(fdc); + 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++) { @@ -806,12 +780,29 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } 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); + if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) { + if (!(val & 0x80)) { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -6; + } + if (fdc->power_down || ((val & 0x80) && !(fdc->dsr & 0x80))) { + if (fdc->power_down) { + timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); + fdc->interrupt = -5; + } else { + 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); + } + } } + fdc->dsr = val; return; case 5: /*Command register*/ if ((fdc->stat & 0xf0) == 0xb0) { @@ -819,8 +810,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dat = val; fdc->stat &= ~0x80; } else { - fdc_fifo_buf_write(fdc, val); - if (fdc->fifobufpos == 0) + fifo_write(val, fdc->fifo_p); + if (fifo_get_full(fdc->fifo_p)) fdc->stat &= ~0x80; } break; @@ -843,7 +834,11 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc_log("Starting FDC command %02X\n", fdc->command); fdc->error = 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)) + 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; @@ -854,7 +849,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 4; fdc->stat |= 0x90; - fdc->pos = 0; fdc->format_state = 0; } else fdc_bad_command(fdc); @@ -866,7 +860,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 8; fdc->stat |= 0x90; - fdc->pos = 0; fdc->mfm = (fdc->command & 0x40) ? 1 : 0; break; case 0x03: /*Specify*/ @@ -888,7 +881,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 8; fdc->stat |= 0x90; - fdc->pos = 0; fdc->mfm = (fdc->command & 0x40) ? 1 : 0; break; case 0x06: /*Read data*/ @@ -907,7 +899,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 8; fdc->stat |= 0x90; - fdc->pos = 0; fdc->mfm = (fdc->command & 0x40) ? 1 : 0; break; case 0x17: /*Powerdown mode*/ @@ -924,28 +915,24 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) 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*/ @@ -964,7 +951,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0x94: /*Lock*/ fdc->lastdrive = fdc->drive; fdc->interrupt = fdc->command; - fdc->pos = 0; fdc_callback(fdc); break; case 0x12: /*Set perpendicular mode*/ @@ -972,7 +958,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 1; fdc->stat |= 0x90; - fdc->pos = 0; } else fdc_bad_command(fdc); break; @@ -980,7 +965,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->pnum = 0; fdc->ptot = 3; fdc->stat |= 0x90; - fdc->pos = 0; break; default: fdc_bad_command(fdc); @@ -1002,6 +986,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } if (fdc->pnum == fdc->ptot) { fdc_log("Got all params %02X\n", fdc->command); + fifo_reset(fdc->fifo_p); fdc->interrupt = fdc->processed_cmd; fdc->reset_stat = 0; /* Disable timer if enabled. */ @@ -1151,7 +1136,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) 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 */ @@ -1273,12 +1257,12 @@ uint8_t fdc_read(uint16_t addr, void *priv) { fdc_t *fdc = (fdc_t *) priv; - uint8_t ret; + uint8_t ret = 0xff; int drive = 0; cycles -= ISA_CYCLES(8); - switch (addr & 7) { + if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) { case 0: /* STA */ if (fdc->flags & FDC_FLAG_PS1) { drive = real_drive(fdc, fdc->dor & 3); @@ -1392,11 +1376,11 @@ fdc_read(uint16_t addr, void *priv) fdc->data_ready = 0; ret = fdc->dat; } else - ret = fdc_fifo_buf_read(fdc); + ret = fifo_read(fdc->fifo_p); break; } - fdc->stat &= ~0x80; if (fdc->paramstogo) { + fdc->stat &= ~0x80; fdc_log("%i parameters to go\n", fdc->paramstogo); fdc->paramstogo--; ret = fdc->res[10 - fdc->paramstogo]; @@ -1404,7 +1388,11 @@ fdc_read(uint16_t addr, void *priv) fdc->stat = 0x80; else fdc->stat |= 0xC0; + } else if (fdc->dma) { + ret = fdc->dat; + break; } else { + fdc->stat &= ~0x80; if (lastbyte) fdc->stat = 0x80; lastbyte = 0; @@ -1513,7 +1501,6 @@ fdc_poll_readwrite_finish(fdc_t *fdc, int compare) if ((fdc->interrupt == 5) || (fdc->interrupt == 9)) fdd_do_writeback(real_drive(fdc, fdc->drive)); - fdc->inread = 0; fdc->interrupt = -2; fdc_poll_common_finish(fdc, compare, 0); @@ -1544,12 +1531,26 @@ fdc_callback(void *priv) case -2: /*End of command*/ fdc->stat = (fdc->stat & 0xf) | 0x80; return; + case -5: /*Reset in power down mode */ + fdc->perp &= 0xfc; + + for (uint8_t i = 0; i < FDD_NUM; i++) + ui_sb_update_icon(SB_FLOPPY | i, 0); + + fdc_ctrl_reset(fdc); + + fdc->fintr = 0; + memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t)); + return; case -1: /*Reset*/ fdc_int(fdc, 1); fdc->fintr = 0; - memset(fdc->pcn, 0, 4 * sizeof(int)); + memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t)); fdc->reset_stat = 4; return; + case -6: /*DSR Reset clear*/ + fdc->dsr |= 0x80; + return; case 0x01: /* Mode */ fdc->stat = 0x80; fdc->densel_force = (fdc->params[2] & 0xC0) >> 6; @@ -1570,7 +1571,6 @@ fdc_callback(void *priv) fdc->stat = 0x50; } } - fdc->inread = 1; return; case 0x04: /* Sense drive status */ fdc->res[10] = (fdc->params[0] & 7) | 0x20; @@ -1686,7 +1686,7 @@ fdc_callback(void *priv) fdc->stat = 0xb0; else { dma_set_drq(fdc->dma_ch, 1); - fdc->stat = 0x90; + fdc->stat = 0x10; } break; case 6: @@ -1708,14 +1708,13 @@ fdc_callback(void *priv) fdc->stat = 0xb0; else { dma_set_drq(fdc->dma_ch, 1); - fdc->stat = 0x90; + fdc->stat = 0x10; } break; default: break; } - fdc->inread = 1; return; case 0x07: /* Recalibrate */ fdc->pcn[fdc->params[0] & 3] = 0; @@ -1800,6 +1799,9 @@ fdc_callback(void *priv) fdc->pretrk = fdc->params[2]; fdc->fifo = (fdc->params[1] & 0x20) ? 0 : 1; fdc->tfifo = (fdc->params[1] & 0xF); + fifo_reset(fdc->fifo_p); + fifo_set_len(fdc->fifo_p, fdc->tfifo + 1); + fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1); fdc->stat = 0x80; return; case 0x14: /*Unlock*/ @@ -1926,7 +1928,6 @@ int fdc_data(fdc_t *fdc, uint8_t data, int last) { int result = 0; - int n; if (fdc->deleted & 2) { /* We're in a VERIFY command, so return with 0. */ @@ -1948,8 +1949,8 @@ fdc_data(fdc_t *fdc, uint8_t data, int last) fdc->stat = 0xf0; } else { /* FIFO enabled */ - fdc_fifo_buf_write(fdc, data); - if (fdc->fifobufpos == 0) { + fifo_write(data, fdc->fifo_p); + if (fifo_get_full(fdc->fifo_p)) { /* We have wrapped around, means FIFO is over */ fdc->data_ready = 1; fdc->stat = 0xf0; @@ -1961,11 +1962,10 @@ fdc_data(fdc_t *fdc, uint8_t data, int last) if (!fdc->fifo || (fdc->tfifo < 1)) { fdc->data_ready = 1; - fdc->stat = 0xd0; + fdc->stat = 0x50; dma_set_drq(fdc->dma_ch, 1); - fdc->fifobufpos = 0; - + fdc->dat = data; result = dma_channel_write(fdc->dma_ch, data); if (result & DMA_OVER) { @@ -1976,19 +1976,15 @@ fdc_data(fdc_t *fdc, uint8_t data, int last) dma_set_drq(fdc->dma_ch, 0); } else { /* FIFO enabled */ - fdc_fifo_buf_write(fdc, data); - if (last || (fdc->fifobufpos == 0)) { + fifo_write(data, fdc->fifo_p); + if (last || fifo_get_full(fdc->fifo_p)) { /* We have wrapped around, means FIFO is over */ fdc->data_ready = 1; - fdc->stat = 0xd0; + fdc->stat = 0x50; dma_set_drq(fdc->dma_ch, 1); - n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; - if (fdc->fifobufpos > 0) - fdc->fifobufpos = 0; - - for (int i = 0; i <= n; i++) { - result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); + while (!fifo_get_empty(fdc->fifo_p)) { + result = dma_channel_write(fdc->dma_ch, fifo_read(fdc->fifo_p)); if (result & DMA_OVER) { dma_set_drq(fdc->dma_ch, 0); @@ -2004,18 +2000,11 @@ fdc_data(fdc_t *fdc, uint8_t data, int last) return 0; } -void -fdc_finishread(fdc_t *fdc) -{ - fdc->inread = 0; -} - void fdc_track_finishread(fdc_t *fdc, int condition) { fdc->stat = 0x10; fdc->satisfying_sectors |= condition; - fdc->inread = 0; fdc_callback(fdc); } @@ -2025,7 +2014,6 @@ fdc_sector_finishcompare(fdc_t *fdc, int satisfying) fdc->stat = 0x10; if (satisfying) fdc->satisfying_sectors++; - fdc->inread = 0; fdc_callback(fdc); } @@ -2033,7 +2021,6 @@ void fdc_sector_finishread(fdc_t *fdc) { fdc->stat = 0x10; - fdc->inread = 0; fdc_callback(fdc); } @@ -2108,9 +2095,9 @@ fdc_getdata(fdc_t *fdc, int last) if (!last) fdc->stat = 0xb0; } else { - data = fdc_fifo_buf_read(fdc); + data = fifo_read(fdc->fifo_p); - if (!last && (fdc->fifobufpos == 0)) + if (!last && fifo_get_empty(fdc->fifo_p)) fdc->stat = 0xb0; } } else { @@ -2122,14 +2109,14 @@ fdc_getdata(fdc_t *fdc, int last) fdc->tc = 1; if (!last) { - fdc->stat = 0x90; dma_set_drq(fdc->dma_ch, 1); + fdc->stat = 0x10; } } else { - if (fdc->fifobufpos == 0) { - for (int i = 0; i <= fdc->tfifo; i++) { + if (fifo_get_empty(fdc->fifo_p)) { + while (!fifo_get_full(fdc->fifo_p)) { data = dma_channel_read(fdc->dma_ch); - fdc->fifobuf[i] = data; + fifo_write(data, fdc->fifo_p); if (data & DMA_OVER) { dma_set_drq(fdc->dma_ch, 0); @@ -2140,11 +2127,11 @@ fdc_getdata(fdc_t *fdc, int last) dma_set_drq(fdc->dma_ch, 0); } - data = fdc_fifo_buf_read(fdc); + data = fifo_read(fdc->fifo_p); - if (!last && (fdc->fifobufpos == 0)) { + if (!last && fifo_get_empty(fdc->fifo_p)) { dma_set_drq(fdc->dma_ch, 1); - fdc->stat = 0x90; + fdc->stat = 0x10; } } } @@ -2342,20 +2329,21 @@ fdc_reset(void *priv) fdc->max_track = (fdc->flags & FDC_FLAG_MORE_TRACKS) ? 85 : 79; fdc_remove(fdc); - if (fdc->flags & FDC_FLAG_SEC) { + if (fdc->flags & FDC_FLAG_SEC) fdc_set_base(fdc, FDC_SECONDARY_ADDR); - } else if (fdc->flags & FDC_FLAG_TER) { + else if (fdc->flags & FDC_FLAG_TER) fdc_set_base(fdc, FDC_TERTIARY_ADDR); - } else if (fdc->flags & FDC_FLAG_QUA) { + else if (fdc->flags & FDC_FLAG_QUA) fdc_set_base(fdc, FDC_QUATERNARY_ADDR); - } else { + else fdc_set_base(fdc, (fdc->flags & FDC_FLAG_PCJR) ? FDC_PRIMARY_PCJR_ADDR : FDC_PRIMARY_ADDR); - } current_drive = 0; for (uint8_t i = 0; i < FDD_NUM; i++) ui_sb_update_icon(SB_FLOPPY | i, 0); + + fdc->power_down = 0; } static void @@ -2363,10 +2351,11 @@ fdc_close(void *priv) { fdc_t *fdc = (fdc_t *) priv; - fdc_reset(fdc); - /* Stop timers. */ - fdc->watchdog_count = 0; + timer_disable(&fdc->watchdog_timer); + timer_disable(&fdc->timer); + + fifo_close(fdc->fifo_p); free(fdc); } @@ -2401,6 +2390,8 @@ fdc_init(const device_t *info) fdc_log("FDC added: %04X (flags: %08X)\n", fdc->base_address, fdc->flags); + fdc->fifo_p = (void *) fifo16_init(); + timer_add(&fdc->timer, fdc_callback, fdc, 0); d86f_set_fdc(fdc); @@ -2418,7 +2409,7 @@ fdc_init(const device_t *info) void fdc_3f1_enable(fdc_t *fdc, int enable) { - fdc->enable_3f1 = enable; + fdc->enable_3f1 = !!enable; } const device_t fdc_xt_device = { @@ -2617,6 +2608,20 @@ const device_t fdc_at_ps1_device = { .config = NULL }; +const device_t fdc_at_ps1_2121_device = { + .name = "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", + .internal_name = "fdc_at_ps1", + .flags = 0, + .local = FDC_FLAG_NO_DSR_RESET | 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 = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 08e57c09b..fa1c070f1 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1274,18 +1274,19 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui 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; + 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); + 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_nodataam(d86f_fdc); return; } @@ -1328,8 +1329,9 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find) /* 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; } } @@ -1347,10 +1349,10 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u } 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); + 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_nodataam(d86f_fdc); return; } @@ -1433,22 +1435,26 @@ d86f_read_sector_id(int drive, int side, int match) 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]); + 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->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->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--; @@ -1458,25 +1464,37 @@ d86f_read_sector_id(int drive, int side, int match) } } 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->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_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); + 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. */ + /* 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)) { + /* Mark that the sector ID is not the one expected by the FDC. */ + dev->error_condition |= 4; /* 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. */ + /* If the two ID's are identical, then we do not need to do + anything regarding the sector size. */ } dev->state++; } else { @@ -1576,7 +1594,8 @@ d86f_read_sector_data(int drive, int side) 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)) + 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 @@ -1589,7 +1608,9 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); + 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++; } @@ -1597,17 +1618,19 @@ d86f_read_sector_data(int drive, int side) } 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->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); + 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_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; @@ -2146,7 +2169,8 @@ d86f_turbo_read(int drive, int side) } 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)); + read_status = fdc_data(d86f_fdc, dat, + dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } @@ -2163,7 +2187,6 @@ d86f_turbo_read(int drive, int side) #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)) { #ifdef ENABLE_D86F_LOG diff --git a/src/game/gameport.c b/src/game/gameport.c index 323555984..58d9a446f 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -31,10 +31,6 @@ #include <86box/timer.h> #include <86box/isapnp.h> #include <86box/gameport.h> -#include <86box/joystick_ch_flightstick_pro.h> -#include <86box/joystick_standard.h> -#include <86box/joystick_sw_pad.h> -#include <86box/joystick_tm_fcs.h> #include <86box/plat_unused.h> typedef struct g_axis_t { diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 49ce824bc..8ca51d531 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index b9c449f99..1d1568738 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 5c91ee1e9..7962c38e3 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -64,7 +64,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_sw_pad.h> #include <86box/plat_unused.h> typedef struct sw_data { diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index d54d0e37d..f5c1e64e6 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index ae2ea260c..f76d70797 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -33,7 +33,10 @@ /* Recently used images */ #define MAX_PREV_IMAGES 4 -#define MAX_IMAGE_PATH_LEN 256 +#define MAX_IMAGE_PATH_LEN 2048 + +/* Max UUID Length */ +#define MAX_UUID_LEN 64 /* Default language 0xFFFF = from system, 0x409 = en-US */ #define DEFAULT_LANGUAGE 0x0409 @@ -124,7 +127,9 @@ 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 novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ extern int postcard_enabled; /* (C) enable POST card */ +extern int unittester_enabled; /* (C) enable unit tester device */ 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 */ @@ -139,10 +144,13 @@ 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 lba_enhancer_enabled; /* (C) enable Vision Systems LBA Enhancer */ 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 other_ide_present; /* IDE controllers from non-IDE cards are present */ +extern int other_scsi_present; /* SCSI controllers from non-SCSI cards are present */ extern int fixed_size_x; extern int fixed_size_y; @@ -164,10 +172,11 @@ 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 int open_dir_usr_path; /* default file open dialog directory of usr_path */ +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 */ +extern char uuid[MAX_UUID_LEN]; /* UUID or machine identifier */ #ifndef USE_NEW_DYNAREC extern FILE *stdlog; /* file to log output to */ #endif diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 2b8a6396f..5a3eb39ec 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -52,12 +52,14 @@ extern "C" { #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_5582 0x01039 +#define VEN_SIS_5595_1997 0x11039 +#define VEN_SIS_5595 0x21039 +#define VEN_SMC 0x01055 +#define VEN_VIA 0x01106 +#define VEN_VIA_596B 0x11106 typedef struct acpi_regs_t { uint8_t acpitst; @@ -76,6 +78,25 @@ typedef struct acpi_regs_t { uint8_t gporeg[4]; uint8_t extiotrapsts; uint8_t extiotrapen; + uint8_t enter_c2_ps; + uint8_t enter_c3_ps; + uint8_t reg_12; + uint8_t reg_13; + uint8_t smi_cmd; + uint8_t reg_24; + uint8_t reg_25; + uint8_t reg_26; + uint8_t smi_en_val; + uint8_t smi_dis_val; + uint8_t mail_box; + uint8_t reg_2b; + uint8_t gp_tmr; + uint8_t leg_sts; + uint8_t leg_en; + uint8_t tst_ctl; + uint8_t reg_34; + uint8_t index; + uint8_t reg_ff; uint16_t pmsts; uint16_t pmen; uint16_t pmcntrl; @@ -91,6 +112,15 @@ typedef struct acpi_regs_t { uint16_t gpsmien; uint16_t pscntrl; uint16_t gpscists; + uint16_t reg_14; + uint16_t reg_16; + uint16_t reg_18; + uint16_t reg_1a; + uint16_t reg_1c; + uint16_t gpe_mul; + uint16_t gpe_ctl; + uint16_t gpe_smi; + uint16_t gpe_rl; int smi_lock; int smi_active; uint32_t pcntrl; @@ -107,7 +137,12 @@ typedef struct acpi_regs_t { uint32_t gpo_val; uint32_t gpi_val; uint32_t extsmi_val; - uint32_t pad0; + uint32_t reg_0c; + uint32_t gpe_sts; + uint32_t gpe_en; + uint32_t gpe_pin; + uint32_t gpe_io; + uint32_t gpe_pol; } acpi_regs_t; typedef struct acpi_t { @@ -128,11 +163,15 @@ typedef struct acpi_t { pc_timer_t timer; pc_timer_t resume_timer; pc_timer_t pwrbtn_timer; + pc_timer_t gp_timer; + pc_timer_t per_timer; nvr_t *nvr; apm_t *apm; void *i2c; void (*trap_update)(void *priv); void *trap_priv; + void *smbus; + void *priv; } acpi_t; /* Global variables. */ @@ -145,6 +184,9 @@ 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; +extern const device_t acpi_sis_5582_device; +extern const device_t acpi_sis_5595_1997_device; +extern const device_t acpi_sis_5595_device; /* Functions */ extern void acpi_update_irq(acpi_t *dev); @@ -163,6 +205,12 @@ 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_get_smbus(void *priv); +extern void acpi_sis5582_pmu_event(void *priv); +extern void acpi_sis5595_smi_raise(void *priv); +extern void acpi_sis5595_pmu_event(void *priv); +extern void acpi_sis5595_smbus_event(void *priv); +extern void acpi_sis5595_software_smi(void *priv); #ifdef __cplusplus } diff --git a/src/include/86box/bswap.h b/src/include/86box/bswap.h index ac758b20a..78183d137 100644 --- a/src/include/86box/bswap.h +++ b/src/include/86box/bswap.h @@ -40,91 +40,55 @@ #include -#ifdef HAVE_BYTESWAP_H -# include -#else -# define bswap_16(x) \ - ( \ - ((uint16_t)( \ - (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ - (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) )) \ - ) +#define bswap_16(x) \ + ((uint16_t)((((x) & 0x00ffu) << 8) | \ + (((x) & 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) )) \ - ) +#define bswap_32(x) \ + ((uint32_t)((((x) & 0x000000fful) << 24) | \ + (((x) & 0x0000ff00ul) << 8) | \ + (((x) & 0x00ff0000ul) >> 8) | \ + (((x) & 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*/ +# define bswap_64(x) \ + ((uint64_t)((((x) & 0x00000000000000ffull) << 56) | \ + (((x) & 0x000000000000ff00ull) << 40) | \ + (((x) & 0x0000000000ff0000ull) << 24) | \ + (((x) & 0x00000000ff000000ull) << 8) | \ + (((x) & 0x000000ff00000000ull) >> 8) | \ + (((x) & 0x0000ff0000000000ull) >> 24) | \ + (((x) & 0x00ff000000000000ull) >> 40) | \ + (((x) & 0xff00000000000000ull) >> 56))) -#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) { +#if defined (__GNUC__) || defined (__clang__) + return __builtin_bswap16(x); +#else return bswap_16(x); -} #endif +} -#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 +#if defined (__GNUC__) || defined (__clang__) + return __builtin_bswap32(x); #else -static __inline uint32_t -bswap32(uint32_t x) -{ return bswap_32(x); -} #endif +} -#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 +#if defined (__GNUC__) || defined (__clang__) + return __builtin_bswap64(x); #else -static __inline uint64_t -bswap64(uint64_t x) -{ - return bswap_64(x); -} + return bswap_16(x); #endif +} static __inline void bswap16s(uint16_t *s) @@ -198,12 +162,10 @@ CPU_CONVERT(le, 64, uint64_t) /* unaligned versions (optimized for frequent unaligned accesses)*/ #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_be16wu(p, v) cpu_to_be16w(p, v) # define cpu_to_be32wu(p, v) cpu_to_be32w(p, v) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index d188c9243..15127b06e 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -244,6 +244,7 @@ typedef struct cdrom { int prev_host_drive; int cd_buflen; int audio_op; + int audio_muted_soft; int sony_msf; const cdrom_ops_t *ops; diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 39faf9f33..5222e8aa0 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -78,8 +78,8 @@ typedef struct 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 void cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); +extern void 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); diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 95440a172..d5a96baf9 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -130,8 +130,16 @@ 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_550x_85c503_device; +extern const device_t sis_85c50x_5503_device; +extern const device_t sis_550x_device; extern const device_t sis_5511_device; extern const device_t sis_5571_device; +extern const device_t sis_5581_device; +extern const device_t sis_5591_1997_device; +extern const device_t sis_5591_device; +extern const device_t sis_5600_1997_device; +extern const device_t sis_5600_device; /* ST */ extern const device_t stpc_client_device; @@ -144,6 +152,8 @@ extern const device_t stpc_lpt_device; /* UMC */ extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; +extern const device_t umc_8886bf_device; +extern const device_t umc_8890_device; extern const device_t umc_hb4_device; /* VIA */ @@ -174,6 +184,8 @@ extern const device_t vlsi_scamp_device; extern const device_t wd76c10_device; /* Miscellaneous Hardware */ +extern const device_t nec_mate_unk_device; + extern const device_t phoenix_486_jumper_device; extern const device_t phoenix_486_jumper_pci_device; diff --git a/src/include/86box/device.h b/src/include/86box/device.h index b2d7a05ed..cc564ceb2 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -41,23 +41,42 @@ #ifndef 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_END -1 /* N/A */ -#define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */ -#define CONFIG_STANDALONE 257 /* not available on the on-board variant */ +#define CONFIG_SHIFT 4 + +#define CONFIG_TYPE_INT (0 << CONFIG_SHIFT) +#define CONFIG_TYPE_STRING (1 << CONFIG_SHIFT) +#define CONFIG_TYPE_HEX16 (2 << CONFIG_SHIFT) +#define CONFIG_TYPE_HEX20 (3 << CONFIG_SHIFT) +#define CONFIG_TYPE_MAC (4 << CONFIG_SHIFT) + +#define CONFIG_INT (0 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_BINARY (1 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_SELECTION (2 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_MIDI_OUT (3 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_SPINNER (4 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_MIDI_IN (5 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_MEMORY (6 | CONFIG_TYPE_INT) /* config_get_int() */ + +#define CONFIG_STRING (0 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_FNAME (1 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_SERPORT (2 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_BIOS (3 | CONFIG_TYPE_STRING) /* config_get_string() */ + +#define CONFIG_HEX16 (0 | CONFIG_TYPE_HEX16) /* config_get_hex16() */ + +#define CONFIG_HEX20 (0 | CONFIG_TYPE_HEX20) /* config_get_hex20() */ + +#define CONFIG_MAC (0 | CONFIG_TYPE_MAC) /* N/A */ + +#define CONFIG_SUBTYPE_MASK (CONFIG_IS_STRING - 1) + +#define CONFIG_DEP (16 << CONFIG_SHIFT) +#define CONFIG_TYPE_MASK (CONFIG_DEP - 1) + +// #define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */ +// #define CONFIG_STANDALONE 257 /* not available on the on-board variant */ enum { DEVICE_PCJR = 2, /* requires an IBM PCjr */ @@ -100,38 +119,49 @@ enum { #define BIOS_INTERLEAVED_INVERT 8 #define BIOS_HIGH_BIT_INVERT 16 +#define device_common_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] + typedef struct device_config_selection_t { const char *description; int value; } device_config_selection_t; -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 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]; +typedef struct _device_dep_config_ { + device_common_config_t; +} device_dep_config_t; + +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]; + /* Configuration options that depend on the device variant. + To prevent excessive nesting, there is no CONFIG_BIOS + option a dep_config struct */ + const device_dep_config_t *dep_config; +} device_config_bios_t; + +typedef struct _device_config_ { + device_common_config_t; const device_config_bios_t bios[32]; } device_config_t; @@ -173,6 +203,7 @@ 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_linked(const device_t *d, void *priv); 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); @@ -188,6 +219,7 @@ 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_get_common_priv(void); 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); @@ -202,6 +234,8 @@ extern const char *device_get_bios_file(const device_t *dev, const char *interna extern int device_is_valid(const device_t *, int m); +extern const device_t* device_context_get_device(void); + 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); diff --git a/src/include/86box/dma.h b/src/include/86box/dma.h index 7ead53ba0..23ce04898 100644 --- a/src/include/86box/dma.h +++ b/src/include/86box/dma.h @@ -96,6 +96,8 @@ extern void writedma2(uint8_t temp); extern int dma_get_drq(int channel); extern void dma_set_drq(int channel, int set); +extern int dma_channel_read_only(int channel); +extern int dma_channel_advance(int channel); extern int dma_channel_read(int channel); extern int dma_channel_write(int channel, uint16_t val); @@ -118,4 +120,6 @@ void dma_high_page_init(void); void dma_remove_sg(void); void dma_set_sg_base(uint8_t sg_base); +extern int dma_channel_readable(int channel); + #endif /*EMU_DMA_H*/ diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 9441bdfc4..9529fde5c 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -55,6 +55,8 @@ extern int fdc_type; #define FDC_FLAG_SEC 0x1000 /* Is Secondary */ #define FDC_FLAG_TER 0x2000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x3000 /* Is Quaternary */ +#define FDC_FLAG_CHANNEL 0x3000 /* Channel mask */ +#define FDC_FLAG_NO_DSR_RESET 0x4000 /* Has no DSR reset */ typedef struct fdc_t { uint8_t dor; @@ -65,76 +67,86 @@ typedef struct fdc_t { 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]; + uint8_t power_down; + + uint8_t head; + uint8_t lastdrive; + uint8_t sector; + uint8_t drive; + uint8_t rate; + uint8_t tc; + uint8_t pnum; + uint8_t ptot; + + uint8_t reset_stat; + uint8_t seek_dir; + uint8_t perp; + uint8_t format_state; + uint8_t format_n; + uint8_t step; + uint8_t noprec; + uint8_t data_ready; + + uint8_t paramstogo; + uint8_t enh_mode; + uint8_t dma; + uint8_t densel_polarity; + uint8_t densel_force; + uint8_t fifo; + uint8_t tfifo; + uint8_t fifobufpos; + + uint8_t drv2en; + uint8_t gap; + uint8_t enable_3f1; + uint8_t format_sectors; + uint8_t mfm; + uint8_t deleted; + uint8_t wrong_am; + uint8_t sc; + + uint8_t fintr; + uint8_t rw_drive; + + uint8_t lock; + uint8_t dsr; + + uint8_t params[15]; + uint8_t specify[2]; + uint8_t res[11]; + uint8_t eot[4]; + uint8_t rwc[4]; + + uint16_t pcn[4]; uint16_t base_address; + uint16_t rw_track; - 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 bit_rate; /* Should be 250 at start. */ - 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 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 flags; int 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 drvrate[4]; + + void *fifo_p; sector_id_t read_track_sector; sector_id_t format_sector_id; @@ -183,6 +195,7 @@ 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 void fdc_set_power_down(fdc_t *fdc, uint8_t power_down); 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); @@ -240,6 +253,7 @@ 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_ps1_2121_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; diff --git a/src/include/86box/fifo.h b/src/include/86box/fifo.h index e76189d8a..f87f932e0 100644 --- a/src/include/86box/fifo.h +++ b/src/include/86box/fifo.h @@ -1,3 +1,6 @@ +#ifndef FIFO_H +#define FIFO_H + /* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM @@ -71,3 +74,5 @@ 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); + +#endif /*FIFO_H*/ diff --git a/src/include/86box/filters.h b/src/include/86box/filters.h index dfe19c654..d11e79512 100644 --- a/src/include/86box/filters.h +++ b/src/include/86box/filters.h @@ -5,7 +5,7 @@ /* fc=150Hz */ static inline float -adgold_highpass_iir(int i, float NewSample) +adgold_highpass_iir(int c, int i, float NewSample) { float ACoef[NCoef + 1] = { 0.98657437157334349000, @@ -19,28 +19,28 @@ adgold_highpass_iir(int i, float NewSample) 0.97261396931534050000 }; - static float y[2][NCoef + 1]; /* output samples */ - static float x[2][NCoef + 1]; /* input samples */ + static float y[2][2][NCoef + 1]; /* output samples */ + static float x[2][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]; + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; for (n = 1; n <= NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; - return y[i][0]; + return y[c][i][0]; } /* fc=150Hz */ static inline float -adgold_lowpass_iir(int i, float NewSample) +adgold_lowpass_iir(int c, int i, float NewSample) { float ACoef[NCoef + 1] = { 0.00009159473951071446, @@ -54,23 +54,23 @@ adgold_lowpass_iir(int i, float NewSample) 0.97261396931306277000 }; - static float y[2][NCoef + 1]; /* output samples */ - static float x[2][NCoef + 1]; /* input samples */ + static float y[2][2][NCoef + 1]; /* output samples */ + static float x[2][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]; + x[c][i][n] = x[c][i][n - 1]; + y[c][i][n] = y[c][i][n - 1]; } /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; for (n = 1; n <= NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; - return y[i][0]; + return y[c][i][0]; } /* fc=56Hz */ @@ -197,8 +197,8 @@ low_iir(int c, int i, double NewSample) 0.93726236021404663000 }; - static double y[3][2][NCoef + 1]; /* output samples */ - static double x[3][2][NCoef + 1]; /* input samples */ + static double y[5][2][NCoef + 1]; /* output samples */ + static double x[5][2][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -232,8 +232,8 @@ low_cut_iir(int c, int i, double NewSample) 0.93726236021916731000 }; - static double y[3][2][NCoef + 1]; /* output samples */ - static double x[3][2][NCoef + 1]; /* input samples */ + static double y[5][2][NCoef + 1]; /* output samples */ + static double x[5][2][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -266,8 +266,8 @@ high_iir(int c, int i, double NewSample) -1.36640781670578510000, 0.52352474706139873000 }; - static double y[3][2][NCoef + 1]; /* output samples */ - static double x[3][2][NCoef + 1]; /* input samples */ + static double y[5][2][NCoef + 1]; /* output samples */ + static double x[5][2][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -300,8 +300,8 @@ high_cut_iir(int c, int i, double NewSample) -1.36640781666419950000, 0.52352474703279628000 }; - static double y[3][2][NCoef + 1]; /* output samples */ - static double x[3][2][NCoef + 1]; /* input samples */ + static double y[5][2][NCoef + 1]; /* output samples */ + static double x[5][2][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -334,8 +334,8 @@ deemph_iir(int i, double NewSample) -1.05429146278569141337, 0.26412280202756849290 }; - static double y[3][NCoef + 1]; /* output samples */ - static double x[3][NCoef + 1]; /* input samples */ + static double y[5][NCoef + 1]; /* output samples */ + static double x[5][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -372,8 +372,8 @@ sb_iir(int c, int i, double NewSample) 0.55326988968868285000 }; - static double y[3][2][NCoef + 1]; /* output samples */ - static double x[3][2][NCoef + 1]; /* input samples */ + static double y[5][2][NCoef + 1]; /* output samples */ + static double x[5][2][NCoef + 1]; /* input samples */ int n; /* shift the old samples */ @@ -395,13 +395,13 @@ sb_iir(int c, int i, double NewSample) #define NCoef 1 #define SB16_NCoef 51 -extern double low_fir_sb16_coef[3][SB16_NCoef]; +extern double low_fir_sb16_coef[5][SB16_NCoef]; static inline double low_fir_sb16(int c, int i, double NewSample) { - static double x[3][2][SB16_NCoef + 1]; // input samples - static int pos[3] = { 0, 0 }; + static double x[4][2][SB16_NCoef + 1]; // input samples + static int pos[4] = { 0, 0, 0, 0 }; double out = 0.0; int n; @@ -422,4 +422,31 @@ low_fir_sb16(int c, int i, double NewSample) return out; } +extern double low_fir_pas16_coef[SB16_NCoef]; + +static inline double +low_fir_pas16(const int i, const double NewSample) +{ + static double x[2][SB16_NCoef + 1]; // input samples + static int pos = 0; + double out = 0.0; + int n; + + /* Calculate the new output */ + x[i][pos] = NewSample; + + for (n = 0; n < ((SB16_NCoef + 1) - pos) && n < SB16_NCoef; n++) + out += low_fir_pas16_coef[n] * x[i][n + pos]; + for (; n < SB16_NCoef; n++) + out += low_fir_pas16_coef[n] * x[i][(n + pos) - (SB16_NCoef + 1)]; + + if (i == 1) { + pos++; + if (pos > SB16_NCoef) + pos = 0; + } + + return out; +} + #endif /*EMU_FILTERS_H*/ diff --git a/src/include/86box/flash.h b/src/include/86box/flash.h index d161d416b..6f0e1ff15 100644 --- a/src/include/86box/flash.h +++ b/src/include/86box/flash.h @@ -60,4 +60,6 @@ extern const device_t sst_flash_49lf080_device; extern const device_t sst_flash_49lf016_device; extern const device_t sst_flash_49lf160_device; +extern const device_t amd_flash_29f020a_device; + #endif /*EMU_FLASH_H*/ diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index ba3568464..d9c702394 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -24,6 +24,10 @@ #define MAX_PLAT_JOYSTICKS 8 #define MAX_JOYSTICKS 4 +#define MAX_JOY_AXES 16 +#define MAX_JOY_BUTTONS 32 +#define MAX_JOY_POVS 4 + #define JS_TYPE_NONE 0 #define JS_TYPE_2AXIS_4BUTTON 1 #define JS_TYPE_2AXIS_6BUTTON 2 @@ -36,7 +40,6 @@ #define POV_X 0x80000000 #define POV_Y 0x40000000 -#define SLIDER 0x20000000 #define AXIS_NOT_PRESENT -99999 @@ -47,46 +50,39 @@ typedef struct plat_joystick_t { char name[260]; - int a[8]; - int b[32]; - int p[4]; - int s[2]; + int a[MAX_JOY_AXES]; + int b[MAX_JOY_BUTTONS]; + int p[MAX_JOY_POVS]; struct { char name[260]; int id; - } axis[8]; + } axis[MAX_JOY_AXES]; struct { char name[260]; int id; - } button[32]; + } button[MAX_JOY_BUTTONS]; struct { char name[260]; int id; - } pov[4]; - - struct { - char name[260]; - int id; - } slider[2]; + } pov[MAX_JOY_POVS]; int nr_axes; int nr_buttons; int nr_povs; - int nr_sliders; } plat_joystick_t; typedef struct joystick_t { - int axis[8]; - int button[32]; - int pov[4]; + int axis[MAX_JOY_AXES]; + int button[MAX_JOY_BUTTONS]; + int pov[MAX_JOY_POVS]; int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; + int axis_mapping[MAX_JOY_AXES]; + int button_mapping[MAX_JOY_BUTTONS]; + int pov_mapping[MAX_JOY_POVS][2]; } joystick_t; typedef struct joystick_if_t { @@ -104,9 +100,9 @@ typedef struct joystick_if_t { int button_count; int pov_count; int max_joysticks; - const char *axis_names[8]; - const char *button_names[32]; - const char *pov_names[4]; + const char *axis_names[MAX_JOY_AXES]; + const char *button_names[MAX_JOY_BUTTONS]; + const char *pov_names[MAX_JOY_POVS]; } joystick_if_t; #ifdef __cplusplus @@ -158,6 +154,19 @@ 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 const joystick_if_t joystick_2axis_2button; +extern const joystick_if_t joystick_2axis_4button; +extern const joystick_if_t joystick_3axis_2button; +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; + +extern const joystick_if_t joystick_ch_flightstick_pro; + +extern const joystick_if_t joystick_sw_pad; + +extern const joystick_if_t joystick_tm_fcs; #ifdef __cplusplus } #endif diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 8ede3e786..38c0a6e9a 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -60,6 +60,9 @@ 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_ali1489_device; /* ALi M1489 */ +extern const device_t ide_ali5213_device; /* ALi M5213 */ + 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) */ @@ -74,24 +77,35 @@ 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_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */ + +extern const device_t ide_um8673f_device; /* UMC UM8673F */ +extern const device_t ide_um8886af_device; /* UMC UM8886AF */ + +extern const device_t ide_w83769f_vlb_device; /* Winbond W83769F VLB */ +extern const device_t ide_w83769f_vlb_34_device; /* Winbond W83769F VLB (Port 34h) */ +extern const device_t ide_w83769f_pci_device; /* Winbond W83769F PCI */ +extern const device_t ide_w83769f_pci_34_device; /* Winbond W83769F PCI (Port 34h) */ 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 mcide_device; + 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 */ +/* Miscellaneous */ +extern const device_t lba_enhancer_device; + extern void hdc_init(void); extern void hdc_reset(void); diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 291dec303..9094f7f00 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -82,7 +82,7 @@ typedef struct ide_s { uint8_t selected; uint8_t command; uint8_t head; - uint8_t pad; + uint8_t params_specified; int type; int board; int irqstat; @@ -188,6 +188,8 @@ extern void ide_atapi_attach(ide_t *dev); extern void *ide_xtide_init(void); extern void ide_xtide_close(void); +extern void ide_drives_set_shadow(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); @@ -203,12 +205,14 @@ extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); extern void ide_set_base_addr(int board, int base, uint16_t port); +extern void ide_set_irq(int board, int irq); extern void ide_handlers(uint8_t board, int set); 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_1addr(uint8_t ld, isapnp_device_config_t *config, void *priv); #endif extern double ide_atapi_get_period(uint8_t channel); diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 2283497bb..3a69fdfac 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -43,6 +43,7 @@ typedef struct sff8038i_t uint8_t irq_state; uint8_t channel; uint8_t irq_line; + uint8_t mirq; uint16_t base; uint16_t pad; uint32_t ptr; @@ -72,10 +73,9 @@ extern void sff_bus_master_reset(sff8038i_t *dev); extern void sff_set_slot(sff8038i_t *dev, int slot); extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); - 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_level(sff8038i_t *dev, int irq_level); +extern void sff_set_mirq(sff8038i_t *dev, uint8_t mirq); #endif /*EMU_HDC_IDE_SFF8038I_H*/ diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index 8c82209c7..89a6cf1ff 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -159,8 +159,8 @@ typedef struct hard_disk_t { char fn[1024]; /* Name of current image file */ char vhd_parent[1041]; /* Differential VHD parent file */ - uint32_t res0; - uint32_t pad1; + uint32_t seek_pos; + uint32_t seek_len; uint32_t base; uint32_t spt; uint32_t hpc; /* Physical geometry parameters */ diff --git a/src/include/86box/joystick_ch_flightstick_pro.h b/src/include/86box/joystick_ch_flightstick_pro.h deleted file mode 100644 index b49800ecb..000000000 --- a/src/include/86box/joystick_ch_flightstick_pro.h +++ /dev/null @@ -1,43 +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 Flight Stick Pro driver. - * - * - * - * Authors: Miran Grca, - * 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 - * 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 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 deleted file mode 100644 index c874677ea..000000000 --- a/src/include/86box/joystick_standard.h +++ /dev/null @@ -1,49 +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 joystick driver. - * - * - * - * Authors: Miran Grca, - * 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 - * 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 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; -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 deleted file mode 100644 index a75d802de..000000000 --- a/src/include/86box/joystick_sw_pad.h +++ /dev/null @@ -1,43 +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 Sidewinder Pro driver. - * - * - * - * Authors: Miran Grca, - * 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 - * 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 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 deleted file mode 100644 index 65e734a40..000000000 --- a/src/include/86box/joystick_tm_fcs.h +++ /dev/null @@ -1,43 +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 Flight Control System driver. - * - * - * - * Authors: Miran Grca, - * 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 - * 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 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 a4b079760..846123627 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -79,6 +79,7 @@ typedef struct atkbc_dev_t { int y; int z; int b; + int ignore; int *scan; @@ -241,9 +242,12 @@ 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_holtek_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_phoenix_device; +extern const device_t keyboard_ps2_mca_1_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; @@ -275,6 +279,9 @@ extern int keyboard_isfsexit_up(void); extern int keyboard_ismsexit(void); extern void keyboard_set_is_amstrad(int ams); +extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); +extern void kbc_at_handler(int set, void *priv); + 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); diff --git a/src/include/86box/language.h b/src/include/86box/language.h deleted file mode 100644 index af459c0ff..000000000 --- a/src/include/86box/language.h +++ /dev/null @@ -1,284 +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 language management module. - * - * - * - * Authors: Fred N. van Kempen, - * - * Copyright 2017-2018 Fred N. van Kempen. - * Copyright 2022 Jasmine Iwanek. - */ - -#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_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_2088 2088 // "Check BPB" -#define IDS_BPB IDS_2088 // "Check BPB" - -#define IDS_2089 2089 // "KB" -#define IDS_KB IDS_2089 // "KB" - -#define IDS_2090 2090 // "Could not initialize the video..." - -#define IDS_2091 2091 // "Default" -#define IDS_DEFAULT IDS_2091 // "Default" - -#define IDS_2092 2092 // "%i Wait state(s)" -#define IDS_WS IDS_2092 // "%i Wait state(s)" - -#define IDS_2093 2093 // "Type" -#define IDS_TYPE IDS_2093 // "Type" - -/* 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_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_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_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_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" - -#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/lpt.h b/src/include/86box/lpt.h index a9a9eac65..4e95b64c3 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -83,6 +83,8 @@ 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 uint8_t lpt_read_port(int port, uint16_t reg); + extern uint8_t lpt_read_status(int port); extern void lpt_irq(void *priv, int raise); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8560f0d3b..c0d60c221 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -49,37 +49,38 @@ #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 */ +#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 (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_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 */ +#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_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI 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_FLAGS_NONE 0x00000000 /* sys has no int devices */ #define MACHINE_SOFTFLOAT_ONLY 0x00000001 /* sys requires SoftFloat FPU */ @@ -244,8 +245,12 @@ enum { MACHINE_CHIPSET_SIS_471, MACHINE_CHIPSET_SIS_496, MACHINE_CHIPSET_SIS_501, + MACHINE_CHIPSET_SIS_5501, MACHINE_CHIPSET_SIS_5511, MACHINE_CHIPSET_SIS_5571, + MACHINE_CHIPSET_SIS_5581, + MACHINE_CHIPSET_SIS_5591, + MACHINE_CHIPSET_SIS_5600, MACHINE_CHIPSET_SMSC_VICTORYBX_66, MACHINE_CHIPSET_STPC_CLIENT, MACHINE_CHIPSET_STPC_CONSUMER_II, @@ -446,6 +451,7 @@ 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_senor_scat286_init(const machine_t *); extern int machine_at_super286c_init(const machine_t *); extern int machine_at_super286tr_init(const machine_t *); extern int machine_at_spc4200p_init(const machine_t *); @@ -471,6 +477,7 @@ 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_325ax_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 *); @@ -485,6 +492,8 @@ 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_ecs386v_init(const machine_t *); +extern int machine_at_tandy4000_init(const machine_t *); extern int machine_at_rycleopardlx_init(const machine_t *); @@ -504,6 +513,7 @@ 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_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); @@ -511,6 +521,9 @@ 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_pb450_init(const machine_t *); +extern int machine_at_pb450_init(const machine_t *); +extern int machine_at_aptiva510_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); @@ -524,16 +537,23 @@ 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_pci400ca_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_4gpv5_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_ms4144_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_amis76_init(const machine_t *); extern int machine_at_ninja_init(const machine_t *); +extern int machine_at_bat4ip3e_init(const machine_t *); +extern int machine_at_486pi_init(const machine_t *); +extern int machine_at_sb486p_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 *); @@ -545,6 +565,7 @@ 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_arb1476_init(const machine_t *); extern int machine_at_pci400cb_init(const machine_t *); extern int machine_at_g486ip_init(const machine_t *); @@ -552,18 +573,24 @@ 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_iach488_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_hot433a_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_actiontower8400_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 *); +extern int machine_at_dvent4xx_init(const machine_t *); +extern int machine_at_ecsal486_init(const machine_t *); +extern int machine_at_ap4100aa_init(const machine_t *); +extern int machine_at_atc1762_init(const machine_t *); /* m_at_commodore.c */ extern int machine_at_cmdpc_init(const machine_t *); @@ -588,7 +615,7 @@ 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_586is_init(const machine_t *); extern int machine_at_pb520r_init(const machine_t *); extern int machine_at_excalibur_init(const machine_t *); @@ -602,22 +629,30 @@ extern int machine_at_p5sp4_init(const machine_t *); extern int machine_at_plato_init(const machine_t *); extern int machine_at_dellplato_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_586ip_init(const machine_t *); +extern int machine_at_tek932_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_pt2000_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_ncselp90_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 *); +extern int machine_at_ms5109_init(const machine_t *); +extern int machine_at_torino_init(const machine_t *); + +extern int machine_at_hot539_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 *); @@ -638,12 +673,17 @@ 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_dellhannibalp_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_pc140_6260_init(const machine_t *); extern int machine_at_ms5124_init(const machine_t *); +extern int machine_at_amis727_init(const machine_t *); extern int machine_at_vectra54_init(const machine_t *); +extern int machine_at_5sbm2_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 *); @@ -654,6 +694,7 @@ 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_epc2102_init(const machine_t *); extern int machine_at_ap5vm_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); @@ -668,6 +709,7 @@ 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_ma23c_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) @@ -678,6 +720,8 @@ extern int machine_at_thunderbolt_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_richmond_init(const machine_t *); +extern int machine_at_tomahawk_init(const machine_t *); extern int machine_at_ficva502_init(const machine_t *); @@ -685,13 +729,20 @@ 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_cb52xsi_init(const machine_t *); extern int machine_at_m560_init(const machine_t *); extern int machine_at_ms5164_init(const machine_t *); +extern int machine_at_sp97xv_init(const machine_t *); +extern int machine_at_sq578_init(const machine_t *); + +extern int machine_at_ms5172_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_gwlucas_init(const machine_t *); extern int machine_at_5aa_init(const machine_t *); extern int machine_at_5ax_init(const machine_t *); @@ -700,12 +751,15 @@ 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_5sg100_init(const machine_t *); + /* m_at_socket8.c */ +extern int machine_at_ap61_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_lgibmx61_init(const machine_t *); extern int machine_at_vs440fx_init(const machine_t *); extern int machine_at_gw2kvenus_init(const machine_t *); extern int machine_at_ap440fx_init(const machine_t *); @@ -726,9 +780,12 @@ 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_ma30d_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_lgibmx7g_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 *); @@ -746,6 +803,9 @@ 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 *); +extern int machine_at_p6f99_init(const machine_t *); +extern int machine_at_m747_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 *); @@ -846,6 +906,7 @@ 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_glabios_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 *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 69a2b5de8..a130309c4 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -302,7 +302,10 @@ extern int memspeed[11]; extern int mmu_perm; extern uint8_t high_page; /* if a high (> 4 gb) page was detected */ +extern uint8_t *_mem_exec[MEM_MAPPINGS_NO]; + extern uint32_t pages_sz; /* #pages in table */ +extern int read_type; extern int mem_a20_state; extern int mem_a20_alt; @@ -398,6 +401,7 @@ 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_set_wp(uint64_t base, uint64_t size, uint8_t flags, uint8_t wp); extern void mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access); extern uint8_t mem_readb_phys(uint32_t addr); @@ -439,6 +443,8 @@ extern void mem_reset_page_blocks(void); extern void flushmmucache(void); extern void flushmmucache_nopc(void); +extern void mem_debug_check_addr(uint32_t addr, int write); + extern void mem_a20_init(void); extern void mem_a20_recalc(void); @@ -447,6 +453,8 @@ extern void mem_close(void); extern void mem_reset(void); extern void mem_remap_top(int kb); +extern void umc_smram_recalc(uint32_t start, int set); + extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index 4bc678817..7f7ad89ae 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -102,7 +102,9 @@ extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #ifdef EMU_DEVICE_H extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; +# if defined(DEV_BRANCH) && defined(USE_OPL4ML) extern const device_t opl4_midi_device; +# endif # ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; # endif diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 3ed6b2126..786b86f41 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -93,6 +93,7 @@ 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_scale_axis(int axis, int val); 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); diff --git a/src/include/86box/net_3c501.h b/src/include/86box/net_3c501.h deleted file mode 100644 index c55151ab8..000000000 --- a/src/include/86box/net_3c501.h +++ /dev/null @@ -1,45 +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 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 deleted file mode 100644 index 44024850f..000000000 --- a/src/include/86box/net_3c503.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of the 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 - -extern const device_t threec503_device; - -#endif /*NET_3C503_H*/ diff --git a/src/include/86box/net_ne2000.h b/src/include/86box/net_ne2000.h index 350668ccb..75185cf90 100644 --- a/src/include/86box/net_ne2000.h +++ b/src/include/86box/net_ne2000.h @@ -37,18 +37,15 @@ #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_NE1000_COMPAT = 2, /* 8-bit ISA NE1000-Compatible */ + NE2K_NE2000 = 3, /* 16-bit ISA NE2000 */ + NE2K_NE2000_COMPAT = 4, /* 16-bit ISA NE2000-Compatible */ + NE2K_ETHERNEXT_MC = 5, /* 16-bit MCA EtherNext/MC */ + NE2K_RTL8019AS = 6, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_DE220P = 7, /* 16-bit ISA PnP D-Link DE-220P */ + NE2K_RTL8029AS = 8 /* 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; - #endif /*NET_NE2000_H*/ diff --git a/src/include/86box/net_pcnet.h b/src/include/86box/net_pcnet.h index ccdc7e832..994d88c75 100644 --- a/src/include/86box/net_pcnet.h +++ b/src/include/86box/net_pcnet.h @@ -30,11 +30,4 @@ enum { 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; - #endif /*NET_PCNET_H*/ diff --git a/src/include/86box/net_plip.h b/src/include/86box/net_plip.h deleted file mode 100644 index 83c33e4c6..000000000 --- a/src/include/86box/net_plip.h +++ /dev/null @@ -1,26 +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 PLIP parallel port network device. - * - * - * - * Authors: RichardG, - * - * Copyright 2020 RichardG. - */ - -#ifndef NET_PLIP_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; - -#endif /*NET_PLIP_H*/ diff --git a/src/include/86box/net_rtl8139.h b/src/include/86box/net_rtl8139.h deleted file mode 100644 index f44d0facb..000000000 --- a/src/include/86box/net_rtl8139.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t rtl8139c_plus_device; diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h deleted file mode 100644 index 3e14deeea..000000000 --- a/src/include/86box/net_tulip.h +++ /dev/null @@ -1,3 +0,0 @@ -extern const device_t dec_tulip_device; -extern const device_t dec_tulip_21140_device; -extern const device_t dec_tulip_21140_vpc_device; diff --git a/src/include/86box/net_wd8003.h b/src/include/86box/net_wd8003.h index 726510cdb..6797c7d88 100644 --- a/src/include/86box/net_wd8003.h +++ b/src/include/86box/net_wd8003.h @@ -54,11 +54,4 @@ enum { 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 wd8013epa_device; - #endif /*NET_WD8003_H*/ diff --git a/src/include/86box/network.h b/src/include/86box/network.h index e9b703ee0..9588de86a 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -192,12 +192,66 @@ 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 *); +#ifdef EMU_DEVICE_H extern const device_t *network_card_getdevice(int); +#endif 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 EMU_DEVICE_H +/* 3Com Etherlink */ +extern const device_t threec501_device; +extern const device_t threec503_device; + +/* Novell NE2000 and compatibles */ +extern const device_t ne1000_device; +extern const device_t ne1000_compat_device; +extern const device_t ne2000_device; +extern const device_t ne2000_compat_device; +extern const device_t ethernext_mc_device; +extern const device_t rtl8019as_device; +extern const device_t de220p_device; +extern const device_t rtl8029as_device; + +/* AMD PCnet*/ +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_am79c973_onboard_device; + +/* Modem */ +extern const device_t modem_device; + +/* PLIP */ +#ifdef EMU_LPT_H +extern const lpt_device_t lpt_plip_device; +#endif +extern const device_t plip_device; + +/* Realtek RTL8139C+ */ +extern const device_t rtl8139c_plus_device; + +/* DEC Tulip */ +extern const device_t dec_tulip_device; +extern const device_t dec_tulip_21140_device; +extern const device_t dec_tulip_21140_vpc_device; +extern const device_t dec_tulip_21040_device; + +/* WD 80x3 */ +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 + #ifdef __cplusplus } #endif diff --git a/src/include/86box/novell_cardkey.h b/src/include/86box/novell_cardkey.h new file mode 100644 index 000000000..8ad3eabab --- /dev/null +++ b/src/include/86box/novell_cardkey.h @@ -0,0 +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. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Novell NetWare 2.x Key Card, which + * was used for anti-piracy protection. + * + * + * Authors: Cacodemon345 + * + * Copyright 2024 Cacodemon345. + */ +#ifndef NOVELL_KEYCARD_H +#define NOVELL_KEYCARD_H + +/* I/O port range used. */ +#define NOVELL_KEYCARD_ADDR 0x23a +#define NOVELL_KEYCARD_ADDRLEN 6 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ +extern const device_t novell_keycard_device; + +/* Functions. */ + +#ifdef __cplusplus +} +#endif + +#endif /*BUGGER_H*/ \ No newline at end of file diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index d24ca903c..85e0954f0 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -122,6 +122,8 @@ 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 uint8_t nvr_get_index(void *priv, uint8_t addr_id); +extern void nvr_at_data_port(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); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 17f9f6687..8483eb417 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -71,6 +71,7 @@ #define FLAG_CONFIG_M1_IO_ON 0x00000020 #define FLAG_NO_IRQ_STEERING 0x00000040 #define FLAG_NO_BRIDGES 0x00000080 +#define FLAG_TRC_CONTROLS_CPURST 0x00000100 #define FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2 #define FLAG_MASK 0x0000007f @@ -285,6 +286,7 @@ extern const device_t via_vp3_agp_device; extern const device_t via_mvp3_agp_device; extern const device_t via_apro_agp_device; extern const device_t via_vt8601_agp_device; +extern const device_t sis_5xxx_agp_device; #endif #endif /*EMU_PCI_H*/ diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index d288b7e6c..eb03fd2c9 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -42,6 +42,7 @@ typedef struct ctr_t { int state; int null_count; int do_read_status; + int enable; union { int32_t count; @@ -55,9 +56,11 @@ typedef struct ctr_t { }; uint32_t l; + uint32_t lback; + uint32_t lback2; void (*load_func)(uint8_t new_m, int new_count); - void (*out_func)(int new_out, int old_out); + void (*out_func)(int new_out, int old_out, void *priv); } ctr_t; typedef struct PIT { @@ -68,8 +71,14 @@ typedef struct PIT { ctr_t counters[3]; uint8_t ctrl; + + uint64_t pit_const; + + void *dev_priv; } pit_t; +extern pit_t *ext_pit; + enum { PIT_8253 = 0, PIT_8254 = 1, @@ -87,10 +96,11 @@ typedef struct pit_intf_t { /* 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)); + void (*set_out_func)(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv)); /* 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 (*set_pit_const)(void *data, uint64_t pit_const); void *data; } pit_intf_t; @@ -102,6 +112,9 @@ extern double PCICLK; extern double AGPCLK; extern uint64_t PITCONST; +extern uint64_t PAS16CONST; +extern uint64_t PAS16CONST2; +extern uint64_t PASSCSICONST; extern uint64_t ISACONST; extern uint64_t CGACONST; extern uint64_t MDACONST; @@ -112,21 +125,35 @@ extern uint64_t RTCCONST; extern int refresh_at_enable; -/* Sets a counter's CLOCK input. */ -extern void pit_ctr_set_clock(ctr_t *ctr, int clock); +extern void pit_device_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 void pit_change_pas16_consts(double prescale); + +extern void pit_set_pit_const(void *data, uint64_t pit_const); + +extern void ctr_clock(void *data, int counter_id); + +/* Sets a counter's CLOCK input. */ +extern void pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv); + +extern void pit_ctr_set_gate(void *data, int counter_id, int gate); + +extern void pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv)); + +extern void pit_ctr_set_using_timer(void *data, int counter_id, int using_timer); + +extern pit_t *pit_common_init(int type, void (*out0)(int new_out, int old_out, void *priv), void (*out1)(int new_out, int old_out, void *priv)); extern pit_t *pit_ps2_init(int type); extern void pit_reset(pit_t *dev); -extern void pit_irq0_timer_ps2(int new_out, int old_out); +extern void pit_irq0_timer_ps2(int new_out, int old_out, void *priv); -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, void *priv); +extern void pit_refresh_timer_at(int new_out, int old_out, void *priv); -extern void pit_speaker_timer(int new_out, int old_out); +extern void pit_speaker_timer(int new_out, int old_out, void *priv); -extern void pit_nmi_timer_ps2(int new_out, int old_out); +extern void pit_nmi_timer_ps2(int new_out, int old_out, void *priv); extern void pit_set_clock(uint32_t clock); extern void pit_handler(int set, uint16_t base, int size, void *priv); @@ -135,6 +162,7 @@ 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 i8253_ext_io_device; extern const device_t i8254_device; extern const device_t i8254_sec_device; extern const device_t i8254_ext_io_device; diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h index 2485a360c..5650ffb4d 100644 --- a/src/include/86box/pit_fast.h +++ b/src/include/86box/pit_fast.h @@ -56,10 +56,14 @@ typedef struct ctrf_t { }; uint32_t l; + + uint64_t pit_const; + pc_timer_t timer; void (*load_func)(uint8_t new_m, int new_count); - void (*out_func)(int new_out, int old_out); + void (*out_func)(int new_out, int old_out, void *priv); + void *priv; } ctrf_t; typedef struct pitf_t { @@ -67,8 +71,22 @@ typedef struct pitf_t { ctrf_t counters[3]; uint8_t ctrl; + + void *dev_priv; } pitf_t; +extern void pitf_set_pit_const(void *data, uint64_t pit_const); + +extern void pitf_handler(int set, uint16_t base, int size, void *priv); + +extern void pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv)); + +extern void pitf_ctr_set_using_timer(void *data, int counter_id, int using_timer); + +extern void pitf_ctr_set_gate(void *data, int counter_id, int gate); + +extern void pitf_ctr_clock(void *data, int counter_id); + extern uint8_t pitf_read_reg(void *priv, uint8_t reg); extern const pit_intf_t pit_fast_intf; diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 0d5b17a3c..5b36bab7e 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -30,7 +30,25 @@ #endif /* String ID numbers. */ -#include <86box/language.h> +enum { + STRING_MOUSE_CAPTURE, /* "Click to capture mouse" */ + STRING_MOUSE_RELEASE, /* "Press F8+F12/Ctrl+End to release mouse" */ + STRING_MOUSE_RELEASE_MMB, /* "Press F8+F12/Ctrl+End or middle button to release mouse" */ + STRING_INVALID_CONFIG, /* "Invalid configuration" */ + STRING_NO_ST506_ESDI_CDROM, /* "MFM/RLL or ESDI CD-ROM drives never existed" */ + STRING_NET_ERROR, /* "Failed to initialize network driver" */ + STRING_NET_ERROR_DESC, /* "The network configuration will be switched..." */ + STRING_PCAP_ERROR_NO_DEVICES, /* "No PCap devices found" */ + STRING_PCAP_ERROR_INVALID_DEVICE, /* "Invalid PCap device" */ + STRING_PCAP_ERROR_DESC, /* "Make sure libpcap is installed..." */ + STRING_GHOSTSCRIPT_ERROR_TITLE, /* "Unable to initialize Ghostscript" */ + STRING_GHOSTSCRIPT_ERROR_DESC, /* "gsdll32.dll/gsdll64.dll/libgs is required..." */ + STRING_HW_NOT_AVAILABLE_TITLE, /* "Hardware not available" */ + STRING_HW_NOT_AVAILABLE_MACHINE, /* "Machine \"%hs\" is not available..." */ + STRING_HW_NOT_AVAILABLE_VIDEO, /* "Video card \"%hs\" is not available..." */ + STRING_HW_NOT_AVAILABLE_VIDEO2, /* "Video card #2 \"%hs\" is not available..." */ + STRING_MONITOR_SLEEP /* "Monitor in sleep mode" */ +}; /* The Win32 API uses _wcsicmp. */ #ifdef _WIN32 @@ -107,14 +125,12 @@ 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 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); @@ -130,28 +146,19 @@ 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(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); +extern void plat_set_thread_name(void *thread, const char *name); /* Resource management. */ -extern void set_language(uint32_t id); extern wchar_t *plat_get_string(int id); /* Emulator start/stop support functions. */ @@ -183,17 +190,11 @@ extern void ioctl_close(uint8_t id); /* Other stuff. */ 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); -#ifdef MTR_ENABLED -extern void init_trace(void); -extern void shutdown_trace(void); -#endif - #ifdef __cplusplus } #endif diff --git a/src/include/86box/plat_netsocket.h b/src/include/86box/plat_netsocket.h new file mode 100644 index 000000000..c994ef9b9 --- /dev/null +++ b/src/include/86box/plat_netsocket.h @@ -0,0 +1,23 @@ +#ifndef _WIN32 +# define SOCKET int +#else +# include +# include +#endif + +enum net_socket_types { + /* Only TCP is supported for now. */ + NET_SOCKET_TCP +}; + +SOCKET plat_netsocket_create(int type); +SOCKET plat_netsocket_create_server(int type, unsigned short port); +void plat_netsocket_close(SOCKET socket); + +SOCKET plat_netsocket_accept(SOCKET socket); +int plat_netsocket_connected(SOCKET socket); /* Returns -1 on trouble. */ +int plat_netsocket_connect(SOCKET socket, const char *hostname, unsigned short port); + +/* Returns 0 in case of inability to send. -1 in case of errors. */ +int plat_netsocket_send(SOCKET socket, const unsigned char *data, unsigned int size, int *wouldblock); +int plat_netsocket_receive(SOCKET socket, unsigned char *data, unsigned int size, int *wouldblock); diff --git a/src/include/86box/printer.h b/src/include/86box/printer.h index eb6eb4a75..b576fbf27 100644 --- a/src/include/86box/printer.h +++ b/src/include/86box/printer.h @@ -46,7 +46,8 @@ #ifndef PRINTER_H #define PRINTER_H -#define FONT_FILE_DOTMATRIX "dotmatrix.ttf" +#define FONT_FILE_DOTMATRIX "dotmatrix.otf" +#define FONT_FILE_DOTMATRIX_ITALIC "dotmatrix_italic.otf" #define FONT_FILE_ROMAN "roman.ttf" #define FONT_FILE_SANSSERIF "sansserif.ttf" diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h deleted file mode 100644 index 20067aa40..000000000 --- a/src/include/86box/resource.h +++ /dev/null @@ -1,524 +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. - * - * Windows resource defines. - * - * - * - * 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 2021-2022 Jasmine Iwanek. - */ - -#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 */ - -/* Static text label IDs. */ - -/* DLG_SND_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: */ - -/* DLG_SPECIFY_DIM */ -#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: */ - -/* DLG_CFG_VIDEO */ -#define IDT_VIDEO 1715 /* Video: */ -#define IDT_VIDEO_2 1716 /* Video 2: */ - -/* DLG_CFG_INPUT */ -#define IDT_MOUSE 1717 /* Mouse: */ -#define IDT_JOYSTICK 1718 /* Joystick: */ - -/* DLG_CFG_SOUND */ -#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 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 1732 /* COM1 Device: */ -#define IDT_COM2 1733 /* COM1 Device: */ -#define IDT_COM3 1734 /* COM1 Device: */ -#define IDT_COM4 1735 /* COM1 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 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 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 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 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 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 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 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_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 -#endif -#define IDC_CHECK_SOFTFLOAT 1018 -#define IDC_MEMTEXT 1019 -#define IDC_MEMSPIN 1020 -#define IDC_TEXT_MB IDT_MB - -#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_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_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 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 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 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 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 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 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 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 1210 /* sound gain dialog */ - -#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 - -/* For the DeviceConfig code, re-do later. */ -#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 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 -#endif -#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 -#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_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_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_MEDIA 40087 -#define IDM_DOCS 40088 - -#define IDM_DISCORD 40090 - -#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_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_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 - -/* 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 -#endif - -#endif /*WIN_RESOURCE_H*/ diff --git a/src/include/86box/scsi.h b/src/include/86box/scsi.h index 376ac79b9..32ad1f912 100644 --- a/src/include/86box/scsi.h +++ b/src/include/86box/scsi.h @@ -22,12 +22,14 @@ #define EMU_SCSI_H /* Configuration. */ -#define SCSI_BUS_MAX 4 /* currently we support up to 4 controllers */ +#define SCSI_CARD_MAX 4 +#define SCSI_BUS_MAX 9 /* currently we support up to 9 controllers: + up to 1 on-board + up to 4x pas plus/16 + up to 4 scsi controllers */ -#define SCSI_ID_MAX 16 /* 16 on wide buses */ -#define SCSI_LUN_MAX 8 /* always 8 */ +#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_current[SCSI_CARD_MAX]; extern int scsi_card_available(int card); #ifdef EMU_DEVICE_H diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 09f9ee2d9..64d3bc853 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -173,8 +173,8 @@ #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_SONY 0x0000000000000100LL +#define GPMODEP_CDROM_AUDIO_PAGE_SONY 0x0000000000000200LL #define GPMODEP_CDROM_PAGE 0x0000000000002000LL #define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL #define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL @@ -308,7 +308,7 @@ #define BUS_REQ 0x20 #define BUS_BSY 0x40 #define BUS_RST 0x80 -#define BUS_ACK 0x200 +#define BUS_ACK 0x100 #define BUS_ATN 0x200 #define BUS_ARB 0x8000 #define BUS_SETDATA(val) ((uint32_t) val << 16) diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index ecf5660ef..8baa4f9d8 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -6,9 +6,8 @@ * * 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 chip made by NCR + * and used in various controllers. * * * @@ -17,21 +16,131 @@ * Fred N. van Kempen, * * Copyright 2017-2018 Sarah Walker. - * Copyright 2017-2018 TheCollector1995. * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2017-2024 TheCollector1995. */ #ifndef SCSI_NCR5380_H #define SCSI_NCR5380_H +#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 MODE_ARBITRATE 0x01 +#define MODE_DMA 0x02 +#define MODE_MONITOR_BUSY 0x04 +#define MODE_ENA_EOP_INT 0x08 + +#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 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_INITIATOR_RECEIVE 2 + +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 irq_state; + + uint8_t command[20]; + uint8_t msgout[4]; + uint8_t bus; + + int msgout_pos; + int is_msgout; + + 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; + + int irq; + + double period; + + void *priv; + void (*dma_mode_ext)(void *priv, void *ext_priv); + int (*dma_send_ext)(void *priv, void *ext_priv); + int (*dma_initiator_receive_ext)(void *priv, void *ext_priv); + void (*timer)(void *ext_priv, double period); +} ncr_t; + +extern int ncr5380_cmd_len[8]; + +extern void ncr5380_irq(ncr_t *ncr, int set_irq); +extern void ncr5380_set_irq(ncr_t *ncr, int irq); +extern uint32_t ncr5380_get_bus_host(ncr_t *ncr); +extern void ncr5380_bus_read(ncr_t *ncr); +extern void ncr5380_bus_update(ncr_t *ncr, int bus); +extern void ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr); +extern uint8_t ncr5380_read(uint16_t port, ncr_t *ncr); + +#ifdef EMU_DEVICE_H extern const device_t scsi_lcs6821n_device; +extern const device_t scsi_pas_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_t228_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 #endif /*SCSI_NCR5380_H*/ diff --git a/src/include/86box/scsi_pcscsi.h b/src/include/86box/scsi_pcscsi.h index 0ce353d33..3acee78f9 100644 --- a/src/include/86box/scsi_pcscsi.h +++ b/src/include/86box/scsi_pcscsi.h @@ -26,6 +26,6 @@ #define SCSI_PCSCSI_H extern const device_t dc390_pci_device; -extern const device_t ncr53c90_mca_device; +extern const device_t ncr53c90a_mca_device; #endif /*SCSI_BUSLOGIC_H*/ diff --git a/src/include/86box/scsi_t128.h b/src/include/86box/scsi_t128.h new file mode 100644 index 000000000..65148a5d1 --- /dev/null +++ b/src/include/86box/scsi_t128.h @@ -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. + * + * Implementation of the NCR 53c400 series of SCSI Host Adapters + * made by NCR. These controllers were designed for the ISA and MCA bus. + * + * Authors: Sarah Walker, + * TheCollector1995, + * Fred N. van Kempen, + * + * Copyright 2017-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + * Copyright 2017-2024 TheCollector1995. + */ + +#ifndef SCSI_T128_H +#define SCSI_T128_H + +typedef struct t128_t { + ncr_t ncr; + rom_t bios_rom; + mem_mapping_t mapping; + + 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; + + uint32_t rom_addr; + + int bios_enabled; + uint8_t pos_regs[8]; + + pc_timer_t timer; +} t128_t; + +extern void t128_write(uint32_t addr, uint8_t val, void *priv); +extern uint8_t t128_read(uint32_t addr, void *priv); + +extern void t128_callback(void *priv); + +#endif /*SCSI_T128_H*/ diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index bd7e85a91..c2312f562 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -92,6 +92,7 @@ typedef struct serial_s { typedef struct serial_device_s { void (*rcr_callback)(struct serial_s *serial, void *priv); + void (*dtr_callback)(struct serial_s *serial, int status, 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); @@ -112,6 +113,12 @@ extern serial_t *serial_attach_ex(int port, void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t data_bits), void *priv); +extern serial_t *serial_attach_ex_2(int port, + void (*rcr_callback)(struct serial_s *serial, void *priv), + void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data), + void (*dtr_callback)(struct serial_s *serial, int status, void *priv), + void *priv); + #define serial_attach(port, rcr_callback, dev_write, priv) \ serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv); @@ -124,11 +131,13 @@ 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 uint8_t serial_read(uint16_t addr, void *priv); 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 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 void serial_set_ri(serial_t *dev, uint8_t enabled); +extern int serial_get_ri(serial_t *dev); extern const device_t ns8250_device; extern const device_t ns8250_pcjr_device; diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 6ec9eceb9..d5fc88fb4 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -19,17 +19,21 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); extern const device_t acc3221_device; +extern const device_t ali5105_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 fdc37c661_ide_device; +extern const device_t fdc37c661_ide_sec_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 fdc37c665_ide_sec_device; extern const device_t fdc37c666_device; extern const device_t fdc37c67x_device; extern const device_t fdc37c669_device; @@ -39,6 +43,8 @@ extern const device_t fdc37c931apm_compaq_device; extern const device_t fdc37c932fr_device; extern const device_t fdc37c932qf_device; extern const device_t fdc37c935_device; +extern const device_t fdc37c935_370_device; +extern const device_t fdc37c935_no_nvr_device; extern const device_t fdc37m60x_device; extern const device_t fdc37m60x_370_device; extern const device_t it8661f_device; @@ -71,6 +77,12 @@ extern const device_t ps1_m2133_sio; #if defined(DEV_BRANCH) && defined(USE_SIO_DETECT) extern const device_t sio_detect_device; #endif +extern const device_t um8663af_device; +extern const device_t um8663af_ide_device; +extern const device_t um8663af_sec_device; +extern const device_t um8663bf_device; +extern const device_t um8663bf_ide_device; +extern const device_t um8663bf_sec_device; extern const device_t um8669f_device; extern const device_t um8669f_ide_device; extern const device_t um8669f_ide_sec_device; diff --git a/src/include/86box/sis_55xx.h b/src/include/86box/sis_55xx.h new file mode 100644 index 000000000..99ccf7dfa --- /dev/null +++ b/src/include/86box/sis_55xx.h @@ -0,0 +1,78 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 implementation of the SiS 55xx Pentium + * PCI/ISA Chipsets. + * + * Authors: Miran Grca, + * + * Copyright 2019-2020 Miran Grca. + */ +#ifndef EMU_SIS_55XX_H +#define EMU_SIS_55XX_H + +typedef struct +{ + uint8_t sb_pci_slot; + uint8_t ide_bits_1_3_writable; + uint8_t usb_enabled; + + uint8_t *pmu_regs; + + sff8038i_t *bm[2]; + acpi_t *acpi; +} sis_55xx_common_t; + +extern void sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5511_host_to_pci_read(int addr, void *priv); +extern void sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5571_host_to_pci_read(int addr, void *priv); +extern void sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5581_host_to_pci_read(int addr, void *priv); +extern void sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5591_host_to_pci_read(int addr, void *priv); +extern void sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5600_host_to_pci_read(int addr, void *priv); + +extern void sis_5513_pci_to_isa_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5513_pci_to_isa_read(int addr, void *priv); +extern void sis_5513_ide_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5513_ide_read(int addr, void *priv); +extern void sis_5572_usb_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5572_usb_read(int addr, void *priv); +extern void sis_5595_pmu_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5595_pmu_read(int addr, void *priv); + +extern const device_t sis_5511_h2p_device; +extern const device_t sis_5571_h2p_device; +extern const device_t sis_5581_h2p_device; +extern const device_t sis_5591_h2p_device; +extern const device_t sis_5600_h2p_device; + +extern const device_t sis_5513_p2i_device; +extern const device_t sis_5572_p2i_device; +extern const device_t sis_5582_p2i_device; +extern const device_t sis_5595_1997_p2i_device; +extern const device_t sis_5595_p2i_device; + +extern const device_t sis_5513_ide_device; +extern const device_t sis_5572_ide_device; +extern const device_t sis_5582_ide_device; +extern const device_t sis_5591_5600_ide_device; + +extern const device_t sis_5572_usb_device; +extern const device_t sis_5582_usb_device; +extern const device_t sis_5595_usb_device; + +extern const device_t sis_5595_pmu_device; +extern const device_t sis_5595_1997_pmu_device; + +extern const device_t sis_55xx_common_device; + + +#endif /*EMU_SIS_55XX_H*/ diff --git a/src/include/86box/smbus.h b/src/include/86box/smbus.h index 340d1d00e..2c06c3d4e 100644 --- a/src/include/86box/smbus.h +++ b/src/include/86box/smbus.h @@ -15,8 +15,8 @@ * Copyright 2020 RichardG. */ -#ifndef EMU_SMBUS_PIIX4_H -#define EMU_SMBUS_PIIX4_H +#ifndef EMU_SMBUS_H +#define EMU_SMBUS_H #define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 #define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) @@ -24,6 +24,9 @@ #define SMBUS_ALI7101_BLOCK_DATA_SIZE 32 #define SMBUS_ALI7101_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) +#define SMBUS_SIS5595_BLOCK_DATA_SIZE 32 +#define SMBUS_SIS5595_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) + enum { SMBUS_PIIX4 = 0, SMBUS_VIA = 1 @@ -63,16 +66,47 @@ typedef struct smbus_ali7101_t { 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); +typedef struct smbus_sis5595_t { + uint32_t local; + uint16_t stat; + uint16_t next_stat; + uint16_t ctl; + uint8_t cmd; + uint8_t addr; + uint8_t saved_addr; + uint8_t block_ptr; + uint8_t count; + uint8_t data0; + uint8_t data1; + uint8_t alias; + uint8_t reg_ff; + uint8_t index; + uint8_t irq_enable; + uint8_t irq_state; + uint8_t data[SMBUS_SIS5595_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; +} smbus_sis5595_t; -extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); +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_sis5595_irq_enable(void *priv, uint8_t enable); + +extern uint8_t smbus_sis5595_read_index(void *priv); +extern uint8_t smbus_sis5595_read_data(void *priv); +extern void smbus_sis5595_write_index(void *priv, uint8_t val); +extern void smbus_sis5595_write_data(void *priv, uint8_t val); #ifdef EMU_DEVICE_H extern const device_t piix4_smbus_device; extern const device_t via_smbus_device; extern const device_t ali7101_smbus_device; + +extern const device_t sis5595_smbus_device; #endif -#endif /*EMU_SMBUS_PIIX4_H*/ +#endif /*EMU_SMBUS_H*/ diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index 6bdd2bf40..319f9bf24 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -61,6 +61,9 @@ typedef struct ad1848_t { int adpcm_data; int adpcm_pos; + uint8_t dma_ff; + uint32_t dma_data; + pc_timer_t timer_count; uint64_t timer_latch; diff --git a/src/include/86box/snd_emu8k.h b/src/include/86box/snd_emu8k.h index 090ab662a..4bad23b97 100644 --- a/src/include/86box/snd_emu8k.h +++ b/src/include/86box/snd_emu8k.h @@ -390,12 +390,12 @@ typedef struct emu8k_t { int16_t out_r; emu8k_chorus_eng_t chorus_engine; - int32_t chorus_in_buffer[SOUNDBUFLEN]; + int32_t chorus_in_buffer[WTBUFLEN]; emu8k_reverb_eng_t reverb_engine; - int32_t reverb_in_buffer[SOUNDBUFLEN]; + int32_t reverb_in_buffer[WTBUFLEN]; int pos; - int32_t buffer[SOUNDBUFLEN * 2]; + int32_t buffer[WTBUFLEN * 2]; uint16_t addr; } emu8k_t; @@ -406,6 +406,8 @@ void emu8k_close(emu8k_t *emu8k); void emu8k_update(emu8k_t *emu8k); +#define EMU8K_ROM_PATH "roms/sound/creative/awe32.raw" + /* Section E - Introduction to the EMU8000 Chip diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 0d89589c4..441e2a119 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -22,7 +22,8 @@ enum fm_type { FM_YMF262 = 1, /* OPL3 */ FM_YMF289B = 2, /* OPL3-L */ FM_YMF278B = 3, /* OPL 4 */ - FM_MAX = 4 + FM_ESFM = 4, /* ESFM */ + FM_MAX = 5 }; enum fm_driver { @@ -45,6 +46,7 @@ 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; +extern const fm_drv_t esfmu_opl_drv; #ifdef EMU_DEVICE_H extern const device_t ym3812_nuked_device; @@ -54,6 +56,8 @@ 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; + +extern const device_t esfm_esfmu_device; #endif #endif /*SOUND_OPL_H*/ diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index f433dd107..b26c5f06e 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -126,6 +126,43 @@ typedef struct sb_ct1745_mixer_t { int output_filter; /* for clones */ } sb_ct1745_mixer_t; +/* ESS AudioDrive */ +typedef struct ess_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_l; + double mic_r; + double auxb_l; + double auxb_r; + double speaker; + /*see sb_ct1745_mixer for values for input selector*/ + int32_t input_selector; + /* extra values for input selector */ + #define INPUT_MIXER_L 128 + #define INPUT_MIXER_R 256 + + int input_filter; + int in_filter_freq; + int output_filter; + + int stereo; + int stereo_isleft; + + uint8_t index; + uint8_t regs[256]; + + uint8_t ess_id_str[4]; + uint8_t ess_id_str_pos; +} ess_mixer_t; + typedef struct sb_t { uint8_t cms_enabled; uint8_t opl_enabled; @@ -138,12 +175,12 @@ typedef struct sb_t { sb_ct1335_mixer_t mixer_sb2; sb_ct1345_mixer_t mixer_sbpro; sb_ct1745_mixer_t mixer_sb16; + ess_mixer_t mixer_ess; }; mpu_t *mpu; emu8k_t emu8k; void *gameport; - int pos; int pnp; uint8_t pos_regs[8]; @@ -164,7 +201,12 @@ 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); +extern void sb_ess_mixer_write(uint16_t addr, uint8_t val, void *priv); +extern uint8_t sb_ess_mixer_read(uint16_t addr, void *priv); +extern void sb_ess_mixer_reset(sb_t *sb); + extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *priv); +extern void sb_get_music_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); diff --git a/src/include/86box/snd_sb_dsp.h b/src/include/86box/snd_sb_dsp.h index ecabe426d..c179fd197 100644 --- a/src/include/86box/snd_sb_dsp.h +++ b/src/include/86box/snd_sb_dsp.h @@ -1,10 +1,19 @@ #ifndef SOUND_SND_SB_DSP_H #define SOUND_SND_SB_DSP_H +#include <86box/fifo.h> + /*Sound Blaster Clones, for quirks*/ -#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/ -#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /*Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone*/ -#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/ +#define SB_SUBTYPE_DEFAULT 0 /* Handle as a Creative card */ +#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /* Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone */ +#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /* Aztech Sound Galaxy Nova 16 Extra / + Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone */ +#define SB_SUBTYPE_ESS_ES688 3 /* ESS Technology ES688 */ +#define SB_SUBTYPE_ESS_ES1688 4 /* ESS Technology ES1688 */ + +/* ESS-related */ +#define IS_ESS(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_ESS_ES688) /* Check for future ESS cards here */ +#define IS_NOT_ESS(dsp) ((dsp)->sb_subtype < SB_SUBTYPE_ESS_ES688) /* Check for future ESS cards here */ /* 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 */ @@ -45,6 +54,10 @@ typedef struct sb_dsp_t { void *dma_priv; uint8_t sb_read_data[256]; + + uint8_t dma_ff; + int dma_data; + int sb_read_wp; int sb_read_rp; int sb_speaker; @@ -97,6 +110,8 @@ typedef struct sb_dsp_t { int sb_irqm16; int sb_irqm401; + uint8_t sb_has_real_opl; + uint8_t sb_asp_regs[256]; uint8_t sb_asp_mode; @@ -108,6 +123,8 @@ typedef struct sb_dsp_t { int sbenable; int sb_enable_i; + int state; + pc_timer_t output_timer; pc_timer_t input_timer; @@ -123,6 +140,8 @@ typedef struct sb_dsp_t { pc_timer_t wb_timer; int wb_full; + pc_timer_t irq_timer; + int busy_count; int record_pos_read; @@ -133,6 +152,28 @@ typedef struct sb_dsp_t { uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */ + uint8_t ess_regs[256]; /* ESS registers. */ + uint8_t ess_playback_mode; + uint8_t ess_extended_mode; + uint8_t ess_reload_len; + uint32_t ess_dma_counter; + + /* IRQ status flags (0x22C) */ + uint8_t ess_irq_generic; + uint8_t ess_irq_dmactr; + + /* ESPCM */ + fifo64_t *espcm_fifo; + uint8_t espcm_fifo_reset; + uint8_t espcm_mode; /* see ESPCM in "NON-PCM SAMPLE FORMATS" deflist in snd_sb_dsp.c */ + uint8_t espcm_sample_idx; + uint8_t espcm_range; + uint8_t espcm_byte_buffer[4]; + uint8_t espcm_code_buffer[19]; /* used for ESPCM_3 and for ESPCM_4 recording */ + int8_t espcm_sample_buffer[19]; /* used for ESPCM_4 recording */ + uint8_t espcm_table_index; /* used for ESPCM_3 */ + uint8_t espcm_last_value; /* used for ESPCM_3 */ + mpu_t *mpu; } sb_dsp_t; @@ -158,6 +199,8 @@ extern void sb_dsp_speed_changed(sb_dsp_t *dsp); extern void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); +extern void sb_dsp_set_real_opl(sb_dsp_t *dsp, uint8_t has_real_opl); + extern void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); extern void sb_dsp_update(sb_dsp_t *dsp); diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 60628ece8..9896b5422 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -33,9 +33,15 @@ extern int sound_gain; #define SOUND_FREQ FREQ_48000 #define SOUNDBUFLEN (SOUND_FREQ / 50) +#define MUSIC_FREQ FREQ_49716 +#define MUSICBUFLEN (MUSIC_FREQ / 36) + #define CD_FREQ FREQ_44100 #define CD_BUFLEN (CD_FREQ / 10) +#define WT_FREQ FREQ_44100 +#define WTBUFLEN (MUSIC_FREQ / 45) + enum { SOUND_NONE = 0, SOUND_INTERNAL @@ -47,12 +53,24 @@ extern int speakval; extern int speakon; extern int sound_pos_global; + +extern int music_pos_global; +extern int wavetable_pos_global; + extern int sound_card_current[SOUND_CARD_MAX]; extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *priv), void *priv); +extern void music_add_handler(void (*get_buffer)(int32_t *buffer, + int len, void *priv), + void *priv); + +extern void wavetable_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); @@ -85,8 +103,10 @@ 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 givealbuffer(const void *buf); +extern void givealbuffer_music(const void *buf); +extern void givealbuffer_wt(const void *buf); +extern void givealbuffer_cd(const 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); @@ -103,31 +123,16 @@ extern const device_t acermagic_s20_device; extern const device_t mirosound_pcm10_device; extern const device_t azt1605_device; -/* Ensoniq AudioPCI */ -extern const device_t es1371_device; -extern const device_t es1371_onboard_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; /* Creative Labs Game Blaster */ extern const device_t cms_device; -/* Gravis UltraSound and UltraSound Max */ -extern const device_t gus_device; - -# if defined(DEV_BRANCH) && defined(USE_PAS16) -/* Pro Audio Spectrum 16 */ -extern const device_t pas16_device; -# endif - -/* IBM PS/1 Audio Card */ -extern const device_t ps1snd_device; - -/* Tandy PSSJ */ -extern const device_t pssj_device; -extern const device_t pssj_isa_device; - -/* Tandy PSG */ -extern const device_t tndy_device; - /* Creative Labs Sound Blaster */ extern const device_t sb_1_device; extern const device_t sb_15_device; @@ -154,13 +159,6 @@ extern const device_t sb_awe64_value_device; extern const device_t sb_awe64_device; extern const device_t sb_awe64_gold_device; -/* Innovation SSI-2001 */ -extern const device_t ssi2001_device; - -/* Windows Sound System */ -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; @@ -168,12 +166,45 @@ 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; +/* ESS Technology */ +extern const device_t ess_688_device; +extern const device_t ess_ess0100_pnp_device; +extern const device_t ess_1688_device; +extern const device_t ess_ess0102_pnp_device; +extern const device_t ess_ess0968_pnp_device; +extern const device_t ess_soundpiper_16_mca_device; +extern const device_t ess_soundpiper_32_mca_device; +extern const device_t ess_chipchat_16_mca_device; + +/* Ensoniq AudioPCI */ +extern const device_t es1371_device; +extern const device_t es1371_onboard_device; + +/* Gravis UltraSound and UltraSound Max */ +extern const device_t gus_device; + +/* IBM PS/1 Audio Card */ +extern const device_t ps1snd_device; + +/* Innovation SSI-2001 */ +extern const device_t ssi2001_device; + +/* Pro Audio Spectrum Plus, 16, and 16D */ +extern const device_t pasplus_device; +extern const device_t pas16_device; +extern const device_t pas16d_device; + +/* Tandy PSSJ */ +extern const device_t pssj_device; +extern const device_t pssj_isa_device; + +/* Tandy PSG */ +extern const device_t tndy_device; + +/* Windows Sound System */ +extern const device_t wss_device; +extern const device_t ncr_business_audio_device; + #endif #endif /*EMU_SOUND_H*/ diff --git a/src/include/86box/thread.h b/src/include/86box/thread.h index 4d5584787..a71d03913 100644 --- a/src/include/86box/thread.h +++ b/src/include/86box/thread.h @@ -28,7 +28,7 @@ extern "C" { # define event_t plat_event_t # define mutex_t plat_mutex_t -# define thread_create plat_thread_create +# define thread_create_named plat_thread_create_named # define thread_wait plat_thread_wait # define thread_create_event plat_thread_create_event # define thread_set_event plat_thread_set_event @@ -48,7 +48,8 @@ typedef void thread_t; typedef void event_t; typedef void mutex_t; -extern thread_t *thread_create(void (*thread_func)(void *param), void *param); +#define thread_create(thread_func, param) thread_create_named((thread_func), (param), #thread_func) +extern thread_t *thread_create_named(void (*thread_func)(void *param), void *param, const char *name); extern int thread_wait(thread_t *arg); extern event_t *thread_create_event(void); extern void thread_set_event(event_t *arg); diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 4ade8aab0..91f903a0f 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -43,7 +43,7 @@ typedef struct pc_timer_t { ts_t ts; #endif int flags; /* The flags are defined above. */ - int pad; + int in_callback; double period; /* This is used for large period timers to count the microseconds and split the period. */ diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 9698f896c..c12eb73a0 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -42,9 +42,6 @@ extern "C" { 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); /* Status Bar functions. */ #define SB_ICON_WIDTH 24 @@ -60,16 +57,13 @@ extern void ui_check_menu_item(int id, int checked); #define SB_TEXT 0x90 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); diff --git a/src/include/86box/unittester.h b/src/include/86box/unittester.h new file mode 100644 index 000000000..00abed3ff --- /dev/null +++ b/src/include/86box/unittester.h @@ -0,0 +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. + * + * This file is part of the 86Box distribution. + * + * Debug device for assisting in unit testing. + * See doc/specifications/86box-unit-tester.md for more info. + * If modifying the protocol, you MUST modify the specification + * and increment the version number. + * + * + * + * Authors: GreaseMonkey, + * + * Copyright 2024 GreaseMonkey. + */ + +#ifndef UNITTESTER_H +#define UNITTESTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ +extern const device_t unittester_device; + +/* Functions. */ + +#ifdef __cplusplus +} +#endif + +#endif /*UNITTESTER_H*/ diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 49b4cb37d..fab504bbe 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -33,6 +33,8 @@ typedef struct hwcursor8514_t { } hwcursor8514_t; typedef struct ibm8514_t { + rom_t bios_rom; + rom_t bios_rom2; hwcursor8514_t hwcursor; hwcursor8514_t hwcursor_latch; uint8_t pos_regs[8]; @@ -60,20 +62,24 @@ typedef struct ibm8514_t { int dac_b; int internal_pitch; int hwcursor_on; + int modechange; + + uint64_t dispontime; + uint64_t dispofftime; struct { uint16_t subsys_cntl; uint16_t setup_md; uint16_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 destx; + int16_t desty; int16_t desty_axstp; int16_t destx_distp; int16_t err_term; int16_t maj_axis_pcnt; + int16_t maj_axis_pcnt_no_limit; uint16_t cmd; uint16_t cmd_back; uint16_t short_stroke; @@ -100,7 +106,9 @@ typedef struct ibm8514_t { int sys_cnt2; int temp_cnt; int16_t cx; + int16_t cx_back; int16_t cy; + int16_t oldcx; int16_t oldcy; int16_t sx; int16_t sy; @@ -133,19 +141,29 @@ typedef struct ibm8514_t { int fill_state; int xdir; int ydir; + int linedraw; uint32_t ge_offset; } accel; uint16_t test; int vendor_mode[2]; + int h_blankstart; + int h_blank_end_val; + int hblankstart; + int hblank_end_val; + int hblankend; + int hblank_ext; + int hblank_sub; + int v_total_reg; int v_total; int dispend; + int v_sync_start; int v_syncstart; int split; int h_disp; - int h_disp_old; int h_total; + int h_sync_width; int h_disp_time; int rowoffset; int dispon; @@ -172,20 +190,17 @@ typedef struct ibm8514_t { uint8_t data_available; uint8_t data_available2; - uint8_t scanmodulos; uint8_t rowcount; + int hsync_start; + int hsync_width; int htotal; int hdisp; - int vtadj; - int vdadj; - int vsadj; + int hdisped; int sc; - int vtb; - int vdb; - int vsb; int vsyncstart; int vsyncwidth; int vtotal; + int v_disp; int vdisp; int disp_cntl; int interlace; @@ -201,6 +216,7 @@ typedef struct ibm8514_t { int pitch; int ext_pitch; int ext_crt_pitch; + int extensions; } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h new file mode 100644 index 000000000..7b5862f35 --- /dev/null +++ b/src/include/86box/vid_ati_mach8.h @@ -0,0 +1,162 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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-2024 TheCollector1995. + */ +#ifndef VIDEO_ATI_MACH8_H +#define VIDEO_ATI_MACH8_H + +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_lo_reg; + 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; + uint16_t shadow_cntl; + int ext_on[2]; + int compat_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; + uint16_t test2; + 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; + 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; + int16_t bleft, bright, btop, bbottom; + 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; + +#endif /*VIDEO_ATI_MACH8_H*/ diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index f49fc73cc..5b6a2dea2 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -66,6 +66,7 @@ typedef struct cga_t { int composite; int snow_enabled; int rgb_type; + int double_type; } cga_t; void cga_init(cga_t *cga); diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 180803c8a..0bccd607e 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -56,6 +56,8 @@ typedef struct ega_t { uint8_t *vram; + uint16_t light_pen; + int vidclock; int fast; int extvram; @@ -109,6 +111,8 @@ typedef struct ega_t { int bpp; int index; int remap_required; + int actual_type; + int chipset; uint32_t charseta; uint32_t charsetb; @@ -143,7 +147,7 @@ typedef struct ega_t { extern const device_t ega_device; extern const device_t cpqega_device; extern const device_t sega_device; -extern const device_t atiega_device; +extern const device_t atiega800p_device; extern const device_t iskra_ega_device; extern const device_t et2000_device; #endif diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index f725996d8..9eecebf2c 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -29,6 +29,7 @@ # define FLAG_ATI 128 # define FLAG_S3_911_16BIT 256 # define FLAG_512K_MASK 512 +# define FLAG_NO_SHIFT3 1024 /* Needed for Bochs VBE. */ struct monitor_t; typedef struct hwcursor_t { @@ -118,16 +119,19 @@ typedef struct svga_t { 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; + int hblank_end_mask; + int hblank_sub; + int packed_4bpp; + int ps_bit_bug; + int ati_4color; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -164,8 +168,12 @@ typedef struct svga_t { latch_t latch; pc_timer_t timer; + pc_timer_t timer8514; double clock; + double clock8514; + + double multiplier; hwcursor_t hwcursor; hwcursor_t hwcursor_latch; @@ -231,6 +239,7 @@ typedef struct svga_t { uint8_t dac_status; uint8_t dpms; uint8_t dpms_ui; + uint8_t color_2bpp; uint8_t ksc5601_sbyte_mask; uint8_t ksc5601_udc_area_msb[2]; @@ -246,6 +255,11 @@ typedef struct svga_t { addresses are shifted to match*/ int packed_chain4; + /*Disable 8bpp blink mode - some cards support it, some don't, it's a weird mode + If mode 13h appears in a reddish-brown background (0x88) with dark green text (0x8F), + you should set this flag when entering that mode*/ + int disable_blink; + /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ int force_dword_mode; @@ -263,22 +277,39 @@ typedef struct svga_t { /* Pointer to monitor */ monitor_t *monitor; + /* Enable LUT mapping of >= 24 bpp modes. */ + int lut_map; + + /* Override the horizontal blanking stuff. */ + int hoverride; + + /* Return a 32 bpp color from a 15/16 bpp color. */ + uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp); + void * dev8514; + void * ext8514; void * xga; } svga_t; extern int vga_on; -extern void ibm8514_poll(void *priv, svga_t *svga); +extern void ibm8514_poll(void *priv); 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_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_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); +#ifdef ATI_8514_ULTRA +extern void ati8514_recalctimings(svga_t *svga); +extern uint8_t ati8514_mca_read(int port, void *priv); +extern void ati8514_mca_write(int port, uint8_t val, void *priv); +extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); +#endif + extern void xga_poll(void *priv, svga_t *svga); extern void xga_recalctimings(svga_t *svga); @@ -329,6 +360,8 @@ enum { RAMDAC_8BIT }; +uint32_t svga_lookup_lut_ram(svga_t* svga, uint32_t val); + /* 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 *priv, svga_t *svga); @@ -388,11 +421,13 @@ extern float stg_getclock(int clock, void *priv); 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 *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); +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 uint32_t tvp3026_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp); +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); +extern void tvp3026_gpio(uint8_t (*read)(uint8_t cntl, void *priv), void (*write)(uint8_t cntl, uint8_t data, void *priv), void *cb_priv, void *priv); # ifdef EMU_DEVICE_H extern const device_t ati68860_ramdac_device; diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index bc6894ca9..224d96c8e 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -53,6 +53,7 @@ extern void svga_render_4bpp_lowres(svga_t *svga); extern void svga_render_4bpp_highres(svga_t *svga); extern void svga_render_8bpp_lowres(svga_t *svga); extern void svga_render_8bpp_highres(svga_t *svga); +extern void svga_render_8bpp_clone_highres(svga_t *svga); extern void svga_render_8bpp_tseng_lowres(svga_t *svga); extern void svga_render_8bpp_tseng_highres(svga_t *svga); extern void svga_render_8bpp_gs_lowres(svga_t *svga); @@ -74,6 +75,7 @@ extern void svga_render_ABGR8888_highres(svga_t *svga); extern void svga_render_RGBA8888_lowres(svga_t *svga); extern void svga_render_RGBA8888_highres(svga_t *svga); +extern void ibm8514_render_blank(svga_t *svga); extern void ibm8514_render_8bpp(svga_t *svga); extern void ibm8514_render_15bpp(svga_t *svga); extern void ibm8514_render_16bpp(svga_t *svga); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 1858fc246..1c8b61015 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -32,6 +32,9 @@ using atomic_int = std::atomic_int; #define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) #define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) +#define getcolr(color) (((color) >> 16) & 0xFF) +#define getcolg(color) (((color) >> 8) & 0xFF) +#define getcolb(color) ((color) & 0xFF) enum { VID_NONE = 0, @@ -220,7 +223,7 @@ extern void video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, in 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_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); @@ -303,7 +306,7 @@ 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 mach8_vga_isa_device; extern const device_t mach32_isa_device; extern const device_t mach32_vlb_device; extern const device_t mach32_mca_device; @@ -317,9 +320,7 @@ extern const device_t mach64gx_pci_device; extern const device_t mach64vt2_device; /* ATi 18800 */ -# if defined(DEV_BRANCH) && defined(USE_VGAWONDER) extern const device_t ati18800_wonder_device; -# endif extern const device_t ati18800_vga88_device; extern const device_t ati18800_device; @@ -333,6 +334,13 @@ extern const device_t compaq_ati28800_device; extern const device_t ati28800_wonderxl24_device; # endif +/* Bochs */ +extern const device_t bochs_svga_device; + +/* Chips & Technologies */ +extern const device_t chips_69000_device; +extern const device_t chips_69000_onboard_device; + /* Cirrus Logic GD54xx */ extern const device_t gd5401_isa_device; extern const device_t gd5402_isa_device; @@ -345,6 +353,7 @@ extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device; extern const device_t gd5426_vlb_device; extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; +extern const device_t gd5428_vlb_onboard_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; @@ -364,8 +373,9 @@ extern const device_t gd5434_onboard_pci_device; extern const device_t gd5434_vlb_device; extern const device_t gd5434_pci_device; extern const device_t gd5436_pci_device; -extern const device_t gd5440_onboard_pci_device; +extern const device_t gd5436_onboard_pci_device; extern const device_t gd5440_pci_device; +extern const device_t gd5440_onboard_pci_device; extern const device_t gd5446_pci_device; extern const device_t gd5446_stb_pci_device; extern const device_t gd5480_pci_device; @@ -431,12 +441,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) /* Matrox MGA */ extern const device_t millennium_device; extern const device_t mystique_device; extern const device_t mystique_220_device; -# endif +extern const device_t millennium_ii_device; +extern const device_t productiva_g100_device; /* Oak OTI-0x7 */ extern const device_t oti037c_device; @@ -455,6 +465,7 @@ extern const device_t paradise_wd90c11_device; extern const device_t paradise_wd90c30_device; /* Realtek (S)VGA */ +extern const device_t realtek_rtg3105_device; extern const device_t realtek_rtg3106_device; /* S3 9XX/8XX/Vision/Trio */ @@ -475,7 +486,9 @@ extern const device_t s3_bahamas64_vlb_device; extern const device_t s3_bahamas64_pci_device; extern const device_t s3_9fx_vlb_device; extern const device_t s3_9fx_pci_device; +extern const device_t s3_phoenix_trio32_onboard_vlb_device; extern const device_t s3_phoenix_trio32_vlb_device; +extern const device_t s3_phoenix_trio32_onboard_pci_device; extern const device_t s3_phoenix_trio32_pci_device; extern const device_t s3_diamond_stealth_se_vlb_device; extern const device_t s3_diamond_stealth_se_pci_device; @@ -483,8 +496,10 @@ extern const device_t s3_spea_mirage_p64_vlb_device; extern const device_t s3_phoenix_trio64_vlb_device; extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; +extern const device_t s3_stb_powergraph_64_video_vlb_device; extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; +extern const device_t s3_cardex_trio64vplus_pci_device; extern const device_t s3_mirocrystal_20sv_964_vlb_device; extern const device_t s3_mirocrystal_20sv_964_pci_device; extern const device_t s3_mirocrystal_20sd_864_vlb_device; @@ -531,6 +546,7 @@ extern const device_t tgui9440_vlb_device; extern const device_t tgui9440_pci_device; extern const device_t tgui9440_onboard_pci_device; extern const device_t tgui9660_pci_device; +extern const device_t tgui9660_onboard_pci_device; extern const device_t tgui9680_pci_device; /* IBM PS/1 (S)VGA */ @@ -539,6 +555,7 @@ extern const device_t ibm_ps1_2121_device; /* Trident TVGA 8900 */ extern const device_t tvga8900b_device; extern const device_t tvga8900d_device; +extern const device_t tvga8900dr_device; extern const device_t tvga9000b_device; extern const device_t nec_sv9000_device; diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 35f6688ad..5cead7cb0 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -26,50 +26,7 @@ #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) -#endif - -#ifndef WM_DPICHANGED_AFTERPARENT -# 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 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" /* Application-specific window messages. @@ -92,163 +49,4 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); /* The emulator has shut down. */ #define WM_HAS_SHUTDOWN 0x8897 -#ifdef USE_VNC -# define RENDERERS_NUM 5 -#else -# define RENDERERS_NUM 4 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -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; - -#if 0 -extern int status_is_open; -#endif - -extern char openfilestring[512]; -extern WCHAR wopenfilestring[512]; - -extern uint8_t filterindex; - -extern void ResizeWindowByClientArea(HWND hwnd, int width, int height); - -/* Emulator start/stop support functions. */ -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 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_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 LPARAM win_get_string(int id); - -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); - -#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); -#endif -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); - -/* Platform UI support functions. */ -extern int ui_init(int nCmdShow); - -/* Functions in win_about.c: */ -extern void AboutDialogCreate(HWND hwnd); - -/* Functions in win_snd_gain.c: */ -extern void SoundGainDialogCreate(HWND hwnd); - -/* Functions in win_new_floppy.c: */ -extern void NewFloppyDialogCreate(HWND hwnd, int id, int part); - -/* Functions in win_specify_dim.c: */ -extern void SpecifyDimensionsDialogCreate(HWND hwnd); - -/* Functions in win_preferences.c: */ -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); - -/* 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); - -/* Functions in win_toolbar.c */ -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); - -/* Functions in win_media_menu.c */ -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(void); - -#ifdef __cplusplus -} -#endif - #endif /*PLAT_WIN_H*/ diff --git a/src/include/86box/win_opengl.h b/src/include/86box/win_opengl.h deleted file mode 100644 index d354131ef..000000000 --- a/src/include/86box/win_opengl.h +++ /dev/null @@ -1,29 +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. - * - * Header file for OpenGL rendering module - * - * Authors: Teemu Korhonen - * - * Copyright 2021 Teemu Korhonen - */ - -#ifndef WIN_OPENGL_H -#define WIN_OPENGL_H - -#define UNICODE -#include - -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*/ diff --git a/src/include/86box/win_opengl_glslp.h b/src/include/86box/win_opengl_glslp.h deleted file mode 100644 index 6586cd526..000000000 --- a/src/include/86box/win_opengl_glslp.h +++ /dev/null @@ -1,24 +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. - * - * Header file for shader file parser. - * - * Authors: 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(void); - -#endif /*!WIN_OPENGL_GLSLP_H*/ diff --git a/src/include/86box/win_sdl.h b/src/include/86box/win_sdl.h deleted file mode 100644 index 69340e8b6..000000000 --- a/src/include/86box/win_sdl.h +++ /dev/null @@ -1,63 +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 libSDL2 rendering module. - * - * - * - * Authors: Fred N. van Kempen, - * 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: - * - * 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 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); - -#endif /*WIN_SDL_H*/ diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h deleted file mode 100644 index 9a175be24..000000000 --- a/src/include_make/86box/version.h +++ /dev/null @@ -1,49 +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 project version, branding, and external links. - * - * - * - * 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_VERSION "4.1" -#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 1 -#define EMU_VERSION_PATCH 0 - -#define EMU_BUILD_NUM 0 - -#define EMU_VERSION_FULL EMU_VERSION -#define EMU_VERSION_FULL_W EMU_VERSION_W - -#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) -#ifdef RELEASE_BUILD -# define EMU_DOCS_URL "https://86box.readthedocs.io/en/v4.1/" -#else -# define EMU_DOCS_URL "https://86box.readthedocs.io" -#endif -#define EMU_DOCS_URL_W LSTR(EMU_DOCS_URL) diff --git a/src/lpt.c b/src/lpt.c index 5bbf79875..419e5ad3d 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -11,7 +11,10 @@ #include <86box/pic.h> #include <86box/sound.h> #include <86box/prt_devs.h> -#include <86box/net_plip.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/network.h> lpt_port_t lpt_ports[PARALLEL_MAX]; @@ -165,6 +168,15 @@ lpt_read(uint16_t port, void *priv) return ret; } +uint8_t +lpt_read_port(int port, uint16_t reg) +{ + lpt_port_t *dev = &(lpt_ports[port]); + uint8_t ret = lpt_read(reg, dev); + + return ret; +} + uint8_t lpt_read_status(int port) { diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index e88631044..ecc374e66 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -37,6 +37,10 @@ if(LASERXT) target_compile_definitions(mch PRIVATE USE_LASERXT) endif() +if(OLIVETTI) + target_compile_definitions(mch PRIVATE USE_OLIVETTI) +endif() + if(OPEN_AT) target_compile_definitions(mch PRIVATE USE_OPEN_AT) endif() diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 4bc53c9b4..dfeb1fa0f 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2124,7 +2124,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x66: softresetx86(); - cpu_set_edx(); break; default: diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 79a82595f..b2470bae2 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -70,7 +70,7 @@ machine_at_headland_common_init(int type) { device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if ((type != 2) && (fdc_type == FDC_INTERNAL)) device_add(&fdc_at_device); if (type == 2) @@ -117,6 +117,8 @@ machine_at_ama932j_init(const machine_t *model) machine_at_headland_common_init(2); + device_add(&ali5105_device); + return ret; } @@ -304,6 +306,8 @@ machine_at_award286_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -348,6 +352,25 @@ machine_at_gw286ct_init(const machine_t *model) return ret; } +int +machine_at_senor_scat286_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/senor286/AMI-DSC2-1115-061390-K8.rom", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_scat_init(model, 0, 1); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_super286c_init(const machine_t *model) { @@ -406,6 +429,8 @@ machine_at_spc4200p_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -449,6 +474,8 @@ machine_at_spc4620p_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -483,6 +510,8 @@ machine_at_deskmaster286_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + + device_add(&ide_isa_device); return ret; } @@ -546,7 +575,7 @@ machine_at_wd76c10_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); if (gfxcard[0] == VID_INTERNAL) device_add(¶dise_wd90c11_megapc_device); @@ -711,7 +740,7 @@ machine_at_sbc350a_init(const machine_t *model) device_add(&ali1217_device); device_add(&fdc37c665_ide_device); - device_add(&keyboard_at_device); + device_add(&keyboard_ps2_ami_device); return ret; } @@ -735,7 +764,27 @@ machine_at_flytech386_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&tvga8900d_device); - device_add(&keyboard_ps2_device); + device_add(&keyboard_at_ami_device); + + return ret; +} + +int +machine_at_325ax_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/325ax/M27C512.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1217_device); + device_add(&fdc_at_device); + device_add(&keyboard_at_ami_device); return ret; } @@ -751,11 +800,11 @@ machine_at_mr1217_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&ali1217_device); device_add(&fdc_at_device); - device_add(&keyboard_ps2_device); + device_add(&keyboard_at_ami_device); return ret; } diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 10f82e4ed..1a6a6db67 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -90,10 +90,30 @@ machine_at_asus386_init(const machine_t *model) return ret; } +int +machine_at_tandy4000_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tandy4000/BIOS Tandy 4000 v1.03.01.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_sis401_common_init(const machine_t *model) { - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&sis_85c401_device); device_add(&keyboard_at_ami_device); @@ -144,7 +164,7 @@ machine_at_av4_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&sis_85c460_device); device_add(&keyboard_at_ami_device); @@ -224,6 +244,27 @@ machine_at_spc6000a_init(const machine_t *model) return ret; } +int +machine_at_ecs386v_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ecs386v/PANDA_386V.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ali1429_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_rycleopardlx_init(const machine_t *model) { @@ -358,8 +399,10 @@ machine_at_d824_init(const machine_t *model) device_add(&gd5428_onboard_device); device_add(&keyboard_ps2_device); - device_add(&fdc37c651_device); + device_add(&ide_isa_device); + device_add(&fdc37c651_device); + return ret; } @@ -381,10 +424,9 @@ machine_at_acera1g_init(const machine_t *model) 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(&ali5105_device); + device_add(&ide_ali5213_device); return ret; } @@ -404,7 +446,7 @@ machine_at_acerv10_init(const machine_t *model) device_add(&sis_85c461_device); device_add(&keyboard_ps2_acer_pci_device); - device_add(&ide_isa_2ch_device); + device_add(&ide_isa_device); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); @@ -441,7 +483,7 @@ machine_at_decpclpv_init(const machine_t *model) static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { - machine_at_common_ide_init(model); + machine_at_common_init(model); if (is_green) device_add(&ali1429g_device); @@ -497,7 +539,7 @@ machine_at_opti495_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&opti495_device); @@ -512,7 +554,7 @@ machine_at_opti495_init(const machine_t *model) static void machine_at_opti495_ami_common_init(const machine_t *model) { - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&opti495_device); @@ -554,6 +596,27 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } +int +machine_at_exp4349_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/exp4349/biosdump.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1429g_device); + device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + return ret; +} + static void machine_at_403tg_common_init(const machine_t *model, int nvr_hack) { @@ -620,11 +683,11 @@ machine_at_403tg_d_mr_init(const machine_t *model) } 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_pb450_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/pc330_6573/$IMAGES.USF", + ret = bios_load_linear("roms/machines/pb450/OPTI802.bin", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -633,6 +696,32 @@ machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU oth 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(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 5, 6, 7, 8); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&opti895_device); + device_add(&opti602_device); + device_add(&opti822_device); + device_add(&keyboard_ps2_phoenix_device); + device_add(&fdc37c665_ide_device); + device_add(&ide_opti611_vlb_sec_device); + device_add(&intel_flash_bxt_device); + device_add(&phoenix_486_jumper_pci_device); + + return ret; +} + +static void +machine_at_pc330_6573_common_init(const machine_t *model) +{ + 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); @@ -644,7 +733,7 @@ machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU oth pci_register_slot(0x0E, PCI_CARD_VIDEO, 13, 14, 15, 16); if (gfxcard[0] == VID_INTERNAL) - device_add(&gd5430_onboard_vlb_device); + device_add(machine_get_vid_device(machine)); device_add(&opti602_device); device_add(&opti802g_device); @@ -653,6 +742,36 @@ machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU oth device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_device); device_add(&intel_flash_bxt_device); +} + +int +machine_at_aptiva510_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/aptiva510/$IMAGES.USF", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_pc330_6573_common_init(model); + + return ret; +} + +int +machine_at_pc330_6573_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pc330_6573/$IMAGES.USF", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_pc330_6573_common_init(model); return ret; } @@ -700,7 +819,6 @@ machine_at_ami471_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; @@ -718,8 +836,7 @@ machine_at_vli486sv2g_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_2ch_device); - device_add(&keyboard_ps2_ami_device); + device_add(&keyboard_at_ami_device); return ret; } @@ -736,7 +853,6 @@ machine_at_dtk486_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_device); return ret; @@ -772,12 +888,44 @@ machine_at_win471_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; } +int +machine_at_pci400ca_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pci400ca/486-AA008851.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(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_SCSI, 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(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_device); + device_add(&sio_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420tx_device); + device_add(&ncr53c810_onboard_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_vi15g_init(const machine_t *model) { @@ -790,7 +938,6 @@ machine_at_vi15g_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; @@ -819,12 +966,35 @@ machine_at_greenb_init(const machine_t *model) return ret; } +int +machine_at_4gpv5_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/4gpv5/4GPV5.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&contaq_82c596a_device); + + device_add(&keyboard_at_device); + + return ret; +} + static void machine_at_sis_85c496_common_init(UNUSED(const machine_t *model)) { device_add(&ide_pci_2ch_device); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); @@ -939,6 +1109,33 @@ machine_at_4dps_init(const machine_t *model) return ret; } +int +machine_at_ms4144_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms4144/ms-4144-1.4.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + machine_at_sis_85c496_common_init(model); + device_add(&sis_85c496_ls486e_device); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&w83787f_device); + device_add(&keyboard_at_ami_device); + + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_486sp3c_init(const machine_t *model) { @@ -1006,7 +1203,7 @@ machine_at_alfredo_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + 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); @@ -1038,7 +1235,7 @@ machine_at_ninja_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); + pci_init(PCI_CONFIG_TYPE_1); 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); @@ -1052,6 +1249,86 @@ machine_at_ninja_init(const machine_t *model) return ret; } +int +machine_at_bat4ip3e_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bat4ip3e/404C.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_IDE, 0xfe, 0xff, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 1, 2, 1, 2); + + device_add(&phoenix_486_jumper_pci_device); + device_add(&keyboard_ps2_pci_device); + device_add(&i420ex_device); + device_add(&ide_cmd640_pci_device); + device_add(&fdc37c665_device); + + return ret; +} + +int +machine_at_486pi_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/486pi/486pi.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 1, 2); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&i420ex_device); + + return ret; +} + +int +machine_at_sb486p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sb486p/amiboot.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i82091aa_device); + device_add(&i420ex_device); + + return ret; +} + int machine_at_486sp3_init(const machine_t *model) { @@ -1085,6 +1362,36 @@ machine_at_486sp3_init(const machine_t *model) return ret; } +int +machine_at_amis76_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/s76p/S76P.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(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, 1, 2, 3 ,4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420tx_device); + // device_add(&ide_cmd640_pci_device); /* is this actually cmd640? is it single channel? */ + device_add(&ide_pci_device); + + return ret; +} + int machine_at_pci400cb_init(const machine_t *model) { @@ -1098,7 +1405,6 @@ machine_at_pci400cb_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); - device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1130,7 +1436,6 @@ machine_at_g486ip_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ami_1992_nvr_device); - device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1192,7 +1497,7 @@ machine_at_486ap4_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); + pci_init(PCI_CONFIG_TYPE_1); /* 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 */ @@ -1403,6 +1708,29 @@ machine_at_tf486_init(const machine_t *model) device_add(&ali1489_device); device_add(&w83977ef_device); + device_add(&keyboard_at_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_arb1476_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/arb1476/w1476b.v21", + 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); + + device_add(&ali1489_device); + device_add(&fdc37c669_device); device_add(&keyboard_ps2_device); device_add(&sst_flash_29ee010_device); @@ -1492,6 +1820,30 @@ machine_at_arb1479_init(const machine_t *model) return ret; } +int +machine_at_iach488_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/iach488/FH48800B.980", + 0x000c0000, 262144, 0); + + if (bios_only || !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); + device_add(&w83977f_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&stpc_consumer2_device); + device_add(&sst_flash_29ee020_device); + + return ret; +} + int machine_at_pcm9340_init(const machine_t *model) { @@ -1580,7 +1932,7 @@ machine_at_ecs486_init(const machine_t *model) } int -machine_at_hot433_init(const machine_t *model) +machine_at_hot433a_init(const machine_t *model) { int ret; @@ -1601,7 +1953,7 @@ machine_at_hot433_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); + device_add(&umc_8886bf_device); device_add(&um8669f_device); device_add(&winbond_flash_w29c010_device); device_add(&keyboard_at_ami_device); @@ -1630,7 +1982,7 @@ machine_at_atc1415_init(const machine_t *model) pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); + device_add(&umc_8886bf_device); device_add(&intel_flash_bxt_device); device_add(&keyboard_at_ami_device); @@ -1654,19 +2006,53 @@ machine_at_actionpc2600_init(const machine_t *model) 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(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 3); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_VIDEO, 0, 0, 0, 0); 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(&umc_8886bf_device); + device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); device_add(&keyboard_ps2_tg_ami_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&tgui9440_onboard_pci_device); + + return ret; +} + +int +machine_at_actiontower8400_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/actiontower8400/V31C.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !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(0x15, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x16, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); + + device_add(&umc_hb4_device); + device_add(&umc_8886f_device); + device_add(&fdc37c665_device); + device_add(&ide_cmd640_pci_device); + device_add(&intel_flash_bxt_device); // The ActionPC 2600 has this so I'm gonna assume this does too. + device_add(&keyboard_ps2_ami_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5430_onboard_pci_device); + return ret; } @@ -1691,8 +2077,8 @@ machine_at_m919_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); - device_add(&um8669f_device); + device_add(&umc_8886af_device); /* AF is correct - the BIOS does IDE writes to ports 108h and 109h. */ + device_add(&um8663bf_device); device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_ami_device); @@ -1821,3 +2207,92 @@ machine_at_tg486g_init(const machine_t *model) return ret; } + +int +machine_at_dvent4xx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dvent4xx/Venturis466_BIOS.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sis_85c471_device); + device_add(&ide_cmd640_vlb_pri_device); + device_add(&fdc37c665_ide_device); + device_add(&keyboard_ps2_phoenix_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} + +int +machine_at_ecsal486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ecsal486/ECS_AL486.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_ap4100aa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap4100aa/M27C512DIP28.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&ami_1994_nvr_device); + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_vlb_device); + device_add(&um8663bf_device); + + return ret; +} + +int +machine_at_atc1762_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/atc1762/atc1762.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + + return ret; +} diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 86656b181..7f31d4ecd 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -633,7 +633,10 @@ compaq_plasma_init(UNUSED(const device_t *info)) memset(self, 0, sizeof(compaq_plasma_t)); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); - loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); + if (compaq_machine_type == COMPAQ_PORTABLEIII) + loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); + else + loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); self->cga.composite = 0; self->cga.revision = 0; @@ -795,6 +798,8 @@ machine_at_compaq_init(const machine_t *model, int type) break; case COMPAQ_PORTABLEIII: + if (hdc_current == 1) + device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); machine_at_init(model); @@ -805,13 +810,13 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + device_add(&compaq_386_device); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); 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); @@ -861,8 +866,8 @@ machine_at_portableiii386_init(const machine_t *model) { int ret; - ret = bios_load_linearr("roms/machines/portableiii/K Combined.bin", - 0x000f8000, 65536, 0); + ret = bios_load_linearr("roms/machines/portableiii/P.2 Combined.bin", + 0x000f0000, 131072, 0); if (bios_only || !ret) return ret; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 184cfc34d..d1486b579 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -143,8 +143,7 @@ machine_at_spitfire_init(const machine_t *model) pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440lx_device); device_add(&piix4e_device); - device_add(&keyboard_ps2_pci_device); - device_add(&fdc37c935_device); + device_add(&fdc37c935_no_nvr_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); device_add(&lm78_device); /* no reporting in BIOS */ @@ -152,6 +151,42 @@ machine_at_spitfire_init(const machine_t *model) return ret; } +int +machine_at_ma30d_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ma30d/BIOS.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); +#ifdef UNKNOWN_SLOT + pci_register_slot(0x0A, PCI_CARD_NETWORK, 2, 3, 4, 1); /* ???? device - GPIO? */ +#endif + 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); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 3, 0, 0, 0); + device_add(&i440lx_device); + device_add(&piix4e_device); + device_add(&nec_mate_unk_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c67x_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_p6i440e2_init(const machine_t *model) { @@ -223,6 +258,37 @@ machine_at_p2bls_init(const machine_t *model) return ret; } +int +machine_at_lgibmx7g_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/lgibmx7g/ms6119.331", + 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(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(0x14, 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(&keyboard_ps2_ami_pci_device); + device_add(&w83977tf_device); + device_add(&winbond_flash_w29c020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_p3bf_init(const machine_t *model) { @@ -740,3 +806,64 @@ machine_at_m729_init(const machine_t *model) return ret; } + +int +machine_at_p6f99_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p6f99/99-8.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_SOUND, 2, 3, 4, 1); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5600_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8661f_device); + device_add(&winbond_flash_w29c020_device); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&es1371_onboard_device); + + return ret; +} + +int +machine_at_m747_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m747/990521.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5600_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8661f_device); + device_add(&winbond_flash_w29c020_device); + + return ret; +} diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 2b2615422..9e686ae8b 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -127,13 +127,13 @@ machine_at_p6bap_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(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); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 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, 3, 2, 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); @@ -141,6 +141,9 @@ machine_at_p6bap_init(const machine_t *model) 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; } @@ -159,13 +162,13 @@ machine_at_p6bat_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(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); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 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, 3, 2, 1); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&via_apro133_device); device_add(&via_vt82c596b_device); device_add(&w83977ef_device); @@ -351,6 +354,9 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); + if (gfxcard[0] == VID_INTERNAL) { + device_add(&chips_69000_onboard_device); + } spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index ad6d2c995..f7aad92ec 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -45,7 +45,7 @@ void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | pci_switch); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -60,37 +60,12 @@ 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) -{ - 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(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); - -#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) { machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Excluded: 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14 */ @@ -181,7 +156,7 @@ machine_at_dellxp60_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -290,8 +265,8 @@ 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", + ret = bios_load_linear_combined("roms/machines/revenge/1013af2_.bio", + "roms/machines/revenge/1013af2_.bi1", 0x1c000, 128); if (bios_only || !ret) @@ -304,12 +279,34 @@ machine_at_revenge_init(const machine_t *model) return ret; } +void +machine_at_award_common_init(const machine_t *model) +{ + machine_at_common_init(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(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(&keyboard_ps2_ami_pci_device); + device_add(&sio_zb_device); + device_add(&intel_flash_bxt_device); +} + int -machine_at_586mc1_init(const machine_t *model) +machine_at_586is_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/586mc1/IS.34", + ret = bios_load_linear("roms/machines/586is/IS.34", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -317,8 +314,6 @@ machine_at_586mc1_init(const machine_t *model) machine_at_award_common_init(model); - device_add(&sio_device); - device_add(&intel_flash_bxt_device); device_add(&i430lx_device); return ret; @@ -427,7 +422,7 @@ machine_at_excaliburpci2_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); 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); diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0b67976af..ff59ec65f 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -64,8 +64,8 @@ machine_at_dellplato_init(const machine_t *model) { int ret; - ret = bios_load_linear_combined("roms/machines/dellplato/1016AX1J.bio", - "roms/machines/dellplato/1016AX1J.bi1", + ret = bios_load_linear_combined("roms/machines/dellplato/1016AX1J.BIO", + "roms/machines/dellplato/1016AX1J.BI1", 0x1d000, 128); if (bios_only || !ret) @@ -98,11 +98,11 @@ machine_at_ambradp90_init(const machine_t *model) } int -machine_at_430nx_init(const machine_t *model) +machine_at_586ip_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/430nx/IP.20", + ret = bios_load_linear("roms/machines/586ip/IP.20", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -110,13 +110,41 @@ machine_at_430nx_init(const machine_t *model) machine_at_award_common_init(model); - device_add(&sio_device); - device_add(&intel_flash_bxt_device); device_add(&i430nx_device); return ret; } +int +machine_at_tek932_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tek932/B932_019.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_CAN_SWITCH_TYPE); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 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, 3, 2, 4); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&i430nx_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_ide_device); + device_add(&ide_vlb_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + int machine_at_acerv30_init(const machine_t *model) { @@ -297,6 +325,35 @@ machine_at_hawk_init(const machine_t *model) return ret; } +int +machine_at_pt2000_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ficpt2000/PT2000_v1.01.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(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); + device_add(&piix_device); + device_add(&pc87332_398_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_pat54pv_init(const machine_t *model) { @@ -349,6 +406,36 @@ machine_at_hot543_init(const machine_t *model) return ret; } +int +machine_at_ncselp90_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ncselp90/elegancep90.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !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_pci_device); + device_add(&opti822_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_opti611_vlb_device); + device_add(&fdc37c665_ide_sec_device); + device_add(&ide_vlb_2ch_device); + + return ret; +} + int machine_at_p54sp4_init(const machine_t *model) { @@ -378,7 +465,7 @@ machine_at_sq588_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); 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) */ @@ -409,7 +496,7 @@ machine_at_p54sps_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); 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); @@ -424,3 +511,99 @@ machine_at_p54sps_init(const machine_t *model) return ret; } + +int +machine_at_ms5109_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5109/A778.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ami_1994_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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(0x07, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 3, 2, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&sis_550x_85c503_device); + device_add(&ide_w83769f_pci_device); + device_add(&keyboard_ps2_ami_device); + device_add(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_torino_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/torino/PER113.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ami_1994_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&sis_550x_85c503_device); + device_add(&ide_um8673f_device); + device_add(&keyboard_ps2_tg_ami_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + +int +machine_at_hot539_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/hot539/539_R17.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x15, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x16, 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); + device_add(&umc_8890_device); + device_add(&umc_8886af_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&um8663af_device); + + return ret; +} diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index fa81b40db..9e2ed9a26 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -43,6 +43,8 @@ #include <86box/fdc.h> #include <86box/nvr.h> #include <86box/scsi_ncr53c8xx.h> +#include <86box/thread.h> +#include <86box/network.h> int machine_at_acerv35n_init(const machine_t *model) @@ -71,9 +73,7 @@ machine_at_acerv35n_init(const machine_t *model) pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_pci_device); device_add(&fdc37c932fr_device); - device_add(&sst_flash_29ee010_device); return ret; @@ -153,7 +153,7 @@ machine_at_m7shi_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); @@ -164,7 +164,6 @@ machine_at_m7shi_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c935_device); device_add(&intel_flash_bxt_device); @@ -433,6 +432,35 @@ machine_at_p65up5_cp55t2d_init(const machine_t *model) return ret; } +int +machine_at_epc2102_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/epc2102/P5000HX.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, 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); + device_add(&keyboard_ps2_pci_device); + device_add(&i82091aa_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_p55tvp4_init(const machine_t *model) { @@ -532,7 +560,7 @@ machine_at_presario2240_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); 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); @@ -543,7 +571,6 @@ machine_at_presario2240_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c932qf_device); device_add(&sst_flash_29ee020_device); @@ -563,7 +590,7 @@ machine_at_presario4500_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); 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); @@ -574,7 +601,6 @@ machine_at_presario4500_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c931apm_compaq_device); device_add(&sst_flash_29ee020_device); @@ -592,7 +618,7 @@ machine_at_p55va_init(const machine_t *model) if (bios_only || !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); @@ -603,7 +629,6 @@ machine_at_p55va_init(const machine_t *model) 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); device_add(&fdc37c932fr_device); device_add(&intel_flash_bxt_device); @@ -621,7 +646,7 @@ machine_at_brio80xx_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); @@ -632,8 +657,7 @@ machine_at_brio80xx_init(const machine_t *model) pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c935_device); + device_add(&fdc37c935_370_device); device_add(&sst_flash_29ee020_device); return ret; @@ -688,7 +712,7 @@ machine_at_pb810_init(const machine_t *model) if (bios_only || !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); @@ -702,8 +726,7 @@ machine_at_pb810_init(const machine_t *model) device_add(&i430vx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_device); - device_add(&fdc37c935_device); + device_add(&fdc37c935_370_device); device_add(&intel_flash_bxt_device); return ret; @@ -767,6 +790,37 @@ machine_at_i430vx_init(const machine_t *model) return ret; } +int +machine_at_ma23c_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ma23c/BIOS.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(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, 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, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_VIDEO, 3, 4, 1, 2); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&nec_mate_unk_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c67x_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_nupro592_init(const machine_t *model) { @@ -1014,6 +1068,80 @@ machine_at_p5mms98_init(const machine_t *model) return ret; } +int +machine_at_richmond_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/richmond/RICHMOND.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(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(&it8671f_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(&lm75_1_4a_device); /* temperature: CPU */ + + return ret; +} + +int +machine_at_tomahawk_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tomahawk/0AAGT046.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(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NETWORK, 4, 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); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c67x_device); + device_add(&amd_flash_29f020a_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + device_add(&lm78_device); /* fans: Thermal, CPU, Chassis; temperature: unused */ + device_add(&lm75_1_4a_device); /* temperature: CPU */ + + if ((gfxcard[0] == VID_INTERNAL) && machine_get_vid_device(machine)) + device_add(machine_get_vid_device(machine)); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)) + device_add(machine_get_snd_device(machine)); + + if ((net_cards_conf[0].device_num == NET_INTERNAL) && machine_get_net_device(machine)) + device_add(machine_get_net_device(machine)); + + return ret; +} + int machine_at_ficva502_init(const machine_t *model) { @@ -1087,9 +1215,9 @@ machine_at_r534f_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -1116,9 +1244,9 @@ machine_at_ms5146_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -1134,6 +1262,119 @@ machine_at_ms5146_init(const machine_t *model) return ret; } +int +machine_at_cb52xsi_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/cb52xsi/CD5205S.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5571_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c669_370_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_sp97xv_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sp97xv/0109XVJ2.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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(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(0x13, PCI_CARD_VIDEO, 1, 2, 3, 4); /* On-chip SiS graphics, absent here. */ + device_add(&sis_5581_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_sq578_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sq578/578b03.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&sis_5581_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_ms5172_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5172/A572MS15.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + 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); + device_add(&sis_5591_1997_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_m560_init(const machine_t *model) { @@ -1213,14 +1454,13 @@ machine_at_thunderbolt_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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 1, 2, 3); /* PIIX4 */ + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 1, 2, 3); /* PIIX4 */ pci_register_slot(0x11, PCI_CARD_NORMAL, 0, 1, 2, 3); pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 0); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 0, 1); pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 0, 1, 2); device_add(&i430tx_device); device_add(&piix4_device); - device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c935_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x3, 128); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index de87ec90d..b1a9515f3 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -534,7 +534,7 @@ machine_at_acerm3a_init(const machine_t *model) if (bios_only || !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); @@ -546,8 +546,7 @@ machine_at_acerm3a_init(const machine_t *model) 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); - device_add(&fdc37c932fr_device); + device_add(&fdc37c935_device); device_add(&sst_flash_29ee010_device); @@ -671,6 +670,39 @@ machine_at_p5vxb_init(const machine_t *model) return ret; } +int +machine_at_dellhannibalp_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/dellhannibalp/1003DY0J.BIO", + "roms/machines/dellhannibalp/1003DY0J.BI1", + "roms/machines/dellhannibalp/1003DY0J.BI2", + "roms/machines/dellhannibalp/1003DY0J.BI3", + "roms/machines/dellhannibalp/1003DY0J.RCV", + 0x3a000, 128); + + 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(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, 4); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&fdc37c932fr_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + int machine_at_gw2kte_init(const machine_t *model) { @@ -686,7 +718,7 @@ machine_at_gw2kte_init(const machine_t *model) if (bios_only || !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); @@ -694,11 +726,10 @@ machine_at_gw2kte_init(const machine_t *model) 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(0x10, 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); - device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c932fr_device); device_add(&intel_flash_bxt_ami_device); @@ -718,7 +749,7 @@ machine_at_ap5s_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); 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); @@ -747,7 +778,7 @@ machine_at_ms5124_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); 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); @@ -763,6 +794,35 @@ machine_at_ms5124_init(const machine_t *model) return ret; } +int +machine_at_amis727_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/amis727/S727p.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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(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(&sis_5511_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_vectra54_init(const machine_t *model) { @@ -787,7 +847,6 @@ machine_at_vectra54_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&s3_phoenix_trio64_onboard_pci_device); - device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&fdc37c931apm_device); @@ -795,3 +854,62 @@ machine_at_vectra54_init(const machine_t *model) return ret; } + +int +machine_at_5sbm2_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/5sbm2/5SBM0717.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + 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, 1, 2); + + device_add(&keyboard_at_ami_device); + device_add(&sis_550x_device); + device_add(&um8663af_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_pc140_6260_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pc140_6260/LYKT32A.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_VIDEO, 0, 0, 0, 0); /* Onboard video */ + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5436_onboard_pci_device); + + device_add(&sis_5511_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c669_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 628206a61..e8262a6f4 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -39,6 +39,39 @@ #include "cpu.h" #include <86box/machine.h> +int +machine_at_ap61_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap61/ap61r120.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + 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(0x07, PCI_CARD_IDE, 0xFE, 0xFF, 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); + device_add(&i450kx_device); + device_add(&sio_zb_device); + device_add(&ide_cmd646_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&fdc37c665_device); + device_add(&sst_flash_29ee010_device); + // device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_p6rp4_init(const machine_t *model) { @@ -142,7 +175,7 @@ machine_at_acerv60n_init(const machine_t *model) if (bios_only || !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); @@ -154,13 +187,43 @@ machine_at_acerv60n_init(const machine_t *model) 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); device_add(&fdc37c935_device); device_add(&sst_flash_29ee010_device); return ret; } +int +machine_at_lgibmx61_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/lgibmx61/bios.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(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); + device_add(&i440fx_device); + device_add(&piix3_device); + // device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_ami_device); + // device_add(&w83787f_device); + device_add(&w83877f_president_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_vs440fx_init(const machine_t *model) { @@ -302,7 +365,7 @@ machine_at_m6mi_init(const machine_t *model) if (bios_only || !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); @@ -313,7 +376,6 @@ machine_at_m6mi_init(const machine_t *model) 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); device_add(&fdc37c935_device); device_add(&intel_flash_bxt_device); diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 382a4f327..32319e160 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -106,6 +106,38 @@ machine_at_m579_init(const machine_t *model) return ret; } +int +machine_at_gwlucas_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/gwlucas/gw2kboot.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(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0E, 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(0x0F, PCI_CARD_SOUND, 1, 2, 3, 4); // ES1373 + pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&ali1541_device); + device_add(&ali1543c_device); /* +0 */ + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 512); + + return ret; +} + int machine_at_5aa_init(const machine_t *model) { @@ -305,3 +337,32 @@ machine_at_5emapro_init(const machine_t *model) return ret; } + +int +machine_at_5sg100_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/5sg100/5sg.20g", + 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, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5591_1997_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 95ca52a3e..a69b62184 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -50,6 +50,7 @@ #include <86box/rom.h> #include <86box/video.h> #include <86box/vid_cga.h> +#include <86box/hdc.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 80a0ffbc1..804da8e30 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -772,7 +772,7 @@ speed_changed(void *priv) } void -pit_irq0_timer_pcjr(int new_out, int old_out) +pit_irq0_timer_pcjr(int new_out, int old_out, UNUSED(void *priv)) { if (new_out && !old_out) { picint(1); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index d2c9f80ba..34691773f 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -63,6 +63,7 @@ #include <86box/video.h> #include <86box/machine.h> #include <86box/sound.h> +#include <86box/plat_unused.h> typedef struct { int model; @@ -242,6 +243,56 @@ ps1_read(uint16_t port, void *priv) return ret; } +static const device_config_t ps1_2011_config[] = { + // clang-format off + { + .name = "bios_language", + .description = "BIOS Language", + .type = CONFIG_BIOS, + .default_string = "english_us", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "English (US)", .internal_name = "english_us", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/FC0000_US.BIN", "" } }, + { .name = "English (UK)", .internal_name = "english_uk", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_UK.BIN", "roms/machines/ibmps1es/FC0000_UK.BIN", "" } }, + { .name = "English (Canada)", .internal_name = "english_ca", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_CA.BIN", "roms/machines/ibmps1es/FC0000_CA.BIN", "" } }, + { .name = "Portuguese", .internal_name = "portuguese", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_PT.BIN", "roms/machines/ibmps1es/FC0000_PT.BIN", "" } }, + { .name = "German", .internal_name = "german", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_DE.BIN", "roms/machines/ibmps1es/FC0000_DE.BIN", "" } }, + { .name = "Swedish", .internal_name = "swedish", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_SE.BIN", "roms/machines/ibmps1es/FC0000_SE.BIN", "" } }, + { .name = "French", .internal_name = "french", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 262144, .files = { "roms/machines/ibmps1es/F80000_FR.BIN", "roms/machines/ibmps1es/FC0000_FR.BIN", "" } }, + { .name = "Italian", .internal_name = "italian", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/f80000.bin", "" } }, + { .name = "Spanish", .internal_name = "spanish", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 524288, .files = { "roms/machines/ibmps1es/F80000_ES.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ps1_2011_device = { + .name = "PS/1 2011", + .internal_name = "ps/1_2011", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = &ps1_2011_config[0] +}; + static void ps1_setup(int model) { @@ -273,9 +324,27 @@ ps1_setup(int model) 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); + if (!strcmp("english_us", device_get_config_bios("bios_language"))) { + /* US English */ + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + + } else if ((device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1)) == NULL) { + /* Combined ROM. */ + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); + } else { + /* Split ROM. */ + rom_init(&ps->mid_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + 0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + + rom_init(&ps->high_rom, + device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1), + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + } lpt2_remove(); @@ -309,7 +378,7 @@ ps1_setup(int model) if (gfxcard[0] == VID_INTERNAL) device_add(&ibm_ps1_2121_device); - device_add(&fdc_at_ps1_device); + device_add(&fdc_at_ps1_2121_device); device_add(&ide_isa_device); @@ -339,16 +408,43 @@ int machine_ps1_m2011_init(const machine_t *model) { int ret; + const char* fn; + uint32_t offset; - ret = bios_load_linear("roms/machines/ibmps1es/f80000.bin", - 0x000e0000, 131072, 0x60000); + if (!device_available(model->device)) { + /* No ROMs available. */ + return 0; + } - if (bios_only || !ret) + device_context(model->device); + if ((fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 1)) == NULL) { + /* Combined ROM or US English. */ + fn = device_get_bios_file(model->device, device_get_config_bios("bios_language"), 0); + offset = (!strcmp("english_us", device_get_config_bios("bios_language"))) ? 0x20000 : 0x60000; + } else { + /* Separated ROM. */ + offset = 0x20000; + } + + if (!fn) { + fn = device_get_bios_file(model->device, "us_english", 0); + offset = 0x20000; + } + + ret = bios_load_linear(fn, 0x000e0000, 131072, offset); + device_context_restore(); + + if (bios_only || !ret) { return ret; + } ps1_common_init(model); - ps1_setup(2011); + device_context(model->device); + + ps1_setup(2011); + + device_context_restore(); return ret; } diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index a6fc30e1c..8ad69e314 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1054,7 +1054,7 @@ ps2_mca_board_model_55sx_init(int has_sec_nvram, int slots) } mca_init(slots); - device_add(&keyboard_ps2_device); + device_add(&keyboard_ps2_mca_1_device); if (has_sec_nvram) device_add(&ps2_nvr_55ls_device); @@ -1228,7 +1228,7 @@ ps2_mca_board_model_70_type34_init(int is_type4, int slots) ps2.split_addr = mem_size * 1024; mca_init(slots); - device_add(&keyboard_ps2_device); + device_add(&keyboard_ps2_mca_1_device); ps2.planar_read = model_70_type3_read; ps2.planar_write = model_70_type3_write; @@ -1321,7 +1321,7 @@ ps2_mca_board_model_80_type2_init(void) ps2.split_addr = mem_size * 1024; mca_init(8); - device_add(&keyboard_ps2_device); + device_add(&keyboard_ps2_mca_1_device); ps2.planar_read = model_80_read; ps2.planar_write = model_80_write; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index a374b58f3..ded68f5dc 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -339,7 +339,7 @@ machine_xt_pravetz16_imko4_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/pravetz16/BIOS_IMKO4_FE00.BIN", + 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", @@ -640,3 +640,19 @@ machine_xt_pb8810_init(const machine_t *model) return ret; } + +int +machine_xt_glabios_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/glabios/GLABIOS_0.2.6_8X_012324.ROM", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + machine_xt_init_ex(model); + + return ret; +} diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 0b5a3eab0..7806d378b 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -1853,8 +1853,8 @@ machine_xt_m240_init(const machine_t *model) 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", + ret = bios_load_interleaved("roms/machines/m240/olivetti_m240_pchj_2.11_low.bin", + "roms/machines/m240/olivetti_m240_pchk_2.11_high.bin", 0x000f8000, 32768, 0); if (bios_only || !ret) diff --git a/src/machine/machine.c b/src/machine/machine.c index 1684f312a..b171dd505 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -156,7 +156,7 @@ machine_available(int m) } void -pit_irq0_timer(int new_out, int old_out) +pit_irq0_timer(int new_out, int old_out, UNUSED(void *priv)) { if (new_out && !old_out) picint(1); @@ -169,6 +169,7 @@ void machine_common_init(UNUSED(const machine_t *model)) { uint8_t cpu_requires_fast_pit = is486 || (!is286 && is8086 && (cpu_s->rspeed >= 8000000)); + cpu_requires_fast_pit = cpu_requires_fast_pit && !cpu_16bitbus; /* System devices first. */ pic_init(); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 014417426..dd3d58625 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -33,6 +33,9 @@ #include <86box/sound.h> #include <86box/video.h> #include <86box/plat_unused.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> // Temporarily here till we move everything out into the right files extern const device_t pcjr_device; @@ -51,6 +54,7 @@ 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; +extern const device_t ps1_2011_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -135,8 +139,12 @@ const machine_filter_t machine_chipsets[] = { { "SiS 471", MACHINE_CHIPSET_SIS_471 }, { "SiS 496", MACHINE_CHIPSET_SIS_496 }, { "SiS 501", MACHINE_CHIPSET_SIS_501 }, + { "SiS 5501", MACHINE_CHIPSET_SIS_5501 }, { "SiS 5511", MACHINE_CHIPSET_SIS_5511 }, { "SiS 5571", MACHINE_CHIPSET_SIS_5571 }, + { "SiS 5581", MACHINE_CHIPSET_SIS_5581 }, + { "SiS 5591", MACHINE_CHIPSET_SIS_5591 }, + { "SiS (5)600", MACHINE_CHIPSET_SIS_5600 }, { "SMSC VictoryBX-66", MACHINE_CHIPSET_SMSC_VICTORYBX_66 }, { "STPC Client", MACHINE_CHIPSET_STPC_CLIENT }, { "STPC Consumer-II", MACHINE_CHIPSET_STPC_CONSUMER_II }, @@ -707,6 +715,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8088] GLaBIOS", + .internal_name = "glabios", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_glabios_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", @@ -760,7 +807,7 @@ const machine_t machines[] = { .package = CPU_PKG_8088, .block = CPU_BLOCK_NONE, .min_bus = 4772728, - .max_bus = 7159092, + .max_bus = 8000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2538,7 +2585,7 @@ const machine_t machines[] = { .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, .ram = { .min = 512, - .max = 16384, + .max = 15360, .step = 512 }, .nvrmask = 63, @@ -2546,7 +2593,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ps1_2011_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -2688,8 +2735,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 12500000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2699,8 +2746,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 640, - .max = 16384, - .step = 128 + .max = 14912, + .step = 64 }, .nvrmask = 127, .kbc_device = NULL, @@ -2728,8 +2775,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 16000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2768,15 +2815,15 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 16000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 640, .max = 16384, @@ -3052,8 +3099,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 12500000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -3300,7 +3347,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 512, .max = 16384, @@ -3320,7 +3367,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[NEAT] Phoenix 286 clone", + .name = "[NEAT] Arche AMA-2010", .internal_name = "px286", .type = MACHINE_TYPE_286, .chipset = MACHINE_CHIPSET_NEAT, @@ -3460,10 +3507,10 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, + .flags = MACHINE_IDE, .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3503,7 +3550,7 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3540,7 +3587,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_FLAGS_NONE, + .flags = MACHINE_IDE, /* Has internal video: C&T VGA 411 */ .ram = { .min = 512, .max = 2048, @@ -3620,7 +3667,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 1024, .max = 5120, @@ -3659,11 +3706,11 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE, /* Has internal video: C&T VGA 411 */ .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3679,6 +3726,45 @@ const machine_t machines[] = { .net_device = NULL }, + { + .name = "[SCAT] Senor Science Co. SCAT-286-003", + .internal_name = "senorscat286", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_SCAT, + .init = machine_at_senor_scat286_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 = 1024, + .max = 4096, + .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 + }, /* 286 machines that utilize the MCA bus */ /* Has IBM PS/2 Type 2 KBC firmware. */ { @@ -3923,7 +4009,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has the AMIKey KBC firmware, which is an updated 'F' type. */ + /* Has the AMIKey-2 KBC. */ { .name = "[ALi M1217] AAEON SBC-350A", .internal_name = "sbc350a", @@ -3963,11 +4049,9 @@ const machine_t machines[] = { .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. */ + /* Has a VIA VT82C42N KBC. */ { - .name = "[ALi M1217] Flytech 386", + .name = "[ALi M1217] Flytech A36", .internal_name = "flytech386", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_ALI_M1217, @@ -3986,7 +4070,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2, + .bus_flags = MACHINE_AT, .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 1024, @@ -4005,10 +4089,49 @@ const machine_t machines[] = { .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. */ + /* Has a JetKey KBC without version, shows up as a 'H'. */ { - .name = "[ALi M1217] MR BIOS 386SX clone", + .name = "[ALi M1217] Chaintech 325AX", + .internal_name = "325ax", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_325ax_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 + }, + /* Has a JetKey KBC without version, shows up as a 'H'. */ + { + .name = "[ALi M1217] Chaintech 325AX (MR BIOS)", .internal_name = "mr1217", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_ALI_M1217, @@ -4028,7 +4151,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4130,7 +4253,7 @@ const machine_t machines[] = { 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. */ { - .name = "[HT18] AMA-932J", + .name = "[HT18] Arche AMA-932J", .internal_name = "ama932j", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_HT18, @@ -4293,7 +4416,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[NEAT] DTK 386SX clone", + .name = "[NEAT] DTK PM-1630C", .internal_name = "dtk386", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_NEAT, @@ -4498,7 +4621,7 @@ const machine_t machines[] = { /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a photo or real hardware BIOS string is found. */ { - .name = "[SCAT] KMX-C-02", + .name = "[SCAT] Kaimei KMX-C-02", .internal_name = "kmxc02", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_SCAT, @@ -4550,8 +4673,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_386SX, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -4703,8 +4826,9 @@ const machine_t machines[] = { }, /* 386DX machines */ + /* Has a Jetkey V3, which identifies as a 'B'. */ { - .name = "[ACC 2168] AMI 386DX clone", + .name = "[ACC 2168] Juko AT046DX3", .internal_name = "acc386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_ACC_2168, @@ -4834,17 +4958,17 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_386DX, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .package = CPU_PKG_386DX_DESKPRO386, + .block = CPU_BLOCK(CPU_486DLC, CPU_RAPIDCAD), + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4873,17 +4997,17 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_386DX, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .package = CPU_PKG_386DX_DESKPRO386, + .block = CPU_BLOCK(CPU_486DLC, CPU_RAPIDCAD), + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4914,8 +5038,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_386DX, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 20000000, + .max_bus = 20000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -4928,7 +5052,7 @@ const machine_t machines[] = { .max = 14336, .step = 1024 }, - .nvrmask = 127, + .nvrmask = 63, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -4980,6 +5104,126 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM AT KBC firmware. */ + { + .name = "[ISA] Tandy 4000", + .internal_name = "tandy4000", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_tandy4000_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 = 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 a Lance LT38C41 with AMI Megakey P KBC firmware */ + { + .name = "[ALi M1429] ECS Panda 386V", + .internal_name = "ecs386v", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_ALI_M1429, + .init = machine_at_ecs386v_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_VLB, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024, + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* The board has a "ASII KB-100" which I was not able to find any information about, + but the BIOS sends commands C9 without a parameter and D5, both of which are + Phoenix MultiKey commands. */ + { + .name = "[OPTi 495] U-Board OPTi 495SLC", + .internal_name = "award495", + .type = MACHINE_TYPE_386DX, + .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, /* Actual machine only supports 386DXes */ + .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 + }, /* Has AMIKey F KBC firmware. */ { .name = "[SiS 310] ASUS ISA-386C", @@ -5064,47 +5308,6 @@ const machine_t machines[] = { }, /* 386DX/486 machines */ - /* The BIOS sends commands C9 without a parameter and D5, both of which are - Phoenix MultiKey commands. */ - { - .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. */ { .name = "[OPTi 495] DataExpert SX495", @@ -5127,7 +5330,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5167,7 +5370,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5185,6 +5388,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Winbond W83C42 with unknown firmware. */ + { + .name = "[ALi M1429G] DataExpert EXP4349", + .internal_name = "exp4349", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_exp4349_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | 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 = 49152, + .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)", @@ -5293,7 +5536,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5376,7 +5619,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5416,7 +5659,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5456,7 +5699,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5497,7 +5740,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5515,7 +5758,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + { + .name = "[SiS 461] Acer V10", + .internal_name = "acerv10", + .type = MACHINE_TYPE_486, + .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_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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI: Adaptec AIC-6360 */ + .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 MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ { .name = "[SiS 471] SiS VL-BUS 471 REV. A1", .internal_name = "px471", @@ -5598,9 +5881,7 @@ const machine_t machines[] = { .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. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { .name = "[VLSI 82C480] HP Vectra 486VL", .internal_name = "vect486vl", @@ -5635,7 +5916,7 @@ const machine_t machines[] = { .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, + .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ .vid_device = &gd5428_onboard_device, .snd_device = NULL, .net_device = NULL @@ -5745,7 +6026,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 4096, .max = 36864, @@ -5785,7 +6066,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 4096, .max = 36864, @@ -5825,7 +6106,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5843,6 +6124,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has a standalone AMI Megakey 1993, which is type 'P'. */ + { + .name = "[IMS 8848] Tekram G486IP", + .internal_name = "g486ip", + .type = MACHINE_TYPE_486_S2, + .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_PCI, + .flags = 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 + }, /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ { .name = "[SiS 461] DEC DECpc LPV", @@ -5865,7 +6186,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5883,46 +6204,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ - { - .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. */ { @@ -5964,15 +6245,57 @@ const machine_t machines[] = { .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. */ + /* Has AMI MegaKey KBC. */ { - .name = "[SiS 471] ABit AB-AH4", - .internal_name = "win471", + .name = "[i420TX] J-Bond PCI400C-A", + .internal_name = "pci400ca", .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_SIS_471, - .init = machine_at_win471_init, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_pci400ca_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_SCSI, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = &keyboard_ps2_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 + }, + + + /* 486 machines - Socket 3 */ + /* 486 machines with just the ISA slot */ + /* Has a Fujitsu MBL8042H KBC. */ + { + .name = "[Contaq 82C596A] A-Trend 4GPV5", + .internal_name = "4gpv5", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_CONTAQ_82C596, + .init = machine_at_4gpv5_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -5988,7 +6311,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6006,12 +6329,9 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - - /* 486 machines - Socket 3 */ - /* 486 machines with just the ISA slot */ /* Has AMI MegaKey KBC firmware. */ { - .name = "[Contaq 82C597] Green-B", + .name = "[Contaq 82C597] Visionex Green-B", .internal_name = "greenb", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_CONTAQ_82C597, @@ -6049,7 +6369,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a VIA VT82C42N KBC. */ + /* Version 1.0 has an AMIKEY-2, version 2.0 has a VIA VT82C42N KBC. */ { .name = "[OPTi 895] Jetway J-403TG", .internal_name = "403tg", @@ -6169,7 +6489,89 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H keyboard BIOS. */ + /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ + { + .name = "[OPTi 895] Packard Bell PB450", + .internal_name = "pb450", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_pb450_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_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, + .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 = &gd5428_vlb_onboard_device, + .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. */ + { + .name = "[SiS 471] ABIT AB-AH4", + .internal_name = "win471", + .type = MACHINE_TYPE_486_S3, + .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_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-2 'H' keyboard BIOS. */ { .name = "[SiS 471] AOpen Vi15G", .internal_name = "vi15g", @@ -6191,7 +6593,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6231,7 +6633,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6271,7 +6673,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6289,9 +6691,9 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ + /* Has a Lance LT38C41L with AMIKey F keyboard BIOS. */ { - .name = "[SiS 471] Epox 486SX/DX Green", + .name = "[SiS 471] Epox GXA486SG", .internal_name = "ami471", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_SIS_471, @@ -6311,7 +6713,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6351,7 +6753,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, /* Has internal video: Western Digital WD90C33-ZZ */ .ram = { .min = 1024, .max = 65536, @@ -6369,9 +6771,170 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Unknown revision phoenix 1993 multikey */ + { + .name = "[SiS 471] DEC Venturis 4xx", + .internal_name = "dvent4xx", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_dvent4xx_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_SUPER_IO | MACHINE_APM | MACHINE_VIDEO, + .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 = &s3_phoenix_trio32_onboard_vlb_device, + .snd_device = NULL, + .net_device = NULL + }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[ALi M1429G] ECS AL486", + .internal_name = "ecsal486", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_ecsal486_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 = 98304, + .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 uses a VIA VT82C42N KBC, which is a clone of type 'F' with additional commands */ + { + .name = "[ALi M1429G] Lanner Electronics AP-4100AA", + .internal_name = "ap4100aa", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_ap4100aa_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_AT, + .flags = MACHINE_SUPER_IO | 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 + }, + /* JETKey V5.0 */ + { + .name = "[ALi M1429G] A-Trend ATC-1762", + .internal_name = "atc1762", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_atc1762_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 = 40960, + .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 */ + /* Has an AMIKEY-2 KBC. */ { .name = "[ALi M1429G] MSI MS-4134", .internal_name = "ms4134", @@ -6392,8 +6955,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6433,7 +6996,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6484,10 +7047,10 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &tgui9440_onboard_pci_device, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &tgui9440_onboard_pci_device, + .vid_device = NULL, .snd_device = NULL, .net_device = NULL }, @@ -6513,7 +7076,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PCI, /* Machine has a PISA slot */ .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, @@ -6660,6 +7223,86 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has an ALi M5042 with phoenix firmware like the ESA TF-486. */ + { + .name = "[ALi M1489] Acrosser AR-B1476", + .internal_name = "arb1476", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_arb1476_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_SUPER_IO | MACHINE_IDE | MACHINE_APM, /* Has onboard video: C&T F65545 */ + .ram = { + .min = 1024, + .max = 32768, + .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. */ + { + .name = "[OPTi 802G] IBM Aptiva 510/710/Vision", + .internal_name = "aptiva510", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_aptiva510_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_vlb_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ { .name = "[OPTi 802G] IBM PC 330 (type 6573)", @@ -6696,7 +7339,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &gd5430_onboard_pci_device, + .vid_device = &gd5430_onboard_vlb_device, .snd_device = NULL, .net_device = NULL }, @@ -6722,7 +7365,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6761,8 +7404,128 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, + .bus_flags = MACHINE_PCI, + .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 + }, + /* Has Phoenix Multikey/42 PS/2 KBC, but unknown version */ + { + .name = "[i420EX] Anigma BAT4IP3e", + .internal_name = "bat4ip3e", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_bat4ip3e_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, + .flags = MACHINE_SUPER_IO | 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 an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[i420EX] Advanced Integration Research 486PI", + .internal_name = "486pi", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_486pi_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_SUPER_IO | 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 + }, + /* absolutely no KBC info */ + { + .name = "[i420EX] ICS SB486P", + .internal_name = "sb486p", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_sb486p_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_SUPER_IO | MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6802,7 +7565,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6842,7 +7605,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -6860,6 +7623,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* According to another string seen on the UH19 website, this has AMI 'H' KBC. */ + { + .name = "[i420TX] AMI Super Voyager PCI", + .internal_name = "amis76", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_amis76_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_SUPER_IO | 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 an AMIKey-2, which is an updated version of type 'H'. Also has a SST 29EE010 Flash chip. */ { @@ -6883,7 +7686,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6922,48 +7725,8 @@ const machine_t machines[] = { .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'. */ - { - .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, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7061,7 +7824,7 @@ const machine_t machines[] = { .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. */ + /* Has a VIA VT82C42N KBC. */ { .name = "[SiS 496] Micronics M4Li", .internal_name = "m4li", @@ -7101,7 +7864,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a BestKey KBC which clones AMI type 'H'. */ + /* Revision 1 has a Lance LT38C41L, revision 2 has a Holtek HT6542B. Another variant with a Bestkey KBC might exist as well. */ { .name = "[SiS 496] Rise Computer R418", .internal_name = "r418", @@ -7141,7 +7904,7 @@ const machine_t machines[] = { .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 + /* This has a Holtek HT6542B 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. */ { .name = "[SiS 496] Soyo 4SAW2", @@ -7183,7 +7946,7 @@ const machine_t machines[] = { .net_device = NULL }, /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version - of type 'H'. */ + of type 'H'. There are other variants of the board with Holtek HT6542B KBCs. */ { .name = "[SiS 496] Zida Tomato 4DP", .internal_name = "4dps", @@ -7205,7 +7968,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 2048, .max = 261120, @@ -7223,6 +7986,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* AMIKEY-2 */ + { + .name = "[SiS 496] MSI MS-4144", + .internal_name = "ms4144", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_ms4144_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_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 5120, /* Hack: machine seems to break with less than 5 MBs of RAM */ + .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 UMC 88xx on-chip KBC. */ { .name = "[UMC 8881] A-Trend ATC-1415", @@ -7265,7 +8068,7 @@ const machine_t machines[] = { }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { - .name = "[UMC 8881] ECS Elite UM8810PAIO", + .name = "[UMC 8881] ECS Elite UM8810P-AIO", .internal_name = "ecs486", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, @@ -7305,7 +8108,7 @@ const machine_t machines[] = { }, /* Has AMIKey Z(!) KBC firmware. */ { - .name = "[UMC 8881] Epson Action PC 2600", + .name = "[UMC 8881] Epson ActionPC 2600", .internal_name = "actionpc2600", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, @@ -7325,7 +8128,48 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .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. */ + { + .name = "[UMC 8881] Epson ActionTower 8400", + .internal_name = "actiontower8400", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_actiontower8400_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_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, .ram = { .min = 1024, .max = 262144, @@ -7427,10 +8271,10 @@ const machine_t machines[] = { /* This has a Holtek KBC. */ { .name = "[UMC 8881] Shuttle HOT-433A", - .internal_name = "hot433", + .internal_name = "hot433a", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, - .init = machine_at_hot433_init, + .init = machine_at_hot433a_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -7485,7 +8329,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCIV, + .bus_flags = MACHINE_PS2_PCIV, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, @@ -7526,7 +8370,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 1024, .max = 131072, @@ -7611,7 +8455,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -7652,7 +8496,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -7670,6 +8514,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[STPC Consumer-II] Lanner Electronics IAC-H488", + .internal_name = "iach488", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_CONSUMER_II, + .init = machine_at_iach488_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, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */ + .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 + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { @@ -7781,7 +8666,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI */ .ram = { .min = 2048, .max = 131072, @@ -7820,8 +8705,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_BUS_PS2_LATCH | MACHINE_PCI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 196608, @@ -7860,8 +8745,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7901,7 +8786,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7943,7 +8828,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7983,7 +8868,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_VIDEO_8514A | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_VIDEO_8514A | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8023,7 +8908,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8041,13 +8926,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC firmware. */ + /* Has AMI MegaKey 'H' KBC firmware. */ { - .name = "[i430LX] Micro Star 586MC1", - .internal_name = "586mc1", + .name = "[i430LX] Gigabyte GA-586IS", + .internal_name = "586is", .type = MACHINE_TYPE_SOCKET4, .chipset = MACHINE_CHIPSET_INTEL_430LX, - .init = machine_at_586mc1_init, + .init = machine_at_586is_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -8062,8 +8947,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8103,7 +8988,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 8192, .max = 139264, @@ -8147,7 +9032,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 65536, @@ -8189,7 +9074,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PCIV, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8231,7 +9116,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8271,7 +9156,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8289,7 +9174,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Socket 5 machines */ /* 430NX */ /* This has the Phoenix MultiKey KBC firmware. */ @@ -8314,7 +9198,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8354,7 +9238,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8395,7 +9279,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8413,13 +9297,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC firmware. */ + /* Has AMI 'H' KBC firmware. */ { .name = "[i430NX] Gigabyte GA-586IP", - .internal_name = "430nx", + .internal_name = "586ip", .type = MACHINE_TYPE_SOCKET5, .chipset = MACHINE_CHIPSET_INTEL_430NX, - .init = machine_at_430nx_init, + .init = machine_at_586ip_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -8435,7 +9319,47 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, + .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 + }, + /* Has AMI MegaKey KBC firmware. */ + { + .name = "[i430NX] Teknor TEK-932", + .internal_name = "tek932", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_tek932_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 | MACHINE_APM, .ram = { .min = 2048, .max = 262144, @@ -8477,7 +9401,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8517,7 +9441,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8559,7 +9483,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8599,7 +9523,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8639,7 +9563,47 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .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 + }, + /* KBC On-Chip the VT82C406MV. */ + { + .name = "[i430FX] FIC PT-2000", + .internal_name = "pt2000", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_pt2000_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, .ram = { .min = 8192, .max = 131072, @@ -8683,7 +9647,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 65536, @@ -8724,7 +9688,46 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PCIV, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, + .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 + }, + { + .name = "[OPTi 597] Northgate Computer Systems Elegance Pentium 90", + .internal_name = "ncselp90", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_ncselp90_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_PS2_PCIV, + .flags = MACHINE_APM | MACHINE_IDE_DUAL | MACHINE_SUPER_IO, .ram = { .min = 8192, .max = 131072, @@ -8766,7 +9769,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8806,7 +9809,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8846,7 +9849,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8864,12 +9867,135 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[SiS 5501] MSI MS-5109", + .internal_name = "ms5109", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_ms5109_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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .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. */ + { + .name = "[SiS 5501] TriGem Torino", + .internal_name = "torino", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_torino_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_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .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 = &tgui9660_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + + /* UMC 889x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[UMC 889x] Shuttle HOT-539", + .internal_name = "hot539", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_UMC_UM8890BF, + .init = machine_at_hot539_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 = 3600, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .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 + }, /* Socket 7 (Single Voltage) machines */ /* 430FX */ - /* This has an AMIKey-2, which is an updated version of type 'H'. */ + /* This has an AMIKey-2, which is an updated version of type 'H'. + This also seems to be revision 2.1 with the FDC37C665 SIO. */ { - .name = "[i430FX] ASUS P/I-P54TP4XE", + .name = "[i430FX] ASUS P/I-P55TP4XE", .internal_name = "p54tp4xe", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -8889,7 +10015,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8909,7 +10035,7 @@ const machine_t machines[] = { }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { - .name = "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", + .name = "[i430FX] ASUS P/I-P55TP4XE (MR BIOS)", .internal_name = "p54tp4xe_mr", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -8929,7 +10055,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8947,7 +10073,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H KBC firmware. */ + /* Has AMIKey H KBC firmware. The KBC itself seems to differ between an AMIKEY-2 and a Winbond W83C42. */ { .name = "[i430FX] DataExpert EXP8551", .internal_name = "exp8551", @@ -8969,7 +10095,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9011,7 +10137,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9052,7 +10178,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9094,7 +10220,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9136,7 +10262,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9178,7 +10304,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9218,7 +10344,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9259,7 +10385,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9299,7 +10425,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9317,7 +10443,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has an AMI 'H' KBC firmware (1992). */ + /* Has an AMI MegaKey 'H' KBC firmware (1992). */ { .name = "[i430FX] QDI FMB", .internal_name = "fmb", @@ -9339,7 +10465,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9359,9 +10485,7 @@ const machine_t machines[] = { }, /* 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. */ + /* Has a Phoenix Multikey KBC in the SM(S)C SIO. */ { .name = "[i430HX] Acer M3A", .internal_name = "acerm3a", @@ -9383,13 +10507,13 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal SCSI */ .ram = { .min = 8192, .max = 196608, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -9401,7 +10525,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey F KBC firmware. */ + /* Has AMIKey-2 or VIA VT82C42N KBC (depending on the revision) with AMIKEY 'F' KBC firmware. */ { .name = "[i430HX] AOpen AP53", .internal_name = "ap53", @@ -9423,7 +10547,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -9463,7 +10587,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -9481,8 +10605,8 @@ const machine_t machines[] = { .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. */ + /* [TEST] The board doesn't seem to have a KBC at all, which probably means it's an on-chip one on the PC87306 SIO. + A list on a Danish site shows the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ { .name = "[i430HX] Supermicro P55T2S", .internal_name = "p55t2s", @@ -9504,7 +10628,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -9524,6 +10648,48 @@ const machine_t machines[] = { }, /* 430VX */ + /* 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 . */ + { + .name = "[i430VX] Dell Hannibal+", + .internal_name = "dellhannibalp", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_dellhannibalp_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_USB, + .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 + }, /* Has AMIKey H KBC firmware (AMIKey-2). */ { .name = "[i430VX] ECS P5VX-B", @@ -9546,7 +10712,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9588,13 +10754,55 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, .step = 8192 }, - .nvrmask = 127, + .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 + }, + + /* SiS 5501 */ + /* Has the Lance LT38C41 KBC. */ + { + .name = "[SiS 5501] Chaintech 5SBM2 (M103)", + .internal_name = "5sbm2", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_5sbm2_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, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -9630,7 +10838,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -9648,6 +10856,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has an SMC FDC37C669QF Super I/O. */ + { + .name = "[SiS 5511] IBM PC 140 (type 6260)", + .internal_name = "pc140_6260", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5511, + .init = machine_at_pc140_6260_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, CPU_PENTIUMMMX), + .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, + .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 = &gd5436_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H KBC firmware (AMIKey-2). */ { .name = "[SiS 5511] MSI MS-5124", @@ -9670,7 +10918,47 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .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 Megakey 'R' KBC */ + { + .name = "[SiS 5511] AMI Atlas PCI-II", + .internal_name = "amis727", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5511, + .init = machine_at_amis727_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, .ram = { .min = 8192, .max = 524288, @@ -9713,13 +11001,13 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 196608, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -9753,7 +11041,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 262144, @@ -9793,7 +11081,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9835,7 +11123,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 131072, @@ -9875,7 +11163,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 131072, @@ -9915,7 +11203,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 196608, @@ -9955,7 +11243,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 196608, @@ -9998,7 +11286,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 196608, @@ -10016,7 +11304,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B with the AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", .internal_name = "p65up5_cp55t2d", @@ -10037,8 +11325,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -10056,9 +11344,49 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Unknown PS/2 KBC. */ + { + .name = "[i430HX] Radisys EPC-2102", + .internal_name = "epc2102", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_epc2102_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, + .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 + }, /* 430VX */ - /* This has the VIA VT82C42N KBC. */ + /* This has the VIA VT82C42N or Holtek HT6542B KBC. */ { .name = "[i430VX] AOpen AP5VM", .internal_name = "ap5vm", @@ -10080,7 +11408,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10098,7 +11426,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H KBC firmware (AMIKey-2). */ + /* Has AMIKey H KBC firmware (AMIKey-2) on a BestKey KBC. */ { .name = "[i430VX] ASUS P/I-P55TVP4", .internal_name = "p55tvp4", @@ -10119,8 +11447,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10161,7 +11489,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10179,7 +11507,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* [TEST] Has AMIKey 'F' KBC firmware. */ + /* [TEST] Has AMIKey 'F' KBC firmware on a VIA VT82C42N KBC. */ { .name = "[i430VX] Biostar MB-8500TVX-A", .internal_name = "8500tvxa", @@ -10201,7 +11529,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10322,13 +11650,13 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -10362,13 +11690,13 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, + .min = 16384, .max = 131072, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -10404,7 +11732,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10444,13 +11772,13 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 8192, .max = 131072, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -10485,7 +11813,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10526,7 +11854,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10568,7 +11896,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, /* Has internal video: C&T B69000 */ .ram = { .min = 8192, .max = 262144, @@ -10608,7 +11936,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10626,6 +11954,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */ + { + .name = "[i430TX] Gateway Tomahawk", + .internal_name = "tomahawk", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_tomahawk_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 | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_NIC | MACHINE_USB, + .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 = &s3_trio64v2_dx_onboard_pci_device, + .snd_device = &cs4236b_device, + .net_device = &pcnet_am79c973_onboard_device + }, #if defined(DEV_BRANCH) && defined(USE_AN430TX) /* This has the Phoenix MultiKey KBC firmware. */ { @@ -10690,7 +12058,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10730,7 +12098,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 262144, @@ -10748,7 +12116,49 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ + /* Has a SM(S)C FDC37C67x Super I/O chip with on-chip KBC with Phoenix or + AMIKey-2 KBC firmware. */ + { + .name = "[i430TX] NEC Mate NX MA23C", + .internal_name = "ma23c", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_ma23c_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 | MACHINE_USB, + .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 + }, + /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. + A picture shows a VIA VT82C42N KBC though, so it could be a case of that KBC with AMI firmware. */ { .name = "[i430TX] PC Partner MB540N", .internal_name = "mb540n", @@ -10770,7 +12180,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10810,7 +12220,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10850,7 +12260,47 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .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. */ + { + .name = "[i430TX] TriGem Richmond", + .internal_name = "richmond", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_richmond_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 | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10893,7 +12343,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -10936,7 +12386,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -10958,11 +12408,11 @@ const machine_t machines[] = { /* SiS 5571 */ /* Has the SiS 5571 chipset with on-chip KBC. */ { - .name = "[SiS 5571] Rise R534F", - .internal_name = "r534f", + .name = "[SiS 5571] Daewoo CB52X-SI", + .internal_name = "cb52xsi", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_SIS_5571, - .init = machine_at_r534f_init, + .init = machine_at_cb52xsi_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -10970,21 +12420,21 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SOCKET5_7, .block = CPU_BLOCK_NONE, - .min_bus = 55000000, - .max_bus = 83333333, - .min_voltage = 2500, + .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, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 393216, + .max = 262144, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -11018,54 +12468,12 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .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. */ - { - .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, @@ -11078,6 +12486,172 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has the SiS 5571 chipset with on-chip KBC. */ + { + .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_USB, + .ram = { + .min = 8192, + .max = 393216, + .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 + }, + + /* SiS 5581 */ + /* Has the SiS 5581 chipset with on-chip KBC. */ + { + .name = "[SiS 5581] ASUS SP97-XV", + .internal_name = "sp97xv", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5581, + .init = machine_at_sp97xv_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 | MACHINE_USB, + .ram = { + .min = 8192, + .max = 1572864, + .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 SiS 5581 chipset with on-chip KBC. */ + { + .name = "[SiS 5581] BCM SQ-578", + .internal_name = "sq578", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5581, + .init = machine_at_sq578_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 | MACHINE_USB, + .ram = { + .min = 8192, + .max = 1572864, + .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 + }, + + /* SiS 5591 */ + /* Has the SiS 5591 chipset with on-chip KBC. */ + { + .name = "[SiS 5591] MSI MS-5172", + .internal_name = "ms5172", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5591, + .init = machine_at_ms5172_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_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 786432, + .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 + }, + + /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */ { .name = "[ALi ALADDiN IV+] MSI MS-5164", @@ -11100,7 +12674,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11118,6 +12692,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has the ALi M1543 southbridge with on-chip KBC. */ + { + .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 | MACHINE_USB, + .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 + }, /* Super Socket 7 machines */ /* ALi ALADDiN V */ @@ -11143,9 +12757,9 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { - .min = 1024, + .min = 8192, .max = 1572864, .step = 8192 }, @@ -11184,7 +12798,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11202,6 +12816,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* M1534c kbc */ + { + .name = "[ALi ALADDiN V] Gateway Lucas", + .internal_name = "gwlucas", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_gwlucas_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_PCIONLY, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal video: ATI 3D Rage Pro Turbo AGP and sound: Ensoniq ES1373*/ + .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 + }, /* Has the ALi M1543C southbridge with on-chip KBC. */ { .name = "[ALi ALADDiN V] Gigabyte GA-5AA", @@ -11224,7 +12878,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11264,7 +12918,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11307,7 +12961,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11348,7 +13002,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11389,7 +13043,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_A97, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11430,7 +13084,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11449,9 +13103,91 @@ const machine_t machines[] = { .net_device = NULL }, + /* SiS 5591 */ + /* Has the SiS 5591 chipset with on-chip KBC. */ + { + .name = "[SiS 5591] Gigabyte GA-5SG100", + .internal_name = "5sg100", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_SIS_5591, + .init = machine_at_5sg100_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 | MACHINE_USB, + .ram = { + .min = 8192, + .max = 786432, + .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 + }, + /* Socket 8 machines */ /* 450KX */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[i450KX] AOpen AP61", + .internal_name = "ap61", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_450KX, + .init = machine_at_ap61_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, + .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 + }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[i450KX] ASUS P/I-P6RP4", .internal_name = "p6rp4", @@ -11472,8 +13208,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -11515,13 +13251,13 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -11533,7 +13269,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", .internal_name = "p65up5_cp6nd", @@ -11554,8 +13290,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11573,8 +13309,7 @@ const machine_t machines[] = { .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. */ + /* Has a VIA VT82C42N with likely AMIKey 'F' KBC firmware. */ { .name = "[i440FX] Biostar MB-8600TTC", .internal_name = "8600ttc", @@ -11596,7 +13331,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11614,6 +13349,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* It's a Intel VS440FX with a Gateway 2000 OEM BIOS */ + { + .name = "[i440FX] Gateway 2000 Venus", + .internal_name = "gw2kvenus", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_440FX, + .init = machine_at_gw2kvenus_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_GAMEPORT | MACHINE_USB, + .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 AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] Gigabyte GA-686NX", .internal_name = "686nx", @@ -11635,7 +13411,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11677,7 +13453,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: S3 ViRGE/DX and sound: Crystal CS4236B */ .ram = { .min = 8192, .max = 131072, @@ -11719,7 +13495,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11737,13 +13513,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* It's a Intel VS440FX with a Gateway 2000 OEM BIOS */ + /* Has the AMIKey-2 (updated 'H') KBC firmware. */ { - .name = "[i440FX] Gateway 2000 Venus", - .internal_name = "gw2kvenus", + .name = "[i440FX] LG IBM Multinet x61 (MSI MS-6106)", + .internal_name = "lgibmx61", .type = MACHINE_TYPE_SOCKET8, .chipset = MACHINE_CHIPSET_INTEL_440FX, - .init = machine_at_gw2kvenus_init, + .init = machine_at_lgibmx61_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -11753,15 +13529,15 @@ const machine_t machines[] = { .block = CPU_BLOCK_NONE, .min_bus = 60000000, .max_bus = 66666667, - .min_voltage = 2100, + .min_voltage = 2500, .max_voltage = 3500, - .min_multi = 2.0, - .max_multi = 3.5 + .min_multi = 1.5, + .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal SCSI: Adaptec AIC-78xx */ .ram = { - .min = 8192, + .min = 40960, .max = 524288, .step = 8192 }, @@ -11799,13 +13575,13 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -11817,9 +13593,7 @@ const machine_t machines[] = { .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. */ + /* Has a VIA VT82C42N KBC with likely AMI MegaKey firmware. */ { .name = "[i440FX] PC Partner MB600N", .internal_name = "mb600n", @@ -11841,7 +13615,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11884,7 +13658,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: C-Media CMI8330 */ .ram = { .min = 1024, .max = 1572864, @@ -11904,7 +13678,7 @@ const machine_t machines[] = { }, /* 440FX */ - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B KBC with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] ASUS P/I-P65UP5 (C-PKND)", .internal_name = "p65up5_cpknd", @@ -11926,7 +13700,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11967,7 +13741,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12010,7 +13784,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12051,7 +13825,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12069,6 +13843,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a SM(S)C FDC37C67x Super I/O chip with on-chip KBC with Phoenix or + AMIKey-2 KBC firmware. */ + { + .name = "[i440LX] NEC Mate NX MA30D/23D", + .internal_name = "ma30d", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440LX, + .init = machine_at_ma30d_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 | MACHINE_USB, + .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 + }, /* 440EX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC @@ -12094,7 +13909,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12137,7 +13952,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal SCSI: Adaptec AIC-7890AB */ .ram = { .min = 8192, .max = 1048576, @@ -12178,7 +13993,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12219,7 +14034,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12260,7 +14075,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12301,7 +14116,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12342,7 +14157,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal video: Matrox MGA-G200 and sound: Crystal CS4820 */ .ram = { .min = 8192, .max = 1048576, @@ -12360,6 +14175,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 (updated 'H') KBC firmware. */ + { + .name = "[i440BX] LG IBM Multinet i x7G (MSI MS-6119)", + .internal_name = "lgibmx7g", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_lgibmx7g_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 | MACHINE_USB, + .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 National Semiconductors PC87309 Super I/O chip with on-chip KBC with most likely AMIKey-2 KBC firmware. */ { @@ -12383,7 +14238,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ .ram = { .min = 8192, .max = 1048576, @@ -12424,7 +14279,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12466,8 +14321,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_AGP, /* AGP is reserved for the internal video */ + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12507,8 +14362,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_AGP, /* AGP is reserved for the internal video */ + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12531,7 +14386,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC6310BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC-6310BXII", .internal_name = "atc6310bxii", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, @@ -12551,7 +14406,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12594,7 +14449,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: ESS ES1938S */ .ram = { .min = 8192, .max = 524288, @@ -12635,7 +14490,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1572864, @@ -12676,7 +14531,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 2097152, @@ -12717,7 +14572,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ .ram = { .min = 8192, .max = 3145728, @@ -12736,6 +14591,88 @@ const machine_t machines[] = { .net_device = NULL }, + /* SiS (5)600 */ + /* Has the SiS (5)600 chipset with on-chip KBC. */ + { + .name = "[SiS 5600] Freetech/Flexus P6F99", + .internal_name = "p6f99", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_SIS_5600, + .init = machine_at_p6f99_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 = 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 | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ + .ram = { + .min = 8192, + .max = 1572864, + .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 = &es1371_onboard_device, /* ES1373 but we currently don't emulate that. */ + .net_device = NULL + }, + /* Has the SiS (5)600 chipset with on-chip KBC. */ + { + .name = "[SiS 5600] PC Chips M747", + .internal_name = "m747", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_SIS_5600, + .init = machine_at_m747_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 = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, + .ram = { + .min = 8192, + .max = 1572864, + .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 + }, + /* Slot 1/2 machines */ /* 440GX */ /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC @@ -12761,7 +14698,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_NOISA, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 16384, .max = 2097152, @@ -12805,7 +14742,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12847,7 +14784,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12891,7 +14828,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal SCSI */ .ram = { .min = 16384, .max = 2097152, @@ -12932,7 +14869,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 16384, .max = 2097152, @@ -12976,7 +14913,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED, }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13018,8 +14955,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 /* limits assumed */ }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has EISA, possibly for a riser? */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB | MACHINE_VIDEO, /* Machine has internal video: C&T B69000, sound: ESS ES1938S and NIC: Realtek RTL8139C */ .ram = { .min = 8192, .max = 524288, @@ -13060,7 +14997,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has quad channel IDE with internal controller: CMD PCI-0648 */ .ram = { .min = 8192, .max = 1048576, @@ -13101,7 +15038,7 @@ const machine_t machines[] = { .max_multi = 8.0 /* limits assumed */ }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13144,7 +15081,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -13167,7 +15104,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC7020BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC-7020BXII", .internal_name = "atc7020bxii", .type = MACHINE_TYPE_SOCKET370, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, @@ -13187,7 +15124,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -13228,7 +15165,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -13271,7 +15208,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13312,7 +15249,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB | MACHINE_SOUND, .ram = { .min = 8192, .max = 1572864, @@ -13327,7 +15264,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cmi8738_onboard_device, .net_device = NULL }, /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA @@ -13353,7 +15290,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_A97, - .flags = MACHINE_IDE_DUAL | MACHINE_AG | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_AG | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 16384, .max = 3145728, @@ -13393,8 +15330,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_NOI97, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_NOI97, /* Has Asus-proprietary LAN/SCSI slot */ + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 16384, .max = 4194304, @@ -13437,7 +15374,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, diff --git a/src/mem/i2c_eeprom.c b/src/mem/i2c_eeprom.c index 7d83bbe88..8e4a6cc14 100644 --- a/src/mem/i2c_eeprom.c +++ b/src/mem/i2c_eeprom.c @@ -60,7 +60,7 @@ 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); + i2c_eeprom_log("I2C EEPROM %s %02X: start(%c)\n", i2c_getbusname(dev->i2c), dev->addr, read ? 'R' : 'W'); if (!read) { dev->addr_pos = 0; @@ -77,8 +77,7 @@ i2c_eeprom_read(UNUSED(void *bus), UNUSED(uint8_t addr), void *priv) 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++; - dev->addr_register &= dev->addr_mask; /* roll-over */ + dev->addr_register = (dev->addr_register + 1) & dev->addr_mask; /* roll-over */ return ret; } @@ -100,8 +99,7 @@ i2c_eeprom_write(UNUSED(void *bus), uint8_t addr, uint8_t data, void *priv) 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 */ + dev->addr_register = (dev->addr_register + 1) & dev->addr_mask; /* roll-over */ return dev->writable; } @@ -137,7 +135,8 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t w uint32_t pow_size = 1 << log2i(size); if (pow_size < size) size = pow_size << 1; - size &= 0x7fffff; /* address space limit of 8 MB = 7 bits from I2C address + 16 bits */ + if (size >= 8388608) + size = 8388608; /* address space limit of 8 MB = 7 bits from I2C address + 16 bits from command address */ i2c_eeprom_log("I2C EEPROM %s %02X: init(%d, %d)\n", i2c_getbusname(i2c), addr, size, writable); @@ -149,7 +148,8 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t w 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); + uint8_t i2c_mask = dev->addr_mask >> dev->addr_len; + i2c_sethandler(dev->i2c, dev->addr & ~i2c_mask, i2c_mask + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, i2c_eeprom_stop, dev); return dev; } @@ -161,7 +161,8 @@ i2c_eeprom_close(void *dev_handle) i2c_eeprom_log("I2C EEPROM %s %02X: close()\n", i2c_getbusname(dev->i2c), dev->addr); - i2c_removehandler(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); + uint8_t i2c_mask = dev->addr_mask >> dev->addr_len; + i2c_removehandler(dev->i2c, dev->addr & ~i2c_mask, i2c_mask + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, i2c_eeprom_stop, dev); free(dev); } diff --git a/src/mem/mem.c b/src/mem/mem.c index 0b002b302..1d373dafb 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -123,6 +123,8 @@ 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]; +uint8_t *_mem_exec[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; @@ -131,7 +133,8 @@ 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 _mem_wp[MEM_MAPPINGS_NO]; +static uint8_t _mem_wp_bus[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; @@ -1585,40 +1588,38 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) for (i = 0; i < num; i++) 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) for (i = 0; i < num; i++) { + 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 { + if (!cpu_state.abrt) { a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } - } else - mmu_perm = page_lookupp[addr >> 12]; - } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else + mmu_perm = page_lookupp[addr >> 12]; addr++; } @@ -1633,7 +1634,7 @@ mem_readb_phys(uint32_t addr) mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) + if (cpu_use_exec && map->exec) ret = map->exec[(addr - map->base) & map->mask]; else if (map->read_b) ret = map->read_b(addr, map->priv); @@ -1651,7 +1652,7 @@ mem_readw_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { 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)) @@ -1673,7 +1674,7 @@ mem_readl_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { 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)) @@ -1713,7 +1714,7 @@ mem_writeb_phys(uint32_t addr, uint8_t val) mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) + if (cpu_use_exec && map->exec) map->exec[(addr - map->base) & map->mask] = val; else if (map->write_b) map->write_b(addr, val, map->priv); @@ -1728,7 +1729,7 @@ mem_writew_phys(uint32_t addr, uint16_t val) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { 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)) @@ -1747,7 +1748,7 @@ mem_writel_phys(uint32_t addr, uint32_t val) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { 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)) @@ -1785,7 +1786,7 @@ mem_read_ram(uint32_t addr, UNUSED(void *priv)) mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; @@ -1799,7 +1800,7 @@ mem_read_ramw(uint32_t addr, UNUSED(void *priv)) mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; @@ -1813,7 +1814,7 @@ mem_read_raml(uint32_t addr, UNUSED(void *priv)) mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; @@ -2045,7 +2046,7 @@ mem_write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write B %02X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[addr >> 12]); } else @@ -2059,7 +2060,7 @@ mem_write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write W %04X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[addr >> 12]); } else @@ -2073,7 +2074,7 @@ mem_write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write L %08X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[addr >> 12]); } else @@ -2084,7 +2085,7 @@ static uint8_t mem_read_remapped(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; } @@ -2093,7 +2094,7 @@ static uint16_t mem_read_remappedw(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; } @@ -2102,7 +2103,7 @@ static uint32_t mem_read_remappedl(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; } @@ -2111,7 +2112,7 @@ static uint8_t mem_read_remapped2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; } @@ -2120,7 +2121,7 @@ static uint16_t mem_read_remappedw2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; } @@ -2129,7 +2130,7 @@ static uint32_t mem_read_remappedl2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; } @@ -2139,7 +2140,7 @@ mem_write_remapped(uint32_t addr, uint8_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2151,7 +2152,7 @@ mem_write_remappedw(uint32_t addr, uint16_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2163,7 +2164,7 @@ mem_write_remappedl(uint32_t addr, uint32_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2175,7 +2176,7 @@ mem_write_remapped2(uint32_t addr, uint8_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2187,7 +2188,7 @@ mem_write_remappedw2(uint32_t addr, uint16_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2199,7 +2200,7 @@ mem_write_remappedl2(uint32_t addr, uint32_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2284,6 +2285,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size) mem_mapping_t *map; int n; uint64_t c; + uint8_t wp; if (!size || (base_mapping == NULL)) return; @@ -2302,27 +2304,42 @@ mem_mapping_recalc(uint64_t base, uint64_t size) /* 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) { + 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); + 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)) + wp = _mem_wp[c >> MEM_GRANULARITY_BITS]; + + 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)) + if (!wp && (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)) + 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)) + wp = _mem_wp_bus[c >> MEM_GRANULARITY_BITS]; + + if (!wp && (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)) + 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; } } @@ -2382,6 +2399,22 @@ mem_mapping_recalc(uint64_t base, uint64_t size) #endif } +void +mem_set_wp(uint64_t base, uint64_t size, uint8_t flags, uint8_t wp) +{ + uint64_t c; + uint64_t end = base + size; + + for (c = base; c < end; c += MEM_GRANULARITY_SIZE) { + if (flags & ACCESS_BUS) + _mem_wp_bus[c >> MEM_GRANULARITY_BITS] = wp; + if (flags & ACCESS_CPU) + _mem_wp[c >> MEM_GRANULARITY_BITS] = wp; + } + + mem_mapping_recalc(base, size); +} + void mem_mapping_set(mem_mapping_t *map, uint32_t base, @@ -2792,6 +2825,8 @@ mem_reset(void) } memset(_mem_exec, 0x00, sizeof(_mem_exec)); + memset(_mem_wp, 0x00, sizeof(_mem_wp)); + memset(_mem_wp_bus, 0x00, sizeof(_mem_wp_bus)); memset(write_mapping, 0x00, sizeof(write_mapping)); memset(read_mapping, 0x00, sizeof(read_mapping)); memset(write_mapping_bus, 0x00, sizeof(write_mapping_bus)); @@ -2871,6 +2906,35 @@ mem_init(void) writelookupp = malloc((1 << 20) * sizeof(uint8_t)); } +static void +umc_page_recalc(uint32_t c, int set) +{ + if (set) { + pages[c].mem = &ram[(c & 0xff) << 12]; + 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].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 & 0xff) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(c & 0xff) * 64]; +#endif +} + +void +umc_smram_recalc(uint32_t start, int set) +{ + for (uint32_t c = start; c < (start + 0x0020); c++) + umc_page_recalc(c, set); +} + void mem_remap_top(int kb) { diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 21c62b833..abc34ff96 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -39,6 +39,44 @@ #include <86box/rom.h> #include <86box/gdbstub.h> +/* As below, 1 = exec, 4 = read. */ +int read_type = 4; + +/* Set trap for data address breakpoints - 1 = exec, 2 = write, 4 = read. */ +void +mem_debug_check_addr(uint32_t addr, int flags) +{ + uint32_t bp_addr; + uint32_t bp_mask; + uint32_t len_type_pair; + int bp_enabled; + uint8_t match_flags[4] = { 0, 2, 0, 6 }; + + if (cpu_state.abrt || ((flags == 1) && (cpu_state.eflags & RF_FLAG))) + return; + + if (dr[7] & 0x000000ff) for (uint8_t i = 0; i < 4; i++) { + bp_addr = dr[i]; + bp_enabled = (dr[7] >> (i << 1)) & 0x03; + len_type_pair = (dr[7] >> (16 + (i << 2))) & 0x0f; + bp_mask = ~((len_type_pair >> 2) & 0x03); + + if ((flags & match_flags[len_type_pair & 0x03]) && ((bp_addr & bp_mask) == (addr & bp_mask))) { + /* + From the Intel i386 documemntation: + + (Note that the processor sets Bn regardless of whether Gn or + Ln is set. If more than one breakpoint condition occurs at one time and if + the breakpoint trap occurs due to an enabled condition other than n, Bn may + be set, even though neither Gn nor Ln is set.) + */ + dr[6] |= (1 << i); + if (bp_enabled) + trap |= (read_type == 1) ? 8 : 4; + } + } +} + uint8_t mem_readb_map(uint32_t addr) { @@ -243,6 +281,7 @@ readmembl_2386(uint32_t addr) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, read_type); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -270,6 +309,7 @@ writemembl_2386(uint32_t addr, uint8_t val) mem_mapping_t *map; uint64_t a; + mem_debug_check_addr(addr, 2); GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); addr64 = (uint64_t) addr; @@ -347,6 +387,8 @@ readmemwl_2386(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, read_type); + mem_debug_check_addr(addr + 1, read_type); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -367,7 +409,8 @@ readmemwl_2386(uint32_t addr) } } - return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); + return readmembl_no_mmut_2386(addr, addr64a[0]) | + (((uint16_t) readmembl_no_mmut_2386(addr + 1, addr64a[1])) << 8); } } @@ -402,6 +445,8 @@ writememwl_2386(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 2); + mem_debug_check_addr(addr + 1, 2); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -428,8 +473,8 @@ writememwl_2386(uint32_t addr, uint16_t val) /* 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); + writemembl_no_mmut_2386(addr, addr64a[0], val); + writemembl_no_mmut_2386(addr + 1, addr64a[1], val >> 8); return; } } @@ -477,7 +522,8 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) return 0xffff; } - return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); + return readmembl_no_mmut_2386(addr, a64[0]) | + (((uint16_t) readmembl_no_mmut_2386(addr + 1, a64[1])) << 8); } } @@ -520,8 +566,8 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) return; } - writemembl_no_mmut(addr, a64[0], val); - writemembl_no_mmut(addr + 1, a64[1], val >> 8); + writemembl_no_mmut_2386(addr, a64[0], val); + writemembl_no_mmut_2386(addr + 1, a64[1], val >> 8); return; } } @@ -555,16 +601,18 @@ readmemll_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, read_type); + } 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) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -591,7 +639,8 @@ readmemll_2386(uint32_t 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); + return readmemwl_no_mmut_2386(addr, addr64a) | + (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); } } @@ -626,16 +675,18 @@ writememll_2386(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 2); + } 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) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -666,8 +717,8 @@ writememll_2386(uint32_t addr, uint32_t val) /* 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); + writememwl_no_mmut_2386(addr, &(addr64a[0]), val); + writememwl_no_mmut_2386(addr + 2, &(addr64a[2]), val >> 16); return; } } @@ -712,8 +763,8 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) mem_logical_addr = addr; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -721,7 +772,8 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) return 0xffffffff; } - return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); + return readmemwl_no_mmut_2386(addr, a64) | + ((uint32_t) (readmemwl_no_mmut_2386(addr + 2, &(a64[2]))) << 16); } } @@ -757,8 +809,8 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) mem_logical_addr = addr; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -766,8 +818,8 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) return; } - writememwl_no_mmut(addr, &(a64[0]), val); - writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); + writememwl_no_mmut_2386(addr, &(a64[0]), val); + writememwl_no_mmut_2386(addr + 2, &(a64[2]), val >> 16); return; } } @@ -807,8 +859,10 @@ readmemql_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, read_type); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -842,7 +896,8 @@ readmemql_2386(uint32_t 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); + return readmemll_no_mmut_2386(addr, addr64a) | + (((uint64_t) readmemll_no_mmut_2386(addr + 4, &(addr64a[4]))) << 32); } } @@ -870,8 +925,10 @@ writememql_2386(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 2); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -909,8 +966,8 @@ writememql_2386(uint32_t addr, uint64_t val) /* 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); + writememll_no_mmut_2386(addr, addr64a, val); + writememll_no_mmut_2386(addr + 4, &(addr64a[4]), val >> 32); return; } } @@ -957,32 +1014,35 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write) uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; + mem_debug_check_addr(addr, write ? 2 : read_type); + 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 (!(cr0 >> 31)) + return; - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { + for (i = 0; i < num; i++) { + /* 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 4a20e8ebc..f9718b7ce 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -296,6 +296,12 @@ rom_load_linear_inverted(const char *fn, uint32_t addr, int sz, int off, uint8_t 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"); + if (sz == 0x40000) { + if (fread(ptr + addr + 0x30000, 1, sz >> 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); + if (fread(ptr + addr + 0x20000, sz >> 1, 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); + } } (void) fclose(fp); diff --git a/src/mem/spd.c b/src/mem/spd.c index a3bcba46d..a0896a05a 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -136,7 +136,7 @@ spd_populate(uint16_t *rows, uint8_t slot_count, uint16_t total_size, uint16_t m /* 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])))) + 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. */ diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 472a042d1..cd6ec7cd9 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -131,6 +131,9 @@ static char flash_path[1024]; #define W29C020 0x4500 #define W29C040 0x4600 +#define AMD 0x01 /* AMD Manufacturer's ID */ +#define AMD29F020A 0xb000 + #define SIZE_512K 0x010000 #define SIZE_1M 0x020000 #define SIZE_2M 0x040000 @@ -144,12 +147,32 @@ 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; - else if ((base >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) - return; + if (dev->manufacturer == AMD) { + base = addr & biosmask; + + if ((base >= 0x00000) && (base <= 0x0ffff)) + memset(&dev->array[0x00000], 0xff, 65536); + else if ((base >= 0x10000) && (base <= 0x1ffff)) + memset(&dev->array[0x10000], 0xff, 65536); + else if ((base >= 0x20000) && (base <= 0x2ffff)) + memset(&dev->array[0x20000], 0xff, 65536); + else if ((base >= 0x30000) && (base <= 0x37fff)) + memset(&dev->array[0x30000], 0xff, 32768); + else if ((base >= 0x38000) && (base <= 0x39fff)) + memset(&dev->array[0x38000], 0xff, 8192); + else if ((base >= 0x3a000) && (base <= 0x3bfff)) + memset(&dev->array[0x3a000], 0xff, 8192); + else if ((base >= 0x3c000) && (base <= 0x3ffff)) + memset(&dev->array[0x3c000], 0xff, 16384); + } else { + if ((base < 0x2000) && (dev->bbp_first_8k & 0x01)) + return; + else if ((base >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) + return; + + memset(&dev->array[base], 0xff, 4096); + } - memset(&dev->array[base], 0xff, 4096); dev->dirty = 1; } @@ -262,10 +285,14 @@ sst_read_id(uint32_t addr, void *priv) { const sst_t *dev = (sst_t *) priv; uint8_t ret = 0x00; + uint32_t mask = 0xffff; - if ((addr & 0xffff) == 0) + if (dev->manufacturer == AMD) + mask >>= 8; + + if ((addr & mask) == 0) ret = dev->manufacturer; - else if ((addr & 0xffff) == 1) + else if ((addr & mask) == 1) ret = dev->id; #ifdef UNKNOWN_FLASH else if ((addr & 0xffff) == 0x100) @@ -278,6 +305,9 @@ sst_read_id(uint32_t addr, void *priv) ret = dev->bbp_first_8k; else if (addr == 0x3fff2) ret = dev->bbp_last_8k; + } else if (dev->manufacturer == AMD) { + if ((addr & mask) == 2) + ret = 0x00; } return ret; @@ -300,6 +330,15 @@ static void sst_write(uint32_t addr, uint8_t val, void *priv) { sst_t *dev = (sst_t *) priv; + uint32_t mask = 0x7fff; + uint32_t addr0 = 0x5555; + uint32_t addr1 = 0x2aaa; + + if (dev->manufacturer == AMD) { + mask >>= 4; + addr0 >>= 4; + addr1 >>= 4; + } switch (dev->command_state) { case 0: @@ -309,7 +348,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) if (dev->id_mode) dev->id_mode = 0; dev->command_state = 0; - } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + } else if (((addr & mask) == addr0) && (val == 0xaa)) dev->command_state++; else { if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { @@ -326,7 +365,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) case 1: case 4: /* 2nd and 5th Bus Write Cycle */ - if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + if (((addr & mask) == addr1) && (val == 0x55)) dev->command_state++; else dev->command_state = 0; @@ -337,7 +376,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) 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) + } else if ((addr & mask) == addr0) sst_new_command(dev, addr, val); else dev->command_state = 0; @@ -481,6 +520,8 @@ sst_init(const device_t *info) 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); + if (dev->manufacturer == AMD) + dev->is_39 = 1; dev->size = info->local & 0xffff0000; if ((dev->size == 0x20000) && (strstr(machine_get_internal_name_ex(machine), "xi8088")) && !xi8088_bios_128kb()) @@ -941,3 +982,17 @@ const device_t sst_flash_49lf160_device = { .force_redraw = NULL, .config = NULL }; + +const device_t amd_flash_29f020a_device = { + .name = "AMD 29F020a Flash BIOS", + .internal_name = "amd_flash_29f020a", + .flags = 0, + .local = AMD | AMD29F020A | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index b0ba913d5..e407d4364 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -15,7 +15,7 @@ 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 - net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c) + net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c net_modem.c utils/getline.c) find_package(PkgConfig REQUIRED) pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 5b9fc0cac..868ee036f 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -56,7 +56,6 @@ #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> diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index d01b423ae..11e823326 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -60,7 +60,6 @@ #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> diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 1e2fd1645..681263717 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -263,6 +263,8 @@ nmc93cxx_eeprom_close(void *priv) uint16_t * nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom) { + if (UNLIKELY(!eeprom)) + return NULL; /* Get EEPROM data array. */ return &eeprom->dev.data[0]; } diff --git a/src/network/net_modem.c b/src/network/net_modem.c new file mode 100644 index 000000000..078320fb4 --- /dev/null +++ b/src/network/net_modem.c @@ -0,0 +1,1610 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Hayes AT-compliant modem emulation. + * + * + * + * Authors: Cacodemon345 + * The DOSBox Team + * + * Copyright 2024 Cacodemon345 + * Copyright 2002-2021 The DOSBox Team + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/thread.h> +#include <86box/fifo.h> +#include <86box/fifo8.h> +#include <86box/timer.h> +#include <86box/serial.h> +#include <86box/plat.h> +#include <86box/network.h> +#include <86box/version.h> +#include <86box/plat_unused.h> +#include <86box/plat_netsocket.h> + +#ifdef ENABLE_MODEM_LOG +int modem_do_log = ENABLE_MODEM_LOG; + +static void +modem_log(const char *fmt, ...) +{ + va_list ap; + + if (modem_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define modem_log(fmt, ...) +#endif + +/* From RFC 1055. */ +#define END 0300 /* indicates end of packet */ +#define ESC 0333 /* indicates byte stuffing */ +#define ESC_END 0334 /* ESC ESC_END means END data byte */ +#define ESC_ESC 0335 /* ESC ESC_ESC means ESC data byte */ + +typedef enum ResTypes { + ResNONE, + ResOK, + ResERROR, + ResCONNECT, + ResRING, + ResBUSY, + ResNODIALTONE, + ResNOCARRIER, + ResNOANSWER +} ResTypes; + +enum modem_types { + MODEM_TYPE_SLIP = 1, + MODEM_TYPE_PPP = 2, + MODEM_TYPE_TCPIP = 3 +}; + +typedef enum modem_mode_t { + MODEM_MODE_COMMAND = 0, + MODEM_MODE_DATA = 1 +} modem_mode_t; + +typedef enum modem_slip_stage_t { + MODEM_SLIP_STAGE_USERNAME, + MODEM_SLIP_STAGE_PASSWORD +} modem_slip_stage_t; + +#define COMMAND_BUFFER_SIZE 512 +#define NUMBER_BUFFER_SIZE 128 +#define PHONEBOOK_SIZE 200 + +typedef struct modem_phonebook_entry_t { + char phone[NUMBER_BUFFER_SIZE]; + char address[NUMBER_BUFFER_SIZE]; +} modem_phonebook_entry_t; + +typedef struct modem_t { + uint8_t mac[6]; + serial_t *serial; + uint32_t baudrate; + + modem_mode_t mode; + + uint8_t esc_character_expected; + pc_timer_t host_to_serial_timer; + pc_timer_t dtr_timer; + pc_timer_t cmdpause_timer; + + uint8_t tx_pkt_ser_line[0x10000]; /* SLIP-encoded. */ + uint32_t tx_count; + + Fifo8 rx_data; /* Data received from the network. */ + uint8_t reg[100]; + + Fifo8 data_pending; /* Data yet to be sent to the host. */ + + char cmdbuf[COMMAND_BUFFER_SIZE]; + char prevcmdbuf[COMMAND_BUFFER_SIZE]; + char numberinprogress[NUMBER_BUFFER_SIZE]; + char lastnumber[NUMBER_BUFFER_SIZE]; + uint32_t cmdpos; + uint32_t port; + int plusinc, flowcontrol; + int in_warmup, dtrmode; + int dcdmode; + + bool connected, ringing; + bool echo, numericresponse; + bool tcpIpMode, tcpIpConnInProgress; + bool cooldown; + bool telnet_mode; + bool dtrstate; + uint32_t tcpIpConnCounter; + + int doresponse; + int cmdpause; + int listen_port; + int ringtimer; + + SOCKET serversocket; + SOCKET clientsocket; + SOCKET waitingclientsocket; + + struct { + bool binary[2]; + bool echo[2]; + bool supressGA[2]; + bool timingMark[2]; + bool inIAC; + bool recCommand; + uint8_t command; + } telClient; + + modem_phonebook_entry_t entries[PHONEBOOK_SIZE]; + uint32_t entries_num; + + netcard_t *card; +} modem_t; + +#define MREG_AUTOANSWER_COUNT 0 +#define MREG_RING_COUNT 1 +#define MREG_ESCAPE_CHAR 2 +#define MREG_CR_CHAR 3 +#define MREG_LF_CHAR 4 +#define MREG_BACKSPACE_CHAR 5 +#define MREG_GUARD_TIME 12 +#define MREG_DTR_DELAY 25 + +static void modem_do_command(modem_t *modem, int repeat); +static void modem_accept_incoming_call(modem_t *modem); + +extern ssize_t local_getline(char **buf, size_t *bufsiz, FILE *fp); + +// https://stackoverflow.com/a/122974 +char * +trim(char *str) +{ + size_t len = 0; + char *frontp = str; + char *endp = NULL; + + if (str == NULL) { + return NULL; + } + if (str[0] == '\0') { + return str; + } + + len = strlen(str); + endp = str + len; + + /* Move the front and back pointers to address the first non-whitespace + * characters from each end. + */ + while (isspace((unsigned char) *frontp)) { + ++frontp; + } + if (endp != frontp) { + while (isspace((unsigned char) *(--endp)) && endp != frontp) { } + } + + if (frontp != str && endp == frontp) + *str = '\0'; + else if (str + len - 1 != endp) + *(endp + 1) = '\0'; + + /* Shift the string so that it starts at str so that if it's dynamically + * allocated, we can still free it on the returned pointer. Note the reuse + * of endp to mean the front of the string buffer now. + */ + endp = str; + if (frontp != str) { + while (*frontp) { + *endp++ = *frontp++; + } + *endp = '\0'; + } + + return str; +} + +static void +modem_read_phonebook_file(modem_t *modem, const char *path) +{ + FILE *file = plat_fopen(path, "r"); + char *buf = NULL; + char *buf2 = NULL; + size_t size = 0; + if (!file) + return; + + modem->entries_num = 0; + + modem_log("Modem: Reading phone book file %s...\n", path); + while (local_getline(&buf, &size, file) != -1) { + modem_phonebook_entry_t entry = { { 0 }, { 0 } }; + buf[strcspn(buf, "\r\n")] = '\0'; + + /* Remove surrounding whitespace from the input line and find the address part. */ + buf = trim(buf); + buf2 = &buf[strcspn(buf, " \t")]; + + /* Remove surrounding whitespace and any extra text from the address part, then store it. */ + buf2 = trim(buf2); + buf2[strcspn(buf2, " \t")] = '\0'; + strncpy(entry.address, buf2, sizeof(entry.address) - 1); + + /* Split the line to get the phone number part, then store it. */ + buf2[0] = '\0'; + strncpy(entry.phone, buf, sizeof(entry.phone) - 1); + + if ((entry.phone[0] == '\0') || (entry.address[0] == '\0')) { + /* Appears to be a bad line. */ + modem_log("Modem: Skipped a bad line\n"); + continue; + } + + if (strspn(entry.phone, "01234567890*=,;#+>") != strlen(entry.phone)) { + /* Invalid characters. */ + modem_log("Modem: Invalid character in phone number %s\n", entry.phone); + continue; + } + + modem_log("Modem: Mapped phone number %s to address %s\n", entry.phone, entry.address); + modem->entries[modem->entries_num++] = entry; + if (modem->entries_num >= PHONEBOOK_SIZE) + break; + } + fclose(file); +} + +static void +modem_echo(modem_t *modem, uint8_t c) +{ + if (modem->echo && fifo8_num_free(&modem->data_pending)) + fifo8_push(&modem->data_pending, c); +} + +static uint32_t +modem_scan_number(char **scan) +{ + char c = 0; + uint32_t ret = 0; + while (1) { + c = **scan; + if (c == 0) + break; + if (c >= '0' && c <= '9') { + ret *= 10; + ret += c - '0'; + *scan = *scan + 1; + } else + break; + } + return ret; +} + +static uint8_t +modem_fetch_character(char **scan) +{ + uint8_t c = **scan; + *scan = *scan + 1; + return c; +} + +static void +modem_speed_changed(void *priv) +{ + modem_t *dev = (modem_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 / (double) dev->baudrate) * 9); +#if 0 + serial_clear_fifo(dev->serial); +#endif +} + +static void +modem_send_line(modem_t *modem, const char *line) +{ + fifo8_push(&modem->data_pending, modem->reg[MREG_CR_CHAR]); + fifo8_push(&modem->data_pending, modem->reg[MREG_LF_CHAR]); + fifo8_push_all(&modem->data_pending, (uint8_t *) line, strlen(line)); + fifo8_push(&modem->data_pending, modem->reg[MREG_CR_CHAR]); + fifo8_push(&modem->data_pending, modem->reg[MREG_LF_CHAR]); +} + +static void +modem_send_number(modem_t *modem, uint32_t val) +{ + fifo8_push(&modem->data_pending, modem->reg[MREG_CR_CHAR]); + fifo8_push(&modem->data_pending, modem->reg[MREG_LF_CHAR]); + + fifo8_push(&modem->data_pending, val / 100 + '0'); + val = val % 100; + fifo8_push(&modem->data_pending, val / 10 + '0'); + val = val % 10; + fifo8_push(&modem->data_pending, val + '0'); + + fifo8_push(&modem->data_pending, modem->reg[MREG_CR_CHAR]); + fifo8_push(&modem->data_pending, modem->reg[MREG_LF_CHAR]); +} + +static void +process_tx_packet(modem_t *modem, uint8_t *p, uint32_t len) +{ + int received = 0; + uint32_t pos = 0; + uint8_t *processed_tx_packet = calloc(len, 1); + uint8_t c = 0; + + modem_log("Processing SLIP packet of %u bytes\n", len); + + while (pos < len) { + c = p[pos]; + pos++; + switch (c) { + case END: + if (received) + goto send_tx_packet; + else + break; + + case ESC: + { + c = p[pos]; + pos++; + + switch (c) { + case ESC_END: + c = END; + break; + case ESC_ESC: + c = ESC; + break; + } + } + + default: + if (received < len) + processed_tx_packet[received++] = c; + break; + } + } + +send_tx_packet: + if (received) { + uint8_t *buf = calloc(received + 14, 1); + buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = 0xFF; + buf[6] = buf[7] = buf[8] = buf[9] = buf[10] = buf[11] = 0xFC; + buf[12] = 0x08; + buf[13] = 0x00; + memcpy(buf + 14, processed_tx_packet, received); + network_tx(modem->card, buf, received + 14); + free(buf); + } + free(processed_tx_packet); + return; +} + +static void +modem_data_mode_process_byte(modem_t *modem, uint8_t data) +{ + if (modem->reg[MREG_ESCAPE_CHAR] <= 127) { + if (modem->plusinc >= 1 && modem->plusinc <= 3 && modem->reg[MREG_ESCAPE_CHAR] == data) { + modem->plusinc++; + } else { + modem->plusinc = 0; + } + } + modem->cmdpause = 0; + + if (modem->tx_count < 0x10000 && modem->connected) { + modem->tx_pkt_ser_line[modem->tx_count++] = data; + if (data == END && !modem->tcpIpMode) { + process_tx_packet(modem, modem->tx_pkt_ser_line, (uint32_t) modem->tx_count); + modem->tx_count = 0; + } + } +} + +static void +host_to_modem_cb(void *priv) +{ + modem_t *modem = (modem_t *) priv; + + if (modem->in_warmup) + goto no_write_to_machine; + + if ((modem->serial->type >= SERIAL_16550) && modem->serial->fifo_enabled) { + if (fifo_get_full(modem->serial->rcvr_fifo)) { + goto no_write_to_machine; + } + } else { + if (modem->serial->lsr & 1) { + goto no_write_to_machine; + } + } + + if (!((modem->serial->mctrl & 2) || modem->flowcontrol != 3)) + goto no_write_to_machine; + + if (modem->mode == MODEM_MODE_DATA && fifo8_num_used(&modem->rx_data) && !modem->cooldown) { + serial_write_fifo(modem->serial, fifo8_pop(&modem->rx_data)); + } else if (fifo8_num_used(&modem->data_pending)) { + uint8_t val = fifo8_pop(&modem->data_pending); + serial_write_fifo(modem->serial, val); + } + + if (fifo8_num_used(&modem->data_pending) == 0) { + modem->cooldown = false; + } + +no_write_to_machine: + timer_on_auto(&modem->host_to_serial_timer, (1000000.0 / (double) modem->baudrate) * (double) 9); +} + +static void +modem_write(UNUSED(serial_t *s), void *priv, uint8_t txval) +{ + modem_t *modem = (modem_t *) priv; + + if (modem->mode == MODEM_MODE_COMMAND) { + if (modem->cmdpos < 2) { + // Ignore everything until we see "AT" sequence. + if (modem->cmdpos == 0 && toupper(txval) != 'A') { + return; + } + + if (modem->cmdpos == 1 && toupper(txval) != 'T') { + if (txval == '/') { + // Repeat the last command. + modem_echo(modem, txval); + modem_log("Repeat last command (%s)\n", modem->prevcmdbuf); + modem_do_command(modem, 1); + } else { + modem_echo(modem, modem->reg[MREG_BACKSPACE_CHAR]); + modem->cmdpos = 0; + } + return; + } + } else { + // Now entering command. + if (txval == modem->reg[MREG_BACKSPACE_CHAR]) { + if (modem->cmdpos > 2) { + modem_echo(modem, txval); + modem->cmdpos--; + } + return; + } + + if (txval == modem->reg[MREG_LF_CHAR]) { + return; // Real modem doesn't seem to skip this? + } + + if (txval == modem->reg[MREG_CR_CHAR]) { + modem_echo(modem, txval); + modem_do_command(modem, 0); + return; + } + } + + if (modem->cmdpos < 99) { + modem_echo(modem, txval); + modem->cmdbuf[modem->cmdpos] = txval; + modem->cmdpos++; + } + } else { + modem_data_mode_process_byte(modem, txval); + } +} + +void +modem_send_res(modem_t *modem, const ResTypes response) +{ + char response_str_connect[256] = { 0 }; + const char *response_str = NULL; + uint32_t code = -1; + + snprintf(response_str_connect, sizeof(response_str_connect), "CONNECT %u", modem->baudrate); + + switch (response) { + case ResOK: + code = 0; + response_str = "OK"; + break; + case ResCONNECT: + code = 1; + response_str = response_str_connect; + break; + case ResRING: + code = 2; + response_str = "RING"; + break; + case ResNOCARRIER: + code = 3; + response_str = "NO CARRIER"; + break; + case ResERROR: + code = 4; + response_str = "ERROR"; + break; + case ResNODIALTONE: + code = 6; + response_str = "NO DIALTONE"; + break; + case ResBUSY: + code = 7; + response_str = "BUSY"; + break; + case ResNOANSWER: + code = 8; + response_str = "NO ANSWER"; + break; + case ResNONE: + return; + } + + if (modem->doresponse != 1) { + if (modem->doresponse == 2 && (response == ResRING || response == ResCONNECT || response == ResNOCARRIER)) { + return; + } + modem_log("Modem response: %s\n", response_str); + if (modem->numericresponse && code != ~0) { + modem_send_number(modem, code); + } else if (response_str != NULL) { + modem_send_line(modem, response_str); + } + + // if(CSerial::CanReceiveByte()) // very fast response + // if(rqueue->inuse() && CSerial::getRTS()) + // { uint8_t rbyte =rqueue->getb(); + // CSerial::receiveByte(rbyte); + // LOG_MSG("SERIAL: Port %" PRIu8 " modem sending byte %2x back to UART2", + // GetPortNumber(), rbyte); + // } + } +} + +void +modem_enter_idle_state(modem_t *modem) +{ + timer_disable(&modem->dtr_timer); + modem->connected = false; + modem->ringing = false; + modem->mode = MODEM_MODE_COMMAND; + modem->in_warmup = 0; + modem->tcpIpConnInProgress = 0; + modem->tcpIpConnCounter = 0; + + if (modem->waitingclientsocket != (SOCKET) -1) + plat_netsocket_close(modem->waitingclientsocket); + + if (modem->clientsocket != (SOCKET) -1) + plat_netsocket_close(modem->clientsocket); + + modem->clientsocket = modem->waitingclientsocket = (SOCKET) -1; + if (modem->serversocket != (SOCKET) -1) { + modem->waitingclientsocket = plat_netsocket_accept(modem->serversocket); + while (modem->waitingclientsocket != (SOCKET) -1) { + plat_netsocket_close(modem->waitingclientsocket); + modem->waitingclientsocket = plat_netsocket_accept(modem->serversocket); + } + plat_netsocket_close(modem->serversocket); + modem->serversocket = (SOCKET) -1; + } + + if (modem->waitingclientsocket != (SOCKET) -1) + plat_netsocket_close(modem->waitingclientsocket); + + modem->waitingclientsocket = (SOCKET) -1; + modem->tcpIpMode = false; + modem->tcpIpConnInProgress = false; + + if (modem->listen_port) { + modem->serversocket = plat_netsocket_create_server(NET_SOCKET_TCP, modem->listen_port); + if (modem->serversocket == (SOCKET) -1) { + pclog("Failed to set up server on port %d\n", modem->listen_port); + } + } + + serial_set_cts(modem->serial, 1); + serial_set_dsr(modem->serial, 1); + serial_set_dcd(modem->serial, (!modem->dcdmode ? 1 : 0)); + serial_set_ri(modem->serial, 0); +} + +void +modem_enter_connected_state(modem_t *modem) +{ + modem_send_res(modem, ResCONNECT); + modem->mode = MODEM_MODE_DATA; + modem->ringing = false; + modem->connected = true; + modem->tcpIpMode = true; + modem->cooldown = true; + modem->tx_count = 0; + plat_netsocket_close(modem->serversocket); + modem->serversocket = -1; + memset(&modem->telClient, 0, sizeof(modem->telClient)); + serial_set_dcd(modem->serial, 1); + serial_set_ri(modem->serial, 0); +} + +void +modem_reset(modem_t *modem) +{ + modem->dcdmode = 1; + modem_enter_idle_state(modem); + modem->cmdpos = 0; + modem->cmdbuf[0] = 0; + modem->prevcmdbuf[0] = 0; + modem->lastnumber[0] = 0; + modem->numberinprogress[0] = 0; + modem->flowcontrol = 0; + modem->cmdpause = 0; + modem->plusinc = 0; + modem->dtrmode = 2; + + memset(&modem->reg, 0, sizeof(modem->reg)); + modem->reg[MREG_AUTOANSWER_COUNT] = 0; // no autoanswer + modem->reg[MREG_RING_COUNT] = 1; + modem->reg[MREG_ESCAPE_CHAR] = '+'; + modem->reg[MREG_CR_CHAR] = '\r'; + modem->reg[MREG_LF_CHAR] = '\n'; + modem->reg[MREG_BACKSPACE_CHAR] = '\b'; + modem->reg[MREG_GUARD_TIME] = 50; + modem->reg[MREG_DTR_DELAY] = 5; + + modem->echo = true; + modem->doresponse = 0; + modem->numericresponse = false; +} + +void +modem_dial(modem_t *modem, const char *str) +{ + modem->tcpIpConnCounter = 0; + modem->tcpIpMode = false; + if (!strncmp(str, "0.0.0.0", sizeof("0.0.0.0") - 1)) { + modem_log("Turning on SLIP\n"); + modem_enter_connected_state(modem); + modem->numberinprogress[0] = 0; + modem->tcpIpMode = false; + } else { + char buf[NUMBER_BUFFER_SIZE] = ""; + strncpy(buf, str, sizeof(buf) - 1); + strncpy(modem->lastnumber, str, sizeof(modem->lastnumber) - 1); + modem_log("Connecting to %s...\n", buf); + + // Scan host for port + uint16_t port; + char *hasport = strrchr(buf, ':'); + if (hasport) { + *hasport++ = 0; + port = (uint16_t) atoi(hasport); + } else { + port = 23; + } + + modem->numberinprogress[0] = 0; + modem->clientsocket = plat_netsocket_create(NET_SOCKET_TCP); + if (modem->clientsocket == -1) { + pclog("Failed to create client socket\n"); + modem_send_res(modem, ResNOCARRIER); + modem_enter_idle_state(modem); + return; + } + + if (-1 == plat_netsocket_connect(modem->clientsocket, buf, port)) { + pclog("Failed to connect to %s\n", buf); + modem_send_res(modem, ResNOCARRIER); + modem_enter_idle_state(modem); + return; + } + modem->tcpIpConnInProgress = 1; + modem->tcpIpConnCounter = 0; + } +} + +static bool +is_next_token(const char *a, size_t N, const char *b) +{ + // Is 'b' at least as long as 'a'? + size_t N_without_null = N - 1; + if (strnlen(b, N) < N_without_null) + return false; + return (strncmp(a, b, N_without_null) == 0); +} + +static const char * +modem_get_address_from_phonebook(modem_t *modem, const char *input) +{ + int i = 0; + for (i = 0; i < modem->entries_num; i++) { + if (strcmp(input, modem->entries[i].phone) == 0) + return modem->entries[i].address; + } + + return NULL; +} + +static void +modem_do_command(modem_t *modem, int repeat) +{ + int i = 0; + char *scanbuf = NULL; + + if (repeat) { + /* Handle the case of A/ being invoked without a previous command to run */ + if (modem->prevcmdbuf[0] == '\0') { + modem_send_res(modem, ResOK); + return; + } + /* Load the stored previous command line */ + strncpy(modem->cmdbuf, modem->prevcmdbuf, sizeof(modem->cmdbuf) - 1); + modem->cmdbuf[COMMAND_BUFFER_SIZE - 1] = '\0'; + } else { + /* Store the command line to be recalled */ + strncpy(modem->prevcmdbuf, modem->cmdbuf, sizeof(modem->prevcmdbuf) - 1); + modem->prevcmdbuf[COMMAND_BUFFER_SIZE - 1] = '\0'; + modem->cmdbuf[modem->cmdpos] = modem->prevcmdbuf[modem->cmdpos] = '\0'; + } + modem->cmdpos = 0; + for (i = 0; i < sizeof(modem->cmdbuf); i++) { + modem->cmdbuf[i] = toupper(modem->cmdbuf[i]); + } + + /* AT command set interpretation */ + if ((modem->cmdbuf[0] != 'A') || (modem->cmdbuf[1] != 'T')) { + modem_send_res(modem, ResERROR); + return; + } + + modem_log("Command received: %s (doresponse = %d)\n", modem->cmdbuf, modem->doresponse); + + scanbuf = &modem->cmdbuf[2]; + + while (1) { + char chr = modem_fetch_character(&scanbuf); + switch (chr) { + case '+': + if (is_next_token("NET", sizeof("NET"), scanbuf)) { + // only walk the pointer ahead if the command matches + scanbuf += 3; + const uint32_t requested_mode = modem_scan_number(&scanbuf); + + // If the mode isn't valid then stop parsing + if (requested_mode != 1 && requested_mode != 0) { + modem_send_res(modem, ResERROR); + return; + } + // Inform the user on changes + if (modem->telnet_mode != !!requested_mode) { + modem->telnet_mode = !!requested_mode; + } + break; + } + modem_send_res(modem, ResERROR); + return; + case 'D': + { // Dial. + char buffer[NUMBER_BUFFER_SIZE]; + char obuffer[NUMBER_BUFFER_SIZE]; + char *foundstr = &scanbuf[0]; + const char *mappedaddr = NULL; + size_t i = 0; + + if (*foundstr == 'T' || *foundstr == 'P') // Tone/pulse dialing + foundstr++; + else if (*foundstr == 'L') { // Redial last number + if (modem->lastnumber[0] == 0) + modem_send_res(modem, ResERROR); + else { + modem_log("Redialing number %s\n", modem->lastnumber); + modem_dial(modem, modem->lastnumber); + } + return; + } + + if ((!foundstr[0] && !modem->numberinprogress[0]) || ((strlen(modem->numberinprogress) + strlen(foundstr)) > (NUMBER_BUFFER_SIZE - 1))) { + // Check for empty or too long strings + modem_send_res(modem, ResERROR); + modem->numberinprogress[0] = 0; + return; + } + + foundstr = trim(foundstr); + + // Check for ; and return to command mode if found + char *semicolon = strchr(foundstr, ';'); + if (semicolon != NULL) { + modem_log("Semicolon found in number, returning to command mode\n"); + strncat(modem->numberinprogress, foundstr, strcspn(foundstr, ";")); + scanbuf = semicolon + 1; + break; + } else { + strcat(modem->numberinprogress, foundstr); + foundstr = modem->numberinprogress; + } + + modem_log("Dialing number %s\n", foundstr); + mappedaddr = modem_get_address_from_phonebook(modem, foundstr); + if (mappedaddr) { + modem_dial(modem, mappedaddr); + return; + } + + if (strlen(foundstr) >= 12) { + // Check if supplied parameter only consists of digits + bool isNum = true; + size_t fl = strlen(foundstr); + for (i = 0; i < fl; i++) + if (foundstr[i] < '0' || foundstr[i] > '9') + isNum = false; + if (isNum && (fl > (NUMBER_BUFFER_SIZE - 5))) { + // Check if the number is long enough to cause buffer + // overflows during the number => IP transformation + modem_send_res(modem, ResERROR); + modem->numberinprogress[0] = 0; + return; + } else if (isNum) { + // Parameter is a number with at least 12 digits => this cannot + // be a valid IP/name + // Transform by adding dots + size_t j = 0; + const size_t foundlen = strlen(foundstr); + for (i = 0; i < foundlen; i++) { + buffer[j++] = foundstr[i]; + // Add a dot after the third, sixth and ninth number + if (i == 2 || i == 5 || i == 8) + buffer[j++] = '.'; + // If the string is longer than 12 digits, + // interpret the rest as port + if (i == 11 && foundlen > 12) + buffer[j++] = ':'; + } + buffer[j] = 0; + foundstr = buffer; + + // Remove Zeros from beginning of octets + size_t k = 0; + size_t foundlen2 = strlen(foundstr); + for (i = 0; i < foundlen2; i++) { + if (i == 0 && foundstr[0] == '0') + continue; + if (i == 1 && foundstr[0] == '0' && foundstr[1] == '0') + continue; + if (foundstr[i] == '0' && foundstr[i - 1] == '.') + continue; + if (foundstr[i] == '0' && foundstr[i - 1] == '0' && foundstr[i - 2] == '.') + continue; + obuffer[k++] = foundstr[i]; + } + obuffer[k] = 0; + foundstr = obuffer; + } + } + modem_dial(modem, foundstr); + return; + } + case 'I': // Some strings about firmware + switch (modem_scan_number(&scanbuf)) { + case 3: + modem_send_line(modem, "86Box Emulated Modem Firmware V1.00"); + break; + case 4: + modem_send_line(modem, "Modem compiled for 86Box version " EMU_VERSION); + break; + } + break; + case 'E': // Echo on/off + switch (modem_scan_number(&scanbuf)) { + case 0: + modem->echo = false; + break; + case 1: + modem->echo = true; + break; + } + break; + case 'V': + switch (modem_scan_number(&scanbuf)) { + case 0: + modem->numericresponse = true; + break; + case 1: + modem->numericresponse = false; + break; + } + break; + case 'H': // Hang up + switch (modem_scan_number(&scanbuf)) { + case 0: + modem->numberinprogress[0] = 0; + if (modem->connected) { + modem_send_res(modem, ResNOCARRIER); + modem_enter_idle_state(modem); + return; + } + // else return ok + } + break; + case 'O': // Return to data mode + switch (modem_scan_number(&scanbuf)) { + case 0: + if (modem->connected) { + modem->mode = MODEM_MODE_DATA; + return; + } else { + modem_send_res(modem, ResERROR); + return; + } + } + break; + case 'T': // Tone Dial + case 'P': // Pulse Dial + break; + case 'M': // Monitor + case 'L': // Volume + case 'W': + case 'X': + modem_scan_number(&scanbuf); + break; + case 'A': // Answer call + { + if (modem->waitingclientsocket == -1) { + modem_send_res(modem, ResERROR); + return; + } + modem_accept_incoming_call(modem); + break; + } + return; + case 'Z': + { // Reset and load profiles + // scan the number away, if any + modem_scan_number(&scanbuf); + if (modem->connected) + modem_send_res(modem, ResNOCARRIER); + modem_reset(modem); + break; + } + case ' ': // skip space + break; + case 'Q': + { + // Response options + // 0 = all on, 1 = all off, + // 2 = no ring and no connect/carrier in answermode + const uint32_t val = modem_scan_number(&scanbuf); + if (!(val > 2)) { + modem->doresponse = val; + break; + } else { + modem_send_res(modem, ResERROR); + return; + } + } + + case 'S': + { // Registers + const uint32_t index = modem_scan_number(&scanbuf); + if (index >= 100) { + modem_send_res(modem, ResERROR); + return; // goto ret_none; + } + + while (scanbuf[0] == ' ') + scanbuf++; // skip spaces + + if (scanbuf[0] == '=') { // set register + scanbuf++; + while (scanbuf[0] == ' ') + scanbuf++; // skip spaces + const uint32_t val = modem_scan_number(&scanbuf); + modem->reg[index] = val; + break; + } else if (scanbuf[0] == '?') { // get register + modem_send_number(modem, modem->reg[index]); + scanbuf++; + break; + } + // else + // LOG_MSG("SERIAL: Port %" PRIu8 " print reg %" PRIu32 + // " with %" PRIu8 ".", + // GetPortNumber(), index, reg[index]); + } + break; + case '&': + { // & escaped commands + char cmdchar = modem_fetch_character(&scanbuf); + switch (cmdchar) { + case 'C': + { + const uint32_t val = modem_scan_number(&scanbuf); + if (val < 2) + modem->dcdmode = val; + else { + modem_send_res(modem, ResERROR); + return; + } + break; + } + case 'K': + { + const uint32_t val = modem_scan_number(&scanbuf); + if (val < 5) + modem->flowcontrol = val; + else { + modem_send_res(modem, ResERROR); + return; + } + break; + } + case 'D': + { + const uint32_t val = modem_scan_number(&scanbuf); + if (val < 4) + modem->dtrmode = val; + else { + modem_send_res(modem, ResERROR); + return; + } + break; + } + case '\0': + // end of string + modem_send_res(modem, ResERROR); + return; + } + break; + } + break; + case '\\': + { // \ escaped commands + char cmdchar = modem_fetch_character(&scanbuf); + switch (cmdchar) { + case 'N': + // error correction stuff - not emulated + if (modem_scan_number(&scanbuf) > 5) { + modem_send_res(modem, ResERROR); + return; + } + break; + case '\0': + // end of string + modem_send_res(modem, ResERROR); + return; + } + break; + } + case '\0': + modem_send_res(modem, ResOK); + return; + } + } +} + +void +modem_dtr_callback_timer(void *priv) +{ + modem_t *dev = (modem_t *) priv; + if (dev->connected) { + switch (dev->dtrmode) { + case 1: + modem_log("DTR dropped, returning to command mode (dtrmode = %i)\n", dev->dtrmode); + dev->mode = MODEM_MODE_COMMAND; + break; + case 2: + modem_log("DTR dropped, hanging up (dtrmode = %i)\n", dev->dtrmode); + modem_send_res(dev, ResNOCARRIER); + modem_enter_idle_state(dev); + break; + case 3: + modem_log("DTR dropped, resetting modem (dtrmode = %i)\n", dev->dtrmode); + modem_send_res(dev, ResNOCARRIER); + modem_reset(dev); + break; + } + } +} + +void +modem_dtr_callback(serial_t *serial, int status, void *priv) +{ + modem_t *dev = (modem_t *) priv; + dev->dtrstate = !!status; + if (status == 1) + timer_disable(&dev->dtr_timer); + else if (!timer_is_enabled(&dev->dtr_timer)) + timer_on_auto(&dev->dtr_timer, 1000000); +} + +static void +fifo8_resize_2x(Fifo8 *fifo) +{ + uint32_t pos = 0; + uint32_t size = fifo->capacity * 2; + uint32_t used = fifo8_num_used(fifo); + if (!used) + return; + + uint8_t *temp_buf = calloc(fifo->capacity * 2, 1); + if (!temp_buf) { + fatal("net_modem: Out Of Memory!\n"); + } + while (!fifo8_is_empty(fifo)) { + temp_buf[pos] = fifo8_pop(fifo); + pos++; + } + pos = 0; + fifo8_destroy(fifo); + fifo8_create(fifo, size); + fifo8_push_all(fifo, temp_buf, used); + free(temp_buf); +} + +#define TEL_CLIENT 0 +#define TEL_SERVER 1 +void +modem_process_telnet(modem_t *modem, uint8_t *data, uint32_t size) +{ + uint32_t i = 0; + for (i = 0; i < size; i++) { + uint8_t c = data[i]; + if (modem->telClient.inIAC) { + if (modem->telClient.recCommand) { + if ((c != 0) && (c != 1) && (c != 3)) { + if (modem->telClient.command > 250) { + /* Reject anything we don't recognize */ + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 252); + modem_data_mode_process_byte(modem, c); /* We won't do crap! */ + } + } + switch (modem->telClient.command) { + case 251: /* Will */ + if (c == 0) + modem->telClient.binary[TEL_SERVER] = true; + if (c == 1) + modem->telClient.echo[TEL_SERVER] = true; + if (c == 3) + modem->telClient.supressGA[TEL_SERVER] = true; + break; + case 252: /* Won't */ + if (c == 0) + modem->telClient.binary[TEL_SERVER] = false; + if (c == 1) + modem->telClient.echo[TEL_SERVER] = false; + if (c == 3) + modem->telClient.supressGA[TEL_SERVER] = false; + break; + case 253: /* Do */ + if (c == 0) { + modem->telClient.binary[TEL_CLIENT] = true; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 251); + modem_data_mode_process_byte(modem, 0); /* Will do binary transfer */ + } + if (c == 1) { + modem->telClient.echo[TEL_CLIENT] = false; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 252); + modem_data_mode_process_byte(modem, 1); /* Won't echo (too lazy) */ + } + if (c == 3) { + modem->telClient.supressGA[TEL_CLIENT] = true; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 251); + modem_data_mode_process_byte(modem, 3); /* Will Suppress GA */ + } + break; + case 254: /* Don't */ + if (c == 0) { + modem->telClient.binary[TEL_CLIENT] = false; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 252); + modem_data_mode_process_byte(modem, 0); /* Won't do binary transfer */ + } + if (c == 1) { + modem->telClient.echo[TEL_CLIENT] = false; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 252); + modem_data_mode_process_byte(modem, 1); /* Won't echo (fine by me) */ + } + if (c == 3) { + modem->telClient.supressGA[TEL_CLIENT] = true; + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 251); + modem_data_mode_process_byte(modem, 3); /* Will Suppress GA (too lazy) */ + } + break; + default: + break; + } + modem->telClient.inIAC = false; + modem->telClient.recCommand = false; + continue; + } else { + if (c == 249) { + /* Go Ahead received */ + modem->telClient.inIAC = false; + continue; + } + modem->telClient.command = c; + modem->telClient.recCommand = true; + + if ((modem->telClient.binary[TEL_SERVER]) && (c == 0xff)) { + /* Binary data with value of 255 */ + modem->telClient.inIAC = false; + modem->telClient.recCommand = false; + fifo8_push(&modem->rx_data, 0xff); + continue; + } + } + } else { + if (c == 0xff) { + modem->telClient.inIAC = true; + continue; + } + fifo8_push(&modem->rx_data, c); + } + } +} + +static int +modem_rx(void *priv, uint8_t *buf, int io_len) +{ + modem_t *modem = (modem_t *) priv; + uint32_t i = 0; + + if (modem->tcpIpMode) + return 0; + + if (!modem->connected) { + /* Drop packet. */ + modem_log("Dropping %d bytes\n", io_len - 14); + return 0; + } + + while ((io_len) >= (fifo8_num_free(&modem->rx_data) / 2)) { + fifo8_resize_2x(&modem->rx_data); + } + + if (!(buf[12] == 0x08 && buf[13] == 0x00)) { + modem_log("Dropping %d bytes (non-IP packet (ethtype 0x%02X%02X))\n", io_len - 14, buf[12], buf[13]); + return 0; + } + + modem_log("Receiving %d bytes\n", io_len - 14); + /* Strip the Ethernet header. */ + io_len -= 14; + buf += 14; + + fifo8_push(&modem->rx_data, END); + for (i = 0; i < io_len; i++) { + switch (buf[i]) { + case END: + fifo8_push(&modem->rx_data, ESC); + fifo8_push(&modem->rx_data, ESC_END); + break; + case ESC: + fifo8_push(&modem->rx_data, ESC); + fifo8_push(&modem->rx_data, ESC_ESC); + break; + default: + fifo8_push(&modem->rx_data, buf[i]); + break; + } + } + fifo8_push(&modem->rx_data, END); + return 1; +} + +static void +modem_rcr_cb(UNUSED(struct serial_s *serial), void *priv) +{ + modem_t *dev = (modem_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 / (double) dev->baudrate) * (double) 9); +#if 0 + serial_clear_fifo(dev->serial); +#endif +} + +static void +modem_accept_incoming_call(modem_t *modem) +{ + if (modem->waitingclientsocket != -1) { + modem->clientsocket = modem->waitingclientsocket; + modem->waitingclientsocket = -1; + modem_enter_connected_state(modem); + modem->in_warmup = 250; + } else { + modem_enter_idle_state(modem); + } +} + +static void +modem_cmdpause_timer_callback(void *priv) +{ + modem_t *modem = (modem_t *) priv; + uint32_t guard_threshold = 0; + timer_on_auto(&modem->cmdpause_timer, 1000); + + if (modem->tcpIpConnInProgress) { + do { + int status = plat_netsocket_connected(modem->clientsocket); + + if (status == -1) { + plat_netsocket_close(modem->clientsocket); + modem->clientsocket = -1; + modem_enter_idle_state(modem); + modem_send_res(modem, ResNOCARRIER); + modem->tcpIpConnInProgress = 0; + break; + } else if (status == 1) { + modem_enter_connected_state(modem); + modem->tcpIpConnInProgress = 0; + break; + } + + modem->tcpIpConnCounter++; + + if (status < 0 || (status == 0 && modem->tcpIpConnCounter >= 5000)) { + plat_netsocket_close(modem->clientsocket); + modem->clientsocket = -1; + modem_enter_idle_state(modem); + modem_send_res(modem, ResNOANSWER); + modem->tcpIpConnInProgress = 0; + modem->tcpIpMode = 0; + break; + } + } while (0); + } + + if (!modem->connected && modem->waitingclientsocket == -1 && modem->serversocket != -1) { + modem->waitingclientsocket = plat_netsocket_accept(modem->serversocket); + if (modem->waitingclientsocket != -1) { + if (modem->dtrstate == 0 && modem->dtrmode != 0) { + modem_enter_idle_state(modem); + } else { + modem->ringing = true; + modem_send_res(modem, ResRING); + serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); + modem->ringtimer = 3000; + modem->reg[MREG_RING_COUNT] = 0; + } + } + } + if (modem->ringing) { + if (modem->ringtimer <= 0) { + modem->reg[MREG_RING_COUNT]++; + if ((modem->reg[MREG_AUTOANSWER_COUNT] > 0) && (modem->reg[MREG_RING_COUNT] >= modem->reg[MREG_AUTOANSWER_COUNT])) { + modem_accept_incoming_call(modem); + return; + } + modem_send_res(modem, ResRING); + serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); + + modem->ringtimer = 3000; + } + --modem->ringtimer; + } + + if (modem->in_warmup) { + modem->in_warmup--; + if (modem->in_warmup == 0) { + modem->tx_count = 0; + fifo8_reset(&modem->rx_data); + } + } else if (modem->connected && modem->tcpIpMode) { + if (modem->tx_count) { + int wouldblock = 0; + int res = plat_netsocket_send(modem->clientsocket, modem->tx_pkt_ser_line, modem->tx_count, &wouldblock); + + if (res <= 0 && !wouldblock) { + /* No bytes sent or error. */ + modem->tx_count = 0; + modem_enter_idle_state(modem); + modem_send_res(modem, ResNOCARRIER); + } else if (res > 0) { + if (res == modem->tx_count) { + modem->tx_count = 0; + } else { + memmove(modem->tx_pkt_ser_line, &modem->tx_pkt_ser_line[res], modem->tx_count - res); + modem->tx_count -= res; + } + } + } + if (modem->connected) { + uint8_t buffer[16]; + int wouldblock = 0; + int res = plat_netsocket_receive(modem->clientsocket, buffer, sizeof(buffer), &wouldblock); + + if (res > 0) { + if (modem->telnet_mode) + modem_process_telnet(modem, buffer, res); + else + fifo8_push_all(&modem->rx_data, buffer, res); + } else if (res == 0) { + modem->tx_count = 0; + modem_enter_idle_state(modem); + modem_send_res(modem, ResNOCARRIER); + } else if (!wouldblock) { + modem->tx_count = 0; + modem_enter_idle_state(modem); + modem_send_res(modem, ResNOCARRIER); + } + } + } + + modem->cmdpause++; + guard_threshold = (uint32_t) (modem->reg[MREG_GUARD_TIME] * 20); + if (modem->cmdpause > guard_threshold) { + if (modem->plusinc == 0) { + modem->plusinc = 1; + } else if (modem->plusinc == 4) { + modem_log("Escape sequence triggered, returning to command mode\n"); + modem->mode = MODEM_MODE_COMMAND; + modem_send_res(modem, ResOK); + modem->plusinc = 0; + } + } +} + +/* Initialize the device for use by the user. */ +static void * +modem_init(const device_t *info) +{ + modem_t *modem = (modem_t *) calloc(1, sizeof(modem_t)); + const char *phonebook_file = NULL; + memset(modem->mac, 0xfc, 6); + + modem->port = device_get_config_int("port"); + modem->baudrate = device_get_config_int("baudrate"); + modem->listen_port = device_get_config_int("listen_port"); + modem->telnet_mode = device_get_config_int("telnet_mode"); + + modem->clientsocket = modem->serversocket = modem->waitingclientsocket = -1; + + fifo8_create(&modem->data_pending, 0x10000); + fifo8_create(&modem->rx_data, 0x10000); + + timer_add(&modem->dtr_timer, modem_dtr_callback_timer, modem, 0); + timer_add(&modem->host_to_serial_timer, host_to_modem_cb, modem, 0); + timer_add(&modem->cmdpause_timer, modem_cmdpause_timer_callback, modem, 0); + timer_on_auto(&modem->cmdpause_timer, 1000); + modem->serial = serial_attach_ex_2(modem->port, modem_rcr_cb, modem_write, modem_dtr_callback, modem); + + modem_reset(modem); + modem->card = network_attach(modem, modem->mac, modem_rx, NULL); + + phonebook_file = device_get_config_string("phonebook_file"); + if (phonebook_file && phonebook_file[0] != 0) { + modem_read_phonebook_file(modem, phonebook_file); + } + + return modem; +} + +void +modem_close(void *priv) +{ + modem_t *modem = (modem_t *) priv; + modem->listen_port = 0; + modem_reset(modem); + fifo8_destroy(&modem->data_pending); + fifo8_destroy(&modem->rx_data); + netcard_close(modem->card); + free(priv); +} + +// clang-format off +static const device_config_t modem_config[] = { + { + .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 = "baudrate", + .description = "Baud Rate", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 115200, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .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 }, + } + }, + { + .name = "listen_port", + .description = "TCP/IP listening port", + .type = CONFIG_SPINNER, + .spinner = + { + .min = 0, + .max = 32767 + }, + .default_int = 0 + }, + { + .name = "phonebook_file", + .description = "Phonebook File", + .type = CONFIG_FNAME, + .default_string = "", + .file_filter = "Text files (*.txt)|*.txt" + }, + { + .name = "telnet_mode", + .description = "Telnet emulation", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +const device_t modem_device = { + .name = "Standard Hayes-compliant Modem", + .internal_name = "modem", + .flags = DEVICE_COM, + .local = 0, + .init = modem_init, + .close = modem_close, + .reset = NULL, + { .poll = NULL }, + .speed_changed = modem_speed_changed, + .force_redraw = NULL, + .config = modem_config +}; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index c7fba404f..ee32119ba 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -82,19 +82,6 @@ #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 */ - 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 */ - - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ -}; - typedef struct nic_t { dp8390_t *dp8390; @@ -947,7 +934,7 @@ nic_init(const device_t *info) 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) { + if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT)) { dev->bios_addr = device_get_config_hex20("bios_addr"); dev->has_bios = !!dev->bios_addr; } else { @@ -993,6 +980,16 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); break; + case NE2K_NE1000_COMPAT: + dev->maclocal[0] = 0x00; /* 00:86:B0 (86Box OID) */ + dev->maclocal[1] = 0x86; + dev->maclocal[2] = 0xB0; + 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; @@ -1002,6 +999,15 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); break; + case NE2K_NE2000_COMPAT: + dev->maclocal[0] = 0x00; /* 00:86:B0 (86Box OID) */ + dev->maclocal[1] = 0x86; + dev->maclocal[2] = 0xB0; + 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; @@ -1013,6 +1019,16 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); break; + case NE2K_DE220P: + dev->maclocal[0] = 0x00; /* 00:80:C8 (D-Link OID) */ + dev->maclocal[1] = 0x80; + dev->maclocal[2] = 0xC8; + rom = NULL; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CLEAR_IRQ); + dp8390_set_id(dev->dp8390, 0x50, 0x70); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); + break; + case NE2K_RTL8019AS: case NE2K_RTL8029AS: dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; @@ -1043,7 +1059,7 @@ nic_init(const device_t *info) * 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) + if ((dev->board < NE2K_RTL8019AS) && (dev->board != NE2K_ETHERNEXT_MC)) nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ @@ -1108,9 +1124,44 @@ nic_init(const device_t *info) 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)); + const char *pnp_rom_file = NULL; + int pnp_rom_len = 0x4a; + switch (dev->board) { + case NE2K_RTL8019AS: + pnp_rom_file = "roms/network/rtl8019as/RTL8019A.BIN"; + break; - 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); + case NE2K_DE220P: + pnp_rom_file = "roms/network/de220p/dlk2201a.bin"; + pnp_rom_len = 0x43; + break; + + default: + break; + } + + uint8_t *pnp_rom = NULL; + if (pnp_rom_file) { + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + if (fp) { + if (fread(&dev->eeprom[0x12], 1, pnp_rom_len, fp) == pnp_rom_len) + pnp_rom = &dev->eeprom[0x12]; + fclose(fp); + } + } + + switch (info->local) { + case NE2K_RTL8019AS: + case NE2K_DE220P: + dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len, + nic_pnp_config_changed, nic_pnp_csn_changed, + nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, + dev); + break; + + default: + break; + } } } @@ -1137,6 +1188,18 @@ nic_close(void *priv) free(dev); } +static int +rtl8019as_available(void) +{ + return rom_present("roms/network/rtl8019as/RTL8019A.BIN"); +} + +static int +de220p_available(void) +{ + return rom_present("roms/network/de220p/dlk2201a.bin"); +} + // clang-format off static const device_config_t ne1000_config[] = { { @@ -1148,12 +1211,11 @@ static const device_config_t ne1000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "0x280", .value = 0x280 }, + /* Source: Windows 95 .INF file. */ { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, - { .description = "0x380", .value = 0x380 }, { .description = "" } }, }, @@ -1166,12 +1228,71 @@ static const device_config_t ne1000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { + /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t ne1000_compat_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .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 = "0x2e0", .value = 0x2e0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "0x3a0", .value = 0x3a0 }, + { .description = "0x3c0", .value = 0x3c0 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .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 10", .value = 10 }, - { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 9", .value = 9 }, { .description = "" } }, }, @@ -1195,12 +1316,85 @@ static const device_config_t ne2000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { + /* Source: Windows 95 .INF file. */ + { .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 = { + /* Source: Windows 95 .INF file. */ + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .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 ne2000_compat_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .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 = "0x2e0", .value = 0x2e0 }, { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, { .description = "0x380", .value = 0x380 }, + { .description = "0x3a0", .value = 0x3a0 }, + { .description = "0x3c0", .value = 0x3c0 }, + { .description = "0x3e0", .value = 0x3e0 }, { .description = "" } }, }, @@ -1213,12 +1407,18 @@ static const device_config_t ne2000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "IRQ 2", .value = 2 }, + /* Source: Windows 95 .INF file - not giving impossible IRQ's + such as 6, 8, or 13. */ { .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 = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, { .description = "" } }, }, @@ -1291,7 +1491,7 @@ static const device_config_t mca_mac_config[] = { const device_t ne1000_device = { .name = "Novell NE1000", - .internal_name = "ne1k", + .internal_name = "novell_ne1k", .flags = DEVICE_ISA, .local = NE2K_NE1000, .init = nic_init, @@ -1303,9 +1503,23 @@ const device_t ne1000_device = { .config = ne1000_config }; +const device_t ne1000_compat_device = { + .name = "NE1000 Compatible", + .internal_name = "ne1k", + .flags = DEVICE_ISA, + .local = NE2K_NE1000_COMPAT, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne1000_compat_config +}; + const device_t ne2000_device = { .name = "Novell NE2000", - .internal_name = "ne2k", + .internal_name = "novell_ne2k", .flags = DEVICE_ISA | DEVICE_AT, .local = NE2K_NE2000, .init = nic_init, @@ -1317,6 +1531,20 @@ const device_t ne2000_device = { .config = ne2000_config }; +const device_t ne2000_compat_device = { + .name = "NE2000 Compatible", + .internal_name = "ne2k", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_NE2000_COMPAT, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne2000_compat_config +}; + const device_t ethernext_mc_device = { .name = "NetWorth EtherNext/MC", .internal_name = "ethernextmc", @@ -1339,7 +1567,21 @@ const device_t rtl8019as_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + { .available = rtl8019as_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rtl8019as_config +}; + +const device_t de220p_device = { + .name = "D-Link DE-220P", + .internal_name = "de220p", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_DE220P, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = de220p_available }, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8019as_config diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index e1747580b..852191c55 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -365,7 +365,13 @@ net_pcap_prepare(netdev_t *list) /* Try loading the DLL. */ #ifdef _WIN32 + /* Add the Npcap directory to the DLL search path. */ + char npcap_dir[512]; + GetSystemDirectoryA(npcap_dir, 480); + strcat(npcap_dir, "\\Npcap"); + SetDllDirectoryA(npcap_dir); libpcap_handle = dynld_module("wpcap.dll", pcap_imports); + SetDllDirectoryA(NULL); /* reset the DLL search path */ #elif defined __APPLE__ libpcap_handle = dynld_module("libpcap.dylib", pcap_imports); #else @@ -494,7 +500,7 @@ net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char * pcap_log("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", 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) )", + "( ((ether broadcast) or (ether multicast) 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) { diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index ab761acf3..1e28c5846 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -787,8 +787,9 @@ static int ladr_match(nic_t *dev, const uint8_t *buf, UNUSED(size_t size)) { const struct ether_header *hdr = (const struct ether_header *) buf; + uint64_t *p = (uint64_t *) &dev->aCSR[8]; - if ((hdr->ether_dhost[0] & 0x01) && ((uint64_t *) &dev->aCSR[8])[0] != 0LL) { + if ((hdr->ether_dhost[0] & 0x01) && p[0] != 0LL) { int index; uint8_t ladr[8]; ladr[0] = dev->aCSR[8] & 0xff; @@ -866,7 +867,7 @@ pcnetSoftReset(nic_t *dev) case DEV_AM79C960_VLB: case DEV_AM79C961: dev->aCSR[88] = 0x3003; - dev->aCSR[89] = 0x0262; + dev->aCSR[89] = 0x0000; break; default: @@ -2896,7 +2897,7 @@ pcnet_init(const device_t *info) dev = malloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); dev->name = info->name; - dev->board = info->local; + dev->board = info->local & 0xff; dev->is_pci = !!(info->flags & DEVICE_PCI); dev->is_vlb = !!(info->flags & DEVICE_VLB); @@ -2997,7 +2998,10 @@ pcnet_init(const device_t *info) pcnet_pci_regs[0x04] = 3; /* 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); + if (info->local & 0x0100) + pci_add_card(PCI_ADD_NETWORK, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); + else + 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; @@ -3101,9 +3105,12 @@ static const device_config_t pcnet_isa_config[] = { { .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 = "IRQ 15", .value = 15 }, { .description = "" } }, }, @@ -3116,6 +3123,7 @@ static const device_config_t pcnet_isa_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { + { .description = "DMA 0", .value = 0 }, { .description = "DMA 3", .value = 3 }, { .description = "DMA 5", .value = 5 }, { .description = "DMA 6", .value = 6 }, @@ -3162,9 +3170,12 @@ static const device_config_t pcnet_vlb_config[] = { { .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 = "IRQ 15", .value = 15 }, { .description = "" } }, }, @@ -3262,3 +3273,17 @@ const device_t pcnet_am79c973_device = { .force_redraw = NULL, .config = pcnet_pci_config }; + +const device_t pcnet_am79c973_onboard_device = { + .name = "AMD PCnet-FAST III", + .internal_name = "pcnetfast_onboard", + .flags = DEVICE_PCI, + .local = DEV_AM79C973 | 0x0100, + .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 f622d455b..8b0bf460c 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -26,7 +26,6 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/language.h> #include <86box/lpt.h> #include <86box/timer.h> #include <86box/pit.h> @@ -34,7 +33,6 @@ #include <86box/thread.h> #include <86box/timer.h> #include <86box/network.h> -#include <86box/net_plip.h> #include <86box/plat_unused.h> enum { diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index d1e14fb12..a7c007115 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -39,10 +39,10 @@ #include <86box/device.h> #include <86box/thread.h> #include <86box/network.h> +#include <86box/net_eeprom_nmc93cxx.h> #include <86box/bswap.h> #include <86box/nvr.h> #include "cpu.h" -#include <86box/net_rtl8139.h> #include <86box/plat_unused.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ @@ -307,6 +307,8 @@ enum CSCRBits { #endif enum CSCRBits { CSCR_Testfun = 1 << 15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ + CSCR_Cable_Changed = 1 << 11, /* Undocumented: 1 = Cable status changed, 0 = No change */ + CSCR_Cable = 1 << 10, /* Undocumented: 1 = Cable connected, 0 = Cable disconnected */ CSCR_LD = 1 << 9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ CSCR_HEART_BIT = 1 << 8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ CSCR_JBEN = 1 << 7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ @@ -351,44 +353,6 @@ enum chip_flags { #define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139CPLUS -/* Size is 64 * 16bit words */ -#define EEPROM_9346_ADDR_BITS 6 -#define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS) -#define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1) - -enum Chip9346Operation { - Chip9346_op_mask = 0xc0, /* 10 zzzzzz */ - Chip9346_op_read = 0x80, /* 10 AAAAAA */ - Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */ - Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */ - Chip9346_op_write_enable = 0x30, /* 00 11zzzz */ - Chip9346_op_write_all = 0x10, /* 00 01zzzz */ - Chip9346_op_write_disable = 0x00, /* 00 00zzzz */ -}; - -enum Chip9346Mode { - Chip9346_none = 0, - Chip9346_enter_command_mode, - Chip9346_read_command, - Chip9346_data_read, /* from output register */ - Chip9346_data_write, /* to input register, then to contents at specified address */ - Chip9346_data_write_all, /* to input register, then filling contents */ -}; - -typedef struct EEprom9346 { - uint16_t contents[EEPROM_9346_SIZE]; - int mode; - uint32_t tick; - uint8_t address; - uint16_t input; - uint16_t output; - - uint8_t eecs; - uint8_t eesk; - uint8_t eedi; - uint8_t eedo; -} EEprom9346; - #pragma pack(push, 1) typedef struct RTL8139TallyCounters { /* Tally counters */ @@ -476,8 +440,6 @@ struct RTL8139State { uint32_t RxRingAddrLO; uint32_t RxRingAddrHI; - EEprom9346 eeprom; - uint32_t TCTR; uint32_t TimerInt; int64_t TCTR_base; @@ -490,6 +452,8 @@ struct RTL8139State { int cplus_txbuffer_len; int cplus_txbuffer_offset; + uint32_t mem_base; + /* PCI interrupt timer */ pc_timer_t timer; @@ -497,190 +461,14 @@ struct RTL8139State { /* Support migration to/from old versions */ int rtl8139_mmio_io_addr_dummy; + + nmc93cxx_eeprom_t *eeprom; + uint8_t eeprom_data[128]; }; /* Writes tally counters to memory via DMA */ static void RTL8139TallyCounters_dma_write(RTL8139State *s, uint32_t tc_addr); -static void -prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) -{ - rtl8139_log("eeprom command 0x%02x\n", command); - - switch (command & Chip9346_op_mask) { - case Chip9346_op_read: - { - eeprom->address = command & EEPROM_9346_ADDR_MASK; - eeprom->output = eeprom->contents[eeprom->address]; - eeprom->eedo = 0; - eeprom->tick = 0; - eeprom->mode = Chip9346_data_read; - rtl8139_log("eeprom read from address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); - } - break; - - case Chip9346_op_write: - { - eeprom->address = command & EEPROM_9346_ADDR_MASK; - eeprom->input = 0; - eeprom->tick = 0; - eeprom->mode = Chip9346_none; /* Chip9346_data_write */ - rtl8139_log("eeprom begin write to address 0x%02x\n", - eeprom->address); - } - break; - default: - eeprom->mode = Chip9346_none; - switch (command & Chip9346_op_ext_mask) { - case Chip9346_op_write_enable: - rtl8139_log("eeprom write enabled\n"); - break; - case Chip9346_op_write_all: - rtl8139_log("eeprom begin write all\n"); - break; - case Chip9346_op_write_disable: - rtl8139_log("eeprom write disabled\n"); - break; - - default: - break; - } - break; - } -} - -static void -prom9346_shift_clock(EEprom9346 *eeprom) -{ - int bit = eeprom->eedi ? 1 : 0; - - ++eeprom->tick; - - rtl8139_log("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, - eeprom->eedo); - - switch (eeprom->mode) { - case Chip9346_enter_command_mode: - if (bit) { - eeprom->mode = Chip9346_read_command; - eeprom->tick = 0; - eeprom->input = 0; - rtl8139_log("eeprom: +++ synchronized, begin command read\n"); - } - break; - - case Chip9346_read_command: - eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 8) { - prom9346_decode_command(eeprom, eeprom->input & 0xff); - } - break; - - case Chip9346_data_read: - eeprom->eedo = (eeprom->output & 0x8000) ? 1 : 0; - eeprom->output <<= 1; - if (eeprom->tick == 16) { -#if 1 - // the FreeBSD drivers (rl and re) don't explicitly toggle - // CS between reads (or does setting Cfg9346 to 0 count too?), - // so we need to enter wait-for-command state here - eeprom->mode = Chip9346_enter_command_mode; - eeprom->input = 0; - eeprom->tick = 0; - - rtl8139_log("eeprom: +++ end of read, awaiting next command\n"); -#else - // original behaviour - ++eeprom->address; - eeprom->address &= EEPROM_9346_ADDR_MASK; - eeprom->output = eeprom->contents[eeprom->address]; - eeprom->tick = 0; - - rtl8139_log("eeprom: +++ read next address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->output); -#endif - } - break; - - case Chip9346_data_write: - eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 16) { - rtl8139_log("eeprom write to address 0x%02x data=0x%04x\n", - eeprom->address, eeprom->input); - - eeprom->contents[eeprom->address] = eeprom->input; - eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */ - eeprom->tick = 0; - eeprom->input = 0; - } - break; - - case Chip9346_data_write_all: - eeprom->input = (eeprom->input << 1) | (bit & 1); - if (eeprom->tick == 16) { - for (int i = 0; i < EEPROM_9346_SIZE; i++) { - eeprom->contents[i] = eeprom->input; - } - rtl8139_log("eeprom filled with data=0x%04x\n", eeprom->input); - - eeprom->mode = Chip9346_enter_command_mode; - eeprom->tick = 0; - eeprom->input = 0; - } - break; - - default: - break; - } -} - -static int -prom9346_get_wire(RTL8139State *s) -{ - const EEprom9346 *eeprom = &s->eeprom; - if (!eeprom->eecs) - return 0; - - return eeprom->eedo; -} - -/* FIXME: This should be merged into/replaced by eeprom93xx.c. */ -static void -prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi) -{ - EEprom9346 *eeprom = &s->eeprom; - uint8_t old_eecs = eeprom->eecs; - uint8_t old_eesk = eeprom->eesk; - - eeprom->eecs = eecs; - eeprom->eesk = eesk; - eeprom->eedi = eedi; - - rtl8139_log("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n", eeprom->eecs, - eeprom->eesk, eeprom->eedi, eeprom->eedo); - - if (!old_eecs && eecs) { - /* Synchronize start */ - eeprom->tick = 0; - eeprom->input = 0; - eeprom->output = 0; - eeprom->mode = Chip9346_enter_command_mode; - - rtl8139_log("=== eeprom: begin access, enter command mode\n"); - } - - if (!eecs) { - rtl8139_log("=== eeprom: end access\n"); - return; - } - - if (!old_eesk && eesk) { - /* SK front rules */ - prom9346_shift_clock(eeprom); - } -} - static void rtl8139_update_irq(RTL8139State *s) { @@ -1434,9 +1222,8 @@ rtl8139_IntrMitigate_read(UNUSED(RTL8139State *s)) static int rtl8139_config_writable(RTL8139State *s) { - if ((s->Cfg9346 & Chip9346_op_mask) == Cfg9346_ConfigWrite) { + if ((s->Cfg9346 & 0xc0) == 0xc0) return 1; - } rtl8139_log("Configuration registers are write-protected\n"); @@ -1518,10 +1305,10 @@ rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val) if (opmode == 0x80) { /* eeprom access */ - int eecs = (eeprom_val & 0x08) ? 1 : 0; - int eesk = (eeprom_val & 0x04) ? 1 : 0; - int eedi = (eeprom_val & 0x02) ? 1 : 0; - prom9346_set_wire(s, eecs, eesk, eedi); + nmc93cxx_eeprom_write(s->eeprom, + !!(eeprom_val & 0x08), + !!(eeprom_val & 0x04), + !!(eeprom_val & 0x02)); } else if (opmode == 0x40) { /* Reset. */ val = 0; @@ -1539,13 +1326,10 @@ rtl8139_Cfg9346_read(RTL8139State *s) uint32_t opmode = ret & 0xc0; if (opmode == 0x80) { - /* eeprom access */ - int eedo = prom9346_get_wire(s); - if (eedo) { + if (nmc93cxx_eeprom_read(s->eeprom)) ret |= 0x01; - } else { + else ret &= ~0x01; - } } rtl8139_log("Cfg9346 read val=0x%02x\n", ret); @@ -2502,7 +2286,17 @@ rtl8139_TSAD_read(RTL8139State *s) static uint16_t rtl8139_CSCR_read(RTL8139State *s) { - uint16_t ret = s->CSCR; + static uint16_t old_ret = 0xffff; + uint16_t ret = s->CSCR | + ((net_cards_conf[s->nic->card_num].link_state & NET_LINK_DOWN) ? 0 : CSCR_Cable); + + if (old_ret != 0xffff) { + ret &= ~CSCR_Cable_Changed; + if ((ret ^ old_ret) & CSCR_Cable) + ret |= CSCR_Cable_Changed; + } + + old_ret = ret; rtl8139_log("CSCR read val=0x%04x\n", ret); @@ -2953,6 +2747,13 @@ rtl8139_io_readb(uint32_t addr, void *priv) rtl8139_log("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); break; + case CSCR: + ret = rtl8139_CSCR_read(s) & 0xff; + break; + case CSCR + 1: + ret = rtl8139_CSCR_read(s) >> 8; + break; + default: rtl8139_log("not implemented read(b) addr=0x%x\n", addr); ret = 0; @@ -3118,37 +2919,136 @@ rtl8139_io_readl(uint32_t addr, void *priv) static uint32_t rtl8139_io_readl_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readl(addr, priv); + uint32_t ret = 0xffffffff; + + ret = rtl8139_io_readl(addr, priv); + + rtl8139_log("[%04X:%08X] [RLI] %04X = %08X\n", CS, cpu_state.pc, addr, ret); + + return ret; } static uint16_t rtl8139_io_readw_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readw(addr, priv); + uint16_t ret = 0xffff; + + ret = rtl8139_io_readw(addr, priv); + + rtl8139_log("[%04X:%08X] [RWI] %04X = %04X\n", CS, cpu_state.pc, addr, ret); + + return ret; } static uint8_t rtl8139_io_readb_ioport(uint16_t addr, void *priv) { - return rtl8139_io_readb(addr, priv); + uint8_t ret = 0xff; + + ret = rtl8139_io_readb(addr, priv); + + rtl8139_log("[%04X:%08X] [RBI] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; } static void rtl8139_io_writel_ioport(uint16_t addr, uint32_t val, void *priv) { - return rtl8139_io_writel(addr, val, priv); + rtl8139_log("[%04X:%08X] [WLI] %04X = %08X\n", CS, cpu_state.pc, addr, val); + + rtl8139_io_writel(addr, val, priv); } static void rtl8139_io_writew_ioport(uint16_t addr, uint16_t val, void *priv) { - return rtl8139_io_writew(addr, val, priv); + rtl8139_log("[%04X:%08X] [WWI] %04X = %04X\n", CS, cpu_state.pc, addr, val); + + rtl8139_io_writew(addr, val, priv); } static void rtl8139_io_writeb_ioport(uint16_t addr, uint8_t val, void *priv) { - return rtl8139_io_writeb(addr, val, priv); + rtl8139_log("[%04X:%08X] [WBI] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + rtl8139_io_writeb(addr, val, priv); +} + +static uint32_t +rtl8139_io_readl_mem(uint32_t addr, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + uint32_t ret = 0xffffffff; + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + ret = rtl8139_io_readl(addr, priv); + + rtl8139_log("[%04X:%08X] [RLM] %08X = %08X\n", CS, cpu_state.pc, addr, ret); + + return ret; + } + +static uint16_t +rtl8139_io_readw_mem(uint32_t addr, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + uint16_t ret = 0xffff; + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + ret = rtl8139_io_readw(addr, priv); + + rtl8139_log("[%04X:%08X] [RWM] %08X = %04X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +static uint8_t +rtl8139_io_readb_mem(uint32_t addr, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + uint8_t ret = 0xff; + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + ret = rtl8139_io_readb(addr, priv); + + rtl8139_log("[%04X:%08X] [RBM] %08X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +static void +rtl8139_io_writel_mem(uint32_t addr, uint32_t val, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + + rtl8139_log("[%04X:%08X] [WLM] %08X = %08X\n", CS, cpu_state.pc, addr, val); + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + rtl8139_io_writel(addr, val, priv); +} + +static void +rtl8139_io_writew_mem(uint32_t addr, uint16_t val, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + + rtl8139_log("[%04X:%08X] [WWM] %08X = %04X\n", CS, cpu_state.pc, addr, val); + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + rtl8139_io_writew(addr, val, priv); +} + +static void +rtl8139_io_writeb_mem(uint32_t addr, uint8_t val, void *priv) +{ + RTL8139State *s = (RTL8139State *) priv; + + rtl8139_log("[%04X:%08X] [WBM] %08X = %02X\n", CS, cpu_state.pc, addr, val); + + if ((addr >= s->mem_base) && (addr < (s->mem_base + 0xff))) + rtl8139_io_writeb(addr, val, priv); } static int @@ -3223,6 +3123,12 @@ rtl8139_pci_read(UNUSED(int func), int addr, void *priv) return 1; case 0x14: return 0; + case 0x15: +#ifdef USE_256_BYTE_BAR + return s->pci_conf[addr & 0xFF]; +#else + return s->pci_conf[addr & 0xFF] & 0xf0; +#endif case 0x2c: return 0xEC; case 0x2d: @@ -3275,19 +3181,34 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); s->pci_conf[addr & 0xFF] = val; + rtl8139_log("New I/O base: %04X\n", s->pci_conf[0x11] << 8); if (s->pci_conf[0x4] & PCI_COMMAND_IO) io_sethandler((s->pci_conf[0x11] << 8), 256, rtl8139_io_readb_ioport, rtl8139_io_readw_ioport, rtl8139_io_readl_ioport, rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); break; +#ifndef USE_256_BYTE_BAR case 0x14: +#endif case 0x15: case 0x16: case 0x17: s->pci_conf[addr & 0xFF] = val; + s->mem_base = (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | + (s->pci_conf[0x17] << 24); +#ifndef USE_256_BYTE_BAR + s->mem_base &= 0xfffff000; +#endif + rtl8139_log("New memory base: %08X\n", s->mem_base); if (s->pci_conf[0x4] & PCI_COMMAND_MEM) - mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 256); +#ifdef USE_256_BYTE_BAR + mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | + (s->pci_conf[0x17] << 24), 256); +#else + mem_mapping_set_addr(&s->bar_mem, ((s->pci_conf[0x15] & 0xf0) << 8) | + (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 4096); +#endif break; case 0x3c: s->pci_conf[addr & 0xFF] = val; @@ -3299,42 +3220,42 @@ static void * nic_init(const device_t *info) { RTL8139State *s = calloc(1, sizeof(RTL8139State)); - FILE *fp = NULL; + nmc93cxx_eeprom_params_t params; char eeprom_filename[1024] = { 0 }; - uint8_t *mac_bytes; - uint32_t mac; + char filename[1024] = { 0 }; + uint8_t *mac_bytes; + uint16_t *eep_data; + uint32_t mac; - mem_mapping_add(&s->bar_mem, 0, 0, rtl8139_io_readb, rtl8139_io_readw, rtl8139_io_readl, rtl8139_io_writeb, rtl8139_io_writew, rtl8139_io_writel, NULL, MEM_MAPPING_EXTERNAL, s); + mem_mapping_add(&s->bar_mem, 0, 0, + rtl8139_io_readb_mem, rtl8139_io_readw_mem, rtl8139_io_readl_mem, + rtl8139_io_writeb_mem, rtl8139_io_writew_mem, rtl8139_io_writel_mem, + NULL, MEM_MAPPING_EXTERNAL, s); pci_add_card(PCI_ADD_NORMAL, rtl8139_pci_read, rtl8139_pci_write, s, &s->pci_slot); s->inst = device_get_instance(); snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); - fp = nvr_fopen(eeprom_filename, "rb"); - if (fp) { - fread(s->eeprom.contents, 2, 64, fp); - fclose(fp); - fp = NULL; - } else { - /* prepare eeprom */ - s->eeprom.contents[0] = 0x8129; + eep_data = (uint16_t *) s->eeprom_data; - /* PCI vendor and device ID should be mirrored here */ - s->eeprom.contents[1] = 0x10EC; - s->eeprom.contents[2] = 0x8139; + /* prepare eeprom */ + eep_data[0] = 0x8129; - /* XXX: Get proper MAC addresses from real EEPROM dumps. OID taken from net_ne2000.c */ + /* PCI vendor and device ID should be mirrored here */ + eep_data[1] = 0x10EC; + eep_data[2] = 0x8139; + + /* XXX: Get proper MAC addresses from real EEPROM dumps. OID taken from net_ne2000.c */ #ifdef USE_REALTEK_OID - s->eeprom.contents[7] = 0xe000; - s->eeprom.contents[8] = 0x124c; + eep_data[7] = 0xe000; + eep_data[8] = 0x124c; #else - s->eeprom.contents[7] = 0x1400; - s->eeprom.contents[8] = 0x122a; + eep_data[7] = 0x1400; + eep_data[8] = 0x122a; #endif - s->eeprom.contents[9] = 0x1413; - } + eep_data[9] = 0x1413; - mac_bytes = (uint8_t *) &(s->eeprom.contents[7]); + mac_bytes = (uint8_t *) &(eep_data[7]); /* See if we have a local MAC address configured. */ mac = device_get_config_mac("mac", -1); @@ -3355,7 +3276,20 @@ nic_init(const device_t *info) mac_bytes[5] = (mac & 0xff); } - s->nic = network_attach(s, (uint8_t *) &s->eeprom.contents[7], rtl8139_do_receive, rtl8139_set_link_status); + for (uint32_t i = 0; i < 6; i++) + s->phys[MAC0 + i] = mac_bytes[i]; + + params.nwords = 64; + params.default_content = (uint16_t *) s->eeprom_data; + params.filename = filename; + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); + s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); + if (!s->eeprom) { + free(s); + return NULL; + } + + s->nic = network_attach(s, (uint8_t *) &s->phys[MAC0], rtl8139_do_receive, rtl8139_set_link_status); timer_add(&s->timer, rtl8139_timer, s, 0); timer_on_auto(&s->timer, 1000000.0 / cpu_pci_speed); @@ -3369,17 +3303,6 @@ nic_init(const device_t *info) static void nic_close(void *priv) { - const RTL8139State *s = (RTL8139State *) priv; - FILE *fp = NULL; - char eeprom_filename[1024] = { 0 }; - - snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_rtl8139c_plus_%d.nvr", s->inst); - fp = nvr_fopen(eeprom_filename, "wb"); - if (fp) { - fwrite(s->eeprom.contents, 2, 64, fp); - fclose(fp); - fp = NULL; - } free(priv); } diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 6aff76a90..599ee896d 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -37,6 +37,7 @@ #include <86box/ini.h> #include <86box/config.h> #include <86box/video.h> +#include <86box/bswap.h> #define _SSIZE_T_DEFINED #include @@ -76,6 +77,29 @@ typedef struct net_slirp_t { #endif } net_slirp_t; +/* Pulled off from libslirp code. This is only needed for modem. */ +#pragma pack(push, 1) +struct arphdr_local { + unsigned char h_dest[6]; /* destination eth addr */ + unsigned char h_source[6]; /* source ether addr */ + unsigned short h_proto; /* packet type ID field */ + + 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... + */ + uint8_t ar_sha[6]; /* sender hardware address */ + uint32_t ar_sip; /* sender IP address */ + uint8_t ar_tha[6]; /* target hardware address */ + uint32_t ar_tip; /* target IP address */ +}; +#pragma pack(pop) + #ifdef ENABLE_SLIRP_LOG int slirp_do_log = ENABLE_SLIRP_LOG; @@ -455,6 +479,32 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv #ifdef _WIN32 slirp->sock_event = CreateEvent(NULL, FALSE, FALSE, NULL); #endif + + if (!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem")) { + /* Send a gratuitous ARP here to make SLiRP work properly with SLIP connections. */ + struct arphdr_local arphdr; + /* ARP part. */ + arphdr.ar_hrd = bswap16(1); + arphdr.ar_pro = bswap16(0x0800); + arphdr.ar_hln = 6; + arphdr.ar_pln = 4; + arphdr.ar_op = bswap16(1); + memcpy(&arphdr.ar_sha, mac_addr, 6); + memcpy(&arphdr.ar_tha, mac_addr, 6); + arphdr.ar_sip = dhcp.s_addr; + arphdr.ar_tip = dhcp.s_addr; + + /* Ethernet header part. */ + arphdr.h_proto = bswap16(0x0806); + memset(arphdr.h_dest, 0xff, 6); + memset(arphdr.h_source, 0x52, 6); + arphdr.h_source[2] = 0x0a; + arphdr.h_source[3] = 0x00; + arphdr.h_source[4] = slirp_card_num; + arphdr.h_source[5] = 2; + slirp_input(slirp->slirp, (const uint8_t *)&arphdr, sizeof(struct arphdr_local)); + } + slirp_log("SLiRP: creating thread...\n"); slirp->poll_tid = thread_create(net_slirp_thread, slirp); diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index b74b345bc..e34327eb5 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -32,7 +32,6 @@ #include <86box/thread.h> #include <86box/network.h> #include <86box/net_eeprom_nmc93cxx.h> -#include <86box/net_tulip.h> #include <86box/bswap.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -323,6 +322,9 @@ struct TULIPState { uint32_t mii_word; uint32_t mii_bitcnt; + /* 21040 ROM read address. */ + uint8_t rom_read_addr; + uint32_t current_rx_desc; uint32_t current_tx_desc; @@ -666,6 +668,9 @@ tulip_mii(TULIPState *s) static uint32_t tulip_csr9_read(TULIPState *s) { + if (s->device_info->local == 3) { + return s->eeprom_data[s->rom_read_addr++]; + } if (s->csr[9] & CSR9_SR) { if (nmc93cxx_eeprom_read(s->eeprom)) { s->csr[9] |= CSR9_SR_DO; @@ -698,6 +703,10 @@ tulip_read(uint32_t addr, void *opaque) break; case CSR(12): + if (s->device_info->local == 3) { + data = 0; + break; + } /* Fake autocompletion complete until we have PHY emulation */ data = 5 << CSR12_ANS_SHIFT; break; @@ -884,8 +893,10 @@ tulip_reset(void *priv) s->csr[13] = 0xffff0000; s->csr[14] = 0xffffffff; s->csr[15] = 0x8ff00000; - s->subsys_id = eeprom_data[1]; - s->subsys_ven_id = eeprom_data[0]; + if (s->device_info->local != 3) { + s->subsys_id = eeprom_data[1]; + s->subsys_ven_id = eeprom_data[0]; + } } static void @@ -955,12 +966,16 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) break; case CSR(9): - tulip_csr9_write(s, s->csr[9], data); - /* don't clear MII read data */ - s->csr[9] &= CSR9_MDI; - s->csr[9] |= (data & ~CSR9_MDI); - tulip_mii(s); - s->old_csr9 = s->csr[9]; + if (s->device_info->local != 3) { + tulip_csr9_write(s, s->csr[9], data); + /* don't clear MII read data */ + s->csr[9] &= CSR9_MDI; + s->csr[9] |= (data & ~CSR9_MDI); + tulip_mii(s); + s->old_csr9 = s->csr[9]; + } else { + s->rom_read_addr = 0; + } break; case CSR(10): @@ -978,6 +993,11 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) case CSR(13): s->csr[13] = data; + if (s->device_info->local == 3 && (data & 0x4)) { + s->csr[13] = 0x8f01; + s->csr[14] = 0xfffd; + s->csr[15] = 0; + } break; case CSR(14): @@ -1017,37 +1037,55 @@ tulip_writel_io(uint16_t addr, uint32_t data, void *opaque) static void tulip_mem_writeb(uint32_t addr, uint8_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static void tulip_mem_writew(uint32_t addr, uint16_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static void tulip_mem_writel(uint32_t addr, uint32_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static uint8_t tulip_mem_readb(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint8_t ret = 0xff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint16_t tulip_mem_readw(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint16_t ret = 0xffff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint32_t tulip_mem_readl(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint32_t ret = 0xffffffff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint8_t @@ -1141,7 +1179,9 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) ret = 0x10; break; case 0x02: - if (s->device_info->local) + if (s->device_info->local == 3) + ret = 0x02; + else if (s->device_info->local) ret = 0x09; else ret = 0x19; @@ -1185,11 +1225,17 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) case 0x13: ret = tulip_pci_bar[0].addr_regs[3]; break; +#ifdef USE_128_BYTE_BAR case 0x14: ret = (tulip_pci_bar[1].addr_regs[0] & 0x80); break; +#endif case 0x15: +#ifdef USE_128_BYTE_BAR ret = tulip_pci_bar[1].addr_regs[1]; +#else + ret = tulip_pci_bar[1].addr_regs[1] & 0xf0; +#endif break; case 0x16: ret = tulip_pci_bar[1].addr_regs[2]; @@ -1229,6 +1275,7 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) break; case 0x3E: case 0x3F: + case 0x41: ret = s->pci_conf[addr & 0xff]; break; } @@ -1259,7 +1306,7 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) //pclog("PCI write cmd: IOBase=%04x, MMIOBase=%08x, val=%02x.\n", s->PCIBase, s->MMIOBase, s->pci_conf[0x04]); mem_mapping_disable(&s->memory); if ((s->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) - mem_mapping_set_addr(&s->memory, s->MMIOBase, 128); + mem_mapping_enable(&s->memory); break; case 0x05: s->pci_conf[0x05] = val & 1; @@ -1284,18 +1331,28 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) priv); } break; +#ifndef USE_128_BYTE_BAR case 0x14: +#endif case 0x15: case 0x16: case 0x17: mem_mapping_disable(&s->memory); tulip_pci_bar[1].addr_regs[addr & 3] = val; +#ifdef USE_128_BYTE_BAR tulip_pci_bar[1].addr &= 0xffffff80; +#else + tulip_pci_bar[1].addr &= 0xfffff000; +#endif s->MMIOBase = tulip_pci_bar[1].addr; if (s->pci_conf[0x4] & PCI_COMMAND_MEM) { //pclog("PCI write=%02x, mmiobase=%08x, mmio?=%x.\n", addr, s->PCIBase, s->pci_conf[0x4] & PCI_COMMAND_MEM); if (s->MMIOBase != 0) +#ifdef USE_128_BYTE_BAR mem_mapping_set_addr(&s->memory, s->MMIOBase, 128); +#else + mem_mapping_set_addr(&s->memory, s->MMIOBase, 4096); +#endif } break; case 0x30: /* PCI_ROMBAR */ @@ -1319,6 +1376,7 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) return; case 0x3E: case 0x3F: + case 0x41: s->pci_conf[addr & 0xff] = val; return; } @@ -1336,7 +1394,7 @@ nic_init(const device_t *info) if (!s) return NULL; - if (info->local) { + if (info->local && info->local != 3) { s->bios_addr = 0xD0000; s->has_bios = device_get_config_int("bios"); } else { @@ -1344,152 +1402,222 @@ nic_init(const device_t *info) s->has_bios = 0; } +#ifdef USE_128_BYTE_BAR mem_mapping_add(&s->memory, 0x0fffff00, 128, tulip_mem_readb, tulip_mem_readw, tulip_mem_readl, tulip_mem_writeb, tulip_mem_writew, tulip_mem_writel, NULL, MEM_MAPPING_EXTERNAL, s); +#else + mem_mapping_add(&s->memory, 0x0ffff000, 4096, tulip_mem_readb, tulip_mem_readw, tulip_mem_readl, tulip_mem_writeb, tulip_mem_writew, tulip_mem_writel, NULL, MEM_MAPPING_EXTERNAL, s); +#endif mem_mapping_disable(&s->memory); s->device_info = info; - /*Subsystem Vendor ID*/ - s->eeprom_data[0] = info->local ? 0x25 : 0x11; - s->eeprom_data[1] = 0x10; + if (info->local != 3) { + if (info->local == 2) { + /*Subsystem Vendor ID*/ + s->eeprom_data[0] = 0x00; + s->eeprom_data[1] = 0x0a; - /*Subsystem ID*/ - s->eeprom_data[2] = info->local ? 0x10 : 0x0a; - s->eeprom_data[3] = info->local ? 0x03 : 0x50; + /*Subsystem ID*/ + s->eeprom_data[2] = 0x14; + s->eeprom_data[3] = 0x21; + } else { + /*Subsystem Vendor ID*/ + s->eeprom_data[0] = info->local ? 0x25 : 0x11; + s->eeprom_data[1] = 0x10; - /*Cardbus CIS Pointer low*/ - s->eeprom_data[4] = 0x00; - s->eeprom_data[5] = 0x00; + /*Subsystem ID*/ + s->eeprom_data[2] = info->local ? 0x10 : 0x0a; + s->eeprom_data[3] = info->local ? 0x03 : 0x50; + } - /*Cardbus CIS Pointer high*/ - s->eeprom_data[6] = 0x00; - s->eeprom_data[7] = 0x00; + /*Cardbus CIS Pointer low*/ + s->eeprom_data[4] = 0x00; + s->eeprom_data[5] = 0x00; - /*ID Reserved1*/ - for (int i = 0; i < 7; i++) - s->eeprom_data[8 + i] = 0x00; + /*Cardbus CIS Pointer high*/ + s->eeprom_data[6] = 0x00; + s->eeprom_data[7] = 0x00; - /*MiscHwOptions*/ - s->eeprom_data[15] = 0x00; + /*ID Reserved1*/ + for (int i = 0; i < 7; i++) + s->eeprom_data[8 + i] = 0x00; - /*ID_BLOCK_CRC*/ - tulip_idblock_crc((uint16_t *) s->eeprom_data); + /*MiscHwOptions*/ + s->eeprom_data[15] = 0x00; - /*Func0_HwOptions*/ - s->eeprom_data[17] = 0x00; + /*ID_BLOCK_CRC*/ + tulip_idblock_crc((uint16_t *) s->eeprom_data); - /*SROM Format Version 1, compatible with older guests*/ - s->eeprom_data[18] = 0x01; + /*Func0_HwOptions*/ + s->eeprom_data[17] = 0x00; - /*Controller Count*/ - s->eeprom_data[19] = 0x01; + /*SROM Format Version 1, compatible with older guests*/ + s->eeprom_data[18] = 0x01; - /*DEC OID*/ - s->eeprom_data[20] = 0x00; - s->eeprom_data[21] = 0x00; - s->eeprom_data[22] = 0xf8; + /*Controller Count*/ + s->eeprom_data[19] = 0x01; - if (info->local == 2) { - /* Microsoft VPC DEC Tulip. */ + /*DEC OID*/ s->eeprom_data[20] = 0x00; - s->eeprom_data[21] = 0x03; - s->eeprom_data[22] = 0x0f; - } + s->eeprom_data[21] = 0x00; + s->eeprom_data[22] = 0xf8; - /* See if we have a local MAC address configured. */ - mac = device_get_config_mac("mac", -1); + if (info->local == 2) { + /* Microsoft VPC DEC Tulip. */ + s->eeprom_data[20] = 0x00; + s->eeprom_data[21] = 0x03; + s->eeprom_data[22] = 0x0f; + } - /* Set up our BIA. */ - if (mac & 0xff000000) { - /* Generate new local MAC. */ - s->eeprom_data[23] = random_generate(); - s->eeprom_data[24] = random_generate(); - s->eeprom_data[25] = random_generate(); - mac = (((int) s->eeprom_data[23]) << 16); - mac |= (((int) s->eeprom_data[24]) << 8); - mac |= ((int) s->eeprom_data[25]); - device_set_config_mac("mac", mac); + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + s->eeprom_data[23] = random_generate(); + s->eeprom_data[24] = random_generate(); + s->eeprom_data[25] = random_generate(); + mac = (((int) s->eeprom_data[23]) << 16); + mac |= (((int) s->eeprom_data[24]) << 8); + mac |= ((int) s->eeprom_data[25]); + device_set_config_mac("mac", mac); + } else { + s->eeprom_data[23] = (mac >> 16) & 0xff; + s->eeprom_data[24] = (mac >> 8) & 0xff; + s->eeprom_data[25] = (mac & 0xff); + } + + /*Controller_0 Device_Number*/ + s->eeprom_data[26] = 0x00; + + /*Controller_0 Info Leaf_Offset*/ + s->eeprom_data[27] = 0x1e; + s->eeprom_data[28] = 0x00; + + /*Selected Connection Type, Powerup AutoSense and Dynamic AutoSense if the board supports it*/ + s->eeprom_data[30] = 0x00; + s->eeprom_data[31] = 0x08; + + if (info->local) { + /*General Purpose Control*/ + s->eeprom_data[32] = 0xff; + + /*Block Count*/ + s->eeprom_data[33] = 0x01; + + /*Extended Format (first part)*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[34] = 0x81; + + /*Block Type (first part)*/ + s->eeprom_data[35] = 0x01; + + /*Extended Format (second part) - Block Type 0 for 21140*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[36] = 0x85; + + /*Block Type (second part)*/ + s->eeprom_data[37] = 0x00; + + /*Media Code (0:5), EXT (6), Reserved (7)*/ + s->eeprom_data[38] = 0x01; + + /*General Purpose Data*/ + s->eeprom_data[39] = 0x00; + + /*Command*/ + s->eeprom_data[40] = 0x00; + s->eeprom_data[41] = 0x00; + } else { + /*SROM Format Version 3*/ + s->eeprom_data[18] = 0x03; + + /*Block Count*/ + s->eeprom_data[32] = 0x01; + + /*Extended Format - Block Type 2 for 21142/21143*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[33] = 0x86; + + /*Block Type*/ + s->eeprom_data[34] = 0x02; + + /*Media Code (0:5), EXT (6), Reserved (7)*/ + s->eeprom_data[35] = 0x01; + + /*General Purpose Control*/ + s->eeprom_data[36] = 0xff; + s->eeprom_data[37] = 0xff; + + /*General Purpose Data*/ + s->eeprom_data[38] = 0x00; + s->eeprom_data[39] = 0x00; + } + + s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff; + s->eeprom_data[127] = tulip_srom_crc(s->eeprom_data) >> 8; } else { - s->eeprom_data[23] = (mac >> 16) & 0xff; - s->eeprom_data[24] = (mac >> 8) & 0xff; - s->eeprom_data[25] = (mac & 0xff); + uint32_t checksum = 0; + /* 21040 is supposed to only have MAC address in its serial ROM if Linux is correct. */ + memset(s->eeprom_data, 0, sizeof(s->eeprom_data)); + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + /*DEC OID*/ + s->eeprom_data[0] = 0x00; + s->eeprom_data[1] = 0x00; + s->eeprom_data[2] = 0xF8; + if (mac & 0xff000000) { + /* Generate new local MAC. */ + s->eeprom_data[3] = random_generate(); + s->eeprom_data[4] = random_generate(); + s->eeprom_data[5] = random_generate(); + mac = (((int) s->eeprom_data[3]) << 16); + mac |= (((int) s->eeprom_data[4]) << 8); + mac |= ((int) s->eeprom_data[5]); + device_set_config_mac("mac", mac); + } else { + s->eeprom_data[3] = (mac >> 16) & 0xff; + s->eeprom_data[4] = (mac >> 8) & 0xff; + s->eeprom_data[5] = (mac & 0xff); + } + + /* Generate checksum. */ + checksum = (s->eeprom_data[0] * 256) | s->eeprom_data[1]; + checksum *= 2; + if (checksum > 65535) + checksum = checksum % 65535; + + /* 2nd pair. */ + checksum += (s->eeprom_data[2] * 256) | s->eeprom_data[3]; + if (checksum > 65535) + checksum = checksum % 65535; + checksum *= 2; + if (checksum > 65535) + checksum = checksum % 65535; + + /* 3rd pair. */ + checksum += (s->eeprom_data[4] * 256) | s->eeprom_data[5]; + if (checksum > 65535) + checksum = checksum % 65535; + + if (checksum >= 65535) + checksum = 0; + + s->eeprom_data[6] = (checksum >> 8) & 0xFF; + s->eeprom_data[7] = checksum & 0xFF; } - /*Controller_0 Device_Number*/ - s->eeprom_data[26] = 0x00; - - /*Controller_0 Info Leaf_Offset*/ - s->eeprom_data[27] = 0x1e; - s->eeprom_data[28] = 0x00; - - /*Selected Connection Type, Powerup AutoSense and Dynamic AutoSense if the board supports it*/ - s->eeprom_data[30] = 0x00; - s->eeprom_data[31] = 0x08; - - if (info->local) { - /*General Purpose Control*/ - s->eeprom_data[32] = 0xff; - - /*Block Count*/ - s->eeprom_data[33] = 0x01; - - /*Extended Format (first part)*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[34] = 0x81; - - /*Block Type (first part)*/ - s->eeprom_data[35] = 0x01; - - /*Extended Format (second part) - Block Type 0 for 21140*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[36] = 0x85; - - /*Block Type (second part)*/ - s->eeprom_data[37] = 0x00; - - /*Media Code (0:5), EXT (6), Reserved (7)*/ - s->eeprom_data[38] = 0x01; - - /*General Purpose Data*/ - s->eeprom_data[39] = 0x00; - - /*Command*/ - s->eeprom_data[40] = 0x00; - s->eeprom_data[41] = 0x00; - } else { - /*Block Count*/ - s->eeprom_data[32] = 0x01; - - /*Extended Format - Block Type 2 for 21142/21143*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[33] = 0x86; - - /*Block Type*/ - s->eeprom_data[34] = 0x02; - - /*Media Code (0:5), EXT (6), Reserved (7)*/ - s->eeprom_data[35] = 0x01; - - /*General Purpose Control*/ - s->eeprom_data[36] = 0xff; - s->eeprom_data[37] = 0xff; - - /*General Purpose Data*/ - s->eeprom_data[38] = 0x00; - s->eeprom_data[39] = 0x00; - } - - s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff; - s->eeprom_data[127] = tulip_srom_crc(s->eeprom_data) >> 8; - - params.nwords = 64; - params.default_content = (uint16_t *) s->eeprom_data; - params.filename = filename; - snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); - s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); - if (!s->eeprom) { - free(s); - return NULL; + if (info->local != 3) { + params.nwords = 64; + params.default_content = (uint16_t *) s->eeprom_data; + params.filename = filename; + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); + s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); + if (!s->eeprom) { + free(s); + return NULL; + } } tulip_pci_bar[0].addr_regs[0] = 1; @@ -1504,11 +1632,11 @@ nic_init(const device_t *info) tulip_pci_bar[2].addr = 0; mem_mapping_disable(&s->bios_rom.mapping); - eeprom_data = (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[0]; + eeprom_data = (info->local == 3) ? s->eeprom_data : (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[0]; //pclog("EEPROM Data Format=%02x, Count=%02x, MAC=%02x:%02x:%02x:%02x:%02x:%02x.\n", eeprom_data[0x12], eeprom_data[0x13], eeprom_data[0x14], eeprom_data[0x15], eeprom_data[0x16], eeprom_data[0x17], eeprom_data[0x18], eeprom_data[0x19]); memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); - s->nic = network_attach(s, &eeprom_data[20], tulip_receive, NULL); + s->nic = network_attach(s, &eeprom_data[(info->local == 3) ? 0 : 20], tulip_receive, NULL); pci_add_card(PCI_ADD_NORMAL, tulip_pci_read, tulip_pci_write, s, &s->pci_slot); tulip_reset(s); return s; @@ -1552,7 +1680,7 @@ static const device_config_t dec_tulip_21140_config[] = { // clang-format on const device_t dec_tulip_device = { - .name = "DE500A Fast Ethernet (DECchip 21143 \"Tulip\")", + .name = "DEC DE-500A Fast Ethernet (DECchip 21143 \"Tulip\")", .internal_name = "dec_21143_tulip", .flags = DEVICE_PCI, .local = 0, @@ -1592,3 +1720,17 @@ const device_t dec_tulip_21140_vpc_device = { .force_redraw = NULL, .config = dec_tulip_21140_config }; + +const device_t dec_tulip_21040_device = { + .name = "DEC DE-435 EtherWorks Turbo (DECchip 21040 \"Tulip\")", + .internal_name = "dec_21040_tulip", + .flags = DEVICE_PCI, + .local = 3, + .init = nic_init, + .close = nic_close, + .reset = tulip_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = dec_tulip_21143_config +}; diff --git a/src/network/net_vde.c b/src/network/net_vde.c index afeeaac9c..d783c9c9d 100644 --- a/src/network/net_vde.c +++ b/src/network/net_vde.c @@ -274,7 +274,7 @@ void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, c vde_args.group = 0; vde_args.port = 0; - vde_args.mode = 0; + vde_args.mode = 0700; // Allow the switch to connect back to our socket if it is run by the same user // We are calling vde_open_real(), not the vde_open() macro... if ((vde->vdeconn = f_vde_open(socket_name, VDE_DESCRIPTION, diff --git a/src/network/network.c b/src/network/network.c index 38af502b2..d0ebe8ef3 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -67,14 +67,9 @@ #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> -#include <86box/net_tulip.h> -#include <86box/net_rtl8139.h> #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN @@ -117,6 +112,9 @@ static const device_t *net_cards[] = { &threec503_device, &pcnet_am79c960_device, &pcnet_am79c961_device, + &de220p_device, + &ne1000_compat_device, + &ne2000_compat_device, &ne1000_device, &ne2000_device, &pcnet_am79c960_eb_device, @@ -136,7 +134,9 @@ static const device_t *net_cards[] = { &rtl8139c_plus_device, &dec_tulip_21140_device, &dec_tulip_21140_vpc_device, + &dec_tulip_21040_device, &pcnet_am79c960_vlb_device, + &modem_device, NULL }; @@ -454,6 +454,7 @@ netcard_t * network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state) { netcard_t *card = calloc(1, sizeof(netcard_t)); + int net_type = net_cards_conf[net_card_current].net_type; card->queued_pkt.data = calloc(1, NET_MAX_FRAME); card->card_drv = card_drv; card->rx = rx; @@ -470,7 +471,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin network_queue_init(&card->queues[i]); } - switch (net_cards_conf[net_card_current].net_type) { + if (!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem") && net_type >= NET_TYPE_PCAP) { + /* Force SLiRP here. Modem only operates on non-Ethernet frames. */ + net_type = NET_TYPE_SLIRP; + } + + switch (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); @@ -498,7 +504,7 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin 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)); + swprintf(tempmsg, sizeof_w(tempmsg), L"%ls:

%s

%ls", plat_get_string(STRING_NET_ERROR), net_drv_error, plat_get_string(STRING_NET_ERROR_DESC)); ui_msgbox(MBX_ERROR, tempmsg); net_cards_conf[net_card_current].net_type = NET_TYPE_NONE; } diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c deleted file mode 100644 index 1d3e39221..000000000 --- a/src/network/pcap_if.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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. - * - * Simple program to show usage of (Win)Pcap. - * - * Based on the "libpcap" examples. - * - * - * - * Authors: 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: - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#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 */ - -/* 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 dllimp_t pcap_imports[] = { - // 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]; -} 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; - 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); - } - - 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; -} - -/* Simple HEXDUMP routine for raw data. */ -static void -hex_dump(unsigned char *bufp, int len) -{ - char asci[20]; - unsigned char c; - 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); - } - } - - if (addr % 16) { - 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]); -} - -/* Print a standard Ethernet header. */ -static int -eth_prhdr(unsigned char *ptr) -{ - unsigned short type; - - printf("Ethernet "); - eth_praddr(ptr + 6); - printf(" > "); - eth_praddr(ptr); - type = (ptr[12] << 8) | ptr[13]; - printf(" type %04x\n", type); - - 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; - const unsigned char *pkt; - 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); - if (pcap == NULL) { - 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; - - /* Did we time out? */ - if (rc == 0) - continue; - - /* Convert the timestamp to readable format. */ - now = hdr->ts.tv_sec; - ltime = localtime(&now); - strftime(temp, sizeof(temp), "%H:%M:%S", ltime); - - /* 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); - } - - /* All done, close up. */ - f_pcap_close(pcap); - - return 0; -} - -/* Show a list of available network interfaces. */ -static void -show_devs(capdev_t *list, int num) -{ - if (num > 0) { - printf("Available network interfaces:\n\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"); - } -} - -int -main(int argc, char **argv) -{ - capdev_t interfaces[32]; - int numdev; - int i; - - /* Try loading the DLL. */ -#ifdef _WIN32 - pcap_handle = dynld_module("wpcap.dll", pcap_imports); -#elif defined __APPLE__ - pcap_handle = dynld_module("libpcap.dylib", pcap_imports); -#else - pcap_handle = dynld_module("libpcap.so", pcap_imports); -#endif - if (pcap_handle == NULL) { -#ifdef _WIN32 - fprintf(stderr, "Unable to load WinPcap DLL !\n"); -#else - fprintf(stderr, "Unable to load libpcap.so !\n"); -#endif - return 1; - } - - /* Get the list. */ - numdev = get_devlist(interfaces); - - if (argc == 1) { - /* No arguments, just show the list. */ - show_devs(interfaces, numdev); - - dynld_close(pcap_handle); - - 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); - - dynld_close(pcap_handle); - - return 1; - } - - /* Looks good, go and listen.. */ - i = start_cap(interfaces[i - 1].device); - - dynld_close(pcap_handle); - - return i; -} diff --git a/src/network/utils/getline.c b/src/network/utils/getline.c new file mode 100644 index 000000000..69ee258fd --- /dev/null +++ b/src/network/utils/getline.c @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 + +ssize_t +local_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) +{ + char *ptr, *eptr; + + + if (*buf == NULL || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = malloc(*bufsiz)) == NULL) + return -1; + } + + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = realloc(*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } +} + +ssize_t +local_getline(char **buf, size_t *bufsiz, FILE *fp) +{ + return local_getdelim(buf, bufsiz, '\n', fp); +} diff --git a/src/nvr_at.c b/src/nvr_at.c index c66799579..9465839a7 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -309,7 +309,6 @@ typedef struct local_t { uint8_t irq_state; uint8_t smi_status; - uint8_t addr[8]; uint8_t wp[2]; uint8_t bank[8]; uint8_t *lock; @@ -317,6 +316,8 @@ typedef struct local_t { int16_t count; int16_t state; + uint16_t addr[8]; + int32_t smi_enable; uint64_t ecount; @@ -686,13 +687,26 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } } +/* Get the NVR register index (used for APC). */ +uint8_t +nvr_get_index(void *priv, uint8_t addr_id) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + uint8_t ret; + + ret = local->addr[addr_id]; + + return ret; +} + /* 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 ret = 0xff; uint8_t addr_id = (addr & 0x0e) >> 1; uint16_t i; uint16_t checksum = 0x0000; @@ -810,7 +824,8 @@ nvr_read(uint16_t addr, void *priv) break; default: - ret = nvr->regs[local->addr[addr_id]]; + if (!(local->lock[local->addr[addr_id]] & 0x02)) + ret = nvr->regs[local->addr[addr_id]]; break; } else { @@ -931,6 +946,17 @@ nvr_at_index_read_handler(int set, uint16_t base, nvr_t *nvr) } } +void +nvr_at_data_port(int set, nvr_t *nvr) +{ + io_handler(0, 0x71, 1, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + + if (set) + io_handler(1, 0x71, 1, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); +} + void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr) { diff --git a/src/pci.c b/src/pci.c index 7c61545b2..13b780050 100644 --- a/src/pci.c +++ b/src/pci.c @@ -424,6 +424,9 @@ pci_write(uint16_t port, uint8_t val, UNUSED(void *priv)) } break; case 0xcf9: + if (pci_flags & FLAG_TRC_CONTROLS_CPURST) + cpu_cpurst_on_sr = !(val & 0x10); + if (!(pci_trc_reg & 4) && (val & 4)) pci_trc_reset(val); @@ -764,7 +767,7 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), if (next_pci_card < PCI_CARDS_NUM) { dev = &pci_card_descs[next_pci_card]; - dev->type = add_type; + dev->type = add_type | PCI_ADD_STRICT; dev->read = read; dev->write = write; dev->priv = priv; diff --git a/src/pit.c b/src/pit.c index f5816aaf5..0816094cb 100644 --- a/src/pit.c +++ b/src/pit.c @@ -47,6 +47,9 @@ pit_intf_t pit_devs[2]; double cpuclock; double PITCONSTD; +double PAS16CONSTD; +double PAS16CONST2D; +double PASSCSICONSTD; double SYSCLK; double isa_timing; double bus_timing; @@ -56,6 +59,9 @@ double PCICLK; double AGPCLK; uint64_t PITCONST; +uint64_t PAS16CONST; +uint64_t PAS16CONST2; +uint64_t PASSCSICONST; uint64_t ISACONST; uint64_t CGACONST; uint64_t MDACONST; @@ -94,13 +100,16 @@ pit_log(const char *fmt, ...) #endif static void -ctr_set_out(ctr_t *ctr, int out) +ctr_set_out(ctr_t *ctr, int out, void *priv) { + pit_t *pit = (pit_t *)priv; + if (ctr == NULL) return; if (ctr->out_func != NULL) - ctr->out_func(out, ctr->out); + ctr->out_func(out, ctr->out, pit); + ctr->out = out; } @@ -146,8 +155,9 @@ ctr_load_count(ctr_t *ctr) } static void -ctr_tick(ctr_t *ctr) +ctr_tick(ctr_t *ctr, void *priv) { + pit_t *pit = (pit_t *)priv; uint8_t state = ctr->state; if ((state & 0x03) == 0x01) { @@ -155,7 +165,7 @@ ctr_tick(ctr_t *ctr) ctr_load_count(ctr); ctr->state++; if (((ctr->m & 0x07) == 0x01) && (ctr->state == 2)) - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, pit); } else switch (ctr->m & 0x07) { case 0: /* Interrupt on terminal count */ @@ -165,7 +175,7 @@ ctr_tick(ctr_t *ctr) ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; - ctr_set_out(ctr, 1); + ctr_set_out(ctr, 1, pit); } } break; @@ -185,7 +195,7 @@ ctr_tick(ctr_t *ctr) ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; - ctr_set_out(ctr, 1); + ctr_set_out(ctr, 1, pit); } } break; @@ -205,7 +215,7 @@ ctr_tick(ctr_t *ctr) case 3: ctr_load_count(ctr); ctr->state = 2; - ctr_set_out(ctr, 1); + ctr_set_out(ctr, 1, pit); break; case 2: if (ctr->gate == 0) @@ -214,7 +224,7 @@ ctr_tick(ctr_t *ctr) ctr_decrease_count(ctr); if (ctr->count < 2) { ctr->state = 3; - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, pit); } } break; @@ -238,9 +248,9 @@ ctr_tick(ctr_t *ctr) } else ctr->count -= (ctr->newcount ? 1 : 2); if (ctr->count < 0) { + ctr_set_out(ctr, 0, pit); ctr_load_count(ctr); ctr->state = 3; - ctr_set_out(ctr, 0); } else if (ctr->newcount) ctr->newcount = 0; } @@ -257,9 +267,9 @@ ctr_tick(ctr_t *ctr) } else ctr->count -= (ctr->newcount ? 3 : 2); if (ctr->count < 0) { + ctr_set_out(ctr, 1, pit); ctr_load_count(ctr); ctr->state = 2; - ctr_set_out(ctr, 1); } else if (ctr->newcount) ctr->newcount = 0; } @@ -284,13 +294,13 @@ ctr_tick(ctr_t *ctr) ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, pit); } } break; case 3: ctr->state = 0; - ctr_set_out(ctr, 1); + ctr_set_out(ctr, 1, pit); break; default: @@ -303,7 +313,7 @@ ctr_tick(ctr_t *ctr) } } -static void +void ctr_clock(void *data, int counter_id) { pit_t *pit = (pit_t *) data; @@ -316,7 +326,7 @@ ctr_clock(void *data, int counter_id) if (ctr->using_timer) return; - ctr_tick(ctr); + ctr_tick(ctr, pit); } static void @@ -351,7 +361,7 @@ ctr_load(ctr_t *ctr) if (ctr->load_func != NULL) ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); - pit_log("Counter loaded, state = %i, gate = %i\n", ctr->state, ctr->gate); + pit_log("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch); } static __inline void @@ -390,7 +400,7 @@ ctr_latch_count(ctr_t *ctr) break; } - pit_log("latched counter = %04X\n", ctr->rl & 0xffff); + pit_log("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff); } uint16_t @@ -415,7 +425,7 @@ pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, in } void -pit_ctr_set_out_func(void *data, int counter_id, 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, void *priv)) { if (data == NULL) return; @@ -435,8 +445,6 @@ pit_ctr_set_gate(void *data, int counter_id, int gate) int old = ctr->gate; uint8_t mode = ctr->m & 3; - ctr->gate = gate; - switch (mode) { case 1: case 2: @@ -448,25 +456,28 @@ pit_ctr_set_gate(void *data, int counter_id, int gate) /* Here we handle the rising edges. */ if (mode & 1) { if (mode != 1) - ctr_set_out(ctr, 1); + ctr_set_out(ctr, 1, pit); 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); + ctr_set_out(ctr, 1, pit); } break; default: break; } + + ctr->gate = gate; } static __inline void -pit_ctr_set_clock_common(ctr_t *ctr, int clock) +pit_ctr_set_clock_common(ctr_t *ctr, int clock, void *priv) { + pit_t *pit = (pit_t *)priv; int old = ctr->clock; ctr->clock = clock; @@ -484,18 +495,18 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->s1_det++; /* Falling edge. */ if (ctr->s1_det >= 2) { ctr->s1_det = 0; - ctr_tick(ctr); + ctr_tick(ctr, pit); } } } else if (old && !ctr->clock) - ctr_tick(ctr); + ctr_tick(ctr, pit); } } void -pit_ctr_set_clock(ctr_t *ctr, int clock) +pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv) { - pit_ctr_set_clock_common(ctr, clock); + pit_ctr_set_clock_common(ctr, clock, priv); } void @@ -516,9 +527,9 @@ pit_timer_over(void *priv) dev->clock ^= 1; for (uint8_t i = 0; i < 3; i++) - pit_ctr_set_clock_common(&dev->counters[i], dev->clock); + pit_ctr_set_clock_common(&dev->counters[i], dev->clock, dev); - timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); + timer_advance_u64(&dev->callback_timer, dev->pit_const >> 1ULL); } static void @@ -528,7 +539,9 @@ pit_write(uint16_t addr, uint8_t val, void *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); + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + } switch (addr & 3) { case 3: /* control */ @@ -544,7 +557,9 @@ pit_write(uint16_t addr, uint8_t val, void *priv) 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 ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i: Initiated readback command\n", t); + } } if (!(val & 0x10)) { if (val & 2) @@ -561,8 +576,10 @@ pit_write(uint16_t addr, uint8_t val, void *priv) if (!(dev->ctrl & 0x30)) { ctr_latch_count(ctr); - pit_log("PIT %i: Initiated latched read, %i bytes latched\n", + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + 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; @@ -571,14 +588,18 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr->m &= 3; ctr->null_count = 1; ctr->bcd = (ctr->ctrl & 0x01); - ctr_set_out(ctr, !!ctr->m); + ctr_set_out(ctr, !!ctr->m, dev); ctr->state = 0; if (ctr->latched) { - pit_log("PIT %i: Reload while counter is latched\n", t); + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + 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); + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); + } } } break; @@ -594,31 +615,48 @@ pit_write(uint16_t addr, uint8_t val, void *priv) break; case 1: ctr->l = val; + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i (1): Written byte %02X, latch now %04X\n", t, val, ctr->l); + } if (ctr->m == 0) - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, dev); ctr_load(ctr); break; case 2: ctr->l = (val << 8); + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i (2): Written byte %02X, latch now %04X\n", t, val, ctr->l); + } if (ctr->m == 0) - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, dev); 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->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i (0x83): 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); + ctr->lback = ctr->l; + ctr->lback2 = ctr->l; + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("PIT %i (3): Written low byte %02X, latch now %04X\n", t, val, ctr->l); + } if (ctr->m == 0) { ctr->state = 0; - ctr_set_out(ctr, 0); + ctr_set_out(ctr, 0, dev); } } - if (ctr->wm & 0x80) ctr->wm &= ~0x80; else @@ -659,13 +697,14 @@ pit_read_reg(void *priv, uint8_t reg) break; case 0x07: /* The SiS 551x datasheet is unclear about how exactly - this register is structured. */ + this register is structured. + Update: But the SiS 5571 datasheet is clear. */ 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; + ret |= (dev->counters[1].rm & 0x80) ? 0x02 : 0x00; + ret |= (dev->counters[2].rm & 0x80) ? 0x04 : 0x00; + ret |= (dev->counters[0].wm & 0x80) ? 0x08 : 0x00; + ret |= (dev->counters[1].wm & 0x80) ? 0x10 : 0x00; + ret |= (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; break; } @@ -748,13 +787,15 @@ pit_read(uint16_t addr, void *priv) break; } - pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { + pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + } return ret; } void -pit_irq0_timer_ps2(int new_out, int old_out) +pit_irq0_timer_ps2(int new_out, int old_out, UNUSED(void *priv)) { if (new_out && !old_out) { picint(1); @@ -769,21 +810,21 @@ pit_irq0_timer_ps2(int new_out, int old_out) } void -pit_refresh_timer_xt(int new_out, int old_out) +pit_refresh_timer_xt(int new_out, int old_out, UNUSED(void *priv)) { if (new_out && !old_out) dma_channel_read(0); } void -pit_refresh_timer_at(int new_out, int old_out) +pit_refresh_timer_at(int new_out, int old_out, UNUSED(void *priv)) { if (refresh_at_enable && new_out && !old_out) ppi.pb ^= 0x10; } void -pit_speaker_timer(int new_out, UNUSED(int old_out)) +pit_speaker_timer(int new_out, UNUSED(int old_out), UNUSED(void *priv)) { int l; @@ -803,7 +844,7 @@ pit_speaker_timer(int new_out, UNUSED(int old_out)) } void -pit_nmi_timer_ps2(int new_out, UNUSED(int old_out)) +pit_nmi_timer_ps2(int new_out, UNUSED(int old_out), UNUSED(void *priv)) { nmi = new_out; @@ -828,6 +869,15 @@ ctr_reset(ctr_t *ctr) ctr->l_det = 0; } +void +pit_device_reset(pit_t *dev) +{ + dev->clock = 0; + + for (uint8_t i = 0; i < 3; i++) + ctr_reset(&dev->counters[i]); +} + void pit_reset(pit_t *dev) { @@ -848,6 +898,20 @@ 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); } +void +pit_set_pit_const(void *data, uint64_t pit_const) +{ + pit_t *pit = (pit_t *) data; + + pit->pit_const = pit_const; +} + +static void +pit_speed_changed(void *priv) +{ + pit_set_pit_const(priv, PITCONST); +} + static void pit_close(void *priv) { @@ -867,14 +931,18 @@ static void * pit_init(const device_t *info) { pit_t *dev = (pit_t *) malloc(sizeof(pit_t)); + pit_reset(dev); + pit_set_pit_const(dev, PITCONST); + 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_set_delay_u64(&dev->callback_timer, dev->pit_const >> 1ULL); } dev->flags = info->local; + dev->dev_priv = NULL; if (!(dev->flags & PIT_EXT_IO)) { io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, @@ -893,6 +961,20 @@ const device_t i8253_device = { .close = pit_close, .reset = NULL, { .available = NULL }, + .speed_changed = pit_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8253_ext_io_device = { + .name = "Intel 8253 Programmable Interval Timer (External I/O)", + .internal_name = "i8253_ext_io", + .flags = DEVICE_ISA, + .local = PIT_8253 | PIT_EXT_IO, + .init = pit_init, + .close = pit_close, + .reset = NULL, + { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -907,7 +989,7 @@ const device_t i8254_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -921,7 +1003,7 @@ const device_t i8254_sec_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -949,13 +1031,13 @@ const device_t i8254_ps2_device = { .close = pit_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pit_speed_changed, .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)) +pit_common_init(int type, void (*out0)(int new_out, int old_out, void *priv), void (*out1)(int new_out, int old_out, void *priv)) { void *pit; @@ -1034,6 +1116,13 @@ pit_ps2_init(int type) return pit; } +void +pit_change_pas16_consts(double prescale) +{ + PAS16CONST = (uint64_t) ((PAS16CONSTD / prescale) * (double) (1ULL << 32)); + PAS16CONST2 = (uint64_t) ((PAS16CONST2D / prescale) * (double) (1ULL << 32)); +} + void pit_set_clock(uint32_t clock) { @@ -1129,6 +1218,15 @@ pit_set_clock(uint32_t clock) TIMER_USEC = (uint64_t) ((cpuclock / 1000000.0) * (double) (1ULL << 32)); + PAS16CONSTD = (cpuclock / 441000.0); + PAS16CONST = (uint64_t) (PAS16CONSTD * (double) (1ULL << 32)); + + PAS16CONST2D = (cpuclock / 1008000.0); + PAS16CONST2 = (uint64_t) (PAS16CONST2D * (double) (1ULL << 32)); + + PASSCSICONSTD = (cpuclock / (28224000.0 / 14.0)); + PASSCSICONST = (uint64_t) (PASSCSICONSTD * (double) (1ULL << 32)); + isa_timing = (cpuclock / (double) cpu_isa_speed); if (cpu_64bitbus) bus_timing = (cpuclock / (cpu_busspeed / 2)); @@ -1160,5 +1258,6 @@ const pit_intf_t pit_classic_intf = { &pit_ctr_set_out_func, &pit_ctr_set_load_func, &ctr_clock, + &pit_set_pit_const, NULL, }; diff --git a/src/pit_fast.c b/src/pit_fast.c index 1168cb3c5..e986600ee 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -66,13 +66,15 @@ pit_log(const char *fmt, ...) #endif static void -pitf_ctr_set_out(ctrf_t *ctr, int out) +pitf_ctr_set_out(ctrf_t *ctr, int out, void *priv) { + pitf_t *pit = (pitf_t *)priv; + if (ctr == NULL) return; if (ctr->out_func != NULL) - ctr->out_func(out, ctr->out); + ctr->out_func(out, ctr->out, pit); ctr->out = out; } @@ -97,8 +99,8 @@ pitf_ctr_get_count(void *data, int 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)) +void +pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv)) { if (data == NULL) return; @@ -109,7 +111,7 @@ pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int ctr->out_func = func; } -static void +void pitf_ctr_set_using_timer(void *data, int counter_id, int using_timer) { if (tsc > 0) @@ -124,14 +126,14 @@ 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); + int read = (int) ((timer_get_remaining_u64(&ctr->timer)) / ctr->pit_const); if (ctr->m == 2) read++; if (read < 0) read = 0; if (read > 0x10000) read = 0x10000; - if (ctr->m == 3) + if ((ctr->m == 3) && ctr->using_timer) read <<= 1; return read; } @@ -154,8 +156,9 @@ pitf_dump_and_disable_timer(ctrf_t *ctr) } static void -pitf_ctr_load(ctrf_t *ctr) +pitf_ctr_load(ctrf_t *ctr, void *priv) { + pitf_t *pit = (pitf_t *)priv; int l = ctr->l ? ctr->l : 0x10000; ctr->newcount = 0; @@ -165,8 +168,8 @@ pitf_ctr_load(ctrf_t *ctr) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); + pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; ctr->enabled = ctr->gate; break; @@ -177,8 +180,8 @@ pitf_ctr_load(ctrf_t *ctr) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * ctr->pit_const)); + pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } ctr->enabled = ctr->gate; @@ -187,8 +190,10 @@ pitf_ctr_load(ctrf_t *ctr) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + else + ctr->newcount = (l & 1); + pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } ctr->enabled = ctr->gate; @@ -199,8 +204,8 @@ pitf_ctr_load(ctrf_t *ctr) else { ctr->count = l; if (ctr->using_timer) - timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); - pitf_ctr_set_out(ctr, 0); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); + pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; } ctr->enabled = ctr->gate; @@ -223,8 +228,9 @@ pitf_ctr_load(ctrf_t *ctr) } static void -pitf_set_gate_no_timer(ctrf_t *ctr, int gate) +pitf_set_gate_no_timer(ctrf_t *ctr, int gate, void *priv) { + pitf_t *pit = (pitf_t *)priv; int l = ctr->l ? ctr->l : 0x10000; if (ctr->disabled) { @@ -236,7 +242,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate) 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)); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); ctr->enabled = gate; break; case 1: /*Hardware retriggerable one-shot*/ @@ -244,8 +250,8 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); + pitf_ctr_set_out(ctr, 0, pit); ctr->thit = 0; ctr->enabled = 1; } @@ -254,8 +260,8 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); + pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } ctr->enabled = gate; @@ -264,8 +270,10 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate) 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); + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + else + ctr->newcount = (l & 1); + pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 0; } ctr->enabled = gate; @@ -280,7 +288,7 @@ pitf_set_gate_no_timer(ctrf_t *ctr, int gate) pitf_dump_and_disable_timer(ctr); } -static void +void pitf_ctr_set_gate(void *data, int counter_id, int gate) { pitf_t *pit = (pitf_t *) data; @@ -291,17 +299,18 @@ pitf_ctr_set_gate(void *data, int counter_id, int gate) return; } - pitf_set_gate_no_timer(ctr, gate); + pitf_set_gate_no_timer(ctr, gate, pit); } static void -pitf_over(ctrf_t *ctr) +pitf_over(ctrf_t *ctr, void *priv) { + pitf_t *pit = (pitf_t *)priv; 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)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); return; } @@ -309,62 +318,71 @@ pitf_over(ctrf_t *ctr) case 0: /*Interrupt on terminal count*/ case 1: /*Hardware retriggerable one-shot*/ if (!ctr->thit) - pitf_ctr_set_out(ctr, 1); + pitf_ctr_set_out(ctr, 1, pit); ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); 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); + timer_advance_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); + pitf_ctr_set_out(ctr, 0, pit); + pitf_ctr_set_out(ctr, 1, pit); 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)); + pitf_ctr_set_out(ctr, 0, pit); + if (ctr->using_timer) { + ctr->count += (l >> 1); + timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * ctr->pit_const)); + } else { + ctr->count += l; + ctr->newcount = (l & 1); + } } else { - pitf_ctr_set_out(ctr, 1); + pitf_ctr_set_out(ctr, 1, pit); ctr->count += ((l + 1) >> 1); - if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + if (ctr->using_timer) { + ctr->count += (l >> 1); + timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * ctr->pit_const)); + } else { + ctr->count += l; + ctr->newcount = (l & 1); + } } #if 0 if (!t) - pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); + pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, ctr->pit_const); #endif break; case 4: /*Software triggered strove*/ if (!ctr->thit) { - pitf_ctr_set_out(ctr, 0); - pitf_ctr_set_out(ctr, 1); + pitf_ctr_set_out(ctr, 0, pit); + pitf_ctr_set_out(ctr, 1, pit); } if (ctr->newcount) { ctr->newcount = 0; ctr->count += l; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (l * ctr->pit_const)); } else { ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); } break; case 5: /*Hardware triggered strove*/ if (!ctr->thit) { - pitf_ctr_set_out(ctr, 0); - pitf_ctr_set_out(ctr, 1); + pitf_ctr_set_out(ctr, 0, pit); + pitf_ctr_set_out(ctr, 1, pit); } ctr->thit = 1; ctr->count += 0xffff; if (ctr->using_timer) - timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * ctr->pit_const)); break; default: @@ -453,9 +471,9 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) ctr->rereadlatch = 1; ctr->initial = 1; if (!ctr->m) - pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 0, dev); else - pitf_ctr_set_out(ctr, 1); + pitf_ctr_set_out(ctr, 1, dev); 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); @@ -472,16 +490,16 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) switch (ctr->wm) { case 1: ctr->l = val; - pitf_ctr_load(ctr); + pitf_ctr_load(ctr, dev); break; case 2: ctr->l = (val << 8); - pitf_ctr_load(ctr); + pitf_ctr_load(ctr, dev); break; case 0: ctr->l &= 0xFF; ctr->l |= (val << 8); - pitf_ctr_load(ctr); + pitf_ctr_load(ctr, dev); ctr->wm = 3; break; case 3: @@ -522,13 +540,14 @@ pitf_read_reg(void *priv, uint8_t reg) break; case 0x07: /* The SiS 551x datasheet is unclear about how exactly - this register is structured. */ + this register is structured. + Update: But the SiS 5571 datasheet is clear. */ 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; + ret |= (dev->counters[1].rm & 0x80) ? 0x02 : 0x00; + ret |= (dev->counters[2].rm & 0x80) ? 0x04 : 0x00; + ret |= (dev->counters[0].wm & 0x80) ? 0x08 : 0x00; + ret |= (dev->counters[1].wm & 0x80) ? 0x10 : 0x00; + ret |= (dev->counters[2].wm & 0x80) ? 0x20 : 0x00; break; } @@ -609,10 +628,11 @@ static void pitf_timer_over(void *priv) { ctrf_t *ctr = (ctrf_t *) priv; - pitf_over(ctr); + pit_t *pit = (pit_t *)ctr->priv; + pitf_over(ctr, pit); } -static void +void pitf_ctr_clock(void *data, int counter_id) { pitf_t *pit = (pitf_t *) data; @@ -624,9 +644,14 @@ pitf_ctr_clock(void *data, int counter_id) if (ctr->using_timer) return; - ctr->count -= (ctr->m == 3) ? 2 : 1; + if ((ctr->m == 3) && ctr->newcount) { + ctr->count -= ctr->out ? 1 : 3; + ctr->newcount = 0; + } else + ctr->count -= (ctr->m == 3) ? 2 : 1; + if (!ctr->count) - pitf_over(ctr); + pitf_over(ctr, pit); } static void @@ -652,6 +677,24 @@ pitf_reset(pitf_t *dev) dev->counters[2].gate = 0; } +void +pitf_set_pit_const(void *data, uint64_t pit_const) +{ + pitf_t *pit = (pitf_t *) data; + ctrf_t *ctr; + + for (uint8_t i = 0; i < 3; i++) { + ctr = &pit->counters[i]; + ctr->pit_const = pit_const; + } +} + +static void +pitf_speed_changed(void *priv) +{ + pitf_set_pit_const(priv, PITCONST); +} + static void pitf_close(void *priv) { @@ -667,17 +710,27 @@ pitf_close(void *priv) free(dev); } +void +pitf_handler(int set, uint16_t base, int size, void *priv) +{ + io_handler(set, base, size, pitf_read, NULL, NULL, pitf_write, NULL, NULL, priv); +} + static void * pitf_init(const device_t *info) { pitf_t *dev = (pitf_t *) malloc(sizeof(pitf_t)); + pitf_reset(dev); + pitf_set_pit_const(dev, PITCONST); + 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]; + ctr->priv = dev; timer_add(&ctr->timer, pitf_timer_over, (void *) ctr, 0); } } @@ -699,7 +752,7 @@ const device_t i8253_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -713,7 +766,7 @@ const device_t i8254_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -727,7 +780,7 @@ const device_t i8254_sec_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -755,7 +808,7 @@ const device_t i8254_ps2_fast_device = { .close = pitf_close, .reset = NULL, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pitf_speed_changed, .force_redraw = NULL, .config = NULL }; @@ -769,5 +822,6 @@ const pit_intf_t pit_fast_intf = { &pitf_ctr_set_out_func, &pitf_ctr_set_load_func, &pitf_ctr_clock, + &pitf_set_pit_const, NULL, }; diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 707590134..8247ecfab 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -437,6 +437,7 @@ reset_printer(escp_t *dev) dev->cpi = PAGE_CPI; dev->curr_char_table = 1; dev->font_style = 0; + dev->print_quality = QUALITY_DRAFT; dev->extra_intra_space = 0.0; dev->print_upper_control = 1; dev->bg_remaining_bytes = 0; @@ -508,9 +509,12 @@ update_font(escp_t *dev) if (dev->fontface) FT_Done_Face(dev->fontface); - if (dev->print_quality == QUALITY_DRAFT) - fn = FONT_FILE_DOTMATRIX; - else + if (dev->print_quality == QUALITY_DRAFT) { + if (dev->font_style & STYLE_ITALICS) + fn = FONT_FILE_DOTMATRIX_ITALIC; + else + fn = FONT_FILE_DOTMATRIX; + } else switch (dev->lq_typeface) { case TYPEFACE_ROMAN: fn = FONT_FILE_ROMAN; @@ -531,7 +535,7 @@ update_font(escp_t *dev) fn = FONT_FILE_OCRB; break; default: - fn = FONT_FILE_DOTMATRIX; + fn = FONT_FILE_ROMAN; } /* Create a full pathname for the ROM file. */ @@ -592,7 +596,7 @@ update_font(escp_t *dev) (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)) { + if ((dev->print_quality != QUALITY_DRAFT) && ((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); @@ -1578,8 +1582,8 @@ handle_char(escp_t *dev, uint8_t ch) 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_x = PIXX + fmax(0.0, dev->fontface->glyph->bitmap_left); + pen_y = (uint16_t) (PIXY + fmax(0.0, -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; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index c0e3958b2..e6362019f 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -23,7 +23,6 @@ #include #include #include <86box/86box.h> -#include <86box/language.h> #include <86box/lpt.h> #include <86box/timer.h> #include <86box/pit.h> @@ -352,7 +351,7 @@ ps_init(void *lpt) } #endif if (ghostscript_handle == NULL) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2115, (wchar_t *) IDS_2133); + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTSCRIPT_ERROR_TITLE), plat_get_string(STRING_GHOSTSCRIPT_ERROR_DESC)); } else { if (gsapi_revision(&rev, sizeof(rev)) == 0) { pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); diff --git a/src/win/86Box-qt.rc b/src/qt/86Box-qt.rc similarity index 100% rename from src/win/86Box-qt.rc rename to src/qt/86Box-qt.rc diff --git a/src/win/86Box.manifest b/src/qt/86Box.manifest similarity index 100% rename from src/win/86Box.manifest rename to src/qt/86Box.manifest diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index fb96de1ea..422989a44 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -61,7 +61,6 @@ add_library(plat STATIC add_library(ui STATIC qt_ui.cpp - qt_cdrom.c qt_mainwindow.cpp qt_mainwindow.hpp @@ -189,16 +188,8 @@ endif() if(WIN32) enable_language(RC) - target_sources(86Box PUBLIC ../win/86Box-qt.rc) + target_sources(86Box PUBLIC 86Box-qt.rc) 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 @@ -206,25 +197,32 @@ 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 DIRECTORY .. PROPERTY COMPILE_DEFINITIONS NO_INCLUDE_MANIFEST) - target_sources(86Box PRIVATE ../win/86Box.manifest) + set_property(SOURCE 86Box-qt.rc DIRECTORY .. PROPERTY COMPILE_DEFINITIONS NO_INCLUDE_MANIFEST) + target_sources(86Box PRIVATE 86Box.manifest) endif() if (MINGW) add_compile_definitions(NTDDI_VERSION=0x06010000) endif() + + option(SDL_JOYSTICK "Use SDL2 joystick backend instead of raw input" OFF) +endif() + +if(WIN32 AND NOT SDL_JOYSTICK) + target_sources(plat PRIVATE win_joystick_rawinput.c) + target_link_libraries(86Box hid) else() - target_sources(plat PRIVATE sdl_joystick.cpp) + target_sources(plat PRIVATE sdl_joystick.c) endif() if(WIN32 AND NOT MINGW) - target_sources(plat PRIVATE ../win/win_opendir.c) + target_sources(plat PRIVATE win_opendir.c) endif() if(WIN32) - target_sources(plat PRIVATE ../win/win_serial_passthrough.c) + target_sources(plat PRIVATE win_serial_passthrough.c win_netsocket.c) else() - target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c) + target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c ../unix/unix_netsocket.c) endif() if (APPLE) diff --git a/src/win/assets/86Box-green.png b/src/qt/assets/86Box-green.png similarity index 100% rename from src/win/assets/86Box-green.png rename to src/qt/assets/86Box-green.png diff --git a/src/win/assets/86box-rb.png b/src/qt/assets/86box-rb.png similarity index 100% rename from src/win/assets/86box-rb.png rename to src/qt/assets/86box-rb.png diff --git a/src/win/assets/86box-red.png b/src/qt/assets/86box-red.png similarity index 100% rename from src/win/assets/86box-red.png rename to src/qt/assets/86box-red.png diff --git a/src/win/assets/86box-yellow.png b/src/qt/assets/86box-yellow.png similarity index 100% rename from src/win/assets/86box-yellow.png rename to src/qt/assets/86box-yellow.png diff --git a/src/win/assets/86box.png b/src/qt/assets/86box.png similarity index 100% rename from src/win/assets/86box.png rename to src/qt/assets/86box.png diff --git a/src/win/assets/status-paused.png b/src/qt/assets/status-paused.png similarity index 100% rename from src/win/assets/status-paused.png rename to src/qt/assets/status-paused.png diff --git a/src/win/assets/status-running.png b/src/qt/assets/status-running.png similarity index 100% rename from src/win/assets/status-running.png rename to src/qt/assets/status-running.png diff --git a/src/win/icons/86Box-gray.ico b/src/qt/icons/86Box-gray.ico similarity index 100% rename from src/win/icons/86Box-gray.ico rename to src/qt/icons/86Box-gray.ico diff --git a/src/win/icons/86Box-green.ico b/src/qt/icons/86Box-green.ico similarity index 100% rename from src/win/icons/86Box-green.ico rename to src/qt/icons/86Box-green.ico diff --git a/src/win/icons/86Box-red.ico b/src/qt/icons/86Box-red.ico similarity index 100% rename from src/win/icons/86Box-red.ico rename to src/qt/icons/86Box-red.ico diff --git a/src/win/icons/86Box-yellow.ico b/src/qt/icons/86Box-yellow.ico similarity index 100% rename from src/win/icons/86Box-yellow.ico rename to src/qt/icons/86Box-yellow.ico diff --git a/src/win/icons/acpi_shutdown.ico b/src/qt/icons/acpi_shutdown.ico similarity index 100% rename from src/win/icons/acpi_shutdown.ico rename to src/qt/icons/acpi_shutdown.ico diff --git a/src/win/icons/cartridge.ico b/src/qt/icons/cartridge.ico similarity index 100% rename from src/win/icons/cartridge.ico rename to src/qt/icons/cartridge.ico diff --git a/src/win/icons/cartridge_empty.ico b/src/qt/icons/cartridge_empty.ico similarity index 100% rename from src/win/icons/cartridge_empty.ico rename to src/qt/icons/cartridge_empty.ico diff --git a/src/win/icons/cassette.ico b/src/qt/icons/cassette.ico similarity index 100% rename from src/win/icons/cassette.ico rename to src/qt/icons/cassette.ico diff --git a/src/win/icons/cassette_active.ico b/src/qt/icons/cassette_active.ico similarity index 100% rename from src/win/icons/cassette_active.ico rename to src/qt/icons/cassette_active.ico diff --git a/src/win/icons/cassette_empty.ico b/src/qt/icons/cassette_empty.ico similarity index 100% rename from src/win/icons/cassette_empty.ico rename to src/qt/icons/cassette_empty.ico diff --git a/src/win/icons/cassette_empty_active.ico b/src/qt/icons/cassette_empty_active.ico similarity index 100% rename from src/win/icons/cassette_empty_active.ico rename to src/qt/icons/cassette_empty_active.ico diff --git a/src/win/icons/cdrom.ico b/src/qt/icons/cdrom.ico similarity index 100% rename from src/win/icons/cdrom.ico rename to src/qt/icons/cdrom.ico diff --git a/src/win/icons/cdrom_active.ico b/src/qt/icons/cdrom_active.ico similarity index 100% rename from src/win/icons/cdrom_active.ico rename to src/qt/icons/cdrom_active.ico diff --git a/src/win/icons/cdrom_disabled.ico b/src/qt/icons/cdrom_disabled.ico similarity index 100% rename from src/win/icons/cdrom_disabled.ico rename to src/qt/icons/cdrom_disabled.ico diff --git a/src/win/icons/cdrom_empty.ico b/src/qt/icons/cdrom_empty.ico similarity index 100% rename from src/win/icons/cdrom_empty.ico rename to src/qt/icons/cdrom_empty.ico diff --git a/src/win/icons/cdrom_empty_active.ico b/src/qt/icons/cdrom_empty_active.ico similarity index 100% rename from src/win/icons/cdrom_empty_active.ico rename to src/qt/icons/cdrom_empty_active.ico diff --git a/src/win/icons/display.ico b/src/qt/icons/display.ico similarity index 100% rename from src/win/icons/display.ico rename to src/qt/icons/display.ico diff --git a/src/win/icons/floppy_35.ico b/src/qt/icons/floppy_35.ico similarity index 100% rename from src/win/icons/floppy_35.ico rename to src/qt/icons/floppy_35.ico diff --git a/src/win/icons/floppy_35_active.ico b/src/qt/icons/floppy_35_active.ico similarity index 100% rename from src/win/icons/floppy_35_active.ico rename to src/qt/icons/floppy_35_active.ico diff --git a/src/win/icons/floppy_35_empty.ico b/src/qt/icons/floppy_35_empty.ico similarity index 100% rename from src/win/icons/floppy_35_empty.ico rename to src/qt/icons/floppy_35_empty.ico diff --git a/src/win/icons/floppy_35_empty_active.ico b/src/qt/icons/floppy_35_empty_active.ico similarity index 100% rename from src/win/icons/floppy_35_empty_active.ico rename to src/qt/icons/floppy_35_empty_active.ico diff --git a/src/win/icons/floppy_525.ico b/src/qt/icons/floppy_525.ico similarity index 100% rename from src/win/icons/floppy_525.ico rename to src/qt/icons/floppy_525.ico diff --git a/src/win/icons/floppy_525_active.ico b/src/qt/icons/floppy_525_active.ico similarity index 100% rename from src/win/icons/floppy_525_active.ico rename to src/qt/icons/floppy_525_active.ico diff --git a/src/win/icons/floppy_525_empty.ico b/src/qt/icons/floppy_525_empty.ico similarity index 100% rename from src/win/icons/floppy_525_empty.ico rename to src/qt/icons/floppy_525_empty.ico diff --git a/src/win/icons/floppy_525_empty_active.ico b/src/qt/icons/floppy_525_empty_active.ico similarity index 100% rename from src/win/icons/floppy_525_empty_active.ico rename to src/qt/icons/floppy_525_empty_active.ico diff --git a/src/win/icons/floppy_and_cdrom_drives.ico b/src/qt/icons/floppy_and_cdrom_drives.ico similarity index 100% rename from src/win/icons/floppy_and_cdrom_drives.ico rename to src/qt/icons/floppy_and_cdrom_drives.ico diff --git a/src/win/icons/floppy_disabled.ico b/src/qt/icons/floppy_disabled.ico similarity index 100% rename from src/win/icons/floppy_disabled.ico rename to src/qt/icons/floppy_disabled.ico diff --git a/src/win/icons/hard_disk.ico b/src/qt/icons/hard_disk.ico similarity index 100% rename from src/win/icons/hard_disk.ico rename to src/qt/icons/hard_disk.ico diff --git a/src/win/icons/hard_disk_active.ico b/src/qt/icons/hard_disk_active.ico similarity index 100% rename from src/win/icons/hard_disk_active.ico rename to src/qt/icons/hard_disk_active.ico diff --git a/src/win/icons/hard_reset.ico b/src/qt/icons/hard_reset.ico similarity index 100% rename from src/win/icons/hard_reset.ico rename to src/qt/icons/hard_reset.ico diff --git a/src/win/icons/input_devices.ico b/src/qt/icons/input_devices.ico similarity index 100% rename from src/win/icons/input_devices.ico rename to src/qt/icons/input_devices.ico diff --git a/src/win/icons/machine.ico b/src/qt/icons/machine.ico similarity index 100% rename from src/win/icons/machine.ico rename to src/qt/icons/machine.ico diff --git a/src/win/icons/mo.ico b/src/qt/icons/mo.ico similarity index 100% rename from src/win/icons/mo.ico rename to src/qt/icons/mo.ico diff --git a/src/win/icons/mo_active.ico b/src/qt/icons/mo_active.ico similarity index 100% rename from src/win/icons/mo_active.ico rename to src/qt/icons/mo_active.ico diff --git a/src/win/icons/mo_disabled.ico b/src/qt/icons/mo_disabled.ico similarity index 100% rename from src/win/icons/mo_disabled.ico rename to src/qt/icons/mo_disabled.ico diff --git a/src/win/icons/mo_empty.ico b/src/qt/icons/mo_empty.ico similarity index 100% rename from src/win/icons/mo_empty.ico rename to src/qt/icons/mo_empty.ico diff --git a/src/win/icons/mo_empty_active.ico b/src/qt/icons/mo_empty_active.ico similarity index 100% rename from src/win/icons/mo_empty_active.ico rename to src/qt/icons/mo_empty_active.ico diff --git a/src/win/icons/network.ico b/src/qt/icons/network.ico similarity index 100% rename from src/win/icons/network.ico rename to src/qt/icons/network.ico diff --git a/src/win/icons/network_active.ico b/src/qt/icons/network_active.ico similarity index 100% rename from src/win/icons/network_active.ico rename to src/qt/icons/network_active.ico diff --git a/src/win/icons/network_empty.ico b/src/qt/icons/network_empty.ico similarity index 100% rename from src/win/icons/network_empty.ico rename to src/qt/icons/network_empty.ico diff --git a/src/win/icons/other_peripherals.ico b/src/qt/icons/other_peripherals.ico similarity index 100% rename from src/win/icons/other_peripherals.ico rename to src/qt/icons/other_peripherals.ico diff --git a/src/win/icons/other_removable_devices.ico b/src/qt/icons/other_removable_devices.ico similarity index 100% rename from src/win/icons/other_removable_devices.ico rename to src/qt/icons/other_removable_devices.ico diff --git a/src/win/icons/pause.ico b/src/qt/icons/pause.ico similarity index 100% rename from src/win/icons/pause.ico rename to src/qt/icons/pause.ico diff --git a/src/win/icons/ports.ico b/src/qt/icons/ports.ico similarity index 100% rename from src/win/icons/ports.ico rename to src/qt/icons/ports.ico diff --git a/src/win/icons/run.ico b/src/qt/icons/run.ico similarity index 100% rename from src/win/icons/run.ico rename to src/qt/icons/run.ico diff --git a/src/win/icons/send_cad.ico b/src/qt/icons/send_cad.ico similarity index 100% rename from src/win/icons/send_cad.ico rename to src/qt/icons/send_cad.ico diff --git a/src/win/icons/send_cae.ico b/src/qt/icons/send_cae.ico similarity index 100% rename from src/win/icons/send_cae.ico rename to src/qt/icons/send_cae.ico diff --git a/src/win/icons/settings.ico b/src/qt/icons/settings.ico similarity index 100% rename from src/win/icons/settings.ico rename to src/qt/icons/settings.ico diff --git a/src/win/icons/sound.ico b/src/qt/icons/sound.ico similarity index 100% rename from src/win/icons/sound.ico rename to src/qt/icons/sound.ico diff --git a/src/win/icons/storage_controllers.ico b/src/qt/icons/storage_controllers.ico similarity index 100% rename from src/win/icons/storage_controllers.ico rename to src/qt/icons/storage_controllers.ico diff --git a/src/win/icons/zip.ico b/src/qt/icons/zip.ico similarity index 100% rename from src/win/icons/zip.ico rename to src/qt/icons/zip.ico diff --git a/src/win/icons/zip_active.ico b/src/qt/icons/zip_active.ico similarity index 100% rename from src/win/icons/zip_active.ico rename to src/qt/icons/zip_active.ico diff --git a/src/win/icons/zip_disabled.ico b/src/qt/icons/zip_disabled.ico similarity index 100% rename from src/win/icons/zip_disabled.ico rename to src/qt/icons/zip_disabled.ico diff --git a/src/win/icons/zip_empty.ico b/src/qt/icons/zip_empty.ico similarity index 100% rename from src/win/icons/zip_empty.ico rename to src/qt/icons/zip_empty.ico diff --git a/src/win/icons/zip_empty_active.ico b/src/qt/icons/zip_empty_active.ico similarity index 100% rename from src/win/icons/zip_empty_active.ico rename to src/qt/icons/zip_empty_active.ico diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 371781b7a..94b35a235 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: ca_ES\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Acció" @@ -40,14 +48,11 @@ msgstr "&Recordar mida i posició" msgid "Re&nderer" msgstr "Re&nderitzador" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Tipus de CPU:" msgid "Speed:" msgstr "Velocitat:" +msgid "Frequency:" +msgstr "Freqüència:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Gràfics Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gràfics IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gràfics IBM 8514/A" msgid "XGA Graphics" msgstr "Gràfics XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Targeta de so 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Targeta de so 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Targeta de so 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Targeta de so 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Comprovar BPB" msgid "CD-ROM drives:" msgstr "Unitats de CD-ROM:" -msgid "Earlier drive" -msgstr "Unitat anterior" - msgid "MO drives:" msgstr "Unitats MO:" @@ -622,12 +627,6 @@ msgstr "Dispositiu ISABugger" msgid "POST card" msgstr "Targeta POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ 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 %1 to release mouse" +msgstr "Premeu %1 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 "Press %1 or middle button to release mouse" +msgstr "Premeu %1 o el botó central per alliberar el ratolí" msgid "Bus" msgstr "Bus" @@ -757,9 +756,6 @@ 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" @@ -790,15 +786,6 @@ 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)" @@ -811,9 +798,6 @@ 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?" @@ -862,26 +846,14 @@ msgstr "Un emulador d'ordinadors antics\n\nAutors: Miran Grča (OBattler), Richa 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 "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Assegureu-vos que el %1 està instal·lat i que està en una connexió de xarxa compatible amb %1." 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 "%1 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 "%1 é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" @@ -901,8 +873,8 @@ msgstr "No resetejar" msgid "CD-ROM images" msgstr "Imatges de CD-ROM" -msgid "%hs Device Configuration" -msgstr "%hs Configuració de Dispositiu" +msgid "%1 Device Configuration" +msgstr "%1 Configuració de Dispositiu" msgid "Monitor in sleep mode" msgstr "Monitor en mode estalvi" @@ -958,14 +930,8 @@ 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 "Hard disk (%1)" +msgstr "Disc dur (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Les unitats de CD-ROM MFM/RLL o ESDI no van existir mai" @@ -1000,9 +966,6 @@ 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" @@ -1075,9 +1038,6 @@ 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" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Ràpid" msgid "&Auto-pause on focus loss" msgstr "&Pausa automàtica en la pèrdua del focus" + +msgid "WinBox is no longer supported" +msgstr "WinBox is no longer supported" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index d86f5b635..84debf20b 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: cs_CZ\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Akce" @@ -40,14 +48,11 @@ msgstr "&Pamatovat velikost a pozici" msgid "Re&nderer" msgstr "&Renderer" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rychlost:" +msgid "Frequency:" +msgstr "Frekvence:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +393,8 @@ msgstr "Grafika:" msgid "Voodoo Graphics" msgstr "Použít grafický akcelerátor Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvuková karta 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvuková karta 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvuková karta 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvuková karta 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Kontrola BPB" msgid "CD-ROM drives:" msgstr "Mechaniky CD-ROM:" -msgid "Earlier drive" -msgstr "Časná mechanika" - msgid "MO drives:" msgstr "Magnetooptické mechaniky:" @@ -622,12 +627,6 @@ msgstr "Zařízení ISABugger" msgid "POST card" msgstr "Karta pro kódy POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Jiné příslušenství" msgid "Click to capture mouse" msgstr "Klikněte pro zabraní myši" -msgid "Press F8+F12 to release mouse" -msgstr "Stiskněte F8+F12 pro uvolnění myši" +msgid "Press %1 to release mouse" +msgstr "Stiskněte %1 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 "Press %1 or middle button to release mouse" +msgstr "Stiskněte %1 nebo prostřední tlačítko pro uvolnění myši" msgid "Bus" msgstr "Sběrnice" @@ -757,9 +756,6 @@ msgstr "%i čekací stav(y)" msgid "Type" msgstr "Typ" -msgid "Failed to set up PCap" -msgstr "Nastala chyba při inicializaci knihovny PCap" - msgid "No PCap devices found" msgstr "Nebyla nalezena žádná PCap zařízení" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Žadné" -msgid "Unable to load keyboard accelerators." -msgstr "Nebylo možné nahrát klávesnicové zkratky." - -msgid "Unable to register raw input." -msgstr "Nebylo možné zaregistrovat raw input." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Rozšířené sektorové obrazy" msgid "Flux images" msgstr "Obrazy magnetického toku" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nastala chyba při inicializaci knihovny SDL, je potřeba SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Opravdu chcete resetovat emulovaný počítač?" @@ -862,26 +846,14 @@ msgstr "Emulátor starých počítačů\n\nAutoři: Miran Grča (OBattler), Rich msgid "Hardware not available" msgstr "Hardware není 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 "Ujistěte se, že je nainstalován libpcap a používáte síťové připojení s ním kompatibilní." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Ujistěte se, že je nainstalován %1 a používáte síťové připojení s ním kompatibilní." msgid "Invalid configuration" msgstr "Neplatná konfigurace" -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 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Vstup do režimu celé obrazovky" @@ -901,8 +873,8 @@ msgstr "Neresetovat" msgid "CD-ROM images" msgstr "Obraz CD-ROM disku" -msgid "%hs Device Configuration" -msgstr "Konfigurace zařízení %hs" +msgid "%1 Device Configuration" +msgstr "Konfigurace zařízení %1" msgid "Monitor in sleep mode" msgstr "Monitor je v režimu spánku" @@ -958,14 +930,8 @@ msgstr "Resetovat" msgid "ACPI shutdown" msgstr "Vypnout skrze rozhraní ACPI" -msgid "Hard disk (%s)" -msgstr "Pevný disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Pevný disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "CD-ROM mechaniky pro rozhraní MFM/RLL nebo ESDI nikdy neexistovaly" @@ -1000,9 +966,6 @@ msgstr "Nebylo možné zapisovat do souboru" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Obraz disku ve formátu HDI nebo HDX s velikostí sektoru jinou než 512 bajtů nejsou podporovány." -msgid "USB is not yet supported" -msgstr "USB zatím není podporováno." - msgid "Disk image file already exists" msgstr "Soubor obrazu disku již existuje" @@ -1075,9 +1038,6 @@ msgstr "Časová razítka nadřazeného a podřazeného disku nesouhlasí" msgid "Could not fix VHD timestamp." msgstr "Nebylo možné opravit časové razítko VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Rychlý" msgid "&Auto-pause on focus loss" msgstr "&Automatická pauza při ztrátě zaměření okna" + +msgid "WinBox is no longer supported" +msgstr "WinBox již není podporován" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Vývoj správce WinBox byl zastaven v roce 2022 z důvodu nedostatku správců. Vzhledem k tomu, že naše úsilí směřujeme k tomu, abychom 86Box ještě vylepšili, rozhodli jsme se WinBox jako správce již nepodporovat.\n\nProstřednictvím WinBoxu nebudou poskytovány žádné další aktualizace a pokud jej budete nadále používat s novějšími verzemi 86Boxu, můžete se setkat s nesprávným chováním. Veškerá hlášení o chybách souvisejících s chováním WinBoxu budou uzavřena jako neplatná.\n\nSeznam dalších správců, které můžete používat, najdete na webu 86box.net." diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 9c985d871..70b856aa2 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: de_DE\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Aktionen" @@ -40,14 +48,11 @@ msgstr "&Größe && Position merken" msgid "Re&nderer" msgstr "Re&nderer" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0-Kern)" @@ -352,6 +357,9 @@ msgstr "CPU-Typ:" msgid "Speed:" msgstr "Takt:" +msgid "Frequency:" +msgstr "Frequenz:" + msgid "FPU:" msgstr "FPU-Einheit:" @@ -385,8 +393,8 @@ msgstr "Videokarte:" msgid "Voodoo Graphics" msgstr "Voodoo-Grafik" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a-Grafik" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-Grafik" msgid "XGA Graphics" msgstr "XGA-Grafik" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Soundkarte 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Soundkarte 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Soundkarte 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Soundkarte 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "ISABugger-Gerät" msgid "POST card" msgstr "POST-Code-Karte" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,14 @@ msgstr "Andere Peripheriegeräte" msgid "Click to capture mouse" msgstr "Zum Einfangen des Mauszeigers bitte klicken" -msgid "Press F8+F12 to release mouse" -msgstr "Bitte F8+F12 zur Mausfreigabe drücken" +msgid "Press %1 to release mouse" +msgstr "Bitte %1 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 "Press %1 or middle button to release mouse" +msgstr "Bitte %1 oder die mittlere Maustaste zur Mausfreigabe drücken" + +msgid "Ctrl+End" +msgstr "Strg+Ende" msgid "Bus" msgstr "Bus" @@ -757,9 +759,6 @@ msgstr "%i Wartezustände" msgid "Type" msgstr "Typ" -msgid "Failed to set up PCap" -msgstr "PCap konnte nicht eingerichtet werden" - msgid "No PCap devices found" msgstr "Keine PCap-Geräte gefunden" @@ -790,15 +789,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ohne" -msgid "Unable to load keyboard accelerators." -msgstr "Tastaturbeschleuniger konnten nicht geladen werden." - -msgid "Unable to register raw input." -msgstr "Roheingaben konnten nicht registriert werden." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +801,6 @@ msgstr "Fortgeschrittene Sektorimages" msgid "Flux images" msgstr "Fluximages" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Sind Sie sich sicher, dass Sie einen Hard-Reset für das emulierte System durchführen wollen?" @@ -862,26 +849,14 @@ msgstr "Ein Emulator für alte Computer\n\nAutoren: Miran Grča (OBattler), Rich msgid "Hardware not available" msgstr "Hardware nicht verfügbar" -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 "Bitte stellen Sie sicher, dass libpcap installiert ist und sie eine libpcap-kompatible Netzwerkverbindung nutzen." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Bitte stellen Sie sicher, dass %1 installiert ist und sie eine %1-kompatible Netzwerkverbindung nutzen." msgid "Invalid configuration" msgstr "Ungültige Konfiguration" -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 " 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Vollbildmodus wird aktiviert" @@ -901,8 +876,8 @@ msgstr "Nicht zurücksetzen" msgid "CD-ROM images" msgstr "CD-ROM-Images" -msgid "%hs Device Configuration" -msgstr "%hs-Gerätekonfiguration" +msgid "%1 Device Configuration" +msgstr "%1-Gerätekonfiguration" msgid "Monitor in sleep mode" msgstr "Monitor im Standbymodus" @@ -958,14 +933,8 @@ msgstr "Hard-Reset" msgid "ACPI shutdown" msgstr "ACPI-basiertes Herunterfahren" -msgid "Hard disk (%s)" -msgstr "Festplatte (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Festplatte (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL- oder ESDI CD-ROM-Laufwerke hat es niemals gegeben" @@ -1000,9 +969,6 @@ msgstr "Die Datei konnte nicht beschrieben werden" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "HDI- oder HDX-Images mit einer Sektorgröße größer als 512 kB werden nicht unterstützt." -msgid "USB is not yet supported" -msgstr "USB wird noch nicht unterstützt" - msgid "Disk image file already exists" msgstr "Die Festplattenimagedatei existiert bereits" @@ -1075,9 +1041,6 @@ msgstr "Die Zeitstempel der Eltern- und der Kindesplatte stimmen nicht überein" msgid "Could not fix VHD timestamp." msgstr "Der Zeitstempel der VHD konnte nicht korrigiert werden." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1056,6 @@ 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" @@ -1224,3 +1169,9 @@ msgstr "Schnell" msgid "&Auto-pause on focus loss" msgstr "&Auto-Pause bei Fokusverlust" + +msgid "WinBox is no longer supported" +msgstr "WinBox wird nicht mehr unterstützt" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Die Entwicklung des WinBox-Managers wurde im Jahr 2022 eingestellt, da es an Betreuern mangelte. Da wir unsere Bemühungen darauf richten, 86Box noch besser zu machen, haben wir uns entschlossen, WinBox nicht mehr als Manager zu unterstützen.\n\nEs werden keine weiteren Updates für WinBox zur Verfügung gestellt, und es kann zu fehlerhaftem Verhalten kommen, wenn Sie WinBox weiterhin mit neueren Versionen von 86Box verwenden. Alle Fehlerberichte, die sich auf das Verhalten von WinBox beziehen, werden als ungültig geschlossen.\n\nAuf 86box.net finden Sie eine Liste anderer Manager, die Sie verwenden können." diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 4a6a58db6..fa6d1e2c3 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -1,140 +1,10 @@ -msgid "&Action" -msgstr "&Action" - -msgid "&Keyboard requires capture" -msgstr "&Keyboard requires capture" - -msgid "&Right CTRL is left ALT" -msgstr "&Right CTRL is left ALT" - -msgid "&Hard Reset..." -msgstr "&Hard Reset..." - -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" - -msgid "Ctrl+Alt+&Esc" -msgstr "Ctrl+Alt+&Esc" - -msgid "&Pause" -msgstr "&Pause" - -msgid "E&xit..." -msgstr "E&xit..." - -msgid "&View" -msgstr "&View" - -msgid "&Hide status bar" -msgstr "&Hide status bar" - -msgid "Hide &toolbar" -msgstr "Hide &toolbar" - -msgid "&Resizeable window" -msgstr "&Resizeable window" - -msgid "R&emember size && position" -msgstr "R&emember size && position" - -msgid "Re&nderer" -msgstr "Re&nderer" - -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 "Specify dimensions..." - -msgid "F&orce 4:3 display ratio" -msgstr "F&orce 4:3 display ratio" - -msgid "&Window scale factor" -msgstr "&Window scale factor" - -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 "Filter method" - -msgid "&Nearest" -msgstr "&Nearest" - -msgid "&Linear" -msgstr "&Linear" - -msgid "Hi&DPI scaling" -msgstr "Hi&DPI scaling" - -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Fullscreen\tCtrl+Alt+PgUp" - -msgid "Fullscreen &stretch mode" -msgstr "Fullscreen &stretch mode" - -msgid "&Full screen stretch" -msgstr "&Full screen stretch" - -msgid "&4:3" -msgstr "&4:3" - -msgid "&Square pixels (Keep ratio)" -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" - -msgid "&Inverted VGA monitor" -msgstr "&Inverted VGA monitor" - -msgid "VGA screen &type" -msgstr "VGA screen &type" +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: en_GB\n" +"X-Source-Language: en_US\n" msgid "RGB &Color" msgstr "RGB &Colour" @@ -142,1085 +12,17 @@ msgstr "RGB &Colour" msgid "&RGB Grayscale" msgstr "&RGB Greyscale" -msgid "&Amber monitor" -msgstr "&Amber monitor" - -msgid "&Green monitor" -msgstr "&Green monitor" - -msgid "&White monitor" -msgstr "&White monitor" - -msgid "Grayscale &conversion type" -msgstr "Grayscale &conversion type" - -msgid "BT&601 (NTSC/PAL)" -msgstr "BT&601 (NTSC/PAL)" - -msgid "BT&709 (HDTV)" -msgstr "BT&709 (HDTV)" - -msgid "&Average" -msgstr "&Average" - -msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" -msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" - -msgid "Change contrast for &monochrome display" -msgstr "Change contrast for &monochrome display" - -msgid "&Media" -msgstr "&Media" - -msgid "&Tools" -msgstr "&Tools" - -msgid "&Settings..." -msgstr "&Settings..." - -msgid "&Update status bar icons" -msgstr "&Update status bar icons" - -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Take s&creenshot\tCtrl+F11" - -msgid "&Preferences..." -msgstr "&Preferences..." - -msgid "Enable &Discord integration" -msgstr "Enable &Discord integration" - -msgid "Sound &gain..." -msgstr "Sound &gain..." - -msgid "Begin trace\tCtrl+T" -msgstr "Begin trace\tCtrl+T" - -msgid "End trace\tCtrl+T" -msgstr "End trace\tCtrl+T" - -msgid "&Help" -msgstr "&Help" - -msgid "&Documentation..." -msgstr "&Documentation..." - -msgid "&About 86Box..." -msgstr "&About 86Box..." - -msgid "&New image..." -msgstr "&New image..." - -msgid "&Existing image..." -msgstr "&Existing image..." - -msgid "Existing image (&Write-protected)..." -msgstr "Existing image (&Write-protected)..." - -msgid "&Record" -msgstr "&Record" - -msgid "&Play" -msgstr "&Play" - -msgid "&Rewind to the beginning" -msgstr "&Rewind to the beginning" - -msgid "&Fast forward to the end" -msgstr "&Fast forward to the end" - -msgid "E&ject" -msgstr "E&ject" - -msgid "&Image..." -msgstr "&Image..." - -msgid "E&xport to 86F..." -msgstr "E&xport to 86F..." - -msgid "&Mute" -msgstr "&Mute" - -msgid "E&mpty" -msgstr "E&mpty" - -msgid "&Reload previous image" -msgstr "&Reload previous image" - -msgid "&Folder..." -msgstr "&Folder..." - -msgid "Target &framerate" -msgstr "Target &framerate" - -msgid "&Sync with video" -msgstr "&Sync with video" - -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 "&Select shader..." - -msgid "&Remove shader" -msgstr "&Remove shader" - -msgid "Preferences" -msgstr "Preferences" - -msgid "Sound Gain" -msgstr "Sound Gain" - -msgid "New Image" -msgstr "New Image" - -msgid "Settings" -msgstr "Settings" - -msgid "Specify Main Window Dimensions" -msgstr "Specify Main Window Dimensions" - -msgid "OK" -msgstr "OK" - -msgid "Cancel" -msgstr "Cancel" - -msgid "Save these settings as &global defaults" -msgstr "Save these settings as &global defaults" - -msgid "&Default" -msgstr "&Default" - -msgid "Language:" -msgstr "Language:" - -msgid "Icon set:" -msgstr "Icon set:" - -msgid "Gain" -msgstr "Gain" - -msgid "File name:" -msgstr "File name:" - -msgid "Disk size:" -msgstr "Disk size:" - -msgid "RPM mode:" -msgstr "RPM mode:" - -msgid "Progress:" -msgstr "Progress:" - -msgid "Width:" -msgstr "Width:" - -msgid "Height:" -msgstr "Height:" - -msgid "Lock to this size" -msgstr "Lock to this size" - -msgid "Machine type:" -msgstr "Machine type:" - -msgid "Machine:" -msgstr "Machine:" - -msgid "Configure" -msgstr "Configure" - -msgid "CPU type:" -msgstr "CPU type:" - -msgid "Speed:" -msgstr "Speed:" - -msgid "FPU:" -msgstr "FPU:" - -msgid "Wait states:" -msgstr "Wait states:" - -msgid "MB" -msgstr "MB" - -msgid "Memory:" -msgstr "Memory:" - msgid "Time synchronization" -msgstr "Time synchronization" - -msgid "Disabled" -msgstr "Disabled" - -msgid "Enabled (local time)" -msgstr "Enabled (local time)" - -msgid "Enabled (UTC)" -msgstr "Enabled (UTC)" - -msgid "Dynamic Recompiler" -msgstr "Dynamic Recompiler" - -msgid "Video:" -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:" - -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 "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:" - -msgid "MIDI In Device:" -msgstr "MIDI In Device:" - -msgid "Standalone MPU-401" -msgstr "Standalone MPU-401" - -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:" - -msgid "PCap device:" -msgstr "PCap device:" - -msgid "Network adapter:" -msgstr "Network adapter:" - -msgid "COM1 Device:" -msgstr "COM1 Device:" - -msgid "COM2 Device:" -msgstr "COM2 Device:" - -msgid "COM3 Device:" -msgstr "COM3 Device:" - -msgid "COM4 Device:" -msgstr "COM4 Device:" - -msgid "LPT1 Device:" -msgstr "LPT1 Device:" - -msgid "LPT2 Device:" -msgstr "LPT2 Device:" - -msgid "LPT3 Device:" -msgstr "LPT3 Device:" - -msgid "LPT4 Device:" -msgstr "LPT4 Device:" - -msgid "Serial port 1" -msgstr "Serial port 1" - -msgid "Serial port 2" -msgstr "Serial port 2" - -msgid "Serial port 3" -msgstr "Serial port 3" - -msgid "Serial port 4" -msgstr "Serial port 4" - -msgid "Parallel port 1" -msgstr "Parallel port 1" - -msgid "Parallel port 2" -msgstr "Parallel port 2" - -msgid "Parallel port 3" -msgstr "Parallel port 3" - -msgid "Parallel port 4" -msgstr "Parallel port 4" - -msgid "HD Controller:" -msgstr "HD Controller:" - -msgid "FD Controller:" -msgstr "FD Controller:" - -msgid "Tertiary IDE Controller" -msgstr "Tertiary IDE Controller" - -msgid "Quaternary IDE Controller" -msgstr "Quaternary IDE Controller" - -msgid "SCSI" -msgstr "SCSI" - -msgid "Controller 1:" -msgstr "Controller 1:" - -msgid "Controller 2:" -msgstr "Controller 2:" - -msgid "Controller 3:" -msgstr "Controller 3:" - -msgid "Controller 4:" -msgstr "Controller 4:" - -msgid "Cassette" -msgstr "Cassette" - -msgid "Hard disks:" -msgstr "Hard disks:" - -msgid "&New..." -msgstr "&New..." - -msgid "&Existing..." -msgstr "&Existing..." - -msgid "&Remove" -msgstr "&Remove" - -msgid "Bus:" -msgstr "Bus:" - -msgid "Channel:" -msgstr "Channel:" - -msgid "ID:" -msgstr "ID:" - -msgid "&Specify..." -msgstr "&Specify..." - -msgid "Sectors:" -msgstr "Sectors:" - -msgid "Heads:" -msgstr "Heads:" - -msgid "Cylinders:" -msgstr "Cylinders:" - -msgid "Size (MB):" -msgstr "Size (MB):" - -msgid "Type:" -msgstr "Type:" - -msgid "Image Format:" -msgstr "Image Format:" - -msgid "Block Size:" -msgstr "Block Size:" - -msgid "Floppy drives:" -msgstr "Floppy drives:" - -msgid "Turbo timings" -msgstr "Turbo timings" - -msgid "Check BPB" -msgstr "Check BPB" - -msgid "CD-ROM drives:" -msgstr "CD-ROM drives:" - -msgid "Earlier drive" -msgstr "Earlier drive" - -msgid "MO drives:" -msgstr "MO drives:" - -msgid "ZIP drives:" -msgstr "ZIP drives:" - -msgid "ZIP 250" -msgstr "ZIP 250" - -msgid "ISA RTC:" -msgstr "ISA RTC:" - -msgid "ISA Memory Expansion" -msgstr "ISA Memory Expansion" - -msgid "Card 1:" -msgstr "Card 1:" - -msgid "Card 2:" -msgstr "Card 2:" - -msgid "Card 3:" -msgstr "Card 3:" - -msgid "Card 4:" -msgstr "Card 4:" - -msgid "ISABugger device" -msgstr "ISABugger device" - -msgid "POST card" -msgstr "POST card" - -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - -msgid "86Box" -msgstr "86Box" - -msgid "Error" -msgstr "Error" - -msgid "Fatal error" -msgstr "Fatal error" - -msgid " - PAUSED" -msgstr " - PAUSED" - -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Press Ctrl+Alt+PgDn to return to windowed mode." - -msgid "Speed" -msgstr "Speed" - -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" - -msgid "ZIP images" -msgstr "ZIP images" - -msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." - -msgid "(empty)" -msgstr "(empty)" - -msgid "All files" -msgstr "All files" - -msgid "Turbo" -msgstr "Turbo" - -msgid "On" -msgstr "On" - -msgid "Off" -msgstr "Off" - -msgid "All images" -msgstr "All images" - -msgid "Basic sector images" -msgstr "Basic sector images" - -msgid "Surface images" -msgstr "Surface images" - -msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." - -msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." - -msgid "Machine" -msgstr "Machine" - -msgid "Display" -msgstr "Display" - -msgid "Input devices" -msgstr "Input devices" - -msgid "Sound" -msgstr "Sound" - -msgid "Network" -msgstr "Network" - -msgid "Ports (COM & LPT)" -msgstr "Ports (COM & LPT)" - -msgid "Storage controllers" -msgstr "Storage controllers" - -msgid "Hard disks" -msgstr "Hard disks" - -msgid "Floppy & CD-ROM drives" -msgstr "Floppy & CD-ROM drives" - -msgid "Other removable devices" -msgstr "Other removable devices" - -msgid "Other peripherals" -msgstr "Other peripherals" - -msgid "Click to capture mouse" -msgstr "Click to capture mouse" - -msgid "Press F8+F12 to release mouse" -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 "Bus" -msgstr "Bus" - -msgid "File" -msgstr "File" - -msgid "C" -msgstr "C" - -msgid "H" -msgstr "H" - -msgid "S" -msgstr "S" - -msgid "KB" -msgstr "KB" +msgstr "Time synchronisation" msgid "Could not initialize the video renderer." -msgstr "Could not initialize the video renderer." - -msgid "Default" -msgstr "Default" - -msgid "%i Wait state(s)" -msgstr "%i Wait state(s)" - -msgid "Type" -msgstr "Type" - -msgid "Failed to set up PCap" -msgstr "Failed to set up PCap" - -msgid "No PCap devices found" -msgstr "No PCap devices found" - -msgid "Invalid PCap device" -msgstr "Invalid PCap device" - -msgid "Standard 2-button joystick(s)" -msgstr "Standard 2-button joystick(s)" - -msgid "Standard 4-button joystick" -msgstr "Standard 4-button joystick" - -msgid "Standard 6-button joystick" -msgstr "Standard 6-button joystick" - -msgid "Standard 8-button joystick" -msgstr "Standard 8-button 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 "None" - -msgid "Unable to load keyboard accelerators." -msgstr "Unable to load keyboard accelerators." - -msgid "Unable to register raw input." -msgstr "Unable to register 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 "Floppy %i (%s): %ls" - -msgid "Advanced sector images" -msgstr "Advanced sector images" - -msgid "Flux images" -msgstr "Flux images" - -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Unable to initialize SDL, SDL2.dll is required" - -msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "Are you sure you want to hard reset the emulated machine?" - -msgid "Are you sure you want to exit 86Box?" -msgstr "Are you sure you want to exit 86Box?" - -msgid "Unable to initialize Ghostscript" -msgstr "Unable to initialize Ghostscript" - -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" - -msgid "MO images" -msgstr "MO images" - -msgid "Welcome to 86Box!" -msgstr "Welcome to 86Box!" - -msgid "Internal controller" -msgstr "Internal controller" - -msgid "Exit" -msgstr "Exit" - -msgid "No ROMs found" -msgstr "No ROMs found" - -msgid "Do you want to save the settings?" -msgstr "Do you want to save the settings?" - -msgid "This will hard reset the emulated machine." -msgstr "This will hard reset the emulated machine." - -msgid "Save" -msgstr "Save" - -msgid "About 86Box" -msgstr "About 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 "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" - -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 "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." - -msgid "Invalid configuration" -msgstr "Invalid configuration" - -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 " 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 "Entering fullscreen mode" -msgstr "Entering fullscreen mode" - -msgid "Don't show this message again" -msgstr "Don't show this message again" - -msgid "Don't exit" -msgstr "Don't exit" - -msgid "Reset" -msgstr "Reset" - -msgid "Don't reset" -msgstr "Don't reset" - -msgid "CD-ROM images" -msgstr "CD-ROM images" - -msgid "%hs Device Configuration" -msgstr "%hs Device Configuration" - -msgid "Monitor in sleep mode" -msgstr "Monitor in sleep mode" - -msgid "OpenGL Shaders" -msgstr "OpenGL Shaders" - -msgid "OpenGL options" -msgstr "OpenGL options" - -msgid "You are loading an unsupported configuration" -msgstr "You are loading an unsupported configuration" - -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 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." - -msgid "Continue" -msgstr "Continue" - -msgid "Cassette: %s" -msgstr "Cassette: %s" - -msgid "Cassette images" -msgstr "Cassette images" - -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" - -msgid "Cartridge images" -msgstr "Cartridge images" +msgstr "Could not initialise the video renderer." msgid "Error initializing renderer" -msgstr "Error initializing renderer" +msgstr "Error initialising 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 "OpenGL (3.0 Core) renderer could not be initialised. Use another renderer." -msgid "Resume execution" -msgstr "Resume execution" - -msgid "Pause execution" -msgstr "Pause execution" - -msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" - -msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" - -msgid "Hard reset" -msgstr "Hard reset" - -msgid "ACPI shutdown" -msgstr "ACPI shutdown" - -msgid "Hard disk (%s)" -msgstr "Hard disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" - -msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "MFM/RLL or ESDI CD-ROM drives never existed" - -msgid "Custom..." -msgstr "Custom..." - -msgid "Custom (large)..." -msgstr "Custom (large)..." - -msgid "Add New Hard Disk" -msgstr "Add New Hard Disk" - -msgid "Add Existing Hard Disk" -msgstr "Add Existing Hard Disk" - -msgid "HDI disk images cannot be larger than 4 GB." -msgstr "HDI disk images cannot be larger than 4 GB." - -msgid "Disk images cannot be larger than 127 GB." -msgstr "Disk images cannot be larger than 127 GB." - -msgid "Hard disk images" -msgstr "Hard disk images" - -msgid "Unable to read file" -msgstr "Unable to read file" - -msgid "Unable to write file" -msgstr "Unable to write file" - -msgid "HDI or HDX images with a sector size other than 512 are not supported." -msgstr "HDI or HDX images with a sector size other than 512 are not supported." - -msgid "USB is not yet supported" -msgstr "USB is not yet supported" - -msgid "Disk image file already exists" -msgstr "Disk image file already exists" - -msgid "Please specify a valid file name." -msgstr "Please specify a valid file name." - -msgid "Disk image created" -msgstr "Disk image created" - -msgid "Make sure the file exists and is readable." -msgstr "Make sure the file exists and is readable." - -msgid "Make sure the file is being saved to a writable directory." -msgstr "Make sure the file is being saved to a writable directory." - -msgid "Disk image too large" -msgstr "Disk image too large" - -msgid "Remember to partition and format the newly-created drive." -msgstr "Remember to partition and format the newly-created drive." - -msgid "The selected file will be overwritten. Are you sure you want to use it?" -msgstr "The selected file will be overwritten. Are you sure you want to use it?" - -msgid "Unsupported disk image" -msgstr "Unsupported disk image" - -msgid "Overwrite" -msgstr "Overwrite" - -msgid "Don't overwrite" -msgstr "Don't overwrite" - -msgid "Raw image (.img)" -msgstr "Raw image (.img)" - -msgid "HDI image (.hdi)" -msgstr "HDI image (.hdi)" - -msgid "HDX image (.hdx)" -msgstr "HDX image (.hdx)" - -msgid "Fixed-size VHD (.vhd)" -msgstr "Fixed-size VHD (.vhd)" - -msgid "Dynamic-size VHD (.vhd)" -msgstr "Dynamic-size VHD (.vhd)" - -msgid "Differencing VHD (.vhd)" -msgstr "Differencing VHD (.vhd)" - -msgid "Large blocks (2 MB)" -msgstr "Large blocks (2 MB)" - -msgid "Small blocks (512 KB)" -msgstr "Small blocks (512 KB)" - -msgid "VHD files" -msgstr "VHD files" - -msgid "Select the parent VHD" -msgstr "Select the parent 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 "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?" - -msgid "Parent and child disk timestamps do not match" -msgstr "Parent and child disk timestamps do not match" - -msgid "Could not fix VHD timestamp." -msgstr "Could not fix VHD timestamp." - -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 "Perfect RPM" - -msgid "1% below perfect RPM" -msgstr "1% below perfect RPM" - -msgid "1.5% below perfect RPM" -msgstr "1.5% below perfect RPM" - -msgid "2% below perfect RPM" -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" +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behaviour will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." diff --git a/src/qt/languages/en-US.po b/src/qt/languages/en-US.po index ce7ceb149..e78536c66 100644 --- a/src/qt/languages/en-US.po +++ b/src/qt/languages/en-US.po @@ -1,1226 +1,7 @@ -msgid "&Action" -msgstr "&Action" - -msgid "&Keyboard requires capture" -msgstr "&Keyboard requires capture" - -msgid "&Right CTRL is left ALT" -msgstr "&Right CTRL is left ALT" - -msgid "&Hard Reset..." -msgstr "&Hard Reset..." - -msgid "&Ctrl+Alt+Del\tCtrl+F12" -msgstr "&Ctrl+Alt+Del\tCtrl+F12" - -msgid "Ctrl+Alt+&Esc" -msgstr "Ctrl+Alt+&Esc" - -msgid "&Pause" -msgstr "&Pause" - -msgid "E&xit..." -msgstr "E&xit..." - -msgid "&View" -msgstr "&View" - -msgid "&Hide status bar" -msgstr "&Hide status bar" - -msgid "Hide &toolbar" -msgstr "Hide &toolbar" - -msgid "&Resizeable window" -msgstr "&Resizeable window" - -msgid "R&emember size && position" -msgstr "R&emember size && position" - -msgid "Re&nderer" -msgstr "Re&nderer" - -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 "Specify dimensions..." - -msgid "F&orce 4:3 display ratio" -msgstr "F&orce 4:3 display ratio" - -msgid "&Window scale factor" -msgstr "&Window scale factor" - -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 "Filter method" - -msgid "&Nearest" -msgstr "&Nearest" - -msgid "&Linear" -msgstr "&Linear" - -msgid "Hi&DPI scaling" -msgstr "Hi&DPI scaling" - -msgid "&Fullscreen\tCtrl+Alt+PgUp" -msgstr "&Fullscreen\tCtrl+Alt+PgUp" - -msgid "Fullscreen &stretch mode" -msgstr "Fullscreen &stretch mode" - -msgid "&Full screen stretch" -msgstr "&Full screen stretch" - -msgid "&4:3" -msgstr "&4:3" - -msgid "&Square pixels (Keep ratio)" -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" - -msgid "&Inverted VGA monitor" -msgstr "&Inverted VGA monitor" - -msgid "VGA screen &type" -msgstr "VGA screen &type" - -msgid "RGB &Color" -msgstr "RGB &Color" - -msgid "&RGB Grayscale" -msgstr "&RGB Grayscale" - -msgid "&Amber monitor" -msgstr "&Amber monitor" - -msgid "&Green monitor" -msgstr "&Green monitor" - -msgid "&White monitor" -msgstr "&White monitor" - -msgid "Grayscale &conversion type" -msgstr "Grayscale &conversion type" - -msgid "BT&601 (NTSC/PAL)" -msgstr "BT&601 (NTSC/PAL)" - -msgid "BT&709 (HDTV)" -msgstr "BT&709 (HDTV)" - -msgid "&Average" -msgstr "&Average" - -msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" -msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" - -msgid "Change contrast for &monochrome display" -msgstr "Change contrast for &monochrome display" - -msgid "&Media" -msgstr "&Media" - -msgid "&Tools" -msgstr "&Tools" - -msgid "&Settings..." -msgstr "&Settings..." - -msgid "&Update status bar icons" -msgstr "&Update status bar icons" - -msgid "Take s&creenshot\tCtrl+F11" -msgstr "Take s&creenshot\tCtrl+F11" - -msgid "&Preferences..." -msgstr "&Preferences..." - -msgid "Enable &Discord integration" -msgstr "Enable &Discord integration" - -msgid "Sound &gain..." -msgstr "Sound &gain..." - -msgid "Begin trace\tCtrl+T" -msgstr "Begin trace\tCtrl+T" - -msgid "End trace\tCtrl+T" -msgstr "End trace\tCtrl+T" - -msgid "&Help" -msgstr "&Help" - -msgid "&Documentation..." -msgstr "&Documentation..." - -msgid "&About 86Box..." -msgstr "&About 86Box..." - -msgid "&New image..." -msgstr "&New image..." - -msgid "&Existing image..." -msgstr "&Existing image..." - -msgid "Existing image (&Write-protected)..." -msgstr "Existing image (&Write-protected)..." - -msgid "&Record" -msgstr "&Record" - -msgid "&Play" -msgstr "&Play" - -msgid "&Rewind to the beginning" -msgstr "&Rewind to the beginning" - -msgid "&Fast forward to the end" -msgstr "&Fast forward to the end" - -msgid "E&ject" -msgstr "E&ject" - -msgid "&Image..." -msgstr "&Image..." - -msgid "E&xport to 86F..." -msgstr "E&xport to 86F..." - -msgid "&Mute" -msgstr "&Mute" - -msgid "E&mpty" -msgstr "E&mpty" - -msgid "&Reload previous image" -msgstr "&Reload previous image" - -msgid "&Folder..." -msgstr "&Folder..." - -msgid "Target &framerate" -msgstr "Target &framerate" - -msgid "&Sync with video" -msgstr "&Sync with video" - -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 "&Select shader..." - -msgid "&Remove shader" -msgstr "&Remove shader" - -msgid "Preferences" -msgstr "Preferences" - -msgid "Sound Gain" -msgstr "Sound Gain" - -msgid "New Image" -msgstr "New Image" - -msgid "Settings" -msgstr "Settings" - -msgid "Specify Main Window Dimensions" -msgstr "Specify Main Window Dimensions" - -msgid "OK" -msgstr "OK" - -msgid "Cancel" -msgstr "Cancel" - -msgid "Save these settings as &global defaults" -msgstr "Save these settings as &global defaults" - -msgid "&Default" -msgstr "&Default" - -msgid "Language:" -msgstr "Language:" - -msgid "Icon set:" -msgstr "Icon set:" - -msgid "Gain" -msgstr "Gain" - -msgid "File name:" -msgstr "File name:" - -msgid "Disk size:" -msgstr "Disk size:" - -msgid "RPM mode:" -msgstr "RPM mode:" - -msgid "Progress:" -msgstr "Progress:" - -msgid "Width:" -msgstr "Width:" - -msgid "Height:" -msgstr "Height:" - -msgid "Lock to this size" -msgstr "Lock to this size" - -msgid "Machine type:" -msgstr "Machine type:" - -msgid "Machine:" -msgstr "Machine:" - -msgid "Configure" -msgstr "Configure" - -msgid "CPU type:" -msgstr "CPU type:" - -msgid "Speed:" -msgstr "Speed:" - -msgid "FPU:" -msgstr "FPU:" - -msgid "Wait states:" -msgstr "Wait states:" - -msgid "MB" -msgstr "MB" - -msgid "Memory:" -msgstr "Memory:" - -msgid "Time synchronization" -msgstr "Time synchronization" - -msgid "Disabled" -msgstr "Disabled" - -msgid "Enabled (local time)" -msgstr "Enabled (local time)" - -msgid "Enabled (UTC)" -msgstr "Enabled (UTC)" - -msgid "Dynamic Recompiler" -msgstr "Dynamic Recompiler" - -msgid "Video:" -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:" - -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 "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:" - -msgid "MIDI In Device:" -msgstr "MIDI In Device:" - -msgid "Standalone MPU-401" -msgstr "Standalone MPU-401" - -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:" - -msgid "PCap device:" -msgstr "PCap device:" - -msgid "Network adapter:" -msgstr "Network adapter:" - -msgid "COM1 Device:" -msgstr "COM1 Device:" - -msgid "COM2 Device:" -msgstr "COM2 Device:" - -msgid "COM3 Device:" -msgstr "COM3 Device:" - -msgid "COM4 Device:" -msgstr "COM4 Device:" - -msgid "LPT1 Device:" -msgstr "LPT1 Device:" - -msgid "LPT2 Device:" -msgstr "LPT2 Device:" - -msgid "LPT3 Device:" -msgstr "LPT3 Device:" - -msgid "LPT4 Device:" -msgstr "LPT4 Device:" - -msgid "Serial port 1" -msgstr "Serial port 1" - -msgid "Serial port 2" -msgstr "Serial port 2" - -msgid "Serial port 3" -msgstr "Serial port 3" - -msgid "Serial port 4" -msgstr "Serial port 4" - -msgid "Parallel port 1" -msgstr "Parallel port 1" - -msgid "Parallel port 2" -msgstr "Parallel port 2" - -msgid "Parallel port 3" -msgstr "Parallel port 3" - -msgid "Parallel port 4" -msgstr "Parallel port 4" - -msgid "HD Controller:" -msgstr "HD Controller:" - -msgid "FD Controller:" -msgstr "FD Controller:" - -msgid "Tertiary IDE Controller" -msgstr "Tertiary IDE Controller" - -msgid "Quaternary IDE Controller" -msgstr "Quaternary IDE Controller" - -msgid "SCSI" -msgstr "SCSI" - -msgid "Controller 1:" -msgstr "Controller 1:" - -msgid "Controller 2:" -msgstr "Controller 2:" - -msgid "Controller 3:" -msgstr "Controller 3:" - -msgid "Controller 4:" -msgstr "Controller 4:" - -msgid "Cassette" -msgstr "Cassette" - -msgid "Hard disks:" -msgstr "Hard disks:" - -msgid "&New..." -msgstr "&New..." - -msgid "&Existing..." -msgstr "&Existing..." - -msgid "&Remove" -msgstr "&Remove" - -msgid "Bus:" -msgstr "Bus:" - -msgid "Channel:" -msgstr "Channel:" - -msgid "ID:" -msgstr "ID:" - -msgid "&Specify..." -msgstr "&Specify..." - -msgid "Sectors:" -msgstr "Sectors:" - -msgid "Heads:" -msgstr "Heads:" - -msgid "Cylinders:" -msgstr "Cylinders:" - -msgid "Size (MB):" -msgstr "Size (MB):" - -msgid "Type:" -msgstr "Type:" - -msgid "Image Format:" -msgstr "Image Format:" - -msgid "Block Size:" -msgstr "Block Size:" - -msgid "Floppy drives:" -msgstr "Floppy drives:" - -msgid "Turbo timings" -msgstr "Turbo timings" - -msgid "Check BPB" -msgstr "Check BPB" - -msgid "CD-ROM drives:" -msgstr "CD-ROM drives:" - -msgid "Earlier drive" -msgstr "Earlier drive" - -msgid "MO drives:" -msgstr "MO drives:" - -msgid "ZIP drives:" -msgstr "ZIP drives:" - -msgid "ZIP 250" -msgstr "ZIP 250" - -msgid "ISA RTC:" -msgstr "ISA RTC:" - -msgid "ISA Memory Expansion" -msgstr "ISA Memory Expansion" - -msgid "Card 1:" -msgstr "Card 1:" - -msgid "Card 2:" -msgstr "Card 2:" - -msgid "Card 3:" -msgstr "Card 3:" - -msgid "Card 4:" -msgstr "Card 4:" - -msgid "ISABugger device" -msgstr "ISABugger device" - -msgid "POST card" -msgstr "POST card" - -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - -msgid "86Box" -msgstr "86Box" - -msgid "Error" -msgstr "Error" - -msgid "Fatal error" -msgstr "Fatal error" - -msgid " - PAUSED" -msgstr " - PAUSED" - -msgid "Press Ctrl+Alt+PgDn to return to windowed mode." -msgstr "Press Ctrl+Alt+PgDn to return to windowed mode." - -msgid "Speed" -msgstr "Speed" - -msgid "ZIP %03i %i (%s): %ls" -msgstr "ZIP %03i %i (%s): %ls" - -msgid "ZIP images" -msgstr "ZIP images" - -msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." - -msgid "(empty)" -msgstr "(empty)" - -msgid "All files" -msgstr "All files" - -msgid "Turbo" -msgstr "Turbo" - -msgid "On" -msgstr "On" - -msgid "Off" -msgstr "Off" - -msgid "All images" -msgstr "All images" - -msgid "Basic sector images" -msgstr "Basic sector images" - -msgid "Surface images" -msgstr "Surface images" - -msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." - -msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." -msgstr "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." - -msgid "Machine" -msgstr "Machine" - -msgid "Display" -msgstr "Display" - -msgid "Input devices" -msgstr "Input devices" - -msgid "Sound" -msgstr "Sound" - -msgid "Network" -msgstr "Network" - -msgid "Ports (COM & LPT)" -msgstr "Ports (COM & LPT)" - -msgid "Storage controllers" -msgstr "Storage controllers" - -msgid "Hard disks" -msgstr "Hard disks" - -msgid "Floppy & CD-ROM drives" -msgstr "Floppy & CD-ROM drives" - -msgid "Other removable devices" -msgstr "Other removable devices" - -msgid "Other peripherals" -msgstr "Other peripherals" - -msgid "Click to capture mouse" -msgstr "Click to capture mouse" - -msgid "Press F8+F12 to release mouse" -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 "Bus" -msgstr "Bus" - -msgid "File" -msgstr "File" - -msgid "C" -msgstr "C" - -msgid "H" -msgstr "H" - -msgid "S" -msgstr "S" - -msgid "KB" -msgstr "KB" - -msgid "Could not initialize the video renderer." -msgstr "Could not initialize the video renderer." - -msgid "Default" -msgstr "Default" - -msgid "%i Wait state(s)" -msgstr "%i Wait state(s)" - -msgid "Type" -msgstr "Type" - -msgid "Failed to set up PCap" -msgstr "Failed to set up PCap" - -msgid "No PCap devices found" -msgstr "No PCap devices found" - -msgid "Invalid PCap device" -msgstr "Invalid PCap device" - -msgid "Standard 2-button joystick(s)" -msgstr "Standard 2-button joystick(s)" - -msgid "Standard 4-button joystick" -msgstr "Standard 4-button joystick" - -msgid "Standard 6-button joystick" -msgstr "Standard 6-button joystick" - -msgid "Standard 8-button joystick" -msgstr "Standard 8-button 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 "None" - -msgid "Unable to load keyboard accelerators." -msgstr "Unable to load keyboard accelerators." - -msgid "Unable to register raw input." -msgstr "Unable to register 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 "Floppy %i (%s): %ls" - -msgid "Advanced sector images" -msgstr "Advanced sector images" - -msgid "Flux images" -msgstr "Flux images" - -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Unable to initialize SDL, SDL2.dll is required" - -msgid "Are you sure you want to hard reset the emulated machine?" -msgstr "Are you sure you want to hard reset the emulated machine?" - -msgid "Are you sure you want to exit 86Box?" -msgstr "Are you sure you want to exit 86Box?" - -msgid "Unable to initialize Ghostscript" -msgstr "Unable to initialize Ghostscript" - -msgid "MO %i (%ls): %ls" -msgstr "MO %i (%ls): %ls" - -msgid "MO images" -msgstr "MO images" - -msgid "Welcome to 86Box!" -msgstr "Welcome to 86Box!" - -msgid "Internal controller" -msgstr "Internal controller" - -msgid "Exit" -msgstr "Exit" - -msgid "No ROMs found" -msgstr "No ROMs found" - -msgid "Do you want to save the settings?" -msgstr "Do you want to save the settings?" - -msgid "This will hard reset the emulated machine." -msgstr "This will hard reset the emulated machine." - -msgid "Save" -msgstr "Save" - -msgid "About 86Box" -msgstr "About 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 "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" - -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 "Make sure libpcap is installed and that you are on a libpcap-compatible network connection." - -msgid "Invalid configuration" -msgstr "Invalid configuration" - -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 " 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 "Entering fullscreen mode" -msgstr "Entering fullscreen mode" - -msgid "Don't show this message again" -msgstr "Don't show this message again" - -msgid "Don't exit" -msgstr "Don't exit" - -msgid "Reset" -msgstr "Reset" - -msgid "Don't reset" -msgstr "Don't reset" - -msgid "CD-ROM images" -msgstr "CD-ROM images" - -msgid "%hs Device Configuration" -msgstr "%hs Device Configuration" - -msgid "Monitor in sleep mode" -msgstr "Monitor in sleep mode" - -msgid "OpenGL Shaders" -msgstr "OpenGL Shaders" - -msgid "OpenGL options" -msgstr "OpenGL options" - -msgid "You are loading an unsupported configuration" -msgstr "You are loading an unsupported configuration" - -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 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." - -msgid "Continue" -msgstr "Continue" - -msgid "Cassette: %s" -msgstr "Cassette: %s" - -msgid "Cassette images" -msgstr "Cassette images" - -msgid "Cartridge %i: %ls" -msgstr "Cartridge %i: %ls" - -msgid "Cartridge images" -msgstr "Cartridge images" - -msgid "Error initializing renderer" -msgstr "Error initializing 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." - -msgid "Resume execution" -msgstr "Resume execution" - -msgid "Pause execution" -msgstr "Pause execution" - -msgid "Press Ctrl+Alt+Del" -msgstr "Press Ctrl+Alt+Del" - -msgid "Press Ctrl+Alt+Esc" -msgstr "Press Ctrl+Alt+Esc" - -msgid "Hard reset" -msgstr "Hard reset" - -msgid "ACPI shutdown" -msgstr "ACPI shutdown" - -msgid "Hard disk (%s)" -msgstr "Hard disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" - -msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "MFM/RLL or ESDI CD-ROM drives never existed" - -msgid "Custom..." -msgstr "Custom..." - -msgid "Custom (large)..." -msgstr "Custom (large)..." - -msgid "Add New Hard Disk" -msgstr "Add New Hard Disk" - -msgid "Add Existing Hard Disk" -msgstr "Add Existing Hard Disk" - -msgid "HDI disk images cannot be larger than 4 GB." -msgstr "HDI disk images cannot be larger than 4 GB." - -msgid "Disk images cannot be larger than 127 GB." -msgstr "Disk images cannot be larger than 127 GB." - -msgid "Hard disk images" -msgstr "Hard disk images" - -msgid "Unable to read file" -msgstr "Unable to read file" - -msgid "Unable to write file" -msgstr "Unable to write file" - -msgid "HDI or HDX images with a sector size other than 512 are not supported." -msgstr "HDI or HDX images with a sector size other than 512 are not supported." - -msgid "USB is not yet supported" -msgstr "USB is not yet supported" - -msgid "Disk image file already exists" -msgstr "Disk image file already exists" - -msgid "Please specify a valid file name." -msgstr "Please specify a valid file name." - -msgid "Disk image created" -msgstr "Disk image created" - -msgid "Make sure the file exists and is readable." -msgstr "Make sure the file exists and is readable." - -msgid "Make sure the file is being saved to a writable directory." -msgstr "Make sure the file is being saved to a writable directory." - -msgid "Disk image too large" -msgstr "Disk image too large" - -msgid "Remember to partition and format the newly-created drive." -msgstr "Remember to partition and format the newly-created drive." - -msgid "The selected file will be overwritten. Are you sure you want to use it?" -msgstr "The selected file will be overwritten. Are you sure you want to use it?" - -msgid "Unsupported disk image" -msgstr "Unsupported disk image" - -msgid "Overwrite" -msgstr "Overwrite" - -msgid "Don't overwrite" -msgstr "Don't overwrite" - -msgid "Raw image (.img)" -msgstr "Raw image (.img)" - -msgid "HDI image (.hdi)" -msgstr "HDI image (.hdi)" - -msgid "HDX image (.hdx)" -msgstr "HDX image (.hdx)" - -msgid "Fixed-size VHD (.vhd)" -msgstr "Fixed-size VHD (.vhd)" - -msgid "Dynamic-size VHD (.vhd)" -msgstr "Dynamic-size VHD (.vhd)" - -msgid "Differencing VHD (.vhd)" -msgstr "Differencing VHD (.vhd)" - -msgid "Large blocks (2 MB)" -msgstr "Large blocks (2 MB)" - -msgid "Small blocks (512 KB)" -msgstr "Small blocks (512 KB)" - -msgid "VHD files" -msgstr "VHD files" - -msgid "Select the parent VHD" -msgstr "Select the parent 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 "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?" - -msgid "Parent and child disk timestamps do not match" -msgstr "Parent and child disk timestamps do not match" - -msgid "Could not fix VHD timestamp." -msgstr "Could not fix VHD timestamp." - -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 "Perfect RPM" - -msgid "1% below perfect RPM" -msgstr "1% below perfect RPM" - -msgid "1.5% below perfect RPM" -msgstr "1.5% below perfect RPM" - -msgid "2% below perfect RPM" -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" +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: en_US\n" +"X-Source-Language: en_US\n" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index d8d648691..21fedd7df 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: es_ES\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Acción" @@ -40,14 +48,11 @@ msgstr "&Recordar tamaño y posición" msgid "Re&nderer" msgstr "Re&nderizador" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Velocidad:" +msgid "Frequency:" +msgstr "Frecuencia:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +417,16 @@ msgstr "Mando 3..." msgid "Joystick 4..." msgstr "Mando 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Tarjeta de sonido 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Tarjeta de sonido 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Tarjeta de sonido 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Tarjeta de sonido 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Chequear BPB" msgid "CD-ROM drives:" msgstr "Unidades de CD-ROM:" -msgid "Earlier drive" -msgstr "Unidad anterior" - msgid "MO drives:" msgstr "Unidades MO:" @@ -622,12 +627,6 @@ msgstr "Dispositivo ISABugger" msgid "POST card" msgstr "Tarjeta POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Otros periféricos" msgid "Click to capture mouse" msgstr "Haga click para capturar el ratón" -msgid "Press F8+F12 to release mouse" -msgstr "Pulse F8+F12 para liberar el ratón" +msgid "Press %1 to release mouse" +msgstr "Pulse %1 para liberar el ratón" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "Pulse F8+F12 o el botón central para liberar el ratón" +msgid "Press %1 or middle button to release mouse" +msgstr "Pulse %1 o el botón central para liberar el ratón" msgid "Bus" msgstr "Bus" @@ -757,9 +756,6 @@ msgstr "%i estado(s) de Espera" msgid "Type" msgstr "Tipo" -msgid "Failed to set up PCap" -msgstr "Incapaz de configurar PCap" - msgid "No PCap devices found" msgstr "No se encontraron dispositivos PCap" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ninguno" -msgid "Unable to load keyboard accelerators." -msgstr "No fué posible cargar aceleradores de teclado." - -msgid "Unable to register raw input." -msgstr "No fué posible registrar entrada directa." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Imágenes avanzadas de sector" msgid "Flux images" 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 "¿Está seguro de que quieres hacer una reinicialización completa de la máquina emulada?" @@ -862,26 +846,14 @@ msgstr "Un emulador de ordenadores antigüos\n\nAutores: Miran Grča (OBattler), msgid "Hardware not available" msgstr "Equipo 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 "Asegúrate de que libpcap está instalado y de que estás en una conexión de red compatible con libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Asegúrate de que %1 está instalado y de que estás en una conexión de red compatible con %1." msgid "Invalid configuration" msgstr "Configuración 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 " 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Entrando en modo pantalla completa" @@ -901,8 +873,8 @@ msgstr "No reinicializar" msgid "CD-ROM images" msgstr "Imágenes de CD-ROM" -msgid "%hs Device Configuration" -msgstr "%hs Configuración de Dispositivo" +msgid "%1 Device Configuration" +msgstr "%1 Configuración de Dispositivo" msgid "Monitor in sleep mode" msgstr "Monitor en modo ahorro" @@ -958,14 +930,8 @@ msgstr "Hard reset" msgid "ACPI shutdown" msgstr "Parada ACPI" -msgid "Hard disk (%s)" -msgstr "Disco duro (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Disco duro (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Nunca existieron unidades de CD-ROM MFM/RLL o ESDI" @@ -1000,9 +966,6 @@ msgstr "No se pudo escribir el archivo" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "No se soportan las imágenes HDI o HDX con un tamaño de sector diferente a 512." -msgid "USB is not yet supported" -msgstr "No se soporta aún el USB" - msgid "Disk image file already exists" msgstr "La imagen de disco ya existe" @@ -1075,9 +1038,6 @@ msgstr "Las marcas de tiempo del padre e hijo no coinciden" msgid "Could not fix VHD timestamp." msgstr "No fué posible corregir la marca de tiempo del VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Rápida" msgid "&Auto-pause on focus loss" msgstr "&Pausa automática al perder el foco" + +msgid "WinBox is no longer supported" +msgstr "WinBox ya no recibe soporte" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "El desarrollo del gestor WinBox se detuvo en 2022 debido a la falta de mantenedores. Como dirigimos nuestros esfuerzos a hacer 86Box aún mejor, hemos tomado la decisión de dejar de dar soporte a WinBox como gestor.\n\nNo se proporcionarán más actualizaciones a través de WinBox, y puede encontrar un comportamiento incorrecto si continúa usándolo con versiones más nuevas de 86Box. Cualquier informe de error relacionado con el comportamiento de WinBox será cerrado como inválido.\n\nVaya a 86box.net para una lista de otros gestores que puede utilizar." diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 217827f74..829e9870f 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: fi_FI\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Toiminto" @@ -40,14 +48,11 @@ msgstr "&Muista koko ja sijainti" msgid "Re&nderer" msgstr "&Renderöijä" -msgid "&SDL (Software)" -msgstr "&SDL (ohjelmistopohjainen)" +msgid "&Qt (Software)" +msgstr "&Qt (ohjelmistopohjainen)" -msgid "SDL (&Hardware)" -msgstr "SDL (&laitteistokiihdytetty)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Suorittimen tyyppi:" msgid "Speed:" msgstr "Nopeus:" +msgid "Frequency:" +msgstr "Taajuus:" + msgid "FPU:" msgstr "Apusuoritin:" @@ -385,8 +393,8 @@ msgstr "Näytönohjain:" msgid "Voodoo Graphics" msgstr "Voodoo-grafiikkasuoritin" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a-grafiikkasuoritin" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-grafiikkasuoritin" msgid "XGA Graphics" msgstr "XGA-grafiikkasuoritin" @@ -409,16 +417,16 @@ msgstr "Peliohjain 3..." msgid "Joystick 4..." msgstr "Peliohjain 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Äänikortti 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Äänikortti 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Äänikortti 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Äänikortti 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Tarkista BPB" msgid "CD-ROM drives:" msgstr "CD-ROM-asemat:" -msgid "Earlier drive" -msgstr "Aiemmat asemat" - msgid "MO drives:" msgstr "Magneettisoptiset asemat (MO):" @@ -622,12 +627,6 @@ msgstr "ISABugger-laite" msgid "POST card" msgstr "POST-kortti" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Muut oheislaitteet" msgid "Click to capture mouse" msgstr "Kaappaa hiiri klikkaamalla" -msgid "Press F8+F12 to release mouse" -msgstr "Paina F8+F12 vapauttaaksesi hiiren" +msgid "Press %1 to release mouse" +msgstr "Paina %1 vapauttaaksesi hiiren" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "Paina F8+F12 tai keskipainiketta vapauttaaksesi hiiren" +msgid "Press %1 or middle button to release mouse" +msgstr "Paina %1 tai keskipainiketta vapauttaaksesi hiiren" msgid "Bus" msgstr "Väylä" @@ -757,9 +756,6 @@ msgstr "%i odotustilaa" msgid "Type" msgstr "Tyyppi" -msgid "Failed to set up PCap" -msgstr "PCap-asennus epäonnistui" - msgid "No PCap devices found" msgstr "PCap-laitteita ei löytynyt" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Ei mikään" -msgid "Unable to load keyboard accelerators." -msgstr "Näppäinkiihdyttimien lataus epäonnistui" - -msgid "Unable to register raw input." -msgstr "Raakasyötteen rekisteröinti epäonnistui" - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u Mt (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Kehittyneet sektorilevykuvat" msgid "Flux images" msgstr "Flux-levykuvat" -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 "Haluatko varmasti käynnistää emuloidun tietokoneen uudelleen?" @@ -862,26 +846,14 @@ msgstr "Vanhojen tietokoneiden emulaattori\n\nTekijät: Miran Grča (OBattler), msgid "Hardware not available" msgstr "Laitteisto ei ole saatavilla" -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 "Varmista, että libpcap on asennettu ja että verkkoyhteytesi on libpcap-yhteensopiva." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Varmista, että %1 on asennettu ja että verkkoyhteytesi on %1-yhteensopiva." msgid "Invalid configuration" msgstr "Virheelliset määritykset" -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 " vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PostScript-tulostimelle lähetetyt asiakirjat tallennetaan PostScript (.ps) -tiedostoina." +msgid "%1 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 "%1 vaaditaan PostScript-tiedostojen automaattiseen muuntamiseen PDF-tiedostoiksi.\n\nKaikki geneeriselle PostScript-tulostimelle lähetetyt asiakirjat tallennetaan PostScript (.ps) -tiedostoina." msgid "Entering fullscreen mode" msgstr "Siirrytään koko näytön tilaan" @@ -901,8 +873,8 @@ msgstr "Älä käynnistä uudelleen" msgid "CD-ROM images" msgstr "CD-ROM-levykuvat" -msgid "%hs Device Configuration" -msgstr "%hs - Laitteen määritykset" +msgid "%1 Device Configuration" +msgstr "%1 - Laitteen määritykset" msgid "Monitor in sleep mode" msgstr "Näyttö lepotilassa" @@ -958,14 +930,8 @@ msgstr "Kylmä uudelleenkäynnistys" msgid "ACPI shutdown" msgstr "ACPI-sammutus" -msgid "Hard disk (%s)" -msgstr "Kiintolevy (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Kiintolevy (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL- tai ESDI-CD-ROM-asemia ei ole koskaan ollut olemassa" @@ -1000,9 +966,6 @@ msgstr "Tiedostoon ei voi kirjoittaa" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "HDI- ja HDX-levykuvien ainoa tuettu sektorikoko on 512" -msgid "USB is not yet supported" -msgstr "USB-tukea ei vielä ole" - msgid "Disk image file already exists" msgstr "Levykuva on jo olemassa" @@ -1075,9 +1038,6 @@ msgstr "Ylä- ja alatason levyjen aikaleimat eivät täsmää" msgid "Could not fix VHD timestamp." msgstr "VHD aikaleimaa ei pystytty korjaamaan." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Nopea" msgid "&Auto-pause on focus loss" msgstr "&Automaattinen tauko tarkennuksen hävitessä" + +msgid "WinBox is no longer supported" +msgstr "WinBoxia ei enää tueta" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "WinBox-managerin kehitys lopetettiin vuonna 2022, koska ylläpitäjiä ei ollut riittävästi. Koska suuntaamme ponnistuksemme 86Boxin parantamiseen entisestään, olemme päättäneet olla enää tukematta WinBoxia managerina.\n\nWinBoxin kautta ei enää toimiteta päivityksiä, ja saatat kohdata virheellistä käyttäytymistä, jos jatkat sen käyttöä 86Boxin uudemmissa versioissa. Kaikki WinBoxin käyttäytymiseen liittyvät vikailmoitukset suljetaan virheellisinä.\n\nSiirry osoitteeseen 86box.net saadaksesi luettelon muista käyttämistäsi hallintaohjelmista." diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index be66e5924..f7687132f 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: fr_FR\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Action" @@ -40,14 +48,11 @@ msgstr "S&auvegarder taille && position" msgid "Re&nderer" msgstr "Moteur de &rendu vidéo" -msgid "&SDL (Software)" -msgstr "&SDL (Logiciel)" +msgid "&Qt (Software)" +msgstr "&Qt (Logiciel)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Materiel)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Type du processeur:" msgid "Speed:" msgstr "Vitesse:" +msgid "Frequency:" +msgstr "Fréquence:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Vidéo:" msgid "Voodoo Graphics" msgstr "Graphique Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Graphique IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Graphique IBM 8514/A" msgid "XGA Graphics" msgstr "Graphique XGA" @@ -409,16 +417,16 @@ msgstr "Manette 3..." msgid "Joystick 4..." msgstr "Manette 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Carte son 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Carte son 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Carte son 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Carte son 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "Dispositif ISABugger" msgid "POST card" msgstr "Carte POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Autres périfériques" msgid "Click to capture mouse" msgstr "Cliquer pour capturer la souris" -msgid "Press F8+F12 to release mouse" -msgstr "Appuyer sur F8+F12 pour libérer la souris" +msgid "Press %1 to release mouse" +msgstr "Appuyer sur %1 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 "Press %1 or middle button to release mouse" +msgstr "Appuyer sur %1 ou le bouton central pour libérer la souris" msgid "Bus" msgstr "Bus" @@ -757,9 +756,6 @@ msgstr "%i état(s) d'attente" msgid "Type" msgstr "Type" -msgid "Failed to set up PCap" -msgstr "Impossible d'initialiser PCap" - msgid "No PCap devices found" msgstr "Aucun dispositif PCap trouvé" @@ -790,15 +786,6 @@ msgstr "Système de contrôle de vol Thrustmaster" msgid "None" msgstr "Aucun" -msgid "Unable to load keyboard accelerators." -msgstr "Impossible de charger les accélérateurs de clavier." - -msgid "Unable to register raw input." -msgstr "Impossible de charger l'entrée raw." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u Mo (CTS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Images du secteur avancés" msgid "Flux images" msgstr "Images du flux" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Impossible d'initialiser SDL, SDL2.dll est nécessaire" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Etes-vous sûr de vouloir réinitialiser la machine émulée ?" @@ -862,26 +846,14 @@ msgstr "Un émulateur de vieux ordinateurs\n\nAuteurs: Miran Grča (OBattler), R msgid "Hardware not available" msgstr "Matériel non 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 "Assurez-vous que libpcap est installé et que vou utilisez une connexion réseau compatible avec libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Assurez-vous que %1 est installé et que vou utilisez une connexion réseau compatible avec %1." msgid "Invalid configuration" msgstr "Configuration non valide" -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 " 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Entrer en mode plein écran" @@ -901,8 +873,8 @@ msgstr "Ne pas réinitialiser" msgid "CD-ROM images" msgstr "Images CD-ROM" -msgid "%hs Device Configuration" -msgstr "Configuration du dispositif %hs" +msgid "%1 Device Configuration" +msgstr "Configuration du dispositif %1" msgid "Monitor in sleep mode" msgstr "Moniteur en mode veille" @@ -958,14 +930,8 @@ msgstr "Hard reset" msgid "ACPI shutdown" msgstr "Arrêt ACPI" -msgid "Hard disk (%s)" -msgstr "Disque dur (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Disque dur (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Les lecteurs de CD-ROM MFM/RLL ou ESDI n'ont jamais existé" @@ -1000,9 +966,6 @@ msgstr "Impossible d'écrire le fichier" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Les images HDI ou HDX avec une taille de secteur différente de 512 non sont pas prises en charge." -msgid "USB is not yet supported" -msgstr "USB n'est pas encore pris en charge." - msgid "Disk image file already exists" msgstr "Le fichier de l'image disque existe déjà." @@ -1075,9 +1038,6 @@ msgstr "Les horodatages des disques parent et enfant ne correspondent pas" msgid "Could not fix VHD timestamp." msgstr "Impossible de réparer l'horodatage du VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1225,3 +1167,8 @@ msgstr "Rapide" msgid "&Auto-pause on focus loss" msgstr "&Pause automatique à perte de mise au point" +msgid "WinBox is no longer supported" +msgstr "WinBox n'est plus pris en charge" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Le développement du gestionnaire WinBox s'est arrêté en 2022 en raison d'un manque de mainteneurs. Comme nous concentrons nos efforts sur l'amélioration de 86Box, nous avons pris la décision de ne plus supporter WinBox en tant que gestionnaire.\n\nAucune mise à jour ne sera fournie par WinBox, et vous pourriez rencontrer des comportements incorrects si vous continuez à l'utiliser avec des versions plus récentes de 86Box. Tous les rapports de bogues relatifs au comportement de WinBox seront classés comme non valides.\n\nAllez sur 86box.net pour une liste d'autres gestionnaires que vous pouvez utiliser." diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index b2aa40d28..eb69971b8 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: hr_HR\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Radnje" @@ -40,14 +48,11 @@ msgstr "&Zapamtite veličinu i položaj" msgid "Re&nderer" msgstr "&Renderer" -msgid "&SDL (Software)" -msgstr "&SDL (Softver)" +msgid "&Qt (Software)" +msgstr "&Qt (Softver)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardver)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 jezgra)" @@ -352,6 +357,9 @@ msgstr "Tip procesora:" msgid "Speed:" msgstr "Brzina:" +msgid "Frequency:" +msgstr "Frekvencija:" + msgid "FPU:" msgstr "FPU uređaj:" @@ -385,8 +393,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a grafika" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A grafika" msgid "XGA Graphics" msgstr "XGA grafika" @@ -409,16 +417,16 @@ msgstr "Palica za igru 3..." msgid "Joystick 4..." msgstr "Palica za igru 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvučna kartica 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvučna kartica 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvučna kartica 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvučna kartica 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Provjeraj BPB" msgid "CD-ROM drives:" msgstr "CD-ROM pogoni:" -msgid "Earlier drive" -msgstr "Raniji pogon" - msgid "MO drives:" msgstr "MO pogoni:" @@ -622,12 +627,6 @@ msgstr "Uređaj ISABugger" msgid "POST card" msgstr "Kartica POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Ostali periferni uređaji" msgid "Click to capture mouse" msgstr "Kliknite da uhvatite miš" -msgid "Press F8+F12 to release mouse" -msgstr "Pritisnite F8+F12 za otpustanje miša" +msgid "Press %1 to release mouse" +msgstr "Pritisnite %1 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 "Press %1 or middle button to release mouse" +msgstr "Pritisnite %1 ili srednji gumb miša za otpuštanje miša" msgid "Bus" msgstr "Bus" @@ -757,9 +756,6 @@ msgstr "%i stanje čekanja" msgid "Type" msgstr "Tip" -msgid "Failed to set up PCap" -msgstr "Postavljanje PCap-a nije uspjelo" - msgid "No PCap devices found" msgstr "Nema PCap uređaja" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Bez" -msgid "Unable to load keyboard accelerators." -msgstr "Nije moguće učitati ubrzivače tipkovnice." - -msgid "Unable to register raw input." -msgstr "Nije moguće registrirati neobrađeni unos." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Flux slike" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Jeste li sigurni da želite hard resetirati emulirani sistem?" @@ -862,26 +846,14 @@ msgstr "Emulator starih računala\n\nAutori: Miran Grča (OBattler), RichardG867 msgid "Hardware not available" msgstr "Hardver nije dostupan" -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 "Provjerite je li libpcap instaliran i jeste li na mreži, kompadibilnoj s libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Provjerite je li %1 instaliran i jeste li na mreži, kompadibilnoj s %1." msgid "Invalid configuration" msgstr "Nevažeća konfiguracija" -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 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Ulazim u cijelozaslonski način" @@ -901,8 +873,8 @@ msgstr "Ne resetiraj" msgid "CD-ROM images" msgstr "CD-ROM slike" -msgid "%hs Device Configuration" -msgstr "Konfiguracija uređaja %hs " +msgid "%1 Device Configuration" +msgstr "Konfiguracija uređaja %1" msgid "Monitor in sleep mode" msgstr "Ekran u stanju mirovanja" @@ -958,14 +930,8 @@ msgstr "Ponovno pokretanje" msgid "ACPI shutdown" msgstr "ACPI bazirano gašenje" -msgid "Hard disk (%s)" -msgstr "Tvrdi disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Tvrdi disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL ili ESDI CD-ROM pogoni nisu nikada postojali" @@ -1000,9 +966,6 @@ msgstr "Nije moguće napisati datoteku" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "HDI ili HDX slike s veličinom sektora koja nije 512 kB nisu podržane." -msgid "USB is not yet supported" -msgstr "USB nije još podržano" - msgid "Disk image file already exists" msgstr "Slika diska već postoji" @@ -1075,9 +1038,6 @@ msgstr "Vremenske ozanke matične i poređenog diska ne odgovaraju." msgid "Could not fix VHD timestamp." msgstr "Ne mogu popraviti vremensku oznaku slike VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Brzi" msgid "&Auto-pause on focus loss" msgstr "&Automatska pauza pri gubitku fokusa" + +msgid "WinBox is no longer supported" +msgstr "WinBox is no longer supported" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 352a64749..ac088e148 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: hu_HU\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Művelet" @@ -40,14 +48,11 @@ msgstr "Méret és pozíció &megjegyzése" msgid "Re&nderer" msgstr "&Megjelenítő" -msgid "&SDL (Software)" -msgstr "&SDL (Szoftveres)" +msgid "&Qt (Software)" +msgstr "&Qt (Szoftveres)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardveres)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Processzor:" msgid "Speed:" msgstr "Seb.:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "FPU-egység:" @@ -385,8 +393,8 @@ 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 "IBM 8514/A Graphics" +msgstr "IBM 8514/A-gyorsítókártya" msgid "XGA Graphics" msgstr "XGA-gyorsítókártya" @@ -409,16 +417,16 @@ msgstr "Játékvez. 3..." msgid "Joystick 4..." msgstr "Játékvez. 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Hangkártya 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Hangkártya 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Hangkártya 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Hangkártya 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "ISABugger eszköz" msgid "POST card" msgstr "POST kártya" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Egyéb perifériák" msgid "Click to capture mouse" msgstr "Kattintson az egér elfogásához" -msgid "Press F8+F12 to release mouse" -msgstr "Nyomja meg az F8+F12-t az egér elengédéséhez" +msgid "Press %1 to release mouse" +msgstr "Nyomja meg az %1-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 "Press %1 or middle button to release mouse" +msgstr "Nyomja meg az %1-t vagy a középső gombot az egér elengédéséhez" msgid "Bus" msgstr "Busz" @@ -757,9 +756,6 @@ msgstr "%i várakozási ciklus(ok)" msgid "Type" msgstr "Típus" -msgid "Failed to set up PCap" -msgstr "Nem sikerült a PCap beállítása" - msgid "No PCap devices found" msgstr "Nem találhatóak PCap eszközök" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nincs" -msgid "Unable to load keyboard accelerators." -msgstr "Nem lehet betölteni a billentyűzetgyorsítókat." - -msgid "Unable to register raw input." -msgstr "A közvetlen nyers bevitel regisztrálása nem sikerült." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Továbbfejlesztett szektor képek" msgid "Flux images" msgstr "Flux képekfájlok" -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" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Biztosan szeretné újraindítani az emulált gépet?" @@ -862,26 +846,14 @@ msgstr "Régi számítógépek emulátora\n\nFejlesztők: Miran Grča (OBattler) msgid "Hardware not available" msgstr "Hardver nem elérhető" -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 "Győződjön meg hogy a(z) libpcap telepítve van és jelenleg a libpcap-kompatibilis kapcsolatot használja." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Győződjön meg hogy a(z) %1 telepítve van és jelenleg a %1-kompatibilis kapcsolatot használja." msgid "Invalid configuration" msgstr "Érvénytelen konfiguráció" -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 " 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Teljes képernyős módra váltás" @@ -901,8 +873,8 @@ msgstr "Ne indítsa újra" msgid "CD-ROM images" msgstr "CD-ROM-képek" -msgid "%hs Device Configuration" -msgstr "%hs eszközkonfiguráció" +msgid "%1 Device Configuration" +msgstr "%1 eszközkonfiguráció" msgid "Monitor in sleep mode" msgstr "Képernyő alvó módban" @@ -958,14 +930,8 @@ msgstr "Hardveres újraindítás" msgid "ACPI shutdown" msgstr "ACPI leállítás" -msgid "Hard disk (%s)" -msgstr "Merevlemez (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Merevlemez (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL vagy ESDI CD-ROM meghajtók soha nem léteztek" @@ -1000,9 +966,6 @@ msgstr "A fájl nem írható" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Az 512-től eltérő szektorméretű HDI vagy HDX képek nem támogatottak." -msgid "USB is not yet supported" -msgstr "Az USB még nem támogatott" - msgid "Disk image file already exists" msgstr "A lemezképfájl már létezik" @@ -1075,9 +1038,6 @@ msgstr "A szülő- és a gyermeklemez időbélyegei nem egyeznek" msgid "Could not fix VHD timestamp." msgstr "Nem sikerült kijavítani a VHD időbélyegét." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Gyors" msgid "&Auto-pause on focus loss" msgstr "&Automatikus szünet fókuszvesztéskor" + +msgid "WinBox is no longer supported" +msgstr "A WinBox már nem támogatott" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "A WinBox menedzser fejlesztése 2022-ben leállt karbantartók hiányában. Mivel erőfeszítéseinket a 86Box még jobbá tételére irányítjuk, úgy döntöttünk, hogy a WinBox-ot mint menedzsert nem támogatjuk tovább.\n\nA WinBoxon keresztül nem lesznek további frissítések, és hibás viselkedéssel találkozhat, ha továbbra is a 86Box újabb verzióival használja. A WinBox viselkedésével kapcsolatos hibajelentéseket érvénytelennek nyilvánítjuk.\n\nA 86box.net oldalon talál egy listát más kezelőkről, amelyeket használhat." diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index df71d148b..0ce1efabb 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: it_IT\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Azione" @@ -40,14 +48,11 @@ msgstr "R&icorda dimensioni e posizione" msgid "Re&nderer" msgstr "Re&nderer" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Tipo del CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequenza:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Grafica Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafica IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafica IBM 8514/A" msgid "XGA Graphics" msgstr "Grafica XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Scheda audio 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Scheda audio 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Scheda audio 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Scheda audio 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Verifica BPB" msgid "CD-ROM drives:" msgstr "Unità CD-ROM:" -msgid "Earlier drive" -msgstr "Unità anteriore" - msgid "MO drives:" msgstr "Unità magneto-ottiche:" @@ -622,12 +627,6 @@ msgstr "Dispositivo ISABugger" msgid "POST card" msgstr "Scheda POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Altre periferiche" msgid "Click to capture mouse" msgstr "Fare clic per catturare mouse" -msgid "Press F8+F12 to release mouse" -msgstr "Premi F8+F12 per rilasciare il mouse" +msgid "Press %1 to release mouse" +msgstr "Premi %1 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 "Press %1 or middle button to release mouse" +msgstr "Premi %1 o pulsante centrale per rilasciare il mouse" msgid "Bus" msgstr "Bus" @@ -757,9 +756,6 @@ msgstr "%i stati d'attesa" msgid "Type" msgstr "Tipo" -msgid "Failed to set up PCap" -msgstr "Impossibile impostare PCap" - msgid "No PCap devices found" msgstr "Nessun dispositivo PCap trovato" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nessuno" -msgid "Unable to load keyboard accelerators." -msgstr "Impossibile caricare gli acceleratori da tastiera." - -msgid "Unable to register raw input." -msgstr "Impossibile registrare input raw." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Immagini da settori avanzati" msgid "Flux images" msgstr "Immagini flusso" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Impossibile inizializzare SDL, SDL2.dll è necessario" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Sei sicuro di voler riavviare la macchina emulata?" @@ -862,26 +846,14 @@ msgstr "Un emulatore di computer vecchi\n\nAutori: Miran Grča (OBattler), Richa msgid "Hardware not available" msgstr "Hardware non disponibile" -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 "Controllare se libpcap è installato e che tu sia connesso ad una connessione libpcap compatibile." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Controllare se %1 è installato e che tu sia connesso ad una connessione %1 compatibile." msgid "Invalid configuration" msgstr "Configurazione invalida" -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 " è 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 "%1 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 "%1 è 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 "Entering fullscreen mode" msgstr "Entrando nella modalità schermo intero" @@ -901,8 +873,8 @@ msgstr "Non riavviare" msgid "CD-ROM images" msgstr "Immagini CD-ROM" -msgid "%hs Device Configuration" -msgstr "Configurazione del dispositivo %hs" +msgid "%1 Device Configuration" +msgstr "Configurazione del dispositivo %1" msgid "Monitor in sleep mode" msgstr "Monitor in modalità riposo" @@ -958,14 +930,8 @@ msgstr "Riavvia" msgid "ACPI shutdown" msgstr "Arresto ACPI" -msgid "Hard disk (%s)" -msgstr "Hard disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Hard disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Le unità CD-ROM MFM/RLL o ESDI non sono mai esistite." @@ -1000,9 +966,6 @@ msgstr "Impossibile scrivere al file" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Le immagini HDI o HDX con settori di dimensioni diverse da 512 non sono supportati." -msgid "USB is not yet supported" -msgstr "USB non è ancora supportato" - msgid "Disk image file already exists" msgstr "Immagine disco già esiste" @@ -1075,9 +1038,6 @@ msgstr "Le marcature di tempo padre e figlio non corrispondono" msgid "Could not fix VHD timestamp." msgstr "Impossibile aggiustare marcature di tempo VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Veloce" msgid "&Auto-pause on focus loss" msgstr "&Pausa automatica alla perdita della messa a fuoco" + +msgid "WinBox is no longer supported" +msgstr "WinBox non è più supportato" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Lo sviluppo del gestore WinBox si è interrotto nel 2022 per mancanza di manutentori. Poiché i nostri sforzi sono rivolti a rendere 86Box ancora migliore, abbiamo deciso di non supportare più WinBox come gestore.\n\nNon saranno forniti ulteriori aggiornamenti tramite WinBox e si potrebbe riscontrare un comportamento non corretto se si continua a utilizzarlo con versioni più recenti di 86Box. Tutte le segnalazioni di bug relative al comportamento di WinBox saranno chiuse in quanto non valide.\n\nPer un elenco di altri gestori utilizzabili, visitare 86box.net." diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7ea47bc1a..c20848be6 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: ja_JP\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "操作(&A)" @@ -40,17 +48,14 @@ msgstr "ウィンドウのサイズと位置を保存(&E)" msgid "Re&nderer" msgstr "レンダラー(&N)" -msgid "&SDL (Software)" -msgstr "SDL (ソフトウェア)(&S)" +msgid "&Qt (Software)" +msgstr "Qt (ソフトウェア)(&Q)" -msgid "SDL (&Hardware)" -msgstr "SDL (ハードウェア)(&H)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (OpenGL)(&O)" +msgid "Qt (&OpenGL)" +msgstr "Qt (OpenGL)(&O)" msgid "Open&GL (3.0 Core)" -msgstr "OpenGL (3.0コア)(&G)" +msgstr "OpenGL (3.0 Core)(&G)" msgid "&VNC" msgstr "VNC(&V)" @@ -352,6 +357,9 @@ msgstr "CPUタイプ:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻度:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "ビデオカード:" msgid "Voodoo Graphics" msgstr "Voodooグラフィック" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/aグラフィック" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/Aグラフィック" msgid "XGA Graphics" msgstr "XGAグラフィック" @@ -409,16 +417,16 @@ msgstr "ジョイスティック3..." msgid "Joystick 4..." msgstr "ジョイスティック4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "サウンドカード1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "サウンドカード2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "サウンドカード3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "サウンドカード4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "BPBチェック" msgid "CD-ROM drives:" msgstr "CD-ROMドライブ:" -msgid "Earlier drive" -msgstr "先のドライブ" - msgid "MO drives:" msgstr "光磁気ドライブ:" @@ -622,12 +627,6 @@ msgstr "ISABuggerデバイス" msgid "POST card" msgstr "POSTカード" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Meiryo UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "他の周辺デバイス" msgid "Click to capture mouse" msgstr "左クリックでマウスをキャプチャします" -msgid "Press F8+F12 to release mouse" -msgstr "F8+F12キーでマウスを解放します" +msgid "Press %1 to release mouse" +msgstr "%1キーでマウスを解放します" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "F8+F12キーまたは中クリックでマウスを解放します" +msgid "Press %1 or middle button to release mouse" +msgstr "%1キーまたは中クリックでマウスを解放します" msgid "Bus" msgstr "バス" @@ -757,9 +756,6 @@ msgstr "%iつのウェイト ステート" msgid "Type" msgstr "タイプ" -msgid "Failed to set up PCap" -msgstr "PCapのセットアップに失敗しました" - msgid "No PCap devices found" msgstr "PCapデバイスがありません" @@ -790,15 +786,6 @@ msgstr "Thrustmaster飛行制御システム" 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)" @@ -811,9 +798,6 @@ 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 "使用中のマシンをハード リセットしますか?" @@ -862,26 +846,14 @@ msgstr "古いパソコンのエミュレーター\n\n著者: Miran Grča (OBatt 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に対応したネットワークに接続されてるか確認してください。" +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "がインストールされてるか、%1に対応したネットワークに接続されてるか確認してください。" 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に自動変換するにはlibgsが必要です。\n\n汎用PostScriptプリンターに送信された文書は、PostScript (.ps) ファイルとして保存されます。" +msgid "%1 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に自動変換するには%1が必要です。\n\n汎用PostScriptプリンターに送信された文書は、PostScript (.ps) ファイルとして保存されます。" msgid "Entering fullscreen mode" msgstr "全画面モードを入力" @@ -901,8 +873,8 @@ msgstr "リセットしない" msgid "CD-ROM images" msgstr "CD-ROMイメージ" -msgid "%hs Device Configuration" -msgstr "%hs のデバイス設定" +msgid "%1 Device Configuration" +msgstr "%1 のデバイス設定" msgid "Monitor in sleep mode" msgstr "モニターのスリープモード" @@ -938,7 +910,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 Core) レンダラーが初期化できません。別のレンダラーを使用してください。" msgid "Resume execution" msgstr "実行を再開" @@ -958,14 +930,8 @@ msgstr "ハードリセット" msgid "ACPI shutdown" msgstr "ACPIシャットダウン" -msgid "Hard disk (%s)" -msgstr "ハードディスク (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "ハードディスク (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLLやESDI CD-ROMドライブが存在しません" @@ -1000,9 +966,6 @@ 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 "ディスクイメージファイルが既に存在します" @@ -1075,9 +1038,6 @@ msgstr "親ディスクと子ディスクのタイムス タンプが一致し msgid "Could not fix VHD timestamp." msgstr "VHD のタイムスタンプを修正できません。" -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "速い" msgid "&Auto-pause on focus loss" msgstr "フォーカスが奪われると自動停止(&A)" + +msgid "WinBox is no longer supported" +msgstr "WinBoxはサポート終了" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "WinBoxマネージャーの開発は、メンテナ不足のため2022年に停止しました。86Boxをより良いものにするため、WinBoxをマネージャーとしてサポートしないことを決定しました。\n\nWinBoxを使ったアップデートは今後提供されませんし、86Boxの新しいバージョンでWinBoxを使い続けると、正しくない動作に遭遇するかもしれません。WinBoxの動作に関連するバグレポートは無効としてクローズされます。\n\n86box.netに他のマネージャのリストがあります。" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index ac4476ca8..afecf78f6 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: ko_KR\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "동작(&A)" @@ -40,17 +48,14 @@ msgstr "창 크기와 위치를 기억하기(&E)" msgid "Re&nderer" msgstr "렌더러(&N)" -msgid "&SDL (Software)" -msgstr "SDL (소프트웨어)(&S)" +msgid "&Qt (Software)" +msgstr "Qt (소프트웨어)(&Q)" -msgid "SDL (&Hardware)" -msgstr "SDL (하드웨어)(&H)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (OpenGL)(&O)" +msgid "Qt (&OpenGL)" +msgstr "Qt (OpenGL)(&O)" msgid "Open&GL (3.0 Core)" -msgstr "OpenGL (3.0 코어)(&G)" +msgstr "OpenGL (3.0 Core)(&G)" msgid "&VNC" msgstr "VNC(&V)" @@ -352,6 +357,9 @@ msgstr "CPU 종류:" msgid "Speed:" msgstr "속도:" +msgid "Frequency:" +msgstr "빈도:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "비디오 카드:" msgid "Voodoo Graphics" msgstr "Voodoo 그래픽" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a 그래픽" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A 그래픽" msgid "XGA Graphics" msgstr "XGA 그래픽" @@ -409,16 +417,16 @@ msgstr "조이스틱 3..." msgid "Joystick 4..." msgstr "조이스틱 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "사운드 카드 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "사운드 카드 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "사운드 카드 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "사운드 카드 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "BPB 확인" msgid "CD-ROM drives:" msgstr "CD-ROM 드라이브:" -msgid "Earlier drive" -msgstr "이전 드라이브" - msgid "MO drives:" msgstr "광자기 드라이브:" @@ -622,12 +627,6 @@ msgstr "ISABugger 장치" msgid "POST card" msgstr "POST 카드" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Malgun Gothic" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "기타 주변기기" msgid "Click to capture mouse" msgstr "이 창을 클릭하면 마우스를 사용합니다" -msgid "Press F8+F12 to release mouse" -msgstr "F12+F8키를 누르면 마우스를 해제합니다" +msgid "Press %1 to release mouse" +msgstr "%1키를 누르면 마우스를 해제합니다" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "F12+F8키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" +msgid "Press %1 or middle button to release mouse" +msgstr "%1키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" msgid "Bus" msgstr "버스" @@ -757,9 +756,6 @@ msgstr "%i 대기 상태" msgid "Type" msgstr "형식" -msgid "Failed to set up PCap" -msgstr "PCap 설정에 실패했습니다" - msgid "No PCap devices found" msgstr "PCap 장치가 없습니다" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "없음" -msgid "Unable to load keyboard accelerators." -msgstr "키보드 가속기를 불러올 수 없습니다." - -msgid "Unable to register raw input." -msgstr "Raw 입력을 등록할 수 없습니다." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "어드밴스드 섹터 이미지" msgid "Flux images" msgstr "플럭스 이미지" -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 "실행중인 머신을 재시작하시겠습니까?" @@ -862,26 +846,14 @@ msgstr "고전 컴퓨터 에뮬레이터\n\n저자: Miran Grča (OBattler), Rich 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에 대응하는 네트워크에 접속되어 있는지 확인해 주세요." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "이 설치되었는지 %1에 대응하는 네트워크에 접속되어 있는지 확인해 주세요." 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 "%1 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 "%1은(는) PostScript 파일을 PDF로 자동변환하는 데에 필요합니다.\n\n표준 PostScript 프린터로 보내신 임의의 문서는 PostScript (.ps) 파일로 저장됩니다." msgid "Entering fullscreen mode" msgstr "전체 화면으로 전환" @@ -901,8 +873,8 @@ msgstr "재시작 안함" msgid "CD-ROM images" msgstr "CD-ROM 이미지" -msgid "%hs Device Configuration" -msgstr "%hs 장치 설정" +msgid "%1 Device Configuration" +msgstr "%1 장치 설정" msgid "Monitor in sleep mode" msgstr "모니터 절전 모드" @@ -958,14 +930,8 @@ msgstr "재시작" msgid "ACPI shutdown" msgstr "ACPI 종료" -msgid "Hard disk (%s)" -msgstr "하드 디스크 (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "하드 디스크 (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL 또는 ESDI CD-ROM 드라이브가 존재하지 않습니다" @@ -1000,9 +966,6 @@ 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 "디스크 이미지 파일이 이미 존재합니다" @@ -1075,9 +1038,6 @@ msgstr "부모 디스크와 자식 디스크의 타임스탬프가 일치하지 msgid "Could not fix VHD timestamp." msgstr "VHD 타임스탬프를 고칠 수 없습니다" -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "빠른" msgid "&Auto-pause on focus loss" msgstr "집중력 저하 시 자동 일시 중지(&A)" + +msgid "WinBox is no longer supported" +msgstr "WinBox는 더 이상 지원되지 않습니다" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "WinBox 매니저의 개발은 유지 관리자의 부족으로 인해 2022년에 중단되었습니다. 86Box를 더욱 개선하기 위한 노력의 일환으로 WinBox 매니저를 더 이상 지원하지 않기로 결정했습니다.\n\nWinBox를 통해 더 이상의 업데이트는 제공되지 않으며, 최신 버전의 86Box를 계속 사용할 경우 잘못된 동작이 발생할 수 있습니다. WinBox 동작과 관련된 모든 버그 보고는 유효하지 않은 것으로 종료됩니다.\n\n사용할 수 있는 다른 관리자 목록을 보려면 86box.net으로 이동하세요." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index b24e338f4..993e6633a 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: pl_PL\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Akcje" @@ -40,14 +48,11 @@ msgstr "P&amiętaj rozmiar &i pozycję" msgid "Re&nderer" msgstr "Re&nderer" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Rodzaj procesora:" msgid "Speed:" msgstr "Szybkość:" +msgid "Frequency:" +msgstr "Częstotliwość:" + msgid "FPU:" msgstr "Jednostka FPU:" @@ -385,8 +393,8 @@ msgstr "Wideo:" msgid "Voodoo Graphics" msgstr "Grafika Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Karta dźwiękowa 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Karta dźwiękowa 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Karta dźwiękowa 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Karta dźwiękowa 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "Urządzenie ISABugger" msgid "POST card" msgstr "Karta POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Inne urządzenia peryferyjne" msgid "Click to capture mouse" msgstr "Kliknij w celu przechwycenia myszy" -msgid "Press F8+F12 to release mouse" -msgstr "Naciśnij klawisze F8+F12 w celu uwolnienia myszy" +msgid "Press %1 to release mouse" +msgstr "Naciśnij klawisze %1 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 "Press %1 or middle button to release mouse" +msgstr "Naciśnij klawisze %1 lub środkowy przycisk w celu uwolnienia myszy" msgid "Bus" msgstr "Magistrala" @@ -757,9 +756,6 @@ msgstr "%i Stany oczekiwania" msgid "Type" msgstr "Rodzaj" -msgid "Failed to set up PCap" -msgstr "Nie udało się ustawić PCap" - msgid "No PCap devices found" msgstr "Nie znaleziono urządzeń PCap" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Żaden" -msgid "Unable to load keyboard accelerators." -msgstr "Nie można załadować akceleratorów klawiaturowych." - -msgid "Unable to register raw input." -msgstr "Nie można zarejestrować surowych danych wejściowych." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Zaawansowane obrazy sektorów" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nie można zainicjować SDL, wymagany SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Jesteś pewien że chcesz wykonać twardy reset emulowanej maszyny?" @@ -862,26 +846,14 @@ msgstr "Emulator starych komputerów\n\nAutorzy: Miran Grča (OBattler), Richard msgid "Hardware not available" msgstr "Sprzęt niedostępny" -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 "Sprawdź, czy libpcap jest zainstalowany i czy posiadasz połączenie sieciowe kompatybilne z libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Sprawdź, czy %1 jest zainstalowany i czy posiadasz połączenie sieciowe kompatybilne z %1." msgid "Invalid configuration" msgstr "Nieprawidłowa konfiguracja" -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 " 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Przechodzenie do trybu pełnoekranowego" @@ -901,8 +873,8 @@ msgstr "Nie przywracaj" msgid "CD-ROM images" msgstr "Obrazy CD-ROM" -msgid "%hs Device Configuration" -msgstr "Konfiguracja urządzenia %hs" +msgid "%1 Device Configuration" +msgstr "Konfiguracja urządzenia %1" msgid "Monitor in sleep mode" msgstr "Monitor w trybie czuwania" @@ -958,14 +930,8 @@ msgstr "Twardy reset" msgid "ACPI shutdown" msgstr "Wyłączenie ACPI" -msgid "Hard disk (%s)" -msgstr "Dysk twardy (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Dysk twardy (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Napędy CD-ROM MFM/RLL lub ESDI nigdy nie istniały" @@ -1000,9 +966,6 @@ msgstr "Nie można zapisać pliku" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Obrazy HDI lub HDX z rozmiarem sektora innym niż 512 nie są wspierane." -msgid "USB is not yet supported" -msgstr "USB nie jest jeszcze wspierane" - msgid "Disk image file already exists" msgstr "Plik obrazu dysku już istnieje" @@ -1075,9 +1038,6 @@ msgstr "Sygnatury czasowe dysku nadrzędnego i podrzędnego nie zgadzają się" msgid "Could not fix VHD timestamp." msgstr "Nie można naprawić sygnatury czasowej VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Szybki" msgid "&Auto-pause on focus loss" msgstr "&Automatyczna pauza po utracie fokusu" + +msgid "WinBox is no longer supported" +msgstr "WinBox nie jest już wspierany" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Rozwój menedżera WinBox został zatrzymany w 2022 roku z powodu braku opiekunów. Ponieważ kierujemy nasze wysiłki na uczynienie 86Box jeszcze lepszym, podjęliśmy decyzję o zaprzestaniu wspierania WinBox jako menedżera.\n\nŻadne dalsze aktualizacje nie będą dostarczane za pośrednictwem WinBox i możesz napotkać nieprawidłowe zachowanie, jeśli będziesz go nadal używać z nowszymi wersjami 86Box. Wszelkie zgłoszenia błędów związane z działaniem WinBox zostaną zamknięte jako nieważne.\n\nLista innych menedżerów, z których można korzystać, znajduje się na stronie 86box.net." diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 0db661b4f..642031e9a 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: pt_BR\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Ação" @@ -40,14 +48,11 @@ msgstr "&Lembrar tamanho e posição" msgid "Re&nderer" msgstr "&Renderizador" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (Núcleo 3.0)" @@ -352,6 +357,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "3DFX Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gráficos IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gráficos IBM 8514/A" msgid "XGA Graphics" msgstr "Gráficos XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Placa de som 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Placa de som 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Placa de som 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Placa de som 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "Dispositivo ISABugger" msgid "POST card" msgstr "Placa de diagnóstico" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Outros periféricos" msgid "Click to capture mouse" msgstr "Clique para capturar o mouse" -msgid "Press F8+F12 to release mouse" -msgstr "Aperte F8+F12 para liberar o mouse" +msgid "Press %1 to release mouse" +msgstr "Aperte %1 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 "Press %1 or middle button to release mouse" +msgstr "Aperte %1 ou botão do meio para liberar o mouse" msgid "Bus" msgstr "Barramento" @@ -757,9 +756,6 @@ msgstr "%i estado(s) de espera" msgid "Type" msgstr "Tipo" -msgid "Failed to set up PCap" -msgstr "Não foi possível configurar o PCap" - msgid "No PCap devices found" msgstr "Nenhum dispositivo PCap encontrado" @@ -790,15 +786,6 @@ msgstr "Sistema de Controle de Voo Thrustmaster" msgid "None" msgstr "Nada" -msgid "Unable to load keyboard accelerators." -msgstr "Não foi possível carregar os aceleradores do teclado." - -msgid "Unable to register raw input." -msgstr "Não foi possível registrar a entrada bruta." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Imagens de setor avançado" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Não é possível inicializar o SDL, é necessário o SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Tem certeza de que deseja reiniciar completamente a máquina emulada?" @@ -862,26 +846,14 @@ msgstr "Um emulador de computadores antigos\n\nAutores: Miran Grča (OBattler), msgid "Hardware not available" msgstr "Hardware não disponível" -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 "Certifique-se de que libpcap esteja instalado e que você tenha uma conexão de rede compatível com libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Certifique-se de que %1 esteja instalado e que você tenha uma conexão de rede compatível com %1." msgid "Invalid configuration" msgstr "Configuração 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 " é 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 "%1 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 "%1 é 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 "Entering fullscreen mode" msgstr "Entrando no modo de tela cheia" @@ -901,8 +873,8 @@ msgstr "Não reiniciar" msgid "CD-ROM images" msgstr "Imagens de CD-ROM" -msgid "%hs Device Configuration" -msgstr "Configuração do dispositivo %hs" +msgid "%1 Device Configuration" +msgstr "Configuração do dispositivo %1" msgid "Monitor in sleep mode" msgstr "Monitor em modo de suspensão" @@ -958,14 +930,8 @@ msgstr "Reinicialização completa" msgid "ACPI shutdown" msgstr "Desligamento por ACPI" -msgid "Hard disk (%s)" -msgstr "Disco rígido (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Disco rígido (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "As unidades de CD-ROM MFM/RLL ou ESDI nunca existiram" @@ -1000,9 +966,6 @@ msgstr "Não foi possível escrever o arquivo" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Imagens HDI ou HDX com um tamanho de setor que não seja 512 não são suportadas." -msgid "USB is not yet supported" -msgstr "O USB ainda não é suportado" - msgid "Disk image file already exists" msgstr "Esta imagem existe" @@ -1075,9 +1038,6 @@ msgstr "A data/hora dos arquivos de pais e filhos não correspondem" msgid "Could not fix VHD timestamp." msgstr "Não foi possível consertar o carimbo de data/hora da VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Rápido" msgid "&Auto-pause on focus loss" msgstr "Pausa &automática ao perder o foco" + +msgid "WinBox is no longer supported" +msgstr "O WinBox não é mais suportado" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "O desenvolvimento do gerenciador WinBox foi interrompido em 2022 devido à falta de mantenedores. Conforme direcionamos nossos esforços para tornar o 86Box ainda melhor, tomamos a decisão de não oferecer mais suporte ao WinBox como gerenciador.\n\nAtualizações não serão mais fornecidas através do WinBox, e você poderá encontrar comportamentos incorretos caso continue a usá-lo com versões mais recentes do 86Box. Quaisquer relatórios de bugs relacionados ao comportamento do WinBox serão fechados como inválidos.\n\nAcesse 86box.net para obter uma lista de outros gerenciadores que você pode usar." diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 8f080e423..3aa004e83 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: pt_PT\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Ação" @@ -40,14 +48,11 @@ msgstr "&Lembrar tamanho e posição" msgid "Re&nderer" msgstr "&Renderizador" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (Núcleo 3.0)" @@ -352,6 +357,9 @@ msgstr "Tipo do CPU:" msgid "Speed:" msgstr "Velocidade:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Gráficos Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gráficos IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gráficos IBM 8514/A" msgid "XGA Graphics" msgstr "Gráficos XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Placa de som 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Placa de som 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Placa de som 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Placa de som 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Verificar BPB" msgid "CD-ROM drives:" msgstr "Unidades CD-ROM:" -msgid "Earlier drive" -msgstr "Unidade anterior" - msgid "MO drives:" msgstr "Unidades magneto-ópticas:" @@ -622,12 +627,6 @@ msgstr "Dispositivo ISABugger" msgid "POST card" msgstr "Placa POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Outros dispositivos" msgid "Click to capture mouse" msgstr "Clique para capturar o rato" -msgid "Press F8+F12 to release mouse" -msgstr "Pressione F8+F12 para soltar o rato" +msgid "Press %1 to release mouse" +msgstr "Pressione %1 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 "Press %1 or middle button to release mouse" +msgstr "Pressione %1 ou tecla média para soltar o rato" msgid "Bus" msgstr "Barramento" @@ -757,9 +756,6 @@ msgstr "%i estado(s) de espera" msgid "Type" msgstr "Tipo" -msgid "Failed to set up PCap" -msgstr "Falha na configuração de PCap" - msgid "No PCap devices found" msgstr "Não foi encontrado um dispositivo PCap" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Nenhum" -msgid "Unable to load keyboard accelerators." -msgstr "Não foi possível inicializar os aceleradores de teclado." - -msgid "Unable to register raw input." -msgstr "Não foi possível registar a entrada bruta." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CCS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Imagens avançadas de sector" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Tem a certeza de que quer um reinício completo da máquina emulada?" @@ -862,26 +846,14 @@ msgstr "Um emulador de computadores antigos\n\nAutores: Miran Grča (OBattler), msgid "Hardware not available" msgstr "Hardware não disponível" -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 "Certifique-se de que a biblioteca libpcap está instalada e de que está a utilizar uma ligação de rede compatível com a biblioteca libpcap." +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Certifique-se de que a biblioteca %1 está instalada e de que está a utilizar uma ligação de rede compatível com a biblioteca %1." msgid "Invalid configuration" msgstr "Configuração 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 " é 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 "%1 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 "%1 é 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 "Entering fullscreen mode" msgstr "A entrar no modo de ecrã cheio" @@ -901,8 +873,8 @@ msgstr "Não reiniciar" msgid "CD-ROM images" msgstr "Imagens CD-ROM" -msgid "%hs Device Configuration" -msgstr "Configuração de dispositivo %hs" +msgid "%1 Device Configuration" +msgstr "Configuração de dispositivo %1" msgid "Monitor in sleep mode" msgstr "Ecrã em modo de sono" @@ -958,14 +930,8 @@ msgstr "Reinicialização completa" msgid "ACPI shutdown" msgstr "Encerramento ACPI" -msgid "Hard disk (%s)" -msgstr "Disco rígido (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Disco rígido (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "Unidades CD-ROM com barramento MFM/RLL ou ESDI nunca existiram!" @@ -1000,9 +966,6 @@ msgstr "Não foi possível escrever o ficheiro" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Imagens HDI ou HDX com um tamanho de sector diferente de 512 não são suportadas." -msgid "USB is not yet supported" -msgstr "O barramento USB ainda não tem suporte" - msgid "Disk image file already exists" msgstr "A imagem de disco já existe" @@ -1075,9 +1038,6 @@ msgstr "Os carimbos de data/hora dos discos pai e filho não correspondem!" msgid "Could not fix VHD timestamp." msgstr "Não foi possível corrigir o carimbo de data/hora do VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Rápido" msgid "&Auto-pause on focus loss" msgstr "Pausa &automática na perda de focagem" + +msgid "WinBox is no longer supported" +msgstr "O WinBox não é mais suportado" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "O desenvolvimento do gerenciador WinBox parou em 2022 devido à falta de mantenedores. Como direcionamos nossos esforços para tornar o 86Box ainda melhor, tomamos a decisão de não mais suportar o WinBox como um gerenciador.\n\nNão serão fornecidas mais actualizações através do WinBox, e poderá encontrar um comportamento incorreto se continuar a usá-lo com versões mais recentes do 86Box. Quaisquer relatórios de erros relacionados com o comportamento do WinBox serão fechados como inválidos.\n\nVá a 86box.net para uma lista de outros gestores que pode utilizar." diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b0bcc0e1e..a4103c3e8 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: ru_RU\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Действие" @@ -31,6 +39,9 @@ msgstr "&Скрыть строку состояния" msgid "Hide &toolbar" msgstr "С&крыть панель инструментов" +msgid "Show non-primary monitors" +msgstr "&Показывать неосновные мониторы" + msgid "&Resizeable window" msgstr "&Изменяемый размер окна" @@ -40,14 +51,11 @@ msgstr "&Запомнить размер и положение" msgid "Re&nderer" msgstr "&Рендеринг" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0)" @@ -55,8 +63,32 @@ msgstr "Open&GL (3.0)" msgid "&VNC" msgstr "&VNC" +msgid "Renderer options..." +msgstr "Параметры рендеринга..." + +msgid "OpenGL 3.0 renderer options" +msgstr "Параметры рендеринга OpenGL 3.0" + +msgid "Render behavior" +msgstr "Режим рендеринга" + +msgid "Synchronize with video" +msgstr "Синхронизировать с видео" + +msgid "Use target framerate:" +msgstr "Использовать целевую частоту кадров:" + +msgid "VSync" +msgstr "Вертикальная синхронизация" + +msgid "Shaders" +msgstr "Шейдеры" + +msgid "No shader selected" +msgstr "Шейдер не выбран" + msgid "Specify dimensions..." -msgstr "&Указать размеры..." +msgstr "&Указать размеры главного окна..." msgid "F&orce 4:3 display ratio" msgstr "У&становить соотношение сторон 4:3" @@ -127,6 +159,9 @@ msgstr "&Целочисленное масштабирование" msgid "4:&3 Integer scale" msgstr "4:&3 Целочисленное масштабирование" +msgid "Apply fullscreen stretch mode when maximized" +msgstr "Применить полноэкранный режим растяжения при разворачивании окна" + msgid "E&GA/(S)VGA settings" msgstr "Настройки E&GA/(S)VGA" @@ -193,6 +228,9 @@ msgstr "Включить интеграцию &Discord" msgid "Sound &gain..." msgstr "&Усиление звука..." +msgid "Open screenshots folder..." +msgstr "Открыть папку скриншотов..." + msgid "Begin trace\tCtrl+T" msgstr "Начать трассировку\tCtrl+T" @@ -232,6 +270,9 @@ msgstr "&Перемотка в конец" msgid "E&ject" msgstr "И&звлечь" +msgid "Eject %s" +msgstr "Извлечь %s" + msgid "&Image..." msgstr "&Образ..." @@ -241,6 +282,9 @@ msgstr "Э&кспорт в 86F..." msgid "&Mute" msgstr "О&тключить звук" +msgid "&Unmute" +msgstr "В&ключить звук" + msgid "E&mpty" msgstr "П&устой" @@ -352,6 +396,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Скорость:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -368,25 +415,28 @@ 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 "Динамический рекомпилятор" msgid "Video:" -msgstr "Видеокарта:" +msgstr "Видеокарта 1:" + +msgid "Video #2:" +msgstr "Видеокарта 2:" msgid "Voodoo Graphics" msgstr "Ускоритель Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Ускоритель IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Ускоритель IBM 8514/A" msgid "XGA Graphics" msgstr "Ускоритель XGA" @@ -409,23 +459,23 @@ msgstr "Джойстик 3..." msgid "Joystick 4..." msgstr "Джойстик 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Звуковая карта 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Звуковая карта 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Звуковая карта 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Звуковая карта 4:" msgid "MIDI Out Device:" -msgstr "MIDI Out устр-во:" +msgstr "MIDI Out устройство:" msgid "MIDI In Device:" -msgstr "MIDI In устр-во:" +msgstr "MIDI In устройство:" msgid "Standalone MPU-401" msgstr "Отдельный MPU-401" @@ -440,7 +490,7 @@ msgid "Nuked (more accurate)" msgstr "Nuked (более точный)" msgid "YMFM (faster)" -msgstr "YMFM (быстрей)" +msgstr "YMFM (быстрее)" msgid "Network type:" msgstr "Тип сети:" @@ -451,6 +501,30 @@ msgstr "Устройство PCap:" msgid "Network adapter:" msgstr "Сетевая карта:" +msgid "Network Card #1" +msgstr "Сетевая карта 1:" + +msgid "Network Card #2" +msgstr "Сетевая карта 2:" + +msgid "Network Card #3" +msgstr "Сетевая карта 3:" + +msgid "Network Card #4" +msgstr "Сетевая карта 4:" + +msgid "Mode" +msgstr "Режим:" + +msgid "Interface" +msgstr "Интерфейс:" + +msgid "Adapter" +msgstr "Адаптер:" + +msgid "VDE Socket" +msgstr "VDE Socket:" + msgid "COM1 Device:" msgstr "Устройство COM1:" @@ -476,16 +550,28 @@ msgid "LPT4 Device:" msgstr "Устройство LPT4:" msgid "Serial port 1" -msgstr "Последов. порт COM1" +msgstr "Последовательный порт COM1" msgid "Serial port 2" -msgstr "Последов. порт COM2" +msgstr "Последовательный порт COM2" msgid "Serial port 3" -msgstr "Последов. порт COM3" +msgstr "Последовательный порт COM3" msgid "Serial port 4" -msgstr "Последов. порт COM4" +msgstr "Последовательный порт COM4" + +msgid "Serial port passthrough 1" +msgstr "Сквозной последовательный порт COM1" + +msgid "Serial port passthrough 2" +msgstr "Сквозной последовательный порт COM2" + +msgid "Serial port passthrough 3" +msgstr "Сквозной последовательный порт COM3" + +msgid "Serial port passthrough 4" +msgstr "Сквозной последовательный порт COM4" msgid "Parallel port 1" msgstr "Параллельный порт LPT1" @@ -538,8 +624,14 @@ msgstr "&Создать..." msgid "&Existing..." msgstr "&Выбрать..." +msgid "Browse..." +msgstr "Выбрать..." + msgid "&Remove" -msgstr "&Убрать" +msgstr "&Удалить" + +msgid "Remove" +msgstr "Удалить" msgid "Bus:" msgstr "Шина:" @@ -554,7 +646,7 @@ msgid "&Specify..." msgstr "&Указать..." msgid "Sectors:" -msgstr "Сектора:" +msgstr "Секторы:" msgid "Heads:" msgstr "Головки:" @@ -586,9 +678,6 @@ msgstr "Проверять BPB" msgid "CD-ROM drives:" msgstr "Дисководы CD-ROM:" -msgid "Earlier drive" -msgstr "Предыдущий дисковод" - msgid "MO drives:" msgstr "Магнитооптические дисководы:" @@ -602,7 +691,7 @@ msgid "ISA RTC:" msgstr "ISA RTC:" msgid "ISA Memory Expansion" -msgstr "Карта расширения памяти (ISA)" +msgstr "Карта расширения памяти ISA" msgid "Card 1:" msgstr "Карта 1:" @@ -622,11 +711,8 @@ msgstr "Устройство ISABugger" msgid "POST card" msgstr "Карта POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" +msgid "86Box Unit Tester" +msgstr "Модульный Тестер 86Box" msgid "86Box" msgstr "86Box" @@ -658,6 +744,9 @@ msgstr "86Box не смог найти ни одного подходящего msgid "(empty)" msgstr "(пусто)" +msgid "Clear image history" +msgstr "Очистить историю образов" + msgid "All files" msgstr "Все файлы" @@ -713,7 +802,7 @@ msgid "Floppy & CD-ROM drives" msgstr "Гибкие диски и CD-ROM" msgid "Other removable devices" -msgstr "Другие съёмные устр-ва" +msgstr "Другие съёмные устройства" msgid "Other peripherals" msgstr "Другая периферия" @@ -721,11 +810,11 @@ msgstr "Другая периферия" msgid "Click to capture mouse" msgstr "Щёлкните мышью для захвата курсора" -msgid "Press F8+F12 to release mouse" -msgstr "Нажмите F8+F12 чтобы освободить курсор" +msgid "Press %1 to release mouse" +msgstr "Нажмите %1, чтобы освободить курсор" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "Нажмите F8+F12 или среднюю кнопку мыши чтобы освободить курсор" +msgid "Press %1 or middle button to release mouse" +msgstr "Нажмите %1 или среднюю кнопку мыши, чтобы освободить курсор" msgid "Bus" msgstr "Шина" @@ -757,9 +846,6 @@ msgstr "%i WS" msgid "Type" msgstr "Тип" -msgid "Failed to set up PCap" -msgstr "Не удалось настроить PCap" - msgid "No PCap devices found" msgstr "Устройства PCap не найдены" @@ -785,20 +871,11 @@ msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" -msgstr "Система управления полетом Thrustmaster" +msgstr "Система управления полётом Thrustmaster" msgid "None" msgstr "Нет" -msgid "Unable to load keyboard accelerators." -msgstr "Невозможно загрузить ускорители клавиатуры." - -msgid "Unable to register raw input." -msgstr "Невозможно зарегистрировать необработанный (RAW) ввод." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u МБ (CHS: %i, %i, %i)" @@ -811,9 +888,6 @@ 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 "Вы уверены, что хотите выполнить холодную перезагрузку эмулируемой машины?" @@ -845,7 +919,7 @@ msgid "Do you want to save the settings?" msgstr "Хотите ли вы сохранить настройки?" msgid "This will hard reset the emulated machine." -msgstr "Это приведет к холодной перезагрузке эмулируемой машины." +msgstr "Это приведёт к холодной перезагрузке эмулируемой машины." msgid "Save" msgstr "Сохранить" @@ -854,7 +928,7 @@ msgid "About 86Box" msgstr "О 86Box" msgid "86Box v" -msgstr "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, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВыпускается под лицензией GNU General Public License версии 2 или более поздней. Дополнительную информацию см. в файле LICENSE." @@ -862,26 +936,14 @@ msgstr "Эмулятор старых компьютеров\n\nАвторы: Mi 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 "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Убедитесь, что %1 установлен и ваше сетевое соединение совместимо с %1." 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 "%1 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 требуется %1.\n\nВсе документы, отправленные на общий принтер PostScript, будут сохранены в виде файлов PostScript (.ps)." msgid "Entering fullscreen mode" msgstr "Вход в полноэкранный режим" @@ -901,8 +963,8 @@ msgstr "Не перезагружать" msgid "CD-ROM images" msgstr "Образы CD-ROM" -msgid "%hs Device Configuration" -msgstr "Конфигурация устройства %hs" +msgid "%1 Device Configuration" +msgstr "Конфигурация устройства %1" msgid "Monitor in sleep mode" msgstr "Монитор в спящем режиме" @@ -958,14 +1020,8 @@ msgstr "Холодная перезагрузка" msgid "ACPI shutdown" msgstr "Сигнал завершения ACPI" -msgid "Hard disk (%s)" -msgstr "Жёсткий диск (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Жёсткий диск (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL или ESDI дисководов CD-ROM никогда не существовало" @@ -1000,9 +1056,6 @@ msgstr "Невозможно записать файл" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Образы HDI или HDX с размером сектора, отличным от 512, не поддерживаются." -msgid "USB is not yet supported" -msgstr "USB пока не поддерживается" - msgid "Disk image file already exists" msgstr "Файл образа диска уже существует" @@ -1075,9 +1128,6 @@ msgstr "Временные метки родительского и дочерн msgid "Could not fix VHD timestamp." msgstr "Не удалось исправить временную метку VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1143,6 @@ 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" @@ -1224,3 +1256,9 @@ msgstr "Быстрый" msgid "&Auto-pause on focus loss" msgstr "&Автопауза при потере фокуса" + +msgid "WinBox is no longer supported" +msgstr "WinBox больше не поддерживается" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Разработка менеджера WinBox прекратилась в 2022 году из-за отсутствия сопровождающих. Поскольку мы направляем наши усилия на то, чтобы сделать 86Box еще лучше, мы приняли решение больше не поддерживать WinBox в качестве менеджера.\n\nWinBox больше не будет обновляться, и вы можете столкнуться с некорректным поведением, если продолжите использовать его с новыми версиями 86Box. Любые сообщения об ошибках, связанных с поведением WinBox, будут закрыты как недействительные.\n\nПерейдите на сайт 86box.net для получения списка других менеджеров, которые вы можете использовать." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index a8f60b861..8aeb0f082 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: sk_SK\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Podujatia" @@ -40,14 +48,11 @@ msgstr "&Pamätať si veľkosť a polohu" msgid "Re&nderer" msgstr "&Renderer" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rýchlosť:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +393,8 @@ msgstr "Grafika:" msgid "Voodoo Graphics" msgstr "Použiť grafický akcelerátor Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +417,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvuková karta 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvuková karta 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvuková karta 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvuková karta 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Kontrola BPB" msgid "CD-ROM drives:" msgstr "Mechaniky CD-ROM:" -msgid "Earlier drive" -msgstr "Skorá mechanika" - msgid "MO drives:" msgstr "Magnetooptické mechaniky:" @@ -622,12 +627,6 @@ 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" @@ -721,11 +720,11 @@ 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 %1 to release mouse" +msgstr "Stlačte %1 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 "Press %1 or middle button to release mouse" +msgstr "Stlačte %1 alebo prostredné tlačidlo na uvoľnenie myši" msgid "Bus" msgstr "Zbernica" @@ -757,9 +756,6 @@ 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" @@ -790,15 +786,6 @@ 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)" @@ -811,9 +798,6 @@ 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č?" @@ -862,26 +846,14 @@ msgstr "Emulátor starých počítačov\n\nAutori: Miran Grča (OBattler), Richa 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 "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "Uistite sa, že je nainštalovaný %1 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 "%1 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 "%1 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" @@ -901,8 +873,8 @@ msgstr "Neresetovať" msgid "CD-ROM images" msgstr "Obraz CD-ROM disku" -msgid "%hs Device Configuration" -msgstr "Konfigurácia zariadenia %hs" +msgid "%1 Device Configuration" +msgstr "Konfigurácia zariadenia %1" msgid "Monitor in sleep mode" msgstr "Monitor je v režime spánku" @@ -958,14 +930,8 @@ 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 "Hard disk (%1)" +msgstr "Pevný disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "CD-ROM mechaniky pre rozhranie MFM/RLL alebo ESDI nikdy neexistovali" @@ -1000,9 +966,6 @@ 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" @@ -1075,9 +1038,6 @@ 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" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Rýchly" msgid "&Auto-pause on focus loss" msgstr "&Automatická pauza pri strate fokusu okna" + +msgid "WinBox is no longer supported" +msgstr "WinBox už nie je podporovaný" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Vývoj správcu WinBox sa zastavil v roku 2022 z dôvodu nedostatku správcov. Keďže naše úsilie smerujeme k ešte lepšiemu systému 86Box, rozhodli sme sa, že správca WinBox už nebude podporovaný.\n\nProstredníctvom WinBoxu nebudú poskytované žiadne ďalšie aktualizácie a v prípade, že ho budete naďalej používať s novšími verziami programu 86Box, môžete sa stretnúť s nesprávnym správaním. Všetky hlásenia o chybách týkajúce sa správania WinBoxu budú uzavreté ako neplatné.\n\nNa stránke 86box.net nájdete zoznam iných správcov, ktoré môžete používať." diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 98a51d863..2a4b68e46 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: sl_SI\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Dejanja" @@ -40,14 +48,11 @@ msgstr "&Zapomni si velikost in položaj" msgid "Re&nderer" msgstr "&Upodabljanje" -msgid "&SDL (Software)" -msgstr "&SDL (programsko)" +msgid "&Qt (Software)" +msgstr "&Qt (programsko)" -msgid "SDL (&Hardware)" -msgstr "SDL (s&trojno)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (Jedro 3.0)" @@ -352,6 +357,9 @@ msgstr "Vrsta procesorja:" msgid "Speed:" msgstr "Hitrost:" +msgid "Frequency:" +msgstr "Pogostost:" + msgid "FPU:" msgstr "Procesor plavajoče vejice:" @@ -385,8 +393,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a grafika" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A grafika" msgid "XGA Graphics" msgstr "XGA grafika" @@ -409,16 +417,16 @@ msgstr "Igralna palica 3..." msgid "Joystick 4..." msgstr "Igralna palica 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvočna kartica 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvočna kartica 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvočna kartica 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvočna kartica 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "Naprava ISABugger" msgid "POST card" msgstr "Kartica POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Druga periferija" msgid "Click to capture mouse" msgstr "Kliknite za zajem miške" -msgid "Press F8+F12 to release mouse" -msgstr "Pritisnite F8+F12 za izpust miške" +msgid "Press %1 to release mouse" +msgstr "Pritisnite %1 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 "Press %1 or middle button to release mouse" +msgstr "Pritisnite %1 ali srednji gumb za izpust miške" msgid "Bus" msgstr "Vodilo" @@ -757,9 +756,6 @@ msgstr "%i stanj čakanja" msgid "Type" msgstr "Vrsta" -msgid "Failed to set up PCap" -msgstr "Nastavitev PCap ni uspela" - msgid "No PCap devices found" msgstr "Nobena naprava PCap ni bila najdena" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Control System" msgid "None" msgstr "Brez" -msgid "Unable to load keyboard accelerators." -msgstr "Ne morem naložiti pospeševalnikov tipkovnice." - -msgid "Unable to register raw input." -msgstr "Ne morem registrirati neobdelanega vnosa." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Tokovne slike" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Ste prepričani, da želite ponovno zagnati emulirani sistem?" @@ -862,26 +846,14 @@ msgstr "Emulator starih računalnikov\n\nAvtorji: Miran Grča (OBattler), Richar msgid "Hardware not available" msgstr "Strojna oprema ni na voljo" -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 "Prepičajte se, da je nameščen libpcap in da ste na omrežni povezavi, združljivi z " +msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "Prepičajte se, da je nameščen %1 in da ste na omrežni povezavi, združljivi z libpcap." msgid "Invalid configuration" msgstr "Neveljavna konfiguracija" -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 potreben za samodejno pretvorbo PostScript datotek v PDF.\n\nVsi dokumenti, poslani generičnemu PostScript tiskalniku bodo shranjeni kot PostScript (.ps) datoteke." +msgid "%1 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 "%1 je potreben za samodejno pretvorbo PostScript datotek v PDF.\n\nVsi dokumenti, poslani generičnemu PostScript tiskalniku bodo shranjeni kot PostScript (.ps) datoteke." msgid "Entering fullscreen mode" msgstr "Preklapljam v celozaslonski način" @@ -901,8 +873,8 @@ msgstr "Ne resetiraj" msgid "CD-ROM images" msgstr "Slike CD-ROM" -msgid "%hs Device Configuration" -msgstr "Konfiguracija naprave %hs" +msgid "%1 Device Configuration" +msgstr "Konfiguracija naprave %1" msgid "Monitor in sleep mode" msgstr "Zaslon v načinu spanja" @@ -958,14 +930,8 @@ msgstr "Ponovni zagon" msgid "ACPI shutdown" msgstr "Zaustavitev ACPI" -msgid "Hard disk (%s)" -msgstr "Trdi disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Trdi disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL ali ESDI pogoni CD-ROM niso nikoli obstajali" @@ -1000,9 +966,6 @@ msgstr "Ne morem pisati v datoteko" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Slike HDI ali HDX, ki nimajo sektorjev velikosti 512 bajtov, niso podprte." -msgid "USB is not yet supported" -msgstr "USB še ni podprt" - msgid "Disk image file already exists" msgstr "Datoteka s sliko diska že obstaja" @@ -1075,9 +1038,6 @@ msgstr "Časovna žiga starševske slike diska in slike diska otroka se ne ujema msgid "Could not fix VHD timestamp." msgstr "Ne morem popraviti časovnega žiga slike VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Hitri" msgid "&Auto-pause on focus loss" msgstr "&Samodejni premor ob izgubi fokusa" + +msgid "WinBox is no longer supported" +msgstr "WinBox ni več podprt" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Razvoj upravitelja WinBox se je leta 2022 ustavil zaradi pomanjkanja vzdrževalcev. Ker svoja prizadevanja usmerjamo v še boljše delovanje programa 86Box, smo se odločili, da programa WinBox kot upravitelja ne bomo več podpirali.\n\nWinBox ne bo več zagotavljal posodobitev, če ga boste še naprej uporabljali z novejšimi različicami programa 86Box, pa lahko naletite na nepravilno obnašanje. Vsa poročila o napakah, povezana z obnašanjem programa WinBox, bodo zaprta kot neveljavna.\n\nZa seznam drugih upraviteljev, ki jih lahko uporabite, obiščite spletno stran 86box.net." diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 0d6875eb8..ada5ff87f 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: tr_TR\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Komutlar" @@ -40,14 +48,11 @@ msgstr "&Pencere boyut ve pozisyonunu hatırla" msgid "Re&nderer" msgstr "&İşleyici" -msgid "&SDL (Software)" -msgstr "&SDL (Yazılım)" +msgid "&Qt (Software)" +msgstr "&Qt (Yazılım)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Donanım)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0 Core)" @@ -352,6 +357,9 @@ msgstr "CPU türü:" msgid "Speed:" msgstr "Hız:" +msgid "Frequency:" +msgstr "Sıklık:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Ekran kartı:" msgid "Voodoo Graphics" msgstr "Voodoo Grafikleri" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Grafikleri" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Grafikleri" msgid "XGA Graphics" msgstr "XGA Grafikleri" @@ -409,16 +417,16 @@ msgstr "Oyun kolu 3..." msgid "Joystick 4..." msgstr "Oyun kolu 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Ses kartı 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Ses kartı 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Ses kartı 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Ses kartı 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ 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:" @@ -622,12 +627,6 @@ msgstr "ISABugger cihazı" msgid "POST card" msgstr "POST kartı" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Diğer cihazlar" msgid "Click to capture mouse" msgstr "Farenin yakalanması için tıklayın" -msgid "Press F8+F12 to release mouse" -msgstr "Farenin bırakılması için F8+F12 tuşlarına basın" +msgid "Press %1 to release mouse" +msgstr "Farenin bırakılması için %1 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 "Press %1 or middle button to release mouse" +msgstr "Farenin bırakılması için %1 veya farenin orta tuşuna basın" msgid "Bus" msgstr "Veri yolu" @@ -757,9 +756,6 @@ msgstr "%i Bekleme durumları" msgid "Type" msgstr "Tür" -msgid "Failed to set up PCap" -msgstr "PCap ayarlanamadı" - msgid "No PCap devices found" msgstr "Herhangi bir PCap cihazı bulunamadı" @@ -790,15 +786,6 @@ msgstr "Thrustmaster Flight Kontrol Sistemi" msgid "None" msgstr "Hiçbiri" -msgid "Unable to load keyboard accelerators." -msgstr "Klavye ivdirgeçleri yüklenemedi." - -msgid "Unable to register raw input." -msgstr "Ham girdi kaydedilemedi." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u MB (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ msgstr "Gelişmiş sektör imajları" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL başlatılamadı, SDL2.dll gerekmektedir" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Emüle edilen makineyi yeniden başlatmak istediğinizden emin misiniz?" @@ -862,26 +846,14 @@ msgstr "Bir eski bilgisayar emülatörü\n\nYapanlar: Miran Grča (OBattler), Ri msgid "Hardware not available" msgstr "Donanım mevcut değil" -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 kurulu olduğundan ve libpcap-uyumlu bir internet ağında bulunduğunuzdan emin olun." +msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "%1 kurulu olduğundan ve libpcap-uyumlu bir internet ağında bulunduğunuzdan emin olun." msgid "Invalid configuration" msgstr "Geçersiz konfigürasyon" -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 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 "%1 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 "%1 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 "Entering fullscreen mode" msgstr "Tam ekran moduna geçiliyor" @@ -901,8 +873,8 @@ msgstr "Yeniden başlatma" msgid "CD-ROM images" msgstr "CD-ROM imajları" -msgid "%hs Device Configuration" -msgstr "%hs Cihaz Konfigürasyonu" +msgid "%1 Device Configuration" +msgstr "%1 Cihaz Konfigürasyonu" msgid "Monitor in sleep mode" msgstr "Monitör uyku modunda" @@ -958,14 +930,8 @@ msgstr "Makineyi yeniden başlat" msgid "ACPI shutdown" msgstr "ACPI kapatma" -msgid "Hard disk (%s)" -msgstr "Hard disk (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Hard disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL veya ESDI CD-ROM sürücüleri hiçbir zaman var olmamıştır" @@ -1000,9 +966,6 @@ msgstr "Dosyanın üzerine yazılamıyor" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "512 dışında sektör boyutu olan HDI veya HDX imajları desteklenmemektedir." -msgid "USB is not yet supported" -msgstr "USB şu anda desteklenmemektedir" - msgid "Disk image file already exists" msgstr "Disk imaj dosyası zaten var olmakta" @@ -1075,9 +1038,6 @@ msgstr "Ana ve ek disk zaman damgaları uyuşmuyor" msgid "Could not fix VHD timestamp." msgstr "VHD zaman damgası düzeltilemedi." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Hızlı" msgid "&Auto-pause on focus loss" msgstr "&Odak kaybında otomatik duraklatma" + +msgid "WinBox is no longer supported" +msgstr "WinBox artık desteklenmiyor" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "WinBox yöneticisinin geliştirilmesi, bakımcı eksikliği nedeniyle 2022 yılında durduruldu. Çabalarımızı 86Box'ı daha da iyi hale getirmeye yönlendirdiğimiz için, WinBox'ı artık bir yönetici olarak desteklememe kararı aldık.\n\nWinBox aracılığıyla daha fazla güncelleme sağlanmayacak ve 86Box'ın daha yeni sürümleriyle kullanmaya devam ederseniz hatalı davranışlarla karşılaşabilirsiniz. WinBox davranışıyla ilgili tüm hata raporları geçersiz olarak kapatılacaktır.\n\nKullanabileceğiniz diğer yöneticilerin bir listesi için 86box.net adresine gidin." diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 6f8ecac52..8dca70a85 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: uk_UA\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "&Дія" @@ -40,14 +48,11 @@ msgstr "&Запам'ятати розмір і становище" msgid "Re&nderer" msgstr "&Рендеринг" -msgid "&SDL (Software)" -msgstr "&SDL (Software)" +msgid "&Qt (Software)" +msgstr "&Qt (Software)" -msgid "SDL (&Hardware)" -msgstr "SDL (&Hardware)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (&OpenGL)" +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" msgid "Open&GL (3.0 Core)" msgstr "Open&GL (3.0)" @@ -352,6 +357,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Швидкість:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +393,8 @@ msgstr "Відеокарта:" msgid "Voodoo Graphics" msgstr "Прискорювач Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Прискорювач IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Прискорювач IBM 8514/A" msgid "XGA Graphics" msgstr "Прискорювач XGA" @@ -409,16 +417,16 @@ msgstr "Джойстик 3..." msgid "Joystick 4..." msgstr "Джойстик 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Звукова карта 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Звукова карта 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Звукова карта 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Звукова карта 4:" msgid "MIDI Out Device:" @@ -586,9 +594,6 @@ msgstr "Перевіряти BPB" msgid "CD-ROM drives:" msgstr "Дисководи CD-ROM:" -msgid "Earlier drive" -msgstr "Більш ранній дисковод" - msgid "MO drives:" msgstr "Магнітооптичні дисководи:" @@ -622,12 +627,6 @@ msgstr "Пристрій ISABugger" msgid "POST card" msgstr "Карта POST" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Segoe UI" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "Інша периферія" msgid "Click to capture mouse" msgstr "Клацніть мишею для захвату курсора" -msgid "Press F8+F12 to release mouse" -msgstr "Натисніть F8+F12, щоб звільнити курсор" +msgid "Press %1 to release mouse" +msgstr "Натисніть %1, щоб звільнити курсор" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "Натисніть F8+F12 або середню кнопку миші, щоб звільнити курсор" +msgid "Press %1 or middle button to release mouse" +msgstr "Натисніть %1 або середню кнопку миші, щоб звільнити курсор" msgid "Bus" msgstr "Шина" @@ -757,9 +756,6 @@ msgstr "%i WS" msgid "Type" msgstr "Тип" -msgid "Failed to set up PCap" -msgstr "Не вдалося налаштувати PCap" - msgid "No PCap devices found" msgstr "Пристрої PCap не знайдені" @@ -790,15 +786,6 @@ msgstr "Система управління польотом Thrustmaster" msgid "None" msgstr "Ні" -msgid "Unable to load keyboard accelerators." -msgstr "Неможливо завантажити прискорювачі клавіатури." - -msgid "Unable to register raw input." -msgstr "Неможливо зарреєструвати необроблене (RAW) введення." - -msgid "%u" -msgstr "%u" - msgid "%u MB (CHS: %i, %i, %i)" msgstr "%u МБ (CHS: %i, %i, %i)" @@ -811,9 +798,6 @@ 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 "Ви впевнені, що хочете виконати холодне перезавантаження емульованої машини?" @@ -854,7 +838,7 @@ msgid "About 86Box" msgstr "Про 86Box" msgid "86Box v" -msgstr "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, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВипускаєтся під ліцензією GNU General Public License версії 2 або більше пізніше. Додадкову інформацію см. у файлі LICENSE." @@ -862,26 +846,14 @@ msgstr "Емулятор старих комп'ютерів\n\nАвтори: Mir 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 "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "Переконайтесь, що %1 встановлений і ваше мережеве з'єднання, сумісне з 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 "%1 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 "%1 потрібно для автоматичного перетворення файлів PostScript в PDF.\n\nВсі документи, відправлені на загальний принтер PostScript, будуть збережені у вигляді файлів PostScript (.ps)." msgid "Entering fullscreen mode" msgstr "Вхід у повноекранний режим" @@ -901,8 +873,8 @@ msgstr "Не перезавантажувати" msgid "CD-ROM images" msgstr "Образи CD-ROM" -msgid "%hs Device Configuration" -msgstr "Конфігурація пристрою %hs" +msgid "%1 Device Configuration" +msgstr "Конфігурація пристрою %1" msgid "Monitor in sleep mode" msgstr "Монітор у сплячому режимі" @@ -958,14 +930,8 @@ msgstr "Холодне перезавантаження" msgid "ACPI shutdown" msgstr "Сигнал завершення ACPI" -msgid "Hard disk (%s)" -msgstr "Жорсткий диск (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "Жорсткий диск (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "MFM/RLL або ESDI дисководів CD-ROM ніколи не існувало" @@ -1000,9 +966,6 @@ msgstr "Неможливо записати файл" msgid "HDI or HDX images with a sector size other than 512 are not supported." msgstr "Образи HDI або HDX з розміром сектора, відмінним від 512, не підтримуються." -msgid "USB is not yet supported" -msgstr "USB поки не підтримується" - msgid "Disk image file already exists" msgstr "Файл образу диска вже існує" @@ -1075,9 +1038,6 @@ msgstr "Тимчасові мітки батьківського та дочір msgid "Could not fix VHD timestamp." msgstr "Не вдалося виправити тимчасову позначку VHD." -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "Швидкий" msgid "&Auto-pause on focus loss" msgstr "&Автопауза при втраті фокусу" + +msgid "WinBox is no longer supported" +msgstr "WinBox більше не підтримується" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Розробку менеджера WinBox було припинено у 2022 році через брак супровідників. Оскільки ми спрямовуємо наші зусилля на те, щоб зробити 86Box ще кращим, ми прийняли рішення більше не підтримувати WinBox як менеджер.\n\nБільше ніяких оновлень не буде надаватися через WinBox, і ви можете зіткнутися з некоректною поведінкою, якщо продовжите використовувати його з новими версіями 86Box. Будь-які повідомлення про помилки, пов'язані з поведінкою WinBox, будуть закриті як недійсні.\n\nПерейдіть на 86box.net для отримання списку інших менеджерів, які ви можете використовувати." diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po new file mode 100644 index 000000000..ee6d77849 --- /dev/null +++ b/src/qt/languages/vi-VN.po @@ -0,0 +1,1174 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: vi_VN\n" +"X-Source-Language: en_US\n" + +msgid "&Action" +msgstr "&Thực hiện" + +msgid "&Keyboard requires capture" +msgstr "Bàn phím &hoạt động cần capture chuột" + +msgid "&Right CTRL is left ALT" +msgstr "Gắn CTRL p&hải vào ALT trái" + +msgid "&Hard Reset..." +msgstr "Buộc khởi độn&g lại" + +msgid "&Ctrl+Alt+Del\tCtrl+F12" +msgstr "&Ctrl+Alt+Del\tCtrl+F12" + +msgid "Ctrl+Alt+&Esc" +msgstr "Ctrl+Alt+&Esc" + +msgid "&Pause" +msgstr "Tạm &dừng" + +msgid "E&xit..." +msgstr "Th&oát..." + +msgid "&View" +msgstr "&Xem" + +msgid "&Hide status bar" +msgstr "Ẩn tha&nh trạng thái" + +msgid "Hide &toolbar" +msgstr "Ẩn thanh &công cụ" + +msgid "&Resizeable window" +msgstr "Tùy chỉnh cỡ cử&a sổ" + +msgid "R&emember size && position" +msgstr "Ghi nhớ vị trí và kíc&h thước cửa sổ" + +msgid "Re&nderer" +msgstr "Re&nderer" + +msgid "&Qt (Software)" +msgstr "&Qt (phần mềm)" + +msgid "Qt (&OpenGL)" +msgstr "Qt (&OpenGL)" + +msgid "Open&GL (3.0 Core)" +msgstr "Open&GL (3.0 Core)" + +msgid "&VNC" +msgstr "&VNC" + +msgid "Specify dimensions..." +msgstr "Tự nhập độ &phân giải..." + +msgid "F&orce 4:3 display ratio" +msgstr "Giữ n&guyên khung hình 4:3" + +msgid "&Window scale factor" +msgstr "Đổi &tỷ lệ cửa sổ" + +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 "&Bộ lọc hình ảnh" + +msgid "&Nearest" +msgstr "&Cực cận" + +msgid "&Linear" +msgstr "Tu&yến tính" + +msgid "Hi&DPI scaling" +msgstr "Tỷ lệ hinh ảnh phân giải cao" + +msgid "&Fullscreen\tCtrl+Alt+PgUp" +msgstr "Toàn màn &hình\tCtrl+Alt+PgUp" + +msgid "Fullscreen &stretch mode" +msgstr "&Chế độ kéo giãn hình" + +msgid "&Full screen stretch" +msgstr "Kéo giãn hình" + +msgid "&4:3" +msgstr "&4:3" + +msgid "&Square pixels (Keep ratio)" +msgstr "Điểm ảnh vuông (giữ tỷ lệ)" + +msgid "&Integer scale" +msgstr "Căn tỷ lệ số nguyên" + +msgid "4:&3 Integer scale" +msgstr "Căn tỷ lệ 4:3 số nguyên" + +msgid "E&GA/(S)VGA settings" +msgstr "Cài đặt EGA/(S)VGA" + +msgid "&Inverted VGA monitor" +msgstr "Đảo mà&u VGA" + +msgid "VGA screen &type" +msgstr "L&oại màn VGA" + +msgid "RGB &Color" +msgstr "Màu R&GB" + +msgid "&RGB Grayscale" +msgstr "Thang xám RG&B" + +msgid "&Amber monitor" +msgstr "Màn hình vàng hổ phách (amber)" + +msgid "&Green monitor" +msgstr "Màn hình lục" + +msgid "&White monitor" +msgstr "Màn hinh trắng" + +msgid "Grayscale &conversion type" +msgstr "Chuyển đổi thang &màu xám" + +msgid "BT&601 (NTSC/PAL)" +msgstr "BT&601 (NTSC/PAL)" + +msgid "BT&709 (HDTV)" +msgstr "BT&709 (HDTV)" + +msgid "&Average" +msgstr "&Trung bình" + +msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" +msgstr "&Overscan CGA/PCjr/Tandy/EGA/(S)VGA" + +msgid "Change contrast for &monochrome display" +msgstr "Chỉnh tương phản cho màn hình đơn sắc" + +msgid "&Media" +msgstr "&Phương tiện" + +msgid "&Tools" +msgstr "&Công cụ" + +msgid "&Settings..." +msgstr "&Cài đặt..." + +msgid "&Update status bar icons" +msgstr "Cậ&p nhật biểu tượng thanh trạng thái" + +msgid "Take s&creenshot\tCtrl+F11" +msgstr "Chụp &màn hình\tCtrl+F11" + +msgid "&Preferences..." +msgstr "&Tùy biến..." + +msgid "Enable &Discord integration" +msgstr "Bật trình trạng thái cho Discord" + +msgid "Sound &gain..." +msgstr "Bộ &tăng âm..." + +msgid "Begin trace\tCtrl+T" +msgstr "Bắt đầu dò\tCtrl+T" + +msgid "End trace\tCtrl+T" +msgstr "Ngưng dò\tCtrl+T" + +msgid "&Help" +msgstr "&Trợ giúp" + +msgid "&Documentation..." +msgstr "&Trợ giúp..." + +msgid "&About 86Box..." +msgstr "&Về 86Box..." + +msgid "&New image..." +msgstr "Tạo file ảnh đĩa mới..." + +msgid "&Existing image..." +msgstr "Ảnh đĩa có sẵn..." + +msgid "Existing image (&Write-protected)..." +msgstr "Ảnh đĩa có sẵn (chống ghi đè)..." + +msgid "&Record" +msgstr "&Ghi lại" + +msgid "&Play" +msgstr "&Phát" + +msgid "&Rewind to the beginning" +msgstr "&Tua về đầu" + +msgid "&Fast forward to the end" +msgstr "T&iến về cuối" + +msgid "E&ject" +msgstr "Đẩy đĩ&a ra" + +msgid "&Image..." +msgstr "&Ảnh đĩa..." + +msgid "E&xport to 86F..." +msgstr "Xuất ra f&ile 86F..." + +msgid "&Mute" +msgstr "Tắt tiến&g" + +msgid "E&mpty" +msgstr "Làm trố&ng đĩa" + +msgid "&Reload previous image" +msgstr "Load đĩ&a trước đó" + +msgid "&Folder..." +msgstr "Thư mụ&c" + +msgid "Target &framerate" +msgstr "Số khung hình mục tiêu" + +msgid "&Sync with video" +msgstr "Đồng bộ &với video" + +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 "&Chọn shader..." + +msgid "&Remove shader" +msgstr "&Bỏ shader" + +msgid "Preferences" +msgstr "Tùy biến" + +msgid "Sound Gain" +msgstr "Tăng âm" + +msgid "New Image" +msgstr "Ảnh đĩa mới" + +msgid "Settings" +msgstr "Cài đặt" + +msgid "Specify Main Window Dimensions" +msgstr "Tùy biến kích thước cửa sổ chính" + +msgid "OK" +msgstr "Đồng ý" + +msgid "Cancel" +msgstr "Thôi" + +msgid "Save these settings as &global defaults" +msgstr "Lưu cài đặt làm mặc định chung" + +msgid "&Default" +msgstr "&Mặc định" + +msgid "Language:" +msgstr "Ngôn ngữ:" + +msgid "Icon set:" +msgstr "Bộ biểu tượng:" + +msgid "Gain" +msgstr "Tăng" + +msgid "File name:" +msgstr "Tên tập tin:" + +msgid "Disk size:" +msgstr "Kích thước đĩa:" + +msgid "RPM mode:" +msgstr "Tốc độ vòng quay:" + +msgid "Progress:" +msgstr "Tiến trình:" + +msgid "Width:" +msgstr "Chiều rộng:" + +msgid "Height:" +msgstr "Chiều cao:" + +msgid "Lock to this size" +msgstr "Cố định kích thước hình hiện tại" + +msgid "Machine type:" +msgstr "Loại máy:" + +msgid "Machine:" +msgstr "Mẫu máy:" + +msgid "Configure" +msgstr "Tinh chỉnh" + +msgid "CPU type:" +msgstr "Loại CPU:" + +msgid "Speed:" +msgstr "Tốc độ:" + +msgid "Frequency:" +msgstr "Tần số xung:" + +msgid "FPU:" +msgstr "FPU:" + +msgid "Wait states:" +msgstr "Trạng thái chờ:" + +msgid "MB" +msgstr "MB" + +msgid "Memory:" +msgstr "Bộ nhớ (RAM):" + +msgid "Time synchronization" +msgstr "Đồng bộ thời gian" + +msgid "Disabled" +msgstr "Vô hiệu hóa" + +msgid "Enabled (local time)" +msgstr "Bật (giờ địa phương)" + +msgid "Enabled (UTC)" +msgstr "Bật (UTC)" + +msgid "Dynamic Recompiler" +msgstr "Bộ tái biên dịch động (Dynamic Recompiler)" + +msgid "Video:" +msgstr "Video:" + +msgid "Voodoo Graphics" +msgstr "Đồ họa Voodoo" + +msgid "IBM 8514/A Graphics" +msgstr "Đồ họa IBM 8514/A" + +msgid "XGA Graphics" +msgstr "Đồ họa XGA" + +msgid "Mouse:" +msgstr "Chuột:" + +msgid "Joystick:" +msgstr "Cần điều khiển:" + +msgid "Joystick 1..." +msgstr "Cần điều khiển 1..." + +msgid "Joystick 2..." +msgstr "Cần điều khiển 2..." + +msgid "Joystick 3..." +msgstr "Cần điều khiển 3..." + +msgid "Joystick 4..." +msgstr "Cần điều khiển 4..." + +msgid "Sound card #1:" +msgstr "Card âm thanh 1:" + +msgid "Sound card #2:" +msgstr "Card âm thanh 2:" + +msgid "Sound card #3:" +msgstr "Card âm thanh 3:" + +msgid "Sound card #4:" +msgstr "Card âm thanh 4:" + +msgid "MIDI Out Device:" +msgstr "Thiết bị MIDI out:" + +msgid "MIDI In Device:" +msgstr "Thiết bị MIDI in:" + +msgid "Standalone MPU-401" +msgstr "MPU-401 độc lập" + +msgid "Use FLOAT32 sound" +msgstr "Dùng âm FLOAT32" + +msgid "FM synth driver" +msgstr "Driver bộ tổng hợp âm FM" + +msgid "Nuked (more accurate)" +msgstr "Nuked (chính xác hơn)" + +msgid "YMFM (faster)" +msgstr "YMFM (nhanh hơn)" + +msgid "Network type:" +msgstr "Kiểu loại mạng:" + +msgid "PCap device:" +msgstr "Thiết bị PCap:" + +msgid "Network adapter:" +msgstr "Bộ thích ứng (adapter) mạng:" + +msgid "COM1 Device:" +msgstr "Thiết bị COM1:" + +msgid "COM2 Device:" +msgstr "Thiết bị COM2:" + +msgid "COM3 Device:" +msgstr "Thiết bị COM3:" + +msgid "COM4 Device:" +msgstr "Thiết bị COM4:" + +msgid "LPT1 Device:" +msgstr "Thiết bị LPT1:" + +msgid "LPT2 Device:" +msgstr "Thiết bị LPT2:" + +msgid "LPT3 Device:" +msgstr "Thiết bị LPT3:" + +msgid "LPT4 Device:" +msgstr "Thiết bị LPT4:" + +msgid "Serial port 1" +msgstr "Cổng serial 1" + +msgid "Serial port 2" +msgstr "Cổng serial 2" + +msgid "Serial port 3" +msgstr "Cổng serial 3" + +msgid "Serial port 4" +msgstr "Cổng serial 4" + +msgid "Parallel port 1" +msgstr "Cổng parallel 1" + +msgid "Parallel port 2" +msgstr "Cổng parallel 2" + +msgid "Parallel port 3" +msgstr "Cổng parallel 3" + +msgid "Parallel port 4" +msgstr "Cổng parallel 4" + +msgid "HD Controller:" +msgstr "Bộ điều khiển ổ cứng:" + +msgid "FD Controller:" +msgstr "Bộ điều khiển ổ mềm:" + +msgid "Tertiary IDE Controller" +msgstr "Bộ điều khiển IDE thứ ba" + +msgid "Quaternary IDE Controller" +msgstr "Bộ điều khiển IDE thứ tư" + +msgid "SCSI" +msgstr "SCSI" + +msgid "Controller 1:" +msgstr "Bộ điều khiển 1:" + +msgid "Controller 2:" +msgstr "Bộ điều khiển 2:" + +msgid "Controller 3:" +msgstr "Bộ điều khiển 3:" + +msgid "Controller 4:" +msgstr "Bộ điều khiển 4:" + +msgid "Cassette" +msgstr "Cassette" + +msgid "Hard disks:" +msgstr "Đĩa cứng:" + +msgid "&New..." +msgstr "Tạ&o mới..." + +msgid "&Existing..." +msgstr "&Có sẵn..." + +msgid "&Remove" +msgstr "Loạ&i bỏ" + +msgid "Bus:" +msgstr "Bus:" + +msgid "Channel:" +msgstr "Kênh:" + +msgid "ID:" +msgstr "ID:" + +msgid "&Specify..." +msgstr "Chỉ &rõ..." + +msgid "Sectors:" +msgstr "Sector:" + +msgid "Heads:" +msgstr "Đầu ghi:" + +msgid "Cylinders:" +msgstr "Trụ:" + +msgid "Size (MB):" +msgstr "Kích thước (MB):" + +msgid "Type:" +msgstr "Loại:" + +msgid "Image Format:" +msgstr "Định dạng ảnh đĩa:" + +msgid "Block Size:" +msgstr "Kích thước bloc:" + +msgid "Floppy drives:" +msgstr "Ổ đĩa mềm:" + +msgid "Turbo timings" +msgstr "Thời gian turbo" + +msgid "Check BPB" +msgstr "Kiểm tra BPB" + +msgid "CD-ROM drives:" +msgstr "Ổ đĩa CD-ROM:" + +msgid "MO drives:" +msgstr "Ổ đĩa MO:" + +msgid "ZIP drives:" +msgstr "Ổ đĩa ZIP:" + +msgid "ZIP 250" +msgstr "ZIP 250" + +msgid "ISA RTC:" +msgstr "ISA RTC:" + +msgid "ISA Memory Expansion" +msgstr "Mở rộng bộ nhớ qua ISA" + +msgid "Card 1:" +msgstr "Thẻ 1:" + +msgid "Card 2:" +msgstr "Thẻ 2:" + +msgid "Card 3:" +msgstr "Thẻ 3:" + +msgid "Card 4:" +msgstr "Thẻ 4:" + +msgid "ISABugger device" +msgstr "Thiết bị ISABugger" + +msgid "POST card" +msgstr "Thẻ POST" + +msgid "86Box" +msgstr "86Box" + +msgid "Error" +msgstr "Lỗi" + +msgid "Fatal error" +msgstr "Lỗi nghiêm trọng" + +msgid " - PAUSED" +msgstr " - TẠM DỪNG" + +msgid "Press Ctrl+Alt+PgDn to return to windowed mode." +msgstr "Bấm Ctrl+Alt+PgDn để quay lại chế độ cửa sổ." + +msgid "Speed" +msgstr "Vận tốc" + +msgid "ZIP %03i %i (%s): %ls" +msgstr "ZIP %03i %i (%s): %ls" + +msgid "ZIP images" +msgstr "Ảnh đĩa 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 không tìm được bản ROM nào.\n\nVui lòng tải về bộ ROM và trích xuất về thư mục \"roms\"." + +msgid "(empty)" +msgstr "(trống trơn)" + +msgid "All files" +msgstr "Tất cả file" + +msgid "Turbo" +msgstr "Turbo" + +msgid "On" +msgstr "Bật" + +msgid "Off" +msgstr "Tắt" + +msgid "All images" +msgstr "Tất cả ảnh" + +msgid "Basic sector images" +msgstr "Ảnh sector cơ bản" + +msgid "Surface images" +msgstr "Ảnh bề mặt" + +msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." +msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/machines. Hãy chọn mẫu máy khác." + +msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card." +msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác." + +msgid "Machine" +msgstr "Mẫu máy" + +msgid "Display" +msgstr "Hiển thị" + +msgid "Input devices" +msgstr "Thiết bị nhập" + +msgid "Sound" +msgstr "Thanh âm" + +msgid "Network" +msgstr "Nối mạng" + +msgid "Ports (COM & LPT)" +msgstr "Cổng (COM và LPT)" + +msgid "Storage controllers" +msgstr "Vi điều khiển bộ nhớ ổ cứng" + +msgid "Hard disks" +msgstr "Ổ cứng" + +msgid "Floppy & CD-ROM drives" +msgstr "Ổ (đĩa) mềm và CD-ROM" + +msgid "Other removable devices" +msgstr "Thiết bị tháo rời được khác" + +msgid "Other peripherals" +msgstr "Thiết bị ngoại vi khác" + +msgid "Click to capture mouse" +msgstr "Bấm để capture ('nhốt') chuột vào" + +msgid "Press %1 to release mouse" +msgstr "Nhấn %1 để thả chuột" + +msgid "Press %1 or middle button to release mouse" +msgstr "Nhấn %1 hoặc nhấp chuột giữa để thả chuột" + +msgid "Bus" +msgstr "Bus" + +msgid "File" +msgstr "File" + +msgid "C" +msgstr "C" + +msgid "H" +msgstr "H" + +msgid "S" +msgstr "S" + +msgid "KB" +msgstr "KB" + +msgid "Could not initialize the video renderer." +msgstr "Không thể khởi tạo trình kết xuất (renderer) video ." + +msgid "Default" +msgstr "Mặc định" + +msgid "%i Wait state(s)" +msgstr "%i trạng thái chờ" + +msgid "Type" +msgstr "Loại" + +msgid "No PCap devices found" +msgstr "Không tìm thấy thiết bị PCap" + +msgid "Invalid PCap device" +msgstr "Thiết bị PCap không hợp quy" + +msgid "Standard 2-button joystick(s)" +msgstr "Cần điều khiển hai nút tiêu chuẩn" + +msgid "Standard 4-button joystick" +msgstr "Cần điều khiển bốn nút tiêu chuẩn" + +msgid "Standard 6-button joystick" +msgstr "Cần điều khiển sáu nút tiêu chuẩn" + +msgid "Standard 8-button joystick" +msgstr "Cần điều khiển tám nút tiêu chuẩn" + +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 "Không có" + +msgid "%u MB (CHS: %i, %i, %i)" +msgstr "%u MB (CHS: %i, %i, %i)" + +msgid "Floppy %i (%s): %ls" +msgstr "Đĩa mềm %i (%s): %ls" + +msgid "Advanced sector images" +msgstr "Ảnh (đĩa) sector nâng cao" + +msgid "Flux images" +msgstr "Ảnh thông lượng (flux)" + +msgid "Are you sure you want to hard reset the emulated machine?" +msgstr "Bạn có thật sự buộc máy khởi động lại không?" + +msgid "Are you sure you want to exit 86Box?" +msgstr "Bạn có muốn thoát 86Box?" + +msgid "Unable to initialize Ghostscript" +msgstr "Không thể khởi tạo Ghostscript" + +msgid "MO %i (%ls): %ls" +msgstr "MO %i (%ls): %ls" + +msgid "MO images" +msgstr "Ảnh đĩa MO" + +msgid "Welcome to 86Box!" +msgstr "Chào mừng đến 86Box!" + +msgid "Internal controller" +msgstr "Vi điều khiển nội bộ" + +msgid "Exit" +msgstr "Thoát" + +msgid "No ROMs found" +msgstr "Không tìm thấy ROM" + +msgid "Do you want to save the settings?" +msgstr "Bạn có muốn lưu cài đặt không?" + +msgid "This will hard reset the emulated machine." +msgstr "Lệnh này sẽ buộc khởi động lại máy ảo." + +msgid "Save" +msgstr "Lưu" + +msgid "About 86Box" +msgstr "Về 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 "Trình giả lập các dòng máy tính cổ.\n\nTác giả: 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, cùng những người khác.\n\nCùng với những đóng góp cốt cán từ Sarah Walker, leilei, JohnElliott, greatpsycho, và một số người khác.\n\nPhát hành dưới giấy phép GNU General Public License version 2 trở đi. Đọc LICENSE để biết thêm thông tin." + +msgid "Hardware not available" +msgstr "Phần cứng không có sẵn" + +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "Đảm bảo rằng %1 đã được cài đặt vào và bạn đang dùng kết nối mạng tương thích %1." + +msgid "Invalid configuration" +msgstr "Tinh chỉnh không hợp lý" + +msgid "%1 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 "Cần có %1 để tự động chuyển đổi file PostScript qua PDF.\n\nMọi tài liệu được đưa qua máy in generic PostScript sẽ lưu ở dạng PostScript (.ps)." + +msgid "Entering fullscreen mode" +msgstr "Đang tiến vào chế độ toàn màn hình" + +msgid "Don't show this message again" +msgstr "Không hiện thông báo này nữa" + +msgid "Don't exit" +msgstr "Không thoát" + +msgid "Reset" +msgstr "Khởi động lại" + +msgid "Don't reset" +msgstr "Không khởi động lại" + +msgid "CD-ROM images" +msgstr "Ảnh đĩa CD-ROM" + +msgid "%1 Device Configuration" +msgstr "Tinh chỉnh thiết bị %1" + +msgid "Monitor in sleep mode" +msgstr "Màn hình chế độ chờ/ngủ" + +msgid "OpenGL Shaders" +msgstr "Shader OpenGL" + +msgid "OpenGL options" +msgstr "Tùy chọn OpenGL" + +msgid "You are loading an unsupported configuration" +msgstr "Bạn đang load tinh chỉnh không được hỗ trợ." + +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 "Phần chọn loại CPU dựa trên mẫu máy đã chọn bị vô hiệu hóa.\n\nỞ đây bạn có thể chọn loại CPU có thể không tương thích với mẫu máy hiện tại. Tuy nhiên bạn có thể gặp vấn đề tương khắc với BIOS hay phần mềm khác.\n\nViệc bật tùy chọn này lên không được khuyến cáo chính thức và các bản bug report (báo lỗi) với nội dung tương tự sẽ bị coi là phạm quy và đóng." + +msgid "Continue" +msgstr "Tiếp tục" + +msgid "Cassette: %s" +msgstr "Cassette: %s" + +msgid "Cassette images" +msgstr "Ảnh đĩa Cassette" + +msgid "Cartridge %i: %ls" +msgstr "Băng cartridge %i: %ls" + +msgid "Cartridge images" +msgstr "Ảnh đĩa băng cartridge" + +msgid "Error initializing renderer" +msgstr "Lỗi khởi tạo renderer (trình kết xuất)" + +msgid "OpenGL (3.0 Core) renderer could not be initialized. Use another renderer." +msgstr "Không khởi tạo được renderer OpenGL (3.0 Core). Hãy dùng renderer khác." + +msgid "Resume execution" +msgstr "Tiếp tục chạy thực thi" + +msgid "Pause execution" +msgstr "Tạm dừng thực thi" + +msgid "Press Ctrl+Alt+Del" +msgstr "Nhấn Ctrl+Alt+Del" + +msgid "Press Ctrl+Alt+Esc" +msgstr "Nhấn Ctrl+Alt+Esc" + +msgid "Hard reset" +msgstr "Buộc khởi động lại" + +msgid "ACPI shutdown" +msgstr "Tắt máy theo ACPI" + +msgid "Hard disk (%1)" +msgstr "Ổ cứng (%1)" + +msgid "MFM/RLL or ESDI CD-ROM drives never existed" +msgstr "Không hề có ổ CD-ROM MFM/RLL hay ESDI nào tồn tại" + +msgid "Custom..." +msgstr "Tùy chỉnh..." + +msgid "Custom (large)..." +msgstr "Tùy chỉnh (dung tích lớn)..." + +msgid "Add New Hard Disk" +msgstr "Thêm ổ cứng mới" + +msgid "Add Existing Hard Disk" +msgstr "Thêm ổ cứng đã có" + +msgid "HDI disk images cannot be larger than 4 GB." +msgstr "Ảnh đĩa ổ HDI không to hơn 4 GB." + +msgid "Disk images cannot be larger than 127 GB." +msgstr "Ảnh đĩa không to hơn 127 GB." + +msgid "Hard disk images" +msgstr "Ảnh đĩa ổ cứng" + +msgid "Unable to read file" +msgstr "Không đọc được file" + +msgid "Unable to write file" +msgstr "Không ghi được vào file" + +msgid "HDI or HDX images with a sector size other than 512 are not supported." +msgstr "Ảnh đĩa HDI hoặc HDX với kích thước sector khác 512 không được hỗ trợ." + +msgid "Disk image file already exists" +msgstr "Đã có file ảnh đĩa rồi" + +msgid "Please specify a valid file name." +msgstr "Vui lòng đặt tên hợp lệ." + +msgid "Disk image created" +msgstr "Đã tạo ảnh đĩa" + +msgid "Make sure the file exists and is readable." +msgstr "Chắc chắn rằng file tồn tại và đọc được." + +msgid "Make sure the file is being saved to a writable directory." +msgstr "Chắc chắn rằng file được lưu ở địa chỉ thư mục có thể ghi đè." + +msgid "Disk image too large" +msgstr "Ảnh đĩa quá to" + +msgid "Remember to partition and format the newly-created drive." +msgstr "Nhớ phân vùng và định dạng ổ đĩa mới tạo." + +msgid "The selected file will be overwritten. Are you sure you want to use it?" +msgstr "File được chọn sẽ bị ghi đè lên. Bạn có chắc muốn chọn dùng không?" + +msgid "Unsupported disk image" +msgstr "File ảnh đĩa không được hỗ trợ" + +msgid "Overwrite" +msgstr "Có ghi đè" + +msgid "Don't overwrite" +msgstr "Không ghi đè" + +msgid "Raw image (.img)" +msgstr "Ảnh đĩa thô (.img)" + +msgid "HDI image (.hdi)" +msgstr "Ảnh đĩa HDI (.hdi)" + +msgid "HDX image (.hdx)" +msgstr "Ảnh đĩa HDX (.hdx)" + +msgid "Fixed-size VHD (.vhd)" +msgstr "Ảnh VHD kích thước cố định (.vhd)" + +msgid "Dynamic-size VHD (.vhd)" +msgstr "Ảnh VHD kích thước tăng dần (.vhd)" + +msgid "Differencing VHD (.vhd)" +msgstr "Ảnh VHD đa chủng (differencing) (.vhd)" + +msgid "Large blocks (2 MB)" +msgstr "Bloc lớn (2 MB)" + +msgid "Small blocks (512 KB)" +msgstr "Bloc bé (512 KB)" + +msgid "VHD files" +msgstr "File VHD" + +msgid "Select the parent VHD" +msgstr "Chọn file VHD cha (parent)" + +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 "Ở đây tức là ảnh đĩa cha (parent) có thể đã bị chỉnh sửa sau khi ảnh đĩa đa chủng (differencing image) được tạo ra.\n\nCũng có thể do ảnh đĩa bị chuyển đi hay bị copy, hoặc do bug/lỗi của phần mềm tạo ảnh đĩa gây ra.\n\nBạn có muốn sửa lại mốc thời gian (timestamp) không?" + +msgid "Parent and child disk timestamps do not match" +msgstr "Mốc timestamp của đĩa con (child) và đĩa cha (parent) không trùng khớp" + +msgid "Could not fix VHD timestamp." +msgstr "Không thể sửa mốc timestamp cho VHD." + +msgid "MFM/RLL" +msgstr "MFM/RLL" + +msgid "XTA" +msgstr "XTA" + +msgid "ESDI" +msgstr "ESDI" + +msgid "IDE" +msgstr "IDE" + +msgid "ATAPI" +msgstr "ATAPI" + +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 "Số RPM(vòng quay đĩa/phút) hoàn thiện" + +msgid "1% below perfect RPM" +msgstr "1% thấp hơn số RPM hoàn thiện" + +msgid "1.5% below perfect RPM" +msgstr "1.5% thấp hơn số RPM hoàn thiện" + +msgid "2% below perfect RPM" +msgstr "2% thấp hơn số RPM hoàn thiện" + +msgid "(System Default)" +msgstr "(Mặc định hệ thống)" + +msgid "Failed to initialize network driver" +msgstr "Không thể khởi tạo trình điều khiển (driver) mạng" + +msgid "The network configuration will be switched to the null driver" +msgstr "Cấu hình mạng sẽ chuyển sang null driver (không có mạng)" + +msgid "Mouse sensitivity:" +msgstr "Độ nhạy chuột:" + +msgid "Select media images from program working directory" +msgstr "Chọn ảnh đĩa phương tiện từ thư mục làm việc của chương trình" + +msgid "PIT mode:" +msgstr "Chế độ PIT:" + +msgid "Auto" +msgstr "Tự động" + +msgid "Slow" +msgstr "Chậm" + +msgid "Fast" +msgstr "Nhanh" + +msgid "&Auto-pause on focus loss" +msgstr "&Tự tạm dừng giả lập khi không tập trung ở cửa sổ" + +msgid "WinBox is no longer supported" +msgstr "WinBox không còn được hỗ trợ" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Trình quản lý phiên WinBox đã bị dừng phát triển năm 2022 do thiếu nhân sự duy trì. Vì những quyết định để cho 86Box trở nên tốt hơn, chúng tôi đã không còn hỗ trợ trình quản lý WinBox.\n\n Sẽ không có bản cập nhật mới cho WinBox nữa, và nếu bạn tiếp tục sử dụng với các bản 86Box mới hơn có thể gặp lỗi. Bất kì các bản bug report liên quan đến lỗi của WinBox sẽ bị coi là không hợp lệ và bị đóng.\n\nTruy cập 86Box.net để tìm qua các trình quản lý phiên/manager khác cho phù hợp." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 3d045b74e..c8bd8f7bd 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: zh_CN\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "操作(&A)" @@ -40,17 +48,14 @@ msgstr "记住窗口大小和位置(&E)" msgid "Re&nderer" msgstr "渲染器(&N)" -msgid "&SDL (Software)" -msgstr "SDL (软件)(&S)" +msgid "&Qt (Software)" +msgstr "Qt (软件)(&Q)" -msgid "SDL (&Hardware)" -msgstr "SDL (硬件)(&H)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (OpenGL)(&O)" +msgid "Qt (&OpenGL)" +msgstr "Qt (OpenGL)(&O)" msgid "Open&GL (3.0 Core)" -msgstr "OpenGL (3.0 核心)(&G)" +msgstr "OpenGL (3.0 Core)(&G)" msgid "&VNC" msgstr "VNC(&V)" @@ -352,6 +357,9 @@ msgstr "CPU 类型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "频率:" + msgid "FPU:" msgstr "浮点处理器 (FPU):" @@ -385,8 +393,8 @@ msgstr "显卡:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +417,16 @@ msgstr "操纵杆 3..." msgid "Joystick 4..." msgstr "操纵杆 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "声卡 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "声卡 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "声卡 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "声卡 4:" msgid "MIDI Out Device:" @@ -431,10 +439,10 @@ msgid "Standalone MPU-401" msgstr "独立 MPU-401" msgid "Use FLOAT32 sound" -msgstr "使用单精度浮点 (FLOAT32)" +msgstr "使用单精度浮点 (FLOAT32) 音频" msgid "FM synth driver" -msgstr "调频合成器驱动器" +msgstr "FM synth driver" msgid "Nuked (more accurate)" msgstr "Nuked (更准确)" @@ -586,9 +594,6 @@ msgstr "检查 BPB" msgid "CD-ROM drives:" msgstr "光盘驱动器:" -msgid "Earlier drive" -msgstr "早先的驱动器" - msgid "MO drives:" msgstr "磁光盘驱动器:" @@ -622,12 +627,6 @@ msgstr "ISABugger 设备" msgid "POST card" msgstr "自检 (POST) 卡" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Microsoft YaHei" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "其他外围设备" msgid "Click to capture mouse" msgstr "单击窗口捕捉鼠标" -msgid "Press F8+F12 to release mouse" -msgstr "按下 F8+F12 释放鼠标" +msgid "Press %1 to release mouse" +msgstr "按下 %1 释放鼠标" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "按下 F8+F12 或鼠标中键释放鼠标" +msgid "Press %1 or middle button to release mouse" +msgstr "按下 %1 或鼠标中键释放鼠标" msgid "Bus" msgstr "总线" @@ -757,9 +756,6 @@ msgstr "%i 等待状态 (WS)" msgid "Type" msgstr "类型" -msgid "Failed to set up PCap" -msgstr "设置 PCap 失败" - msgid "No PCap devices found" msgstr "未找到 PCap 设备" @@ -790,15 +786,6 @@ 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)" @@ -811,9 +798,6 @@ 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 "确定要硬重置模拟器吗?" @@ -862,26 +846,14 @@ msgstr "一个旧式计算机模拟器\n\n作者: Miran Grča (OBattler)、Richa 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 "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "请确认 %1 已安装且使用兼容 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 "%1 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 "%1 是将 PostScript 文件转换为 PDF 所需要的库。\n\n使用通用 PostScript 打印机打印的文档将被保存为 PostScript (.ps) 文件。" msgid "Entering fullscreen mode" msgstr "正在进入全屏模式" @@ -901,8 +873,8 @@ msgstr "不重置" msgid "CD-ROM images" msgstr "光盘映像" -msgid "%hs Device Configuration" -msgstr "%hs 设备配置" +msgid "%1 Device Configuration" +msgstr "%1 设备配置" msgid "Monitor in sleep mode" msgstr "显示器处在睡眠状态" @@ -938,7 +910,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 Core) 渲染器。请使用其他渲染器。" msgid "Resume execution" msgstr "恢复执行" @@ -958,14 +930,8 @@ msgstr "硬重置" msgid "ACPI shutdown" msgstr "ACPI 关机" -msgid "Hard disk (%s)" -msgstr "硬盘 (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "硬盘 (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "不存在 MFM/RLL 或 ESDI CD-ROM 驱动器" @@ -1000,9 +966,6 @@ 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 "磁盘映像文件已存在" @@ -1075,9 +1038,6 @@ msgstr "父盘与子盘的时间戳不匹配" msgid "Could not fix VHD timestamp." msgstr "无法修复 VHD 时间戳。" -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1225,3 +1167,8 @@ msgstr "快" msgid "&Auto-pause on focus loss" msgstr "失去焦点时自动暂停(&A)" +msgid "WinBox is no longer supported" +msgstr "WinBox 不再受支持" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "由于缺乏维护者,WinBox 管理器的开发工作于 2022 年停止。由于我们正努力将 86Box 做得更好,因此决定不再支持 WinBox 作为管理器。\n\nWinBox将不再提供更新,如果你继续在86Box的新版本中使用WinBox,可能会遇到不正确的行为。任何与 WinBox 行为相关的错误报告都将被视为无效而关闭。\n\n请访问 86box.net,查看你可以使用的其他管理器列表。" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 2d2ea473e..3de6bf4c4 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -1,3 +1,11 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Language: zh_TW\n" +"X-Source-Language: en_US\n" + msgid "&Action" msgstr "動作(&A)" @@ -40,17 +48,14 @@ msgstr "記住視窗大小和位置(&E)" msgid "Re&nderer" msgstr "渲染器(&N)" -msgid "&SDL (Software)" -msgstr "SDL (軟體)(&S)" +msgid "&Qt (Software)" +msgstr "Qt (軟體)(&Q)" -msgid "SDL (&Hardware)" -msgstr "SDL (硬體)(&H)" - -msgid "SDL (&OpenGL)" -msgstr "SDL (OpenGL)(&O)" +msgid "Qt (&OpenGL)" +msgstr "Qt (OpenGL)(&O)" msgid "Open&GL (3.0 Core)" -msgstr "OpenGL (3.0 核心)(&G)" +msgstr "OpenGL (3.0 Core)(&G)" msgid "&VNC" msgstr "VNC(&V)" @@ -352,6 +357,9 @@ msgstr "CPU 類型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻率:" + msgid "FPU:" msgstr "浮點處理器 (FPU):" @@ -368,7 +376,7 @@ msgid "Time synchronization" msgstr "時間同步" msgid "Disabled" -msgstr "禁用" +msgstr "停用" msgid "Enabled (local time)" msgstr "啟用 (本地時間)" @@ -385,8 +393,8 @@ msgstr "顯示卡:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +417,16 @@ msgstr "搖桿 3..." msgid "Joystick 4..." msgstr "搖桿 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "音效卡 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "音效卡 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "音效卡 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "音效卡 4:" msgid "MIDI Out Device:" @@ -431,10 +439,10 @@ msgid "Standalone MPU-401" msgstr "獨立 MPU-401" msgid "Use FLOAT32 sound" -msgstr "使用單精度浮點 (FLOAT32)" +msgstr "使用單精度浮點 (FLOAT32) 音訊" msgid "FM synth driver" -msgstr "調頻合成器驅動器" +msgstr "FM synth driver" msgid "Nuked (more accurate)" msgstr "Nuked (更準確)" @@ -586,9 +594,6 @@ msgstr "檢查 BPB" msgid "CD-ROM drives:" msgstr "光碟機:" -msgid "Earlier drive" -msgstr "早先的光碟機" - msgid "MO drives:" msgstr "磁光碟機:" @@ -622,12 +627,6 @@ msgstr "ISABugger 裝置" msgid "POST card" msgstr "自檢 (POST) 卡" -msgid "FONT_SIZE" -msgstr "9" - -msgid "FONT_NAME" -msgstr "Microsoft JhengHei" - msgid "86Box" msgstr "86Box" @@ -721,11 +720,11 @@ msgstr "其他周邊裝置" msgid "Click to capture mouse" msgstr "點擊視窗捕捉滑鼠" -msgid "Press F8+F12 to release mouse" -msgstr "按下 F8+F12 釋放滑鼠" +msgid "Press %1 to release mouse" +msgstr "按下 %1 釋放滑鼠" -msgid "Press F8+F12 or middle button to release mouse" -msgstr "按下 F8+F12 或滑鼠中鍵釋放滑鼠" +msgid "Press %1 or middle button to release mouse" +msgstr "按下 %1 或滑鼠中鍵釋放滑鼠" msgid "Bus" msgstr "匯流排" @@ -757,9 +756,6 @@ msgstr "%i 等待狀態 (WS)" msgid "Type" msgstr "類型" -msgid "Failed to set up PCap" -msgstr "設定 PCap 失敗" - msgid "No PCap devices found" msgstr "未找到 PCap 裝置" @@ -790,15 +786,6 @@ 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)" @@ -811,9 +798,6 @@ 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 "確定要硬重設模擬器嗎?" @@ -862,26 +846,14 @@ msgstr "一個舊式電腦模擬器\n\n作者: Miran Grča (OBattler)、RichardG 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 "Make sure %1 is installed and that you are on a libpcap-compatible network connection." +msgstr "請確認 %1 已安裝且使用相容 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 "%1 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 "%1 是將 PostScript 檔案轉換為 PDF 所需要的庫。\n\n使用通用 PostScript 印表機列印的文件將被儲存為 PostScript (.ps) 檔案。" msgid "Entering fullscreen mode" msgstr "正在進入全螢幕模式" @@ -901,8 +873,8 @@ msgstr "不重設" msgid "CD-ROM images" msgstr "光碟映像" -msgid "%hs Device Configuration" -msgstr "%hs 裝置設定" +msgid "%1 Device Configuration" +msgstr "%1 裝置設定" msgid "Monitor in sleep mode" msgstr "顯示器處在睡眠狀態" @@ -917,7 +889,7 @@ 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啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" +msgstr "此模擬電腦停用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" msgid "Continue" msgstr "繼續" @@ -938,7 +910,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 Core) 渲染器。請使用其他渲染器。" msgid "Resume execution" msgstr "恢復執行" @@ -958,14 +930,8 @@ msgstr "硬重設" msgid "ACPI shutdown" msgstr "ACPI 關機" -msgid "Hard disk (%s)" -msgstr "硬碟 (%s)" - -msgid "%01i:%01i" -msgstr "%01i:%01i" - -msgid "%01i" -msgstr "%01i" +msgid "Hard disk (%1)" +msgstr "硬碟 (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" msgstr "不存在 MFM/RLL 或 ESDI CD-ROM 光碟機" @@ -1000,9 +966,6 @@ 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 "磁碟映像檔案已存在" @@ -1075,9 +1038,6 @@ msgstr "父碟與子碟的時間戳不匹配" msgid "Could not fix VHD timestamp." msgstr "無法修復 VHD 時間戳。" -msgid "%01i:%02i" -msgstr "%01i:%02i" - msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1093,24 +1053,6 @@ 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" @@ -1224,3 +1166,9 @@ msgstr "快" msgid "&Auto-pause on focus loss" msgstr "失去焦點時自動暫停(&A)" + +msgid "WinBox is no longer supported" +msgstr "WinBox is no longer supported" + +msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." diff --git a/src/qt/qt.c b/src/qt/qt.c index c2a5396da..47f5b9410 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -52,10 +52,8 @@ plat_vidapi(char *api) 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 5; } return 0; @@ -83,9 +81,6 @@ plat_vidapi_name(int api) name = "qt_vulkan"; break; case 5: - name = "qt_d3d9"; - break; - case 6: name = "vnc"; break; default: diff --git a/src/qt/qt_cdrom.c b/src/qt/qt_cdrom.c deleted file mode 100644 index 1facae486..000000000 --- a/src/qt/qt_cdrom.c +++ /dev/null @@ -1,54 +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 the platform-side of CDROM/ZIP/MO drives. - * - * - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017-2018 Fred N. van Kempen. - */ - -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/cassette.h> -#include <86box/cartridge.h> -#include <86box/fdd.h> -#include <86box/hdd.h> -#include <86box/scsi_device.h> -#include <86box/cdrom.h> -#include <86box/mo.h> -#include <86box/zip.h> -#include <86box/scsi_disk.h> -#include <86box/plat.h> -#include <86box/ui.h> - -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); - } else { - ui_sb_update_icon_state(SB_CDROM | id, 0); - } - - // 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 deleted file mode 100644 index 868f58274..000000000 --- a/src/qt/qt_d3d9renderer.cpp +++ /dev/null @@ -1,200 +0,0 @@ -#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 deleted file mode 100644 index 37c27443b..000000000 --- a/src/qt/qt_d3d9renderer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#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 6c7db0f3d..b031e6544 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ extern "C" { #include <86box/device.h> #include <86box/midi_rtmidi.h> #include <86box/mem.h> +#include <86box/random.h> #include <86box/rom.h> } @@ -84,10 +86,15 @@ EnumerateSerialDevices() #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)))) { + snprintf(devstr.data(), 1024, R"(\\.\COM%d)", i); + const auto handle = CreateFileA(devstr.data(), + GENERIC_READ | GENERIC_WRITE, 0, + nullptr, OPEN_EXISTING, + 0, nullptr); + const auto dwError = GetLastError(); + if ((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)); } @@ -104,206 +111,267 @@ EnumerateSerialDevices() return serialDevices; } +void +DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) +{ + auto * device_context = static_cast(dc); + const auto * config = static_cast(c); + const QString blank = ""; + int p; + int q; + + while (config->type != -1) { + const int config_type = config->type & CONFIG_TYPE_MASK; + + /* Ignore options of the wrong class. */ + if (!!(config->type & CONFIG_DEP) != is_dep) + continue; + + /* If this is a BIOS-dependent option and it's BIOS, ignore it. */ + if (!!(config->type & CONFIG_DEP) && (config_type == CONFIG_BIOS)) + continue; + + const int config_major_type = (config_type >> CONFIG_SHIFT) << CONFIG_SHIFT; + + int value = 0; + auto selected = blank; + + switch (config_major_type) { + default: + break; + case CONFIG_TYPE_INT: + value = config_get_int(device_context->name, const_cast(config->name), + config->default_int); + break; + case CONFIG_TYPE_HEX16: + value = config_get_hex16(device_context->name, const_cast(config->name), + config->default_int); + break; + case CONFIG_TYPE_HEX20: + value = config_get_hex20(device_context->name, const_cast(config->name), + config->default_int); + break; + case CONFIG_TYPE_STRING: + selected = config_get_string(device_context->name, const_cast(config->name), + const_cast(config->default_string)); + break; + } + + switch (config->type) { + default: + break; + case CONFIG_BINARY: + { + auto *cbox = new QCheckBox(); + cbox->setObjectName(config->name); + cbox->setChecked(value > 0); + this->ui->formLayout->addRow(config->description, cbox); + break; + } +#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; + 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 (i == value) + currentIndex = i; + } + this->ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } + case CONFIG_MIDI_IN: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + 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 (i == value) + currentIndex = i; + } + this->ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } +#endif + case CONFIG_INT: + case CONFIG_SELECTION: + case CONFIG_HEX16: + case CONFIG_HEX20: + { + auto *cbox = new QComboBox(); + cbox->setObjectName(config->name); + cbox->setMaxVisibleItems(30); + auto *model = cbox->model(); + int currentIndex = -1; + + 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 (sel->value == value) + currentIndex = row; + } + this->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; + + 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) { + const int row = Models::AddEntry(model, bios->name, q); + if (!strcmp(selected.toUtf8().constData(), bios->internal_name)) + currentIndex = row; + } + q++; + } + this->ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } + case CONFIG_SPINNER: + { + 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); + this->ui->formLayout->addRow(config->description, spinBox); + break; + } + case CONFIG_FNAME: + { + auto *fileField = new FileField(); + fileField->setObjectName(config->name); + fileField->setFileName(selected); + fileField->setFilter(QString(config->file_filter).left(static_cast(strcspn(config->file_filter, + "|")))); + this->ui->formLayout->addRow(config->description, fileField); + break; + } + case CONFIG_STRING: + { + const auto lineEdit = new QLineEdit; + lineEdit->setObjectName(config->name); + lineEdit->setCursor(Qt::IBeamCursor); + lineEdit->setText(selected); + this->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(); + + Models::AddEntry(model, "None", -1); + for (int i = 0; i < serialDevices.size(); i++) { + const int row = Models::AddEntry(model, serialDevices[i], i); + if (selected == serialDevices[i]) + currentIndex = row; + } + + this->ui->formLayout->addRow(config->description, cbox); + cbox->setCurrentIndex(currentIndex); + break; + } + case CONFIG_MAC: + { + // QHBoxLayout for the line edit widget and the generate button + const auto hboxLayout = new QHBoxLayout(); + const auto generateButton = new QPushButton(tr("Generate")); + const auto lineEdit = new QLineEdit; + // Allow the line edit to expand and fill available space + lineEdit->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Preferred); + lineEdit->setInputMask("HH:HH:HH;0"); + lineEdit->setObjectName(config->name); + // Display the current or generated MAC in uppercase + // When stored it will be converted to lowercase + if (config_get_mac(device_context->name, config->name, + config->default_int) & 0xFF000000) { + lineEdit->setText(QString::asprintf("%02X:%02X:%02X", random_generate(), + random_generate(), random_generate())); + } else { + auto current_mac = QString(config_get_string(device_context->name, config->name, + const_cast(config->default_string))); + lineEdit->setText(current_mac.toUpper()); + } + // Action for the generate button + connect(generateButton, &QPushButton::clicked, [lineEdit] { + lineEdit->setText(QString::asprintf("%02X:%02X:%02X", random_generate(), + random_generate(), random_generate())); + }); + hboxLayout->addWidget(lineEdit); + hboxLayout->addWidget(generateButton); + this->ui->formLayout->addRow(config->description, hboxLayout); + break; + } + } + ++config; + } +} + 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); - auto device_label = new QLabel(device->name); + const auto device_label = new QLabel(device->name); + device_label->setAlignment(Qt::AlignCenter); dc.ui->formLayout->addRow(device_label); - auto line = new QFrame; + const 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; - } -#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); + const _device_config_ *config = device->config; - Models::AddEntry(model, midiName, i); - if (selected == i) { - currentIndex = i; - } - } - dc.ui->formLayout->addRow(config->description, cbox); - cbox->setCurrentIndex(currentIndex); - break; - } - 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: - case CONFIG_HEX16: - case CONFIG_HEX20: - { - 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 != 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; - } - } - ++config; - } + dc.ProcessConfig(&device_context, config, false); dc.setFixedSize(dc.minimumSizeHint()); - int res = dc.exec(); - if (res == QDialog::Accepted) { + if (dc.exec() == QDialog::Accepted) { config = device->config; while (config->type != -1) { switch (config->type) { + default: + break; case CONFIG_BINARY: { - auto *cbox = dc.findChild(config->name); + const auto *cbox = dc.findChild(config->name); config_set_int(device_context.name, const_cast(config->name), cbox->isChecked() ? 1 : 0); break; } @@ -362,6 +430,14 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se config_set_int(device_context.name, const_cast(config->name), spinBox->value()); break; } + case CONFIG_MAC: + { + const auto *lineEdit = dc.findChild(config->name); + // Store the mac address as lowercase + auto macText = lineEdit->displayText().toLower(); + config_set_string(device_context.name, config->name, macText.toUtf8().constData()); + break; + } } config++; } @@ -369,15 +445,15 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se } QString -DeviceConfig::DeviceName(const _device_ *device, const char *internalName, int bus) +DeviceConfig::DeviceName(const _device_ *device, const char *internalName, const int bus) { - if (QStringLiteral("none") == internalName) { + if (QStringLiteral("none") == internalName) return tr("None"); - } else if (QStringLiteral("internal") == internalName) { + else if (QStringLiteral("internal") == internalName) return tr("Internal controller"); - } else if (device == nullptr) { - return QString(); - } else { + else if (device == nullptr) + return ""; + else { char temp[512]; device_get_name(device, bus, temp); return tr(temp, nullptr, 512); diff --git a/src/qt/qt_deviceconfig.hpp b/src/qt/qt_deviceconfig.hpp index 1ed24d618..a16c152a6 100644 --- a/src/qt/qt_deviceconfig.hpp +++ b/src/qt/qt_deviceconfig.hpp @@ -20,13 +20,15 @@ class DeviceConfig : public QDialog { public: explicit DeviceConfig(QWidget *parent = nullptr); - ~DeviceConfig(); + ~DeviceConfig() override; - static void ConfigureDevice(const _device_ *device, int instance = 0, Settings *settings = nullptr); + 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; + void ProcessConfig(void *dc, const void *c, bool is_dep); }; #endif // QT_DEVICECONFIG_HPP diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index 5dab101b8..df10a6d38 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -516,8 +516,8 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) 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; + if (settings_msgbox_ex(MBX_QUESTION_YN, L"Disk image file already exists", L"The selected file will be overwritten. Are you sure you want to use it?", L"Overwrite", L"Don't overwrite", NULL) != 0) / * yes * / + return false; } } @@ -525,8 +525,8 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) if (fp == NULL) { hdd_add_file_open_error: 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; + settings_msgbox_header(MBX_ERROR, (existing & 1) ? L"Make sure the file exists and is readable." : L"Make sure the file is being saved to a writable directory.", (existing & 1) ? L"Unable to read file" : L"Unable to write file"); + return true; } #endif @@ -567,7 +567,7 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) } else if (image_is_vhd(fileNameUtf8.data(), 1)) { 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")); + QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable.")); return; } else if (vhd_error == MVHD_ERR_TIMESTAMP) { QMessageBox::StandardButton btn = QMessageBox::warning(this, tr("Parent and child disk timestamps do not match"), tr("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?"), QMessageBox::Yes | QMessageBox::No); @@ -618,7 +618,7 @@ HarddiskDialog::onExistingFileSelected(const QString &fileName, bool precheck) } if ((sectors > max_sectors) || (heads > max_heads) || (cylinders > max_cylinders)) { - QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable")); + QMessageBox::critical(this, tr("Unable to read file"), tr("Make sure the file exists and is readable.")); return; } @@ -746,7 +746,7 @@ HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) ui->lineEditHeads->setValidator(new QIntValidator(1, max_heads, this)); ui->lineEditSectors->setValidator(new QIntValidator(1, max_sectors, this)); - Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt()); + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt(), Harddrives::busTrackClass); Harddrives::populateSpeeds(ui->comboBoxSpeed->model(), ui->comboBoxBus->currentData().toInt()); switch (ui->comboBoxBus->currentData().toInt()) { diff --git a/src/qt/qt_harddrive_common.cpp b/src/qt/qt_harddrive_common.cpp index dda36917f..e0b0233f1 100644 --- a/src/qt/qt_harddrive_common.cpp +++ b/src/qt/qt_harddrive_common.cpp @@ -20,10 +20,12 @@ extern "C" { #include <86box/hdd.h> +#include <86box/scsi.h> #include <86box/cdrom.h> } #include +#include void Harddrives::populateBuses(QAbstractItemModel *model) @@ -96,7 +98,7 @@ Harddrives::populateSpeeds(QAbstractItemModel *model, int bus) } void -Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) +Harddrives::populateBusChannels(QAbstractItemModel *model, int bus, SettingsBusTracking *sbt) { model->removeRows(0, model->rowCount()); @@ -104,22 +106,45 @@ Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) int shifter = 1; int orer = 1; int subChannelWidth = 1; + QList busesToCheck; + QList channelsInUse; switch (bus) { case HDD_BUS_MFM: + busRows = 2; + busesToCheck.append(HDD_BUS_MFM); + break; case HDD_BUS_XTA: + busRows = 2; + busesToCheck.append(HDD_BUS_XTA); + break; case HDD_BUS_ESDI: busRows = 2; + busesToCheck.append(HDD_BUS_ESDI); break; case HDD_BUS_IDE: + busRows = 8; + busesToCheck.append(HDD_BUS_ATAPI); + busesToCheck.append(HDD_BUS_IDE); + break; case HDD_BUS_ATAPI: busRows = 8; + busesToCheck.append(HDD_BUS_IDE); + busesToCheck.append(HDD_BUS_ATAPI); break; case HDD_BUS_SCSI: shifter = 4; orer = 15; - busRows = 64; + busRows = /*64*/ SCSI_BUS_MAX * SCSI_ID_MAX; subChannelWidth = 2; + busesToCheck.append(HDD_BUS_SCSI); break; + default: + break; + } + if(sbt != nullptr && !busesToCheck.empty()) { + for (auto const &checkBus : busesToCheck) { + channelsInUse.append(sbt->busChannelsInUse(checkBus)); + } } model->insertRows(0, busRows); @@ -127,6 +152,11 @@ Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) auto idx = model->index(i, 0); model->setData(idx, QString("%1:%2").arg(i >> shifter).arg(i & orer, subChannelWidth, 10, QChar('0'))); model->setData(idx, ((i >> shifter) << shifter) | (i & orer), Qt::UserRole); + const auto *channelModel = qobject_cast(model); + auto *channelItem = channelModel->item(i); + if(channelItem) { + channelItem->setEnabled(!channelsInUse.contains(i)); + } } } diff --git a/src/qt/qt_harddrive_common.hpp b/src/qt/qt_harddrive_common.hpp index 2aca184b3..28189f328 100644 --- a/src/qt/qt_harddrive_common.hpp +++ b/src/qt/qt_harddrive_common.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "qt_settings_bus_tracking.hpp" class QString; class QAbstractItemModel; @@ -9,7 +10,7 @@ class SettingsBusTracking; namespace Harddrives { void populateBuses(QAbstractItemModel *model); void populateRemovableBuses(QAbstractItemModel *model); -void populateBusChannels(QAbstractItemModel *model, int bus); +void populateBusChannels(QAbstractItemModel *model, int bus, SettingsBusTracking *sbt = nullptr); 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 47f0de718..ee2ec07df 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -136,22 +136,6 @@ HardwareRenderer::initializeGL() m_context->swapBuffers(this); } -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) { - m_context->makeCurrent(nullptr); - makeCurrent(); - QPainter painter(this); - drawStatusBarIcons(&painter); - painter.end(); - doneCurrent(); - m_context->makeCurrent(this); - } -} - void HardwareRenderer::paintGL() { diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index 1918cda18..f7861d2bd 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -53,7 +53,7 @@ public: { 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()) diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index 8523a258d..e03d57e09 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -118,19 +118,12 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); } - for (int d = 0; d < plat_joystick_state[joystick].nr_sliders; d++) { - Models::AddEntry(model, plat_joystick_state[joystick].slider[d].name, 0); - } - int nr_axes = plat_joystick_state[joystick].nr_axes; - int nr_povs = plat_joystick_state[joystick].nr_povs; int mapping = joystick_state[joystick_nr].axis_mapping[c]; if (mapping & POV_X) cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2); else if (mapping & POV_Y) cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2 + 1); - else if (mapping & SLIDER) - cbox->setCurrentIndex(nr_axes + nr_povs * 2 + (mapping & 3)); else cbox->setCurrentIndex(mapping); @@ -186,7 +179,7 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) Models::AddEntry(model, plat_joystick_state[joystick].axis[d].name, 0); } - int mapping = joystick_state[joystick_nr].pov_mapping[c][0]; + int mapping = joystick_state[joystick_nr].pov_mapping[c / 2][c & 1]; int nr_povs = plat_joystick_state[joystick].nr_povs; if (mapping & POV_X) cbox->setCurrentIndex((mapping & 3) * 2); @@ -195,14 +188,6 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) 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); - else if (mapping & POV_Y) - cbox->setCurrentIndex((mapping & 3) * 2 + 1); - else - cbox->setCurrentIndex(mapping + nr_povs * 2); - ui->ct->addWidget(label, row, 0); ui->ct->addWidget(cbox, row, 1); diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index d7b115a64..53e875e33 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -272,13 +272,13 @@ MachineStatus::hasCassette() bool MachineStatus::hasIDE() { - return machine_has_flags(machine, MACHINE_IDE_QUAD) > 0; + return (machine_has_flags(machine, MACHINE_IDE_QUAD) > 0) || other_ide_present; } bool MachineStatus::hasSCSI() { - return machine_has_flags(machine, MACHINE_SCSI) > 0; + return (machine_has_flags(machine, MACHINE_SCSI) > 0) || other_scsi_present; } void @@ -297,9 +297,14 @@ 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.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !hasIDE() && + (hdc_name.left(3) != QStringLiteral("ide")) && + (hdc_name.left(5) != QStringLiteral("xtide")) && + (hdc_name.left(5) != QStringLiteral("mcide"))) 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; @@ -315,9 +320,14 @@ 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.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !hasIDE() && + (hdc_name.left(3) != QStringLiteral("ide")) && + (hdc_name.left(5) != QStringLiteral("xtide")) && + (hdc_name.left(5) != QStringLiteral("mcide"))) 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); @@ -331,9 +341,14 @@ 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.left(3) != QStringLiteral("ide") && hdc_name.left(5) != QStringLiteral("xtide")) + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !hasIDE() && + (hdc_name.left(3) != QStringLiteral("ide")) && + (hdc_name.left(5) != QStringLiteral("xtide")) && + (hdc_name.left(5) != QStringLiteral("mcide"))) 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); @@ -577,48 +592,53 @@ MachineStatus::refresh(QStatusBar *sbar) }); auto hdc_name = QString(hdc_get_internal_name(hdc_current)); - if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) { + 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")); + d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%1)").arg("MFM/RLL")); sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get()); } - if ((has_esdi || hdc_name.left(4) == QStringLiteral("esdi")) && c_esdi > 0) { + 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")); + d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%1)").arg("ESDI")); sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get()); } - if ((has_xta || hdc_name.left(3) == QStringLiteral("xta")) && c_xta > 0) { + 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")); + d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%1)").arg("XTA")); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } - if (hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) { + if (hasIDE() || (hdc_name.left(5) == QStringLiteral("xtide")) || + (hdc_name.left(5) == QStringLiteral("mcide")) || + (hdc_name.left(3) == QStringLiteral("ide"))) { if (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")); + d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%1)").arg("IDE")); sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); } if (c_atapi > 0) { d->hdds[HDD_BUS_ATAPI].label = std::make_unique(); d->hdds[HDD_BUS_ATAPI].setActive(false); d->hdds[HDD_BUS_ATAPI].refresh(); - d->hdds[HDD_BUS_ATAPI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "ATAPI")); + d->hdds[HDD_BUS_ATAPI].label->setToolTip(tr("Hard disk (%1)").arg("ATAPI")); sbar->addWidget(d->hdds[HDD_BUS_ATAPI].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")); + d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%1)").arg("SCSI")); sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get()); } diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 845ff705f..dc8e1970f 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef QT_STATIC /* Static builds need plugin imports */ @@ -58,6 +59,7 @@ extern "C" { # include <86box/discord.h> #endif #include <86box/gdbstub.h> +#include <86box/version.h> } #include @@ -70,6 +72,7 @@ extern "C" { #include "cocoa_mouse.hpp" #include "qt_styleoverride.hpp" #include "qt_unixmanagerfilter.hpp" +#include "qt_util.hpp" // Void Cast #define VC(x) const_cast(x) @@ -88,25 +91,23 @@ void qt_set_sequence_auto_mnemonic(bool b); void main_thread_fn() { - uint64_t old_time; - uint64_t new_time; - int drawits; int frames; QThread::currentThread()->setPriority(QThread::HighestPriority); + plat_set_thread_name(nullptr, "main_thread_fn"); framecountx = 0; // title_update = 1; - old_time = elapsed_timer.elapsed(); - drawits = frames = 0; + uint64_t old_time = elapsed_timer.elapsed(); + int 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(); + const uint64_t new_time = elapsed_timer.elapsed(); #ifdef USE_GDBSTUB if (gdbstub_next_asap && (drawits <= 0)) drawits = 10; else #endif - drawits += (new_time - old_time); + drawits += static_cast(new_time - old_time); old_time = new_time; if (drawits > 0 && !dopause) { /* Yes, so do one frame now. */ @@ -189,16 +190,76 @@ main(int argc, char *argv[]) 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"); - auto font_size = QObject::tr("FONT_SIZE"); - QApplication::setFont(QFont(font_name, font_size.toInt())); + QApplication::setFont(QFont(ProgSettings::getFontName(lang_id), 9)); SetCurrentProcessExplicitAppUserModelID(L"86Box.86Box"); #endif + +#ifndef Q_OS_MACOS +# ifdef RELEASE_BUILD + app.setWindowIcon(QIcon(":/settings/qt/icons/86Box-green.ico")); +# elif defined ALPHA_BUILD + app.setWindowIcon(QIcon(":/settings/qt/icons/86Box-red.ico")); +# elif defined BETA_BUILD + app.setWindowIcon(QIcon(":/settings/qt/icons/86Box-yellow.ico")); +# else + app.setWindowIcon(QIcon(":/settings/qt/icons/86Box-gray.ico")); +# endif + +# ifdef Q_OS_UNIX + app.setDesktopFileName("net.86box.86Box"); +# endif +#endif + if (!pc_init_modules()) { - ui_msgbox_header(MBX_FATAL, (void *) IDS_2121, (void *) IDS_2056); + QMessageBox fatalbox(QMessageBox::Icon::Critical, QObject::tr("No ROMs found"), + QObject::tr("86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory."), + QMessageBox::Ok); + fatalbox.setTextFormat(Qt::TextFormat::RichText); + fatalbox.exec(); return 6; } + // UUID / copy / move detection + if(!util::compareUuid()) { + QMessageBox movewarnbox; + movewarnbox.setIcon(QMessageBox::Icon::Warning); + movewarnbox.setText("This machine might have been moved or copied."); + movewarnbox.setInformativeText("In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure."); + const QPushButton *movedButton = movewarnbox.addButton(QObject::tr("I Moved It"), QMessageBox::AcceptRole); + const QPushButton *copiedButton = movewarnbox.addButton(QObject::tr("I Copied It"), QMessageBox::DestructiveRole); + QPushButton *cancelButton = movewarnbox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole); + movewarnbox.setDefaultButton(cancelButton); + movewarnbox.exec(); + if (movewarnbox.clickedButton() == copiedButton) { + util::storeCurrentUuid(); + util::generateNewMacAdresses(); + } else if (movewarnbox.clickedButton() == movedButton) { + util::storeCurrentUuid(); + } + } + +#ifdef Q_OS_WINDOWS +# if !defined(EMU_BUILD_NUM) || (EMU_BUILD_NUM != 5624) + HWND winbox = FindWindow("TWinBoxMain", NULL); + if (winbox && + FindWindowEx(winbox, NULL, "TToolBar", NULL) && + FindWindowEx(winbox, NULL, "TListBox", NULL) && + FindWindowEx(winbox, NULL, "TStatusBar", NULL) && + (winbox = FindWindowEx(winbox, NULL, "TPageControl", NULL)) && /* holds a TTabSheet even on VM pages */ + FindWindowEx(winbox, NULL, "TTabSheet", NULL)) +# endif + { + QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("WinBox is no longer supported"), + QObject::tr("Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use."), + 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; + } +#endif + if (settings_only) { Settings settings; if (settings.exec() == QDialog::Accepted) { @@ -293,8 +354,6 @@ main(int argc, char *argv[]) // pc_reset_hard_init(); - /* Set the PAUSE mode depending on the renderer. */ - // plat_pause(0); QTimer onesec; QObject::connect(&onesec, &QTimer::timeout, &app, [] { pc_onesec(); @@ -323,9 +382,17 @@ main(int argc, char *argv[]) QTimer::singleShot(0, &app, [] { pc_reset_hard_init(); main_thread = new std::thread(main_thread_fn); + + /* Set the PAUSE mode depending on the renderer. */ +#ifdef USE_VNC + if (vnc_enabled && vid_api != 5) + plat_pause(1); + else +#endif + plat_pause(0); }); - auto ret = app.exec(); + const auto ret = app.exec(); cpu_thread_run = 0; main_thread->join(); pc_close(nullptr); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index f3503caeb..c48dfd052 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -91,6 +91,7 @@ extern int qt_nvr_save(void); #endif #include +#include #include #include "qt_settings.hpp" @@ -157,8 +158,6 @@ keyb_filter(BMessage *message, BHandler **target, BMessageFilter *filter) 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); @@ -196,15 +195,6 @@ MainWindow::MainWindow(QWidget *parent) auto toolbar_label = new QLabel(); ui->toolBar->addWidget(toolbar_label); -#ifdef RELEASE_BUILD - this->setWindowIcon(QIcon(":/settings/win/icons/86Box-green.ico")); -#elif defined ALPHA_BUILD - this->setWindowIcon(QIcon(":/settings/win/icons/86Box-red.ico")); -#elif defined BETA_BUILD - this->setWindowIcon(QIcon(":/settings/win/icons/86Box-yellow.ico")); -#else - this->setWindowIcon(QIcon(":/settings/win/icons/86Box-gray.ico")); -#endif this->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, vid_resize != 1); this->setWindowFlag(Qt::WindowMaximizeButtonHint, vid_resize == 1); @@ -300,14 +290,15 @@ MainWindow::MainWindow(QWidget *parent) resizableonce = true; } if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) { - w = (w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)); + w = static_cast(w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)); - int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.)) + const int modifiedHeight = + static_cast(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 / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.))); + ui->stackedWidget->resize(w, static_cast(h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.))); setFixedSize(w, modifiedHeight); } }); @@ -317,9 +308,9 @@ MainWindow::MainWindow(QWidget *parent) #ifdef QT_RESIZE_DEBUG qDebug() << "Resize"; #endif - w = (w / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); + w = static_cast(w / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); - int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); + int modifiedHeight = static_cast(h / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.)); renderers[monitor_index]->setFixedSize(w, modifiedHeight); } @@ -351,7 +342,6 @@ MainWindow::MainWindow(QWidget *parent) 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); @@ -378,14 +368,9 @@ MainWindow::MainWindow(QWidget *parent) 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 #ifndef USE_VNC - if (vid_api == 6) + if (vid_api == 5) vid_api = 0; ui->actionVNC->setVisible(false); #endif @@ -411,22 +396,19 @@ MainWindow::MainWindow(QWidget *parent) ui->actionVulkan->setVisible(false); } - QActionGroup *actGroup = nullptr; - - actGroup = new QActionGroup(this); + auto 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) { + if (vnc_enabled && vid_api != 5) { startblit(); vnc_enabled = 0; vnc_close(); @@ -436,6 +418,8 @@ MainWindow::MainWindow(QWidget *parent) #endif RendererStack::Renderer newVidApi = RendererStack::Renderer::Software; switch (vid_api) { + default: + break; case 0: newVidApi = RendererStack::Renderer::Software; break; @@ -451,11 +435,8 @@ MainWindow::MainWindow(QWidget *parent) case 4: newVidApi = RendererStack::Renderer::Vulkan; break; - case 5: - newVidApi = RendererStack::Renderer::Direct3D9; - break; #ifdef USE_VNC - case 6: + case 5: { newVidApi = RendererStack::Renderer::Software; startblit(); @@ -478,7 +459,7 @@ MainWindow::MainWindow(QWidget *parent) }); /* Trigger initial renderer switch */ - for (auto action : actGroup->actions()) + for (const auto action : actGroup->actions()) if (action->property("vid_api").toInt() == vid_api) { action->setChecked(true); emit actGroup->triggered(action); @@ -486,6 +467,8 @@ MainWindow::MainWindow(QWidget *parent) } switch (scale) { + default: + break; case 0: ui->action0_5x->setChecked(true); break; @@ -529,6 +512,8 @@ MainWindow::MainWindow(QWidget *parent) actGroup->addAction(ui->action7x); actGroup->addAction(ui->action8x); switch (video_filter_method) { + default: + break; case 0: ui->actionNearest->setChecked(true); break; @@ -540,6 +525,8 @@ MainWindow::MainWindow(QWidget *parent) actGroup->addAction(ui->actionNearest); actGroup->addAction(ui->actionLinear); switch (video_fullscreen_scale) { + default: + break; case FULLSCR_SCALE_FULL: ui->actionFullScreen_stretch->setChecked(true); break; @@ -563,6 +550,8 @@ MainWindow::MainWindow(QWidget *parent) actGroup->addAction(ui->actionFullScreen_int); actGroup->addAction(ui->actionFullScreen_int43); switch (video_grayscale) { + default: + break; case 0: ui->actionRGB_Color->setChecked(true); break; @@ -586,6 +575,8 @@ MainWindow::MainWindow(QWidget *parent) actGroup->addAction(ui->actionWhite_monitor); actGroup->addAction(ui->actionRGB_Color); switch (video_graytype) { + default: + break; case 0: ui->actionBT601_NTSC_PAL->setChecked(true); break; @@ -621,7 +612,7 @@ MainWindow::MainWindow(QWidget *parent) video_setblit(qt_blit); if (start_in_fullscreen) { - connect(ui->stackedWidget, &RendererStack::blit, this, [this] () { + connect(ui->stackedWidget, &RendererStack::blitToRenderer, this, [this] () { if (start_in_fullscreen) { QTimer::singleShot(100, ui->actionFullscreen, &QAction::trigger); start_in_fullscreen = 0; @@ -743,7 +734,7 @@ MainWindow::closeEvent(QCloseEvent *event) 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")); + auto chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!confirm_exit); @@ -792,7 +783,7 @@ void MainWindow::initRendererMonitorSlot(int monitor_index) { auto &secondaryRenderer = this->renderers[monitor_index]; - secondaryRenderer.reset(new RendererStack(nullptr, monitor_index)); + secondaryRenderer = std::make_unique(nullptr, monitor_index); if (secondaryRenderer) { connect(secondaryRenderer.get(), &RendererStack::rendererChanged, this, [this, monitor_index] { this->renderers[monitor_index]->show(); @@ -800,9 +791,8 @@ MainWindow::initRendererMonitorSlot(int monitor_index) secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1)); - if (vid_resize == 2) { + if (vid_resize == 2) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); - } secondaryRenderer->setWindowIcon(this->windowIcon()); if (show_second_monitors) { secondaryRenderer->show(); @@ -812,11 +802,18 @@ MainWindow::initRendererMonitorSlot(int monitor_index) 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) { + if (monitor_settings[monitor_index].mon_window_maximized) secondaryRenderer->showMaximized(); - } secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api); secondaryRenderer->setMouseTracking(true); + + if (monitor_settings[monitor_index].mon_window_maximized) { + if (renderers[monitor_index]) + renderers[monitor_index]->onResize(renderers[monitor_index]->width(), + renderers[monitor_index]->height()); + + device_force_redraw(); + } } } } @@ -890,7 +887,7 @@ MainWindow::on_actionHard_Reset_triggered() QMessageBox questionbox(QMessageBox::Icon::Question, "86Box", tr("Are you sure you want to hard reset the emulated machine?"), QMessageBox::NoButton, this); 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")); + const auto chkbox = new QCheckBox(tr("Don't show this message again")); questionbox.setCheckBox(chkbox); chkbox->setChecked(!confirm_reset); @@ -934,7 +931,7 @@ MainWindow::on_actionExit_triggered() void MainWindow::on_actionSettings_triggered() { - int currentPause = dopause; + const int currentPause = dopause; plat_pause(1); Settings settings(this); settings.setModal(true); @@ -945,6 +942,8 @@ MainWindow::on_actionSettings_triggered() settings.exec(); switch (settings.result()) { + default: + break; case QDialog::Accepted: pc_reset_hard_close(); settings.save(); @@ -981,6 +980,9 @@ MainWindow::processKeyboardInput(bool down, uint32_t keycode) /* Apply special cases. */ switch (keycode) { + default: + break; + case 0x54: /* Alt + Print Screen (special case, i.e. evdev SELECTIVE_SCREENSHOT) */ /* Send Alt as well. */ if (down) { @@ -1157,8 +1159,6 @@ 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(); @@ -1194,8 +1194,6 @@ MainWindow::on_actionFullscreen_triggered() ui->toolBar->hide(); ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); showFullScreen(); - if (vid_api == 5) - QTimer::singleShot(0, this, [this]() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9); }); } ui->stackedWidget->onResize(width(), height()); } @@ -1317,7 +1315,7 @@ void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index) { if (monitor_index >= 1) { - if (!blitDummied && renderers[monitor_index] && renderers[monitor_index]->isVisible()) + if (renderers[monitor_index] && renderers[monitor_index]->isVisible()) renderers[monitor_index]->blit(x, y, w, h); else video_blit_complete_monitor(monitor_index); @@ -1350,18 +1348,18 @@ MainWindow::checkFullscreenHotkey() { if (!fs_off_signal && video_fullscreen && keyboard_isfsexit()) { /* Signal "exit fullscreen mode". */ - fs_off_signal = 1; + fs_off_signal = true; } else if (fs_off_signal && video_fullscreen && keyboard_isfsexit_up()) { ui->actionFullscreen->trigger(); - fs_off_signal = 0; + fs_off_signal = false; } if (!fs_on_signal && !video_fullscreen && keyboard_isfsenter()) { /* Signal "enter fullscreen mode". */ - fs_on_signal = 1; + fs_on_signal = true; } else if (fs_on_signal && !video_fullscreen && keyboard_isfsenter_up()) { ui->actionFullscreen->trigger(); - fs_on_signal = 0; + fs_on_signal = false; } } @@ -1388,12 +1386,12 @@ MainWindow::on_actionResizable_window_triggered(bool checked) { if (checked) { vid_resize = 1; - setWindowFlag(Qt::WindowMaximizeButtonHint); + setWindowFlag(Qt::WindowMaximizeButtonHint, true); 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]->setWindowFlag(Qt::WindowMaximizeButtonHint, true); renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } @@ -1716,18 +1714,18 @@ MainWindow::on_actionAbout_86Box_triggered() 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(EMU_SITE, QMessageBox::ButtonRole::HelpRole); + const auto webSiteButton = msgBox.addButton(EMU_SITE, QMessageBox::ButtonRole::HelpRole); webSiteButton->connect(webSiteButton, &QPushButton::released, []() { QDesktopServices::openUrl(QUrl("https://" EMU_SITE)); }); #ifdef RELEASE_BUILD - msgBox.setIconPixmap(QIcon(":/settings/win/icons/86Box-green.ico").pixmap(32, 32)); + msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-green.ico").pixmap(32, 32)); #elif defined ALPHA_BUILD - msgBox.setIconPixmap(QIcon(":/settings/win/icons/86Box-red.ico").pixmap(32, 32)); + msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-red.ico").pixmap(32, 32)); #elif defined BETA_BUILD - msgBox.setIconPixmap(QIcon(":/settings/win/icons/86Box-yellow.ico").pixmap(32, 32)); + msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-yellow.ico").pixmap(32, 32)); #else - msgBox.setIconPixmap(QIcon(":/settings/win/icons/86Box-gray.ico").pixmap(32, 32)); + msgBox.setIconPixmap(QIcon(":/settings/qt/icons/86Box-gray.ico").pixmap(32, 32)); #endif msgBox.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); msgBox.exec(); @@ -1864,8 +1862,8 @@ void MainWindow::on_actionTake_screenshot_triggered() { startblit(); - for (int i = 0; i < MONITORS_NUM; i++) - monitors[i].mon_screenshots++; + for (auto & monitor : monitors) + ++monitor.mon_screenshots; endblit(); device_force_redraw(); } @@ -1886,8 +1884,10 @@ MainWindow::setSendKeyboardInput(bool enabled) void MainWindow::updateUiPauseState() { - 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")); + const auto pause_icon = dopause ? QIcon(":/menuicons/qt/icons/run.ico") : + QIcon(":/menuicons/qt/icons/pause.ico"); + const auto tooltip_text = dopause ? QString(tr("Resume execution")) : + QString(tr("Pause execution")); ui->actionPause->setIcon(pause_icon); ui->actionPause->setToolTip(tooltip_text); } @@ -1936,9 +1936,7 @@ MainWindow::changeEvent(QEvent *event) { #ifdef Q_OS_WINDOWS 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())); + QApplication::setFont(QFont(ProgSettings::getFontName(lang_id), 9)); } #endif QWidget::changeEvent(event); @@ -1951,9 +1949,7 @@ MainWindow::changeEvent(QEvent *event) void MainWindow::on_actionRenderer_options_triggered() { - auto dlg = ui->stackedWidget->getOptions(this); - - if (dlg) { + if (const auto dlg = ui->stackedWidget->getOptions(this)) { if (dlg->exec() == QDialog::Accepted) { for (int i = 1; i < MONITORS_NUM; i++) { if (renderers[i] && renderers[i]->hasOptions()) @@ -1966,22 +1962,18 @@ MainWindow::on_actionRenderer_options_triggered() void MainWindow::on_actionMCA_devices_triggered() { - auto dlg = new MCADeviceList(this); - - if (dlg) + if (const auto dlg = new MCADeviceList(this)) dlg->exec(); } void MainWindow::on_actionShow_non_primary_monitors_triggered() { - show_second_monitors = (int) ui->actionShow_non_primary_monitors->isChecked(); - - blitDummied = true; + show_second_monitors = static_cast(ui->actionShow_non_primary_monitors->isChecked()); if (show_second_monitors) { for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { - auto &secondaryRenderer = renderers[monitor_index]; + const auto &secondaryRenderer = renderers[monitor_index]; if (!renderers[monitor_index]) continue; secondaryRenderer->show(); @@ -1991,8 +1983,8 @@ MainWindow::on_actionShow_non_primary_monitors_triggered() 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); + secondaryRenderer->switchRenderer(static_cast(vid_api)); + ui->stackedWidget->switchRenderer(static_cast(vid_api)); } } else { for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { @@ -2008,14 +2000,12 @@ MainWindow::on_actionShow_non_primary_monitors_triggered() } } } - - blitDummied = false; } void MainWindow::on_actionOpen_screenshots_folder_triggered() { - QDir(QString(usr_path) + QString("/screenshots/")).mkpath("."); + static_cast(QDir(QString(usr_path) + QString("/screenshots/")).mkpath(".")); QDesktopServices::openUrl(QUrl(QString("file:///") + usr_path + QString("/screenshots/"))); } @@ -2024,7 +2014,7 @@ MainWindow::on_actionApply_fullscreen_stretch_mode_when_maximized_triggered(bool { video_fullscreen_scale_maximized = checked; - auto widget = ui->stackedWidget->currentWidget(); + const auto widget = ui->stackedWidget->currentWidget(); ui->stackedWidget->onResize(widget->width(), widget->height()); for (int i = 1; i < MONITORS_NUM; i++) { @@ -2052,11 +2042,3 @@ void MainWindow::on_actionACPI_Shutdown_triggered() { acpi_pwrbut_pressed = 1; } - -void MainWindow::on_actionShow_status_icons_in_fullscreen_triggered() -{ - status_icons_fullscreen = !status_icons_fullscreen; - ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); - config_save(); -} - diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 553f9602c..1fca09231 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -12,8 +12,6 @@ class MediaMenu; class RendererStack; -extern std::atomic blitDummied; - namespace Ui { class MainWindow; } @@ -75,7 +73,7 @@ private slots: 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(); + static void on_actionKeyboard_requires_capture_triggered(); void on_actionResizable_window_triggered(bool checked); void on_actionInverted_VGA_monitor_triggered(); void on_action0_5x_triggered(); @@ -144,7 +142,6 @@ 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(); diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index d682815bb..90dbfdab7 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -117,7 +117,6 @@ - @@ -180,7 +179,6 @@ - @@ -294,7 +292,7 @@ - :/menuicons/win/icons/hard_reset.ico:/menuicons/win/icons/hard_reset.ico + :/menuicons/qt/icons/hard_reset.ico:/menuicons/qt/icons/hard_reset.ico &Hard Reset... @@ -306,7 +304,7 @@ - :/menuicons/win/icons/send_cad.ico:/menuicons/win/icons/send_cad.ico + :/menuicons/qt/icons/send_cad.ico:/menuicons/qt/icons/send_cad.ico &Ctrl+Alt+Del @@ -327,7 +325,7 @@ - :/menuicons/win/icons/send_cae.ico:/menuicons/win/icons/send_cae.ico + :/menuicons/qt/icons/send_cae.ico:/menuicons/qt/icons/send_cae.ico Ctrl+Alt+&Esc @@ -342,7 +340,7 @@ - :/menuicons/win/icons/pause.ico:/menuicons/win/icons/pause.ico + :/menuicons/qt/icons/pause.ico:/menuicons/qt/icons/pause.ico &Pause @@ -359,7 +357,7 @@ - :/menuicons/win/icons/settings.ico:/menuicons/win/icons/settings.ico + :/menuicons/qt/icons/settings.ico:/menuicons/qt/icons/settings.ico &Settings... @@ -770,13 +768,13 @@ - :/menuicons/win/icons/acpi_shutdown.ico:/menuicons/win/icons/acpi_shutdown.ico + :/menuicons/qt/icons/acpi_shutdown.ico:/menuicons/qt/icons/acpi_shutdown.ico - ACPI Shutdown + ACPI shutdown - ACPI Shutdown + ACPI shutdown true @@ -831,17 +829,6 @@ MCA devices... - - - true - - - Direct3D 9 - - - 5 - - true @@ -858,7 +845,7 @@ VNC - 6 + 5 @@ -882,14 +869,6 @@ Cursor/Puck - - - true - - - Show status icons in fullscreen - - true diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 26169b0d0..c4fd50567 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -61,6 +61,7 @@ MediaMenu::MediaMenu(QWidget *parent) : QObject(parent) { parentWidget = parent; + connect(this, &MediaMenu::onCdromUpdateUi, this, &MediaMenu::cdromUpdateUi, Qt::QueuedConnection); } void @@ -251,7 +252,7 @@ void MediaMenu::cassetteUpdateMenu() { QString name = cassette_fname; - QString mode = cassette_mode; + const QString mode = cassette_mode; auto childs = cassetteMenu->children(); auto *recordMenu = dynamic_cast(childs[cassetteRecordPos]); auto *playMenu = dynamic_cast(childs[cassettePlayPos]); @@ -265,11 +266,12 @@ MediaMenu::cassetteUpdateMenu() fastFwdMenu->setEnabled(!name.isEmpty()); ejectMenu->setEnabled(!name.isEmpty()); - bool isSaving = mode == QStringLiteral("save"); + const bool isSaving = (mode == QStringLiteral("save")); recordMenu->setChecked(isSaving); playMenu->setChecked(!isSaving); - cassetteMenu->setTitle(QString::asprintf(tr("Cassette: %s").toUtf8().constData(), (name.isEmpty() ? tr("(empty)") : name).toUtf8().constData())); + cassetteMenu->setTitle(QString::asprintf(tr("Cassette: %s").toUtf8().constData(), + (name.isEmpty() ? tr("(empty)") : name).toUtf8().constData())); } void @@ -288,7 +290,7 @@ MediaMenu::cartridgeMount(int i, const QString &filename) void MediaMenu::cartridgeSelectImage(int i) { - auto filename = QFileDialog::getOpenFileName( + const auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), getMediaOpenDirectory(), @@ -313,8 +315,8 @@ MediaMenu::cartridgeEject(int i) void MediaMenu::cartridgeUpdateMenu(int i) { - QString name = cart_fns[i]; - auto *menu = cartridgeMenus[i]; + const QString name = cart_fns[i]; + auto *menu = cartridgeMenus[i]; auto childs = menu->children(); auto *ejectMenu = dynamic_cast(childs[cartridgeEjectPos]); ejectMenu->setEnabled(!name.isEmpty()); @@ -327,8 +329,10 @@ MediaMenu::floppyNewImage(int i) { NewFloppyDialog dialog(NewFloppyDialog::MediaType::Floppy, parentWidget); switch (dialog.exec()) { + default: + break; case QDialog::Accepted: - QByteArray filename = dialog.fileName().toUtf8(); + const QByteArray filename = dialog.fileName().toUtf8(); floppyMount(i, filename, false); break; } @@ -456,6 +460,13 @@ MediaMenu::cdromMount(int i, const QString &filename) cdrom[i].ops = nullptr; memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path)); +#ifdef _WIN32 + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '/')) + fn.data()[strlen(fn.data()) - 1] = '\\'; +#else + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '\\')) + fn.data()[strlen(fn.data()) - 1] = '/'; +#endif cdrom_image_open(&(cdrom[i]), fn.data()); /* Signal media change to the emulated machine. */ if (cdrom[i].insert) @@ -508,12 +519,29 @@ MediaMenu::cdromEject(int i) void MediaMenu::cdromReload(int index, int slot) { - QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Optical); + const 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::cdromUpdateUi(int i) +{ + cdrom_t *drv = &cdrom[i]; + + if (drv->host_drive == 0) { + mhm.addImageToHistory(i, ui::MediaType::Optical, drv->prev_image_path, QString()); + ui_sb_update_icon_state(SB_CDROM | i, 1); + } else { + mhm.addImageToHistory(i, ui::MediaType::Optical, drv->prev_image_path, drv->image_path); + ui_sb_update_icon_state(SB_CDROM | i, 0); + } + + cdromUpdateMenu(i); + ui_sb_update_tip(SB_CDROM | i); +} + void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) { @@ -547,7 +575,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) return; } - QString menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + const 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()); @@ -577,8 +605,8 @@ MediaMenu::cdromUpdateMenu(int i) 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"); + const QString menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData(); + const 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())); @@ -588,15 +616,17 @@ MediaMenu::cdromUpdateMenu(int i) QString busName = tr("Unknown Bus"); switch (cdrom[i].bus_type) { + default: + break; case CDROM_BUS_ATAPI: busName = "ATAPI"; break; case CDROM_BUS_SCSI: busName = "SCSI"; break; - case CDROM_BUS_MITSUMI: - busName = "Mitsumi"; - 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)); @@ -608,6 +638,8 @@ MediaMenu::zipNewImage(int i) { NewFloppyDialog dialog(NewFloppyDialog::MediaType::Zip, parentWidget); switch (dialog.exec()) { + default: + break; case QDialog::Accepted: QByteArray filename = dialog.fileName().toUtf8(); zipMount(i, filename, false); @@ -618,7 +650,7 @@ MediaMenu::zipNewImage(int i) void MediaMenu::zipSelectImage(int i, bool wp) { - auto filename = QFileDialog::getOpenFileName( + const auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), QString(), @@ -631,7 +663,7 @@ MediaMenu::zipSelectImage(int i, bool wp) void MediaMenu::zipMount(int i, const QString &filename, bool wp) { - zip_t *dev = (zip_t *) zip_drives[i].priv; + const auto dev = static_cast(zip_drives[i].priv); zip_disk_close(dev); zip_drives[i].read_only = wp; @@ -651,7 +683,7 @@ MediaMenu::zipMount(int i, const QString &filename, bool wp) void MediaMenu::zipEject(int i) { - zip_t *dev = (zip_t *) zip_drives[i].priv; + const auto dev = static_cast(zip_drives[i].priv); zip_disk_close(dev); zip_drives[i].image_path[0] = 0; @@ -669,7 +701,7 @@ MediaMenu::zipEject(int i) void MediaMenu::zipReload(int i) { - zip_t *dev = (zip_t *) zip_drives[i].priv; + const auto dev = static_cast(zip_drives[i].priv); zip_disk_reload(dev); if (strlen(zip_drives[i].image_path) == 0) { @@ -687,8 +719,8 @@ MediaMenu::zipReload(int i) void MediaMenu::zipUpdateMenu(int i) { - QString name = zip_drives[i].image_path; - QString prev_name = zip_drives[i].prev_image_path; + const QString name = zip_drives[i].image_path; + const QString prev_name = zip_drives[i].prev_image_path; if (!zipMenus.contains(i)) return; auto *menu = zipMenus[i]; @@ -701,6 +733,8 @@ MediaMenu::zipUpdateMenu(int i) QString busName = tr("Unknown Bus"); switch (zip_drives[i].bus_type) { + default: + break; case ZIP_BUS_ATAPI: busName = "ATAPI"; break; @@ -718,6 +752,8 @@ MediaMenu::moNewImage(int i) { NewFloppyDialog dialog(NewFloppyDialog::MediaType::Mo, parentWidget); switch (dialog.exec()) { + default: + break; case QDialog::Accepted: QByteArray filename = dialog.fileName().toUtf8(); moMount(i, filename, false); @@ -728,7 +764,7 @@ MediaMenu::moNewImage(int i) void MediaMenu::moSelectImage(int i, bool wp) { - auto filename = QFileDialog::getOpenFileName( + const auto filename = QFileDialog::getOpenFileName( parentWidget, QString(), getMediaOpenDirectory(), @@ -744,7 +780,7 @@ MediaMenu::moSelectImage(int i, bool wp) void MediaMenu::moMount(int i, const QString &filename, bool wp) { - mo_t *dev = (mo_t *) mo_drives[i].priv; + const auto dev = static_cast(mo_drives[i].priv); mo_disk_close(dev); mo_drives[i].read_only = wp; @@ -764,7 +800,7 @@ MediaMenu::moMount(int i, const QString &filename, bool wp) void MediaMenu::moEject(int i) { - mo_t *dev = (mo_t *) mo_drives[i].priv; + const auto dev = static_cast(mo_drives[i].priv); mo_disk_close(dev); mo_drives[i].image_path[0] = 0; @@ -814,6 +850,8 @@ MediaMenu::moUpdateMenu(int i) QString busName = tr("Unknown Bus"); switch (mo_drives[i].bus_type) { + default: + break; case MO_BUS_ATAPI: busName = "ATAPI"; break; @@ -851,6 +889,8 @@ MediaMenu::nicUpdateMenu(int i) QString netType = tr("Null Driver"); switch (net_cards_conf[i].net_type) { + default: + break; case NET_TYPE_SLIRP: netType = "SLiRP"; break; @@ -876,14 +916,62 @@ QString MediaMenu::getMediaOpenDirectory() { QString openDirectory; - if (open_dir_usr_path > 0) { + + if (open_dir_usr_path > 0) openDirectory = QString::fromUtf8(usr_path); - } + return openDirectory; } // callbacks from 86box C code extern "C" { +void +cassette_mount(char *fn, uint8_t wp) +{ + MediaMenu::ptr->cassetteMount(QString(fn), wp); +} + +void +cassette_eject(void) +{ + MediaMenu::ptr->cassetteEject(); +} + +void +cartridge_mount(uint8_t id, char *fn, uint8_t wp) +{ + MediaMenu::ptr->cartridgeMount(id, QString(fn)); +} + +void +cartridge_eject(uint8_t id) +{ + MediaMenu::ptr->cartridgeEject(id); +} + +void +floppy_mount(uint8_t id, char *fn, uint8_t wp) +{ + MediaMenu::ptr->floppyMount(id, QString(fn), wp); +} + +void +floppy_eject(uint8_t id) +{ + MediaMenu::ptr->floppyEject(id); +} + +void +cdrom_mount(uint8_t id, char *fn) +{ + MediaMenu::ptr->cdromMount(id, QString(fn)); +} + +void +plat_cdrom_ui_update(uint8_t id, uint8_t reload) +{ + emit MediaMenu::ptr->onCdromUpdateUi(id); +} void zip_eject(uint8_t id) @@ -891,6 +979,12 @@ zip_eject(uint8_t id) MediaMenu::ptr->zipEject(id); } +void +zip_mount(uint8_t id, char *fn, uint8_t wp) +{ + MediaMenu::ptr->zipMount(id, QString(fn), wp); +} + void zip_reload(uint8_t id) { @@ -903,6 +997,12 @@ mo_eject(uint8_t id) MediaMenu::ptr->moEject(id); } +void +mo_mount(uint8_t id, char *fn, uint8_t wp) +{ + MediaMenu::ptr->moMount(id, QString(fn), wp); +} + void mo_reload(uint8_t id) { diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp index 57fd8dfc2..7835077b3 100644 --- a/src/qt/qt_mediamenu.hpp +++ b/src/qt/qt_mediamenu.hpp @@ -10,7 +10,7 @@ extern "C" { } class QMenu; -class MediaMenu : QObject { +class MediaMenu : public QObject { Q_OBJECT public: MediaMenu(QWidget *parent); @@ -67,6 +67,12 @@ public: void nicDisconnect(int i); void nicUpdateMenu(int i); +public slots: + void cdromUpdateUi(int i); + +signals: + void onCdromUpdateUi(int i); + private: QWidget *parentWidget = nullptr; diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index f306b6138..e0b11ad7b 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -50,6 +50,7 @@ #include "qt_util.hpp" #ifdef Q_OS_UNIX +# include # include #endif @@ -148,6 +149,11 @@ strnicmp(const char *s1, const char *s2, size_t n) #endif } +void +do_start(void) +{ +} + void do_stop(void) { @@ -371,7 +377,7 @@ plat_pause(int p) wchar_t title[1024]; wchar_t paused_msg[512]; - if (p == dopause) { + 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()); @@ -412,7 +418,7 @@ void plat_power_off(void) { plat_mouse_capture(0); - confirm_exit = 0; + confirm_exit_cmdl = 0; nvr_save(); config_save(); @@ -424,12 +430,6 @@ plat_power_off(void) QTimer::singleShot(0, (const QWidget *) main_window, &QMainWindow::close); } -void -set_language(uint32_t id) -{ - lang_id = id; -} - extern "C++" { QMap> ProgSettings::lcid_langcode = { { 0x0403, { "ca-ES", "Catalan (Spain)" } }, @@ -455,6 +455,7 @@ QMap> ProgSettings::lcid_langcode = { { 0x0C0A, { "es-ES", "Spanish (Spain, Modern Sort)" } }, { 0x041F, { "tr-TR", "Turkish (Turkey)" } }, { 0x0422, { "uk-UA", "Ukrainian (Ukraine)" } }, + { 0x042A, { "vi-VN", "Vietnamese (Vietnam)" } }, { 0xFFFF, { "system", "(System Default)" } }, }; } @@ -580,11 +581,17 @@ c16stombs(char dst[], const uint16_t src[], int len) #endif #ifdef _WIN32 -# define LIB_NAME_GS "gsdll32.dll" +# if defined(__amd64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) +# define LIB_NAME_GS "gsdll64.dll" +# else +# define LIB_NAME_GS "gsdll32.dll" +# endif +# define LIB_NAME_PCAP "Npcap" # define MOUSE_CAPTURE_KEYSEQ "F8+F12" #else # define LIB_NAME_GS "libgs" -# define MOUSE_CAPTURE_KEYSEQ "CTRL-END" +# define LIB_NAME_PCAP "libpcap" +# define MOUSE_CAPTURE_KEYSEQ "Ctrl+End" #endif QMap ProgSettings::translatedstrings; @@ -593,33 +600,23 @@ 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_2131] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); - translatedstrings[IDS_4099] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").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_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 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(); + translatedstrings[STRING_MOUSE_CAPTURE] = QCoreApplication::translate("", "Click to capture mouse").toStdWString(); + translatedstrings[STRING_MOUSE_RELEASE] = QCoreApplication::translate("", "Press %1 to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); + translatedstrings[STRING_MOUSE_RELEASE_MMB] = QCoreApplication::translate("", "Press %1 or middle button to release mouse").arg(QCoreApplication::translate("", MOUSE_CAPTURE_KEYSEQ)).toStdWString(); + translatedstrings[STRING_INVALID_CONFIG] = QCoreApplication::translate("", "Invalid configuration").toStdWString(); + translatedstrings[STRING_NO_ST506_ESDI_CDROM] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString(); + translatedstrings[STRING_PCAP_ERROR_NO_DEVICES] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); + translatedstrings[STRING_PCAP_ERROR_INVALID_DEVICE] = QCoreApplication::translate("", "Invalid PCap device").toStdWString(); + translatedstrings[STRING_PCAP_ERROR_DESC] = QCoreApplication::translate("", "Make sure %1 is installed and that you are on a %1-compatible network connection.").arg(LIB_NAME_PCAP).toStdWString(); + translatedstrings[STRING_GHOSTSCRIPT_ERROR_TITLE] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString(); + translatedstrings[STRING_GHOSTSCRIPT_ERROR_DESC] = QCoreApplication::translate("", "%1 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.").arg(LIB_NAME_GS).toStdWString(); + translatedstrings[STRING_HW_NOT_AVAILABLE_MACHINE] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString(); + translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO] = 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[STRING_HW_NOT_AVAILABLE_VIDEO2] = 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[STRING_HW_NOT_AVAILABLE_TITLE] = QCoreApplication::translate("", "Hardware not available").toStdWString(); + translatedstrings[STRING_MONITOR_SLEEP] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString(); + translatedstrings[STRING_NET_ERROR] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); + translatedstrings[STRING_NET_ERROR_DESC] = QCoreApplication::translate("", "The network configuration will be switched to the null driver").toStdWString(); } wchar_t * @@ -690,7 +687,7 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { return; } QByteArray result = process->readAll(); - auto command_result = QString(result).split(": ").last(); + auto command_result = QString(result).split(": ").last().trimmed(); if(!command_result.isEmpty()) { cpu_string = command_result; } @@ -737,8 +734,47 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { } -double -plat_get_dpi(void) +void +plat_set_thread_name(void *thread, const char *name) { - return util::screenOfWidget(main_window)->devicePixelRatio(); +#ifdef Q_OS_WINDOWS + /* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */ + static void *kernel32_handle = NULL; + static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL; + static dllimp_t kernel32_imports[] = { + // clang-format off + { "SetThreadDescription", &pSetThreadDescription }, + { NULL, NULL } + // clang-format on + }; + + if (!kernel32_handle) { + kernel32_handle = dynld_module("kernel32.dll", kernel32_imports); + if (!kernel32_handle) { + kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */ + pSetThreadDescription = NULL; + } + } + + if (pSetThreadDescription) { + size_t len = strlen(name) + 1; + wchar_t wname[len + 1]; + mbstowcs(wname, name, len); + pSetThreadDescription(thread ? (HANDLE) thread : GetCurrentThread(), wname); + } +#else +# ifdef Q_OS_DARWIN + if (thread) /* Apple pthread can only set self's name */ + return; + char truncated[64]; +# else + char truncated[16]; +# endif + strncpy(truncated, name, sizeof(truncated) - 1); +# ifdef Q_OS_DARWIN + pthread_setname_np(truncated); +# else + pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); +# endif +#endif } diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 4dda901d7..2d047a787 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -46,7 +46,7 @@ ProgSettings::getIconSetPath() { if (iconset_to_qt.isEmpty()) { // Always include default bundled icons - iconset_to_qt.insert("", ":/settings/win/icons"); + iconset_to_qt.insert("", ":/settings/qt/icons"); // 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 @@ -110,6 +110,7 @@ ProgSettings::ProgSettings(QWidget *parent) ui->comboBoxLanguage->setCurrentIndex(ui->comboBoxLanguage->findData(i.key())); } } + ui->comboBoxLanguage->model()->sort(Qt::AscendingOrder); mouseSensitivity = mouse_sensitivity; ui->horizontalSlider->setValue(mouseSensitivity * 100.); @@ -152,6 +153,25 @@ ProgSettings::on_pushButton_released() ui->comboBox->setCurrentIndex(0); } +#ifdef Q_OS_WINDOWS +/* Return the standard font name on Windows, which is overridden per-language + to prevent CJK fonts with embedded bitmaps being chosen as a fallback. */ +QString +ProgSettings::getFontName(uint32_t lcid) +{ + if (lcid == 0x0804) /* zh-CN */ + return "Microsoft YaHei"; + else if (lcid == 0x0404) /* zh-TW */ + return "Microsoft JhengHei"; + else if (lcid == 0x0411) /* ja-JP */ + return "Meiryo UI"; + else if (lcid == 0x0412) /* ko-KR */ + return "Malgun Gothic"; + else + return "Segoe UI"; +} +#endif + void ProgSettings::loadTranslators(QObject *parent) { diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index 7565869b0..642b2002d 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -16,6 +16,9 @@ public: ~ProgSettings(); static QString getIconSetPath(); static QIcon loadIcon(QString file); +#ifdef Q_OS_WINDOWS + static QString getFontName(uint32_t lcid); +#endif static void loadTranslators(QObject *parent = nullptr); static void reloadStrings(); class CustomTranslator : public QTranslator { @@ -37,12 +40,6 @@ public: 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)"); - return finalstr; - } QString finalstr = QTranslator::translate("", sourceText, disambiguation, n); #ifdef Q_OS_MACOS if (finalstr.contains('\t')) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 983f14d26..178134c9d 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -17,15 +17,11 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" -#include "qt_machinestatus.hpp" #include #include #include #include -#include -#include -#include #include @@ -33,8 +29,6 @@ extern "C" { #include <86box/86box.h> #include <86box/plat.h> #include <86box/video.h> - -int status_icons_fullscreen = 0; } RendererCommon::RendererCommon() = default; @@ -88,7 +82,7 @@ RendererCommon::onResize(int width, int height) if (video_fullscreen_scale == FULLSCR_SCALE_INT43) { gh = gw / r43; - gw = gw; +// gw = gw; gsr = r43; } @@ -137,52 +131,6 @@ RendererCommon::onResize(int width, int height) monitors[r_monitor_index].mon_res_y = (double) destination.height(); } -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++) { - QLabel* label = qobject_cast(main_window->statusBar()->children()[i]); - if (label) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QPixmap pixmap = label->pixmap(); -#elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - const QPixmap pixmap = label->pixmap(Qt::ReturnByValue); -#else - const QPixmap pixmap = (label->pixmap() ? *label->pixmap() : QPixmap()); -#endif - 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); - 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)); - 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)); - } - } - } - 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->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->setCompositionMode(prevcompositionMode); -} - bool RendererCommon::eventDelegate(QEvent *event, bool &result) { diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index 897240d27..af72474c7 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -35,9 +35,6 @@ public: /* 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: diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 1b1ed45c3..bc4cb9c13 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -25,9 +25,6 @@ #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" @@ -144,7 +141,7 @@ int ignoreNextMouseEvent = 1; void RendererStack::mouseReleaseEvent(QMouseEvent *event) { - if (!dopause && this->geometry().contains(event->pos()) && + if (!dopause && this->geometry().contains(m_monitor_index >= 1 ? event->globalPos() : event->pos()) && (event->button() == Qt::LeftButton) && !mouse_capture && (isMouseDown & 1) && (kbd_req_capture || (mouse_get_buttons() != 0)) && (mouse_input_mode == 0)) { @@ -279,40 +276,14 @@ RendererStack::switchRenderer(Renderer renderer) { startblit(); if (current) { - 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); - } + rendererWindow->finalize(); + removeWidget(current.get()); + disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); - 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); }); - /* 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(); - } + current.release()->deleteLater(); } else { createRenderer(renderer); } @@ -321,7 +292,6 @@ RendererStack::switchRenderer(Renderer renderer) void RendererStack::createRenderer(Renderer renderer) { - current_vid_api = renderer; switch (renderer) { default: case Renderer::Software: @@ -374,27 +344,6 @@ RendererStack::createRenderer(Renderer renderer) 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: { @@ -444,44 +393,21 @@ RendererStack::createRenderer(Renderer renderer) 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) { + if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) { 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::blitCommon(int x, int y, int w, int h) +RendererStack::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) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set()) { + if ((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; } diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index c9d90869b..5a08b351c 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -59,7 +59,6 @@ public: OpenGLES, OpenGL3, Vulkan, - Direct3D9, None = -1 }; void switchRenderer(Renderer renderer); @@ -81,13 +80,10 @@ public: 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 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); + void blit(int x, int y, int w, int h); private: void createRenderer(Renderer renderer); @@ -107,13 +103,10 @@ private: int isMouseDown = 0; int m_monitor_index = 0; - Renderer current_vid_api = Renderer::None; - std::vector> imagebufs; RendererCommon *rendererWindow { nullptr }; std::unique_ptr current; - std::atomic directBlitting { false }; }; #endif // QT_RENDERERCONTAINER_HPP diff --git a/src/qt/qt_sdl.c b/src/qt/qt_sdl.c deleted file mode 100644 index 15af4d7b6..000000000 --- a/src/qt/qt_sdl.c +++ /dev/null @@ -1,708 +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. - * - * 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 - * covers the entire desktop. - * - * - * - * Authors: Fred N. van Kempen, - * 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: - * - * 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. - */ -#include - -#include -#include -#include -#include -/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */ -#undef HAVE_STDARG_H -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/mouse.h> -#include <86box/keyboard.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/plat_dynld.h> -#include <86box/video.h> -#include <86box/ui.h> -#include <86box/version.h> - -#include "qt_sdl.h" - -#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 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_LGUI] = 0x15B, - [SDL_SCANCODE_RGUI] = 0x15C, - [SDL_SCANCODE_APPLICATION] = 0x15D, - [SDL_SCANCODE_PRINTSCREEN] = 0x137, - [SDL_SCANCODE_NONUSBACKSLASH] = 0x56, -}; - -// #define ENABLE_SDL_LOG 3 -#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); - } -} -#else -# 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; - } else { - ratio = ceil(*d / *g); - *d = *g / ratio; - } -} - -static void -sdl_stretch(int *w, int *h, int *x, int *y) -{ - 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; - 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; - } -} - -static void -sdl_blit(int x, int y, int w, int h) -{ - SDL_Rect r_src; - 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(); - return; - } - - SDL_LockMutex(sdl_mutex); - SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch); - - video_copy(pixeldata, &(buffer32->line[y][x]), h * (2048) * sizeof(uint32_t)); - - if (monitors[m_monitor_index].mon_screenshots) - video_screenshot((uint32_t *) pixeldata, 0, 0, (2048)); - - SDL_UnlockTexture(sdl_tex); - - video_blit_complete(); - - SDL_RenderClear(sdl_render); - - r_src.x = 0; - r_src.y = 0; - r_src.w = w; - r_src.h = 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_RenderPresent(sdl_render); - - SDL_UnlockMutex(sdl_mutex); -} - -static void -sdl_destroy_window(void) -{ - if (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_DestroyRenderer also automatically destroys all associated textures. */ - if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; - } -} - -void -sdl_close(void) -{ - if (sdl_mutex != NULL) - SDL_LockMutex(sdl_mutex); - - /* Unregister our renderer! */ - video_setblit(NULL); - - if (sdl_enabled) - sdl_enabled = 0; - - if (sdl_mutex != NULL) { - SDL_DestroyMutex(sdl_mutex); - sdl_mutex = NULL; - } - - sdl_destroy_texture(); - sdl_destroy_window(); - - /* Quit. */ - SDL_Quit(); - sdl_flags = -1; -} - -static void -sdl_select_best_hw_driver(void) -{ - SDL_RendererInfo renderInfo; - - 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"); - } else { - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); - } - - sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); - - if (sdl_render == NULL) { - sdl_log("SDL: unable to SDL_CreateRenderer (%s)\n", SDL_GetError()); - } - if (sdl_tex == NULL) { - sdl_log("SDL: unable to SDL_CreateTexture (%s)\n", SDL_GetError()); - } -} - -static void -sdl_reinit_texture(void) -{ - if (sdl_flags == -1) - return; - - sdl_destroy_texture(); - sdl_init_texture(); -} - -void -sdl_set_fs(int fs) -{ - SDL_SetWindowFullscreen(sdl_win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - SDL_SetRelativeMouseMode((SDL_bool) mouse_capture); - - sdl_fs = fs; - - if (fs) { - sdl_flags |= RENDERER_FULL_SCREEN; - } else { - sdl_flags &= ~RENDERER_FULL_SCREEN; - } - - sdl_reinit_texture(); -} - -static int -sdl_init_common(void *win, int flags) -{ - wchar_t temp[128]; - SDL_version ver; - - sdl_log("SDL: init (fs=%d)\n", 0); - - /* Get and log the version of the DLL we are using. */ - SDL_GetVersion(&ver); - sdl_log("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch); - - /* Initialize the SDL system. */ - if (SDL_Init(SDL_INIT_VIDEO) < 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(); - } - - /* Get the size of the (current) desktop. */ - SDL_DisplayMode dm; - if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { - sdl_log("SDL: SDL_GetDesktopDisplayMode failed (%s)\n", SDL_GetError()); - return (0); - } - sdl_w = dm.w; - sdl_h = dm.h; - sdl_flags = flags; - - sdl_win = SDL_CreateWindow("86Box renderer", 640, 480, 100, 100, sdl_flags); - if (sdl_win == NULL) { - sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError()); - } - sdl_init_texture(); - sdl_set_fs(video_fullscreen & 1); - - /* Make sure we get a clean exit. */ - atexit(sdl_close); - - /* Register our renderer! */ - video_setblit(sdl_blit); - - sdl_enabled = 1; - sdl_mutex = SDL_CreateMutex(); - - return (1); -} - -int -sdl_inits(void *win) -{ - return sdl_init_common(win, 0); -} - -int -sdl_inith(void *win) -{ - return sdl_init_common(win, RENDERER_HARDWARE); -} - -int -sdl_initho(void *win) -{ - return sdl_init_common(win, RENDERER_HARDWARE | RENDERER_OPENGL); -} - -int -sdl_pause(void) -{ - return 0; -} - -void -sdl_resize(int w, int h) -{ - int ww = 0; - int wh = 0; - - if (video_fullscreen & 2) - return; - - if ((w == cur_w) && (h == cur_h)) - return; - - SDL_LockMutex(sdl_mutex); - - ww = w; - wh = h; - - if (sdl_fs) { - // sdl_stretch(&ww, &wh, &wx, &wy); - // MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); - } - - cur_w = w; - cur_h = h; - - cur_ww = ww; - cur_wh = wh; - - SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); - sdl_reinit_texture(); - - SDL_UnlockMutex(sdl_mutex); -} - -void -sdl_enable(int enable) -{ - if (sdl_flags == -1) - return; - - SDL_LockMutex(sdl_mutex); - sdl_enabled = !!enable; - - if (enable == 1) { - 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_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); - - SDL_UnlockMutex(sdl_mutex); - } -} - -static int mouse_inside = 0; -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) { - event.wheel.x *= -1; - event.wheel.y *= -1; - } - mouse_set_z(event.wheel.y); - } - break; - } - 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; - 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; - } - 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; - } - } - } - } - - if (mouse_capture && keyboard_ismsexit()) { - plat_mouse_capture(0); - } - if (video_fullscreen && keyboard_isfsexit()) { - plat_setfullscreen(0); - } - - return ret; -} - -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 deleted file mode 100644 index f9709c857..000000000 --- a/src/qt/qt_sdl.h +++ /dev/null @@ -1,72 +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 libSDL2 rendering module. - * - * - * - * Authors: Fred N. van Kempen, - * 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: - * - * 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 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); - -enum sdl_main_status { - SdlMainOk, - SdlMainQuit, -}; - -extern enum sdl_main_status sdl_main(); - -extern void sdl_mouse_capture(int on); - -#endif /*WIN_SDL_H*/ diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index c7cb99086..e9767083a 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -153,6 +153,30 @@ Settings::Settings(QWidget *parent) &SettingsStorageControllers::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, otherPeripherals, &SettingsOtherPeripherals::onCurrentMachineChanged); + connect(floppyCdrom, &SettingsFloppyCDROM::cdromChannelChanged, harddisks, + &SettingsHarddisks::reloadBusChannels); + connect(floppyCdrom, &SettingsFloppyCDROM::cdromChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_MO); + connect(floppyCdrom, &SettingsFloppyCDROM::cdromChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_ZIP); + connect(harddisks, &SettingsHarddisks::driveChannelChanged, floppyCdrom, + &SettingsFloppyCDROM::reloadBusChannels); + connect(harddisks, &SettingsHarddisks::driveChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_MO); + connect(harddisks, &SettingsHarddisks::driveChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_ZIP); + connect(otherRemovable, &SettingsOtherRemovable::moChannelChanged, harddisks, + &SettingsHarddisks::reloadBusChannels); + connect(otherRemovable, &SettingsOtherRemovable::moChannelChanged, floppyCdrom, + &SettingsFloppyCDROM::reloadBusChannels); + connect(otherRemovable, &SettingsOtherRemovable::moChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_ZIP); + connect(otherRemovable, &SettingsOtherRemovable::zipChannelChanged, harddisks, + &SettingsHarddisks::reloadBusChannels); + connect(otherRemovable, &SettingsOtherRemovable::zipChannelChanged, floppyCdrom, + &SettingsFloppyCDROM::reloadBusChannels); + connect(otherRemovable, &SettingsOtherRemovable::zipChannelChanged, otherRemovable, + &SettingsOtherRemovable::reloadBusChannels_MO); connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex ¤t, const QModelIndex &previous) { diff --git a/src/qt/qt_settings_bus_tracking.cpp b/src/qt/qt_settings_bus_tracking.cpp index 4fe112627..6fb8637da 100644 --- a/src/qt/qt_settings_bus_tracking.cpp +++ b/src/qt/qt_settings_bus_tracking.cpp @@ -22,6 +22,7 @@ #include #include "86box/hdd.h" +#include "86box/scsi.h" #include "qt_settings_bus_tracking.hpp" SettingsBusTracking::SettingsBusTracking() @@ -30,12 +31,11 @@ SettingsBusTracking::SettingsBusTracking() esdi_tracking = 0x0000000000000000ULL; xta_tracking = 0x0000000000000000ULL; - for (uint8_t i = 0; i < 8; i++) { - if (i < 4) - ide_tracking[i] = 0x0000000000000000ULL; + for (uint8_t i = 0; i < 4; i++) + ide_tracking[i] = 0x0000000000000000ULL; + for (uint8_t i = 0; i < 32; i++) scsi_tracking[i] = 0x0000000000000000ULL; - } } uint8_t @@ -101,7 +101,7 @@ SettingsBusTracking::next_free_scsi_id() uint64_t mask; uint8_t ret = CHANNEL_NONE; - for (uint8_t i = 0; i < 64; i++) { + for (uint8_t i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { element = ((i << 3) >> 6); mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); @@ -187,7 +187,7 @@ SettingsBusTracking::scsi_bus_full() uint64_t mask; uint8_t count = 0; - for (uint8_t i = 0; i < 64; i++) { + for (uint8_t i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { element = ((i << 3) >> 6); mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); @@ -198,6 +198,64 @@ SettingsBusTracking::scsi_bus_full() return (count == 64); } +QList SettingsBusTracking::busChannelsInUse(const int bus) { + + QList channelsInUse; + int element; + uint64_t mask; + switch (bus) { + case HDD_BUS_MFM: + for (uint8_t i = 0; i < 32; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + if (mfm_tracking & mask) + channelsInUse.append(i); + } + break; + case HDD_BUS_ESDI: + for (uint8_t i = 0; i < 32; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + if (esdi_tracking & mask) + channelsInUse.append(i); + } + break; + case HDD_BUS_XTA: + for (uint8_t i = 0; i < 32; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + if (xta_tracking & mask) + channelsInUse.append(i); + } + break; + case HDD_BUS_IDE: + for (uint8_t i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = ((uint64_t) 0xffULL) << ((uint64_t) ((i << 3) & 0x3f)); + if (ide_tracking[element] & mask) + channelsInUse.append(i); + } + break; + case HDD_BUS_ATAPI: + for (uint8_t i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = ((uint64_t) 0xffULL) << ((uint64_t) ((i << 3) & 0x3f)); + if (ide_tracking[element] & mask) + channelsInUse.append(i); + } + break; + case HDD_BUS_SCSI: + for (uint8_t i = 0; i < (SCSI_BUS_MAX * SCSI_ID_MAX); i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + if (scsi_tracking[element] & mask) + channelsInUse.append(i); + } + break; + default: + break; + } + + return channelsInUse; +} + void SettingsBusTracking::device_track(int set, uint8_t dev_type, int bus, int channel) { diff --git a/src/qt/qt_settings_bus_tracking.hpp b/src/qt/qt_settings_bus_tracking.hpp index 3ec61dfb7..917706428 100644 --- a/src/qt/qt_settings_bus_tracking.hpp +++ b/src/qt/qt_settings_bus_tracking.hpp @@ -28,6 +28,8 @@ public: explicit SettingsBusTracking(); ~SettingsBusTracking() = default; + QList busChannelsInUse(int bus); + /* These return 0xff is none is free. */ uint8_t next_free_mfm_channel(); uint8_t next_free_esdi_channel(); @@ -55,8 +57,10 @@ private: 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 }; + /* 9 buses (rounded upwards to 16for future-proofing), 16 devices per bus, + 8 bits per device (future-proofing) = 2048 bits. */ + uint64_t scsi_tracking[32] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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 fcb70f8c5..6969a1c2c 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -139,6 +139,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) if (index < 0) { return; } + static QRegularExpression voodooRegex("3dfx|voodoo|banshee", QRegularExpression::CaseInsensitiveOption); auto curVideoCard_2 = videoCard[1]; videoCard[0] = ui->comboBoxVideo->currentData().toInt(); if (videoCard[0] == VID_INTERNAL) @@ -147,10 +148,6 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) 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; @@ -159,15 +156,16 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) 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); + bool machineSupports8514 = ((machineHasIsa16 || machineHasMca) && !videoCardHas8514); + bool machineSupportsXga = (((machineHasIsa16 && device_available(&xga_isa_device)) || (machineHasMca && device_available(&xga_device))) && !videoCardHasXga); - ui->checkBoxXga->setEnabled((machineHasIsa16 || machineHasMca) && !videoCardHasXga); - if (machineHasIsa16 || machineHasMca) - ui->checkBoxXga->setChecked(xga_standalone_enabled && !videoCardHasXga); + ui->checkBox8514->setEnabled(machineSupports8514); + ui->checkBox8514->setChecked(ibm8514_standalone_enabled && machineSupports8514); - ui->pushButtonConfigureXga->setEnabled((machineHasIsa16 || machineHasMca) && ui->checkBoxXga->isChecked() && !videoCardHasXga); + ui->checkBoxXga->setEnabled(machineSupportsXga); + ui->checkBoxXga->setChecked(xga_standalone_enabled && machineSupportsXga); + + ui->pushButtonConfigureXga->setEnabled(ui->checkBoxXga->isEnabled() && ui->checkBoxXga->isChecked()); int c = 2; @@ -206,6 +204,28 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) ui->comboBoxVideoSecondary->setCurrentIndex(0); ui->pushButtonConfigureSecondary->setEnabled(false); } + + // Is the currently selected video card a voodoo? + if (ui->comboBoxVideo->currentText().contains(voodooRegex)) { + // Get the name of the video card currently in use + const device_t *video_dev = video_card_getdevice(gfxcard[0]); + const QString currentVideoName = DeviceConfig::DeviceName(video_dev, video_get_internal_name(gfxcard[0]), 1); + // Is it a voodoo? + const bool currentCardIsVoodoo = currentVideoName.contains(voodooRegex); + // Don't uncheck if + // * Current card is voodoo + // * Add-on voodoo was manually overridden in config + if (ui->checkBoxVoodoo->isChecked() && !currentCardIsVoodoo) { + // Otherwise, uncheck the add-on voodoo when a main voodoo is selected + ui->checkBoxVoodoo->setCheckState(Qt::Unchecked); + } + ui->checkBoxVoodoo->setDisabled(true); + } else { + ui->checkBoxVoodoo->setEnabled(machineHasPci); + if (machineHasPci) { + ui->checkBoxVoodoo->setChecked(voodoo_enabled); + } + } } void diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index dfda43c40..a9b7e6e2c 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -42,7 +42,7 @@ - XGA + XGA Graphics @@ -61,15 +61,15 @@ - - 30 - 0 0 + + 30 + @@ -95,14 +95,14 @@ - 8514/A + IBM 8514/A Graphics - Voodoo Graphics + Voodoo 1 or 2 Graphics @@ -122,15 +122,15 @@ - - 30 - 0 0 + + 30 + diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index 988f9e856..8f0ac81a9 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -263,6 +263,7 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); ui->comboBoxCDROMType->setCurrentIndex(type); + enableCurrentlySelectedChannel(); } void @@ -288,6 +289,13 @@ SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) ui->tableViewFloppy->selectionModel()->currentIndex(), index); } +void SettingsFloppyCDROM::reloadBusChannels() { + auto selected = ui->comboBoxChannel->currentIndex(); + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt(), Harddrives::busTrackClass); + ui->comboBoxChannel->setCurrentIndex(selected); + enableCurrentlySelectedChannel(); +} + void SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index) { @@ -298,7 +306,7 @@ SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index) ui->comboBoxSpeed->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled); ui->comboBoxCDROMType->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled); - Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus); + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus, Harddrives::busTrackClass); } } @@ -360,6 +368,18 @@ SettingsFloppyCDROM::on_comboBoxBus_activated(int) setCDROMType(ui->tableViewCDROM->model(), ui->tableViewCDROM->selectionModel()->currentIndex(), ui->comboBoxCDROMType->currentData().toUInt()); + emit cdromChannelChanged(); +} + +void +SettingsFloppyCDROM::enableCurrentlySelectedChannel() +{ + const auto *item_model = qobject_cast(ui->comboBoxChannel->model()); + const auto index = ui->comboBoxChannel->currentIndex(); + auto *item = item_model->item(index); + if(item) { + item->setEnabled(true); + } } void @@ -376,6 +396,7 @@ SettingsFloppyCDROM::on_comboBoxChannel_activated(int) Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); + emit cdromChannelChanged(); } void diff --git a/src/qt/qt_settingsfloppycdrom.hpp b/src/qt/qt_settingsfloppycdrom.hpp index 3d6dd0e45..0a3424216 100644 --- a/src/qt/qt_settingsfloppycdrom.hpp +++ b/src/qt/qt_settingsfloppycdrom.hpp @@ -13,9 +13,12 @@ class SettingsFloppyCDROM : public QWidget { public: explicit SettingsFloppyCDROM(QWidget *parent = nullptr); ~SettingsFloppyCDROM(); + void reloadBusChannels(); void save(); +signals: + void cdromChannelChanged(); private slots: void on_comboBoxCDROMType_activated(int index); void on_comboBoxChannel_activated(int index); @@ -30,6 +33,7 @@ private slots: private: Ui::SettingsFloppyCDROM *ui; + void enableCurrentlySelectedChannel(); }; #endif // QT_SETTINGSFLOPPYCDROM_HPP diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index a66203406..3f02ffe54 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -166,6 +166,13 @@ SettingsHarddisks::save() } } +void SettingsHarddisks::reloadBusChannels() { + const auto selected = ui->comboBoxChannel->currentIndex(); + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt(), Harddrives::busTrackClass); + ui->comboBoxChannel->setCurrentIndex(selected); + enableCurrentlySelectedChannel(); +} + void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { @@ -184,7 +191,7 @@ SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) model->setData(col, ui->comboBoxBus->currentData(Qt::UserRole), DataBusPrevious); } - Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt()); + Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt(), Harddrives::busTrackClass); Harddrives::populateSpeeds(ui->comboBoxSpeed->model(), ui->comboBoxBus->currentData().toInt()); int chanIdx = 0; @@ -233,6 +240,18 @@ SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) 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); + emit driveChannelChanged(); + } +} + +void +SettingsHarddisks::enableCurrentlySelectedChannel() +{ + const auto *item_model = qobject_cast(ui->comboBoxChannel->model()); + const auto index = ui->comboBoxChannel->currentIndex(); + auto *item = item_model->item(index); + if(item) { + item->setEnabled(true); } } @@ -283,6 +302,7 @@ SettingsHarddisks::onTableRowChanged(const QModelIndex ¤t) if (!match.isEmpty()) { ui->comboBoxSpeed->setCurrentIndex(match.first().row()); } + reloadBusChannels(); } static void @@ -317,6 +337,7 @@ SettingsHarddisks::on_pushButtonNew_clicked() switch (dialog.exec()) { case QDialog::Accepted: addDriveFromDialog(ui, dialog); + reloadBusChannels(); break; } } @@ -328,6 +349,7 @@ SettingsHarddisks::on_pushButtonExisting_clicked() switch (dialog.exec()) { case QDialog::Accepted: addDriveFromDialog(ui, dialog); + reloadBusChannels(); break; } } @@ -341,6 +363,8 @@ SettingsHarddisks::on_pushButtonRemove_clicked() } auto *model = ui->tableView->model(); + const auto col = idx.siblingAtColumn(ColumnBus); + Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannel).toInt()); 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 68d7ca3d6..4bd287d29 100644 --- a/src/qt/qt_settingsharddisks.hpp +++ b/src/qt/qt_settingsharddisks.hpp @@ -13,9 +13,13 @@ class SettingsHarddisks : public QWidget { public: explicit SettingsHarddisks(QWidget *parent = nullptr); ~SettingsHarddisks(); + void reloadBusChannels(); void save(); +signals: + void driveChannelChanged(); + private slots: void on_comboBoxChannel_currentIndexChanged(int index); void on_comboBoxSpeed_currentIndexChanged(int index); @@ -30,6 +34,7 @@ private slots: private: Ui::SettingsHarddisks *ui; + void enableCurrentlySelectedChannel(); bool buschangeinprogress = false; }; diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 66d6e3de0..05e44c2c0 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -137,22 +137,16 @@ 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; 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); + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); } static int @@ -190,9 +184,9 @@ updateJoystickConfig(int type, int joystick_nr, QWidget *parent) for (int c = 0; c < joystick_get_button_count(type); c++) { joystick_state[joystick_nr].button_mapping[c] = jc.selectedButton(c); } - for (int c = 0; c < joystick_get_button_count(type); c++) { + for (int c = 0; c < joystick_get_pov_count(type) * 2; c += 2) { joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(jc, c, joystick_nr); - joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(jc, c, joystick_nr); + joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(jc, c + 1, joystick_nr); } } } diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 475730db9..aff55203e 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -61,6 +61,11 @@ SettingsMachine::SettingsMachine(QWidget *parent) break; } + auto warning_icon = ui->softFloatWarningIcon->style()->standardIcon(QStyle::SP_MessageBoxWarning); + ui->softFloatWarningIcon->setPixmap(warning_icon.pixmap(warning_icon.actualSize(QSize(16, 16)))); + ui->softFloatWarningIcon->setVisible(false); + ui->softFloatWarningText->setVisible(false); + auto *waitStatesModel = ui->comboBoxWaitStates->model(); waitStatesModel->insertRows(0, 9); auto idx = waitStatesModel->index(0, 0); @@ -337,3 +342,13 @@ SettingsMachine::on_pushButtonConfigure_clicked() const auto *device = machine_get_device(machineId); DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); } + +void SettingsMachine::on_checkBoxFPUSoftfloat_stateChanged(int state) { + if(state == Qt::Checked) { + ui->softFloatWarningIcon->setVisible(true); + ui->softFloatWarningText->setVisible(true); + } else { + ui->softFloatWarningIcon->setVisible(false); + ui->softFloatWarningText->setVisible(false); + } +} \ No newline at end of file diff --git a/src/qt/qt_settingsmachine.hpp b/src/qt/qt_settingsmachine.hpp index 9d0ec62ff..7e89d7fa4 100644 --- a/src/qt/qt_settingsmachine.hpp +++ b/src/qt/qt_settingsmachine.hpp @@ -35,6 +35,7 @@ private slots: private slots: void on_comboBoxMachineType_currentIndexChanged(int index); + void on_checkBoxFPUSoftfloat_stateChanged(int state); private: Ui::SettingsMachine *ui; diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index 22ecc15df..0c9c2708e 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -7,7 +7,7 @@ 0 0 458 - 434 + 459 @@ -41,13 +41,6 @@ 0 - - - - Wait states: - - - @@ -55,6 +48,13 @@ + + + + FPU: + + + @@ -69,55 +69,21 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 30 - - - - 0 - 0 - - - - - - - - PIT Mode: - - - - - - - 30 - - - - 0 - 0 - - - - - + + + + + 0 + 0 + + + + + + + + Machine type: + @@ -144,21 +110,21 @@ - - 30 - 0 0 + + 30 + - Speed: + Frequency: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -167,27 +133,31 @@ - - 30 - 0 0 + + 30 + - - - - - 0 - 0 - + + + + Wait states: + + + + + + + Machine: @@ -229,55 +199,120 @@ - - - - Machine type: - - - - - - - Machine: - - - - - - - FPU: - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 30 + + + + + + + PIT mode: + + + + + + + + 0 + 0 + + + + 30 + + + + - - - - 2 - 2 - - - - Dynamic Recompiler - - + + + + + + 2 + 2 + + + + Dynamic Recompiler + + + + - - - - 3 - 3 - - - - Softfloat FPU - - + + + + + + 3 + 3 + + + + Softfloat FPU + + + + + + + + + + + + + + High performance impact + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index d168138a5..3904b653a 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -23,6 +23,8 @@ extern "C" { #include <86box/machine.h> #include <86box/isamem.h> #include <86box/isartc.h> +#include <86box/unittester.h> +#include <86box/novell_cardkey.h> } #include "qt_deviceconfig.hpp" @@ -44,7 +46,12 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) 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->checkBoxUnitTester->setChecked(unittester_enabled > 0 ? true : false); + ui->checkBoxKeyCard->setChecked((machineHasIsa && (novell_keycard_enabled > 0)) ? true : false); ui->checkBoxISABugger->setEnabled(machineHasIsa); + ui->checkBoxKeyCard->setEnabled(machineHasIsa); + ui->pushButtonConfigureKeyCard->setEnabled(novell_keycard_enabled > 0); + ui->pushButtonConfigureUT->setEnabled(unittester_enabled > 0); ui->comboBoxRTC->setEnabled(machineHasIsa); ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); @@ -112,9 +119,11 @@ void SettingsOtherPeripherals::save() { /* Other peripherals category */ - bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; - postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; - isartc_type = ui->comboBoxRTC->currentData().toInt(); + bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0; + postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0; + unittester_enabled = ui->checkBoxUnitTester->isChecked() ? 1 : 0; + novell_keycard_enabled = ui->checkBoxKeyCard->isChecked() ? 1 : 0; + isartc_type = ui->comboBoxRTC->currentData().toInt(); /* ISA memory boards. */ for (int i = 0; i < ISAMEM_MAX; i++) { @@ -197,3 +206,26 @@ SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() { DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()), 4, qobject_cast(Settings::settings)); } + +void +SettingsOtherPeripherals::on_checkBoxUnitTester_stateChanged(int arg1) +{ + ui->pushButtonConfigureUT->setEnabled(arg1 != 0); +} + +void +SettingsOtherPeripherals::on_pushButtonConfigureUT_clicked() +{ + DeviceConfig::ConfigureDevice(&unittester_device); +} + +void SettingsOtherPeripherals::on_pushButtonConfigureKeyCard_clicked() +{ + DeviceConfig::ConfigureDevice(&novell_keycard_device); +} + +void SettingsOtherPeripherals::on_checkBoxKeyCard_stateChanged(int arg1) +{ + ui->pushButtonConfigureKeyCard->setEnabled(arg1 != 0); +} + diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index 97e47c90e..d5804a68b 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -30,6 +30,12 @@ private slots: void on_comboBoxCard1_currentIndexChanged(int index); void on_pushButtonConfigureRTC_clicked(); void on_comboBoxRTC_currentIndexChanged(int index); + void on_checkBoxUnitTester_stateChanged(int arg1); + void on_pushButtonConfigureUT_clicked(); + + void on_pushButtonConfigureKeyCard_clicked(); + + void on_checkBoxKeyCard_stateChanged(int arg1); private: Ui::SettingsOtherPeripherals *ui; diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 01f5545f8..41df2deac 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -37,15 +37,15 @@ - - 30 - 0 0 + + 30 + @@ -72,15 +72,15 @@ - - 30 - 0 0 + + 30 + @@ -113,15 +113,15 @@ - - 30 - 0 0 + + 30 + @@ -133,28 +133,28 @@ - - 30 - 0 0 + + 30 + - - 30 - 0 0 + + 30 + @@ -192,6 +192,64 @@ + + + + + + + 0 + 0 + + + + 86Box Unit Tester + + + + + + + Configure + + + + + + + + + 0 + + + + + Novell NetWare 2.x Key Card + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Configure + + + + + diff --git a/src/qt/qt_settingsotherremovable.cpp b/src/qt/qt_settingsotherremovable.cpp index f8b29dac5..1a6dceacb 100644 --- a/src/qt/qt_settingsotherremovable.cpp +++ b/src/qt/qt_settingsotherremovable.cpp @@ -140,8 +140,8 @@ SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) model = new QStandardItemModel(0, 2, this); ui->tableViewZIP->setModel(model); - model->setHeaderData(0, Qt::Horizontal, "Bus"); - model->setHeaderData(1, Qt::Horizontal, "Type"); + model->setHeaderData(0, Qt::Horizontal, tr("Bus")); + model->setHeaderData(1, Qt::Horizontal, tr("Type")); model->insertRows(0, ZIP_NUM); for (int i = 0; i < ZIP_NUM; i++) { auto idx = model->index(i, 0); @@ -201,6 +201,7 @@ SettingsOtherRemovable::onMORowChanged(const QModelIndex ¤t) if (!match.isEmpty()) ui->comboBoxMOChannel->setCurrentIndex(match.first().row()); ui->comboBoxMOType->setCurrentIndex(type); + enableCurrentlySelectedChannel_MO(); } void @@ -221,6 +222,16 @@ SettingsOtherRemovable::onZIPRowChanged(const QModelIndex ¤t) if (!match.isEmpty()) ui->comboBoxZIPChannel->setCurrentIndex(match.first().row()); ui->checkBoxZIP250->setChecked(is250); + enableCurrentlySelectedChannel_ZIP(); +} + +void +SettingsOtherRemovable::reloadBusChannels_MO() { + auto selected = ui->comboBoxMOChannel->currentIndex(); + Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), + ui->comboBoxMOBus->currentData().toInt(), Harddrives::busTrackClass); + ui->comboBoxMOChannel->setCurrentIndex(selected); + enableCurrentlySelectedChannel_MO(); } void @@ -231,7 +242,7 @@ SettingsOtherRemovable::on_comboBoxMOBus_currentIndexChanged(int index) bool enabled = (bus != MO_BUS_DISABLED); ui->comboBoxMOChannel->setEnabled(enabled); ui->comboBoxMOType->setEnabled(enabled); - Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), bus); + Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), bus, Harddrives::busTrackClass); } } @@ -258,6 +269,17 @@ SettingsOtherRemovable::on_comboBoxMOBus_activated(int) Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); + emit moChannelChanged(); +} + +void +SettingsOtherRemovable::enableCurrentlySelectedChannel_MO() +{ + const auto *item_model = qobject_cast(ui->comboBoxMOChannel->model()); + const auto index = ui->comboBoxMOChannel->currentIndex(); + auto *item = item_model->item(index); + if (item) + item->setEnabled(true); } void @@ -274,6 +296,7 @@ SettingsOtherRemovable::on_comboBoxMOChannel_activated(int) Harddrives::busTrackClass->device_track(1, DEV_MO, ui->tableViewMO->model()->data(i, Qt::UserRole).toInt(), ui->tableViewMO->model()->data(i, Qt::UserRole + 1).toInt()); + emit moChannelChanged(); } void @@ -286,6 +309,15 @@ SettingsOtherRemovable::on_comboBoxMOType_activated(int) ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); } +void +SettingsOtherRemovable::reloadBusChannels_ZIP() { + auto selected = ui->comboBoxZIPChannel->currentIndex(); + Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), + ui->comboBoxZIPBus->currentData().toInt(), Harddrives::busTrackClass); + ui->comboBoxZIPChannel->setCurrentIndex(selected); + enableCurrentlySelectedChannel_ZIP(); +} + void SettingsOtherRemovable::on_comboBoxZIPBus_currentIndexChanged(int index) { @@ -294,7 +326,7 @@ SettingsOtherRemovable::on_comboBoxZIPBus_currentIndexChanged(int index) bool enabled = (bus != ZIP_BUS_DISABLED); ui->comboBoxZIPChannel->setEnabled(enabled); ui->checkBoxZIP250->setEnabled(enabled); - Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), bus); + Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), bus, Harddrives::busTrackClass); } } @@ -315,6 +347,17 @@ SettingsOtherRemovable::on_comboBoxZIPBus_activated(int) Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); + emit zipChannelChanged(); +} + +void +SettingsOtherRemovable::enableCurrentlySelectedChannel_ZIP() +{ + const auto *item_model = qobject_cast(ui->comboBoxZIPChannel->model()); + const auto index = ui->comboBoxZIPChannel->currentIndex(); + auto *item = item_model->item(index); + if (item) + item->setEnabled(true); } void @@ -331,6 +374,7 @@ SettingsOtherRemovable::on_comboBoxZIPChannel_activated(int) Harddrives::busTrackClass->device_track(1, DEV_ZIP, ui->tableViewZIP->model()->data(i, Qt::UserRole).toInt(), ui->tableViewZIP->model()->data(i, Qt::UserRole + 1).toInt()); + emit zipChannelChanged(); } void diff --git a/src/qt/qt_settingsotherremovable.hpp b/src/qt/qt_settingsotherremovable.hpp index 8b81fb0f0..cea1d202b 100644 --- a/src/qt/qt_settingsotherremovable.hpp +++ b/src/qt/qt_settingsotherremovable.hpp @@ -13,9 +13,14 @@ class SettingsOtherRemovable : public QWidget { public: explicit SettingsOtherRemovable(QWidget *parent = nullptr); ~SettingsOtherRemovable(); + void reloadBusChannels_MO(); + void reloadBusChannels_ZIP(); void save(); +signals: + void moChannelChanged(); + void zipChannelChanged(); private slots: void on_checkBoxZIP250_stateChanged(int arg1); @@ -46,6 +51,8 @@ private slots: private: Ui::SettingsOtherRemovable *ui; + void enableCurrentlySelectedChannel_MO(); + void enableCurrentlySelectedChannel_ZIP(); }; #endif // QT_SETTINGSOTHERREMOVABLE_HPP diff --git a/src/qt/qt_settingssound.cpp b/src/qt/qt_settingssound.cpp index b4df4ff69..e0572c3d8 100644 --- a/src/qt/qt_settingssound.cpp +++ b/src/qt/qt_settingssound.cpp @@ -67,17 +67,17 @@ SettingsSound::save() } void -SettingsSound::onCurrentMachineChanged(int machineId) +SettingsSound::onCurrentMachineChanged(const int machineId) { this->machineId = machineId; - int c = 0; - int selectedRow = 0; + int c; + int selectedRow; 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(); + auto * cbox = findChild(QString("comboBoxSoundCard%1").arg(i + 1)); + auto * model = cbox->model(); + const auto removeRows = model->rowCount(); c = 0; selectedRow = 0; @@ -207,7 +207,7 @@ SettingsSound::on_pushButtonConfigureSoundCard1_clicked() auto *device = sound_card_getdevice(sndCard); if (sndCard == SOUND_INTERNAL) device = machine_get_snd_device(machineId); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 1, qobject_cast(Settings::settings)); } void @@ -225,7 +225,7 @@ SettingsSound::on_pushButtonConfigureSoundCard2_clicked() { int sndCard = ui->comboBoxSoundCard2->currentData().toInt(); auto *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 2, qobject_cast(Settings::settings)); } void @@ -243,7 +243,7 @@ SettingsSound::on_pushButtonConfigureSoundCard3_clicked() { int sndCard = ui->comboBoxSoundCard3->currentData().toInt(); auto *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 3, qobject_cast(Settings::settings)); } void @@ -261,7 +261,7 @@ SettingsSound::on_pushButtonConfigureSoundCard4_clicked() { int sndCard = ui->comboBoxSoundCard4->currentData().toInt(); auto *device = sound_card_getdevice(sndCard); - DeviceConfig::ConfigureDevice(device, 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(device, 4, qobject_cast(Settings::settings)); } void @@ -278,7 +278,8 @@ SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) void SettingsSound::on_pushButtonConfigureMidiOut_clicked() { - DeviceConfig::ConfigureDevice(midi_out_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(midi_out_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()), 0, + qobject_cast(Settings::settings)); } void @@ -295,7 +296,8 @@ SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) void SettingsSound::on_pushButtonConfigureMidiIn_clicked() { - DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()), 0, qobject_cast(Settings::settings)); + DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()), 0, + qobject_cast(Settings::settings)); } void @@ -307,9 +309,8 @@ SettingsSound::on_checkBoxMPU401_stateChanged(int state) void SettingsSound::on_pushButtonConfigureMPU401_clicked() { - if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { + if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) DeviceConfig::ConfigureDevice(&mpu401_mca_device, 0, qobject_cast(Settings::settings)); - } else { + else DeviceConfig::ConfigureDevice(&mpu401_device, 0, qobject_cast(Settings::settings)); - } } diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 30949de3a..389e22852 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -52,7 +52,7 @@ void SettingsStorageControllers::save() { /* Storage devices category */ - for (int i = 0; i < SCSI_BUS_MAX; ++i) { + for (int i = 0; i < SCSI_CARD_MAX; ++i) { auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); scsi_card_current[i] = cbox->currentData().toInt(); } @@ -62,6 +62,7 @@ SettingsStorageControllers::save() ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0; + lba_enhancer_enabled = ui->checkBoxLbaEnhancer->isChecked() ? 1 : 0; } void @@ -160,7 +161,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->comboBoxCDInterface->setCurrentIndex(-1); ui->comboBoxCDInterface->setCurrentIndex(selectedRow); - for (int i = 0; i < SCSI_BUS_MAX; ++i) { + for (int i = 0; i < SCSI_CARD_MAX; ++i) { auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); model = cbox->model(); removeRows = model->rowCount(); @@ -204,6 +205,9 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->checkBoxCassette->setChecked(false); ui->checkBoxCassette->setEnabled(false); } + + ui->checkBoxLbaEnhancer->setChecked(lba_enhancer_enabled > 0 && device_available(&lba_enhancer_device)); + ui->pushButtonConfigureLbaEnhancer->setEnabled(ui->checkBoxLbaEnhancer->isChecked()); } void @@ -333,3 +337,15 @@ SettingsStorageControllers::on_pushButtonSCSI4_clicked() { DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4, qobject_cast(Settings::settings)); } + +void SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1) +{ + ui->pushButtonConfigureLbaEnhancer->setEnabled(arg1 != 0); +} + + +void SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked() +{ + DeviceConfig::ConfigureDevice(&lba_enhancer_device); +} + diff --git a/src/qt/qt_settingsstoragecontrollers.hpp b/src/qt/qt_settingsstoragecontrollers.hpp index 5641889e4..c50a94574 100644 --- a/src/qt/qt_settingsstoragecontrollers.hpp +++ b/src/qt/qt_settingsstoragecontrollers.hpp @@ -39,6 +39,10 @@ private slots: void on_comboBoxHD_currentIndexChanged(int index); void on_comboBoxCDInterface_currentIndexChanged(int index); + void on_checkBoxLbaEnhancer_stateChanged(int arg1); + + void on_pushButtonConfigureLbaEnhancer_clicked(); + private: Ui::SettingsStorageControllers *ui; int machineId = 0; diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index d67127e2d..16d6e2494 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -51,45 +51,45 @@ - - CD-ROM Controller: - false + + CD-ROM Controller: + - - 30 - false + + 30 + - - Configure - false + + Configure + - - 30 - 0 0 + + 30 + @@ -171,15 +171,15 @@ - - 30 - 0 0 + + 30 + @@ -191,41 +191,41 @@ - - 30 - 0 0 + + 30 + - - 30 - 0 0 + + 30 + - - 30 - 0 0 + + 30 + @@ -266,6 +266,43 @@ + + + + 0 + + + 0 + + + + + Vision Systems LBA Enhancer + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Configure + + + + + diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index ab9ed932d..a8c0229d3 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -24,7 +24,6 @@ extern "C" { #include <86box/86box.h> -#include <86box/plat.h> #include <86box/video.h> } @@ -114,7 +113,6 @@ SoftwareRenderer::onPaint(QPaintDevice *device) #endif painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawImage(destination, *images[cur_image], source); - if (video_fullscreen && status_icons_fullscreen) drawStatusBarIcons(&painter); } std::vector> diff --git a/src/qt/qt_translations.qrc b/src/qt/qt_translations.qrc index 017354f82..9f75fd6d6 100644 --- a/src/qt/qt_translations.qrc +++ b/src/qt/qt_translations.qrc @@ -21,6 +21,7 @@ 86box_sl-SI.qm 86box_tr-TR.qm 86box_uk-UA.qm + 86box_vi-VN.qm 86box_zh-CN.qm 86box_zh-TW.qm diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 47e6b48a2..fc111e5b4 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -66,13 +66,13 @@ wchar_t * ui_window_title(wchar_t *str) { if (str == nullptr) { - static wchar_t title[512]; - memset(title, 0, sizeof(title)); + static wchar_t title[512] = { 0 }; + main_window->getTitle(title); str = title; - } else { + } else emit main_window->setTitle(QString::fromWCharArray(str)); - } + return str; } @@ -95,14 +95,14 @@ 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); + plat_resize(fixed_size_x, fixed_size_y, monitor_index); } else { - plat_resize_monitor(w, h, monitor_index); + plat_resize(w, h, monitor_index); } } void -plat_resize_monitor(int w, int h, int monitor_index) +plat_resize(int w, int h, int monitor_index) { if (monitor_index >= 1) main_window->resizeContentsMonitor(w, h, monitor_index); @@ -110,12 +110,6 @@ plat_resize_monitor(int w, int h, int monitor_index) main_window->resizeContents(w, h); } -void -plat_setfullscreen(int on) -{ - main_window->setFullscreen(on > 0 ? true : false); -} - void plat_mouse_capture(int on) { @@ -128,13 +122,10 @@ plat_mouse_capture(int on) 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)); + const auto hdr = (flags & MBX_ANSI) ? QString(static_cast(header)) : + QString::fromWCharArray(static_cast(header)); + const auto msg = (flags & MBX_ANSI) ? QString(static_cast(message)) : + QString::fromWCharArray(static_cast(message)); // any error in early init if (main_window == nullptr) { @@ -231,9 +222,13 @@ ui_sb_set_ready(int ready) void ui_sb_update_icon_state(int tag, int state) { - int category = tag & 0xfffffff0; - int item = tag & 0xf; + const auto temp = static_cast(tag); + const int category = static_cast(temp & 0xfffffff0); + const int item = tag & 0xf; + switch (category) { + default: + break; case SB_CASSETTE: machine_status.cassette.empty = state > 0 ? true : false; break; @@ -258,7 +253,6 @@ ui_sb_update_icon_state(int tag, int state) machine_status.net[item].empty = state > 0 ? true : false; break; case SB_SOUND: - break; case SB_TEXT: break; } @@ -267,11 +261,13 @@ ui_sb_update_icon_state(int tag, int state) void ui_sb_update_icon(int tag, int active) { - int category = tag & 0xfffffff0; - int item = tag & 0xf; + const auto temp = static_cast(tag); + const int category = static_cast(temp & 0xfffffff0); + const int item = tag & 0xf; + switch (category) { + default: case SB_CASSETTE: - break; case SB_CARTRIDGE: break; case SB_FLOPPY: @@ -293,7 +289,6 @@ ui_sb_update_icon(int tag, int active) machine_status.net[item].active = active > 0 ? true : false; break; case SB_SOUND: - break; case SB_TEXT: break; } diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index b05b656bb..0a59cdf5d 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -21,8 +21,20 @@ #if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0) # include #endif +#include #include "qt_util.hpp" +extern "C" { +#include <86box/86box.h> +#include <86box/config.h> +#include <86box/device.h> +#include <86box/ini.h> +#include <86box/random.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> +} + namespace util { QScreen * screenOfWidget(QWidget *widget) @@ -56,4 +68,45 @@ DlgFilter(std::initializer_list extensions, bool last) return " (" % temp.join(' ') % ")" % (!last ? ";;" : ""); } +QString currentUuid() +{ + return QUuid::createUuidV5(QUuid{}, QString(usr_path)).toString(QUuid::WithoutBraces); +} + +bool compareUuid() +{ + // A uuid not set in the config file will have a zero length. + // Any uuid that is lower than the minimum length will be considered invalid + // and a new one will be generated + if (const auto currentUuidLength = QString(uuid).length(); currentUuidLength < UUID_MIN_LENGTH) { + storeCurrentUuid(); + return true; + } + // The uuid appears to be a valid, at least by length. + // Compare with a simple string match + return uuid == currentUuid(); +} + +void +storeCurrentUuid() +{ + strncpy(uuid, currentUuid().toUtf8().constData(), sizeof(uuid) - 1); +} + +void +generateNewMacAdresses() +{ + for (int i = 0; i < NET_CARD_MAX; ++i) { + auto net_card = net_cards_conf[i]; + if (net_card.device_num != 0) { + const auto network_device = network_card_getdevice(net_card.device_num); + device_context_t device_context; + + device_set_context(&device_context, network_device, i+1); + auto generatedMac = QString::asprintf("%02X:%02X:%02X", random_generate(), random_generate(), random_generate()).toLower(); + config_set_string(device_context.name, "mac", generatedMac.toUtf8().constData()); + } + } +} + } diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 6ecd904b3..07e44b621 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -8,10 +8,15 @@ class QScreen; namespace util { +static constexpr auto UUID_MIN_LENGTH = 36; /* 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); +QString currentUuid(); +void storeCurrentUuid(); +bool compareUuid(); +void generateNewMacAdresses(); }; #endif diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index b8e7d1038..3ca091ae6 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -53,17 +53,15 @@ 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}, + .hwndTarget = nullptr}, { .usUsagePage = 0x01, .usUsage = 0x02, .dwFlags = 0, - .hwndTarget = wnd} + .hwndTarget = nullptr} }; if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE) diff --git a/src/qt/sdl_joystick.cpp b/src/qt/sdl_joystick.c similarity index 69% rename from src/qt/sdl_joystick.cpp rename to src/qt/sdl_joystick.c index cdbf102b8..d56612872 100644 --- a/src/qt/sdl_joystick.cpp +++ b/src/qt/sdl_joystick.c @@ -1,28 +1,53 @@ -// Lifted from wx-sdl2-joystick.c in PCem - +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * SDL2 joystick interface. + * + * + * + * Authors: Sarah Walker, + * Joakim L. Gilje + * + * Copyright 2017-2021 Sarah Walker + * Copyright 2021 Joakim L. Gilje + */ #include -#include - -extern "C" { +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */ +#undef HAVE_STDARG_H +#define HAVE_STDARG_H +#include <86box/86box.h> #include <86box/device.h> #include <86box/gameport.h> +#include <86box/plat_unused.h> 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 #endif void -joystick_init() +joystick_init(void) { + /* This is needed for SDL's Windows raw input backend to work properly without SDL video. */ + SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) { return; } @@ -36,19 +61,19 @@ joystick_init() 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_buttons = SDL_JoystickNumButtons(sdl_joy[c]); - plat_joystick_state[c].nr_povs = SDL_JoystickNumHats(sdl_joy[c]); + plat_joystick_state[c].nr_axes = MIN(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES); + plat_joystick_state[c].nr_buttons = MIN(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS); + plat_joystick_state[c].nr_povs = MIN(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS); - for (d = 0; d < std::min(plat_joystick_state[c].nr_axes, 8); d++) { + for (d = 0; d < plat_joystick_state[c].nr_axes; 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++) { + for (d = 0; d < plat_joystick_state[c].nr_buttons; 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++) { + for (d = 0; d < plat_joystick_state[c].nr_povs; 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; } @@ -57,7 +82,7 @@ joystick_init() } void -joystick_close() +joystick_close(void) { int c; @@ -103,8 +128,9 @@ joystick_get_axis(int joystick_nr, int mapping) } else return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } + void -joystick_process() +joystick_process(void) { int c; int d; @@ -116,17 +142,13 @@ joystick_process() for (c = 0; c < joysticks_present; c++) { int b; - plat_joystick_state[c].a[0] = SDL_JoystickGetAxis(sdl_joy[c], 0); - plat_joystick_state[c].a[1] = SDL_JoystickGetAxis(sdl_joy[c], 1); - plat_joystick_state[c].a[2] = SDL_JoystickGetAxis(sdl_joy[c], 2); - plat_joystick_state[c].a[3] = SDL_JoystickGetAxis(sdl_joy[c], 3); - plat_joystick_state[c].a[4] = SDL_JoystickGetAxis(sdl_joy[c], 4); - plat_joystick_state[c].a[5] = SDL_JoystickGetAxis(sdl_joy[c], 5); + for (b = 0; b < plat_joystick_state[c].nr_axes; b++) + plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b); - for (b = 0; b < 16; b++) + for (b = 0; b < plat_joystick_state[c].nr_buttons; b++) plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b); - for (b = 0; b < 4; b++) + for (b = 0; b < plat_joystick_state[c].nr_povs; b++) plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b); // 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); } @@ -164,3 +186,11 @@ joystick_process() } } } + +#ifdef _WIN32 +void +win_joystick_handle(UNUSED(void *raw)) +{ + /* Nothing to be done here, atleast currently */ +} +#endif diff --git a/src/win/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c similarity index 100% rename from src/win/win_cdrom_ioctl.c rename to src/qt/win_cdrom_ioctl.c diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index 7ee0e8227..bb05c3f5c 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -35,6 +35,29 @@ #include <86box/gameport.h> #include <86box/win.h> +/* These are defined in hidusage.h in the Windows SDK, but not in mingw-w64. */ +#ifndef HID_USAGE_SIMULATION_AILERON +# define HID_USAGE_SIMULATION_AILERON ((USAGE) 0xb0) +#endif +#ifndef HID_USAGE_SIMULATION_ELEVATOR +# define HID_USAGE_SIMULATION_ELEVATOR ((USAGE) 0xb8) +#endif +#ifndef HID_USAGE_SIMULATION_ACCELLERATOR +# define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xc4) +#endif +#ifndef HID_USAGE_SIMULATION_BRAKE +# define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xc5) +#endif +#ifndef HID_USAGE_SIMULATION_CLUTCH +# define HID_USAGE_SIMULATION_CLUTCH ((USAGE) 0xc6) +#endif +#ifndef HID_USAGE_SIMULATION_SHIFTER +# define HID_USAGE_SIMULATION_SHIFTER ((USAGE) 0xc7) +#endif +#ifndef HID_USAGE_SIMULATION_STEERING +# define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xc8) +#endif + #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; @@ -65,14 +88,14 @@ typedef struct { USHORT bitsize; LONG max; LONG min; - } axis[8]; + } axis[MAX_JOY_AXES]; struct raw_pov_t { USAGE usage; USHORT link; LONG max; LONG min; - } pov[4]; + } pov[MAX_JOY_POVS]; } raw_joystick_t; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; @@ -85,7 +108,7 @@ raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; void joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) { - if (joy->nr_buttons >= 32) + if (joy->nr_buttons >= MAX_JOY_BUTTONS) return; if (usage < 1 || usage > 128) return; @@ -98,7 +121,7 @@ joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) void joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_axes >= 8) + if (joy->nr_axes >= MAX_JOY_AXES) return; switch (prop->Range.UsageMin) { @@ -120,6 +143,42 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS case HID_USAGE_GENERIC_RZ: sprintf(joy->axis[joy->nr_axes].name, "RZ"); break; + case HID_USAGE_GENERIC_SLIDER: + sprintf(joy->axis[joy->nr_axes].name, "Slider"); + break; + case HID_USAGE_GENERIC_DIAL: + sprintf(joy->axis[joy->nr_axes].name, "Dial"); + break; + case HID_USAGE_GENERIC_WHEEL: + sprintf(joy->axis[joy->nr_axes].name, "Wheel"); + break; + case HID_USAGE_SIMULATION_AILERON: + sprintf(joy->axis[joy->nr_axes].name, "Aileron"); + break; + case HID_USAGE_SIMULATION_ELEVATOR: + sprintf(joy->axis[joy->nr_axes].name, "Elevator"); + break; + case HID_USAGE_SIMULATION_RUDDER: + sprintf(joy->axis[joy->nr_axes].name, "Rudder"); + break; + case HID_USAGE_SIMULATION_THROTTLE: + sprintf(joy->axis[joy->nr_axes].name, "Throttle"); + break; + case HID_USAGE_SIMULATION_ACCELLERATOR: + sprintf(joy->axis[joy->nr_axes].name, "Accelerator"); + break; + case HID_USAGE_SIMULATION_BRAKE: + sprintf(joy->axis[joy->nr_axes].name, "Brake"); + break; + case HID_USAGE_SIMULATION_CLUTCH: + sprintf(joy->axis[joy->nr_axes].name, "Clutch"); + break; + case HID_USAGE_SIMULATION_SHIFTER: + sprintf(joy->axis[joy->nr_axes].name, "Shifter"); + break; + case HID_USAGE_SIMULATION_STEERING: + sprintf(joy->axis[joy->nr_axes].name, "Steering"); + break; default: return; } @@ -147,7 +206,7 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS void joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_povs >= 4) + if (joy->nr_povs >= MAX_JOY_POVS) return; sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); @@ -367,10 +426,10 @@ win_joystick_handle(PRAWINPUT raw) /* 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; + 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); @@ -395,14 +454,16 @@ win_joystick_handle(PRAWINPUT raw) } plat_joystick_state[j].a[a] = value; - // joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#if 0 + joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#endif } /* 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; + 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); @@ -415,9 +476,13 @@ win_joystick_handle(PRAWINPUT raw) plat_joystick_state[j].p[p] = value; - // joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); +#if 0 + joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); +#endif } - // joystick_log("\n"); +#if 0 + joystick_log("\n"); +#endif } static int diff --git a/src/qt/win_netsocket.c b/src/qt/win_netsocket.c new file mode 100644 index 000000000..55a84d414 --- /dev/null +++ b/src/qt/win_netsocket.c @@ -0,0 +1,203 @@ +#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/plat_netsocket.h> +#include <86box/ui.h> + +#include +#include +#include +#include + +SOCKET +plat_netsocket_create(int type) +{ + SOCKET socket = -1; + u_long yes = 1; + + if (type != NET_SOCKET_TCP) + return -1; + + socket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + if (socket == INVALID_SOCKET) + return -1; + + ioctlsocket(socket, FIONBIO, &yes); + + return socket; +} + +SOCKET +plat_netsocket_create_server(int type, unsigned short port) +{ + struct sockaddr_in sock_addr; + SOCKET socket = -1; + u_long yes = 1; + + if (type != NET_SOCKET_TCP) + return -1; + + socket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + if (socket == INVALID_SOCKET) + return -1; + + memset(&sock_addr, 0, sizeof(struct sockaddr_in)); + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = INADDR_ANY; + sock_addr.sin_port = htons(port); + + if (bind(socket, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + plat_netsocket_close(socket); + return (SOCKET) -1; + } + + if (listen(socket, 5) == SOCKET_ERROR) { + plat_netsocket_close(socket); + return (SOCKET) -1; + } + + ioctlsocket(socket, FIONBIO, &yes); + + return socket; +} + +void +plat_netsocket_close(SOCKET socket) +{ + closesocket((SOCKET) socket); +} + +SOCKET +plat_netsocket_accept(SOCKET socket) +{ + SOCKET clientsocket = accept(socket, NULL, NULL); + + if (clientsocket == INVALID_SOCKET) + return -1; + + return clientsocket; +} + +int +plat_netsocket_connected(SOCKET socket) +{ + struct sockaddr addr; + socklen_t len = sizeof(struct sockaddr); + fd_set wrfds, exfds; + struct timeval tv; + int res = SOCKET_ERROR; + int status = 0; + int optlen = 4; + + FD_ZERO(&wrfds); + FD_ZERO(&exfds); + FD_SET(socket, &wrfds); + FD_SET(socket, &exfds); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + res = select(socket + 1, NULL, &wrfds, &exfds, &tv); + + if (res == SOCKET_ERROR) + return -1; + + if (res >= 1 && FD_ISSET(socket, &exfds)) { + res = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *) &status, &optlen); + pclog("Socket error %d\n", status); + return -1; + } + + if (res == 0 || !(res >= 1 && FD_ISSET(socket, &wrfds))) + return 0; + + res = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *) &status, &optlen); + + if (res == SOCKET_ERROR) + return -1; + + if (status != 0) + return -1; + + if (getpeername(socket, &addr, &len) == SOCKET_ERROR) + return -1; + + return 1; +} + +int +plat_netsocket_connect(SOCKET socket, const char *hostname, unsigned short port) +{ + struct sockaddr_in sock_addr; + int res = -1; + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = inet_addr(hostname); + sock_addr.sin_port = htons(port); + + if (sock_addr.sin_addr.s_addr == INADDR_ANY || sock_addr.sin_addr.s_addr == INADDR_NONE) { + struct hostent *hp; + + hp = gethostbyname(hostname); + + if (hp) + memcpy(&sock_addr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); + else + return -1; + } + + res = connect(socket, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_in)); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (error == WSAEISCONN || error == WSAEWOULDBLOCK) + return 0; + + res = -1; + } + return res; +} + +int +plat_netsocket_send(SOCKET socket, const unsigned char *data, unsigned int size, int *wouldblock) +{ + int res = send(socket, (const char *) data, size, 0); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (wouldblock) + *wouldblock = !!(error == WSAEWOULDBLOCK); + + return -1; + } + return res; +} + +int +plat_netsocket_receive(SOCKET socket, unsigned char *data, unsigned int size, int *wouldblock) +{ + int res = recv(socket, (char *) data, size, 0); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (wouldblock) + *wouldblock = !!(error == WSAEWOULDBLOCK); + + return -1; + } + return res; +} diff --git a/src/win/win_opendir.c b/src/qt/win_opendir.c similarity index 100% rename from src/win/win_opendir.c rename to src/qt/win_opendir.c diff --git a/src/win/win_serial_passthrough.c b/src/qt/win_serial_passthrough.c similarity index 97% rename from src/win/win_serial_passthrough.c rename to src/qt/win_serial_passthrough.c index b2d09b1d0..2b77bd219 100644 --- a/src/win/win_serial_passthrough.c +++ b/src/qt/win_serial_passthrough.c @@ -173,7 +173,7 @@ 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); + 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 }; diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 67f9cadac..265fb6376 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -1,62 +1,62 @@ - win/icons/cartridge.ico - win/icons/cartridge_empty.ico - win/icons/cassette.ico - win/icons/cassette_active.ico - win/icons/cassette_empty.ico - win/icons/cassette_empty_active.ico - win/icons/cdrom.ico - win/icons/cdrom_active.ico - win/icons/cdrom_disabled.ico - win/icons/cdrom_empty.ico - win/icons/cdrom_empty_active.ico - win/icons/display.ico - win/icons/floppy_35.ico - win/icons/floppy_35_active.ico - win/icons/floppy_35_empty.ico - win/icons/floppy_35_empty_active.ico - win/icons/floppy_525.ico - win/icons/floppy_525_active.ico - win/icons/floppy_525_empty.ico - win/icons/floppy_525_empty_active.ico - win/icons/floppy_and_cdrom_drives.ico - win/icons/floppy_disabled.ico - win/icons/hard_disk.ico - win/icons/hard_disk_active.ico - win/icons/input_devices.ico - win/icons/machine.ico - win/icons/mo.ico - win/icons/mo_active.ico - win/icons/mo_disabled.ico - win/icons/mo_empty.ico - 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 - win/icons/sound.ico - win/icons/storage_controllers.ico - win/icons/zip.ico - win/icons/zip_active.ico - win/icons/zip_disabled.ico - win/icons/zip_empty.ico - win/icons/zip_empty_active.ico - win/icons/86Box-gray.ico - win/icons/86Box-green.ico - win/icons/86Box-red.ico - win/icons/86Box-yellow.ico + qt/icons/cartridge.ico + qt/icons/cartridge_empty.ico + qt/icons/cassette.ico + qt/icons/cassette_active.ico + qt/icons/cassette_empty.ico + qt/icons/cassette_empty_active.ico + qt/icons/cdrom.ico + qt/icons/cdrom_active.ico + qt/icons/cdrom_disabled.ico + qt/icons/cdrom_empty.ico + qt/icons/cdrom_empty_active.ico + qt/icons/display.ico + qt/icons/floppy_35.ico + qt/icons/floppy_35_active.ico + qt/icons/floppy_35_empty.ico + qt/icons/floppy_35_empty_active.ico + qt/icons/floppy_525.ico + qt/icons/floppy_525_active.ico + qt/icons/floppy_525_empty.ico + qt/icons/floppy_525_empty_active.ico + qt/icons/floppy_and_cdrom_drives.ico + qt/icons/floppy_disabled.ico + qt/icons/hard_disk.ico + qt/icons/hard_disk_active.ico + qt/icons/input_devices.ico + qt/icons/machine.ico + qt/icons/mo.ico + qt/icons/mo_active.ico + qt/icons/mo_disabled.ico + qt/icons/mo_empty.ico + qt/icons/mo_empty_active.ico + qt/icons/network.ico + qt/icons/network_active.ico + qt/icons/network_empty.ico + qt/icons/other_peripherals.ico + qt/icons/other_removable_devices.ico + qt/icons/ports.ico + qt/icons/sound.ico + qt/icons/storage_controllers.ico + qt/icons/zip.ico + qt/icons/zip_active.ico + qt/icons/zip_disabled.ico + qt/icons/zip_empty.ico + qt/icons/zip_empty_active.ico + qt/icons/86Box-gray.ico + qt/icons/86Box-green.ico + qt/icons/86Box-red.ico + qt/icons/86Box-yellow.ico - win/icons/acpi_shutdown.ico - win/icons/hard_reset.ico - win/icons/pause.ico - win/icons/run.ico - win/icons/send_cad.ico - win/icons/send_cae.ico - win/icons/settings.ico + qt/icons/acpi_shutdown.ico + qt/icons/hard_reset.ico + qt/icons/pause.ico + qt/icons/run.ico + qt/icons/send_cad.ico + qt/icons/send_cae.ico + qt/icons/settings.ico qt/texture_vert.spv diff --git a/src/scsi/CMakeLists.txt b/src/scsi/CMakeLists.txt index addde844e..01e20b929 100644 --- a/src/scsi/CMakeLists.txt +++ b/src/scsi/CMakeLists.txt @@ -14,5 +14,5 @@ # 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) + scsi_x54x.c scsi_aha154x.c scsi_buslogic.c scsi_ncr5380.c scsi_ncr53c400.c + scsi_t128.c scsi_ncr53c8xx.c scsi_pcscsi.c scsi_spock.c) diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 238fa7cb3..23c3e65f3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -42,7 +42,7 @@ #include <86box/scsi_pcscsi.h> #include <86box/scsi_spock.h> -int scsi_card_current[SCSI_BUS_MAX] = { 0, 0, 0, 0 }; +int scsi_card_current[SCSI_CARD_MAX] = { 0, 0, 0, 0 }; double scsi_bus_speed[SCSI_BUS_MAX] = { 0.0, 0.0, 0.0, 0.0 }; static uint8_t next_scsi_bus = 0; @@ -82,10 +82,11 @@ static SCSI_CARD scsi_cards[] = { { &scsi_rt1000b_device, }, { &scsi_rt1000mc_device, }, { &scsi_t128_device, }, + { &scsi_t228_device, }, { &scsi_t130b_device, }, { &aha1640_device, }, { &buslogic_640a_device, }, - { &ncr53c90_mca_device, }, + { &ncr53c90a_mca_device, }, { &spock_device, }, { &tribble_device, }, { &buslogic_958d_pci_device, }, @@ -168,12 +169,7 @@ scsi_card_get_from_internal_name(char *s) void scsi_card_init(void) { - 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--; + int max = SCSI_CARD_MAX; /* Do not initialize any controllers if we have do not have any SCSI bus left. */ diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 05b8b2726..2927d797c 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -70,6 +70,11 @@ uint16_t aha_ports[] = { static uint8_t *aha1542cp_pnp_rom = NULL; +// static char *aha1542cp_rev = "F001"; +static char aha1542cp_rev[16] = { 0 }; + +static uint16_t fw_chksum = 0x0000; + #pragma pack(push, 1) typedef struct aha_setup_t { uint8_t CustomerSignature[20]; @@ -466,8 +471,10 @@ aha_setup_data(void *priv) ReplyISI->fParityCheckingEnabled = dev->parity & 1; U32_TO_ADDR(aha_setup->BIOSMailboxAddress, dev->BIOSMailboxOutAddr); - aha_setup->uChecksum = 0xA3; - aha_setup->uUnknown = 0xC2; + // aha_setup->uChecksum = 0xA3; + // aha_setup->uUnknown = 0xC2; + aha_setup->uChecksum = fw_chksum >> 8; + aha_setup->uUnknown = fw_chksum & 0xff; } static void @@ -822,6 +829,7 @@ aha_setmcode(x54x_t *dev) { uint32_t temp; FILE *fp; + uint16_t tempb = 0x00; /* Only if this device has a BIOS ROM. */ if (dev->mcode_path == NULL) @@ -851,6 +859,9 @@ aha_setmcode(x54x_t *dev) return; } + fseek(fp, 0x3136, SEEK_SET); + (void) !fread(dev->fw_rev, 4, 1, fp); + /* Allocate the buffer and then read the real PnP ROM into it. */ if (aha1542cp_pnp_rom != NULL) { free(aha1542cp_pnp_rom); @@ -874,6 +885,14 @@ aha_setmcode(x54x_t *dev) fseek(fp, dev->cmd_33_offset, SEEK_SET); (void) !fread(dev->cmd_33_buf, dev->cmd_33_len, 1, fp); + fw_chksum = 0x0000; + + for (uint16_t i = 0; i < 32768; i++) { + (void) fseek(fp, i, SEEK_SET); + (void) !fread(&tempb, 1, 1, fp); + fw_chksum += tempb; + } + (void) fclose(fp); } @@ -892,7 +911,7 @@ aha_initnvr(x54x_t *dev) 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*/ + EE6_RSTBUS); /* reset SCSI bus on boot */ } /* Initialize the board's EEPROM (NVR.) */ @@ -942,6 +961,7 @@ static void * aha_init(const device_t *info) { x54x_t *dev; + const char *bios_rev = NULL; /* Call common initializer. */ dev = x54x_init(info); @@ -981,13 +1001,16 @@ aha_init(const device_t *info) strcpy(dev->vendor, "Adaptec"); + fw_chksum = 0xa3c2; + /* 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. */ + /* 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 */ @@ -1009,7 +1032,8 @@ aha_init(const device_t *info) 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. */ + /* 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 */ @@ -1053,10 +1077,11 @@ aha_init(const device_t *info) 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"; + bios_rev = (char *) device_get_config_bios("bios_rev"); + dev->bios_path = (char *) device_get_bios_file(info, bios_rev, 0); + dev->mcode_path = (char *) device_get_bios_file(info, bios_rev, 1); dev->nvr_path = "aha1542cp.nvr"; - dev->fw_rev = "F001"; + dev->fw_rev = aha1542cp_rev; 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 */ @@ -1069,11 +1094,14 @@ aha_init(const device_t *info) 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 */ + if (!strcmp(bios_rev, "v1_02_en")) + dev->pnp_offset = 0x533d; /* offset of the PnP ROM in the microcode ROM */ + else + dev->pnp_offset = 0x5345; /* 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); @@ -1384,6 +1412,31 @@ static const device_config_t aha_154xcf_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; + +static const device_config_t aha_154xcp_config[] = { + { + .name = "bios_rev", + .description = "BIOS Revision", + .type = CONFIG_BIOS, + .default_string = "v1_02_en", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 1.02 (English)", .internal_name = "v1_02_en", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp102.bin", + "roms/scsi/adaptec/908301-00_f_mcode_17c9.u12", "" } }, + { .name = "Version 1.02 (German)", .internal_name = "v1_02_de", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/buff_1-0_bios.bin", + "roms/scsi/adaptec/buff_1-0_mcode.bin", "" } }, + { .name = "Version 1.03 (English)", .internal_name = "v1_03_en", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 32768, .files = { "roms/scsi/adaptec/aha1542cp103.bin", + "roms/scsi/adaptec/908301-00_g_mcode_144c.u12.bin", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; // clang-format on const device_t aha154xa_device = { @@ -1453,7 +1506,7 @@ const device_t aha154xcp_device = { { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = aha_154xcp_config }; const device_t aha1640_device = { diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index fb52ca898..47ba0535e 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -990,7 +990,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) if (dev->current_cdb[0] == 0x42) dev->callback += 40.0; /* Account for seek time. */ - bytes_per_second = 176.0 * 1024.0; + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; case 0xc6 ... 0xc7: @@ -1000,7 +1001,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) 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 = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; } @@ -1011,7 +1012,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) 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; + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; } @@ -1023,7 +1025,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) 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; + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; } @@ -1037,7 +1040,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) case CDROM_TYPE_TEXEL_DMXX24_100: if (dev->current_cdb[0] == 0xc2) dev->callback += 40.0; - bytes_per_second = 176.0 * 1024.0; + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; } @@ -1049,7 +1053,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) 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; + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; } @@ -1388,7 +1393,7 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch, int ven type = (dev->current_cdb[1] >> 2) & 7; flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); } else { - type = 8; + type = 8; /* Internal type code indicating both Mode 1 and Mode 2 Form 1 are allowed. */ flags = 0x10; } @@ -1751,7 +1756,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) int used_len; int alloc_length; int msf; - int pos = 0; + int pos = dev->drv->seek_pos; int size_idx; int idx = 0; uint32_t feature; @@ -1859,7 +1864,9 @@ begin: cdrom_audio_pause_resume(dev->drv, 0x00); dev->drv->audio_op = 0x01; scsi_cdrom_command_complete(dev); - break; + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + scsi_cdrom_buf_free(dev); + return; } fallthrough; case GPCMD_SET_SPEED: @@ -2787,6 +2794,15 @@ begin: return; } + if (max_len <= 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; + } + if (!(cdb[2] & 0x40)) alloc_length = 4; else @@ -3182,7 +3198,10 @@ begin: size_idx = 4; memset(dev->buffer, 0, 8); - dev->buffer[0] = 5; /*CD-ROM*/ + if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) + dev->buffer[0] = 0x7f; /*No physical device on this LUN*/ + else + dev->buffer[0] = 5; /*CD-ROM*/ dev->buffer[1] = 0x80; /*Removable*/ if (dev->drv->bus_type == CDROM_BUS_SCSI) { @@ -3608,6 +3627,14 @@ atapi_out: dev->sony_vendor = 1; len = (cdb[7] << 8) | cdb[8]; + if (!len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: PlayBack Control Sony 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, 65536); scsi_cdrom_set_buf_len(dev, BufLen, &len); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 837800eb0..f29e85431 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -446,7 +446,7 @@ scsi_disk_command_common(scsi_disk_t *dev) 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); + period = hdd_timing_write(dev->drv, dev->drv->seek_pos, dev->drv->seek_len); scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", dev->id, (uint64_t) period); dev->callback += period; @@ -482,7 +482,7 @@ scsi_disk_command_common(scsi_disk_t *dev) case 0x28: case 0xa8: /* Seek time is in us. */ - period = hdd_timing_read(dev->drv, dev->sector_pos, dev->packet_len >> 9); + period = hdd_timing_read(dev->drv, dev->drv->seek_pos, dev->drv->seek_len); scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", dev->id, (uint64_t) period); dev->callback += period; @@ -928,6 +928,10 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_REZERO_UNIT: dev->sector_pos = dev->sector_len = 0; + + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = dev->sector_len; + scsi_disk_seek(dev, 0); scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); break; @@ -1031,6 +1035,9 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->packet_len = max_len * alloc_length; scsi_disk_buf_alloc(dev, dev->packet_len); + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = dev->sector_len; + ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); if (ret <= 0) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); @@ -1118,6 +1125,9 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; } + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = dev->sector_len; + max_len = dev->sector_len; /* If we're writing all blocks in one go for DMA, why not also for @@ -1318,7 +1328,10 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) size_idx = 4; memset(dev->temp_buffer, 0, 8); - dev->temp_buffer[0] = 0; /*SCSI HD*/ + if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff))) + dev->temp_buffer[0] = 0x7f; /*No physical device on this LUN*/ + else + 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; @@ -1371,6 +1384,10 @@ atapi_out: default: break; } + + dev->drv->seek_pos = dev->sector_pos; + dev->drv->seek_len = 0; + scsi_disk_seek(dev, pos); scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 285c65c80..527ff373f 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -6,8 +6,8 @@ * * 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 chip made by NCR + * and used in various controllers. * * * @@ -16,8 +16,8 @@ * Fred N. van Kempen, * * Copyright 2017-2019 Sarah Walker. - * Copyright 2017-2019 TheCollector1995. * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2024 TheCollector1995. */ #include #include @@ -42,156 +42,13 @@ #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 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 MODE_ARBITRATE 0x01 -#define MODE_DMA 0x02 -#define MODE_MONITOR_BUSY 0x04 -#define MODE_ENA_EOP_INT 0x08 - -#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 STATUS_53C80_ACCESSIBLE 0x80 - -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; - - 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 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 ncr5380_t { - ncr_t ncr; - t128_t t128; - - const char *name; - - uint8_t buffer[128]; - uint8_t int_ram[0x40]; - uint8_t ext_ram[0x600]; - - 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; - - rom_t bios_rom; - mem_mapping_t mapping; - - int block_count_loaded; - - int buffer_pos; - int buffer_host_pos; - - int dma_enabled; - - pc_timer_t timer; - double period; - - 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 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 }; +int ncr5380_cmd_len[8] = { 6, 10, 10, 6, 16, 12, 10, 6 }; #ifdef ENABLE_NCR5380_LOG int ncr5380_do_log = ENABLE_NCR5380_LOG; static void -ncr_log(const char *fmt, ...) +ncr5380_log(const char *fmt, ...) { va_list ap; @@ -202,34 +59,35 @@ ncr_log(const char *fmt, ...) } } #else -# define ncr_log(fmt, ...) +# define ncr5380_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 -ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev); - -static void -ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev); - -static void -ncr_callback(void *priv); - -static void -ncr_irq(ncr5380_t *ncr_dev, ncr_t *ncr, int set_irq) +void +ncr5380_irq(ncr_t *ncr, int set_irq) { if (set_irq) { + ncr->irq_state = 1; ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); + if (ncr->irq != -1) + picint(1 << ncr->irq); } else { + ncr->irq_state = 0; ncr->isr &= ~STATUS_INT; - picintc(1 << ncr_dev->irq); + if (ncr->irq != 1) + picintc(1 << ncr->irq); } } +void +ncr5380_set_irq(ncr_t *ncr, int irq) +{ + ncr->irq = irq; +} + static int -get_dev_id(uint8_t data) +ncr5380_get_dev_id(uint8_t data) { for (uint8_t c = 0; c < SCSI_ID_MAX; c++) { if (data & (1 << c)) @@ -240,7 +98,7 @@ get_dev_id(uint8_t data) } static int -getmsglen(uint8_t *msgp, int len) +ncr5380_getmsglen(uint8_t *msgp, int len) { uint8_t msg = msgp[0]; if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) || msg >= 0x80) @@ -253,42 +111,32 @@ getmsglen(uint8_t *msgp, int len) } static void -ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) +ncr5380_reset(ncr_t *ncr) { - memset(ncr, 0x00, sizeof(ncr_t)); - ncr_log("NCR reset\n"); + ncr->command_pos = 0; + ncr->data_pos = 0; + ncr->state = STATE_IDLE; + ncr->clear_req = 0; + ncr->cur_bus = 0; + ncr->tx_data = 0; + ncr->output_data = 0; + ncr->data_wait = 0; + ncr->mode = 0; + ncr->tcr = 0; + ncr->icr = 0; + ncr->dma_mode = DMA_IDLE; + ncr5380_log("NCR Reset\n"); - timer_stop(&ncr_dev->timer); + ncr->timer(ncr->priv, 0.0); for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[ncr_dev->bus][i]); + scsi_device_reset(&scsi_devices[ncr->bus][i]); - ncr_irq(ncr_dev, ncr, 0); + ncr5380_irq(ncr, 0); } -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; - } - - 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 +ncr5380_get_bus_host(ncr_t *ncr) { uint32_t bus_host = 0; @@ -325,10 +173,9 @@ get_bus_host(ncr_t *ncr) return (bus_host | BUS_SETDATA(ncr->output_data)); } -static void -ncr_bus_read(ncr5380_t *ncr_dev) +void +ncr5380_bus_read(ncr_t *ncr) { - ncr_t *ncr = &ncr_dev->ncr; const scsi_device_t *dev; int phase; @@ -336,7 +183,7 @@ ncr_bus_read(ncr5380_t *ncr_dev) if (ncr->clear_req) { ncr->clear_req--; if (!ncr->clear_req) { - ncr_log("Prelude to command data\n"); + ncr5380_log("Prelude to command data\n"); SET_BUS_STATE(ncr, ncr->new_phase); ncr->cur_bus |= BUS_REQ; } @@ -345,7 +192,7 @@ ncr_bus_read(ncr5380_t *ncr_dev) if (ncr->wait_data) { ncr->wait_data--; if (!ncr->wait_data) { - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + dev = &scsi_devices[ncr->bus][ncr->target_id]; SET_BUS_STATE(ncr, ncr->new_phase); phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); @@ -381,12 +228,10 @@ ncr_bus_read(ncr5380_t *ncr_dev) } } -static void -ncr_bus_update(void *priv, int bus) +void +ncr5380_bus_update(ncr_t *ncr, 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]; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; double p; uint8_t sel_data; int msglen; @@ -395,25 +240,25 @@ ncr_bus_update(void *priv, int bus) if (bus & BUS_ARB) ncr->state = STATE_IDLE; - ncr_log("State = %i\n", ncr->state); + ncr5380_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"); + ncr5380_log("Selection phase\n"); sel_data = BUS_GETDATA(bus); - ncr->target_id = get_dev_id(sel_data); + ncr->target_id = ncr5380_get_dev_id(sel_data); - ncr_log("Select - target ID = %i\n", ncr->target_id); + ncr5380_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])) { + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->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); + ncr5380_log("Device not found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); ncr->cur_bus = 0; } } @@ -421,11 +266,11 @@ ncr_bus_update(void *priv, int bus) 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); + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) { + ncr5380_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); + ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); ncr->command_pos = 0; SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); } else { @@ -433,7 +278,7 @@ ncr_bus_update(void *priv, int bus) ncr->cur_bus = 0; } } else { - ncr_log("Set to SCSI Message Out\n"); + ncr5380_log("Set to SCSI Message Out\n"); ncr->new_phase = SCSI_PHASE_MESSAGE_OUT; ncr->wait_data = 4; ncr->msgout_pos = 0; @@ -449,9 +294,9 @@ ncr_bus_update(void *priv, int bus) 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)); + ncr5380_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->command_pos == ncr5380_cmd_len[(ncr->command[0] >> 5) & 7]) { if (ncr->is_msgout) { ncr->is_msgout = 0; #if 0 @@ -462,28 +307,23 @@ ncr_bus_update(void *priv, int bus) /*Reset data position to default*/ ncr->data_pos = 0; - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + dev = &scsi_devices[ncr->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); + ncr5380_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); + ncr5380_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->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)) { + 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->period = (p > 0.0) ? p : (((double) dev->buffer_length) * 0.2); + ncr5380_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", ncr->target_id, ncr->command[0], scsi_device_get_callback(dev), ncr->period, dev->buffer_length, ncr->dma_mode); } } ncr->new_phase = dev->phase; @@ -491,7 +331,7 @@ ncr_bus_update(void *priv, int bus) } break; case STATE_DATAIN: - dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + dev = &scsi_devices[ncr->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; @@ -502,21 +342,22 @@ ncr_bus_update(void *priv, int bus) } 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 + ncr5380_log("DMA mode idle in\n"); + ncr->timer(ncr->priv, ncr->period); + } else { + ncr5380_log("DMA mode IN.\n"); 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]; + dev = &scsi_devices[ncr->bus][ncr->target_id]; if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); @@ -530,20 +371,20 @@ ncr_bus_update(void *priv, int bus) /*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 { + ncr5380_log("DMA mode idle out\n"); + ncr->timer(ncr->priv, ncr->period); + } else ncr->clear_req = 3; - } + ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + ncr5380_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); + scsi_device_identify(&scsi_devices[ncr->bus][ncr->target_id], SCSI_LUN_USE_CDB); ncr->cur_bus &= ~BUS_REQ; ncr->new_phase = SCSI_PHASE_MESSAGE_IN; ncr->wait_data = 4; @@ -558,10 +399,10 @@ ncr_bus_update(void *priv, int bus) } break; case STATE_MESSAGEOUT: - ncr_log("Ack on MSGOUT = %02x\n", (bus & BUS_ACK)); + ncr5380_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); + msglen = ncr5380_getmsglen(ncr->msgout, ncr->msgout_pos); if (ncr->msgout_pos >= msglen) { if ((ncr->msgout[0] & (0x80 | 0x20)) == 0x80) ncr->msglun = ncr->msgout[0] & 7; @@ -571,12 +412,12 @@ ncr_bus_update(void *priv, int bus) } 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); + if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) { + ncr5380_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->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); + ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); ncr->command_pos = 0; SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); } @@ -589,33 +430,30 @@ ncr_bus_update(void *priv, int bus) ncr->bus_in = bus; } -static void -ncr_write(uint16_t port, uint8_t val, void *priv) +void +ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr) { - 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); + ncr5380_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); + ncr5380_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"); + ncr5380_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); + ncr5380_log("Resetting the 5380\n"); + ncr5380_reset(ncr); } ncr->icr = val; break; case 2: /* Mode register */ - ncr_log("Write: Mode register, val=%02x.\n", val); + ncr5380_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; @@ -623,179 +461,108 @@ ncr_write(uint16_t port, uint8_t val, void *priv) 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); - } - - /*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); - } - - /*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; - } - } + ncr->dma_mode_ext(ncr, ncr->priv); break; case 3: /* Target Command Register */ - ncr_log("Write: Target Command register\n"); + ncr5380_log("Write: Target Command register\n"); ncr->tcr = val; break; case 4: /* Select Enable Register */ - ncr_log("Write: Select Enable register\n"); + ncr5380_log("Write: Select Enable register\n"); break; case 5: /* start DMA Send */ - ncr_log("Write: start DMA send register\n"); + ncr5380_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_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; - - 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); - } - } + if (ncr->dma_send_ext) + ncr->dma_send_ext(ncr, ncr->priv); break; case 7: /* start DMA Initiator Receive */ - ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); + ncr5380_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); - } - } + if (ncr->dma_initiator_receive_ext) + ncr->dma_initiator_receive_ext(ncr, ncr->priv); break; default: - ncr_log("NCR5380: bad write %04x %02x\n", port, val); + ncr5380_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); - } + bus_host = ncr5380_get_bus_host(ncr); + ncr5380_bus_update(ncr, bus_host); } -static uint8_t -ncr_read(uint16_t port, void *priv) +uint8_t +ncr5380_read(uint16_t port, ncr_t *ncr) { - ncr5380_t *ncr_dev = (ncr5380_t *) priv; - ncr_t *ncr = &ncr_dev->ncr; - uint8_t ret = 0xff; + 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"); + ncr5380_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); + ncr5380_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)); + ncr5380_bus_read(ncr); + ncr5380_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); + ncr5380_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 = %02x.\n", ncr->mode); + ncr5380_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); + ncr5380_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"); + ncr5380_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); + ncr5380_bus_read(ncr); + ncr5380_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; + // if ((ret & SCSI_PHASE_MESSAGE_IN) == SCSI_PHASE_MESSAGE_IN) + // ret &= ~BUS_REQ; break; case 5: /* Bus and Status register */ - ncr_log("Read: Bus and Status register\n"); + ncr5380_log("Read: Bus and Status register\n"); ret = 0; - bus = get_bus_host(ncr); - ncr_log("Get host from Interrupt\n"); + bus = ncr5380_get_bus_host(ncr); + ncr5380_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"); + ncr5380_log("Phase match\n"); ret |= STATUS_PHASE_MATCH; } - ncr_bus_read(ncr_dev); + ncr5380_bus_read(ncr); bus = ncr->cur_bus; if ((bus & BUS_ACK) || (ncr->icr & ICR_ACK)) @@ -804,7 +571,7 @@ ncr_read(uint16_t port, void *priv) ret |= 0x02; if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { - ncr_log("Entering DMA mode\n"); + ncr5380_log("Entering DMA mode\n"); ret |= STATUS_DRQ; bus_state = 0; @@ -816,12 +583,12 @@ ncr_read(uint16_t port, void *priv) 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"); + ncr5380_irq(ncr, 1); + ncr5380_log("IRQ issued\n"); } } if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - ncr_log("Busy error\n"); + ncr5380_log("Busy error\n"); ret |= STATUS_BUSY_ERROR; } ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); @@ -833,1171 +600,16 @@ ncr_read(uint16_t port, void *priv) case 7: /* reset Parity/Interrupt */ ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20); - ncr_irq(ncr_dev, ncr, 0); - ncr_log("Reset Interrupt\n"); + ncr5380_irq(ncr, 0); + ncr5380_log("Reset Interrupt\n"); break; default: - ncr_log("NCR5380: bad read %04x\n", port); + ncr5380_log("NCR5380: bad read %04x\n", port); break; } - ncr_log("NCR5380 read(%04x)=%02x\n", port & 7, ret); + ncr5380_log("NCR5380 read(%04x)=%02x\n", port & 7, ret); return ret; } - -/* Memory-mapped I/O READ handler. */ -static uint8_t -memio_read(uint32_t addr, void *priv) -{ - 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]; - else if (addr < 0x3800) - ret = 0xff; - else if (addr >= 0x3a00) - 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]); -#endif - ret = ncr_dev->int_ram[addr & 0x3f]; - break; - - case 0x3880: -#if ENABLE_NCR5380_LOG - 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++]; - - 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 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 0x3981: /* block counter register*/ - ret = ncr_dev->block_count; - 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); -#endif - - return ret; -} - -/* Memory-mapped I/O WRITE handler. */ -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; - const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; - - addr &= 0x3fff; - - if (addr >= 0x3a00) - 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; - - ncr_log("Write host pos = %i, val = %02x\n", 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; - - 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; - - 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 -t130b_read(uint32_t addr, void *priv) -{ - 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]; - else if (addr >= 0x1800 && addr < 0x1880) - ret = ncr_dev->ext_ram[addr & 0x7f]; - - ncr_log("MEM: Reading %02X from %08X\n", ret, addr); - return ret; -} - -/* Memory-mapped I/O WRITE handler for the Trantor T130B. */ -static void -t130b_write(uint32_t addr, uint8_t val, void *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; -} - -static uint8_t -t130b_in(uint16_t port, void *priv) -{ - 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 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; -} - -static void -t130b_out(uint16_t port, uint8_t val, void *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 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; - 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 (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]; - 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->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; - } - } - 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; - 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 (uint8_t c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; - } - - /* Data ready. */ - ncr_bus_read(ncr_dev); - temp = BUS_GETDATA(ncr->cur_bus); - - bus = get_bus_host(ncr); - - 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; - } - } - 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]; - - 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; - } - } - - 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_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; - } - - 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); - } -} - -static uint8_t -t128_read(uint32_t addr, void *priv) -{ - 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 (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; -} - -static void -t128_write(uint32_t addr, uint8_t val, void *priv) -{ - 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)) - 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); - - 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) -{ - const char *fn = NULL; - char temp[128]; - ncr5380_t *ncr_dev; - - ncr_dev = malloc(sizeof(ncr5380_t)); - memset(ncr_dev, 0x00, sizeof(ncr5380_t)); - ncr_dev->name = info->name; - ncr_dev->type = info->local; - - 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); - - 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/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; - } - - switch (ncr_dev->bios_ver) { - case 0: - fn = RT1000B_810R_ROM; - break; - case 1: - fn = RT1000B_820R_ROM; - break; - } - - rom_init(&ncr_dev->bios_rom, fn, - 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; - - 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"); - - if (ncr_dev->rom_addr > 0x00000) { - rom_init(&ncr_dev->bios_rom, T130B_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); - } - - 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); - if (ncr_dev->irq != 0) - 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->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; - - 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 -ncr_close(void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *) priv; - - if (ncr_dev) { - /* Tell the timer to terminate. */ - timer_stop(&ncr_dev->timer); - - free(ncr_dev); - ncr_dev = NULL; - } -} - -static int -lcs6821n_available(void) -{ - return (rom_present(LCS6821N_ROM)); -} - -static int -rt1000b_available(void) -{ - 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)); -} - -static int -t128_available(void) -{ - return (rom_present(T128_ROM)); -} - -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 = "" } - }, - }, - { - .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 = "", .description = "", .type = CONFIG_END } -}; - -static const device_config_t rancho_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 = "" } - }, - }, - { - .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 = "" } - }, - }, - { .name = "", .description = "", .type = CONFIG_END } -}; - -static const device_config_t t130b_config[] = { - { - .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 = "" } - }, - }, - { - .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 = "" } - }, - }, - { - .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 = "", .description = "", .type = CONFIG_END } -}; - -static const device_config_t t128_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 = "" } - }, - }, - { - .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 = "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_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_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 = { - .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 = { - .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_ncr53c400.c b/src/scsi/scsi_ncr53c400.c new file mode 100644 index 000000000..ca4d28ffb --- /dev/null +++ b/src/scsi/scsi_ncr53c400.c @@ -0,0 +1,995 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 NCR 53c400 series of SCSI Host Adapters + * made by NCR. These controllers were designed for the ISA and MCA bus. + * + * + * + * Authors: Sarah Walker, + * TheCollector1995, + * Fred N. van Kempen, + * + * Copyright 2017-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2024 TheCollector1995. + */ +#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/dma.h> +#include <86box/pic.h> +#include <86box/mca.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/nvr.h> +#include <86box/plat.h> +#include <86box/scsi.h> +#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 COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.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 CTRL_DATA_DIR 0x40 +#define STATUS_BUFFER_NOT_READY 0x04 +#define STATUS_5380_ACCESSIBLE 0x80 + +enum { + ROM_LCS6821N = 0, + ROM_LS2000, + ROM_RT1000B, + ROM_T130B +}; + +typedef struct ncr53c400_t { + rom_t bios_rom; + mem_mapping_t mapping; + ncr_t ncr; + uint8_t buffer[128]; + uint8_t int_ram[0x40]; + uint8_t ext_ram[0x600]; + + uint32_t rom_addr; + uint16_t base; + + int8_t type; + uint8_t block_count; + uint8_t status_ctrl; + + int block_count_loaded; + + int buffer_pos; + int buffer_host_pos; + + int busy; + uint8_t pos_regs[8]; + + pc_timer_t timer; +} ncr53c400_t; + +#ifdef ENABLE_NCR53C400_LOG +int ncr53c400_do_log = ENABLE_NCR53C400_LOG; + +static void +ncr53c400_log(const char *fmt, ...) +{ + va_list ap; + + if (ncr53c400_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ncr53c400_log(fmt, ...) +#endif + +static void +ncr53c400_timer_on_auto(void *ext_priv, double period) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv; + + ncr53c400_log("53c400: PERIOD=%lf, timer=%x.\n", period, timer_is_enabled(&ncr400->timer)); + if (period <= 0.0) + timer_stop(&ncr400->timer); + else if ((period > 0.0) && !timer_is_enabled(&ncr400->timer)) + timer_on_auto(&ncr400->timer, period); +} + +/* Memory-mapped I/O WRITE handler. */ +static void +ncr53c400_write(uint32_t addr, uint8_t val, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + ncr_t *ncr = &ncr400->ncr; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + + addr &= 0x3fff; + + if (addr >= 0x3a00) + ncr400->ext_ram[addr - 0x3a00] = val; + else { + switch (addr & 0x3f80) { + case 0x3800: + ncr400->int_ram[addr & 0x3f] = val; + break; + + case 0x3880: + ncr5380_write(addr, val, ncr); + break; + + case 0x3900: + if (!(ncr400->status_ctrl & CTRL_DATA_DIR) && (ncr400->buffer_host_pos < MIN(128, dev->buffer_length))) { + ncr400->buffer[ncr400->buffer_host_pos++] = val; + + ncr53c400_log("Write host pos=%i, val=%02x.\n", ncr400->buffer_host_pos, val); + + if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { + ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + ncr400->busy = 1; + if (!(ncr->mode & MODE_MONITOR_BUSY)) + timer_on_auto(&ncr400->timer, ncr->period / 280.0); + } + } + break; + + case 0x3980: + switch (addr) { + case 0x3980: /* Control */ + ncr53c400_log("NCR 53c400 control=%02x, mode=%02x.\n", val, ncr->mode); + if ((val & CTRL_DATA_DIR) && !(ncr400->status_ctrl & CTRL_DATA_DIR)) { + ncr400->buffer_host_pos = MIN(128, dev->buffer_length); + ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + } else if (!(val & CTRL_DATA_DIR) && (ncr400->status_ctrl & CTRL_DATA_DIR)) { + ncr400->buffer_host_pos = 0; + ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + ncr400->status_ctrl = (ncr400->status_ctrl & 0x87) | (val & 0x78); + break; + + case 0x3981: /* block counter register */ + ncr53c400_log("Write block counter register: val=%d, dma mode=%x, period=%lf.\n", val, ncr->dma_mode, ncr->period); + ncr400->block_count = val; + ncr400->block_count_loaded = 1; + + if (ncr400->status_ctrl & CTRL_DATA_DIR) { + ncr400->buffer_host_pos = MIN(128, dev->buffer_length); + ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + } else { + ncr400->buffer_host_pos = 0; + ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); + if (ncr->mode & MODE_MONITOR_BUSY) + timer_on_auto(&ncr400->timer, ncr->period); + else + timer_on_auto(&ncr400->timer, 40.0); + ncr53c400_log("DMA timer on, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); + } + break; + + default: + break; + } + break; + + default: + break; + } + } +} + +/* Memory-mapped I/O READ handler. */ +static uint8_t +ncr53c400_read(uint32_t addr, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + ncr_t *ncr = &ncr400->ncr; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + uint8_t ret = 0xff; + + addr &= 0x3fff; + + if (addr < 0x2000) + ret = ncr400->bios_rom.rom[addr & 0x1fff]; + else if (addr < 0x3800) + ret = 0xff; + else if (addr >= 0x3a00) + ret = ncr400->ext_ram[addr - 0x3a00]; + else { + switch (addr & 0x3f80) { + case 0x3800: + ncr53c400_log("Read intRAM %02x %02x.\n", addr & 0x3f, ncr400->int_ram[addr & 0x3f]); + ret = ncr400->int_ram[addr & 0x3f]; + break; + + case 0x3880: + ncr53c400_log("Read 5380 %04x.\n", addr); + ret = ncr5380_read(addr, ncr); + break; + + case 0x3900: + if (ncr400->buffer_host_pos >= MIN(128, dev->buffer_length) || (!(ncr400->status_ctrl & CTRL_DATA_DIR))) { + ret = 0xff; + ncr53c400_log("No Read.\n"); + } else { + ret = ncr400->buffer[ncr400->buffer_host_pos++]; + ncr53c400_log("Read host pos=%i, ret=%02x.\n", ncr400->buffer_host_pos, ret); + + if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { + ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl); + if (!(ncr->mode & MODE_MONITOR_BUSY)) + timer_on_auto(&ncr400->timer, ncr->period / 280.0); + } + } + break; + + case 0x3980: + switch (addr) { + case 0x3980: /* status */ + ret = ncr400->status_ctrl; + ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY); + if (!ncr400->busy) + ret |= STATUS_5380_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.*/ + } + } + ncr53c400_log("NCR 53c400 status=%02x.\n", ret); + break; + + case 0x3981: /* block counter register*/ + ret = ncr400->block_count; + ncr53c400_log("NCR 53c400 block count read=%02x.\n", ret); + break; + + case 0x3982: /* switch register read */ + ret = 0xff; + ncr53c400_log("Switches read=%02x.\n", ret); + break; + + default: + break; + } + break; + + default: + break; + } + } + + if (addr >= 0x3880) + ncr53c400_log("memio_read(%08x)=%02x\n", addr, ret); + + return ret; +} + + +/* Memory-mapped I/O WRITE handler for the Trantor T130B. */ +static void +t130b_write(uint32_t addr, uint8_t val, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + + addr &= 0x3fff; + ncr53c400_log("MEM: Writing %02X to %08X\n", val, addr); + if (addr >= 0x1800 && addr < 0x1880) + ncr400->ext_ram[addr & 0x7f] = val; +} + +/* Memory-mapped I/O READ handler for the Trantor T130B. */ +static uint8_t +t130b_read(uint32_t addr, void *priv) +{ + const ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + uint8_t ret = 0xff; + + addr &= 0x3fff; + if (addr < 0x1800) + ret = ncr400->bios_rom.rom[addr & 0x1fff]; + else if (addr >= 0x1800 && addr < 0x1880) + ret = ncr400->ext_ram[addr & 0x7f]; + + ncr53c400_log("MEM: Reading %02X from %08X\n", ret, addr); + return ret; +} + +static void +t130b_out(uint16_t port, uint8_t val, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + ncr_t *ncr = &ncr400->ncr; + + ncr53c400_log("I/O: Writing %02X to %04X\n", val, port); + + switch (port & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + ncr53c400_write((port & 7) | 0x3980, val, ncr400); + break; + + case 0x04: + case 0x05: + ncr53c400_write(0x3900, val, ncr400); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ncr5380_write(port, val, ncr); + break; + + default: + break; + } +} + +static uint8_t +t130b_in(uint16_t port, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + ncr_t *ncr = &ncr400->ncr; + uint8_t ret = 0xff; + + switch (port & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + ret = ncr53c400_read((port & 7) | 0x3980, ncr400); + break; + + case 0x04: + case 0x05: + ret = ncr53c400_read(0x3900, ncr400); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ret = ncr5380_read(port, ncr); + break; + + default: + break; + } + + ncr53c400_log("I/O: Reading %02X from %04X\n", ret, port); + return ret; +} + +static void +ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv)) +{ + ncr_t *ncr = (ncr_t *) priv; + + /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ + if (!(ncr->mode & MODE_DMA)) { + ncr53c400_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } +} + +static void +ncr53c400_callback(void *priv) +{ + ncr53c400_t *ncr400 = (void *) priv; + ncr_t *ncr = &ncr400->ncr; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + int bus; + uint8_t c; + uint8_t temp; + + if (ncr->dma_mode != DMA_IDLE) + timer_on_auto(&ncr400->timer, 1.0); + + if (ncr->data_wait & 1) { + ncr->clear_req = 3; + ncr->data_wait &= ~1; + } + + if (ncr->dma_mode == DMA_IDLE) + return; + + switch (ncr->dma_mode) { + case DMA_SEND: + if (ncr400->status_ctrl & CTRL_DATA_DIR) { + ncr53c400_log("DMA_SEND with DMA direction set wrong\n"); + break; + } + + if (!(ncr400->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr53c400_log("Write buffer status ready\n"); + break; + } + + if (!ncr400->block_count_loaded) { + ncr53c400_log("Write block count not loaded.\n"); + break; + } + + while (1) { + for (c = 0; c < 10; c++) { + ncr5380_bus_read(ncr); + if (ncr->cur_bus & BUS_REQ) + break; + } + /* Data ready. */ + temp = ncr400->buffer[ncr400->buffer_pos]; + + bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr5380_bus_update(ncr, bus | BUS_ACK); + ncr5380_bus_update(ncr, bus & ~BUS_ACK); + + ncr400->buffer_pos++; + ncr53c400_log("NCR 53c400 Buffer pos for writing = %d\n", ncr400->buffer_pos); + + if (ncr400->buffer_pos == MIN(128, dev->buffer_length)) { + ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr400->buffer_pos = 0; + ncr400->buffer_host_pos = 0; + ncr400->busy = 0; + ncr400->block_count = (ncr400->block_count - 1) & 0xff; + ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count); + if (!ncr400->block_count) { + ncr400->block_count_loaded = 0; + ncr53c400_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR 53c400 write irq\n"); + ncr5380_irq(ncr, 1); + } + } + break; + } + } + break; + + case DMA_INITIATOR_RECEIVE: + if (!(ncr400->status_ctrl & CTRL_DATA_DIR)) { + ncr53c400_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + break; + } + + if (!(ncr400->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr53c400_log("Read buffer status ready\n"); + break; + } + + if (!ncr400->block_count_loaded) + break; + + while (1) { + for (c = 0; c < 10; c++) { + ncr5380_bus_read(ncr); + if (ncr->cur_bus & BUS_REQ) + break; + } + /* Data ready. */ + ncr5380_bus_read(ncr); + temp = BUS_GETDATA(ncr->cur_bus); + + bus = ncr5380_get_bus_host(ncr); + + ncr5380_bus_update(ncr, bus | BUS_ACK); + ncr5380_bus_update(ncr, bus & ~BUS_ACK); + + ncr400->buffer[ncr400->buffer_pos++] = temp; + ncr53c400_log("NCR 53c400 Buffer pos for reading = %d\n", ncr400->buffer_pos); + + if (ncr400->buffer_pos == MIN(128, dev->buffer_length)) { + ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr400->buffer_pos = 0; + ncr400->buffer_host_pos = 0; + ncr400->block_count = (ncr400->block_count - 1) & 0xff; + ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count); + if (!ncr400->block_count) { + ncr400->block_count_loaded = 0; + ncr53c400_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } + break; + } + } + break; + + default: + break; + } + + ncr5380_bus_read(ncr); + + if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + ncr53c400_log("Updating DMA\n"); + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; + ncr400->block_count_loaded = 0; + } +} + +static uint8_t +rt1000b_mc_read(int port, void *priv) +{ + const ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + + return (ncr400->pos_regs[port & 7]); +} + +static void +rt1000b_mc_write(int port, uint8_t val, void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + mem_mapping_disable(&ncr400->bios_rom.mapping); + mem_mapping_disable(&ncr400->mapping); + + /* Save the MCA register value. */ + ncr400->pos_regs[port & 7] = val; + + if (ncr400->pos_regs[2] & 1) { + switch (ncr400->pos_regs[2] & 0xe0) { + case 0: + ncr400->rom_addr = 0xd4000; + break; + case 0x20: + ncr400->rom_addr = 0xd0000; + break; + case 0x40: + ncr400->rom_addr = 0xcc000; + break; + case 0x60: + ncr400->rom_addr = 0xc8000; + break; + case 0xc0: + ncr400->rom_addr = 0xdc000; + break; + case 0xe0: + ncr400->rom_addr = 0xd8000; + break; + + default: + break; + } + + mem_mapping_set_addr(&ncr400->bios_rom.mapping, ncr400->rom_addr, 0x4000); + mem_mapping_set_addr(&ncr400->mapping, ncr400->rom_addr, 0x4000); + } +} + +static uint8_t +rt1000b_mc_feedb(void *priv) +{ + const ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + + return ncr400->pos_regs[2] & 1; +} + +static void * +ncr53c400_init(const device_t *info) +{ + const char *bios_ver = NULL; + const char *fn; + ncr53c400_t *ncr400; + ncr_t *ncr; + + ncr400 = malloc(sizeof(ncr53c400_t)); + memset(ncr400, 0x00, sizeof(ncr53c400_t)); + ncr = &ncr400->ncr; + + ncr400->type = info->local; + + ncr->bus = scsi_get_bus(); + + switch (ncr400->type) { + case ROM_LCS6821N: /* Longshine LCS6821N */ + ncr400->rom_addr = device_get_config_hex20("bios_addr"); + ncr->irq = device_get_config_int("irq"); + + rom_init(&ncr400->bios_rom, LCS6821N_ROM, + ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&ncr400->mapping, ncr400->rom_addr, 0x4000, + ncr53c400_read, NULL, NULL, + ncr53c400_write, NULL, NULL, + ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400); + break; + + + case ROM_LS2000: /* Corel LS2000 */ + ncr400->rom_addr = device_get_config_hex20("bios_addr"); + ncr->irq = device_get_config_int("irq"); + + rom_init(&ncr400->bios_rom, COREL_LS2000_ROM, + ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&ncr400->mapping, ncr400->rom_addr, 0x4000, + ncr53c400_read, NULL, NULL, + ncr53c400_write, NULL, NULL, + ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400); + break; + + case ROM_RT1000B: /* Rancho RT1000B/MC */ + ncr400->rom_addr = device_get_config_hex20("bios_addr"); + ncr->irq = device_get_config_int("irq"); + if (info->flags & DEVICE_MCA) { + rom_init(&ncr400->bios_rom, RT1000B_820R_ROM, + 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_add(&ncr400->mapping, 0xd8000, 0x4000, + ncr53c400_read, NULL, NULL, + ncr53c400_write, NULL, NULL, + ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400); + mem_mapping_disable(&ncr400->bios_rom.mapping); + ncr400->pos_regs[0] = 0x8d; + ncr400->pos_regs[1] = 0x70; + mca_add(rt1000b_mc_read, rt1000b_mc_write, rt1000b_mc_feedb, NULL, ncr400); + } else { + bios_ver = (char *) device_get_config_bios("bios_ver"); + fn = (char *) device_get_bios_file(info, bios_ver, 0); + rom_init(&ncr400->bios_rom, fn, + ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_add(&ncr400->mapping, ncr400->rom_addr, 0x4000, + ncr53c400_read, NULL, NULL, + ncr53c400_write, NULL, NULL, + ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400); + } + break; + + case ROM_T130B: /* Trantor T130B */ + ncr400->rom_addr = device_get_config_hex20("bios_addr"); + ncr400->base = device_get_config_hex16("base"); + ncr->irq = device_get_config_int("irq"); + + if (ncr400->rom_addr > 0x00000) { + rom_init(&ncr400->bios_rom, T130B_ROM, + ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&ncr400->mapping, ncr400->rom_addr, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400); + } + + io_sethandler(ncr400->base, 16, + t130b_in, NULL, NULL, t130b_out, NULL, NULL, ncr400); + break; + + default: + break; + } + + ncr->priv = ncr400; + ncr->dma_mode_ext = ncr53c400_dma_mode_ext; + ncr->dma_send_ext = NULL; + ncr->dma_initiator_receive_ext = NULL; + ncr->timer = ncr53c400_timer_on_auto; + ncr400->status_ctrl = STATUS_BUFFER_NOT_READY; + ncr400->buffer_host_pos = 128; + timer_add(&ncr400->timer, ncr53c400_callback, ncr400, 0); + + scsi_bus_set_speed(ncr->bus, 5000000.0); + + return ncr400; +} + +static void +ncr53c400_close(void *priv) +{ + ncr53c400_t *ncr400 = (ncr53c400_t *) priv; + + if (ncr400) { + /* Tell the timer to terminate. */ + timer_stop(&ncr400->timer); + + free(ncr400); + ncr400 = NULL; + } +} + +static int +lcs6821n_available(void) +{ + return (rom_present(LCS6821N_ROM)); +} + +static int +rt1000b_mc_available(void) +{ + return (rom_present(RT1000B_820R_ROM)); +} + +static int +t130b_available(void) +{ + return (rom_present(T130B_ROM)); +} + +static int +corel_ls2000_available(void) +{ + return (rom_present(COREL_LS2000_ROM)); +} + +// clang-format off +static const device_config_t ncr53c400_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 = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = -1 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t rt1000b_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 = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = -1 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "bios_ver", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "v8_10r", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 8.10R", .internal_name = "v8_10r", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_810R_ROM, "" } }, + { .name = "Version 8.20R", .internal_name = "v8_20r", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { RT1000B_820R_ROM, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t rt1000b_mc_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = -1 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t t130b_config[] = { + { + .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 = "" } + }, + }, + { + .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 = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "None", .value = -1 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { .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 = ROM_LCS6821N, + .init = ncr53c400_init, + .close = ncr53c400_close, + .reset = NULL, + { .available = lcs6821n_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr53c400_mmio_config +}; + +const device_t scsi_rt1000b_device = { + .name = "Rancho RT1000B", + .internal_name = "rt1000b", + .flags = DEVICE_ISA, + .local = ROM_RT1000B, + .init = ncr53c400_init, + .close = ncr53c400_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rt1000b_config +}; + +const device_t scsi_rt1000mc_device = { + .name = "Rancho RT1000B-MC", + .internal_name = "rt1000mc", + .flags = DEVICE_MCA, + .local = ROM_RT1000B, + .init = ncr53c400_init, + .close = ncr53c400_close, + .reset = NULL, + { .available = rt1000b_mc_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rt1000b_mc_config +}; + +const device_t scsi_t130b_device = { + .name = "Trantor T130B", + .internal_name = "t130b", + .flags = DEVICE_ISA, + .local = ROM_T130B, + .init = ncr53c400_init, + .close = ncr53c400_close, + .reset = NULL, + { .available = t130b_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = t130b_config +}; + +const device_t scsi_ls2000_device = { + .name = "Corel LS2000", + .internal_name = "ls2000", + .flags = DEVICE_ISA, + .local = ROM_LS2000, + .init = ncr53c400_init, + .close = ncr53c400_close, + .reset = NULL, + { .available = corel_ls2000_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ncr53c400_mmio_config +}; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 42925338d..f640c49a6 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -280,6 +280,7 @@ typedef struct ncr53c8xx_t { uint8_t swide; uint8_t gpcntl; uint8_t last_command; + uint8_t sodl; int command_complete; ncr53c8xx_request *current; @@ -1704,6 +1705,8 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) dev->stest3 = val; break; case 0x54: + dev->sodl = val; + break; case 0x55: break; CASE_SET_REG32(scratchb, 0x5c) @@ -1989,6 +1992,9 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { ncr53c8xx_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); return dev->msg[0]; + } else if (dev->stest2 & 0x80) { + ncr53c8xx_log("NCR 810: Read SBDL %02X\n", dev->sodl); + return dev->sodl; } ncr53c8xx_log("NCR 810: Read SBDL 00\n"); return 0; @@ -2561,28 +2567,39 @@ ncr53c8xx_init(const device_t *info) else 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; - } else if (dev->chip == CHIP_860) { - 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; - } else if (dev->chip == CHIP_825) { - 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; - } else if (dev->chip == CHIP_815) { - dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c815.nvr"; - dev->wide = 0; + scsi_bus_set_speed(dev->bus, 10000000.0); + + switch (dev->chip) { + case CHIP_810: + dev->nvr_path = "ncr53c810.nvr"; + dev->wide = 0; + break; + case CHIP_815: + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c815.nvr"; + dev->wide = 0; + break; + case CHIP_820: + dev->nvr_path = "ncr53c820.nvr"; + dev->wide = 1; + break; + case CHIP_825: + dev->chip_rev = 0x26; + dev->nvr_path = "ncr53c825a.nvr"; + dev->wide = 1; + break; + case CHIP_860: + scsi_bus_set_speed(dev->bus, 20000000.0); + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c860.nvr"; + dev->wide = 1; + break; + case CHIP_875: + scsi_bus_set_speed(dev->bus, 40000000.0); + dev->chip_rev = 0x04; + dev->nvr_path = "ncr53c875.nvr"; + dev->wide = 1; + break; } ncr53c8xx_pci_bar[0].addr_regs[0] = 1; @@ -2623,8 +2640,6 @@ ncr53c8xx_init(const device_t *info) timer_add(&dev->timer, ncr53c8xx_callback, dev, 0); - scsi_bus_set_speed(dev->bus, 10000000.0); - return dev; } diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 7bf06b1c0..674bbdabf 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -238,12 +238,10 @@ esp_irq(esp_t *dev, int level) { if (dev->mca) { if (level) { - picint(1 << dev->irq); - dev->dma_86c01.status |= 0x01; + picintlevel(1 << dev->irq, &dev->irq_state); esp_log("Raising IRQ...\n"); } else { - picintc(1 << dev->irq); - dev->dma_86c01.status &= ~0x01; + picintclevel(1 << dev->irq, &dev->irq_state); esp_log("Lowering IRQ...\n"); } } else { @@ -465,7 +463,7 @@ esp_do_command_phase(esp_t *dev) scsi_device_identify(sd, SCSI_LUN_USE_CDB); - dev->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); esp_raise_irq(dev); } @@ -518,7 +516,6 @@ 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; 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); @@ -529,7 +526,6 @@ esp_dma_enable(esp_t *dev, int level) } else { esp_log("ESP DMA Disabled\n"); dev->dma_enabled = 0; - dev->dma_86c01.status &= ~0x02; } } @@ -727,7 +723,7 @@ esp_do_dma(esp_t *dev, scsi_device_t *sd) 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]); + esp_log("ESP SCSI DMA read for 53C9x: 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; @@ -741,7 +737,7 @@ esp_do_dma(esp_t *dev, scsi_device_t *sd) 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); + esp_log("ESP SCSI DMA write for 53C9x: 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++; } @@ -967,7 +963,7 @@ esp_callback(void *priv) } } - 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, CMD = %02x\n", dev->dma_enabled, dev->do_cmd, (dev->rregs[ESP_CMD] & CMD_CMD)); } static uint32_t @@ -1060,14 +1056,13 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) 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); } + if (dev->mca) + esp_dma_enable(dev, dev->dma); + 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: @@ -1094,7 +1089,7 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) } break; case CMD_TI: - esp_log("val = %02X\n", val); + esp_log("Transfer Information val = %02X\n", val); break; case CMD_SEL: handle_s_without_atn(dev); @@ -1876,10 +1871,10 @@ dc390_init(UNUSED(const device_t *info)) } static uint16_t -ncr53c90_in(uint16_t port, void *priv) +ncr53c9x_in(uint16_t port, void *priv) { esp_t *dev = (esp_t *) priv; - uint16_t ret = 0; + uint16_t ret = 0xffff; port &= 0x1f; @@ -1892,6 +1887,16 @@ ncr53c90_in(uint16_t port, void *priv) break; case 0x0c: + if (dev->rregs[ESP_RSTAT] & STAT_INT) + dev->dma_86c01.status |= 0x01; + else + dev->dma_86c01.status &= ~0x01; + + if ((dev->dma_86c01.mode & 0x40) || dev->dma_enabled) + dev->dma_86c01.status |= 0x02; + else + dev->dma_86c01.status &= ~0x02; + ret = dev->dma_86c01.status; break; @@ -1900,56 +1905,55 @@ ncr53c90_in(uint16_t port, void *priv) } } - esp_log("[%04X:%08X]: NCR53c90 DMA read port = %02x, ret = %02x\n", CS, cpu_state.pc, port, ret); + esp_log("[%04X:%08X]: NCR53c9x DMA read port = %02x, ret = %02x.\n\n", CS, cpu_state.pc, port, ret); return ret; } static uint8_t -ncr53c90_inb(uint16_t port, void *priv) +ncr53c9x_inb(uint16_t port, void *priv) { - return ncr53c90_in(port, priv); + return ncr53c9x_in(port, priv); } static uint16_t -ncr53c90_inw(uint16_t port, void *priv) +ncr53c9x_inw(uint16_t port, void *priv) { - return (ncr53c90_in(port, priv) & 0xff) | (ncr53c90_in(port + 1, priv) << 8); + return (ncr53c9x_in(port, priv) & 0xff) | (ncr53c9x_in(port + 1, priv) << 8); } static void -ncr53c90_out(uint16_t port, uint16_t val, void *priv) +ncr53c9x_out(uint16_t port, uint16_t val, void *priv) { esp_t *dev = (esp_t *) priv; port &= 0x1f; - esp_log("[%04X:%08X]: NCR53c90 DMA write port = %02x, val = %02x\n", CS, cpu_state.pc, port, val); + esp_log("[%04X:%08X]: NCR53c9x 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 == 0x02) + dev->dma_86c01.mode = val; } } static void -ncr53c90_outb(uint16_t port, uint8_t val, void *priv) +ncr53c9x_outb(uint16_t port, uint8_t val, void *priv) { - ncr53c90_out(port, val, priv); + ncr53c9x_out(port, val, priv); } static void -ncr53c90_outw(uint16_t port, uint16_t val, void *priv) +ncr53c9x_outw(uint16_t port, uint16_t val, void *priv) { - ncr53c90_out(port, val & 0xff, priv); - ncr53c90_out(port + 1, val >> 8, priv); + ncr53c9x_out(port, val & 0xff, priv); + ncr53c9x_out(port + 1, val >> 8, priv); } static uint8_t -ncr53c90_mca_read(int port, void *priv) +ncr53c9x_mca_read(int port, void *priv) { const esp_t *dev = (esp_t *) priv; @@ -1957,7 +1961,7 @@ ncr53c90_mca_read(int port, void *priv) } static void -ncr53c90_mca_write(int port, uint8_t val, void *priv) +ncr53c9x_mca_write(int port, uint8_t val, void *priv) { esp_t *dev = (esp_t *) priv; static const uint16_t ncrmca_iobase[] = { @@ -1974,8 +1978,8 @@ ncr53c90_mca_write(int port, uint8_t val, void *priv) /* 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); + ncr53c9x_inb, ncr53c9x_inw, NULL, + ncr53c9x_outb, ncr53c9x_outw, NULL, dev); } /* Get the new assigned I/O base address. */ @@ -1999,20 +2003,20 @@ ncr53c90_mca_write(int port, uint8_t val, void *priv) 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); + ncr53c9x_inb, ncr53c9x_inw, NULL, + ncr53c9x_outb, ncr53c9x_outw, NULL, dev); esp_hard_reset(dev); } /* Say hello. */ - esp_log("NCR 53c90: I/O=%04x, IRQ=%d, DMA=%d, HOST ID %i\n", + esp_log("NCR 53c9x: 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) +ncr53c9x_mca_feedb(void *priv) { const esp_t *dev = (esp_t *) priv; @@ -2020,7 +2024,7 @@ ncr53c90_mca_feedb(void *priv) } static void * -ncr53c90_mca_init(UNUSED(const device_t *info)) +ncr53c9x_mca_init(UNUSED(const device_t *info)) { esp_t *dev; @@ -2034,9 +2038,9 @@ ncr53c90_mca_init(UNUSED(const device_t *info)) 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[0] = 0x4f; /* MCA board ID */ dev->pos_regs[1] = 0x7f; - mca_add(ncr53c90_mca_read, ncr53c90_mca_write, ncr53c90_mca_feedb, NULL, dev); + mca_add(ncr53c9x_mca_read, ncr53c9x_mca_write, ncr53c9x_mca_feedb, NULL, dev); esp_hard_reset(dev); @@ -2088,12 +2092,12 @@ const device_t dc390_pci_device = { .config = bios_enable_config }; -const device_t ncr53c90_mca_device = { - .name = "NCR 53c90 MCA", - .internal_name = "ncr53c90", +const device_t ncr53c90a_mca_device = { + .name = "NCR 53c90a MCA", + .internal_name = "ncr53c90a", .flags = DEVICE_MCA, .local = 0, - .init = ncr53c90_mca_init, + .init = ncr53c9x_mca_init, .close = esp_close, .reset = NULL, { .available = NULL }, diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c new file mode 100644 index 000000000..7e42a089d --- /dev/null +++ b/src/scsi/scsi_t128.c @@ -0,0 +1,626 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 Trantor 128/228 series of SCSI Host Adapters + * made by Trantor. These controllers were designed for the ISA and MCA bus. + * + * + * + * Authors: Sarah Walker, + * TheCollector1995, + * Fred N. van Kempen, + * + * Copyright 2017-2019 Sarah Walker. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2017-2024 TheCollector1995. + */ +#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/dma.h> +#include <86box/pic.h> +#include <86box/mca.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/nvr.h> +#include <86box/plat.h> +#include <86box/scsi.h> +#include <86box/scsi_device.h> +#include <86box/scsi_ncr5380.h> +#include <86box/scsi_t128.h> + +#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin" + +#ifdef ENABLE_T128_LOG +int t128_do_log = ENABLE_T128_LOG; + +static void +t128_log(const char *fmt, ...) +{ + va_list ap; + + if (t128_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define t128_log(fmt, ...) +#endif + +/* Memory-mapped I/O WRITE handler. */ +void +t128_write(uint32_t addr, uint8_t val, void *priv) +{ + t128_t *t128 = (t128_t *) priv; + ncr_t *ncr = &t128->ncr; + const scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + + addr &= 0x3fff; + if ((addr >= 0x1800) && (addr < 0x1880)) + t128->ext_ram[addr & 0x7f] = val; + else if ((addr >= 0x1c00) && (addr < 0x1c20)) { + if ((val & 0x02) && !(t128->ctrl & 0x02)) + t128->status |= 0x02; + + t128->ctrl = val; + t128_log("T128 ctrl write=%02x\n", val); + } else if ((addr >= 0x1d00) && (addr < 0x1e00)) + ncr5380_write((addr - 0x1d00) >> 5, val, ncr); + else if ((addr >= 0x1e00) && (addr < 0x2000)) { + if ((t128->host_pos < MIN(512, dev->buffer_length)) && + (ncr->dma_mode == DMA_SEND)) { + t128->buffer[t128->host_pos] = val; + t128->host_pos++; + + t128_log("T128 Write transfer, addr = %i, pos = %i, val = %02x\n", + addr & 0x1ff, t128->host_pos, val); + + if (t128->host_pos == MIN(512, dev->buffer_length)) { + t128->status &= ~0x04; + t128_log("Transfer busy write, status = %02x\n", t128->status); + timer_on_auto(&t128->timer, 0.02); + } + } + } +} + +/* Memory-mapped I/O READ handler. */ +uint8_t +t128_read(uint32_t addr, void *priv) +{ + t128_t *t128 = (t128_t *) priv; + ncr_t *ncr = &t128->ncr; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + uint8_t ret = 0xff; + + addr &= 0x3fff; + if (t128->bios_enabled && (addr >= 0) && (addr < 0x1800)) + ret = t128->bios_rom.rom[addr & 0x1fff]; + else if ((addr >= 0x1800) && (addr < 0x1880)) + ret = t128->ext_ram[addr & 0x7f]; + else if ((addr >= 0x1c00) && (addr < 0x1c20)) { + ret = t128->ctrl; + t128_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + } else if ((addr >= 0x1c20) && (addr < 0x1c40)) { + ret = t128->status; + t128_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + } else if ((addr >= 0x1d00) && (addr < 0x1e00)) + ret = ncr5380_read((addr - 0x1d00) >> 5, ncr); + else if (addr >= 0x1e00 && addr < 0x2000) { + if ((t128->host_pos >= MIN(512, dev->buffer_length)) || + (ncr->dma_mode != DMA_INITIATOR_RECEIVE)) + ret = 0xff; + else { + ret = t128->buffer[t128->host_pos++]; + + t128_log("T128 Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, + t128->host_pos); + + if (t128->host_pos == MIN(512, dev->buffer_length)) { + t128->status &= ~0x04; + t128_log("T128 Transfer busy read, status = %02x, period = %lf\n", + t128->status, ncr->period); + if ((ncr->period == 0.2) || (ncr->period == 0.02)) + timer_on_auto(&t128->timer, 40.2); + } else if ((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 +t128_dma_mode_ext(void *priv, void *ext_priv) +{ + t128_t *t128 = (t128_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; + + /*Don't stop the timer until it finishes the transfer*/ + if (t128->block_loaded && (ncr->mode & MODE_DMA)) { + t128_log("Continuing DMA mode\n"); + timer_on_auto(&t128->timer, ncr->period + 1.0); + } + + /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ + if (!t128->block_loaded && !(ncr->mode & MODE_DMA)) { + t128_log("No DMA mode\n"); + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + ncr->dma_mode = DMA_IDLE; + } +} + +static int +t128_dma_send_ext(void *priv, void *ext_priv) +{ + t128_t *t128 = (t128_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + + if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + memset(t128->buffer, 0, MIN(512, dev->buffer_length)); + t128->status |= 0x04; + t128->host_pos = 0; + t128->block_count = dev->buffer_length >> 9; + + if (dev->buffer_length < 512) + t128->block_count = 1; + + t128->block_loaded = 1; + } + return 1; +} + +static int +t128_dma_initiator_receive_ext(void *priv, void *ext_priv) +{ + t128_t *t128 = (t128_t *) ext_priv; + ncr_t *ncr = (ncr_t *) priv; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + + if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) { + memset(t128->buffer, 0, MIN(512, dev->buffer_length)); + t128->status |= 0x04; + t128->host_pos = MIN(512, dev->buffer_length); + t128->block_count = dev->buffer_length >> 9; + + if (dev->buffer_length < 512) + t128->block_count = 1; + + t128->block_loaded = 1; + timer_on_auto(&t128->timer, 0.02); + } + return 1; +} + +static void +t128_timer_on_auto(void *ext_priv, double period) +{ + t128_t *t128 = (t128_t *) ext_priv; + + if (period == 0.0) + timer_stop(&t128->timer); + else + timer_on_auto(&t128->timer, period); +} + +void +t128_callback(void *priv) +{ + t128_t *t128 = (void *) priv; + ncr_t *ncr = &t128->ncr; + scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id]; + int bus; + uint8_t c; + uint8_t temp; + + if ((ncr->dma_mode != DMA_IDLE) && (ncr->mode & MODE_DMA) && t128->block_loaded) { + if ((t128->host_pos == MIN(512, dev->buffer_length)) && t128->block_count) + t128->status |= 0x04; + + timer_on_auto(&t128->timer, ncr->period / 55.0); + } + + if (ncr->data_wait & 1) { + ncr->clear_req = 3; + ncr->data_wait &= ~1; + if (ncr->dma_mode == DMA_IDLE) + return; + } + + switch (ncr->dma_mode) { + case DMA_SEND: + if (!(t128->status & 0x04)) { + t128_log("Write status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); + break; + } + + if (!t128->block_loaded) { + t128_log("Write block not loaded\n"); + break; + } + + if (t128->host_pos < MIN(512, dev->buffer_length)) + break; + +write_again: + for (c = 0; c < 10; c++) { + ncr5380_bus_read(ncr); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + temp = t128->buffer[t128->pos]; + + bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr5380_bus_update(ncr, bus | BUS_ACK); + ncr5380_bus_update(ncr, bus & ~BUS_ACK); + + t128->pos++; + t128_log("T128 Buffer pos for writing = %d\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->pos = 0; + t128->host_pos = 0; + t128->status &= ~0x02; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + t128_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&t128->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 write irq\n"); + ncr5380_irq(ncr, 1); + } + } + break; + } else + goto write_again; + break; + + case DMA_INITIATOR_RECEIVE: + if (!(t128->status & 0x04)) { + t128_log("Read status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos); + break; + } + + if (!t128->block_loaded) { + t128_log("Read block not loaded\n"); + break; + } + + if (t128->host_pos < MIN(512, dev->buffer_length)) + break; + +read_again: + for (c = 0; c < 10; c++) { + ncr5380_bus_read(ncr); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + ncr5380_bus_read(ncr); + temp = BUS_GETDATA(ncr->cur_bus); + + bus = ncr5380_get_bus_host(ncr); + + ncr5380_bus_update(ncr, bus | BUS_ACK); + ncr5380_bus_update(ncr, bus & ~BUS_ACK); + + t128->buffer[t128->pos++] = temp; + t128_log("T128 Buffer pos for reading=%d, temp=%02x, len=%d.\n", t128->pos, temp, dev->buffer_length); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->pos = 0; + t128->host_pos = 0; + t128->status &= ~0x02; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); + if (!t128->block_count) { + t128->block_loaded = 0; + t128_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&t128->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } + break; + } else + goto read_again; + break; + + default: + break; + } + + ncr5380_bus_read(ncr); + + if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + t128_log("Updating DMA\n"); + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; + timer_on_auto(&t128->timer, 10.0); + } +} + +static uint8_t +t228_read(int port, void *priv) +{ + const t128_t *t128 = (t128_t *) priv; + + return (t128->pos_regs[port & 7]); +} + +static void +t228_write(int port, uint8_t val, void *priv) +{ + t128_t *t128 = (t128_t *) priv; + ncr_t *ncr = &t128->ncr; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) + return; + + mem_mapping_disable(&t128->bios_rom.mapping); + mem_mapping_disable(&t128->mapping); + + /* Save the MCA register value. */ + t128->pos_regs[port & 7] = val; + + if (t128->pos_regs[2] & 1) { + switch (t128->pos_regs[2] & 6) { + case 0: + t128->rom_addr = 0xcc000; + break; + case 2: + t128->rom_addr = 0xc8000; + break; + case 4: + t128->rom_addr = 0xdc000; + break; + case 6: + t128->rom_addr = 0xd8000; + break; + + default: + break; + } + + t128->bios_enabled = !(t128->pos_regs[2] & 8); + + switch (t128->pos_regs[2] & 0x70) { + case 0: + ncr->irq = -1; + break; + case 0x10: + ncr->irq = 3; + break; + case 0x20: + ncr->irq = 5; + break; + case 0x30: + ncr->irq = 7; + break; + case 0x40: + ncr->irq = 10; + break; + case 0x50: + ncr->irq = 12; + break; + case 0x60: + ncr->irq = 14; + break; + case 0x70: + ncr->irq = 15; + break; + + default: + break; + } + + if (t128->bios_enabled) { + t128->status &= ~0x80; + mem_mapping_set_addr(&t128->bios_rom.mapping, t128->rom_addr, 0x4000); + mem_mapping_set_addr(&t128->mapping, t128->rom_addr, 0x4000); + } else + t128->status |= 0x80; + } +} + +static uint8_t +t228_feedb(void *priv) +{ + const t128_t *t128 = (t128_t *) priv; + + return t128->pos_regs[2] & 1; +} + +static void * +t128_init(const device_t *info) +{ + t128_t *t128; + ncr_t *ncr; + + t128 = malloc(sizeof(t128_t)); + memset(t128, 0x00, sizeof(t128_t)); + ncr = &t128->ncr; + + ncr->bus = scsi_get_bus(); + + if (info->flags & DEVICE_MCA) { + rom_init(&t128->bios_rom, T128_ROM, + 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_add(&t128->mapping, 0xd8000, 0x4000, + t128_read, NULL, NULL, + t128_write, NULL, NULL, + t128->bios_rom.rom, MEM_MAPPING_EXTERNAL, t128); + mem_mapping_disable(&t128->bios_rom.mapping); + t128->pos_regs[0] = 0x8c; + t128->pos_regs[1] = 0x50; + mca_add(t228_read, t228_write, t228_feedb, NULL, t128); + } else if (info->local == 0) { + ncr->irq = device_get_config_int("irq"); + t128->rom_addr = device_get_config_hex20("bios_addr"); + t128->bios_enabled = device_get_config_int("boot"); + if (t128->bios_enabled) + rom_init(&t128->bios_rom, T128_ROM, + t128->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_add(&t128->mapping, t128->rom_addr, 0x4000, + t128_read, NULL, NULL, + t128_write, NULL, NULL, + t128->bios_rom.rom, MEM_MAPPING_EXTERNAL, t128); + } + + ncr->priv = t128; + ncr->dma_mode_ext = t128_dma_mode_ext; + ncr->dma_send_ext = t128_dma_send_ext; + ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext; + ncr->timer = t128_timer_on_auto; + t128->status = 0x00 /*0x04*/; + t128->host_pos = 512; + if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) + t128->status |= 0x80; + + if (info->local == 0) + timer_add(&t128->timer, t128_callback, t128, 0); + + scsi_bus_set_speed(ncr->bus, 5000000.0); + + return t128; +} + +static void +t128_close(void *priv) +{ + t128_t *t128 = (t128_t *) priv; + + if (t128) { + /* Tell the timer to terminate. */ + timer_stop(&t128->timer); + + free(t128); + t128 = NULL; + } +} + +static int +t128_available(void) +{ + return (rom_present(T128_ROM)); +} + +// clang-format off +static const device_config_t t128_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 = "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 = "None", .value = -1 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { + .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_t128_device = { + .name = "Trantor T128", + .internal_name = "t128", + .flags = DEVICE_ISA, + .local = 0, + .init = t128_init, + .close = t128_close, + .reset = NULL, + { .available = t128_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = t128_config +}; + + +const device_t scsi_t228_device = { + .name = "Trantor T228", + .internal_name = "t228", + .flags = DEVICE_MCA, + .local = 0, + .init = t128_init, + .close = t128_close, + .reset = NULL, + { .available = t128_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t scsi_pas_device = { + .name = "Pro Audio Spectrum Plus/16 SCSI", + .internal_name = "scsi_pas", + .flags = DEVICE_ISA, + .local = 1, + .init = t128_init, + .close = t128_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 3140a7181..dff0fcd0f 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -18,7 +18,8 @@ add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c sio_it86x1f.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 - sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c + sio_w83787f.c sio_w83877f.c sio_w83977f.c + sio_um8663f.c sio_um8669f.c sio_vt82c686.c) if(SIO_DETECT) diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index b2c8933c6..0cd686991 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -12,13 +12,15 @@ * * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2024 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> @@ -45,35 +47,67 @@ typedef struct fdc37c669_t { static int next_id = 0; -static uint16_t -make_port(fdc37c669_t *dev, uint8_t reg) +#ifdef ENABLE_FDC37C669_LOG +int fdc37c669_do_log = ENABLE_FDC37C669_LOG; + +static void +fdc37c669_log(const char *fmt, ...) { - uint16_t p = 0; - uint16_t mask = 0; + va_list ap; - 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; + if (fdc37c669_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } +} +#else +# define fdc37c669_log(fmt, ...) +#endif - p = ((uint16_t) (dev->regs[reg] & mask)) << 2; - if (reg == 0x22) - p |= 6; +static void +fdc37c669_fdc_handler(fdc37c669_t *dev) +{ + fdc_remove(dev->fdc); + if (dev->regs[0x20] & 0xc0) + fdc_set_base(dev->fdc, ((uint16_t) dev->regs[0x20]) << 2); +} - return p; +static void +fdc37c669_uart_handler(fdc37c669_t *dev, uint8_t uart) +{ + uint8_t uart_reg = 0x24 + uart; + uint8_t pwrdn_mask = 0x08 << (uart << 2); + uint8_t uart_shift = ((uart ^ 1) << 2); + + serial_remove(dev->uart[uart]); + if ((dev->regs[0x02] & pwrdn_mask) && (dev->regs[uart_reg] & 0xc0)) + serial_setup(dev->uart[0], ((uint16_t) dev->regs[0x24]) << 2, + (dev->regs[0x28] >> uart_shift) & 0x0f); +} + +static double +fdc37c669_uart_get_clock_src(fdc37c669_t *dev, uint8_t uart) +{ + double clock_srcs[4] = { 24000000.0 / 13.0, 24000000.0 / 12.0, 24000000.0 / 3.0, 24000000.0 / 3.0 }; + double ret; + uint8_t clock_src_0 = !!(dev->regs[0x04] & (0x10 << uart)); + uint8_t clock_src_1 = !!(dev->regs[0x0c] & (0x40 << uart)); + uint8_t clock_src = clock_src_0 | (clock_src_1 << 1); + + ret = clock_srcs[clock_src]; + + return ret; +} + +static void +fdc37c669_lpt_handler(fdc37c669_t *dev) +{ + uint8_t mask = ~(dev->regs[0x04] & 0x01); + + lpt_port_remove(dev->id); + if ((dev->regs[0x01] & 0x04) && (dev->regs[0x23] >= 0x40)) + lpt_port_init(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2); } static void @@ -81,149 +115,153 @@ 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; + uint8_t valxor = val ^ dev->regs[dev->cur_reg]; + + fdc37c669_log("[%04X:%08X] [W] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, val, + dev->tries, dev->locked); if (index) { if ((val == 0x55) && !dev->locked) { - if (dev->tries) { + dev->tries = (dev->tries + 1) & 1; + + 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; - } + else + dev->cur_reg = val; + } else + 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]; + } else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) switch (dev->cur_reg) { + case 0x00: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x74) | (val & 0x8b); + if (!dev->id && (valxor & 8)) + fdc_set_power_down(dev->fdc, !(val & 0x08)); + break; + case 0x01: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x73) | (val & 0x8c); + if (valxor & 0x04) + fdc37c669_lpt_handler(dev); + if (valxor & 0x80) + dev->rw_locked = !(val & 0x80); + break; + case 0x02: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x77) | (val & 0x88); + if (valxor & 0x08) + fdc37c669_uart_handler(dev, 0); + if (valxor & 0x80) + fdc37c669_uart_handler(dev, 1); + break; + case 0x03: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x08) | (val & 0xf7); + if (!dev->id && (valxor & 0x02)) + fdc_update_enh_mode(dev->fdc, !!(val & 0x02)); + break; + case 0x04: 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)); - } + if (valxor & 0x03) + fdc37c669_lpt_handler(dev); + if (valxor & 0x10) + serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0)); + if (valxor & 0x20) + serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1)); 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: + case 0x05: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x83) | (val & 0x7c); 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); + case 0x06: + dev->regs[dev->cur_reg] = val; + break; + case 0x07: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x06) | (val & 0xf9); + break; + case 0x08: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x0f) | (val & 0xf0); + break; + case 0x09: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x38) | (val & 0xc7); + break; + case 0x0a: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xf0) | (val & 0x0f); + break; + case 0x0b: + dev->regs[dev->cur_reg] = val; + if (!dev->id && (valxor & 0x03)) + fdc_update_rwc(dev->fdc, 0, val & 0x03); + if (!dev->id && (valxor & 0x0c)) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + break; + case 0x0c: + dev->regs[dev->cur_reg] = val; + if (valxor & 0x40) + serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0)); + if (valxor & 0x80) + serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1)); + break; + case 0x0f: + case 0x12 ... 0x1f: + dev->regs[dev->cur_reg] = val; + break; + case 0x10: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x07) | (val & 0xf8); + break; + case 0x11: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xfc) | (val & 0x03); 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)); - } + dev->regs[dev->cur_reg] = val & 0xfc; + if (!dev->id && (valxor & 0xfc)) + fdc37c669_fdc_handler(dev); + break; + case 0x21: + dev->regs[dev->cur_reg] = val & 0xfc; + break; + case 0x22: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x03) | (val & 0xfc); 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)); - } - } + dev->regs[dev->cur_reg] = val; + if (valxor) + fdc37c669_lpt_handler(dev); 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); - } + dev->regs[dev->cur_reg] = val & 0xfe; + if (valxor & 0xfe) + fdc37c669_uart_handler(dev, 0); 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); - } + dev->regs[dev->cur_reg] = val & 0xfe; + if (valxor & 0xfe) + fdc37c669_uart_handler(dev, 1); + break; + case 0x26: + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc_set_dma_ch(dev->fdc, val >> 4); break; case 0x27: - if (valxor & 0xf) { - if (dev->id) - lpt2_irq(val & 0xf); - else - lpt1_irq(val & 0xf); - } + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc_set_irq(dev->fdc, val >> 4); + if (valxor & 0x0f) + lpt_port_irq(dev->id, val & 0x0f); 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); - } + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc37c669_uart_handler(dev, 0); + if (valxor & 0x0f) + fdc37c669_uart_handler(dev, 1); break; - - default: + case 0x29: + dev->regs[dev->cur_reg] = val & 0x0f; break; } } @@ -238,23 +276,23 @@ fdc37c669_read(uint16_t port, void *priv) if (dev->locked) { if (index) ret = dev->cur_reg; - else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) + else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) ret = dev->regs[dev->cur_reg]; } + fdc37c669_log("[%04X:%08X] [R] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, ret, + dev->tries, dev->locked); + return ret; } static void -fdc37c669_reset(fdc37c669_t *dev) +fdc37c669_reset(void *priv) { - serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + fdc37c669_t *dev = (fdc37c669_t *) priv; - serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + memset(dev->regs, 0x00, 42); - memset(dev->regs, 0, 42); dev->regs[0x00] = 0x28; dev->regs[0x01] = 0x9c; dev->regs[0x02] = 0x88; @@ -262,32 +300,23 @@ 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] = (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] = (LPT2_ADDR >> 2); + dev->regs[0x1e] = 0x3c; /* Gameport controller. */ + dev->regs[0x20] = 0x3c; + dev->regs[0x21] = 0x3c; + dev->regs[0x22] = 0x3d; - lpt2_remove(); - lpt2_init(LPT2_ADDR); - - dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe; - dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe; - } else { + if (dev->id != 1) { fdc_reset(dev->fdc); - - lpt1_remove(); - lpt1_init(LPT1_ADDR); - - dev->regs[0x23] = (LPT1_ADDR >> 2); - - dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe; - dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe; + fdc37c669_fdc_handler(dev); } - dev->regs[0x26] = (2 << 4) | 3; - dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7); - dev->regs[0x28] = (4 << 4) | 3; + + fdc37c669_uart_handler(dev, 0); + serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0)); + + fdc37c669_uart_handler(dev, 1); + serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1)); + + fdc37c669_lpt_handler(dev); dev->locked = 0; dev->rw_locked = 0; @@ -317,8 +346,8 @@ fdc37c669_init(const device_t *info) 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 ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 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); @@ -334,7 +363,7 @@ const device_t fdc37c669_device = { .local = 0, .init = fdc37c669_init, .close = fdc37c669_close, - .reset = NULL, + .reset = fdc37c669_reset, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, @@ -348,7 +377,7 @@ const device_t fdc37c669_370_device = { .local = 1, .init = fdc37c669_init, .close = fdc37c669_close, - .reset = NULL, + .reset = fdc37c669_reset, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 23fcd2fb3..c1fb2c1a5 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -394,6 +394,20 @@ const device_t fdc37c661_ide_device = { .config = NULL }; +const device_t fdc37c661_ide_sec_device = { + .name = "SMC FDC37C661 Super I/O (With Secondary IDE)", + .internal_name = "fdc37c661_ide_sec", + .flags = 0, + .local = 0x261, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc37c663_device = { .name = "SMC FDC37C663 Super I/O", .internal_name = "fdc37c663", @@ -464,6 +478,20 @@ const device_t fdc37c665_ide_pri_device = { .config = NULL }; +const device_t fdc37c665_ide_sec_device = { + .name = "SMC FDC37C665 Super I/O (With Secondary IDE)", + .internal_name = "fdc37c665_ide_sec", + .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 fdc37c666_device = { .name = "SMC FDC37C666 Super I/O", .internal_name = "fdc37c666", diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 4acbfeff5..97fcb3fbd 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -31,6 +31,7 @@ #include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/keyboard.h> #include <86box/nvr.h> #include <86box/apm.h> #include <86box/acpi.h> @@ -51,11 +52,14 @@ typedef struct access_bus_t { typedef struct fdc37c93x_t { uint8_t chip_id; uint8_t is_apm; + uint8_t has_nvr; uint8_t tries; + uint8_t port_370; uint8_t gpio_regs[2]; uint8_t auxio_reg; uint8_t regs[48]; uint8_t ld_regs[11][256]; + uint16_t superio_base; uint16_t gpio_base; /* Set to EA */ uint16_t auxio_base; uint16_t nvr_sec_base; @@ -66,8 +70,23 @@ typedef struct fdc37c93x_t { access_bus_t *access_bus; nvr_t *nvr; acpi_t *acpi; + void *kbc; } fdc37c93x_t; +static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv); +static uint8_t fdc37c93x_read(uint16_t port, void *priv); + +static uint16_t +make_port_superio(fdc37c93x_t *dev) +{ + uint16_t r0 = dev->regs[0x26]; + uint16_t r1 = dev->regs[0x27]; + + uint16_t p = (r1 << 8) + r0; + + return p; +} + static uint16_t make_port(fdc37c93x_t *dev, uint8_t ld) { @@ -126,6 +145,16 @@ fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); } +static void +fdc37c93x_superio_handler(fdc37c93x_t *dev) +{ + io_removehandler(dev->superio_base, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + dev->superio_base = make_port_superio(dev); + io_sethandler(dev->superio_base, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); +} + static void fdc37c93x_fdc_handler(fdc37c93x_t *dev) { @@ -180,7 +209,9 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, int uart) static void fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) { - uint8_t local_enable = !!dev->ld_regs[6][0x30]; + uint8_t local_enable = !!dev->ld_regs[6][0x30]; + + local_enable &= ((dev->ld_regs[6][0xf0] & 0x90) != 0x80); nvr_at_handler(0, 0x70, dev->nvr); if (local_enable) @@ -193,6 +224,9 @@ fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) uint16_t ld_port = 0; uint8_t local_enable = !!dev->ld_regs[6][0x30]; + local_enable &= (((dev->ld_regs[6][0xf0] & 0xe0) == 0x80) || + ((dev->ld_regs[6][0xf0] & 0xe0) == 0xe0)); + 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; @@ -203,6 +237,14 @@ fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) } } +static void +fdc37c93x_kbc_handler(fdc37c93x_t *dev) +{ + uint8_t local_enable = !!dev->ld_regs[7][0x30]; + + kbc_at_handler(local_enable, dev->kbc); +} + static void fdc37c93x_auxio_handler(fdc37c93x_t *dev) { @@ -401,10 +443,9 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) switch (dev->regs[7]) { case 0x01: case 0x02: - case 0x07: return; case 0x06: - if (dev->chip_id != 0x30) + if (!dev->has_nvr) return; /* Bits 0 to 3 of logical device 6 (RTC) register F0h must stay set once they are set. */ @@ -453,6 +494,10 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) fdc37c93x_access_bus_handler(dev); break; + case 0x27: + fdc37c93x_superio_handler(dev); + break; + default: break; } @@ -566,12 +611,15 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) break; case 6: /* RTC/NVR */ - if (dev->chip_id != 0x30) - break; + if (!dev->has_nvr) + return; switch (dev->cur_reg) { case 0x30: - if (valxor) + if (valxor) { fdc37c93x_nvr_pri_handler(dev); + fdc37c93x_nvr_sec_handler(dev); + } + break; case 0x62: case 0x63: if (valxor) @@ -617,6 +665,9 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) nvr_bank_set(0, 0, dev->nvr); nvr_bank_set(1, 0xff, dev->nvr); } + + fdc37c93x_nvr_pri_handler(dev); + fdc37c93x_nvr_sec_handler(dev); } break; @@ -624,6 +675,18 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) break; } break; + case 7: + /* Keyboard */ + switch (dev->cur_reg) { + case 0x30: + if (valxor) + fdc37c93x_kbc_handler(dev); + break; + + default: + break; + } + break; case 8: /* Auxiliary I/O */ switch (dev->cur_reg) { @@ -723,14 +786,14 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->regs[0x21] = 0x01; dev->regs[0x22] = 0x39; dev->regs[0x24] = 0x04; - dev->regs[0x26] = 0xF0; + dev->regs[0x26] = dev->port_370 ? 0x70 : 0xF0; dev->regs[0x27] = 0x03; 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; + dev->ld_regs[0][0x30] = 0; dev->ld_regs[0][0x60] = 3; dev->ld_regs[0][0x61] = 0xF0; dev->ld_regs[0][0x70] = 6; @@ -756,7 +819,7 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[2][0x70] = 0xF; /* Logical device 3: Parallel Port */ - dev->ld_regs[3][0x30] = 1; + dev->ld_regs[3][0x30] = 0; dev->ld_regs[3][0x60] = 3; dev->ld_regs[3][0x61] = 0x78; dev->ld_regs[3][0x70] = 7; @@ -764,7 +827,7 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->ld_regs[3][0xF0] = 0x3C; /* Logical device 4: Serial Port 1 */ - dev->ld_regs[4][0x30] = 1; + dev->ld_regs[4][0x30] = 0; dev->ld_regs[4][0x60] = 3; dev->ld_regs[4][0x61] = 0xf8; dev->ld_regs[4][0x70] = 4; @@ -772,7 +835,7 @@ fdc37c93x_reset(fdc37c93x_t *dev) serial_setup(dev->uart[0], COM1_ADDR, dev->ld_regs[4][0x70]); /* Logical device 5: Serial Port 2 */ - dev->ld_regs[5][0x30] = 1; + dev->ld_regs[5][0x30] = 0; dev->ld_regs[5][0x60] = 2; dev->ld_regs[5][0x61] = 0xf8; dev->ld_regs[5][0x70] = 3; @@ -782,12 +845,13 @@ fdc37c93x_reset(fdc37c93x_t *dev) serial_setup(dev->uart[1], COM2_ADDR, dev->ld_regs[5][0x70]); /* Logical device 6: RTC */ - dev->ld_regs[6][0x30] = 1; - dev->ld_regs[6][0x63] = (dev->chip_id == 0x30) ? 0x70 : 0x00; + dev->ld_regs[6][0x30] = 0; + dev->ld_regs[6][0x63] = (dev->has_nvr) ? 0x70 : 0x00; + dev->ld_regs[6][0xF0] = 0; dev->ld_regs[6][0xF4] = 3; /* Logical device 7: Keyboard */ - dev->ld_regs[7][0x30] = 1; + dev->ld_regs[7][0x30] = 0; dev->ld_regs[7][0x61] = 0x60; dev->ld_regs[7][0x70] = 1; @@ -810,13 +874,22 @@ fdc37c93x_reset(fdc37c93x_t *dev) fdc_reset(dev->fdc); fdc37c93x_fdc_handler(dev); - if (dev->chip_id == 0x30) { + if (dev->has_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); + + nvr_lock_set(0x80, 0x20, 0, dev->nvr); + nvr_lock_set(0xa0, 0x20, 0, dev->nvr); + nvr_lock_set(0xc0, 0x20, 0, dev->nvr); + nvr_lock_set(0xe0, 0x20, 0, dev->nvr); } + fdc37c93x_kbc_handler(dev); + + fdc37c93x_superio_handler(dev); + dev->locked = 0; } @@ -868,12 +941,14 @@ fdc37c93x_init(const device_t *info) 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); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + 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->chip_id = info->local & 0xff; + dev->is_apm = (info->local >> 8) & 0x01; + is_compaq = (info->local >> 8) & 0x02; + dev->has_nvr = !((info->local >> 8) & 0x04); + dev->port_370 = ((info->local >> 8) & 0x08); dev->gpio_regs[0] = 0xff; #if 0 @@ -881,7 +956,7 @@ fdc37c93x_init(const device_t *info) #endif dev->gpio_regs[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; - if (dev->chip_id == 0x30) { + if (dev->has_nvr) { dev->nvr = device_add(&at_nvr_device); nvr_bank_set(0, 0, dev->nvr); @@ -901,20 +976,17 @@ fdc37c93x_init(const device_t *info) 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(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); } + dev->kbc = device_add(&keyboard_ps2_ami_pci_device); + fdc37c93x_reset(dev); return dev; } const device_t fdc37c931apm_device = { - .name = "SMC FDC37C932QF Super I/O", + .name = "SMC FDC37C931APM Super I/O", .internal_name = "fdc37c931apm", .flags = 0, .local = 0x130, /* Share the same ID with the 932QF. */ @@ -928,7 +1000,7 @@ const device_t fdc37c931apm_device = { }; const device_t fdc37c931apm_compaq_device = { - .name = "SMC FDC37C932QF Super I/O (Compaq Presario 4500)", + .name = "SMC FDC37C931APM Super I/O (Compaq Presario 4500)", .internal_name = "fdc37c931apm_compaq", .flags = 0, .local = 0x330, /* Share the same ID with the 932QF. */ @@ -982,3 +1054,32 @@ const device_t fdc37c935_device = { .force_redraw = NULL, .config = NULL }; + +const device_t fdc37c935_370_device = { + .name = "SMC FDC37C935 Super I/O (Port 370h)", + .internal_name = "fdc37c935_370", + .flags = 0, + .local = 0x802, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t fdc37c935_no_nvr_device = { + .name = "SMC FDC37C935 Super I/O", + .internal_name = "fdc37c935", + .flags = 0, + .local = 0x402, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index d53e78050..00524863a 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -14,9 +14,10 @@ * * Copyright 2023 RichardG. */ +#include #include -#include #include +#include #include #include #include @@ -413,8 +414,10 @@ it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) case 0x23: val &= (1 << dev->gpio_ldn) - 1; dev->global_regs[reg & 0x0f] = val; +#ifdef ENABLE_IT86X1F_LOG if (val) - pclog("IT86x1F: Warning: ISAPnP mode enabled.\n"); + it86x1f_log("IT86x1F: Warning: ISAPnP mode enabled.\n"); +#endif break; case 0x24: @@ -805,10 +808,10 @@ it86x1f_init(UNUSED(const device_t *info)) break; } if (i >= (sizeof(it86x1f_models) / sizeof(it86x1f_models[0]))) { - fatal("IT86x1F: Unknown type %04X selected\n", info->local); + fatal("IT86x1F: Unknown type %04" PRIXPTR " selected\n", info->local); return NULL; } - it86x1f_log("IT86x1F: init(%04X)\n", info->local); + it86x1f_log("IT86x1F: init(%04" PRIXPTR ")\n", info->local); /* Let the resource data parser figure out the ROM size. */ dev->pnp_card = isapnp_add_card(it86x1f_models[i].pnp_rom, -1, it86x1f_models[i].pnp_config_changed, NULL, it86x1f_pnp_read_vendor_reg, it86x1f_pnp_write_vendor_reg, dev); diff --git a/src/sio/sio_pc87310.c b/src/sio/sio_pc87310.c index d567bd4d5..075b819ff 100644 --- a/src/sio/sio_pc87310.c +++ b/src/sio/sio_pc87310.c @@ -8,15 +8,13 @@ * * Emulation of the NatSemi PC87310 Super I/O chip. * - * - * * Authors: Miran Grca, - * Tiseno100 - * EngiNerd + * EngiNerd, + * Tiseno100, * - * Copyright 2020 Miran Grca. - * Copyright 2020 Tiseno100 + * Copyright 2020-2024 Miran Grca. * Copyright 2021 EngiNerd. + * Copyright 2020 Tiseno100. */ #include #include @@ -42,7 +40,8 @@ #include <86box/sio.h> #include <86box/plat_unused.h> -#define HAS_IDE_FUNCTIONALITY dev->ide_function +#define FLAG_IDE 0x00000001 +#define FLAG_ALI 0x00000002 #ifdef ENABLE_PC87310_LOG int pc87310_do_log = ENABLE_PC87310_LOG; @@ -64,8 +63,8 @@ pc87310_log(const char *fmt, ...) typedef struct pc87310_t { uint8_t tries; - uint8_t ide_function; - uint8_t reg; + uint8_t flags; + uint8_t regs[2]; fdc_t *fdc; serial_t *uart[2]; } pc87310_t; @@ -83,7 +82,9 @@ lpt1_handler(pc87310_t *dev) * 10 278h * 11 disabled */ - temp = dev->reg & 3; + temp = dev->regs[1] & 0x03; + + lpt1_remove(); switch (temp) { case 0: @@ -111,23 +112,59 @@ lpt1_handler(pc87310_t *dev) } static void -serial_handler(pc87310_t *dev, int uart) +serial_handler(pc87310_t *dev) { - int temp; - /* bit 2: disable serial port 1 - * bit 3: disable serial port 2 - * bit 4: swap serial ports + uint8_t temp, temp2 = 0x00; + uint16_t base1 = 0x0000, base2 = 0x0000; + uint8_t irq1, irq2; + /* - Bit 2: Disable serial port 1; + * - Bit 3: Disable serial port 2; + * - Bit 4: Swap serial ports. */ - temp = (dev->reg >> (2 + uart)) & 1; + temp = (dev->regs[1] >> 2) & 0x07; - // current serial port is enabled - if (!temp) { - // configure serial port as COM2 - if (((dev->reg >> 4) & 1) ^ uart) - serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ); - // configure serial port as COM1 - else - serial_setup(dev->uart[uart], COM1_ADDR, COM1_IRQ); + /* - Bits 1, 0: 0, 0 = Normal (3F8 and 2F8); + * 0, 1 = 2E8 instead of 2F8; + * 1, 0 = 3E8 instead of 3F8 and 2E8 instead of 2F8; + * 1, 1 = 3E8 instead of 3F8. + * + * If we XOR bit 0 with bit 1, we get this: + * 0, 0 = Normal (3F8 and 2F8); + * 0, 1 = 2E8 instead of 2F8; + * 1, 0 = 3E8 instead of 3F8; + * 1, 1 = 3E8 instead of 3F8 and 2E8 instead of 2F8. + * + * Then they become simple toggle bits. + * Therefore, we do this for easier operation. + */ + if (dev->flags & FLAG_ALI) { + temp2 = dev->regs[0] & 0x03; + temp2 ^= ((temp2 & 0x02) >> 1); + } + + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + + if (!(temp & 0x01)) { + base1 = (temp & 0x04) ? COM2_ADDR : COM1_ADDR; + if ((base1 == COM1_ADDR) && (temp2 & 0x02)) + base1 = 0x03e8; + else if ((base1 == COM2_ADDR) && (temp2 & 0x01)) + base1 = 0x02e8; + irq1 = (temp & 0x04) ? COM2_IRQ : COM1_IRQ; + serial_setup(dev->uart[0], base1, irq1); + pc87310_log("UART 1 at %04X, IRQ %i\n", base1, irq1); + } + + if (!(temp & 0x02)) { + base2 = (temp & 0x04) ? COM1_ADDR : COM2_ADDR; + if ((base2 == COM1_ADDR) && (temp2 & 0x02)) + base2 = 0x03e8; + else if ((base2 == COM2_ADDR) && (temp2 & 0x01)) + base2 = 0x02e8; + irq2 = (temp & 0x04) ? COM1_IRQ : COM2_IRQ; + serial_setup(dev->uart[1], base2, irq2); + pc87310_log("UART 2 at %04X, IRQ %i\n", base2, irq2); } } @@ -136,61 +173,63 @@ pc87310_write(UNUSED(uint16_t port), uint8_t val, void *priv) { pc87310_t *dev = (pc87310_t *) priv; uint8_t valxor; + uint8_t idx = (uint8_t) ((port & 0x0002) >> 1); + + pc87310_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); - // second write to config register if (dev->tries) { - valxor = val ^ dev->reg; - dev->tries = 0; - dev->reg = val; - // first write to config register - } else { + /* Second write to config register. */ + valxor = val ^ dev->regs[idx]; + dev->tries = 0; + dev->regs[idx] = val; + + if (idx) { + /* Register, common to both PC87310 and ALi M5105. */ + pc87310_log("SIO: Common register written %02X\n", val); + + /* Reconfigure parallel port. */ + if (valxor & 0x03) + /* Bits 1, 0: 1, 1 = Disable parallel port. */ + lpt1_handler(dev); + + /* Reconfigure serial ports. */ + if (valxor & 0x1c) + serial_handler(dev); + + /* Reconfigure IDE controller. */ + if ((dev->flags & FLAG_IDE) && (valxor & 0x20)) { + pc87310_log("SIO: HDC disabled\n"); + ide_pri_disable(); + /* Bit 5: 1 = Disable IDE controller. */ + if (!(val & 0x20)) { + pc87310_log("SIO: HDC enabled\n"); + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + ide_pri_enable(); + } + } + + /* Reconfigure floppy disk controller. */ + if (valxor & 0x40) { + pc87310_log("SIO: FDC disabled\n"); + fdc_remove(dev->fdc); + /* Bit 6: 1 = Disable FDC. */ + if (!(val & 0x40)) { + pc87310_log("SIO: FDC enabled\n"); + fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); + } + } + } else { + /* ALi M5105 extension register. */ + pc87310_log("SIO: M5105 extension register written %02X\n", val); + + /* Reconfigure serial ports. */ + if (valxor & 0x03) + serial_handler(dev); + } + } else + /* First write to config register. */ dev->tries++; - return; - } - - pc87310_log("SIO: written %01X\n", val); - - /* reconfigure parallel port */ - if (valxor & 0x03) { - lpt1_remove(); - /* bits 0-1: 11 disable parallel port */ - if (!((val & 1) && (val & 2))) - lpt1_handler(dev); - } - /* reconfigure serial ports */ - if (valxor & 0x1c) { - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); - /* bit 2: 1 disable first serial port */ - if (!(val & 4)) - serial_handler(dev, 0); - /* bit 3: 1 disable second serial port */ - if (!(val & 8)) - serial_handler(dev, 1); - } - /* reconfigure IDE controller */ - if (valxor & 0x20) { - pc87310_log("SIO: HDC disabled\n"); - ide_pri_disable(); - /* bit 5: 1 disable ide controller */ - if (!(val & 0x20) && HAS_IDE_FUNCTIONALITY) { - pc87310_log("SIO: HDC enabled\n"); - ide_set_base(0, 0x1f0); - ide_set_side(0, 0x3f6); - ide_pri_enable(); - } - } - /* reconfigure floppy disk controller */ - if (valxor & 0x40) { - pc87310_log("SIO: FDC disabled\n"); - fdc_remove(dev->fdc); - /* bit 6: 1 disable fdc */ - if (!(val & 0x40)) { - pc87310_log("SIO: FDC enabled\n"); - fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); - } - } - return; } uint8_t @@ -198,12 +237,13 @@ pc87310_read(UNUSED(uint16_t port), void *priv) { pc87310_t *dev = (pc87310_t *) priv; uint8_t ret = 0xff; + uint8_t idx = (uint8_t) ((port & 0x0002) >> 1); dev->tries = 0; - ret = dev->reg; + ret = dev->regs[idx]; - pc87310_log("SIO: read %01X\n", ret); + pc87310_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); return ret; } @@ -211,22 +251,18 @@ pc87310_read(UNUSED(uint16_t port), void *priv) void pc87310_reset(pc87310_t *dev) { - 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" - */ - lpt1_remove(); + dev->regs[0] = 0x00; + dev->regs[1] = 0x00; + + dev->tries = 0; + lpt1_handler(dev); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); - serial_handler(dev, 0); - serial_handler(dev, 1); + serial_handler(dev); + if (dev->flags & FLAG_IDE) { + ide_pri_disable(); + ide_pri_enable(); + } fdc_reset(dev->fdc); -#if 0 - ide_pri_enable(); -#endif } static void @@ -240,25 +276,28 @@ pc87310_close(void *priv) static void * pc87310_init(const device_t *info) { - pc87310_t *dev = (pc87310_t *) malloc(sizeof(pc87310_t)); - memset(dev, 0, sizeof(pc87310_t)); + pc87310_t *dev = (pc87310_t *) calloc(1, sizeof(pc87310_t)); /* Avoid conflicting with machines that make no use of the PC87310 Internal IDE */ - HAS_IDE_FUNCTIONALITY = info->local; + dev->flags = 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); + 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_device); + if (dev->flags & FLAG_IDE) + device_add((dev->flags & FLAG_ALI) ? &ide_vlb_device : &ide_isa_device); pc87310_reset(dev); io_sethandler(0x3f3, 0x0001, pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev); + if (dev->flags & FLAG_ALI) + io_sethandler(0x3f1, 0x0001, + pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev); + return dev; } @@ -280,7 +319,21 @@ const device_t pc87310_ide_device = { .name = "National Semiconductor PC87310 Super I/O with IDE functionality", .internal_name = "pc87310_ide", .flags = 0, - .local = 1, + .local = FLAG_IDE, + .init = pc87310_init, + .close = pc87310_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ali5105_device = { + .name = "ALi M5105 Super I/O", + .internal_name = "ali5105", + .flags = 0, + .local = FLAG_ALI, .init = pc87310_init, .close = pc87310_close, .reset = NULL, diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c new file mode 100644 index 000000000..7391b029f --- /dev/null +++ b/src/sio/sio_um8663f.c @@ -0,0 +1,366 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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 UMC UMF8663F Super I/O chip. + * + * Authors: Miran Grca, + * + * Copyright 2024 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/timer.h> +#include <86box/pci.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/gameport.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/sio.h> +#include <86box/random.h> +#include <86box/plat_unused.h> + +#ifdef ENABLE_UM8663F_LOG +int um8663f_do_log = ENABLE_UM8663F_LOG; + +static void +um8663f_log(const char *fmt, ...) +{ + va_list ap; + + if (um8663f_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define um8663f_log(fmt, ...) +#endif + +typedef struct um8663f_t { + uint8_t max_reg; + uint8_t ide; + uint8_t locked; + uint8_t cur_reg; + uint8_t regs[5]; + + fdc_t *fdc; + serial_t *uart[2]; +} um8663f_t; + +static void +um8663f_fdc_handler(um8663f_t *dev) +{ + fdc_remove(dev->fdc); + if (dev->regs[0] & 0x01) + fdc_set_base(dev->fdc, (dev->regs[1] & 0x01) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); +} + +static void +um8663f_uart_handler(um8663f_t *dev, int port) +{ + uint8_t shift = (port + 1); + + serial_remove(dev->uart[port]); + if (dev->regs[0] & (2 << port)) { + switch ((dev->regs[1] >> shift) & 0x01) { + case 0x00: + if (port == 1) + serial_setup(dev->uart[port], COM4_ADDR, COM4_IRQ); + else + serial_setup(dev->uart[port], COM3_ADDR, COM1_IRQ); + break; + case 0x01: + if (port == 1) + serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ); + else + serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ); + break; + + default: + break; + } + } +} + +static void +um8663f_lpt_handler(um8663f_t *dev) +{ + lpt1_remove(); + if (dev->regs[0] & 0x08) { + switch ((dev->regs[1] >> 3) & 0x01) { + case 0x01: + lpt1_init(LPT1_ADDR); + lpt1_irq(7); + break; + case 0x00: + lpt1_init(LPT2_ADDR); + lpt1_irq(5); + break; + + default: + break; + } + } +} + +static void +um8663f_ide_handler(um8663f_t *dev) +{ + int board = dev->ide - 1; + + if (dev->ide > 0) { + ide_handlers(board, 0); + ide_set_base(board, (dev->regs[1] & 0x10) ? 0x01f0 : 0x0170); + ide_set_side(board, (dev->regs[1] & 0x10) ? 0x03f6 : 0x0376); + if (dev->regs[0] & 0x10) + ide_handlers(board, 1); + } +} + +static void +um8663f_write(uint16_t port, uint8_t val, void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + uint8_t valxor; + + um8663f_log("UM8663F: write(%04X, %02X)\n", port, val); + + if (dev->locked) { + if ((port == 0x108) && (val == 0xaa)) + dev->locked = 0; + } else { + if (port == 0x108) { + if (val == 0x55) + dev->locked = 1; + else + dev->cur_reg = val; + } else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= dev->max_reg)) { + valxor = (dev->regs[dev->cur_reg - 0xc0] ^ val); + dev->regs[dev->cur_reg - 0xc0] = val; + switch (dev->cur_reg - 0xc0) { + /* Port enable register. */ + case 0x00: + if (valxor & 0x10) + um8663f_ide_handler(dev); + if (valxor & 0x08) + um8663f_lpt_handler(dev); + if (valxor & 0x04) + um8663f_uart_handler(dev, 1); + if (valxor & 0x02) + um8663f_uart_handler(dev, 0); + if (valxor & 0x01) + um8663f_fdc_handler(dev); + break; + /* + Port configuration register: + - Bits 7, 6: + - 0, 0 = LPT 1 is none; + - 0, 1 = LPT 1 is EPP; + - 1, 0 = LPT 1 is SPP; + - 1, 1 = LPT 1 is ECP; + - Bit 4 = 0 = IDE is secondary, 1 = IDE is primary; + - Bit 3 = 0 = LPT 1 is 278h, 1 = LPT 1 is 378h; + - Bit 2 = 0 = UART 2 is COM4, 1 = UART 2 is COM2; + - Bit 1 = 0 = UART 1 is COM3, 1 = UART 2 is COM1; + - Bit 0 = 0 = FDC is 370h, 1 = UART 2 is 3f0h. + */ + case 0x01: + if (valxor & 0x10) + um8663f_ide_handler(dev); + if (valxor & 0x08) + um8663f_lpt_handler(dev); + if (valxor & 0x04) + um8663f_uart_handler(dev, 1); + if (valxor & 0x02) + um8663f_uart_handler(dev, 0); + if (valxor & 0x01) + um8663f_fdc_handler(dev); + break; + } + } + } +} + +static uint8_t +um8663f_read(uint16_t port, void *priv) +{ + const um8663f_t *dev = (um8663f_t *) priv; + uint8_t ret = 0xff; + + if (!dev->locked) { + if (port == 0x108) + ret = dev->cur_reg; /* ??? */ + else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= dev->max_reg)) { + ret = dev->regs[dev->cur_reg - 0xc0]; + if (dev->cur_reg == 0xc0) + ret = (ret & 0x1f) | ((random_generate() & 0x07) << 5); + } + } + + um8663f_log("UM8663F: read(%04X) = %02X\n", port, ret); + + return ret; +} + +static void +um8663f_reset(void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + + serial_remove(dev->uart[0]); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + + serial_remove(dev->uart[1]); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + + lpt1_remove(); + lpt1_init(LPT1_ADDR); + + fdc_reset(dev->fdc); + fdc_remove(dev->fdc); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x00] = (dev->ide > 0) ? 0x1f : 0x0f; + dev->regs[0x01] = (dev->ide == 2) ? 0x0f : 0x1f; + + um8663f_fdc_handler(dev); + um8663f_uart_handler(dev, 0); + um8663f_uart_handler(dev, 1); + um8663f_lpt_handler(dev); + um8663f_ide_handler(dev); + + dev->locked = 1; +} + +static void +um8663f_close(void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + + free(dev); +} + +static void * +um8663f_init(UNUSED(const device_t *info)) +{ + um8663f_t *dev = (um8663f_t *) calloc(1, sizeof(um8663f_t)); + + 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); + + dev->ide = info->local & 0xff; + if (dev->ide < IDE_BUS_MAX) + device_add(&ide_isa_device); + + dev->max_reg = info->local >> 8; + + io_sethandler(0x0108, 0x0002, um8663f_read, NULL, NULL, um8663f_write, NULL, NULL, dev); + + um8663f_reset(dev); + + return dev; +} + +const device_t um8663af_device = { + .name = "UMC UM8663AF Super I/O", + .internal_name = "um8663af", + .flags = 0, + .local = 0xc300, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663af_ide_device = { + .name = "UMC UM8663AF Super I/O (With IDE)", + .internal_name = "um8663af_ide", + .flags = 0, + .local = 0xc301, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663af_ide_sec_device = { + .name = "UMC UM8663AF Super I/O (With Secondary IDE)", + .internal_name = "um8663af_ide_sec", + .flags = 0, + .local = 0xc302, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_device = { + .name = "UMC UM8663BF Super I/O", + .internal_name = "um8663bf", + .flags = 0, + .local = 0xc400, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_ide_device = { + .name = "UMC UM8663BF Super I/O (With IDE)", + .internal_name = "um8663bf_ide", + .flags = 0, + .local = 0xc401, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_ide_sec_device = { + .name = "UMC UM8663BF Super I/O (With Secondary IDE)", + .internal_name = "um8663bf_ide_sec", + .flags = 0, + .local = 0xc402, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .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 61e9abd97..136b1add6 100644 --- a/src/sio/sio_um8669f.c +++ b/src/sio/sio_um8669f.c @@ -222,7 +222,11 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri if (dev->ide < IDE_BUS_MAX) { config->io[1].base = config->io[0].base + 0x206; /* status port apparently fixed */ +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + ide_pnp_config_changed(0, config, (void *) (int64_t) dev->ide); +#else ide_pnp_config_changed(0, config, (void *) (int) dev->ide); +#endif } break; diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index 33cfc6311..2e4b82059 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -215,8 +215,9 @@ static void w83787f_fdc_handler(w83787f_t *dev) { fdc_remove(dev->fdc); - if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08)) + if (!(dev->regs[0] & 0x20)) fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); + fdc_set_power_down(dev->fdc, !!(dev->regs[6] & 0x08)); } static void @@ -258,10 +259,10 @@ w83787f_write(uint16_t port, uint8_t val, void *priv) return; } else { if (dev->locked) { - if (dev->rw_locked) + if (dev->rw_locked && (dev->cur_reg <= 0x0b)) return; if (dev->cur_reg == 6) - val &= 0xF3; + val &= 0xFB; valxor = val ^ dev->regs[dev->cur_reg]; dev->regs[dev->cur_reg] = val; } else @@ -363,7 +364,7 @@ w83787f_read(uint16_t port, void *priv) 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) + else if (!dev->rw_locked || (dev->cur_reg > 0x0b)) ret = dev->regs[dev->cur_reg]; } } @@ -406,6 +407,7 @@ w83787f_reset(w83787f_t *dev) dev->regs[0x00] = 0xd0; fdc_reset(dev->fdc); + w83787f_fdc_handler(dev); dev->regs[0x01] = 0x2C; dev->regs[0x03] = 0x70; diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index 8cbb82876..c9a437630 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -78,12 +78,12 @@ w83877f_remap(w83877f_t *dev) { uint8_t hefras = HEFRAS; - io_removehandler(0x250, 0x0002, + io_removehandler(0x250, 0x0003, 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, + io_sethandler(dev->base_address, hefras ? 0x0002 : 0x0003, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); dev->key_times = hefras + 1; dev->key = (hefras ? 0x86 : 0x88) | HEFERE; @@ -155,8 +155,9 @@ 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, FDC_PRIMARY_ADDR); + if (dev->regs[0x20] & 0xc0) + fdc_set_base(dev->fdc, make_port(dev, 0x20)); + fdc_set_power_down(dev->fdc, !!(dev->regs[6] & 0x08)); } static void @@ -252,7 +253,7 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) if (dev->cur_reg == 0x29) return; if (dev->cur_reg == 6) - val &= 0xF3; + val &= 0xFB; valxor = val ^ dev->regs[dev->cur_reg]; dev->regs[dev->cur_reg] = val; } else diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index d6672ac18..f67630c47 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -17,8 +17,8 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_re 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_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 midi_opl4.c midi_opl4_yrw801.c) + snd_emu8k.c snd_mpu401.c snd_pas16.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c + snd_optimc.c esfmu/esfm.c esfmu/esfm_registers.c snd_opl_esfm.c) if(OPENAL) if(VCPKG_TOOLCHAIN) @@ -116,14 +116,14 @@ 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) -endif() - if(GUSMAX) target_compile_definitions(snd PRIVATE USE_GUSMAX) endif() +if(OPL4ML) + target_compile_definitions(snd PRIVATE USE_OPL4ML) + target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) +endif() + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) diff --git a/src/sound/esfmu/esfm.c b/src/sound/esfmu/esfm.c new file mode 100644 index 000000000..89fa82d4f --- /dev/null +++ b/src/sound/esfmu/esfm.c @@ -0,0 +1,2327 @@ +/* + * ESFMu: emulator for the ESS "ESFM" enhanced OPL3 clone + * Copyright (C) 2023 Kagamiin~ + * + * This file includes code and data from the Nuked OPL3 project, copyright (C) + * 2013-2023 Nuke.YKT. Its usage, modification and redistribution is allowed + * under the terms of the GNU Lesser General Public License version 2.1 or + * later. + * + * ESFMu 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. + * + * ESFMu 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 ESFMu. If not, see . + */ + +/* + * ESFMu wouldn't have been possible without the hard work and dedication of + * the retro computer hardware research and preservation community. + * + * I'd like to thank: + * - Nuke.YKT + * Developer of Nuked OPL3, which was the basis for ESFMu's code and + * also a great learning resource on Yamaha FM synthesis for myself. + * Nuke.YKT also gives shoutouts on behalf of Nuked OPL3 to: + * - 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. + * - rainwarrior + * For performing the initial research on ESFM drivers and documenting + * ESS's patent on native mode operator organization. + * - jwt27 + * For kickstarting the ESFM research project and compiling rainwarrior's + * findings and more in an accessible document ("ESFM Demystified"). + * - pachuco/CatButts + * For documenting ESS's patent on ESFM's feedback implementation, which + * was vital in getting ESFMu's sound output to be accurate. + * - akumanatt + * For helping out with code optimization. + * - And everybody who helped out with real hardware testing + */ + +#include "esfm.h" +#include +#include +#include +#include +#include + +/* + * Log-scale quarter sine table extracted from OPL3 ROM; taken straight from + * Nuked OPL3 source code. + * TODO: Extract sine table from ESFM die scans... does ESFM even use a sine + * table? Patent documents give a hint to a possible method of generating sine + * waves using some sort of boolean logic wizardry (lol) + * Optimization: All 8 waveforms are calculated and unfolded from the actual + * data in OPL3's ROM. Negative entries are marked by 0x8000. + */ +static const uint16_t logsinrom[1024*8] = { + // wave 0 + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0003, 0x0003, 0x0003, 0x0004, 0x0004, + 0x0004, 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, + 0x0007, 0x0008, 0x0008, 0x0009, 0x0009, 0x000a, 0x000a, 0x000b, + 0x000c, 0x000c, 0x000d, 0x000d, 0x000e, 0x000f, 0x000f, 0x0010, + 0x0011, 0x0011, 0x0012, 0x0013, 0x0014, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, + 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002d, 0x002e, + 0x002f, 0x0030, 0x0031, 0x0033, 0x0034, 0x0035, 0x0037, 0x0038, + 0x0039, 0x003b, 0x003c, 0x003e, 0x003f, 0x0040, 0x0042, 0x0043, + 0x0045, 0x0046, 0x0048, 0x004a, 0x004b, 0x004d, 0x004e, 0x0050, + 0x0052, 0x0053, 0x0055, 0x0057, 0x0059, 0x005b, 0x005c, 0x005e, + 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, + 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007a, 0x007d, 0x007f, + 0x0081, 0x0083, 0x0086, 0x0088, 0x008a, 0x008d, 0x008f, 0x0092, + 0x0094, 0x0097, 0x0099, 0x009c, 0x009f, 0x00a1, 0x00a4, 0x00a7, + 0x00a9, 0x00ac, 0x00af, 0x00b2, 0x00b5, 0x00b8, 0x00bb, 0x00be, + 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00d1, 0x00d4, 0x00d7, + 0x00db, 0x00de, 0x00e2, 0x00e5, 0x00e9, 0x00ec, 0x00f0, 0x00f4, + 0x00f8, 0x00fb, 0x00ff, 0x0103, 0x0107, 0x010b, 0x010f, 0x0114, + 0x0118, 0x011c, 0x0121, 0x0125, 0x0129, 0x012e, 0x0133, 0x0137, + 0x013c, 0x0141, 0x0146, 0x014b, 0x0150, 0x0155, 0x015b, 0x0160, + 0x0166, 0x016b, 0x0171, 0x0177, 0x017c, 0x0182, 0x0188, 0x018f, + 0x0195, 0x019b, 0x01a2, 0x01a9, 0x01b0, 0x01b7, 0x01be, 0x01c5, + 0x01cd, 0x01d4, 0x01dc, 0x01e4, 0x01ec, 0x01f5, 0x01fd, 0x0206, + 0x020f, 0x0218, 0x0222, 0x022c, 0x0236, 0x0240, 0x024b, 0x0256, + 0x0261, 0x026d, 0x0279, 0x0286, 0x0293, 0x02a0, 0x02af, 0x02bd, + 0x02cd, 0x02dc, 0x02ed, 0x02ff, 0x0311, 0x0324, 0x0339, 0x034e, + 0x0365, 0x037e, 0x0398, 0x03b5, 0x03d3, 0x03f5, 0x041a, 0x0443, + 0x0471, 0x04a6, 0x04e4, 0x052e, 0x058b, 0x0607, 0x06c3, 0x0859, + 0x8859, 0x86c3, 0x8607, 0x858b, 0x852e, 0x84e4, 0x84a6, 0x8471, + 0x8443, 0x841a, 0x83f5, 0x83d3, 0x83b5, 0x8398, 0x837e, 0x8365, + 0x834e, 0x8339, 0x8324, 0x8311, 0x82ff, 0x82ed, 0x82dc, 0x82cd, + 0x82bd, 0x82af, 0x82a0, 0x8293, 0x8286, 0x8279, 0x826d, 0x8261, + 0x8256, 0x824b, 0x8240, 0x8236, 0x822c, 0x8222, 0x8218, 0x820f, + 0x8206, 0x81fd, 0x81f5, 0x81ec, 0x81e4, 0x81dc, 0x81d4, 0x81cd, + 0x81c5, 0x81be, 0x81b7, 0x81b0, 0x81a9, 0x81a2, 0x819b, 0x8195, + 0x818f, 0x8188, 0x8182, 0x817c, 0x8177, 0x8171, 0x816b, 0x8166, + 0x8160, 0x815b, 0x8155, 0x8150, 0x814b, 0x8146, 0x8141, 0x813c, + 0x8137, 0x8133, 0x812e, 0x8129, 0x8125, 0x8121, 0x811c, 0x8118, + 0x8114, 0x810f, 0x810b, 0x8107, 0x8103, 0x80ff, 0x80fb, 0x80f8, + 0x80f4, 0x80f0, 0x80ec, 0x80e9, 0x80e5, 0x80e2, 0x80de, 0x80db, + 0x80d7, 0x80d4, 0x80d1, 0x80cd, 0x80ca, 0x80c7, 0x80c4, 0x80c1, + 0x80be, 0x80bb, 0x80b8, 0x80b5, 0x80b2, 0x80af, 0x80ac, 0x80a9, + 0x80a7, 0x80a4, 0x80a1, 0x809f, 0x809c, 0x8099, 0x8097, 0x8094, + 0x8092, 0x808f, 0x808d, 0x808a, 0x8088, 0x8086, 0x8083, 0x8081, + 0x807f, 0x807d, 0x807a, 0x8078, 0x8076, 0x8074, 0x8072, 0x8070, + 0x806e, 0x806c, 0x806a, 0x8068, 0x8066, 0x8064, 0x8062, 0x8060, + 0x805e, 0x805c, 0x805b, 0x8059, 0x8057, 0x8055, 0x8053, 0x8052, + 0x8050, 0x804e, 0x804d, 0x804b, 0x804a, 0x8048, 0x8046, 0x8045, + 0x8043, 0x8042, 0x8040, 0x803f, 0x803e, 0x803c, 0x803b, 0x8039, + 0x8038, 0x8037, 0x8035, 0x8034, 0x8033, 0x8031, 0x8030, 0x802f, + 0x802e, 0x802d, 0x802b, 0x802a, 0x8029, 0x8028, 0x8027, 0x8026, + 0x8025, 0x8024, 0x8023, 0x8022, 0x8021, 0x8020, 0x801f, 0x801e, + 0x801d, 0x801c, 0x801b, 0x801a, 0x8019, 0x8018, 0x8017, 0x8017, + 0x8016, 0x8015, 0x8014, 0x8014, 0x8013, 0x8012, 0x8011, 0x8011, + 0x8010, 0x800f, 0x800f, 0x800e, 0x800d, 0x800d, 0x800c, 0x800c, + 0x800b, 0x800a, 0x800a, 0x8009, 0x8009, 0x8008, 0x8008, 0x8007, + 0x8007, 0x8007, 0x8006, 0x8006, 0x8005, 0x8005, 0x8005, 0x8004, + 0x8004, 0x8004, 0x8003, 0x8003, 0x8003, 0x8002, 0x8002, 0x8002, + 0x8002, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8002, + 0x8002, 0x8002, 0x8002, 0x8003, 0x8003, 0x8003, 0x8004, 0x8004, + 0x8004, 0x8005, 0x8005, 0x8005, 0x8006, 0x8006, 0x8007, 0x8007, + 0x8007, 0x8008, 0x8008, 0x8009, 0x8009, 0x800a, 0x800a, 0x800b, + 0x800c, 0x800c, 0x800d, 0x800d, 0x800e, 0x800f, 0x800f, 0x8010, + 0x8011, 0x8011, 0x8012, 0x8013, 0x8014, 0x8014, 0x8015, 0x8016, + 0x8017, 0x8017, 0x8018, 0x8019, 0x801a, 0x801b, 0x801c, 0x801d, + 0x801e, 0x801f, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, + 0x8026, 0x8027, 0x8028, 0x8029, 0x802a, 0x802b, 0x802d, 0x802e, + 0x802f, 0x8030, 0x8031, 0x8033, 0x8034, 0x8035, 0x8037, 0x8038, + 0x8039, 0x803b, 0x803c, 0x803e, 0x803f, 0x8040, 0x8042, 0x8043, + 0x8045, 0x8046, 0x8048, 0x804a, 0x804b, 0x804d, 0x804e, 0x8050, + 0x8052, 0x8053, 0x8055, 0x8057, 0x8059, 0x805b, 0x805c, 0x805e, + 0x8060, 0x8062, 0x8064, 0x8066, 0x8068, 0x806a, 0x806c, 0x806e, + 0x8070, 0x8072, 0x8074, 0x8076, 0x8078, 0x807a, 0x807d, 0x807f, + 0x8081, 0x8083, 0x8086, 0x8088, 0x808a, 0x808d, 0x808f, 0x8092, + 0x8094, 0x8097, 0x8099, 0x809c, 0x809f, 0x80a1, 0x80a4, 0x80a7, + 0x80a9, 0x80ac, 0x80af, 0x80b2, 0x80b5, 0x80b8, 0x80bb, 0x80be, + 0x80c1, 0x80c4, 0x80c7, 0x80ca, 0x80cd, 0x80d1, 0x80d4, 0x80d7, + 0x80db, 0x80de, 0x80e2, 0x80e5, 0x80e9, 0x80ec, 0x80f0, 0x80f4, + 0x80f8, 0x80fb, 0x80ff, 0x8103, 0x8107, 0x810b, 0x810f, 0x8114, + 0x8118, 0x811c, 0x8121, 0x8125, 0x8129, 0x812e, 0x8133, 0x8137, + 0x813c, 0x8141, 0x8146, 0x814b, 0x8150, 0x8155, 0x815b, 0x8160, + 0x8166, 0x816b, 0x8171, 0x8177, 0x817c, 0x8182, 0x8188, 0x818f, + 0x8195, 0x819b, 0x81a2, 0x81a9, 0x81b0, 0x81b7, 0x81be, 0x81c5, + 0x81cd, 0x81d4, 0x81dc, 0x81e4, 0x81ec, 0x81f5, 0x81fd, 0x8206, + 0x820f, 0x8218, 0x8222, 0x822c, 0x8236, 0x8240, 0x824b, 0x8256, + 0x8261, 0x826d, 0x8279, 0x8286, 0x8293, 0x82a0, 0x82af, 0x82bd, + 0x82cd, 0x82dc, 0x82ed, 0x82ff, 0x8311, 0x8324, 0x8339, 0x834e, + 0x8365, 0x837e, 0x8398, 0x83b5, 0x83d3, 0x83f5, 0x841a, 0x8443, + 0x8471, 0x84a6, 0x84e4, 0x852e, 0x858b, 0x8607, 0x86c3, 0x8859, + // wave 1 + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0003, 0x0003, 0x0003, 0x0004, 0x0004, + 0x0004, 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, + 0x0007, 0x0008, 0x0008, 0x0009, 0x0009, 0x000a, 0x000a, 0x000b, + 0x000c, 0x000c, 0x000d, 0x000d, 0x000e, 0x000f, 0x000f, 0x0010, + 0x0011, 0x0011, 0x0012, 0x0013, 0x0014, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, + 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002d, 0x002e, + 0x002f, 0x0030, 0x0031, 0x0033, 0x0034, 0x0035, 0x0037, 0x0038, + 0x0039, 0x003b, 0x003c, 0x003e, 0x003f, 0x0040, 0x0042, 0x0043, + 0x0045, 0x0046, 0x0048, 0x004a, 0x004b, 0x004d, 0x004e, 0x0050, + 0x0052, 0x0053, 0x0055, 0x0057, 0x0059, 0x005b, 0x005c, 0x005e, + 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, + 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007a, 0x007d, 0x007f, + 0x0081, 0x0083, 0x0086, 0x0088, 0x008a, 0x008d, 0x008f, 0x0092, + 0x0094, 0x0097, 0x0099, 0x009c, 0x009f, 0x00a1, 0x00a4, 0x00a7, + 0x00a9, 0x00ac, 0x00af, 0x00b2, 0x00b5, 0x00b8, 0x00bb, 0x00be, + 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00d1, 0x00d4, 0x00d7, + 0x00db, 0x00de, 0x00e2, 0x00e5, 0x00e9, 0x00ec, 0x00f0, 0x00f4, + 0x00f8, 0x00fb, 0x00ff, 0x0103, 0x0107, 0x010b, 0x010f, 0x0114, + 0x0118, 0x011c, 0x0121, 0x0125, 0x0129, 0x012e, 0x0133, 0x0137, + 0x013c, 0x0141, 0x0146, 0x014b, 0x0150, 0x0155, 0x015b, 0x0160, + 0x0166, 0x016b, 0x0171, 0x0177, 0x017c, 0x0182, 0x0188, 0x018f, + 0x0195, 0x019b, 0x01a2, 0x01a9, 0x01b0, 0x01b7, 0x01be, 0x01c5, + 0x01cd, 0x01d4, 0x01dc, 0x01e4, 0x01ec, 0x01f5, 0x01fd, 0x0206, + 0x020f, 0x0218, 0x0222, 0x022c, 0x0236, 0x0240, 0x024b, 0x0256, + 0x0261, 0x026d, 0x0279, 0x0286, 0x0293, 0x02a0, 0x02af, 0x02bd, + 0x02cd, 0x02dc, 0x02ed, 0x02ff, 0x0311, 0x0324, 0x0339, 0x034e, + 0x0365, 0x037e, 0x0398, 0x03b5, 0x03d3, 0x03f5, 0x041a, 0x0443, + 0x0471, 0x04a6, 0x04e4, 0x052e, 0x058b, 0x0607, 0x06c3, 0x0859, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + // wave 2 + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0003, 0x0003, 0x0003, 0x0004, 0x0004, + 0x0004, 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, + 0x0007, 0x0008, 0x0008, 0x0009, 0x0009, 0x000a, 0x000a, 0x000b, + 0x000c, 0x000c, 0x000d, 0x000d, 0x000e, 0x000f, 0x000f, 0x0010, + 0x0011, 0x0011, 0x0012, 0x0013, 0x0014, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, + 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002d, 0x002e, + 0x002f, 0x0030, 0x0031, 0x0033, 0x0034, 0x0035, 0x0037, 0x0038, + 0x0039, 0x003b, 0x003c, 0x003e, 0x003f, 0x0040, 0x0042, 0x0043, + 0x0045, 0x0046, 0x0048, 0x004a, 0x004b, 0x004d, 0x004e, 0x0050, + 0x0052, 0x0053, 0x0055, 0x0057, 0x0059, 0x005b, 0x005c, 0x005e, + 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, + 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007a, 0x007d, 0x007f, + 0x0081, 0x0083, 0x0086, 0x0088, 0x008a, 0x008d, 0x008f, 0x0092, + 0x0094, 0x0097, 0x0099, 0x009c, 0x009f, 0x00a1, 0x00a4, 0x00a7, + 0x00a9, 0x00ac, 0x00af, 0x00b2, 0x00b5, 0x00b8, 0x00bb, 0x00be, + 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00d1, 0x00d4, 0x00d7, + 0x00db, 0x00de, 0x00e2, 0x00e5, 0x00e9, 0x00ec, 0x00f0, 0x00f4, + 0x00f8, 0x00fb, 0x00ff, 0x0103, 0x0107, 0x010b, 0x010f, 0x0114, + 0x0118, 0x011c, 0x0121, 0x0125, 0x0129, 0x012e, 0x0133, 0x0137, + 0x013c, 0x0141, 0x0146, 0x014b, 0x0150, 0x0155, 0x015b, 0x0160, + 0x0166, 0x016b, 0x0171, 0x0177, 0x017c, 0x0182, 0x0188, 0x018f, + 0x0195, 0x019b, 0x01a2, 0x01a9, 0x01b0, 0x01b7, 0x01be, 0x01c5, + 0x01cd, 0x01d4, 0x01dc, 0x01e4, 0x01ec, 0x01f5, 0x01fd, 0x0206, + 0x020f, 0x0218, 0x0222, 0x022c, 0x0236, 0x0240, 0x024b, 0x0256, + 0x0261, 0x026d, 0x0279, 0x0286, 0x0293, 0x02a0, 0x02af, 0x02bd, + 0x02cd, 0x02dc, 0x02ed, 0x02ff, 0x0311, 0x0324, 0x0339, 0x034e, + 0x0365, 0x037e, 0x0398, 0x03b5, 0x03d3, 0x03f5, 0x041a, 0x0443, + 0x0471, 0x04a6, 0x04e4, 0x052e, 0x058b, 0x0607, 0x06c3, 0x0859, + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0003, 0x0003, 0x0003, 0x0004, 0x0004, + 0x0004, 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, + 0x0007, 0x0008, 0x0008, 0x0009, 0x0009, 0x000a, 0x000a, 0x000b, + 0x000c, 0x000c, 0x000d, 0x000d, 0x000e, 0x000f, 0x000f, 0x0010, + 0x0011, 0x0011, 0x0012, 0x0013, 0x0014, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, + 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002d, 0x002e, + 0x002f, 0x0030, 0x0031, 0x0033, 0x0034, 0x0035, 0x0037, 0x0038, + 0x0039, 0x003b, 0x003c, 0x003e, 0x003f, 0x0040, 0x0042, 0x0043, + 0x0045, 0x0046, 0x0048, 0x004a, 0x004b, 0x004d, 0x004e, 0x0050, + 0x0052, 0x0053, 0x0055, 0x0057, 0x0059, 0x005b, 0x005c, 0x005e, + 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, + 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007a, 0x007d, 0x007f, + 0x0081, 0x0083, 0x0086, 0x0088, 0x008a, 0x008d, 0x008f, 0x0092, + 0x0094, 0x0097, 0x0099, 0x009c, 0x009f, 0x00a1, 0x00a4, 0x00a7, + 0x00a9, 0x00ac, 0x00af, 0x00b2, 0x00b5, 0x00b8, 0x00bb, 0x00be, + 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00d1, 0x00d4, 0x00d7, + 0x00db, 0x00de, 0x00e2, 0x00e5, 0x00e9, 0x00ec, 0x00f0, 0x00f4, + 0x00f8, 0x00fb, 0x00ff, 0x0103, 0x0107, 0x010b, 0x010f, 0x0114, + 0x0118, 0x011c, 0x0121, 0x0125, 0x0129, 0x012e, 0x0133, 0x0137, + 0x013c, 0x0141, 0x0146, 0x014b, 0x0150, 0x0155, 0x015b, 0x0160, + 0x0166, 0x016b, 0x0171, 0x0177, 0x017c, 0x0182, 0x0188, 0x018f, + 0x0195, 0x019b, 0x01a2, 0x01a9, 0x01b0, 0x01b7, 0x01be, 0x01c5, + 0x01cd, 0x01d4, 0x01dc, 0x01e4, 0x01ec, 0x01f5, 0x01fd, 0x0206, + 0x020f, 0x0218, 0x0222, 0x022c, 0x0236, 0x0240, 0x024b, 0x0256, + 0x0261, 0x026d, 0x0279, 0x0286, 0x0293, 0x02a0, 0x02af, 0x02bd, + 0x02cd, 0x02dc, 0x02ed, 0x02ff, 0x0311, 0x0324, 0x0339, 0x034e, + 0x0365, 0x037e, 0x0398, 0x03b5, 0x03d3, 0x03f5, 0x041a, 0x0443, + 0x0471, 0x04a6, 0x04e4, 0x052e, 0x058b, 0x0607, 0x06c3, 0x0859, + // wave 3 + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x0859, 0x06c3, 0x0607, 0x058b, 0x052e, 0x04e4, 0x04a6, 0x0471, + 0x0443, 0x041a, 0x03f5, 0x03d3, 0x03b5, 0x0398, 0x037e, 0x0365, + 0x034e, 0x0339, 0x0324, 0x0311, 0x02ff, 0x02ed, 0x02dc, 0x02cd, + 0x02bd, 0x02af, 0x02a0, 0x0293, 0x0286, 0x0279, 0x026d, 0x0261, + 0x0256, 0x024b, 0x0240, 0x0236, 0x022c, 0x0222, 0x0218, 0x020f, + 0x0206, 0x01fd, 0x01f5, 0x01ec, 0x01e4, 0x01dc, 0x01d4, 0x01cd, + 0x01c5, 0x01be, 0x01b7, 0x01b0, 0x01a9, 0x01a2, 0x019b, 0x0195, + 0x018f, 0x0188, 0x0182, 0x017c, 0x0177, 0x0171, 0x016b, 0x0166, + 0x0160, 0x015b, 0x0155, 0x0150, 0x014b, 0x0146, 0x0141, 0x013c, + 0x0137, 0x0133, 0x012e, 0x0129, 0x0125, 0x0121, 0x011c, 0x0118, + 0x0114, 0x010f, 0x010b, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f8, + 0x00f4, 0x00f0, 0x00ec, 0x00e9, 0x00e5, 0x00e2, 0x00de, 0x00db, + 0x00d7, 0x00d4, 0x00d1, 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, + 0x00be, 0x00bb, 0x00b8, 0x00b5, 0x00b2, 0x00af, 0x00ac, 0x00a9, + 0x00a7, 0x00a4, 0x00a1, 0x009f, 0x009c, 0x0099, 0x0097, 0x0094, + 0x0092, 0x008f, 0x008d, 0x008a, 0x0088, 0x0086, 0x0083, 0x0081, + 0x007f, 0x007d, 0x007a, 0x0078, 0x0076, 0x0074, 0x0072, 0x0070, + 0x006e, 0x006c, 0x006a, 0x0068, 0x0066, 0x0064, 0x0062, 0x0060, + 0x005e, 0x005c, 0x005b, 0x0059, 0x0057, 0x0055, 0x0053, 0x0052, + 0x0050, 0x004e, 0x004d, 0x004b, 0x004a, 0x0048, 0x0046, 0x0045, + 0x0043, 0x0042, 0x0040, 0x003f, 0x003e, 0x003c, 0x003b, 0x0039, + 0x0038, 0x0037, 0x0035, 0x0034, 0x0033, 0x0031, 0x0030, 0x002f, + 0x002e, 0x002d, 0x002b, 0x002a, 0x0029, 0x0028, 0x0027, 0x0026, + 0x0025, 0x0024, 0x0023, 0x0022, 0x0021, 0x0020, 0x001f, 0x001e, + 0x001d, 0x001c, 0x001b, 0x001a, 0x0019, 0x0018, 0x0017, 0x0017, + 0x0016, 0x0015, 0x0014, 0x0014, 0x0013, 0x0012, 0x0011, 0x0011, + 0x0010, 0x000f, 0x000f, 0x000e, 0x000d, 0x000d, 0x000c, 0x000c, + 0x000b, 0x000a, 0x000a, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, + 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, + 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + // wave 4 + 0x0859, 0x0607, 0x052e, 0x04a6, 0x0443, 0x03f5, 0x03b5, 0x037e, + 0x034e, 0x0324, 0x02ff, 0x02dc, 0x02bd, 0x02a0, 0x0286, 0x026d, + 0x0256, 0x0240, 0x022c, 0x0218, 0x0206, 0x01f5, 0x01e4, 0x01d4, + 0x01c5, 0x01b7, 0x01a9, 0x019b, 0x018f, 0x0182, 0x0177, 0x016b, + 0x0160, 0x0155, 0x014b, 0x0141, 0x0137, 0x012e, 0x0125, 0x011c, + 0x0114, 0x010b, 0x0103, 0x00fb, 0x00f4, 0x00ec, 0x00e5, 0x00de, + 0x00d7, 0x00d1, 0x00ca, 0x00c4, 0x00be, 0x00b8, 0x00b2, 0x00ac, + 0x00a7, 0x00a1, 0x009c, 0x0097, 0x0092, 0x008d, 0x0088, 0x0083, + 0x007f, 0x007a, 0x0076, 0x0072, 0x006e, 0x006a, 0x0066, 0x0062, + 0x005e, 0x005b, 0x0057, 0x0053, 0x0050, 0x004d, 0x004a, 0x0046, + 0x0043, 0x0040, 0x003e, 0x003b, 0x0038, 0x0035, 0x0033, 0x0030, + 0x002e, 0x002b, 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, + 0x001d, 0x001b, 0x0019, 0x0017, 0x0016, 0x0014, 0x0013, 0x0011, + 0x0010, 0x000f, 0x000d, 0x000c, 0x000b, 0x000a, 0x0009, 0x0008, + 0x0007, 0x0006, 0x0005, 0x0005, 0x0004, 0x0003, 0x0003, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0003, 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000f, 0x0010, + 0x0011, 0x0013, 0x0014, 0x0016, 0x0017, 0x0019, 0x001b, 0x001d, + 0x001f, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002b, 0x002e, + 0x0030, 0x0033, 0x0035, 0x0038, 0x003b, 0x003e, 0x0040, 0x0043, + 0x0046, 0x004a, 0x004d, 0x0050, 0x0053, 0x0057, 0x005b, 0x005e, + 0x0062, 0x0066, 0x006a, 0x006e, 0x0072, 0x0076, 0x007a, 0x007f, + 0x0083, 0x0088, 0x008d, 0x0092, 0x0097, 0x009c, 0x00a1, 0x00a7, + 0x00ac, 0x00b2, 0x00b8, 0x00be, 0x00c4, 0x00ca, 0x00d1, 0x00d7, + 0x00de, 0x00e5, 0x00ec, 0x00f4, 0x00fb, 0x0103, 0x010b, 0x0114, + 0x011c, 0x0125, 0x012e, 0x0137, 0x0141, 0x014b, 0x0155, 0x0160, + 0x016b, 0x0177, 0x0182, 0x018f, 0x019b, 0x01a9, 0x01b7, 0x01c5, + 0x01d4, 0x01e4, 0x01f5, 0x0206, 0x0218, 0x022c, 0x0240, 0x0256, + 0x026d, 0x0286, 0x02a0, 0x02bd, 0x02dc, 0x02ff, 0x0324, 0x034e, + 0x037e, 0x03b5, 0x03f5, 0x0443, 0x04a6, 0x052e, 0x0607, 0x0859, + 0x8859, 0x8607, 0x852e, 0x84a6, 0x8443, 0x83f5, 0x83b5, 0x837e, + 0x834e, 0x8324, 0x82ff, 0x82dc, 0x82bd, 0x82a0, 0x8286, 0x826d, + 0x8256, 0x8240, 0x822c, 0x8218, 0x8206, 0x81f5, 0x81e4, 0x81d4, + 0x81c5, 0x81b7, 0x81a9, 0x819b, 0x818f, 0x8182, 0x8177, 0x816b, + 0x8160, 0x8155, 0x814b, 0x8141, 0x8137, 0x812e, 0x8125, 0x811c, + 0x8114, 0x810b, 0x8103, 0x80fb, 0x80f4, 0x80ec, 0x80e5, 0x80de, + 0x80d7, 0x80d1, 0x80ca, 0x80c4, 0x80be, 0x80b8, 0x80b2, 0x80ac, + 0x80a7, 0x80a1, 0x809c, 0x8097, 0x8092, 0x808d, 0x8088, 0x8083, + 0x807f, 0x807a, 0x8076, 0x8072, 0x806e, 0x806a, 0x8066, 0x8062, + 0x805e, 0x805b, 0x8057, 0x8053, 0x8050, 0x804d, 0x804a, 0x8046, + 0x8043, 0x8040, 0x803e, 0x803b, 0x8038, 0x8035, 0x8033, 0x8030, + 0x802e, 0x802b, 0x8029, 0x8027, 0x8025, 0x8023, 0x8021, 0x801f, + 0x801d, 0x801b, 0x8019, 0x8017, 0x8016, 0x8014, 0x8013, 0x8011, + 0x8010, 0x800f, 0x800d, 0x800c, 0x800b, 0x800a, 0x8009, 0x8008, + 0x8007, 0x8006, 0x8005, 0x8005, 0x8004, 0x8003, 0x8003, 0x8002, + 0x8002, 0x8001, 0x8001, 0x8001, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8001, 0x8002, + 0x8002, 0x8003, 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, + 0x8008, 0x8009, 0x800a, 0x800b, 0x800c, 0x800d, 0x800f, 0x8010, + 0x8011, 0x8013, 0x8014, 0x8016, 0x8017, 0x8019, 0x801b, 0x801d, + 0x801f, 0x8021, 0x8023, 0x8025, 0x8027, 0x8029, 0x802b, 0x802e, + 0x8030, 0x8033, 0x8035, 0x8038, 0x803b, 0x803e, 0x8040, 0x8043, + 0x8046, 0x804a, 0x804d, 0x8050, 0x8053, 0x8057, 0x805b, 0x805e, + 0x8062, 0x8066, 0x806a, 0x806e, 0x8072, 0x8076, 0x807a, 0x807f, + 0x8083, 0x8088, 0x808d, 0x8092, 0x8097, 0x809c, 0x80a1, 0x80a7, + 0x80ac, 0x80b2, 0x80b8, 0x80be, 0x80c4, 0x80ca, 0x80d1, 0x80d7, + 0x80de, 0x80e5, 0x80ec, 0x80f4, 0x80fb, 0x8103, 0x810b, 0x8114, + 0x811c, 0x8125, 0x812e, 0x8137, 0x8141, 0x814b, 0x8155, 0x8160, + 0x816b, 0x8177, 0x8182, 0x818f, 0x819b, 0x81a9, 0x81b7, 0x81c5, + 0x81d4, 0x81e4, 0x81f5, 0x8206, 0x8218, 0x822c, 0x8240, 0x8256, + 0x826d, 0x8286, 0x82a0, 0x82bd, 0x82dc, 0x82ff, 0x8324, 0x834e, + 0x837e, 0x83b5, 0x83f5, 0x8443, 0x84a6, 0x852e, 0x8607, 0x8859, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + // wave 5 + 0x0859, 0x0607, 0x052e, 0x04a6, 0x0443, 0x03f5, 0x03b5, 0x037e, + 0x034e, 0x0324, 0x02ff, 0x02dc, 0x02bd, 0x02a0, 0x0286, 0x026d, + 0x0256, 0x0240, 0x022c, 0x0218, 0x0206, 0x01f5, 0x01e4, 0x01d4, + 0x01c5, 0x01b7, 0x01a9, 0x019b, 0x018f, 0x0182, 0x0177, 0x016b, + 0x0160, 0x0155, 0x014b, 0x0141, 0x0137, 0x012e, 0x0125, 0x011c, + 0x0114, 0x010b, 0x0103, 0x00fb, 0x00f4, 0x00ec, 0x00e5, 0x00de, + 0x00d7, 0x00d1, 0x00ca, 0x00c4, 0x00be, 0x00b8, 0x00b2, 0x00ac, + 0x00a7, 0x00a1, 0x009c, 0x0097, 0x0092, 0x008d, 0x0088, 0x0083, + 0x007f, 0x007a, 0x0076, 0x0072, 0x006e, 0x006a, 0x0066, 0x0062, + 0x005e, 0x005b, 0x0057, 0x0053, 0x0050, 0x004d, 0x004a, 0x0046, + 0x0043, 0x0040, 0x003e, 0x003b, 0x0038, 0x0035, 0x0033, 0x0030, + 0x002e, 0x002b, 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, + 0x001d, 0x001b, 0x0019, 0x0017, 0x0016, 0x0014, 0x0013, 0x0011, + 0x0010, 0x000f, 0x000d, 0x000c, 0x000b, 0x000a, 0x0009, 0x0008, + 0x0007, 0x0006, 0x0005, 0x0005, 0x0004, 0x0003, 0x0003, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0003, 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000f, 0x0010, + 0x0011, 0x0013, 0x0014, 0x0016, 0x0017, 0x0019, 0x001b, 0x001d, + 0x001f, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002b, 0x002e, + 0x0030, 0x0033, 0x0035, 0x0038, 0x003b, 0x003e, 0x0040, 0x0043, + 0x0046, 0x004a, 0x004d, 0x0050, 0x0053, 0x0057, 0x005b, 0x005e, + 0x0062, 0x0066, 0x006a, 0x006e, 0x0072, 0x0076, 0x007a, 0x007f, + 0x0083, 0x0088, 0x008d, 0x0092, 0x0097, 0x009c, 0x00a1, 0x00a7, + 0x00ac, 0x00b2, 0x00b8, 0x00be, 0x00c4, 0x00ca, 0x00d1, 0x00d7, + 0x00de, 0x00e5, 0x00ec, 0x00f4, 0x00fb, 0x0103, 0x010b, 0x0114, + 0x011c, 0x0125, 0x012e, 0x0137, 0x0141, 0x014b, 0x0155, 0x0160, + 0x016b, 0x0177, 0x0182, 0x018f, 0x019b, 0x01a9, 0x01b7, 0x01c5, + 0x01d4, 0x01e4, 0x01f5, 0x0206, 0x0218, 0x022c, 0x0240, 0x0256, + 0x026d, 0x0286, 0x02a0, 0x02bd, 0x02dc, 0x02ff, 0x0324, 0x034e, + 0x037e, 0x03b5, 0x03f5, 0x0443, 0x04a6, 0x052e, 0x0607, 0x0859, + 0x0859, 0x0607, 0x052e, 0x04a6, 0x0443, 0x03f5, 0x03b5, 0x037e, + 0x034e, 0x0324, 0x02ff, 0x02dc, 0x02bd, 0x02a0, 0x0286, 0x026d, + 0x0256, 0x0240, 0x022c, 0x0218, 0x0206, 0x01f5, 0x01e4, 0x01d4, + 0x01c5, 0x01b7, 0x01a9, 0x019b, 0x018f, 0x0182, 0x0177, 0x016b, + 0x0160, 0x0155, 0x014b, 0x0141, 0x0137, 0x012e, 0x0125, 0x011c, + 0x0114, 0x010b, 0x0103, 0x00fb, 0x00f4, 0x00ec, 0x00e5, 0x00de, + 0x00d7, 0x00d1, 0x00ca, 0x00c4, 0x00be, 0x00b8, 0x00b2, 0x00ac, + 0x00a7, 0x00a1, 0x009c, 0x0097, 0x0092, 0x008d, 0x0088, 0x0083, + 0x007f, 0x007a, 0x0076, 0x0072, 0x006e, 0x006a, 0x0066, 0x0062, + 0x005e, 0x005b, 0x0057, 0x0053, 0x0050, 0x004d, 0x004a, 0x0046, + 0x0043, 0x0040, 0x003e, 0x003b, 0x0038, 0x0035, 0x0033, 0x0030, + 0x002e, 0x002b, 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, + 0x001d, 0x001b, 0x0019, 0x0017, 0x0016, 0x0014, 0x0013, 0x0011, + 0x0010, 0x000f, 0x000d, 0x000c, 0x000b, 0x000a, 0x0009, 0x0008, + 0x0007, 0x0006, 0x0005, 0x0005, 0x0004, 0x0003, 0x0003, 0x0002, + 0x0002, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0002, + 0x0002, 0x0003, 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000f, 0x0010, + 0x0011, 0x0013, 0x0014, 0x0016, 0x0017, 0x0019, 0x001b, 0x001d, + 0x001f, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002b, 0x002e, + 0x0030, 0x0033, 0x0035, 0x0038, 0x003b, 0x003e, 0x0040, 0x0043, + 0x0046, 0x004a, 0x004d, 0x0050, 0x0053, 0x0057, 0x005b, 0x005e, + 0x0062, 0x0066, 0x006a, 0x006e, 0x0072, 0x0076, 0x007a, 0x007f, + 0x0083, 0x0088, 0x008d, 0x0092, 0x0097, 0x009c, 0x00a1, 0x00a7, + 0x00ac, 0x00b2, 0x00b8, 0x00be, 0x00c4, 0x00ca, 0x00d1, 0x00d7, + 0x00de, 0x00e5, 0x00ec, 0x00f4, 0x00fb, 0x0103, 0x010b, 0x0114, + 0x011c, 0x0125, 0x012e, 0x0137, 0x0141, 0x014b, 0x0155, 0x0160, + 0x016b, 0x0177, 0x0182, 0x018f, 0x019b, 0x01a9, 0x01b7, 0x01c5, + 0x01d4, 0x01e4, 0x01f5, 0x0206, 0x0218, 0x022c, 0x0240, 0x0256, + 0x026d, 0x0286, 0x02a0, 0x02bd, 0x02dc, 0x02ff, 0x0324, 0x034e, + 0x037e, 0x03b5, 0x03f5, 0x0443, 0x04a6, 0x052e, 0x0607, 0x0859, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + // wave 6 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + // wave 7 + 0x0000, 0x0008, 0x0010, 0x0018, 0x0020, 0x0028, 0x0030, 0x0038, + 0x0040, 0x0048, 0x0050, 0x0058, 0x0060, 0x0068, 0x0070, 0x0078, + 0x0080, 0x0088, 0x0090, 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x00b8, + 0x00c0, 0x00c8, 0x00d0, 0x00d8, 0x00e0, 0x00e8, 0x00f0, 0x00f8, + 0x0100, 0x0108, 0x0110, 0x0118, 0x0120, 0x0128, 0x0130, 0x0138, + 0x0140, 0x0148, 0x0150, 0x0158, 0x0160, 0x0168, 0x0170, 0x0178, + 0x0180, 0x0188, 0x0190, 0x0198, 0x01a0, 0x01a8, 0x01b0, 0x01b8, + 0x01c0, 0x01c8, 0x01d0, 0x01d8, 0x01e0, 0x01e8, 0x01f0, 0x01f8, + 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, 0x0238, + 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, + 0x0280, 0x0288, 0x0290, 0x0298, 0x02a0, 0x02a8, 0x02b0, 0x02b8, + 0x02c0, 0x02c8, 0x02d0, 0x02d8, 0x02e0, 0x02e8, 0x02f0, 0x02f8, + 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, + 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, + 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, + 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8, + 0x0400, 0x0408, 0x0410, 0x0418, 0x0420, 0x0428, 0x0430, 0x0438, + 0x0440, 0x0448, 0x0450, 0x0458, 0x0460, 0x0468, 0x0470, 0x0478, + 0x0480, 0x0488, 0x0490, 0x0498, 0x04a0, 0x04a8, 0x04b0, 0x04b8, + 0x04c0, 0x04c8, 0x04d0, 0x04d8, 0x04e0, 0x04e8, 0x04f0, 0x04f8, + 0x0500, 0x0508, 0x0510, 0x0518, 0x0520, 0x0528, 0x0530, 0x0538, + 0x0540, 0x0548, 0x0550, 0x0558, 0x0560, 0x0568, 0x0570, 0x0578, + 0x0580, 0x0588, 0x0590, 0x0598, 0x05a0, 0x05a8, 0x05b0, 0x05b8, + 0x05c0, 0x05c8, 0x05d0, 0x05d8, 0x05e0, 0x05e8, 0x05f0, 0x05f8, + 0x0600, 0x0608, 0x0610, 0x0618, 0x0620, 0x0628, 0x0630, 0x0638, + 0x0640, 0x0648, 0x0650, 0x0658, 0x0660, 0x0668, 0x0670, 0x0678, + 0x0680, 0x0688, 0x0690, 0x0698, 0x06a0, 0x06a8, 0x06b0, 0x06b8, + 0x06c0, 0x06c8, 0x06d0, 0x06d8, 0x06e0, 0x06e8, 0x06f0, 0x06f8, + 0x0700, 0x0708, 0x0710, 0x0718, 0x0720, 0x0728, 0x0730, 0x0738, + 0x0740, 0x0748, 0x0750, 0x0758, 0x0760, 0x0768, 0x0770, 0x0778, + 0x0780, 0x0788, 0x0790, 0x0798, 0x07a0, 0x07a8, 0x07b0, 0x07b8, + 0x07c0, 0x07c8, 0x07d0, 0x07d8, 0x07e0, 0x07e8, 0x07f0, 0x07f8, + 0x0800, 0x0808, 0x0810, 0x0818, 0x0820, 0x0828, 0x0830, 0x0838, + 0x0840, 0x0848, 0x0850, 0x0858, 0x0860, 0x0868, 0x0870, 0x0878, + 0x0880, 0x0888, 0x0890, 0x0898, 0x08a0, 0x08a8, 0x08b0, 0x08b8, + 0x08c0, 0x08c8, 0x08d0, 0x08d8, 0x08e0, 0x08e8, 0x08f0, 0x08f8, + 0x0900, 0x0908, 0x0910, 0x0918, 0x0920, 0x0928, 0x0930, 0x0938, + 0x0940, 0x0948, 0x0950, 0x0958, 0x0960, 0x0968, 0x0970, 0x0978, + 0x0980, 0x0988, 0x0990, 0x0998, 0x09a0, 0x09a8, 0x09b0, 0x09b8, + 0x09c0, 0x09c8, 0x09d0, 0x09d8, 0x09e0, 0x09e8, 0x09f0, 0x09f8, + 0x0a00, 0x0a08, 0x0a10, 0x0a18, 0x0a20, 0x0a28, 0x0a30, 0x0a38, + 0x0a40, 0x0a48, 0x0a50, 0x0a58, 0x0a60, 0x0a68, 0x0a70, 0x0a78, + 0x0a80, 0x0a88, 0x0a90, 0x0a98, 0x0aa0, 0x0aa8, 0x0ab0, 0x0ab8, + 0x0ac0, 0x0ac8, 0x0ad0, 0x0ad8, 0x0ae0, 0x0ae8, 0x0af0, 0x0af8, + 0x0b00, 0x0b08, 0x0b10, 0x0b18, 0x0b20, 0x0b28, 0x0b30, 0x0b38, + 0x0b40, 0x0b48, 0x0b50, 0x0b58, 0x0b60, 0x0b68, 0x0b70, 0x0b78, + 0x0b80, 0x0b88, 0x0b90, 0x0b98, 0x0ba0, 0x0ba8, 0x0bb0, 0x0bb8, + 0x0bc0, 0x0bc8, 0x0bd0, 0x0bd8, 0x0be0, 0x0be8, 0x0bf0, 0x0bf8, + 0x0c00, 0x0c08, 0x0c10, 0x0c18, 0x0c20, 0x0c28, 0x0c30, 0x0c38, + 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68, 0x0c70, 0x0c78, + 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0, 0x0cb8, + 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8, + 0x0d00, 0x0d08, 0x0d10, 0x0d18, 0x0d20, 0x0d28, 0x0d30, 0x0d38, + 0x0d40, 0x0d48, 0x0d50, 0x0d58, 0x0d60, 0x0d68, 0x0d70, 0x0d78, + 0x0d80, 0x0d88, 0x0d90, 0x0d98, 0x0da0, 0x0da8, 0x0db0, 0x0db8, + 0x0dc0, 0x0dc8, 0x0dd0, 0x0dd8, 0x0de0, 0x0de8, 0x0df0, 0x0df8, + 0x0e00, 0x0e08, 0x0e10, 0x0e18, 0x0e20, 0x0e28, 0x0e30, 0x0e38, + 0x0e40, 0x0e48, 0x0e50, 0x0e58, 0x0e60, 0x0e68, 0x0e70, 0x0e78, + 0x0e80, 0x0e88, 0x0e90, 0x0e98, 0x0ea0, 0x0ea8, 0x0eb0, 0x0eb8, + 0x0ec0, 0x0ec8, 0x0ed0, 0x0ed8, 0x0ee0, 0x0ee8, 0x0ef0, 0x0ef8, + 0x0f00, 0x0f08, 0x0f10, 0x0f18, 0x0f20, 0x0f28, 0x0f30, 0x0f38, + 0x0f40, 0x0f48, 0x0f50, 0x0f58, 0x0f60, 0x0f68, 0x0f70, 0x0f78, + 0x0f80, 0x0f88, 0x0f90, 0x0f98, 0x0fa0, 0x0fa8, 0x0fb0, 0x0fb8, + 0x0fc0, 0x0fc8, 0x0fd0, 0x0fd8, 0x0fe0, 0x0fe8, 0x0ff0, 0x0ff8, + 0x8ff8, 0x8ff0, 0x8fe8, 0x8fe0, 0x8fd8, 0x8fd0, 0x8fc8, 0x8fc0, + 0x8fb8, 0x8fb0, 0x8fa8, 0x8fa0, 0x8f98, 0x8f90, 0x8f88, 0x8f80, + 0x8f78, 0x8f70, 0x8f68, 0x8f60, 0x8f58, 0x8f50, 0x8f48, 0x8f40, + 0x8f38, 0x8f30, 0x8f28, 0x8f20, 0x8f18, 0x8f10, 0x8f08, 0x8f00, + 0x8ef8, 0x8ef0, 0x8ee8, 0x8ee0, 0x8ed8, 0x8ed0, 0x8ec8, 0x8ec0, + 0x8eb8, 0x8eb0, 0x8ea8, 0x8ea0, 0x8e98, 0x8e90, 0x8e88, 0x8e80, + 0x8e78, 0x8e70, 0x8e68, 0x8e60, 0x8e58, 0x8e50, 0x8e48, 0x8e40, + 0x8e38, 0x8e30, 0x8e28, 0x8e20, 0x8e18, 0x8e10, 0x8e08, 0x8e00, + 0x8df8, 0x8df0, 0x8de8, 0x8de0, 0x8dd8, 0x8dd0, 0x8dc8, 0x8dc0, + 0x8db8, 0x8db0, 0x8da8, 0x8da0, 0x8d98, 0x8d90, 0x8d88, 0x8d80, + 0x8d78, 0x8d70, 0x8d68, 0x8d60, 0x8d58, 0x8d50, 0x8d48, 0x8d40, + 0x8d38, 0x8d30, 0x8d28, 0x8d20, 0x8d18, 0x8d10, 0x8d08, 0x8d00, + 0x8cf8, 0x8cf0, 0x8ce8, 0x8ce0, 0x8cd8, 0x8cd0, 0x8cc8, 0x8cc0, + 0x8cb8, 0x8cb0, 0x8ca8, 0x8ca0, 0x8c98, 0x8c90, 0x8c88, 0x8c80, + 0x8c78, 0x8c70, 0x8c68, 0x8c60, 0x8c58, 0x8c50, 0x8c48, 0x8c40, + 0x8c38, 0x8c30, 0x8c28, 0x8c20, 0x8c18, 0x8c10, 0x8c08, 0x8c00, + 0x8bf8, 0x8bf0, 0x8be8, 0x8be0, 0x8bd8, 0x8bd0, 0x8bc8, 0x8bc0, + 0x8bb8, 0x8bb0, 0x8ba8, 0x8ba0, 0x8b98, 0x8b90, 0x8b88, 0x8b80, + 0x8b78, 0x8b70, 0x8b68, 0x8b60, 0x8b58, 0x8b50, 0x8b48, 0x8b40, + 0x8b38, 0x8b30, 0x8b28, 0x8b20, 0x8b18, 0x8b10, 0x8b08, 0x8b00, + 0x8af8, 0x8af0, 0x8ae8, 0x8ae0, 0x8ad8, 0x8ad0, 0x8ac8, 0x8ac0, + 0x8ab8, 0x8ab0, 0x8aa8, 0x8aa0, 0x8a98, 0x8a90, 0x8a88, 0x8a80, + 0x8a78, 0x8a70, 0x8a68, 0x8a60, 0x8a58, 0x8a50, 0x8a48, 0x8a40, + 0x8a38, 0x8a30, 0x8a28, 0x8a20, 0x8a18, 0x8a10, 0x8a08, 0x8a00, + 0x89f8, 0x89f0, 0x89e8, 0x89e0, 0x89d8, 0x89d0, 0x89c8, 0x89c0, + 0x89b8, 0x89b0, 0x89a8, 0x89a0, 0x8998, 0x8990, 0x8988, 0x8980, + 0x8978, 0x8970, 0x8968, 0x8960, 0x8958, 0x8950, 0x8948, 0x8940, + 0x8938, 0x8930, 0x8928, 0x8920, 0x8918, 0x8910, 0x8908, 0x8900, + 0x88f8, 0x88f0, 0x88e8, 0x88e0, 0x88d8, 0x88d0, 0x88c8, 0x88c0, + 0x88b8, 0x88b0, 0x88a8, 0x88a0, 0x8898, 0x8890, 0x8888, 0x8880, + 0x8878, 0x8870, 0x8868, 0x8860, 0x8858, 0x8850, 0x8848, 0x8840, + 0x8838, 0x8830, 0x8828, 0x8820, 0x8818, 0x8810, 0x8808, 0x8800, + 0x87f8, 0x87f0, 0x87e8, 0x87e0, 0x87d8, 0x87d0, 0x87c8, 0x87c0, + 0x87b8, 0x87b0, 0x87a8, 0x87a0, 0x8798, 0x8790, 0x8788, 0x8780, + 0x8778, 0x8770, 0x8768, 0x8760, 0x8758, 0x8750, 0x8748, 0x8740, + 0x8738, 0x8730, 0x8728, 0x8720, 0x8718, 0x8710, 0x8708, 0x8700, + 0x86f8, 0x86f0, 0x86e8, 0x86e0, 0x86d8, 0x86d0, 0x86c8, 0x86c0, + 0x86b8, 0x86b0, 0x86a8, 0x86a0, 0x8698, 0x8690, 0x8688, 0x8680, + 0x8678, 0x8670, 0x8668, 0x8660, 0x8658, 0x8650, 0x8648, 0x8640, + 0x8638, 0x8630, 0x8628, 0x8620, 0x8618, 0x8610, 0x8608, 0x8600, + 0x85f8, 0x85f0, 0x85e8, 0x85e0, 0x85d8, 0x85d0, 0x85c8, 0x85c0, + 0x85b8, 0x85b0, 0x85a8, 0x85a0, 0x8598, 0x8590, 0x8588, 0x8580, + 0x8578, 0x8570, 0x8568, 0x8560, 0x8558, 0x8550, 0x8548, 0x8540, + 0x8538, 0x8530, 0x8528, 0x8520, 0x8518, 0x8510, 0x8508, 0x8500, + 0x84f8, 0x84f0, 0x84e8, 0x84e0, 0x84d8, 0x84d0, 0x84c8, 0x84c0, + 0x84b8, 0x84b0, 0x84a8, 0x84a0, 0x8498, 0x8490, 0x8488, 0x8480, + 0x8478, 0x8470, 0x8468, 0x8460, 0x8458, 0x8450, 0x8448, 0x8440, + 0x8438, 0x8430, 0x8428, 0x8420, 0x8418, 0x8410, 0x8408, 0x8400, + 0x83f8, 0x83f0, 0x83e8, 0x83e0, 0x83d8, 0x83d0, 0x83c8, 0x83c0, + 0x83b8, 0x83b0, 0x83a8, 0x83a0, 0x8398, 0x8390, 0x8388, 0x8380, + 0x8378, 0x8370, 0x8368, 0x8360, 0x8358, 0x8350, 0x8348, 0x8340, + 0x8338, 0x8330, 0x8328, 0x8320, 0x8318, 0x8310, 0x8308, 0x8300, + 0x82f8, 0x82f0, 0x82e8, 0x82e0, 0x82d8, 0x82d0, 0x82c8, 0x82c0, + 0x82b8, 0x82b0, 0x82a8, 0x82a0, 0x8298, 0x8290, 0x8288, 0x8280, + 0x8278, 0x8270, 0x8268, 0x8260, 0x8258, 0x8250, 0x8248, 0x8240, + 0x8238, 0x8230, 0x8228, 0x8220, 0x8218, 0x8210, 0x8208, 0x8200, + 0x81f8, 0x81f0, 0x81e8, 0x81e0, 0x81d8, 0x81d0, 0x81c8, 0x81c0, + 0x81b8, 0x81b0, 0x81a8, 0x81a0, 0x8198, 0x8190, 0x8188, 0x8180, + 0x8178, 0x8170, 0x8168, 0x8160, 0x8158, 0x8150, 0x8148, 0x8140, + 0x8138, 0x8130, 0x8128, 0x8120, 0x8118, 0x8110, 0x8108, 0x8100, + 0x80f8, 0x80f0, 0x80e8, 0x80e0, 0x80d8, 0x80d0, 0x80c8, 0x80c0, + 0x80b8, 0x80b0, 0x80a8, 0x80a0, 0x8098, 0x8090, 0x8088, 0x8080, + 0x8078, 0x8070, 0x8068, 0x8060, 0x8058, 0x8050, 0x8048, 0x8040, + 0x8038, 0x8030, 0x8028, 0x8020, 0x8018, 0x8010, 0x8008, 0x8000, +}; + +/* + * Inverse exponent table extracted from OPL3 ROM; taken straight from + * Nuked OPL3 source code. + * TODO: Verify if ESFM uses an exponent table or if it possibly uses another + * method to skirt around Yamaha's patents? + * Optimization: All entries are shifted left by one from the actual data in + * OPL3's ROM. + */ +static const uint16_t exprom[256] = { + 0xff4, 0xfea, 0xfde, 0xfd4, 0xfc8, 0xfbe, 0xfb4, 0xfa8, + 0xf9e, 0xf92, 0xf88, 0xf7e, 0xf72, 0xf68, 0xf5c, 0xf52, + 0xf48, 0xf3e, 0xf32, 0xf28, 0xf1e, 0xf14, 0xf08, 0xefe, + 0xef4, 0xeea, 0xee0, 0xed4, 0xeca, 0xec0, 0xeb6, 0xeac, + 0xea2, 0xe98, 0xe8e, 0xe84, 0xe7a, 0xe70, 0xe66, 0xe5c, + 0xe52, 0xe48, 0xe3e, 0xe34, 0xe2a, 0xe20, 0xe16, 0xe0c, + 0xe04, 0xdfa, 0xdf0, 0xde6, 0xddc, 0xdd2, 0xdca, 0xdc0, + 0xdb6, 0xdac, 0xda4, 0xd9a, 0xd90, 0xd88, 0xd7e, 0xd74, + 0xd6a, 0xd62, 0xd58, 0xd50, 0xd46, 0xd3c, 0xd34, 0xd2a, + 0xd22, 0xd18, 0xd10, 0xd06, 0xcfe, 0xcf4, 0xcec, 0xce2, + 0xcda, 0xcd0, 0xcc8, 0xcbe, 0xcb6, 0xcae, 0xca4, 0xc9c, + 0xc92, 0xc8a, 0xc82, 0xc78, 0xc70, 0xc68, 0xc60, 0xc56, + 0xc4e, 0xc46, 0xc3c, 0xc34, 0xc2c, 0xc24, 0xc1c, 0xc12, + 0xc0a, 0xc02, 0xbfa, 0xbf2, 0xbea, 0xbe0, 0xbd8, 0xbd0, + 0xbc8, 0xbc0, 0xbb8, 0xbb0, 0xba8, 0xba0, 0xb98, 0xb90, + 0xb88, 0xb80, 0xb78, 0xb70, 0xb68, 0xb60, 0xb58, 0xb50, + 0xb48, 0xb40, 0xb38, 0xb32, 0xb2a, 0xb22, 0xb1a, 0xb12, + 0xb0a, 0xb02, 0xafc, 0xaf4, 0xaec, 0xae4, 0xade, 0xad6, + 0xace, 0xac6, 0xac0, 0xab8, 0xab0, 0xaa8, 0xaa2, 0xa9a, + 0xa92, 0xa8c, 0xa84, 0xa7c, 0xa76, 0xa6e, 0xa68, 0xa60, + 0xa58, 0xa52, 0xa4a, 0xa44, 0xa3c, 0xa36, 0xa2e, 0xa28, + 0xa20, 0xa18, 0xa12, 0xa0c, 0xa04, 0x9fe, 0x9f6, 0x9f0, + 0x9e8, 0x9e2, 0x9da, 0x9d4, 0x9ce, 0x9c6, 0x9c0, 0x9b8, + 0x9b2, 0x9ac, 0x9a4, 0x99e, 0x998, 0x990, 0x98a, 0x984, + 0x97c, 0x976, 0x970, 0x96a, 0x962, 0x95c, 0x956, 0x950, + 0x948, 0x942, 0x93c, 0x936, 0x930, 0x928, 0x922, 0x91c, + 0x916, 0x910, 0x90a, 0x904, 0x8fc, 0x8f6, 0x8f0, 0x8ea, + 0x8e4, 0x8de, 0x8d8, 0x8d2, 0x8cc, 0x8c6, 0x8c0, 0x8ba, + 0x8b4, 0x8ae, 0x8a8, 0x8a2, 0x89c, 0x896, 0x890, 0x88a, + 0x884, 0x87e, 0x878, 0x872, 0x86c, 0x866, 0x860, 0x85a, + 0x854, 0x850, 0x84a, 0x844, 0x83e, 0x838, 0x832, 0x82c, + 0x828, 0x822, 0x81c, 0x816, 0x810, 0x80c, 0x806, 0x800 +}; + +/* + * Frequency multiplier table multiplied by 2; taken straight from Nuked OPL3 + * source code. + */ +static const uint8_t mt[16] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 +}; + +/* + * This is used during the envelope generation to apply KSL to the envelope by + * determining how much to shift right the keyscale attenuation value before + * adding it to the envelope level. + */ +static const uint8_t kslshift[4] = { + 8, 1, 2, 0 +}; + +/* + * This encodes which emulation mode channels are the secondary channel in a + * 4-op channel pair (where the entry is non-negative), and which is the + * corresponding primary channel for that secondary channel. + */ +static const int emu_4op_secondary_to_primary[18] = +{ + -1, -1, -1, 0, 1, 2, -1, -1, -1, + -1, -1, -1, 9, 10, 11, -1, -1, -1 +}; + +/* + * Envelope generator dither table, taken straight from Nuked OPL3 source code. + */ +static const uint8_t eg_incstep[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } +}; + +/* ------------------------------------------------------------------------- */ +static inline int13 +ESFM_envelope_wavegen(uint3 waveform, int16 phase, uint10 envelope) +{ + int13 out; + uint16 lookup = logsinrom[((uint16)waveform << 10) | (phase & 0x3ff)]; + uint16 level = (lookup & 0x1fff) + (envelope << 3); + if (level > 0x1fff) + { + level = 0x1fff; + } + out = exprom[level & 0xff] >> (level >> 8); + if (lookup & 0x8000) + { + out = -out; + } + return out; +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_envelope_calc(esfm_slot *slot) +{ + uint8 nonzero; + uint8 rate; + uint5 rate_hi; + uint2 rate_lo; + uint4 reg_rate = 0; + uint4 ks; + uint8 eg_shift, shift; + bool eg_off; + uint9 eg_rout; + int16 eg_inc; + bool reset = 0; + bool key_on; + bool key_on_signal; + + key_on = *slot->in.key_on; + if (!slot->chip->native_mode) + { + int pair_primary_idx = emu_4op_secondary_to_primary[slot->channel->channel_idx]; + if (pair_primary_idx >= 0) + { + esfm_channel *pair_primary = &slot->channel->chip->channels[pair_primary_idx]; + if (pair_primary->emu_mode_4op_enable) + { + key_on = *pair_primary->slots[0].in.key_on; + } + } + else if ((slot->channel->channel_idx == 7 || slot->channel->channel_idx == 8) + && slot->slot_idx == 1) + { + key_on = slot->channel->key_on_2; + } + } + + slot->in.eg_output = slot->in.eg_position + (slot->t_level << 2) + + (slot->in.eg_ksl_offset >> kslshift[slot->ksl]); + if (slot->tremolo_en) + { + uint8 tremolo; + if (slot->chip->native_mode) + { + tremolo = slot->channel->chip->tremolo >> ((!slot->tremolo_deep << 1) + 2); + } + else + { + tremolo = slot->channel->chip->tremolo >> ((!slot->chip->emu_tremolo_deep << 1) + 2); + } + slot->in.eg_output += tremolo; + } + + if (slot->in.eg_delay_run && slot->in.eg_delay_counter < 32768) + { + slot->in.eg_delay_counter++; + } + + // triggers on key-on edge + if (key_on && !slot->in.key_on_gate) + { + slot->in.eg_delay_run = 1; + slot->in.eg_delay_counter = 0; + slot->in.eg_delay_transitioned_01 = 0; + slot->in.eg_delay_transitioned_01_gate = 0; + slot->in.eg_delay_transitioned_10 = 0; + slot->in.eg_delay_transitioned_10_gate = 0; + slot->in.eg_delay_counter_compare = 0; + if (slot->env_delay > 0) + { + slot->in.eg_delay_counter_compare = 256 << slot->env_delay; + } + } + else if (!key_on) + { + slot->in.eg_delay_run = 0; + } + + // TODO: is this really how the chip behaves? Can it only transition the envelope delay once? Am I implementing this in a sane way? I feel like this is a roundabout hack. + if ((slot->in.eg_delay_transitioned_10 && !slot->in.eg_delay_transitioned_10_gate) || + (slot->in.eg_delay_transitioned_01 && !slot->in.eg_delay_transitioned_01_gate) + ) + { + slot->in.eg_delay_counter_compare = 0; + if (slot->env_delay > 0) + { + slot->in.eg_delay_counter_compare = 256 << slot->env_delay; + } + if (slot->in.eg_delay_transitioned_10) + { + slot->in.eg_delay_transitioned_10_gate = 1; + } + if (slot->in.eg_delay_transitioned_01) + { + slot->in.eg_delay_transitioned_01_gate = 1; + } + } + + if (key_on && ((slot->in.eg_delay_counter >= slot->in.eg_delay_counter_compare) || !slot->chip->native_mode)) + { + key_on_signal = 1; + } else { + key_on_signal = 0; + } + + if (key_on && slot->in.eg_state == EG_RELEASE) + { + + if ((slot->in.eg_delay_counter >= slot->in.eg_delay_counter_compare) || !slot->chip->native_mode) + { + reset = 1; + reg_rate = slot->attack_rate; + } + else + { + reg_rate = slot->release_rate; + } + } + else + { + switch (slot->in.eg_state) + { + case EG_ATTACK: + reg_rate = slot->attack_rate; + break; + case EG_DECAY: + reg_rate = slot->decay_rate; + break; + case EG_SUSTAIN: + if (!slot->env_sustaining) + { + reg_rate = slot->release_rate; + } + break; + case EG_RELEASE: + reg_rate = slot->release_rate; + break; + } + } + slot->in.key_on_gate = key_on; + slot->in.phase_reset = reset; + ks = slot->in.keyscale >> ((!slot->ksr) << 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; + } + eg_shift = rate_hi + slot->chip->eg_clocks; + shift = 0; + if (nonzero) + { + if (rate_hi < 12) + { + if (slot->chip->eg_tick) + { + switch (eg_shift) + { + case 12: + shift = 1; + break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; + case 14: + shift = rate_lo & 0x01; + break; + default: + break; + } + } + } + else + { + shift = (rate_hi & 0x03) + + eg_incstep[rate_lo][slot->chip->global_timer & 0x03]; + if (shift & 0x04) + { + shift = 0x03; + } + if (!shift) + { + shift = slot->chip->eg_tick; + } + } + } + eg_rout = slot->in.eg_position; + eg_inc = 0; + eg_off = 0; + /* Instant attack */ + if (reset && rate_hi == 0x0f) + { + eg_rout = 0x00; + } + /* Envelope off */ + if ((slot->in.eg_position & 0x1f8) == 0x1f8) + { + eg_off = 1; + } + if (slot->in.eg_state != EG_ATTACK && !reset && eg_off) + { + eg_rout = 0x1ff; + } + switch (slot->in.eg_state) + { + case EG_ATTACK: + if (slot->in.eg_position == 0) + { + slot->in.eg_state = EG_DECAY; + } + else if (key_on_signal && shift > 0 && rate_hi != 0x0f) + { + eg_inc = ~slot->in.eg_position >> (4 - shift); + } + break; + case EG_DECAY: + if ((slot->in.eg_position >> 4) == slot->sustain_lvl) + { + slot->in.eg_state = EG_SUSTAIN; + } + else if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + case EG_SUSTAIN: + case EG_RELEASE: + if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + } + slot->in.eg_position = (eg_rout + eg_inc) & 0x1ff; + /* Key off */ + if (reset) + { + slot->in.eg_state = EG_ATTACK; + } + if (!key_on_signal) + { + slot->in.eg_state = EG_RELEASE; + } +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_phase_generate(esfm_slot *slot) +{ + esfm_chip *chip; + uint10 f_num; + uint32 basefreq; + bool rm_xor, n_bit; + uint23 noise; + uint10 phase; + + chip = slot->chip; + f_num = slot->f_num; + if (slot->vibrato_en) + { + int8_t range; + uint8_t vibpos; + + range = (f_num >> 7) & 7; + vibpos = chip->vibrato_pos; + + if (!(vibpos & 3)) + { + range = 0; + } + else if (vibpos & 1) + { + range >>= 1; + } + range >>= !slot->vibrato_deep; + + if (vibpos & 4) + { + range = -range; + } + f_num += range; + } + basefreq = (f_num << slot->block) >> 1; + phase = (uint10)(slot->in.phase_acc >> 9); + if (slot->in.phase_reset) + { + slot->in.phase_acc = 0; + } + slot->in.phase_acc += (basefreq * mt[slot->mult]) >> 1; + slot->in.phase_acc &= (1 << 19) - 1; + slot->in.phase_out = phase; + /* Noise mode (rhythm) sounds */ + noise = chip->lfsr; + if (slot->slot_idx == 3 && slot->rhy_noise) + { + esfm_slot *prev_slot = &slot->channel->slots[2]; + + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + + chip->rm_tc_bit3 = (prev_slot->in.phase_out >> 3) & 1; + chip->rm_tc_bit5 = (prev_slot->in.phase_out >> 5) & 1; + + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + + switch(slot->rhy_noise) + { + case 1: + // SD + slot->in.phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + break; + case 2: + // HH + slot->in.phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->in.phase_out |= 0xd0; + } + else + { + slot->in.phase_out |= 0x34; + } + break; + case 3: + // TC + slot->in.phase_out = (rm_xor << 9) | 0x80; + break; + } + } + + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->lfsr = (noise >> 1) | (n_bit << 22); +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_phase_generate_emu(esfm_slot *slot) +{ + esfm_chip *chip; + uint3 block; + uint10 f_num; + uint32 basefreq; + bool rm_xor, n_bit; + uint23 noise; + uint10 phase; + int pair_primary_idx; + + chip = slot->chip; + block = slot->channel->slots[0].block; + f_num = slot->channel->slots[0].f_num; + + pair_primary_idx = emu_4op_secondary_to_primary[slot->channel->channel_idx]; + if (pair_primary_idx >= 0) + { + esfm_channel *pair_primary = &slot->channel->chip->channels[pair_primary_idx]; + if (pair_primary->emu_mode_4op_enable) + { + block = pair_primary->slots[0].block; + f_num = pair_primary->slots[0].f_num; + } + } + + if (slot->vibrato_en) + { + int8_t range; + uint8_t vibpos; + + range = (f_num >> 7) & 7; + vibpos = chip->vibrato_pos; + + if (!(vibpos & 3)) + { + range = 0; + } + else if (vibpos & 1) + { + range >>= 1; + } + range >>= !chip->emu_vibrato_deep; + + if (vibpos & 4) + { + range = -range; + } + f_num += range; + } + basefreq = (f_num << block) >> 1; + phase = (uint10)(slot->in.phase_acc >> 9); + if (slot->in.phase_reset) + { + slot->in.phase_acc = 0; + } + slot->in.phase_acc += (basefreq * mt[slot->mult]) >> 1; + slot->in.phase_acc &= (1 << 19) - 1; + slot->in.phase_out = phase; + + /* Noise mode (rhythm) sounds */ + noise = chip->lfsr; + // HH + if (slot->channel->channel_idx == 7 && slot->slot_idx == 0) + { + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + } + // TC + if (slot->channel->channel_idx == 8 && slot->slot_idx == 1) + { + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; + } + if (chip->emu_rhy_mode_flags & 0x20) + { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + if (slot->channel->channel_idx == 7) + { + if (slot->slot_idx == 0) { + // HH + slot->in.phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->in.phase_out |= 0xd0; + } + else + { + slot->in.phase_out |= 0x34; + } + } + else if (slot->slot_idx == 1) + { + // SD + slot->in.phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + } + } + else if (slot->channel->channel_idx == 8 && slot->slot_idx == 1) + { + // TC + slot->in.phase_out = (rm_xor << 9) | 0x80; + } + } + + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->lfsr = (noise >> 1) | (n_bit << 22); +} + +/** + * TODO: Figure out what's ACTUALLY going on inside the real chip! + * This is not accurate at all, but it's the closest I was able to get with + * empirical testing (and it's closer than nothing). + */ +/* ------------------------------------------------------------------------- */ +static int16 +ESFM_slot3_noise3_mod_input_calc(esfm_slot *slot) +{ + esfm_channel *channel = slot->channel; + int16 phase; + int13 output_buf = *channel->slots[1].in.mod_input; + int i; + + // Go through previous slots' partial results and recalculate outputs + // (we skip slot 0 because its calculation happens at the end, not at the beginning) + for (i = 1; i < 3; i++) + { + // double the pitch + phase = channel->slots[i].in.phase_acc >> 8; + if (channel->slots[i].mod_in_level) + { + phase += output_buf >> (7 - channel->slots[i].mod_in_level); + } + output_buf = ESFM_envelope_wavegen(channel->slots[2].waveform, phase, channel->slots[i].in.eg_output); + } + + return output_buf >> (8 - slot->mod_in_level); +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_slot_generate(esfm_slot *slot) +{ + int16 phase = slot->in.phase_out; + if (slot->mod_in_level) + { + if (slot->slot_idx == 3 && slot->rhy_noise == 3) + { + phase += ESFM_slot3_noise3_mod_input_calc(slot); + } + else + { + phase += *slot->in.mod_input >> (7 - slot->mod_in_level); + } + } + slot->in.output = ESFM_envelope_wavegen(slot->waveform, phase, slot->in.eg_output); + if (slot->output_level) + { + int13 output_value = slot->in.output >> (7 - slot->output_level); + slot->channel->output[0] += output_value & slot->out_enable[0]; + slot->channel->output[1] += output_value & slot->out_enable[1]; + } +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_slot_generate_emu(esfm_slot *slot) +{ + const esfm_chip *chip = slot->chip; + uint3 waveform = slot->waveform & (chip->emu_newmode != 0 ? 0x07 : 0x03); + bool rhythm_slot_double_volume = (slot->chip->emu_rhy_mode_flags & 0x20) != 0 + && slot->channel->channel_idx >= 6 && slot->channel->channel_idx < 9; + int16 phase = slot->in.phase_out; + int14 output_value; + + phase += *slot->in.mod_input & slot->in.emu_mod_enable; + slot->in.output = ESFM_envelope_wavegen(waveform, phase, slot->in.eg_output); + output_value = (slot->in.output & slot->in.emu_output_enable) << rhythm_slot_double_volume; + if (chip->emu_newmode) + { + slot->channel->output[0] += output_value & slot->channel->slots[0].out_enable[0]; + slot->channel->output[1] += output_value & slot->channel->slots[0].out_enable[1]; + } + else + { + slot->channel->output[0] += output_value; + slot->channel->output[1] += output_value; + } +} + +/* ------------------------------------------------------------------------- */ +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunknown-pragmas" +static void +ESFM_process_feedback(esfm_chip *chip) +{ + int channel_idx; + + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + esfm_slot *slot = &chip->channels[channel_idx].slots[0]; + uint32 basefreq, phase_offset; + uint3 block; + uint10 f_num; + int32_t wave_out, wave_last; + int32_t phase_feedback; + uint32_t iter_counter; + uint3 waveform; + uint3 mod_in_shift; + uint32_t phase, phase_acc; + uint10 eg_output; + + if (slot->mod_in_level && (chip->native_mode || (slot->in.mod_input == &slot->in.feedback_buf))) + { + if (chip->native_mode) + { + waveform = slot->waveform; + } + else + { + waveform = slot->waveform & (0x03 | (0x02 << (chip->emu_newmode != 0))); + } + f_num = slot->f_num; + block = slot->block; + basefreq = (f_num << block) >> 1; + phase_offset = (basefreq * mt[slot->mult]) >> 1; + mod_in_shift = 7 - slot->mod_in_level; + phase_acc = (uint32_t)(slot->in.phase_acc - phase_offset * 28); + eg_output = slot->in.eg_output; + + // ASM optimizaions! +#if defined(__GNUC__) && defined(__x86_64__) && !defined(_ESFMU_DISABLE_ASM_OPTIMIZATIONS) + asm ( + "movzbq %[wave], %%r8 \n\t" + "shll $11, %%r8d \n\t" + "leaq %[sinrom], %%rax \n\t" + "addq %%rax, %%r8 \n\t" + "leaq %[exprom], %%r9 \n\t" + "movzwl %[eg_out], %%r10d \n\t" + "shll $3, %%r10d \n\t" + "xorl %%r11d, %%r11d \n\t" + "movl %%r11d, %[out] \n\t" + "movl $29, %%edx \n" + "1: \n\t" + // phase_feedback = (wave_out + wave_last) >> 2; + "movl %[out], %[p_fb] \n\t" + "addl %%r11d, %[p_fb] \n\t" + "sarl $2, %[p_fb] \n\t" + // wave_last = wave_out + "movl %[out], %%r11d \n\t" + // phase = phase_feedback >> mod_in_shift; + "movl %[p_fb], %%eax \n\t" + "movb %[mod_in], %%cl \n\t" + "sarl %%cl, %%eax \n\t" + // phase += phase_acc >> 9; + "movl %[p_acc], %%ebx \n\t" + "sarl $9, %%ebx \n\t" + "addl %%ebx, %%eax \n\t" + // lookup = logsinrom[(waveform << 10) | (phase & 0x3ff)]; + "andq $0x3ff, %%rax \n\t" + "movzwl (%%r8, %%rax, 2), %%ebx \n\t" + "movl %%ebx, %%eax \n\t" + // level = (lookup & 0x1fff) + (envelope << 3); + "movl $0x1fff, %%ecx \n\t" + "andl %%ecx, %%eax \n\t" + "addl %%r10d, %%eax \n\t" + // if (level > 0x1fff) level = 0x1fff; + "cmpl %%ecx, %%eax \n\t" + "cmoval %%ecx, %%eax \n\t" + // wave_out = exprom[level & 0xff] >> (level >> 8); + "movb %%ah, %%cl \n\t" + "movzbl %%al, %%eax \n\t" + "movzwl (%%r9, %%rax, 2), %[out] \n\t" + "shrl %%cl, %[out] \n\t" + // if (lookup & 0x8000) wave_out = -wave_out; + // in other words, lookup is negative + "movl %[out], %%ecx \n\t" + "negl %%ecx \n\t" + "testw %%bx, %%bx \n\t" + "cmovsl %%ecx, %[out] \n\t" + // phase_acc += phase_offset + "addl %[p_off], %[p_acc] \n\t" + // loop + "decl %%edx \n\t" + "jne 1b \n\t" + : [p_fb] "=&r" (phase_feedback), + [p_acc] "+r" (phase_acc), + [out] "=&r" (wave_out) + : [p_off] "r" (phase_offset), + [mod_in] "r" (mod_in_shift), + [wave] "g" (waveform), + [eg_out] "g" (eg_output), + [sinrom] "m" (logsinrom), + [exprom] "m" (exprom) + : "cc", "ax", "bx", "cx", "dx", "r8", "r9", "r10", "r11" + ); +#elif defined(__GNUC__) && defined(__i386__) && !defined(_ESFMU_DISABLE_ASM_OPTIMIZATIONS) + size_t logsinrom_addr = (size_t)logsinrom; + size_t exprom_addr = (size_t)exprom; + + asm ( + "movzbl %b[wave], %%eax \n\t" + "shll $11, %%eax \n\t" + "movl %[sinrom], %%edi \n\t" + "addl %%eax, %%edi \n\t" + "shlw $3, %[eg_out] \n\t" + "xorl %[out], %[out] \n\t" + "movl %[out], %[last] \n\t" + "movl $29, %[i] \n" + "1: \n\t" + // phase_feedback = (wave_out + wave_last) >> 2; + "movl %[out], %%eax \n\t" + "addl %[last], %%eax \n\t" + "sarl $2, %%eax \n\t" + "movl %%eax, %[p_fb] \n\t" + // wave_last = wave_out + "movl %[out], %[last] \n\t" + // phase = phase_feedback >> mod_in_shift; + "movb %[mod_in], %%cl \n\t" + "sarl %%cl, %%eax \n\t" + // phase += phase_acc >> 9; + "movl %[p_acc], %%ebx \n\t" + "shrl $9, %%ebx \n\t" + "addl %%ebx, %%eax \n\t" + // lookup = logsinrom[(waveform << 10) | (phase & 0x3ff)]; + "andl $0x3ff, %%eax \n\t" + "movzwl (%%edi, %%eax, 2), %%ebx \n\t" + "movl %%ebx, %%eax \n\t" + // level = (lookup & 0x1fff) + (envelope << 3); + "movl $0x1fff, %%ecx \n\t" + "andl %%ecx, %%eax \n\t" + "addw %[eg_out], %%ax \n\t" + // if (level > 0x1fff) level = 0x1fff; + "cmpl %%ecx, %%eax \n\t" + "cmoval %%ecx, %%eax \n\t" + // wave_out = exprom[level & 0xff] >> (level >> 8); + "movb %%ah, %%cl \n\t" + "movzbl %%al, %%eax \n\t" + "movl %[exprom], %[out] \n\t" + "movzwl (%[out], %%eax, 2), %[out] \n\t" + "shrl %%cl, %[out] \n\t" + // if (lookup & 0x8000) wave_out = -wave_out; + // in other words, lookup is negative + "movl %[out], %%ecx \n\t" + "negl %%ecx \n\t" + "testw %%bx, %%bx \n\t" + "cmovsl %%ecx, %[out] \n\t" + // phase_acc += phase_offset + "addl %[p_off], %[p_acc] \n\t" + // loop + "decl %[i] \n\t" + "jne 1b \n\t" + : [p_fb] "=&m" (phase_feedback), + [p_acc] "+r" (phase_acc), + [out] "=&r" (wave_out), + [last] "=&m" (wave_last), + [eg_out] "+m" (eg_output) + : [p_off] "m" (phase_offset), + [mod_in] "m" (mod_in_shift), + [wave] "m" (waveform), + [sinrom] "m" (logsinrom_addr), + [exprom] "m" (exprom_addr), + [i] "m" (iter_counter) + : "cc", "ax", "bx", "cx", "di" + ); +#elif defined(__GNUC__) && defined(__arm__) && !defined(_ESFMU_DISABLE_ASM_OPTIMIZATIONS) + asm ( + "movs r3, #0 \n\t" + "movs %[out], #0 \n\t" + "ldr r8, =0x1fff \n\t" + "movs r2, #29 \n" + "1: \n\t" + // phase_feedback = (wave_out + wave_last) >> 2; + "adds %[p_fb], %[out], r3 \n\t" + "asrs %[p_fb], %[p_fb], #2 \n\t" + // wave_last = wave_out + "mov r3, %[out] \n\t" + // phase = phase_feedback >> mod_in_shift; + "asr r0, %[p_fb], %[mod_in] \n\t" + // phase += phase_acc >> 9; + "add r0, r0, %[p_acc], asr #9 \n\t" + // lookup = logsinrom[(waveform << 10) | (phase & 0x3ff)]; + "lsls r0, r0, #22 \n\t" + "lsrs r0, r0, #21 \n\t" + "ldrsh r1, [%[sinrom], r0] \n\t" + // level = (lookup & 0x1fff) + (envelope << 3); + "and r0, r8, r1 \n\t" + "add r0, r0, %[eg_out], lsl #3 \n\t" + // if (level > 0x1fff) level = 0x1fff; + "cmp r0, r8 \n\t" + "it hi \n\t" + "movhi r0, r8 \n\t" + // wave_out = exprom[level & 0xff] >> (level >> 8); + "lsrs %[out], r0, #8 \n\t" + "ands r0, r0, #255 \n\t" + "lsls r0, r0, #1 \n\t" + "ldrh r0, [%[exprom], r0] \n\t" + "lsr %[out], r0, %[out] \n\t" + // if (lookup & 0x8000) wave_out = -wave_out; + // in other words, lookup is negative + "tst r1, r1 \n\t" + "it mi \n\t" + "negmi %[out], %[out] \n\t" + // phase_acc += phase_offset + "adds %[p_acc], %[p_acc], %[p_off]\n\t" + // loop + "subs r2, r2, #1 \n\t" + "bne 1b \n\t" + : [p_fb] "=&r" (phase_feedback), + [p_acc] "+r" (phase_acc), + [out] "=&r" (wave_out) + : [p_off] "r" (phase_offset), + [mod_in] "r" (mod_in_shift), + [eg_out] "r" (eg_output), + [sinrom] "r" (logsinrom + waveform * 1024), + [exprom] "r" (exprom) + : "cc", "r0", "r1", "r2", "r3", "r8" + ); +#else + wave_out = 0; + wave_last = 0; + for (iter_counter = 0; iter_counter < 29; iter_counter++) + { + phase_feedback = (wave_out + wave_last) >> 2; + wave_last = wave_out; + phase = phase_feedback >> mod_in_shift; + phase += phase_acc >> 9; + wave_out = ESFM_envelope_wavegen(waveform, phase, eg_output); + phase_acc += phase_offset; + } +#endif + + // TODO: Figure out - is this how the ESFM chip does it, like the + // patent literally says? (it's really hacky...) + // slot->in.output = wave_out; + + // This would be the more canonical way to do it, reusing the rest of + // the synthesis pipeline to finish the calculation: + if (chip->native_mode) + { + slot->in.feedback_buf = phase_feedback; + } + else + { + slot->in.feedback_buf = phase_feedback >> (7 - slot->mod_in_level); + } + } + } +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_process_channel(esfm_channel *channel) +{ + int slot_idx; + channel->output[0] = channel->output[1] = 0; + for (slot_idx = 0; slot_idx < 4; slot_idx++) + { + esfm_slot *slot = &channel->slots[slot_idx]; + ESFM_envelope_calc(slot); + ESFM_phase_generate(slot); + if(slot_idx > 0) + { + ESFM_slot_generate(slot); + } + } + // ESFM feedback calculation takes a large number of clock cycles, so + // defer slot 0 generation to the end + // TODO: verify this behavior on real hardware +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_process_channel_emu(esfm_channel *channel) +{ + int slot_idx; + channel->output[0] = channel->output[1] = 0; + for (slot_idx = 0; slot_idx < 2; slot_idx++) + { + esfm_slot *slot = &channel->slots[slot_idx]; + ESFM_envelope_calc(slot); + ESFM_phase_generate_emu(slot); + if(slot_idx > 0) + { + ESFM_slot_generate_emu(slot); + } + } + // ESFM feedback calculation takes a large number of clock cycles, so + // defer slot 0 generation to the end + // TODO: verify this behavior on real hardware +} + +/* ------------------------------------------------------------------------- */ +static int16_t +ESFM_clip_sample(int32 sample) +{ + // TODO: Supposedly, the real ESFM chip actually overflows rather than + // clipping. Verify that. + if (sample > 32767) + { + sample = 32767; + } + else if (sample < -32768) + { + sample = -32768; + } + return (int16_t)sample; +} + +#define TIMER1_CONST (0.2517482517482517) +#define TIMER2_CONST (0.06293706293706293) +/* ------------------------------------------------------------------------- */ +static void +ESFM_update_timers(esfm_chip *chip) +{ + int i; + // Tremolo + if ((chip->global_timer & 0x3f) == 0x3f) + { + chip->tremolo_pos = (chip->tremolo_pos + 1) % 210; + if (chip->tremolo_pos < 105) + { + chip->tremolo = chip->tremolo_pos; + } + else + { + chip->tremolo = (210 - chip->tremolo_pos); + } + } + + // Vibrato + if ((chip->global_timer & 0x3ff) == 0x3ff) + { + chip->vibrato_pos = (chip->vibrato_pos + 1) & 0x07; + } + + chip->global_timer = (chip->global_timer + 1) & 0x3ff; + + // Envelope generator dither clocks + chip->eg_clocks = 0; + if (chip->eg_timer) + { + uint8 shift = 0; + while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) + { + shift++; + } + + if (shift <= 12) + { + chip->eg_clocks = shift + 1; + } + } + + if (chip->eg_tick || chip->eg_timer_overflow) + { + if (chip->eg_timer == (1llu << 36) - 1) + { + chip->eg_timer = 0; + chip->eg_timer_overflow = 1; + } + else + { + chip->eg_timer++; + chip->eg_timer_overflow = 0; + } + } + + for (i = 0; i < 2; i++) + { + if (chip->timer_enable[i]) + { + chip->timer_accumulator[i] += (i == 0) ? TIMER1_CONST : TIMER2_CONST; + if (chip->timer_accumulator[i] > 1.0) + { + chip->timer_accumulator[i] -= 1.0; + chip->timer_counter[i]++; + if (chip->timer_counter[i] == 0) + { + if (chip->timer_mask[i] == 0) + { + chip->irq_bit = true; + chip->timer_overflow[i] = true; + } + chip->timer_counter[i] = chip->timer_reload[i]; + } + } + } + } + + chip->eg_tick ^= 1; +} + +#define KEY_ON_REGS_START (18 * 4 * 8) +/* ------------------------------------------------------------------------- */ +int +ESFM_reg_write_chan_idx(esfm_chip *chip, uint16_t reg) +{ + int which_reg = -1; + if (chip->native_mode) + { + bool is_key_on_reg = reg >= KEY_ON_REGS_START && reg < (KEY_ON_REGS_START + 20); + if (is_key_on_reg) + { + which_reg = reg - KEY_ON_REGS_START; + } + } + else + { + uint8_t reg_low = reg & 0xff; + bool high = reg & 0x100; + bool is_key_on_reg = reg_low >= 0xb0 && reg_low < 0xb9; + if (is_key_on_reg) + { + which_reg = (reg_low & 0x0f) + high * 9; + } + } + + return which_reg; +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_update_write_buffer(esfm_chip *chip) +{ + esfm_write_buf *write_buf; + bool note_off_written[20]; + bool bassdrum_written = false; + int i; + for (i = 0; i < 20; i++) + { + note_off_written[i] = false; + } + while((write_buf = &chip->write_buf[chip->write_buf_start]), + write_buf->valid && write_buf->timestamp <= chip->write_buf_timestamp) + { + int is_which_note_on_reg = + ESFM_reg_write_chan_idx(chip, write_buf->address); + if (is_which_note_on_reg >= 0) + { + if ((chip->native_mode && (write_buf->data & 0x01) == 0) + || (!chip->native_mode && (write_buf->data & 0x20) == 0) + ) + { + // this is a note off command; note down that we got note off for this channel + note_off_written[is_which_note_on_reg] = true; + } + else + { + // this is a note on command; have we gotten a note off for this channel in this cycle? + if (note_off_written[is_which_note_on_reg]) + { + // we have a conflict; let the note off be processed first and defer the + // rest of the buffer to the next cycle + break; + } + } + } + if ((chip->native_mode && write_buf->address == 0x4bd) + || (!chip->native_mode && (write_buf->address & 0xff) == 0xbd) + ) + { + // bassdrum register write (rhythm mode note-on/off control) + // have we already written to the bassdrum register in this cycle + if (bassdrum_written) { + // we have a conflict + break; + } + bassdrum_written = true; + } + + write_buf->valid = 0; + ESFM_write_reg(chip, write_buf->address, write_buf->data); + chip->write_buf_start = (chip->write_buf_start + 1) % ESFM_WRITEBUF_SIZE; + } + + chip->write_buf_timestamp++; +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_generate(esfm_chip *chip, int32_t *buf) +{ + int channel_idx; + + chip->output_accm[0] = chip->output_accm[1] = 0; + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + esfm_channel *channel = &chip->channels[channel_idx]; + if (chip->native_mode) + { + ESFM_process_channel(channel); + } + else + { + ESFM_process_channel_emu(channel); + } + } + ESFM_process_feedback(chip); + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + esfm_channel *channel = &chip->channels[channel_idx]; + if (chip->native_mode) + { + ESFM_slot_generate(&channel->slots[0]); + } + else + { + ESFM_slot_generate_emu(&channel->slots[0]); + } + chip->output_accm[0] += channel->output[0]; + chip->output_accm[1] += channel->output[1]; + } + + buf[0] = chip->output_accm[0]; + buf[1] = chip->output_accm[1]; + + ESFM_update_timers(chip); + ESFM_update_write_buffer(chip); +} + +/* ------------------------------------------------------------------------- */ +int16_t +ESFM_get_channel_output_native(esfm_chip *chip, int channel_idx) +{ + int16_t result; + int32_t temp_mix = 0; + int i; + + if (channel_idx < 0 || channel_idx >= 18) + { + return 0; + } + + for (i = 0; i < 4; i++) + { + esfm_slot *slot = &chip->channels[channel_idx].slots[i]; + + if (slot->output_level) + { + int13 output_value = slot->in.output >> (7 - slot->output_level); + temp_mix += output_value & slot->out_enable[0]; + temp_mix += output_value & slot->out_enable[1]; + } + } + + if (temp_mix > 32767) + { + temp_mix = 32767; + } + else if (temp_mix < -32768) + { + temp_mix = -32768; + } + result = temp_mix; + return result; +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_generate_stream(esfm_chip *chip, int16_t *sndptr, uint32_t num_samples) +{ + uint32_t i; + int32_t buf[2] = { 0 }; + + for (i = 0; i < num_samples; i++) + { + ESFM_generate(chip, buf); + sndptr[0] = ESFM_clip_sample(buf[0]); + sndptr[1] = ESFM_clip_sample(buf[1]); + sndptr += 2; + } +} diff --git a/src/sound/esfmu/esfm.h b/src/sound/esfmu/esfm.h new file mode 100644 index 000000000..766c7312d --- /dev/null +++ b/src/sound/esfmu/esfm.h @@ -0,0 +1,289 @@ +/* + * ESFMu: emulator for the ESS "ESFM" enhanced OPL3 clone + * Copyright (C) 2023 Kagamiin~ + * + * ESFMu 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. + * + * ESFMu 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 ESFMu. If not, see . + */ + +/* + * ESFMu wouldn't have been possible without the hard work and dedication of + * the retro computer hardware research and preservation community. + * + * I'd like to thank: + * - Nuke.YKT + * Developer of Nuked OPL3, which was the basis for ESFMu's code and + * also a great learning resource on Yamaha FM synthesis for myself. + * Nuke.YKT also gives shoutouts on behalf of Nuked OPL3 to: + * - 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. + * - rainwarrior + * For performing the initial research on ESFM drivers and documenting + * ESS's patent on native mode operator organization. + * - jwt27 + * For kickstarting the ESFM research project and compiling rainwarrior's + * findings and more in an accessible document ("ESFM Demystified"). + * - pachuco/CatButts + * For documenting ESS's patent on ESFM's feedback implementation, which + * was vital in getting ESFMu's sound output to be accurate. + * - akumanatt + * For helping out with code optimization. + * - And everybody who helped out with real hardware testing + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _esfm_slot esfm_slot; +typedef struct _esfm_slot_internal esfm_slot_internal; +typedef struct _esfm_channel esfm_channel; +typedef struct _esfm_chip esfm_chip; + + +void ESFM_init (esfm_chip *chip); +void ESFM_write_reg (esfm_chip *chip, uint16_t address, uint8_t data); +void ESFM_write_reg_buffered (esfm_chip *chip, uint16_t address, uint8_t data); +void ESFM_write_reg_buffered_fast (esfm_chip *chip, uint16_t address, uint8_t data); +void ESFM_write_port (esfm_chip *chip, uint8_t offset, uint8_t data); +uint8_t ESFM_readback_reg (esfm_chip *chip, uint16_t address); +uint8_t ESFM_read_port (esfm_chip *chip, uint8_t offset); +void ESFM_generate(esfm_chip *chip, int32_t *buf); +void ESFM_generate_stream(esfm_chip *chip, int16_t *sndptr, uint32_t num_samples); +int16_t ESFM_get_channel_output_native(esfm_chip *chip, int channel_idx); + + +// These are fake types just for syntax sugar. +// Beware of their underlying types when reading/writing to them. +typedef uint8_t ebit; +typedef uint8_t uint2; +typedef uint8_t uint3; +typedef uint8_t uint4; +typedef uint8_t uint5; +typedef uint8_t uint6; +typedef uint8_t uint8; +typedef uint16_t uint9; +typedef uint16_t uint10; +typedef uint16_t uint11; +typedef uint16_t uint12; +typedef uint16_t uint16; +typedef uint32_t uint19; +typedef uint32_t uint23; +typedef uint32_t uint32; +typedef uint64_t uint36; + +typedef int16_t int13; +typedef int16_t int14; +typedef int16_t int16; +typedef int32_t int32; + +enum eg_states +{ + EG_ATTACK, + EG_DECAY, + EG_SUSTAIN, + EG_RELEASE +}; + + +typedef struct _esfm_write_buf +{ + uint64_t timestamp; + uint16_t address; + uint8_t data; + ebit valid; + +} esfm_write_buf; + +typedef struct _emu_slot_channel_mapping +{ + int channel_idx; + int slot_idx; + +} emu_slot_channel_mapping; + +typedef struct _esfm_slot_internal +{ + uint9 eg_position; + uint9 eg_ksl_offset; + uint10 eg_output; + + uint4 keyscale; + + int13 output; + int13 emu_output_enable; + int13 emu_mod_enable; + int13 feedback_buf; + int13 *mod_input; + + uint19 phase_acc; + uint10 phase_out; + ebit phase_reset; + ebit *key_on; + ebit key_on_gate; + + uint2 eg_state; + ebit eg_delay_run; + ebit eg_delay_transitioned_10; + ebit eg_delay_transitioned_10_gate; + ebit eg_delay_transitioned_01; + ebit eg_delay_transitioned_01_gate; + uint16 eg_delay_counter; + uint16 eg_delay_counter_compare; + +} esfm_slot_internal; + +struct _esfm_slot +{ + // Metadata + esfm_channel *channel; + esfm_chip *chip; + uint2 slot_idx; + + // Register data + int13 out_enable[2]; + uint10 f_num; + uint3 block; + uint3 output_level; + // a.k.a. feedback level in emu mode + uint3 mod_in_level; + + uint6 t_level; + uint4 mult; + uint3 waveform; + // Only for 4th slot + uint2 rhy_noise; + + uint4 attack_rate; + uint4 decay_rate; + uint4 sustain_lvl; + uint4 release_rate; + + ebit tremolo_en; + ebit tremolo_deep; + ebit vibrato_en; + ebit vibrato_deep; + ebit emu_connection_typ; + ebit env_sustaining; + ebit ksr; + uint2 ksl; + uint3 env_delay; + // overlaps with env_delay bit 0 + // TODO: check if emu mode only uses this, or if it actually overwrites the channel field used by native mode + ebit emu_key_on; + + // Internal state + esfm_slot_internal in; +}; + +struct _esfm_channel +{ + esfm_chip *chip; + esfm_slot slots[4]; + uint5 channel_idx; + int16 output[2]; + ebit key_on; + ebit emu_mode_4op_enable; + // Only for 17th and 18th channels + ebit key_on_2; + ebit emu_mode_4op_enable_2; +}; + +#define ESFM_WRITEBUF_SIZE 1024 +#define ESFM_WRITEBUF_DELAY 2 + +struct _esfm_chip +{ + esfm_channel channels[18]; + int32 output_accm[2]; + uint16 addr_latch; + + ebit emu_wavesel_enable; + ebit emu_newmode; + ebit native_mode; + + ebit keyscale_mode; + + // Global state + uint36 eg_timer; + uint10 global_timer; + uint8 eg_clocks; + ebit eg_tick; + ebit eg_timer_overflow; + uint8 tremolo; + uint8 tremolo_pos; + uint8 vibrato_pos; + uint23 lfsr; + + ebit rm_hh_bit2; + ebit rm_hh_bit3; + ebit rm_hh_bit7; + ebit rm_hh_bit8; + ebit rm_tc_bit3; + ebit rm_tc_bit5; + + // 0xbd register in emulation mode, exposed in 0x4bd in native mode + // ("bass drum" register) + uint8 emu_rhy_mode_flags; + + ebit emu_vibrato_deep; + ebit emu_tremolo_deep; + + double timer_accumulator[2]; + uint8 timer_reload[2]; + uint8 timer_counter[2]; + ebit timer_enable[2]; + ebit timer_mask[2]; + ebit timer_overflow[2]; + ebit irq_bit; + + // -- Test bits (NOT IMPLEMENTED) -- + // Halts the envelope generators from advancing. Written on bit 0, read back from bit 5. + ebit test_bit_w0_r5_eg_halt; + /* + * Activates some sort of waveform test mode that amplifies the output volume greatly + * and continuously shifts the waveform table downwards, possibly also outputting the + * waveform's derivative? (it's so weird!) + */ + ebit test_bit_1_distort; + // Seems to do nothing. + ebit test_bit_2; + // Seems to do nothing. + ebit test_bit_3; + // Appears to attenuate the output by about 3 dB. + ebit test_bit_4_attenuate; + // Written on bit 5, read back from bit 0. Seems to do nothing. + ebit test_bit_w5_r0; + // Resets all phase generators and holds them in the reset state while this bit is set. + ebit test_bit_6_phase_stop_reset; + // Seems to do nothing. + ebit test_bit_7; + + esfm_write_buf write_buf[ESFM_WRITEBUF_SIZE]; + size_t write_buf_start; + size_t write_buf_end; + uint64_t write_buf_timestamp; +}; + +#ifdef __cplusplus +} +#endif diff --git a/src/sound/esfmu/esfm_registers.c b/src/sound/esfmu/esfm_registers.c new file mode 100644 index 000000000..e2f432ed1 --- /dev/null +++ b/src/sound/esfmu/esfm_registers.c @@ -0,0 +1,1009 @@ +/* + * ESFMu: emulator for the ESS "ESFM" enhanced OPL3 clone + * Copyright (C) 2023 Kagamiin~ + * + * This file includes code and data from the Nuked OPL3 project, copyright (C) + * 2013-2023 Nuke.YKT. Its usage, modification and redistribution is allowed + * under the terms of the GNU Lesser General Public License version 2.1 or + * later. + * + * ESFMu 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. + * + * ESFMu 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 ESFMu. If not, see . + */ + +/* + * ESFMu wouldn't have been possible without the hard work and dedication of + * the retro computer hardware research and preservation community. + * + * I'd like to thank: + * - Nuke.YKT + * Developer of Nuked OPL3, which was the basis for ESFMu's code and + * also a great learning resource on Yamaha FM synthesis for myself. + * Nuke.YKT also gives shoutouts on behalf of Nuked OPL3 to: + * - 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. + * - rainwarrior + * For performing the initial research on ESFM drivers and documenting + * ESS's patent on native mode operator organization. + * - jwt27 + * For kickstarting the ESFM research project and compiling rainwarrior's + * findings and more in an accessible document ("ESFM Demystified"). + * - pachuco/CatButts + * For documenting ESS's patent on ESFM's feedback implementation, which + * was vital in getting ESFMu's sound output to be accurate. + * - And everybody who helped out with real hardware testing + */ + +#include "esfm.h" +#include +#include +#include +#include + + +/* + * Table of KSL values extracted from OPL3 ROM; taken straight from Nuked OPL3 + * source code. + * TODO: Check if ESFM uses the same KSL values. + */ + +static const int16 kslrom[16] = { + 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 +}; + +/* + * This maps the low 5 bits of emulation mode address to an emulation mode + * slot; taken straight from Nuked OPL3. Used for decoding certain emulation + * mode address ranges. + */ +static const int8_t ad_slot[0x20] = { + 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, + 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/* + * This maps an emulation mode slot index to a tuple representing the + * corresponding native mode channel and slot. + */ +static const emu_slot_channel_mapping emu_slot_map[36] = +{ + { 0, 0}, { 1, 0}, { 2, 0}, { 0, 1}, { 1, 1}, { 2, 1}, + { 3, 0}, { 4, 0}, { 5, 0}, { 3, 1}, { 4, 1}, { 5, 1}, + { 6, 0}, { 7, 0}, { 8, 0}, { 6, 1}, { 7, 1}, { 8, 1}, + { 9, 0}, {10, 0}, {11, 0}, { 9, 1}, {10, 1}, {11, 1}, + {12, 0}, {13, 0}, {14, 0}, {12, 1}, {13, 1}, {14, 1}, + {15, 0}, {16, 0}, {17, 0}, {15, 1}, {16, 1}, {17, 1} +}; + +/* + * This encodes which emulation mode channels are the secondary channel in a + * 4-op channel pair (where the entry is non-negative), and which is the + * corresponding primary channel for that secondary channel. + */ +static const int emu_4op_secondary_to_primary[18] = +{ + -1, -1, -1, 0, 1, 2, -1, -1, -1, + -1, -1, -1, 9, 10, 11, -1, -1, -1 +}; + +/* + * This encodes the operator outputs to be enabled or disabled for + * each 4-op algorithm in emulation mode. + * Indices: FM+FM, FM+AM, AM+FM, AM+AM (lower channel MSB, upper channel LSB) + * Values: enable OP1, OP2, OP3, OP4 + */ +static const bool emu_4op_alg_output_enable[4][4] = +{ + {0, 0, 0, 1}, + {0, 1, 0, 1}, + {1, 0, 0, 1}, + {1, 0, 1, 1} +}; + +/* + * This encodes the operator interconnections to be enabled or disabled for + * each 4-op algorithm in emulation mode. + * Indices: FM+FM, FM+AM, AM+FM, AM+AM (lower channel MSB, upper channel LSB) + * Values: enable OP1FB, OP1->2, OP2->3, OP3->4 + */ +static const bool emu_4op_alg_mod_enable[4][4] = +{ + {1, 1, 1, 1}, + {1, 1, 0, 1}, + {1, 0, 1, 1}, + {1, 0, 1, 0} +}; + + +/* ------------------------------------------------------------------------- */ +static void +ESFM_emu_rearrange_connections(esfm_channel *channel) +{ + int secondary_to_primary; + + secondary_to_primary = emu_4op_secondary_to_primary[channel->channel_idx]; + if (secondary_to_primary >= 0) + { + esfm_channel *pair_primary = &channel->chip->channels[secondary_to_primary]; + if (pair_primary->emu_mode_4op_enable) + { + // always work from primary channel in pair when dealing with 4-op + channel = pair_primary; + } + } + + if (channel->emu_mode_4op_enable && (channel->channel_idx % 9) < 3 && channel->chip->emu_newmode) + { + esfm_channel *secondary = &channel->chip->channels[channel->channel_idx + 3]; + uint2 algorithm = ((channel->slots[0].emu_connection_typ != 0) << 1) + | (secondary->slots[0].emu_connection_typ != 0); + int i; + + secondary->slots[0].in.mod_input = &channel->slots[1].in.output; + + for (i = 0; i < 2; i++) + { + channel->slots[i].in.emu_mod_enable = + emu_4op_alg_mod_enable[algorithm][i] ? ~((int13) 0) : 0; + channel->slots[i].in.emu_output_enable = + emu_4op_alg_output_enable[algorithm][i] ? ~((int13) 0) : 0; + + secondary->slots[i].in.emu_mod_enable = + emu_4op_alg_mod_enable[algorithm][i + 2] ? ~((int13) 0) : 0; + secondary->slots[i].in.emu_output_enable = + emu_4op_alg_output_enable[algorithm][i + 2] ? ~((int13) 0) : 0; + } + } + else if ((channel->chip->emu_rhy_mode_flags & 0x20) != 0 + && (channel->channel_idx == 7 || channel->channel_idx == 8)) + { + channel->slots[0].in.emu_mod_enable = 0; + channel->slots[1].in.emu_mod_enable = 0; + channel->slots[0].in.emu_output_enable = ~((int13) 0); + channel->slots[1].in.emu_output_enable = ~((int13) 0); + } + else + { + channel->slots[0].in.mod_input = &channel->slots[0].in.feedback_buf; + + channel->slots[0].in.emu_mod_enable = ~((int13) 0); + channel->slots[0].in.emu_output_enable = + (channel->slots[0].emu_connection_typ != 0) ? ~((int13) 0) : 0; + channel->slots[1].in.emu_output_enable = ~((int13) 0); + channel->slots[1].in.emu_mod_enable = + (channel->slots[0].emu_connection_typ != 0) ? 0 : ~((int13) 0); + } +} + + +/* ------------------------------------------------------------------------- */ +static void +ESFM_emu_to_native_switch(esfm_chip *chip) +{ + size_t channel_idx, slot_idx; + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + for (slot_idx = 0; slot_idx < 4; slot_idx++) + { + esfm_channel *channel = &chip->channels[channel_idx]; + esfm_slot *slot = &channel->slots[slot_idx]; + + if (slot_idx == 0) + { + slot->in.mod_input = &slot->in.feedback_buf; + } + else + { + esfm_slot *prev_slot = &channel->slots[slot_idx - 1]; + slot->in.mod_input = &prev_slot->in.output; + } + } + } +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_native_to_emu_switch(esfm_chip *chip) +{ + size_t channel_idx; + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + ESFM_emu_rearrange_connections(&chip->channels[channel_idx]); + } +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_slot_update_keyscale(esfm_slot *slot) +{ + if (slot->slot_idx > 0 && !slot->chip->native_mode) + { + return; + } + + int16 ksl = (kslrom[slot->f_num >> 6] << 2) - ((0x08 - slot->block) << 5); + if (ksl < 0) + { + ksl = 0; + } + slot->in.eg_ksl_offset = ksl; + slot->in.keyscale = (slot->block << 1) + | ((slot->f_num >> (8 + !slot->chip->keyscale_mode)) & 0x01); +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_emu_channel_update_keyscale(esfm_channel *channel) +{ + int secondary_to_primary; + + secondary_to_primary = emu_4op_secondary_to_primary[channel->channel_idx]; + if (secondary_to_primary >= 0) + { + esfm_channel *pair_primary = &channel->chip->channels[secondary_to_primary]; + if (pair_primary->emu_mode_4op_enable) + { + // always work from primary channel in pair when dealing with 4-op + channel = pair_primary; + } + } + + ESFM_slot_update_keyscale(&channel->slots[0]); + channel->slots[1].in.eg_ksl_offset = channel->slots[0].in.eg_ksl_offset; + channel->slots[1].in.keyscale = channel->slots[0].in.keyscale; + + if (channel->emu_mode_4op_enable && (channel->channel_idx % 9) < 3 && channel->chip->emu_newmode) + { + int i; + esfm_channel *secondary = &channel->chip->channels[channel->channel_idx + 3]; + secondary->slots[0].f_num = channel->slots[0].f_num; + secondary->slots[0].block = channel->slots[0].block; + + for (i = 0; i < 2; i++) + { + secondary->slots[i].in.eg_ksl_offset = channel->slots[0].in.eg_ksl_offset; + secondary->slots[i].in.keyscale = channel->slots[0].in.keyscale; + } + } +} + +/* ------------------------------------------------------------------------- */ +static inline uint8_t +ESFM_slot_readback (esfm_slot *slot, uint8_t register_idx) +{ + uint8_t data = 0; + switch (register_idx & 0x07) + { + case 0x00: + data |= (slot->tremolo_en != 0) << 7; + data |= (slot->vibrato_en != 0) << 6; + data |= (slot->env_sustaining != 0) << 5; + data |= (slot->vibrato_en != 0) << 4; + data |= slot->mult & 0x0f; + break; + case 0x01: + data |= slot->ksl << 6; + data |= slot->t_level & 0x3f; + break; + case 0x02: + data |= slot->attack_rate << 4; + data |= slot->decay_rate & 0x0f; + break; + case 0x03: + data |= slot->sustain_lvl << 4; + data |= slot->release_rate & 0x0f; + break; + case 0x04: + data = slot->f_num & 0xff; + break; + case 0x05: + data |= slot->env_delay << 5; + data |= (slot->block & 0x07) << 2; + data |= (slot->f_num >> 8) & 0x03; + break; + case 0x06: + data |= (slot->tremolo_deep != 0) << 7; + data |= (slot->vibrato_deep != 0) << 6; + data |= (slot->out_enable[1] != 0) << 5; + data |= (slot->out_enable[0] != 0) << 4; + data |= (slot->mod_in_level & 0x07) << 1; + data |= slot->emu_connection_typ & 0x01; + break; + case 0x07: + data |= slot->output_level << 5; + data |= (slot->rhy_noise & 0x03) << 3; + data |= slot->waveform & 0x07; + break; + } + return data; +} + +/* ------------------------------------------------------------------------- */ +static inline void +ESFM_slot_write (esfm_slot *slot, uint8_t register_idx, uint8_t data) +{ + switch (register_idx & 0x07) + { + case 0x00: + slot->tremolo_en = (data & 0x80) != 0; + slot->vibrato_en = (data & 0x40) != 0; + slot->env_sustaining = (data & 0x20) != 0; + slot->ksr = (data & 0x10) != 0; + slot->mult = data & 0x0f; + break; + case 0x01: + slot->ksl = data >> 6; + slot->t_level = data & 0x3f; + ESFM_slot_update_keyscale(slot); + break; + case 0x02: + slot->attack_rate = data >> 4; + slot->decay_rate = data & 0x0f; + break; + case 0x03: + slot->sustain_lvl = data >> 4; + slot->release_rate = data & 0x0f; + break; + case 0x04: + slot->f_num = (slot->f_num & 0x300) | data; + ESFM_slot_update_keyscale(slot); + break; + case 0x05: + if (slot->env_delay < (data >> 5)) + { + slot->in.eg_delay_transitioned_01 = 1; + } + else if (slot->env_delay > (data >> 5)) + { + slot->in.eg_delay_transitioned_10 = 1; + } + slot->env_delay = data >> 5; + slot->emu_key_on = (data >> 5) & 0x01; + slot->block = (data >> 2) & 0x07; + slot->f_num = (slot->f_num & 0xff) | ((data & 0x03) << 8); + ESFM_slot_update_keyscale(slot); + break; + case 0x06: + slot->tremolo_deep = (data & 0x80) != 0; + slot->vibrato_deep = (data & 0x40) != 0; + slot->out_enable[1] = (data & 0x20) ? ~((int13) 0) : 0; + slot->out_enable[0] = (data & 0x10) ? ~((int13) 0) : 0; + slot->mod_in_level = (data >> 1) & 0x07; + slot->emu_connection_typ = data & 0x01; + break; + case 0x07: + slot->output_level = data >> 5; + slot->rhy_noise = (data >> 3) & 0x03; + slot->waveform = data & 0x07; + break; + } +} + +#define KEY_ON_REGS_START (18 * 4 * 8) +#define TIMER1_REG (0x402) +#define TIMER2_REG (0x403) +#define TIMER_SETUP_REG (0x404) +#define CONFIG_REG (0x408) +#define BASSDRUM_REG (0x4bd) +#define TEST_REG (0x501) +#define FOUROP_CONN_REG (0x504) +#define NATIVE_MODE_REG (0x505) + +/* ------------------------------------------------------------------------- */ +static void +ESFM_write_reg_native (esfm_chip *chip, uint16_t address, uint8_t data) +{ + int i; + address = address & 0x7ff; + + if (address < KEY_ON_REGS_START) + { + // Slot register write + size_t channel_idx = address >> 5; + size_t slot_idx = (address >> 3) & 0x03; + size_t register_idx = address & 0x07; + esfm_slot *slot = &chip->channels[channel_idx].slots[slot_idx]; + + ESFM_slot_write(slot, register_idx, data); + } + else if (address < KEY_ON_REGS_START + 16) + { + // Key-on registers + size_t channel_idx = (address - KEY_ON_REGS_START); + esfm_channel *channel = &chip->channels[channel_idx]; + channel->key_on = data & 0x01; + channel->emu_mode_4op_enable = (data & 0x02) != 0; + } + else if (address < KEY_ON_REGS_START + 20) + { + // Key-on channels 17 and 18 (each half) + size_t channel_idx = 16 + ((address & 0x02) >> 1); + bool second_half = address & 0x01; + esfm_channel *channel = &chip->channels[channel_idx]; + if (second_half) + { + channel->key_on_2 = data & 0x01; + channel->emu_mode_4op_enable_2 = (data & 0x02) != 0; + } + else + { + channel->key_on = data & 0x01; + channel->emu_mode_4op_enable = (data & 0x02) != 0; + } + } + else + { + switch (address & 0x5ff) + { + case TIMER1_REG: + chip->timer_reload[0] = data; + chip->timer_counter[0] = data; + break; + case TIMER2_REG: + chip->timer_reload[1] = data; + chip->timer_counter[1] = data; + break; + case TIMER_SETUP_REG: + if (data & 0x80) + { + chip->irq_bit = 0; + chip->timer_overflow[0] = 0; + chip->timer_overflow[1] = 0; + break; + } + chip->timer_enable[0] = (data & 0x01) != 0; + chip->timer_enable[1] = (data & 0x02) != 0; + chip->timer_mask[1] = (data & 0x20) != 0; + chip->timer_mask[0] = (data & 0x40) != 0; + break; + case CONFIG_REG: + chip->keyscale_mode = (data & 0x40) != 0; + break; + case BASSDRUM_REG: + chip->emu_rhy_mode_flags = data & 0x3f; + chip->emu_vibrato_deep = (data & 0x40) != 0; + chip->emu_tremolo_deep = (data & 0x80) != 0; + break; + case FOUROP_CONN_REG: + for (i = 0; i < 3; i++) + { + chip->channels[i].emu_mode_4op_enable = (data >> i) & 0x01; + chip->channels[i + 9].emu_mode_4op_enable = (data >> (i + 3)) & 0x01; + } + break; + case TEST_REG: + chip->test_bit_w0_r5_eg_halt = (data & 0x01) | ((data & 0x20) != 0); + chip->test_bit_1_distort = (data & 0x02) != 0; + chip->test_bit_2 = (data & 0x04) != 0; + chip->test_bit_3 = (data & 0x08) != 0; + chip->test_bit_4_attenuate = (data & 0x10) != 0; + chip->test_bit_w5_r0 = (data & 0x20) != 0; + chip->test_bit_6_phase_stop_reset = (data & 0x40) != 0; + chip->test_bit_7 = (data & 0x80) != 0; + break; + } + } +} + +/* ------------------------------------------------------------------------- */ +static uint8_t +ESFM_readback_reg_native (esfm_chip *chip, uint16_t address) +{ + int i; + uint8_t data = 0; + address = address & 0x7ff; + + if (address < KEY_ON_REGS_START) + { + // Slot register read + size_t channel_idx = address >> 5; + size_t slot_idx = (address >> 3) & 0x03; + size_t register_idx = address & 0x07; + esfm_slot *slot = &chip->channels[channel_idx].slots[slot_idx]; + + data = ESFM_slot_readback(slot, register_idx); + } + else if (address < KEY_ON_REGS_START + 16) + { + // Key-on registers + size_t channel_idx = (address - KEY_ON_REGS_START); + esfm_channel *channel = &chip->channels[channel_idx]; + + data |= channel->key_on != 0; + data |= (channel->emu_mode_4op_enable != 0) << 1; + } + else if (address < KEY_ON_REGS_START + 20) + { + // Key-on channels 17 and 18 (each half) + size_t channel_idx = 16 + ((address & 0x02) >> 1); + bool second_half = address & 0x01; + esfm_channel *channel = &chip->channels[channel_idx]; + if (second_half) + { + data |= channel->key_on_2 != 0; + data |= (channel->emu_mode_4op_enable_2 != 0) << 1; + } + else + { + data |= channel->key_on != 0; + data |= (channel->emu_mode_4op_enable != 0) << 1; + } + } + else + { + switch (address & 0x5ff) + { + case TIMER1_REG: + data = chip->timer_counter[0]; + break; + case TIMER2_REG: + data = chip->timer_counter[1]; + break; + case TIMER_SETUP_REG: + data |= chip->timer_enable[0] != 0; + data |= (chip->timer_enable[1] != 0) << 1; + data |= (chip->timer_mask[1] != 0) << 5; + data |= (chip->timer_mask[0] != 0) << 6; + break; + case CONFIG_REG: + data |= (chip->keyscale_mode != 0) << 6; + break; + case BASSDRUM_REG: + data |= chip->emu_rhy_mode_flags; + data |= chip->emu_vibrato_deep << 6; + data |= chip->emu_tremolo_deep << 7; + break; + case TEST_REG: + data |= chip->test_bit_w5_r0 != 0; + data |= (chip->test_bit_1_distort != 0) << 1; + data |= (chip->test_bit_2 != 0) << 2; + data |= (chip->test_bit_3 != 0) << 3; + data |= (chip->test_bit_4_attenuate != 0) << 4; + data |= (chip->test_bit_w0_r5_eg_halt != 0) << 5; + data |= (chip->test_bit_6_phase_stop_reset != 0) << 6; + data |= (chip->test_bit_7 != 0) << 7; + break; + case FOUROP_CONN_REG: + for (i = 0; i < 3; i++) + { + data |= (chip->channels[i].emu_mode_4op_enable != 0) << i; + data |= (chip->channels[i + 9].emu_mode_4op_enable != 0) << (i + 3); + } + break; + case NATIVE_MODE_REG: + data |= (chip->emu_newmode != 0); + data |= (chip->native_mode != 0) << 7; + break; + } + } + return data; +} + +/* ------------------------------------------------------------------------- */ +static void +ESFM_write_reg_emu (esfm_chip *chip, uint16_t address, uint8_t data) +{ + bool high = (address & 0x100) != 0; + uint8_t reg = address & 0xff; + int emu_slot_idx = ad_slot[address & 0x1f]; + int natv_chan_idx = -1; + int natv_slot_idx = -1; + int emu_chan_idx = (reg & 0x0f) > 8 ? -1 : ((reg & 0x0f) + high * 9); + + if (emu_slot_idx >= 0) + { + if (high) + { + emu_slot_idx += 18; + } + + natv_chan_idx = emu_slot_map[emu_slot_idx].channel_idx; + natv_slot_idx = emu_slot_map[emu_slot_idx].slot_idx; + } + + if (reg == 0xbd) + { + chip->emu_rhy_mode_flags = data & 0x3f; + chip->emu_vibrato_deep = (data & 0x40) != 0; + chip->emu_tremolo_deep = (data & 0x80) != 0; + if (chip->emu_rhy_mode_flags & 0x20) + { + // TODO: check if writes to 0xbd actually affect the readable key-on flags at + // 0x246, 0x247, 0x248; and if there's any visible effect from the SD and TC flags + chip->channels[6].key_on = (data & 0x10) != 0; + chip->channels[7].key_on = (data & 0x01) != 0; + chip->channels[8].key_on = (data & 0x04) != 0; + chip->channels[7].key_on_2 = (data & 0x08) != 0; + chip->channels[8].key_on_2 = (data & 0x02) != 0; + } + ESFM_emu_rearrange_connections(&chip->channels[7]); + ESFM_emu_rearrange_connections(&chip->channels[8]); + return; + } + + switch(reg & 0xf0) + { + case 0x00: + if (high) + { + int i; + switch(reg & 0x0f) + { + case 0x01: + chip->emu_wavesel_enable = (data & 0x20) != 0; + break; + case 0x02: + chip->timer_reload[0] = data; + chip->timer_counter[0] = data; + break; + case 0x03: + chip->timer_reload[1] = data; + chip->timer_counter[1] = data; + break; + case 0x04: + for (i = 0; i < 3; i++) + { + chip->channels[i].emu_mode_4op_enable = (data >> i) & 0x01; + chip->channels[i + 9].emu_mode_4op_enable = (data >> (i + 3)) & 0x01; + } + for (i = 0; i < 6; i++) + { + ESFM_emu_rearrange_connections(&chip->channels[i]); + ESFM_emu_rearrange_connections(&chip->channels[i + 9]); + } + break; + case 0x05: + chip->emu_newmode = data & 0x01; + if ((data & 0x80) != 0) + { + chip->native_mode = 1; + ESFM_emu_to_native_switch(chip); + } + break; + case 0x08: + chip->keyscale_mode = (data & 0x40) != 0; + break; + } + } + else + { + switch(reg & 0x0f) + { + case 0x01: + chip->emu_wavesel_enable = (data & 0x20) != 0; + break; + case 0x02: + chip->timer_reload[0] = data; + chip->timer_counter[0] = data; + break; + case 0x03: + chip->timer_reload[1] = data; + chip->timer_counter[1] = data; + break; + case 0x04: + if (data & 0x80) + { + chip->irq_bit = 0; + chip->timer_overflow[0] = 0; + chip->timer_overflow[1] = 0; + break; + } + chip->timer_enable[0] = data & 0x01; + chip->timer_enable[1] = (data & 0x02) != 0; + chip->timer_mask[1] = (data & 0x20) != 0; + chip->timer_mask[0] = (data & 0x40) != 0; + break; + case 0x08: + chip->keyscale_mode = (data & 0x40) != 0; + break; + } + } + break; + case 0x20: case 0x30: + if (emu_slot_idx >= 0) + { + ESFM_slot_write(&chip->channels[natv_chan_idx].slots[natv_slot_idx], 0x0, data); + } + break; + case 0x40: case 0x50: + if (emu_slot_idx >= 0) + { + ESFM_slot_write(&chip->channels[natv_chan_idx].slots[natv_slot_idx], 0x1, data); + ESFM_emu_channel_update_keyscale(&chip->channels[natv_chan_idx]); + } + break; + case 0x60: case 0x70: + if (emu_slot_idx >= 0) + { + ESFM_slot_write(&chip->channels[natv_chan_idx].slots[natv_slot_idx], 0x2, data); + } + break; + case 0x80: case 0x90: + if (emu_slot_idx >= 0) + { + ESFM_slot_write(&chip->channels[natv_chan_idx].slots[natv_slot_idx], 0x3, data); + } + break; + case 0xa0: + if (emu_chan_idx >= 0) + { + ESFM_slot_write(&chip->channels[emu_chan_idx].slots[0], 0x4, data); + ESFM_emu_channel_update_keyscale(&chip->channels[emu_chan_idx]); + } + break; + case 0xb0: + if (emu_chan_idx >= 0) + { + esfm_channel *channel = &chip->channels[emu_chan_idx]; + // TODO: check if emulation mode actually writes to the native mode key on registers + // it might only use slot 0's emu key on field... + channel->key_on = (data & 0x20) != 0; + if (channel->channel_idx == 7 || channel->channel_idx == 8) + { + channel->key_on_2 = (data & 0x20) != 0; + } + ESFM_slot_write(&channel->slots[0], 0x5, data); + ESFM_emu_channel_update_keyscale(&chip->channels[emu_chan_idx]); + } + break; + case 0xc0: + if (emu_chan_idx >= 0) + { + ESFM_slot_write(&chip->channels[emu_chan_idx].slots[0], 0x6, data); + ESFM_emu_rearrange_connections(&chip->channels[emu_chan_idx]); + } + break; + case 0xe0: case 0xf0: + if (emu_slot_idx >= 0) + { + ESFM_slot_write(&chip->channels[natv_chan_idx].slots[natv_slot_idx], 0x7, data); + } + break; + } +} + + +/* ------------------------------------------------------------------------- */ +void +ESFM_write_reg (esfm_chip *chip, uint16_t address, uint8_t data) +{ + if (chip->native_mode) + { + ESFM_write_reg_native(chip, address, data); + return; + } + else + { + ESFM_write_reg_emu(chip, address, data); + return; + } +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_write_reg_buffered (esfm_chip *chip, uint16_t address, uint8_t data) +{ + uint64_t timestamp; + esfm_write_buf *new_entry, *last_entry; + + new_entry = &chip->write_buf[chip->write_buf_end]; + last_entry = &chip->write_buf[(chip->write_buf_end - 1) % ESFM_WRITEBUF_SIZE]; + + if (new_entry->valid) { + ESFM_write_reg(chip, new_entry->address, new_entry->data); + chip->write_buf_start = (chip->write_buf_end + 1) % ESFM_WRITEBUF_SIZE; + } + + new_entry->valid = 1; + new_entry->address = address; + new_entry->data = data; + timestamp = last_entry->timestamp + ESFM_WRITEBUF_DELAY; + if (timestamp < chip->write_buf_timestamp) + { + timestamp = chip->write_buf_timestamp; + } + + new_entry->timestamp = timestamp; + chip->write_buf_end = (chip->write_buf_end + 1) % ESFM_WRITEBUF_SIZE; +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_write_reg_buffered_fast (esfm_chip *chip, uint16_t address, uint8_t data) +{ + esfm_write_buf *new_entry; + + new_entry = &chip->write_buf[chip->write_buf_end]; + + if (new_entry->valid) { + ESFM_write_reg(chip, new_entry->address, new_entry->data); + chip->write_buf_start = (chip->write_buf_end + 1) % ESFM_WRITEBUF_SIZE; + } + + new_entry->valid = 1; + new_entry->address = address; + new_entry->data = data; + new_entry->timestamp = chip->write_buf_timestamp; + chip->write_buf_end = (chip->write_buf_end + 1) % ESFM_WRITEBUF_SIZE; +} + +/* ------------------------------------------------------------------------- */ +uint8_t +ESFM_readback_reg (esfm_chip *chip, uint16_t address) +{ + if (chip->native_mode) + { + return ESFM_readback_reg_native(chip, address); + } + else + { + return 0; + } +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_write_port (esfm_chip *chip, uint8_t offset, uint8_t data) +{ + if (chip->native_mode) + { + switch(offset) + { + case 0: + chip->native_mode = 0; + ESFM_native_to_emu_switch(chip); + // TODO: verify if the address write goes through + chip->addr_latch = data; + break; + case 1: + ESFM_write_reg_native(chip, chip->addr_latch, data); + break; + case 2: + chip->addr_latch = (chip->addr_latch & 0xff00) | data; + break; + case 3: + chip->addr_latch = chip->addr_latch & 0xff; + chip->addr_latch |= (uint16)data << 8; + break; + } + } + else + { + switch(offset) + { + case 0: + chip->addr_latch = data; + break; + case 1: case 3: + ESFM_write_reg_emu(chip, chip->addr_latch, data); + break; + case 2: + chip->addr_latch = (uint16)data | 0x100; + break; + } + } +} + +/* ------------------------------------------------------------------------- */ +uint8_t +ESFM_read_port (esfm_chip *chip, uint8_t offset) +{ + uint8_t data = 0; + + switch(offset) + { + case 0: + data |= (chip->irq_bit != 0) << 7; + data |= (chip->timer_overflow[0] != 0) << 6; + data |= (chip->timer_overflow[1] != 0) << 5; + break; + case 1: + if (chip->native_mode) + { + data = ESFM_readback_reg_native(chip, chip->addr_latch); + } + else + { + data = 0; + } + break; + case 2: case 3: + // This matches OPL3 behavior. + data = 0xff; + break; + } + + return data; +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_set_mode (esfm_chip *chip, bool native_mode) +{ + native_mode = native_mode != 0; + + if (native_mode != (chip->native_mode != 0)) + { + chip->native_mode = native_mode; + if (native_mode) + { + ESFM_emu_to_native_switch(chip); + } + else + { + ESFM_native_to_emu_switch(chip); + } + } +} + +/* ------------------------------------------------------------------------- */ +void +ESFM_init (esfm_chip *chip) +{ + esfm_slot *slot; + esfm_channel *channel; + size_t channel_idx, slot_idx; + + memset(chip, 0, sizeof(esfm_chip)); + for (channel_idx = 0; channel_idx < 18; channel_idx++) + { + for (slot_idx = 0; slot_idx < 4; slot_idx++) + { + channel = &chip->channels[channel_idx]; + slot = &channel->slots[slot_idx]; + + channel->chip = chip; + channel->channel_idx = channel_idx; + slot->channel = channel; + slot->chip = chip; + slot->slot_idx = slot_idx; + slot->in.eg_position = slot->in.eg_output = 0x1ff; + slot->in.eg_state = EG_RELEASE; + slot->in.emu_mod_enable = ~((int13) 0); + if (slot_idx == 0) + { + slot->in.mod_input = &slot->in.feedback_buf; + } + else + { + esfm_slot *prev_slot = &channel->slots[slot_idx - 1]; + slot->in.mod_input = &prev_slot->in.output; + } + + if (slot_idx == 1) + { + slot->in.emu_output_enable = ~((int13) 0); + } + + if (channel_idx > 15 && slot_idx & 0x02) + { + slot->in.key_on = &channel->key_on_2; + } + else + { + slot->in.key_on = &channel->key_on; + } + + slot->out_enable[0] = slot->out_enable[1] = ~((int13) 0); + } + } + + chip->lfsr = 1; +} + diff --git a/src/sound/midi.c b/src/sound/midi.c index c5dbd666f..bb107acbf 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -100,7 +100,9 @@ static const MIDI_OUT_DEVICE devices[] = { #ifdef USE_RTMIDI { &rtmidi_output_device }, #endif +#if defined(DEV_BRANCH) && defined(USE_OPL4ML) { &opl4_midi_device }, +#endif { NULL } // clang-format on }; diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index 91d85e438..f38474ac8 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -435,7 +435,7 @@ const device_t mt32_old_device = { const device_t mt32_new_device = { .name = "Roland MT-32 (New) Emulation", - .internal_name = "mt32", + .internal_name = "mt32_new", .flags = 0, .local = 0, .init = mt32_new_init, diff --git a/src/sound/openal.c b/src/sound/openal.c index 76656c66e..a41199b23 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -21,7 +21,6 @@ #include #include #include -#include #undef AL_API #undef ALC_API #define AL_LIBTYPE_STATIC @@ -38,10 +37,12 @@ #define FREQ SOUND_FREQ #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_music[4]; /* front and back buffers */ +ALuint buffers_wt[4]; /* front and back buffers */ +ALuint buffers_cd[4]; /* front and back buffers */ +ALuint buffers_midi[4]; /* front and back buffers */ +static ALuint source[5]; /* audio source */ static int midi_freq = 44100; static int midi_buf_size = 4410; @@ -51,13 +52,12 @@ static ALCcontext *Context; static ALCdevice *Device; void -al_set_midi(int freq, int buf_size) +al_set_midi(const int freq, const int buf_size) { midi_freq = freq; midi_buf_size = buf_size; } -void closeal(void); ALvoid alutInit(UNUSED(ALint *argc), UNUSED(ALbyte **argv)) { @@ -99,9 +99,10 @@ closeal(void) alSourceStopv(sources, source); alDeleteSources(sources, source); - if (sources == 3) + if (sources == 4) alDeleteBuffers(4, buffers_midi); alDeleteBuffers(4, buffers_cd); + alDeleteBuffers(4, buffers_music); alDeleteBuffers(4, buffers); alutExit(); @@ -112,14 +113,17 @@ closeal(void) void inital(void) { - 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; + float *buf = NULL; + float *music_buf = NULL; + float *wt_buf = NULL; + float *cd_buf = NULL; + float *midi_buf = NULL; + int16_t *buf_int16 = NULL; + int16_t *music_buf_int16 = NULL; + int16_t *wt_buf_int16 = NULL; + int16_t *cd_buf_int16 = NULL; + int16_t *midi_buf_int16 = NULL; - const char *mdn; int init_midi = 0; if (initialized) @@ -128,60 +132,80 @@ inital(void) alutInit(0, 0); atexit(closeal); - mdn = midi_out_device_get_internal_name(midi_output_device_current); - if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME)) + const char *mdn = midi_out_device_get_internal_name(midi_output_device_current); + if ((strcmp(mdn, "none") != 0) && (strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME) != 0)) 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; + MIDI buffer and source, otherwise, do not. */ + sources = 4 + !!init_midi; if (sound_is_float) { - buf = (float *) calloc((BUFLEN << 1), sizeof(float)); - cd_buf = (float *) calloc((CD_BUFLEN << 1), sizeof(float)); + buf = (float *) calloc((BUFLEN << 1), sizeof(float)); + music_buf = (float *) calloc((MUSICBUFLEN << 1), sizeof(float)); + wt_buf = (float *) calloc((WTBUFLEN << 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 *) calloc((BUFLEN << 1), sizeof(int16_t)); - cd_buf_int16 = (int16_t *) calloc((CD_BUFLEN << 1), sizeof(int16_t)); + buf_int16 = (int16_t *) calloc((BUFLEN << 1), sizeof(int16_t)); + music_buf_int16 = (int16_t *) calloc((MUSICBUFLEN << 1), sizeof(int16_t)); + wt_buf_int16 = (int16_t *) calloc((WTBUFLEN << 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); + alGenBuffers(4, buffers_music); + alGenBuffers(4, buffers_wt); if (init_midi) alGenBuffers(4, buffers_midi); if (init_midi) - alGenSources(3, source); + alGenSources(5, source); else - alGenSources(2, source); + alGenSources(4, 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); + alSource3f(source[0], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[0], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[0], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0f); 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); + alSource3f(source[1], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[1], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[1], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0f); alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source[2], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[2], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[2], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(source[3], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[3], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[3], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[3], AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source[3], 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[4], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[4], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[4], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[4], AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source[4], AL_SOURCE_RELATIVE, AL_TRUE); } if (sound_is_float) { memset(buf, 0, BUFLEN * 2 * sizeof(float)); - memset(cd_buf, 0, BUFLEN * 2 * sizeof(float)); + memset(cd_buf, 0, CD_BUFLEN * 2 * sizeof(float)); + memset(music_buf, 0, MUSICBUFLEN * 2 * sizeof(float)); + memset(wt_buf, 0, WTBUFLEN * 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)); + memset(cd_buf_int16, 0, CD_BUFLEN * 2 * sizeof(int16_t)); + memset(music_buf_int16, 0, MUSICBUFLEN * 2 * sizeof(int16_t)); + memset(wt_buf_int16, 0, WTBUFLEN * 2 * sizeof(int16_t)); if (init_midi) memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t)); } @@ -189,35 +213,47 @@ inital(void) 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_music[c], AL_FORMAT_STEREO_FLOAT32, music_buf, MUSICBUFLEN * 2 * sizeof(float), MUSIC_FREQ); + alBufferData(buffers_wt[c], AL_FORMAT_STEREO_FLOAT32, wt_buf, WTBUFLEN * 2 * sizeof(float), WT_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); + alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * (int) sizeof(float), midi_freq); } else { alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ); + alBufferData(buffers_music[c], AL_FORMAT_STEREO16, music_buf_int16, MUSICBUFLEN * 2 * sizeof(int16_t), MUSIC_FREQ); + alBufferData(buffers_wt[c], AL_FORMAT_STEREO16, wt_buf_int16, WTBUFLEN * 2 * sizeof(int16_t), WT_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); + alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * (int) sizeof(int16_t), midi_freq); } } alSourceQueueBuffers(source[0], 4, buffers); - alSourceQueueBuffers(source[1], 4, buffers_cd); + alSourceQueueBuffers(source[1], 4, buffers_music); + alSourceQueueBuffers(source[2], 4, buffers_wt); + alSourceQueueBuffers(source[3], 4, buffers_cd); if (init_midi) - alSourceQueueBuffers(source[2], 4, buffers_midi); + alSourceQueueBuffers(source[4], 4, buffers_midi); alSourcePlay(source[0]); alSourcePlay(source[1]); + alSourcePlay(source[2]); + alSourcePlay(source[3]); if (init_midi) - alSourcePlay(source[2]); + alSourcePlay(source[4]); if (sound_is_float) { if (init_midi) free(midi_buf); free(cd_buf); + free(wt_buf); + free(music_buf); free(buf); } else { if (init_midi) free(midi_buf_int16); free(cd_buf_int16); + free(wt_buf_int16); + free(music_buf_int16); free(buf_int16); } @@ -225,12 +261,11 @@ inital(void) } void -givealbuffer_common(void *buf, uint8_t src, int size, int freq) +givealbuffer_common(const void *buf, const uint8_t src, const int size, const int freq) { int processed; int state; ALuint buffer; - double gain; if (!initialized) return; @@ -243,34 +278,46 @@ givealbuffer_common(void *buf, uint8_t src, int size, int freq) alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed); if (processed >= 1) { - gain = pow(10.0, (double) sound_gain / 20.0); - alListenerf(AL_GAIN, gain); + const double gain = pow(10.0, (double) sound_gain / 20.0); + alListenerf(AL_GAIN, (float) gain); alSourceUnqueueBuffers(source[src], 1, &buffer); if (sound_is_float) - alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq); + alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * (int) sizeof(float), freq); else - alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq); + alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * (int) sizeof(int16_t), freq); alSourceQueueBuffers(source[src], 1, &buffer); } } void -givealbuffer(void *buf) +givealbuffer(const void *buf) { givealbuffer_common(buf, 0, BUFLEN << 1, FREQ); } void -givealbuffer_cd(void *buf) +givealbuffer_music(const void *buf) { - givealbuffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ); + givealbuffer_common(buf, 1, MUSICBUFLEN << 1, MUSIC_FREQ); } void -givealbuffer_midi(void *buf, uint32_t size) +givealbuffer_wt(const void *buf) { - givealbuffer_common(buf, 2, size, midi_freq); + givealbuffer_common(buf, 2, WTBUFLEN << 1, WT_FREQ); +} + +void +givealbuffer_cd(const void *buf) +{ + givealbuffer_common(buf, 3, CD_BUFLEN << 1, CD_FREQ); +} + +void +givealbuffer_midi(const void *buf, const uint32_t size) +{ + givealbuffer_common(buf, 4, (int) size, midi_freq); } diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index d2a05fd6f..4b7941959 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -63,46 +63,85 @@ ad1848_updatevolmask(ad1848_t *ad1848) ad1848->wave_vol_mask = 0x7f; } +static double +ad1848_get_default_freq(ad1848_t *ad1848) +{ + double freq = (ad1848->regs[8] & 1) ? 16934400.0 : 24576000.0; + + switch ((ad1848->regs[8] >> 1) & 7) { + default: + break; + + case 0: + freq /= 3072.0; + break; + case 1: + freq /= 1536.0; + break; + case 2: + freq /= 896.0; + break; + case 3: + freq /= 768.0; + break; + case 4: + freq /= 448.0; + break; + case 5: + freq /= 384.0; + break; + case 6: + freq /= 512.0; + break; + case 7: + freq /= 2560.0; + break; + } + + return freq; +} + static void ad1848_updatefreq(ad1848_t *ad1848) { - double freq = 0.0; - uint8_t set = 0; + double freq; if (ad1848->type >= AD1848_TYPE_CS4235) { if (ad1848->xregs[11] & 0x20) { - freq = 16934400LL; + freq = 16934400.0; switch (ad1848->xregs[13]) { + default: + freq /= 16.0 * MAX(ad1848->xregs[13], 21); + break; case 1: - freq /= 353; + freq /= 353.0; break; case 2: - freq /= 529; + freq /= 529.0; break; case 3: - freq /= 617; + freq /= 617.0; break; case 4: - freq /= 1058; + freq /= 1058.0; break; case 5: - freq /= 1764; + freq /= 1764.0; break; case 6: - freq /= 2117; + freq /= 2117.0; break; case 7: - freq /= 2558; - break; - default: - freq /= 16 * MAX(ad1848->xregs[13], 21); + freq /= 2558.0; break; } - set = 1; } else if (ad1848->regs[22] & 0x80) { - freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL; - set = (ad1848->regs[22] >> 1) & 0x3f; + const uint8_t set = (ad1848->regs[22] >> 1) & 0x3f; + freq = (ad1848->regs[22] & 1) ? 33868800.0 : 49152000.0; switch (ad1848->regs[10] & 0x30) { + default: + break; + case 0x00: freq /= 128 * set; break; @@ -112,48 +151,13 @@ ad1848_updatefreq(ad1848_t *ad1848) case 0x20: freq /= 256 * set; break; - - default: - break; } - set = 1; - } - } + } else + freq = ad1848_get_default_freq(ad1848); + } else + freq = ad1848_get_default_freq(ad1848); - 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; - - default: - break; - } - } - - ad1848->freq = freq; + ad1848->freq = (int) trunc(freq); ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq)); } @@ -251,6 +255,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) case 9: if (!ad1848->enable && (val & 0x41) == 0x01) { ad1848->adpcm_pos = 0; + ad1848->dma_ff = 0; if (ad1848->timer_latch) timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch); else @@ -450,18 +455,32 @@ 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); + int temp = (((byte & 0x0f) << 3) + 0x84); + int16_t dec; + temp <<= ((byte & 0x70) >> 4); + temp = (byte & 0x80) ? (0x84 - temp) : (temp - 0x84); + if (temp > 32767) + dec = 32767; + else if (temp < -32768) + dec = -32768; + else + dec = (int16_t) temp; + + return dec; } static int16_t ad1848_process_alaw(uint8_t byte) { byte ^= 0x55; - int16_t dec = (byte & 0x0f) << 4; - int seg = (byte & 0x70) >> 4; + int dec = ((byte & 0x0f) << 4);; + const int seg = (int) ((byte & 0x70) >> 4); switch (seg) { + default: + dec |= 0x108; + dec <<= seg - 1; + break; + case 0: dec |= 0x8; break; @@ -469,13 +488,34 @@ ad1848_process_alaw(uint8_t byte) case 1: dec |= 0x108; break; - - default: - dec |= 0x108; - dec <<= seg - 1; - break; } - return (byte & 0x80) ? dec : -dec; + dec = (byte & 0x80) ? dec : -dec; + return (int16_t) dec; +} + +static uint32_t +ad1848_dma_channel_read(ad1848_t *ad1848, int channel) +{ + uint32_t ret; + + if (channel >= 4) { + if (ad1848->dma_ff) { + ret = (ad1848->dma_data & 0xff00) >> 8; + ret |= (ad1848->dma_data & 0xffff0000); + } else { + ad1848->dma_data = dma_channel_read(channel); + + if (ad1848->dma_data == DMA_NODATA) + return DMA_NODATA; + + ret = ad1848->dma_data & 0xff; + } + + ad1848->dma_ff = !ad1848->dma_ff; + } else + ret = dma_channel_read(channel); + + return ret; } static int16_t @@ -485,7 +525,7 @@ ad1848_process_adpcm(ad1848_t *ad1848) if (ad1848->adpcm_pos++ & 1) { temp = (ad1848->adpcm_data & 0x0f) + ad1848->adpcm_step; } else { - ad1848->adpcm_data = dma_channel_read(ad1848->dma); + ad1848->adpcm_data = (int) (ad1848_dma_channel_read(ad1848, ad1848->dma) & 0xffff); temp = (ad1848->adpcm_data >> 4) + ad1848->adpcm_step; } if (temp < 0) @@ -499,9 +539,9 @@ ad1848_process_adpcm(ad1848_t *ad1848) else if (ad1848->adpcm_ref < 0x00) ad1848->adpcm_ref = 0x00; - ad1848->adpcm_step = (ad1848->adpcm_step + adjustMap4[temp]) & 0xff; + ad1848->adpcm_step = (int8_t) ((ad1848->adpcm_step + adjustMap4[temp]) & 0xff); - return (ad1848->adpcm_ref ^ 0x80) << 8; + return (int16_t) ((ad1848->adpcm_ref ^ 0x80) << 8); } static void @@ -521,42 +561,42 @@ ad1848_poll(void *priv) 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; + ad1848->out_l = ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8); 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; + ad1848->out_l = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8); + ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8); break; case 0x20: /* Mono, 8-bit Mu-Law */ - ad1848->out_l = ad1848->out_r = ad1848_process_mulaw(dma_channel_read(ad1848->dma)); + ad1848->out_l = ad1848->out_r = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); 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)); + ad1848->out_l = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); + ad1848->out_r = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); 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; + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_l = ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp); 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; + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_l = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp); + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp); break; case 0x60: /* Mono, 8-bit A-Law */ - ad1848->out_l = ad1848->out_r = ad1848_process_alaw(dma_channel_read(ad1848->dma)); + ad1848->out_l = ad1848->out_r = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); break; 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)); + ad1848->out_l = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); + ad1848->out_r = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma)); break; /* 0x80 and 0x90 reserved */ @@ -571,15 +611,15 @@ ad1848_poll(void *priv) 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); + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_l = ad1848->out_r = (int16_t) (ad1848_dma_channel_read(ad1848, 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); + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_l = (int16_t) (ad1848_dma_channel_read(ad1848, ad1848->dma) | (temp << 8)); + temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma); + ad1848->out_r = (int16_t) (ad1848_dma_channel_read(ad1848, ad1848->dma) | (temp << 8)); break; /* 0xe0 and 0xf0 reserved */ @@ -591,12 +631,12 @@ ad1848_poll(void *priv) 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; + ad1848->out_l = (int16_t) ((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; + ad1848->out_r = (int16_t) ((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); diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index 5d0d7c7aa..f5eae9b93 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -112,7 +112,7 @@ adlib_init(UNUSED(const device_t *info)) adlib->opl.read, NULL, NULL, adlib->opl.write, NULL, NULL, adlib->opl.priv); - sound_add_handler(adlib_get_buffer, adlib); + music_add_handler(adlib_get_buffer, adlib); return adlib; } diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 71cbbcaa6..488dcb8a6 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -788,13 +788,10 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) 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; } @@ -857,8 +854,8 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) /*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); + lowpass = adgold_lowpass_iir(0, 0, temp); + highpass = adgold_highpass_iir(0, 0, temp); if (adgold->bass > 6) temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; else if (adgold->bass < 6) @@ -874,8 +871,124 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) 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); + lowpass = adgold_lowpass_iir(0, 1, temp); + highpass = adgold_highpass_iir(0, 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->pos = 0; + + free(adgold_buffer); +} + +static void +adgold_get_music_buffer(int32_t *buffer, int len, void *priv) +{ + adgold_t *adgold = (adgold_t *) priv; + int16_t *adgold_buffer = malloc(sizeof(int16_t) * len * 2); + if (adgold_buffer == NULL) + fatal("adgold_buffer = NULL"); + + 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 + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2; + } + + 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(1, 0, temp); + highpass = adgold_highpass_iir(1, 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, 1, temp); + highpass = adgold_highpass_iir(1, 1, temp); if (adgold->bass > 6) temp += (lowpass * bass_attenuation[adgold->bass]) >> 14; else if (adgold->bass < 6) @@ -892,7 +1005,6 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) } adgold->opl.reset_buffer(adgold->opl.priv); - adgold->pos = 0; free(adgold_buffer); } @@ -1054,6 +1166,8 @@ adgold_init(UNUSED(const device_t *info)) timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1); sound_add_handler(adgold_get_buffer, adgold); + music_add_handler(adgold_get_music_buffer, adgold); + sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold); if (device_get_config_int("receive_input")) diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index 80d668599..28ab2b7ac 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1237,6 +1237,7 @@ azt_init(const device_t *info) if (azt2316a->sb->opl_enabled) fm_driver_get(FM_YMF262, &azt2316a->sb->opl); + sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1); 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); @@ -1253,6 +1254,8 @@ azt_init(const device_t *info) azt2316a_create_config_word(azt2316a); sound_add_handler(azt2316a_get_buffer, azt2316a); + if (azt2316a->sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sbpro, azt2316a->sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, azt2316a->sb); if (azt2316a->cur_mpu401_enabled) { diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index fad1d76b9..90aa0b0dd 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -543,13 +543,31 @@ cs423x_ctxswitch_write(uint16_t addr, UNUSED(uint8_t val), void *priv) static void cs423x_get_buffer(int32_t *buffer, int len, void *priv) +{ + cs423x_t *dev = (cs423x_t *) priv; + + /* Output audio from the WSS codec, and also the OPL if we're in charge of it. */ + ad1848_update(&dev->ad1848); + + /* Don't output anything if the analog section is powered down. */ + if (!(dev->indirect_regs[2] & 0xa4)) { + for (int c = 0; c < len * 2; c += 2) { + buffer[c] += dev->ad1848.buffer[c] / 2; + buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2; + } + } + + dev->ad1848.pos = 0; +} + +static void +cs423x_get_music_buffer(int32_t *buffer, int len, void *priv) { 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) opl_buf = dev->sb->opl.update(dev->sb->opl.priv); @@ -560,13 +578,9 @@ cs423x_get_buffer(int32_t *buffer, int len, void *priv) 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; } } - dev->ad1848.pos = 0; if (opl_wss) dev->sb->opl.reset_buffer(dev->sb->opl.priv); } @@ -846,6 +860,7 @@ cs423x_init(const device_t *info) /* Initialize RAM, registers and WSS codec. */ cs423x_reset(dev); sound_add_handler(cs423x_get_buffer, dev); + music_add_handler(cs423x_get_music_buffer, dev); /* Add Control/RAM backdoor handlers for CS4235. */ dev->ad1848.cram_priv = dev; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index 22435c065..5f13d2f8e 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -1758,8 +1758,7 @@ int32_t old_vol[32] = { 0 }; void emu8k_update(emu8k_t *emu8k) { - int new_pos = (sound_pos_global * FREQ_44100) / SOUND_FREQ; - if (emu8k->pos >= new_pos) + if (emu8k->pos >= wavetable_pos_global) return; int32_t *buf; @@ -1768,16 +1767,16 @@ emu8k_update(emu8k_t *emu8k) /* 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])); + memset(buf, 0, 2 * (wavetable_pos_global - emu8k->pos) * sizeof(emu8k->buffer[0])); + memset(&emu8k->chorus_in_buffer[emu8k->pos], 0, (wavetable_pos_global - emu8k->pos) * sizeof(emu8k->chorus_in_buffer[0])); + memset(&emu8k->reverb_in_buffer[emu8k->pos], 0, (wavetable_pos_global - 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++) { + for (pos = emu8k->pos; pos < wavetable_pos_global; pos++) { int32_t dat; if (emu_voice->cvcf_curr_volume) { @@ -2121,29 +2120,14 @@ emu8k_update(emu8k_t *emu8k) } 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; - } + emu8k_work_reverb(&emu8k->reverb_in_buffer[emu8k->pos], buf, &emu8k->reverb_engine, wavetable_pos_global - emu8k->pos); + emu8k_work_chorus(&emu8k->chorus_in_buffer[emu8k->pos], buf, &emu8k->chorus_engine, wavetable_pos_global - emu8k->pos); + emu8k_work_eq(buf, wavetable_pos_global - emu8k->pos); /* Update EMU clock. */ - emu8k->wc += (new_pos - emu8k->pos); + emu8k->wc += (wavetable_pos_global - emu8k->pos); - emu8k->pos = new_pos; + emu8k->pos = wavetable_pos_global; } void @@ -2172,7 +2156,7 @@ emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) int c; double out; - fp = rom_fopen("roms/sound/creative/awe32.raw", "rb"); + fp = rom_fopen(EMU8K_ROM_PATH, "rb"); if (!fp) fatal("AWE32.RAW not found\n"); diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 21cc66f04..d98b3ccc2 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -68,6 +68,11 @@ fm_driver_get(int chip_id, fm_drv_t *drv) *drv = ymfm_drv; drv->priv = device_add_inst(&ymf278b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); break; + + case FM_ESFM: + *drv = esfmu_opl_drv; + drv->priv = device_add_inst(&esfm_esfmu_device, fm_dev_inst[fm_driver][chip_id]++); + break; default: return 0; diff --git a/src/sound/snd_opl_esfm.c b/src/sound/snd_opl_esfm.c new file mode 100644 index 000000000..78cbec11d --- /dev/null +++ b/src/sound/snd_opl_esfm.c @@ -0,0 +1,355 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ESFMu ESFM emulator. + * + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Alexey Khokholov (Nuke.YKT) + * Cacodemon345 + * + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) + * Copyright 2024 Cacodemon345 + */ + +#include +#include +#include +#include +#include + +#include "esfmu/esfm.h" + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/sound.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/snd_opl.h> + +#define RSM_FRAC 10 + +typedef struct { + esfm_chip opl; + int8_t flags; + int8_t pad; + + uint8_t status; + uint8_t timer_ctrl; + uint16_t timer_count[2]; + uint16_t timer_cur_count[2]; + + pc_timer_t timers[2]; + + int16_t samples[2]; + + int pos; + int32_t buffer[MUSICBUFLEN * 2]; +} esfm_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 esfm_do_log = ENABLE_OPL_LOG; + +static void +esfm_log(const char *fmt, ...) +{ + va_list ap; + + if (esfm_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define esfm_log(fmt, ...) +#endif + +void +esfm_generate_raw(esfm_drv_t *dev, int32_t *bufp) +{ + ESFM_generate(&dev->opl, bufp); +} + +void +esfm_drv_generate_stream(esfm_drv_t *dev, int32_t *sndptr, uint32_t num) +{ + for (uint32_t i = 0; i < num; i++) { + esfm_generate_raw(dev, sndptr); + sndptr += 2; + } +} + +static void +esfm_timer_tick(esfm_drv_t *dev, int tmr) +{ + dev->timer_cur_count[tmr] = (dev->timer_cur_count[tmr] + 1) & 0xff; + + esfm_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]; + + esfm_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 +esfm_timer_control(esfm_drv_t *dev, int tmr, int start) +{ + timer_on_auto(&dev->timers[tmr], 0.0); + + if (start) { + esfm_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) + esfm_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 { + esfm_log("Timer %i stopped\n", tmr); + if (tmr == 1) { + dev->status &= ~STAT_TMR2_OVER; + } else + dev->status &= ~STAT_TMR1_OVER; + } +} + +static void +esfm_timer_1(void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + esfm_timer_tick(dev, 0); +} + +static void +esfm_timer_2(void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + esfm_timer_tick(dev, 1); +} + +static void +esfm_drv_set_do_cycles(void *priv, int8_t do_cycles) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + if (do_cycles) + dev->flags |= FLAG_CYCLES; + else + dev->flags &= ~FLAG_CYCLES; +} + +static void * +esfm_drv_init(const device_t *info) +{ + esfm_drv_t *dev = (esfm_drv_t *) calloc(1, sizeof(esfm_drv_t)); + dev->flags = FLAG_CYCLES | FLAG_OPL3; + + /* Initialize the ESFMu object. */ + ESFM_init(&dev->opl); + + timer_add(&dev->timers[0], esfm_timer_1, dev, 0); + timer_add(&dev->timers[1], esfm_timer_2, dev, 0); + + return dev; +} + +static void +esfm_drv_close(void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + free(dev); +} + +static int32_t * +esfm_drv_update(void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + if (dev->pos >= music_pos_global) + return dev->buffer; + + esfm_drv_generate_stream(dev, + &dev->buffer[dev->pos * 2], + music_pos_global - dev->pos); + + for (; dev->pos < music_pos_global; dev->pos++) { + dev->buffer[dev->pos * 2] /= 2; + dev->buffer[(dev->pos * 2) + 1] /= 2; + } + + return dev->buffer; +} + +static void +esfm_drv_reset_buffer(void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + dev->pos = 0; +} + +static uint8_t +esfm_drv_read(uint16_t port, void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + if (dev->flags & FLAG_CYCLES) + cycles -= ((int) (isa_timing * 8)); + + esfm_drv_update(dev); + + uint8_t ret = 0xff; + + switch (port & 0x0003) { + case 0x0000: + ret = dev->status; + if (dev->status & STAT_TMR_OVER) + ret |= STAT_TMR_ANY; + break; + case 0x0001: + ret = ESFM_read_port(&dev->opl, port & 3); + switch (dev->opl.addr_latch & 0x5ff) { + case 0x402: + ret = dev->timer_count[0]; + break; + case 0x403: + ret = dev->timer_count[1]; + break; + case 0x404: + ret = dev->timer_ctrl; + break; + } + break; + case 0x0002: + case 0x0003: + ret = 0xff; + break; + } + + return ret; +} + +static void +esfm_drv_write_buffered(esfm_drv_t *dev, uint8_t val) +{ + uint16_t p = dev->opl.addr_latch & 0x07ff; + + if (dev->opl.native_mode) { + p -= 0x400; + } + p &= 0x1ff; + + switch (p) { + case 0x002: /* Timer 1 */ + dev->timer_count[0] = val; + esfm_log("Timer 0 count now: %i\n", dev->timer_count[0]); + break; + + case 0x003: /* Timer 2 */ + dev->timer_count[1] = val; + esfm_log("Timer 1 count now: %i\n", dev->timer_count[1]); + break; + + case 0x004: /* Timer control */ + if (val & CTRL_RESET) { + esfm_log("Resetting timer status...\n"); + dev->status &= ~STAT_TMR_OVER; + } else { + dev->timer_ctrl = val; + esfm_timer_control(dev, 0, val & CTRL_TMR1_START); + esfm_timer_control(dev, 1, val & CTRL_TMR2_START); + esfm_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val); + } + break; + + default: + break; + } + + ESFM_write_reg_buffered_fast(&dev->opl, dev->opl.addr_latch, val); +} + +static void +esfm_drv_write(uint16_t port, uint8_t val, void *priv) +{ + esfm_drv_t *dev = (esfm_drv_t *) priv; + + if (dev->flags & FLAG_CYCLES) + cycles -= ((int) (isa_timing * 8)); + + esfm_drv_update(dev); + + if (dev->opl.native_mode) { + if ((port & 0x0003) == 0x0001) + esfm_drv_write_buffered(dev, val); + else { + ESFM_write_port(&dev->opl, port & 3, val); + } + } else { + if ((port & 0x0001) == 0x0001) + esfm_drv_write_buffered(dev, val); + else { + ESFM_write_port(&dev->opl, port & 3, val); + } + } +} + +const device_t esfm_esfmu_device = { + .name = "ESS Technology ESFM (ESFMu)", + .internal_name = "esfm_esfmu", + .flags = 0, + .local = FM_ESFM, + .init = esfm_drv_init, + .close = esfm_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const fm_drv_t esfmu_opl_drv = { + &esfm_drv_read, + &esfm_drv_write, + &esfm_drv_update, + &esfm_drv_reset_buffer, + &esfm_drv_set_do_cycles, + NULL, + NULL, +}; diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index e4131f1fe..95b61638e 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -55,7 +55,8 @@ #define WRBUF_DELAY 1 #define RSM_FRAC 10 -#define OPL_FREQ FREQ_48000 +// #define OPL_FREQ FREQ_48000 +#define OPL_FREQ FREQ_49716 // Channel types enum { @@ -189,7 +190,7 @@ typedef struct { pc_timer_t timers[2]; int pos; - int32_t buffer[SOUNDBUFLEN * 2]; + int32_t buffer[MUSICBUFLEN * 2]; } nuked_drv_t; enum { @@ -1381,11 +1382,20 @@ nuked_generate_resampled(nuked_t *dev, int32_t *bufp) dev->samplecnt += 1 << RSM_FRAC; } +void +nuked_generate_raw(nuked_t *dev, int32_t *bufp) +{ + nuked_generate(dev, dev->samples); + + bufp[0] = (int32_t) dev->samples[0]; + bufp[1] = (int32_t) dev->samples[1]; +} + void nuked_generate_stream(nuked_t *dev, int32_t *sndptr, uint32_t num) { for (uint32_t i = 0; i < num; i++) { - nuked_generate_resampled(dev, sndptr); + nuked_generate_raw(dev, sndptr); sndptr += 2; } } @@ -1533,14 +1543,14 @@ nuked_drv_update(void *priv) { nuked_drv_t *dev = (nuked_drv_t *) priv; - if (dev->pos >= sound_pos_global) + if (dev->pos >= music_pos_global) return dev->buffer; nuked_generate_stream(&dev->opl, &dev->buffer[dev->pos * 2], - sound_pos_global - dev->pos); + music_pos_global - dev->pos); - for (; dev->pos < sound_pos_global; dev->pos++) { + for (; dev->pos < music_pos_global; dev->pos++) { dev->buffer[dev->pos * 2] /= 2; dev->buffer[(dev->pos * 2) + 1] /= 2; } @@ -1581,17 +1591,17 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv) nuked_write_reg_buffered(&dev->opl, dev->port, val); switch (dev->port) { - case 0x02: /* Timer 1 */ + case 0x002: /* Timer 1 */ dev->timer_count[0] = val; nuked_log("Timer 0 count now: %i\n", dev->timer_count[0]); break; - case 0x03: /* Timer 2 */ + case 0x003: /* Timer 2 */ dev->timer_count[1] = val; nuked_log("Timer 1 count now: %i\n", dev->timer_count[1]); break; - case 0x04: /* Timer control */ + case 0x004: /* Timer control */ if (val & CTRL_RESET) { nuked_log("Resetting timer status...\n"); dev->status &= ~STAT_TMR_OVER; @@ -1603,6 +1613,10 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv) } break; + case 0x105: + dev->opl.newm = val & 0x01; + break; + default: break; } diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp index 0f996f6bc..1da97adfa 100644 --- a/src/sound/snd_opl_ymfm.cpp +++ b/src/sound/snd_opl_ymfm.cpp @@ -51,10 +51,11 @@ enum { class YMFMChipBase { public: - YMFMChipBase(UNUSED(uint32_t clock), fm_type type, UNUSED(uint32_t samplerate)) + YMFMChipBase(UNUSED(uint32_t clock), fm_type type, uint32_t samplerate) : m_buf_pos(0) , m_flags(0) , m_type(type) + , m_samplerate(samplerate) { memset(m_buffer, 0, sizeof(m_buffer)); } @@ -73,16 +74,17 @@ public: 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; + int32_t m_buffer[MUSICBUFLEN * 2]; + int m_buf_pos; + int *m_buf_pos_global; + int8_t m_flags; + fm_type m_type; + uint32_t m_samplerate; }; template @@ -97,11 +99,12 @@ public: { 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; + 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; + m_buf_pos_global = (samplerate == FREQ_49716) ? &music_pos_global : &wavetable_pos_global; if (m_type == FM_YMF278B) { if (rom_load_linear("roms/sound/yamaha/yrw801.rom", 0, 0x200000, 0, m_yrw801) == 0) { @@ -168,8 +171,14 @@ public: } } +#if 0 virtual void generate_resampled(int32_t *data, uint32_t num_samples) override { + if ((m_samplerate == FREQ_49716) || (m_samplerate == FREQ_44100)) { + generate(data, num_samples); + return; + } + for (uint32_t i = 0; i < num_samples; i++) { while (m_samplecnt >= m_rateratio) { m_oldsamples[0] = m_samples[0]; @@ -203,15 +212,16 @@ public: m_samplecnt += 1 << RSM_FRAC; } } +#endif virtual int32_t *update() override { - if (m_buf_pos >= sound_pos_global) + if (m_buf_pos >= *m_buf_pos_global) return m_buffer; - generate_resampled(&m_buffer[m_buf_pos * 2], sound_pos_global - m_buf_pos); + generate(&m_buffer[m_buf_pos * 2], *m_buf_pos_global - m_buf_pos); - for (; m_buf_pos < sound_pos_global; m_buf_pos++) { + for (; m_buf_pos < *m_buf_pos_global; m_buf_pos++) { m_buffer[m_buf_pos * 2] /= 2; m_buffer[(m_buf_pos * 2) + 1] /= 2; } @@ -314,21 +324,21 @@ ymfm_drv_init(const device_t *info) switch (info->local) { default: case FM_YM3812: - fm = (YMFMChipBase *) new YMFMChip(3579545, FM_YM3812, OPL_FREQ); + fm = (YMFMChipBase *) new YMFMChip(3579545, FM_YM3812, FREQ_49716); break; case FM_YMF262: - fm = (YMFMChipBase *) new YMFMChip(14318181, FM_YMF262, OPL_FREQ); + fm = (YMFMChipBase *) new YMFMChip(14318181, FM_YMF262, FREQ_49716); 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); + fm = (YMFMChipBase *) new YMFMChip(14318181, FM_YMF289B, FREQ_49716); break; case FM_YMF278B: - fm = (YMFMChipBase *) new YMFMChip(33868800, FM_YMF278B, OPL_FREQ); + fm = (YMFMChipBase *) new YMFMChip(33868800, FM_YMF278B, FREQ_44100); break; } @@ -403,7 +413,8 @@ static void ymfm_drv_generate(void *priv, int32_t *data, uint32_t num_samples) { YMFMChipBase *drv = (YMFMChipBase *) priv; - drv->generate_resampled(data, num_samples); + // drv->generate_resampled(data, num_samples); + drv->generate(data, num_samples); } const device_t ym3812_ymfm_device = { diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index d7afca382..3b649639a 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -391,6 +391,9 @@ optimc_init(const device_t *info) optimc->sb = calloc(1, sizeof(sb_t)); optimc->sb->opl_enabled = 1; + optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; + + sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B); 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); @@ -400,7 +403,6 @@ optimc_init(const device_t *info) 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); @@ -411,6 +413,10 @@ optimc_init(const device_t *info) 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); + if (optimc->fm_type == FM_YMF278B) + wavetable_add_handler(sb_get_music_buffer_sbpro, optimc->sb); + else + music_add_handler(sb_get_music_buffer_sbpro, optimc->sb); 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)); diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 674acfcbb..243332257 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1,9 +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. + * + * Pro Audio Spectrum Plus and 16 emulation. + * + * Original PAS uses: + * - 2 x OPL2; + * - PIT - sample rate/count; + * - LMC835N/LMC1982 - mixer; + * - YM3802 - MIDI Control System. + * + * 9A01 - I/O base: + * - base >> 2. + * + * All below + I/O 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 - ????. + * 2789 - Board revision. + * + * 8389: + * - Bit 2 - 8/16 bit. + * + * BF88 - Wait states. + * + * EF8B: + * - Bit 3 - 16 bits okay ?. + * + * 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 address: + * - Bits 0-3 - Address bits 4-7. + * + * FB8A - SB IRQ/DMA: + * - Bits 3-5 - IRQ; + * - Bits 6-7 - DMA. + * + * FF88 - board model: + * - 3 = PAS16. + * + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, + * + * Copyright 2008-2024 Sarah Walker. + * Copyright 2024 Miran Grca. + */ +#include #include #include #include #include #include -#include #define HAVE_STDARG_H #include "cpu.h" @@ -11,170 +99,178 @@ #include <86box/device.h> #include <86box/dma.h> #include <86box/filters.h> +#include <86box/plat_unused.h> #include <86box/io.h> +#include <86box/mem.h> +#include <86box/midi.h> #include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/rom.h> +#include <86box/scsi_device.h> +#include <86box/scsi_ncr5380.h> +#include <86box/scsi_t128.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 +typedef struct nsc_mixer_t { + double master_l; + double master_r; + int bass; + int treble; - 9A01 - IO base - base >> 2 + double fm_l; + double fm_r; + double imixer_l; + double imixer_r; + double line_l; + double line_r; + double cd_l; + double cd_r; + double mic_l; + double mic_r; + double pcm_l; + double pcm_r; + double speaker_l; + double speaker_r; - All below + IO base + uint8_t lmc1982_regs[8]; + uint8_t lmc835_regs[32]; - B89 - interrupt status / clear - bit 2 - sample rate - bit 3 - PCM - bit 4 - MIDI + uint8_t im_state; + uint16_t im_data[4]; +} nsc_mixer_t; - B88 - Audio mixer control register +typedef struct mv508_mixer_t { + double master_l; + double master_r; - B8A - Audio filter control - bit 5 - mute? + int bass; + int treble; - B8B - interrupt mask / board ID - bits 5-7 - board ID (read only on PAS16) + double fm_l; + double fm_r; + double imixer_l; + double imixer_r; + double line_l; + double line_r; + double cd_l; + double cd_r; + double mic_l; + double mic_r; + double pcm_l; + double pcm_r; + double speaker_l; + double speaker_r; + double sb_l; + double sb_r; - 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 - - 2789 - board revision - - 8389 - - bit 2 - 8/16 bit - - BF88 - wait states - - EF8B - - bit 3 - 16 bits okay ? - - 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 -*/ + uint8_t index; + uint8_t regs[3][128]; +} mv508_mixer_t; typedef struct pas16_t { - uint16_t base; + uint8_t this_id; + uint8_t board_id; + uint8_t master_ff; + uint8_t has_scsi; + uint8_t dma; + uint8_t sb_irqdma; + uint8_t type; + uint8_t filter; - int irq; - int dma; - - uint8_t audiofilt; - - uint8_t audio_mixer; - - 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 audiofilt; + uint8_t audio_mixer; + uint8_t compat; + uint8_t compat_base; + 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; + uint8_t prescale_div; + uint8_t stereo_lr; + uint8_t dma8_ff; + uint8_t waitstates; + uint8_t enhancedscsi; + uint8_t sys_conf_1; + uint8_t sys_conf_2; + uint8_t sys_conf_3; + uint8_t sys_conf_4; + uint8_t midi_ctrl; + uint8_t midi_stat; + uint8_t midi_data; + uint8_t fifo_stat; + + uint8_t timeout_count; + uint8_t timeout_status; + uint8_t pad_array[6]; + + uint8_t midi_queue[256]; + + uint16_t base; + uint16_t new_base; + uint16_t sb_compat_base; + uint16_t mpu401_base; + uint16_t dma8_dat; + uint16_t ticks; uint16_t pcm_dat_l; uint16_t pcm_dat_r; - uint8_t sb_irqdma; + int32_t pcm_buffer[2][SOUNDBUFLEN * 2]; - int stereo_lr; + int pos; + int midi_r; + int midi_w; + int midi_uart_out; + int midi_uart_in; + int sysex; - uint8_t sys_conf_1; - uint8_t sys_conf_2; - uint8_t sys_conf_3; - uint8_t sys_conf_4; + int irq; + int scsi_irq; - 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; + nsc_mixer_t nsc_mixer; + mv508_mixer_t mv508_mixer; fm_drv_t opl; sb_dsp_t dsp; - int16_t pcm_buffer[2][SOUNDBUFLEN]; + mpu_t * mpu; - int pos; + pitf_t * pit; + + t128_t * scsi; + + pc_timer_t scsi_timer; } 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 uint8_t pas16_next = 0; + 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 }; enum { PAS16_INT_SAMP = 0x04, - PAS16_INT_PCM = 0x08 + PAS16_INT_PCM = 0x08, + PAS16_INT_MIDI = 0x10 }; enum { PAS16_PCM_MONO = 0x20, - PAS16_PCM_ENA = 0x40 + PAS16_PCM_ENA = 0x40, + PAS16_PCM_DMA_ENA = 0x80 }; enum { @@ -186,6 +282,387 @@ enum { PAS16_FILT_MUTE = 0x20 }; +enum { + STATE_SM_IDLE = 0x00, + STATE_LMC1982_ADDR = 0x10, + STATE_LMC1982_ADDR_0 = 0x10, + STATE_LMC1982_ADDR_1, + STATE_LMC1982_ADDR_2, + STATE_LMC1982_ADDR_3, + STATE_LMC1982_ADDR_4, + STATE_LMC1982_ADDR_5, + STATE_LMC1982_ADDR_6, + STATE_LMC1982_ADDR_7, + STATE_LMC1982_ADDR_OVER, + STATE_LMC1982_DATA = 0x10, + STATE_LMC1982_DATA_0 = 0x20, + STATE_LMC1982_DATA_1, + STATE_LMC1982_DATA_2, + STATE_LMC1982_DATA_3, + STATE_LMC1982_DATA_4, + STATE_LMC1982_DATA_5, + STATE_LMC1982_DATA_6, + STATE_LMC1982_DATA_7, + STATE_LMC1982_DATA_8, + STATE_LMC1982_DATA_9, + STATE_LMC1982_DATA_A, + STATE_LMC1982_DATA_B, + STATE_LMC1982_DATA_C, + STATE_LMC1982_DATA_D, + STATE_LMC1982_DATA_E, + STATE_LMC1982_DATA_F, + STATE_LMC1982_DATA_OVER, + STATE_LMC835_DATA = 0x40, + STATE_LMC835_DATA_0 = 0x40, + STATE_LMC835_DATA_1, + STATE_LMC835_DATA_2, + STATE_LMC835_DATA_3, + STATE_LMC835_DATA_4, + STATE_LMC835_DATA_5, + STATE_LMC835_DATA_6, + STATE_LMC835_DATA_7, + STATE_LMC835_DATA_OVER, +}; + +#define STATE_DATA_MASK 0x07 +#define STATE_DATA_MASK_W 0x0f + +#define LMC1982_ADDR 0x00 +#define LMC1982_DATA 0x01 +#define LMC835_ADDR 0x02 +#define LMC835_DATA 0x03 + +#define LMC835_FLAG_ADDR 0x80 + +#define SERIAL_MIXER_IDENT 0x10 +#define SERIAL_MIXER_STROBE 0x04 +#define SERIAL_MIXER_CLOCK 0x02 +#define SERIAL_MIXER_DATA 0x01 +#define SERIAL_MIXER_RESET_PCM 0x01 + +#define PAS16_PCM_AND_DMA_ENA (PAS16_PCM_ENA | PAS16_PCM_DMA_ENA) + +/* + LMC1982CIN registers (data bits 7 and 6 are always don't care): + - 40 = Mode (0x01 = INPUT2); + - 41 = 0 = Loudness (1 = on, 0 = off), 1 = Stereo Enhance (1 = on, 0 = off) + (0x00); + - 42 = Bass, 00-0c (0x06); + - 43 = Treble, 00-0c (0x06); + - 45 [L] / 44 [R] = Master, 28-00, counting down (0x28, later 0xa8); + - 46 = ???? (0x05 = Stereo). + */ +#define LMC1982_REG_MASK 0xf8 /* LMC1982CIN: Register Mask */ +#define LMC1982_REG_VALID 0x40 /* LMC1982CIN: Register Valid Value */ + +#define LMC1982_REG_ISELECT 0x00 /* LMC1982CIN: Input Select + Mute */ +#define LMC1982_REG_LES 0x01 /* LMC1982CIN: Loudness, Enhanced Stereo */ +#define LMC1982_REG_BASS 0x02 /* LMC1982CIN: Bass */ +#define LMC1982_REG_TREBLE 0x03 /* LMC1982CIN: Treble */ +/* The Windows 95 driver indicates left and right are swapped in the wiring. */ +#define LMC1982_REG_VOL_L 0x04 /* LMC1982CIN: Left Volume */ +#define LMC1982_REG_VOL_R 0x05 /* LMC1982CIN: Right Volume */ +#define LMC1982_REG_MODE 0x06 /* LMC1982CIN: Mode */ +#define LMC1982_REG_DINPUT 0x07 /* LMC1982CIN: Digital Input 1 and 2 */ + +/* Bits 7-2: Don't care. */ +#define LMC1982_ISELECT_MASK 0x03 /* LMC1982CIN: Input Select: Mask */ +#define LMC1982_ISELECT_I1 0x00 /* LMC1982CIN: Input Select: INPUT1 */ +#define LMC1982_ISELECT_I2 0x01 /* LMC1982CIN: Input Select: INPUT2 */ +#define LMC1982_ISELECT_NA 0x02 /* LMC1982CIN: Input Select: N/A */ +#define LMC1982_ISELECT_MUTE 0x03 /* LMC1982CIN: Input Select: MUTE */ + +/* Bits 7-2: Don't care. */ +#define LMC1982_LES_MASK 0x03 /* LMC1982CIN: Loudness, Enhanced Stereo: Mask */ +#define LMC1982_LES_BOTH_OFF 0x00 /* LMC1982CIN: Loudness OFF, Enhanced Stereo OFF */ +#define LMC1982_L_ON_ES_OFF 0x01 /* LMC1982CIN: Loudness ON, Enhanced Stereo OFF */ +#define LMC1982_L_OFF_ES_ON 0x02 /* LMC1982CIN: Loudness OFF, Enhanced Stereo ON */ +#define LMC1982_LES_BOTH_ON 0x03 /* LMC1982CIN: Loudness OFF, Enhanced Stereo ON */ + +/* Bits 7-3: Don't care. */ +#define LMC1982_MODE_MASK 0x07 /* LMC1982CIN: Mode: Mask */ +#define LMC1982_MODE_MONO_L 0x04 /* LMC1982CIN: Mode: Left Mono */ +#define LMC1982_MODE_STEREO 0x05 /* LMC1982CIN: Mode: Stereo */ +#define LMC1982_MODE_MONO_R 0x06 /* LMC1982CIN: Mode: Right Mono */ +#define LMC1982_MODE_MONO_R_2 0x07 /* LMC1982CIN: Mode: Right Mono (Alternate value) */ + +/* Bits 7-2: Don't care. */ +#define LMC1982_DINPUT_MASK 0x03 /* LMC1982CIN: Digital Input 1 and 2: Mask */ +#define LMC1982_DINPUT_DI1 0x01 /* LMC1982CIN: Digital Input 1 */ +#define LMC1982_DINPUT_DI2 0x02 /* LMC1982CIN: Digital Input 2 */ + +/* + LMC835N registers: + - 01 [L] / 08 [R] = FM, 00-2f, bit 6 = clear, but the DOS driver sets + the bit, indicating a volume boost (0x69); + - 02 [L] / 09 [R] = Rec. monitor, 00-2f, bit 6 = clear (0x29); + - 03 [L] / 0A [R] = Line in, 00-2f, bit 6 = clear, except for the DOS + driver (0x69); + - 04 [L] / 0B [R] = CD, 00-2f, bit 6 = clear, except for the DOS driver + (0x69); + - 05 [L] / 0C [R] = Microphone, 00-2f, bit 6 = clear, except for the DOS + driver (0x44); + - 06 [L] / 0D [R] = Wave out, 00-2f, bit 6 = set, except for DOS driver, + which clears the bit (0x29); + - 07 [L] / 0E [R] = PC speaker, 00-2f, bit 6 = clear, except for the DOS + drive (0x06). + The registers for which the DOS driver sets the boost, also have bit 6 + set in the address, despite the fact it should be a don't care - why? + Apparently, no Sound Blaster control. +*/ +#define LMC835_REG_MODE 0x00 /* LMC835N: Mode, not an actual register, but our internal register + to store the mode for Channels A (1-7) and B (8-e). */ + +#define LMC835_REG_FM_L 0x01 /* LMC835N: FM Left */ +#define LMC835_REG_IMIXER_L 0x02 /* LMC835N: Record Monitor Left */ +#define LMC835_REG_LINE_L 0x03 /* LMC835N: Line in Left */ +#define LMC835_REG_CDROM_L 0x04 /* LMC835N: CD Left */ +#define LMC835_REG_MIC_L 0x05 /* LMC835N: Microphone Left */ +#define LMC835_REG_PCM_L 0x06 /* LMC835N: Wave out Left */ +#define LMC835_REG_SPEAKER_L 0x07 /* LMC83N5: PC speaker Left */ + +#define LMC835_REG_FM_R 0x08 /* LMC835N: FM Right */ +#define LMC835_REG_IMIXER_R 0x09 /* LMC835N: Record Monitor Right */ +#define LMC835_REG_LINE_R 0x0a /* LMC835N: Line in Right */ +#define LMC835_REG_CDROM_R 0x0b /* LMC835N: CD Right */ +#define LMC835_REG_MIC_R 0x0c /* LMC835N: Microphone Right */ +#define LMC835_REG_PCM_R 0x0d /* LMC835N: Wave out Right */ +#define LMC835_REG_SPEAKER_R 0x0e /* LMC83N5: PC speaker Right */ + +#define MV508_ADDRESS 0x80 /* Flag indicating it is the address */ +/* + I think this may actually operate as such: + - Bit 6: Mask left channel; + - Bit 5: Mask right channel. + */ +#define MV508_CHANNEL 0x60 +#define MV508_LEFT 0x20 +#define MV508_RIGHT 0x40 +#define MV508_BOTH 0x00 +#define MV508_MIXER 0x10 /* Flag indicating it is a mixer rather than a volume */ + +#define MV508_INPUT_MIX 0x20 /* Flag indicating the selected mixer is input */ + +#define MV508_MASTER_A 0x01 /* Volume: Output */ +#define MV508_MASTER_B 0x02 /* Volume: DSP input */ +#define MV508_BASS 0x03 /* Volume: Bass */ +#define MV508_TREBLE 0x04 /* Volume: Treble */ +#define MV508_MODE 0x05 /* Volume: Mode */ + +#define MV508_LOUDNESS 0x04 /* Mode: Loudness */ +#define MV508_ENH_MASK 0x03 /* Mode: Stereo enhancement bit mask */ +#define MV508_ENH_NONE 0x00 /* Mode: No stereo enhancement */ +#define MV508_ENH_40 0x01 /* Mode: 40% stereo enhancement */ +#define MV508_ENH_60 0x02 /* Mode: 60% stereo enhancement */ +#define MV508_ENH_80 0x03 /* Mode: 80% stereo enhancement */ + +#define MV508_FM 0x00 /* Mixer: FM */ +#define MV508_IMIXER 0x01 /* Mixer: Input mixer (recording monitor) */ +#define MV508_LINE 0x02 /* Mixer: Line in */ +#define MV508_CDROM 0x03 /* Mixer: CD-ROM */ +#define MV508_MIC 0x04 /* Mixer: Microphone */ +#define MV508_PCM 0x05 /* Mixer: PCM */ +#define MV508_SPEAKER 0x06 /* Mixer: PC Speaker */ +#define MV508_SB 0x07 /* Mixer: Sound Blaster DSP */ + +#define MV508_REG_MASTER_A_L (MV508_MASTER_A | MV508_LEFT) +#define MV508_REG_MASTER_A_R (MV508_MASTER_A | MV508_RIGHT) +#define MV508_REG_MASTER_B_L (MV508_MASTER_B | MV508_LEFT) +#define MV508_REG_MASTER_B_R (MV508_MASTER_B | MV508_RIGHT) +#define MV508_REG_BASS (MV508_BASS | MV508_LEFT) +#define MV508_REG_TREBLE (MV508_TREBLE | MV508_LEFT) + +#define MV508_REG_FM_L (MV508_MIXER | MV508_FM | MV508_LEFT) +#define MV508_REG_FM_R (MV508_MIXER | MV508_FM | MV508_RIGHT) +#define MV508_REG_IMIXER_L (MV508_MIXER | MV508_IMIXER | MV508_LEFT) +#define MV508_REG_IMIXER_R (MV508_MIXER | MV508_IMIXER | MV508_RIGHT) +#define MV508_REG_LINE_L (MV508_MIXER | MV508_LINE | MV508_LEFT) +#define MV508_REG_LINE_R (MV508_MIXER | MV508_LINE | MV508_RIGHT) +#define MV508_REG_CDROM_L (MV508_MIXER | MV508_CDROM | MV508_LEFT) +#define MV508_REG_CDROM_R (MV508_MIXER | MV508_CDROM | MV508_RIGHT) +#define MV508_REG_MIC_L (MV508_MIXER | MV508_MIC | MV508_LEFT) +#define MV508_REG_MIC_R (MV508_MIXER | MV508_MIC | MV508_RIGHT) +#define MV508_REG_PCM_L (MV508_MIXER | MV508_PCM | MV508_LEFT) +#define MV508_REG_PCM_R (MV508_MIXER | MV508_PCM | MV508_RIGHT) +#define MV508_REG_SPEAKER_L (MV508_MIXER | MV508_SPEAKER | MV508_LEFT) +#define MV508_REG_SPEAKER_R (MV508_MIXER | MV508_SPEAKER | MV508_RIGHT) +#define MV508_REG_SB_L (MV508_MIXER | MV508_SB | MV508_LEFT) +#define MV508_REG_SB_R (MV508_MIXER | MV508_SB | MV508_RIGHT) + +double low_fir_pas16_coef[SB16_NCoef]; + +/* + Also used for the MVA508. + */ +static double lmc1982_bass_treble_4bits[16]; + +/* + Copied from the Sound Blaster code: -62 dB to 0 dB in 2 dB steps. + Note that these are voltage dB's, so it corresonds in power dB + (formula for conversion to percentage: 10 ^ (dB / 10)) to -31 dB + to 0 dB in 1 dB steps. + + This is used for the MVA508 Volumes. + */ +static const double mva508_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 +}; + +/* + The same but in 1 dB steps, used for the MVA508 Master Volume. + */ +static const double mva508_att_1dbstep_6bits[] = { + 18.0, 25.0, 29.0, 32.0, 36.0, 41.0, 46.0, 51.0, + 58.0, 65.0, 73.0, 82.0, 92.0, 103.0, 116.0, 130.0, + 146.0, 164.0, 184.0, 206.0, 231.0, 260.0, 292.0, 327.0, + 367.0, 412.0, 462.0, 519.0, 582.0, 653.0, 733.0, 822.0, + 923.0, 1036.0, 1162.0, 1304.0, 1463.0, 1641.0, 1842.0, 2067.0, + 2319.0, 2602.0, 2920.0, 3276.0, 3676.0, 4125.0, 4628.0, 5192.0, + 5826.0, 6537.0, 7335.0, 8230.0, 9234.0, 10362.0, 11626.0, 13044.0, + 14636.0, 16422.0, 18426.0, 20674.0, 23197.0, 26027.0, 29204.0, 32767.0 +}; + +/* + In 2 dB steps again, but to -80 dB and counting down (0 = Flat), used + for the LMC1982CIN Master Volume. + */ +static const double lmc1982_att_2dbstep_6bits[] = { + 32767.0, 26027.0, 20674.0, 16422.0, 13044.0, 10362.0, 8230.0, 6537.0, + 5192.0, 4125.0, 3276.0, 2602.0, 2067.0, 1641.0, 1304.0, 1036.0, + 822.0, 653.0, 519.0, 412.0, 327.0, 260.0, 206.0, 164.0, + 130.0, 103.0, 82.0, 65.0, 51.0, 41.0, 32.0, 25.0, + 20.0, 16.0, 13.0, 10.0, 8.0, 6.0, 5.0, 4.0, + 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, + 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, + 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 +}; + +/* + LMC385N attenuation, both +/- 12 dB and +/- 6 dB. + + Since the DOS and Windows 95 driver diverge on boost vs. cut for + the various inputs, I think it is best to just do a 12 dB cut on + the input, and then apply cut or boost as needed. I have factored + in said cut in the below values. + */ +static const double lmc835_att_1dbstep_7bits[128] = { + /* Flat */ + [0x40] = 8230.0, /* Flat */ + /* Boost */ + [0x60] = 9234.0, /* 1 dB Boost */ + [0x50] = 10362.0, /* 2 dB Boost */ + [0x48] = 11626.0, /* 3 dB Boost */ + [0x44] = 13044.0, /* 4 dB Boost */ + [0x42] = 14636.0, /* 5 dB Boost */ + [0x52] = 16422.0, /* 6 dB Boost */ + [0x6a] = 18426.0, /* 7 dB Boost */ + [0x56] = 20674.0, /* 8 dB Boost */ + [0x41] = 23197.0, /* 9 dB Boost */ + [0x69] = 26027.0, /* 10 dB Boost */ + [0x6d] = 29204.0, /* 11 dB Boost */ + /* The Win95 drivers use D5-D0 = 1D instead of 2D, datasheet erratum? */ + [0x5d] = 29204.0, /* 11 dB Boost */ + [0x6f] = 32767.0, /* 12 dB Boost */ + /* Flat */ + /* The datasheet says this should be Flat (1.0) but the + Windows 95 drivers use this as basically mute (12 dB Cut). */ + [0x00] = 2067.0, /* 12 dB Cut */ + /* Cut - D5-D0 = 2F is minimum cut (0 dB) according to Windows 95 */ + [0x20] = 2319.0, /* 11 dB Cut */ + [0x10] = 2602.0, /* 10 dB Cut */ + [0x08] = 2920.0, /* 9 dB Cut */ + [0x04] = 3276.0, /* 8 dB Cut */ + [0x02] = 3676.0, /* 7 dB Cut */ + [0x12] = 4125.0, /* 6 dB Cut */ + [0x2a] = 4628.0, /* 5 dB Cut */ + [0x16] = 5192.0, /* 4 dB Cut */ + [0x01] = 5826.0, /* 3 dB Cut */ + [0x29] = 6537.0, /* 2 dB Cut */ + [0x2d] = 7335.0, /* 1 dB Cut */ + /* The Win95 drivers use D5-D0 = 1D instead of 2D, datasheet erratum? */ + [0x1d] = 7335.0, /* 1 dB Cut */ + [0x2f] = 8230.0, /* Flat */ + 0.0 +}; + +static const double lmc835_att_05dbstep_7bits[128] = { + /* Flat */ + [0x40] = 8230.0, /* Flat */ + /* Boost */ + [0x60] = 8718.0, /* 0.5 dB Boost */ + [0x50] = 9234.0, /* 1.0 dB Boost */ + [0x48] = 9782.0, /* 1.5 dB Boost */ + [0x44] = 10362.0, /* 2.0 dB Boost */ + [0x42] = 10975.0, /* 2.5 dB Boost */ + [0x52] = 11626.0, /* 3.0 dB Boost */ + [0x6a] = 12315.0, /* 3.5 dB Boost */ + [0x56] = 13044.0, /* 4.0 dB Boost */ + [0x41] = 13817.0, /* 4.5 dB Boost */ + [0x69] = 14636.0, /* 5.0 dB Boost */ + [0x6d] = 15503.0, /* 5.5 dB Boost */ + /* The Win95 drivers use D5-D0 = 1D instead of 2D, datasheet erratum? */ + [0x5d] = 15503.0, /* 5.5 dB Boost */ + [0x6f] = 16422.0, /* 6.0 dB Boost */ + /* Flat */ + /* The datasheet says this should be Flat (1.0) but the + Windows 95 drivers use this as basically mute (12 dB Cut). */ + [0x00] = 4125.0, /* 6.0 dB Cut */ + /* Cut - D5-D0 = 2F is minimum cut (0 dB) according to Windows 95 */ + [0x20] = 4369.0, /* 5.5 dB Cut */ + [0x10] = 4628.0, /* 5.0 dB Cut */ + [0x08] = 4920.0, /* 4.5 dB Cut */ + [0x04] = 5192.0, /* 4.0 dB Cut */ + [0x02] = 5500.0, /* 3.5 dB Cut */ + [0x12] = 5826.0, /* 3.0 dB Cut */ + [0x2a] = 6172.0, /* 2.5 dB Cut */ + [0x16] = 6537.0, /* 2.0 dB Cut */ + [0x01] = 6925.0, /* 1.5 dB Cut */ + [0x29] = 7335.0, /* 1.0 dB Cut */ + [0x2d] = 7770.0, /* 0.5 dB Cut */ + /* The Win95 drivers use D5-D0 = 1D instead of 2D, datasheet erratum? */ + [0x1d] = 7770.0, /* 0.5 dB Cut */ + [0x2f] = 8230.0, /* Flat */ + 0.0 +}; + +static __inline double +sinc(const double x) +{ + return sin(M_PI * x) / (M_PI * x); +} + +static void +recalc_pas16_filter(const int playback_freq) +{ + /* Cutoff frequency = playback / 2 */ + int n; + const double fC = ((double) playback_freq) / (double) FREQ_96000; + double gain = 0.0; + + for (n = 0; n < SB16_NCoef; n++) { + /* Blackman window */ + const double 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 */ + const double h = sinc(2.0 * fC * ((double) n - ((double) (SB16_NCoef - 1) / 2.0))); + + /* Create windowed-sinc filter */ + low_fir_pas16_coef[n] = w * h; + } + + low_fir_pas16_coef[(SB16_NCoef - 1) / 2] = 1.0; + + for (n = 0; n < SB16_NCoef; n++) + gain += low_fir_pas16_coef[n]; + + /* Normalise filter, to produce unity gain */ + for (n = 0; n < SB16_NCoef; n++) + low_fir_pas16_coef[n] /= gain; +} + #ifdef ENABLE_PAS16_LOG int pas16_do_log = ENABLE_PAS16_LOG; @@ -204,458 +681,1185 @@ pas16_log(const char *fmt, ...) # define pas16_log(fmt, ...) #endif +static uint8_t +pas16_in(uint16_t port, void *priv); +static void +pas16_out(uint16_t port, uint8_t val, void *priv); + +static void +pas16_update_irq(pas16_t *pas16) +{ + if (pas16->midi_uart_out && (pas16->midi_stat & 0x18)) { + pas16->irq_stat |= PAS16_INT_MIDI; + if ((pas16->irq != -1) && (pas16->irq_ena & PAS16_INT_MIDI)) + picint(1 << pas16->irq); + } + if (pas16->midi_uart_in && (pas16->midi_stat & 0x04)) { + pas16->irq_stat |= PAS16_INT_MIDI; + if ((pas16->irq != -1) && (pas16->irq_ena & PAS16_INT_MIDI)) + picint(1 << pas16->irq); + } +} + static uint8_t pas16_in(uint16_t port, void *priv) { 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); + uint8_t ret = 0xff; + + port -= pas16->base; + + switch (port) { + case 0x0000 ... 0x0003: + ret = pas16->opl.read(port + 0x0388, pas16->opl.priv); break; - case 0xb88: - temp = pas16->audio_mixer; + case 0x0800: + ret = pas16->type ? pas16->audio_mixer : 0xff; + break; + case 0x0801: + ret = pas16->irq_stat & 0xdf; + break; + case 0x0802: + ret = pas16->audiofilt; + break; + case 0x0803: + ret = pas16->irq_ena | 0x20; + pas16_log("IRQ Mask read=%02x.\n", ret); break; - case 0xb89: - temp = pas16->irq_stat; + case 0x0c02: + ret = pas16->pcm_ctrl; break; - case 0xb8a: - temp = pas16->audiofilt; + case 0x1401: + case 0x1403: + ret = pas16->midi_ctrl; + break; + case 0x1402: + case 0x1802: + ret = 0; + if (pas16->midi_uart_in) { + if ((pas16->midi_data == 0xaa) && (pas16->midi_ctrl & 0x04)) + ret = pas16->midi_data; + else { + ret = pas16->midi_queue[pas16->midi_r]; + if (pas16->midi_r != pas16->midi_w) { + pas16->midi_r++; + pas16->midi_r &= 0xff; + } + } + pas16->midi_stat &= ~0x04; + pas16_update_irq(pas16); + } break; - case 0xb8b: - temp = (pas16->irq_ena & ~0xe0) | 0x20; + case 0x1800: + ret = pas16->midi_stat; + break; + case 0x1801: + ret = pas16->fifo_stat; break; - case 0xf8a: - temp = pas16->pcm_ctrl; + case 0x1c00 ... 0x1c03: /* NCR5380 ports 0 to 3. */ + case 0x3c00 ... 0x3c03: /* NCR5380 ports 4 to 7. */ + if (pas16->has_scsi) + ret = ncr5380_read((port & 0x0003) | ((port & 0x2000) >> 11), &pas16->scsi->ncr); break; - case 0x1388: - case 0x1389: - case 0x138a: - case 0x138b: - temp = pas16_pit_in(port, pas16); + case 0x2401: /* Board revision */ + ret = 0x00; break; - case 0x2789: /*Board revision*/ - temp = 0; + case 0x4000: + ret = pas16->timeout_count; + break; + case 0x4001: + ret = pas16->timeout_status; break; - case 0x7f89: - temp = pas16->enhancedscsi & ~1; + case 0x5c00: + if (pas16->has_scsi) + ret = t128_read(0x1e00, pas16->scsi); + break; + case 0x5c01: + if (pas16->has_scsi) + /* Bits 0-6 must absolutely be set for SCSI hard disk drivers to work. */ + ret = (((pas16->scsi->ncr.dma_mode != DMA_IDLE) && (pas16->scsi->status & 0x04)) << 7) | 0x7f; + break; + case 0x5c03: + if (pas16->has_scsi) + ret = pas16->scsi->ncr.irq_state << 7; 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; + case 0x7c01: + ret = pas16->enhancedscsi & ~0x01; break; - case 0xef8b: - temp = 0x0c; + case 0x8000: + ret = pas16->sys_conf_1; + break; + case 0x8001: + ret = pas16->sys_conf_2; + break; + case 0x8002: + ret = pas16->sys_conf_3; + break; + case 0x8003: + ret = pas16->sys_conf_4; break; - case 0xf388: - temp = pas16->io_conf_1; + case 0xbc00: + ret = pas16->waitstates; break; - case 0xf389: - temp = pas16->io_conf_2; - break; - case 0xf38b: - temp = pas16->io_conf_3; - break; - case 0xf38c: - temp = pas16->io_conf_4; + case 0xbc02: + ret = pas16->prescale_div; break; - case 0xf788: - temp = pas16->compat; - break; - case 0xf789: - temp = pas16->compat_base; + case 0xec03: + /* + Operation mode 1: + - 1,0 = CD-ROM (1,1 = SCSI, 1,0 = Sony, 0,0 = N/A); + - 2 = FM (1 = stereo, 0 = mono); + - 3 = Code (1 = 16-bit, 0 = 8-bit). + */ + ret = pas16->type ? pas16->type : 0x06; break; - case 0xfb8a: - temp = pas16->sb_irqdma; + case 0xf000: + ret = pas16->io_conf_1; + break; + case 0xf001: + ret = pas16->io_conf_2; + pas16_log("pas16_in : set PAS DMA %i\n", pas16->dma); + break; + case 0xf002: + ret = pas16->io_conf_3; + pas16_log("pas16_in : set PAS IRQ %i\n", pas16->irq); + break; + case 0xf003: + ret = pas16->io_conf_4; break; - case 0xff88: /*Board model*/ - temp = 4; /*PAS16*/ + case 0xf400: + ret = (pas16->compat & 0xf3); + + if (pas16->dsp.sb_irqm8 || pas16->dsp.sb_irqm16 || pas16->dsp.sb_irqm401) + ret |= 0x04; + + if (pas16->mpu->mode == M_UART) + ret |= 0x08; break; - case 0xff8b: /*Master mode read*/ - temp = 0x20 | 0x10 | 0x01; /*AT bus, XT/AT timing*/ + case 0xf401: + ret = pas16->compat_base; + break; + + case 0xf802: + ret = pas16->sb_irqdma; + break; + + case 0xfc00: /* Board model */ + /* PAS16 or PASPlus */ + ret = pas16->type ? 0x0c : 0x01; + break; + case 0xfc03: /* Master mode read */ + /* AT bus, XT/AT timing */ + ret = 0x11; + if (pas16->type) + ret |= 0x20; break; default: break; } - pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS, cpu_state.pc); - return temp; + + pas16_log("[%04X:%08X] PAS16: [R] %04X (%04X) = %02X\n", + CS, cpu_state.pc, port + pas16->base, port, ret); + + return ret; +} + +static void +pas16_change_pit_clock_speed(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + pitf_t *pit = (pitf_t *) pas16->pit; + + if (pas16->type && (pas16->sys_conf_1 & 0x02) && pas16->prescale_div) { + pit_change_pas16_consts((double) pas16->prescale_div); + if (pas16->sys_conf_3 & 0x02) + pitf_set_pit_const(pit, PAS16CONST2); + else + pitf_set_pit_const(pit, PAS16CONST); + } else + pitf_set_pit_const(pit, PITCONST); +} + +static void +pas16_io_handler(pas16_t *pas16, int set) +{ + if (pas16->base != 0x0000) { + for (uint32_t addr = 0x0000; addr <= 0xffff; addr += 0x0400) { + pas16_log("%04X-%04X: %i\n", pas16->base + addr, pas16->base + addr + 3, set); + if (addr != 0x1000) + io_handler(set, pas16->base + addr, 0x0004, + pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); + } + + pitf_handler(set, pas16->base + 0x1000, 0x0004, pas16->pit); + } +} + +static void +pas16_reset_pcm(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + + pas16->pcm_ctrl = 0x00; + + pas16->stereo_lr = 0; + + pas16->irq_stat &= 0xd7; + + if ((pas16->irq != -1) && !pas16->irq_stat) + picintc(1 << pas16->irq); +} + +static void +lmc1982_recalc(nsc_mixer_t *mixer) +{ + /* LMC1982CIN */ + /* According to the Windows 95 driver, the two volumes are swapped. */ + if ((mixer->lmc1982_regs[LMC1982_REG_ISELECT] & LMC1982_ISELECT_MASK) == LMC1982_ISELECT_I2) { + switch (mixer->lmc1982_regs[LMC1982_REG_MODE] & LMC1982_MODE_MASK) { + case LMC1982_MODE_MONO_L: + mixer->master_l = mixer->master_r = lmc1982_att_2dbstep_6bits[mixer->lmc1982_regs[LMC1982_REG_VOL_R]] / 32767.0; + break; + case LMC1982_MODE_STEREO: + mixer->master_l = lmc1982_att_2dbstep_6bits[mixer->lmc1982_regs[LMC1982_REG_VOL_R]] / 32767.0; + mixer->master_r = lmc1982_att_2dbstep_6bits[mixer->lmc1982_regs[LMC1982_REG_VOL_L]] / 32767.0; + break; + case LMC1982_MODE_MONO_R: + case LMC1982_MODE_MONO_R_2: + mixer->master_l = mixer->master_r = lmc1982_att_2dbstep_6bits[mixer->lmc1982_regs[LMC1982_REG_VOL_L]] / 32767.0; + break; + default: + mixer->master_l = mixer->master_r = 0.0; + break; + } + + mixer->bass = mixer->lmc1982_regs[LMC1982_REG_BASS] & 0x0f; + mixer->treble = mixer->lmc1982_regs[LMC1982_REG_TREBLE] & 0x0f; + } else { + mixer->master_l = mixer->master_r = 0.0; + + mixer->bass = 0x06; + mixer->treble = 0x06; + } +} + +static void +lmc835_recalc(nsc_mixer_t *mixer) +{ + /* LMC835N */ + /* Channel A (1-7) */ + const double *lmc835_att = (const double *) ((mixer->lmc835_regs[LMC835_REG_MODE] & 0x20) ? + lmc835_att_05dbstep_7bits : lmc835_att_1dbstep_7bits); + + mixer->fm_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_FM_L] & 0x7f] / 32767.0; + mixer->imixer_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_IMIXER_L] & 0x7f] / 32767.0; + mixer->line_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_LINE_L] & 0x7f] / 32767.0; + mixer->cd_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_CDROM_L] & 0x7f] / 32767.0; + mixer->mic_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_MIC_L] & 0x7f] / 32767.0; + mixer->pcm_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_PCM_L] & 0x7f] / 32767.0; + mixer->speaker_l = lmc835_att[mixer->lmc835_regs[LMC835_REG_SPEAKER_L] & 0x7f] / 32767.0; + + /* Channel B (8-e) */ + lmc835_att = (const double *) ((mixer->lmc835_regs[LMC835_REG_MODE] & 0x08) ? + lmc835_att_05dbstep_7bits : lmc835_att_1dbstep_7bits); + + mixer->fm_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_FM_R] & 0x7f] / 32767.0; + mixer->imixer_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_IMIXER_R] & 0x7f] / 32767.0; + mixer->line_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_LINE_R] & 0x7f] / 32767.0; + mixer->cd_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_CDROM_R] & 0x7f] / 32767.0; + mixer->mic_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_MIC_R] & 0x7f] / 32767.0; + mixer->pcm_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_PCM_R] & 0x7f] / 32767.0; + mixer->speaker_r = lmc835_att[mixer->lmc835_regs[LMC835_REG_SPEAKER_R] & 0x7f] / 32767.0; +} + +static void +mv508_mixer_recalc(mv508_mixer_t *mixer) +{ + mixer->fm_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_FM_L]] / 32767.0; + mixer->fm_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_FM_R]] / 32767.0; + mixer->imixer_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_IMIXER_L]] / 32767.0; + mixer->imixer_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_IMIXER_R]] / 32767.0; + mixer->line_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_LINE_L]] / 32767.0; + mixer->line_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_LINE_R]] / 32767.0; + mixer->cd_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_CDROM_L]] / 32767.0; + mixer->cd_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_CDROM_R]] / 32767.0; + mixer->mic_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_MIC_L]] / 32767.0; + mixer->mic_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_MIC_R]] / 32767.0; + mixer->pcm_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_PCM_L]] / 32767.0; + mixer->pcm_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_PCM_R]] / 32767.0; + mixer->speaker_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_SPEAKER_L]] / 32767.0; + mixer->speaker_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_SPEAKER_R]] / 32767.0; + mixer->sb_l = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_SB_L]] / 32767.0; + mixer->sb_r = mva508_att_2dbstep_5bits[mixer->regs[0][MV508_REG_SB_R]] / 32767.0; + + mixer->master_l = mva508_att_1dbstep_6bits[mixer->regs[2][MV508_REG_MASTER_A_L]] / 32767.0; + mixer->master_r = mva508_att_1dbstep_6bits[mixer->regs[2][MV508_REG_MASTER_A_R]] / 32767.0; + + mixer->bass = mixer->regs[2][MV508_REG_BASS] & 0x0f; + mixer->treble = mixer->regs[2][MV508_REG_TREBLE] & 0x0f; +} + +static void +pas16_nsc_mixer_reset(nsc_mixer_t *mixer) +{ + mixer->lmc1982_regs[LMC1982_REG_ISELECT] = 0x01; + mixer->lmc1982_regs[LMC1982_REG_LES] = 0x00; + mixer->lmc1982_regs[LMC1982_REG_BASS] = mixer->lmc1982_regs[LMC1982_REG_TREBLE] = 0x06; + mixer->lmc1982_regs[LMC1982_REG_VOL_L] = mixer->lmc1982_regs[LMC1982_REG_VOL_R] = 0x28; + mixer->lmc1982_regs[LMC1982_REG_MODE] = 0x05; + + lmc1982_recalc(mixer); + + mixer->lmc835_regs[LMC835_REG_MODE] = 0x00; + + mixer->lmc835_regs[LMC835_REG_FM_L] = mixer->lmc835_regs[LMC835_REG_FM_R] = 0x69; + mixer->lmc835_regs[LMC835_REG_IMIXER_L] = mixer->lmc835_regs[LMC835_REG_IMIXER_R] = 0x29; + mixer->lmc835_regs[LMC835_REG_LINE_L] = mixer->lmc835_regs[LMC835_REG_LINE_R] = 0x69; + mixer->lmc835_regs[LMC835_REG_CDROM_L] = mixer->lmc835_regs[LMC835_REG_CDROM_R] = 0x69; + mixer->lmc835_regs[LMC835_REG_MIC_L] = mixer->lmc835_regs[LMC835_REG_MIC_R] = 0x44; + mixer->lmc835_regs[LMC835_REG_PCM_L] = mixer->lmc835_regs[LMC835_REG_PCM_R] = 0x29; + mixer->lmc835_regs[LMC835_REG_SPEAKER_L] = mixer->lmc835_regs[LMC835_REG_SPEAKER_R] = 0x06; + + lmc835_recalc(mixer); +} + +static void +pas16_mv508_mixer_reset(mv508_mixer_t *mixer) +{ + /* Based on the Linux driver - TODO: The actual card's defaults. */ + mixer->regs[0][MV508_REG_FM_L] = mixer->regs[0][MV508_REG_FM_R] = 0x18; + mixer->regs[0][MV508_REG_IMIXER_L] = mixer->regs[0][MV508_REG_IMIXER_R] = 0x1f; + mixer->regs[0][MV508_REG_LINE_L] = mixer->regs[0][MV508_REG_LINE_R] = 0x17; + mixer->regs[0][MV508_REG_CDROM_L] = mixer->regs[0][MV508_REG_CDROM_R] = 0x17; + mixer->regs[0][MV508_REG_MIC_L] = mixer->regs[0][MV508_REG_MIC_R] = 0x17; + mixer->regs[0][MV508_REG_PCM_L] = mixer->regs[0][MV508_REG_PCM_R] = 0x17; + mixer->regs[0][MV508_REG_SPEAKER_L] = mixer->regs[0][MV508_REG_SPEAKER_R] = 0x0f; + mixer->regs[0][MV508_REG_SB_L] = mixer->regs[0][MV508_REG_SB_R] = 0x17; + + mixer->regs[2][MV508_REG_MASTER_A_L] = mixer->regs[2][MV508_REG_MASTER_A_R] = 0x1f; + + mixer->regs[2][MV508_REG_BASS] = 0x06; + mixer->regs[2][MV508_REG_TREBLE] = 0x06; + + mv508_mixer_recalc(mixer); +} + +static void +pas16_reset_regs(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + nsc_mixer_t *nsc_mixer = &pas16->nsc_mixer; + mv508_mixer_t *mv508_mixer = &pas16->mv508_mixer; + pitf_t *pit = (pitf_t *) pas16->pit; + + if (pas16->irq != -1) + picintc(1 << pas16->irq); + + pas16->sys_conf_1 &= 0xfd; + + pas16->sys_conf_2 = 0x00; + pas16->sys_conf_3 = 0x00; + + pas16->prescale_div = 0x00; + + pitf_set_pit_const(pit, PITCONST); + + pas16->audiofilt = 0x00; + pas16->filter = 0; + + pitf_ctr_set_gate(pit, 0, 0); + pitf_ctr_set_gate(pit, 1, 0); + + pas16_reset_pcm(pas16); + pas16->dma8_ff = 0; + + pas16->irq_ena = 0x00; + pas16->irq_stat = 0x00; + + if (pas16->type) + pas16_mv508_mixer_reset(mv508_mixer); + else + pas16_nsc_mixer_reset(nsc_mixer); +} + +static void +pas16_reset_common(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + + pas16_reset_regs(pas16); + + if (pas16->irq != -1) + picintc(1 << pas16->irq); + + pas16_io_handler(pas16, 0); + pas16->base = 0x0000; +} + +static void +pas16_reset(void *priv) +{ + pas16_t *pas16 = (pas16_t *) priv; + + pas16_reset_common(priv); + + pas16->board_id = 0; + pas16->master_ff = 0; + + pas16->base = 0x0388; + pas16_io_handler(pas16, 1); + + pas16->new_base = 0x0388; + + pas16->sb_compat_base = 0x0220; + pas16->compat = 0x02; + pas16->compat_base = 0x02; + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); +} + +static int +pas16_irq_convert(uint8_t val) +{ + int ret = val; + + if (ret == 0) + ret = -1; + else if (ret <= 6) + ret++; + else if (ret < 0x0b) + ret += 3; + else + ret += 4; + + return ret; +} + +static void +lmc1982_update_reg(nsc_mixer_t *mixer) +{ + pas16_log("LMC1982CIN register %02X = %04X\n", + mixer->im_data[LMC1982_ADDR], mixer->im_data[LMC1982_DATA]); + + if ((mixer->im_data[LMC1982_ADDR] & LMC1982_REG_MASK) == LMC1982_REG_VALID) { + mixer->im_data[LMC1982_ADDR] &= ~LMC1982_REG_MASK; + mixer->lmc1982_regs[mixer->im_data[LMC1982_ADDR]] = mixer->im_data[LMC1982_DATA] & 0xff; + lmc1982_recalc(mixer); + } + + mixer->im_state = STATE_SM_IDLE; +} + +static void +lmc835_update_reg(nsc_mixer_t *mixer) +{ + pas16_log("LMC835N register %02X = %02X\n", + mixer->im_data[LMC835_ADDR], mixer->im_data[LMC835_DATA]); + + mixer->lmc835_regs[LMC835_REG_MODE] = mixer->im_data[LMC835_ADDR] & 0xf0; + mixer->im_data[LMC835_ADDR] &= 0x0f; + if ((mixer->im_data[LMC835_ADDR] >= 0x01) && (mixer->im_data[LMC835_ADDR] <= 0x0e)) + mixer->lmc835_regs[mixer->im_data[LMC835_ADDR] & 0x0f] = mixer->im_data[LMC835_DATA]; + lmc835_recalc(mixer); +} + +static void +pas16_scsi_callback(void *priv) +{ + pas16_t * pas16 = (pas16_t *) priv; + t128_t * dev = pas16->scsi; + + t128_callback(pas16->scsi); + + if ((dev->ncr.dma_mode != DMA_IDLE) && (dev->status & 0x04)) { + timer_stop(&pas16->scsi_timer); + pas16->timeout_status &= 0x7f; + } +} + +static void +pas16_timeout_callback(void *priv) +{ + pas16_t * pas16 = (pas16_t *) priv; + + pas16->timeout_status |= 0x80; + + if ((pas16->timeout_status & 0x08) && (pas16->irq != -1)) + picint(1 << pas16->irq); + + timer_advance_u64(&pas16->scsi_timer, (pas16->timeout_count & 0x3f) * PASSCSICONST); } static void pas16_out(uint16_t port, uint8_t val, void *priv) { - 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); + pas16_t * pas16 = (pas16_t *) priv; + nsc_mixer_t * nsc_mixer = &pas16->nsc_mixer; + mv508_mixer_t *mv508_mixer = &pas16->mv508_mixer; + + pas16_log("[%04X:%08X] PAS16: [W] %04X (%04X) = %02X\n", + CS, cpu_state.pc, port, port - pas16->base, val); + + port -= pas16->base; + + switch (port) { + case 0x0000 ... 0x0003: + pas16->opl.write(port + 0x0388, val, pas16->opl.priv); break; - case 0xb88: - pas16->audio_mixer = val; + case 0x0400 ... 0x0402: + break; + case 0x0403: + if (val & MV508_ADDRESS) + mv508_mixer->index = val & ~MV508_ADDRESS; + else { + uint8_t bank; + uint8_t mask; + + pas16_log("MVA508 register %02X = %02X\n", + mv508_mixer->index, val); + + if (mv508_mixer->index & MV508_MIXER) { + bank = !!(val & MV508_INPUT_MIX); + mask = 0x1f; + } else { + bank = 2; + mask = 0x3f; + } + + if (mv508_mixer->index & MV508_CHANNEL) + mv508_mixer->regs[bank][mv508_mixer->index] = val & mask; + else { + mv508_mixer->regs[bank][mv508_mixer->index | MV508_LEFT] = val & mask; + mv508_mixer->regs[bank][mv508_mixer->index | MV508_RIGHT] = val & mask; + } + + mv508_mixer_recalc(mv508_mixer); + } break; - case 0xb89: + case 0x0800: + if (pas16->type && !(val & SERIAL_MIXER_RESET_PCM)) { + pas16->audio_mixer = val; + pas16_reset_pcm(pas16); + } else if (!pas16->type) { + switch (nsc_mixer->im_state) { + default: + break; + case STATE_SM_IDLE: + /* Transmission initiated. */ + if (val & SERIAL_MIXER_IDENT) { + if (!(val & SERIAL_MIXER_CLOCK) && (pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* Prepare for receiving LMC835N data. */ + nsc_mixer->im_data[LMC835_DATA] = 0x0000; + nsc_mixer->im_state |= STATE_LMC835_DATA; + } + } else { + if ((pas16->audio_mixer & SERIAL_MIXER_IDENT)) { + /* + Prepare for receiving the LMC1982CIN address. + */ + nsc_mixer->im_data[LMC1982_ADDR] = 0x0000; + nsc_mixer->im_state |= STATE_LMC1982_ADDR; + } + if ((val & SERIAL_MIXER_CLOCK) && !(pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* + Clock the least siginificant bit of the LMC1982CIN address. + */ + nsc_mixer->im_data[LMC1982_ADDR] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK)); + nsc_mixer->im_state++; + } + } + break; + case STATE_LMC1982_ADDR_0: + if (val & SERIAL_MIXER_IDENT) { + /* + IDENT went high in LM1982CIN address state 0, + behave as if we were in the idle state. + */ + if (!(val & SERIAL_MIXER_CLOCK) && (pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + nsc_mixer->im_data[LMC835_DATA] = 0x0000; + nsc_mixer->im_state = STATE_LMC835_DATA_0; + } + } else if ((val & SERIAL_MIXER_CLOCK) && + !(pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* + Clock the least siginificant bit of the LMC1982CIN address. + */ + nsc_mixer->im_data[LMC1982_ADDR] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK)); + nsc_mixer->im_state++; + } + break; + case STATE_LMC1982_ADDR_1 ... STATE_LMC1982_ADDR_7: + if ((val & 0x02) && !(pas16->audio_mixer & 0x02)) { + /* + Clock the next bit of the LMC1982CIN address. + */ + nsc_mixer->im_data[LMC1982_ADDR] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK)); + nsc_mixer->im_state++; + } + break; + case STATE_LMC1982_ADDR_OVER: + /* + Prepare for receiving the LMC1982CIN data. + */ + nsc_mixer->im_data[LMC1982_DATA] = 0x0000; + nsc_mixer->im_state = STATE_LMC1982_DATA_0; + break; + case STATE_LMC1982_DATA_0 ... STATE_LMC1982_DATA_7: + case STATE_LMC1982_DATA_9 ... STATE_LMC1982_DATA_F: + if ((val & SERIAL_MIXER_CLOCK) && !(pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* + Clock the next bit of the LMC1982CIN data. + */ + nsc_mixer->im_data[LMC1982_DATA] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK_W)); + nsc_mixer->im_state++; + } + break; + case STATE_LMC1982_DATA_8: + if (val & SERIAL_MIXER_IDENT) { + if (!(pas16->audio_mixer & SERIAL_MIXER_IDENT)) + /* + LMC1982CIN data transfer ended after 8 bits, process the data and + reset the state back to idle. + */ + lmc1982_update_reg(nsc_mixer); + else if ((val & SERIAL_MIXER_CLOCK) && + !(pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* + Clock the next bit of the LMC1982CIN data. + */ + nsc_mixer->im_data[LMC1982_DATA] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK_W)); + nsc_mixer->im_state++; + } + } + break; + case STATE_LMC1982_DATA_OVER: + if ((val & SERIAL_MIXER_IDENT) && !(pas16->audio_mixer & SERIAL_MIXER_IDENT)) + /* + LMC1982CIN data transfer ended, process the data and reset the state + back to idle. + */ + lmc1982_update_reg(nsc_mixer); + break; + case STATE_LMC835_DATA_0 ... STATE_LMC835_DATA_7: + if ((val & SERIAL_MIXER_CLOCK) && !(pas16->audio_mixer & SERIAL_MIXER_CLOCK)) { + /* + Clock the next bit of the LMC835N data. + */ + nsc_mixer->im_data[LMC835_DATA] |= + ((val & SERIAL_MIXER_DATA) << (nsc_mixer->im_state & STATE_DATA_MASK)); + nsc_mixer->im_state++; + } + break; + case STATE_LMC835_DATA_OVER: + if ((val & SERIAL_MIXER_STROBE) && !(pas16->audio_mixer & SERIAL_MIXER_STROBE)) { + if (nsc_mixer->im_data[LMC835_DATA] & LMC835_FLAG_ADDR) + /* + The LMC835N data is an address, copy it into its own space for usage + when processing it at the end and strip bits 7 (it's the address/data + indicator) and 6 (it's a "don't care" bit). + */ + nsc_mixer->im_data[LMC835_ADDR] = nsc_mixer->im_data[LMC835_DATA] & 0x7f; + else + lmc835_update_reg(nsc_mixer); + nsc_mixer->im_state = STATE_SM_IDLE; + } + break; + } + + pas16->audio_mixer = val; + } + break; + case 0x0801: pas16->irq_stat &= ~val; + if ((pas16->irq != -1) && !(pas16->irq_stat & 0x1f)) + picintc(1 << pas16->irq); break; - - case 0xb8a: + case 0x0802: pas16_update(pas16); + + pitf_ctr_set_gate(pas16->pit, 1, !!(val & 0x80)); + pitf_ctr_set_gate(pas16->pit, 0, !!(val & 0x40)); + + pas16->stereo_lr = 0; + pas16->dma8_ff = 0; + + if ((val & 0x20) && !(pas16->audiofilt & 0x20)) { + pas16_log("Reset.\n"); + pas16_reset_regs(pas16); + } + pas16->audiofilt = val; + + if (val & 0x1f) { + pas16->filter = 1; + switch (val & 0x1f) { + default: + pas16->filter = 0; + break; + case 0x01: + recalc_pas16_filter(17897); + break; + case 0x02: + recalc_pas16_filter(15909); + break; + case 0x04: + recalc_pas16_filter(2982); + break; + case 0x09: + recalc_pas16_filter(11931); + break; + case 0x11: + recalc_pas16_filter(8948); + break; + case 0x19: + recalc_pas16_filter(5965); + break; + } + } else + pas16->filter = 0; + break; + case 0x0803: + pas16->irq_ena = val & 0x1f; + pas16->irq_stat &= ((val & 0x1f) | 0xe0); + + if ((pas16->irq != -1) && !(pas16->irq_stat & 0x1f)) + picintc(1 << pas16->irq); break; - case 0xb8b: - pas16->irq_ena = val; - break; - - case 0xf88: + case 0x0c00: + case 0x0c01: 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*/ + case 0x0c02: + if ((val & PAS16_PCM_ENA) && !(pas16->pcm_ctrl & PAS16_PCM_ENA)) { + /* Guess */ pas16->stereo_lr = 0; + pas16->irq_stat &= 0xd7; + /* Needed for 8-bit DMA to work correctly on a 16-bit DMA channel. */ + pas16->dma8_ff = 0; + } + pas16->pcm_ctrl = val; + pas16_log("Now in: %s (%02X)\n", (pas16->pcm_ctrl & PAS16_PCM_MONO) ? "Mono" : "Stereo", val); break; - case 0x1388: - case 0x1389: - case 0x138a: - case 0x138b: - pas16_pit_out(port, val, pas16); + case 0x1401: + case 0x1403: + pas16->midi_ctrl = val; + if ((val & 0x60) == 0x60) { + pas16->midi_uart_out = 0; + pas16->midi_uart_in = 0; + } else if ((val & 0x1c) == 0x04) + pas16->midi_uart_in = 1; + else + pas16->midi_uart_out = 1; + + pas16_update_irq(pas16); + break; + case 0x1402: + case 0x1802: + pas16->midi_data = val; + pas16_log("UART OUT=%d.\n", pas16->midi_uart_out); + if (pas16->midi_uart_out) + midi_raw_out_byte(val); break; - case 0x7f89: + case 0x1800: + pas16->midi_stat = val; + pas16_update_irq(pas16); + break; + case 0x1801: + pas16->fifo_stat = val; + break; + + case 0x1c00 ... 0x1c03: /* NCR5380 ports 0 to 3. */ + case 0x3c00 ... 0x3c03: /* NCR5380 ports 4 to 7. */ + if (pas16->has_scsi) + ncr5380_write((port & 0x0003) | ((port & 0x2000) >> 11), val, &pas16->scsi->ncr); + break; + + case 0x4000: + if (pas16->has_scsi) { + pas16->timeout_count = val; + if (timer_is_enabled(&pas16->scsi_timer)) + timer_disable(&pas16->scsi_timer); + timer_set_delay_u64(&pas16->scsi_timer, (val & 0x3f) * PASSCSICONST); + } + break; + + case 0x4001: + if (pas16->has_scsi) { + pas16->timeout_status = val & 0x7f; + if (pas16->scsi_irq != -1) + picintc(1 << pas16->scsi_irq); + } + break; + + case 0x5c00: + if (pas16->has_scsi) + t128_write(0x1e00, val, pas16->scsi); + break; + case 0x5c03: + if (pas16->has_scsi) { + if (val & 0x80) { + pas16->scsi->ncr.irq_state = 0; + if (pas16->scsi_irq != -1) + picintc(1 << pas16->scsi_irq); + } + } + break; + + case 0x7c01: pas16->enhancedscsi = val; break; - case 0x8388: + case 0x8000: + if ((val & 0xc0) && !(pas16->sys_conf_1 & 0xc0)) { + pas16_log("Reset.\n"); + val = 0x00; + pas16_reset_common(pas16); + pas16->base = pas16->new_base; + pas16_io_handler(pas16, 1); + } + pas16->sys_conf_1 = val; + pas16_change_pit_clock_speed(pas16); + pas16_log("Now in: %s mode\n", (pas16->sys_conf_1 & 0x02) ? "native" : "compatibility"); break; - case 0x8389: + case 0x8001: pas16->sys_conf_2 = val; + pas16_log("Now in: %i bits (%02X)\n", + (pas16->sys_conf_2 & 0x04) ? ((pas16->sys_conf_2 & 0x08) ? 12 : 16) : 8, val); break; - case 0x838a: + case 0x8002: pas16->sys_conf_3 = val; + pas16_change_pit_clock_speed(pas16); + pas16_log("Use 1.008 MHz clok for PCM: %c\n", (val & 0x02) ? 'Y' : 'N'); break; - case 0x838b: + case 0x8003: pas16->sys_conf_4 = val; + if (pas16->has_scsi && (pas16->scsi_irq != -1) && !(val & 0x20)) + picintc(1 << pas16->scsi_irq); break; - case 0xf388: + case 0xbc00: + pas16->waitstates = val; + break; + case 0xbc02: + pas16->prescale_div = val; + pas16_change_pit_clock_speed(pas16); + pas16_log("Prescale divider now: %i\n", val); + break; + + case 0xf000: pas16->io_conf_1 = val; break; - case 0xf389: + case 0xf001: pas16->io_conf_2 = val; pas16->dma = pas16_dmas[val & 0x7]; + pas16_change_pit_clock_speed(pas16); pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma); break; - case 0xf38a: + case 0xf002: pas16->io_conf_3 = val; - pas16->irq = pas16_irqs[val & 0xf]; - pas16_log("pas16_out : set PAS IRQ %i\n", pas16->irq); + if (pas16->irq != -1) + picintc(1 << pas16->irq); + pas16->irq = pas16_irq_convert(val & 0x0f); + if (pas16->has_scsi) { + if (pas16->scsi_irq != -1) + picintc(1 << pas16->scsi_irq); + pas16->scsi_irq = pas16_irq_convert(val >> 4); + ncr5380_set_irq(&pas16->scsi->ncr, pas16->scsi_irq); + } + + pas16_log("pas16_out : set PAS IRQ %i, val=%02x\n", pas16->irq, val & 0x0f); break; - case 0xf38b: + case 0xf003: pas16->io_conf_4 = val; break; - case 0xf788: - pas16->compat = val; + case 0xf400: + pas16->compat = val & 0xf3; + pas16_log("PCM compression is now %sabled\n", (val & 0x10) ? "en" : "dis"); if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); else sb_dsp_setaddr(&pas16->dsp, 0); + if (pas16->compat & 0x01) + mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300)); + else + mpu401_change_addr(pas16->mpu, 0); break; - case 0xf789: + case 0xf401: pas16->compat_base = val; + pas16->sb_compat_base = ((pas16->compat_base & 0xf) << 4) | 0x200; + pas16_log("SB Compatibility base: %04X\n", pas16->sb_compat_base); if (pas16->compat & 0x02) - sb_dsp_setaddr(&pas16->dsp, ((pas16->compat_base & 0xf) << 4) | 0x200); + sb_dsp_setaddr(&pas16->dsp, pas16->sb_compat_base); + if (pas16->compat & 0x01) + mpu401_change_addr(pas16->mpu, ((pas16->compat_base & 0xf0) | 0x300)); break; - case 0xfb8a: + case 0xf802: pas16->sb_irqdma = val; + mpu401_setirq(pas16->mpu, pas16_sb_irqs[val & 7]); 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]); + 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; +} + +/* + 8-bit mono: + - 8-bit DMA : On every timer 0 over, read the 8-bit sample and ctr_clock(); + (One ctr_clock() per timer 0 over) + - 16-bit DMA: On every even timer 0 over, read two 8-bit samples at once and ctr_clock(); + On every odd timer 0 over, read the MSB of the previously read sample word. + (One ctr_clock() per two timer 0 overs) + 8-bit stereo: + - 8-bit DMA : On every timer 0, read two 8-bit samples and ctr_clock() twice; + (Two ctr_clock()'s per timer 0 over) + - 16-bit DMA: On every timer 0, read two 8-bit samples and ctr_clock() once. + (One ctr_clock() per timer 0 over) + 16-bit mono (to be verified): + - 8-bit DMA : On every timer 0, read one 16-bit sample and ctr_clock() twice; + (Two ctr_clock()'s per timer 0 over) + - 16-bit DMA: On every timer 0, read one 16-bit sample and ctr_clock() once. + (One ctr_clock() per timer 0 over) + 16-bit stereo: + - 8-bit DMA : On every timer 0, read one 16-bit sample and ctr_clock() twice; + (Two ctr_clock()'s per timer 0 over) + - 16-bit DMA: On every timer 0, read one 16-bit sample and ctr_clock() twice. + (Two ctr_clock()'s per timer 0 over) + + What we can conclude from this is: + - Maximum 16 bits per timer 0 over; + - A 8-bit sample always takes one ctr_clock() tick, unless it has been read + alongside the previous sample; + - A 16-bit sample always takes two ctr_clock() ticks. + */ +static uint16_t +pas16_dma_channel_read(pas16_t *pas16, int channel) +{ + int status; + uint16_t ret; + + if (pas16->pcm_ctrl & PAS16_PCM_DMA_ENA) { + if (pas16->dma >= 5) { + dma_channel_advance(pas16->dma); + status = dma_channel_read_only(pas16->dma); + } else + status = dma_channel_read(pas16->dma); + ret = (status == DMA_NODATA) ? 0x0000 : (status & 0xffff); + } else + ret = 0x0000; + + return ret; +} + +static uint16_t +pas16_dma_readb(pas16_t *pas16) +{ + const uint16_t ret = pas16_dma_channel_read(pas16, pas16->dma); + + pas16->ticks++; + + return ret; +} + +static uint16_t +pas16_dma_readw(pas16_t *pas16, const uint8_t timer1_ticks) +{ + uint16_t ret; + + if (pas16->dma >= 5) + ret = pas16_dma_channel_read(pas16, pas16->dma); + else { + ret = pas16_dma_channel_read(pas16, pas16->dma); + ret |= (pas16_dma_channel_read(pas16, pas16->dma) << 8); } -#endif + + pas16->ticks += timer1_ticks; + + return ret; } -static void -pas16_pit_out(uint16_t port, uint8_t val, void *priv) +static uint16_t +pas16_readdmab(pas16_t *pas16) { - 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; - - default: - 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 uint8_t -pas16_pit_in(uint16_t port, void *priv) -{ - 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; - } - } - 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_readdma(pas16_t *pas16) -{ - return dma_channel_read(pas16->dma); -} - -static void -pas16_pcm_poll(void *priv) -{ - pas16_t *pas16 = (pas16_t *) priv; - - 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); + if (pas16->dma >= 5) { + if (pas16->dma8_ff) + pas16->dma8_dat >>= 8; else - timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST); - } else { - pas16->pit.enable[0] = 0; - } + pas16->dma8_dat = pas16_dma_readb(pas16); - pas16->irq_stat |= PAS16_INT_SAMP; - if (pas16->irq_ena & PAS16_INT_SAMP) - picint(1 << pas16->irq); + pas16->dma8_ff = !pas16->dma8_ff; + } else + pas16->dma8_dat = pas16_dma_readb(pas16); - /*Update sample rate counter*/ - if (pas16->pit.enable[1]) { - if (pas16->pcm_ctrl & PAS16_PCM_ENA) { - uint16_t temp; + return ((pas16->dma8_dat & 0xff) ^ 0x80) << 8; +} - if (pas16->sys_conf_2 & PAS16_SC2_16BIT) { - temp = pas16_readdma(pas16) << 8; - temp |= pas16_readdma(pas16); - } else - temp = (pas16_readdma(pas16) ^ 0x80) << 8; +static uint16_t +pas16_readdmaw_mono(pas16_t *pas16) +{ + const uint16_t ret = pas16_dma_readw(pas16, 1 + (pas16->dma < 5)); - 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 { + return ret; +} + +static uint16_t +pas16_readdmaw_stereo(pas16_t *pas16) +{ + uint16_t ret; + uint16_t ticks = (pas16->sys_conf_1 & 0x02) ? (1 + (pas16->dma < 5)) : 2; + + ret = pas16_dma_readw(pas16, ticks); + + return ret; +} + +static uint16_t +pas16_readdma_mono(pas16_t *pas16) +{ + uint16_t ret; + + if (pas16->sys_conf_2 & 0x04) { + ret = pas16_readdmaw_mono(pas16); + + if (pas16->sys_conf_2 & 0x08) + ret &= 0xfff0; + } else + ret = pas16_readdmab(pas16); + + if (pas16->sys_conf_2 & PAS16_SC2_MSBINV) + ret ^= 0x8000; + + return ret; +} + +static uint16_t +pas16_readdma_stereo(pas16_t *pas16) +{ + uint16_t ret; + + if (pas16->sys_conf_2 & 0x04) { + ret = pas16_readdmaw_stereo(pas16); + + if (pas16->sys_conf_2 & 0x08) + ret &= 0xfff0; + } else + ret = pas16_readdmab(pas16); + + if (pas16->sys_conf_2 & PAS16_SC2_MSBINV) + ret ^= 0x8000; + + return ret; +} + +static void +pas16_pit_timer0(const int new_out, UNUSED(int old_out), void *priv) +{ + const pitf_t *pit = (const pitf_t *) priv; + pas16_t * pas16 = (pas16_t *) pit->dev_priv; + + if (!pas16->pit->counters[0].gate) + return; + + if (!dma_channel_readable(pas16->dma)) + return; + + pas16_update_irq(pas16); + + if (((pas16->pcm_ctrl & PAS16_PCM_ENA) == PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) { + uint16_t temp; + + pas16->ticks = 0; + + if (pas16->pcm_ctrl & PAS16_PCM_MONO) { + temp = pas16_readdma_mono(pas16); + + pas16->pcm_dat_l = pas16->pcm_dat_r = temp; + } else { + temp = pas16_readdma_stereo(pas16); + + if (pas16->sys_conf_1 & 0x02) { + pas16->pcm_dat_l = temp; + + temp = pas16_readdma_stereo(pas16); + + 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; + pas16->irq_stat = (pas16->irq_stat & 0xdf) | (pas16->stereo_lr << 5); } } - 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); + if (pas16->ticks) { + for (uint16_t i = 0; i < pas16->ticks; i++) + pitf_ctr_clock(pas16->pit, 1); + + pas16->ticks = 0; + } + + pas16->irq_stat |= PAS16_INT_SAMP; + if (pas16->irq_ena & PAS16_INT_SAMP) { + pas16_log("INT SAMP.\n"); + if (pas16->irq != -1) + picint(1 << pas16->irq); + } + + pas16_update(pas16); + } +} + +static void +pas16_pit_timer1(const int new_out, UNUSED(int old_out), void *priv) +{ + const pitf_t *pit = (pitf_t * )priv; + pas16_t * pas16 = (pas16_t *) pit->dev_priv; + + if (!pas16->pit->counters[1].gate) + return; + + /* At new_out = 0, it's in the counter reload phase. */ + if ((pas16->pcm_ctrl & PAS16_PCM_ENA) && (pit->counters[1].m & 2) && new_out) { + if (pas16->irq_ena & PAS16_INT_PCM) { + pas16->irq_stat |= PAS16_INT_PCM; + pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); + if (pas16->irq != -1) picint(1 << pas16->irq); - } } } } @@ -665,46 +1869,54 @@ pas16_out_base(UNUSED(uint16_t port), uint8_t val, void *priv) { 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_log("[%04X:%08X] PAS16: [W] %04X = %02X\n", CS, cpu_state.pc, port, val); - pas16->base = val << 2; - pas16_log("pas16_write_base : PAS16 base now at %04X\n", pas16->base); + if (pas16->master_ff && (pas16->board_id == pas16->this_id)) + pas16->new_base = val << 2; + else if (!pas16->master_ff) + pas16->board_id = val; - 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->master_ff = !pas16->master_ff; +} + +static void +pas16_input_msg(void *priv, uint8_t *msg, uint32_t len) +{ + pas16_t *pas16 = (pas16_t *) priv; + + if (pas16->sysex) + return; + + if (pas16->midi_uart_in) { + pas16->midi_stat |= 0x04; + + for (uint32_t i = 0; i < len; i++) { + pas16->midi_queue[pas16->midi_w++] = msg[i]; + pas16->midi_w &= 0xff; + } + + pas16_update_irq(pas16); + } +} + +static int +pas16_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) +{ + pas16_t *pas16 = (pas16_t *) priv; + + if (abort) { + pas16->sysex = 0; + return 0; + } + pas16->sysex = 1; + for (uint32_t i = 0; i < len; i++) { + if (pas16->midi_r == pas16->midi_w) + return (int) (len - i); + pas16->midi_queue[pas16->midi_w++] = buffer[i]; + pas16->midi_w &= 0xff; + } + pas16->sysex = 0; + return 0; } static void @@ -724,38 +1936,450 @@ pas16_update(pas16_t *pas16) } void -pas16_get_buffer(int32_t *buffer, int len, void *priv) +pasplus_get_buffer(int32_t *buffer, int len, void *priv) { - pas16_t *pas16 = (pas16_t *) priv; + pas16_t * pas16 = (pas16_t *) priv; + const nsc_mixer_t *mixer = &pas16->nsc_mixer; + double bass_treble; - 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); + for (int c = 0; c < len * 2; c += 2) { + double out_l = pas16->dsp.buffer[c]; + double out_r = pas16->dsp.buffer[c + 1]; + + if (pas16->filter) { + /* We divide by 3 to get the volume down to normal. */ + out_l += low_fir_pas16(0, (double) pas16->pcm_buffer[0][c >> 1]) * mixer->pcm_l; + out_r += low_fir_pas16(1, (double) pas16->pcm_buffer[1][c >> 1]) * mixer->pcm_r; + } else { + out_l += ((double) pas16->pcm_buffer[0][c >> 1]) * mixer->pcm_l; + out_r += ((double) pas16->pcm_buffer[1][c >> 1]) * mixer->pcm_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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->bass]; + + if (mixer->bass > 6) { + out_l += (low_iir(0, 0, out_l) * bass_treble); + out_r += (low_iir(0, 1, out_r) * bass_treble); + } else if (mixer->bass < 6) { + out_l = (out_l *bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + } + + if (mixer->treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->treble]; + + if (mixer->treble > 6) { + out_l += (high_iir(0, 0, out_l) * bass_treble); + out_r += (high_iir(0, 1, out_r) * bass_treble); + } else if (mixer->treble < 6) { + out_l = (out_l *bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + } + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; } pas16->pos = 0; - pas16->opl.reset_buffer(pas16->opl.priv); pas16->dsp.pos = 0; } -static void * -pas16_init(UNUSED(const device_t *info)) +void +pasplus_get_music_buffer(int32_t *buffer, int len, void *priv) { - pas16_t *pas16 = malloc(sizeof(pas16_t)); - memset(pas16, 0, sizeof(pas16_t)); + const pas16_t * pas16 = (const pas16_t *) priv; + const nsc_mixer_t *mixer = &pas16->nsc_mixer; + const int32_t * opl_buf = pas16->opl.update(pas16->opl.priv); + double bass_treble; + for (int c = 0; c < len * 2; c += 2) { + double out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; + double out_r = (((double) opl_buf[c + 1]) * mixer->fm_r) * 0.7171630859375; + + /* 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; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->bass]; + + if (mixer->bass > 6) { + out_l += (low_iir(1, 0, out_l) * bass_treble); + out_r += (low_iir(1, 1, out_r) * bass_treble); + } else if (mixer->bass < 6) { + out_l = (out_l *bass_treble + low_cut_iir(1, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + low_cut_iir(1, 1, out_r) * (1.0 - bass_treble)); + } + } + + if (mixer->treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->treble]; + + if (mixer->treble > 6) { + out_l += (high_iir(1, 0, out_l) * bass_treble); + out_r += (high_iir(1, 1, out_r) * bass_treble); + } else if (mixer->treble < 6) { + out_l = (out_l *bass_treble + high_cut_iir(1, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + high_cut_iir(1, 1, out_r) * (1.0 - bass_treble)); + } + } + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + pas16->opl.reset_buffer(pas16->opl.priv); +} + +void +pasplus_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const pas16_t * pas16 = (const pas16_t *) priv; + const nsc_mixer_t *mixer = &pas16->nsc_mixer; + const double cd = channel ? mixer->cd_r : mixer->cd_l; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = mixer->bass; + const int32_t treble = mixer->treble; + double c = (*buffer) * cd * master; + double bass_treble; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[bass]; + + if (bass > 6) + c += (low_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(2, channel, c) * (1.0 - bass_treble)); + } + + if (treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[treble]; + + if (treble > 6) + c += (high_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(2, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c; +} + +void +pasplus_filter_pc_speaker(int channel, double *buffer, void *priv) +{ + const pas16_t * pas16 = (pas16_t *) priv; + const nsc_mixer_t *mixer = &pas16->nsc_mixer; + const double spk = channel ? mixer->speaker_r : mixer->speaker_l; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = mixer->bass; + const int32_t treble = mixer->treble; + double c = (*buffer) * spk * master; + double bass_treble; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[bass]; + + if (bass > 6) + c += (low_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(3, channel, c) * (1.0 - bass_treble)); + } + + if (treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[treble]; + + if (treble > 6) + c += (high_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(3, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c; +} + +void +pas16_get_buffer(int32_t *buffer, int len, void *priv) +{ + pas16_t * pas16 = (pas16_t *) priv; + const mv508_mixer_t *mixer = &pas16->mv508_mixer; + double bass_treble; + + sb_dsp_update(&pas16->dsp); + pas16_update(pas16); + for (int c = 0; c < len * 2; c += 2) { + double out_l = (pas16->dsp.buffer[c] * mixer->sb_l) / 3.0; + double out_r = (pas16->dsp.buffer[c + 1] * mixer->sb_r) / 3.0; + + if (pas16->filter) { + /* We divide by 3 to get the volume down to normal. */ + out_l += (low_fir_pas16(0, (double) pas16->pcm_buffer[0][c >> 1]) * mixer->pcm_l) / 3.0; + out_r += (low_fir_pas16(1, (double) pas16->pcm_buffer[1][c >> 1]) * mixer->pcm_r) / 3.0; + } else { + out_l += (((double) pas16->pcm_buffer[0][c >> 1]) * mixer->pcm_l) / 3.0; + out_r += (((double) pas16->pcm_buffer[1][c >> 1]) * mixer->pcm_r) / 3.0; + } + + 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->bass]; + + if (mixer->bass > 6) { + out_l += (low_iir(0, 0, out_l) * bass_treble); + out_r += (low_iir(0, 1, out_r) * bass_treble); + } else if (mixer->bass < 6) { + out_l = (out_l *bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + } + + if (mixer->treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->treble]; + + if (mixer->treble > 6) { + out_l += (high_iir(0, 0, out_l) * bass_treble); + out_r += (high_iir(0, 1, out_r) * bass_treble); + } else if (mixer->treble < 6) { + out_l = (out_l *bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + } + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + pas16->pos = 0; + pas16->dsp.pos = 0; +} + +void +pas16_get_music_buffer(int32_t *buffer, int len, void *priv) +{ + const pas16_t * pas16 = (const pas16_t *) priv; + const mv508_mixer_t *mixer = &pas16->mv508_mixer; + const int32_t * opl_buf = pas16->opl.update(pas16->opl.priv); + double bass_treble; + + for (int c = 0; c < len * 2; c += 2) { + double out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; + double out_r = (((double) opl_buf[c + 1]) * mixer->fm_r) * 0.7171630859375; + + /* 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; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->bass]; + + if (mixer->bass > 6) { + out_l += (low_iir(1, 0, out_l) * bass_treble); + out_r += (low_iir(1, 1, out_r) * bass_treble); + } else if (mixer->bass < 6) { + out_l = (out_l *bass_treble + low_cut_iir(1, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + low_cut_iir(1, 1, out_r) * (1.0 - bass_treble)); + } + } + + if (mixer->treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[mixer->treble]; + + if (mixer->treble > 6) { + out_l += (high_iir(1, 0, out_l) * bass_treble); + out_r += (high_iir(1, 1, out_r) * bass_treble); + } else if (mixer->treble < 6) { + out_l = (out_l *bass_treble + high_cut_iir(1, 0, out_l) * (1.0 - bass_treble)); + out_r = (out_r *bass_treble + high_cut_iir(1, 1, out_r) * (1.0 - bass_treble)); + } + } + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + pas16->opl.reset_buffer(pas16->opl.priv); +} + +void +pas16_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const pas16_t * pas16 = (const pas16_t *) priv; + const mv508_mixer_t *mixer = &pas16->mv508_mixer; + const double cd = channel ? mixer->cd_r : mixer->cd_l; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = mixer->bass; + const int32_t treble = mixer->treble; + double c = (((*buffer) * cd) / 3.0) * master; + double bass_treble; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[bass]; + + if (bass > 6) + c += (low_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(2, channel, c) * (1.0 - bass_treble)); + } + + if (treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[treble]; + + if (treble > 6) + c += (high_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(2, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c; +} + +void +pas16_filter_pc_speaker(int channel, double *buffer, void *priv) +{ + const pas16_t * pas16 = (const pas16_t *) priv; + const mv508_mixer_t *mixer = &pas16->mv508_mixer; + const double spk = channel ? mixer->speaker_r : mixer->speaker_l; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = mixer->bass; + const int32_t treble = mixer->treble; + double c = (((*buffer) * spk) / 3.0) * master; + double bass_treble; + + /* 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 != 6) { + bass_treble = lmc1982_bass_treble_4bits[bass]; + + if (bass > 6) + c += (low_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(3, channel, c) * (1.0 - bass_treble)); + } + + if (treble != 6) { + bass_treble = lmc1982_bass_treble_4bits[treble]; + + if (treble > 6) + c += (high_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(3, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c; +} + +static void +pas16_speed_changed(void *priv) +{ + pas16_change_pit_clock_speed(priv); +} + +static void * +pas16_init(const device_t *info) +{ + pas16_t *pas16 = calloc(1, sizeof(pas16_t)); + + if (pas16_next > 3) { + fatal("Attempting to add a Pro Audio Spectrum instance beyond the maximum amount\n"); + + free(pas16); + return NULL; + } + + pas16->type = info->local & 0xff; + pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f); fm_driver_get(FM_YMF262, &pas16->opl); + sb_dsp_set_real_opl(&pas16->dsp, 1); sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16); + pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(pas16->mpu, 0, sizeof(mpu_t)); + mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&pas16->dsp, pas16->mpu); + + pas16->sb_compat_base = 0x0000; io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16); + pas16->this_id = 0xbc + pas16_next; - timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0); + if (pas16->has_scsi) { + pas16->scsi = device_add(&scsi_pas_device); + timer_add(&pas16->scsi->timer, pas16_scsi_callback, pas16, 0); + timer_add(&pas16->scsi_timer, pas16_timeout_callback, pas16, 0); + other_scsi_present++; + } - sound_add_handler(pas16_get_buffer, pas16); + pas16->pit = device_add(&i8254_ext_io_fast_device); + pas16_reset(pas16); + pas16->pit->dev_priv = pas16; + pas16->irq = pas16->type ? 10 : 5; + pas16->io_conf_3 = pas16->type ? 0x07 : 0x04; + if (pas16->has_scsi) { + pas16->scsi_irq = pas16->type ? 11 : 7; + pas16->io_conf_3 |= (pas16->type ? 0x80 : 0x60); + ncr5380_set_irq(&pas16->scsi->ncr, pas16->scsi_irq); + } + pas16->dma = 3; + for (uint8_t i = 0; i < 3; i++) + pitf_ctr_set_gate(pas16->pit, i, 0); + + pitf_ctr_set_out_func(pas16->pit, 0, pas16_pit_timer0); + pitf_ctr_set_out_func(pas16->pit, 1, pas16_pit_timer1); + pitf_ctr_set_using_timer(pas16->pit, 0, 1); + pitf_ctr_set_using_timer(pas16->pit, 1, 0); + pitf_ctr_set_using_timer(pas16->pit, 2, 0); + + if (pas16->type) { + sound_add_handler(pas16_get_buffer, pas16); + music_add_handler(pas16_get_music_buffer, pas16); + sound_set_cd_audio_filter(pas16_filter_cd_audio, pas16); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(pas16_filter_pc_speaker, pas16); + } else { + sound_add_handler(pasplus_get_buffer, pas16); + music_add_handler(pasplus_get_music_buffer, pas16); + sound_set_cd_audio_filter(pasplus_filter_cd_audio, pas16); + if (device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(pasplus_filter_pc_speaker, pas16); + } + + if (device_get_config_int("receive_input")) + midi_in_handler(1, pas16_input_msg, pas16_input_sysex, pas16); + + for (uint8_t i = 0; i < 16; i++) { + if (i < 6) + lmc1982_bass_treble_4bits[i] = pow(10.0, (-((double) (12 - (i << 1))) / 10.0)); + else if (i == 6) + lmc1982_bass_treble_4bits[i] = 0.0; + else if ((i > 6) && (i <= 12)) + lmc1982_bass_treble_4bits[i] = 1.0 - pow(10.0, ((double) ((i - 6) << 1) / 10.0)); + else + lmc1982_bass_treble_4bits[i] = 1.0 - pow(10.0, 1.2); + } + + pas16_next++; return pas16; } @@ -766,18 +2390,73 @@ pas16_close(void *priv) pas16_t *pas16 = (pas16_t *) priv; free(pas16); + + pas16_next = 0; } -const device_t pas16_device = { - .name = "Pro Audio Spectrum 16", - .internal_name = "pas16", +static const device_config_t pas16_config[] = { + { + .name = "control_pc_speaker", + .description = "Control PC speaker", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input401", + .description = "Receive input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 0 + }, + { + .name = "receive_input", + .description = "Receive input (PAS MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +const device_t pasplus_device = { + .name = "Pro Audio Spectrum Plus", + .internal_name = "pasplus", .flags = DEVICE_ISA, .local = 0, .init = pas16_init, .close = pas16_close, - .reset = NULL, + .reset = pas16_reset, { .available = NULL }, - .speed_changed = NULL, + .speed_changed = pas16_speed_changed, .force_redraw = NULL, - .config = NULL + .config = pas16_config +}; + +const device_t pas16_device = { + .name = "Pro Audio Spectrum 16", + .internal_name = "pas16", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x0f, + .init = pas16_init, + .close = pas16_close, + .reset = pas16_reset, + { .available = NULL }, + .speed_changed = pas16_speed_changed, + .force_redraw = NULL, + .config = pas16_config +}; + +const device_t pas16d_device = { + .name = "Pro Audio Spectrum 16D", + .internal_name = "pas16d", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0x0c, + .init = pas16_init, + .close = pas16_close, + .reset = pas16_reset, + { .available = NULL }, + .speed_changed = pas16_speed_changed, + .force_redraw = NULL, + .config = pas16_config }; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 602c1c2a7..364c01557 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -43,6 +43,19 @@ #include <86box/snd_sb.h> #include <86box/plat_unused.h> +#define PNP_ROM_SB_16_PNP "roms/sound/creative/CTL0024A.BIN" +#define PNP_ROM_SB_VIBRA16XV "roms/sound/creative/CT4170 PnP.BIN" +#define PNP_ROM_SB_VIBRA16C "roms/sound/creative/CT4180 PnP.BIN" +#define PNP_ROM_SB_32_PNP "roms/sound/creative/CT3600 PnP.BIN" +#define PNP_ROM_SB_AWE32_PNP "roms/sound/creative/CT3980 PnP.BIN" +#define PNP_ROM_SB_AWE64_VALUE "roms/sound/creative/CT4520 PnP.BIN" +#define PNP_ROM_SB_AWE64 "roms/sound/creative/CTL009DA.BIN" +#define PNP_ROM_SB_AWE64_GOLD "roms/sound/creative/CT4540 PnP.BIN" +/* TODO: Find real ESS PnP ROM dumps. */ +#define PNP_ROM_ESS0100 "roms/sound/ess/ESS0100.BIN" +#define PNP_ROM_ESS0102 "roms/sound/ess/ESS0102.BIN" +#define PNP_ROM_ESS0968 "roms/sound/ess/ESS0968.BIN" + /* 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[] = { @@ -67,97 +80,30 @@ static const double sb_att_4dbstep_3bits[] = { static const double sb_att_7dbstep_2bits[] = { 164.0, 6537.0, 14637.0, 32767.0 }; + +/* Attenuation table for ESS 4-bit microphone volume. + * The last step is a jump to -48 dB. */ +static const double sb_att_1p4dbstep_4bits[] = { + 164.0, 3431.0, 4031.0, 4736.0, 5565.0, 6537.0, 7681.0, 9025.0, + 10603.0, 12458.0, 14637.0, 17196.0, 20204.0, 23738.0, 27889.0, 32767.0 +}; + +/* Attenuation table for ESS 4-bit mixer volume. + * The last step is a jump to -48 dB. */ +static const double sb_att_2dbstep_4bits[] = { + 164.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 +}; + +/* Attenuation table for ESS 3-bit PC speaker volume. */ +static const double sb_att_3dbstep_3bits[] = { + 0.0, 4125.0, 5826.0, 8230.0, 11626.0, 16422.0, 23197.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 }; -/* 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 */ - - 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 */ - - 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 */ - - 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 */ - - 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; @@ -180,15 +126,9 @@ sb_log(const char *fmt, ...) static void sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) { - 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) - opl_buf = sb->opl.update(sb->opl.priv); + sb_t *sb = (sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + double out_mono; sb_dsp_update(&sb->dsp); @@ -196,21 +136,15 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) cms_update(&sb->cms); 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) opl_buf[c]) * 0.7171630859375; + double out_l = 0.0; + double out_r = 0.0; 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) { + if (sb->cms_enabled && sb->mixer_enabled) { out_l *= mixer->fm; out_r *= mixer->fm; } @@ -234,17 +168,47 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) buffer[c + 1] += (int32_t) out_r; } - sb->pos = 0; - - if (sb->opl_enabled) - sb->opl.reset_buffer(sb->opl.priv); - sb->dsp.pos = 0; if (sb->cms_enabled) sb->cms.pos = 0; } +static void +sb_get_music_buffer_sb2(int32_t *buffer, int len, void *priv) +{ + const sb_t *sb = (const sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + const int32_t *opl_buf = NULL; + + opl_buf = sb->opl.update(sb->opl.priv); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; + + const double out_mono = ((double) opl_buf[c]) * 0.7171630859375; + + out_l += out_mono; + out_r += out_mono; + + if (sb->mixer_enabled) { + out_l *= mixer->fm; + out_r *= mixer->fm; + } + + 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; + } + + sb->opl.reset_buffer(sb->opl.priv); +} + static void sb2_filter_cd_audio(UNUSED(int channel), double *buffer, void *priv) { @@ -253,52 +217,25 @@ sb2_filter_cd_audio(UNUSED(int channel), double *buffer, void *priv) double c; if (sb->mixer_enabled) { - c = ((sb_iir(1, 0, *buffer) / 1.3) * mixer->cd) / 3.0; + c = ((sb_iir(2, 0, *buffer) / 1.3) * mixer->cd) / 3.0; *buffer = c * mixer->master; } else { - c = (((sb_iir(1, 0, (*buffer)) / 1.3) * 65536) / 3.0) / 65536.0; + c = (((sb_iir(2, 0, (*buffer)) / 1.3) * 65536) / 3.0) / 65536.0; *buffer = c; } } void -sb_get_buffer_sbpro(int32_t *buffer, int len, void *priv) +sb_get_buffer_sbpro(int32_t *buffer, const int len, void *priv) { 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) { - 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 (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) 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); - } - } - } + double out_l = 0.0; + double out_r = 0.0; /* TODO: Implement the stereo switch on the mixer instead of on the dsp? */ if (mixer->output_filter) { @@ -317,78 +254,84 @@ sb_get_buffer_sbpro(int32_t *buffer, int len, void *priv) buffer[c + 1] += (int32_t) out_r; } - sb->pos = 0; - - if (sb->opl_enabled) { - 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 *priv) +sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) { - 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; + 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 (mixer->output_filter) - c = (sb_iir(1, channel, *buffer) * cd) / 3.9; - else - c = (*buffer * cd) / 3.0; - *buffer = c * master; -} + if (!sb->opl_enabled) + return; -static void -sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) -{ - 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) + 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); - if (sb->dsp.sb_type > SB16) - emu8k_update(&sb->emu8k); - sb_dsp_update(&sb->dsp); 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) * FREQ_44100) / SOUND_FREQ) * 2); - - 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 == 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; + if (opl2_buf != NULL) + 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); } - 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: 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; - /* 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; + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + sb->opl.reset_buffer(sb->opl.priv); + if (sb->dsp.sb_type == SBPRO) + sb->opl2.reset_buffer(sb->opl2.priv); +} + +void +sbpro_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const sb_t *sb = (sb_t *) priv; + const sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + const double cd = channel ? mixer->cd_r : mixer->cd_l; + const double master = channel ? mixer->master_r : mixer->master_l; + double c = ((*buffer * cd) / 3.0) * master; + + *buffer = c; +} + +static void +sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) +{ + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + double bass_treble; + + sb_dsp_update(&sb->dsp); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; if (mixer->output_filter) { /* We divide by 3 to get the volume down to normal. */ @@ -409,7 +352,7 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) if (mixer->bass_l > 8) out_l += (low_iir(0, 0, out_l) * bass_treble); - else if (mixer->bass_l < 8) + else out_l = (out_l *bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); } @@ -418,7 +361,7 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) if (mixer->bass_r > 8) out_r += (low_iir(0, 1, out_r) * bass_treble); - else if (mixer->bass_r < 8) + else out_r = (out_r *bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); } @@ -427,7 +370,7 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) if (mixer->treble_l > 8) out_l += (high_iir(0, 0, out_l) * bass_treble); - else if (mixer->treble_l < 8) + else out_l = (out_l *bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); } @@ -436,12 +379,88 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) if (mixer->treble_r > 8) out_r += (high_iir(0, 1, out_r) * bass_treble); - else if (mixer->treble_r < 8) + else out_r = (out_l *bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); } + buffer[c] += (int32_t) (out_l * mixer->output_gain_L); + buffer[c + 1] += (int32_t) (out_r * mixer->output_gain_R); + } + + sb->dsp.pos = 0; +} + +static void +sb_get_music_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv) +{ + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + const int dsp_rec_pos = sb->dsp.record_pos_write; + double bass_treble; + const int32_t *opl_buf = NULL; + + if (sb->opl_enabled) + opl_buf = sb->opl.update(sb->opl.priv); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; + + 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; + } + + /* TODO: Multi-recording mic with agc/+20db, CD, and line in with channel inversion */ + int32_t 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; + int32_t 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; + + 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]; + + if (mixer->bass_l > 8) + out_l += (low_iir(1, 0, out_l) * bass_treble); + else + out_l = (out_l *bass_treble + low_cut_iir(1, 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) + out_r += (low_iir(1, 1, out_r) * bass_treble); + else + out_r = (out_r *bass_treble + low_cut_iir(1, 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) + out_l += (high_iir(1, 0, out_l) * bass_treble); + else + out_l = (out_l *bass_treble + high_cut_iir(1, 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) + out_r += (high_iir(1, 1, out_r) * bass_treble); + else + out_r = (out_l *bass_treble + high_cut_iir(1, 1, out_r) * (1.0 - bass_treble)); + } + if (sb->dsp.sb_enable_i) { - c_record = dsp_rec_pos + ((c * sb->dsp.sb_freq) / SOUND_FREQ); + const int c_record = dsp_rec_pos + ((c * sb->dsp.sb_freq) / MUSIC_FREQ); + in_l <<= mixer->input_gain_L; in_r <<= mixer->input_gain_R; @@ -456,8 +475,8 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) 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] = (int16_t) in_l; + sb->dsp.record_buffer[(c_record + 1) & 0xffff] = (int16_t) in_r; } buffer[c] += (int32_t) (out_l * mixer->output_gain_L); @@ -467,35 +486,86 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) sb->dsp.record_pos_write += ((len * sb->dsp.sb_freq) / 24000); sb->dsp.record_pos_write &= 0xffff; - sb->pos = 0; - if (sb->opl_enabled) sb->opl.reset_buffer(sb->opl.priv); +} - sb->dsp.pos = 0; +static void +sb_get_wavetable_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv) +{ + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + double bass_treble; - if (sb->dsp.sb_type > SB16) - sb->emu8k.pos = 0; + emu8k_update(&sb->emu8k); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; + + out_l += (((double) sb->emu8k.buffer[c]) * mixer->fm_l); + out_r += (((double) sb->emu8k.buffer[c + 1]) * mixer->fm_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]; + + if (mixer->bass_l > 8) + out_l += (low_iir(4, 0, out_l) * bass_treble); + else + out_l = (out_l *bass_treble + low_cut_iir(4, 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) + out_r += (low_iir(4, 1, out_r) * bass_treble); + else + out_r = (out_r *bass_treble + low_cut_iir(4, 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) + out_l += (high_iir(4, 0, out_l) * bass_treble); + else + out_l = (out_l *bass_treble + high_cut_iir(4, 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) + out_r += (high_iir(4, 1, out_r) * bass_treble); + else + out_r = (out_l *bass_treble + high_cut_iir(4, 1, out_r) * (1.0 - bass_treble)); + } + + buffer[c] += (int32_t) (out_l * mixer->output_gain_L); + buffer[c + 1] += (int32_t) (out_r * mixer->output_gain_R); + } + + sb->emu8k.pos = 0; } void sb16_awe32_filter_cd_audio(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 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; + const sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + const double cd = channel ? mixer->cd_r : mixer->cd_l /* / 3.0 */; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = channel ? mixer->bass_r : mixer->bass_l; + const int32_t treble = channel ? mixer->treble_r : mixer->treble_l; + const double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); double bass_treble; - double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); - - if (mixer->output_filter) - c = (low_fir_sb16(1, channel, *buffer) * cd) / 3.0; - else - c = ((*buffer) * cd) / 3.0; - c *= master; + double c = (((*buffer) * cd) / 3.0) * 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. */ @@ -503,18 +573,18 @@ sb16_awe32_filter_cd_audio(int channel, double *buffer, void *priv) 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)); + c += (low_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(2, channel, c) * (1.0 - bass_treble)); } if (treble != 8) { 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)); + c += (high_iir(2, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(2, channel, c) * (1.0 - bass_treble)); } *buffer = c * output_gain; @@ -523,18 +593,18 @@ sb16_awe32_filter_cd_audio(int channel, double *buffer, void *priv) 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; + const sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + const double spk = mixer->speaker; + const double master = channel ? mixer->master_r : mixer->master_l; + const int32_t bass = channel ? mixer->bass_r : mixer->bass_l; + const int32_t treble = channel ? mixer->treble_r : mixer->treble_l; + const double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); double bass_treble; - double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); + double c; if (mixer->output_filter) - c = (low_fir_sb16(2, channel, *buffer) * spk) / 3.0; + c = (low_fir_sb16(3, channel, *buffer) * spk) / 3.0; else c = ((*buffer) * spk) / 3.0; c *= master; @@ -545,23 +615,118 @@ sb16_awe32_filter_pc_speaker(int channel, double *buffer, void *priv) 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)); + c += (low_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + low_cut_iir(3, 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)); + c += (high_iir(3, channel, c) * bass_treble); + else + c = (c * bass_treble + high_cut_iir(3, channel, c) * (1.0 - bass_treble)); } *buffer = c * output_gain; } +void +sb_get_buffer_ess(int32_t *buffer, int len, void *priv) +{ + sb_t *ess = (sb_t *) priv; + const ess_mixer_t *mixer = &ess->mixer_ess; + + sb_dsp_update(&ess->dsp); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; + + /* TODO: Implement the stereo switch on the mixer instead of on the dsp? */ + if (mixer->output_filter) { + out_l += (low_fir_sb16(0, 0, (double) ess->dsp.buffer[c]) * mixer->voice_l) / 3.0; + out_r += (low_fir_sb16(0, 1, (double) ess->dsp.buffer[c + 1]) * mixer->voice_r) / 3.0; + } else { + out_l += (ess->dsp.buffer[c] * mixer->voice_l) / 3.0; + out_r += (ess->dsp.buffer[c + 1] * mixer->voice_r) / 3.0; + } + + /* TODO: recording from the mixer. */ + out_l *= mixer->master_l; + out_r *= mixer->master_r; + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + ess->dsp.pos = 0; +} + +void +sb_get_music_buffer_ess(int32_t *buffer, int len, void *priv) +{ + sb_t *ess = (sb_t *) priv; + const ess_mixer_t *mixer = &ess->mixer_ess; + double out_l = 0.0; + double out_r = 0.0; + const int32_t *opl_buf = NULL; + + opl_buf = ess->opl.update(ess->opl.priv); + + for (int c = 0; c < len * 2; c += 2) { + out_l = 0.0; + out_r = 0.0; + + out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; + out_r = (((double) opl_buf[c + 1]) * mixer->fm_r) * 0.7171630859375; + if (ess->opl_mix && ess->opl_mixer) + ess->opl_mix(ess->opl_mixer, &out_l, &out_r); + + /* TODO: recording from the mixer. */ + out_l *= mixer->master_l; + out_r *= mixer->master_r; + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + ess->opl.reset_buffer(ess->opl.priv); +} + +void +ess_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const sb_t *ess = (sb_t *) priv; + const ess_mixer_t *mixer = &ess->mixer_ess; + double c; + double cd = channel ? mixer->cd_r : mixer->cd_l; + double master = channel ? mixer->master_r : mixer->master_l; + + /* TODO: recording from the mixer. */ + c = (*buffer * cd) / 3.0; + *buffer = c * master; +} + +void +ess_filter_pc_speaker(int channel, double *buffer, void *priv) +{ + const sb_t *ess = (sb_t *) priv; + const ess_mixer_t *mixer = &ess->mixer_ess; + double c; + double spk = mixer->speaker; + double master = channel ? mixer->master_r : mixer->master_l; + + if (mixer->output_filter) + c = (low_fir_sb16(3, channel, *buffer) * spk) / 3.0; + else + c = ((*buffer) * spk) / 3.0; + c *= master; + + *buffer = c; +} + void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *priv) { @@ -636,7 +801,10 @@ void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *priv) { sb_t *sb = (sb_t *) priv; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + sb_ct1345_mixer_t *mixer = (sb == NULL) ? NULL : &sb->mixer_sbpro; + + if (mixer == NULL) + return; if (!(addr & 1)) { mixer->index = val; @@ -774,7 +942,10 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) { sb_t *sb = (sb_t *) priv; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + sb_ct1745_mixer_t *mixer = (sb == NULL) ? NULL : &sb->mixer_sb16; + + if (mixer == NULL) + return; if (!(addr & 1)) mixer->index = val; @@ -796,7 +967,9 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) mixer->regs[0x36] = mixer->regs[0x37] = 0xf8; mixer->regs[0x38] = mixer->regs[0x39] = 0x00; - mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00; + mixer->regs[0x3a] = 0x00; + /* Speaker control - it appears to be in steps of 64. */ + mixer->regs[0x3b] = 0x80; 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); @@ -980,7 +1153,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) 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->speaker = sb_att_7dbstep_2bits[(mixer->regs[0x3b] >> 6) & 0x3] / 32768.0; mixer->input_gain_L = (mixer->regs[0x3f] >> 6); mixer->input_gain_R = (mixer->regs[0x40] >> 6); @@ -1002,7 +1175,6 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) { 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)) @@ -1105,6 +1277,8 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) break; } switch (sb->dsp.sb_16_dmanum) { + default: + break; case 5: ret |= 0x20; break; @@ -1118,6 +1292,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) break; case 0x82: + ; /* Empty statement to make compilers happy about the following variable declaration. */ /* 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. */ @@ -1126,8 +1301,8 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) 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); + const uint8_t 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 @@ -1193,8 +1368,278 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) void sb_ct1745_mixer_reset(sb_t *sb) { - sb_ct1745_mixer_write(4, 0, sb); - sb_ct1745_mixer_write(5, 0, sb); + if (sb != NULL) { + sb_ct1745_mixer_write(4, 0, sb); + sb_ct1745_mixer_write(5, 0, sb); + } +} + +void +ess_mixer_write(uint16_t addr, uint8_t val, void *priv) +{ + sb_t *ess = (sb_t *) priv; + ess_mixer_t *mixer = (ess == NULL) ? NULL : &ess->mixer_ess; + + sb_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if (mixer == NULL) + return; + + if (!(addr & 1)) { + mixer->index = val; + mixer->regs[0x01] = val; + if (val == 0x40) { + mixer->ess_id_str_pos = 0; + } + } 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; + + /* Initialize ESS regs + * Defaulting to 0dB instead of the standard -11dB. */ + mixer->regs[0x14] = mixer->regs[0x32] = 0xff; + mixer->regs[0x36] = mixer->regs[0x38] = 0xff; + mixer->regs[0x3a] = 0x00; + mixer->regs[0x3c] = 0x05; + mixer->regs[0x3e] = 0x00; + + sb_dsp_set_stereo(&ess->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; + + case 0x0A: + { + uint8_t mic_vol_2bit = (mixer->regs[0x0a] >> 1) & 0x3; + mixer->mic_l = mixer->mic_r = sb_att_7dbstep_2bits[mic_vol_2bit] / 32767.0; + mixer->regs[0x1A] = mic_vol_2bit | (mic_vol_2bit << 2) | (mic_vol_2bit << 4) | (mic_vol_2bit << 6); + break; + } + + case 0x0C: + switch (mixer->regs[0x0C] & 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; + } + mixer->input_filter = !(mixer->regs[0xC] & 0x20); + mixer->in_filter_freq = ((mixer->regs[0xC] & 0x8) == 0) ? 3200 : 8800; + break; + + case 0x0E: + mixer->output_filter = !(mixer->regs[0xE] & 0x20); + mixer->stereo = mixer->regs[0xE] & 2; + sb_dsp_set_stereo(&ess->dsp, val & 2); + break; + + case 0x14: + mixer->regs[0x4] = val & 0xee; + break; + + case 0x1A: + mixer->mic_l = sb_att_1p4dbstep_4bits[(mixer->regs[0x1A] >> 4) & 0xF] / 32767.0; + mixer->mic_r = sb_att_1p4dbstep_4bits[mixer->regs[0x1A] & 0xF] / 32767.0; + break; + + case 0x1C: + if ((mixer->regs[0x1C] & 0x07) == 0x07) { + mixer->input_selector = INPUT_MIXER_L | INPUT_MIXER_R; + } else if ((mixer->regs[0x1C] & 0x07) == 0x06) { + mixer->input_selector = INPUT_LINE_L | INPUT_LINE_R; + } else if ((mixer->regs[0x1C] & 0x06) == 0x02) { + mixer->input_selector = INPUT_CD_L | INPUT_CD_R; + } else if ((mixer->regs[0x1C] & 0x02) == 0) { + mixer->input_selector = INPUT_MIC; + } + break; + + case 0x22: + case 0x26: + case 0x28: + case 0x2E: + mixer->regs[mixer->index - 0x20] = (val & 0xe); + mixer->regs[mixer->index + 0x10] = val; + 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: + case 0x3e: + mixer->regs[mixer->index - 0x10] = (val & 0xee); + break; + + case 0x00: case 0x04: case 0x3a: case 0x3c: + break; + + case 0x64: + mixer->regs[mixer->index] = (mixer->regs[mixer->index] & 0xf7) | 0x20; + // mixer->regs[mixer->index] &= ~0x8; + break; + + case 0x40: + { + uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] << 1) & 0x30); + sb_log("mpu401_base_addr = %04X\n", mpu401_base_addr); + gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200); + + if (ess->dsp.sb_subtype != SB_SUBTYPE_ESS_ES1688) { + /* Not on ES1688. */ + io_removehandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + if ((mixer->regs[0x40] & 0x1) != 0) { + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + } + } + switch ((mixer->regs[0x40] >> 5) & 0x7) { + default: + break; + case 0: + mpu401_change_addr(ess->mpu, 0x00); + mpu401_setirq(ess->mpu, -1); + break; + case 1: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, -1); + break; + case 2: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, ess->dsp.sb_irqnum); + break; + case 3: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 11); + break; + case 4: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 9); + break; + case 5: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 5); + break; + case 6: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 7); + break; + case 7: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 10); + break; + } + break; + } + + default: + sb_log("ess: Unknown mixer register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } + + mixer->voice_l = sb_att_2dbstep_4bits[(mixer->regs[0x14] >> 4) & 0x0F] / 32767.0; + mixer->voice_r = sb_att_2dbstep_4bits[mixer->regs[0x14] & 0x0F] / 32767.0; + mixer->master_l = sb_att_2dbstep_4bits[(mixer->regs[0x32] >> 4) & 0x0F] / 32767.0; + mixer->master_r = sb_att_2dbstep_4bits[mixer->regs[0x32] & 0x0F] / 32767.0; + mixer->fm_l = sb_att_2dbstep_4bits[(mixer->regs[0x36] >> 4) & 0x0F] / 32767.0; + mixer->fm_r = sb_att_2dbstep_4bits[mixer->regs[0x36] & 0x0F] / 32767.0; + mixer->cd_l = sb_att_2dbstep_4bits[(mixer->regs[0x38] >> 4) & 0x0F] / 32767.0; + mixer->cd_r = sb_att_2dbstep_4bits[mixer->regs[0x38] & 0x0F] / 32767.0; + mixer->auxb_l = sb_att_2dbstep_4bits[(mixer->regs[0x3a] >> 4) & 0x0F] / 32767.0; + mixer->auxb_r = sb_att_2dbstep_4bits[mixer->regs[0x3a] & 0x0F] / 32767.0; + mixer->line_l = sb_att_2dbstep_4bits[(mixer->regs[0x3e] >> 4) & 0x0F] / 32767.0; + mixer->line_r = sb_att_2dbstep_4bits[mixer->regs[0x3e] & 0x0F] / 32767.0; + mixer->speaker = sb_att_3dbstep_3bits[mixer->regs[0x3c] & 0x07] / 32767.0; + } +} + +uint8_t +ess_mixer_read(uint16_t addr, void *priv) +{ + const sb_t * ess = (sb_t *) priv; + const ess_mixer_t *mixer = &ess->mixer_ess; + uint8_t ret = 0x0a; + + if (!(addr & 1)) + ret = mixer->index; + else switch (mixer->index) { + case 0x00: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x14: + case 0x02: + case 0x06: + case 0x30: + case 0x32: + case 0x36: + case 0x38: + case 0x3e: + ret = mixer->regs[mixer->index]; + break; + + case 0x04: + case 0x22: + case 0x26: + case 0x28: + case 0x2e: + ret = mixer->regs[mixer->index] | 0x11; + break; + + case 0x40: + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index]; + else + ret = 0x0a; + break; + + case 0x48: + ret = mixer->regs[mixer->index]; + break; + + /* Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. */ + case 0x64: + ret = (mixer->regs[mixer->index] & 0xf7) | 0x20; + break; + + default: + sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + + sb_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +void +ess_mixer_reset(sb_t *ess) +{ + ess_mixer_write(4, 0, ess); + ess_mixer_write(5, 0, ess); } uint8_t @@ -1343,12 +1788,9 @@ sb_16_reply_mca_read(int port, void *priv) } static void -sb_16_reply_mca_write(int port, uint8_t val, void *priv) +sb_16_reply_mca_write(const int port, const 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) @@ -1402,6 +1844,8 @@ sb_16_reply_mca_write(int port, uint8_t val, void *priv) sb->pos_regs[port & 7] = val; if (sb->pos_regs[2] & 1) { + uint16_t mpu401_addr; + switch (sb->pos_regs[2] & 0xc4) { case 4: addr = 0x220; @@ -1420,6 +1864,7 @@ sb_16_reply_mca_write(int port, uint8_t val, void *priv) addr = 0; break; } + switch (sb->pos_regs[2] & 0x18) { case 8: mpu401_addr = 0x330; @@ -1472,8 +1917,8 @@ sb_16_reply_mca_write(int port, uint8_t val, void *priv) break; } - low_dma = sb->pos_regs[3] & 3; - high_dma = (sb->pos_regs[3] >> 4) & 7; + const int low_dma = sb->pos_regs[3] & 3; + int high_dma = (sb->pos_regs[3] >> 4) & 7; if (!high_dma) high_dma = low_dma; @@ -1521,13 +1966,16 @@ sb_vibra16s_onboard_relocate_base(uint16_t new_addr, void *priv) } static void -sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; uint16_t addr = sb->dsp.sb_addr; - uint8_t val; switch (ld) { + default: + case 4: /* StereoEnhance (32) */ + break; + case 0: /* Audio */ io_removehandler(addr, 0x0004, sb->opl.read, NULL, NULL, @@ -1559,6 +2007,8 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) mpu401_change_addr(sb->mpu, 0); if (config->activate) { + uint8_t val = config->irq[0].irq; + addr = config->io[0].base; if (addr != ISAPNP_IO_DISABLED) { io_sethandler(addr, 0x0004, @@ -1590,7 +2040,6 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) sb->opl.priv); } - val = config->irq[0].irq; if (val != ISAPNP_IRQ_DISABLED) sb_dsp_setirq(&sb->dsp, val); @@ -1623,17 +2072,11 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) 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; - - default: - break; } } static void -sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +sb_vibra16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; @@ -1649,7 +2092,7 @@ sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void * } static void -sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +sb_awe32_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; @@ -1670,7 +2113,28 @@ sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pr } static void -sb_awe64_gold_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +sb_awe64_pnp_config_changed(const 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 1: /* Game */ + case 3: /* IDE */ + sb_16_pnp_config_changed(ld ^ 2, config, sb); + break; + + default: + break; + } +} + +static void +sb_awe64_gold_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { sb_t *sb = (sb_t *) priv; @@ -1689,6 +2153,333 @@ sb_awe64_gold_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, voi } } +static void +ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *config, void *priv) +{ + sb_t *ess = (sb_t *) priv; + uint16_t addr = ess->dsp.sb_addr; + uint8_t val; + + switch (ld) { + case 0: /* Audio */ + io_removehandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + + ess->mixer_ess.ess_id_str[2] = 0x00; + ess->mixer_ess.ess_id_str[3] = 0x00; + + addr = ess->opl_pnp_addr; + if (addr) { + ess->opl_pnp_addr = 0; + io_removehandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + } + + if (ess->pnp == 3) + mpu401_change_addr(ess->mpu, 0); + + sb_dsp_setaddr(&ess->dsp, 0); + sb_dsp_setirq(&ess->dsp, 0); + if (ess->pnp == 3) + mpu401_setirq(ess->mpu, -1); + sb_dsp_setdma8(&ess->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16_8(&ess->dsp, ISAPNP_DMA_DISABLED); + + if (config->activate) { + addr = config->io[0].base; + if (addr != ISAPNP_IO_DISABLED) { + io_sethandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + + sb_dsp_setaddr(&ess->dsp, addr); + + ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff; + ess->mixer_ess.ess_id_str[3] = addr & 0xff; + } + + addr = config->io[1].base; + if (addr != ISAPNP_IO_DISABLED) { + ess->opl_pnp_addr = addr; + io_sethandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + } + + if (ess->pnp == 3) { + addr = config->io[2].base; + if (addr != ISAPNP_IO_DISABLED) + mpu401_change_addr(ess->mpu, addr); + } + + val = config->irq[0].irq; + if (val != ISAPNP_IRQ_DISABLED) { + sb_dsp_setirq(&ess->dsp, val); + if (ess->pnp == 3) + mpu401_setirq(ess->mpu, val); + } + + val = config->dma[0].dma; + if (val != ISAPNP_DMA_DISABLED) { + sb_dsp_setdma8(&ess->dsp, val); + sb_dsp_setdma16_8(&ess->dsp, val); + } + } + break; + + case 1: + if (ess->pnp == 3) { /* Game */ + gameport_remap(ess->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + } else { /* MPU-401 */ + mpu401_change_addr(ess->mpu, 0); + mpu401_setirq(ess->mpu, -1); + + if (config->activate) { + addr = config->io[0].base; + if (addr != ISAPNP_IO_DISABLED) + mpu401_change_addr(ess->mpu, addr); + + val = config->irq[0].irq; + if (val != ISAPNP_IRQ_DISABLED) + mpu401_setirq(ess->mpu, val); + } + } + break; + + case 2: + if (ess->pnp == 3) /* IDE */ + ide_pnp_config_changed_1addr(0, config, (void *) 3); + else /* Game */ + gameport_remap(ess->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; + + case 3: + if (ess->pnp <= 2) /* IDE */ + ide_pnp_config_changed_1addr(0, config, (void *) 3); + break; + + default: + break; + } +} + +/* This function is common to all the ESS MCA cards. */ +static uint8_t +ess_x688_mca_read(const int port, void *priv) +{ + const sb_t *ess = (sb_t *) priv; + const uint8_t ret = ess->pos_regs[port & 7]; + + sb_log("ess_mca_read: port=%04x ret=%02x\n", port, ret); + + return ret; +} + +static void +ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) +{ + sb_t *ess = (sb_t *) priv; + + if (port < 0x102) + return; + + sb_log("ess_soundpiper_mca_write: port=%04x val=%02x\n", port, val); + + if (ess->dsp.sb_addr != 0x0000) { + io_removehandler(ess->dsp.sb_addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&ess->dsp, 0); + gameport_remap(ess->gameport, 0); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_change_addr(ess->mpu, 0); + + ess->pos_regs[port & 7] = val; + + if (ess->pos_regs[2] & 1) { + switch (ess->pos_regs[2] & 0x0e) { + default: + ess->dsp.sb_addr = 0x0000; + break; + case 0x08: + ess->dsp.sb_addr = 0x0240; + break; + case 0x0c: + ess->dsp.sb_addr = 0x0220; + break; + } + + if (ess->dsp.sb_addr != 0x0000) { + io_sethandler(ess->dsp.sb_addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_change_addr(ess->mpu, ess->pos_regs[3] & 0x02 ? 0x0330 : 0); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&ess->dsp, ess->dsp.sb_addr); + gameport_remap(ess->gameport, (ess->pos_regs[3] & 0x01) ? 0x200 : 0); + } + + switch (ess->pos_regs[3] & 0xc0) { + default: + break; + case 0x80: + sb_dsp_setirq(&ess->dsp, 9); + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_setirq(ess->mpu, 9); + break; + case 0xa0: + sb_dsp_setirq(&ess->dsp, 5); + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_setirq(ess->mpu, 5); + break; + case 0xc0: + sb_dsp_setirq(&ess->dsp, 7); + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_setirq(ess->mpu, 7); + break; + case 0xe0: + sb_dsp_setirq(&ess->dsp, 10); + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_setirq(ess->mpu, 10); + break; + } + + if (ess->pos_regs[3] & 0x04) { + sb_dsp_setdma8(&ess->dsp, ess->pos_regs[2] >> 4); + sb_dsp_setdma16_8(&ess->dsp, ess->pos_regs[2] >> 4); + } +} + +static void +ess_chipchat_mca_write(int port, uint8_t val, void *priv) +{ + sb_t *ess = (sb_t *) priv; + + if (port < 0x102) + return; + + sb_log("ess_chipchat_mca_write: port=%04x val=%02x\n", port, val); + + if (ess->dsp.sb_addr != 0x0000) { + io_removehandler(ess->dsp.sb_addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&ess->dsp, 0); + gameport_remap(ess->gameport, 0); + + mpu401_change_addr(ess->mpu, 0); + + ess->pos_regs[port & 7] = val; + + if (ess->pos_regs[2] & 1) { + ess->dsp.sb_addr = (ess->pos_regs[2] == 0x51) ? 0x0220 : 0x0000; + + if (ess->dsp.sb_addr != 0x0000) { + io_sethandler(ess->dsp.sb_addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + mpu401_change_addr(ess->mpu, (ess->pos_regs[2] == 0x51) ? 0x0330 : 0); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&ess->dsp, ess->dsp.sb_addr); + gameport_remap(ess->gameport, (ess->pos_regs[2] == 0x51) ? 0x200 : 0); + } + + if (ess->pos_regs[2] == 0x51) { + sb_dsp_setirq(&ess->dsp, 7); + mpu401_setirq(ess->mpu, 7); + + sb_dsp_setdma8(&ess->dsp, 1); + sb_dsp_setdma16_8(&ess->dsp, 1); + } +} + void * sb_1_init(UNUSED(const device_t *info)) { @@ -1696,14 +2487,15 @@ sb_1_init(UNUSED(const device_t *info)) 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)); - uint16_t addr = device_get_config_hex16("base"); + sb_t * sb = malloc(sizeof(sb_t)); + const 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) fm_driver_get(FM_YM3812, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); @@ -1729,6 +2521,8 @@ sb_1_init(UNUSED(const device_t *info)) sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) @@ -1744,14 +2538,15 @@ sb_15_init(UNUSED(const device_t *info)) 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)); - uint16_t addr = device_get_config_hex16("base"); + sb_t * sb = malloc(sizeof(sb_t)); + const 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) fm_driver_get(FM_YM3812, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); @@ -1779,6 +2574,8 @@ sb_15_init(UNUSED(const device_t *info)) sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) @@ -1800,6 +2597,7 @@ sb_mcv_init(UNUSED(const device_t *info)) if (sb->opl_enabled) fm_driver_get(FM_YM3812, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); @@ -1807,6 +2605,8 @@ sb_mcv_init(UNUSED(const device_t *info)) sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); /* I/O handlers activated in sb_mcv_write */ @@ -1845,6 +2645,7 @@ sb_2_init(UNUSED(const device_t *info)) if (sb->opl_enabled) fm_driver_get(FM_YM3812, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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")); @@ -1888,6 +2689,8 @@ sb_2_init(UNUSED(const device_t *info)) } else sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); if (device_get_config_int("receive_input")) @@ -1937,6 +2740,7 @@ sb_pro_v1_init(UNUSED(const device_t *info)) sb->opl2.set_do_cycles(sb->opl2.priv, 0); } + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); @@ -1968,6 +2772,8 @@ sb_pro_v1_init(UNUSED(const device_t *info)) sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sbpro, sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); if (device_get_config_int("receive_input")) @@ -1993,6 +2799,7 @@ sb_pro_v2_init(UNUSED(const device_t *info)) if (sb->opl_enabled) fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); @@ -2020,6 +2827,8 @@ sb_pro_v2_init(UNUSED(const device_t *info)) sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sbpro, sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); if (device_get_config_int("receive_input")) @@ -2042,11 +2851,13 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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); + music_add_handler(sb_get_music_buffer_sbpro, sb); sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); /* I/O handlers activated in sb_pro_mcv_write */ @@ -2068,11 +2879,14 @@ sb_pro_compat_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sbpro, sb); sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); @@ -2085,16 +2899,17 @@ sb_pro_compat_init(UNUSED(const device_t *info)) static void * sb_16_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"); + sb_t *sb = malloc(sizeof(sb_t)); + const uint16_t addr = device_get_config_hex16("base"); + const 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) - fm_driver_get(info->local, &sb->opl); + fm_driver_get((int) (intptr_t) info->local, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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")); @@ -2124,6 +2939,8 @@ sb_16_init(UNUSED(const device_t *info)) 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); + if (sb->opl_enabled) + music_add_handler(sb_get_music_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); @@ -2141,6 +2958,7 @@ sb_16_init(UNUSED(const device_t *info)) sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); return sb; } @@ -2154,6 +2972,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_dsp_setdma16_enabled(&sb->dsp, 1); @@ -2162,6 +2981,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) sb->mixer_enabled = 1; sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); + music_add_handler(sb_get_music_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); @@ -2186,6 +3006,12 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) return sb; } +static int +sb_16_pnp_available(void) +{ + return rom_present(PNP_ROM_SB_16_PNP); +} + static void * sb_16_pnp_init(UNUSED(const device_t *info)) { @@ -2204,6 +3030,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) sb->mixer_enabled = 1; sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); + music_add_handler(sb_get_music_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); @@ -2219,9 +3046,21 @@ sb_16_pnp_init(UNUSED(const device_t *info)) sb->gameport = gameport_add(&gameport_pnp_device); device_add(&ide_qua_pnp_device); + other_ide_present++; - isapnp_add_card(sb_16_pnp_rom, sizeof(sb_16_pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb); + uint8_t *pnp_rom = NULL; + FILE *fp = rom_fopen(PNP_ROM_SB_16_PNP, "rb"); + if (fp) { + if (fread(sb->pnp_rom, 1, 390, fp) == 390) + pnp_rom = sb->pnp_rom; + fclose(fp); + } + + isapnp_add_card(pnp_rom, 390, sb_16_pnp_config_changed, + NULL, NULL, NULL, sb); + + sb_dsp_set_real_opl(&sb->dsp, 1); sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, 0); sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); @@ -2239,13 +3078,13 @@ sb_16_pnp_init(UNUSED(const device_t *info)) static int sb_vibra16xv_available(void) { - return rom_present("roms/sound/creative/CT4170 PnP.BIN"); + return rom_present(PNP_ROM_SB_VIBRA16XV); } static int sb_vibra16c_available(void) { - return rom_present("roms/sound/creative/CT4180 PnP.BIN"); + return rom_present(PNP_ROM_SB_VIBRA16C); } static void * @@ -2259,6 +3098,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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); @@ -2267,6 +3107,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) sb->mixer_enabled = 1; sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); + music_add_handler(sb_get_music_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); @@ -2284,11 +3125,11 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) const char *pnp_rom_file = NULL; switch (info->local) { case 0: - pnp_rom_file = "roms/sound/creative/CT4170 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_VIBRA16XV; break; case 1: - pnp_rom_file = "roms/sound/creative/CT4180 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_VIBRA16C; break; default: @@ -2308,7 +3149,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) switch (info->local) { case 0: case 1: - isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_vibra16_pnp_config_changed, + isapnp_add_card(pnp_rom, 512, sb_vibra16_pnp_config_changed, NULL, NULL, NULL, sb); break; @@ -2337,21 +3178,25 @@ sb_16_compat_init(const device_t *info) fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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->opl_enabled = 1; sb->mixer_enabled = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); + music_add_handler(sb_get_music_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); + mpu401_init(sb->mpu, 0, 0, M_UART, (int) (intptr_t) info->local); sb_dsp_set_mpu(&sb->dsp, sb->mpu); sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); return sb; } @@ -2359,37 +3204,37 @@ sb_16_compat_init(const device_t *info) static int sb_awe32_available(void) { - return rom_present("roms/sound/creative/awe32.raw"); + return rom_present(EMU8K_ROM_PATH); } static int sb_32_pnp_available(void) { - return sb_awe32_available() && rom_present("roms/sound/creative/CT3600 PnP.BIN"); + return sb_awe32_available() && rom_present(PNP_ROM_SB_32_PNP); } static int sb_awe32_pnp_available(void) { - return sb_awe32_available() && rom_present("roms/sound/creative/CT3980 PnP.BIN"); + return sb_awe32_available() && rom_present(PNP_ROM_SB_AWE32_PNP); } static int sb_awe64_value_available(void) { - return sb_awe32_available() && rom_present("roms/sound/creative/CT4520 PnP.BIN"); + return sb_awe32_available() && rom_present(PNP_ROM_SB_AWE64_VALUE); } static int sb_awe64_available(void) { - return sb_awe32_available() && rom_present("roms/sound/creative/CT4520 PnP.BIN"); + return sb_awe32_available() && rom_present(PNP_ROM_SB_AWE64); } static int sb_awe64_gold_available(void) { - return sb_awe32_available() && rom_present("roms/sound/creative/CT4540 PnP.BIN"); + return sb_awe32_available() && rom_present(PNP_ROM_SB_AWE64_GOLD); } static void * @@ -2407,6 +3252,7 @@ sb_awe32_init(UNUSED(const device_t *info)) if (sb->opl_enabled) fm_driver_get(FM_YMF262, &sb->opl); + sb_dsp_set_real_opl(&sb->dsp, 1); 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")); @@ -2436,6 +3282,9 @@ sb_awe32_init(UNUSED(const device_t *info)) 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); + if (sb->opl_enabled) + music_add_handler(sb_get_music_buffer_sb16_awe32, sb); + wavetable_add_handler(sb_get_wavetable_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); @@ -2455,6 +3304,7 @@ sb_awe32_init(UNUSED(const device_t *info)) sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); return sb; } @@ -2477,9 +3327,12 @@ sb_awe32_pnp_init(const device_t *info) sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); + sb_dsp_set_real_opl(&sb->dsp, 1); sb->mixer_enabled = 1; sb->mixer_sb16.output_filter = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); + music_add_handler(sb_get_music_buffer_sb16_awe32, sb); + wavetable_add_handler(sb_get_wavetable_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); @@ -2496,26 +3349,31 @@ sb_awe32_pnp_init(const device_t *info) sb->gameport = gameport_add(&gameport_pnp_device); - if ((info->local != 2) && (info->local != 3) && (info->local != 4)) + if ((info->local != 2) && (info->local != 4)) { device_add(&ide_qua_pnp_device); + other_ide_present++; + } const char *pnp_rom_file = NULL; switch (info->local) { case 0: - pnp_rom_file = "roms/sound/creative/CT3600 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_32_PNP; break; case 1: - pnp_rom_file = "roms/sound/creative/CT3980 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_AWE32_PNP; break; case 2: + pnp_rom_file = PNP_ROM_SB_AWE64_VALUE; + break; + case 3: - pnp_rom_file = "roms/sound/creative/CT4520 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_AWE64; break; case 4: - pnp_rom_file = "roms/sound/creative/CT4540 PnP.BIN"; + pnp_rom_file = PNP_ROM_SB_AWE64_GOLD; break; default: @@ -2541,8 +3399,11 @@ sb_awe32_pnp_init(const device_t *info) isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb); break; - case 2: case 3: + isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe64_pnp_config_changed, NULL, NULL, NULL, sb); + break; + + case 2: case 4: isapnp_add_card(pnp_rom, sizeof(sb->pnp_rom), sb_awe64_gold_pnp_config_changed, NULL, NULL, NULL, sb); break; @@ -2557,7 +3418,7 @@ sb_awe32_pnp_init(const device_t *info) sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); mpu401_change_addr(sb->mpu, 0); - if ((info->local != 2) && (info->local != 3) && (info->local != 4)) + if ((info->local != 2) && (info->local != 4)) ide_remove_handlers(3); emu8k_change_addr(&sb->emu8k, 0); @@ -2569,6 +3430,245 @@ sb_awe32_pnp_init(const device_t *info) return sb; } +static void * +ess_x688_init(UNUSED(const device_t *info)) +{ + sb_t *ess = calloc(sizeof(sb_t), 1); + const uint16_t addr = device_get_config_hex16("base"); + const uint16_t ide_ctrl = (const uint16_t) device_get_config_int("ide_ctrl"); + const uint16_t ide_base = ide_ctrl & 0x0fff; + const uint16_t ide_side = ide_base + 0x0206; + const uint16_t ide_irq = ide_ctrl >> 12; + + fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); + + sb_dsp_set_real_opl(&ess->dsp, 1); + sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_setaddr(&ess->dsp, addr); + sb_dsp_setirq(&ess->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma")); + sb_dsp_setdma16_8(&ess->dsp, device_get_config_int("dma")); + sb_dsp_setdma16_supported(&ess->dsp, 0); + ess_mixer_reset(ess); + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + { + io_sethandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + } + + ess->mixer_enabled = 1; + ess->mixer_ess.regs[0x40] = 0x0a; + io_sethandler(addr + 4, 0x0002, + ess_mixer_read, NULL, NULL, + ess_mixer_write, NULL, NULL, + ess); + sound_add_handler(sb_get_buffer_ess, ess); + music_add_handler(sb_get_music_buffer_ess, ess); + sound_set_cd_audio_filter(ess_filter_cd_audio, ess); + if (info->local && device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(ess_filter_pc_speaker, ess); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp); + + if (info->local) { + ess->mixer_ess.ess_id_str[0] = 0x16; + ess->mixer_ess.ess_id_str[1] = 0x88; + ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff; + ess->mixer_ess.ess_id_str[3] = addr & 0xff; + + ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); + /* NOTE: The MPU is initialized disabled and with no IRQ assigned. + * It will be later initialized by the guest OS's drivers. */ + mpu401_init(ess->mpu, 0, -1, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&ess->dsp, ess->mpu); + } + + ess->gameport = gameport_add(&gameport_pnp_device); + ess->gameport_addr = 0x200; + gameport_remap(ess->gameport, ess->gameport_addr); + + if (ide_base > 0x0000) { + device_add(&ide_qua_pnp_device); + ide_set_base(4, ide_base); + ide_set_side(4, ide_side); + ide_set_irq(4, ide_irq); + other_ide_present++; + } + + return ess; +} + +static int +ess_688_pnp_available(void) +{ + return rom_present(PNP_ROM_ESS0100); +} + +static int +ess_1688_pnp_available(void) +{ + return rom_present(PNP_ROM_ESS0102); +} + +static int +ess_1688_968_pnp_available(void) +{ + return rom_present(PNP_ROM_ESS0968); +} + +static void * +ess_x688_pnp_init(UNUSED(const device_t *info)) +{ + sb_t *ess = calloc(sizeof(sb_t), 1); + int len = 512; + + ess->pnp = 1 + (int) info->local; + + fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); + + sb_dsp_set_real_opl(&ess->dsp, 1); + sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_setdma16_supported(&ess->dsp, 0); + ess_mixer_reset(ess); + + ess->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_ess, ess); + music_add_handler(sb_get_music_buffer_ess, ess); + sound_set_cd_audio_filter(ess_filter_cd_audio, ess); + if (info->local && device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(ess_filter_pc_speaker, ess); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp); + + /* Not on ES688. */ + ess->mixer_ess.ess_id_str[0] = 0x16; + ess->mixer_ess.ess_id_str[1] = 0x88; + ess->mixer_ess.ess_id_str[2] = 0x00; + ess->mixer_ess.ess_id_str[3] = 0x00; + + ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); + /* NOTE: The MPU is initialized disabled and with no IRQ assigned. + * It will be later initialized by the guest OS's drivers. */ + mpu401_init(ess->mpu, 0, -1, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&ess->dsp, ess->mpu); + + ess->gameport = gameport_add(&gameport_pnp_device); + + device_add(&ide_qua_pnp_device); + other_ide_present++; + + const char *pnp_rom_file = NULL; + switch (info->local) { + case 0: + pnp_rom_file = PNP_ROM_ESS0100; + len = 145; + break; + + case 1: + pnp_rom_file = PNP_ROM_ESS0102; + len = 145; + break; + + case 2: + pnp_rom_file = PNP_ROM_ESS0968; + len = 135; + break; + + default: + break; + } + + uint8_t *pnp_rom = NULL; + if (pnp_rom_file) { + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + if (fp) { + if (fread(ess->pnp_rom, 1, len, fp) == len) + pnp_rom = ess->pnp_rom; + fclose(fp); + } + } + + isapnp_add_card(pnp_rom, len, ess_x688_pnp_config_changed, + NULL, NULL, NULL, ess); + + sb_dsp_setaddr(&ess->dsp, 0); + sb_dsp_setirq(&ess->dsp, 0); + sb_dsp_setdma8(&ess->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16_8(&ess->dsp, ISAPNP_DMA_DISABLED); + + mpu401_change_addr(ess->mpu, 0); + + ess->gameport_addr = 0; + gameport_remap(ess->gameport, 0); + + ide_remove_handlers(3); + + return ess; +} + +static void * +ess_x688_mca_init(UNUSED(const device_t *info)) +{ + sb_t *ess = calloc(1, sizeof(sb_t)); + + ess->opl_enabled = 1; + fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); + + sb_dsp_set_real_opl(&ess->dsp, 1); + sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_setdma16_supported(&ess->dsp, 0); + ess_mixer_reset(ess); + + ess->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_ess, ess); + music_add_handler(sb_get_music_buffer_ess, ess); + sound_set_cd_audio_filter(ess_filter_cd_audio, ess); + if (info->local && device_get_config_int("control_pc_speaker")) + sound_set_pc_speaker_filter(ess_filter_pc_speaker, ess); + + if (info->local) { + ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); + mpu401_init(ess->mpu, 0, -1, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&ess->dsp, ess->mpu); + } + + ess->gameport = gameport_add(&gameport_device); + + mpu401_change_addr(ess->mpu, 0); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp); + + ess->gameport_addr = 0; + gameport_remap(ess->gameport, 0); + + /* I/O handlers activated in sb_pro_mcv_write */ + if (info->local == 2) { + mca_add(ess_x688_mca_read, ess_chipchat_mca_write, sb_mcv_feedb, NULL, ess); + ess->pos_regs[0] = 0x50; + ess->pos_regs[1] = 0x51; + } else { + mca_add(ess_x688_mca_read, ess_soundpiper_mca_write, sb_mcv_feedb, NULL, ess); + ess->pos_regs[0] = 0x30; + ess->pos_regs[1] = 0x51; + } + + return ess; +} + void sb_close(void *priv) { @@ -3837,6 +4937,305 @@ static const device_config_t sb_awe64_gold_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; + +static const device_config_t ess_688_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { .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 = "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 = "ide_ctrl", + .description = "IDE Controller", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Disabled", + .value = 0x0000 + }, + { + .description = "0x170, IRQ 15", + .value = 0xf170 + }, + { + .description = "0x1E8, IRQ 11", + .value = 0xb1e8 + }, + { + .description = "0x168, IRQ 9", + .value = 0x9168 + }, + { + .description = "0x168, IRQ 10", + .value = 0xa168 + }, + { .description = "" } + } + }, + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +static const device_config_t ess_1688_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x220, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "0x220", + .value = 0x220 + }, + { + .description = "0x230", + .value = 0x230 + }, + { + .description = "0x240", + .value = 0x240 + }, + { + .description = "0x250", + .value = 0x250 + }, + { .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 = "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 = "ide_ctrl", + .description = "IDE Controller", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "Disabled", + .value = 0x0000 + }, + { + .description = "0x170, IRQ 15", + .value = 0xf170 + }, + { + .description = "0x1E8, IRQ 11", + .value = 0xb1e8 + }, + { + .description = "0x168, IRQ 9", + .value = 0x9168 + }, + { + .description = "0x168, IRQ 10", + .value = 0xa168 + }, + { .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 + +static const device_config_t ess_688_pnp_config[] = { + { + .name = "receive_input", + .description = "Receive input (SB MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +static const device_config_t ess_1688_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 } +}; // clang-format on const device_t sb_1_device = { @@ -4057,7 +5456,7 @@ const device_t sb_16_pnp_device = { .init = sb_16_pnp_init, .close = sb_close, .reset = NULL, - { .available = NULL }, + { .available = sb_16_pnp_available }, .speed_changed = sb_speed_changed, .force_redraw = NULL, .config = sb_16_pnp_config @@ -4174,3 +5573,117 @@ const device_t sb_awe64_gold_device = { .force_redraw = NULL, .config = sb_awe64_gold_config }; + +const device_t ess_688_device = { + .name = "ESS AudioDrive ES688", + .internal_name = "ess_es688", + .flags = DEVICE_ISA, + .local = 0, + .init = ess_x688_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_688_config +}; + +const device_t ess_ess0100_pnp_device = { + .name = "ESS AudioDrive ES688 (ESS0100) PnP", + .internal_name = "ess_ess0100_pnp", + .flags = DEVICE_ISA, + .local = 0, + .init = ess_x688_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = ess_688_pnp_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_688_pnp_config +}; + +const device_t ess_1688_device = { + .name = "ESS AudioDrive ES1688", + .internal_name = "ess_es1688", + .flags = DEVICE_ISA, + .local = 1, + .init = ess_x688_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_1688_config +}; + +const device_t ess_ess0102_pnp_device = { + .name = "ESS AudioDrive ES1688 (ESS0102) PnP", + .internal_name = "ess_ess0102_pnp", + .flags = DEVICE_ISA, + .local = 1, + .init = ess_x688_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = ess_1688_pnp_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_1688_pnp_config +}; + +const device_t ess_ess0968_pnp_device = { + .name = "ESS AudioDrive ES1688 (ESS0968) PnP", + .internal_name = "ess_ess0968_pnp", + .flags = DEVICE_ISA, + .local = 2, + .init = ess_x688_pnp_init, + .close = sb_close, + .reset = NULL, + { .available = ess_1688_968_pnp_available }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_1688_pnp_config +}; + +const device_t ess_soundpiper_16_mca_device = { + .name = "SoundPiper 16 (ESS AudioDrive ES688) MCA", + .internal_name = "soundpiper_16_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = ess_x688_mca_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_688_pnp_config +}; + +const device_t ess_soundpiper_32_mca_device = { + .name = "SoundPiper 32 (ESS AudioDrive ES1688) MCA", + .internal_name = "soundpiper_32_mca", + .flags = DEVICE_MCA, + .local = 1, + .init = ess_x688_mca_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_1688_pnp_config +}; + +const device_t ess_chipchat_16_mca_device = { + .name = "ChipChat 16 (ESS AudioDrive ES1688) MCA", + .internal_name = "chipchat_16_mca", + .flags = DEVICE_MCA, + .local = 2, + .init = ess_x688_mca_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = ess_1688_pnp_config +}; + + diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 6fc7815ab..e5c2359a0 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -6,6 +6,7 @@ #define _USE_MATH_DEFINES #include +#include #include #include #include @@ -28,40 +29,52 @@ #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +/* NON-PCM SAMPLE FORMATS */ #define ADPCM_4 1 #define ADPCM_26 2 #define ADPCM_2 3 +#define ESPCM_4 4 +#define ESPCM_3 5 +/* ESPCM_2? */ +#define ESPCM_1 7 +#define ESPCM_4E 8 /* For differentiating between 4-bit encoding and decoding modes. */ -/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ +/* 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 +enum { + DSP_S_NORMAL = 0, + DSP_S_RESET, + DSP_S_RESET_WAIT +}; + 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, 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, 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, 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 + 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."; @@ -69,33 +82,33 @@ uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0 /*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, @@ -103,19 +116,139 @@ 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, - 252, 4, 252, 4, 252, 4, 252, 4, - 252, 4, 252, 4, 252, 4, 252, 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[3][SB16_NCoef]; +// clang-format off +/* Upper half only used for ESPCM_3 mode. */ +/* TODO: Extract actual table (or exact ranges + range interpolation algo, whatever it is) from chip, someday, somehow. + * This current table is part software reverse engineering, part guesswork/extrapolation. + * It's close enough to what's in the chip to produce acceptable results, but not exact. + **/ +int8_t espcm_range_map[512] = { + -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, + -10, -8, -7, -5, -4, -3, -2, -1, 0, 2, 3, 4, 5, 6, 8, 9, + -12, -11, -9, -8, -6, -5, -3, -2, 0, 2, 3, 5, 6, 8, 10, 11, + -14, -12, -11, -9, -7, -5, -4, -2, 0, 2, 4, 5, 7, 9, 11, 13, + -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, + -21, -18, -16, -13, -11, -8, -6, -3, 0, 2, 5, 7, 10, 12, 15, 18, + -27, -24, -21, -17, -14, -11, -8, -4, 0, 3, 7, 10, 13, 17, 20, 24, + -35, -28, -24, -20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20, 24, 28, + -40, -35, -30, -25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, + -48, -42, -36, -30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30, 36, 43, + -56, -49, -42, -35, -28, -21, -14, -7, 0, 7, 14, 21, 28, 35, 42, 49, + -72, -63, -54, -45, -36, -27, -18, -9, 0, 9, 18, 27, 36, 45, 54, 63, + -85, -74, -64, -53, -43, -32, -22, -11, 0, 11, 22, 33, 43, 54, 64, 75, + -102, -98, -85, -71, -58, -45, -31, -14, 0, 13, 26, 39, 52, 65, 78, 90, + -127,-112, -96, -80, -64, -48, -32, -16, 0, 16, 32, 48, 64, 80, 96, 112, + -128,-127,-109, -91, -73, -54, -36, -18, 0, 18, 36, 54, 73, 91, 109, 127, + -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, + -10, -9, -8, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 6, 7, 8, + -13, -11, -9, -7, -6, -5, -3, -2, -1, 2, 3, 5, 6, 7, 9, 10, + -15, -13, -12, -10, -8, -6, -5, -3, -1, 2, 3, 5, 6, 8, 10, 12, + -18, -15, -13, -11, -9, -7, -5, -3, -1, 2, 3, 5, 7, 9, 11, 13, + -24, -20, -17, -15, -12, -10, -7, -5, -2, 2, 3, 6, 8, 11, 13, 16, + -29, -26, -23, -19, -16, -13, -10, -6, -2, 2, 5, 8, 11, 15, 18, 22, + -34, -30, -26, -22, -18, -14, -10, -6, -2, 2, 6, 10, 14, 18, 22, 26, + -43, -38, -33, -28, -23, -18, -13, -8, -3, 2, 7, 12, 17, 22, 27, 32, + -51, -45, -39, -33, -27, -21, -15, -9, -3, 3, 9, 15, 21, 27, 33, 39, + -60, -53, -46, -39, -32, -25, -18, -11, -4, 3, 10, 17, 24, 31, 38, 45, + -77, -68, -59, -50, -41, -32, -23, -14, -5, 4, 13, 22, 31, 40, 49, 58, + -90, -80, -69, -59, -48, -38, -27, -17, -6, 5, 16, 27, 38, 48, 59, 69, + -112,-104, -91, -78, -65, -52, -38, -23, -7, 6, 19, 32, 45, 58, 71, 84, + -128,-120,-104, -88, -72, -56, -40, -24, -8, 8, 24, 40, 56, 72, 88, 104, + -128,-128,-118,-100, -82, -64, -45, -27, -9, 9, 27, 45, 63, 82, 100, 118 +}; + +/* address = table_index(9:8) | dsp->espcm_last_value(7:3) | codeword(2:0) + * the value is a base index into espcm_range_map with bits at (8, 3:0), + * to be OR'ed with dsp->espcm_range at (7:4) + */ +uint16_t espcm3_dpcm_tables[1024] = +{ + /* Table 0 */ + 256, 257, 258, 259, 260, 263, 266, 269, 0, 257, 258, 259, 260, 263, 266, 269, + 0, 1, 258, 259, 260, 263, 266, 269, 1, 2, 259, 260, 261, 263, 266, 269, + 1, 3, 260, 261, 262, 264, 266, 269, 1, 3, 4, 261, 262, 264, 266, 269, + 2, 4, 5, 262, 263, 264, 266, 269, 2, 4, 6, 263, 264, 265, 267, 269, + 2, 4, 6, 7, 264, 265, 267, 269, 2, 5, 7, 8, 265, 266, 267, 269, + 2, 5, 7, 8, 9, 266, 268, 270, 2, 5, 7, 9, 10, 267, 268, 270, + 2, 5, 8, 10, 11, 268, 269, 270, 2, 5, 8, 11, 12, 269, 270, 271, + 2, 5, 8, 11, 12, 13, 270, 271, 2, 5, 8, 11, 12, 13, 14, 271, + 0, 257, 258, 259, 260, 263, 266, 269, 0, 1, 258, 259, 260, 263, 266, 269, + 0, 1, 2, 259, 260, 263, 266, 269, 1, 2, 3, 260, 261, 263, 266, 269, + 1, 3, 4, 261, 262, 264, 266, 269, 1, 3, 5, 262, 263, 264, 266, 269, + 2, 4, 5, 6, 263, 264, 266, 269, 2, 4, 6, 7, 264, 265, 267, 269, + 2, 4, 6, 7, 8, 265, 267, 269, 2, 5, 7, 8, 9, 266, 267, 269, + 2, 5, 7, 9, 10, 267, 268, 270, 2, 5, 7, 9, 10, 11, 268, 270, + 2, 5, 8, 10, 11, 12, 269, 270, 2, 5, 8, 11, 12, 13, 270, 271, + 2, 5, 8, 11, 12, 13, 14, 271, 2, 5, 8, 11, 12, 13, 14, 15, + /* Table 1 */ + 257, 260, 262, 263, 264, 265, 267, 270, 257, 260, 262, 263, 264, 265, 267, 270, + 1, 260, 262, 263, 264, 265, 267, 270, 1, 260, 262, 263, 264, 265, 267, 270, + 1, 260, 262, 263, 264, 265, 267, 270, 1, 4, 262, 263, 264, 265, 267, 270, + 1, 4, 262, 263, 264, 265, 267, 270, 1, 4, 6, 263, 264, 265, 267, 270, + 1, 4, 6, 7, 264, 265, 267, 270, 1, 4, 6, 7, 8, 265, 267, 270, + 1, 4, 6, 7, 8, 9, 267, 270, 1, 4, 6, 7, 8, 9, 267, 270, + 1, 4, 6, 7, 8, 9, 11, 270, 1, 4, 6, 7, 8, 9, 11, 270, + 1, 4, 6, 7, 8, 9, 11, 270, 1, 4, 6, 7, 8, 9, 11, 14, + 257, 260, 262, 263, 264, 265, 267, 270, 1, 260, 262, 263, 264, 265, 267, 270, + 1, 260, 262, 263, 264, 265, 267, 270, 1, 260, 262, 263, 264, 265, 267, 270, + 1, 4, 262, 263, 264, 265, 267, 270, 1, 4, 262, 263, 264, 265, 267, 270, + 1, 4, 6, 263, 264, 265, 267, 270, 1, 4, 6, 7, 264, 265, 267, 270, + 1, 4, 6, 7, 8, 265, 267, 270, 1, 4, 6, 7, 8, 9, 267, 270, + 1, 4, 6, 7, 8, 9, 267, 270, 1, 4, 6, 7, 8, 9, 11, 270, + 1, 4, 6, 7, 8, 9, 11, 270, 1, 4, 6, 7, 8, 9, 11, 270, + 1, 4, 6, 7, 8, 9, 11, 14, 1, 4, 6, 7, 8, 9, 11, 14, + /* Table 2 */ + 256, 257, 258, 259, 260, 262, 265, 268, 0, 257, 258, 259, 260, 262, 265, 268, + 0, 1, 258, 259, 260, 262, 265, 269, 1, 2, 259, 260, 261, 263, 265, 269, + 1, 3, 260, 261, 262, 263, 265, 269, 1, 3, 4, 261, 262, 263, 265, 269, + 1, 3, 5, 262, 263, 264, 266, 269, 1, 4, 5, 6, 263, 264, 266, 269, + 1, 4, 6, 7, 264, 265, 266, 269, 1, 4, 6, 7, 8, 265, 266, 269, + 2, 4, 6, 7, 8, 9, 267, 269, 2, 4, 6, 7, 8, 9, 267, 269, + 2, 5, 7, 8, 9, 10, 11, 270, 2, 5, 7, 8, 9, 10, 11, 270, + 2, 5, 8, 9, 10, 11, 12, 270, 2, 6, 8, 10, 11, 12, 13, 14, + 257, 258, 259, 260, 261, 263, 265, 269, 1, 259, 260, 261, 262, 263, 266, 269, + 1, 260, 261, 262, 263, 264, 266, 269, 1, 260, 261, 262, 263, 264, 266, 269, + 2, 4, 262, 263, 264, 265, 267, 269, 2, 4, 262, 263, 264, 265, 267, 269, + 2, 5, 6, 263, 264, 265, 267, 270, 2, 5, 6, 7, 264, 265, 267, 270, + 2, 5, 7, 8, 265, 266, 267, 270, 2, 5, 7, 8, 9, 266, 268, 270, + 2, 6, 8, 9, 10, 267, 268, 270, 2, 6, 8, 9, 10, 11, 268, 270, + 2, 6, 8, 10, 11, 12, 269, 270, 2, 6, 9, 11, 12, 13, 270, 271, + 3, 6, 9, 11, 12, 13, 14, 271, 3, 6, 9, 11, 12, 13, 14, 15, + /* Table 3 */ + 256, 258, 260, 261, 262, 263, 264, 265, 0, 258, 260, 261, 262, 263, 264, 265, + 1, 259, 260, 261, 262, 263, 264, 266, 1, 259, 260, 261, 262, 263, 264, 266, + 1, 3, 260, 261, 262, 263, 264, 266, 1, 3, 4, 261, 262, 263, 264, 267, + 1, 3, 4, 5, 262, 263, 264, 267, 1, 3, 4, 5, 6, 263, 264, 267, + 1, 3, 5, 6, 7, 264, 265, 268, 1, 3, 5, 6, 7, 8, 265, 268, + 1, 4, 6, 7, 8, 9, 266, 269, 1, 4, 6, 7, 8, 9, 10, 269, + 1, 4, 6, 7, 8, 9, 10, 269, 1, 4, 6, 7, 8, 9, 11, 270, + 1, 4, 6, 7, 8, 9, 11, 270, 1, 4, 6, 7, 8, 9, 11, 14, + 257, 260, 262, 263, 264, 265, 267, 270, 1, 260, 262, 263, 264, 265, 267, 270, + 1, 260, 262, 263, 264, 265, 267, 270, 2, 261, 262, 263, 264, 265, 267, 270, + 2, 261, 262, 263, 264, 265, 267, 270, 2, 5, 262, 263, 264, 265, 267, 270, + 3, 6, 263, 264, 265, 266, 268, 270, 3, 6, 7, 264, 265, 266, 268, 270, + 4, 7, 8, 265, 266, 267, 268, 270, 4, 7, 8, 9, 266, 267, 268, 270, + 4, 7, 8, 9, 10, 267, 268, 270, 5, 7, 8, 9, 10, 11, 268, 270, + 5, 7, 8, 9, 10, 11, 12, 270, 5, 7, 8, 9, 10, 11, 12, 270, + 6, 7, 8, 9, 10, 11, 13, 271, 6, 7, 8, 9, 10, 11, 13, 15 +}; +// clang-format on + +double low_fir_sb16_coef[5][SB16_NCoef]; #ifdef ENABLE_SB_DSP_LOG int sb_dsp_do_log = ENABLE_SB_DSP_LOG; @@ -135,6 +268,8 @@ sb_dsp_log(const char *fmt, ...) # define sb_dsp_log(fmt, ...) #endif +#define ESSreg(reg) (dsp)->ess_regs[reg - 0xA0] + static __inline double sinc(double x) { @@ -142,20 +277,18 @@ sinc(double x) } static void -recalc_sb16_filter(int c, int playback_freq) +recalc_sb16_filter(const int c, const int playback_freq) { /* Cutoff frequency = playback / 2 */ - int n; - double w; - double h; - double fC = ((double) playback_freq) / (double) FREQ_96000; - double gain; + int n; + const double fC = ((double) playback_freq) / (double) FREQ_96000; 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))); + const double 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))); + const double 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; @@ -163,7 +296,7 @@ recalc_sb16_filter(int c, int playback_freq) low_fir_sb16_coef[c][(SB16_NCoef - 1) / 2] = 1.0; - gain = 0.0; + double gain = 0.0; for (n = 0; n < SB16_NCoef; n++) gain += low_fir_sb16_coef[c][n]; @@ -173,7 +306,36 @@ recalc_sb16_filter(int c, int playback_freq) } static void -sb_irq_update_pic(void *priv, int set) +recalc_opl_filter(const int playback_freq) +{ + /* Cutoff frequency = playback / 2 */ + int n; + const double fC = ((double) playback_freq) / (double) (FREQ_49716 * 2); + + for (n = 0; n < SB16_NCoef; n++) { + /* Blackman window */ + const double 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 */ + const double h = sinc(2.0 * fC * ((double) n - ((double) (SB16_NCoef - 1) / 2.0))); + + /* Create windowed-sinc filter */ + low_fir_sb16_coef[1][n] = w * h; + } + + low_fir_sb16_coef[1][(SB16_NCoef - 1) / 2] = 1.0; + + double gain = 0.0; + for (n = 0; n < SB16_NCoef; n++) + gain += low_fir_sb16_coef[1][n]; + + /* Normalise filter, to produce unity gain */ + for (n = 0; n < SB16_NCoef; n++) + low_fir_sb16_coef[1][n] /= gain; +} + +static void +sb_irq_update_pic(void *priv, const int set) { const sb_dsp_t *dsp = (sb_dsp_t *) priv; if (set) @@ -206,6 +368,14 @@ sb_update_status(sb_dsp_t *dsp, int bit, int set) { int masked = 0; + if (dsp->sb_irq8 || dsp->sb_irq16) + return; + + /* NOTE: not on ES1688 or ES1868 */ + if (IS_ESS(dsp) && (dsp->sb_subtype != SB_SUBTYPE_ESS_ES1688) && !(ESSreg(0xB1) & 0x10)) + /* If ESS playback, and IRQ disabled, do not fire. */ + return; + switch (bit) { default: case 0: @@ -222,6 +392,17 @@ sb_update_status(sb_dsp_t *dsp, int bit, int set) break; } + /* NOTE: not on ES1688, apparently; investigate on ES1868 */ + if (IS_ESS(dsp) && (dsp->sb_subtype > SB_SUBTYPE_ESS_ES1688)) { + /* TODO: Investigate real hardware for this (the ES1887 datasheet documents this bit somewhat oddly.) */ + if (dsp->ess_playback_mode && bit <= 1 && set && !masked) { + if (!(ESSreg(0xB1) & 0x40)) // if ESS playback, and IRQ disabled, do not fire + { + return; + } + } + } + if (set && !masked) dsp->irq_update(dsp->irq_priv, 1); else if (!set) @@ -241,7 +422,7 @@ sb_irqc(sb_dsp_t *dsp, int irq8) } static void -sb_dsp_irq_update(void *priv, int set) +sb_dsp_irq_update(void *priv, const int set) { sb_dsp_t *dsp = (sb_dsp_t *) priv; @@ -321,20 +502,23 @@ sb_doreset(sb_dsp_t *dsp) dsp->sb_asp_regs[5] = 0x01; dsp->sb_asp_regs[9] = 0xf8; + + /* Initialize ESS registers */ + ESSreg(0xA5) = 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 = (double) (TIMER_USEC * (256 - dsp->sb_timeo)); else - dsp->sblatcho = (uint64_t) (TIMER_USEC * (1000000.0f / (float) (dsp->sb_timeo - 256))); + dsp->sblatcho = ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_timeo - 256))); if (dsp->sb_timei < 256) - dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei); + dsp->sblatchi = (double) (TIMER_USEC * (256 - dsp->sb_timei)); else - dsp->sblatchi = (uint64_t) (TIMER_USEC * (1000000.0f / (float) (dsp->sb_timei - 256))); + dsp->sblatchi = ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_timei - 256))); } void @@ -344,6 +528,21 @@ sb_add_data(sb_dsp_t *dsp, uint8_t v) dsp->sb_read_wp &= 0xff; } +static unsigned int +sb_ess_get_dma_counter(const sb_dsp_t *dsp) +{ + unsigned int c = (unsigned int) ESSreg(0xA5) << 8U; + c |= (unsigned int) ESSreg(0xA4); + + return c; +} + +static unsigned int +sb_ess_get_dma_len(const sb_dsp_t *dsp) +{ + return 0x10000U - sb_ess_get_dma_counter(dsp); +} + void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { @@ -355,14 +554,17 @@ sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) dsp->sb_8_autoinit = autoinit; dsp->sb_8_pause = 0; dsp->sb_8_enable = 1; + dsp->dma_ff = 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); + timer_set_delay_u64(&dsp->output_timer, (uint64_t) dsp->sblatcho); dsp->sbleftright = dsp->sbleftright_default; dsp->sbdacpos = 0; + + dma_set_drq(dsp->sb_8_dmanum, 1); } else { dsp->sb_16_length = dsp->sb_16_origlength = len; dsp->sb_16_format = format; @@ -373,8 +575,16 @@ sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) 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); + timer_set_delay_u64(&dsp->output_timer, (uint64_t) dsp->sblatcho); + + if (dsp->sb_16_dma_supported) + dma_set_drq(dsp->sb_16_dmanum, 1); + else + dma_set_drq(dsp->sb_16_8_dmanum, 1); } + + /* This will be set later for ESS playback/record modes. */ + dsp->ess_playback_mode = 0; } void @@ -390,7 +600,9 @@ sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) 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); + timer_set_delay_u64(&dsp->input_timer, (uint64_t) dsp->sblatchi); + + dma_set_drq(dsp->sb_8_dmanum, 1); } else { dsp->sb_16_length = dsp->sb_16_origlength = len; dsp->sb_16_format = format; @@ -401,18 +613,90 @@ sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) 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); + timer_set_delay_u64(&dsp->input_timer, (uint64_t) dsp->sblatchi); + + if (dsp->sb_16_dma_supported) + dma_set_drq(dsp->sb_16_dmanum, 1); + else + dma_set_drq(dsp->sb_16_8_dmanum, 1); } memset(dsp->record_buffer, 0, sizeof(dsp->record_buffer)); } +void +sb_start_dma_ess(sb_dsp_t *dsp) +{ + uint8_t real_format = 0; + dsp->ess_dma_counter = sb_ess_get_dma_counter(dsp); + uint32_t len = sb_ess_get_dma_len(dsp); + + if (IS_ESS(dsp)) { + dma_set_drq(dsp->sb_8_dmanum, 0); + dma_set_drq(dsp->sb_16_8_dmanum, 0); + } + real_format |= !!(ESSreg(0xB7) & 0x20) ? 0x10 : 0; + real_format |= !!(ESSreg(0xB7) & 0x8) ? 0x20 : 0; + if (!!(ESSreg(0xB8) & 8)) + sb_start_dma_i(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, (int) len); + else + sb_start_dma(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, (int) len); + dsp->ess_playback_mode = 1; + dma_set_drq(dsp->sb_8_dmanum, 1); + dma_set_drq(dsp->sb_16_8_dmanum, 1); +} + +void +sb_stop_dma_ess(sb_dsp_t *dsp) +{ + dsp->sb_8_enable = dsp->sb_16_enable = 0; + dma_set_drq(dsp->sb_16_8_dmanum, 0); + dma_set_drq(dsp->sb_8_dmanum, 0); +} + +static void +sb_ess_update_dma_status(sb_dsp_t *dsp) +{ + bool dma_en = (ESSreg(0xB8) & 1) ? true : false; + + /* If the DRQ is disabled, do not start. */ + if (!(ESSreg(0xB2) & 0x40)) + dma_en = false; + + if (dma_en) { + if (!dsp->sb_8_enable && !dsp->sb_16_enable) + sb_start_dma_ess(dsp); + } else { + if (dsp->sb_8_enable || dsp->sb_16_enable) + sb_stop_dma_ess(dsp); + } +} + int sb_8_read_dma(void *priv) { - const sb_dsp_t *dsp = (sb_dsp_t *) priv; + sb_dsp_t *dsp = (sb_dsp_t *) priv; + int ret; - return dma_channel_read(dsp->sb_8_dmanum); + if (dsp->sb_8_dmanum >= 4) { + if (dsp->dma_ff) { + uint32_t temp = (dsp->dma_data & 0xff00) >> 8; + temp |= (dsp->dma_data & 0xffff0000); + ret = (int) temp; + } else { + dsp->dma_data = dma_channel_read(dsp->sb_8_dmanum); + + if (dsp->dma_data == DMA_NODATA) + return DMA_NODATA; + + ret = dsp->dma_data & 0xff; + } + + dsp->dma_ff = !dsp->dma_ff; + } else + ret = dma_channel_read(dsp->sb_8_dmanum); + + return ret; } int @@ -439,8 +723,9 @@ 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; + + int ret; + 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_read(dma_ch); @@ -448,22 +733,21 @@ sb_16_read_dma(void *priv) 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; + 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; + int 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; + const int dma_flags = temp & DMA_OVER; temp &= ~DMA_OVER; ret |= (temp << 8) | dma_flags; - } + } } } @@ -474,36 +758,92 @@ int sb_16_write_dma(void *priv, uint16_t val) { const sb_dsp_t *dsp = (sb_dsp_t *) priv; - int temp, ret = 0; int dma_ch = dsp->sb_16_dmanum; - + int ret; + 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; + 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; + int 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; + ret = temp; } } return ret; } +void +sb_ess_update_irq_drq_readback_regs(sb_dsp_t *dsp, bool legacy) +{ + sb_t *ess = (sb_t *) dsp->parent; + ess_mixer_t *mixer = &ess->mixer_ess; + uint8_t t = 0x00; + + /* IRQ control */ + if (legacy) { + t |= 0x80; + } + switch (dsp->sb_irqnum) { + default: + break; + case 2: + case 9: + t |= 0x0; + break; + case 5: + t |= 0x5; + break; + case 7: + t |= 0xA; + break; + case 10: + t |= 0xF; + break; + } + ESSreg(0xB1) = (ESSreg(0xB1) & 0xF0) | t; + if ((mixer != NULL) && (ess->mpu != NULL) && (((mixer->regs[0x40] >> 5) & 0x7) == 2)) + mpu401_setirq(ess->mpu, ess->dsp.sb_irqnum); + + /* DRQ control */ + t = 0x00; + if (legacy) { + t |= 0x80; + } + switch (dsp->sb_8_dmanum) { + default: + break; + case 0: + t |= 0x5; + break; + case 1: + t |= 0xA; + break; + case 3: + t |= 0xF; + break; + } + ESSreg(0xB2) = (ESSreg(0xB2) & 0xF0) | t; +} + void sb_dsp_setirq(sb_dsp_t *dsp, int irq) { sb_dsp_log("IRQ now: %i\n", irq); dsp->sb_irqnum = irq; + + sb_ess_update_irq_drq_readback_regs(dsp, true); + + ESSreg(0xB1) = (ESSreg(0xB1) & 0xEF) | 0x10; } void @@ -511,6 +851,8 @@ sb_dsp_setdma8(sb_dsp_t *dsp, int dma) { sb_dsp_log("8-bit DMA now: %i\n", dma); dsp->sb_8_dmanum = dma; + + sb_ess_update_irq_drq_readback_regs(dsp, true); } void @@ -542,12 +884,233 @@ sb_dsp_setdma16_supported(sb_dsp_t *dsp, int supported) } void -sb_dsp_setdma16_translate(sb_dsp_t *dsp, int translate) +sb_dsp_setdma16_translate(sb_dsp_t *dsp, const int translate) { sb_dsp_log("16-bit to 8-bit translation now: %sabled\n", translate ? "en" : "dis"); dsp->sb_16_dma_translate = translate; } +static void +sb_ess_update_reg_a2(sb_dsp_t *dsp, const uint8_t val) +{ + const double freq = (7160000.0 / (256.0 - ((double) val))) * 41.0; + const int temp = (int) freq; + ESSreg(0xA2) = val; + + if (dsp->sb_freq != temp) + recalc_sb16_filter(0, temp); + dsp->sb_freq = temp; +} + +/* TODO: Investigate ESS cards' filtering on real hardware as well. + (DOSBox-X did it purely off some laptop's ESS chip, which isn't a good look.) */ +static void +sb_ess_update_filter_freq(sb_dsp_t *dsp) +{ + const double temp = (7160000.0 / (((((double) dsp->sb_freq) / 2.0) * 0.80) * 82.0)) - 256.0; + + if (dsp->sb_freq >= 22050) + ESSreg(0xA1) = 256 - (795500UL / dsp->sb_freq); + else + ESSreg(0xA1) = 128 - (397700UL / dsp->sb_freq); + + sb_ess_update_reg_a2(dsp, (uint8_t) temp); +} + +static uint8_t +sb_ess_read_reg(const sb_dsp_t *dsp, const uint8_t reg) +{ + return ESSreg(reg); +} + +static void +sb_ess_update_autolen(sb_dsp_t *dsp) +{ + dsp->sb_8_autolen = dsp->sb_16_autolen = (int) sb_ess_get_dma_len(dsp); +} + +static void +sb_ess_write_reg(sb_dsp_t *dsp, const uint8_t reg, uint8_t data) +{ + uint8_t chg; + + switch (reg) { + case 0xA1: /* Extended Mode Sample Rate Generator */ + { + ESSreg(reg) = data; + if (data & 0x80) + dsp->sb_freq = (int) (795500UL / (256ul - data)); + else + dsp->sb_freq = (int) (397700UL / (128ul - data)); + const double temp = 1000000.0 / dsp->sb_freq; + dsp->sblatchi = dsp->sblatcho = ((double) TIMER_USEC * temp); + + dsp->sb_timei = dsp->sb_timeo; + break; + } + case 0xA2: /* Filter divider (effectively, a hardware lowpass filter under S/W control) */ + sb_ess_update_reg_a2(dsp, data); + break; + + case 0xA4: /* DMA Transfer Count Reload (low) */ + case 0xA5: /* DMA Transfer Count Reload (high) */ + ESSreg(reg) = data; + sb_ess_update_autolen(dsp); + if ((dsp->sb_16_length < 0 && !dsp->sb_16_enable) && (dsp->sb_8_length < 0 && !dsp->sb_8_enable)) + dsp->ess_reload_len = 1; + break; + + case 0xA8: /* Analog Control */ + /* bits 7:5 0 Reserved. Always write 0 + * bit 4 1 Reserved. Always write 1 + * bit 3 Record monitor 1=Enable record monitor + * enable + * bit 2 0 Reserved. Always write 0 + * bits 1:0 Stereo/mono select 00=Reserved + * 01=Stereo + * 10=Mono + * 11=Reserved */ + chg = ESSreg(reg) ^ data; + ESSreg(reg) = data; + if (chg & 0x3) { + if (dsp->sb_16_enable || dsp->sb_8_enable) { + uint8_t real_format = 0x00; + real_format |= !!(ESSreg(0xB7) & 0x20) ? 0x10 : 0; + real_format |= !!(ESSreg(0xB7) & 0x8) ? 0x20 : 0; + + if (dsp->sb_16_enable) + dsp->sb_16_format = real_format; + + if (dsp->sb_8_enable) + dsp->sb_8_format = real_format; + } + } + break; + + case 0xB1: /* Legacy Audio Interrupt Control */ + ESSreg(reg) = (ESSreg(reg) & 0x0F) + (data & 0xF0); // lower 4 bits not writeable + switch (data & 0x0C) { + default: + break; + case 0x00: + dsp->sb_irqnum = 2; + break; + case 0x04: + dsp->sb_irqnum = 5; + break; + case 0x08: + dsp->sb_irqnum = 7; + break; + case 0x0C: + dsp->sb_irqnum = 10; + break; + } + sb_ess_update_irq_drq_readback_regs(dsp, false); + break; + case 0xB2: /* DRQ Control */ + chg = ESSreg(reg) ^ data; + ESSreg(reg) = (ESSreg(reg) & 0x0F) + (data & 0xF0); // lower 4 bits not writeable + switch (data & 0x0C) { + default: + break; + case 0x00: + dsp->sb_8_dmanum = -1; + break; + case 0x04: + dsp->sb_8_dmanum = 0; + break; + case 0x08: + dsp->sb_8_dmanum = 1; + break; + case 0x0C: + dsp->sb_8_dmanum = 3; + break; + } + sb_ess_update_irq_drq_readback_regs(dsp, false); + if (chg & 0x40) + sb_ess_update_dma_status(dsp); + break; + case 0xB5: /* DAC Direct Access Holding (low) */ + case 0xB6: /* DAC Direct Access Holding (high) */ + ESSreg(reg) = data; + break; + + case 0xB7: /* Audio 1 Control 1 */ + /* bit 7 Enable FIFO to/from codec + * bit 6 Opposite from bit 3 Must be set opposite to bit 3 + * bit 5 FIFO signed mode 1=Data is signed twos-complement 0=Data is unsigned + * bit 4 Reserved Always write 1 + * bit 3 FIFO stereo mode 1=Data is stereo + * bit 2 FIFO 16-bit mode 1=Data is 16-bit + * bit 1 Reserved Always write 0 + * bit 0 Generate load signal */ + chg = ESSreg(reg) ^ data; + ESSreg(reg) = data; + + if (chg & 4) + sb_ess_update_autolen(dsp); + + if (chg & 0x0C) { + if (dsp->sb_16_enable || dsp->sb_8_enable) { + sb_stop_dma_ess(dsp); + sb_start_dma_ess(dsp); + } + } + break; + + case 0xB8: /* Audio 1 Control 2 */ + /* bits 7:4 reserved + * bit 3 CODEC mode 1=first DMA converter in ADC mode + * 0=first DMA converter in DAC mode + * bit 2 DMA mode 1=auto-initialize mode + * 0=normal DMA mode + * bit 1 DMA read enable 1=first DMA is read (for ADC) + * 0=first DMA is write (for DAC) + * bit 0 DMA xfer enable 1=DMA is allowed to proceed */ + data &= 0xF; + chg = ESSreg(reg) ^ data; + ESSreg(reg) = data; + + if (chg & 1) { + if (dsp->sb_16_enable || dsp->sb_8_enable) { + if (dsp->sb_16_enable) + dsp->sb_16_length = (int) sb_ess_get_dma_len(dsp); + if (dsp->sb_8_enable) + dsp->sb_8_length = (int) sb_ess_get_dma_len(dsp); + } else + dsp->ess_reload_len = 1; + } + + if (chg & 0x4) { + if (dsp->sb_16_enable) { + dsp->sb_16_autoinit = (ESSreg(0xB8) & 0x4) != 0; + } + if (dsp->sb_8_enable) { + dsp->sb_8_autoinit = (ESSreg(0xB8) & 0x4) != 0; + } + } + + if (chg & 0xB) { + if (chg & 0xA) + sb_stop_dma_ess(dsp); /* changing capture/playback direction? stop DMA to reinit */ + sb_ess_update_dma_status(dsp); + } + break; + + case 0xB9: /* Audio 1 Transfer Type */ + case 0xBA: /* Left Channel ADC Offset Adjust */ + case 0xBB: /* Right Channel ADC Offset Adjust */ + case 0xC3: /* Internal state register */ + case 0xCF: /* GPO0/1 power management register */ + ESSreg(reg) = data; + break; + + default: + sb_dsp_log("UNKNOWN ESS register write reg=%02xh val=%02xh\n", reg, data); + break; + } +} + void sb_exec_command(sb_dsp_t *dsp) { @@ -558,8 +1121,29 @@ sb_exec_command(sb_dsp_t *dsp) /* Update 8051 ram with the current DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16) { dsp->sb_8051_ram[0x20] = dsp->sb_command; + } + + if (IS_ESS(dsp) && dsp->sb_command >= 0xA0 && dsp->sb_command <= 0xCF) { + if (dsp->sb_command == 0xC6 || dsp->sb_command == 0xC7) { + dsp->ess_extended_mode = !!(dsp->sb_command == 0xC6); + return; + } else if (dsp->sb_command == 0xC2) { + sb_ess_write_reg(dsp, 0xC3, dsp->sb_data[0]); + } else if (dsp->sb_command == 0xC3) { + sb_add_data(dsp, sb_ess_read_reg(dsp, 0xC3)); + } else if (dsp->sb_command == 0xCE) { + sb_add_data(dsp, sb_ess_read_reg(dsp, 0xCF)); + } else if (dsp->sb_command == 0xCF) { + sb_ess_write_reg(dsp, 0xCF, dsp->sb_data[0]); + } else if (dsp->sb_command == 0xC0) { + sb_add_data(dsp, sb_ess_read_reg(dsp, dsp->sb_data[0])); + } else if (dsp->sb_command < 0xC0 && dsp->ess_extended_mode) { + sb_ess_write_reg(dsp, dsp->sb_command, dsp->sb_data[0]); + } + return; + } switch (dsp->sb_command) { case 0x01: /* ???? */ @@ -579,8 +1163,9 @@ sb_exec_command(sb_dsp_t *dsp) } /* else DSP Status (Obsolete) */ break; case 0x05: /* ASP set codec parameter */ - if (dsp->sb_type >= SB16) + 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; @@ -666,7 +1251,10 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0x10: /* 8-bit direct mode */ sb_dsp_update(dsp); - dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8; + dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (int16_t) ((dsp->sb_data[0] ^ 0x80) << 8); + // FIXME: What does the ESS AudioDrive do to its filter/sample rate divider registers when emulating this Sound Blaster command? + ESSreg(0xA1) = 128 - (397700 / 22050); + ESSreg(0xA2) = 256 - (7160000 / (82 * ((4 * 22050) / 10))); 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)); @@ -679,8 +1267,11 @@ sb_exec_command(sb_dsp_t *dsp) 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->ess_dma_counter++; + if (dsp->sb_command == 0x17) { dsp->sb_8_length--; + dsp->ess_dma_counter++; + } break; case 0x1C: /* 8-bit autoinit DMA output */ if (dsp->sb_type >= SB15) @@ -691,6 +1282,7 @@ sb_exec_command(sb_dsp_t *dsp) 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--; + dsp->ess_dma_counter++; } break; case 0x20: /* 8-bit direct input */ @@ -699,10 +1291,10 @@ sb_exec_command(sb_dsp_t *dsp) 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; + dsp->sblatchi = (double) ((double) TIMER_USEC * 22.0); temp = 1000000 / 22; dsp->sb_freq = temp; - timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi); + timer_set_delay_u64(&dsp->input_timer, (uint64_t) dsp->sblatchi); } break; case 0x24: /* 8-bit single cycle DMA input */ @@ -725,7 +1317,6 @@ sb_exec_command(sb_dsp_t *dsp) dsp->uart_irq = 1; break; case 0x32: /* MIDI Read Timestamp Poll */ - break; case 0x33: /* MIDI Read Timestamp Interrupt */ break; case 0x34: /* MIDI In poll */ @@ -752,37 +1343,83 @@ sb_exec_command(sb_dsp_t *dsp) 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]); + dsp->sblatcho = dsp->sblatchi = (double) (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); + sb_dsp_log("Sample rate - %ihz (%f)\n", temp, dsp->sblatcho); if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) recalc_sb16_filter(0, temp); dsp->sb_freq = temp; + if (IS_ESS(dsp)) { + sb_ess_update_filter_freq(dsp); + } 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); + dsp->sblatcho = (double) ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); + sb_dsp_log("Sample rate - %ihz (%f)\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->sb_timeo = 256 + dsp->sb_freq; dsp->sblatchi = dsp->sblatcho; dsp->sb_timei = dsp->sb_timeo; - if (dsp->sb_freq != temp && dsp->sb_type >= SB16) + if (dsp->sb_freq != temp) 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 0x65: /* 4-bit ESPCM output with reference */ + case 0x64: /* 4-bit ESPCM output */ + if (IS_ESS(dsp)) { + if (dsp->espcm_mode != ESPCM_4 || (dsp->sb_8_enable && dsp->sb_8_pause)) { + fifo_reset(dsp->espcm_fifo); + dsp->espcm_sample_idx = 0; + } + dsp->espcm_mode = ESPCM_4; + sb_start_dma(dsp, 1, 0, ESPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + } + break; + case 0x67: /* 3-bit ESPCM output with reference */ + case 0x66: /* 3-bit ESPCM output */ + if (IS_ESS(dsp)) { + if (dsp->espcm_mode != ESPCM_3 || (dsp->sb_8_enable && dsp->sb_8_pause)) { + fifo_reset(dsp->espcm_fifo); + dsp->espcm_sample_idx = 0; + } + dsp->espcm_mode = ESPCM_3; + sb_start_dma(dsp, 1, 0, ESPCM_3, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + } + break; + case 0x6D: /* 1-bit ESPCM output with reference */ + case 0x6C: /* 1-bit ESPCM output */ + if (IS_ESS(dsp)) { + if (dsp->espcm_mode != ESPCM_1 || (dsp->sb_8_enable && dsp->sb_8_pause)) { + fifo_reset(dsp->espcm_fifo); + dsp->espcm_sample_idx = 0; + } + dsp->espcm_mode = ESPCM_1; + sb_start_dma(dsp, 1, 0, ESPCM_1, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); + } + break; + case 0x6F: /* 4-bit ESPCM input with reference */ + case 0x6E: /* 4-bit ESPCM input */ + if (IS_ESS(dsp)) { + if (dsp->espcm_mode != ESPCM_4E || (dsp->sb_8_enable && dsp->sb_8_pause)) { + fifo_reset(dsp->espcm_fifo); + dsp->espcm_sample_idx = 0; + } + dsp->espcm_mode = ESPCM_4E; + sb_start_dma_i(dsp, 1, 0, ESPCM_4E, 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; @@ -791,8 +1428,11 @@ sb_exec_command(sb_dsp_t *dsp) 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->ess_dma_counter++; + if (dsp->sb_command == 0x75) { dsp->sb_8_length--; + dsp->ess_dma_counter++; + } break; case 0x77: /* 2.6-bit ADPCM output with reference */ dsp->sbref = dsp->dma_readb(dsp->dma_priv); @@ -802,14 +1442,18 @@ sb_exec_command(sb_dsp_t *dsp) 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->ess_dma_counter++; + if (dsp->sb_command == 0x77) { dsp->sb_8_length--; + dsp->ess_dma_counter++; + } 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--; + dsp->ess_dma_counter++; } break; case 0x7F: /* 2.6-bit ADPCM autoinit output */ @@ -817,12 +1461,13 @@ sb_exec_command(sb_dsp_t *dsp) 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--; + dsp->ess_dma_counter++; } 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); + timer_set_delay_u64(&dsp->output_timer, (uint64_t) trunc(dsp->sblatcho)); break; case 0x90: /* High speed 8-bit autoinit DMA output */ if (dsp->sb_type >= SB2) @@ -906,17 +1551,21 @@ sb_exec_command(sb_dsp_t *dsp) 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; + if (IS_NOT_ESS(dsp)) { + 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; + if (IS_NOT_ESS(dsp)) { + 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 */ @@ -944,6 +1593,11 @@ sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, ~dsp->sb_data[0]); break; case 0xE1: /* Get DSP version */ + if (IS_ESS(dsp)) { + sb_add_data(dsp, 0x3); + sb_add_data(dsp, 0x1); + break; + } if (IS_AZTECH(dsp)) { if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) { sb_add_data(dsp, 0x3); @@ -964,7 +1618,10 @@ sb_exec_command(sb_dsp_t *dsp) } dsp->sbe2 += sbe2dat[dsp->sbe2count & 3][8]; dsp->sbe2count++; - dsp->dma_writeb(dsp->dma_priv, dsp->sbe2); + if (dsp->dma_writeb(dsp->dma_priv, dsp->sbe2)) + /* Undocumented behavior: If write to DMA fails, the byte is written + to the CPU instead. The NT 3.1 Sound Blaster Pro driver relies on this. */ + sb_add_data(dsp, dsp->sbe2); break; case 0xE3: /* DSP copyright */ if (dsp->sb_type >= SB16) { @@ -972,23 +1629,47 @@ sb_exec_command(sb_dsp_t *dsp) while (sb16_copyright[c]) sb_add_data(dsp, sb16_copyright[c++]); sb_add_data(dsp, 0); + } else if (IS_ESS(dsp)) { + sb_add_data(dsp, 0); } break; case 0xE4: /* Write test register */ dsp->sb_test = dsp->sb_data[0]; break; - case 0xE7: /* ???? */ + case 0xE7: /* ESS detect/read config on ESS cards */ + if (IS_ESS(dsp)) { + switch (dsp->sb_subtype) { + default: + break; + case SB_SUBTYPE_ESS_ES688: + sb_add_data(dsp, 0x68); + sb_add_data(dsp, 0x80 | 0x04); + break; + case SB_SUBTYPE_ESS_ES1688: + // Determined via Windows driver debugging. + sb_add_data(dsp, 0x68); + sb_add_data(dsp, 0x80 | 0x09); + break; + } + } 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); + if (IS_ESS(dsp)) { + if (!timer_is_enabled(&dsp->irq_timer)) { + timer_set_delay_u64(&dsp->irq_timer, (100ULL * TIMER_USEC)); + } + } else { + sb_irq(dsp, 1); + dsp->ess_irq_generic = true; + } break; case 0xF3: /* Trigger 16-bit IRQ */ sb_dsp_log("Trigger IRQ\n"); - sb_irq(dsp, 0); + dsp->ess_irq_generic = true; break; case 0xF8: if (dsp->sb_type < SB16) @@ -1030,27 +1711,42 @@ sb_exec_command(sb_dsp_t *dsp) dsp->sb_8051_ram[0x30] = dsp->sb_command; } +static void +sb_do_reset(sb_dsp_t *dsp, const uint8_t v) +{ + if (((v & 1) != 0) && (dsp->state != DSP_S_RESET)) { + sb_dsp_reset(dsp); + dsp->sb_read_rp = dsp->sb_read_wp = 0; + dsp->state = DSP_S_RESET; + } else if (((v & 1) == 0) && (dsp->state == DSP_S_RESET)) { + dsp->state = DSP_S_RESET_WAIT; + dsp->sb_read_rp = dsp->sb_read_wp = 0; + sb_add_data(dsp, 0xaa); + } +} + void sb_write(uint16_t a, uint8_t v, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; + sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, a, v); + /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if (dsp->sb_type < SB16) + if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xE))) 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; + sb_do_reset(dsp, v); + + if (!(v & 2) && (dsp->espcm_fifo_reset & 2)) { + fifo_reset(dsp->espcm_fifo); } - dsp->uart_midi = 0; - dsp->uart_irq = 0; - dsp->onebyte_midi = 0; + dsp->espcm_fifo_reset = 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) { @@ -1071,8 +1767,6 @@ sb_write(uint16_t a, uint8_t v, void *priv) 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) @@ -1080,6 +1774,24 @@ sb_write(uint16_t a, uint8_t v, void *priv) else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07) sb_commands[dsp->sb_command] = 2; } + if (IS_ESS(dsp) && dsp->sb_command >= 0x64 && dsp->sb_command <= 0x6F) { + sb_commands[dsp->sb_command] = 2; + } else if (IS_ESS(dsp) && dsp->sb_command >= 0xA0 && dsp->sb_command <= 0xCF) { + if (dsp->sb_command <= 0xC0 + || dsp->sb_command == 0xC2 + || dsp->sb_command == 0xCF) { + sb_commands[dsp->sb_command] = 1; + } else if (dsp->sb_command == 0xC3 + || dsp->sb_command == 0xC6 + || dsp->sb_command == 0xC7 + || dsp->sb_command == 0xCE) { + sb_commands[dsp->sb_command] = 0; + } else { + sb_commands[dsp->sb_command] = -1; + } + } + } else { + dsp->sb_data[dsp->sb_data_stat++] = v; } if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { sb_exec_command(dsp); @@ -1104,62 +1816,106 @@ sb_read(uint16_t a, void *priv) uint8_t ret = 0x00; /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if (dsp->sb_type < SB16) - a &= 0xfffe; + if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xF))) + /* Exception: ESS AudioDrive does not alias port base+0xf */ + a &= 0xfffe; switch (a & 0xf) { + case 0x6: + ret = IS_ESS(dsp) ? 0x00 : 0xff; + break; case 0xA: /* Read data */ - if (dsp->mpu && dsp->uart_midi) { + if (dsp->mpu && dsp->uart_midi) ret = MPU401_ReadData(dsp->mpu); - } else { - dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; + else { if (dsp->sb_read_rp != dsp->sb_read_wp) { + dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp]; dsp->sb_read_rp++; dsp->sb_read_rp &= 0xff; } - return dsp->sbreaddat; + ret = dsp->sbreaddat; } + /* Advance the state just in case something reads from here + without reading the status first. */ + if (dsp->state == DSP_S_RESET_WAIT) + dsp->state = DSP_S_NORMAL; 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; + if ((dsp->state == DSP_S_NORMAL) || IS_ESS(dsp)) { + if (dsp->sb_8_enable || dsp->sb_type >= SB16) + dsp->busy_count = (dsp->busy_count + 1) & 3; + else + dsp->busy_count = 0; + if (IS_ESS(dsp)) { + if (dsp->wb_full || (dsp->busy_count & 2)) + dsp->wb_full = timer_is_enabled(&dsp->wb_timer); + + const uint8_t busy_flag = dsp->wb_full ? 0x80 : 0x00; + const uint8_t data_rdy = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x40; + const uint8_t fifo_full = 0; /* Unimplemented */ + const uint8_t fifo_empty = 0; /* (this is for the 256-byte extended mode FIFO, */ + const uint8_t fifo_half = 0; /* not the standard 64-byte FIFO) */ + const uint8_t irq_generic = dsp->ess_irq_generic ? 0x04 : 0x00; + const uint8_t irq_fifohe = 0; /* Unimplemented (ditto) */ + const uint8_t irq_dmactr = dsp->ess_irq_dmactr ? 0x01 : 0x00; + + ret = busy_flag | data_rdy | fifo_full | fifo_empty | fifo_half | irq_generic | irq_fifohe | irq_dmactr; + } else 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"); + ret = 0x80; + } else { + sb_dsp_log("SB Write Data Creative read 0xff\n"); + if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + ret = 0xaa; + else + ret = 0xff; + } + } else 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 0xff\n"); - return 0xff; + sb_dsp_log("SB Write Data Creative read 0x7f\n"); + if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + ret = 0x2a; + else + ret = 0x7f; } - } - 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; - } + } else + ret = 0xff; 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. */ + dsp->ess_irq_generic = dsp->ess_irq_dmactr = false; + /* + 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); + 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; + if ((dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x2a : 0xaa; + else + ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; + } + if (dsp->state == DSP_S_RESET_WAIT) { + ret &= 0x7f; + dsp->state = DSP_S_NORMAL; } 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"); + if (IS_NOT_ESS(dsp)) { + 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; @@ -1167,6 +1923,8 @@ sb_read(uint16_t a, void *priv) break; } + sb_dsp_log("[%04X:%08X] DSP: [R] %04X = %02X\n", CS, cpu_state.pc, a, ret); + return ret; } @@ -1189,6 +1947,7 @@ sb_dsp_input_msg(void *priv, uint8_t *msg, uint32_t len) for (uint32_t i = 0; i < len; i++) sb_add_data(dsp, msg[i]); sb_irq(dsp, 1); + dsp->ess_irq_generic = true; } else if (dsp->midi_in_poll) { for (uint32_t i = 0; i < len; i++) sb_add_data(dsp, msg[i]); @@ -1213,7 +1972,7 @@ sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) 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); + return (int) (len - i); } sb_add_data(dsp, buffer[i]); @@ -1224,6 +1983,15 @@ sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) return 0; } +void +sb_dsp_irq_poll(void *priv) +{ + sb_dsp_t *dsp = (sb_dsp_t *) priv; + + sb_irq(dsp, 1); + dsp->ess_irq_generic = true; +} + void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) { @@ -1252,12 +2020,35 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) timer_add(&dsp->output_timer, pollsb, dsp, 0); timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); timer_add(&dsp->wb_timer, NULL, dsp, 0); + timer_add(&dsp->irq_timer, sb_dsp_irq_poll, dsp, 0); - /* 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, FREQ_44100); - recalc_sb16_filter(2, 18939); + if (IS_ESS(dsp)) + /* Initialize ESS filter to 8 kHz. This will be recalculated when a set frequency command is + sent. */ + recalc_sb16_filter(0, 8000 * 2); + else + /* 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); + if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2)) { + /* OPL3 or dual OPL2 is stereo. */ + if (dsp->sb_has_real_opl) + recalc_opl_filter(FREQ_49716 * 2); + else + recalc_sb16_filter(1, FREQ_48000 * 2); + } else { + /* OPL2 is mono. */ + if (dsp->sb_has_real_opl) + recalc_opl_filter(FREQ_49716); + else + recalc_sb16_filter(1, FREQ_48000); + } + /* CD Audio is stereo. */ + recalc_sb16_filter(2, FREQ_44100 * 2); + /* PC speaker is mono. */ + recalc_sb16_filter(3, 18939); + /* E-MU 8000 is stereo. */ + recalc_sb16_filter(4, FREQ_44100 * 2); /* Initialize SB16 8051 RAM and ASP internal RAM */ memset(dsp->sb_8051_ram, 0x00, sizeof(dsp->sb_8051_ram)); @@ -1266,6 +2057,9 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) dsp->sb_8051_ram[0x37] = 0x38; memset(dsp->sb_asp_ram, 0xff, sizeof(dsp->sb_asp_ram)); + + dsp->espcm_fifo = fifo64_init(); + fifo_set_trigger_len(dsp->espcm_fifo, 1); } void @@ -1283,6 +2077,12 @@ sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) } } +void +sb_dsp_set_real_opl(sb_dsp_t *dsp, uint8_t has_real_opl) +{ + dsp->sb_has_real_opl = has_real_opl; +} + void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo) { @@ -1311,6 +2111,31 @@ sb_dsp_dma_attach(sb_dsp_t *dsp, dsp->dma_priv = priv; } +void +sb_ess_finish_dma(sb_dsp_t *dsp) +{ + if (!dsp->ess_playback_mode) + return; + ESSreg(0xB8) &= ~0x01; + dma_set_drq(dsp->sb_8_dmanum, 0); +} + +void +sb_espcm_fifoctl_run(sb_dsp_t *dsp) +{ + if (fifo_get_empty(dsp->espcm_fifo) && !dsp->sb_8_pause) { + while (!fifo_get_full(dsp->espcm_fifo)) { + int32_t val; + val = dsp->dma_readb(dsp->dma_priv); + dsp->ess_dma_counter++; + fifo_write(val & 0xff, dsp->espcm_fifo); + if (val & DMA_OVER) { + break; + } + } + } +} + void pollsb(void *priv) { @@ -1319,198 +2144,434 @@ pollsb(void *priv) 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) { + timer_advance_u64(&dsp->output_timer, (uint64_t) dsp->sblatcho); + if (dsp->sb_8_enable && dsp->sb_pausetime < 0 && dsp->sb_8_output) { sb_dsp_update(dsp); 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--; + if (!dsp->sb_8_pause) { + 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 = (int16_t) ((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--; + dsp->ess_dma_counter++; + } 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--; + if (!dsp->sb_8_pause) { + data[0] = dsp->dma_readb(dsp->dma_priv); + if (data[0] == DMA_NODATA) + break; + dsp->sbdat = (int16_t) (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--; + dsp->ess_dma_counter++; + } 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; + if (!dsp->sb_8_pause) { + 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 = (int16_t) ((data[0] ^ 0x80) << 8); + dsp->sbdatr = (int16_t) ((data[1] ^ 0x80) << 8); + dsp->sb_8_length -= 2; + dsp->ess_dma_counter += 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; + if (!dsp->sb_8_pause) { + 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 = (int16_t) (data[0] << 8); + dsp->sbdatr = (int16_t) (data[1] << 8); + dsp->sb_8_length -= 2; + dsp->ess_dma_counter += 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; - - 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->sbdacpos++; - - if (dsp->sbdacpos >= 2) { - dsp->sbdacpos = 0; - dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); - dsp->sb_8_length--; - } - - 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; + if (!dsp->sb_8_pause) { + if (dsp->sbdacpos) + tempi = (dsp->sbdat2 & 0xF) + dsp->sbstep; else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + 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; + + dsp->sbstep = (int8_t) ((dsp->sbstep + adjustMap4[tempi]) & 0xff); + dsp->sbdat = (int16_t) ((dsp->sbref ^ 0x80) << 8); + + dsp->sbdacpos++; + + if (dsp->sbdacpos >= 2) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + dsp->ess_dma_counter++; + } + + 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; - - 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; - - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; - - dsp->sbdacpos++; - if (dsp->sbdacpos >= 3) { - dsp->sbdacpos = 0; - dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); - dsp->sb_8_length--; - } - - 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; + if (!dsp->sb_8_pause) { + if (!dsp->sbdacpos) + tempi = (dsp->sbdat2 >> 5) + dsp->sbstep; + else if (dsp->sbdacpos == 1) + tempi = ((dsp->sbdat2 >> 2) & 7) + dsp->sbstep; else - dsp->sbdatr = dsp->sbdat; - dsp->sbleftright = !dsp->sbleftright; - } else - dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + tempi = ((dsp->sbdat2 << 1) & 7) + dsp->sbstep; + + 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 = (int8_t) ((dsp->sbstep + adjustMap26[tempi]) & 0xff); + + dsp->sbdat = (int16_t) ((dsp->sbref ^ 0x80) << 8); + + dsp->sbdacpos++; + if (dsp->sbdacpos >= 3) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + dsp->ess_dma_counter++; + } + + 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; + if (!dsp->sb_8_pause) { + 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 = (int8_t) ((dsp->sbstep + adjustMap2[tempi]) & 0xff); - dsp->sbdat = (dsp->sbref ^ 0x80) << 8; + dsp->sbdat = (int16_t) ((dsp->sbref ^ 0x80) << 8); - dsp->sbdacpos++; - if (dsp->sbdacpos >= 4) { - dsp->sbdacpos = 0; - dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sbdacpos++; + if (dsp->sbdacpos >= 4) { + dsp->sbdacpos = 0; + dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); + dsp->sb_8_length--; + dsp->ess_dma_counter++; + } + + 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; + + case ESPCM_4: + if (dsp->espcm_sample_idx >= 19) { + dsp->espcm_sample_idx = 0; + } + if (dsp->espcm_sample_idx == 0) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[0] = fifo_read(dsp->espcm_fifo); + + dsp->espcm_range = dsp->espcm_byte_buffer[0] & 0x0F; + tempi = dsp->espcm_byte_buffer[0] >> 4; + } else if (dsp->espcm_sample_idx & 1) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[0] = fifo_read(dsp->espcm_fifo); + dsp->sb_8_length--; + + tempi = dsp->espcm_byte_buffer[0] & 0x0F; + } else { + tempi = dsp->espcm_byte_buffer[0] >> 4; } + if (dsp->espcm_sample_idx == 18) { + dsp->sb_8_length--; + } + + dsp->espcm_sample_idx++; + + tempi |= (dsp->espcm_range << 4); + data[0] = (int) espcm_range_map[tempi]; + dsp->sbdat = (int16_t) (data[0] << 8); if (dsp->stereo) { - sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n", + sb_dsp_log("pollsb: ESPCM 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 + } else { dsp->sbdatl = dsp->sbdatr = dsp->sbdat; + } + break; + + case ESPCM_3: + if (dsp->espcm_sample_idx >= 19) { + dsp->espcm_sample_idx = 0; + } + if (dsp->espcm_sample_idx == 0) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[0] = fifo_read(dsp->espcm_fifo); + + dsp->espcm_range = dsp->espcm_byte_buffer[0] & 0x0F; + tempi = dsp->espcm_byte_buffer[0] >> 4; + dsp->espcm_last_value = tempi; + } else if (dsp->espcm_sample_idx == 1) { + for (tempi = 0; tempi < 4; tempi++) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[tempi] = fifo_read(dsp->espcm_fifo); + dsp->sb_8_length--; + } + if (tempi < 4) { + break; + } + + dsp->espcm_table_index = dsp->espcm_byte_buffer[0] & 0x03; + + dsp->espcm_code_buffer[0] = (dsp->espcm_byte_buffer[0] >> 2) & 0x07; + dsp->espcm_code_buffer[1] = (dsp->espcm_byte_buffer[0] >> 5) & 0x07; + dsp->espcm_code_buffer[2] = (dsp->espcm_byte_buffer[1]) & 0x07; + dsp->espcm_code_buffer[3] = (dsp->espcm_byte_buffer[1] >> 3) & 0x07; + dsp->espcm_code_buffer[4] = ((dsp->espcm_byte_buffer[1] >> 6) & 0x03) | ((dsp->espcm_byte_buffer[2] & 0x01) << 2); + dsp->espcm_code_buffer[5] = (dsp->espcm_byte_buffer[2] >> 1) & 0x07; + dsp->espcm_code_buffer[6] = (dsp->espcm_byte_buffer[2] >> 4) & 0x07; + dsp->espcm_code_buffer[7] = ((dsp->espcm_byte_buffer[2] >> 7) & 0x01) | ((dsp->espcm_byte_buffer[3] & 0x03) << 1); + dsp->espcm_code_buffer[8] = (dsp->espcm_byte_buffer[3] >> 2) & 0x07; + dsp->espcm_code_buffer[9] = (dsp->espcm_byte_buffer[3] >> 5) & 0x07; + + tempi = (dsp->espcm_table_index << 8) | (dsp->espcm_last_value << 3) | dsp->espcm_code_buffer[0]; + tempi = espcm3_dpcm_tables[tempi]; + dsp->espcm_last_value = tempi; + } else if (dsp->espcm_sample_idx == 11) { + for (tempi = 1; tempi < 4; tempi++) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[tempi] = fifo_read(dsp->espcm_fifo); + dsp->sb_8_length--; + } + if (tempi < 4) { + break; + } + + dsp->espcm_code_buffer[0] = (dsp->espcm_byte_buffer[1]) & 0x07; + dsp->espcm_code_buffer[1] = (dsp->espcm_byte_buffer[1] >> 3) & 0x07; + dsp->espcm_code_buffer[2] = ((dsp->espcm_byte_buffer[1] >> 6) & 0x03) | ((dsp->espcm_byte_buffer[2] & 0x01) << 2); + dsp->espcm_code_buffer[3] = (dsp->espcm_byte_buffer[2] >> 1) & 0x07; + dsp->espcm_code_buffer[4] = (dsp->espcm_byte_buffer[2] >> 4) & 0x07; + dsp->espcm_code_buffer[5] = ((dsp->espcm_byte_buffer[2] >> 7) & 0x01) | ((dsp->espcm_byte_buffer[3] & 0x03) << 1); + dsp->espcm_code_buffer[6] = (dsp->espcm_byte_buffer[3] >> 2) & 0x07; + dsp->espcm_code_buffer[7] = (dsp->espcm_byte_buffer[3] >> 5) & 0x07; + + tempi = (dsp->espcm_table_index << 8) | (dsp->espcm_last_value << 3) | dsp->espcm_code_buffer[0]; + tempi = espcm3_dpcm_tables[tempi]; + dsp->espcm_last_value = tempi; + } else { + tempi = (dsp->espcm_table_index << 8) | (dsp->espcm_last_value << 3) | dsp->espcm_code_buffer[(dsp->espcm_sample_idx - 1) % 10]; + tempi = espcm3_dpcm_tables[tempi]; + dsp->espcm_last_value = tempi; + } + + if (dsp->espcm_sample_idx == 18) { + dsp->sb_8_length--; + } + + dsp->espcm_sample_idx++; + + tempi |= (dsp->espcm_range << 4); + data[0] = (int) (espcm_range_map[tempi]); + dsp->sbdat = (int16_t) (data[0] << 8); + if (dsp->stereo) { + sb_dsp_log("pollsb: ESPCM 3, 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 ESPCM_1: + if (dsp->espcm_sample_idx >= 19) { + dsp->espcm_sample_idx = 0; + } + if (dsp->espcm_sample_idx == 0) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[0] = fifo_read(dsp->espcm_fifo); + + dsp->espcm_range = dsp->espcm_byte_buffer[0] & 0x0F; + dsp->espcm_byte_buffer[0] >>= 5; + tempi = dsp->espcm_byte_buffer[0] & 1 ? 0xC : 0x4; + dsp->espcm_byte_buffer[0] >>= 1; + } else if ((dsp->espcm_sample_idx == 3) | (dsp->espcm_sample_idx == 11)) { + sb_espcm_fifoctl_run(dsp); + if (fifo_get_empty(dsp->espcm_fifo)) { + break; + } + dsp->espcm_byte_buffer[0] = fifo_read(dsp->espcm_fifo); + dsp->sb_8_length--; + + tempi = dsp->espcm_byte_buffer[0] & 1 ? 0xC : 0x4; + dsp->espcm_byte_buffer[0] >>= 1; + } else { + tempi = dsp->espcm_byte_buffer[0] & 1 ? 0xC : 0x4; + dsp->espcm_byte_buffer[0] >>= 1; + } + + if (dsp->espcm_sample_idx == 18) { + dsp->sb_8_length--; + } + + dsp->espcm_sample_idx++; + + tempi |= (dsp->espcm_range << 4); + data[0] = (int) espcm_range_map[tempi]; + dsp->sbdat = (int16_t) (data[0] << 8); + if (dsp->stereo) { + sb_dsp_log("pollsb: ESPCM 1, 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; default: break; } - if (dsp->sb_8_length < 0) { + if (dsp->sb_8_length < 0 && !dsp->ess_playback_mode) { 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_ess_finish_dma(dsp); } sb_irq(dsp, 1); + dsp->ess_irq_generic = true; + } + if (dsp->ess_dma_counter > 0xffff) { + if (dsp->ess_playback_mode) { + if (!dsp->sb_8_autoinit) { + dsp->sb_8_enable = 0; + timer_disable(&dsp->output_timer); + sb_ess_finish_dma(dsp); + } + if (ESSreg(0xB1) & 0x40) { + sb_irq(dsp, 1); + dsp->ess_irq_dmactr = true; + } + } + uint32_t temp = dsp->ess_dma_counter & 0xffff; + dsp->ess_dma_counter = sb_ess_get_dma_counter(dsp); + dsp->ess_dma_counter += temp; } } if (dsp->sb_16_enable && !dsp->sb_16_pause && (dsp->sb_pausetime < 0LL) && dsp->sb_16_output) { @@ -1521,54 +2582,77 @@ pollsb(void *priv) data[0] = dsp->dma_readw(dsp->dma_priv); if (data[0] == DMA_NODATA) break; - dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; + dsp->sbdatl = dsp->sbdatr = (int16_t) ((data[0] & 0xffff) ^ 0x8000); dsp->sb_16_length--; + dsp->ess_dma_counter += 2; 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->sbdatl = dsp->sbdatr = (int16_t) (data[0] & 0xffff); dsp->sb_16_length--; + dsp->ess_dma_counter += 2; 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->sbdatl = (int16_t) ((data[0] & 0xffff) ^ 0x8000); + dsp->sbdatr = (int16_t) ((data[1] & 0xffff) ^ 0x8000); dsp->sb_16_length -= 2; + dsp->ess_dma_counter += 4; 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->sbdatl = (int16_t) (data[0] & 0xffff); + dsp->sbdatr = (int16_t) (data[1] & 0xffff); dsp->sb_16_length -= 2; + dsp->ess_dma_counter += 4; break; default: break; } - if (dsp->sb_16_length < 0) { + if (dsp->sb_16_length < 0 && !dsp->ess_playback_mode) { 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_ess_finish_dma(dsp); } sb_irq(dsp, 0); + dsp->ess_irq_generic = true; + } + if (dsp->ess_dma_counter > 0xffff) { + if (dsp->ess_playback_mode) { + if (!dsp->sb_16_autoinit) { + dsp->sb_16_enable = 0; + timer_disable(&dsp->output_timer); + sb_ess_finish_dma(dsp); + } + if (ESSreg(0xB1) & 0x40) { + sb_irq(dsp, 0); + dsp->ess_irq_dmactr = true; + } + } + uint32_t temp = dsp->ess_dma_counter & 0xffff; + dsp->ess_dma_counter = sb_ess_get_dma_counter(dsp); + dsp->ess_dma_counter += temp; } } if (dsp->sb_pausetime > -1) { dsp->sb_pausetime--; if (dsp->sb_pausetime < 0) { sb_irq(dsp, 1); + dsp->ess_irq_generic = true; if (!dsp->sb_8_enable) timer_disable(&dsp->output_timer); sb_dsp_log("SB pause over\n"); @@ -1582,19 +2666,21 @@ sb_poll_i(void *priv) sb_dsp_t *dsp = (sb_dsp_t *) priv; int processed = 0; - timer_advance_u64(&dsp->input_timer, dsp->sblatchi); + timer_advance_u64(&dsp->input_timer, (uint64_t) 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 */ dsp->dma_writeb(dsp->dma_priv, (dsp->record_buffer[dsp->record_pos_read] >> 8) ^ 0x80); dsp->sb_8_length--; + dsp->ess_dma_counter++; 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->ess_dma_counter++; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1602,6 +2688,7 @@ sb_poll_i(void *priv) 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->ess_dma_counter += 2; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1609,22 +2696,117 @@ sb_poll_i(void *priv) 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->ess_dma_counter += 2; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; + case ESPCM_4E: + /* + I assume the real hardware double-buffers the blocks or something like that. + We're not gonna do that here. + */ + dsp->espcm_sample_buffer[dsp->espcm_sample_idx] = (int8_t) (dsp->record_buffer[dsp->record_pos_read] >> 8); + dsp->espcm_sample_idx++; + dsp->record_pos_read += 2; + dsp->record_pos_read &= 0xFFFF; + if (dsp->espcm_sample_idx >= 19) { + int i, table_addr; + int8_t min_sample = 127, max_sample = -128, s; + + for (i = 0; i < 19; i++) { + s = dsp->espcm_sample_buffer[i]; + if (s < min_sample) { + min_sample = s; + } + if (s > max_sample) { + max_sample = s; + } + } + if (min_sample < 0) { + if (min_sample == -128) + min_sample = 127; /* Clip it to make it fit into int8_t. */ + else + min_sample = (int8_t) -min_sample; + } + if (max_sample < 0) { + if (max_sample == -128) + max_sample = 127; /* Clip it to make it fit into int8_t. */ + else + max_sample = (int8_t) -max_sample; + } + if (min_sample > max_sample) + max_sample = min_sample; + + for (table_addr = 15; table_addr < 256; table_addr += 16) { + if (max_sample <= espcm_range_map[table_addr]) { + break; + } + } + dsp->espcm_range = table_addr >> 4; + + for (i = 0; i < 19; i++) { + int last_sigma = 9999; + table_addr = dsp->espcm_range << 4; + s = dsp->espcm_sample_buffer[i]; + for (; (table_addr >> 4) == dsp->espcm_range; table_addr++) { + int sigma = espcm_range_map[table_addr] - s; + if (sigma < 0) { + sigma = -sigma; + } + if (sigma > last_sigma) { + break; + } + last_sigma = sigma; + } + table_addr--; + dsp->espcm_code_buffer[i] = table_addr & 0x0F; + } + + uint8_t b = dsp->espcm_range | (dsp->espcm_code_buffer[0] << 4); + dsp->dma_writeb(dsp->dma_priv, b); + dsp->sb_8_length--; + dsp->ess_dma_counter++; + + for (i = 1; i < 10; i++) { + b = dsp->espcm_code_buffer[i * 2 - 1] | (dsp->espcm_code_buffer[i * 2] << 4); + dsp->dma_writeb(dsp->dma_priv, b); + dsp->sb_8_length--; + dsp->ess_dma_counter++; + } + + dsp->espcm_sample_idx = 0; + } default: break; } - if (dsp->sb_8_length < 0) { + if (dsp->sb_8_length < 0 && !dsp->ess_playback_mode) { 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_ess_finish_dma(dsp); } sb_irq(dsp, 1); + dsp->ess_irq_generic = true; + } + if (dsp->ess_dma_counter > 0xffff) { + if (dsp->ess_playback_mode) { + if (!dsp->sb_8_autoinit) { + dsp->sb_8_enable = 0; + timer_disable(&dsp->input_timer); + sb_ess_finish_dma(dsp); + } + if (ESSreg(0xB1) & 0x40) { + sb_irq(dsp, 1); + dsp->ess_irq_dmactr = true; + } + } + uint32_t temp = dsp->ess_dma_counter & 0xffff; + dsp->ess_dma_counter = sb_ess_get_dma_counter(dsp); + dsp->ess_dma_counter += temp; } processed = 1; } @@ -1634,6 +2816,7 @@ sb_poll_i(void *priv) if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read] ^ 0x8000)) return; dsp->sb_16_length--; + dsp->ess_dma_counter += 2; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1641,6 +2824,7 @@ sb_poll_i(void *priv) if (dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read])) return; dsp->sb_16_length--; + dsp->ess_dma_counter += 2; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1649,6 +2833,7 @@ sb_poll_i(void *priv) return; dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read + 1] ^ 0x8000); dsp->sb_16_length -= 2; + dsp->ess_dma_counter += 4; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1657,6 +2842,7 @@ sb_poll_i(void *priv) return; dsp->dma_writew(dsp->dma_priv, dsp->record_buffer[dsp->record_pos_read + 1]); dsp->sb_16_length -= 2; + dsp->ess_dma_counter += 4; dsp->record_pos_read += 2; dsp->record_pos_read &= 0xFFFF; break; @@ -1665,14 +2851,32 @@ sb_poll_i(void *priv) break; } - if (dsp->sb_16_length < 0) { + if (dsp->sb_16_length < 0 && !dsp->ess_playback_mode) { 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_ess_finish_dma(dsp); } sb_irq(dsp, 0); + dsp->ess_irq_generic = true; + } + if (dsp->ess_dma_counter > 0xffff) { + if (dsp->ess_playback_mode) { + if (!dsp->sb_16_autoinit) { + dsp->sb_16_enable = 0; + timer_disable(&dsp->input_timer); + sb_ess_finish_dma(dsp); + } + if (ESSreg(0xB1) & 0x40) { + sb_irq(dsp, 0); + dsp->ess_irq_dmactr = true; + } + } + uint32_t temp = dsp->ess_dma_counter & 0xffff; + dsp->ess_dma_counter = sb_ess_get_dma_counter(dsp); + dsp->ess_dma_counter += temp; } processed = 1; } diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index a69d746da..da88b29e9 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -80,21 +80,28 @@ static void wss_get_buffer(int32_t *buffer, int len, void *priv) { wss_t *wss = (wss_t *) priv; - const int32_t *opl_buf = NULL; - - if (wss->opl_enabled) - opl_buf = wss->opl.update(wss->opl.priv); ad1848_update(&wss->ad1848); + for (int c = 0; c < len * 2; c++) + buffer[c] += wss->ad1848.buffer[c] / 2; + + wss->ad1848.pos = 0; +} + +static void +wss_get_music_buffer(int32_t *buffer, int len, void *priv) +{ + wss_t *wss = (wss_t *) priv; + const int32_t *opl_buf = NULL; + + opl_buf = wss->opl.update(wss->opl.priv); + for (int c = 0; c < len * 2; c++) { if (opl_buf) buffer[c] += opl_buf[c]; - buffer[c] += wss->ad1848.buffer[c] / 2; } - if (wss->opl_enabled) - wss->opl.reset_buffer(wss->opl.priv); - wss->ad1848.pos = 0; + wss->opl.reset_buffer(wss->opl.priv); } void * @@ -131,6 +138,9 @@ wss_init(UNUSED(const device_t *info)) sound_add_handler(wss_get_buffer, wss); + if (wss->opl_enabled) + music_add_handler(wss_get_music_buffer, wss); + return wss; } @@ -214,6 +224,9 @@ ncr_audio_init(UNUSED(const device_t *info)) sound_add_handler(wss_get_buffer, wss); + if (wss->opl_enabled) + music_add_handler(wss_get_music_buffer, wss); + return wss; } diff --git a/src/sound/sound.c b/src/sound/sound.c index ed7f821e0..f527cbc61 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -22,25 +22,20 @@ #include #include #include -#include #define HAVE_STDARG_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; @@ -53,19 +48,38 @@ typedef struct { int sound_card_current[SOUND_CARD_MAX] = { 0, 0, 0, 0 }; int sound_pos_global = 0; +int music_pos_global = 0; +int wavetable_pos_global = 0; int sound_gain = 0; static sound_handler_t sound_handlers[8]; +static sound_handler_t music_handlers[8]; +static sound_handler_t wavetable_handlers[8]; + +static double cd_audio_volume_lut[256]; + 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 int32_t *outbuffer_m; +static float *outbuffer_m_ex; +static int16_t *outbuffer_m_ex_int16; +static int32_t *outbuffer_w; +static float *outbuffer_w_ex; +static int16_t *outbuffer_w_ex_int16; static int sound_handlers_num; +static int music_handlers_num; +static int wavetable_handlers_num; static pc_timer_t sound_poll_timer; static uint64_t sound_poll_latch; +static pc_timer_t music_poll_timer; +static uint64_t music_poll_latch; +static pc_timer_t wavetable_poll_timer; +static uint64_t wavetable_poll_latch; static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2]; static float cd_out_buffer[CD_BUFLEN * 2]; @@ -112,52 +126,60 @@ static const device_t sound_internal_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 }, -#endif - { &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 } + { &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 }, + { &pasplus_device }, + { &pas16_device }, + { &pas16d_device }, + { &pssj_isa_device }, + { &tndy_device }, + { &wss_device }, + { &adlib_mca_device }, + { &ess_chipchat_16_mca_device }, + { &ncr_business_audio_device }, + { &sb_mcv_device }, + { &sb_pro_mcv_device }, + { &sb_16_reply_mca_device }, + { &ess_soundpiper_16_mca_device }, + { &ess_soundpiper_32_mca_device }, + { &cmi8338_device }, + { &cmi8738_device }, + { &es1371_device }, + { &ad1881_device }, + { &cs4297a_device }, + { &ess_688_device }, + { &ess_ess0100_pnp_device }, + { &ess_1688_device }, + { &ess_ess0102_pnp_device }, + { &ess_ess0968_pnp_device }, + { NULL } // clang-format on }; @@ -197,7 +219,7 @@ sound_card_getdevice(int card) int sound_card_has_config(int card) { - if (!sound_cards[card].device) + if (sound_cards[card].device == NULL) return 0; return device_has_config(sound_cards[card].device) ? 1 : 0; } @@ -226,13 +248,13 @@ void sound_card_init(void) { if ((sound_card_current[0] > SOUND_INTERNAL) && (sound_cards[sound_card_current[0]].device)) - device_add(sound_cards[sound_card_current[0]].device); + device_add_inst(sound_cards[sound_card_current[0]].device, 1); if ((sound_card_current[1] > SOUND_INTERNAL) && (sound_cards[sound_card_current[1]].device)) - device_add(sound_cards[sound_card_current[1]].device); + device_add_inst(sound_cards[sound_card_current[1]].device, 2); if ((sound_card_current[2] > SOUND_INTERNAL) && (sound_cards[sound_card_current[2]].device)) - device_add(sound_cards[sound_card_current[2]].device); + device_add_inst(sound_cards[sound_card_current[2]].device, 3); if ((sound_card_current[3] > SOUND_INTERNAL) && (sound_cards[sound_card_current[3]].device)) - device_add(sound_cards[sound_card_current[3]].device); + device_add_inst(sound_cards[sound_card_current[3]].device, 4); } void @@ -254,9 +276,7 @@ sound_cd_clean_buffers(void) static void sound_cd_thread(UNUSED(void *param)) { - uint32_t lba; - int r; - int pre; + int temp_buffer[2]; int channel_select[2]; double audio_vol_l; double audio_vol_r; @@ -273,47 +293,35 @@ sound_cd_thread(UNUSED(void *param)) sound_cd_clean_buffers(); + temp_buffer[0] = temp_buffer[1] = 0; + 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) + const uint32_t lba = cdrom[i].seek_pos; + const int r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); + if (!cdrom[i].sound_on || !r) continue; - pre = cdrom_is_pre(&(cdrom[i]), lba); + const int 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)); + audio_vol_l = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 0)]; + audio_vol_r = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 1)]; } else { - audio_vol_l = 255.0; - audio_vol_r = 255.0; + audio_vol_l = cd_audio_volume_lut[255]; + audio_vol_r = cd_audio_volume_lut[255]; } - /* 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 (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); + channel_select[0] = (int) cdrom[i].get_channel(cdrom[i].priv, 0); + channel_select[1] = (int) cdrom[i].get_channel(cdrom[i].priv, 1); } else { channel_select[0] = 1; channel_select[1] = 2; } - for (uint16_t c = 0; c < CD_BUFLEN * 2; c += 2) { + for (int c = 0; c < CD_BUFLEN * 2; c += 2) { /*Apply ATAPI channel select*/ cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0; @@ -351,17 +359,20 @@ sound_cd_thread(UNUSED(void *param)) 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; + temp_buffer[0] += (int) trunc(cd_buffer_temp[0]); + temp_buffer[1] += (int) trunc(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]; + if (temp_buffer[0] > 32767) + temp_buffer[0] = 32767; + if (temp_buffer[0] < -32768) + temp_buffer[0] = -32768; + if (temp_buffer[1] > 32767) + temp_buffer[1] = 32767; + if (temp_buffer[1] < -32768) + temp_buffer[1] = -32768; + + cd_out_buffer_int16[c] = (int16_t) temp_buffer[0]; + cd_out_buffer_int16[c + 1] = (int16_t) temp_buffer[1]; } } } @@ -395,6 +406,50 @@ sound_realloc_buffers(void) } } +static void +music_realloc_buffers(void) +{ + if (outbuffer_m_ex != NULL) { + free(outbuffer_m_ex); + outbuffer_m_ex = NULL; + } + + if (outbuffer_m_ex_int16 != NULL) { + free(outbuffer_m_ex_int16); + outbuffer_m_ex_int16 = NULL; + } + + if (sound_is_float) { + outbuffer_m_ex = calloc(MUSICBUFLEN * 2, sizeof(float)); + memset(outbuffer_m_ex, 0x00, MUSICBUFLEN * 2 * sizeof(float)); + } else { + outbuffer_m_ex_int16 = calloc(MUSICBUFLEN * 2, sizeof(int16_t)); + memset(outbuffer_m_ex_int16, 0x00, MUSICBUFLEN * 2 * sizeof(int16_t)); + } +} + +static void +wavetable_realloc_buffers(void) +{ + if (outbuffer_w_ex != NULL) { + free(outbuffer_w_ex); + outbuffer_w_ex = NULL; + } + + if (outbuffer_w_ex_int16 != NULL) { + free(outbuffer_w_ex_int16); + outbuffer_w_ex_int16 = NULL; + } + + if (sound_is_float) { + outbuffer_w_ex = calloc(WTBUFLEN * 2, sizeof(float)); + memset(outbuffer_w_ex, 0x00, WTBUFLEN * 2 * sizeof(float)); + } else { + outbuffer_w_ex_int16 = calloc(WTBUFLEN * 2, sizeof(int16_t)); + memset(outbuffer_w_ex_int16, 0x00, WTBUFLEN * 2 * sizeof(int16_t)); + } +} + void sound_init(void) { @@ -403,10 +458,37 @@ sound_init(void) outbuffer_ex = NULL; outbuffer_ex_int16 = NULL; + outbuffer_m_ex = NULL; + outbuffer_m_ex_int16 = NULL; + + outbuffer_w_ex = NULL; + outbuffer_w_ex_int16 = NULL; + outbuffer = NULL; outbuffer = calloc(SOUNDBUFLEN * 2, sizeof(int32_t)); memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t)); + outbuffer_m = NULL; + outbuffer_m = calloc(MUSICBUFLEN * 2, sizeof(int32_t)); + memset(outbuffer_m, 0x00, MUSICBUFLEN * 2 * sizeof(int32_t)); + + outbuffer_w = NULL; + outbuffer_w = calloc(WTBUFLEN * 2, sizeof(int32_t)); + memset(outbuffer_w, 0x00, WTBUFLEN * 2 * sizeof(int32_t)); + + for (uint16_t i = 0; i < 256; i++) { + double di = (double) i; + + if (di >= 255.0) + di = 1.0; + else if (di > 0.0) + di = (48.0 + (20.0 * log(di / 256.0))) / 48.0; + else + di = 0.0; + + cd_audio_volume_lut[i] = di; + } + for (uint8_t i = 0; i < CDROM_NUM; i++) { if (cdrom[i].bus_type != CDROM_BUS_DISABLED) available_cdrom_drives++; @@ -438,6 +520,22 @@ sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *priv), void sound_handlers_num++; } +void +music_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *priv), void *priv) +{ + music_handlers[music_handlers_num].get_buffer = get_buffer; + music_handlers[music_handlers_num].priv = priv; + music_handlers_num++; +} + +void +wavetable_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *priv), void *priv) +{ + wavetable_handlers[wavetable_handlers_num].get_buffer = get_buffer; + wavetable_handlers[wavetable_handlers_num].priv = priv; + wavetable_handlers_num++; +} + void sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *priv), void *priv) { @@ -481,7 +579,7 @@ sound_poll(UNUSED(void *priv)) if (outbuffer[c] < -32768) outbuffer[c] = -32768; - outbuffer_ex_int16[c] = outbuffer[c]; + outbuffer_ex_int16[c] = (int16_t) outbuffer[c]; } } @@ -502,10 +600,86 @@ sound_poll(UNUSED(void *priv)) } } +void +music_poll(UNUSED(void *priv)) +{ + timer_advance_u64(&music_poll_timer, music_poll_latch); + + music_pos_global++; + if (music_pos_global == MUSICBUFLEN) { + int c; + + memset(outbuffer_m, 0x00, MUSICBUFLEN * 2 * sizeof(int32_t)); + + for (c = 0; c < music_handlers_num; c++) + music_handlers[c].get_buffer(outbuffer_m, MUSICBUFLEN, music_handlers[c].priv); + + for (c = 0; c < MUSICBUFLEN * 2; c++) { + if (sound_is_float) + outbuffer_m_ex[c] = ((float) outbuffer_m[c]) / (float) 32768.0; + else { + if (outbuffer_m[c] > 32767) + outbuffer_m[c] = 32767; + if (outbuffer_m[c] < -32768) + outbuffer_m[c] = -32768; + + outbuffer_m_ex_int16[c] = (int16_t) outbuffer_m[c]; + } + } + + if (sound_is_float) + givealbuffer_music(outbuffer_m_ex); + else + givealbuffer_music(outbuffer_m_ex_int16); + + music_pos_global = 0; + } +} + +void +wavetable_poll(UNUSED(void *priv)) +{ + timer_advance_u64(&wavetable_poll_timer, wavetable_poll_latch); + + wavetable_pos_global++; + if (wavetable_pos_global == WTBUFLEN) { + int c; + + memset(outbuffer_w, 0x00, WTBUFLEN * 2 * sizeof(int32_t)); + + for (c = 0; c < wavetable_handlers_num; c++) + wavetable_handlers[c].get_buffer(outbuffer_w, WTBUFLEN, wavetable_handlers[c].priv); + + for (c = 0; c < WTBUFLEN * 2; c++) { + if (sound_is_float) + outbuffer_w_ex[c] = ((float) outbuffer_w[c]) / (float) 32768.0; + else { + if (outbuffer_w[c] > 32767) + outbuffer_w[c] = 32767; + if (outbuffer_w[c] < -32768) + outbuffer_w[c] = -32768; + + outbuffer_w_ex_int16[c] = (int16_t) outbuffer_w[c]; + } + } + + if (sound_is_float) + givealbuffer_wt(outbuffer_w_ex); + else + givealbuffer_wt(outbuffer_w_ex_int16); + + wavetable_pos_global = 0; + } +} + void sound_speed_changed(void) { sound_poll_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) SOUND_FREQ)); + + music_poll_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) MUSIC_FREQ)); + + wavetable_poll_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) WT_FREQ)); } void @@ -513,6 +687,10 @@ sound_reset(void) { sound_realloc_buffers(); + music_realloc_buffers(); + + wavetable_realloc_buffers(); + midi_out_device_init(); midi_in_device_init(); @@ -523,6 +701,16 @@ sound_reset(void) sound_handlers_num = 0; memset(sound_handlers, 0x00, 8 * sizeof(sound_handler_t)); + timer_add(&music_poll_timer, music_poll, NULL, 1); + + music_handlers_num = 0; + memset(music_handlers, 0x00, 8 * sizeof(sound_handler_t)); + + timer_add(&wavetable_poll_timer, wavetable_poll, NULL, 1); + + wavetable_handlers_num = 0; + memset(wavetable_handlers, 0x00, 8 * sizeof(sound_handler_t)); + filter_cd_audio = NULL; filter_cd_audio_p = NULL; diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c index 0d9e7d909..9b341f574 100644 --- a/src/sound/xaudio2.c +++ b/src/sound/xaudio2.c @@ -51,6 +51,8 @@ static int initialized = 0; static IXAudio2 *xaudio2 = NULL; static IXAudio2MasteringVoice *mastervoice = NULL; static IXAudio2SourceVoice *srcvoice = NULL; +static IXAudio2SourceVoice *srcvoicemusic = NULL; +static IXAudio2SourceVoice *srcvoicewt = NULL; static IXAudio2SourceVoice *srcvoicemidi = NULL; static IXAudio2SourceVoice *srcvoicecd = NULL; @@ -164,24 +166,38 @@ inital(void) return; } + fmt.nSamplesPerSec = MUSIC_FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + + (void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemusic, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + + fmt.nSamplesPerSec = WT_FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + + (void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicewt, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + 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); + (void) 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); + (void) IXAudio2SourceVoice_SetVolume(srcvoice, 1, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_Start(srcvoice, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_Start(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_Start(srcvoicemusic, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_Start(srcvoicewt, 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)) { + if ((strcmp(mdn, "none") != 0) && (strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME) != 0)) { 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); + (void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + (void) IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); } initialized = 1; @@ -194,17 +210,23 @@ 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); + (void) IXAudio2SourceVoice_Stop(srcvoice, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoice); + (void) IXAudio2SourceVoice_Stop(srcvoicemusic, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemusic); + (void) IXAudio2SourceVoice_Stop(srcvoicewt, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicewt); + (void) IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd); if (srcvoicemidi) { - IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); - IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); + (void) IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); IXAudio2SourceVoice_DestroyVoice(srcvoicemidi); } - IXAudio2SourceVoice_DestroyVoice(srcvoice); + IXAudio2SourceVoice_DestroyVoice(srcvoicewt); IXAudio2SourceVoice_DestroyVoice(srcvoicecd); + IXAudio2SourceVoice_DestroyVoice(srcvoicemusic); + IXAudio2SourceVoice_DestroyVoice(srcvoice); IXAudio2MasteringVoice_DestroyVoice(mastervoice); IXAudio2_Release(xaudio2); srcvoice = srcvoicecd = srcvoicemidi = NULL; @@ -218,12 +240,13 @@ closeal(void) } void -givealbuffer_common(void *buf, IXAudio2SourceVoice *sourcevoice, size_t buflen) +givealbuffer_common(const void *buf, IXAudio2SourceVoice *sourcevoice, const size_t buflen) { if (!initialized) return; - IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double) sound_gain / 20.0), XAUDIO2_COMMIT_NOW); + (void) 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) { @@ -240,31 +263,43 @@ givealbuffer_common(void *buf, IXAudio2SourceVoice *sourcevoice, size_t buflen) buffer.PlayBegin = buffer.PlayLength = 0; buffer.PlayLength = buflen >> 1; buffer.pContext = (void *) buffer.pAudioData; - IXAudio2SourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, NULL); + (void) IXAudio2SourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, NULL); } void -givealbuffer(void *buf) +givealbuffer(const void *buf) { givealbuffer_common(buf, srcvoice, BUFLEN << 1); } void -givealbuffer_cd(void *buf) +givealbuffer_music(const void *buf) +{ + givealbuffer_common(buf, srcvoicemusic, MUSICBUFLEN << 1); +} + +void +givealbuffer_wt(const void *buf) +{ + givealbuffer_common(buf, srcvoicewt, WTBUFLEN << 1); +} + +void +givealbuffer_cd(const void *buf) { if (srcvoicecd) givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1); } void -al_set_midi(int freq, int buf_size) +al_set_midi(const int freq, const int buf_size) { midi_freq = freq; midi_buf_size = buf_size; if (initialized && srcvoicemidi) { - IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); - IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); + (void) IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); IXAudio2SourceVoice_DestroyVoice(srcvoicemidi); srcvoicemidi = NULL; WAVEFORMATEX fmt; @@ -280,13 +315,13 @@ al_set_midi(int freq, int buf_size) 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) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + (void) IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); } } void -givealbuffer_midi(void *buf, uint32_t size) +givealbuffer_midi(const void *buf, const uint32_t size) { givealbuffer_common(buf, srcvoicemidi, size); } diff --git a/src/thread.cpp b/src/thread.cpp index 1b4311f37..f2a0ceaf0 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -14,9 +14,10 @@ struct event_cpp11_t { extern "C" { thread_t * -thread_create(void (*thread_rout)(void *param), void *param) +thread_create_named(void (*thread_rout)(void *param), void *param, const char *name) { - auto thread = new std::thread([thread_rout, param] { + auto thread = new std::thread([thread_rout, param, name] { + plat_set_thread_name(NULL, name); thread_rout(param); }); return thread; diff --git a/src/timer.c b/src/timer.c index fa8376bde..d7102ffc3 100644 --- a/src/timer.c +++ b/src/timer.c @@ -94,6 +94,7 @@ timer_disable(pc_timer_t *timer) fatal("timer_disable - !timer->next\n"); timer->flags &= ~TIMER_ENABLED; + timer->in_callback = 0; if (timer->prev) timer->prev->next = timer->next; @@ -127,11 +128,15 @@ timer_process(void) 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. */ + 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->in_callback = 1; timer->callback(timer->priv); + timer->in_callback = 0; + } } timer_target = timer_head->ts.ts32.integer; @@ -171,10 +176,11 @@ timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start { memset(timer, 0, sizeof(pc_timer_t)); - timer->callback = callback; - timer->priv = priv; - timer->flags = 0; - timer->prev = timer->next = NULL; + timer->callback = callback; + timer->in_callback = 0; + timer->priv = priv; + timer->flags = 0; + timer->prev = timer->next = NULL; if (start_timer) timer_set_delay_u64(timer, 0); } @@ -189,6 +195,7 @@ timer_stop(pc_timer_t *timer) timer->period = 0.0; timer_disable(timer); timer->flags &= ~TIMER_SPLIT; + timer->in_callback = 0; } static void @@ -240,7 +247,9 @@ timer_on_auto(pc_timer_t *timer, double period) return; if (period > 0.0) - timer_on(timer, period, timer->period <= 0.0); + /* If the timer is in the callback, signal that, so that timer_advance_u64() + is used instead of timer_set_delay_u64(). */ + timer_on(timer, period, (timer->period <= 0.0) && !timer->in_callback); else timer_stop(timer); } diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 43c730315..aa4cc84e2 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -17,7 +17,7 @@ # Copyright 2021-2022 Jasmine Iwanek. # -add_library(plat OBJECT unix.c unix_serial_passthrough.c) +add_library(plat OBJECT unix.c unix_serial_passthrough.c unix_netsocket.c) if (NOT CPPTHREADS) target_sources(plat PRIVATE unix_thread.c) diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index a7e4786be..fdd7bbf55 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver 4.1 Name: 86Box -Version: 4.1 +Version: 4.2 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Mon Oct 16 2023 Robert de Rooy 4.1-1 +* Sat Mar 23 2024 Robert de Rooy 4.2-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 9e2c5dc88..18df49703 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -4,13 +4,14 @@ CC0-1.0 GPL-2.0-or-later 86Box + 86Box developers An emulator for classic IBM PC clones - Emulation + Emulator net.86box.86Box.desktop - + diff --git a/src/unix/unix.c b/src/unix/unix.c index ecd17cadb..3eddc2bbb 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -45,6 +45,9 @@ #include <86box/ui.h> #include <86box/gdbstub.h> +#define __USE_GNU 1 /* shouldn't be done, yet it is */ +#include + static int first_use = 1; static uint64_t StartingTime; static uint64_t Frequency; @@ -60,7 +63,6 @@ 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; @@ -244,37 +246,33 @@ wchar_t * plat_get_string(int i) { switch (i) { - case IDS_2077: + case STRING_MOUSE_CAPTURE: return L"Click to capture mouse"; - case IDS_2078: + case STRING_MOUSE_RELEASE: return L"Press CTRL-END to release mouse"; - case IDS_2079: + case STRING_MOUSE_RELEASE_MMB: return L"Press CTRL-END or middle button to release mouse"; - case IDS_2131: + case STRING_INVALID_CONFIG: return L"Invalid configuration"; - case IDS_4099: + case STRING_NO_ST506_ESDI_CDROM: return L"MFM/RLL or ESDI CD-ROM drives never existed"; - case IDS_2094: - return L"Failed to set up PCap"; - case IDS_2095: + case STRING_PCAP_ERROR_NO_DEVICES: return L"No PCap devices found"; - case IDS_2096: + case STRING_PCAP_ERROR_INVALID_DEVICE: return L"Invalid PCap device"; - case IDS_2112: - return L"Unable to initialize SDL, libsdl2 is required"; - case IDS_2133: + case STRING_GHOSTSCRIPT_ERROR_DESC: 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_2130: + case STRING_PCAP_ERROR_DESC: return L"Make sure libpcap is installed and that you are on a libpcap-compatible network connection."; - case IDS_2115: + case STRING_GHOSTSCRIPT_ERROR_TITLE: return L"Unable to initialize Ghostscript"; - case IDS_2063: + case STRING_HW_NOT_AVAILABLE_MACHINE: return L"Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."; - case IDS_2064: + case STRING_HW_NOT_AVAILABLE_VIDEO: 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_2129: + case STRING_HW_NOT_AVAILABLE_TITLE: return L"Hardware not available"; - case IDS_2143: + case STRING_MONITOR_SLEEP: return L"Monitor in sleep mode"; } return L""; @@ -448,12 +446,6 @@ plat_get_ticks(void) return (uint32_t) (plat_get_ticks_common() / 1000); } -uint32_t -plat_get_micro_ticks(void) -{ - return (uint32_t) plat_get_ticks_common(); -} - void plat_remove(char *path) { @@ -578,9 +570,9 @@ main_thread(void *param) /* 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); + plat_resize(fixed_size_x, fixed_size_y, 0); else - plat_resize(scrnsz_x, scrnsz_y); + plat_resize(scrnsz_x, scrnsz_y, 0); atomic_store(&doresize_monitors[0], 1); } } @@ -644,14 +636,8 @@ ui_msgbox_header(int flags, void *header, void *message) SDL_MessageBoxData msgdata; SDL_MessageBoxButtonData msgbtn; -#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); + header = (void *) ((flags & MBX_ANSI) ? "86Box" : L"86Box"); msgbtn.buttonid = 1; msgbtn.text = "OK"; @@ -699,7 +685,7 @@ plat_get_exe_name(char *s, int size) void plat_power_off(void) { - confirm_exit = 0; + confirm_exit_cmdl = 0; nvr_save(); config_save(); @@ -762,10 +748,13 @@ plat_pause(int p) static wchar_t oldtitle[512]; wchar_t title[512]; + if ((!!p) == dopause) + return; + if ((p == 0) && (time_sync & TIME_SYNC_ENABLED)) nvr_time_sync(); - dopause = p; + do_pause(p); if (p) { wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1); wcscpy(title, oldtitle); @@ -816,7 +805,7 @@ plat_init_rom_paths(void) 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) { + 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); @@ -830,7 +819,7 @@ plat_init_rom_paths(void) rom_add_path("/usr/share/86Box/roms/"); } #else - char default_rom_path[1024] = { '\0 ' }; + char default_rom_path[1024] = { '\0' }; getDefaultROMPath(default_rom_path); rom_add_path(default_rom_path); #endif @@ -914,12 +903,16 @@ monitor_thread(void *param) while (!exit_event) { if (feof(stdin)) break; +#ifdef ENABLE_READLINE if (f_readline) line = f_readline("(86Box) "); else { +#endif printf("(86Box) "); - !getline(&line, &n, stdin); + (void) !getline(&line, &n, stdin); +#ifdef ENABLE_READLINE } +#endif if (line) { int cmdargc = 0; char *linecpy; @@ -1160,9 +1153,12 @@ main(int argc, char **argv) { SDL_Event event; void *libedithandle; + int ret = 0; SDL_Init(0); - pc_init(argc, argv); + ret = pc_init(argc, argv); + if (ret == 0) + return 0; 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(); @@ -1197,7 +1193,7 @@ main(int argc, char **argv) pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ - // plat_pause(0); + plat_pause(0); /* Initialize the rendering window, or fullscreen. */ @@ -1350,12 +1346,6 @@ plat_vidapi_name(int i) return "default"; } -void -set_language(uint32_t id) -{ - lang_id = id; -} - /* Sets up the program language before initialization. */ uint32_t plat_language_code(char *langcode) @@ -1371,6 +1361,24 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { strncpy(outbuf, cpu_string, len); } +void +plat_set_thread_name(void *thread, const char *name) +{ +#ifdef __APPLE__ + if (thread) /* Apple pthread can only set self's name */ + return; + char truncated[64]; +#else + char truncated[16]; +#endif + strncpy(truncated, name, sizeof(truncated) - 1); +#ifdef __APPLE__ + pthread_setname_np(truncated); +#else + pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); +#endif +} + /* Converts back the language code to LCID */ void plat_language_code_r(uint32_t lcid, char *outbuf, int len) diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 424f1a9a3..61813a754 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -145,6 +145,8 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); + if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\')) + fn[strlen(fn) - 1] = '/'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) diff --git a/src/unix/unix_netsocket.c b/src/unix/unix_netsocket.c new file mode 100644 index 000000000..d626d025b --- /dev/null +++ b/src/unix/unix_netsocket.c @@ -0,0 +1,203 @@ +#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/plat_netsocket.h> +#include <86box/ui.h> + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SOCKET +plat_netsocket_create(int type) +{ + SOCKET fd = -1; + int yes = 1; + + if (type != NET_SOCKET_TCP) + return -1; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return -1; + + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &yes, sizeof(yes)); + + return fd; +} + +SOCKET +plat_netsocket_create_server(int type, unsigned short port) +{ + struct sockaddr_in sock_addr; + SOCKET fd = -1; + int yes = 1; + + if (type != NET_SOCKET_TCP) + return -1; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return -1; + + memset(&sock_addr, 0, sizeof(struct sockaddr_in)); + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = INADDR_ANY; + sock_addr.sin_port = htons(port); + + if (bind(fd, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_in)) == -1) { + plat_netsocket_close(fd); + return (SOCKET) -1; + } + + if (listen(fd, 5) == -1) { + plat_netsocket_close(fd); + return (SOCKET) -1; + } + + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &yes, sizeof(yes)); + + return fd; +} + +void +plat_netsocket_close(SOCKET socket) +{ + close((SOCKET) socket); +} + +SOCKET +plat_netsocket_accept(SOCKET socket) +{ + SOCKET clientsocket = accept(socket, NULL, NULL); + + if (clientsocket == -1) + return -1; + + return clientsocket; +} + +int +plat_netsocket_connected(SOCKET socket) +{ + struct sockaddr addr; + socklen_t len = sizeof(struct sockaddr); + fd_set wrfds; + struct timeval tv; + int res = -1; + int status = 0; + socklen_t optlen = 4; + + FD_ZERO(&wrfds); + FD_SET(socket, &wrfds); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + res = select(socket + 1, NULL, &wrfds, NULL, &tv); + + if (res == -1) + return -1; + + if (res == 0 || !(res >= 1 && FD_ISSET(socket, &wrfds))) + return 0; + + res = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *) &status, &optlen); + + if (res == -1) + return -1; + + if (status != 0) + return -1; + + if (getpeername(socket, &addr, &len) == -1) + return -1; + + return 1; +} + +int +plat_netsocket_connect(SOCKET socket, const char *hostname, unsigned short port) +{ + struct sockaddr_in sock_addr; + int res = -1; + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = inet_addr(hostname); + sock_addr.sin_port = htons(port); + + if (sock_addr.sin_addr.s_addr == ((in_addr_t) -1) || sock_addr.sin_addr.s_addr == 0) { + struct hostent *hp; + + hp = gethostbyname(hostname); + + if (hp) + memcpy(&sock_addr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); + else + return -1; + } + + res = connect(socket, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_in)); + + if (res == -1) { + int error = errno; + + if (error == EISCONN || error == EWOULDBLOCK || error == EAGAIN || error == EINPROGRESS) + return 0; + + res = -1; + } + return res; +} + +int +plat_netsocket_send(SOCKET socket, const unsigned char *data, unsigned int size, int *wouldblock) +{ + int res = send(socket, (const char *) data, size, 0); + + if (res == -1) { + int error = errno; + + if (wouldblock) + *wouldblock = !!(error == EWOULDBLOCK || error == EAGAIN); + + return -1; + } + return res; +} + +int +plat_netsocket_receive(SOCKET socket, unsigned char *data, unsigned int size, int *wouldblock) +{ + int res = recv(socket, (char *) data, size, 0); + + if (res == -1) { + int error = errno; + + if (wouldblock) + *wouldblock = !!(error == EWOULDBLOCK || error == EAGAIN); + + return -1; + } + return res; +} diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index 3ba8c1ae0..c7cc898be 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -424,9 +424,9 @@ sdl_init_common(int flags) sdl_set_fs(video_fullscreen); if (!(video_fullscreen & 1)) { if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); + plat_resize(fixed_size_x, fixed_size_y, 0); else - plat_resize(scrnsz_x, scrnsz_y); + plat_resize(scrnsz_x, scrnsz_y, 0); } if ((vid_resize < 2) && window_remember) { SDL_SetWindowSize(sdl_win, window_w, window_h); @@ -479,7 +479,7 @@ plat_mouse_capture(int on) } void -plat_resize(int w, int h) +plat_resize(int w, int h, UNUSED(int monitor_index)) { SDL_LockMutex(sdl_mutex); resize_w = w; diff --git a/src/unix/unix_serial_passthrough.c b/src/unix/unix_serial_passthrough.c index d80f8a1e7..0184ebbc0 100644 --- a/src/unix/unix_serial_passthrough.c +++ b/src/unix/unix_serial_passthrough.c @@ -22,7 +22,7 @@ # define _BSD_SOURCE 1 #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# define __BSD_VISIBLE 1 +# define __BSD_VISIBLE 1 #endif #include #include @@ -112,7 +112,7 @@ plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data) if (dev->mode == SERPT_MODE_HOSTSER) { do { res = write(dev->master_fd, &data, 1); - } while (res == 0 || (res == -1 && (errno == EAGAIN || res == EWOULDBLOCK))); + } while (res == 0 || (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))); } else res = write(dev->master_fd, &data, 1); } diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c index 0c2e9bf6b..88ce01456 100644 --- a/src/unix/unix_thread.c +++ b/src/unix/unix_thread.c @@ -32,7 +32,7 @@ thread_run_wrapper(thread_param *arg) } thread_t * -thread_create(void (*thread_rout)(void *param), void *param) +thread_create_named(void (*thread_rout)(void *param), void *param, const char *name) { pthread_t *thread = malloc(sizeof(pthread_t)); thread_param *thrparam = malloc(sizeof(thread_param)); @@ -40,6 +40,7 @@ thread_create(void (*thread_rout)(void *param), void *param) thrparam->param = param; pthread_create(thread, NULL, (void *(*) (void *) ) thread_run_wrapper, thrparam); + plat_set_thread_name(thread, name); return thread; } @@ -51,7 +52,7 @@ thread_wait(thread_t *arg) } event_t * -thread_create_event() +thread_create_event(void) { event_pthread_t *event = malloc(sizeof(event_pthread_t)); diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 59205f235..c8fb7021d 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -19,23 +19,15 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.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_mach8.c vid_ati_mach64.c vid_ati68875_ramdac.c - vid_ati68860_ramdac.c vid_bt48x_ramdac.c + vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_chips_69000.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c vid_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c 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) - target_sources(vid PRIVATE vid_mga.c) -endif() - -if(VGAWONDER) - target_compile_definitions(vid PRIVATE USE_VGAWONDER) -endif() + vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c + vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c + vid_bochs_vbe.c) if(XL24) target_compile_definitions(vid PRIVATE USE_XL24) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 955199970..ff1470164 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -38,8 +38,14 @@ #include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> #include "cpu.h" +#ifdef ATI_8514_ULTRA +#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140.BIN" +#endif + 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); @@ -63,6 +69,27 @@ ibm8514_log(const char *fmt, ...) # define ibm8514_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_WORD(cx, n) \ if ((cmd <= 1) || (cmd == 5)) { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ @@ -221,7 +248,7 @@ ibm8514_cpu_dest(svga_t *svga) } void -ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint16_t val, int len) +ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t nibble = 0; @@ -447,35 +474,34 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + if (port != 0x9ae8 && port != 0xe2e8) + ibm8514_log("Port OUT FIFO=%04x, val=%04x, len=%d.\n", port, val, len); + switch (port) { case 0x82e8: case 0xc2e8: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else { + else dev->accel.cur_y = val & 0x7ff; - } break; case 0x82e9: case 0xc2e9: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: case 0xc6e8: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else { + else dev->accel.cur_x = val & 0x7ff; - } break; case 0x86e9: case 0xc6e9: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); - } break; case 0x8ae8: @@ -483,6 +509,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; else { + dev->accel.desty = val & 0x07ff; dev->accel.desty_axstp = val & 0x3fff; if (val & 0x2000) dev->accel.desty_axstp |= ~0x1fff; @@ -502,6 +529,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; else { + dev->accel.destx = val & 0x07ff; dev->accel.destx_distp = val & 0x3fff; if (val & 0x2000) dev->accel.destx_distp |= ~0x1fff; @@ -544,6 +572,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0x700) | val; else { dev->accel.maj_axis_pcnt = val & 0x7ff; + dev->accel.maj_axis_pcnt_no_limit = val; } break; case 0x96e9: @@ -566,6 +595,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; } + ibm8514_log("8514/A CMD=%04x.\n", dev->accel.cmd); ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; @@ -737,16 +767,19 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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) { + 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) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - if (val & 0x400) - dev->accel.clip_left |= ~0x3ff; - } + + 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; + + ibm8514_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch); if (port == 0xfee8) dev->accel.cmd_back = 1; else @@ -758,6 +791,12 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) 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 (port == 0xfee9) dev->accel.cmd_back = 1; else @@ -848,128 +887,128 @@ static void ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t old = 0; - if (port & 0x8000) { + if (port & 0x8000) ibm8514_accel_out_fifo(svga, port, val, len); - } else { + 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); - } + WRITE8(port, dev->htotal, val); break; case 0x6e8: - dev->hdisp = val; - ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); - svga_recalctimings(svga); + case 0x6e9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } + } + ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d, advfunc=%x.\n", dev->hdisp, dev->accel.advfunc_cntl & 4); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07); + } + } ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0xee8: + case 0xee9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; + } + } 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); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->vtotal = dev->v_total_reg; + dev->vtotal++; } 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); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; } + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); 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); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->vsyncstart = dev->v_sync_start; + dev->vsyncstart++; } break; case 0x1ee8: - dev->vsyncwidth = val; + case 0x1ee9: 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); + ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); break; case 0x42e8: - if (len == 1) { - dev->subsys_stat &= ~val; - } else { - dev->subsys_stat &= ~(val & 0xff); - dev->subsys_cntl = (val >> 8); - } + old = dev->subsys_stat; + if (val & 1) + dev->subsys_stat &= ~1; + if (val & 2) + dev->subsys_stat &= ~2; + if (val & 4) + dev->subsys_stat &= ~4; + if (val & 8) + dev->subsys_stat &= ~8; break; case 0x42e9: - if (len == 1) { - dev->subsys_cntl = val; - } + old = dev->subsys_cntl; + dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; break; case 0x4ae8: - if (!val) - break; - dev->accel.advfunc_cntl = val & 0x0f; - dev->on[0] = val & 0x01; - vga_on = !dev->on[0]; - ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + case 0x4ae9: + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + vga_on = !dev->on[port & 1]; + dev->vendor_mode[port & 1] = 0; + ibm8514_log("IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; + default: break; } @@ -1006,16 +1045,16 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -1038,6 +1077,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) break; case 0x42e8: + cmd = dev->accel.cmd >> 13; vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; @@ -1058,10 +1098,21 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) temp |= 0x80; break; + case 0x82e8: + case 0xc2e8: + if (len != 1) + temp = dev->accel.cur_y; + break; + + case 0x86e8: + case 0xc6e8: + if (len != 1) + temp = dev->accel.cur_x; + break; + case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x9ae8: @@ -1178,8 +1229,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat 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; + int and3 = dev->accel.cur_x & 3; if (!dev->bpp) { compare &= 0xff; @@ -1298,9 +1348,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_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)*/ - if (dev->accel.cmd == 0x53b1 && !cpu_dat) - ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x, cpu=%08x, frgdmix=%02x, bkgdmix=%02x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6, cpu_dat, dev->accel.frgd_mix, dev->accel.bkgd_mix); - switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (dev->accel.ssv_state == 0) @@ -1517,15 +1564,15 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x >= 0x600) { + if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - } - if (dev->accel.cur_y >= 0x600) { + + if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - } dev->accel.sy = dev->accel.maj_axis_pcnt; + ibm8514_log("Line Draw 8514/A, frgdmix=%d, bkgdmix=%d, c(%d,%d), pixcntl=%d, sy=%d, polyfill=%x, selfrmix=%02x, selbkmix=%02x, bkgdcol=%02x, frgdcol=%02x, clipt=%d, clipb=%d.\n", frgd_mix, bkgd_mix, dev->accel.cx, dev->accel.cy, pixcntl, dev->accel.sy, dev->accel.multifunc[0x0a] & 6, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, bkgd_color, frgd_color, dev->accel.clip_top, clip_b); if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { if (dev->accel.cmd & 8) { @@ -1585,7 +1632,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); - } else + } else { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1603,6 +1650,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat default: break; } + } READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); @@ -1784,70 +1832,34 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat 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: + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) dev->accel.cy++; - break; - case 0xe0: - dev->accel.cy++; - break; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } dev->accel.sy--; @@ -1908,74 +1920,37 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else cpu_dat >>= 8; - if (dev->accel.sy == 0) { + 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: + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) dev->accel.cy++; - break; - case 0xe0: - dev->accel.cy++; - break; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } dev->accel.sy--; @@ -2009,13 +1984,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) 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) @@ -2061,7 +2034,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.output = 1; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) 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; @@ -2075,7 +2048,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 2) && (frgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.input = 1; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) 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; @@ -2219,15 +2192,14 @@ rect_fill_pix: dev->accel.sx--; if (dev->accel.sx < 0) { dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (and3 == 1) { + if (and3 == 1) dev->accel.sx += 4; - } else if (and3 == 2) { + else if (and3 == 2) dev->accel.sx += 5; - } else if (and3 == 3) { + else if (and3 == 3) dev->accel.sx += 6; - } else { + else dev->accel.sx += 3; - } if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx + 1); @@ -2258,10 +2230,11 @@ rect_fill_pix: break; } - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) 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; } @@ -2343,7 +2316,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2435,7 +2408,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2494,7 +2467,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { 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 { @@ -2519,7 +2492,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { 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 { @@ -2575,7 +2548,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { 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 { @@ -2600,7 +2573,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) { + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) { 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 { @@ -2690,7 +2663,7 @@ rect_fill_pix: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2767,7 +2740,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2782,7 +2755,7 @@ rect_fill: } else { dev->accel.temp_cnt = 8; while (count-- && dev->accel.sy >= 0) { - if (dev->accel.temp_cnt == 0) { + if (!dev->accel.temp_cnt) { dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } @@ -2838,7 +2811,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -2854,95 +2827,78 @@ rect_fill: } } } else { - if (dev->accel.multifunc[0x0a] & 6) { - while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.multifunc[0x0a] & 6) == 4) { + 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; - } + READ(dev->accel.dest + dev->accel.cx, mix_dat); + if ((mix_dat & rd_mask_polygon) == rd_mask_polygon) + dev->accel.fill_state = !dev->accel.fill_state; + READ(dev->accel.dest + dev->accel.cx, dest_dat); + old_dest_dat = dest_dat; 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); + if (!(rd_mask_polygon & 1) && (wrt_mask & 1)) { + MIX(mix_dat ^ rd_mask_polygon, dest_dat, mix_dat); + ibm8514_log("Filling c(%d,%d) without bit 0 of rdmask=%02x, wrtmask=%02x, mixdat=%02x, dest=%02x, old=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, old_dest_dat); + dest_dat &= ~rd_mask_polygon; + } else if ((rd_mask_polygon & 1) && (wrt_mask & 1)) { + ibm8514_log("Filling c(%d,%d) with bit 0 of rdmask=%02x, wrtmask=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask); + dest_dat &= ~(rd_mask_polygon & wrt_mask); } + } else { + if (!(rd_mask_polygon & 1) && (wrt_mask & 1)) + dest_dat &= ~rd_mask_polygon; + else if ((rd_mask_polygon & 1) && (wrt_mask & 1)) + dest_dat &= ~(rd_mask_polygon & wrt_mask); + } + + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + 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))) { + ibm8514_log("Results c(%d,%d):rdmask=%02x, wrtmask=%02x, mix=%02x, destdat=%02x, nowrite=%d.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, dev->accel.cx_back); + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); } } - mix_dat <<= 1; - mix_dat |= 1; - - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx++; - } else { + 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; + dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else { + else dev->accel.cx += (dev->accel.sx) + 1; - } if (dev->accel.cmd & 0x80) dev->accel.cy++; else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && 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.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; + ibm8514_log(".\n"); return; } } } } else { + ibm8514_log("Rectangle Fill Normal CMD=%04x, CURRENT(%d,%d), sx=%d, FR(%02x), linedraw=%d.\n", dev->accel.cmd, dev->accel.cx, dev->accel.cy, dev->accel.sx, frgd_color, dev->accel.linedraw); 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; + if (!bkgd_mix && (dev->accel.cmd & 0x40) && ((dev->accel.frgd_mix & 0x1f) == 7) && ((dev->accel.bkgd_mix & 0x1f) == 3) && !dev->bpp && (bkgd_color == 0x00)) /*For some reason, the September 1992 Mach8/32 drivers for Win3.x don't set the background colors properly.*/ + src_dat = frgd_color; break; case 1: src_dat = frgd_color; @@ -2958,13 +2914,17 @@ rect_fill: 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.cmd & 0x10) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } } } @@ -2978,11 +2938,12 @@ rect_fill: dev->accel.sx--; if (dev->accel.sx < 0) { + dev->accel.fill_state = 0; dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else + else dev->accel.cx += (dev->accel.sx) + 1; if (dev->accel.cmd & 0x80) @@ -2990,7 +2951,7 @@ rect_fill: else dev->accel.cy--; - if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && (dev->accel_bpp == 24)) + if (((dev->local & 0xff) >= 0x02) && dev->accel.ge_offset && ((dev->accel_bpp == 24) || (dev->accel_bpp == 8))) dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); else dev->accel.dest = dev->accel.cy * dev->pitch; @@ -3010,17 +2971,25 @@ rect_fill: } break; - case 5: /*Draw Polygon Boundary Line*/ + 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; - + dev->accel.cy = dev->accel.cur_y; if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - dev->accel.oldcy = dev->accel.cy; - dev->accel.sy = 0; + + dev->accel.sy = dev->accel.maj_axis_pcnt_no_limit; + + if (dev->accel.cmd & 0x80) + dev->accel.oldcy = dev->accel.cy + 1; + else + dev->accel.oldcy = dev->accel.cy - 1; + + dev->accel.oldcx = 0; + + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cur_x_nolimit, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.clip_left, clip_r, dev->accel.clip_top, clip_b, compare_mode, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -3033,160 +3002,200 @@ rect_fill: } } - 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; + if (dev->accel.cmd & 8) { + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.cx < 0) + dev->accel.cx = 0; + if (dev->accel.cy < 0) + dev->accel.cy = 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 & 0x10) { + if (dev->accel.sy && (dev->accel.cmd & 4)) { + if (dev->accel.oldcy != dev->accel.cy) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else if (!(dev->accel.cmd & 4)) { + if (dev->accel.oldcy != dev->accel.cy) { + 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) + break; + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; break; - case 1: - src_dat = frgd_color; + case 0x20: + dev->accel.cx++; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; break; - case 2: - src_dat = cpu_dat; + case 0x40: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; break; - case 3: - src_dat = 0; + case 0x60: + dev->accel.cx--; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; break; default: break; } - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + dev->accel.sy--; + } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if (dev->accel.cx < 0) + dev->accel.cx = 0; + if (dev->accel.cy < 0) + dev->accel.cy = 0; - 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); - } + 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 & 0x14) == 0x14) { + if (dev->accel.sy) { + if (dev->accel.cmd & 0x40) { + 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); + if (dev->accel.oldcy != dev->accel.cy) { + 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; + 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++; + if (!dev->accel.sy) 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; + if (dev->accel.cmd & 0x40) { + if (dev->accel.cmd & 0x80) 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; + else + dev->accel.cy--; - default: - break; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + } else + dev->accel.err_term += dev->accel.desty_axstp; + } else { + if (dev->accel.cmd & 0x20) + dev->accel.cx++; + else + dev->accel.cx--; + + dev->accel.oldcy = dev->accel.cy; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + if (dev->accel.cmd & 0x80) + dev->accel.cy++; + else + dev->accel.cy--; + } else + dev->accel.err_term += dev->accel.desty_axstp; } - } else - dev->accel.err_term += dev->accel.desty_axstp; - dev->accel.sy++; + dev->accel.sy--; + } } - break; + } + break; - case 6: /*BitBlt*/ + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { dev->accel.x_count = 0; @@ -3195,12 +3204,12 @@ rect_fill: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - dev->accel.dx = dev->accel.destx_distp; - dev->accel.dy = dev->accel.desty_axstp; + dev->accel.dx = dev->accel.destx; + dev->accel.dy = dev->accel.desty; - if (dev->accel.destx_distp >= 0x600) + if (dev->accel.destx >= 0x600) dev->accel.dx |= ~0x5ff; - if (dev->accel.desty_axstp >= 0x600) + if (dev->accel.desty >= 0x600) dev->accel.dy |= ~0x5ff; dev->accel.cx = dev->accel.cur_x; @@ -3213,6 +3222,7 @@ rect_fill: dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.fill_state = 0; if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { @@ -3277,6 +3287,7 @@ bitblt_pix: 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); @@ -3410,8 +3421,8 @@ bitblt_pix: 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 = dev->accel.destx; + if (dev->accel.destx >= 0x600) dev->accel.dx |= ~0x5ff; } } @@ -3441,6 +3452,7 @@ 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); @@ -3695,6 +3707,7 @@ bitblt: 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); @@ -3713,6 +3726,7 @@ bitblt: return; } + ibm8514_log("BitBLT 8514/A=%04x, selfrmix=%d, selbkmix=%d, d(%d,%d), c(%d,%d), pixcntl=%d, sy=%d, frgdmix=%02x, bkgdmix=%02x, rdmask=%02x, wrtmask=%02x, linedraw=%d.\n", dev->accel.cmd, frgd_mix, bkgd_mix, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, pixcntl, dev->accel.sy, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, dev->accel.rd_mask, wrt_mask, dev->accel.linedraw); 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)) { @@ -3740,7 +3754,7 @@ bitblt: case 3: READ(dev->accel.src + dev->accel.cx, src_dat); if (pixcntl == 3) { - if (dev->accel.cmd & 0x10) { + if ((dev->accel.cmd & 0x10) && !(dev->accel.cmd & 0x40)) { src_dat = ((src_dat & rd_mask) == rd_mask); } } @@ -3756,7 +3770,6 @@ bitblt: 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); @@ -3779,15 +3792,18 @@ bitblt: dev->accel.sx--; if (dev->accel.sx < 0) { + dev->accel.fill_state = 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; - } + dev->accel.dx = dev->accel.destx; + + if (dev->accel.destx >= 0x600) + dev->accel.dx |= ~0x5ff; + + dev->accel.cx = dev->accel.cur_x; + + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; if (dev->accel.cmd & 0x80) { dev->accel.dy++; @@ -3801,9 +3817,8 @@ bitblt: dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; - if (dev->accel.sy < 0) { + if (dev->accel.sy < 0) return; - } } } } @@ -3816,6 +3831,25 @@ bitblt: } } +void +ibm8514_render_blank(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + uint32_t *line_ptr = &svga->monitor->target_buffer->line[dev->displine + svga->y_add][svga->x_add]; + uint32_t line_width = (uint32_t)(dev->h_disp) * sizeof(uint32_t); + + if (dev->h_disp > 0) + memset(line_ptr, 0, line_width); +} + void ibm8514_render_8bpp(svga_t *svga) { @@ -3823,9 +3857,8 @@ ibm8514_render_8bpp(svga_t *svga) uint32_t *p; uint32_t dat; - if ((dev->displine + svga->y_add) < 0) { + 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]; @@ -4036,7 +4069,7 @@ ibm8514_render_ABGR8888(svga_t *svga) } void -ibm8514_render_RGBA8888(svga_t *svga) +ibm8514_render_32bpp(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int x; @@ -4046,7 +4079,7 @@ ibm8514_render_RGBA8888(svga_t *svga) if ((dev->displine + svga->y_add) < 0) return; - if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { + if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; if (dev->firstline_draw == 2000) @@ -4055,7 +4088,7 @@ ibm8514_render_RGBA8888(svga_t *svga) for (x = 0; x <= dev->h_disp; x++) { dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]); - *p++ = dat >> 8; + p[x] = dat & 0xffffff; } dev->ma += (x * 4); dev->ma &= dev->vram_mask; @@ -4092,148 +4125,153 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) } void -ibm8514_poll(void *priv, svga_t *svga) +ibm8514_poll(void *priv) { - ibm8514_t *dev = (ibm8514_t *) priv; + svga_t *svga = (svga_t *)priv; + ibm8514_t *dev = (ibm8514_t *)svga->dev8514; 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); + ibm8514_log("IBM 8514/A poll.\n"); + if (dev->on[0] || dev->on[1]) { + ibm8514_log("ON!\n"); + 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->hwcursor_on) - dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2; + 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; + } - svga->render8514(svga); + timer_advance_u64(&svga->timer8514, dev->dispofftime); + svga->cgastat |= 1; + dev->linepos = 1; - 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->dispon) { + dev->hdisp_on = 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->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; } - 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; + 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->timer8514, dev->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->linepos = 0; + if (dev->dispon) { + if (dev->sc == dev->rowcount) { + dev->sc = 0; dev->maback += (dev->rowoffset << 3); - dev->maback &= dev->vram_mask; - dev->ma = dev->maback; - } else { - dev->sc++; - dev->sc &= 0x1f; - dev->ma = dev->maback; - } - } + if (dev->interlace) + dev->maback += (dev->rowoffset << 3); - 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]--; + dev->maback &= dev->vram_mask; + dev->ma = dev->maback; + } else { + dev->sc++; + dev->sc &= 0x1f; + dev->ma = dev->maback; + } } - if (svga->fullchange) - svga->fullchange--; - } - if (dev->vc == dev->v_syncstart) { - dev->dispon = 0; - svga->cgastat |= 8; - x = dev->h_disp; + dev->vc++; + dev->vc &= 0x7ff; - if (dev->interlace && !dev->oddeven) - dev->lastline++; - if (dev->interlace && dev->oddeven) - dev->firstline--; + if (dev->vc == dev->dispend) { + dev->dispon = 0; - wx = x; + for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { + if (dev->changedvram[x]) + dev->changedvram[x]--; + } - wy = dev->lastline - dev->firstline; - svga_doblit(wx, wy, svga); + if (svga->fullchange) + svga->fullchange--; + } + if (dev->vc == dev->v_syncstart) { + dev->dispon = 0; + svga->cgastat |= 8; + x = dev->h_disp; - dev->firstline = 2000; - dev->lastline = 0; + if (dev->interlace && !dev->oddeven) + dev->lastline++; + if (dev->interlace && dev->oddeven) + dev->firstline--; - dev->firstline_draw = 2000; - dev->lastline_draw = 0; + wx = x; + wy = dev->lastline - dev->firstline; + svga_doblit(wx, wy, svga); - dev->oddeven ^= 1; + dev->firstline = 2000; + dev->lastline = 0; - svga->monitor->mon_changeframecount = dev->interlace ? 3 : 2; - svga->vslines = 0; + dev->firstline_draw = 2000; + dev->lastline_draw = 0; - if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1); - else - dev->ma = dev->maback = 0; + dev->oddeven ^= 1; - 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->monitor->mon_changeframecount = dev->interlace ? 3 : 2; + svga->vslines = 0; - svga->x_add = (overscan_x >> 1); + if (dev->interlace && dev->oddeven) + dev->ma = dev->maback = (dev->rowoffset << 1); + else + dev->ma = dev->maback = 0; - dev->hwcursor_on = 0; - dev->hwcursor_latch = dev->hwcursor; + 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; + } } } } @@ -4243,48 +4281,41 @@ ibm8514_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (dev->on[0]) { - 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; + svga->render8514 = ibm8514_render_blank; +#ifdef ATI_8514_ULTRA + if (dev->extensions) { + if (svga->ext8514 != NULL) + ati8514_recalctimings(svga); + } else +#endif + { + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal; + dev->v_syncstart = dev->vsyncstart; + dev->dispend = dev->vdisp; + dev->rowcount = !!(dev->disp_cntl & 0x08); - if (dev->dispend == 598) - dev->dispend += 2; + if (dev->dispend == 766) + 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; + if (dev->accel.advfunc_cntl & 4) { + dev->pitch = 1024; + if (!dev->h_disp) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } 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; + dev->pitch = 640; + if (!dev->h_disp) { + dev->h_disp = 640; + dev->dispend = 480; + } + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } if (dev->interlace) { @@ -4297,11 +4328,10 @@ ibm8514_recalctimings(svga_t *svga) } dev->rowoffset = 0x80; - - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled); } - 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); } @@ -4338,6 +4368,19 @@ ibm8514_mca_feedb(void *priv) return dev->pos_regs[2] & 1; } +static void +ibm8514_mca_reset(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + ibm8514_log("MCA reset.\n"); + dev->on[0] = 0; + dev->on[1] = 0; + vga_on = 1; + ibm8514_mca_write(0x102, 0, svga); +} + static void * ibm8514_init(const device_t *info) { @@ -4348,23 +4391,70 @@ ibm8514_init(const device_t *info) ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); svga->dev8514 = dev; + svga->ext8514 = 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; dev->map8 = dev->pallook; + dev->local = 0; dev->type = info->flags; dev->bpp = 0; +#ifdef ATI_8514_ULTRA + dev->extensions = device_get_config_int("extensions"); + + switch (dev->extensions) { + case 1: + if (rom_present(BIOS_MACH8_ROM_PATH)) { + mach = (mach_t *) calloc(1, sizeof(mach_t)); + svga->ext8514 = mach; + ati8514_init(svga, svga->ext8514, svga->dev8514); + + if (dev->type & DEVICE_MCA) { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xc6800, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + dev->pos_regs[0] = 0x88; + dev->pos_regs[1] = 0x80; + mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); + ati_eeprom_load(&mach->eeprom, "ati8514_mca.nvr", 0); + } else { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xd0000, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0); + } + break; + } + fallthrough; + + default: + 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, ibm8514_mca_reset, svga); + } + break; + } +#else 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); + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); } +#endif + + timer_add(&svga->timer8514, ibm8514_poll, svga, 1); return svga; } @@ -4375,6 +4465,13 @@ ibm8514_close(void *priv) svga_t *svga = (svga_t *) priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; +#ifdef ATI_8514_ULTRA + mach_t *mach = (mach_t *) svga->ext8514; + + if (mach) + free(mach); +#endif + if (dev) { free(dev->vram); free(dev->changedvram); @@ -4399,6 +4496,34 @@ ibm8514_force_redraw(void *priv) svga->fullchange = changeframecount; } +#ifdef ATI_8514_ULTRA +// clang-format off +static const device_config_t ext8514_config[] = { + { + .name = "extensions", + .description = "Vendor", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "IBM", + .value = 0 + }, + { + .description = "ATI", + .value = 1 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; +#endif + // clang-format off const device_t gen8514_isa_device = { .name = "Generic 8514/A clone (ISA)", diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 5847faa39..7f0993ef8 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -32,21 +32,14 @@ #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" -#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_WONDER "roms/video/ati18800/VGA_Wonder_V3-1.02.bin" +#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 -#else - ATI18800_VGA88 = 0, - ATI18800_EDGE16 -#endif }; typedef struct ati18800_t { @@ -57,6 +50,8 @@ typedef struct ati18800_t { uint8_t regs[256]; int index; + int type; + uint32_t memory; } ati18800_t; 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 }; @@ -76,19 +71,20 @@ ati18800_out(uint16_t addr, uint8_t val, void *priv) ati18800->index = val; break; case 0x1cf: + old = ati18800->regs[ati18800->index]; ati18800->regs[ati18800->index] = val; switch (ati18800->index) { case 0xb0: - svga_recalctimings(svga); + if ((old ^ val) & 6) + 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; + if (ati18800->regs[0xbe] & 8) { /*Read/write bank mode*/ + svga->read_bank = ((ati18800->regs[0xb2] & 0xe0) >> 5) * 0x10000; + svga->write_bank = ((ati18800->regs[0xb2] & 0x0e) >> 1) * 0x10000; } else /*Single bank mode*/ - svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000; + svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] & 0x0e) >> 1) * 0x10000; break; case 0xb3: ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1); @@ -172,21 +168,73 @@ static void ati18800_recalctimings(svga_t *svga) { const ati18800_t *ati18800 = (ati18800_t *) svga->priv; + int clock_sel; - if (svga->crtc[0x17] & 4) { - svga->vtotal <<= 1; - svga->dispend <<= 1; - svga->vsyncstart <<= 1; - svga->split <<= 1; - svga->vblankstart <<= 1; + clock_sel = ((svga->miscout >> 2) & 3) | ((ati18800->regs[0xbe] & 0x10) >> 1) | ((ati18800->regs[0xb9] & 2) << 1); + + if (ati18800->regs[0xb6] & 0x10) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->rowoffset <<= 1; + svga->gdcreg[5] &= ~0x40; } - 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; + if (ati18800->regs[0xb0] & 6) { + svga->gdcreg[5] |= 0x40; + if ((ati18800->regs[0xb6] & 0x18) >= 0x10) + svga->packed_4bpp = 1; + else + svga->packed_4bpp = 0; + } else + svga->packed_4bpp = 0; + + if ((ati18800->regs[0xb6] & 0x18) == 8) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->ati_4color = 1; + } else + svga->ati_4color = 0; + + + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); + 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; + if (!svga->packed_4bpp) { + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; + } + } + break; + } + break; + + default: + break; + } + } } } @@ -198,52 +246,48 @@ ati18800_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800); + ati18800->type = info->local; + switch (info->local) { default: -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) case ATI18800_WONDER: rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + ati18800->memory = device_get_config_int("memory"); break; -#endif case ATI18800_VGA88: rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + ati18800->memory = 256; break; case ATI18800_EDGE16: rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + ati18800->memory = 512; 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); - } + svga_init(info, &ati18800->svga, ati18800, ati18800->memory << 10, + ati18800_recalctimings, + ati18800_in, ati18800_out, + NULL, + NULL); + ati18800->svga.clock_gen = device_add(&ati18810_device); + ati18800->svga.getclock = ics2494_getclock; 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.bpp = 8; ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0); return ati18800; } -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) static int ati18800_wonder_available(void) { return rom_present(BIOS_ROM_PATH_WONDER); } -#endif static int ati18800_vga88_available(void) @@ -283,7 +327,31 @@ ati18800_force_redraw(void *priv) ati18800->svga.fullchange = changeframecount; } -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) +static const device_config_t ati18800_wonder_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 + } +}; + const device_t ati18800_wonder_device = { .name = "ATI-18800", .internal_name = "ati18800w", @@ -295,12 +363,11 @@ const device_t ati18800_wonder_device = { { .available = ati18800_wonder_available }, .speed_changed = ati18800_speed_changed, .force_redraw = ati18800_force_redraw, - .config = NULL + .config = ati18800_wonder_config }; -#endif const device_t ati18800_vga88_device = { - .name = "ATI-18800-1", + .name = "ATI 18800-1", .internal_name = "ati18800v", .flags = DEVICE_ISA, .local = ATI18800_VGA88, @@ -314,7 +381,7 @@ const device_t ati18800_vga88_device = { }; const device_t ati18800_device = { - .name = "ATI-18800-5", + .name = "ATI VGA Edge 16", .internal_name = "ati18800", .flags = DEVICE_ISA, .local = ATI18800_EDGE16, diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index aa5800d1c..368312fcb 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -136,6 +136,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv) if ((old ^ val) & 0x80) svga_recalctimings(svga); break; + case 0xad: + if ((old ^ val) & 0x0c) + svga_recalctimings(svga); + break; case 0xb0: if ((old ^ val) & 0x60) svga_recalctimings(svga); @@ -400,7 +404,14 @@ ati28800k_in(uint16_t addr, void *priv) static void ati28800_recalctimings(svga_t *svga) { - const ati28800_t *ati28800 = (ati28800_t *) svga->priv; + ati28800_t *ati28800 = (ati28800_t *) svga->priv; + int clock_sel; + + if (ati28800->regs[0xad] & 0x08) + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2]; + + clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | + ((ati28800->regs[0xb9] & 2) << 1); if (ati28800->regs[0xa3] & 0x10) svga->ma_latch |= 0x10000; @@ -408,78 +419,45 @@ ati28800_recalctimings(svga_t *svga) 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[0xb8] & 0x40) svga->clock *= 2; if (ati28800->regs[0xa7] & 0x80) svga->clock *= 3; - if (ati28800->regs[0xb6] & 0x10) { + if ((ati28800->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; + svga->dots_per_clock <<= 1; svga->gdcreg[5] &= ~0x40; } if (ati28800->regs[0xb0] & 0x20) { svga->gdcreg[5] |= 0x40; - } + if ((ati28800->regs[0xb6] & 0x18) >= 0x10) + svga->packed_4bpp = 1; + else + svga->packed_4bpp = 0; + } else + svga->packed_4bpp = 0; - if (!svga->scrblank && svga->attr_palette_enable) { - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((ati28800->regs[0xb6] & 0x18) == 8) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->dots_per_clock <<= 1; + svga->ati_4color = 1; + } else + svga->ati_4color = 0; + + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); + ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, " + "planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", + svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, + ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, + ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80); switch (svga->gdcreg[5] & 0x60) { case 0x00: if (svga->seqregs[1] & 8) /*Low res (320)*/ @@ -502,8 +480,10 @@ ati28800_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_lowres; else { svga->render = svga_render_8bpp_highres; - svga->rowoffset <<= 1; - svga->ma_latch <<= 1; + if (!svga->packed_4bpp) { + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; + } } break; case 15: @@ -512,11 +492,11 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; svga->rowoffset <<= 1; svga->ma_latch <<= 1; } break; - default: break; } @@ -586,6 +566,8 @@ ati28800k_init(const device_t *info) ati28800k_in, ati28800k_out, NULL, NULL); + ati28800->svga.clock_gen = device_add(&ati18810_device); + ati28800->svga.getclock = ics2494_getclock; 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); @@ -652,6 +634,8 @@ ati28800_init(const device_t *info) ati28800_in, ati28800_out, NULL, NULL); + ati28800->svga.clock_gen = device_add(&ati18810_device); + ati28800->svga.getclock = ics2494_getclock; io_sethandler(0x01ce, 2, ati28800_in, NULL, NULL, diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 7cdd18019..ac2a0f7cb 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -44,6 +44,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/rom.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_8514a.h> @@ -129,7 +130,8 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) ramdac->render = svga_render_4bpp_highres; break; case 0x83: - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; break; case 0xa0: case 0xb0: @@ -154,7 +156,8 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) ramdac->render = svga_render_RGBA8888_highres; break; default: - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; break; } break; @@ -234,7 +237,8 @@ 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)); - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; return ramdac; } diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index da1b5d556..9aa396383 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -113,6 +113,7 @@ typedef struct mach64_t { uint32_t crtc_gen_cntl; uint8_t crtc_int_cntl; + uint32_t crtc_h_sync_strt_wid; uint32_t crtc_h_total_disp; uint32_t crtc_v_sync_strt_wid; uint32_t crtc_v_total_disp; @@ -514,6 +515,10 @@ mach64_recalctimings(svga_t *svga) 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->hblankstart = (mach64->crtc_h_sync_strt_wid & 255) + + ((mach64->crtc_h_sync_strt_wid >> 8) & 7); + svga->hblank_end_val = (svga->hblankstart + + ((mach64->crtc_h_sync_strt_wid >> 16) & 31) - 1) & 63; 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); @@ -565,9 +570,8 @@ mach64_recalctimings(svga_t *svga) } svga->vram_display_mask = mach64->vram_mask; - } else { + } else svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff; - } } void @@ -2348,6 +2352,12 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x03: READ8(addr, mach64->crtc_h_total_disp); break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + READ8(addr, mach64->crtc_h_sync_strt_wid); + break; case 0x08: case 0x09: case 0x0a: @@ -3050,6 +3060,14 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) svga_recalctimings(&mach64->svga); svga->fullchange = svga->monitor->mon_changeframecount; break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + WRITE8(addr, mach64->crtc_h_sync_strt_wid, val); + svga_recalctimings(&mach64->svga); + svga->fullchange = svga->monitor->mon_changeframecount; + break; case 0x08: case 0x09: case 0x0a: diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index dea8821e6..29a687f24 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -40,150 +40,14 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> -#define BIOS_MACH8_ROM_PATH "roms/video/mach8/BIOS.BIN" +#define BIOS_MACH8_VGA_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[2]; - - 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 }; @@ -195,7 +59,17 @@ 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 ATI_8514_ULTRA +static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv); +static void ati8514_accel_outw(uint16_t port, uint16_t val, void *priv); +static void ati8514_accel_outl(uint16_t port, uint32_t val, void *priv); +static uint8_t ati8514_accel_inb(uint16_t port, void *priv); +static uint16_t ati8514_accel_inw(uint16_t port, void *priv); +static uint32_t ati8514_accel_inl(uint16_t port, void *priv); +#endif + + +static void mach32_updatemapping(mach_t *mach, svga_t *svga); #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -249,9 +123,9 @@ mach_log(const char *fmt, ...) #define READ_PIXTRANS_WORD(cx, n) \ if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ - if (dev->bpp) { \ + if (dev->bpp) \ temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ - } else { \ + 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); \ } \ @@ -411,7 +285,7 @@ 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 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; @@ -458,10 +332,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } 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); + if (cpu_input && (cmd_type == 2)) + mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, 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) { @@ -566,6 +438,41 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } 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 { + 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 (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); @@ -577,99 +484,64 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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; + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + 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: - src_dat = dev->accel.frgd_color; + compare = 1; break; case 2: - src_dat = cpu_dat; + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; 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; - } - } + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; 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; + 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 (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); + 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); + } } - } - 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 (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + 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); } } - } 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); - } } } } @@ -777,6 +649,41 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } 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 { + 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 (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); @@ -788,99 +695,64 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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; + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + 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: - src_dat = dev->accel.frgd_color; + compare = 1; break; case 2: - src_dat = cpu_dat; + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; 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; - } - } + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; 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; + 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 (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); + 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); + } } - } - 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 (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + 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); } } - } 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); - } } } } @@ -926,6 +798,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.sx++; } } + mach->accel.poly_fill = 0; dev->accel.cur_x = dev->accel.dx; dev->accel.cur_y = dev->accel.dy; break; @@ -943,10 +816,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.cur_y >= 0x600) dev->accel.dy |= ~0x5ff; + if (mach->accel.dp_config == 0x5211) { + if (mach->accel.dest_x_end == 1024) { + goto skip_dx; + } + } /*Destination Width*/ if (mach->accel.dest_x_start != dev->accel.dx) mach->accel.dest_x_start = dev->accel.dx; +skip_dx: mach->accel.dx_start = mach->accel.dest_x_start; if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; @@ -1044,10 +923,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); - if ((dev->accel_bpp == 24) && (frgd_sel == 5)) { + 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)); + else if (mach->accel.dp_config & 0x02) + mach_log("BitBLT=%04x, Pitch=%d, C(%d,%d), D(%d,%d), SRCWidth=%d, SRCXStep=%d, WH(%d,%d), clipt=%d, clipb=%d, geoffset=%08x.\n", mach->accel.dp_config, dev->ext_pitch, mach->accel.src_x, mach->accel.src_y, dev->accel.cur_x, dev->accel.cur_y, mach->accel.src_width, mach->accel.src_stepx, mach->accel.width, mach->accel.height, clip_t, clip_b, (mach->accel.ge_offset << 2)); if (mono_src == 1) { if ((mach->accel.mono_pattern_enable) && !(mach->accel.patt_len_reg & 0x4000)) { @@ -1181,14 +1060,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } 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); + if ((mach->accel.dp_config & 0x02) || (mach->accel.linedraw_opt & 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; + mach->accel.poly_fill ^= 1; } - if (!mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { + if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02) || !(mach->accel.linedraw_opt & 0x02)) { switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1203,7 +1082,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - READ(dev->accel.src + (dev->accel.cx), src_dat); + READ(dev->accel.src + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; } @@ -1221,62 +1100,62 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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); + 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); } - } 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; + 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); + default: + break; } - } - 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); + 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); } - } else { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } } @@ -1286,7 +1165,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else cpu_dat >>= 8; - if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3)) { + if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) { dev->accel.cx += mach->accel.src_stepx; mach->accel.sx++; if (mach->accel.sx >= mach->accel.src_width) { @@ -1331,8 +1210,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } dev->accel.sx++; - if (dev->accel.sx >= mach->accel.width) { - mach->accel.poly_fill = 0; + if ((dev->accel.sx >= mach->accel.width) || (dev->accel.dx >= 0x600)) { dev->accel.sx = 0; if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; @@ -1342,6 +1220,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dy += mach->accel.stepy; dev->accel.sy++; + mach->accel.poly_fill = 0; if (dev->bpp) dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); else @@ -1360,7 +1239,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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)) + if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02) || (mach->accel.linedraw_opt & 0x02)) return; if ((mono_src == 1) && (frgd_sel == 5) && (dev->accel_bpp == 24) && (mach->accel.patt_len_reg & 0x4000)) return; @@ -1395,7 +1274,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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); + mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d), bounds: l=%d, r=%d, t=%d, b=%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, mach->accel.bleft, mach->accel.bright, mach->accel.btop, mach->accel.bbottom); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -1437,7 +1316,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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)) { + 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: @@ -1452,14 +1331,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 case 3: if (mach_pixel_read(mach)) src_dat = cpu_dat; - else { + else src_dat = 0; - } break; case 5: - if (mix) { + if (mix) src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; - } else + else src_dat = 0; break; @@ -1507,7 +1385,15 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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 (count) { + 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 { @@ -1559,8 +1445,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + 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; + if (mach->accel.linedraw_opt & 0x02) { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1625,7 +1517,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!compare) { if (mach_pixel_write(mach)) { old_dest_dat = dest_dat; - MIX(mix, dest_dat, src_dat); + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + MIX(mix, dest_dat, src_dat); + } dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } } @@ -1681,7 +1575,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 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)) { + 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: @@ -1752,10 +1646,20 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } 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); + if (mach->accel.linedraw_opt & 0x04) { + if (count) { + 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 { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); + 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 @@ -1803,8 +1707,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - if (((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b)) { + 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; @@ -1913,6 +1818,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } } + mach->accel.poly_fill = 0; 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]; @@ -2124,10 +2030,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - READ(dev->accel.src + (dev->accel.cx), src_dat); - if (mono_src == 3) { + READ(dev->accel.src + dev->accel.cx, src_dat); + if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } } break; case 5: @@ -2147,7 +2052,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - READ(dev->accel.dest + (dev->accel.dx), dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); switch (compare_mode) { case 1: @@ -2267,7 +2172,7 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) case 0x000: /*8-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if ((mach->accel.dp_config & 0x1000) && ((dev->local & 0xff) >= 0x02)) + if (mach->accel.dp_config & 0x1000) val = (val >> 8) | (val << 8); mach_accel_start(mach->accel.cmd_type, 1, 8, val | (val << 16), 0, mach, dev); } else @@ -2281,12 +2186,10 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) 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 { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } - } else { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } break; default: @@ -2366,7 +2269,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) break; case 0xbd: if ((old ^ val) & 4) { - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; case 0xb3: @@ -2476,6 +2379,9 @@ mach_in(uint16_t addr, void *priv) break; case 0x1cf: switch (mach->index) { + case 0xa0: + temp = mach->regs[0xa0] | 0x10; + break; case 0xa8: temp = (svga->vc >> 8) & 3; break; @@ -2484,11 +2390,10 @@ mach_in(uint16_t addr, void *priv) break; case 0xb0: temp = mach->regs[0xb0] | 0x80; + temp &= ~0x18; if ((dev->local & 0xff) >= 0x02) { /*Mach32 VGA 1MB memory*/ temp |= 0x08; - temp &= ~0x10; } else { /*ATI 28800 VGA 512kB memory*/ - temp &= ~0x08; temp |= 0x10; } break; @@ -2555,13 +2460,95 @@ mach_in(uint16_t addr, void *priv) return temp; } + +#ifdef ATI_8514_ULTRA +static void +ati8514_out(uint16_t addr, uint8_t val, void *priv) +{ + mach_log("ADDON OUT addr=%03x, val=%02x.\n", addr, val); + svga_out(addr, val, priv); +} + +static uint8_t +ati8514_in(uint16_t addr, void *priv) +{ + uint8_t temp = 0xff; + + temp = svga_in(addr, priv); + + mach_log("ADDON IN addr=%03x, temp=%02x.\n", addr, temp); + return temp; +} + +void +ati8514_recalctimings(svga_t *svga) +{ + const mach_t *mach = (mach_t *) svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("ON0=%d, ON1=%d, vgahdisp=%d.\n", dev->on[0], dev->on[1], svga->hdisp); + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal; + dev->v_syncstart = dev->vsyncstart; + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = dev->vdisp; + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->accel.advfunc_cntl & 4) { + if (dev->h_disp != 800) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else { + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } + + 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, advfunc_cntl=%x, shadow=%x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, dev->accel.advfunc_cntl & 4, mach->shadow_set & 3); + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + } else { + 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; + } + } + } +} +#endif + static void mach_recalctimings(svga_t *svga) { - const mach_t *mach = (mach_t *) svga->priv; + mach_t *mach = (mach_t *) svga->priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int clock_sel; + if (mach->regs[0xad] & 0x08) + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2]; + clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); if ((dev->local & 0xff) >= 0x02) { @@ -2578,61 +2565,78 @@ mach_recalctimings(svga_t *svga) if (mach->regs[0xb0] & 0x40) svga->ma_latch |= 0x20000; - if (mach->regs[0xb6] & 0x10) { + if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; + svga->dots_per_clock <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; - svga->attrregs[0x10] &= ~0x40; } if (mach->regs[0xb0] & 0x20) { svga->gdcreg[5] |= 0x40; - svga->attrregs[0x10] |= 0x40; + if ((mach->regs[0xb6] & 0x18) >= 0x10) + svga->packed_4bpp = 1; + else + svga->packed_4bpp = 0; + } else + svga->packed_4bpp = 0; + + if ((dev->local & 0xff) < 0x02) { + if ((mach->regs[0xb6] & 0x18) == 8) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->dots_per_clock <<= 1; + svga->ati_4color = 1; + } else + svga->ati_4color = 0; } + svga->render8514 = ibm8514_render_blank; mach_log("ON[0]=%d, ON[1]=%d, exton[0]=%d, exton[1]=%d, vendormode0=%d, vendormode1=%d.\n", dev->on[0], dev->on[1], mach->ext_on[0], mach->ext_on[1], dev->vendor_mode[0], dev->vendor_mode[1]); if (dev->on[0] || dev->on[1]) { mach_log("8514/A ON.\n"); - if ((dev->local & 0xff) >= 0x02) { - 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); + dev->h_total = dev->htotal + 1; + dev->v_total = dev->v_total_reg + 1; + dev->v_syncstart = dev->v_sync_start + 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); + mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04); + if ((dev->hdisp == 640) || (dev->hdisp == 800) || (dev->hdisp == 1280) || dev->bpp) { + /*For VESA/ATI modes in 8514/A mode.*/ + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } else { + /*Default modes for 8514/A mode*/ + if (dev->accel.advfunc_cntl & 0x04) { + dev->h_disp = 1024; + dev->dispend = 768; } 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); + dev->h_disp = 640; + dev->dispend = 480; + } + } + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->dispend == 478) + dev->dispend += 2; + + if ((dev->local & 0xff) >= 0x02) { + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } if (dev->interlace) { @@ -2643,6 +2647,8 @@ mach_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } + + mach_log("HDISP=%d.\n", dev->h_disp); 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))) { @@ -2659,7 +2665,7 @@ mach_recalctimings(svga_t *svga) } 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); + mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp, mach->shadow_set & 3, svga->hdisp); switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2671,16 +2677,18 @@ mach_recalctimings(svga_t *svga) svga->render8514 = ibm8514_render_16bpp; break; case 24: + mach_log("GEConfig24bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); if (mach->accel.ext_ge_config & 0x400) svga->render8514 = ibm8514_render_BGR; else svga->render8514 = ibm8514_render_24bpp; break; case 32: + mach_log("GEConfig32bpp: %03x.\n", mach->accel.ext_ge_config & 0x600); if (mach->accel.ext_ge_config & 0x400) svga->render8514 = ibm8514_render_ABGR8888; else - svga->render8514 = ibm8514_render_RGBA8888; + svga->render8514 = ibm8514_render_32bpp; break; default: @@ -2689,53 +2697,31 @@ mach_recalctimings(svga_t *svga) } switch (mach->regs[0xb8] & 0xc0) { case 0x40: - svga->clock *= 2; + svga->clock8514 *= 2; break; case 0x80: - svga->clock *= 3; + svga->clock8514 *= 3; break; case 0xc0: - svga->clock *= 4; + svga->clock8514 *= 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); + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } 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 ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } + if (dev->interlace) { dev->dispend >>= 1; dev->v_syncstart >>= 2; @@ -2744,13 +2730,14 @@ mach_recalctimings(svga_t *svga) 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); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; if (mach->regs[0xb8] & 0x40) - svga->clock *= 2; + svga->clock8514 *= 2; } } @@ -2760,58 +2747,41 @@ mach_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); if (mach->regs[0xa7] & 0x80) svga->clock *= 3; - if (svga->bpp <= 8) { - if (svga->attrregs[0x10] & 0x40) { /*8bpp mode*/ - svga->map8 = svga->pallook; - if (svga->lowres) /*Low res (320)*/ - svga->render = svga_render_8bpp_lowres; - else { - svga->render = svga_render_8bpp_highres; - svga->ma_latch <<= 1; - svga->rowoffset <<= 1; - } - } else { - mach_log("4bpp.\n"); + 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; - } - } else { - 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; + 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; + mach_log("Lowres=%x, seqreg[1]bit3=%x.\n", svga->lowres, svga->seqregs[1] & 8); + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else { + svga->render = svga_render_8bpp_highres; + if (!svga->packed_4bpp) { svga->ma_latch <<= 1; svga->rowoffset <<= 1; } - break; + } + break; + } + break; - } - break; - - default: - break; - } + default: + break; } } } @@ -2824,29 +2794,30 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u int bkgd_sel; int mono_src; + mach_log("[%04X:%08X]: Port FIFO OUT=%04x, val=%04x, len=%d.\n", CS, cpu_state.pc, port, val, len); + switch (port) { case 0x82e8: case 0xc2e8: - if (len == 1) { + case 0xf6ee: + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else { + else dev->accel.cur_y = val & 0x7ff; - } break; case 0x82e9: case 0xc2e9: - if (len == 1) { + case 0xf6ef: + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: case 0xc6e8: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else { + else dev->accel.cur_x = val & 0x7ff; - } break; case 0x86e9: case 0xc6e9: @@ -2861,6 +2832,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; else { mach->accel.src_y = val; + dev->accel.desty = val & 0x07ff; dev->accel.desty_axstp = val & 0x3fff; if (val & 0x2000) dev->accel.desty_axstp |= ~0x1fff; @@ -2881,6 +2853,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; else { mach->accel.src_x = val; + dev->accel.destx = val & 0x07ff; dev->accel.destx_distp = val & 0x3fff; if (val & 0x2000) dev->accel.destx_distp |= ~0x1fff; @@ -2901,7 +2874,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u fallthrough; case 0xd2e8: - mach_log("92E8 = %04x\n", val); if (len == 1) dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; else { @@ -2926,6 +2898,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { mach->accel.test = val & 0x1fff; dev->accel.maj_axis_pcnt = val & 0x07ff; + dev->accel.maj_axis_pcnt_no_limit = val; } break; case 0x96e9: @@ -2944,7 +2917,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->data_available = 0; dev->data_available2 = 0; dev->accel.cmd = val; - mach_log("CMD8514 = %04x.\n", val); + mach_log("CMD8514=%04x, len=%d, pixcntl=%02x.\n", val, len, dev->accel.multifunc[0x0a]); mach->accel.cmd_type = -1; if (port == 0xdae8) { if (dev->accel.cmd & 0x100) @@ -3192,8 +3165,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xeae8: if (len == 1) dev->accel.wrt_mask = (dev->accel.wrt_mask & 0x00ff) | val; - else + else { dev->accel.wrt_mask = val; + mach_log("WrtMask=%04x.\n", val); + } break; case 0xaae9: case 0xeae9: @@ -3205,8 +3180,10 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xeee8: if (len == 1) dev->accel.rd_mask = (dev->accel.rd_mask & 0x00ff) | val; - else + else { dev->accel.rd_mask = val; + mach_log("ReadMask=%04x.\n", val); + } break; case 0xaee9: case 0xeee9: @@ -3244,24 +3221,22 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 3) { + + if ((dev->accel.multifunc_cntl >> 12) == 3) dev->accel.multifunc[3] = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 4) { + + 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) + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - - svga_recalctimings(svga); } if (port == 0xfee8) dev->accel.cmd_back = 1; @@ -3274,17 +3249,15 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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) { + 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 ((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 & 0xff) < 0x02) + dev->ext_crt_pitch = 128; } if (port == 0xfee9) dev->accel.cmd_back = 1; @@ -3344,7 +3317,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach->accel.bres_count = (mach->accel.bres_count & 0x700) | val; else { mach->accel.bres_count = val & 0x7ff; - mach_log("96EE line draw.\n"); + mach_log("BresenhamDraw = %04x.\n", mach->accel.dp_config); dev->data_available = 0; dev->data_available2 = 0; mach->accel.cmd_type = 1; @@ -3372,6 +3345,16 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach->accel.linedraw_opt = (mach->accel.linedraw_opt & 0xff00) | val; else { mach->accel.linedraw_opt = val; + mach->accel.bbottom = dev->accel.multifunc[3] & 0x7ff; + mach->accel.btop = dev->accel.clip_top & 0x7ff; + mach->accel.bleft = dev->accel.clip_left & 0x7ff; + mach->accel.bright = dev->accel.multifunc[4] & 0x7ff; + if (mach->accel.linedraw_opt & 0x100) { + mach->accel.bbottom = 2047; + mach->accel.btop = 0; + mach->accel.bleft = 0; + mach->accel.bright = 2047; + } } break; case 0xa2ef: @@ -3404,7 +3387,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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 { @@ -3471,7 +3453,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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 { @@ -3502,6 +3483,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 1) mach->accel.dp_config = (mach->accel.dp_config & 0xff00) | val; else { + dev->data_available = 0; + dev->data_available2 = 0; mach->accel.dp_config = val; } break; @@ -3607,8 +3590,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u 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); + mach_log("LineDraw = %04x.\n", mach->accel.dp_config); 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]; @@ -3631,91 +3613,132 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } static void -mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t old = 0; - mach_log("Port accel out = %04x, val = %04x.\n", port, val); + if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9 && port != 0x46e8 && port != 0x46e9) + mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { case 0x2e8: - case 0x2e9: - WRITE8(port, dev->htotal, val); + case 0x6e9: + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) + 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); - } + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) + dev->hdisped = val; + + mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc bit 2=%x, dispcntl=%02x, clocksel bit 0=%x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 0x04, dev->disp_cntl & 0x60, mach->accel.clock_sel & 0x01); + mach_log("ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", port, val); svga_recalctimings(svga); break; case 0xae8: - mach_log("ATI 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) + dev->hsync_start = val; + + mach_log("ATI 8514/A: (0x%04x): val=%d, hsync_start=%d.\n", port, val, (val + 1) << 3); svga_recalctimings(svga); break; case 0xee8: - mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) + dev->hsync_width = val; + + mach_log("ATI 8514/A: (0x%04x): val=%d, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); svga_recalctimings(svga); break; case 0x12e8: case 0x12e9: - WRITE8(port, dev->vtotal, val); - dev->vtotal &= 0x1fff; + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + } svga_recalctimings(svga); break; case 0x16e8: case 0x16e9: - WRITE8(port, dev->vdisp, val); - dev->vdisp &= 0x1fff; + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + } + dev->modechange = dev->accel.advfunc_cntl & 0x04; + mach->compat_mode = mach->shadow_set & 0x03; + mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); svga_recalctimings(svga); break; case 0x1ae8: case 0x1ae9: - WRITE8(port, dev->vsyncstart, val); - dev->vsyncstart &= 0x1fff; + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 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->disp_cntl = val; 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); + mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); break; case 0x42e8: - dev->subsys_stat &= ~val; + old = dev->subsys_stat; + if (val & 1) + dev->subsys_stat &= ~1; + if (val & 2) + dev->subsys_stat &= ~2; + if (val & 4) + dev->subsys_stat &= ~4; + if (val & 8) + dev->subsys_stat &= ~8; break; case 0x42e9: + old = dev->subsys_cntl; dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; break; case 0x4ae8: case 0x4ae9: - if (dev->local < 2) + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on[port & 1] = (dev->accel.advfunc_cntl & 0x01); - mach_log("ATI 8514/A: (0x%04x): ON=%d.\n", port, dev->on[port & 1]); vga_on = !dev->on[port & 1]; mach->ext_on[port & 1] = dev->on[port & 1]; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); dev->vendor_mode[port & 1] = 0; + dev->hdisp = (dev->hdisped + 1) << 3; + dev->vdisp = (dev->v_disp >> 1) + 1; + mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + mach_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); break; @@ -3736,7 +3759,8 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0xaee: case 0xaef: - WRITE8(port, mach->cursor_offset_lo, val); + WRITE8(port, mach->cursor_offset_lo_reg, val); + mach->cursor_offset_lo = mach->cursor_offset_lo_reg; break; case 0xeee: @@ -3776,7 +3800,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x22ee: if (mach->pci_bus) { mach->pci_cntl_reg = val; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; @@ -3792,14 +3816,14 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) else dev->ext_crt_pitch <<= 1; } - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); svga_recalctimings(svga); break; case 0x32ee: case 0x32ef: WRITE8(port, mach->local_cntl, val); - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x36ee: @@ -3825,44 +3849,52 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x42ee: case 0x42ef: - mach->accel.test2[port & 1] = val; + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->accel.test2, val); break; case 0x46ee: case 0x46ef: - mach->accel.test3[port & 1] = val; + WRITE8(port, mach->shadow_cntl, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); break; case 0x4aee: case 0x4aef: WRITE8(port, mach->accel.clock_sel, val); dev->on[port & 1] = mach->accel.clock_sel & 0x01; - mach_log("ATI 8514/A: (0x%04x): ON=%d.\n", port, dev->on[port & 1]); + mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], val, dev->hdisp, dev->vdisp); + mach_log("ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); mach->ext_on[port & 1] = dev->on[port & 1]; vga_on = !dev->on[port & 1]; dev->vendor_mode[port & 1] = 1; + dev->hdisp = (dev->hdisped + 1) << 3; + dev->vdisp = (dev->v_disp >> 1) + 1; svga_recalctimings(svga); break; case 0x52ee: case 0x52ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); WRITE8(port, mach->accel.scratch0, val); - mach->ext_on[port & 1] = 1; break; case 0x56ee: case 0x56ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); WRITE8(port, mach->accel.scratch1, val); - mach->ext_on[port & 1] = 1; break; case 0x5aee: case 0x5aef: WRITE8(port, mach->shadow_set, val); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - svga_recalctimings(svga); + mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); + if ((mach->shadow_set & 0x03) == 0x00) + mach_log("Primary CRT register set.\n"); + else if ((mach->shadow_set & 0x03) == 0x01) + mach_log("Shadow Set 1: 640x480.\n"); + else if ((mach->shadow_set & 0x03) == 0x02) + mach_log("Shadow Set 2: 1024x768.\n"); break; case 0x5eee: @@ -3872,7 +3904,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x62ee: @@ -3904,7 +3936,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x76ef: WRITE8(port, mach->accel.ge_pitch, val); dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%04x, extpitch=%d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; @@ -3936,18 +3968,20 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); dev->vendor_mode[port & 1] = 1; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); + mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); + svga_recalctimings(svga); + } else { + if (mach->accel.ext_ge_config & 0x8080) + ati_eeprom_write(&mach->eeprom, mach->accel.ext_ge_config & 0x4040, mach->accel.ext_ge_config & 0x2020, mach->accel.ext_ge_config & 0x1010); } - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - 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); + ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 8, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - svga_recalctimings(svga); break; default: @@ -3955,6 +3989,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } } +static void +mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +{ + svga_t *svga = &mach->svga; + + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint16_t mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) { @@ -3968,28 +4012,24 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: case 0xc2e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_y; - } break; case 0x86e8: case 0xc6e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_x; - } break; case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x96e8: - if (len != 1) { + if (len != 1) temp = dev->accel.maj_axis_pcnt; - } break; case 0x9ae8: @@ -4178,6 +4218,11 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in temp = mach->accel.patt_data_idx; break; + case 0x86ee: + case 0x86ef: + temp = 0x0000; + break; + case 0x8eee: if (len == 1) temp = mach->accel.ext_ge_config & 0xff; @@ -4207,9 +4252,9 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x96ee: - if (len == 1) { + if (len == 1) temp = dev->accel.maj_axis_pcnt & 0xff; - } else { + else { temp = dev->accel.maj_axis_pcnt; if ((mach->accel.test == 0x1555) || (mach->accel.test == 0x0aaa)) temp = mach->accel.test; @@ -4223,9 +4268,8 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xa2ee: if (len == 1) temp = mach->accel.linedraw_opt & 0xff; - else { + else temp = mach->accel.linedraw_opt; - } break; case 0xa2ef: if (len == 1) @@ -4234,54 +4278,61 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xb2ee: if (len == 1) - temp = dev->hdisp; + temp = dev->hdisped; else { - temp = dev->hdisp & 0xff; + temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); - mach_log("HDISP read=%d, HTOTAL read=%d.\n", temp & 0xff, temp >> 8); } + mach_log("B2EE read=%02x.\n", temp & 0xff); break; case 0xb2ef: - if (len == 1) { + if (len == 1) temp = dev->htotal; - } + break; + + case 0xb6ee: + temp = dev->hsync_start; + break; + + case 0xbaee: + temp = dev->hsync_width; break; case 0xc2ee: if (len == 1) - temp = dev->vtotal & 0xff; + temp = dev->v_total_reg & 0xff; else { - temp = dev->vtotal; + temp = dev->v_total_reg; mach_log("VTOTAL read=%d.\n", temp); } break; case 0xc2ef: if (len == 1) - temp = dev->vtotal >> 8; + temp = dev->v_total_reg >> 8; break; case 0xc6ee: if (len == 1) - temp = dev->vdisp & 0xff; + temp = dev->v_disp & 0xff; else { - temp = dev->vdisp; + temp = dev->v_disp; mach_log("VDISP read=%d.\n", temp); } break; case 0xc6ef: if (len == 1) - temp = dev->vdisp >> 8; + temp = dev->v_disp >> 8; break; case 0xcaee: if (len == 1) - temp = dev->vsyncstart & 0xff; + temp = dev->v_sync_start & 0xff; else - temp = dev->vsyncstart; + temp = dev->v_sync_start; break; case 0xcaef: if (len == 1) - temp = dev->vsyncstart >> 8; + temp = dev->v_sync_start >> 8; break; case 0xceee: @@ -4347,34 +4398,33 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; } - mach_log("Port FIFO IN=%04x, temp=%04x, len=%d.\n", port, temp, len); + mach_log("[%04X:%08X]: Port FIFO IN=%04x, temp=%04x, len=%d.\n", CS, cpu_state.pc, port, temp, len); + return temp; } static uint8_t -mach_accel_in(uint16_t port, mach_t *mach) +mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - 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]; + uint8_t temp = 0; + uint16_t vpos = 0; + uint16_t 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) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -4382,8 +4432,7 @@ mach_accel_in(uint16_t port, mach_t *mach) break; case 0x26e8: - case 0x26e9: - READ8(port, dev->htotal); + temp = dev->htotal; break; case 0x2ee8: @@ -4398,26 +4447,23 @@ mach_accel_in(uint16_t port, mach_t *mach) vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) dev->subsys_stat |= 1; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) dev->subsys_stat |= 1; } - if (port & 1) { + if (port & 1) temp = 0x80; - } else { + else { temp = dev->subsys_stat | 0x80; - if (mach->accel.ext_ge_config & 0x08) { + if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); - } else + else temp |= 0x20; } - break; - - case 0x4ae8: - temp = dev->accel.advfunc_cntl; + mach_log("Subsystem Status=%04x, 4ae8 shadow set=%02x.\n", temp, dev->accel.advfunc_cntl & 4); break; /*ATI Mach8/32 specific registers*/ @@ -4432,9 +4478,8 @@ mach_accel_in(uint16_t port, mach_t *mach) break; case 0x22ee: - if (mach->pci_bus) { + if (mach->pci_bus) temp = mach->pci_cntl_reg; - } break; case 0x32ee: @@ -4447,10 +4492,8 @@ mach_accel_in(uint16_t port, mach_t *mach) READ8(port, mach->misc); if (!(port & 1)) { + temp &= ~0x0c; switch (mach->memory) { - case 512: - temp &= ~0x0c; - break; case 1024: temp |= 0x04; break; @@ -4462,23 +4505,21 @@ mach_accel_in(uint16_t port, mach_t *mach) break; default: + if ((dev->local & 0xff) < 0x02) + temp |= 0x04; break; } } break; case 0x42ee: - temp = mach->accel.test2[0]; - break; case 0x42ef: - temp = mach->accel.test2[1]; + READ8(port, mach->accel.test2); break; case 0x46ee: - temp = mach->accel.test3[0]; - break; case 0x46ef: - temp = mach->accel.test3[1]; + READ8(port, mach->shadow_cntl); break; case 0x4aee: @@ -4489,6 +4530,23 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x52ee: case 0x52ef: READ8(port, mach->accel.scratch0); +#ifdef ATI_8514_ULTRA + if (mach->mca_bus) { + if (!(port & 1)) { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[4]; + } else { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[5]; + } + } else { + if (!(port & 1)) { + if (svga->ext8514 != NULL) { + temp = 0x20 | 0x80; + } + } + } +#endif break; case 0x56ee: @@ -4511,6 +4569,7 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x62ef: if (mach->force_busy) temp |= 0x20; + mach->force_busy = 0; if (ati_eeprom_read(&mach->eeprom)) temp |= 0x40; @@ -4524,31 +4583,86 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x72ee: case 0x72ef: - READ8(port, dev->accel.clip_left); + READ8(port, (mach->accel.bleft)); break; case 0x76ee: case 0x76ef: - READ8(port, dev->accel.clip_top); + READ8(port, (mach->accel.btop)); break; case 0x7aee: case 0x7aef: - READ8(port, dev->accel.multifunc[4]); + READ8(port, (mach->accel.bright)); break; case 0x7eee: case 0x7eef: - READ8(port, dev->accel.multifunc[3]); + READ8(port, (mach->accel.bbottom)); break; default: break; } - mach_log("Port accel in = %04x, temp = %04x.\n", port, temp); + if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9) + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + return temp; } +#ifdef ATI_8514_ULTRA +static void +ati8514_accel_out(uint16_t port, uint8_t val, svga_t *svga) +{ + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, (mach_t *)svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static void +ati8514_accel_outb(uint16_t port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); + else + ati8514_accel_out(port, val, svga); +} + +static void +ati8514_accel_outw(uint16_t port, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); + else { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + } +} + +static void +ati8514_accel_outl(uint16_t port, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + 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 { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + ati8514_accel_out(port + 2, (val >> 16), svga); + ati8514_accel_out(port + 3, (val >> 24), svga); + } +} +#endif + static void mach_accel_outb(uint16_t port, uint8_t val, void *priv) { @@ -4591,6 +4705,72 @@ mach_accel_outl(uint16_t port, uint32_t val, void *priv) mach_accel_out(port + 3, (val >> 24), mach); } } + +#ifdef ATI_8514_ULTRA +static uint8_t +ati8514_accel_in(uint16_t port, svga_t *svga) +{ + return mach_accel_in_call(port, (mach_t *) svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static uint8_t +ati8514_accel_inb(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint8_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 1); + else + temp = ati8514_accel_in(port, svga); + + return temp; +} + +static uint16_t +ati8514_accel_inw(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint16_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + else { + temp = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + } + return temp; +} + +static uint32_t +ati8514_accel_inl(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + 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 = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + temp |= (ati8514_accel_in(port + 2, svga) << 16); + temp |= (ati8514_accel_in(port + 3, svga) << 24); + } + return temp; +} +#endif + +static uint8_t +mach_accel_in(uint16_t port, mach_t *mach) +{ + svga_t *svga = &mach->svga; + return mach_accel_in_call(port, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint8_t mach_accel_inb(uint16_t port, void *priv) { @@ -4701,6 +4881,7 @@ mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach) if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; + mach_log("WriteCommon chain4 = %x.\n", svga->chain4); if (((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && (svga->writemode < 4)) { writemask2 = 1 << (addr & 3); addr &= ~3; @@ -4865,6 +5046,7 @@ mach32_read_common(uint32_t addr, int linear, mach_t *mach) latch_addr = (addr << count) & svga->decode_mask; count = (1 << count); + mach_log("ReadCommon chain4 = %x.\n", svga->chain4); if ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) { addr &= svga->decode_mask; if (addr >= dev->vram_size) @@ -5135,9 +5317,8 @@ mach32_ap_readl(uint32_t addr, void *priv) } static void -mach32_updatemapping(mach_t *mach) +mach32_updatemapping(mach_t *mach, svga_t *svga) { - 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))) { @@ -5209,8 +5390,13 @@ mach32_hwcursor_draw(svga_t *svga, int displine) int offset = dev->hwcursor_latch.x - dev->hwcursor_latch.xoff; uint32_t color0; uint32_t color1; + uint32_t *p; + int x_pos; + int y_pos; + mach_log("BPP=%d.\n", dev->accel_bpp); switch (dev->accel_bpp) { + default: case 8: color0 = dev->pallook[mach->cursor_col_0]; color1 = dev->pallook[mach->cursor_col_1]; @@ -5225,7 +5411,6 @@ mach32_hwcursor_draw(svga_t *svga, int displine) break; case 24: case 32: - default: 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); break; @@ -5238,16 +5423,22 @@ mach32_hwcursor_draw(svga_t *svga, int displine) 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; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + if (offset >= dev->hwcursor_latch.x) { + mach_log("COMB=%d.\n", comb); switch (comb) { case 0: - (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color0; + p[x_pos] = color0; break; case 1: - (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color1; + p[x_pos] = color1; break; case 3: - (svga->monitor->target_buffer->line[displine])[offset + svga->x_add] ^= 0xffffff; + p[x_pos] ^= 0xffffff; break; default: @@ -5262,119 +5453,120 @@ mach32_hwcursor_draw(svga_t *svga, int displine) dev->hwcursor_latch.addr += 16; } -#if 0 +#ifdef ATI_8514_ULTRA static void -mach_io_remove(mach_t *mach) +ati8514_io_set(svga_t *svga) { - 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_sethandler(0x2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - 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_sethandler(0xc2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - 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); + io_sethandler(0x02ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x06ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x32ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x36ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x46ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x62ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x66ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x72ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x76ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xceee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); } #endif @@ -5464,6 +5656,7 @@ mach_io_set(mach_t *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(0x86ee, 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); @@ -5488,7 +5681,7 @@ mach_io_set(mach_t *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(0xf6ee, 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); } @@ -5544,6 +5737,34 @@ mach_mca_reset(void *priv) mach_mca_write(0x102, 0, mach); } +#ifdef ATI_8514_ULTRA +uint8_t +ati8514_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]); +} + +void +ati8514_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (port < 0x102) + return; + + dev->pos_regs[port & 7] = val; + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, dev->pos_regs[port & 7], (((dev->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mem_mapping_disable(&dev->bios_rom.mapping); + + if (dev->pos_regs[2] & 0x01) + mem_mapping_enable(&dev->bios_rom.mapping); +} +#endif + static uint8_t mach32_pci_read(UNUSED(int func), int addr, void *priv) { @@ -5639,19 +5860,19 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) 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); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); } - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x12: mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x13: mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x30: @@ -5729,12 +5950,11 @@ mach8_init(const device_t *info) 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } - } else { + } else rom_init(&mach->bios_rom, - BIOS_MACH8_ROM_PATH, + BIOS_MACH8_VGA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } if ((dev->local & 0xff) >= 0x02) { svga_init(info, svga, mach, mach->memory << 10, /*default: 2MB for Mach32*/ @@ -5767,7 +5987,6 @@ mach8_init(const device_t *info) 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); @@ -5796,7 +6015,7 @@ mach8_init(const device_t *info) 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->config1 = 0x01 | 0x02 | 0x20 | 0x08 | 0x80; mach->config2 = 0x02; svga->clock_gen = device_add(&ati18810_device); } @@ -5823,6 +6042,7 @@ mach8_init(const device_t *info) mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; mach->ext_cur_col_1_g = 0xff; + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); if (mach->vlb_bus) ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); else if (mach->mca_bus) { @@ -5839,23 +6059,54 @@ mach8_init(const device_t *info) 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 { + } else ati_eeprom_load_mach8(&mach->eeprom, "mach8.nvr"); - } + + timer_add(&svga->timer8514, ibm8514_poll, svga, 1); return mach; } -static int -mach8_available(void) +#ifdef ATI_8514_ULTRA +void +ati8514_init(svga_t *svga, void *ext8514, void *dev8514) { - return rom_present(BIOS_MACH8_ROM_PATH); + mach_t *mach = (mach_t *)ext8514; + ibm8514_t *dev = (ibm8514_t *)dev8514; + + dev->on[0] = 0; + dev->on[1] = 0; + dev->ext_pitch = 1024; + dev->ext_crt_pitch = 0x80; + dev->accel_bpp = 8; + dev->rowoffset = 0x80; + dev->hdisp = 1024; + dev->vdisp = 768; + + io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); + ati8514_io_set(svga); + mach->mca_bus = !!(dev->type & DEVICE_MCA); + + if (mach->mca_bus) + mach->config1 = 0x02 | 0x04 | 0x08 | 0x20 | 0x80; + else + mach->config1 = 0x02 | 0x08 | 0x20 | 0x80; + + mach->config2 = 0x01 | 0x02; +} +#endif + +static int +mach8_vga_available(void) +{ + return rom_present(BIOS_MACH8_VGA_ROM_PATH); } static int @@ -6005,15 +6256,15 @@ static const device_config_t mach32_pci_config[] = { } }; -const device_t mach8_isa_device = { - .name = "ATI Mach8 (ISA)", - .internal_name = "mach8_isa", +const device_t mach8_vga_isa_device = { + .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", + .internal_name = "mach8_vga_isa", .flags = DEVICE_ISA, .local = 1, .init = mach8_init, .close = mach_close, .reset = NULL, - { .available = mach8_available }, + { .available = mach8_vga_available }, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, .config = NULL diff --git a/src/video/vid_bochs_vbe.c b/src/video/vid_bochs_vbe.c new file mode 100644 index 000000000..a4459ce4c --- /dev/null +++ b/src/video/vid_bochs_vbe.c @@ -0,0 +1,983 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Bochs VBE SVGA emulation. + * + * Uses code from libxcvt to calculate CRTC timings. + * + * Authors: Cacodemon345 + * The Bochs Project + * Fabrice Bellard + * The libxcvt authors + * + * Copyright 2024 Cacodemon345 + * Copyright 2003 Fabrice Bellard + * Copyright 2002-2024 The Bochs Project + * Copyright 2002-2003 Mike Nordell + * Copyright 2000-2021 The libxcvt authors + * + * See https://gitlab.freedesktop.org/xorg/lib/libxcvt/-/blob/master/COPYING for libxcvt license details + */ + +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.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> +#include <86box/pci.h> +#include <86box/i2c.h> +#include <86box/vid_ddc.h> + +#define VBE_DISPI_BANK_SIZE_KB 64 +#define VBE_DISPI_BANK_GRANULARITY_KB 32 + +#define VBE_DISPI_MAX_XRES 1920 +#define VBE_DISPI_MAX_YRES 1600 + +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa +#define VBE_DISPI_INDEX_DDC 0xb + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 +#define VBE_DISPI_ID5 0xB0C5 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_BANK_GRANULARITY_32K 0x10 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +#define VBE_DISPI_BANK_WR 0x4000 +#define VBE_DISPI_BANK_RD 0x8000 +#define VBE_DISPI_BANK_RW 0xc000 + + +typedef struct vbe_mode_info_t { + uint32_t hdisplay; + uint32_t vdisplay; + float vrefresh; + float hsync; + uint64_t dot_clock; + uint16_t hsync_start; + uint16_t hsync_end; + uint16_t htotal; + uint16_t vsync_start; + uint16_t vsync_end; + uint16_t vtotal; +} vbe_mode_info_t; + +static video_timings_t timing_bochs = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; + +typedef struct bochs_vbe_t { + svga_t svga; + + uint8_t pci_conf_status; + uint8_t pci_rom_enable; + uint8_t pci_line_interrupt; + uint8_t slot; + + uint8_t pci_regs[256]; + + uint16_t vbe_index; + uint16_t bank_gran; + uint16_t rom_addr; + uint16_t id5_val; + + uint16_t vbe_regs[16]; + + uint32_t vram_size; + + rom_t bios_rom; + + mem_mapping_t linear_mapping; + mem_mapping_t linear_mapping_2; + uint32_t ma_latch_old; + + void * i2c; + void * ddc; +} bochs_vbe_t; + +static bochs_vbe_t *reset_state = NULL; + +static void +gen_mode_info(int hdisplay, int vdisplay, float vrefresh, vbe_mode_info_t* mode_info) +{ + int vsync; + int vsync_and_back_porch; + + mode_info->hdisplay = hdisplay; + mode_info->vdisplay = vdisplay; + mode_info->vrefresh = vrefresh; + + /* 1) top/bottom margin size (% of height) - default: 1.8 */ +#define CVT_MARGIN_PERCENTAGE 1.8 + + /* 2) character cell horizontal granularity (pixels) - default 8 */ +#define CVT_H_GRANULARITY 8 + + /* 4) Minimum vertical front porch (lines) - default 3 */ +#define CVT_MIN_V_PORCH_RND 3 + + /* 4) Minimum number of vertical back porch lines - default 6 */ +#define CVT_MIN_V_BPORCH 6 + + /* Pixel Clock step (kHz) */ +#define CVT_CLOCK_STEP 250 + + /* CVT default is 60.0Hz */ + if (!mode_info->vrefresh) + mode_info->vrefresh = 60.0; + + /* 1. Required field rate */ + const float vfield_rate = mode_info->vrefresh; + + /* 2. Horizontal pixels */ + const int hdisplay_rnd = mode_info->hdisplay - (mode_info->hdisplay % CVT_H_GRANULARITY); + + /* 3. Determine left and right borders */ + const int hmargin = 0; + + /* 4. Find total active pixels */ + mode_info->hdisplay = hdisplay_rnd + (2 * hmargin); + + /* 5. Find number of lines per field */ + const int vdisplay_rnd = mode_info->vdisplay; + + /* 6. Find top and bottom margins */ + const int vmargin = 0; + + mode_info->vdisplay = mode_info->vdisplay + 2 * vmargin; + + /* 7. interlace */ + /* Please rename this */ + const float interlace = 0.0; + + /* Determine vsync Width from aspect ratio */ + if (!(mode_info->vdisplay % 3) && ((mode_info->vdisplay * 4 / 3) == mode_info->hdisplay)) + vsync = 4; + else if (!(mode_info->vdisplay % 9) && + ((mode_info->vdisplay * 16 / 9) == mode_info->hdisplay)) + vsync = 5; + else if (!(mode_info->vdisplay % 10) && + ((mode_info->vdisplay * 16 / 10) == mode_info->hdisplay)) + vsync = 6; + else if (!(mode_info->vdisplay % 4) && + ((mode_info->vdisplay * 5 / 4) == mode_info->hdisplay)) + vsync = 7; + else if (!(mode_info->vdisplay % 9) && + ((mode_info->vdisplay * 15 / 9) == mode_info->hdisplay)) + vsync = 7; + else /* Custom */ + vsync = 10; + + /* Simplified GTF calculation. */ + + /* 4) Minimum time of vertical sync + back porch interval (µs) + * default 550.0 */ +#define CVT_MIN_VSYNC_BP 550.0 + + /* 3) Nominal HSync width (% of line period) - default 8 */ +#define CVT_HSYNC_PERCENTAGE 8 + + /* 8. Estimated Horizontal period */ + const float hperiod = ((float) (1000000.0 / vfield_rate - CVT_MIN_VSYNC_BP)) / + (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH_RND + interlace); + + /* 9. Find number of lines in sync + backporch */ + if (((int) (CVT_MIN_VSYNC_BP / hperiod) + 1) < (vsync + CVT_MIN_V_BPORCH)) + vsync_and_back_porch = vsync + CVT_MIN_V_BPORCH; + else + vsync_and_back_porch = (int) (CVT_MIN_VSYNC_BP / hperiod) + 1; + + /* 10. Find number of lines in back porch */ + + /* 11. Find total number of lines in vertical field */ + mode_info->vtotal = vdisplay_rnd + (2 * vmargin) + vsync_and_back_porch + interlace + + CVT_MIN_V_PORCH_RND; + + /* 5) Definition of Horizontal blanking time limitation */ + /* Gradient (%/kHz) - default 600 */ +#define CVT_M_FACTOR 600 + + /* Offset (%) - default 40 */ +#define CVT_C_FACTOR 40 + + /* Blanking time scaling factor - default 128 */ +#define CVT_K_FACTOR 128 + + /* Scaling factor weighting - default 20 */ +#define CVT_J_FACTOR 20 + +#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 +#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ + CVT_J_FACTOR + + /* 12. Find ideal blanking duty cycle from formula */ + float hblank_percentage = CVT_C_PRIME - CVT_M_PRIME * hperiod / 1000.0; + + /* 13. Blanking time */ + if (hblank_percentage < 20) + hblank_percentage = 20; + + int hblank = mode_info->hdisplay * hblank_percentage / (100.0 - hblank_percentage); + hblank -= hblank % (2 * CVT_H_GRANULARITY); + + /* 14. Find total number of pixels in a line. */ + mode_info->htotal = mode_info->hdisplay + hblank; + + /* Fill in HSync values */ + mode_info->hsync_end = mode_info->hdisplay + hblank / 2; + + int hsync_w = (mode_info->htotal * CVT_HSYNC_PERCENTAGE) / 100; + hsync_w -= hsync_w % CVT_H_GRANULARITY; + mode_info->hsync_start = mode_info->hsync_end - hsync_w; + + /* Fill in vsync values */ + mode_info->vsync_start = mode_info->vdisplay + CVT_MIN_V_PORCH_RND; + mode_info->vsync_end = mode_info->vsync_start + vsync; + + /* 15/13. Find pixel clock frequency (kHz for xf86) */ + mode_info->dot_clock = mode_info->htotal * 1000.0 / hperiod; + mode_info->dot_clock -= mode_info->dot_clock % CVT_CLOCK_STEP; + + /* 16/14. Find actual Horizontal Frequency (kHz) */ + mode_info->hsync = ((float) mode_info->dot_clock) / ((float) mode_info->htotal); + + /* 17/15. Find actual Field rate */ + mode_info->vrefresh = (1000.0 * ((float) mode_info->dot_clock)) / + ((float) (mode_info->htotal * mode_info->vtotal)); + + /* 18/16. Find actual vertical frame frequency */ + /* ignore - we don't do interlace here */ +} + +void +bochs_vbe_recalctimings(svga_t* svga) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) svga->priv; + + if (dev->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + vbe_mode_info_t mode = { 0 }; + svga->bpp = dev->vbe_regs[VBE_DISPI_INDEX_BPP]; + dev->vbe_regs[VBE_DISPI_INDEX_XRES] &= ~7; + if (dev->vbe_regs[VBE_DISPI_INDEX_XRES] == 0) { + dev->vbe_regs[VBE_DISPI_INDEX_XRES] = 8; + } + if (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] > VBE_DISPI_MAX_XRES) + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = VBE_DISPI_MAX_XRES; + if (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] < dev->vbe_regs[VBE_DISPI_INDEX_XRES]) + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = dev->vbe_regs[VBE_DISPI_INDEX_XRES]; + if (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] > VBE_DISPI_MAX_XRES) + dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = VBE_DISPI_MAX_XRES; + if (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] > VBE_DISPI_MAX_YRES) + dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = VBE_DISPI_MAX_YRES; + + if (dev->vbe_regs[VBE_DISPI_INDEX_YRES] == 0) + dev->vbe_regs[VBE_DISPI_INDEX_YRES] = 1; + if (dev->vbe_regs[VBE_DISPI_INDEX_YRES] > VBE_DISPI_MAX_YRES) + dev->vbe_regs[VBE_DISPI_INDEX_YRES] = VBE_DISPI_MAX_YRES; + gen_mode_info(dev->vbe_regs[VBE_DISPI_INDEX_XRES], + dev->vbe_regs[VBE_DISPI_INDEX_YRES], 72.f, &mode); + svga->char_width = 1; + svga->dots_per_clock = 1; + svga->clock = (cpuclock * (double) (1ULL << 32)) / (mode.dot_clock * 1000.); + svga->dispend = mode.vdisplay; + svga->hdisp = mode.hdisplay; + svga->vsyncstart = mode.vsync_start; + svga->vtotal = mode.vtotal; + svga->htotal = mode.htotal; + svga->hblankstart = mode.hdisplay; + svga->hblankend = mode.hdisplay + (mode.htotal - mode.hdisplay - 1); + svga->vblankstart = svga->dispend; /* no vertical overscan. */ + svga->rowcount = 0; + svga->hoverride = 1; + if (dev->vbe_regs[VBE_DISPI_INDEX_BPP] != 4) { + svga->fb_only = 1; + svga->adv_flags |= FLAG_NO_SHIFT3; + } else { + svga->fb_only = 0; + svga->adv_flags &= ~FLAG_NO_SHIFT3; + } + + svga->bpp = dev->vbe_regs[VBE_DISPI_INDEX_BPP]; + + if (svga->bpp == 4) { + svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); + } else { + svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); + } + if (svga->ma_latch != dev->ma_latch_old) { + if (svga->bpp == 4) { + svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + + (svga->ma_latch << 2); + } else { + svga->maback = (svga->maback - (dev->ma_latch_old)) + + (svga->ma_latch); + dev->ma_latch_old = svga->ma_latch; + } + } + + if (svga->bpp == 4) + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (svga->vram_max * 2) / dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; + else + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (svga->vram_max / ((svga->bpp == 15) ? 2 : (svga->bpp / 8))) / dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH]; + svga->split = 0xffffff; + + switch (svga->bpp) { + case 4: + svga->render = svga_render_4bpp_highres; + break; + default: + case 8: + svga->render = svga_render_8bpp_clone_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; + } + } else { + svga->fb_only = 0; + svga->packed_4bpp = 0; + svga->adv_flags &= ~FLAG_NO_SHIFT3; + svga->hoverride = 0; + } +} + +uint16_t +bochs_vbe_inw(const uint16_t addr, void *priv) +{ + const bochs_vbe_t *dev = (bochs_vbe_t *) priv; + const bool vbe_get_caps = !!(dev->vbe_regs[VBE_DISPI_INDEX_ENABLE] & + VBE_DISPI_GETCAPS); + uint16_t ret; + + if (addr == 0x1ce) + ret = dev->vbe_index; + else switch (dev->vbe_index) { + default: + ret = dev->vbe_regs[dev->vbe_index]; + break; + case VBE_DISPI_INDEX_XRES: + ret = vbe_get_caps ? VBE_DISPI_MAX_XRES : dev->vbe_regs[dev->vbe_index]; + break; + case VBE_DISPI_INDEX_YRES: + ret = vbe_get_caps ? VBE_DISPI_MAX_YRES : dev->vbe_regs[dev->vbe_index]; + break; + case VBE_DISPI_INDEX_BPP: + ret = vbe_get_caps ? 32 : dev->vbe_regs[dev->vbe_index]; + break; + case VBE_DISPI_INDEX_VIDEO_MEMORY_64K: + ret = dev->vram_size >> 16; + break; + case VBE_DISPI_INDEX_BANK: + ret = vbe_get_caps ? (VBE_DISPI_BANK_GRANULARITY_32K << 8) : + dev->vbe_regs[dev->vbe_index]; + break; + case VBE_DISPI_INDEX_DDC: + if (dev->vbe_regs[dev->vbe_index] & (1 << 7)) { + ret = dev->vbe_regs[dev->vbe_index] & ((1 << 7) | 0x3); + if ((ret & 0x01) && i2c_gpio_get_scl(dev->i2c)) + ret |= 0x04; + if ((ret & 0x02) && i2c_gpio_get_sda(dev->i2c)) + ret |= 0x08; + } else + ret = 0x000f; + break; + } + + return ret; +} + +uint32_t +bochs_vbe_inl(const uint16_t addr, void *priv) +{ + const bochs_vbe_t *dev = (bochs_vbe_t *) priv; + uint32_t ret; + + if (addr == 0x1ce) + ret = dev->vbe_index; + else + ret = dev->vram_size; + + return ret; +} + +void +bochs_vbe_outw(const uint16_t addr, const uint16_t val, void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) priv; + + if (addr == 0x1ce) + dev->vbe_index = val; + else if ((addr == 0x1cf) || (addr == 0x1d0)) switch (dev->vbe_index) { + default: + break; + case VBE_DISPI_INDEX_ID: + if ((val == VBE_DISPI_ID0) || (val == VBE_DISPI_ID1) || + (val == VBE_DISPI_ID2) || (val == VBE_DISPI_ID3) || + (val == VBE_DISPI_ID4)) + dev->vbe_regs[dev->vbe_index] = val; + else if (val == VBE_DISPI_ID5) + dev->vbe_regs[dev->vbe_index] = dev->id5_val; + break; + case VBE_DISPI_INDEX_XRES: + case VBE_DISPI_INDEX_YRES: + case VBE_DISPI_INDEX_BPP: + case VBE_DISPI_INDEX_VIRT_WIDTH: + case VBE_DISPI_INDEX_X_OFFSET: + case VBE_DISPI_INDEX_Y_OFFSET: + dev->vbe_regs[dev->vbe_index] = val; + if (dev->vbe_index == VBE_DISPI_INDEX_X_OFFSET || dev->vbe_index == VBE_DISPI_INDEX_Y_OFFSET) { + svga_t *svga = &dev->svga; + if (svga->bpp == 4) { + svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3; + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3); + } else { + svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)); + svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) + + (dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8))); + } + if (svga->ma_latch != dev->ma_latch_old) { + if (svga->bpp == 4) { + svga->maback = (svga->maback - (dev->ma_latch_old << 2)) + + (svga->ma_latch << 2); + } else { + svga->maback = (svga->maback - (dev->ma_latch_old)) + + (svga->ma_latch); + dev->ma_latch_old = svga->ma_latch; + } + } + } + else + svga_recalctimings(&dev->svga); + break; + + case VBE_DISPI_INDEX_BANK: + if (val & VBE_DISPI_BANK_RD) + dev->svga.read_bank = (val & 0x1ff) * (dev->bank_gran << 10); + if (val & VBE_DISPI_BANK_WR) + dev->svga.write_bank = (val & 0x1ff) * (dev->bank_gran << 10); + break; + + case VBE_DISPI_INDEX_DDC: + if (val & (1 << 7)) { + i2c_gpio_set(dev->i2c, !!(val & 1), !!(val & 2)); + dev->vbe_regs[dev->vbe_index] = val; + } else + dev->vbe_regs[dev->vbe_index] &= ~(1 << 7); + break; + + case VBE_DISPI_INDEX_ENABLE: { + uint32_t new_bank_gran; + dev->vbe_regs[dev->vbe_index] = val; + if ((val & VBE_DISPI_ENABLED) && + !(dev->vbe_regs[VBE_DISPI_ENABLED] & VBE_DISPI_ENABLED)) { + dev->vbe_regs[dev->vbe_index] = val; + dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0; + dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0; + dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0; + svga_recalctimings(&dev->svga); + if (!(val & VBE_DISPI_NOCLEARMEM)) { + memset(dev->svga.vram, 0, + dev->vbe_regs[VBE_DISPI_INDEX_YRES] * dev->svga.rowoffset); + } + } else + dev->svga.read_bank = dev->svga.write_bank = 0; + if ((val & VBE_DISPI_BANK_GRANULARITY_32K) != 0) + new_bank_gran = 32; + else + new_bank_gran = 64; + if (dev->bank_gran != new_bank_gran) { + dev->bank_gran = new_bank_gran; + dev->svga.read_bank = dev->svga.write_bank = 0; + } + if (val & VBE_DISPI_8BIT_DAC) + dev->svga.adv_flags &= ~FLAG_RAMDAC_SHIFT; + else + dev->svga.adv_flags |= FLAG_RAMDAC_SHIFT; + dev->vbe_regs[dev->vbe_index] &= ~VBE_DISPI_NOCLEARMEM; + } + } +} + +void +bochs_vbe_outl(const uint16_t addr, const uint32_t val, void *priv) +{ + bochs_vbe_outw(addr, val & 0xffff, priv); + bochs_vbe_outw(addr + 2, val >> 16, priv); +} + +void +bochs_vbe_out(uint16_t addr, uint8_t val, void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_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 VBE_DISPI_IOPORT_INDEX: + dev->vbe_index = val; + return; + case VBE_DISPI_IOPORT_DATA: + bochs_vbe_outw(0x1cf, val | (bochs_vbe_inw(0x1cf, dev) & 0xFF00), dev); + return; + case VBE_DISPI_IOPORT_DATA + 1: + bochs_vbe_outw(0x1cf, (val << 8) | (bochs_vbe_inw(0x1cf, dev) & 0xFF), dev); + return; + 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 +bochs_vbe_in(uint16_t addr, void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) priv; + svga_t * svga = &dev->svga; + uint8_t ret; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + default: + ret = svga_in(addr, svga); + break; + case VBE_DISPI_IOPORT_INDEX: + ret = dev->vbe_index; + break; + case VBE_DISPI_IOPORT_DATA: + ret = bochs_vbe_inw(0x1cf, dev); + break; + case VBE_DISPI_IOPORT_DATA + 1: + ret = bochs_vbe_inw(0x1cf, dev) >> 8; + break; + case 0x3D4: + ret = svga->crtcreg; + break; + case 0x3D5: + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; + break; + } + + return ret; +} + +static uint8_t +bochs_vbe_pci_read(const int func, const int addr, void *priv) +{ + const bochs_vbe_t *dev = (bochs_vbe_t *) priv; + uint8_t ret = 0x00; + + if (func == 0x00) switch (addr) { + default: + break; + case 0x00: + ret = (dev->id5_val == VBE_DISPI_ID5) ? 0x34 : 0xee; + break; + case 0x01: + ret = (dev->id5_val == VBE_DISPI_ID5) ? 0x12 : 0x80; + break; + case 0x02: + ret = (dev->id5_val == VBE_DISPI_ID5) ? 0x11 : 0xef; + break; + case 0x03: + ret = (dev->id5_val == VBE_DISPI_ID5) ? 0x11 : 0xbe; + break; + case 0x04: + ret = (dev->pci_conf_status & 0b11100011) | 0x80; + break; + case 0x06: + ret = 0x80; + break; + case 0x07: + ret = 0x02; + break; + case 0x0b: + ret = 0x03; + break; + case 0x13: + ret = dev->pci_regs[addr]; + break; + case 0x17: + ret = (dev->pci_regs[0x13] != 0x00) ? 0xe0 : 0x00; + break; + case 0x30: + ret = dev->pci_rom_enable & 0x01; + break; + case 0x32: + ret = dev->rom_addr & 0xff; + break; + case 0x33: + ret = (dev->rom_addr & 0xff00) >> 8; + break; + case 0x3c: + ret = dev->pci_line_interrupt; + break; + case 0x3d: + ret = 0x01; + break; + } else + ret = 0xff; + + return ret; +} + +static void +bochs_vbe_disable_handlers(bochs_vbe_t *dev) +{ + io_removehandler(0x03c0, 0x0020, bochs_vbe_in, NULL, NULL, + bochs_vbe_out, NULL, NULL, dev); + io_removehandler(0x01ce, 0x0003, bochs_vbe_in, bochs_vbe_inw, + bochs_vbe_inl, bochs_vbe_out, bochs_vbe_outw, bochs_vbe_outl, dev); + + mem_mapping_disable(&dev->linear_mapping_2); + mem_mapping_disable(&dev->linear_mapping); + mem_mapping_disable(&dev->svga.mapping); + mem_mapping_disable(&dev->bios_rom.mapping); + + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->linear_mapping_2 = dev->linear_mapping_2; + reset_state->linear_mapping = dev->linear_mapping; + reset_state->svga.mapping = dev->svga.mapping; + reset_state->bios_rom.mapping = dev->bios_rom.mapping; + + reset_state->svga.timer = dev->svga.timer; + reset_state->svga.timer8514 = dev->svga.timer8514; +} + +static void +bochs_vbe_pci_write(const int func, const int addr, const uint8_t val, void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) priv; + + if (func == 0x00) switch (addr) { + default: + break; + case 0x04: + dev->pci_conf_status = val; + io_removehandler(0x03c0, 0x0020, bochs_vbe_in, NULL, NULL, + bochs_vbe_out, NULL, NULL, dev); + io_removehandler(0x01ce, 0x0003, bochs_vbe_in, bochs_vbe_inw, + bochs_vbe_inl, bochs_vbe_out, bochs_vbe_outw, bochs_vbe_outl, dev); + mem_mapping_disable(&dev->linear_mapping_2); + mem_mapping_disable(&dev->linear_mapping); + mem_mapping_disable(&dev->svga.mapping); + if (dev->pci_conf_status & PCI_COMMAND_IO) { + io_sethandler(0x03c0, 0x0020, bochs_vbe_in, NULL, NULL, + bochs_vbe_out, NULL, NULL, dev); + io_sethandler(0x01ce, 0x0003, bochs_vbe_in, bochs_vbe_inw, bochs_vbe_inl, + bochs_vbe_out, bochs_vbe_outw, bochs_vbe_outl, dev); + } + if (dev->pci_conf_status & PCI_COMMAND_MEM) { + mem_mapping_enable(&dev->svga.mapping); + if (dev->pci_regs[0x13] != 0x00) { + mem_mapping_enable(&dev->linear_mapping); + if (dev->pci_regs[0x13] != 0xe0) + mem_mapping_enable(&dev->linear_mapping_2); + } + } + break; + case 0x13: + dev->pci_regs[addr] = val; + + mem_mapping_disable(&dev->linear_mapping_2); + mem_mapping_disable(&dev->linear_mapping); + + if ((dev->pci_conf_status & PCI_COMMAND_MEM) && (val != 0x00)) { + mem_mapping_set_addr(&dev->linear_mapping, val << 24, 0x01000000); + if (val != 0xe0) + mem_mapping_set_addr(&dev->linear_mapping_2, 0xe0000000, 0x01000000); + } + break; + case 0x3c: + dev->pci_line_interrupt = val; + break; + case 0x30: + dev->pci_rom_enable = val & 0x01; + mem_mapping_disable(&dev->bios_rom.mapping); + if (dev->pci_rom_enable) + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + break; + case 0x32: + dev->rom_addr = (dev->rom_addr & 0xff00) | (val & 0xfc); + if (dev->pci_rom_enable) + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + break; + case 0x33: + dev->rom_addr = (dev->rom_addr & 0x00ff) | (val << 8); + if (dev->pci_rom_enable) + mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr << 16, 0x10000); + break; + } +} + +static void +bochs_vbe_reset(void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) priv; + + if (reset_state != NULL) { + bochs_vbe_disable_handlers(dev); + reset_state->slot = dev->slot; + + *dev = *reset_state; + } +} + +static void * +bochs_vbe_init(const device_t *info) +{ + bochs_vbe_t *dev = calloc(1, sizeof(bochs_vbe_t)); + reset_state = calloc(1, sizeof(bochs_vbe_t)); + + dev->id5_val = device_get_config_int("revision"); + dev->vram_size = device_get_config_int("memory") * (1 << 20); + + rom_init(&dev->bios_rom, "roms/video/bochs/VGABIOS-lgpl-latest.bin", + 0xc0000, 0x10000, 0xffff, 0x0000, + MEM_MAPPING_EXTERNAL); + + if (dev->id5_val == VBE_DISPI_ID4) { + /* Patch the BIOS to match the PCI ID. */ + dev->bios_rom.rom[0x010c] = 0xee; + dev->bios_rom.rom[0x8dff] -= (0xee - 0x34); + + dev->bios_rom.rom[0x010d] = 0x80; + dev->bios_rom.rom[0x8dff] -= (0x80 - 0x12); + + dev->bios_rom.rom[0x010e] = 0xef; + dev->bios_rom.rom[0x8dff] -= (0xef - 0x11); + + dev->bios_rom.rom[0x010f] = 0xbe; + dev->bios_rom.rom[0x8dff] -= (0xbe - 0x11); + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_bochs); + + svga_init(info, &dev->svga, dev, dev->vram_size, + bochs_vbe_recalctimings, + bochs_vbe_in, bochs_vbe_out, + NULL, + NULL); + + mem_mapping_add(&dev->linear_mapping, 0, 0, + svga_readb_linear, svga_readw_linear, svga_readl_linear, + svga_writeb_linear, svga_writew_linear, svga_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, &dev->svga); + /* Hack: If the mapping gets mapped anywhere other than at 0xe0000000, + enable this second copy of it at 0xe0000000 so michaln's driver works. */ + mem_mapping_add(&dev->linear_mapping_2, 0, 0, + svga_readb_linear, svga_readw_linear, svga_readl_linear, + svga_writeb_linear, svga_writew_linear, svga_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, &dev->svga); + + mem_mapping_disable(&dev->bios_rom.mapping); + + mem_mapping_disable(&dev->svga.mapping); + + mem_mapping_disable(&dev->linear_mapping); + mem_mapping_disable(&dev->linear_mapping_2); + + dev->svga.bpp = 8; + dev->svga.miscout = 1; + + dev->bank_gran = 64; + + svga_set_ramdac_type(&dev->svga, RAMDAC_8BIT); + + dev->svga.adv_flags |= FLAG_RAMDAC_SHIFT; + dev->svga.decode_mask = 0xffffff; + + dev->i2c = i2c_gpio_init("ddc_bochs"); + dev->ddc = ddc_init(i2c_gpio_get_bus(dev->i2c)); + dev->svga.packed_chain4 = 1; + + pci_add_card(PCI_ADD_NORMAL, bochs_vbe_pci_read, bochs_vbe_pci_write, dev, &dev->slot); + + *reset_state = *dev; + + return dev; +} + +static int +bochs_vbe_available(void) +{ + return rom_present("roms/video/bochs/VGABIOS-lgpl-latest.bin"); +} + +void +bochs_vbe_close(void *priv) +{ + bochs_vbe_t *dev = (bochs_vbe_t *) priv; + + ddc_close(dev->ddc); + i2c_gpio_close(dev->i2c); + + svga_close(&dev->svga); + + free(reset_state); + reset_state = NULL; + + free(dev); +} + +void +bochs_vbe_speed_changed(void *priv) +{ + bochs_vbe_t *bochs_vbe = (bochs_vbe_t *) priv; + + svga_recalctimings(&bochs_vbe->svga); +} + +void +bochs_vbe_force_redraw(void *priv) +{ + bochs_vbe_t *bochs_vbe = (bochs_vbe_t *) priv; + + bochs_vbe->svga.fullchange = changeframecount; +} + +static const device_config_t bochs_vbe_config[] = { + // clang-format off + { + .name = "revision", + .description = "Revision", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "VirtualBox", + .value = VBE_DISPI_ID4 + }, + { + .description = "Bochs latest", + .value = VBE_DISPI_ID5 + }, + { + .description = "" + } + }, + .default_int = VBE_DISPI_ID5 + }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "16 MB", + .value = 16 + }, + { + .description = "" + } + }, + .default_int = 16 + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +const device_t bochs_svga_device = { + .name = "Bochs SVGA", + .internal_name = "bochs_svga", + .flags = DEVICE_PCI, + .local = 0, + .init = bochs_vbe_init, + .close = bochs_vbe_close, + .reset = bochs_vbe_reset, + { .available = bochs_vbe_available }, + .speed_changed = bochs_vbe_speed_changed, + .force_redraw = bochs_vbe_force_redraw, + .config = bochs_vbe_config +}; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 3d806d95b..2ea07c346 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -43,11 +43,29 @@ #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 +#define DOUBLE_NONE 0 +#define DOUBLE_SIMPLE 1 +#define DOUBLE_INTERPOLATE_SRGB 2 +#define DOUBLE_INTERPOLATE_LINEAR 3 + +typedef union +{ + uint32_t color; + struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + }; +} color_t; + 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 interp_lut[2][256][256]; + 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); @@ -201,24 +219,275 @@ cga_recalctimings(cga_t *cga) cga->dispofftime = (uint64_t) (_dispofftime); } -void -cga_poll(void *priv) +static void +cga_render(cga_t *cga, int line) { - 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; + + if ((cga->cgamode & 0x12) == 0x12) { + for (c = 0; c < 8; ++c) { + buffer32->line[line][c] = 0; + if (cga->cgamode & 1) + buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = 0; + else + buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = 0; + } + } else { + for (c = 0; c < 8; ++c) { + buffer32->line[line][c] = (cga->cgacol & 15) + 16; + if (cga->cgamode & 1) + buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; + else + buffer32->line[line][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[line][(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[line][(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[line][(x << 4) + (c << 1) + 8] + = buffer32->line[line][(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[line][(x << 4) + (c << 1) + 8] + = buffer32->line[line][(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[line][(x << 4) + (c << 1) + 8] + = buffer32->line[line][(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[line][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } +} + +static void +cga_render_blank(cga_t *cga, int line) +{ + int col = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; + + if (cga->cgamode & 1) + hline(buffer32, 0, line, (cga->crtc[1] << 3) + 16, col); + else + hline(buffer32, 0, line, (cga->crtc[1] << 4) + 16, col); +} + +static void +cga_render_process(cga_t *cga, int line) +{ + int x; + uint8_t border; + + if (cga->cgamode & 1) + x = (cga->crtc[1] << 3) + 16; + else + x = (cga->crtc[1] << 4) + 16; + + if (cga->composite) { + border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); + + Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]); + } else + video_process_8(x, line); +} + +static uint8_t +cga_interpolate_srgb(uint8_t co1, uint8_t co2, double fraction) +{ + uint8_t ret = ((co2 - co1) * fraction + co1); + + return ret; +} + +static uint8_t +cga_interpolate_linear(uint8_t co1, uint8_t co2, double fraction) +{ + double c1, c2; + double r1, r2; + uint8_t ret; + + c1 = ((double) co1) / 255.0; + c1 = pow((co1 >= 0) ? c1 : -c1, 2.19921875); + if (co1 <= 0) + c1 = -c1; + c2 = ((double) co2) / 255.0; + c2 = pow((co2 >= 0) ? c2 : -c2, 2.19921875); + if (co2 <= 0) + c2 = -c2; + r1 = ((c2 - c1) * fraction + c1); + r2 = pow((r1 >= 0.0) ? r1 : -r1, 1.0 / 2.19921875); + if (r1 <= 0.0) + r2 = -r2; + ret = (uint8_t) (r2 * 255.0); + + return ret; +} + +static color_t +cga_interpolate_lookup(cga_t *cga, color_t color1, color_t color2, double fraction) +{ + color_t ret; + uint8_t dt = cga->double_type - DOUBLE_INTERPOLATE_SRGB; + + ret.a = 0x00; + ret.r = interp_lut[dt][color1.r][color2.r]; + ret.g = interp_lut[dt][color1.g][color2.g]; + ret.b = interp_lut[dt][color1.b][color2.b]; + + return ret; +} + +static void +cga_interpolate(cga_t *cga, int x, int y, int w, int h) +{ + double quotient = 0.5; + + for (int i = y; i < (y + h); i++) { + if (i & 1) for (int j = x; j < (x + w); j++) { + int prev = i - 1; + int next = i + 1; + color_t prev_color, next_color; + color_t black; + color_t interim_1, interim_2; + color_t final; + + if (i < 0) + continue; + + black.color = 0x00000000; + + if ((prev >= 0) && (prev < (y + h))) + prev_color.color = buffer32->line[prev][j]; + else + prev_color.color = 0x00000000; + + if ((next >= 0) && (next < (y + h))) + next_color.color = buffer32->line[next][j]; + else + next_color.color = 0x00000000; + + interim_1 = cga_interpolate_lookup(cga, prev_color, black, quotient); + interim_2 = cga_interpolate_lookup(cga, black, next_color, quotient); + final = cga_interpolate_lookup(cga, interim_1, interim_2, quotient); + + buffer32->line[i][j] = final.color; + } + } +} + +static void +cga_blit_memtoscreen(cga_t *cga, int x, int y, int w, int h) +{ + if (cga->double_type > DOUBLE_SIMPLE) + cga_interpolate(cga, x, y, w, h); + + video_blit_memtoscreen(x, y, w, h); +} + +void +cga_poll(void *priv) +{ + cga_t *cga = (cga_t *) priv; + int x; int oldsc; + int oldvc; + int xs_temp; + int ys_temp; + int old_ma; if (!cga->linepos) { timer_advance_u64(&cga->timer, cga->dispofftime); @@ -233,143 +502,44 @@ cga_poll(void *priv) 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; - } - } + switch (cga->double_type) { + default: + cga_render(cga, cga->displine << 1); + cga_render_blank(cga, (cga->displine << 1) + 1); + break; + case DOUBLE_NONE: + cga_render(cga, cga->displine); + break; + case DOUBLE_SIMPLE: + old_ma = cga->ma; + cga_render(cga, cga->displine << 1); + cga->ma = old_ma; + cga_render(cga, (cga->displine << 1) + 1); + break; } } 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]); + switch (cga->double_type) { + default: + cga_render_blank(cga, cga->displine << 1); + break; + case DOUBLE_NONE: + cga_render_blank(cga, cga->displine); + break; + case DOUBLE_SIMPLE: + cga_render_blank(cga, cga->displine << 1); + cga_render_blank(cga, (cga->displine << 1) + 1); + break; } } - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; - else - x = (cga->crtc[1] << 4) + 16; - - if (cga->composite) { - border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); - - Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[cga->displine]); - } else { - video_process_8(x, cga->displine); + switch (cga->double_type) { + default: + cga_render_process(cga, cga->displine << 1); + cga_render_process(cga, (cga->displine << 1) + 1); + break; + case DOUBLE_NONE: + cga_render_process(cga, cga->displine); + break; } cga->sc = oldsc; @@ -386,7 +556,8 @@ cga_poll(void *priv) 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))) { + 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; } @@ -445,6 +616,8 @@ cga_poll(void *priv) xs_temp = x; ys_temp = cga->lastline - cga->firstline; + if (cga->double_type > DOUBLE_NONE) + ys_temp <<= 1; if ((xs_temp > 0) && (ys_temp > 0)) { if (xs_temp < 64) @@ -454,21 +627,33 @@ cga_poll(void *priv) if (!enable_overscan) xs_temp -= 16; - if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { + 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 (cga->double_type > DOUBLE_NONE) + set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + else + set_screen_size(xsize, ysize + (enable_overscan ? 8 : 0)); if (video_force_resize_get()) video_force_resize_set(0); } - if (enable_overscan) { - video_blit_memtoscreen(0, cga->firstline - 4, - xsize, (cga->lastline - cga->firstline) + 8); + if (cga->double_type > DOUBLE_NONE) { + if (enable_overscan) + cga_blit_memtoscreen(cga, 0, (cga->firstline - 4) << 1, + xsize, ((cga->lastline - cga->firstline) << 1) + 16); + else + cga_blit_memtoscreen(cga, 8, cga->firstline << 1, + xsize, (cga->lastline - cga->firstline) << 1); } else { - video_blit_memtoscreen(8, cga->firstline, - xsize, cga->lastline - cga->firstline); + 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); } } @@ -502,7 +687,8 @@ cga_poll(void *priv) } 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))) + 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++) @@ -546,6 +732,15 @@ cga_standalone_init(UNUSED(const device_t *info)) cgapal_rebuild(); update_cga16_color(cga->cgamode); + cga->double_type = device_get_config_int("double_type"); + + for (uint16_t i = 0; i < 256; i++) { + for (uint16_t j = 0; j < 256; j++) { + interp_lut[0][i][j] = cga_interpolate_srgb(i, j, 0.5); + interp_lut[1][i][j] = cga_interpolate_linear(i, j, 0.5); + } + } + return cga; } @@ -625,10 +820,10 @@ const device_config_t cga_config[] = { .name = "rgb_type", .description = "RGB type", .type = CONFIG_SELECTION, - .default_int = 0, + .default_int = 5, .selection = { { - .description = "Color", + .description = "Color (generic)", .value = 0 }, { @@ -647,6 +842,37 @@ const device_config_t cga_config[] = { .description = "Color (no brown)", .value = 4 }, + { + .description = "Color (IBM 5153)", + .value = 5 + }, + { + .description = "" + } + } + }, + { + .name = "double_type", + .description = "Line doubling type", + .type = CONFIG_SELECTION, + .default_int = DOUBLE_NONE, + .selection = { + { + .description = "None", + .value = DOUBLE_NONE + }, + { + .description = "Simple doubling", + .value = DOUBLE_SIMPLE + }, + { + .description = "sRGB interpolation", + .value = DOUBLE_INTERPOLATE_SRGB + }, + { + .description = "Linear interpolation", + .value = DOUBLE_INTERPOLATE_LINEAR + }, { .description = "" } @@ -665,7 +891,7 @@ const device_config_t cga_config[] = { // clang-format on const device_t cga_device = { - .name = "CGA", + .name = "IBM CGA", .internal_name = "cga", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c new file mode 100644 index 000000000..d91ab1a8b --- /dev/null +++ b/src/video/vid_chips_69000.c @@ -0,0 +1,2551 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * 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&T 69000 emulation. + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2023-2024 Cacodemon345 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.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> +#include <86box/pci.h> +#include <86box/thread.h> +#include <86box/i2c.h> +#include <86box/vid_ddc.h> +#include <86box/plat_unused.h> +#include <86box/bswap.h> +#include + +#pragma pack(push, 1) +typedef struct chips_69000_bitblt_t +{ + /* BR00 - Source and Destination Span Register. */ + uint16_t source_span; + uint16_t destination_span; + + /* BR01 - Pattern/Source Expansion Background Color & Transparency Key Register. */ + uint32_t pattern_source_key_bg; + + /* BR02 - Pattern/Source Expansion Foreground Color Register. */ + uint32_t pattern_source_key_fg; + + /* BR03 - Monochrome Source Control Register. */ + uint8_t monochrome_source_left_clip; + uint8_t monochrome_source_right_clip; + uint8_t monochrome_source_initial_discard; + uint8_t monochrome_source_alignment : 3; + uint8_t monochrome_source_expansion_color_reg_select : 1; + uint8_t dummy_8 : 4; + + /* BR04 - BitBLT Control Register. */ + uint32_t bitblt_control; + + /* BR05 - Pattern Address Register. */ + uint32_t pat_addr; + + /* BR06 - Source Address Register. */ + uint32_t source_addr; + + /* BR07 - Destination Address Register. */ + uint32_t destination_addr; + + /* BR08 - Destination Width & Height Register. */ + uint16_t destination_width; + uint16_t destination_height; + + /* BR09 - Source Expansion Background Color & Transparency Key Register. */ + uint32_t source_key_bg; + + /* BR0A - Source Expansion Foreground Color Register. */ + uint32_t source_key_fg; +} chips_69000_bitblt_t; +#pragma pack(pop) + +typedef struct chips_69000_t { + svga_t svga; + uint8_t pci_conf_status; + uint8_t slot, irq_state; + uint8_t pci_line_interrupt; + uint8_t pci_rom_enable; + uint8_t read_write_bank; + bool engine_active; + bool quit; + thread_t *accel_thread; + event_t *fifo_event, *fifo_data_event; + pc_timer_t decrement_timer; + uint16_t rom_addr; + mem_mapping_t linear_mapping; + uint8_t on_board; + + rgb_t cursor_palette[8]; + uint32_t cursor_pallook[8]; + + uint8_t mm_regs[256], mm_index; + uint8_t flat_panel_regs[256], flat_panel_index; + uint8_t ext_regs[256], ext_index; + + union { + uint32_t mem_regs[4]; + uint16_t mem_regs_w[4 * 2]; + uint8_t mem_regs_b[4 * 4]; + }; + union { + uint32_t bitblt_regs[11]; + uint16_t bitblt_regs_w[11 * 2]; + uint8_t bitblt_regs_b[11 * 4]; + struct chips_69000_bitblt_t bitblt; + }; + + struct + { + struct chips_69000_bitblt_t bitblt; + + uint32_t actual_source_height; + uint32_t actual_destination_height; + + uint32_t actual_destination_width; + + uint32_t count_x, count_y; + int x, y; + int x_dir, y_dir; + + uint8_t bytes_per_pixel; + + /* Byte counter for BitBLT port writes. */ + uint8_t bytes_written; + uint8_t bytes_skip; + uint32_t mono_bytes_pitch; + uint8_t mono_bits_skip_left; + uint32_t bytes_counter; + uint32_t bytes_in_line_written; + uint8_t bytes_port[256]; + } bitblt_running; + + union { + uint16_t subsys_vid; + uint8_t subsys_vid_b[2]; + }; + + union { + uint16_t subsys_pid; + uint8_t subsys_pid_b[2]; + }; + + rom_t bios_rom; + + void* i2c_ddc, *ddc; + + uint8_t st01; +} chips_69000_t; + +/* TODO: Probe timings on real hardware. */ +static video_timings_t timing_chips = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; + +uint8_t chips_69000_readb_linear(uint32_t addr, void *p); +uint16_t chips_69000_readw_linear(uint32_t addr, void *p); +uint32_t chips_69000_readl_linear(uint32_t addr, void *p); +void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p); +void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p); +void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p); + +/* Multimedia handling. */ +uint8_t +chips_69000_read_multimedia(chips_69000_t* chips) +{ + switch (chips->mm_index) { + case 0: + /* Report no playback/capture capability. */ + return 0; + default: + return chips->mm_regs[chips->mm_index]; + } + return chips->mm_regs[chips->mm_index]; +} + +/* Multimedia (write) handling. */ +void +chips_69000_write_multimedia(chips_69000_t* chips, uint8_t val) +{ + switch (chips->mm_index) { + case 0: + return; + default: + chips->mm_regs[chips->mm_index] = val; + break; + } + chips->mm_regs[chips->mm_index] = val; +} + +/* Flat panel handling. */ +uint8_t +chips_69000_read_flat_panel(chips_69000_t* chips) +{ + switch (chips->flat_panel_index) { + case 0: + return 1; + default: + return chips->flat_panel_regs[chips->flat_panel_index]; + } + return chips->flat_panel_regs[chips->flat_panel_index]; +} + +/* Flat panel (write) handling. */ +void +chips_69000_write_flat_panel(chips_69000_t* chips, uint8_t val) +{ + switch (chips->flat_panel_index) { + case 0: + return; + case 1: + case 0x20 ... 0x33: + case 0x35: + case 0x36: + chips->flat_panel_regs[chips->flat_panel_index] = val; + svga_recalctimings(&chips->svga); + return; + default: + chips->flat_panel_regs[chips->flat_panel_index] = val; + break; + } + chips->flat_panel_regs[chips->flat_panel_index] = val; +} + +void +chips_69000_interrupt(chips_69000_t* chips) +{ + pci_irq(chips->slot, PCI_INTA, 0, !!((chips->mem_regs[0] & chips->mem_regs[1]) & 0x80004040), &chips->irq_state); +} + +void +chips_69000_bitblt_interrupt(chips_69000_t* chips) +{ + chips->engine_active = 0; + chips->mem_regs[1] |= 1 << 31; + + chips_69000_interrupt(chips); +} + +void +chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFF; + break; + } +} + +void +chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFFFF; + break; + } +} + +void +chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) +{ + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_8bpp(dst, src, rop); + } + + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + } +} + +void +chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) +{ + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_16bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src, uint8_t rop) +{ + uint32_t orig_dst = *dst & 0xFF000000; + + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_24bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } + *dst &= 0xFFFFFF; + *dst |= orig_dst; +} + +void +chips_69000_recalctimings(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->priv); + + if (chips->ext_regs[0x81] & 0x10) { + svga->htotal -= 5; + } + + if (((chips->ext_regs[0x61] & 0x8) && !(chips->ext_regs[0x61] & 0x4)) + || ((chips->ext_regs[0x61] & 0x2) && !(chips->ext_regs[0x61] & 0x1))) { + svga->dpms = 1; + } else + svga->dpms = 0; + + if (chips->ext_regs[0x09] & 0x1) { + svga->vtotal -= 2; + svga->vtotal &= 0xFF; + svga->vtotal |= (svga->crtc[0x30] & 0xF) << 8; + svga->vtotal += 2; + + svga->dispend--; + svga->dispend &= 0xFF; + svga->dispend |= (svga->crtc[0x31] & 0xF) << 8; + svga->dispend++; + + svga->vsyncstart--; + svga->vsyncstart &= 0xFF; + svga->vsyncstart |= (svga->crtc[0x32] & 0xF) << 8; + svga->vsyncstart++; + + svga->vblankstart--; + svga->vblankstart &= 0xFF; + svga->vblankstart |= (svga->crtc[0x33] & 0xF) << 8; + svga->vblankstart++; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal -= 5; + + svga->htotal |= (svga->crtc[0x38] & 0x1) << 8; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal += 5; + + svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000); + svga->hblank_end_mask = 0xff; + + svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; + svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; + + svga->interlace = !!(svga->crtc[0x70] & 0x80); + + if (svga->hdisp == 1280 && svga->dispend == 1024) { + svga->interlace = 0; + } + + switch (chips->ext_regs[0x81] & 0xF) { + default: + svga->bpp = 8; + break; + case 0b0010: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + break; + + case 0b0100: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + break; + case 0b0101: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + case 0b0110: + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + break; + case 0b0111: + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + break; + } +#if 1 + if (chips->flat_panel_regs[0x01] & 0x2) { + /* TODO: Fix horizontal parameter calculations. */ + if (svga->hdisp > (((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3)) { + svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3; + //svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3; + //svga->hblank_end_val = svga->htotal - 1; + svga->hoverride = 1; + } else + svga->hoverride = 0; + + if (svga->dispend > (((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1))) { + svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1); + } + //svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3; + //svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3; + //svga->hblank_end_val = svga->htotal - 1; + //svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1); + //svga->vsyncstart = ((chips->flat_panel_regs[0x31] | ((chips->flat_panel_regs[0x35] & 0xF0) << 4)) + 1); + //svga->vtotal = ((chips->flat_panel_regs[0x33] | ((chips->flat_panel_regs[0x36] & 0xF) << 8)) + 2); + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((chips->flat_panel_regs[0x03] >> 2) & 3, svga->priv); + } else { + svga->hoverride = 0; + } +#endif + } else { + svga->bpp = 8; + svga->hoverride = 0; + } +} + +void +chips_69000_decrement_timer(void* p) +{ + chips_69000_t *chips = (chips_69000_t*)p; + + chips->ext_regs[0xD2]--; + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); +} + +void +chips_69000_recalc_banking(chips_69000_t *chips) +{ + svga_t* svga = &chips->svga; + chips->svga.read_bank = chips->svga.write_bank = 0; + + svga->chain2_write = !(svga->seqregs[0x4] & 4); + svga->chain4 = (svga->seqregs[0x4] & 8) || (chips->ext_regs[0xA] & 0x4); + 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); + + if (chips->ext_regs[0xA] & 1) { + chips->svga.read_bank = chips->svga.write_bank = 0x10000 * (chips->ext_regs[0xE] & 0x7f); + } + + /*if (chips->ext_regs[0x40] & 2) { + svga->decode_mask = (1 << 18) - 1; + } else { + svga->decode_mask = (1 << 21) - 1; + }*/ +} + +void +chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) +{ + uint32_t pattern_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t pattern_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + uint8_t pattern_data = 0; + uint32_t pattern_pixel = 0; + uint32_t dest_pixel = 0; + uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt_running.bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + uint8_t vert_pat_alignment = (chips->bitblt_running.bitblt.bitblt_control >> 20) & 7; + uint8_t orig_dest_addr_bit = chips->bitblt_running.bitblt.destination_addr & 1; + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16; + break; + } + } + + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr >>= 1; + } + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) { + uint8_t is_true = 0; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) + pattern_data = 0; + else + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); + + is_true = !!(pattern_data & (1 << (7 - ((chips->bitblt_running.bitblt.destination_addr + chips->bitblt_running.x) & 7)))); + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 17))) { + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr <<= 1; + chips->bitblt_running.bitblt.destination_addr |= orig_dest_addr_bit; + } + return; + } + + pattern_pixel = is_true ? pattern_fg : pattern_bg; + + pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + } else { + if (chips->bitblt_running.bytes_per_pixel == 1) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); + } + if (chips->bitblt_running.bytes_per_pixel == 2) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + } + if (chips->bitblt_running.bytes_per_pixel == 3) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; + } + } + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr <<= 1; + chips->bitblt_running.bitblt.destination_addr |= orig_dest_addr_bit; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 1: + case 3: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_do_rop_8bpp_patterned((uint8_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_do_rop_16bpp_patterned((uint16_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_do_rop_24bpp_patterned((uint32_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 0: + case 2: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips); + break; + } + } +} + +void +chips_69000_process_mono_bit(chips_69000_t* chips, uint8_t val) +{ + uint32_t pixel = 0x0; + uint8_t is_true = !!val; + uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + + if (!chips->engine_active) + return; + + if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { + source_fg = chips->bitblt_running.bitblt.source_key_fg; + source_bg = chips->bitblt_running.bitblt.source_key_bg; + } + + if (chips->bitblt_running.bitblt.monochrome_source_initial_discard) { + chips->bitblt_running.bitblt.monochrome_source_initial_discard--; + return; + } + + if (chips->bitblt_running.mono_bits_skip_left) { + chips->bitblt_running.mono_bits_skip_left--; + return; + } + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { + goto advance; + } + pixel = is_true ? source_fg : source_bg; + pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + chips_69000_process_pixel(chips, pixel); + +advance: + chips->bitblt_running.x += chips->bitblt_running.x_dir; + chips->bitblt_running.count_x += 1; + if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + chips->bitblt_running.count_y += 1; + chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + if (chips->bitblt_running.count_y >= (chips->bitblt_running.actual_destination_height)) + chips_69000_bitblt_interrupt(chips); + } +} + +void chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data); + +void +chips_69000_setup_bitblt(chips_69000_t* chips) +{ + chips->engine_active = 1; + + memset(&chips->bitblt_running, 0, sizeof(chips->bitblt_running)); + chips->bitblt_running.bitblt = chips->bitblt; + chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; + chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; + chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; + chips->bitblt_running.bytes_written = 0; + chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.bytes_in_line_written = 0; + chips->bitblt_running.bytes_skip = 0; + chips->bitblt_running.mono_bytes_pitch = 0; + chips->bitblt_running.mono_bits_skip_left = 0; + int orig_cycles = cycles; + + if (chips->bitblt.bitblt_control & (1 << 23)) { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); + } else { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->ext_regs[0x20] >> 4) & 3); + } + + chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel; + + chips->bitblt_running.x = 0; + chips->bitblt_running.y = 0; + + switch ((chips->bitblt_running.bitblt.bitblt_control >> 8) & 3) { + case 0: + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = 1; + break; + case 1: + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = 1; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + break; + case 2: + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = -1; + break; + case 3: + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = -1; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + break; + } + + /* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */ + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) { + chips_69000_bitblt_interrupt(chips); + return; + } + +#if 0 + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " + "monochrome left clip = %d, " + "monochrome right clip = %d, " + "monochrome initial discard = %d, " + "destination_width = %d, destination_height = %d)\n", chips->bitblt_running.bitblt.monochrome_source_alignment, + chips->bitblt_running.bitblt.monochrome_source_left_clip, + chips->bitblt_running.bitblt.monochrome_source_right_clip, + chips->bitblt_running.bitblt.monochrome_source_initial_discard, + chips->bitblt_running.bitblt.destination_width, + chips->bitblt_running.bitblt.destination_height); + } +#endif + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + chips->bitblt_running.bitblt.source_addr &= 7; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + /* Yes, the NT 4.0 and Linux drivers will send this many amount of bytes to the video adapter on quadword-boundary-crossing image blits. + This weird calculation is intended and deliberate. + */ + if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) + chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); + } else { + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5) + chips->bitblt_running.bitblt.monochrome_source_alignment = 0; + + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { + chips->bitblt_running.mono_bytes_pitch = ((chips->bitblt_running.actual_destination_width + chips->bitblt_running.bitblt.monochrome_source_left_clip + 63) & ~63) / 8; + } + } + + return; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr; + + while (chips->engine_active) { + switch (chips->bitblt_running.bitblt.monochrome_source_alignment) { + case 0: /* Source-span aligned. */ + { + /* Note: This value means quadword-alignment when BitBLT port is the source. */ + /* TODO: This is handled purely on a best case basis. */ + uint32_t orig_count_y = chips->bitblt_running.count_y; + uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; + while (orig_count_y == chips->bitblt_running.count_y) { + int i = 0; + uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); + orig_source_addr++; + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(data & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + break; + } + } + if ((source_addr + chips->bitblt_running.bitblt.source_span) == orig_source_addr) + break; + } + + source_addr = chips->bitblt_running.bitblt.source_addr + chips->bitblt_running.bitblt.source_span; + chips->bitblt_running.bitblt.source_addr = source_addr; + break; + } + case 1: /* Bit-aligned */ + case 2: /* Byte-aligned */ + { + uint32_t data = chips_69000_readb_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + source_addr += 1; + break; + } + case 3: /* Word-aligned*/ + { + uint32_t data = chips_69000_readw_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + source_addr += 2; + break; + } + case 4: /* Doubleword-aligned*/ + { + uint32_t data = chips_69000_readl_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + source_addr += 4; + break; + } + case 5: /* Quadword-aligned*/ + { + uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 32ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 40ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 48ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 56ull) & 0xFF); + source_addr += 8; + break; + } + } + } + return; + } + + do { + do { + uint32_t pixel = 0; + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.y * chips->bitblt.source_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16; + break; + } + } + + chips_69000_process_pixel(chips, pixel); + + chips->bitblt_running.x += chips->bitblt_running.x_dir; + } while ((++chips->bitblt_running.count_x) < chips->bitblt_running.actual_destination_width); + + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); + cycles = orig_cycles; + chips_69000_bitblt_interrupt(chips); +} + +void +chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { + + if (!chips->engine_active) { + return; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + int orig_cycles = cycles; + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 1) { + uint8_t val = chips->bitblt_running.bytes_port[0]; + int i = 0; + chips->bitblt_running.bytes_written = 0; + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && chips->bitblt_running.mono_bytes_pitch && chips->bitblt_running.mono_bytes_pitch == chips->bitblt_running.bytes_written) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0, j = 0; + chips->bitblt_running.bytes_written = 0; + + for (j = 0; j < chips->bitblt_running.mono_bytes_pitch; j++) { + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(chips->bitblt_running.bytes_port[j] & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } + } + else if ((chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && !chips->bitblt_running.mono_bytes_pitch) + || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint8_t val = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y && chips->bitblt_running.bitblt.monochrome_source_alignment != 1) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 3 + && chips->bitblt_running.bytes_written == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint16_t val = (chips->bitblt_running.bytes_port[1]) | (chips->bitblt_running.bytes_port[0] << 8); + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 16; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (15 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 + && chips->bitblt_running.bytes_written == 4) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint32_t val = chips->bitblt_running.bytes_port[3] | (chips->bitblt_running.bytes_port[2] << 8) | (chips->bitblt_running.bytes_port[1] << 16) | (chips->bitblt_running.bytes_port[0] << 24); + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 32; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (31 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5 && chips->bitblt_running.bytes_written == 8) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint64_t val = 0; + + val |= chips->bitblt_running.bytes_port[7]; + val |= chips->bitblt_running.bytes_port[6] << 8; + val |= chips->bitblt_running.bytes_port[5] << 16; + val |= chips->bitblt_running.bytes_port[4] << 24; + val |= (uint64_t)chips->bitblt_running.bytes_port[3] << 32ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[2] << 40ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[1] << 48ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[0] << 56ULL; + + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 64; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (63 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } + cycles = orig_cycles; + return; + } + + chips->bitblt_running.bytes_counter++; + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr)) { + return; + } + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { + int orig_cycles = cycles; + uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + if (chips->bitblt_running.bytes_per_pixel >= 2) + source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); + if (chips->bitblt_running.bytes_per_pixel >= 3) + source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); + + chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; + + chips_69000_process_pixel(chips, source_pixel); + cycles = orig_cycles; + chips->bitblt_running.x += chips->bitblt_running.x_dir; + + if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { + if (chips->bitblt_running.bytes_skip) { + chips->bitblt_running.bitblt.source_addr = chips->bitblt_running.bytes_skip; + } + else if (chips->bitblt_running.bitblt.destination_width & 7) + chips->bitblt_running.bitblt.source_addr = 8 - ((chips->bitblt_running.bitblt.destination_width) & 7); + else + chips->bitblt_running.bitblt.source_addr = 0; + + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_y++; + chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.bytes_in_line_written = 0; + + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + + if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) { + chips_69000_bitblt_interrupt(chips); + return; + } + } + } +} + +uint8_t +chips_69000_read_ext_reg(chips_69000_t* chips) +{ + uint8_t index = chips->ext_index; + uint8_t val = chips->ext_regs[index]; + switch (index) { + case 0x00: + val = 0x2C; + break; + case 0x01: + val = 0x10; + break; + case 0x02: + val = 0xC0; + break; + case 0x03: + val = 0x00; + break; + case 0x04: + val = 0x62; + break; + case 0x05: + val = 0x00; + break; + case 0x06: + val = chips->linear_mapping.base >> 24; + break; + case 0x08: + val = 0x02; + break; + case 0x0A: + val = chips->ext_regs[index] & 0x37; + break; + case 0x20: + val &= ~1; + val |= !!chips->engine_active; + /* TODO: Handle BitBLT reset, if required. */ + break; + case 0x63: + { + val = chips->ext_regs[index]; + if (!(chips->ext_regs[0x62] & 0x8)) + val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c_ddc) << 3); + + if (!(chips->ext_regs[0x62] & 0x4)) + val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c_ddc) << 2); + + break; + } + case 0x70: + val = 0x3; + break; + case 0x71: + val = 0b01101000; + break; + case 0xD0: + val |= 1; + break; + } + return val; +} + +void +chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) +{ + switch (chips->ext_index) { + case 0xA: + chips->ext_regs[chips->ext_index] = val & 0x37; + chips_69000_recalc_banking(chips); + break; + case 0xB: + chips->ext_regs[chips->ext_index] = val & 0xD; + break; + case 0xE: + chips->ext_regs[chips->ext_index] = val & 0x7f; + chips_69000_recalc_banking(chips); + break; + case 0x9: + chips->ext_regs[chips->ext_index] = val & 0x3; + svga_recalctimings(&chips->svga); + break; + case 0x40: + chips->ext_regs[chips->ext_index] = val & 0x3; + chips_69000_recalc_banking(chips); + svga_recalctimings(&chips->svga); + break; + case 0x60: + chips->ext_regs[chips->ext_index] = val & 0x43; + break; + case 0x20: + chips->ext_regs[chips->ext_index] = val & 0x3f; + break; + case 0x61: + chips->ext_regs[chips->ext_index] = val & 0x7f; + svga_recalctimings(&chips->svga); + break; + case 0x62: + chips->ext_regs[chips->ext_index] = val & 0x9C; + break; + case 0x63: + { + uint8_t scl = 0, sda = 0; + if (chips->ext_regs[0x62] & 0x8) + scl = !!(val & 8); + else + scl = i2c_gpio_get_scl(chips->i2c_ddc); + + if (chips->ext_regs[0x62] & 0x4) + sda = !!(val & 4); + else + scl = i2c_gpio_get_sda(chips->i2c_ddc); + + i2c_gpio_set(chips->i2c_ddc, scl, sda); + + chips->ext_regs[chips->ext_index] = val & 0x9F; + break; + } + case 0x67: + chips->ext_regs[chips->ext_index] = val & 0x2; + break; + case 0x80: + chips->ext_regs[chips->ext_index] = val & 0xBF; + svga_set_ramdac_type(&chips->svga, (val & 0x80) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; + case 0x81: + chips->ext_regs[chips->ext_index] = val & 0x1f; + svga_recalctimings(&chips->svga); + break; + case 0x82: + chips->ext_regs[chips->ext_index] = val & 0xf; + chips->svga.lut_map = !!(val & 0x8); + break; + case 0xA0: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.ena = ((val & 7) == 0b101) || ((val & 7) == 0b1); + chips->svga.hwcursor.cur_xsize = chips->svga.hwcursor.cur_ysize = ((val & 7) == 0b1) ? 32 : 64; + break; + case 0xA2: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = (val << 8) | ((chips->ext_regs[0xA3] & 0x3F) << 16); + break; + case 0xA3: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = ((chips->ext_regs[0xA2]) << 8) | ((val & 0x3F) << 16); + break; + case 0xA4: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = val | (chips->ext_regs[0xA5] & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; + break; + case 0xA5: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = chips->ext_regs[0xA4] | (val & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; + break; + case 0xA6: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = val | (chips->ext_regs[0xA7] & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) { + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + } + break; + case 0xA7: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) { + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + } + break; + case 0xC8: + case 0xC9: + case 0xCB: + chips->ext_regs[chips->ext_index] = val; + svga_recalctimings(&chips->svga); + break; + case 0xD2: + break; + default: + chips->ext_regs[chips->ext_index] = val; + break; + } +} + +void +chips_69000_out(uint16_t addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t old, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c0: + if (!(chips->ext_regs[0x09] & 0x02)) + break; + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + return; + case 0x3c1: + if ((chips->ext_regs[0x09] & 0x02)) + { + svga->attrff = 1; + svga_out(addr, val, svga); + svga->attrff = 0; + return; + } + break; + case 0x3c9: + if (!(chips->ext_regs[0x80] & 0x01)) + break; + 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 & 7; + chips->cursor_palette[index].r = svga->dac_r; + chips->cursor_palette[index].g = svga->dac_g; + chips->cursor_palette[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + chips->cursor_pallook[index] = makecol32(chips->cursor_palette[index].r, chips->cursor_palette[index].g, chips->cursor_palette[index].b); + else + chips->cursor_pallook[index] = makecol32(video_6to8[chips->cursor_palette[index].r & 0x3f], video_6to8[chips->cursor_palette[index].g & 0x3f], video_6to8[chips->cursor_palette[index].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + } + return; + case 0x3c5: + svga_out(addr, val, svga); + chips_69000_recalc_banking(chips); + return; + case 0x3D0: + chips->flat_panel_index = val; + return; + case 0x3D1: + return chips_69000_write_flat_panel(chips, val); + case 0x3D2: + chips->mm_index = val; + return; + case 0x3D3: + return chips_69000_write_multimedia(chips, val); + case 0x3D4: + svga->crtcreg = val & 0xff; + 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 0x3B6: + case 0x3D6: + chips->ext_index = val; + return; + case 0x3B7: + case 0x3D7: + return chips_69000_write_ext_reg(chips, val); + + } + svga_out(addr, val, svga); +} + +uint8_t +chips_69000_in(uint16_t addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t temp = 0, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3C5: + return svga->seqregs[svga->seqaddr]; + case 0x3c9: + if (!(chips->ext_regs[0x80] & 0x01)) { + temp = svga_in(addr, svga); + break; + } + index = (svga->dac_addr - 1) & 7; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].r; + else + temp = chips->cursor_palette[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].g; + else + temp = chips->cursor_palette[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].b; + else + temp = chips->cursor_palette[index].b & 0x3f; + break; + } + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + temp >>= 2; + break; + case 0x3D0: + return chips->flat_panel_index; + case 0x3D1: + return chips_69000_read_flat_panel(chips); + case 0x3D2: + return chips->mm_index; + case 0x3D3: + return chips_69000_read_multimedia(chips); + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; + break; + case 0x3B6: + case 0x3D6: + temp = chips->ext_index; + break; + case 0x3B7: + case 0x3D7: + temp = chips_69000_read_ext_reg(chips); + break; + default: + temp = svga_in(addr, svga); + break; + } + return temp; +} + +static uint8_t +chips_69000_pci_read(int func, int addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x00: + return 0x2C; + case 0x01: + return 0x10; + case 0x02: + return 0xC0; + case 0x03: + return 0x00; + case 0x04: + return (chips->pci_conf_status & 0b11100011) | 0x80; + case 0x06: + return 0x80; + case 0x07: + return 0x02; + case 0x08: + case 0x09: + case 0x0a: + return 0x00; + case 0x0b: + return 0x03; + case 0x13: + return chips->linear_mapping.base >> 24; + case 0x30: + return chips->pci_rom_enable & 0x1; + case 0x31: + return 0x0; + case 0x32: + return chips->rom_addr & 0xFF; + case 0x33: + return (chips->rom_addr & 0xFF00) >> 8; + case 0x3c: + return chips->pci_line_interrupt; + case 0x3d: + return 0x01; + case 0x2C: + case 0x2D: + case 0x6C: + case 0x6D: + return (chips->subsys_vid >> ((addr & 1) * 8)) & 0xFF; + case 0x2E: + case 0x2F: + case 0x6E: + case 0x6F: + return (chips->subsys_pid >> ((addr & 1) * 8)) & 0xFF; + default: + return 0x00; + } + } +} + +static void +chips_69000_pci_write(int func, int addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x04: + { + chips->pci_conf_status = val; + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (chips->pci_conf_status & PCI_COMMAND_IO) { + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + } + if (chips->pci_conf_status & PCI_COMMAND_MEM) { + mem_mapping_enable(&chips->svga.mapping); + if (chips->linear_mapping.base) + mem_mapping_enable(&chips->linear_mapping); + } + break; + } + case 0x13: + { + if (!chips->linear_mapping.enable) { + chips->linear_mapping.base = val << 24; + break; + } + mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24)); + break; + } + case 0x3c: + chips->pci_line_interrupt = val; + break; + case 0x30: + if (chips->on_board) break; + chips->pci_rom_enable = val & 0x1; + mem_mapping_disable(&chips->bios_rom.mapping); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x32: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF; + chips->rom_addr |= val & 0xFC; + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x33: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF00; + chips->rom_addr |= (val << 8); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x6C: + case 0x6D: + chips->subsys_vid_b[addr & 1] = val; + break; + case 0x6E: + case 0x6F: + chips->subsys_pid_b[addr & 1] = val; + break; + } + } +} + +uint8_t +chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + case 0x00 ... 0x2B: + if (addr == 0x13) { + return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); + } + return chips->bitblt_regs_b[addr & 0xFF]; + case 0x3b: + return (chips->engine_active ? 0x80 : 0x00); + case 0x38: + return 0x7F; + case 0x600 ... 0x60F: + return chips->mem_regs_b[addr & 0xF]; + case 0x768: + return chips_69000_in(0x3b4, chips); + case 0x769: + return chips_69000_in(0x3b5, chips); + case 0x774: + return chips_69000_in(0x3ba, chips); + case 0x780: + return chips_69000_in(0x3c0, chips); + case 0x781: + return chips_69000_in(0x3c1, chips); + case 0x784: + return chips_69000_in(0x3c2, chips); + case 0x788: + return chips_69000_in(0x3c4, chips); + case 0x789: + return chips_69000_in(0x3c5, chips); + case 0x78C: + return chips_69000_in(0x3c6, chips); + case 0x78D: + return chips_69000_in(0x3c7, chips); + case 0x790: + return chips_69000_in(0x3c8, chips); + case 0x791: + return chips_69000_in(0x3c9, chips); + case 0x794: + return chips_69000_in(0x3ca, chips); + case 0x798: + return chips_69000_in(0x3cc, chips); + case 0x79C: + return chips_69000_in(0x3ce, chips); + case 0x79D: + return chips_69000_in(0x3cf, chips); + case 0x7A0: + return chips_69000_in(0x3d0, chips); + case 0x7A1: + return chips_69000_in(0x3d1, chips); + case 0x7A4: + return chips_69000_in(0x3d2, chips); + case 0x7A5: + return chips_69000_in(0x3d3, chips); + case 0x7A8: + return chips_69000_in(0x3d4, chips); + case 0x7A9: + return chips_69000_in(0x3d5, chips); + case 0x7AC: + return chips_69000_in(0x3d6, chips); + case 0x7AD: + return chips_69000_in(0x3d7, chips); + case 0x7B4: + return chips_69000_in(0x3da, chips); + } + return 0x00; +} + +uint16_t +chips_69000_readw_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + return chips_69000_readb_mmio(addr, chips) | (chips_69000_readb_mmio(addr + 1, chips) << 8); + } + return 0xFFFF; +} + +uint32_t +chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + return chips_69000_readw_mmio(addr, chips) | (chips_69000_readw_mmio(addr + 2, chips) << 16); + } + return 0xFFFFFFFF; +} + +void +chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) +{ + //pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); + if (addr & 0x10000) { + chips_69000_bitblt_write(chips, val); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + case 0x00 ... 0x2B: + if (addr <= 0x3) { + //pclog("[%04X:%08X] C&T Write span 0x%X, val = 0x%02X\n", CS, cpu_state.pc, addr, val); + } + chips->bitblt_regs_b[addr & 0xFF] = val; + if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { + chips_69000_setup_bitblt(chips); + } + break; + default: + pclog("C&T Write (unknown) 0x%X, val = 0x%02X\n", addr, val); + break; + case 0x600 ... 0x60F: + switch (addr & 0xFFF) + { + case 0x600 ... 0x603: + { + chips->mem_regs_b[addr & 0xF] = val; + chips->mem_regs[(addr >> 2) & 0x3] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x604 ... 0x607: + { + chips->mem_regs_b[addr & 0xF] &= ~val; + chips->mem_regs[(addr >> 2) & 0x3] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x60c ... 0x60f: + { + chips->mem_regs_b[addr & 0xF] = val; + break; + } + + } + chips->mem_regs_b[addr & 0xF] = val; + break; + case 0x768: + chips_69000_out(0x3b4, val, chips); break; + case 0x769: + chips_69000_out(0x3b5, val, chips); break; + case 0x774: + chips_69000_out(0x3ba, val, chips); break; + case 0x780: + chips_69000_out(0x3c0, val, chips); break; + case 0x781: + chips_69000_out(0x3c1, val, chips); break; + case 0x784: + chips_69000_out(0x3c2, val, chips); break; + case 0x788: + chips_69000_out(0x3c4, val, chips); break; + case 0x789: + chips_69000_out(0x3c5, val, chips); break; + case 0x78C: + chips_69000_out(0x3c6, val, chips); break; + case 0x78D: + chips_69000_out(0x3c7, val, chips); break; + case 0x790: + chips_69000_out(0x3c8, val, chips); break; + case 0x791: + chips_69000_out(0x3c9, val, chips); break; + case 0x794: + chips_69000_out(0x3ca, val, chips); break; + case 0x798: + chips_69000_out(0x3cc, val, chips); break; + case 0x79C: + chips_69000_out(0x3ce, val, chips); break; + case 0x79D: + chips_69000_out(0x3cf, val, chips); break; + case 0x7A0: + chips_69000_out(0x3d0, val, chips); break; + case 0x7A1: + chips_69000_out(0x3d1, val, chips); break; + case 0x7A4: + chips_69000_out(0x3d2, val, chips); break; + case 0x7A5: + chips_69000_out(0x3d3, val, chips); break; + case 0x7A8: + chips_69000_out(0x3d4, val, chips); break; + case 0x7A9: + chips_69000_out(0x3d5, val, chips); break; + case 0x7AC: + chips_69000_out(0x3d6, val, chips); break; + case 0x7AD: + chips_69000_out(0x3d7, val, chips); break; + case 0x7B4: + chips_69000_out(0x3da, val, chips); break; + } +} + +void +chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) +{ + if (addr & 0x10000) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + //pclog("BitBLT mono 0x%04X\n", val); + } + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + chips_69000_writeb_mmio(addr, val, chips); + chips_69000_writeb_mmio(addr + 1, val >> 8, chips); + break; + } +} + +void +chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) +{ + if (addr & 0x10000) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + //pclog("BitBLT mono 0x%08X\n", val); + } + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 24) & 0xFF); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + chips_69000_writew_mmio(addr, val, chips); + chips_69000_writew_mmio(addr + 2, val >> 16, chips); + break; + } +} + +uint8_t +chips_69000_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x400000) + return chips_69000_readb_mmio(addr, chips); + + return svga_readb_linear(addr & 0x1FFFFF, p); +} + +uint16_t +chips_69000_readw_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap16(chips_69000_readw_mmio(addr, chips)); + + return bswap16(svga_readw_linear(addr & 0x1FFFFF, p)); + } + + if (addr & 0x400000) + return chips_69000_readw_mmio(addr, chips); + + return svga_readw_linear(addr & 0x1FFFFF, p); +} + +uint32_t +chips_69000_readl_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap32(chips_69000_readl_mmio(addr, chips)); + + return bswap32(svga_readl_linear(addr & 0x1FFFFF, p)); + } + + if (addr & 0x400000) + return chips_69000_readl_mmio(addr, chips); + + return svga_readl_linear(addr & 0x1FFFFF, p); +} + +void +chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x400000) + return chips_69000_writeb_mmio(addr, val, chips); + + svga_writeb_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) + val = bswap16(val); + + if (addr & 0x400000) + return chips_69000_writew_mmio(addr, val, chips); + + svga_writew_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) + val = bswap32(val); + + if (addr & 0x400000) + return chips_69000_writel_mmio(addr, val, chips); + + svga_writel_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_vblank_start(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + chips->mem_regs[1] |= 1 << 14; + chips->svga.crtc[0x40] &= ~0x80; + + chips_69000_interrupt(chips); +} + +static void +chips_69000_hwcursor_draw_64x64(svga_t *svga, int displine) +{ + chips_69000_t *chips = (chips_69000_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; + + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + + for (uint8_t x = 0; x < 64; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + +static void +chips_69000_hwcursor_draw(svga_t *svga, int displine) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + if ((chips->ext_regs[0xa0] & 7) == 0b101) + return chips_69000_hwcursor_draw_64x64(svga, displine); + + if (svga->interlace) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + if (svga->hwcursor_oddeven) { + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } + for (uint8_t x = 0; x < 32; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + return; + } + + if ((svga->hwcursor_on & 1)) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr - 16])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[(svga->hwcursor_latch.addr - 16) + 8])); + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } + else { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + } + + for (uint8_t x = 0; x < 32; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } +} + +static float +chips_69000_getclock(int clock, void *priv) +{ + const chips_69000_t *chips = (chips_69000_t *) priv; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + + int m = chips->ext_regs[0xc8]; + int n = chips->ext_regs[0xc9]; + int pl = ((chips->ext_regs[0xcb] >> 4) & 7); + + float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); + if (chips->ext_regs[0xcb] & 4) + fvco *= 4.0; + float fo = fvco / (float)(1 << pl); + + return fo; +} + +uint32_t +chips_69000_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + uint32_t ret = 0x00000000; + + if (svga->lut_map) { + if (bpp == 15) { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 2]); + uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 7]); + ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b); + } else { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 3]); + uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 8]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } + } else + ret = (bpp == 15) ? video_15to32[color] : video_16to32[color]; + + return ret; +} + +static int +chips_69000_line_compare(svga_t* svga) +{ + const chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (chips->ext_regs[0x81] & 0xF) { + return 0; + } + + return 1; +} + +static void * +chips_69000_init(const device_t *info) +{ + chips_69000_t *chips = calloc(1, sizeof(chips_69000_t)); + + /* Appears to have an odd VBIOS size. */ + if (!info->local) { + rom_init(&chips->bios_rom, "roms/video/chips/69000.ROM", 0xc0000, 0x10000, 0xffff, 0x0000, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&chips->bios_rom.mapping); + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_chips); + + svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ + chips_69000_recalctimings, + chips_69000_in, chips_69000_out, + NULL, + NULL); + + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + + pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); + + chips->svga.bpp = 8; + chips->svga.miscout = 1; + chips->svga.recalctimings_ex = chips_69000_recalctimings; + chips->svga.vblank_start = chips_69000_vblank_start; + chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; + chips->svga.getclock = chips_69000_getclock; + chips->svga.conv_16to32 = chips_69000_conv_16to32; + chips->svga.line_compare = chips_69000_line_compare; + + mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); + + chips->quit = 0; + chips->engine_active = 0; + chips->on_board = !!(info->local); + + chips->svga.packed_chain4 = 1; + + timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); + + chips->i2c_ddc = i2c_gpio_init("c&t_69000_mga"); + chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c_ddc)); + + chips->flat_panel_regs[0x01] = 1; + + return chips; +} + +static int +chips_69000_available(void) +{ + return rom_present("roms/video/chips/69000.ROM"); +} + +void +chips_69000_close(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->quit = 1; +// thread_set_event(chips->fifo_event); + // thread_wait(chips->accel_thread); + ddc_close(chips->ddc); + i2c_gpio_close(chips->i2c_ddc); + svga_close(&chips->svga); + + free(chips); +} + +void +chips_69000_speed_changed(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + svga_recalctimings(&chips->svga); +} + +void +chips_69000_force_redraw(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->svga.fullchange = changeframecount; +} + +const device_t chips_69000_device = { + .name = "Chips & Technologies B69000", + .internal_name = "c&t_69000", + .flags = DEVICE_PCI, + .local = 0, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; + +const device_t chips_69000_onboard_device = { + .name = "Chips & Technologies B69000 (onboard)", + .internal_name = "c&t_69000_onboard", + .flags = DEVICE_PCI, + .local = 1, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 05e45b7d7..bf27a700a 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -809,13 +809,14 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256)); break; case 0x07: - svga->packed_chain4 = svga->seqregs[7] & 1; + svga->packed_chain4 = svga->seqregs[0x07] & CIRRUS_SR7_BPP_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; + svga->set_reset_disabled = svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA; + gd54xx_set_svga_fast(gd54xx); svga_recalctimings(svga); break; @@ -1641,8 +1642,6 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx) } else svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; } - - svga->write_bank = svga->read_bank = svga->extra_banks[0]; } static void @@ -1661,7 +1660,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) gd54xx->mmio_vram_overlap = 0; - if (!gd54xx_is_5422(svga) || !(svga->seqregs[7] & 0xf0) || !(svga->seqregs[0x07] & 0x01)) { + if (!gd54xx_is_5422(svga) || !(svga->seqregs[0x07] & 0xf0) || !(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->aperture2_mapping); switch (svga->gdcreg[6] & 0x0c) { @@ -1687,7 +1686,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) break; } - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & 0x01) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) && (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); @@ -1698,10 +1697,10 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) } 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; + base = (svga->seqregs[0x07] & 0xf0) << 16; size = 1 * 1024 * 1024; } else { - base = (svga->seqregs[7] & 0xe0) << 16; + base = (svga->seqregs[0x07] & 0xe0) << 16; size = 2 * 1024 * 1024; } } else if (gd54xx->pci) { @@ -1751,6 +1750,34 @@ gd54xx_recalctimings(svga_t *svga) uint8_t rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + svga->hblankstart = svga->crtc[2]; + + if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { + /* Special blanking mode: the blank start and end become components of the window generator, + and the actual blanking comes from the display enable signal. */ + /* This means blanking during overscan, we already calculate it that way, so just use the + same calculation and force otvercan to 0. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | + (((svga->crtc[0x1a] >> 4) & 3) << 6); + + svga->hblank_end_mask = 0x000000ff; + + if (svga->crtc[0x1b] & 0x20) { + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } + } + svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); @@ -1760,13 +1787,15 @@ gd54xx_recalctimings(svga_t *svga) } svga->map8 = svga->pallook; - if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) { + if (svga->seqregs[0x07] & 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)) + if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } } } else if (svga->gdcreg[5] & 0x40) svga->render = svga_render_8bpp_lowres; @@ -1807,7 +1836,7 @@ gd54xx_recalctimings(svga_t *svga) break; case 5: - if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { + if (gd54xx_is_5434(svga) && (svga->seqregs[0x07] & CIRRUS_SR7_BPP_32)) { svga->bpp = 32; if (linedbl) svga->render = svga_render_32bpp_lowres; @@ -1844,7 +1873,7 @@ gd54xx_recalctimings(svga_t *svga) break; case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { + switch (svga->seqregs[0x07] & CIRRUS_SR7_BPP_MASK) { case CIRRUS_SR7_BPP_32: if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { svga->bpp = 32; @@ -1924,7 +1953,7 @@ gd54xx_recalctimings(svga_t *svga) 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)) { + switch (svga->seqregs[0x07] & (gd54xx_is_5434(svga) ? 0xe : 6)) { case 2: freq /= 2.0F; break; @@ -1942,12 +1971,20 @@ gd54xx_recalctimings(svga_t *svga) svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) + svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) { + if (svga->seqregs[1] & 8) svga->render = svga_render_text_40; - } else + else svga->render = svga_render_text_80; } + + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { + svga->extra_banks[0] = 0; + svga->extra_banks[1] = 0x8000; + } } static void @@ -1970,11 +2007,11 @@ gd54xx_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += pitch; for (int x = 0; x < svga->hwcursor.cur_xsize; x += 8) { - dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask]; + dat[0] = svga->vram[svga->hwcursor_latch.addr & gd54xx->vram_mask]; if (svga->hwcursor.cur_xsize == 64) - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & gd54xx->vram_mask]; else - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & gd54xx->vram_mask]; for (uint8_t xx = 0; xx < 8; xx++) { b0 = (dat[0] >> (7 - xx)) & 1; b1 = (dat[1] >> (7 - xx)) & 1; @@ -2074,18 +2111,49 @@ gd54xx_rop(gd54xx_t *gd54xx, uint8_t *res, uint8_t *dst, const uint8_t *src) } static uint8_t -gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx) +gd54xx_get_aperture(uint32_t addr) { + uint32_t ap = addr >> 22; + return (uint8_t) (ap & 0x03); +} + +static uint32_t +gd54xx_mem_sys_pos_adj(gd54xx_t *gd54xx, uint8_t ap, uint32_t pos) +{ + uint32_t ret = pos; + + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && + !(gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) { + switch (ap) { + case 1: + ret ^= 1; + break; + case 2: + ret ^= 3; + break; + } + } + + return ret; +} + +static uint8_t +gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx, uint8_t ap) +{ + uint32_t adj_pos = gd54xx_mem_sys_pos_adj(gd54xx, ap, gd54xx->blt.msd_buf_pos); uint8_t ret = 0xff; if (gd54xx->blt.msd_buf_cnt != 0) { - ret = gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos++]; + ret = gd54xx->blt.msd_buf[adj_pos]; + + 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)) + 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); @@ -2098,14 +2166,17 @@ gd54xx_mem_sys_dest_read(gd54xx_t *gd54xx) } static void -gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val) +gd54xx_mem_sys_src_write(gd54xx_t *gd54xx, uint8_t val, uint8_t ap) { - gd54xx->blt.sys_src32 &= ~(0xff << (gd54xx->blt.sys_cnt << 3)); - gd54xx->blt.sys_src32 |= (val << (gd54xx->blt.sys_cnt << 3)); + uint32_t adj_pos = gd54xx_mem_sys_pos_adj(gd54xx, ap, gd54xx->blt.sys_cnt); + + gd54xx->blt.sys_src32 &= ~(0xff << (adj_pos << 3)); + gd54xx->blt.sys_src32 |= (val << (adj_pos << 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)) { + 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 @@ -2120,17 +2191,12 @@ gd54xx_write(uint32_t addr, uint8_t val, void *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 ((svga->seqregs[0x07] & 0x01) == 0) { - svga_write(addr, val, svga); + gd54xx_mem_sys_src_write(gd54xx, val, 0); return; } + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; - svga_write_linear(addr, val, svga); } @@ -2146,11 +2212,7 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writew(addr, val, svga); - return; - } - + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; if (svga->writemode < 4) @@ -2175,11 +2237,7 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writel(addr, val, svga); - return; - } - + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; if (svga->writemode < 4) @@ -2251,13 +2309,6 @@ gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) svga->changedvram[addr >> 12] = changeframecount; } -static uint8_t -gd54xx_get_aperture(uint32_t addr) -{ - uint32_t ap = addr >> 22; - return (uint8_t) (ap & 0x03); -} - static int gd54xx_aperture2_enabled(gd54xx_t *gd54xx) { @@ -2284,7 +2335,7 @@ gd54xx_readb_linear(uint32_t addr, void *priv) uint8_t ap = gd54xx_get_aperture(addr); addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_read_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2294,7 +2345,7 @@ gd54xx_readb_linear(uint32_t addr, void *priv) /* 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); + return gd54xx_mem_sys_dest_read(gd54xx, ap); switch (ap) { default: @@ -2318,15 +2369,16 @@ gd54xx_readb_linear(uint32_t addr, void *priv) static uint16_t gd54xx_readw_linear(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t old_addr = addr; uint8_t ap = gd54xx_get_aperture(addr); uint16_t temp; addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_readw_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2338,8 +2390,8 @@ gd54xx_readw_linear(uint32_t addr, void *priv) /* 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, priv); - temp |= gd54xx_readb_linear(addr + 1, priv) << 8; + temp = gd54xx_readb_linear(old_addr, priv); + temp |= gd54xx_readb_linear(old_addr + 1, priv) << 8; return temp; } @@ -2367,15 +2419,16 @@ gd54xx_readw_linear(uint32_t addr, void *priv) static uint32_t gd54xx_readl_linear(uint32_t addr, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t old_addr = addr; uint8_t ap = gd54xx_get_aperture(addr); uint32_t temp; addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_readl_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2387,10 +2440,10 @@ gd54xx_readl_linear(uint32_t addr, void *priv) /* 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, 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; + temp = gd54xx_readb_linear(old_addr, priv); + temp |= gd54xx_readb_linear(old_addr + 1, priv) << 8; + temp |= gd54xx_readb_linear(old_addr + 2, priv) << 16; + temp |= gd54xx_readb_linear(old_addr + 3, priv) << 24; return temp; } @@ -2427,9 +2480,11 @@ static uint8_t gd5436_aperture2_readb(UNUSED(uint32_t addr), void *priv) { gd54xx_t *gd54xx = (gd54xx_t *) priv; + uint8_t ap = gd54xx_get_aperture(addr); - 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, ap); return 0xff; } @@ -2440,7 +2495,8 @@ gd5436_aperture2_readw(uint32_t addr, void *priv) 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)) { + 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; @@ -2455,7 +2511,8 @@ gd5436_aperture2_readl(uint32_t addr, void *priv) 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)) { + 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; @@ -2470,10 +2527,11 @@ static void gd5436_aperture2_writeb(UNUSED(uint32_t addr), uint8_t val, void *priv) { gd54xx_t *gd54xx = (gd54xx_t *) priv; + uint8_t ap = gd54xx_get_aperture(addr); - 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); + 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, ap); } static void @@ -2481,8 +2539,8 @@ gd5436_aperture2_writew(uint32_t addr, uint16_t val, void *priv) { gd54xx_t *gd54xx = (gd54xx_t *) priv; - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest - && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + 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); } @@ -2493,8 +2551,8 @@ gd5436_aperture2_writel(uint32_t addr, uint32_t val, void *priv) { gd54xx_t *gd54xx = (gd54xx_t *) priv; - if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest - && gd54xx_aperture2_enabled(gd54xx) && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + 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); @@ -2508,9 +2566,9 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv) 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); - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_write_linear(addr, val, svga); return; } @@ -2526,7 +2584,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv) /* 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); + gd54xx_mem_sys_src_write(gd54xx, val, ap); return; } @@ -2552,12 +2610,12 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv) static void gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t old_addr = addr; + uint8_t ap = gd54xx_get_aperture(addr); - uint8_t ap = gd54xx_get_aperture(addr); - - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_writew_linear(addr, val, svga); return; } @@ -2573,8 +2631,8 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv) /* 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(old_addr, val, gd54xx); + gd54xx_writeb_linear(old_addr + 1, val >> 8, gd54xx); return; } @@ -2619,12 +2677,12 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv) static void gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv) { - gd54xx_t *gd54xx = (gd54xx_t *) priv; - svga_t *svga = &gd54xx->svga; + gd54xx_t *gd54xx = (gd54xx_t *) priv; + svga_t *svga = &gd54xx->svga; + uint32_t old_addr = addr; + uint8_t ap = gd54xx_get_aperture(addr); - uint8_t ap = gd54xx_get_aperture(addr); - - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_writel_linear(addr, val, svga); return; } @@ -2640,10 +2698,10 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv) /* 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); + gd54xx_writeb_linear(old_addr, val, gd54xx); + gd54xx_writeb_linear(old_addr + 1, val >> 8, gd54xx); + gd54xx_writeb_linear(old_addr + 2, val >> 16, gd54xx); + gd54xx_writeb_linear(old_addr + 3, val >> 24, gd54xx); return; } @@ -2701,12 +2759,10 @@ gd54xx_read(uint32_t addr, void *priv) gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_t *svga = &gd54xx->svga; - if ((svga->seqregs[0x07] & 0x01) == 0) - 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); + return gd54xx_mem_sys_dest_read(gd54xx, 0); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); } @@ -2718,15 +2774,13 @@ gd54xx_readw(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint16_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readw(addr, svga); - 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 &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readw_linear(addr, svga); } @@ -2738,9 +2792,6 @@ gd54xx_readl(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint32_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readl(addr, svga); - 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; @@ -2749,6 +2800,7 @@ gd54xx_readl(uint32_t addr, void *priv) return ret; } + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readl_linear(addr, svga); } @@ -2938,7 +2990,7 @@ gd543x_mmio_writeb(uint32_t addr, uint8_t val, void *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); + gd54xx_mem_sys_src_write(gd54xx, val, 0); return; } @@ -3127,7 +3179,7 @@ gd543x_mmio_read(uint32_t addr, void *priv) } 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_mem_sys_dest_read(gd54xx, 0); } return ret; @@ -3376,7 +3428,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) pattern_pitch = 1; - dsta = gd54xx->blt.dst_addr & svga->vram_mask; + dsta = gd54xx->blt.dst_addr & gd54xx->vram_mask; /* The vertical offset is in the three low-order bits of the Source Address register. */ pattern_y = gd54xx->blt.src_addr & 0x07; @@ -3390,7 +3442,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) */ /* The boundary has to be equal to the size of the pattern. */ - srca = (gd54xx->blt.src_addr & ~0x07) & svga->vram_mask; + srca = (gd54xx->blt.src_addr & ~0x07) & gd54xx->vram_mask; for (uint16_t y = 0; y <= gd54xx->blt.height; y++) { /* Go to the correct pattern line. */ @@ -3401,16 +3453,16 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) bitmask = 1; else - bitmask = svga->vram[srca2 & svga->vram_mask] & (0x80 >> pixel); + bitmask = svga->vram[srca2 & gd54xx->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]; + src = svga->vram[(srca2 + (x % (gd54xx->blt.pixel_width << 3)) + xx) & gd54xx->vram_mask]; bitmask = gd54xx_transparent_comp(gd54xx, xx, src); } - dst = &(svga->vram[(dsta + x + xx) & svga->vram_mask]); + dst = &(svga->vram[(dsta + x + xx) & gd54xx->vram_mask]); target = *dst; gd54xx_rop(gd54xx, &target, &target, &src); if (gd54xx->blt.pixel_width == 3) @@ -3419,7 +3471,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) gd54xx_blit(gd54xx, bitmask, dst, target, (x < gd54xx->blt.pattern_x)); } pixel = (pixel + 1) & 7; - svga->changedvram[((dsta + x) & svga->vram_mask) >> 12] = changeframecount; + svga->changedvram[((dsta + x) & gd54xx->vram_mask) >> 12] = changeframecount; } pattern_y = (pattern_y + 1) & 7; dsta += gd54xx->blt.dst_pitch; @@ -3480,7 +3532,7 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) bitmask = gd54xx_transparent_comp(gd54xx, gd54xx->blt.xx_count, exp); } - dst = &(svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]); + dst = &(svga->vram[gd54xx->blt.dst_addr_backup & gd54xx->vram_mask]); target = *dst; gd54xx_rop(gd54xx, &target, &target, &exp); if ((gd54xx->blt.pixel_width == 3) && (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) @@ -3493,7 +3545,7 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) 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 & gd54xx->vram_mask) >> 12] = changeframecount; if (!gd54xx->blt.xx_count) { /* 1 mask bit = 1 blitted pixel */ @@ -3550,18 +3602,18 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) 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)); + mask = svga->vram[src_addr & gd54xx->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 = svga->vram[src_addr & gd54xx->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 & gd54xx->vram_mask]; + svga->changedvram[(dst_addr & gd54xx->vram_mask) >> 12] = changeframecount; gd54xx_rop(gd54xx, &dst, &dst, (const uint8_t *) &src); @@ -3573,7 +3625,7 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) 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; + svga->vram[dst_addr & gd54xx->vram_mask] = dst; } dst_addr += gd54xx->blt.dir; @@ -3597,10 +3649,10 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) } 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 &= gd54xx->vram_mask; + gd54xx->blt.dst_addr_backup &= gd54xx->vram_mask; + src_addr &= gd54xx->vram_mask; + gd54xx->blt.src_addr_backup &= gd54xx->vram_mask; gd54xx->blt.x_count = 0; @@ -3641,7 +3693,7 @@ gd54xx_mem_sys_dest(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) 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.msd_buf[gd54xx->blt.msd_buf_pos & 0x1f] = svga->vram[gd54xx->blt.src_addr_backup & gd54xx->vram_mask]; gd54xx->blt.src_addr_backup += gd54xx->blt.dir; gd54xx->blt.msd_buf_pos++; @@ -4080,7 +4132,11 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5436: - romfn = BIOS_GD5436_PATH; + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else + romfn = BIOS_GD5436_PATH; break; case CIRRUS_ID_CLGD5430: @@ -4912,6 +4968,20 @@ const device_t gd5428_onboard_device = { .config = gd5428_onboard_config }; +const device_t gd5428_vlb_onboard_device = { + .name = "Cirrus Logic GD5428 (VLB) (On-Board)", + .internal_name = "cl_gd5428_vlb_onboard", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .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", @@ -5082,6 +5152,20 @@ const device_t gd5434_pci_device = { .config = gd5434_config }; +const device_t gd5436_onboard_pci_device = { + .name = "Cirrus Logic GD5436 (PCI) (On-Board)", + .internal_name = "cl_gd5436_onboard_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5436 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .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", diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 4753ec223..430c7a64d 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -121,7 +121,7 @@ compaq_cga_poll(void *priv) if (self->cga.displine < self->cga.firstline) { self->cga.firstline = self->cga.displine; video_wait_for_buffer(); - compaq_cga_log("Firstline %i\n", firstline); + compaq_cga_log("Firstline %i\n", self->cga.firstline); } self->cga.lastline = self->cga.displine; diff --git a/src/video/vid_ddc.c b/src/video/vid_ddc.c index 387edaeb8..787e7560e 100644 --- a/src/video/vid_ddc.c +++ b/src/video/vid_ddc.c @@ -138,12 +138,12 @@ ddc_init(void *i2c) memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2); - edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */ + edid->mfg[0] = 0x09; /* manufacturer "BOX" (currently unassigned by UEFI) */ edid->mfg[1] = 0xf8; edid->mfg_week = 48; edid->mfg_year = 2020 - 1990; edid->edid_version = 0x01; - edid->edid_rev = 0x04; /* EDID 1.4, required for Xorg on Linux to use the preferred mode timing */ + edid->edid_rev = 0x04; /* EDID 1.4, required for Xorg on newer Linux to use the preferred mode timing instead of maxing out */ edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */ edid->horiz_size = round(horiz_mm / 10.0); @@ -169,7 +169,7 @@ ddc_init(void *i2c) 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[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 */ + STANDARD_TIMING(standard_timings[5], 1600, STD_ASPECT_4_3, 60); /* 1600x1200 */ STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */ STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */ @@ -207,15 +207,15 @@ ddc_init(void *i2c) /* Detailed timing for 1366x768 */ DETAILED_TIMING(ext_detailed_timings[0], 85500, 1366, 768, 426, 30, 70, 143, 3, 3); - /* High refresh rate timings (VGA is limited to 85 Hz) */ + /* High refresh rate timings (within the standard 85 Hz VGA limit) */ 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, 85); /* 640x480 @ 85 Hz */ + STANDARD_TIMING(ext_standard_timings0[1], 800, STD_ASPECT_4_3, 85); /* 800x600 @ 85 Hz */ + STANDARD_TIMING(ext_standard_timings0[2], 1024, STD_ASPECT_4_3, 85); /* 1024x768 @ 85 Hz */ + STANDARD_TIMING(ext_standard_timings0[3], 1280, STD_ASPECT_5_4, 85); /* 1280x1024 @ 85 Hz */ + STANDARD_TIMING(ext_standard_timings0[4], 1600, STD_ASPECT_4_3, 85); /* 1600x1200 @ 85 Hz */ + STANDARD_TIMING(ext_standard_timings0[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 @ 60 Hz (previously in standard timings) */ edid->ext_descriptors[1].ext_standard_timings.padding = 0x0a; for (uint8_t c = 128; c < 255; c++) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index d4abebb39..8f995117c 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -41,7 +41,7 @@ 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_ATIEGA800P_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" @@ -49,7 +49,7 @@ enum { EGA_IBM = 0, EGA_COMPAQ, EGA_SUPEREGA, - EGA_ATI, + EGA_ATI800P, EGA_ISKRA, EGA_TSENG }; @@ -89,16 +89,6 @@ ega_out(uint16_t addr, uint8_t val, void *priv) 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; -#endif - break; case 0xb3: ati_eeprom_write((ati_eeprom_t *) ega->eeprom, val & 8, val & 2, val & 1); break; @@ -118,6 +108,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega_recalctimings(ega); } } else { + if ((ega->attraddr == 0x13) && (ega->attrregs[0x13] != val)) + ega->fullchange = changeframecount; o = ega->attrregs[ega->attraddr & 31]; ega->attrregs[ega->attraddr & 31] = val; if (ega->attraddr < 16) @@ -156,8 +148,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) 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); + ega_recalctimings(ega); break; case 0x3c4: ega->seqaddr = val; @@ -238,14 +229,24 @@ ega_out(uint16_t addr, uint8_t val, void *priv) break; case 0x3d0: case 0x3d4: - ega->crtcreg = val & 31; + if (ega->chipset) + ega->crtcreg = val & 0x3f; + else + ega->crtcreg = val & 0x1f; 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); + if (ega->chipset) { + if ((ega->crtcreg < 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) + return; + if ((ega->crtcreg == 7) && (ega->crtc[0x11] & 0x80) && !(ega->regs[0xb4] & 0x80)) + val = (ega->crtc[7] & ~0x10) | (val & 0x10); + } else { + 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) { @@ -294,22 +295,22 @@ ega_in(uint16_t addr, void *priv) break; case 0x3c0: - if (ega_type) + if (ega_type == 1) ret = ega->attraddr | ega->attr_palette_enable; break; case 0x3c1: - if (ega_type) + if (ega_type == 1) ret = ega->attrregs[ega->attraddr]; break; case 0x3c2: - ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; - break; + ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; + break; case 0x3c4: - if (ega_type) + if (ega_type == 1) ret = ega->seqaddr; break; case 0x3c5: - if (ega_type) + if (ega_type == 1) ret = ega->seqregs[ega->seqaddr & 0xf]; break; case 0x3c6: @@ -317,24 +318,24 @@ ega_in(uint16_t addr, void *priv) ret = ega->ctl_mode; break; case 0x3c8: - if (ega_type) + if (ega_type == 1) ret = 2; break; case 0x3cc: - if (ega_type) + if (ega_type == 1) ret = ega->miscout; break; case 0x3ce: - if (ega_type) + if (ega_type == 1) ret = ega->gdcaddr; break; case 0x3cf: - if (ega_type) + if (ega_type == 1) ret = ega->gdcreg[ega->gdcaddr & 0xf]; break; case 0x3d0: case 0x3d4: - if (ega_type) + if (ega_type == 1) ret = ega->crtcreg; break; case 0x3d1: @@ -348,15 +349,23 @@ ega_in(uint16_t addr, void *priv) break; case 0x10: - case 0x11: - /* TODO: Return light pen address once implemented. */ - if (ega_type) + if (ega_type == 1) ret = ega->crtc[ega->crtcreg]; + else + ret = ega->light_pen >> 8; + break; + + case 0x11: + if (ega_type == 1) + ret = ega->crtc[ega->crtcreg]; + else + ret = ega->light_pen & 0xff; break; default: - if (ega_type) + if (ega_type == 1) ret = ega->crtc[ega->crtcreg]; + break; } break; case 0x3da: @@ -532,20 +541,33 @@ ega_recalctimings(ega_t *ega) } } - if (enable_overscan) { - overscan_y = (ega->rowcount + 1) << 1; - - if (overscan_y < 16) - overscan_y = 16; + if (ega->chipset) { + if (ega->hdisp > 640) { + ega->dispend <<= 1; + ega->vtotal <<= 1; + ega->split <<= 1; + ega->vsyncstart <<= 1; + } } + overscan_y = (ega->rowcount + 1) << 1; + + if (overscan_y < 16) + overscan_y = 16; + overscan_x = (ega->seqregs[1] & 1) ? 16 : 18; + if (ega->vres) + overscan_y <<= 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); + ega->y_add = (overscan_y >> 1); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; + + if (ega->vres) + ega->y_add >>= 1; if (ega->seqregs[1] & 8) { disptime = (double) ((ega->crtc[0] + 2) << 1); @@ -673,7 +695,7 @@ void ega_poll(void *priv) { ega_t *ega = (ega_t *) priv; - int x; + int x, y; int old_ma; int wx = 640; int wy = 350; @@ -693,37 +715,26 @@ ega_poll(void *priv) video_wait_for_buffer(); } - if (ega->vres) { - old_ma = ega->ma; - - ega->displine <<= 1; - ega->y_add <<= 1; - + old_ma = ega->ma; + ega->displine *= ega->vres + 1; + ega->y_add *= ega->vres + 1; + for (y = 0; y <= ega->vres; y++) { + /* Render scanline */ ega->render(ega); + /* Render overscan */ 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 (y != ega->vres) { + ega->ma = old_ma; + ega->displine++; + } } + ega->displine /= ega->vres + 1; + ega->y_add /= ega->vres + 1; if (ega->lastline < ega->displine) ega->lastline = ega->displine; @@ -735,8 +746,18 @@ ega_poll(void *priv) 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->chipset) { + if (ega->hdisp > 640) { + if (ega->displine > 2000) + ega->displine = 0; + } else { + if (ega->displine > 500) + ega->displine = 0; + } + } else { + if (ega->displine > 500) + ega->displine = 0; + } } else { timer_advance_u64(&ega->timer, ega->dispontime); @@ -748,6 +769,7 @@ ega_poll(void *priv) if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount)) ega->con = 0; if (ega->dispon) { + /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */ if (ega->linedbl && !ega->linecountff) { ega->linecountff = 1; ega->ma = ega->maback; @@ -772,7 +794,13 @@ ega_poll(void *priv) } } ega->vc++; - ega->vc &= 511; + if (ega->chipset) { + if (ega->hdisp > 640) + ega->vc &= 1023; + else + ega->vc &= 511; + } else + 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) @@ -783,10 +811,6 @@ ega_poll(void *priv) 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; @@ -854,21 +878,15 @@ ega_poll(void *priv) } if (ega->vc == ega->vtotal) { ega->vc = 0; - ega->sc = 0; + ega->sc = (ega->crtc[0x8] & 0x1f); 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->scrollcache >= 0x8) + ega->scrollcache = 0; + else + ega->scrollcache++; if (ega->seqregs[1] & 8) ega->scrollcache <<= 1; @@ -885,11 +903,12 @@ ega_poll(void *priv) void ega_doblit(int wx, int wy, ega_t *ega) { - int y_add = enable_overscan ? overscan_y : 0; + int unscaled_overscan_y = ega->vres ? overscan_y >> 1 : overscan_y; + int y_add = enable_overscan ? unscaled_overscan_y : 0; int x_add = enable_overscan ? overscan_x : 0; - int y_start = enable_overscan ? 0 : (overscan_y >> 1); + int y_start = enable_overscan ? 0 : (unscaled_overscan_y >> 1); int x_start = enable_overscan ? 0 : (overscan_x >> 1); - int bottom = (overscan_y >> 1) + (ega->crtc[8] & 0x1f); + int bottom = (unscaled_overscan_y >> 1); uint32_t *p; int i; int j; @@ -1399,6 +1418,9 @@ ega_standalone_init(const device_t *info) else ega_type = 1; + ega->actual_type = info->local; + ega->chipset = 0; + switch (info->local) { default: case EGA_IBM: @@ -1414,9 +1436,10 @@ ega_standalone_init(const device_t *info) 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, + case EGA_ATI800P: + rom_init(&ega->bios_rom, BIOS_ATIEGA800P_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + ega->chipset = 1; break; case EGA_ISKRA: rom_init_interleaved(&ega->bios_rom, BIOS_ISKRA_PATH, @@ -1445,11 +1468,11 @@ ega_standalone_init(const device_t *info) 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) { + if (ega->chipset) { 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); + ati_eeprom_load((ati_eeprom_t *) ega->eeprom, "egawonder800p.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); @@ -1479,9 +1502,9 @@ sega_standalone_available(void) } static int -atiega_standalone_available(void) +atiega800p_standalone_available(void) { - return rom_present(BIOS_ATIEGA_PATH); + return rom_present(BIOS_ATIEGA800P_PATH); } static int @@ -1599,7 +1622,7 @@ static const device_config_t ega_config[] = { }; const device_t ega_device = { - .name = "EGA", + .name = "IBM EGA", .internal_name = "ega", .flags = DEVICE_ISA, .local = EGA_IBM, @@ -1640,15 +1663,15 @@ const device_t sega_device = { .config = ega_config }; -const device_t atiega_device = { +const device_t atiega800p_device = { .name = "ATI EGA Wonder 800+", - .internal_name = "egawonder800", + .internal_name = "egawonder800p", .flags = DEVICE_ISA, - .local = EGA_ATI, + .local = EGA_ATI800P, .init = ega_standalone_init, .close = ega_close, .reset = NULL, - { .available = atiega_standalone_available }, + { .available = atiega800p_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 2d15d6dc5..0cb1216ad 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -126,6 +126,14 @@ ega_render_text(ega_t *ega) const bool blinked = ega->blink & 0x10; uint32_t *p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; + /* Compensate for 8dot scroll */ + if (!seq9dot) { + for (int x = 0; x < dotwidth; x++) { + p[x] = ega->overscan_color; + } + p += dotwidth; + } + for (int x = 0; x < (ega->hdisp + ega->scrollcache); x += charwidth) { uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; @@ -191,6 +199,7 @@ ega_render_graphics(ega_t *ega) const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); const bool blinked = ega->blink & 0x10; const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 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]; @@ -198,6 +207,15 @@ ega_render_graphics(ega_t *ega) const int dotwidth = 1 << dwshift; const int charwidth = dotwidth * 8; int secondcclk = 0; + + /* Compensate for 8dot scroll */ + if (!seq9dot) { + for (int x = 0; x < dotwidth; x++) { + p[x] = ega->overscan_color; + } + p += dotwidth; + } + for (int x = 0; x <= (ega->hdisp + ega->scrollcache); x += charwidth) { uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 4f7dbae3e..a7d2a749f 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -14,11 +14,13 @@ * * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/mca.h> @@ -40,7 +42,12 @@ typedef struct { rom_t bios_rom; + uint8_t pel_wd; uint8_t banking; + uint8_t reg_3d8; + uint8_t reg_3bf; + uint8_t tries; + uint8_t ext_enable; } et3000_t; static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 }; @@ -48,30 +55,130 @@ 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); +#ifdef ENABLE_ET3000_LOG +int svga_do_log = ENABLE_ET3000_LOG; + +static void +et3000_log(const char *fmt, ...) +{ + va_list ap; + + if (et3000_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define et3000_log(fmt, ...) +#endif + static uint8_t et3000_in(uint16_t addr, void *priv) { et3000_t *dev = (et3000_t *) priv; svga_t *svga = &dev->svga; + uint8_t ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if ((addr >= 0x03b0) && (addr < 0x03bc) && (svga->miscout & 1)) + return 0xff; + + if ((addr >= 0x03d0) && (addr < 0x03dc) && !(svga->miscout & 1)) + return 0xff; switch (addr) { - case 0x3cd: /*Banking*/ - return dev->banking; - - case 0x3d4: - return svga->crtcreg; - - case 0x3d5: - return svga->crtc[svga->crtcreg]; - default: + ret = svga_in(addr, svga); + +#ifdef ENABLE_ET3000_LOG + if (addr != 0x03da) + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); +#endif + break; + + case 0x3c1: + /* It appears the extended attribute registers are **NOT** + protected by key on the ET3000AX, as the BIOS attempts to + write to attribute register 16h without the key. */ + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->attraddr, ret, dev->ext_enable); + break; + + case 0x3c5: + if ((svga->seqaddr >= 6) && !dev->ext_enable) + ret = 0xff; + else + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->seqaddr, ret, dev->ext_enable); + break; + + case 0x3cf: + if ((svga->gdcaddr >= 0x0d) && !dev->ext_enable) + ret = 0xff; + else + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->gdcaddr & 15, ret, dev->ext_enable); + break; + + case 0x3cb: /*PEL Address/Data Wd*/ + ret = dev->pel_wd; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3cd: /*Banking*/ + ret = dev->banking; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3b4: + case 0x3d4: + ret = svga->crtcreg; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3b5: + case 0x3d5: + if ((svga->crtcreg >= 0x18) && (svga->crtcreg < 0x23) && !dev->ext_enable) + ret = 0xff; + else if (svga->crtcreg > 0x25) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X\n", CS, cpu_state.pc, + addr, svga->crtcreg, ret); + break; + + case 0x3b8: + case 0x3d8: + ret = dev->reg_3d8; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3ba: + case 0x3da: + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; + break; + + case 0x3bf: + ret = dev->reg_3bf; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); break; } - return svga_in(addr, svga); + return ret; } static void @@ -80,47 +187,119 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) et3000_t *dev = (et3000_t *) priv; svga_t *svga = &dev->svga; uint8_t old; + uint8_t index; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + et3000_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if ((addr >= 0x03b0) && (addr < 0x03bc) && (svga->miscout & 1)) + return; + + if ((addr >= 0x03d0) && (addr < 0x03dc) && !(svga->miscout & 1)) + return; switch (addr) { case 0x3c0: - case 0x3c1: + /* It appears the extended attribute registers are **NOT** + protected by key on the ET3000AX, as the BIOS attempts to + write to attribute register 16h without the key. */ + if (svga->attrff && (svga->attraddr == 0x11) && (svga->attrregs[0x16] & 0x01)) + val = (val & 0xf0) | (svga->attrregs[0x11] & 0x0f); +#ifdef ENABLE_ET3000_LOG + if (svga->attrff && (svga->attraddr > 0x14)) + et3000_log("3C1: %02X = %02X\n", svga->attraddr, val); +#endif 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); + return; } break; + case 0x3c1: + return; + case 0x3c2: + svga->miscout = val; + svga->vidclock = val & 4; + svga_recalctimings(svga); + return; + + case 0x3c4: + svga->seqaddr = val & 0x07; + return; case 0x3c5: + if ((svga->seqaddr >= 6) && !dev->ext_enable) + return; + 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); + et3000_log("CHAIN2 = %i, CHAIN4 = %i\n", svga->chain2_write, svga->chain4); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4 && + !(svga->adv_flags & FLAG_ADDR_BY8); return; } +#ifdef ENABLE_ET3000_LOG + else if (svga->seqaddr > 4) + et3000_log("3C5: %02X = %02X\n", svga->seqaddr, val); +#endif break; - case 0x3cf: - if ((svga->gdcaddr & 15) == 5) { - svga->chain4 &= ~0x10; - if (val & 0x40) - svga->chain4 |= (svga->attrregs[0x16] & 0x10); + case 0x3c9: + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + val <<= 2; + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 0: + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 255; + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) { + 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; } + return; + + case 0x3cb: /*PEL Address/Data Wd*/ + et3000_log("3CB = %02X\n", val); + dev->pel_wd = val; break; case 0x3cd: /*Banking*/ - dev->banking = val; + et3000_log("3CD = %02X\n", 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->write_bank = ((val >> 0) & 7) << 17; svga->read_bank = ((val >> 3) & 7) << 17; break; case 1: /*64K segments*/ @@ -132,13 +311,68 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) break; } } + dev->banking = val; return; + case 0x3ce: + svga->gdcaddr = val & 0x0f; + return; + case 0x3cf: + if ((svga->gdcaddr >= 0x0d) && !dev->ext_enable) + return; + + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x10; + if (val & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + } else if ((svga->gdcaddr & 15) == 6) { + if (!(svga->crtc[0x23] & 0x80) && !(val & 0x08)) { + switch ((dev->banking >> 6) & 3) { + case 0: /*128K segments*/ + svga->write_bank = ((dev->banking >> 0) & 7) << 17; + svga->read_bank = ((dev->banking >> 3) & 7) << 17; + break; + case 1: /*64K segments*/ + svga->write_bank = (dev->banking & 7) << 16; + svga->read_bank = ((dev->banking >> 3) & 7) << 16; + break; + + default: + break; + } + } 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 - ET3000 supports linear 128k at A0000. */ + svga->banked_mask = 0x1ffff; + } + return; + } +#ifdef ENABLE_ET3000_LOG + else if ((svga->gdcaddr & 15) > 8) + et3000_log("3CF: %02X = %02X\n", (svga->gdcaddr & 15), val); +#endif + break; + + case 0x3b4: case 0x3d4: svga->crtcreg = val & 0x3f; return; + case 0x3b5: case 0x3d5: + if ((svga->crtcreg >= 0x18) && (svga->crtcreg < 0x23) && !dev->ext_enable) + return; + else if (svga->crtcreg > 0x25) + return; + + /* Unlike the ET4000AX, which protects all bits of the + overflow high register (0x35 there, 0x25 here) except for + bits 4 and 7, if bit 7 of CRTC 11h is set, the ET3000AX + does not to that. */ if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -146,6 +380,11 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; +#ifdef ENABLE_ET3000_LOG + if (svga->crtcreg > 0x18) + et3000_log("3D5: %02X = %02X\n", svga->crtcreg, val); +#endif + if (old != val) { if (svga->crtcreg < 0x0e || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; @@ -154,6 +393,27 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) } break; + case 0x3b8: + case 0x3d8: + et3000_log("%04X = %02X\n", addr, val); + dev->reg_3d8 = val; + if ((val == 0xa0) && (dev->tries == 1)) { + dev->ext_enable = 1; + dev->tries = 0; + } else if (val == 0x29) + dev->tries = 1; + return; + + case 0x3bf: + et3000_log("%04X = %02X\n", addr, val); + dev->reg_3bf = val; + if ((val == 0x01) && (dev->tries == 1)) { + dev->ext_enable = 0; + dev->tries = 0; + } else if (val == 0x03) + dev->tries = 1; + return; + default: break; } @@ -199,10 +459,8 @@ et3000_recalctimings(svga_t *svga) } } -#if 0 - pclog("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", - svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); -#endif + et3000_log("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", + svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x24] << 1) & 4)) { case 0: @@ -238,7 +496,7 @@ et3000_init(const device_t *info) svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, et3000_recalctimings, et3000_in, et3000_out, NULL, NULL); - io_sethandler(0x03c0, 32, + io_sethandler(0x03b0, 48, et3000_in, NULL, NULL, et3000_out, NULL, NULL, dev); break; @@ -299,8 +557,6 @@ static const device_config_t et3000_config[] = { .value = 256 }, { .description = "512 KB", .value = 512 }, - { .description = "1 MB", - .value = 1024 }, { .description = "" } } }, { .type = CONFIG_END } }; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 834de7513..583487c5f 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -55,17 +55,21 @@ #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */ #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 V8_06_BIOS_ROM_PATH "roms/video/et4000/ET4000_V8_06.BIN" +#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin" +#define V1_21_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.21.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; @@ -115,6 +119,7 @@ et4000_in(uint16_t addr, void *priv) { et4000_t *dev = (et4000_t *) priv; svga_t *svga = &dev->svga; + uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -138,7 +143,8 @@ et4000_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - return sc1502x_ramdac_in(addr, svga->ramdac, svga); + if (dev->type >= ET4000_TYPE_ISA) + return sc1502x_ramdac_in(addr, svga->ramdac, svga); case 0x3cd: /*Banking*/ return dev->banking; @@ -149,6 +155,26 @@ et4000_in(uint16_t addr, void *priv) case 0x3d5: return svga->crtc[svga->crtcreg]; + case 0x3da: + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; + + if (ret & 0x08) + ret &= 0x7f; + else + ret |= 0x80; + + return ret; + default: break; } @@ -220,17 +246,88 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) et4000_t *dev = (et4000_t *) priv; svga_t *svga = &dev->svga; uint8_t old; + uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f }; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 0x1f; + 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; + old = svga->attrregs[svga->attraddr & 0x1f]; + svga->attrregs[svga->attraddr & 0x1f] = val; + if (svga->attraddr < 0x10) + svga->fullchange = svga->monitor->mon_changeframecount; + + if ((svga->attraddr == 0x10) || (svga->attraddr == 0x14) || (svga->attraddr < 0x10)) { + for (int c = 0; c < 0x10; c++) { + if (svga->attrregs[0x10] & 0x80) + svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); + else if (svga->ati_4color) + svga->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + 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) { + svga->chain4 &= ~0x02; + if ((val & 0x40) && (svga->attrregs[0x10] & 0x40)) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + if (old != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + if (old != 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; + return; + + 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; + } else if (svga->seqaddr == 0x0e) { + svga->seqregs[0x0e] = val; + svga->chain4 &= ~0x02; + if ((svga->gdcreg[5] & 0x40) && svga->lowres) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + svga_recalctimings(svga); + return; + } + break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - return; + if (dev->type >= ET4000_TYPE_ISA) { + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + break; case 0x3cd: /*Banking*/ if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { @@ -241,7 +338,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) return; case 0x3cf: - if ((svga->gdcaddr & 15) == 6) { + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x02; + if ((val & 0x40) && svga->lowres) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + } else 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; @@ -418,7 +519,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) break; case 1: case 2: - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + if ((et4000->kasan_cfg_index - 0xF0) <= 16) + 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); @@ -463,7 +565,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) 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; + if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4) + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; } break; case 6: @@ -548,22 +651,29 @@ et4000_recalctimings(svga_t *svga) const et4000_t *dev = (et4000_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; + + svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; + + svga->ps_bit_bug = (dev->type == ET4000_TYPE_TC6058AF) && svga->lowres && ((svga->gdcreg[5] & 0x60) >= 0x40); + if (svga->crtc[0x35] & 1) - svga->vblankstart += 0x400; + svga->vblankstart |= 0x400; if (svga->crtc[0x35] & 2) - svga->vtotal += 0x400; + svga->vtotal |= 0x400; if (svga->crtc[0x35] & 4) - svga->dispend += 0x400; + svga->dispend |= 0x400; if (svga->crtc[0x35] & 8) - svga->vsyncstart += 0x400; + svga->vsyncstart |= 0x400; if (svga->crtc[0x35] & 0x10) - svga->split += 0x400; - if (!svga->rowoffset) + svga->split |= 0x400; + if (!svga->rowoffset && !svga->ps_bit_bug) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) - svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + svga->htotal |= 0x100; + if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { case 0: @@ -584,10 +694,12 @@ et4000_recalctimings(svga_t *svga) case 15: case 16: svga->hdisp /= 2; + svga->dots_per_clock /= 2; break; case 24: svga->hdisp /= 3; + svga->dots_per_clock /= 3; break; default: @@ -613,6 +725,12 @@ et4000_recalctimings(svga_t *svga) else svga->render = svga_render_8bpp_highres; } + + if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40) && svga->lowres) { + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; + svga->render = svga_render_8bpp_highres; + } } static void @@ -623,7 +741,8 @@ et4000_kasan_recalctimings(svga_t *svga) et4000_recalctimings(svga); if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { - svga->ma_latch -= 3; + svga->hdisp += svga->dots_per_clock; + svga->ma_latch -= 4; 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)) @@ -661,6 +780,7 @@ et4000_mca_feedb(UNUSED(void *priv)) static void * et4000_init(const device_t *info) { + const char *bios_ver = NULL; const char *fn; et4000_t *dev; int i; @@ -672,6 +792,7 @@ et4000_init(const device_t *info) fn = BIOS_ROM_PATH; switch (dev->type) { + case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */ case ET4000_TYPE_ISA: /* ISA ET4000AX */ dev->vram_size = device_get_config_int("memory") << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); @@ -680,6 +801,8 @@ et4000_init(const device_t *info) NULL, NULL); io_sethandler(0x03c0, 32, et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev); + bios_ver = (char *) device_get_config_bios("bios_ver"); + fn = (char *) device_get_bios_file(info, bios_ver, 0); break; case ET4000_TYPE_MCA: /* MCA ET4000AX */ @@ -759,7 +882,8 @@ et4000_init(const device_t *info) break; } - dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + if (dev->type >= ET4000_TYPE_ISA) + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); dev->vram_mask = dev->vram_size - 1; @@ -817,6 +941,100 @@ et4000_kasan_available(void) return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH); } +static const device_config_t et4000_tc6058af_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 = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .name = "bios_ver", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "v1_10", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 1.10", .internal_name = "v1_10", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 32768, .files = { TC6058AF_BIOS_ROM_PATH, "" } }, + { .name = "Version 1.21", .internal_name = "v1_21", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 32768, .files = { V1_21_BIOS_ROM_PATH, "" } }, + { .files_no = 0 } + }, + }, + { + .type = CONFIG_END + } +// clang-format on +}; + +static const device_config_t et4000_bios_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 = "" + } + } + }, + { + .name = "bios_ver", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "v8_01", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Version 8.01", .internal_name = "v8_01", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 32768, .files = { BIOS_ROM_PATH, "" } }, + { .name = "Version 8.06", .internal_name = "v8_06", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 32768, .files = { V8_06_BIOS_ROM_PATH, "" } }, + { .files_no = 0 } + }, + }, + { + .type = CONFIG_END + } + // clang-format on +}; + static const device_config_t et4000_config[] = { // clang-format off { @@ -848,6 +1066,20 @@ static const device_config_t et4000_config[] = { // clang-format on }; +const device_t et4000_tc6058af_isa_device = { + .name = "Tseng Labs ET4000AX (TC6058AF) (ISA)", + .internal_name = "et4000ax_tc6058af", + .flags = DEVICE_ISA, + .local = ET4000_TYPE_TC6058AF, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = et4000_speed_changed, + .force_redraw = et4000_force_redraw, + .config = et4000_tc6058af_config +}; + const device_t et4000_isa_device = { .name = "Tseng Labs ET4000AX (ISA)", .internal_name = "et4000ax", @@ -856,10 +1088,10 @@ const device_t et4000_isa_device = { .init = et4000_init, .close = et4000_close, .reset = NULL, - { .available = et4000_available }, + { .available = NULL }, .speed_changed = et4000_speed_changed, .force_redraw = et4000_force_redraw, - .config = et4000_config + .config = et4000_bios_config }; const device_t et4000_mca_device = { diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index b48135c37..2f086f3c7 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -42,7 +42,7 @@ #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_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" @@ -431,22 +431,27 @@ et4000w32p_recalctimings(svga_t *svga) et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; + + svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; + if (svga->crtc[0x35] & 0x01) - svga->vblankstart += 0x400; + svga->vblankstart |= 0x400; if (svga->crtc[0x35] & 0x02) - svga->vtotal += 0x400; + svga->vtotal |= 0x400; if (svga->crtc[0x35] & 0x04) - svga->dispend += 0x400; + svga->dispend |= 0x400; if (svga->crtc[0x35] & 0x08) - svga->vsyncstart += 0x400; + svga->vsyncstart |= 0x400; if (svga->crtc[0x35] & 0x10) - svga->split += 0x400; + svga->split |= 0x400; if (svga->crtc[0x3F] & 0x80) - svga->rowoffset += 0x100; + svga->rowoffset |= 0x100; if (svga->crtc[0x3F] & 0x01) - svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + svga->htotal |= 0x100; + if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); @@ -472,30 +477,6 @@ et4000w32p_recalctimings(svga_t *svga) } } - 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) { @@ -518,8 +499,10 @@ et4000w32p_recalctimings(svga_t *svga) switch (svga->bpp) { case 15: case 16: - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } if (et4000->type <= ET4000W32P_REVC) { if (et4000->type == ET4000W32P_REVC) { if (svga->hdisp != 1024) @@ -530,6 +513,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 24: svga->hdisp /= 3; + svga->dots_per_clock /= 3; if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { @@ -549,15 +533,8 @@ et4000w32p_recalctimings(svga_t *svga) 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 (et4000->rev == 5) - svga->ma_latch++; - if (svga->seqregs[1] & 8) /* Low res (320) */ svga->render = svga_render_4bpp_lowres; else @@ -2616,6 +2593,9 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv) { const et4000w32p_t *et4000 = (et4000w32p_t *) priv; + if (func > 0) + return 0xff; + addr &= 0xff; switch (addr) { @@ -2676,6 +2656,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_t *svga = &et4000->svga; + if (func > 0) + return; + addr &= 0xff; switch (addr) { @@ -2799,7 +2782,6 @@ et4000w32p_init(const device_t *info) 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_REVC: @@ -2824,7 +2806,6 @@ et4000w32p_init(const device_t *info) 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_CARDEX: @@ -2837,7 +2818,6 @@ et4000w32p_init(const device_t *info) 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: diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 9cd68e4ee..213cf9ed4 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -312,6 +312,11 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) ht216_remap(ht216); break; + case 0xca: + if (ht216->id == 0x7861) + svga_recalctimings(svga); + break; + case 0xc9: case 0xcf: ht216_remap(ht216); @@ -321,6 +326,7 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) svga->adv_flags &= ~FLAG_RAMDAC_SHIFT; if (val & 0x04) svga->adv_flags |= FLAG_RAMDAC_SHIFT; + svga_recalctimings(svga); fallthrough; /*Bank registers*/ case 0xe8: @@ -449,14 +455,10 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) 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); @@ -480,12 +482,14 @@ ht216_in(uint16_t addr, void *priv) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - if ((ht216->id == 0x7152) && ht216->isabus) { - if (addr == 0x105) - return ht216->extensions; - } - switch (addr) { + case 0x105: + if (ht216->isabus && (ht216->id == 0x7152)) { + ret &= ~0x03; + return ret; + } + break; + case 0x3c4: return svga->seqaddr; @@ -623,6 +627,16 @@ ht216_recalctimings(svga_t *svga) ht216_t *ht216 = (ht216_t *) svga->priv; int high_res_256 = 0; + + if (ht216->id == 0x7861) { + if (ht216->ht_regs[0xe0] & 0x20) { + if (ht216->ht_regs[0xca] & 0x01) + svga->htotal |= 0x200; + if (ht216->ht_regs[0xca] & 0x04) + svga->hblankstart |= 0x200; + } + } + 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: @@ -643,12 +657,15 @@ ht216_recalctimings(svga_t *svga) svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); - svga->interlace = ht216->ht_regs[0xe0] & 1; + if (ht216->ht_regs[0xf6] & 0x80) + svga->ma_latch = ((ht216->ht_regs[0xf6] & 0x30) << 12); + + svga->interlace = ht216->ht_regs[0xe0] & 0x01; if (svga->interlace) - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4); + high_res_256 = (svga->htotal << 3) > (svga->vtotal << 2); else - high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2); + high_res_256 = (svga->htotal << 3) > (svga->vtotal << 1); ht216->adjust_cursor = 0; @@ -688,7 +705,7 @@ ht216_recalctimings(svga_t *svga) if (!(svga->crtc[1] & 1)) svga->hdisp--; svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp *= svga->dots_per_clock; svga->rowoffset <<= 1; if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ svga->crtc[0x17] |= 0x40; @@ -705,8 +722,6 @@ ht216_recalctimings(svga_t *svga) } } - 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; else @@ -733,9 +748,9 @@ ht216_hwcursor_draw(svga_t *svga, int displine) for (int x = 0; x < width; x++) { if (!(dat[0] & 0x80000000)) - (buffer32->line[displine])[svga->x_add + offset + x] = 0; + svga->monitor->target_buffer->line[displine][svga->x_add + offset + x] = 0; if (dat[1] & 0x80000000) - (buffer32->line[displine])[svga->x_add + offset + x] ^= 0xffffff; + svga->monitor->target_buffer->line[displine][svga->x_add + offset + x] ^= 0xffffff; dat[0] <<= shift; dat[1] <<= shift; @@ -1466,9 +1481,8 @@ radius_mca_feedb(UNUSED(void *priv)) return 1; } -void - * - ht216_init(const device_t *info, uint32_t mem_size, int has_rom) +void * +ht216_init(const device_t *info, uint32_t mem_size, int has_rom) { ht216_t *ht216 = malloc(sizeof(ht216_t)); svga_t *svga; @@ -1527,12 +1541,13 @@ void } 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); + if (info->local == 0x7152) { + if (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); + } else + io_sethandler(0x0105, 0x0001, ht216_in, NULL, NULL, NULL, NULL, NULL, ht216); } rom_init(&ht216->bios_rom, BIOS_RADIUS_SVGA_MULTIVIEW_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; @@ -1720,31 +1735,6 @@ static const device_config_t ht216_32_standalone_config[] = { .type = CONFIG_END } }; - -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 = { @@ -1814,7 +1804,7 @@ const device_t radius_svga_multiview_isa_device = { { .available = radius_svga_multiview_available }, .speed_changed = ht216_speed_changed, .force_redraw = ht216_force_redraw, - .config = radius_svga_multiview_config + .config = NULL }; const device_t radius_svga_multiview_mca_device = { diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index a53199324..702fb7e32 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -386,7 +386,7 @@ static const device_config_t mda_config[] = { }; const device_t mda_device = { - .name = "MDA", + .name = "IBM MDA", .internal_name = "mda", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 74bb9d07a..fdbb2e411 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -15,6 +15,7 @@ * Copyright 2008-2020 Sarah Walker. */ #include +#include #include #include #include @@ -36,9 +37,11 @@ #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_MILLENNIUM_II "roms/video/matrox/matrox2164wpc.BIN" +#define ROM_MYSTIQUE "roms/video/matrox/MYSTIQUE.VBI" +#define ROM_MYSTIQUE_220 "roms/video/matrox/Myst220_66-99mhz.vbi" +#define ROM_G100 "roms/video/matrox/productiva8mbsdr.BIN" #define FIFO_SIZE 65536 #define FIFO_MASK (FIFO_SIZE - 1) @@ -55,7 +58,7 @@ #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 (20 * 14) /*280 quad words per 100us poll*/ /*These registers are also mirrored into 0x1dxx, with the mirrored versions starting the blitter*/ @@ -111,6 +114,14 @@ #define REG_DR14 0x1cf8 #define REG_DR15 0x1cfc +#define REG_DR0_Z32LSB 0x2c50 +#define REG_DR0_Z32MSB 0x2c54 +#define REG_DR2_Z32LSB 0x2c60 +#define REG_DR2_Z32MSB 0x2c64 +#define REG_DR3_Z32LSB 0x2c68 +#define REG_DR3_Z32MSB 0x2c6c +#define REG_TEXFILTER 0x2c58 + #define REG_FIFOSTATUS 0x1e10 #define REG_STATUS 0x1e14 #define REG_ICLEAR 0x1e18 @@ -157,6 +168,14 @@ #define REG_SECADDRESS 0x2c40 #define REG_SECEND 0x2c44 #define REG_SOFTRAP 0x2c48 +#define REG_ALPHASTART 0x2c70 +#define REG_ALPHACTRL 0x2c7c +#define REG_ALPHAXINC 0x2c74 +#define REG_ALPHAYINC 0x2c78 +#define REG_FOGSTART 0x1cc4 +#define REG_FOGXINC 0x1cd4 +#define REG_FOGYINC 0x1ce4 +#define REG_FOGCOL 0x1cf4 /*Mystique only*/ #define REG_PALWTADD 0x3c00 @@ -173,6 +192,8 @@ #define CRTCX_R0_OFFSET_MASK (3 << 4) #define CRTCX_R1_HTOTAL8 (1 << 0) +#define CRTCX_R1_HBLKSTRT8 (1 << 1) +#define CRTCX_R1_HBLKEND6 (1 << 6) #define CRTCX_R2_VTOTAL10 (1 << 0) #define CRTCX_R2_VTOTAL11 (1 << 1) @@ -234,6 +255,7 @@ #define XREG_XPIXPLLSTAT 0x4f #define XMISCCTRL_VGA8DAC (1 << 3) +#define XMISCCTRL_RAMCS (1 << 4) #define XMULCTRL_DEPTH_MASK (7 << 0) #define XMULCTRL_DEPTH_8 (0 << 0) @@ -293,6 +315,7 @@ #define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT) #define DWGCTRL_BLTMOD_MASK (0xf << 25) #define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25) +#define DWGCTRL_BLTMOD_BPLAN (0x1 << 25) #define DWGCTRL_BLTMOD_BFCOL (0x2 << 25) #define DWGCTRL_BLTMOD_BU32BGR (0x3 << 25) #define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25) @@ -308,11 +331,13 @@ #define MACCESS_PWIDTH_16 (1 << 0) #define MACCESS_PWIDTH_32 (2 << 0) #define MACCESS_PWIDTH_24 (3 << 0) +#define MACCESS_ZWIDTH (1 << 3) +#define MACCESS_FOGEN (1 << 26) #define MACCESS_TLUTLOAD (1 << 29) #define MACCESS_NODITHER (1 << 30) #define MACCESS_DIT555 (1 << 31) -#define PITCH_MASK 0x7e0 +#define PITCH_MASK 0xfe0 #define PITCH_YLIN (1 << 15) #define SGN_SDYDXL (1 << 0) @@ -348,7 +373,10 @@ #define TEXCTL_PALSEL_MASK (0xf << 4) #define TEXCTL_TPITCH_SHIFT (16) #define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT) +#define TEXCTL_TPITCHLIN (1 << 8) +#define TEXCTL_TPITCHEXT_MASK (0x7ff << 9) #define TEXCTL_NPCEN (1 << 21) +#define TEXCTL_AZEROEXTEND (1 << 23) #define TEXCTL_DECALCKEY (1 << 24) #define TEXCTL_TAKEY (1 << 25) #define TEXCTL_TAMASK (1 << 26) @@ -382,6 +410,8 @@ enum { MGA_2064W, /*Millennium*/ MGA_1064SG, /*Mystique*/ MGA_1164SG, /*Mystique 220*/ + MGA_2164W, /*Millennium II*/ + MGA_G100, /*Productiva G100*/ }; enum { @@ -429,8 +459,7 @@ typedef struct mystique_t { uint8_t pci_regs[256], crtcext_regs[6], xreg_regs[256], dmamap[16]; - int vram_size, crtcext_idx, xreg_idx, xzoomctrl, - pixel_count, trap_count; + int vram_size, crtcext_idx, xreg_idx, xzoomctrl; atomic_int busy, blitter_submit_refcount, blitter_submit_dma_refcount, blitter_complete_refcount, @@ -440,7 +469,10 @@ typedef struct mystique_t { 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; + softrap_pending_val; + + atomic_uint status; + atomic_bool softrap_status_read; uint64_t blitter_time, status_time; @@ -471,7 +503,7 @@ typedef struct mystique_t { 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; + lastpix_b, highv_line, beta, dither, err, k1, k2; int pattern[8][16]; @@ -479,11 +511,16 @@ typedef struct mystique_t { pitch, plnwt, ybot, ydstorg, ytop, texorg, texwidth, texheight, texctl, textrans, zorg, ydst_lin, - src_addr, z_base, iload_rem_data, highv_data; + src_addr, z_base, iload_rem_data, highv_data, + fogcol, fogxinc : 24, fogyinc : 24, fogstart : 24, + alphactrl, alphaxinc : 24, alphayinc : 24, alphastart : 24, + texfilter; uint32_t src[4], ar[7], dr[16], tmr[9]; + uint64_t extended_dr[4]; + struct { int sdydxl, scanleft, sdxl, sdy, @@ -505,13 +542,14 @@ typedef struct mystique_t { struct { - int pri_pos, sec_pos, iload_pos, - pri_state, sec_state, iload_state, state; + atomic_int pri_state, sec_state, iload_state, state; - uint32_t primaddress, primend, secaddress, secend, + atomic_uint primaddress, primend, secaddress, secend, pri_header, sec_header, iload_header; + atomic_uint words_expected; + mutex_t *lock; } dma; @@ -623,6 +661,13 @@ static const uint8_t trans_masks[16][16] = { static int8_t dither5[256][2][2]; static int8_t dither6[256][2][2]; +static double bayer_mat[4][4] = +{ + { 0.0, 8. / 16., 2. / 16., 10. / 16.}, + { 12. / 16., 4. / 16., 14. / 16., 6. / 16.}, + { 3. / 16., 11. / 16., 1. / 16., 9. / 16.}, + { 15. / 16., 7. / 16., 13. / 16., 5. / 16.}, +}; 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 }; @@ -669,7 +714,7 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) case 0x3c6: case 0x3c7: case 0x3c9: - if (mystique->type == MGA_2064W) { + if (mystique->type == MGA_2064W || mystique->type == MGA_2164W) { tvp3026_ramdac_out(addr, 0, 0, val, svga->ramdac, svga); return; } @@ -715,32 +760,66 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) 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); + old = mystique->crtcext_regs[mystique->crtcext_idx]; + if (mystique->crtcext_idx < 6) + mystique->crtcext_regs[mystique->crtcext_idx] = val; + + if ((mystique->type >= MGA_1064SG) && (mystique->crtcext_idx == 0) && + (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE)) { + svga->rowoffset = svga->crtc[0x13] | + ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + + if (!(mystique->type >= MGA_2164W)) + svga->rowoffset <<= 1; + + 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_2164W)) + svga->ma_latch <<= 1; + + if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->interlace && svga->oddeven) + svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + + (svga->ma_latch << 2) + (svga->rowoffset << 1); + else + svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + + (svga->ma_latch << 2); + mystique->ma_latch_old = svga->ma_latch; + } } + if (mystique->crtcext_idx == 4) { if (svga->gdcreg[6] & 0xc) { /*64k banks*/ - svga->read_bank = (val & 0x7f) << 16; - svga->write_bank = (val & 0x7f) << 16; + if (mystique->type >= MGA_2164W) { + svga->read_bank = val << 16; + svga->write_bank = val << 16; + } else { + 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; + if (mystique->type >= MGA_2164W) { + svga->read_bank = (val & 0xfe) << 16; + svga->write_bank = (val & 0xfe) << 16; + } else { + svga->read_bank = (val & 0x7e) << 16; + svga->write_bank = (val & 0x7e) << 16; + } } } + if (!((mystique->type >= MGA_1064SG) && (mystique->crtcext_idx == 0) && + (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE))) + svga_recalctimings(svga); + break; default: @@ -772,7 +851,7 @@ mystique_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (mystique->type == MGA_2064W) + if (mystique->type == MGA_2064W || mystique->type == MGA_2164W) temp = tvp3026_ramdac_in(addr, 0, 0, svga->ramdac, svga); else temp = svga_in(addr, svga); @@ -816,6 +895,18 @@ mystique_line_compare(svga_t *svga) return 0; } +static void +mystique_vblank_start(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *) svga->priv; + + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { + 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->ma_latch <<= 1; + } +} + static void mystique_vsync_callback(svga_t *svga) { @@ -856,81 +947,123 @@ mystique_recalctimings(svga_t *svga) 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; - if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) - svga->vtotal += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) - svga->vtotal += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) - svga->dispend += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) - svga->vblankstart += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) - svga->vblankstart += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) - svga->vsyncstart += 0x400; - if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) - svga->vsyncstart += 0x800; - if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) - svga->split += 0x400; + svga->htotal |= 0x100; - if (mystique->type == MGA_2064W) + svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2]; + + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) + svga->vtotal |= 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) + svga->vtotal |= 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) + svga->dispend |= 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) + svga->vblankstart |= 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) + svga->vblankstart |= 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) + svga->vsyncstart |= 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) + svga->vsyncstart |= 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) + svga->split |= 0x400; + + if (mystique->type == MGA_2064W || mystique->type == MGA_2164W) { tvp3026_recalctimings(svga->ramdac, svga); - else + svga->interlace |= !!(mystique->crtcext_regs[0] & 0x80); + } 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 = (svga->crtc[1] + 1) << 3; 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->dots_per_clock = 8; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); + svga->hblank_end_mask = 0x0000007f; + + if (mystique->type != MGA_2164W && mystique->type != MGA_2064W) + svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); + + if (mystique->type >= MGA_1064SG) + 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) + svga->ma_latch <<= 1; } + if (mystique->type >= MGA_1064SG) { - /*Mystique, unlike most SVGA cards, allows display start to take + /*Mystique and later, unlike most SVGA cards, allows display start to take effect mid-screen*/ + if (!(mystique->type >= MGA_2164W)) + svga->ma_latch <<= 1; + /* Only change maback so the new display start will take effect on the next + horizontal retrace. */ 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); + 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); + svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + + (svga->ma_latch << 2); mystique->ma_latch_old = svga->ma_latch; } - svga->rowoffset <<= 1; + if (!(mystique->type >= MGA_2164W)) + svga->rowoffset <<= 1; + if (mystique->type != MGA_2164W) { + 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; - 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; + 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; + } } } else { switch (svga->bpp) { @@ -949,18 +1082,28 @@ mystique_recalctimings(svga_t *svga) case 32: svga->render = svga_render_32bpp_highres; break; - - default: - break; } } + svga->packed_chain4 = 1; svga->line_compare = mystique_line_compare; + if (mystique->type < MGA_1064SG) + svga->vblank_start = mystique_vblank_start; } else { svga->packed_chain4 = 0; svga->line_compare = NULL; + svga->lut_map = 0; if (mystique->type >= MGA_1064SG) svga->bpp = 8; + else + svga->vblank_start = NULL; } + + svga->fb_only = svga->packed_chain4; + svga->disable_blink = (svga->bpp > 4); + video_force_resize_set_monitor(1, svga->monitor_index); +#if 0 + pclog("PackedChain4=%d, chain4=%x, fast=%x, bit6 attrreg10=%02x, bits 5-6 gdcreg5=%02x, extmode=%02x.\n", svga->packed_chain4, svga->chain4, svga->fast, svga->attrregs[0x10] & 0x40, svga->gdcreg[5] & 0x60, mystique->pci_regs[0x41] & 1, mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE); +#endif } static void @@ -986,7 +1129,7 @@ mystique_recalc_mapping(mystique_t *mystique) 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, (mystique->type >= MGA_2164W) ? 0x1000000 : 0x800000); else mem_mapping_disable(&mystique->lfb_mapping); @@ -998,8 +1141,8 @@ mystique_recalc_mapping(mystique_t *mystique) 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; + 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); @@ -1038,6 +1181,8 @@ mystique_update_irqs(mystique_t *mystique) if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) irq = 1; + if ((mystique->status & mystique->ien) & STATUS_VLINEPEN) + irq = 1; if ((mystique->status & STATUS_VSYNCPEN) && (svga->crtc[0x11] & 0x30) == 0x10) irq = 1; @@ -1269,6 +1414,8 @@ mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) case XREG_XMISCCTRL: mystique->xmiscctrl = val; svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) + svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); break; case XREG_XGENCTRL: @@ -1381,12 +1528,12 @@ mystique_ctrl_read_b(uint32_t addr, void *priv) svga_t *svga = &mystique->svga; uint8_t ret = 0xff; int fifocount; - uint16_t addr_0x0f = 0; + uint8_t addr_0x0f = 0; uint16_t addr_0x03 = 0; int rs2 = 0; int rs3 = 0; - if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) { + if ((mystique->type == MGA_2064W || mystique->type == MGA_2164W) && (addr & 0x3e00) == 0x3c00) { /*RAMDAC*/ addr_0x0f = addr & 0x0f; @@ -1415,14 +1562,14 @@ mystique_ctrl_read_b(uint32_t addr, void *priv) switch (addr & 0x3fff) { case REG_FIFOSTATUS: fifocount = FIFO_SIZE - FIFO_ENTRIES; - if (fifocount > 64) - fifocount = 64; + if (fifocount > (mystique->type <= MGA_1064SG ? 32 : 64)) + fifocount = (mystique->type <= MGA_1064SG ? 32 : 64); ret = fifocount; break; case REG_FIFOSTATUS + 1: if (FIFO_EMPTY) ret |= 2; - else if (FIFO_ENTRIES >= 64) + else if (FIFO_ENTRIES >= (mystique->type <= MGA_1064SG ? 32 : 64)) ret |= 1; break; case REG_FIFOSTATUS + 2: @@ -1434,13 +1581,20 @@ mystique_ctrl_read_b(uint32_t addr, void *priv) ret = mystique->status & 0xff; if (svga->cgastat & 8) ret |= REG_STATUS_VSYNCSTS; + if (ret & 1) + mystique->softrap_status_read = 1; + if (mystique->softrap_status_read == 0 && !(ret & 1)) { + mystique->softrap_status_read = 1; + ret |= 1; + } 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) + if (mystique->busy || ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || !FIFO_EMPTY + || mystique->dma.state != DMA_STATE_IDLE || mystique->softrap_pending || mystique->endprdmasts_pending) ret |= (STATUS_DWGENGSTS >> 16); break; case REG_STATUS + 3: @@ -1448,7 +1602,7 @@ mystique_ctrl_read_b(uint32_t addr, void *priv) break; case REG_IEN: - ret = mystique->ien & 0x64; + ret = mystique->ien & 0x65; break; case REG_IEN + 1: case REG_IEN + 2: @@ -1617,6 +1771,10 @@ mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) case REG_MACCESS + 3: WRITE8(addr, mystique->maccess, val); mystique->dwgreg.dither = mystique->maccess >> 30; + if (mystique->type < MGA_2164W) + mystique->maccess &= ~MACCESS_ZWIDTH; + else + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * ((mystique->maccess & MACCESS_ZWIDTH) ? 4 : 2) + mystique->dwgreg.zorg; break; case REG_MCTLWTST: @@ -1753,7 +1911,7 @@ mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) 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; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * ((mystique->maccess & MACCESS_ZWIDTH) ? 4 : 2) + mystique->dwgreg.zorg; break; case REG_YTOP: case REG_YTOP + 1: @@ -1944,12 +2102,12 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) { mystique_t *mystique = (mystique_t *) priv; svga_t *svga = &mystique->svga; - uint16_t addr_0x0f = 0; + uint8_t addr_0x0f = 0; uint16_t addr_0x03 = 0; int rs2 = 0; int rs3 = 0; - if ((mystique->type == MGA_2064W) && (addr & 0x3e00) == 0x3c00) { + if ((mystique->type == MGA_2064W || mystique->type == MGA_2164W) && (addr & 0x3e00) == 0x3c00) { /*RAMDAC*/ addr_0x0f = addr & 0x0f; @@ -1991,6 +2149,7 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) switch (addr & 0x3fff) { case REG_ICLEAR: if (val & ICLEAR_SOFTRAPICLR) { + //pclog("softrapiclr\n"); mystique->status &= ~STATUS_SOFTRAPEN; mystique_update_irqs(mystique); } @@ -2035,6 +2194,10 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) thread_wait_mutex(mystique->dma.lock); WRITE8(addr, mystique->dma.primaddress, val); mystique->dma.pri_state = 0; + if (mystique->dma.state == DMA_STATE_IDLE && !(mystique->softrap_pending || mystique->endprdmasts_pending || !mystique->softrap_status_read)) { + mystique->dma.words_expected = 0; + } + mystique->dma.state = DMA_STATE_IDLE; thread_release_mutex(mystique->dma.lock); break; @@ -2068,6 +2231,12 @@ mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *priv) mystique->blitter_complete_refcount = 0; mystique->dwgreg.iload_rem_count = 0; mystique->status = STATUS_ENDPRDMASTS; + thread_wait_mutex(mystique->dma.lock); + mystique->dma.pri_state = 0; + mystique->dma.sec_state = 0; + mystique->dma.state = DMA_STATE_IDLE; + mystique->dma.words_expected = 0; + thread_release_mutex(mystique->dma.lock); break; case REG_ATTR_IDX: @@ -2225,7 +2394,7 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) case REG_ZORG: mystique->dwgreg.zorg = val; - mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * 2 + mystique->dwgreg.zorg; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg * ((mystique->maccess & MACCESS_ZWIDTH) ? 4 : 2) + mystique->dwgreg.zorg; break; case REG_PLNWT: @@ -2233,10 +2402,10 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) break; case REG_SHIFT: - mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.funcnt = val & 0x7f; mystique->dwgreg.xoff = val & 7; mystique->dwgreg.yoff = (val >> 4) & 7; - mystique->dwgreg.stylelen = (val >> 16) & 0xff; + mystique->dwgreg.stylelen = (val >> 16) & 0x7f; break; case REG_PITCH: @@ -2352,14 +2521,47 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) mystique->dwgreg.ar[6] = val; break; + case REG_DR0_Z32LSB: + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFFFFF) | val; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + break; + + case REG_DR0_Z32MSB: + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & 0xFFFFFFFF) | ((val & 0xFFFFull) << 32ull); + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + break; + + case REG_DR2_Z32LSB: + mystique->dwgreg.extended_dr[2] = (mystique->dwgreg.extended_dr[2] & ~0xFFFFFFFF) | val; + mystique->dwgreg.dr[2] = (mystique->dwgreg.extended_dr[2] >> 16) & 0xFFFFFFFF; + break; + + case REG_DR2_Z32MSB: + mystique->dwgreg.extended_dr[2] = (mystique->dwgreg.extended_dr[2] & 0xFFFFFFFF) | ((val & 0xFFFFull) << 32ull); + mystique->dwgreg.dr[2] = (mystique->dwgreg.extended_dr[2] >> 16) & 0xFFFFFFFF; + break; + + case REG_DR3_Z32LSB: + mystique->dwgreg.extended_dr[3] = (mystique->dwgreg.extended_dr[3] & ~0xFFFFFFFF) | val; + mystique->dwgreg.dr[3] = (mystique->dwgreg.extended_dr[3] >> 16) & 0xFFFFFFFF; + break; + + case REG_DR3_Z32MSB: + mystique->dwgreg.extended_dr[3] = (mystique->dwgreg.extended_dr[3] & 0xFFFFFFFF) | ((val & 0xFFFFull) << 32ull); + mystique->dwgreg.dr[3] = (mystique->dwgreg.extended_dr[3] >> 16) & 0xFFFFFFFF; + break; + case REG_DR0: mystique->dwgreg.dr[0] = val; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)val << 16ull); break; case REG_DR2: mystique->dwgreg.dr[2] = val; + mystique->dwgreg.extended_dr[2] = (mystique->dwgreg.extended_dr[2] & ~0xFFFFull) | ((uint64_t)val << 16ull); break; case REG_DR3: mystique->dwgreg.dr[3] = val; + mystique->dwgreg.extended_dr[3] = (mystique->dwgreg.extended_dr[3] & ~0xFFFFull) | ((uint64_t)val << 16ull); break; case REG_DR4: mystique->dwgreg.dr[4] = val; @@ -2397,9 +2599,47 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) case REG_SOFTRAP: mystique->dma.state = DMA_STATE_IDLE; + mystique->dma.pri_state = 0; + mystique->dma.words_expected = 0; mystique->endprdmasts_pending = 1; mystique->softrap_pending_val = val; - mystique->softrap_pending = 1; + mystique->softrap_pending += 1; + break; + + case REG_ALPHACTRL: + mystique->dwgreg.alphactrl = val; + break; + + case REG_ALPHASTART: + mystique->dwgreg.alphastart = val; + break; + + case REG_ALPHAXINC: + mystique->dwgreg.alphaxinc = val; + break; + + case REG_ALPHAYINC: + mystique->dwgreg.alphayinc = val; + break; + + case REG_FOGCOL: + mystique->dwgreg.fogcol = val; + break; + + case REG_FOGSTART: + mystique->dwgreg.fogstart = val; + break; + + case REG_FOGXINC: + mystique->dwgreg.fogxinc = val; + break; + + case REG_FOGYINC: + mystique->dwgreg.fogyinc = val; + break; + + case REG_TEXFILTER: + mystique->dwgreg.texfilter = val; break; default: @@ -2436,14 +2676,25 @@ mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) case REG_PRIMEND: thread_wait_mutex(mystique->dma.lock); mystique->dma.primend = val; + //pclog("PRIMADDRESS = 0x%08X, PRIMEND = 0x%08X\n", mystique->dma.primaddress, mystique->dma.primend); 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; + //mystique->dma.pri_state = 0; wake_fifo_thread(mystique); } + /* HACK: For DirectX 9.0b Direct3D testing on Windows 98 SE. + + The 4.12.013 drivers give an out-of-bounds busmastering range when dxdiag enumerates Direct3D, with exactly 16384 bytes of difference. + Don't attempt busmastering in such cases. This isn't ideal, but there are no more crashes faced in this case. */ + if ((mystique->dma.primend & DMA_ADDR_MASK) < (mystique->dma.primaddress & DMA_ADDR_MASK) && ((mystique->dma.primaddress & DMA_ADDR_MASK) - (mystique->dma.primend & DMA_ADDR_MASK)) == 0x4000) + { + mystique->dma.primaddress = mystique->dma.primend; + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } thread_release_mutex(mystique->dma.lock); break; @@ -2569,7 +2820,14 @@ mystique_readb_linear(uint32_t addr, void *priv) { const svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_b; + cycles -= svga->monitor->mon_video_timing_read_b; + + if (!svga->fast) { + if (svga->chain2_read) { + addr &= ~1; + addr <<= 2; + } + } addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -2583,7 +2841,7 @@ mystique_readw_linear(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_w; + cycles -= svga->monitor->mon_video_timing_read_w; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -2597,7 +2855,7 @@ mystique_readl_linear(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= video_timing_read_l; + cycles -= svga->monitor->mon_video_timing_read_l; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -2611,13 +2869,20 @@ mystique_writeb_linear(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_b; + cycles -= svga->monitor->mon_video_timing_write_b; + + if (!svga->fast) { + if (svga->chain2_write) { + addr &= ~1; + addr <<= 2; + } + } addr &= svga->decode_mask; if (addr >= svga->vram_max) return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; svga->vram[addr] = val; } @@ -2626,13 +2891,13 @@ mystique_writew_linear(uint32_t addr, uint16_t val, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_w; + cycles -= svga->monitor->mon_video_timing_write_w; addr &= svga->decode_mask; if (addr >= svga->vram_max) return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; *(uint16_t *) &svga->vram[addr] = val; } @@ -2641,13 +2906,13 @@ mystique_writel_linear(uint32_t addr, uint32_t val, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= video_timing_write_l; + cycles -= svga->monitor->mon_video_timing_write_l; addr &= svga->decode_mask; if (addr >= svga->vram_max) return; addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; *(uint32_t *) &svga->vram[addr] = val; } @@ -2658,27 +2923,52 @@ run_dma(mystique_t *mystique) thread_wait_mutex(mystique->dma.lock); + if (mystique->softrap_pending || mystique->endprdmasts_pending || !mystique->softrap_status_read) + { + thread_release_mutex(mystique->dma.lock); + return; + } + if (mystique->dma.state == DMA_STATE_IDLE) { + if (!(mystique->status & STATUS_ENDPRDMASTS)) + { + /* Force this to appear. */ + mystique->endprdmasts_pending = 1; + } thread_release_mutex(mystique->dma.lock); return; } while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { - switch (mystique->dma.state) { + switch (atomic_load(&mystique->dma.state)) { case DMA_STATE_PRI: switch (mystique->dma.primaddress & DMA_MODE_MASK) { case DMA_MODE_REG: - if (mystique->dma.pri_state == 0) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + break; + } + if (mystique->dma.pri_state == 0 && !mystique->dma.words_expected) { dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.pri_header, 4, 4); + //pclog("DMA header: 0x%08X\n", mystique->dma.pri_header); mystique->dma.primaddress += 4; + mystique->dma.words_expected = 4; + words_transferred++; } - if ((mystique->dma.pri_header & 0xff) != 0x15) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + break; + } + + { 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; + words_transferred++; reg_addr = (mystique->dma.pri_header & 0x7f) << 2; if (mystique->dma.pri_header & 0x80) @@ -2689,15 +2979,24 @@ run_dma(mystique_t *mystique) if ((reg_addr & 0x300) == 0x100) mystique->blitter_submit_dma_refcount++; + //pclog("DMA value: 0x%08X to reg 0x%04X\n", val, reg_addr); mystique_accel_ctrl_write_l(reg_addr, val, mystique); + if (reg_addr == REG_SOFTRAP) { + mystique->dma.primaddress += 4; + break; + } } + if (mystique->dma.words_expected) + mystique->dma.words_expected--; + mystique->dma.primaddress += 4; + 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; + if (mystique->dma.state == DMA_STATE_SEC) { + mystique->dma.sec_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; @@ -2712,9 +3011,36 @@ run_dma(mystique_t *mystique) case DMA_STATE_SEC: switch (mystique->dma.secaddress & DMA_MODE_MASK) { case DMA_MODE_REG: + 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; + mystique->dma.pri_state = 0; + mystique->dma.words_expected = 0; + } else { + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } + } 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; + //pclog("DMA header (secondary): 0x%08X\n", mystique->dma.sec_header); + 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; + mystique->dma.pri_state = 0; + mystique->dma.words_expected = 0; + } else { + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } } uint32_t val; @@ -2733,23 +3059,40 @@ run_dma(mystique_t *mystique) mystique->blitter_submit_dma_refcount++; mystique_accel_ctrl_write_l(reg_addr, val, mystique); - + //pclog("DMA value (secondary): 0x%08X\n", val); 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.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.pri_state = 0; + mystique->dma.words_expected = 0; + } else { mystique->dma.state = DMA_STATE_PRI; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } } break; case DMA_MODE_BLIT: { uint32_t val; + 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; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } else { + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } + } dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4); mystique->dma.secaddress += 4; @@ -2758,12 +3101,17 @@ run_dma(mystique_t *mystique) blit_iload_write(mystique, val, 32); words_transferred++; - if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + 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.words_expected = 0; + mystique->dma.pri_state = 0; + } else { mystique->dma.state = DMA_STATE_PRI; + mystique->dma.words_expected = 0; + mystique->dma.pri_state = 0; + } } } break; @@ -2882,12 +3230,14 @@ mystique_softrap_pending_timer(void *priv) mystique->status |= STATUS_ENDPRDMASTS; } if (mystique->softrap_pending) { - mystique->softrap_pending = 0; - mystique->dma.secaddress = mystique->softrap_pending_val; mystique->status |= STATUS_SOFTRAPEN; + mystique->softrap_status_read = 0; + //pclog("softrapen\n"); mystique_update_irqs(mystique); + mystique->softrap_pending--; } + } static void @@ -3236,6 +3586,12 @@ blit_fbitblt(mystique_t *mystique) mystique->blitter_complete_refcount++; } +static uint8_t +dither_24_to_8(int r, int g, int b) +{ + return ((b >> 6) & 3) | (((g >> 5) & 7) << 2) | (((r >> 5) & 7) << 5); +} + static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size) { @@ -3468,6 +3824,26 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) 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_16: + { + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(dither(mystique, (data64 >> 16) & 0xFF, (data64 >> 8) & 0xFF, data64 & 0xFF, mystique->dwgreg.xdst & 1, mystique->dwgreg.selline & 1), 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_8: + { + dst = ((uint8_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(dither_24_to_8((data64 >> 16) & 0xFF, (data64 >> 8) & 0xFF, data64 & 0xFF), dst, mystique->dwgreg.dwgctrl_running); + + ((uint8_t *) 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; + } case MACCESS_PWIDTH_32: dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; @@ -3509,13 +3885,39 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) 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]; + pclog("maccess = 0x%X\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); 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]; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + { + dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; - 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; + dst = bitop(dither(mystique, (data64 >> 16) & 0xFF, (data64 >> 8) & 0xFF, data64 & 0xFF, mystique->dwgreg.xdst & 1, mystique->dwgreg.selline & 1), 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_8: + { + dst = ((uint8_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(dither_24_to_8((data64 >> 16) & 0xFF, (data64 >> 8) & 0xFF, data64 & 0xFF), dst, mystique->dwgreg.dwgctrl_running); + + ((uint8_t *) 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; + } + default: { + dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + 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; + break; + } + } } size = 0; @@ -3943,21 +4345,43 @@ z_check(uint16_t z, uint16_t old_z, uint32_t z_mode) // mystique->dwgreg.dwgctrl } } +static int +z_check_32(uint32_t z, uint32_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_NOZCMP: + default: + return 1; + } +} + static void -blit_line(mystique_t *mystique, UNUSED(int closed)) +blit_line(mystique_t *mystique, int closed, int autoline) { svga_t *svga = &mystique->svga; - uint32_t src; + uint32_t src = 0; uint32_t dst; uint32_t old_dst; - int x; + int x = mystique->dwgreg.xdst; 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) { + 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: @@ -3965,8 +4389,16 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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; + if (closed) { + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { + 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: @@ -3974,17 +4406,33 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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; + if (closed) { + ((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; + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + ((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; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { + ((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; + 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; + if (closed) { + *(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; + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + *(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; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { + *(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: @@ -3992,8 +4440,16 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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; + if (closed) { + ((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; + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + ((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; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { + ((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: @@ -4001,19 +4457,26 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) } } + if (!mystique->dwgreg.length) + break; + if (mystique->dwgreg.sgn.sdydxl) x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else + else { + mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1); + mystique->dwgreg.ydst &= 0x7fffff; 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) + } + if (mystique->dwgreg.err >= 0) { + mystique->dwgreg.err += mystique->dwgreg.k2; + if (mystique->dwgreg.sgn.sdydxl) { + mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1); + mystique->dwgreg.ydst &= 0x7fffff; mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else + } else x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.err += mystique->dwgreg.k1; mystique->dwgreg.length--; } @@ -4022,22 +4485,46 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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]; + bool z_check_pass = false; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + uint32_t z = (mystique->dwgreg.extended_dr[0] & (1ull << 47ull)) ? 0 : (mystique->dwgreg.extended_dr[0] >> 15ull); + uint32_t *z_p = (uint32_t *) &svga->vram[(mystique->dwgreg.ydst_lin * 4 + mystique->dwgreg.zorg) & mystique->vram_mask]; + uint32_t old_z = z_p[x]; + z_check_pass = z_check_32(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + if (z_write && z_check_pass) { + z_p[x] = z; + } + } else { + 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]; + z_check_pass = z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + if (z_write && z_check_pass) { + z_p[x] = z; + } + } - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + if (z_check_pass) { int r = 0; int g = 0; int b = 0; - if (z_write) - z_p[x] = z; - switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 20) & 0x7; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 20) & 0x7; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 21) & 0x3; + dst = (r << 5) | (g << 2) | b; + + ((uint8_t *) 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: if (!(mystique->dwgreg.dr[4] & (1 << 23))) r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; @@ -4051,6 +4538,33 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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.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; + dst = (r << 16) | (g << 8) | b; + + ((uint32_t *) svga->vram)[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = dst | (old_dst & 0xFF000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + 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; + dst = (r << 16) | (g << 8) | b; + + ((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 I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } @@ -4062,25 +4576,37 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) 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]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += mystique->dwgreg.extended_dr[2]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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 (mystique->dwgreg.err >= 0) { + mystique->dwgreg.err += mystique->dwgreg.k2; 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]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += mystique->dwgreg.extended_dr[3]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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.err += mystique->dwgreg.k1; mystique->dwgreg.length--; } @@ -4097,7 +4623,7 @@ blit_line(mystique_t *mystique, UNUSED(int closed)) } static void -blit_autoline(mystique_t *mystique, int closed) +blit_line_start(mystique_t *mystique, int closed, int autoline) { int start_x = (int32_t) mystique->dwgreg.ar[5]; int start_y = (int32_t) mystique->dwgreg.ar[6]; @@ -4106,45 +4632,54 @@ blit_autoline(mystique_t *mystique, int closed) 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); + if (autoline) { + if (ABS(dx) > ABS(dy)) { + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.k1 = 2 * ABS(dy); + mystique->dwgreg.err = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.k2 = 2 * ABS(dy) - 2 * ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); + } else { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.k1 = 2 * ABS(dx); + mystique->dwgreg.err = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.k2 = 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; } 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.k1 = (int32_t) mystique->dwgreg.ar[0]; + mystique->dwgreg.err = (int32_t) mystique->dwgreg.ar[1]; + mystique->dwgreg.k2 = (int32_t) mystique->dwgreg.ar[2]; } - mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; - mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; - blit_line(mystique, closed); + blit_line(mystique, closed, autoline); - 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; + if (autoline) { + 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; + uint64_t z_back_32; uint32_t z_back; uint32_t r_back; uint32_t g_back; uint32_t b_back; int z_write; int y; + int err_l = (int32_t)mystique->dwgreg.ar[1]; + int err_r = (int32_t)mystique->dwgreg.ar[4]; 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: @@ -4153,8 +4688,14 @@ blit_trap(mystique_t *mystique) 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; + int len; - while (x_l != x_r) { + if (x_l > x_r) + len = x_l - x_r; + else + len = x_r - x_l; + + while (len > 0) { 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]; @@ -4186,25 +4727,21 @@ blit_trap(mystique_t *mystique) fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } + len--; 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]; + while ((err_l < 0) && mystique->dwgreg.ar[0]) { + err_l += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + err_l += 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]; + while ((err_r < 0) && mystique->dwgreg.ar[6]) { + err_r += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + err_r += mystique->dwgreg.ar[5]; mystique->dwgreg.ydst++; mystique->dwgreg.ydst &= 0x7fffff; @@ -4220,8 +4757,14 @@ blit_trap(mystique_t *mystique) 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; + int len; - while (x_l != x_r) { + if (x_l > x_r) + len = x_l - x_r; + else + len = x_r - x_l; + + while (len > 0) { 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]; @@ -4267,24 +4810,20 @@ blit_trap(mystique_t *mystique) } } x_l++; - mystique->pixel_count++; + len--; } - 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]; + while ((err_l < 0) && mystique->dwgreg.ar[0]) { + err_l += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + err_l += 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]; + while ((err_r < 0) && mystique->dwgreg.ar[6]) { + err_r += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + err_r += mystique->dwgreg.ar[5]; mystique->dwgreg.ydst++; mystique->dwgreg.ydst &= 0x7fffff; @@ -4300,12 +4839,14 @@ blit_trap(mystique_t *mystique) 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]; + uint16_t *z_p = (uint16_t *) &svga->vram[(mystique->dwgreg.ydst_lin * ((mystique->maccess_running & MACCESS_ZWIDTH) ? 4 : 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_32 = mystique->dwgreg.extended_dr[0]; + z_back = mystique->dwgreg.dr[0]; r_back = mystique->dwgreg.dr[4]; g_back = mystique->dwgreg.dr[8]; @@ -4313,10 +4854,18 @@ blit_trap(mystique_t *mystique) 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]; + bool z_check_pass = false; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + uint32_t z = (mystique->dwgreg.extended_dr[0] & (1ull << 47ull)) ? 0 : (mystique->dwgreg.extended_dr[0] >> 15ull); + uint32_t old_z = *(uint32_t*)&z_p[x_l * 2]; + z_check_pass = z_check_32(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + } else { + uint16_t z = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + z_check_pass = z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + } - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + if (z_check_pass) { uint32_t dst = 0; uint32_t old_dst; int r = 0; @@ -4330,8 +4879,13 @@ blit_trap(mystique_t *mystique) 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) { + if (mystique->maccess_running & MACCESS_ZWIDTH) { + *(uint32_t*)(&z_p[x_l * 2]) = (mystique->dwgreg.extended_dr[0] & (1ull << 47ull)) ? 0 : (mystique->dwgreg.extended_dr[0] >> 15ull); + } + else + z_p[x_l] = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + } switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: @@ -4362,16 +4916,30 @@ blit_trap(mystique_t *mystique) } } - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += mystique->dwgreg.extended_dr[2]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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++; + if (x_l > x_r) + x_l--; + else + x_l++; } - mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] = z_back_32 + mystique->dwgreg.extended_dr[3]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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]; @@ -4389,7 +4957,13 @@ blit_trap(mystique_t *mystique) 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]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += dx * mystique->dwgreg.extended_dr[2]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += dx * mystique->dwgreg.dr[2]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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]; @@ -4403,41 +4977,27 @@ blit_trap(mystique_t *mystique) break; default: - fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); +#if 0 + pclog("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); +#endif + break; } mystique->blitter_complete_refcount++; } -static int -texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) +static uint16_t texture_texel_fetch(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *tex_a, int *atransp, int s, int t, int tex_pitch) { - 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; - int t; + const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; + svga_t* svga = &mystique->svga; + uint16_t src = 0x0; - 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); + int atransp_dummy = 0; - 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; - - 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 (!atransp) + atransp = &atransp_dummy; if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { if (s < 0) @@ -4457,7 +5017,7 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra 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]; + src = svga->vram[(mystique->dwgreg.texorg + (((t * tex_pitch) + s) >> 1)) & mystique->vram_mask]; if (s & 1) src >>= 4; else @@ -4468,14 +5028,14 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra *atransp = 0; break; case TEXCTL_TEXFORMAT_TW8: - src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; + src = svga->vram[(mystique->dwgreg.texorg + (t * tex_pitch) + 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]; + src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t * tex_pitch) + s) & mystique->vram_mask_w]; *tex_r = ((src >> 10) & 0x1f) << 3; *tex_g = ((src >> 5) & 0x1f) << 3; *tex_b = (src & 0x1f) << 3; @@ -4484,8 +5044,22 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra else *atransp = 0; break; + case TEXCTL_TEXFORMAT_TW12: + src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t * tex_pitch) + s) & mystique->vram_mask_w]; + *tex_r = ((src >> 8) & 0xf) << 4; + *tex_g = ((src >> 4) & 0xf) << 4; + *tex_b = (src & 0xf) << 4; + *tex_a = ((src >> 12) & 0xf) << 4; + if (mystique->dwgreg.texctl & TEXCTL_AZEROEXTEND) { + *atransp = (((src >> 12) & 0xf) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key; + } else { + uint8_t ta_mask = mystique->dwgreg.ta_mask ? 0xf : 0x0; + uint8_t ta_key = mystique->dwgreg.ta_key ? 0xf : 0x0; + *atransp = (((src >> 12) & 0xf) & ta_mask) == ta_key; + } + break; case TEXCTL_TEXFORMAT_TW16: - src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + src = ((uint16_t *) svga->vram)[((mystique->dwgreg.texorg >> 1) + (t * tex_pitch) + s) & mystique->vram_mask_w]; *tex_r = (src >> 11) << 3; *tex_g = ((src >> 5) & 0x3f) << 2; *tex_b = (src & 0x1f) << 3; @@ -4495,6 +5069,111 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); break; } + return src; +} + +static double lerp(double v0, double v1, double t) { + return (1. - t) * v0 + t * v1; +} + +static int +texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp, int *tex_a) +{ + const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); + 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; + int tex_pitch = 1 << tex_shift; + double s_frac = 0; + double t_frac = 0; + + *tex_a = 255; + + if (mystique->type >= MGA_G100 && (mystique->dwgreg.texctl & TEXCTL_TPITCHLIN)) + { + tex_pitch = (mystique->dwgreg.texctl & TEXCTL_TPITCHEXT_MASK) >> 9; + if (tex_pitch == 0) + tex_pitch = 2048; + } + + 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); + + s = (int32_t) mystique->dwgreg.tmr[6] >> s_shift; + t = (int32_t) mystique->dwgreg.tmr[7] >> t_shift; + s_frac = (((int32_t) mystique->dwgreg.tmr[6] >> s_shift) & ((1 << s_shift) - 1)) / (double)(1 << s_shift); + t_frac = (((int32_t) mystique->dwgreg.tmr[7] >> t_shift) & ((1 << t_shift) - 1)) / (double)(1 << 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]) : 0; + + s = ((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) >> s_shift; + t = ((int64_t) (int32_t) mystique->dwgreg.tmr[7] * q) >> t_shift; + s_frac = (((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) & ((1 << s_shift) - 1)) / (double)(1 << s_shift); + t_frac = (((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) & ((1 << t_shift) - 1)) / (double)(1 << t_shift); + } + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { + if (s < 0) + s = 0; + else if (s > w_mask) + s = w_mask; + } else + s &= w_mask; + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { + if (t < 0) + t = 0; + else if (t > h_mask) + t = h_mask; + } else + t &= h_mask; + + src = texture_texel_fetch(mystique, tex_r, tex_g, tex_b, tex_a, atransp, s, t, tex_pitch); + switch (mystique->dwgreg.texfilter & 3) + { + case 0: + s_frac = t_frac = 0; + break; + case 1: + case 2: + break; + case 3: + s_frac = t_frac = .25; + break; + } + if (s_frac && s != w_mask) + { + int s_tex_r = 0, s_tex_g = 0, s_tex_b = 0, s_tex_a = 255; + texture_texel_fetch(mystique, &s_tex_r, &s_tex_g, &s_tex_b, &s_tex_a, NULL, s + 1, t, tex_pitch); + *tex_r = (int)lerp(*tex_r, s_tex_r, s_frac); + *tex_g = (int)lerp(*tex_g, s_tex_g, s_frac); + *tex_b = (int)lerp(*tex_b, s_tex_b, s_frac); + *tex_a = (int)lerp(*tex_a, s_tex_a, s_frac); + if (*tex_r > 255) *tex_r = 255; + if (*tex_g > 255) *tex_g = 255; + if (*tex_b > 255) *tex_b = 255; + if (*tex_a > 255) *tex_a = 255; + } + if (t_frac && t != h_mask) + { + int t_tex_r = 0, t_tex_g = 0, t_tex_b = 0, t_tex_a = 255; + texture_texel_fetch(mystique, &t_tex_r, &t_tex_g, &t_tex_b, &t_tex_a, NULL, s, t + 1, tex_pitch); + *tex_r = (int)lerp(*tex_r, t_tex_r, t_frac); + *tex_g = (int)lerp(*tex_g, t_tex_g, t_frac); + *tex_b = (int)lerp(*tex_b, t_tex_b, t_frac); + *tex_a = (int)lerp(*tex_a, t_tex_a, t_frac); + if (*tex_r > 255) *tex_r = 255; + if (*tex_g > 255) *tex_g = 255; + if (*tex_b > 255) *tex_b = 255; + if (*tex_a > 255) *tex_a = 255; + } return ((src & tkmask) == tckey); } @@ -4508,8 +5187,6 @@ blit_texture_trap(mystique_t *mystique) 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); - mystique->trap_count++; - switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_I: case DWGCTRL_ATYPE_ZI: @@ -4517,12 +5194,14 @@ blit_texture_trap(mystique_t *mystique) 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]; + uint16_t *z_p = (uint16_t *) &svga->vram[(mystique->dwgreg.ydst_lin * ((mystique->maccess_running & MACCESS_ZWIDTH) ? 4 : 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; + uint64_t z_back_32 = mystique->dwgreg.extended_dr[0]; + uint32_t z_back = mystique->dwgreg.dr[0]; uint32_t r_back = mystique->dwgreg.dr[4]; uint32_t g_back = mystique->dwgreg.dr[8]; @@ -4530,21 +5209,35 @@ blit_texture_trap(mystique_t *mystique) 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 a_back = mystique->dwgreg.alphastart; + uint32_t fog_back = mystique->dwgreg.fogstart; 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]; + bool z_check_pass = false; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + uint32_t z = (mystique->dwgreg.extended_dr[0] & (1ull << 47ull)) ? 0 : (mystique->dwgreg.extended_dr[0] >> 15ull); + uint32_t old_z = *(uint32_t*)&z_p[x_l * 2]; + z_check_pass = z_check_32(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + } else { + uint16_t z = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + z_check_pass = z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK); + } - if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + if (z_check_pass) { int tex_r = 0; int tex_g = 0; int tex_b = 0; + int tex_a = 255; int ctransp; int atransp = 0; int i_r = 0; int i_g = 0; int i_b = 0; + int i_a = 255; + int i_fog = 0; + uint8_t final_a = 255; if (!(mystique->dwgreg.dr[4] & (1 << 23))) i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; @@ -4553,7 +5246,43 @@ blit_texture_trap(mystique_t *mystique) 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); + if (mystique->type >= MGA_G100) + { + if (!(mystique->dwgreg.alphastart & (1 << 23))) + i_a = (mystique->dwgreg.alphastart >> 15) & 0xff; + else + i_a = 0; + + if (!(mystique->dwgreg.fogstart & (1 << 23))) + i_fog = (mystique->dwgreg.fogstart >> 15) & 0xff; + else + i_fog = 0; + } + + ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp, &tex_a); + + if (mystique->type >= MGA_G100) + { + uint8_t alpha_sel = (mystique->dwgreg.alphactrl >> 24) & 3; + + switch (alpha_sel) + { + case 0x0: /* alpha from texture */ + final_a = tex_a; + break; + default: + case 0x1: /* interpolated alpha */ + if ((mystique->dwgreg.alphactrl & (1 << 11))) + final_a = i_a; + break; + case 0x2: /* modulated alpha */ + if (!(mystique->dwgreg.alphactrl & (1 << 11))) + final_a = tex_a; + else + final_a = ((i_a * tex_a) >> 8) & 0xFF; + break; + } + } switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) { case 0: @@ -4603,6 +5332,26 @@ blit_texture_trap(mystique_t *mystique) fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); } + if (mystique->type >= MGA_G100 && (mystique->maccess_running & MACCESS_FOGEN)) + { + tex_r = (tex_r * ((i_fog) / 255.)) + (mystique->dwgreg.fogcol >> 16) * ((255 - i_fog) / 255.); + tex_g = (tex_g * ((i_fog) / 255.)) + ((mystique->dwgreg.fogcol >> 8) & 0xFF) * ((255 - i_fog) / 255.); + tex_b = (tex_b * ((i_fog) / 255.)) + ((mystique->dwgreg.fogcol) & 0xFF) * ((255 - i_fog) / 255.); + } + + if (final_a != 255) + { + { + double threshold = bayer_mat[mystique->dwgreg.selline & 3][x_l & 3]; + double final_a_frac = (final_a) / 255.; + if (final_a_frac >= threshold) { + final_a = 255; + } else { + goto skip_pixel; + } + } + } + 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; @@ -4610,30 +5359,57 @@ blit_texture_trap(mystique_t *mystique) ((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 (z_write) { + if (mystique->maccess_running & MACCESS_ZWIDTH) { + *(uint32_t*)(&z_p[x_l * 2]) = (mystique->dwgreg.extended_dr[0] & (1ull << 47ull)) ? 0 : (mystique->dwgreg.extended_dr[0] >> 15ull); + } + else + z_p[x_l] = ((int32_t) mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + } } } skip_pixel: - x_l++; - mystique->pixel_count++; + if (x_l > x_r) + x_l--; + else + x_l++; - mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += mystique->dwgreg.extended_dr[2]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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.fogstart += mystique->dwgreg.fogxinc; + mystique->dwgreg.alphastart += mystique->dwgreg.alphaxinc; + mystique->dwgreg.fogstart &= 0xFFFFFF; + mystique->dwgreg.alphastart &= 0xFFFFFF; } - 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]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] = z_back_32 + mystique->dwgreg.extended_dr[3]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } + 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.fogstart = fog_back + mystique->dwgreg.fogyinc; + mystique->dwgreg.alphastart = a_back + mystique->dwgreg.alphayinc; + mystique->dwgreg.fogstart &= 0xFFFFFF; + mystique->dwgreg.alphastart &= 0xFFFFFF; while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; @@ -4648,13 +5424,23 @@ skip_pixel: 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]; + if (mystique->maccess_running & MACCESS_ZWIDTH) { + mystique->dwgreg.extended_dr[0] += dx * mystique->dwgreg.extended_dr[2]; + mystique->dwgreg.dr[0] = (mystique->dwgreg.extended_dr[0] >> 16) & 0xFFFFFFFF; + } else { + mystique->dwgreg.dr[0] += dx * mystique->dwgreg.dr[2]; + mystique->dwgreg.extended_dr[0] = (mystique->dwgreg.extended_dr[0] & ~0xFFFFull) | ((uint64_t)mystique->dwgreg.dr[0] << 16ull); + } 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.fogstart += dx * mystique->dwgreg.fogxinc; + mystique->dwgreg.alphastart += dx * mystique->dwgreg.alphaxinc; + mystique->dwgreg.fogstart &= 0xFFFFFF; + mystique->dwgreg.alphastart &= 0xFFFFFF; mystique->dwgreg.ydst++; mystique->dwgreg.ydst &= 0x7fffff; @@ -4681,11 +5467,25 @@ blit_bitblt(mystique_t *mystique) 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; + uint32_t bltckey = mystique->dwgreg.fcol; + uint32_t bltcmsk = mystique->dwgreg.bcol; + + 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; + } switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_BLK: switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { case DWGCTRL_BLTMOD_BMONOLEF: + case DWGCTRL_BLTMOD_BMONOWF: src_addr = mystique->dwgreg.ar[3]; for (y = 0; y < mystique->dwgreg.length; y++) { @@ -4694,7 +5494,7 @@ blit_bitblt(mystique_t *mystique) 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; + int bit_offset = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) == DWGCTRL_BLTMOD_BMONOWF) ? (7 - (src_addr & 7)) : (src_addr & 7); uint32_t old_dst; switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { @@ -4747,9 +5547,14 @@ blit_bitblt(mystique_t *mystique) } else src_addr += x_dir; - if (x != x_end) - x += x_dir; - else + if (x != x_end) { + if ((x > x_end) && (x_dir == 1)) + x--; + else if ((x < x_end) && (x_dir == -1)) + x++; + else + x += x_dir; + } else break; } @@ -4786,7 +5591,93 @@ blit_bitblt(mystique_t *mystique) } case DWGCTRL_ATYPE_RSTR: switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + /* TODO: This isn't exactly perfect. */ + case DWGCTRL_BLTMOD_BPLAN: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + fatal("BITBLT RPL/RSTR BPLAN with pattern\n"); + + 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; + + while (1) { + uint32_t byte_addr = src_addr & mystique->vram_mask; + + 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) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && trans[x & 3]) { + uint32_t src = (svga->vram[byte_addr] & 1) ? 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]; + + 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: + 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; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); // & DWGCTRL_BOP_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; + + case MACCESS_PWIDTH_32: + 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; + + default: + fatal("BITBLT RPL BPLAN 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]; + } else + src_addr += x_dir; + + if (x != x_end) { + if ((x > x_end) && (x_dir == 1)) + x--; + else if ((x < x_end) && (x_dir == -1)) + x++; + else + 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; case DWGCTRL_BLTMOD_BMONOLEF: + case DWGCTRL_BLTMOD_BMONOWF: if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); @@ -4798,7 +5689,7 @@ blit_bitblt(mystique_t *mystique) while (1) { uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; - int bit_offset = src_addr & 7; + int bit_offset = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) == DWGCTRL_BLTMOD_BMONOWF) ? (7 - (src_addr & 7)) : (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; @@ -4854,9 +5745,14 @@ blit_bitblt(mystique_t *mystique) } else src_addr += x_dir; - if (x != x_end) - x += x_dir; - else + if (x != x_end) { + if ((x > x_end) && (x_dir == 1)) + x--; + else if ((x < x_end) && (x_dir == -1)) + x++; + else + x += x_dir; + } else break; } @@ -4886,6 +5782,8 @@ blit_bitblt(mystique_t *mystique) case MACCESS_PWIDTH_8: src = svga->vram[src_addr & mystique->vram_mask]; dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + if (!((!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) || (src & bltcmsk) != bltckey))) + break; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4896,6 +5794,8 @@ blit_bitblt(mystique_t *mystique) 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]; + if (!((!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) || (src & bltcmsk) != bltckey))) + break; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4906,6 +5806,8 @@ blit_bitblt(mystique_t *mystique) 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]; + if (!((!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) || (src & bltcmsk) != bltckey))) + break; dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); @@ -4916,6 +5818,8 @@ blit_bitblt(mystique_t *mystique) 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]; + if (!((!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) || (src & bltcmsk) != bltckey))) + break; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4937,9 +5841,14 @@ blit_bitblt(mystique_t *mystique) } else src_addr += x_dir; - if (x != x_end) - x += x_dir; - else + if (x != x_end) { + if ((x > x_end) && (x_dir == 1)) + x--; + else if ((x < x_end) && (x_dir == -1)) + x++; + else + x += x_dir; + } else break; } @@ -5024,7 +5933,9 @@ blit_idump(mystique_t *mystique) mystique->dwgreg.iload_rem_data = 0; mystique->dwgreg.idump_end_of_line = 0; mystique->busy = 1; - /* pclog("IDUMP ATYPE RPL busy\n"); */ +#if 0 + pclog("IDUMP ATYPE RPL busy\n"); +#endif break; default: @@ -5121,27 +6032,32 @@ blit_iload_highv(mystique_t *mystique) static void mystique_start_blit(mystique_t *mystique) { + svga_t *svga = &mystique->svga; uint64_t start_time = plat_timer_read(); uint64_t end_time; + /*Make sure we don't get any artifacts.*/ + svga->chain2_write = 0; + svga->chain2_read = 0; + mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; mystique->maccess_running = mystique->maccess; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { case DWGCTRL_OPCODE_LINE_OPEN: - blit_line(mystique, 0); + blit_line_start(mystique, 0, 0); break; case DWGCTRL_OPCODE_AUTOLINE_OPEN: - blit_autoline(mystique, 0); + blit_line_start(mystique, 0, 1); break; case DWGCTRL_OPCODE_LINE_CLOSE: - blit_line(mystique, 1); + blit_line_start(mystique, 1, 0); break; case DWGCTRL_OPCODE_AUTOLINE_CLOSE: - blit_autoline(mystique, 1); + blit_line_start(mystique, 1, 1); break; case DWGCTRL_OPCODE_TRAP: @@ -5210,9 +6126,20 @@ mystique_hwcursor_draw(svga_t *svga, int displine) 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]; + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, mystique->cursor.col[1]) : svga_lookup_lut_ram(svga, mystique->cursor.col[0]); else if (dat[0] & (1ULL << 63)) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + break; + + case XCURCTRL_CURMODE_XWIN: + for (uint8_t x = 0; x < 64; x++) { + if ((dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? (mystique->cursor.col[1]) : (mystique->cursor.col[0]); offset++; dat[0] <<= 1; @@ -5228,6 +6155,27 @@ mystique_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += 16; } +static uint8_t +mystique_tvp3026_gpio_read(uint8_t cntl, void *priv) +{ + mystique_t *mystique = (mystique_t *) priv; + + uint8_t ret = 0xff; + if (!i2c_gpio_get_scl(mystique->i2c_ddc)) + ret &= ~0x10; + if (!i2c_gpio_get_sda(mystique->i2c_ddc)) + ret &= ~0x04; + return ret; +} + +static void +mystique_tvp3026_gpio_write(uint8_t cntl, uint8_t data, void *priv) +{ + mystique_t *mystique = (mystique_t *) priv; + + i2c_gpio_set(mystique->i2c_ddc, !(cntl & 0x10) || (data & 0x10), !(cntl & 0x04) || (data & 0x04)); +} + static uint8_t mystique_pci_read(UNUSED(int func), int addr, void *priv) { @@ -5246,10 +6194,16 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) break; case 0x02: - ret = (mystique->type == MGA_2064W) ? 0x19 : 0x1a; + if (mystique->type == MGA_G100) + ret = 0x01; + else + ret = (mystique->type == MGA_2164W) ? 0x1b : ((mystique->type == MGA_2064W) ? 0x19 : 0x1a); break; /*MGA*/ case 0x03: - ret = 0x05; + if (mystique->type == MGA_G100) + ret = 0x10; + else + ret = 0x05; break; case PCI_REG_COMMAND: @@ -5267,7 +6221,7 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) break; /*Fast DEVSEL timing*/ case 0x08: - ret = 0; + ret = (mystique->type == MGA_1164SG) ? 3 : 0; break; /*Revision ID*/ case 0x09: ret = 0; @@ -5282,25 +6236,46 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0x10: ret = 0x00; - break; /*Control aperture*/ + break; /*Control aperture for Millennium and Mystique, LFB for Mystique 220 and later*/ case 0x11: - ret = (mystique->ctrl_base >> 8) & 0xc0; + if (mystique->type >= MGA_1164SG) + ret = 0x00; + else + ret = (mystique->ctrl_base >> 8) & 0xc0; break; case 0x12: - ret = mystique->ctrl_base >> 16; + if (mystique->type >= MGA_1164SG) + ret = (mystique->type >= MGA_2164W) ? 0x00 : ((mystique->lfb_base >> 16) & 0x80); + else + ret = mystique->ctrl_base >> 16; break; case 0x13: - ret = mystique->ctrl_base >> 24; + if (mystique->type >= MGA_1164SG) + ret = mystique->lfb_base >> 24; + else + ret = mystique->ctrl_base >> 24; break; case 0x14: ret = 0x00; - break; /*Linear frame buffer*/ + break; /*LFB for Millennium and Mystique, Control aperture for Mystique 220 and later*/ + case 0x15: + if (mystique->type >= MGA_1164SG) + ret = (mystique->ctrl_base >> 8) & 0xc0; + else + ret = 0x00; + break; case 0x16: - ret = (mystique->lfb_base >> 16) & 0x80; + if (mystique->type >= MGA_1164SG) + ret = mystique->ctrl_base >> 16; + else + ret = (mystique->lfb_base >> 16) & 0x80; break; case 0x17: - ret = mystique->lfb_base >> 24; + if (mystique->type >= MGA_1164SG) + ret = mystique->ctrl_base >> 24; + else + ret = mystique->lfb_base >> 24; break; case 0x18: @@ -5339,6 +6314,10 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) ret = mystique->pci_regs[0x33]; break; + case 0x34: + ret = (mystique->type == MGA_G100) ? 0xdc : 0x00; + break; + case 0x3c: ret = mystique->int_line; break; @@ -5374,6 +6353,59 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) ret = mystique_ctrl_read_b(addr, mystique); break; + case 0xdc: + ret = 0x01; + break; + + case 0xdd: + ret = 0xf0; + break; + + case 0xde: + ret = 0x21; + break; + + /* No support for turning off the video adapter yet. */ + case 0xe0: + ret = 0x0; + break; + + case 0xf0: + ret = 0x02; + break; + + case 0xf1: + ret = 0x00; + break; + + case 0xf2: + ret = 0x10; + break; + + case 0xf4: + ret = 0x1; + break; + + case 0xf5: + ret = 0x2; + break; + + case 0xf7: + ret = 0x1; + break; + + case 0xf8: + ret = mystique->pci_regs[0xf8] & 0x7; + break; + + case 0xf9: + ret = mystique->pci_regs[0xf9] & 0x3; + break; + + case 0xfb: + ret = mystique->pci_regs[0xfb]; + break; + default: break; } @@ -5401,25 +6433,61 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x11: - mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) + break; + else { + 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); + if (mystique->type >= MGA_1164SG) { + if (mystique->type >= MGA_2164W) + break; + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + } else { + 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); + if (mystique->type >= MGA_1164SG) { + if (mystique->type >= MGA_2164W) + mystique->lfb_base = val << 24; + else + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + + mystique_recalc_mapping(mystique); + } else { + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + } break; + case 0x15: + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + } + break; case 0x16: - mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + } else { + 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); + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + } else { + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + } break; case 0x1a: @@ -5437,9 +6505,11 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) if (!(mystique->pci_regs[0x43] & 0x40)) return; mystique->pci_regs[addr] = val; + if (addr == 0x30) + mystique->pci_regs[addr] &= 1; 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); + uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else mem_mapping_disable(&mystique->bios_rom.mapping); return; @@ -5462,12 +6532,12 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) 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); + uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else mem_mapping_disable(&mystique->bios_rom.mapping); } else - mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, 0x8000); + mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } break; @@ -5496,11 +6566,55 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) mystique_ctrl_write_b(addr, val, mystique); break; + case 0xf8: + mystique->pci_regs[0xf8] = val & 0x7; + break; + + case 0xf9: + mystique->pci_regs[0xf9] = val & 0x3; + break; + + case 0xfb: + mystique->pci_regs[0xfb] = val; + break; + default: break; } } +static uint32_t +mystique_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + mystique_t *mystique = (mystique_t*)svga->priv; + uint32_t ret = 0x00000000; + + if (svga->lut_map) { + if (bpp == 15) { + if (mystique->xgenctrl & (1 << 2)) + color &= 0x7FFF; +#if 0 + uint8_t b = getcolr(svga->pallook[(color & 0x1F) | (!!(color & 0x8000) >> 8)]); + uint8_t g = getcolg(svga->pallook[((color & 0x3E0) >> 5) | (!!(color & 0x8000) >> 8)]); + uint8_t r = getcolb(svga->pallook[((color & 0x7C00) >> 10) | (!!(color & 0x8000) >> 8)]); +#else + uint8_t b = getcolr(svga->pallook[color & 0x1f]); + uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 5]); + uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 10]); +#endif + ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b); + } else { + uint8_t b = getcolr(svga->pallook[color & 0x1f]); + uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 5]); + uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 11]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } + } else + ret = (bpp == 15) ? video_15to32[color] : video_16to32[color]; + + return ret; +} + static void * mystique_init(const device_t *info) { @@ -5513,12 +6627,19 @@ mystique_init(const device_t *info) if (mystique->type == MGA_2064W) romfn = ROM_MILLENNIUM; + else if (mystique->type == MGA_2164W) + romfn = ROM_MILLENNIUM_II; else if (mystique->type == MGA_1064SG) romfn = ROM_MYSTIQUE; + else if (mystique->type == MGA_G100) + romfn = ROM_G100; else romfn = ROM_MYSTIQUE_220; - rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (mystique->type == MGA_G100) + rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else + 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"); @@ -5528,8 +6649,8 @@ mystique_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); - if (mystique->type == MGA_2064W) { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_millennium); + if (mystique->type == MGA_2064W || mystique->type == MGA_2164W) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, (mystique->type == MGA_2164W) ? &timing_matrox_mystique : &timing_matrox_millennium); svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, mystique_recalctimings, mystique_in, mystique_out, @@ -5539,6 +6660,10 @@ mystique_init(const device_t *info) mystique->svga.ramdac = device_add(&tvp3026_ramdac_device); mystique->svga.clock_gen = mystique->svga.ramdac; mystique->svga.getclock = tvp3026_getclock; + mystique->svga.conv_16to32 = tvp3026_conv_16to32; + if (mystique->type == MGA_2164W) + mystique->svga.decode_mask = 0xffffff; + tvp3026_gpio(mystique_tvp3026_gpio_read, mystique_tvp3026_gpio_write, mystique, mystique->svga.ramdac); } else { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20, @@ -5548,6 +6673,8 @@ mystique_init(const device_t *info) NULL); mystique->svga.clock_gen = mystique; mystique->svga.getclock = mystique_getclock; + if (mystique->type == MGA_G100) + mystique->svga.decode_mask = 0xffffff; } io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); @@ -5560,7 +6687,7 @@ mystique_init(const device_t *info) 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); + NULL, 0, &mystique->svga); mem_mapping_disable(&mystique->lfb_mapping); mem_mapping_add(&mystique->iload_mapping, 0, 0, @@ -5572,7 +6699,7 @@ mystique_init(const device_t *info) 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); + pci_add_card((info->flags & DEVICE_AGP) ? PCI_ADD_AGP : 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]; @@ -5621,8 +6748,13 @@ mystique_init(const device_t *info) mystique->status = STATUS_ENDPRDMASTS; + mystique->softrap_status_read = 1; + mystique->svga.vsync_callback = mystique_vsync_callback; + if (mystique->type != MGA_2064W && mystique->type != MGA_2164W) + mystique->svga.conv_16to32 = mystique_conv_16to32; + 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)); @@ -5669,6 +6801,18 @@ mystique_220_available(void) return rom_present(ROM_MYSTIQUE_220); } +static int +millennium_ii_available(void) +{ + return rom_present(ROM_MILLENNIUM_II); +} + +static int +matrox_g100_available(void) +{ + return rom_present(ROM_G100); +} + static void mystique_speed_changed(void *priv) { @@ -5717,6 +6861,38 @@ static const device_config_t mystique_config[] = { // clang-format on }; +static const device_config_t millennium_ii_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "16 MB", + .value = 16 + }, + { + .description = "" + } + }, + .default_int = 8 + }, + { + .type = CONFIG_END + } + // clang-format on +}; + const device_t millennium_device = { .name = "Matrox Millennium", .internal_name = "millennium", @@ -5758,3 +6934,31 @@ const device_t mystique_220_device = { .force_redraw = mystique_force_redraw, .config = mystique_config }; + +const device_t millennium_ii_device = { + .name = "Matrox Millennium II", + .internal_name = "millennium_ii", + .flags = DEVICE_PCI, + .local = MGA_2164W, + .init = mystique_init, + .close = mystique_close, + .reset = NULL, + { .available = millennium_ii_available }, + .speed_changed = mystique_speed_changed, + .force_redraw = mystique_force_redraw, + .config = millennium_ii_config +}; + +const device_t productiva_g100_device = { + .name = "Matrox Productiva G100", + .internal_name = "productiva_g100", + .flags = DEVICE_AGP, + .local = MGA_G100, + .init = mystique_init, + .close = mystique_close, + .reset = NULL, + { .available = matrox_g100_available }, + .speed_changed = mystique_speed_changed, + .force_redraw = mystique_force_redraw, + .config = millennium_ii_config +}; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index ad197f302..30666e82c 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -51,7 +51,7 @@ typedef struct paradise_t { uint32_t read_bank[4], write_bank[4]; int interlace; - int check, check2; + int check; struct { uint8_t reg_block_ptr; @@ -79,6 +79,7 @@ paradise_in(uint16_t addr, void *priv) { paradise_t *paradise = (paradise_t *) priv; svga_t *svga = ¶dise->svga; + uint8_t temp = 0; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -109,13 +110,14 @@ paradise_in(uint16_t addr, void *priv) } switch (svga->gdcaddr) { case 0x0b: + temp = svga->gdcreg[0x0b]; if (paradise->type == WD90C30) { if (paradise->vram_mask == ((512 << 10) - 1)) { - svga->gdcreg[0x0b] |= 0xc0; - svga->gdcreg[0x0b] &= ~0x40; + temp &= ~0x40; + temp |= 0xc0; } } - return svga->gdcreg[0x0b]; + return temp; case 0x0f: return (svga->gdcreg[0x0f] & 0x17) | 0x80; @@ -184,9 +186,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) return; } + old = svga->gdcreg[svga->gdcaddr]; switch (svga->gdcaddr) { case 6: - if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { + if (old ^ (val & 0x0c)) { switch (val & 0x0c) { case 0x00: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -208,9 +211,9 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) default: break; } + svga->gdcreg[6] = val; + paradise_remap(paradise); } - svga->gdcreg[6] = val; - paradise_remap(paradise); return; case 9: @@ -222,6 +225,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) svga->gdcreg[0x0b] = val; paradise_remap(paradise); return; + case 0x0e: + svga->gdcreg[0x0e] = val; + svga_recalctimings(svga); + return; default: break; @@ -258,15 +265,6 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) } 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; } @@ -277,7 +275,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) void paradise_remap(paradise_t *paradise) { - const svga_t *svga = ¶dise->svga; + svga_t *svga = ¶dise->svga; paradise->check = 0; @@ -319,8 +317,6 @@ paradise_recalctimings(svga_t *svga) { const paradise_t *paradise = (paradise_t *) svga->priv; - svga->lowres = !(svga->gdcreg[0x0e] & 0x01); - if (paradise->type == WD90C30) { if (svga->crtc[0x3e] & 0x01) svga->vtotal |= 0x400; @@ -335,50 +331,42 @@ paradise_recalctimings(svga_t *svga) 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 + if (!svga->interlace && !(svga->gdcreg[0x0e] & 0x01) && (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 (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->interlace = 0; - } - 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; - 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 { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { svga->render = svga_render_8bpp_highres; } } + } else { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { + 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; - } + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } static void @@ -389,10 +377,15 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_write(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -427,7 +420,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) } } } - svga_write_linear(addr, val, svga); } static void @@ -438,10 +430,15 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_writew(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -476,7 +473,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) } } } - svga_writew_linear(addr, val, svga); } @@ -488,10 +484,14 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_read(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -526,7 +526,6 @@ paradise_read(uint32_t addr, void *priv) } } } - return svga_read_linear(addr, svga); } static uint16_t @@ -537,10 +536,14 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_readw(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -575,7 +578,6 @@ paradise_readw(uint32_t addr, void *priv) } } } - return svga_readw_linear(addr, svga); } @@ -641,7 +643,6 @@ paradise_init(const device_t *info, uint32_t memsize) 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'; diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index aa1517ddf..354c7e265 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2736,7 +2736,7 @@ pgc_standalone_init(const device_t *info) } const device_t pgc_device = { - .name = "PGC", + .name = "IBM PGC", .internal_name = "pgc", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index eef95a910..e82763d15 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -29,7 +29,8 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" +#define RTG_3105_BIOS_ROM_PATH "roms/video/rtg/RTG3105I.VBI" +#define RTG_3106_BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" typedef struct { const char *name; @@ -86,18 +87,18 @@ rtg_in(uint16_t addr, void *priv) 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) { + ret = svga->crtc[0x1e]; + ret &= ~3; if (dev->vram_size == 1024) ret = 2; else if (dev->vram_size == 512) ret = 1; else ret = 0; - return svga->crtc[0x1e] | ret; + return ret; } return svga->crtc[svga->crtcreg]; @@ -208,13 +209,12 @@ 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); + const rtg_t *dev = (rtg_t *) svga->priv; + 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; - /*Clock table not available, currently a guesswork*/ switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { case 0: @@ -258,50 +258,41 @@ rtg_recalctimings(svga_t *svga) 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->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else { + if (svga->hdisp == 1280) + svga->rowoffset >>= 1; - 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; + 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_8bpp_highres; - } - break; + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: + if (svga->crtc[0x19] & 2) { + if (svga->hdisp == 1280) + svga->hdisp >>= 1; + else if (dev->type == 2) + svga->rowoffset <<= 1; - default: - break; + svga->render = svga_render_8bpp_highres; + } else + svga->render = svga_render_8bpp_lowres; + break; + + default: + break; + } } } } @@ -316,13 +307,24 @@ rtg_init(const device_t *info) memset(dev, 0x00, sizeof(rtg_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; + fn = NULL; switch (dev->type) { - case 2: /* ISA RTG3106 */ - dev->vram_size = device_get_config_int("memory") << 10; + case 1: /* ISA RTG3105 */ + fn = RTG_3105_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, + svga_init(info, &dev->svga, dev, dev->vram_size << 10, + rtg_recalctimings, rtg_in, rtg_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev); + break; + case 2: /* ISA RTG3106 */ + fn = RTG_3106_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); + svga_init(info, &dev->svga, dev, dev->vram_size << 10, rtg_recalctimings, rtg_in, rtg_out, NULL, NULL); io_sethandler(0x03c0, 32, @@ -371,12 +373,45 @@ rtg_force_redraw(void *priv) } static int -rtg_available(void) +rtg3105_available(void) { - return rom_present(BIOS_ROM_PATH); + return rom_present(RTG_3105_BIOS_ROM_PATH); } -static const device_config_t rtg_config[] = { +static int +rtg3106_available(void) +{ + return rom_present(RTG_3106_BIOS_ROM_PATH); +} + +static const device_config_t rtg3105_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 +}; + +static const device_config_t rtg3106_config[] = { // clang-format off { .name = "memory", @@ -407,16 +442,30 @@ static const device_config_t rtg_config[] = { // clang-format on }; +const device_t realtek_rtg3105_device = { + .name = "Realtek RTG3105 (ISA)", + .internal_name = "rtg3105", + .flags = DEVICE_ISA, + .local = 1, + .init = rtg_init, + .close = rtg_close, + .reset = NULL, + { .available = rtg3105_available }, + .speed_changed = rtg_speed_changed, + .force_redraw = rtg_force_redraw, + .config = rtg3105_config +}; + const device_t realtek_rtg3106_device = { .name = "Realtek RTG3106 (ISA)", .internal_name = "rtg3106", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA, .local = 2, .init = rtg_init, .close = rtg_close, .reset = NULL, - { .available = rtg_available }, + { .available = rtg3106_available }, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, - .config = rtg_config + .config = rtg3106_config }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index f35f729da..a971c2f65 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -16,6 +16,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> @@ -61,7 +63,9 @@ #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_STB_POWERGRAPH_64_VIDEO "roms/video/s3/VBIOS.BIN" #define ROM_PHOENIX_TRIO64VPLUS "roms/video/s3/64V1506.ROM" +#define ROM_CARDEX_TRIO64VPLUS "roms/video/s3/S3T64VP.VBI" #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" @@ -77,6 +81,7 @@ enum { S3_PARADISE_BAHAMAS64, S3_DIAMOND_STEALTH64_964, S3_PHOENIX_TRIO32, + S3_PHOENIX_TRIO32_ONBOARD, S3_PHOENIX_TRIO64, S3_PHOENIX_TRIO64_ONBOARD, S3_PHOENIX_VISION864, @@ -90,8 +95,10 @@ enum { S3_AMI_86C924, S3_TRIO64V2_DX, S3_TRIO64V2_DX_ONBOARD, + S3_STB_POWERGRAPH_64_VIDEO, S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, + S3_CARDEX_TRIO64VPLUS, S3_DIAMOND_STEALTH_SE, S3_DIAMOND_STEALTH_VRAM, S3_ELSAWIN2KPROX_964, @@ -146,6 +153,7 @@ static video_timings_t timing_s3_trio32_vlb = { .type = VIDEO_BUS, .write_b = 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_trio64vp_cardex_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 19, .read_w = 19, .read_l = 30 }; enum { VRAM_4MB = 0, @@ -265,6 +273,18 @@ typedef struct s3_t { int ssv_len; uint8_t ssv_dir; uint8_t ssv_draw; + uint8_t dat_buf_16bit; + uint8_t frgd_color_actual[2]; + uint8_t bkgd_color_actual[2]; + uint8_t wrt_mask_actual[2]; + uint8_t rd_mask_actual[2]; + uint8_t *pix_trans_ptr; + int pix_trans_ptr_cnt; + int pix_trans_x_count; + int pix_trans_x_count2; + int color_16bit_check; + int color_16bit_check_rectfill; + uint16_t minus, srcminus; /*For non-threaded FIFO*/ int setup_fifo_slot; @@ -362,6 +382,8 @@ typedef struct s3_t { void *i2c, *ddc; int vram; + + void (*accel_start)(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); } s3_t; #define INT_VSY (1 << 0) @@ -396,6 +418,24 @@ 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); +#ifdef ENABLE_S3_LOG +int s3_do_log = ENABLE_S3_LOG; + +static void +s3_log(const char *fmt, ...) +{ + va_list ap; + + if (s3_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define s3_log(fmt, ...) +#endif + /*Remap address for chain-4/doubleword style layout. These will stay for convenience.*/ static __inline uint32_t @@ -472,7 +512,7 @@ s3_update_irqs(s3_t *s3) } } -void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); +void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); 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); @@ -493,7 +533,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); } #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->accel.minus)) & s3->vram_mask]; #define READ_PIXTRANS_BYTE_MM \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; @@ -503,7 +543,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ 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)]; \ + temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx - s3->accel.minus)) & (s3->vram_mask >> 1)]; \ } #define READ_PIXTRANS_LONG \ @@ -564,20 +604,33 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) const svga_t *svga = &s3->svga; if (s3->accel.cmd & 0x100) { + s3_log("S3 PIXTRANS_W write: cmd=%03x, pixelcntl=%02x, frgdmix=%02x, bkgdmix=%02x, " + "curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], + s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val); 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); + s3->accel_start(8, 1, val | (val << 16), 0, s3); } else - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + 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); + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Word: CPU data CMD=%04x, byte write=%02x, " + "cnt=%d, check=%d.\n", s3->accel.cmd, val & 0xff, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val & 0xff; + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count + 1] = val >> 8; + s3->accel.pix_trans_x_count += 2; + } + } + break; + } + s3->accel_start(1, 1, 0xffffffff, val | (val << 16), s3); } break; case 0x200: @@ -585,11 +638,54 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) 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); + s3->accel_start(16, 1, val | (val << 16), 0, s3); } else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } else { - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, " + "totalptrcnt=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check, + s3->accel.pix_trans_ptr_cnt); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val & 0xff; + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count + 1] = val >> 8; + s3->accel.pix_trans_x_count += 2; + s3->accel.pix_trans_x_count2 = s3->accel.pix_trans_x_count; + } + } else { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Word: CPU data CMD=%04x, word write=%04x, cnt=%d, check=%d, " + "totalptrcnt=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check, + s3->accel.pix_trans_ptr_cnt); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val & 0xff; + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2 + 1] = val >> 8; + s3->accel.pix_trans_x_count += 2; + } + if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) { + for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) { + s3_log("Transferring write count=%d, bytes=%08x.\n", i, + s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8) | + (s3->accel.pix_trans_ptr[i + 2] << 16) | + (s3->accel.pix_trans_ptr[i + 3] << 24)); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8), s3); + } + + s3->accel.pix_trans_x_count2 = 0; + s3->accel.color_16bit_check_rectfill = 0; + if (s3->accel.pix_trans_ptr != NULL) { + free(s3->accel.pix_trans_ptr); + s3->accel.pix_trans_ptr = NULL; + } + } + } + break; + } + s3->accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } break; case 0x400: @@ -598,21 +694,21 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) 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); + s3->accel_start(32, 1, val | (val << 16), 0, s3); } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + s3->accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + 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); + s3->accel_start(16, 1, val | (val << 16), 0, s3); } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + s3->accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } else - s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + s3->accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } break; case 0x600: @@ -621,8 +717,8 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) 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); + s3->accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3->accel_start(8, 1, val & 0xff, 0, s3); } } } @@ -644,15 +740,15 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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); + 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); + 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); + s3->accel_start(1, 1, 0xffffffff, val, s3); + s3->accel_start(1, 1, 0xffffffff, val >> 16, s3); } break; case 0x200: @@ -660,15 +756,15 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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); + 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); + 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); + s3->accel_start(2, 1, 0xffffffff, val, s3); + s3->accel_start(2, 1, 0xffffffff, val >> 16, s3); } break; case 0x400: @@ -676,11 +772,11 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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); + s3->accel_start(32, 1, val, 0, s3); } else - s3_accel_start(4, 1, 0xffffffff, val, s3); + s3->accel_start(4, 1, 0xffffffff, val, s3); } else - s3_accel_start(4, 1, 0xffffffff, val, s3); + 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) { @@ -688,10 +784,10 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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); + 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); } } } @@ -851,7 +947,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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_start(-1, 0, 0xffffffff, 0, s3); break; case 0x994a: @@ -887,166 +983,216 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (val << 8); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + + if (s3->accel.color_16bit_check) + s3->accel.bkgd_color_actual[1] = s3->accel.bkgd_color & 0xff; + else + s3->accel.bkgd_color_actual[0] = s3->accel.bkgd_color & 0xff; 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); + 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->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)) + 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 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); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); else - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (val << 8); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + + if (s3->accel.color_16bit_check) + s3->accel.frgd_color_actual[1] = s3->accel.frgd_color & 0xff; + else + s3->accel.frgd_color_actual[0] = s3->accel.frgd_color & 0xff; 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); + 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->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)) + 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 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); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (val << 8); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + + if (s3->accel.color_16bit_check) + s3->accel.wrt_mask_actual[1] = s3->accel.wrt_mask & 0xff; + else + s3->accel.wrt_mask_actual[0] = s3->accel.wrt_mask & 0xff; 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); + 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->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)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 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); + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); else - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffff00ff) | (val << 8); + 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->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); + 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->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)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 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); + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); else - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); else - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffff00ff) | (val << 8); + 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->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); + 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->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)) + 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 0xb548: @@ -1080,34 +1226,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffff00ff) | (val << 8); + 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->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); + 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->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)) + 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: @@ -1128,34 +1281,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffffff00) | val; + 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 & 0x00ffffff) | (val << 24); + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffff00ff) | (val << 8); + 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->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); + 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->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)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xe148: @@ -1169,14 +1329,50 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); + 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); + 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); + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val; + s3->accel.pix_trans_x_count++; + s3->accel.pix_trans_x_count2 = s3->accel.pix_trans_x_count; + } + } else { + if (s3->accel.pix_trans_x_count2 < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count2, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val; + s3->accel.pix_trans_x_count2++; + } + s3_log("WriteCNT=%d, TotalCNT=%d.\n", s3->accel.pix_trans_x_count2, + s3->accel.pix_trans_ptr_cnt); + if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) { + for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) { + s3_log("Transferring write count=%d, bytes=%04x.\n", i, + s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8)); + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8), s3); + } + + s3->accel.pix_trans_x_count2 = 0; + s3->accel.color_16bit_check_rectfill = 0; + if (s3->accel.pix_trans_ptr != NULL) { + free(s3->accel.pix_trans_ptr); + s3->accel.pix_trans_ptr = NULL; + } + } + } + break; + } + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } break; @@ -1192,63 +1388,67 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[1] = val; if (s3->accel.cmd & 0x100) { + s3_log("S3 PIXTRANS_B write (E2E9): cmd=%03x, pixelcntl=%02x, frgdmix=%02x, " + "bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], + s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val); 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); + 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); - } + 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.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); + 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); + 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); - } + 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); - } + 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); + 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); + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_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); + s3->accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } } } @@ -1276,58 +1476,49 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); + 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); + 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); + 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); + 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)); + 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->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); + 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); + 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->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); + 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); + 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); + 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); + 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); } } } @@ -1374,11 +1565,10 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (port == 0xb2e8 || port == 0xb148) { + if (port == 0xb2e8 || port == 0xb148) s3->accel.b2e8_pix = 1; - } else { + else s3->accel.b2e8_pix = 0; - } s3_accel_out_pixtrans_l(s3, val); } @@ -1549,11 +1739,11 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) 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); + 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); + 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); + s3->accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { switch (addr & 0x1ffff) { @@ -1630,7 +1820,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } } else { if (addr & 0x8000) { - if ((addr == 0xe2e8) || (addr == 0xe2e9)) { + if ((addr == 0xe2e8) || (addr == 0xe2e9) || (addr == 0xe2ea) || (addr == 0xe2eb)) { if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) goto mmio_byte_write; else @@ -1643,19 +1833,19 @@ mmio_byte_write: 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); + 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); + 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); + 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); + 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); + 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); + s3->accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } } @@ -1906,7 +2096,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) } else { if (addr & 0x8000) { if (addr == 0xe2e8) { - if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI) + if ((s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) s3_accel_out_pixtrans_l(s3, val); else { s3_accel_write_fifo(s3, addr, val); @@ -1938,8 +2128,8 @@ s3_vblank_start(svga_t *svga) 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) + if ((svga->bpp == 8) && (((svga->gdcreg[5] & 0x60) == 0x20) || (svga->crtc[0x3a] & 0x10)) && (svga->crtc[0x45] & 0x10)) { + if (svga->crtc[0x3a] & 0x10) 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; @@ -1981,7 +2171,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if ((s3->card_type != S3_MIROCRYSTAL10SD_805) && (s3->card_type != S3_MIROCRYSTAL8S_805)) { if (!(svga->crtc[0x45] & 0x04)) { shift = 2; width = 8; @@ -1995,8 +2185,13 @@ s3_hwcursor_draw(svga_t *svga, int displine) break; case 24: - fg = s3->hwc_fg_col; - bg = s3->hwc_bg_col; + if (s3->chip <= S3_86C805) { + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; + } else { + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + } break; case 32: @@ -2516,7 +2711,6 @@ s3_out(uint16_t addr, uint8_t val, void *priv) s3_t *s3 = (s3_t *) priv; svga_t *svga = &s3->svga; uint8_t old; - uint8_t mask; int rs2; int rs3; @@ -2576,26 +2770,21 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x3C7: case 0x3C8: case 0x3C9: - if ((svga->crtc[0x55] & 0x03) == 0x00) - rs2 = !!(svga->crtc[0x43] & 0x02); - else - rs2 = (svga->crtc[0x55] & 0x01); + rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); 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; + rs3 = !!(svga->crtc[0x55] & 0x02); 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)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C924)) && + ((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) { + else if (s3->chip == S3_86C911) { 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); @@ -2632,45 +2821,17 @@ s3_out(uint16_t addr, uint8_t val, void *priv) 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; + if (s3->bpp == 3) { + if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/ + s3->accel.multifunc[0xe] &= ~0x10; + } break; case 0x5c: @@ -2753,6 +2914,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.x >>= 1; } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) svga->hwcursor.x /= 3; + else if ((s3->chip <= S3_86C805) && s3->color_16bit) + svga->hwcursor.x >>= 1; break; case 0x4a: @@ -2799,7 +2962,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x55: if (s3->chip == S3_86C928) { - if ((val & 0x08) || ((val & 0x20) == 0x20)) { + if (val & 0x28) { svga->hwcursor_draw = NULL; svga->dac_hwcursor_draw = bt48x_hwcursor_draw; } else { @@ -2818,6 +2981,21 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x43: if (s3->chip < S3_VISION964) { + if (s3->chip <= S3_86C805) { + s3->color_16bit = !!(val & 8); + if (s3->color_16bit) { + s3->width = 1024; + } else { + if (s3->chip <= S3_86C924) + s3->width = 1024; + else { + if (s3->accel.advfunc_cntl & 4) + s3->width = 1024; + else + s3->width = 640; + } + } + } s3_io_remove_alt(s3); s3->translate = !!(val & 0x10); s3_io_set_alt(s3); @@ -2903,7 +3081,9 @@ s3_in(uint16_t addr, void *priv) 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)) + if (((s3->card_type == S3_STB_POWERGRAPH_64_VIDEO) || + (s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) || + (s3->card_type == S3_CARDEX_TRIO64VPLUS)) && (svga->seqaddr == 0x17)) svga->seqregs[svga->seqaddr] ^= 0x01; return temp; } @@ -2917,16 +3097,21 @@ s3_in(uint16_t addr, void *priv) 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); + if (s3->chip == S3_86C928) + rs3 = !!(svga->crtc[0x55] & 0x28) || !!(svga->crtc[0x45] & 0x20) || !!(svga->crtc[0x55] & 0x02); /*Quite insane but Win95's S3 driver wants it set at all costs for 8bpp+ mode*/ + else + rs3 = !!(svga->crtc[0x55] & 0x02); + temp = bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + return temp; } 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)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C924)) && + ((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) + else if (s3->chip == S3_86C911) 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); @@ -2943,8 +3128,15 @@ s3_in(uint16_t addr, void *priv) 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 0x2f: switch (s3->chip) { /*Revision level*/ + case S3_TRIO64V: + return 0x40; + case S3_TRIO64V2: + return 0x16; /*Confirmed on an onboard 64V2/DX*/ + default: + return 0x00; + } + break; case 0x30: return s3->id; /*Chip ID*/ case 0x31: @@ -2953,7 +3145,7 @@ s3_in(uint16_t addr, void *priv) return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); case 0x45: s3->hwc_col_stack_pos = 0; - break; + return svga->crtc[0x45]; case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); case 0x5c: /* General Output Port Register */ @@ -2984,6 +3176,7 @@ s3_in(uint16_t addr, void *priv) } } else return svga->crtc[0x6b]; + break; case 0x6c: if (s3->chip != S3_TRIO64V2) { if (svga->crtc[0x53] & 0x08) { @@ -2992,6 +3185,7 @@ s3_in(uint16_t addr, void *priv) return (svga->crtc[0x5a] & 0x80); } else return svga->crtc[0x6c]; + break; default: break; @@ -3009,24 +3203,28 @@ s3_recalctimings(svga_t *svga) { s3_t *s3 = (s3_t *) svga->priv; int clk_sel = (svga->miscout >> 2) & 3; + uint8_t mask = 0xc0; - 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; - } + if (svga->crtc[0x33] & 0x20) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } else { + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } } + svga->hdisp = svga->hdisp_old; svga->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { - svga->hdisp = svga->hdisp_old; + if (s3->chip >= S3_86C928) { 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); + svga->hdisp |= (0x100 * svga->dots_per_clock); } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -3034,6 +3232,8 @@ s3_recalctimings(svga_t *svga) svga->dispend |= 0x400; if (svga->crtc[0x5e] & 0x04) svga->vblankstart |= 0x400; + else + svga->vblankstart = svga->dispend; if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; if (svga->crtc[0x5e] & 0x40) @@ -3044,24 +3244,27 @@ s3_recalctimings(svga_t *svga) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - } + } 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 + else { bt48x_recalctimings(svga->ramdac, svga); + svga->interlace |= (!!(svga->crtc[0x42] & 0x20)); + } } else if (s3->chip == S3_VISION968) { - if (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968) + 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) + 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); @@ -3077,13 +3280,71 @@ s3_recalctimings(svga_t *svga) break; } - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); + if (s3->chip != S3_86C801) + mask |= 0x01; + switch (svga->crtc[0x50] & mask) { + case 0x00: + if (s3->color_16bit) + s3->width = 1024; + else + 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; + } + + if (svga->crtc[0x33] & 0x20) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + + if (s3->chip >= S3_VISION964) + svga->hblank_end_mask = 0x7f; + } else if (s3->chip >= S3_86C801) { + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; + + if (s3->chip >= S3_VISION964) { + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; + } + } + +#ifdef OLD_CODE_REFERENCE 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*/ + if (svga->crtc[0x31] & 2) s3->width = 2048; else { if (s3->card_type == S3_MIROCRYSTAL10SD_805) { @@ -3104,24 +3365,117 @@ s3_recalctimings(svga_t *svga) s3->width = 1024; } } +#endif - 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)) { + if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { + svga->vram_display_mask = s3->vram_mask; + s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " + "attr=%02x.\n", svga->bpp, s3->width, svga->crtc[0x50], + svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, + svga->attrregs[0x10] & 0x40); switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; + switch (s3->chip) { + case S3_86C928: + switch (s3->card_type) { + case S3_METHEUS_86C928: + switch (s3->width) { + case 1280: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + case 2048: /*Account for the 1280x1024 resolution*/ + switch (svga->hdisp) { + case 320: + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + break; + case 640: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_86C928PCI: + switch (s3->card_type) { + case S3_SPEA_MERCURY_LITE_PCI: + switch (s3->width) { + case 640: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION964: + switch (s3->card_type) { + case S3_ELSAWIN2KPROX_964: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION968: + switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + case S3_ELSAWIN2KPROX: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + default: + break; + } + break; + + default: + break; + } + break; + + default: + break; + } +#ifdef OLD_CODE_REFERENCE if (s3->chip != S3_VISION868) { if (s3->chip == S3_86C928) { if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) { @@ -3139,57 +3493,179 @@ s3_recalctimings(svga_t *svga) } 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; - } } +#endif break; case 15: svga->render = svga_render_15bpp_highres; + switch (s3->chip) { + case S3_86C911: + case S3_86C924: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + case S3_86C801: + switch (s3->card_type) { + case S3_PHOENIX_86C801: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } + break; + case S3_86C805: + switch (s3->card_type) { + case S3_MIROCRYSTAL8S_805: + case S3_MIROCRYSTAL10SD_805: + case S3_PHOENIX_86C805: + case S3_86C805_ONBOARD: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + case S3_SPEA_MIRAGE_86C805: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + switch (s3->width) { + case 800: + case 1024: + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_86C928: + switch (s3->card_type) { + case S3_METHEUS_86C928: + if (!s3->color_16bit) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + switch (svga->hdisp) { /*This might be a driver issue*/ + case 800: + s3->width = 1024; + break; + case 1280: + s3->width = 2048; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_86C928PCI: + switch (s3->card_type) { + case S3_SPEA_MERCURY_LITE_PCI: + switch (s3->width) { + case 640: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION864: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + case S3_VISION964: + switch (s3->card_type) { + case S3_ELSAWIN2KPROX_964: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION868: + switch (s3->card_type) { + case S3_PHOENIX_VISION868: + case S3_NUMBER9_9FX_531: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } + break; + case S3_VISION968: + switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + /* TODO: Is this still needed? */ + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + + case S3_ELSAWIN2KPROX: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + default: + break; + } + break; + + case S3_TRIO64: + case S3_TRIO32: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } +#ifdef OLD_CODE_REFERENCE 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; @@ -3211,9 +3687,173 @@ s3_recalctimings(svga_t *svga) 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; +#endif break; case 16: svga->render = svga_render_16bpp_highres; + switch (s3->chip) { + case S3_86C911: + case S3_86C924: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + case S3_86C801: + switch (s3->card_type) { + case S3_PHOENIX_86C801: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } + break; + case S3_86C805: + switch (s3->card_type) { + case S3_MIROCRYSTAL8S_805: + case S3_MIROCRYSTAL10SD_805: + case S3_PHOENIX_86C805: + case S3_86C805_ONBOARD: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + case S3_SPEA_MIRAGE_86C805: + svga->hdisp >>= 1; + switch (s3->width) { + case 800: + case 1024: + if (svga->hdisp == 400) { + /*SPEA specific drivers + its VBE RAM BIOS...*/ + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_86C928: + switch (s3->card_type) { + case S3_METHEUS_86C928: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + switch (svga->hdisp) { /*This might be a driver issue*/ + case 800: + s3->width = 1024; + break; + case 1280: + s3->width = 2048; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_86C928PCI: + switch (s3->card_type) { + case S3_SPEA_MERCURY_LITE_PCI: + switch (s3->width) { + case 640: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION864: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + case S3_VISION868: + switch (s3->card_type) { + case S3_PHOENIX_VISION868: + case S3_NUMBER9_9FX_531: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } + break; + case S3_VISION964: + switch (s3->card_type) { + case S3_ELSAWIN2KPROX_964: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + + default: + break; + } + break; + case S3_VISION968: + switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + /* TODO: Is this still needed? */ + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + + case S3_ELSAWIN2KPROX: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + default: + break; + } + break; + + case S3_TRIO64: + case S3_TRIO32: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + + default: + break; + } + +#ifdef OLD_CODE_REFERENCE if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { if (s3->width == 1280 || s3->width == 1600) svga->hdisp <<= 1; @@ -3232,7 +3872,7 @@ s3_recalctimings(svga_t *svga) 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)) + if (svga->hdisp == (1408 << 1)) svga->hdisp >>= 1; else svga->hdisp = s3->width; @@ -3240,9 +3880,74 @@ s3_recalctimings(svga_t *svga) 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; +#endif break; case 24: svga->render = svga_render_24bpp_highres; + switch (s3->chip) { + case S3_86C924: + switch (s3->card_type) { + case S3_AMI_86C924: + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + /* TODO: Is this still needed? */ + if (svga->hdisp == 645) + svga->hdisp -= 5; + break; + default: + break; + } + break; + case S3_86C801: + switch (s3->card_type) { + case S3_PHOENIX_86C801: + case S3_SPEA_MIRAGE_86C801: + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + break; + default: + break; + } + break; + case S3_86C805: + switch (s3->card_type) { + case S3_MIROCRYSTAL8S_805: + case S3_MIROCRYSTAL10SD_805: + case S3_PHOENIX_86C805: + case S3_SPEA_MIRAGE_86C805: + case S3_86C805_ONBOARD: + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + break; + default: + break; + } + break; + case S3_86C928PCI: + switch (s3->card_type) { + case S3_SPEA_MERCURY_LITE_PCI: + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + break; + default: + break; + } + break; + case S3_VISION864: + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + break; + + case S3_TRIO64: + case S3_TRIO32: + svga->hdisp /= 3; + svga->dots_per_clock /= 3; + break; + + default: + break; + } +#ifdef OLD_CODE_REFERENCE if (s3->chip != S3_VISION968) { if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) svga->hdisp /= 3; @@ -3250,7 +3955,7 @@ s3_recalctimings(svga_t *svga) svga->hdisp = (svga->hdisp * 2) / 3; if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (s3->width == 2048) + if (s3->width == 2048) { switch (svga->dispend) { case 480: svga->hdisp = 640; @@ -3259,14 +3964,96 @@ s3_recalctimings(svga_t *svga) default: break; } + } + } else if (s3->chip == S3_86C924) { + if (svga->dispend == 480) + svga->hdisp = 640; } } else { - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) + 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; } +#endif break; case 32: svga->render = svga_render_32bpp_highres; + switch (s3->chip) { + case S3_VISION868: + switch (s3->card_type) { + case S3_PHOENIX_VISION868: + case S3_NUMBER9_9FX_531: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + default: + break; + } + break; + case S3_VISION964: + switch (s3->card_type) { + case S3_MIROCRYSTAL20SV_964: + switch (s3->width) { + case 800: + case 1024: + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + break; + default: + break; + } + break; + case S3_ELSAWIN2KPROX_964: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + default: + break; + } + break; + case S3_VISION968: + switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + /* TODO: Is this still needed? */ + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; + + case S3_ELSAWIN2KPROX: + switch (s3->width) { + case 1280: + case 1600: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + default: + break; + } + break; + default: + break; + } + break; + + default: + break; + } +#ifdef OLD_CODE_REFERENCE 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; @@ -3307,47 +4094,57 @@ s3_recalctimings(svga_t *svga) } } } +#endif break; default: break; } } else { - if (!svga->scrblank && svga->attr_palette_enable) { + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && 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->crtc[0x31] & 0x08) { + svga->vram_display_mask = s3->vram_mask; 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; + /*Enhanced 4bpp mode, just like the 8bpp mode per the spec. */ + svga->render = svga_render_8bpp_highres; + svga->rowoffset <<= 1; } } - } else { - if (s3->chip <= S3_86C924) - s3->width = 1024; } } } + + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + svga->hoverride = 1; + else + svga->hoverride = 0; } static void s3_trio64v_recalctimings(svga_t *svga) { - const s3_t *s3 = (s3_t *) svga->priv; + 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; - } + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + + if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } + 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); + svga->hdisp |= 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -3363,6 +4160,53 @@ s3_trio64v_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); + switch (svga->crtc[0x50] & 0xc1) { + case 0x00: + s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; + break; + case 0x01: + s3->width = 1152; + break; + case 0x40: + s3->width = 640; + break; + case 0x80: + s3->width = (s3->accel.advfunc_cntl & 4) ? 1600 : 800; + break; + case 0x81: + s3->width = 1600; + break; + case 0xc0: + s3->width = 1280; + break; + + default: + break; + } + + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3)*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; + + /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? + The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, + and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, + and Vision968. */ + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; + } + if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ { svga->ma_latch |= (s3->ma_ext << 16); @@ -3373,9 +4217,10 @@ s3_trio64v_recalctimings(svga_t *svga) if (!svga->rowoffset) svga->rowoffset = 256; - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { + if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { + svga->vram_display_mask = s3->vram_mask; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3383,14 +4228,17 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; + svga->dots_per_clock /= 3; break; case 32: svga->render = svga_render_32bpp_highres; @@ -3399,7 +4247,9 @@ s3_trio64v_recalctimings(svga_t *svga) default: break; } - } + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + } else /*Streams mode*/ { if (s3->streams.buffer_ctrl & 1) @@ -3424,16 +4274,17 @@ s3_trio64v_recalctimings(svga_t *svga) svga->overlay.v_acc = s3->streams.dda_vert_accumulator; svga->rowoffset = s3->streams.pri_stride >> 3; + svga->vram_display_mask = s3->vram_mask; 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->multiplier = 0.5; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; + svga->multiplier = 0.5; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -3447,6 +4298,8 @@ s3_trio64v_recalctimings(svga_t *svga) break; } } + + svga->hoverride = 1; } static void @@ -3541,11 +4394,10 @@ s3_updatemapping(s3_t *s3) svga->banked_mask = 0xffff; } } else { - if (s3->chip >= S3_TRIO64V) { + if (s3->chip >= S3_TRIO64V) s3->linear_base &= 0xfc000000; - } else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { + 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); } @@ -3639,8 +4491,7 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv) svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); } - if (s3->chip > S3_86C924) - s3_updatemapping(s3); + s3_updatemapping(s3); break; default: @@ -3801,6 +4652,7 @@ s3_accel_in(uint16_t port, void *priv) temp |= 0x02; /*Hardware busy*/ else temp |= 0x04; /*FIFO empty*/ + s3->force_busy = 0; if (s3->chip >= S3_VISION964) { @@ -3813,9 +4665,30 @@ s3_accel_in(uint16_t port, void *priv) s3->data_available = 0; } } else { - if (s3->force_busy) { + if (s3->force_busy) temp |= 0x02; /*Hardware busy*/ + else { + switch (s3->accel.cmd >> 13) { /*Some drivers may not set FIFO on but may still turn on FIFO empty bits!*/ + case 0: + if (!s3->accel.ssv_len) + temp |= 0x04; + break; + case 1: + if (!s3->accel.sy) + temp |= 0x04; + break; + case 2: + case 6: + case 7: + if (s3->accel.sy < 0) + temp |= 0x04; + break; + + default: + break; + } } + s3->force_busy = 0; if (s3->data_available) { temp |= 0x01; /*Read Data available*/ @@ -4329,21 +5202,20 @@ s3_accel_in(uint16_t port, void *priv) 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); + 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); + 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); + 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); + 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); - } + 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: @@ -4362,30 +5234,30 @@ s3_accel_in(uint16_t port, void *priv) 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } break; @@ -4412,20 +5284,20 @@ s3_accel_in(uint16_t port, void *priv) 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); + 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); + 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); + 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); + 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); + 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); + 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: @@ -4471,28 +5343,22 @@ s3_accel_in_w(uint16_t port, void *priv) 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); - } - } + s3->accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) temp = (temp >> 8) | (temp << 8); - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + s3->accel_start(16, 1, temp | (temp << 16), 0, s3); } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else { - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } break; @@ -4529,15 +5395,15 @@ s3_accel_in_l(UNUSED(uint16_t port), void *priv) 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); + 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); + 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); + s3->accel_start(1, 1, 0xffffffff, temp, s3); + s3->accel_start(1, 1, 0xffffffff, temp >> 16, s3); } break; case 0x200: @@ -4545,15 +5411,15 @@ s3_accel_in_l(UNUSED(uint16_t port), void *priv) 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); + 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); + 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); + s3->accel_start(2, 1, 0xffffffff, temp, s3); + s3->accel_start(2, 1, 0xffffffff, temp >> 16, s3); } break; @@ -4700,20 +5566,20 @@ s3_accel_read(uint32_t addr, void *priv) 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); + 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); + 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); + 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); + 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); + 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); + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; default: @@ -4764,20 +5630,20 @@ s3_accel_read_w(uint32_t addr, void *priv) 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); + s3->accel_start(8, 1, temp | (temp << 16), 0, s3); else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + s3->accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + 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); + s3->accel_start(16, 1, temp | (temp << 16), 0, s3); else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + s3->accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; default: @@ -4938,29 +5804,29 @@ s3_accel_read_l(uint32_t addr, void *priv) 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); + 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); + 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); + 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); + 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); + 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); + s3->accel_start(2, 1, 0xffffffff, temp, s3); + s3->accel_start(2, 1, 0xffffffff, temp >> 16, s3); } break; @@ -5015,11 +5881,13 @@ polygon_setup(s3_t *s3) #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) \ + else if ((s3->bpp == 1) || (s3->color_16bit && (svga->bpp < 24))) \ dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ - else if (s3->bpp == 2) \ + else if (s3->bpp == 2) \ dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ - else \ + else if (s3->color_16bit && (svga->bpp == 24)) { \ + dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ + } else \ dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; #define MIX_READ \ @@ -5080,7 +5948,7 @@ polygon_setup(s3_t *s3) { \ old_dest_dat = dest_dat; \ MIX_READ \ - dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); \ } #define ROPMIX_READ(D, P, S) \ @@ -5868,12 +6736,15 @@ polygon_setup(s3_t *s3) if ((s3->bpp == 0) && !s3->color_16bit) { \ svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else if ((s3->bpp == 1) || s3->color_16bit) { \ + } else if ((s3->bpp == 1) || (s3->color_16bit && (svga->bpp < 24))) { \ 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) { \ + } 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 if (s3->color_16bit && (svga->bpp == 24)) { \ + 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 { \ 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; \ @@ -6261,30 +7132,13 @@ s3_visionx68_video_engine_op(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) +s3_911_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv) { - 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); -} - -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; + s3_t *s3 = (s3_t *)priv; + 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; @@ -6292,93 +7146,34 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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; + uint32_t mix_mask = (s3->accel.cmd & 0x200) ? 0x8000 : 0x80; 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; + uint32_t wrt_mask = s3->accel.wrt_mask; + uint32_t frgd_color = s3->accel.frgd_color; + uint32_t bkgd_color = s3->accel.bkgd_color; 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->color_16bit) { + if (count > 1) + 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) + if (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; - } + else + rd_mask &= 0xff; /*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) @@ -6387,16 +7182,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.cmd & 8) /*Radial*/ - { + 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; + src_dat = bkgd_color; break; case 1: - src_dat = s3->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -6409,14 +7203,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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); + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - MIX + MIX - if (s3->accel.ssv_draw) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } + if (s3->accel.ssv_draw) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -6474,6 +7266,832 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } 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 & 0x7ff; + + if (s3->color_16bit && (svga->bpp < 24)) { + if (s3->accel.wrt_mask != 0xffff) { + if (s3->accel.cur_x & 0x400) { + s3->accel.color_16bit_check = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.color_16bit_check = 1; + s3->accel.minus = 0; + } + } else { + if (s3->accel.cur_x & 0x400) + s3->accel.color_16bit_check = 1; + else + s3->accel.color_16bit_check = 0; + + s3->accel.minus = 0; + } + } else { + s3->accel.color_16bit_check = 0; + s3->accel.minus = 0; + } + + 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*/ + if (s3->color_16bit && (svga->bpp < 24)) { + if (s3->accel.color_16bit_check) + return; + if (s3->accel.wrt_mask != 0xffff) + wrt_mask = (s3->accel.wrt_mask_actual[0] | (s3->accel.wrt_mask_actual[1] << 8)); + } + + 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 = bkgd_color; + if (s3->color_16bit && (svga->bpp < 24)) + src_dat = s3->accel.bkgd_color_actual[0] | (s3->accel.bkgd_color_actual[1] << 8); + break; + case 1: + src_dat = frgd_color; + if (s3->color_16bit && (svga->bpp < 24)) + src_dat = s3->accel.frgd_color_actual[0] | (s3->accel.frgd_color_actual[1] << 8); + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, 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; + } + + if (s3->color_16bit && (svga->bpp < 24)) { + if (!s3->accel.b2e8_pix) { + if (!s3->accel.color_16bit_check) + wrt_mask = (s3->accel.wrt_mask_actual[0] | (s3->accel.wrt_mask_actual[1] << 8)); + else + return; + } + } + + s3_log("CMD=%04x, curx=%d, lwrtmask=%04x, actual wrtmask=%04x, frgdmix=%d, " + "bkgdmix=%d, input=%d, cnt=%d.\n", s3->accel.cmd, s3->accel.cur_x, + wrt_mask, s3->accel.wrt_mask, frgd_mix, bkgd_mix, cpu_input, count); + 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 = bkgd_color; + if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.bkgd_color_actual[0] | + (s3->accel.bkgd_color_actual[1] << 8); + } + break; + case 1: + src_dat = frgd_color; + if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.frgd_color_actual[0] | + (s3->accel.frgd_color_actual[1] << 8); + } + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx - s3->accel.minus, 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->color_16bit) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (!s3->accel.sy) + break; + + if (s3->accel.cmd & 0x40) { + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; + + if (s3->accel.err_term >= 0) { + s3->accel.err_term += s3->accel.destx_distp; + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + } else + s3->accel.err_term += s3->accel.desty_axstp; + } else { + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + + if (s3->accel.err_term >= 0) { + s3->accel.err_term += s3->accel.destx_distp; + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; + } else + s3->accel.err_term += s3->accel.desty_axstp; + } + + 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.pix_trans_x_count = 0; + + s3->accel.dest = s3->accel.cy * s3->width; + + if (s3->color_16bit && (svga->bpp < 24)) { + if (s3->accel.cur_x & 0x400) { + s3->accel.color_16bit_check = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.color_16bit_check = 1; + s3->accel.minus = 0; + } + + if (s3->accel.color_16bit_check) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x00) && !(s3->accel.cmd & 2)) + s3->accel.color_16bit_check_rectfill = !!s3_cpu_src(s3); + else + s3->accel.color_16bit_check_rectfill = 0; + } + + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + s3->accel.pix_trans_ptr = (uint8_t *) calloc(1, (s3->accel.sx + 1) << 1); + s3->accel.pix_trans_ptr_cnt = (s3->accel.sx + 1) << 1; + } + } else + s3->accel.pix_trans_x_count = 0; + } else { + s3->accel.pix_trans_x_count = 0; + s3->accel.color_16bit_check = 0; + s3->accel.color_16bit_check_rectfill = 0; + s3->accel.minus = 0; + } + + 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; + } + + if (s3->color_16bit && (svga->bpp < 24)) { + if (!s3->accel.b2e8_pix) { + if (!s3->accel.color_16bit_check) { + wrt_mask = (s3->accel.wrt_mask_actual[0] | (s3->accel.wrt_mask_actual[1] << 8)); + } else if (s3->accel.color_16bit_check && (s3->accel.cmd == 0x40f3)) + return; + } + } + + 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) { + 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 - s3->accel.minus, 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 - s3->accel.minus, 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 = bkgd_color; + if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix && (s3->accel.cmd != 0x41b3)) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.bkgd_color_actual[0] | (s3->accel.bkgd_color_actual[1] << 8); + } + break; + case 1: + src_dat = frgd_color; + if (s3->color_16bit && (svga->bpp < 24) && !s3->accel.b2e8_pix && (s3->accel.cmd != 0x41b3)) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.frgd_color_actual[0] | (s3->accel.frgd_color_actual[1] << 8); + } + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + } + + READ(s3->accel.dest + s3->accel.cx - s3->accel.minus, dest_dat); + + MIX + + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.cx - s3->accel.minus, 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->color_16bit) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + 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 = 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 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; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + + if (s3->color_16bit && (svga->bpp < 24)) { + if (s3->accel.destx_distp & 0x400) { + s3->accel.color_16bit_check = 0; + s3->accel.minus = 0x400; + } else { + s3->accel.color_16bit_check = 1; + s3->accel.minus = 0; + } + s3->accel.srcminus = 0x400; + } else { + s3->accel.color_16bit_check = 0; + s3->accel.minus = 0; + s3->accel.srcminus = 0; + } + } + + 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 (s3->color_16bit && (svga->bpp < 24)) { + if (!s3->accel.color_16bit_check) + wrt_mask = (s3->accel.wrt_mask_actual[0] | (s3->accel.wrt_mask_actual[1] << 8)); + else + return; + } + + if (!cpu_input && (frgd_mix == 3) && !vram_mask && ((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 - s3->accel.srcminus, src_dat); + READ(s3->accel.dest + s3->accel.dx - s3->accel.minus, dest_dat); + + dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); + + WRITE(s3->accel.dest + s3->accel.dx - s3->accel.minus, dest_dat); + } + + s3->accel.cx++; + s3->accel.dx++; + s3->accel.sx--; + s3->accel.dx &= 0xfff; + 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.dy &= 0xfff; + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (s3->accel.sy < 0) { /*It's evident that this is a clear undocumented difference compared to later chips, per what NT 3.5+ does to DX/DY.*/ + s3->accel.destx_distp = s3->accel.dx; + s3->accel.desty_axstp = s3->accel.dy; + 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 - s3->accel.srcminus, 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; + if (s3->color_16bit && (svga->bpp < 24)) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.bkgd_color_actual[0] | (s3->accel.bkgd_color_actual[1] << 8); + } + break; + case 1: + src_dat = frgd_color; + if (s3->color_16bit && (svga->bpp < 24)) { + if (!s3->accel.color_16bit_check) + src_dat = s3->accel.frgd_color_actual[0] | (s3->accel.frgd_color_actual[1] << 8); + } + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(s3->accel.src + s3->accel.cx - s3->accel.srcminus, src_dat); + if (vram_mask && (s3->accel.cmd & 0x10)) + src_dat = ((src_dat & rd_mask) == rd_mask); + break; + + default: + break; + } + + READ(s3->accel.dest + s3->accel.dx - s3->accel.minus, dest_dat); + + MIX + + if ((!(s3->accel.cmd & 0x10) && vram_mask) || (s3->accel.cmd & 0x10)) { + WRITE(s3->accel.dest + s3->accel.dx - s3->accel.minus, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + + if (s3->color_16bit) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (s3->accel.cmd & 0x20) { + s3->accel.cx++; + s3->accel.dx++; + } else { + s3->accel.cx--; + s3->accel.dx--; + } + s3->accel.dx &= 0xfff; + 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.dy &= 0xfff; + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (cpu_input) + return; + + if (s3->accel.sy < 0) { /*It's evident that this is a clear undocumented difference compared to later chips, per what NT 3.5+ does to DX/DY.*/ + s3->accel.destx_distp = s3->accel.dx; + s3->accel.desty_axstp = s3->accel.dy; + return; + } + } + } + } + break; + + default: + break; + } +} + +void +s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +{ + if (!cpu_input) { + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = ssv & 0x10; + + 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, void *priv) +{ + s3_t *s3 = (s3_t *)priv; + 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; + uint32_t wrt_mask = s3->accel.wrt_mask; + uint32_t frgd_color = s3->accel.frgd_color; + uint32_t bkgd_color = s3->accel.bkgd_color; + int cmd = s3->accel.cmd >> 13; + uint32_t srcbase; + uint32_t dstbase; + + s3->accel.srcminus = 0; + s3->accel.minus = 0; + + 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) || s3->color_16bit) { + 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) + compare &= 0xff; + else if (s3->bpp == 1) + 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 = 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; + } + + 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 && !s3->color_16bit) + 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 & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; + } + break; + case 1: /*Draw line*/ if (!cpu_input) { s3->accel.cx = s3->accel.cur_x & 0xfff; @@ -6486,16 +8104,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.cmd & 8) /*Radial*/ - { + 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; + src_dat = bkgd_color; break; case 1: - src_dat = s3->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -6564,10 +8181,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx &= 0xfff; s3->accel.cy &= 0xfff; } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } else /*Bresenham*/ - { + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; + } 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; @@ -6582,10 +8198,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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; + src_dat = bkgd_color; break; case 1: - src_dat = s3->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -6617,87 +8233,51 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; } + if (s3->bpp == 0 && !s3->color_16bit) cpu_dat >>= 8; - else { + 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; + if (s3->accel.cmd & 0x40) { + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; - default: - break; - } + if (s3->accel.err_term >= 0) { + s3->accel.err_term += s3->accel.destx_distp; + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + } else + s3->accel.err_term += s3->accel.desty_axstp; } else { - s3->accel.err_term += s3->accel.desty_axstp; + if (s3->accel.cmd & 0x20) + s3->accel.cx++; + else + s3->accel.cx--; + + if (s3->accel.err_term >= 0) { + s3->accel.err_term += s3->accel.destx_distp; + if (s3->accel.cmd & 0x80) + s3->accel.cy++; + else + s3->accel.cy--; + } 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; + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; } break; @@ -6748,13 +8328,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ READ(s3->accel.dest + s3->accel.cx, src_dat); if (vram_mask) src_dat = ((src_dat & rd_mask) == rd_mask); - } else + } else { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: - src_dat = s3->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = s3->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -6766,6 +8346,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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); @@ -6789,11 +8370,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; } - if ((s3->bpp == 0) && !s3->color_16bit) + if (s3->bpp == 0 && !s3->color_16bit) cpu_dat >>= 8; - else { + else cpu_dat >>= 16; - } if (s3->accel.cmd & 0x20) s3->accel.cx++; @@ -6807,8 +8387,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) s3->accel.cy++; else @@ -6918,17 +8498,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; case 6: /*BitBlt*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { + 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.dx = s3->accel.destx_distp & 0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; @@ -6950,16 +8525,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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); + dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); - if (s3->accel.cmd & 0x10) { - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); - } + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); } s3->accel.cx++; s3->accel.dx++; s3->accel.sx--; + s3->accel.dx &= 0xfff; 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; @@ -6968,12 +8542,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy++; s3->accel.dy++; + s3->accel.dy &= 0xfff; 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) { + s3->accel.destx_distp = s3->accel.dx; + s3->accel.desty_axstp = s3->accel.dy; return; } } @@ -6988,10 +8565,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: - src_dat = s3->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = s3->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -7007,7 +8584,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } 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 @@ -7023,9 +8599,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->bpp == 0 && !s3->color_16bit) cpu_dat >>= 8; - else { + else cpu_dat >>= 16; - } if (s3->accel.cmd & 0x20) { s3->accel.cx++; @@ -7034,6 +8609,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx--; s3->accel.dx--; } + s3->accel.dx &= 0xfff; s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { @@ -7052,16 +8628,18 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy--; s3->accel.dy--; } + s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; s3->accel.sy--; - if (cpu_input) { + if (cpu_input) return; - } if (s3->accel.sy < 0) { + s3->accel.destx_distp = s3->accel.dx; + s3->accel.desty_axstp = s3->accel.dy; return; } } @@ -7076,11 +8654,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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; @@ -7142,7 +8716,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; - if (s3->bpp == 0) + if (s3->bpp == 0 && !s3->color_16bit) cpu_dat >>= 8; else cpu_dat >>= 16; @@ -7154,6 +8728,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); s3->accel.dx--; } + s3->accel.dx &= 0xfff; s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { @@ -7173,6 +8748,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy--; } + s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -7182,6 +8758,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ return; } if (s3->accel.sy < 0) { + s3->accel.destx_distp = s3->accel.dx; + s3->accel.desty_axstp = s3->accel.dy; return; } } @@ -7563,12 +9141,20 @@ s3_pci_read(UNUSED(int func), int addr, void *priv) return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ else return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + break; case 0x07: return (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 0x08: switch (s3->chip) { /*Revision ID*/ + case S3_TRIO64V: + return 0x40; + case S3_TRIO64V2: + return 0x16; /*Confirmed on an onboard 64V2/DX*/ + default: + return 0x00; + } + break; case 0x09: return 0; /*Programming interface*/ @@ -7595,6 +9181,7 @@ s3_pci_read(UNUSED(int func), int addr, void *priv) return 0x00; else return (svga->crtc[0x5a] & 0x80); + break; case 0x13: if (svga->crtc[0x53] & 0x08) { @@ -7602,6 +9189,7 @@ s3_pci_read(UNUSED(int func), int addr, void *priv) } else { return svga->crtc[0x59]; } + break; case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ @@ -7819,6 +9407,11 @@ s3_reset(void *priv) s3->pci_regs[0x32] = 0x0c; s3->pci_regs[0x33] = 0x00; + if (s3->chip <= S3_86C924) + s3->accel_start = s3_911_accel_start; + else + s3->accel_start = s3_accel_start; + switch (s3->card_type) { case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: @@ -7888,12 +9481,14 @@ s3_reset(void *priv) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_STB_POWERGRAPH_64_VIDEO: + case S3_CARDEX_TRIO64VPLUS: 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) + if (s3->chip == S3_TRIO64V) svga->crtc[0x53] = 0x08; break; @@ -8093,6 +9688,14 @@ s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); break; + case S3_PHOENIX_TRIO32_ONBOARD: + bios_fn = NULL; + 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; @@ -8122,6 +9725,14 @@ s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + case S3_STB_POWERGRAPH_64_VIDEO: + bios_fn = ROM_STB_POWERGRAPH_64_VIDEO; + 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: bios_fn = ROM_PHOENIX_TRIO64VPLUS; chip = S3_TRIO64V; @@ -8138,6 +9749,11 @@ s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + case S3_CARDEX_TRIO64VPLUS: + bios_fn = ROM_CARDEX_TRIO64VPLUS; + chip = S3_TRIO64V; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64vp_cardex_pci); + break; case S3_DIAMOND_STEALTH64_764: bios_fn = ROM_DIAMOND_STEALTH64_764; chip = S3_TRIO64; @@ -8236,12 +9852,34 @@ s3_init(const device_t *info) svga->hwcursor.cur_ysize = 64; - 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; + switch (chip) { + case S3_VISION964: + switch (info->local) { + case S3_ELSAWIN2KPROX_964: + svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; + break; + default: + svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + break; + } + break; + + case S3_VISION968: + switch (info->local) { + case S3_ELSAWIN2KPROX: + case S3_PHOENIX_VISION968: + case S3_NUMBER9_9FX_771: + svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; + break; + case S3_SPEA_MERCURY_P64V: + case S3_MIROVIDEO40SV_ERGO_968: + svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; + break; + default: + break; + } + break; + } if (chip >= S3_VISION964) { switch (vram) { @@ -8311,6 +9949,11 @@ s3_init(const device_t *info) svga->force_old_addr = 1; + if (s3->chip <= S3_86C924) + s3->accel_start = s3_911_accel_start; + else + s3->accel_start = s3_accel_start; + switch (s3->card_type) { case S3_ORCHID_86C911: case S3_DIAMOND_STEALTH_VRAM: @@ -8336,7 +9979,7 @@ s3_init(const device_t *info) s3->packed_mmio = 0; s3->width = 1024; - svga->ramdac = device_add(&sc11487_ramdac_device); + svga->ramdac = device_add(&att490_ramdac_device); svga->clock_gen = device_add(&ics2494an_305_device); svga->getclock = ics2494_getclock; break; @@ -8359,14 +10002,14 @@ s3_init(const device_t *info) case S3_SPEA_MIRAGE_86C801: case S3_SPEA_MIRAGE_86C805: svga->decode_mask = (2 << 20) - 1; - stepping = 0xa0; /*86C801/86C805*/ + stepping = 0xa2; /*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->ramdac = device_add(&att491_ramdac_device); svga->clock_gen = device_add(&av9194_device); svga->getclock = av9194_getclock; break; @@ -8402,7 +10045,7 @@ s3_init(const device_t *info) case S3_METHEUS_86C928: svga->decode_mask = (4 << 20) - 1; - stepping = 0x91; /*86C928*/ + stepping = 0x91; /*86C928D*/ s3->id = stepping; s3->id_ext = stepping; s3->id_ext_pci = 0; @@ -8430,7 +10073,7 @@ s3_init(const device_t *info) 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) + if (info->local == S3_PARADISE_BAHAMAS64) stepping = 0xc0; /*Vision864*/ else stepping = 0xc1; /*Vision864P*/ @@ -8453,13 +10096,18 @@ s3_init(const device_t *info) 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; + switch (info->local) { + case S3_ELSAWIN2KPROX_964: + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; + default: + svga->ramdac = device_add(&bt485_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; + } break; case S3_ELSAWIN2KPROX: @@ -8483,14 +10131,20 @@ s3_init(const device_t *info) 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; + switch (info->local) { + case S3_ELSAWIN2KPROX: + case S3_PHOENIX_VISION968: + case S3_NUMBER9_9FX_771: + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; + default: + svga->ramdac = device_add(&tvp3026_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = tvp3026_getclock; + svga->conv_16to32 = tvp3026_conv_16to32; + break; } break; @@ -8525,6 +10179,7 @@ s3_init(const device_t *info) break; case S3_PHOENIX_TRIO32: + case S3_PHOENIX_TRIO32_ONBOARD: case S3_DIAMOND_STEALTH_SE: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio32*/ @@ -8538,8 +10193,10 @@ s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_STB_POWERGRAPH_64_VIDEO: case S3_PHOENIX_TRIO64VPLUS: case S3_PHOENIX_TRIO64VPLUS_ONBOARD: + case S3_CARDEX_TRIO64VPLUS: case S3_DIAMOND_STEALTH64_764: case S3_SPEA_MIRAGE_P64: if (device_get_config_int("memory") == 1) @@ -8552,9 +10209,8 @@ s3_init(const device_t *info) s3->id_ext = s3->id_ext_pci = 0x11; s3->packed_mmio = 1; - if (info->local == S3_PHOENIX_TRIO64VPLUS || info->local == S3_PHOENIX_TRIO64VPLUS_ONBOARD) { + if (s3->chip == S3_TRIO64V) svga->crtc[0x53] = 0x08; - } svga->clock_gen = s3; svga->getclock = s3_trio64_getclock; @@ -8777,12 +10433,24 @@ s3_phoenix_trio64_available(void) return rom_present(ROM_PHOENIX_TRIO64); } +static int +s3_stb_powergraph_64_video_available(void) +{ + return rom_present(ROM_STB_POWERGRAPH_64_VIDEO); +} + static int s3_phoenix_trio64vplus_available(void) { return rom_present(ROM_PHOENIX_TRIO64VPLUS); } +static int +s3_cardex_trio64vplus_available(void) +{ + return rom_present(ROM_PHOENIX_TRIO64VPLUS); +} + static int s3_diamond_stealth64_764_available(void) { @@ -9089,7 +10757,7 @@ const device_t s3_spea_mercury_lite_86c928_pci_device = { { .available = s3_spea_mercury_lite_pci_available }, .speed_changed = s3_speed_changed, .force_redraw = s3_force_redraw, - .config = s3_standard_config + .config = s3_orchid_86c911_config }; const device_t s3_mirocrystal_20sd_864_vlb_device = { @@ -9288,6 +10956,20 @@ const device_t s3_9fx_pci_device = { .config = s3_9fx_config }; +const device_t s3_phoenix_trio32_onboard_vlb_device = { + .name = "S3 Trio32 VLB On-Board (Phoenix)", + .internal_name = "px_trio32_onboard_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_TRIO32_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config +}; + const device_t s3_phoenix_trio32_vlb_device = { .name = "S3 Trio32 VLB (Phoenix)", .internal_name = "px_trio32_vlb", @@ -9302,6 +10984,20 @@ const device_t s3_phoenix_trio32_vlb_device = { .config = s3_phoenix_trio32_config }; +const device_t s3_phoenix_trio32_onboard_pci_device = { + .name = "S3 Trio32 PCI On-Board (Phoenix)", + .internal_name = "px_trio32_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO32_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config +}; + const device_t s3_phoenix_trio32_pci_device = { .name = "S3 Trio32 PCI (Phoenix)", .internal_name = "px_trio32_pci", @@ -9386,6 +11082,20 @@ const device_t s3_phoenix_trio64_pci_device = { .config = s3_standard_config }; +const device_t s3_stb_powergraph_64_video_vlb_device = { + .name = "S3 Trio64V+ (STB PowerGraph 64 Video) VLB", + .internal_name = "stb_trio64vplus_vlb", + .flags = DEVICE_VLB, + .local = S3_STB_POWERGRAPH_64_VIDEO, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_stb_powergraph_64_video_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config +}; + const device_t s3_phoenix_trio64vplus_onboard_pci_device = { .name = "S3 Trio64V+ PCI On-Board (Phoenix)", .internal_name = "px_trio64vplus_onboard_pci", @@ -9414,6 +11124,20 @@ const device_t s3_phoenix_trio64vplus_pci_device = { .config = s3_standard_config }; +const device_t s3_cardex_trio64vplus_pci_device = { + .name = "S3 Trio64V+ PCI (Cardex)", + .internal_name = "cardex_trio64vplus_pci", + .flags = DEVICE_PCI, + .local = S3_CARDEX_TRIO64VPLUS, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_cardex_trio64vplus_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config +}; + const device_t s3_phoenix_vision864_vlb_device = { .name = "S3 Vision864 VLB (Phoenix)", .internal_name = "px_vision864_vlb", diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index ce9dda100..4d64dffbd 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -778,11 +778,22 @@ s3_virge_recalctimings(svga_t *svga) svga->hdisp = svga->hdisp_old; + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } + 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); + svga->hdisp += 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; @@ -813,7 +824,29 @@ s3_virge_recalctimings(svga_t *svga) svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; } - if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + video_force_resize_set_monitor(1, svga->monitor_index); + } else { + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; + + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; + video_force_resize_set_monitor(1, svga->monitor_index); + } + + /* ViRGE/GX2 and later does not use primary stream registers. */ + if ((svga->crtc[0x67] & 0xc) != 0xc || virge->chip >= S3_VIRGEGX2) /*VGA mode*/ { svga->ma_latch |= (virge->ma_ext << 16); if (svga->crtc[0x51] & 0x30) @@ -832,15 +865,21 @@ s3_virge_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - svga->htotal >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; } break; case 16: svga->render = svga_render_16bpp_highres; if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - svga->htotal >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; } break; case 24: @@ -857,7 +896,24 @@ s3_virge_recalctimings(svga_t *svga) } } svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; + svga->overlay.ena = 0; s3_virge_log("VGA mode\n"); + if (virge->chip >= S3_VIRGEGX2 && (svga->crtc[0x67] & 0xc) == 0xc) { + /* ViRGE/GX2 and later does not use primary stream registers. */ + svga->overlay.x = virge->streams.sec_x; + svga->overlay.y = virge->streams.sec_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) && !!(virge->streams.blend_ctrl & 0x20); + svga->overlay.v_acc = virge->streams.dda_vert_accumulator; + svga->rowoffset = virge->streams.pri_stride >> 3; + svga->vram_display_mask = virge->vram_mask; + } } else /*Streams mode*/ { if (virge->streams.buffer_ctrl & 1) @@ -882,16 +938,30 @@ s3_virge_recalctimings(svga_t *svga) svga->overlay.v_acc = virge->streams.dda_vert_accumulator; svga->rowoffset = virge->streams.pri_stride >> 3; + if (virge->chip <= S3_VIRGEDX && svga->overlay.ena) { + svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) || (((virge->streams.blend_ctrl >> 24) & 7) == 0b101); + } else if (virge->chip == S3_VIRGEGX2 && svga->overlay.ena) { + /* 0x20 = Secondary Stream enabled */ + /* 0x2000 = Primary Stream enabled */ + svga->overlay.ena = !!(virge->streams.blend_ctrl & 0x20); + } + 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->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; + // svga->dots_per_clock >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; + // svga->dots_per_clock >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -906,6 +976,31 @@ s3_virge_recalctimings(svga_t *svga) } svga->vram_display_mask = virge->vram_mask; } + + svga->hoverride = 1; +} + +static void +s3_virge_update_buffer(virge_t *virge) +{ + svga_t *svga = &virge->svga; + + if ((svga->crtc[0x67] & 0xc) != 0xc) + return; + + if (virge->chip < S3_VIRGEGX2) { + if (virge->streams.buffer_ctrl & 1) + svga->ma_latch = virge->streams.pri_fb1 >> 2; + else + svga->ma_latch = virge->streams.pri_fb0 >> 2; + } + + if (virge->streams.buffer_ctrl & 2) + svga->overlay.addr = virge->streams.sec_fb1; + else + svga->overlay.addr = virge->streams.sec_fb0; + + svga->rowoffset = virge->streams.pri_stride >> 3; } static void @@ -1921,40 +2016,40 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x81a0: virge->streams.blend_ctrl = val; + svga_recalctimings(svga); break; case 0x81c0: virge->streams.pri_fb0 = val & 0x7fffff; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81c4: virge->streams.pri_fb1 = val & 0x7fffff; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81c8: virge->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81cc: virge->streams.buffer_ctrl = val; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81d0: virge->streams.sec_fb0 = val; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81d4: virge->streams.sec_fb1 = val; - svga_recalctimings(svga); + s3_virge_update_buffer(virge); svga->fullchange = changeframecount; break; case 0x81d8: virge->streams.sec_stride = val; - svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81dc: diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/vid_sc1502x_ramdac.c index 7cbcaf05d..7315c65ad 100644 --- a/src/video/vid_sc1502x_ramdac.c +++ b/src/video/vid_sc1502x_ramdac.c @@ -34,84 +34,126 @@ typedef struct sc1502x_ramdac_t { int state; uint8_t ctrl; + uint8_t idx; + uint8_t regs[256]; + uint32_t pixel_mask; + uint8_t enable_ext; } sc1502x_ramdac_t; -void -sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) +static void +sc1502x_ramdac_bpp(uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga) { - 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) + int oldbpp = 0; + if (val == 0xff) + return; + 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; - 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; - } + 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 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; - } + case 0x20: + svga->bpp = 24; break; default: break; } - if (oldbpp != svga->bpp) - svga_recalctimings(svga); + } else + svga->bpp = 16; + break; + + default: + break; + } + if (oldbpp != svga->bpp) + svga_recalctimings(svga); +} + +void +sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) +{ + sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv; + + switch (addr) { + case 0x3C6: + if (ramdac->state == 0) + ramdac->enable_ext = (val == 0x10); + + if (ramdac->state == 4) { + ramdac->state = 0; + sc1502x_ramdac_bpp(val, ramdac, svga); return; } ramdac->state = 0; break; case 0x3C7: + if (ramdac->enable_ext) { + ramdac->idx = val; + return; + } + ramdac->state = 0; + break; case 0x3C8: + if (ramdac->enable_ext) { + switch (ramdac->idx) { + case 8: + ramdac->regs[ramdac->idx] = val; + svga_set_ramdac_type(svga, (ramdac->regs[ramdac->idx] & 1) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; + case 0x0d: + ramdac->pixel_mask = val & svga->dac_mask; + break; + case 0x0e: + ramdac->pixel_mask |= ((val & svga->dac_mask) << 8); + break; + case 0x0f: + ramdac->pixel_mask |= ((val & svga->dac_mask) << 16); + break; + default: + ramdac->regs[ramdac->idx] = val; + break; + } + return; + } + ramdac->state = 0; + break; case 0x3C9: + if (ramdac->enable_ext) + return; ramdac->state = 0; break; default: break; } - svga_out(addr, val, svga); } @@ -131,10 +173,45 @@ sc1502x_ramdac_in(uint16_t addr, void *priv, svga_t *svga) ramdac->state++; break; case 0x3C7: - case 0x3C8: - case 0x3C9: ramdac->state = 0; break; + case 0x3C8: + if (ramdac->enable_ext) { + switch (ramdac->idx) { + case 9: + temp = 0x53; + break; + case 0x0a: + temp = 0x3a; + break; + case 0x0b: + temp = 0xb1; + break; + case 0x0c: + temp = 0x41; + break; + case 0x0d: + temp = ramdac->pixel_mask & 0xff; + break; + case 0x0e: + temp = ramdac->pixel_mask >> 8; + break; + case 0x0f: + temp = ramdac->pixel_mask >> 16; + break; + default: + temp = ramdac->regs[ramdac->idx]; + break; + } + } else + ramdac->state = 0; + break; + case 0x3C9: + if (ramdac->enable_ext) + temp = ramdac->idx; + else + ramdac->state = 0; + break; default: break; @@ -149,6 +226,9 @@ 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)); + ramdac->ctrl = 0; + ramdac->pixel_mask = 0xffffff; + return ramdac; } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5f5efcd9e..4632ab85e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -90,14 +90,13 @@ svga_set_override(svga_t *svga, int val) svga->fullchange = svga->monitor->mon_changeframecount; svga->override = val; +#ifdef OVERRIDE_OVERSCAN if (!val) { /* Override turned off, restore overscan X and Y per the CRTC. */ - if (enable_overscan) { - svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; + svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; - if (svga->monitor->mon_overscan_y < 16) - svga->monitor->mon_overscan_y = 16; - } + if (svga->monitor->mon_overscan_y < 16) + svga->monitor->mon_overscan_y = 16; svga->monitor->mon_overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; @@ -106,6 +105,7 @@ svga_set_override(svga_t *svga, int val) } else svga->monitor->mon_overscan_x = svga->monitor->mon_overscan_y = 16; /* Override turned off, fix overcan X and Y to 16. */ +#endif } void @@ -116,6 +116,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) xga_t *xga = (xga_t *) svga->xga; uint8_t o; uint8_t index; + uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f }; if (!dev && (addr >= 0x2ea) && (addr <= 0x2ed)) return; @@ -163,7 +164,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) case 0x3c0: case 0x3c1: if (!svga->attrff) { - svga->attraddr = val & 31; + svga->attraddr = val & 0x1f; if ((val & 0x20) != svga->attr_palette_enable) { svga->fullchange = 3; svga->attr_palette_enable = val & 0x20; @@ -172,17 +173,19 @@ svga_out(uint16_t addr, uint8_t val, void *priv) } 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) + o = svga->attrregs[svga->attraddr & 0x1f]; + svga->attrregs[svga->attraddr & 0x1f] = val; + if (svga->attraddr < 0x10) 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) { + + if ((svga->attraddr == 0x10) || (svga->attraddr == 0x14) || (svga->attraddr < 0x10)) { + for (int c = 0; c < 0x10; c++) { + if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); - } else { + else if (svga->ati_4color) + svga->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); - } } svga->fullchange = svga->monitor->mon_changeframecount; } @@ -221,6 +224,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) svga_log("3C3: VGA ON = %d.\n", val & 0x01); vga_on = val & 0x01; + svga_recalctimings(svga); break; case 0x3c4: svga->seqaddr = val; @@ -252,7 +256,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) break; case 4: svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; + svga->chain4 = (svga->chain4 & ~8) | (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; @@ -354,6 +358,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv) if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; + case 0x3da: + svga->fcr = val; + break; default: break; @@ -474,6 +481,9 @@ svga_in(uint16_t addr, void *priv) if (svga->adv_flags & FLAG_RAMDAC_SHIFT) ret >>= 2; break; + case 0x3ca: + ret = svga->fcr; + break; case 0x3cc: ret = svga->miscout; break; @@ -510,6 +520,8 @@ svga_in(uint16_t addr, void *priv) ret = svga->cgastat; + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; break; default: @@ -558,11 +570,23 @@ svga_set_ramdac_type(svga_t *svga, int type) void svga_recalctimings(svga_t *svga) { - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; double crtcconst; double _dispontime; double _dispofftime; double disptime; + double crtcconst8514 = 0.0; + double _dispontime8514 = 0.0; + double _dispofftime8514 = 0.0; + double disptime8514 = 0.0; +#ifdef ENABLE_SVGA_LOG + int vsyncend; + int vblankend; + int hdispstart; + int hdispend; + int hsyncstart; + int hsyncend; +#endif svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -600,7 +624,7 @@ svga_recalctimings(svga_t *svga) svga->vblankstart |= 0x200; svga->vblankstart++; - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + svga->hdisp = svga->crtc[1]; svga->hdisp++; svga->htotal = svga->crtc[0]; @@ -618,64 +642,57 @@ svga_recalctimings(svga_t *svga) 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->rowcount = svga->crtc[9] & 0x1f; svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } else { + if (svga->seqregs[1] & 8) + svga->hdisp *= 16; + else + svga->hdisp *= 8; + } + 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; - if (svga->bpp <= 8) { - if (svga->attrregs[0x10] & 0x40) { /*8bpp mode*/ + if ((svga->bpp <= 8) || ((svga->gdcreg[5] & 0x60) <= 0x20)) { + if ((svga->gdcreg[5] & 0x60) == 0x00) { + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + } else if ((svga->gdcreg[5] & 0x60) == 0x20) { + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + } else { svga->map8 = svga->pallook; if (svga->lowres) /*Low res (320)*/ svga->render = svga_render_8bpp_lowres; else svga->render = svga_render_8bpp_highres; - } else { - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; } } else { 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; @@ -722,12 +739,10 @@ svga_recalctimings(svga_t *svga) svga->linedbl = svga->crtc[9] & 0x80; svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; - if (enable_overscan) { - svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; + svga->monitor->mon_overscan_y = (svga->rowcount + 1) << 1; - if (svga->monitor->mon_overscan_y < 16) - svga->monitor->mon_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)) { svga->monitor->mon_overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; @@ -737,9 +752,33 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; - if (svga->recalctimings_ex) { + svga->hblankstart = svga->crtc[2]; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + svga->hblank_end_mask = 0x0000003f; + + svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", + svga->htotal, svga->hblankstart, svga->hblank_end_val); + + if (!svga->scrblank && svga->attr_palette_enable) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + else + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + } else { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = 16; + else + svga->dots_per_clock = 8; + } + } else + svga->dots_per_clock = 1; + + svga->multiplier = 1.0; + + if (svga->recalctimings_ex) svga->recalctimings_ex(svga); - } if (ibm8514_active && (svga->dev8514 != NULL)) { if ((dev->local & 0xff) == 0x00) @@ -749,20 +788,124 @@ svga_recalctimings(svga_t *svga) if (xga_active && (svga->xga != NULL)) xga_recalctimings(svga); + if (!svga->hoverride) { + uint32_t dot = svga->hblankstart; + uint32_t adj_dot = svga->hblankstart; + /* Verified with both the Voodoo 3 and the S3 cards: compare 7 bits if bit 7 is set, + otherwise compare 6 bits. */ + uint32_t eff_mask = (svga->hblank_end_val & ~0x0000003f) ? svga->hblank_end_mask : 0x0000003f; + svga->hblank_sub = 0; + + svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, svga->hblankstart, svga->hblank_end_val, + svga->htotal, eff_mask, adj_dot); + + while (adj_dot < (svga->htotal << 1)) { + if (dot == svga->htotal) + dot = 0; + + if (adj_dot >= svga->htotal) + svga->hblank_sub++; + + svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, svga->hblank_end_val); + if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) + break; + + dot++; + adj_dot++; + } + + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + } + +#ifdef TBD + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + uint32_t dot8514 = dev->h_blankstart; + uint32_t adj_dot8514 = dev->h_blankstart; + uint32_t eff_mask8514 = 0x0000003f; + dev->hblank_sub = 0; + + while (adj_dot8514 < (dev->h_total << 1)) { + if (dot8514 == dev->h_total) + dot8514 = 0; + + if (adj_dot8514 >= dev->h_total) + dev->hblank_sub++; + + if ((dot8514 & eff_mask8514) == (dev->h_blank_end_val & eff_mask8514)) + break; + + dot8514++; + adj_dot8514++; + } + + dev->h_disp -= dev->hblank_sub; + } + } +#endif + if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; - svga->y_add = (svga->monitor->mon_overscan_y >> 1) - (svga->crtc[8] & 0x1f); + svga->y_add = (svga->monitor->mon_overscan_y >> 1); svga->x_add = (svga->monitor->mon_overscan_x >> 1); if (svga->vblankstart < svga->dispend) svga->dispend = svga->vblankstart; crtcconst = svga->clock * svga->char_width; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) + crtcconst8514 = svga->clock8514; + } - disptime = svga->htotal; +#ifdef ENABLE_SVGA_LOG + vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); + if (vsyncend <= svga->vsyncstart) + vsyncend += 0x00000010; + vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); + if (vblankend <= svga->vblankstart) + vblankend += 0x00000080; + + hdispstart = ((svga->crtc[3] >> 5) & 3); + hdispend = svga->crtc[1] + 1; + hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; + hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); + if (hsyncend <= hsyncstart) + hsyncend += 0x00000020; +#endif + + svga_log("Last scanline in the vertical period: %i\n" + "First scanline after the last of active display: %i\n" + "First scanline with vertical retrace asserted: %i\n" + "First scanline after the last with vertical retrace asserted: %i\n" + "First scanline of blanking: %i\n" + "First scanline after the last of blanking: %i\n" + "\n" + "Last character in the horizontal period: %i\n" + "First character of active display: %i\n" + "First character after the last of active display: %i\n" + "First character with horizontal retrace asserted: %i\n" + "First character after the last with horizontal retrace asserted: %i\n" + "First character of blanking: %i\n" + "First character after the last of blanking: %i\n" + "\n" + "\n", + svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend, + svga->vblankstart, vblankend, + svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, + svga->hblankstart, svga->hblankend); + + disptime = svga->htotal * svga->multiplier; _dispontime = svga->hdisp_time; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + disptime8514 = dev->h_total ? dev->h_total : TIMER_USEC; + _dispontime8514 = dev->hdisped; + } + } + if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; @@ -779,14 +922,44 @@ svga_recalctimings(svga_t *svga) if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + timer_disable(&svga->timer); + timer_set_delay_u64(&svga->timer8514, TIMER_USEC); + } else { + timer_disable(&svga->timer8514); + timer_set_delay_u64(&svga->timer, TIMER_USEC); + } + } + 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) { + /* Make sure to black out the entire screen to avoid lingering image. */ + int y_add = enable_overscan ? svga->monitor->mon_overscan_y : 0; + int x_add = enable_overscan ? svga->monitor->mon_overscan_x : 0; + int y_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_y >> 1); + int x_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_x >> 1); + video_wait_for_buffer_monitor(svga->monitor_index); + memset(svga->monitor->target_buffer->dat, 0, svga->monitor->target_buffer->w * svga->monitor->target_buffer->h * 4); + video_blit_memtoscreen_monitor(x_start, y_start, svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); + video_wait_for_buffer_monitor(svga->monitor_index); svga->dpms_ui = 1; - ui_sb_set_text_w(plat_get_string(IDS_2143)); + ui_sb_set_text_w(plat_get_string(STRING_MONITOR_SLEEP)); } } else if (svga->dpms_ui) { svga->dpms_ui = 0; @@ -822,7 +995,7 @@ svga_do_render(svga_t *svga) 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_draw(svga, (svga->displine + svga->y_add + ((svga->dac_hwcursor_latch.y >= 0) ? 0 : svga->dac_hwcursor_latch.y)) & 2047); svga->dac_hwcursor_on--; if (svga->dac_hwcursor_on && svga->interlace) svga->dac_hwcursor_on--; @@ -830,7 +1003,7 @@ svga_do_render(svga_t *svga) if (svga->hwcursor_on) { if (!svga->override && svga->hwcursor_draw) - svga->hwcursor_draw(svga, svga->displine + svga->y_add); + svga->hwcursor_draw(svga, (svga->displine + svga->y_add + ((svga->hwcursor_latch.y >= 0) ? 0 : svga->hwcursor_latch.y)) & 2047); svga->hwcursor_on--; if (svga->hwcursor_on && svga->interlace) svga->hwcursor_on--; @@ -841,7 +1014,6 @@ void svga_poll(void *priv) { 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; @@ -851,10 +1023,6 @@ svga_poll(void *priv) int old_ma; if (!svga->override) { - if (ibm8514_active && dev && (dev->on[0] || dev->on[1])) { - ibm8514_poll(dev, svga); - return; - } if (xga_active && xga && xga->on) { if ((xga->disp_cntl_2 & 7) >= 2) { xga_poll(xga, svga); @@ -864,22 +1032,22 @@ svga_poll(void *priv) } if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { + if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : 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) { + if (svga->displine == (((svga->hwcursor_latch.y < 0) ? 0 : 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) { + if (svga->displine == ((svga->dac_hwcursor_latch.y < 0) ? 0 : 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) { + if (svga->displine == (((svga->dac_hwcursor_latch.y < 0) ? 0 : 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; } @@ -953,6 +1121,8 @@ svga_poll(void *priv) if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount)) svga->con = 0; if (svga->dispon) { + /* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll + - S3 Trio64V2/DX: sc == rowcount, wrapping 5-bit counter. */ if (svga->linedbl && !svga->linecountff) { svga->linecountff = 1; svga->ma = svga->maback; @@ -960,9 +1130,9 @@ svga_poll(void *priv) svga->linecountff = 0; svga->sc = 0; - svga->maback += (svga->rowoffset << 3); + svga->maback += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); if (svga->interlace) - svga->maback += (svga->rowoffset << 3); + svga->maback += (svga->adv_flags & FLAG_NO_SHIFT3) ? svga->rowoffset : (svga->rowoffset << 3); svga->maback &= svga->vram_display_mask; svga->ma = svga->maback; @@ -990,9 +1160,9 @@ svga_poll(void *priv) if (ret) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = (svga->rowoffset << 1) + svga->hblank_sub; else - svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->hblank_sub; svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); @@ -1062,21 +1232,26 @@ svga_poll(void *priv) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + svga->hblank_sub; else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + svga->hblank_sub; 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); + if (!(svga->adv_flags & FLAG_NO_SHIFT3)) { + svga->ma = (svga->ma << 2); + svga->maback = (svga->maback << 2); + } svga->ca = (svga->ca << 2); if (svga->vsync_callback) svga->vsync_callback(svga); } +#if 0 + if (svga->vc == lines_num) { +#endif if (svga->vc == svga->vtotal) { svga->vc = 0; - svga->sc = 0; + svga->sc = (svga->crtc[0x8] & 0x1f); svga->dispon = 1; svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; @@ -1115,6 +1290,12 @@ svga_poll(void *priv) } } +uint32_t +svga_conv_16to32(struct svga_t *svga, uint16_t color, uint8_t bpp) +{ + return (bpp == 15) ? video_15to32[color] : video_16to32[color]; +} + int svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, void (*recalctimings_ex)(struct svga_t *svga), @@ -1161,6 +1342,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->video_out = video_out; svga->hwcursor_draw = hwcursor_draw; svga->overlay_draw = overlay_draw; + svga->conv_16to32 = svga_conv_16to32; + svga->render = svga_render_blank; svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 32; @@ -1194,7 +1377,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->ramdac_type = RAMDAC_6BIT; - svga->map8 = svga->pallook; + svga->map8 = svga->pallook; return 0; } @@ -1239,14 +1422,10 @@ svga_decode_addr(svga_t *svga, uint32_t addr, int write) } 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 (write) + addr += svga->write_bank; + else + addr += svga->read_bank; } return addr; @@ -1646,7 +1825,7 @@ svga_doblit(int wx, int wy, svga_t *svga) 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); + bottom = (svga->monitor->mon_overscan_y >> 1); if (svga->vertical_linedbl) { y_add <<= 1; @@ -1698,14 +1877,14 @@ svga_doblit(int wx, int wy, svga_t *svga) p = &svga->monitor->target_buffer->line[i & 0x7ff][0]; for (j = 0; j < (svga->monitor->mon_xsize + x_add); j++) - p[j] = svga->overscan_color; + p[j] = svga->dpms ? 0 : svga->overscan_color; } 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 < (svga->monitor->mon_xsize + x_add); j++) - p[j] = svga->overscan_color; + p[j] = svga->dpms ? 0 : svga->overscan_color; } } @@ -1920,9 +2099,8 @@ svga_readl_common(uint32_t addr, uint8_t linear, void *priv) { svga_t *svga = (svga_t *) priv; - if (!svga->fast) { + if (!svga->fast) 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 -= svga->monitor->mon_video_timing_read_l; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 7cc0aafc3..9b395ea6c 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -30,6 +30,20 @@ #include <86box/vid_svga_render.h> #include <86box/vid_svga_render_remap.h> +uint32_t +svga_lookup_lut_ram(svga_t* svga, uint32_t val) +{ + if (!svga->lut_map) + return val; + + uint8_t r = getcolr(svga->pallook[getcolr(val)]); + uint8_t g = getcolg(svga->pallook[getcolg(val)]); + uint8_t b = getcolb(svga->pallook[getcolb(val)]); + return makecol32(r, g, b) | (val & 0xFF000000); +} + +#define lookup_lut(val) svga_lookup_lut_ram(svga, val) + void svga_render_null(svga_t *svga) { @@ -71,9 +85,20 @@ svga_render_blank(svga_t *svga) break; } +#if 0 + pclog("svga->displine = %i, svga->y_add = %i, svga->x_add = %i\n", svga->displine, svga->y_add, svga->x_add); +#endif uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; +#if 0 + pclog("svga->hdisp = %i, svga->scrollcache = %i, char_width = %i, sizeof(uint32_t) = %i\n", svga->hdisp, svga->scrollcache, char_width, sizeof(uint32_t)); +#endif uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t); - memset(line_ptr, 0, line_width); + +#if 0 + pclog("line_width = %i\n", line_width); +#endif + if ((svga->hdisp + svga->scrollcache) > 0) + memset(line_ptr, 0, line_width); } void @@ -82,7 +107,7 @@ svga_render_overscan_left(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->scrblank || (svga->hdisp == 0)) + if (svga->scrblank || (svga->hdisp <= 0)) return; uint32_t *line_ptr = svga->monitor->target_buffer->line[svga->displine + svga->y_add]; @@ -98,7 +123,7 @@ svga_render_overscan_right(svga_t *svga) if ((svga->displine + svga->y_add) < 0) return; - if (svga->scrblank || (svga->hdisp == 0)) + if (svga->scrblank || (svga->hdisp <= 0)) return; uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp]; @@ -456,8 +481,8 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) uint32_t *p; uint32_t changed_offset; - const bool blinked = svga->blink & 0x10; - const bool attrblink = ((svga->attrregs[0x10] & 0x08) != 0); + const bool blinked = !!(svga->blink & 0x10); + const bool attrblink = (!svga->disable_blink) && ((svga->attrregs[0x10] & 0x08) != 0); /* The following is likely how it works on an IBM VGA - that is, it works with its BIOS. @@ -485,11 +510,11 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) const uint32_t loadevery = forcepacked ? 1 : (dwordload ? 4 : wordload ? 2 : 1); const bool shift4bit = ((svga->gdcreg[0x05] & 0x40) == 0x40) || highres8bpp; - const bool shift2bit = ((svga->gdcreg[0x05] & 0x60) == 0x20) && !shift4bit; + const bool shift2bit = (((svga->gdcreg[0x05] & 0x60) == 0x20) && !shift4bit); const int dwshift = highres ? 0 : 1; const int dotwidth = 1 << dwshift; - const int charwidth = dotwidth * (combine8bits ? 4 : 8); + const int charwidth = dotwidth * ((combine8bits && !svga->packed_4bpp) ? 4 : 8); const uint32_t planemask = 0x11111111 * (uint32_t) (svga->plane_mask); const uint32_t blinkmask = (attrblink ? 0x88888888 : 0x0); const uint32_t blinkval = (attrblink && blinked ? 0x88888888 : 0x0); @@ -571,8 +596,8 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) But 4bpp chunky is generally easier to deal with on a modern CPU. shift4bit is the native format for this renderer (4bpp chunky). */ - if (!shift4bit) { - if (shift2bit) { + if (svga->ati_4color || !shift4bit) { + if (shift2bit && !svga->ati_4color) { /* Group 2x 2bpp values into 4bpp values */ edat = (edat & 0xCCCC3333) | ((edat << 14) & 0x33330000) | ((edat >> 14) & 0x0000CCCC); } else { @@ -623,7 +648,7 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) */ out_edat = ((out_edat & planemask & ~blinkmask) | ((out_edat | ~planemask) & blinkmask & blinkval)) ^ blinkmask; - for (int i = 0; i < 8; i += 2) { + for (int i = 0; i < (8 + (svga->ati_4color ? 8 : 0)); i += (svga->ati_4color ? 4 : 2)) { /* c0 denotes the first 4bpp pixel shifted, while c1 denotes the second. For 8bpp modes, the first 4bpp pixel is the upper 4 bits. @@ -633,12 +658,34 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) uint32_t c1 = (out_edat >> (current_shift & 0x1C)) & 0xF; current_shift >>= 3; - if (combine8bits) { - uint32_t ccombined = (c0 << 4) | c1; - uint32_t p0 = svga->map8[ccombined]; - const int outoffs = (i >> 1) << dwshift; - for (int subx = 0; subx < dotwidth; subx++) - p[outoffs + subx] = p0; + if (svga->ati_4color) { + uint32_t q[4]; + q[0] = svga->pallook[svga->egapal[(c0 & 0x0c) >> 2]]; + q[1] = svga->pallook[svga->egapal[c0 & 0x03]]; + q[2] = svga->pallook[svga->egapal[(c1 & 0x0c) >> 2]]; + q[3] = svga->pallook[svga->egapal[c1 & 0x03]]; + + const int outoffs = i << dwshift; + for (int ch = 0; ch < 4; ch++) { + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx + (dotwidth * ch)] = q[ch]; + } + } else if (combine8bits) { + if (svga->packed_4bpp) { + uint32_t p0 = svga->map8[c0]; + uint32_t p1 = svga->map8[c1]; + const int outoffs = i << dwshift; + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx] = p0; + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx + dotwidth] = p1; + } else { + uint32_t ccombined = (c0 << 4) | c1; + uint32_t p0 = svga->map8[ccombined]; + const int outoffs = (i >> 1) << dwshift; + for (int subx = 0; subx < dotwidth; subx++) + p[outoffs + subx] = p0; + } } else { uint32_t p0 = svga->pallook[svga->egapal[c0]]; uint32_t p1 = svga->pallook[svga->egapal[c1]]; @@ -650,7 +697,11 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) } } - p += charwidth; + if (svga->ati_4color) + p += (charwidth << 1); + // p += charwidth; + else + p += charwidth; } } @@ -665,6 +716,89 @@ void svga_render_4bpp_highres(svga_t *svga) { svga_render_indexed_gfx(svga, true void svga_render_8bpp_lowres(svga_t *svga) { svga_render_indexed_gfx(svga, false, true); } void svga_render_8bpp_highres(svga_t *svga) { svga_render_indexed_gfx(svga, true, true); } +void +svga_render_8bpp_clone_highres(svga_t *svga) +{ + int x; + uint32_t *p; + uint32_t dat; + uint32_t changed_addr; + uint32_t addr; + + if ((svga->displine + svga->y_add) < 0) + return; + + 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->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + 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; + } + 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] = 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; + } + } +} + // TODO: Integrate more of this into the generic paletted renderer --GM #if 0 void @@ -945,13 +1079,13 @@ svga_render_15bpp_lowres(svga_t *svga) 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_15to32[dat & 0xffff]; - p[(x << 1) + 2] = p[(x << 1) + 3] = video_15to32[dat >> 16]; + p[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 15); dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & 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]; + p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 15); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -970,13 +1104,13 @@ svga_render_15bpp_lowres(svga_t *svga) 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++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); } svga->ma += x << 1; } else { @@ -984,8 +1118,8 @@ svga_render_15bpp_lowres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); svga->ma += 4; } } @@ -1016,20 +1150,20 @@ svga_render_15bpp_highres(svga_t *svga) 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]; + p[x] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[x + 1] = svga->conv_16to32(svga, dat >> 16, 15); 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]; + p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[x + 3] = svga->conv_16to32(svga, dat >> 16, 15); 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]; + p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[x + 5] = svga->conv_16to32(svga, dat >> 16, 15); 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]; + p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 15); + p[x + 7] = svga->conv_16to32(svga, dat >> 16, 15); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -1047,20 +1181,20 @@ svga_render_15bpp_highres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - *p++ = video_15to32[dat & 0xffff]; - *p++ = video_15to32[dat >> 16]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); } svga->ma += x << 1; } else { @@ -1068,8 +1202,8 @@ svga_render_15bpp_highres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 15); + *p++ = svga->conv_16to32(svga, dat >> 16, 15); svga->ma += 4; } } @@ -1097,16 +1231,16 @@ svga_render_15bpp_mix_lowres(svga_t *svga) 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]; + p[x << 1] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); 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]; + p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -1132,24 +1266,24 @@ svga_render_15bpp_mix_highres(svga_t *svga) 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]; + p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); 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]; + p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); 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]; + p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); 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]; + p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); dat >>= 16; - p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; + p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -1178,12 +1312,12 @@ svga_render_16bpp_lowres(svga_t *svga) 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[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 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]; + p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 16); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -1202,13 +1336,13 @@ svga_render_16bpp_lowres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 16); } svga->ma += x << 1; } else { @@ -1216,8 +1350,8 @@ svga_render_16bpp_lowres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 16); } svga->ma += 4; } @@ -1248,20 +1382,20 @@ svga_render_16bpp_highres(svga_t *svga) 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]; + p[x] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[x + 1] = svga->conv_16to32(svga, dat >> 16, 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]; + p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[x + 3] = svga->conv_16to32(svga, dat >> 16, 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]; + p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[x + 5] = svga->conv_16to32(svga, dat >> 16, 16); 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]; + p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 16); + p[x + 7] = svga->conv_16to32(svga, dat >> 16, 16); } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -1279,20 +1413,20 @@ svga_render_16bpp_highres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 16); } svga->ma += x << 1; } else { @@ -1300,8 +1434,8 @@ svga_render_16bpp_highres(svga_t *svga) 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]; + *p++ = svga->conv_16to32(svga, dat & 0xffff, 16); + *p++ = svga->conv_16to32(svga, dat >> 16, 16); svga->ma += 4; } @@ -1339,7 +1473,7 @@ svga_render_24bpp_lowres(svga_t *svga) 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; + 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] = lookup_lut(fg); } } } else { @@ -1358,10 +1492,10 @@ svga_render_24bpp_lowres(svga_t *svga) 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; + p[0] = p[1] = lookup_lut(dat0 & 0xffffff); + p[2] = p[3] = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); + p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); + p[6] = p[7] = lookup_lut(dat2 >> 8); svga->ma += 12; } @@ -1374,10 +1508,10 @@ svga_render_24bpp_lowres(svga_t *svga) 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; + p[0] = p[1] = lookup_lut(dat0 & 0xffffff); + p[2] = p[3] = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); + p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); + p[6] = p[7] = lookup_lut(dat2 >> 8); svga->ma += 12; } @@ -1412,16 +1546,16 @@ svga_render_24bpp_highres(svga_t *svga) 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[x] = lookup_lut(dat & 0xffffff); dat = *(uint32_t *) (&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); - p[x + 1] = dat & 0xffffff; + p[x + 1] = lookup_lut(dat & 0xffffff); dat = *(uint32_t *) (&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); - p[x + 2] = dat & 0xffffff; + p[x + 2] = lookup_lut(dat & 0xffffff); dat = *(uint32_t *) (&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); - p[x + 3] = dat & 0xffffff; + p[x + 3] = lookup_lut(dat & 0xffffff); svga->ma += 12; } @@ -1443,10 +1577,10 @@ svga_render_24bpp_highres(svga_t *svga) 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; + *p++ = lookup_lut(dat0 & 0xffffff); + *p++ = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); + *p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); + *p++ = lookup_lut(dat2 >> 8); svga->ma += 12; } @@ -1459,10 +1593,10 @@ svga_render_24bpp_highres(svga_t *svga) 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; + *p++ = lookup_lut(dat0 & 0xffffff); + *p++ = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8)); + *p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16)); + *p++ = lookup_lut(dat2 >> 8); svga->ma += 12; } @@ -1494,7 +1628,7 @@ svga_render_32bpp_lowres(svga_t *svga) 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; + 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] = lookup_lut(dat); } } } else { @@ -1510,16 +1644,16 @@ svga_render_32bpp_lowres(svga_t *svga) 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; + *p++ = lookup_lut(dat & 0xffffff); + *p++ = lookup_lut(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; + *p++ = lookup_lut(dat & 0xffffff); + *p++ = lookup_lut(dat & 0xffffff); svga->ma += 4; } svga->ma &= svga->vram_display_mask; @@ -1550,7 +1684,7 @@ svga_render_32bpp_highres(svga_t *svga) 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; + p[x] = lookup_lut(dat & 0xffffff); } svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -1568,14 +1702,14 @@ svga_render_32bpp_highres(svga_t *svga) 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++ = lookup_lut(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++ = lookup_lut(dat & 0xffffff); svga->ma += 4; } @@ -1609,14 +1743,14 @@ svga_render_ABGR8888_highres(svga_t *svga) 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); + *p++ = lookup_lut(((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); + *p++ = lookup_lut(((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16)); svga->ma += 4; } @@ -1649,14 +1783,14 @@ svga_render_RGBA8888_highres(svga_t *svga) 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; + *p++ = lookup_lut(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; + *p++ = lookup_lut(dat >> 8); svga->ma += 4; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index b4198eefd..b2686b2f3 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -77,197 +77,202 @@ static const device_t vid_internal_device = { static const VIDEO_CARD video_cards[] = { // 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 }, + { &vid_none_device }, + { &vid_internal_device }, + { &atiega800p_device }, + { &mach8_vga_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 }, -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - { &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_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, VIDEO_FLAG_TYPE_SPECIAL }, - { &mystique_device }, - { &mystique_220_device }, -#endif - { &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 } + { &ati18800_device }, + { &ati18800_wonder_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_rtg3105_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 }, + { &tvga8900dr_device }, + { &tvga9000b_device }, + { &nec_sv9000_device }, + { &et4000k_isa_device }, + { &et2000_device }, + { &et3000_isa_device }, + { &et4000_tc6058af_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 }, + { &bochs_svga_device }, + { &chips_69000_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 }, + { &et4000w32p_videomagic_revb_pci_device }, + { &et4000w32p_revc_pci_device }, + { &et4000w32p_cardex_pci_device }, + { &et4000w32p_noncardex_pci_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_cardex_trio64vplus_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 }, + { &millennium_device }, + { &millennium_ii_device }, + { &mystique_device }, + { &mystique_220_device }, + { &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 }, + { &s3_stb_powergraph_64_video_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 }, + { &productiva_g100_device, VIDEO_FLAG_TYPE_SPECIAL }, + { &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 }; diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 7bed43ac2..490c724ce 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -76,7 +76,8 @@ #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_9440_VLB "roms/video/tgui9440/trident_9440_vlb.bin" +#define ROM_TGUI_9440_PCI "roms/video/tgui9440/BIOS.BIN" #define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI" #define EXT_CTRL_16BIT 0x01 @@ -891,7 +892,6 @@ tgui_recalcmapping(tgui_t *tgui) } } 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); @@ -899,12 +899,6 @@ tgui_recalcmapping(tgui_t *tgui) 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*/ @@ -919,6 +913,18 @@ tgui_recalcmapping(tgui_t *tgui) default: break; } + + if (tgui->pci && tgui->linear_base) /*Assume that, with PCI, linear addressing is always enabled.*/ + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); + + 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 + mem_mapping_disable(&tgui->accel_mapping); } if (tgui->type >= TGUI_9440) { @@ -982,7 +988,7 @@ tgui_pci_read(UNUSED(int func), int addr, void *priv) return (tgui->type == TGUI_9440) ? 0x94 : 0x96; case PCI_REG_COMMAND: - return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + return tgui->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -1043,11 +1049,12 @@ tgui_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) switch (addr) { case PCI_REG_COMMAND: - tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23); - if (val & PCI_COMMAND_IO) { + tgui->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) tgui_set_io(tgui); - } else + else tgui_remove_io(tgui); + tgui_recalcmapping(tgui); break; @@ -3141,11 +3148,14 @@ tgui_init(const device_t *info) bios_fn = ROM_TGUI_9400CXI; break; case TGUI_9440: - bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; + if (tgui->pci) + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440_PCI; + else + bios_fn = ROM_TGUI_9440_VLB; break; case TGUI_9660: case TGUI_9680: - bios_fn = ROM_TGUI_96xx; + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_96xx; break; default: free(tgui); @@ -3193,7 +3203,7 @@ tgui_init(const device_t *info) pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); } - tgui->pci_regs[PCI_REG_COMMAND] = 7; + tgui->pci_regs[PCI_REG_COMMAND] = 0x83; if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; @@ -3218,9 +3228,15 @@ tgui9400cxi_available(void) } static int -tgui9440_available(void) +tgui9440_vlb_available(void) { - return rom_present(ROM_TGUI_9440); + return rom_present(ROM_TGUI_9440_VLB); +} + +static int +tgui9440_pci_available(void) +{ + return rom_present(ROM_TGUI_9440_PCI); } static int @@ -3338,7 +3354,7 @@ const device_t tgui9440_vlb_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_vlb_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3352,7 +3368,7 @@ const device_t tgui9440_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_pci_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3386,6 +3402,20 @@ const device_t tgui9660_pci_device = { .config = tgui96xx_config }; +const device_t tgui9660_onboard_pci_device = { + .name = "Trident TGUI 9660XGi On-Board PCI", + .internal_name = "tgui9660_onboard_pci", + .flags = DEVICE_PCI, + .local = TGUI_9660 | ONBOARD, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui96xx_config +}; + const device_t tgui9680_pci_device = { .name = "Trident TGUI 9680XGi PCI", .internal_name = "tgui9680_pci", diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 591851016..cd5714d04 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -37,6 +37,7 @@ #define ROM_TVGA_8900B "roms/video/tvga/tvga8900b.vbi" #define ROM_TVGA_8900CLD "roms/video/tvga/trident.bin" +#define ROM_TVGA_8900DR "roms/video/tvga/8900DR.VBI" #define ROM_TVGA_9000B "roms/video/tvga/tvga9000b.bin" #define ROM_TVGA_9000B_NEC_SV9000 "roms/video/tvga/SV9000.VBI" @@ -59,6 +60,7 @@ typedef struct tvga_t { } tvga_t; 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_tvga8900dr = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; 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] = { @@ -417,7 +419,10 @@ tvga_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000); tvga->vram_size = 512 << 10; } else { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900); + if (info->local & 0x0100) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900dr); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900); tvga->vram_size = device_get_config_int("memory") << 10; } @@ -428,7 +433,10 @@ tvga_init(const device_t *info) bios_fn = ROM_TVGA_8900B; break; case TVGA8900CLD_ID: - bios_fn = ROM_TVGA_8900CLD; + if (info->local & 0x0100) + bios_fn = ROM_TVGA_8900DR; + else + bios_fn = ROM_TVGA_8900CLD; break; case TVGA9000B_ID: bios_fn = (info->local & 0x100) ? ROM_TVGA_9000B_NEC_SV9000 : ROM_TVGA_9000B; @@ -466,6 +474,12 @@ tvga8900d_available(void) return rom_present(ROM_TVGA_8900CLD); } +static int +tvga8900dr_available(void) +{ + return rom_present(ROM_TVGA_8900DR); +} + static int tvga9000b_available(void) { @@ -564,6 +578,20 @@ const device_t tvga8900d_device = { .config = tvga_config }; +const device_t tvga8900dr_device = { + .name = "Trident TVGA 8900D-R", + .internal_name = "tvga8900dr", + .flags = DEVICE_ISA, + .local = TVGA8900CLD_ID | 0x0100, + .init = tvga_init, + .close = tvga_close, + .reset = NULL, + { .available = tvga8900dr_available }, + .speed_changed = tvga_speed_changed, + .force_redraw = tvga_force_redraw, + .config = tvga_config +}; + const device_t tvga9000b_device = { .name = "Trident TVGA 9000B", .internal_name = "tvga9000b", diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index 15215c45d..b50d0406b 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -55,12 +55,17 @@ typedef struct tvp3026_ramdac_t { uint8_t n; uint8_t p; } pix, mem, loop; + uint8_t gpio_cntl; + uint8_t gpio_data; + uint8_t (*gpio_read)(uint8_t cntl, void *priv); + void (*gpio_write)(uint8_t cntl, uint8_t val, void *priv); + void *gpio_priv; } tvp3026_ramdac_t; static void tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga) { - if ((ramdac->true_color & 0x80) == 0x80) { + if (ramdac->true_color & 0x80) { if (ramdac->mcr & 0x08) svga->bpp = 8; else @@ -211,6 +216,16 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svg ramdac->misc = val; svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT; break; + case 0x2a: /* General-Purpose I/O Control */ + ramdac->gpio_cntl = val; + if (ramdac->gpio_write) + ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv); + break; + case 0x2b: /* General-Purpose I/O Data */ + ramdac->gpio_data = val; + if (ramdac->gpio_write) + ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv); + break; case 0x2c: /* PLL Address */ ramdac->pll_addr = val; break; @@ -389,6 +404,16 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) case 0x1e: /* Miscellaneous Control */ temp = ramdac->misc; break; + case 0x2a: /* General-Purpose I/O Control */ + temp = ramdac->gpio_cntl; + break; + case 0x2b: /* General-Purpose I/O Data */ + if (ramdac->gpio_read) { + temp = 0xe0 | (ramdac->gpio_cntl & 0x1f); /* keep upper bits untouched */ + ramdac->gpio_data = (ramdac->gpio_data & temp) | (ramdac->gpio_read(ramdac->gpio_cntl, ramdac->gpio_priv) & ~temp); + } + temp = ramdac->gpio_data; + break; case 0x2c: /* PLL Address */ temp = ramdac->pll_addr; break; @@ -489,7 +514,39 @@ tvp3026_recalctimings(void *priv, svga_t *svga) { const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; - svga->interlace = (ramdac->ccr & 0x40); + svga->interlace = !!(ramdac->ccr & 0x40); + /* TODO: Figure out gamma correction for 15/16 bpp color. */ + svga->lut_map = !!(svga->bpp >= 15 && (ramdac->true_color & 0xf0) != 0x00); + + if (!(ramdac->clock_sel & 0x70)) { + if (ramdac->mcr != 0x98) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + } +} + +uint32_t +tvp3026_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + uint32_t ret = 0x00000000; + + if (svga->lut_map) { + if (bpp == 15) { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 2]); + uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 7]); + ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b); + } else { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 3]); + uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 8]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } + } else + ret = (bpp == 15) ? video_15to32[color] : video_16to32[color]; + + return ret; } void @@ -540,7 +597,7 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine) comb = (b0 | (b1 << 1)); y_pos = displine; - x_pos = offset + svga->x_add; + x_pos = (offset + svga->x_add) & 2047; p = svga->monitor->target_buffer->line[y_pos]; if (offset >= svga->dac_hwcursor_latch.x) { @@ -630,6 +687,18 @@ tvp3026_getclock(int clock, void *priv) return f_pll; } +void +tvp3026_gpio(uint8_t (*read)(uint8_t cntl, void *priv), + void (*write)(uint8_t cntl, uint8_t val, void *priv), + void *cb_priv, void *priv) +{ + tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; + + ramdac->gpio_read = read; + ramdac->gpio_write = write; + ramdac->gpio_priv = cb_priv; +} + void * tvp3026_ramdac_init(const device_t *info) { diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 43b8a2750..8b2e761a3 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -186,7 +186,7 @@ vga_force_redraw(void *priv) } const device_t vga_device = { - .name = "VGA", + .name = "IBM VGA", .internal_name = "vga", .flags = DEVICE_ISA, .local = 0, @@ -200,7 +200,7 @@ const device_t vga_device = { }; const device_t ps1vga_device = { - .name = "PS/1 VGA", + .name = "IBM PS/1 VGA", .internal_name = "ps1vga", .flags = DEVICE_ISA, .local = 0, @@ -214,7 +214,7 @@ const device_t ps1vga_device = { }; const device_t ps1vga_mca_device = { - .name = "PS/1 VGA", + .name = "IBM PS/1 VGA", .internal_name = "ps1vga_mca", .flags = DEVICE_MCA, .local = 0, diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index a34f26503..93bdd1a4c 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -505,6 +505,9 @@ voodoo_writel(uint32_t addr, uint32_t val, void *priv) voodoo->videoDimensions = val; voodoo->h_disp = (val & 0xfff) + 1; voodoo->v_disp = (val >> 16) & 0xfff; + if ((voodoo->v_disp == 386) || (voodoo->v_disp == 402) || + (voodoo->v_disp == 482) || (voodoo->v_disp == 602)) + voodoo->v_disp -= 2; break; case SST_fbiInit0: if (voodoo->initEnable & 0x01) { @@ -772,7 +775,7 @@ voodoo_pci_read(int func, int addr, void *priv) switch (addr) { case 0x00: - return 0x1a; /*3dfx*/ + return 0x1a; /*3Dfx*/ case 0x01: return 0x12; @@ -1310,7 +1313,7 @@ static const device_config_t voodoo_config[] = { .type = CONFIG_SELECTION, .selection = { { - .description = "Voodoo Graphics", + .description = "3Dfx Voodoo Graphics", .value = VOODOO_1 }, { @@ -1318,7 +1321,7 @@ static const device_config_t voodoo_config[] = { .value = VOODOO_SB50 }, { - .description = "Voodoo 2", + .description = "3Dfx Voodoo 2", .value = VOODOO_2 }, { @@ -1427,7 +1430,7 @@ static const device_config_t voodoo_config[] = { }; const device_t voodoo_device = { - .name = "3DFX Voodoo Graphics", + .name = "3Dfx Voodoo Graphics", .internal_name = "voodoo", .flags = DEVICE_PCI, .local = 0, diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index d0fad5b95..5b6dbb434 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -219,7 +219,9 @@ enum { #define VIDPROCCFG_INTERLACE (1 << 3) #define VIDPROCCFG_HALF_MODE (1 << 4) #define VIDPROCCFG_OVERLAY_ENABLE (1 << 8) +#define VIDPROCCFG_DESKTOP_CLUT_BYPASS (1 << 10) #define VIDPROCCFG_OVERLAY_CLUT_BYPASS (1 << 11) +#define VIDPROCCFG_DESKTOP_CLUT_SEL (1 << 12) #define VIDPROCCFG_OVERLAY_CLUT_SEL (1 << 13) #define VIDPROCCFG_H_SCALE_ENABLE (1 << 14) #define VIDPROCCFG_V_SCALE_ENABLE (1 << 15) @@ -466,6 +468,32 @@ banshee_updatemapping(banshee_t *banshee) mem_mapping_set_addr(&banshee->reg_mapping_high, banshee->memBaseAddr0 + 0xc00000, 20 << 20); } +uint32_t +banshee_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + banshee_t *banshee = (banshee_t *) svga->priv; + uint32_t ret = 0x00000000; + uint16_t src_b = (color & 0x1f) << 3; + uint16_t src_g = (color & 0x7e0) >> 3; + uint16_t src_r = (color & 0xf800) >> 8; + + if (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_CLUT_SEL) { + src_b += 256; + src_g += 256; + src_r += 256; + } + + if (svga->lut_map) { + uint8_t b = getcolr(svga->pallook[src_b]); + uint8_t g = getcolg(svga->pallook[src_g]); + uint8_t r = getcolb(svga->pallook[src_r]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } else + ret = video_16to32[color]; + + return ret; +} + static void banshee_render_16bpp_tiled(svga_t *svga) { @@ -482,6 +510,9 @@ banshee_render_16bpp_tiled(svga_t *svga) else addr = banshee->desktop_addr + (banshee->desktop_y & 31) * 128 + ((banshee->desktop_y >> 5) * banshee->desktop_stride_tiled); + if (addr >= svga->vram_max) + return; + for (int x = 0; x <= svga->hdisp; x += 64) { if (svga->hwcursor_on || svga->overlay_on) svga->changedvram[addr >> 12] = 2; @@ -489,7 +520,7 @@ banshee_render_16bpp_tiled(svga_t *svga) 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++]; + *p++ = banshee_conv_16to32(svga, *vram_p++, 16); drawn = 1; } else @@ -515,7 +546,7 @@ banshee_recalctimings(svga_t *svga) /*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 + 4 R/W Horizontal Blank Start bit 8. 0x3 ---- Erratum: Actually, 0x02! 3 R/W Reserved. - 2 R/W Horizontal Display Enable End bit 8. 0x1 1 R/W Reserved. - @@ -524,6 +555,44 @@ banshee_recalctimings(svga_t *svga) svga->htotal += 0x100; if (svga->crtc[0x1a] & 0x04) svga->hdisp += 0x100; + + if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) { + /* Video processing mode - assume timings akin to Cirrus' special blanking mode, + that is, no overscan and relying on display end to blank. */ + if (banshee->vgaInit0 & 0x40) { + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3)*/ + + (((svga->crtc[0x1a] & 0x04) >> 2) << 8); + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3)*/; + svga->hblank_end_mask = 0x0000003f; + } + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; + + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + + svga->monitor->mon_overscan_y = 0; + svga->monitor->mon_overscan_x = 0; + + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + + svga->linedbl = 0; + } else { + if (banshee->vgaInit0 & 0x40) { + svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2]; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[2]; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5); + svga->hblank_end_mask = 0x0000003f; + } + } + /*6 R/W Vertical Retrace Start bit 10 0x10 5 R/W Reserved. - 4 R/W Vertical Blank Start bit 10. 0x15 @@ -539,6 +608,7 @@ banshee_recalctimings(svga_t *svga) svga->vblankstart += 0x400; if (svga->crtc[0x1b] & 0x40) svga->vsyncstart += 0x400; + #if 0 banshee_log("svga->hdisp=%i\n", svga->hdisp); #endif @@ -585,7 +655,7 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; - svga->htotal *= 2; + svga->dots_per_clock *= 2; } svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); @@ -767,6 +837,7 @@ banshee_ext_outl(uint16_t addr, uint32_t val, void *priv) case Init_vgaInit0: banshee->vgaInit0 = val; svga_set_ramdac_type(svga, (val & VGAINIT0_RAMDAC_8BIT ? RAMDAC_8BIT : RAMDAC_6BIT)); + svga_recalctimings(svga); break; case Init_vgaInit1: banshee->vgaInit1 = val; @@ -806,6 +877,7 @@ banshee_ext_outl(uint16_t addr, uint32_t val, void *priv) 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->lut_map = !(val & VIDPROCCFG_DESKTOP_CLUT_BYPASS) && (svga->bpp < 24); svga_recalctimings(svga); break; @@ -2037,10 +2109,12 @@ banshee_hwcursor_draw(svga_t *svga, int displine) 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; + if (((x_off + xx + svga->x_add) >= 0) && ((x_off + xx + svga->x_add) <= 2047)) { + 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; @@ -3029,6 +3103,61 @@ static const device_config_t banshee_sgram_config[] = { } }; +static const device_config_t banshee_sgram_16mbonly_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 + } +}; + static const device_config_t banshee_sdram_config[] = { { .name = "bilinear", @@ -3107,7 +3236,9 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int #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) + if ((banshee->type == TYPE_V3_1000) || (banshee->type == TYPE_VELOCITY200)) + mem_size = 16; /* Our Voodoo 3 1000 and Velocity 200 bios'es are hardcoded to 16 MB. */ + else if (banshee->type == TYPE_VELOCITY100) mem_size = 8; /* Velocity 100 only supports 8 MB */ else mem_size = device_get_config_int("memory"); @@ -3190,6 +3321,8 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int banshee->i2c_ddc = i2c_gpio_init("ddc_voodoo_banshee"); banshee->ddc = ddc_init(i2c_gpio_get_bus(banshee->i2c_ddc)); + banshee->svga.conv_16to32 = banshee_conv_16to32; + switch (type) { case TYPE_BANSHEE: if (has_sgram) { @@ -3472,7 +3605,7 @@ banshee_force_redraw(void *priv) } const device_t voodoo_banshee_device = { - .name = "3dfx Voodoo Banshee", + .name = "3Dfx Voodoo Banshee", .internal_name = "voodoo_banshee_pci", .flags = DEVICE_PCI, .local = 0, @@ -3524,7 +3657,7 @@ const device_t voodoo_3_1000_agp_device = { { .available = v3_1000_agp_available }, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, - .config = banshee_sgram_config + .config = banshee_sgram_16mbonly_config }; const device_t voodoo_3_2000_device = { @@ -3692,5 +3825,5 @@ const device_t velocity_200_agp_device = { { .available = velocity_200_available }, .speed_changed = banshee_speed_changed, .force_redraw = banshee_force_redraw, - .config = banshee_sgram_config + .config = banshee_sgram_16mbonly_config }; diff --git a/src/video/vid_voodoo_banshee_blitter.c b/src/video/vid_voodoo_banshee_blitter.c index 33ee602b5..b8809d3fd 100644 --- a/src/video/vid_voodoo_banshee_blitter.c +++ b/src/video/vid_voodoo_banshee_blitter.c @@ -216,6 +216,9 @@ PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_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]; + if (addr > voodoo->fb_mask) + break; + voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_8); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -226,6 +229,9 @@ PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_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]; + if (addr > voodoo->fb_mask) + break; + *(uint16_t *) &voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_16); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -236,6 +242,9 @@ PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_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]; + if (addr > voodoo->fb_mask) + break; + *(uint32_t *) &voodoo->vram[addr] = (MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -246,6 +255,9 @@ PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_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]; + if (addr > voodoo->fb_mask) + break; + *(uint32_t *) &voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -265,6 +277,9 @@ PLOT_LINE(voodoo_t *voodoo, int x, int y, UNUSED(uint8_t rop), uint32_t pattern, 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]; + if (addr > voodoo->fb_mask) + break; + voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_8); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -274,6 +289,9 @@ PLOT_LINE(voodoo_t *voodoo, int x, int y, UNUSED(uint8_t rop), uint32_t pattern, 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]; + if (addr > voodoo->fb_mask) + break; + *(uint16_t *) &voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_16); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -283,6 +301,9 @@ PLOT_LINE(voodoo_t *voodoo, int x, int y, UNUSED(uint8_t rop), uint32_t pattern, 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]; + if (addr > voodoo->fb_mask) + break; + *(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; @@ -292,6 +313,9 @@ PLOT_LINE(voodoo_t *voodoo, int x, int y, UNUSED(uint8_t rop), uint32_t pattern, 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]; + if (addr > voodoo->fb_mask) + break; + *(uint32_t *) &voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32); voodoo->changedvram[addr >> 12] = changeframecount; break; @@ -573,6 +597,9 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr 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]; + if (dst_addr > voodoo->fb_mask) + break; + voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); voodoo->changedvram[dst_addr >> 12] = changeframecount; break; @@ -584,6 +611,9 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr 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]; + if (dst_addr > voodoo->fb_mask) + break; + *(uint16_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); voodoo->changedvram[dst_addr >> 12] = changeframecount; break; @@ -595,6 +625,9 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr 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]; + if (dst_addr > voodoo->fb_mask) + break; + *(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; @@ -606,6 +639,9 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr 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]; + if (dst_addr > voodoo->fb_mask) + break; + *(uint32_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); voodoo->changedvram[dst_addr >> 12] = changeframecount; break; @@ -904,6 +940,9 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in 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]; + if (dst_addr > voodoo->fb_mask) + break; + 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]); @@ -918,6 +957,9 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in 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]; + if (dst_addr > voodoo->fb_mask) + break; + *(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]); @@ -932,6 +974,9 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in 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 (dst_addr > voodoo->fb_mask) + break; + *(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]); @@ -946,6 +991,9 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in 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 (dst_addr > voodoo->fb_mask) + break; + *(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]); diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index e6cf13674..d04376941 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -511,6 +511,8 @@ voodoo_callback(void *priv) { voodoo_t *voodoo = (voodoo_t *) priv; const monitor_t *monitor = &monitors[voodoo->monitor_index]; + int v_y_add = (monitor->mon_overscan_y >> 1); + int v_x_add = (monitor->mon_overscan_x >> 1); if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) { if (voodoo->line < voodoo->v_disp) { @@ -534,7 +536,7 @@ voodoo_callback(void *priv) } if (draw_voodoo->dirty_line[draw_line]) { - uint32_t *p = &monitor->target_buffer->line[voodoo->line + 8][8]; + uint32_t *p = &monitor->target_buffer->line[voodoo->line + v_y_add][v_x_add]; uint16_t *src = (uint16_t *) &draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line * draw_voodoo->row_width]; int x; @@ -548,8 +550,8 @@ voodoo_callback(void *priv) voodoo->dirty_line_high = voodoo->line; /* Draw left overscan. */ - for (x = 0; x < 8; x++) - monitor->target_buffer->line[voodoo->line + 8][x] = 0x00000000; + for (x = 0; x < v_x_add; x++) + monitor->target_buffer->line[voodoo->line + v_y_add][x] = 0x00000000; if (voodoo->scrfilter && voodoo->scrfilterEnabled) { uint8_t fil[4096 * 3]; /* interleaved 24-bit RGB */ @@ -570,8 +572,9 @@ voodoo_callback(void *priv) } /* Draw right overscan. */ - for (x = 0; x < 8; x++) - monitor->target_buffer->line[voodoo->line + 8][voodoo->h_disp + x + 8] = 0x00000000; + for (x = 0; x < v_x_add; x++) + monitor->target_buffer->line[voodoo->line + v_y_add][voodoo->h_disp + x + v_x_add] = + 0x00000000; } } } diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index 42426744a..0f31fbc9f 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -1394,7 +1394,7 @@ next_line: void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) { - voodoo_state_t state; + voodoo_state_t state = { 0 }; int vertexAy_adjusted; int vertexCy_adjusted; int dx; @@ -1406,6 +1406,8 @@ voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) int LOD; int lodbias; + state.dx1 = state.dx2 = 0; + voodoo->tri_count++; dx = 8 - (params->vertexAx & 0xf); diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 17b6dfdb5..a908c3418 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -151,37 +151,50 @@ xga_updatemapping(svga_t *svga) 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); + switch (xga->op_mode & 7) { + case 0: + xga_log("XGA: VGA mode address decode disabled.\n"); + break; + case 1: + xga_log("XGA: VGA mode address decode enabled.\n"); + break; + case 2: + xga_log("XGA: 132-Column mode address decode disabled.\n"); + break; + case 3: + xga_log("XGA: 132-Column mode address decode enabled.\n"); + break; + default: + xga_log("XGA: Extended Graphics mode.\n"); + switch (xga->aperture_cntl) { + case 0: + xga_log("XGA: No 64KB aperture.\n"); + if (xga->base_addr_1mb) + mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); + else if (xga->linear_base) + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + else + mem_mapping_disable(&xga->linear_mapping); - 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"); + mem_mapping_disable(&xga->video_mapping); + break; + case 1: + xga_log("XGA: 64KB aperture at A0000.\n"); + mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); + mem_mapping_enable(&xga->video_mapping); + xga->banked_mask = 0xffff; + break; + case 2: + xga_log("XGA: 64KB aperture at B0000.\n"); + mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); + mem_mapping_enable(&xga->video_mapping); + xga->banked_mask = 0xffff; + break; + default: + break; } - } - - xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, - xga->disp_cntl_2 & 7, xga->aperture_cntl); + break; } - xga_log("VGA on = %d, map = %02x.\n", vga_on, svga->gdcreg[6] & 0x0c); } void @@ -198,7 +211,7 @@ xga_recalctimings(svga_t *svga) xga->h_disp = (xga->hdisp + 1) << 3; - xga->rowoffset = (xga->hdisp + 1); + xga->rowoffset = xga->hdisp + 1; xga->interlace = !!(xga->disp_cntl_1 & 0x08); xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6; @@ -213,6 +226,11 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; + if ((xga->disp_cntl_2 & 7) == 2) + xga->rowoffset >>= 1; + else if ((xga->disp_cntl_2 & 7) == 4) + xga->rowoffset <<= 1; + 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: @@ -405,27 +423,6 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) 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); @@ -509,13 +506,12 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *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->aperture_cntl = val & 3; xga_updatemapping(svga); break; case 4: @@ -555,6 +551,7 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) case 0x0e: case 0x0f: xga->regs[xga->regs_idx] = val; + xga_log("EXT OUT Reg=%02x, val=%02x.\n", xga->regs_idx, val); xga_ext_out_reg(xga, svga, xga->regs_idx, xga->regs[xga->regs_idx]); break; @@ -795,6 +792,8 @@ xga_ext_inb(uint16_t addr, void *priv) default: ret = xga->regs[xga->regs_idx]; + if ((xga->regs_idx == 0x0c) || (xga->regs_idx == 0x0d)) + xga_log("EXT IN Reg=%02x, val=%02x.\n", xga->regs_idx, ret); break; } break; @@ -803,7 +802,7 @@ xga_ext_inb(uint16_t addr, void *priv) break; } - xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); + xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -998,9 +997,9 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int addr += x; if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } + return byte; case 4: /*16-bit*/ addr += (y * (width << 1)); @@ -1082,6 +1081,7 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui } else { byte = mem_readb_phys(addr); } + if (xga->linear_endian_reverse) mask = 0x0f << ((1 - (x & 1)) << 2); else { @@ -1233,9 +1233,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) } } - if (!y) { + if (!y) break; - } dx += dirx; dy += diry; @@ -1249,50 +1248,28 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) 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 old_dest_dat = 0x00000000; 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 = (xga->accel.octant & 0x04) ? -1 : 1; - int ydir = (xga->accel.octant & 0x02) ? -1 : 1; int y = xga->accel.blt_width; int x = 0; int16_t dx; int16_t dy; - int draw_pixel; + int16_t cx; + int16_t cy; + int err = xga->accel.bres_err_term; + int draw_pixel = 0; - 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; + cx = xga->accel.src_map_x & 0xfff; + cy = xga->accel.src_map_y & 0xfff; dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) @@ -1305,17 +1282,87 @@ xga_line_draw_write(svga_t *svga) 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 ((xga->accel.command & 0x30) == 0x30) { + while (y >= 0) { + draw_pixel = 0; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (x) + draw_pixel = 1; + } else { /*Top-to-Bottom*/ + if (y) + draw_pixel = 1; + } + } else if (!(xga->accel.octant & 0x04) && (err < (xga->accel.bres_k2 + xga->accel.bres_k1))) /*X+*/ + draw_pixel = 1; + else if ((xga->accel.octant & 0x04) && (err >= 0)) /*X-*/ + draw_pixel = 1; + + 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))) { + if (draw_pixel) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, 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))) { + ROP(1, dest_dat, src_dat); + 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 (draw_pixel) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, 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))) { + ROP(1, dest_dat, src_dat); + 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 (x == xga->accel.blt_width) + break; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } else + err += xga->accel.bres_k1; + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } else + err += xga->accel.bres_k1; + } + x++; + y--; + } + } else { + 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); @@ -1330,54 +1377,9 @@ xga_line_draw_write(svga_t *svga) 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); @@ -1391,84 +1393,52 @@ xga_line_draw_write(svga_t *svga) 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; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } else + err += xga->accel.bres_k1; + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } else + err += xga->accel.bres_k1; + } + y--; + x++; } - - 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; @@ -1507,6 +1477,7 @@ xga_bitblt(svga_t *svga) xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth); xga->accel.pattern = 0; + xga->accel.filling = 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, " @@ -1637,76 +1608,66 @@ xga_bitblt(svga_t *svga) 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) { + if ((((xga->accel.command >> 24) & 0x0f) == 0x0a) && ((xga->accel.bkgd_mix & 0x1f) == 5)) { 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; + xga->accel.filling = !xga->accel.filling; 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))) { - 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, dx, 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, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + 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; + if (xga->accel.filling) { + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, 1024, 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_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, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } } } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - 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, dx, 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, dx, 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, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + 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; + if (xga->accel.filling) { + dest_dat = xga_accel_read_map_pixel(svga, dx, 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_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, dx, 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, dx, 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.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); + xga->accel.px++; + dx++; xga->accel.x--; if (xga->accel.x < 0) { - area_state = 0; xga->accel.y--; xga->accel.x = xga->accel.blt_width & 0xfff; dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) 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; - dy += ydir; + xga->accel.py++; - if (xga->accel.y < 0) { - xga->accel.dst_map_x = dx; - xga->accel.dst_map_y = dy; + dy++; + xga->accel.filling = 0; + + if (xga->accel.y < 0) return; - } } } } else { @@ -1715,11 +1676,11 @@ xga_bitblt(svga_t *svga) 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))) { - if (mix) { + 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 { + 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, dx, 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; @@ -1730,11 +1691,11 @@ xga_bitblt(svga_t *svga) } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - if (mix) { + 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 { + 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, dx, 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; @@ -1760,6 +1721,7 @@ xga_bitblt(svga_t *svga) dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; @@ -1791,6 +1753,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) switch (addr & 0x7f) { case 0x11: xga->accel.control = val; + xga_log("Control=%02x.\n", val); break; case 0x12: @@ -1853,7 +1816,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_err_term = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_err_term |= ~0x3fff; + xga->accel.bres_err_term |= ~0x1fff; } else xga->accel.bres_err_term = (xga->accel.bres_err_term & 0x3f00) | val; break; @@ -1861,7 +1824,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) 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; + xga->accel.bres_err_term |= ~0x1fff; } break; @@ -1869,7 +1832,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_k1 = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_k1 |= ~0x3fff; + xga->accel.bres_k1 |= ~0x1fff; } else xga->accel.bres_k1 = (xga->accel.bres_k1 & 0x3f00) | val; break; @@ -1877,7 +1840,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len == 1) { xga->accel.bres_k1 = (xga->accel.bres_k1 & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - xga->accel.bres_k1 |= ~0x3fff; + xga->accel.bres_k1 |= ~0x1fff; } break; @@ -1885,7 +1848,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_k2 = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_k2 |= ~0x3fff; + xga->accel.bres_k2 |= ~0x1fff; } else xga->accel.bres_k2 = (xga->accel.bres_k2 & 0x3f00) | val; break; @@ -1893,7 +1856,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len == 1) { xga->accel.bres_k2 = (xga->accel.bres_k2 & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - xga->accel.bres_k2 |= ~0x3fff; + xga->accel.bres_k2 |= ~0x1fff; } break; @@ -1998,6 +1961,30 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.plane_mask = (xga->accel.plane_mask & 0x00ffffff) | (val << 24); break; + case 0x54: + if (len == 4) + xga->accel.carry_chain = val; + else if (len == 2) + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffff0000) | val; + else + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffffff00) | val; + break; + case 0x55: + if (len == 1) + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffff00ff) | (val << 8); + break; + case 0x56: + if (len == 2) + xga->accel.carry_chain = (xga->accel.carry_chain & 0x0000ffff) | (val << 16); + else + xga->accel.carry_chain = (xga->accel.carry_chain & 0xff00ffff) | (val << 16); + break; + case 0x57: + if (len == 1) + xga->accel.carry_chain = (xga->accel.carry_chain & 0x00ffffff) | (val << 24); + break; + + case 0x58: if (len == 4) xga->accel.frgd_color = val; @@ -2310,6 +2297,12 @@ xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) temp = xga->vga_bios_rom.rom[addr]; } else { switch (addr & 0x7f) { + case 0x0c: + temp = xga->regs[0x0c]; + break; + case 0x0d: + temp = xga->regs[0x0d]; + break; case 0x11: temp = xga->accel.control; if (xga->accel.control & 0x08) @@ -2422,7 +2415,7 @@ xga_memio_readl(uint32_t addr, void *priv) 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); + xga_log("[%04X:%08X]: Read MEMIOL = %04x, temp = %08x\n", CS, cpu_state.pc, addr, temp); return temp; } @@ -2430,42 +2423,45 @@ xga_memio_readl(uint32_t addr, void *priv) 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; + xga_t *xga = (xga_t *) svga->xga; + int comb; + uint8_t dat = 0; + int offset = xga->hwcursor_latch.x - xga->hwcursor_latch.xoff; + int idx = 0; + int x_pos; + int y_pos; + uint32_t *p; + const uint8_t *cd; + + if (xga->hwcursor_latch.xoff & 0x20) + idx = 32; + + cd = (uint8_t *) xga->sprite_data; 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++) { + dat = cd[xga->hwcursor_latch.addr & 0x3ff]; + + comb = (dat >> ((x & 0x03) << 1)) & 0x03; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + 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 */ + /* Cursor Color 1 */ p[x_pos] = xga->hwc_color0; break; case 0x01: - /* Cursor Color 2 */ + /* Cursor Color 2 */ p[x_pos] = xga->hwc_color1; break; case 0x03: - /* Complement */ + /* Complement */ p[x_pos] ^= 0xffffff; break; @@ -2473,6 +2469,8 @@ xga_hwcursor_draw(svga_t *svga, int displine) break; } } + offset++; + xga_log("P=%08x, xpos=%d, comb=%x, ypos=%d, offset=%d, latchx=%d, latchxoff=%d.\n", p[x_pos], x_pos, comb, y_pos, offset, xga->hwcursor_latch.x, xga->hwcursor_latch.xoff); if ((x & 0x03) == 0x03) xga->hwcursor_latch.addr++; @@ -2532,20 +2530,24 @@ xga_render_4bpp(svga_t *svga) 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]; + p[0] = xga->pallook[dat & 0x0f]; + p[1] = xga->pallook[(dat >> 4) & 0x0f]; + p[2] = xga->pallook[(dat >> 8) & 0x0f]; + p[3] = xga->pallook[(dat >> 12) & 0x0f]; + p[4] = xga->pallook[(dat >> 16) & 0x0f]; + p[5] = xga->pallook[(dat >> 20) & 0x0f]; + p[6] = xga->pallook[(dat >> 24) & 0x0f]; + p[7] = xga->pallook[(dat >> 28) & 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]; + p[8] = xga->pallook[dat & 0x0f]; + p[9] = xga->pallook[(dat >> 4) & 0x0f]; + p[10] = xga->pallook[(dat >> 8) & 0x0f]; + p[11] = xga->pallook[(dat >> 12) & 0x0f]; + p[12] = xga->pallook[(dat >> 16) & 0x0f]; + p[13] = xga->pallook[(dat >> 20) & 0x0f]; + p[14] = xga->pallook[(dat >> 24) & 0x0f]; + p[15] = xga->pallook[(dat >> 28) & 0x0f]; xga->ma += 8; p += 16; @@ -2609,7 +2611,7 @@ xga_render_16bpp(svga_t *svga) xga->firstline_draw = xga->displine; xga->lastline_draw = xga->displine; - for (x = 0; x <= (xga->h_disp); x += 8) { + 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]; @@ -2930,12 +2932,12 @@ xga_poll(void *priv, svga_t *svga) 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_on = xga->hwcursor_latch.cur_ysize; 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_on = xga->hwcursor_latch.cur_ysize - 1; xga->hwcursor_oddeven = 1; } @@ -2952,9 +2954,8 @@ xga_poll(void *priv, svga_t *svga) video_wait_for_buffer_monitor(svga->monitor_index); } - if (xga->hwcursor_on) { + if (xga->hwcursor_on) xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - } xga_do_render(svga); @@ -2976,9 +2977,10 @@ xga_poll(void *priv, svga_t *svga) if (xga->sc == xga->rowcount) { xga->sc = 0; - xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + xga->maback += (xga->rowoffset << 3); if (xga->interlace) - xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + xga->maback += (xga->rowoffset << 3); + xga->maback &= xga->vram_mask; xga->ma = xga->maback; } else { @@ -2996,6 +2998,7 @@ xga_poll(void *priv, svga_t *svga) xga->ma = xga->maback = (xga->rowoffset << 1); else xga->ma = xga->maback = 0; + xga->ma = (xga->ma << 2); xga->maback = (xga->maback << 2); @@ -3135,6 +3138,8 @@ xga_mca_reset(void *priv) xga->on = 0; vga_on = 1; xga_mca_write(0x102, 0, svga); + xga->linear_endian_reverse = 0; + xga->a5_test = 0; } static void diff --git a/src/video/video.c b/src/video/video.c index 4c561e229..0773e61ce 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -104,7 +104,7 @@ 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); #endif @@ -601,8 +601,27 @@ cgapal_rebuild_monitor(int monitor_index) } } - if (cga_palette_monitor == 7) + if (cga_palette_monitor == 8) palette_lookup[0x16] = makecol(video_6to8[42], video_6to8[42], video_6to8[0]); + else if (cga_palette_monitor == 10) { + /* IBM 5153 CRT, colors by VileR */ + palette_lookup[0x10] = 0x00000000; + palette_lookup[0x11] = 0x000000c4; + palette_lookup[0x12] = 0x0000c400; + palette_lookup[0x13] = 0x0000c4c4; + palette_lookup[0x14] = 0x00c40000; + palette_lookup[0x15] = 0x00c400c4; + palette_lookup[0x16] = 0x00c47e00; + palette_lookup[0x17] = 0x00c4c4c4; + palette_lookup[0x18] = 0x004e4e4e; + palette_lookup[0x19] = 0x004e4edc; + palette_lookup[0x1a] = 0x004edc4e; + palette_lookup[0x1b] = 0x004ef3f3; + palette_lookup[0x1c] = 0x00dc4e4e; + palette_lookup[0x1d] = 0x00f34ef3; + palette_lookup[0x1e] = 0x00f3f34e; + palette_lookup[0x1f] = 0x00ffffff; + } } void @@ -812,9 +831,9 @@ destroy_bitmap(bitmap_t *b) bitmap_t * create_bitmap(int x, int y) { - bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint32_t *))); + bitmap_t *b = calloc(sizeof(bitmap_t), (y * sizeof(uint32_t *))); - b->dat = malloc((size_t) x * y * 4); + b->dat = calloc((size_t) x * y, 4); for (int c = 0; c < y; c++) b->line[c] = &(b->dat[c * x]); b->w = x; diff --git a/src/win/86Box.rc b/src/win/86Box.rc deleted file mode 100644 index 2932b7d62..000000000 --- a/src/win/86Box.rc +++ /dev/null @@ -1,365 +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. - * - * 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á' - */ -#define IN_RESOURCE_H -#include <86box/resource.h> -#include <86box/language.h> -#include <86box/version.h> -#undef IN_RESOURCE_H - -#define APSTUDIO_READONLY_SYMBOLS -#define APSTUDIO_HIDDEN_SYMBOLS -#include -#undef APSTUDIO_HIDDEN_SYMBOLS -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -MainAccel ACCELERATORS MOVEABLE PURE -BEGIN -#ifdef MTR_ENABLED - "T", IDM_ACTION_TRACE, CONTROL, VIRTKEY -#endif - // 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 -END - - -#ifndef NO_INCLUDE_MANIFEST -///////////////////////////////////////////////////////////////////////////// -// -// 24 -// - -1 24 MOVEABLE PURE "86Box.manifest" -#endif - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -#ifdef CMAKE -#define ICON_PATH -#else -#define ICON_PATH "win/" -#endif - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -// defining the icons depending on the build status -#ifdef RELEASE_BUILD -/* Icon by OBattler and laciba96 (green for release builds)*/ - 10 ICON DISCARDABLE ICON_PATH "icons/86Box-green.ico" -#elif BETA_BUILD -/* Icon by OBattler and laciba96 (yellow for beta builds done by Jenkins)*/ - 10 ICON DISCARDABLE ICON_PATH "icons/86Box-yellow.ico" -#elif ALPHA_BUILD -/* Icon by OBattler and laciba96 (red for alpha builds done by Jenkins)*/ - 10 ICON DISCARDABLE ICON_PATH "icons/86Box-red.ico" -#else -/* Icon by OBattler and laciba96 (gray for builds of branches and from the git master)*/ - 10 ICON DISCARDABLE ICON_PATH "icons/86Box-gray.ico" -#endif - 16 ICON DISCARDABLE ICON_PATH "icons/floppy_525.ico" - 17 ICON DISCARDABLE ICON_PATH "icons/floppy_525_active.ico" - 24 ICON DISCARDABLE ICON_PATH "icons/floppy_35.ico" - 25 ICON DISCARDABLE ICON_PATH "icons/floppy_35_active.ico" - 32 ICON DISCARDABLE ICON_PATH "icons/cdrom.ico" - 33 ICON DISCARDABLE ICON_PATH "icons/cdrom_active.ico" - 48 ICON DISCARDABLE ICON_PATH "icons/zip.ico" - 49 ICON DISCARDABLE ICON_PATH "icons/zip_active.ico" - 56 ICON DISCARDABLE ICON_PATH "icons/mo.ico" - 57 ICON DISCARDABLE ICON_PATH "icons/mo_active.ico" - 64 ICON DISCARDABLE ICON_PATH "icons/cassette.ico" - 65 ICON DISCARDABLE ICON_PATH "icons/cassette_active.ico" - 80 ICON DISCARDABLE ICON_PATH "icons/hard_disk.ico" - 81 ICON DISCARDABLE ICON_PATH "icons/hard_disk_active.ico" - 96 ICON DISCARDABLE ICON_PATH "icons/network.ico" - 97 ICON DISCARDABLE ICON_PATH "icons/network_active.ico" -104 ICON DISCARDABLE ICON_PATH "icons/cartridge.ico" -144 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty.ico" -145 ICON DISCARDABLE ICON_PATH "icons/floppy_525_empty_active.ico" -152 ICON DISCARDABLE ICON_PATH "icons/floppy_35_empty.ico" -153 ICON DISCARDABLE ICON_PATH "icons/floppy_35_empty_active.ico" -160 ICON DISCARDABLE ICON_PATH "icons/cdrom_empty.ico" -161 ICON DISCARDABLE ICON_PATH "icons/cdrom_empty_active.ico" -176 ICON DISCARDABLE ICON_PATH "icons/zip_empty.ico" -177 ICON DISCARDABLE ICON_PATH "icons/zip_empty_active.ico" -184 ICON DISCARDABLE ICON_PATH "icons/mo_empty.ico" -185 ICON DISCARDABLE ICON_PATH "icons/mo_empty_active.ico" -192 ICON DISCARDABLE ICON_PATH "icons/cassette_empty.ico" -193 ICON DISCARDABLE ICON_PATH "icons/cassette_empty_active.ico" -200 ICON DISCARDABLE ICON_PATH "icons/run.ico" -201 ICON DISCARDABLE ICON_PATH "icons/pause.ico" -202 ICON DISCARDABLE ICON_PATH "icons/send_cad.ico" -203 ICON DISCARDABLE ICON_PATH "icons/send_cae.ico" -204 ICON DISCARDABLE ICON_PATH "icons/hard_reset.ico" -205 ICON DISCARDABLE ICON_PATH "icons/acpi_shutdown.ico" -206 ICON DISCARDABLE ICON_PATH "icons/settings.ico" -232 ICON DISCARDABLE ICON_PATH "icons/cartridge_empty.ico" -240 ICON DISCARDABLE ICON_PATH "icons/machine.ico" -241 ICON DISCARDABLE ICON_PATH "icons/display.ico" -242 ICON DISCARDABLE ICON_PATH "icons/input_devices.ico" -243 ICON DISCARDABLE ICON_PATH "icons/sound.ico" -244 ICON DISCARDABLE ICON_PATH "icons/ports.ico" -245 ICON DISCARDABLE ICON_PATH "icons/other_peripherals.ico" -246 ICON DISCARDABLE ICON_PATH "icons/floppy_and_cdrom_drives.ico" -247 ICON DISCARDABLE ICON_PATH "icons/other_removable_devices.ico" -248 ICON DISCARDABLE ICON_PATH "icons/floppy_disabled.ico" -249 ICON DISCARDABLE ICON_PATH "icons/cdrom_disabled.ico" -250 ICON DISCARDABLE ICON_PATH "icons/zip_disabled.ico" -251 ICON DISCARDABLE ICON_PATH "icons/mo_disabled.ico" -252 ICON DISCARDABLE ICON_PATH "icons/storage_controllers.ico" - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""resources.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - DLG_SND_GAIN, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 167 - TOPMARGIN, 7 - BOTTOMMARGIN, 129 - END - - DLG_NEW_FLOPPY, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 219 - TOPMARGIN, 7 - BOTTOMMARGIN, 79 - END - - DLG_CFG_MAIN, DIALOG - BEGIN - RIGHTMARGIN, 365 - END - - ABOUTDLG, DIALOG - BEGIN - RIGHTMARGIN, 208 - END - - DLG_CFG_MACHINE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 -#ifdef USE_DYNAREC - BOTTOMMARGIN, 87 -#else - BOTTOMMARGIN, 72 -#endif - END - - DLG_CFG_VIDEO, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 38 - END - - DLG_CFG_INPUT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 58 - END - - DLG_CFG_SOUND, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 109 - END - - DLG_CFG_NETWORK, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 56 - END - - DLG_CFG_PORTS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 48 - END - - DLG_CFG_PERIPHERALS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 85 - END - - DLG_CFG_HARD_DISKS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 137 - END - - DLG_CFG_FLOPPY_DRIVES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 96 - END - - DLG_CFG_OTHER_REMOVABLE_DEVICES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 300 - TOPMARGIN, 7 - BOTTOMMARGIN, 214 - END -END -#endif // APSTUDIO_INVOKED - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION EMU_VERSION_MAJ,EMU_VERSION_MIN,EMU_VERSION_PATCH,EMU_BUILD_NUM - PRODUCTVERSION EMU_VERSION_MAJ,EMU_VERSION_MIN,EMU_VERSION_PATCH,EMU_BUILD_NUM - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", EMU_NAME "\0" - VALUE "FileDescription", EMU_NAME "\0" - VALUE "FileVersion", EMU_VERSION "\0" - VALUE "InternalName", EMU_NAME "\0" - VALUE "LegalCopyright", "Copyright \xa9 2007-" COPYRIGHT_YEAR " " EMU_NAME " contributors\0" - VALUE "OriginalFilename", EMU_NAME ".exe\0" - VALUE "ProductName", EMU_NAME "\0" - VALUE "ProductVersion", EMU_VERSION "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - -#endif - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - - -#include "languages/zh-CN.rc" -#include "languages/cs-CZ.rc" -#include "languages/de-DE.rc" -#include "languages/en-US.rc" -#include "languages/en-GB.rc" -#include "languages/fr-FR.rc" -#include "languages/hr-HR.rc" -#include "languages/fi-FI.rc" -#include "languages/hu-HU.rc" -#include "languages/it-IT.rc" -#include "languages/ja-JP.rc" -#include "languages/ko-KR.rc" -#include "languages/pl-PL.rc" -#include "languages/pt-BR.rc" -#include "languages/pt-PT.rc" -#include "languages/ru-RU.rc" -#include "languages/sl-SI.rc" -#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 deleted file mode 100644 index 604ba9bb0..000000000 --- a/src/win/CMakeLists.txt +++ /dev/null @@ -1,62 +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. -# Copyright 2021-2022 Jasmine Iwanek. -# - -enable_language(RC) - -add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.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 - win_jsconf.c win_media_menu.c win_preferences.c glad.c win_opengl.c - win_opengl_glslp.c win_toolbar.c 86Box.rc) - -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)) - # 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 86Box.rc PROPERTY COMPILE_DEFINITIONS NO_INCLUDE_MANIFEST) - target_sources(86Box PRIVATE 86Box.manifest) -endif() - -if(NOT MINGW) - # Append null to resource strings (fixes file dialogs) - set_property(SOURCE 86Box.rc PROPERTY COMPILE_FLAGS -n) - - # `opendir` is only included in MinGW, so include an implementation - # for other builds. - target_sources(plat PRIVATE win_opendir.c) -endif() - -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_link_libraries(86Box advapi32 comctl32 comdlg32 gdi32 shell32 iphlpapi - dxguid imm32 hid setupapi uxtheme version winmm psapi ws2_32) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw deleted file mode 100644 index 022a639f2..000000000 --- a/src/win/Makefile.mingw +++ /dev/null @@ -1,985 +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. -# -# Makefile for Win32 (MinGW32) environment. -# -# Authors: Miran Grca, -# Fred N. van Kempen, -# - -# Various compile-time options. -ifndef STUFF - STUFF := -endif - -# Add feature selections here. -ifndef EXTRAS - EXTRAS := -endif - -ifndef DEV_BUILD - DEV_BUILD := n -endif - -ifeq ($(DEV_BUILD), y) - ifndef DEBUG - DEBUG := y - endif - ifndef GDBSTUB - GDBSTUB := n - endif - ifndef DEV_BRANCH - DEV_BRANCH := y - endif - ifndef AMD_K5 - AMD_K5 := y - endif - ifndef AN430TX - AN430TX := y - endif - ifndef CYRIX_6X86 - CYRIX_6X86 := y - endif - ifndef DESKPRO386 - DESKPRO386 := y - endif - ifndef GUSMAX - GUSMAX := y - endif - ifndef ISAMEM_RAMPAGE - ISAMEM_RAMPAGE := y - endif - ifndef ISAMEM_IAB - ISAMEM_IAB := y - endif - ifndef ISAMEM_BRAT - ISAMEM_BRAT := y - endif - ifndef LASERXT - LASERXT := y - endif - ifndef MGA - MGA := y - endif - ifndef OLIVETTI - 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 - endif -else - ifndef DEBUG - DEBUG := n - endif - ifndef GDBSTUB - GDBSTUB := n - endif - ifndef DEV_BRANCH - DEV_BRANCH := n - endif - ifndef AMD_K5 - AMD_K5 := n - endif - ifndef AN430TX - AN430TX := n - endif - ifndef CYRIX_6X86 - CYRIX_6X86 := n - endif - ifndef DESKPRO386 - DESKPRO386 := n - endif - ifndef GUSMAX - GUSMAX := n - endif - ifndef ISAMEM_RAMPAGE - ISAMEM_RAMPAGE := n - endif - ifndef ISAMEM_IAB - ISAMEM_IAB := n - endif - ifndef ISAMEM_BRAT - ISAMEM_BRAT := n - endif - ifndef LASERXT - LASERXT := n - endif - ifndef MGA - MGA := n - endif - ifndef OLIVETTI - 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 - endif -endif - -# Defaults for several build options (possibly defined in a chained file.) -ifndef AUTODEP - AUTODEP := n -endif -ifndef OPTIM - OPTIM := n -endif -ifndef RELEASE - RELEASE := n -endif -ifndef X64 - X64 := n -endif -ifndef ARM - ARM := n -endif -ifndef ARM64 - ARM64 := n -endif -ifndef DINPUT - DINPUT := n -endif -ifndef FAUDIO - FAUDIO := n -endif -ifndef OPENAL - OPENAL := y -endif -ifndef FLUIDSYNTH - FLUIDSYNTH := y -endif -ifndef MUNT - MUNT := y -endif -ifndef VNC - VNC := n -endif -ifndef NEW_DYNAREC - NEW_DYNAREC := n -endif -ifndef DYNAREC - DYNAREC := y -endif -ifndef CPPTHREADS - 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 - endif - endif - ifeq ($(ARM64), y) - ifeq ($(NEW_DYNAREC), n) - DYNAREC := n - endif - endif -endif - - -# Path to the dynamic recompiler code. -ifeq ($(NEW_DYNAREC), y) - CODEGEN := codegen_new -else - CODEGEN := codegen -endif - - -# Name of the executable. -PROG := 86Box - - -######################################################################### -# Nothing should need changing from here on.. # -######################################################################### -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- -else - 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 -else - CPP := ${TOOL_PREFIX}g++ - CC := ${TOOL_PREFIX}gcc -endif - -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 -ifdef EXFLAGS - OPTS += $(EXFLAGS) -endif -ifdef EXINC - OPTS += -I$(EXINC) -endif -ifeq ($(OPTIM), y) - DFLAGS := -march=native -else - ifeq ($(X64), y) - DFLAGS := - else - DFLAGS := -march=i686 - endif -endif -ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG - AOPTIM := - ifndef COPTIM - COPTIM := -Og - endif - ifndef CXXOPTIM - ifeq ($(CLANG), y) - CXXOPTIM := -Os - else - CXXOPTIM := -Og - endif - endif -else - DFLAGS += -g0 - ifeq ($(OPTIM), y) - AOPTIM := -mtune=native - ifndef COPTIM - 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 - endif - ifndef CXXOPTIM - ifeq ($(CLANG), y) - CXXOPTIM := -Os - else - CXXOPTIM := -O3 - endif - endif - endif -endif -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 -endif -ifeq ($(ARM64), y) - DFLAGS := -march=armv8-a - AOPTIM := - AFLAGS := -mfloat-abi=hard -endif -RFLAGS := --input-format=rc -O coff -Iinclude -Iinclude_make -ifeq ($(RELEASE), y) - OPTS += -DRELEASE_BUILD - RFLAGS += -DRELEASE_BUILD -endif - - -# Optional modules. -ifeq ($(DYNAREC), y) - OPTS += -DUSE_DYNAREC - RFLAGS += -DUSE_DYNAREC - - ifeq ($(NEW_DYNAREC), y) - 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 - else ifeq ($(ARM64), y) - 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 - 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 - 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) - else - ifeq ($(X64), y) - PLATCG := codegen_x86-64.o codegen_accumulate_x86-64.o - else - PLATCG := codegen_x86.o codegen_accumulate_x86.o - endif - - 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 -else - ifeq ($(NEW_DYNAREC), y) - OPTS += -DUSE_NEW_DYNAREC - RFLAGS += -DUSE_NEW_DYNAREC - endif -endif - -ifeq ($(FLUIDSYNTH), y) - OPTS += -DUSE_FLUIDSYNTH - FSYNTHOBJ := midi_fluidsynth.o -endif - -ifeq ($(MUNT), y) - 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 -else - THREADOBJ := win_thread.o -endif - -ifeq ($(VNC), y) - OPTS += -DUSE_VNC - RFLAGS += -DUSE_VNC - ifneq ($(VNC_PATH), ) - OPTS += -I$(VNC_PATH)\INCLUDE - VNCLIB := -L$(VNC_PATH)\LIB - endif - VNCLIB += -lvncserver.dll - VNCOBJ := vnc.o vnc_keymap.o -endif - -ifeq ($(MINITRACE), y) - 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 := - - 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 ($(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 - -# Add freetyp2 references through pkgconfig -CFLAGS := $(CFLAGS) `pkg-config --cflags freetype2` - -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. # -######################################################################### -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 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 \ - 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 \ - 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_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 - -KBCOBJ := kbc_at.o kbc_at_dev.o \ - keyboard_at.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 - -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_it86x1f.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 - -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 - -GAMEOBJ := gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.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 - -MINIVHDOBJ := cwalk.o xml2_encoding.o convert.o \ - create.o minivhd_io.o manage.o struct_rw.o minivhd_util.o - -CDROMOBJ := cdrom.o \ - cdrom_image_backend.o cdrom_image_viso.o cdrom_image.o cdrom_mitsumi.o - -ZIPOBJ := zip.o - -MOOBJ := mo.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 - -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 \ - net_eeprom_nmc93cxx.o \ - net_tulip.o \ - net_rtl8139.o \ - net_l80225.o - -PRINTOBJ := png.o prt_cpmap.o \ - prt_escp.o prt_text.o prt_ps.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 \ - midi_opl4.o \ - midi_opl4_yrw801.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 - -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 - -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 - -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 -else - PLATOBJ += win_joystick_rawinput.o -endif - -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) -endif - -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 -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 -ifneq ($(X64), y) - ifneq ($(ARM64), y) - LIBS += -Wl,--large-address-aware - endif -endif -ifeq ($(ARM64), y) - LIBS += -lgcc -endif -ifeq ($(DINPUT), y) - LIBS += -ldinput8 -endif - -LIBS += -static - -# Build module rules. -ifeq ($(AUTODEP), y) -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) $(DEPS) -c $< -else -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CXXFLAGS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CXXFLAGS) -c $< - -%.d: %.c $(wildcard $*.d) - @echo $< - @$(CC) $(CFLAGS) $(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 -endif - -# Suppress false positive warnings in vid_voodoo_codegen_x86[-64].h -# that cause ~3000 lines to be output into the logs each time. -ifneq ($(CLANG), y) - $(VOODOOOBJ): CFLAGS += -Wstringop-overflow=0 -endif - -all: $(PROG).exe - - -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 -ifneq ($(DEBUG), y) - @$(STRIP) $(PROG).exe -endif - -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 -ifneq ($(DEBUG), y) - @$(STRIP) pcap_if.exe -endif - -hello.exe: hello.o - $(CXX) $(LDFLAGS) -o hello.exe hello.o $(LIBS) -ifneq ($(DEBUG), y) - @$(STRIP) hello.exe -endif - - -clean: - @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 - -ifneq ($(AUTODEP), y) -depclean: - @-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) - -$(DEPFILE): -endif - - -# Module dependencies. -ifeq ($(AUTODEP), y) -#-include $(OBJ:%.o=%.d) (better, but sloooowwwww) --include *.d -else -include $(wildcard $(DEPFILE)) -endif - - -# End of Makefile.mingw. diff --git a/src/win/glad.c b/src/win/glad.c deleted file mode 100644 index 7c282ebee..000000000 --- a/src/win/glad.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - - OpenGL loader generated by glad 0.1.36 on Sat Jan 7 18:24:33 2023. - - Language/Generator: C/C++ - Specification: gl - APIs: gl=3.0 - Profile: core - Extensions: - GL_ARB_buffer_storage, - GL_ARB_debug_output, - GL_ARB_sync - Loader: True - Local files: False - Omit khrplatform: False - Reproducible: False - - Commandline: - --profile="core" --api="gl=3.0" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_debug_output,GL_ARB_sync" - Online: - https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D3.0&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_debug_output&extensions=GL_ARB_sync -*/ - -#include -#include -#include -#include - -static void *get_proc(const char *namez); - -#if defined(_WIN32) || defined(__CYGWIN__) -# ifndef _WINDOWS_ -# undef APIENTRY -# endif -# include -static HMODULE libGL; - -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 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 - libGL = LoadLibraryW(L"opengl32.dll"); - if (libGL != NULL) { - void (*tmp)(void); - tmp = (void (*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); - gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; - return gladGetProcAddressPtr != NULL; - } -# endif - - return 0; -} - -static void -close_gl(void) -{ - if (libGL != NULL) { - FreeLibrary((HMODULE) libGL); - libGL = NULL; - } -} -#else -# include -static void *libGL; - -# if !defined(__APPLE__) && !defined(__HAIKU__) -typedef void *(APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char *); -static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; -# endif - -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 - - unsigned int index = 0; - 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__) - return 1; -# else - gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE) dlsym(libGL, - "glXGetProcAddressARB"); - return gladGetProcAddressPtr != NULL; -# endif - } - } - - return 0; -} - -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; - -#if !defined(__APPLE__) && !defined(__HAIKU__) - if (gladGetProcAddressPtr != NULL) { - result = gladGetProcAddressPtr(namez); - } -#endif - if (result == NULL) { -#if defined(_WIN32) || defined(__CYGWIN__) - result = (void *) GetProcAddress((HMODULE) libGL, namez); -#else - result = dlsym(libGL, namez); -#endif - } - - return result; -} - -int -gladLoadGL(void) -{ - int status = 0; - - if (open_gl()) { - status = gladLoadGLLoader(&get_proc); - close_gl(); - } - - return status; -} - -struct gladGLversionStruct GLVersion = { 0, 0 }; - -#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) -# 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 int -get_exts(void) -{ -#ifdef _GLAD_IS_SOME_NEW_VERSION - if (max_loaded_major < 3) { -#endif - exts = (const char *) glGetString(GL_EXTENSIONS); -#ifdef _GLAD_IS_SOME_NEW_VERSION - } else { - unsigned int index; - - 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)); - } - - 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); - - 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; - } - } -#endif - return 1; -} - -static void -free_exts(void) -{ - if (exts_i != NULL) { - int index; - for (index = 0; index < num_exts_i; index++) { - free((char *) exts_i[index]); - } - free((void *) exts_i); - exts_i = NULL; - } -} - -static int -has_ext(const char *ext) -{ -#ifdef _GLAD_IS_SOME_NEW_VERSION - if (max_loaded_major < 3) { -#endif - const char *extensions; - const char *loc; - const char *terminator; - extensions = exts; - if (extensions == NULL || ext == NULL) { - return 0; - } - - while (1) { - loc = strstr(extensions, ext); - if (loc == NULL) { - return 0; - } - - terminator = loc + strlen(ext); - if ((loc == extensions || *(loc - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) { - return 1; - } - extensions = terminator; - } -#ifdef _GLAD_IS_SOME_NEW_VERSION - } else { - int 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) { - return 1; - } - } - } -#endif - - 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; -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"); -} -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_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_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_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_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_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 void -find_coreGL(void) -{ - - /* Thank you @elmindreda - * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176 - * https://github.com/glfw/glfw/blob/master/src/context.c#L36 - */ - int i, major, minor; - - const char *version; - const char *prefixes[] = { - "OpenGL ES-CM ", - "OpenGL ES-CL ", - "OpenGL ES ", - NULL - }; - - version = (const char *) glGetString(GL_VERSION); - if (!version) - return; - - for (i = 0; prefixes[i]; i++) { - const size_t length = strlen(prefixes[i]); - if (strncmp(version, prefixes[i], length) == 0) { - version += length; - break; - } - } - -/* PR #18 */ -#ifdef _MSC_VER - sscanf_s(version, "%d.%d", &major, &minor); -#else - 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; - } -} - -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; -} diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc deleted file mode 100644 index 6c0982c5c..000000000 --- a/src/win/languages/cs-CZ.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Czech (Czech Republic) resources - -#ifdef _WIN32 -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "P&ozastavit", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Š&kálování HiDPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 - END - POPUP "Nastavení pro E&GA a (S)VGA" - BEGIN - 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 - 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 - 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 - END - MENUITEM "&Média", IDM_MEDIA - POPUP "&Nástroje" - BEGIN - 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 SEPARATOR - MENUITEM "&Předvolby...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Povolit integraci s &Discordem", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "Ná&pověda" - BEGIN - MENUITEM "&Dokumentace", IDM_DOCS - MENUITEM "&O programu 86Box", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Vyjmout", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xportovat do 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Ztišit", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Vyjmout", IDM_CDROM_EMPTY - MENUITEM "&Načíst znova předchozí obraz", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Obraz...", IDM_CDROM_IMAGE - MENUITEM "&Složka...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Vyjmout", IDM_ZIP_EJECT - MENUITEM "&Načíst znova předchozí obraz", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Vyjmout", IDM_MO_EJECT - MENUITEM "&Načíst znova předchozí obraz", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Cílová snímková frekvence" - BEGIN - MENUITEM "&Synchronizovat s obrazem", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Zvolit shader...", IDM_VID_GL_SHADER - MENUITEM "&Odebrat shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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č." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Vypnuto" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 031f935cd..000000000 --- a/src/win/languages/de-DE.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// German (de-DE) resources - -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Hi&DPI-Skalierung", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Quadratische Pixel (Seitenverhältnis beibehalten)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer-Skalierung", IDM_VID_FS_INT - END - POPUP "E&GA/(S)VGA-Einstellungen" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Werkzeuge" - BEGIN - MENUITEM "&Optionen...", IDM_CONFIG - MENUITEM "&Statusleistenicons aktualisieren", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "S&creenshot aufnehmen\tStrg+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Einstellungen...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "&Discord-Integration aktivieren", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Hilfe" - BEGIN - MENUITEM "&Dokumentation...", IDM_DOCS - MENUITEM "&Über 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "A&uswerfen", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Cartridgeimage...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "A&uswerfen", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&In das 86F-Format e&xportieren...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Auswerfen", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Stummschalten", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "L&eer", IDM_CDROM_EMPTY - MENUITEM "&Voriges Image neu laden", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Image...", IDM_CDROM_IMAGE - MENUITEM "&Verzeichnis...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "A&uswerfen", IDM_ZIP_EJECT - MENUITEM "&Voriges Image neu laden", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Auswerfen", IDM_MO_EJECT - MENUITEM "&Bestehendes Image erneut laden", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Ziel&framerate" - BEGIN - MENUITEM "&Mit Videoausgabe synchronisieren", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Shader auswählen...", IDM_VID_GL_SHADER - MENUITEM "&Shader entfernen", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Deaktiviert" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#define IDS_LANG_ENUS IDS_7168 - -// German (de-DE) resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc deleted file mode 100644 index 1daf46b4c..000000000 --- a/src/win/languages/dialogs.rc +++ /dev/null @@ -1,1143 +0,0 @@ -#define CFG_CHECKBOX_PRI_WIDTH 94 -#define CFG_CHECKBOX_HEIGHT 10 -#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 -#define CFG_COMBO_BOX_LEFT CFG_PANE_LTEXT_PRI_WIDTH + 10 -#define CFG_COMBO_BTN_LEFT CFG_COMBO_BOX_LEFT + CFG_COMBO_BTN_WIDTH + 8 -#define CFG_COMBO_HEIGHT 120 -#define CFG_LIST_WIDTH 123 -#define CFG_LIST_HEIGHT 212 -#define CFG_PANE_TOP 0 -#define CFG_PANE_LEFT CFG_LIST_WIDTH + 8 -#define CFG_PANE_WIDTH CFG_COMBO_BOX_LEFT + CFG_COMBO_NOBTN_WIDTH -#define CFG_PANE_HEIGHT 221 -#define CFG_HMARGIN 7 -#define CFG_VMARGIN 9 -#define CFG_SYSLISTVIEW32_WIDTH CFG_PANE_WIDTH - 7 - -DLG_PREFERENCES DIALOG DISCARDABLE 0, 0, 240, 118 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_PREFERENCES -FONT FONT_SIZE, FONT_NAME -BEGIN - DEFPUSHBUTTON STR_OK, IDOK, - 123, 97, 50, CFG_BTN_HEIGHT - - PUSHBUTTON STR_CANCEL, IDCANCEL, - 179, 97, 50, CFG_BTN_HEIGHT - - LTEXT STR_LANGUAGE, - 2000, 13, 8, 100, 8 - COMBOBOX IDC_COMBO_LANG, - 13, 18, 213, 22, - CBS_DROPDOWNLIST | CBS_HASSTRINGS - PUSHBUTTON STR_DEFAULT, IDC_BUTTON_DEFAULT, - 162, 32, 60, CFG_BTN_HEIGHT - - LTEXT STR_ICONSET, - 2001, 13, 40, 100, 8 - COMBOBOX IDC_COMBO_ICON, - 13, 50, 213, 22, - CBS_DROPDOWNLIST | CBS_HASSTRINGS - PUSHBUTTON STR_DEFAULT, IDC_BUTTON_DEFICON, - 162, 64, 60, CFG_BTN_HEIGHT - - AUTOCHECKBOX STR_GLOBAL, IDC_CHECKBOX_GLOBAL, - 13, 82, 217, 8, - WS_DISABLED -END - -DLG_SND_GAIN DIALOG DISCARDABLE 0, 0, 113, 136 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_SND_GAIN -FONT FONT_SIZE, FONT_NAME -BEGIN - DEFPUSHBUTTON STR_OK, IDOK, - 57, 7, 50, CFG_BTN_HEIGHT - - PUSHBUTTON STR_CANCEL, IDCANCEL, - 57, 24, 50, CFG_BTN_HEIGHT - - CONTROL STR_GAIN, IDC_SLIDER_GAIN, - "msctls_trackbar32", - TBS_VERT | TBS_BOTH | TBS_AUTOTICKS | WS_TABSTOP, - 15, 20, 20, 109 - CTEXT STR_GAIN,IDT_GAIN, - 10, 7, 32, 9, - SS_CENTERIMAGE -END - -DLG_NEW_FLOPPY DIALOG DISCARDABLE 0, 0, 226, 86 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_NEW_FLOPPY -FONT FONT_SIZE, FONT_NAME -BEGIN - DEFPUSHBUTTON STR_OK, IDOK, - 104, 65, 50, CFG_BTN_HEIGHT - - PUSHBUTTON STR_CANCEL, IDCANCEL, - 162, 65, 50, CFG_BTN_HEIGHT - - LTEXT STR_FILE_NAME, IDT_FLP_FILE_NAME, - 7, 6, 44, 12, - SS_CENTERIMAGE - EDITTEXT IDC_EDIT_FILE_NAME, - 53, 5, 150, 14, - ES_AUTOHSCROLL | ES_READONLY - - LTEXT STR_DISK_SIZE, IDT_FLP_DISK_SIZE, - 7, 25, 44, 12, - SS_CENTERIMAGE - COMBOBOX IDC_COMBO_DISK_SIZE, - 53, 25, 166, 14, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "...", IDC_CFILE, - 206, 5, 13, CFG_BTN_HEIGHT - - LTEXT STR_RPM_MODE, IDT_FLP_RPM_MODE, - 7, 45, 44, 12, - SS_CENTERIMAGE - COMBOBOX IDC_COMBO_RPM_MODE, - 53, 45, 166, 14, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_PROGRESS, IDT_FLP_PROGRESS, - 7, 45, 44, 12, - SS_CENTERIMAGE - CONTROL "IMGCreateProgress", IDC_PBAR_IMG_CREATE, - "msctls_progress32", - PBS_SMOOTH | WS_BORDER, - 53, 45, 166, 14 -END - -DLG_SPECIFY_DIM DIALOG DISCARDABLE 0, 0, 175, 66 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_SPECIFY_DIM -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_WIDTH, IDT_WIDTH, - 7, 9, 24, 12 - EDITTEXT IDC_EDIT_WIDTH, - 33, 7, 45, 12, - ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_WIDTHSPIN, - "msctls_updown32", - UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS, - 76, 6, 12, 12 - - LTEXT STR_HEIGHT, IDT_HEIGHT, - 97, 9, 24, 12 - EDITTEXT IDC_EDIT_HEIGHT, - 123, 7, 45, 12, - ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_HEIGHTSPIN, - "msctls_updown32", - UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS, - 166, 6, 12, 12 - - CONTROL STR_LOCK_TO_SIZE,IDC_CHECK_LOCK_SIZE, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 7, 26, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - DEFPUSHBUTTON STR_OK,IDOK, - 30, 45, 50, CFG_BTN_HEIGHT - - PUSHBUTTON STR_CANCEL, IDCANCEL, - 99, 45, 50, CFG_BTN_HEIGHT -END - -DLG_CONFIG DIALOG DISCARDABLE 0, 0, CFG_LIST_WIDTH + CFG_PANE_WIDTH + 18, 256 -STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_CONFIG -FONT FONT_SIZE, FONT_NAME -BEGIN - DEFPUSHBUTTON STR_OK, IDOK, - CFG_LIST_WIDTH + CFG_PANE_WIDTH - 108, 235, 50, CFG_BTN_HEIGHT - - PUSHBUTTON STR_CANCEL, IDCANCEL, - CFG_LIST_WIDTH + CFG_PANE_WIDTH - 48 , 235, 50, CFG_BTN_HEIGHT - - CONTROL "List2", IDC_SETTINGSCATLIST, - "SysListView32", - LVS_REPORT | LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, CFG_VMARGIN, CFG_LIST_WIDTH, CFG_LIST_HEIGHT - - CONTROL "",-1, - "Static", SS_BLACKFRAME | SS_SUNKEN, - 1, 226, CFG_LIST_WIDTH + CFG_PANE_WIDTH + 16, 1 -END - -DLG_CFG_MACHINE DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_MACHINE_TYPE,IDT_MACHINE_TYPE, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MACHINE_TYPE, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_MACHINE, IDT_MACHINE, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MACHINE, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MACHINE, - CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_CPU_TYPE, IDT_CPU_TYPE, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CPU_TYPE, - CFG_COMBO_BOX_LEFT, 45, 110, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CPU_SPEED, IDT_CPU_SPEED, - 216, 47, 34, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CPU_SPEED, - 252, 45, 109, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_FPU,IDT_FPU, - CFG_HMARGIN, 66, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_FPU, - CFG_COMBO_BOX_LEFT, 64, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_WAIT_STATES, IDT_WAIT_STATES, - CFG_HMARGIN, 85, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_WS, - CFG_COMBO_BOX_LEFT, 83, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_MEMORY, IDT_MEMORY, - CFG_HMARGIN, 104, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - EDITTEXT IDC_MEMTEXT, - CFG_COMBO_BOX_LEFT, 102, 45, 12, - ES_AUTOHSCROLL | ES_NUMBER - CONTROL "", IDC_MEMSPIN, - "msctls_updown32", - UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS, - 138, 101, 12, 12 - LTEXT STR_MB, IDT_MB, - 148, 104, 12, CFG_PANE_LTEXT_HEIGHT - -#ifdef USE_DYNAREC - CONTROL STR_DYNAREC, IDC_CHECK_DYNAREC, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 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, 150, 110, 56 - - CONTROL STR_DISABLED, IDC_RADIO_TS_DISABLED, - "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, - 14, 162, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_ENABLED_LOCAL, IDC_RADIO_TS_LOCAL, - "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, - 14, 176, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_ENABLED_UTC, IDC_RADIO_TS_UTC, - "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, - 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 -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_VIDEO, IDT_VIDEO, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_VIDEO, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - 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, - CFG_HMARGIN, 47, 199, CFG_CHECKBOX_HEIGHT - PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_VOODOO, - 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 -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_MOUSE, IDT_MOUSE, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MOUSE, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MOUSE, - CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_JOYSTICK, IDT_JOYSTICK, - CFG_HMARGIN, 27, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_JOYSTICK, - CFG_COMBO_BOX_LEFT, 25, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - PUSHBUTTON STR_JOY1, IDC_JOY1, - CFG_HMARGIN, 44, 84, CFG_BTN_HEIGHT - - PUSHBUTTON STR_JOY2, IDC_JOY2, - 96, 44, 84, CFG_BTN_HEIGHT - - PUSHBUTTON STR_JOY3, IDC_JOY3, - 187, 44, 84, CFG_BTN_HEIGHT - - PUSHBUTTON STR_JOY4, IDC_JOY4, - 277, 44, 84, CFG_BTN_HEIGHT -END - -DLG_CFG_SOUND DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_SOUND1, IDT_SOUND1, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - 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_SND1, - CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_SOUND2, IDT_SOUND2, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - 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, 85, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_MIDI_IN, IDT_MIDI_IN, - CFG_HMARGIN, 108, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MIDI_IN, - 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, 105, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_MPU401,IDC_CHECK_MPU401, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 126, 199, CFG_CHECKBOX_HEIGHT - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_MPU401, - CFG_COMBO_BTN_LEFT, 125, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_FLOAT, IDC_CHECK_FLOAT, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 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 -STYLE DS_CONTROL | WS_CHILD -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 - LTEXT STR_PCAP, IDT_PCAP, - 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 - - COMBOBOX IDC_COMBO_PCAP1, - CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 28, 110, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - 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 -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN -/* - LTEXT STR_COM1, IDT_COM1, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_COM1, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_COM2, IDT_COM2, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_COM2, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_COM3, IDT_COM3, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_COM3, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_COM4, IDT_COM4, - CFG_HMARGIN, 66, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_COM4, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP -*/ - - LTEXT STR_LPT1, IDT_LPT1, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_LPT1, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_LPT2, IDT_LPT2, - CFG_HMARGIN, 24, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_LPT2, - 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, 39, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_LPT3, - 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, 54, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_LPT4, - 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, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_SERIAL2, IDC_CHECK_SERIAL2, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_SERIAL3, IDC_CHECK_SERIAL3, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_SERIAL4, IDC_CHECK_SERIAL4, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_PARALLEL1, IDC_CHECK_PARALLEL1, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_PARALLEL2, IDC_CHECK_PARALLEL2, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_PARALLEL3, IDC_CHECK_PARALLEL3, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 167, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_PARALLEL4, IDC_CHECK_PARALLEL4, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 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 -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_HDC, IDT_HDC, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_HDC, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_HDC, - CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_FDC, IDT_FDC, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_FDC, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_FDC, - CFG_COMBO_BTN_LEFT, 25, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_IDE_TER,IDC_CHECK_IDE_TER, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 47, 239, 10 - PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_IDE_TER, - CFG_COMBO_BTN_LEFT, 45, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_IDE_QUA, IDC_CHECK_IDE_QUA, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 66, 239, 10 - PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_IDE_QUA, - CFG_COMBO_BTN_LEFT, 64, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - GROUPBOX STR_SCSI, IDC_GROUP_SCSI, - CFG_HMARGIN, 85, CFG_SYSLISTVIEW32_WIDTH, 93 - - LTEXT STR_SCSI_1, IDT_SCSI_1, - 16, 102, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_SCSI_1, - CFG_COMBO_BOX_LEFT, 100, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SCSI_1, - CFG_COMBO_BTN_LEFT - 10, 99, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_SCSI_2, IDT_SCSI_2, - 16, 121, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_SCSI_2, - CFG_COMBO_BOX_LEFT, 119, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SCSI_2, - CFG_COMBO_BTN_LEFT - 10, 118, CFG_BTN_WIDTH,CFG_BTN_HEIGHT - - LTEXT STR_SCSI_3,IDT_SCSI_3, - 16, 140, 64, 10 - COMBOBOX IDC_COMBO_SCSI_3, - CFG_COMBO_BOX_LEFT, 138, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SCSI_3, - CFG_COMBO_BTN_LEFT - 10, 137, CFG_BTN_WIDTH,CFG_BTN_HEIGHT - - LTEXT STR_SCSI_4, IDT_SCSI_4, - 16, 159, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_SCSI_4, - CFG_COMBO_BOX_LEFT, 157, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SCSI_4, - CFG_COMBO_BTN_LEFT - 10, 156, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_CASSETTE,IDC_CHECK_CASSETTE, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 185, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT -END - -DLG_CFG_HARD_DISKS DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_HDD, IDT_HDD, - CFG_HMARGIN, CFG_VMARGIN, 258, CFG_PANE_LTEXT_HEIGHT - CONTROL "List1", IDC_LIST_HARD_DISKS, - "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, 18, CFG_SYSLISTVIEW32_WIDTH, 162 - - LTEXT STR_BUS,IDT_BUS, - CFG_HMARGIN, 188, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_HD_BUS, - 33, 186, 40, 12,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CHANNEL, IDT_CHANNEL, - 91, 188, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_HD_CHANNEL, - 131, 186, 40, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBO_HD_CHANNEL_IDE, - 131, 186, 40, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ID, IDT_ID, - 91, 188, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_HD_ID, - 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, - CFG_HMARGIN, 207, 112, CFG_BTN_HEIGHT - - PUSHBUTTON STR_EXISTING, IDC_BUTTON_HDD_ADD, - 128, 207, 112, CFG_BTN_HEIGHT - - PUSHBUTTON STR_REMOVE, IDC_BUTTON_HDD_REMOVE, - 249, 207, 112, CFG_BTN_HEIGHT - -END - -DLG_CFG_HARD_DISKS_ADD DIALOG DISCARDABLE 0, 0, 239, 151 -STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Add Hard Disk" -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_FILE_NAME, IDT_FILE_NAME, - 7, 7, 204, 12 - EDITTEXT IDC_EDIT_HD_FILE_NAME, - 7, 18, 173, 12 - PUSHBUTTON STR_SPECIFY, IDC_CFILE, - 187, 18, 44, CFG_BTN_HEIGHT - - LTEXT STR_CYLS, IDT_CYLS, - 7, 37, 42, 12 - EDITTEXT IDC_EDIT_HD_CYL, - 50, 36, 28, 12 - - LTEXT STR_HEADS, IDT_HEADS, - 86, 37, 29, 12 - EDITTEXT IDC_EDIT_HD_HPC, - 122, 36, 28, 12 - - LTEXT STR_SECTORS, IDT_SECTORS, - 164, 37, 33, 12 - EDITTEXT IDC_EDIT_HD_SPT, - 197, 36, 28, 12 - - LTEXT STR_SIZE_MB, IDT_SIZE_MB, - 7, 56, 48, 12 - EDITTEXT IDC_EDIT_HD_SIZE, - 50, 54, 28, 12 - - LTEXT STR_TYPE, IDT_TYPE, - 86, 56, 24, 12 - COMBOBOX IDC_COMBO_HD_TYPE, - 133, 54, 98, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_BUS,IDT_BUS, - 7, 75, 24, 12 - COMBOBOX IDC_COMBO_HD_BUS, - 43, 73, 58, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CHANNEL, IDT_CHANNEL, - 109, 75, 34, 12 - COMBOBOX IDC_COMBO_HD_CHANNEL, - 144, 73, 87, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBO_HD_CHANNEL_IDE, - 144, 73, 87, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ID, IDT_ID, - 109, 75, 34, 12 - COMBOBOX IDC_COMBO_HD_ID, - 144, 73, 87, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_IMG_FORMAT, IDT_IMG_FORMAT, - 7, 94, 70, 12 - COMBOBOX IDC_COMBO_HD_IMG_FORMAT, - 78, 92, 153, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_BLOCK_SIZE, IDT_BLOCK_SIZE, - 7, 113, 50, 12 - COMBOBOX IDC_COMBO_HD_BLOCK_SIZE, - 58, 111, 153, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_PROGRESS, IDT_PROGRESS, - 7, 7, 204, 12 - CONTROL "IMGCreateProgress", IDC_PBAR_IMG_CREATE, - "msctls_progress32", - PBS_SMOOTH | WS_BORDER, - 7, 16, 204, 12 - - DEFPUSHBUTTON STR_OK, IDOK, - 75, 129, 50, CFG_BTN_HEIGHT - PUSHBUTTON STR_CANCEL, IDCANCEL, - 132, 129, 50, CFG_BTN_HEIGHT -END - -DLG_CFG_FLOPPY_AND_CDROM_DRIVES DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_FLOPPY_DRIVES, IDT_FLOPPY_DRIVES, - CFG_HMARGIN, CFG_VMARGIN, 258, CFG_PANE_LTEXT_HEIGHT - CONTROL "List1", IDC_LIST_FLOPPY_DRIVES, - "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, 18, CFG_SYSLISTVIEW32_WIDTH, 60 - - LTEXT STR_TYPE, IDT_FDD_TYPE, - CFG_HMARGIN, 87, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_FD_TYPE, - 33, 85, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - CONTROL STR_TURBO, IDC_CHECKTURBO, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 186, 86, 84, CFG_CHECKBOX_HEIGHT - - CONTROL STR_CHECKBPB, IDC_CHECKBPB, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 272, 86, 84, CFG_CHECKBOX_HEIGHT - - LTEXT STR_CDROM_DRIVES, IDT_CD_DRIVES, - CFG_HMARGIN, 107, 258, CFG_PANE_LTEXT_HEIGHT - CONTROL "List1", IDC_LIST_CDROM_DRIVES, - "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, 117, CFG_SYSLISTVIEW32_WIDTH, 60 - - LTEXT STR_BUS, IDT_CD_BUS, - CFG_HMARGIN, 187, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CD_BUS, - 33, 185, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CHANNEL, IDT_CD_CHANNEL, - 181, 187, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CD_CHANNEL_IDE, - 221, 185, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ID, IDT_CD_ID, - 181, 187, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CD_ID, - 221, 185, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CD_SPEED, IDT_CD_SPEED, - CFG_HMARGIN, 207, 34, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_CD_SPEED, - 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 -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - - LTEXT STR_MO_DRIVES, IDT_MO_DRIVES, - CFG_HMARGIN, CFG_VMARGIN, 258, CFG_PANE_LTEXT_HEIGHT - CONTROL "List1", IDC_LIST_MO_DRIVES, - "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, 17, CFG_SYSLISTVIEW32_WIDTH, 60 - - LTEXT STR_BUS, IDT_MO_BUS, - CFG_HMARGIN, 87, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MO_BUS, - 33, 85, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ID, IDT_MO_ID, - 181, 87, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MO_ID, - 221, 85, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CHANNEL, IDT_MO_CHANNEL, - 181, 87, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MO_CHANNEL_IDE, - 221, 85, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_TYPE, IDT_MO_TYPE, - CFG_HMARGIN, 107, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_MO_TYPE, - 33, 105, 328, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ZIP_DRIVES, IDT_ZIP_DRIVES, - CFG_HMARGIN, 127, 258, CFG_PANE_LTEXT_HEIGHT - CONTROL "List1", IDC_LIST_ZIP_DRIVES, - "SysListView32", - LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | - WS_BORDER | WS_TABSTOP, - CFG_HMARGIN, 137, CFG_SYSLISTVIEW32_WIDTH, 60 - - LTEXT STR_BUS, IDT_ZIP_BUS, - CFG_HMARGIN, 207, 24, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ZIP_BUS, - 33, 205, 140, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_CHANNEL, IDT_ZIP_CHANNEL, - 181, 207, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ZIP_CHANNEL_IDE, - 221, 205, 105, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT STR_ID, IDT_ZIP_ID, - 181, 207, 38, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ZIP_ID, - 221, 205, 105, 12, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - CONTROL STR_250, IDC_CHECK250, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 329, 206, 44, CFG_CHECKBOX_HEIGHT -END - -DLG_CFG_PERIPHERALS DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT -STYLE DS_CONTROL | WS_CHILD -FONT FONT_SIZE, FONT_NAME -BEGIN - LTEXT STR_ISARTC, IDT_ISARTC, - CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ISARTC, - CFG_COMBO_BOX_LEFT, 7,CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_ISARTC, - CFG_COMBO_BTN_LEFT, 6, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - GROUPBOX STR_ISAMEM, IDC_GROUP_ISAMEM, - CFG_HMARGIN, 28, CFG_SYSLISTVIEW32_WIDTH, 93 - - LTEXT STR_ISAMEM_1, IDT_ISAMEM_1, - 16, 45, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ISAMEM_1, - CFG_COMBO_BOX_LEFT, 43, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_ISAMEM_1, - CFG_COMBO_BTN_LEFT - 10, 42, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_ISAMEM_2,IDT_ISAMEM_2, - 16, 64, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ISAMEM_2, - CFG_COMBO_BOX_LEFT, 62, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_ISAMEM_2, - CFG_COMBO_BTN_LEFT - 10, 61, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_ISAMEM_3, IDT_ISAMEM_3, - 16, 83, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ISAMEM_3, - CFG_COMBO_BOX_LEFT, 81, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_ISAMEM_3, - CFG_COMBO_BTN_LEFT - 10, 80, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - LTEXT STR_ISAMEM_4, IDT_ISAMEM_4, - 16, 102, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_ISAMEM_4, - CFG_COMBO_BOX_LEFT, 100, CFG_COMBO_BTN_WIDTH - 10, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_ISAMEM_4, - CFG_COMBO_BTN_LEFT - 10, 99, CFG_BTN_WIDTH, CFG_BTN_HEIGHT - - CONTROL STR_BUGGER, IDC_CHECK_BUGGER, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 128, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT - - CONTROL STR_POSTCARD,IDC_CHECK_POSTCARD, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - CFG_HMARGIN, 146, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT -END - -#undef CFG_CHECKBOX_PRI_WIDTH -#undef CFG_CHECKBOX_HEIGHT -#undef CFG_BTN_WIDTH -#undef CFG_BTN_HEIGHT -#undef CFG_PANE_LTEXT_PRI_WIDTH -#undef CFG_PANE_LTEXT_HEIGHT -#undef CFG_COMBO_BTN_WIDTH -#undef CFG_COMBO_NOBTN_WIDTH -#undef CFG_COMBO_BOX_LEFT -#undef CFG_COMBO_BTN_LEFT -#undef CFG_COMBO_HEIGHT -#undef CFG_LIST_WIDTH -#undef CFG_LIST_HEIGHT -#undef CFG_PANE_TOP -#undef CFG_PANE_LEFT -#undef CFG_PANE_WIDTH -#undef CFG_PANE_HEIGHT -#undef CFG_HMARGIN -#undef CFG_VMARGIN -#undef CFG_SYSLISTVIEW32_WIDTH - - -#undef STR_PREFERENCES -#undef STR_SND_GAIN -#undef STR_NEW_FLOPPY -#undef STR_CONFIG -#undef STR_SPECIFY_DIM - -#undef STR_OK -#undef STR_CANCEL -#undef STR_GLOBAL -#undef STR_DEFAULT -#undef STR_LANGUAGE -#undef STR_ICONSET - -#undef STR_GAIN - -#undef STR_FILE_NAME -#undef STR_DISK_SIZE -#undef STR_RPM_MODE -#undef STR_PROGRESS - -#undef STR_WIDTH -#undef STR_HEIGHT -#undef STR_LOCK_TO_SIZE - -#undef STR_MACHINE_TYPE -#undef STR_MACHINE -#undef STR_CONFIGURE -#undef STR_CPU_TYPE -#undef STR_CPU_SPEED -#undef STR_FPU -#undef STR_WAIT_STATES -#undef STR_MB -#undef STR_MEMORY -#undef STR_TIME_SYNC -#undef STR_DISABLED -#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 -#undef STR_JOY1 -#undef STR_JOY2 -#undef STR_JOY3 -#undef STR_JOY4 - -#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_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 -#undef STR_COM3 -#undef STR_COM4 -#undef STR_LPT1 -#undef STR_LPT2 -#undef STR_LPT3 -#undef STR_LPT4 -#undef STR_SERIAL1 -#undef STR_SERIAL2 -#undef STR_SERIAL3 -#undef STR_SERIAL4 -#undef STR_PARALLEL1 -#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 -#undef STR_IDE_TER -#undef STR_IDE_QUA -#undef STR_SCSI -#undef STR_SCSI_1 -#undef STR_SCSI_2 -#undef STR_SCSI_3 -#undef STR_SCSI_4 -#undef STR_CASSETTE - -#undef STR_HDD -#undef STR_NEW -#undef STR_EXISTING -#undef STR_REMOVE -#undef STR_BUS -#undef STR_CHANNEL -#undef STR_ID -#undef STR_SPEED - -#undef STR_SPECIFY -#undef STR_SECTORS -#undef STR_HEADS -#undef STR_CYLS -#undef STR_SIZE_MB -#undef STR_TYPE -#undef STR_IMG_FORMAT -#undef STR_BLOCK_SIZE - -#undef STR_FLOPPY_DRIVES -#undef STR_TURBO -#undef STR_CHECKBPB -#undef STR_CDROM_DRIVES -#undef STR_CD_SPEED -#undef STR_EARLY - -#undef STR_MO_DRIVES -#undef STR_ZIP_DRIVES -#undef STR_250 - -#undef STR_ISARTC -#undef STR_ISAMEM -#undef STR_ISAMEM_1 -#undef STR_ISAMEM_2 -#undef STR_ISAMEM_3 -#undef STR_ISAMEM_4 -#undef STR_BUGGER -#undef STR_POSTCARD - -#undef FONT_SIZE -#undef FONT_NAME diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc deleted file mode 100644 index 01e18f71a..000000000 --- a/src/win/languages/en-GB.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// English (U.K.) resources - -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Square pixels (Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer scale", IDM_VID_FS_INT - END - POPUP "E&GA/(S)VGA settings" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Tools" - BEGIN - MENUITEM "&Settings...", IDM_CONFIG - MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Preferences...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Enable &Discord integration", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Help" - BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&About 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&ject", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "E&mpty", IDM_CDROM_EMPTY - MENUITEM "&Reload previous image", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Image...", IDM_CDROM_IMAGE - MENUITEM "&Folder...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&ject", IDM_ZIP_EJECT - MENUITEM "&Reload previous image", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&ject", IDM_MO_EJECT - MENUITEM "&Reload previous image", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Target &framerate" - BEGIN - MENUITEM "&Sync with video", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Select shader...", IDM_VID_GL_SHADER - MENUITEM "&Remove shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Disabled" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 6ca6945d6..000000000 --- a/src/win/languages/en-US.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Square pixels (Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Integer scale", IDM_VID_FS_INT - END - POPUP "E&GA/(S)VGA settings" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Tools" - BEGIN - MENUITEM "&Settings...", IDM_CONFIG - MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Preferences...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Enable &Discord integration", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Help" - BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&About 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&ject", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xport to 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&ject", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "E&mpty", IDM_CDROM_EMPTY - MENUITEM "&Reload previous image", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Image...", IDM_CDROM_IMAGE - MENUITEM "&Folder...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&ject", IDM_ZIP_EJECT - MENUITEM "&Reload previous image", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&ject", IDM_MO_EJECT - MENUITEM "&Reload previous image", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Target &framerate" - BEGIN - MENUITEM "&Sync with video", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Select shader...", IDM_VID_GL_SHADER - MENUITEM "&Remove shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Disabled" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 1fd0bceff..000000000 --- a/src/win/languages/es-ES.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Spanish (Spain) resources - -#ifdef _WIN32 -LANGUAGE LANG_SPANISH, SUBLANG_SPANISH -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "&Escalado alta densidad", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Píxeles cuadrados (Mant. aspecto)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Escalado valor entero", IDM_VID_FS_INT - END - POPUP "&Ajustes EGA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Herramientas" - BEGIN - 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 SEPARATOR - MENUITEM "&Preferencias...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Habilitar integración con &Discord", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Ayuda" - BEGIN - MENUITEM "&Documentación...", IDM_DOCS - MENUITEM "&Acerca de 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&xtraer", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Imagen...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xportar a 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&xtraer", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Silenciar", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "E&xtraer disco", IDM_CDROM_EMPTY - MENUITEM "&Recargar imagen previa", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Imagen...", IDM_CDROM_IMAGE - MENUITEM "&Carpeta...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xtraer", IDM_ZIP_EJECT - MENUITEM "&Recargar imagen previa", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xtraer", IDM_MO_EJECT - MENUITEM "&Recargar imagen previa", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Tasa de refresco objetivo" - BEGIN - MENUITEM "&Sincronizar con vídeo", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Seleccionar shader...", IDM_VID_GL_SHADER - MENUITEM "&Eliminar shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Deshabilitado" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 3f875cb3d..000000000 --- a/src/win/languages/fi-FI.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Finnish resources - -#ifdef _WIN32 -LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Tauko", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - MENUITEM "&Poistu...", IDM_ACTION_EXIT - END - POPUP "&Näytä" - BEGIN - MENUITEM "&Piilota tilapalkki", IDM_VID_HIDE_STATUS_BAR - MENUITEM "Piilota &työkalupalkki", IDM_VID_HIDE_TOOLBAR - MENUITEM SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "&Suuri DPI-skaalaus", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 - END - POPUP "&EGA/(S)VGA-asetukset" - BEGIN - 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ä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 - 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 - END - MENUITEM "&Media", IDM_MEDIA - POPUP "Työ&kalut" - BEGIN - MENUITEM "&Kokoonpano...", IDM_CONFIG - MENUITEM "&Päivitä tilapalkin kuvakkeita", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "Ota &kuvakaappaus\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Sovellusasetukset...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Käytä &Discord-integraatiota", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Ohje" - BEGIN - MENUITEM "&Ohjekirja...", IDM_DOCS - MENUITEM "&Tietoja 86Boxista...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Poista kasettipesästä", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&ROM-moduulikuva...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Irrota", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Vie 86F-tiedostoon...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Poista asemasta", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Mykistä", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Tyhjä", IDM_CDROM_EMPTY - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "L&evykuva...", IDM_CDROM_IMAGE - MENUITEM "&Kansio...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Poista asemasta", IDM_ZIP_EJECT - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Poista asemasta", IDM_MO_EJECT - MENUITEM "&Lataa edellinen levykuva uudelleen", IDM_MO_RELOAD - END -END - -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 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "Valitse varjostin&ohjelma...", IDM_VID_GL_SHADER - MENUITEM "&Poista varjostinohjelma", IDM_VID_GL_NOSHADER -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -#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_GAIN "Taso" - -#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_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_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_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_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_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 "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_SPEED "Speed:" - -#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_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 FONT_SIZE 9 -#define FONT_NAME "Segoe UI" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - 2048 "86Box" - IDS_2049 "Virhe" - IDS_2050 "Vakava virhe" - 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_2057 "(tyhjä)" - IDS_2058 "ZIP-levykuvat (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2059 "Turbo" - IDS_2060 "Päällä" - IDS_2061 "Pois" - IDS_2062 "Kaikki levykuvat (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Perussektorilevykuvat (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Pintalevykuvat (*.86F)\0*.86F\0" - IDS_2063 "Konetta ""%hs"" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen koneeseen." -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_2064 "Näytönohjainta ""%hs"" ei voi käyttää puuttuvien ROM-tiedostojen vuoksi. Vaihdetaan käyttökelpoiseen näytönohjaimeen." - IDS_2065 "Tietokone" - IDS_2066 "Näyttö" - IDS_2067 "Syöttölaitteet" - IDS_2068 "Ääni" - IDS_2069 "Verkko" - IDS_2070 "Portit (COM & LPT)" - IDS_2071 "Tallennusohjaimet" - IDS_2072 "Kiintolevyt" - IDS_2073 "Levyke ja CD-ROM" - IDS_2074 "Muut tallennuslaitteet" - IDS_2075 "Muut oheislaitteet" - IDS_2076 "Pintalevykuvat (*.86F)\0*.86F\0" - IDS_2077 "Kaappaa hiiri klikkaamalla" - IDS_2078 "Paina F8+F12 vapauttaaksesi hiiren" - IDS_2079 "Paina F8+F12 tai keskipainiketta vapauttaaksesi hiiren" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_2081 "Väylä" - IDS_2082 "Tiedosto" - IDS_2083 "C" - IDS_2084 "H" - IDS_2085 "S" - IDS_2086 "Mt" - 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_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_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_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 -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_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_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" - IDS_4108 "Tiedostoon ei voi kirjoittaa" - IDS_4109 "HDI- ja HDX-levykuvien ainoa tuettu sektorikoko on 512" - IDS_4110 "USB-tukea ei vielä ole" - IDS_4111 "Levykuva on jo olemassa" - IDS_4112 "Anna kelvollinen tiedostonimi." - IDS_4113 "Levykuva luotu" - IDS_4114 "Varmista, että tiedosto on olemassa ja lukukelpoinen" - 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 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)" - IDS_4125 "Kiinteä VHD (.vhd)" - IDS_4126 "Dynaaminen VHD (.vhd)" - IDS_4127 "Differentiaalinen VHD (.vhd)" - IDS_4128 "Suuret lohkot (2 Mt)" - IDS_4129 "Pienet lohkot (512 kt)" - IDS_4130 "VHD-tiedostot (*.VHD)\0*.VHD\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_4131 "Valitse ylätason VHD" - IDS_4132 "Tämä saattaa tarkoittaa, että ylätason levykuvaa on muokattu differentiaalisen levykuvan luonnin jälkeen.\n\nNäin voi käydä myös, jos levykuvatiedostoja on siirretty tai kopioitu. Lisäksi syynä voi olla levyn luoneessa sovelluksessa oleva ohjelmistovirhe.\n\nKorjataanko aikaleimat?" - IDS_4133 "Ylä- ja alatason levyjen aikaleimat eivät täsmää" - IDS_4134 "VHD aikaleimaa ei pystytty korjaamaan." - 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 "CD-ROM %i (%s): %s" - - IDS_5376 "Ei käytössä" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - IDS_5632 "Ei käytössä" - IDS_5637 "ATAPI (%01i:%01i)" - IDS_5638 "SCSI (%01i:%02i)" - - IDS_5888 "160 kt" - IDS_5889 "180 kt" - IDS_5890 "320 kt" - IDS_5891 "360 kt" - IDS_5892 "640 kt" - IDS_5893 "720 kt" - IDS_5894 "1.2 Mt" - IDS_5895 "1.25 Mt" - IDS_5896 "1.44 Mt" - IDS_5897 "DMF (lohko 1024)" - IDS_5898 "DMF (lohko 2048)" - IDS_5899 "2.88 Mt" - IDS_5900 "ZIP 100" - IDS_5901 "ZIP 250" - IDS_5902 "3.5"" 128 Mt (ISO 10090)" - IDS_5903 "3.5"" 230 Mt (ISO 13963)" - IDS_5904 "3.5"" 540 Mt (ISO 15498)" - IDS_5905 "3.5"" 640 Mt (ISO 15498)" - IDS_5906 "3.5"" 1.3 Gt (GigaMO)" - IDS_5907 "3.5"" 2.3 Gt (GigaMO 2)" - IDS_5908 "5.25"" 600 Mt" - IDS_5909 "5.25"" 650 Mt" - IDS_5910 "5.25"" 1 Gt" - IDS_5911 "5.25"" 1.3 Gt" - - IDS_6144 "Täydellinen RPM" - IDS_6145 "1% alle täydellisen RPM:n" - IDS_6146 "1.5% alle täydellisen RPM:n" - IDS_6147 "2% alle täydellisen RPM:n" - - IDS_7168 "(Järjestelmän oletus)" -END -#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 deleted file mode 100644 index 1ad5a4da1..000000000 --- a/src/win/languages/fr-FR.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// French (fr-FR) resources - -#ifdef _WIN32 -LANGUAGE LANG_FRENCH, SUBLANG_FRENCH -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pause", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Mise à l'échelle Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "pixels &Carrés(Keep ratio)", IDM_VID_FS_KEEPRATIO - MENUITEM "Echelle &Entière", IDM_VID_FS_INT - END - POPUP "Réglages E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "Ou&tils" - BEGIN - 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 SEPARATOR - MENUITEM "&Préférences...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Activer intégration &Discord", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Aide" - BEGIN - MENUITEM "&Documentation...", IDM_DOCS - MENUITEM "&A Propos de 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&jecter", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Image...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xport vers 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Couper", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "E&jecter", IDM_CDROM_EMPTY - MENUITEM "&Recharger image précedente", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Image...", IDM_CDROM_IMAGE - MENUITEM "&Dossier...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jecter", IDM_ZIP_EJECT - MENUITEM "&Recharger image précédente", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jecter", IDM_MO_EJECT - MENUITEM "&Recharger image précédente", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Taux de rafraîchissement cible" - BEGIN - MENUITEM "&Synchronisation avec la vidéo", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 images par seconde", IDM_VID_GL_FPS_25 - MENUITEM "&30 images par seconde", IDM_VID_GL_FPS_30 - MENUITEM "&50 images par seconde", IDM_VID_GL_FPS_50 - MENUITEM "&60 images par seconde", IDM_VID_GL_FPS_60 - MENUITEM "&75 images par seconde", IDM_VID_GL_FPS_75 - END - MENUITEM "Synchronisation &verticale", IDM_VID_GL_VSYNC - MENUITEM "Sé&lectionnez le shader...", IDM_VID_GL_SHADER - MENUITEM "S&upprimer le shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Désactivé" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 9497a7b0d..000000000 --- a/src/win/languages/hr-HR.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Croatian (hr-HR) resources - -#ifdef _WIN32 -LANGUAGE LANG_CROATIAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pauza", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "&HiDPI skaliranje", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Kvadratni pikseli (zadrži omjer)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Cijelobrojno skaliranje", IDM_VID_FS_INT - END - POPUP "E&GA/(S)VGA postavke" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Alati" - BEGIN - 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 SEPARATOR - 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 -#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 -#endif - END - POPUP "&Pomoć" - BEGIN - MENUITEM "&Dokumentacija...", IDM_DOCS - MENUITEM "&O programu 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Izbaci", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Slika...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Izvozi u 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Izbaci", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Isključi zvuk", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Prazno", IDM_CDROM_EMPTY - MENUITEM "&Ponovo učitaj prethodnu sliku", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Slika...", IDM_CDROM_IMAGE - MENUITEM "&Mapa...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Izbaci", IDM_ZIP_EJECT - MENUITEM "&Ponovo učitaj prethodnu sliku", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Izbaci", IDM_MO_EJECT - MENUITEM "&Ponovo učitaj prethodnu sliku", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Ciljni broj okvira u sekundi" - BEGIN - MENUITEM "&Sinkroniziraj s videom", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Odaberi shader...", IDM_VID_GL_SHADER - MENUITEM "&Ukloni shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Deaktivirano" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index ab91d43f5..000000000 --- a/src/win/languages/hu-HU.rc +++ /dev/null @@ -1,641 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Hungarian resources -// -// Translated by Laci bá', 2021 -// - -//#define TRANSLATORS_NAME "Laci bá'" - -#ifdef _WIN32 -LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Szüneteltetés", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Hi&DPI méretezés", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Négyzetes képpontok (aránytartás)", IDM_VID_FS_KEEPRATIO - 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 - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Eszközök" - BEGIN - 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 SEPARATOR - 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 -#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 -#endif - END - POPUP "&Súgó" - BEGIN - MENUITEM "&Dokumentáció...", IDM_DOCS - MENUITEM "A 86Box &névjegye...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Kiadás", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "Kép&fájl...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xportálás 86F formátumba...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Kiadás", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Meglévő képfájl &megnyitása...", IDM_CDROM_IMAGE - MENUITEM "&Mappa...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "Kiadás", IDM_ZIP_EJECT - MENUITEM "Előző képfájl &újratöltése", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "Kiadás", IDM_MO_EJECT - MENUITEM "Előző képfájl &újratöltése", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Cél &képkockasebesség" - BEGIN - MENUITEM "&Szinkronizálás a videóval ", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "Shader &kiválasztása...", IDM_VID_GL_SHADER - MENUITEM "Shader &eltávolítása", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Letiltva" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Hungarian resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc deleted file mode 100644 index cb6e7afa1..000000000 --- a/src/win/languages/it-IT.rc +++ /dev/null @@ -1,638 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Italian (IT-it) resources - -#ifdef _WIN32 -LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN -#pragma code_page(65001) -#endif //_WIN32 - -// explorerdotexe -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Scala Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Pixel quadrati (mantiene l'aspetto)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Scala intera", IDM_VID_FS_INT - END - POPUP "Impostazioni E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Strumenti" - BEGIN - 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 SEPARATOR - MENUITEM "&Preferenze...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Abilita &integrazione Discord", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&?" - BEGIN - MENUITEM "&Documentazione...", IDM_DOCS - MENUITEM "&Informazioni su 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Espelli", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Immagine...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&sporta in 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Muto", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Espelli", IDM_CDROM_EMPTY - MENUITEM "&Ricarica l'immagine precedente", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Immagine...", IDM_CDROM_IMAGE - MENUITEM "&Cartella...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Espelli", IDM_ZIP_EJECT - MENUITEM "&Ricarica l'immagine precedente", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Espelli", IDM_MO_EJECT - MENUITEM "&Ricarica l'immagine precedente", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Imposta obiettivo &fotogrammi" - BEGIN - MENUITEM "&Sincronizza col video", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 FPS", IDM_VID_GL_FPS_25 - MENUITEM "&30 FPS", IDM_VID_GL_FPS_30 - MENUITEM "&50 FPS", IDM_VID_GL_FPS_50 - MENUITEM "&60 FPS", IDM_VID_GL_FPS_60 - MENUITEM "&75 FPS", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Seleziona shader...", IDM_VID_GL_SHADER - MENUITEM "&Rimuovi shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Disabilitato" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index bf9509453..000000000 --- a/src/win/languages/ja-JP.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Japanese resources - -#ifdef _WIN32 -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT -#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 "プライマリ以外のモニターを表示(&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 "E&GA/(S)VGAの設定" - BEGIN - 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 - 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 "垂直同期(VSync)(&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 "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 "ウェイト ステート:" -#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グラフィック" -#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_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_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 "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_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_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_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" - -#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\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 -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キーまたは中クリックでマウスを解放します" -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つのウェイト ステート" - 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_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_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 "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 -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_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 "CD-ROM %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%低いRPM" - IDS_6146 "1.5%低いRPM" - IDS_6147 "2%低いRPM" - - IDS_7168 "(システム既定値)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Japanese resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc deleted file mode 100644 index 360d6e36b..000000000 --- a/src/win/languages/ko-KR.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Korean resources - -#ifdef _WIN32 -LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT -#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 "툴바 숨기기", IDM_VID_HIDE_TOOLBAR - MENUITEM SEPARATOR - 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 -#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.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 - 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 "E&GA/(S)VGA 설정" - 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 "디스코드 연동 활성화하기(&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 "대기 상태:" -#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 그래픽" -#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_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_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 "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_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_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_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" - -#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\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 -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키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" -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 대기 상태" - 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_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_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 "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 -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_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 "CD-ROM %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 "완벽한 회전수" - IDS_6145 "1% 낮은 회전수" - IDS_6146 "1.5% 낮은 회전수" - IDS_6147 "2% 낮은 회전수" - - IDS_7168 "(시스템 기본값)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Korean resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc deleted file mode 100644 index f835ad9eb..000000000 --- a/src/win/languages/pl-PL.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Polish (pl-PL) resources - -#ifdef _WIN32 -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pauza", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Skalowanie Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Kwadratowe piksele (Zachowaj proporcje)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Skalowanie całkowite", IDM_VID_FS_INT - END - POPUP "Ustawienia E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Narzędzia" - BEGIN - 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 SEPARATOR - 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 -#ifdef MTR_ENABLED - MENUITEM SEPARATOR - 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 - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "W&yjmij", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Obraz...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&ksportuj do 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "W&yjmij", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Ścisz", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "P&usty", IDM_CDROM_EMPTY - MENUITEM "&Przeładuj poprzedni obraz", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Obraz...", IDM_CDROM_IMAGE - MENUITEM "&Teczka...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "W&yjmij", IDM_ZIP_EJECT - MENUITEM "&Przeładuj poprzedni obraz", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "W&yjmij", IDM_MO_EJECT - MENUITEM "&Przeładuj poprzedni obraz", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Docelowa &liczba klatek na sekundę" - BEGIN - MENUITEM "&Zsynchronizuj z wideo", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Wybierz shader...", IDM_VID_GL_SHADER - MENUITEM "&Usuń shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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ę." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Wyłączony" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 00e9c243d..000000000 --- a/src/win/languages/pt-BR.rc +++ /dev/null @@ -1,640 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Portuguese (pt-BR) resources -// -// Translated by Altieres Lima da Silva, 2021 -// - -#ifdef _WIN32 -LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Pausar", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "Pixel&s quadrados (manter proporção)", IDM_VID_FS_KEEPRATIO - 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 - POPUP "&Tipo de tela VGA" - BEGIN - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Ferramentas" - BEGIN - 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 SEPARATOR - 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 -#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 -#endif - END - POPUP "&Ajuda" - BEGIN - MENUITEM "&Documentação...", IDM_DOCS - MENUITEM "&Sobre o 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&jetar", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Sem som", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Vazio", IDM_CDROM_EMPTY - MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Imagem...", IDM_CDROM_IMAGE - MENUITEM "&Pasta...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jetar", IDM_ZIP_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jetar", IDM_MO_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Taxa de quadro pretendida" - BEGIN - MENUITEM "&Sincronizar com vídeo", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 qps", IDM_VID_GL_FPS_25 - MENUITEM "&30 qps", IDM_VID_GL_FPS_30 - MENUITEM "&50 qps", IDM_VID_GL_FPS_50 - MENUITEM "&60 qps", IDM_VID_GL_FPS_60 - MENUITEM "&75 qps", IDM_VID_GL_FPS_75 - END - MENUITEM "Sincronização &vertical", IDM_VID_GL_VSYNC - MENUITEM "&Selecionar shader...", IDM_VID_GL_SHADER - MENUITEM "&Remover shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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 "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_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 FONT_SIZE 9 -#define FONT_NAME "Segoe UI" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - 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 -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Desativado" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 88db4f18c..000000000 --- a/src/win/languages/pt-PT.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Portuguese (Portugal) resources - -#ifdef _WIN32 -LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -MainMenu MENU DISCARDABLE -BEGIN - POPUP "&Ação" - BEGIN - 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 SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC - MENUITEM SEPARATOR - MENUITEM "&Pausa", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Escala Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "Pixels &quadrados (Manter rácio)", IDM_VID_FS_KEEPRATIO - MENUITEM "Escala &inteira", IDM_VID_FS_INT - END - POPUP "Definições E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Ferramentas" - BEGIN - 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 SEPARATOR - 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 -#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 -#endif - END - POPUP "&Ajuda" - BEGIN - MENUITEM "&Documentação...", IDM_DOCS - MENUITEM "&Acerca do 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "E&jetar", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Imagem...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&xportar para 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "E&jetar", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Mute", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&CDROM vazio", IDM_CDROM_EMPTY - MENUITEM "&Recarregar imagem anterior", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Imagem...", IDM_CDROM_IMAGE - MENUITEM "&Pasta...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jetar", IDM_ZIP_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "E&jetar", IDM_MO_EJECT - MENUITEM "&Recarregar imagem anterior", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Taxa de quadros de destino" - BEGIN - MENUITEM "&Sincronizar com vídeo", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 q/s", IDM_VID_GL_FPS_25 - MENUITEM "&30 q/s", IDM_VID_GL_FPS_30 - MENUITEM "&50 q/s", IDM_VID_GL_FPS_50 - MENUITEM "&60 q/s", IDM_VID_GL_FPS_60 - MENUITEM "&75 q/s", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Selecionar shader...", IDM_VID_GL_SHADER - MENUITEM "&Remover shader", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Desativado" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#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 deleted file mode 100644 index 647b43d44..000000000 --- a/src/win/languages/ru-RU.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Russian resources - -#ifdef _WIN32 -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -MainMenu MENU DISCARDABLE -BEGIN - POPUP "&Действие" - BEGIN - 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 SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC - MENUITEM SEPARATOR - MENUITEM "&Пауза", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - MENUITEM "&Выход...", IDM_ACTION_EXIT - END - POPUP "&Вид" - BEGIN - MENUITEM "&Скрыть строку состояния", IDM_VID_HIDE_STATUS_BAR - MENUITEM "С&крыть панель инструментов", IDM_VID_HIDE_TOOLBAR - MENUITEM SEPARATOR - 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 -#ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC -#endif - END - MENUITEM SEPARATOR - 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 "&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 - END - MENUITEM "Масштабирование Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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_KEEPRATIO - MENUITEM "&Целочисленное масштабирование", IDM_VID_FS_INT - END - POPUP "Настройки E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - MENUITEM "Вылеты развёртки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN - MENUITEM "Изменить контрастность &монохромного дисплея", IDM_VID_CGACON - END - MENUITEM "&Носители", IDM_MEDIA - POPUP "&Инструменты" - BEGIN - MENUITEM "&Настройки машины...", IDM_CONFIG - MENUITEM "&Обновление значков строки состояния", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "Сделать с&криншот\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Параметры...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Включить интеграцию &Discord", IDM_DISCORD -#endif - MENUITEM SEPARATOR - MENUITEM "&Усиление звука...", 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 "&Помощь" - BEGIN - MENUITEM "&Документация...", IDM_DOCS - MENUITEM "&О программе 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новый образ...", IDM_CASSETTE_IMAGE_NEW - MENUITEM SEPARATOR - 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 SEPARATOR - MENUITEM "И&звлечь", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новый образ...", IDM_FLOPPY_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от записи)...", IDM_FLOPPY_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "Э&кспорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "О&тключить звук", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "П&устой", IDM_CDROM_EMPTY - MENUITEM "&Снова загрузить предыдущий образ", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Образ...", IDM_CDROM_IMAGE - MENUITEM "&Папка...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новый образ...", IDM_ZIP_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от записи)...", IDM_ZIP_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_ZIP_EJECT - MENUITEM "&Снова загрузить предыдущий образ", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новый образ...", IDM_MO_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Выбрать образ...", IDM_MO_IMAGE_EXISTING - MENUITEM "Выбрать образ (&Защита от записи)...", IDM_MO_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "И&звлечь", IDM_MO_EJECT - MENUITEM "&Снова загрузить предыдущий образ", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Целевая &частота кадров" - BEGIN - MENUITEM "&Синхронизация с видео", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 кадров в секунду", IDM_VID_GL_FPS_25 - MENUITEM "&30 кадров в секунду", IDM_VID_GL_FPS_30 - MENUITEM "&50 кадров в секунду", IDM_VID_GL_FPS_50 - MENUITEM "&60 кадров в секунду", IDM_VID_GL_FPS_60 - MENUITEM "&75 кадров в секунду", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Выбрать шейдер...", IDM_VID_GL_SHADER - MENUITEM "&Удалить шейдер", 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 "OK" -#define STR_CANCEL "Отмена" -#define STR_GLOBAL "Сохранить эти параметры как &глобальные по умолчанию" -#define STR_DEFAULT "&По умолчанию" -#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 "Тип ЦП:" -#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_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_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_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_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_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_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_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" - -#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 не смог найти ни одного подходящего для использования файла с ПЗУ.\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 -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 или среднюю кнопку мыши чтобы освободить курсор" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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 "Образы 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 -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_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 "CD-ROM %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 кБ" - 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_7168 "(Системный)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Russian resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc deleted file mode 100644 index b3a00c9de..000000000 --- a/src/win/languages/sl-SI.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Slovenian resources - -#ifdef _WIN32 -LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Premor", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "&Raztezanje za visok DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Kvadratni piksli (ohrani razmerje)", IDM_VID_FS_KEEPRATIO - MENUITEM "&Celoštevilsko raztezanje", IDM_VID_FS_INT - END - POPUP "Nastavitve E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Orodja" - BEGIN - MENUITEM "&Nastavitve...", IDM_CONFIG - MENUITEM "&Posodabljaj ikone statusne vrstice", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "&Zajemi posnetek zaslona\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - 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 -#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 -#endif - END - POPUP "&Pomoč" - BEGIN - MENUITEM "&Dokumentacija...", IDM_DOCS - MENUITEM "&O programu 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "Izvrzi", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "Slika...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "Izvrzi", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Izvozi v 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "I&zvrzi", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Utišaj", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Prazen", IDM_CDROM_EMPTY - MENUITEM "&Naloži zadnjo sliko", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Slika...", IDM_CDROM_IMAGE - MENUITEM "&Mapa...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "I&zvrzi", IDM_ZIP_EJECT - MENUITEM "&Naloži zadnjo sliko", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "I&zvrzi", IDM_MO_EJECT - MENUITEM "&Naloži zadnjo sliko", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "&Ciljno št. sličic na sekundo" - BEGIN - MENUITEM "&Sinhroniziraj z videom", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Izberi senčilnik...", IDM_VID_GL_SHADER - MENUITEM "&Odstrani senčilnik", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Onemogočeno" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Slovenian resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc deleted file mode 100644 index 78e7b4b87..000000000 --- a/src/win/languages/tr-TR.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Turkish (TR) resources - -#ifdef _WIN32 -LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -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 SEPARATOR - 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 SEPARATOR - MENUITEM "&Duraklat", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - 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 SEPARATOR - 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 -#ifdef USE_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 - 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 "&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 - END - MENUITEM "Hi&DPI ölçeklemesi", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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 "&Kare piksel (ölçeği koru)", IDM_VID_FS_KEEPRATIO - 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 - 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 - 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 - END - END - MENUITEM SEPARATOR - 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 - POPUP "&Araçlar" - BEGIN - 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 SEPARATOR - MENUITEM "&Tercihler...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "&Discord entegrasyonunu etkinleştir", IDM_DISCORD -#endif - MENUITEM SEPARATOR - 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 -#endif - END - POPUP "&Yardım" - BEGIN - MENUITEM "&Dökümanlar...", IDM_DOCS - MENUITEM "&86Box Hakkında...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 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 SEPARATOR - MENUITEM "&Çıkar", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&İmaj...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&86F dosyası olarak aktar...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Çıkar", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Sesi kapat", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "İmajı &çıkar", IDM_CDROM_EMPTY - MENUITEM "&Önceki imajı seç", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&İmaj seç...", IDM_CDROM_IMAGE - MENUITEM "&Klasör...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Çıkar", IDM_ZIP_EJECT - MENUITEM "&Önceki imajı seç", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - 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 SEPARATOR - MENUITEM "&Çıkar", IDM_MO_EJECT - MENUITEM "&Önceki imajı seç", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Hedef &kare oranı" - BEGIN - MENUITEM "Video ile &senkronize et", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 fps", IDM_VID_GL_FPS_25 - MENUITEM "&30 fps", IDM_VID_GL_FPS_30 - MENUITEM "&50 fps", IDM_VID_GL_FPS_50 - MENUITEM "&60 fps", IDM_VID_GL_FPS_60 - MENUITEM "&75 fps", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "Gölgelendirici &seç...", IDM_VID_GL_SHADER - MENUITEM "&Gölgelendiriciyi kaldır", IDM_VID_GL_NOSHADER -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_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_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_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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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." -END - -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" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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_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 -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_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 "CD-ROM %i (%s): %s" - - IDS_5376 "Devre dışı" - IDS_5381 "ATAPI" - IDS_5382 "SCSI" - - 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_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ı)" -END -#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 deleted file mode 100644 index 41bf85f1a..000000000 --- a/src/win/languages/uk-UA.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Ukrainian resources - -#ifdef _WIN32 -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT -#pragma code_page(65001) -#endif //_WIN32 - -#define AUTHORS - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -MainMenu MENU DISCARDABLE -BEGIN - POPUP "&Дія" - BEGIN - 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 SEPARATOR - MENUITEM "Ctrl+Alt+&Esc", IDM_ACTION_CTRL_ALT_ESC - MENUITEM SEPARATOR - MENUITEM "&Пауза", IDM_ACTION_PAUSE - MENUITEM SEPARATOR - MENUITEM "&Вихід...", IDM_ACTION_EXIT - END - POPUP "&Вигляд" - BEGIN - MENUITEM "&Приховати рядок стану", IDM_VID_HIDE_STATUS_BAR - MENUITEM "&Приховати панель інструментів", IDM_VID_HIDE_TOOLBAR - MENUITEM SEPARATOR - 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 -#ifdef USE_VNC - MENUITEM "&VNC", IDM_VID_VNC -#endif - END - MENUITEM SEPARATOR - 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 "&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 - END - MENUITEM "Масштабування Hi&DPI", IDM_VID_HIDPI - MENUITEM SEPARATOR - 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_KEEPRATIO - MENUITEM "&Цілісночисленне масштабування", IDM_VID_FS_INT - END - POPUP "Налаштування E&GA/(S)VGA" - BEGIN - 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 - 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 - END - END - MENUITEM SEPARATOR - MENUITEM "Вильоти розгортки CGA/PCjr/Tandy/E&GA/(S)VGA", IDM_VID_OVERSCAN - MENUITEM "Змінити контрастність &монохромного дисплея", IDM_VID_CGACON - END - MENUITEM "&Носії", IDM_MEDIA - POPUP "&Інструменти" - BEGIN - MENUITEM "&Налаштування машини...", IDM_CONFIG - MENUITEM "&Обновлення значків рядка стану", IDM_UPDATE_ICONS - MENUITEM SEPARATOR - MENUITEM "Зробити &знімок\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR - MENUITEM "&Параметри...", IDM_PREFERENCES -#ifdef DISCORD - MENUITEM "Увімкнути інтеграцію &Discord", IDM_DISCORD -#endif - MENUITEM SEPARATOR - MENUITEM "&Посилення звуку...", 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 "&Допомога" - BEGIN - MENUITEM "&Документація...", IDM_DOCS - MENUITEM "&Про програму 86Box...", IDM_ABOUT - END -END - -StatusBarMenu MENU DISCARDABLE -BEGIN - MENUITEM SEPARATOR -END - -CassetteSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новий образ...", IDM_CASSETTE_IMAGE_NEW - MENUITEM SEPARATOR - 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 SEPARATOR - MENUITEM "&Вилучити", IDM_CASSETTE_EJECT - END -END - -CartridgeSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Образ...", IDM_CARTRIDGE_IMAGE - MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_CARTRIDGE_EJECT - END -END - -FloppySubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новий образ...", IDM_FLOPPY_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_FLOPPY_IMAGE_EXISTING - MENUITEM "Вибрати образ (&Захист від запису)...", IDM_FLOPPY_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "&Експорт в 86F...", IDM_FLOPPY_EXPORT_TO_86F - MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_FLOPPY_EJECT - END -END - -CdromSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Відключити звук", IDM_CDROM_MUTE - MENUITEM SEPARATOR - MENUITEM "&Пустий", IDM_CDROM_EMPTY - MENUITEM "&Знову завантажити попередній образ", IDM_CDROM_RELOAD - MENUITEM SEPARATOR - MENUITEM "&Образ...", IDM_CDROM_IMAGE - MENUITEM "&Тека...", IDM_CDROM_DIR - END -END - -ZIPSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новий образ...", IDM_ZIP_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_ZIP_IMAGE_EXISTING - MENUITEM "Вибрати образ (&Захист від запису)...", IDM_ZIP_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_ZIP_EJECT - MENUITEM "&Знову завантажити попередній образ", IDM_ZIP_RELOAD - END -END - -MOSubmenu MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Новий образ...", IDM_MO_IMAGE_NEW - MENUITEM SEPARATOR - MENUITEM "&Вибрати образ...", IDM_MO_IMAGE_EXISTING - MENUITEM "Вибрати образ (&Захист від запису)...", IDM_MO_IMAGE_EXISTING_WP - MENUITEM SEPARATOR - MENUITEM "&Вилучити", IDM_MO_EJECT - MENUITEM "&Знову завантажити попередній образ", IDM_MO_RELOAD - END -END - -VidGLSubMenu MENU DISCARDABLE -BEGIN - POPUP "Цільова &частота кадрів" - BEGIN - MENUITEM "&Синхронізація з відео", IDM_VID_GL_FPS_BLITTER - MENUITEM "&25 кадрів в секунду", IDM_VID_GL_FPS_25 - MENUITEM "&30 кадрів в секунду", IDM_VID_GL_FPS_30 - MENUITEM "&50 кадрів в секунду", IDM_VID_GL_FPS_50 - MENUITEM "&60 кадрів в секунду", IDM_VID_GL_FPS_60 - MENUITEM "&75 кадрів в секунду", IDM_VID_GL_FPS_75 - END - MENUITEM "&VSync", IDM_VID_GL_VSYNC - MENUITEM "&Вибрати шейдер...", IDM_VID_GL_SHADER - MENUITEM "&Видалити шейдер", 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 "OK" -#define STR_CANCEL "Відміна" -#define STR_GLOBAL "Зберегти ці параметри як &глобальні за замовчуванням" -#define STR_DEFAULT "&За замовчуванням" -#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 "Тип ЦП:" -#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_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_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_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_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_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_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_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" - -#include "dialogs.rc" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -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. Переключення на доступну системну плату." -END - -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 або середню кнопку миші, щоб звільнити курсор" -END - -STRINGTABLE DISCARDABLE -BEGIN - 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_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_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 "Образи 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_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 "CD-ROM %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 кБ" - 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_7168 "(Системний)" -END -#define IDS_LANG_ENUS IDS_7168 - -// Ukrainian resources -//////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc deleted file mode 100644 index 92afaf86d..000000000 --- a/src/win/languages/zh-CN.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Simplified Chinese resources - -#ifdef _WIN32 -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -#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 "显示次要显示器(&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 "启用 (协调世界时)" -#define STR_DYNAREC "动态重编译器" -#define STR_SOFTFLOAT "软浮点 FPU" - -#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_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 "速度:" - -#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 YaHei" - -#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 "速度" - 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 "类型" - IDS_2163 "无动态重编译" - IDS_2164 "旧式动态重编译" - IDS_2165 "新式动态重编译" - IDS_2166 "由于 roms/video 文件夹中缺少合适的 ROM,显卡 #2 ""%hs"" 不可用。将禁用第二张显卡。" - IDS_2167 "初始化网络驱动程序失败" - IDS_2168 "网络配置将切换为空驱动程序" -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 - -// Simplified Chinese resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/win/languages/zh-TW.rc b/src/win/languages/zh-TW.rc deleted file mode 100644 index 039993e5d..000000000 --- a/src/win/languages/zh-TW.rc +++ /dev/null @@ -1,637 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// 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/pcap_if.rc b/src/win/pcap_if.rc deleted file mode 100644 index acc6d25c4..000000000 --- a/src/win/pcap_if.rc +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef _WIN32 -#include -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - - -/* - * Icons by Devcore - * - https://commons.wikimedia.org/wiki/File:Icon_PC_256x256.png - */ -#ifdef RELEASE_BUILD -100 ICON DISCARDABLE "win/icons/86Box-RB.ico" -#else -100 ICON DISCARDABLE "win/icons/86Box.ico" -#endif - - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,2,0 - PRODUCTVERSION 1,0,2,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "\0" - VALUE "CompanyName", "IRC #SoftHistory\0" - VALUE "FileDescription", "PCap_IF - test tool for WinPcap\0" - VALUE "FileVersion", "1.0.2\0" - VALUE "InternalName", "pcap_if\0" - VALUE "LegalCopyright", "Copyright 2017 Fred N. van Kempen\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "pcap_if.exe\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "WinPcap Test Tool\0" - VALUE "ProductVersion", "1.0.2\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/src/win/win.c b/src/win/win.c deleted file mode 100644 index 21ff6646c..000000000 --- a/src/win/win.c +++ /dev/null @@ -1,1316 +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. - * - * Platform main support module for Windows. - * - * - * - * 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 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define NTDDI_VERSION 0x06010000 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/mouse.h> -#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> -#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 -#endif - -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; /* 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; -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); -} 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 } -#ifdef USE_VNC - , - { "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); - } -} -#else -# define win_log(fmt, ...) -#endif - -void -free_string(rc_str_t **str) -{ - if (*str != NULL) { - free(*str); - *str = NULL; - } -} - -static void -LoadCommonStrings(void) -{ - int i; - - free_string(&lpRCstr7168); - free_string(&lpRCstr6144); - free_string(&lpRCstr5888); - free_string(&lpRCstr5632); - free_string(&lpRCstr5376); - free_string(&lpRCstr5120); - free_string(&lpRCstr4608); - free_string(&lpRCstr4352); - free_string(&lpRCstr4096); - free_string(&lpRCstr2048); - - lpRCstr2048 = calloc(STR_NUM_2048, sizeof(rc_str_t)); - lpRCstr4096 = calloc(STR_NUM_4096, sizeof(rc_str_t)); - lpRCstr4352 = calloc(STR_NUM_4352, sizeof(rc_str_t)); - lpRCstr4608 = calloc(STR_NUM_4608, sizeof(rc_str_t)); - lpRCstr5120 = calloc(STR_NUM_5120, sizeof(rc_str_t)); - lpRCstr5376 = calloc(STR_NUM_5376, sizeof(rc_str_t)); - lpRCstr5632 = calloc(STR_NUM_5632, sizeof(rc_str_t)); - lpRCstr5888 = calloc(STR_NUM_5888, sizeof(rc_str_t)); - lpRCstr6144 = calloc(STR_NUM_6144, sizeof(rc_str_t)); - lpRCstr7168 = calloc(STR_NUM_7168, sizeof(rc_str_t)); - - for (i = 0; i < STR_NUM_2048; i++) - LoadString(hinstance, 2048 + i, lpRCstr2048[i].str, 1024); - - for (i = 0; i < STR_NUM_4096; i++) - LoadString(hinstance, 4096 + i, lpRCstr4096[i].str, 1024); - - for (i = 0; i < STR_NUM_4352; i++) - LoadString(hinstance, 4352 + i, lpRCstr4352[i].str, 1024); - - for (i = 0; i < STR_NUM_4608; i++) - LoadString(hinstance, 4608 + i, lpRCstr4608[i].str, 1024); - - for (i = 0; i < STR_NUM_5120; i++) - LoadString(hinstance, 5120 + i, lpRCstr5120[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 < STR_NUM_5632; i++) { - if ((i == 0) || (i > 3)) - LoadString(hinstance, 5632 + i, lpRCstr5632[i].str, 1024); - } - - for (i = 0; i < STR_NUM_5888; i++) - LoadString(hinstance, 5888 + i, lpRCstr5888[i].str, 1024); - - for (i = 0; i < STR_NUM_6144; i++) - LoadString(hinstance, 6144 + i, lpRCstr6144[i].str, 1024); - - for (i = 0; i < STR_NUM_7168; i++) - LoadString(hinstance, 7168 + i, lpRCstr7168[i].str, 1024); -} - -size_t -mbstoc16s(uint16_t dst[], const char src[], int len) -{ - if (src == NULL) - return 0; - if (len < 0) - return 0; - - size_t ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, dst == NULL ? 0 : len); - - if (!ret) { - return -1; - } - - return ret; -} - -size_t -c16stombs(char dst[], const uint16_t src[], int len) -{ - if (src == NULL) - return 0; - if (len < 0) - return 0; - - size_t ret = WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst == NULL ? 0 : len, NULL, NULL); - - if (!ret) { - return -1; - } - - return ret; -} - -int -has_language_changed(uint32_t id) -{ - return (lang_id != id); -} - -/* Set (or re-set) the language for the application. */ -void -set_language(uint32_t id) -{ - if (id == 0xFFFF) { - set_language(lang_sys); - lang_id = id; - return; - } - - if (lang_id != id) { - /* Set our new language ID. */ - lang_id = id; - SetThreadUILanguage(lang_id); - - /* Load the strings table for this ID. */ - LoadCommonStrings(); - - /* Reload main menu */ - menuMain = LoadMenu(hinstance, L"MainMenu"); - if (hwndMain != NULL) - SetMenu(hwndMain, menuMain); - - /* Re-init all the menus */ - ResetAllMenus(); - media_menu_init(); - } -} - -wchar_t * -plat_get_string(int i) -{ - LPTSTR str; - - if ((i >= 2048) && (i <= 3071)) - str = lpRCstr2048[i - 2048].str; - else if ((i >= 4096) && (i <= 4351)) - str = lpRCstr4096[i - 4096].str; - else if ((i >= 4352) && (i <= 4607)) - str = lpRCstr4352[i - 4352].str; - else if ((i >= 4608) && (i <= 5119)) - str = lpRCstr4608[i - 4608].str; - else if ((i >= 5120) && (i <= 5375)) - str = lpRCstr5120[i - 5120].str; - else if ((i >= 5376) && (i <= 5631)) - str = lpRCstr5376[i - 5376].str; - else if ((i >= 5632) && (i <= 5887)) - str = lpRCstr5632[i - 5632].str; - else if ((i >= 5888) && (i <= 6143)) - str = lpRCstr5888[i - 5888].str; - else if ((i >= 6144) && (i <= 7167)) - str = lpRCstr6144[i - 6144].str; - else - str = lpRCstr7168[i - 7168].str; - - return str; -} - -#ifdef MTR_ENABLED -void -init_trace(void) -{ - mtr_init("trace.json"); - mtr_start(); -} - -void -shutdown_trace(void) -{ - mtr_stop(); - mtr_shutdown(); -} -#endif - -/* Create a console if we don't already have one. */ -static void -CreateConsole(int init) -{ - HANDLE h; - FILE *fp; - fpos_t p; - int i; - - if (!init) { - if (force_debug) - FreeConsole(); - return; - } - - /* Are we logging to a file? */ - p = 0; - (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; - } - } - 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); - } - } - } - - if (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; - int q; - int argc; - - if (acp_utf8) { - 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); - } - - argc = 0; - argc_max = 64; - args = (char **) malloc(sizeof(char *) * argc_max); - if (args == NULL) { - free(argbuf); - return 0; - } - - /* parse commandline into argc/argv format */ - i = 0; - while (argbuf[i]) { - while (argbuf[i] == ' ') - i++; - - if (argbuf[i]) { - if ((argbuf[i] == '\'') || (argbuf[i] == '"')) { - q = argbuf[i++]; - if (!argbuf[i]) - break; - } else - q = 0; - - 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; - } - } - - while ((argbuf[i]) && (q ? (argbuf[i] != q) : (argbuf[i] != ' '))) - i++; - - if (argbuf[i]) { - argbuf[i] = 0; - i++; - } - } - } - - args[argc] = NULL; - *argv = args; - - 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; - 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; - else - acp_utf8 = 0; - - /* Set this to the default value (windowed mode). */ - video_fullscreen = 0; - - /* We need this later. */ - hinstance = hInst; - - /* 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(); - 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 (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); - - free(argbuf); - free(argv); - return 1; - } - - extern int gfxcard[2]; - gfxcard[1] = 0; - - /* Create console window. */ - if (force_debug) { - CreateConsole(1); - atexit(CloseConsole); - } - - /* Handle our GUI. */ - i = ui_init(nCmdShow); - - /* Uninitialize COM before exit. */ - CoUninitialize(); - - free(argbuf); - free(argv); - return i; -} - -void -main_thread(void *param) -{ - uint32_t old_time; - uint32_t new_time; - int drawits; - int frames; - - framecountx = 0; - title_update = 1; - 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(); -#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(); - - /* 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_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 - * main() so we can call it from the UI module as well. - */ -void -do_start(void) -{ - LARGE_INTEGER qpc; - - /* We have not stopped yet. */ - is_quit = 0; - - /* Initialize the high-precision timer. */ - timeBeginPeriod(1); - QueryPerformanceFrequency(&qpc); - timer_freq = qpc.QuadPart; - win_log("Main timer precision: %llu\n", timer_freq); - - /* Start the emulator, really. */ - thMain = thread_create(main_thread, NULL); - SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); -} - -/* Cleanly stop the emulator. */ -void -do_stop(void) -{ - /* Claim the video blitter. */ - startblit(); - - vid_apis[vid_api].close(); - - pc_close(thMain); - - thMain = NULL; - - if (source_hwnd) - 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); - else { - 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, ""); - - 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); -} - -int -plat_getcwd(char *bufp, int max) -{ - wchar_t *temp; - - if (acp_utf8) - (void) _getcwd(bufp, max); - else { - temp = malloc(max * sizeof(wchar_t)); - (void) _wgetcwd(temp, max); - c16stombs(bufp, temp, max); - free(temp); - } - - return 0; -} - -int -plat_chdir(char *path) -{ - wchar_t *temp; - int len; - int ret; - - if (acp_utf8) - return (_chdir(path)); - else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); - - ret = _wchdir(temp); - - free(temp); - return ret; - } -} - -FILE * -plat_fopen(const char *path, const char *mode) -{ - wchar_t *pathw; - wchar_t *modew; - int len; - FILE *fp; - - if (acp_utf8) - return fopen(path, mode); - else { - 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); - - fp = _wfopen(pathw, modew); - - free(pathw); - free(modew); - - return fp; - } -} - -/* Open a file, using Unicode pathname, with 64bit pointers. */ -FILE * -plat_fopen64(const char *path, const char *mode) -{ - return plat_fopen(path, mode); -} - -void -plat_remove(char *path) -{ - wchar_t *temp; - int len; - - if (acp_utf8) - remove(path); - else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); - - _wremove(temp); - - free(temp); - } -} - -void -path_normalize(UNUSED(char *path)) -{ - /* No-op */ -} - -/* Make sure a path ends with a trailing (back)slash. */ -void -path_slash(char *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 -path_abs(char *path) -{ - if ((path[1] == ':') || (path[0] == '\\') || (path[0] == '/')) - return 1; - - return 0; -} - -/* Return the last element of a pathname. */ -char * -plat_get_basename(const char *path) -{ - int c = (int) strlen(path); - - while (c > 0) { - if (path[c] == '/' || path[c] == '\\') - return ((char *) &path[c + 1]); - c--; - } - - return ((char *) path); -} - -/* Return the 'directory' element of a pathname. */ -void -path_get_dirname(char *dest, const char *path) -{ - int c = (int) strlen(path); - const char *ptr; - - ptr = (char *) path; - - while (c > 0) { - if (path[c] == '/' || path[c] == '\\') { - ptr = (char *) &path[c]; - break; - } - c--; - } - - /* Copy to destination. */ - while (path < ptr) - *dest++ = *path++; - *dest = '\0'; -} - -char * -path_get_filename(char *s) -{ - int c = strlen(s) - 1; - - while (c > 0) { - if (s[c] == '/' || s[c] == '\\') - return (&s[c + 1]); - c--; - } - - return s; -} - -char * -path_get_extension(char *s) -{ - int c = strlen(s) - 1; - - if (c <= 0) - return s; - - while (c && s[c] != '.') - c--; - - if (!c) - return (&s[strlen(s)]); - - return (&s[c + 1]); -} - -void -path_append_filename(char *dest, const char *s1, const char *s2) -{ - strcpy(dest, s1); - path_slash(dest); - strcat(dest, s2); -} - -void -plat_put_backslash(char *s) -{ - int c = strlen(s) - 1; - - if (s[c] != '/' && s[c] != '\\') - s[c] = '/'; -} - -int -plat_dir_check(char *path) -{ - DWORD dwAttrib; - int len; - wchar_t *temp; - - if (acp_utf8) - dwAttrib = GetFileAttributesA(path); - else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); - - dwAttrib = GetFileAttributesW(temp); - - free(temp); - } - - return ((dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0); -} - -int -plat_dir_create(char *path) -{ - int ret; - int len; - wchar_t *temp; - - if (acp_utf8) - return SHCreateDirectoryExA(NULL, path, NULL); - else { - len = mbstoc16s(NULL, path, 0) + 1; - temp = malloc(len * sizeof(wchar_t)); - mbstoc16s(temp, path, len); - - ret = SHCreateDirectoryExW(NULL, temp, NULL); - - free(temp); - - 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_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) -{ - LARGE_INTEGER li; - - QueryPerformanceCounter(&li); - - return (li.QuadPart); -} - -static LARGE_INTEGER -plat_get_ticks_common(void) -{ - LARGE_INTEGER EndingTime; - LARGE_INTEGER ElapsedMicroseconds; - - if (first_use) { - QueryPerformanceFrequency(&Frequency); - QueryPerformanceCounter(&StartingTime); - first_use = 0; - } - - QueryPerformanceCounter(&EndingTime); - ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; - - /* We now have the elapsed number of ticks, along with the - number of ticks-per-second. We use these values - to convert to the number of elapsed microseconds. - To guard against loss-of-precision, we convert - to microseconds *before* dividing by ticks-per-second. */ - ElapsedMicroseconds.QuadPart *= 1000000; - ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; - - return ElapsedMicroseconds; -} - -uint32_t -plat_get_ticks(void) -{ - return (uint32_t) (plat_get_ticks_common().QuadPart / 1000); -} - -uint32_t -plat_get_micro_ticks(void) -{ - return (uint32_t) plat_get_ticks_common().QuadPart; -} - -void -plat_delay_ms(uint32_t count) -{ - Sleep(count); -} - -/* Return the VIDAPI number for the given name. */ -int -plat_vidapi(char *name) -{ - /* Default/System is SDL Hardware. */ - 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; - - 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 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; -#ifdef USE_VNC - case 4: - name = "vnc"; - break; -#endif - default: - fatal("Unknown renderer: %i\n", api); - break; - } - - return name; -} - -int -plat_setvid(int api) -{ - int i; - - win_log("Initializing VIDAPI: api=%d\n", api); - startblit(); - - /* Close the (old) API. */ - vid_apis[vid_api].close(); - vid_api = api; - - if (vid_apis[vid_api].local) - ShowWindow(hwndRender, SW_SHOW); - else - ShowWindow(hwndRender, SW_HIDE); - - /* Initialize the (new) API. */ - i = vid_apis[vid_api].init((void *) hwndRender); - endblit(); - if (!i) - return 0; - - device_force_redraw(); - - vid_api_inited = 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; - - 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; - - vid_apis[vid_api].enable(enable != 0); - - if (!i) - return; - - if (enable) - device_force_redraw(); -} - -int -get_vidpause(void) -{ - return (vid_apis[vid_api].pause()); -} - -void -plat_setfullscreen(int on) -{ - RECT rect; - 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; - - if (on && video_fullscreen_first) { - 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(); - - /* 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); - 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); - - 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); - - 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); - - /* 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); - - 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; - } - } - video_fullscreen &= 1; - video_force_resize_set(1); - if (!(on & 1)) - atomic_store(&doresize_monitors[0], 1); - - win_mouse_init(); - - if (!(on & 2)) { - /* Release video and make it redraw the screen. */ - device_force_redraw(); - - /* Send a CTRL break code so CTRL does not get stuck. */ - keyboard_input(0, 0x01D); - } - - /* Finally, handle the host's mouse cursor. */ - /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ - show_cursor(video_fullscreen ? 0 : -1); - - if (!(on & 2)) { - /* 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; - - 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) -{ - 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); - - 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) -{ - 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(); - monitors[0].mon_screenshots++; - endblit(); - device_force_redraw(); -} - -/* LPARAM interface to plat_get_string(). */ -LPARAM -win_get_string(int id) -{ - wchar_t *ret; - - ret = plat_get_string(id); - return ((LPARAM) ret); -} - -void /* plat_ */ -startblit(void) -{ - WaitForSingleObject(ghMutex, INFINITE); -} - -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 deleted file mode 100644 index 7ba55f73e..000000000 --- a/src/win/win_about.c +++ /dev/null @@ -1,80 +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 the About dialog. - * - * - * - * Authors: Miran Grca, - * 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 -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> -#include <86box/win.h> -#include <86box/version.h> - -void -AboutDialogCreate(HWND hwnd) -{ - int i; - TASKDIALOGCONFIG tdconfig = { 0 }; - TASKDIALOG_BUTTON tdbuttons[] = { - {IDOK, EMU_SITE_W }, - { IDCANCEL, MAKEINTRESOURCE(IDS_2128)} - }; - - wchar_t emu_version[256]; - i = swprintf(emu_version, sizeof_w(emu_version), L"%ls v%ls", EMU_NAME_W, EMU_VERSION_FULL_W); -#ifdef EMU_GIT_HASH - i += swprintf(&emu_version[i], sizeof_w(emu_version) - i, L" [%ls]", EMU_GIT_HASH_W); -#endif - -#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_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); -} diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c deleted file mode 100644 index 37b741c29..000000000 --- a/src/win/win_cdrom.c +++ /dev/null @@ -1,256 +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 the platform-side of CDROM/ZIP/MO drives. - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * Jasmine Iwanek, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017-2018 Fred N. van Kempen. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/cassette.h> -#include <86box/cartridge.h> -#include <86box/fdd.h> -#include <86box/hdd.h> -#include <86box/scsi_device.h> -#include <86box/cdrom.h> -#include <86box/mo.h> -#include <86box/zip.h> -#include <86box/scsi_disk.h> -#include <86box/plat.h> -#include <86box/ui.h> -#include <86box/win.h> - -void -cassette_mount(char *fn, uint8_t wp) -{ - pc_cas_set_fname(cassette, NULL); - memset(cassette_fname, 0, sizeof(cassette_fname)); - cassette_ui_writeprot = wp; - pc_cas_set_fname(cassette, fn); - if (fn != NULL) - 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) -{ - 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(); - ui_sb_update_tip(SB_CASSETTE); - config_save(); -} - -void -cartridge_mount(uint8_t id, char *fn, UNUSED(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); - 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); - ui_sb_update_tip(SB_CARTRIDGE | id); - config_save(); -} - -void -floppy_mount(uint8_t id, char *fn, uint8_t wp) -{ - fdd_close(id); - 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); - 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); - ui_sb_update_tip(SB_FLOPPY | id); - config_save(); -} - -void -plat_cdrom_ui_update(uint8_t id, UNUSED(uint8_t reload)) -{ - const cdrom_t *drv = &cdrom[id]; - - if (drv->host_drive == 0) { - ui_sb_update_icon_state(SB_CDROM | id, 1); - } else { - ui_sb_update_icon_state(SB_CDROM | id, 0); - } - - media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM | id); -} - -void -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 = 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].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); - } else { - ui_sb_update_icon_state(SB_CDROM | id, 1); - } - media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM | id); - config_save(); -} - -void -mo_eject(uint8_t id) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_close(dev); - if (mo_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - mo_insert(dev); - } - - ui_sb_update_icon_state(SB_MO | id, 1); - media_menu_update_mo(id); - ui_sb_update_tip(SB_MO | id); - config_save(); -} - -void -mo_mount(uint8_t id, char *fn, uint8_t wp) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_close(dev); - mo_drives[id].read_only = wp; - mo_load(dev, fn); - mo_insert(dev); - - ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1); - media_menu_update_mo(id); - ui_sb_update_tip(SB_MO | id); - - config_save(); -} - -void -mo_reload(uint8_t id) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_reload(dev); - if (strlen(mo_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_MO | id, 1); - } else { - ui_sb_update_icon_state(SB_MO | id, 0); - } - - media_menu_update_mo(id); - ui_sb_update_tip(SB_MO | id); - - config_save(); -} - -void -zip_eject(uint8_t id) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_close(dev); - if (zip_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - zip_insert(dev); - } - - ui_sb_update_icon_state(SB_ZIP | id, 1); - media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP | id); - config_save(); -} - -void -zip_mount(uint8_t id, char *fn, uint8_t wp) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_close(dev); - zip_drives[id].read_only = wp; - zip_load(dev, fn); - zip_insert(dev); - - ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1); - media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP | id); - - config_save(); -} - -void -zip_reload(uint8_t id) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_reload(dev); - if (strlen(zip_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_ZIP | id, 1); - } else { - ui_sb_update_icon_state(SB_ZIP | id, 0); - } - - media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP | id); - - config_save(); -} diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c deleted file mode 100644 index 92ab6b614..000000000 --- a/src/win/win_devconf.c +++ /dev/null @@ -1,832 +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. - * - * Windows device configuration dialog implementation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#include -#include -#include -#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, UNUSED(LPARAM lParam)) -{ - HWND h; - - 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; - 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; - - lptsTemp = (LPTSTR) malloc(512); - memset(combo_to_struct, 0, 256 * sizeof(int)); - - 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); - - 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); - - 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_BIOS: - val_str = config_get_string((char *) config_device.name, - (char *) config->name, (char *) config->default_string); - - 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; -#ifdef USE_RTMIDI - case CONFIG_MIDI_OUT: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); - - 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_MIDI_IN: - 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); - } - - id += 2; - break; -#endif - case CONFIG_SPINNER: - 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); - - 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 && 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_HEX20: - val_int = config_get_hex20((char *) config_device.name, - (char *) config->name, config->default_int); - - 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]; - - while (config->type != -1) { - const device_config_selection_t *selection = config->selection; - 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); - - if (val_int != SendMessage(h, BM_GETCHECK, 0, 0)) - changed = 1; - - id++; - break; - case CONFIG_SELECTION: - val_int = config_get_int((char *) config_device.name, - (char *) config->name, config->default_int); - - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - for (; c > 0; c--) - selection++; - - if (val_int != selection->value) - changed = 1; - - id += 2; - break; - case CONFIG_BIOS: - bios = config->bios; - - val_str = config_get_string((char *) config_device.name, - (char *) config->name, (char *) config->default_string); - - c = combo_to_struct[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - for (; c > 0; c--) - bios++; - - if (strcmp(val_str, bios->internal_name)) - changed = 1; - - id += 2; - break; - case CONFIG_MIDI_OUT: - 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 != c) - changed = 1; - - 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); - - if (val_int != c) - 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 += 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; - - SendMessage(h, WM_GETTEXT, 79, (LPARAM) ws); - wcstombs(s, ws, 512); - sscanf(s, "%i", &c); - - 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); - - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - for (; c > 0; c--) - selection++; - - if (val_int != selection->value) - changed = 1; - - id += 2; - break; - case CONFIG_HEX20: - val_int = config_get_hex20((char *) config_device.name, - (char *) config->name, config->default_int); - - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - for (; c > 0; c--) - selection++; - - if (val_int != selection->value) - changed = 1; - - id += 2; - break; - } - config++; - } - - if (!changed) { - deviceconfig_changed = 0; - EndDialog(hdlg, 0); - return TRUE; - } - - deviceconfig_changed = 1; - - id = IDC_CONFIG_BASE; - config = config_device.dev->config; - - while (config->type != -1) { - selection = config->selection; - h = GetDlgItem(hdlg, id); - - switch (config->type) { - case CONFIG_BINARY: - config_set_int((char *) config_device.name, - (char *) config->name, SendMessage(h, BM_GETCHECK, 0, 0)); - - 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; - 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); - - 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); - - 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); - - 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); - - 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; - - data_block = malloc(16384); - 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; - - data = (uint16_t *) (dlg + 1); - - *data++ = 0; /*no menu*/ - *data++ = 0; /*predefined dialog box class*/ - - 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++; - - while (config->type != -1) { - 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->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX; - - 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 */ - - y += 20; - break; - - 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->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, config->description, -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; - case CONFIG_SPINNER: - /*Spinner*/ - item = (DLGITEMTEMPLATE *) data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 140; - item->cy = 14; - - 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 += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); - *data++ = 0; /* no creation 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++; - - 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; - case CONFIG_STRING: - /*Editable Text*/ - item = (DLGITEMTEMPLATE *) data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 140; - item->cy = 14; - - 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 += MultiByteToWideChar(CP_ACP, 0, "", -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; - case CONFIG_FNAME: - /*File*/ - item = (DLGITEMTEMPLATE *) data; - item->x = 70; - item->y = y; - item->id = id++; - - item->cx = 100; - item->cy = 14; - - 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 += MultiByteToWideChar(CP_ACP, 0, "", -1, data, 256); - *data++ = 0; /* no creation data */ - - if (((uintptr_t) data) & 2) - data++; - - /* Button */ - item = (DLGITEMTEMPLATE *) data; - item->x = 175; - item->y = y; - item->id = id++; - - item->cx = 35; - item->cy = 14; - - 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->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; /* 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, "Cancel", -1, data, 50); - *data++ = 0; /* no creation data */ - - dlg->cy = y + 25; - - device_set_context(&config_device, device, inst); - - DialogBoxIndirect(hinstance, dlg, hwnd, deviceconfig_dlgproc); - - free(data_block); - - return deviceconfig_changed; -} - -uint8_t -deviceconfig_open(HWND hwnd, const device_t *device) -{ - return deviceconfig_inst_open(hwnd, device, 0); -} diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c deleted file mode 100644 index 15b00bf3f..000000000 --- a/src/win/win_dialog.c +++ /dev/null @@ -1,256 +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. - * - * Several dialogs for the application. - * - * - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#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/ui.h> -#include <86box/win.h> - -#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; - -int -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]; - 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; - else - 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; - - 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; - - 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 (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 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; - } - - /* Configure the rest of the TaskDialog. */ - tdconfig.cbSize = sizeof(tdconfig); - tdconfig.hwndParent = hwndMain; - if (flags & MBX_LINKS) - tdconfig.dwFlags = TDF_USE_COMMAND_LINKS; - tdconfig.pszWindowTitle = MAKEINTRESOURCE(IDS_STRINGS); - if (header) - tdconfig.pszMainInstruction = STRING_OR_RESOURCE(header); - tdconfig.pButtons = tdbuttons; - if (flags & MBX_DONTASK) - 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; - - /* 10 is added to the return value if "don't show again" is checked. */ - if (checked) - ret += 10; - - return ret; -} - -int -file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, WCHAR *title, int save) -{ - OPENFILENAME ofn; - 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; - - /* - * 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)); - 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; - if (title) - ofn.lpstrTitle = title; - - /* Display the Open dialog box. */ - old_dopause = dopause; - plat_pause(1); - if (save) - r = GetSaveFileName(&ofn); - else - r = GetOpenFileName(&ofn); - plat_pause(old_dopause); - - plat_chdir(usr_path); - - if (r) { - c16stombs(openfilestring, wopenfilestring, sizeof(openfilestring)); - filterindex = ofn.nFilterIndex; - - return 0; - } - - return 1; -} - -int -file_dlg(HWND hwnd, WCHAR *f, char *fn, char *title, int save) -{ - WCHAR ufn[512]; - WCHAR title_buf[512]; - - if (fn) - mbstoc16s(ufn, fn, strlen(fn) + 1); - if (title) - mbstoc16s(title_buf, title, sizeof title_buf); - - 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]; - 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)); -} - -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)); -} - -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)); -} diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c deleted file mode 100644 index 24690f2ba..000000000 --- a/src/win/win_dynld.c +++ /dev/null @@ -1,83 +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. - * - * Try to load a support DLL. - * - * - * - * Authors: Fred N. van Kempen, - * - * Copyright 2017-2018 Fred N. van Kempen - * Copyright 2021-2023 Jasmine Iwanek. - */ -#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; - 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 (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; - } - - /* 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/win/win_icon.c b/src/win/win_icon.c deleted file mode 100644 index f3426b8b5..000000000 --- a/src/win/win_icon.c +++ /dev/null @@ -1,168 +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. - * - * Implement the application's icon changing system. - * - * - * - * Authors: Laci bá' - * - * Copyright 2021 Laci bá'. - * Copyright 2021-2023 Jasmine Iwanek. - */ - -#include -#include -#include -#include -#include -#include -#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(void) -{ - for (uint16_t i = 0; i < 256; i++) - if (hIcon[i] != 0) { - DestroyIcon(hIcon[i]); - hIcon[i] = 0; - } -} - -void -win_system_icon_set(void) -{ - int x = win_get_system_metrics(SM_CXSMICON, dpi); - int y = win_get_system_metrics(SM_CYSMICON, dpi); - - 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; -} _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" } -}; - -void -win_get_icons_path(char *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_clear_icon_set(); - win_system_icon_set(); - - if (strlen(icon_set) == 0) { - ToolBarLoadIcons(); - return; - } - - 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 deleted file mode 100644 index df8a99a05..000000000 --- a/src/win/win_joystick.cpp +++ /dev/null @@ -1,324 +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. - * - * Joystick interface to host device. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define DIRECTINPUT_VERSION 0x0800 -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/gameport.h> -#include <86box/win.h> - -#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]; - -#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); - } -} -#else -# define joystick_log(fmt, ...) -#endif - -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; - - return DIENUM_CONTINUE; -} - -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++; - } - } 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++; - } - } - - return DIENUM_CONTINUE; -} - -void -joystick_init() -{ - 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"); - - if (FAILED(lpdi->EnumDevices(DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY))) - fatal("joystick_init : EnumDevices failed\n"); - - 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); - - 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() -{ - 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) -{ - 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]; - } else - return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; -} - -void -joystick_process(void) -{ - int c; - int d; - - 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 (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 - 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(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 deleted file mode 100644 index c5c2a3d6e..000000000 --- a/src/win/win_joystick_rawinput.c +++ /dev/null @@ -1,490 +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. - * - * RawInput joystick interface. - * - * - * - * Authors: Miran Grca, - * GH Cao, - * Jasmine Iwanek, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2020 GH Cao. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#include -#include -#include -#include -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/gameport.h> -#include <86box/win.h> - -#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); - } -} -#else -# define joystick_log(fmt, ...) -#endif - -typedef struct { - HANDLE hdevice; - PHIDP_PREPARSED_DATA data; - - USAGE usage_button[256]; - - 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; - -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 & ((1ULL << 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 < 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_get_device_name(raw_joystick_t *rawjoy, plat_joystick_t *joy, PRID_DEVICE_INFO info) -{ - UINT size = 0; - WCHAR *device_name = NULL; - WCHAR device_desc_wide[200] = { 0 }; - - 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"); - - 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); - - 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 deleted file mode 100644 index f313522a9..000000000 --- a/src/win/win_joystick_xinput.c +++ /dev/null @@ -1,268 +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. - * - * Xinput joystick interface. - * - * - * - * Authors: Miran Grca, - * GH Cao, - * Jasmine Iwanek, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2019 GH Cao. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/gameport.h> -#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" - -#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); - } -} -#else -# define joystick_log(fmt, ...) -#endif - -plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -joystick_t joystick_state[MAX_JOYSTICKS]; -int joysticks_present = 0; - -XINPUT_STATE controllers[XINPUT_MAX_JOYSTICKS]; - -void -joystick_init() -{ - atexit(joystick_close); - - joysticks_present = 0; - - memset(controllers, 0, sizeof(XINPUT_STATE) * XINPUT_MAX_JOYSTICKS); - - for (uint8_t c = 0; c < XINPUT_MAX_JOYSTICKS; c++) { - int value = XInputGetState(c, &controllers[c]); - if (value != ERROR_SUCCESS) - continue; - memcpy(plat_joystick_state[c].name, XINPUT_NAME, sizeof(XINPUT_NAME)); - - plat_joystick_state[c].nr_axes = 8; - - /* analog stick */ - memcpy(plat_joystick_state[c].axis[0].name, XINPUT_NAME_LX, sizeof(XINPUT_NAME_LX)); - plat_joystick_state[c].axis[0].id = 0; /* X axis */ - memcpy(plat_joystick_state[c].axis[1].name, XINPUT_NAME_LY, sizeof(XINPUT_NAME_LY)); - plat_joystick_state[c].axis[1].id = 1; /* Y axis */ - memcpy(plat_joystick_state[c].axis[2].name, XINPUT_NAME_RX, sizeof(XINPUT_NAME_RX)); - plat_joystick_state[c].axis[2].id = 3; /* RX axis */ - memcpy(plat_joystick_state[c].axis[3].name, XINPUT_NAME_RY, sizeof(XINPUT_NAME_RY)); - plat_joystick_state[c].axis[3].id = 4; /* RY axis */ - - /* d-pad, assigned to Z and RZ */ - memcpy(plat_joystick_state[c].axis[4].name, XINPUT_NAME_DPAD_X, sizeof(XINPUT_NAME_DPAD_X)); - plat_joystick_state[c].axis[4].id = 2; - memcpy(plat_joystick_state[c].axis[5].name, XINPUT_NAME_DPAD_Y, sizeof(XINPUT_NAME_DPAD_Y)); - plat_joystick_state[c].axis[5].id = 5; - - /* Analog trigger */ - memcpy(plat_joystick_state[c].axis[6].name, XINPUT_NAME_LT, sizeof(XINPUT_NAME_LT)); - plat_joystick_state[c].axis[6].id = 6; - memcpy(plat_joystick_state[c].axis[7].name, XINPUT_NAME_RT, sizeof(XINPUT_NAME_RT)); - plat_joystick_state[c].axis[7].id = 7; - - plat_joystick_state[c].nr_buttons = 12; - memcpy(plat_joystick_state[c].button[0].name, XINPUT_NAME_A, sizeof(XINPUT_NAME_A)); - memcpy(plat_joystick_state[c].button[1].name, XINPUT_NAME_B, sizeof(XINPUT_NAME_B)); - memcpy(plat_joystick_state[c].button[2].name, XINPUT_NAME_X, sizeof(XINPUT_NAME_X)); - memcpy(plat_joystick_state[c].button[3].name, XINPUT_NAME_Y, sizeof(XINPUT_NAME_Y)); - memcpy(plat_joystick_state[c].button[4].name, XINPUT_NAME_LB, sizeof(XINPUT_NAME_LB)); - memcpy(plat_joystick_state[c].button[5].name, XINPUT_NAME_RB, sizeof(XINPUT_NAME_RB)); - memcpy(plat_joystick_state[c].button[6].name, XINPUT_NAME_LT, sizeof(XINPUT_NAME_LT)); - memcpy(plat_joystick_state[c].button[7].name, XINPUT_NAME_RT, sizeof(XINPUT_NAME_RT)); - memcpy(plat_joystick_state[c].button[8].name, XINPUT_NAME_BACK, sizeof(XINPUT_NAME_BACK)); - memcpy(plat_joystick_state[c].button[9].name, XINPUT_NAME_START, sizeof(XINPUT_NAME_START)); - memcpy(plat_joystick_state[c].button[10].name, XINPUT_NAME_LS, sizeof(XINPUT_NAME_LS)); - memcpy(plat_joystick_state[c].button[11].name, XINPUT_NAME_RS, sizeof(XINPUT_NAME_RS)); - - plat_joystick_state[c].nr_povs = 0; - - joysticks_present++; - } - joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); -} - -void -joystick_close() -{ - // -} - -void -joystick_poll(void) -{ - for (int c = 0; c < joysticks_present; c++) { - int value = XInputGetState(c, &controllers[c]); - if (value != ERROR_SUCCESS) - continue; - - 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].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; - - 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) -{ - 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) - return; - - joystick_poll(); - - 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; - } - } -} - -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 deleted file mode 100644 index 190338d3e..000000000 --- a/src/win/win_jsconf.c +++ /dev/null @@ -1,538 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/device.h> -#include <86box/gameport.h> -#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 uint8_t joystickconfig_changed = 0; - -static void -rebuild_axis_button_selections(HWND hdlg) -{ - 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); - - 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); - - 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); - } else - EnableWindow(h, FALSE); - - id += 2; - } - - for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) { - h = GetDlgItem(hdlg, id); - SendMessage(h, CB_RESETCONTENT, 0, 0); - - 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); - - 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) -{ - 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; - - return SLIDER | (axis_sel >> 1); -} - -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; - - 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__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -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; - - 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"); - - 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); - 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; -} - -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]; - - joystickconfig_changed = 0; - - joystick_nr = joy_nr; - joystick_config_type = type; - - 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->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_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++ = 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 deleted file mode 100644 index 54be91e6c..000000000 --- a/src/win/win_keyboard.c +++ /dev/null @@ -1,198 +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. - * - * Windows raw keyboard input handler. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define _WIN32_WINNT 0x0501 -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/plat.h> -#include <86box/win.h> - -static uint16_t scancode_map[768]; - -/* This is so we can disambiguate scan codes that would otherwise conflict and get - passed on incorrectly. */ -static UINT16 -convert_scan_code(UINT16 scan_code) -{ - if ((scan_code & 0xff00) == 0xe000) - scan_code = (scan_code & 0xff) | 0x0100; - - if (scan_code == 0xE11D) - 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; - - return scan_code; -} - -void -keyboard_getkeymap(void) -{ - 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; - 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. - * 512 bytes so this takes less memory, bit 9 set means E0 - * prefix. - */ - for (j = 0; j < 512; 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]; - - 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); - } -} - -void -keyboard_handle(PRAWINPUT raw) -{ - 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; - - if (kbd_req_capture && !mouse_capture && !video_fullscreen) - 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; - - /* 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]; - - /* 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; - - /* 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); - } -} diff --git a/src/win/win_media_menu.c b/src/win/win_media_menu.c deleted file mode 100644 index 549a495b9..000000000 --- a/src/win/win_media_menu.c +++ /dev/null @@ -1,766 +0,0 @@ -#define UNICODE -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/cdrom.h> -#include <86box/config.h> -#include <86box/device.h> -#include <86box/timer.h> -#include <86box/cassette.h> -#include <86box/cartridge.h> -#include <86box/fdd.h> -#include <86box/fdd_86f.h> -#include <86box/hdc.h> -#include <86box/language.h> -#include <86box/machine.h> -#include <86box/scsi_device.h> -#include <86box/mo.h> -#include <86box/plat.h> -#include <86box/scsi.h> -#include <86box/sound.h> -#include <86box/ui.h> -#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)) - -#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 char index_map[255]; - -static void -media_menu_set_ids(HMENU hMenu, int id) -{ - int c = GetMenuItemCount(hMenu); - - MENUITEMINFO mii = { 0 }; - 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); - } -} - -/* Loads the submenu from resource by name */ -static HMENU -media_menu_load_resource(wchar_t *lpName) -{ - HMENU loaded = LoadMenu(NULL, lpName); - - /* The actual submenu is in a dummy popup menu item */ - HMENU actual = GetSubMenu(loaded, 0); - - /* Now that we have our submenu, we can destroy the parent menu */ - RemoveMenu(loaded, (UINT_PTR) actual, MF_BYCOMMAND); - DestroyMenu(loaded); - - return actual; -} - -static void -media_menu_set_name_cassette(void) -{ - wchar_t name[512]; - wchar_t fn[512]; - MENUITEMINFO mii = { 0 }; - - if (strlen(cassette_fname) == 0) - _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_2149), fn); - } - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = name; - - SetMenuItemInfo(media_menu, (UINT_PTR) menus[CASSETTE_FIRST], FALSE, &mii); -} - -static void -media_menu_set_name_cartridge(int drive) -{ - wchar_t name[512]; - wchar_t fn[512]; - MENUITEMINFO mii = { 0 }; - - if (strlen(cart_fns[drive]) == 0) { - _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_2151), - drive + 1, fn); - } - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = name; - - SetMenuItemInfo(media_menu, (UINT_PTR) menus[CARTRIDGE_FIRST + drive], FALSE, &mii); -} - -static void -media_menu_set_name_floppy(int drive) -{ - 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); - if (strlen(floppyfns[drive]) == 0) { - _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_2109), - drive + 1, temp, fn); - } - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = name; - - SetMenuItemInfo(media_menu, (UINT_PTR) menus[FDD_FIRST + drive], FALSE, &mii); -} - -static void -media_menu_set_name_cdrom(int drive) -{ - 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); - - 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); - } - } else - _swprintf(name, plat_get_string(IDS_5120), drive + 1, temp, plat_get_string(IDS_2057)); - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = name; - - SetMenuItemInfo(media_menu, (UINT_PTR) menus[CDROM_FIRST + drive], FALSE, &mii); -} - -static void -media_menu_set_name_zip(int drive) -{ - 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); - - 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)); - } else { - 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.dwTypeData = name; - - SetMenuItemInfo(media_menu, (UINT_PTR) menus[ZIP_FIRST + drive], FALSE, &mii); -} - -static void -media_menu_set_name_mo(int drive) -{ - 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); - - temp = plat_get_string(id); - - if (strlen(mo_drives[drive].image_path) == 0) { - _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_2116), - drive + 1, temp, fn); - } - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = name; - - 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); - } 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); - } - - 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); - else - 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); - } 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); - } - - 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); - else - 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 | (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_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); - else - 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); - else - 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); - else - 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); - else - 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); - else - EnableMenuItem(menus[i], IDM_MO_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); - - media_menu_set_name_mo(id); -} - -static void -media_menu_load_submenus(void) -{ - memset(index_map, -1, sizeof(index_map)); - - int curr = 0; - - 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 < 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 < 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); - } -} - -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; - 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; - 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; - return mo_drives[i].bus_type != 0; -} - -void -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); - - /* 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(); - } - 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 < 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 < 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(void) -{ - HMENU hMenu; - LPWSTR lpMenuName; - - hMenu = GetMenu(hwndMain); - media_menu = CreatePopupMenu(); - - /* Get the menu name */ - 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); - - /* Clean up */ - DrawMenuBar(hwndMain); - free(lpMenuName); -} - -void -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); - - /* Load the submenus for each drive type. */ - media_menu_load_submenus(); - - /* Populate the Media and status bar menus. */ - media_menu_reset(); -} - -int -media_menu_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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_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_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_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_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_2110, floppyfns[id], NULL, 0); - if (!ret) - floppy_mount(id, openfilestring, wp); - 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_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_RELOAD: - cdrom_reload(id); - 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_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_NEW: - NewFloppyDialogCreate(hwnd, id | 0x80, 0); /* NewZIPDialogCreate */ - 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_EJECT: - zip_eject(id); - break; - - case IDM_ZIP_RELOAD: - zip_reload(id); - break; - - case IDM_MO_IMAGE_NEW: - NewFloppyDialogCreate(hwnd, id | 0x100, 0); /* NewZIPDialogCreate */ - 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_EJECT: - mo_eject(id); - break; - - case IDM_MO_RELOAD: - mo_reload(id); - break; - - default: - return 0; - } - - 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) -{ - return menus[MO_FIRST + id]; -} diff --git a/src/win/win_mouse.c b/src/win/win_mouse.c deleted file mode 100644 index f2b185eaa..000000000 --- a/src/win/win_mouse.c +++ /dev/null @@ -1,125 +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. - * - * RawInput mouse interface. - * - * - * - * 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; - -void -win_mouse_init(void) -{ - atexit(win_mouse_close); - - 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"); -} - -void -win_mouse_handle(PRAWINPUT raw) -{ - 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; - - b = mouse_get_buttons_ex(); - - /* 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_MIDDLE_BUTTON_DOWN) - b |= 4; - else if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) - b &= ~4; - - 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. - */ - 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)); -} diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c deleted file mode 100644 index d0a245a45..000000000 --- a/src/win/win_new_floppy.c +++ /dev/null @@ -1,842 +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 the New Floppy Image dialog. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2019 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/disksizes.h> -#include <86box/plat.h> -#include <86box/random.h> -#include <86box/ui.h> -#include <86box/scsi_device.h> -#include <86box/mo.h> -#include <86box/zip.h> -#include <86box/win.h> - -static unsigned char *empty; - -static int -create_86f(char *file_name, disk_size_t disk_size, uint8_t rpm_mode) -{ - 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; - 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. */ - - tflags = disk_size.data_rate; /* Data rate. */ - tflags |= (disk_size.encoding << 3); /* Encoding. */ - tflags |= (disk_size.rpm << 5); /* RPM. */ - - switch (disk_size.hole) { - 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); - - memset(tarray, 0, 2048); - memset(empty, 0, array_size); - - fp = plat_fopen(file_name, "wb"); - if (!fp) - return 0; - - 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; - - for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) - tarray[i] = track_base + (i * track_size); - - 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, fp); - fwrite(&index_hole_pos, 4, 1, fp); - fwrite(empty, 1, array_size, fp); - } - - free(empty); - - fclose(fp); - - return 1; -} - -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 *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; - - 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; - 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; - - if (!is_zip && !is_mo && is_fdi) { - 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; - - 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); - - 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; - - *(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(); - - 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[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; - } - - fwrite(empty, 1, total_size, fp); - free(empty); - - 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 *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; - MSG msg; - - 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; - 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 (is_zdi) - pbar_max += base; - pbar_max >>= 11; - pbar_max--; - - h = GetDlgItem(hwnd, IDC_COMBO_RPM_MODE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hwnd, IDT_FLP_RPM_MODE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) pbar_max); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - h = GetDlgItem(hwnd, IDT_FLP_PROGRESS); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - - h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); - pbar_max++; - - if (is_zdi) { - 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; - - 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); - } - - fwrite(&empty[0x0800], 1, 2048, fp); - free(empty); - - SendMessage(h, PBM_SETPOS, (WPARAM) 2, (LPARAM) 0); - - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - 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; - - *(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; - - /* 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; - - 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); - - 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[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 */ - } 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; - - *(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; - - /* 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; - - /* 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(); - - 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[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; - - /* Root directory = 0x3FE00 - Data = 0x38200 */ - } - - 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); - } - } - - free(empty); - - 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 *fp; - const mo_type_t *dp = &mo_types[disk_size]; - 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; - - 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_size2 = (total_size >> 20) << 20; - total_size2 = total_size - total_size2; - - pbar_max = total_size; - pbar_max >>= 20; - blocks_num = pbar_max; - if (is_mdi) - pbar_max++; - if (total_size2 == 0) - pbar_max++; - - j = is_mdi ? 1 : 0; - - h = GetDlgItem(hwnd, IDC_COMBO_RPM_MODE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hwnd, IDT_FLP_RPM_MODE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) pbar_max - 1); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - h = GetDlgItem(hwnd, IDT_FLP_PROGRESS); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - - h = GetDlgItem(hwnd, IDC_PBAR_IMG_CREATE); - - if (is_mdi) { - 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; - - 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); - } - - fwrite(&empty[0x0800], 1, 2048, fp); - free(empty); - - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - - 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); - } - - for (uint32_t i = 0; i < blocks_num; i++) { - fwrite(empty, 1, 1048576, fp); - - SendMessage(h, PBM_SETPOS, (WPARAM) i + j, (LPARAM) 0); - - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - if (total_size2 > 0) { - fwrite(empty2, 1, total_size2, fp); - - SendMessage(h, PBM_SETPOS, (WPARAM) pbar_max - 1, (LPARAM) 0); - - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - if (empty2 != NULL) - free(empty2); - free(empty); - - fclose(fp); - - return 1; -} - -static int fdd_id; -static int sb_part; - -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; - - h = hwndMain; - hwndMain = hwnd; - - i = ui_msgbox_header(flags, header, message); - - hwndMain = h; - - 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; - - h = hwndMain; - hwndMain = hwnd; - - i = ui_msgbox_ex(flags, header, message, btn1, btn2, btn3); - - hwndMain = h; - - return i; -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) -{ - 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_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_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; - } - - return FALSE; -} - -void -NewFloppyDialogCreate(HWND hwnd, int id, int part) -{ - fdd_id = id & 0x7f; - sb_part = part; - 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; - } - DialogBox(hinstance, (LPCTSTR) DLG_NEW_FLOPPY, hwnd, NewFloppyDialogProcedure); -} diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c deleted file mode 100644 index 094b3d063..000000000 --- a/src/win/win_opengl.c +++ /dev/null @@ -1,1002 +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. - * - * 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 - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#define UNICODE -#include -#include -#include -#include -#include - -#include -#include -#include - -#if !defined(_MSC_VER) || defined(__clang__) -# include -#else -typedef LONG atomic_flag; -# 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) */ - -/** - * @brief A dedicated OpenGL thread. - * OpenGL context's don't handle multiple threads well. - */ -static thread_t *thread = NULL; - -/** - * @brief A window usable with an OpenGL context - */ -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]; -} 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. */ -} blit_info_t; - -/** - * @brief Array of blit_infos, one for each buffer. - */ -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; -} 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; -} options = { 0 }; - -/** - * @brief Identifiers to OpenGL objects and uniforms. - */ -typedef struct -{ - GLuint vertexArrayID; - GLuint vertexBufferID; - GLuint textureID; - GLuint unpackBufferID; - GLuint shader_progID; - - /* Uniforms */ - - 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) -{ - 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; - } - - SetWindowLong(window_hwnd, GWL_STYLE, style); - SetWindowLong(window_hwnd, GWL_EXSTYLE, ex_style); - - SetParent(window_hwnd, enable ? parent : NULL); -} - -/** - * @brief Windows message handler for our window. - * @param message - * @param wParam - * @param lParam - * @param fullscreen - * @return Was message handled - */ -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)); - - /* 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; - - /* 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; -} - -/** - * @brief (Re-)apply shaders to OpenGL context. - * @param gl Identifiers from initialize - */ -static void -apply_shaders(gl_identifiers *gl) -{ - GLuint old_shader_ID = 0; - - 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 (gl->shader_progID == 0) - gl->shader_progID = load_default_shaders(); - - glUseProgram(gl->shader_progID); - - /* 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 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 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 */ - - 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) -{ - /* 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); - - glBindVertexArray(gl->vertexArrayID); - - 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); - - 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); - - glGenBuffers(1, &gl->unpackBufferID); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->unpackBufferID); - - 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); - - 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); - } - - 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); - } - - glClearColor(0.f, 0.f, 0.f, 1.f); - - apply_shaders(gl); - - return 1; -} - -/** - * @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); - - 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 int frame_counter = 0; - - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - SDL_GL_SwapWindow(window); - - 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(void) -{ - if (window != NULL) { - SDL_DestroyWindow(window); - window = NULL; - } - - 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); - - _endthread(); -} - -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); -} - -/** - * @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(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; - 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); - - /* 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, int monitor_index) -{ - 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; - } - - 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)); - - if (monitors[0].mon_screenshots) - video_screenshot(blit_info[write_pos].buffer, 0, 0, ROW_LENGTH); - - video_blit_complete(); - - blit_info[write_pos].w = w; - blit_info[write_pos].h = h; - - write_pos = (write_pos + 1) % BUFFERCOUNT; - - ReleaseSemaphore(sync_objects.blit_waiting, 1, NULL); -} - -static int -framerate_to_frametime(int framerate) -{ - if (framerate < 0) - return -1; - - return (int) ceilf(1.e6f / (float) framerate); -} - -int -opengl_init(HWND hwnd) -{ - 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); - - 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; - - GetWindowRect(parent, &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(); - - 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(); - - blit_info = (blit_info_t *) malloc(BUFFERCOUNT * sizeof(blit_info_t)); - memset(blit_info, 0, BUFFERCOUNT * sizeof(blit_info_t)); - - /* 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); - - write_pos = 0; - - thread = thread_create(opengl_main, NULL); - - atexit(opengl_close); - - video_setblit(opengl_blit); - - return 1; -} - -int -opengl_pause(void) -{ - return 0; -} - -void -opengl_close(void) -{ - if (thread == NULL) - return; - - SetEvent(sync_objects.closing); - - thread_wait(thread); - - thread_close_mutex(resize_info.mutex); - thread_close_mutex(options.mutex); - - thread = NULL; - - free(blit_info); - - for (int i = 0; i < sizeof(sync_objects) / sizeof(HANDLE); i++) { - CloseHandle(sync_objects.asArray[i]); - sync_objects.asArray[i] = NULL; - } - - parent = NULL; -} - -void -opengl_set_fs(int fs) -{ - if (thread == NULL) - return; - - thread_wait_mutex(resize_info.mutex); - - resize_info.fullscreen = fs; - resize_info.scaling_mode = video_fullscreen_scale; - - thread_release_mutex(resize_info.mutex); - - SetEvent(sync_objects.resize); -} - -void -opengl_resize(int w, int h) -{ - if (thread == NULL) - return; - - thread_wait_mutex(resize_info.mutex); - - resize_info.width = w; - resize_info.height = h; - resize_info.scaling_mode = video_fullscreen_scale; - - thread_release_mutex(resize_info.mutex); - - SetEvent(sync_objects.resize); -} - -void -opengl_reload(void) -{ - if (thread == NULL) - return; - - 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; - } - - if (video_filter_method != options.filter) { - options.filter = video_filter_method; - options.filter_changed = 1; - } - - 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 deleted file mode 100644 index 9689f3ab2..000000000 --- a/src/win/win_opengl_glslp.c +++ /dev/null @@ -1,270 +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. - * - * File parser for .glslp and .glsl shader files - * in the format of libretro. - * - * TODO: Read .glslp files for multipass shaders and settings. - * - * - * - * 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 - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include - -#include -#include -#include -#include - -#include <86box/86box.h> -#include <86box/plat.h> -#include <86box/win_opengl_glslp.h> - -/** - * @brief Default vertex shader. - */ -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\ -}\n"; - -/** - * @brief Default fragment shader. - */ -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\ -}\n"; - -/** - * @brief OpenGL shader program build targets - */ -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) -{ - FILE *fp = plat_fopen(path, "rb"); - - if (fp != NULL) { - /* get file size */ - fseek(fp, 0, SEEK_END); - - size_t file_size = (size_t) ftell(fp); - - fseek(fp, 0, SEEK_SET); - - /* read to buffer and close */ - char *content = (char *) malloc(sizeof(char) * (file_size + 1)); - - if (!content) - return NULL; - - size_t length = fread(content, sizeof(char), file_size, fp); - - 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) -{ - 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 (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); - - 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); - - 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; - } - - /* 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); - - free(info_log_text); - - return 0; - } - - return 1; -} - -/** - * @brief Compile custom shaders into a program. - * @return Shader program identifier. - */ -GLuint -load_custom_shaders(const char *path) -{ - char *shader = read_file_to_string(path); - - 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 }; - - /* 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 */ - const char *version_end = strchr(version_start, '\n'); - - if (version_end != NULL) { - char version[30] = ""; - - size_t version_len = MIN(version_end - version_start + 1, 29); - - strncat(version, version_start, version_len); - - /* 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); - } - - 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(fragment_id, 3, fragment_sources, NULL); - glCompileShader(fragment_id); - success *= check_status(fragment_id, OPENGL_BUILD_TARGET_FRAGMENT, path); - - free(shader); - - GLuint prog_id = 0; - - 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); - - glDetachShader(prog_id, vertex_id); - glDetachShader(prog_id, fragment_id); - } - - glDeleteShader(vertex_id); - glDeleteShader(fragment_id); - - return prog_id; - } - return 0; -} - -/** - * @brief Compile default shaders into a program. - * @return Shader program identifier. - */ -GLuint -load_default_shaders(void) -{ - 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(fragment_id, 1, &fragment_shader, NULL); - glCompileShader(fragment_id); - - GLuint prog_id = glCreateProgram(); - - glAttachShader(prog_id, vertex_id); - glAttachShader(prog_id, fragment_id); - - glLinkProgram(prog_id); - - glDetachShader(prog_id, vertex_id); - glDetachShader(prog_id, fragment_id); - - glDeleteShader(vertex_id); - glDeleteShader(fragment_id); - - return prog_id; -} diff --git a/src/win/win_preferences.c b/src/win/win_preferences.c deleted file mode 100644 index ee93321a8..000000000 --- a/src/win/win_preferences.c +++ /dev/null @@ -1,290 +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 the dialog for changing the program's language and other global settings. - * - * - * - * Authors: Laci bá' - * - * Copyright 2021 Laci bá' - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/plat.h> -#include <86box/sound.h> -#include <86box/win.h> -#include <86box/ui.h> -#include <86box/resource.h> - -/* Language */ -static LCID temp_language; - -static char temp_icon_set[256] = { 0 }; - -int enum_helper; -int c; - -HWND hwndPreferences; - -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; -} - -/* 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); -} - -/* 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_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. */ -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 -preferences_indexof(HWND combo, LPARAM itemdata) -{ - 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); - - /* Iconset */ - strcpy(icon_set, temp_icon_set); - win_load_icon_set(); - - /* Update title bar */ - update_mouse_msg(); - - /* Update status bar */ - config_changed = 1; - ui_sb_set_ready(-1); - ui_sb_update_panes(); - ui_sb_update_text(); - - /* Save the language changes */ - config_save(); -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -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_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: - { - 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; -} - -void -PreferencesDlgCreate(HWND hwnd) -{ - DialogBox(hinstance, (LPCTSTR) DLG_PREFERENCES, hwnd, PreferencesDlgProcedure); -} diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c deleted file mode 100644 index ea9c8455d..000000000 --- a/src/win/win_sdl.c +++ /dev/null @@ -1,626 +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. - * - * 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 - * covers the entire desktop. - * - * - * - * Authors: Fred N. van Kempen, - * 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: - * - * 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. - */ -#define UNICODE -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -#include -#include -#include -#include -/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */ -#undef HAVE_STDARG_H -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/plat.h> -#include <86box/plat_dynld.h> -#include <86box/video.h> -#include <86box/ui.h> -#include <86box/win.h> -#include <86box/win_sdl.h> -#include <86box/version.h> - -#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; -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; - 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; - - /* Stored position and size for windowed mode */ - SDL_Rect windowed; - - SDL_DisplayMode fullscreen_mode; - - float brightness; - Uint16 *gamma; - Uint16 *saved_gamma; /* (just offset into gamma) */ - - SDL_Surface *surface; - SDL_bool surface_valid; - - SDL_bool is_hiding; - SDL_bool is_destroying; - - void *shaper; - - SDL_HitTest hit_test; - void *hit_test_data; - - void *data; - - void *driverdata; - - SDL_Window *prev; - 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); - } -} -#else -# 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; - } else { - ratio = ceil(*d / *g); - *d = *g / ratio; - } -} - -static void -sdl_stretch(int *w, int *h, int *x, int *y) -{ - 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; - hsr = hw / hh; - - switch (video_fullscreen_scale) { - 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, int monitor_index) -{ - SDL_Rect r_src; - 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) || monitor_index >= 1) { - video_blit_complete_monitor(monitor_index); - return; - } - - SDL_LockMutex(sdl_mutex); - - r_src.x = x; - r_src.y = y; - r_src.w = w; - r_src.h = h; - SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), 2048 * sizeof(uint32_t)); - - if (monitors[0].mon_screenshots) - video_screenshot(buffer32->dat, x, y, 2048); - - video_blit_complete(); - - SDL_RenderClear(sdl_render); - - r_src.x = x; - r_src.y = y; - r_src.w = w; - r_src.h = 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_RenderPresent(sdl_render); - SDL_UnlockMutex(sdl_mutex); -} - -static void -sdl_blit_ex(int x, int y, int w, int h, UNUSED(int monitor_index)) -{ - SDL_Rect r_src; - 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; - } - - SDL_LockMutex(sdl_mutex); - - SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch); - - 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[0].mon_screenshots) - video_screenshot((uint32_t *) pixeldata, 0, 0, 2048); - - SDL_UnlockTexture(sdl_tex); - - video_blit_complete(); - - SDL_RenderClear(sdl_render); - - r_src.x = 0; - r_src.y = 0; - r_src.w = w; - r_src.h = 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_RenderPresent(sdl_render); - SDL_UnlockMutex(sdl_mutex); -} - -static void -sdl_destroy_window(void) -{ - if (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_DestroyRenderer also automatically destroys all associated textures. */ - if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; - } -} - -void -sdl_close(void) -{ - if (sdl_mutex != NULL) - SDL_LockMutex(sdl_mutex); - - /* Unregister our renderer! */ - video_setblit(NULL); - - if (sdl_enabled) - sdl_enabled = 0; - - if (sdl_mutex != NULL) { - SDL_DestroyMutex(sdl_mutex); - sdl_mutex = NULL; - } - - sdl_destroy_texture(); - sdl_destroy_window(); - ImmAssociateContext(hwndMain, NULL); - SetFocus(hwndMain); - - if (sdl_parent_hwnd != NULL) { - DestroyWindow(sdl_parent_hwnd); - sdl_parent_hwnd = NULL; - } - - /* Quit. */ - SDL_Quit(); - sdl_flags = -1; -} - -static int old_capture = 0; - -static void -sdl_select_best_hw_driver(void) -{ - SDL_RendererInfo renderInfo; - - 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"); - } else - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); - - sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); -} - -static void -sdl_reinit_texture(void) -{ - if (sdl_flags == -1) - return; - - sdl_destroy_texture(); - sdl_init_texture(); -} - -void -sdl_set_fs(int fs) -{ - 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); - - /* 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; - } else { - 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); - } - - sdl_fs = fs; - - if (fs) - sdl_flags |= RENDERER_FULL_SCREEN; - else - sdl_flags &= ~RENDERER_FULL_SCREEN; - -#if 0 - sdl_reinit_texture(); -#endif - sdl_enabled = 1; - SDL_UnlockMutex(sdl_mutex); -} - -static int -sdl_init_common(int flags) -{ - wchar_t temp[128]; - SDL_version ver; - - sdl_log("SDL: init (flags=%d)\n", flags); - - /* Get and log the version of the DLL we are using. */ - SDL_GetVersion(&ver); - sdl_log("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch); - - /* Initialize the SDL system. */ - if (SDL_Init(SDL_INIT_VIDEO) < 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(); - } - - /* Get the size of the (current) desktop. */ - sdl_w = GetSystemMetrics(SM_CXSCREEN); - sdl_h = GetSystemMetrics(SM_CYSCREEN); - - /* 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); - ShowWindow(sdl_parent_hwnd, FALSE); - - sdl_flags = flags; - - if (sdl_win == NULL) { - sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError()); - } - - sdl_win = SDL_CreateWindowFrom((void *) hwndRender); - sdl_init_texture(); - sdl_set_fs(video_fullscreen & 1); - - /* Make sure we get a clean exit. */ - atexit(sdl_close); - - /* Register our renderer! */ - video_setblit((video_grayscale || invert_display) ? sdl_blit_ex : sdl_blit); - - sdl_enabled = 1; - sdl_mutex = SDL_CreateMutex(); - - return 1; -} - -int -sdl_inits(UNUSED(HWND h)) -{ - return sdl_init_common(0); -} - -int -sdl_inith(UNUSED(HWND h)) -{ - return sdl_init_common(RENDERER_HARDWARE); -} - -int -sdl_initho(UNUSED(HWND h)) -{ - return sdl_init_common(RENDERER_HARDWARE | RENDERER_OPENGL); -} - -int -sdl_pause(void) -{ - return 0; -} - -void -sdl_resize(int x, int y) -{ - int ww = 0; - int wh = 0; - int wx = 0; - int wy = 0; - - if (video_fullscreen & 2) - return; - - if ((x == cur_w) && (y == cur_h)) - return; - - SDL_LockMutex(sdl_mutex); - - ww = x; - wh = y; - - if (sdl_fs) { - sdl_stretch(&ww, &wh, &wx, &wy); - MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); - } - - cur_w = x; - cur_h = y; - - cur_wx = wx; - cur_wy = wy; - cur_ww = ww; - cur_wh = wh; - - SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); - SDL_SetWindowPosition(sdl_win, cur_wx, cur_wy); - - sdl_reinit_texture(); - - SDL_UnlockMutex(sdl_mutex); -} - -void -sdl_enable(int enable) -{ - if (sdl_flags == -1) - return; - - SDL_LockMutex(sdl_mutex); - sdl_enabled = !!enable; - - if (enable == 1) { - 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_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); - - SDL_UnlockMutex(sdl_mutex); - } - - video_setblit((video_grayscale || invert_display) ? sdl_blit_ex : sdl_blit); -} diff --git a/src/win/win_settings.c b/src/win/win_settings.c deleted file mode 100644 index 139c387a8..000000000 --- a/src/win/win_settings.c +++ /dev/null @@ -1,5708 +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. - * - * Windows 86Box Settings dialog handler. - * - * - * - * Authors: Miran Grca, - * David Hrdlička, - * Jasmine Iwanek, - * - * 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 -#include -#include -#include -#undef BITMAP -#ifdef ENABLE_SETTINGS_LOG -# include -#endif -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include "cpu.h" -#include <86box/mem.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/timer.h> -#include <86box/cassette.h> -#include <86box/nvr.h> -#include <86box/machine.h> -#include <86box/gameport.h> -#include <86box/isamem.h> -#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> -#include <86box/hdd.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/zip.h> -#include <86box/mo.h> -#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" - -/* Icon, Bus, File, C, H, S, Size, Speed */ -#define C_COLUMNS_HARD_DISKS 7 - -#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; -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; -#ifdef USE_DYNAREC -static int temp_dynarec; -#endif -static int temp_fpu_softfloat; - -/* Video category */ -static int temp_gfxcard[2]; -static int temp_ibm8514; -static int temp_voodoo; -static int temp_xga; - -/* Input devices category */ -static int temp_mouse; -static int temp_joystick; - -/* Sound category */ -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[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 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; -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; -static int temp_isartc; -static int temp_isamem[ISAMEM_MAX]; - -static uint8_t temp_deviceconfig; - -/* Hard disks category */ -static hard_disk_t temp_hdd[HDD_NUM]; - -/* Floppy drives category */ -static int temp_fdd_types[FDD_NUM]; -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 zip_drive_t temp_zip_drives[ZIP_NUM]; -static mo_drive_t temp_mo_drives[MO_NUM]; - -static HWND hwndParentDialog; -static HWND hwndChildDialog; - -static uint32_t displayed_category = 0; - -extern int is486; -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; -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; -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; -static hard_disk_t *hdd_ptr; - -static wchar_t hd_file_name[512]; -static WCHAR device_name[512]; - -static int -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) -{ - HWND h; - - h = GetDlgItem(hdlg, id); - EnableWindow(h, condition ? TRUE : FALSE); - ShowWindow(h, condition ? SW_SHOW : SW_HIDE); -} - -static void -settings_listview_enable_styles(HWND hdlg, int id) -{ - HWND h; - - h = GetDlgItem(hdlg, id); - SetWindowTheme(h, L"Explorer", NULL); - ListView_SetExtendedListViewStyle(h, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); -} - -static void -settings_listview_select(HWND hdlg, int id, int selection) -{ - HWND h; - - h = GetDlgItem(hdlg, id); - ListView_SetItemState(h, selection, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); -} - -static void -settings_process_messages(void) -{ - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -static BOOL -image_list_init(HWND hdlg, int id, const uint8_t *icon_ids) -{ - HICON hiconItem; - HIMAGELIST hSmall; - HWND hwndList = GetDlgItem(hdlg, id); - - int i = 0; - - hSmall = ListView_GetImageList(hwndList, LVSIL_SMALL); - 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); - - while (1) { - if (icon_ids[i] == 0) - break; - - hiconItem = hIcon[icon_ids[i]]; - ImageList_AddIcon(hSmall, hiconItem); - - i++; - } - - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - 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; - - h = hwndMain; - hwndMain = hwndParentDialog; - - i = ui_msgbox_header(flags, header, message); - - hwndMain = h; - - return i; -} - -static int -settings_msgbox_ex(int flags, void *header, void *message, void *btn1, void *btn2, void *btn3) -{ - HWND h; - int i; - - h = hwndMain; - hwndMain = hwndParentDialog; - - i = ui_msgbox_ex(flags, header, message, btn1, btn2, btn3); - - hwndMain = h; - - return i; -} - -/* This does the initial read of global variables into the temporary ones. */ -static void -win_settings_init(void) -{ - int i = 0; - - /* 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; -#ifdef USE_DYNAREC - temp_dynarec = cpu_use_dynarec; -#endif - temp_fpu_softfloat = fpu_softfloat; - temp_fpu = fpu_type; - temp_sync = time_sync; - - /* Video category */ - 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_joystick = joystick_type; - - /* Sound category */ - 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 */ - 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[i]) == sizeof(net_cards_conf[i].host_dev_name)); -#endif - 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; - } - for (i = 0; i < SERIAL_MAX; i++) { - temp_serial[i] = com_ports[i].enabled; - temp_serial_passthrough_enabled[i] = serial_passthrough_enabled[i]; - } - - /* Storage devices category */ - for (i = 0; i < SCSI_BUS_MAX; 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_cassette = cassette_enable; - - mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 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)); - } - - /* 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); - } - - /* 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)); - } - 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)); - } - 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)); - } - - /* Other peripherals category */ - temp_bugger = bugger_enabled; - temp_postcard = postcard_enabled; - temp_isartc = isartc_type; - - /* ISA memory boards. */ - for (i = 0; i < ISAMEM_MAX; 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; - - /* Machine category */ - i = i || (machine != temp_machine); - i = i || (cpu_f != temp_cpu_f); - i = i || (cpu_waitstates != temp_wait_states); - i = i || (cpu != temp_cpu); - i = i || (mem_size != temp_mem_size); -#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[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 */ - 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 || (sound_is_float != temp_float); - i = i || (fm_driver != temp_fm_driver); - - /* Network category */ - 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 (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]); - } - - /* Storage devices category */ - 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); - i = i || (temp_ide_qua != ide_qua_enabled); - i = i || (temp_cassette != cassette_enable); - - /* Hard disks category */ - i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - - /* Floppy drives category */ - 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 */ - i = i || memcmp(cdrom, temp_cdrom, CDROM_NUM * sizeof(cdrom_t)); - i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); - i = i || memcmp(mo_drives, temp_mo_drives, MO_NUM * sizeof(mo_drive_t)); - - /* Other peripherals category */ - i = i || (temp_bugger != bugger_enabled); - i = i || (temp_postcard != postcard_enabled); - i = i || (temp_isartc != isartc_type); - - /* ISA memory boards. */ - 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) -{ - pc_reset_hard_close(); - - /* Machine category */ - machine = temp_machine; - cpu_f = temp_cpu_f; - cpu_waitstates = temp_wait_states; - cpu = temp_cpu; - mem_size = temp_mem_size; -#ifdef USE_DYNAREC - cpu_use_dynarec = temp_dynarec; -#endif - fpu_softfloat = temp_fpu_softfloat; - fpu_type = temp_fpu; - time_sync = temp_sync; - - /* Video category */ - 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; - joystick_type = temp_joystick; - - /* Sound category */ - 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 */ - 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 (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]; - } - - /* Storage devices category */ - 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 (uint8_t i = 0; i < HDD_NUM; i++) - hdd[i].priv = NULL; - - /* Floppy drives category */ - 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 (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 (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 (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; - postcard_enabled = temp_postcard; - isartc_type = temp_isartc; - - /* ISA memory boards. */ - for (uint8_t i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = temp_isamem[i]; - - /* Mark configuration as changed. */ - config_changed = 2; - - 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; - int type; - LPTSTR lptsTemp; - const char *stransi; - - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - - settings_reset_content(hdlg, IDC_COMBO_FPU); - c = 0; - while (1) { - 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); - - 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) -{ - int cpu_type; -#ifdef USE_DYNAREC - int cpu_flags; -#endif - - cpu_type = temp_cpu_f->cpus[temp_cpu].cpu_type; - settings_enable_window(hdlg, IDC_COMBO_WS, (cpu_type >= CPU_286) && (cpu_type <= CPU_386DX)); - -#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) && !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); - } -#endif - - win_settings_machine_recalc_fpu(hdlg); -} - -static void -win_settings_machine_recalc_cpu_m(HWND hdlg) -{ - 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 (first_eligible == -1) - first_eligible = i; - if (temp_cpu == c) - current_eligible = i; - last_eligible = i; - - listtocpu[i++] = c; - } - c++; - } - if (i == 0) - 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; - else if (current_eligible > last_eligible) - current_eligible = last_eligible; - temp_cpu = listtocpu[current_eligible]; - settings_set_cur_sel(hdlg, IDC_COMBO_CPU_SPEED, current_eligible); - - win_settings_machine_recalc_cpu(hdlg); - - free(lptsTemp); -} - -static void -win_settings_machine_recalc_machine(HWND hdlg) -{ - 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_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; - 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 (i == 0) - 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); - } else { - 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)); - - 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); - - 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)); - - accel.nSec = 0; - accel.nInc = machine_get_ram_granularity(temp_machine) >> 10; - - SendMessage(h, UDM_SETACCEL, 1, (LPARAM) &accel); - - SendMessage(h, UDM_SETPOS, 0, temp_mem_size >> 10); - - 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)); - settings_enable_window(hdlg, IDC_MEMTEXT, machine_get_min_ram(temp_machine) != machine_get_max_ram(temp_machine)); - - free(lptsTemp); -} - -static char * -machine_type_get_internal_name(int id) -{ - if (id < MACHINE_TYPE_MAX) - return ""; - else - 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++; - } - } - - 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, UNUSED(LPARAM lParam)) -{ - HWND h; - HWND h2; - int c; - int d; - int old_machine_type; - LPTSTR lptsTemp; - char *stransi; - - switch (message) { - 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); - 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_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); - -#ifdef USE_DYNAREC - settings_set_check(hdlg, IDC_CHECK_DYNAREC, 0); -#endif - - settings_set_check(hdlg, IDC_CHECK_SOFTFLOAT, 0); - - h = GetDlgItem(hdlg, IDC_MEMSPIN); - h2 = GetDlgItem(hdlg, IDC_MEMTEXT); - SendMessage(h, UDM_SETBUDDY, (WPARAM) h2, 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); - - win_settings_machine_recalc_machine(hdlg); - - free(lptsTemp); - - return TRUE; - - 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)]; - - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - - 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]; - - win_settings_machine_recalc_machine(hdlg); - } - - 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; - } - - 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); -#endif - - temp_fpu_softfloat = settings_get_check(hdlg, IDC_CHECK_SOFTFLOAT); - - if (settings_get_check(hdlg, IDC_RADIO_TS_DISABLED)) - temp_sync = TIME_SYNC_DISABLED; - - if (settings_get_check(hdlg, IDC_RADIO_TS_LOCAL)) - temp_sync = TIME_SYNC_ENABLED; - - if (settings_get_check(hdlg, IDC_RADIO_TS_UTC)) - temp_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - - temp_wait_states = settings_get_cur_sel(hdlg, IDC_COMBO_WS); - - 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, const char *internal_name, int bus) -{ - 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_2104); - memcpy(device_name, wtemp, (wcslen(wtemp) + 1) * sizeof(WCHAR)); - return; - } else if (!strcmp(internal_name, "internal")) - memcpy(temp, "Internal", 9); - else - 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, UNUSED(LPARAM lParam)) -{ - int c = 0; - int d = 0; - int e; - - switch (message) { - 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; - } - - generate_device_name(video_card_getdevice(c), video_get_internal_name(c), 1); - - if (!device_name[0]) - break; - - 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++; - - 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)); - - // 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)); - - 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; - - dev = mouse_get_device(num); - 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, UNUSED(LPARAM lParam)) -{ - 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_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)); - - 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); - - for (c = 0; c < 4; c++) - settings_enable_window(hdlg, IDC_JOY1 + c, joystick_get_max_joysticks(temp_joystick) > c); - - 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 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); - - 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 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; - } - return FALSE; -} - -static int -mpu401_present(void) -{ - return temp_mpu401 ? 1 : 0; -} - -int -mpu401_standalone_allow(void) -{ - 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; - - mdout = midi_out_device_get_internal_name(temp_midi_output_device); - mdin = midi_in_device_get_internal_name(temp_midi_input_device); - - if (mdout != NULL) { - if (!strcmp(mdout, "none") && !strcmp(mdin, "none")) - return 0; - } - - return 1; -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) -{ - 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)); - - 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); - - if (!device_name[0]) - break; - - if (sound_card_available(c)) { - sound_dev[0] = sound_card_getdevice(c); - - 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++; - } - - 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_SOUND2); - while (1) { - /* Skip "internal" */ - if (c == 1) { - c++; - continue; - } - - generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - - if (!device_name[0]) - break; - - if (sound_card_available(c)) { - sound_dev[1] = sound_card_getdevice(c); - - 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++; - } - - settings_enable_window(hdlg, IDC_COMBO_SOUND2, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SND2, sound_card_has_config(temp_sound_card[1])); - - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_SOUND3); - while (1) { - /* Skip "internal" */ - if (c == 1) { - c++; - continue; - } - - generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - - if (!device_name[0]) - break; - - if (sound_card_available(c)) { - sound_dev[2] = sound_card_getdevice(c); - - 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++; - } - } - - c++; - } - - settings_enable_window(hdlg, IDC_COMBO_SOUND3, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SND3, sound_card_has_config(temp_sound_card[2])); - - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_SOUND4); - while (1) { - /* Skip "internal" */ - if (c == 1) { - c++; - continue; - } - - generate_device_name(sound_card_getdevice(c), sound_card_get_internal_name(c), 1); - - if (!device_name[0]) - break; - - if (sound_card_available(c)) { - sound_dev[3] = sound_card_getdevice(c); - - 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++; - } - } - - c++; - } - - settings_enable_window(hdlg, IDC_COMBO_SOUND4, d); - settings_enable_window(hdlg, IDC_CONFIGURE_SND4, sound_card_has_config(temp_sound_card[3])); - - 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); - - if (!device_name[0]) - 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++; - } - - c++; - } - - settings_enable_window(hdlg, IDC_CONFIGURE_MIDI_OUT, midi_out_device_has_config(temp_midi_output_device)); - - 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); - - if (!device_name[0]) - break; - - 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++; - } - - c++; - } - - 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, UNUSED(LPARAM lParam)) -{ - int c; - int i; - const char *s; - LPTSTR lptsTemp; - - switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - - for (i = 0; i < PARALLEL_MAX; i++) { - c = 0; - while (1) { - s = (char *) lpt_device_get_name(c); - - if (!s) - break; - - 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]); - - 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]); - settings_set_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i, temp_serial_passthrough_enabled[i]); - } - - free(lptsTemp); - - 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_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); - temp_serial_passthrough_enabled[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i); - } - - 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, UNUSED(LPARAM lParam)) -{ - 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); - - /*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); - - if (!device_name[0]) - break; - - 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_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++; - } - - 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); - - if (!device_name[0]) - break; - - 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_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++; - } - - 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); - - if (!device_name[0]) - break; - - 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_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); - } - - settings_list_to_device[0][d] = c; - d++; - } - } - - 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_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); - - 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 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_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_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_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_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_BUTTON_IDE_TER: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &ide_ter_device); - 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_QUA: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *) &ide_qua_device); - break; - } - 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) -{ - ignore_change = 1; - - 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, UNUSED(LPARAM lParam)) -{ - int c; - int d; - LPTSTR lptsTemp; - - switch (message) { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - - 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_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_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 (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++; - } - - settings_enable_window(hdlg, IDC_COMBO_NET1 + i, d); - network_recalc_combos(hdlg); - } - free(lptsTemp); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_COMBO_NET1_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[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; - - 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; - - temp_net_type[3] = settings_get_cur_sel(hdlg, IDC_COMBO_NET4_TYPE); - network_recalc_combos(hdlg); - break; - - case IDC_COMBO_PCAP1: - if (ignore_change) - return FALSE; - - 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; - - 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; - - 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; - - 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; - - 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(void) -{ - hard_disk_t ihdd[HDD_NUM]; - int j = 0; - - memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); - - 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 j = 0; - HWND h; - - if (hd_listview_items == 0) - return 0; - - 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; - - 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)); - - 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); - } - - 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 < (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) -{ - 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) -{ - 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) -{ - 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 bus = 0; - - 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; - - 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].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].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((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) { - 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; - 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++; - } - - for (i = 0; i < HDD_NUM; i++) { - 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) || !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)); -} - -static void -win_settings_hard_disks_update_item(HWND hdlg, int i, int column) -{ - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - LVITEM lvI; - WCHAR szText[256]; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = column; - lvI.iItem = i; - - 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; -} - -static BOOL -win_settings_hard_disks_recalc_list(HWND hdlg) -{ - LVITEM lvI; - 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; - - ListView_DeleteAllItems(hwndList); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 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; - - /* 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; - - if (ListView_InsertItem(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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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 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 (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; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - 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 = 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; - } - - win_settings_hard_disks_resize_columns(hdlg); - return TRUE; -} - -static void -get_edit_box_contents(HWND hdlg, int id, uint32_t *val) -{ - HWND h; - WCHAR szText[256]; - char stransi[256]; - - h = GetDlgItem(hdlg, id); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) szText); - wcstombs(stransi, szText, 256); - sscanf(stransi, "%u", val); -} - -static void -set_edit_box_contents(HWND hdlg, int id, uint32_t val) -{ - HWND h; - WCHAR szText[256]; - - h = GetDlgItem(hdlg, id); - 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) -{ - 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) -{ - HWND h = GetDlgItem(hdlg, id); - SendMessage(h, WM_GETTEXT, (WPARAM) buffer_size, (LPARAM) text_buffer); -} - -static int -hdconf_initialize_hdt_combo(HWND hdlg) -{ - uint64_t temp_size = 0; - uint32_t size_mb = 0; - WCHAR szText[256]; - - selection = 127; - - 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)); - settings_set_cur_sel(hdlg, IDC_COMBO_HD_TYPE, selection); - return selection; -} - -static void -recalc_selection(HWND hdlg) -{ - selection = 127; - 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; - settings_set_cur_sel(hdlg, IDC_COMBO_HD_TYPE, selection); -} - -HWND vhd_progress_hdlg; - -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, 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, - * we adjust it to the next-largest size that is compatible. On average, this will be a difference - * 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) -{ - 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 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; - - 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) -{ - 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 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; -} - -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); - - 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); - } - - return _86box_geometry; -} - -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; - - 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; -} - -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; - - 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; - } - - mvhd_close(vhd); - } - - 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, UNUSED(LPARAM lParam)) -{ - 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)); - - hdd_ptr = &(temp_hdd[next_free_id]); - - 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); - - 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_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); - - /* 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; - - 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); - - 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); - - 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; - - /* 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; - - 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); - - 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; - } - - 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 == 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, 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, 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 != 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; - - hard_disk_added = 1; - EndDialog(hdlg, 0); - return TRUE; - } - - big_buf = (char *) malloc(1048576); - memset(big_buf, 0, 1048576); - - 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); - - 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); - - 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 (fp) { - fwrite(big_buf, 1, 1048576, fp); - } - SendMessage(h, PBM_SETPOS, (i + 1), (LPARAM) 0); - - settings_process_messages(); - } - } - - free(big_buf); - - 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; - - 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'; - } - } - - 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; - } - } - - fp = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); - if (fp == NULL) { -hdd_add_file_open_error: - 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(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; - } - - 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); - - 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; - - no_update = 0; - } - - 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); - - return TRUE; - - 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); - } - - 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_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); - } - - 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; - - 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); - } - - 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; - - 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); - } - - 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 (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; - - 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)); - } - - 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 (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_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; - - 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 (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 (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 = 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; - - 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; - - 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; -} - -int -hard_disk_was_added(void) -{ - return hard_disk_added; -} - -void -hard_disk_add_open(HWND hwnd, int is_existing) -{ - existing = is_existing; - hard_disk_added = 0; - 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; - } -} - -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; - } -} - -static void -hard_disk_track_all(void) -{ - for (uint8_t i = 0; i < HDD_NUM; i++) - hard_disk_track(i); -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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; - - 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); - - ignore_change = 0; - return TRUE; - - 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; - - 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_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_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 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; - 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.stateMask = lvI.state = 0; - - 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; - - 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; - - 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; - } - - return TRUE; -} - -static BOOL -win_settings_cdrom_drives_recalc_list(HWND hdlg) -{ - LVITEM lvI; - int fsid = 0; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - 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) { - 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; - - 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_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 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 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; - - for (uint8_t 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) { - 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; - } - - lvI.iItem = i; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; - - 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); - - 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 fsid = 0; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - 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) { - 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; - - 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; - - 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 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 (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[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); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - /* Type */ - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_TYPE); - - lvc.cx = C_COLUMNS_FLOPPY_DRIVES_TYPE; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; - - /* Turbo */ - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2059); - - lvc.cx = C_COLUMNS_FLOPPY_DRIVES_TURBO; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; - - /* Check BPB */ - lvc.iSubItem = 2; - lvc.pszText = plat_get_string(IDS_BPB); - - lvc.cx = C_COLUMNS_FLOPPY_DRIVES_BPB; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) - 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[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); - 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); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - /* Bus */ - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_BUS); - - lvc.cx = C_COLUMNS_CDROM_DRIVES_BUS; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; - - /* Speed */ - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2053); - - lvc.cx = C_COLUMNS_CDROM_DRIVES_SPEED; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - 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[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[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); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - /* Bus */ - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_BUS); - - lvc.cx = C_COLUMNS_MO_DRIVES_BUS; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; - - /* Type */ - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_TYPE); - - lvc.cx = C_COLUMNS_MO_DRIVES_TYPE; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - 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[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[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); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - /* Bus */ - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_BUS); - - lvc.cx = C_COLUMNS_ZIP_DRIVES_BUS; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - return FALSE; - - /* Type */ - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_TYPE); - - lvc.cx = C_COLUMNS_ZIP_DRIVES_TYPE; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; - - win_settings_zip_drives_resize_columns(hdlg); - return TRUE; -} - -static int -get_selected_drive(HWND hdlg, int id, int max) -{ - int drive = -1; - int j = 0; - HWND h; - - 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]; - const char *t; - WCHAR szText[256]; - HWND hwndList = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = 0; - 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; - } else - lvI.pszText = plat_get_string(IDS_5376); - lvI.iImage = temp_fdd_types[i]; - - if (ListView_SetItem(hwndList, &lvI) == -1) - return; - - 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; - - 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; -} - -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); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = 0; - lvI.iItem = i; - - fsid = combo_id_to_format_string_id(temp_cdrom[i].bus_type); - - 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; - } - - if (ListView_SetItem(hwndList, &lvI) == -1) - return; - - 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; - -#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); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - /* Bus */ - lvI.iSubItem = 0; - lvI.iItem = i; - - fsid = combo_id_to_format_string_id(temp_mo_drives[i].bus_type); - - 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_SetItem(hwndList, &lvI) == -1) - return; - - /* Type */ - 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); - mbstowcs(szText, szType, strlen(szType) + 1); - lvI.pszText = szText; - } - lvI.iItem = i; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - 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); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = 0; - lvI.iItem = i; - - fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); - - 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; - } - - if (ListView_SetItem(hwndList, &lvI) == -1) - 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; - - if (ListView_SetItem(hwndList, &lvI) == -1) - return; -} - -static void -cdrom_add_locations(HWND hdlg) -{ - LPTSTR lptsTemp; - 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))); - } - - for (i = 1; i <= 72; i++) { - wsprintf(lptsTemp, L"%ix", i); - settings_add_string(hdlg, IDC_COMBO_CD_SPEED, (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 < (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 bus = temp_cdrom[lv2_current_sel].bus_type; - - 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 - } - - 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); - - 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); - - if (assign_id) - next_free_scsi_id(&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; - } -} - -static void -mo_add_locations(HWND hdlg) -{ - LPTSTR lptsTemp; - char *temp; - int i = 0; - - lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); - 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))); - } - - 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 < (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); - - 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 bus = temp_mo_drives[lv1_current_sel].bus_type; - - 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); - - 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(); - - 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(&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; - } -} - -static void -zip_add_locations(HWND hdlg) -{ - LPTSTR lptsTemp; - 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))); - } - - 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 < (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 bus = temp_zip_drives[lv2_current_sel].bus_type; - - 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); - - 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(); - - 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(&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; - } -} - -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)); - 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)); -} - -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)); - 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)); -} - -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); - 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)); -} - -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); - 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)); -} - -static void -mo_track(uint8_t id) -{ - if (temp_mo_drives[id].bus_type == MO_BUS_ATAPI) - 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)); -} - -static void -mo_untrack(uint8_t id) -{ - if (temp_mo_drives[id].bus_type == MO_BUS_ATAPI) - 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)); -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -win_settings_floppy_and_cdrom_drives_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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 }; - - switch (message) { - 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 (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_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); - - 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); - - ignore_change = 0; - return TRUE; - - 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, 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) { - 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; - - 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; - - 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_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_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; - -#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 -static BOOL CALLBACK -#endif -win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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; - - 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) { - 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); - - 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) { - 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); - - ignore_change = 0; - return TRUE; - - 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, MO_NUM); - if (lv1_current_sel == old_sel) - return FALSE; - ignore_change = 1; - - 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, ZIP_NUM); - if (lv2_current_sel == old_sel) - return FALSE; - ignore_change = 1; - - 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; - - 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; - - 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_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_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_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; - } - - 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, UNUSED(LPARAM lParam)) -{ - 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); - - /* 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_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); - - 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_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 && machine_has_bus(temp_machine, MACHINE_BUS_ISA))); - settings_set_check(hdlg, IDC_CHECK_POSTCARD, temp_postcard); - - free(stransi); - free(lptsTemp); - - 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 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_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); - - default: - return FALSE; - } - return FALSE; -} - -void -win_settings_show_child(HWND hwndParent, DWORD child_id) -{ - if (child_id == displayed_category) - return; - else - 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; - } - - ShowWindow(hwndChildDialog, SW_SHOWNORMAL); -} - -static BOOL -win_settings_main_insert_categories(HWND hwndList) -{ - LVITEM lvI; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - 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; - } - - return TRUE; -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -win_settings_confirm(HWND hdlg) -{ - int i; - - 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_2122, (wchar_t *) IDS_2123, (wchar_t *) IDS_2124, NULL, NULL); - else - i = 0; - - if (i == 10) { - confirm_save = 0; - i = 0; - } - - if (i == 0) - win_settings_save(); - else - return FALSE; - } - - DestroyWindow(hwndChildDialog); - EndDialog(hdlg, 0); - win_notify_dlg_closed(); - return TRUE; -} - -static void -win_settings_categories_resize_columns(HWND hdlg) -{ - HWND hwndList = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); - RECT r; - - GetWindowRect(hwndList, &r); - 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); - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(2048); - - lvc.cx = 171; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) - return FALSE; - - win_settings_categories_resize_columns(hdlg); - return TRUE; -} - -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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 (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; - } - - 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); -} - -void -win_settings_open(HWND hwnd) -{ - win_settings_open_ex(hwnd, SETTINGS_PAGE_MACHINE); -} diff --git a/src/win/win_snd_gain.c b/src/win/win_snd_gain.c deleted file mode 100644 index 5297661bf..000000000 --- a/src/win/win_snd_gain.c +++ /dev/null @@ -1,90 +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 the sound gain dialog. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include <86box/plat.h> -#include <86box/sound.h> -#include <86box/win.h> - -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, 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, 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_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; - - default: - break; - } - break; - } - - return FALSE; -} - -void -SoundGainDialogCreate(HWND hwnd) -{ - DialogBox(hinstance, (LPCTSTR) DLG_SND_GAIN, hwnd, SoundGainDialogProcedure); -} diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c deleted file mode 100644 index 5bedb846d..000000000 --- a/src/win/win_specify_dim.c +++ /dev/null @@ -1,188 +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 the dialog for specifying the dimensions of the main window. - * - * - * - * Authors: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2021-2023 Jasmine Iwanek. - */ -#define UNICODE -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include -#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 -static BOOL CALLBACK -#endif -SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - 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); - - 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_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); - - 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_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 (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); - } - - 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); - 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_store(&doresize_monitors[0], 1); - - GetWindowRect(hwndMain, &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; - } - } - - config_save(); - - free(stransi); - free(lptsTemp); - - EndDialog(hdlg, 0); - return TRUE; - - case IDCANCEL: - EndDialog(hdlg, 0); - return TRUE; - - default: - break; - } - break; - } - - return FALSE; -} - -void -SpecifyDimensionsDialogCreate(HWND hwnd) -{ - DialogBox(hinstance, (LPCTSTR) DLG_SPECIFY_DIM, hwnd, SpecifyDimensionsDialogProcedure); -} diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c deleted file mode 100644 index 2cf8d84f4..000000000 --- a/src/win/win_stbar.c +++ /dev/null @@ -1,1058 +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. - * - * Implement the application's Status Bar. - * - * - * - * Authors: Miran Grca, - * 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 -#include -#include -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/config.h> -#include "cpu.h" -#include <86box/device.h> -#include <86box/machine.h> -#include <86box/timer.h> -#include <86box/cassette.h> -#include <86box/cartridge.h> -#include <86box/hdd.h> -#include <86box/hdc.h> -#include <86box/fdd.h> -#include <86box/fdd_86f.h> -#include <86box/scsi.h> -#include <86box/scsi_device.h> -#include <86box/cdrom.h> -#include <86box/zip.h> -#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> -#include <86box/plat.h> -#include <86box/ui.h> -#include <86box/win.h> - -HWND hwndSBAR; -int update_icons = 1; -int 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"; - -/* Also used by win_settings.c */ -intptr_t -fdd_type_to_icon(int type) -{ - int ret = 248; - - switch (type) { - case 0: - 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; - - default: - break; - } - - return ret; -} - -/* FIXME: should be hdd_count() in hdd.c */ -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; -} - -void -ui_sb_timer_callback(int pane) -{ - if (!(reset_occurred & 1)) { - sb_part_icons[pane] &= ~1; - - if (sb_part_icons && sb_part_icons[pane]) { - SendMessage(hwndSBAR, SB_SETICON, pane, - (LPARAM) hIcon[sb_part_icons[pane]]); - } - } else - reset_occurred &= ~1; - - reset_occurred &= ~2; -} - -/* API */ -/* API: update one of the icons after activity. */ -void -ui_sb_update_icon(int tag, int active) -{ - uint8_t found = 0xff; - - if (!update_icons || !sb_ready) - 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; - - PostMessage(hwndSBAR, SB_SETICON, found, - (LPARAM) hIcon[sb_part_icons[found]]); - - 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) -{ - uint8_t found = 0xff; - - if (!sb_ready || ((tag & 0xf0) >= SB_HDD)) - return; - - found = sb_map[tag]; - if (found != 0xff) { - sb_part_icons[found] &= ~128; - sb_part_icons[found] |= (state ? 128 : 0); - - SendMessage(hwndSBAR, SB_SETICON, found, - (LPARAM) hIcon[sb_part_icons[found]]); - } -} - -static void -StatusBarCreateCassetteTip(int part) -{ - WCHAR tempTip[512]; - WCHAR fn[512]; - - if (strlen(cassette_fname) == 0) - _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_2149), fn); - } - - if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; - } - 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; - - if (strlen(cart_fns[drive]) == 0) { - _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_2151), - drive + 1, fn); - } - - if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateFloppyTip(int part) -{ - WCHAR wtext[512]; - WCHAR tempTip[512]; - WCHAR fn[512]; - - int drive = sb_part_meanings[part] & 0xf; - - mbstoc16s(wtext, fdd_getname(fdd_get_type(drive)), - strlen(fdd_getname(fdd_get_type(drive))) + 1); - if (strlen(floppyfns[drive]) == 0) { - _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_2109), - drive + 1, wtext, fn); - } - - if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateCdromTip(int part) -{ - WCHAR tempTip[512]; - WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = cdrom[drive].bus_type; - - 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); - } - } else - _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; - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 4); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateZIPTip(int part) -{ - WCHAR tempTip[512]; - WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = zip_drives[drive].bus_type; - - 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)); - } else { - 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; - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateMOTip(int part) -{ - WCHAR tempTip[512]; - WCHAR *szText; - WCHAR fn[512]; - int id; - int drive = sb_part_meanings[part] & 0xf; - int bus = mo_drives[drive].bus_type; - - id = IDS_5377 + (bus - 1); - szText = plat_get_string(id); - - if (strlen(mo_drives[drive].image_path) == 0) { - _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_2116), - drive + 1, szText, fn); - } - - if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; - } - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateDiskTip(int part) -{ - WCHAR tempTip[512]; - WCHAR *szText; - int id; - int bus = sb_part_meanings[part] & 0xf; - - 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); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateNetworkTip(int part) -{ - WCHAR tempTip[512]; - - _swprintf(tempTip, plat_get_string(IDS_2069)); - - if (sbTips[part] != NULL) - free(sbTips[part]); - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -static void -StatusBarCreateSoundTip(int part) -{ - WCHAR tempTip[512]; - - _swprintf(tempTip, plat_get_string(IDS_2068)); - - if (sbTips[part] != NULL) - free(sbTips[part]); - sbTips[part] = (WCHAR *) malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - -/* API */ -void -ui_sb_update_tip(int meaning) -{ - uint8_t part = 0xff; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - return; - - part = sb_map[meaning]; - - if (part != 0xff) { - switch (meaning & 0xf0) { - case SB_CASSETTE: - StatusBarCreateCassetteTip(part); - break; - - case SB_CARTRIDGE: - StatusBarCreateCartridgeTip(part); - break; - - case SB_FLOPPY: - StatusBarCreateFloppyTip(part); - break; - - case SB_CDROM: - StatusBarCreateCdromTip(part); - break; - - case SB_ZIP: - StatusBarCreateZIPTip(part); - break; - - case SB_MO: - StatusBarCreateMOTip(part); - break; - - case SB_HDD: - StatusBarCreateDiskTip(part); - break; - - case SB_NETWORK: - StatusBarCreateNetworkTip(part); - break; - - case SB_SOUND: - StatusBarCreateSoundTip(part); - break; - - default: - break; - } - - SendMessage(hwndSBAR, SB_SETTIPTEXT, part, (LPARAM) sbTips[part]); - } -} - -static void -StatusBarDestroyTips(void) -{ - if (sb_parts == 0) - return; - - if (!sbTips) - return; - - for (int i = 0; i < sb_parts; i++) { - if (sbTips[i]) { - free(sbTips[i]); - sbTips[i] = NULL; - } - } - - free(sbTips); - sbTips = NULL; -} - -/* API: mark the status bar as not ready. */ -/* Values: -1 - not ready, but don't clear POST text - 0 - not ready - 1 - ready */ -void -ui_sb_set_ready(int ready) -{ - if (ready == 0) { - ui_sb_bugui(NULL); - ui_sb_set_text(NULL); - } - - if (ready == -1) - ready = 0; - - sb_ready = ready; -} - -/* API: update the status bar panes. */ -void -ui_sb_update_panes(void) -{ - int i; - int id; - int cart_int; - int mfm_int; - int xta_int; - int esdi_int; - int ide_int; - int scsi_int; - int edge = 0; - int c_mfm; - int c_esdi; - int c_xta; - int c_ide; - int c_scsi; - int do_net; - const char *hdc_name; - - if (!config_changed) - return; - - if (sb_ready) { - sb_ready = 0; - } - - cart_int = machine_has_cartridge(machine) ? 1 : 0; - mfm_int = machine_has_flags(machine, MACHINE_MFM) ? 1 : 0; - xta_int = machine_has_flags(machine, MACHINE_XTA) ? 1 : 0; - esdi_int = machine_has_flags(machine, MACHINE_ESDI) ? 1 : 0; - ide_int = machine_has_flags(machine, MACHINE_IDE_QUAD) ? 1 : 0; - scsi_int = machine_has_flags(machine, MACHINE_SCSI) ? 1 : 0; - - c_mfm = hdd_count(HDD_BUS_MFM); - c_esdi = hdd_count(HDD_BUS_ESDI); - c_xta = hdd_count(HDD_BUS_XTA); - c_ide = hdd_count(HDD_BUS_IDE); - c_scsi = hdd_count(HDD_BUS_SCSI); - do_net = network_available(); - - media_menu_reset(); - - if (sb_parts > 0) { - 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(); - } - - memset(sb_map, 0xff, sizeof(sb_map)); - - sb_parts = 0; - if (cassette_enable) - sb_parts++; - if (cart_int) - sb_parts += 2; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_type(i) != 0) - sb_parts++; - } - hdc_name = hdc_get_internal_name(hdc_current); - for (i = 0; i < CDROM_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !scsi_int && (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 != 0) - sb_parts++; - } - for (i = 0; i < ZIP_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !scsi_int && (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) - sb_parts++; - } - for (i = 0; i < MO_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !scsi_int && (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) - sb_parts++; - } - if (c_mfm && (mfm_int || !memcmp(hdc_name, "st506", 5))) { - /* MFM drives, and MFM or Internal controller. */ - sb_parts++; - } - if (c_esdi && (esdi_int || !memcmp(hdc_name, "esdi", 4))) { - /* ESDI drives, and ESDI or Internal controller. */ - sb_parts++; - } - if (c_xta && (xta_int || !memcmp(hdc_name, "xta", 3))) - sb_parts++; - if (c_ide && (ide_int || !memcmp(hdc_name, "xtide", 5) || !memcmp(hdc_name, "ide", 3))) - sb_parts++; - if (c_scsi && (scsi_int || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0))) - sb_parts++; - if (do_net) - sb_parts++; - sb_parts += 2; - - iStatusWidths = (int *) malloc(sb_parts * sizeof(int)); - memset(iStatusWidths, 0, sb_parts * sizeof(int)); - sb_part_meanings = (int *) malloc(sb_parts * sizeof(int)); - memset(sb_part_meanings, 0, sb_parts * sizeof(int)); - sb_part_icons = (uint8_t *) malloc(sb_parts * sizeof(uint8_t)); - memset(sb_part_icons, 0, sb_parts * sizeof(uint8_t)); - sbTips = (WCHAR **) malloc(sb_parts * sizeof(WCHAR *)); - memset(sbTips, 0, sb_parts * sizeof(WCHAR *)); - - sb_parts = 0; - if (cassette_enable) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_CASSETTE; - sb_map[SB_CASSETTE] = sb_parts; - sb_parts++; - } - for (i = 0; i < 2; i++) { - if (cart_int) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_CARTRIDGE | i; - sb_map[SB_CARTRIDGE | i] = sb_parts; - sb_parts++; - } - } - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_type(i) != 0) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_FLOPPY | i; - sb_map[SB_FLOPPY | i] = sb_parts; - sb_parts++; - } - } - for (i = 0; i < CDROM_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !scsi_int && (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 != 0) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_CDROM | i; - sb_map[SB_CDROM | i] = sb_parts; - sb_parts++; - } - } - for (i = 0; i < ZIP_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !scsi_int && (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) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_ZIP | i; - sb_map[SB_ZIP | i] = sb_parts; - sb_parts++; - } - } - for (i = 0; i < MO_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !ide_int && memcmp(hdc_name, "xtide", 5) && memcmp(hdc_name, "ide", 3)) - continue; - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !scsi_int && (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) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_MO | i; - sb_map[SB_MO | i] = sb_parts; - sb_parts++; - } - } - if (c_mfm && (mfm_int || !memcmp(hdc_name, "st506", 5))) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_MFM; - sb_map[SB_HDD | HDD_BUS_MFM] = sb_parts; - sb_parts++; - } - if (c_esdi && (esdi_int || !memcmp(hdc_name, "esdi", 4))) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_ESDI; - sb_map[SB_HDD | HDD_BUS_ESDI] = sb_parts; - sb_parts++; - } - if (c_xta && (xta_int || !memcmp(hdc_name, "xta", 3))) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_XTA; - sb_map[SB_HDD | HDD_BUS_XTA] = sb_parts; - sb_parts++; - } - if (c_ide && (ide_int || !memcmp(hdc_name, "xtide", 5) || !memcmp(hdc_name, "ide", 3))) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_IDE; - sb_map[SB_HDD | HDD_BUS_IDE] = sb_parts; - sb_parts++; - } - if (c_scsi && (scsi_int || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0))) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_SCSI; - sb_map[SB_HDD | HDD_BUS_SCSI] = sb_parts; - sb_parts++; - } - if (do_net) { - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_NETWORK; - sb_map[SB_NETWORK] = sb_parts; - sb_parts++; - } - - edge += icon_width; - iStatusWidths[sb_parts] = edge; - sb_part_meanings[sb_parts] = SB_SOUND; - sb_map[SB_SOUND] = sb_parts; - sb_parts++; - - if (sb_parts) - iStatusWidths[sb_parts] = -1; - sb_part_meanings[sb_parts] = SB_TEXT; - sb_map[SB_TEXT] = sb_parts; - sb_parts++; - - SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM) sb_parts, (LPARAM) iStatusWidths); - - for (i = 0; i < sb_parts; i++) { - switch (sb_part_meanings[i] & 0xf0) { - case SB_CASSETTE: /* Cassette */ - sb_part_icons[i] = (strlen(cassette_fname) == 0) ? 128 : 0; - sb_part_icons[i] |= 64; - StatusBarCreateCassetteTip(i); - break; - - case SB_CARTRIDGE: /* Cartridge */ - sb_part_icons[i] = (strlen(cart_fns[sb_part_meanings[i] & 0xf]) == 0) ? 128 : 0; - sb_part_icons[i] |= 104; - StatusBarCreateCartridgeTip(i); - break; - - case SB_FLOPPY: /* Floppy */ - sb_part_icons[i] = (strlen(floppyfns[sb_part_meanings[i] & 0xf]) == 0) ? 128 : 0; - sb_part_icons[i] |= fdd_type_to_icon(fdd_get_type(sb_part_meanings[i] & 0xf)); - StatusBarCreateFloppyTip(i); - break; - - case SB_CDROM: /* CD-ROM */ - id = sb_part_meanings[i] & 0xf; - if (cdrom[id].host_drive == 200) - sb_part_icons[i] = (strlen(cdrom[id].image_path) == 0) ? 128 : 0; - else - sb_part_icons[i] = 128; - sb_part_icons[i] |= 32; - StatusBarCreateCdromTip(i); - break; - - case SB_ZIP: /* Iomega ZIP */ - sb_part_icons[i] = (strlen(zip_drives[sb_part_meanings[i] & 0xf].image_path) == 0) ? 128 : 0; - sb_part_icons[i] |= 48; - StatusBarCreateZIPTip(i); - break; - - case SB_MO: /* Magneto-Optical disk */ - sb_part_icons[i] = (strlen(mo_drives[sb_part_meanings[i] & 0xf].image_path) == 0) ? 128 : 0; - sb_part_icons[i] |= 56; - StatusBarCreateMOTip(i); - break; - - case SB_HDD: /* Hard disk */ - sb_part_icons[i] = 80; - StatusBarCreateDiskTip(i); - break; - - case SB_NETWORK: /* Network */ - sb_part_icons[i] = 96; - StatusBarCreateNetworkTip(i); - break; - - case SB_SOUND: /* Sound */ - sb_part_icons[i] = 243; - StatusBarCreateSoundTip(i); - break; - - case SB_TEXT: /* Status text */ - SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM) L""); - sb_part_icons[i] = 255; - break; - } - - if (sb_part_icons[i] != 255) { - SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM) L""); - SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM) hIcon[sb_part_icons[i]]); - SendMessage(hwndSBAR, SB_SETTIPTEXT, i, (LPARAM) sbTips[i]); - } else - SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM) NULL); - } - - sb_ready = 1; - if (reset_occurred & 2) - reset_occurred |= 1; -} - -static VOID APIENTRY -StatusBarPopupMenu(HWND hwnd, POINT pt, int id) -{ - HMENU menu; - - if (id >= (sb_parts - 1)) - return; - - 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; - } - - TrackPopupMenu(menu, - TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, - pt.x, pt.y, 0, hwndSBAR, NULL); -} - -/* API: Load status bar icons */ -void -StatusBarLoadIcon(UNUSED(HINSTANCE hInst)) -{ - win_load_icon_set(); -} - -/* Handle messages for the Status Bar window. */ -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -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; - - switch (message) { - case WM_COMMAND: - media_menu_proc(hwnd, message, wParam, lParam); - return 0; - - 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, &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); - - for (i = 0; i < sb_parts; i++) { - if (sb_part_icons[i] != 255) { - SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM) hIcon[sb_part_icons[i]]); - } - - iStatusWidths[i] = (i + 1) * icon_width; - } - iStatusWidths[i - 1] = -1; - SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM) sb_parts, (LPARAM) iStatusWidths); - break; - - default: - return (CallWindowProc((WNDPROC) OriginalProcedure, - hwnd, message, wParam, lParam)); - } - - return 0; -} - -/* API: Create and set up the Status Bar window. */ -void -StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) -{ - RECT rectDialog; - int dw; - int dh; - - /* Get current DPI and calculate icon sizes */ - dpi = win_get_dpi(hwndParent); - icon_width = MulDiv(SB_ICON_WIDTH, dpi, 96); - - /* Load our icons into the cache for faster access. */ - StatusBarLoadIcon(hInst); - - GetWindowRect(hwndParent, &rectDialog); - dw = rectDialog.right - rectDialog.left; - dh = rectDialog.bottom - rectDialog.top; - - /* Load the Common Controls DLL if needed. */ - InitCommonControls(); - - /* Create the window, and make sure it's using the STATUS class. */ - hwndSBAR = CreateWindowEx(0, - STATUSCLASSNAME, - (LPCTSTR) NULL, - SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE | SBT_TOOLTIPS, - 0, dh - 17, dw, 17, - hwndParent, - (HMENU) idStatus, hInst, NULL); - - /* Replace the original procedure with ours. */ - OriginalProcedure = GetWindowLongPtr(hwndSBAR, GWLP_WNDPROC); - SetWindowLongPtr(hwndSBAR, GWLP_WNDPROC, (LONG_PTR) &StatusBarProcedure); - - SendMessage(hwndSBAR, SB_SETMINHEIGHT, (WPARAM) 17, (LPARAM) 0); - - /* Align the window with the parent (main) window. */ - GetWindowRect(hwndSBAR, &rectDialog); - SetWindowPos(hwndSBAR, - HWND_TOPMOST, - rectDialog.left, rectDialog.top, - rectDialog.right - rectDialog.left, - rectDialog.bottom - rectDialog.top, - SWP_SHOWWINDOW); - - /* Initialize the status bar. This is clumsy. */ - sb_parts = 1; - iStatusWidths = (int *) malloc(sb_parts * sizeof(int)); - memset(iStatusWidths, 0, sb_parts * sizeof(int)); - sb_part_meanings = (int *) malloc(sb_parts * sizeof(int)); - memset(sb_part_meanings, 0, sb_parts * sizeof(int)); - sb_part_icons = (uint8_t *) malloc(sb_parts * sizeof(uint8_t)); - memset(sb_part_icons, 0, sb_parts * sizeof(uint8_t)); - sbTips = (WCHAR **) malloc(sb_parts * sizeof(WCHAR *)); - memset(sbTips, 0, sb_parts * sizeof(WCHAR *)); - sb_parts = 0; - iStatusWidths[sb_parts] = -1; - sb_part_meanings[sb_parts] = SB_TEXT; - sb_part_icons[sb_parts] = 255; - sb_parts++; - SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM) sb_parts, (LPARAM) iStatusWidths); - SendMessage(hwndSBAR, SB_SETTEXT, 0 | SBT_NOBORDERS, - (LPARAM) plat_get_string(IDS_2118)); - - sb_ready = 1; -} - -void -ui_sb_update_text(void) -{ - uint8_t part = 0xff; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) - return; - - part = sb_map[SB_TEXT]; - - if (part != 0xff) - SendMessage(hwndSBAR, SB_SETTEXT, part | SBT_NOBORDERS, (LPARAM) ((sb_text[0] != L'\0') ? sb_text : sb_bugtext)); -} - -/* API */ -void -ui_sb_set_text_w(wchar_t *wstr) -{ - if (wstr) - wcscpy(sb_text, wstr); - else - memset(sb_text, 0x00, sizeof(sb_text)); - ui_sb_update_text(); -} - -/* API */ -void -ui_sb_set_text(char *str) -{ - if (str) - mbstowcs(sb_text, str, strlen(str) + 1); - else - memset(sb_text, 0x00, sizeof(sb_text)); - ui_sb_update_text(); -} - -/* API */ -void -ui_sb_bugui(char *str) -{ - if (str) - mbstowcs(sb_bugtext, str, strlen(str) + 1); - else - memset(sb_bugtext, 0x00, sizeof(sb_bugtext)); - ui_sb_update_text(); -} - -/* API */ -void -ui_sb_mt32lcd(UNUSED(char *str)) -{ - // -} diff --git a/src/win/win_thread.c b/src/win/win_thread.c deleted file mode 100644 index faacca74f..000000000 --- a/src/win/win_thread.c +++ /dev/null @@ -1,179 +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. - * - * Implement threads and mutexes for the Win32 platform. - * - * - * - * Authors: Sarah Walker, - * 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 -#include -#include -#include -#undef BITMAP -#include -#include -#include -#include -#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); -} - -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 (WaitForSingleObject(arg, INFINITE)) - return 1; - - return 0; -} - -event_t * -thread_create_event(void) -{ - win_event_t *ev = malloc(sizeof(win_event_t)); - - ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); - - return ((event_t *) ev); -} - -void -thread_set_event(event_t *arg) -{ - win_event_t *ev = (win_event_t *) arg; - - if (arg == NULL) - return; - - SetEvent(ev->handle); -} - -void -thread_reset_event(event_t *arg) -{ - win_event_t *ev = (win_event_t *) arg; - - if (arg == NULL) - return; - - ResetEvent(ev->handle); -} - -int -thread_wait_event(event_t *arg, int timeout) -{ - win_event_t *ev = (win_event_t *) arg; - - if (arg == NULL) - return 0; - - if (ev->handle == NULL) - return 0; - - if (timeout == -1) - timeout = INFINITE; - - if (WaitForSingleObject(ev->handle, timeout)) - return 1; - - return 0; -} - -void -thread_destroy_event(event_t *arg) -{ - win_event_t *ev = (win_event_t *) arg; - - if (arg == NULL) - return; - - CloseHandle(ev->handle); - - free(ev); -} - -mutex_t * -thread_create_mutex(void) -{ - mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); - - InitializeCriticalSection(mutex); - - return mutex; -} - -int -thread_wait_mutex(mutex_t *mutex) -{ - if (mutex == NULL) - return 0; - - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; - - EnterCriticalSection(critsec); - - return 1; -} - -int -thread_release_mutex(mutex_t *mutex) -{ - if (mutex == NULL) - return 0; - - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; - - LeaveCriticalSection(critsec); - - return 1; -} - -void -thread_close_mutex(mutex_t *mutex) -{ - if (mutex == NULL) - return; - - LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; - - DeleteCriticalSection(critsec); - - free(critsec); -} diff --git a/src/win/win_toolbar.c b/src/win/win_toolbar.c deleted file mode 100644 index 5c8621eea..000000000 --- a/src/win/win_toolbar.c +++ /dev/null @@ -1,208 +0,0 @@ -#define UNICODE -#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; - -enum image_index { - RUN, - PAUSE, - CTRL_ALT_DEL, - CTRL_ALT_ESC, - HARD_RESET, - ACPI_SHUTDOWN, - SETTINGS -}; - -void -ToolBarLoadIcons(void) -{ - if (!hwndToolbar) - return; - - if (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); - - // The icons must be loaded in the same order as the `image_index` - // enumeration above. - - ImageList_AddIcon(hImageList, hIcon[200]); // Run - ImageList_AddIcon(hImageList, hIcon[201]); // Pause - ImageList_AddIcon(hImageList, hIcon[202]); // Ctrl+Alt+Delete - ImageList_AddIcon(hImageList, hIcon[203]); // Ctrl+Alt+Esc - ImageList_AddIcon(hImageList, hIcon[204]); // Hard reset - ImageList_AddIcon(hImageList, hIcon[205]); // ACPI shutdown - ImageList_AddIcon(hImageList, hIcon[206]); // Settings - - 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_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)); -} - -void -ToolBarUpdatePause(int pause) -{ - TBBUTTONINFO tbbi; - - tbbi.cbSize = sizeof(tbbi); - tbbi.dwMask = TBIF_IMAGE; - tbbi.iImage = pause ? RUN : 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} -}; - -void -ToolBarCreate(HWND hwndParent, HINSTANCE hInst) -{ - REBARINFO rbi = { 0 }; - REBARBANDINFO rbbi = { 0 }; - 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); - - ToolBarLoadIcons(); - - // Add buttons. - SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); - 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)); - - // Replace the original procedure with ours. - pOriginalProcedure = (WNDPROC) GetWindowLongPtr(hwndToolbar, GWLP_WNDPROC); - 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); - - // Create and send the REBARINFO structure. - rbi.cbSize = sizeof(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.cxMinChild = 0; - rbbi.cyMinChild = btnSize; - rbbi.fStyle = RBBS_NOGRIPPER; - SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM) &rbbi); - - // Add a label for machine information. - rbbi.fMask = RBBIM_TEXT | RBBIM_STYLE; - rbbi.lpText = TEXT("Test"); - rbbi.fStyle = RBBS_NOGRIPPER; - SendMessage(hwndRebar, RB_INSERTBAND, -1, (LPARAM) &rbbi); - - SendMessage(hwndRebar, RB_MAXIMIZEBAND, 0, 0); - ShowWindow(hwndRebar, TRUE); - - 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; - - rbbi.cbSize = sizeof(rbbi); - rbbi.fMask = RBBIM_TEXT; - rbbi.lpText = s; - SendMessage(hwndRebar, RB_SETBANDINFO, 1, (LPARAM) &rbbi); - } else { - if (s == NULL) - s = wTitle; - } - - return s; -} diff --git a/src/win/win_ui.c b/src/win/win_ui.c deleted file mode 100644 index 73119140c..000000000 --- a/src/win/win_ui.c +++ /dev/null @@ -1,1664 +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. - * - * user Interface module for WinAPI on Windows. - * - * - * - * 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 2021-2023 Jasmine Iwanek. - */ -#include -#define UNICODE -#include -#include -#include -#include -#include -#include -#include -#include -#include <86box/plat.h> -#include <86box/86box.h> -#include <86box/config.h> -#include "../cpu/cpu.h" -#include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/mouse.h> -#include <86box/timer.h> -#include <86box/nvr.h> -#include <86box/video.h> -#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> -#ifdef DISCORD -# include <86box/discord.h> -#endif - -#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 */ -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; - -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; -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); -static dllimp_t user32_imports[] = { - {"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 } -}; - -int -win_get_dpi(HWND hwnd) -{ - if (user32_handle != NULL) { - return pGetDpiForWindow(hwnd); - } else { - HDC dc = GetDC(hwnd); - UINT dpi = GetDeviceCaps(dc, LOGPIXELSX); - ReleaseDC(hwnd, dc); - return 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); - if (pAreDpiAwarenessContextsEqual(c, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) - return pGetSystemMetricsForDpi(index, dpi); - } - - return GetSystemMetrics(index); -} - -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; - } - - 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); -} - -/* Set host cursor visible or not. */ -void -show_cursor(int val) -{ - if (val == vis) - return; - - if (val == 0) { - while (1) - if (ShowCursor(FALSE) < 0) - break; - } else - ShowCursor(TRUE); - - vis = val; -} - -static void -video_toggle_option(HMENU h, int *val, int id) -{ - startblit(); - *val ^= 1; - CheckMenuItem(h, id, *val ? MF_CHECKED : MF_UNCHECKED); - endblit(); - config_save(); - device_force_redraw(); -} - -/* Recursively finds and deletes target submenu */ -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; - - 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; -} - -static int menu_vidapi = -1; -static HMENU cur_menu = NULL; - -static void -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_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) -{ - 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 -ResetAllMenus(void) -{ - CheckMenuItem(menuMain, IDM_ACTION_RCTRL_IS_LALT, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_ACTION_KBD_REQ_CAPTURE, MF_UNCHECKED); - - CheckMenuItem(menuMain, IDM_UPDATE_ICONS, MF_UNCHECKED); - - CheckMenuItem(menuMain, IDM_VID_HIDE_STATUS_BAR, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_HIDE_TOOLBAR, MF_UNCHECKED); - CheckMenuItem(menuMain, IDM_VID_FORCE43, MF_UNCHECKED); - 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; - show_render_options_menu(); -#ifdef USE_VNC - CheckMenuItem(menuMain, IDM_VID_VNC, MF_UNCHECKED); -#endif - 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, 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, 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); - - CheckMenuItem(menuMain, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED); - - 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_INVERT, invert_display ? MF_CHECKED : MF_UNCHECKED); - - if (show_second_monitors == 1) - CheckMenuItem(menuMain, IDM_VID_MONITORS, 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); - else - 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); - } - - 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; - pause_state = dopause; - plat_pause(1); - if (source_hwnd) - 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); - plat_pause(pause_state); - manager_wm = 0; -} - -void -plat_power_off(void) -{ - confirm_exit = 0; - nvr_save(); - config_save(); - - /* Deduct a sufficiently large number of cycles that no instructions will - run before the main thread is terminated */ - cycles -= 99999999; - - KillTimer(hwndMain, TIMER_1SEC); - PostQuitMessage(0); - - /* Cleanly terminate all of the emulator's components so as - to avoid things like threads getting stuck. */ -#if 0 - do_stop(); -#endif - cpu_thread_run = 0; - -#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); - if (trace) { - init_trace(); - } else { - shutdown_trace(); - } -} -#endif - -/* Catch WM_INPUT messages for 'current focus' window. */ -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -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; - - /* 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_LBUTTONDOWN: - 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; - - default: - return 1; -#if 0 - return(CallWindowProc((WNDPROC)input_orig_proc, - hwnd, message, wParam, lParam)); -#endif - } - - return 0; -} - -static LRESULT CALLBACK -MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HMENU hmenu; - - int i; - RECT rect; - RECT *rect_p; - - WINDOWPOS *pos; - - int temp_x; - int temp_y; - - if (input_proc(hwnd, message, wParam, lParam) == 0) - return 0; - - switch (message) { - 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; - -#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; -#endif - - 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_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_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_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_SND_GAIN: - SoundGainDialogCreate(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_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_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_MONITORS: - show_second_monitors ^= 1; - CheckMenuItem(hmenu, IDM_VID_MONITORS, (show_second_monitors & 1) ? MF_CHECKED : MF_UNCHECKED); - break; - - case IDM_VID_RESIZE: - vid_resize ^= 1; - CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize & 1) ? MF_CHECKED : MF_UNCHECKED); - - 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); - - /* 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; - } - - ResizeWindowByClientArea(hwnd, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height)); - - if (mouse_capture) { - ClipCursor(&rect); - } - - 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 = unscaled_size_x; - scrnsz_y = unscaled_size_y; - atomic_store(&doresize_monitors[0], 1); - config_save(); - break; - - 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: -#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; - - 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_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: - 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_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_PREFERENCES: - PreferencesDlgCreate(hwnd); - break; - - case IDM_VID_SPECIFY_DIM: - SpecifyDimensionsDialogCreate(hwnd); - break; - - case IDM_VID_FORCE43: - video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); - 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_OVERSCAN: - update_overscan = 1; - video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); - video_force_resize_set(1); - 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_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_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; - -#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 - - default: - media_menu_proc(hwnd, message, wParam, lParam); - break; - } - return 0; - - case WM_ENTERMENULOOP: - 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); - } - - /* 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; - - case WM_WINDOWPOSCHANGED: - if (video_fullscreen & 1) - PostMessage(hwndMain, WM_LEAVEFULLSCREEN, 0, 0); - - pos = (WINDOWPOS *) lParam; - GetClientRect(hwndMain, &rect); - - 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) && (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 (!(pos->flags & SWP_NOSIZE) || !user_resize) { - plat_vidapi_enable(0); - - if (!hide_status_bar) - MoveWindow(hwndSBAR, 0, rect.bottom - sbar_height, sbar_height, rect.right, TRUE); - - if (!hide_tool_bar) - MoveWindow(hwndRebar, 0, 0, rect.right, tbar_height, 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); - - GetClientRect(hwndRender, &rect); - if (dpi_scale) { - temp_x = MulDiv(rect.right, 96, dpi); - temp_y = MulDiv(rect.bottom, 96, dpi); - - 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); - } - } - - plat_vidsize(rect.right, rect.bottom); - - if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); - } - - plat_vidapi_enable(2); - } - - return 0; - - case WM_TIMER: - if (wParam == TIMER_1SEC) - pc_onesec(); - else if ((wParam >= 0x8000) && (wParam <= 0x80ff)) - ui_sb_timer_callback(wParam & 0xff); - break; - - case WM_LEAVEFULLSCREEN: - plat_setfullscreen(0); - config_save(); - break; - - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - return 0; - - 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_DESTROY: - win_clear_icon_set(); - KillTimer(hwnd, TIMER_1SEC); - PostQuitMessage(0); - break; - - case WM_SHOWSETTINGS: - if (manager_wm) - break; - manager_wm = 1; - win_settings_open(hwnd); - manager_wm = 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_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_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_CTRLALTDEL: - if (manager_wm) - break; - manager_wm = 1; - pc_send_cad(); - manager_wm = 0; - 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*/ - } - - default: - return (DefWindowProc(hwnd, message, wParam, lParam)); - - case WM_SETFOCUS: - infocus = 1; - break; - - case WM_KILLFOCUS: - infocus = 0; - plat_mouse_capture(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_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_ENTERSIZEMOVE: - user_resize = 1; - 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; -} - -static LRESULT CALLBACK -SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - 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_MBUTTONUP: - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; - - default: - return (DefWindowProc(hwnd, message, wParam, lParam)); - } - - 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 (DefWindowProc(hwnd, message, wParam, lParam)); -} - -static LRESULT CALLBACK -SDLSubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return (DefWindowProc(hwnd, message, wParam, lParam)); -} - -static HRESULT CALLBACK -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; - } - - 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_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); - - /* Set the application ID for the taskbar. */ - shell32_handle = dynld_module("shell32.dll", shell32_imports); - if (shell32_handle) - 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.pszMainInstruction = MAKEINTRESOURCE(IDS_2050); - 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_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); - - win_settings_open(NULL); - return 0; - } - -#ifdef DISCORD - if (!discord_load()) { - enable_discord = 0; - } else if (enable_discord) { - /* Initialize the Discord API */ - discord_init(); - - /* Update Discord status */ - discord_update_activity(dopause); - } -#endif - - /* Create our main window's class and register it. */ - 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)); - - /* Load proper icons */ - 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; - wincl.lpszClassName = SUB_CLASS_NAME; - wincl.lpfnWndProc = SubWindowProcedure; - if (!RegisterClassEx(&wincl)) - return 2; - wincl.lpszClassName = SDL_CLASS_NAME; - wincl.lpfnWndProc = SDLMainWindowProcedure; - if (!RegisterClassEx(&wincl)) - return 2; - wincl.lpszClassName = SDL_SUB_CLASS_NAME; - 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 */ - hwndMain = tdconfig.hwndParent = hwnd; - - ui_window_title(title); - - /* Get the current DPI */ - dpi = win_get_dpi(hwndMain); - - /* Check if we have a padded window frame */ - padded_frame = (GetSystemMetrics(SM_CXPADDEDBORDER) != 0); - - /* Create the status bar window. */ - StatusBarCreate(hwndMain, IDC_STATUS, hinstance); - - /* Get the actual height of the status bar */ - GetWindowRect(hwndSBAR, &rect); - sbar_height = rect.bottom - rect.top; - if (hide_status_bar) - ShowWindow(hwndSBAR, SW_HIDE); - - /* Create the toolbar window. */ - ToolBarCreate(hwndMain, hinstance); - - /* Get the actual height of the toolbar */ - tbar_height = SendMessage(hwndRebar, RB_GETROWHEIGHT, 0, 0); - if (hide_tool_bar) - ShowWindow(hwndRebar, SW_HIDE); - - /* Set up main window for resizing if configured. */ - if (vid_resize == 1) - SetWindowLongPtr(hwnd, GWL_STYLE, - (WS_OVERLAPPEDWINDOW)); - else - 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); - - /* 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); - 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)); - } - - /* Load the desired language */ - helper_lang = lang_id; - 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_2146, (void *) IDS_2147, (void *) IDS_2148, (void *) IDS_2120, NULL)) { - DestroyWindow(hwnd); - return 0; - } - - GetClipCursor(&oldclip); - - /* 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_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_2105); - TaskDialogIndirect(&tdconfig, NULL, NULL, NULL); - return 3; - } - - /* Initialize the mouse module. */ - if (!start_in_fullscreen) - win_mouse_init(); - - /* - * Before we can create the Render window, we first have - * to prepare some other things that it depends on. - */ - 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_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_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); - else - plat_resize(scrnsz_x, scrnsz_y); - - /* Initialize the rendering window, or fullscreen. */ - if (start_in_fullscreen) - plat_setfullscreen(3); - - /* Fire up the machine. */ - pc_reset_hard_init(); - - /* Set the PAUSE mode depending on the renderer. */ - plat_pause(0); - - /* If so requested via the command line, inform the - * application that started us of our HWND, using the - * the hWnd and unique ID the application has given - * us. */ - if (source_hwnd) - PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDHWND, (WPARAM) unique_id, (LPARAM) hwndMain); - - /* - * Everything has been configured, and all seems to work, - * so now it is time to start the main thread to do some - * real work, and we will hang in here, dealing with the - * UI until we're done. - */ - 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; - - 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 (!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); - - /* Close down the emulator. */ - do_stop(); - - UnregisterClass(SDL_SUB_CLASS_NAME, hinstance); - UnregisterClass(SDL_CLASS_NAME, hinstance); - UnregisterClass(SUB_CLASS_NAME, hinstance); - UnregisterClass(CLASS_NAME, hinstance); - - win_mouse_close(); - -#ifdef DISCORD - /* Shut down the Discord integration */ - discord_close(); -#endif - - if (user32_handle != NULL) - dynld_close(user32_handle); - - 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]; - - /* If un-pausing, as the renderer if that's OK. */ - if (p == 0) - 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); - - return; - } - - if (p) { - 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(); - - dopause = p; - - /* Update the actual menu. */ - CheckMenuItem(menuMain, IDM_ACTION_PAUSE, - dopause ? MF_CHECKED : MF_UNCHECKED); - -#ifdef DISCORD - /* Update Discord status */ - if (enable_discord) - 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); -} - -/* 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)); - } -} - -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) && !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; - } else if (!on && mouse_capture) { - /* Disable the in-app mouse. */ - ClipCursor(&oldclip); - show_cursor(-1); - - 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 5fdfc175b..d9ea83dba 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "4.1", + "version-string": "4.2", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later",