Merge branch '86Box:master' into net-add-tap-backend

This commit is contained in:
Doug Johnson
2025-01-09 19:47:38 -07:00
committed by GitHub
78 changed files with 6726 additions and 4466 deletions

View File

@@ -144,23 +144,6 @@ plat_cdrom_ext_medium_changed(void *local)
return ret;
}
void
plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out)
{
dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local;
plat_cdrom_read_toc(ioctl);
*st_track = 1;
*end = 1;
lead_out->min = 0;
lead_out->sec = 0;
lead_out->fr = 2;
dummy_cdrom_ioctl_log("plat_cdrom_get_audio_tracks(): %02i, %02i, %02i:%02i:%02i\n",
*st_track, *end, lead_out->min, lead_out->sec, lead_out->fr);
}
/* This replaces both Info and EndInfo, they are specified by a variable. */
int
plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr)
@@ -218,18 +201,14 @@ plat_cdrom_get_sector_size(UNUSED(void *local), UNUSED(uint32_t sector))
}
int
plat_cdrom_read_sector(void *local, uint8_t *buffer, int raw, uint32_t sector)
plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector)
{
dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local;
plat_cdrom_open(ioctl);
if (raw)
/* Raw */
dummy_cdrom_ioctl_log("Raw\n");
else
/* Cooked */
dummy_cdrom_ioctl_log("Cooked\n");
/* Raw */
dummy_cdrom_ioctl_log("Raw\n");
plat_cdrom_close(ioctl);

View File

@@ -43,10 +43,12 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
#endif
#ifdef Q_OS_WINDOWS
# include "qt_rendererstack.hpp"
# include "qt_winrawinputfilter.hpp"
# include "qt_winmanagerfilter.hpp"
# include <86box/win.h>
# include <shobjidl.h>
# include <windows.h>
#endif
extern "C" {
@@ -81,6 +83,7 @@ extern QElapsedTimer elapsed_timer;
extern MainWindow *main_window;
extern "C" {
#include <86box/keyboard.h>
#include <86box/timer.h>
#include <86box/nvr.h>
extern int qt_nvr_save(void);
@@ -88,6 +91,177 @@ extern int qt_nvr_save(void);
void qt_set_sequence_auto_mnemonic(bool b);
#ifdef Q_OS_WINDOWS
static void
keyboard_getkeymap()
{
const LPCSTR keyName = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout";
const LPCSTR valueName = "Scancode Map";
unsigned char buf[32768];
DWORD bufSize;
HKEY hKey;
int j;
UINT32 *bufEx2;
int scMapCount;
UINT16 *bufEx;
int scancode_unmapped;
int scancode_mapped;
/* First, prepare the default scan code map list which is 1:1.
* Remappings will be inserted directly into it.
* 512 bytes so this takes less memory, bit 9 set means E0
* prefix.
*/
for (j = 0; j < 512; j++)
scancode_map[j] = j;
/* Get the scan code remappings from:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout */
bufSize = 32768;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) {
if (RegQueryValueExA(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) {
bufEx2 = (UINT32 *) buf;
scMapCount = bufEx2[2];
if ((bufSize != 0) && (scMapCount != 0)) {
bufEx = (UINT16 *) (buf + 12);
for (j = 0; j < scMapCount * 2; j += 2) {
/* Each scan code is 32-bit: 16 bits of remapped scan code,
and 16 bits of original scan code. */
scancode_unmapped = bufEx[j + 1];
scancode_mapped = bufEx[j];
scancode_unmapped = convert_scan_code(scancode_unmapped);
scancode_mapped = convert_scan_code(scancode_mapped);
/* Ignore source scan codes with prefixes other than E1
that are not E1 1D. */
if (scancode_unmapped != 0xFFFF)
scancode_map[scancode_unmapped] = scancode_mapped;
}
}
}
RegCloseKey(hKey);
}
}
void
win_keyboard_handle(uint32_t scancode, int up, int e0, int e1)
{
/* If it's not a scan code that starts with 0xE1 */
if (e1) {
if (scancode == 0x1D) {
scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would
otherwise be E0 00 but that is invalid
anyway).
Also, take a potential mapping into
account. */
} else
scancode = 0xFFFF;
if (scancode != 0xFFFF)
keyboard_input(!up, scancode);
} else {
if (e0)
scancode |= 0x100;
/* Translate the scan code to 9-bit */
scancode = convert_scan_code(scancode);
/* Remap it according to the list from the Registry */
if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) {
// pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]);
scancode = scancode_map[scancode];
}
/* If it's not 0xFFFF, send it to the emulated
keyboard.
We use scan code 0xFFFF to mean a mapping that
has a prefix other than E0 and that is not E1 1D,
which is, for our purposes, invalid. */
/* Translate right CTRL to left ALT if the user has so
chosen. */
if ((scancode == 0x11d) && rctrl_is_lalt)
scancode = 0x038;
/* Normal scan code pass through, pass it through as is if
it's not an invalid scan code. */
if (scancode != 0xFFFF)
keyboard_input(!up, scancode);
main_window->checkFullscreenHotkey();
}
}
static LRESULT CALLBACK
emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LPKBDLLHOOKSTRUCT lpKdhs = (LPKBDLLHOOKSTRUCT) lParam;
/* Checks if CTRL was pressed. */
BOOL bCtrlDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
BOOL is_over_window = (GetForegroundWindow() == ((HWND) main_window->winId()));
BOOL ret = TRUE;
static int last = 0;
if (show_second_monitors) for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) {
const auto &secondaryRenderer = main_window->renderers[monitor_index];
is_over_window = is_over_window || ((secondaryRenderer != nullptr) &&
(GetForegroundWindow() == ((HWND) secondaryRenderer->winId())));
}
if ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window)
return CallNextHookEx(NULL, nCode, wParam, lParam);
else if ((lpKdhs->scanCode == 0x01) && (lpKdhs->flags & LLKHF_ALTDOWN) &&
!(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x01) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x0f) && (lpKdhs->flags & LLKHF_ALTDOWN) &&
!(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x0f) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x39) && (lpKdhs->flags & LLKHF_ALTDOWN) &&
!(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) &&
!(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED)))
ret = TRUE;
else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP))
ret = TRUE;
else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED))
ret = TRUE;
else
ret = CallNextHookEx(NULL, nCode, wParam, lParam);
if (lpKdhs->scanCode == 0x00000045) {
if ((lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000090)) {
/* NumLock. */
lpKdhs->flags &= ~LLKHF_EXTENDED;
} else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) {
/* Pause - send E1 1D. */
win_keyboard_handle(0xe1, 0, 0, 0);
win_keyboard_handle(0x1d, LLKHF_UP, 0, 0);
}
} else if (!last && (lpKdhs->scanCode == 0x00000036))
/* Non-fake right shift. */
lpKdhs->flags &= ~LLKHF_EXTENDED;
if (lpKdhs->scanCode == 0x00000236)
last = 1;
else if (last && (lpKdhs->scanCode == 0x00000036))
last = 0;
win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0);
return ret;
}
#endif
#ifdef Q_OS_WINDOWS
static HHOOK llhook = NULL;
#endif
void
main_thread_fn()
{
@@ -149,7 +323,7 @@ main_thread_fn()
if (dopause)
ack_pause();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
plat_delay_ms(1);
}
}
@@ -157,7 +331,7 @@ main_thread_fn()
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
if (gfxcard[i]) {
ui_deinit_monitor(i);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
plat_delay_ms(500);
}
}
QTimer::singleShot(0, QApplication::instance(), []() { QApplication::processEvents(); QApplication::instance()->quit(); });
@@ -176,6 +350,7 @@ main(int argc, char *argv[])
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
QApplication app(argc, argv);
QLocale::setDefault(QLocale::C);
@@ -193,6 +368,13 @@ main(int argc, char *argv[])
#endif
elapsed_timer.start();
for (size_t i = 0; i < sizeof(scancode_map) / sizeof(scancode_map[0]); i++)
scancode_map[i] = i;
#ifdef Q_OS_WINDOWS
keyboard_getkeymap();
#endif
if (!pc_init(argc, argv)) {
return 0;
}
@@ -340,6 +522,21 @@ main(int argc, char *argv[])
});
}
/* Force raw input if a debugger is present. */
if (IsDebuggerPresent()) {
pclog("WARNING: Debugged detected, forcing raw input\n");
hook_enabled = 0;
}
if (hook_enabled) {
/* Yes, low-level hooks *DO* work with raw input, at least global ones. */
llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0);
atexit([] () -> void {
if (llhook)
UnhookWindowsHookEx(llhook);
});
}
/* Setup raw input */
auto rawInputFilter = WindowsRawInputFilter::Register(main_window);
if (rawInputFilter) {
@@ -392,7 +589,6 @@ main(int argc, char *argv[])
/* Initialize the rendering window, or fullscreen. */
QTimer::singleShot(0, &app, [] {
pc_reset_hard_init();
main_thread = new std::thread(main_thread_fn);
/* Set the PAUSE mode depending on the renderer. */
#ifdef USE_VNC
@@ -401,6 +597,8 @@ main(int argc, char *argv[])
else
#endif
plat_pause(0);
main_thread = new std::thread(main_thread_fn);
});
const auto ret = app.exec();

View File

@@ -336,16 +336,20 @@ MediaHistoryManager::removeMissingImages(device_index_list_t &device_history)
continue;
}
char temp[MAX_IMAGE_PATH_LEN -1] = { 0 };
char temp[MAX_IMAGE_PATH_LEN * 2] = { 0 };
if (path_abs(checked_path.toUtf8().data())) {
if (checked_path.length() > (MAX_IMAGE_PATH_LEN - 1))
fatal("removeMissingImages(): checked_path.length() > 2047\n");
fatal("removeMissingImages(): checked_path.length() > %i\n", MAX_IMAGE_PATH_LEN - 1);
else
snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s", checked_path.toUtf8().constData());
} else
snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path,
path_get_slash(usr_path), checked_path.toUtf8().constData());
} else {
if ((strlen(usr_path) + strlen(path_get_slash(usr_path)) + checked_path.length()) > (MAX_IMAGE_PATH_LEN - 1))
fatal("removeMissingImages(): Combined absolute path length > %i\n", MAX_IMAGE_PATH_LEN - 1);
else
snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path,
path_get_slash(usr_path), checked_path.toUtf8().constData());
}
path_normalize(temp);
QString qstr = QString::fromUtf8(temp);

View File

@@ -524,7 +524,8 @@ MediaMenu::cdromMute(int i)
void
MediaMenu::cdromMount(int i, const QString &filename)
{
QByteArray fn = filename.toUtf8().data();
QByteArray fn = filename.toUtf8().data();
int was_empty = cdrom_is_empty(i);
cdrom_exit(i);
@@ -542,9 +543,14 @@ MediaMenu::cdromMount(int i, const QString &filename)
cdrom_image_open(&(cdrom[i]), fn.data());
/* Signal media change to the emulated machine. */
if (cdrom[i].insert)
if (cdrom[i].insert) {
cdrom[i].insert(cdrom[i].priv);
/* The drive was previously empty, transition directly to UNIT ATTENTION. */
if (was_empty)
cdrom[i].insert(cdrom[i].priv);
}
if (strlen(cdrom[i].image_path) > 0)
ui_sb_update_icon_state(SB_CDROM | i, 0);
else

View File

@@ -160,6 +160,7 @@ SettingsPorts::on_pushButtonSerialPassThru4_clicked()
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast<Settings *>(Settings::settings));
}
#if 0
void
SettingsPorts::on_pushButtonSerialPassThru5_clicked()
{
@@ -177,6 +178,7 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked()
{
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast<Settings *>(Settings::settings));
}
#endif
void
SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked)
@@ -220,4 +222,4 @@ SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked)
{
ui->pushButtonSerialPassThru7->setEnabled(checked);
}
#endif
#endif

View File

@@ -19,45 +19,23 @@ public:
#if 0
private slots:
void on_checkBoxSerialPassThru7_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru6_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru5_clicked(bool checked);
#endif
private slots:
void on_checkBoxSerialPassThru4_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru3_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru2_clicked(bool checked);
private slots:
void on_checkBoxSerialPassThru1_clicked(bool checked);
private slots:
#if 0
void on_pushButtonSerialPassThru7_clicked();
private slots:
void on_pushButtonSerialPassThru6_clicked();
private slots:
void on_pushButtonSerialPassThru5_clicked();
private slots:
#endif
void on_pushButtonSerialPassThru4_clicked();
private slots:
void on_pushButtonSerialPassThru3_clicked();
private slots:
void on_pushButtonSerialPassThru2_clicked();
private slots:
void on_pushButtonSerialPassThru1_clicked();
private slots:

View File

@@ -56,10 +56,22 @@ extern "C" {
#include <86box/network.h>
#include <86box/machine_status.h>
#ifdef Q_OS_WINDOWS
# include <86box/win.h>
#endif
void
plat_delay_ms(uint32_t count)
{
#ifdef Q_OS_WINDOWS
// On Win32 the accuracy of Sleep() depends on the timer resolution, which can be set by calling timeBeginPeriod
// https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
timeBeginPeriod(1);
Sleep(count);
timeEndPeriod(1);
#else
QThread::msleep(count);
#endif
}
wchar_t *

View File

@@ -44,6 +44,8 @@
#include <86box/plat.h>
#include <86box/86box.h>
extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1);
#include <array>
#include <memory>
@@ -64,8 +66,10 @@ WindowsRawInputFilter::Register(MainWindow *window)
.hwndTarget = nullptr}
};
if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)
return std::unique_ptr<WindowsRawInputFilter>(nullptr);
if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE))
return std::unique_ptr<WindowsRawInputFilter>(nullptr);
else if (!hook_enabled && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE))
return std::unique_ptr<WindowsRawInputFilter>(nullptr);
std::unique_ptr<WindowsRawInputFilter> inputfilter(new WindowsRawInputFilter(window));
@@ -80,11 +84,6 @@ WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window)
connect(menu, &QMenu::aboutToShow, this, [=]() { menus_open++; });
connect(menu, &QMenu::aboutToHide, this, [=]() { menus_open--; });
}
for (size_t i = 0; i < sizeof(scancode_map) / sizeof(scancode_map[0]); i++)
scancode_map[i] = i;
keyboard_getkeymap();
}
WindowsRawInputFilter::~WindowsRawInputFilter()
@@ -100,7 +99,10 @@ WindowsRawInputFilter::~WindowsRawInputFilter()
.hwndTarget = NULL}
};
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
if (hook_enabled)
RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0]));
else
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
}
bool
@@ -158,10 +160,8 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input)
mouse_handle(raw);
break;
case RIM_TYPEHID:
{
win_joystick_handle(raw);
break;
}
win_joystick_handle(raw);
break;
}
}
}
@@ -171,125 +171,10 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input)
void
WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw)
{
USHORT scancode;
RAWKEYBOARD rawKB = raw->data.keyboard;
scancode = rawKB.MakeCode;
/* If it's not a scan code that starts with 0xE1 */
if ((rawKB.Flags & RI_KEY_E1)) {
if (rawKB.MakeCode == 0x1D) {
scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would
otherwise be E0 00 but that is invalid
anyway).
Also, take a potential mapping into
account. */
} else
scancode = 0xFFFF;
if (scancode != 0xFFFF)
keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode);
} else {
if (rawKB.Flags & RI_KEY_E0)
scancode |= 0x100;
/* Translate the scan code to 9-bit */
scancode = convert_scan_code(scancode);
/* Remap it according to the list from the Registry */
if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) {
pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]);
scancode = scancode_map[scancode];
}
/* If it's not 0xFFFF, send it to the emulated
keyboard.
We use scan code 0xFFFF to mean a mapping that
has a prefix other than E0 and that is not E1 1D,
which is, for our purposes, invalid. */
/* Translate right CTRL to left ALT if the user has so
chosen. */
if ((scancode == 0x11d) && rctrl_is_lalt)
scancode = 0x038;
/* Normal scan code pass through, pass it through as is if
it's not an invalid scan code. */
if (scancode != 0xFFFF)
keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode);
window->checkFullscreenHotkey();
}
}
/* This is so we can disambiguate scan codes that would otherwise conflict and get
passed on incorrectly. */
UINT16
WindowsRawInputFilter::convert_scan_code(UINT16 scan_code)
{
if ((scan_code & 0xff00) == 0xe000)
scan_code = (scan_code & 0xff) | 0x0100;
if (scan_code == 0xE11D)
scan_code = 0x0100;
/* E0 00 is sent by some USB keyboards for their special keys, as it is an
invalid scan code (it has no untranslated set 2 equivalent), we mark it
appropriately so it does not get passed through. */
else if ((scan_code > 0x01FF) || (scan_code == 0x0100))
scan_code = 0xFFFF;
return scan_code;
}
void
WindowsRawInputFilter::keyboard_getkeymap()
{
const LPCSTR keyName = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout";
const LPCSTR valueName = "Scancode Map";
unsigned char buf[32768];
DWORD bufSize;
HKEY hKey;
int j;
UINT32 *bufEx2;
int scMapCount;
UINT16 *bufEx;
int scancode_unmapped;
int scancode_mapped;
/* First, prepare the default scan code map list which is 1:1.
* Remappings will be inserted directly into it.
* 512 bytes so this takes less memory, bit 9 set means E0
* prefix.
*/
for (j = 0; j < 512; j++)
scancode_map[j] = j;
/* Get the scan code remappings from:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout */
bufSize = 32768;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, 1, &hKey) == ERROR_SUCCESS) {
if (RegQueryValueExA(hKey, valueName, NULL, NULL, buf, &bufSize) == ERROR_SUCCESS) {
bufEx2 = (UINT32 *) buf;
scMapCount = bufEx2[2];
if ((bufSize != 0) && (scMapCount != 0)) {
bufEx = (UINT16 *) (buf + 12);
for (j = 0; j < scMapCount * 2; j += 2) {
/* Each scan code is 32-bit: 16 bits of remapped scan code,
and 16 bits of original scan code. */
scancode_unmapped = bufEx[j + 1];
scancode_mapped = bufEx[j];
scancode_unmapped = convert_scan_code(scancode_unmapped);
scancode_mapped = convert_scan_code(scancode_mapped);
/* Ignore source scan codes with prefixes other than E1
that are not E1 1D. */
if (scancode_unmapped != 0xFFFF)
scancode_map[scancode_unmapped] = scancode_mapped;
}
}
}
RegCloseKey(hKey);
}
win_keyboard_handle(rawKB.MakeCode, (rawKB.Flags & RI_KEY_BREAK),
(rawKB.Flags & RI_KEY_E0), (rawKB.Flags & RI_KEY_E1));
}
void

View File

@@ -61,7 +61,6 @@ public:
private:
MainWindow *window;
uint16_t scancode_map[768];
int buttons = 0;
int dx = 0;
int dy = 0;
@@ -73,8 +72,6 @@ private:
void handle_input(HRAWINPUT input);
void keyboard_handle(PRAWINPUT raw);
void mouse_handle(PRAWINPUT raw);
static UINT16 convert_scan_code(UINT16 scan_code);
void keyboard_getkeymap();
};
#endif

View File

@@ -26,6 +26,7 @@
#include "ntddcdrm.h"
#include "ntddscsi.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -72,12 +73,19 @@ win_cdrom_ioctl_log(const char *fmt, ...)
# define win_cdrom_ioctl_log(fmt, ...)
#endif
static void
plat_cdrom_close_handle(win_cdrom_ioctl_t *ioctl)
{
if (ioctl->handle != NULL)
CloseHandle(ioctl->handle);
}
static int
plat_cdrom_open(void *local)
{
win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local;
plat_cdrom_close(local);
plat_cdrom_close_handle(local);
ioctl->handle = CreateFileW((LPCWSTR) ioctl->path, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
@@ -107,20 +115,47 @@ plat_cdrom_load(void *local)
static int
plat_cdrom_read_normal_toc(win_cdrom_ioctl_t *ioctl, uint8_t *toc_buf)
{
long size = 0;
long size = 0;
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
memset(toc_buf, 0x00, 65536);
cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536);
if (ioctl->blocks_num != 0) {
memset(ioctl->cur_rti, 0x00, ioctl->blocks_num * 11);
ioctl->blocks_num = 0;
}
ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
win_cdrom_ioctl_log("cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format);
ioctl->cur_read_toc_ex.Msf = 1;
ioctl->cur_read_toc_ex.SessionTrack = 0;
plat_cdrom_open(ioctl);
int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC, NULL, 0, toc_buf, 65535, (LPDWORD) &size, NULL);
int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535,
cur_full_toc, 65535, (LPDWORD) &size, NULL);
plat_cdrom_close(ioctl);
#ifdef ENABLE_WIN_CDROM_IOCTL_LOG
win_cdrom_ioctl_log("temp = %i\n", temp);
if (temp != 0) {
int length = ((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) + 2;
memcpy(toc_buf, cur_full_toc, length);
}
free(cur_full_toc);
#ifdef ENABLE_WIN_CDROM_IOCTL_LOG
PCDROM_TOC toc = (PCDROM_TOC) toc_buf;
const int tracks_num = (((toc->Length[0] << 8) | toc->Length[1]) - 2) / 8;
win_cdrom_ioctl_log("%i tracks\n", tracks_num);
for (int i = 0; i < tracks_num; i++)
win_cdrom_ioctl_log("Track %03i: Point %02X\n", i, (int) toc->TrackData[i].TrackNumber);
win_cdrom_ioctl_log("%i tracks: %02X %02X %02X %02X\n",
tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]);
for (int i = 0; i < tracks_num; i++) {
uint8_t *t = (uint8_t *) &toc->TrackData[i];
win_cdrom_ioctl_log("Track %03i: %02X %02X %02X %02X %02X %02X %02X %02X\n",
i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
}
#endif
return temp;
@@ -130,10 +165,10 @@ static void
plat_cdrom_read_raw_toc(win_cdrom_ioctl_t *ioctl)
{
long size = 0;
int status;
PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL;
memset(ioctl->cur_rti, 0x00, 65536);
cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536);
if (ioctl->blocks_num != 0) {
memset(ioctl->cur_rti, 0x00, ioctl->blocks_num * 11);
@@ -143,11 +178,11 @@ plat_cdrom_read_raw_toc(win_cdrom_ioctl_t *ioctl)
ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC;
win_cdrom_ioctl_log("cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format);
ioctl->cur_read_toc_ex.Msf = 1;
ioctl->cur_read_toc_ex.SessionTrack = 1;
ioctl->cur_read_toc_ex.SessionTrack = 0;
plat_cdrom_open(ioctl);
status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535,
cur_full_toc, 65535, (LPDWORD) &size, NULL);
int status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535,
cur_full_toc, 65535, (LPDWORD) &size, NULL);
plat_cdrom_close(ioctl);
win_cdrom_ioctl_log("status = %i\n", status);
@@ -156,15 +191,21 @@ plat_cdrom_read_raw_toc(win_cdrom_ioctl_t *ioctl)
memcpy(ioctl->cur_rti, cur_full_toc->Descriptors, ioctl->blocks_num * 11);
}
free(cur_full_toc);
#ifdef ENABLE_WIN_CDROM_IOCTL_LOG
win_cdrom_ioctl_log("%i blocks\n", ioctl->blocks_num);
uint8_t *u = (uint8_t *) cur_full_toc;
win_cdrom_ioctl_log("%i blocks: %02X %02X %02X %02X\n",
ioctl->blocks_num, u[0], u[1], u[2], u[3]);
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
for (int i = 0; i < ioctl->blocks_num; i++)
win_cdrom_ioctl_log("Block %03i: Session %03i, Point %02X\n", i, (int) rti[i].session, (int) rti[i].point);
for (int i = 0; i < ioctl->blocks_num; i++) {
uint8_t *t = (uint8_t *) &rti[i];
win_cdrom_ioctl_log("Block %03i: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10]);
}
#endif
free(cur_full_toc);
}
void
@@ -206,7 +247,7 @@ plat_cdrom_is_track_audio(void *local, uint32_t sector)
win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, A: %08X, S: %08X\n",
toc->FirstTrack, toc->LastTrack, cur_td->TrackNumber, c,
cur_td->Control, track_addr, sector);
cur_td->Control, cur_addr, sector);
if ((cur_td->TrackNumber >= toc->FirstTrack) && (cur_td->TrackNumber <= toc->LastTrack) &&
(sector >= cur_addr) && (sector < next_addr)) {
@@ -343,35 +384,20 @@ plat_cdrom_ext_medium_changed(void *local)
memcpy(toc, new_toc, 65535);
if (memcmp(ioctl->path, ioctl->old_path, sizeof(ioctl->path)) != 0)
memcpy(ioctl->old_path, ioctl->path, sizeof(ioctl->path));
} else if (memcmp(&(new_ltd->Address[1]), &(cur_ltd->Address[1]), 3))
} else if (memcmp(&(new_ltd->Address[1]), &(cur_ltd->Address[1]), 3)) {
/* The TOC has changed. */
ioctl->toc_valid = 1;
memcpy(toc, new_toc, 65535);
if (memcmp(ioctl->path, ioctl->old_path, sizeof(ioctl->path)) != 0)
memcpy(ioctl->old_path, ioctl->path, sizeof(ioctl->path));
ret = 1;
}
win_cdrom_ioctl_log("plat_cdrom_ext_medium_changed(): %i\n", ret);
return ret;
}
void
plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out)
{
win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local;
PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc;
plat_cdrom_read_toc(ioctl);
PTRACK_DATA ltd = &toc->TrackData[toc->LastTrack];
*st_track = 1;
*end = toc->LastTrack;
lead_out->min = ltd->Address[1];
lead_out->sec = ltd->Address[2];
lead_out->fr = ltd->Address[3];
win_cdrom_ioctl_log("plat_cdrom_get_audio_tracks(): %02i, %02i, %02i:%02i:%02i\n",
*st_track, *end, lead_out->min, lead_out->sec, lead_out->fr);
}
/* This replaces both Info and EndInfo, they are specified by a variable. */
int
plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr)
@@ -458,38 +484,61 @@ plat_cdrom_get_sector_size(void *local, UNUSED(uint32_t sector))
}
int
plat_cdrom_read_sector(void *local, uint8_t *buffer, int raw, uint32_t sector)
plat_cdrom_read_sector(void *local, uint8_t *buffer, uint32_t sector)
{
win_cdrom_ioctl_t * ioctl = (win_cdrom_ioctl_t *) local;
int status;
long size = 0;
int buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
typedef struct SCSI_PASS_THROUGH_DIRECT_BUF {
SCSI_PASS_THROUGH_DIRECT spt;
ULONG Filler;
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_BUF;
win_cdrom_ioctl_t * ioctl = (win_cdrom_ioctl_t *) local;
int sc_offs = (sector == 0xffffffff) ? 0 : 2352;
unsigned long int unused = 0;
int ret;
SCSI_PASS_THROUGH_DIRECT_BUF req;
memset(&req, 0x00, sizeof(req));
req.Filler = 0;
req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
req.spt.CdbLength = 12;
req.spt.DataIn = SCSI_IOCTL_DATA_IN;
req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf);
req.spt.SenseInfoLength = sizeof(req.SenseBuf);
req.spt.TimeOutValue = 6;
req.spt.DataTransferLength = 2368;
req.spt.DataBuffer = buffer;
/* Fill in the CDB. */
req.spt.Cdb[0] = 0xbe; /* READ CD */
req.spt.Cdb[1] = 0x00; /* DAP = 0, Any Sector Type. */
req.spt.Cdb[2] = (sector >> 24) & 0xff;
req.spt.Cdb[3] = (sector >> 16) & 0xff;
req.spt.Cdb[4] = (sector >> 8) & 0xff;
req.spt.Cdb[5] = sector & 0xff; /* Starting Logical Block Address. */
req.spt.Cdb[6] = 0x00;
req.spt.Cdb[7] = 0x00;
req.spt.Cdb[8] = 0x01; /* Transfer Length. */
/* If sector is FFFFFFFF, only return the subchannel. */
req.spt.Cdb[9] = (sector == 0xffffffff) ? 0x00 : 0xf8;
req.spt.Cdb[10] = 0x02;
req.spt.Cdb[11] = 0x00;
plat_cdrom_open(ioctl);
if (raw) {
/* Raw */
win_cdrom_ioctl_log("Raw\n");
RAW_READ_INFO in;
in.DiskOffset.LowPart = sector * COOKED_SECTOR_SIZE;
in.DiskOffset.HighPart = 0;
in.SectorCount = 1;
in.TrackMode = CDDA;
status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_RAW_READ, &in, sizeof(in),
buffer, buflen, (LPDWORD) &size, NULL);
} else {
/* Cooked */
win_cdrom_ioctl_log("Cooked\n");
int success = 0;
DWORD newPos = SetFilePointer(ioctl->handle, sector * COOKED_SECTOR_SIZE, 0, FILE_BEGIN);
if (newPos != 0xFFFFFFFF)
success = ReadFile(ioctl->handle, buffer, buflen, (LPDWORD) &size, NULL);
status = (success != 0);
}
ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, &req, sizeof(req), &req, sizeof(req),
&unused, NULL);
plat_cdrom_close(ioctl);
win_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size);
return (status > 0) ? (size == buflen) : -1;
/* Construct raw subchannel data from Q only. */
if (ret && (req.spt.DataTransferLength >= 2368))
for (int i = 11; i >= 0; i--)
for (int j = 7; j >= 0; j--)
buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6;
win_cdrom_ioctl_log("plat_cdrom_read_scsi_direct: ret = %d, req.spt.DataTransferLength = %lu\n",
ret, req.spt.DataTransferLength);
win_cdrom_ioctl_log("Sense: %08X, %08X\n", req.spt.SenseInfoLength, req.spt.SenseInfoOffset);
return ret && (req.spt.DataTransferLength >= 2368);
}
void
@@ -508,10 +557,8 @@ plat_cdrom_close(void *local)
{
win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local;
if (ioctl->handle != NULL) {
CloseHandle(ioctl->handle);
ioctl->handle = NULL;
}
plat_cdrom_close_handle(ioctl);
ioctl->handle = NULL;
}
int