diff --git a/.ci/build.sh b/.ci/build.sh index 278e252d8..3ac28eb8a 100644 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -107,6 +107,19 @@ make_tar() { return $? } +cache_dir="$HOME/86box-build-cache" +[ ! -d "$cache_dir" ] && mkdir -p "$cache_dir" +check_buildtag() { + [ -z "$BUILD_TAG" -o "$BUILD_TAG" != "$(cat "$cache_dir/buildtag.$1" 2> /dev/null)" ] + return $? +} +save_buildtag() { + local contents="$BUILD_TAG" + [ -n "$2" ] && local contents="$2" + echo "$contents" > "$cache_dir/buildtag.$1" + return $? +} + # Set common variables. project=86Box cwd=$(pwd) @@ -244,105 +257,128 @@ then fi echo [-] Using MSYSTEM [$MSYSTEM] - # Update keyring, as the package signing keys sometimes change. - echo [-] Updating package databases and keyring - yes | pacman -Sy --needed msys2-keyring - - # Query installed packages. - pacman -Qe > pacman.txt - - # Download the specified versions of architecture-specific dependencies. - echo -n [-] Downloading dependencies: - pkg_dir="/var/cache/pacman/pkg" - repo_base="https://repo.msys2.org/mingw/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')" - cat .ci/dependencies_msys.txt | tr -d '\r' > deps.txt - pkgs="" - while IFS=" " read pkg version - do - prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg" - installed_version=$(grep -E "^$prefixed_pkg " pacman.txt | cut -d " " -f 2) - if [ "$installed_version" != "$version" ] # installed_version will be empty if not installed + # Install dependencies only if we're in a new build and/or architecture. + freetype_dll="$cache_dir/freetype.$MSYSTEM.dll" + if check_buildtag "$MSYSTEM" + then + # Update databases and keyring only if we're in a new build. + if check_buildtag pacmansync then - echo -n " [$pkg" + # Update keyring as well, since the package signing keys sometimes change. + echo [-] Updating package databases and keyring + yes | pacman -Sy --needed msys2-keyring - # Download package if not already present in the local cache. - pkg_tar="$prefixed_pkg-$version-any.pkg.tar" - if [ -s "$pkg_dir/$pkg_tar.xz" ] + # Save build tag to skip pacman sync/keyring later. + save_buildtag pacmansync + else + echo [-] Not updating package databases and keyring again + fi + + # Query installed packages. + pacman -Qe > "$cache_dir/pacman.txt" + + # Download the specified versions of architecture-specific dependencies. + echo -n [-] Downloading dependencies: + pkg_dir="/var/cache/pacman/pkg" + repo_base="https://repo.msys2.org/mingw/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')" + cat .ci/dependencies_msys.txt | tr -d '\r' > "$cache_dir/deps.txt" + pkgs="" + while IFS=" " read pkg version + do + prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg" + installed_version=$(grep -E "^$prefixed_pkg " "$cache_dir/pacman.txt" | cut -d " " -f 2) + if [ "$installed_version" != "$version" ] # installed_version will be empty if not installed then - pkg_fn="$pkg_tar.xz" - pkg_dest="$pkg_dir/$pkg_fn" - else - pkg_fn="$pkg_tar.zst" - pkg_dest="$pkg_dir/$pkg_fn" - if [ ! -s "$pkg_dest" ] + echo -n " [$pkg" + + # Download package if not already present in the local cache. + pkg_tar="$prefixed_pkg-$version-any.pkg.tar" + if [ -s "$pkg_dir/$pkg_tar.xz" ] then - if ! wget -qO "$pkg_dest" "$repo_base/$pkg_fn" + pkg_fn="$pkg_tar.xz" + pkg_dest="$pkg_dir/$pkg_fn" + else + pkg_fn="$pkg_tar.zst" + pkg_dest="$pkg_dir/$pkg_fn" + if [ ! -s "$pkg_dest" ] then - rm -f "$pkg_dest" - pkg_fn="$pkg_tar.xz" - pkg_dest="$pkg_dir/$pkg_fn" - wget -qO "$pkg_dest" "$repo_base/$pkg_fn" || rm -f "$pkg_dest" - fi - if [ -s "$pkg_dest" ] - then - wget -qO "$pkg_dest.sig" "$repo_base/$pkg_fn.sig" || rm -f "$pkg_dest.sig" - [ ! -s "$pkg_dest.sig" ] && rm -f "$pkg_dest.sig" + if ! wget -qO "$pkg_dest" "$repo_base/$pkg_fn" + then + rm -f "$pkg_dest" + pkg_fn="$pkg_tar.xz" + pkg_dest="$pkg_dir/$pkg_fn" + wget -qO "$pkg_dest" "$repo_base/$pkg_fn" || rm -f "$pkg_dest" + fi + if [ -s "$pkg_dest" ] + then + wget -qO "$pkg_dest.sig" "$repo_base/$pkg_fn.sig" || rm -f "$pkg_dest.sig" + [ ! -s "$pkg_dest.sig" ] && rm -f "$pkg_dest.sig" + fi fi fi - fi - # Check if the cached package is valid. - if [ -s "$pkg_dest" ] + # Check if the cached package is valid. + if [ -s "$pkg_dest" ] + then + # Add cached zst package. + pkgs="$pkgs $pkg_fn" + else + # Not valid, remove if it exists. + rm -f "$pkg_dest" "$pkg_dest.sig" + echo -n " FAIL" + fi + echo -n "]" + fi + done < "$cache_dir/deps.txt" + [ -z "$pkgs" ] && echo -n ' none required' + echo + + # Install the downloaded architecture-specific dependencies. + echo [-] Installing dependencies through pacman + if [ -n "$pkgs" ] + then + pushd "$pkg_dir" + yes | pacman -U --needed $pkgs + if [ $? -ne 0 ] then - # Add cached zst package. - pkgs="$pkgs $pkg_fn" - else - # Not valid, remove if it exists. - rm -f "$pkg_dest" "$pkg_dest.sig" - echo -n " FAIL" + # Install packages individually if installing them all together failed. + for pkg in $pkgs + do + yes | pacman -U --needed "$pkg" + done fi - echo -n "]" - fi - done < deps.txt - [ -z "$pkgs" ] && echo -n ' none required' - echo + popd - # Install the downloaded architecture-specific dependencies. - echo [-] Installing dependencies through pacman - if [ -n "$pkgs" ] - then - pushd "$pkg_dir" - yes | pacman -U --needed $pkgs + # Query installed packages again. + pacman -Qe > "$cache_dir/pacman.txt" + fi + + # Install the latest versions for any missing packages (if the specified version couldn't be installed). + pkgs="git" + while IFS=" " read pkg version + do + prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg" + grep -qE "^$prefixed_pkg " "$cache_dir/pacman.txt" || pkgs="$pkgs $prefixed_pkg" + done < "$cache_dir/deps.txt" + rm -f "$cache_dir/pacman.txt" "$cache_dir/deps.txt" + yes | pacman -S --needed $pkgs if [ $? -ne 0 ] then # Install packages individually if installing them all together failed. for pkg in $pkgs do - yes | pacman -U --needed "$pkg" + yes | pacman -S --needed "$pkg" done fi - popd - # Query installed packages again. - pacman -Qe > pacman.txt - fi + # Generate a new freetype DLL for this architecture. + rm -f "$freetype_dll" - # Install the latest versions for any missing packages (if the specified version couldn't be installed). - pkgs="git" - while IFS=" " read pkg version - do - prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg" - grep -qE "^$prefixed_pkg " pacman.txt || pkgs="$pkgs $prefixed_pkg" - done < deps.txt - rm -f pacman.txt deps.txt - yes | pacman -S --needed $pkgs - if [ $? -ne 0 ] - then - # Install packages individually if installing them all together failed. - for pkg in $pkgs - do - yes | pacman -S --needed "$pkg" - done + # Save build tag to skip this later. Doing it here (once everything is + # in place) is important to avoid potential issues with retried builds. + save_buildtag "$MSYSTEM" + else + echo [-] Not installing dependencies again fi # Point CMake to the toolchain file. @@ -352,7 +388,7 @@ then # macOS lacks nproc, but sysctl can do the same job. alias nproc='sysctl -n hw.logicalcpu' - # Handle universal build. + # Handle universal building. if echo "$arch" | grep -q '+' then # Create temporary directory for merging app bundles. @@ -391,18 +427,18 @@ then echo [-] Merging app bundles [$merge_src] and [$arch_universal] into [$merge_dest] # Merge directory structures. - (cd "archive_tmp_universal/$merge_src.app" && find . -type d && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type d && cd ../..) | sort > universal_listing.txt - cat universal_listing.txt | uniq | while IFS= read line + (cd "archive_tmp_universal/$merge_src.app" && find . -type d && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type d && cd ../..) | sort > "$cache_dir/universal_listing.txt" + cat "$cache_dir/universal_listing.txt" | uniq | while IFS= read line do echo "> Directory: $line" mkdir -p "archive_tmp_universal/$merge_dest.app/$line" done # Create merged file listing. - (cd "archive_tmp_universal/$merge_src.app" && find . -type f && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type f && cd ../..) | sort > universal_listing.txt + (cd "archive_tmp_universal/$merge_src.app" && find . -type f && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type f && cd ../..) | sort > "$cache_dir/universal_listing.txt" # Copy files that only exist on one bundle. - cat universal_listing.txt | uniq -u | while IFS= read line + cat "$cache_dir/universal_listing.txt" | uniq -u | while IFS= read line do if [ -e "archive_tmp_universal/$merge_src.app/$line" ] then @@ -415,7 +451,7 @@ then done # Copy or lipo files that exist on both bundles. - cat universal_listing.txt | uniq -d | while IFS= read line + cat "$cache_dir/universal_listing.txt" | uniq -d | while IFS= read line do if cmp -s "archive_tmp_universal/$merge_src.app/$line" "archive_tmp_universal/$arch_universal.app/$line" then @@ -431,8 +467,8 @@ then done # Merge symlinks. - (cd "archive_tmp_universal/$merge_src.app" && find . -type l && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type l && cd ../..) | sort > universal_listing.txt - cat universal_listing.txt | uniq | while IFS= read line + (cd "archive_tmp_universal/$merge_src.app" && find . -type l && cd "../../archive_tmp_universal/$arch_universal.app" && find . -type l && cd ../..) | sort > "$cache_dir/universal_listing.txt" + cat "$cache_dir/universal_listing.txt" | uniq | while IFS= read line do # Get symlink destinations. other_link_dest= @@ -526,10 +562,21 @@ then [ "$arch" = "x86_64" -a -e "/opt/intel/bin/port" ] && macports="/opt/intel" export PATH="$macports/bin:$macports/sbin:$macports/libexec/qt5/bin:$PATH" - # Install dependencies. - echo [-] Installing dependencies through MacPorts - sudo "$macports/bin/port" selfupdate - sudo "$macports/bin/port" install $(cat .ci/dependencies_macports.txt) + # Install dependencies only if we're in a new build and/or architecture. + if check_buildtag "$(arch)" + then + # Install dependencies. + echo [-] Installing dependencies through MacPorts + sudo "$macports/bin/port" selfupdate + sudo "$macports/bin/port" install $(cat .ci/dependencies_macports.txt) + + # Save build tag to skip this later. Doing it here (once everything is + # in place) is important to avoid potential issues with retried builds. + save_buildtag "$(arch)" + else + echo [-] Not installing dependencies again + + fi # Point CMake to the toolchain file. [ -e "cmake/$toolchain.cmake" ] && cmake_flags_extra="$cmake_flags_extra -D \"CMAKE_TOOLCHAIN_FILE=cmake/$toolchain.cmake\"" @@ -548,7 +595,15 @@ else then pkgs="$pkgs build-essential" else - sudo dpkg --add-architecture "$arch_deb" + # Add foreign architecture if required. + if ! dpkg --print-foreign-architectures | grep -qE '^'"$arch_deb"'$' + then + sudo dpkg --add-architecture "$arch_deb" + + # Force an apt-get update. + save_buildtag aptupdate "arch_$arch_deb" + fi + pkgs="$pkgs crossbuild-essential-$arch_deb" fi @@ -606,11 +661,28 @@ EOF cmake_flags_extra="$cmake_flags_extra -D CMAKE_TOOLCHAIN_FILE=toolchain.cmake" strip_binary="$arch_triplet-strip" - # Install or update dependencies. - echo [-] Installing dependencies through apt - sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get -y install $pkgs $libpkgs - sudo apt-get clean + # Install dependencies only if we're in a new build and/or architecture. + if check_buildtag "$arch_deb" + then + # Install or update dependencies. + echo [-] Installing dependencies through apt + if check_buildtag aptupdate + then + sudo apt-get update + + # Save build tag to skip apt-get update later, unless a new architecture + # is added to dpkg, in which case, this saved tag file gets replaced. + save_buildtag aptupdate + fi + DEBIAN_FRONTEND=noninteractive sudo apt-get -y install $pkgs $libpkgs + sudo apt-get clean + + # Save build tag to skip this later. Doing it here (once everything is + # in place) is important to avoid potential issues with retried builds. + save_buildtag "$arch_deb" + else + echo [-] Not installing dependencies again + fi # Link against the system libslirp instead of compiling ours. cmake_flags_extra="$cmake_flags_extra -D SLIRP_EXTERNAL=ON" @@ -618,12 +690,7 @@ fi # Clean workspace. echo [-] Cleaning workspace -if [ -d "build" ] -then - cmake --build build -j$(nproc) --target clean 2> /dev/null - rm -rf build -fi -find . \( -name Makefile -o -name CMakeCache.txt -o -name CMakeFiles \) -exec rm -rf "{}" \; 2> /dev/null +rm -rf build # Add ARCH to skip the arch_detect process. case $arch in @@ -671,17 +738,25 @@ then exit 4 fi -# Download Discord Game SDK from their CDN if necessary. -if [ ! -e "discord_game_sdk.zip" ] +# Download Discord Game SDK from their CDN if we're in a new build. +discord_zip="$cache_dir/discord_game_sdk.zip" +if check_buildtag discord then + # Download file. echo [-] Downloading Discord Game SDK - wget -qO discord_game_sdk.zip "https://dl-game-sdk.discordapp.net/latest/discord_game_sdk.zip" + wget -qO "$discord_zip" "https://dl-game-sdk.discordapp.net/latest/discord_game_sdk.zip" status=$? if [ $status -ne 0 ] then echo [!] Discord Game SDK download failed with status [$status] - rm -f discord_game_sdk.zip + rm -f "$discord_zip" + else + # Save build tag to skip this later. Doing it here (once everything is + # in place) is important to avoid potential issues with retried builds. + save_buildtag discord fi +else + echo [-] Not downloading Discord Game SDK again fi # Determine Discord Game SDK architecture. @@ -713,8 +788,9 @@ then sevenzip="$pf/7-Zip/7z.exe" [ "$arch" = "32" -a -d "/c/Program Files (x86)" ] && pf="/c/Program Files (x86)" - # Archive freetype from local MSYS installation. - .ci/static2dll.sh -p freetype2 /$MSYSTEM/lib/libfreetype.a archive_tmp/freetype.dll + # Archive freetype from cache or generate it from local MSYS installation. + [ ! -e "$freetype_dll" ] && .ci/static2dll.sh -p freetype2 /$MSYSTEM/lib/libfreetype.a "$freetype_dll" + cp -p "$freetype_dll" archive_tmp/freetype.dll # Archive Ghostscript DLL from local official distribution installation. for gs in "$pf"/gs/gs*.*.* @@ -723,7 +799,7 @@ then done # Archive Discord Game SDK DLL. - "$sevenzip" e -y -o"archive_tmp" discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.dll" + "$sevenzip" e -y -o"archive_tmp" "$discord_zip" "lib/$arch_discord/discord_game_sdk.dll" [ ! -e "archive_tmp/discord_game_sdk.dll" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] # Archive other DLLs from local directory. @@ -749,31 +825,29 @@ then if [ $status -eq 0 ] then # Archive Discord Game SDK library. - unzip -j discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.dylib" -d "archive_tmp/"*".app/Contents/Frameworks" + unzip -j "$discord_zip" "lib/$arch_discord/discord_game_sdk.dylib" -d "archive_tmp/"*".app/Contents/Frameworks" [ ! -e "archive_tmp/"*".app/Contents/Frameworks/discord_game_sdk.dylib" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] # Sign app bundle, unless we're in an universal build. [ $skip_archive -eq 0 ] && codesign --force --deep -s - "archive_tmp/"*".app" fi else - cwd_root=$(pwd) - cache_dir="$HOME/86box-build-cache" - [ ! -d "$cache_dir" ] && mkdir -p "$cache_dir" + cwd_root="$(pwd)" + check_buildtag "libs.$arch_deb" if grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt then # Build openal-soft 1.21.1 manually to fix audio issues. This is a temporary # workaround until a newer version of openal-soft trickles down to Debian repos. prefix="$cache_dir/openal-soft-1.21.1" - if [ -d "$prefix" ] + if [ ! -d "$prefix" ] then - rm -rf "$prefix/build" - else wget -qO - https://github.com/kcat/openal-soft/archive/refs/tags/1.21.1.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 - cmake --build "$prefix/build" -j$(nproc) || exit 99 - cmake --install "$prefix/build" || exit 99 + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 # Build SDL2 without sound systems. sdl_ss=OFF @@ -781,15 +855,14 @@ else # Build FAudio 22.03 manually to remove the dependency on GStreamer. This is a temporary # workaround until a newer version of FAudio trickles down to Debian repos. prefix="$cache_dir/FAudio-22.03" - if [ -d "$prefix" ] + if [ ! -d "$prefix" ] then - rm -rf "$prefix/build" - else wget -qO - https://github.com/FNA-XNA/FAudio/archive/refs/tags/22.03.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 - cmake --build "$prefix/build" -j$(nproc) || exit 99 - cmake --install "$prefix/build" || exit 99 + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 # Build SDL2 with sound systems. sdl_ss=ON @@ -801,15 +874,14 @@ else # Build rtmidi without JACK support to remove the dependency on libjack. prefix="$cache_dir/rtmidi-4.0.0" - if [ -d "$prefix" ] + if [ ! -d "$prefix" ] then - rm -rf "$prefix/build" - else wget -qO - https://github.com/thestk/rtmidi/archive/refs/tags/4.0.0.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - cmake -G Ninja -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix/build" || exit 99 - cmake --build "$prefix/build" -j$(nproc) || exit 99 - cmake --install "$prefix/build" || exit 99 + prefix_build="$prefix/build-$arch_deb" + cmake -G Ninja -D RTMIDI_API_JACK=OFF -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 # Build SDL2 for joystick and FAudio support, with most components # disabled to remove the dependencies on PulseAudio and libdrm. @@ -818,7 +890,7 @@ else then wget -qO - https://www.libsdl.org/release/SDL2-2.0.20.tar.gz | tar zxf - -C "$cache_dir" || rm -rf "$prefix" fi - rm -rf "$cache_dir/sdlbuild" + prefix_build="$cache_dir/SDL2-2.0.20-build-$arch_deb" cmake -G Ninja -D SDL_SHARED=ON -D SDL_STATIC=OFF \ \ -D SDL_AUDIO=$sdl_ss -D SDL_DUMMYAUDIO=$sdl_ss -D SDL_DISKAUDIO=OFF -D SDL_OSS=OFF -D SDL_ALSA=$sdl_ss -D SDL_ALSA_SHARED=$sdl_ss \ @@ -837,12 +909,12 @@ else -D SDL_LOADSO=ON -D SDL_CPUINFO=ON -D SDL_FILESYSTEM=$sdl_ui -D SDL_DLOPEN=OFF -D SDL_SENSOR=OFF -D SDL_LOCALE=OFF \ \ -D "CMAKE_TOOLCHAIN_FILE=$cwd_root/toolchain.cmake" -D "CMAKE_INSTALL_PREFIX=$cwd_root/archive_tmp/usr" \ - -S "$prefix" -B "$cache_dir/sdlbuild" || exit 99 - cmake --build "$cache_dir/sdlbuild" -j$(nproc) || exit 99 - cmake --install "$cache_dir/sdlbuild" || exit 99 + -S "$prefix" -B "$prefix_build" || exit 99 + cmake --build "$prefix_build" -j$(nproc) || exit 99 + cmake --install "$prefix_build" || exit 99 # Archive Discord Game SDK library. - 7z e -y -o"archive_tmp/usr/lib" discord_game_sdk.zip "lib/$arch_discord/discord_game_sdk.so" + 7z e -y -o"archive_tmp/usr/lib" "$discord_zip" "lib/$arch_discord/discord_game_sdk.so" [ ! -e "archive_tmp/usr/lib/discord_game_sdk.so" ] && echo [!] No Discord Game SDK for architecture [$arch_discord] # Archive readme with library package versions. diff --git a/.gitignore b/.gitignore index 5b1c5bbd1..267f3d766 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,6 @@ Makefile /archive_tmp /archive_tmp_universal /static2dll.* -/pacman.txt -/deps.txt -/universal_listing.txt /VERSION *.zip *.tar diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index 138349955..12b7e19a0 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -45,8 +45,6 @@ #define LOCK dev->lock #define UNLOCKED !dev->lock -#define ENABLE_WD76C10_LOG 1 - #ifdef ENABLE_WD76C10_LOG int wd76c10_do_log = ENABLE_WD76C10_LOG; static void diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index 50da6f2a0..7fde5dacc 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -259,7 +259,7 @@ static int opF6_a32(uint32_t fetchdat) static int opF7_w_a16(uint32_t fetchdat) { - uint32_t templ, templ2; + uint32_t templ, templ2 = 0; int tempws, tempws2 = 0; int16_t temps16; uint16_t src, dst; @@ -356,7 +356,7 @@ static int opF7_w_a16(uint32_t fetchdat) } static int opF7_w_a32(uint32_t fetchdat) { - uint32_t templ, templ2; + uint32_t templ, templ2 = 0; int tempws, tempws2 = 1; int16_t temps16; uint16_t src, dst; diff --git a/src/dma.c b/src/dma.c index c109f1b8d..5eb129860 100644 --- a/src/dma.c +++ b/src/dma.c @@ -62,6 +62,7 @@ static struct { #define DMA_PS2_IOA (1 << 0) +#define DMA_PS2_AUTOINIT (1 << 1) #define DMA_PS2_XFER_MEM_TO_IO (1 << 2) #define DMA_PS2_XFER_IO_TO_MEM (3 << 2) #define DMA_PS2_XFER_MASK (3 << 2) @@ -729,6 +730,8 @@ dma_ps2_write(uint16_t addr, uint8_t val, void *priv) else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) mode |= 4; dma_c->mode = (dma_c->mode & ~0x2c) | mode; + if (val & DMA_PS2_AUTOINIT) + dma_c->mode |= 0x10; dma_c->ps2_mode = val; dma_c->size = val & DMA_PS2_SIZE16; break; diff --git a/src/include/86box/net_wd8003.h b/src/include/86box/net_wd8003.h index 8fc89a88b..08bd901fe 100644 --- a/src/include/86box/net_wd8003.h +++ b/src/include/86box/net_wd8003.h @@ -50,7 +50,8 @@ enum { WD8003EB, /* WD8003EB : 8-bit ISA, 5x3 interface chip */ WD8013EBT, /* WD8013EBT : 16-bit ISA, no interface chip */ WD8003ETA, /* WD8003ET/A: 16-bit MCA, no interface chip */ - WD8003EA /* WD8003E/A : 16-bit MCA, 5x3 interface chip */ + WD8003EA, /* WD8003E/A : 16-bit MCA, 5x3 interface chip */ + WD8013EPA }; extern const device_t wd8003e_device; @@ -58,5 +59,6 @@ extern const device_t wd8003eb_device; extern const device_t wd8013ebt_device; extern const device_t wd8003eta_device; extern const device_t wd8003ea_device; +extern const device_t wd8013epa_device; #endif /*NET_WD8003_H*/ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 2696954ef..71d4942d0 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -120,6 +120,7 @@ extern const device_t sb_16_device; extern const device_t sb_16_pnp_device; extern const device_t sb_16_compat_device; extern const device_t sb_16_compat_nompu_device; +extern const device_t sb_16_reply_mca_device; extern const device_t sb_32_pnp_device; extern const device_t sb_awe32_device; extern const device_t sb_awe32_pnp_device; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 2c4a3bba9..6ece57fdf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4721,7 +4721,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO, + .flags = MACHINE_IDE_DUAL, /* No MACHINE_VIDEO yet, because on-board video is not yet implemented. */ .ram = { .min = 1024, .max = 32768, @@ -4756,7 +4756,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO, + .flags = MACHINE_IDE_DUAL, .ram = { .min = 1024, .max = 32768, diff --git a/src/mem/rom.c b/src/mem/rom.c index eb2b5791b..debdf5c39 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -646,7 +646,7 @@ rom_init_oddeven(rom_t *rom, char *fn, uint32_t addr, int sz, int mask, int off, addr, sz, rom_read, rom_readw, rom_readl, NULL, NULL, NULL, - rom->rom, flags | MEM_MAPPING_ROM, rom); + rom->rom, flags | MEM_MAPPING_ROM_WS, rom); return(0); } @@ -674,7 +674,7 @@ rom_init_interleaved(rom_t *rom, char *fnl, char *fnh, uint32_t addr, int sz, in addr, sz, rom_read, rom_readw, rom_readl, NULL, NULL, NULL, - rom->rom, flags | MEM_MAPPING_ROM, rom); + rom->rom, flags | MEM_MAPPING_ROM_WS, rom); return(0); } diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 81e6d91ec..81429fe19 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -540,7 +540,6 @@ wd_mca_read(int port, void *priv) #define MCA_6FC0_IRQS { 3, 4, 10, 15 } - static void wd_mca_write(int port, uint8_t val, void *priv) { @@ -582,6 +581,68 @@ wd_mca_write(int port, uint8_t val, void *priv) dev->base_address, dev->irq, dev->ram_addr); } +static void +wd_8013epa_mca_write(int port, uint8_t val, void *priv) +{ + wd_t *dev = (wd_t *)priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 7] = val; + + /* + * The PS/2 Model 80 BIOS always enables a card if it finds one, + * even if no resources were assigned yet (because we only added + * the card, but have not run AutoConfig yet...) + * + * So, remove current address, if any. + */ + if (dev->base_address) + wd_io_remove(dev, dev->base_address); + + dev->base_address = 0x800 + ((dev->pos_regs[2] & 0xf0) << 8); + + switch (dev->pos_regs[5] & 0x0c) { + case 0: + dev->irq = 3; + break; + case 4: + dev->irq = 4; + break; + case 8: + dev->irq = 10; + break; + case 0x0c: + dev->irq = 14; + break; + } + + if (dev->pos_regs[3] & 0x10) + dev->ram_size = 0x4000; + else + dev->ram_size = 0x2000; + + dev->ram_addr = ((dev->pos_regs[3] & 0x0f) << 13) + 0xc0000; + if (dev->pos_regs[3] & 0x80) + dev->ram_addr += 0xf00000; + + /* Initialize the device if fully configured. */ + /* Register (new) I/O handler. */ + if (dev->pos_regs[2] & 0x01) + wd_io_set(dev, dev->base_address); + + mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size); + + mem_mapping_disable(&dev->ram_mapping); + if ((dev->msr & WE_MSR_ENABLE_RAM) && (dev->pos_regs[2] & 0x01)) + mem_mapping_enable(&dev->ram_mapping); + + wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, + dev->base_address, dev->irq, dev->ram_addr); +} + static uint8_t wd_mca_feedb(void *priv) @@ -624,9 +685,12 @@ wd_init(const device_t *info) dev->maclocal[5] = (mac & 0xff); } - if ((dev->board == WD8003ETA) || (dev->board == WD8003EA)) - mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev); - else { + if ((dev->board == WD8003ETA) || (dev->board == WD8003EA) || dev->board == WD8013EPA) { + if (dev->board == WD8013EPA) + mca_add(wd_mca_read, wd_8013epa_mca_write, wd_mca_feedb, NULL, dev); + else + mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev); + } else { dev->base_address = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); dev->ram_addr = device_get_config_hex20("ram_addr"); @@ -679,12 +743,20 @@ wd_init(const device_t *info) dev->board_chip = WE_ID_SOFT_CONFIG; /* Ethernet, MCA, no interface chip, RAM 16k */ case WD8003ETA: - dev->board_chip |= 0x05 | WE_ID_BUS_MCA; + dev->board_chip |= WE_TYPE_WD8013EBT | WE_ID_BUS_MCA; dev->ram_size = 0x4000; dev->pos_regs[0] = 0xC0; dev->pos_regs[1] = 0x6F; dev->bit16 = 3; break; + + case WD8013EPA: + dev->board_chip = WE_TYPE_WD8013EP | WE_ID_BUS_MCA; + dev->ram_size = device_get_config_int("ram_size"); + dev->pos_regs[0] = 0xC8; + dev->pos_regs[1] = 0x61; + dev->bit16 = 3; + break; } dev->irr |= WE_IRR_ENABLE_IRQ; @@ -969,6 +1041,31 @@ static const device_config_t wd8013_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t wd8013epa_config[] = { + { + .name = "ram_size", + .description = "Initial RAM size", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 16384, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "8 kB", .value = 8192 }, + { .description = "16 kB", .value = 16384 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t mca_mac_config[] = { { .name = "mac", @@ -1050,3 +1147,17 @@ const device_t wd8003ea_device = { .force_redraw = NULL, .config = mca_mac_config }; + +const device_t wd8013epa_device = { + .name = "Western Digital WD8013EP/A", + .internal_name = "wd8013epa", + .flags = DEVICE_MCA, + .local = WD8013EPA, + .init = wd_init, + .close = wd_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = wd8013epa_config +}; diff --git a/src/network/network.c b/src/network/network.c index 49915024a..6a7fbdfa5 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -103,6 +103,7 @@ static netcard_t net_cards[] = { { ðernext_mc_device, NULL }, { &wd8003eta_device, NULL }, { &wd8003ea_device, NULL }, + { &wd8013epa_device, NULL }, { &pcnet_am79c973_device, NULL }, { &pcnet_am79c970a_device, NULL }, { &rtl8029as_device, NULL }, diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index b9d0e40e9..0cb4560c4 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -178,6 +178,7 @@ endif() if(WIN32) enable_language(RC) target_sources(86Box PUBLIC ../win/86Box-qt.rc) + target_sources(plat PRIVATE win_dynld.c) target_sources(plat PRIVATE win_joystick_rawinput.c) target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) target_link_libraries(86Box hid d3d9) diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 7d1eecb09..b7f325a9a 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -116,7 +116,7 @@ msgid "VGA screen &type" msgstr "&Tipo de tela VGA" msgid "RGB &Color" -msgstr "&Cor RGB" +msgstr "&Cores RGB" msgid "&RGB Grayscale" msgstr "Tons de cinza &RGB" @@ -347,13 +347,13 @@ msgid "Time synchronization" msgstr "Sincronização da hora" msgid "Disabled" -msgstr "Desativada" +msgstr "Desativar" msgid "Enabled (local time)" -msgstr "Ativada (hora local)" +msgstr "Ativar (hora local)" msgid "Enabled (UTC)" -msgstr "Ativada (UTC)" +msgstr "Ativar (UTC)" msgid "Dynamic Recompiler" msgstr "Recompilador dinâmico" @@ -386,10 +386,10 @@ msgid "Sound card:" msgstr "Placa de som:" msgid "MIDI Out Device:" -msgstr "Disp. saída MIDI:" +msgstr "Disp. de saída MIDI:" msgid "MIDI In Device:" -msgstr "Disp. entrada MIDI:" +msgstr "Disp. de entrada MIDI:" msgid "Standalone MPU-401" msgstr "MPU-401 autônomo" @@ -506,7 +506,7 @@ msgid "&Remove" msgstr "&Remover" msgid "Bus:" -msgstr "Bar.:" +msgstr "Barramento:" msgid "Channel:" msgstr "Canal:" @@ -536,7 +536,7 @@ msgid "Image Format:" msgstr "Formato:" msgid "Block Size:" -msgstr "Bloco:" +msgstr "Blocos:" msgid "Floppy drives:" msgstr "Unidades de disquete:" @@ -599,7 +599,7 @@ msgid "Fatal error" msgstr "Erro fatal" msgid " - PAUSED" -msgstr " - PAUSED" +msgstr " - PAUSADO" msgid "Press Ctrl+Alt+PgDn to return to windowed mode." msgstr "Use Ctrl+Alt+PgDn para retornar ao modo janela" @@ -749,7 +749,7 @@ msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" -msgstr "Thrustmaster Flight Control System" +msgstr "Sistema de Controle de Voo Thrustmaster" msgid "None" msgstr "Nada" @@ -821,7 +821,7 @@ msgid "About 86Box" msgstr "Sobre o 86Box" msgid "86Box v" -msgstr "86Box versão" +msgstr "86Box versão " msgid "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." msgstr "Um emulador de computadores antigos\n\nAutores: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, Tiseno100, reenigne, leilei, JohnElliott, greatpsycho, e outros.\n\nTraduzido por: Altieres Lima da Silva\n\nLançado sob a Licença Pública Geral GNU versão 2 ou posterior. Veja o arquivo LICENSE para mais informações." diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 91f76d900..89ead7acd 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -54,6 +54,7 @@ QElapsedTimer elapsed_timer; static std::atomic_int blitmx_contention = 0; static std::recursive_mutex blitmx; +static thread_local std::unique_lock blit_lock { blitmx, std::defer_lock }; class CharPointer { public: @@ -431,6 +432,7 @@ void plat_language_code_r(uint32_t lcid, char* outbuf, int len) { return; } +#ifndef Q_OS_WINDOWS void* dynld_module(const char *name, dllimp_t *table) { QString libraryName = name; @@ -462,21 +464,22 @@ void dynld_close(void *handle) { delete reinterpret_cast(handle); } +#endif void startblit() { blitmx_contention++; - if (blitmx.try_lock()) { + if (blit_lock.try_lock()) { return; } - blitmx.lock(); + blit_lock.lock(); } void endblit() { blitmx_contention--; - blitmx.unlock(); + blit_lock.unlock(); if (blitmx_contention > 0) { // a deadlock has been observed on linux when toggling via video_toggle_option // because the mutex is typically unfair on linux diff --git a/src/qt/win_dynld.c b/src/qt/win_dynld.c new file mode 100644 index 000000000..98eb4739f --- /dev/null +++ b/src/qt/win_dynld.c @@ -0,0 +1,87 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Try to load a support DLL. + * + * + * + * Author: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/plat_dynld.h> + + +#ifdef ENABLE_DYNLD_LOG +int dynld_do_log = ENABLE_DYNLD_LOG; + + +static void +dynld_log(const char *fmt, ...) +{ + va_list ap; + + if (dynld_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define dynld_log(fmt, ...) +#endif + + +void * +dynld_module(const char *name, dllimp_t *table) +{ + HMODULE h; + dllimp_t *imp; + void *func; + + /* See if we can load the desired module. */ + if ((h = LoadLibrary(name)) == NULL) { + dynld_log("DynLd(\"%s\"): library not found! (%08X)\n", name, GetLastError()); + return(NULL); + } + + /* Now load the desired function pointers. */ + for (imp=table; imp->name!=NULL; imp++) { + func = GetProcAddress(h, imp->name); + if (func == NULL) { + dynld_log("DynLd(\"%s\"): function '%s' not found! (%08X)\n", + name, imp->name, GetLastError()); + FreeLibrary(h); + return(NULL); + } + + /* To overcome typing issues.. */ + *(char **)imp->func = (char *)func; + } + + /* All good. */ + dynld_log("loaded %s\n", name); + return((void *)h); +} + + +void +dynld_close(void *handle) +{ + if (handle != NULL) + FreeLibrary((HMODULE)handle); +} diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 0e504065b..a15174b45 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -20,6 +20,7 @@ typedef struct adgold_t { int adgold_irq_status; + int irq, dma, hdma; uint8_t adgold_eeprom[0x1a]; @@ -157,7 +158,7 @@ adgold_update_irq_status(adgold_t *adgold) adgold->adgold_status = temp; if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status) { - picint(0x80); + picint(1 << adgold->irq); } adgold->adgold_irq_status = adgold->adgold_status ^ 0xf; @@ -167,23 +168,26 @@ void adgold_getsamp_dma(adgold_t *adgold, int channel) { int temp; + dma_set_drq(adgold->dma, 1); if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127)) return; - temp = dma_channel_read(1); - if (temp == DMA_NODATA) + temp = dma_channel_read(adgold->dma); + if (temp == DMA_NODATA) { return; + } adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp; - adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; + adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; if (adgold->adgold_mma_regs[channel][0xc] & 0x60) { - temp = dma_channel_read(1); + temp = dma_channel_read(adgold->dma); adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp; - adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; + adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255; } if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= adgold->adgold_mma_intpos[channel]) { adgold->adgold_mma_status &= ~(0x01 << channel); adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } } @@ -335,10 +339,11 @@ adgold_write(uint16_t addr, uint8_t val, void *p) break; /* 7350 Hz*/ } if (val & 0x80) { - adgold->adgold_mma_enable[0] = 0; + adgold->adgold_mma_enable[0] = 0; adgold->adgold_mma_fifo_end[0] = adgold->adgold_mma_fifo_start[0] = 0; adgold->adgold_mma_status &= ~0x01; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } if ((val & 0x01)) /*Start playback*/ { @@ -347,7 +352,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p) if (adgold->adgold_mma_regs[0][0xc] & 1) { if (adgold->adgold_mma_regs[0][0xc] & 0x80) { - adgold->adgold_mma_enable[1] = 1; + adgold->adgold_mma_enable[1] = 1; adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1]; while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { @@ -357,10 +362,12 @@ adgold_write(uint16_t addr, uint8_t val, void *p) if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { adgold->adgold_mma_status &= ~0x01; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) { adgold->adgold_mma_status &= ~0x02; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } } else { while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { @@ -369,6 +376,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p) if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { adgold->adgold_mma_status &= ~0x01; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } } } @@ -379,10 +387,11 @@ adgold_write(uint16_t addr, uint8_t val, void *p) case 0xb: if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) { adgold->adgold_mma_fifo[0][adgold->adgold_mma_fifo_end[0]] = val; - adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255; + adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255; if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) { adgold->adgold_mma_status &= ~0x01; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } } break; @@ -457,6 +466,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p) adgold->adgold_mma_fifo_end[1] = adgold->adgold_mma_fifo_start[1] = 0; adgold->adgold_mma_status &= ~0x02; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } if ((val & 0x01)) /*Start playback*/ { @@ -479,6 +489,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p) if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) { adgold->adgold_mma_status &= ~0x02; adgold_update_irq_status(adgold); + dma_set_drq(adgold->dma, 0); } } break; @@ -525,6 +536,7 @@ adgold_read(uint16_t addr, void *p) default: temp = adgold->adgold_38x_regs[adgold->adgold_38x_addr]; + break; } } else temp = adgold->opl.read(addr, adgold->opl.priv); @@ -877,8 +889,9 @@ adgold_init(const device_t *info) adgold_t *adgold = malloc(sizeof(adgold_t)); memset(adgold, 0, sizeof(adgold_t)); + adgold->dma = device_get_config_int("dma"); + adgold->irq = device_get_config_int("irq"); adgold->surround_enabled = device_get_config_int("surround"); - adgold->gameport_enabled = device_get_config_int("gameport"); fm_driver_get(FM_YMF262, &adgold->opl); @@ -912,9 +925,9 @@ adgold_init(const device_t *info) adgold->adgold_eeprom[0x10] = 0xff; adgold->adgold_eeprom[0x11] = 0x20; adgold->adgold_eeprom[0x12] = 0x00; - adgold->adgold_eeprom[0x13] = 0x0b; /* IRQ 1, DMA1 */ - adgold->adgold_eeprom[0x14] = 0x00; /* DMA2 */ - adgold->adgold_eeprom[0x15] = 0x71; /* Port */ + adgold->adgold_eeprom[0x13] = 0xa0; + adgold->adgold_eeprom[0x14] = 0x00; + adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/ adgold->adgold_eeprom[0x16] = 0x00; adgold->adgold_eeprom[0x17] = 0x68; adgold->adgold_eeprom[0x18] = 0x00; /* Surround */ @@ -927,25 +940,36 @@ adgold_init(const device_t *info) fclose(f); } - adgold->adgold_status = 0xf; - adgold->adgold_38x_addr = 0; - adgold->adgold_eeprom[0x13] = 3 | (1 << 3); /*IRQ 7, DMA 1*/ - // adgold->adgold_eeprom[0x14] = 3 << 4; /*DMA 3 - Double check this */ - adgold->adgold_eeprom[0x14] = 0x00; /*DMA ?*/ - adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/ + adgold->adgold_status = 0xf; + adgold->adgold_38x_addr = 0; + switch (adgold->irq) { + case 3: + adgold->adgold_eeprom[0x13] |= 0x00; + break; + case 4: + adgold->adgold_eeprom[0x13] |= 0x01; + break; + case 5: + adgold->adgold_eeprom[0x13] |= 0x02; + break; + case 7: + adgold->adgold_eeprom[0x13] |= 0x03; + break; + } + adgold->adgold_eeprom[0x13] |= (adgold->dma << 3); memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x19); - adgold->vol_l = attenuation[adgold->adgold_eeprom[0x04] & 0x3f]; - adgold->vol_r = attenuation[adgold->adgold_eeprom[0x05] & 0x3f]; - adgold->bass = adgold->adgold_eeprom[0x06] & 0xf; - adgold->treble = adgold->adgold_eeprom[0x07] & 0xf; - adgold->fm_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x09] - 128); - adgold->fm_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0a] - 128); + adgold->vol_l = attenuation[adgold->adgold_eeprom[0x04] & 0x3f]; + adgold->vol_r = attenuation[adgold->adgold_eeprom[0x05] & 0x3f]; + adgold->bass = adgold->adgold_eeprom[0x06] & 0xf; + adgold->treble = adgold->adgold_eeprom[0x07] & 0xf; + adgold->fm_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x09] - 128); + adgold->fm_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0a] - 128); adgold->samp_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0b] - 128); adgold->samp_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0c] - 128); adgold->aux_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0d] - 128); adgold->aux_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0e] - 128); - adgold->adgold_mma_enable[0] = 0; + adgold->adgold_mma_enable[0] = 0; adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0; /*388/389 are handled by adlib_init*/ @@ -982,6 +1006,54 @@ adgold_close(void *p) static const device_config_t adgold_config[] = { // clang-format off + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "IRQ 3", + .value = 3 + }, + { + .description = "IRQ 4", + .value = 4 + }, + { + .description = "IRQ 5", + .value = 5 + }, + { + .description = "IRQ 7", + .value = 7 + }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "Low DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 1, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "DMA 1", + .value = 1 + }, + { + .description = "DMA 3", + .value = 3 + }, + { .description = "" } + } + }, { .name = "gameport", .description = "Enable Game port", diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 75c59e11e..e1546acdc 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1201,6 +1201,151 @@ sb_pro_mcv_write(int port, uint8_t val, void *p) sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } +static uint8_t +sb_16_reply_mca_read(int port, void *p) +{ + sb_t *sb = (sb_t *) p; + uint8_t ret = sb->pos_regs[port & 7]; + + sb_log("sb_16_reply_mca_read: port=%04x ret=%02x\n", port, ret); + + return ret; +} + +static void +sb_16_reply_mca_write(int port, uint8_t val, void *p) +{ + uint16_t addr, mpu401_addr; + int low_dma, high_dma; + sb_t *sb = (sb_t *) p; + + if (port < 0x102) + return; + + sb_log("sb_16_reply_mca_write: port=%04x val=%02x\n", port, val); + + switch (sb->pos_regs[2] & 0xc4) { + case 4: + addr = 0x220; + break; + case 0x44: + addr = 0x240; + break; + case 0x84: + addr = 0x260; + break; + case 0xc4: + addr = 0x280; + break; + case 0: + default: + addr = 0; + break; + } + + if (addr) { + io_removehandler(addr, 0x0004, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, + &sb->opl); + io_removehandler(addr + 8, 0x0002, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, + &sb->opl); + io_removehandler(0x0388, 0x0004, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, + &sb->opl); + io_removehandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, 0); + mpu401_change_addr(sb->mpu, 0); + gameport_remap(sb->gameport, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) { + switch (sb->pos_regs[2] & 0xc4) { + case 4: + addr = 0x220; + break; + case 0x44: + addr = 0x240; + break; + case 0x84: + addr = 0x260; + break; + case 0xc4: + addr = 0x280; + break; + case 0: + default: + addr = 0; + break; + } + switch (sb->pos_regs[2] & 0x18) { + case 8: + mpu401_addr = 0x330; + break; + case 0x18: + mpu401_addr = 0x300; + break; + case 0: + default: + mpu401_addr = 0; + break; + } + + if (addr) { + io_sethandler(addr, 0x0004, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, + &sb->opl); + io_sethandler(addr + 8, 0x0002, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, + &sb->opl); + io_sethandler(0x0388, 0x0004, + opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 4, 0x0002, + sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, + sb); + } + + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); + mpu401_change_addr(sb->mpu, mpu401_addr); + gameport_remap(sb->gameport, (sb->pos_regs[2] & 0x20) ? 0x200 : 0); + } + + switch (sb->pos_regs[4] & 0x60) { + case 0x20: + sb_dsp_setirq(&sb->dsp, 5); + break; + case 0x40: + sb_dsp_setirq(&sb->dsp, 7); + break; + case 0x60: + sb_dsp_setirq(&sb->dsp, 10); + break; + } + + low_dma = sb->pos_regs[3] & 3; + high_dma = (sb->pos_regs[3] >> 4) & 7; + if (!high_dma) + high_dma = low_dma; + + sb_dsp_setdma8(&sb->dsp, low_dma); + sb_dsp_setdma16(&sb->dsp, high_dma); +} + static void sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { @@ -1788,6 +1933,41 @@ sb_16_init(const device_t *info) return sb; } +static void * +sb_16_reply_mca_init(const device_t *info) +{ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0x00, sizeof(sb_t)); + + sb->opl_enabled = 1; + opl3_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_ct1745_mixer_reset(sb); + + sb->mixer_enabled = 1; + sb->mixer_sb16.output_filter = 1; + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + sb->gameport = gameport_add(&gameport_device); + + /* I/O handlers activated in sb_pro_mcv_write */ + mca_add(sb_16_reply_mca_read, sb_16_reply_mca_write, sb_mcv_feedb, NULL, sb); + sb->pos_regs[0] = 0x38; + sb->pos_regs[1] = 0x51; + + return sb; +} + static void * sb_16_pnp_init(const device_t *info) { @@ -3374,6 +3554,20 @@ const device_t sb_16_device = { .config = sb_16_config }; +const device_t sb_16_reply_mca_device = { + .name = "Sound Blaster 16 Reply MCA", + .internal_name = "sb16_reply_mca", + .flags = DEVICE_MCA, + .local = 0, + .init = sb_16_reply_mca_init, + .close = sb_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = sb_speed_changed, + .force_redraw = NULL, + .config = sb_16_pnp_config +}; + const device_t sb_16_pnp_device = { .name = "Sound Blaster 16 PnP", .internal_name = "sb16_pnp", diff --git a/src/sound/sound.c b/src/sound/sound.c index ec9e51f91..604dac38f 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -140,6 +140,7 @@ static const SOUND_CARD sound_cards[] = { { &ncr_business_audio_device }, { &sb_mcv_device }, { &sb_pro_mcv_device }, + { &sb_16_reply_mca_device }, { &cmi8338_device }, { &cmi8738_device }, { &es1371_device }, diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 59b9f2247..3ca44746c 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -77,6 +77,64 @@ static video_timings_t timing_paradise_wd90c = {VIDEO_ISA, 3, 3, 6, 5, 5, 1 void paradise_remap(paradise_t *paradise); +uint8_t paradise_in(uint16_t addr, void *p) +{ + paradise_t *paradise = (paradise_t *)p; + svga_t *svga = ¶dise->svga; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3c5: + if (svga->seqaddr > 7) + { + if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) + return 0xff; + if (svga->seqaddr > 0x12) + return 0xff; + return svga->seqregs[svga->seqaddr & 0x1f]; + } + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (paradise->type == WD90C30) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); + + case 0x3cf: + if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { + if (svga->gdcreg[0x0f] & 0x10) + return 0xff; + } + switch (svga->gdcaddr) { + case 0x0b: + if (paradise->type == WD90C30) { + if (paradise->vram_mask == ((512 << 10) - 1)) { + svga->gdcreg[0x0b] |= 0xc0; + svga->gdcreg[0x0b] &= ~0x40; + } + } + return svga->gdcreg[0x0b]; + + case 0x0f: + return (svga->gdcreg[0x0f] & 0x17) | 0x80; + } + break; + + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return 0xff; + if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) + return 0xff; + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); +} + void paradise_out(uint16_t addr, uint8_t val, void *p) { paradise_t *paradise = (paradise_t *)p; @@ -187,69 +245,21 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) } } break; + + case 0x46e8: + io_removehandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + mem_mapping_disable(¶dise->svga.mapping); + if (val & 8) + { + io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); + mem_mapping_enable(¶dise->svga.mapping); + } + break; } svga_out(addr, val, svga); } -uint8_t paradise_in(uint16_t addr, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - svga_t *svga = ¶dise->svga; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c5: - if (svga->seqaddr > 7) - { - if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) - return 0xff; - if (svga->seqaddr > 0x12) - return 0xff; - return svga->seqregs[svga->seqaddr & 0x1f]; - } - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (paradise->type == WD90C30) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); - - case 0x3cf: - if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { - if (svga->gdcreg[0x0f] & 0x10) - return 0xff; - } - switch (svga->gdcaddr) { - case 0x0b: - if (paradise->type == WD90C30) { - if (paradise->vram_mask == ((512 << 10) - 1)) { - svga->gdcreg[0x0b] |= 0xc0; - svga->gdcreg[0x0b] &= ~0x40; - } - } - return svga->gdcreg[0x0b]; - - case 0x0f: - return (svga->gdcreg[0x0f] & 0x17) | 0x80; - } - break; - - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) - return 0xff; - if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) - return 0xff; - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); -} - void paradise_remap(paradise_t *paradise) { svga_t *svga = ¶dise->svga; @@ -579,6 +589,7 @@ void *paradise_init(const device_t *info, uint32_t memsize) case WD90C11: svga->crtc[0x36] = '1'; svga->crtc[0x37] = '1'; + io_sethandler(0x46e8, 0x0001, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); break; case WD90C30: svga->crtc[0x36] = '3'; diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index 81b2e290a..5e23a9d71 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -80,7 +80,7 @@ BEGIN MENUITEM "Monitor VGA &invertido", IDM_VID_INVERT POPUP "&Tipo de tela VGA" BEGIN - MENUITEM "&Cor RGB", IDM_VID_GRAY_RGB + MENUITEM "&Cores RGB", IDM_VID_GRAY_RGB MENUITEM "Tons de cinza &RGB", IDM_VID_GRAY_MONO MENUITEM "Monitor &âmbar", IDM_VID_GRAY_AMBER MENUITEM "Monitor &verde", IDM_VID_GRAY_GREEN @@ -267,15 +267,15 @@ END #define STR_MB "MB" #define STR_MEMORY "Memória:" #define STR_TIME_SYNC "Sincronização da hora" -#define STR_DISABLED "Desativada" -#define STR_ENABLED_LOCAL "Ativada (hora local)" -#define STR_ENABLED_UTC "Ativada (UTC)" +#define STR_DISABLED "Desativar" +#define STR_ENABLED_LOCAL "Ativar (hora local)" +#define STR_ENABLED_UTC "Ativar (UTC)" #define STR_DYNAREC "Recompilador dinâmico" #define STR_VIDEO "Vídeo:" #define STR_VOODOO "3DFX Voodoo" -#define STR_IBM8514 "IBM 8514/a Graphics" -#define STR_XGA "XGA Graphics" +#define STR_IBM8514 "Gráficos IBM 8514/a" +#define STR_XGA "Gráficos XGA" #define STR_MOUSE "Mouse:" #define STR_JOYSTICK "Joystick:" @@ -340,7 +340,7 @@ END #define STR_SIZE_MB "Tamanho (MB):" #define STR_TYPE "Tipo:" #define STR_IMG_FORMAT "Formato:" -#define STR_BLOCK_SIZE "Bloco:" +#define STR_BLOCK_SIZE "Blocos:" #define STR_FLOPPY_DRIVES "Unidades de disquete:" #define STR_TURBO "Turbo" @@ -376,7 +376,7 @@ BEGIN 2048 "86Box" IDS_2049 "Erro" IDS_2050 "Erro fatal" - IDS_2051 " - PAUSED" + IDS_2051 " - PAUSADO" IDS_2052 "Use Ctrl+Alt+PgDn para retornar ao modo janela" IDS_2053 "Velocidade" IDS_2054 "ZIP %03i %i (%s): %ls" @@ -435,7 +435,7 @@ BEGIN IDS_2099 "Joystick padrão de 8 botões" IDS_2100 "CH Flightstick Pro" IDS_2101 "Microsoft SideWinder Pad" - IDS_2102 "Thrustmaster Flight Control System" + IDS_2102 "Sistema de Controle de Voo Thrustmaster" IDS_2103 "Nada" IDS_2104 "Não foi possível carregar os aceleradores do teclado." IDS_2105 "Não foi possível registrar a entrada bruta."