diff --git a/src/core/kernel/common/types.h b/src/core/kernel/common/types.h index 294bfc96b..da159c68c 100644 --- a/src/core/kernel/common/types.h +++ b/src/core/kernel/common/types.h @@ -2081,6 +2081,11 @@ typedef enum _XC_VALUE_INDEX } XC_VALUE_INDEX, *PXC_VALUE_INDEX; +#define XBOX_HW_FLAG_INTERNAL_USB_HUB 0x00000001 +#define XBOX_HW_FLAG_DEVKIT_KERNEL 0x00000002 +#define XBOX_480P_MACROVISION_ENABLED 0x00000004 +#define XBOX_HW_FLAG_ARCADE 0x00000008 + // ****************************************************************** // * XBOX_HARDWARE_INFO // ****************************************************************** diff --git a/src/core/kernel/exports/EmuKrnlXbox.cpp b/src/core/kernel/exports/EmuKrnlXbox.cpp index 12bd8a8e0..17756295a 100644 --- a/src/core/kernel/exports/EmuKrnlXbox.cpp +++ b/src/core/kernel/exports/EmuKrnlXbox.cpp @@ -41,13 +41,19 @@ XBSYSAPI EXPORTNUM(321) xbox::XBOX_KEY_DATA xbox::XboxEEPROMKey = { 0 }; // ****************************************************************** // * 0x0142 - XboxHardwareInfo // ****************************************************************** +// TODO: The main goal is to completely unset custom init values and have +// them set from kernel's initialization end and device classes. +// Although, device classes does not really set this value but read +// from PCI space for Gpu rev, Mcp rev, and possibility INTERNAL_USB flag. XBSYSAPI EXPORTNUM(322) xbox::XBOX_HARDWARE_INFO xbox::XboxHardwareInfo = { - 0xC0000031, // Flags: 1=INTERNAL_USB, 2=DEVKIT, 4=MACROVISION, 8=CHIHIRO - 0xA2, // GpuRevision, byte read from NV2A first register, at 0xFD0000000 - see NV_PMC_BOOT_0 - 0xD3, // McpRevision, Retail 1.6 - see https://github.com/JayFoxRox/xqemu-jfr/wiki/MCPX-and-bootloader - 0, // unknown - 0 // unknown + // TODO: What exactly 0xC0000030 flags are? Might need default to null then set them later properly. + // NOTE: Will be set by src/devices/Xbox.cpp and maybe other file(s)... + .Flags = 0xC0000030, // Flags: 1=INTERNAL_USB, 2=DEVKIT, 4=MACROVISION, 8=CHIHIRO + .GpuRevision = 0xD3, // GpuRevision, byte read from NV2A first register, at 0xFD0000000 - see NV_PMC_BOOT_0 + .McpRevision = 0, // NOTE: Will be set by src/devices/Xbox.cpp file. + .Unknown3 = 0, // unknown + .Unknown4 = 0 // unknown }; // ****************************************************************** diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 3643381af..d0447f83b 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -542,7 +542,10 @@ static void CxbxrKrnlSetupMemorySystem(int BootFlags, unsigned emulate_system, u } } -static bool CxbxrKrnlXbeSystemSelector(int BootFlags, unsigned& reserved_systems, blocks_reserved_t blocks_reserved) +static bool CxbxrKrnlXbeSystemSelector(int BootFlags, + unsigned& reserved_systems, + blocks_reserved_t blocks_reserved, + HardwareModel &hardwareModel) { unsigned int emulate_system = 0; // Get title path : @@ -717,6 +720,17 @@ static bool CxbxrKrnlXbeSystemSelector(int BootFlags, unsigned& reserved_systems g_bIsChihiro = (emulate_system == SYSTEM_CHIHIRO); g_bIsDevKit = (emulate_system == SYSTEM_DEVKIT); g_bIsRetail = (emulate_system == SYSTEM_XBOX); + if (g_bIsChihiro) { + hardwareModel = HardwareModel::Chihiro_Type1; // TODO: Make configurable to support Type-3 console. + } + else if (g_bIsDevKit) { + hardwareModel = HardwareModel::DebugKit_r1_2; // Unlikely need to make configurable. + } + // Retail (default) + else { + // Should not be configurable. Otherwise, titles compiled with newer XDK will patch older xbox kernel. + hardwareModel = HardwareModel::Revision1_6; + } #ifdef CHIHIRO_WORK // If this is a Chihiro title, we need to patch the init flags to disable HDD setup @@ -934,7 +948,8 @@ static bool CxbxrKrnlPrepareXbeMap() Xbe::Header* XbeHeader, uint32_t XbeHeaderSize, void (*Entry)(), - int BootFlags + int BootFlags, + HardwareModel hardwareModel ); void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_reserved) @@ -1088,7 +1103,8 @@ void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_res // using XeLoadImage from LaunchDataPage->Header.szLaunchPath // Now we can load the XBE : - if (!CxbxrKrnlXbeSystemSelector(BootFlags, reserved_systems, blocks_reserved)) { + HardwareModel hardwareModel = HardwareModel::Revision1_6; // It is configured by CxbxrKrnlXbeSystemSelector function according to console type. + if (!CxbxrKrnlXbeSystemSelector(BootFlags, reserved_systems, blocks_reserved, hardwareModel)) { return; } @@ -1116,7 +1132,8 @@ void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_res (Xbe::Header*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, CxbxKrnl_Xbe->m_Header.dwSizeofHeaders, (void(*)())EntryPoint, - BootFlags + BootFlags, + hardwareModel ); } @@ -1178,7 +1195,8 @@ static void CxbxrKrnlInitHacks() Xbe::Header *pXbeHeader, uint32_t dwXbeHeaderSize, void(*Entry)(), - int BootFlags) + int BootFlags, + HardwareModel hardwareModel) { unsigned Host2XbStackBaseReserved = 0; __asm mov Host2XbStackBaseReserved, esp; @@ -1383,7 +1401,7 @@ static void CxbxrKrnlInitHacks() SetupXboxDeviceTypes(); } - InitXboxHardware(HardwareModel::Revision1_5); // TODO : Make configurable + InitXboxHardware(hardwareModel); // Read Xbox video mode from the SMC, store it in HalBootSMCVideoMode xbox::HalReadSMBusValue(SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER, SMC_COMMAND_AV_PACK, FALSE, (xbox::PULONG)&xbox::HalBootSMCVideoMode); diff --git a/src/devices/SMCDevice.cpp b/src/devices/SMCDevice.cpp index 7dbfb8eaf..189621adc 100644 --- a/src/devices/SMCDevice.cpp +++ b/src/devices/SMCDevice.cpp @@ -91,10 +91,13 @@ uint8_t SMCDevice::ReadByte(uint8_t command) // See https://xboxdevwiki.net/PIC#PIC_version_string switch (m_revision) { case SCMRevision::P01: buffer[1] = "P01"[m_PICVersionStringIndex]; break; - case SCMRevision::P2L: buffer[1] = "P05"[m_PICVersionStringIndex]; break; // ?? + case SCMRevision::P05: buffer[1] = "P05"[m_PICVersionStringIndex]; break; + case SCMRevision::P11: buffer[1] = "P11"[m_PICVersionStringIndex]; break; + case SCMRevision::P2L: buffer[1] = "P2L"[m_PICVersionStringIndex]; break; case SCMRevision::D01: buffer[1] = "DXB"[m_PICVersionStringIndex]; break; case SCMRevision::D05: buffer[1] = "D05"[m_PICVersionStringIndex]; break; // ?? - // default: UNREACHABLE(m_revision); + case SCMRevision::B11: buffer[1] = "B11"[m_PICVersionStringIndex]; break; // ?? + default: CxbxrAbort("Unknown PIC revision: %d", m_revision); } m_PICVersionStringIndex = (m_PICVersionStringIndex + 1) % 3; diff --git a/src/devices/SMCDevice.h b/src/devices/SMCDevice.h index 6c1b6bed2..7e36ab525 100644 --- a/src/devices/SMCDevice.h +++ b/src/devices/SMCDevice.h @@ -93,10 +93,14 @@ typedef enum { // https://xboxdevwiki.net/System_Management_Controller + // https://xboxdevwiki.net/Xboxen_Info P01, + P05, + P11, P2L, D01, // Seen in a debug kit D05, // Seen in a earlier model chihiro + B11, } SCMRevision; class SMCDevice : public SMDevice { diff --git a/src/devices/Xbox.cpp b/src/devices/Xbox.cpp index 68b21371e..3d81343db 100644 --- a/src/devices/Xbox.cpp +++ b/src/devices/Xbox.cpp @@ -25,8 +25,12 @@ // * // ****************************************************************** +#define LOG_PREFIX CXBXR_MODULE::XBOX + #include "Xbox.h" // For HardwareModel #include "common\xbe\Xbe.h" // Without this HLEIntercept complains about some undefined xbe variables +#include "core\kernel\common\xbox.h" +#include "cxbxr.hpp" #include "core\hle\Intercept.hpp" PCIBus* g_PCIBus; @@ -41,66 +45,82 @@ USBDevice* g_USB0; MCPXRevision MCPXRevisionFromHardwareModel(HardwareModel hardwareModel) { - switch (hardwareModel) { - case Revision1_0: - case Revision1_1: - case Revision1_2: - case Revision1_3: - case Revision1_4: - case Revision1_5: - case Revision1_6: + // https://xboxdevwiki.net/Xboxen_Info + switch (GET_HW_CONSOLE(hardwareModel)) { + case Retail: return MCPXRevision::MCPX_X3; case DebugKit: - // EmuLog(LOG_LEVEL::WARNING, "Guessing MCPXVersion"); + case Chihiro: return MCPXRevision::MCPX_X2; default: - // UNREACHABLE(hardwareModel); - return MCPXRevision::MCPX_X3; + CxbxrAbort("MCPXRevisionFromHardwareModel: Unknown conversion for hardware model (0x%02X)", hardwareModel); } } SCMRevision SCMRevisionFromHardwareModel(HardwareModel hardwareModel) { + // https://xboxdevwiki.net/Xboxen_Info switch (hardwareModel) { case Revision1_0: - return SCMRevision::P01; // Our SCM returns PIC version string "P01" + return SCMRevision::P01; case Revision1_1: + return SCMRevision::P05; case Revision1_2: case Revision1_3: case Revision1_4: + return SCMRevision::P11; case Revision1_5: case Revision1_6: - // EmuLog(LOG_LEVEL::WARNING, "Guessing SCMRevision"); - return SCMRevision::P2L; // Assumption; Our SCM returns PIC version string "P05" - case DebugKit: - return SCMRevision::D01; // Our SCM returns PIC version string "DXB" - default: - // UNREACHABLE(hardwareModel); return SCMRevision::P2L; + case DebugKit: + return SCMRevision::D01; + case Chihiro_Type1: + return SCMRevision::D05; + case DebugKit_r1_2: + case Chihiro_Type3: + return SCMRevision::B11; + default: + CxbxrAbort("SCMRevisionFromHardwareModel: Unknown conversion for hardware model (0x%02X)", hardwareModel); } } TVEncoder TVEncoderFromHardwareModel(HardwareModel hardwareModel) { - switch (hardwareModel) { + // https://xboxdevwiki.net/Xboxen_Info + // LukeUsher : My debug kit and at least most of them (maybe all?) + // are equivalent to v1.0 and have Conexant encoders. + switch (GET_HW_REVISION(hardwareModel)) { case Revision1_0: case Revision1_1: case Revision1_2: case Revision1_3: return TVEncoder::Conexant; case Revision1_4: + case Revision1_5: // Assumption return TVEncoder::Focus; - case Revision1_5: - return TVEncoder::Focus; // Assumption case Revision1_6: return TVEncoder::XCalibur; - case DebugKit: - // LukeUsher : My debug kit and at least most of them (maybe all?) - // are equivalent to v1.0 and have Conexant encoders. - return TVEncoder::Conexant; - default: - // UNREACHABLE(hardwareModel); - return TVEncoder::Focus; + default: + CxbxrAbort("TVEncoderFromHardwareModel: Unknown conversion for hardware model (0x%02X)", hardwareModel); + } +} + +xbox::uchar_xt MCP_PCIRevisionFromHardwareModel(HardwareModel hardwareModel) +{ + // https://xboxdevwiki.net/Xboxen_Info + switch (GET_HW_REVISION(hardwareModel)) { + case Revision1_0: + return 0xB2; + case Revision1_1: + case Revision1_2: + case Revision1_3: + case Revision1_4: + case Revision1_5: // Assumption + return 0xD4; + case Revision1_6: + return 0xD5; + default: + CxbxrAbort("MCP_PCIRevisionFromHardwareModel: Unknown conversion for hardware model (0x%02X)", hardwareModel); } } @@ -111,16 +131,29 @@ void InitXboxHardware(HardwareModel hardwareModel) SCMRevision smc_revision = SCMRevisionFromHardwareModel(hardwareModel); TVEncoder tv_encoder = TVEncoderFromHardwareModel(hardwareModel); + // Only Xbox 1.0 has usb daughterboard supplied, later revisions are integrated onto motherboard. + if (GET_HW_REVISION(hardwareModel) == HardwareModel::Revision1_0) { + xbox::XboxHardwareInfo.Flags |= XBOX_HW_FLAG_INTERNAL_USB_HUB; + } + // Set the special type of consoles according to xbox kernel designed respectively. + if (IS_DEVKIT(hardwareModel)) { + xbox::XboxHardwareInfo.Flags |= XBOX_HW_FLAG_DEVKIT_KERNEL; + } + else if (IS_CHIHIRO(hardwareModel)) { + xbox::XboxHardwareInfo.Flags |= XBOX_HW_FLAG_ARCADE; + } + + xbox::XboxHardwareInfo.McpRevision = MCP_PCIRevisionFromHardwareModel(hardwareModel); + // Create busses g_PCIBus = new PCIBus(); g_SMBus = new SMBus(); // Create devices g_MCPX = new MCPXDevice(mcpx_revision); - - g_SMC = new SMCDevice(smc_revision, g_bIsChihiro ? 6 : 1); // 6 = AV_PACK_STANDARD, 1 = AV_PACK_HDTV. Chihiro doesn't support HDTV! - // SMC uses different AV_PACK values than the Kernel - // See https://xboxdevwiki.net/PIC#The_AV_Pack + g_SMC = new SMCDevice(smc_revision, IS_CHIHIRO(hardwareModel) ? 6 : 1); // 6 = AV_PACK_STANDARD, 1 = AV_PACK_HDTV. Chihiro doesn't support HDTV! + // SMC uses different AV_PACK values than the Kernel + // See https://xboxdevwiki.net/PIC#The_AV_Pack g_EEPROM = new EEPROMDevice(); g_NVNet = new NVNetDevice(); g_NV2A = new NV2ADevice(); diff --git a/src/devices/Xbox.h b/src/devices/Xbox.h index 46a9ca650..22a426ca5 100644 --- a/src/devices/Xbox.h +++ b/src/devices/Xbox.h @@ -53,9 +53,21 @@ typedef enum { Revision1_4, Revision1_5, Revision1_6, - DebugKit + Retail = 0x00, + // We don't need include revison 1.0 to 1.6 here, use above revision range instead. + DebugKit = 0x10, // TODO: Since there are 1.0/1.1/1.2 revisions. For now, let's go with 1.2 by default. + DebugKit_r1_2 = DebugKit | Revision1_2, + Chihiro = 0x20, + Chihiro_Type1 = Chihiro | Revision1_1, + Chihiro_Type3 = Chihiro | Revision1_2, // TODO: Need verify on Chihiro hw, it is currently base on (B11) Debug Kit list. } HardwareModel; +#define GET_HW_REVISION(hardwareModel) (hardwareModel & 0x0F) +#define GET_HW_CONSOLE(hardwareModel) (hardwareModel & 0xF0) +#define IS_RETAIL(hardwareModel) (GET_HW_CONSOLE(hardwareModel) == Retail) +#define IS_DEVKIT(hardwareModel) (GET_HW_CONSOLE(hardwareModel) == DebugKit) +#define IS_CHIHIRO(hardwareModel) (GET_HW_CONSOLE(hardwareModel) == Chihiro) + typedef enum { // TODO : Move to it's own file // https://xboxdevwiki.net/Hardware_Revisions#Video_encoder Conexant,