// ****************************************************************** // * func: EmuShared::EmuSharedInit // ****************************************************************** CXBXKRNL_API void EmuShared::Init() { // ****************************************************************** // * Ensure initialization only occurs once // ****************************************************************** bool init = true; // ****************************************************************** // * Prevent multiple initializations // ****************************************************************** if(hMapObject != NULL) return; // ****************************************************************** // * Create the shared memory "file" // ****************************************************************** { hMapObject = CreateFileMapping ( INVALID_HANDLE_VALUE, // Paging file NULL, // default security attributes PAGE_READWRITE, // read/write access 0, // size: high 32 bits sizeof(EmuShared), // size: low 32 bits "Local\\EmuShared" // name of map object ); if(hMapObject == NULL) CxbxKrnlCleanup("Could not map shared memory!"); if(GetLastError() == ERROR_ALREADY_EXISTS) init = false; } // ****************************************************************** // * Memory map this file // ****************************************************************** { g_EmuShared = (EmuShared*)MapViewOfFile ( hMapObject, // object to map view of FILE_MAP_WRITE, // read/write access 0, // high offset: map from 0, // low offset: beginning 0 // default: map entire file ); if(g_EmuShared == NULL) CxbxKrnlCleanup("Could not map view of shared memory!"); } // ****************************************************************** // * Executed only on first initialization of shared memory // ****************************************************************** if(init) g_EmuShared->EmuShared::EmuShared(); g_EmuSharedRefCount++; }
// ****************************************************************** // * patch: XGSwizzleRect // ****************************************************************** VOID WINAPI XTL::EMUPATCH(XGSwizzleRect) ( LPCVOID pSource, DWORD Pitch, LPCRECT pRect, LPVOID pDest, DWORD Width, DWORD Height, CONST LPPOINT pPoint, DWORD BytesPerPixel ) { FUNC_EXPORTS LOG_FUNC_BEGIN LOG_FUNC_ARG(pSource) LOG_FUNC_ARG(Pitch) LOG_FUNC_ARG(pRect) LOG_FUNC_ARG(pDest) LOG_FUNC_ARG(Width) LOG_FUNC_ARG(Height) LOG_FUNC_ARG(pPoint) LOG_FUNC_ARG(BytesPerPixel) LOG_FUNC_END; if(pRect == NULL && pPoint == NULL && Pitch == 0) { memcpy(pDest, pSource, Width*Height*BytesPerPixel); } else { if(pPoint != NULL && (pPoint->x != 0 || pPoint->y != 0)) CxbxKrnlCleanup("Temporarily unsupported swizzle (very easy fix)"); DWORD dwMaxY = Height; DWORD dwChunkSize = Width; uint08 *pSrc = (uint08*)pSource; uint08 *pDst = (uint08*)pDest; if(pRect != 0) { pSrc += pRect->top*Pitch; pSrc += pRect->left; dwMaxY = pRect->bottom - pRect->top; dwChunkSize = pRect->right - pRect->left; } for(DWORD y=0;y<dwMaxY;y++) { memcpy(pSrc, pDst, dwChunkSize); pSrc += Pitch; pDst += Pitch; } } }
extern "C" CXBXKRNL_API void CxbxKrnlPanic() { if(EmuIsXboxFS()) EmuSwapFS(); // Win2k/XP FS DbgPrintf("EmuMain (0x%X): CxbxKrnlPanic()\n", GetCurrentThreadId()); CxbxKrnlCleanup("Kernel Panic!"); EmuSwapFS(); // XBox FS }
extern "C" CXBXKRNL_API void CxbxKrnlRegisterThread(HANDLE hThread) { int v=0; for(v=0;v<MAXIMUM_XBOX_THREADS;v++) { if(g_hThreads[v] == 0) { g_hThreads[v] = hThread; break; } } if(v == MAXIMUM_XBOX_THREADS) { CxbxKrnlCleanup("There are too many active threads!"); } }
// ****************************************************************** // * func: EmuAllocateLDT // ****************************************************************** uint16 EmuAllocateLDT(uint32 dwBaseAddr, uint32 dwLimit) { #ifndef __WINE__ NtDll::LDT_ENTRY LDTEntry; #else LDT_ENTRY LDTEntry; #endif int x=0; EnterCriticalSection(&EmuLDTLock); // ****************************************************************** // * Locate a free LDT entry // ****************************************************************** { for(x=0;x<MAXIMUM_XBOX_THREADS;x++) if(FreeLDTEntries[x]) break; if(x == MAXIMUM_XBOX_THREADS) { LeaveCriticalSection(&EmuLDTLock); CxbxKrnlCleanup("Could not locate free LDT entry (too many threads?)"); return 0; } } // ****************************************************************** // * Set up selector information // ****************************************************************** { LDTEntry.BaseLow = (WORD)(dwBaseAddr & 0xFFFF); LDTEntry.HighWord.Bits.BaseMid = (dwBaseAddr >> 16) & 0xFF; LDTEntry.HighWord.Bits.BaseHi = (dwBaseAddr >> 24) & 0xFF; LDTEntry.HighWord.Bits.Type = 0x13; // RW data segment LDTEntry.HighWord.Bits.Dpl = 3; // user segment LDTEntry.HighWord.Bits.Pres = 1; // present LDTEntry.HighWord.Bits.Sys = 0; LDTEntry.HighWord.Bits.Reserved_0 = 0; LDTEntry.HighWord.Bits.Default_Big = 1; // 386 segment LDTEntry.HighWord.Bits.Granularity = (dwLimit >= 0x00100000) ? 1 : 0; if(LDTEntry.HighWord.Bits.Granularity) dwLimit >>= 12; LDTEntry.LimitLow = (WORD)(dwLimit & 0xFFFF); LDTEntry.HighWord.Bits.LimitHi = (dwLimit >> 16) & 0xF; } // ****************************************************************** // * Allocate selector // ****************************************************************** { #ifndef __WINE__ if(!NT_SUCCESS(NtDll::_NtSetLdtEntries(LDT_ENTRY_NUM(x), LDTEntry, 0, LDTEntry))) #else if(wine_ldt_set_entry(LDT_ENTRY_NUM(x), &LDTEntry) < 0) #endif { LeaveCriticalSection(&EmuLDTLock); CxbxKrnlCleanup("Could not set LDT entries"); return 0; } } LeaveCriticalSection(&EmuLDTLock); FreeLDTEntries[x] = 0; return LDT_ENTRY_NUM(x); }
// ****************************************************************** // * func: EmuXGSwizzleRect // ****************************************************************** VOID WINAPI XTL::EmuXGSwizzleRect ( LPCVOID pSource, DWORD Pitch, LPCRECT pRect, LPVOID pDest, DWORD Width, DWORD Height, CONST LPPOINT pPoint, DWORD BytesPerPixel ) { EmuSwapFS(); // Win2k/XP FS DbgPrintf("EmuXapi (0x%X): EmuXGSwizzleRect\n" "(\n" " pSource : 0x%.08X\n" " Pitch : 0x%.08X\n" " pRect : 0x%.08X\n" " pDest : 0x%.08X\n" " Width : 0x%.08X\n" " Height : 0x%.08X\n" " pPoint : 0x%.08X\n" " BytesPerPixel : 0x%.08X\n" ");\n", GetCurrentThreadId(), pSource, Pitch, pRect, pDest, Width, Height, pPoint, BytesPerPixel); if(pRect == NULL && pPoint == NULL && Pitch == 0) { memcpy(pDest, pSource, Width*Height*BytesPerPixel); } else { if(pPoint != NULL && (pPoint->x != 0 || pPoint->y != 0)) CxbxKrnlCleanup("Temporarily unsupported swizzle (very easy fix)"); DWORD dwMaxY = Height; DWORD dwChunkSize = Width; uint08 *pSrc = (uint08*)pSource; uint08 *pDst = (uint08*)pDest; if(pRect != 0) { pSrc += pRect->top*Pitch; pSrc += pRect->left; dwMaxY = pRect->bottom - pRect->top; dwChunkSize = pRect->right - pRect->left; } for(DWORD y=0;y<dwMaxY;y++) { memcpy(pSrc, pDst, dwChunkSize); pSrc += Pitch; pDst += Pitch; } } EmuSwapFS(); // Xbox FS return; }
// ****************************************************************** // * func: EmuXGSwizzleBox // ****************************************************************** VOID WINAPI XTL::EmuXGSwizzleBox ( LPCVOID pSource, DWORD RowPitch, DWORD SlicePitch, CONST D3DBOX *pBox, LPVOID pDest, DWORD Width, DWORD Height, DWORD Depth, CONST XGPOINT3D *pPoint, DWORD BytesPerPixel ) { EmuSwapFS(); // Win2k/XP FS DbgPrintf("EmuXapi (0x%X): EmuXGSwizzleBox\n" "(\n" " pSource : 0x%.08X\n" " RowPitch : 0x%.08X\n" " SlicePitch : 0x%.08X\n" " pBox : 0x%.08X\n" " pDest : 0x%.08X\n" " Width : 0x%.08X\n" " Height : 0x%.08X\n" " Depth : 0x%.08X\n" " pPoint : 0x%.08X\n" " BytesPerPixel : 0x%.08X\n" ");\n", GetCurrentThreadId(), pSource, RowPitch, SlicePitch, pBox, pDest, Width, Height, Depth, pPoint, BytesPerPixel); if(pDest != (LPVOID) 0x80000000) { if(pBox == NULL && pPoint == NULL && RowPitch == 0 && SlicePitch == 0) { memcpy(pDest, pSource, Width*Height*Depth*BytesPerPixel); } else { if(pPoint != NULL && (pPoint->u != 0 || pPoint->v != 0 || pPoint->w != 0)) CxbxKrnlCleanup("Temporarily unsupported swizzle (very easy fix)"); DWORD dwMaxY = Height; DWORD dwMaxZ = Depth; DWORD dwChunkSize = Width; uint08 *pSrc = (uint08*)pSource; uint08 *pDst = (uint08*)pDest; if(pBox != 0) { pSrc += pBox->Top*RowPitch; pSrc += pBox->Left; dwMaxY = pBox->Bottom - pBox->Top; dwChunkSize = pBox->Right - pBox->Left; } for(DWORD y=0;y<dwMaxY;y++) { memcpy(pSrc, pDst, dwChunkSize); pSrc += RowPitch; pDst += RowPitch; } } } EmuSwapFS(); // Xbox FS return; }
void KiUnexpectedInterrupt() { xboxkrnl::KeBugCheck(TRAP_CAUSE_UNKNOWN); // see CxbxKrnlCleanup("Unexpected Software Interrupt!"); }
// ****************************************************************** // * patch: XGSwizzleBox // ****************************************************************** VOID WINAPI XTL::EMUPATCH(XGSwizzleBox) ( LPCVOID pSource, DWORD RowPitch, DWORD SlicePitch, CONST D3DBOX *pBox, LPVOID pDest, DWORD Width, DWORD Height, DWORD Depth, CONST XGPOINT3D *pPoint, DWORD BytesPerPixel ) { //FUNC_EXPORTS LOG_FUNC_BEGIN LOG_FUNC_ARG(pSource) LOG_FUNC_ARG(RowPitch) LOG_FUNC_ARG(SlicePitch) LOG_FUNC_ARG(pBox) LOG_FUNC_ARG(pDest) LOG_FUNC_ARG(Width) LOG_FUNC_ARG(Height) LOG_FUNC_ARG(Depth) LOG_FUNC_ARG(pPoint) LOG_FUNC_ARG(BytesPerPixel) LOG_FUNC_END; if(pDest != (LPVOID) 0x80000000) { if(pBox == NULL && pPoint == NULL && RowPitch == 0 && SlicePitch == 0) { memcpy(pDest, pSource, Width*Height*Depth*BytesPerPixel); } else { if(pPoint != NULL && (pPoint->u != 0 || pPoint->v != 0 || pPoint->w != 0)) CxbxKrnlCleanup("Temporarily unsupported swizzle (very easy fix)"); DWORD dwMaxY = Height; DWORD dwMaxZ = Depth; DWORD dwChunkSize = Width; uint08 *pSrc = (uint08*)pSource; uint08 *pDst = (uint08*)pDest; if(pBox != 0) { pSrc += pBox->Top*RowPitch; pSrc += pBox->Left; dwMaxY = pBox->Bottom - pBox->Top; dwChunkSize = pBox->Right - pBox->Left; } for(DWORD y=0;y<dwMaxY;y++) { memcpy(pSrc, pDst, dwChunkSize); pSrc += RowPitch; pDst += RowPitch; } } } }
extern "C" CXBXKRNL_API void CxbxKrnlInit ( HWND hwndParent, void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *pLibraryVersion, DebugMode DbgMode, char *szDebugFilename, Xbe::Header *pXbeHeader, uint32 dwXbeHeaderSize, void (*Entry)()) { // update caches CxbxKrnl_TLS = pTLS; CxbxKrnl_TLSData = pTLSData; CxbxKrnl_XbeHeader = pXbeHeader; CxbxKrnl_hEmuParent = IsWindow(hwndParent) ? hwndParent : NULL; // for unicode conversions setlocale(LC_ALL, "English"); // debug console allocation (if configured) if(DbgMode == DM_CONSOLE) { if(AllocConsole()) { freopen("CONOUT$", "wt", stdout); freopen("CONIN$", "rt", stdin); SetConsoleTitle("Cxbx : Kernel Debug Console"); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED); printf("EmuMain (0x%X): Cxbx Version %s\n", GetCurrentThreadId(), _CXBX_VERSION); printf("EmuMain (0x%X): Debug Console Allocated (DM_CONSOLE).\n", GetCurrentThreadId()); } } else if(DbgMode == DM_FILE) { FreeConsole(); freopen(szDebugFilename, "wt", stdout); printf("EmuMain (0x%X): Cxbx Version %s\n", GetCurrentThreadId(), _CXBX_VERSION); printf("EmuMain (0x%X): Debug Console Allocated (DM_FILE).\n", GetCurrentThreadId()); } else { FreeConsole(); char buffer[16]; if(GetConsoleTitle(buffer, 16) != NULL) freopen("nul", "w", stdout); } // // debug trace // { #ifdef _DEBUG_TRACE printf("EmuMain (0x%X): Debug Trace Enabled.\n", GetCurrentThreadId()); printf("EmuMain (0x%X): CxbxKrnlInit\n" "(\n" " hwndParent : 0x%.08X\n" " pTLSData : 0x%.08X\n" " pTLS : 0x%.08X\n" " pLibraryVersion : 0x%.08X\n" " DebugConsole : 0x%.08X\n" " DebugFilename : \"%s\"\n" " pXBEHeader : 0x%.08X\n" " pXBEHeaderSize : 0x%.08X\n" " Entry : 0x%.08X\n" ");\n", GetCurrentThreadId(), hwndParent, pTLSData, pTLS, pLibraryVersion, DbgMode, szDebugFilename, pXbeHeader, dwXbeHeaderSize, Entry); #else printf("EmuMain (0x%X): Debug Trace Disabled.\n", GetCurrentThreadId()); #endif } // // load the necessary pieces of XbeHeader // { 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 = pXbeHeader->dwSizeofHeaders; MemXbeHeader->dwCertificateAddr = pXbeHeader->dwCertificateAddr; MemXbeHeader->dwPeHeapReserve = pXbeHeader->dwPeHeapReserve; MemXbeHeader->dwPeHeapCommit = pXbeHeader->dwPeHeapCommit; memcpy(&MemXbeHeader->dwInitFlags, &pXbeHeader->dwInitFlags, sizeof(pXbeHeader->dwInitFlags)); memcpy((void*)pXbeHeader->dwCertificateAddr, &((uint08*)pXbeHeader)[pXbeHeader->dwCertificateAddr - 0x00010000], sizeof(Xbe::Certificate)); } // // initialize current directory // { char szBuffer[260]; g_EmuShared->GetXbePath(szBuffer); if(szBuffer && *szBuffer) SetCurrentDirectory(szBuffer); else GetCurrentDirectory(260, szBuffer); g_strCurDrive = _strdup(szBuffer); g_hCurDir = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if(g_hCurDir == INVALID_HANDLE_VALUE) CxbxKrnlCleanup("Could not map D:\\\n"); DbgPrintf("EmuMain (0x%X): CurDir := %s\n", GetCurrentThreadId(), szBuffer); } // // initialize EmuDisk // { char szBuffer[260]; SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_APPDATA, TRUE); strcat(szBuffer, "\\Cxbx\\"); CreateDirectory(szBuffer, NULL); sint32 spot = -1; for(int v=0;v<260;v++) { if(szBuffer[v] == '\\') { spot = v; } else if(szBuffer[v] == '\0') { break; } } if(spot != -1) { szBuffer[spot] = '\0'; } Xbe::Certificate *pCertificate = (Xbe::Certificate*)pXbeHeader->dwCertificateAddr; // // create EmuDisk directory // strcpy(&szBuffer[spot], "\\EmuDisk"); CreateDirectory(szBuffer, NULL); // // create T:\ directory // { strcpy(&szBuffer[spot], "\\EmuDisk\\T"); CreateDirectory(szBuffer, NULL); sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId); CreateDirectory(szBuffer, NULL); g_strTDrive = _strdup(szBuffer); g_hTDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if(g_hTDrive == INVALID_HANDLE_VALUE) CxbxKrnlCleanup("Could not map T:\\\n"); DbgPrintf("EmuMain (0x%X): T Data := %s\n", GetCurrentThreadId(), szBuffer); } // // create U:\ directory // { strcpy(&szBuffer[spot], "\\EmuDisk\\U"); CreateDirectory(szBuffer, NULL); sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId); CreateDirectory(szBuffer, NULL); g_strUDrive = _strdup(szBuffer); g_hUDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if(g_hUDrive == INVALID_HANDLE_VALUE) CxbxKrnlCleanup("Could not map U:\\\n"); DbgPrintf("EmuMain (0x%X): U Data := %s\n", GetCurrentThreadId(), szBuffer); } // // create Z:\ directory // { strcpy(&szBuffer[spot], "\\EmuDisk\\Z"); CreateDirectory(szBuffer, NULL); //* is it necessary to make this directory title unique? sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId); CreateDirectory(szBuffer, NULL); //*/ g_strZDrive = _strdup(szBuffer); g_hZDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if(g_hUDrive == INVALID_HANDLE_VALUE) CxbxKrnlCleanup("Could not map Z:\\\n"); DbgPrintf("EmuMain (0x%X): Z Data := %s\n", GetCurrentThreadId(), szBuffer); } } // // initialize FS segment selector // { EmuInitFS(); EmuGenerateFS(pTLS, pTLSData); } // // duplicate handle in order to retain Suspend/Resume thread rights from a remote thread // { HANDLE hDupHandle = NULL; DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); CxbxKrnlRegisterThread(hDupHandle); } // // Clear critical section list // //extern void InitializeSectionStructures(void); InitializeSectionStructures(); DbgPrintf("EmuMain (0x%X): Initializing Direct3D.\n", GetCurrentThreadId()); XTL::EmuD3DInit(pXbeHeader, dwXbeHeaderSize); EmuHLEIntercept(pLibraryVersion, pXbeHeader); DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId()); // // Xbe entry point // __try { EmuSwapFS(); // XBox FS // _USE_XGMATH Disabled in mesh :[ // halo : dword_0_2E2D18 // halo : 1744F0 (bink) //_asm int 3; /* for(int v=0;v<sizeof(funcAddr)/sizeof(uint32);v++) { bool bExclude = false; for(int r=0;r<sizeof(funcExclude)/sizeof(uint32);r++) { if(funcAddr[v] == funcExclude[r]) { bExclude = true; break; } } if(!bExclude) { *(uint08*)(funcAddr[v]) = 0xCC; } } //*/ Entry(); EmuSwapFS(); // Win2k/XP FS } __except(EmuException(GetExceptionInformation())) { printf("Emu: WARNING!! Problem with ExceptionFilter\n"); } DbgPrintf("EmuMain (0x%X): Initial thread ended.\n", GetCurrentThreadId()); fflush(stdout); CxbxKrnlTerminateThread(); return; }
void DbgConsole::ParseCommand() { printf("\n"); char szCmd[32]; szCmd[0] = '\0'; sscanf(m_szInput, "%s", szCmd); // TODO: as command list grows, turn into static string/ptr lookup if(_stricmp(szCmd, "h") == 0 || _stricmp(szCmd, "help") == 0) { printf("CxbxDbg: \n"); printf("CxbxDbg: Cxbx-Reloaded Debug Command List:\n"); printf("CxbxDbg: \n"); printf("CxbxDbg: Help [H] : Show Command List\n"); printf("CxbxDbg: Quit/Exit [Q] : Stop Emulation\n"); printf("CxbxDbg: Trace [T] : Toggle Debug Trace\n"); #ifdef _DEBUG_TRACK_VB printf("CxbxDbg: ListVB [LVB] : List Active Vertex Buffers\n"); printf("CxbxDbg: DisableVB [DVB #] : Disable Active Vertex Buffer(s)\n"); printf("CxbxDbg: EnableVB [EVB #] : Enable Active Vertex Buffer(s)\n"); printf("CxbxDbg: DumpStreamCache [DSC] : Dumps the patched streams cache\n"); #endif #ifdef _DEBUG_ALLOC printf("CxbxDbg: DumpMem [DMEM] : Dump the heap allocation tracking table\n"); #endif // _DEBUG_ALLOCC printf("CxbxDbg: CLS\n"); printf("CxbxDbg: \n"); printf("CxbxDbg: # denotes parameter of form [#] or [#-#]\n"); printf("CxbxDbg: \n"); } else if(_stricmp(szCmd, "q") == 0 || _stricmp(szCmd, "quit") == 0 || _stricmp(szCmd, "exit") == 0) { printf("CxbxDbg: Goodbye...\n"); CxbxKrnlCleanup(NULL); } else if(_stricmp(szCmd, "t") == 0 || _stricmp(szCmd, "trace") == 0) { g_bPrintfOn = !g_bPrintfOn; printf("CxbxDbg: Trace is now %s\n", g_bPrintfOn ? "ON" : "OFF"); } #ifdef _DEBUG_TRACK_VB else if(_stricmp(szCmd, "lvb") == 0 || _stricmp(szCmd, "ListVB") == 0) { int v=0; g_VBTrackTotal.Lock(); RTNode *cur = g_VBTrackTotal.getHead(); while(cur != NULL && cur->pNext != NULL) { bool enabled = g_VBTrackDisable.exists(cur->pResource); printf("CxbxDbg: %.2d : 0x%p (%s)\n", v++, cur->pResource, enabled ? "enabled" : "disabled"); cur = cur->pNext; } g_VBTrackTotal.Unlock(); } else if(_stricmp(szCmd, "dvb") == 0 || _stricmp(szCmd, "DisableVB") == 0) { int n=0, m=0; int c = sscanf(m_szInput, "%*s %d-%d", &n, &m); if(c == 1) { EnableTracker(g_VBTrackTotal, g_VBTrackDisable, n, n, ETA_DISABLE); } else if(c == 2) { EnableTracker(g_VBTrackTotal, g_VBTrackDisable, n, m, ETA_DISABLE); } else { printf("CxbxDbg: Syntax Incorrect (dvb #)\n"); } } else if(_stricmp(szCmd, "evb") == 0 || _stricmp(szCmd, "EnableVB") == 0) { int n=0, m=0; int c = sscanf(m_szInput, "%*s %d-%d", &n, &m); if(c == 1) { EnableTracker(g_VBTrackTotal, g_VBTrackDisable, n, n, ETA_ENABLE); } else if(c == 2) { EnableTracker(g_VBTrackTotal, g_VBTrackDisable, n, m, ETA_ENABLE); } else { printf("CxbxDbg: Syntax Incorrect (dvb #)\n"); } } #endif #ifdef _DEBUG_ALLOC else if(_stricmp(szCmd, "dmem") == 0 || _stricmp(szCmd, "DumpMem") == 0) { int Full; int c = sscanf(m_szInput, "%*s %d", &Full); CxbxAllocDump(Full != 0); } #endif // _DEBUG_ALLOC else if(_stricmp(szCmd, "cls") == 0) { // clear screen using system call system("cls"); } else { printf("CxbxDbg: Cmd \"%s\" not recognized!\n", szCmd); } }