Updated kernel file nt functions to support MUs + fixed bugs in xapi functions and input gui related to MUs
This commit is contained in:
parent
88a786b700
commit
3e60c31d26
|
@ -1 +1 @@
|
|||
Subproject commit 9a411fea58d97f4abe49e08893c57d6d9ff7f666
|
||||
Subproject commit 8b000c0ca7f20d88dddd95e80ad257ba2a0cffaa
|
|
@ -144,18 +144,23 @@ protected:
|
|||
|
||||
public:
|
||||
// retrieves the map of input bindings
|
||||
const std::map<int, IoControl*> GetBindings() const {
|
||||
const std::map<int, IoControl*> GetBindings(const std::string &Port) const {
|
||||
std::lock_guard<std::mutex> lck(m_BindingsMtx);
|
||||
return m_Bindings;
|
||||
return m_Bindings.find(Port)->second;
|
||||
}
|
||||
// sets a pair in the map of the input bindings
|
||||
void SetBindings(int XButton, IoControl* Control) {
|
||||
void SetBindings(int XButton, IoControl* Control, const std::string &Port) {
|
||||
std::lock_guard<std::mutex> lck(m_BindingsMtx);
|
||||
m_Bindings[XButton] = Control;
|
||||
m_Bindings[Port][XButton] = Control;
|
||||
}
|
||||
// clears all input bindings for the specified xbox port
|
||||
void ClearBindings(const std::string &Port) {
|
||||
std::lock_guard<std::mutex> lck(m_BindingsMtx);
|
||||
m_Bindings[Port].clear();
|
||||
}
|
||||
|
||||
private:
|
||||
// arbitrary ID assigned by to the device
|
||||
// arbitrary ID assigned to the device
|
||||
int m_ID;
|
||||
// all the input controls detected and usable on this device
|
||||
std::vector<Input*> m_Inputs;
|
||||
|
@ -163,8 +168,8 @@ private:
|
|||
std::vector<Output*> m_Outputs;
|
||||
// xbox port(s) this device is attached to
|
||||
std::vector<std::string> m_XboxPort;
|
||||
// button bindings to the xbox device buttons
|
||||
std::map<int, IoControl*> m_Bindings;
|
||||
// per xbox port button bindings to the xbox device buttons
|
||||
std::unordered_map<std::string, std::map<int, IoControl*>> m_Bindings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -129,7 +129,7 @@ void InputDeviceManager::Initialize(bool is_gui, HWND hwnd)
|
|||
g_EmuShared->GetInputSlotTypeSettings(&type, i, slot);
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||
assert(type == to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT));
|
||||
ConstructHleInputDevice(&g_devs[MU_OFFSET + slot], &g_devs[CTRL_OFFSET + i], type, port + "." + std::to_string(slot));
|
||||
ConstructHleInputDevice(&g_devs[MU_OFFSET + (XBOX_CTRL_NUM_SLOTS * i) + slot], &g_devs[CTRL_OFFSET + i], type, port + "." + std::to_string(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ void InputDeviceManager::RemoveDevice(std::function<bool(const InputDevice*)> Ca
|
|||
void InputDeviceManager::UpdateDevices(std::string_view port, bool ack)
|
||||
{
|
||||
DeviceState *dev, *upstream;
|
||||
int port1, type, slot;
|
||||
int port1, slot, type;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
dev = &g_devs[port1];
|
||||
|
||||
|
@ -234,16 +234,27 @@ void InputDeviceManager::UpdateDevices(std::string_view port, bool ack)
|
|||
g_EmuShared->GetInputDevTypeSettings(&type, port1);
|
||||
}
|
||||
else { // Port references a device attached to a slot port
|
||||
assert(dev->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE ||
|
||||
dev->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S);
|
||||
upstream = dev;
|
||||
dev = dev->slots[slot];
|
||||
g_EmuShared->GetInputSlotTypeSettings(&type, port1, slot);
|
||||
}
|
||||
|
||||
// connect slot
|
||||
// updating a slot
|
||||
if (dev == nullptr) {
|
||||
ConnectDevice(&g_devs[MU_OFFSET + port1 + slot], upstream, type, port);
|
||||
// connect slot
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
g_devs[MU_OFFSET + (XBOX_CTRL_NUM_SLOTS * port1) + slot].type == XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
ConnectDevice(&g_devs[MU_OFFSET + (XBOX_CTRL_NUM_SLOTS * port1) + slot], upstream, type, port);
|
||||
}
|
||||
// disconnect slot
|
||||
else if (type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
g_devs[MU_OFFSET + (XBOX_CTRL_NUM_SLOTS * port1) + slot].type != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
DisconnectDevice(&g_devs[MU_OFFSET + (XBOX_CTRL_NUM_SLOTS * port1) + slot], port, ack);
|
||||
}
|
||||
// update bindings slot
|
||||
else {
|
||||
// MUs don't have any host devices attached, so this is a nop for now
|
||||
}
|
||||
}
|
||||
// connect
|
||||
else if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
|
@ -253,8 +264,8 @@ void InputDeviceManager::UpdateDevices(std::string_view port, bool ack)
|
|||
// disconnect
|
||||
else if (type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
dev->type != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
// We don't need to check of we need to destroy child devices because the UpdateInputEvent_t message always
|
||||
// calls us on the entire slot connectivity if the device has slots available
|
||||
// We don't need to check if we need to destroy child devices because the UpdateInputEvent_t message always
|
||||
// calls us on the entire slot connectivity of a port
|
||||
DisconnectDevice(dev, port, ack);
|
||||
}
|
||||
// update bindings
|
||||
|
@ -309,7 +320,7 @@ void InputDeviceManager::DisconnectDevice(DeviceState *dev, std::string_view por
|
|||
void InputDeviceManager::BindHostDevice(int type, std::string_view port)
|
||||
{
|
||||
if (type == to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT)) {
|
||||
// MUs don't have any host device bound, so we just return
|
||||
// MUs don't have any host devices bound, so we just return
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -322,6 +333,8 @@ void InputDeviceManager::BindHostDevice(int type, std::string_view port)
|
|||
|
||||
auto dev = FindDevice(std::string(dev_name));
|
||||
if (dev != nullptr) {
|
||||
std::string port1(port);
|
||||
dev->ClearBindings(port1);
|
||||
std::vector<InputDevice::IoControl *> controls = dev->GetIoControls();
|
||||
for (int index = 0; index < dev_num_buttons[type]; index++) {
|
||||
std::string dev_button(dev_control_names[index]);
|
||||
|
@ -331,7 +344,7 @@ void InputDeviceManager::BindHostDevice(int type, std::string_view port)
|
|||
}
|
||||
return false;
|
||||
});
|
||||
dev->SetBindings(index, (it != controls.end()) ? *it : nullptr);
|
||||
dev->SetBindings(index, (it != controls.end()) ? *it : nullptr, port1);
|
||||
}
|
||||
dev->SetPort(port, true);
|
||||
}
|
||||
|
@ -348,18 +361,19 @@ bool InputDeviceManager::UpdateXboxPortInput(int port, void* buffer, int directi
|
|||
// If somebody else is currently holding the lock, we won't wait and instead report no input changes
|
||||
if (!g_renderbase->IsImGuiFocus() && m_Mtx.try_lock()) {
|
||||
for (auto &dev : m_Devices) {
|
||||
if (dev->GetPort(std::to_string(port))) {
|
||||
std::string port1 = std::to_string(port);
|
||||
if (dev->GetPort(port1)) {
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
|
||||
has_changed = UpdateInputXpad(dev, buffer, direction);
|
||||
has_changed = UpdateInputXpad(dev, buffer, direction, port1);
|
||||
m_Mtx.unlock();
|
||||
return has_changed;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
|
||||
has_changed = UpdateInputSBC(dev, buffer, direction, port);
|
||||
has_changed = UpdateInputSBC(dev, buffer, direction, port, port1);
|
||||
m_Mtx.unlock();
|
||||
return has_changed;
|
||||
|
||||
|
@ -383,9 +397,9 @@ bool InputDeviceManager::UpdateXboxPortInput(int port, void* buffer, int directi
|
|||
return has_changed;
|
||||
}
|
||||
|
||||
bool InputDeviceManager::UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction)
|
||||
bool InputDeviceManager::UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, const std::string &Port1)
|
||||
{
|
||||
std::map<int, InputDevice::IoControl*> bindings = Device->GetBindings();
|
||||
std::map<int, InputDevice::IoControl*> bindings = Device->GetBindings(Port1);
|
||||
assert(bindings.size() == static_cast<size_t>(dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE)]));
|
||||
|
||||
if (Direction == DIRECTION_IN) {
|
||||
|
@ -447,9 +461,9 @@ bool InputDeviceManager::UpdateInputXpad(std::shared_ptr<InputDevice>& Device, v
|
|||
return true;
|
||||
}
|
||||
|
||||
bool InputDeviceManager::UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port)
|
||||
bool InputDeviceManager::UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port, const std::string &Port1)
|
||||
{
|
||||
std::map<int, InputDevice::IoControl*> bindings = Device->GetBindings();
|
||||
std::map<int, InputDevice::IoControl*> bindings = Device->GetBindings(Port1);
|
||||
assert(bindings.size() == static_cast<size_t>(dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER)]));
|
||||
|
||||
// NOTE: the output state is not supported
|
||||
|
|
|
@ -165,9 +165,9 @@ public:
|
|||
|
||||
private:
|
||||
// update input for an xbox controller
|
||||
bool UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction);
|
||||
bool UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, const std::string &Port1);
|
||||
// update input for a Steel Battalion controller
|
||||
bool UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port);
|
||||
bool UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port, const std::string &Port1);
|
||||
// bind a host device to an emulated device
|
||||
void BindHostDevice(int type, std::string_view port);
|
||||
// connect a device to the emulated machine
|
||||
|
|
|
@ -43,7 +43,7 @@ InputWindow::~InputWindow()
|
|||
m_DeviceConfig = nullptr;
|
||||
}
|
||||
|
||||
int InputWindow::IsProfileSaved()
|
||||
bool InputWindow::IsProfileSaved()
|
||||
{
|
||||
if (m_bHasChanges) {
|
||||
PopupReturn ret = PopupQuestion(m_hwnd_window, "Current configuration is not saved. Save before closing?");
|
||||
|
@ -53,24 +53,24 @@ int InputWindow::IsProfileSaved()
|
|||
char name[50];
|
||||
SendMessage(m_hwnd_profile_list, WM_GETTEXT, sizeof(name), reinterpret_cast<LPARAM>(name));
|
||||
if (SaveProfile(std::string(name))) {
|
||||
return EXIT_SAVE;
|
||||
return true;
|
||||
}
|
||||
return EXIT_ABORT;
|
||||
return false;
|
||||
}
|
||||
|
||||
case PopupReturn::No: {
|
||||
return EXIT_IGNORE;
|
||||
return true;
|
||||
}
|
||||
|
||||
case PopupReturn::Cancel:
|
||||
default: {
|
||||
return EXIT_ABORT;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_IGNORE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputWindow::UpdateDeviceList()
|
||||
|
|
|
@ -42,10 +42,6 @@
|
|||
#define BUTTON_SWAP 9
|
||||
#define SLOTS_CHANGED 10
|
||||
|
||||
#define EXIT_ABORT 0
|
||||
#define EXIT_SAVE 1
|
||||
#define EXIT_IGNORE 2
|
||||
|
||||
#define XINPUT_DEFAULT 0
|
||||
#define DINPUT_DEFAULT 1
|
||||
|
||||
|
@ -65,7 +61,7 @@ public:
|
|||
virtual void ClearBindings() = 0;
|
||||
virtual void UpdateProfile(const std::string& name, int command);
|
||||
void UpdateCurrentDevice();
|
||||
virtual int IsProfileSaved();
|
||||
bool IsProfileSaved();
|
||||
void SwapMoCursorAxis(Button *button);
|
||||
|
||||
|
||||
|
@ -111,7 +107,6 @@ public:
|
|||
void BindDefault();
|
||||
void ClearBindings() override;
|
||||
void UpdateProfile(const std::string &name, int command) override;
|
||||
int IsProfileSaved() override;
|
||||
void SaveSlotConfig();
|
||||
|
||||
|
||||
|
|
|
@ -163,20 +163,19 @@ namespace Sdl
|
|||
std::string port = std::to_string(*static_cast<int *>(Event.user.data1));
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
if (g_devs[port1].type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE || g_devs[port1].type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S) {
|
||||
// Force an update of the entire slot connectivity of this port
|
||||
g_InputDeviceManager.UpdateDevices(port + ".0", false);
|
||||
g_InputDeviceManager.UpdateDevices(port + ".1", false);
|
||||
}
|
||||
|
||||
g_InputDeviceManager.UpdateDevices(port, false);
|
||||
// Force an update of the entire slot connectivity of this port
|
||||
g_InputDeviceManager.UpdateDevices(port + ".0", false);
|
||||
g_InputDeviceManager.UpdateDevices(port + ".1", false);
|
||||
}
|
||||
|
||||
delete Event.user.data1;
|
||||
delete static_cast<int *>(Event.user.data1);
|
||||
Event.user.data1 = nullptr;
|
||||
}
|
||||
else if (Event.type == DeviceRemoveAck_t) {
|
||||
g_InputDeviceManager.UpdateDevices(std::string(static_cast<char *>(Event.user.data1)), true);
|
||||
delete Event.user.data1;
|
||||
g_InputDeviceManager.UpdateDevices(*static_cast<std::string *>(Event.user.data1), true);
|
||||
delete static_cast<std::string *>(Event.user.data1);
|
||||
Event.user.data1 = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,12 +43,6 @@ namespace Sdl
|
|||
}
|
||||
SDL_INIT_STATUS;
|
||||
|
||||
struct UPDATE_INPUT_DATA {
|
||||
int Port;
|
||||
int Slot;
|
||||
bool Opt;
|
||||
};
|
||||
|
||||
extern uint32_t ExitEvent_t;
|
||||
extern uint32_t PopulateEvent_t;
|
||||
extern uint32_t UpdateInputEvent_t;
|
||||
|
|
|
@ -352,7 +352,7 @@ g_EmuCDPD;
|
|||
|
||||
XB_TRAMPOLINES(XB_trampoline_declare);
|
||||
|
||||
void LookupTrampolines()
|
||||
void LookupTrampolinesD3D()
|
||||
{
|
||||
XB_TRAMPOLINES(XB_trampoline_lookup);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
#define DIRECTDRAW_VERSION 0x0700
|
||||
#include <ddraw.h>
|
||||
|
||||
extern void LookupTrampolines();
|
||||
extern void LookupTrampolinesD3D();
|
||||
extern void LookupTrampolinesXAPI();
|
||||
|
||||
// initialize render window
|
||||
extern void CxbxInitWindow(bool bFullInit);
|
||||
|
|
|
@ -365,6 +365,7 @@ std::map<const std::string, const xbox_patch_t> g_PatchTable = {
|
|||
PATCH_ENTRY("XSetProcessQuantumLength", xbox::EMUPATCH(XSetProcessQuantumLength), PATCH_ALWAYS),
|
||||
PATCH_ENTRY("timeKillEvent", xbox::EMUPATCH(timeKillEvent), PATCH_ALWAYS),
|
||||
PATCH_ENTRY("timeSetEvent", xbox::EMUPATCH(timeSetEvent), PATCH_ALWAYS),
|
||||
PATCH_ENTRY("XReadMUMetaData", xbox::EMUPATCH(XReadMUMetaData), PATCH_ALWAYS),
|
||||
PATCH_ENTRY("XUnmountMU", xbox::EMUPATCH(XUnmountMU), PATCH_ALWAYS),
|
||||
};
|
||||
|
||||
|
@ -445,7 +446,8 @@ void EmuInstallPatches()
|
|||
EmuInstallPatch(it.first, it.second);
|
||||
}
|
||||
|
||||
LookupTrampolines();
|
||||
LookupTrampolinesD3D();
|
||||
LookupTrampolinesXAPI();
|
||||
}
|
||||
|
||||
void* GetPatchedFunctionTrampoline(const std::string functionName)
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
#include "Windef.h"
|
||||
#include <vector>
|
||||
#include "core\hle\XAPI\Xapi.h"
|
||||
#include "distorm.h"
|
||||
#include "mnemonics.h"
|
||||
#include <charconv>
|
||||
|
||||
|
||||
|
@ -63,9 +61,26 @@ std::atomic<bool> g_bXppGuard = false;
|
|||
// 4 duke / S / sbc / arcade joystick (mutually exclusive) + 8 memory units
|
||||
DeviceState g_devs[4 + 8];
|
||||
|
||||
xbox::ulong_xt g_Mounted_MUs = 0; // fallback if XapiMountedMUs is not found
|
||||
xbox::ulong_xt g_Mounted_MUs = 0;
|
||||
xbox::char_xt g_AltLett_MU = 0;
|
||||
xbox::ulong_xt *g_XapiMountedMUs = &g_Mounted_MUs;
|
||||
std::mutex g_MuLock;
|
||||
xbox::char_xt *g_XapiAltLett_MU = &g_AltLett_MU;
|
||||
std::recursive_mutex g_MuLock;
|
||||
|
||||
// Declare trampolines
|
||||
#define XB_TRAMPOLINES(XB_MACRO) \
|
||||
XB_MACRO(xbox::dword_xt, WINAPI, XUnmountAlternateTitleA, (xbox::char_xt) ); \
|
||||
XB_MACRO(xbox::ntstatus_xt, WINAPI, XapiMapLetterToDirectory, (xbox::PSTRING, xbox::PSTRING, const xbox::PCHAR, xbox::bool_xt, xbox::PCWSTR, xbox::bool_xt) ); \
|
||||
|
||||
XB_TRAMPOLINES(XB_trampoline_declare);
|
||||
|
||||
void LookupTrampolinesXAPI()
|
||||
{
|
||||
XB_TRAMPOLINES(XB_trampoline_lookup);
|
||||
}
|
||||
|
||||
#undef XB_TRAMPOLINES
|
||||
|
||||
|
||||
static inline xbox::char_xt MuPort2Lett(xbox::dword_xt port, xbox::dword_xt slot)
|
||||
{
|
||||
|
@ -168,8 +183,6 @@ void UpdateXppState(DeviceState *dev, XBOX_INPUT_DEVICE type, std::string_view p
|
|||
while (g_bXppGuard) {}
|
||||
|
||||
if (xpp == g_DeviceType_MU) {
|
||||
assert((dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE) ||
|
||||
(dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S));
|
||||
assert(slot != PORT_INVALID);
|
||||
if (slot == 1) {
|
||||
slot_mask = 16;
|
||||
|
@ -193,7 +206,7 @@ void ConstructHleInputDevice(DeviceState *dev, DeviceState *upstream, int type,
|
|||
if (g_bIsChihiro) {
|
||||
// Don't emulate XID devices during Chihiro Emulation
|
||||
g_bIsDevicesEmulating = false;
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
// Set up common device state
|
||||
int port1, slot;
|
||||
|
@ -280,7 +293,7 @@ void DestructHleInputDevice(DeviceState *dev)
|
|||
dev->bSignaled = false;
|
||||
dev->slots[SLOT_TOP] = dev->slots[SLOT_BOTTOM] = nullptr;
|
||||
|
||||
switch (dev->type)
|
||||
switch (type)
|
||||
{
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE:
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_S:
|
||||
|
@ -314,8 +327,7 @@ void DestructHleInputDevice(DeviceState *dev)
|
|||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::MEMORY_UNIT: {
|
||||
assert(dev->upstream != nullptr && (dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE ||
|
||||
dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S));
|
||||
assert(dev->upstream != nullptr);
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
assert(slot != PORT_INVALID);
|
||||
|
@ -403,77 +415,23 @@ void SetupXboxDeviceTypes()
|
|||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_GAMEPAD found at 0x%08X", (uintptr_t)g_DeviceType_Gamepad);
|
||||
}
|
||||
|
||||
// The MU device type is not present in the xpp table, because that only holds the types that XInputOpen supports, and MUs are not
|
||||
// one of those. Insted, this type is referenced by MU_Init, the main MU initialization function, so we can derive it from that.
|
||||
// Unfortunately, the offset of the MU type varies slightly between xdk revisions, so we cannot just read from a fixed offset. What's
|
||||
// constant is that the type is always hardcoded in a push instruction immediately followed by a call, and there are no other push - call
|
||||
// instructions between the start of MU_Init and the offset of interest.
|
||||
|
||||
if (uint8_t *start = reinterpret_cast<uint8_t *>(g_SymbolAddresses["MU_Init"])) {
|
||||
_CodeInfo ci;
|
||||
ci.code = start;
|
||||
ci.codeLen = 100;
|
||||
ci.codeOffset = 0;
|
||||
ci.dt = Decode32Bits;
|
||||
ci.features = DF_NONE;
|
||||
std::array<_DInst, 50> info;
|
||||
unsigned i;
|
||||
|
||||
distorm_decompose(&ci, info.data(), 50, &i);
|
||||
|
||||
i = 0;
|
||||
const auto &it = std::find_if(info.begin(), info.end(), [&info, &i](_DInst &op) {
|
||||
if (!(op.opcode == I_PUSH)) {
|
||||
++i;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((i + 1) <= 49) && (info[i + 1].opcode == I_CALL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (it == info.end()) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "XDEVICE_TYPE_MEMORY_UNIT was not found inside MU_Init");
|
||||
}
|
||||
else {
|
||||
g_DeviceType_MU = reinterpret_cast<xbox::PXPP_DEVICE_TYPE>(*reinterpret_cast<uint32_t *>((it->addr + start + 1)));
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT found at 0x%08X", reinterpret_cast<uintptr_t>(g_DeviceType_MU));
|
||||
}
|
||||
if (xbox::addr_xt mu_xpp_type = g_SymbolAddresses["g_DeviceType_MU"]) {
|
||||
g_DeviceType_MU = reinterpret_cast<xbox::PXPP_DEVICE_TYPE>(mu_xpp_type);
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT found at 0x%08X", reinterpret_cast<uintptr_t>(g_DeviceType_MU));
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT was not found because MU_Init could not be found");
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT was not found by XbSymbolDatabase");
|
||||
}
|
||||
|
||||
// Temporary code until XapiMountedMUs is derived by XbSymbolDatabase
|
||||
Xbe::LibraryVersion *pLibraryVersion = reinterpret_cast<Xbe::LibraryVersion *>(CxbxKrnl_Xbe->m_Header.dwLibraryVersionsAddr);
|
||||
if (pLibraryVersion != nullptr) {
|
||||
if (uint8_t *start = reinterpret_cast<uint8_t *>(g_SymbolAddresses["XUnmountMU"])) {
|
||||
uint32_t offset = 0;
|
||||
for (unsigned v = 0; v < CxbxKrnl_Xbe->m_Header.dwLibraryVersions; ++v) {
|
||||
if (std::strcmp(pLibraryVersion[v].szName, "XAPILIB") == 0) {
|
||||
if (pLibraryVersion[v].wBuildVersion < 4242) {
|
||||
offset = 0x1D;
|
||||
}
|
||||
else {
|
||||
offset = 0x2A;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// skip 2 because the address is hard-coded inside a test instruction
|
||||
g_XapiMountedMUs = reinterpret_cast<xbox::ulong_xt *>(*reinterpret_cast<uint32_t *>((g_SymbolAddresses["XUnmountMU"] + offset + 2)));
|
||||
EmuLog(LOG_LEVEL::INFO, "XapiMountedMUs found at 0x%08X", reinterpret_cast<uintptr_t>(g_XapiMountedMUs));
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "XapiMountedMUs was not found because XUnmountMU could not be found");
|
||||
}
|
||||
if (xbox::addr_xt xapi_mounted_mu = g_SymbolAddresses["g_XapiMountedMUs"]) {
|
||||
g_XapiMountedMUs = reinterpret_cast<xbox::ulong_xt *>(xapi_mounted_mu);
|
||||
EmuLog(LOG_LEVEL::INFO, "XapiMountedMUs found at 0x%08X", reinterpret_cast<uintptr_t>(g_XapiMountedMUs));
|
||||
|
||||
g_XapiAltLett_MU = reinterpret_cast<xbox::char_xt *>(g_XapiMountedMUs - 1);
|
||||
EmuLog(LOG_LEVEL::INFO, "XapiAltLett_MU found at 0x%08X", reinterpret_cast<uintptr_t>(g_XapiAltLett_MU));
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "XapiMountedMUs was not found because this xbe does not have a library version address");
|
||||
EmuLog(LOG_LEVEL::INFO, "XapiMountedMUs was not found by XbSymbolDatabase");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,10 +503,10 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XGetDevices)
|
|||
LOG_FUNC_ONE_ARG(DeviceType);
|
||||
|
||||
g_bXppGuard = true;
|
||||
static dword_xt last_connected = 0;
|
||||
|
||||
if (g_bIsDevicesInitializing || g_bIsDevicesEmulating) {
|
||||
g_bXppGuard = false;
|
||||
RETURN(last_connected);
|
||||
RETURN(DeviceType->CurrentConnected);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 12; ++i) {
|
||||
|
@ -558,15 +516,14 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XGetDevices)
|
|||
SDL_Event DeviceRemoveEvent;
|
||||
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
|
||||
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
|
||||
DeviceRemoveEvent.user.data1 = new char[g_devs[i].port.size()];
|
||||
std::strcpy(static_cast<char *>(DeviceRemoveEvent.user.data1), g_devs[i].port.c_str());
|
||||
DeviceRemoveEvent.user.data1 = new std::string(g_devs[i].port);
|
||||
SDL_PushEvent(&DeviceRemoveEvent);
|
||||
}
|
||||
}
|
||||
|
||||
UCHAR oldIrql = xbox::KeRaiseIrqlToDpcLevel();
|
||||
|
||||
last_connected = DeviceType->CurrentConnected;
|
||||
dword_xt ret = DeviceType->CurrentConnected;
|
||||
|
||||
DeviceType->ChangeConnected = 0;
|
||||
DeviceType->PreviousConnected = DeviceType->CurrentConnected;
|
||||
|
@ -575,7 +532,7 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XGetDevices)
|
|||
|
||||
g_bXppGuard = false;
|
||||
|
||||
RETURN(last_connected);
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -613,8 +570,7 @@ xbox::bool_xt WINAPI xbox::EMUPATCH(XGetDeviceChanges)
|
|||
SDL_Event DeviceRemoveEvent;
|
||||
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
|
||||
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
|
||||
DeviceRemoveEvent.user.data1 = new char[g_devs[i].port.size()];
|
||||
std::strcpy(static_cast<char *>(DeviceRemoveEvent.user.data1), g_devs[i].port.c_str());
|
||||
DeviceRemoveEvent.user.data1 = new std::string(g_devs[i].port);
|
||||
SDL_PushEvent(&DeviceRemoveEvent);
|
||||
}
|
||||
}
|
||||
|
@ -1384,6 +1340,22 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XMountMUA)
|
|||
RETURN(ERROR_ALREADY_ASSIGNED);
|
||||
}
|
||||
|
||||
char title_id_buff[9];
|
||||
std::sprintf(title_id_buff, "%08lx", CxbxKrnl_Xbe->m_Certificate.dwTitleId);
|
||||
std::string mu_path_str(DrivePrefix + lett + ":");
|
||||
std::string mu_dev_str(DeviceMU + std::to_string(MuPort2Idx(dwPort, dwSlot)));
|
||||
ANSI_STRING mu_dev, mu_path;
|
||||
RtlInitAnsiString(&mu_path, mu_path_str.data());
|
||||
RtlInitAnsiString(&mu_dev, mu_dev_str.data());
|
||||
mu_dev_str += '\\';
|
||||
|
||||
ntstatus_xt status = XB_TRMP(XapiMapLetterToDirectory)(&mu_path, &mu_dev, title_id_buff, 1,
|
||||
reinterpret_cast<const char16_t *>(CxbxKrnl_Xbe->m_Certificate.wsTitleName), 0);
|
||||
|
||||
if (!nt_success(status)) {
|
||||
RETURN(RtlNtStatusToDosError(status));
|
||||
}
|
||||
|
||||
MuSetMounted(lett);
|
||||
if (pchDrive != zeroptr) {
|
||||
*pchDrive = lett;
|
||||
|
@ -1465,8 +1437,7 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XMountMURootA)
|
|||
if (pchDrive != zeroptr) {
|
||||
*pchDrive = 0;
|
||||
}
|
||||
RtlNtStatusToDosError(status);
|
||||
RETURN(status);
|
||||
RETURN(RtlNtStatusToDosError(status));
|
||||
}
|
||||
|
||||
MuSetMounted(lett);
|
||||
|
@ -1498,21 +1469,115 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XUnmountMU)
|
|||
RETURN(ERROR_INVALID_DRIVE);
|
||||
}
|
||||
|
||||
if (*g_XapiAltLett_MU == lett) {
|
||||
XB_TRMP(XUnmountAlternateTitleA)('X');
|
||||
}
|
||||
|
||||
std::string mu_path_str(DrivePrefix + lett + ":");
|
||||
ANSI_STRING mu_path;
|
||||
RtlInitAnsiString(&mu_path, mu_path_str.data());
|
||||
ntstatus_xt status = IoDeleteSymbolicLink(&mu_path);
|
||||
|
||||
if (!nt_success(status)) {
|
||||
RtlNtStatusToDosError(status);
|
||||
RETURN(status);
|
||||
RETURN(RtlNtStatusToDosError(status));
|
||||
}
|
||||
|
||||
MuClearMounted(lett);
|
||||
g_io_mu_metadata->flush(static_cast<wchar_t>(lett));
|
||||
|
||||
RETURN(ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XReadMUMetaData
|
||||
// ******************************************************************
|
||||
xbox::dword_xt WINAPI xbox::EMUPATCH(XReadMUMetaData)
|
||||
(
|
||||
IN dword_xt dwPort,
|
||||
IN dword_xt dwSlot,
|
||||
IN LPVOID lpBuffer,
|
||||
IN dword_xt dwByteOffset,
|
||||
IN dword_xt dwNumberOfBytesToRead
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(dwPort)
|
||||
LOG_FUNC_ARG(dwSlot)
|
||||
LOG_FUNC_ARG(lpBuffer)
|
||||
LOG_FUNC_ARG(dwByteOffset)
|
||||
LOG_FUNC_ARG(dwNumberOfBytesToRead)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// NOTE: in reality, this function should actually use IoSynchronousFsdRequest to read the metadata of the MU. Unfortunately,
|
||||
// that requires kernel support for device objects, which when this was implemented, was non-existent. So, we instead cheat
|
||||
// and use NtFsControlFile to perform the same action.
|
||||
|
||||
std::lock_guard lock(g_MuLock);
|
||||
|
||||
bool unmount = false;
|
||||
char_xt lett = MuPort2Lett(dwPort, dwSlot);
|
||||
if (!MuIsMounted(lett)) {
|
||||
unmount = true;
|
||||
dword_xt ret = EMUPATCH(XMountMURootA(dwPort, dwSlot, &lett));
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
RETURN(ret);
|
||||
}
|
||||
}
|
||||
|
||||
OBJECT_ATTRIBUTES obj;
|
||||
std::string mu_path_str(DrivePrefix + lett + ":");
|
||||
ANSI_STRING mu_path;
|
||||
RtlInitAnsiString(&mu_path, mu_path_str.data());
|
||||
XB_InitializeObjectAttributes(&obj, &mu_path, obj_case_insensitive, ObDosDevicesDirectory());
|
||||
|
||||
HANDLE handle;
|
||||
IO_STATUS_BLOCK io_status_block;
|
||||
ntstatus_xt status = NtOpenFile(&handle,
|
||||
SYNCHRONIZE | GENERIC_READ,
|
||||
&obj,
|
||||
&io_status_block,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
||||
if (nt_success(status)) {
|
||||
fatx_volume_metadata volume;
|
||||
volume.offset = dwByteOffset;
|
||||
volume.length = dwNumberOfBytesToRead;
|
||||
volume.buffer = new char[dwNumberOfBytesToRead];
|
||||
|
||||
status = NtFsControlFile(handle,
|
||||
zeroptr,
|
||||
zeroptr,
|
||||
zeroptr,
|
||||
&io_status_block,
|
||||
fsctl_read_fatx_metadata,
|
||||
&volume,
|
||||
sizeof(volume),
|
||||
zeroptr,
|
||||
0);
|
||||
|
||||
if (nt_success(status)) {
|
||||
std::memcpy(lpBuffer, volume.buffer, dwNumberOfBytesToRead);
|
||||
status = status_success;
|
||||
}
|
||||
else {
|
||||
status = status_unrecognized_volume;
|
||||
}
|
||||
|
||||
delete[] volume.buffer;
|
||||
NtClose(handle);
|
||||
}
|
||||
else {
|
||||
status = status_unrecognized_volume;
|
||||
}
|
||||
|
||||
if (unmount) {
|
||||
EMUPATCH(XUnmountMU(dwPort, dwSlot));
|
||||
}
|
||||
|
||||
RETURN(RtlNtStatusToDosError(status));
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: OutputDebugStringA
|
||||
// ******************************************************************
|
||||
|
|
|
@ -693,6 +693,18 @@ xbox::dword_xt WINAPI EMUPATCH(XUnmountMU)
|
|||
dword_xt dwSlot
|
||||
);
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XReadMUMetaData
|
||||
// ******************************************************************
|
||||
xbox::dword_xt WINAPI EMUPATCH(XReadMUMetaData)
|
||||
(
|
||||
IN dword_xt dwPort,
|
||||
IN dword_xt dwSlot,
|
||||
IN LPVOID lpBuffer,
|
||||
IN dword_xt dwByteOffset,
|
||||
IN dword_xt dwNumberOfBytesToRead
|
||||
);
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XMountAlternateTitleA
|
||||
// ******************************************************************
|
||||
|
|
|
@ -100,6 +100,7 @@ inline constexpr dword_xt status_unable_to_free_vm = 0xC000001AL;
|
|||
inline constexpr dword_xt status_free_vm_not_at_base = 0xC000009FL;
|
||||
inline constexpr dword_xt status_memory_not_allocated = 0xC00000A0L;
|
||||
inline constexpr dword_xt status_not_committed = 0xC000002DL;
|
||||
inline constexpr dword_xt status_unrecognized_volume = 0xC000014FL;
|
||||
|
||||
// ******************************************************************
|
||||
// * Registry value types
|
||||
|
|
|
@ -619,8 +619,7 @@ XBSYSAPI EXPORTNUM(196) xbox::ntstatus_xt NTAPI xbox::NtDeviceIoControlFile
|
|||
|
||||
switch (IoControlCode)
|
||||
{
|
||||
case 0x4D014: // IOCTL_SCSI_PASS_THROUGH_DIRECT
|
||||
{
|
||||
case 0x4D014: { // IOCTL_SCSI_PASS_THROUGH_DIRECT
|
||||
PSCSI_PASS_THROUGH_DIRECT PassThrough = (PSCSI_PASS_THROUGH_DIRECT)InputBuffer;
|
||||
PDVDX2_AUTHENTICATION Authentication = (PDVDX2_AUTHENTICATION)PassThrough->DataBuffer;
|
||||
|
||||
|
@ -628,34 +627,63 @@ XBSYSAPI EXPORTNUM(196) xbox::ntstatus_xt NTAPI xbox::NtDeviceIoControlFile
|
|||
Authentication->AuthenticationPage.CDFValid = 1;
|
||||
Authentication->AuthenticationPage.PartitionArea = 1;
|
||||
Authentication->AuthenticationPage.Authentication = 1;
|
||||
break;
|
||||
}
|
||||
case 0x70000: // IOCTL_DISK_GET_DRIVE_GEOMETRY
|
||||
{
|
||||
break;
|
||||
|
||||
case 0x70000: { // IOCTL_DISK_GET_DRIVE_GEOMETRY
|
||||
PDISK_GEOMETRY DiskGeometry = (PDISK_GEOMETRY)OutputBuffer;
|
||||
|
||||
DiskGeometry->MediaType = FixedMedia;
|
||||
DiskGeometry->TracksPerCylinder = 1;
|
||||
DiskGeometry->SectorsPerTrack = 1;
|
||||
DiskGeometry->BytesPerSector = 512;
|
||||
DiskGeometry->Cylinders.QuadPart = 0x1400000; // Around 10GB, size of stock xbox HDD
|
||||
break;
|
||||
DeviceType type = CxbxrGetDeviceTypeFromHandle(FileHandle);
|
||||
if (type == DeviceType::Harddisk0) {
|
||||
DiskGeometry->MediaType = FixedMedia;
|
||||
DiskGeometry->TracksPerCylinder = 1;
|
||||
DiskGeometry->SectorsPerTrack = 1;
|
||||
DiskGeometry->BytesPerSector = 512;
|
||||
DiskGeometry->Cylinders.QuadPart = 0x1400000; // 10GB, size of stock xbox HDD
|
||||
}
|
||||
else if (type == DeviceType::MU) {
|
||||
DiskGeometry->MediaType = FixedMedia;
|
||||
DiskGeometry->TracksPerCylinder = 1;
|
||||
DiskGeometry->SectorsPerTrack = 1;
|
||||
DiskGeometry->BytesPerSector = 512;
|
||||
DiskGeometry->Cylinders.QuadPart = 0x4000; // 8MB, Microsoft original MUs
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "%s: Unrecongnized handle 0x%X with IoControlCode IOCTL_DISK_GET_DRIVE_GEOMETRY.", __func__, FileHandle);
|
||||
ret = status_invalid_handle;
|
||||
}
|
||||
}
|
||||
case 0x74004: // IOCTL_DISK_GET_PARTITION_INFO
|
||||
{
|
||||
break;
|
||||
|
||||
case 0x74004: { // IOCTL_DISK_GET_PARTITION_INFO
|
||||
PPARTITION_INFORMATION partitioninfo = (PPARTITION_INFORMATION)OutputBuffer;
|
||||
|
||||
XboxPartitionTable partitionTable = CxbxGetPartitionTable();
|
||||
int partitionNumber = CxbxGetPartitionNumberFromHandle(FileHandle);
|
||||
|
||||
// Now we read from the partition table, to fill in the partitionInfo struct
|
||||
partitioninfo->PartitionNumber = partitionNumber;
|
||||
partitioninfo->StartingOffset.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBAStart * 512;
|
||||
partitioninfo->PartitionLength.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBASize * 512;
|
||||
partitioninfo->HiddenSectors = partitionTable.TableEntries[partitionNumber - 1].Reserved;
|
||||
partitioninfo->RecognizedPartition = true;
|
||||
break;
|
||||
DeviceType type = CxbxrGetDeviceTypeFromHandle(FileHandle);
|
||||
if (type == DeviceType::Harddisk0) {
|
||||
XboxPartitionTable partitionTable = CxbxGetPartitionTable();
|
||||
int partitionNumber = CxbxGetPartitionNumberFromHandle(FileHandle);
|
||||
|
||||
// Now we read from the partition table, to fill in the partitionInfo struct
|
||||
partitioninfo->PartitionNumber = partitionNumber;
|
||||
partitioninfo->StartingOffset.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBAStart * 512;
|
||||
partitioninfo->PartitionLength.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBASize * 512;
|
||||
partitioninfo->HiddenSectors = partitionTable.TableEntries[partitionNumber - 1].Reserved;
|
||||
partitioninfo->RecognizedPartition = true;
|
||||
}
|
||||
else if (type == DeviceType::MU) {
|
||||
partitioninfo->PartitionNumber = 0;
|
||||
partitioninfo->StartingOffset.QuadPart = 0; // FIXME: where does the MU partition start?
|
||||
partitioninfo->PartitionLength.QuadPart = 16384; // 8MB
|
||||
partitioninfo->HiddenSectors = 0;
|
||||
partitioninfo->RecognizedPartition = true;
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "%s: Unrecongnized handle 0x%X with IoControlCode IOCTL_DISK_GET_PARTITION_INFO.", __func__, FileHandle);
|
||||
ret = status_invalid_handle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_UNIMPLEMENTED();
|
||||
}
|
||||
|
@ -802,19 +830,55 @@ XBSYSAPI EXPORTNUM(200) xbox::ntstatus_xt NTAPI xbox::NtFsControlFile
|
|||
LOG_FUNC_ARG(OutputBufferLength)
|
||||
LOG_FUNC_END;
|
||||
|
||||
NTSTATUS ret = STATUS_INVALID_PARAMETER;
|
||||
ntstatus_xt ret = STATUS_INVALID_PARAMETER;
|
||||
|
||||
switch (FsControlCode)
|
||||
{
|
||||
case fsctl_dismount_volume: {
|
||||
int partitionNumber = CxbxGetPartitionNumberFromHandle(FileHandle);
|
||||
if (partitionNumber > 0) {
|
||||
CxbxFormatPartitionByHandle(FileHandle);
|
||||
ret = xbox::status_success;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case fsctl_read_fatx_metadata: {
|
||||
const std::wstring path = CxbxGetFinalPathNameByHandle(FileHandle);
|
||||
size_t pos = path.rfind(L"\\EmuMu");
|
||||
if (pos != std::string::npos && path[pos + 6] == '\\') {
|
||||
// Ensure that InputBuffer is indeed what we think it is
|
||||
pfatx_volume_metadata volume = static_cast<pfatx_volume_metadata>(InputBuffer);
|
||||
assert(InputBufferLength == sizeof(fatx_volume_metadata));
|
||||
g_io_mu_metadata->read(path[pos + 7], volume->offset, static_cast<char *>(volume->buffer), volume->length);
|
||||
ret = xbox::status_success;
|
||||
}
|
||||
else {
|
||||
ret = status_invalid_handle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case fsctl_write_fatx_metadata: {
|
||||
const std::wstring path = CxbxGetFinalPathNameByHandle(FileHandle);
|
||||
size_t pos = path.rfind(L"\\EmuMu");
|
||||
if (pos != std::string::npos && path[pos + 6] == '\\') {
|
||||
// Ensure that InputBuffer is indeed what we think it is
|
||||
pfatx_volume_metadata volume = static_cast<pfatx_volume_metadata>(InputBuffer);
|
||||
assert(InputBufferLength == sizeof(fatx_volume_metadata));
|
||||
g_io_mu_metadata->write(path[pos + 7], volume->offset, static_cast<const char *>(volume->buffer), volume->length);
|
||||
ret = xbox::status_success;
|
||||
}
|
||||
else {
|
||||
ret = status_invalid_handle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
switch (FsControlCode) {
|
||||
case 0x00090020: // FSCTL_DISMOUNT_VOLUME
|
||||
int partitionNumber = CxbxGetPartitionNumberFromHandle(FileHandle);
|
||||
if (partitionNumber > 0) {
|
||||
CxbxFormatPartitionByHandle(FileHandle);
|
||||
ret = xbox::status_success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_UNIMPLEMENTED();
|
||||
LOG_INCOMPLETE();
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
|
@ -1499,16 +1563,15 @@ XBSYSAPI EXPORTNUM(218) xbox::ntstatus_xt NTAPI xbox::NtQueryVolumeInformationFi
|
|||
|
||||
// FileFsSizeInformation is a special case that should read from our emulated partition table
|
||||
if ((DWORD)FileInformationClass == FileFsSizeInformation) {
|
||||
ntstatus_xt status;
|
||||
PFILE_FS_SIZE_INFORMATION XboxSizeInfo = (PFILE_FS_SIZE_INFORMATION)FileInformation;
|
||||
|
||||
// This might access the HDD or a MU, so we need to figure out the correct one first
|
||||
const std::wstring path = CxbxGetFinalPathNameByHandle(FileHandle);
|
||||
size_t pos = path.rfind(L"\\EmuDisk\\Partition");
|
||||
if (pos != std::string::npos) {
|
||||
// We are accessing a disk partition
|
||||
// This might access the HDD, a MU or the DVD drive, so we need to figure out the correct one first
|
||||
DeviceType type = CxbxrGetDeviceTypeFromHandle(FileHandle);
|
||||
if (type == DeviceType::Harddisk0) {
|
||||
|
||||
XboxPartitionTable partitionTable = CxbxGetPartitionTable();
|
||||
int partitionNumber = CxbxGetPartitionNumberFromPath(path);
|
||||
int partitionNumber = CxbxGetPartitionNumberFromHandle(FileHandle);
|
||||
FATX_SUPERBLOCK superBlock = CxbxGetFatXSuperBlock(partitionNumber);
|
||||
|
||||
XboxSizeInfo->BytesPerSector = 512;
|
||||
|
@ -1525,24 +1588,31 @@ XBSYSAPI EXPORTNUM(218) xbox::ntstatus_xt NTAPI xbox::NtQueryVolumeInformationFi
|
|||
XboxSizeInfo->TotalAllocationUnits.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBASize / XboxSizeInfo->SectorsPerAllocationUnit;
|
||||
XboxSizeInfo->AvailableAllocationUnits.QuadPart = partitionTable.TableEntries[partitionNumber - 1].LBASize / XboxSizeInfo->SectorsPerAllocationUnit;
|
||||
|
||||
RETURN(xbox::status_success);
|
||||
status = status_success;
|
||||
}
|
||||
|
||||
pos = path.rfind(L"\\EmuMu");
|
||||
if (pos != std::string::npos) {
|
||||
// We are accessing a MU
|
||||
else if (type == DeviceType::MU) {
|
||||
|
||||
XboxSizeInfo->BytesPerSector = 512;
|
||||
XboxSizeInfo->SectorsPerAllocationUnit = 32;
|
||||
XboxSizeInfo->TotalAllocationUnits.QuadPart = 512; // 8MB -> ((1024)^2 * 8) / (BytesPerSector * SectorsPerAllocationUnit)
|
||||
XboxSizeInfo->AvailableAllocationUnits.QuadPart = 512; // constant, so there's always free space available to write stuff
|
||||
|
||||
RETURN(xbox::status_success);
|
||||
status = status_success;
|
||||
}
|
||||
else if (type == DeviceType::Cdrom0) {
|
||||
|
||||
XboxSizeInfo->BytesPerSector = 2048;
|
||||
XboxSizeInfo->SectorsPerAllocationUnit = 1;
|
||||
XboxSizeInfo->TotalAllocationUnits.QuadPart = 3820880; // assuming DVD-9 (dual layer), redump reports a total size in bytes of 7825162240
|
||||
|
||||
status = status_success;
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "%s: Unrecongnized handle 0x%X with class FileFsSizeInformation.", __func__, FileHandle);
|
||||
status = status_invalid_handle;
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::WARNING, "%s: Unrecongnized handle 0x%X with class FileFsSizeInformation", __func__, FileHandle);
|
||||
|
||||
RETURN(xbox::status_invalid_handle);
|
||||
RETURN(status);
|
||||
}
|
||||
|
||||
// Get the required size for the host buffer
|
||||
|
|
|
@ -1509,15 +1509,21 @@ __declspec(noreturn) void CxbxKrnlInit
|
|||
CxbxRegisterDeviceHostPath(DeviceHarddisk0Partition7, CxbxBasePath + "Partition7");
|
||||
CxbxRegisterDeviceHostPath(DevicePrefix + "\\Chihiro", CxbxBasePath + "Chihiro");
|
||||
|
||||
// Create the MU directories
|
||||
CxbxRegisterDeviceHostPath(DeviceMU0, MuBasePath + "F");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU1, MuBasePath + "G");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU2, MuBasePath + "H");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU3, MuBasePath + "I");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU4, MuBasePath + "J");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU5, MuBasePath + "K");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU6, MuBasePath + "L");
|
||||
CxbxRegisterDeviceHostPath(DeviceMU7, MuBasePath + "M");
|
||||
// Create the MU directories and the bin files
|
||||
CxbxRegisterDeviceHostPath(DeviceMU0, MuBasePath + "F", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU1, MuBasePath + "G", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU2, MuBasePath + "H", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU3, MuBasePath + "I", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU4, MuBasePath + "J", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU5, MuBasePath + "K", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU6, MuBasePath + "L", false, sizeof(FATX_SUPERBLOCK));
|
||||
CxbxRegisterDeviceHostPath(DeviceMU7, MuBasePath + "M", false, sizeof(FATX_SUPERBLOCK));
|
||||
|
||||
std::mbstate_t ps = std::mbstate_t();
|
||||
const char *src = MuBasePath.c_str();
|
||||
std::wstring wMuBasePath(MuBasePath.size(), L'0');
|
||||
std::mbsrtowcs(wMuBasePath.data(), &src, wMuBasePath.size(), &ps);
|
||||
g_io_mu_metadata = new io_mu_metadata(wMuBasePath);
|
||||
|
||||
// Create default symbolic links :
|
||||
EmuLogInit(LOG_LEVEL::DEBUG, "Creating default symbolic links.");
|
||||
|
@ -1942,6 +1948,11 @@ void CxbxKrnlShutDown(bool is_reboot)
|
|||
// Shutdown the memory manager
|
||||
g_VMManager.Shutdown();
|
||||
|
||||
if (g_io_mu_metadata) {
|
||||
delete g_io_mu_metadata;
|
||||
g_io_mu_metadata = nullptr;
|
||||
}
|
||||
|
||||
// Shutdown the render manager
|
||||
if (g_renderbase != nullptr) {
|
||||
g_renderbase->Shutdown();
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cassert>
|
||||
#include <Shlobj.h>
|
||||
#include <Shlwapi.h>
|
||||
#pragma warning(disable:4005) // Ignore redefined status values
|
||||
#include <ntstatus.h>
|
||||
#pragma warning(default:4005)
|
||||
#include "core\kernel\init\CxbxKrnl.h"
|
||||
#include "Logging.h"
|
||||
#include "common/util/strConverter.hpp" // utf16_to_ascii
|
||||
#include "common/util/cliConfig.hpp"
|
||||
|
@ -84,7 +84,102 @@ XboxPartitionTable BackupPartTbl =
|
|||
}
|
||||
};
|
||||
|
||||
void CxbxCreatePartitionHeaderFile(std::string filename, bool partition0 = false)
|
||||
io_mu_metadata *g_io_mu_metadata = nullptr;
|
||||
|
||||
io_mu_metadata::io_mu_metadata(const std::wstring_view root_path) : m_root_path(root_path)
|
||||
{
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
m_buff[i] = new char[sizeof(FATX_SUPERBLOCK)];
|
||||
assert(m_buff[i] != nullptr);
|
||||
std::wstring path = m_root_path + static_cast<wchar_t>(L'F' + i) + L".bin";
|
||||
std::fstream fs(path, std::ios_base::in | std::ios_base::out | std::ios_base::binary);
|
||||
if (!fs.is_open()) {
|
||||
CxbxKrnlCleanup("%s: could not open MU bin file at \"%ls\"!", __func__, path.c_str());
|
||||
}
|
||||
fs.seekg(0);
|
||||
fs.read(m_buff[i], sizeof(FATX_SUPERBLOCK));
|
||||
// if the signature is not "fatx" or we read less bytes than expected, then we assume the bin file is either corrupted or
|
||||
// unformatted, so we reformat it now
|
||||
FATX_SUPERBLOCK *volume = reinterpret_cast<FATX_SUPERBLOCK *>(m_buff[i]);
|
||||
if ((fs.gcount() != sizeof(FATX_SUPERBLOCK)) || (volume->Signature != fatx_signature)) {
|
||||
volume->Signature = fatx_signature;
|
||||
volume->VolumeID = 0x11223344 + i;
|
||||
volume->ClusterSize = 32;
|
||||
volume->FatCopies = 1;
|
||||
std::memset(volume->Name, 0, mu_max_name_lenght);
|
||||
std::memset(volume->OnlineData, 0, fatx_online_data_length);
|
||||
std::memset(volume->Unused, 0xFF, fatx_reserved_length);
|
||||
fs.write(m_buff[i], sizeof(FATX_SUPERBLOCK));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io_mu_metadata::~io_mu_metadata()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lck(m_rw_lock);
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
std::wstring path = m_root_path + static_cast<wchar_t>(L'F' + i) + L".bin";
|
||||
std::ofstream ofs(path, std::ios_base::out | std::ios_base::binary);
|
||||
if (!ofs.is_open()) {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "%s: could not open MU bin file at \"%ls\"!", __func__, path.c_str());
|
||||
delete[] m_buff[i];
|
||||
continue;
|
||||
}
|
||||
ofs.seekp(0);
|
||||
ofs.write(m_buff[i], sizeof(FATX_SUPERBLOCK));
|
||||
delete[] m_buff[i];
|
||||
}
|
||||
}
|
||||
|
||||
void io_mu_metadata::read(const wchar_t lett, std::size_t offset, char *buff, std::size_t size)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lck(m_rw_lock); // allows for concurrent reads
|
||||
std::memcpy(buff, m_buff[lett - L'F'] + offset, size);
|
||||
}
|
||||
|
||||
void io_mu_metadata::write(const wchar_t lett, std::size_t offset, const char *buff, std::size_t size)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lck(m_rw_lock); // blocks when there is rw in progress
|
||||
std::memcpy(m_buff[lett - L'F'] + offset, buff, size);
|
||||
}
|
||||
|
||||
void io_mu_metadata::flush(const wchar_t lett)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lck(m_rw_lock);
|
||||
std::wstring path = m_root_path + lett + L".bin";
|
||||
std::ofstream ofs(path, std::ios_base::out | std::ios_base::binary);
|
||||
if (!ofs.is_open()) {
|
||||
EmuLog(LOG_LEVEL::ERROR2, "%s: could not open MU bin file at \"%ls\"!", __func__, path.c_str());
|
||||
return;
|
||||
}
|
||||
ofs.seekp(0);
|
||||
ofs.write(m_buff[lett - L'F'], sizeof(FATX_SUPERBLOCK));
|
||||
ofs.flush();
|
||||
}
|
||||
|
||||
DeviceType CxbxrGetDeviceTypeFromHandle(HANDLE hFile)
|
||||
{
|
||||
const std::wstring path = CxbxGetFinalPathNameByHandle(hFile);
|
||||
|
||||
size_t pos = path.rfind(L"\\EmuDisk\\Partition");
|
||||
if (pos != std::string::npos) {
|
||||
return DeviceType::Harddisk0;
|
||||
}
|
||||
|
||||
pos = path.rfind(L"\\EmuMu");
|
||||
if (pos != std::string::npos) {
|
||||
return DeviceType::MU;
|
||||
}
|
||||
|
||||
EmuNtSymbolicLinkObject *ret = FindNtSymbolicLinkObjectByDevice(DeviceCdrom0);
|
||||
if (ret != nullptr && path.rfind(ret->wHostSymbolicLinkPath) != std::string::npos) {
|
||||
return DeviceType::Cdrom0;
|
||||
}
|
||||
|
||||
return DeviceType::Invalid;
|
||||
}
|
||||
|
||||
void CxbxCreatePartitionHeaderFile(std::string filename, bool partition0 = false, std::size_t size = 512 * ONE_KB)
|
||||
{
|
||||
HANDLE hf = CreateFile(filename.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
if (!hf) {
|
||||
|
@ -98,7 +193,7 @@ void CxbxCreatePartitionHeaderFile(std::string filename, bool partition0 = false
|
|||
WriteFile(hf, &BackupPartTbl, sizeof(XboxPartitionTable), &NumberOfBytesWritten, 0);
|
||||
}
|
||||
|
||||
SetFilePointer(hf, 512 * ONE_KB, 0, FILE_BEGIN);
|
||||
SetFilePointer(hf, size, 0, FILE_BEGIN);
|
||||
SetEndOfFile(hf);
|
||||
CloseHandle(hf);
|
||||
}
|
||||
|
@ -701,7 +796,7 @@ std::string CxbxConvertXboxToHostPath(const std::string_view XboxDevicePath)
|
|||
return XbePath;
|
||||
}
|
||||
|
||||
int CxbxRegisterDeviceHostPath(const std::string_view XboxDevicePath, std::string HostDevicePath, bool IsFile)
|
||||
int CxbxRegisterDeviceHostPath(const std::string_view XboxDevicePath, std::string HostDevicePath, bool IsFile, std::size_t size)
|
||||
{
|
||||
XboxDevice newDevice;
|
||||
newDevice.XboxDevicePath = XboxDevicePath;
|
||||
|
@ -709,11 +804,12 @@ int CxbxRegisterDeviceHostPath(const std::string_view XboxDevicePath, std::strin
|
|||
|
||||
bool succeeded{ false };
|
||||
|
||||
// All HDD partitions have a .bin file to allow direct file io on the partition info
|
||||
if (_strnicmp(XboxDevicePath.data(), DeviceHarddisk0PartitionPrefix.c_str(), DeviceHarddisk0PartitionPrefix.length()) == 0) {
|
||||
// All HDD and MU partitions have a .bin file to allow direct file io on the partition info
|
||||
if (_strnicmp(XboxDevicePath.data(), DeviceHarddisk0PartitionPrefix.c_str(), DeviceHarddisk0PartitionPrefix.length()) == 0 ||
|
||||
_strnicmp(XboxDevicePath.data(), DeviceMU.c_str(), DeviceMU.length()) == 0) {
|
||||
std::string partitionHeaderPath = HostDevicePath + ".bin";
|
||||
if (!std::filesystem::exists(partitionHeaderPath)) {
|
||||
CxbxCreatePartitionHeaderFile(partitionHeaderPath, XboxDevicePath == DeviceHarddisk0Partition0);
|
||||
CxbxCreatePartitionHeaderFile(partitionHeaderPath, XboxDevicePath == DeviceHarddisk0Partition0, size);
|
||||
}
|
||||
|
||||
succeeded = true;
|
||||
|
@ -833,6 +929,10 @@ NTSTATUS EmuNtSymbolicLinkObject::Init(std::string aSymbolicLinkName, std::strin
|
|||
}
|
||||
else
|
||||
{
|
||||
std::mbstate_t ps = std::mbstate_t();
|
||||
const char *src = HostSymbolicLinkPath.c_str();
|
||||
wHostSymbolicLinkPath.resize(HostSymbolicLinkPath.size());
|
||||
std::mbsrtowcs(wHostSymbolicLinkPath.data(), &src, wHostSymbolicLinkPath.size(), &ps);
|
||||
NtSymbolicLinkObjects[DriveLetter - 'A'] = this;
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Linked \"%s\" to \"%s\" (residing at \"%s\")", aSymbolicLinkName.c_str(), aFullPath.c_str(), HostSymbolicLinkPath.c_str());
|
||||
}
|
||||
|
@ -918,6 +1018,19 @@ EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(const HANDLE Handl
|
|||
}
|
||||
|
||||
|
||||
EmuNtSymbolicLinkObject *FindNtSymbolicLinkObjectByDevice(const std::string_view Device)
|
||||
{
|
||||
for (char DriveLetter = 'A'; DriveLetter <= 'Z'; DriveLetter++)
|
||||
{
|
||||
EmuNtSymbolicLinkObject *result = NtSymbolicLinkObjects[DriveLetter - 'A'];
|
||||
if ((result != nullptr) && (result->XboxSymbolicLinkPath == Device))
|
||||
return result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void _CxbxPVOIDDeleter(PVOID *ptr)
|
||||
{
|
||||
if (*ptr) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
|
||||
#include <core\kernel\exports\xboxkrnl.h>
|
||||
#include "core\kernel\init\CxbxKrnl.h"
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
@ -106,6 +107,18 @@ extern const std::string DeviceMU6;
|
|||
extern const std::string DeviceMU7;
|
||||
constexpr char CxbxAutoMountDriveLetter = 'D';
|
||||
|
||||
enum class DeviceType : int {
|
||||
Invalid = -1,
|
||||
Cdrom0,
|
||||
Harddisk0,
|
||||
MU,
|
||||
};
|
||||
|
||||
inline constexpr xbox::ulong_xt fsctl_dismount_volume = 0x00090020;
|
||||
inline constexpr xbox::ulong_xt fsctl_read_fatx_metadata = 0x0009411C;
|
||||
inline constexpr xbox::ulong_xt fsctl_write_fatx_metadata = 0x00098120;
|
||||
|
||||
inline constexpr std::size_t mu_max_name_lenght = 32 * sizeof(xbox::wchar_xt); // MU names are in wide chars
|
||||
extern std::string CxbxBasePath;
|
||||
extern HANDLE CxbxBasePathHandle;
|
||||
|
||||
|
@ -218,6 +231,7 @@ public:
|
|||
bool IsHostBasedPath;
|
||||
std::string XboxSymbolicLinkPath;
|
||||
std::string HostSymbolicLinkPath;
|
||||
std::wstring wHostSymbolicLinkPath;
|
||||
HANDLE RootDirectoryHandle;
|
||||
NTSTATUS Init(std::string aSymbolicLinkName, std::string aFullPath);
|
||||
~EmuNtSymbolicLinkObject();
|
||||
|
@ -235,9 +249,31 @@ struct EmuDirPath {
|
|||
HANDLE HostDirHandle;
|
||||
};
|
||||
|
||||
typedef struct _fatx_volume_metadata {
|
||||
xbox::dword_xt offset;
|
||||
xbox::dword_xt length;
|
||||
xbox::PVOID buffer;
|
||||
} fatx_volume_metadata, *pfatx_volume_metadata;
|
||||
|
||||
CHAR* NtStatusToString(IN NTSTATUS Status);
|
||||
|
||||
int CxbxRegisterDeviceHostPath(std::string_view XboxFullPath, std::string HostDevicePath, bool IsFile = false);
|
||||
class io_mu_metadata
|
||||
{
|
||||
public:
|
||||
io_mu_metadata(const std::wstring_view root_path);
|
||||
~io_mu_metadata();
|
||||
void read(const wchar_t lett, std::size_t offset, char *buff, std::size_t size);
|
||||
void write(const wchar_t lett, std::size_t offset, const char *buff, std::size_t size);
|
||||
void flush(const wchar_t lett);
|
||||
|
||||
private:
|
||||
char *m_buff[8];
|
||||
const std::wstring m_root_path;
|
||||
std::shared_mutex m_rw_lock;
|
||||
};
|
||||
extern io_mu_metadata *g_io_mu_metadata;
|
||||
|
||||
int CxbxRegisterDeviceHostPath(std::string_view XboxFullPath, std::string HostDevicePath, bool IsFile = false, std::size_t size = 512 * ONE_KB);
|
||||
int CxbxDeviceIndexByDevicePath(const char *XboxDevicePath);
|
||||
XboxDevice* CxbxDeviceByDevicePath(const std::string_view XboxDevicePath);
|
||||
XboxDevice* CxbxDeviceByHostPath(const std::string_view HostPath);
|
||||
|
@ -248,6 +284,8 @@ EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByDriveLetter(const char DriveL
|
|||
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByName(std::string SymbolicLinkName);
|
||||
void FindEmuDirPathByDevice(std::string DeviceName, EmuDirPath& hybrid_path);
|
||||
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(HANDLE Handle);
|
||||
EmuNtSymbolicLinkObject *FindNtSymbolicLinkObjectByDevice(const std::string_view Device);
|
||||
DeviceType CxbxrGetDeviceTypeFromHandle(HANDLE hFile);
|
||||
void CleanupSymbolicLinks();
|
||||
|
||||
HANDLE CxbxGetDeviceNativeRootHandle(std::string XboxFullPath);
|
||||
|
@ -314,16 +352,25 @@ typedef struct
|
|||
XboxPartitionTableEntry TableEntries[14];
|
||||
} XboxPartitionTable;
|
||||
|
||||
inline constexpr xbox::ulong_xt fatx_name_length = 32;
|
||||
inline constexpr xbox::ulong_xt fatx_online_data_length = 2048;
|
||||
inline constexpr xbox::ulong_xt fatx_reserved_length = 1968;
|
||||
|
||||
inline constexpr xbox::ulong_xt fatx_signature = 'XTAF';
|
||||
|
||||
typedef struct _FATX_SUPERBLOCK
|
||||
{
|
||||
char Tag[4];
|
||||
unsigned int VolumeID;
|
||||
unsigned int ClusterSize;
|
||||
USHORT FatCopies;
|
||||
int Resvd;
|
||||
char Unused[4078];
|
||||
xbox::ulong_xt Signature;
|
||||
xbox::ulong_xt VolumeID;
|
||||
xbox::ulong_xt ClusterSize;
|
||||
xbox::ulong_xt FatCopies;
|
||||
xbox::wchar_xt Name[fatx_name_length];
|
||||
xbox::uchar_xt OnlineData[fatx_online_data_length];
|
||||
xbox::uchar_xt Unused[fatx_reserved_length];
|
||||
} FATX_SUPERBLOCK;
|
||||
|
||||
static_assert(sizeof(FATX_SUPERBLOCK) == PAGE_SIZE);
|
||||
|
||||
XboxPartitionTable CxbxGetPartitionTable();
|
||||
FATX_SUPERBLOCK CxbxGetFatXSuperBlock(int partitionNumber);
|
||||
int CxbxGetPartitionNumberFromHandle(HANDLE hFile);
|
||||
|
|
|
@ -88,6 +88,14 @@ void DukeInputWindow::Initialize(HWND hwnd, int port_num, int dev_type)
|
|||
|
||||
if (m_dev_type == to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK)) {
|
||||
// The arcade joystick does not have slot ports so we always disable the corresponding options
|
||||
LRESULT index_top = SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_ADDSTRING, 0,
|
||||
reinterpret_cast<LPARAM>(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)).c_str()));
|
||||
LRESULT index_bottom = SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_ADDSTRING, 0,
|
||||
reinterpret_cast<LPARAM>(GetInputDeviceName(to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)).c_str()));
|
||||
SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_SETITEMDATA, index_top, to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID));
|
||||
SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_SETITEMDATA, index_bottom, to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID));
|
||||
SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_SETCURSEL, index_top, 0);
|
||||
SendMessage(m_hwnd_slot_list[SLOT_BOTTOM], CB_SETCURSEL, index_bottom, 0);
|
||||
EnableWindow(m_hwnd_slot_list[SLOT_TOP], FALSE);
|
||||
EnableWindow(m_hwnd_slot_list[SLOT_BOTTOM], FALSE);
|
||||
}
|
||||
|
@ -248,24 +256,6 @@ void DukeInputWindow::DetectOutput(int ms)
|
|||
}
|
||||
}
|
||||
|
||||
int DukeInputWindow::IsProfileSaved()
|
||||
{
|
||||
if (int ret = InputWindow::IsProfileSaved()) {
|
||||
if (ret == EXIT_IGNORE) {
|
||||
return EXIT_IGNORE;
|
||||
}
|
||||
else {
|
||||
if (m_dev_type != to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK)) {
|
||||
SaveSlotConfig();
|
||||
}
|
||||
|
||||
return EXIT_SAVE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_ABORT;
|
||||
}
|
||||
|
||||
void DukeInputWindow::SaveSlotConfig()
|
||||
{
|
||||
int DeviceType = SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_GETITEMDATA, SendMessage(m_hwnd_slot_list[SLOT_TOP], CB_GETCURSEL, 0, 0), 0);
|
||||
|
|
Loading…
Reference in New Issue