Merge branch 'master'

This commit is contained in:
MaxwellS04
2025-08-25 04:11:49 +07:00
454 changed files with 82675 additions and 29321 deletions

View File

@@ -96,3 +96,4 @@ AppDir:
AppImage:
arch: !ENV '${arch_appimage}'
file_name: !ENV '${appimage_path}'
comp: gzip

View File

@@ -48,6 +48,13 @@
# architecture when invoking build.sh (either standalone or as part of an universal build)
# - port and sed are called through sudo to manage dependencies; make sure those are configured
# as NOPASSWD in /etc/sudoers if you're doing unattended builds
# - Binaries are ad-hoc signed by default; specify a keychain name in ~/86box-keychain-name.txt
# and password in ~/86box-keychain-password.txt to sign binaries with the first developer
# certificate found inside that keychain.
# - Notarization uses credentials stored in the same keychain used for signing. To save these
# credentials, you must find the keychain's file path, run notarytool store-credentials with
# --keychain pointed at that path, and specify the profile name you passed to notarytool in
# ~/86box-keychain-notarytool.txt
#
# Define common functions.
@@ -126,6 +133,70 @@ save_buildtag() {
return $?
}
mac_keychain() {
keychain_name=$(cat ~/86box-keychain-name.txt)
if [ -n "$keychain_name" ]
then
echo $keychain_name
security list-keychains -d user -s $(security list-keychains -d user | grep -Fv "/$keychain_name" | sed -e s/\ \*\"//g) "$keychain_name"
security unlock-keychain -p "$(cat ~/86box-keychain-password.txt)" "$keychain_name"
return $?
fi
}
mac_signidentity() {
if keychain_name=$(mac_keychain)
then
if [ -n "$keychain_name" ]
then
cert_name=$(security find-identity -v -p codesigning "$keychain_name" | perl -nle 'print for /([0-9A-F]+) "Developer ID Application: /')
if [ -n "$cert_name" ]
then
echo [-] Using signing certificate [$cert_name] in keychain [$keychain_name] >&2
echo "--keychain $keychain_name -s $cert_name"
return 0
else
err="Keychain [$keychain_name] has no developer certificate"
fi
else
err="No keychain specified"
fi
else
err="Keychain [$keychain_name] failed to unlock"
fi
echo [!] $err, falling back to ad-hoc signing >&2
echo "-s -"
}
mac_notarize() {
if keychain_name=$(mac_keychain)
then
if [ -n "$keychain_name" ]
then
keychain_profile=$(cat ~/86box-keychain-notarytool.txt)
if [ -n "$keychain_profile" ]
then
keychain_path=$(security list-keychains -d user | grep -F "/$keychain_name" | sed -e s/\ \*\"//g)
if [ -n "$keychain_path" ]
then
echo [-] Notarizing with profile [$keychain_profile] in keychain [$keychain_name]
# FIXME: needs a stapling system
xcrun notarytool submit "$1" --keychain-profile "$keychain_profile" --keychain "$keychain_path" --no-wait
return $?
else
err="File path for keychain [$keychain_name] not found"
fi
else
err="No keychain profile specified"
fi
else
err="No keychain specified"
fi
else
err="Keychain [$keychain_name] failed to unlock"
fi
echo [!] $err, skipping notarization
return 1
}
# Set common variables.
project=86Box
cwd=$(pwd)
@@ -472,12 +543,13 @@ then
mv "archive_tmp_universal/$merge_src.app" "$app_bundle_name"
# Sign final app bundle.
arch -"$(uname -m)" codesign --force --deep -s - "$app_bundle_name"
arch -"$(uname -m)" codesign --force --deep $(mac_signidentity) -o runtime --entitlements src/mac/entitlements.plist --timestamp "$app_bundle_name"
# Create zip.
echo [-] Creating artifact archive
cd archive_tmp
zip --symlinks -r "$cwd/$package_name.zip" .
zip_name="$cwd/$package_name.zip"
zip --symlinks -r "$zip_name" .
status=$?
# Check if the archival succeeded.
@@ -487,6 +559,9 @@ then
exit 7
fi
# Notarize the compressed app bundle.
mac_notarize "$zip_name"
# All good.
echo [-] Universal build of [$package_name] for [$arch] with flags [$cmake_flags] successful
exit 0
@@ -603,7 +678,7 @@ else
grep -q " bullseye " /etc/apt/sources.list || echo [!] WARNING: System not running the expected Debian version
# Establish general dependencies.
pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream qttranslations5-l10n"
pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream qttranslations5-l10n python3-pip python3-venv squashfs-tools"
if [ "$(dpkg --print-architecture)" = "$arch_deb" ]
then
pkgs="$pkgs build-essential"
@@ -905,7 +980,7 @@ then
fi
# Sign app bundle, unless we're in an universal build.
[ $skip_archive -eq 0 ] && codesign --force --deep -s - "archive_tmp/"*".app"
[ $skip_archive -eq 0 ] && codesign --force --deep $(mac_signidentity) -o runtime --entitlements src/mac/entitlements.plist --timestamp "archive_tmp/"*".app"
elif [ "$BUILD_TAG" = "precondition" ]
then
# Continue with no app bundle on a dry build.
@@ -1104,7 +1179,8 @@ elif is_mac
then
# Create zip.
cd archive_tmp
zip --symlinks -r "$cwd/$package_name.zip" .
zip_name="$cwd/$package_name.zip"
zip --symlinks -r "$zip_name" .
status=$?
else
# Determine AppImage runtime architecture.
@@ -1141,55 +1217,32 @@ EOF
# Copy line.
echo "$line" >> AppImageBuilder-generated.yml
# Workaround for appimage-builder issues 272 and 283 (i686 and armhf are also missing)
if [ "$arch_appimage" != "x86_64" -a "$line" = " files:" ]
then
# Some mild arbitrary code execution with a dummy package...
[ ! -d /runtime ] && sudo apt-get -y -o 'DPkg::Post-Invoke::=mkdir -p /runtime; chmod 777 /runtime' install libsixel1 > /dev/null 2>&1
echo " include:" >> AppImageBuilder-generated.yml
for loader in "/lib/$libdir/ld-linux"*.so.*
do
for loader_copy in "$loader" "/lib/$(basename "$loader")"
do
if [ ! -e "/runtime/compat$loader_copy" ]
then
mkdir -p "/runtime/compat$(dirname "$loader_copy")"
ln -s "$loader" "/runtime/compat$loader_copy"
fi
echo " - /runtime/compat$loader_copy" >> AppImageBuilder-generated.yml
done
done
fi
done < .ci/AppImageBuilder.yml
# Download appimage-builder if necessary.
appimage_builder_url="https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-$(uname -m).AppImage"
appimage_builder_binary="$cache_dir/$(basename "$appimage_builder_url")"
if [ ! -e "$appimage_builder_binary" ]
appimage_builder_commit=22fefa298f9cee922a651a6f65a46fe0ccbfa34e # from issue 376
appimage_builder_dir="$cache_dir/appimage-builder-$appimage_builder_commit"
if [ ! -x "$appimage_builder_dir/bin/appimage-builder" ]
then
rm -rf "$cache_dir/"*".AppImage" # remove old versions
wget -qO "$appimage_builder_binary" "$appimage_builder_url"
rm -rf "$cache_dir/appimage-builder-"* # remove old versions
python3 -m venv "$appimage_builder_dir" # venv to solve some Debian setuptools headaches
"$appimage_builder_dir/bin/pip" install -U "git+https://github.com/AppImageCrafters/appimage-builder.git@$appimage_builder_commit"
fi
# Symlink appimage-builder binary and global cache directory.
# Symlink appimage-builder global cache directory.
rm -rf appimage-builder.AppImage appimage-builder-cache "$project-"*".AppImage" # also remove any dangling AppImages which may interfere with the renaming process
ln -s "$appimage_builder_binary" appimage-builder.AppImage
chmod u+x appimage-builder.AppImage
mkdir -p "$cache_dir/appimage-builder-cache"
ln -s "$cache_dir/appimage-builder-cache" appimage-builder-cache
# Run appimage-builder in extract-and-run mode for Docker compatibility.
# Run appimage-builder from the virtual environment created above.
# --appdir is a workaround for appimage-builder issue 270 reported by us.
for retry in 1 2 3 4 5
do
project="$project" project_id="$project_id" project_version="$project_version" project_icon="$project_icon" arch_deb="$arch_deb" \
arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage \
arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" "$appimage_builder_dir/bin/appimage-builder" \
--recipe AppImageBuilder-generated.yml --appdir "$(grep -oP '^\s+path: \K(.+)' AppImageBuilder-generated.yml)"
status=$?
[ $status -eq 0 ] && break
[ $status -eq 127 ] && rm -rf /tmp/appimage_extracted_*
done
# Remove appimage-builder binary on failure, just in case it's corrupted.
@@ -1203,6 +1256,9 @@ then
exit 7
fi
# Notarize the compressed app bundle if we're on macOS.
is_mac && mac_notarize "$zip_name"
# All good.
echo [-] Build of [$package_name] for [$arch] with flags [$cmake_flags] successful
exit 0

View File

@@ -3,9 +3,7 @@ name: CMake (Linux)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -17,6 +15,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -57,10 +56,12 @@ jobs:
ui:
- name: SDL GUI
qt: off
qt6: off
static: on
- name: Qt GUI
- name: Qt 5 GUI
qt: on
slug: -Qt
qt6: off
slug: -Qt5
packages: >-
qtbase5-dev
qtbase5-private-dev
@@ -68,6 +69,20 @@ jobs:
qttranslations5-l10n
libevdev-dev
libxkbcommon-x11-dev
- name: Qt 6 GUI
qt: on
qt6: on
slug: -Qt6
packages: >-
qt6-base-dev
qt6-base-private-dev
qt6-tools-dev
qt6-tools-dev-tools
qt6-l10n-tools
qt6-translations-l10n
libevdev-dev
libxkbcommon-x11-dev
libvulkan-dev
environment:
- arch: x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
@@ -113,6 +128,7 @@ jobs:
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D QT=${{ matrix.ui.qt }}
-D USE_QT6=${{ matrix.ui.qt6 }}
- name: Build
run: |

View File

@@ -3,9 +3,7 @@ name: CMake (macos)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -17,6 +15,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "main" ]
paths:
- src/**
- cmake/**

View File

@@ -3,9 +3,7 @@ name: CMake (Windows, msys2)
on:
push:
branches:
- main
branches: [ "main" ]
paths:
- src/**
- cmake/**
@@ -17,6 +15,7 @@ on:
- "!**/Makefile*"
pull_request:
branches: [ "msin" ]
paths:
- src/**
- cmake/**

View File

@@ -36,7 +36,7 @@ if(MUNT_EXTERNAL)
endif()
project(86Box
VERSION 5.0
VERSION 5.0.1
DESCRIPTION "Emulator of x86-based systems"
HOMEPAGE_URL "https://86box.net"
LANGUAGES C CXX)
@@ -184,6 +184,7 @@ cmake_dependent_option(PCL "Generic PCL5e Printer"
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
cmake_dependent_option(WACOM "Wacom Input Devices" ON "DEV_BRANCH" OFF)
cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
cmake_dependent_option(NETSWITCH "Network Switch Support" ON "DEV_BRANCH" OFF)
# Ditto but for Qt
if(QT)
@@ -221,7 +222,7 @@ if(NOT EMU_BUILD_NUM)
set(EMU_BUILD_NUM 0)
endif()
if(NOT EMU_COPYRIGHT_YEAR)
set(EMU_COPYRIGHT_YEAR 2024)
set(EMU_COPYRIGHT_YEAR 2025)
endif()
# Libasan
@@ -230,4 +231,6 @@ if(LIBASAN)
add_link_options(-fsanitize=address)
endif()
set(CMAKE_TOP_LEVEL_PROCESSED TRUE)
add_subdirectory(src)

4
debian/changelog vendored
View File

@@ -1,5 +1,5 @@
86box (5.0) UNRELEASED; urgency=medium
86box (5.0.1) UNRELEASED; urgency=medium
* Bump release.
-- Jasmine Iwanek <jriwanek@gmail.com> Wed, 16 Apr 2025 22:08:04 +0200
-- Jasmine Iwanek <jriwanek@gmail.com> Sun, 24 Aug 2025 15:20:01 +0200

View File

@@ -88,7 +88,7 @@
#include <86box/scsi_device.h>
#include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/mo.h>
#include <86box/scsi_disk.h>
#include <86box/cdrom_image.h>
@@ -161,7 +161,7 @@ int window_remember;
int vid_resize; /* (C) allow resizing */
int invert_display = 0; /* (C) invert the display */
int suppress_overscan = 0; /* (C) suppress overscans */
int lang_id = 0; /* (C) language id */
int lang_id = 0; /* (G) language id */
int scale = 0; /* (C) screen scale factor */
int dpi_scale = 0; /* (C) DPI scaling of the emulated
screen */
@@ -199,24 +199,28 @@ int cpu = 0; /* (C) cpu typ
int fpu_type = 0; /* (C) fpu type */
int fpu_softfloat = 0; /* (C) fpu uses softfloat */
int time_sync = 0; /* (C) enable time sync */
int confirm_reset = 1; /* (C) enable reset confirmation */
int confirm_exit = 1; /* (C) enable exit confirmation */
int confirm_save = 1; /* (C) enable save confirmation */
int confirm_reset = 1; /* (G) enable reset confirmation */
int confirm_exit = 1; /* (G) enable exit confirmation */
int confirm_save = 1; /* (G) enable save confirmation */
int enable_discord = 0; /* (C) enable Discord integration */
int pit_mode = -1; /* (C) force setting PIT mode */
int fm_driver = 0; /* (C) select FM sound driver */
int open_dir_usr_path = 0; /* (C) default file open dialog directory
int open_dir_usr_path = 0; /* (G) default file open dialog directory
of usr_path */
int video_fullscreen_scale_maximized = 0; /* (C) Whether fullscreen scaling settings
also apply when maximized. */
int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus
loss */
int force_constant_mouse = 0; /* (C) Force constant updating of the mouse */
int hook_enabled = 1; /* (C) Keyboard hook is enabled */
int test_mode = 0; /* (C) Test mode */
char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */
int sound_muted = 0; /* (C) Is sound muted? */
int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */
int jumpered_internal_ecp_dma = 0; /* (C) Jumpered internal EPC DMA */
int inhibit_multimedia_keys; /* (G) Inhibit multimedia keys on Windows. */
int force_10ms; /* (C) Force 10ms CPU frame intervals. */
int vmm_disabled = 0; /* (G) disable built-in manager */
char vmm_path_cfg[1024] = { '\0' }; /* (G) VMs path (unless -E is used)*/
int other_ide_present = 0; /* IDE controllers from non-IDE cards are
present */
@@ -230,33 +234,50 @@ struct accelKey acc_keys[NUM_ACCELS];
// Default accelerator key values
struct accelKey def_acc_keys[NUM_ACCELS] = {
{ .name="send_ctrl_alt_del", .desc="Send Control+Alt+Del",
.seq="Ctrl+F12" },
{ .name="send_ctrl_alt_esc", .desc="Send Control+Alt+Escape",
.seq="Ctrl+F10" },
{ .name="fullscreen", .desc="Toggle fullscreen",
.seq="Ctrl+Alt+PgUp" },
{ .name="screenshot", .desc="Screenshot",
.seq="Ctrl+F11" },
{ .name="release_mouse", .desc="Release mouse pointer",
.seq="Ctrl+End" },
{ .name="hard_reset", .desc="Hard reset",
.seq="Ctrl+Alt+F12" },
{ .name="pause", .desc="Toggle pause",
.seq="Ctrl+Alt+F1" },
{ .name="mute", .desc="Toggle mute",
.seq="Ctrl+Alt+M" }
{
.name="send_ctrl_alt_del",
.desc="Send Control+Alt+Del",
.seq="Ctrl+F12"
},
{
.name="send_ctrl_alt_esc",
.desc="Send Control+Alt+Escape",
.seq="Ctrl+F10"
},
{
.name="fullscreen",
.desc="Toggle fullscreen",
.seq="Ctrl+Alt+PgUp"
},
{
.name="screenshot",
.desc="Screenshot",
.seq="Ctrl+F11"
},
{
.name="release_mouse",
.desc="Release mouse pointer",
.seq="Ctrl+End"
},
{
.name="hard_reset",
.desc="Hard reset",
.seq="Ctrl+Alt+F12"
},
{
.name="pause",
.desc="Toggle pause",
.seq="Ctrl+Alt+F1"
},
{
.name="mute",
.desc="Toggle mute",
.seq="Ctrl+Alt+M"
}
};
char vmm_path[1024] = { '\0'}; /* TEMPORARY - VM manager path to scan for VMs */
int vmm_enabled = 0;
char vmm_path[1024] = { '\0' }; /* VM manager path to scan for VMs */
int start_vmm = 1;
/* Statistics. */
extern int mmuflush;
@@ -276,6 +297,7 @@ extern double exp_pow_table[0x800];
char exe_path[2048]; /* path (dir) of executable */
char usr_path[1024]; /* path (dir) of user data */
char cfg_path[1024]; /* full path of config file */
char global_cfg_path[1024]; /* full path of config file */
FILE *stdlog = NULL; /* file to log output to */
#if 0
int scrnsz_x = SCREEN_RES_X; /* current screen size, X */
@@ -299,9 +321,9 @@ static wchar_t mouse_msg[3][200];
static volatile atomic_int do_pause_ack = 0;
static volatile atomic_int pause_ack = 0;
#ifndef RELEASE_BUILD
#define LOG_SIZE_BUFFER 8192 /* Log size buffer */
#define LOG_SIZE_BUFFER 1024 /* Log size buffer */
#ifndef RELEASE_BUILD
static char buff[LOG_SIZE_BUFFER];
@@ -313,7 +335,7 @@ static int suppr_seen = 1;
void pclog_ensure_stdlog_open(void);
#endif
/*
/*
Ensures STDLOG is open for pclog_ex and pclog_ex_cyclic
*/
void pclog_ensure_stdlog_open(void)
@@ -363,8 +385,6 @@ pclog_ex(UNUSED(const char *fmt), UNUSED(va_list ap))
#endif
}
void
pclog_toggle_suppr(void)
{
@@ -386,11 +406,35 @@ pclog(UNUSED(const char *fmt), ...)
#endif
}
/* Log something even in release builds. */
void
always_log(const char *fmt, ...)
{
char temp[LOG_SIZE_BUFFER];
va_list ap;
va_start(ap, fmt);
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
va_end(ap);
}
/* Log a fatal error, and display a UI message before exiting. */
void
fatal(const char *fmt, ...)
{
char temp[1024];
char temp[LOG_SIZE_BUFFER];
va_list ap;
char *sp;
@@ -438,7 +482,7 @@ fatal(const char *fmt, ...)
void
fatal_ex(const char *fmt, va_list ap)
{
char temp[1024];
char temp[LOG_SIZE_BUFFER];
char *sp;
if (stdlog == NULL) {
@@ -481,7 +525,7 @@ fatal_ex(const char *fmt, va_list ap)
void
warning(const char *fmt, ...)
{
char temp[1024];
char temp[LOG_SIZE_BUFFER];
va_list ap;
char *sp;
@@ -517,7 +561,7 @@ warning(const char *fmt, ...)
void
warning_ex(const char *fmt, va_list ap)
{
char temp[1024];
char temp[LOG_SIZE_BUFFER];
char *sp;
if (stdlog == NULL) {
@@ -594,54 +638,65 @@ extern void device_find_all_descs(void);
static void
pc_show_usage(char *s)
{
char p[4096] = { 0 };
char p[8192] = { 0 };
sprintf(p,
"\n%sUsage: 86box [options] [cfg-file]\n\n"
"Valid options are:\n\n"
"-? or --help\t\t\t- show this information\n"
#ifdef SHOW_EXTRA_PARAMS
"-C or --config path\t\t- set 'path' to be config file\n"
#endif
#ifdef _WIN32
"-D or --debug\t\t\t- force debug output logging\n"
#endif
#if 1
#ifndef USE_SDL_UI
"-E or --vmmpath\t\t- vm manager path\n"
#endif
"-F or --fullscreen\t\t- start in fullscreen mode\n"
"-G or --lang langid\t\t- start with specified language\n"
"\t\t\t\t (e.g. en-US, or system)\n"
#ifdef SHOW_EXTRA_PARAMS
#ifdef _WIN32
"-H or --hwnd id,hwnd\t\t- sends back the main dialog's hwnd\n"
#endif
#endif
"-I or --image d:path\t\t- load 'path' as floppy image on drive d\n"
#ifdef USE_INSTRUMENT
"-J or --instrument name\t- set 'name' to be the profiling instrument\n"
#endif
"-L or --logfile pat\t\t- set 'path' to be the logfile\n"
"-L or --logfile path\t\t- set 'path' to be the logfile\n"
"-M or --missing\t\t- dump missing machines and video cards\n"
"-N or --noconfirm\t\t- do not ask for confirmation on quit\n"
"-P or --vmpath path\t\t- set 'path' to be root for vm\n"
"-O or --global path\t\t- set 'path' to be global config file\n"
"-R or --rompath path\t\t- set 'path' to be ROM path\n"
#ifndef USE_SDL_UI
"-S or --settings\t\t\t- show only the settings dialog\n"
#endif
#ifdef SHOW_EXTRA_PARAMS
"-T or --testmode\t\t- test mode: execute the test mode entry\n"
"\t\t\t\t point on init/hard reset\n"
#endif
"-V or --vmname name\t\t- overrides the name of the running VM\n"
#ifdef _WIN32
"-W or --nohook\t\t- disables keyboard hook\n"
"\t\t\t\t (compatibility-only outside Windows)\n"
#else
"-W or --nohook\t\t- alters keyboard behavior\n"
#endif
"-X or --clear what\t\t- clears the 'what' (cmos/flash/both)\n"
#ifdef SHOW_EXTRA_PARAMS
"-Y or --donothing\t\t- do not show any UI or run the emulation\n"
"-Z or --lastvmpath\t\t- the last parameter is VM path rather\n"
"\t\t\t\t than config\n"
#endif
"-Z or --lastvmpath\t\t- the last param. is VM path rather than config\n"
"\nA config file can be specified. If none is, the default file will be used.\n",
(s == NULL) ? "" : s);
s);
#ifdef _WIN32
ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p);
#else
if (s == NULL)
pclog("%s", p);
always_log("%s", p);
else
ui_msgbox(MBX_ANSI | MBX_WARNING, p);
#endif
@@ -660,6 +715,7 @@ pc_init(int argc, char *argv[])
char *ppath = NULL;
char *rpath = NULL;
char *cfg = NULL;
char *global = NULL;
char *p;
char temp[2048];
char *fn[FDD_NUM] = { NULL };
@@ -670,9 +726,6 @@ pc_init(int argc, char *argv[])
time_t now;
int c;
int lvmp = 0;
#ifdef DEPRECATE_USAGE
int deprecated = 1;
#endif
#ifdef ENABLE_NG
int ng = 0;
#endif
@@ -693,10 +746,6 @@ pc_init(int argc, char *argv[])
p = path_get_filename(exe_path);
*p = '\0';
}
if (!strncmp(exe_path, "/private/var/folders/", 21)) {
ui_msgbox_header(MBX_FATAL, L"App Translocation", EMU_NAME_W L" cannot determine the emulated machine's location due to a macOS security feature. Please move the " EMU_NAME_W L" app to another folder (not /Applications), or make a copy of it and open that copy instead.");
return 0;
}
#elif !defined(_WIN32)
/* Grab the actual path if we are an AppImage. */
p = getenv("APPIMAGE");
@@ -730,7 +779,7 @@ usage:
}
}
pc_show_usage(NULL);
pc_show_usage("");
return 0;
} else if (!strcasecmp(argv[c], "--lastvmpath") || !strcasecmp(argv[c], "-Z")) {
lvmp = 1;
@@ -738,7 +787,7 @@ usage:
} else if (!strcasecmp(argv[c], "--debug") || !strcasecmp(argv[c], "-D")) {
force_debug = 1;
#endif
//#ifdef ENABLE_NG
#ifndef USE_SDL_UI
} else if (!strcasecmp(argv[c], "--vmmpath") ||
!strcasecmp(argv[c], "-E")) {
/* Using this variable for vm manager path
@@ -749,7 +798,7 @@ usage:
memcpy(vmm_path, vp, sizeof(vmm_path));
else
memcpy(vmm_path, vp, strlen(vp) + 1);
//#endif
#endif
} else if (!strcasecmp(argv[c], "--fullscreen") || !strcasecmp(argv[c], "-F")) {
start_in_fullscreen = 1;
} else if (!strcasecmp(argv[c], "--logfile") || !strcasecmp(argv[c], "-L")) {
@@ -762,9 +811,7 @@ usage:
goto usage;
ppath = argv[++c];
#ifdef DEPRECATE_USAGE
deprecated = 0;
#endif
start_vmm = 0;
} else if (!strcasecmp(argv[c], "--rompath") || !strcasecmp(argv[c], "-R")) {
if ((c + 1) == argc)
goto usage;
@@ -776,9 +823,12 @@ usage:
goto usage;
cfg = argv[++c];
#ifdef DEPRECATE_USAGE
deprecated = 0;
#endif
start_vmm = 0;
} else if (!strcasecmp(argv[c], "--global") || !strcasecmp(argv[c], "-O")) {
if ((c + 1) == argc || plat_dir_check(argv[c + 1]))
goto usage;
global = argv[++c];
} else if (!strcasecmp(argv[c], "--image") || !strcasecmp(argv[c], "-I")) {
if ((c + 1) == argc)
goto usage;
@@ -851,7 +901,7 @@ usage:
lang_init = plat_language_code(argv[++c]);
if (!lang_init)
printf("\nWarning: Invalid language code, ignoring --lang parameter.\n\n");
always_log("\nWarning: Invalid language code, ignoring --lang parameter.\n\n");
// The return value of 0 only means that the code is invalid,
// not related to that translation is exists or not for the
@@ -882,21 +932,12 @@ usage:
else
cfg = argv[c++];
#ifdef DEPRECATE_USAGE
deprecated = 0;
#endif
start_vmm = 0;
}
if (c != argc)
goto usage;
#ifdef DEPRECATE_USAGE
if (deprecated)
pc_show_usage("Running 86Box without a specified VM path and/or configuration\n"
"file has been deprected. Please specify one or use a manager\n"
"(Avalonia 86 is recommended).\n\n");
#endif
path_slash(usr_path);
path_slash(rom_path);
@@ -1010,6 +1051,14 @@ usage:
/* At this point, we can safely create the full path name. */
path_append_filename(cfg_path, usr_path, p);
/* Build the global configuration file path. */
if (global == NULL) {
plat_get_global_config_dir(global_cfg_path, sizeof(global_cfg_path));
path_append_filename(global_cfg_path, global_cfg_path, GLOBAL_CONFIG_FILE);
} else {
strncpy(global_cfg_path, global, sizeof(global_cfg_path) - 1);
}
/*
* Get the current directory's name
*
@@ -1033,6 +1082,8 @@ usage:
#ifdef _WIN32
if (localtime_s(&time_buf, &now) == 0)
info = &time_buf;
else
info = NULL;
#else
info = localtime_r(&now, &time_buf);
#endif
@@ -1044,59 +1095,92 @@ usage:
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);
pclog("# Emulator path: %s\n", exe_path);
pclog("# Userfiles path: %s\n", usr_path);
for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) {
pclog("# ROM path: %s\n", rom_path->path);
pclog("# Global configuration file: %s\n", global_cfg_path);
/* Load the global configuration file. */
config_load_global();
config_save_global(); // hack
/* Determine whether to start the VM manager. */
#ifndef USE_SDL_UI
if (vmm_disabled && start_vmm)
#endif
{
start_vmm = 0;
#ifdef __APPLE__
if (!strncmp(exe_path, "/private/var/folders/", 21)) {
ui_msgbox_header(MBX_FATAL, L"App Translocation", EMU_NAME_W L" cannot determine the emulated machine's location due to a macOS security feature. Please move the " EMU_NAME_W L" app to another folder (not /Applications), or make a copy of it and open that copy instead.");
return 0;
}
#endif
}
pclog("# Configuration file: %s\n#\n\n", cfg_path);
#ifndef USE_SDL_UI
if (strlen(vmm_path) != 0) {
vmm_enabled = 1;
/* -E specified on the command line. */
start_vmm = 1;
} else {
strncpy(vmm_path, vmm_path_cfg, sizeof(vmm_path) - 1);
}
if (start_vmm) {
pclog("# VM Manager enabled. Path: %s\n", vmm_path);
}
/*
* We are about to read the configuration file, which MAY
* put data into global variables (the hard- and floppy
* disks are an example) so we have to initialize those
* modules before we load the config..
*/
hdd_init();
network_init();
mouse_init();
cdrom_global_init();
zip_global_init();
mo_global_init();
strncpy(usr_path, vmm_path, sizeof(usr_path) - 1);
} else
#endif
{
pclog("# VM: %s\n#\n", vm_name);
pclog("# Configuration file: %s\n#\n\n", cfg_path);
pclog("# Userfiles path: %s\n", usr_path);
/* Initialize the keyboard accelerator list with default values */
for (int x = 0; x < NUM_ACCELS; x++) {
strcpy(acc_keys[x].name, def_acc_keys[x].name);
strcpy(acc_keys[x].desc, def_acc_keys[x].desc);
strcpy(acc_keys[x].seq, def_acc_keys[x].seq);
}
for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) {
pclog("# ROM path: %s\n", rom_path->path);
}
/* Load the configuration file. */
config_load();
/*
* We are about to read the configuration file, which MAY
* put data into global variables (the hard- and floppy
* disks are an example) so we have to initialize those
* modules before we load the config..
*/
hdd_init();
network_init();
mouse_init();
cdrom_global_init();
rdisk_global_init();
mo_global_init();
/* Clear the CMOS and/or BIOS flash file, if we were started with
the relevant parameter(s). */
if (clear_cmos) {
delete_nvr_file(0);
clear_cmos = 0;
}
/* Initialize the keyboard accelerator list with default values */
for (int x = 0; x < NUM_ACCELS; x++) {
strcpy(acc_keys[x].name, def_acc_keys[x].name);
strcpy(acc_keys[x].desc, def_acc_keys[x].desc);
strcpy(acc_keys[x].seq, def_acc_keys[x].seq);
}
if (clear_flash) {
delete_nvr_file(1);
clear_flash = 0;
}
/* Load the configuration file. */
config_load();
for (uint8_t i = 0; i < FDD_NUM; i++) {
if (fn[i] != NULL) {
if (strlen(fn[i]) <= 511)
strncpy(floppyfns[i], fn[i], 511);
free(fn[i]);
fn[i] = NULL;
/* Clear the CMOS and/or BIOS flash file, if we were started with
the relevant parameter(s). */
if (clear_cmos) {
delete_nvr_file(0);
clear_cmos = 0;
}
if (clear_flash) {
delete_nvr_file(1);
clear_flash = 0;
}
for (uint8_t i = 0; i < FDD_NUM; i++) {
if (fn[i] != NULL) {
if (strlen(fn[i]) <= 511)
strncpy(floppyfns[i], fn[i], 511);
free(fn[i]);
fn[i] = NULL;
}
}
}
@@ -1131,11 +1215,10 @@ pc_full_speed(void)
/* Initialize modules, ran once, after pc_init. */
int
pc_init_modules(void)
pc_init_roms(void)
{
int c;
int m;
wchar_t temp[512];
char tempc[512];
if (dump_missing) {
@@ -1174,6 +1257,16 @@ pc_init_modules(void)
}
pc_log("A total of %d ROM sets have been loaded.\n", c);
return 1;
}
int
pc_init_modules(void)
{
int c;
wchar_t temp[512];
char tempc[512];
/* Load the ROMs for the selected machine. */
if (!machine_available(machine)) {
swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_MACHINE), machine_getname());
@@ -1262,6 +1355,11 @@ pc_init_modules(void)
machine_status_init();
serial_set_next_inst(0);
lpt_set_3bc_used(0);
lpt_set_next_inst(0);
for (c = 0; c <= 0x7ff; c++) {
int64_t exp = c - 1023; /* 1023 = BIAS64 */
exp_pow_table[c] = pow(2.0, (double) exp);
@@ -1376,10 +1474,6 @@ pc_reset_hard_close(void)
lpt_devices_close();
#ifdef UNCOMMENT_LATER
lpt_close();
#endif
nvr_save();
nvr_close();
@@ -1395,7 +1489,7 @@ pc_reset_hard_close(void)
cdrom_close();
zip_close();
rdisk_close();
mo_close();
@@ -1408,6 +1502,9 @@ pc_reset_hard_close(void)
cpu_close();
serial_set_next_inst(0);
lpt_set_3bc_used(0);
lpt_set_next_inst(0);
}
/*
@@ -1446,6 +1543,8 @@ pc_reset_hard_init(void)
scsi_reset();
scsi_device_init();
ide_hard_reset();
/* Initialize the actual machine and its basic modules. */
machine_init();
@@ -1467,6 +1566,7 @@ pc_reset_hard_init(void)
/* Initialize parallel devices. */
/* note: PLIP LPT side has to be initialized before the network side */
lpt_standalone_init();
lpt_devices_init();
/* Reset and reconfigure the serial ports. */
@@ -1489,9 +1589,6 @@ pc_reset_hard_init(void)
fdd_reset();
/* Reset the CD-ROM Controller module. */
cdrom_interface_reset();
/* Reset and reconfigure the SCSI layer. */
scsi_card_init();
@@ -1499,9 +1596,12 @@ pc_reset_hard_init(void)
cdrom_hard_reset();
/* Reset the CD-ROM Controller module. */
cdrom_interface_reset();
mo_hard_reset();
zip_hard_reset();
rdisk_hard_reset();
/* Reset any ISA ROM cards. */
@@ -1514,8 +1614,9 @@ pc_reset_hard_init(void)
the chances of the SCSI controller ending up on the bridge. */
video_voodoo_init();
if (joystick_type)
gameport_update_joystick_type(); /* installs game port if no device provides one, must be late */
/* installs first game port if no device provides one, must be late */
if (joystick_type[0])
gameport_update_joystick_type(0);
ui_sb_update_panes();
@@ -1664,7 +1765,7 @@ pc_close(UNUSED(thread_t *ptr))
cdrom_close();
zip_close();
rdisk_close();
mo_close();
@@ -1723,7 +1824,7 @@ pc_run(void)
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
}
#endif
joystick_process();
joystick_process(0); // Gameport 0
endblit();
/* Done with this frame, update statistics. */
@@ -1928,13 +2029,11 @@ do_pause(int p)
// Helper to find an accelerator key and return it's index in acc_keys
int FindAccelerator(const char *name) {
for(int x=0;x<NUM_ACCELS;x++)
{
if(strcmp(acc_keys[x].name, name) == 0)
{
return(x);
}
}
// No key was found
return -1;
for (int x = 0; x < NUM_ACCELS; x++) {
if(strcmp(acc_keys[x].name, name) == 0)
return(x);
}
// No key was found
return -1;
}

View File

@@ -16,6 +16,10 @@
# Copyright 2024 Jasmine Iwanek.
#
if(NOT CMAKE_TOP_LEVEL_PROCESSED)
message(FATAL_ERROR "Incorrect source directory specified. Delete your build directory and retry with the top-level directory instead")
endif()
if(APPLE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
@@ -99,7 +103,7 @@ if(INSTRUMENT)
add_compile_definitions(USE_INSTRUMENT)
endif()
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom rdisk mo hdd
net print scsi sio snd utils vid voodoo plat ui)
if(HAIKU)
@@ -149,16 +153,6 @@ if(APPLE)
target_link_libraries(86Box Freetype::Freetype)
endif()
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
if(STATIC_BUILD AND TARGET SDL2::SDL2-static)
target_link_libraries(86Box SDL2::SDL2-static)
elseif(TARGET SDL2::SDL2)
target_link_libraries(86Box SDL2::SDL2)
else()
target_link_libraries(86Box ${SDL2_LIBRARIES})
endif()
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)

View File

@@ -2373,26 +2373,32 @@ acpi_reset(void *priv)
dev->regs.gporeg[i] = dev->gporeg_default[i];
if (dev->vendor == VEN_VIA_596B) {
dev->regs.gpo_val = 0x7fffffff;
/* FIC VA-503A:
- Bit 11: ATX power (active high)
- Bit 4: 80-conductor cable on primary IDE channel (active low)
- Bit 3: 80-conductor cable on secondary IDE channel (active low)
- Bit 2: password cleared (active low)
ASUS P3V4X:
- Bit 15: 80-conductor cable on secondary IDE channel (active low)
- Bit 5: 80-conductor cable on primary IDE channel (active low)
BCM GT694VA:
- Bit 19: 80-conductor cable on secondary IDE channel (active low)
- Bit 17: 80-conductor cable on primary IDE channel (active low)
ASUS CUV4X-LS:
- Bit 2: 80-conductor cable on secondary IDE channel (active low)
- Bit 1: 80-conductor cable on primary IDE channel (active low)
Acorp 6VIA90AP:
- Bit 3: 80-conductor cable on secondary IDE channel (active low)
- Bit 1: 80-conductor cable on primary IDE channel (active low) */
/*
- FIC VA-503A:
- Bit 11: ATX power (active high);
- Bit 4: 80-conductor cable on primary IDE channel (active low);
- Bit 3: 80-conductor cable on secondary IDE channel (active low);
- Bit 2: password cleared (active low).
- ASUS P3V4X:
- Bit 15: 80-conductor cable on secondary IDE channel (active low);
- Bit 5: 80-conductor cable on primary IDE channel (active low).
- BCM GT694VA:
- Bit 19: 80-conductor cable on secondary IDE channel (active low);
- Bit 17: 80-conductor cable on primary IDE channel (active low).
- ASUS CUV4X-LS:
- Bit 2: 80-conductor cable on secondary IDE channel (active low);
- Bit 1: 80-conductor cable on primary IDE channel (active low).
- Acorp 6VIA90AP:
- Bit 3: 80-conductor cable on secondary IDE channel (active low);
- Bit 1: 80-conductor cable on primary IDE channel (active low).
- FIC KA-6130:
- Bit 19: password cleared (active low).
*/
dev->regs.gpi_val = 0xfff57fc1;
if (!strcmp(machine_get_internal_name(), "ficva503a") || !strcmp(machine_get_internal_name(), "6via90ap"))
dev->regs.gpi_val |= 0x00000004;
else if (!strcmp(machine_get_internal_name(), "ficka6130"))
dev->regs.gpi_val |= 0x00080000;
/*
TriGem Delhi-III second GPI word:
- Bit 7 = Save CMOS (must be set);

View File

@@ -23,7 +23,11 @@ add_library(cdrom OBJECT
cdrom.c
cdrom_image.c
cdrom_image_viso.c
cdrom_mke.c
)
if(NOT WIN32)
target_include_directories(86Box PRIVATE PkgConfig::SNDFILE)
endif()
target_link_libraries(86Box PkgConfig::SNDFILE)
if(CDROM_MITSUMI)

View File

@@ -32,6 +32,7 @@
#ifdef USE_CDROM_MITSUMI
#include <86box/cdrom_mitsumi.h>
#endif
#include <86box/cdrom_mke.h>
#include <86box/log.h>
#include <86box/plat.h>
#include <86box/plat_cdrom_ioctl.h>
@@ -121,8 +122,10 @@ static const struct {
// clang-format off
{ &cdrom_interface_none_device },
#ifdef USE_CDROM_MITSUMI
{ &mitsumi_cdrom_device },
{ &mitsumi_cdrom_device },
#endif
{ &mke_cdrom_noncreative_device },
{ &mke_cdrom_device },
{ NULL }
// clang-format on
};
@@ -292,10 +295,80 @@ msf_to_bcd(int *m, int *s, int *f)
*f = bin2bcd(*f);
}
static int
read_data(cdrom_t *dev, const uint32_t lba)
void
cdrom_compute_ecc_block(cdrom_t *dev, uint8_t *parity, const uint8_t *data,
uint32_t major_count, uint32_t minor_count,
uint32_t major_mult, uint32_t minor_inc, int m2f1)
{
int ret = 1;
uint32_t size = major_count * minor_count;
for (uint32_t major = 0; major < major_count; ++major) {
uint32_t index = (major >> 1) * major_mult + (major & 1);
uint8_t ecc_a = 0;
uint8_t ecc_b = 0;
for (uint32_t minor = 0; minor < minor_count; ++minor) {
uint8_t temp = data[index];
if (m2f1 && (index < 4))
temp = 0x00;
index += minor_inc;
if (index >= size)
index -= size;
ecc_a ^= temp;
ecc_b ^= temp;
ecc_a = dev->_F_LUT[ecc_a];
}
parity[major] = dev->_B_LUT[dev->_F_LUT[ecc_a] ^ ecc_b];
parity[major + major_count] = parity[major] ^ ecc_b;
}
}
static void
cdrom_generate_ecc_data(cdrom_t *dev, const uint8_t *data, int m2f1)
{
/* Compute ECC P code. */
cdrom_compute_ecc_block(dev, dev->p_parity, data, 86, 24, 2, 86, m2f1);
/* Compute ECC Q code. */
cdrom_compute_ecc_block(dev, dev->q_parity, data, 52, 43, 86, 88, m2f1);
}
static int
cdrom_is_sector_good(cdrom_t *dev, const uint8_t *b, const uint8_t mode2, const uint8_t form)
{
int ret = 1;
if (!mode2 || (form != 1)) {
if (mode2 && (form == 1)) {
const uint32_t crc = cdrom_crc32(0xffffffff, &(b[16]), 2056) ^ 0xffffffff;
ret = ret && (crc == (*(uint32_t *) &(b[2072])));
} else if (!mode2) {
const uint32_t crc = cdrom_crc32(0xffffffff, b, 2064) ^ 0xffffffff;
ret = ret && (crc == (*(uint32_t *) &(b[2064])));
}
cdrom_generate_ecc_data(dev, &(b[12]), mode2 && (form == 1));
ret = ret && !memcmp(dev->p_parity, &(b[2076]), 172);
ret = ret && !memcmp(dev->q_parity, &(b[2248]), 104);
}
return ret;
}
static int
read_data(cdrom_t *dev, const uint32_t lba, int check)
{
int ret = 1;
int form = 0;
if (dev->cached_sector != lba) {
dev->cached_sector = lba;
@@ -303,6 +376,25 @@ read_data(cdrom_t *dev, const uint32_t lba)
ret = dev->ops->read_sector(dev->local,
dev->raw_buffer[dev->cur_buf ^ 1], lba);
if ((ret > 0) && check) {
if (dev->mode2) {
if (dev->raw_buffer[dev->cur_buf ^ 1][0x000f] == 0x01)
/*
Use Mode 1, since evidently specification-violating
discs exist.
*/
dev->mode2 = 0;
else if (dev->raw_buffer[dev->cur_buf ^ 1][0x0012] ==
dev->raw_buffer[dev->cur_buf ^ 1][0x0016])
form = ((dev->raw_buffer[dev->cur_buf ^ 1][0x0012] &
0x20) >> 5) + 1;
} else if (dev->raw_buffer[dev->cur_buf ^ 1][0x000f] == 0x02)
dev->mode2 = 1;
if (!cdrom_is_sector_good(dev, dev->raw_buffer[dev->cur_buf ^ 1], dev->mode2, form))
ret = -1;
}
if (ret <= 0) {
memset(dev->raw_buffer[dev->cur_buf ^ 1], 0x00, 2448);
dev->cached_sector = -1;
@@ -322,7 +414,7 @@ cdrom_get_subchannel(cdrom_t *dev, const uint32_t lba,
if (lba != dev->cached_sector)
dev->cached_sector = -1;
(void) read_data(dev, lba);
(void) read_data(dev, lba, 0);
for (int i = 0; i < 12; i++)
for (int j = 0; j < 8; j++)
@@ -679,7 +771,7 @@ track_type_is_valid(UNUSED(const cdrom_t *dev), const int type, const int flags,
static int
read_audio(cdrom_t *dev, const uint32_t lba, uint8_t *b)
{
const int ret = read_data(dev, lba);
const int ret = read_data(dev, lba, 0);
memcpy(b, dev->raw_buffer[dev->cur_buf], 2352);
@@ -1100,6 +1192,12 @@ cdrom_is_early(const int type)
return (cdrom_drive_types[type].scsi_std == 1);
}
int
cdrom_is_dvd(const int type)
{
return (cdrom_drive_types[type].is_dvd == 1);
}
int
cdrom_is_generic(const int type)
{
@@ -1151,6 +1249,26 @@ cdrom_get_type_count(void)
return count;
}
void
cdrom_generate_name_mke(const int type, char *name)
{
char elements[2][512] = { 0 };
memcpy(elements[0], cdrom_drive_types[type].model,
strlen(cdrom_drive_types[type].model) + 1);
char *s = strstr(elements[0], " ");
if (s != NULL)
s[0] = 0x00;
memcpy(elements[1], cdrom_drive_types[type].revision,
strlen(cdrom_drive_types[type].revision) + 1);
s = strstr(elements[1], " ");
if (s != NULL)
s[0] = 0x00;
sprintf(name, "%s%s", elements[0], elements[1]);
}
void
cdrom_get_identify_model(const int type, char *name, const int id)
{
@@ -1589,7 +1707,7 @@ cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos,
dev->seek_pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
else {
cdrom_log(dev->log, "Unable to get the starting position for "
"track %08X\n", ismsf & 0xff);
"track %08X\n", pos2 & 0xff);
cdrom_stop(dev);
}
break;
@@ -1707,7 +1825,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type)
dev->cd_end = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
else {
cdrom_log(dev->log, "Unable to get the starting position for "
"track %08X\n", ismsf & 0xff);
"track %08X\n", pos2 & 0xff);
cdrom_stop(dev);
}
break;
@@ -1740,7 +1858,7 @@ cdrom_audio_scan(cdrom_t *dev, const uint32_t pos)
uint8_t ret = 0;
if (dev->cd_status & CD_STATUS_HAS_AUDIO) {
cdrom_log(dev->log, "Audio Scan: MSF = %06x, type = %02x\n", pos, type);
cdrom_log(dev->log, "Audio Scan: MSF = %06x\n", pos);
if (pos == 0xffffffff) {
cdrom_log(dev->log, "(Type 0) Search from current position\n");
@@ -2009,9 +2127,10 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
cdrom_get_current_subcodeq(dev, b);
switch (dev->cd_status) {
default: case CD_STATUS_EMPTY:
case CD_STATUS_DATA_ONLY: case CD_STATUS_DVD:
case CD_STATUS_STOPPED: case CD_STATUS_PLAYING_COMPLETED:
default: case CD_STATUS_EMPTY:
case CD_STATUS_DATA_ONLY: case CD_STATUS_DVD:
case CD_STATUS_STOPPED: case CD_STATUS_PLAYING_COMPLETED:
case CD_STATUS_DVD_REJECTED:
ret = 0x03;
break;
case CD_STATUS_HOLD:
@@ -2360,7 +2479,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
ecc_diff = 0;
}
if (dev->cd_status != CD_STATUS_EMPTY) {
if ((dev->cd_status != CD_STATUS_EMPTY) && (dev->cd_status != CD_STATUS_DVD_REJECTED)) {
uint8_t *temp_b;
uint8_t *b = temp_b = buffer;
int audio = 0;
@@ -2379,6 +2498,8 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
if (dm != CD_TRACK_NORMAL)
mode2 = 1;
dev->mode2 = mode2;
memset(dev->extra_buffer, 0, 296);
if ((cdrom_sector_flags & 0xf8) == 0x08) {
@@ -2405,7 +2526,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
else
ret = read_audio(dev, lba, temp_b);
} else {
ret = read_data(dev, lba);
ret = read_data(dev, lba, 1);
/* Return with error if we had one. */
if (ret > 0) {
@@ -2800,7 +2921,7 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer)
}
if (track->adr_ctl & 0x04) {
ret = read_data(dev, start);
ret = read_data(dev, start, 0);
mode = dev->raw_buffer[dev->cur_buf][3];
}
} else if (track->point != 0xa2)
@@ -2829,9 +2950,9 @@ uint8_t
cdrom_get_current_mode(cdrom_t *dev)
{
if (dev->cached_sector == -1)
(void) read_data(dev, dev->seek_pos);
(void) read_data(dev, dev->seek_pos, 0);
else
(void) read_data(dev, dev->cached_sector);
(void) read_data(dev, dev->cached_sector, 0);
return dev->raw_buffer[dev->cur_buf][3];
}
@@ -2864,7 +2985,7 @@ cdrom_update_status(cdrom_t *dev)
dev->cached_sector = -1;
dev->cdrom_capacity = dev->ops->get_last_block(dev->local);
if (dev->cd_status != CD_STATUS_EMPTY) {
if ((dev->cd_status != CD_STATUS_EMPTY) && (dev->cd_status != CD_STATUS_DVD_REJECTED)) {
/* Signal media change to the emulated machine. */
cdrom_insert(dev->id);
@@ -2906,9 +3027,14 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
if ((dev->ops->is_empty != NULL) && dev->ops->is_empty(dev->local))
dev->cd_status = CD_STATUS_EMPTY;
else if (dev->ops->is_dvd(dev->local))
dev->cd_status = CD_STATUS_DVD;
else
else if (dev->ops->is_dvd(dev->local)) {
if (cdrom_is_dvd(dev->type))
dev->cd_status = CD_STATUS_DVD;
else {
warning("DVD image \"%s\" in a CD-only drive, reporting as empty\n", fn);
dev->cd_status = CD_STATUS_DVD_REJECTED;
}
} else
dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED :
CD_STATUS_DATA_ONLY;
@@ -2922,7 +3048,7 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
cdrom_toc_dump(dev);
#endif
if (!skip_insert && (dev->cd_status != CD_STATUS_EMPTY)) {
if (!skip_insert && (dev->cd_status != CD_STATUS_EMPTY) && (dev->cd_status != CD_STATUS_DVD_REJECTED)) {
/* Signal media change to the emulated machine. */
cdrom_insert(dev->id);
@@ -3011,6 +3137,11 @@ cdrom_hard_reset(void)
cdrom_load(dev, dev->image_path, 0);
}
for (uint32_t j = 0; j < _LUT_SIZE; ++j) {
dev->_F_LUT[j] = (j << 1) ^ (j & 0x80 ? 0x11d : 0);
dev->_B_LUT[j ^ dev->_F_LUT[j]] = j;
}
}
}

View File

@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <sys/stat.h>
#ifndef _WIN32
# include <libgen.h>
@@ -84,17 +85,148 @@ typedef struct track_t {
track_index_t idx[3];
} track_t;
/*
MDS for DVD has the disc structure table - 4 byte pointer to BCA,
followed by the copyright, DMI, and layer pages.
*/
#pragma pack(push, 1)
typedef struct
{
uint8_t f1[4];
uint8_t f4[2048];
uint8_t f0[2048];
} layer_t;
typedef struct
{
layer_t layers[2];
} mds_disc_struct_t;
#pragma pack(pop)
#define dstruct_t mds_disc_struct_t
typedef struct cd_image_t {
cdrom_t *dev;
void *log;
int is_dvd;
int has_audio;
int has_dstruct;
int32_t tracks_num;
uint32_t bad_sectors_num;
track_t *tracks;
uint32_t *bad_sectors;
dstruct_t dstruct;
} cd_image_t;
typedef enum
{
CD = 0x00, /* CD-ROM */
CD_R = 0x01, /* CD-R */
CD_RW = 0x02, /* CD-RW */
DVD = 0x10, /* DVD-ROM */
DVD_MINUS_R = 0x12 /* DVD-R */
} mds_medium_type_t;
typedef enum
{
UNKNOWN = 0x00,
AUDIO = 0xa9, /* sector size = 2352 */
MODE1 = 0xaa, /* sector size = 2048 */
MODE2 = 0xab, /* sector size = 2336 */
MODE2_FORM1 = 0xac, /* sector size = 2048 */
MODE2_FORM2 = 0xad /* sector size = 2324 (+4) */
} mds_trk_mode_t;
typedef enum
{
NONE = 0x00, /* no subchannel */
PW_INTERLEAVED = 0x08 /* 96-byte PW subchannel, interleaved */
} mds_subch_mode_t;
#pragma pack(push, 1)
typedef struct
{
uint8_t file_sig[16];
uint8_t file_ver[2];
uint16_t medium_type;
uint16_t sess_num;
uint16_t pad[2];
uint16_t bca_data_len;
uint32_t pad0[2];
uint32_t bca_data_offs_offs;
uint32_t pad1[6];
uint32_t disc_struct_offs;
uint32_t pad2[3];
uint32_t sess_blocks_offs;
uint32_t dpm_blocks_offs;
} mds_hdr_t; /* 88 bytes */
typedef struct
{
int32_t sess_start;
int32_t sess_end;
uint16_t sess_id;
uint8_t all_blocks_num;
uint8_t non_track_blocks_num;
uint16_t first_trk;
uint16_t last_trk;
uint32_t pad;
uint32_t trk_blocks_offs;
} mds_sess_block_t; /* 24 bytes */
typedef struct
{
uint8_t trk_mode;
/* DiscImageCreator says this is the number of subchannels. */
uint8_t subch_mode;
uint8_t adr_ctl;
uint8_t track_id;
uint8_t point;
uint8_t m;
uint8_t s;
uint8_t f;
uint8_t zero;
uint8_t pm;
uint8_t ps;
uint8_t pf;
/* DiscImageCreator calls this the index offset. */
uint32_t ex_offs;
uint16_t sector_len;
/* DiscImageCreator says unknown1 followed by 17x zero. */
uint8_t pad0[18];
uint32_t start_sect;
uint64_t start_offs;
uint32_t files_num;
uint32_t footer_offs;
uint8_t pad1[24];
} mds_trk_block_t; /* 80 bytes */
/*
DiscImageCreator's interpretation here makes sense and essentially
matches libmirage's - Index 0 sectors followed by Index 1 sectors.
*/
typedef struct
{
uint32_t pregap;
uint32_t trk_sectors;
} mds_trk_ex_block_t; /* 8 bytes */
typedef struct
{
uint32_t fn_offs;
uint32_t fn_is_wide;
uint32_t pad;
uint32_t pad0;
} mds_footer_t; /* 16 bytes */
typedef struct
{
uint32_t type;
uint32_t pad[2];
uint32_t entries;
} mds_dpm_block_t;
#pragma pack(pop)
#ifdef ENABLE_IMAGE_LOG
int image_do_log = ENABLE_IMAGE_LOG;
@@ -284,6 +416,9 @@ bin_close(void *priv)
memset(tf->fn, 0x00, sizeof(tf->fn));
log_close(tf->log);
tf->log = NULL;
free(priv);
}
@@ -298,6 +433,11 @@ bin_init(const uint8_t id, const char *filename, int *error)
return NULL;
}
char n[1024] = { 0 };
sprintf(n, "CD-ROM %i Bin ", id + 1);
tf->log = log_open(n);
memset(tf->fn, 0x00, sizeof(tf->fn));
strncpy(tf->fn, filename, sizeof(tf->fn) - 1);
tf->fp = plat_fopen64(tf->fn, "rb");
@@ -314,11 +454,6 @@ bin_init(const uint8_t id, const char *filename, int *error)
tf->read = bin_read;
tf->get_length = bin_get_length;
tf->close = bin_close;
char n[1024] = { 0 };
sprintf(n, "CD-ROM %i Bin ", id + 1);
tf->log = log_open(n);
} else {
/* From the check above, error may still be non-zero if opening a directory.
* The error is set for viso to try and open the directory following this function.
@@ -326,8 +461,12 @@ bin_init(const uint8_t id, const char *filename, int *error)
if ((tf->fp != NULL) && ((stats.st_mode & S_IFMT) == S_IFDIR)) {
/* tf is freed by bin_close */
bin_close(tf);
} else
} else {
log_close(tf->log);
tf->log = NULL;
free(tf);
}
tf = NULL;
}
@@ -1183,7 +1322,7 @@ image_process(cd_image_t *img)
ct->point, j,
cit[ci->type + 2], ci->file_start * ct->sector_size);
image_log(img->log, " TOC data: %02X %02X %02X "
"%%02X %02X %02X %02X 02X %02X %02X %02X\n",
"%02X %02X %02X %02X %02X %02X %02X %02X\n",
ct->session, ct->attr, ct->tno, ct->point,
ct->extra[0], ct->extra[1], ct->extra[2], ct->extra[3],
(uint32_t) ((ci->start / 75) / 60),
@@ -1208,12 +1347,12 @@ image_set_track_subch_type(track_t *ct)
static int
image_load_iso(cd_image_t *img, const char *filename)
{
track_t *ct = NULL;
track_index_t *ci = NULL;
track_file_t *tf = NULL;
int success = 1;
int error = 1;
int is_viso = 0;
track_t *ct = NULL;
track_index_t *ci = NULL;
track_file_t *tf = NULL;
int success = 1;
int error = 1;
int is_viso = 0;
int sector_sizes[8] = { 2448, 2368, RAW_SECTOR_SIZE, 2336,
2332, 2328, 2324, COOKED_SECTOR_SIZE };
@@ -1308,8 +1447,12 @@ image_load_iso(cd_image_t *img, const char *filename)
if (success)
image_process(img);
else {
image_log(img->log, " [ISO ] Unable to open image or folder \"%s\"\n",
filename);
#ifdef ENABLE_IMAGE_LOG
log_warning(img->log, "Unable to open image or folder \"%s\"\n",
filename);
#else
warning("Unable to open image or folder \"%s\"\n", filename);
#endif
return 0;
}
@@ -1446,9 +1589,9 @@ image_load_cue(cd_image_t *img, const char *cuefile)
if (last_t != -1) {
/*
Important: This has to be done like this because pointers
change due to realloc.
change due to realloc.
*/
ct = &(img->tracks[t]);
ct = &(img->tracks[img->tracks_num - 1]);
for (int i = 2; i >= 0; i--) {
if (ct->idx[i].file == NULL)
@@ -1654,11 +1797,434 @@ image_load_cue(cd_image_t *img, const char *cuefile)
if (success)
image_process(img);
else {
image_log(img->log, " [CUE ] Unable to open Cue sheet \"%s\"\n", cuefile);
else
#ifdef ENABLE_IMAGE_LOG
log_warning(img->log, " [CUE ] Unable to open Cue sheet \"%s\"\n", cuefile);
#else
warning("Unable to open Cue sheet \"%s\"\n", cuefile);
#endif
return success;
}
// Converts UTF-16 string into UTF-8 string.
// If destination string is NULL returns total number of symbols that would've
// been written (without null terminator). However, when actually writing into
// destination string, it does include it. So, be sure to allocate extra byte
// for destination string.
// Params:
// u16_str - source UTF-16 string
// u16_str_len - length of source UTF-16 string
// u8_str - destination UTF-8 string
// u8_str_size - size of destination UTF-8 string in bytes
// Return value:
// 0 on success, -1 if encountered invalid surrogate pair, -2 if
// encountered buffer overflow or length of destination UTF-8 string in bytes
// (without including the null terminator).
long int utf16_to_utf8(const uint16_t *u16_str, size_t u16_str_len,
uint8_t *u8_str, size_t u8_str_size)
{
size_t i = 0, j = 0;
if (!u8_str) {
u8_str_size = u16_str_len * 4;
}
while (i < u16_str_len) {
uint32_t codepoint = u16_str[i++];
// check for surrogate pair
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
uint16_t high_surr = codepoint;
uint16_t low_surr = u16_str[i++];
if (low_surr < 0xDC00 || low_surr > 0xDFFF)
return -1;
codepoint = ((high_surr - 0xD800) << 10) +
(low_surr - 0xDC00) + 0x10000;
}
if (codepoint < 0x80) {
if (j + 1 > u8_str_size) return -2;
if (u8_str) u8_str[j] = (char)codepoint;
j++;
} else if (codepoint < 0x800) {
if (j + 2 > u8_str_size) return -2;
if (u8_str) {
u8_str[j + 0] = 0xC0 | (codepoint >> 6);
u8_str[j + 1] = 0x80 | (codepoint & 0x3F);
}
j += 2;
} else if (codepoint < 0x10000) {
if (j + 3 > u8_str_size) return -2;
if (u8_str) {
u8_str[j + 0] = 0xE0 | (codepoint >> 12);
u8_str[j + 1] = 0x80 | ((codepoint >> 6) & 0x3F);
u8_str[j + 2] = 0x80 | (codepoint & 0x3F);
}
j += 3;
} else {
if (j + 4 > u8_str_size) return -2;
if (u8_str) {
u8_str[j + 0] = 0xF0 | (codepoint >> 18);
u8_str[j + 1] = 0x80 | ((codepoint >> 12) & 0x3F);
u8_str[j + 2] = 0x80 | ((codepoint >> 6) & 0x3F);
u8_str[j + 3] = 0x80 | (codepoint & 0x3F);
}
j += 4;
}
}
if (u8_str) {
if (j >= u8_str_size) return -2;
u8_str[j] = '\0';
}
return (long int)j;
}
static int
image_load_mds(cd_image_t *img, const char *mdsfile)
{
track_t *ct = NULL;
track_index_t *ci = NULL;
track_file_t *tf = NULL;
int is_viso = 0;
int last_t = -1;
int error;
char pathname[MAX_FILENAME_LENGTH];
char ofn[2048] = { 0 };
mds_hdr_t mds_hdr = { 0 };
mds_sess_block_t mds_sess_block = { 0 };
mds_trk_block_t mds_trk_block = { 0 };
mds_trk_ex_block_t mds_trk_ex_block = { 0 };
mds_footer_t mds_footer = { 0 };
mds_dpm_block_t mds_dpm_block = { 0 };
uint32_t mds_dpm_blocks_num = 0x00000000;
uint32_t mds_dpm_block_offs = 0x00000000;
img->tracks = NULL;
img->tracks_num = 0;
/* Get a copy of the filename into pathname, we need it later. */
memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(char));
path_get_dirname(pathname, mdsfile);
/* Open the file. */
FILE *fp = plat_fopen(mdsfile, "rb");
if (fp == NULL)
return 0;
int success = 0;
/*
Pass 1 - loading the MDS sheet.
*/
image_log(img->log, "Pass 1 (loading the Media Descriptor Sheet)...\n");
img->tracks_num = 0;
success = 2;
fseek(fp, 0, SEEK_SET);
fread(&mds_hdr, 1, sizeof(mds_hdr_t), fp);
if (memcmp(mds_hdr.file_sig, "MEDIA DESCRIPTOR", 16)) {
#ifdef ENABLE_IMAGE_LOG
log_warning(img->log, " [MDS ] \"%s\"\n is not an actual MDF file",
mdsfile);
#else
warning("\"%s\"\n is not an actual MDF file", mdsfile);
#endif
fclose(fp);
return 0;
}
if (mds_hdr.file_ver[0] == 0x02) {
#ifdef ENABLE_IMAGE_LOG
log_warning(img->log, " [MDS ] \"%s\" is a Daemon Tools encrypted MDS which is not supported\n",
mdsfile);
#else
warning("\"%s\" is a Daemon Tools encrypted MDS which is not supported\n", mdsfile);
#endif
fclose(fp);
return 0;
}
img->is_dvd = (mds_hdr.medium_type >= 0x10);
if (img->is_dvd) {
if (mds_hdr.disc_struct_offs != 0x00) {
fseek(fp, mds_hdr.disc_struct_offs, SEEK_SET);
fread(&(img->dstruct.layers[0]), 1, sizeof(layer_t), fp);
img->has_dstruct = 1;
if (((img->dstruct.layers[0].f0[2] & 0x60) >> 4) == 0x01) {
fseek(fp, mds_hdr.disc_struct_offs, SEEK_SET);
fread(&(img->dstruct.layers[1]), 1, sizeof(layer_t), fp);
img->has_dstruct++;
}
}
for (int t = 0; t < 3; t++) {
ct = image_insert_track(img, 1, 0xa0 + t);
ct->attr = DATA_TRACK;
ct->mode = 0;
ct->form = 0;
ct->tno = 0;
ct->subch_type = 0;
memset(ct->extra, 0x00, 4);
for (int i = 0; i < 3; i++) {
ci = &(ct->idx[i]);
ci->type = INDEX_NONE;
ci->start = 0;
ci->length = 0;
ci->file_start = 0;
ci->file_length = 0;
ci->file = NULL;
}
ci = &(ct->idx[1]);
if (t < 2)
ci->start = (0x01 * 60 * 75) + (0 * 75) + 0;
}
}
if (mds_hdr.dpm_blocks_offs != 0x00) {
fseek(fp, mds_hdr.dpm_blocks_offs, SEEK_SET);
fread(&mds_dpm_blocks_num, 1, sizeof(uint32_t), fp);
if (mds_dpm_blocks_num > 0) for (int b = 0; b < mds_dpm_blocks_num; b++) {
fseek(fp, mds_hdr.dpm_blocks_offs + 4 + (b * 4), SEEK_SET);
fread(&mds_dpm_block_offs, 1, sizeof(uint32_t), fp);
fseek(fp, mds_dpm_block_offs, SEEK_SET);
fread(&mds_dpm_block, 1, sizeof(mds_dpm_block_t), fp);
/* We currently only support the bad sectors block and not (yet) actual DPM. */
if (mds_dpm_block.type == 0x00000002) {
/* Bad sectors. */
img->bad_sectors_num = mds_dpm_block.entries;
img->bad_sectors = (uint32_t *) malloc(img->bad_sectors_num * sizeof(uint32_t));
fseek(fp, mds_dpm_block_offs + sizeof(mds_dpm_block_t), SEEK_SET);
fread(img->bad_sectors, 1, img->bad_sectors_num * sizeof(uint32_t), fp);
break;
}
}
}
for (int s = 0; s < mds_hdr.sess_num; s++) {
fseek(fp, mds_hdr.sess_blocks_offs + (s * sizeof(mds_sess_block_t)), SEEK_SET);
fread(&mds_sess_block, 1, sizeof(mds_sess_block_t), fp);
for (int t = 0; t < mds_sess_block.all_blocks_num; t++) {
fseek(fp, mds_sess_block.trk_blocks_offs + (t * sizeof(mds_trk_block_t)), SEEK_SET);
fread(&mds_trk_block, 1, sizeof(mds_trk_block_t), fp);
if (last_t != -1) {
/*
Important: This has to be done like this because pointers
change due to realloc.
*/
ct = &(img->tracks[img->tracks_num - 1]);
for (int i = 2; i >= 0; i--) {
if (ct->idx[i].file == NULL)
ct->idx[i].file = tf;
else
break;
}
}
last_t = mds_trk_block.point;
ct = image_insert_track(img, mds_sess_block.sess_id, mds_trk_block.point);
if (img->is_dvd) {
/* DVD images have no extra block - the extra block offset is the track length. */
memset(&mds_trk_ex_block, 0x00, sizeof(mds_trk_ex_block_t));
mds_trk_ex_block.pregap = 0x00000000;
mds_trk_ex_block.trk_sectors = mds_trk_block.ex_offs;
} else if (mds_trk_block.ex_offs != 0ULL) {
fseek(fp, mds_trk_block.ex_offs, SEEK_SET);
fread(&mds_trk_ex_block, 1, sizeof(mds_trk_ex_block), fp);
}
uint32_t astart = mds_trk_block.start_sect - mds_trk_ex_block.pregap;
uint32_t aend = astart + mds_trk_ex_block.pregap;
uint32_t aend2 = aend + mds_trk_ex_block.trk_sectors;
uint32_t astart2 = mds_trk_block.start_sect + mds_trk_ex_block.trk_sectors;
if (mds_trk_block.footer_offs != 0ULL) for (uint32_t ff = 0; ff < mds_trk_block.files_num; ff++) {
fseek(fp, mds_trk_block.footer_offs + (ff * sizeof(mds_footer_t)), SEEK_SET);
fread(&mds_footer, 1, sizeof(mds_footer_t), fp);
uint16_t wfn[2048] = { 0 };
char fn[2048] = { 0 };
fseek(fp, mds_footer.fn_offs, SEEK_SET);
if (mds_footer.fn_is_wide) {
for (int i = 0; i < 256; i++) {
fread(&(wfn[i]), 1, 2, fp);
if (wfn[i] == 0x0000)
break;
}
(void) utf16_to_utf8(wfn, 2048, (uint8_t *) fn, 2048);
} else for (int i = 0; i < 512; i++) {
fread(&fn[i], 1, 1, fp);
if (fn[i] == 0x00)
break;
}
if (!stricmp(fn, "*.mdf")) {
strcpy(fn, mdsfile);
fn[strlen(mdsfile) - 3] = 'm';
fn[strlen(mdsfile) - 2] = 'd';
fn[strlen(mdsfile) - 1] = 'f';
}
char filename[2048] = { 0 };
if (!path_abs(fn))
path_append_filename(filename, pathname, fn);
else
strcpy(filename, fn);
if (strcmp(ofn, filename) != 0) {
tf = index_file_init(img->dev->id, filename, &error, &is_viso);
strcpy(ofn, filename);
}
}
ct->sector_size = mds_trk_block.sector_len;
ct->form = 0;
ct->tno = mds_trk_block.track_id;
ct->subch_type = mds_trk_block.subch_mode;
ct->extra[0] = mds_trk_block.m;
ct->extra[1] = mds_trk_block.s;
ct->extra[2] = mds_trk_block.f;
ct->extra[3] = mds_trk_block.zero;
/*
Note from DiscImageCreator:
I hexedited the track mode field with various values and fed it to Alchohol;
it seemed that high part of byte had no effect at all; only the lower one
affected the mode, in the following manner:
00: Mode 2, 01: Audio, 02: Mode 1, 03: Mode 2, 04: Mode 2 Form 1,
05: Mode 2 Form 2, 06: UKNONOWN, 07: Mode 2
08: Mode 2, 09: Audio, 0A: Mode 1, 0B: Mode 2, 0C: Mode 2 Form 1,
0D: Mode 2 Form 2, 0E: UKNONOWN, 0F: Mode 2
*/
ct->attr = ((mds_trk_block.trk_mode & 0x07) == 0x01) ?
AUDIO_TRACK : DATA_TRACK;
ct->mode = 0;
ct->form = 0;
if (((mds_trk_block.trk_mode & 0x07) != 0x01) &&
((mds_trk_block.trk_mode & 0x07) != 0x06))
ct->mode = ((mds_trk_block.trk_mode & 0x07) != 0x02) + 1;
if ((mds_trk_block.trk_mode & 0x06) == 0x04)
ct->form = (mds_trk_block.trk_mode & 0x07) - 0x03;
if (ct->attr == AUDIO_TRACK)
success = 1;
if (((ct->sector_size == 2336) || (ct->sector_size == 2332)) && (ct->mode == 2) && (ct->form == 1))
ct->skip = 8;
ci = &(ct->idx[0]);
if (ct->point < 0xa0) {
ci->start = astart + 150;
ci->length = mds_trk_ex_block.pregap;
}
ci->type = (ci->length > 0) ? INDEX_ZERO : INDEX_NONE;
ci->file_start = 0;
ci->file_length = 0;
ci->file = NULL;
ci = &(ct->idx[1]);
if ((mds_trk_block.point >= 1) && (mds_trk_block.point <= 99)) {
ci->start = aend + 150;
ci->length = mds_trk_ex_block.trk_sectors;
ci->type = INDEX_NORMAL;
ci->file_start = mds_trk_block.start_offs / ct->sector_size;
ci->file_length = ci->length;
ci->file = tf;
} else {
ci->start = (mds_trk_block.pm * 60 * 75) + (mds_trk_block.ps * 75) + mds_trk_block.pf;
ci->type = INDEX_NONE;
ci->file_start = 0;
ci->file_length = 0;
ci->file = NULL;
}
ci = &(ct->idx[2]);
if (ct->point < 0xa0) {
ci->start = aend2 + 150;
ci->length = astart2 - aend2;
}
ci->type = (ci->length > 0) ? INDEX_ZERO : INDEX_NONE;
ci->file_start = 0;
ci->file_length = 0;
ci->file = NULL;
if (img->is_dvd) {
ci = &(ct->idx[1]);
uint32_t total = ci->start + ci->length;
ci = &(img->tracks[2].idx[1]);
ci->start = total;
}
}
for (int i = 2; i >= 0; i--) {
if (ct->point >= 0xa0)
ci->type = INDEX_SPECIAL;
if (ct->idx[i].file == NULL)
ct->idx[i].file = tf;
else
break;
}
}
tf = NULL;
fclose(fp);
if (success) {
#ifdef ENABLE_IMAGE_LOG
image_log(img->log, "Final tracks list:\n");
for (int i = 0; i < img->tracks_num; i++) {
ct = &(img->tracks[i]);
for (int j = 0; j < 3; j++) {
ci = &(ct->idx[j]);
image_log(img->log, " [TRACK ] %02X INDEX %02X: [%8s, %016" PRIX64 "]\n",
ct->point, j,
cit[ci->type + 2], ci->file_start * ct->sector_size);
image_log(img->log, " TOC data: %02X %02X %02X "
"%02X %02X %02X %02X %02X %02X %02X %02X\n",
ct->session, ct->attr, ct->tno, ct->point,
ct->extra[0], ct->extra[1], ct->extra[2], ct->extra[3],
(uint32_t) ((ci->start / 75) / 60),
(uint32_t) ((ci->start / 75) % 60),
(uint32_t) (ci->start % 75));
}
}
#endif
} else
#ifdef ENABLE_IMAGE_LOG
log_warning(img->log, " [MDS ] Unable to open MDS sheet \"%s\"\n", mdsfile);
#else
warning("Unable to open MDS sheet \"%s\"\n", mdsfile);
#endif
return success;
}
@@ -1713,8 +2279,8 @@ image_get_track_info(const void *local, const uint32_t track,
}
if (ct != NULL) {
const uint32_t pos = end ? ct->idx[1].start :
(ct->idx[1].start + ct->idx[1].length);
const uint32_t pos = end ? (ct->idx[1].start + ct->idx[1].length) :
ct->idx[1].start;
ti->number = ct->point;
ti->attr = ct->attr;
@@ -1784,6 +2350,7 @@ image_read_sector(const void *local, uint8_t *buffer,
const uint32_t sector)
{
const cd_image_t *img = (const cd_image_t *) local;
cdrom_t *dev = (cdrom_t *) img->dev;
int m = 0;
int s = 0;
int f = 0;
@@ -1792,6 +2359,7 @@ image_read_sector(const void *local, uint8_t *buffer,
int track;
int index;
uint8_t q[16] = { 0x00 };
uint8_t *buf = buffer;
if (sector == 0xffffffff)
lba = img->dev->seek_pos;
@@ -1851,6 +2419,26 @@ image_read_sector(const void *local, uint8_t *buffer,
/* Index is not in the file, no read to fail here. */
ret = 1;
if ((ret > 0) && (trk->attr & 0x04) && ((idx->type < INDEX_NORMAL) || !track_is_raw)) {
uint32_t crc;
if ((trk->mode == 2) && (trk->form == 1)) {
crc = cdrom_crc32(0xffffffff, &(buf[16]), 2056) ^ 0xffffffff;
memcpy(&(buf[2072]), &crc, 4);
} else {
crc = cdrom_crc32(0xffffffff, buf, 2064) ^ 0xffffffff;
memcpy(&(buf[2064]), &crc, 4);
}
int m2f1 = (trk->mode == 2) && (trk->form == 1);
/* Compute ECC P code. */
cdrom_compute_ecc_block(dev, &(buf[2076]), &(buf[12]), 86, 24, 2, 86, m2f1);
/* Compute ECC Q code. */
cdrom_compute_ecc_block(dev, &(buf[2248]), &(buf[12]), 52, 43, 86, 88, m2f1);
}
if ((ret > 0) && ((idx->type < INDEX_NORMAL) || (trk->subch_type != 0x08))) {
buffer -= offset;
@@ -1945,7 +2533,27 @@ static int
image_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format,
uint8_t *buffer, uint32_t *info)
{
return 0;
const cd_image_t *img = (const cd_image_t *) local;
int ret = 0;
if ((img->has_dstruct > 0) && ((layer + 1) > img->has_dstruct)) {
switch (format) {
case 0x00:
memcpy(buffer + 4, img->dstruct.layers[layer].f0, 2048);
ret = 2048 + 2;
break;
case 0x01:
memcpy(buffer + 4, img->dstruct.layers[layer].f1, 4);
ret = 4 + 2;
break;
case 0x04:
memcpy(buffer + 4, img->dstruct.layers[layer].f4, 2048);
ret = 2048 + 2;
break;
}
}
return ret;
}
static int
@@ -1977,6 +2585,9 @@ image_close(void *local)
log_close(img->log);
img->log = NULL;
if (img->bad_sectors != NULL)
free(img->bad_sectors);
free(img);
}
}
@@ -2005,40 +2616,54 @@ image_open(cdrom_t *dev, const char *path)
if (img != NULL) {
int ret;
const int is_cue = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE"));
const int is_cue = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE"));
const int is_mds = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "MDS"));
char n[1024] = { 0 };
img->dev = dev;
sprintf(n, "CD-ROM %i Image", dev->id + 1);
img->log = log_open(n);
if (is_cue) {
img->dev = dev;
if (is_mds) {
ret = image_load_mds(img, path);
if (ret >= 2)
img->has_audio = 0;
else if (ret)
img->has_audio = 1;
} else if (is_cue) {
ret = image_load_cue(img, path);
if (ret >= 2)
img->has_audio = 0;
else if (ret)
img->has_audio = 1;
else {
image_close(img);
img = NULL;
}
if (ret >= 1)
img->is_dvd = 2;
} else {
ret = image_load_iso(img, path);
if (!ret) {
image_close(img);
img = NULL;
} else
if (ret) {
img->has_audio = 0;
img->is_dvd = 2;
}
}
if (ret) {
char n[1024] = { 0 };
sprintf(n, "CD-ROM %i Image", dev->id + 1);
img->log = log_open(n);
if (ret > 0) {
if (img->is_dvd == 2) {
uint32_t lb = image_get_last_block(img); /* Should be safer than previous way of doing it? */
img->is_dvd = (lb >= 524287); /* Minimum 1 GB total capacity as threshold for DVD. */
}
dev->ops = &image_ops;
} else
warning("Unable to load CD-ROM image: %s\n", path);
} else {
log_warning(img->log, "Unable to load CD-ROM image: %s\n", path);
image_close(img);
img = NULL;
}
}
return img;

View File

@@ -8,11 +8,11 @@
*
* Mitsumi CD-ROM emulation for the ISA bus.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2022 Miran Grca.
* Copyright 2022 Miran Grca.
* Copyright 2024-2025 Jasmine Iwanek.
*/
#include <inttypes.h>
#include <stdarg.h>
@@ -33,10 +33,6 @@
#include <86box/plat.h>
#include <86box/sound.h>
#define MCD_DEFAULT_IOPORT 0x310
#define MCD_DEFAULT_IRQ 5
#define MCD_DEFAULT_DMA 5
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
@@ -116,6 +112,8 @@ typedef struct mcd_t {
int cur_toc_track;
int pos;
int newstat;
cdrom_t *cdrom_dev;
} mcd_t;
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
@@ -140,17 +138,15 @@ mitsumi_cdrom_log(const char *fmt, ...)
#endif
static int
mitsumi_cdrom_is_ready(const cdrom_t *dev)
mitsumi_cdrom_is_ready(const mcd_t *dev)
{
return (dev->image_path[0] != 0x00);
return (dev->cdrom_dev->image_path[0] != 0x00);
}
static void
mitsumi_cdrom_reset(mcd_t *dev)
{
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | STAT_CHANGE) : 0;
dev->stat = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | STAT_CHANGE) : 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 0;
dev->buf_count = 0;
@@ -168,12 +164,11 @@ mitsumi_cdrom_reset(mcd_t *dev)
static int
mitsumi_cdrom_read_sector(mcd_t *dev, int first)
{
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
uint8_t status;
int ret = 0;
if (dev->drvmode == DRV_MODE_CDDA) {
status = cdrom_mitsumi_audio_play(cdrom, dev->readmsf, dev->readcount);
status = cdrom_mitsumi_audio_play(dev->cdrom_dev, dev->readmsf, dev->readcount);
if (status == 1)
return status;
else
@@ -187,15 +182,15 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first)
dev->data = 0;
return 0;
}
cdrom_stop(cdrom);
ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
cdrom_stop(dev->cdrom_dev);
ret = cdrom_readsector_raw(dev->cdrom_dev, dev->buf, dev->cdrom_dev->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (ret <= 0)
return 0;
if (dev->mode & 0x40) {
dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff);
dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff);
}
dev->readmsf = cdrom_lba_to_msf_accurate(cdrom->seek_pos + 1);
dev->readmsf = cdrom_lba_to_msf_accurate(dev->cdrom_dev->seek_pos + 1);
dev->buf_count = dev->dmalen + 1;
dev->buf_idx = 0;
dev->data = 1;
@@ -258,7 +253,6 @@ static void
mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
cdrom_t *cdrom = calloc(1, sizeof(cdrom_t));
pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val);
switch (port & 1) {
@@ -340,19 +334,19 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
}
if (!dev->cmdrd_count)
dev->stat = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->stat = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
return;
}
dev->cmd = val;
dev->cmdbuf_idx = 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = mitsumi_cdrom_is_ready(cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->cmdbuf[0] = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->data = 0;
switch (val) {
case CMD_GET_INFO:
if (mitsumi_cdrom_is_ready(cdrom)) {
cdrom_get_track_buffer(cdrom, &(dev->cmdbuf[1]));
if (mitsumi_cdrom_is_ready(dev)) {
cdrom_get_track_buffer(dev->cdrom_dev, &(dev->cmdbuf[1]));
dev->cmdbuf_count = 10;
dev->readcount = 0;
} else {
@@ -361,7 +355,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
}
break;
case CMD_GET_Q:
if (mitsumi_cdrom_is_ready(cdrom)) {
if (mitsumi_cdrom_is_ready(dev)) {
cdrom_get_q(cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
dev->cmdbuf_count = 11;
dev->readcount = 0;
@@ -378,7 +372,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_STOPCDDA:
case CMD_STOP:
cdrom_stop(cdrom);
cdrom_stop(dev->cdrom_dev);
dev->drvmode = DRV_MODE_STOP;
dev->cur_toc_track = 0;
break;
@@ -387,7 +381,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_READ1X:
case CMD_READ2X:
if (mitsumi_cdrom_is_ready(cdrom)) {
if (mitsumi_cdrom_is_ready(dev)) {
dev->readcount = 0;
dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ;
dev->cmdrd_count = 6;
@@ -403,7 +397,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
dev->cmdbuf_count = 3;
break;
case CMD_EJECT:
cdrom_stop(cdrom);
cdrom_stop(dev->cdrom_dev);
cdrom_eject(0);
dev->readcount = 0;
break;
@@ -434,10 +428,23 @@ mitsumi_cdrom_init(UNUSED(const device_t *info))
{
mcd_t *dev = calloc(1, sizeof(mcd_t));
dev->irq = MCD_DEFAULT_IRQ;
dev->dma = MCD_DEFAULT_DMA;
for (uint8_t i = 0; i < CDROM_NUM; i++) {
if (cdrom[i].bus_type == CDROM_BUS_MITSUMI) {
dev->cdrom_dev = &cdrom[i];
break;
}
}
io_sethandler(MCD_DEFAULT_IOPORT, 3,
if (!dev->cdrom_dev)
return NULL;
dev->cdrom_dev->priv = &dev;
uint16_t base = device_get_config_hex16("base");
dev->irq = device_get_config_int("irq");
dev->dma = device_get_config_int("dma");
io_sethandler(base, 3,
mitsumi_cdrom_in, NULL, NULL, mitsumi_cdrom_out, NULL, NULL, dev);
mitsumi_cdrom_reset(dev);
@@ -456,6 +463,64 @@ mitsumi_cdrom_close(void *priv)
}
}
static const device_config_t mitsumi_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0x310,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "300H", .value = 0x300 },
{ .description = "310H", .value = 0x310 },
{ .description = "320H", .value = 0x320 },
{ .description = "340H", .value = 0x340 },
{ .description = "350H", .value = 0x350 },
{ NULL }
},
.bios = { { 0 } }
},
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 5,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 9", .value = 9 },
{ .description = "IRQ 10", .value = 10 },
{ .description = "IRQ 11", .value = 11 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "dma",
.description = "DMA",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 5,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "DMA 5", .value = 5 },
{ .description = "DMA 6", .value = 6 },
{ .description = "DMA 7", .value = 7 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format off
};
const device_t mitsumi_cdrom_device = {
.name = "Mitsumi CD-ROM interface",
.internal_name = "mcd",
@@ -467,5 +532,5 @@ const device_t mitsumi_cdrom_device = {
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.config = mitsumi_config
};

1078
src/cdrom/cdrom_mke.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -30,12 +30,15 @@ add_library(chipset OBJECT
ali1621.c
ali6117.c
ali1409.c
headland.c
ims8848.c
intel_82335.c
compaq.c
compaq_386.c
contaq_82c59x.c
cs4031.c
grid1520.c
gc100.c
headland.c
ims8848.c
intel_82335.c
intel_420ex.c
intel_4x0.c
intel_i450kx.c
@@ -43,6 +46,7 @@ add_library(chipset OBJECT
intel_piix.c
isa486c.c
../ioapic.c
laserxt.c
neat.c
olivetti_eva.c
opti283.c
@@ -55,6 +59,8 @@ add_library(chipset OBJECT
opti822.c
opti895.c
opti5x7.c
philips.c
sanyo.c
scamp.c
scat.c
sis_85c310.c
@@ -77,10 +83,9 @@ add_library(chipset OBJECT
sis_5595_pmu.c
sis_55xx.c
sl82c461.c
stpc.c
via_vt82c49x.c
via_vt82c505.c
gc100.c
stpc.c
umc_8886.c
umc_hb4.c
umc_8890.c

135
src/chipset/compaq.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Compaq 386 memory controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/machine.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
typedef struct cpq_t {
mem_mapping_t ram_mapping;
} cpq_t;
static uint8_t
read_ram(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (ram[addr]);
}
static uint16_t
read_ramw(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (*(uint16_t *) &ram[addr]);
}
static uint32_t
read_raml(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (*(uint32_t *) &ram[addr]);
}
static void
write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramb_page(addr, val, &pages[addr >> 12]);
}
static void
write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramw_page(addr, val, &pages[addr >> 12]);
}
static void
write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_raml_page(addr, val, &pages[addr >> 12]);
}
static void
compaq_close(void *priv)
{
cpq_t *dev = (cpq_t *) priv;
free(dev);
}
static void *
compaq_init(UNUSED(const device_t *info))
{
cpq_t *dev = (cpq_t *) calloc(1, sizeof(cpq_t));
mem_remap_top(384);
mem_mapping_add(&dev->ram_mapping, 0xfa0000, 0x60000,
read_ram, read_ramw, read_raml,
write_ram, write_ramw, write_raml,
0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL);
return dev;
}
const device_t compaq_device = {
.name = "Compaq Memory Control",
.internal_name = "compaq",
.flags = 0,
.local = 0,
.init = compaq_init,
.close = compaq_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -39,6 +39,7 @@
#include <86box/rom.h>
#include <86box/vid_cga.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#define GRID_APPROM_SELECT 0x440
#define GRID_APPROM_ENABLE 0x405
@@ -317,7 +318,7 @@ static void grid_reset(void *priv) {
dev->grid_rom_select = 0;
}
const device_t grid_device = {
const device_t grid1520_device = {
.name = "GRiDcase 1520 chipset",
.internal_name = "grid1520",
.flags = 0,
@@ -330,26 +331,3 @@ const device_t grid_device = {
.force_redraw = NULL,
.config = NULL
};
int machine_at_grid1520_init(const machine_t *model) {
int ret = 0;
ret = bios_load_linear("roms/machines/grid1520/grid1520_891025.rom",
0x000f8000, 0x8000, 0);
if (bios_only || !ret)
return ret;
machine_at_common_ide_init(model);
mem_remap_top(384);
device_add(&keyboard_at_device);
// for now just select CGA with amber monitor
//device_add(&cga_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&grid_device);
return ret;
}

View File

@@ -47,6 +47,7 @@
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/usb.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/smbus.h>
#include <86box/chipset.h>
@@ -618,6 +619,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x76:
if (dev->type > 1)
fregs[addr] = val & 0x87;
else if (dev->type <= 4)
fregs[addr] = val & 0x8f;
if ((dev->type == 1) && machine_has_jumpered_ecp_dma(machine, MACHINE_DMA_USE_MBDMA))
lpt1_dma(((val & 0x08) || ((val & 0x07) == 0x04)) ? 0xff : (val & 0x07));
break;
case 0x77:
if (dev->type > 1)
fregs[addr] = val & 0x87;

View File

@@ -1,4 +1,23 @@
/*This is the chipset used in the LaserXT series model*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the VTech LaserXT chipset.
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2008-2025 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2017-2025 Fred N. van Kempen.
* Copyright 2025 Jasmine Iwanek.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -452,53 +471,3 @@ const device_t lxt3_device = {
.force_redraw = NULL,
.config = lxt3_config
};
static void
machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3)
{
machine_common_init(model);
pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_xt_device);
nmi_init();
standalone_gameport_type = &gameport_device;
device_add(is_lxt3 ? &lxt3_device : &laserxt_device);
device_add(&keyboard_xt_lxt3_device);
}
int
machine_xt_laserxt_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/ltxt/27c64.bin",
0x000fe000, 8192, 0);
if (bios_only || !ret)
return ret;
machine_xt_laserxt_common_init(model, 0);
return ret;
}
int
machine_xt_lxt3_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/lxt3/27c64d.bin",
0x000fe000, 8192, 0);
if (bios_only || !ret)
return ret;
machine_xt_laserxt_common_init(model, 1);
return ret;
}

View File

@@ -8,11 +8,9 @@
*
* Emulation of the Philips XT-compatible machines.
*
*
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2021 EngiNerd.
* Copyright 2020-2025 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -148,60 +146,3 @@ const device_t philips_device = {
.force_redraw = NULL,
.config = NULL
};
void
machine_xt_philips_common_init(const machine_t *model)
{
machine_common_init(model);
pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt);
nmi_init();
standalone_gameport_type = &gameport_device;
device_add(&keyboard_pc_device);
device_add(&philips_device);
device_add(&xta_hd20_device);
}
int
machine_xt_p3105_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/p3105/philipsnms9100.bin",
0x000fc000, 16384, 0);
if (bios_only || !ret)
return ret;
machine_xt_philips_common_init(model);
/* On-board FDC cannot be disabled */
device_add(&fdc_xt_device);
return ret;
}
int
machine_xt_p3120_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/p3120/philips_p3120.bin",
0x000f8000, 32768, 0);
if (bios_only || !ret)
return ret;
machine_xt_philips_common_init(model);
device_add(&gc100a_device);
device_add(&fdc_at_device);
return ret;
}

123
src/chipset/sanyo.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Philips XT-compatible machines.
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2025 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/nmi.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/hdc.h>
#include <86box/gameport.h>
#include <86box/ibm_5161.h>
#include <86box/keyboard.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/io.h>
#include <86box/video.h>
#include <86box/plat_unused.h>
typedef struct sanyo_t {
uint8_t reg;
} sanyo_t;
#ifdef ENABLE_SANYO_LOG
int sanyo_do_log = ENABLE_SANYO_LOG;
static void
sanyo_log(const char *fmt, ...)
{
va_list ap;
if (sanyo_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sanyo_log(fmt, ...)
#endif
static void
sanyo_write(uint16_t port, uint8_t val, void *priv)
{
sanyo_t *dev = (sanyo_t *) priv;
dev->reg = val;
cpu_waitstates = !(val & 0x01);
cpu_update_waitstates();
sanyo_log("Sanyo MBC-17 Mainboard: Write %02x at %02x\n", val, port);
}
static uint8_t
sanyo_read(uint16_t port, void *priv)
{
const sanyo_t *dev = (sanyo_t *) priv;
uint8_t ret = 0xff;
ret = dev->reg;
sanyo_log("Sanyo MBC-17 Mainboard: Read %02x at %02x\n", ret, port);
return ret;
}
static void
sanyo_close(void *priv)
{
sanyo_t *dev = (sanyo_t *) priv;
free(dev);
}
static void *
sanyo_init(UNUSED(const device_t *info))
{
sanyo_t *dev = (sanyo_t *) calloc(1, sizeof(sanyo_t));
dev->reg = cpu_waitstates ? 0x00 : 0x01;
io_sethandler(0x0063, 0x01, sanyo_read, NULL, NULL, sanyo_write, NULL, NULL, dev);
return dev;
}
const device_t sanyo_device = {
.name = "Sanyo MBC-17 Mainboard",
.internal_name = "sanyo",
.flags = 0,
.local = 0,
.init = sanyo_init,
.close = sanyo_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -840,7 +840,7 @@ recalc_sltptr(scamp_t *dev)
recalc_ems(dev);
}
} else {
for (uint8_t i = 0; i < (sltptr / EMS_PGSIZE); i++)
for (uint32_t i = 0; i < (sltptr / EMS_PGSIZE); i++)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_SLOTBUS);
for (uint8_t i = (sltptr / EMS_PGSIZE); i < 40; i++)

View File

@@ -24,8 +24,9 @@
#include <86box/io.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
@@ -319,6 +320,8 @@ sis_5513_00_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev)
case 0x62: /* On-board Device DMA Control Register */
dev->pci_conf[addr] = val;
if (machine_has_jumpered_ecp_dma(machine, MACHINE_DMA_USE_MBDMA))
lpt1_dma(((val & 0x08) || ((val & 0x07) == 0x04)) ? 0xff : (val & 0x07));
break;
case 0x63: /* IDEIRQ Remapping Control Register */

View File

@@ -27,6 +27,7 @@
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -166,6 +167,8 @@ sis_5571_init(UNUSED(const device_t *info))
dev->ide = device_add_linked(&sis_5572_ide_device, dev->sis);
dev->usb = device_add_linked(&sis_5572_usb_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}

View File

@@ -27,6 +27,7 @@
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -166,6 +167,8 @@ sis_5581_init(UNUSED(const device_t *info))
dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis);
dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}

View File

@@ -27,6 +27,7 @@
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -178,6 +179,8 @@ sis_5591_init(UNUSED(const device_t *info))
else
dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}

View File

@@ -27,6 +27,7 @@
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -178,6 +179,8 @@ sis_5600_init(UNUSED(const device_t *info))
else
dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}

View File

@@ -596,15 +596,6 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
switch (rel_reg) {
case 0x00:
if (dev->is_471) {
if (val & 0x01) {
kbc_at_set_fast_reset(0);
cpu_cpurst_on_sr = 1;
} else {
kbc_at_set_fast_reset(1);
cpu_cpurst_on_sr = 0;
}
}
break;
case 0x01:

View File

@@ -80,10 +80,12 @@ typedef struct stpc_serial_t {
} stpc_serial_t;
typedef struct stpc_lpt_t {
uint8_t unlocked;
uint8_t offset;
uint8_t reg1;
uint8_t reg4;
uint8_t unlocked;
uint8_t offset;
uint8_t reg1;
uint8_t reg4;
lpt_t *lpt;
} stpc_lpt_t;
#ifdef ENABLE_STPC_LOG
@@ -977,22 +979,22 @@ stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val)
{
const uint8_t new_addr = (val & 0x03);
lpt1_remove();
lpt_port_remove(dev->lpt);
switch (new_addr) {
case 0x1:
stpc_log("STPC: Remapping parallel port to LPT3\n");
lpt1_setup(LPT_MDA_ADDR);
lpt_port_setup(dev->lpt, LPT_MDA_ADDR);
break;
case 0x2:
stpc_log("STPC: Remapping parallel port to LPT1\n");
lpt1_setup(LPT1_ADDR);
lpt_port_setup(dev->lpt, LPT1_ADDR);
break;
case 0x3:
stpc_log("STPC: Remapping parallel port to LPT2\n");
lpt1_setup(LPT2_ADDR);
lpt_port_setup(dev->lpt, LPT2_ADDR);
break;
default:
@@ -1063,6 +1065,8 @@ stpc_lpt_init(UNUSED(const device_t *info))
stpc_lpt_t *dev = (stpc_lpt_t *) calloc(1, sizeof(stpc_lpt_t));
dev->lpt = device_add_inst(&lpt_port_device, 1);
stpc_lpt_reset(dev);
io_sethandler(0x3f0, 2,

View File

@@ -419,6 +419,9 @@ umc_8886_init(const device_t *info)
device_add(&ide_um8673f_device);
}
if (machine_get_kbc_device(machine) == NULL)
device_add_params(&kbc_at_device, (void *) KBC_VEN_UMC);
umc_8886_reset(dev);
return dev;

View File

@@ -43,6 +43,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/keyboard.h>
#include <86box/usb.h>
#include <86box/machine.h>
#include <86box/smbus.h>
@@ -1774,6 +1775,38 @@ pipc_init(const device_t *info)
acpi_set_irq_mode(dev->acpi, 0);
}
uint32_t kbc_params = 0x00424600;
/*
NOTE: The VIA VT82C42N returns 0x46 ('F') in command 0xA1 (so it
emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in
command 0xAF.
The version on the VIA VT82C686B southbridge also returns
'F' in command 0xA1, but 0x45 ('E') in command 0xAF.
The version on the VIA VT82C586B southbridge also returns
'F' in command 0xA1, but 0x44 ('D') in command 0xAF.
The version on the VIA VT82C586A southbridge also returns
'F' in command 0xA1, but 0x43 ('C') in command 0xAF.
*/
switch (dev->local) {
/* 596A, 596B, 686B, and 8231 are guesses because we have no probes yet. */
case VIA_PIPC_586A: case VIA_PIPC_596A:
kbc_params = 0x00434600;
break;
case VIA_PIPC_586B: case VIA_PIPC_596B:
kbc_params = 0x00444600;
break;
case VIA_PIPC_686A: case VIA_PIPC_686B:
case VIA_PIPC_8231:
kbc_params = 0x00454600;
break;
}
kbc_params |= KBC_VEN_VIA;
if (machine_get_kbc_device(machine) == NULL)
device_add_params(&kbc_at_device, (void *) (uintptr_t) kbc_params);
return dev;
}

View File

@@ -193,6 +193,8 @@ vt82c49x_recalc(vt82c49x_t *dev)
default:
break;
}
flushmmucache_nopc();
}
static void

View File

@@ -81,7 +81,9 @@ typedef struct {
typedef struct
{
uint8_t ep, p92;
uint8_t addr_sel;
uint8_t addr_regs[8];
uint8_t vbios_states[4];
uint8_t bios_states[8];
uint8_t high_bios_states[8];
@@ -100,6 +102,7 @@ typedef struct
};
uint16_t ems_page_regs[40];
uint16_t lpt_base;
int locked;
@@ -113,9 +116,9 @@ typedef struct
mem_mapping_t ram_mapping;
nvr_t *nvr;
fdc_t *fdc;
serial_t *uart[2];
fdc_t *fdc;
serial_t *uart[2];
lpt_t *lpt;
} wd76c10_t;
static uint32_t bank_sizes[4] = { 0x00020000, /* 64 Kbit X 16 = 1024 Kbit = 128 kB, 8x 8 */
@@ -841,7 +844,7 @@ wd76c10_pf_loc_recalc(wd76c10_t *dev)
uint8_t ems_page;
uint32_t base;
for (uint8_t i = (0x031 + pf_loc); i <= (0x037 + pf_loc); i++) {
for (uint16_t i = (0x031 + pf_loc); i <= (0x037 + pf_loc); i++) {
ems_page = (i - 0x10) & 0xf7;
dev->mem_pages[i] = ems_page;
base = ((uint32_t) i) << 14;
@@ -873,6 +876,92 @@ wd76c10_low_pages_recalc(wd76c10_t *dev)
}
}
static void
wd73c30_reset(wd76c10_t *dev)
{
dev->addr_sel = 0x00;
dev->addr_regs[0x00] = 0x00;
dev->addr_regs[0x01] = 0x00;
dev->addr_regs[0x05] = 0x00;
serial_set_type(dev->uart[0], SERIAL_16450);
serial_set_type(dev->uart[1], SERIAL_16450);
serial_set_clock_src(dev->uart[1], 1843200.0);
serial_set_clock_src(dev->uart[0], 1843200.0);
lpt_set_ext(dev->lpt, 0);
}
static void
wd76c30_write(uint16_t port, uint8_t val, void *priv)
{
wd76c10_t *dev = (wd76c10_t *) priv;
switch (port & 0x0007) {
case 0x0003:
dev->addr_sel = val;
switch (val & 0x60) {
case 0x00:
serial_set_clock_src(dev->uart[1], 1843200.0);
break;
case 0x20:
serial_set_clock_src(dev->uart[1], 3072000.0);
break;
case 0x40:
serial_set_clock_src(dev->uart[1], 6000000.0); /* What is MSTRX1? */
break;
case 0x60:
serial_set_clock_src(dev->uart[1], 8000000.0);
break;
}
switch (val & 0x18) {
case 0x00:
serial_set_clock_src(dev->uart[0], 1843200.0);
break;
case 0x08:
serial_set_clock_src(dev->uart[0], 3072000.0);
break;
case 0x10:
serial_set_clock_src(dev->uart[0], 6000000.0); /* What is MSTRX1? */
break;
case 0x18:
serial_set_clock_src(dev->uart[0], 8000000.0);
break;
}
break;
case 0x0007:
dev->addr_regs[dev->addr_sel & 0x07] = val;
switch (dev->addr_sel & 0x07) {
case 0x05:
lpt_set_ext(dev->lpt, !!(val & 0x02));
serial_set_type(dev->uart[0], (val & 0x01) ? SERIAL_16550 : SERIAL_16450);
serial_set_type(dev->uart[1], (val & 0x01) ? SERIAL_16550 : SERIAL_16450);
break;
}
break;
}
}
static uint8_t
wd76c30_read(uint16_t port, void *priv)
{
wd76c10_t *dev = (wd76c10_t *) priv;
uint8_t ret = 0xff;
switch (port & 0x0007) {
case 0x0003:
ret = dev->addr_sel;
break;
case 0x0007:
ret = dev->addr_regs[dev->addr_sel & 0x07];
break;
}
return ret;
}
static void
wd76c10_ser_par_cs_recalc(wd76c10_t *dev)
{
@@ -911,21 +1000,24 @@ wd76c10_ser_par_cs_recalc(wd76c10_t *dev)
}
/* LPT */
lpt1_remove();
lpt_port_remove(dev->lpt);
if (dev->lpt_base != 0x0000)
io_removehandler(dev->lpt_base, 0x0008, wd76c30_read, NULL, NULL, wd76c30_write, NULL, NULL, dev);
dev->lpt_base = 0x0000;
switch ((dev->ser_par_cs >> 9) & 0x03) {
case 1:
lpt1_setup(LPT_MDA_ADDR);
lpt1_irq(LPT1_IRQ);
dev->lpt_base = LPT_MDA_ADDR;
break;
case 2:
lpt1_setup(LPT1_ADDR);
lpt1_irq(LPT1_IRQ);
dev->lpt_base = LPT1_ADDR;
break;
case 3:
lpt1_setup(LPT2_ADDR);
lpt1_irq(LPT1_IRQ);
dev->lpt_base = LPT2_ADDR;
break;
}
io_sethandler(dev->lpt_base, 0x0008, wd76c30_read, NULL, NULL, wd76c30_write, NULL, NULL, dev);
lpt_port_setup(dev->lpt, dev->lpt_base);
lpt_port_irq(dev->lpt, LPT1_IRQ);
}
static void
@@ -1173,8 +1265,8 @@ wd76c10_inw(uint16_t port, void *priv)
case 0xd072:
ret = (serial_read(0x0002, dev->uart[0]) & 0xc0) << 8;
ret |= (serial_read(0x0002, dev->uart[1]) & 0xc0) << 6;
ret |= (lpt_read_port(0, 0x0002) & 0x0f) << 8;
ret |= lpt_read_port(0, 0x0000);
ret |= (lpt_read_port(dev->lpt, 0x0002) & 0x0f) << 8;
ret |= lpt_read_port(dev->lpt, 0x0000);
break;
case 0xe072:
@@ -1188,7 +1280,7 @@ wd76c10_inw(uint16_t port, void *priv)
break;
case 0xfc72:
ret = ((lpt_read_status(0) & 0x20) >> 2);
ret = ((lpt_read_status(dev->lpt) & 0x20) >> 2);
ret |= (((uint16_t) dma_m) << 4);
ret |= dev->toggle;
dev->toggle ^= 0x8000;
@@ -1239,6 +1331,8 @@ wd76c10_reset(void *priv)
nvr_lock_set(0x38, 0x08, 0x00, dev->nvr);
wd73c30_reset(dev);
wd76c10_banks_recalc(dev);
wd76c10_split_recalc(dev);
wd76c10_dis_mem_recalc(dev);
@@ -1303,6 +1397,7 @@ wd76c10_init(UNUSED(const device_t *info))
dev->nvr = device_add(&amstrad_megapc_nvr_device);
dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2);
dev->lpt = device_add_inst(&lpt_port_device, 1);
dev->fdc = device_add(&fdc_at_device);
device_add(&ide_isa_device);

View File

@@ -3875,19 +3875,31 @@ FP_LOAD_IMM_Q(uint64_t v)
static __inline void
FP_FCHS(void)
{
addbyte(0x48); /* MOVABS RAX, 0x8000000000000000 */
addbyte(0xb8);
addquad(0x8000000000000000);
addbyte(0x66); /* MOVQ XMM15, RAX */
addbyte(0x4c);
addbyte(0x0f);
addbyte(0x6e);
addbyte(0xf8);
addbyte(0x48); /* XOR RAX, RAX */
addbyte(0x31);
addbyte(0xc0);
addbyte(0x8b); /*MOV EAX, TOP*/
addbyte(0x45);
addbyte((uint8_t) cpu_state_offset(TOP));
addbyte(0xf2); /*SUBSD XMM0, XMM0*/
addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/
addbyte(0x0f);
addbyte(0x5c);
addbyte(0xc0);
addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/
addbyte(0x0f);
addbyte(0x5c);
addbyte(0x7e);
addbyte(0x44);
addbyte(0xc5);
addbyte((uint8_t) cpu_state_offset(ST));
addbyte(0x66); /* PXOR XMM0, XMM15 */
addbyte(0x41);
addbyte(0x0F);
addbyte(0xEF);
addbyte(0xC7);
addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/
addbyte(0x64);
addbyte(0x05);

View File

@@ -636,9 +636,10 @@ codegen_FCHS(codeblock_t *block, uop_t *uop)
int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) {
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg);
host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg_a);
host_x86_MOV64_REG_IMM(block, REG_RCX, 0x8000000000000000);
host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RCX);
host_x86_PXOR_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
}
# ifdef RECOMPILER_DEBUG
else

File diff suppressed because it is too large Load Diff

View File

@@ -539,10 +539,9 @@ pfq_write(void)
static uint8_t
pfq_read(void)
{
uint8_t temp, i;
uint8_t temp = pfq[0];
temp = pfq[0];
for (i = 0; i < (pfq_size - 1); i++)
for (int i = 0; i < (pfq_size - 1); i++)
pfq[i] = pfq[i + 1];
pfq_pos--;
cpu_state.pc = (cpu_state.pc + 1) & 0xffff;

View File

@@ -283,7 +283,7 @@ reset_common(int hard)
cr0 = 1 << 30;
else
cr0 = 0;
if (is386 && !is486 && (fpu_type == FPU_387))
if (is386 && !is486 && ((fpu_type == FPU_387) || (fpu_type == FPU_NONE)))
cr0 |= 0x10;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();

View File

@@ -349,12 +349,6 @@ device_reset_all(uint32_t match_flags)
devices[c]->reset(device_priv[c]);
}
}
#ifdef UNCOMMENT_LATER
/* TODO: Actually convert the LPT devices to device_t's. */
if ((match_flags == DEVICE_ALL) || (match_flags == DEVICE_PCI))
lpt_reset();
#endif
}
void *
@@ -469,7 +463,6 @@ device_get_bios_local(const device_t *dev, const char *internal_name)
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
printf("Internal name was: %s", internal_name);
if (!strcmp(internal_name, bios->internal_name))
return bios->local;
bios++;
@@ -666,9 +659,9 @@ device_get_name(const device_t *dev, int bus, char *name)
fbus = strstr(tname, sbus);
if (fbus == tname)
strcat(name, tname + strlen(sbus) + 1);
/* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or
the "-ISA" from "AMD PCnet-ISA". */
else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-') || (*(fbus - 2) == 'r'))
/* Special case to not strip the "oPCI" from "Ensoniq AudioPCI",
the "-ISA" from "AMD PCnet-ISA" or the " PCI" from "CMD PCI-064x". */
else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-') || (*(fbus - 2) == 'r') || ((fbus[0] == 'P') && (fbus[1] == 'C') && (fbus[2] == 'I') && (fbus[3] == '-')))
strcat(name, tname);
else {
strncat(name, tname, fbus - tname - 1);

View File

@@ -38,6 +38,7 @@ add_library(dev OBJECT
isapnp.c
kbc_at.c
kbc_at_dev.c
kbc_xt.c
keyboard.c
keyboard_at.c
keyboard_xt.c
@@ -47,11 +48,13 @@ add_library(dev OBJECT
mouse_microtouch_touchscreen.c
mouse_ps2.c
mouse_serial.c
mouse_upc.c
nec_mate_unk.c
novell_cardkey.c
pci_bridge.c
phoenix_486_jumper.c
postcard.c
radisys_config.c
serial.c
serial_passthrough.c
smbus_ali7101.c
@@ -59,6 +62,7 @@ add_library(dev OBJECT
smbus_sis5595.c
tulip_jumper.c
unittester.c
zenith_scratchpad.c
)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC)

View File

@@ -152,10 +152,11 @@ pc_cas_del(pc_cassette_t *cas)
}
int
pc_cas_set_fname(pc_cassette_t *cas, const char *fname)
pc_cas_set_fname(pc_cassette_t *cas, char *fname)
{
unsigned n;
const char *ext;
int offs = 0;
if (cas->close)
fclose(cas->fp);
@@ -176,6 +177,13 @@ pc_cas_set_fname(pc_cassette_t *cas, const char *fname)
return 0;
}
if (strstr(fname, "wp://") == fname) {
offs = 5;
cassette_ui_writeprot = 1;
}
fname += offs;
cas->fp = plat_fopen(fname, "r+b");
if (cas->fp == NULL)
@@ -197,10 +205,10 @@ pc_cas_set_fname(pc_cassette_t *cas, const char *fname)
n = strlen(fname);
cas->fname = malloc((n + 1) * sizeof(char));
cas->fname = malloc((n + offs + 1) * sizeof(char));
if (cas->fname != NULL)
memcpy(cas->fname, fname, (n + 1) * sizeof(char));
memcpy(cas->fname, fname - offs, (n + offs + 1) * sizeof(char));
if (n > 4) {
ext = fname + (n - 4);
@@ -216,6 +224,8 @@ pc_cas_set_fname(pc_cassette_t *cas, const char *fname)
pc_cas_set_pcm(cas, 0);
}
ui_sb_update_icon_wp(SB_CASSETTE, cassette_ui_writeprot);
return 0;
}

View File

@@ -28,8 +28,8 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/lpt.h>
#include <86box/device.h>
#include <86box/lpt.h>
#define HASP_BYTEARRAY(...) \
{ \

View File

@@ -107,6 +107,7 @@
#define ISAMEM_BRAT_CARD 14
#define ISAMEM_EV165A_CARD 15
#define ISAMEM_LOTECH_EMS_CARD 16
#define ISAMEM_MPLUS2_CARD 17
#define ISAMEM_DEBUG 0
@@ -495,6 +496,7 @@ isamem_init(const device_t *info)
case ISAMEM_SYSTEMCARD_CARD: /* Microsoft SystemCard */
case ISAMEM_P5PAK_CARD: /* Paradise Systems 5-PAK */
case ISAMEM_A6PAK_CARD: /* AST SixPakPlus */
case ISAMEM_MPLUS2_CARD: /* AST MegaPlus II */
dev->total_size = device_get_config_int("size");
dev->start_addr = device_get_config_int("start");
tot = dev->total_size;
@@ -1391,10 +1393,10 @@ static const device_config_t ems5150_config[] = {
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0x0000 },
{ .description = "Board 1", .value = 0x0208 },
{ .description = "Board 2", .value = 0x020a },
{ .description = "Board 3", .value = 0x020c },
{ .description = "Board 4", .value = 0x020e },
{ .description = "208H", .value = 0x0208 },
{ .description = "20AH", .value = 0x020a },
{ .description = "20CH", .value = 0x020c },
{ .description = "20EH", .value = 0x020e },
{ .description = "" }
},
.bios = { { 0 } }
@@ -2094,6 +2096,54 @@ static const device_t iab_device = {
};
#endif /* USE_ISAMEM_IAB */
static const device_config_t mplus2_config[] = {
// clang-format off
{
.name = "size",
.description = "Memory Size",
.type = CONFIG_SPINNER,
.default_string = "",
.default_int = 64,
.file_filter = "",
.spinner = {
.min = 0,
.max = 512,
.step = 64
},
.selection = { { 0 } }
},
{
.name = "start",
.description = "Start Address",
.type = CONFIG_SPINNER,
.default_string = "",
.default_int = 256,
.file_filter = "",
.spinner = {
.min = 64,
.max = 576,
.step = 64
},
.selection = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_t mplus2_device = {
.name = "AST MegaPlus II",
.internal_name = "mplus2",
.flags = DEVICE_ISA,
.local = ISAMEM_MPLUS2_CARD,
.init = isamem_init,
.close = isamem_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = mplus2_config
};
static const struct {
const device_t *dev;
} boards[] = {
@@ -2127,6 +2177,7 @@ static const struct {
{ &iab_device },
#endif /* USE_ISAMEM_IAB */
{ &lotech_ems_device },
{ &mplus2_device },
{ NULL }
// clang-format on
};

View File

@@ -1117,13 +1117,17 @@ isapnp_enable_card(void *priv, uint8_t enable)
/* Enable or disable the card. */
if (!!enable ^ !!card->enable)
card->state = (enable == ISAPNP_CARD_FORCE_CONFIG) ? PNP_STATE_CONFIG : PNP_STATE_WAIT_FOR_KEY;
int old_enable = card->enable;
card->enable = enable;
/* Invalidate other references if we're disabling this card. */
if (!card->enable) {
if ((card->enable) && (dev->current_ld_card != NULL) && (dev->current_ld_card != card)) {
dev->current_ld = NULL;
dev->current_ld_card = NULL;
} if (!card->enable) {
if (dev->isolated_card == card)
dev->isolated_card = NULL;
if (dev->current_ld_card == card) {
if ((dev->current_ld_card == card) && (old_enable != ISAPNP_CARD_FORCE_CONFIG)) {
dev->current_ld = NULL;
dev->current_ld_card = NULL;
}

View File

@@ -248,7 +248,7 @@ static const device_config_t isarom_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -557,7 +557,7 @@ static const device_config_t isarom_quad_config[] = {
static const device_config_t lba_enhancer_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,

View File

@@ -89,10 +89,11 @@
#define ISARTC_P5PAK 2
#define ISARTC_A6PAK 3
#define ISARTC_VENDEX 4
#define ISARTC_MPLUS2 5
#define ISARTC_MM58167 10
#define ISARTC_ROM_MM58167_1 "roms/rtc/glatick/GLaTICK_0.8.5_NS_RP.ROM"
#define ISARTC_ROM_MM58167_2 "roms/rtc/glatick/GLaTICK_0.8.5_86B.ROM"
#define ISARTC_ROM_MM58167_1 "roms/rtc/glatick/GLaTICK_0.8.8_NS_86B.ROM" /* Generic 58167, AST or EV-170 */
#define ISARTC_ROM_MM58167_2 "roms/rtc/glatick/GLaTICK_0.8.8_NS_86B2.ROM" /* PII-147 */
#define ISARTC_DEBUG 0
@@ -409,6 +410,7 @@ mm67_read(uint16_t port, void *priv)
break;
case MM67_AL_MSEC:
case MM67_MSEC:
ret = dev->nvr.regs[reg] & 0xf0;
break;
@@ -416,6 +418,10 @@ mm67_read(uint16_t port, void *priv)
ret = dev->nvr.regs[reg] & 0x0f;
break;
case MM67_DOW:
ret = dev->nvr.regs[reg] & 0x07;
break;
default:
ret = dev->nvr.regs[reg];
break;
@@ -563,8 +569,9 @@ isartc_init(const device_t *info)
dev->year = MM67_AL_HUNTEN; /* year, NON STANDARD */
break;
case ISARTC_P5PAK: /* Paradise Systems 5PAK */
case ISARTC_A6PAK: /* AST SixPakPlus */
case ISARTC_P5PAK: /* Paradise Systems 5PAK */
case ISARTC_A6PAK: /* AST SixPakPlus */
case ISARTC_MPLUS2: /* AST MegaPlus II */
dev->flags |= FLAG_YEAR80;
dev->base_addr = 0x02c0;
dev->base_addrsz = 32;
@@ -786,6 +793,42 @@ static const device_t a6pak_device = {
.config = a6pak_config
};
static const device_config_t mplus2_config[] = {
// clang-format off
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = -1,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ "Disabled", -1 },
{ "IRQ2", 2 },
{ "IRQ3", 3 },
{ "IRQ5", 5 },
{ "" }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_t mplus2_device = {
.name = "AST MegaPlus II",
.internal_name = "mplus2",
.flags = DEVICE_ISA,
.local = ISARTC_MPLUS2,
.init = isartc_init,
.close = isartc_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = mplus2_config
};
static const device_config_t mm58167_config[] = {
// clang-format off
{
@@ -823,7 +866,7 @@ static const device_config_t mm58167_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xcc000,
@@ -897,6 +940,7 @@ static const struct {
{ &pii147_device },
{ &p5pak_device },
{ &a6pak_device },
{ &mplus2_device },
{ &mm58167_device },
{ NULL }
// clang-format on

File diff suppressed because it is too large Load Diff

View File

@@ -8,11 +8,9 @@
*
* AT / PS/2 attached device emulation.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 Miran Grca.
* Copyright 2023-2025 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
@@ -22,23 +20,9 @@
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/ppi.h>
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/m_at_t3100e.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/sound.h>
#include <86box/snd_speaker.h>
#include <86box/video.h>
#include <86box/keyboard.h>
#include <86box/plat_fallthrough.h>
#include <86box/keyboard.h>
#ifdef ENABLE_KBC_AT_DEV_LOG
int kbc_at_dev_do_log = ENABLE_KBC_AT_DEV_LOG;

903
src/device/kbc_xt.c Normal file
View File

@@ -0,0 +1,903 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the XT-style keyboard.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* EngiNerd, <webmaster.crrc@yahoo.it>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van kempen.
* Copyright 2020 EngiNerd.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/fdd.h>
#include <86box/machine.h>
#include <86box/m_xt_t1000.h>
#include <86box/cassette.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/ppi.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/sound.h>
#include <86box/snd_speaker.h>
#include <86box/video.h>
#include <86box/keyboard.h>
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
#define STAT_TTIMEOUT 0x20
#define STAT_LOCK 0x10
#define STAT_CD 0x08
#define STAT_SYSFLAG 0x04
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
/* Keyboard Types */
enum {
KBD_TYPE_PC81 = 0,
KBD_TYPE_PC82,
KBD_TYPE_XT82,
KBD_TYPE_XT86,
KBD_TYPE_COMPAQ,
KBD_TYPE_TANDY,
KBD_TYPE_TOSHIBA,
KBD_TYPE_VTECH,
KBD_TYPE_OLIVETTI,
KBD_TYPE_ZENITH,
KBD_TYPE_PRAVETZ,
KBD_TYPE_HYUNDAI,
KBD_TYPE_FE2010,
KBD_TYPE_XTCLONE
};
typedef struct xtkbd_t {
int want_irq;
int blocked;
int tandy;
uint8_t pa;
uint8_t pb;
uint8_t pd;
uint8_t cfg;
uint8_t clock;
uint8_t key_waiting;
uint8_t type;
uint8_t pravetz_flags;
uint8_t cpu_speed;
pc_timer_t send_delay_timer;
} xtkbd_t;
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
static int is_tandy = 0;
static int is_t1x00 = 0;
static int is_amstrad = 0;
#ifdef ENABLE_KEYBOARD_XT_LOG
int keyboard_xt_do_log = ENABLE_KEYBOARD_XT_LOG;
static void
kbd_log(const char *fmt, ...)
{
va_list ap;
if (keyboard_xt_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define kbd_log(fmt, ...)
#endif
static uint8_t
get_fdd_switch_settings(void)
{
uint8_t fdd_count = 0;
for (uint8_t i = 0; i < FDD_NUM; i++) {
if (fdd_get_flags(i))
fdd_count++;
}
if (!fdd_count)
return 0x00;
else
return ((fdd_count - 1) << 6) | 0x01;
}
static uint8_t
get_videomode_switch_settings(void)
{
if (video_is_mda())
return 0x30;
else if (video_is_cga())
return 0x20; /* 0x10 would be 40x25 */
else
return 0x00;
}
static void
kbd_poll(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC);
if (!(kbd->pb & 0x40) && (kbd->type != KBD_TYPE_TANDY))
return;
if (kbd->want_irq) {
kbd->want_irq = 0;
kbd->pa = kbd->key_waiting;
kbd->blocked = 1;
picint(2);
#ifdef ENABLE_KEYBOARD_XT_LOG
kbd_log("XTkbd: kbd_poll(): keyboard_xt : take IRQ\n");
#endif
}
if ((key_queue_start != key_queue_end) && !kbd->blocked) {
kbd->key_waiting = key_queue[key_queue_start];
kbd_log("XTkbd: reading %02X from the key queue at %i\n",
kbd->key_waiting, key_queue_start);
key_queue_start = (key_queue_start + 1) & 0x0f;
kbd->want_irq = 1;
}
}
static void
kbd_adddata(uint16_t val)
{
/* Test for T1000 'Fn' key (Right Alt / Right Ctrl) */
if (is_t1x00) {
if (keyboard_recv(0x138) || keyboard_recv(0x11d)) { /* 'Fn' pressed */
t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */
switch (val) {
case 0x45: /* Num Lock => toggle numpad */
t1000_syskey(0x00, 0x00, 0x10);
break;
case 0x47: /* Home => internal display */
t1000_syskey(0x40, 0x00, 0x00);
break;
case 0x49: /* PgDn => turbo on */
t1000_syskey(0x80, 0x00, 0x00);
break;
case 0x4D: /* Right => toggle LCD font */
t1000_syskey(0x00, 0x00, 0x20);
break;
case 0x4F: /* End => external display */
t1000_syskey(0x00, 0x40, 0x00);
break;
case 0x51: /* PgDn => turbo off */
t1000_syskey(0x00, 0x80, 0x00);
break;
case 0x54: /* SysRQ => toggle window */
t1000_syskey(0x00, 0x00, 0x08);
break;
default:
break;
}
} else
t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */
}
key_queue[key_queue_end] = val;
kbd_log("XTkbd: %02X added to key queue at %i\n",
val, key_queue_end);
key_queue_end = (key_queue_end + 1) & 0x0f;
}
void
kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val))
{
uint8_t num_lock = 0;
uint8_t shift_states = 0;
if (!adddata)
return;
keyboard_get_states(NULL, &num_lock, NULL, NULL);
shift_states = keyboard_get_shift() & STATE_LSHIFT;
if (is_amstrad)
num_lock = !num_lock;
/* If NumLock is on, invert the left shift state so we can always check for
the the same way flag being set (and with NumLock on that then means it
is actually *NOT* set). */
if (num_lock)
shift_states ^= STATE_LSHIFT;
switch (val) {
case FAKE_LSHIFT_ON:
/* If NumLock is on, fake shifts are sent when shift is *NOT* presed,
if NumLock is off, fake shifts are sent when shift is pressed. */
if (shift_states) {
/* Send fake shift. */
adddata(num_lock ? 0x2a : 0xaa);
}
break;
case FAKE_LSHIFT_OFF:
if (shift_states) {
/* Send fake shift. */
adddata(num_lock ? 0xaa : 0x2a);
}
break;
default:
adddata(val);
break;
}
}
static void
kbd_adddata_ex(uint16_t val)
{
kbd_adddata_process(val, kbd_adddata);
}
static void
kbd_write(uint16_t port, uint8_t val, void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
uint8_t bit;
uint8_t set;
uint8_t new_clock;
switch (port) {
case 0x61: /* Keyboard Control Register (aka Port B) */
if (!(val & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) {
new_clock = !!(val & 0x40);
if (!kbd->clock && new_clock) {
key_queue_start = key_queue_end = 0;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd_adddata(0xaa);
}
}
kbd->pb = val;
if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI))
kbd->clock = !!(kbd->pb & 0x40);
ppi.pb = val;
timer_process();
if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) && (cassette != NULL))
pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0);
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
if (speaker_enable)
was_speaker_enable = 1;
pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1);
if (val & 0x80) {
kbd->pa = 0;
kbd->blocked = 0;
picintc(2);
}
#ifdef ENABLE_KEYBOARD_XT_LOG
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ))
kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF");
#endif
break;
case 0x62: /* Switch Register (aka Port C) */
#ifdef ENABLE_KEYBOARD_XT_LOG
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ))
kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10));
#endif
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Switch register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->pd = (kbd->pd & 0x30) | (val & 0xcf);
}
break;
case 0x63:
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Configuration register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->cfg = val;
}
break;
case 0xc0 ... 0xcf: /* Pravetz Flags */
kbd_log("XTkbd: Port %02X out: %02X\n", port, val);
if (kbd->type == KBD_TYPE_PRAVETZ) {
bit = (port >> 1) & 0x07;
set = (port & 0x01) << bit;
kbd->pravetz_flags = (kbd->pravetz_flags & ~(1 << bit)) | set;
}
break;
case 0x1f0:
kbd_log("XTkbd: Port %04X out: %02X\n", port, val);
if (kbd->type == KBD_TYPE_VTECH) {
kbd->cpu_speed = val;
cpu_dynamic_switch(kbd->cpu_speed >> 7);
}
break;
default:
break;
}
}
static uint8_t
kbd_read(uint16_t port, void *priv)
{
const xtkbd_t *kbd = (xtkbd_t *) priv;
uint8_t ret = 0xff;
switch (port) {
case 0x60: /* Keyboard Data Register (aka Port A) */
if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) ||
(kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) ||
(kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))) {
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI))
ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00);
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_VTECH))
/* According to Ruud on the PCem forum, this is supposed to
return 0xFF on the XT. */
ret = 0xff;
else if (kbd->type == KBD_TYPE_ZENITH) {
/* Zenith Data Systems Z-151
* SW1 switch settings:
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bit 2-3: base memory size
* bit 1: fpu enable
* bit 0: fdc enable
*/
ret = get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
/* Base memory size should always be 64k */
ret |= 0x0c;
if (hasfpu)
ret |= 0x02;
}
} else
ret = kbd->pa;
break;
case 0x61: /* Keyboard Control Register (aka Port B) */
ret = kbd->pb;
break;
case 0x62: /* Switch Register (aka Port C) */
if (kbd->type == KBD_TYPE_FE2010) {
if (kbd->pb & 0x04) /* PB2 */
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
else
ret = kbd->pd >> 4;
} else if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) {
if (kbd->pb & 0x04) /* PB2 */
switch (mem_size + isa_mem_size) {
case 64:
case 48:
case 32:
case 16:
ret = 0x00;
break;
default:
ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f;
break;
}
else
ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4;
} else if ((kbd->type == KBD_TYPE_OLIVETTI) ||
(kbd->type == KBD_TYPE_ZENITH)) {
/* Olivetti M19 or Zenith Data Systems Z-151 */
if (kbd->pb & 0x04) /* PB2 */
ret = kbd->pd & 0xbf;
else
ret = kbd->pd >> 4;
} else {
if (kbd->pb & 0x08) /* PB3 */
ret = kbd->pd >> 4;
else
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
}
ret |= (ppispeakon ? 0x20 : 0);
/* This is needed to avoid error 131 (cassette error).
This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) {
if (cassette == NULL)
ret |= (ppispeakon ? 0x10 : 0);
else
ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0);
}
if (kbd->type == KBD_TYPE_TANDY)
ret |= (tandy1k_eeprom_read() ? 0x10 : 0);
break;
case 0x63: /* Keyboard Configuration Register (aka Port D) */
if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))
ret = kbd->pd;
break;
case 0xc0: /* Pravetz Flags */
if (kbd->type == KBD_TYPE_PRAVETZ)
ret = kbd->pravetz_flags;
kbd_log("XTkbd: Port %02X in : %02X\n", port, ret);
break;
case 0x1f0:
if (kbd->type == KBD_TYPE_VTECH)
ret = kbd->cpu_speed;
kbd_log("XTkbd: Port %04X in : %02X\n", port, ret);
break;
default:
break;
}
return ret;
}
static void
kbd_reset(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd->pa = 0x00;
kbd->pb = 0x00;
kbd->pravetz_flags = 0x00;
keyboard_scan = 1;
key_queue_start = 0;
key_queue_end = 0;
}
void
keyboard_set_is_amstrad(int ams)
{
is_amstrad = ams;
}
static void *
kbd_init(const device_t *info)
{
xtkbd_t *kbd;
kbd = (xtkbd_t *) calloc(1, sizeof(xtkbd_t));
io_sethandler(0x0060, 4,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
keyboard_send = kbd_adddata_ex;
kbd->type = info->local;
if (kbd->type == KBD_TYPE_VTECH)
kbd->cpu_speed = (!!cpu) << 2;
kbd_reset(kbd);
if (kbd->type == KBD_TYPE_PRAVETZ)
io_sethandler(0x00c0, 16,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
if (kbd->type == KBD_TYPE_VTECH)
io_sethandler(0x01f0, 1,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
key_queue_start = key_queue_end = 0;
video_reset(gfxcard[0]);
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) ||
(kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) ||
(kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH) || (kbd->type == KBD_TYPE_FE2010)) {
/* DIP switch readout: bit set = OFF, clear = ON. */
if (kbd->type == KBD_TYPE_OLIVETTI)
/* Olivetti M19
* Jumpers J1, J2 - monitor type.
* 01 - mono (high-res)
* 10 - color (low-res, disables 640x400x2 mode)
* 00 - autoswitching
*/
kbd->pd |= 0x00;
else
/* Switches 7, 8 - floppy drives. */
kbd->pd = get_fdd_switch_settings();
/* Switches 5, 6 - video card type */
kbd->pd |= get_videomode_switch_settings();
/* Switches 3, 4 - memory size. */
if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_FE2010)) {
switch (mem_size) {
case 256:
kbd->pd |= 0x00;
break;
case 512:
kbd->pd |= 0x04;
break;
case 576:
kbd->pd |= 0x08;
break;
case 640:
default:
kbd->pd |= 0x0c;
break;
}
} else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_VTECH)) {
switch (mem_size) {
case 64: /* 1x64k */
kbd->pd |= 0x00;
break;
case 128: /* 2x64k */
kbd->pd |= 0x04;
break;
case 192: /* 3x64k */
kbd->pd |= 0x08;
break;
case 256: /* 4x64k */
default:
kbd->pd |= 0x0c;
break;
}
} else if (kbd->type == KBD_TYPE_PC82) {
switch (mem_size) {
#ifdef PC82_192K_3BANK
case 192: /* 3x64k, not supported by stock BIOS due to bugs */
kbd->pd |= 0x08;
break;
#else
case 192: /* 2x64k + 2x32k */
#endif
case 64: /* 4x16k */
case 96: /* 2x32k + 2x16k */
case 128: /* 4x32k */
case 160: /* 2x64k + 2x16k */
case 224: /* 3x64k + 1x32k */
case 256: /* 4x64k */
default:
kbd->pd |= 0x0c;
break;
}
} else { /* really just the PC '81 */
switch (mem_size) {
case 16: /* 1x16k */
kbd->pd |= 0x00;
break;
case 32: /* 2x16k */
kbd->pd |= 0x04;
break;
case 48: /* 3x16k */
kbd->pd |= 0x08;
break;
case 64: /* 4x16k */
default:
kbd->pd |= 0x0c;
break;
}
}
/* Switch 2 - 8087 FPU. */
if (hasfpu)
kbd->pd |= 0x02;
} else if (kbd->type == KBD_TYPE_ZENITH) {
/* Zenith Data Systems Z-151
* SW2 switch settings:
* bit 7: monitor frequency
* bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd)
* bits 0-4: installed memory
*/
kbd->pd = 0x20;
switch (mem_size) {
case 128:
kbd->pd |= 0x02;
break;
case 192:
kbd->pd |= 0x04;
break;
case 256:
kbd->pd |= 0x06;
break;
case 320:
kbd->pd |= 0x08;
break;
case 384:
kbd->pd |= 0x0a;
break;
case 448:
kbd->pd |= 0x0c;
break;
case 512:
kbd->pd |= 0x0e;
break;
case 576:
kbd->pd |= 0x10;
break;
case 640:
default:
kbd->pd |= 0x12;
break;
}
}
timer_add(&kbd->send_delay_timer, kbd_poll, kbd, 1);
is_tandy = (kbd->type == KBD_TYPE_TANDY);
is_t1x00 = (kbd->type == KBD_TYPE_TOSHIBA);
if (keyboard_type == KEYBOARD_TYPE_INTERNAL)
keyboard_set_table(scancode_xt);
else
keyboard_add_device();
is_amstrad = 0;
return kbd;
}
static void
kbd_close(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
/* Stop the timer. */
timer_disable(&kbd->send_delay_timer);
/* Disable scanning. */
keyboard_scan = 0;
keyboard_send = NULL;
io_removehandler(0x0060, 4,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
free(kbd);
}
const device_t kbc_pc_device = {
.name = "IBM PC Keyboard Controller (1981)",
.internal_name = "kbc_pc",
.flags = 0,
.local = KBD_TYPE_PC81,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_pc82_device = {
.name = "IBM PC Keyboard Controller (1982)",
.internal_name = "kbc_pc82",
.flags = 0,
.local = KBD_TYPE_PC82,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_pravetz_device = {
.name = "Pravetz Keyboard Controller",
.internal_name = "kbc_pravetz",
.flags = 0,
.local = KBD_TYPE_PRAVETZ,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_device = {
.name = "XT (1982) Keyboard Controller",
.internal_name = "kbc_xt",
.flags = 0,
.local = KBD_TYPE_XT82,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt86_device = {
.name = "XT (1986) Keyboard Controller",
.internal_name = "kbc_xt86",
.flags = 0,
.local = KBD_TYPE_XT86,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_compaq_device = {
.name = "Compaq Portable Keyboard Controller",
.internal_name = "kbc_xt_compaq",
.flags = 0,
.local = KBD_TYPE_COMPAQ,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_tandy_device = {
.name = "Tandy 1000 Keyboard Controller",
.internal_name = "kbc_tandy",
.flags = 0,
.local = KBD_TYPE_TANDY,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_t1x00_device = {
.name = "Toshiba T1x00 Keyboard Controller",
.internal_name = "kbc_xt_t1x00",
.flags = 0,
.local = KBD_TYPE_TOSHIBA,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_lxt3_device = {
.name = "VTech Laser Turbo XT Keyboard Controller",
.internal_name = "kbc_xt_lxt",
.flags = 0,
.local = KBD_TYPE_VTECH,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_olivetti_device = {
.name = "Olivetti XT Keyboard Controller",
.internal_name = "kbc_xt_olivetti",
.flags = 0,
.local = KBD_TYPE_OLIVETTI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_zenith_device = {
.name = "Zenith XT Keyboard Controller",
.internal_name = "kbc_xt_zenith",
.flags = 0,
.local = KBD_TYPE_ZENITH,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_hyundai_device = {
.name = "Hyundai XT Keyboard Controller",
.internal_name = "kbc_xt_hyundai",
.flags = 0,
.local = KBD_TYPE_HYUNDAI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xt_fe2010_device = {
.name = "Faraday FE2010 XT Keyboard Controller",
.internal_name = "kbc_xt_fe2010",
.flags = 0,
.local = KBD_TYPE_FE2010,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t kbc_xtclone_device = {
.name = "XT (Clone) Keyboard Controller",
.internal_name = "kbc_xtclone",
.flags = 0,
.local = KBD_TYPE_XTCLONE,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -27,6 +27,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/machine.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/plat.h>
@@ -36,6 +37,38 @@ uint16_t scancode_map[768] = { 0 };
int keyboard_scan;
typedef struct keyboard_t {
const device_t *device;
} keyboard_t;
int keyboard_type = 0;
static const device_t keyboard_internal_device = {
.name = "Internal",
.internal_name = "internal",
.flags = 0,
.local = KEYBOARD_TYPE_INTERNAL,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
static keyboard_t keyboard_devices[] = {
// clang-format off
{ &keyboard_internal_device },
{ &keyboard_pc_xt_device },
{ &keyboard_at_device },
{ &keyboard_ax_device },
{ &keyboard_ps2_device },
{ &keyboard_ps55_device },
{ NULL }
// clang-format on
};
#ifdef ENABLE_KBC_AT_LOG
int kbc_at_do_log = ENABLE_KBC_AT_LOG;
@@ -516,3 +549,57 @@ convert_scan_code(uint16_t scan_code)
return scan_code;
}
const char *
keyboard_get_name(int keyboard)
{
return (keyboard_devices[keyboard].device->name);
}
const char *
keyboard_get_internal_name(int keyboard)
{
return device_get_internal_name(keyboard_devices[keyboard].device);
}
int
keyboard_get_from_internal_name(char *s)
{
int c = 0;
while (keyboard_devices[c].device != NULL) {
if (!strcmp((char *) keyboard_devices[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
int
keyboard_has_config(int keyboard)
{
if (keyboard_devices[keyboard].device == NULL)
return 0;
return (keyboard_devices[keyboard].device->config ? 1 : 0);
}
const device_t *
keyboard_get_device(int keyboard)
{
return (keyboard_devices[keyboard].device);
}
/* Return number of MOUSE types we know about. */
int
keyboard_get_ndev(void)
{
return ((sizeof(keyboard_devices) / sizeof(keyboard_t)) - 1);
}
void
keyboard_add_device(void)
{
device_add(keyboard_devices[keyboard_type].device);
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,62 +35,8 @@
#include <86box/machine.h>
#include <86box/m_xt_t1000.h>
#include <86box/cassette.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/ppi.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/sound.h>
#include <86box/snd_speaker.h>
#include <86box/video.h>
#include <86box/keyboard.h>
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
#define STAT_TTIMEOUT 0x20
#define STAT_LOCK 0x10
#define STAT_CD 0x08
#define STAT_SYSFLAG 0x04
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
/* Keyboard Types */
enum {
KBD_TYPE_PC81 = 0,
KBD_TYPE_PC82,
KBD_TYPE_XT82,
KBD_TYPE_XT86,
KBD_TYPE_COMPAQ,
KBD_TYPE_TANDY,
KBD_TYPE_TOSHIBA,
KBD_TYPE_VTECH,
KBD_TYPE_OLIVETTI,
KBD_TYPE_ZENITH,
KBD_TYPE_PRAVETZ,
KBD_TYPE_HYUNDAI,
KBD_TYPE_FE2010,
KBD_TYPE_XTCLONE
};
typedef struct xtkbd_t {
int want_irq;
int blocked;
int tandy;
uint8_t pa;
uint8_t pb;
uint8_t pd;
uint8_t cfg;
uint8_t clock;
uint8_t key_waiting;
uint8_t type;
uint8_t pravetz_flags;
uint8_t cpu_speed;
pc_timer_t send_delay_timer;
} xtkbd_t;
/*XT keyboard has no escape scancodes, and no scancodes beyond 53*/
const scancode scancode_xt[512] = {
// clang-format off
@@ -609,810 +555,66 @@ const scancode scancode_xt[512] = {
// clang-format on
};
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
static int is_tandy = 0;
static int is_t1x00 = 0;
static int is_amstrad = 0;
#ifdef ENABLE_KEYBOARD_XT_LOG
int keyboard_xt_do_log = ENABLE_KEYBOARD_XT_LOG;
static void
kbd_log(const char *fmt, ...)
{
va_list ap;
if (keyboard_xt_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define kbd_log(fmt, ...)
#endif
static uint8_t
get_fdd_switch_settings(void)
{
uint8_t fdd_count = 0;
for (uint8_t i = 0; i < FDD_NUM; i++) {
if (fdd_get_flags(i))
fdd_count++;
}
if (!fdd_count)
return 0x00;
else
return ((fdd_count - 1) << 6) | 0x01;
}
static uint8_t
get_videomode_switch_settings(void)
{
if (video_is_mda())
return 0x30;
else if (video_is_cga())
return 0x20; /* 0x10 would be 40x25 */
else
return 0x00;
}
static void
kbd_poll(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC);
if (!(kbd->pb & 0x40) && (kbd->type != KBD_TYPE_TANDY))
return;
if (kbd->want_irq) {
kbd->want_irq = 0;
kbd->pa = kbd->key_waiting;
kbd->blocked = 1;
picint(2);
#ifdef ENABLE_KEYBOARD_XT_LOG
kbd_log("XTkbd: kbd_poll(): keyboard_xt : take IRQ\n");
#endif
}
if ((key_queue_start != key_queue_end) && !kbd->blocked) {
kbd->key_waiting = key_queue[key_queue_start];
kbd_log("XTkbd: reading %02X from the key queue at %i\n",
kbd->key_waiting, key_queue_start);
key_queue_start = (key_queue_start + 1) & 0x0f;
kbd->want_irq = 1;
}
}
static void
kbd_adddata(uint16_t val)
{
/* Test for T1000 'Fn' key (Right Alt / Right Ctrl) */
if (is_t1x00) {
if (keyboard_recv(0x138) || keyboard_recv(0x11d)) { /* 'Fn' pressed */
t1000_syskey(0x00, 0x04, 0x00); /* Set 'Fn' indicator */
switch (val) {
case 0x45: /* Num Lock => toggle numpad */
t1000_syskey(0x00, 0x00, 0x10);
break;
case 0x47: /* Home => internal display */
t1000_syskey(0x40, 0x00, 0x00);
break;
case 0x49: /* PgDn => turbo on */
t1000_syskey(0x80, 0x00, 0x00);
break;
case 0x4D: /* Right => toggle LCD font */
t1000_syskey(0x00, 0x00, 0x20);
break;
case 0x4F: /* End => external display */
t1000_syskey(0x00, 0x40, 0x00);
break;
case 0x51: /* PgDn => turbo off */
t1000_syskey(0x00, 0x80, 0x00);
break;
case 0x54: /* SysRQ => toggle window */
t1000_syskey(0x00, 0x00, 0x08);
break;
default:
break;
}
} else
t1000_syskey(0x04, 0x00, 0x00); /* Reset 'Fn' indicator */
}
key_queue[key_queue_end] = val;
kbd_log("XTkbd: %02X added to key queue at %i\n",
val, key_queue_end);
key_queue_end = (key_queue_end + 1) & 0x0f;
}
void
kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val))
{
uint8_t num_lock = 0;
uint8_t shift_states = 0;
if (!adddata)
return;
keyboard_get_states(NULL, &num_lock, NULL, NULL);
shift_states = keyboard_get_shift() & STATE_LSHIFT;
if (is_amstrad)
num_lock = !num_lock;
/* If NumLock is on, invert the left shift state so we can always check for
the the same way flag being set (and with NumLock on that then means it
is actually *NOT* set). */
if (num_lock)
shift_states ^= STATE_LSHIFT;
switch (val) {
case FAKE_LSHIFT_ON:
/* If NumLock is on, fake shifts are sent when shift is *NOT* presed,
if NumLock is off, fake shifts are sent when shift is pressed. */
if (shift_states) {
/* Send fake shift. */
adddata(num_lock ? 0x2a : 0xaa);
}
break;
case FAKE_LSHIFT_OFF:
if (shift_states) {
/* Send fake shift. */
adddata(num_lock ? 0xaa : 0x2a);
}
break;
default:
adddata(val);
break;
}
}
static void
kbd_adddata_ex(uint16_t val)
{
kbd_adddata_process(val, kbd_adddata);
}
static void
kbd_write(uint16_t port, uint8_t val, void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
uint8_t bit;
uint8_t set;
uint8_t new_clock;
switch (port) {
case 0x61: /* Keyboard Control Register (aka Port B) */
if (!(val & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) {
new_clock = !!(val & 0x40);
if (!kbd->clock && new_clock) {
key_queue_start = key_queue_end = 0;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd_adddata(0xaa);
}
}
kbd->pb = val;
if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI))
kbd->clock = !!(kbd->pb & 0x40);
ppi.pb = val;
timer_process();
if (((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) && (cassette != NULL))
pc_cas_set_motor(cassette, (kbd->pb & 0x08) == 0);
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
if (speaker_enable)
was_speaker_enable = 1;
pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1);
if (val & 0x80) {
kbd->pa = 0;
kbd->blocked = 0;
picintc(2);
}
#ifdef ENABLE_KEYBOARD_XT_LOG
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ))
kbd_log("XTkbd: Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF");
#endif
break;
case 0x62: /* Switch Register (aka Port C) */
#ifdef ENABLE_KEYBOARD_XT_LOG
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ))
kbd_log("XTkbd: Cassette IN is %i\n", !!(val & 0x10));
#endif
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Switch register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->pd = (kbd->pd & 0x30) | (val & 0xcf);
}
break;
case 0x63:
if (kbd->type == KBD_TYPE_FE2010) {
kbd_log("XTkbd: Configuration register in is %02X\n", val);
if (!(kbd->cfg & 0x08))
kbd->cfg = val;
}
break;
case 0xc0 ... 0xcf: /* Pravetz Flags */
kbd_log("XTkbd: Port %02X out: %02X\n", port, val);
if (kbd->type == KBD_TYPE_PRAVETZ) {
bit = (port >> 1) & 0x07;
set = (port & 0x01) << bit;
kbd->pravetz_flags = (kbd->pravetz_flags & ~(1 << bit)) | set;
}
break;
case 0x1f0:
kbd_log("XTkbd: Port %04X out: %02X\n", port, val);
if (kbd->type == KBD_TYPE_VTECH) {
kbd->cpu_speed = val;
cpu_dynamic_switch(kbd->cpu_speed >> 7);
}
break;
default:
break;
}
}
static uint8_t
kbd_read(uint16_t port, void *priv)
{
const xtkbd_t *kbd = (xtkbd_t *) priv;
uint8_t ret = 0xff;
switch (port) {
case 0x60: /* Keyboard Data Register (aka Port A) */
if ((kbd->pb & 0x80) && ((kbd->type == KBD_TYPE_PC81) ||
(kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) ||
(kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))) {
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI))
ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00);
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_VTECH))
/* According to Ruud on the PCem forum, this is supposed to
return 0xFF on the XT. */
ret = 0xff;
else if (kbd->type == KBD_TYPE_ZENITH) {
/* Zenith Data Systems Z-151
* SW1 switch settings:
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bit 2-3: base memory size
* bit 1: fpu enable
* bit 0: fdc enable
*/
ret = get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
/* Base memory size should always be 64k */
ret |= 0x0c;
if (hasfpu)
ret |= 0x02;
}
} else
ret = kbd->pa;
break;
case 0x61: /* Keyboard Control Register (aka Port B) */
ret = kbd->pb;
break;
case 0x62: /* Switch Register (aka Port C) */
if (kbd->type == KBD_TYPE_FE2010) {
if (kbd->pb & 0x04) /* PB2 */
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
else
ret = kbd->pd >> 4;
} else if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) {
if (kbd->pb & 0x04) /* PB2 */
switch (mem_size + isa_mem_size) {
case 64:
case 48:
case 32:
case 16:
ret = 0x00;
break;
default:
ret = (((mem_size + isa_mem_size) - 64) / 32) & 0x0f;
break;
}
else
ret = (((mem_size + isa_mem_size) - 64) / 32) >> 4;
} else if ((kbd->type == KBD_TYPE_OLIVETTI) ||
(kbd->type == KBD_TYPE_ZENITH)) {
/* Olivetti M19 or Zenith Data Systems Z-151 */
if (kbd->pb & 0x04) /* PB2 */
ret = kbd->pd & 0xbf;
else
ret = kbd->pd >> 4;
} else {
if (kbd->pb & 0x08) /* PB3 */
ret = kbd->pd >> 4;
else
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
}
ret |= (ppispeakon ? 0x20 : 0);
/* This is needed to avoid error 131 (cassette error).
This is serial read: bit 5 = clock, bit 4 = data, cassette header is 256 x 0xff. */
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ)) {
if (cassette == NULL)
ret |= (ppispeakon ? 0x10 : 0);
else
ret |= (pc_cas_get_inp(cassette) ? 0x10 : 0);
}
if (kbd->type == KBD_TYPE_TANDY)
ret |= (tandy1k_eeprom_read() ? 0x10 : 0);
break;
case 0x63: /* Keyboard Configuration Register (aka Port D) */
if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))
ret = kbd->pd;
break;
case 0xc0: /* Pravetz Flags */
if (kbd->type == KBD_TYPE_PRAVETZ)
ret = kbd->pravetz_flags;
kbd_log("XTkbd: Port %02X in : %02X\n", port, ret);
break;
case 0x1f0:
if (kbd->type == KBD_TYPE_VTECH)
ret = kbd->cpu_speed;
kbd_log("XTkbd: Port %04X in : %02X\n", port, ret);
break;
default:
break;
}
return ret;
}
static void
kbd_reset(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
kbd->want_irq = 0;
kbd->blocked = 0;
kbd->pa = 0x00;
kbd->pb = 0x00;
kbd->pravetz_flags = 0x00;
keyboard_scan = 1;
key_queue_start = 0;
key_queue_end = 0;
}
void
keyboard_set_is_amstrad(int ams)
{
is_amstrad = ams;
}
typedef struct {
int type;
} kbd_t;
static void *
kbd_init(const device_t *info)
{
xtkbd_t *kbd;
kbd_t *dev = (kbd_t *) calloc(1, sizeof(kbd_t));
kbd = (xtkbd_t *) calloc(1, sizeof(xtkbd_t));
dev->type = info->local;
io_sethandler(0x0060, 4,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
keyboard_send = kbd_adddata_ex;
kbd->type = info->local;
if (kbd->type == KBD_TYPE_VTECH)
kbd->cpu_speed = (!!cpu) << 2;
kbd_reset(kbd);
if (kbd->type == KBD_TYPE_PRAVETZ)
io_sethandler(0x00c0, 16,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
if (kbd->type == KBD_TYPE_VTECH)
io_sethandler(0x01f0, 1,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
if (dev->type == KBD_83_KEY)
keyboard_set_table(scancode_xt);
else
keyboard_set_table(scancode_set1);
key_queue_start = key_queue_end = 0;
video_reset(gfxcard[0]);
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) ||
(kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) ||
(kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH) || (kbd->type == KBD_TYPE_FE2010)) {
/* DIP switch readout: bit set = OFF, clear = ON. */
if (kbd->type == KBD_TYPE_OLIVETTI)
/* Olivetti M19
* Jumpers J1, J2 - monitor type.
* 01 - mono (high-res)
* 10 - color (low-res, disables 640x400x2 mode)
* 00 - autoswitching
*/
kbd->pd |= 0x00;
else
/* Switches 7, 8 - floppy drives. */
kbd->pd = get_fdd_switch_settings();
/* Switches 5, 6 - video card type */
kbd->pd |= get_videomode_switch_settings();
/* Switches 3, 4 - memory size. */
if ((kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_HYUNDAI) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_FE2010)) {
switch (mem_size) {
case 256:
kbd->pd |= 0x00;
break;
case 512:
kbd->pd |= 0x04;
break;
case 576:
kbd->pd |= 0x08;
break;
case 640:
default:
kbd->pd |= 0x0c;
break;
}
} else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_VTECH)) {
switch (mem_size) {
case 64: /* 1x64k */
kbd->pd |= 0x00;
break;
case 128: /* 2x64k */
kbd->pd |= 0x04;
break;
case 192: /* 3x64k */
kbd->pd |= 0x08;
break;
case 256: /* 4x64k */
default:
kbd->pd |= 0x0c;
break;
}
} else if (kbd->type == KBD_TYPE_PC82) {
switch (mem_size) {
#ifdef PC82_192K_3BANK
case 192: /* 3x64k, not supported by stock BIOS due to bugs */
kbd->pd |= 0x08;
break;
#else
case 192: /* 2x64k + 2x32k */
#endif
case 64: /* 4x16k */
case 96: /* 2x32k + 2x16k */
case 128: /* 4x32k */
case 160: /* 2x64k + 2x16k */
case 224: /* 3x64k + 1x32k */
case 256: /* 4x64k */
default:
kbd->pd |= 0x0c;
break;
}
} else { /* really just the PC '81 */
switch (mem_size) {
case 16: /* 1x16k */
kbd->pd |= 0x00;
break;
case 32: /* 2x16k */
kbd->pd |= 0x04;
break;
case 48: /* 3x16k */
kbd->pd |= 0x08;
break;
case 64: /* 4x16k */
default:
kbd->pd |= 0x0c;
break;
}
}
/* Switch 2 - 8087 FPU. */
if (hasfpu)
kbd->pd |= 0x02;
} else if (kbd->type == KBD_TYPE_ZENITH) {
/* Zenith Data Systems Z-151
* SW2 switch settings:
* bit 7: monitor frequency
* bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd)
* bits 0-4: installed memory
*/
kbd->pd = 0x20;
switch (mem_size) {
case 128:
kbd->pd |= 0x02;
break;
case 192:
kbd->pd |= 0x04;
break;
case 256:
kbd->pd |= 0x06;
break;
case 320:
kbd->pd |= 0x08;
break;
case 384:
kbd->pd |= 0x0a;
break;
case 448:
kbd->pd |= 0x0c;
break;
case 512:
kbd->pd |= 0x0e;
break;
case 576:
kbd->pd |= 0x10;
break;
case 640:
default:
kbd->pd |= 0x12;
break;
}
}
timer_add(&kbd->send_delay_timer, kbd_poll, kbd, 1);
keyboard_set_table(scancode_xt);
is_tandy = (kbd->type == KBD_TYPE_TANDY);
is_t1x00 = (kbd->type == KBD_TYPE_TOSHIBA);
is_amstrad = 0;
return kbd;
return dev;
}
static void
kbd_close(void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
/* Stop the timer. */
timer_disable(&kbd->send_delay_timer);
/* Disable scanning. */
keyboard_scan = 0;
keyboard_send = NULL;
io_removehandler(0x0060, 4,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
kbd_t *kbd = (kbd_t *) priv;
free(kbd);
}
const device_t keyboard_pc_device = {
.name = "IBM PC Keyboard (1981)",
.internal_name = "keyboard_pc",
.flags = 0,
.local = KBD_TYPE_PC81,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
static const device_config_t keyboard_pc_xt_config[] = {
// clang-format off
{
.name = "keys",
.description = "Keys",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = KBD_83_KEY,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "83", .value = KBD_83_KEY },
{ .description = "101 (ANSI)", .value = KBD_101_KEY },
{ .description = "102 (ISO)", .value = KBD_102_KEY }
},
.bios = { { 0 } }
},
{
.name = "", .description = "", .type = CONFIG_END
}
// clang-format on
};
const device_t keyboard_pc82_device = {
.name = "IBM PC Keyboard (1982)",
.internal_name = "keyboard_pc82",
.flags = 0,
.local = KBD_TYPE_PC82,
const device_t keyboard_pc_xt_device = {
.name = "PC/XT Keyboard",
.internal_name = "keyboard_pc_xt",
.flags = DEVICE_XT_KBC,
.local = 0,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_pravetz_device = {
.name = "Pravetz Keyboard",
.internal_name = "keyboard_pravetz",
.flags = 0,
.local = KBD_TYPE_PRAVETZ,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_device = {
.name = "XT (1982) Keyboard",
.internal_name = "keyboard_xt",
.flags = 0,
.local = KBD_TYPE_XT82,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt86_device = {
.name = "XT (1986) Keyboard",
.internal_name = "keyboard_xt86",
.flags = 0,
.local = KBD_TYPE_XT86,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_compaq_device = {
.name = "Compaq Portable Keyboard",
.internal_name = "keyboard_xt_compaq",
.flags = 0,
.local = KBD_TYPE_COMPAQ,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_tandy_device = {
.name = "Tandy 1000 Keyboard",
.internal_name = "keyboard_tandy",
.flags = 0,
.local = KBD_TYPE_TANDY,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_t1x00_device = {
.name = "Toshiba T1x00 Keyboard",
.internal_name = "keyboard_xt_t1x00",
.flags = 0,
.local = KBD_TYPE_TOSHIBA,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_lxt3_device = {
.name = "VTech Laser Turbo XT Keyboard",
.internal_name = "keyboard_xt_lxt",
.flags = 0,
.local = KBD_TYPE_VTECH,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_olivetti_device = {
.name = "Olivetti XT Keyboard",
.internal_name = "keyboard_xt_olivetti",
.flags = 0,
.local = KBD_TYPE_OLIVETTI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_zenith_device = {
.name = "Zenith XT Keyboard",
.internal_name = "keyboard_xt_zenith",
.flags = 0,
.local = KBD_TYPE_ZENITH,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_hyundai_device = {
.name = "Hyundai XT Keyboard",
.internal_name = "keyboard_xt_hyundai",
.flags = 0,
.local = KBD_TYPE_HYUNDAI,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xt_fe2010_device = {
.name = "Faraday FE2010 XT Keyboard",
.internal_name = "keyboard_xt_fe2010",
.flags = 0,
.local = KBD_TYPE_FE2010,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_xtclone_device = {
.name = "XT (Clone) Keyboard",
.internal_name = "keyboard_xtclone",
.flags = 0,
.local = KBD_TYPE_XTCLONE,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.config = keyboard_pc_xt_config
};

File diff suppressed because it is too large Load Diff

View File

@@ -90,12 +90,16 @@ static mouse_t mouse_devices[] = {
#ifdef USE_GENIBUS
{ &mouse_genibus_device },
#endif
{ &mouse_mssystems_device },
{ &mouse_mssystems_bus_device },
{ &mouse_msserial_device },
{ &mouse_msserial_ballpoint_device },
{ &mouse_ltserial_device },
{ &mouse_ps2_device },
#ifdef USE_STANDALONE_QUICKPORT
{ &mouse_upc_standalone_device },
#endif
#ifdef USE_WACOM
{ &mouse_wacom_device },
{ &mouse_wacom_artpad_device },
@@ -555,7 +559,7 @@ mouse_get_buttons_ex(void)
void
mouse_set_sample_rate(double new_rate)
{
mouse_timed = (new_rate > 0.0);
mouse_timed = !force_constant_mouse && (new_rate > 0.0);
timer_stop(&mouse_timer);
@@ -564,6 +568,12 @@ mouse_set_sample_rate(double new_rate)
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
}
void
mouse_update_sample_rate(void)
{
mouse_set_sample_rate(sample_rate);
}
/* Callback from the hardware driver. */
void
mouse_set_buttons(int buttons)
@@ -672,8 +682,7 @@ mouse_reset(void)
/* Clear local data. */
mouse_clear_coords();
mouse_clear_buttons();
mouse_input_mode = 0;
mouse_timed = 1;
mouse_input_mode = 0;
/* If no mouse configured, we're done. */
if (mouse_type == 0)
@@ -682,8 +691,7 @@ mouse_reset(void)
timer_add(&mouse_timer, mouse_timer_poll, NULL, 0);
/* Poll at 100 Hz, the default of a PS/2 mouse. */
sample_rate = 100.0;
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
mouse_set_sample_rate(100.0);
if ((mouse_type > 1) && (mouse_devices[mouse_type].device != NULL))
mouse_priv = device_add(mouse_devices[mouse_type].device);

View File

@@ -508,7 +508,7 @@ bm_poll(void *priv)
dev->mouse_buttons |= 0x40;
/* Set bits 3-5 according to button state changes. */
xor = ((dev->current_b ^ mouse_get_buttons_ex()) & 0x07) << 3;
xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3;
dev->mouse_buttons |= xor;
}

View File

@@ -10,7 +10,7 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 Miran Grca.
* Copyright 2023-2025 Miran Grca.
*/
#include <stdarg.h>
#include <stdatomic.h>
@@ -21,7 +21,6 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
@@ -353,6 +352,9 @@ mouse_ps2_init(const device_t *info)
atkbc_dev_t *dev = kbc_at_dev_init(DEV_AUX);
int i;
if (info->local & MOUSE_TYPE_QPORT)
device_context(&mouse_upc_standalone_device);
dev->name = info->name;
dev->type = info->local;
@@ -382,6 +384,9 @@ mouse_ps2_init(const device_t *info)
mouse_set_poll(ps2_poll, dev);
if (info->local & MOUSE_TYPE_QPORT)
device_context_restore();
/* Return our private data to the I/O layer. */
return dev;
}

View File

@@ -480,7 +480,7 @@ ltsermouse_update_report_period(mouse_t *dev)
}
static void
ltsermouse_switch_baud_rate(mouse_t *dev, int next_state)
ltsermouse_switch_baud_rate(mouse_t *dev, int next_state, int prompt_off)
{
double word_lens[FORMATS_NUM] = {
[FORMAT_BP1_ABS] = 7.0 + 1.0, /* 7 data bits + even parity */
@@ -517,7 +517,7 @@ ltsermouse_switch_baud_rate(mouse_t *dev, int next_state)
ltsermouse_set_report_period(dev, dev->rps);
if (!dev->continuous && (next_state != STATE_BAUD_RATE)) {
if (dev->prompt)
if (dev->prompt && prompt_off)
ltsermouse_set_prompt_mode(dev, 0);
sermouse_transmit_report(dev, 0);
@@ -569,7 +569,7 @@ ltsermouse_process_command(mouse_t *dev)
dev->buf[0] = 0x06;
sermouse_transmit(dev, 1, 0, 0);
ltsermouse_switch_baud_rate(dev, STATE_BAUD_RATE);
ltsermouse_switch_baud_rate(dev, STATE_BAUD_RATE, 0);
break;
case 0x4a: /* Report Rate Selection commands */
@@ -614,7 +614,7 @@ ltsermouse_process_command(mouse_t *dev)
case 0x58: /* Microsoft Compatible Format (3+1 byte 3-button, from the FreeBSD source code) */
if ((dev->rev >= 0x02) && ((dev->command != 0x58) || (dev->rev > 0x04))) {
dev->format = dev->command & 0x1f;
ltsermouse_switch_baud_rate(dev, sermouse_next_state(dev));
ltsermouse_switch_baud_rate(dev, sermouse_next_state(dev), 0);
}
break;
@@ -706,7 +706,7 @@ ltsermouse_process_data(mouse_t *dev)
dev->bps = 9600;
break;
}
ltsermouse_switch_baud_rate(dev, (dev->prompt || dev->continuous) ? STATE_IDLE : STATE_TRANSMIT_REPORT);
ltsermouse_switch_baud_rate(dev, (dev->prompt || dev->continuous) ? STATE_IDLE : STATE_TRANSMIT_REPORT, 0);
break;
default:
dev->state = STATE_IDLE;
@@ -744,7 +744,7 @@ sermouse_reset(mouse_t *dev, int callback)
break;
}
ltsermouse_switch_baud_rate(dev, callback ? STATE_TRANSMIT : STATE_IDLE);
ltsermouse_switch_baud_rate(dev, callback ? STATE_TRANSMIT : STATE_IDLE, 1);
}
static void
@@ -900,9 +900,11 @@ sermouse_init(const device_t *info)
dev->status = 0x0f;
dev->id_len = 1;
dev->id[0] = 'M';
if (info->local == 1) // Logitech Serial Mouse
if (info->local == 1) {
/* Logitech Serial Mouse */
dev->rev = device_get_config_int("revision");
dev->default_bps = device_get_config_int("default_baud");
}
switch (dev->but) {
default:
case 2:

446
src/device/mouse_upc.c Normal file
View File

@@ -0,0 +1,446 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Chips & Technologies F82C710 Universal
* Peripheral Controller (UPC) PS/2 mouse port.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include "x86seg.h"
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
#define STAT_DEV_IDLE 0x01
#define STAT_RX_FULL 0x02
#define STAT_TX_IDLE 0x04
#define STAT_RESET 0x08
#define STAT_INTS_ON 0x10
#define STAT_ERROR_FLAG 0x20
#define STAT_CLEAR 0x40
#define STAT_ENABLE 0x80
typedef struct mouse_upc_t {
uint8_t status;
uint8_t ib;
uint8_t ob;
uint8_t state;
uint8_t ctrl_queue_start;
uint8_t ctrl_queue_end;
uint8_t handler_enable[2];
uint16_t mdata_addr;
uint16_t mstat_addr;
uint16_t irq;
uint16_t base_addr[2];
/* Local copies of the pointers to both ports for easier swapping (AMI '5' MegaKey). */
kbc_at_port_t *port;
/* Main timers. */
pc_timer_t poll_timer;
pc_timer_t dev_poll_timer;
struct {
uint8_t (*read)(uint16_t port, void *priv);
void (*write)(uint16_t port, uint8_t val, void *priv);
} handlers[2];
void *mouse_ps2;
} mouse_upc_t;
enum {
STATE_MAIN_IBF, /* UPC checking if the input buffer is full. */
STATE_MAIN, /* UPC checking if the auxiliary has anything to send. */
STATE_OUT, /* UPC is sending multiple bytes. */
STATE_SEND, /* UPC is sending command to the auxiliary device. */
STATE_SCAN /* UPC is waiting for the auxiliary command response. */
};
#ifdef ENABLE_MOUSE_UPC_LOG
int mouse_upc_do_log = ENABLE_MOUSE_UPC_LOG;
static void
mouse_upc_log(const char *fmt, ...)
{
va_list ap;
if (mouse_upc_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define mouse_upc_log(fmt, ...)
#endif
static void
mouse_upc_send_to_ob(mouse_upc_t *dev, uint8_t val)
{
dev->status = (dev->status & ~STAT_DEV_IDLE) | STAT_RX_FULL;
if (dev->status & STAT_INTS_ON) {
picint_common(1 << dev->irq, 0, 0, NULL);
picint_common(1 << dev->irq, 0, 1, NULL);
}
dev->ob = val;
}
static void
set_enable_aux(mouse_upc_t *dev, uint8_t enable)
{
dev->status &= ~STAT_ENABLE;
dev->status |= (enable ? STAT_ENABLE : 0x00);
}
static void
mouse_upc_ibf_process(mouse_upc_t *dev)
{
/* IBF set, process both commands and data. */
dev->status |= STAT_TX_IDLE;
dev->state = STATE_MAIN_IBF;
set_enable_aux(dev, 1);
if (dev->port != NULL) {
dev->port->wantcmd = 1;
dev->port->dat = dev->ib;
dev->state = STATE_SEND;
}
}
/*
Correct Procedure:
1. Controller asks the device (keyboard or auxiliary device) for a byte.
2. The device, unless it's in the reset or command states, sees if there's anything to give it,
and if yes, begins the transfer.
3. The controller checks if there is a transfer, if yes, transfers the byte and sends it to the host,
otherwise, checks the next device, or if there is no device left to check, checks if IBF is full
and if yes, processes it.
*/
static int
mouse_upc_scan(mouse_upc_t *dev)
{
if ((dev->port != NULL) && (dev->port->out_new != -1)) {
mouse_upc_log("UPC Mouse: %02X coming\n", dev->port->out_new & 0xff);
mouse_upc_send_to_ob(dev, dev->port->out_new);
dev->port->out_new = -1;
dev->state = STATE_MAIN_IBF;
return 1;
}
return 0;
}
static void
mouse_upc_poll(void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
timer_advance_u64(&dev->poll_timer, (100ULL * TIMER_USEC));
switch (dev->state) {
case STATE_MAIN_IBF:
default:
if (!(dev->status & STAT_TX_IDLE))
mouse_upc_ibf_process(dev);
else if (!(dev->status & STAT_RX_FULL)) {
if (dev->status & STAT_ENABLE)
dev->state = STATE_MAIN;
}
break;
case STATE_MAIN:
if (!(dev->status & STAT_TX_IDLE))
mouse_upc_ibf_process(dev);
else {
(void) mouse_upc_scan(dev);
dev->state = STATE_MAIN_IBF;
}
break;
case STATE_SEND:
if (!dev->port->wantcmd)
dev->state = STATE_SCAN;
break;
case STATE_SCAN:
(void) mouse_upc_scan(dev);
break;
}
}
static void
mouse_upc_dev_poll(void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
timer_advance_u64(&dev->dev_poll_timer, (100ULL * TIMER_USEC));
if ((dev->port != NULL) && (dev->port->priv != NULL))
dev->port->poll(dev->port->priv);
}
static void
mouse_upc_port_1_write(uint16_t port, uint8_t val, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
mouse_upc_log("UPC Mouse: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
if ((dev->status & STAT_TX_IDLE) && (dev->status & STAT_ENABLE)) {
dev->ib = val;
dev->status &= ~STAT_TX_IDLE;
}
}
static void
mouse_upc_port_2_write(uint16_t port, uint8_t val, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
mouse_upc_log("UPC Mouse: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
dev->status = (dev->status & 0x27) | (val & 0xd8);
if (dev->status & (STAT_CLEAR | STAT_RESET)) {
/* TODO: Silently reset the mouse. */
dev->status &= ~STAT_RX_FULL;
dev->status |= (STAT_DEV_IDLE | STAT_TX_IDLE);
}
}
static uint8_t
mouse_upc_port_1_read(uint16_t port, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
uint8_t ret = 0xff;
cycles -= ISA_CYCLES(8);
ret = dev->ob;
dev->ob = 0xff;
dev->status &= ~STAT_RX_FULL;
dev->status |= STAT_DEV_IDLE;
mouse_upc_log("UPC Mouse: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
return ret;
}
static uint8_t
mouse_upc_port_2_read(uint16_t port, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
uint8_t ret = 0xff;
cycles -= ISA_CYCLES(8);
ret = dev->status;
mouse_upc_log("UPC Mouse: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
return ret;
}
static void
mouse_upc_reset(void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
dev->status = STAT_DEV_IDLE | STAT_TX_IDLE;
dev->ob = 0xff;
dev->state = STATE_MAIN_IBF;
}
static void
mouse_upc_close(void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
/* Stop timers. */
timer_disable(&dev->dev_poll_timer);
timer_disable(&dev->poll_timer);
if (kbc_at_ports[1] != NULL) {
free(kbc_at_ports[1]);
kbc_at_ports[1] = NULL;
}
free(dev);
}
void
mouse_upc_port_handler(int num, int set, uint16_t port, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
io_removehandler(dev->base_addr[num], 1,
dev->handlers[num].read, NULL, NULL,
dev->handlers[num].write, NULL, NULL, priv);
dev->handler_enable[num] = set;
dev->base_addr[num] = port;
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
io_sethandler(dev->base_addr[num], 1,
dev->handlers[num].read, NULL, NULL,
dev->handlers[num].write, NULL, NULL, priv);
}
void
mouse_upc_handler(int set, uint16_t port, void *priv)
{
mouse_upc_port_handler(0, set, port, priv);
mouse_upc_port_handler(1, set, port + 0x0001, priv);
}
void
mouse_upc_set_irq(int num, uint16_t irq, void *priv)
{
mouse_upc_t *dev = (mouse_upc_t *) priv;
if (dev->irq != 0xffff)
picintc(1 << dev->irq);
dev->irq = irq;
}
static void *
mouse_upc_init_common(int standalone, int irq)
{
mouse_upc_t *dev;
dev = (mouse_upc_t *) calloc(1, sizeof(mouse_upc_t));
mouse_upc_reset(dev);
dev->handlers[0].read = mouse_upc_port_1_read;
dev->handlers[0].write = mouse_upc_port_1_write;
dev->handlers[1].read = mouse_upc_port_2_read;
dev->handlers[1].write = mouse_upc_port_2_write;
dev->irq = irq;
if (kbc_at_ports[1] == NULL) {
kbc_at_ports[1] = (kbc_at_port_t *) calloc(1, sizeof(kbc_at_port_t));
kbc_at_ports[1]->out_new = -1;
}
dev->port = kbc_at_ports[1];
timer_add(&dev->poll_timer, mouse_upc_poll, dev, 1);
timer_add(&dev->dev_poll_timer, mouse_upc_dev_poll, dev, 1);
if (standalone) {
mouse_upc_handler(1, 0x02d4, dev);
dev->mouse_ps2 = device_add_params(&mouse_ps2_device, (void *) (uintptr_t) MOUSE_TYPE_PS2_QPORT);
}
return dev;
}
static void *
mouse_upc_init(const device_t *info)
{
void *dev = NULL;
if (info->local == 1)
dev = mouse_upc_init_common(1, device_get_config_int("irq"));
else
dev = mouse_upc_init_common(0, info->local);
return dev;
}
static const device_config_t upc_config[] = {
// clang-format off
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 12,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "IRQ 12", .value = 12 },
{ .description = "IRQ 2/9", .value = 2 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "buttons",
.description = "Buttons",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 2,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Two", .value = 2 },
{ .description = "Three", .value = 3 },
{ .description = "Wheel", .value = 4 },
{ .description = "Five + Wheel", .value = 5 },
{ .description = "Five + 2 Wheels", .value = 6 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "", .description = "", .type = CONFIG_END
}
// clang-format on
};
const device_t mouse_upc_device = {
.name = "PS/2 QuickPort Mouse (F82C710)",
.internal_name = "mouse_upc",
.flags = DEVICE_ISA,
.local = 0,
.init = mouse_upc_init,
.close = mouse_upc_close,
.reset = mouse_upc_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t mouse_upc_standalone_device = {
.name = "PS/2 QuickPort Mouse",
.internal_name = "mouse_upc_standalone",
.flags = DEVICE_ISA,
.local = 1,
.init = mouse_upc_init,
.close = mouse_upc_close,
.reset = mouse_upc_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = upc_config
};

View File

@@ -0,0 +1,89 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Radisys EPC-2012 Configuration registers.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/plat_unused.h>
typedef struct radisys_config_t {
uint8_t regs[2];
} radisys_config_t;
static uint8_t
radisys_config_read(uint16_t port, void *priv)
{
radisys_config_t *dev = (radisys_config_t *) priv;
uint8_t ret = dev->regs[port & 0x0001];
return ret;
}
static void
radisys_config_write(uint16_t port, uint8_t val, void *priv)
{
radisys_config_t *dev = (radisys_config_t *) priv;
dev->regs[port & 0x0001] = val;
if (!(port & 0x0001) && machine_has_jumpered_ecp_dma(machine, MACHINE_DMA_USE_CONFIG))
lpt1_dma((val & 0x02) ? 3 : 1);
}
static void
radisys_config_close(void *priv)
{
radisys_config_t *dev = (radisys_config_t *) priv;
free(dev);
}
static void *
radisys_config_init(UNUSED(const device_t *info))
{
/* We have to return something non-NULL. */
radisys_config_t *dev = (radisys_config_t *) calloc(1, sizeof(radisys_config_t));
/* 370h is also supported. */
io_sethandler(0x0270, 0x0002, radisys_config_read, NULL, NULL, radisys_config_write, NULL, NULL, dev);
return dev;
}
const device_t radisys_config_device = {
.name = "Radisys EPC-2012 Configuration",
.internal_name = "radisys_config",
.flags = 0,
.local = 0,
.init = radisys_config_init,
.close = radisys_config_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -475,6 +475,12 @@ serial_set_clock_src(serial_t *dev, double clock_src)
serial_update_speed(dev);
}
void
serial_set_type(serial_t *dev, uint8_t type)
{
dev->type = type;
}
void
serial_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -746,6 +752,14 @@ serial_read(uint16_t addr, void *priv)
return ret;
}
uint8_t
serial_get_shadow(serial_t *dev)
{
uint8_t ret = dev->fcr;
return ret;
}
void
serial_remove(serial_t *dev)
{

View File

@@ -47,6 +47,7 @@
#include <86box/io.h>
#include <86box/video.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
typedef struct {
mem_mapping_t scratchpad_mapping;
@@ -94,7 +95,7 @@ zenith_scratchpad_close(void *priv)
free(dev);
}
static const device_t zenith_scratchpad_device = {
const device_t zenith_scratchpad_device = {
.name = "Zenith scratchpad RAM",
.internal_name = "zenith_scratchpad",
.flags = 0,
@@ -107,99 +108,3 @@ static const device_t zenith_scratchpad_device = {
.force_redraw = NULL,
.config = NULL
};
void
machine_zenith_init(const machine_t *model)
{
machine_common_init(model);
device_add(&zenith_scratchpad_device);
pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt);
device_add(&keyboard_xt_zenith_device);
nmi_init();
}
/*
* Current bugs and limitations:
* - missing NVRAM implementation
*/
int
machine_xt_z184_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/zdsupers/z184m v3.1d.10d",
0x000f8000, 32768, 0);
if (bios_only || !ret)
return ret;
machine_zenith_init(model);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_xt_device);
lpt1_remove(); /* only one parallel port */
lpt2_remove();
lpt1_setup(LPT2_ADDR);
device_add(&ns8250_device);
/* So that serial_standalone_init() won't do anything. */
serial_set_next_inst(SERIAL_MAX - 1);
device_add(&cga_device);
return ret;
}
int
machine_xt_z151_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/zdsz151/444-229-18.bin",
0x000fc000, 32768, 0);
if (ret) {
bios_load_aux_linear("roms/machines/zdsz151/444-260-18.bin",
0x000f8000, 16384, 0);
}
if (bios_only || !ret)
return ret;
machine_zenith_init(model);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_xt_tandy_device);
return ret;
}
/*
* Current bugs and limitations:
* - Memory board support for EMS currently missing
*/
int
machine_xt_z159_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/zdsz159/z159m v2.9e.10d",
0x000f8000, 32768, 0);
if (bios_only || !ret)
return ret;
machine_zenith_init(model);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_xt_tandy_device);
/* parallel port is on the memory board */
lpt1_remove(); /* only one parallel port */
lpt2_remove();
lpt1_setup(LPT2_ADDR);
return ret;
}

View File

@@ -23,6 +23,7 @@ add_library(hdd OBJECT
hdc_st506_xt.c
hdc_st506_at.c
hdc_xta.c
hdc_xta_ps1.c
hdc_esdi_at.c
hdc_esdi_mca.c
hdc_xtide.c
@@ -37,7 +38,7 @@ add_library(hdd OBJECT
hdc_ide_w83769f.c
)
add_library(zip OBJECT zip.c)
add_library(rdisk OBJECT rdisk.c)
add_library(mo OBJECT mo.c)

View File

@@ -63,6 +63,7 @@ static const struct {
{ &xtide_device },
{ &st506_xt_st11_m_device },
{ &st506_xt_st11_r_device },
{ &xta_st50x_device },
{ &st506_xt_victor_v86p_device },
{ &st506_xt_wd1002a_27x_device },
{ &st506_xt_wd1002a_wx1_device },
@@ -78,6 +79,8 @@ static const struct {
{ &xtide_at_2ch_device },
{ &xtide_at_ps2_device },
{ &xtide_at_ps2_2ch_device },
{ &ide_ter_device },
{ &ide_qua_device },
{ &st506_at_wd1003_device },
{ &esdi_at_wd1007vse1_device },
/* MCA */
@@ -88,6 +91,9 @@ static const struct {
{ &ide_vlb_device },
{ &ide_vlb_2ch_device },
/* PCI */
{ &ide_cmd646_ter_qua_device },
{ &ide_cmd648_ter_qua_device },
{ &ide_cmd649_ter_qua_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ NULL }
@@ -108,18 +114,14 @@ hdc_init(void)
void
hdc_reset(void)
{
hdc_log("HDC: reset(current=%d, internal=%d)\n",
hdc_current[0], (machines[machine].flags & MACHINE_HDC) ? 1 : 0);
for (int i = 0; i < HDC_MAX; i++) {
hdc_log("HDC %i: reset(current=%d, internal=%d)\n", i,
hdc_current[i], hdc_current[i] == HDC_INTERNAL);
/* If we have a valid controller, add its device. */
if (hdc_current[0] > HDC_INTERNAL)
device_add(controllers[hdc_current[0]].device);
/* Now, add the tertiary and/or quaternary IDE controllers. */
if (ide_ter_enabled)
device_add(&ide_ter_device);
if (ide_qua_enabled)
device_add(&ide_qua_device);
/* If we have a valid controller, add its device. */
if (hdc_current[i] > HDC_INTERNAL)
device_add_inst(controllers[hdc_current[i]].device, i + 1);
}
}
const char *
@@ -129,7 +131,7 @@ hdc_get_internal_name(int hdc)
}
int
hdc_get_from_internal_name(char *s)
hdc_get_from_internal_name(const char *s)
{
int c = 0;

View File

@@ -46,7 +46,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdd.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/version.h>
/* Bits of 'atastat' */
@@ -234,9 +234,7 @@ static uint8_t ide_qua_pnp_rom[] = {
0x79, 0x00
};
ide_t *ide_drives[IDE_NUM];
int ide_ter_enabled = 0;
int ide_qua_enabled = 0;
ide_t *ide_drives[IDE_NUM] = { 0 };
static void ide_atapi_callback(ide_t *ide);
static void ide_callback(void *priv);
@@ -482,7 +480,7 @@ static int
ide_get_max(const ide_t *ide, const int type)
{
const int ata_4 = ide_is_ata4(ide_boards[ide->board]);
const int max[2][4] = { { 0, -1, -1, -1 }, { 4, 2, 2, 5 } };
const int max[2][4] = { { 3, -1, -1, -1 }, { 4, 2, 2, 5 } };
int ret;
if (ide->type == IDE_ATAPI)
@@ -497,7 +495,7 @@ static int
ide_get_timings(const ide_t *ide, const int type)
{
const int ata_4 = ide_is_ata4(ide_boards[ide->board]);
const int timings[2][3] = { { 0, 0, 0 }, { 120, 120, 0 } };
const int timings[2][3] = { { 0, 240, 180 }, { 120, 120, 120 } };
int ret;
if (ide->type == IDE_ATAPI)
@@ -668,8 +666,9 @@ ide_identify(ide_t *ide)
ide->buffer[88] = 0x0000;
if (max_pio >= 3) {
ide->buffer[49] |= 0x0c00;
ide->buffer[53] |= 0x0002;
ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO);
ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO_FC);
ide->buffer[68] = ide_get_timings(ide, TIMINGS_PIO_FC);
for (i = 3; i <= max_pio; i++)
ide->buffer[64] |= (1 << (i - 3));
@@ -712,12 +711,8 @@ ide_identify(ide_t *ide)
}
if (ide->mdma_mode != -1) {
d = (ide->mdma_mode & 0xff);
d <<= 8;
if ((ide->mdma_mode & 0x300) == 0x000) {
if ((ide->mdma_mode & 0xff) >= 3)
ide->buffer[64] |= d;
} else if ((ide->mdma_mode & 0x300) == 0x100)
d = (ide->mdma_mode & 0xff) << 8;
if ((ide->mdma_mode & 0x300) == 0x100)
ide->buffer[62] |= d;
else if ((ide->mdma_mode & 0x300) == 0x200)
ide->buffer[63] |= d;
@@ -831,6 +826,7 @@ ide_set_features(ide_t *ide)
int mode;
int submode;
int max;
int max_pio_submode;
features = ide->tf->cylprecomp;
features_data = ide->tf->secount;
@@ -846,9 +842,10 @@ ide_set_features(ide_t *ide)
switch (mode) {
case 0x00: /* PIO default */
if (submode != 0)
max = ide_get_max(ide, TYPE_PIO);
max_pio_submode = (max >= 3) ? 1 : 0;
if (submode > max_pio_submode)
return 0;
max = ide_get_max(ide, TYPE_PIO);
ide->mdma_mode = (1 << max);
ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel,
submode, ide->mdma_mode);
@@ -2828,20 +2825,23 @@ ide_board_close(int board)
ide_log("ide_board_close(%i)\n", board);
if ((ide_boards[board] == NULL) || !ide_boards[board]->inited)
if (ide_boards[board] == NULL)
return;
ide_log("IDE: Closing board %i...\n", board);
timer_stop(&ide_boards[board]->timer);
if (ide_boards[board]->inited) {
timer_stop(&ide_boards[board]->timer);
ide_clear_bus_master(board);
ide_clear_bus_master(board);
}
/* Close hard disk image files (if previously open) */
for (uint8_t d = 0; d < 2; d++) {
c = (board << 1) + d;
ide_boards[board]->ide[d] = NULL;
if (ide_boards[board]->inited)
ide_boards[board]->ide[d] = NULL;
dev = ide_drives[c];
@@ -3265,6 +3265,16 @@ ide_close(UNUSED(void *priv))
}
}
void
ide_hard_reset(void)
{
for (int i = 0; i < IDE_BUS_MAX; i++)
ide_boards[i] = NULL;
for (int i = 0; i < IDE_NUM; i++)
ide_drives[i] = NULL;
}
static uint8_t
mcide_mca_read(const int port, void *priv)
{

View File

@@ -34,7 +34,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/mo.h>
typedef struct cmd640_t {
@@ -45,7 +45,7 @@ typedef struct cmd640_t {
uint8_t pci;
uint8_t irq_state;
uint8_t pci_slot;
uint8_t pad0;
uint8_t force_on;
uint8_t regs[256];
uint32_t local;
int irq_mode[2];
@@ -143,7 +143,7 @@ cmd640_ide_handlers(cmd640_t *dev)
ide_set_base(0, main);
ide_set_side(0, side);
if (dev->regs[0x04] & 0x01)
if ((dev->regs[0x04] & 0x01) || dev->force_on)
ide_pri_enable();
}
@@ -161,7 +161,7 @@ cmd640_ide_handlers(cmd640_t *dev)
ide_set_base(1, main);
ide_set_side(1, side);
if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08))
if (((dev->regs[0x04] & 0x01) || dev->force_on) && (dev->regs[0x51] & 0x08))
ide_sec_enable();
}
}
@@ -417,10 +417,10 @@ cmd640_reset(void *priv)
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) &&
(zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && (rdisk_drives[i].ide_channel >= min_channel) &&
(rdisk_drives[i].ide_channel <= max_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&
@@ -512,6 +512,7 @@ cmd640_init(const device_t *info)
dev->local = info->local;
dev->channels = ((info->local & 0x60000) >> 17) & 0x03;
dev->force_on = !!(info->local & 0x100000);
if (info->flags & DEVICE_PCI) {
device_add(&ide_pci_2ch_device);
@@ -667,7 +668,7 @@ const device_t ide_cmd640_pci_legacy_only_device = {
};
const device_t ide_cmd640_pci_single_channel_device = {
.name = "CMD PCI-0640B PCI",
.name = "CMD PCI-0640B PCI (Single Channel)",
.internal_name = "ide_cmd640_pci_single_channel",
.flags = DEVICE_PCI,
.local = 0x2000a,
@@ -681,7 +682,7 @@ const device_t ide_cmd640_pci_single_channel_device = {
};
const device_t ide_cmd640_pci_single_channel_sec_device = {
.name = "CMD PCI-0640B PCI",
.name = "CMD PCI-0640B PCI (Single Channel, Secondary)",
.internal_name = "ide_cmd640_pci_single_channel_sec",
.flags = DEVICE_PCI,
.local = 0x4000a,

View File

@@ -34,8 +34,26 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/rom.h>
#include <86box/hdd.h>
#include <86box/scsi_disk.h>
#include <86box/mo.h>
#include "cpu.h"
#include "x86.h"
#define CMD_TYPE_646 0x0000000
#define CMD_TYPE_648 0x0100000
#define CMD_TYPE_649 0x0200000
#define CMD648_JP7 0x0400000 /* Reload subsystem ID on reset. */
#define CMD648_RAID 0x0800000
#define CMD64X_ONBOARD 0x1000000
#define CMD648_BIOS_FILE "roms/hdd/ide/648_1910.bin"
#define CMD649_REV_1914_BIOS_FILE "roms/hdd/ide/649_1914.bin"
#define CMD649_REV_2301_BIOS_FILE "roms/hdd/ide/649_2301.bin"
typedef struct cmd646_t {
uint8_t vlb_idx;
@@ -46,11 +64,17 @@ typedef struct cmd646_t {
uint8_t regs[256];
uint32_t local;
uint32_t rom_addr;
uint32_t rom_addr_size;
uint32_t rom_addr_mask;
int irq_pin;
int has_bios;
int irq_mode[2];
rom_t bios_rom;
sff8038i_t *bm[2];
} cmd646_t;
@@ -80,7 +104,8 @@ cmd646_set_irq_0(uint8_t status, void *priv)
if (!(dev->regs[0x50] & 0x04) || (status & 0x04))
dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status;
sff_bus_master_set_irq(status, dev->bm[0]);
if (!(dev->local & CMD_TYPE_648) || !(dev->regs[0x71] & 0x10))
sff_bus_master_set_irq(status, dev->bm[0]);
}
static void
@@ -91,7 +116,8 @@ cmd646_set_irq_1(uint8_t status, void *priv)
if (!(dev->regs[0x57] & 0x10) || (status & 0x04))
dev->regs[0x57] = (dev->regs[0x57] & ~0x10) | (status << 2);
sff_bus_master_set_irq(status, dev->bm[1]);
if (!(dev->local & CMD_TYPE_648) || !(dev->regs[0x71] & 0x20))
sff_bus_master_set_irq(status, dev->bm[1]);
}
static int
@@ -116,13 +142,24 @@ cmd646_ide_handlers(cmd646_t *dev)
uint16_t main;
uint16_t side;
int irq_mode[2] = { IRQ_MODE_LEGACY, IRQ_MODE_LEGACY };
int first = 0;
int reg09 = dev->regs[0x09];
int reg50 = dev->regs[0x50];
if ((dev->local & CMD_TYPE_648) && (dev->local & CMD648_RAID)) {
reg09 = 0xff;
reg50 |= 0x40;
}
if (dev->local & 0x80000)
first += 2;
sff_set_slot(dev->bm[0], dev->pci_slot);
sff_set_slot(dev->bm[1], dev->pci_slot);
ide_pri_disable();
ide_handlers(first, 0);
if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) {
if ((reg09 & 0x01) && (reg50 & 0x40)) {
main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8);
side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2;
} else {
@@ -130,23 +167,28 @@ cmd646_ide_handlers(cmd646_t *dev)
side = 0x3f6;
}
ide_set_base(0, main);
ide_set_side(0, side);
ide_set_base(first, main);
ide_set_side(first, side);
if (dev->regs[0x09] & 0x01)
if (reg09 & 0x01)
irq_mode[0] = IRQ_MODE_PCI_IRQ_PIN;
sff_set_irq_mode(dev->bm[0], irq_mode[0]);
cmd646_log("IDE %i: %04X, %04X, %i\n", first, main, side, irq_mode[0]);
if (dev->regs[0x04] & 0x01)
ide_pri_enable();
int pri_enabled = (dev->regs[0x04] & 0x01);
if (dev->local & CMD_TYPE_648)
pri_enabled = pri_enabled && (dev->regs[0x51] & 0x04);
if (pri_enabled)
ide_handlers(first, 1);
if (dev->single_channel)
return;
ide_sec_disable();
ide_handlers(first + 1, 0);
if ((dev->regs[0x09] & 0x04) && (dev->regs[0x50] & 0x40)) {
if ((reg09 & 0x04) && (reg50 & 0x40)) {
main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8);
side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2;
} else {
@@ -154,16 +196,17 @@ cmd646_ide_handlers(cmd646_t *dev)
side = 0x376;
}
ide_set_base(1, main);
ide_set_side(1, side);
ide_set_base(first + 1, main);
ide_set_side(first + 1, side);
if (dev->regs[0x09] & 0x04)
irq_mode[1] = 1;
if (reg09 & 0x04)
irq_mode[1] = IRQ_MODE_PCI_IRQ_PIN;
sff_set_irq_mode(dev->bm[1], irq_mode[1]);
cmd646_log("IDE %i: %04X, %04X, %i\n", first + 1, main, side, irq_mode[1]);
if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08))
ide_sec_enable();
ide_handlers(first + 1, 1);
}
static void
@@ -175,74 +218,176 @@ cmd646_ide_bm_handlers(cmd646_t *dev)
sff_bus_master_handler(dev->bm[1], (dev->regs[0x04] & 1), base + 8);
}
uint8_t
cmd646_bm_write(uint16_t port, uint8_t val, void *priv)
{
cmd646_t *dev = (cmd646_t *) priv;
uint8_t ret = val;
switch (port & 0x000f) {
case 0x0001:
dev->regs[(port & 0x000f) | 0x70] = val & 0xf0;
if (val & 0x04)
dev->regs[0x50] &= ~0x04;
if (val & 0x08)
dev->regs[0x57] &= ~0x10;
ret &= 0x03;
break;
case 0x0003:
dev->regs[0x73] = val;
break;
case 0x0009:
dev->regs[(port & 0x000f) | 0x70] = (dev->regs[(port & 0x000f) | 0x70] & 0x0f) | (val & 0xf0);
ret &= 0x03;
break;
case 0x000b:
dev->regs[0x7b] = val;
break;
}
return ret;
}
uint8_t
cmd646_bm_read(uint16_t port, uint8_t val, void *priv)
{
cmd646_t *dev = (cmd646_t *) priv;
uint8_t ret = val;
switch (port & 0x000f) {
case 0x0001:
ret = (dev->regs[(port & 0x000f) | 0x70] & 0xf3) | (dev->regs[0x50] & 0x04) | ((dev->regs[0x57] & 0x10) >> 1);
break;
case 0x0002: case 0x000a:
ret |= 0x08;
break;
case 0x0003:
ret = dev->regs[0x73];
break;
case 0x0009:
ret = dev->regs[(port & 0x000f) | 0x70];
break;
case 0x000b:
ret = dev->regs[0x7b];
break;
}
return ret;
}
static void
cmd646_bios_handler(cmd646_t *dev)
{
if ((dev->local & CMD_TYPE_648) && dev->has_bios) {
uint32_t *addr = (uint32_t *) &(dev->regs[0x30]);
*addr &= (~dev->rom_addr_mask) | 0x00000001;
dev->rom_addr = *addr & 0xfffffff0;
cmd646_log("ROM address now: %08X\n", dev->rom_addr);
if ((dev->regs[0x04] & 0x02) && (*addr & 0x00000001))
mem_mapping_set_addr(&dev->bios_rom.mapping, dev->rom_addr, dev->rom_addr_size);
else
mem_mapping_disable(&dev->bios_rom.mapping);
}
}
static void
cmd646_pci_write(int func, int addr, uint8_t val, void *priv)
{
cmd646_t *dev = (cmd646_t *) priv;
cmd646_t *dev = (cmd646_t *) priv;
int reg50 = dev->regs[0x50];
if ((dev->local & CMD_TYPE_648) && (dev->regs[0x0a] == 0x04) && (dev->regs[0x0b] == 0x01))
reg50 |= 0x40;
cmd646_log("[%04X:%08X] (%08X) cmd646_pci_write(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, val);
if (func == 0x00)
switch (addr) {
case 0x04:
dev->regs[addr] = (val & 0x45);
if (dev->has_bios)
dev->regs[addr] = (val & 0x47);
else
dev->regs[addr] = (val & 0x45);
cmd646_ide_handlers(dev);
cmd646_ide_bm_handlers(dev);
cmd646_bios_handler(dev);
break;
case 0x05:
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = (dev->regs[addr] & 0x7e) | (val & 0x01);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0xb1);
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = ((dev->regs[addr] & ~(val & 0xb9)) & 0xbf) | (val & 0x40);
else
dev->regs[addr] &= ~(val & 0xb1);
break;
case 0x09:
if ((dev->regs[addr] & 0x0a) == 0x0a) {
dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05);
dev->irq_mode[0] = !!(val & 0x01);
dev->irq_mode[1] = !!(val & 0x04);
if (!(dev->local & CMD_TYPE_648) ||
((dev->regs[0x0a] == 0x01) && (dev->regs[0x0b] == 0x01))) {
if ((dev->regs[addr] & 0x0a) == 0x0a) {
dev->regs[addr] = (dev->regs[addr] & 0x8a) | (val & 0x05);
dev->irq_mode[0] = !!(val & 0x01);
dev->irq_mode[1] = !!(val & 0x04);
cmd646_ide_handlers(dev);
}
}
break;
case 0x0a: case 0x0b:
if ((dev->local & CMD_TYPE_648) && (dev->regs[0x4f] & 0x04)) {
dev->regs[addr] = val;
cmd646_ide_handlers(dev);
}
break;
case 0x10:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x10] = (val & 0xf8) | 1;
cmd646_ide_handlers(dev);
}
break;
case 0x11:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x11] = val;
cmd646_ide_handlers(dev);
}
break;
case 0x14:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x14] = (val & 0xfc) | 1;
cmd646_ide_handlers(dev);
}
break;
case 0x15:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x15] = val;
cmd646_ide_handlers(dev);
}
break;
case 0x18:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x18] = (val & 0xf8) | 1;
cmd646_ide_handlers(dev);
}
break;
case 0x19:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x19] = val;
cmd646_ide_handlers(dev);
}
break;
case 0x1c:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x1c] = (val & 0xfc) | 1;
cmd646_ide_handlers(dev);
}
break;
case 0x1d:
if (dev->regs[0x50] & 0x40) {
if (reg50 & 0x40) {
dev->regs[0x1d] = val;
cmd646_ide_handlers(dev);
}
@@ -255,18 +400,42 @@ cmd646_pci_write(int func, int addr, uint8_t val, void *priv)
dev->regs[0x21] = val;
cmd646_ide_bm_handlers(dev);
break;
case 0x2c ... 0x2f:
case 0x8c ... 0x8f:
if (dev->local & CMD_TYPE_648)
dev->regs[(addr & 0x0f) | 0x20] = val;
break;
case 0x30 ... 0x33:
if ((dev->local & CMD_TYPE_648) && dev->has_bios) {
dev->regs[addr] = val;
cmd646_bios_handler(dev);
}
break;
case 0x3c:
dev->regs[0x3c] = val;
break;
case 0x4f:
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = (dev->regs[addr] & 0xfa) | (val & 0x05);
break;
case 0x51:
dev->regs[addr] = val & 0xc8;
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = val & 0xcc;
else
dev->regs[addr] = val & 0xc8;
cmd646_ide_handlers(dev);
break;
case 0x52:
case 0x54:
case 0x56:
case 0x58:
case 0x59:
case 0x5b:
dev->regs[addr] = val;
break;
case 0x59:
if ((dev->local & CMD_TYPE_649) || !(dev->local & CMD_TYPE_648))
dev->regs[addr] = val;
break;
case 0x53:
case 0x55:
dev->regs[addr] = val & 0xc0;
@@ -274,10 +443,32 @@ cmd646_pci_write(int func, int addr, uint8_t val, void *priv)
case 0x57:
dev->regs[addr] = (dev->regs[addr] & 0x10) | (val & 0xcc);
break;
case 0x70 ... 0x77:
case 0x64:
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = (dev->regs[addr] & 0xfc) | (val & 0x03);
break;
case 0x65:
if (dev->local & CMD_TYPE_648)
dev->regs[addr] = (dev->regs[addr] & 0x7f) | (val & 0x80);
break;
case 0x71:
if (dev->local & CMD_TYPE_648)
sff_bus_master_write(addr & 0x0f, val, dev->bm[0]);
else
sff_bus_master_write(addr & 0x0f, val & 0x03, dev->bm[0]);
break;
case 0x70:
case 0x72 ... 0x77:
sff_bus_master_write(addr & 0x0f, val, dev->bm[0]);
break;
case 0x78 ... 0x7f:
case 0x79:
if (dev->local & CMD_TYPE_648)
sff_bus_master_write(addr & 0x0f, val, dev->bm[1]);
else
sff_bus_master_write(addr & 0x0f, val & 0x03, dev->bm[1]);
break;
case 0x78:
case 0x7a ... 0x7f:
sff_bus_master_write(addr & 0x0f, val, dev->bm[1]);
break;
@@ -295,14 +486,18 @@ cmd646_pci_read(int func, int addr, void *priv)
if (func == 0x00) {
ret = dev->regs[addr];
if (addr == 0x50)
if ((addr == 0x09) && (dev->local & CMD_TYPE_648) && (dev->regs[0x0a] == 0x04))
ret = 0x00;
else if (addr == 0x50)
dev->regs[0x50] &= ~0x04;
else if (addr == 0x57)
dev->regs[0x57] &= ~0x10;
else if ((addr >= 0x70) && (addr <= 0x77))
ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]);
else if ((addr >= 0x78) && (addr <= 0x7f))
ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]);
ret = sff_bus_master_read(addr & 0x0f, dev->bm[1]);
else if ((dev->local & CMD_TYPE_648) && (addr >= 0x8c) && (addr <= 0x8f))
ret = dev->regs[(addr & 0x0f) | 0x20];
}
cmd646_log("[%04X:%08X] (%08X) cmd646_pci_read(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, ret);
@@ -310,22 +505,44 @@ cmd646_pci_read(int func, int addr, void *priv)
return ret;
}
static int
check_ch(cmd646_t *dev, int channel)
{
int ret = 0;
int min = 0;
int max = dev->single_channel ? 1 : 3;
if (dev->local & 0x80000) {
min += 4;
max += 4;
}
if ((channel >= min) && (channel <= max))
ret = 1;
return ret;
}
static void
cmd646_reset(void *priv)
{
cmd646_t *dev = (cmd646_t *) priv;
int i = 0;
for (i = 0; i < HDD_NUM; i++) {
if ((hdd[i].bus_type == HDD_BUS_ATAPI) && check_ch(dev, hdd[i].ide_channel) && hdd[i].priv)
scsi_disk_reset((scsi_common_t *) hdd[i].priv);
}
for (i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv)
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && check_ch(dev, cdrom[i].ide_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) && zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && check_ch(dev, rdisk_drives[i].ide_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) && mo_drives[i].priv)
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && check_ch(dev, mo_drives[i].ide_channel) && mo_drives[i].priv)
mo_reset((scsi_common_t *) mo_drives[i].priv);
}
@@ -336,16 +553,40 @@ cmd646_reset(void *priv)
dev->regs[0x00] = 0x95; /* CMD */
dev->regs[0x01] = 0x10;
dev->regs[0x02] = 0x46; /* PCI-0646 */
if (dev->local & CMD_TYPE_649)
dev->regs[0x02] = 0x49; /* PCI-0649 */
else if (dev->local & CMD_TYPE_648)
dev->regs[0x02] = 0x48; /* PCI-0648 */
else
dev->regs[0x02] = 0x46; /* PCI-0646 */
dev->regs[0x03] = 0x06;
dev->regs[0x04] = 0x00;
dev->regs[0x06] = 0x80;
dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */
dev->regs[0x09] = dev->local; /* Programming interface */
dev->regs[0x0a] = 0x01; /* IDE controller */
if ((dev->local & CMD_TYPE_648) && (dev->local & CMD648_RAID)) {
dev->regs[0x06] = 0x90;
dev->regs[0x08] = 0x02;
dev->regs[0x0a] = 0x04; /* RAID controller */
dev->regs[0x50] = 0x40; /* Enable Base address register R/W;
If 0, they return 0 and are read-only 8 */
/* Blank base addresses */
dev->regs[0x10] = 0x01;
dev->regs[0x14] = 0x01;
dev->regs[0x18] = 0x01;
dev->regs[0x1c] = 0x01;
} else {
dev->regs[0x06] = 0x80;
dev->regs[0x0a] = 0x01; /* IDE controller */
}
dev->regs[0x0b] = 0x01; /* Mass storage controller */
if ((dev->local & 0xffff) == 0x8a) {
if ((dev->local & CMD_TYPE_648) && (dev->local & CMD648_JP7))
for (int i = 0; i < 4; i++)
dev->regs[0x2c + i] = dev->regs[i];
if ((dev->regs[0x0a] == 0x01) && ((dev->regs[0x09] & 0x8a) == 0x8a)) {
dev->regs[0x50] = 0x40; /* Enable Base address register R/W;
If 0, they return 0 and are read-only 8 */
@@ -371,13 +612,47 @@ cmd646_reset(void *priv)
dev->regs[0x51] = 0x08;
dev->regs[0x57] = 0x0c;
dev->regs[0x59] = 0x40;
dev->irq_mode[0] = dev->irq_mode[1] = 0;
if (dev->local & CMD_TYPE_648) {
dev->regs[0x34] = 0x60;
dev->regs[0x4f] = (dev->local & CMD648_JP7) ? 0x02 : 0x00;
dev->regs[0x51] |= 0x04;
if (dev->local & CMD_TYPE_649) {
dev->regs[0x57] |= 0x80;
dev->regs[0x59] = 0x40;
} else
dev->regs[0x57] |= 0xc0;
dev->regs[0x60] = 0x01;
dev->regs[0x62] = 0x21;
dev->regs[0x63] = 0x06;
dev->regs[0x65] = 0x60;
dev->regs[0x67] = 0xf0;
/* 80-pin stuff. */
dev->regs[0x72] = 0x08;
dev->regs[0x7a] = 0x08;
dev->regs[0x79] = 0x83;
} else
dev->regs[0x59] = 0x40;
dev->irq_pin = PCI_INTA;
if ((dev->local & CMD_TYPE_648) && (dev->local & CMD648_RAID))
dev->irq_mode[0] = dev->irq_mode[1] = IRQ_MODE_PCI_IRQ_PIN;
else {
dev->irq_mode[0] = (dev->regs[0x09] & 0x01) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY;
dev->irq_mode[1] = (dev->regs[0x09] & 0x04) ? IRQ_MODE_PCI_IRQ_PIN : IRQ_MODE_LEGACY;
}
dev->irq_pin = PCI_INTA;
cmd646_ide_handlers(dev);
cmd646_ide_bm_handlers(dev);
cmd646_bios_handler(dev);
}
static void
@@ -391,42 +666,147 @@ cmd646_close(void *priv)
static void *
cmd646_init(const device_t *info)
{
cmd646_t *dev = (cmd646_t *) calloc(1, sizeof(cmd646_t));
cmd646_t *dev = (cmd646_t *) calloc(1, sizeof(cmd646_t));
int first = 0;
dev->local = info->local;
device_add(&ide_pci_2ch_device);
if (info->local & 0x80000)
pci_add_card(PCI_ADD_NORMAL, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot);
else
if (info->local & 0x80000) {
first = 2;
device_add(&ide_pci_ter_qua_2ch_device);
} else
device_add(&ide_pci_2ch_device);
if (info->local & CMD64X_ONBOARD)
pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot);
else
pci_add_card(PCI_ADD_NORMAL, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot);
dev->single_channel = !!(info->local & 0x20000);
dev->bm[0] = device_add_inst(&sff8038i_device, 1);
dev->bm[0] = device_add_inst(&sff8038i_device, first + 1);
if (!dev->single_channel)
dev->bm[1] = device_add_inst(&sff8038i_device, 2);
dev->bm[1] = device_add_inst(&sff8038i_device, first + 2);
ide_set_bus_master(0, cmd646_bus_master_dma_0, cmd646_set_irq_0, dev);
ide_set_bus_master(first, cmd646_bus_master_dma_0, cmd646_set_irq_0, dev);
if (!dev->single_channel)
ide_set_bus_master(1, cmd646_bus_master_dma_1, cmd646_set_irq_1, dev);
ide_set_bus_master(first + 1, cmd646_bus_master_dma_1, cmd646_set_irq_1, dev);
sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY);
if (!dev->single_channel)
sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
sff_set_slot(dev->bm[0], dev->pci_slot);
sff_set_slot(dev->bm[1], dev->pci_slot);
if (dev->local & CMD_TYPE_648) {
sff_set_ven_handlers(dev->bm[0], cmd646_bm_write, cmd646_bm_read, dev);
sff_set_ven_handlers(dev->bm[1], cmd646_bm_write, cmd646_bm_read, dev);
dev->has_bios = device_get_config_int("bios");
if (dev->has_bios) {
char *fn = NULL;
if (dev->local & CMD_TYPE_649) {
const char *bios_rev = (char *) device_get_config_bios("bios_rev");
fn = (char *) device_get_bios_file(info, bios_rev, 0);
dev->rom_addr_size = device_get_bios_file_size(info, bios_rev);
} else {
fn = CMD648_BIOS_FILE;
dev->rom_addr_size = 0x00004000;
}
dev->rom_addr_mask = dev->rom_addr_size - 1;
rom_init(&dev->bios_rom, fn,
0x000d0000, dev->rom_addr_size, dev->rom_addr_mask, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_disable(&dev->bios_rom.mapping);
}
}
cmd646_reset(dev);
if (dev->local & CMD_TYPE_648)
for (int i = 0; i < 4; i++)
dev->regs[0x2c + i] = dev->regs[i];
return dev;
}
static const device_config_t cmd648_config[] = {
{
.name = "bios",
.description = "Enable BIOS",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
// clang-format on
static const device_config_t cmd649_config[] = {
{
.name = "bios",
.description = "Enable BIOS",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "bios_rev",
.description = "BIOS Revision",
.type = CONFIG_BIOS,
.default_string = "rev_2301",
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.bios = {
{
.name = "Revision 1.9.14",
.internal_name = "rev_1914",
.bios_type = BIOS_NORMAL,
.files_no = 1,
.local = 0,
.size = 16384,
.files = { CMD649_REV_2301_BIOS_FILE, "" }
},
{
.name = "Revision 2.3.01",
.internal_name = "rev_2301",
.bios_type = BIOS_NORMAL,
.files_no = 1,
.local = 0,
.size = 65536,
.files = { CMD649_REV_2301_BIOS_FILE, "" }
},
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
};
// clang-format on
const device_t ide_cmd646_device = {
.name = "CMD PCI-0646",
.internal_name = "ide_cmd646",
.flags = DEVICE_PCI,
.local = 0x8a,
.local = 0x000008a | CMD64X_ONBOARD,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
@@ -440,7 +820,7 @@ const device_t ide_cmd646_legacy_only_device = {
.name = "CMD PCI-0646 (Legacy Mode Only)",
.internal_name = "ide_cmd646_legacy_only",
.flags = DEVICE_PCI,
.local = 0x80,
.local = 0x0000080 | CMD64X_ONBOARD,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
@@ -451,10 +831,10 @@ const device_t ide_cmd646_legacy_only_device = {
};
const device_t ide_cmd646_single_channel_device = {
.name = "CMD PCI-0646",
.name = "CMD PCI-0646 (Single Channel)",
.internal_name = "ide_cmd646_single_channel",
.flags = DEVICE_PCI,
.local = 0x2008a,
.local = 0x002008a | CMD64X_ONBOARD,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
@@ -463,3 +843,59 @@ const device_t ide_cmd646_single_channel_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t ide_cmd646_ter_qua_device = {
.name = "CMD PCI-0646 (Tertiary and Quaternary)",
.internal_name = "ide_cmd646_ter_qua",
.flags = DEVICE_PCI,
.local = 0x008008f,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_cmd648_ter_qua_device = {
.name = "CMD PCI-0648 (Tertiary and Quaternary)",
.internal_name = "ide_cmd648_ter_qua",
.flags = DEVICE_PCI,
.local = 0x0d8008f,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = cmd648_config
};
const device_t ide_cmd648_ter_qua_onboard_device = {
.name = "CMD PCI-0648 (Tertiary and Quaternary) On-Board",
.internal_name = "ide_cmd648_ter_qua_onboard",
.flags = DEVICE_PCI,
.local = 0x0d8008f | CMD64X_ONBOARD,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_cmd649_ter_qua_device = {
.name = "CMD PCI-0649 (Tertiary and Quaternary)",
.internal_name = "ide_cmd649_ter_qua",
.flags = DEVICE_PCI,
.local = 0x0f8008f,
.init = cmd646_init,
.close = cmd646_close,
.reset = cmd646_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = cmd649_config
};

View File

@@ -34,7 +34,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/mo.h>
typedef struct rz1000_t {
@@ -182,10 +182,10 @@ rz1000_reset(void *priv)
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) &&
(zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && (rdisk_drives[i].ide_channel >= min_channel) &&
(rdisk_drives[i].ide_channel <= max_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&
@@ -275,7 +275,7 @@ const device_t ide_rz1000_pci_device = {
};
const device_t ide_rz1000_pci_single_channel_device = {
.name = "PC Technology RZ-1000 PCI",
.name = "PC Technology RZ-1000 PCI (Single Channel)",
.internal_name = "ide_rz1000_pci_single_channel",
.flags = DEVICE_PCI,
.local = 0x20000,

View File

@@ -42,7 +42,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/mo.h>
#include <86box/plat_unused.h>
@@ -118,6 +118,9 @@ sff_bus_master_write(uint16_t port, uint8_t val, void *priv)
sff_log("SFF-8038i Bus master BYTE write: %04X %02X\n", port, val);
if (dev->ven_write != NULL)
val = dev->ven_write(port, val, dev->priv);
switch (port & 7) {
case 0:
sff_log("sff Cmd : val = %02X, old = %02X\n", val, dev->command);
@@ -255,6 +258,9 @@ sff_bus_master_read(uint16_t port, void *priv)
break;
}
if (dev->ven_read != NULL)
ret= dev->ven_read(port, ret, dev->priv);
sff_log("SFF-8038i Bus master BYTE read : %04X %02X\n", port, ret);
return ret;
@@ -489,10 +495,10 @@ sff_reset(void *priv)
cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (uint8_t i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel < 4) &&
zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
for (uint8_t i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && (rdisk_drives[i].ide_channel < 4) &&
rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (uint8_t i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) &&
@@ -569,6 +575,16 @@ sff_set_mirq(sff8038i_t *dev, uint8_t mirq)
dev->mirq = mirq;
}
void
sff_set_ven_handlers(sff8038i_t *dev, uint8_t (*ven_write)(uint16_t port, uint8_t val, void *priv),
uint8_t (*ven_read)(uint16_t port, uint8_t val, void *priv), void *priv)
{
dev->ven_write = ven_write;
dev->ven_read = ven_read;
dev->priv = priv;
}
static void
sff_close(void *priv)
{

View File

@@ -34,7 +34,7 @@
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/rdisk.h>
#include <86box/mo.h>
typedef struct w83769f_t {
@@ -297,10 +297,10 @@ w83769f_reset(void *priv)
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) &&
(zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && (rdisk_drives[i].ide_channel >= min_channel) &&
(rdisk_drives[i].ide_channel <= max_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&

View File

@@ -1915,7 +1915,7 @@ victor_v86p_available(void)
static const device_config_t dtc_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -1969,7 +1969,7 @@ static const device_config_t st11_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -2006,7 +2006,7 @@ static const device_config_t st11_config[] = {
static const device_config_t wd_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -2089,7 +2089,7 @@ static const device_config_t wd_nobios_config[] = {
static const device_config_t wd_rll_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -2153,7 +2153,7 @@ static const device_config_t wd_rll_config[] = {
static const device_config_t wd1004a_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -2202,7 +2202,7 @@ static const device_config_t wd1004a_config[] = {
static const device_config_t wd1004_rll_config[] = {
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,

View File

@@ -82,6 +82,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -101,11 +102,15 @@
#include <86box/ui.h>
#include <86box/hdc.h>
#include <86box/hdd.h>
#include "cpu.h"
#define HDC_TIME (250 * TIMER_USEC)
#define WD_REV_1_BIOS_FILE "roms/hdd/xta/idexywd2.bin"
#define WD_REV_2_BIOS_FILE "roms/hdd/xta/infowdbios.rom"
#define PC3086_BIOS_FILE "roms/machines/pc3086/c800.bin"
#define ST50X_BIOS_FILE "roms/hdd/xta/ST05XBIO.BIN"
#define PC5086_BIOS_FILE "roms/machines/pc5086/c800.bin"
enum {
STATE_IDLE = 0,
@@ -236,6 +241,7 @@ typedef struct hdc_t {
const char *name; /* controller name */
uint16_t base; /* controller base I/O address */
uint8_t sw; /* controller switches */
int8_t irq; /* controller IRQ channel */
int8_t dma; /* controller DMA channel */
int8_t type; /* controller type ID */
@@ -269,6 +275,10 @@ typedef struct hdc_t {
uint8_t sector_buf[512]; /* sector buffer */
} hdc_t;
typedef struct hdc_dual_t {
hdc_t *hdc[2];
} hdc_dual_t;
#ifdef ENABLE_XTA_LOG
int xta_do_log = ENABLE_XTA_LOG;
@@ -882,7 +892,7 @@ hdc_read(uint16_t port, void *priv)
hdc_t *dev = (hdc_t *) priv;
uint8_t ret = 0xff;
switch (port & 7) {
switch (port & 3) {
case 0: /* DATA register */
dev->status &= ~STAT_IRQ;
@@ -915,7 +925,7 @@ hdc_read(uint16_t port, void *priv)
break;
case 2: /* "read option jumpers" */
ret = 0xff; /* all switches off */
ret = dev->sw;
break;
default:
@@ -931,7 +941,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
{
hdc_t *dev = (hdc_t *) priv;
switch (port & 7) {
switch (port & 3) {
case 0: /* DATA register */
if (dev->state == STATE_RDATA) {
if (!(dev->status & STAT_REQ)) {
@@ -989,38 +999,92 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
}
}
void
xta_handler(void *priv, int set)
{
hdc_t *dev = (hdc_t *) priv;
io_handler(set, dev->base, 4,
hdc_read, NULL, NULL, hdc_write, NULL, NULL, dev);
}
static void *
xta_init(const device_t *info)
xta_init_common(const device_t *info, int type)
{
drive_t *drive;
const char *bios_rev = NULL;
const char *fn = NULL;
hdc_t *dev;
int c;
int max = XTA_NUM;
int min = 0;
int max = XTA_NUM;
/* Allocate and initialize device block. */
dev = calloc(1, sizeof(hdc_t));
dev->type = info->local;
dev->sw = 0xff; /* all switches off */
dev->type = type;
/* Do per-controller-type setup. */
switch (dev->type) {
case 0: /* WDXT-150, with BIOS */
dev->name = "WDXT-150";
bios_rev = (char *) device_get_config_bios("bios_rev");
fn = (char *) device_get_bios_file(info, bios_rev, 0);
/* Revision 2 actually supports 2 drives using drive select. */
if (!strcmp(bios_rev, "rev_1"))
max = 1;
#ifdef SELECTABLE_BASE
dev->base = device_get_config_hex16("base");
#else
dev->base = 0x0320;
#endif
dev->irq = device_get_config_int("irq");
dev->rom_addr = device_get_config_hex20("bios_addr");
dev->dma = 3;
bios_rev = (char *) device_get_config_bios("bios_rev");
fn = (char *) device_get_bios_file(info, bios_rev, 0);
max = 1;
case 1: /* Amstrad PC3086 */
dev->name = "WDXT-150 PC3086";
dev->rom_addr = 0xc8000;
fn = PC3086_BIOS_FILE;
dev->base = 0x0320;
dev->irq = 5;
dev->dma = 3;
break;
case 1: /* EuroPC */
dev->name = "HD20";
dev->base = 0x0320;
dev->irq = 5;
dev->dma = 3;
case 2: /* EuroPC */
case 5: /* Amstrad PC5086 */
switch (dev->type) {
case 2:
dev->name = "HD20";
break;
case 5:
dev->name = "ST-50X PC5086";
dev->rom_addr = 0xc8000;
fn = PC5086_BIOS_FILE;
max = 1;
break;
}
dev->base = 0x0320;
dev->irq = 5;
dev->dma = 3;
break;
case 3: /* Seagate ST-05X Standalone */
case 4: /* Seagate ST-05X Standalone secondary device */
switch (dev->type) {
case 3:
dev->name = "ST-50X PRI";
dev->rom_addr = device_get_config_hex20("bios_addr");
fn = ST50X_BIOS_FILE;
max = 1;
break;
case 4:
dev->name = "ST-50X SEC";
min = 1;
break;
}
dev->base = 0x0320 + (dev->type & 4);
dev->irq = 5;
dev->dma = 3;
break;
default:
@@ -1031,14 +1095,16 @@ xta_init(const device_t *info)
dev->name, dev->base, dev->irq, dev->dma);
if (dev->rom_addr != 0x000000)
xta_log(", BIOS=%06X", dev->rom_addr);
xta_log(")\n");
/* Load any disks for this device class. */
c = 0;
for (uint8_t i = 0; i < HDD_NUM; i++) {
if ((hdd[i].bus_type == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) {
drive = &dev->drives[hdd[i].xta_channel];
if ((hdd[i].bus_type == HDD_BUS_XTA) && (hdd[i].xta_channel >= min) && (hdd[i].xta_channel < max)) {
if (dev->type == 4)
drive = &dev->drives[0];
else
drive = &dev->drives[hdd[i].xta_channel];
if (!hdd_image_load(i)) {
drive->present = 0;
@@ -1058,6 +1124,156 @@ xta_init(const device_t *info)
drive->hpc = drive->cfg_hpc;
drive->tracks = drive->cfg_tracks;
if (dev->type == 0) {
if (!strcmp(bios_rev, "rev_1")) {
/*
WDXT-150, Revision 1 switches:
- Bit 6: 1 = IBM (INT 13h), 0 = Tandy (INT 0Ah).
- Bit 5: 1 = 17 sectors per track, 0 = 27 sectors per track.
- Drive 0, bits 1,0:
- With bit 4 set:
- 0,0 = 820/4/17;
- 0,1 = 615/4/17;
- 1,0 = 782/4/17;
- 1,1 = 782/2/17.
- With bit 4 clear:
- 0,0 = 1024/4/17;
- 0,1 = 940/4/17;
- 1,0 = 1024/4/17;
- 1,1 = 1024/2/17.
- Drive 1, bits 3,2:
- With bit 4 set:
- 0,0 = 820/4/17;
- 0,1 = 615/4/17;
- 1,0 = 782/4/17;
- 1,1 = 782/2/17.
- With bit 4 clear:
- 0,0 = 1024/4/17;
- 0,1 = 940/4/17;
- 1,0 = 1024/4/17;
- 1,1 = 1024/2/17.
*/
if (drive->tracks == 940)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
else if (drive->tracks == 1024) {
if (drive->hpc == 4)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 782) {
if (drive->hpc == 4)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x02 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 820)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
} else {
/*
WDXT-150, Revision 2 switches:
- Drive 0, bits 1,0:
- With bit 4 set:
- 0,0 = 612/4/17;
- 0,1 = 615/6/17;
- 1,0 = 977/5/17;
- 1,1 = 615/4/17.
- With bit 4 clear:
- 0,0 = 976/4/17;
- 0,1 = 1024/3/17;
- 1,0 = 1024/4/17;
- 1,1 = 1024/2/17.
- Drive 1, bits 3,2:
- With bit 4 set:
- 0,0 = 612/4/17;
- 0,1 = 615/6/17;
- 1,0 = 977/5/17;
- 1,1 = 615/4/17.
- With bit 4 clear:
- 0,0 = 976/4/17;
- 0,1 = 1024/3/17;
- 1,0 = 1024/4/17;
- 1,1 = 1024/2/17.
*/
if (drive->tracks == 976)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else if (drive->tracks == 1024) {
if (drive->hpc == 3)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
else if (drive->hpc == 4)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x02 << (c << 1));
else
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 615) {
if (drive->hpc == 6)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 612)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x02 << (c << 1));
}
} else if (dev->type == 1) {
/*
WDXT-150, Revision 3 (Amstrad PC3086) switches:
- Drive 0, bits 1,0:
- With bit 4 set:
- 0,0 = 612/4/17;
- 0,1 = 615/6/17;
- 1,0 = 977/5/17;
- 1,1 = 615/4/17.
- With bit 4 clear:
- 0,0 = 971/4/17;
- 0,1 = 976/6/17;
- 1,0 = 1024/5/17;
- 1,1 = 976/4/17.
- Drive 1, bits 3,2:
- With bit 4 set:
- 0,0 = 612/4/17;
- 0,1 = 615/6/17;
- 1,0 = 977/5/17;
- 1,1 = 615/4/17.
- With bit 4 clear:
- 0,0 = 971/4/17;
- 0,1 = 976/6/17;
- 1,0 = 1024/5/17;
- 1,1 = 976/4/17.
*/
if (drive->tracks == 971)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else if (drive->tracks == 976) {
if (drive->hpc == 6)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
else
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 1024)
dev->sw = ((dev->sw & 0xef) & (c ? 0xf3 : 0xfc)) | (0x02 << (c << 1));
else if (drive->tracks == 615) {
if (drive->hpc == 6)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x01 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x03 << (c << 1));
} else if (drive->tracks == 612)
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x00 << (c << 1));
else
dev->sw = (dev->sw & (c ? 0xf3 : 0xfc)) | (0x02 << (c << 1));
} else if ((dev->type >= 3) && (dev->type <= 5)) {
/*
Bits 1, 0:
- 1, 1 = 615/4/17 (20 MB);
- 1, 0 or 0, 0 = 980/5/17 (40 MB);
- 0, 1 = 615/6/17 (30 MB).
- 0, 0 is actually no hard disk present - switch port supposed to be readable always?
*/
if (drive->tracks == 980)
dev->sw = 0xfe;
else if (drive->hpc == 6)
dev->sw = 0xfd;
else
dev->sw = 0xff;
}
xta_log("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n",
dev->name, hdd[i].xta_channel, drive->tracks,
drive->hpc, drive->spt, i);
@@ -1083,6 +1299,23 @@ xta_init(const device_t *info)
return dev;
}
static void *
xta_init(const device_t *info)
{
return xta_init_common(info, info->local);
}
static void *
xta_st50x_init(const device_t *info)
{
hdc_dual_t *dev = (hdc_dual_t *) calloc(1, sizeof(hdc_dual_t));
dev->hdc[0] = xta_init_common(info, info->local);
dev->hdc[1] = xta_init_common(info, 4);
return dev;
}
static void
xta_close(void *priv)
{
@@ -1104,6 +1337,21 @@ xta_close(void *priv)
free(dev);
}
static void
xta_st50x_close(void *priv)
{
hdc_dual_t *dev = (hdc_dual_t *) priv;
xta_close(dev->hdc[1]);
xta_close(dev->hdc[0]);
}
static int
st50x_available(void)
{
return (rom_present(ST50X_BIOS_FILE));
}
static const device_config_t wdxt150_config[] = {
// clang-format off
{
@@ -1136,6 +1384,7 @@ static const device_config_t wdxt150_config[] = {
{ .files_no = 0 }
},
},
#ifdef SELECTABLE_BASE
{
.name = "base",
.description = "Address",
@@ -1151,6 +1400,7 @@ static const device_config_t wdxt150_config[] = {
},
.bios = { { 0 } }
},
#endif
{
.name = "irq",
.description = "IRQ",
@@ -1168,7 +1418,28 @@ static const device_config_t wdxt150_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "C800H", .value = 0xc8000 },
{ .description = "CA00H", .value = 0xca000 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format off
};
static const device_config_t st50x_config[] = {
// clang-format off
{
.name = "bios_addr",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,
@@ -1199,11 +1470,53 @@ const device_t xta_wdxt150_device = {
.config = wdxt150_config
};
const device_t xta_wdxt150_pc3086_device = {
.name = "WDXT-150 XTA Fixed Disk Controller (PC3086)",
.internal_name = "xta_wdxt150",
.flags = DEVICE_ISA,
.local = 1,
.init = xta_init,
.close = xta_close,
.reset = NULL,
.available = NULL /*xta_available*/,
.speed_changed = NULL,
.force_redraw = NULL,
.config = wdxt150_config
};
const device_t xta_hd20_device = {
.name = "EuroPC HD20 Fixed Disk Controller",
.internal_name = "xta_hd20",
.flags = DEVICE_ISA,
.local = 1,
.local = 2,
.init = xta_init,
.close = xta_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t xta_st50x_device = {
.name = "ST-50X Fixed Disk Controller",
.internal_name = "xta_st50x",
.flags = DEVICE_ISA,
.local = 3,
.init = xta_st50x_init,
.close = xta_st50x_close,
.reset = NULL,
.available = st50x_available,
.speed_changed = NULL,
.force_redraw = NULL,
.config = st50x_config
};
const device_t xta_st50x_pc5086_device = {
.name = "ST-50X Fixed Disk Controller (PC5086)",
.internal_name = "xta_st50x_pc5086",
.flags = DEVICE_ISA,
.local = 5,
.init = xta_init,
.close = xta_close,
.reset = NULL,

View File

@@ -341,7 +341,7 @@ static const device_config_t xtide_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xd0000,

View File

@@ -78,6 +78,12 @@ no_cdrom:
if (!strcmp(str, "scsi"))
return HDD_BUS_SCSI;
if (!strcmp(str, "mitsumi"))
return CDROM_BUS_MITSUMI;
if (!strcmp(str, "mke"))
return CDROM_BUS_MKE;
return 0;
}
@@ -89,6 +95,17 @@ hdd_bus_to_string(int bus, UNUSED(int cdrom))
switch (bus) {
default:
if (cdrom) {
switch (bus) {
case CDROM_BUS_MITSUMI:
s = "mitsumi";
break;
case CDROM_BUS_MKE:
s = "mke";
break;
}
break;
}
case HDD_BUS_DISABLED:
break;
@@ -143,8 +160,12 @@ hdd_seek_get_time(hard_disk_t *hdd, uint32_t dst_addr, uint8_t operation, uint8_
const hdd_zone_t *zone = NULL;
if (hdd->num_zones <= 0) {
#ifdef DO_FATAL
fatal("hdd_seek_get_time(): hdd->num_zones < 0)\n");
return 0.0;
#else
return 1000.0;
#endif
}
for (uint32_t i = 0; i < hdd->num_zones; i++) {
zone = &hdd->zones[i];

View File

@@ -152,6 +152,14 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert)
{
const int was_empty = mo_is_empty(dev->id);
int ret = 0;
int offs = 0;
if (strstr(fn, "wp://") == fn) {
offs = 5;
dev->drv->read_only = 1;
}
fn += offs;
if (dev->drv == NULL)
mo_eject(dev->id);
@@ -202,7 +210,7 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert)
log_fatal(dev->log, "mo_load(): Error seeking to the beginning of "
"the file\n");
strncpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path) - 1);
strncpy(dev->drv->image_path, fn - offs, sizeof(dev->drv->image_path) - 1);
ret = 1;
} else
@@ -218,6 +226,9 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert)
if (was_empty)
mo_insert((mo_t *) dev);
}
if (ret)
ui_sb_update_icon_wp(SB_MO | dev->id, dev->drv->read_only);
}
void
@@ -2005,7 +2016,7 @@ mo_get_max(UNUSED(const ide_t *ide), const int ide_has_dma, const int type)
switch (type) {
case TYPE_PIO:
ret = ide_has_dma ? 3 : 0;
ret = 3;
break;
case TYPE_SDMA:
default:
@@ -2032,10 +2043,10 @@ mo_get_timings(UNUSED(const ide_t *ide), const int ide_has_dma, const int type)
ret = ide_has_dma ? 0x96 : 0;
break;
case TIMINGS_PIO:
ret = ide_has_dma ? 0xb4 : 0;
ret = 0xf0;
break;
case TIMINGS_PIO_FC:
ret = ide_has_dma ? 0xb4 : 0;
ret = 0xb4;
break;
default:
ret = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -335,14 +335,18 @@ fdc_int(fdc_t *fdc, int set_fintr)
{
int ienable = 0;
if (!(fdc->flags & FDC_FLAG_PCJR))
if (fdc->flags & FDC_FLAG_PS2_MCA)
ienable = 1;
else if (!(fdc->flags & FDC_FLAG_PCJR))
ienable = !!(fdc->dor & 8);
if (ienable)
picint(1 << fdc->irq);
if (ienable) {
if (fdc->irq != 0xff)
picint(1 << fdc->irq);
if (set_fintr)
fdc->fintr = 1;
if (set_fintr)
fdc->fintr = 1;
}
fdc_log("fdc_int(%i): fdc->fintr = %i\n", set_fintr, fdc->fintr);
}
@@ -355,7 +359,7 @@ fdc_watchdog_poll(void *priv)
if (fdc->watchdog_count)
timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC);
else {
if (fdc->dor & 0x20)
if ((fdc->dor & 0x20) && (fdc->irq != 0xff))
picint(1 << fdc->irq);
}
}
@@ -435,6 +439,44 @@ fdc_set_media_id(fdc_t *fdc, int id, int set)
fdc->media_id = (fdc->media_id & ~(1 << id)) | (set << id);
}
void
fdc_set_flags(fdc_t *fdc, int flags)
{
fdc->flags |= flags;
}
void
fdc_clear_flags(fdc_t *fdc, int flags)
{
fdc->flags &= ~flags;
}
void
fdc_set_fdd_changed(int drive, int changed)
{
if (changed)
fdd_changed[drive] = 1;
}
uint8_t
fdc_get_fdd_changed(int drive)
{
uint8_t ret = !!fdd_changed[drive];
return ret;
}
uint8_t
fdc_get_shadow(fdc_t *fdc)
{
uint8_t ret = (fdc->rate & 0x03) |
((fdc->pretrk & 0x07) << 2) |
(fdc->power_down ? 0x40 : 0x00) |
((fdc_read(0x03f2, fdc) & 0x04) ? 0x80 : 0x00);
return ret;
}
int
fdc_get_boot_drive(fdc_t *fdc)
{
@@ -762,9 +804,17 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->st0 &= ~0x07;
fdc->st0 |= (fdd_get_head(0) ? 4 : 0);
} else {
if (!(val & 8) && (fdc->dor & 8)) {
fdc->tc = 1;
fdc_int(fdc, 1);
/*
Writing this bit to logic "1" will enable the DRQ,
nDACK, TC and FINTR outputs. This bit being a
logic "0" will disable the nDACK and TC inputs, and
hold the DRQ and FINTR outputs in a high
impedance state.
*/
if (!(val & 8) && (fdc->dor & 8) && !(fdc->flags & FDC_FLAG_PS2_MCA)) {
fdc->tc = 1;
fdc->fintr = 0;
picintc(1 << fdc->irq);
}
if (!(val & 4)) {
fdd_stop(real_drive(fdc, val & 3));

View File

@@ -110,7 +110,7 @@ static const device_config_t b215_config[] = {
// clang-format off
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xca000,

View File

@@ -162,7 +162,7 @@ static const device_config_t monster_fdc_config[] = {
#endif
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xc8000,

View File

@@ -123,7 +123,7 @@ static const device_config_t pii_config[] = {
// clang-format off
{
.name = "bios_addr",
.description = "BIOS Address",
.description = "BIOS address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xce000,

View File

@@ -459,11 +459,17 @@ fdd_load(int drive, char *fn)
int size;
const char *p;
FILE *fp;
int offs = 0;
fdd_log("FDD: loading drive %d with '%s'\n", drive, fn);
if (!fn)
return;
if (strstr(fn, "wp://") == fn) {
offs = 5;
ui_writeprot[drive] = 1;
}
fn += offs;
p = path_get_extension(fn);
if (!p)
return;
@@ -476,13 +482,14 @@ fdd_load(int drive, char *fn)
while (loaders[c].ext) {
if (!strcasecmp(p, (char *) loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) {
driveloaders[drive] = c;
if (floppyfns[drive] != fn)
strcpy(floppyfns[drive], fn);
if (floppyfns[drive] != (fn - offs))
strcpy(floppyfns[drive], fn - offs);
d86f_setup(drive);
loaders[c].load(drive, floppyfns[drive]);
loaders[c].load(drive, floppyfns[drive] + offs);
drive_empty[drive] = 0;
fdd_forced_seek(drive, 0);
fdd_changed[drive] = 1;
ui_sb_update_icon_wp(SB_FLOPPY | drive, ui_writeprot[drive]);
return;
}
c++;
@@ -532,7 +539,7 @@ fdd_hole(int drive)
static __inline uint64_t
fdd_byteperiod(int drive)
{
if (!fdd_get_turbo(drive) && drives[drive].byteperiod)
if (drives[drive].byteperiod)
return drives[drive].byteperiod(drive);
else
return 32ULL * TIMER_USEC;

View File

@@ -758,36 +758,43 @@ d86f_get_encoding(int drive)
uint64_t
d86f_byteperiod(int drive)
{
double dusec = (double) TIMER_USEC;
double p = 2.0;
d86f_t *dev = d86f[drive];
uint64_t ret = 32ULL * TIMER_USEC;
switch (d86f_track_flags(drive) & 0x0f) {
case 0x02: /* 125 kbps, FM */
p = 4.0;
break;
case 0x01: /* 150 kbps, FM */
p = 20.0 / 6.0;
break;
case 0x0a: /* 250 kbps, MFM */
case 0x00: /* 250 kbps, FM */
default:
p = 2.0;
break;
case 0x09: /* 300 kbps, MFM */
p = 10.0 / 6.0;
break;
case 0x08: /* 500 kbps, MFM */
p = 1.0;
break;
case 0x0b: /* 1000 kbps, MFM */
p = 0.5;
break;
case 0x0d: /* 2000 kbps, MFM */
p = 0.25;
break;
if (!fdd_get_turbo(drive) || (dev->version != 0x0063) || (dev->state == STATE_SECTOR_NOT_FOUND)) {
double dusec = (double) TIMER_USEC;
double p = 2.0;
switch (d86f_track_flags(drive) & 0x0f) {
case 0x02: /* 125 kbps, FM */
p = 4.0;
break;
case 0x01: /* 150 kbps, FM */
p = 20.0 / 6.0;
break;
case 0x0a: /* 250 kbps, MFM */
case 0x00: /* 250 kbps, FM */
default:
p = 2.0;
break;
case 0x09: /* 300 kbps, MFM */
p = 10.0 / 6.0;
break;
case 0x08: /* 500 kbps, MFM */
p = 1.0;
break;
case 0x0b: /* 1000 kbps, MFM */
p = 0.5;
break;
case 0x0d: /* 2000 kbps, MFM */
p = 0.25;
break;
}
ret = (uint64_t) (p * dusec);
}
return (uint64_t) (p * dusec);
return ret;
}
int
@@ -2463,16 +2470,17 @@ d86f_poll(int drive)
dev->state = STATE_SECTOR_NOT_FOUND;
}
if (fdd_get_turbo(drive) && (dev->version == 0x0063)) {
d86f_turbo_poll(drive, side);
return;
}
if ((dev->state != STATE_IDLE) && (dev->state != STATE_SECTOR_NOT_FOUND) && ((dev->state & 0xF8) != 0xE8)) {
if (!d86f_can_read_address(drive))
dev->state = STATE_SECTOR_NOT_FOUND;
}
/* Do normal poll if DENSEL is wrong, because Windows 95 is very strict about timings there. */
if (fdd_get_turbo(drive) && (dev->version == 0x0063) && (dev->state != STATE_SECTOR_NOT_FOUND)) {
d86f_turbo_poll(drive, side);
return;
}
if ((dev->state != STATE_02_SPIN_TO_INDEX) && (dev->state != STATE_0D_SPIN_TO_INDEX))
d86f_get_bit(drive, side ^ 1);
@@ -2577,12 +2585,6 @@ d86f_poll(int drive)
d86f_advance_bit(drive, side);
if (d86f_wrong_densel(drive) && (dev->state != STATE_IDLE)) {
dev->state = STATE_IDLE;
fdc_noidam(d86f_fdc);
return;
}
if ((dev->index_count == 2) && (dev->state != STATE_IDLE)) {
switch (dev->state) {
case STATE_0A_FIND_ID:
@@ -3277,7 +3279,12 @@ d86f_readsector(int drive, int sector, int track, int side, int rate, int sector
if (!ret)
return;
if (sector == SECTOR_FIRST)
if (d86f_wrong_densel(drive)) {
dev->state = STATE_SECTOR_NOT_FOUND;
if (fdd_get_turbo(drive))
dev->track_pos = 0;
} else if (sector == SECTOR_FIRST)
dev->state = STATE_02_SPIN_TO_INDEX;
else if (sector == SECTOR_NEXT)
dev->state = STATE_02_FIND_ID;
@@ -3302,7 +3309,13 @@ d86f_writesector(int drive, int sector, int track, int side, int rate, int secto
if (!ret)
return;
dev->state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID;
if (d86f_wrong_densel(drive)) {
dev->state = STATE_SECTOR_NOT_FOUND;
if (fdd_get_turbo(drive))
dev->track_pos = 0;
} else
dev->state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID;
}
void
@@ -3315,7 +3328,13 @@ d86f_comparesector(int drive, int sector, int track, int side, int rate, int sec
if (!ret)
return;
dev->state = STATE_11_FIND_ID;
if (d86f_wrong_densel(drive)) {
dev->state = STATE_SECTOR_NOT_FOUND;
if (fdd_get_turbo(drive))
dev->track_pos = 0;
} else
dev->state = STATE_11_FIND_ID;
}
void
@@ -3336,7 +3355,13 @@ d86f_readaddress(int drive, UNUSED(int side), UNUSED(int rate))
dev->id_found = 0;
dev->dma_over = 0;
dev->state = STATE_0A_FIND_ID;
if (d86f_wrong_densel(drive)) {
dev->state = STATE_SECTOR_NOT_FOUND;
if (fdd_get_turbo(drive))
dev->track_pos = 0;
} else
dev->state = STATE_0A_FIND_ID;
}
void
@@ -3438,7 +3463,13 @@ d86f_common_format(int drive, int side, UNUSED(int rate), uint8_t fill, int prox
dev->index_count = dev->error_condition = dev->satisfying_bytes = dev->sector_count = 0;
dev->dma_over = 0;
dev->state = STATE_0D_SPIN_TO_INDEX;
if (d86f_wrong_densel(drive) && !proxy) {
dev->state = STATE_SECTOR_NOT_FOUND;
if (fdd_get_turbo(drive))
dev->track_pos = 0;
} else
dev->state = STATE_0D_SPIN_TO_INDEX;
}
void

View File

@@ -61,13 +61,13 @@ typedef struct _joystick_instance_ {
uint8_t state;
g_axis_t axis[4];
const joystick_if_t *intf;
void *dat;
const joystick_t *intf;
void *dat;
} joystick_instance_t;
int joystick_type = JS_TYPE_NONE;
int joystick_type[GAMEPORT_MAX] = { JS_TYPE_NONE, JS_TYPE_NONE };
static const joystick_if_t joystick_none = {
static const joystick_t joystick_none = {
.name = "None",
.internal_name = "none",
.init = NULL,
@@ -86,7 +86,7 @@ static const joystick_if_t joystick_none = {
};
static const struct {
const joystick_if_t *joystick;
const joystick_t *joystick;
} joysticks[] = {
{ &joystick_none },
{ &joystick_2axis_2button },
@@ -100,7 +100,7 @@ static const struct {
{ &joystick_3axis_2button },
{ &joystick_2button_yoke_throttle },
{ &joystick_3axis_4button },
{ &joystick_win95_steering_wheel }, // Temp
{ &joystick_win95_steering_wheel },
{ &joystick_4button_yoke_throttle },
{ &joystick_4axis_4button },
{ &joystick_ch_flightstick_pro },
@@ -114,24 +114,39 @@ static const struct {
static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL };
static uint8_t gameport_pnp_rom[] = {
0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0002, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
0x82, 0x09, 0x00, 'G', 'a', 'm', 'e', ' ', 'P', 'o', 'r', 't', /* ANSI identifier */
/* BOX0002, serial 0, dummy checksum (filled in by isapnp_add_card) */
0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
/* PnP version 1.0, vendor version 1.0 */
0x0a, 0x10, 0x10,
/* ANSI identifier */
0x82, 0x09, 0x00, 'G', 'a', 'm', 'e', ' ', 'P', 'o', 'r', 't',
0x15, 0x09, 0xf8, 0x00, 0x02, 0x01, /* logical device BOX0002, can participate in boot */
0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */
0x31, 0x00, /* start dependent functions, preferred */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */
0x30, /* start dependent functions, acceptable */
0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */
0x31, 0x02, /* start dependent functions, sub-optimal */
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
0x38, /* end dependent functions */
/* Logical device BOX0002, can participate in boot */
0x15, 0x09, 0xf8, 0x00, 0x02, 0x01,
/* Compatible device PNPB02F */
0x1c, 0x41, 0xd0, 0xb0, 0x2f,
/* Start dependent functions, preferred */
0x31, 0x00,
/* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08,
/* Start dependent functions, acceptable */
0x30,
/* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */
0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08,
/* Start dependent functions, sub-optimal */
0x31, 0x02,
/* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08,
/* End dependent functions */
0x38,
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
/* End tag, dummy checksum (filled in by isapnp_add_card) */
0x79, 0x00
};
static const isapnp_device_config_t gameport_pnp_defaults[] = {
{.activate = 1,
{
.activate = 1,
.io = {
{ .base = 0x200 },
}
@@ -244,10 +259,8 @@ gameport_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), void *priv)
/* Read all axes. */
joystick->state |= 0x0f;
gameport_time(joystick, 0, joystick->intf->read_axis(joystick->dat, 0));
gameport_time(joystick, 1, joystick->intf->read_axis(joystick->dat, 1));
gameport_time(joystick, 2, joystick->intf->read_axis(joystick->dat, 2));
gameport_time(joystick, 3, joystick->intf->read_axis(joystick->dat, 3));
for (uint8_t i = 0; i < 4; i++)
gameport_time(joystick, i, joystick->intf->read_axis(joystick->dat, i));
/* Notify the interface. */
joystick->intf->write(joystick->dat);
@@ -286,17 +299,17 @@ timer_over(void *priv)
}
void
gameport_update_joystick_type(void)
gameport_update_joystick_type(uint8_t gp)
{
/* Add a standalone game port if a joystick is enabled but no other game ports exist. */
if (standalone_gameport_type)
gameport_add(standalone_gameport_type);
/* Reset the joystick interface. */
if (joystick_instance[0]) {
joystick_instance[0]->intf->close(joystick_instance[0]->dat);
joystick_instance[0]->intf = joysticks[joystick_type].joystick;
joystick_instance[0]->dat = joystick_instance[0]->intf->init();
if (joystick_instance[gp]) {
joystick_instance[gp]->intf->close(joystick_instance[gp]->dat);
joystick_instance[gp]->intf = joysticks[joystick_type[gp]].joystick;
joystick_instance[gp]->dat = joystick_instance[gp]->intf->init();
}
}
@@ -380,37 +393,34 @@ gameport_init(const device_t *info)
{
gameport_t *dev = calloc(1, sizeof(gameport_t));
// TODO: Later we'll actually support more than one gameport
uint8_t joy_insn = 0;
/* Allocate global instance. */
if (!joystick_instance[0] && joystick_type) {
joystick_instance[0] = calloc(1, sizeof(joystick_instance_t));
if (!joystick_instance[joy_insn] && joystick_type[joy_insn]) {
joystick_instance[joy_insn] = calloc(1, sizeof(joystick_instance_t));
joystick_instance[0]->axis[0].joystick = joystick_instance[0];
joystick_instance[0]->axis[1].joystick = joystick_instance[0];
joystick_instance[0]->axis[2].joystick = joystick_instance[0];
joystick_instance[0]->axis[3].joystick = joystick_instance[0];
// For each analog joystick axis
for (uint8_t i = 0; i < 4; i++) {
joystick_instance[joy_insn]->axis[i].joystick = joystick_instance[joy_insn];
joystick_instance[0]->axis[0].axis_nr = 0;
joystick_instance[0]->axis[1].axis_nr = 1;
joystick_instance[0]->axis[2].axis_nr = 2;
joystick_instance[0]->axis[3].axis_nr = 3;
joystick_instance[joy_insn]->axis[i].axis_nr = i;
timer_add(&joystick_instance[0]->axis[0].timer, timer_over, &joystick_instance[0]->axis[0], 0);
timer_add(&joystick_instance[0]->axis[1].timer, timer_over, &joystick_instance[0]->axis[1], 0);
timer_add(&joystick_instance[0]->axis[2].timer, timer_over, &joystick_instance[0]->axis[2], 0);
timer_add(&joystick_instance[0]->axis[3].timer, timer_over, &joystick_instance[0]->axis[3], 0);
timer_add(&joystick_instance[joy_insn]->axis[i].timer, timer_over, &joystick_instance[joy_insn]->axis[i], 0);
}
joystick_instance[0]->intf = joysticks[joystick_type].joystick;
joystick_instance[0]->dat = joystick_instance[0]->intf->init();
joystick_instance[joy_insn]->intf = joysticks[joystick_type[joy_insn]].joystick;
joystick_instance[joy_insn]->dat = joystick_instance[joy_insn]->intf->init();
}
dev->joystick = joystick_instance[0];
dev->joystick = joystick_instance[joy_insn];
/* Map game port to the default address. Not applicable on PnP-only ports. */
dev->len = (info->local >> 16) & 0xff;
gameport_remap(dev, info->local & 0xffff);
/* Register ISAPnP if this is a standard game port card. */
if ((info->local & 0xffff) == 0x200)
/* Register ISAPnP if this is a PNP game port card. */
if (info->local & GAMEPORT_PNPROM)
isapnp_set_device_defaults(isapnp_add_card(gameport_pnp_rom, sizeof(gameport_pnp_rom), gameport_pnp_config_changed, NULL, NULL, NULL, dev), 0, gameport_pnp_defaults);
return dev;
@@ -468,24 +478,41 @@ gameport_close(void *priv)
{
gameport_t *dev = (gameport_t *) priv;
// TODO: Later we'll actually support more than one gameport
uint8_t joy_insn = 0;
/* If this port was active, remove it from the active ports list. */
gameport_remap(dev, 0);
/* Free the global instance here, if it wasn't already freed. */
if (joystick_instance[0]) {
joystick_instance[0]->intf->close(joystick_instance[0]->dat);
if (joystick_instance[joy_insn]) {
joystick_instance[joy_insn]->intf->close(joystick_instance[joy_insn]->dat);
free(joystick_instance[0]);
joystick_instance[0] = NULL;
free(joystick_instance[joy_insn]);
joystick_instance[joy_insn] = NULL;
}
free(dev);
}
const device_t gameport_device = {
.name = "Game port",
.name = "86Box PNP Game port",
.internal_name = "gameport",
.flags = 0,
.local = GAMEPORT_PNPROM | GAMEPORT_8ADDR | 0x0200,
.init = gameport_init,
.close = gameport_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t gameport_200_device = {
.name = "Game port (Port 200h-207h)",
.internal_name = "gameport_200",
.flags = 0,
.local = GAMEPORT_8ADDR | 0x0200,
.init = gameport_init,
.close = gameport_close,
@@ -736,7 +763,7 @@ const device_t gameport_sio_device = {
const device_t gameport_sio_1io_device = {
.name = "Game port (Super I/O, 1 I/O port)",
.internal_name = "gameport_sio",
.internal_name = "gameport_sio_1io",
.flags = 0,
.local = GAMEPORT_SIO | GAMEPORT_1ADDR,
.init = gameport_init,
@@ -751,6 +778,7 @@ const device_t gameport_sio_1io_device = {
static const GAMEPORT gameports[] = {
{ &device_none },
{ &device_internal },
{ &gameport_200_device },
{ &gameport_device },
{ &gameport_208_device },
{ &gameport_pnp_device },
@@ -771,7 +799,7 @@ gameport_available(int port)
/* UI */
const device_t *
gameports_getdevice(int port)
gameport_get_device(int port)
{
return (gameports[port].device);
}

View File

@@ -8,8 +8,6 @@
*
* Implementation of the Flight Stick Pro.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
@@ -138,7 +136,7 @@ ch_flightstick_pro_a0_over(UNUSED(void *priv))
//
}
const joystick_if_t joystick_ch_flightstick_pro = {
const joystick_t joystick_ch_flightstick_pro = {
.name = "CH Flightstick Pro",
.internal_name = "ch_flightstick_pro",
.init = ch_flightstick_pro_init,
@@ -156,7 +154,7 @@ const joystick_if_t joystick_ch_flightstick_pro = {
.pov_names = { "POV" }
};
const joystick_if_t joystick_ch_flightstick_pro_ch_pedals = {
const joystick_t joystick_ch_flightstick_pro_ch_pedals = {
.name = "CH Flightstick Pro + CH Pedals",
.internal_name = "ch_flightstick_pro_ch_pedals",
.init = ch_flightstick_pro_init,

View File

@@ -274,7 +274,7 @@ joystick_standard_a0_over(UNUSED(void *priv))
//
}
const joystick_if_t joystick_2axis_2button = {
const joystick_t joystick_2axis_2button = {
.name = "2-axis, 2-button joystick(s)",
.internal_name = "2axis_2button",
.init = joystick_standard_init,
@@ -292,7 +292,7 @@ const joystick_if_t joystick_2axis_2button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_gamepad = {
const joystick_t joystick_2button_gamepad = {
.name = "2-button gamepad(s)",
.internal_name = "2button_gamepad",
.init = joystick_standard_init,
@@ -310,7 +310,7 @@ const joystick_if_t joystick_2button_gamepad = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_flight_yoke = {
const joystick_t joystick_2button_flight_yoke = {
.name = "2-button flight yoke",
.internal_name = "2button_flight_yoke",
.init = joystick_standard_init,
@@ -328,7 +328,7 @@ const joystick_if_t joystick_2button_flight_yoke = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2axis_4button = {
const joystick_t joystick_2axis_4button = {
.name = "2-axis, 4-button joystick",
.internal_name = "2axis_4button",
.init = joystick_standard_init,
@@ -346,7 +346,7 @@ const joystick_if_t joystick_2axis_4button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_gamepad = {
const joystick_t joystick_4button_gamepad = {
.name = "4-button gamepad",
.internal_name = "4button_gamepad",
.init = joystick_standard_init,
@@ -364,7 +364,7 @@ const joystick_if_t joystick_4button_gamepad = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_flight_yoke = {
const joystick_t joystick_4button_flight_yoke = {
.name = "4-button flight yoke",
.internal_name = "4button_flight_yoke",
.init = joystick_standard_init,
@@ -382,7 +382,7 @@ const joystick_if_t joystick_4button_flight_yoke = {
.pov_names = { NULL }
};
const joystick_if_t joystick_3axis_2button = {
const joystick_t joystick_3axis_2button = {
.name = "3-axis, 2-button joystick",
.internal_name = "3axis_2button",
.init = joystick_standard_init,
@@ -400,7 +400,7 @@ const joystick_if_t joystick_3axis_2button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2button_yoke_throttle = {
const joystick_t joystick_2button_yoke_throttle = {
.name = "2-button flight yoke with throttle",
.internal_name = "2button_yoke_throttle",
.init = joystick_standard_init,
@@ -418,7 +418,7 @@ const joystick_if_t joystick_2button_yoke_throttle = {
.pov_names = { NULL }
};
const joystick_if_t joystick_3axis_4button = {
const joystick_t joystick_3axis_4button = {
.name = "3-axis, 4-button joystick",
.internal_name = "3axis_4button",
.init = joystick_standard_init,
@@ -436,7 +436,7 @@ const joystick_if_t joystick_3axis_4button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4button_yoke_throttle = {
const joystick_t joystick_4button_yoke_throttle = {
.name = "4-button flight yoke with throttle",
.internal_name = "4button_yoke_throttle",
.init = joystick_standard_init,
@@ -454,7 +454,7 @@ const joystick_if_t joystick_4button_yoke_throttle = {
.pov_names = { NULL }
};
const joystick_if_t joystick_win95_steering_wheel = {
const joystick_t joystick_win95_steering_wheel = {
.name = "Win95 Steering Wheel (3-axis, 4-button)",
.internal_name = "win95_steering_wheel",
.init = joystick_standard_init,
@@ -472,7 +472,7 @@ const joystick_if_t joystick_win95_steering_wheel = {
.pov_names = { NULL }
};
const joystick_if_t joystick_4axis_4button = {
const joystick_t joystick_4axis_4button = {
.name = "4-axis, 4-button joystick",
.internal_name = "4axis_4button",
.init = joystick_standard_init,
@@ -490,7 +490,7 @@ const joystick_if_t joystick_4axis_4button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2axis_6button = {
const joystick_t joystick_2axis_6button = {
.name = "2-axis, 6-button joystick",
.internal_name = "2axis_6button",
.init = joystick_standard_init,
@@ -508,7 +508,7 @@ const joystick_if_t joystick_2axis_6button = {
.pov_names = { NULL }
};
const joystick_if_t joystick_2axis_8button = {
const joystick_t joystick_2axis_8button = {
.name = "2-axis, 8-button joystick",
.internal_name = "2axis_8button",
.init = joystick_standard_init,

View File

@@ -29,8 +29,6 @@
* - Some DOS stuff will write to 0x201 while a packet is
* being transferred. This seems to be ignored.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
@@ -244,7 +242,7 @@ sw_a0_over(void *priv)
timer_set_delay_u64(&sw->trigger_timer, TIMER_USEC * 10000);
}
const joystick_if_t joystick_sw_pad = {
const joystick_t joystick_sw_pad = {
.name = "Microsoft SideWinder Pad",
.internal_name = "sidewinder_pad",
.init = sw_init,

View File

@@ -8,8 +8,6 @@
*
* Implementation of Thrust Master Flight Control System.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
@@ -148,7 +146,7 @@ tm_fcs_a0_over(UNUSED(void *priv))
//
}
const joystick_if_t joystick_tm_fcs = {
const joystick_t joystick_tm_fcs = {
.name = "Thrustmaster Flight Control System",
.internal_name = "thrustmaster_fcs",
.init = tm_fcs_init,
@@ -166,7 +164,7 @@ const joystick_if_t joystick_tm_fcs = {
.pov_names = { "POV" }
};
const joystick_if_t joystick_tm_fcs_rcs = {
const joystick_t joystick_tm_fcs_rcs = {
.name = "Thrustmaster FCS + Rudder Control System",
.internal_name = "thrustmaster_fcs_rcs",
.init = tm_fcs_init,

View File

@@ -25,6 +25,11 @@
#include <stdarg.h>
#endif
#if defined(__HAIKU__)
/* Doesn't compile on Haiku without this include */
#include <stdlib.h>
#endif
/* Configuration values. */
#define GFXCARD_MAX 2
#define SERIAL_MAX 8
@@ -33,9 +38,10 @@
#define SCREEN_RES_Y 480
/* Filename and pathname info. */
#define CONFIG_FILE "86box.cfg"
#define NVR_PATH "nvr"
#define SCREENSHOT_PATH "screenshots"
#define CONFIG_FILE "86box.cfg"
#define GLOBAL_CONFIG_FILE "86box_global.cfg"
#define NVR_PATH "nvr"
#define SCREENSHOT_PATH "screenshots"
/* Recently used images */
#define MAX_PREV_IMAGES 10
@@ -110,16 +116,21 @@ extern uint64_t instru_run_ms;
#define window_y monitor_settings[0].mon_window_y
#define window_w monitor_settings[0].mon_window_w
#define window_h monitor_settings[0].mon_window_h
extern int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */
extern int inhibit_multimedia_keys; /* (G) Inhibit multimedia keys on Windows. */
extern int window_remember;
extern int vid_resize; /* (C) allow resizing */
extern int invert_display; /* (C) invert the display */
extern int suppress_overscan; /* (C) suppress overscans */
extern int lang_id; /* (C) language id */
extern int lang_id; /* (G) language id */
extern int scale; /* (C) screen scale factor */
extern int dpi_scale; /* (C) DPI scaling of the emulated screen */
extern int vid_api; /* (C) video renderer */
extern int vid_cga_contrast; /* (C) video */
extern int vid_cga_comp_brightness; /* (C) CGA composite brightness */
extern int vid_cga_comp_sharpness; /* (C) CGA composite sharpness */
extern int vid_cga_comp_hue; /* (C) CGA composite hue */
extern int vid_cga_comp_saturation; /* (C) CGA composite saturation */
extern int vid_cga_comp_contrast; /* (C) CGA composite saturation */
extern int video_fullscreen; /* (C) video */
extern int video_fullscreen_scale; /* (C) video */
extern int enable_overscan; /* (C) video */
@@ -149,11 +160,12 @@ extern int fpu_type; /* (C) fpu type */
extern int fpu_softfloat; /* (C) fpu uses softfloat */
extern int time_sync; /* (C) enable time sync */
extern int hdd_format_type; /* (C) hard disk file format */
extern int confirm_reset; /* (C) enable reset confirmation */
extern int confirm_exit; /* (C) enable exit confirmation */
extern int confirm_save; /* (C) enable save confirmation */
extern int confirm_reset; /* (G) enable reset confirmation */
extern int confirm_exit; /* (G) enable exit confirmation */
extern int confirm_save; /* (G) enable save confirmation */
extern int enable_discord; /* (C) enable Discord integration */
extern int force_10ms; /* (C) force 10ms CPU frame interval */
extern int jumpered_internal_ecp_dma; /* (C) Jumpered internal EPC DMA */
extern int other_ide_present; /* IDE controllers from non-IDE cards are present */
extern int other_scsi_present; /* SCSI controllers from non-SCSI cards are present */
extern int is_pcjr; /* The current machine is PCjr. */
@@ -164,7 +176,8 @@ extern int fixed_size_y;
extern int sound_muted; /* (C) Is sound muted? */
extern int do_auto_pause; /* (C) Auto-pause the emulator on focus loss */
extern int auto_paused;
extern double mouse_sensitivity; /* (C) Mouse sensitivity scale */
extern int force_constant_mouse; /* (C) Force constant updating of the mouse */
extern double mouse_sensitivity; /* (G) Mouse sensitivity scale */
#ifdef _Atomic
extern _Atomic double mouse_x_error; /* Mouse error accumulator - Y */
extern _Atomic double mouse_y_error; /* Mouse error accumulator - Y */
@@ -172,14 +185,17 @@ extern _Atomic double mouse_y_error; /* Mouse error accumulator - Y */
extern int pit_mode; /* (C) force setting PIT mode */
extern int fm_driver; /* (C) select FM sound driver */
extern int hook_enabled; /* (C) Keyboard hook is enabled */
extern int vmm_disabled; /* (G) disable built-in manager */
extern char vmm_path_cfg[1024]; /* (G) VMs path (unless -E is used) */
extern char exe_path[2048]; /* path (dir) of executable */
extern char usr_path[1024]; /* path (dir) of user data */
extern char cfg_path[1024]; /* full path of config file */
extern char global_cfg_path[1024]; /* full path of global config file */
extern int open_dir_usr_path; /* default file open dialog directory of usr_path */
extern char uuid[MAX_UUID_LEN]; /* UUID or machine identifier */
extern char vmm_path[1024]; /* VM Manager path to scan (temporary) */
extern int vmm_enabled;
extern char vmm_path[1024]; /* VM Manager path to scan */
extern int start_vmm;
#ifndef USE_NEW_DYNAREC
extern FILE *stdlog; /* file to log output to */
#endif
@@ -195,6 +211,7 @@ extern void warning_ex(const char *fmt, va_list ap);
#endif
extern void pclog_toggle_suppr(void);
extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void always_log(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void warning(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void set_screen_size(int x, int y);
@@ -206,6 +223,7 @@ extern void update_mouse_msg(void);
#if 0
extern void pc_reload(wchar_t *fn);
#endif
extern int pc_init_roms(void);
extern int pc_init_modules(void);
extern int pc_init(int argc, char *argv[]);
extern void pc_close(void *threadid);

View File

@@ -75,7 +75,7 @@ void pc_cas_del(pc_cassette_t *cas);
* @short Set the cassette file
* @return True on error, false otherwise
*****************************************************************************/
int pc_cas_set_fname(pc_cassette_t *cas, const char *fname);
int pc_cas_set_fname(pc_cassette_t *cas, char *fname);
/*!***************************************************************************
* @short Get the cassette mode

View File

@@ -29,8 +29,9 @@
#define CD_STATUS_STOPPED 6
#define CD_STATUS_PLAYING_COMPLETED 7
#define CD_STATUS_HOLD 8
#define CD_STATUS_DVD_REJECTED 16
#define CD_STATUS_HAS_AUDIO 0xc
#define CD_STATUS_MASK 0xf
#define CD_STATUS_MASK 0x1f
/* Medium changed flag. */
#define CD_STATUS_TRANSITION 0x40
@@ -69,6 +70,8 @@
#define CD_FPS 75
#define _LUT_SIZE 0x100
#define FRAMES_TO_MSF(f, M, S, F) \
{ \
uint64_t value = f; \
@@ -91,13 +94,19 @@ extern "C" {
#endif
enum {
CDROM_BUS_DISABLED = 0,
CDROM_BUS_ATAPI = 5,
CDROM_BUS_SCSI = 6,
CDROM_BUS_MITSUMI = 7,
CDROM_BUS_USB = 8
CDROM_BUS_DISABLED = 0,
CDROM_BUS_PHILIPS = 1,
CDROM_BUS_SONY = 2,
CDROM_BUS_HITACHI = 3,
CDROM_BUS_MKE = 4,
CDROM_BUS_MITSUMI = 5,
CDROM_BUS_LPT = 6,
CDROM_BUS_ATAPI = 8,
CDROM_BUS_SCSI = 9,
CDROM_BUS_USB = 10
};
#define BUS_TYPE_MKE CDROM_BUS_MKE
#define BUS_TYPE_IDE CDROM_BUS_ATAPI
#define BUS_TYPE_SCSI CDROM_BUS_SCSI
#define BUS_TYPE_BOTH -2
@@ -116,107 +125,112 @@ static const struct cdrom_drive_types_s {
const int speed;
const int inquiry_len;
const int caddy;
const int is_dvd;
const int transfer_max[4];
} cdrom_drive_types[] = {
{ EMU_NAME, "86B_CD", CDV, "86cd", BUS_TYPE_BOTH, 2, -1, 36, 0, { 4, 2, 2, 5 } },
{ EMU_NAME, "86B_CD", CDV, "86cd", BUS_TYPE_BOTH, 2, -1, 36, 0, 0, { 4, 2, 2, 5 } },
/* SCSI-1 / early ATAPI generic - second on purpose so the later variant is the default. */
{ EMU_NAME, "86B_CD", "1.00", "86cd100", BUS_TYPE_BOTH, 1, -1, 36, 1, { 0, -1, -1, -1 } },
{ EMU_NAME, "86B_CD", "1.00", "86cd100", BUS_TYPE_BOTH, 1, -1, 36, 1, 0, { 0, -1, -1, -1 } },
/* No difference from 86BOX CD-ROM, other than name - but enough people have requested such a name to warrant it. */
{ EMU_NAME, "86B_DVD", "4.30", "86dvd", BUS_TYPE_BOTH, 2, -1, 36, 0, { 4, 2, 2, 5 } },
{ "ASUS", "CD-S500/A", "1.41", "asus_500", BUS_TYPE_IDE, 0, 50, 36, 0, { 4, 2, 2, 2 } },
{ "ASUS", "CD-S520/A4", "1.32", "asus_520", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } },
{ "AZT", "CDA46802I", "1.15", "azt_cda", BUS_TYPE_IDE, 0, 4, 36, 0, { 3, 0, 0, 0 } },
{ "BTC", "CD-ROM BCD36XH", "U1.0", "btc_36xh", BUS_TYPE_IDE, 0, 36, 36, 0, { 4, 2, 2, -1 } },
{ "GOLDSTAR", "CRD-8160B", "3.14", "goldstar", BUS_TYPE_IDE, 0, 16, 36, 0, { 4, 2, 2, -1 } },
{ EMU_NAME, "86B_DVD", "5.00", "86dvd", BUS_TYPE_BOTH, 2, -1, 36, 0, 1, { 4, 2, 2, 5 } },
{ "ASUS", "CD-S500/A", "1.41", "asus_500", BUS_TYPE_IDE, 0, 50, 36, 0, 0, { 4, 2, 2, 2 } },
{ "ASUS", "CD-S520/A4", "1.32", "asus_520", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "AZT", "CDA46802I", "1.15", "azt_cda", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 3, 0, 0, 0 } },
{ "BTC", "CD-ROM BCD36XH", "U1.0", "btc_36xh", BUS_TYPE_IDE, 0, 36, 36, 0, 0, { 4, 2, 2, -1 } },
{ "GOLDSTAR", "CRD-8160B", "3.14", "goldstar", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 4, 2, 2, -1 } },
/* TODO: Find an IDENTIFY and/or INQUIRY dump. */
{ "GOLDSTAR", "GCD-R560B", "1.00", "goldstar", BUS_TYPE_IDE, 0, 6, 36, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "CDR-8130", "0020", "hitachi_r8130", BUS_TYPE_IDE, 0, 16, 36, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "GD-7500", "A1 ", "hitachi_7500", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, 2 } }, /* DVD. */
{ "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "hldtst_8526b", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } },
{ "HL-DT-ST", "DVDRAM GSA-4160", "A302", "hldtst_4160", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, 2 } },
{ "KENWOOD", "CD-ROM UCR-421", "208E", "kenwood_421", BUS_TYPE_IDE, 0, 72, 36, 0, { 4, 2, 2, 4 } },
{ "GOLDSTAR", "GCD-R560B", "1.00", "goldstar", BUS_TYPE_IDE, 0, 6, 36, 0, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "CDR-8130", "0020", "hitachi_r8130", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 4, 2, 2, -1 } },
{ "HITACHI", "GD-7500", "A1 ", "hitachi_7500", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, 2 } }, /* DVD. */
{ "HL-DT-ST", "CD-ROM GCR-8526B", "1.01", "hldtst_8526b", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "HL-DT-ST", "DVDRAM GSA-4160", "A302", "hldtst_4160", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, 2 } },
{ "KENWOOD", "CD-ROM UCR-421", "208E", "kenwood_421", BUS_TYPE_IDE, 0, 72, 36, 0, 0, { 4, 2, 2, 4 } },
/*
This is a laptop/notebook drive, as is also evident from the name:
CRN = Notebook, CRD = Desktop.
*/
{ "LG", "CD-ROM CRN-8245B", "1.30", "lg_8245b", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } },
{ "LG", "CD-ROM CRD-8322B", "1.06", "lg_8322b", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } },
{ "LG", "CD-ROM CRN-8245B", "1.30", "lg_8245b", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "LG", "CD-ROM CRD-8322B", "1.06", "lg_8322b", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
/* Nothing on Google, deduced 48x from the name. */
{ "LITE-ON", "LTN48125S", "1S07", "liteon_48125s", BUS_TYPE_IDE, 0, 48, 36, 0, { 4, 2, 2, 2 } },
{ "LITE-ON", "LTN48125S", "1S07", "liteon_48125s", BUS_TYPE_IDE, 0, 48, 36, 0, 0, { 4, 2, 2, 2 } },
/* Confirmed to be 52x, was the basis for deducing the other one's speed. */
{ "LITE-ON", "LTN526D", "YSR5", "liteon_526d", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 2 } },
{ "MATSHITA", "CD-ROM CR-583", "1.07", "matshita_583", BUS_TYPE_IDE, 0, 8, 36, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-585", "Z18P", "matshita_585", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-587", "7S13", "matshita_587", BUS_TYPE_IDE, 0, 24, 36, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-588", "LS15", "matshita_588", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CR-571", "1.0e", "matshita_571", BUS_TYPE_IDE, 0, 2, 36, 0, { 0, -1, -1, -1 } },
{ "MATSHITA", "CR-572", "1.0j", "matshita_572", BUS_TYPE_IDE, 0, 4, 36, 0, { 0, -1, -1, -1 } },
{ "MITSUMI", "CRMC-FX4820T", "D02A", "mitsumi_4820t", BUS_TYPE_IDE, 0, 48, 36, 0, { 4, 2, 2, 2 } },
{ "LITE-ON", "LTN526D", "YSR5", "liteon_526d", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 2 } },
{ "MATSHITA", "CD-ROM CR-583", "1.07", "matshita_583", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-585", "Z18P", "matshita_585", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-587", "7S13", "matshita_587", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CD-ROM CR-588", "LS15", "matshita_588", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
{ "MATSHITA", "CR-571", "1.0e", "matshita_571", BUS_TYPE_IDE, 0, 2, 36, 0, 0, { 0, -1, -1, -1 } },
{ "MATSHITA", "CR-572", "1.0j", "matshita_572", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 0, -1, -1, -1 } },
{ "MITSUMI", "CRMC-FX4820T", "D02A", "mitsumi_4820t", BUS_TYPE_IDE, 0, 48, 36, 0, 0, { 4, 2, 2, 2 } },
/* TODO: Find an IDENTIFY and/or INQUIRY dump. */
{ "MITSUMI", "CRMC-FX810T4", "????", "mitsumi_810t4", BUS_TYPE_IDE, 0, 8, 36, 0, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.00", "nec_260_early", BUS_TYPE_IDE, 1, 2, 36, 1, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.01", "nec_260", BUS_TYPE_IDE, 1, 4, 36, 1, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:273", "4.20", "nec_273", BUS_TYPE_IDE, 0, 4, 36, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "1.05", "nec_280_early", BUS_TYPE_IDE, 0, 6, 36, 1, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "3.08", "nec_280", BUS_TYPE_IDE, 0, 8, 36, 1, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1300A", "1.05", "nec_1300a", BUS_TYPE_IDE, 0, 6, 36, 0, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1900A", "1.00", "nec_1900a", BUS_TYPE_IDE, 0, 32, 36, 0, { 4, 2, 2, -1 } },
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "philips_403", BUS_TYPE_IDE, 0, 40, 36, 0, { 4, 2, 2, -1 } },
{ "SONY", "CD-ROM CDU76", "1.0i", "sony_76", BUS_TYPE_IDE, 0, 4, 36, 0, { 2, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU311", "3.0h", "sony_311", BUS_TYPE_IDE, 0, 8, 36, 0, { 3, 2, 1, -1 } },
{ "SONY", "CD-ROM CDU5225", "NYS4", "sony_5225", BUS_TYPE_IDE, 0, 52, 36, 0, { 4, 2, 2, 4 } },
{ "TEAC", "CD-516E", "1.0G", "teac_516e", BUS_TYPE_IDE, 0, 16, 36, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-524EA", "3.0D", "teac_524ea", BUS_TYPE_IDE, 0, 24, 36, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-532E", "2.0A", "teac_532e", BUS_TYPE_IDE, 0, 32, 36, 0, { 3, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-5302TA", "0305", "toshiba_5302ta", BUS_TYPE_IDE, 0, 4, 96, 0, { 0, -1, -1, -1 } },
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "toshiba_5702b", BUS_TYPE_IDE, 0, 12, 96, 0, { 3, 2, 1, -1 } },
{ "TOSHIBA", "CD-ROM XM-6202B", "1512", "toshiba_6202b", BUS_TYPE_IDE, 0, 32, 96, 0, { 4, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-6402B", "1008", "toshiba_6402b", BUS_TYPE_IDE, 0, 32, 96, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "CD-ROM XM-6702B", "1007", "toshiba_6720b", BUS_TYPE_IDE, 0, 48, 96, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "DVD-ROM SD-M1802", "1051", "toshiba_m1802", BUS_TYPE_IDE, 0, 48, 96, 0, { 4, 2, 2, 2 } },
{ "CHINON", "CD-ROM CDS-431", "H42 ", "chinon_431", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } },
{ "CHINON", "CD-ROM CDX-435", "M62 ", "chinon_435", BUS_TYPE_SCSI, 1, 2, 36, 1, { -1, -1, -1, -1 } },
{ "DEC", "RRD45 (C) DEC", "0436", "dec_45", BUS_TYPE_SCSI, 1, 4, 36, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "matshita_501", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:25", "1.0a", "nec_25", BUS_TYPE_SCSI, 1, 2, 36, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:38", "1.00", "nec_38", BUS_TYPE_SCSI, 2, 1, 36, 0, { -1, -1, -1, -1 } },
{ "MITSUMI", "CRMC-FX810T4", "????", "mitsumi_810t4", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.00", "nec_260_early", BUS_TYPE_IDE, 1, 2, 36, 1, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:260", "1.01", "nec_260", BUS_TYPE_IDE, 1, 4, 36, 1, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:273", "4.20", "nec_273", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 0, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "1.05", "nec_280_early", BUS_TYPE_IDE, 0, 6, 36, 1, 0, { 4, 2, 2, -1 } },
{ "NEC", "CD-ROM DRIVE:280", "3.08", "nec_280", BUS_TYPE_IDE, 0, 8, 36, 1, 0, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1300A", "1.05", "nec_1300a", BUS_TYPE_IDE, 0, 6, 36, 0, 0, { 4, 2, 2, -1 } },
{ "NEC", "CDR-1900A", "1.00", "nec_1900a", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 4, 2, 2, -1 } },
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "philips_403", BUS_TYPE_IDE, 0, 40, 36, 0, 0, { 4, 2, 2, -1 } },
{ "SONY", "CD-ROM CDU76", "1.0i", "sony_76", BUS_TYPE_IDE, 0, 4, 36, 0, 0, { 2, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU311", "3.0h", "sony_311", BUS_TYPE_IDE, 0, 8, 36, 0, 0, { 3, 2, 1, -1 } },
{ "SONY", "CD-ROM CDU5225", "NYS4", "sony_5225", BUS_TYPE_IDE, 0, 52, 36, 0, 0, { 4, 2, 2, 4 } },
{ "TEAC", "CD-516E", "1.0G", "teac_516e", BUS_TYPE_IDE, 0, 16, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-524EA", "3.0D", "teac_524ea", BUS_TYPE_IDE, 0, 24, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TEAC", "CD-532E", "2.0A", "teac_532e", BUS_TYPE_IDE, 0, 32, 36, 0, 0, { 3, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-5302TA", "0305", "toshiba_5302ta", BUS_TYPE_IDE, 0, 4, 96, 0, 0, { 0, -1, -1, -1 } },
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "toshiba_5702b", BUS_TYPE_IDE, 0, 12, 96, 0, 0, { 3, 2, 1, -1 } },
{ "TOSHIBA", "CD-ROM XM-6202B", "1512", "toshiba_6202b", BUS_TYPE_IDE, 0, 32, 96, 0, 0, { 4, 2, 2, -1 } },
{ "TOSHIBA", "CD-ROM XM-6402B", "1008", "toshiba_6402b", BUS_TYPE_IDE, 0, 32, 96, 0, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "CD-ROM XM-6702B", "1007", "toshiba_6720b", BUS_TYPE_IDE, 0, 48, 96, 0, 0, { 4, 2, 2, 2 } },
{ "TOSHIBA", "DVD-ROM SD-M1802", "1051", "toshiba_m1802", BUS_TYPE_IDE, 0, 48, 96, 0, 1, { 4, 2, 2, 2 } },
{ "CHINON", "CD-ROM CDS-431", "H42 ", "chinon_431", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "CHINON", "CD-ROM CDX-435", "M62 ", "chinon_435", BUS_TYPE_SCSI, 1, 2, 36, 1, 0, { -1, -1, -1, -1 } },
{ "DEC", "RRD45 (C) DEC", "0436", "dec_45", BUS_TYPE_SCSI, 1, 4, 36, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "matshita_501", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:25", "1.0a", "nec_25", BUS_TYPE_SCSI, 1, 2, 36, 0, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:38", "1.00", "nec_38", BUS_TYPE_SCSI, 2, 1, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the CDR-74. */
{ "NEC", "CD-ROM DRIVE:75", "1.03", "nec_75", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:77", "1.06", "nec_77", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:211", "1.00", "nec_211", BUS_TYPE_SCSI, 2, 3, 36, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:75", "1.03", "nec_75", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:77", "1.06", "nec_77", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:211", "1.00", "nec_211", BUS_TYPE_SCSI, 2, 3, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the CDR-400. */
{ "NEC", "CD-ROM DRIVE:464", "1.05", "nec_464", BUS_TYPE_SCSI, 2, 3, 36, 0, { -1, -1, -1, -1 } },
{ "NEC", "CD-ROM DRIVE:464", "1.05", "nec_464", BUS_TYPE_SCSI, 2, 3, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the name. */
{ "ShinaKen", "CD-ROM DM-3x1S", "1.04", "shinaken_3x1s", BUS_TYPE_SCSI, 1, 3, 36, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-541", "1.0i", "sony_541", BUS_TYPE_SCSI, 1, 1, 36, 1, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-561", "1.8k", "sony_561", BUS_TYPE_SCSI, 2, 2, 36, 1, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-76S", "1.00", "sony_76s", BUS_TYPE_SCSI, 2, 4, 36, 0, { -1, -1, -1, -1 } },
{ "PHILIPS", "CDD2600", "1.07", "philips_2600", BUS_TYPE_SCSI, 2, 6, 36, 0, { -1, -1, -1, -1 } },
{ "ShinaKen", "CD-ROM DM-3x1S", "1.04", "shinaken_3x1s", BUS_TYPE_SCSI, 1, 3, 36, 0, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-541", "1.0i", "sony_541", BUS_TYPE_SCSI, 1, 1, 36, 1, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-561", "1.8k", "sony_561", BUS_TYPE_SCSI, 2, 2, 36, 1, 0, { -1, -1, -1, -1 } },
{ "SONY", "CD-ROM CDU-76S", "1.00", "sony_76s", BUS_TYPE_SCSI, 2, 4, 36, 0, 0, { -1, -1, -1, -1 } },
{ "PHILIPS", "CDD2600", "1.07", "philips_2600", BUS_TYPE_SCSI, 2, 6, 36, 0, 0, { -1, -1, -1, -1 } },
/* NOTE: The real thing is a CD changer drive! */
{ "PIONEER", "CD-ROM DRM-604X", "2403", "pioneer_604x", BUS_TYPE_SCSI, 2, 4, 47, 0, { -1, -1, -1, -1 } },
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "plextor_32ts", BUS_TYPE_SCSI, 2, 32, 36, 0, { -1, -1, -1, -1 } },
{ "PIONEER", "CD-ROM DRM-604X", "2403", "pioneer_604x", BUS_TYPE_SCSI, 2, 4, 47, 0, 0, { -1, -1, -1, -1 } },
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "plextor_32ts", BUS_TYPE_SCSI, 2, 32, 36, 0, 0, { -1, -1, -1, -1 } },
/* The speed of the following two is guesswork based on the R55S. */
{ "TEAC", "CD 50", "1.00", "teac_50", BUS_TYPE_SCSI, 2, 4, 36, 1, { -1, -1, -1, -1 } },
{ "TEAC", "CD-ROM R55S", "1.0R", "teac_55s", BUS_TYPE_SCSI, 2, 4, 36, 0, { -1, -1, -1, -1 } },
{ "TEAC", "CD 50", "1.00", "teac_50", BUS_TYPE_SCSI, 2, 4, 36, 1, 0, { -1, -1, -1, -1 } },
{ "TEAC", "CD-ROM R55S", "1.0R", "teac_55s", BUS_TYPE_SCSI, 2, 4, 36, 0, 0, { -1, -1, -1, -1 } },
/* Texel is Plextor according to Plextor's own EU website. */
{ "TEXEL", "CD-ROM DM-3024", "1.00", "texel_3024", BUS_TYPE_SCSI, 2, 2, 36, 1, { -1, -1, -1, -1 } },
{ "TEXEL", "CD-ROM DM-3024", "1.00", "texel_3024", BUS_TYPE_SCSI, 2, 2, 36, 1, 0, { -1, -1, -1, -1 } },
/*
Unusual 2.23x according to Google, I'm rounding it upwards to 3x.
Assumed caddy based on the DM-3024.
*/
{ "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1, { -1, -1, -1, -1 } }, /* Caddy. */
{ "TEXEL", "CD-ROM DM-3028", "1.06", "texel_3028", BUS_TYPE_SCSI, 2, 3, 36, 1, 0, { -1, -1, -1, -1 } }, /* Caddy. */
/*
The characteristics are a complete guesswork because I can't find
this one on Google.
Also, INQUIRY length is always 96 on these Toshiba drives.
*/
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1, { -1, -1, -1, -1 } }, /* Caddy. */
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0, { -1, -1, -1, -1 } }
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "toshiba_xm", BUS_TYPE_SCSI, 2, 2, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-3201B", "3232", "toshiba_3201b", BUS_TYPE_SCSI, 1, 1, 96, 1, 0, { -1, -1, -1, -1 } }, /* Caddy. */
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "toshiba_3301ta", BUS_TYPE_SCSI, 2, 2, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "toshiba_5701a", BUS_TYPE_SCSI, 2, 12, 96, 0, 0, { -1, -1, -1, -1 } }, /* Tray. */
{ "TOSHIBA", "DVD-ROM SD-M1401", "1008", "toshiba_m1401", BUS_TYPE_SCSI, 2, 40, 96, 0, 1, { -1, -1, -1, -1 } }, /* Tray. */
{ "MATSHITA", "CR-562", "0.75", "cr562", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-562", "0.80", "cr562_080", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-563", "0.75", "cr563", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "MATSHITA", "CR-563", "0.80", "cr563_080", BUS_TYPE_MKE , 0, 2, 0, 0, 0, { -1, -1, -1, -1 } },
{ "", "", "", "", BUS_TYPE_NONE, 0, -1, 0, 0, 0, { -1, -1, -1, -1 } }
};
/* To shut up the GCC compilers. */
@@ -283,7 +297,7 @@ typedef struct cdrom {
union {
uint8_t res;
uint8_t res0; /* Reserved for other ID's. */
uint8_t res1;
uint8_t mke_channel;
uint8_t ide_channel;
uint8_t scsi_device_id;
};
@@ -351,6 +365,13 @@ typedef struct cdrom {
/* Only used on Windows hosts for disc change notifications. */
uint8_t host_letter;
uint8_t mode2;
uint8_t _F_LUT[_LUT_SIZE];
uint8_t _B_LUT[_LUT_SIZE];
uint8_t p_parity[172];
uint8_t q_parity[104];
} cdrom_t;
extern cdrom_t cdrom[CDROM_NUM];
@@ -374,6 +395,7 @@ extern void cdrom_get_model(const int type, char *name, const int id)
extern char *cdrom_get_revision(const int type);
extern int cdrom_get_scsi_std(const int type);
extern int cdrom_is_early(const int type);
extern int cdrom_is_dvd(const int type);
extern int cdrom_is_generic(const int type);
extern int cdrom_is_caddy(const int type);
extern int cdrom_get_speed(const int type);
@@ -381,6 +403,7 @@ extern int cdrom_get_inquiry_len(const int type);
extern int cdrom_has_dma(const int type);
extern int cdrom_get_transfer_max(const int type, const int mode);
extern int cdrom_get_type_count(void);
extern void cdrom_generate_name_mke(const int type, char *name);
extern void cdrom_get_identify_model(const int type, char *name, const int id);
extern void cdrom_get_name(const int type, char *name);
extern char *cdrom_get_internal_name(const int type);
@@ -448,6 +471,12 @@ extern int cdrom_is_empty(const uint8_t id);
extern void cdrom_eject(const uint8_t id);
extern void cdrom_reload(const uint8_t id);
extern void cdrom_compute_ecc_block(cdrom_t *dev, uint8_t *parity, const uint8_t *data,
uint32_t major_count, uint32_t minor_count,
uint32_t major_mult, uint32_t minor_inc, int m2f1);
extern unsigned long cdrom_crc32(unsigned long crc, const unsigned char *buf,
size_t len);
extern int cdrom_assigned_letters;
#ifdef __cplusplus

View File

@@ -8,11 +8,11 @@
*
* Mitsumi CD-ROM emulation for the ISA bus.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2022 Miran Grca.
* Copyright 2022 Miran Grca.
* Copyright 2024-2025 Jasmine Iwanek.
*/
#ifndef CDROM_MITSUMI_H
#define CDROM_MITSUMI_H

View File

@@ -0,0 +1,24 @@
/*
* 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.
*
* Panasonic/MKE CD-ROM emulation for the ISA bus.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Cacodemon345
*
* Copyright 2022-2025 Miran Grca.
* Copyright 2025 Cacodemon345.
*/
#ifndef CDROM_MKE_H
#define CDROM_MKE_H
extern const device_t mke_cdrom_device;
extern const device_t mke_cdrom_noncreative_device;
#endif /*CDROM_MKE_H*/

View File

@@ -42,6 +42,8 @@ extern const device_t amd640_device;
extern const device_t isa486c_device;
/* Compaq */
extern const device_t compaq_device;
extern const device_t compaq_386_device;
extern const device_t compaq_genoa_device;
@@ -64,6 +66,9 @@ extern const device_t cs4031_device;
extern const device_t gc100_device;
extern const device_t gc100a_device;
/* GRiDcase */
extern const device_t grid1520_device;
/* Headland */
extern const device_t headland_gc10x_device;
extern const device_t headland_gc113_device;
@@ -114,6 +119,10 @@ extern const device_t slc90e66_device;
extern const device_t ioapic_device;
/* VTech */
extern const device_t laserxt_device;
extern const device_t lxt3_device;
/* Olivetti */
extern const device_t olivetti_eva_device;
@@ -126,6 +135,7 @@ extern const device_t opti481_device;
extern const device_t opti493_device;
extern const device_t opti495slc_device;
extern const device_t opti495sx_device;
extern const device_t opti496_device;
extern const device_t opti498_device;
extern const device_t opti499_device;
extern const device_t opti601_device;
@@ -138,6 +148,12 @@ extern const device_t opti895_device;
extern const device_t opti5x7_device;
extern const device_t opti5x7_pci_device;
/* Philips */
extern const device_t philips_device;
/* Sanyo */
extern const device_t sanyo_device;
/* SiS */
extern const device_t rabbit_device;
extern const device_t sis_85c401_device;
@@ -212,4 +228,8 @@ extern const device_t nec_mate_unk_device;
extern const device_t phoenix_486_jumper_device;
extern const device_t phoenix_486_jumper_pci_device;
extern const device_t radisys_config_device;
extern const device_t zenith_scratchpad_device;
#endif /*EMU_CHIPSET_H*/

View File

@@ -133,11 +133,13 @@ typedef struct config_t {
/* Other removable devices category */
storage_cfg_t cdrom[CDROM_NUM]; /* CD-ROM drives */
storage_cfg_t rdisk[ZIP_NUM]; /* Removable disk drives */
storage_cfg_t rdisk[RDISK_NUM]; /* Removable disk drives */
} config_t;
#endif
extern void config_load_global(void);
extern void config_load(void);
extern void config_save_global(void);
extern void config_save(void);
#ifdef EMU_INI_H

View File

@@ -223,6 +223,11 @@ extern uint8_t fdc_get_diswr(fdc_t *fdc);
extern void fdc_set_diswr(fdc_t *fdc, uint8_t diswr);
extern uint8_t fdc_get_swap(fdc_t *fdc);
extern void fdc_set_swap(fdc_t *fdc, uint8_t swap);
extern void fdc_set_flags(fdc_t *fdc, int flags);
extern void fdc_clear_flags(fdc_t *fdc, int flags);
extern void fdc_set_fdd_changed(int drive, int changed);
extern uint8_t fdc_get_fdd_changed(int drive);
extern uint8_t fdc_get_shadow(fdc_t *fdc);
extern void fdc_finishcompare(fdc_t *fdc, int satisfying);
extern void fdc_finishread(fdc_t *fdc);

View File

@@ -51,8 +51,9 @@
#define GAMEPORT_6ADDR 0x060000
#define GAMEPORT_8ADDR 0x080000
#define GAMEPORT_SIO 0x1000000
#define GAMEPORT_PNPROM 0x2000000
typedef struct joystick_if_t {
typedef struct joystick_t {
const char *name;
const char *internal_name;
@@ -70,9 +71,9 @@ typedef struct joystick_if_t {
const char *axis_names[MAX_JOY_AXES];
const char *button_names[MAX_JOY_BUTTONS];
const char *pov_names[MAX_JOY_POVS];
} joystick_if_t;
} joystick_t;
typedef struct plat_joystick_t {
typedef struct plat_joystick_state_t {
char name[260];
int a[MAX_JOY_AXES];
@@ -97,9 +98,9 @@ typedef struct plat_joystick_t {
int nr_axes;
int nr_buttons;
int nr_povs;
} plat_joystick_t;
} plat_joystick_state_t;
typedef struct joystick_t {
typedef struct joystick_state_t {
int axis[MAX_JOY_AXES];
int button[MAX_JOY_BUTTONS];
int pov[MAX_JOY_POVS];
@@ -108,7 +109,7 @@ typedef struct joystick_t {
int axis_mapping[MAX_JOY_AXES];
int button_mapping[MAX_JOY_BUTTONS];
int pov_mapping[MAX_JOY_POVS][2];
} joystick_t;
} joystick_state_t;
extern device_t game_ports[GAMEPORT_MAX];
@@ -118,7 +119,7 @@ extern "C" {
extern int gameport_available(int port);
#ifdef EMU_DEVICE_H
extern const device_t *gameport_getdevice(int port);
extern const device_t *gameport_get_device(int port);
#endif
extern int gameport_has_config(int port);
extern const char *gameport_get_internal_name(int port);
@@ -126,6 +127,7 @@ extern int gameport_get_from_internal_name(const char *str);
#ifdef EMU_DEVICE_H
extern const device_t gameport_device;
extern const device_t gameport_200_device;
extern const device_t gameport_201_device;
extern const device_t gameport_203_device;
extern const device_t gameport_205_device;
@@ -144,16 +146,16 @@ extern const device_t gameport_sio_1io_device;
extern const device_t *standalone_gameport_type;
#endif
extern int gameport_instance_id;
extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
extern joystick_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS];
extern int joysticks_present;
extern int gameport_instance_id;
extern plat_joystick_state_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
extern joystick_state_t joystick_state[GAMEPORT_MAX][MAX_JOYSTICKS];
extern int joysticks_present;
extern int joystick_type;
extern int joystick_type[GAMEPORT_MAX];
extern void joystick_init(void);
extern void joystick_close(void);
extern void joystick_process(void);
extern void joystick_process(uint8_t gp);
extern const char *joystick_get_name(int js);
extern const char *joystick_get_internal_name(int js);
@@ -166,32 +168,32 @@ extern const char *joystick_get_axis_name(int js, int id);
extern const char *joystick_get_button_name(int js, int id);
extern const char *joystick_get_pov_name(int js, int id);
extern void gameport_update_joystick_type(void);
extern void gameport_update_joystick_type(uint8_t gp);
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;
extern const joystick_t joystick_2axis_2button;
extern const joystick_t joystick_2button_gamepad;
extern const joystick_t joystick_2button_flight_yoke;
extern const joystick_t joystick_2axis_4button;
extern const joystick_t joystick_4button_gamepad;
extern const joystick_t joystick_4button_flight_yoke;
extern const joystick_t joystick_3axis_2button;
extern const joystick_t joystick_2button_yoke_throttle;
extern const joystick_t joystick_3axis_4button;
extern const joystick_t joystick_4button_yoke_throttle;
extern const joystick_t joystick_win95_steering_wheel;
extern const joystick_t joystick_4axis_4button;
extern const joystick_t joystick_2axis_6button;
extern const joystick_t joystick_2axis_8button;
extern const joystick_if_t joystick_ch_flightstick_pro;
extern const joystick_if_t joystick_ch_flightstick_pro_ch_pedals;
extern const joystick_t joystick_ch_flightstick_pro;
extern const joystick_t joystick_ch_flightstick_pro_ch_pedals;
extern const joystick_if_t joystick_sw_pad;
extern const joystick_t joystick_sw_pad;
extern const joystick_if_t joystick_tm_fcs;
extern const joystick_if_t joystick_tm_fcs_rcs;
extern const joystick_t joystick_tm_fcs;
extern const joystick_t joystick_tm_fcs_rcs;
#ifdef __cplusplus
}

View File

@@ -27,7 +27,7 @@
#define HDC_NONE 0
#define HDC_INTERNAL 1
#define HDC_MAX 2
#define HDC_MAX 4
extern int hdc_current[HDC_MAX];
@@ -79,6 +79,9 @@ extern const device_t ide_cmd646_device; /* CMD PCI-646 *
extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */
extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */
extern const device_t ide_cmd646_ter_qua_device; /* CMD PCI-646 (Tertiary and quaternary channels) */
extern const device_t ide_cmd648_ter_qua_device; /* CMD PCI-648 (Tertiary and quaternary channels) */
extern const device_t ide_cmd648_ter_qua_onboard_device; /* CMD PCI-648 (Tertiary and quaternary channels, on-board) */
extern const device_t ide_cmd649_ter_qua_device; /* CMD PCI-649 (Tertiary and quaternary channels) */
extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */
extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */
@@ -102,8 +105,11 @@ extern const device_t ide_qua_pnp_device;
extern const device_t mcide_device;
extern const device_t xta_wdxt150_device; /* xta_wdxt150 */
extern const device_t xta_hd20_device; /* EuroPC internal */
extern const device_t xta_wdxt150_device; /* xta_wdxt150 */
extern const device_t xta_wdxt150_pc3086_device; /* xta_wdxt150 (PC3086) */
extern const device_t xta_hd20_device; /* EuroPC internal */
extern const device_t xta_st50x_device; /* ST-50X */
extern const device_t xta_st50x_pc5086_device; /* ST-50X (PC5086) */
extern const device_t xtide_device; /* xtide_xt */
extern const device_t xtide_at_device; /* xtide_at */
@@ -116,10 +122,12 @@ extern void hdc_init(void);
extern void hdc_reset(void);
extern const char *hdc_get_internal_name(int hdc);
extern int hdc_get_from_internal_name(char *s);
extern int hdc_get_from_internal_name(const char *s);
extern int hdc_has_config(int hdc);
extern const device_t *hdc_get_device(int hdc);
extern int hdc_get_flags(int hdc);
extern int hdc_available(int hdc);
extern void xta_handler(void *priv, int set);
#endif /*EMU_HDC_H*/

View File

@@ -178,9 +178,6 @@ enum {
TIMINGS_PIO_FC = 2
};
extern int ide_ter_enabled;
extern int ide_qua_enabled;
#ifdef SCSI_DEVICE_H
extern ide_t *ide_get_drive(int ch);
extern void ide_irq(ide_t *ide, int set, int log);
@@ -230,6 +227,8 @@ extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src);
extern uint8_t ide_read_ali_75(void);
extern uint8_t ide_read_ali_76(void);
extern void ide_hard_reset(void);
/* Legacy #define's. */
#define ide_irq_raise(ide) ide_irq(ide, 1, 1)
#define ide_irq_lower(ide) ide_irq(ide, 0, 1)

View File

@@ -56,6 +56,11 @@ typedef struct sff8038i_t
int irq_level;
int irq_pin;
int pci_irq_line;
uint8_t (*ven_write)(uint16_t port, uint8_t val, void *priv);
uint8_t (*ven_read)(uint16_t port, uint8_t val, void *priv);
void *priv;
} sff8038i_t;
extern const device_t sff8038i_device;
@@ -78,4 +83,7 @@ extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin);
extern void sff_set_irq_level(sff8038i_t *dev, int irq_level);
extern void sff_set_mirq(sff8038i_t *dev, uint8_t mirq);
extern void sff_set_ven_handlers(sff8038i_t *dev, uint8_t (*ven_write)(uint16_t port, uint8_t val, void *priv),
uint8_t (*ven_read)(uint16_t port, uint8_t val, void *priv), void *priv);
#endif /*EMU_HDC_IDE_SFF8038I_H*/

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