From 8ceca49e6fa4b0a98a17de0595543962a3d44cb7 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 10 Mar 2017 15:01:12 +0100 Subject: [PATCH] EEPROM refactorings: Memory mapped load, offset-based access, centralized --- build/win32/Cxbx.vcxproj | 2 + build/win32/Cxbx.vcxproj.filters | 36 ++++++++ src/Common/EmuEEPROM.cpp | 143 +++++++++++++++++++++++++++++++ src/Common/EmuEEPROM.h | 106 +++++++++++++++++++++++ src/Common/ReservedMemory.h | 2 +- src/CxbxKrnl/CxbxKrnl.cpp | 61 ++++--------- src/CxbxKrnl/CxbxKrnl.h | 2 - src/CxbxKrnl/EmuKrnl.cpp | 4 - src/CxbxKrnl/EmuKrnl.h | 5 -- src/CxbxKrnl/EmuKrnlEx.cpp | 106 +++++++++-------------- src/CxbxKrnl/EmuKrnlHal.cpp | 31 +++++-- 11 files changed, 369 insertions(+), 129 deletions(-) create mode 100644 src/Common/EmuEEPROM.cpp create mode 100644 src/Common/EmuEEPROM.h diff --git a/build/win32/Cxbx.vcxproj b/build/win32/Cxbx.vcxproj index 60d2fe819..ca86bd86a 100644 --- a/build/win32/Cxbx.vcxproj +++ b/build/win32/Cxbx.vcxproj @@ -184,6 +184,7 @@ $(SOLUTIONDIR)Export.bat + @@ -357,6 +358,7 @@ $(SOLUTIONDIR)Export.bat + %(AdditionalIncludeDirectories) diff --git a/build/win32/Cxbx.vcxproj.filters b/build/win32/Cxbx.vcxproj.filters index 620f2b787..2d90b8cef 100644 --- a/build/win32/Cxbx.vcxproj.filters +++ b/build/win32/Cxbx.vcxproj.filters @@ -193,6 +193,9 @@ Shared + + Shared + @@ -504,6 +507,24 @@ Shared + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + + + Shared + @@ -653,6 +674,21 @@ Shared + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + + + HLEDatabase + diff --git a/src/Common/EmuEEPROM.cpp b/src/Common/EmuEEPROM.cpp new file mode 100644 index 000000000..96154ac5b --- /dev/null +++ b/src/Common/EmuEEPROM.cpp @@ -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 +// * +// * All rights reserved +// * +// ****************************************************************** +#define _CXBXKRNL_INTERNAL +#define _XBOXKRNL_DEFEXTRN_ + +// prevent name collisions +namespace xboxkrnl +{ + #include // For XC_VALUE_INDEX and XBOX_EEPROM +}; + +#include // For printf +#include // 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; +} diff --git a/src/Common/EmuEEPROM.h b/src/Common/EmuEEPROM.h new file mode 100644 index 000000000..6708566a8 --- /dev/null +++ b/src/Common/EmuEEPROM.h @@ -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 +// * +// * 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 \ No newline at end of file diff --git a/src/Common/ReservedMemory.h b/src/Common/ReservedMemory.h index fcf140727..f6cb3d858 100644 --- a/src/Common/ReservedMemory.h +++ b/src/Common/ReservedMemory.h @@ -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. // * diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 58adb394a..c37010956 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -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 = { diff --git a/src/CxbxKrnl/CxbxKrnl.h b/src/CxbxKrnl/CxbxKrnl.h index c793d8f36..1060d8d66 100644 --- a/src/CxbxKrnl/CxbxKrnl.h +++ b/src/CxbxKrnl/CxbxKrnl.h @@ -125,8 +125,6 @@ void CxbxInitPerformanceCounters(); // Implemented in EmuKrnlKe.cpp void CxbxInitFilePaths(); -void CxbxRestoreEEPROM(); - void CxbxRestorePersistentMemoryRegions(); void ConnectWindowsTimersToThunkTable(); diff --git a/src/CxbxKrnl/EmuKrnl.cpp b/src/CxbxKrnl/EmuKrnl.cpp index 74a86394e..208f29462 100644 --- a/src/CxbxKrnl/EmuKrnl.cpp +++ b/src/CxbxKrnl/EmuKrnl.cpp @@ -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 { diff --git a/src/CxbxKrnl/EmuKrnl.h b/src/CxbxKrnl/EmuKrnl.h index 06efa89f6..7b82a1af6 100644 --- a/src/CxbxKrnl/EmuKrnl.h +++ b/src/CxbxKrnl/EmuKrnl.h @@ -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 diff --git a/src/CxbxKrnl/EmuKrnlEx.cpp b/src/CxbxKrnl/EmuKrnlEx.cpp index af40f73f4..330a06015 100644 --- a/src/CxbxKrnl/EmuKrnlEx.cpp +++ b/src/CxbxKrnl/EmuKrnlEx.cpp @@ -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, diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index 88f6bc26a..4a18c1485 100644 --- a/src/CxbxKrnl/EmuKrnlHal.cpp +++ b/src/CxbxKrnl/EmuKrnlHal.cpp @@ -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; }