mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 09:58:19 -07:00
Merge branch 'master'
This commit is contained in:
40
.github/workflows/cmake_linux.yml
vendored
40
.github/workflows/cmake_linux.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_linux.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -21,7 +22,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_linux.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -29,12 +30,10 @@ on:
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.arch }}"
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
runs-on: ${{ matrix.environment.runner }}
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
@@ -69,6 +68,20 @@ jobs:
|
||||
qttranslations5-l10n
|
||||
libevdev-dev
|
||||
libxkbcommon-x11-dev
|
||||
environment:
|
||||
- arch: x86_64
|
||||
toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
slug: "-x86_64"
|
||||
runner: ubuntu-22.04
|
||||
- arch: arm64
|
||||
toolchain: ./cmake/flags-gcc-aarch64.cmake
|
||||
slug: -arm64
|
||||
runner: ubuntu-22.04-arm
|
||||
exclude:
|
||||
- dynarec:
|
||||
new: off
|
||||
environment:
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
@@ -93,28 +106,17 @@ jobs:
|
||||
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@v3
|
||||
|
||||
- name: Configure CMake
|
||||
run: >-
|
||||
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
||||
--toolchain ./cmake/flags-gcc-x86_64.cmake
|
||||
--toolchain ${{ matrix.environment.toolchain }}
|
||||
-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 }}"
|
||||
cmake --build build
|
||||
|
||||
- name: Generate package
|
||||
run: |
|
||||
@@ -123,5 +125,5 @@ jobs:
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}'
|
||||
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy${{ matrix.environment.slug }}-gha${{ github.run_number }}'
|
||||
path: build/artifacts/**
|
||||
|
||||
45
.github/workflows/cmake_macos.yml
vendored
45
.github/workflows/cmake_macos.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_macos.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -21,7 +22,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_macos.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -29,13 +30,11 @@ on:
|
||||
jobs:
|
||||
|
||||
macos13-x86_64:
|
||||
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
|
||||
|
||||
runs-on: macos-13
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
@@ -83,9 +82,6 @@ jobs:
|
||||
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@v3
|
||||
|
||||
- name: Configure CMake
|
||||
run: >-
|
||||
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
||||
@@ -99,20 +95,10 @@ jobs:
|
||||
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
|
||||
|
||||
- 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 }}"
|
||||
run: cmake --build build
|
||||
|
||||
- name: Generate package
|
||||
run: |
|
||||
cmake --install build
|
||||
run: cmake --install build
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -121,13 +107,11 @@ jobs:
|
||||
path: build/artifacts/**
|
||||
|
||||
macos14-arm64:
|
||||
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, arm64"
|
||||
|
||||
runs-on: macos-14
|
||||
|
||||
# env:
|
||||
# BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
@@ -175,9 +159,6 @@ jobs:
|
||||
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@v3
|
||||
|
||||
- name: Configure CMake
|
||||
run: >-
|
||||
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
||||
@@ -191,20 +172,10 @@ jobs:
|
||||
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
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 }}"
|
||||
run: cmake --build build
|
||||
|
||||
- name: Generate package
|
||||
run: |
|
||||
cmake --install build
|
||||
run: cmake --install build
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
48
.github/workflows/cmake_windows_msys2.yml
vendored
48
.github/workflows/cmake_windows_msys2.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_windows_msys2.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -21,6 +22,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/cmake_windows_msys2.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -28,13 +30,11 @@ on:
|
||||
jobs:
|
||||
|
||||
msys2:
|
||||
|
||||
name: "${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
|
||||
|
||||
runs-on: ${{ matrix.environment.runner }}
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
@@ -43,23 +43,47 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
build:
|
||||
- name: Dev Debug
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
- name: Debug
|
||||
preset: dev_debug
|
||||
slug: -Dev-Debug
|
||||
slug: -Debug
|
||||
- name: Dev
|
||||
preset: development
|
||||
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-base:p
|
||||
qt5-tools:p
|
||||
vulkan-headers:p
|
||||
environment:
|
||||
# - msystem: MSYS
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
# slug: "-MSYS64"
|
||||
- msystem: MINGW64
|
||||
prefix: mingw-w64-x86_64
|
||||
toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
slug: "-64"
|
||||
runner: windows-2022
|
||||
# - msystem: CLANG64
|
||||
# prefix: mingw-w64-clang-x86_64
|
||||
# toolchain: ./cmake/llvm-win32-x86_64.cmake
|
||||
# slug: "CLANG64"
|
||||
# - msystem: UCRT64
|
||||
# prefix: mingw-w64-ucrt-x86_64
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
# slug: "UCRT64"
|
||||
- msystem: CLANGARM64
|
||||
toolchain: ./cmake/flags-gcc-aarch64.cmake
|
||||
slug: -arm64
|
||||
@@ -100,9 +124,6 @@ jobs:
|
||||
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@v3
|
||||
|
||||
- name: Configure CMake
|
||||
run: >-
|
||||
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
||||
@@ -110,20 +131,9 @@ jobs:
|
||||
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
|
||||
-D CMAKE_INSTALL_PREFIX=./build/artifacts
|
||||
|
||||
# - 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: Build
|
||||
run: cmake --build build
|
||||
|
||||
# - name: Run sonar-scanner
|
||||
# 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
|
||||
|
||||
|
||||
40
.github/workflows/codeql_linux.yml
vendored
40
.github/workflows/codeql_linux.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_linux.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -20,7 +21,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_linux.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -32,10 +33,13 @@ jobs:
|
||||
|
||||
analyze-linux:
|
||||
|
||||
name: "Analyze Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
|
||||
name: "Analyze (${{ 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
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -48,12 +52,12 @@ jobs:
|
||||
build:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
# - name: Debug
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
- name: Debug
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
slug: -Debug
|
||||
# - name: Dev
|
||||
# preset: development
|
||||
# slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
new: off
|
||||
@@ -64,6 +68,7 @@ jobs:
|
||||
ui:
|
||||
- name: SDL GUI
|
||||
qt: off
|
||||
static: on
|
||||
- name: Qt GUI
|
||||
qt: on
|
||||
slug: -Qt
|
||||
@@ -95,6 +100,11 @@ jobs:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Install Build Wrapper
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -111,9 +121,23 @@ jobs:
|
||||
-D QT=${{ matrix.ui.qt }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
run: |
|
||||
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: SonarQube Scan
|
||||
if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
# if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
|
||||
with:
|
||||
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
|
||||
args: >
|
||||
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"
|
||||
|
||||
40
.github/workflows/codeql_macos.yml
vendored
40
.github/workflows/codeql_macos.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_macos.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -20,7 +21,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_macos.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -32,10 +33,13 @@ jobs:
|
||||
|
||||
analyze-macos13-x86_64:
|
||||
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
|
||||
name: "Analyze (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
|
||||
|
||||
runs-on: macos-13
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -48,12 +52,12 @@ jobs:
|
||||
build:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
# - name: Debug
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
- name: Debug
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
slug: -Debug
|
||||
# - name: Dev
|
||||
# preset: development
|
||||
# slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
new: off
|
||||
@@ -74,7 +78,6 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: >-
|
||||
brew install
|
||||
ninja
|
||||
sdl2
|
||||
rtmidi
|
||||
openal-soft
|
||||
@@ -86,6 +89,11 @@ jobs:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Install Build Wrapper
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -106,9 +114,23 @@ jobs:
|
||||
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
run: |
|
||||
build-wrapper-macosx-x86 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: SonarQube Scan
|
||||
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
|
||||
with:
|
||||
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
|
||||
args: >
|
||||
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"
|
||||
|
||||
68
.github/workflows/codeql_windows_msys2.yml
vendored
68
.github/workflows/codeql_windows_msys2.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_windows_msys2.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -20,7 +21,7 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- "!.github/workflows/**"
|
||||
- .github/workflows/codeql_windows_msys2.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -32,9 +33,12 @@ jobs:
|
||||
|
||||
analyze-msys2:
|
||||
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
|
||||
name: "Analyze (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})"
|
||||
|
||||
runs-on: windows-2022
|
||||
runs-on: ${{ matrix.environment.runner }}
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -52,12 +56,12 @@ jobs:
|
||||
build:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
# - name: Debug
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
- name: Debug
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
slug: -Debug
|
||||
# - name: Dev
|
||||
# preset: development
|
||||
# slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
new: off
|
||||
@@ -77,21 +81,37 @@ jobs:
|
||||
environment:
|
||||
# - msystem: MSYS
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
# slug: "-MSYS64"
|
||||
- msystem: MINGW64
|
||||
prefix: mingw-w64-x86_64
|
||||
toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
slug: "-64"
|
||||
runner: windows-2022
|
||||
# - 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
|
||||
# slug: "CLANG64"
|
||||
# runner: windows-2022
|
||||
# - msystem: UCRT64
|
||||
# prefix: mingw-w64-ucrt-x86_64
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
# slug: "UCRT64"
|
||||
# runner: windows-2022
|
||||
# - msystem: CLANGARM64
|
||||
# toolchain: ./cmake/flags-gcc-aarch64.cmake
|
||||
# slug: -arm64
|
||||
# runner: windows-11-arm
|
||||
exclude:
|
||||
- dynarec:
|
||||
new: off
|
||||
environment:
|
||||
msystem: CLANGARM64
|
||||
|
||||
steps:
|
||||
- name: Prepare MSYS2 environment
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
release: false
|
||||
release: true
|
||||
update: true
|
||||
msystem: ${{ matrix.environment.msystem }}
|
||||
pacboy: >-
|
||||
@@ -109,9 +129,15 @@ jobs:
|
||||
fluidsynth:p
|
||||
libserialport:p
|
||||
${{ matrix.ui.packages }}
|
||||
openmp:p
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
# - name: Install Build Wrapper
|
||||
# uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -128,11 +154,27 @@ jobs:
|
||||
-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: Build
|
||||
run: cmake --build build
|
||||
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: SonarQube Scan
|
||||
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
|
||||
with:
|
||||
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
|
||||
args: >
|
||||
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"
|
||||
|
||||
568
src/cpu/808x.c
568
src/cpu/808x.c
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,20 @@
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <fenv.h>
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
|
||||
# define X87_INLINE_ASM
|
||||
# endif
|
||||
#else
|
||||
# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__
|
||||
# define X87_INLINE_ASM
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef X87_INLINE_ASM
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#include "x87_timings.h"
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
@@ -38,7 +52,9 @@ extern void fpu_log(const char *fmt, ...);
|
||||
|
||||
extern double exp_pow_table[0x800];
|
||||
|
||||
#ifndef X87_INLINE_ASM
|
||||
static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO };
|
||||
#endif
|
||||
|
||||
#define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)]
|
||||
|
||||
@@ -64,16 +80,6 @@ typedef union {
|
||||
};
|
||||
} double_decompose_t;
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
|
||||
# define X87_INLINE_ASM
|
||||
# endif
|
||||
#else
|
||||
# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 || defined __amd64__
|
||||
# define X87_INLINE_ASM
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FPU_8087
|
||||
# define x87_div(dst, src1, src2) \
|
||||
do { \
|
||||
@@ -575,7 +581,7 @@ static int
|
||||
FPU_ILLEGAL_a16(UNUSED(uint32_t fetchdat))
|
||||
{
|
||||
geteaw();
|
||||
wait(timing_rr, 0);
|
||||
wait_cycs(timing_rr, 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
|
||||
#ifdef X87_INLINE_ASM
|
||||
static inline double float_add(double src, double val, int round)
|
||||
{
|
||||
int rounding_mode_orig;
|
||||
|
||||
__m128d xmm_src = _mm_load_sd(&src);
|
||||
__m128d xmm_dst = _mm_load_sd(&val);
|
||||
__m128d xmm_res;
|
||||
|
||||
rounding_mode_orig = _MM_GET_ROUNDING_MODE();
|
||||
if (round == 0) _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST);
|
||||
if (round == 1) _MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
|
||||
if (round == 2) _MM_SET_ROUNDING_MODE(_MM_ROUND_UP);
|
||||
if (round == 3) _MM_SET_ROUNDING_MODE(_MM_ROUND_TOWARD_ZERO);
|
||||
|
||||
xmm_res = _mm_add_sd(xmm_src, xmm_dst);
|
||||
|
||||
_MM_SET_ROUNDING_MODE(rounding_mode_orig);
|
||||
|
||||
return _mm_cvtsd_f64(xmm_res);
|
||||
}
|
||||
|
||||
#define DO_FADD(use_var) \
|
||||
do \
|
||||
{ \
|
||||
ST(0) = float_add(ST(0), use_var, (cpu_state.npxc >> 10) & 3); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
#define DO_FADD(use_var) \
|
||||
do \
|
||||
{ \
|
||||
if ((cpu_state.npxc >> 10) & 3) \
|
||||
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \
|
||||
ST(0) += use_var; \
|
||||
if ((cpu_state.npxc >> 10) & 3) \
|
||||
fesetround(FE_TONEAREST); \
|
||||
} \
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
#define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \
|
||||
static int opFADD##name##_a##a_size(UNUSED(uint32_t fetchdat)) \
|
||||
{ \
|
||||
@@ -8,11 +51,7 @@
|
||||
load_var = get(); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if ((cpu_state.npxc >> 10) & 3) \
|
||||
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \
|
||||
ST(0) += use_var; \
|
||||
if ((cpu_state.npxc >> 10) & 3) \
|
||||
fesetround(FE_TONEAREST); \
|
||||
DO_FADD(use_var); \
|
||||
FP_TAG_VALID; \
|
||||
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fadd##cycle_postfix) : ((x87_timings.fadd##cycle_postfix) * cpu_multi)); \
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fadd##cycle_postfix) : ((x87_concurrency.fadd##cycle_postfix) * cpu_multi)); \
|
||||
|
||||
@@ -7,7 +7,7 @@ opFI(uint32_t fetchdat)
|
||||
cpu_state.npxc &= ~0x80;
|
||||
if (rmdat == 0xe1)
|
||||
cpu_state.npxc |= 0x80;
|
||||
wait(3, 0);
|
||||
wait_cycs(3, 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -354,7 +354,7 @@ sf_FI(uint32_t fetchdat)
|
||||
fpu_state.cwd &= ~FPU_SW_Summary;
|
||||
if (rmdat == 0xe1)
|
||||
fpu_state.cwd |= FPU_SW_Summary;
|
||||
wait(3, 0);
|
||||
wait_cycs(3, 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Connor Hyde / starfrost, <mario64crashed@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2025 starfrost (refactoring)
|
||||
* Copyright 2025 starfrost (refactoring).
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_CGA_H
|
||||
@@ -24,8 +22,7 @@
|
||||
|
||||
// Mode flags for the CGA.
|
||||
// Set by writing to 3D8
|
||||
typedef enum cga_mode_flags_e
|
||||
{
|
||||
typedef enum cga_mode_flags_e {
|
||||
CGA_MODE_FLAG_HIGHRES = 1 << 0, // 80-column text mode
|
||||
CGA_MODE_FLAG_GRAPHICS = 1 << 1, // Graphics mode
|
||||
CGA_MODE_FLAG_BW = 1 << 2, // Black and white
|
||||
@@ -35,8 +32,7 @@ typedef enum cga_mode_flags_e
|
||||
} cga_mode_flags;
|
||||
|
||||
// Motorola MC6845 CRTC registers
|
||||
typedef enum cga_crtc_registers_e
|
||||
{
|
||||
typedef enum cga_crtc_registers_e {
|
||||
CGA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync)
|
||||
CGA_CRTC_HDISP = 0x1, // Horizontal display
|
||||
CGA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc
|
||||
@@ -58,8 +54,7 @@ typedef enum cga_crtc_registers_e
|
||||
} cga_crtc_registers;
|
||||
|
||||
// Registers for the CGA
|
||||
typedef enum cga_registers_e
|
||||
{
|
||||
typedef enum cga_registers_e {
|
||||
CGA_REGISTER_CRTC_INDEX = 0x3D4,
|
||||
CGA_REGISTER_CRTC_DATA = 0x3D5,
|
||||
CGA_REGISTER_MODE_CONTROL = 0x3D8,
|
||||
@@ -129,11 +124,11 @@ uint8_t cga_read(uint32_t addr, void *priv);
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
void cga_poll(void *priv);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_config_t cga_config[];
|
||||
|
||||
extern const device_t cga_device;
|
||||
extern const device_t cga_pravetz_device;
|
||||
#endif
|
||||
|
||||
//#ifdef EMU_DEVICE_H
|
||||
//extern const device_config_t cga_config[];
|
||||
//
|
||||
//extern const device_t cga_device;
|
||||
//extern const device_t cga_pravetz_device;
|
||||
//#endif
|
||||
//
|
||||
#endif /*VIDEO_CGA_H*/
|
||||
|
||||
93
src/include/86box/vid_quadcolor.h
Normal file
93
src/include/86box/vid_quadcolor.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Quadram Quadcolor I / I+II emulation
|
||||
*
|
||||
* Authors: Benedikt Freisen, <https://pcem-emulator.co.uk/>
|
||||
* Jasmine Iwanek, <jriwanek@gmail.com>
|
||||
*
|
||||
* Copyright 2024 Benedikt Freisen.
|
||||
Copyright 2025 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
#ifndef _VID_QUADCOLOR_H_
|
||||
#define _VID_QUADCOLOR_H_
|
||||
|
||||
typedef struct quadcolor_t {
|
||||
mem_mapping_t mapping;
|
||||
mem_mapping_t mapping_2;
|
||||
|
||||
int crtcreg;
|
||||
#if 0
|
||||
uint8_t crtc[CGA_NUM_CRTC_REGS];
|
||||
#else
|
||||
uint8_t crtc[32];
|
||||
#endif
|
||||
uint8_t cgastat;
|
||||
|
||||
uint8_t cgamode;
|
||||
uint8_t cgacol;
|
||||
|
||||
uint8_t lp_strobe;
|
||||
|
||||
uint8_t quadcolor_ctrl;
|
||||
uint8_t quadcolor_2_oe;
|
||||
uint16_t page_offset;
|
||||
|
||||
int fontbase;
|
||||
int linepos;
|
||||
int displine;
|
||||
int scanline;
|
||||
int vc;
|
||||
int cgadispon;
|
||||
int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE.
|
||||
int cursoron;
|
||||
int cgablink;
|
||||
int vsynctime;
|
||||
int vadj;
|
||||
uint16_t memaddr;
|
||||
uint16_t memaddr_backup;
|
||||
int oddeven;
|
||||
|
||||
int qc2idx;
|
||||
uint8_t qc2mask;
|
||||
|
||||
uint64_t dispontime;
|
||||
uint64_t dispofftime;
|
||||
pc_timer_t timer;
|
||||
|
||||
int firstline;
|
||||
int lastline;
|
||||
|
||||
int drawcursor;
|
||||
|
||||
int fullchange;
|
||||
|
||||
uint8_t *vram;
|
||||
uint8_t *vram_2;
|
||||
|
||||
uint8_t charbuffer[256];
|
||||
|
||||
int revision;
|
||||
int composite;
|
||||
int rgb_type;
|
||||
int double_type;
|
||||
|
||||
int has_2nd_charset;
|
||||
int has_quadcolor_2;
|
||||
} quadcolor_t;
|
||||
|
||||
void quadcolor_init(quadcolor_t *quadcolor);
|
||||
void quadcolor_out(uint16_t addr, uint8_t val, void *priv);
|
||||
uint8_t quadcolor_in(uint16_t addr, void *priv);
|
||||
void quadcolor_write(uint32_t addr, uint8_t val, void *priv);
|
||||
uint8_t quadcolor_read(uint32_t addr, void *priv);
|
||||
void quadcolor_recalctimings(quadcolor_t *quadcolor);
|
||||
void quadcolor_poll(void *priv);
|
||||
|
||||
#endif /* _VID_QUADCOLOR_H_ */
|
||||
@@ -30,6 +30,7 @@
|
||||
# define FLAG_S3_911_16BIT 256
|
||||
# define FLAG_512K_MASK 512
|
||||
# define FLAG_NO_SHIFT3 1024 /* Needed for Bochs VBE. */
|
||||
# define FLAG_PRECISETIME 2048 /* Needed for Copper demo if on dynarec. */
|
||||
struct monitor_t;
|
||||
|
||||
typedef struct hwcursor_t {
|
||||
@@ -137,6 +138,9 @@ typedef struct svga_t {
|
||||
int ps_bit_bug;
|
||||
int ati_4color;
|
||||
int vblankend;
|
||||
int panning_blank;
|
||||
int render_line_offset;
|
||||
int start_retrace_latch;
|
||||
|
||||
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
|
||||
0MB-1MB - VRAM
|
||||
|
||||
@@ -55,6 +55,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_4bpp_tseng_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);
|
||||
|
||||
@@ -399,6 +399,13 @@ extern const device_t gd5446_pci_device;
|
||||
extern const device_t gd5446_stb_pci_device;
|
||||
extern const device_t gd5480_pci_device;
|
||||
|
||||
|
||||
/* IBM CGA*/
|
||||
extern const device_t cga_device;
|
||||
|
||||
/* pravetz CGA */
|
||||
extern const device_t cga_pravetz_device;
|
||||
|
||||
/* Compaq CGA */
|
||||
extern const device_t compaq_cga_device;
|
||||
extern const device_t compaq_cga_2_device;
|
||||
@@ -491,6 +498,9 @@ extern const device_t paradise_wd90c11_megapc_device;
|
||||
extern const device_t paradise_wd90c11_device;
|
||||
extern const device_t paradise_wd90c30_device;
|
||||
|
||||
/* Quadram Quadcolor I / I + II */
|
||||
extern const device_t quadcolor_device;
|
||||
|
||||
/* Realtek (S)VGA */
|
||||
extern const device_t realtek_rtg3105_device;
|
||||
extern const device_t realtek_rtg3106_device;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <86box/serial.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -14730,7 +14730,7 @@ const machine_t machines[] = {
|
||||
.bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB,
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.min = 8192,
|
||||
.max = 1572864,
|
||||
.step = 8192
|
||||
},
|
||||
@@ -14770,7 +14770,7 @@ const machine_t machines[] = {
|
||||
.bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB,
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.min = 8192,
|
||||
.max = 1572864,
|
||||
.step = 8192
|
||||
},
|
||||
|
||||
@@ -790,20 +790,6 @@ main(int argc, char *argv[])
|
||||
main_window->installEventFilter(&manager_socket);
|
||||
}
|
||||
|
||||
/* Warn the user about unsupported configs */
|
||||
if (cpu_override) {
|
||||
QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("You are loading an unsupported configuration"),
|
||||
QObject::tr("CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."),
|
||||
QMessageBox::NoButton, main_window);
|
||||
warningbox.addButton(QObject::tr("Continue"), QMessageBox::AcceptRole);
|
||||
warningbox.addButton(QObject::tr("Exit"), QMessageBox::RejectRole);
|
||||
warningbox.exec();
|
||||
if (warningbox.result() == QDialog::Accepted) {
|
||||
confirm_exit_cmdl = 0; /* skip the confirmation prompt without touching the config */
|
||||
emit main_window->close();
|
||||
}
|
||||
}
|
||||
|
||||
// pc_reset_hard_init();
|
||||
|
||||
QTimer onesec;
|
||||
|
||||
@@ -102,10 +102,10 @@ UpdateDetails::visitDownloadPage(const UpdateCheck::UpdateChannel &channel)
|
||||
{
|
||||
switch (channel) {
|
||||
case UpdateCheck::UpdateChannel::Stable:
|
||||
QDesktopServices::openUrl(QUrl("https://ci.86box.net/job/86Box/lastSuccessfulBuild/artifact/"));
|
||||
break;
|
||||
case UpdateCheck::UpdateChannel::CI:
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/86Box/86Box/releases/latest"));
|
||||
break;
|
||||
break;
|
||||
case UpdateCheck::UpdateChannel::CI:
|
||||
QDesktopServices::openUrl(QUrl("https://ci.86box.net/job/86Box/lastSuccessfulBuild/artifact/"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,13 @@ NameAndLocationPage(QWidget *parent)
|
||||
{
|
||||
setTitle(tr("System name and location"));
|
||||
|
||||
dirValidate = QRegularExpression(R"(^[^\\/:*?"<>|\s]+$)");
|
||||
#if defined(_WIN32)
|
||||
dirValidate = QRegularExpression(R"(^[^\\/:*?"<>|]+$)");
|
||||
#elif defined(__APPLE__)
|
||||
dirValidate = QRegularExpression(R"(^[^/:]+$)");
|
||||
#else
|
||||
dirValidate = QRegularExpression(R"(^[^/]+$)");
|
||||
#endif
|
||||
|
||||
const auto topLabel = new QLabel(tr("Enter the name of the system and choose the location"));
|
||||
topLabel->setWordWrap(true);
|
||||
@@ -282,7 +288,7 @@ NameAndLocationPage::isComplete() const
|
||||
if (systemName->text().isEmpty()) {
|
||||
systemNameValidation->setText(tr("Please enter a system name"));
|
||||
} else if (!systemName->text().contains(dirValidate)) {
|
||||
systemNameValidation->setText(tr("System name cannot contain a space or certain characters"));
|
||||
systemNameValidation->setText(tr("System name cannot contain certain characters"));
|
||||
} else if (const QDir newDir = QDir::cleanPath(systemLocation->text() + "/" + systemName->text()); newDir.exists()) {
|
||||
systemNameValidation->setText(tr("System name already exists"));
|
||||
} else {
|
||||
|
||||
@@ -72,10 +72,6 @@ VMManagerMain::VMManagerMain(QWidget *parent) :
|
||||
}
|
||||
});
|
||||
|
||||
QAction convertToP3(tr("Convert system to PIII"));
|
||||
contextMenu.addAction(&convertToP3);
|
||||
convertToP3.setEnabled(false);
|
||||
|
||||
QAction setSystemIcon(tr("Set icon"));
|
||||
contextMenu.addAction(&setSystemIcon);
|
||||
connect(&setSystemIcon, &QAction::triggered, [this] {
|
||||
@@ -460,6 +456,7 @@ VMManagerMain::onPreferencesUpdated()
|
||||
void
|
||||
VMManagerMain::backgroundUpdateCheckStart() const
|
||||
{
|
||||
#if EMU_BUILD_NUM != 0
|
||||
auto updateChannel = UpdateCheck::UpdateChannel::CI;
|
||||
#ifdef RELEASE_BUILD
|
||||
updateChannel = UpdateCheck::UpdateChannel::Stable;
|
||||
@@ -468,6 +465,7 @@ VMManagerMain::backgroundUpdateCheckStart() const
|
||||
connect(updateCheck, &UpdateCheck::updateCheckComplete, this, &VMManagerMain::backgroundUpdateCheckComplete);
|
||||
connect(updateCheck, &UpdateCheck::updateCheckError, this, &VMManagerMain::backgroundUpdateCheckError);
|
||||
updateCheck->checkForUpdates();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -48,8 +48,13 @@ VMManagerMainWindow(QWidget *parent)
|
||||
connect(ui->actionNew_Machine, &QAction::triggered, vmm, &VMManagerMain::newMachineWizard);
|
||||
|
||||
// Set up menu actions
|
||||
connect(ui->actionCheck_for_updates, &QAction::triggered, this, &VMManagerMainWindow::checkForUpdatesTriggered);
|
||||
|
||||
// (Disable this if the EMU_BUILD_NUM == 0)
|
||||
#if EMU_BUILD_NUM == 0
|
||||
ui->actionCheck_for_updates->setVisible(false);
|
||||
#else
|
||||
connect(ui->actionCheck_for_updates, &QAction::triggered, this, &VMManagerMainWindow::checkForUpdatesTriggered);
|
||||
#endif
|
||||
|
||||
// TODO: Remove all of this (all the way to END REMOVE) once certain the search will no longer be in the toolbar.
|
||||
// BEGIN REMOVE
|
||||
// Everything is still setup here for it but it is all hidden. None of it will be
|
||||
|
||||
@@ -55,8 +55,9 @@ add_library(vid OBJECT
|
||||
vid_cga_colorplus.c
|
||||
vid_cga_ncr.c
|
||||
vid_cga_olivetti.c
|
||||
vid_cga_toshiba_t1000.c
|
||||
vid_cga_toshiba_t3100e.c
|
||||
vid_cga_quadcolor.c
|
||||
vid_cga_toshiba_t1000.c
|
||||
vid_cga_toshiba_t3100e.c
|
||||
|
||||
# PCJr/Tandy
|
||||
vid_pcjr.c
|
||||
|
||||
@@ -3819,7 +3819,7 @@ ibm8514_recalctimings(svga_t *svga)
|
||||
} else {
|
||||
if (dev->on) {
|
||||
dev->hdisp = (dev->hdisped + 1) << 3;
|
||||
dev->h_total = (dev->htotal + 1) << 3;
|
||||
dev->h_total = dev->htotal + 1;
|
||||
|
||||
if (dev->h_total == 1) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/
|
||||
dev->h_total = 0x9e;
|
||||
@@ -3854,6 +3854,7 @@ ibm8514_recalctimings(svga_t *svga)
|
||||
|
||||
dev->h_disp = dev->hdisp;
|
||||
dev->dispend = dev->vdisp;
|
||||
dev->h_disp_time = dev->hdisp >> 3;
|
||||
|
||||
if (dev->accel.advfunc_cntl & 0x04)
|
||||
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
|
||||
|
||||
@@ -2707,9 +2707,9 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
|
||||
{
|
||||
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
|
||||
|
||||
dev->h_total = (dev->htotal + 1) << 3;
|
||||
dev->h_total = (dev->htotal + 1);
|
||||
if (dev->h_total == 8) /*Default to 1024x768 87hz 8514/A htotal timings if it goes to 0.*/
|
||||
dev->h_total = 0x9e << 3;
|
||||
dev->h_total = 0x9e;
|
||||
|
||||
dev->hdisp = (dev->hdisped + 1) << 3;
|
||||
|
||||
@@ -2730,7 +2730,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
|
||||
switch (mach->shadow_set & 0x03) {
|
||||
case 0x01:
|
||||
if (!(dev->accel.advfunc_cntl & 0x04)) {
|
||||
dev->h_total = 0x64 << 3;
|
||||
dev->h_total = 0x64;
|
||||
dev->hdisp = 640;
|
||||
dev->vdisp = 480;
|
||||
dev->v_total = 0x0419;
|
||||
@@ -2739,7 +2739,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
|
||||
break;
|
||||
case 0x02:
|
||||
if (dev->accel.advfunc_cntl & 0x04) {
|
||||
dev->h_total = 0x9e << 3;
|
||||
dev->h_total = 0x9e;
|
||||
dev->hdisp = 1024;
|
||||
dev->vdisp = 768;
|
||||
dev->v_total = 0x0669;
|
||||
@@ -2754,7 +2754,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
|
||||
} else if ((dev->disp_cntl >> 5) == 2) { /*Reset 8514/A to defaults if needed.*/
|
||||
if (dev->accel.advfunc_cntl & 0x04) {
|
||||
if (dev->hdisp == 640) {
|
||||
dev->h_total = 0x9e << 3;
|
||||
dev->h_total = 0x9e;
|
||||
dev->hdisp = 1024;
|
||||
dev->vdisp = 768;
|
||||
dev->v_total = 0x0669;
|
||||
@@ -2763,7 +2763,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
|
||||
}
|
||||
} else {
|
||||
if (dev->hdisp == 1024) {
|
||||
dev->h_total = 0x64 << 3;
|
||||
dev->h_total = 0x64;
|
||||
dev->hdisp = 640;
|
||||
dev->vdisp = 480;
|
||||
dev->v_total = 0x0419;
|
||||
@@ -2926,6 +2926,8 @@ mach_recalctimings(svga_t *svga)
|
||||
else if (dev->h_disp == 640)
|
||||
dev->dispend = 480;
|
||||
|
||||
dev->h_disp_time = dev->hdisp >> 3;
|
||||
|
||||
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen);
|
||||
if (mach->accel.clock_sel & 0x40)
|
||||
svga->clock_8514 *= 2;
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* W. M. Martinez, <anikom15@outlook.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2023 W. M. Martinez
|
||||
* Copyright 2023 W. M. Martinez
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -284,7 +282,7 @@ cga_render(cga_t *cga, int line)
|
||||
buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16;
|
||||
}
|
||||
}
|
||||
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
|
||||
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) { /* 80-column text */
|
||||
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
|
||||
chr = cga->charbuffer[x << 1];
|
||||
@@ -342,7 +340,7 @@ cga_render(cga_t *cga, int line)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
|
||||
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { /* not hi-res (but graphics) => 4-color mode */
|
||||
cols[0] = (cga->cgacol & 15) | 16;
|
||||
col = (cga->cgacol & 16) ? 24 : 16;
|
||||
if (cga->cgamode & CGA_MODE_FLAG_BW) {
|
||||
@@ -372,7 +370,7 @@ cga_render(cga_t *cga, int line)
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else { /* 2-color hi-res graphics mode */
|
||||
cols[0] = 0;
|
||||
cols[1] = (cga->cgacol & 15) + 16;
|
||||
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
@@ -500,7 +498,7 @@ cga_interpolate(cga_t *cga, int x, int y, int w, int h)
|
||||
|
||||
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);
|
||||
final = cga_interpolate_lookup(cga, interim_1, interim_2, quotient);
|
||||
|
||||
buffer32->line[i][j] = final.color;
|
||||
}
|
||||
@@ -746,9 +744,8 @@ void *
|
||||
cga_standalone_init(UNUSED(const device_t *info))
|
||||
{
|
||||
int display_type;
|
||||
cga_t *cga = malloc(sizeof(cga_t));
|
||||
cga_t *cga = calloc(1, sizeof(cga_t));
|
||||
|
||||
memset(cga, 0, sizeof(cga_t));
|
||||
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_cga);
|
||||
|
||||
display_type = device_get_config_int("display_type");
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/vid_cga.h>
|
||||
extern const device_config_t cga_config[]; /* defined in vid_cga.c */
|
||||
#include <86box/vid_ogc.h>
|
||||
#include <86box/vid_cga_comp.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
981
src/video/vid_cga_quadcolor.c
Normal file
981
src/video/vid_cga_quadcolor.c
Normal file
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Quadram Quadcolor I / I+II emulation
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* W. M. Martinez, <anikom15@outlook.com>
|
||||
* Benedikt Freisen, <https://pcem-emulator.co.uk/>
|
||||
* Jasmine Iwanek, <jriwanek@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2023 W. M. Martinez
|
||||
* Copyright 2024 Benedikt Freisen.
|
||||
* Copyright 2025 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
/* This has been derived from CGA emulation */
|
||||
/* omissions: simulated snow (Quadcolor has dual-ported RAM), single and dual 8x16 font configuration */
|
||||
/* additions: ports 0x3dd and 0x3de, 2nd char set, 2nd VRAM bank, hi-res bg color, Quadcolor II memory and mode */
|
||||
/* assumptions: MA line 12 XORed with Bank Select, hi-res bg is also border color, QC2 mode has simple address counter */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/vid_quadcolor.h>
|
||||
#include <86box/vid_cga_comp.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
#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
|
||||
|
||||
#define DEVICE_VRAM 0x8000
|
||||
#define DEVICE_VRAM_MASK 0x7fff
|
||||
|
||||
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_quadcolor = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
|
||||
void quadcolor_recalctimings(quadcolor_t *quadcolor);
|
||||
|
||||
static void
|
||||
quadcolor_update_latch(quadcolor_t *quadcolor)
|
||||
{
|
||||
uint32_t lp_latch = quadcolor->displine * quadcolor->crtc[CGA_CRTC_HDISP];
|
||||
|
||||
quadcolor->crtc[CGA_CRTC_LIGHT_PEN_ADDR_HIGH] = (lp_latch >> 8) & 0x3f;
|
||||
quadcolor->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff;
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_out(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
uint8_t old;
|
||||
|
||||
if ((addr >= 0x3d0) && (addr <= 0x3d7))
|
||||
addr = (addr & 0xff9) | 0x004;
|
||||
|
||||
switch (addr) {
|
||||
case CGA_REGISTER_CRTC_INDEX:
|
||||
quadcolor->crtcreg = val & 31;
|
||||
return;
|
||||
case CGA_REGISTER_CRTC_DATA:
|
||||
old = quadcolor->crtc[quadcolor->crtcreg];
|
||||
quadcolor->crtc[quadcolor->crtcreg] = val & crtcmask[quadcolor->crtcreg];
|
||||
if (old != val) {
|
||||
// Recalc the timings if we are writing any invalid CRTC register or a valid CRTC register
|
||||
// except the CURSOR and LIGHT PEN registers
|
||||
if ((quadcolor->crtcreg < 0xe) || (quadcolor->crtcreg > 0x11)) {
|
||||
quadcolor->fullchange = changeframecount;
|
||||
quadcolor_recalctimings(quadcolor);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case CGA_REGISTER_MODE_CONTROL:
|
||||
old = quadcolor->cgamode;
|
||||
quadcolor->cgamode = val;
|
||||
|
||||
if (old ^ val) {
|
||||
if ((old ^ val) & 0x07)
|
||||
update_cga16_color(val);
|
||||
|
||||
quadcolor_recalctimings(quadcolor);
|
||||
}
|
||||
return;
|
||||
case CGA_REGISTER_COLOR_SELECT:
|
||||
old = quadcolor->cgacol;
|
||||
quadcolor->cgacol = val;
|
||||
if (old ^ val)
|
||||
quadcolor_recalctimings(quadcolor);
|
||||
return;
|
||||
|
||||
case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH:
|
||||
if (quadcolor->lp_strobe == 1)
|
||||
quadcolor->lp_strobe = 0;
|
||||
return;
|
||||
case CGA_REGISTER_SET_LIGHT_PEN_LATCH:
|
||||
if (quadcolor->lp_strobe == 0) {
|
||||
quadcolor->lp_strobe = 1;
|
||||
quadcolor_update_latch(quadcolor);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x3dd:
|
||||
quadcolor->quadcolor_ctrl = val & 0x3f;
|
||||
/* helper variable that can be XORed onto the VRAM address to select the page to display */
|
||||
quadcolor->page_offset = (val & 0x10) << 8;
|
||||
/* in dual 8x8 font configuration, use fontbase 256 if "Character Set Select" bit is set */
|
||||
if (quadcolor->has_2nd_charset)
|
||||
quadcolor->fontbase = (val & 0x20) << 3;
|
||||
return;
|
||||
case 0x3de:
|
||||
/* NOTE: the polarity of this register is the opposite of what the manual says */
|
||||
if (quadcolor->has_quadcolor_2)
|
||||
quadcolor->quadcolor_2_oe = !(val & 0x10);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
quadcolor_in(uint16_t addr, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if ((addr >= 0x3d0) && (addr <= 0x3d7))
|
||||
addr = (addr & 0xff9) | 0x004;
|
||||
|
||||
switch (addr) {
|
||||
case CGA_REGISTER_CRTC_INDEX:
|
||||
ret = quadcolor->crtcreg;
|
||||
break;
|
||||
case CGA_REGISTER_CRTC_DATA:
|
||||
ret = quadcolor->crtc[quadcolor->crtcreg];
|
||||
break;
|
||||
case CGA_REGISTER_STATUS:
|
||||
ret = quadcolor->cgastat;
|
||||
break;
|
||||
case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH:
|
||||
if (quadcolor->lp_strobe == 1)
|
||||
quadcolor->lp_strobe = 0;
|
||||
break;
|
||||
case CGA_REGISTER_SET_LIGHT_PEN_LATCH:
|
||||
if (quadcolor->lp_strobe == 0) {
|
||||
quadcolor->lp_strobe = 1;
|
||||
quadcolor_update_latch(quadcolor);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_waitstates(UNUSED(void *priv))
|
||||
{
|
||||
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
|
||||
int ws;
|
||||
|
||||
ws = ws_array[cycles & 0xf];
|
||||
cycles -= ws;
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
|
||||
quadcolor->vram[addr & DEVICE_VRAM_MASK] = val;
|
||||
quadcolor_waitstates(quadcolor);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
quadcolor_read(uint32_t addr, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
|
||||
quadcolor_waitstates(quadcolor);
|
||||
return quadcolor->vram[addr & DEVICE_VRAM_MASK];
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_2_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
quadcolor->vram_2[addr & 0xffff] = val;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
quadcolor_2_read(uint32_t addr, void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
return quadcolor->vram_2[addr & 0xffff];
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_recalctimings(quadcolor_t *quadcolor)
|
||||
{
|
||||
double disptime;
|
||||
double _dispontime;
|
||||
double _dispofftime;
|
||||
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) {
|
||||
disptime = (double) (quadcolor->crtc[CGA_CRTC_HTOTAL] + 1);
|
||||
_dispontime = (double) quadcolor->crtc[CGA_CRTC_HDISP];
|
||||
} else {
|
||||
disptime = (double) ((quadcolor->crtc[CGA_CRTC_HTOTAL] + 1) << 1);
|
||||
_dispontime = (double) (quadcolor->crtc[CGA_CRTC_HDISP] << 1);
|
||||
}
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime = _dispontime * CGACONST;
|
||||
_dispofftime = _dispofftime * CGACONST;
|
||||
quadcolor->dispontime = (uint64_t) (_dispontime);
|
||||
quadcolor->dispofftime = (uint64_t) (_dispofftime);
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
get_next_qc2_pixel(quadcolor_t *quadcolor)
|
||||
{
|
||||
uint8_t mask = quadcolor->qc2mask;
|
||||
quadcolor->qc2mask = ~quadcolor->qc2mask;
|
||||
uint8_t pixel = (quadcolor->vram_2[quadcolor->qc2idx] & mask) >> (quadcolor->qc2mask & 4);
|
||||
|
||||
quadcolor->qc2idx += quadcolor->qc2mask >> 7;
|
||||
|
||||
return quadcolor->quadcolor_2_oe ? pixel : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
quadcolor_render(quadcolor_t *quadcolor, int line)
|
||||
{
|
||||
uint16_t cursoraddr = (quadcolor->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (quadcolor->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & DEVICE_VRAM_MASK;
|
||||
int drawcursor;
|
||||
int x;
|
||||
int column;
|
||||
uint8_t chr;
|
||||
uint8_t attr;
|
||||
uint16_t dat;
|
||||
int cols[4];
|
||||
int col;
|
||||
|
||||
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
|
||||
|
||||
if (((quadcolor->cgamode & highres_graphics_flag) == highres_graphics_flag)) {
|
||||
for (column = 0; column < 8; ++column) {
|
||||
buffer32->line[line][column] = 0;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 8] = (quadcolor->quadcolor_ctrl & 15); /* TODO: Is Quadcolor bg color actually relevant, here? */
|
||||
else
|
||||
buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 8] = (quadcolor->quadcolor_ctrl & 15); /* TODO: Is Quadcolor bg color actually relevant, here? */
|
||||
}
|
||||
} else {
|
||||
for (column = 0; column < 8; ++column) {
|
||||
buffer32->line[line][column] = (quadcolor->cgacol & 15) + 16;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 8] = (quadcolor->cgacol & 15) + 16;
|
||||
else
|
||||
buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 8] = (quadcolor->cgacol & 15) + 16;
|
||||
}
|
||||
}
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) { /* 80-column text */
|
||||
for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
|
||||
chr = quadcolor->charbuffer[x << 1];
|
||||
attr = quadcolor->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((quadcolor->memaddr == cursoraddr) && quadcolor->cursorvisible && quadcolor->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((quadcolor->cgablink & 8) && (attr & 0x80) && !quadcolor->drawcursor)
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
if (drawcursor) {
|
||||
for (column = 0; column < 8; column++) {
|
||||
buffer32->line[line][(x << 3) + column + 8]
|
||||
= (cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15) | get_next_qc2_pixel(quadcolor);
|
||||
}
|
||||
} else {
|
||||
for (column = 0; column < 8; column++) {
|
||||
buffer32->line[line][(x << 3) + column + 8]
|
||||
= cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] | get_next_qc2_pixel(quadcolor);
|
||||
}
|
||||
}
|
||||
quadcolor->memaddr++;
|
||||
}
|
||||
} else if (!(quadcolor->cgamode & CGA_MODE_FLAG_GRAPHICS)) { /* not graphics (nor 80-column text) => 40-column text */
|
||||
for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
|
||||
chr = quadcolor->vram[(quadcolor->page_offset ^ (quadcolor->memaddr << 1)) & DEVICE_VRAM_MASK];
|
||||
attr = quadcolor->vram[(quadcolor->page_offset ^ ((quadcolor->memaddr << 1) + 1)) & DEVICE_VRAM_MASK];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((quadcolor->memaddr == cursoraddr) && quadcolor->cursorvisible && quadcolor->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
if ((quadcolor->cgablink & 8) && (attr & 0x80))
|
||||
cols[1] = cols[0];
|
||||
} else
|
||||
cols[0] = (attr >> 4) + 16;
|
||||
quadcolor->memaddr++;
|
||||
if (drawcursor) {
|
||||
for (column = 0; column < 8; column++) {
|
||||
dat = (cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15);
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 8] = dat | get_next_qc2_pixel(quadcolor);
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 9] = dat | get_next_qc2_pixel(quadcolor);
|
||||
|
||||
}
|
||||
} else {
|
||||
for (column = 0; column < 8; column++) {
|
||||
dat = cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0];
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 8] = dat | get_next_qc2_pixel(quadcolor);
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 9] = dat | get_next_qc2_pixel(quadcolor);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!(quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { /* not hi-res (but graphics) => 4-color mode */
|
||||
cols[0] = (quadcolor->cgacol & 15) | 16;
|
||||
col = (quadcolor->cgacol & 16) ? 24 : 16;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_BW) {
|
||||
cols[1] = col | 3; /* Cyan */
|
||||
cols[2] = col | 4; /* Red */
|
||||
cols[3] = col | 7; /* White */
|
||||
} else if (quadcolor->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 < quadcolor->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)
|
||||
dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000))] << 8) |
|
||||
quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000) + 1)];
|
||||
else
|
||||
dat = 0;
|
||||
quadcolor->memaddr++;
|
||||
for (column = 0; column < 8; column++) {
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 8] = cols[dat >> 14] | get_next_qc2_pixel(quadcolor);
|
||||
buffer32->line[line][(x << 4) + (column << 1) + 9] = cols[dat >> 14] | get_next_qc2_pixel(quadcolor);
|
||||
dat <<= 2;
|
||||
}
|
||||
}
|
||||
} else { /* 2-color hi-res graphics mode */
|
||||
cols[0] = quadcolor->quadcolor_ctrl & 15; /* background color (Quadcolor-specific) */;
|
||||
cols[1] = (quadcolor->cgacol & 15) + 16;
|
||||
for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) /* video enabled */
|
||||
dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000))] << 8) |
|
||||
quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000) + 1)];
|
||||
else
|
||||
dat = quadcolor->quadcolor_ctrl & 15; /* TODO: Is Quadcolor bg color actually relevant, here? Probably. See QC2 manual p.46 1. */;
|
||||
quadcolor->memaddr++;
|
||||
for (column = 0; column < 16; column++) {
|
||||
buffer32->line[line][(x << 4) + column + 8] = cols[dat >> 15] | get_next_qc2_pixel(quadcolor);
|
||||
dat <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
quadcolor_render_blank(quadcolor_t *quadcolor, int line)
|
||||
{
|
||||
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
|
||||
|
||||
/* `+ 16` isn't in PCem's version */
|
||||
int col = ((quadcolor->cgamode & highres_graphics_flag) == highres_graphics_flag) ? (quadcolor->quadcolor_ctrl & 15) + 16 : (quadcolor->cgacol & 15) + 16; /* TODO: Is Quadcolor bg color actually relevant, here? */
|
||||
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
hline(buffer32, 0, line, (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 16, col);
|
||||
else
|
||||
hline(buffer32, 0, line, (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 16, col);
|
||||
}
|
||||
|
||||
static void
|
||||
quadcolor_render_process(quadcolor_t *quadcolor, int line)
|
||||
{
|
||||
int x;
|
||||
uint8_t border;
|
||||
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
|
||||
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
x = (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 16;
|
||||
else
|
||||
x = (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 16;
|
||||
|
||||
if (quadcolor->composite) {
|
||||
border = ((quadcolor->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (quadcolor->cgacol & 15);
|
||||
|
||||
Composite_Process(quadcolor->cgamode, border, x >> 2, buffer32->line[line]);
|
||||
} else
|
||||
video_process_8(x, line);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
quadcolor_interpolate_srgb(uint8_t co1, uint8_t co2, double fraction)
|
||||
{
|
||||
uint8_t ret = ((co2 - co1) * fraction + co1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
quadcolor_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) round(r2 * 255.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static color_t
|
||||
quadcolor_interpolate_lookup(quadcolor_t *quadcolor, color_t color1, color_t color2, UNUSED(double fraction))
|
||||
{
|
||||
color_t ret;
|
||||
uint8_t dt = quadcolor->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
|
||||
quadcolor_interpolate(quadcolor_t *quadcolor, 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 = quadcolor_interpolate_lookup(quadcolor, prev_color, black, quotient);
|
||||
interim_2 = quadcolor_interpolate_lookup(quadcolor, black, next_color, quotient);
|
||||
final = quadcolor_interpolate_lookup(quadcolor, interim_1, interim_2, quotient);
|
||||
|
||||
buffer32->line[i][j] = final.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
quadcolor_blit_memtoscreen(quadcolor_t *quadcolor, int x, int y, int w, int h)
|
||||
{
|
||||
if (quadcolor->double_type > DOUBLE_SIMPLE)
|
||||
quadcolor_interpolate(quadcolor, x, y, w, h);
|
||||
|
||||
video_blit_memtoscreen(x, y, w, h);
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_poll(void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
int x;
|
||||
int scanline_old;
|
||||
int oldvc;
|
||||
int xs_temp;
|
||||
int ys_temp;
|
||||
int old_ma;
|
||||
|
||||
if (!quadcolor->linepos) {
|
||||
timer_advance_u64(&quadcolor->timer, quadcolor->dispofftime);
|
||||
quadcolor->cgastat |= 1;
|
||||
quadcolor->linepos = 1;
|
||||
scanline_old = quadcolor->scanline;
|
||||
if ((quadcolor->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
quadcolor->scanline = ((quadcolor->scanline << 1) + quadcolor->oddeven) & 7;
|
||||
if (quadcolor->cgadispon) {
|
||||
if (quadcolor->displine < quadcolor->firstline) {
|
||||
quadcolor->firstline = quadcolor->displine;
|
||||
video_wait_for_buffer();
|
||||
}
|
||||
quadcolor->lastline = quadcolor->displine;
|
||||
switch (quadcolor->double_type) {
|
||||
default:
|
||||
quadcolor_render(quadcolor, quadcolor->displine << 1);
|
||||
quadcolor_render_blank(quadcolor, (quadcolor->displine << 1) + 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
quadcolor_render(quadcolor, quadcolor->displine);
|
||||
break;
|
||||
case DOUBLE_SIMPLE:
|
||||
old_ma = quadcolor->memaddr;
|
||||
quadcolor_render(quadcolor, quadcolor->displine << 1);
|
||||
quadcolor->memaddr = old_ma;
|
||||
quadcolor_render(quadcolor, (quadcolor->displine << 1) + 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (quadcolor->double_type) {
|
||||
default:
|
||||
quadcolor_render_blank(quadcolor, quadcolor->displine << 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
quadcolor_render_blank(quadcolor, quadcolor->displine);
|
||||
break;
|
||||
case DOUBLE_SIMPLE:
|
||||
quadcolor_render_blank(quadcolor, quadcolor->displine << 1);
|
||||
quadcolor_render_blank(quadcolor, (quadcolor->displine << 1) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (quadcolor->double_type) {
|
||||
default:
|
||||
quadcolor_render_process(quadcolor, quadcolor->displine << 1);
|
||||
quadcolor_render_process(quadcolor, (quadcolor->displine << 1) + 1);
|
||||
break;
|
||||
case DOUBLE_NONE:
|
||||
quadcolor_render_process(quadcolor, quadcolor->displine);
|
||||
break;
|
||||
}
|
||||
|
||||
quadcolor->scanline = scanline_old;
|
||||
if (quadcolor->vc == quadcolor->crtc[CGA_CRTC_VSYNC] && !quadcolor->scanline)
|
||||
quadcolor->cgastat |= 8;
|
||||
quadcolor->displine++;
|
||||
if (quadcolor->displine >= 360)
|
||||
quadcolor->displine = 0;
|
||||
} else {
|
||||
timer_advance_u64(&quadcolor->timer, quadcolor->dispontime);
|
||||
quadcolor->linepos = 0;
|
||||
if (quadcolor->vsynctime) {
|
||||
quadcolor->vsynctime--;
|
||||
if (!quadcolor->vsynctime)
|
||||
quadcolor->cgastat &= ~8;
|
||||
quadcolor->qc2idx = 0;
|
||||
quadcolor->qc2mask = 0xf0;
|
||||
}
|
||||
if (quadcolor->scanline == (quadcolor->crtc[CGA_CRTC_CURSOR_END] & 31) || ((quadcolor->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
|
||||
quadcolor->scanline == ((quadcolor->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
|
||||
quadcolor->cursorvisible = 0;
|
||||
}
|
||||
if ((quadcolor->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && quadcolor->scanline == (quadcolor->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
quadcolor->memaddr_backup = quadcolor->memaddr;
|
||||
if (quadcolor->vadj) {
|
||||
quadcolor->scanline++;
|
||||
quadcolor->scanline &= 31;
|
||||
quadcolor->memaddr = quadcolor->memaddr_backup;
|
||||
quadcolor->vadj--;
|
||||
if (!quadcolor->vadj) {
|
||||
quadcolor->cgadispon = 1;
|
||||
quadcolor->memaddr = quadcolor->memaddr_backup = (quadcolor->crtc[CGA_CRTC_START_ADDR_LOW] | (quadcolor->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & DEVICE_VRAM_MASK;
|
||||
quadcolor->scanline = 0;
|
||||
}
|
||||
} else if (quadcolor->scanline == quadcolor->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
|
||||
quadcolor->memaddr_backup = quadcolor->memaddr;
|
||||
quadcolor->scanline = 0;
|
||||
oldvc = quadcolor->vc;
|
||||
quadcolor->vc++;
|
||||
quadcolor->vc &= 127;
|
||||
|
||||
if (quadcolor->vc == quadcolor->crtc[CGA_CRTC_VDISP])
|
||||
quadcolor->cgadispon = 0;
|
||||
|
||||
if (oldvc == quadcolor->crtc[CGA_CRTC_VTOTAL]) {
|
||||
quadcolor->vc = 0;
|
||||
quadcolor->vadj = quadcolor->crtc[CGA_CRTC_VTOTAL_ADJUST];
|
||||
if (!quadcolor->vadj) {
|
||||
quadcolor->cgadispon = 1;
|
||||
quadcolor->memaddr = quadcolor->memaddr_backup = (quadcolor->crtc[CGA_CRTC_START_ADDR_LOW] | (quadcolor->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & DEVICE_VRAM_MASK;
|
||||
}
|
||||
|
||||
switch (quadcolor->crtc[CGA_CRTC_CURSOR_START] & 0x60) {
|
||||
case 0x20:
|
||||
quadcolor->cursoron = 0;
|
||||
break;
|
||||
case 0x60:
|
||||
quadcolor->cursoron = quadcolor->cgablink & 0x10;
|
||||
break;
|
||||
default:
|
||||
quadcolor->cursoron = quadcolor->cgablink & 0x08;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (quadcolor->vc == quadcolor->crtc[CGA_CRTC_VSYNC]) {
|
||||
quadcolor->cgadispon = 0;
|
||||
quadcolor->displine = 0;
|
||||
quadcolor->vsynctime = 16;
|
||||
if (quadcolor->crtc[CGA_CRTC_VSYNC]) {
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
x = (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 16;
|
||||
else
|
||||
x = (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 16;
|
||||
quadcolor->lastline++;
|
||||
|
||||
xs_temp = x;
|
||||
ys_temp = quadcolor->lastline - quadcolor->firstline;
|
||||
if (quadcolor->double_type > DOUBLE_NONE)
|
||||
ys_temp <<= 1;
|
||||
|
||||
if ((xs_temp > 0) && (ys_temp > 0)) {
|
||||
if (xs_temp < 64)
|
||||
xs_temp = 656;
|
||||
if (ys_temp < 32)
|
||||
ys_temp = 200;
|
||||
if (!enable_overscan)
|
||||
xs_temp -= 16;
|
||||
|
||||
if ((quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) ||
|
||||
(ys_temp != ysize) || video_force_resize_get())) {
|
||||
xsize = xs_temp;
|
||||
ysize = ys_temp;
|
||||
if (quadcolor->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 (quadcolor->double_type > DOUBLE_NONE) {
|
||||
if (enable_overscan)
|
||||
quadcolor_blit_memtoscreen(quadcolor, 0, (quadcolor->firstline - 4) << 1,
|
||||
xsize, ((quadcolor->lastline - quadcolor->firstline) << 1) + 16);
|
||||
else
|
||||
quadcolor_blit_memtoscreen(quadcolor, 8, quadcolor->firstline << 1,
|
||||
xsize, (quadcolor->lastline - quadcolor->firstline) << 1);
|
||||
} else {
|
||||
if (enable_overscan)
|
||||
video_blit_memtoscreen(0, quadcolor->firstline - 4,
|
||||
xsize, (quadcolor->lastline - quadcolor->firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen(8, quadcolor->firstline,
|
||||
xsize, quadcolor->lastline - quadcolor->firstline);
|
||||
}
|
||||
}
|
||||
|
||||
frames++;
|
||||
|
||||
video_res_x = xsize;
|
||||
video_res_y = ysize;
|
||||
if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) {
|
||||
video_res_x /= 8;
|
||||
video_res_y /= quadcolor->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
|
||||
video_bpp = 0;
|
||||
} else if (!(quadcolor->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
|
||||
video_res_x /= 16;
|
||||
video_res_y /= quadcolor->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
|
||||
video_bpp = 0;
|
||||
} else if (!(quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
|
||||
video_res_x /= 2;
|
||||
video_bpp = 2;
|
||||
} else
|
||||
video_bpp = 1;
|
||||
}
|
||||
quadcolor->firstline = 1000;
|
||||
quadcolor->lastline = 0;
|
||||
quadcolor->cgablink++;
|
||||
quadcolor->oddeven ^= 1;
|
||||
}
|
||||
} else {
|
||||
quadcolor->scanline++;
|
||||
quadcolor->scanline &= 31;
|
||||
quadcolor->memaddr = quadcolor->memaddr_backup;
|
||||
}
|
||||
if (quadcolor->cgadispon)
|
||||
quadcolor->cgastat &= ~1;
|
||||
if (quadcolor->scanline == (quadcolor->crtc[CGA_CRTC_CURSOR_START] & 31) || ((quadcolor->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
|
||||
quadcolor->scanline == ((quadcolor->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
|
||||
quadcolor->cursorvisible = 1;
|
||||
if (quadcolor->cgadispon && (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES)) {
|
||||
for (x = 0; x < (quadcolor->crtc[CGA_CRTC_HDISP] << 1); x++)
|
||||
quadcolor->charbuffer[x] = quadcolor->vram[(quadcolor->page_offset ^ ((quadcolor->memaddr << 1) + x)) & DEVICE_VRAM_MASK];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_init(quadcolor_t *quadcolor)
|
||||
{
|
||||
timer_add(&quadcolor->timer, quadcolor_poll, quadcolor, 1);
|
||||
quadcolor->composite = 0;
|
||||
}
|
||||
|
||||
void *
|
||||
quadcolor_standalone_init(UNUSED(const device_t *info))
|
||||
{
|
||||
int display_type;
|
||||
quadcolor_t *quadcolor = calloc(1, sizeof(quadcolor_t));
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_quadcolor);
|
||||
|
||||
display_type = device_get_config_int("display_type");
|
||||
quadcolor->composite = (display_type != CGA_RGB);
|
||||
quadcolor->revision = device_get_config_int("composite_type");
|
||||
quadcolor->has_2nd_charset = device_get_config_int("has_2nd_charset");
|
||||
quadcolor->has_quadcolor_2 = device_get_config_int("has_quadcolor_2");
|
||||
|
||||
quadcolor->vram = malloc(DEVICE_VRAM);
|
||||
quadcolor->vram_2 = malloc(0x10000);
|
||||
|
||||
cga_comp_init(quadcolor->revision);
|
||||
timer_add(&quadcolor->timer, quadcolor_poll, quadcolor, 1);
|
||||
mem_mapping_add(&quadcolor->mapping, 0xb8000, 0x08000, quadcolor_read, NULL, NULL, quadcolor_write, NULL, NULL, NULL /*quadcolor->vram*/, MEM_MAPPING_EXTERNAL, quadcolor);
|
||||
/* add mapping for vram_2 at 0xd0000, mirrored at 0xe0000 */
|
||||
if (quadcolor->has_quadcolor_2)
|
||||
mem_mapping_add(&quadcolor->mapping_2, 0xd0000, 0x20000, quadcolor_2_read, NULL, NULL, quadcolor_2_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL,
|
||||
quadcolor);
|
||||
|
||||
io_sethandler(0x03d0, 0x0010, quadcolor_in, NULL, NULL, quadcolor_out, NULL, NULL, quadcolor);
|
||||
|
||||
overscan_x = overscan_y = 16;
|
||||
|
||||
quadcolor->rgb_type = device_get_config_int("rgb_type");
|
||||
cga_palette = (quadcolor->rgb_type << 1);
|
||||
cgapal_rebuild();
|
||||
update_cga16_color(quadcolor->cgamode);
|
||||
|
||||
quadcolor->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] = quadcolor_interpolate_srgb(i, j, 0.5);
|
||||
interp_lut[1][i][j] = quadcolor_interpolate_linear(i, j, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
switch(device_get_config_int("font")) {
|
||||
case 0:
|
||||
loadfont(FONT_IBM_MDA_437_PATH, 0);
|
||||
break;
|
||||
case 1:
|
||||
loadfont(FONT_IBM_MDA_437_NORDIC_PATH, 0);
|
||||
break;
|
||||
case 4:
|
||||
loadfont(FONT_TULIP_DGA_PATH, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return quadcolor;
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_close(void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
|
||||
free(quadcolor->vram);
|
||||
free(quadcolor->vram_2);
|
||||
free(quadcolor);
|
||||
}
|
||||
|
||||
void
|
||||
quadcolor_speed_changed(void *priv)
|
||||
{
|
||||
quadcolor_t *quadcolor = (quadcolor_t *) priv;
|
||||
|
||||
quadcolor_recalctimings(quadcolor);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const device_config_t quadcolor_config[] = {
|
||||
{
|
||||
.name = "display_type",
|
||||
.description = "Display type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = CGA_RGB,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "RGB", .value = CGA_RGB },
|
||||
{ .description = "Composite", .value = CGA_COMPOSITE },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "composite_type",
|
||||
.description = "Composite type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = COMPOSITE_OLD,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Old", .value = COMPOSITE_OLD },
|
||||
{ .description = "New", .value = COMPOSITE_NEW },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "rgb_type",
|
||||
.description = "RGB type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Color (generic)", .value = 0 },
|
||||
{ .description = "Green Monochrome", .value = 1 },
|
||||
{ .description = "Amber Monochrome", .value = 2 },
|
||||
{ .description = "Gray Monochrome", .value = 3 },
|
||||
{ .description = "Color (no brown)", .value = 4 },
|
||||
{ .description = "Color (IBM 5153)", .value = 5 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "double_type",
|
||||
.description = "Line doubling type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = DOUBLE_NONE,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.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 = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "font",
|
||||
.description = "Font",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "US (CP 437)", .value = 0 },
|
||||
{ .description = "IBM Nordic (CP 437-Nordic)", .value = 1 },
|
||||
{ .description = "Tulip DGA", .value = 4 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "has_2nd_charset",
|
||||
.description = "Has secondary 8x8 character set",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "has_quadcolor_2",
|
||||
.description = "Has Quadcolor II daughter board",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 1,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "contrast",
|
||||
.description = "Alternate monochrome contrast",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const device_t quadcolor_device = {
|
||||
.name = "Quadram Quadcolor I / I+II",
|
||||
.internal_name = "quadcolor",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = quadcolor_standalone_init,
|
||||
.close = quadcolor_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = quadcolor_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = quadcolor_config
|
||||
};
|
||||
@@ -476,6 +476,20 @@ et3000_recalctimings(svga_t *svga)
|
||||
svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (svga->render == svga_render_4bpp_highres)
|
||||
svga->render = svga_render_4bpp_tseng_highres;
|
||||
}
|
||||
|
||||
static int
|
||||
et3000_line_compare(svga_t* svga)
|
||||
{
|
||||
if (svga->split > svga->vsyncstart) {
|
||||
/* Don't do line compare if we're already in vertical retrace. */
|
||||
/* This makes picture bouncing effect work on Copper demo. */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -511,6 +525,7 @@ et3000_init(const device_t *info)
|
||||
dev->svga.miscout = 1;
|
||||
|
||||
dev->svga.packed_chain4 = 1;
|
||||
dev->svga.line_compare = et3000_line_compare;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -723,6 +723,17 @@ et4000_recalctimings(svga_t *svga)
|
||||
svga->rowoffset <<= 1;
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
}
|
||||
|
||||
if (svga->render == svga_render_4bpp_highres)
|
||||
svga->render = svga_render_4bpp_tseng_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
|
||||
@@ -773,6 +784,17 @@ et4000_mca_feedb(UNUSED(void *priv))
|
||||
return et4000->pos_regs[2] & 1;
|
||||
}
|
||||
|
||||
static int
|
||||
et4000_line_compare(svga_t* svga)
|
||||
{
|
||||
if (svga->split > svga->vsyncstart) {
|
||||
/* Don't do line compare if we're already in vertical retrace. */
|
||||
/* This makes picture bouncing effect work on Copper demo. */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
et4000_init(const device_t *info)
|
||||
{
|
||||
@@ -881,8 +903,13 @@ et4000_init(const device_t *info)
|
||||
if (dev->type >= ET4000_TYPE_ISA)
|
||||
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
|
||||
|
||||
if (dev->type == ET4000_TYPE_TC6058AF)
|
||||
dev->svga.adv_flags |= FLAG_PRECISETIME;
|
||||
|
||||
dev->vram_mask = dev->vram_size - 1;
|
||||
|
||||
dev->svga.line_compare = et4000_line_compare;
|
||||
|
||||
rom_init(&dev->bios_rom, fn,
|
||||
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
|
||||
@@ -600,6 +600,9 @@ et4000w32p_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (svga->render == svga_render_4bpp_highres)
|
||||
svga->render = svga_render_4bpp_tseng_highres;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -703,6 +703,13 @@ svga_recalctimings(svga_t *svga)
|
||||
int old_monitor_overscan_x = svga->monitor->mon_overscan_x;
|
||||
int old_monitor_overscan_y = svga->monitor->mon_overscan_y;
|
||||
|
||||
if (svga->adv_flags & FLAG_PRECISETIME) {
|
||||
#ifdef USE_DYNAREC
|
||||
if (cpu_use_dynarec)
|
||||
update_tsc();
|
||||
#endif
|
||||
}
|
||||
|
||||
svga->vtotal = svga->crtc[6];
|
||||
svga->dispend = svga->crtc[0x12];
|
||||
svga->vsyncstart = svga->crtc[0x10];
|
||||
@@ -1024,7 +1031,7 @@ svga_recalctimings(svga_t *svga)
|
||||
svga->y_add = svga->vtotal - svga->vblankend - 1;
|
||||
svga->monitor->mon_overscan_y = svga->y_add + abs(svga->vblankstart - svga->dispend);
|
||||
|
||||
if ((svga->dispend >= 2048) || (svga->y_add < 0)) {
|
||||
if ((dev->dispend >= 2048) || (svga->y_add < 0)) {
|
||||
svga->y_add = 0;
|
||||
svga->monitor->mon_overscan_y = 0;
|
||||
}
|
||||
@@ -1087,7 +1094,7 @@ svga_recalctimings(svga_t *svga)
|
||||
if (ibm8514_active && (svga->dev8514 != NULL)) {
|
||||
if (dev->on) {
|
||||
disptime8514 = dev->h_total;
|
||||
_dispontime8514 = dev->h_disp;
|
||||
_dispontime8514 = dev->h_disp_time;
|
||||
svga_log("HTOTAL=%d, HDISP=%d.\n", dev->h_total, dev->h_disp);
|
||||
}
|
||||
}
|
||||
@@ -1253,6 +1260,7 @@ svga_do_render(svga_t *svga)
|
||||
}
|
||||
|
||||
if (!svga->override) {
|
||||
svga->render_line_offset = svga->start_retrace_latch - svga->crtc[0x4];
|
||||
svga->render(svga);
|
||||
|
||||
svga->x_add = svga->left_overscan;
|
||||
@@ -1435,10 +1443,8 @@ svga_poll(void *priv)
|
||||
svga->memaddr_backup = (svga->memaddr_backup << 2);
|
||||
|
||||
svga->scanline = 0;
|
||||
if (svga->attrregs[0x10] & 0x20) {
|
||||
svga->scrollcache = 0;
|
||||
svga->x_add = svga->left_overscan;
|
||||
}
|
||||
if (svga->attrregs[0x10] & 0x20)
|
||||
svga->panning_blank = 1;
|
||||
}
|
||||
}
|
||||
if (svga->vc == svga->dispend) {
|
||||
@@ -1516,6 +1522,8 @@ svga_poll(void *priv)
|
||||
|
||||
if (svga->vsync_callback)
|
||||
svga->vsync_callback(svga);
|
||||
|
||||
svga->start_retrace_latch = svga->crtc[0x4];
|
||||
}
|
||||
#if 0
|
||||
if (svga->vc == lines_num) {
|
||||
@@ -1526,25 +1534,6 @@ svga_poll(void *priv)
|
||||
svga->dispon = 1;
|
||||
svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
|
||||
|
||||
svga->scrollcache = (svga->attrregs[0x13] & 0x0f);
|
||||
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
|
||||
if (svga->seqregs[1] & 1)
|
||||
svga->scrollcache &= 0x07;
|
||||
else {
|
||||
svga->scrollcache++;
|
||||
if (svga->scrollcache > 8)
|
||||
svga->scrollcache = 0;
|
||||
}
|
||||
} else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres))
|
||||
svga->scrollcache &= 0x07;
|
||||
else
|
||||
svga->scrollcache = (svga->scrollcache & 0x06) >> 1;
|
||||
|
||||
if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres))
|
||||
svga->scrollcache <<= 1;
|
||||
|
||||
svga->x_add = svga->left_overscan - svga->scrollcache;
|
||||
|
||||
svga->linecountff = 0;
|
||||
|
||||
svga->hwcursor_on = 0;
|
||||
@@ -1555,9 +1544,37 @@ svga_poll(void *priv)
|
||||
|
||||
svga->overlay_on = 0;
|
||||
svga->overlay_latch = svga->overlay;
|
||||
|
||||
svga->panning_blank = 0;
|
||||
}
|
||||
|
||||
if (svga->scanline == (svga->crtc[10] & 31))
|
||||
svga->cursorvisible = 1;
|
||||
|
||||
if (svga->panning_blank) {
|
||||
svga->scrollcache = 0;
|
||||
svga->x_add = svga->left_overscan;
|
||||
} else {
|
||||
svga->scrollcache = (svga->attrregs[0x13] & 0x0f);
|
||||
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
|
||||
if (svga->seqregs[1] & 1)
|
||||
svga->scrollcache &= 0x07;
|
||||
else {
|
||||
svga->scrollcache++;
|
||||
if (svga->scrollcache > 8)
|
||||
svga->scrollcache = 0;
|
||||
}
|
||||
} else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) ||
|
||||
(svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres))
|
||||
svga->scrollcache &= 0x07;
|
||||
else
|
||||
svga->scrollcache = (svga->scrollcache & 0x06) >> 1;
|
||||
|
||||
if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres))
|
||||
svga->scrollcache <<= 1;
|
||||
|
||||
svga->x_add = svga->left_overscan - svga->scrollcache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -744,6 +744,13 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits)
|
||||
return;
|
||||
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->render_line_offset) {
|
||||
if (svga->render_line_offset > 0) {
|
||||
memset(p, svga->overscan_color, charwidth * svga->render_line_offset * sizeof(uint32_t));
|
||||
p += charwidth * svga->render_line_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
@@ -900,6 +907,12 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits)
|
||||
else
|
||||
p += charwidth;
|
||||
}
|
||||
|
||||
if (svga->render_line_offset < 0) {
|
||||
uint32_t *orig_line = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
memmove(orig_line, orig_line + (charwidth * -svga->render_line_offset), (svga->hdisp) * 4);
|
||||
memset((orig_line + svga->hdisp) - (charwidth * -svga->render_line_offset), svga->overscan_color, charwidth * -svga->render_line_offset * 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -913,6 +926,126 @@ 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_4bpp_tseng_highres(svga_t *svga)
|
||||
{
|
||||
int changed_offset;
|
||||
int x;
|
||||
int oddeven;
|
||||
uint32_t addr;
|
||||
uint32_t *p;
|
||||
uint8_t edat[4];
|
||||
uint8_t dat;
|
||||
uint32_t changed_addr;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->force_old_addr) {
|
||||
changed_offset = (svga->memaddr + (svga->scanline & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
|
||||
|
||||
if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) {
|
||||
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
|
||||
addr = svga->memaddr;
|
||||
oddeven = 0;
|
||||
|
||||
if (!(svga->crtc[0x17] & 0x40)) {
|
||||
addr = (addr << 1) & svga->vram_mask;
|
||||
|
||||
if (svga->seqregs[1] & 4)
|
||||
oddeven = (addr & 4) ? 1 : 0;
|
||||
|
||||
addr &= ~7;
|
||||
|
||||
if ((svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x20000))
|
||||
addr |= 4;
|
||||
if (!(svga->crtc[0x17] & 0x20) && (svga->memaddr & 0x8000))
|
||||
addr |= 4;
|
||||
}
|
||||
|
||||
if (!(svga->crtc[0x17] & 0x01))
|
||||
addr = (addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0);
|
||||
if (!(svga->crtc[0x17] & 0x02))
|
||||
addr = (addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0);
|
||||
|
||||
if (svga->seqregs[1] & 4) {
|
||||
edat[0] = svga->vram[addr | oddeven];
|
||||
edat[2] = svga->vram[addr | oddeven | 0x2];
|
||||
edat[1] = edat[3] = 0;
|
||||
svga->memaddr += 2;
|
||||
} else {
|
||||
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]);
|
||||
svga->memaddr += 4;
|
||||
}
|
||||
svga->memaddr &= svga->vram_mask;
|
||||
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
changed_addr = svga->remap_func(svga, svga->memaddr);
|
||||
|
||||
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) {
|
||||
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
|
||||
addr = svga->remap_func(svga, svga->memaddr);
|
||||
oddeven = 0;
|
||||
|
||||
if (svga->seqregs[1] & 4) {
|
||||
oddeven = (addr & 4) ? 1 : 0;
|
||||
edat[0] = svga->vram[addr | oddeven];
|
||||
edat[2] = svga->vram[addr | oddeven | 0x2];
|
||||
edat[1] = edat[3] = 0;
|
||||
svga->memaddr += 2;
|
||||
} else {
|
||||
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr]);
|
||||
svga->memaddr += 4;
|
||||
}
|
||||
svga->memaddr &= svga->vram_mask;
|
||||
|
||||
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
|
||||
p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
|
||||
p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
|
||||
p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
|
||||
p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
|
||||
p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
|
||||
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
svga_render_8bpp_clone_highres(svga_t *svga)
|
||||
{
|
||||
@@ -1163,13 +1296,20 @@ svga_render_8bpp_tseng_lowres(svga_t *svga)
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) {
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange || svga->render_line_offset) {
|
||||
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->render_line_offset) {
|
||||
if (svga->render_line_offset > 0) {
|
||||
memset(p, svga->overscan_color, 8 * svga->render_line_offset * sizeof(uint32_t));
|
||||
p += 8 * svga->render_line_offset;
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
|
||||
dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
|
||||
if (svga->attrregs[0x10] & 0x80)
|
||||
@@ -1191,6 +1331,11 @@ svga_render_8bpp_tseng_lowres(svga_t *svga)
|
||||
svga->memaddr += 4;
|
||||
p += 8;
|
||||
}
|
||||
if (svga->render_line_offset < 0) {
|
||||
uint32_t *orig_line = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
memmove(orig_line, orig_line + (8 * -svga->render_line_offset), (svga->hdisp) * 4);
|
||||
memset((orig_line + svga->hdisp) - (8 * -svga->render_line_offset), svga->overscan_color, 8 * -svga->render_line_offset * 4);
|
||||
}
|
||||
svga->memaddr &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
@@ -1204,13 +1349,20 @@ svga_render_8bpp_tseng_highres(svga_t *svga)
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange) {
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->fullchange || svga->render_line_offset) {
|
||||
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->render_line_offset) {
|
||||
if (svga->render_line_offset > 0) {
|
||||
memset(p, svga->overscan_color, 8 * svga->render_line_offset * sizeof(uint32_t));
|
||||
p += 8 * svga->render_line_offset;
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) {
|
||||
dat = *(uint32_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
|
||||
if (svga->attrregs[0x10] & 0x80)
|
||||
@@ -1249,6 +1401,13 @@ svga_render_8bpp_tseng_highres(svga_t *svga)
|
||||
svga->memaddr += 8;
|
||||
p += 8;
|
||||
}
|
||||
|
||||
if (svga->render_line_offset < 0) {
|
||||
uint32_t *orig_line = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
memmove(orig_line, orig_line + (8 * -svga->render_line_offset), (svga->hdisp) * 4);
|
||||
memset((orig_line + svga->hdisp) - (8 * -svga->render_line_offset), svga->overscan_color, 8 * -svga->render_line_offset * 4);
|
||||
}
|
||||
|
||||
svga->memaddr &= svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ video_cards[] = {
|
||||
{ .device = &ati18800_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &ati18800_wonder_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &cga_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &quadcolor_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &sega_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &jega_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
{ .device = &gd5401_isa_device, .flags = VIDEO_FLAG_TYPE_NONE },
|
||||
|
||||
Reference in New Issue
Block a user