diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.cc index 43b87e01a..abee49775 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.cc @@ -26,11 +26,74 @@ namespace kernel { namespace xboxkrnl { -// SHIM_CALL ExGetXConfigSetting_shim( -// xe_ppc_state_t* ppc_state, KernelState* state) { -// // ? -// SHIM_SET_RETURN(0); -// } +X_STATUS xeExGetXConfigSetting( + uint16_t category, uint16_t setting, void* buffer, uint16_t buffer_size, + uint16_t* required_size) { + uint16_t setting_size = 0; + uint32_t value = 0; + + // TODO(benvanik): have real structs here that just get copied from. + // http://free60.org/XConfig + switch (category) { + case 0x0003: + // XCONFIG_USER_CATEGORY + switch (setting) { + case 0x000A: + // VideoFlags + setting_size = 4; + value = 0x00040000; + break; + default: + XEASSERTALWAYS(); + return X_STATUS_INVALID_PARAMETER_2; + } + break; + default: + XEASSERTALWAYS(); + return X_STATUS_INVALID_PARAMETER_1; + } + + if (buffer_size < setting_size) { + return X_STATUS_BUFFER_TOO_SMALL; + } + if (!buffer && buffer_size) { + return X_STATUS_INVALID_PARAMETER_3; + } + + if (buffer) { + XESETUINT32BE(buffer, value); + } + if (required_size) { + *required_size = setting_size; + } + + return X_STATUS_SUCCESS; +} + + +SHIM_CALL ExGetXConfigSetting_shim( + xe_ppc_state_t* ppc_state, KernelState* state) { + uint16_t category = SHIM_GET_ARG_16(0); + uint16_t setting = SHIM_GET_ARG_16(1); + uint32_t buffer_ptr = SHIM_GET_ARG_32(2); + uint16_t buffer_size = SHIM_GET_ARG_16(3); + uint32_t required_size_ptr = SHIM_GET_ARG_32(4); + + XELOGD( + "ExGetXConfigSetting(%.4X, %.4X, %.8X, %.4X, %.8X)", + category, setting, buffer_ptr, buffer_size, required_size_ptr); + + void* buffer = buffer_ptr ? SHIM_MEM_ADDR(buffer_ptr) : NULL; + uint16_t required_size = 0; + X_STATUS result = xeExGetXConfigSetting( + category, setting, buffer, buffer_size, &required_size); + + if (required_size_ptr) { + SHIM_SET_MEM_16(required_size_ptr, required_size); + } + + SHIM_SET_RETURN(result); +} int xeXexCheckExecutablePriviledge(uint32_t privilege) { @@ -134,7 +197,7 @@ SHIM_CALL XexGetModuleHandle_shim( void xe::kernel::xboxkrnl::RegisterModuleExports( ExportResolver* export_resolver, KernelState* state) { - // SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state); + SHIM_SET_MAPPING("xboxkrnl.exe", ExGetXConfigSetting, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state); diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.h b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.h index ed71dd097..8e561fcec 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.h +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_module.h @@ -20,6 +20,9 @@ namespace xe { namespace kernel { namespace xboxkrnl { +X_STATUS xeExGetXConfigSetting( + uint16_t category, uint16_t setting, void* buffer, uint16_t buffer_size, + uint16_t* required_size); int xeXexCheckExecutablePriviledge(uint32_t privilege); diff --git a/src/xenia/kernel/shim_utils.h b/src/xenia/kernel/shim_utils.h index 81f26ffc9..24fc220b9 100644 --- a/src/xenia/kernel/shim_utils.h +++ b/src/xenia/kernel/shim_utils.h @@ -39,11 +39,13 @@ namespace kernel { #define SHIM_SET_MEM_32(a, v) (*(uint32_t*)SHIM_MEM_ADDR(a)) = XESWAP32(v) #define SHIM_SET_MEM_64(a, v) (*(uint64_t*)SHIM_MEM_ADDR(a)) = XESWAP64(v) +#define SHIM_GPR_16(n) (uint16_t)(ppc_state->r[n]) #define SHIM_GPR_32(n) (uint32_t)(ppc_state->r[n]) #define SHIM_SET_GPR_32(n, v) ppc_state->r[n] = (uint64_t)((v) & UINT32_MAX) #define SHIM_GPR_64(n) ppc_state->r[n] #define SHIM_SET_GPR_64(n, v) ppc_state->r[n] = (uint64_t)(v) +#define SHIM_GET_ARG_16(n) SHIM_GPR_16(3 + n) #define SHIM_GET_ARG_32(n) SHIM_GPR_32(3 + n) #define SHIM_GET_ARG_64(n) SHIM_GPR_64(3 + n) #define SHIM_SET_RETURN(v) SHIM_SET_GPR_64(3, v) diff --git a/src/xenia/kernel/xbox.h b/src/xenia/kernel/xbox.h index 9cf21c425..49bd92b08 100644 --- a/src/xenia/kernel/xbox.h +++ b/src/xenia/kernel/xbox.h @@ -42,6 +42,9 @@ typedef uint32_t X_STATUS; #define X_STATUS_OBJECT_TYPE_MISMATCH ((uint32_t)0xC0000024L) #define X_STATUS_INVALID_PAGE_PROTECTION ((uint32_t)0xC0000045L) #define X_STATUS_MEMORY_NOT_ALLOCATED ((uint32_t)0xC00000A0L) +#define X_STATUS_INVALID_PARAMETER_1 ((uint32_t)0xC00000EFL) +#define X_STATUS_INVALID_PARAMETER_2 ((uint32_t)0xC00000F0L) +#define X_STATUS_INVALID_PARAMETER_3 ((uint32_t)0xC00000F1L) // MEM_*, used by NtAllocateVirtualMemory