diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 79f350f4f..2a22a19cf 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -1,4 +1,4 @@ -name: MSYS2 Makefile +name: MSYS2 Makefile (Windows, Legacy) on: @@ -16,7 +16,9 @@ on: jobs: msys2: - name: "Windows MSYS2 Makefile (Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})" + # Negative condition disables the job + if: false + name: "Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}" runs-on: windows-2022 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..c09789bfc --- /dev/null +++ b/.github/workflows/cmake_linux.yml @@ -0,0 +1,122 @@ +name: CMake (Linux) + +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: + + 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 + 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/** diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml new file mode 100644 index 000000000..7a6edcde9 --- /dev/null +++ b/.github/workflows/cmake_macos.yml @@ -0,0 +1,127 @@ +name: CMake (macos) + +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: + + 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 + 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_windows_llvm.yml b/.github/workflows/cmake_windows_llvm.yml new file mode 100644 index 000000000..a49f9488a --- /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.yml + - vcpkg.json + - "!**/Makefile*" + + pull_request: + paths: + - src/** + - cmake/** + - "**/CMakeLists.txt" + - "CMakePresets.json" + - .github/workflows/** + - .github/workflows/cmake.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@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/** diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml new file mode 100644 index 000000000..46fc25b67 --- /dev/null +++ b/.github/workflows/cmake_windows_msys2.yml @@ -0,0 +1,146 @@ +name: CMake (Windows, msys2) + +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: "${{ 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 +# 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/** 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..a97951abf --- /dev/null +++ b/.github/workflows/codeql_linux.yml @@ -0,0 +1,112 @@ +name: CodeQL Analysis (Linux) + +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-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}}" diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml new file mode 100644 index 000000000..724bdc6f6 --- /dev/null +++ b/.github/workflows/codeql_macos.yml @@ -0,0 +1,108 @@ +name: CodeQL Analysis (macos) + +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-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 + 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_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml new file mode 100644 index 000000000..5b0c2485f --- /dev/null +++ b/.github/workflows/codeql_windows_msys2.yml @@ -0,0 +1,141 @@ +name: CodeQL Analysis (Windows, msys2) + +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: "${{ 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}}" diff --git a/CMakeLists.txt b/CMakeLists.txt index d9f92add3..a6b50baf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,6 @@ cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" 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) @@ -197,7 +196,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/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..8218c208c 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,7 @@ #include <86box/machine.h> #include <86box/bugger.h> #include <86box/postcard.h> +#include <86box/unittester.h> #include <86box/isamem.h> #include <86box/isartc.h> #include <86box/lpt.h> @@ -111,7 +112,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; @@ -173,6 +174,7 @@ bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activat pass-through for serial ports */ int bugger_enabled = 0; /* (C) enable ISAbugger */ 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 */ @@ -236,8 +238,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 +544,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 +613,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")) { @@ -1042,6 +1048,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 */ @@ -1153,9 +1160,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(); @@ -1199,10 +1203,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 +1224,18 @@ pc_reset_hard_init(void) device_add(&bugger_device); if (postcard_enabled) device_add(&postcard_device); + if (unittester_enabled) + device_add(&unittester_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(); @@ -1359,9 +1372,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 +1592,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..ec32d7548 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -229,5 +229,6 @@ if (QT) elseif(WIN32) add_subdirectory(win) else() + add_compile_definitions(USE_SDL_UI) add_subdirectory(unix) endif() diff --git a/src/acpi.c b/src/acpi.c index 5672fb135..ddd2ffbe7 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -723,7 +723,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); } } @@ -1668,6 +1669,10 @@ 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); diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 40686f14a..ea025de2a 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); @@ -1932,8 +1960,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 +2060,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/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..fe3a0fda3 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -489,12 +489,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; } @@ -984,7 +982,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 +1406,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/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..a1f923e49 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1522,6 +1522,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; 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..3b00b4ffd 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -673,13 +673,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/sis_5511.c b/src/chipset/sis_5511.c index f2ee01ebb..e58066c95 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -262,7 +262,7 @@ sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) 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); + spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82); break; case 0x71: /* DRAM Bank Register 0-0 */ @@ -579,16 +579,19 @@ sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) 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 */ + dev->pci_conf_sb[1][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 */ case 0x49: /* IDE Command Active Time Control */ - dev->pci_conf_sb[1][addr] = val; + dev->pci_conf_sb[1][addr] = val & 0x07; break; case 0x4a: /* IDE General Control Register 0 */ @@ -659,7 +662,11 @@ sis_5513_read(int func, int addr, void *priv) 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]; + if (addr == 0x3d) + ret = (((dev->pci_conf_sb[0x01][0x4b] & 0xc0) == 0xc0) || + (dev->pci_conf_sb[0x01][0x09] & 0x05)) ? PCI_INTA : 0x00; + else + ret = dev->pci_conf_sb[func][addr]; sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret); } @@ -785,7 +792,9 @@ sis_5511_reset(void *priv) 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; @@ -820,13 +829,13 @@ sis_5511_reset(void *priv) 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][0x48] = dev->pci_conf_sb[0][0x49] = 0x00; + dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00; + dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x61] = 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][0x65] = 0x00; 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; @@ -873,6 +882,23 @@ sis_5511_reset(void *priv) 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; + dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00; + dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00; + dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00; + dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00; + dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00; + dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00; + dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00; + dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00; + dev->pci_conf_sb[1][0x40] = 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] = 0x06; + dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00; + dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00; sis_5513_ide_irq_handler(dev); sis_5513_ide_handler(dev); @@ -896,8 +922,6 @@ 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 */ diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index f130ecd8a..007a96178 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 Pentium PCI/ISA Chipset. * + * Authors: Miran Grca, * - * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. + * Copyright 2023-2024 Miran Grca. */ #include #include @@ -26,36 +24,26 @@ #include <86box/io.h> #include <86box/timer.h> -#include <86box/dma.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/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/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; @@ -75,49 +63,87 @@ 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 index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[3][256]; + uint8_t regs[16]; + uint8_t states[7]; + uint8_t pad0; - port_92_t *port_92; - sff8038i_t *ide_drive[2]; + uint8_t usb_unk_regs[8]; + + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[3][256]; + + uint16_t usb_unk_base; + + sff8038i_t *bm[2]; smram_t *smram; + port_92_t *port_92; + void *pit; + nvr_t *nvr; usb_t *usb; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); } sis_5571_t; static void -sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev) +sis_5571_shadow_recalc(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); + 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_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_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_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } flushmmucache_nopc(); } static void -sis_5571_smm_recalc(sis_5571_t *dev) +sis_5571_smram_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); + switch (dev->pci_conf[0xa3] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); break; - case 0x01: - smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); break; - case 0x02: - smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); break; - case 0x03: - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1); + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1); break; default: @@ -127,543 +153,1012 @@ sis_5571_smm_recalc(sis_5571_t *dev) flushmmucache(); } -void -sis_5571_ide_handler(sis_5571_t *dev) +static void +sis_5571_mem_to_pci_reset(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(); + 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_mem_to_pci_write(int func, int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + if (func == 0) { + sis_5571_log("SiS 5571 M2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + 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; + + default: + break; } } } -void -sis_5571_bm_handler(sis_5571_t *dev) +static uint8_t +sis_5571_mem_to_pci_read(int func, int addr, void *priv) { - 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); + const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) { + ret = dev->pci_conf[addr]; + + sis_5571_log("SiS 5571 M2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + } + + return ret; } static void -memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *priv) +sis_5571_pci_to_isa_reset(sis_5571_t *dev) +{ + /* PCI to ISA Bridge */ + dev->pci_conf_sb[0][0x00] = 0x39; + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x03] = 0x00; + dev->pci_conf_sb[0][0x04] = 0x07; + dev->pci_conf_sb[0][0x05] = 0x00; + dev->pci_conf_sb[0][0x06] = 0x00; + dev->pci_conf_sb[0][0x07] = 0x02; + dev->pci_conf_sb[0][0x08] = 0x01; + dev->pci_conf_sb[0][0x09] = 0x00; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; + dev->pci_conf_sb[0][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][0x45] = 0x00; + dev->pci_conf_sb[0][0x46] = 0x00; + dev->pci_conf_sb[0][0x47] = 0x00; + dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00; + dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00; + dev->pci_conf_sb[0][0x61] = 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] = 0x00; + dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00; + dev->pci_conf_sb[0][0x68] = 0x80; + dev->pci_conf_sb[0][0x69] = dev->pci_conf_sb[0][0x6a] = 0x00; + dev->pci_conf_sb[0][0x6b] = 0x00; + dev->pci_conf_sb[0][0x6c] = 0x02; + dev->pci_conf_sb[0][0x6d] = 0x00; + dev->pci_conf_sb[0][0x6e] = dev->pci_conf_sb[0][0x6f] = 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][0x75] = 0x00; + dev->pci_conf_sb[0][0x76] = dev->pci_conf_sb[0][0x77] = 0x00; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + + cpu_set_isa_speed(7159091); + nvr_bank_set(0, 0, dev->nvr); +} + +static void +sis_5571_pci_to_isa_write(int addr, uint8_t val, void *priv) { sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t old; + + sis_5571_log("SiS 5571 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val); switch (addr) { - case 0x04: /* Command - low byte */ - case 0x05: /* Command - high byte */ - dev->pci_conf[addr] |= val; + default: break; - case 0x06: /* Status - Low Byte */ - dev->pci_conf[addr] &= val; + case 0x04: /* Command */ + // dev->pci_conf_sb[0][addr] = val & 0x0f; break; - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= val & 0xbe; + case 0x07: /* Status */ + dev->pci_conf_sb[0][addr] &= ~(val & 0x30); break; - case 0x0d: /* Master latency timer */ - dev->pci_conf[addr] = val; + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3f; break; - case 0x50: /* Host Interface and DRAM arbiter */ - dev->pci_conf[addr] = val & 0xec; + 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 0x51: /* CACHE */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 0x40); - cpu_update_waitstates(); + case 0x45: + dev->pci_conf_sb[0][addr] = val & 0xec; + 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 0x52: - dev->pci_conf[addr] = val & 0xd0; + case 0x46: + dev->pci_conf_sb[0][addr] = val & 0xec; break; - case 0x53: /* DRAM */ - dev->pci_conf[addr] = val & 0xfe; + case 0x47: /* DMA Clock and Wait State Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3e; break; - case 0x54: /* FP/EDO */ - dev->pci_conf[addr] = val; + 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 0x55: - dev->pci_conf[addr] = val & 0xe0; + case 0x60: + outb(0x0070, val); break; - case 0x56: /* MDLE delay */ - case 0x57: /* SDRAM */ - dev->pci_conf[addr] = val & 0xf8; + /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */ + case 0x61: /* MIRQ Remapping Control Register */ + sis_5571_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 0x59: /* Buffer strength and current rating */ - dev->pci_conf[addr] = val; + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf_sb[0][addr] = val; break; - case 0x5a: - dev->pci_conf[addr] = val & 0x03; + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5571_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 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; + 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 */ + sis_5571_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf_sb[0][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_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 & 0x02; + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf_sb[0][addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf_sb[0][addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf_sb[0][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); + dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x02) | (val & 0xdc); break; - case 0x77: /* Characteristics of non-cacheable area */ - dev->pci_conf[addr] = val & 0x0f; + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xef; 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; + case 0x72: /* SMI Triggered By IRQ/GPIO Control */ + case 0x73: /* SMI Triggered By IRQ/GPIO Control */ + dev->pci_conf_sb[0][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: + case 0x74: /* System Standby Timer Reload, + System Standby State Exit And Throttling State Exit Control */ + case 0x75: /* System Standby Timer Reload, + System Standby State Exit And Throttling State Exit Control */ + case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + dev->pci_conf_sb[0][addr] = val; break; } - sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val); } static uint8_t -memory_pci_bridge_read(UNUSED(int func), int addr, void *priv) +sis_5571_pci_to_isa_read(int addr, void *priv) { const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; - sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); - return dev->pci_conf[addr]; + switch (addr) { + default: + ret = dev->pci_conf_sb[0][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: + ret = inb(0x0070); + break; + } + + sis_5571_log("SiS 5571 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret); + + return ret; } static void -pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) +sis_5571_ide_irq_handler(sis_5571_t *dev) +{ + if (dev->pci_conf_sb[1][0x09] & 0x01) { + /* Primary IDE is native. */ + sis_5571_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_5571_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_5571_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_5571_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + } +} + +static void +sis_5571_ide_handler(sis_5571_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_5571_log("sis_5571_ide_handler(): Disabling primary IDE...\n"); + ide_pri_disable(); + sis_5571_log("sis_5571_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_5571_log("sis_5571_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + sis_5571_log("sis_5571_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); + + sis_5571_log("sis_5571_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); + + sis_5571_log("SiS 5571 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->pci_conf_sb[1][0x4a] & 0x04) { + sis_5571_log("sis_5571_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + sis_5571_log("sis_5571_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); + + sis_5571_log("sis_5571_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); + + sis_5571_log("SiS 5571: 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); +} + +static void +sis_5571_ide_reset(sis_5571_t *dev) +{ + /* PCI IDE */ + 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] = 0xc0; + 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; + dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00; + dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00; + dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00; + dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00; +#ifdef DATASHEET + dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00; +#else + /* The only Linux lspci listing I could find of this chipset, + shows a subsystem of 0058:0000. */ + dev->pci_conf_sb[1][0x2c] = 0x58; + dev->pci_conf_sb[1][0x2d] = 0x00; +#endif + dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00; + dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00; + dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00; + dev->pci_conf_sb[1][0x40] = 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] = 0x06; + dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00; + dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00; + + sis_5571_ide_irq_handler(dev); + sis_5571_ide_handler(dev); + + sff_bus_master_reset(dev->bm[0]); + sff_bus_master_reset(dev->bm[1]); +} + +static void +sis_5571_ide_write(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; + sis_5571_log("SiS 5571 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val); + switch (addr) { default: break; + + case 0x04: /* Command low byte */ + dev->pci_conf_sb[1][addr] = val & 0x05; + sis_5571_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 & 0x45); + sis_5571_ide_irq_handler(dev); + sis_5571_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_5571_ide_handler(dev); + break; + + /* The only Linux lspci listing I could find of this chipset, + does not show any BIOS bar, therefore writes to that are disabled. */ +#ifdef DATASHEET + 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; +#endif + + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + 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_sb[1][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 */ + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf_sb[1][addr] = val & 0x07; + 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 */ + dev->pci_conf_sb[1][addr] = val; + 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; } } static uint8_t -pci_isa_bridge_read(int func, int addr, void *priv) +sis_5571_ide_read(int addr, void *priv) { const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + default: + ret = dev->pci_conf_sb[1][addr]; + break; + + case 0x09: + ret = dev->pci_conf_sb[1][addr]; + if (dev->pci_conf_sb[1][0x09] & 0x40) + ret |= ((dev->pci_conf_sb[1][0x4a] & 0x06) << 3); + break; + + case 0x3d: + ret = (dev->pci_conf_sb[1][0x09] & 0x05) ? PCI_INTA : 0x00; + break; + } + + sis_5571_log("SiS 5571 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret); + + return ret; +} + +/* SiS 5571 unknown I/O port (second USB PCI BAR). */ +static void +sis_5571_usb_unk_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + addr = (addr - dev->usb_unk_base) & 0x07; + + sis_5571_log("SiS 5571 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val); + + dev->usb_unk_regs[addr] = val; +} + +static uint8_t +sis_5571_usb_unk_read(uint16_t addr, void *priv) +{ + const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->usb_unk_base) & 0x07; + + ret = dev->usb_unk_regs[addr & 0x07]; + + sis_5571_log("SiS 5571 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5571_usb_reset(sis_5571_t *dev) +{ + /* USB */ + dev->pci_conf_sb[2][0x00] = 0x39; + dev->pci_conf_sb[2][0x01] = 0x10; + dev->pci_conf_sb[2][0x02] = 0x01; + dev->pci_conf_sb[2][0x03] = 0x70; + dev->pci_conf_sb[2][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; + dev->pci_conf_sb[2][0x06] = 0x00; + dev->pci_conf_sb[2][0x07] = 0x02; + 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] = 0x0c; + dev->pci_conf_sb[2][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; + dev->pci_conf_sb[2][0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */; + dev->pci_conf_sb[2][0x0f] = 0x00; + dev->pci_conf_sb[2][0x10] = 0x00; + dev->pci_conf_sb[2][0x11] = 0x00; + dev->pci_conf_sb[2][0x12] = 0x00; + dev->pci_conf_sb[2][0x13] = 0x00; + dev->pci_conf_sb[2][0x14] = 0x01; + dev->pci_conf_sb[2][0x15] = 0x00; + dev->pci_conf_sb[2][0x16] = 0x00; + dev->pci_conf_sb[2][0x17] = 0x00; + dev->pci_conf_sb[2][0x3c] = 0x00; + dev->pci_conf_sb[2][0x3d] = PCI_INTA; + dev->pci_conf_sb[2][0x3e] = 0x00; + dev->pci_conf_sb[2][0x3f] = 0x00; + + 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][0x04] & 0x02); + + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5571_usb_unk_read, NULL, NULL, + sis_5571_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_5571_usb_write(int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + sis_5571_log("SiS 5571 USB: [W] dev->pci_conf_sb[2][%02X] = %02X\n", addr, val); + + if (dev->pci_conf_sb[0][0x68] & 0x40) switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf_sb[2][addr] = val & 0x47; + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5571_usb_unk_read, NULL, NULL, + sis_5571_usb_unk_write, NULL, NULL, dev); + if (dev->pci_conf_sb[2][0x04] & 0x01) + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5571_usb_unk_read, NULL, NULL, + sis_5571_usb_unk_write, NULL, NULL, dev); + } + 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][0x04] & 0x02); + break; + + case 0x05: /* Command - High Byte */ + dev->pci_conf_sb[2][addr] = val & 0x01; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf_sb[2][addr] &= ~(val & 0xf9); + break; + + case 0x0d: /* Latency Timer */ + dev->pci_conf_sb[2][addr] = val; + break; + + 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) ? 0xf0 : 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] & 0x02); + break; + + case 0x14: /* IO Space Base Address Register */ + case 0x15: /* IO Space Base Address Register */ + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5571_usb_unk_read, NULL, NULL, + sis_5571_usb_unk_write, NULL, NULL, dev); + } + dev->pci_conf_sb[2][addr] = val; + dev->usb_unk_base = (dev->pci_conf_sb[2][0x14] & 0xf8) | + (dev->pci_conf_sb[2][0x15] << 8); + if (dev->usb_unk_base != 0x0000) { + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5571_usb_unk_read, NULL, NULL, + sis_5571_usb_unk_write, NULL, NULL, dev); + } + break; + + case 0x3c: /* Interrupt Line */ + dev->pci_conf_sb[2][addr] = val; + break; + } +} + +static uint8_t +sis_5571_usb_read(int addr, void *priv) +{ + const sis_5571_t *dev = (sis_5571_t *) priv; + uint8_t ret = 0xff; + + if (dev->pci_conf_sb[0][0x68] & 0x40) { + ret = dev->pci_conf_sb[2][addr]; + + sis_5571_log("SiS 5571 USB: [R] dev->pci_conf_sb[2][%02X] = %02X\n", addr, ret); + } + + return ret; +} + +static void +sis_5571_sb_write(int func, int addr, uint8_t val, void *priv) +{ + switch (func) { + case 0x00: + sis_5571_pci_to_isa_write(addr, val, priv); + break; + case 0x01: + sis_5571_ide_write(addr, val, priv); + break; + case 0x02: + sis_5571_usb_write(addr, val, priv); + break; + } +} + +static uint8_t +sis_5571_sb_read(int func, int addr, void *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_5571_pci_to_isa_read(addr, priv); + break; + case 0x01: + ret = sis_5571_ide_read(addr, priv); + break; + case 0x02: + ret = sis_5571_usb_read(addr, priv); + break; } + + return ret; } static void @@ -672,52 +1167,16 @@ 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; + sis_5571_mem_to_pci_reset(dev); /* PCI to ISA bridge */ - dev->pci_conf_sb[0][0x00] = 0x39; - dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 0x08; - dev->pci_conf_sb[0][0x04] = 0xfd; - dev->pci_conf_sb[0][0x08] = 0x01; - dev->pci_conf_sb[0][0x0a] = 0x01; - dev->pci_conf_sb[0][0x0b] = 0x06; + sis_5571_pci_to_isa_reset(dev); /* 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]); + sis_5571_ide_reset(dev); /* USB Controller */ - dev->pci_conf_sb[2][0x00] = 0x39; - dev->pci_conf_sb[2][0x01] = 0x10; - dev->pci_conf_sb[2][0x02] = 0x01; - dev->pci_conf_sb[2][0x03] = 0x70; - dev->pci_conf_sb[2][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; + sis_5571_usb_reset(dev); } static void @@ -732,22 +1191,40 @@ sis_5571_close(void *priv) 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)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); - 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: Memory/PCI Bridge */ + pci_add_card(PCI_ADD_NORTHBRIDGE, + sis_5571_mem_to_pci_read, sis_5571_mem_to_pci_write, dev, &dev->nb_slot); + /* Device 1: Southbridge */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5571_sb_read, sis_5571_sb_write, dev, &dev->sb_slot); /* MIRQ */ - pci_enable_mirq(0); + pci_enable_mirq(1); - /* Port 92 & SMRAM */ - dev->port_92 = device_add(&port_92_pci_device); - dev->smram = smram_add(); + /* IDEIRQ */ + pci_enable_mirq(2); + + /* USBIRQ */ + pci_enable_mirq(3); + + /* Port 92h */ + dev->port_92 = device_add(&port_92_device); /* SFF IDE */ - dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); - dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); + 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); /* USB */ dev->usb = device_add(&usb_device); diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 4d1db2d9e..b9b2544c8 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()*/; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index ae4b30228..ef076b606 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,452 @@ #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]; + + 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_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; + } +} + +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)) + mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + 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)) + mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); +} + +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; +} + +static void +wd76c10_shadow_ram_do_recalc(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); + mem_set_mem_state_both(base, 0x00004000, flags); + } + } +} + + +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(vbios_states, dev->vbios_states, 0, 4, 0x000c0000); + wd76c10_shadow_ram_do_recalc(bios_states, dev->bios_states, 0, 8, 0x000e0000); + + /* This is not shadowed, but there is a CSPROM# (= ROMCS#) toggle. */ + wd76c10_shadow_ram_do_recalc(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); + + size = 0x01000000 - base; + mem_set_wp(base, size, ACCESS_NORMAL, hm_wp); + + 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; + mem_set_mem_state(base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + + /* 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) + mem_set_mem_state(dev->ems_pages[ems_page].virt, 0x00004000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } +} + +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; + } +} + +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 +491,463 @@ 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); + return dev; } 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..f1807c316 100644 --- a/src/config.c +++ b/src/config.c @@ -244,25 +244,81 @@ 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; + /* 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_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; @@ -721,6 +777,7 @@ 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; @@ -754,17 +811,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) { @@ -1104,13 +1160,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 +1276,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 +1409,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 +1525,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 +1570,9 @@ 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); 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); @@ -1622,6 +1680,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; @@ -1845,11 +1920,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); @@ -1866,57 +1936,6 @@ save_machine(void) 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 @@ -2348,6 +2367,11 @@ 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); + 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..b5a1e61e3 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -240,6 +240,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 +260,14 @@ 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(); + + if (!cpu_state.abrt && ins_fetch_fault) { + x86gen(); + ins_fetch_fault = 0; + /* No instructions executed at this point. */ + goto block_ended; + } if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG @@ -267,7 +276,7 @@ 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); @@ -287,6 +296,7 @@ exec386_2386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; +block_ended: if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; @@ -309,14 +319,17 @@ exec386_2386(int32_t cycs) #endif } } + if (!x86_was_reset && ins_fetch_fault) + x86gen(); /* This is supposed to be the first one serviced by the processor according to the manual. */ } 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..4b4037207 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; @@ -1491,7 +1492,7 @@ x86_int_sw(int num) } } - trap = 0; + trap &= ~1; CPU_BLOCK_END(); } @@ -1534,7 +1535,7 @@ x86_int_sw_rm(int num) #endif cycles -= timing_int_rm; - trap = 0; + trap &= ~1; CPU_BLOCK_END(); return 0; @@ -1655,6 +1656,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..35d4f7cc8 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -674,3 +674,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..1bb3c167f 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -181,7 +181,11 @@ extern void x386_dynarec_log(const char *fmt, ...); #ifndef OPS_286_386 # include "x86_ops_cyrix.h" #endif -#include "x86_ops_flag.h" +#ifdef OPS_286_386 +# include "x86_ops_flag_2386.h" +#else +# include "x86_ops_flag.h" +#endif #include "x86_ops_fpu.h" #include "x86_ops_inc_dec.h" #include "x86_ops_int.h" @@ -200,7 +204,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 @@ -218,7 +226,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 +641,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 +656,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 +678,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 +700,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 +722,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..90563d9ab 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -563,9 +563,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 +1223,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 diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 47e64a275..e05ec0d9c 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -181,6 +181,8 @@ int cpu_multi; int cpu_16bitbus; int cpu_64bitbus; int cpu_cyrix_alignment; +int cpu_cpurst_on_sr; +int cpu_use_exec = 0; int CPUID; int is186; @@ -742,6 +744,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) { @@ -1782,16 +1785,20 @@ 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_486DLC)) { 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; @@ -2370,14 +2377,20 @@ cpu_CPUID(void) EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { - EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries - Instruction TLB: 4 MB pages, fully associative, 2 entries - Data TLB: 4 KB pages, 4-way set associative, 64 entries */ + /* if (!strcmp(machine_get_internal_name(), "ap61")) { + EAX = 0x00000001; + EDX = 0x00000000; + } else */ { + EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries + Instruction TLB: 4 MB pages, fully associative, 2 entries + Data TLB: 4 KB pages, 4-way set associative, 64 entries */ + 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 */ + } + EBX = ECX = 0; - 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 */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2791,7 +2804,9 @@ amd_k_invalid_rdmsr: case CPU_PENTIUM2: case CPU_PENTIUM2D: EAX = EDX = 0; - 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) { case 0x00: case 0x01: break; @@ -2813,6 +2828,11 @@ amd_k_invalid_rdmsr: 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; case 0x2a: EAX = 0xc4000000; EDX = 0; @@ -3014,22 +3034,6 @@ amd_k_invalid_rdmsr: EAX = msr.ecx570 & 0xffffffff; EDX = msr.ecx570 >> 32; break; - case 0x1002ff: - EAX = msr.ecx1002ff & 0xffffffff; - EDX = msr.ecx1002ff >> 32; - break; - case 0xf0f00250: - EAX = msr.ecxf0f00250 & 0xffffffff; - EDX = msr.ecxf0f00250 >> 32; - break; - case 0xf0f00258: - EAX = msr.ecxf0f00258 & 0xffffffff; - EDX = msr.ecxf0f00258 >> 32; - break; - case 0xf0f00259: - EAX = msr.ecxf0f00259 & 0xffffffff; - EDX = msr.ecxf0f00259 >> 32; - break; default: i686_invalid_rdmsr: cpu_log("RDMSR: Invalid MSR: %08X\n", ECX); @@ -3291,7 +3295,9 @@ amd_k_invalid_wrmsr: 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) { case 0x00: case 0x01: if (EAX || EDX) @@ -3306,6 +3312,10 @@ amd_k_invalid_wrmsr: 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; case 0x2a: break; case 0x79: @@ -3450,18 +3460,6 @@ amd_k_invalid_wrmsr: case 0x570: msr.ecx570 = EAX | ((uint64_t) EDX << 32); break; - case 0x1002ff: - msr.ecx1002ff = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00250: - msr.ecxf0f00250 = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00258: - msr.ecxf0f00258 = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00259: - msr.ecxf0f00259 = EAX | ((uint64_t) EDX << 32); - break; default: i686_invalid_wrmsr: cpu_log("WRMSR: Invalid MSR: %08X\n", ECX); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 9bdcca84c..dfde094f0 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -86,42 +86,34 @@ 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_SOCKET6 = (1 << 18), + CPU_PKG_STPC = (1 << 19), + CPU_PKG_SOCKET4 = (1 << 20), + CPU_PKG_SOCKET5_7 = (1 << 21), + CPU_PKG_SOCKET8 = (1 << 22), + CPU_PKG_SLOT1 = (1 << 23), + CPU_PKG_SLOT2 = (1 << 24), + CPU_PKG_SOCKET370 = (1 << 25) }; -#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 +157,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 @@ -253,6 +234,12 @@ typedef struct { /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */ + + /* Weird long MSR's used by the Hyper-V BIOS. */ + uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits + like a real Deschutes does. */ + + /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ uint64_t ecx79; /* 0x00000079 */ /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ @@ -314,9 +301,6 @@ typedef struct { /* 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 */ @@ -338,11 +322,6 @@ typedef struct { /* 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 */ } msr_t; typedef struct { @@ -530,7 +509,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 +522,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; @@ -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,6 +814,9 @@ 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); diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 947804014..dbbf0f397 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} } }, { @@ -1267,7 +1278,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. They are functionally identical*/ + .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330 | CPU_PKG_SOCKET6, /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. They are functionally identical*/ .manufacturer = "Intel", .name = "iDX4", .internal_name = "idx4", @@ -1277,7 +1288,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330 | CPU_PKG_SOCKET6, .manufacturer = "Intel", .name = "Pentium OverDrive", .internal_name = "pentium_p24t", @@ -1349,7 +1360,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "AMD", .name = "Am486DX4", .internal_name = "am486dx4", @@ -1361,7 +1372,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "AMD", .name = "Am486DX2 (Enhanced)", .internal_name = "am486dx2_slenh", @@ -1371,7 +1382,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "AMD", .name = "Am486DX4 (Enhanced)", .internal_name = "am486dx4_slenh", @@ -1382,7 +1393,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "AMD", .name = "Am5x86", .internal_name = "am5x86", @@ -1425,7 +1436,17 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET6, + .manufacturer = "Cyrix", + .name = "Cx486DX2", + .internal_name = "cx486dx2v", + .cpus = (const CPU[]) { + {"66", CPU_Cx486DX, fpus_internal, 66666666, 2.0, 5000, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, + {"80", CPU_Cx486DX, fpus_internal, 80000000, 2.0, 5000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"", 0} + } + }, { + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "Cyrix", .name = "Cx486DX4", .internal_name = "cx486dx4", @@ -1435,7 +1456,7 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { - .package = CPU_PKG_SOCKET3, + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET6, .manufacturer = "Cyrix", .name = "Cx5x86", .internal_name = "cx5x86", @@ -1972,957 +1993,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/x86.c b/src/cpu/x86.c index 93674ae5c..64ff6be4c 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -342,6 +342,8 @@ reset_common(int hard) if (!is286) reset_808x(hard); + + 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_misc.h b/src/cpu/x86_ops_misc.h index e36fa4800..cbd2b3fbe 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); diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index b0c841f83..eafe3cdde 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -124,7 +124,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) 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) + if ((cpu_s->cpu_type != CPU_386DX) || (fpu_type == FPU_387)) cr0 |= 0x10; if (!(cr0 & 0x80000000)) mmu_perm = 4; @@ -181,7 +181,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) 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) + if ((cpu_s->cpu_type != CPU_386DX) || (fpu_type == FPU_387)) cr0 |= 0x10; if (!(cr0 & 0x80000000)) mmu_perm = 4; 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..c57dc8226 --- /dev/null +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -0,0 +1,414 @@ +static int +opMOV_r_CRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_CRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_r_DRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_DRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_CRx_r_a16(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + break; + } + + 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 || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[6] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + dr[7] |= 0x2000; + dr[6] &= ~0x2000; + x86gen(); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + 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 || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + if (cpu_reg == 4 || cpu_reg == 5) { + if (cr4 & 0x8) + x86illegal(); + else + cpu_reg += 2; + } + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + 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_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_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/x86seg.c b/src/cpu/x86seg.c index 96061d3fa..245f3fa65 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,15 @@ 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); + + rf_flag_no_clear = 1; + + if (t_bit) { + trap |= 2; +#ifdef USE_DYNAREC + cpu_block_end = 1; +#endif + } } else { if (limit < 43) { x86ts(NULL, seg); @@ -2454,6 +2469,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.limit = limit; tr.access = segdat[2] >> 8; tr.ar_high = segdat[3] & 0xff; + 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/device.c b/src/device.c index c517f98e9..6125674db 100644 --- a/src/device.c +++ b/src/device.c @@ -849,3 +849,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..24a9d7ac4 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -17,11 +17,11 @@ 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 + postcard.c serial.c unittester.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c kbc_at.c kbc_at_dev.c keyboard_at.c - mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c + mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c serial_passthrough.c) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") 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/isapnp.c b/src/device/isapnp.c index 7b9d570bb..f9d10b380 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. */ diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 8045ea1df..bc4a1f366 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 @@ -141,8 +144,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; @@ -695,10 +699,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 +748,7 @@ 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*/ + if (!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"); @@ -765,6 +777,28 @@ write_p2(atkbc_t *dev, uint8_t val) /* Do this here to avoid an infinite reset loop. */ dev->p2 = val; + + if (cpu_cpurst_on_sr && ((old ^ val) & 0x01)) { /*Reset*/ + if (!(val & 0x01)) { /* Pin 0 selected. */ + /* Pin 0 selected. */ + pclog("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 @@ -1753,6 +1787,9 @@ kbc_at_process_cmd(void *priv) if (dev->ib == 0xbb) break; + if (strstr(machine_get_internal_name(), "pb") != 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)) { @@ -1857,6 +1894,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(), "pb") != NULL) && (cpu_override_dynarec == 1)) + cpu_override_dynarec = 0; break; case 0x64: @@ -1934,7 +1973,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) { @@ -1966,9 +2006,11 @@ kbc_at_init(const device_t *info) io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev); io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, dev); - timer_add(&dev->send_delay_timer, kbc_at_poll, dev, 1); + timer_add(&dev->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; 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/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..00da385d4 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) add_library(zip OBJECT zip.c) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 07df9d0e6..7bfb7e05a 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -100,12 +100,10 @@ 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 }, diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 2bb83b4ab..39031138f 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -734,19 +734,25 @@ ide_get_sector(ide_t *ide) 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 @@ -1389,8 +1395,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; @@ -1771,7 +1784,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->tf->error = ABRT_ERR; ide_irq_raise(ide); } - return; + break; default: break; @@ -1788,7 +1801,7 @@ ide_read_data(ide_t *ide, int length) double xfer_us; #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 @@ -1868,7 +1881,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) @@ -1948,8 +1962,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; @@ -2070,7 +2084,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 +2096,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) { @@ -2287,6 +2305,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 +2326,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: @@ -2446,6 +2468,7 @@ ide_callback(void *priv) else { ide->blocksize = ide->tf->secount; ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); } break; @@ -2961,6 +2984,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)) 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_st506_xt.c b/src/disk/hdc_st506_xt.c index 40709d307..fc20350b0 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. */ @@ -1533,6 +1533,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 +1547,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 +1667,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/zip.c b/src/disk/zip.c index 7045b1e41..d4b644865 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -531,7 +531,7 @@ zip_load(zip_t *dev, char *fn) if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) fatal("zip_load(): Error seeking to the beginning of the file\n"); - strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1); + strncpy(dev->drv->image_path, fn, strlen(dev->drv->image_path) + 1); return 1; } diff --git a/src/dma.c b/src/dma.c index 55cf31236..50ae598b8 100644 --- a/src/dma.c +++ b/src/dma.c @@ -949,16 +949,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; } diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 88948aed9..f30d86168 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -212,6 +212,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 +258,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 +271,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 +293,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 @@ -321,7 +322,7 @@ fdc_stop_id_request(fdc_t *fdc) int fdc_get_gap(fdc_t *fdc) { - return fdc->gap; + return (int) fdc->gap; } int @@ -333,7 +334,7 @@ fdc_get_dtl(fdc_t *fdc) int fdc_get_format_sectors(fdc_t *fdc) { - return fdc->format_sectors; + return (int) fdc->format_sectors; } static void @@ -418,6 +419,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 +434,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 +497,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 +507,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*/ } @@ -688,10 +692,6 @@ fdc_io_command_phase1(fdc_t *fdc, int out) fdc->stat |= 0x20; else dma_set_drq(fdc->dma_ch, 1); - if (out) - fdc->pos = 0; - else - fdc->inread = 1; } static void @@ -741,7 +741,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 +776,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++) { @@ -854,7 +860,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 +871,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 +892,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 +910,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 +926,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 +962,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 +969,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 +976,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); @@ -1151,7 +1146,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 +1267,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); @@ -1513,7 +1507,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,10 +1537,21 @@ 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 0x01: /* Mode */ @@ -1570,7 +1574,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; @@ -1715,7 +1718,6 @@ fdc_callback(void *priv) default: break; } - fdc->inread = 1; return; case 0x07: /* Recalibrate */ fdc->pcn[fdc->params[0] & 3] = 0; @@ -2004,18 +2006,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 +2020,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 +2027,6 @@ void fdc_sector_finishread(fdc_t *fdc) { fdc->stat = 0x10; - fdc->inread = 0; fdc_callback(fdc); } @@ -2356,6 +2349,8 @@ fdc_reset(void *priv) for (uint8_t i = 0; i < FDD_NUM; i++) ui_sb_update_icon(SB_FLOPPY | i, 0); + + fdc->power_down = 0; } static void @@ -2418,7 +2413,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 = { 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/include/86box/86box.h b/src/include/86box/86box.h index ae2ea260c..20f3fffcc 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -33,7 +33,7 @@ /* Recently used images */ #define MAX_PREV_IMAGES 4 -#define MAX_IMAGE_PATH_LEN 256 +#define MAX_IMAGE_PATH_LEN 2048 /* Default language 0xFFFF = from system, 0x409 = en-US */ #define DEFAULT_LANGUAGE 0x0409 @@ -125,6 +125,7 @@ extern int gfxcard[2]; /* (C) graphics/video card */ extern char video_shader[512]; /* (C) video */ extern int bugger_enabled; /* (C) enable ISAbugger */ extern int postcard_enabled; /* (C) enable POST card */ +extern int 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 */ 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/chipset.h b/src/include/86box/chipset.h index 95440a172..4aa3ee3e9 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -174,6 +174,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..71a76c6b1 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -41,23 +41,41 @@ #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_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 +118,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; @@ -202,6 +231,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/fdc.h b/src/include/86box/fdc.h index 9441bdfc4..09c9c4578 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -65,76 +65,85 @@ 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 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 specify[2]; + + uint8_t res[11]; + + uint8_t eot[4]; + uint8_t rwc[4]; + uint8_t params[8]; uint8_t fifobuf[16]; + 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]; sector_id_t read_track_sector; sector_id_t format_sector_id; @@ -183,6 +192,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); 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/hdc.h b/src/include/86box/hdc.h index 8ede3e786..01f927185 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) */ @@ -86,9 +89,7 @@ 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 */ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 291dec303..1f7a78c9f 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -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); 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/keyboard.h b/src/include/86box/keyboard.h index a4b079760..759fad714 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; 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..4fba180b2 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 */ @@ -471,6 +472,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 +487,7 @@ 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_rycleopardlx_init(const machine_t *); @@ -504,6 +507,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 +515,8 @@ 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_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); @@ -524,16 +530,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 +558,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 +566,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 +608,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,17 +622,20 @@ 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 *); @@ -638,10 +661,12 @@ 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_ms5124_init(const machine_t *); +extern int machine_at_amis727_init(const machine_t *); extern int machine_at_vectra54_init(const machine_t *); /* m_at_socket7.c */ @@ -654,6 +679,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 *); @@ -678,6 +704,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,6 +713,7 @@ 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 *); @@ -692,6 +721,7 @@ extern int machine_at_ms5164_init(const machine_t *); /* m_at_sockets7.c */ extern int machine_at_p5a_init(const machine_t *); extern int machine_at_m579_init(const machine_t *); +extern int machine_at_gwlucas_init(const machine_t *); extern int machine_at_5aa_init(const machine_t *); extern int machine_at_5ax_init(const machine_t *); @@ -701,11 +731,12 @@ extern int machine_at_ficva503a_init(const machine_t *); extern int machine_at_5emapro_init(const machine_t *); /* m_at_socket8.c */ +extern int machine_at_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 +757,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 *); @@ -846,6 +880,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..15afcb160 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -398,6 +398,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 +440,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 +450,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/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_pcnet.h b/src/include/86box/net_pcnet.h index ccdc7e832..23ee643ed 100644 --- a/src/include/86box/net_pcnet.h +++ b/src/include/86box/net_pcnet.h @@ -36,5 +36,6 @@ 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; #endif /*NET_PCNET_H*/ diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h index 3e14deeea..2ee7ec3c1 100644 --- a/src/include/86box/net_tulip.h +++ b/src/include/86box/net_tulip.h @@ -1,3 +1,4 @@ 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; diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 17f9f6687..2bcb6b3b8 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 diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 0d5b17a3c..1f5f2b695 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -149,6 +149,7 @@ 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); 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 index 20067aa40..2e6628c77 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -79,10 +79,10 @@ #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_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: */ 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/serial.h b/src/include/86box/serial.h index bd7e85a91..08f77ea13 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -124,11 +124,11 @@ 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 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..b07e73e8e 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; 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/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 da4e9e700..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 ibm_mode; + 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..624e85a1b 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -118,16 +118,18 @@ 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 ati_4color; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -164,8 +166,10 @@ typedef struct svga_t { latch_t latch; pc_timer_t timer; + pc_timer_t timer8514; double clock; + double clock8514; hwcursor_t hwcursor; hwcursor_t hwcursor_latch; @@ -231,6 +235,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 +251,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 +273,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 +356,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 +417,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..e82807a12 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, @@ -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; @@ -345,6 +348,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; @@ -431,12 +435,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 +459,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 +480,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; @@ -485,6 +492,7 @@ extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_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; diff --git a/src/include_make/86box/version.h b/src/include_make/86box/version.h index 9a175be24..4004f58b3 100644 --- a/src/include_make/86box/version.h +++ b/src/include_make/86box/version.h @@ -34,7 +34,7 @@ #define EMU_VERSION_FULL EMU_VERSION #define EMU_VERSION_FULL_W EMU_VERSION_W -#define COPYRIGHT_YEAR "2022" +#define COPYRIGHT_YEAR "2024" /* Web URL info. */ #define EMU_SITE "86box.net" diff --git a/src/lpt.c b/src/lpt.c index 5bbf79875..dd77b3516 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -165,6 +165,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/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..a688181b4 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -304,6 +304,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; } @@ -406,6 +408,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 +453,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 +489,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 +554,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 +719,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 +743,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 +779,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..5a47af620 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -93,7 +93,7 @@ machine_at_asus386_init(const machine_t *model) 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 +144,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 +224,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) { @@ -381,10 +402,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 +424,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 +461,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 +517,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 +532,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 +574,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) { @@ -619,6 +660,39 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } +int +machine_at_pb450_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pb450/OPTI802.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, 5, 4, 3, 2); + pci_register_slot(0x12, PCI_CARD_NORMAL, 9, 8, 7, 6); + + device_add(&opti895_device); + device_add(&opti822_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c661_ide_device); + device_add(&ide_opti611_vlb_sec_device); + device_add(&ide_vlb_2ch_device); + device_add(&intel_flash_bxt_device); + device_add(&phoenix_486_jumper_pci_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5428_vlb_onboard_device); + + return ret; +} + int machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU other than the iDX4 and the Intel OverDrive, hangs without a PS/2 mouse */ { @@ -700,7 +774,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 +791,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 +808,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 +843,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 +893,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,6 +921,29 @@ 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)) { @@ -939,6 +1064,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 +1158,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 +1190,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 +1204,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 +1317,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 +1360,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 +1391,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 +1452,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 +1663,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 +1775,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 +1887,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; @@ -1670,6 +1977,37 @@ machine_at_actionpc2600_init(const machine_t *model) 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); + if (gfxcard[0] == VID_INTERNAL) + pci_register_slot(0x15, PCI_CARD_VIDEO, 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_8886af_device); + device_add(&fdc37c665_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_pci_device); // VBIOS not included in BIOS ROM + + return ret; +} + int machine_at_m919_init(const machine_t *model) { @@ -1821,3 +2159,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_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_phoenix_trio32_onboard_vlb_device); + + 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(&um8669f_device); // needs um8663 + + 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; +} \ No newline at end of file diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 86656b181..428199de7 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -795,11 +795,6 @@ machine_at_compaq_init(const machine_t *model, int type) break; case COMPAQ_PORTABLEIII: - if (gfxcard[0] == VID_INTERNAL) - device_add(&compaq_plasma_device); - machine_at_init(model); - break; - case COMPAQ_PORTABLEIII386: if (hdc_current == 1) device_add(&ide_isa_device); @@ -810,8 +805,6 @@ machine_at_compaq_init(const machine_t *model, int type) 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); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 184cfc34d..12c84ffdf 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -152,6 +152,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 +259,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) { diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 2b2615422..4164b425a 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -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; } diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index ad6d2c995..02018949c 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,31 +60,6 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) device_add(&intel_flash_bxt_ami_device); } -void -machine_at_award_common_init(const machine_t *model) -{ - 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) { @@ -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; diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0b67976af..4a86c75d0 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -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) { diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index fa81b40db..fd453f9af 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) @@ -433,6 +435,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 +563,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); @@ -563,7 +594,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); @@ -1014,6 +1045,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 +1192,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 +1221,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 +1239,35 @@ 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_m560_init(const machine_t *model) { diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index de87ec90d..2e642082d 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -547,7 +547,7 @@ machine_at_acerm3a_init(const machine_t *model) 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 +671,40 @@ 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(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 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); + + return ret; +} + int machine_at_gw2kte_init(const machine_t *model) { @@ -694,7 +728,7 @@ 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); @@ -718,7 +752,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 +781,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 +797,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) { diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 628206a61..e1dad68e7 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) { @@ -161,6 +194,37 @@ machine_at_acerv60n_init(const machine_t *model) 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) { diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 382a4f327..8ff1a367d 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) { 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_ps1.c b/src/machine/m_ps1.c index d2c9f80ba..e0a15126e 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(); @@ -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_xt.c b/src/machine/m_xt.c index a374b58f3..9a0b39a89 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -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/machine.c b/src/machine/machine.c index 1684f312a..9e530eb3b 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -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..13a5d5452 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -33,6 +33,7 @@ #include <86box/sound.h> #include <86box/video.h> #include <86box/plat_unused.h> +#include <86box/net_pcnet.h> // Temporarily here till we move everything out into the right files extern const device_t pcjr_device; @@ -51,6 +52,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 }, @@ -707,6 +709,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", @@ -2546,7 +2587,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, @@ -2728,8 +2769,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 +2809,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, @@ -3300,7 +3341,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 +3361,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,7 +3501,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, + .flags = MACHINE_IDE, .ram = { .min = 512, .max = 16384, @@ -3540,7 +3581,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 +3661,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,8 +3700,8 @@ 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, @@ -3923,7 +3964,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 +4004,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 +4025,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 +4044,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 +4106,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4498,7 +4576,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 +4628,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 +4781,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 +4913,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 +4952,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 +4993,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, @@ -4980,6 +5059,86 @@ const machine_t machines[] = { .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 +5223,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 +5245,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 +5285,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 +5303,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 +5451,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 +5534,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 +5574,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 +5614,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 +5655,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 +5673,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 +5796,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 +5831,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 @@ -5785,7 +5981,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 +6021,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 +6039,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 +6101,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 +6119,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 +6160,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 +6226,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 +6244,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 +6284,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 +6404,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 = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &gd5428_vlb_onboard_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an + 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. + The photo of the board shows an AMIKey KBC which is indeed F. */ + { + .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 +6508,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 +6548,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 +6588,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 +6606,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 +6628,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, @@ -6369,9 +6686,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 = &s3_phoenix_trio32_onboard_vlb_device, + .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 = "[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 = &tgui9440_onboard_pci_device, + .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 +6870,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 +6911,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 +6962,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 +6991,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 +7138,46 @@ 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, + .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 PC 330 (type 6573)", @@ -6722,7 +7240,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 +7279,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 +7440,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 +7480,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 +7498,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 +7561,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 +7600,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 +7699,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 +7739,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 +7779,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 +7821,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", @@ -7223,6 +7861,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 +7943,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 +7983,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, @@ -7343,6 +8021,47 @@ const machine_t machines[] = { .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, + .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. */ { @@ -7427,10 +8146,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, @@ -7670,6 +8389,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, + .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 +8541,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 +8580,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_APM, .ram = { .min = 2048, .max = 196608, @@ -7860,8 +8620,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 +8661,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 +8703,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 +8743,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 +8783,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 +8801,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 +8822,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 +8863,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 +8907,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 +8949,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 +8991,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 +9031,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 +9049,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Socket 5 machines */ /* 430NX */ /* This has the Phoenix MultiKey KBC firmware. */ @@ -8314,7 +9073,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 +9113,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 +9154,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 +9172,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 +9194,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 +9276,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 +9316,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 +9358,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 +9398,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 +9438,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 +9522,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 +9563,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 +9644,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 +9684,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 +9724,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, @@ -8867,9 +9745,10 @@ const machine_t machines[] = { /* 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 +9768,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 +9788,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 +9808,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 +9826,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 +9848,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 +9890,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 +9931,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 +9973,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 +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 | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9178,7 +10057,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 +10097,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 +10138,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 +10178,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 +10196,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 +10218,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 +10238,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,7 +10260,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, /* Machine has internal SCSI */ .ram = { .min = 8192, .max = 196608, @@ -9401,7 +10278,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 +10300,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 +10340,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 +10358,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 +10381,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 +10401,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 = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey H KBC firmware (AMIKey-2). */ { .name = "[i430VX] ECS P5VX-B", @@ -9546,7 +10465,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,7 +10507,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, @@ -9630,7 +10549,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, @@ -9670,7 +10589,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,7 +10672,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, @@ -9753,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, .ram = { .min = 8192, .max = 262144, @@ -9793,7 +10752,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 +10794,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 +10834,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 +10874,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 +10914,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 +10957,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 +10975,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 +10996,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 +11015,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 +11079,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 +11097,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 +11118,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 +11160,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 +11178,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 +11200,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,7 +11321,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, @@ -10362,9 +11361,9 @@ 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 }, @@ -10404,7 +11403,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,7 +11443,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, .ram = { .min = 8192, .max = 131072, @@ -10485,7 +11484,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 +11525,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 +11567,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 +11607,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 +11625,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 +11729,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 +11769,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 +11787,8 @@ 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. */ + /* 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 +11810,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 +11850,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 +11890,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 +11973,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 +12016,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 +12038,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 +12050,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 +12098,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 +12116,48 @@ 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 + }, + + /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */ { .name = "[ALi ALADDiN IV+] MSI MS-5164", @@ -11100,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 = 1048576, @@ -11118,6 +12198,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,7 +12263,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_GAMEPORT | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11184,7 +12304,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 +12322,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 +12384,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 +12424,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 +12467,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 +12508,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 +12549,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 +12590,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, @@ -11452,6 +12612,46 @@ const machine_t machines[] = { /* 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 +12672,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,7 +12715,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, @@ -11533,7 +12733,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 +12754,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 +12773,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 +12795,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 +12813,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 +12875,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 +12917,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 +12959,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 +12977,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 +12993,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,7 +13039,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_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11817,9 +13057,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 +13079,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 +13122,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 +13142,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 +13164,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 +13205,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 +13248,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 +13289,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 +13307,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a SM(S)C FDC37M60x 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 +13373,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 +13416,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 +13457,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 +13498,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 +13539,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 +13580,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 +13621,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 +13639,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 +13702,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 +13743,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 +13785,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 +13826,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 +13850,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 +13870,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 +13913,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 +13954,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 +13995,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 +14036,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, @@ -12761,7 +14080,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 +14124,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 +14166,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 +14210,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 +14251,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 +14295,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 +14337,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 has internal video: C&T B69000, sound: ESS ES1938S and NIC: Realtek RTL8139C */ .ram = { .min = 8192, .max = 524288, @@ -13060,7 +14379,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 +14420,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 +14463,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 +14486,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 +14506,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 +14547,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 +14590,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 +14631,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 +14646,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 +14672,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 +14712,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 +14756,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..188aa49d0 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -132,6 +132,8 @@ 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 +1587,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 +1633,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 +1651,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 +1673,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 +1713,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 +1728,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 +1747,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 +1785,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 +1799,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 +1813,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 +2045,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 +2059,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 +2073,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 +2084,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 +2093,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 +2102,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 +2111,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 +2120,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 +2129,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 +2139,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 +2151,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 +2163,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 +2175,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 +2187,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 +2199,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 +2284,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 +2303,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 +2398,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 +2824,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 +2905,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..9ed26edfa 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -39,6 +39,54 @@ #include <86box/rom.h> #include <86box/gdbstub.h> +/* Set trap for data address breakpoints. */ +void +mem_debug_check_addr(uint32_t addr, int write) +{ + int i = 0; + int set_trap = 0; + + if (!(dr[7] & 0xFF)) + return; + + for (i = 0; i < 4; i++) { + uint32_t dr_addr = dr[i]; + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); + int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); + if (!breakpoint_enabled) + continue; + if (!write && (len_type_pair & 3) != 3) + continue; + if ((len_type_pair & 3) != 1) + continue; + + switch ((len_type_pair >> 2) & 3) + { + case 0x00: + if (dr_addr == addr) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x01: + if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x03: + dr_addr &= ~3; + if (addr >= dr_addr && addr < (dr_addr + 4)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + } + } + if (set_trap) + trap |= 4; +} + uint8_t mem_readb_map(uint32_t addr) { @@ -243,6 +291,7 @@ readmembl_2386(uint32_t addr) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, 0); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -270,6 +319,7 @@ writemembl_2386(uint32_t addr, uint8_t val) mem_mapping_t *map; uint64_t a; + mem_debug_check_addr(addr, 1); GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); addr64 = (uint64_t) addr; @@ -347,6 +397,8 @@ readmemwl_2386(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 0); + mem_debug_check_addr(addr + 1, 0); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -402,6 +454,8 @@ writememwl_2386(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 1); + mem_debug_check_addr(addr + 1, 1); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -555,8 +609,10 @@ 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, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; @@ -626,8 +682,10 @@ 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, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; @@ -807,8 +865,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, 0); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -870,8 +930,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, 1); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -957,32 +1019,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); + 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/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/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_pcnet.c b/src/network/net_pcnet.c index ab761acf3..9ddcfe29d 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -866,7 +866,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 +2896,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 +2997,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 +3104,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 +3122,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 +3169,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 +3272,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_rtl8139.c b/src/network/net_rtl8139.c index d1e14fb12..8afb7b4b8 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -39,6 +39,7 @@ #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" @@ -307,6 +308,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 +354,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 +441,6 @@ struct RTL8139State { uint32_t RxRingAddrLO; uint32_t RxRingAddrHI; - EEprom9346 eeprom; - uint32_t TCTR; uint32_t TimerInt; int64_t TCTR_base; @@ -490,6 +453,8 @@ struct RTL8139State { int cplus_txbuffer_len; int cplus_txbuffer_offset; + uint32_t mem_base; + /* PCI interrupt timer */ pc_timer_t timer; @@ -497,190 +462,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 +1223,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 +1306,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 +1327,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 +2287,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 +2748,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 +2920,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 +3124,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 +3182,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 +3221,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 +3277,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 +3304,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_tulip.c b/src/network/net_tulip.c index b74b345bc..5fed7f1d1 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -323,6 +323,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 +669,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 +704,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 +894,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 +967,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 +994,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 +1038,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 +1180,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 +1226,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 +1276,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 +1307,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 +1332,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 +1377,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 +1395,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 +1403,219 @@ 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 { + /*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 +1630,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; @@ -1592,3 +1718,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/network.c b/src/network/network.c index 38af502b2..4d11ba955 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -136,6 +136,7 @@ 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, NULL }; diff --git a/src/nvr_at.c b/src/nvr_at.c index c66799579..7e356f55d 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -692,7 +692,7 @@ 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 +810,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 { diff --git a/src/pci.c b/src/pci.c index 7c61545b2..15a119cb7 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); diff --git a/src/pit.c b/src/pit.c index f5816aaf5..6045fd842 100644 --- a/src/pit.c +++ b/src/pit.c @@ -659,13 +659,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; } diff --git a/src/pit_fast.c b/src/pit_fast.c index 1168cb3c5..f9d055375 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -522,13 +522,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; } 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/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 371781b7a..71b643220 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -352,6 +352,9 @@ msgstr "Tipus de CPU:" msgid "Speed:" msgstr "Velocitat:" +msgid "Frequency:" +msgstr "Freqüència:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index d86f5b635..0069f245b 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -352,6 +352,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rychlost:" +msgid "Frequency:" +msgstr "Frekvence:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 9c985d871..ed8e57ffa 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -352,6 +352,9 @@ msgstr "CPU-Typ:" msgid "Speed:" msgstr "Takt:" +msgid "Frequency:" +msgstr "Frequenz:" + msgid "FPU:" msgstr "FPU-Einheit:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 4a6a58db6..b56c274d3 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -352,6 +352,9 @@ msgstr "CPU type:" msgid "Speed:" msgstr "Speed:" +msgid "Frequency:" +msgstr "Frequency:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Video:" 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,17 +412,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" -msgstr "Sound card 1:" +msgid "Sound card #1:" +msgstr "Sound card #1:" -msgid "Sound card 2:" -msgstr "Sound card 2:" +msgid "Sound card #2:" +msgstr "Sound card #2:" -msgid "Sound card 3:" -msgstr "Sound card 3:" +msgid "Sound card #3:" +msgstr "Sound card #3:" -msgid "Sound card 4:" -msgstr "Sound card 4:" +msgid "Sound card #4:" +msgstr "Sound card #4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" diff --git a/src/qt/languages/en-US.po b/src/qt/languages/en-US.po index ce7ceb149..e3cfa3f77 100644 --- a/src/qt/languages/en-US.po +++ b/src/qt/languages/en-US.po @@ -352,6 +352,9 @@ msgstr "CPU type:" msgid "Speed:" msgstr "Speed:" +msgid "Frequency:" +msgstr "Frequency:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Video:" 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,17 +412,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" -msgstr "Sound card 1:" +msgid "Sound card #1:" +msgstr "Sound card #1:" -msgid "Sound card 2:" -msgstr "Sound card 2:" +msgid "Sound card #2:" +msgstr "Sound card #2:" -msgid "Sound card 3:" -msgstr "Sound card 3:" +msgid "Sound card #3:" +msgstr "Sound card #3:" -msgid "Sound card 4:" -msgstr "Sound card 4:" +msgid "Sound card #4:" +msgstr "Sound card #4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index d8d648691..c0f38893d 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -352,6 +352,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Velocidad:" +msgid "Frequency:" +msgstr "Frecuencia:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 217827f74..4998d008b 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -352,6 +352,9 @@ msgstr "Suorittimen tyyppi:" msgid "Speed:" msgstr "Nopeus:" +msgid "Frequency:" +msgstr "Taajuus:" + msgid "FPU:" msgstr "Apusuoritin:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index be66e5924..0c50b3e46 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -352,6 +352,9 @@ msgstr "Type du processeur:" msgid "Speed:" msgstr "Vitesse:" +msgid "Frequency:" +msgstr "Fréquence:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index b2aa40d28..436bae5c5 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -352,6 +352,9 @@ msgstr "Tip procesora:" msgid "Speed:" msgstr "Brzina:" +msgid "Frequency:" +msgstr "Frekvencija:" + msgid "FPU:" msgstr "FPU uređaj:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 352a64749..129df1e2b 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -352,6 +352,9 @@ msgstr "Processzor:" msgid "Speed:" msgstr "Seb.:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "FPU-egység:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index df71d148b..334ecadaa 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -352,6 +352,9 @@ msgstr "Tipo del CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequenza:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7ea47bc1a..32236adaa 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -352,6 +352,9 @@ msgstr "CPUタイプ:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻度:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index ac4476ca8..a8ff2723d 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -352,6 +352,9 @@ msgstr "CPU 종류:" msgid "Speed:" msgstr "속도:" +msgid "Frequency:" +msgstr "빈도:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index b24e338f4..a449d8951 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -352,6 +352,9 @@ msgstr "Rodzaj procesora:" msgid "Speed:" msgstr "Szybkość:" +msgid "Frequency:" +msgstr "Częstotliwość:" + msgid "FPU:" msgstr "Jednostka FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 0db661b4f..c06f24835 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -352,6 +352,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 8f080e423..9743bc83c 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -352,6 +352,9 @@ msgstr "Tipo do CPU:" msgid "Speed:" msgstr "Velocidade:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b0bcc0e1e..04f3bc5b3 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -31,6 +31,12 @@ msgstr "&Скрыть строку состояния" msgid "Hide &toolbar" msgstr "С&крыть панель инструментов" +msgid "Show status icons in fullscreen" +msgstr "Показывать значки состояния в полноэкранном режиме" + +msgid "Show non-primary monitors" +msgstr "&Показывать неосновные мониторы" + msgid "&Resizeable window" msgstr "&Изменяемый размер окна" @@ -55,8 +61,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 +157,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 +226,9 @@ msgstr "Включить интеграцию &Discord" msgid "Sound &gain..." msgstr "&Усиление звука..." +msgid "Open screenshots folder..." +msgstr "Открыть папку скриншотов..." + msgid "Begin trace\tCtrl+T" msgstr "Начать трассировку\tCtrl+T" @@ -232,6 +268,9 @@ msgstr "&Перемотка в конец" msgid "E&ject" msgstr "И&звлечь" +msgid "Eject %s" +msgstr "Извлечь %s" + msgid "&Image..." msgstr "&Образ..." @@ -241,6 +280,9 @@ msgstr "Э&кспорт в 86F..." msgid "&Mute" msgstr "О&тключить звук" +msgid "&Unmute" +msgstr "В&ключить звук" + msgid "E&mpty" msgstr "П&устой" @@ -352,6 +394,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Скорость:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -368,25 +413,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 +457,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 +488,7 @@ msgid "Nuked (more accurate)" msgstr "Nuked (более точный)" msgid "YMFM (faster)" -msgstr "YMFM (быстрей)" +msgstr "YMFM (быстрее)" msgid "Network type:" msgstr "Тип сети:" @@ -451,6 +499,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 +548,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 +622,14 @@ msgstr "&Создать..." msgid "&Existing..." msgstr "&Выбрать..." +msgid "Browse..." +msgstr "Выбрать..." + msgid "&Remove" -msgstr "&Убрать" +msgstr "&Удалить" + +msgid "Remove" +msgstr "Удалить" msgid "Bus:" msgstr "Шина:" @@ -554,7 +644,7 @@ msgid "&Specify..." msgstr "&Указать..." msgid "Sectors:" -msgstr "Сектора:" +msgstr "Секторы:" msgid "Heads:" msgstr "Головки:" @@ -602,7 +692,7 @@ msgid "ISA RTC:" msgstr "ISA RTC:" msgid "ISA Memory Expansion" -msgstr "Карта расширения памяти (ISA)" +msgstr "Карта расширения памяти ISA" msgid "Card 1:" msgstr "Карта 1:" @@ -622,6 +712,9 @@ msgstr "Устройство ISABugger" msgid "POST card" msgstr "Карта POST" +msgid "86Box Unit Tester" +msgstr "Модульный Тестер 86Box" + msgid "FONT_SIZE" msgstr "9" @@ -658,6 +751,9 @@ msgstr "86Box не смог найти ни одного подходящего msgid "(empty)" msgstr "(пусто)" +msgid "Clear image history" +msgstr "Очистить историю образов" + msgid "All files" msgstr "Все файлы" @@ -713,7 +809,7 @@ msgid "Floppy & CD-ROM drives" msgstr "Гибкие диски и CD-ROM" msgid "Other removable devices" -msgstr "Другие съёмные устр-ва" +msgstr "Другие съёмные устройства" msgid "Other peripherals" msgstr "Другая периферия" @@ -785,7 +881,7 @@ msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" -msgstr "Система управления полетом Thrustmaster" +msgstr "Система управления полётом Thrustmaster" msgid "None" msgstr "Нет" @@ -845,7 +941,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 +950,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." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index a8f60b861..c2f129a3d 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -352,6 +352,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rýchlosť:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 98a51d863..8c1d62ded 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -352,6 +352,9 @@ msgstr "Vrsta procesorja:" msgid "Speed:" msgstr "Hitrost:" +msgid "Frequency:" +msgstr "Pogostost:" + msgid "FPU:" msgstr "Procesor plavajoče vejice:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 0d6875eb8..65a039c42 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -352,6 +352,9 @@ msgstr "CPU türü:" msgid "Speed:" msgstr "Hız:" +msgid "Frequency:" +msgstr "Sıklık:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 6f8ecac52..0d8522f15 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -352,6 +352,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Швидкість:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,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 +412,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:" @@ -854,7 +857,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." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 3d045b74e..0ac54f4e7 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -352,6 +352,9 @@ msgstr "CPU 类型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "频率:" + msgid "FPU:" msgstr "浮点处理器 (FPU):" @@ -385,8 +388,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 +412,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:" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 2d2ea473e..cf53b3488 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -352,6 +352,9 @@ msgstr "CPU 類型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻率:" + msgid "FPU:" msgstr "浮點處理器 (FPU):" @@ -368,7 +371,7 @@ msgid "Time synchronization" msgstr "時間同步" msgid "Disabled" -msgstr "禁用" +msgstr "停用" msgid "Enabled (local time)" msgstr "啟用 (本地時間)" @@ -385,8 +388,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 +412,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:" @@ -917,7 +920,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 "繼續" diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index 8523a258d..c363cd544 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -186,7 +186,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 +195,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_main.cpp b/src/qt/qt_main.cpp index 845ff705f..4d02e2601 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -94,6 +94,7 @@ main_thread_fn() int frames; QThread::currentThread()->setPriority(QThread::HighestPriority); + plat_set_thread_name(NULL, "main_thread_fn"); framecountx = 0; // title_update = 1; old_time = elapsed_timer.elapsed(); @@ -194,6 +195,23 @@ main(int argc, char *argv[]) QApplication::setFont(QFont(font_name, font_size.toInt())); SetCurrentProcessExplicitAppUserModelID(L"86Box.86Box"); #endif + +#ifndef Q_OS_MACOS +# ifdef RELEASE_BUILD + app.setWindowIcon(QIcon(":/settings/win/icons/86Box-green.ico")); +# elif defined ALPHA_BUILD + app.setWindowIcon(QIcon(":/settings/win/icons/86Box-red.ico")); +# elif defined BETA_BUILD + app.setWindowIcon(QIcon(":/settings/win/icons/86Box-yellow.ico")); +# else + app.setWindowIcon(QIcon(":/settings/win/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); return 6; @@ -293,8 +311,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,6 +339,14 @@ 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 != 6) + plat_pause(1); + else +#endif + plat_pause(0); }); auto ret = app.exec(); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index f3503caeb..eb4634dee 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -196,15 +196,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); @@ -817,6 +808,14 @@ MainWindow::initRendererMonitorSlot(int monitor_index) } 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(); + } } } } @@ -1388,12 +1387,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); } } diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index d682815bb..c14c33207 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -773,10 +773,10 @@ :/menuicons/win/icons/acpi_shutdown.ico:/menuicons/win/icons/acpi_shutdown.ico - ACPI Shutdown + ACPI shutdown - ACPI Shutdown + ACPI shutdown true diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 26169b0d0..541e31190 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -456,6 +456,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) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index f306b6138..6890bd407 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 @@ -371,7 +372,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()); @@ -742,3 +743,48 @@ plat_get_dpi(void) { return util::screenOfWidget(main_window)->devicePixelRatio(); } + +void +plat_set_thread_name(void *thread, const char *name) +{ +#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_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 983f14d26..05c35e09b 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -88,7 +88,7 @@ RendererCommon::onResize(int width, int height) if (video_fullscreen_scale == FULLSCR_SCALE_INT43) { gh = gw / r43; - gw = gw; +// gw = gw; gsr = r43; } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 1b1ed45c3..e5ed77ba7 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -144,7 +144,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)) { diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index dfda43c40..5dd76287f 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -42,7 +42,7 @@ - XGA + XGA Graphics @@ -95,7 +95,7 @@ - 8514/A + IBM 8514/A Graphics diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 66d6e3de0..34d111e10 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -190,9 +190,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.ui b/src/qt/qt_settingsmachine.ui index 22ecc15df..54bc06f5c 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -100,7 +100,7 @@ - PIT Mode: + PIT mode: @@ -158,7 +158,7 @@ - Speed: + Frequency: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index d168138a5..f662b644c 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -23,6 +23,7 @@ extern "C" { #include <86box/machine.h> #include <86box/isamem.h> #include <86box/isartc.h> +#include <86box/unittester.h> } #include "qt_deviceconfig.hpp" @@ -44,7 +45,9 @@ 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->checkBoxISABugger->setEnabled(machineHasIsa); + ui->pushButtonConfigureUT->setEnabled(unittester_enabled > 0); ui->comboBoxRTC->setEnabled(machineHasIsa); ui->pushButtonConfigureRTC->setEnabled(machineHasIsa); @@ -112,9 +115,10 @@ 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; + isartc_type = ui->comboBoxRTC->currentData().toInt(); /* ISA memory boards. */ for (int i = 0; i < ISAMEM_MAX; i++) { @@ -197,3 +201,15 @@ 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); +} diff --git a/src/qt/qt_settingsotherperipherals.hpp b/src/qt/qt_settingsotherperipherals.hpp index 97e47c90e..feaa7a001 100644 --- a/src/qt/qt_settingsotherperipherals.hpp +++ b/src/qt/qt_settingsotherperipherals.hpp @@ -30,6 +30,8 @@ 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(); private: Ui::SettingsOtherPeripherals *ui; diff --git a/src/qt/qt_settingsotherperipherals.ui b/src/qt/qt_settingsotherperipherals.ui index 01f5545f8..af953a984 100644 --- a/src/qt/qt_settingsotherperipherals.ui +++ b/src/qt/qt_settingsotherperipherals.ui @@ -192,6 +192,30 @@ + + + + + + 86Box Unit Tester + + + + 0 + 0 + + + + + + + + Configure + + + + + 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/scsi/scsi.c b/src/scsi/scsi.c index 238fa7cb3..94c9048ef 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -85,7 +85,7 @@ static SCSI_CARD scsi_cards[] = { { &scsi_t130b_device, }, { &aha1640_device, }, { &buslogic_640a_device, }, - { &ncr53c90_mca_device, }, + { &ncr53c90a_mca_device, }, { &spock_device, }, { &tribble_device, }, { &buslogic_958d_pci_device, }, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index fb52ca898..f52401785 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: @@ -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; } @@ -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; @@ -3608,6 +3613,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 93d29a672..39a69ea32 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; @@ -709,7 +709,7 @@ static int scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int out) { *len = 0; - uint32_t medium_size = hdd_image_get_last_sector(dev->id); + uint32_t medium_size = hdd_image_get_last_sector(dev->id) + 1; if (!dev->sector_len) { scsi_disk_command_complete(dev); @@ -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 @@ -1371,6 +1381,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..e9ebe8504 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -185,7 +185,7 @@ typedef struct ncr5380_t { #define DMA_SEND 1 #define DMA_INITIATOR_RECEIVE 2 -static int cmd_len[8] = { 6, 10, 10, 6, 16, 12, 6, 6 }; +static int cmd_len[8] = { 6, 10, 10, 6, 16, 12, 10, 6 }; #ifdef ENABLE_NCR5380_LOG int ncr5380_do_log = ENABLE_NCR5380_LOG; @@ -207,12 +207,6 @@ ncr_log(const char *fmt, ...) #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); @@ -256,7 +250,7 @@ static void ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) { memset(ncr, 0x00, sizeof(ncr_t)); - ncr_log("NCR reset\n"); + ncr_log("NCR Reset\n"); timer_stop(&ncr_dev->timer); @@ -266,27 +260,6 @@ ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) ncr_irq(ncr_dev, 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) { @@ -477,13 +450,8 @@ ncr_bus_update(void *priv, int bus) /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { p = scsi_device_get_callback(dev); - if (p <= 0.0) { - ncr_dev->period = 0.2; - } else { - ncr_dev->period = p / ((double) dev->buffer_length); - } - ncr->data_wait |= 2; - ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length); + ncr_dev->period = (p > 0.0) ? p : (((double) dev->buffer_length) * 0.2); + ncr_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_dev->period, dev->buffer_length, ncr->dma_mode); } } ncr->new_phase = dev->phase; @@ -502,14 +470,15 @@ 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 + } else { + ncr_log("DMA mode IN.\n"); ncr->clear_req = 3; + } + ncr->cur_bus &= ~BUS_REQ; ncr->new_phase = SCSI_PHASE_DATA_IN; } @@ -532,9 +501,9 @@ ncr_bus_update(void *priv, int bus) ncr->data_wait |= 1; ncr_log("DMA mode idle out\n"); timer_on_auto(&ncr_dev->timer, ncr_dev->period); - } else { + } else ncr->clear_req = 3; - } + ncr->cur_bus &= ~BUS_REQ; ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); } @@ -594,7 +563,7 @@ ncr_write(uint16_t port, 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]; + 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); @@ -627,7 +596,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*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); + timer_on_auto(&ncr_dev->timer, ncr_dev->period + 1.0); } /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ @@ -638,13 +607,6 @@ ncr_write(uint16_t port, uint8_t val, void *priv) 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"); @@ -669,22 +631,16 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*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) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (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_dev->t128.host_pos = 0; + ncr_dev->t128.block_count = dev->buffer_length >> 9; - ncr_log("DMA send timer on\n"); - ncr_timer_on(ncr_dev, ncr, 0); + if (dev->buffer_length < 512) + ncr_dev->t128.block_count = 1; + + ncr_dev->t128.block_loaded = 1; } } break; @@ -694,29 +650,18 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*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) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (dev->buffer_length > 0)) { memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - + ncr_dev->t128.status |= 0x04; + ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); ncr_dev->t128.block_count = dev->buffer_length >> 9; if (dev->buffer_length < 512) ncr_dev->t128.block_count = 1; ncr_dev->t128.block_loaded = 1; - - ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); - ncr_dev->t128.status |= 0x04; timer_on_auto(&ncr_dev->timer, 0.02); } - } else { - if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { - memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); - - ncr_log("DMA receive timer start\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } } break; @@ -725,10 +670,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv) 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 = get_bus_host(ncr); + ncr_bus_update(priv, bus_host); } static uint8_t @@ -853,7 +796,7 @@ 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]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; uint8_t ret = 0xff; addr &= 0x3fff; @@ -881,10 +824,12 @@ memio_read(uint32_t addr, void *priv) break; case 0x3900: - if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || (!(ncr_dev->status_ctrl & CTRL_DATA_DIR))) { ret = 0xff; + ncr_log("No Read.\n"); } else { ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + ncr_log("Read host pos = %i, ret = %02x\n", ncr_dev->buffer_host_pos, ret); if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -914,11 +859,9 @@ memio_read(uint32_t addr, void *priv) break; case 0x3982: /* switch register read */ - ret = 0xff; - break; - - case 0x3983: - ret = 0xff; + ret = 0xf8; + ret |= (ncr_dev->irq & 0x07); + ncr_log("Switches read=%02x.\n", ret); break; default: @@ -944,7 +887,7 @@ 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]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; addr &= 0x3fff; @@ -988,13 +931,10 @@ memio_write(uint32_t addr, uint8_t val, void *priv) 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_log("Write block counter register: val=%d, dma mode=%x, 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; @@ -1002,6 +942,11 @@ memio_write(uint32_t addr, uint8_t val, void *priv) ncr_dev->buffer_host_pos = 0; ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; } + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (dev->buffer_length > 0)) { + memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); + ncr_log("DMA timer on\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); + } break; default: @@ -1117,191 +1062,43 @@ t130b_out(uint16_t port, uint8_t val, void *priv) } } -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]; + int bus; + int bytes_tx = 0; + int limit = 100; + uint8_t temp; - 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); - } + if (ncr_dev->type != 3) { + if (ncr->dma_mode != DMA_IDLE) + timer_on_auto(&ncr_dev->timer, 1.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->dma_mode != DMA_IDLE) && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) { + if ((ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) && ncr_dev->t128.block_count) + ncr_dev->t128.status |= 0x04; + + timer_on_auto(&ncr_dev->timer, ncr_dev->period / 55.0); } } if (ncr->data_wait & 1) { ncr->clear_req = 3; ncr->data_wait &= ~1; - if (ncr->dma_mode == DMA_IDLE) { - return; + if (ncr_dev->type == 3) { + if (ncr->dma_mode == DMA_IDLE) + return; } } + if (ncr_dev->type != 3) { + if (ncr->dma_mode == DMA_IDLE) + return; + } + switch (ncr->dma_mode) { case DMA_SEND: if (ncr_dev->type != 3) { @@ -1317,9 +1114,52 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; + + while (bytes_tx < limit) { + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + temp = ncr_dev->buffer[ncr_dev->buffer_pos]; + + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->buffer_pos++; + bytes_tx++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); + + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + bytes_tx = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + 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); + } + } + break; + } + } } else { if (!(ncr_dev->t128.status & 0x04)) { - ncr_log("Write status busy\n"); + ncr_log("Write status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos); break; } @@ -1330,8 +1170,48 @@ ncr_callback(void *priv) if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) break; + +write_again: + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + temp = ncr_dev->t128.buffer[ncr_dev->t128.pos]; + + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->t128.pos++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->t128.pos); + + if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.pos = 0; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status &= ~0x02; + ncr_dev->ncr_busy = 0; + 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); + } + } + break; + } else + goto write_again; } - ncr_dma_send(ncr_dev, ncr, dev); break; case DMA_INITIATOR_RECEIVE: @@ -1348,6 +1228,47 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; + + while (bytes_tx < limit) { + 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); + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); + bytes_tx++; + + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + bytes_tx = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + 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); + } + } + 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); @@ -1361,8 +1282,46 @@ ncr_callback(void *priv) if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) break; + +read_again: + 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); + + ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp; + ncr_log("Buffer pos for reading=%d, temp=%02x, len=%d.\n", ncr_dev->t128.pos, temp, dev->buffer_length); + + 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); + } + } + break; + } else + goto read_again; } - ncr_dma_initiator_receive(ncr_dev, ncr, dev); break; default: @@ -1375,7 +1334,8 @@ ncr_callback(void *priv) ncr_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; ncr->dma_mode = DMA_IDLE; - timer_on_auto(&ncr_dev->timer, 10.0); + if (ncr_dev->type == 3) + timer_on_auto(&ncr_dev->timer, 10.0); } } @@ -1392,12 +1352,12 @@ t128_read(uint32_t addr, void *priv) 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)) + else if ((addr >= 0x1c00) && (addr < 0x1c20)) { ret = ncr_dev->t128.ctrl; - else if ((addr >= 0x1c20) && (addr < 0x1c40)) { + ncr_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + } 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); + ncr_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ret = ncr_read((addr - 0x1d00) >> 5, ncr_dev); else if (addr >= 0x1e00 && addr < 0x2000) { @@ -1414,7 +1374,7 @@ t128_read(uint32_t addr, void *priv) 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) + 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)) @@ -1436,12 +1396,11 @@ t128_write(uint32_t addr, uint8_t val, void *priv) 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)) { + 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); + 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)) { @@ -1455,11 +1414,11 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { ncr_dev->t128.status &= ~0x04; + ncr_dev->ncr_busy = 1; 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); + } } } @@ -1645,14 +1604,12 @@ ncr_init(const device_t *info) 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; + 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; - + ncr_dev->t128.status = 0x04; + ncr_dev->t128.host_pos = 512; if (!ncr_dev->t128.bios_enabled) ncr_dev->t128.status |= 0x80; } 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/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..22b88615d 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", + .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_it86x1f.c b/src/sio/sio_it86x1f.c index d53e78050..74e79bbed 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 @@ -805,10 +806,18 @@ it86x1f_init(UNUSED(const device_t *info)) break; } if (i >= (sizeof(it86x1f_models) / sizeof(it86x1f_models[0]))) { +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + fatal("IT86x1F: Unknown type %04" PRIX64 " selected\n", info->local); +#else fatal("IT86x1F: Unknown type %04X selected\n", info->local); +#endif return NULL; } +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + it86x1f_log("IT86x1F: init(%04" PRIX64 ")\n", info->local); +#else it86x1f_log("IT86x1F: init(%04X)\n", info->local); +#endif /* 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_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/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index e4131f1fe..d8281ba1d 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1581,17 +1581,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 +1603,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_sb.c b/src/sound/snd_sb.c index 602c1c2a7..3aa152b8f 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -796,7 +796,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 +982,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); @@ -2141,6 +2143,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; } @@ -2352,6 +2355,7 @@ sb_16_compat_init(const device_t *info) sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); return sb; } @@ -2455,6 +2459,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; } 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/unix/unix.c b/src/unix/unix.c index ecd17cadb..4f21ddd53 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; @@ -644,10 +647,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 + header = (void *) ((flags & MBX_ANSI) ? "86Box" : L"86Box"); if (header <= (void *) 7168) header = (void *) plat_get_string((uintptr_t) header); if (message <= (void *) 7168) @@ -762,10 +763,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 +820,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 +834,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 +918,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 +1168,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 +1208,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. */ @@ -1371,6 +1382,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_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..638837757 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -25,14 +25,9 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.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_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) -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() diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 314fee307..3505d1e0b 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) + 1; + } + } 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && 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 >= 2) && dev->accel.ge_offset && (dev->accel_bpp == 24)) - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - else - dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.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 >= 2) && 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); @@ -3685,7 +3697,7 @@ bitblt: } } } else { - if ((dev->accel_bpp == 24) && (dev->local >= 2) && (dev->accel.cmd == 0xc2b5)) { + if ((dev->accel_bpp == 24) && ((dev->local & 0xff) >= 0x02) && (dev->accel.cmd == 0xc2b5)) { int64_t cx; int64_t dx; @@ -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, 0); 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..b54f6b89e 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -35,8 +35,8 @@ #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_VGA88 "roms/video/ati18800/vga88.bin" +#define BIOS_ROM_PATH_EDGE16 "roms/video/ati18800/vgaedge16.vbi" enum { #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) @@ -57,6 +57,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 +78,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 +175,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,6 +253,8 @@ 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) @@ -207,30 +264,27 @@ ati18800_init(const device_t *info) #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); @@ -300,7 +354,7 @@ const device_t ati18800_wonder_device = { #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 +368,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..be9654aca 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] + 1; + + 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,12 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; + svga->hblank_end_val >>= 1; svga->rowoffset <<= 1; svga->ma_latch <<= 1; } break; - default: break; } @@ -586,6 +567,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 +635,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..cdd906067 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) + 1; + 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 90e41d9ba..5628e149a 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,151 +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]; - int ati_mode[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 }; @@ -196,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; @@ -250,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); \ } \ @@ -412,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; @@ -459,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) { @@ -567,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); @@ -578,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); - } } } } @@ -778,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); @@ -789,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); - } } } } @@ -927,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; @@ -944,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; @@ -1045,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)) { @@ -1173,7 +1051,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 3: - READ(dev->accel.src + ((dev->accel.cx)), mix); + READ(dev->accel.src + dev->accel.cx, mix); mix = (mix & rd_mask) == rd_mask; break; @@ -1182,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; @@ -1204,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; } @@ -1222,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); } } } @@ -1287,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) { @@ -1296,6 +1174,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.cx += mach->accel.src_width; else dev->accel.cx -= mach->accel.src_width; + dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); if (dev->bpp) dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); @@ -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 >= 2)) + 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: @@ -2325,7 +2228,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); break; case 0xad: - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if ((old ^ val) & 0x0c) svga_recalctimings(svga); } @@ -2341,7 +2244,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) if (mach->regs[0xbe] & 0x08) { /* Read/write bank mode */ mach->bank_r = (((mach->regs[0xb2] & 1) << 3) | ((mach->regs[0xb2] & 0xe0) >> 5)); mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } @@ -2349,7 +2252,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } else { /* Single bank mode */ mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } mach->bank_r = mach->bank_w; @@ -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: @@ -2377,7 +2280,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); break; case 0xb8: - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if ((old ^ val) & 0x40) svga_recalctimings(svga); } else { @@ -2401,7 +2304,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus && !mach->ramdac_type) ati68860_ramdac_out((addr & 3) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); else @@ -2416,7 +2319,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x3C9: rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus && !mach->ramdac_type) ati68860_ramdac_out((addr & 3) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); else @@ -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; - if (dev->local >= 2) { /*Mach32 VGA 1MB memory*/ + 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; @@ -2514,7 +2419,7 @@ mach_in(uint16_t addr, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus && !mach->ramdac_type) temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); else @@ -2529,7 +2434,7 @@ mach_in(uint16_t addr, void *priv) case 0x3C9: rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus && !mach->ramdac_type) temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); else @@ -2555,16 +2460,98 @@ 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] + 1; + clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->regs[0xad] & 0x04) svga->ma_latch |= 0x40000; @@ -2578,57 +2565,66 @@ 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; } - if (mach->regs[0xb0] & 0x20) + if (mach->regs[0xb0] & 0x20) { svga->gdcreg[5] |= 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 >= 2) { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->dispend = ((dev->vdisp >> 1) + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); + 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 == 766) - dev->dispend += 2; + if (dev->dispend == 766) + dev->dispend += 2; - if (dev->dispend == 598) - 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->dispend == 478) + 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; - } - 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); + 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 (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; - } - if (mach->shadow_set & 1) { - mach_log("Shadow set 1.\n"); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + if ((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) { @@ -2656,7 +2652,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; @@ -2668,16 +2664,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: @@ -2686,53 +2684,38 @@ 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 ^ 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 (((mach->shadow_set & 0x03) != 0x02) || !(dev->accel.advfunc_cntl & 0x04)) { /*Shadow set of 2 and bit 2 of port 0x4ae8 mean 1024x768+*/ + if (!(mach->accel.clock_sel & 0x01)) { + dev->h_disp = 640; + dev->dispend = 480; + } } - if (mach->shadow_set & 1) { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } + if (dev->interlace) { dev->dispend >>= 1; dev->v_syncstart >>= 2; @@ -2741,13 +2724,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; } } @@ -2776,15 +2760,17 @@ mach_recalctimings(svga_t *svga) 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; - svga->ma_latch <<= 1; - svga->rowoffset <<= 1; + if (!svga->packed_4bpp) { + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; + } } break; - } break; @@ -2802,29 +2788,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: @@ -2839,6 +2826,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; @@ -2859,6 +2847,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; @@ -2879,7 +2868,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 { @@ -2904,6 +2892,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: @@ -2922,7 +2911,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) @@ -3170,8 +3159,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: @@ -3183,8 +3174,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: @@ -3222,24 +3215,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; @@ -3252,17 +3243,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; @@ -3322,7 +3311,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; @@ -3350,6 +3339,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: @@ -3382,7 +3381,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 { @@ -3449,7 +3447,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 { @@ -3480,6 +3477,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; @@ -3585,8 +3584,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]; @@ -3609,91 +3607,133 @@ 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); - 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); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } } - svga_recalctimings(svga); + mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc=%x, dispcntl=%02x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 4, dev->disp_cntl & 0x60); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07) + 1; + } + } mach_log("ATI 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)) || (mach->accel.clock_sel & 0x01)) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; + } + } mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0x12e8: case 0x12e9: - WRITE8(port, dev->vtotal, val); - dev->vtotal &= 0x1fff; - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->vtotal = dev->v_total_reg; + dev->vtotal++; + } break; case 0x16e8: case 0x16e9: - WRITE8(port, dev->vdisp, val); - dev->vdisp &= 0x1fff; - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; + } + 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->vdisp); break; case 0x1ae8: case 0x1ae9: - WRITE8(port, dev->vsyncstart, val); - dev->vsyncstart &= 0x1fff; - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->vsyncstart = dev->v_sync_start; + dev->vsyncstart++; + } 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 22E8 = %02x, interlace = %d\n", 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("%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); - mach->ati_mode[port & 1] = 0; + mach32_updatemapping(mach, svga); + dev->vendor_mode[port & 1] = 0; + mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; @@ -3714,7 +3754,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: @@ -3754,7 +3795,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; @@ -3770,13 +3811,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); svga_recalctimings(svga); break; case 0x32ee: case 0x32ef: WRITE8(port, mach->local_cntl, val); - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x36ee: @@ -3802,21 +3844,24 @@ 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; + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->shadow_cntl, 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->ext_on[port & 1] = dev->on[port & 1]; vga_on = !dev->on[port & 1]; - mach->ati_mode[port & 1] = 1; + dev->vendor_mode[port & 1] = 1; svga_recalctimings(svga); break; @@ -3824,23 +3869,20 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x52ef: 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); WRITE8(port, mach->accel.scratch1, val); - mach->ext_on[port & 1] = 1; break; case 0x5aee: case 0x5aef: - WRITE8(port, mach->shadow_set, val); - if (port & 1) - mach_log("Shadow set = %02x.\n", mach->shadow_set & 0x03); - - svga_recalctimings(svga); + if (!(mach->shadow_cntl & 0x3f)) { + WRITE8(port, mach->shadow_set, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + } break; case 0x5eee: @@ -3850,7 +3892,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: @@ -3882,13 +3924,14 @@ 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, extpitch = %d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; case 0x7aee: case 0x7aef: WRITE8(port, mach->accel.ext_ge_config, val); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->accel.crt_pitch & 0xff) dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; switch (mach->accel.ext_ge_config & 0x30) { @@ -3912,18 +3955,21 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) break; } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); - mach->ati_mode[port & 1] = 1; - mach32_updatemapping(mach); + dev->vendor_mode[port & 1] = 1; + 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); } - svga_recalctimings(svga); break; case 0x7eee: case 0x7eef: WRITE8(port, mach->accel.eeprom_control, val); - ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 4, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); - mach_log("[%04X]: 7EEE+%d VGA ON = %d, Ext = %i, val = %04x, pagesel = %04x.\n", CS, port & 1, vga_on, ibm8514_on, mach->accel.eeprom_control & 0x10ff, (mach->accel.eeprom_control & 0xf0) << 7); - svga_recalctimings(svga); + 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); break; default: @@ -3931,6 +3977,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) { @@ -3944,28 +4000,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: @@ -4154,6 +4206,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; @@ -4183,9 +4240,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; @@ -4199,9 +4256,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) @@ -4210,17 +4266,23 @@ 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); } 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: @@ -4238,26 +4300,26 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in 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: @@ -4274,7 +4336,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xdaee: if (len != 1) { temp = mach->accel.src_x; - if (dev->local >= 2) + if ((dev->local & 0xff) >= 0x02) temp &= 0x7ff; } else temp = mach->accel.src_x & 0xff; @@ -4287,7 +4349,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xdeee: if (len != 1) { temp = mach->accel.src_y; - if (dev->local >= 2) + if ((dev->local & 0xff) >= 0x02) temp &= 0x7ff; } else temp = mach->accel.src_y & 0xff; @@ -4323,34 +4385,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: @@ -4374,26 +4435,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*/ @@ -4408,9 +4466,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: @@ -4423,10 +4480,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; @@ -4438,23 +4493,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: @@ -4465,6 +4518,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: @@ -4487,6 +4557,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; @@ -4500,31 +4571,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) { @@ -4567,6 +4693,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) { @@ -4617,10 +4809,47 @@ mach_accel_inl(uint16_t port, void *priv) return temp; } -static void -mach32_write_linear(uint32_t addr, uint8_t val, void *priv) +static uint32_t +mach32_decode_addr(svga_t *svga, uint32_t addr, int write) { - svga_t *svga = (svga_t *) priv; + int memory_map_mode = (svga->gdcreg[6] >> 2) & 3; + + addr &= 0x1ffff; + + switch (memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xffffffff; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xffffffff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xffffffff; + break; + } + + if (memory_map_mode <= 1) { + if (write) + addr = (addr & svga->banked_mask) + svga->write_bank; + else + addr = (addr & svga->banked_mask) + svga->read_bank; + } + + return addr; +} + +static __inline void +mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach) +{ + svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int writemask2 = svga->writemask; int reset_wm = 0; @@ -4631,14 +4860,24 @@ mach32_write_linear(uint32_t addr, uint8_t val, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; + if (!linear) { + addr = mach32_decode_addr(svga, addr, 1); + if (addr == 0xffffffff) + return; + } + 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; } else if (svga->chain4 && (svga->writemode < 4)) { writemask2 = 1 << (addr & 3); + if (!linear) + addr &= ~3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); } else if (svga->chain2_write) { writemask2 &= ~0xa; @@ -4750,40 +4989,31 @@ static void mach32_write(uint32_t addr, uint8_t val, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - - addr = (addr & svga->banked_mask) + svga->write_bank; - mach32_write_linear(addr, val, svga); + mach32_write_common(addr, val, 0, mach); } static void mach32_writew(uint32_t addr, uint16_t val, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - - addr = (addr & svga->banked_mask) + svga->write_bank; - mach32_write_linear(addr, val & 0xff, svga); - mach32_write_linear(addr + 1, val >> 8, svga); + mach32_write_common(addr, val & 0xff, 0, mach); + mach32_write_common(addr + 1, val >> 8, 0, mach); } static void mach32_writel(uint32_t addr, uint32_t val, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - - addr = (addr & svga->banked_mask) + svga->write_bank; - mach32_write_linear(addr, val & 0xff, svga); - mach32_write_linear(addr + 1, val >> 8, svga); - mach32_write_linear(addr + 2, val >> 16, svga); - mach32_write_linear(addr + 3, val >> 24, svga); + mach32_write_common(addr, val & 0xff, 0, mach); + mach32_write_common(addr + 1, val >> 8, 0, mach); + mach32_write_common(addr + 2, val >> 16, 0, mach); + mach32_write_common(addr + 3, val >> 24, 0, mach); } -static uint8_t -mach32_read_linear(uint32_t addr, void *priv) +static __inline uint8_t +mach32_read_common(uint32_t addr, int linear, mach_t *mach) { - svga_t *svga = (svga_t *) priv; + svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t latch_addr = 0; int readplane = svga->readplane; @@ -4793,11 +5023,18 @@ mach32_read_linear(uint32_t addr, void *priv) cycles -= svga->monitor->mon_video_timing_read_b; + if (!linear) { + addr = mach32_decode_addr(svga, addr, 0); + if (addr == 0xffffffff) + return 0xff; + } + count = 2; 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) @@ -4865,11 +5102,9 @@ static uint8_t mach32_read(uint32_t addr, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; uint8_t ret; - addr = (addr & svga->banked_mask) + svga->read_bank; - ret = mach32_read_linear(addr, svga); + ret = mach32_read_common(addr, 0, mach); return ret; } @@ -4877,12 +5112,10 @@ static uint16_t mach32_readw(uint32_t addr, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; uint16_t ret; - addr = (addr & svga->banked_mask) + svga->read_bank; - ret = mach32_read_linear(addr, svga); - ret |= (mach32_read_linear(addr + 1, svga) << 8); + ret = mach32_read_common(addr, 0, mach); + ret |= (mach32_read_common(addr + 1, 0, mach) << 8); return ret; } @@ -4890,23 +5123,22 @@ static uint32_t mach32_readl(uint32_t addr, void *priv) { mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; uint32_t ret; - addr = (addr & svga->banked_mask) + svga->read_bank; - ret = mach32_read_linear(addr, svga); - ret |= (mach32_read_linear(addr + 1, svga) << 8); - ret |= (mach32_read_linear(addr + 2, svga) << 16); - ret |= (mach32_read_linear(addr + 3, svga) << 24); + ret = mach32_read_common(addr, 0, mach); + ret |= (mach32_read_common(addr + 1, 0, mach) << 8); + ret |= (mach32_read_common(addr + 2, 0, mach) << 16); + ret |= (mach32_read_common(addr + 3, 0, mach) << 24); return ret; } static void mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - uint8_t port_dword = addr & 0xfc; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { @@ -4918,17 +5150,21 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_accel_outb(0x02e8 + (addr & 1) + (port_dword << 8), val, mach); } } else { - mach_log("Linear WORDB Write=%08x.\n", addr); - mach32_write_linear(addr, val, svga); + mach_log("Linear WORDB Write=%08x, val=%02x.\n", addr, val); + if (dev->on[0] || dev->on[1]) + mach32_write_common(addr, val, 1, mach); + else + svga_write_linear(addr, val, svga); } } static void mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - uint8_t port_dword = addr & 0xfc; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { @@ -4940,18 +5176,22 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8), val, mach); } } else { - mach_log("Linear WORDW Write=%08x.\n", addr); - mach32_write_linear(addr, val & 0xff, svga); - mach32_write_linear(addr + 1, val >> 8, svga); + mach_log("Linear WORDW Write=%08x, val=%04x.\n", addr, val); + if (dev->on[0] || dev->on[1]) { + mach32_write_common(addr, val & 0xff, 1, mach); + mach32_write_common(addr + 1, val >> 8, 1, mach); + } else + svga_writew_linear(addr, val, svga); } } static void mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; - uint8_t port_dword = addr & 0xfc; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { @@ -4965,31 +5205,40 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); } } else { - mach_log("Linear WORDL Write=%08x.\n", addr); - mach32_write_linear(addr, val & 0xff, svga); - mach32_write_linear(addr + 1, val >> 8, svga); - mach32_write_linear(addr + 2, val >> 16, svga); - mach32_write_linear(addr + 3, val >> 24, svga); + mach_log("Linear WORDL Write=%08x, val=%08x.\n", addr, val); + if (dev->on[0] || dev->on[1]) { + mach32_write_common(addr, val & 0xff, 1, mach); + mach32_write_common(addr + 1, val >> 8, 1, mach); + mach32_write_common(addr + 2, val >> 16, 1, mach); + mach32_write_common(addr + 3, val >> 24, 1, mach); + } else + svga_writel_linear(addr, val, svga); } } static uint8_t mach32_ap_readb(uint32_t addr, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + if (addr & 0x100) temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); - } else { + else temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); - } - } else - temp = mach32_read_linear(addr, svga); + } else { + if (dev->on[0] || dev->on[1]) + temp = mach32_read_common(addr, 1, mach); + else + temp = svga_read_linear(addr, svga); + + mach_log("Linear WORDB Read=%08x, ret=%02x, fast=%d.\n", addr, temp, svga->fast); + } return temp; } @@ -4997,21 +5246,26 @@ mach32_ap_readb(uint32_t addr, void *priv) static uint16_t mach32_ap_readw(uint32_t addr, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint16_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + if (addr & 0x100) temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); - } else { + else temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); - } } else { - temp = mach32_read_linear(addr, svga); - temp |= (mach32_read_linear(addr + 1, svga) << 8); + if (dev->on[0] || dev->on[1]) { + temp = mach32_read_common(addr, 1, mach); + temp |= (mach32_read_common(addr + 1, 1, mach) << 8); + } else + temp = svga_readw_linear(addr, svga); + + mach_log("Linear WORDW Read=%08x, ret=%04x.\n", addr, temp); } return temp; @@ -5020,10 +5274,11 @@ mach32_ap_readw(uint32_t addr, void *priv) static uint32_t mach32_ap_readl(uint32_t addr, void *priv) { - mach_t *mach = (mach_t *) priv; - svga_t *svga = &mach->svga; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = addr & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { @@ -5035,19 +5290,23 @@ mach32_ap_readl(uint32_t addr, void *priv) temp |= (mach_accel_inw(0x02e8 + (port_dword << 8) + 4, mach) << 8); } } else { - temp = mach32_read_linear(addr, svga); - temp |= (mach32_read_linear(addr + 1, svga) << 8); - temp |= (mach32_read_linear(addr + 2, svga) << 16); - temp |= (mach32_read_linear(addr + 3, svga) << 24); + if (dev->on[0] || dev->on[1]) { + temp = mach32_read_common(addr, 1, mach); + temp |= (mach32_read_common(addr + 1, 1, mach) << 8); + temp |= (mach32_read_common(addr + 2, 1, mach) << 16); + temp |= (mach32_read_common(addr + 3, 1, mach) << 24); + } else + temp = svga_readl_linear(addr, svga); + + mach_log("Linear WORDL Read=%08x, ret=%08x, ON0=%d, ON1=%d.\n", addr, temp, dev->on[0], dev->on[1]); } return temp; } 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))) { @@ -5098,7 +5357,7 @@ mach32_updatemapping(mach_t *mach) mach->ap_size = 4; mem_mapping_disable(&mach->mmio_linear_mapping); } - if ((mach->ext_on[0] || mach->ext_on[1]) && (dev->local >= 2) && (mach->ati_mode[0] || mach->ati_mode[1])) { + if (((dev->local & 0xff) >= 0x02) && (dev->on[0] || dev->on[1]) && (mach->ext_on[0] || mach->ext_on[1]) && (dev->vendor_mode[0] || dev->vendor_mode[1])) { mach_log("ExtON.\n"); mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); mem_mapping_set_p(&svga->mapping, mach); @@ -5119,19 +5378,30 @@ 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; - if (dev->accel_bpp == 8) { - color0 = dev->pallook[mach->cursor_col_0]; - color1 = dev->pallook[mach->cursor_col_1]; - } else if (dev->accel_bpp == 15) { - color0 = video_15to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; - color1 = video_15to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; - } else if (dev->accel_bpp == 16) { - color0 = video_16to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; - color1 = video_16to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; - } else { - color0 = ((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0); - color1 = ((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1); + 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]; + break; + case 15: + color0 = video_15to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; + color1 = video_15to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; + break; + case 16: + color0 = video_16to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; + color1 = video_16to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; + break; + case 24: + case 32: + 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; } if (dev->interlace && dev->hwcursor_oddeven) @@ -5141,16 +5411,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: @@ -5165,119 +5441,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 @@ -5367,6 +5644,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); @@ -5391,7 +5669,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); } @@ -5447,6 +5725,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) { @@ -5542,19 +5848,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: @@ -5603,7 +5909,7 @@ mach8_init(const device_t *info) mach->memory = device_get_config_int("memory"); mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1; - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus) { if (mach->has_bios) { rom_init(&mach->bios_rom, @@ -5632,14 +5938,13 @@ 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 >= 2) { + if ((dev->local & 0xff) >= 0x02) { svga_init(info, svga, mach, mach->memory << 10, /*default: 2MB for Mach32*/ mach_recalctimings, mach_in, mach_out, @@ -5670,7 +5975,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); @@ -5699,7 +6003,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); } @@ -5721,11 +6025,12 @@ mach8_init(const device_t *info) io_sethandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); mach_io_set(mach); - if (dev->local >= 2) { + if ((dev->local & 0xff) >= 0x02) { svga->decode_mask = (4 << 20) - 1; mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; mach->ext_cur_col_1_g = 0xff; + 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) { @@ -5742,23 +6047,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, 0); 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 @@ -5908,15 +6244,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_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_cl54xx.c b/src/video/vid_cl54xx.c index 83c4f5a63..49899b7b4 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -650,6 +650,23 @@ gd54xx_is_5434(svga_t *svga) return 0; } +static void +gd54xx_set_svga_fast(gd54xx_t *gd54xx) +{ + svga_t *svga = &gd54xx->svga; + + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424)) + svga->fast = ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && + ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && + !(svga->adv_flags & FLAG_ADDR_BY8); + /* TODO: needs verification on other Cirrus chips */ + else + svga->fast = ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || + svga->fb_only); +} + static void gd54xx_out(uint16_t addr, uint8_t val, void *priv) { @@ -792,14 +809,16 @@ 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_recalctimings(svga); + 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_recalc_banking(gd54xx); + gd54xx_set_svga_fast(gd54xx); + svga_recalctimings(svga); break; case 0x17: if (gd54xx_is_5422(svga)) @@ -919,10 +938,8 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv) break; } - if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5422) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5424)) - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); /*TODO: needs verification on other Cirrus chips*/ - else - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only); + gd54xx_set_svga_fast(gd54xx); + if (((svga->gdcaddr == 5) && ((val ^ o) & 0x70)) || ((svga->gdcaddr == 6) && ((val ^ o) & 1))) svga_recalctimings(svga); } else { @@ -1645,7 +1662,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) { @@ -1671,7 +1688,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); @@ -1682,10 +1699,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) { @@ -1735,6 +1752,34 @@ gd54xx_recalctimings(svga_t *svga) uint8_t rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + svga->hblankstart = svga->crtc[2] + 1; + + 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 = 0x0000007f; + + if (svga->crtc[0x1b] & 0x20) { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_val = ((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); @@ -1744,13 +1789,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; @@ -1791,7 +1838,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; @@ -1828,7 +1875,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; @@ -1908,7 +1955,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; @@ -1926,6 +1973,9 @@ 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) { svga->render = svga_render_text_40; @@ -1954,11 +2004,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; @@ -2058,18 +2108,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); @@ -2082,14 +2163,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 @@ -2104,11 +2188,11 @@ 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); + gd54xx_mem_sys_src_write(gd54xx, val, 0); return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) || !(svga->gdcreg[5] & 0x40)) { svga_write(addr, val, svga); return; } @@ -2130,7 +2214,7 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) || !(svga->gdcreg[5] & 0x40)) { svga_writew(addr, val, svga); return; } @@ -2235,13 +2319,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) { @@ -2268,7 +2345,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)) { @@ -2278,7 +2355,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: @@ -2302,15 +2379,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)) { @@ -2322,8 +2400,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; } @@ -2351,15 +2429,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)) { @@ -2371,10 +2450,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; } @@ -2411,9 +2490,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; } @@ -2424,7 +2505,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; @@ -2439,7 +2521,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; @@ -2454,10 +2537,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 @@ -2465,8 +2549,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); } @@ -2477,8 +2561,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); @@ -2492,9 +2576,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; } @@ -2510,7 +2594,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; } @@ -2536,12 +2620,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; } @@ -2557,8 +2641,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; } @@ -2603,12 +2687,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; } @@ -2624,10 +2708,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; } @@ -2685,11 +2769,11 @@ gd54xx_read(uint32_t addr, void *priv) gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_t *svga = &gd54xx->svga; - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) || !(svga->gdcreg[5] & 0x40)) 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 = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); @@ -2702,7 +2786,7 @@ gd54xx_readw(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint16_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) || !(svga->gdcreg[5] & 0x40)) return svga_readw(addr, svga); if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { @@ -2722,7 +2806,7 @@ gd54xx_readl(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint32_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) || !(svga->gdcreg[5] & 0x40)) return svga_readl(addr, svga); if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { @@ -2922,7 +3006,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; } @@ -3111,7 +3195,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; @@ -3360,7 +3444,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; @@ -3374,7 +3458,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. */ @@ -3385,16 +3469,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) @@ -3403,7 +3487,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; @@ -3464,7 +3548,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)) @@ -3477,7 +3561,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 */ @@ -3534,18 +3618,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); @@ -3557,7 +3641,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; @@ -3581,10 +3665,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; @@ -3625,7 +3709,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++; @@ -4896,6 +4980,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", 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_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..97da08822 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; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 834de7513..6d52fc91b 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -55,17 +55,19 @@ #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 TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.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 +117,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 +141,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 +153,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 +244,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 +336,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 +517,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 +563,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,6 +649,9 @@ 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] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400; if (svga->crtc[0x35] & 2) @@ -562,8 +666,10 @@ et4000_recalctimings(svga_t *svga) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + 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 +690,14 @@ et4000_recalctimings(svga_t *svga) case 15: case 16: svga->hdisp /= 2; + svga->hblankstart /= 2; + svga->hblank_end_val /= 2; break; case 24: svga->hdisp /= 3; + svga->hblankstart /= 3; + svga->hblank_end_val /= 3; break; default: @@ -613,6 +723,19 @@ 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; + } + + if (dev->type == ET4000_TYPE_TC6058AF) { + if (svga->render == svga_render_8bpp_lowres) + svga->render = svga_render_8bpp_tseng_lowres; + else if (svga->render == svga_render_8bpp_highres) + svga->render = svga_render_8bpp_tseng_highres; + } } static void @@ -623,7 +746,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 -= 5; 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)) @@ -672,6 +796,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 +805,8 @@ et4000_init(const device_t *info) NULL, NULL); io_sethandler(0x03c0, 32, et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev); + if (dev->type == ET4000_TYPE_TC6058AF) + fn = TC6058AF_BIOS_ROM_PATH; break; case ET4000_TYPE_MCA: /* MCA ET4000AX */ @@ -759,7 +886,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; @@ -799,6 +927,12 @@ et4000_force_redraw(void *priv) dev->svga.fullchange = changeframecount; } +static int +et4000_tc6058af_available(void) +{ + return rom_present(TC6058AF_BIOS_ROM_PATH); +} + static int et4000_available(void) { @@ -817,6 +951,33 @@ 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 = "" + } + } + }, + { + .type = CONFIG_END + } +// clang-format on +}; + static const device_config_t et4000_config[] = { // clang-format off { @@ -848,6 +1009,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 = 0, + .init = et4000_init, + .close = et4000_close, + .reset = NULL, + { .available = et4000_tc6058af_available }, + .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", diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index b48135c37..259fefffb 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -431,6 +431,9 @@ 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] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; if (svga->crtc[0x35] & 0x02) @@ -445,8 +448,10 @@ et4000w32p_recalctimings(svga_t *svga) svga->rowoffset += 0x100; if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + 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,10 +533,6 @@ 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) @@ -2616,6 +2596,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 +2659,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 +2785,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 +2809,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 +2821,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..35d335ed2 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -312,6 +312,10 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) ht216_remap(ht216); break; + case 0xca: + svga_recalctimings(svga); + break; + case 0xc9: case 0xcf: ht216_remap(ht216); @@ -321,6 +325,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 +454,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); @@ -688,7 +689,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; @@ -711,6 +712,9 @@ ht216_recalctimings(svga_t *svga) svga->vram_display_mask = 0x7ffff; else svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; + + if (ht216->ht_regs[0xe0] & 0x20) + svga->hblankstart = ((ht216->ht_regs[0xca] >> 2) << 8) + svga->crtc[4] + 1; } static void @@ -1466,9 +1470,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; 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..088085355 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) @@ -308,6 +330,8 @@ #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) @@ -348,7 +372,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 +409,8 @@ enum { MGA_2064W, /*Millennium*/ MGA_1064SG, /*Mystique*/ MGA_1164SG, /*Mystique 220*/ + MGA_2164W, /*Millennium II*/ + MGA_G100, /*Productiva G100*/ }; enum { @@ -429,8 +458,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 +468,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 +502,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 +510,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 +541,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 +660,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 +713,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,30 +759,60 @@ 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); + 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 == 3) { - if (val & CRTCX_R3_MGAMODE) - svga->fb_only = 1; - else - svga->fb_only = 0; - svga_recalctimings(svga); - } - if (mystique->crtcext_idx == 4) { + + 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; + } } } break; @@ -772,7 +846,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 +890,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 +942,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] + 1; + + 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 +1077,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 +1124,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,7 +1136,7 @@ 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); + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0x1ffff; break; case 0x4: /*64k at A0000*/ @@ -1038,6 +1176,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 +1409,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 +1523,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; @@ -1434,13 +1576,16 @@ 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; 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 +1593,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 +1762,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 +1902,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 +2093,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 +2140,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 +2185,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 +2222,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 +2385,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 +2393,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 +2512,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 +2590,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 +2667,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; @@ -2568,8 +2810,14 @@ static uint8_t mystique_readb_linear(uint32_t addr, void *priv) { const svga_t *svga = (svga_t *) priv; + mystique_t *mystique = (mystique_t *) svga->priv; - cycles -= video_timing_read_b; + if (mystique->type < MGA_1064SG) { + if (!svga->fast) + return svga_read_linear(addr, priv); + } + + cycles -= svga->monitor->mon_video_timing_read_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -2583,7 +2831,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 +2845,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) @@ -2610,14 +2858,22 @@ static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; + mystique_t *mystique = (mystique_t *) svga->priv; - cycles -= video_timing_write_b; + if (mystique->type < MGA_1064SG) { + if (!svga->fast) { + svga_write_linear(addr, val, priv); + return; + } + } + + cycles -= svga->monitor->mon_video_timing_write_b; 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 +2882,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 +2897,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 +2914,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 +2970,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 +3002,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 +3050,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 +3092,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 +3221,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 @@ -3943,21 +4284,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 +4328,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 +4345,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 +4379,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 +4396,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,21 +4424,32 @@ 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_16: if (!(mystique->dwgreg.dr[4] & (1 << 23))) @@ -4062,25 +4475,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 +4522,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 +4531,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 +4587,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 +4626,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 +4656,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 +4709,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 +4738,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 +4753,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 +4778,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 +4815,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 +4856,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 +4876,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 +4916,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 +4927,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 +4943,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 +4968,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 +5086,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 +5093,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 +5108,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 +5145,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 +5231,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 +5258,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 +5323,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; @@ -4686,6 +5371,7 @@ blit_bitblt(mystique_t *mystique) 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 +5380,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 +5433,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; } @@ -4787,6 +5478,7 @@ blit_bitblt(mystique_t *mystique) case DWGCTRL_ATYPE_RSTR: switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { 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 +5490,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 +5546,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; } @@ -4937,9 +5634,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 +5726,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: @@ -5129,19 +5833,19 @@ mystique_start_blit(mystique_t *mystique) 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,7 +5914,7 @@ 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] = (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; @@ -5228,12 +5932,42 @@ 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) { mystique_t *mystique = (mystique_t *) priv; uint8_t ret = 0x00; + if (mystique->type >= MGA_1164SG) + { + /* Mystique 220, Millennium II and later Matrox cards swap MGABASE1 and 2. */ + if (addr >= 0x10 && addr <= 0x13) + addr += 0x4; + else if (addr >= 0x14 && addr <= 0x17) + addr -= 0x4; + } + if ((addr >= 0x30) && (addr <= 0x33) && !(mystique->pci_regs[0x43] & 0x40)) ret = 0x00; else @@ -5246,10 +5980,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 +6007,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; @@ -5297,7 +6037,7 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) ret = 0x00; break; /*Linear frame buffer*/ case 0x16: - ret = (mystique->lfb_base >> 16) & 0x80; + ret = (mystique->type >= MGA_2164W) ? 0x00 : ((mystique->lfb_base >> 16) & 0x80); break; case 0x17: ret = mystique->lfb_base >> 24; @@ -5339,6 +6079,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 +6118,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; } @@ -5386,6 +6183,15 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { mystique_t *mystique = (mystique_t *) priv; + if (mystique->type >= MGA_1164SG) + { + /* Mystique 220, Millennium II and later Matrox cards swap MGABASE1 and 2. */ + if (addr >= 0x10 && addr <= 0x13) + addr += 0x4; + else if (addr >= 0x14 && addr <= 0x17) + addr -= 0x4; + } + switch (addr) { case PCI_REG_COMMAND: mystique->pci_regs[PCI_REG_COMMAND] = (val & 0x27) | 0x80; @@ -5414,11 +6220,13 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x16: + if (mystique->type >= MGA_2164W) + break; 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->lfb_base = (mystique->lfb_base & ((mystique->type >= MGA_2164W) ? 0x00000000 : 0x00800000)) | (val << 24); mystique_recalc_mapping(mystique); break; @@ -5437,9 +6245,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); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else mem_mapping_disable(&mystique->bios_rom.mapping); return; @@ -5463,11 +6273,11 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) 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); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, (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 +6306,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 +6367,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 +6389,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 +6400,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->vram_size >= 16) + mystique->svga.decode_mask = mystique->svga.vram_mask; + 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 +6413,8 @@ mystique_init(const device_t *info) NULL); mystique->svga.clock_gen = mystique; mystique->svga.getclock = mystique_getclock; + if (mystique->vram_size >= 16) + mystique->svga.decode_mask = mystique->svga.vram_mask; } io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); @@ -5560,7 +6427,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 +6439,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 +6488,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 +6541,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 +6601,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 +6674,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..d8691ad77 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> @@ -62,6 +64,7 @@ #define ROM_DIAMOND_STEALTH64_764 "roms/video/s3/stealt64.bin" #define ROM_TRIO64V2_DX_VBE20 "roms/video/s3/86c775_2.bin" #define ROM_PHOENIX_TRIO64VPLUS "roms/video/s3/64V1506.ROM" +#define ROM_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 +80,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, @@ -92,6 +96,7 @@ enum { S3_TRIO64V2_DX_ONBOARD, S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, + S3_CARDEX_TRIO64VPLUS, S3_DIAMOND_STEALTH_SE, S3_DIAMOND_STEALTH_VRAM, S3_ELSAWIN2KPROX_964, @@ -146,6 +151,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 +271,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 +380,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 +416,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 +510,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 +531,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 +541,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 +602,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 +636,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 +692,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 +715,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 +738,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 +754,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 +770,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 +782,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 +945,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: @@ -899,6 +993,11 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (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: @@ -932,6 +1031,11 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (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: @@ -965,6 +1069,11 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (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: @@ -1169,14 +1278,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 +1337,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 +1425,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 +1514,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 +1688,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 +1769,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 +1782,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 +2045,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); @@ -1981,7 +2120,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 +2134,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 +2660,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 +2719,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 +2770,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 +2863,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 +2911,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 +2930,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 +3030,8 @@ 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_PHOENIX_TRIO64VPLUS_ONBOARD) || + (s3->card_type == S3_CARDEX_TRIO64VPLUS)) && (svga->seqaddr == 0x17)) svga->seqregs[svga->seqaddr] ^= 0x01; return temp; } @@ -2917,16 +3045,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 +3076,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 +3093,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 +3124,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 +3133,7 @@ s3_in(uint16_t addr, void *priv) return (svga->crtc[0x5a] & 0x80); } else return svga->crtc[0x6c]; + break; default: break; @@ -3009,24 +3151,29 @@ 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->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { - svga->hdisp = svga->hdisp_old; + svga->hdisp = svga->hdisp_old; + svga->ma_latch |= (s3->ma_ext << 16); + + 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 +3181,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 +3193,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 +3229,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->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] + 1; + + 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 +3314,112 @@ 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_PHOENIX_VISION968: + case S3_NUMBER9_9FX_771: + 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 +3437,174 @@ 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_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + 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 +3626,168 @@ 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_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + 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 +3806,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 +3814,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 +3889,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 +3898,91 @@ 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_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: + 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,24 +4023,24 @@ 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; } } } @@ -3333,21 +4049,26 @@ s3_recalctimings(svga_t *svga) 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 +4084,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) + 1; + svga->hblank_end_val = ((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] + 1; + + /* 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 +4141,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 +4152,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 +4171,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 +4198,21 @@ 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->hblankstart >>= 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -3541,11 +4320,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 +4417,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 +4578,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 +4591,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 +5128,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 +5160,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 +5210,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 +5269,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 +5321,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 +5337,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 +5492,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 +5556,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 +5730,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 +5807,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 +5874,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 +6662,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; \ @@ -6260,6 +7057,746 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +void +s3_911_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; + 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 = (s3->accel.cmd & 0x200) ? 0x8000 : 0x80; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint32_t *vram_l = (uint32_t *) svga->vram; + 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; + + 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.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { + if (s3->color_16bit) { + if (count > 1) + count >>= 1; + } + } + + if (s3->color_16bit) + rd_mask &= 0xffff; + 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) + 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; + } + + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + if (s3->accel.ssv_draw) { + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (!s3->accel.ssv_len) + break; + + switch (s3->accel.ssv_dir & 0xe0) { + case 0x00: + s3->accel.cx++; + break; + case 0x20: + s3->accel.cx++; + s3->accel.cy--; + break; + case 0x40: + s3->accel.cy--; + break; + case 0x60: + s3->accel.cx--; + s3->accel.cy--; + break; + case 0x80: + s3->accel.cx--; + break; + case 0xa0: + s3->accel.cx--; + s3->accel.cy++; + break; + case 0xc0: + s3->accel.cy++; + break; + case 0xe0: + s3->accel.cx++; + s3->accel.cy++; + break; + + default: + break; + } + + s3->accel.ssv_len--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; + } + + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 1: /*Draw line*/ + if (!cpu_input) { + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + s3->accel.sy = s3->accel.maj_axis_pcnt & 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) { @@ -6273,12 +7810,13 @@ s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_d } } - s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); + 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) +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; @@ -6299,10 +7837,16 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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; @@ -6317,7 +7861,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); - if (s3->bpp == 1) { + if ((s3->bpp == 1) || s3->color_16bit) { srcbase >>= 1; dstbase >>= 1; } else if (s3->bpp == 3) { @@ -6353,9 +7897,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else if ((s3->bpp == 1) || s3->color_16bit) rd_mask &= 0xffff; - if ((s3->bpp == 0) && !s3->color_16bit) + if (s3->bpp == 0) compare &= 0xff; - else if ((s3->bpp == 1) || s3->color_16bit) + else if (s3->bpp == 1) compare &= 0xffff; switch (s3->accel.cmd & 0x600) { @@ -6393,10 +7937,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; @@ -6422,7 +7966,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; @@ -6486,16 +8030,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; @@ -6566,8 +8109,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; - } else /*Bresenham*/ - { + } 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 +8124,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,81 +8159,45 @@ 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; @@ -6748,13 +8254,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 +8272,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 +8296,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 +8313,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 +8424,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 +8451,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 +8468,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 +8491,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 +8510,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 +8525,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 +8535,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 +8554,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 +8580,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 +8642,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 +8654,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 +8674,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 +8684,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 +9067,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 +9107,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 +9115,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 +9333,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 +9407,13 @@ s3_reset(void *priv) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + 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 +9613,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; @@ -8138,6 +9666,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 +9769,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 +9866,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 +9896,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; @@ -8402,7 +9962,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 +9990,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 +10013,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 +10048,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 +10096,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*/ @@ -8540,6 +10112,7 @@ s3_init(const device_t *info) case S3_PHOENIX_TRIO64_ONBOARD: 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 +10125,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; @@ -8783,6 +10355,12 @@ 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 +10667,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 +10866,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 +10894,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", @@ -9414,6 +11020,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..3184a1ccd 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,6 +824,25 @@ s3_virge_recalctimings(svga_t *svga) svga->clock = (cpuclock * (float) (1ULL << 32)) / freq; } + 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->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] + 1; + + 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 |= (virge->ma_ext << 16); @@ -834,6 +864,8 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; } break; case 16: @@ -841,6 +873,8 @@ s3_virge_recalctimings(svga_t *svga) if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { svga->htotal >>= 1; svga->hdisp >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; } break; case 24: @@ -888,10 +922,14 @@ s3_virge_recalctimings(svga_t *svga) break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; + svga->hblankstart >>= 1; + svga->hblank_end_val >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ 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 1b9b3cf7c..d982a1ada 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -92,12 +92,10 @@ svga_set_override(svga_t *svga, int val) 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; @@ -116,6 +114,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 +162,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 +171,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; } @@ -219,8 +220,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv) dev->on[1] = dev->on[0]; } - svga_log("3C3: XGA ON = %d.\n", xga->on); + svga_log("3C3: VGA ON = %d.\n", val & 0x01); vga_on = val & 0x01; + svga_recalctimings(svga); break; case 0x3c4: svga->seqaddr = val; @@ -252,7 +254,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 +356,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 +479,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 +518,8 @@ svga_in(uint16_t addr, void *priv) ret = svga->cgastat; + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; break; default: @@ -558,11 +568,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; + double _dispontime8514; + double _dispofftime8514; + double disptime8514; +#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 +622,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]; @@ -611,71 +633,64 @@ svga_recalctimings(svga_t *svga) svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; - svga->lowres = svga->attrregs[0x10] & 0x40; + svga->lowres = !!(svga->attrregs[0x10] & 0x40); svga->interlace = 0; svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); svga->ca_adj = 0; - svga->rowcount = svga->crtc[9] & 31; + svga->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 +737,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,32 +750,155 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; - if (svga->recalctimings_ex) { + svga->hblankstart = svga->crtc[2] + 1; + 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; + + if (svga->recalctimings_ex) svga->recalctimings_ex(svga); - } if (ibm8514_active && (svga->dev8514 != NULL)) { - if (!dev->local) + if ((dev->local & 0xff) == 0x00) ibm8514_recalctimings(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("Blank: %04i-%04i, Total: %04i, Mask: %02X\n", svga->hblankstart, svga->hblank_end_val, + svga->htotal, eff_mask); + + while (1) { + if (dot == svga->htotal) + dot = 0; + + if (adj_dot >= svga->htotal) + svga->hblank_sub++; + + if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) + break; + + dot++; + adj_dot++; + } + + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + + 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 (1) { + if (dot8514 == dev->h_total) + dot = 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; + } + } + } + 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; + } + +#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; _dispontime = svga->hdisp_time; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + disptime8514 = dev->htotal; + _dispontime8514 = dev->hdisped; + } + } + if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; @@ -779,6 +915,27 @@ 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_enable(&svga->timer8514); + } else { + timer_disable(&svga->timer8514); + timer_enable(&svga->timer); + } + } + if (!svga->force_old_addr) svga_recalc_remap_func(svga); @@ -851,10 +1008,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); @@ -953,6 +1106,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; @@ -990,9 +1145,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->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); @@ -1062,9 +1217,10 @@ 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->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + 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); @@ -1074,9 +1230,12 @@ svga_poll(void *priv) 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 +1274,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 +1326,7 @@ 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->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 32; @@ -1194,7 +1360,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,9 +1405,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 (svga->adv_flags & FLAG_EXTRA_BANKS) { + if ((svga->gdcreg[5] & 0x40) || svga->packed_chain4) + addr = (addr & 0x17fff) + svga->extra_banks[(addr >> 15) & 1]; + } else { if (write) addr += svga->write_bank; else @@ -1646,7 +1813,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; @@ -1920,9 +2087,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 b14199f06..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]; @@ -454,11 +479,10 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) int x; uint32_t addr; uint32_t *p; - uint8_t edat[4]; 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. @@ -466,33 +490,50 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) - S3 Trio: mode 13h (320x200x8), incbypow2 given as 2 treated as 0 - ET4000/W32i: mode 2Eh (640x480x8), incevery given as 2 treated as 1 */ - const bool forcepacked = combine8bits && (svga->force_old_addr || svga->packed_chain4); + const bool forcepacked = combine8bits && (svga->force_old_addr || svga->packed_chain4); /* SVGA cards with a high-resolution 8bpp mode may actually bypass the VGA shifter logic. - HT-216 (+ other Video7 chipsets?) has 0x3C4.0xC8 bit 4 which, when set to 1, loads bytes directly, bypassing the shifters. */ - const bool highres8bpp = combine8bits && highres; + const bool highres8bpp = combine8bits && highres; - const bool dwordload = ((svga->seqregs[0x01] & 0x10) != 0); - const bool wordload = ((svga->seqregs[0x01] & 0x04) != 0) && !dwordload; - const bool wordincr = ((svga->crtc[0x17] & 0x08) != 0); - const bool dwordincr = ((svga->crtc[0x14] & 0x20) != 0) && !wordincr; - const bool dwordshift = ((svga->crtc[0x14] & 0x40) != 0); - const bool wordshift = ((svga->crtc[0x17] & 0x40) == 0) && !dwordshift; + const bool dwordload = ((svga->seqregs[0x01] & 0x10) != 0); + const bool wordload = ((svga->seqregs[0x01] & 0x04) != 0) && !dwordload; + const bool wordincr = ((svga->crtc[0x17] & 0x08) != 0); + const bool dwordincr = ((svga->crtc[0x14] & 0x20) != 0) && !wordincr; + const bool dwordshift = ((svga->crtc[0x14] & 0x40) != 0); + const bool wordshift = ((svga->crtc[0x17] & 0x40) == 0) && !dwordshift; const uint32_t incbypow2 = forcepacked ? 0 : (dwordshift ? 2 : wordshift ? 1 : 0); - const uint32_t incevery = forcepacked ? 1 : (dwordincr ? 4 : wordincr ? 2 : 1); - const uint32_t loadevery = forcepacked ? 1 : (dwordload ? 4 : wordload ? 2 : 1); + const uint32_t incevery = forcepacked ? 1 : (dwordincr ? 4 : wordincr ? 2 : 1); + 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 shift4bit = ((svga->gdcreg[0x05] & 0x40) == 0x40) || highres8bpp; + 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 uint8_t blinkmask = (attrblink ? 0x8 : 0x0); - const uint8_t blinkval = (attrblink && blinked ? 0x8 : 0x0); + const int dwshift = highres ? 0 : 1; + const int dotwidth = 1 << dwshift; + 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); + + /* + This is actually a 8x 3-bit lookup table, + preshifted by 2 bits to allow shifting by multiples of 4 bits. + + Anyway, when we perform a planar-to-chunky conversion, + we keep the pixel values in a scrambled order. + This lookup table unscrambles them. + + WARNING: Octal values are used here! + */ + const uint32_t shift_values = (shift4bit + ? ((067452301) << 2) + : shift2bit + ? ((026370415) << 2) + : ((002461357) << 2)); if ((svga->displine + svga->y_add) < 0) return; @@ -502,8 +543,7 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) else changed_offset = svga->remap_func(svga, svga->ma) >> 12; - if (!(svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || - svga->fullchange)) + if (!(svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)) return; p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; @@ -513,6 +553,7 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) uint32_t incr_counter = 0; uint32_t load_counter = 0; + uint32_t edat = 0; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += charwidth) { if (load_counter == 0) { /* Find our address */ @@ -529,7 +570,7 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) if (svga->ma & (4 << 15)) addr |= 0x4; } else { - if (svga->ma & (4<<13)) + if (svga->ma & (4 << 13)) addr |= 0x4; } } else { @@ -548,42 +589,31 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) addr &= svga->vram_display_mask; /* Load VRAM */ - *(uint32_t *)&edat[0] = *(uint32_t *)&svga->vram[addr]; + edat = *(uint32_t *) &svga->vram[addr]; - if (shift4bit) { - /* - Remap VGA 4bpp-chunky data into fully planar data - Plane 3 LSbit is aligned with MSbit - */ - uint8_t tmpdat[4] = {0, 0, 0, 0}; - for (int j = 0; j < 4; j++) { - for (int i = 0; i < 8; i++) { - tmpdat[j] <<= 1; - tmpdat[j] |= (edat[i>>1] >> (((0x1&~i)<<2)+j)) & 0x1; - } + /* + EGA and VGA actually use 4bpp planar as its native format. + But 4bpp chunky is generally easier to deal with on a modern CPU. + shift4bit is the native format for this renderer (4bpp chunky). + */ + 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 { + /* Group 4x 1bpp values into 4bpp values */ + edat = (edat & 0xAA55AA55) | ((edat << 7) & 0x55005500) | ((edat >> 7) & 0x00AA00AA); + edat = (edat & 0xCCCC3333) | ((edat << 14) & 0x33330000) | ((edat >> 14) & 0x0000CCCC); } - *(uint32_t *) (&edat[0]) = *(uint32_t *) (&tmpdat[0]); - } - - if (shift2bit) { - // Remap CGA 2bpp-chunky data into fully planar data - uint8_t dat0 = egaremap2bpp[edat[1]] | (egaremap2bpp[edat[0]] << 4); - uint8_t dat1 = egaremap2bpp[edat[1] >> 1] | (egaremap2bpp[edat[0] >> 1] << 4); - uint8_t dat2 = egaremap2bpp[edat[3]] | (egaremap2bpp[edat[2]] << 4); - uint8_t dat3 = egaremap2bpp[edat[3] >> 1] | (egaremap2bpp[edat[2] >> 1] << 4); - edat[0] = dat0; - edat[1] = dat1; - edat[2] = dat2; - edat[3] = dat3; } } else { /* According to the 82C451 VGA clone chipset datasheet, all 4 planes chain in a ring. So, rotate them all around. + Planar version: edat = (edat >> 8) | (edat << 24); + Here's the chunky version... */ - *(uint32_t *)&edat[0] - = ((*(uint32_t *)&edat[0]) >> 8) - | ((*(uint32_t *)&edat[0]) << 24); + edat = ((edat >> 1) & 0x77777777) | ((edat << 3) & 0x88888888); } load_counter += 1; if (load_counter >= loadevery) @@ -593,50 +623,72 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) if (incr_counter >= incevery) { incr_counter = 0; svga->ma += 4; - // DISCREPANCY TODO FIXME 2/4bpp used vram_mask, 8bpp used vram_display_mask --GM + /* DISCREPANCY TODO FIXME 2/4bpp used vram_mask, 8bpp used vram_display_mask --GM */ svga->ma &= svga->vram_display_mask; } + uint32_t current_shift = shift_values; + uint32_t out_edat = edat; /* - Now that we've converted it all to planar, convert it (back?) to chunky! + Apply blink + FIXME: Confirm blink behaviour on real hardware + + The VGA 4bpp graphics blink logic was a pain to work out. + + If plane 3 is enabled in the attribute controller, then: + - if bit 3 is 0, then we force the output of it to be 1. + - if bit 3 is 1, then the output blinks. + This can be tested with Lotus 1-2-3 release 2.3 with the WYSIWYG addon. + + If plane 3 is disabled in the attribute controller, then the output blinks. + This can be tested with QBASIC SCREEN 10 - anything using color #2 should + blink and nothing else. + + If you can simplify the following and have it still work, give yourself a medal. */ - for (int i = 0; i < 8; i += 2) { - const int inshift = 6 - i; - uint8_t dat - = (edatlookup[(edat[0] >> inshift) & 3][(edat[1] >> inshift) & 3]) - | (edatlookup[(edat[2] >> inshift) & 3][(edat[3] >> inshift) & 3] << 2); + out_edat = ((out_edat & planemask & ~blinkmask) | ((out_edat | ~planemask) & blinkmask & blinkval)) ^ blinkmask; - /* FIXME: Confirm blink behaviour on real hardware - - The VGA 4bpp graphics blink logic was a pain to work out. - - If plane 3 is enabled in the attribute controller, then: - - if bit 3 is 0, then we force the output of it to be 1. - - if bit 3 is 1, then the output blinks. - This can be tested with Lotus 1-2-3 release 2.3 with the WYSIWYG addon. - - If plane 3 is disabled in the attribute controller, then the output blinks. - This can be tested with QBASIC SCREEN 10 - anything using color #2 should - blink and nothing else. - - If you can simplify the following and have it still work, give yourself a medal. + 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. */ - uint32_t c0 = (dat >> 4) & 0xF; - uint32_t c1 = dat & 0xF; - c0 = ((c0 & svga->plane_mask & ~blinkmask) | - ((c0 | ~svga->plane_mask) & blinkmask & blinkval)) ^ blinkmask; - c1 = ((c1 & svga->plane_mask & ~blinkmask) | - ((c1 | ~svga->plane_mask) & blinkmask & blinkval)) ^ blinkmask; + uint32_t c0 = (out_edat >> (current_shift & 0x1C)) & 0xF; + current_shift >>= 3; + 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]]; + uint32_t p0 = svga->pallook[svga->egapal[c0]]; + uint32_t p1 = svga->pallook[svga->egapal[c1]]; const int outoffs = i << dwshift; for (int subx = 0; subx < dotwidth; subx++) p[outoffs + subx] = p0; @@ -645,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; } } @@ -660,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 @@ -940,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; @@ -965,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 { @@ -979,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; } } @@ -1011,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; @@ -1042,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 { @@ -1063,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; } } @@ -1092,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; @@ -1127,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; @@ -1173,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; @@ -1197,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 { @@ -1211,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; } @@ -1243,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; @@ -1274,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 { @@ -1295,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; } @@ -1334,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 { @@ -1353,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; } @@ -1369,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; } @@ -1407,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; } @@ -1438,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; } @@ -1454,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; } @@ -1489,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 { @@ -1505,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; @@ -1545,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; @@ -1563,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; } @@ -1604,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; } @@ -1644,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..d40f00e13 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -77,197 +77,200 @@ 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 }, + { &ati18800_device }, #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - { &ati18800_wonder_device }, + { &ati18800_wonder_device }, #endif - { &cga_device }, - { &sega_device }, - { &gd5401_isa_device }, - { &gd5402_isa_device }, - { &gd5420_isa_device }, - { &gd5422_isa_device }, - { &gd5426_isa_device }, - { &gd5426_diamond_speedstar_pro_a1_isa_device }, - { &gd5428_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 } + { &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 }, + { &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 }, + { &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_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 }, + { &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..86159ed0a 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,7 +3148,10 @@ 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: @@ -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 diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index 15215c45d..4b63892de 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -55,6 +55,11 @@ 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 @@ -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; @@ -490,6 +515,90 @@ tvp3026_recalctimings(void *priv, svga_t *svga) const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; 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); + + switch (ramdac->mcr) { + case 0x41: + case 0x4a: + case 0x61: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + case 0x42: + case 0x4b: + case 0x62: + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + break; + case 0x43: + case 0x4c: + case 0x63: + svga->hdisp <<= 3; + svga->dots_per_clock <<= 3; + break; + case 0x44: + case 0x64: + svga->hdisp <<= 4; + svga->dots_per_clock <<= 4; + break; + case 0x5b: + switch (ramdac->true_color) { + case 0x16: + case 0x17: + svga->hdisp = (svga->hdisp << 2) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 2) / 3; + break; + case 0x1e: + case 0x1f: + svga->hdisp = (svga->hdisp * 5) >> 2; + svga->dots_per_clock = (svga->dots_per_clock * 5) >> 2; + break; + } + break; + case 0x5c: + switch (ramdac->true_color) { + case 0x06: + case 0x07: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + break; + case 0x16: + case 0x17: + svga->hdisp = (svga->hdisp << 3) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 3) / 3; + break; + case 0x1e: + case 0x1f: + svga->hdisp = (svga->hdisp * 5) >> 1; + svga->dots_per_clock = (svga->dots_per_clock * 5) >> 1; + break; + } + break; + } +} + +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 @@ -630,6 +739,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..734179fa9 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -772,7 +772,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 +1310,7 @@ static const device_config_t voodoo_config[] = { .type = CONFIG_SELECTION, .selection = { { - .description = "Voodoo Graphics", + .description = "3Dfx Voodoo Graphics", .value = VOODOO_1 }, { @@ -1318,7 +1318,7 @@ static const device_config_t voodoo_config[] = { .value = VOODOO_SB50 }, { - .description = "Voodoo 2", + .description = "3Dfx Voodoo 2", .value = VOODOO_2 }, { @@ -1427,7 +1427,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..9fec8c073 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) { @@ -489,7 +517,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 +543,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 +552,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) + 1; + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; + svga->hblank_end_mask = 0x0000003f; + } + svga->hblank_end_val = ((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] + 1; + 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] + 1; + 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 +605,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 +652,10 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; - svga->htotal *= 2; + // svga->htotal *= 2; + // svga->hblankstart *= 2; + // svga->hblank_end_val *= 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; @@ -3190,6 +3262,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 +3546,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, diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index f53ba9bb4..fad5e4124 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -178,8 +178,8 @@ xga_updatemapping(svga_t *svga) } } - xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, - xga->disp_cntl_2 & 7, xga->aperture_cntl); + xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d, on = %d, linear endian reverse = %d.\n", xga->op_mode & 7, + xga->disp_cntl_2 & 7, xga->aperture_cntl, xga->on, xga->linear_endian_reverse); } xga_log("VGA on = %d, map = %02x.\n", vga_on, svga->gdcreg[6] & 0x0c); } @@ -198,7 +198,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 +213,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: @@ -410,7 +415,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) 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) { + else if (!xga->aperture_cntl) { if (xga->linear_endian_reverse && !(xga->access_mode & 8)) xga->cursor_data_on = 0; } @@ -422,10 +427,11 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->cursor_data_on = 1; else xga->cursor_data_on = 0; - } else { + } else xga->cursor_data_on = 0; - } - } + } else if (!xga->sprite_pos && xga->cursor_data_on && !xga->aperture_cntl && xga->linear_endian_reverse) + 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); @@ -519,7 +525,6 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) xga_updatemapping(svga); break; case 4: - xga->access_mode &= ~8; if ((xga->disp_cntl_2 & 7) == 4) xga->aperture_cntl = 0; break; @@ -804,7 +809,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; } @@ -926,16 +931,22 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b addr += (x >> 3); if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } - if (xga->linear_endian_reverse) { + + if (xga->linear_endian_reverse) bits = 7 - (x & 7); - } else { - if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) - bits = (x & 7); - else { - bits = 7 - (x & 7); + else { + if (xga->accel.px_map_format[xga->accel.dst_map] & 8) { + if ((xga->accel.px_map_format[xga->accel.src_map] & 8) && (xga->accel.px_map_format[map] & 8)) + bits = (x & 7); + else + bits = 7 - (x & 7); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) + bits = (x & 7); + else + bits = 7 - (x & 7); } } px = (byte >> bits) & 1; @@ -966,17 +977,16 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int addr += (x >> 3); if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } - if (xga->linear_endian_reverse) { + + if (xga->linear_endian_reverse) bits = 7 - (x & 7); - } else { + else { if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) bits = (x & 7); - else { + else bits = 7 - (x & 7); - } } px = (byte >> bits) & 1; return px; @@ -985,18 +995,18 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int addr += (x >> 1); if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } + return byte; case 3: /*8-bit*/ addr += (y * width); addr += x; if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } + return byte; case 4: /*16-bit*/ addr += (y * (width << 1)); @@ -1010,9 +1020,8 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int } else { if (!skip) { READW(addr, byte); - } else { + } else byte = mem_readb_phys(addr) | (mem_readb_phys(addr + 1) << 8); - } } return byte; @@ -1045,9 +1054,9 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui addr += (x >> 3); if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } + if (xga->linear_endian_reverse) { mask = 1 << (7 - (x & 7)); } else { @@ -1079,14 +1088,14 @@ 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) { + + if (xga->linear_endian_reverse) mask = 0x0f << ((1 - (x & 1)) << 2); - } else { - if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) { + else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) mask = 0x0f << ((x & 1) << 2); - } else { + else mask = 0x0f << ((1 - (x & 1)) << 2); - } } byte = (byte & ~mask) | (pixel & mask); if (!skip) { @@ -1136,8 +1145,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; int y = ssv & 0x0f; int x = 0; - int dx; - int dy; + int16_t dx; + int16_t dy; int dirx = 0; int diry = 0; @@ -1231,9 +1240,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) } } - if (!y) { + if (!y) break; - } dx += dirx; dy += diry; @@ -1247,62 +1255,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; - int ydir; int y = xga->accel.blt_width; int x = 0; - int dx; - int dy; - int draw_pixel; + int16_t dx; + int16_t dy; + 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; - - if (xga->accel.octant & 0x02) { - ydir = -1; - } else { - ydir = 1; - } - - if (xga->accel.octant & 0x04) { - xdir = -1; - } else { - xdir = 1; - } + 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) @@ -1315,17 +1289,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); @@ -1340,54 +1384,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); @@ -1401,84 +1400,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; @@ -1492,26 +1459,14 @@ xga_bitblt(svga_t *svga) uint32_t srcwidth = xga->accel.px_map_width[xga->accel.src_map]; uint32_t patheight = xga->accel.px_map_height[xga->accel.pat_src]; uint32_t srcheight = xga->accel.px_map_height[xga->accel.src_map]; -#if 0 uint32_t dstheight = xga->accel.px_map_height[xga->accel.dst_map]; -#endif uint32_t frgdcol = xga->accel.frgd_color; uint32_t bkgdcol = xga->accel.bkgd_color; + int16_t dx; + int16_t dy; int mix = 0; - int xdir; - int ydir; - - if (xga->accel.octant & 0x02) { - ydir = -1; - } else { - ydir = 1; - } - - if (xga->accel.octant & 0x04) { - xdir = -1; - } else { - xdir = 1; - } + int xdir = (xga->accel.octant & 0x04) ? -1 : 1; + int ydir = (xga->accel.octant & 0x02) ? -1 : 1; xga->accel.x = xga->accel.blt_width & 0xfff; xga->accel.y = xga->accel.blt_height & 0xfff; @@ -1520,14 +1475,16 @@ xga_bitblt(svga_t *svga) xga->accel.sy = xga->accel.src_map_y & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; xga->accel.py = xga->accel.pat_map_y & 0xfff; - xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + dx = xga->accel.dst_map_x & 0x1fff; + dy = xga->accel.dst_map_y & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) - xga->accel.dx |= ~0x17ff; - xga->accel.dy = xga->accel.dst_map_y & 0x1fff; + dx |= ~0x17ff; if (xga->accel.dst_map_y >= 0x1800) - xga->accel.dy |= ~0x17ff; + dy |= ~0x17ff; + 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, " @@ -1544,44 +1501,46 @@ xga_bitblt(svga_t *svga) xga->accel.pattern = 1; else { if ((dstwidth == (xga->h_disp - 1)) && (srcwidth == 1)) { - if ((xga->accel.dst_map == 1) && (xga->accel.src_map == 2) && xga->linear_endian_reverse) { - if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x0b)) { + if ((xga->accel.dst_map == 1) && (xga->accel.src_map == 2)) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x0b)) xga->accel.pattern = 1; - } } } } + xga_log("PAT8: PatFormat=%x, SrcFormat=%x, DstFormat=%x.\n", xga->accel.px_map_format[xga->accel.pat_src] & 8, (xga->accel.px_map_format[xga->accel.src_map]), (xga->accel.px_map_format[xga->accel.dst_map])); xga_log("Pattern Map = 8: CMD = %08x: SRCBase = %08x, DSTBase = %08x, from/to vram dir = %d, " "cmd dir = %06x\n", xga->accel.command, srcbase, dstbase, xga->from_to_vram, xga->accel.dir_cmd); xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d\n", xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, xga->accel.src_map, - xga->accel.dst_map, xga->accel.py, xga->accel.sy, xga->accel.dy, + xga->accel.dst_map, xga->accel.py, xga->accel.sy, dy, xga->accel.px_map_width[0], xga->accel.px_map_width[1], xga->accel.px_map_width[2], xga->accel.px_map_width[3]); while (xga->accel.y >= 0) { if (xga->accel.command & 0xc0) { - if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + 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.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + 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_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); } } } else { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(1, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, 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_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } } } @@ -1589,17 +1548,19 @@ xga_bitblt(svga_t *svga) xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); else xga->accel.sx += xdir; - xga->accel.dx += xdir; + + dx += xdir; xga->accel.x--; if (xga->accel.x < 0) { - xga->accel.x = (xga->accel.blt_width & 0xfff); + xga->accel.x = xga->accel.blt_width & 0xfff; - xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) - xga->accel.dx |= ~0x17ff; + dx |= ~0x17ff; xga->accel.sx = xga->accel.src_map_x & 0xfff; - xga->accel.dy += ydir; + dy += ydir; + if (xga->accel.pattern) xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); else @@ -1608,8 +1569,8 @@ xga_bitblt(svga_t *svga) xga->accel.y--; if (xga->accel.y < 0) { - xga->accel.dst_map_x = xga->accel.dx; - xga->accel.dst_map_y = xga->accel.dy; + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; return; } } @@ -1620,13 +1581,12 @@ xga_bitblt(svga_t *svga) else { if (dstwidth == (xga->h_disp - 1)) { if (srcwidth == (xga->h_disp - 1)) { - if ((xga->accel.src_map == 1) && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2) && xga->linear_endian_reverse) { - if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { + if ((xga->accel.src_map == 1) && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2)) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) xga->accel.pattern = 1; - } } } else { - if (!xga->accel.src_map && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2) && xga->linear_endian_reverse) { + if (!xga->accel.src_map && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2)) { if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0b) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { if ((patwidth >= 7) && ((xga->accel.command & 0xc0) == 0x40)) xga->accel.pattern = 0; @@ -1638,6 +1598,7 @@ xga_bitblt(svga_t *svga) } } + xga_log("PAT%d: PatFormat=%x, SrcFormat=%x, DstFormat=%x.\n", xga->accel.pat_src, xga->accel.px_map_format[xga->accel.pat_src] & 8, (xga->accel.px_map_format[xga->accel.src_map]), (xga->accel.px_map_format[xga->accel.dst_map])); xga_log("XGA bitblt linear endian reverse=%d, octanty=%d, src command = %08x, pxsrcmap=%x, " "pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, dstwidth=%d, dstheight=%d, srcwidth=%d, " "srcheight=%d, dstbase=%08x, srcbase=%08x.\n", xga->linear_endian_reverse, ydir, @@ -1654,74 +1615,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 ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (area_state) - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(area_state, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + 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.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 (area_state) - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(area_state, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, xga->accel.dx, xga->accel.dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { + 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.dx++; + 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; - xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) - xga->accel.dx |= ~0x17ff; + dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); - xga->accel.py += ydir; - xga->accel.dy += ydir; + xga->accel.py++; - if (xga->accel.y < 0) { - xga->accel.dst_map_x = xga->accel.dx; - xga->accel.dst_map_y = xga->accel.dy; + dy++; + xga->accel.filling = 0; + + if (xga->accel.y < 0) return; - } } } } else { @@ -1729,32 +1682,34 @@ xga_bitblt(svga_t *svga) mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); if (xga->accel.command & 0xc0) { - if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (mix) { + 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) 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, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + + 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(mix, dest_dat, src_dat); dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); } } } else { - if (mix) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(mix, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { + if (mix) + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + else + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + + dest_dat = xga_accel_read_map_pixel(svga, 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(mix, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } } } @@ -1763,15 +1718,17 @@ xga_bitblt(svga_t *svga) xga->accel.px = ((xga->accel.px + xdir) & patwidth) | (xga->accel.px & ~patwidth); else xga->accel.px += xdir; - xga->accel.dx += xdir; + + dx += xdir; xga->accel.x--; if (xga->accel.x < 0) { xga->accel.y--; - xga->accel.x = (xga->accel.blt_width & 0xfff); + xga->accel.x = xga->accel.blt_width & 0xfff; - xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) - xga->accel.dx |= ~0x17ff; + dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; @@ -1780,11 +1737,12 @@ xga_bitblt(svga_t *svga) xga->accel.py = ((xga->accel.py + ydir) & patheight) | (xga->accel.py & ~patheight); else xga->accel.py += ydir; - xga->accel.dy += ydir; + + dy += ydir; if (xga->accel.y < 0) { - xga->accel.dst_map_x = xga->accel.dx; - xga->accel.dst_map_y = xga->accel.dy; + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; return; } } @@ -1864,7 +1822,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; @@ -1872,7 +1830,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; @@ -1880,7 +1838,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; @@ -1888,7 +1846,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; @@ -1896,7 +1854,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; @@ -1904,7 +1862,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; @@ -2009,6 +1967,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; @@ -2433,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; } @@ -2448,7 +2430,7 @@ xga_hwcursor_draw(svga_t *svga, int displine) int y_pos; int comb = 0; uint32_t *p; - int idx = (xga->cursor_data_on) ? 32 : 0; + int idx = xga->cursor_data_on ? 32 : 0; if (xga->interlace && xga->hwcursor_oddeven) xga->hwcursor_latch.addr += 16; @@ -2543,20 +2525,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; @@ -2620,7 +2606,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]; @@ -2963,9 +2949,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); @@ -2987,9 +2972,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 { @@ -3007,6 +2993,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); @@ -3146,6 +3133,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..710449746 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -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 diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 022a639f2..0cf34d6c6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -64,9 +64,6 @@ ifeq ($(DEV_BUILD), y) ifndef LASERXT LASERXT := y endif - ifndef MGA - MGA := y - endif ifndef OLIVETTI OLIVETTI := y endif @@ -128,9 +125,6 @@ else ifndef LASERXT LASERXT := n endif - ifndef MGA - MGA := n - endif ifndef OLIVETTI OLIVETTI := n endif @@ -496,11 +490,6 @@ ifeq ($(DEV_BRANCH), y) 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 @@ -628,7 +617,9 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm mouse_bus.o \ mouse_serial.o mouse_ps2.o \ mouse_wacom_tablet.o \ - phoenix_486_jumper.o serial_passthrough.o + nec_mate_unk.o phoenix_486_jumper.o \ + serial_passthrough.o \ + unittester.o SIOOBJ := sio_acc3221.o sio_ali5123.o \ sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \ @@ -658,6 +649,7 @@ HDDOBJ := hdd.o \ hdc_xta.o \ hdc_esdi_at.o hdc_esdi_mca.o \ hdc_xtide.o hdc_ide.o \ + hdc_ide_ali5213.o \ hdc_ide_opti611.o \ hdc_ide_cmd640.o hdc_ide_cmd646.o \ hdc_ide_sff8038i.o @@ -765,6 +757,7 @@ VIDOBJ := agpgart.o video.o \ vid_s3.o vid_s3_virge.o \ vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ vid_ogc.o \ + vid_mga.o \ vid_nga.o \ vid_tvp3026_ramdac.o \ vid_xga.o diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc index 6c0982c5c..353ea55b6 100644 --- a/src/win/languages/cs-CZ.rc +++ b/src/win/languages/cs-CZ.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "Grafika IBM 8514/A" #define STR_XGA "Grafika XGA" #define STR_MOUSE "Myš:" diff --git a/src/win/languages/de-DE.rc b/src/win/languages/de-DE.rc index 031f935cd..0fe48b0ef 100644 --- a/src/win/languages/de-DE.rc +++ b/src/win/languages/de-DE.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Videokarte:" #define STR_VIDEO_2 "Videokarte 2:" #define STR_VOODOO "Voodoo-Grafik" -#define STR_IBM8514 "IBM 8514/a-Grafik" +#define STR_IBM8514 "IBM 8514/A-Grafik" #define STR_XGA "XGA-Grafik" #define STR_MOUSE "Maus:" diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc index 01e18f71a..bc0df4d05 100644 --- a/src/win/languages/en-GB.rc +++ b/src/win/languages/en-GB.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" @@ -293,10 +293,10 @@ END #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_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" diff --git a/src/win/languages/en-US.rc b/src/win/languages/en-US.rc index 6ca6945d6..05ef61790 100644 --- a/src/win/languages/en-US.rc +++ b/src/win/languages/en-US.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" @@ -293,10 +293,10 @@ END #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_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" diff --git a/src/win/languages/es-ES.rc b/src/win/languages/es-ES.rc index 1fd0bceff..e9fef50d4 100644 --- a/src/win/languages/es-ES.rc +++ b/src/win/languages/es-ES.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Ratón:" diff --git a/src/win/languages/fi-FI.rc b/src/win/languages/fi-FI.rc index 3f875cb3d..1b958cc82 100644 --- a/src/win/languages/fi-FI.rc +++ b/src/win/languages/fi-FI.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "IBM 8514/A-grafiikkasuoritin" #define STR_XGA "XGA-grafiikkasuoritin" #define STR_MOUSE "Hiiri:" diff --git a/src/win/languages/fr-FR.rc b/src/win/languages/fr-FR.rc index 1ad5a4da1..8c77979ef 100644 --- a/src/win/languages/fr-FR.rc +++ b/src/win/languages/fr-FR.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "Graphique IBM 8514/A" #define STR_XGA "Graphique XGA" #define STR_MOUSE "Souris:" diff --git a/src/win/languages/hr-HR.rc b/src/win/languages/hr-HR.rc index 9497a7b0d..2e6caea43 100644 --- a/src/win/languages/hr-HR.rc +++ b/src/win/languages/hr-HR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo grafika" -#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_IBM8514 "IBM 8514/A grafika" #define STR_XGA "XGA grafika" #define STR_MOUSE "Miš:" diff --git a/src/win/languages/hu-HU.rc b/src/win/languages/hu-HU.rc index ab91d43f5..34bf512c1 100644 --- a/src/win/languages/hu-HU.rc +++ b/src/win/languages/hu-HU.rc @@ -288,7 +288,7 @@ END #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_IBM8514 "IBM 8514/A-gyorsítókártya" #define STR_XGA "XGA-gyorsítókártya" #define STR_MOUSE "Egér:" diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc index cb6e7afa1..6f5b67201 100644 --- a/src/win/languages/it-IT.rc +++ b/src/win/languages/it-IT.rc @@ -284,7 +284,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Grafica Voodoo" -#define STR_IBM8514 "Grafica IBM 8514/a" +#define STR_IBM8514 "Grafica IBM 8514/A" #define STR_XGA "Grafica XGA" #define STR_MOUSE "Mouse:" diff --git a/src/win/languages/ja-JP.rc b/src/win/languages/ja-JP.rc index bf9509453..a8e90d062 100644 --- a/src/win/languages/ja-JP.rc +++ b/src/win/languages/ja-JP.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "ビデオカード:" #define STR_VIDEO_2 "ビデオカード2:" #define STR_VOODOO "Voodooグラフィック" -#define STR_IBM8514 "IBM 8514/aグラフィック" +#define STR_IBM8514 "IBM 8514/Aグラフィック" #define STR_XGA "XGAグラフィック" #define STR_MOUSE "マウス:" diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc index 360d6e36b..535ff1df4 100644 --- a/src/win/languages/ko-KR.rc +++ b/src/win/languages/ko-KR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "비디오 카드:" #define STR_VIDEO_2 "비디오 카드 2:" #define STR_VOODOO "Voodoo 그래픽" -#define STR_IBM8514 "IBM 8514/a 그래픽" +#define STR_IBM8514 "IBM 8514/A 그래픽" #define STR_XGA "XGA 그래픽" #define STR_MOUSE "마우스:" diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc index f835ad9eb..bdd73f6cf 100644 --- a/src/win/languages/pl-PL.rc +++ b/src/win/languages/pl-PL.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Wideo:" #define STR_VIDEO_2 "Wideo 2:" #define STR_VOODOO "Grafika Voodoo" -#define STR_IBM8514 "Grafika IBM 8514/a" +#define STR_IBM8514 "Grafika IBM 8514/A" #define STR_XGA "Grafika XGA" #define STR_MOUSE "Mysz:" diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index 00e9c243d..48cbba111 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -286,7 +286,7 @@ END #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_IBM8514 "Gráficos IBM 8514/A" #define STR_XGA "Gráficos XGA" #define STR_MOUSE "Mouse:" diff --git a/src/win/languages/pt-PT.rc b/src/win/languages/pt-PT.rc index 88db4f18c..e4394b0cb 100644 --- a/src/win/languages/pt-PT.rc +++ b/src/win/languages/pt-PT.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "Gráficos IBM 8514/A" #define STR_XGA "Gráficos XGA" #define STR_MOUSE "Rato:" diff --git a/src/win/languages/ru-RU.rc b/src/win/languages/ru-RU.rc index 647b43d44..01562063a 100644 --- a/src/win/languages/ru-RU.rc +++ b/src/win/languages/ru-RU.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Видеокарта:" #define STR_VIDEO_2 "Видеокарта 2:" #define STR_VOODOO "Ускоритель Voodoo" -#define STR_IBM8514 "Ускоритель IBM 8514/a" +#define STR_IBM8514 "Ускоритель IBM 8514/A" #define STR_XGA "Ускоритель XGA" #define STR_MOUSE "Мышь:" diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc index b3a00c9de..80da82276 100644 --- a/src/win/languages/sl-SI.rc +++ b/src/win/languages/sl-SI.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo grafika" -#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_IBM8514 "IBM 8514/A grafika" #define STR_XGA "XGA grafika" #define STR_MOUSE "Miška:" diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc index 78e7b4b87..d7285bdf7 100644 --- a/src/win/languages/tr-TR.rc +++ b/src/win/languages/tr-TR.rc @@ -283,7 +283,7 @@ END #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_IBM8514 "IBM 8514/A Grafikleri" #define STR_XGA "XGA Grafikleri" #define STR_MOUSE "Fare:" diff --git a/src/win/languages/uk-UA.rc b/src/win/languages/uk-UA.rc index 41bf85f1a..d9674260c 100644 --- a/src/win/languages/uk-UA.rc +++ b/src/win/languages/uk-UA.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Відеокарта:" #define STR_VIDEO_2 "Відеокарта 2:" #define STR_VOODOO "Прискорювач Voodoo" -#define STR_IBM8514 "Прискорювач IBM 8514/a" +#define STR_IBM8514 "Прискорювач IBM 8514/A" #define STR_XGA "Прискорювач XGA" #define STR_MOUSE "Миша:" diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc index 92afaf86d..1be833eb3 100644 --- a/src/win/languages/zh-CN.rc +++ b/src/win/languages/zh-CN.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "显卡:" #define STR_VIDEO_2 "显卡 2:" #define STR_VOODOO "Voodoo 显卡" -#define STR_IBM8514 "IBM 8514/a 显卡" +#define STR_IBM8514 "IBM 8514/A 显卡" #define STR_XGA "XGA 显卡" #define STR_MOUSE "鼠标:" diff --git a/src/win/languages/zh-TW.rc b/src/win/languages/zh-TW.rc index 039993e5d..dcc01836b 100644 --- a/src/win/languages/zh-TW.rc +++ b/src/win/languages/zh-TW.rc @@ -274,7 +274,7 @@ END #define STR_MB "MB" #define STR_MEMORY "記憶體:" #define STR_TIME_SYNC "時間同步" -#define STR_DISABLED "禁用" +#define STR_DISABLED "停用" #define STR_ENABLED_LOCAL "啟用 (本地時間)" #define STR_ENABLED_UTC "啟用 (UTC)" #define STR_DYNAREC "動態重編譯器" @@ -283,7 +283,7 @@ END #define STR_VIDEO "顯示卡:" #define STR_VIDEO_2 "顯示卡 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "滑鼠:" @@ -508,7 +508,7 @@ BEGIN IDS_2144 "OpenGL 著色器 (*.GLSL)\0*.GLSL\0所有檔案 (*.*)\0*.*\0" IDS_2145 "OpenGL 選項" IDS_2146 "正在載入一個不受支援的設定" - IDS_2147 "此模擬電腦禁用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" + 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" @@ -591,11 +591,11 @@ BEGIN IDS_5120 "光碟 %i (%s): %s" - IDS_5376 "禁用" + IDS_5376 "停用" IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "禁用" + IDS_5632 "停用" IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" diff --git a/src/win/win.c b/src/win/win.c index 21ff6646c..d77ab32fd 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -51,6 +51,7 @@ #include <86box/path.h> #define GLOBAL #include <86box/plat.h> +#include <86box/plat_dynld.h> #include <86box/thread.h> #include <86box/ui.h> #ifdef USE_VNC @@ -1276,6 +1277,35 @@ plat_get_cpu_string(char *outbuf, uint8_t len) { strncpy(outbuf, cpu_string, len); } +void +plat_set_thread_name(void *thread, const char *name) +{ + /* 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); + } +} + void take_screenshot(void) { diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 37b741c29..58bd85c65 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -136,6 +136,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/win/win_jsconf.c b/src/win/win_jsconf.c index 190338d3e..66ad60c73 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -247,7 +247,7 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lPa 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++) { + for (c = 0; c < joystick_get_pov_count(joystick_config_type); c++) { h = GetDlgItem(hdlg, id); joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(hdlg, id); id += 2; diff --git a/src/win/win_thread.c b/src/win/win_thread.c index faacca74f..e874c4941 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -37,9 +37,10 @@ typedef struct { } win_event_t; thread_t * -thread_create(void (*func)(void *param), void *param) +thread_create_named(void (*func)(void *param), void *param, const char *name) { uintptr_t bt = _beginthread(func, 0, param); + plat_set_thread_name((void *) bt, name); return ((thread_t *) bt); }