Merge pull request #814 from LukeUsher/avmode-fixes
Properly implement D3DDevice_GetDisplayFieldStatus patch
This commit is contained in:
commit
edae7898f7
|
@ -121,18 +121,29 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
|
||||||
|
|
||||||
// TODO : Verify checksums
|
// TODO : Verify checksums
|
||||||
|
|
||||||
|
// Check for (and fix) invalid fields that were set by previous versions of Cxbx-Reloaded
|
||||||
|
// Without this, all users would have to delete their EEPROM.bin
|
||||||
|
// The issue was that the AV_FLAG_XXhz was set in the wrong field, we fix it by
|
||||||
|
// resetting FactorySettings.AVRegion and setting user video flags to the default
|
||||||
|
// The user can then set their desired settings using the Xbox Dashboard
|
||||||
|
if (pEEPROM->FactorySettings.AVRegion == AV_STANDARD_NTSC_M) {
|
||||||
|
DbgPrintf("INIT: Repairing bad EEPROM (from previous Cxbx-Reloaded builds)\n");
|
||||||
|
pEEPROM->UserSettings.VideoFlags = 0;
|
||||||
|
pEEPROM->FactorySettings.AVRegion = AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
|
||||||
|
}
|
||||||
|
|
||||||
if (NeedsInitialization)
|
if (NeedsInitialization)
|
||||||
{
|
{
|
||||||
memset(pEEPROM, 0, EEPROM_SIZE);
|
memset(pEEPROM, 0, EEPROM_SIZE);
|
||||||
|
|
||||||
// TODO: Make these configurable or autodetect of some sort :
|
// TODO: Make these configurable or autodetect of some sort :
|
||||||
pEEPROM->UserSettings.Language = 0x01; // = English
|
pEEPROM->UserSettings.Language = 0x01; // = English
|
||||||
pEEPROM->UserSettings.VideoFlags = (AV_FLAGS_LETTERBOX | AV_FLAGS_60Hz) >> AV_USER_FLAGS_SHIFT; // = Letterbox
|
pEEPROM->UserSettings.VideoFlags = 0; // = Use XDK defaults
|
||||||
pEEPROM->UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
|
pEEPROM->UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
|
||||||
pEEPROM->UserSettings.ParentalControlGames = 0; // = XC_PC_ESRB_ALL
|
pEEPROM->UserSettings.ParentalControlGames = 0; // = XC_PC_ESRB_ALL
|
||||||
pEEPROM->UserSettings.ParentalControlMovies = 0; // = XC_PC_ESRB_ALL
|
pEEPROM->UserSettings.ParentalControlMovies = 0; // = XC_PC_ESRB_ALL
|
||||||
pEEPROM->UserSettings.MiscFlags = 0; // No automatic power down
|
pEEPROM->UserSettings.MiscFlags = 0; // No automatic power down
|
||||||
pEEPROM->FactorySettings.AVRegion = AV_STANDARD_NTSC_M; // = 0x100 = NTSC_M
|
pEEPROM->FactorySettings.AVRegion = AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
|
||||||
|
|
||||||
XboxFactoryGameRegion = 1; // = North America - TODO : This should be derived from EncryptedSection somehow
|
XboxFactoryGameRegion = 1; // = North America - TODO : This should be derived from EncryptedSection somehow
|
||||||
|
|
||||||
|
|
|
@ -2494,18 +2494,38 @@ HRESULT WINAPI XTL::EMUPATCH(D3D_CheckDeviceFormat)
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
VOID WINAPI XTL::EMUPATCH(D3DDevice_GetDisplayFieldStatus)(X_D3DFIELD_STATUS *pFieldStatus)
|
VOID WINAPI XTL::EMUPATCH(D3DDevice_GetDisplayFieldStatus)(X_D3DFIELD_STATUS *pFieldStatus)
|
||||||
{
|
{
|
||||||
//FUNC_EXPORTS
|
// NOTE: This can be unpatched only when NV2A does it's own VBlank and HLE _Swap function is unpatched
|
||||||
|
FUNC_EXPORTS
|
||||||
|
|
||||||
LOG_FUNC_ONE_ARG(pFieldStatus);
|
LOG_FUNC_ONE_ARG(pFieldStatus);
|
||||||
|
|
||||||
// TODO: Read AV Flags to determine if Progressive or Interlaced
|
// Read AV Flags to determine if Progressive or Interlaced
|
||||||
#if 1
|
// The xbox does this by reading from pDevice->m_Miniport.m_CurrentAvInfo
|
||||||
pFieldStatus->Field = (g_VBData.VBlank%2 == 0) ? X_D3DFIELD_ODD : X_D3DFIELD_EVEN;
|
// but we don't have an OOVPA for that. Instead, we call the Xbox implementation of
|
||||||
|
// D3DDevice_GetDisplayMode and read the result
|
||||||
|
|
||||||
|
// Get a function pointer to the unpatched xbox function D3DDevice_GetDisplayMode
|
||||||
|
typedef VOID(__stdcall *XB_D3DDevice_GetDisplayMode_t)(X_D3DDISPLAYMODE*);
|
||||||
|
static XB_D3DDevice_GetDisplayMode_t XB_D3DDevice_GetDisplayMode = (XB_D3DDevice_GetDisplayMode_t)GetXboxFunctionPointer("D3DDevice_GetDisplayMode");
|
||||||
|
|
||||||
|
// Check the function pointer for validity, if it is not valid, we must abort as we have a missing OOVPA
|
||||||
|
if (XB_D3DDevice_GetDisplayMode == nullptr) {
|
||||||
|
CxbxKrnlCleanup("D3DDevice_GetDisplayFieldStatus: Could not locate D3DDevice_GetDisplayMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the Xbox GetDisplayMode function to retrieve flags for the active video mode
|
||||||
|
X_D3DDISPLAYMODE displayMode;
|
||||||
|
XB_D3DDevice_GetDisplayMode(&displayMode);
|
||||||
|
|
||||||
|
// Set the VBlank count
|
||||||
pFieldStatus->VBlankCount = g_VBData.VBlank;
|
pFieldStatus->VBlankCount = g_VBData.VBlank;
|
||||||
#else
|
|
||||||
|
// If we are interlaced, return the current field, otherwise, return progressive scan
|
||||||
|
if (displayMode.Flags & X_D3DPRESENTFLAG_INTERLACED) {
|
||||||
|
pFieldStatus->Field = (g_VBData.VBlank % 2 == 0) ? X_D3DFIELD_ODD : X_D3DFIELD_EVEN;
|
||||||
|
} else {
|
||||||
pFieldStatus->Field = X_D3DFIELD_PROGRESSIVE;
|
pFieldStatus->Field = X_D3DFIELD_PROGRESSIVE;
|
||||||
pFieldStatus->VBlankCount = 0;
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -260,6 +260,8 @@ typedef enum _X_D3DSET_DEPTH_CLIP_PLANES_FLAGS
|
||||||
}
|
}
|
||||||
X_D3DSET_DEPTH_CLIP_PLANES_FLAGS;
|
X_D3DSET_DEPTH_CLIP_PLANES_FLAGS;
|
||||||
|
|
||||||
|
#define X_D3DPRESENTFLAG_INTERLACED 0x00000020
|
||||||
|
|
||||||
typedef struct _X_D3DDISPLAYMODE
|
typedef struct _X_D3DDISPLAYMODE
|
||||||
{
|
{
|
||||||
UINT Width;
|
UINT Width;
|
||||||
|
|
|
@ -63,16 +63,40 @@ PVOID g_pPersistedData = NULL;
|
||||||
ULONG AvQueryAvCapabilities()
|
ULONG AvQueryAvCapabilities()
|
||||||
{
|
{
|
||||||
// This is the only AV mode we currently emulate, so we can hardcode the return value
|
// This is the only AV mode we currently emulate, so we can hardcode the return value
|
||||||
// TODO: Once we allow the user to configure the connected AV pack, we should implement this proper
|
// TODO: Once we add the ability to change av pack, read HalSmcVideoMode) and convert it to a AV_PACK_*
|
||||||
// This function should first query the AV Pack type, read the user's EEPROM settings and
|
ULONG avpack = AV_PACK_HDTV;
|
||||||
// return the correct flags based on this.
|
ULONG type;
|
||||||
//
|
ULONG resultSize;
|
||||||
// For the AV Pack, read SMC_COMMAND_VIDEO_MODE (or HalBootSMCVideoMode) and convert it to a AV_PACK_*
|
|
||||||
//
|
// First, read the factory AV settings
|
||||||
// To read the EEPROM, call ExQueryNonVolatileSetting() with these config flags :
|
ULONG avRegion;
|
||||||
// XC_FACTORY_AV_REGION; if that fails, fallback on AV_STANDARD_NTSC_M | AV_FLAGS_60Hz
|
NTSTATUS result = xboxkrnl::ExQueryNonVolatileSetting(
|
||||||
// XC_VIDEO_FLAGS; if that fails, fallback on 0
|
xboxkrnl::XC_FACTORY_AV_REGION,
|
||||||
return AV_PACK_HDTV | AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
|
&type,
|
||||||
|
&avRegion,
|
||||||
|
sizeof(ULONG),
|
||||||
|
&resultSize);
|
||||||
|
|
||||||
|
// If this failed, default to AV_STANDARD_NTSC_M | AV_FLAGS_60Hz
|
||||||
|
if (result != STATUS_SUCCESS || resultSize != sizeof(ULONG)) {
|
||||||
|
avRegion = AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the user-configurable (via the dashboard) settings
|
||||||
|
ULONG userSettings;
|
||||||
|
result = xboxkrnl::ExQueryNonVolatileSetting(
|
||||||
|
xboxkrnl::XC_VIDEO,
|
||||||
|
&type,
|
||||||
|
&userSettings,
|
||||||
|
sizeof(ULONG),
|
||||||
|
&resultSize);
|
||||||
|
|
||||||
|
// If this failed, default to no user-options set
|
||||||
|
if (result != STATUS_SUCCESS || resultSize != sizeof(ULONG)) {
|
||||||
|
userSettings = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return avpack | (avRegion & (AV_STANDARD_MASK | AV_REFRESH_MASK)) | (userSettings & ~(AV_STANDARD_MASK | AV_PACK_MASK));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Xbox code will set this address via AvSetSavedDataAddress
|
// Xbox code will set this address via AvSetSavedDataAddress
|
||||||
|
|
|
@ -79,6 +79,14 @@ void* GetXboxFunctionPointer(std::string functionName)
|
||||||
return g_FunctionHooks[functionName].GetTrampoline();
|
return g_FunctionHooks[functionName].GetTrampoline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we got here, the function wasn't patched, so we can just look it up the HLE cache
|
||||||
|
// and return the correct offset
|
||||||
|
auto symbol = g_SymbolAddresses.find(functionName);
|
||||||
|
if (symbol != g_SymbolAddresses.end()) {
|
||||||
|
return (void*)symbol->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, if none of the above were matched, return nullptr
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue