Reduce clutter in Loader by splitting up functionality in task-specific source files

This commit is contained in:
PatrickvL 2019-02-04 13:41:11 +01:00 committed by RadWolfie
parent 420d689d82
commit 032eee144f
9 changed files with 435 additions and 265 deletions

View File

@ -23,11 +23,13 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
endif()
file (GLOB HEADERS
"${CXBXR_ROOT_DIR}/src/common/XboxAddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/ReserveAddressRanges.h"
)
file (GLOB SOURCES
"${CXBXR_ROOT_DIR}/src/common/XboxAddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/LoaderTooling.cpp"
"${CXBXR_ROOT_DIR}/src/common/ReserveAddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/CxbxLoader/loader.cpp"
)

View File

@ -34,11 +34,8 @@
// *
// ******************************************************************
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h> // For DWORD, CALLBACK, VirtualAlloc, LPVOID, SIZE_T, HMODULE
#include "..\Common\XboxAddressRanges.h" // For XboxAddressRangeType, XboxAddressRanges
#include "..\Common\AddressRanges.h"
#include "..\Common\ReserveAddressRanges.h"
// Reserve the first 128 MB MemLowVirtual address range without inflating the EXE size,
// by simply declaring an array, first thing, in global scope. It gets placed in the BSS segment,

125
src/common/AddressRanges.h Normal file
View File

@ -0,0 +1,125 @@
// 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->AddressRanges.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h> // For DWORD, CALLBACK, VirtualAlloc, LPVOID, SIZE_T, HMODULE
#define KB(x) ((x) * 1024 ) // = 0x00000400
#define MB(x) ((x) * KB(1024)) // = 0x00100000
// Windows' address space allocation granularity;
// See https://blogs.msdn.microsoft.com/oldnewthing/20031008-00/?p=42223
const int BLOCK_SIZE = KB(64);
// One allocation block consists of 16 pages (since PAGE_SIZE is 4 kilobytes)
const int PAGE_SIZE = KB(4);
#define ARRAY_SIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
const struct {
unsigned __int32 Start;
#ifdef DEBUG
unsigned __int32 End; // TODO : Add validation that this End corresponds to specified Size
#endif
int Size;
DWORD InitialMemoryProtection; // Memory page protection, for use by VirtualAlloc
// Shortend symbol aliasses for memory page protection
#define PROT_UNH 0 // UNHANDLED
#define PROT_RW PAGE_READWRITE
#define PROT_XRW PAGE_EXECUTE_READWRITE
#define PROT_NAC PAGE_NOACCESS
unsigned int RangeFlags;
// Range flags (used for system selection and optional marker)
#define MAY_FAIL (1 << 0) // Optional (may fail address range reservation)
#define SYSTEM_XBOX (1 << 1)
#define SYSTEM_DEVKIT (1 << 2)
#define SYSTEM_CHIHIRO (1 << 3)
#ifdef INCLUDE_SYSTEM_ALPHA
#define SYSTEM_ALPHA (1 << 4)
#endif
// Short-hand for sets of system configurations
#define SYSTEM_ALL (SYSTEM_XBOX | SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
#define SYSTEM_RETAIL (SYSTEM_XBOX | SYSTEM_DEVKIT )
#define SYSTEM_128MB ( SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
#ifdef DEBUG
const char *Comment;
#endif
} XboxAddressRanges[] = {
#ifdef DEBUG
#define RANGE_ENTRY(START, END, SIZE, PROT, FLAGS, COMMENT) { START, END, SIZE, PROT, FLAGS, COMMENT }
#else
#define RANGE_ENTRY(START, END, SIZE, PROT, FLAGS, COMMENT) { START, SIZE, PROT, FLAGS }
#endif
// See http://xboxdevwiki.net/Memory
// and http://xboxdevwiki.net/Boot_Process#Paging
// Entry : Start , End , Size , Protect , RangeFlags , Comment
RANGE_ENTRY(0x00000000, 0x03FFFFFF, MB( 64), PROT_XRW, SYSTEM_XBOX | MAY_FAIL, "MemLowVirtual (Retail Xbox) Optional (already reserved via virtual_memory_placeholder)"),
RANGE_ENTRY(0x00000000, 0x07FFFFFF, MB(128), PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit)"),
RANGE_ENTRY(0x80000000, 0x83FFFFFF, MB( 64), PROT_XRW, SYSTEM_XBOX , "MemPhysical (Retail)"),
RANGE_ENTRY(0x80000000, 0x87FFFFFF, MB(128), PROT_XRW, SYSTEM_128MB , "MemPhysical (Chihiro / DevKit)"),
RANGE_ENTRY(0xB0000000, 0xB7FFFFFF, MB(128), PROT_NAC, SYSTEM_DEVKIT , "DevKitMemory"), // TODO : Check reserved range (might behave like MemTiled)
RANGE_ENTRY(0xC0000000, 0xC001FFFF, KB(128), PROT_RW, SYSTEM_ALL , "MemPageTable"), // TODO : MB(4)?
RANGE_ENTRY(0xD0000000, 0xEFFFFFFF, MB(512), PROT_UNH, SYSTEM_ALL | MAY_FAIL, "SystemMemory Optional"), // TODO : Check reserved range (might behave like MemTiled)
RANGE_ENTRY(0xF0000000, 0xF3FFFFFF, MB( 64), PROT_UNH, SYSTEM_ALL | MAY_FAIL, "MemTiled Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?)"),
RANGE_ENTRY(0xFD000000, 0xFD6FFFFF, MB( 7), PROT_NAC, SYSTEM_ALL , "DeviceNV2A_a (GPU)"),
RANGE_ENTRY(0xFD700000, 0xFD7FFFFF, MB( 1), PROT_RW, SYSTEM_ALL , "MemNV2APRAMIN"),
RANGE_ENTRY(0xFD800000, 0xFDFFFFFF, MB( 8), PROT_NAC, SYSTEM_ALL , "DeviceNV2A_b (GPU)"),
RANGE_ENTRY(0xFE800000, 0xFE87FFFF, KB(512), PROT_NAC, SYSTEM_ALL , "DeviceAPU"),
RANGE_ENTRY(0xFEC00000, 0xFEC00FFF, KB( 4), PROT_NAC, SYSTEM_ALL , "DeviceAC97 (ACI)"),
RANGE_ENTRY(0xFED00000, 0xFED00FFF, KB( 4), PROT_NAC, SYSTEM_ALL , "DeviceUSB0"),
#ifdef INCLUDE_SYSTEM_ALPHA
RANGE_ENTRY(0xFED08000, 0xFED08FFF, KB( 4), PROT_NAC, SYSTEM_ALPHA | MAY_FAIL, "DeviceUSB1 Optional (won't be emulated for a long while?)"),
#endif
RANGE_ENTRY(0xFEF00000, 0xFEF003FF, KB( 1), PROT_NAC, SYSTEM_ALL , "DeviceNVNet"),
RANGE_ENTRY(0xFF000000, 0xFF3FFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_a (Flash mirror 1)"),
RANGE_ENTRY(0xFF400000, 0xFF7FFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_b (Flash mirror 2)"),
RANGE_ENTRY(0xFF800000, 0xFFBFFFFF, MB( 4), PROT_NAC, SYSTEM_ALL , "DeviceFlash_c (Flash mirror 3)"),
RANGE_ENTRY(0xFFC00000, 0xFFFFFFFF, MB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL, "DeviceFlash_d (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine"),
RANGE_ENTRY(0xFFFFFE00, 0xFFFFFFFF, 512 , PROT_NAC, SYSTEM_RETAIL | MAY_FAIL, "DeviceMCPX (not Chihiro, Xbox - if enabled) Optional (can safely be ignored)"),
#undef RANGE_ENTRY
};
extern bool AddressRangeMatchesFlags(const int index, const int flags);
extern bool IsOptionalAddressRange(const int index);
extern LPTSTR GetLastErrorString();
extern void FreeLastErrorString(LPTSTR Error);

View File

@ -0,0 +1,75 @@
// 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->LoaderTooling.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#include "AddressRanges.h"
bool AddressRangeMatchesFlags(const int index, const int flags)
{
return XboxAddressRanges[index].RangeFlags & flags;
}
bool IsOptionalAddressRange(const int index)
{
return AddressRangeMatchesFlags(index, MAY_FAIL);
}
LPTSTR GetLastErrorString()
{
DWORD err = GetLastError();
// Translate ErrorCode to String.
LPTSTR Error = nullptr;
if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
0,
(LPTSTR)&Error,
0,
NULL) == 0) {
// Failed in translating.
}
return Error;
}
void FreeLastErrorString(LPTSTR Error)
{
if (Error) {
::LocalFree(Error);
Error = nullptr;
}
}

View File

@ -0,0 +1,149 @@
// 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->ReserveAddressRanges.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#include "AddressRanges.h"
#ifdef DEBUG
// This array keeps track of which ranges have successfully been reserved.
// Having this helps debugging, but isn't strictly necessary, as we could
// retrieve the same information using VirtualQuery.
struct {
int Index;
unsigned __int32 Start;
int Size;
} ReservedRanges[128];
int ReservedRangeCount = 0;
#endif // DEBUG
// Reserve an address range up to the extend of what the host allows.
bool ReserveMemoryRange(int index)
{
unsigned __int32 Start = XboxAddressRanges[index].Start;
int Size = XboxAddressRanges[index].Size;
bool HadAnyFailure = false;
if (Start == 0) {
// The zero page (the entire first 64 KB block) can't be reserved (if we would
// try to reserve VirtualAlloc at address zero, it would hand us another address)
Start += BLOCK_SIZE;
Size -= BLOCK_SIZE;
HadAnyFailure = true;
}
#ifdef DEBUG
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Initialize the reservation of a new range
ReservedRanges[ReservedRangeCount].Index = index;
ReservedRanges[ReservedRangeCount].Start = Start;
ReservedRanges[ReservedRangeCount].Size = 0;
}
#endif // DEBUG
// Reserve this range in 64 Kb block increments, so that during emulation
// our memory-management code can VirtualFree() each block individually :
bool HadFailure = HadAnyFailure;
const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection;
while (Size > 0) {
SIZE_T BlockSize = (SIZE_T)(Size > BLOCK_SIZE) ? BLOCK_SIZE : Size;
LPVOID Result = VirtualAlloc((LPVOID)Start, BlockSize, MEM_RESERVE, Protect);
if (Result == NULL) {
HadFailure = true;
HadAnyFailure = true;
}
#ifdef DEBUG
else {
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
if (HadFailure) {
HadFailure = false;
// Starting a new range - did the previous one have any size?
if (ReservedRanges[ReservedRangeCount].Size > 0) {
// Then start a new range, and copy over the current type
ReservedRangeCount++;
ReservedRanges[ReservedRangeCount].Index = index;
}
// Register a new ranges starting address
ReservedRanges[ReservedRangeCount].Start = Start;
}
// Accumulate the size of each successfull reservation
ReservedRanges[ReservedRangeCount].Size += BlockSize;
}
}
#endif // DEBUG
// Handle the next block
Start += BLOCK_SIZE;
Size -= BLOCK_SIZE;
}
#ifdef DEBUG
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Keep the current block only if it contains a successfully reserved range
if (ReservedRanges[ReservedRangeCount].Size > 0) {
ReservedRangeCount++;
}
}
#endif // DEBUG
// Only a complete success when the entire request was reserved in a single range
// (Otherwise, we have either a complete failure, or reserved it partially over multiple ranges)
return !HadAnyFailure;
}
bool ReserveAddressRanges(const int system) {
// Loop over all Xbox address ranges
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
// Skip address ranges that don't match the given flags
if (!AddressRangeMatchesFlags(i, system))
continue;
// Try to reserve each address range
if (ReserveMemoryRange(i))
continue;
// Some ranges are allowed to fail reserving
if (!IsOptionalAddressRange(i)) {
return false;
}
}
return true;
}

View File

@ -0,0 +1,38 @@
// 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->ReserveAddressRanges.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
extern bool ReserveAddressRanges(const int system);

View File

@ -9,7 +9,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Common->XboxAddressRanges.cpp
// * Common->VerifyAddressRanges.cpp
// *
// * This file is part of the Cxbx project.
// *
@ -34,126 +34,7 @@
// *
// ******************************************************************
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h> // For DWORD, CALLBACK, VirtualAlloc, LPVOID, SIZE_T, HMODULE
#include "XboxAddressRanges.h"
typedef struct {
int Index;
unsigned __int32 Start;
int Size;
} ReservedRange;
// This array keeps track of which ranges have successfully been reserved.
// Having this helps debugging, but isn't strictly necessary, as we could
// retrieve the same information using VirtualQuery.
ReservedRange ReservedRanges[128];
int ReservedRangeCount = 0;
// Reserve an address range up to the extend of what the host allows.
bool ReserveMemoryRange(int index)
{
unsigned __int32 Start = XboxAddressRanges[index].Start;
int Size = XboxAddressRanges[index].Size;
bool HadAnyFailure = false;
if (Start == 0) {
// The zero page (the entire first 64 KB block) can't be reserved (if we would
// try to reserve VirtualAlloc at address zero, it would hand us another address)
Start += BLOCK_SIZE;
Size -= BLOCK_SIZE;
HadAnyFailure = true;
}
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Initialize the reservation of a new range
ReservedRanges[ReservedRangeCount].Index = index;
ReservedRanges[ReservedRangeCount].Start = Start;
ReservedRanges[ReservedRangeCount].Size = 0;
}
// Reserve this range in 64 Kb block increments, so later on our
// memory-management code can VirtualFree() each block individually :
bool HadFailure = HadAnyFailure;
const DWORD Protect = XboxAddressRanges[index].InitialMemoryProtection;
while (Size > 0) {
SIZE_T BlockSize = (SIZE_T)(Size > BLOCK_SIZE) ? BLOCK_SIZE : Size;
LPVOID Result = VirtualAlloc((LPVOID)Start, BlockSize, MEM_RESERVE, Protect);
if (Result == NULL) {
HadFailure = true;
HadAnyFailure = true;
}
else {
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
if (HadFailure) {
HadFailure = false;
// Starting a new range - did the previous one have any size?
if (ReservedRanges[ReservedRangeCount].Size > 0) {
// Then start a new range, and copy over the current type
ReservedRangeCount++;
ReservedRanges[ReservedRangeCount].Index = index;
}
// Register a new ranges starting address
ReservedRanges[ReservedRangeCount].Start = Start;
}
// Accumulate the size of each successfull reservation
ReservedRanges[ReservedRangeCount].Size += BlockSize;
}
}
// Handle the next block
Start += BLOCK_SIZE;
Size -= BLOCK_SIZE;
}
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Keep the current block only if it contains a successfully reserved range
if (ReservedRanges[ReservedRangeCount].Size > 0) {
ReservedRangeCount++;
}
}
// Only a complete success when the entire request was reserved in a single range
// (Otherwise, we have either a complete failure, or reserved it partially over multiple ranges)
return !HadAnyFailure;
}
bool AddressRangeMatchesFlags(const int index, const int flags)
{
return XboxAddressRanges[index].RangeFlags & flags;
}
bool IsOptionalAddressRange(const int index)
{
return AddressRangeMatchesFlags(index, MAY_FAIL);
}
bool ReserveAddressRanges(const int system) {
// Loop over all Xbox address ranges
for (int i = 0; i < ARRAY_SIZE(XboxAddressRanges); i++) {
// Skip address ranges that don't match the given flags
if (!AddressRangeMatchesFlags(i, system))
continue;
// Try to reserve each address range
if (ReserveMemoryRange(i))
continue;
// Some ranges are allowed to fail reserving
if (!IsOptionalAddressRange(i)) {
return false;
}
}
return true;
}
#include "AddressRanges.h"
bool VerifyAddressRange(int index)
{
@ -285,31 +166,3 @@ bool AllocateMemoryRange(const int index)
return true;
}
LPTSTR GetLastErrorString()
{
DWORD err = GetLastError();
// Translate ErrorCode to String.
LPTSTR Error = nullptr;
if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
0,
(LPTSTR)&Error,
0,
NULL) == 0) {
// Failed in translating.
}
return Error;
}
void FreeLastErrorString(LPTSTR Error)
{
if (Error) {
::LocalFree(Error);
Error = nullptr;
}
}

View File

@ -0,0 +1,40 @@
// 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->VerifyAddressRanges.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
extern bool VerifyAddressRanges(const int system);
extern void UnreserveMemoryRange(const int index);
extern bool AllocateMemoryRange(const int index);

View File

@ -1,109 +0,0 @@
// 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->XboxAddressRanges.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it 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-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#define KB(x) ((x) * 1024 ) // = 0x00000400
#define MB(x) ((x) * KB(1024)) // = 0x00100000
// Windows' address space allocation granularity;
// See https://blogs.msdn.microsoft.com/oldnewthing/20031008-00/?p=42223
const int BLOCK_SIZE = KB(64);
// One allocation block consists of 16 pages (since PAGE_SIZE is 4 kilobytes)
const int PAGE_SIZE = KB(4);
#define ARRAY_SIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
typedef struct {
const char *Name;
unsigned __int32 Start;
int Size;
DWORD InitialMemoryProtection; // Memory page protection, for use by VirtualAlloc
unsigned int RangeFlags;
} XboxAddressRange;
// Shortend symbol aliasses for memory page protection
#define PROT_UNH 0 // UNHANDLED
#define PROT_RW PAGE_READWRITE
#define PROT_XRW PAGE_EXECUTE_READWRITE
#define PROT_NAC PAGE_NOACCESS
// Range flags (used for system selection and optional marker)
#define SYSTEM_XBOX (1 << 0)
#define SYSTEM_DEVKIT (1 << 1)
#define SYSTEM_CHIHIRO (1 << 2)
#define MAY_FAIL (1 << 3) // Optional (may fail address range reservation)
// Short-hand for sets of system configurations
#define SYSTEM_ALL (SYSTEM_XBOX | SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
#define SYSTEM_RETAIL (SYSTEM_XBOX | SYSTEM_DEVKIT )
#define SYSTEM_128MB ( SYSTEM_DEVKIT | SYSTEM_CHIHIRO)
const XboxAddressRange XboxAddressRanges[] = {
// See http://xboxdevwiki.net/Memory
// and http://xboxdevwiki.net/Boot_Process#Paging
{ "MemLowVirtual", 0x00000000, MB( 64), PROT_XRW, SYSTEM_XBOX | MAY_FAIL }, // - 0x07FFFFFF (Retail Xbox) Optional (already reserved via virtual_memory_placeholder)
{ "MemLowVirtual", 0x00000000, MB(128), PROT_XRW, SYSTEM_128MB | MAY_FAIL }, // - 0x07FFFFFF (Chihiro / DevKit)
{ "MemPhysical", 0x80000000, MB( 64), PROT_XRW, SYSTEM_XBOX }, // - 0x87FFFFFF (Retail)
{ "MemPhysical", 0x80000000, MB(128), PROT_XRW, SYSTEM_128MB }, // - 0x87FFFFFF (Chihiro / DevKit)
{ "DevKitMemory", 0xB0000000, MB(128), PROT_NAC, SYSTEM_DEVKIT }, // - 0xBFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled) + Flag [O]ptional?
{ "MemPageTable", 0xC0000000, KB(128), PROT_RW, SYSTEM_ALL }, // - 0xC001FFFF TODO : MB(4)?
{ "SystemMemory", 0xD0000000, MB(512), PROT_UNH, SYSTEM_ALL | MAY_FAIL }, // - 0xEFFFFFFF Optional (TODO : Check reserved range (might behave like MemTiled)
{ "MemTiled", 0xF0000000, MB( 64), PROT_UNH, SYSTEM_ALL | MAY_FAIL }, // - 0xF3FFFFFF Optional (even though it can't be reserved, MapViewOfFileEx to this range still works!?)
{ "DeviceNV2A_a", 0xFD000000, MB( 7), PROT_NAC, SYSTEM_ALL }, // - 0xFD6FFFFF (GPU)
{ "MemNV2APRAMIN", 0xFD700000, MB( 1), PROT_RW, SYSTEM_ALL }, // - 0xFD7FFFFF
{ "DeviceNV2A_b", 0xFD800000, MB( 8), PROT_NAC, SYSTEM_ALL }, // - 0xFDFFFFFF (GPU)
{ "DeviceAPU", 0xFE800000, KB(512), PROT_NAC, SYSTEM_ALL }, // - 0xFE87FFFF
{ "DeviceAC97", 0xFEC00000, KB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFEC00FFF (ACI)
{ "DeviceUSB0", 0xFED00000, KB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFED00FFF
{ "DeviceUSB1", 0xFED08000, KB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL }, // - 0xFED08FFF Optional (won't be emulated for a long while?)
{ "DeviceNVNet", 0xFEF00000, KB( 1), PROT_NAC, SYSTEM_ALL }, // - 0xFEF003FF
{ "DeviceFlash_a", 0xFF000000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFF3FFFFF (Flash mirror 1)
{ "DeviceFlash_b", 0xFF400000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFF7FFFFF (Flash mirror 2)
{ "DeviceFlash_c", 0xFF800000, MB( 4), PROT_NAC, SYSTEM_ALL }, // - 0xFFBFFFFF (Flash mirror 3)
{ "DeviceFlash_d", 0xFFC00000, MB( 4), PROT_NAC, SYSTEM_ALL | MAY_FAIL }, // - 0xFFFFFFFF (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine
{ "DeviceMCPX", 0xFFFFFE00, 512 , PROT_NAC, SYSTEM_RETAIL | MAY_FAIL }, // - 0xFFFFFFFF (not Chihiro, Xbox - if enabled) Optional (can safely be ignored)
};
extern bool ReserveAddressRanges(const int system);
extern bool VerifyAddressRanges(const int system);
extern void UnreserveMemoryRange(const int index);
extern bool AllocateMemoryRange(const int index);
extern LPTSTR GetLastErrorString();
extern void FreeLastErrorString(LPTSTR Error);