Begin implementing Xbe Loader
This commit is contained in:
parent
517d411452
commit
72d9fecd12
|
@ -105,11 +105,11 @@ Xbe::Xbe(const char *x_szFilename)
|
|||
{
|
||||
printf("Xbe::Xbe: Reading Image Header Extra Bytes...");
|
||||
|
||||
uint32 ExSize = RoundUp(m_Header.dwSizeofHeaders, 0x1000) - sizeof(m_Header);
|
||||
m_ExSize = RoundUp(m_Header.dwSizeofHeaders, 0x1000) - sizeof(m_Header);
|
||||
|
||||
m_HeaderEx = new char[ExSize];
|
||||
m_HeaderEx = new char[m_ExSize];
|
||||
|
||||
if(fread(m_HeaderEx, ExSize, 1, XbeFile) != 1)
|
||||
if(fread(m_HeaderEx, m_ExSize, 1, XbeFile) != 1)
|
||||
{
|
||||
SetError("Unexpected end of file while reading Xbe Image Header (Ex)", true);
|
||||
goto cleanup;
|
||||
|
|
|
@ -117,6 +117,7 @@ class Xbe : public Error
|
|||
|
||||
// Xbe header extra byte (used to preserve unknown data)
|
||||
char *m_HeaderEx;
|
||||
uint32 m_ExSize;
|
||||
|
||||
// Xbe certificate
|
||||
#include "AlignPrefix1.h"
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "CxbxKrnl/Emu.h"
|
||||
#include "CxbxKrnl/EmuShared.h"
|
||||
|
||||
unsigned char memory[XBOX_MEMORY_SIZE];
|
||||
|
||||
/*! program entry point */
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
|
@ -50,6 +52,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (__argc >= 2 && strcmp(__argv[1], "/load") == 0 && strlen(__argv[2]) > 0) {
|
||||
CxbxKrnlMain(__argc, __argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! initialize shared memory */
|
||||
EmuShared::Init();
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
/**
|
||||
* Silly little hack to fix link error with libjpeg on MSVC 2015
|
||||
*/
|
||||
FILE _iob[] = { *stdin, *stdout, *stderr };
extern "C" FILE * __cdecl __iob_func(void) { return _iob; }
|
||||
FILE _iob[] = { *stdin, *stdout, *stderr };
|
||||
extern "C" FILE * __cdecl __iob_func(void) { return _iob; }
|
||||
|
||||
WndMain::WndMain(HINSTANCE x_hInstance) : Wnd(x_hInstance), m_bCreated(false), m_Xbe(0), m_Exe(0), m_bExeChanged(false), m_bXbeChanged(false), m_bCanStart(true), m_hwndChild(NULL), m_AutoConvertToExe(AUTO_CONVERT_WINDOWS_TEMP), m_KrnlDebug(DM_NONE), m_CxbxDebug(DM_NONE), m_dwRecentXbe(0), m_dwRecentExe(0)
|
||||
{
|
||||
|
@ -1832,45 +1833,6 @@ void WndMain::StartEmulation(EnumAutoConvert x_AutoConvert, HWND hwndParent)
|
|||
{
|
||||
char szBuffer[260];
|
||||
|
||||
// convert xbe to exe, if necessary
|
||||
if(m_ExeFilename[0] == '\0' || m_bExeChanged)
|
||||
{
|
||||
if(x_AutoConvert == AUTO_CONVERT_WINDOWS_TEMP)
|
||||
{
|
||||
char szTempPath[260];
|
||||
|
||||
GetTempPath(259, szTempPath);
|
||||
|
||||
SuggestFilename(m_XbeFilename, szBuffer, ".exe");
|
||||
|
||||
int v=0, c=0;
|
||||
|
||||
while(szBuffer[v] != '\0')
|
||||
{
|
||||
if(szBuffer[v] == '\\')
|
||||
c = v+1;
|
||||
v++;
|
||||
}
|
||||
|
||||
strcat(szTempPath, &szBuffer[c]);
|
||||
|
||||
if(!ConvertToExe(szTempPath, false, hwndParent))
|
||||
return;
|
||||
}
|
||||
else if(x_AutoConvert == AUTO_CONVERT_XBE_PATH)
|
||||
{
|
||||
SuggestFilename(m_XbeFilename, szBuffer, ".exe");
|
||||
|
||||
if(!ConvertToExe(szBuffer, false, hwndParent))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!ConvertToExe(NULL, true, hwndParent))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// register xbe path with CxbxKrnl.dll
|
||||
g_EmuShared->SetXbePath(m_Xbe->m_szPath);
|
||||
|
||||
|
@ -1890,10 +1852,12 @@ void WndMain::StartEmulation(EnumAutoConvert x_AutoConvert, HWND hwndParent)
|
|||
if(spot != -1)
|
||||
szBuffer[spot] = '\0';
|
||||
|
||||
// std::string args = "/load " + std::string("\"") + std::string(m_Xbe->m_szPath) + std::string(itoa(0));
|
||||
|
||||
if((int)ShellExecute(NULL, "open", m_ExeFilename, NULL, szBuffer, SW_SHOWDEFAULT) <= 32)
|
||||
{
|
||||
m_bCanStart = true;
|
||||
MessageBox(m_hwnd, "Emulation failed.\n\nTry converting again. If this message repeats, the Xbe is not supported.", "Cxbx", MB_ICONSTOP | MB_OK);
|
||||
MessageBox(m_hwnd, "Emulation failed.\n\n If this message repeats, the Xbe is not supported.", "Cxbx", MB_ICONSTOP | MB_OK);
|
||||
|
||||
printf("WndMain: %s shell failed.\n", m_Xbe->m_szAsciiTitle);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = { 0 };
|
|||
|
||||
std::string CxbxBasePath;
|
||||
HANDLE CxbxBasePathHandle;
|
||||
Exe* CxbxKrnl_Exe = NULL;
|
||||
Xbe* CxbxKrnl_Xbe = NULL;
|
||||
|
||||
DWORD_PTR g_CPUXbox = 0;
|
||||
DWORD_PTR g_CPUOthers = 0;
|
||||
|
@ -214,6 +214,80 @@ void CxbxLaunchXbe(void(*Entry)())
|
|||
|
||||
}
|
||||
|
||||
extern "C" CXBXKRNL_API void CxbxKrnlMain(int argc, char* argv[])
|
||||
{
|
||||
std::string xbePath = argv[2];
|
||||
|
||||
MessageBoxA(NULL, xbePath.c_str(), "", 0);
|
||||
HWND hWnd = (HWND)StrToInt(argv[3]);
|
||||
DebugMode DbgMode = (DebugMode)StrToInt(argv[4]);
|
||||
std::string DebugFileName = argv[5];
|
||||
|
||||
// Backup the area of the EXE required for WinAPI
|
||||
Exe::DOSHeader* header = (Exe::DOSHeader*)0x10000;
|
||||
DWORD magic = header->m_magic;
|
||||
DWORD lfaNew = header->m_lfanew;
|
||||
|
||||
DWORD OldProtection;
|
||||
VirtualProtect((void*)0x10000, XBOX_MEMORY_SIZE, PAGE_EXECUTE_READWRITE, &OldProtection);
|
||||
ZeroMemory((void*)0x10000, XBOX_MEMORY_SIZE);
|
||||
|
||||
g_EmuShared->SetXbePath(xbePath.c_str());
|
||||
|
||||
CxbxKrnl_Xbe = new Xbe(xbePath.c_str());
|
||||
|
||||
// Load Xbe Headers
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header));
|
||||
memcpy((void*)(CxbxKrnl_Xbe->m_Header.dwBaseAddr + sizeof(Xbe::Header)), CxbxKrnl_Xbe->m_HeaderEx, CxbxKrnl_Xbe->m_ExSize);
|
||||
|
||||
// Load Sections
|
||||
for (int i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
|
||||
memcpy((void*)CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr, CxbxKrnl_Xbe->m_bzSection[i], CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw);
|
||||
}
|
||||
|
||||
// Fixup Kernel Imports
|
||||
uint32 kt = CxbxKrnl_Xbe->m_Header.dwKernelImageThunkAddr;
|
||||
|
||||
if ((kt ^ XOR_KT_DEBUG) > 0x01000000)
|
||||
kt ^= XOR_KT_RETAIL;
|
||||
else
|
||||
kt ^= XOR_KT_DEBUG;
|
||||
|
||||
uint32_t* kt_tbl = (uint32_t*)kt;
|
||||
|
||||
int i = 0;
|
||||
while (kt_tbl[i] != 0) {
|
||||
int t = kt_tbl[i] & 0x7FFFFFFF;
|
||||
kt_tbl[i] = CxbxKrnl_KernelThunkTable[t];
|
||||
i++;
|
||||
}
|
||||
|
||||
// Load TLS
|
||||
Xbe::TLS* XbeTls = (Xbe::TLS*)CxbxKrnl_Xbe->m_Header.dwTLSAddr;
|
||||
void* XbeTlsData = nullptr;
|
||||
|
||||
if (XbeTls != nullptr) {
|
||||
XbeTlsData = (void*)CxbxKrnl_Xbe->m_TLS->dwDataStartAddr;
|
||||
}
|
||||
|
||||
// Decode Entry Point
|
||||
uint32_t EntryPoint = CxbxKrnl_Xbe->m_Header.dwEntryAddr;
|
||||
if ((EntryPoint ^ XOR_EP_DEBUG) > 0x01000000)
|
||||
EntryPoint ^= XOR_EP_RETAIL;
|
||||
else
|
||||
EntryPoint ^= XOR_EP_DEBUG;
|
||||
|
||||
// Restore the area of the EXE required for WinAPI
|
||||
header->m_magic = magic;
|
||||
header->m_lfanew = lfaNew;
|
||||
|
||||
// Launch XBE
|
||||
CxbxKrnlInit(
|
||||
hWnd, XbeTlsData, XbeTls, CxbxKrnl_Xbe->m_LibraryVersion, DbgMode,
|
||||
DebugFileName.c_str(), &CxbxKrnl_Xbe->m_Header, CxbxKrnl_Xbe->m_Header.dwSizeofHeaders, (void(*)())EntryPoint
|
||||
);
|
||||
}
|
||||
|
||||
extern "C" CXBXKRNL_API void CxbxKrnlInit
|
||||
(
|
||||
HWND hwndParent,
|
||||
|
@ -221,7 +295,7 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
|
|||
Xbe::TLS *pTLS,
|
||||
Xbe::LibraryVersion *pLibraryVersion,
|
||||
DebugMode DbgMode,
|
||||
char *szDebugFilename,
|
||||
const char *szDebugFilename,
|
||||
Xbe::Header *pXbeHeader,
|
||||
uint32 dwXbeHeaderSize,
|
||||
void(*Entry)())
|
||||
|
@ -357,13 +431,6 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
|
|||
((Xbe::Certificate*)pXbeHeader->dwCertificateAddr)->dwAllowedMedia |= 0x00FFFFFF;
|
||||
}
|
||||
|
||||
// Load EXE structure, this is used by Xapi Section functions
|
||||
{
|
||||
char szBuffer[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, szBuffer, MAX_PATH);
|
||||
CxbxKrnl_Exe = new Exe(szBuffer);
|
||||
}
|
||||
|
||||
// Initialize devices :
|
||||
char szBuffer[260];
|
||||
SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_APPDATA, TRUE);
|
||||
|
@ -477,19 +544,27 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
|
|||
}
|
||||
|
||||
|
||||
DbgPrintf("EmuMain : Determining CPU affinity.");
// Make sure the Xbox1 code runs on one core (as the box itself has only 1 CPU,
|
||||
DbgPrintf("EmuMain : Determining CPU affinity.");
|
||||
|
||||
// Make sure the Xbox1 code runs on one core (as the box itself has only 1 CPU,
|
||||
// this will better aproximate the environment with regard to multi-threading) :
|
||||
{
GetProcessAffinityMask(GetCurrentProcess(), &g_CPUXbox, &g_CPUOthers);
|
||||
{
|
||||
GetProcessAffinityMask(GetCurrentProcess(), &g_CPUXbox, &g_CPUOthers);
|
||||
// For the other threads, remove one bit from the processor mask:
|
||||
g_CPUOthers = ((g_CPUXbox - 1) & g_CPUXbox);
|
||||
|
||||
// Test if there are any other cores available :
|
||||
if (g_CPUOthers > 0) {
|
||||
// If so, make sure the Xbox threads run on the core NOT running Xbox code :
|
||||
g_CPUXbox = g_CPUXbox & (~g_CPUOthers);
} else {
// Else the other threads must run on the same core as the Xbox code :
|
||||
g_CPUOthers = g_CPUXbox;
}
|
||||
g_CPUXbox = g_CPUXbox & (~g_CPUOthers);
|
||||
} else {
|
||||
// Else the other threads must run on the same core as the Xbox code :
|
||||
g_CPUOthers = g_CPUXbox;
|
||||
}
|
||||
|
||||
// Make sure Xbox1 code runs on one core :
|
||||
SetThreadAffinityMask(GetCurrentThread(), g_CPUXbox);
}
|
||||
SetThreadAffinityMask(GetCurrentThread(), g_CPUXbox);
|
||||
}
|
||||
|
||||
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());
|
||||
|
||||
|
|
|
@ -46,11 +46,16 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XBOX_MEMORY_SIZE 128 * 1024 * 1024
|
||||
|
||||
/*! validate version string match */
|
||||
CXBXKRNL_API bool CxbxKrnlVerifyVersion(const char *szVersion);
|
||||
|
||||
/*! Cxbx Kernel Entry Point */
|
||||
CXBXKRNL_API void CxbxKrnlMain(int argc, char* argv[]);
|
||||
|
||||
/*! initialize emulation */
|
||||
CXBXKRNL_API void CxbxKrnlInit(HWND hwndParent, void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, char *szDebugFilename, Xbe::Header *XbeHeader, uint32 XbeHeaderSize, void (*Entry)());
|
||||
CXBXKRNL_API void CxbxKrnlInit(HWND hwndParent, void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, const char *szDebugFilename, Xbe::Header *XbeHeader, uint32 XbeHeaderSize, void (*Entry)());
|
||||
|
||||
/*! cleanup emulation */
|
||||
CXBXKRNL_API void CxbxKrnlCleanup(const char *szErrorMessage, ...);
|
||||
|
@ -85,7 +90,7 @@ extern CXBXKRNL_API void *CxbxKrnl_TLSData;
|
|||
/*! xbe header structure */
|
||||
extern CXBXKRNL_API Xbe::Header *CxbxKrnl_XbeHeader;
|
||||
|
||||
extern Exe* CxbxKrnl_Exe;
|
||||
extern Xbe *CxbxKrnl_Xbe;
|
||||
|
||||
/*! parent window handle */
|
||||
extern CXBXKRNL_API HWND CxbxKrnl_hEmuParent;
|
||||
|
|
|
@ -284,16 +284,16 @@ void EmuInitFS()
|
|||
long numberOfInstructions = fsInstructions.size();
|
||||
|
||||
// Iterate through each CODE section
|
||||
for (int sectionIndex = 0; sectionIndex < CxbxKrnl_Exe->m_Header.m_sections; sectionIndex++) {
|
||||
if (CxbxKrnl_Exe->m_SectionHeader[sectionIndex].m_characteristics & IMAGE_SCN_CNT_CODE != IMAGE_SCN_CNT_CODE) {
|
||||
for (int sectionIndex = 0; sectionIndex < CxbxKrnl_Xbe->m_Header.dwSections; sectionIndex++) {
|
||||
if (!CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwFlags.bExecutable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string sectionName(CxbxKrnl_Exe->m_SectionHeader[sectionIndex].m_name, 8);
|
||||
std::string sectionName(CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwSectionNameAddr, 8);
|
||||
|
||||
DbgPrintf("Searching for FS Instruction in section %s\n", sectionName.c_str());
|
||||
uint32_t startAddr = CxbxKrnl_Exe->m_SectionHeader[sectionIndex].m_virtual_addr + CxbxKrnl_XbeHeader->dwBaseAddr;
|
||||
uint32_t endAddr = startAddr + CxbxKrnl_Exe->m_SectionHeader[sectionIndex].m_sizeof_raw;
|
||||
uint32_t startAddr = CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwVirtualAddr + CxbxKrnl_XbeHeader->dwBaseAddr;
|
||||
uint32_t endAddr = startAddr + CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwSizeofRaw;
|
||||
for (uint32 addr = startAddr; addr < endAddr; addr++)
|
||||
{
|
||||
for (int i = 0; i < numberOfInstructions; i++)
|
||||
|
|
|
@ -976,15 +976,13 @@ HANDLE WINAPI XTL::EmuXGetSectionHandleA
|
|||
void* pRet = NULL;
|
||||
|
||||
// Iterate thrugh sections
|
||||
for (int i = 0; i < CxbxKrnl_Exe->m_Header.m_sections; i++) {
|
||||
if (!strncmp(pSectionName, CxbxKrnl_Exe->m_SectionHeader[i].m_name, 8)) {
|
||||
pRet = (void*)(CxbxKrnl_Exe->m_SectionHeader[i].m_virtual_addr + CxbxKrnl_XbeHeader->dwBaseAddr);
|
||||
for (int i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
|
||||
if (!strncmp(pSectionName, (char*)CxbxKrnl_Xbe->m_SectionHeader[i].dwSectionNameAddr, 8)) {
|
||||
pRet = (void*)(CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr + CxbxKrnl_XbeHeader->dwBaseAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (LPVOID) pRet;
|
||||
}
|
||||
|
||||
|
@ -1054,14 +1052,13 @@ DWORD WINAPI XTL::EmuXGetSectionSize
|
|||
|
||||
|
||||
// Iterate thrugh sections
|
||||
for (int i = 0; i < CxbxKrnl_Exe->m_Header.m_sections; i++) {
|
||||
if ((HANDLE)(CxbxKrnl_Exe->m_SectionHeader[i].m_virtual_addr + CxbxKrnl_XbeHeader->dwBaseAddr) == hSection) {
|
||||
return CxbxKrnl_Exe->m_SectionHeader[i].m_sizeof_raw;
|
||||
for (int i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
|
||||
if ((HANDLE)(CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr + CxbxKrnl_XbeHeader->dwBaseAddr) == hSection) {
|
||||
return CxbxKrnl_Xbe->m_SectionHeader[i].dwRawAddr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
EmuWarning("EmuXApi : EmuXGetSectionSize : Could not determine section size: %x08X", hSection);
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue