Cxbx-Reloaded/Source/Win32/CxbxKrnl/Emu.cpp

536 lines
18 KiB
C++
Raw Normal View History

// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
2003-03-27 06:23:58 +00:00
// * Cxbx->Win32->CxbxKrnl->Emu.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) 2002-2003 Aaron Robinson <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
2003-03-07 22:01:44 +00:00
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_LOCAL_
2003-03-07 22:01:44 +00:00
// ******************************************************************
// * prevent name collisions
// ******************************************************************
2003-04-02 02:23:30 +00:00
namespace xboxkrnl
{
2003-04-02 02:23:30 +00:00
#include <xboxkrnl/xboxkrnl.h>
};
2003-04-02 02:23:30 +00:00
#include "Emu.h"
#include "EmuFS.h"
#include "EmuD3D8.h"
2003-04-26 04:32:46 +00:00
#include "EmuKrnl.h"
#include "EmuShared.h"
2003-04-02 02:23:30 +00:00
#include "HLEDataBase.h"
2003-04-06 20:07:36 +00:00
#include <math.h>
2003-03-27 05:56:08 +00:00
// ******************************************************************
2003-03-27 06:33:57 +00:00
// * global / static
// ******************************************************************
2003-03-27 06:23:58 +00:00
static void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, void (*Entry)(), Xbe::Header *XbeHeader);
2003-04-08 03:34:05 +00:00
extern uint32 g_TlsAdjust = 0;
2003-04-06 00:25:30 +00:00
2003-03-27 05:56:08 +00:00
// ******************************************************************
// * func: DllMain
// ******************************************************************
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
2003-04-04 03:31:43 +00:00
EmuShared::Init();
2003-03-27 05:56:08 +00:00
if(fdwReason == DLL_PROCESS_DETACH)
2003-04-04 03:31:43 +00:00
EmuShared::Cleanup();
2003-03-27 05:56:08 +00:00
return TRUE;
}
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuNoFunc
// ******************************************************************
2003-04-02 02:23:30 +00:00
extern "C" CXBXKRNL_API void NTAPI EmuNoFunc()
2003-03-27 06:23:58 +00:00
{
EmuSwapFS(); // Win2k/XP FS
printf("Emu (0x%.08X): EmuNoFunc()\n", GetCurrentThreadId());
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuInit
// ******************************************************************
2003-04-06 00:25:30 +00:00
extern "C" CXBXKRNL_API void NTAPI EmuInit(uint32 TlsAdjust, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, char *szDebugFilename, Xbe::Header *XbeHeader, uint32 XbeHeaderSize, void (*Entry)())
{
2003-04-06 00:25:30 +00:00
g_TlsAdjust = TlsAdjust;
// ******************************************************************
// * debug console allocation (if configured)
// ******************************************************************
2003-04-04 04:35:00 +00:00
if(DbgMode == DM_CONSOLE)
{
if(AllocConsole())
{
freopen("CONOUT$", "wt", stdout);
2003-02-15 08:56:40 +00:00
SetConsoleTitle("Cxbx : Kernel Debug Console");
2003-02-09 09:11:52 +00:00
2003-02-09 09:40:37 +00:00
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
2003-03-28 20:14:48 +00:00
printf("CxbxKrnl (0x%.08X): Debug console allocated (DM_CONSOLE).\n", GetCurrentThreadId());
}
}
2003-04-04 04:35:00 +00:00
else if(DbgMode == DM_FILE)
{
FreeConsole();
2003-04-04 04:35:00 +00:00
freopen(szDebugFilename, "wt", stdout);
2003-03-28 20:14:48 +00:00
printf("Emu (0x%.08X): Debug console allocated (DM_FILE).\n", GetCurrentThreadId());
}
2003-04-15 08:08:53 +00:00
else
{
FreeConsole();
freopen("NUL", "wt", stdout);
}
// ******************************************************************
// * debug trace
// ******************************************************************
{
2003-03-28 20:14:48 +00:00
#ifdef _DEBUG_TRACE
printf("CxbxKrnl (0x%.08X): _DEBUG_TRACE enabled.\n", GetCurrentThreadId());
2003-03-27 06:23:58 +00:00
printf("Emu: EmuInit\n"
2003-02-09 08:35:33 +00:00
"(\n"
2003-04-06 00:25:30 +00:00
" TlsAdjust : 0x%.08X\n"
2003-02-19 20:53:33 +00:00
" LibraryVersion : 0x%.08X\n"
2003-02-09 08:35:33 +00:00
" DebugConsole : 0x%.08X\n"
" DebugFilename : \"%s\"\n"
" XBEHeader : 0x%.08X\n"
" XBEHeaderSize : 0x%.08X\n"
" Entry : 0x%.08X\n"
");\n",
2003-04-06 00:25:30 +00:00
TlsAdjust, LibraryVersion, DbgMode, szDebugFilename, XbeHeader, XbeHeaderSize, Entry);
2003-03-28 20:14:48 +00:00
#else
printf("CxbxKrnl (0x%.08X): _DEBUG_TRACE disabled.\n", GetCurrentThreadId());
#endif
}
// ******************************************************************
2003-04-08 03:34:05 +00:00
// * Load the necessary pieces of XBEHeader
// ******************************************************************
{
2003-04-08 03:34:05 +00:00
Xbe::Header *MemXbeHeader = (Xbe::Header*)0x00010000;
uint32 old_protection = 0;
VirtualProtect(MemXbeHeader, 0x1000, PAGE_READWRITE, &old_protection);
// we sure hope we aren't corrupting anything necessary for an .exe to survive :]
MemXbeHeader->dwSizeofHeaders = XbeHeader->dwSizeofHeaders;
MemXbeHeader->dwCertificateAddr = XbeHeader->dwCertificateAddr;
MemXbeHeader->dwPeHeapReserve = XbeHeader->dwPeHeapReserve;
MemXbeHeader->dwPeHeapCommit = XbeHeader->dwPeHeapCommit;
memcpy(&MemXbeHeader->dwInitFlags, &XbeHeader->dwInitFlags, sizeof(XbeHeader->dwInitFlags));
memcpy((void*)XbeHeader->dwCertificateAddr, &((uint08*)XbeHeader)[XbeHeader->dwCertificateAddr - 0x00010000], sizeof(Xbe::Certificate));
}
// ******************************************************************
// * Initialize all components
// ******************************************************************
{
EmuInitFS();
EmuGenerateFS(TlsAdjust);
}
// ******************************************************************
// * Initialize OpenXDK emulation
// ******************************************************************
if(LibraryVersion == 0)
{
printf("Emu: Detected OpenXDK application...\n");
}
// ******************************************************************
// * Initialize Microsoft XDK emulation
// ******************************************************************
if(LibraryVersion != 0)
{
printf("Emu: Detected Microsoft XDK application...\n");
2003-02-19 20:53:33 +00:00
uint32 dwLibraryVersions = XbeHeader->dwLibraryVersions;
uint32 dwHLEEntries = HLEDataBaseSize/sizeof(HLEData);
2003-02-15 22:48:07 +00:00
2003-02-19 20:53:33 +00:00
for(uint32 v=0;v<dwLibraryVersions;v++)
{
2003-02-22 07:49:02 +00:00
uint16 MajorVersion = LibraryVersion[v].wMajorVersion;
uint16 MinorVersion = LibraryVersion[v].wMinorVersion;
uint16 BuildVersion = LibraryVersion[v].wBuildVersion;
2003-02-19 20:53:33 +00:00
char szLibraryName[9] = {0};
for(uint32 c=0;c<8;c++)
szLibraryName[c] = LibraryVersion[v].szName[c];
2003-03-27 06:23:58 +00:00
printf("Emu: Locating HLE Information for %s %d.%d.%d...", szLibraryName, MajorVersion, MinorVersion, BuildVersion);
2003-02-19 20:53:33 +00:00
bool found=false;
2003-02-22 07:49:02 +00:00
2003-02-19 20:53:33 +00:00
for(uint32 d=0;d<dwHLEEntries;d++)
{
2003-02-22 07:49:02 +00:00
if
(
BuildVersion != HLEDataBase[d].BuildVersion ||
MinorVersion != HLEDataBase[d].MinorVersion ||
MajorVersion != HLEDataBase[d].MajorVersion ||
strcmp(szLibraryName, HLEDataBase[d].Library) != 0
)
continue;
2003-02-15 22:48:07 +00:00
2003-02-19 20:53:33 +00:00
found = true;
2003-02-22 07:49:02 +00:00
2003-02-19 20:53:33 +00:00
printf("Found\n");
2003-03-27 06:23:58 +00:00
EmuInstallWrappers(HLEDataBase[d].OovpaTable, HLEDataBase[d].OovpaTableSize, Entry, XbeHeader);
2003-02-19 20:53:33 +00:00
}
if(!found)
printf("Skipped\n");
}
2003-04-08 03:34:05 +00:00
2003-04-16 19:06:20 +00:00
EmuD3DInit(XbeHeader, XbeHeaderSize);
}
2003-04-08 03:34:05 +00:00
printf("Emu (0x%.08X): Initial thread starting.\n", GetCurrentThreadId());
// ******************************************************************
2003-04-08 03:34:05 +00:00
// * Entry Point
// ******************************************************************
2003-04-08 03:34:05 +00:00
__try
{
2003-04-08 03:34:05 +00:00
EmuSwapFS(); // XBox FS
2003-04-08 03:34:05 +00:00
Entry();
2003-04-08 03:34:05 +00:00
EmuSwapFS(); // Win2k/XP FS
}
2003-04-08 03:34:05 +00:00
__except(EmuException(GetExceptionInformation()))
{
2003-04-08 03:34:05 +00:00
printf("Emu: WARNING!! Problem with ExceptionFilter\n");
}
2003-03-27 06:23:58 +00:00
printf("Emu (0x%.08X): Initial thread ended.\n", GetCurrentThreadId());
fflush(stdout);
return;
}
2003-04-26 07:30:21 +00:00
// ******************************************************************
// * func: EmuCleanThread
// ******************************************************************
static __declspec(naked) void EmuCleanThread()
{
if(EmuIsXboxFS())
EmuSwapFS(); // Win2k/XP FS
EmuCleanupFS();
ExitThread(0);
}
2003-04-16 19:06:20 +00:00
// ******************************************************************
// * func: EmuCleanup
// ******************************************************************
2003-04-26 04:32:46 +00:00
extern "C" CXBXKRNL_API void NTAPI EmuCleanup(const char *szErrorMessage)
2003-04-16 19:06:20 +00:00
{
if(EmuIsXboxFS())
EmuSwapFS(); // Win2k/XP FS
2003-04-26 04:32:46 +00:00
// ******************************************************************
// * Suspend all Threads
// ******************************************************************
while(true)
{
2003-04-26 07:30:21 +00:00
ThreadList *tl = ThreadList::pFirst;
2003-04-26 04:32:46 +00:00
if(tl == NULL)
break;
SuspendThread(tl->hThread);
2003-04-26 07:30:21 +00:00
CONTEXT Context;
Context.ContextFlags = CONTEXT_CONTROL;
Context.Eip = (DWORD)EmuCleanThread;
SetThreadContext(tl->hThread, &Context);
ResumeThread(tl->hThread);
DWORD dwTerm = 0;
while(GetExitCodeThread(tl->hThread, &dwTerm) == 0)
Sleep(50);
ThreadList::pFirst = tl->pNext;
2003-04-26 04:32:46 +00:00
delete tl;
}
// ******************************************************************
// * Print out ErrorMessage (if exists)
// ******************************************************************
if(szErrorMessage != NULL)
{
char buffer[255];
sprintf(buffer, "CxbxKrnl: Recieved Exception \"%s\"\n", szErrorMessage);
printf("%s", buffer);
MessageBox(NULL, buffer, "CxbxKrnl", MB_OK | MB_ICONEXCLAMATION);
}
printf("CxbxKrnl: Terminating Process\n");
2003-04-26 07:30:21 +00:00
EmuCleanThread();
2003-04-16 19:06:20 +00:00
return;
}
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuPanic
// ******************************************************************
2003-04-02 02:23:30 +00:00
extern "C" CXBXKRNL_API void NTAPI EmuPanic()
{
2003-04-12 11:21:35 +00:00
if(EmuIsXboxFS())
EmuSwapFS(); // Win2k/XP FS
2003-03-27 06:23:58 +00:00
printf("Emu (0x%.08X): EmuPanic()\n", GetCurrentThreadId());
2003-02-21 00:07:28 +00:00
#ifdef _DEBUG_TRACE
MessageBox(NULL, "Kernel Panic! Process will now terminate.\n\n"
"Check debug traces for hints on the cause of this crash.", "CxbxKrnl", MB_OK | MB_ICONEXCLAMATION);
#else
MessageBox(NULL, "Kernel Panic! Process will now terminate.", "CxbxKrnl", MB_OK | MB_ICONEXCLAMATION);
2003-02-21 00:07:28 +00:00
#endif
2003-04-12 11:21:35 +00:00
2003-04-26 04:32:46 +00:00
EmuCleanup("Kernel Panic!");
2003-04-12 11:21:35 +00:00
2003-03-27 06:23:58 +00:00
EmuSwapFS(); // XBox FS
}
2003-02-09 08:35:33 +00:00
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuInstallWrapper
2003-02-09 08:35:33 +00:00
// ******************************************************************
2003-03-27 06:23:58 +00:00
inline void EmuInstallWrapper(void *FunctionAddr, void *WrapperAddr)
2003-02-09 08:35:33 +00:00
{
uint08 *FuncBytes = (uint08*)FunctionAddr;
*(uint08*)&FuncBytes[0] = 0xE9;
*(uint32*)&FuncBytes[1] = (uint32)WrapperAddr - (uint32)FunctionAddr - 5;
}
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuInstallWrappers
// ******************************************************************
2003-03-27 06:23:58 +00:00
void EmuInstallWrappers(OOVPATable *OovpaTable, uint32 OovpaTableSize, void (*Entry)(), Xbe::Header *XbeHeader)
{
// ******************************************************************
// * traverse the full OOVPA table
// ******************************************************************
for(uint32 a=0;a<OovpaTableSize/sizeof(OOVPATable);a++)
{
2003-02-21 04:51:03 +00:00
#ifdef _DEBUG_TRACE
2003-04-15 08:08:53 +00:00
printf("Emu: Searching for %s...", OovpaTable[a].szFuncName);
2003-02-21 04:51:03 +00:00
#endif
OOVPA *Oovpa = OovpaTable[a].Oovpa;
2003-02-09 08:35:33 +00:00
uint32 count = Oovpa->Count;
uint32 lower = XbeHeader->dwBaseAddr;
uint32 upper = XbeHeader->dwBaseAddr + XbeHeader->dwSizeofImage;
2003-02-09 08:35:33 +00:00
// ******************************************************************
// * Large
// ******************************************************************
if(Oovpa->Large == 1)
{
LOOVPA<1> *Loovpa = (LOOVPA<1>*)Oovpa;
2003-02-20 08:07:52 +00:00
upper -= Loovpa->Lovp[count-1].Offset;
2003-02-22 07:49:02 +00:00
bool found = false;
2003-02-20 08:07:52 +00:00
// ******************************************************************
// * Search all of the image memory
// ******************************************************************
for(uint32 cur=lower;cur<upper;cur++)
{
uint32 v=0;
// ******************************************************************
// * check all pairs, moving on if any do not match
// ******************************************************************
for(v=0;v<count;v++)
{
uint32 Offset = Loovpa->Lovp[v].Offset;
uint32 Value = Loovpa->Lovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
// ******************************************************************
// * success if we found all pairs
// ******************************************************************
if(v == count)
{
#ifdef _DEBUG_TRACE
2003-02-21 04:51:03 +00:00
printf("Found! (0x%.08X)\n", cur);
2003-02-20 08:07:52 +00:00
#endif
2003-03-27 06:23:58 +00:00
EmuInstallWrapper((void*)cur, OovpaTable[a].lpRedirect);
2003-02-20 08:07:52 +00:00
2003-02-22 07:49:02 +00:00
found = true;
2003-02-20 08:07:52 +00:00
break;
}
2003-02-22 07:49:02 +00:00
}
2003-02-21 04:51:03 +00:00
2003-02-22 07:49:02 +00:00
// ******************************************************************
// * not found
// ******************************************************************
if(!found)
{
#ifdef _DEBUG_TRACE
printf("None (OK)\n");
#endif
2003-02-20 08:07:52 +00:00
}
}
// ******************************************************************
// * Small
// ******************************************************************
else
2003-02-09 08:35:33 +00:00
{
SOOVPA<1> *Soovpa = (SOOVPA<1>*)Oovpa;
2003-02-15 06:54:56 +00:00
upper -= Soovpa->Sovp[count-1].Offset;
2003-02-15 06:54:56 +00:00
2003-02-22 07:49:02 +00:00
bool found = false;
// ******************************************************************
// * Search all of the image memory
// ******************************************************************
for(uint32 cur=lower;cur<upper;cur++)
2003-02-15 06:54:56 +00:00
{
uint32 v=0;
// ******************************************************************
// * check all pairs, moving on if any do not match
// ******************************************************************
for(v=0;v<count;v++)
{
uint32 Offset = Soovpa->Sovp[v].Offset;
uint32 Value = Soovpa->Sovp[v].Value;
uint08 RealValue = *(uint08*)(cur + Offset);
if(RealValue != Value)
break;
}
// ******************************************************************
// * success if we found all pairs
// ******************************************************************
if(v == count)
{
#ifdef _DEBUG_TRACE
2003-02-21 04:51:03 +00:00
printf("Found! (0x%.08X)\n", cur);
#endif
2003-03-27 06:23:58 +00:00
EmuInstallWrapper((void*)cur, OovpaTable[a].lpRedirect);
2003-02-15 04:55:31 +00:00
2003-02-22 07:49:02 +00:00
found = true;
break;
}
2003-02-22 07:49:02 +00:00
}
2003-02-21 04:51:03 +00:00
2003-02-22 07:49:02 +00:00
// ******************************************************************
// * not found
// ******************************************************************
if(!found)
{
#ifdef _DEBUG_TRACE
printf("None (OK)\n");
#endif
}
2003-02-09 08:35:33 +00:00
}
}
2003-04-08 03:34:05 +00:00
}
2003-04-08 03:34:05 +00:00
// ******************************************************************
// * func: EmuException
2003-04-25 23:49:58 +00:00
// ******************************************************************
2003-04-08 03:34:05 +00:00
int EmuException(LPEXCEPTION_POINTERS e)
{
2003-04-25 23:49:58 +00:00
// ******************************************************************
// * Debugging Information
// ******************************************************************
{
printf("\n");
printf("Recieved Exception : 0x%.08X\n", e->ExceptionRecord->ExceptionCode);
printf("\n");
}
// ******************************************************************
// * Notify User
// ******************************************************************
{
char buffer[256];
sprintf(buffer, "Recieved Exception [0x%.08X]\n\nPress 'OK' to terminate emulation.\nPress 'Cancel' to debug.", e->ExceptionRecord->ExceptionCode);
if(MessageBox(NULL, buffer, "Cxbx", MB_ICONSTOP | MB_OKCANCEL) == IDOK)
ExitProcess(1);
2003-04-25 16:55:24 +00:00
}
2003-04-08 03:34:05 +00:00
return EXCEPTION_CONTINUE_SEARCH;
}