EEPROM refactorings: Memory mapped load, offset-based access, centralized

This commit is contained in:
PatrickvL 2017-03-10 15:01:12 +01:00
parent 53b562704c
commit 8ceca49e6f
11 changed files with 369 additions and 129 deletions

View File

@ -184,6 +184,7 @@ $(SOLUTIONDIR)Export.bat</Command>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\import\stb\stb_image.h" />
<ClInclude Include="..\..\src\Common\EmuEEPROM.h" />
<ClInclude Include="..\..\src\Common\Logging.h" />
<ClInclude Include="..\..\src\Common\Win32\AlignPosfix1.h" />
<ClInclude Include="..\..\src\Common\Win32\AlignPrefix1.h" />
@ -357,6 +358,7 @@ $(SOLUTIONDIR)Export.bat</Command>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\Common\EmuEEPROM.cpp" />
<ClCompile Include="..\..\src\Common\Logging.cpp" />
<ClCompile Include="..\..\src\Common\Win32\EmuShared.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

View File

@ -193,6 +193,9 @@
<ClCompile Include="..\..\src\Common\XDVDFS Tools\buffered_io.cpp">
<Filter>Shared</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Common\EmuEEPROM.cpp">
<Filter>Shared</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\Cxbx\DlgControllerConfig.h">
@ -504,6 +507,24 @@
<ClInclude Include="..\..\src\Common\XDVDFS Tools\xdvdfs.h">
<Filter>Shared</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.1.0.5344.h">
<Filter>HLEDatabase</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\DSound.1.0.5344.h">
<Filter>HLEDatabase</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\Xapi.1.0.5344.h">
<Filter>HLEDatabase</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\XG.1.0.5344.h">
<Filter>HLEDatabase</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\XOnline.1.0.5344.h">
<Filter>HLEDatabase</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Common\EmuEEPROM.h">
<Filter>Shared</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\resource\About.jpg">
@ -653,6 +674,21 @@
<None Include="..\..\resource\Logo.bmp">
<Filter>Shared</Filter>
</None>
<None Include="..\..\src\CxbxKrnl\HLEDataBase\D3D8.1.0.5344.inl">
<Filter>HLEDatabase</Filter>
</None>
<None Include="..\..\src\CxbxKrnl\HLEDataBase\DSound.1.0.5344.inl">
<Filter>HLEDatabase</Filter>
</None>
<None Include="..\..\src\CxbxKrnl\HLEDataBase\Xapi.1.0.5344.inl">
<Filter>HLEDatabase</Filter>
</None>
<None Include="..\..\src\CxbxKrnl\HLEDataBase\XG.1.0.5344.inl">
<Filter>HLEDatabase</Filter>
</None>
<None Include="..\..\src\CxbxKrnl\HLEDataBase\XOnline.1.0.5344.inl">
<Filter>HLEDatabase</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="GUI">

143
src/Common/EmuEEPROM.cpp Normal file
View File

@ -0,0 +1,143 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Common->EmuEEPROM.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2017 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_DEFEXTRN_
// prevent name collisions
namespace xboxkrnl
{
#include <xboxkrnl/xboxkrnl.h> // For XC_VALUE_INDEX and XBOX_EEPROM
};
#include <stdio.h> // For printf
#include <shlobj.h> // For HANDLE, CreateFile, CreateFileMapping, MapViewOfFile
#include "Cxbx.h" // For DbgPrintf
#include "EmuEEPROM.h" // For EEPROMInfo, EEPROMInfos
xboxkrnl::XBOX_EEPROM *EEPROM = nullptr; // Set using CxbxRestoreEEPROM()
xboxkrnl::ULONG XboxFactoryGameRegion = 1; // = North America
const EEPROMInfo* EmuFindEEPROMInfo(xboxkrnl::XC_VALUE_INDEX index)
{
for (int i = 0; EEPROMInfos[i].index != XC_END_MARKER; i++)
if (EEPROMInfos[i].index == index)
return &EEPROMInfos[i];
return nullptr;
}
xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
{
xboxkrnl::XBOX_EEPROM *EEPROM;
// First, try to open an existing EEPROM.bin file :
HANDLE hFileEEPROM = CreateFile(szFilePath_EEPROM_bin,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* lpSecurityAttributes */nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
/* hTemplateFile */nullptr);
bool NeedsInitialization = (hFileEEPROM == INVALID_HANDLE_VALUE);
if (NeedsInitialization)
{
// If the EEPROM.bin file doesn't exist yet, create it :
hFileEEPROM = CreateFile(szFilePath_EEPROM_bin,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* lpSecurityAttributes */nullptr,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, // FILE_FLAG_WRITE_THROUGH
/* hTemplateFile */nullptr);
if (hFileEEPROM == INVALID_HANDLE_VALUE)
{
DbgPrintf("CxbxRestoreEEPROM : Couldn't create EEPROM.bin file!\n");
return nullptr;
}
}
// TODO : Make sure EEPROM.bin is at least 256 bytes in size - FileSeek(hFileEEPROM, EEPROM_SIZE, soFromBeginning);
HANDLE hFileMappingEEPROM = CreateFileMapping(
hFileEEPROM,
/* lpFileMappingAttributes */nullptr,
PAGE_READWRITE,
/* dwMaximumSizeHigh */0,
/* dwMaximumSizeLow */EEPROM_SIZE,
/**/nullptr);
if (hFileMappingEEPROM == NULL)
{
DbgPrintf("CxbxRestoreEEPROM : Couldn't create EEPROM.bin file mapping!\n");
return nullptr;
}
// Map EEPROM.bin contents into memory :
EEPROM = (xboxkrnl::XBOX_EEPROM *)MapViewOfFile(
hFileMappingEEPROM,
FILE_MAP_READ | FILE_MAP_WRITE,
/* dwFileOffsetHigh */0,
/* dwFileOffsetLow */0,
EEPROM_SIZE);
if (EEPROM == NULL)
DbgPrintf("CxbxRestoreEEPROM : Couldn't map EEPROM.bin into memory!\n");
// TODO : Verify checksums
if (NeedsInitialization)
{
memset(EEPROM, 0, EEPROM_SIZE);
// TODO: Make these configurable or autodetect of some sort :
EEPROM->UserSettings.Language = 0x01; // = English
EEPROM->UserSettings.VideoFlags = 0x10; // = Letterbox
EEPROM->UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
EEPROM->UserSettings.ParentalControlGames = 0; // = XC_PC_ESRB_ALL
EEPROM->UserSettings.ParentalControlMovies = 0; // = XC_PC_ESRB_ALL
EEPROM->UserSettings.MiscFlags = 0; // No automatic power down
EEPROM->FactorySettings.AVRegion = 0x01; // = NTSC_M
XboxFactoryGameRegion = 1; // = North America - TODO : This should be derived from EncryptedSection somehow
DbgPrintf("EmuMain: Initialized default EEPROM\n");
}
else
DbgPrintf("EmuMain: Loaded EEPROM.bin\n");
return EEPROM;
}

106
src/Common/EmuEEPROM.h Normal file
View File

@ -0,0 +1,106 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Common->EmuEEPROM.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2017 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef EMU_EEPROM_H
#define EMU_EEPROM_H
#if defined(__cplusplus)
#pragma once
extern "C"
{
#endif
#define EEPROM_SIZE sizeof(xboxkrnl::XBOX_EEPROM)
typedef struct EEPROMInfo {
xboxkrnl::XC_VALUE_INDEX index;
int value_offset;
int value_type;
int value_length;
} EEPROMInfo;
#define XC_END_MARKER (xboxkrnl::XC_VALUE_INDEX)-1
#define EEPROM_INFO_ENTRY(XC, Member, REG_Type) \
{ xboxkrnl::##XC, offsetof(xboxkrnl::XBOX_EEPROM, Member), REG_Type, sizeof(((xboxkrnl::XBOX_EEPROM *)0)->Member) }
static const EEPROMInfo EEPROMInfos[] = {
EEPROM_INFO_ENTRY(XC_TIMEZONE_BIAS, UserSettings.TimeZoneBias, REG_DWORD),
EEPROM_INFO_ENTRY(XC_TZ_STD_NAME, UserSettings.TimeZoneStdName, REG_BINARY),
EEPROM_INFO_ENTRY(XC_TZ_STD_DATE, UserSettings.TimeZoneStdDate, REG_DWORD),
EEPROM_INFO_ENTRY(XC_TZ_STD_BIAS, UserSettings.TimeZoneStdBias, REG_DWORD),
EEPROM_INFO_ENTRY(XC_TZ_DLT_NAME, UserSettings.TimeZoneDltName, REG_BINARY),
EEPROM_INFO_ENTRY(XC_TZ_DLT_DATE, UserSettings.TimeZoneDltDate, REG_DWORD),
EEPROM_INFO_ENTRY(XC_TZ_DLT_BIAS, UserSettings.TimeZoneDltBias, REG_DWORD),
EEPROM_INFO_ENTRY(XC_LANGUAGE, UserSettings.Language, REG_DWORD),
EEPROM_INFO_ENTRY(XC_VIDEO, UserSettings.VideoFlags, REG_DWORD),
EEPROM_INFO_ENTRY(XC_AUDIO, UserSettings.AudioFlags, REG_DWORD),
EEPROM_INFO_ENTRY(XC_P_CONTROL_GAMES, UserSettings.ParentalControlGames, REG_DWORD), // Zapper queries this. TODO : Should this be REG_NONE?
EEPROM_INFO_ENTRY(XC_P_CONTROL_PASSWORD, UserSettings.ParentalControlPassword, REG_DWORD),
EEPROM_INFO_ENTRY(XC_P_CONTROL_MOVIES, UserSettings.ParentalControlMovies, REG_DWORD), // Xbox Dashboard queries this.
EEPROM_INFO_ENTRY(XC_ONLINE_IP_ADDRESS, UserSettings.OnlineIpAddress, REG_DWORD),
EEPROM_INFO_ENTRY(XC_ONLINE_DNS_ADDRESS, UserSettings.OnlineDnsAddress, REG_DWORD),
EEPROM_INFO_ENTRY(XC_ONLINE_DEFAULT_GATEWAY_ADDRESS, UserSettings.OnlineDefaultGatewayAddress, REG_DWORD),
EEPROM_INFO_ENTRY(XC_ONLINE_SUBNET_ADDRESS, UserSettings.OnlineSubnetMask, REG_DWORD),
EEPROM_INFO_ENTRY(XC_MISC, UserSettings.MiscFlags, REG_DWORD),
EEPROM_INFO_ENTRY(XC_DVD_REGION, UserSettings.DvdRegion, REG_DWORD),
EEPROM_INFO_ENTRY(XC_MAX_OS, UserSettings, REG_BINARY),
// XC_MAX_OS is called to return a complete XBOX_USER_SETTINGS structure
//
// One example is from XapipQueryTimeZoneInformation(, REG_DWORD, sizeof(DWORD), where it is used to
// detect the local timezone information.
EEPROM_INFO_ENTRY(XC_FACTORY_SERIAL_NUMBER, FactorySettings.SerialNumber, REG_BINARY),
EEPROM_INFO_ENTRY(XC_FACTORY_ETHERNET_ADDR, FactorySettings.EthernetAddr, REG_BINARY),
EEPROM_INFO_ENTRY(XC_FACTORY_ONLINE_KEY, FactorySettings.OnlineKey, REG_BINARY),
EEPROM_INFO_ENTRY(XC_FACTORY_AV_REGION, FactorySettings.AVRegion, REG_DWORD),
// Note : XC_FACTORY_GAME_REGION is linked to a separate ULONG XboxFactoryGameRegion (of type REG_DWORD)
EEPROM_INFO_ENTRY(XC_ENCRYPTED_SECTION, EncryptedSettings, REG_BINARY),
{ xboxkrnl::XC_MAX_ALL, 0, REG_BINARY, sizeof(xboxkrnl::XBOX_EEPROM) },
{ XC_END_MARKER }
};
extern xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin);
extern const EEPROMInfo* EmuFindEEPROMInfo(xboxkrnl::XC_VALUE_INDEX index);
extern xboxkrnl::XBOX_EEPROM *EEPROM;
extern xboxkrnl::ULONG XboxFactoryGameRegion;
#if defined(__cplusplus)
}
#endif
#endif // EMU_EEPROM_H

View File

@ -7,7 +7,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuD3D8->ReservedMemory.h
// * Common->ReservedMemory.h
// *
// * This file is part of the Cxbx project.
// *

View File

@ -48,7 +48,7 @@ namespace xboxkrnl
#include "EmuX86.h"
#include "EmuFile.h"
#include "EmuFS.h"
#include "EmuKrnl.h" // For EEPROM, XboxFactoryGameRegion
#include "EmuEEPROM.h" // For CxbxRestoreEEPROM, EEPROM, XboxFactoryGameRegion
#include "EmuShared.h"
#include "EmuNV2A.h" // For InitOpenGLContext
#include "HLEIntercept.h"
@ -79,6 +79,11 @@ char* CxbxKrnl_DebugFileName = NULL;
/*! thread handles */
static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = { 0 };
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
char szFilePath_LaunchDataPage_bin[MAX_PATH] = { 0 };
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
std::string CxbxBasePath;
HANDLE CxbxBasePathHandle;
Xbe* CxbxKrnl_Xbe = NULL;
@ -285,7 +290,11 @@ void CxbxKrnlMain(int argc, char* argv[])
RestoreExeImageHeader();
}
CxbxRestoreEEPROM();
CxbxInitFilePaths();
EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin);
if (EEPROM == nullptr)
CxbxKrnlCleanup("EmuMain : Couldn't init EEPROM!");
CxbxRestorePersistentMemoryRegions();
@ -391,7 +400,6 @@ void CxbxKrnlInit
setlocale(LC_ALL, "English");
g_CurrentProcessHandle = GetCurrentProcess();
CxbxInitPerformanceCounters();
CxbxInitFilePaths();
#ifdef _DEBUG
// MessageBoxA(NULL, "Attach a Debugger", "DEBUG", 0);
// Debug child processes using https://marketplace.visualstudio.com/items?itemName=GreggMiskelly.MicrosoftChildProcessDebuggingPowerTool
@ -634,11 +642,6 @@ void CxbxKrnlInit
return;
}
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
char szFolder_CxbxReloadedData[MAX_PATH] = { 0 };
char szFilePath_LaunchDataPage_bin[MAX_PATH] = { 0 };
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
void CxbxInitFilePaths()
{
// Determine (local)appdata folder :
@ -651,48 +654,18 @@ void CxbxInitFilePaths()
}
snprintf(szFolder_CxbxReloadedData, MAX_PATH, "%s\\CxbxReloaded", szLocalAppDataFolder);
// Make sure our data folder exists :
int result = SHCreateDirectoryEx(nullptr, szFolder_CxbxReloadedData, nullptr);
if ((result != ERROR_SUCCESS) && (result != ERROR_ALREADY_EXISTS))
CxbxKrnlCleanup("CxbxInitFilePaths : Couldn't create CxbxReloaded AppData folder!");
snprintf(szFilePath_LaunchDataPage_bin, MAX_PATH, "%s\\CxbxLaunchDataPage.bin", szFolder_CxbxReloadedData);
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", szFolder_CxbxReloadedData); // TODO : Start using this
GetModuleFileName(GetModuleHandle(NULL), szFilePath_CxbxReloaded_Exe, MAX_PATH);
}
void EmuInitializeDefaultEEPROM()
{
memset(&EEPROM, 0, sizeof(xboxkrnl::XBOX_EEPROM));
// TODO: Make these configurable or autodetect of some sort :
EEPROM.UserSettings.Language = 0x01; // = English
EEPROM.UserSettings.VideoFlags = 0x10; // = Letterbox
EEPROM.UserSettings.AudioFlags = 0; // = Stereo, no AC3, no DTS
EEPROM.UserSettings.ParentalControlGames = 0; // = XC_PC_ESRB_ALL
EEPROM.UserSettings.ParentalControlMovies = 0; // = XC_PC_ESRB_ALL
EEPROM.UserSettings.MiscFlags = 0; // No automatic power down
EEPROM.FactorySettings.AVRegion = 0x01; // = NTSC_M
XboxFactoryGameRegion = 1; // = North America - TODO : This should be derived from EncryptedSection somehow
DbgPrintf("EmuMain: Initialized default EEPROM\n");
}
void CxbxRestoreEEPROM()
{
// If EEPROM.bin exists, load it into our buffer
FILE *fp = fopen(szFilePath_EEPROM_bin, "rb");
if (fp)
{
// Read in the contents.
fseek(fp, 0, SEEK_SET);
fread(&EEPROM, sizeof(xboxkrnl::XBOX_EEPROM), 1, fp);
fclose(fp);
DbgPrintf("EmuMain: Loaded EEPROM.bin\n");
}
else
EmuInitializeDefaultEEPROM();
}
// TODO : Is DefaultLaunchDataPage really necessary? (No-one assigns it yet to LaunchDataPage)
xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage =
{

View File

@ -125,8 +125,6 @@ void CxbxInitPerformanceCounters(); // Implemented in EmuKrnlKe.cpp
void CxbxInitFilePaths();
void CxbxRestoreEEPROM();
void CxbxRestorePersistentMemoryRegions();
void ConnectWindowsTimersToThunkTable();

View File

@ -51,10 +51,6 @@ namespace xboxkrnl
#include "EmuKrnlLogging.h"
#include "CxbxKrnl.h"
xboxkrnl::XBOX_EEPROM EEPROM = { 0 }; // See EmuInitializeDefaultEEPROM()
xboxkrnl::ULONG XboxFactoryGameRegion = 1; // = North America
// prevent name collisions
namespace NtDll
{

View File

@ -55,9 +55,4 @@ xboxkrnl::PLIST_ENTRY RemoveTailList(xboxkrnl::PLIST_ENTRY pListHead);
extern xboxkrnl::LAUNCH_DATA_PAGE DefaultLaunchDataPage;
extern xboxkrnl::XBOX_EEPROM EEPROM;
extern xboxkrnl::ULONG XboxFactoryGameRegion;
#endif

View File

@ -44,6 +44,7 @@ namespace xboxkrnl
};
#include "Logging.h" // For LOG_FUNC()
#include "EmuEEPROM.h" // For EmuFindEEPROMInfo, EEPROM, XboxFactoryGameRegion
#include "EmuKrnlLogging.h"
// prevent name collisions
@ -286,60 +287,6 @@ XBSYSAPI EXPORTNUM(23) xboxkrnl::ULONG NTAPI xboxkrnl::ExQueryPoolBlockSize
RETURN(ret);
}
typedef struct EEPROMInfo {
xboxkrnl::XC_VALUE_INDEX index;
void *value_addr;
DWORD value_type;
int value_length;
} EEPROMInfo;
#define XC_END_MARKER (xboxkrnl::XC_VALUE_INDEX)-1
static const EEPROMInfo EEPROMInfos[] = {
{ xboxkrnl::XC_TIMEZONE_BIAS, &EEPROM.UserSettings.TimeZoneBias, REG_DWORD, sizeof(LONG) },
{ xboxkrnl::XC_TZ_STD_NAME, &EEPROM.UserSettings.TimeZoneStdName[0], REG_BINARY, TIME_ZONE_NAME_LENGTH },
{ xboxkrnl::XC_TZ_STD_DATE, &EEPROM.UserSettings.TimeZoneStdDate, REG_DWORD, sizeof(xboxkrnl::XBOX_TIMEZONE_DATE) },
{ xboxkrnl::XC_TZ_STD_BIAS, &EEPROM.UserSettings.TimeZoneStdBias, REG_DWORD, sizeof(LONG) },
{ xboxkrnl::XC_TZ_DLT_NAME, &EEPROM.UserSettings.TimeZoneDltName[0], REG_BINARY, TIME_ZONE_NAME_LENGTH },
{ xboxkrnl::XC_TZ_DLT_DATE, &EEPROM.UserSettings.TimeZoneDltDate, REG_DWORD, sizeof(xboxkrnl::XBOX_TIMEZONE_DATE) },
{ xboxkrnl::XC_TZ_DLT_BIAS, &EEPROM.UserSettings.TimeZoneDltBias, REG_DWORD, sizeof(LONG) },
{ xboxkrnl::XC_LANGUAGE, &EEPROM.UserSettings.Language, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_VIDEO, &EEPROM.UserSettings.VideoFlags, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_AUDIO, &EEPROM.UserSettings.AudioFlags, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_P_CONTROL_GAMES, &EEPROM.UserSettings.ParentalControlGames, REG_DWORD, sizeof(ULONG) }, // Zapper queries this. TODO : Should this be REG_NONE?
{ xboxkrnl::XC_P_CONTROL_PASSWORD, &EEPROM.UserSettings.ParentalControlPassword, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_P_CONTROL_MOVIES, &EEPROM.UserSettings.ParentalControlMovies, REG_DWORD, sizeof(ULONG) }, // Xbox Dashboard queries this.
{ xboxkrnl::XC_ONLINE_IP_ADDRESS, &EEPROM.UserSettings.OnlineIpAddress, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_ONLINE_DNS_ADDRESS, &EEPROM.UserSettings.OnlineDnsAddress, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_ONLINE_DEFAULT_GATEWAY_ADDRESS, &EEPROM.UserSettings.OnlineDefaultGatewayAddress, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_ONLINE_SUBNET_ADDRESS, &EEPROM.UserSettings.OnlineSubnetMask, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_MISC, &EEPROM.UserSettings.MiscFlags, REG_DWORD, sizeof(DWORD) },
{ xboxkrnl::XC_DVD_REGION, &EEPROM.UserSettings.DvdRegion, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_MAX_OS, &EEPROM.UserSettings, REG_BINARY, sizeof(xboxkrnl::XBOX_USER_SETTINGS)
// This is called to return a complete XBOX_USER_SETTINGS structure
//
// One example is from XapipQueryTimeZoneInformation(, REG_DWORD, sizeof(DWORD), where it is used to
// detect the local timezone information.
},
{ xboxkrnl::XC_FACTORY_SERIAL_NUMBER, &EEPROM.FactorySettings.SerialNumber[0], REG_BINARY, 12 },
{ xboxkrnl::XC_FACTORY_ETHERNET_ADDR, &EEPROM.FactorySettings.EthernetAddr[0], REG_BINARY, 6 },
{ xboxkrnl::XC_FACTORY_ONLINE_KEY, &EEPROM.FactorySettings.OnlineKey, REG_BINARY, 16 },
{ xboxkrnl::XC_FACTORY_AV_REGION, &EEPROM.FactorySettings.AVRegion, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_FACTORY_GAME_REGION, &XboxFactoryGameRegion, REG_DWORD, sizeof(ULONG) },
{ xboxkrnl::XC_ENCRYPTED_SECTION, &EEPROM.EncryptedSettings, REG_BINARY, sizeof(xboxkrnl::XBOX_ENCRYPTED_SETTINGS) },
{ xboxkrnl::XC_MAX_ALL, &EEPROM, REG_BINARY, sizeof(xboxkrnl::XBOX_EEPROM) },
{ XC_END_MARKER }
};
const EEPROMInfo* EmuFindEEPROMInfo(xboxkrnl::XC_VALUE_INDEX index)
{
for (int i = 0; EEPROMInfos[i].index != XC_END_MARKER; i++)
if (EEPROMInfos[i].index == index)
return &EEPROMInfos[i];
return nullptr;
}
// ******************************************************************
// * 0x0018 - ExQueryNonVolatileSetting()
// ******************************************************************
@ -361,13 +308,30 @@ XBSYSAPI EXPORTNUM(24) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExQueryNonVolatileSett
LOG_FUNC_END;
NTSTATUS Status = STATUS_SUCCESS;
void * value_addr = nullptr;
int value_type;
int result_length;
// handle eeprom read
const EEPROMInfo* info = EmuFindEEPROMInfo((XC_VALUE_INDEX)ValueIndex);
if (info != nullptr)
if (ValueIndex == XC_FACTORY_GAME_REGION)
{
int result_length = info->value_length;
value_addr = &XboxFactoryGameRegion;
value_type = REG_DWORD;
result_length = sizeof(ULONG);
}
else
{
const EEPROMInfo* info = EmuFindEEPROMInfo((XC_VALUE_INDEX)ValueIndex);
if (info != nullptr)
{
value_addr = (void *)((PBYTE)EEPROM + info->value_offset);
value_type = info->value_type;
result_length = info->value_length;
};
}
if (value_addr != nullptr)
{
if (ResultLength != nullptr)
*ResultLength = result_length;
@ -381,11 +345,11 @@ XBSYSAPI EXPORTNUM(24) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExQueryNonVolatileSett
// 32-bit 1's complement sum, that must equal 0xFFFFFFFF)
// Set the output value type :
*Type = info->value_type;
*Type = value_type;
// Clear the output value buffer :
memset(Value, 0, ValueLength);
// Copy the emulated EEPROM value into the output value buffer :
memcpy(Value, info->value_addr, result_length);
memcpy(Value, value_addr, result_length);
}
else
Status = STATUS_BUFFER_TOO_SMALL;
@ -539,25 +503,39 @@ XBSYSAPI EXPORTNUM(29) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExSaveNonVolatileSetti
LOG_FUNC_END;
NTSTATUS Status = STATUS_SUCCESS;
void * value_addr = nullptr;
DWORD result_length;
// handle eeprom write
const EEPROMInfo* info = EmuFindEEPROMInfo((XC_VALUE_INDEX)ValueIndex);
if (ValueIndex == XC_FACTORY_GAME_REGION)
{
value_addr = &XboxFactoryGameRegion;
result_length = sizeof(ULONG);
}
else
{
const EEPROMInfo* info = EmuFindEEPROMInfo((XC_VALUE_INDEX)ValueIndex);
if (info != nullptr)
{
value_addr = (void *)(EEPROM + info->value_offset);
result_length = info->value_length;
};
}
// TODO : Only allow writing to factory section contents when running
// in DEVKIT mode, otherwise, nil the info pointer.
if (info != nullptr)
if (value_addr != nullptr)
{
// Note : Type could be verified against info->value_type here, but the orginal kernel doesn't even bother
DWORD result_length = info->value_length;
if (ValueLength <= result_length)
{
// TODO : Make EEPROM-access thread-safe
// Clear the emulated EEMPROM value :
memset(info->value_addr, 0, result_length);
memset(value_addr, 0, result_length);
// Copy the input value buffer into the emulated EEPROM value :
memcpy(info->value_addr, Value, ValueLength);
memcpy(value_addr, Value, ValueLength);
// TODO : When writing to the factory settings section (thus in DEVKIT
// mode), set XboxFactoryGameRegion to FactorySettings.GameRegion,

View File

@ -49,7 +49,7 @@ namespace xboxkrnl
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
#include "Emu.h" // For EmuWarning()
#include "EmuX86.h" // HalReadWritePciSpace needs this
#include "EmuKrnl.h" // For EEPROM
#include "EmuEEPROM.h" // For EEPROM
#include "EmuFile.h" // For FindNtSymbolicLinkObjectByDriveLetter
// prevent name collisions
@ -225,8 +225,21 @@ XBSYSAPI EXPORTNUM(44) xboxkrnl::ULONG NTAPI xboxkrnl::HalGetInterruptVector
RETURN(dwVector);
}
#define EEPROM_SMBUS_WRITE 0xA8
#define EEPROM_SMBUS_READ 0xA9
#define SMC_SLAVE_ADDRESS 0x20
#define SMBUS_SMC_WRITE SMC_SLAVE_ADDRESS // = 0x20
#define SMBUS_SMC_READ (SMC_SLAVE_ADDRESS || 1) // = 0x21
#define EEPROM_ADDRESS 0xA8
#define SMBUS_EEPROM_WRITE EEPROM_ADDRESS // = 0xA8
#define SMBUS_EEPROM_READ (EEPROM_ADDRESS || 1) // = 0xA9
#define SMBUS_TV_ENCODER_ID_CONEXANT 0x8A
#define SMBUS_TV_ENCODER_ID_CONEXANT_WRITE SMBUS_TV_ENCODER_ID_CONEXANT // = 0x8A
#define SMBUS_TV_ENCODER_ID_CONEXANT_READ (SMBUS_TV_ENCODER_ID_CONEXANT_WRITE || 1) // = 0x8B
#define SMBUS_TV_ENCODER_ID_FOCUS 0xD4
#define SMBUS_TV_ENCODER_ID_FOCUS_WRITE SMBUS_TV_ENCODER_ID_FOCUS // = 0xD4
#define SMBUS_TV_ENCODER_ID_FOCUS_READ (SMBUS_TV_ENCODER_ID_FOCUS_WRITE || 1) // = 0xD5
// ******************************************************************
// * 0x002D - HalReadSMBusValue()
@ -249,11 +262,11 @@ XBSYSAPI EXPORTNUM(45) xboxkrnl::NTSTATUS NTAPI xboxkrnl::HalReadSMBusValue
NTSTATUS Status = STATUS_SUCCESS;
switch (Address) {
case EEPROM_SMBUS_READ: {
case SMBUS_EEPROM_READ: {
if (ReadWord)
*DataValue = *((PWORD)(((PBYTE)&EEPROM) + Command));
*DataValue = *((PWORD)(((PBYTE)EEPROM) + Command));
else
*DataValue = *(((PBYTE)&EEPROM) + Command);
*DataValue = *(((PBYTE)EEPROM) + Command);
break;
}
@ -483,11 +496,11 @@ XBSYSAPI EXPORTNUM(50) xboxkrnl::NTSTATUS NTAPI xboxkrnl::HalWriteSMBusValue
NTSTATUS Status = STATUS_SUCCESS;
switch (Address) {
case EEPROM_SMBUS_WRITE: {
case SMBUS_EEPROM_WRITE: {
if (WriteWord)
*((PWORD)(((PBYTE)&EEPROM) + Command)) = (WORD)DataValue;
*((PWORD)(((PBYTE)EEPROM) + Command)) = (WORD)DataValue;
else
*(((PBYTE)&EEPROM) + Command) = (BYTE)DataValue;
*(((PBYTE)EEPROM) + Command) = (BYTE)DataValue;
break;
}