This commit is contained in:
starfrost013
2025-07-04 22:00:23 +01:00
132 changed files with 5284 additions and 2208 deletions

View File

@@ -8,6 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,7 +19,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- "!.github/workflows/**"
- .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -26,12 +27,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
@@ -66,6 +65,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
@@ -90,28 +103,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: |
@@ -120,5 +122,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/**

View File

@@ -8,6 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,7 +19,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- "!.github/workflows/**"
- .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -26,13 +27,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:
@@ -66,7 +65,6 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
sdl2
rtmidi
openal-soft
@@ -81,9 +79,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 }}
@@ -97,20 +92,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
@@ -119,13 +104,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:
@@ -159,12 +142,12 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
sdl2
rtmidi
openal-soft
fluidsynth
libslirp
vde
libserialport
${{ matrix.ui.packages }}
@@ -173,9 +156,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 }}
@@ -189,20 +169,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

View File

@@ -8,6 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,6 +19,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -25,13 +27,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}
@@ -40,23 +40,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
@@ -97,9 +121,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 }}
@@ -107,20 +128,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

View File

@@ -3,34 +3,43 @@ name: CodeQL Analysis (Linux)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- "!.github/workflows/**"
- .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
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
@@ -43,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
@@ -59,6 +68,7 @@ jobs:
ui:
- name: SDL GUI
qt: off
static: on
- name: Qt GUI
qt: on
slug: -Qt
@@ -90,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
@@ -106,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"

View File

@@ -3,34 +3,43 @@ name: CodeQL Analysis (macos)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- "!.github/workflows/**"
- .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
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
@@ -43,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
@@ -69,7 +78,6 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
sdl2
rtmidi
openal-soft
@@ -81,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
@@ -101,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"

View File

@@ -3,33 +3,42 @@ name: CodeQL Analysis (Windows, msys2)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- "!.github/workflows/**"
- .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- "!.github/workflows/**"
- .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
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
@@ -47,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
@@ -72,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: >-
@@ -104,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
@@ -123,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"

View File

@@ -137,15 +137,8 @@ option(GDBSTUB "Enable GDB stub server for debugging"
option(DEV_BRANCH "Development branch" OFF)
option(DISCORD "Discord Rich Presence support" ON)
option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF)
# Remove when merged, should just be -D
option(NV_LOG "NVidia RIVA 128 debug logging" ON)
option(NV_LOG_ULTRA "Even more NVidia RIVA 128 debug logging" OFF)
option(LIBASAN "Enable compilation with the addresss sanitizer" OFF)
# Remove when merged, should just be -D
option(NV_LOG "NVidia RIVA 128 debug logging" ON)
option(NV_LOG_ULTRA "Even more NVidia RIVA 128 debug logging" OFF)
if (NV_LOG)
add_compile_definitions(ENABLE_NV_LOG)
endif()
@@ -240,4 +233,10 @@ if(NOT EMU_COPYRIGHT_YEAR)
set(EMU_COPYRIGHT_YEAR 2024)
endif()
# Libasan
if(LIBASAN)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
add_subdirectory(src)

View File

@@ -782,7 +782,11 @@ usage:
goto usage;
temp2 = (char *) calloc(2048, 1);
sscanf(argv[++c], "%c:%s", &drive, temp2);
if (sscanf(argv[++c], "%c:%2047s", &drive, temp2) != 2) {
fprintf(stderr, "Invalid input format for --image option.\n");
free(temp2);
goto usage;
}
if (drive > 0x40)
drive = (drive & 0x1f) - 1;
else
@@ -1021,9 +1025,21 @@ usage:
* This is where we start outputting to the log file,
* if there is one. Create a little info header first.
*/
struct tm time_buf;
(void) time(&now);
info = localtime(&now);
strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info);
#ifdef _WIN32
if (localtime_s(&time_buf, &now) == 0)
info = &time_buf;
#else
info = localtime_r(&now, &time_buf);
#endif
if (info)
strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info);
else
strcpy(temp, "unknown");
pclog("#\n# %ls v%ls logfile, created %s\n#\n",
EMU_NAME_W, EMU_VERSION_FULL_W, temp);
pclog("# VM: %s\n#\n", vm_name);
@@ -1656,6 +1672,10 @@ pc_close(UNUSED(thread_t *ptr))
scsi_disk_close();
gdbstub_close();
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
mem_free();
#endif
}
#ifdef __APPLE__

View File

@@ -2655,7 +2655,7 @@ cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer)
buffer[ 3] = first; /* Number of First Track on Disc */
buffer[ 4] = sessions; /* Number of Sessions (LSB) */
buffer[ 5] = ls_first; /* First Track Number in Last Session (LSB) */
buffer[ 5] = ls_last; /* Last Track Number in Last Session (LSB) */
buffer[ 6] = ls_last; /* Last Track Number in Last Session (LSB) */
buffer[ 7] = 0x20; /* Unrestricted use */
buffer[ 8] = t[0].ps; /* Disc Type */
buffer[ 9] = 0x00; /* Number Of Sessions (MSB) */

View File

@@ -446,24 +446,36 @@ static int
viso_fill_time(uint8_t *data, time_t time, int format, int longform)
{
uint8_t *p = data;
struct tm *time_s = localtime(&time);
if (!time_s) {
/* localtime will return NULL if the time_t is negative (Windows)
or way too far into 64-bit space (Linux). Fall back to epoch. */
time_t epoch = 0;
time_s = localtime(&epoch);
if (UNLIKELY(!time_s))
fatal("VISO: localtime(0) = NULL\n");
struct tm time_s_buf;
struct tm *time_s = NULL;
time_t epoch = 0;
/* Force year clamping if the timestamp is known to be outside the supported ranges. */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &time) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&time, &time_s_buf);
#endif
if (!time_s) {
/* localtime may return NULL if time is negative or out of range */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &epoch) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&epoch, &time_s_buf);
#endif
if (!time_s)
fatal("VISO: localtime fallback to epoch failed\n");
/* Force year clamping for out-of-range times */
if (time < (longform ? -62135596800LL : -2208988800LL)) /* 0001-01-01 00:00:00 : 1900-01-01 00:00:00 */
time_s->tm_year = -1901;
else if (time > (longform ? 253402300799LL : 5869583999LL)) /* 9999-12-31 23:59:59 : 2155-12-31 23:59:59 */
time_s->tm_year = 8100;
}
/* Clamp year to the supported ranges, and assume the
OS returns valid numbers in the other struct fields. */
/* Clamp year within supported ranges */
if (time_s->tm_year < (longform ? -1900 : 0)) {
time_s->tm_year = longform ? -1900 : 0;
time_s->tm_mon = time_s->tm_hour = time_s->tm_min = time_s->tm_sec = 0;
@@ -476,18 +488,18 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
time_s->tm_min = time_s->tm_sec = 59;
}
/* Convert timestamp. */
/* Convert timestamp */
if (longform) {
p += sprintf((char *) p, "%04u%02u%02u%02u%02u%02u00",
1900 + time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
p += sprintf((char *)p, "%04u%02u%02u%02u%02u%02u00",
1900 + (unsigned)time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
time_s->tm_hour, time_s->tm_min, time_s->tm_sec);
} else {
*p++ = time_s->tm_year; /* year since 1900 */
*p++ = 1 + time_s->tm_mon; /* month */
*p++ = time_s->tm_mday; /* day */
*p++ = time_s->tm_hour; /* hour */
*p++ = time_s->tm_min; /* minute */
*p++ = time_s->tm_sec; /* second */
*p++ = (uint8_t)time_s->tm_year; /* year since 1900 */
*p++ = (uint8_t)(1 + time_s->tm_mon); /* month */
*p++ = (uint8_t)time_s->tm_mday; /* day */
*p++ = (uint8_t)time_s->tm_hour; /* hour */
*p++ = (uint8_t)time_s->tm_min; /* minute */
*p++ = (uint8_t)time_s->tm_sec; /* second */
}
if (format & VISO_FORMAT_ISO)
*p++ = tz_offset; /* timezone (ISO only) */
@@ -1034,8 +1046,15 @@ next_dir:
the timezone offset for descriptors and file times to use. */
tzset();
time_t now = time(NULL);
if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
struct tm now_tm;
if (viso->format & VISO_FORMAT_ISO) { /* timezones are ISO only */
#ifdef _WIN32
gmtime_s(&now_tm, &now); // Windows: output first param, input second
#else
gmtime_r(&now, &now_tm); // POSIX: input first param, output second
#endif
tz_offset = (now - mktime(&now_tm)) / (3600 / 4);
}
/* Get root directory basename for the volume ID. */
const char *basename = path_get_filename(viso->root_dir->path);

View File

@@ -158,7 +158,7 @@ acc2036_recalc(acc2036_t *dev)
/* 0E0000-0FFFFF */
master_write = dev->regs[0x02] & 0x02;
master_read = dev->regs[0x02] & 0x01;
bit = (((i - 8) >> 2) + 2);
bit = ((i - 8) >> 2);
val = dev->regs[0x0c] & (1 << bit);
if (i >= 20) {
ew_flag = MEM_WRITE_EXTANY;

View File

@@ -786,7 +786,7 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
codegen_addquad(block, (uintptr_t) p);
codegen_addbyte3(block, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/
} else {
fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram);
fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIXPTR ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram);
codegen_alloc_bytes(block, 6);
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));

View File

@@ -658,8 +658,10 @@ load_network(void)
nc->net_type = NET_TYPE_PCAP;
else if (!strcmp(p, "slirp") || !strcmp(p, "2"))
nc->net_type = NET_TYPE_SLIRP;
else if (!strcmp(p, "vde") || !strcmp(p, "2"))
else if (!strcmp(p, "vde") || !strcmp(p, "3"))
nc->net_type = NET_TYPE_VDE;
else if (!strcmp(p, "tap") || !strcmp(p, "4"))
nc->net_type = NET_TYPE_TAP;
else
nc->net_type = NET_TYPE_NONE;
} else
@@ -704,13 +706,14 @@ load_network(void)
nc->net_type = NET_TYPE_PCAP;
else if (!strcmp(p, "slirp") || !strcmp(p, "2"))
nc->net_type = NET_TYPE_SLIRP;
else if (!strcmp(p, "vde") || !strcmp(p, "2"))
else if (!strcmp(p, "vde") || !strcmp(p, "3"))
nc->net_type = NET_TYPE_VDE;
else if (!strcmp(p, "tap") || !strcmp(p, "4"))
nc->net_type = NET_TYPE_TAP;
else
nc->net_type = NET_TYPE_NONE;
} else
nc->net_type = NET_TYPE_NONE;
sprintf(temp, "net_%02i_host_device", c + 1);
p = ini_section_get_string(cat, temp, NULL);
if (p != NULL) {
@@ -2433,7 +2436,9 @@ save_network(void)
case NET_TYPE_VDE:
ini_section_set_string(cat, temp, "vde");
break;
case NET_TYPE_TAP:
ini_section_set_string(cat, temp, "tap");
break;
default:
break;
}

View File

@@ -264,6 +264,7 @@ opVPCEXT(uint32_t fetchdat)
uint8_t b2;
uint16_t cent;
time_t now;
struct tm tm_buf;
struct tm *tm = NULL;
if (!is_vpc) /* only emulate this on Virtual PC machines */
@@ -282,7 +283,16 @@ opVPCEXT(uint32_t fetchdat)
/* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */
if (b1 == 0x03) {
(void) time(&now);
tm = localtime(&now);
#ifdef _WIN32
if (localtime_s(&tm_buf, &now) == 0)
tm = &tm_buf;
#else
tm = localtime_r(&now, &tm_buf);
#endif
if (!tm)
fatal("localtime() failed for host clock\n");
}
if ((b1 == 0x07) && (b2 == 0x0b)) {

File diff suppressed because it is too large Load Diff

View File

@@ -381,7 +381,7 @@ typedef struct {
MMX_REG MM[8];
#ifdef USE_NEW_DYNAREC
# if defined(__APPLE__) && defined(__aarch64__)
# if (defined(__APPLE__) && defined(__aarch64__)) || defined(__aarch64__)
uint64_t old_fp_control;
uint64_t new_fp_control;
# else

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stddef.h>
#include <stdint.h>
#include "primitiveTypes.h"
@@ -64,7 +65,7 @@ void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *
{
uint64_t wordJam;
uint32_t wordDist;
uint64_t *ptr;
uint64_t *ptr = NULL;
uint8_t i, innerDist;
wordJam = 0;
@@ -89,7 +90,7 @@ void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *
aPtr,
innerDist,
zPtr + indexMultiwordLoBut(4, wordDist)
);
);
if (! wordDist) goto wordJam;
} else {
aPtr += indexWordLo(4 - wordDist);

View File

@@ -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

View File

@@ -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)); \

View File

@@ -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

View File

@@ -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

View File

@@ -41,7 +41,7 @@ add_library(dev OBJECT
keyboard.c
keyboard_at.c
keyboard_xt.c
../lpt.c
lpt.c
mouse.c
mouse_bus.c
mouse_microtouch_touchscreen.c

View File

@@ -27,6 +27,7 @@
#include <stdarg.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/lpt.h>
#include <86box/device.h>
@@ -334,13 +335,16 @@ hasp_close(void *priv)
}
const lpt_device_t lpt_hasp_savquest_device = {
.name = "Protection Dongle for Savage Quest",
.internal_name = "dongle_savquest",
.init = hasp_init_savquest,
.close = hasp_close,
.write_data = hasp_write_data,
.write_ctrl = NULL,
.read_data = NULL,
.read_status = hasp_read_status,
.read_ctrl = NULL
.name = "Protection Dongle for Savage Quest",
.internal_name = "dongle_savquest",
.init = hasp_init_savquest,
.close = hasp_close,
.write_data = hasp_write_data,
.write_ctrl = NULL,
.autofeed = NULL,
.strobe = NULL,
.read_status = hasp_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -156,7 +156,7 @@ isarom_init(const device_t *info)
snprintf(dev->socket[i].nvr_path, sizeof(dev->socket[i].nvr_path), "isarom_%i_%i.nvr", dev->inst, i + 1);
FILE *fp = nvr_fopen(dev->socket[i].nvr_path, "rb");
if (fp != NULL) {
fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp);
(void) !fread(dev->socket[i].rom.rom, 1, dev->socket[i].size, fp);
fclose(fp);
isarom_log("isarom[%u]: loaded %zu bytes from %s\n", dev->inst, read_bytes, dev->socket[i].nvr_path);
} else

View File

@@ -1817,8 +1817,6 @@ read_p1(atkbc_t *dev)
Compaq: Reserved;
NCR: DMA mode.
*/
kbc_at_log("ATkbc: read P1\n");
fixed_bits = 4;
/* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */
@@ -2108,7 +2106,7 @@ kbc_at_process_cmd(void *priv)
break;
case 0xc0: /* read P1 */
kbc_at_log("ATkbc: read P2\n");
kbc_at_log("ATkbc: read P1\n");
kbc_delay_to_ob(dev, read_p1(dev), 0, 0x00);
break;

839
src/device/lpt.c Normal file
View File

@@ -0,0 +1,839 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/fifo.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/lpt.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/prt_devs.h>
#include <86box/thread.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/network.h>
lpt_port_t lpt_ports[PARALLEL_MAX];
const lpt_device_t lpt_none_device = {
.name = "None",
.internal_name = "none",
.init = NULL,
.close = NULL,
.write_data = NULL,
.write_ctrl = NULL,
.read_status = NULL,
.read_ctrl = NULL
};
static const struct {
const char *internal_name;
const lpt_device_t *device;
} lpt_devices[] = {
// clang-format off
{"none", &lpt_none_device },
{"dss", &dss_device },
{"lpt_dac", &lpt_dac_device },
{"lpt_dac_stereo", &lpt_dac_stereo_device },
{"text_prt", &lpt_prt_text_device },
{"dot_matrix", &lpt_prt_escp_device },
{"postscript", &lpt_prt_ps_device },
#ifdef USE_PCL
{"pcl", &lpt_prt_pcl_device },
#endif
{"plip", &lpt_plip_device },
{"dongle_savquest", &lpt_hasp_savquest_device },
{"", NULL }
// clang-format on
};
#ifdef ENABLE_LPT_LOG
int lpt_do_log = ENABLE_LPT_LOG;
static void
lpt_log(const char *fmt, ...)
{
va_list ap;
if (lpt_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define lpt_log(fmt, ...)
#endif
const char *
lpt_device_get_name(const int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
if (lpt_devices[id].device == NULL)
return "None";
return lpt_devices[id].device->name;
}
const char *
lpt_device_get_internal_name(const int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
return lpt_devices[id].internal_name;
}
int
lpt_device_get_from_internal_name(const char *s)
{
int c = 0;
while (strlen(lpt_devices[c].internal_name) != 0) {
if (strcmp(lpt_devices[c].internal_name, s) == 0)
return c;
c++;
}
return 0;
}
void
lpt_devices_init(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device;
if (lpt_ports[i].dt && lpt_ports[i].dt->init)
lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]);
}
}
void
lpt_devices_close(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_port_t *dev = &lpt_ports[i];
if (lpt_ports[i].dt && lpt_ports[i].dt->close)
dev->dt->close(dev->priv);
dev->dt = NULL;
}
}
static uint8_t
lpt_get_ctrl_raw(const lpt_port_t *dev)
{
uint8_t ret;
if (dev->dt && dev->dt->read_ctrl && dev->priv)
ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq;
else
ret = 0xc0 | dev->ctrl | dev->enable_irq;
return ret & 0xdf;
}
static uint8_t
lpt_is_epp(const lpt_port_t *dev)
{
return (dev->epp || ((dev->ecp) && ((dev->ecr & 0xe0) == 0x80)));
}
static uint8_t
lpt_get_ctrl(const lpt_port_t *dev)
{
uint8_t ret = lpt_get_ctrl_raw(dev);
if (!dev->ecp && !dev->epp)
ret |= 0x20;
return ret;
}
static void
lpt_write_fifo(lpt_port_t *dev, const uint8_t val, const uint8_t tag)
{
if (!fifo_get_full(dev->fifo)) {
fifo_write_evt_tagged(tag, val, dev->fifo);
if (!timer_is_enabled(&dev->fifo_out_timer))
timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
}
}
static void
lpt_ecp_update_irq(lpt_port_t *dev)
{
if (!(dev->ecr & 0x04) && ((dev->fifo_stat | dev->dma_stat) & 0x04))
picintlevel(1 << dev->irq, &dev->irq_state);
else
picintclevel(1 << dev->irq, &dev->irq_state);
}
static void
lpt_autofeed(lpt_port_t *dev, const uint8_t val)
{
if (dev->dt && dev->dt->autofeed && dev->priv)
dev->dt->autofeed(val, dev->priv);
dev->autofeed = val;
}
static void
lpt_strobe(lpt_port_t *dev, const uint8_t val)
{
if (dev->dt && dev->dt->strobe && dev->priv)
dev->dt->strobe(dev->strobe, val, dev->priv);
dev->strobe = val;
}
static void
lpt_fifo_out_callback(void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
switch (dev->state) {
default:
break;
case LPT_STATE_READ_DMA:
;
int ret = 0xff;
if (dev->dma == 0xff)
ret = DMA_NODATA;
else
ret = dma_channel_read(dev->dma);
lpt_log("DMA %02X: %08X\n", dev->dma, ret);
if (ret != DMA_NODATA) {
fifo_write_evt_tagged(0x01, (uint8_t) (ret & 0xff), dev->fifo);
if (ret & DMA_OVER)
/* Internal flag to indicate we have finished the DMA reads. */
dev->dma_stat = 0x08;
}
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
if (dev->dma_stat || fifo_get_full(dev->fifo))
dev->state = LPT_STATE_WRITE_FIFO;
break;
case LPT_STATE_WRITE_FIFO:
if (!fifo_get_empty(dev->fifo)) {
uint8_t tag = 0x00;
const uint8_t val = fifo_read_evt_tagged(&tag, dev->fifo);
lpt_log("FIFO: %02X, TAG = %02X\n", val, tag);
/* We do not currently support sending commands. */
if (tag == 0x01) {
if (dev->dt && dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
lpt_strobe(dev, 1);
lpt_strobe(dev, 0);
}
}
if (dev->ecr & 0x08) {
if (fifo_get_empty(dev->fifo)) {
if (dev->dma_stat) {
/* Now actually set the external flag. */
dev->dma_stat = 0x04;
dev->state = LPT_STATE_IDLE;
lpt_ecp_update_irq(dev);
lpt_autofeed(dev, 0);
} else {
dev->state = LPT_STATE_READ_DMA;
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
}
} else
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
} else if (!fifo_get_empty(dev->fifo))
timer_advance_u64(&dev->fifo_out_timer,
(uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
else
lpt_autofeed(dev, 0);
break;
}
}
void
lpt_write(const uint16_t port, const uint8_t val, void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
uint16_t mask = 0x0407;
lpt_log("[W] %04X = %02X\n", port, val);
/* This is needed so the parallel port at 3BC works. */
if (dev->addr & 0x0004)
mask = 0x0403;
switch (port & mask) {
case 0x0000:
if (dev->ecp) {
if ((dev->ecr & 0xe0) == 0x60)
/* AFIFO */
lpt_write_fifo(dev, val, 0x00);
else if (!(dev->ecr & 0xc0) && (!(dev->ecr & 0x20) || !(lpt_get_ctrl_raw(dev) & 0x20)) &&
dev->dt && dev->dt->write_data && dev->priv)
/* DATAR */
dev->dt->write_data(val, dev->priv);
dev->dat = val;
} else {
/* DTR */
if ((!dev->ext || !(lpt_get_ctrl_raw(dev) & 0x20)) && dev->dt &&
dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
dev->dat = val;
}
break;
case 0x0001:
break;
case 0x0002:
if (dev->dt && dev->dt->write_ctrl && dev->priv) {
if (dev->ecp)
dev->dt->write_ctrl((val & 0xfc) | dev->autofeed | dev->strobe, dev->priv);
else
dev->dt->write_ctrl(val, dev->priv);
}
dev->ctrl = val;
dev->enable_irq = val & 0x10;
if (!(val & 0x10) && (dev->irq != 0xff))
picintc(1 << dev->irq);
dev->irq_state = 0;
break;
case 0x0003:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_write_data && dev->priv)
dev->dt->epp_write_data(1, val, dev->priv);
}
break;
case 0x0004 ... 0x0007:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_write_data && dev->priv)
dev->dt->epp_write_data(0, val, dev->priv);
}
break;
case 0x0400: case 0x0404:
switch (dev->ecr >> 5) {
default:
break;
case 2:
lpt_write_fifo(dev, val, 0x01);
break;
case 3:
if (!(lpt_get_ctrl_raw(dev) & 0x20))
lpt_write_fifo(dev, val, 0x01);
break;
case 6:
/* TFIFO */
if (!fifo_get_full(dev->fifo))
fifo_write_evt(val, dev->fifo);
break;
}
break;
case 0x0402: case 0x0406:
if (!(val & 0x0c))
lpt_autofeed(dev, 0x00);
else
lpt_autofeed(dev, 0x02);
if ((dev->ecr & 0x04) && !(val & 0x04)) {
dev->dma_stat = 0x00;
fifo_reset(dev->fifo);
if (val & 0x08) {
dev->state = LPT_STATE_READ_DMA;
dev->fifo_stat = 0x00;
if (!timer_is_enabled(&dev->fifo_out_timer))
timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC));
} else {
dev->state = LPT_STATE_WRITE_FIFO;
if (lpt_get_ctrl_raw(dev) & 0x20)
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00;
else
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04;
}
} else if ((val & 0x04) && !(dev->ecr & 0x04)) {
if (timer_is_enabled(&dev->fifo_out_timer))
timer_disable(&dev->fifo_out_timer);
dev->state = LPT_STATE_IDLE;
}
dev->ecr = val;
lpt_ecp_update_irq(dev);
break;
default:
break;
}
}
static void
lpt_fifo_d_ready_evt(void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (!(dev->ecr & 0x08)) {
if (lpt_get_ctrl_raw(dev) & 0x20)
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00;
else
dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04;
}
lpt_ecp_update_irq(dev);
}
void
lpt_write_to_fifo(void *priv, const uint8_t val)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->ecp) {
if (((dev->ecr & 0xe0) == 0x20) && (lpt_get_ctrl_raw(dev) & 0x20))
dev->dat = val;
else if (((dev->ecr & 0xe0) == 0x60) && (lpt_get_ctrl_raw(dev) & 0x20) &&
!fifo_get_full(dev->fifo))
fifo_write_evt_tagged(0x01, val, dev->fifo);
if (((dev->ecr & 0x0c) == 0x08) && (dev->dma != 0xff)) {
const int ret = dma_channel_write(dev->dma, val);
if (ret & DMA_OVER)
dev->dma_stat |= 0x04;
}
} else {
if (dev->ext && (lpt_get_ctrl_raw(dev) & 0x20))
dev->dat = val;
}
}
void
lpt_write_to_dat(void *priv, const uint8_t val)
{
lpt_port_t *dev = (lpt_port_t *) priv;
dev->dat = val;
}
static uint8_t
lpt_read_fifo(const lpt_port_t *dev)
{
uint8_t ret = 0xff;
if (!fifo_get_empty(dev->fifo))
ret = fifo_read(dev->fifo);
return ret;
}
uint8_t
lpt_read_status(const int port)
{
lpt_port_t *dev = &lpt_ports[port];
uint8_t low_bits = 0x07;
uint8_t ret;
if (dev->ext) {
low_bits = 0x03 | (dev->irq_state ? 0x00 : 0x04);
if (dev->irq != 0xff)
picintclevel(1 << dev->irq, &dev->irq_state);
dev->irq_state = 0;
}
if (dev->epp || dev->ecp) {
low_bits = lpt_is_epp(dev) ? 0x02 : 0x03;
if (lpt_get_ctrl_raw(dev) & 0x10)
low_bits |= (dev->irq_state ? 0x00 : 0x04);
else
low_bits |= 0x04;
}
if (dev->dt && dev->dt->read_status && dev->priv)
ret = (dev->dt->read_status(dev->priv) & 0xf8) | low_bits;
else
ret = 0xd8 | low_bits;
return ret;
}
uint8_t
lpt_read(const uint16_t port, void *priv)
{
const lpt_port_t *dev = (lpt_port_t *) priv;
uint16_t mask = 0x0407;
uint8_t ret = 0xff;
/* This is needed so the parallel port at 3BC works. */
if (dev->addr & 0x0004)
mask = 0x0403;
switch (port & mask) {
case 0x0000:
if (dev->ecp) {
if (!(dev->ecr & 0xc0))
ret = dev->dat;
} else {
/* DTR */
ret = dev->dat;
}
break;
case 0x0001:
ret = lpt_read_status(dev->id);
break;
case 0x0002:
ret = lpt_get_ctrl(dev);
if (dev->ecp)
ret = (ret & 0xfc) | (dev->ctrl & 0x03);
break;
case 0x0003:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_request_read && dev->priv)
dev->dt->epp_request_read(1, dev->priv);
ret = dev->dat;
}
break;
case 0x0004 ... 0x0007:
if (lpt_is_epp(dev)) {
if (dev->dt && dev->dt->epp_request_read && dev->priv)
dev->dt->epp_request_read(0, dev->priv);
ret = dev->dat;
}
break;
case 0x0400: case 0x0404:
switch (dev->ecr >> 5) {
default:
break;
case 3:
if (lpt_get_ctrl_raw(dev) & 0x20)
ret = lpt_read_fifo(dev);
break;
case 6:
/* TFIFO */
if (!fifo_get_empty(dev->fifo))
ret = fifo_read_evt(dev->fifo);
break;
case 7:
/* CNFGA */
ret = 0x14;
break;
}
break;
case 0x0401: case 0x0405:
if ((dev->ecr & 0xe0) == 0xe0) {
/* CNFGB */
ret = 0x08;
ret |= (dev->irq_state ? 0x40 : 0x00);
ret |= ((dev->irq == 0x05) ? 0x30 : 0x00);
if ((dev->dma >= 1) && (dev->dma <= 3))
ret |= dev->dma;
}
break;
case 0x0402: case 0x0406:
ret = dev->ecr | dev->fifo_stat | (dev->dma_stat & 0x04);
ret |= (fifo_get_full(dev->fifo) ? 0x02 : 0x00);
ret |= (fifo_get_empty(dev->fifo) ? 0x01 : 0x00);
break;
default:
break;
}
lpt_log("[R] %04X = %02X\n", port, ret);
return ret;
}
uint8_t
lpt_read_port(const int port, const uint16_t reg)
{
lpt_port_t *dev = &(lpt_ports[port]);
return lpt_read(reg, dev);
}
void
lpt_irq(void *priv, const int raise)
{
lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->enable_irq) {
if (dev->irq != 0xff) {
if (dev->ext) {
if (raise)
picintlevel(1 << dev->irq, &dev->irq_state);
else
picintclevel(1 << dev->irq, &dev->irq_state);
} else {
if (raise)
picint(1 << dev->irq);
else
picintc(1 << dev->irq);
}
}
if (!dev->ext || (dev->irq == 0xff))
dev->irq_state = raise;
} else {
if (dev->irq != 0xff) {
if (dev->ext)
picintclevel(1 << dev->irq, &dev->irq_state);
else
picintc(1 << dev->irq);
}
dev->irq_state = 0;
}
}
void
lpt_set_ext(const int port, const uint8_t ext)
{
if (lpt_ports[port].enabled)
lpt_ports[port].ext = ext;
}
void
lpt_set_ecp(const int port, const uint8_t ecp)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].ecp = ecp;
lpt_port_setup(port, addr);
}
}
void
lpt_set_epp(const int port, const uint8_t epp)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].epp = epp;
lpt_port_setup(port, addr);
}
}
void
lpt_set_lv2(const int port, const uint8_t lv2)
{
if (lpt_ports[port].enabled) {
const uint16_t addr = lpt_ports[port].addr;
lpt_port_setup(port, 0xfff);
lpt_ports[port].lv2 = lv2;
lpt_port_setup(port, addr);
}
}
void
lpt_close(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
if (lpt_ports[i].enabled) {
fifo_close(lpt_ports[i].fifo);
lpt_ports[i].fifo = NULL;
timer_disable(&lpt_ports[i].fifo_out_timer);
}
}
}
void
lpt_port_zero(lpt_port_t *dev)
{
lpt_port_t temp = { 0 };
temp.irq = dev->irq;
temp.id = dev->id;
temp.device = dev->device;
temp.dt = dev->dt;
temp.priv = dev->priv;
temp.enabled = dev->enabled;
temp.fifo = dev->fifo;
temp.fifo_out_timer = dev->fifo_out_timer;
if (dev->enabled)
lpt_port_remove(dev->id);
memset(dev, 0x00, sizeof(lpt_port_t));
dev->addr = 0xffff;
dev->irq = temp.irq;
dev->id = temp.id;
dev->device = temp.device;
dev->dt = temp.dt;
dev->priv = temp.priv;
dev->enabled = temp.enabled;
dev->fifo = temp.fifo;
dev->fifo_out_timer = temp.fifo_out_timer;
if (machine_has_bus(machine, MACHINE_BUS_MCA))
dev->ext = 1;
}
void
lpt_reset(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
if (lpt_ports[i].enabled)
if (timer_is_enabled(&lpt_ports[i].fifo_out_timer))
timer_disable(&lpt_ports[i].fifo_out_timer);
lpt_port_zero(&(lpt_ports[i]));
if (lpt_ports[i].enabled) {
if (lpt_ports[i].irq_state) {
if (lpt_ports[i].irq == 0xff)
lpt_ports[i].irq_state = 0x00;
else {
picintclevel(lpt_ports[i].irq, &lpt_ports[i].irq_state);
picintc(lpt_ports[i].irq);
}
}
lpt_ports[i].enable_irq = 0x00;
lpt_ports[i].ext = !!(machine_has_bus(machine, MACHINE_BUS_MCA));
lpt_ports[i].epp = 0;
lpt_ports[i].ecp = 0;
lpt_ports[i].ecr = 0x15;
lpt_ports[i].dat = 0xff;
lpt_ports[i].fifo_stat = 0x00;
lpt_ports[i].dma_stat = 0x00;
}
}
}
void
lpt_init(void)
{
const uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR };
const uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ };
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].id = i;
lpt_ports[i].dt = NULL;
lpt_ports[i].priv = NULL;
lpt_ports[i].fifo = NULL;
memset(&lpt_ports[i].fifo_out_timer, 0x00, sizeof(pc_timer_t));
lpt_port_zero(&(lpt_ports[i]));
lpt_ports[i].addr = 0xffff;
lpt_ports[i].irq = 0xff;
lpt_ports[i].dma = 0xff;
lpt_ports[i].enable_irq = 0x00;
lpt_ports[i].ext = 0;
lpt_ports[i].epp = 0;
lpt_ports[i].ecp = 0;
lpt_ports[i].ecr = 0x15;
if (lpt_ports[i].enabled) {
lpt_port_setup(i, default_ports[i]);
lpt_port_irq(i, default_irqs[i]);
lpt_ports[i].fifo = fifo16_init();
fifo_set_trigger_len(lpt_ports[i].fifo, 8);
fifo_set_d_ready_evt(lpt_ports[i].fifo, lpt_fifo_d_ready_evt);
fifo_set_priv(lpt_ports[i].fifo, &lpt_ports[i]);
timer_add(&lpt_ports[i].fifo_out_timer, lpt_fifo_out_callback, &lpt_ports[i], 0);
}
}
}
void
lpt_port_setup(const int i, const uint16_t port)
{
if (lpt_ports[i].enabled) {
if (lpt_ports[i].addr != 0xffff) {
io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
}
if (port != 0xffff) {
lpt_log("Set handler: %04X-%04X\n", port, port + 0x0003);
io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].epp)
io_sethandler(lpt_ports[i].addr + 0x0003, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].ecp || lpt_ports[i].lv2) {
io_sethandler(port + 0x0400, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if (lpt_ports[i].epp)
io_sethandler(lpt_ports[i].addr + 0x0403, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
}
}
lpt_ports[i].addr = port;
} else
lpt_ports[i].addr = 0xffff;
}
void
lpt_port_irq(const int i, const uint8_t irq)
{
if (lpt_ports[i].enabled)
lpt_ports[i].irq = irq;
else
lpt_ports[i].irq = 0xff;
lpt_log("Port %i IRQ = %02X\n", i, irq);
}
void
lpt_port_dma(const int i, const uint8_t dma)
{
if (lpt_ports[i].enabled)
lpt_ports[i].dma = dma;
else
lpt_ports[i].dma = 0xff;
lpt_log("Port %i DMA = %02X\n", i, dma);
}
void
lpt_port_remove(const int i)
{
if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) {
io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = 0xffff;
}
}
void
lpt1_remove_ams(void)
{
if (lpt_ports[0].enabled)
io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]);
}

View File

@@ -13,7 +13,7 @@
* Jasmine Iwanek <jasmine@iwanek.co.uk>
*
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#include <stdarg.h>
@@ -222,10 +222,15 @@ serial_passthrough_dev_init(const device_t *info)
}
const char *serpt_mode_names[SERPT_MODES_MAX] = {
[SERPT_MODE_VCON] = "vcon",
[SERPT_MODE_TCPSRV] = "tcpsrv",
[SERPT_MODE_TCPCLNT] = "tcpclnt",
[SERPT_MODE_HOSTSER] = "hostser",
#ifdef _WIN32
[SERPT_MODE_NPIPE_SRV] = "npipesrv",
[SERPT_MODE_NPIPE_CLNT] = "npipeclnt",
#else
[SERPT_MODE_VCON] = "vcon",
#endif
[SERPT_MODE_TCP_SRV] = "tcpsrv",
[SERPT_MODE_TCP_CLNT] = "tcpclnt",
[SERPT_MODE_HOSTSER] = "hostser",
};
// clang-format off
@@ -240,19 +245,17 @@ static const device_config_t serial_passthrough_config[] = {
.spinner = { 0 },
.selection = {
#ifdef _WIN32
{ .description = "Named Pipe (Server)", .value = SERPT_MODE_VCON },
#if 0 /* TODO */
{ .description = "Named Pipe (Client)", .value = SERPT_MODE_VCON },
#endif
{ .description = "Named Pipe (Server)", .value = SERPT_MODE_NPIPE_SRV },
{ .description = "Named Pipe (Client)", .value = SERPT_MODE_NPIPE_CLNT },
#else /* _WIN32 */
{ .description = "Pseudo Terminal/Virtual Console", .value = SERPT_MODE_VCON },
{ .description = "Pseudo Terminal/Virtual Console", .value = SERPT_MODE_VCON },
#endif /* _WIN32 */
#if 0 /* TODO */
{ .description = "TCP Server", .value = SERPT_MODE_TCPSRV },
{ .description = "TCP Client", .value = SERPT_MODE_TCPCLNT },
{ .description = "TCP Server", .value = SERPT_MODE_TCP_SRV },
{ .description = "TCP Client", .value = SERPT_MODE_TCP_CLNT },
#endif
{ .description = "Host Serial Passthrough", .value = SERPT_MODE_HOSTSER },
{ .description = "" }
{ .description = "Host Serial Passthrough", .value = SERPT_MODE_HOSTSER },
{ .description = "" }
},
.bios = { { 0 } }
},

View File

@@ -56,35 +56,40 @@ static const struct {
// clang-format off
{ &device_none },
{ &device_internal },
{ &st506_xt_xebec_device },
{ &st506_xt_wdxt_gen_device },
/* ISA */
{ &xtide_acculogic_device },
{ &st506_xt_dtc5150x_device },
{ &st506_xt_xebec_device },
{ &xtide_device },
{ &st506_xt_st11_m_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_xt_wd1004a_wx1_device },
{ &st506_at_wd1003_device },
{ &st506_xt_st11_r_device },
{ &st506_xt_victor_v86p_device },
{ &st506_xt_wd1002a_27x_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_xt_wd1004_27x_device },
{ &st506_xt_wd1004a_27x_device },
{ &st506_xt_victor_v86p_device },
{ &esdi_at_wd1007vse1_device },
{ &st506_xt_wd1004a_wx1_device },
{ &xta_wdxt150_device },
{ &st506_xt_wdxt_gen_device },
/* ISA16 */
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_2ch_device },
{ &xtide_at_ps2_device },
{ &xtide_at_ps2_2ch_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },
{ &st506_at_wd1003_device },
{ &esdi_at_wd1007vse1_device },
/* MCA */
{ &esdi_ps2_device },
{ &esdi_integrated_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ &mcide_device },
/* VLB */
{ &ide_vlb_device },
{ &ide_vlb_2ch_device },
{ &mcide_device },
/* PCI */
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ NULL }
// clang-format on
};

View File

@@ -154,7 +154,7 @@ xtide_init(const device_t *info)
sprintf(xtide->nvr_path, "xtide_%i.nvr", device_get_instance());
FILE *fp = nvr_fopen(xtide->nvr_path, "rb");
if (fp != NULL) {
fread(xtide->bios_rom.rom, 1, 0x2000, fp);
(void) !fread(xtide->bios_rom.rom, 1, 0x2000, fp);
fclose(fp);
}
}

View File

@@ -56,7 +56,9 @@ typedef struct hdd_image_t {
hdd_image_t hdd_images[HDD_NUM];
static char empty_sector[512];
#ifndef __unix__
static char *empty_sector_1mb;
#endif
#ifdef ENABLE_HDD_IMAGE_LOG
int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG;

View File

@@ -191,7 +191,7 @@ fdc_ctrl_reset(void *priv)
fdc->step = 0;
fdc->power_down = 0;
if (!fdc->lock) {
if (!fdc->lock && !fdc->fifointest) {
fdc->fifo = 0;
fdc->tfifo = 1;
@@ -808,6 +808,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->tfifo = 1;
fdc->fifointest = 0;
}
fifo_reset(fdc->fifo_p);
fifo_set_len(fdc->fifo_p, fdc->tfifo + 1);
fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1);
}
return;
case 4: /* DSR */

View File

@@ -15,7 +15,7 @@
*
* Copyright 2016-2022 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2021 RichardG.
* Copyright 2021 RichardG.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#include <stdio.h>
@@ -90,11 +90,18 @@ static const struct {
} joysticks[] = {
{ &joystick_none },
{ &joystick_2axis_2button },
{ &joystick_2button_gamepad },
{ &joystick_2button_flight_yoke },
{ &joystick_2axis_4button },
{ &joystick_4button_gamepad },
{ &joystick_4button_flight_yoke },
{ &joystick_2axis_6button },
{ &joystick_2axis_8button },
{ &joystick_3axis_2button },
{ &joystick_2button_yoke_throttle },
{ &joystick_3axis_4button },
{ &joystick_win95_steering_wheel }, // Temp
{ &joystick_4button_yoke_throttle },
{ &joystick_4axis_4button },
{ &joystick_ch_flightstick_pro },
{ &joystick_ch_flightstick_pro_ch_pedals },

View File

@@ -8,13 +8,14 @@
*
* Implementation of a standard joystick.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2021-2025 Jasmine Iwanek.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -147,6 +148,40 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis)
}
}
#if 0
// For later use
static int
joystick_standard_read_axis_with_pov(UNUSED(void *priv), int axis)
{
if (!JOYSTICK_PRESENT(0, 0))
return AXIS_NOT_PRESENT;
switch (axis) {
case 0: // X-axis
return joystick_state[0][0].axis[0];
case 1: // Y-axis
return joystick_state[0][0].axis[1];
case 2: // POV Hat (mapped to the 3rd logical axis, index 2)
if (joystick_state[0][0].pov[0] == -1)
return 32767; // Centered/No input (as per tm_fcs_rcs_read_axis example)
if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45)
return -32768; // Up
if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135)
return -16384; // Up-Right (example value, matches tm_fcs_rcs_read_axis)
if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225)
return 0; // Right/Left (example, matches tm_fcs_rcs_read_axis)
if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315)
return 16384; // Down-Left (example value, matches tm_fcs_rcs_read_axis)
return 0; // Fallback
case 3: // This case might be used for a Z-axis if present, or can return 0 if not.
// For gamepads with only X/Y and POV, this will likely be unused or return 0.
return 0;
default:
return 0;
}
}
#endif
static int
joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis)
{
@@ -257,6 +292,42 @@ const joystick_if_t joystick_2axis_2button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_gamepad = {
.name = "2-button gamepad(s)",
.internal_name = "2button_gamepad",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis,
.a0_over = joystick_standard_a0_over,
.axis_count = 2,
.button_count = 2,
.pov_count = 0,
.max_joysticks = 2,
.axis_names = { "X axis", "Y axis" },
.button_names = { "Button 1", "Button 2" },
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_flight_yoke = {
.name = "2-button flight yoke",
.internal_name = "2button_flight_yoke",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis,
.a0_over = joystick_standard_a0_over,
.axis_count = 2,
.button_count = 2,
.pov_count = 0,
.max_joysticks = 2,
.axis_names = { "Roll axis", "Pitch axis" },
.button_names = { "Trigger", "Button 2" },
.pov_names = { NULL }
};
const joystick_if_t joystick_2axis_4button = {
.name = "2-axis, 4-button joystick",
.internal_name = "2axis_4button",
@@ -275,6 +346,42 @@ const joystick_if_t joystick_2axis_4button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_gamepad = {
.name = "4-button gamepad",
.internal_name = "4button_gamepad",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read_4button,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis_4button,
.a0_over = joystick_standard_a0_over,
.axis_count = 2,
.button_count = 4,
.pov_count = 0,
.max_joysticks = 1,
.axis_names = { "X axis", "Y axis" },
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_flight_yoke = {
.name = "4-button flight yoke",
.internal_name = "4button_flight_yoke",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read_4button,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis_4button,
.a0_over = joystick_standard_a0_over,
.axis_count = 2,
.button_count = 4,
.pov_count = 0,
.max_joysticks = 1,
.axis_names = { "Roll axis", "Pitch axis" },
.button_names = { "Trigger", "Button 2", "Button 3", "Button 4" },
.pov_names = { NULL }
};
const joystick_if_t joystick_3axis_2button = {
.name = "3-axis, 2-button joystick",
.internal_name = "3axis_2button",
@@ -293,6 +400,24 @@ const joystick_if_t joystick_3axis_2button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_yoke_throttle = {
.name = "2-button flight yoke with throttle",
.internal_name = "2button_yoke_throttle",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis_3axis,
.a0_over = joystick_standard_a0_over,
.axis_count = 3,
.button_count = 2,
.pov_count = 0,
.max_joysticks = 1,
.axis_names = { "Roll axis", "Pitch axis", "Throttle axis" },
.button_names = { "Trigger", "Button 2" },
.pov_names = { NULL }
};
const joystick_if_t joystick_3axis_4button = {
.name = "3-axis, 4-button joystick",
.internal_name = "3axis_4button",
@@ -311,6 +436,42 @@ const joystick_if_t joystick_3axis_4button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_yoke_throttle = {
.name = "4-button flight yoke with throttle",
.internal_name = "4button_yoke_throttle",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read_4button,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis_3axis,
.a0_over = joystick_standard_a0_over,
.axis_count = 3,
.button_count = 4,
.pov_count = 0,
.max_joysticks = 1,
.axis_names = { "Roll axis", "Pitch axis", "Throttle axis" },
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { NULL }
};
const joystick_if_t joystick_win95_steering_wheel = {
.name = "Win95 Steering Wheel (3-axis, 4-button)",
.internal_name = "win95_steering_wheel",
.init = joystick_standard_init,
.close = joystick_standard_close,
.read = joystick_standard_read_4button,
.write = joystick_standard_write,
.read_axis = joystick_standard_read_axis_3axis,
.a0_over = joystick_standard_a0_over,
.axis_count = 3,
.button_count = 4,
.pov_count = 0,
.max_joysticks = 1,
.axis_names = { "Steering axis", "Accelerator axis", "Brake axis" },
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { NULL }
};
const joystick_if_t joystick_4axis_4button = {
.name = "4-axis, 4-button joystick",
.internal_name = "4axis_4button",

View File

@@ -15,7 +15,7 @@
*
* Copyright 2016-2022 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2021 RichardG.
* Copyright 2021 RichardG.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#ifndef EMU_GAMEPORT_H
@@ -52,6 +52,26 @@
#define GAMEPORT_8ADDR 0x080000
#define GAMEPORT_SIO 0x1000000
typedef struct joystick_if_t {
const char *name;
const char *internal_name;
void *(*init)(void);
void (*close)(void *priv);
uint8_t (*read)(void *priv);
void (*write)(void *priv);
int (*read_axis)(void *priv, int axis);
void (*a0_over)(void *priv);
int axis_count;
int button_count;
int pov_count;
int max_joysticks;
const char *axis_names[MAX_JOY_AXES];
const char *button_names[MAX_JOY_BUTTONS];
const char *pov_names[MAX_JOY_POVS];
} joystick_if_t;
typedef struct plat_joystick_t {
char name[260];
@@ -90,26 +110,6 @@ typedef struct joystick_t {
int pov_mapping[MAX_JOY_POVS][2];
} joystick_t;
typedef struct joystick_if_t {
const char *name;
const char *internal_name;
void *(*init)(void);
void (*close)(void *priv);
uint8_t (*read)(void *priv);
void (*write)(void *priv);
int (*read_axis)(void *priv, int axis);
void (*a0_over)(void *priv);
int axis_count;
int button_count;
int pov_count;
int max_joysticks;
const char *axis_names[MAX_JOY_AXES];
const char *button_names[MAX_JOY_BUTTONS];
const char *pov_names[MAX_JOY_POVS];
} joystick_if_t;
extern device_t game_ports[GAMEPORT_MAX];
#ifdef __cplusplus
@@ -171,9 +171,16 @@ extern void gameport_remap(void *priv, uint16_t address);
extern void *gameport_add(const device_t *gameport_type);
extern const joystick_if_t joystick_2axis_2button;
extern const joystick_if_t joystick_2button_gamepad;
extern const joystick_if_t joystick_2button_flight_yoke;
extern const joystick_if_t joystick_2axis_4button;
extern const joystick_if_t joystick_4button_gamepad;
extern const joystick_if_t joystick_4button_flight_yoke;
extern const joystick_if_t joystick_3axis_2button;
extern const joystick_if_t joystick_2button_yoke_throttle;
extern const joystick_if_t joystick_3axis_4button;
extern const joystick_if_t joystick_4button_yoke_throttle;
extern const joystick_if_t joystick_win95_steering_wheel;
extern const joystick_if_t joystick_4axis_4button;
extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
@@ -186,14 +193,6 @@ extern const joystick_if_t joystick_sw_pad;
extern const joystick_if_t joystick_tm_fcs;
extern const joystick_if_t joystick_tm_fcs_rcs;
extern int gameport_available(int);
extern int gameport_has_config(int);
extern const char *gameport_get_internal_name(int);
extern int gampeport_get_from_internal_name(char *);
#ifdef EMU_DEVICE_H
extern const device_t *gameport_getdevice(int);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -25,14 +25,24 @@ typedef struct lpt_device_t {
void (*close)(void *priv);
void (*write_data)(uint8_t val, void *priv);
void (*write_ctrl)(uint8_t val, void *priv);
uint8_t (*read_data)(void *priv);
void (*autofeed)(uint8_t val,void *priv);
void (*strobe)(uint8_t old, uint8_t val,void *priv);
uint8_t (*read_status)(void *priv);
uint8_t (*read_ctrl)(void *priv);
void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv);
void (*epp_request_read)(uint8_t is_addr, void *priv);
} lpt_device_t;
extern void lpt_set_ext(int port, uint8_t ext);
extern void lpt_set_ecp(int port, uint8_t ecp);
extern void lpt_set_epp(int port, uint8_t epp);
extern void lpt_set_lv2(int port, uint8_t lv2);
extern void lpt_reset(void);
extern void lpt_close(void);
extern void lpt_init(void);
extern void lpt_port_setup(int i, uint16_t port);
extern void lpt_port_irq(int i, uint8_t irq);
extern void lpt_port_dma(int i, uint8_t dma);
extern void lpt_port_remove(int i);
extern void lpt1_remove_ams(void);
@@ -68,31 +78,62 @@ void lpt_devices_close(void);
typedef struct lpt_port_t {
uint8_t enabled;
uint8_t irq;
uint8_t irq_state;
uint8_t dma;
uint8_t dat;
uint8_t ctrl;
uint8_t ext;
uint8_t epp;
uint8_t ecp;
uint8_t ecr;
uint8_t in_dat;
uint8_t fifo_stat;
uint8_t dma_stat;
uint8_t state;
uint8_t autofeed;
uint8_t strobe;
uint8_t lv2;
uint8_t pad[7];
uint16_t addr;
uint16_t pad0;
uint16_t id;
uint16_t pad0[2];
int device;
int enable_irq;
lpt_device_t *dt;
#ifdef FIFO_H
fifo16_t *fifo;
#else
void *fifo;
#endif
void *priv;
pc_timer_t fifo_out_timer;
} lpt_port_t;
typedef enum {
LPT_STATE_IDLE = 0,
LPT_STATE_READ_DMA,
LPT_STATE_WRITE_FIFO
} lpt_state_t;
extern lpt_port_t lpt_ports[PARALLEL_MAX];
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t lpt_read(uint16_t port, void *priv);
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t lpt_read_port(int port, uint16_t reg);
extern void lpt_write_to_fifo(void *priv, uint8_t val);
extern uint8_t lpt_read_status(int port);
extern void lpt_irq(void *priv, int raise);
extern uint8_t lpt_read(uint16_t port, void *priv);
extern uint8_t lpt_read_port(int port, uint16_t reg);
extern uint8_t lpt_read_status(int port);
extern void lpt_irq(void *priv, int raise);
extern int lpt_device_get_from_internal_name(const char *s);
extern const char *lpt_device_get_name(int id);
extern const char *lpt_device_get_internal_name(int id);
extern int lpt_device_get_from_internal_name(char *s);
extern const lpt_device_t lpt_dac_device;
extern const lpt_device_t lpt_dac_stereo_device;

View File

@@ -469,6 +469,7 @@ extern int machine_at_quadt386sx_init(const machine_t *);
extern int machine_at_award286_init(const machine_t *);
extern int machine_at_gdc212m_init(const machine_t *);
extern int machine_at_gw286ct_init(const machine_t *);
extern int machine_at_drsm35286_init(const machine_t *);
extern int machine_at_senor_scat286_init(const machine_t *);
extern int machine_at_super286c_init(const machine_t *);
extern int machine_at_super286tr_init(const machine_t *);
@@ -517,6 +518,7 @@ extern int machine_at_dataexpert386wb_init(const machine_t *);
extern int machine_at_isa486c_init(const machine_t *);
extern int machine_at_genoa486_init(const machine_t *);
extern int machine_at_ga486l_init(const machine_t *);
extern int machine_at_cobalt_init(const machine_t *);
extern int machine_at_cougar_init(const machine_t *);
extern int machine_at_acc386_init(const machine_t *);
@@ -653,6 +655,7 @@ extern void machine_at_award_common_init(const machine_t *);
extern void machine_at_sp4_common_init(const machine_t *model);
extern int machine_at_v12p_init(const machine_t *);
extern int machine_at_excaliburpci_init(const machine_t *);
extern int machine_at_p5mp3_init(const machine_t *);
extern int machine_at_dellxp60_init(const machine_t *);

View File

@@ -265,12 +265,16 @@ extern uint32_t biosmask;
extern uint32_t biosaddr;
extern int readlookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern uintptr_t *readlookup2;
#endif
extern uintptr_t old_rl2;
extern uint8_t uncached;
extern int readlnext;
extern int writelookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern uintptr_t *writelookup2;
#endif
extern int writelnext;
extern uint32_t ram_mapped_addr[64];
extern uint8_t page_ff[4096];
@@ -288,7 +292,16 @@ extern mem_mapping_t bios_high_mapping;
extern uint32_t mem_logical_addr;
extern page_t *pages;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern page_t **page_lookup;
#endif
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
/* The lookup tables. */
extern page_t *page_lookup[1048576];
extern uintptr_t readlookup2[1048576];
extern uintptr_t writelookup2[1048576];
#endif
extern uint32_t get_phys_virt;
extern uint32_t get_phys_phys;
@@ -457,6 +470,9 @@ extern void mem_a20_init(void);
extern void mem_a20_recalc(void);
extern void mem_init(void);
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
extern void mem_free(void);
#endif
extern void mem_close(void);
extern void mem_zero(void);
extern void mem_reset(void);

View File

@@ -52,6 +52,7 @@
#define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */
#define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */
#define NET_TYPE_VDE 3 /* use the VDE plug API */
#define NET_TYPE_TAP 4 /* use a linux TAP device */
#define NET_MAX_FRAME 1518
/* Queue size must be a power of 2 */
@@ -126,6 +127,7 @@ typedef struct netdrv_t {
extern const netdrv_t net_pcap_drv;
extern const netdrv_t net_slirp_drv;
extern const netdrv_t net_vde_drv;
extern const netdrv_t net_tap_drv;
extern const netdrv_t net_null_drv;
struct _netcard_t {
@@ -155,10 +157,11 @@ typedef struct {
int has_slirp;
int has_pcap;
int has_vde;
int has_tap;
} network_devmap_t;
#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde)
#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde || x.has_tap)
#ifdef __cplusplus
extern "C" {

View File

@@ -0,0 +1,40 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* definitions for renderers
*
* Authors: Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2025 Jasmine Iwanek.
*/
#ifndef EMU_RENDERDEFS_H
#define EMU_RENDERDEFS_H
#define RENDERER_NAME_DEFAULT "default"
#define RENDERER_NAME_SYSTEM "system"
#define RENDERER_NAME_QT_SOFTWARE "qt_software"
#define RENDERER_NAME_QT_OPENGL "qt_opengl"
#define RENDERER_NAME_QT_OPENGLES "qt_opengles"
#define RENDERER_NAME_QT_OPENGL3 "qt_opengl3"
#define RENDERER_NAME_QT_VULKAN "qt_vulkan"
#define RENDERER_NAME_VNC "vnc"
#define RENDERER_SOFTWARE 0
#define RENDERER_OPENGL3 1
#define RENDERER_VULKAN 2
#define RENDERER_VNC 3
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /*EMU_RENDERDEFS_H*/

View File

@@ -13,7 +13,7 @@
* Jasmine Iwanek <jasmine@iwanek.co.uk>
*
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
* Copyright 2021-2025 Jasmine Iwanek.
*/
#ifndef SERIAL_PASSTHROUGH_H
@@ -28,10 +28,15 @@
#include <86box/serial.h>
enum serial_passthrough_mode {
SERPT_MODE_VCON, /*Named Pipe (Server) / Pseudo Terminal/Virtual Console */
SERPT_MODE_TCPSRV, /* TCP Server (TODO) */
SERPT_MODE_TCPCLNT, /* TCP Client (TODO) */
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
#ifdef _WIN32
SERPT_MODE_NPIPE_SRV, /* Named Pipe (Server) */
SERPT_MODE_NPIPE_CLNT, /* Named Pipe (Client) */
#else
SERPT_MODE_VCON, /* Pseudo Terminal/Virtual Console */
#endif
SERPT_MODE_TCP_SRV, /* TCP Server (TODO) */
SERPT_MODE_TCP_CLNT, /* TCP Client (TODO) */
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
SERPT_MODES_MAX,
};

View File

@@ -20,8 +20,6 @@
extern const device_t acc3221_device;
/* Acer / ALi */
extern const device_t ali5105_device;
extern const device_t ali5123_device;
/* Chips & Technologies */
@@ -79,10 +77,13 @@ extern const device_t i82091aa_398_device;
extern const device_t i82091aa_ide_pri_device;
extern const device_t i82091aa_ide_device;
/* National Semiconductors */
extern const device_t pc87310_device;
extern const device_t pc87310_ide_device;
/* National Semiconductors PC87310 / ALi M5105 */
#define PC87310_IDE 0x0001
#define PC87310_ALI 0x0002
extern const device_t pc87310_device;
/* National Semiconductors */
extern const device_t pc87306_device;
extern const device_t pc87311_device;
extern const device_t pc87311_ide_device;
@@ -92,6 +93,7 @@ extern const device_t pc87332_398_ide_device;
extern const device_t pc87332_398_ide_sec_device;
extern const device_t pc87332_398_ide_fdcon_device;
/* National Semiconductors PC87307 / PC87309 */
#define PCX7307_PC87307 0x00c0
#define PCX7307_PC97307 0x00cf

View File

@@ -4,7 +4,7 @@
#ifdef __cplusplus
extern "C" {
#endif
void *sid_init(uint8_t type);
void *sid_init(uint8_t type, double range);
void sid_close(void *priv);
void sid_reset(void *priv);
uint8_t sid_read(uint16_t addr, void *priv);

View File

@@ -37,6 +37,13 @@ typedef enum {
EXTENSIONS_MAX
} ibm8514_extensions_t;
typedef enum {
VGA_MODE = 0,
IBM_MODE,
ATI_MODE,
MODE_MAX
} ibm8514_mode_t;
typedef struct hwcursor8514_t {
int ena;
int x;
@@ -202,6 +209,7 @@ typedef struct ibm8514_t {
int split;
int h_disp;
int h_total;
int h_sync_start;
int h_sync_width;
int h_disp_time;
int rowoffset;
@@ -260,6 +268,7 @@ typedef struct ibm8514_t {
int ext_pitch;
int ext_crt_pitch;
ibm8514_extensions_t extensions;
ibm8514_mode_t mode;
int onboard;
int linear;
uint32_t vram_amount;

View File

@@ -18,6 +18,12 @@
#ifndef VIDEO_ATI_MACH8_H
#define VIDEO_ATI_MACH8_H
typedef enum {
ATI_68875 = 0,
ATI_68860,
RAMDAC_MAX
} mach_ramdac_type;
typedef struct mach_t {
ati_eeprom_t eeprom;
svga_t svga;
@@ -39,7 +45,7 @@ typedef struct mach_t {
uint8_t irq_state;
int index;
int ramdac_type;
mach_ramdac_type ramdac_type;
int old_mode;
uint16_t config1;

View File

@@ -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*/

View 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_ */

View File

@@ -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 {
@@ -136,6 +137,10 @@ typedef struct svga_t {
int packed_4bpp;
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
@@ -281,6 +286,10 @@ typedef struct svga_t {
you should set this flag when entering that mode*/
int disable_blink;
/*Force special shifter bypass logic for 8-bpp lowres modes.
Needed if the screen is squished on certain S3 cards.*/
int force_shifter_bypass;
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
@@ -404,15 +413,15 @@ uint32_t svga_lookup_lut_ram(svga_t* svga, uint32_t val);
/* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and
possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68860_ramdac_in(uint16_t addr, int is_8514, void *priv, svga_t *svga);
extern void ati68860_set_ramdac_type(void *priv, int type);
extern void ati68860_ramdac_set_render(void *priv, svga_t *svga);
extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col);
extern void ati68860_hwcursor_draw(svga_t *svga, int displine);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, int is_8514, void *priv, svga_t *svga);
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, int is_8514, void *priv, svga_t *svga);
extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);

View File

@@ -55,13 +55,10 @@ 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);
extern void svga_render_8bpp_gs_lowres(svga_t *svga);
extern void svga_render_8bpp_gs_highres(svga_t *svga);
extern void svga_render_8bpp_rgb_lowres(svga_t *svga);
extern void svga_render_8bpp_rgb_highres(svga_t *svga);
extern void svga_render_15bpp_lowres(svga_t *svga);
extern void svga_render_15bpp_highres(svga_t *svga);
extern void svga_render_15bpp_mix_lowres(svga_t *svga);

View File

@@ -358,6 +358,7 @@ extern const device_t chips_69000_onboard_device;
/* Cirrus Logic GD54xx */
extern const device_t gd5401_isa_device;
extern const device_t gd5401_onboard_device;
extern const device_t gd5402_isa_device;
extern const device_t gd5402_onboard_device;
extern const device_t gd5420_isa_device;
@@ -398,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;
@@ -490,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;

264
src/lpt.c
View File

@@ -1,264 +0,0 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/lpt.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/prt_devs.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/network.h>
lpt_port_t lpt_ports[PARALLEL_MAX];
const lpt_device_t lpt_none_device = {
.name = "None",
.internal_name = "none",
.init = NULL,
.close = NULL,
.write_data = NULL,
.write_ctrl = NULL,
.read_data = NULL,
.read_status = NULL,
.read_ctrl = NULL
};
static const struct {
const char *internal_name;
const lpt_device_t *device;
} lpt_devices[] = {
// clang-format off
{"none", &lpt_none_device },
{"dss", &dss_device },
{"lpt_dac", &lpt_dac_device },
{"lpt_dac_stereo", &lpt_dac_stereo_device },
{"text_prt", &lpt_prt_text_device },
{"dot_matrix", &lpt_prt_escp_device },
{"postscript", &lpt_prt_ps_device },
#ifdef USE_PCL
{"pcl", &lpt_prt_pcl_device },
#endif
{"plip", &lpt_plip_device },
{"dongle_savquest", &lpt_hasp_savquest_device },
{"", NULL }
// clang-format on
};
const char *
lpt_device_get_name(int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
if (!lpt_devices[id].device)
return "None";
return lpt_devices[id].device->name;
}
const char *
lpt_device_get_internal_name(int id)
{
if (strlen(lpt_devices[id].internal_name) == 0)
return NULL;
return lpt_devices[id].internal_name;
}
int
lpt_device_get_from_internal_name(char *s)
{
int c = 0;
while (strlen(lpt_devices[c].internal_name) != 0) {
if (strcmp(lpt_devices[c].internal_name, s) == 0)
return c;
c++;
}
return 0;
}
void
lpt_devices_init(void)
{
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device;
if (lpt_ports[i].dt && lpt_ports[i].dt->init)
lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]);
}
}
void
lpt_devices_close(void)
{
lpt_port_t *dev;
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
dev = &lpt_ports[i];
if (lpt_ports[i].dt && lpt_ports[i].dt->close)
dev->dt->close(dev->priv);
dev->dt = NULL;
}
}
void
lpt_write(uint16_t port, uint8_t val, void *priv)
{
lpt_port_t *dev = (lpt_port_t *) priv;
switch (port & 3) {
case 0:
if (dev->dt && dev->dt->write_data && dev->priv)
dev->dt->write_data(val, dev->priv);
dev->dat = val;
break;
case 1:
break;
case 2:
if (dev->dt && dev->dt->write_ctrl && dev->priv)
dev->dt->write_ctrl(val, dev->priv);
dev->ctrl = val;
dev->enable_irq = val & 0x10;
break;
default:
break;
}
}
uint8_t
lpt_read(uint16_t port, void *priv)
{
uint8_t ret = 0xff;
lpt_port_t *dev = (lpt_port_t *) priv;
switch (port & 3) {
case 0:
if (dev->dt && dev->dt->read_data && dev->priv)
ret = dev->dt->read_data(dev->priv);
else
ret = dev->dat;
break;
case 1:
if (dev->dt && dev->dt->read_status && dev->priv)
ret = dev->dt->read_status(dev->priv) | 0x07;
else
ret = 0xdf;
break;
case 2:
if (dev->dt && dev->dt->read_ctrl && dev->priv)
ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq;
else
ret = 0xe0 | dev->ctrl | dev->enable_irq;
break;
default:
break;
}
return ret;
}
uint8_t
lpt_read_port(int port, uint16_t reg)
{
lpt_port_t *dev = &(lpt_ports[port]);
uint8_t ret = lpt_read(reg, dev);
return ret;
}
uint8_t
lpt_read_status(int port)
{
lpt_port_t *dev = &(lpt_ports[port]);
uint8_t ret = 0xff;
if (dev->dt && dev->dt->read_status && dev->priv)
ret = dev->dt->read_status(dev->priv) | 0x07;
else
ret = 0xdf;
return ret;
}
void
lpt_irq(void *priv, int raise)
{
const lpt_port_t *dev = (lpt_port_t *) priv;
if (dev->enable_irq && (dev->irq != 0xff)) {
if (raise)
picint(1 << dev->irq);
else
picintc(1 << dev->irq);
}
}
void
lpt_init(void)
{
uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR };
uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ };
for (uint8_t i = 0; i < PARALLEL_MAX; i++) {
lpt_ports[i].addr = 0xffff;
lpt_ports[i].irq = 0xff;
lpt_ports[i].enable_irq = 0x10;
if (lpt_ports[i].enabled) {
lpt_port_setup(i, default_ports[i]);
lpt_port_irq(i, default_irqs[i]);
}
}
}
void
lpt_port_setup(int i, uint16_t port)
{
if (lpt_ports[i].enabled) {
if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000))
io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
if ((port != 0xffff) && (port != 0x0000))
io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = port;
} else
lpt_ports[i].addr = 0xffff;
}
void
lpt_port_irq(int i, uint8_t irq)
{
if (lpt_ports[i].enabled)
lpt_ports[i].irq = irq;
else
lpt_ports[i].irq = 0xff;
}
void
lpt_port_remove(int i)
{
if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) {
io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
lpt_ports[i].addr = 0xffff;
}
}
void
lpt1_remove_ams(void)
{
if (lpt_ports[0].enabled)
io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]);
}

View File

@@ -118,7 +118,7 @@ machine_at_ama932j_init(const machine_t *model)
machine_at_headland_common_init(model, 2);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
return ret;
}
@@ -529,6 +529,28 @@ machine_at_gw286ct_init(const machine_t *model)
return ret;
}
int
machine_at_drsm35286_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/drsm35286/syab04-665821fb81363428830424.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
device_add(&ide_isa_device);
device_add(&fdc37c651_ide_device);
machine_at_scat_init(model, 1, 0);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
return ret;
}
int
machine_at_senor_scat286_init(const machine_t *model)
{
@@ -858,7 +880,7 @@ machine_at_cmdsl386sx25_init(const machine_t *model)
device_add(&ide_isa_device);
device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */
device_add(&vlsi_scamp_device);
@@ -1008,7 +1030,7 @@ machine_at_acer100t_init(const machine_t *model)
if (gfxcard[0] == VID_INTERNAL)
device_add(&oti077_acer100t_device);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
return ret;
}

View File

@@ -535,7 +535,7 @@ machine_at_acera1g_init(const machine_t *model)
device_add(&keyboard_ps2_acer_pci_device);
device_add(&ali5105_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&ide_ali5213_device);
return ret;
@@ -2869,6 +2869,32 @@ machine_at_ga486l_init(const machine_t *model)
return ret;
}
int
machine_at_cobalt_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/cobalt/Cobalt_2.3.BIN",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&opti499_device);
device_add(&ide_opti611_vlb_device);
device_add(&ide_isa_sec_device);
device_add(&fdc37c665_device);
device_add(&keyboard_ps2_ami_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(machine_get_vid_device(machine));
return ret;
}
int
machine_at_cougar_init(const machine_t *model)
{

View File

@@ -41,6 +41,79 @@
#include <86box/video.h>
#include <86box/machine.h>
int
machine_at_v12p_init(const machine_t *model)
{
int ret = 0;
const char* fn;
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 0);
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init(model);
device_add(&ide_isa_device);
pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SCSI, 1, 4, 3, 2);
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 2, 1, 4, 3);
pci_register_slot(0x03, PCI_CARD_NORMAL, 3, 2, 1, 4);
pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 0, 0, 0);
pci_register_slot(0x05, PCI_CARD_NORMAL, 0, 0, 0, 0);
device_add(&i430lx_device);
device_add(&keyboard_ps2_acer_pci_device);
device_add(&sio_zb_device);
device_add_params(&pc87310_device, (void *) (PC87310_ALI));
device_add(&amd_am28f010_flash_device);
return ret;
}
static const device_config_t v12p_config[] = {
// clang-format off
{
.name = "bios_versions",
.description = "BIOS Versions",
.type = CONFIG_BIOS,
.default_string = "v12p_14",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "Core Version 1.2 Version R1.4", .internal_name = "v12p_14", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_14.bin", "" } },
{ .name = "Core Version 1.2 Version R1.6", .internal_name = "v12p_16", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_16.bin", "" } },
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t v12p_device = {
.name = "Acer V12P",
.internal_name = "v12p",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = &v12p_config[0]
};
void
machine_at_premiere_common_init(const machine_t *model, int pci_switch)
{

View File

@@ -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 {

View File

@@ -72,6 +72,7 @@ extern const device_t d943_device;
extern const device_t dells333sl_device;
extern const device_t hot433a_device;
extern const device_t pbl300sx_device;
extern const device_t v12p_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -3141,7 +3142,7 @@ const machine_t machines[] = {
},
/* Has Olivetti KBC firmware. */
{
.name = "[ISA] Olivetti M290",
.name = "[ISA] Olivetti M290/AT&T 6286 WGS",
.internal_name = "m290",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_PROPRIETARY,
@@ -3163,7 +3164,7 @@ const machine_t machines[] = {
.bus_flags = MACHINE_AT,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 640,
.min = 1024,
.max = 16384,
.step = 128
},
@@ -3981,6 +3982,45 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{
.name = "[SCAT] ICL DRS M35/286",
.internal_name = "drsm35286",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_SCAT,
.init = machine_at_drsm35286_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2,
.flags = MACHINE_IDE | MACHINE_VIDEO,
.ram = {
.min = 512,
.max = 5120,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5401_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/2 Type 1 KBC firmware. */
{
.name = "[SCAT] Samsung SPC-4200P",
@@ -7179,6 +7219,45 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{
.name = "[OPTi 499] Alaris Cobalt LPX",
.internal_name = "cobalt",
.type = MACHINE_TYPE_486_S2,
.chipset = MACHINE_CHIPSET_OPTI_499,
.init = machine_at_cobalt_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET3 | CPU_PKG_486BL,
.block = CPU_BLOCK(CPU_P24T),
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2_VLB,
.flags = MACHINE_APM | MACHINE_VIDEO | MACHINE_IDE_DUAL,
.ram = {
.min = 1024,
.max = 65536,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &gd5428_vlb_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey-2 'H' KBC firmware. */
{
.name = "[OPTi 499] Alaris COUGAR 486BL",
@@ -9979,6 +10058,45 @@ const machine_t machines[] = {
/* Socket 4 machines */
/* 430LX */
{
.name = "[i430LX] Acer V12P",
.internal_name = "v12p",
.type = MACHINE_TYPE_SOCKET4,
.chipset = MACHINE_CHIPSET_INTEL_430LX,
.init = machine_at_v12p_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET4,
.block = CPU_BLOCK_NONE,
.min_bus = 60000000,
.max_bus = 66666667,
.min_voltage = 5000,
.max_voltage = 5000,
.min_multi = MACHINE_MULTIPLIER_FIXED,
.max_multi = MACHINE_MULTIPLIER_FIXED
},
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE | MACHINE_APM,
.ram = {
.min = 2048,
.max = 196608,
.step = 2048
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = &v12p_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has AMIKey H KBC firmware (AMIKey-2), per POST screen with BIOS string
shown in the manual. Has PS/2 mouse support with serial-style (DB9)
connector.
@@ -12172,7 +12290,7 @@ const machine_t machines[] = {
.ram = {
.min = 8192,
.max = 131072,
.step = 8192
.step = 4096
},
.nvrmask = 511,
.kbc_device = NULL,
@@ -14612,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
},
@@ -14652,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
},

View File

@@ -67,7 +67,9 @@ mem_mapping_t bios_mapping;
mem_mapping_t bios_high_mapping;
page_t *pages; /* RAM page table */
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
page_t **page_lookup; /* pagetable lookup */
#endif
uint32_t pages_sz; /* #pages in table */
uint8_t *ram; /* the virtual RAM */
@@ -85,12 +87,23 @@ uint8_t *pccache2;
int readlnext;
int readlookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
uintptr_t *readlookup2;
#endif
uintptr_t old_rl2;
uint8_t uncached = 0;
int writelnext;
int writelookup[256];
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
uintptr_t *writelookup2;
#endif
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
/* The lookup tables. */
page_t *page_lookup[1048576] = { 0 };
uintptr_t readlookup2[1048576] = { 0 };
uintptr_t writelookup2[1048576] = { 0 };
#endif
uint32_t mem_logical_addr;
@@ -2987,12 +3000,25 @@ mem_init(void)
ram2 = NULL;
pages = NULL;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
/* Allocate the lookup tables. */
page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *));
readlookup2 = malloc((1 << 20) * sizeof(uintptr_t));
writelookup2 = malloc((1 << 20) * sizeof(uintptr_t));
#endif
}
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
void
mem_free(void)
{
free(page_lookup);
free(readlookup2);
free(writelookup2);
}
#endif
static void
umc_page_recalc(uint32_t c, uint32_t phys, int set)
{

View File

@@ -70,5 +70,14 @@ if (UNIX)
endif()
endif()
endif()
if (UNIX AND NOT APPLE) # Support for TAP on Linux and BSD, supposedly.
find_path(HAS_TAP "linux/if_tun.h" PATHS ${TAP_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" )
if(HAS_TAP)
add_compile_definitions(HAS_TAP)
list(APPEND net_sources net_tap.c)
else()
message(WARNING "TAP support not available. Are you on some BSD?")
endif()
endif()
add_library(net OBJECT ${net_sources})

View File

@@ -488,15 +488,18 @@ plip_close(void *priv)
}
const lpt_device_t lpt_plip_device = {
.name = "Parallel Line Internet Protocol",
.internal_name = "plip",
.init = plip_lpt_init,
.close = plip_close,
.write_data = plip_write_data,
.write_ctrl = plip_write_ctrl,
.read_data = NULL,
.read_status = plip_read_status,
.read_ctrl = NULL
.name = "Parallel Line Internet Protocol",
.internal_name = "plip",
.init = plip_lpt_init,
.close = plip_close,
.write_data = plip_write_data,
.write_ctrl = plip_write_ctrl,
.autofeed = NULL,
.strobe = NULL,
.read_status = plip_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
const device_t plip_device = {

353
src/network/net_tap.c Normal file
View File

@@ -0,0 +1,353 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Linux TAP network interface for 86box.
*
* This file was created by looking at the VDE network backend
* as a reference, credit to jguillaumes.
*
* Authors: Doug Johnson <dougvj@gmail.com>
*
*
* Copyright 2023 Doug Johnson
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef _WIN32
# error TAP networking is only supported on Linux
#endif
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdbool.h>
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_arp.h>
#include <linux/sockios.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/network.h>
#include <86box/net_event.h>
typedef struct net_tap_t {
int fd; // tap device file descriptor
netcard_t *card;
thread_t *poll_tid;
net_evt_t tx_event;
net_evt_t stop_event;
netpkt_t pkt_rx;
netpkt_t pkts_tx[NET_QUEUE_LEN];
} net_tap_t;
#ifdef ENABLE_TAP_LOG
int tap_do_log = ENABLE_TAP_LOG;
static void tap_logv(const char *fmt, va_list ap)
{
if (tap_do_log) {
pclog_ex(fmt, ap);
}
}
static void tap_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (tap_do_log) {
va_start(ap, fmt);
tap_logv(fmt, ap);
va_end(ap);
}
va_end(ap);
}
#else
# define tap_log(...) \
do { \
} while (0)
# define tap_logv(...) \
do { \
} while (0)
#endif
static void net_tap_thread(void *priv) {
enum {
NET_EVENT_STOP = 0,
NET_EVENT_TX,
NET_EVENT_RX,
NET_EVENT_TAP,
NET_EVENT_MAX,
};
net_tap_t *tap = priv;
tap_log("TAP: poll thread started.\n");
struct pollfd pfd[NET_EVENT_MAX];
pfd[NET_EVENT_STOP].fd = net_event_get_fd(&tap->stop_event);
pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TX].fd = net_event_get_fd(&tap->tx_event);
pfd[NET_EVENT_TX].events = POLLIN | POLLPRI;
pfd[NET_EVENT_RX].fd = tap->fd;
pfd[NET_EVENT_RX].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TAP].fd = tap->fd;
pfd[NET_EVENT_TAP].events = POLLERR | POLLHUP | POLLPRI;
fcntl(tap->fd, F_SETFL, O_NONBLOCK);
while(1) {
ssize_t ret = poll(pfd, NET_EVENT_MAX, -1);
if (ret < 0) {
tap_log("TAP: poll error: %s\n", strerror(errno));
net_event_set(&tap->stop_event);
break;
}
if (pfd[NET_EVENT_TAP].revents) {
tap_log("TAP: tap close/error event received.\n");
net_event_set(&tap->stop_event);
}
if (pfd[NET_EVENT_TX].revents & POLLIN) {
net_event_clear(&tap->tx_event);
int packets = network_tx_popv(tap->card, tap->pkts_tx,
NET_QUEUE_LEN);
for(int i = 0; i < packets; i++) {
netpkt_t *pkt = &tap->pkts_tx[i];
ssize_t ret = write(tap->fd, pkt->data, pkt->len);
if (ret < 0) {
tap_log("TAP: write error: %s\n", strerror(errno));
}
}
}
if (pfd[NET_EVENT_RX].revents & POLLIN) {
ssize_t len = read(tap->fd, tap->pkt_rx.data, NET_MAX_FRAME);
if (len < 0) {
tap_log("TAP: read error: %s\n", strerror(errno));
continue;
}
tap->pkt_rx.len = len;
network_rx_put_pkt(tap->card, &tap->pkt_rx);
}
if (pfd[NET_EVENT_STOP].revents & POLLIN) {
net_event_clear(&tap->stop_event);
break;
}
}
}
void net_tap_close(void *priv)
{
if (!priv) {
return;
}
net_tap_t *tap = priv;
tap_log("TAP: closing.\n");
net_event_set(&tap->stop_event);
tap_log("TAP: waiting for poll thread to exit.\n");
thread_wait(tap->poll_tid);
tap_log("TAP: poll thread exited.\n");
for(int i = 0; i < NET_QUEUE_LEN; i++) {
free(tap->pkts_tx[i].data);
}
free(tap->pkt_rx.data);
if (tap->fd >= 0) {
close(tap->fd);
}
free(tap);
}
void net_tap_error(char *errbuf, const char* format, ...)
{
va_list ap;
va_start(ap, format);
vsnprintf(errbuf, NET_DRV_ERRBUF_SIZE, format, ap);
tap_log("TAP: %s", errbuf);
va_end(ap);
}
// Error handling macro for the many ioctl calls we use in net_tap_alloc
#define ioctl_or_fail(fd, request, argp) \
do { \
if ((err = ioctl(fd, request, argp)) < 0) { \
tap_log("TAP: ioctl " #request " error: %s\n", strerror(errno)); \
goto fail; \
} \
} while (0)
// Returns -ERRNO so we can get an idea what's wrong
int net_tap_alloc(const uint8_t *mac_addr, const char* bridge_dev)
{
int fd;
struct ifreq ifr = {0};
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
tap_log("TAP: open error: %s\n", strerror(errno));
return -errno;
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
int err;
if ((err = ioctl(fd, TUNSETIFF, &ifr)) < 0) {
tap_log("TAP: ioctl TUNSETIFF error: %s\n", strerror(errno));
close(fd);
return -errno;
}
// Create a socket for ioctl operations
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
tap_log("TAP: socket error: %s\n", strerror(errno));
close(fd);
return -errno;
}
// Bring the interface up
tap_log("TAP: Bringing interface '%s' up.\n", ifr.ifr_name);
ifr.ifr_flags = IFF_UP;
ioctl_or_fail(sock, SIOCSIFFLAGS, &ifr);
// Add interface to bridge, if specified
if (bridge_dev && bridge_dev[0] != '\0') {
// First see if the bridge exists
struct ifreq ifr_bridge;
//NOTE strncpy does not null terminate if the string is too long, I use
// snprintf or strlcpy instead
//strncpy(ifr_bridge.ifr_name, bridge_dev, IFNAMSIZ);
snprintf(ifr_bridge.ifr_name, IFNAMSIZ, "%s", bridge_dev);
if ((err = ioctl(sock, SIOCGIFINDEX, &ifr_bridge)) < 0) {
if (errno != ENODEV) {
tap_log("TAP: ioctl SIOCGIFINDEX error: %s\n", strerror(errno));
goto fail;
} else {
// Create the bridge
ioctl_or_fail(sock, SIOCBRADDBR, &ifr_bridge);
// Set the bridge up
ifr_bridge.ifr_flags = IFF_UP;
ioctl_or_fail(sock, SIOCSIFFLAGS, &ifr_bridge);
}
}
// Get TAP index
ioctl_or_fail(sock, SIOCGIFINDEX, &ifr);
// Add the tap device to the bridge
ifr_bridge.ifr_ifindex = ifr.ifr_ifindex;
ioctl_or_fail(sock, SIOCBRADDIF, &ifr_bridge);
}
// close the socket we used for ioctl operations
close(sock);
tap_log("Allocated tap device %s\n", ifr.ifr_name);
return fd;
// cleanup point used by ioctl_or_fail macro
fail:
close(sock);
close(fd);
return -errno;
}
void net_tap_in_available(void *priv)
{
net_tap_t *tap = priv;
net_event_set(&tap->tx_event);
}
void *
net_tap_init(
const netcard_t *card,
const uint8_t *mac_addr,
void *priv,
char *netdrv_errbuf)
{
const char *bridge_dev = (void *) priv;
int tap_fd = net_tap_alloc(mac_addr, bridge_dev);
if (tap_fd < 0) {
if (tap_fd == -EPERM) {
net_tap_error(
netdrv_errbuf,
"No permissions to allocate tap device. "
"Try adding NET_CAP_ADMIN,NET_CAP_RAW to 86box ("
"sudo setcap 'CAP_NET_RAW,CAP_NET_ADMIN=eip')");
} else {
net_tap_error(
netdrv_errbuf,
"Unable to allocate TAP device: %s",
strerror(-tap_fd));
}
return NULL;
}
if (bridge_dev && bridge_dev[0] != '\0') {
}
net_tap_t *tap = calloc(1, sizeof(net_tap_t));
if (!tap) {
goto alloc_fail;
}
tap->pkt_rx.data = calloc(1, NET_MAX_FRAME);
if (!tap->pkt_rx.data) {
goto alloc_fail;
}
for(int i = 0; i < NET_QUEUE_LEN; i++) {
tap->pkts_tx[i].data = calloc(1, NET_MAX_FRAME);
if (!tap->pkts_tx[i].data) {
goto alloc_fail;
}
}
tap->fd = tap_fd;
tap->card = (netcard_t *) card;
net_event_init(&tap->tx_event);
net_event_init(&tap->stop_event);
tap->poll_tid = thread_create(net_tap_thread, tap);
return tap;
alloc_fail:
net_tap_error(netdrv_errbuf, "Failed to allocate memory");
close(tap_fd);
free(tap);
return NULL;
}
const netdrv_t net_tap_drv = {
&net_tap_in_available,
&net_tap_init,
&net_tap_close,
NULL
};

View File

@@ -85,36 +85,43 @@ static const NETWORK_CARD net_cards[] = {
// clang-format off
{ &device_none },
{ &device_internal },
/* ISA */
{ &threec501_device },
{ &threec503_device },
{ &pcnet_am79c960_device },
{ &pcnet_am79c961_device },
{ &de220p_device },
{ &ne1000_compat_device },
{ &ne2000_compat_device },
{ &ne2000_compat_8bit_device },
{ &ne1000_device },
{ &ne2000_device },
{ &pcnet_am79c960_eb_device },
{ &rtl8019as_pnp_device },
{ &wd8003e_device },
{ &wd8003eb_device },
{ &wd8013ebt_device },
/* COM */
{ &modem_device },
/* LPT */
{ &plip_device },
/* ISA16 */
{ &pcnet_am79c960_device },
{ &pcnet_am79c961_device },
{ &de220p_device },
{ &ne2000_compat_device },
{ &ne2000_device },
{ &pcnet_am79c960_eb_device },
{ &rtl8019as_pnp_device },
/* MCA */
{ &ethernext_mc_device },
{ &wd8003eta_device },
{ &wd8003ea_device },
{ &wd8013epa_device },
/* VLB */
{ &pcnet_am79c960_vlb_device },
/* PCI */
{ &pcnet_am79c973_device },
{ &pcnet_am79c970a_device },
{ &dec_tulip_21140_device },
{ &dec_tulip_21040_device },
{ &dec_tulip_device },
{ &dec_tulip_21140_vpc_device },
{ &rtl8029as_device },
{ &rtl8139c_plus_device },
{ &dec_tulip_21140_device },
{ &dec_tulip_21140_vpc_device },
{ &dec_tulip_21040_device },
{ &pcnet_am79c960_vlb_device },
{ &modem_device },
{ NULL }
// clang-format on
};
@@ -489,6 +496,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
card->host_drv = net_vde_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error);
break;
#endif
#ifdef HAS_TAP
case NET_TYPE_TAP:
card->host_drv = net_tap_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name, net_drv_error);
break;
#endif
default:
card->host_drv.priv = NULL;

View File

@@ -310,18 +310,25 @@ nvr_close(void)
void
nvr_time_sync(void)
{
struct tm *tm;
time_t now;
struct tm tm;
time_t now;
/* Get the current time of day, and convert to local time. */
(void) time(&now);
if (time_sync & TIME_SYNC_UTC)
tm = gmtime(&now);
else
tm = localtime(&now);
/* Set the internal clock. */
nvr_time_set(tm);
#ifdef _WIN32
if (time_sync & TIME_SYNC_UTC)
gmtime_s(&tm, &now);
else
localtime_s(&tm, &now);
#else
if (time_sync & TIME_SYNC_UTC)
gmtime_r(&now, &tm);
else
localtime_r(&now, &tm);
#endif
nvr_time_set(&tm);
}
/* Get current time from internal clock. */

View File

@@ -1881,6 +1881,39 @@ write_data(uint8_t val, void *priv)
dev->data = val;
}
static void
autofeed(uint8_t val, void *priv)
{
escp_t *dev = (escp_t *) priv;
if (dev == NULL)
return;
dev->autofeed = ((val & 0x02) > 0);
}
static void
strobe(uint8_t old, uint8_t val, void *priv)
{
escp_t *dev = (escp_t *) priv;
if (dev == NULL)
return;
/* Data is strobed to the parallel printer on the falling edge of the
strobe bit. */
if (!(val & 0x01) && (old & 0x01)) {
/* Process incoming character. */
handle_char(dev, dev->data);
/* ACK it, will be read on next READ STATUS. */
dev->ack = 1;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
write_ctrl(uint8_t val, void *priv)
{
@@ -1919,14 +1952,6 @@ write_ctrl(uint8_t val, void *priv)
dev->autofeed = ((val & 0x02) > 0);
}
static uint8_t
read_data(void *priv)
{
const escp_t *dev = (escp_t *) priv;
return dev->data;
}
static uint8_t
read_ctrl(void *priv)
{
@@ -2058,13 +2083,16 @@ escp_close(void *priv)
}
const lpt_device_t lpt_prt_escp_device = {
.name = "Generic ESC/P Dot-Matrix Printer",
.internal_name = "dot_matrix",
.init = escp_init,
.close = escp_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.read_data = read_data,
.read_status = read_status,
.read_ctrl = read_ctrl
.name = "Generic ESC/P Dot-Matrix",
.internal_name = "dot_matrix",
.init = escp_init,
.close = escp_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.autofeed = autofeed,
.strobe = strobe,
.read_status = read_status,
.read_ctrl = read_ctrl,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -319,6 +319,35 @@ process_data(ps_t *dev)
dev->buffer[dev->buffer_pos] = 0;
}
static void
ps_autofeed(uint8_t val, void *priv)
{
ps_t *dev = (ps_t *) priv;
if (dev == NULL)
return;
dev->autofeed = val & 0x02 ? true : false;
}
static void
ps_strobe(uint8_t old, uint8_t val, void *priv)
{
ps_t *dev = (ps_t *) priv;
if (dev == NULL)
return;
if (!(val & 0x01) && (old & 0x01)) {
process_data(dev);
dev->ack = true;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
ps_write_ctrl(uint8_t val, void *priv)
{
@@ -479,27 +508,33 @@ ps_close(void *priv)
}
const lpt_device_t lpt_prt_ps_device = {
.name = "Generic PostScript Printer",
.internal_name = "postscript",
.init = ps_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.read_data = NULL,
.read_status = ps_read_status,
.read_ctrl = NULL
.name = "Generic PostScript Printer",
.internal_name = "postscript",
.init = ps_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.autofeed = ps_autofeed,
.strobe = ps_strobe,
.read_status = ps_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
#ifdef USE_PCL
const lpt_device_t lpt_prt_pcl_device = {
.name = "Generic PCL5e Printer",
.internal_name = "pcl",
.init = pcl_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.read_data = NULL,
.read_status = ps_read_status,
.read_ctrl = NULL
.name = "Generic PCL5e Printer",
.internal_name = "pcl",
.init = pcl_init,
.close = ps_close,
.write_data = ps_write_data,
.write_ctrl = ps_write_ctrl,
.autofeed = ps_autofeed,
.strobe = ps_strobe,
.read_status = ps_read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};
#endif

View File

@@ -367,6 +367,38 @@ write_data(uint8_t val, void *priv)
dev->data = val;
}
static void
autofeed(uint8_t val, void *priv)
{
prnt_t *dev = (prnt_t *) priv;
if (dev == NULL)
return;
/* set autofeed value */
dev->autofeed = val & 0x02 ? 1 : 0;
}
static void
strobe(uint8_t old, uint8_t val, void *priv)
{
prnt_t *dev = (prnt_t *) priv;
if (dev == NULL)
return;
if (!(val & 0x01) && (old & 0x01)) { /* STROBE */
/* Process incoming character. */
handle_char(dev);
/* ACK it, will be read on next READ STATUS. */
dev->ack = 1;
timer_set_delay_u64(&dev->pulse_timer, ISACONST);
timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC);
}
}
static void
write_ctrl(uint8_t val, void *priv)
{
@@ -465,13 +497,16 @@ prnt_close(void *priv)
}
const lpt_device_t lpt_prt_text_device = {
.name = "Generic Text Printer",
.internal_name = "text_prt",
.init = prnt_init,
.close = prnt_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.read_data = NULL,
.read_status = read_status,
.read_ctrl = NULL
.name = "Generic Text Printer",
.internal_name = "text_prt",
.init = prnt_init,
.close = prnt_close,
.write_data = write_data,
.write_ctrl = write_ctrl,
.autofeed = autofeed,
.strobe = strobe,
.read_status = read_status,
.read_ctrl = NULL,
.epp_write_data = NULL,
.epp_request_read = NULL
};

View File

@@ -85,8 +85,6 @@ add_library(ui STATIC
qt_renderercommon.hpp
qt_softwarerenderer.cpp
qt_softwarerenderer.hpp
qt_hardwarerenderer.cpp
qt_hardwarerenderer.hpp
qt_openglrenderer.cpp
qt_openglrenderer.hpp
qt_glsl_parser.cpp

View File

@@ -162,6 +162,7 @@ ioctl_is_empty(const void *local)
return 1;
}
#if 0
static int
ioctl_ext_medium_changed(UNUSED(void *local))
{
@@ -174,6 +175,7 @@ ioctl_ext_medium_changed(UNUSED(void *local))
return ret;
}
#endif
static void
ioctl_close(void *local)

View File

@@ -13,7 +13,7 @@ msgid "&Keyboard requires capture"
msgstr "&Klawaitura wymaga przechwytu myszy"
msgid "&Right CTRL is left ALT"
msgstr "&Prawy CTRL to lewy Alt"
msgstr "&Prawy CTRL to lewy ALT"
msgid "&Hard Reset..."
msgstr "&Twardy reset..."
@@ -49,7 +49,7 @@ msgid "Re&nderer"
msgstr "Re&nderer"
msgid "&Qt (Software)"
msgstr "&Qt (Software)"
msgstr "&Qt (programowy)"
msgid "Qt (&OpenGL)"
msgstr "Qt (&OpenGL)"
@@ -61,13 +61,13 @@ msgid "&VNC"
msgstr "&VNC"
msgid "Specify dimensions..."
msgstr "Określ rozmiary..."
msgstr "Określ wymiary..."
msgid "F&orce 4:3 display ratio"
msgstr "&Wymuś proporcje wyświetlania 4:3"
msgid "&Window scale factor"
msgstr "&Czynnik skalowania okna"
msgstr "Współ&czynnik skalowania okna"
msgid "&0.5x"
msgstr "&0.5x"
@@ -103,10 +103,10 @@ msgid "Filter method"
msgstr "Metoda filtrowania"
msgid "&Nearest"
msgstr "&Nearest"
msgstr "&Najbliższa"
msgid "&Linear"
msgstr "&Linear"
msgstr "&Liniowa"
msgid "Hi&DPI scaling"
msgstr "Skalowanie Hi&DPI"
@@ -145,7 +145,7 @@ msgid "RGB &Color"
msgstr "RGB - &Kolorowy"
msgid "&RGB Grayscale"
msgstr "&RGB - Skala szarości"
msgstr "&RGB - Skala odcieni szarości"
msgid "&Amber monitor"
msgstr "&Bursztynowy monitor"
@@ -157,7 +157,7 @@ msgid "&White monitor"
msgstr "&Biały monitor"
msgid "Grayscale &conversion type"
msgstr "Typ konwersji &w skali szarości"
msgstr "Typ konwersji &w skali odcieni szarości"
msgid "BT&601 (NTSC/PAL)"
msgstr "BT&601 (NTSC/PAL)"
@@ -166,13 +166,13 @@ msgid "BT&709 (HDTV)"
msgstr "BT&709 (HDTV)"
msgid "&Average"
msgstr "&Średni"
msgstr "&Średnia"
msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan"
msgstr "Overscan dla CGA/PCjr/Tandy/E&GA/(S)VGA"
msgid "Change contrast for &monochrome display"
msgstr "Zmień kontrast dla &monochromatycznego ekranu"
msgstr "Zmień kontrast dla ekranu &monochromatycznego"
msgid "&Media"
msgstr "&Nośnik"
@@ -196,7 +196,7 @@ msgid "&Preferences..."
msgstr "&Preferencje..."
msgid "Enable &Discord integration"
msgstr "Włącz integrację z &Discord"
msgstr "Włącz integrację z &Discordem"
msgid "Sound &gain..."
msgstr "Wzmocnienie &dźwięku..."
@@ -214,7 +214,7 @@ msgid "&Documentation..."
msgstr "&Dokumentacja..."
msgid "&About 86Box..."
msgstr "&O 86Box..."
msgstr "&O 86Boxie..."
msgid "&New image..."
msgstr "&Nowy obraz..."
@@ -247,7 +247,7 @@ msgid "E&xport to 86F..."
msgstr "E&ksportuj do 86F..."
msgid "&Mute"
msgstr "&Ścisz"
msgstr "&Wycisz"
msgid "E&mpty"
msgstr "P&usty"
@@ -256,13 +256,13 @@ msgid "Reload previous image"
msgstr "Przeładuj poprzedni obraz"
msgid "&Folder..."
msgstr "&Teczka..."
msgstr "&Folder..."
msgid "Target &framerate"
msgstr "Docelowa &liczba klatek na sekundę"
msgid "&Sync with video"
msgstr "&Zsynchronizuj z wideo"
msgstr "&Zsynchronizuj z obrazem"
msgid "&25 fps"
msgstr "&25 fps"
@@ -355,7 +355,7 @@ msgid "Speed:"
msgstr "Szybkość:"
msgid "Frequency:"
msgstr "Częstotliwość:"
msgstr "Taktowanie:"
msgid "FPU:"
msgstr "Jednostka FPU:"
@@ -391,7 +391,7 @@ msgid "Video #2:"
msgstr "Wideo 2:"
msgid "Voodoo 1 or 2 Graphics"
msgstr "Grafika Voodoo 1 czy 2"
msgstr "Grafika Voodoo 1 lub 2"
msgid "IBM 8514/A Graphics"
msgstr "Grafika IBM 8514/A"
@@ -505,10 +505,10 @@ msgid "FD Controller:"
msgstr "Kontroler dyskietek:"
msgid "Tertiary IDE Controller"
msgstr "Trzeciorzędowy kontroler IDE"
msgstr "Trzeciorzędny kontroler IDE"
msgid "Quaternary IDE Controller"
msgstr "Czwartorzędowy kontroler IDE"
msgstr "Czwartorzędny kontroler IDE"
msgid "SCSI"
msgstr "SCSI"
@@ -577,7 +577,7 @@ msgid "Floppy drives:"
msgstr "Napędy dyskietek:"
msgid "Turbo timings"
msgstr "Rozrządy Turbo"
msgstr "Timing Turbo"
msgid "Check BPB"
msgstr "Sprawdzaj BPB"
@@ -628,7 +628,7 @@ msgid "Fatal error"
msgstr "Fatalny błąd"
msgid " - PAUSED"
msgstr " - PAUSED"
msgstr " - PAUZA"
msgid "Speed"
msgstr "Szybkość"
@@ -664,19 +664,19 @@ msgid "Basic sector images"
msgstr "Podstawowe obrazy sektorów"
msgid "Surface images"
msgstr "Obrazy powierzchniowe"
msgstr "Obrazy powierzchni"
msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."
msgstr "Maszyna \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/machines. Przełączanie na dostępną maszynę."
msgstr "Maszyna \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/machines. Przełączanie na dostępną maszynę."
msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card."
msgstr "Karta wideo \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Przełączanie na dostępną kartę wideo."
msgstr "Karta wideo \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/video. Przełączanie na dostępną kartę graficzną."
msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card."
msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje obrazów ROM w katalogu roms/video. Wyłączenie drugiej karty graficznej."
msgstr "Karta wideo 2 \"%hs\" nie jest dostępna, ponieważ brakuje ROM-ów w katalogu roms/video. Wyłączenie drugiej karty graficznej."
msgid "Device \"%hs\" is not available due to missing ROMs. Ignoring the device."
msgstr "Urządzenie \"%hs\" nie jest dostępne, ponieważ brakuje obrazów ROM. Ignorowanie urządzenia."
msgstr "Urządzenie \"%hs\" nie jest dostępne, ponieważ brakuje ROM-ów. Ignorowanie urządzenia."
msgid "Machine"
msgstr "Maszyna"
@@ -697,7 +697,7 @@ msgid "Ports (COM & LPT)"
msgstr "Porty (COM & LPT)"
msgid "Storage controllers"
msgstr "Kontrolery pamięci"
msgstr "Kontrolery pamięci masowej"
msgid "Hard disks"
msgstr "Dyski twarde"
@@ -712,13 +712,13 @@ msgid "Other peripherals"
msgstr "Inne urządzenia peryferyjne"
msgid "Click to capture mouse"
msgstr "Kliknij w celu przechwycenia myszy"
msgstr "Kliknij, by przechwyc mysz"
msgid "Press %1 to release mouse"
msgstr "Naciśnij klawisze %1 w celu uwolnienia myszy"
msgstr "Naciśnij %1 w celu uwolnienia myszy"
msgid "Press %1 or middle button to release mouse"
msgstr "Naciśnij klawisze %1 lub środkowy przycisk w celu uwolnienia myszy"
msgstr "Naciśnij %1 lub środkowy przycisk w celu uwolnienia myszy"
msgid "Bus"
msgstr "Magistrala"
@@ -742,7 +742,7 @@ msgid "Default"
msgstr "Domyślny"
msgid "%1 Wait state(s)"
msgstr "%1 Stany oczekiwania"
msgstr "%1 stan(y/ów) oczekiwania"
msgid "Type"
msgstr "Rodzaj"
@@ -796,16 +796,16 @@ msgid "Advanced sector images"
msgstr "Zaawansowane obrazy sektorów"
msgid "Flux images"
msgstr "Flux images"
msgstr "Obrazy flux"
msgid "Are you sure you want to hard reset the emulated machine?"
msgstr "Jesteś pewien że chcesz wykonać twardy reset emulowanej maszyny?"
msgstr "Czy na pewno chcesz wykonać twardy reset emulowanej maszyny?"
msgid "Are you sure you want to exit 86Box?"
msgstr "Jesteś pewien że chcesz zakończyć 86Box?"
msgstr "Czy na pewno chcesz zakończyć 86Box?"
msgid "Unable to initialize Ghostscript"
msgstr "Nie można zainicjować Ghostscript"
msgstr "Nie można zainicjować Ghostscriptu"
msgid "Unable to initialize GhostPCL"
msgstr "Nie można zainicjować GhostPCL"
@@ -817,7 +817,7 @@ msgid "MO images"
msgstr "Obrazy MO"
msgid "Welcome to 86Box!"
msgstr "Witamy w 86Box!"
msgstr "Witamy w 86Boxie!"
msgid "Internal device"
msgstr "Urządzenie wewnętrzne"
@@ -826,7 +826,7 @@ msgid "Exit"
msgstr "Zakończ"
msgid "No ROMs found"
msgstr "Nie znaleziono obrazów ROM"
msgstr "Nie znaleziono ROM-ów"
msgid "Do you want to save the settings?"
msgstr "Czy chcesz zapisać ustawienia?"
@@ -844,7 +844,7 @@ msgid "86Box v"
msgstr "86Box v"
msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information."
msgstr "Emulator starych komputerów\n\nAutorzy: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i inni.\n\nZ wcześniejszym wkładem od Sarah Walker, leilei, JohnElliott, greatpsycho i innych.\n\nPrzetłumaczony przez: Fanta-Shokata\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać więcej informacji."
msgstr "Emulator starych komputerów\n\nAutorzy: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, i inni.\n\nZ wcześniejszym wkładem od Sarah Walker, leilei, JohnElliott, greatpsycho i innych.\n\nPrzetłumaczony przez: Fanta-Shokata, Lili1228\n\nWydany na licencji GNU General Public License w wersji 2 lub nowszej. Zobacz LICENSE aby uzyskać więcej informacji."
msgid "Hardware not available"
msgstr "Sprzęt niedostępny"
@@ -886,10 +886,10 @@ msgid "GLSL shaders"
msgstr "Shadery GLSL"
msgid "You are loading an unsupported configuration"
msgstr "Ładujesz nieobsługiwaną konfigurację"
msgstr "Wczytujesz nieobsługiwaną konfigurację"
msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."
msgstr "Wybór rodzaju procesora oparty na wybranej maszynie jest wyłączony dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora który jest niekompatybilny z wybraną maszyną. Jednak możesz napotkać niezgodności z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgłoszenie błędu może zostać zamknięte jako nieważne."
msgstr "Filtrowanie rodzaju procesora na podstawie wybranej maszyny jest wyłączone dla tej emulowanej maszyny.\n\nPozwala to na wybór procesora, który jest niekompatybilny z wybraną maszyną, jednak możesz napotkać niezgodności z BIOS-em maszyny lub innym oprogramowaniem.\n\nAktywacja tego ustawienia nie jest wspierana i każde zgłoszenie błędu może zostać zamknięte jako nieprawidłowe."
msgid "Continue"
msgstr "Kontynuuj"
@@ -901,10 +901,10 @@ msgid "Cassette images"
msgstr "Obrazy kaset"
msgid "Cartridge %1: %2"
msgstr "Kartrydż %1: %2"
msgstr "Kartridż %1: %2"
msgid "Cartridge images"
msgstr "Obrazy kartryu"
msgstr "Obrazy kartriów"
msgid "Resume execution"
msgstr "Wznów wykonywanie"
@@ -994,7 +994,7 @@ msgid "Don't overwrite"
msgstr "Nie nadpisuj"
msgid "Raw image"
msgstr "Obraz surowy"
msgstr "Surowy obraz"
msgid "HDI image"
msgstr "Obraz HDI"
@@ -1012,10 +1012,10 @@ msgid "Differencing VHD"
msgstr "VHD różnicujący"
msgid "(N/A)"
msgstr "(Bez)"
msgstr "(nd.)"
msgid "Raw image (.img)"
msgstr "Obraz surowy (.img)"
msgstr "Surowy obraz (.img)"
msgid "HDI image (.hdi)"
msgstr "Obraz HDI (.hdi)"
@@ -1030,7 +1030,7 @@ msgid "Dynamic-size VHD (.vhd)"
msgstr "VHD o dynamicznym rozmiarze (.vhd)"
msgid "Differencing VHD (.vhd)"
msgstr "VHD różnicujący (.vhd)"
msgstr "VHD różnicowy (.vhd)"
msgid "Large blocks (2 MB)"
msgstr "Duże bloki (2 MB)"
@@ -1045,7 +1045,7 @@ msgid "Select the parent VHD"
msgstr "Wybierz nadrzędny plik VHD"
msgid "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?"
msgstr "Może to oznaczać, że obraz nadrzędny został zmodyfikowany po utworzeniu obrazu różnicującego.\n\nMoże się to również zdarzyć, jeśli pliki obrazów zostały przeniesione lub skopiowane, lub wystąpił błąd w programie, który utworzył ten dysk\n\nCzy chcesz naprawić sygnatury czasowe?"
msgstr "Może to oznaczać, że obraz nadrzędny został zmodyfikowany po utworzeniu obrazu różnicowego.\n\nMoże się to również zdarzyć, jeśli pliki obrazów zostały przeniesione lub skopiowane, lub wystąpił błąd w programie, który utworzył ten dysk.\n\nCzy chcesz naprawić sygnatury czasowe?"
msgid "Parent and child disk timestamps do not match"
msgstr "Sygnatury czasowe dysku nadrzędnego i podrzędnego nie zgadzają się"
@@ -1162,10 +1162,10 @@ msgid "The network configuration will be switched to the null driver"
msgstr "Konfiguracja sieci zostanie przełączona na sterownik null"
msgid "Mouse sensitivity:"
msgstr "Wrażliwość myszy:"
msgstr "Czułość myszy:"
msgid "Select media images from program working directory"
msgstr "Wybór obrazów multimedialnych z katalogu roboczego programu"
msgstr "Wybór obrazów nośników z katalogu roboczego programu"
msgid "PIT mode:"
msgstr "Tryb PIT:"
@@ -1186,7 +1186,7 @@ msgid "WinBox is no longer supported"
msgstr "WinBox nie jest już wspierany"
msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use."
msgstr "Rozwój menedżera WinBox został zatrzymany w 2022 roku z powodu braku opiekunów. Ponieważ kierujemy nasze wysiłki na uczynienie 86Box jeszcze lepszym, podjęliśmy decyzję o zaprzestaniu wspierania WinBox jako menedżera.\n\nŻadne dalsze aktualizacje nie będą dostarczane za pośrednictwem WinBox i możesz napotkać nieprawidłowe zachowanie, jeśli będziesz go nadal używać z nowszymi wersjami 86Box. Wszelkie zgłoszenia błędów związane z działaniem WinBox zostaną zamknięte jako nieważne.\n\nLista innych menedżerów, z których można korzystać, znajduje się na stronie 86box.net."
msgstr "Menedżer WinBox przestał być rozwijany w 2022 roku z powodu braku opiekunów. Ponieważ kierujemy nasze wysiłki na uczynienie 86Box jeszcze lepszym, podjęliśmy decyzję o zaprzestaniu wspierania WinBox jako menedżera.\n\nŻadne dalsze aktualizacje nie będą dostarczane za pośrednictwem WinBoxa i możesz napotkać nieprawidłowe zachowanie, jeśli będziesz go nadal używać z nowszymi wersjami 86Box. Wszelkie zgłoszenia błędów związane z działaniem WinBox zostaną zamknięte jako nieważne.\n\nLista innych menedżerów, z których można korzystać, znajduje się na stronie 86box.net."
msgid "Generate"
msgstr "Generuj"
@@ -1273,7 +1273,7 @@ msgid "VSync"
msgstr "VSync"
msgid "Synchronize with video"
msgstr "Zsynchronizuj z wideo"
msgstr "Synchronizuj z obrazem"
msgid "Shaders"
msgstr "Shadery"
@@ -1297,10 +1297,10 @@ msgid "Error initializing OpenGL"
msgstr "Błąd inicjalizacji OpenGL"
msgid "\nFalling back to software rendering."
msgstr "\nPowrót do renderowania oprogramowania."
msgstr "\nPowrót do renderowania programowego."
msgid "<html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html>"
msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itp.) otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>"
msgstr "<html><head/><body><p>Podczas wybierania obrazów nośników (CD-ROM, dyskietka itd.), otwarte okno dialogowe rozpocznie się w tym samym katalogu, co plik konfiguracyjny 86Box. To ustawienie prawdopodobnie będzie miało znaczenie tylko na macOS.</p></body></html>"
msgid "This machine might have been moved or copied."
msgstr "To urządzenie mogło zostać przeniesione lub skopiowane."
@@ -1354,25 +1354,25 @@ msgid "Novell NetWare 2.x Key Card"
msgstr "Karta klucza Novell NetWare 2.x"
msgid "Serial port passthrough 1"
msgstr "Przełączanie portu szeregowego 1"
msgstr "Przelotka portu szeregowego 1"
msgid "Serial port passthrough 2"
msgstr "Przełączanie portu szeregowego 2"
msgstr "Przelotka portu szeregowego 2"
msgid "Serial port passthrough 3"
msgstr "Przełączanie portu szeregowego 3"
msgstr "Przelotka portu szeregowego 3"
msgid "Serial port passthrough 4"
msgstr "Przełączanie portu szeregowego 4"
msgstr "Przelotka portu szeregowego 4"
msgid "Renderer options..."
msgstr "Opcje renderowania..."
msgid "Logitech/Microsoft Bus Mouse"
msgstr "Mysz magistralna Logitech/Microsoft"
msgstr "Mysz magistralowa Logitech/Microsoft"
msgid "Microsoft Bus Mouse (InPort)"
msgstr "Mysz magistralna Microsoft (InPort)"
msgstr "Mysz magistralowa Microsoft (InPort)"
msgid "Mouse Systems Serial Mouse"
msgstr "Mysz szeregowa Mouse Systems"
@@ -1387,7 +1387,7 @@ msgid "PS/2 Mouse"
msgstr "Mysz PS/2"
msgid "3M MicroTouch (Serial)"
msgstr "3M MicroTouch (szeregowa)"
msgstr "3M MicroTouch (szeregowy)"
msgid "[COM] Standard Hayes-compliant Modem"
msgstr "[COM] Standardowy modem zgodny z Hayes"
@@ -1396,7 +1396,7 @@ msgid "Roland MT-32 Emulation"
msgstr "Emulacja Roland MT-32"
msgid "Roland MT-32 (New) Emulation"
msgstr "Emulacja Roland MT-32 (nowego)"
msgstr "(Nowa) emulacja Roland MT-32"
msgid "Roland CM-32L Emulation"
msgstr "Emulacja Roland CM-32L"
@@ -1405,7 +1405,7 @@ msgid "Roland CM-32LN Emulation"
msgstr "Emulacja Roland CM-32LN"
msgid "OPL4-ML Daughterboard"
msgstr "Płyta córka OPL4-ML"
msgstr "Płyta-córka OPL4-ML"
msgid "System MIDI"
msgstr "System MIDI"
@@ -1612,7 +1612,7 @@ msgid "CODEC"
msgstr "CODEC"
msgid "Raise CODEC interrupt on CODEC setup (needed by some drivers)"
msgstr "Podniesienie przerwania CODEC przy konfiguracji CODEC (wymagane przez niektóre sterowniki)"
msgstr "Podnieś przerwanie CODEC podczas konfiguracji CODEC-a (wymagane przez niektóre sterowniki)"
msgid "SB Address"
msgstr "Adres SB"
@@ -1630,7 +1630,7 @@ msgid "Receive MIDI input (MPU-401)"
msgstr "Odbiór wejścia MIDI (MPU-401)"
msgid "SB low DMA"
msgstr "SB low DMA"
msgstr "Low DMA SB"
msgid "6CH variant (6-channel)"
msgstr "Wariant 6CH (6-kanałowy)"
@@ -1645,7 +1645,7 @@ msgid "High DMA"
msgstr "Wysokie DMA"
msgid "Control PC speaker"
msgstr "Głośnik komputera sterującego"
msgstr "Kontroluj PC speaker"
msgid "Memory size"
msgstr "Rozmiar pamięci"
@@ -1663,10 +1663,10 @@ msgid "GUS type"
msgstr "Typ GUS"
msgid "Enable 0x04 \"Exit 86Box\" command"
msgstr "Włącz polecenie 0x04 \"Wyjdź z 86Box\""
msgstr "Włącz polecenie 0x04 \"Wyjdź z 86Boxa\""
msgid "Display type"
msgstr "Typ wyświetlacza"
msgstr "Typ ekranu"
msgid "Composite type"
msgstr "Typ kompozytowy"
@@ -1777,7 +1777,7 @@ msgid "Triangle"
msgstr "Trójkątny"
msgid "Linear"
msgstr "Liniowa"
msgstr "Liniowy"
msgid "4th Order"
msgstr "4. rzędu"
@@ -1798,13 +1798,13 @@ msgid "Three"
msgstr "Trzy"
msgid "Wheel"
msgstr "Koło"
msgstr "Rolka"
msgid "Five + Wheel"
msgstr ""
msgstr "Pięć + rolka"
msgid "Five + 2 Wheels"
msgstr ""
msgstr "Pięć + dwie rolki"
msgid "A3 - SMT2 Serial / SMT3(R)V"
msgstr "A3 - SMT2 szeregowa / SMT3(R)V"
@@ -1876,7 +1876,7 @@ msgid "New"
msgstr "Nowość"
msgid "Color (generic)"
msgstr "Kolor (generyczny)"
msgstr "Kolorowy (generyczny)"
msgid "Green Monochrome"
msgstr "Zielony monochromatyczny"
@@ -1888,10 +1888,10 @@ msgid "Gray Monochrome"
msgstr "Szary monochromatyczny"
msgid "Color (no brown)"
msgstr "Kolor (bez brązowego)"
msgstr "Kolorowy (bez brązowego)"
msgid "Color (IBM 5153)"
msgstr "Kolor (IBM 5153)"
msgstr "Kolorowy (IBM 5153)"
msgid "Simple doubling"
msgstr "Proste podwojenie"
@@ -1921,7 +1921,7 @@ msgid "Color 80x25 (5153/CGA)"
msgstr "Kolor 80x25 (5153/CGA)"
msgid "Enhanced Color - Normal Mode (5154/ECD)"
msgstr "Rozszerzone kolory - tryb normalny (5154/ECD)"
msgstr "Rozszerzony kolor - tryb zwykły (5154/ECD)"
msgid "Enhanced Color - Enhanced Mode (5154/ECD)"
msgstr "Rozszerzony kolor - tryb rozszerzony (5154/ECD)"
@@ -1936,10 +1936,10 @@ msgid "Gray"
msgstr "Szary"
msgid "Color"
msgstr "Kolor"
msgstr "Kolorowy"
msgid "U.S. English"
msgstr "Amerykański angielski"
msgstr "Angielski (USA)"
msgid "Scandinavian"
msgstr "Skandynawski"
@@ -1948,13 +1948,13 @@ msgid "Other languages"
msgstr "Inne języki"
msgid "Bochs latest"
msgstr "Bochs najnowsze"
msgstr "Najnowszy Bochs"
msgid "Mono Non-Interlaced"
msgstr "Mono bez przeplotu"
msgstr "Monochromatyczny bez przeplotu"
msgid "Color Interlaced"
msgstr "Kolor z przeplotem"
msgstr "Kolorowy z przeplotem"
msgid "Color Non-Interlaced"
msgstr "Kolor bez przeplotu"
@@ -1963,7 +1963,7 @@ msgid "3Dfx Voodoo Graphics"
msgstr "Grafika 3Dfx Voodoo"
msgid "Obsidian SB50 + Amethyst (2 TMUs)"
msgstr "Obsydian SB50 + Ametyst (2 jednostki TMU)"
msgstr "Obsydian SB50 + Amethyst (2 jednostki TMU)"
msgid "8-bit"
msgstr "8-bitowy"
@@ -1987,7 +1987,7 @@ msgid "High-Speed"
msgstr "Wysoka prędkość"
msgid "Stereo LPT DAC"
msgstr "Stereofoniczny przetwornik cyfrowo-analogowy LPT"
msgstr "Stereo LPT DAC"
msgid "Generic Text Printer"
msgstr "Generyczna drukarka tekstowa"
@@ -2002,7 +2002,7 @@ msgid "Generic PCL5e Printer"
msgstr "Generyczna drukarka PCL5e"
msgid "Parallel Line Internet Protocol"
msgstr "Protokół internetowy linii równoległej"
msgstr "Parallel Line Internet Protocol"
msgid "Protection Dongle for Savage Quest"
msgstr "Klucz ochronny dla Savage Quest"
@@ -2017,7 +2017,7 @@ msgid "Host Serial Device"
msgstr "Urządzenie szeregowe hosta"
msgid "Name of pipe"
msgstr "Nazwa rury"
msgstr "Nazwa potoku"
msgid "Data bits"
msgstr "Bity danych"
@@ -2026,19 +2026,19 @@ msgid "Stop bits"
msgstr "Bity stopu"
msgid "Baud Rate of Passthrough"
msgstr "Szybkość transmisji Passthrough"
msgstr "Szybkość transmisji przelotowej"
msgid "Named Pipe (Server)"
msgstr "Nazwana rura (serwer)"
msgstr "Nazwany potok (serwer)"
msgid "Host Serial Passthrough"
msgstr "Przejście przez port szeregowy hosta"
msgstr "Przelot przez port szeregowy hosta"
msgid "E&ject %1"
msgstr "W&yjmij %1"
msgid "&Unmute"
msgstr "&Wycisz"
msgstr "O&dcisz"
msgid "Softfloat FPU"
msgstr "FPU Softfloat"
@@ -2047,28 +2047,28 @@ msgid "High performance impact"
msgstr "Wysoki wpływ na wydajność"
msgid "[Generic] RAM Disk (max. speed)"
msgstr "[Generic] Dysk RAM (maks. prędkość)"
msgstr "[generyczny] Dysk RAM (maks. prędkość)"
msgid "[Generic] 1989 (3500 RPM)"
msgstr ""
msgstr "[generyczny] 1989 (3500 RPM)"
msgid "[Generic] 1992 (3600 RPM)"
msgstr ""
msgstr "[generyczny] 1992 (3600 RPM)"
msgid "[Generic] 1994 (4500 RPM)"
msgstr ""
msgstr "[generyczny] 1994 (4500 RPM)"
msgid "[Generic] 1996 (5400 RPM)"
msgstr ""
msgstr "[generyczny] 1996 (5400 RPM)"
msgid "[Generic] 1997 (5400 RPM)"
msgstr ""
msgstr "[generyczny] 1997 (5400 RPM)"
msgid "[Generic] 1998 (5400 RPM)"
msgstr ""
msgstr "[generyczny] 1998 (5400 RPM)"
msgid "[Generic] 2000 (7200 RPM)"
msgstr ""
msgstr "[generyczny] 2000 (7200 RPM)"
msgid "IBM 8514/A clone (ISA)"
msgstr "Klon IBM 8514/A (ISA)"
@@ -2083,67 +2083,67 @@ msgid "Generic PC/AT Memory Expansion"
msgstr "Generyczne rozszerzenie pamięci PC/AT"
msgid "Unable to find Dot-Matrix fonts"
msgstr "Nie można znaleźć czcionek igłowych"
msgstr "Nie można znaleźć fontów igłowych"
msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer."
msgstr "Czcionki TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generyczniej drukarki igłowej ESC/P."
msgstr "Fonty TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generycznej drukarki igłowej ESC/P."
msgid "Inhibit multimedia keys"
msgstr ""
msgstr "Przejmij klawisze multimedialne"
msgid "Ask for confirmation before saving settings"
msgstr ""
msgstr "Pytaj o potwierdzenie przed zapisaniem ustawień"
msgid "Ask for confirmation before hard resetting"
msgstr ""
msgstr "Pytaj o potwierdzenie przed twardym resetem"
msgid "Ask for confirmation before quitting"
msgstr ""
msgstr "Pytaj o potwierdzenie przed wyjściem"
msgid "Options"
msgstr ""
msgstr "Opcje"
msgid "Model"
msgstr ""
msgstr "Model"
msgid "Model:"
msgstr ""
msgstr "Model:"
msgid "Failed to initialize Vulkan renderer."
msgstr ""
msgstr "Nie udało się zainicjować renderera Vulkan."
msgid "GLSL Error"
msgstr ""
msgstr "Błąd GLSL"
msgid "Could not load shader: %1"
msgstr ""
msgstr "Nie udało się wczytać shadera: %1"
msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2"
msgstr ""
msgstr "Wymagana jest wersja OpenGL 3.0 lub wyższa. Aktualna wersja GLSL to %1.%2"
msgid "Could not load texture: %1"
msgstr ""
msgstr "Nie udało się wczytać tekstury: %1"
msgid "Could not compile shader:\n\n%1"
msgstr ""
msgstr "Nie udało się skompilować shadera:\n\n%1"
msgid "Program not linked:\n\n%1"
msgstr ""
msgstr "Program niezalinkowany:\n\n%1"
msgid "Shader Manager"
msgstr ""
msgstr "Menedżer shaderów"
msgid "Shader Configuration"
msgstr ""
msgstr "Konfiguracja shadera"
msgid "Add"
msgstr ""
msgstr "Dodaj"
msgid "Move up"
msgstr ""
msgstr "Przesuń w górę"
msgid "Move down"
msgstr ""
msgstr "Przesuń w dół"
msgid "Could not load file %1"
msgstr ""
msgstr "Nie można wczytać pliku %1"

View File

@@ -147,6 +147,12 @@ msgstr "RGB &цветной"
msgid "&RGB Grayscale"
msgstr "&RGB монохромный"
msgid "RGB (no brown)"
msgstr "RGB (без коричневого)"
msgid "Generic RGBI color monitor"
msgstr "Стандартный цветной монитор RGBI"
msgid "&Amber monitor"
msgstr "&Янтарный оттенок"
@@ -1789,7 +1795,7 @@ msgid "Dithering"
msgstr "Дизеринг"
msgid "Enable NMI for CGA emulation"
msgstr "Включение NMI для эмуляции CGA"
msgstr "Включить NMI для эмуляции CGA"
msgid "Voodoo type"
msgstr "Тип Voodoo"

View File

@@ -28,6 +28,7 @@
#include <86box/plat.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/renderdefs.h>
int
qt_nvr_save(void)
@@ -38,21 +39,16 @@ qt_nvr_save(void)
int
plat_vidapi(const char *api)
{
if (!strcasecmp(api, "default") || !strcasecmp(api, "system")) {
return 0;
} else if (!strcasecmp(api, "qt_software")) {
return 0;
} else if (!strcasecmp(api, "qt_opengl")) {
return 1;
} else if (!strcasecmp(api, "qt_opengles")) {
return 2;
} else if (!strcasecmp(api, "qt_opengl3")) {
return 3;
} else if (!strcasecmp(api, "qt_vulkan")) {
return 4;
} else if (!strcasecmp(api, "vnc")) {
return 5;
}
if (!strcasecmp(api, RENDERER_NAME_DEFAULT) || !strcasecmp(api, RENDERER_NAME_SYSTEM))
return RENDERER_SOFTWARE;
else if (!strcasecmp(api, RENDERER_NAME_QT_SOFTWARE))
return RENDERER_SOFTWARE;
else if (!strcasecmp(api, RENDERER_NAME_QT_OPENGL) || !strcasecmp(api, RENDERER_NAME_QT_OPENGLES) || !strcasecmp(api, RENDERER_NAME_QT_OPENGL3))
return RENDERER_OPENGL3;
else if (!strcasecmp(api, RENDERER_NAME_QT_VULKAN))
return RENDERER_VULKAN;
else if (!strcasecmp(api, RENDERER_NAME_VNC))
return RENDERER_VNC;
return 0;
}
@@ -60,26 +56,20 @@ plat_vidapi(const char *api)
char *
plat_vidapi_name(int api)
{
char *name = "default";
char *name = RENDERER_NAME_DEFAULT;
switch (api) {
case 0:
name = "qt_software";
case RENDERER_SOFTWARE:
name = RENDERER_NAME_QT_SOFTWARE;
break;
case 1:
name = "qt_opengl";
case RENDERER_OPENGL3:
name = RENDERER_NAME_QT_OPENGL3;
break;
case 2:
name = "qt_opengles";
case RENDERER_VULKAN:
name = RENDERER_NAME_QT_VULKAN;
break;
case 3:
name = "qt_opengl3";
break;
case 4:
name = "qt_vulkan";
break;
case 5:
name = "vnc";
case RENDERER_VNC:
name = RENDERER_NAME_VNC;
break;
default:
fatal("Unknown renderer: %i\n", api);
@@ -87,4 +77,4 @@ plat_vidapi_name(int api)
}
return name;
}
}

View File

@@ -24,7 +24,7 @@
#include <QFile>
class Downloader : public QObject {
class Downloader final : public QObject {
Q_OBJECT
public:
enum class DownloadLocation {

View File

@@ -69,13 +69,12 @@ static inline int wx_config_has_entry(void *config, const char *name) { return i
static inline void wx_config_free(void *config) { ini_close(config); };
static int endswith(const char *str, const char *ext) {
int i;
const char *p;
int elen = strlen(ext);
int slen = strlen(str);
if (slen >= elen) {
p = &str[slen - elen];
for (i = 0; i < elen; ++i) {
for (int i = 0; i < elen; ++i) {
if (tolower(p[i]) != tolower(ext[i]))
return 0;
}
@@ -118,12 +117,18 @@ static char *load_file(const char *fn) {
char *data = (char*)malloc(fsize + 1);
(void) fread(data, fsize, 1, fp);
fclose(fp);
size_t read_bytes = fread(data, fsize, 1, fp);
if (read_bytes != 1) {
fclose(fp);
free(data);
return nullptr;
} else {
fclose(fp);
data[fsize] = 0;
data[fsize] = 0;
return data;
return data;
}
}
static void strip_lines(const char *program, const char *starts_with) {
@@ -147,17 +152,15 @@ static void strip_defines(const char *program) {
}
static int has_parameter(glslp_t *glsl, char *id) {
int i;
for (i = 0; i < glsl->num_parameters; ++i)
for (int i = 0; i < glsl->num_parameters; ++i)
if (!strcmp(glsl->parameters[i].id, id))
return 1;
return 0;
}
static int get_parameters(glslp_t *glsl) {
int i;
struct parameter p;
for (i = 0; i < glsl->num_shaders; ++i) {
for (int i = 0; i < glsl->num_shaders; ++i) {
size_t size = 0;
char* line = NULL;
struct shader *shader = &glsl->shaders[i];
@@ -197,8 +200,7 @@ static int get_parameters(glslp_t *glsl) {
}
static struct parameter *get_parameter(glslp_t *glslp, const char *id) {
int i;
for (i = 0; i < glslp->num_parameters; ++i) {
for (int i = 0; i < glslp->num_parameters; ++i) {
if (!strcmp(glslp->parameters[i].id, id)) {
return &glslp->parameters[i];
}
@@ -207,8 +209,7 @@ static struct parameter *get_parameter(glslp_t *glslp, const char *id) {
}
static glslp_t *glsl_parse(const char *f) {
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
memset(glslp, 0, sizeof(glslp_t));
glslp_t *glslp = (glslp_t*) calloc(1, sizeof(glslp_t));
glslp->num_shaders = 1;
struct shader *shader = &glslp->shaders[0];
strcpy(shader->shader_fn, f);
@@ -233,7 +234,9 @@ extern "C" {
void get_glslp_name(const char *f, char *s, int size) { safe_strncpy(s, path_get_filename((char *)f), size); }
glslp_t *glslp_parse(const char *f) {
int i, j, len, sublen;
int j;
int len;
int sublen;
char s[513], t[513], z[540];
memset(s, 0, sizeof(s));
@@ -247,8 +250,7 @@ glslp_t *glslp_parse(const char *f) {
return 0;
}
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
memset(glslp, 0, sizeof(glslp_t));
glslp_t *glslp = (glslp_t*) calloc(1, sizeof(glslp_t));
get_glslp_name(f, glslp->name, sizeof(glslp->name));
@@ -256,7 +258,7 @@ glslp_t *glslp_parse(const char *f) {
wx_config_get_bool(cfg, "filter_linear0", &glslp->input_filter_linear, -1);
for (i = 0; i < glslp->num_shaders; ++i) {
for (int i = 0; i < glslp->num_shaders; ++i) {
struct shader *shader = &glslp->shaders[i];
snprintf(s, sizeof(s) - 1, "shader%d", i);
@@ -267,12 +269,31 @@ glslp_t *glslp_parse(const char *f) {
}
strcpy(s, f);
*path_get_filename(s) = 0;
snprintf(shader->shader_fn, sizeof(shader->shader_fn) - 1, "%s%s", s, t);
size_t max_len = sizeof(shader->shader_fn);
size_t s_len = strlen(s);
if (s_len >= max_len) {
// s alone fills or overflows the buffer, truncate and null-terminate
size_t copy_len = max_len - 1 < s_len ? max_len - 1 : s_len;
memcpy(shader->shader_fn, s, copy_len);
shader->shader_fn[copy_len] = '\0';
} else {
// Copy s fully
memcpy(shader->shader_fn, s, s_len);
// Copy as much of t as fits after s
size_t avail = max_len - 1 - s_len; // space left for t + null terminator
// Copy as much of t as fits into the remaining space
memcpy(shader->shader_fn + s_len, t, avail);
// Null-terminate
shader->shader_fn[s_len + avail] = '\0';
}
shader->shader_program = load_file(shader->shader_fn);
if (!shader->shader_program) {
fprintf(stderr, "GLSLP Error: Could not load shader %s\n", shader->shader_fn);
glslp_free(glslp);
return 0;
fprintf(stderr, "GLSLP Error: Could not load shader %s\n", shader->shader_fn);
glslp_free(glslp);
return 0;
}
strip_parameters(shader->shader_program);
strip_defines(shader->shader_program);
@@ -327,7 +348,7 @@ glslp_t *glslp_parse(const char *f) {
len = strlen(t);
j = 0;
sublen = 0;
for (i = 0; i < len; ++i) {
for (int i = 0; i < len; ++i) {
if (t[i] == ';' || i == len - 1) {
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
safe_strncpy(s, t + j, sublen);
@@ -361,7 +382,7 @@ glslp_t *glslp_parse(const char *f) {
len = strlen(t);
j = 0;
sublen = 0;
for (i = 0; i < len; ++i) {
for (int i = 0; i < len; ++i) {
if (t[i] == ';' || i == len - 1) {
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
safe_strncpy(s, t + j, sublen);
@@ -382,8 +403,7 @@ glslp_t *glslp_parse(const char *f) {
}
void glslp_free(glslp_t *p) {
int i;
for (i = 0; i < p->num_shaders; ++i)
for (int i = 0; i < p->num_shaders; ++i)
if (p->shaders[i].shader_program)
free(p->shaders[i].shader_program);
free(p);
@@ -391,10 +411,9 @@ void glslp_free(glslp_t *p) {
void glslp_read_shader_config(glslp_t *shader) {
char s[512];
int i;
char *name = shader->name;
sprintf(s, "GL3 Shaders - %s", name);
for (i = 0; i < shader->num_parameters; ++i) {
snprintf(s, sizeof(s) -1, "GL3 Shaders - %s", name);
for (int i = 0; i < shader->num_parameters; ++i) {
struct parameter *param = &shader->parameters[i];
param->value = config_get_double(s, param->id, param->default_value);
}
@@ -402,12 +421,11 @@ void glslp_read_shader_config(glslp_t *shader) {
void glslp_write_shader_config(glslp_t *shader) {
char s[512];
int i;
char *name = shader->name;
startblit();
sprintf(s, "GL3 Shaders - %s", name);
for (i = 0; i < shader->num_parameters; ++i) {
snprintf(s, sizeof(s) - 1, "GL3 Shaders - %s", name);
for (int i = 0; i < shader->num_parameters; ++i) {
struct parameter *param = &shader->parameters[i];
config_set_double(s, param->id, param->value);
}

View File

@@ -1,257 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Hardware renderer module.
*
*
*
* Authors: Joakim L. Gilje <jgilje@jgilje.net>
* Cacodemon345
* Teemu Korhonen
*
* Copyright 2021 Joakim L. Gilje
* Copyright 2021-2022 Cacodemon345
* Copyright 2021-2022 Teemu Korhonen
*/
#include "qt_hardwarerenderer.hpp"
#include <QApplication>
#include <QVector2D>
#include <QOpenGLPixelTransferOptions>
#include <atomic>
#include <cstdint>
#include <vector>
extern "C" {
#include <86box/86box.h>
#include <86box/plat.h>
#include <86box/video.h>
}
void
HardwareRenderer::resizeGL(int w, int h)
{
m_context->makeCurrent(this);
glViewport(0, 0, qRound(w * devicePixelRatioF()), qRound(h * devicePixelRatioF()));
}
#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1
void
HardwareRenderer::initializeGL()
{
m_context->makeCurrent(this);
initializeOpenGLFunctions();
auto image = QImage(2048, 2048, QImage::Format_RGB32);
image.fill(0xff000000);
m_texture = new QOpenGLTexture(image);
m_blt = new QOpenGLTextureBlitter;
m_blt->setRedBlueSwizzle(true);
m_blt->create();
QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
const char *vsrc = "attribute highp vec4 VertexCoord;\n"
"attribute mediump vec4 TexCoord;\n"
"varying mediump vec4 texc;\n"
"uniform mediump mat4 MVPMatrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = MVPMatrix * VertexCoord;\n"
" texc = TexCoord;\n"
"}\n";
QString vsrccore = "in highp vec4 VertexCoord;\n"
"in mediump vec4 TexCoord;\n"
"out mediump vec4 texc;\n"
"uniform mediump mat4 MVPMatrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = MVPMatrix * VertexCoord;\n"
" texc = TexCoord;\n"
"}\n";
if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) {
vsrccore.prepend("#version 300 es\n");
vshader->compileSourceCode(vsrccore);
} else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) {
vsrccore.prepend("#version 130\n");
vshader->compileSourceCode(vsrccore);
} else
vshader->compileSourceCode(vsrc);
QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
const char *fsrc = "uniform sampler2D texture;\n"
"varying mediump vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st).bgra;\n"
"}\n";
QString fsrccore = "uniform sampler2D texture;\n"
"in mediump vec4 texc;\n"
"out highp vec4 FragColor;\n"
"void main(void)\n"
"{\n"
" FragColor = texture2D(texture, texc.st).bgra;\n"
"}\n";
if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) {
fsrccore.prepend("#version 300 es\n");
fshader->compileSourceCode(fsrccore);
} else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) {
fsrccore.prepend("#version 130\n");
fshader->compileSourceCode(fsrccore);
} else
fshader->compileSourceCode(fsrc);
m_prog = new QOpenGLShaderProgram;
m_prog->addShader(vshader);
m_prog->addShader(fshader);
m_prog->bindAttributeLocation("VertexCoord", PROGRAM_VERTEX_ATTRIBUTE);
m_prog->bindAttributeLocation("TexCoord", PROGRAM_TEXCOORD_ATTRIBUTE);
m_prog->link();
m_prog->bind();
m_prog->setUniformValue("texture", 0);
if (m_context->format().version() >= qMakePair(3, 0) && m_vao.create()) {
m_vao.bind();
}
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].create();
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind();
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].allocate(sizeof(QVector2D) * 4);
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].create();
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind();
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].allocate(sizeof(QVector2D) * 4);
pclog("OpenGL vendor: %s\n", glGetString(GL_VENDOR));
pclog("OpenGL renderer: %s\n", glGetString(GL_RENDERER));
pclog("OpenGL version: %s\n", glGetString(GL_VERSION));
pclog("OpenGL shader language version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
glClearColor(0, 0, 0, 1);
m_texture->setWrapMode(QOpenGLTexture::ClampToEdge);
glClear(GL_COLOR_BUFFER_BIT);
m_context->swapBuffers(this);
}
void
HardwareRenderer::paintGL()
{
m_context->makeCurrent(this);
glClear(GL_COLOR_BUFFER_BIT);
QVector<QVector2D> verts;
QVector<QVector2D> texcoords;
QMatrix4x4 mat;
mat.setToIdentity();
mat.ortho(QRectF(0, 0, (qreal) width() * (qreal) devicePixelRatioF(), (qreal) height() * (qreal) devicePixelRatioF()));
verts.push_back(QVector2D((float) destination.x(), (float) destination.y()));
verts.push_back(QVector2D((float) destination.x(), (float) destination.y() + (float) destination.height()));
verts.push_back(QVector2D((float) destination.x() + (float) destination.width(), (float) destination.y() + (float) destination.height()));
verts.push_back(QVector2D((float) destination.x() + (float) destination.width(), (float) destination.y()));
texcoords.push_back(QVector2D((float) source.x() / 2048.f, (float) (source.y()) / 2048.f));
texcoords.push_back(QVector2D((float) source.x() / 2048.f, (float) (source.y() + source.height()) / 2048.f));
texcoords.push_back(QVector2D((float) (source.x() + source.width()) / 2048.f, (float) (source.y() + source.height()) / 2048.f));
texcoords.push_back(QVector2D((float) (source.x() + source.width()) / 2048.f, (float) (source.y()) / 2048.f));
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind();
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].write(0, verts.data(), sizeof(QVector2D) * 4);
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release();
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind();
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].write(0, texcoords.data(), sizeof(QVector2D) * 4);
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release();
m_prog->setUniformValue("MVPMatrix", mat);
m_prog->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
m_prog->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind();
m_prog->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2, 0);
m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release();
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind();
m_prog->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 0, 2, 0);
m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release();
m_texture->bind();
m_texture->setMinMagFilters(video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest, video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void
HardwareRenderer::setRenderType(RenderType type)
{
QSurfaceFormat format;
switch (type) {
case RenderType::OpenGL3:
format.setVersion(3, 0);
format.setProfile(QSurfaceFormat::CoreProfile);
case RenderType::OpenGL:
format.setRenderableType(QSurfaceFormat::OpenGL);
break;
case RenderType::OpenGLES:
format.setRenderableType(QSurfaceFormat::OpenGLES);
break;
}
format.setSwapInterval(0);
setFormat(format);
}
void
HardwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
{
auto tval = this;
void *nuldata = 0;
if (memcmp(&tval, &nuldata, sizeof(void *)) == 0)
return;
auto origSource = source;
if (!m_texture || !m_texture->isCreated()) {
buf_usage[buf_idx].clear();
source.setRect(x, y, w, h);
return;
}
m_context->makeCurrent(this);
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
m_texture->setData(x, y, 0, w, h, 0, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4)), &m_transferOptions);
#else
m_texture->bind();
glPixelStorei(GL_UNPACK_ROW_LENGTH, 2048);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void *) ((uintptr_t) imagebufs[buf_idx].get() + (uintptr_t) (2048 * 4 * y + x * 4)));
m_texture->release();
#endif
buf_usage[buf_idx].clear();
source.setRect(x, y, w, h);
if (origSource != source) {
this->pixelRatio = devicePixelRatioF();
onResize(this->width(), this->height());
}
update();
}
void
HardwareRenderer::resizeEvent(QResizeEvent *event)
{
this->pixelRatio = devicePixelRatioF();
onResize(width(), height());
QOpenGLWindow::resizeEvent(event);
}
bool
HardwareRenderer::event(QEvent *event)
{
bool res = false;
if (!eventDelegate(event, res))
return QOpenGLWindow::event(event);
return res;
}
std::vector<std::tuple<uint8_t *, std::atomic_flag *>>
HardwareRenderer::getBuffers()
{
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> buffers;
buffers.push_back(std::make_tuple(imagebufs[0].get(), &buf_usage[0]));
buffers.push_back(std::make_tuple(imagebufs[1].get(), &buf_usage[1]));
return buffers;
}

View File

@@ -1,103 +0,0 @@
#pragma once
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLWindow>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLTextureBlitter>
#include <QOpenGLPixelTransferOptions>
#include <QPainter>
#include <QEvent>
#include <QKeyEvent>
#include <QWidget>
#include <atomic>
#include <mutex>
#include <array>
#include <vector>
#include <memory>
#include <QApplication>
#include "qt_renderercommon.hpp"
#ifdef WAYLAND
# include "wl_mouse.hpp"
#endif
class HardwareRenderer : public QOpenGLWindow, protected QOpenGLFunctions, public RendererCommon {
Q_OBJECT
private:
bool wayland = false;
QOpenGLContext *m_context;
QOpenGLTexture *m_texture { nullptr };
QOpenGLShaderProgram *m_prog { nullptr };
QOpenGLTextureBlitter *m_blt { nullptr };
QOpenGLBuffer m_vbo[2];
QOpenGLVertexArrayObject m_vao;
QOpenGLPixelTransferOptions m_transferOptions;
public:
enum class RenderType {
OpenGL,
OpenGLES,
OpenGL3,
};
void resizeGL(int w, int h) override;
void initializeGL() override;
void paintGL() override;
void exposeEvent(QExposeEvent *event) override
{
onResize(size().width(), size().height());
}
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() override;
HardwareRenderer(QWidget *parent = nullptr, RenderType rtype = RenderType::OpenGL)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent->windowHandle())
, QOpenGLFunctions()
{
imagebufs[0] = std::unique_ptr<uint8_t>(new uint8_t[2048 * 2048 * 4]);
imagebufs[1] = std::unique_ptr<uint8_t>(new uint8_t[2048 * 2048 * 4]);
buf_usage = std::vector<std::atomic_flag>(2);
buf_usage[0].clear();
buf_usage[1].clear();
setMinimumSize(QSize(16, 16));
setFlags(Qt::FramelessWindowHint);
parentWidget = parent;
setRenderType(rtype);
m_transferOptions.setRowLength(2048);
m_context = new QOpenGLContext();
m_context->setFormat(format());
m_context->create();
update();
}
~HardwareRenderer()
{
m_context->makeCurrent(this);
if (m_blt)
m_blt->destroy();
m_prog->release();
delete m_prog;
m_prog = nullptr;
m_context->doneCurrent();
delete m_context;
}
void setRenderType(RenderType type);
public slots:
void onBlit(int buf_idx, int x, int y, int w, int h);
protected:
std::array<std::unique_ptr<uint8_t>, 2> imagebufs;
void resizeEvent(QResizeEvent *event) override;
bool event(QEvent *event) override;
};

View File

@@ -26,8 +26,8 @@ public:
private:
Ui::KeyBinder *ui;
bool eventFilter(QObject *obj, QEvent *event);
void showEvent( QShowEvent* event );
bool eventFilter(QObject *obj, QEvent *event) override;
void showEvent( QShowEvent* event ) override;
};
#endif // QT_KeyBinder_HPP

View File

@@ -55,6 +55,7 @@ extern "C" {
#endif
#include <86box/gdbstub.h>
#include <86box/version.h>
#include <86box/renderdefs.h>
}
#ifdef Q_OS_WINDOWS
@@ -789,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;
@@ -835,7 +822,7 @@ main(int argc, char *argv[])
/* Set the PAUSE mode depending on the renderer. */
#ifdef USE_VNC
if (vid_api == 5)
if (vid_api == RENDERER_VNC)
plat_pause(1);
else
#endif

View File

@@ -54,6 +54,7 @@ extern "C" {
#include <86box/apm.h>
#include <86box/nvr.h>
#include <86box/acpi.h>
#include <86box/renderdefs.h>
#ifdef USE_VNC
# include <86box/vnc.h>
@@ -424,29 +425,17 @@ MainWindow::MainWindow(QWidget *parent)
ui->actionEnable_Discord_integration->setEnabled(discord_loaded);
#endif
#if defined Q_OS_WINDOWS || defined Q_OS_MACOS
/* Make the option visible only if ANGLE is loaded. */
ui->actionHardware_Renderer_OpenGL_ES->setVisible(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES && vid_api == 2)
vid_api = 1;
#endif
ui->actionHardware_Renderer_OpenGL->setVisible(QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES);
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && vid_api == 1)
vid_api = 0;
if ((QApplication::platformName().contains("eglfs") || QApplication::platformName() == "haiku")) {
if (vid_api >= 1)
if ((vid_api == RENDERER_OPENGL3) || (vid_api == RENDERER_VULKAN))
fprintf(stderr, "OpenGL renderers are unsupported on %s.\n", QApplication::platformName().toUtf8().data());
vid_api = 0;
ui->actionHardware_Renderer_OpenGL->setVisible(false);
ui->actionHardware_Renderer_OpenGL_ES->setVisible(false);
vid_api = RENDERER_SOFTWARE;
ui->actionVulkan->setVisible(false);
ui->actionOpenGL_3_0_Core->setVisible(false);
}
#ifndef USE_VNC
if (vid_api == 5)
vid_api = 0;
if (vid_api == RENDERER_VNC)
vid_api = RENDERER_SOFTWARE;
ui->actionVNC->setVisible(false);
#endif
@@ -466,15 +455,13 @@ MainWindow::MainWindow(QWidget *parent)
if (!vulkanAvailable)
#endif
{
if (vid_api == 4)
vid_api = 0;
if (vid_api == RENDERER_VULKAN)
vid_api = RENDERER_SOFTWARE;
ui->actionVulkan->setVisible(false);
}
auto actGroup = new QActionGroup(this);
actGroup->addAction(ui->actionSoftware_Renderer);
actGroup->addAction(ui->actionHardware_Renderer_OpenGL);
actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES);
actGroup->addAction(ui->actionOpenGL_3_0_Core);
actGroup->addAction(ui->actionVulkan);
actGroup->addAction(ui->actionVNC);
@@ -483,7 +470,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(actGroup, &QActionGroup::triggered, [this](QAction *action) {
vid_api = action->property("vid_api").toInt();
#ifdef USE_VNC
if (vnc_enabled && vid_api != 5) {
if (vnc_enabled && vid_api != RENDERER_VNC) {
startblit();
vnc_enabled = 0;
vnc_close();
@@ -495,23 +482,17 @@ MainWindow::MainWindow(QWidget *parent)
switch (vid_api) {
default:
break;
case 0:
case RENDERER_SOFTWARE:
newVidApi = RendererStack::Renderer::Software;
break;
case 1:
newVidApi = RendererStack::Renderer::OpenGL;
break;
case 2:
newVidApi = RendererStack::Renderer::OpenGLES;
break;
case 3:
case RENDERER_OPENGL3:
newVidApi = RendererStack::Renderer::OpenGL3;
break;
case 4:
case RENDERER_VULKAN:
newVidApi = RendererStack::Renderer::Vulkan;
break;
#ifdef USE_VNC
case 5:
case RENDERER_VNC:
{
newVidApi = RendererStack::Renderer::Software;
startblit();

View File

@@ -121,8 +121,6 @@
<string>Re&amp;nderer</string>
</property>
<addaction name="actionSoftware_Renderer"/>
<addaction name="actionHardware_Renderer_OpenGL"/>
<addaction name="actionHardware_Renderer_OpenGL_ES"/>
<addaction name="actionOpenGL_3_0_Core"/>
<addaction name="actionVulkan"/>
<addaction name="actionVNC"/>
@@ -407,28 +405,6 @@
<number>0</number>
</property>
</action>
<action name="actionHardware_Renderer_OpenGL">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Qt (&amp;OpenGL)</string>
</property>
<property name="vid_api" stdset="0">
<number>1</number>
</property>
</action>
<action name="actionHardware_Renderer_OpenGL_ES">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Qt (OpenGL &amp;ES)</string>
</property>
<property name="vid_api" stdset="0">
<number>2</number>
</property>
</action>
<action name="actionHide_status_bar">
<property name="checkable">
<bool>true</bool>
@@ -759,7 +735,7 @@
<string>Open&amp;GL (3.0 Core)</string>
</property>
<property name="vid_api" stdset="0">
<number>3</number>
<number>1</number>
</property>
</action>
<action name="actionPreferences">
@@ -851,7 +827,7 @@
<string>&amp;Vulkan</string>
</property>
<property name="vid_api" stdset="0">
<number>4</number>
<number>2</number>
</property>
</action>
<action name="actionMCA_devices">
@@ -875,7 +851,7 @@
<string>VNC</string>
</property>
<property name="vid_api" stdset="0">
<number>5</number>
<number>3</number>
</property>
</action>
<action name="actionOpen_screenshots_folder">

View File

@@ -1081,6 +1081,9 @@ MediaMenu::nicUpdateMenu(int i)
case NET_TYPE_VDE:
netType = "VDE";
break;
case NET_TYPE_TAP:
netType = "TAP";
break;
}
QString devName = DeviceConfig::DeviceName(network_card_getdevice(net_cards_conf[i].device_num), network_card_get_internal_name(net_cards_conf[i].device_num), 1);

View File

@@ -303,27 +303,27 @@ OpenGLRenderer::find_uniforms(struct glsl_shader *glsl, int num_pass)
u->orig.texture_size = get_uniform(p, "OrigTextureSize");
for (i = 0; i < glsl->num_passes; ++i) {
sprintf(s, "Pass%dTexture", (i + 1));
snprintf(s, sizeof(s) -1, "Pass%dTexture", (i + 1));
u->pass[i].texture = get_uniform(p, s);
sprintf(s, "Pass%dInputSize", (i + 1));
snprintf(s, sizeof(s) -1, "Pass%dInputSize", (i + 1));
u->pass[i].input_size = get_uniform(p, s);
sprintf(s, "Pass%dTextureSize", (i + 1));
snprintf(s, sizeof(s) -1, "Pass%dTextureSize", (i + 1));
u->pass[i].texture_size = get_uniform(p, s);
sprintf(s, "PassPrev%dTexture", num_pass - i);
snprintf(s, sizeof(s) -1, "PassPrev%dTexture", num_pass - i);
u->prev_pass[i].texture = get_uniform(p, s);
sprintf(s, "PassPrev%dInputSize", num_pass - i);
snprintf(s, sizeof(s) -1, "PassPrev%dInputSize", num_pass - i);
u->prev_pass[i].input_size = get_uniform(p, s);
sprintf(s, "PassPrev%dTextureSize", num_pass - i);
snprintf(s, sizeof(s) -1, "PassPrev%dTextureSize", num_pass - i);
u->prev_pass[i].texture_size = get_uniform(p, s);
}
u->prev[0].texture = get_uniform(p, "PrevTexture");
u->prev[0].tex_coord = get_attrib(p, "PrevTexCoord");
for (i = 1; i < MAX_PREV; ++i) {
sprintf(s, "Prev%dTexture", i);
snprintf(s, sizeof(s) -1, "Prev%dTexture", i);
u->prev[i].texture = get_uniform(p, s);
sprintf(s, "Prev%dTexCoord", i);
snprintf(s, sizeof(s) -1, "Prev%dTexCoord", i);
u->prev[i].tex_coord = get_attrib(p, s);
}
for (i = 0; i < MAX_PREV; ++i)
@@ -434,23 +434,21 @@ OpenGLRenderer::delete_prev(struct shader_prev *prev)
void
OpenGLRenderer::delete_shader(struct glsl_shader *glsl)
{
int i;
for (i = 0; i < glsl->num_passes; ++i)
for (int i = 0; i < glsl->num_passes; ++i)
delete_pass(&glsl->passes[i]);
if (glsl->has_prev) {
delete_pass(&glsl->prev_scene);
for (i = 0; i < MAX_PREV; ++i)
for (int i = 0; i < MAX_PREV; ++i)
delete_prev(&glsl->prev[i]);
}
for (i = 0; i < glsl->num_lut_textures; ++i)
for (int i = 0; i < glsl->num_lut_textures; ++i)
delete_texture(&glsl->lut_textures[i].texture);
}
void
OpenGLRenderer::delete_glsl(glsl_t *glsl)
{
int i;
for (i = 0; i < glsl->num_shaders; ++i)
for (int i = 0; i < glsl->num_shaders; ++i)
delete_shader(&glsl->shaders[i]);
delete_pass(&glsl->scene);
delete_pass(&glsl->fs_color);
@@ -622,7 +620,6 @@ load_texture(const char *f, struct shader_texture *tex)
glsl_t *
OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
{
int i, j;
glslp_t *p = glslp_parse(f);
if (p) {
@@ -639,10 +636,10 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
gshader->num_lut_textures = p->num_textures;
for (i = 0; i < p->num_textures; ++i) {
for (int i = 0; i < p->num_textures; ++i) {
struct texture *texture = &p->textures[i];
sprintf(file, "%s%s", path, texture->path);
snprintf(file, sizeof(file) - 1, "%s%s", path, texture->path);
struct shader_lut_texture *tex = &gshader->lut_textures[i];
strcpy(tex->name, texture->name);
@@ -681,18 +678,18 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
gshader->input_filter_linear = p->input_filter_linear;
gshader->num_parameters = p->num_parameters;
for (j = 0; j < gshader->num_parameters; ++j)
for (int j = 0; j < gshader->num_parameters; ++j)
memcpy(&gshader->parameters[j], &p->parameters[j], sizeof(struct shader_parameter));
gshader->num_passes = p->num_shaders;
for (i = 0; i < p->num_shaders; ++i) {
for (int i = 0; i < p->num_shaders; ++i) {
struct shader *shader = &p->shaders[i];
struct shader_pass *pass = &gshader->passes[i];
strcpy(pass->alias, shader->alias);
if (!strlen(pass->alias))
sprintf(pass->alias, "Pass %u", (i + 1));
snprintf(pass->alias, sizeof(pass->alias) - 1, "Pass %u", (i + 1));
ogl3_log("Creating pass %u (%s)\n", (i + 1), pass->alias);
ogl3_log("Loading shader %s...\n", shader->shader_fn);
@@ -726,7 +723,7 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
if (num_shader == glsl->num_shaders - 1) {
pass->fbo.id = -1;
for (j = 0; j < 2; ++j) {
for (uint8_t j = 0; j < 2; ++j) {
if (pass->scale.mode[j] != SCALE_SOURCE || pass->scale.value[j] != 1) {
setup_fbo(shader, &pass->fbo);
break;
@@ -755,7 +752,7 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
if (gshader->has_prev) {
struct shader scene_shader_conf;
memset(&scene_shader_conf, 0, sizeof(struct shader));
for (i = 0; i < MAX_PREV; ++i) {
for (int i = 0; i < MAX_PREV; ++i) {
setup_fbo(&scene_shader_conf, &gshader->prev[i].fbo);
}
}
@@ -772,7 +769,6 @@ OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f)
glsl_t *
OpenGLRenderer::load_shaders(int num, char shaders[MAX_USER_SHADERS][512])
{
int i;
glsl_t *glsl;
glsl = (glsl_t *) malloc(sizeof(glsl_t));
@@ -780,7 +776,7 @@ OpenGLRenderer::load_shaders(int num, char shaders[MAX_USER_SHADERS][512])
glsl->num_shaders = num;
int failed = 0;
for (i = num - 1; i >= 0; --i) {
for (int i = num - 1; i >= 0; --i) {
const char *f = shaders[i];
if (f && strlen(f)) {
if (!load_glslp(glsl, i, f)) {
@@ -800,13 +796,12 @@ void
OpenGLRenderer::read_shader_config()
{
char s[512];
int i, j;
for (i = 0; i < active_shader->num_shaders; ++i) {
for (int i = 0; i < active_shader->num_shaders; ++i) {
struct glsl_shader *shader = &active_shader->shaders[i];
char *name = shader->name;
sprintf(s, "GL3 Shaders - %s", name);
snprintf(s, sizeof(s) -1, "GL3 Shaders - %s", name);
// shader->shader_refresh_rate = config_get_float(CFG_MACHINE, s, "shader_refresh_rate", -1);
for (j = 0; j < shader->num_parameters; ++j) {
for (int j = 0; j < shader->num_parameters; ++j) {
struct shader_parameter *param = &shader->parameters[j];
param->value = config_get_double(s, param->id, param->default_value);
}
@@ -1233,7 +1228,6 @@ OpenGLRenderer::resizeEvent(QResizeEvent *event)
void
OpenGLRenderer::render_pass(struct render_data *data)
{
int i;
GLuint texture_unit = 0;
// ogl3_log("pass %d: %gx%g, %gx%g -> %gx%g, %gx%g, %gx%g\n", num_pass, pass->state.input_size[0],
@@ -1278,7 +1272,7 @@ OpenGLRenderer::render_pass(struct render_data *data)
if (data->shader) {
/* parameters */
for (i = 0; i < data->shader->num_parameters; ++i)
for (int i = 0; i < data->shader->num_parameters; ++i)
if (u->parameters[i] >= 0)
glw.glUniform1f(u->parameters[i], data->shader->parameters[i].value);
@@ -1296,7 +1290,7 @@ OpenGLRenderer::render_pass(struct render_data *data)
if (u->orig.texture_size >= 0)
glw.glUniform2fv(u->orig.texture_size, 1, orig->state.input_texture_size);
for (i = 0; i < data->pass; ++i) {
for (int i = 0; i < data->pass; ++i) {
if (u->pass[i].texture >= 0) {
glw.glActiveTexture(GL_TEXTURE0 + texture_unit);
glw.glBindTexture(GL_TEXTURE_2D, passes[i].fbo.texture.id);
@@ -1323,7 +1317,7 @@ OpenGLRenderer::render_pass(struct render_data *data)
if (data->shader->has_prev) {
/* loop through each previous frame */
for (i = 0; i < MAX_PREV; ++i) {
for (int i = 0; i < MAX_PREV; ++i) {
if (u->prev[i].texture >= 0) {
glw.glActiveTexture(GL_TEXTURE0 + texture_unit);
glw.glBindTexture(GL_TEXTURE_2D, data->shader->prev[i].fbo.texture.id);
@@ -1340,7 +1334,7 @@ OpenGLRenderer::render_pass(struct render_data *data)
}
}
for (i = 0; i < data->shader->num_lut_textures; ++i) {
for (int i = 0; i < data->shader->num_lut_textures; ++i) {
if (u->lut_textures[i] >= 0) {
glw.glActiveTexture(GL_TEXTURE0 + texture_unit);
glw.glBindTexture(GL_TEXTURE_2D, data->shader->lut_textures[i].texture.id);
@@ -1364,7 +1358,7 @@ OpenGLRenderer::render_pass(struct render_data *data)
glw.glDisableVertexAttribArray(data->shader_pass->uniforms.color);
if (data->shader && data->shader->has_prev) {
for (i = 0; i < MAX_PREV; ++i) {
for (int i = 0; i < MAX_PREV; ++i) {
if (u->prev[i].tex_coord >= 0)
glw.glDisableVertexAttribArray(u->prev[i].tex_coord);
}
@@ -1401,10 +1395,11 @@ OpenGLRenderer::render()
if (notReady())
return;
int s, i, j;
struct {
uint32_t x, y, w, h;
uint32_t x;
uint32_t y;
uint32_t w;
uint32_t h;
} window_rect;
window_rect.x = destination.x();
@@ -1434,7 +1429,10 @@ OpenGLRenderer::render()
struct shader_pass *pass = &active_shader->scene;
struct {
uint32_t x, y, w, h;
uint32_t x;
uint32_t y;
uint32_t w;
uint32_t h;
} rect;
rect.x = 0;
rect.y = 0;
@@ -1496,20 +1494,20 @@ OpenGLRenderer::render()
struct shader_pass *orig = &active_shader->scene;
struct shader_pass *input = &active_shader->scene;
for (s = 0; s < active_shader->num_shaders; ++s) {
for (int s = 0; s < active_shader->num_shaders; ++s) {
struct glsl_shader *shader = &active_shader->shaders[s];
int frame_count = frameCounter;
/* loop through each pass */
for (i = 0; i < shader->num_passes; ++i) {
for (int i = 0; i < shader->num_passes; ++i) {
bool resetFiltering = false;
struct shader_pass *pass = &shader->passes[i];
memcpy(pass->state.input_size, input->state.output_size, 2 * sizeof(GLfloat));
memcpy(pass->state.input_texture_size, input->state.output_texture_size, 2 * sizeof(GLfloat));
for (j = 0; j < 2; ++j) {
for (uint8_t j = 0; j < 2; ++j) {
if (pass->scale.mode[j] == SCALE_VIEWPORT)
pass->state.output_size[j] = orig_output_size[j] * pass->scale.value[j];
else if (pass->scale.mode[j] == SCALE_ABSOLUTE)
@@ -1640,7 +1638,7 @@ OpenGLRenderer::render()
memcpy(pass->state.input_size, input->state.output_size, 2 * sizeof(GLfloat));
memcpy(pass->state.input_texture_size, input->state.output_texture_size, 2 * sizeof(GLfloat));
for (j = 0; j < 2; ++j) {
for (uint8_t j = 0; j < 2; ++j) {
if (pass->scale.mode[j] == SCALE_VIEWPORT)
pass->state.output_size[j] = orig_output_size[j] * pass->scale.value[j];
else if (pass->scale.mode[j] == SCALE_ABSOLUTE)

View File

@@ -34,6 +34,7 @@
# include <QtOpenGLExtensions/QOpenGLExtensions>
#endif
#include <array>
#include <atomic>
#include <stdexcept>
#include <tuple>

View File

@@ -341,9 +341,25 @@ path_get_slash(char *path)
void
path_append_filename(char *dest, const char *s1, const char *s2)
{
strcpy(dest, s1);
path_slash(dest);
strcat(dest, s2);
size_t dest_size = 260;
size_t len;
if (!dest || !s1 || !s2)
return;
snprintf(dest, dest_size, "%s", s1);
len = strlen(dest);
if (len > 0 && dest[len - 1] != '/' && dest[len - 1] != '\\') {
if (len + 1 < dest_size) {
dest[len++] = '/';
dest[len] = '\0';
}
}
if (len < dest_size - 1) {
strncat(dest, s2, dest_size - len - 1);
}
}
void

View File

@@ -21,7 +21,6 @@
#include "qt_rendererstack.hpp"
#include "ui_qt_rendererstack.h"
#include "qt_hardwarerenderer.hpp"
#include "qt_openglrenderer.hpp"
#include "qt_softwarerenderer.hpp"
#include "qt_vulkanwindowrenderer.hpp"
@@ -41,6 +40,22 @@
#include <QTouchEvent>
#include <QStringBuilder>
#include <QPainter>
#include <QEvent>
#include <QKeyEvent>
#include <QWidget>
#include <atomic>
#include <mutex>
#include <array>
#include <vector>
#include <memory>
#include <QApplication>
#ifdef WAYLAND
# include "wl_mouse.hpp"
#endif
#ifdef __APPLE__
# include <CoreGraphics/CoreGraphics.h>
#endif
@@ -336,24 +351,6 @@ RendererStack::createRenderer(Renderer renderer)
#endif
}
break;
case Renderer::OpenGL:
{
this->createWinId();
auto hw = new HardwareRenderer(this);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGLES:
{
this->createWinId();
auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGLES);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGL3:
{
this->createWinId();

View File

@@ -80,8 +80,6 @@ public:
enum class Renderer {
Software,
OpenGL,
OpenGLES,
OpenGL3,
Vulkan,
None = -1

View File

@@ -36,18 +36,22 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui)
auto *nic_cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1));
auto *net_type_cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
auto *intf_label = findChild<QLabel *>(QString("labelIntf%1").arg(i + 1));
auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
auto *intf_label = findChild<QLabel *>(QString("labelIntf%1").arg(i + 1));
auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
auto *conf_btn = findChild<QPushButton *>(QString("pushButtonConf%1").arg(i + 1));
// auto *net_type_conf_btn = findChild<QPushButton *>(QString("pushButtonNetTypeConf%1").arg(i + 1));
auto *vde_socket_label = findChild<QLabel *>(QString("labelSocketVDENIC%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
auto *bridge_label = findChild<QLabel *>(QString("labelBridgeTAPNIC%1").arg(i + 1));
auto *bridge_line = findChild<QLineEdit *>(QString("bridgeTAPNIC%1").arg(i + 1));
auto *option_list_label = findChild<QLabel *>(QString("labelOptionList%1").arg(i + 1));
auto *option_list_line = findChild<QWidget *>(QString("lineOptionList%1").arg(i + 1));
auto *option_list_line = findChild<QWidget *>(QString("lineOptionList%1").arg(i + 1));
bridge_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_TAP);
intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP);
conf_btn->setEnabled(network_card_has_config(nic_cbox->currentData().toInt()));
// net_type_conf_btn->setEnabled(network_type_has_config(netType));
@@ -60,6 +64,10 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui)
vde_socket_label->setVisible(false);
socket_line->setVisible(false);
// TAP
bridge_label->setVisible(false);
bridge_line->setVisible(false);
// PCAP
intf_cbox->setVisible(false);
intf_label->setVisible(false);
@@ -86,6 +94,17 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui)
intf_label->setVisible(true);
break;
#if defined(__unix__) || defined(__APPLE__)
case NET_TYPE_TAP:
// option_list_label->setText("TAP Options");
option_list_label->setVisible(true);
option_list_line->setVisible(true);
bridge_label->setVisible(true);
bridge_line->setVisible(true);
break;
#endif
case NET_TYPE_SLIRP:
default:
break;
@@ -123,6 +142,7 @@ SettingsNetwork::save()
for (int i = 0; i < NET_CARD_MAX; ++i) {
auto *cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
auto *bridge_line = findChild<QLineEdit *>(QString("bridgeTAPNIC%1").arg(i + 1));
net_cards_conf[i].device_num = cbox->currentData().toInt();
cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
net_cards_conf[i].net_type = cbox->currentData().toInt();
@@ -132,6 +152,10 @@ SettingsNetwork::save()
strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1);
else if (net_cards_conf[i].net_type == NET_TYPE_VDE)
strncpy(net_cards_conf[i].host_dev_name, socket_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name));
#if defined(__unix__) || defined(__APPLE__)
else if (net_cards_conf[i].net_type == NET_TYPE_TAP)
strncpy(net_cards_conf[i].host_dev_name, bridge_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name));
#endif
}
}
@@ -198,6 +222,10 @@ SettingsNetwork::onCurrentMachineChanged(int machineId)
if (network_devmap.has_vde)
Models::AddEntry(model, "VDE", NET_TYPE_VDE);
#if defined(__unix__) || defined(__APPLE__)
Models::AddEntry(model, "TAP", NET_TYPE_TAP);
#endif
model->removeRows(0, removeRows);
cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type));
@@ -216,12 +244,18 @@ SettingsNetwork::onCurrentMachineChanged(int machineId)
}
model->removeRows(0, removeRows);
cbox->setCurrentIndex(selectedRow);
}
}
if (net_cards_conf[i].net_type == NET_TYPE_VDE) {
QString currentVdeSocket = net_cards_conf[i].host_dev_name;
auto editline = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i+1));
editline->setText(currentVdeSocket);
#if defined(__unix__) || defined(__APPLE__)
} else if (net_cards_conf[i].net_type == NET_TYPE_TAP) {
QString currentTapDevice = net_cards_conf[i].host_dev_name;
auto editline = findChild<QLineEdit *>(QString("bridgeTAPNIC%1").arg(i+1));
editline->setText(currentTapDevice);
#endif
}
}
}

View File

@@ -31,7 +31,6 @@
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabNet1">
<attribute name="title">
<string>Network Card #1</string>
@@ -156,7 +155,21 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="6" column="0">
<widget class="QLabel" name="labelBridgeTAPNIC1">
<property name="text">
<string>TAP Bridge Device</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="bridgeTAPNIC1">
<property name="maxLength">
<number>127</number>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="verticalSpacerNIC1">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -171,7 +184,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabNet2">
<attribute name="title">
<string>Network Card #2</string>
@@ -296,7 +308,21 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="6" column="0">
<widget class="QLabel" name="labelBridgeTAPNIC2">
<property name="text">
<string>TAP Bridge Device</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="bridgeTAPNIC2">
<property name="maxLength">
<number>127</number>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="verticalSpacerNIC2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -311,7 +337,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabNet3">
<attribute name="title">
<string>Network Card #3</string>
@@ -436,7 +461,21 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="6" column="0">
<widget class="QLabel" name="labelBridgeTAPNIC3">
<property name="text">
<string>TAP Bridge Device</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="bridgeTAPNIC3">
<property name="maxLength">
<number>127</number>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="verticalSpacerNIC3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -451,7 +490,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabNet4">
<attribute name="title">
<string>Network Card #4</string>
@@ -576,7 +614,21 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="6" column="0">
<widget class="QLabel" name="labelBridgeTAPNIC4">
<property name="text">
<string>TAP Bridge Device</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="bridgeTAPNIC4">
<property name="maxLength">
<number>127</number>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="verticalSpacerNIC4">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -591,7 +643,6 @@
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@@ -243,7 +243,7 @@ SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index)
if (index < 0)
return;
ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0);
ui->pushButtonFD->setEnabled(fdc_card_has_config(ui->comboBoxFD->currentData().toInt()) > 0);
}
void

View File

@@ -46,7 +46,7 @@ UpdateDetails(const UpdateCheck::UpdateResult &updateResult, QWidget *parent) :
const auto downloadButton = new QPushButton(tr("Visit download page"));
ui->buttonBox->addButton(downloadButton, QDialogButtonBox::AcceptRole);
// Override accepted to mean "I want to visit the download page"
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this, updateResult] {
connect(ui->buttonBox, &QDialogButtonBox::accepted, [updateResult] {
visitDownloadPage(updateResult.channel);
});
const auto logo = QPixmap(":/assets/86box.png").scaled(QSize(64, 64), Qt::KeepAspectRatio, Qt::SmoothTransformation);
@@ -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;
}
}

View File

@@ -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 {

View File

@@ -26,6 +26,8 @@
extern bool windows_is_light_theme();
#endif
using namespace VMManager;
VMManagerDetails::VMManagerDetails(QWidget *parent) :
QWidget(parent), ui(new Ui::VMManagerDetails) {
ui->setupUi(this);

View File

@@ -21,6 +21,7 @@
#include <QPushButton>
const QString VMManagerDetailSection::sectionSeparator = ";";
using namespace VMManager;
VMManagerDetailSection::
VMManagerDetailSection(const QString &sectionName)

View File

@@ -60,7 +60,7 @@ public:
~VMManagerDetailSection() override;
void addSection(const QString &name, const QString &value, Display::Name displayField = Display::Name::Unknown);
void addSection(const QString &name, const QString &value, VMManager::Display::Name displayField = VMManager::Display::Name::Unknown);
void clear();
CollapseButton *collapseButton;

View File

@@ -62,7 +62,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) :
QAction openSystemFolderAction(tr("Open folder"));
contextMenu.addAction(&openSystemFolderAction);
connect(&openSystemFolderAction, &QAction::triggered, [this, indexAt] {
connect(&openSystemFolderAction, &QAction::triggered, [indexAt] {
if (const auto configDir = indexAt.data(VMManagerModel::Roles::ConfigDir).toString(); !configDir.isEmpty()) {
QDir dir(configDir);
if (!dir.exists())
@@ -72,13 +72,9 @@ 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, indexAt] {
connect(&setSystemIcon, &QAction::triggered, [this] {
IconSelectionDialog dialog(":/systemicons/");
if(dialog.exec() == QDialog::Accepted) {
const QString iconName = dialog.getSelectedIconName();
@@ -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

View File

@@ -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

View File

@@ -51,6 +51,8 @@ extern "C" {
#include <86box/mouse.h>
}
using namespace VMManager;
VMManagerSystem::VMManagerSystem(const QString &sysconfig_file) {
// The 86Box configuration file
@@ -717,7 +719,7 @@ VMManagerSystem::setupVars() {
// Serial
// By default serial 1 and 2 are enabled unless otherwise specified
static auto serial_match = QRegularExpression("serial\\d_enabled", QRegularExpression::CaseInsensitiveOption);
QList<bool> serial_enabled = {true, true, false, false};
QList<bool> serial_enabled = {true, true, false, false, false, false, false, false};
// Parallel
// By default lpt 1 is enabled unless otherwise specified
static auto lpt_match = QRegularExpression("lpt\\d_enabled", QRegularExpression::CaseInsensitiveOption);

View File

@@ -34,6 +34,8 @@ inline uint qHash(const T &t, uint seed) { \
return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \
}
namespace VMManager {
Q_NAMESPACE
namespace Display {
Q_NAMESPACE
enum class Name {
@@ -58,11 +60,12 @@ enum class Name {
Q_ENUM_NS(Name)
QHASH_FOR_CLASS_ENUM(Name)
}
}
class VMManagerSystem : public QWidget {
Q_OBJECT
typedef QHash<Display::Name, QString> display_table_t;
typedef QHash<VMManager::Display::Name, QString> display_table_t;
typedef QHash <QString, QHash <QString, QString>> config_hash_t;
public:
@@ -127,7 +130,7 @@ public:
bool window_obscured;
QString getDisplayValue(Display::Name key);
QString getDisplayValue(VMManager::Display::Name key);
QFileInfoList getScreenshots();
inline bool operator==(const VMManagerSystem &rhs) const

View File

@@ -222,6 +222,7 @@ joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy)
UINT size = 0;
PHIDP_BUTTON_CAPS btn_caps = NULL;
PHIDP_VALUE_CAPS val_caps = NULL;
HIDP_CAPS caps;
/* Get preparsed data (HID data format) */
GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size);
@@ -229,7 +230,6 @@ joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy)
if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0)
fatal("joystick_get_capabilities: Failed to get preparsed data.\n");
HIDP_CAPS caps;
HidP_GetCaps(rawjoy->data, &caps);
/* Buttons */
@@ -356,6 +356,7 @@ end_loop:
free(info);
}
free(deviceList);
joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present);
/* Initialize the RawInput (joystick and gamepad) module. */

View File

@@ -13,7 +13,7 @@
* Jasmine Iwanek <jasmine@iwanek.co.uk>
*
* Copyright 2021 Andreas J. Reichel
* Copyright 2021-2023 Jasmine Iwanek
* Copyright 2021-2025 Jasmine Iwanek
*/
#define _XOPEN_SOURCE 500
@@ -46,9 +46,9 @@ plat_serpt_close(void *priv)
fclose(dev->master_fd);
#endif
FlushFileBuffers((HANDLE) dev->master_fd);
if (dev->mode == SERPT_MODE_VCON)
if (dev->mode == SERPT_MODE_NPIPE_SRV)
DisconnectNamedPipe((HANDLE) dev->master_fd);
if (dev->mode == SERPT_MODE_HOSTSER) {
else if (dev->mode == SERPT_MODE_HOSTSER) {
SetCommState((HANDLE) dev->master_fd, (DCB *) dev->backend_priv);
free(dev->backend_priv);
}
@@ -133,7 +133,8 @@ plat_serpt_write(void *priv, uint8_t data)
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
switch (dev->mode) {
case SERPT_MODE_VCON:
case SERPT_MODE_NPIPE_SRV:
case SERPT_MODE_NPIPE_CLNT:
case SERPT_MODE_HOSTSER:
plat_serpt_write_vcon(dev, data);
break;
@@ -157,7 +158,8 @@ plat_serpt_read(void *priv, uint8_t *data)
int res = 0;
switch (dev->mode) {
case SERPT_MODE_VCON:
case SERPT_MODE_NPIPE_SRV:
case SERPT_MODE_NPIPE_CLNT:
case SERPT_MODE_HOSTSER:
res = plat_serpt_read_vcon(dev, data);
break;
@@ -187,6 +189,42 @@ open_pseudo_terminal(serial_passthrough_t *dev)
return 1;
}
static int
connect_named_pipe_client(serial_passthrough_t *dev)
{
char ascii_pipe_name[1024] = { 0 };
size_t len = strlen(dev->named_pipe);
if ((len + 1) >= sizeof(ascii_pipe_name))
memcpy(ascii_pipe_name, dev->named_pipe, sizeof(ascii_pipe_name));
else
memcpy(ascii_pipe_name, dev->named_pipe, len + 1);
HANDLE hPipe = CreateFileA(
ascii_pipe_name, // pipe name
GENERIC_READ | GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // open existing pipe
0, // default attributes
NULL); // no template file
if (hPipe == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
wchar_t errorMsg[1024] = { 0 };
wchar_t finalMsg[1024] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMsg, 1024, NULL);
swprintf(finalMsg, 1024, L"Named Pipe (client, named_pipe=\"%hs\", port=COM%d): %ls\n", ascii_pipe_name, dev->port + 1, errorMsg);
ui_msgbox(MBX_ERROR | MBX_FATAL, finalMsg);
return 0;
}
DWORD mode = PIPE_READMODE_BYTE | PIPE_NOWAIT;
SetNamedPipeHandleState(hPipe, &mode, NULL, NULL);
dev->master_fd = (intptr_t) hPipe;
pclog("Named Pipe client connected to %s\n", ascii_pipe_name);
return 1;
}
static int
open_host_serial_port(serial_passthrough_t *dev)
{
@@ -222,15 +260,18 @@ plat_serpt_open_device(void *priv)
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
switch (dev->mode) {
case SERPT_MODE_VCON:
if (open_pseudo_terminal(dev)) {
case SERPT_MODE_NPIPE_SRV:
if (open_pseudo_terminal(dev))
return 0;
break;
case SERPT_MODE_NPIPE_CLNT:
if (connect_named_pipe_client(dev))
return 0;
}
break;
case SERPT_MODE_HOSTSER:
if (open_host_serial_port(dev)) {
if (open_host_serial_port(dev))
return 0;
}
break;
default:
break;
}

View File

@@ -50,12 +50,6 @@ static struct zwp_relative_pointer_v1_listener rel_listener = {
rel_mouse_event
};
static struct zwp_keyboard_shortcuts_inhibitor_v1_listener kbd_listener
{
[](void *data, struct zwp_keyboard_shortcuts_inhibitor_v1 *zwp_keyboard_shortcuts_inhibitor_v1) -> void {},
[](void *data, struct zwp_keyboard_shortcuts_inhibitor_v1 *zwp_keyboard_shortcuts_inhibitor_v1) -> void {}
};
static void
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)

View File

@@ -54,6 +54,14 @@ typedef const struct {
static SCSI_CARD scsi_cards[] = {
// clang-format off
{ &device_none, },
/* ISA/Sidecar */
{ &scsi_ls2000_device, },
/* ISA */
{ &scsi_lcs6821n_device, },
{ &scsi_rt1000b_device, },
{ &scsi_t128_device, },
{ &scsi_t130b_device, },
/* ISA16 */
{ &aha154xa_device, },
{ &aha154xb_device, },
{ &aha154xc_device, },
@@ -63,18 +71,19 @@ static SCSI_CARD scsi_cards[] = {
{ &buslogic_542bh_device, },
{ &buslogic_545s_device, },
{ &buslogic_545c_device, },
{ &scsi_ls2000_device, },
{ &scsi_lcs6821n_device, },
{ &scsi_rt1000b_device, },
{ &scsi_rt1000mc_device, },
{ &scsi_t128_device, },
{ &scsi_t228_device, },
{ &scsi_t130b_device, },
/* MCA */
{ &aha1640_device, },
{ &buslogic_640a_device, },
{ &ncr53c90a_mca_device, },
{ &spock_device, },
{ &tribble_device, },
{ &ncr53c90a_mca_device, },
{ &scsi_rt1000mc_device, },
{ &scsi_t228_device, },
/* VLB */
{ &buslogic_445s_device, },
{ &buslogic_445c_device, },
/* PCI */
{ &am53c974_pci_device, },
{ &buslogic_958d_pci_device, },
{ &ncr53c810_pci_device, },
{ &ncr53c815_pci_device, },
@@ -82,10 +91,7 @@ static SCSI_CARD scsi_cards[] = {
{ &ncr53c825a_pci_device, },
{ &ncr53c860_pci_device, },
{ &ncr53c875_pci_device, },
{ &am53c974_pci_device, },
{ &dc390_pci_device, },
{ &buslogic_445s_device, },
{ &buslogic_445c_device, },
{ NULL, },
// clang-format on
};

View File

@@ -85,11 +85,18 @@ ali5123_lpt_handler(ali5123_t *dev)
uint8_t global_enable = !(dev->regs[0x22] & (1 << 3));
uint8_t local_enable = !!dev->ld_regs[3][0x30];
uint8_t lpt_irq = dev->ld_regs[3][0x70];
uint8_t lpt_dma = dev->ld_regs[3][0x74];
if (lpt_irq > 15)
lpt_irq = 0xff;
if (lpt_dma == 4)
lpt_dma = 0xff;
lpt1_remove();
lpt_set_epp(0, !!(dev->ld_regs[3][0xf0] & 0x01));
lpt_set_ecp(0, !!(dev->ld_regs[3][0xf0] & 0x02));
lpt_set_ext(0, !(dev->ld_regs[3][0xf0] & 0x04) || !!(dev->ld_regs[3][0xf1] & 0x80));
if (global_enable && local_enable) {
ld_port = make_port(dev, 3) & 0xFFFC;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
@@ -247,7 +254,7 @@ ali5123_write(uint16_t port, uint8_t val, void *priv)
dev->regs[dev->cur_reg] = val;
} else {
valxor = val ^ dev->ld_regs[cur_ld][dev->cur_reg];
if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4))
if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4) && (cur_ld != 3))
return;
/* Block writes to some logical devices. */
if (cur_ld > 0x0c)
@@ -357,6 +364,9 @@ ali5123_write(uint16_t port, uint8_t val, void *priv)
case 0x60:
case 0x61:
case 0x70:
case 0x74:
case 0xf0:
case 0xf1:
if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] &= ~0x08;
if (valxor)

Some files were not shown because too many files have changed in this diff Show More