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
|
||||
|
||||
// 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)
|
||||
{
|
||||
memset(pEEPROM, 0, EEPROM_SIZE);
|
||||
|
||||
// TODO: Make these configurable or autodetect of some sort :
|
||||
pEEPROM->UserSettings.Language = 0x01; // = English
|
||||
pEEPROM->UserSettings.VideoFlags = (AV_FLAGS_LETTERBOX | AV_FLAGS_60Hz) >> AV_USER_FLAGS_SHIFT; // = Letterbox
|
||||
pEEPROM->UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
|
||||
pEEPROM->UserSettings.VideoFlags = 0; // = Use XDK defaults
|
||||
pEEPROM->UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
|
||||
pEEPROM->UserSettings.ParentalControlGames = 0; // = XC_PC_ESRB_ALL
|
||||
pEEPROM->UserSettings.ParentalControlMovies = 0; // = XC_PC_ESRB_ALL
|
||||
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
|
||||
|
||||
|
|
|
@ -2494,18 +2494,38 @@ HRESULT WINAPI XTL::EMUPATCH(D3D_CheckDeviceFormat)
|
|||
// ******************************************************************
|
||||
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);
|
||||
|
||||
// TODO: Read AV Flags to determine if Progressive or Interlaced
|
||||
#if 1
|
||||
pFieldStatus->Field = (g_VBData.VBlank%2 == 0) ? X_D3DFIELD_ODD : X_D3DFIELD_EVEN;
|
||||
pFieldStatus->VBlankCount = g_VBData.VBlank;
|
||||
#else
|
||||
pFieldStatus->Field = X_D3DFIELD_PROGRESSIVE;
|
||||
pFieldStatus->VBlankCount = 0;
|
||||
#endif
|
||||
// Read AV Flags to determine if Progressive or Interlaced
|
||||
// The xbox does this by reading from pDevice->m_Miniport.m_CurrentAvInfo
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -260,6 +260,8 @@ typedef enum _X_D3DSET_DEPTH_CLIP_PLANES_FLAGS
|
|||
}
|
||||
X_D3DSET_DEPTH_CLIP_PLANES_FLAGS;
|
||||
|
||||
#define X_D3DPRESENTFLAG_INTERLACED 0x00000020
|
||||
|
||||
typedef struct _X_D3DDISPLAYMODE
|
||||
{
|
||||
UINT Width;
|
||||
|
|
|
@ -63,16 +63,40 @@ PVOID g_pPersistedData = NULL;
|
|||
ULONG AvQueryAvCapabilities()
|
||||
{
|
||||
// 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
|
||||
// This function should first query the AV Pack type, read the user's EEPROM settings and
|
||||
// return the correct flags based on this.
|
||||
//
|
||||
// For the AV Pack, read SMC_COMMAND_VIDEO_MODE (or HalBootSMCVideoMode) and convert it to a AV_PACK_*
|
||||
//
|
||||
// To read the EEPROM, call ExQueryNonVolatileSetting() with these config flags :
|
||||
// XC_FACTORY_AV_REGION; if that fails, fallback on AV_STANDARD_NTSC_M | AV_FLAGS_60Hz
|
||||
// XC_VIDEO_FLAGS; if that fails, fallback on 0
|
||||
return AV_PACK_HDTV | AV_STANDARD_NTSC_M | AV_FLAGS_60Hz;
|
||||
// TODO: Once we add the ability to change av pack, read HalSmcVideoMode) and convert it to a AV_PACK_*
|
||||
ULONG avpack = AV_PACK_HDTV;
|
||||
ULONG type;
|
||||
ULONG resultSize;
|
||||
|
||||
// First, read the factory AV settings
|
||||
ULONG avRegion;
|
||||
NTSTATUS result = xboxkrnl::ExQueryNonVolatileSetting(
|
||||
xboxkrnl::XC_FACTORY_AV_REGION,
|
||||
&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
|
||||
|
|
|
@ -79,6 +79,14 @@ void* GetXboxFunctionPointer(std::string functionName)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue