2003-02-08 22:25:08 +00:00
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ 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
2003-02-08 22:25:08 +00:00
// *
// * 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
2003-02-08 22:25:08 +00:00
# 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-02-08 22:25:08 +00:00
{
2003-04-02 02:23:30 +00:00
# include <xboxkrnl/xboxkrnl.h>
2003-02-08 22:25:08 +00:00
} ;
2003-04-02 02:23:30 +00:00
# include "Emu.h"
# include "EmuFS.h"
# include "EmuD3D8.h"
2003-04-01 07:11:07 +00:00
# include "EmuShared.h"
2003-04-02 02:23:30 +00:00
# include "HLEDataBase.h"
2003-04-01 07:11:07 +00:00
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-02-08 22:25:08 +00:00
// ******************************************************************
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-02-08 22:25:08 +00:00
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuNoFunc
2003-02-08 22:25:08 +00:00
// ******************************************************************
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-02-08 22:25:08 +00:00
{
2003-04-06 00:25:30 +00:00
g_TlsAdjust = TlsAdjust ;
2003-02-08 22:25:08 +00:00
// ******************************************************************
// * debug console allocation (if configured)
// ******************************************************************
2003-04-04 04:35:00 +00:00
if ( DbgMode = = DM_CONSOLE )
2003-02-08 22:25:08 +00:00
{
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-02-08 22:25:08 +00:00
}
}
2003-04-04 04:35:00 +00:00
else if ( DbgMode = = DM_FILE )
2003-02-08 22:25:08 +00:00
{
FreeConsole ( ) ;
2003-04-04 04:35:00 +00:00
freopen ( szDebugFilename , " wt " , stdout ) ;
2003-02-08 22:25:08 +00:00
2003-03-28 20:14:48 +00:00
printf ( " Emu (0x%.08X): Debug console allocated (DM_FILE). \n " , GetCurrentThreadId ( ) ) ;
2003-02-08 22:25:08 +00:00
}
// ******************************************************************
// * 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-02-08 22:25:08 +00:00
}
// ******************************************************************
2003-04-08 03:34:05 +00:00
// * Load the necessary pieces of XBEHeader
2003-02-08 22:25:08 +00:00
// ******************************************************************
{
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
EmuInitD3D ( XbeHeader , XbeHeaderSize ) ;
2003-02-08 22:25:08 +00:00
}
2003-04-08 03:34:05 +00:00
printf ( " Emu (0x%.08X): Initial thread starting. \n " , GetCurrentThreadId ( ) ) ;
2003-02-08 22:25:08 +00:00
// ******************************************************************
2003-04-08 03:34:05 +00:00
// * Entry Point
2003-02-08 22:25:08 +00:00
// ******************************************************************
2003-04-08 03:34:05 +00:00
__try
2003-02-08 22:25:08 +00:00
{
2003-04-08 03:34:05 +00:00
EmuSwapFS ( ) ; // XBox FS
2003-02-08 22:25:08 +00:00
2003-04-08 03:34:05 +00:00
Entry ( ) ;
2003-02-08 22:25:08 +00:00
2003-04-08 03:34:05 +00:00
EmuSwapFS ( ) ; // Win2k/XP FS
2003-02-08 22:25:08 +00:00
}
2003-04-08 03:34:05 +00:00
__except ( EmuException ( GetExceptionInformation ( ) ) )
2003-02-08 22:25:08 +00:00
{
2003-04-08 03:34:05 +00:00
printf ( " Emu: WARNING!! Problem with ExceptionFilter \n " ) ;
2003-02-15 22:16:14 +00:00
}
2003-03-27 06:23:58 +00:00
printf ( " Emu (0x%.08X): Initial thread ended. \n " , GetCurrentThreadId ( ) ) ;
2003-02-08 22:25:08 +00:00
fflush ( stdout ) ;
2003-02-19 20:53:33 +00:00
while ( true )
Sleep ( 1000 ) ;
2003-02-08 22:25:08 +00:00
return ;
}
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuPanic
2003-02-08 22:25:08 +00:00
// ******************************************************************
2003-04-02 02:23:30 +00:00
extern " C " CXBXKRNL_API void NTAPI EmuPanic ( )
2003-02-08 22:25:08 +00:00
{
2003-04-12 11:21:35 +00:00
if ( EmuIsXboxFS ( ) )
EmuSwapFS ( ) ; // Win2k/XP FS
2003-02-08 22:25:08 +00:00
2003-03-27 06:23:58 +00:00
printf ( " Emu (0x%.08X): EmuPanic() \n " , GetCurrentThreadId ( ) ) ;
2003-02-08 22:25:08 +00:00
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
2003-02-08 22:25:08 +00:00
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
ExitProcess ( 1 ) ;
2003-03-27 06:23:58 +00:00
EmuSwapFS ( ) ; // XBox FS
2003-02-08 22:25:08 +00:00
}
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-02-08 22:25:08 +00:00
// ******************************************************************
2003-03-27 06:23:58 +00:00
// * func: EmuInstallWrappers
2003-02-08 22:25:08 +00:00
// ******************************************************************
2003-03-27 06:23:58 +00:00
void EmuInstallWrappers ( OOVPATable * OovpaTable , uint32 OovpaTableSize , void ( * Entry ) ( ) , Xbe : : Header * XbeHeader )
2003-02-08 22:25:08 +00:00
{
// ******************************************************************
2003-02-15 22:16:14 +00:00
// * traverse the full OOVPA table
2003-02-08 22:25:08 +00:00
// ******************************************************************
2003-02-15 22:16:14 +00:00
for ( uint32 a = 0 ; a < OovpaTableSize / sizeof ( OOVPATable ) ; a + + )
2003-02-08 22:25:08 +00:00
{
2003-02-21 04:51:03 +00:00
# ifdef _DEBUG_TRACE
2003-03-27 06:23:58 +00:00
printf ( " EmuInstallWrappers: Searching for %s... " , OovpaTable [ a ] . szFuncName ) ;
2003-02-21 04:51:03 +00:00
# endif
2003-02-15 22:16:14 +00:00
OOVPA * Oovpa = OovpaTable [ a ] . Oovpa ;
2003-02-09 08:35:33 +00:00
2003-02-15 22:16:14 +00:00
uint32 count = Oovpa - > Count ;
uint32 lower = XbeHeader - > dwBaseAddr ;
uint32 upper = XbeHeader - > dwBaseAddr + XbeHeader - > dwSizeofImage ;
2003-02-09 08:35:33 +00:00
2003-02-15 22:16:14 +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
}
2003-02-15 22:16:14 +00:00
}
// ******************************************************************
// * Small
// ******************************************************************
else
2003-02-09 08:35:33 +00:00
{
2003-02-15 22:16:14 +00:00
SOOVPA < 1 > * Soovpa = ( SOOVPA < 1 > * ) Oovpa ;
2003-02-15 06:54:56 +00:00
2003-02-15 22:16:14 +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 ;
2003-02-15 22:16:14 +00:00
// ******************************************************************
// * Search all of the image memory
// ******************************************************************
for ( uint32 cur = lower ; cur < upper ; cur + + )
2003-02-15 06:54:56 +00:00
{
2003-02-15 22:16:14 +00:00
uint32 v = 0 ;
2003-02-08 22:25:08 +00:00
2003-02-15 22:16:14 +00:00
// ******************************************************************
// * check all pairs, moving on if any do not match
// ******************************************************************
for ( v = 0 ; v < count ; v + + )
2003-02-15 04:48:21 +00:00
{
2003-02-15 22:16:14 +00:00
uint32 Offset = Soovpa - > Sovp [ v ] . Offset ;
uint32 Value = Soovpa - > Sovp [ v ] . Value ;
2003-02-15 04:48:21 +00:00
2003-02-15 22:16:14 +00:00
uint08 RealValue = * ( uint08 * ) ( cur + Offset ) ;
2003-02-15 04:48:21 +00:00
2003-02-15 22:16:14 +00:00
if ( RealValue ! = Value )
break ;
}
2003-02-15 04:48:21 +00:00
2003-02-15 22:16:14 +00:00
// ******************************************************************
// * 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-15 22:16:14 +00:00
# endif
2003-02-15 04:48:21 +00:00
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 ;
2003-02-15 22:16:14 +00:00
break ;
2003-02-15 04:48:21 +00:00
}
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-15 04:48:21 +00:00
}
2003-02-09 08:35:33 +00:00
}
2003-02-08 22:25:08 +00:00
}
2003-04-08 03:34:05 +00:00
}
2003-02-15 22:16:14 +00:00
2003-04-08 03:34:05 +00:00
// ******************************************************************
// * func: EmuException
// ******************************************************************
int EmuException ( LPEXCEPTION_POINTERS e )
{
2003-04-11 09:13:06 +00:00
static int count = 0 ;
count + + ;
2003-04-11 22:16:14 +00:00
if ( count < 20000 )
2003-04-11 09:13:06 +00:00
return EXCEPTION_CONTINUE_EXECUTION ;
else
count = 0 ;
int ret = MessageBox ( NULL , " ERROR: Maximum exception count reached. \n \n Press 'OK' to terminate emulation. \n Press 'Cancel' to debug. " , " Cxbx " , MB_ICONSTOP | MB_OKCANCEL ) ;
2003-04-08 03:34:05 +00:00
if ( ret = = IDOK )
ExitProcess ( 1 ) ;
return EXCEPTION_CONTINUE_SEARCH ;
}