bool RivenConsole::Cmd_CurStack(int argc, const char **argv) { debugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str()); return true; }
bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) { debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1); debugPrintf("\n"); debugPrintf("Exit information:\n"); debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); debugPrintf("Special exit information:\n"); if (!_vm->_specialExitCount) { debugPrintf("No special exits.\n"); } else { debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); for (int i = 0; i < _vm->_specialExitCount; ++i) { debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, _vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i], _vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]); } } return true; }
bool Console::cmdCurrentScene(int argc, const char **argv) { debugPrintf("Current Scene is: %i, scene resource id: %i\n", _vm->_scene->currentSceneNumber(), _vm->_scene->currentSceneResourceId()); return true; }
static BOOL attachDebugger(DWORD dwProcessId) { long lRet; HKEY hKey; lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 0, KEY_READ, &hKey); if (lRet != ERROR_SUCCESS) { debugPrintf("inject: error: RegOpenKeyExA failed\n"); return FALSE; } char szDebugger[1024]; DWORD cbDebugger = sizeof szDebugger; lRet = RegQueryValueExA(hKey, "Debugger", NULL, NULL, (BYTE *)szDebugger, &cbDebugger); RegCloseKey(hKey); if (lRet != ERROR_SUCCESS) { if (lRet == ERROR_FILE_NOT_FOUND) { debugPrintf("inject: error: no automatic debugger configured\n"); } else { debugPrintf("inject: error: RegQueryValueExA failed (0x%08lx)\n", lRet); } return FALSE; } SECURITY_ATTRIBUTES sa = { sizeof sa, 0, TRUE }; HANDLE hEvent = CreateEvent(&sa, FALSE, FALSE, NULL); char szDebuggerCommand[1024]; _snprintf(szDebuggerCommand, sizeof szDebuggerCommand, szDebugger, dwProcessId, (DWORD)(UINT_PTR)hEvent, NULL); debugPrintf("%s\n", szDebuggerCommand); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof pi); STARTUPINFOA si; ZeroMemory(&si, sizeof si); si.cb = sizeof &si; BOOL bRet = FALSE; if (!CreateProcessA( NULL, szDebuggerCommand, NULL, // process attributes NULL, // thread attributes TRUE, // inherit (event) handles 0, NULL, // environment NULL, // current directory &si, &pi)) { debugPrintf("inject: error: failed to execute \"%s\" with 0x%08lx\n", szDebuggerCommand, GetLastError()); } else { HANDLE handles[] = { hEvent, pi.hProcess }; DWORD dwRet = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE); bRet = dwRet == WAIT_OBJECT_0; CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } CloseHandle(hEvent); return bRet; }
int main(int argc, char *argv[]) { BOOL bDebug = FALSE; BOOL bAttach = FALSE; DWORD dwProcessId = 0; DWORD dwThreadId = 0; char cVerbosity = 0; const char *szDll = NULL; int option_index = 0; while (true) { int opt = getopt_long_only(argc, argv, short_options, long_options, &option_index); if (opt == -1) { break; } switch (opt) { case 'h': help(); return 0; case 'd': bDebug = TRUE; break; case 'D': szDll = optarg; break; case 'p': dwProcessId = strtoul(optarg, NULL, 0); bAttach = TRUE; break; case 't': dwThreadId = strtoul(optarg, NULL, 0); bAttach = TRUE; break; case 'v': ++cVerbosity; break; default: debugPrintf("inject: invalid option '%c'\n", optopt); help(); return 1; } } if (!bAttach) { if (argc - optind < 1) { debugPrintf("inject: error: insufficient number of arguments\n"); help(); return 1; } if (isNumber(argv[optind])) { dwProcessId = atol(argv[optind]); bAttach = TRUE; } else if (argv[optind][0] == '!') { const char *szProcessName = &argv[optind][1]; dwProcessId = getProcessIdByName(szProcessName); if (!dwProcessId) { debugPrintf("error: failed to find process %s\n", szProcessName); return 1; } bAttach = TRUE; } } if (!szDll) { debugPrintf("inject: error: DLL not specificed\n"); help(); return 1; } HANDLE hSemaphore = NULL; if (!USE_SHARED_MEM) { SetEnvironmentVariableA("INJECT_DLL", szDll); } else { hSemaphore = CreateSemaphore(NULL, 1, 1, "inject_semaphore"); if (hSemaphore == NULL) { debugPrintf("error: failed to create semaphore\n"); return 1; } DWORD dwWait = WaitForSingleObject(hSemaphore, 0); if (dwWait == WAIT_TIMEOUT) { debugPrintf("info: waiting for another inject instance to finish\n"); dwWait = WaitForSingleObject(hSemaphore, INFINITE); } if (dwWait != WAIT_OBJECT_0) { debugPrintf("error: failed to enter semaphore gate\n"); return 1; } SharedMem *pSharedMem = OpenSharedMemory(); if (!pSharedMem) { debugPrintf("error: failed to open shared memory\n"); return 1; } pSharedMem->cVerbosity = cVerbosity; strncpy(pSharedMem->szDllName, szDll, _countof(pSharedMem->szDllName) - 1); pSharedMem->szDllName[_countof(pSharedMem->szDllName) - 1] = '\0'; } BOOL bAttachDwm = FALSE; PROCESS_INFORMATION processInfo; HANDLE hProcess; if (bAttach) { BOOL bRet; HANDLE hToken = NULL; bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken); if (!bRet) { debugPrintf("error: OpenProcessToken returned %u\n", (unsigned)bRet); return 1; } LUID Luid; bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid); if (!bRet) { debugPrintf("error: LookupPrivilegeValue returned %u\n", (unsigned)bRet); return 1; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = Luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof tp, NULL, NULL); if (!bRet) { debugPrintf("error: AdjustTokenPrivileges returned %u\n", (unsigned)bRet); return 1; } DWORD dwDesiredAccess = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE; hProcess = OpenProcess( dwDesiredAccess, FALSE /* bInheritHandle */, dwProcessId); if (!hProcess) { logLastError("failed to open process"); return 1; } char szProcess[MAX_PATH]; DWORD dwRet = GetModuleFileNameEx(hProcess, 0, szProcess, sizeof szProcess); assert(dwRet); if (dwRet && stricmp(getBaseName(szProcess), "dwm.exe") == 0) { bAttachDwm = TRUE; } } else { std::string commandLine; char sep = 0; for (int i = optind; i < argc; ++i) { const char *arg = argv[i]; if (sep) { commandLine.push_back(sep); } if (needsQuote(arg)) { quoteArg(commandLine, arg); } else { commandLine.append(arg); } sep = ' '; } STARTUPINFO startupInfo; memset(&startupInfo, 0, sizeof startupInfo); startupInfo.cb = sizeof startupInfo; // Create the process in suspended state if (!CreateProcessA( NULL, const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW 0, // process attributes 0, // thread attributes TRUE, // inherit handles CREATE_SUSPENDED, NULL, // environment NULL, // current directory &startupInfo, &processInfo)) { DWORD dwLastError = GetLastError(); fprintf(stderr, "inject: error: failed to execute %s (%lu)\n", commandLine.c_str(), dwLastError); if (dwLastError == ERROR_ELEVATION_REQUIRED) { fprintf(stderr, "error: target program requires elevated priviledges and must be started from an Administrator Command Prompt, or UAC must be disabled\n"); } return 1; } hProcess = processInfo.hProcess; } /* * XXX: Mixed architecture don't quite work. See also * http://www.corsix.org/content/dll-injection-and-wow64 */ { typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL); PFNISWOW64PROCESS pfnIsWow64Process; pfnIsWow64Process = (PFNISWOW64PROCESS) GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); if (pfnIsWow64Process) { BOOL isParentWow64 = FALSE; BOOL isChildWow64 = FALSE; if (pfnIsWow64Process(GetCurrentProcess(), &isParentWow64) && pfnIsWow64Process(hProcess, &isChildWow64) && isParentWow64 != isChildWow64) { debugPrintf("error: binaries mismatch: you need to use the " #ifdef _WIN64 "32-bits" #else "64-bits" #endif " apitrace binaries to trace this application\n"); TerminateProcess(hProcess, 1); return 1; } } } if (bAttachDwm && IsWindows8OrGreater()) { // Switch to Microsoft Basic Display Driver before injecting, so that // we don't trace with it. devconDisable(DEVCON_CLASS_DISPLAY); Sleep(1000); } const char *szDllName; szDllName = "injectee.dll"; char szDllPath[MAX_PATH]; GetModuleFileNameA(NULL, szDllPath, sizeof szDllPath); getDirName(szDllPath); strncat(szDllPath, szDllName, sizeof szDllPath - strlen(szDllPath) - 1); if (bDebug) { if (!attachDebugger(GetProcessId(hProcess))) { if (!bAttach) { TerminateProcess(hProcess, 1); } return 1; } } #if 1 if (!injectDll(hProcess, szDllPath)) { if (!bAttach) { TerminateProcess(hProcess, 1); } return 1; } #endif DWORD exitCode; if (bAttach) { if (bAttachDwm) { restartDwmComposition(hProcess); } else { fprintf(stderr, "Press any key when finished tracing\n"); getchar(); ejectDll(hProcess, szDllPath); } if (dwThreadId) { HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, TRUE, dwThreadId); if (hThread) { ResumeThread(hThread); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } else { debugPrintf("inject: failed to open thread %lu\n", dwThreadId); } return 0; } exitCode = 0; } else { // Start main process thread ResumeThread(processInfo.hThread); // Wait for it to finish WaitForSingleObject(hProcess, INFINITE); if (pSharedMem && !pSharedMem->bReplaced) { debugPrintf("warning: %s was never used: application probably does not use this API\n", szDll); } exitCode = ~0; GetExitCodeProcess(hProcess, &exitCode); CloseHandle(processInfo.hThread); } CloseHandle(hProcess); if (hSemaphore) { ReleaseSemaphore(hSemaphore, 1, NULL); CloseHandle(hSemaphore); } return (int)exitCode; }
void Console::notifyStep(const char *filename, int line) { debugPrintf("Step: %s:%d\n", filename, line); printSource(0); attach(); onFrame(); }
void Console::printError(const Common::String &command, Error error) { debugPrintf("%s: %s\n", command.c_str(), error.getErrorDisplayStr().c_str()); }
EXTERN_C BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { const char *szNewDllName = NULL; const char *szNewDllBaseName; switch (fdwReason) { case DLL_PROCESS_ATTACH: InitializeCriticalSection(&g_Mutex); g_hThisModule = hinstDLL; /* * Calling LoadLibrary inside DllMain is strongly discouraged. But it * works quite well, provided that the loaded DLL does not require or do * anything special in its DllMain, which seems to be the general case. * * See also: * - http://stackoverflow.com/questions/4370812/calling-loadlibrary-from-dllmain * - http://msdn.microsoft.com/en-us/library/ms682583 */ if (!USE_SHARED_MEM) { szNewDllName = getenv("INJECT_DLL"); if (!szNewDllName) { debugPrintf("inject: warning: INJECT_DLL not set\n"); return FALSE; } } else { SharedMem *pSharedMem = OpenSharedMemory(NULL); if (!pSharedMem) { debugPrintf("inject: error: failed to open shared memory\n"); return FALSE; } VERBOSITY = pSharedMem->cVerbosity; static char szSharedMemCopy[MAX_PATH]; strncpy(szSharedMemCopy, pSharedMem->szDllName, _countof(szSharedMemCopy) - 1); szSharedMemCopy[_countof(szSharedMemCopy) - 1] = '\0'; szNewDllName = szSharedMemCopy; } if (VERBOSITY > 0) { debugPrintf("inject: DLL_PROCESS_ATTACH\n"); } if (VERBOSITY > 0) { char szProcess[MAX_PATH]; GetModuleFileNameA(NULL, szProcess, sizeof szProcess); debugPrintf("inject: attached to process %s\n", szProcess); } if (VERBOSITY > 0) { debugPrintf("inject: loading %s\n", szNewDllName); } g_hHookModule = LoadLibraryA(szNewDllName); if (!g_hHookModule) { debugPrintf("inject: warning: failed to load %s\n", szNewDllName); return FALSE; } // Ensure we use kernel32.dll's CreateProcessAsUserW, and not advapi32.dll's. { HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); assert(hKernel32); pfnCreateProcessAsUserW = (PFNCREATEPROCESSASUSERW)GetProcAddress(hKernel32, "CreateProcessAsUserW"); } /* * Hook kernel32.dll functions, and its respective Windows API Set. * * http://msdn.microsoft.com/en-us/library/dn505783.aspx (Windows 8.1) * http://msdn.microsoft.com/en-us/library/hh802935.aspx (Windows 8) */ registerLibraryLoaderHooks("kernel32.dll"); registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-1-0.dll"); registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-1-1.dll"); registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-2-0.dll"); registerLibraryLoaderHooks("api-ms-win-core-kernel32-legacy-l1-1-0.dll"); registerLibraryLoaderHooks("api-ms-win-core-kernel32-legacy-l1-1-1.dll"); registerProcessThreadsHooks("kernel32.dll"); registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-0.dll"); registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-1.dll"); registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-2.dll"); szNewDllBaseName = getBaseName(szNewDllName); if (stricmp(szNewDllBaseName, "dxgitrace.dll") == 0) { registerModuleHooks("dxgi.dll", g_hHookModule); registerModuleHooks("d3d10.dll", g_hHookModule); registerModuleHooks("d3d10_1.dll", g_hHookModule); registerModuleHooks("d3d11.dll", g_hHookModule); registerModuleHooks("d3d9.dll", g_hHookModule); // for D3DPERF_* registerModuleHooks("dcomp.dll", g_hHookModule); } else if (stricmp(szNewDllBaseName, "d3d9.dll") == 0) { registerModuleHooks("d3d9.dll", g_hHookModule); registerModuleHooks("dxva2.dll", g_hHookModule); } else if (stricmp(szNewDllBaseName, "d2d1trace.dll") == 0) { registerModuleHooks("d2d1.dll", g_hHookModule); registerModuleHooks("dwrite.dll", g_hHookModule); } else { registerModuleHooks(szNewDllBaseName, g_hHookModule); } dumpRegisteredHooks(); patchAllModules(ACTION_HOOK); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (VERBOSITY > 0) { debugPrintf("inject: DLL_PROCESS_DETACH\n"); } assert(!lpvReserved); patchAllModules(ACTION_UNHOOK); if (g_hHookModule) { FreeLibrary(g_hHookModule); } break; } return TRUE; }
static void patchModule(HMODULE hModule, const char *szModule, Action action) { /* Never patch this module */ if (hModule == g_hThisModule) { return; } /* Never patch our hook module */ if (hModule == g_hHookModule) { return; } /* Hook modules only once */ if (action == ACTION_HOOK) { std::pair< std::set<HMODULE>::iterator, bool > ret; EnterCriticalSection(&g_Mutex); ret = g_hHookedModules.insert(hModule); LeaveCriticalSection(&g_Mutex); if (!ret.second) { return; } } const char *szBaseName = getBaseName(szModule); /* Don't hook our replacement modules to avoid tracing internal APIs */ /* XXX: is this really a good idea? */ if (isMatchModuleName(szBaseName)) { return; } /* Leave these modules alone. * * Hooking other injection DLLs easily leads to infinite recursion (and * stack overflow), especially when those libraries use techniques like * modifying the hooked functions prolog (instead of patching IAT like we * do). * * See also: * - http://www.nynaeve.net/?p=62 */ if (stricmp(szBaseName, "kernel32.dll") == 0 || stricmp(szBaseName, "AcLayers.dll") == 0 || stricmp(szBaseName, "ConEmuHk.dll") == 0 || stricmp(szBaseName, "gameoverlayrenderer.dll") == 0 || stricmp(szBaseName, "gameoverlayrenderer64.dll") == 0) { return; } if (VERBOSITY > 0) { debugPrintf("inject: found module %s\n", szModule); } PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getFirstImportDescriptor(hModule, szModule); if (pImportDescriptor) { while (pImportDescriptor->FirstThunk) { patchDescriptor(hModule, szModule, pImportDescriptor, action); ++pImportDescriptor; } } PImgDelayDescr pDelayDescriptor = getDelayImportDescriptor(hModule, szModule); if (pDelayDescriptor) { while (pDelayDescriptor->rvaDLLName) { if (VERBOSITY > 1) { const char* szName = getDescriptorName(hModule, pDelayDescriptor); debugPrintf("inject: found %sdelay-load import entry for module %s\n", pDelayDescriptor->grAttrs & dlattrRva ? "" : "old-style ", szName); } patchDescriptor(hModule, szModule, pDelayDescriptor, action); ++pDelayDescriptor; } } }
bool MystConsole::Cmd_CurCard(int argc, const char **argv) { debugPrintf("Current Card: %d\n", _vm->getCurCard()); return true; }
/* Main mex gateway routine */ void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] ) { integer iprint = (integer)1; integer task=(integer)START, csave=(integer)1; integer iterations = 0; integer total_iterations = 0; int iterMax = 100; int total_iterMax = 200; integer n, m, *nbd=NULL, *iwa=NULL; double f=0, factr, pgtol, *x, *l, *u, *g, *wa=NULL; int i; mxLogical FREE_nbd=false; int ndim = 2; /* for lcc compiler, must declare these here, not later ... */ mwSize dims[2] = { LENGTH_ISAVE, 1 }; logical lsave[LENGTH_LSAVE]; integer isave[LENGTH_ISAVE]; double dsave[LENGTH_DSAVE]; double *nbd_dbl=NULL; long long *nbd_long=NULL; mxArray *LHS[2]; mxArray *RHS[3]; double *tempX, *tempG, *tempIter; /* Parse inputs. Quite boring */ if (nrhs < 5 ) mexErrMsgTxt("Needs at least 5 input arguments"); m = (int)*mxGetPr( prhs[N_m] ); n = (integer)mxGetM( prhs[N_x] ); if ( mxGetN(prhs[N_x]) != 1 ) mexErrMsgTxt("x must be a column vector"); if ( mxGetM(prhs[N_l]) != n ) mexErrMsgTxt("l must have same size as x"); if ( mxGetM(prhs[N_u]) != n ) mexErrMsgTxt("u must have same size as x"); if ( mxGetM(prhs[N_nbd]) != n ) mexErrMsgTxt("nbd must have same size as x"); if (nlhs < 2 ) mexErrMsgTxt("Should have 2 or 3 output arguments"); if (!mxIsDouble(prhs[N_x])) mexErrMsgTxt("x should be of type double!\n"); plhs[1] = mxDuplicateArray( prhs[N_x] ); x = mxGetPr( plhs[1] ); l = mxGetPr( prhs[N_l] ); u = mxGetPr( prhs[N_u] ); if ( isInt( prhs[N_nbd] ) ) { nbd = (integer *)mxGetData( prhs[N_nbd] ); } else { debugPrintf("Converting nbd array to integers\n" ); if (!mxIsDouble(prhs[N_nbd])){ if (mxIsInt64(prhs[N_nbd])){ nbd_long = mxGetData( prhs[N_nbd] ); nbd = (integer *)mxMalloc( n * sizeof(integer) ); assert( nbd != NULL ); FREE_nbd = true; /* convert nbd_dbl (in double format) to integers */ for (i=0;i<n;i++) nbd[i] = (integer)nbd_long[i]; } else { debugPrintf("Sizeof(int) is %d bits, sizeof(integer) is %d bits\n", CHAR_BIT*sizeof(int),CHAR_BIT*sizeof(integer) ); /* integer is aliased to 'long int' and should be at least * 32 bits. 'long long' should be at least 64 bits. * On 64-bit Windows, it seems 'long int' is exactly 32 bits, * while on 64-bit linux and Mac, it is 67 bits */ debugPrintf("Nbd is of type %s\n", mxGetClassName( prhs[N_nbd] ) ); mexErrMsgTxt("Nbd array not doubles or type int64!\n"); } } else { nbd_dbl = mxGetPr( prhs[N_nbd] ); nbd = (integer *)mxMalloc( n * sizeof(integer) ); assert( nbd != NULL ); FREE_nbd = true; /* convert nbd_dbl (in double format) to integers */ for (i=0;i<n;i++) nbd[i] = (integer)nbd_dbl[i]; } } /* some scalar parameters */ if ( nrhs < N_factr+1 ) factr = 1.0e7; else if (mxGetNumberOfElements( prhs[N_factr] )!=1) factr = 1.0e7; else { factr = (double)mxGetScalar( prhs[N_factr] ); if (factr < 0 ) mexErrMsgTxt("factr must be >= 0\n"); } if ( nrhs < N_pgtol+1 ) pgtol = 1.0e-5; else if (mxGetNumberOfElements( prhs[N_pgtol] )!=1) pgtol = 1.0e-5; else { pgtol = (double)mxGetScalar( prhs[N_pgtol] ); if (pgtol < 0) mexErrMsgTxt("pgtol must be >= 0\n"); } if ( nrhs < N_iprint+1 ) { iprint = (integer)1; } else if (mxGetNumberOfElements( prhs[N_iprint] )!=1) { iprint = (integer)1; } else { iprint = (integer)mxGetScalar( prhs[N_iprint] ); } if ( nrhs >= N_iterMax+1 ) iterMax = (int)mxGetScalar( prhs[N_iterMax] ); if ( nrhs >= N_total_iterMax+1 ) total_iterMax = (int)mxGetScalar( prhs[N_total_iterMax] ); /* allocate memory for arrays */ g = (double *)mxMalloc( n * sizeof(double) ); assert( g != NULL ); wa = (double *)mxMalloc( (2*m*n + 5*n + 11*m*m + 8*m ) * sizeof(double) ); assert( wa != NULL ); iwa = (integer *)mxMalloc( (3*n)*sizeof(integer) ); assert( iwa != NULL ); /* -- Finally, done with parsing inputs. Now, call lbfgsb fortran routine */ /* Be careful! This modifies many variables in-place! * Basically, anything without a '&' before it will be changed in the Matlab * workspace */ if ( nrhs < N_fcn - 1 ) mexErrMsgTxt("For this f(x) feature, need more input aguments\n"); RHS[0] = mxDuplicateArray( prhs[N_fcn] ); RHS[1] = mxCreateDoubleMatrix(n,1,mxREAL); RHS[2] = mxCreateDoubleScalar( 0.0 ); /* The iterations counter */ tempX = (double*)mxGetPr( RHS[1] ); if (!mxIsDouble(RHS[2])) mexErrMsgTxt("Error trying to create RHS[2]\n"); tempIter = (double*)mxGetPr( RHS[2] ); while ( (iterations < iterMax) && (total_iterations < total_iterMax ) ){ total_iterations++; setulb(&n,&m,x,l,u,nbd,&f,g,&factr,&pgtol,wa,iwa,&task,&iprint, &csave,lsave,isave,dsave); /* (ftnlen) TASK_LEN, (ftnlen) CSAVE_LEN); */ if ( IS_FG(task) ) { /* copy data from x to RHS[1] or just set pointer with mxSetPr */ for (i=0;i<n;i++) tempX[i] = x[i]; /*Try being bold: */ /*mxSetPr( RHS[1], x ); */ *tempIter = (double)iterations; mexCallMATLAB(2,LHS,3,RHS,"feval"); f = mxGetScalar( LHS[0] ); if (mxGetM(LHS[1]) != n ) mexErrMsgTxt("Error with [f,g]=fcn(x) : g wrong size\n"); if (mxGetN(LHS[1]) != 1 ) mexErrMsgTxt("Error with [f,g]=fcn(x) : g wrong size (should be column vector)\n"); /* could use memcpy, or just do it by hand... */ if (!mxIsDouble(LHS[1])) mexErrMsgTxt("[f,g]=fcn(x) did not return g as type double\n"); tempG = mxGetPr( LHS[1] ); for (i=0;i<n;i++) g[i] = tempG[i]; /* Or, be a bit bolder: */ /*g = tempG; // Hmm, crashed */ continue; } if ( task==NEW_X ) { iterations++; continue; } else break; } mxDestroyArray( LHS[0] ); mxDestroyArray( LHS[1] ); mxDestroyArray( RHS[0] ); mxDestroyArray( RHS[1] ); plhs[0] = mxCreateDoubleScalar( f ); if ( nlhs >= 3 ) plhs[2] = mxCreateDoubleScalar( task ); if ( nlhs >= 4 ) plhs[3] = mxCreateDoubleScalar( iterations ); if ( nlhs >= 5 ) plhs[4] = mxCreateDoubleScalar( total_iterations ); if ( nlhs >= 6 ) mexErrMsgTxt("Did not expect more than 5 outputs\n"); if (FREE_nbd) mxFree(nbd); mxFree(g); mxFree(wa); mxFree(iwa); return; }
bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) { debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); return true; }
bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) { uint32 rmapCode = _vm->getCurCardRMAP(); debugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode); return true; }
bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { if (argc < 4) { debugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); return true; } uint16 oldStack = _vm->getCurStack(); uint newStack = kStackUnknown; for (uint i = kStackFirst; i <= kStackLast; i++) { if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) { newStack = i; break; } } if (newStack == kStackUnknown) { debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } _vm->changeToStack(newStack); // Load in Variable Names Common::SeekableReadStream *nameStream = _vm->getResource(ID_NAME, VariableNames); Common::StringArray varNames; uint16 namesCount = nameStream->readUint16BE(); uint16 *stringOffsets = new uint16[namesCount]; for (uint16 i = 0; i < namesCount; i++) stringOffsets[i] = nameStream->readUint16BE(); nameStream->seek(namesCount * 2, SEEK_CUR); int32 curNamesPos = nameStream->pos(); for (uint32 i = 0; i < namesCount; i++) { nameStream->seek(curNamesPos + stringOffsets[i]); Common::String name; for (char c = nameStream->readByte(); c; c = nameStream->readByte()) name += c; varNames.push_back(name); } delete nameStream; delete[] stringOffsets; // Load in External Command Names nameStream = _vm->getResource(ID_NAME, ExternalCommandNames); Common::StringArray xNames; namesCount = nameStream->readUint16BE(); stringOffsets = new uint16[namesCount]; for (uint16 i = 0; i < namesCount; i++) stringOffsets[i] = nameStream->readUint16BE(); nameStream->seek(namesCount * 2, SEEK_CUR); curNamesPos = nameStream->pos(); for (uint32 i = 0; i < namesCount; i++) { nameStream->seek(curNamesPos + stringOffsets[i]); Common::String name; for (char c = nameStream->readByte(); c; c = nameStream->readByte()) name += c; xNames.push_back(name); } delete nameStream; delete[] stringOffsets; // Get CARD/HSPT data and dump their scripts if (!scumm_stricmp(argv[2], "CARD")) { // Use debugN to print these because the scripts can get very large and would // really be useless if the the text console is not used. A DumpFile could also // theoretically be used, but I (clone2727) typically use this dynamically and // don't want countless files laying around without game context. If one would // want a file of a script they could just redirect stdout to a file or use // deriven. debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3])); debugN("==================================\n\n"); Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3])); cardStream->seek(4); RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false); for (uint32 i = 0; i < scriptList.size(); i++) { scriptList[i]->dumpScript(varNames, xNames, 0); delete scriptList[i]; } delete cardStream; } else if (!scumm_stricmp(argv[2], "HSPT")) { // See above for why this is printed via debugN debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3])); debugN("===========================================\n\n"); Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3])); uint16 hotspotCount = hsptStream->readUint16BE(); for (uint16 i = 0; i < hotspotCount; i++) { debugN("Hotspot %d:\n", i); hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false); for (uint32 j = 0; j < scriptList.size(); j++) { scriptList[j]->dumpScript(varNames, xNames, 1); delete scriptList[j]; } } delete hsptStream; } else { debugPrintf("%s doesn't have any scripts!\n", argv[2]); } // See above for why this is printed via debugN debugN("\n\n"); _vm->changeToStack(oldStack); debugPrintf("Script dump complete.\n"); return true; }
void ArticulatedViewer::onInit(const String& filename) { ArticulatedModel::clearCache(); Texture::clearCache(); m_filename = filename; m_selectedPart = NULL; m_selectedMesh = NULL; m_selectedTriangleIndex = -1; m_numFaces = 0; m_numVertices = 0; m_shadowMapDirty = true; UniversalMaterial::clearCache(); const RealTime start = System::time(); if (toLower(FilePath::ext(filename)) == "any") { if ((toLower(FilePath::ext(FilePath::base(filename))) == "material") || (toLower(FilePath::ext(FilePath::base(filename))) == "universalmaterial")) { // Assume that this is an .UniversalMaterial.Any file. Load a square and apply the material Any any(Any::TABLE, "ArticulatedModel::Specification"); any["filename"] = "model/crate/crate4xtex.obj"; any["stripMaterials"] = true; any["preprocess"] = Any(Any::ARRAY); Any arg(Any::ARRAY, "setMaterial"); arg.append(Any(Any::ARRAY, "all")); arg.append(Any::fromFile(filename)); any["preprocess"].append(arg); Any arg2(Any::ARRAY, "setTwoSided"); arg2.append(Any(Any::ARRAY, "all")); arg2.append(true); any["preprocess"].append(arg2); m_model = ArticulatedModel::create(ArticulatedModel::Specification(any)); } else { // Assume that this is an .ArticulatedModel.Any file Any any; any.load(filename); m_model = ArticulatedModel::create(ArticulatedModel::Specification(any)); } } else { m_model = ArticulatedModel::fromFile(filename); } debugPrintf("%s loaded in %f seconds\n", filename.c_str(), System::time() - start); Array<shared_ptr<Surface> > arrayModel; if (m_model->usesSkeletalAnimation()) { Array<G3D::String> animationNames; m_model->getAnimationNames(animationNames); // TODO: Add support for selecting animations. m_model->getAnimation(animationNames[0], m_animation); m_animation.getCurrentPose(0.0f, m_pose); } m_model->pose(arrayModel, CFrame(), m_pose); m_model->countTrianglesAndVertices(m_numFaces, m_numVertices); m_scale = 1; m_offset = Vector3::zero(); bool overwrite = true; // Find the size of the bounding box of the entire model AABox bounds; if (arrayModel.size() > 0) { for (int x = 0; x < arrayModel.size(); ++x) { //merges the bounding boxes of all the seperate parts into the bounding box of the entire object AABox temp; CFrame cframe; arrayModel[x]->getCoordinateFrame(cframe); arrayModel[x]->getObjectSpaceBoundingBox(temp); Box partBounds = cframe.toWorldSpace(temp); // Some models have screwed up bounding boxes if (partBounds.extent().isFinite()) { if (overwrite) { partBounds.getBounds(bounds); overwrite = false; } else { partBounds.getBounds(temp); bounds.merge(temp); } } } if (overwrite) { // We never found a part with a finite bounding box bounds = AABox(Vector3::zero()); } Vector3 extent = bounds.extent(); Vector3 center = bounds.center(); // Scale to X units float scale = 1.0f / max(extent.x, max(extent.y, extent.z)); if (scale <= 0) { scale = 1; } if (! isFinite(scale)) { scale = 1; } m_scale = scale; scale *= VIEW_SIZE; m_offset = -scale * center; if (! center.isFinite()) { center = Vector3(); } // Transform parts in-place m_model->scaleWholeModel(scale); ArticulatedModel::CleanGeometrySettings csg; // Merging vertices is slow and topology hasn't changed at all, so preclude vertex merging csg.allowVertexMerging = false; m_model->cleanGeometry(csg); } // Get the newly transformed animation if (m_model->usesSkeletalAnimation()) { Array<String> animationNames; m_model->getAnimationNames(animationNames); // TODO: Add support for selecting animations. m_model->getAnimation(animationNames[0], m_animation); m_animation.getCurrentPose(0.0f, m_pose); } // saveGeometry(); }
static FARPROC WINAPI MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { if (VERBOSITY >= 3) { /* XXX this can cause segmentation faults */ logGetProcAddress(hModule, lpProcName); } if (!NOOP) { char szModule[MAX_PATH]; DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule); assert(dwRet); const char *szBaseName = getBaseName(szModule); ModulesMap::const_iterator modIt; modIt = modulesMap.find(szBaseName); if (modIt != modulesMap.end()) { if (VERBOSITY > 1 && VERBOSITY < 3) { logGetProcAddress(hModule, lpProcName); } const Module & module = modIt->second; const FunctionMap & functionMap = module.functionMap; FunctionMap::const_iterator fnIt; if (HIWORD(lpProcName) == 0) { FARPROC proc = GetProcAddress(hModule, lpProcName); if (!proc) { return proc; } for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) { FARPROC pRealProc = GetProcAddress(hModule, fnIt->first); if (proc == pRealProc) { if (VERBOSITY > 0) { debugPrintf("inject: replacing %s!%s\n", szBaseName, lpProcName); } return (FARPROC)fnIt->second; } } debugPrintf("inject: ignoring %s!@%u\n", szBaseName, LOWORD(lpProcName)); return proc; } fnIt = functionMap.find(lpProcName); if (fnIt != functionMap.end()) { LPVOID pProcAddress = fnIt->second; if (VERBOSITY > 0) { debugPrintf("inject: replacing %s!%s\n", szBaseName, lpProcName); } if (!module.bInternal && pSharedMem) { pSharedMem->bReplaced = TRUE; } return (FARPROC)pProcAddress; } else { if (VERBOSITY > 0 && !module.bInternal) { debugPrintf("inject: ignoring %s!%s\n", szBaseName, lpProcName); } } } } return GetProcAddress(hModule, lpProcName); }
void Console::notifyBreakpoint(const char *filename, int line) { debugPrintf("Breakpoint hit %s: %d\n", filename, line); printSource(0); attach(); onFrame(); }
EXTERN_C void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) { debugPrintf("Assertion failed: %S, file %S, line %u\n", _Message, _File, _Line); TerminateProcess(GetCurrentProcess(), 1); }
void Console::notifyWatch(const char *filename, const char *symbol, const char *newValue) { debugPrintf("Watch: %s:%s <---- %s\n", filename, symbol, newValue); printSource(0); attach(); onFrame(); }
void Console::showIndent(int indentLevel) { for (int i = 0; i < indentLevel; ++i) { debugPrintf(" "); } }
void Console::printUsage(const Common::String &command) { // TODO: This is horrible and would probably benefit from a map or something. if (command.equals(BREAK_CMD)) { debugPrintf("Usage: %s <file path> <line> to break at line <line> of file <file path>\n", command.c_str()); } else if (command.equals(REMOVE_BREAKPOINT_CMD)) { debugPrintf("Usage: %s <id> to remove breakpoint #id\n", command.c_str()); } else if (command.equals(ENABLE_BREAKPOINT_CMD)) { debugPrintf("Usage: %s <id> to enable breakpoint #id\n", command.c_str()); } else if (command.equals(DISABLE_BREAKPOINT_CMD)) { debugPrintf("Usage: %s <id> to disable breakpoint #id\n", command.c_str()); } else if (command.equals(REMOVE_WATCH_CMD)) { debugPrintf("Usage: %s <id> to remove watchpoint #id\n", command.c_str()); } else if (command.equals(ENABLE_WATCH_CMD)) { debugPrintf("Usage: %s <id> to enable watchpoint #id\n", command.c_str()); } else if (command.equals(DISABLE_WATCH_CMD)) { debugPrintf("Usage: %s <id> to disable watchpoint #id\n", command.c_str()); } else if (command.equals(INFO_CMD)) { debugPrintf("Usage: %s [watch|breakpoints]\n", command.c_str()); } else if (command.equals(WATCH_CMD)) { debugPrintf("Usage: %s <file path> <name> to watch for <name> in file <file path>\n", command.c_str()); } else if (command.equals(STEP_CMD)) { debugPrintf("Usage: %s to step\n", command.c_str()); } else if (command.equals(CONTINUE_CMD)) { debugPrintf("Usage: %s to continue\n", command.c_str()); } else if (command.equals(FINISH_CMD)) { debugPrintf("Usage: %s to finish\n", command.c_str()); } else if (command.equals(PRINT_CMD)) { debugPrintf("Usage: %s <name> to print value of <name>\n", command.c_str()); } else if (command.equals(SET_CMD)) { debugPrintf("Usage: %s <name> = <value> to set <name> to <value>\n", command.c_str()); } else { debugPrintf("No help about this command, sorry."); } }
bool Console::cmd_dumpsceneinfo(int argc, const char **argv) { uint8 sceneId = _vm->getGame().getGameData()._currentScene; if (argc == 2) { sceneId = atoi(argv[1]); } else if (argc != 1) { debugPrintf("dumpsceneinfo [<sceneid>]\n"); } if (Scene *const scene = _vm->getGame().getGameData().getScene(sceneId)) { debugPrintf("Scene ID: %u\n", (unsigned int) sceneId); debugPrintf("Startup: %u\n", (unsigned int) scene->_startup); debugPrintf("Delay: %u\n", (unsigned int) scene->_delay); debugPrintf("Doors: %u\n", (unsigned int) scene->_noDoors); debugPrintf("Objects: %u\n", (unsigned int) scene->_noObjects); debugPrintf("Statics: %u\n", (unsigned int) scene->_noStatics); debugPrintf("ObstacleY1: %u\n", (unsigned int) scene->_obstacleY1); debugPrintf("PalRotFirst: %u\n", (unsigned int) scene->_palRotFirst); debugPrintf("PalRotLast: %u\n", (unsigned int) scene->_palRotLast); debugPrintf("PalRotDelay: %u\n", (unsigned int) scene->_palRotDelay); } else { debugPrintf("Scene %u not found.\n", (unsigned int) sceneId); } return true; }
static BOOL ejectDll(HANDLE hProcess, const char *szDllPath) { /* * Enumerate all modules. */ HMODULE *phModules = NULL; DWORD cb = sizeof *phModules * #ifdef NDEBUG 32 #else 4 #endif ; DWORD cbNeeded = 0; while (true) { phModules = (HMODULE *)realloc(phModules, cb); if (!EnumProcessModules(hProcess, phModules, cb, &cbNeeded)) { logLastError("failed to enumerate modules in remote process"); free(phModules); return FALSE; } if (cbNeeded < cb) { break; } cb *= 2; } DWORD cNumModules = cbNeeded / sizeof *phModules; /* * Search our DLL. */ const char *szDllName = getBaseName(szDllPath); HMODULE hModule = NULL; for (unsigned i = 0; i < cNumModules; ++i) { char szModName[MAX_PATH]; if (GetModuleFileNameExA(hProcess, phModules[i], szModName, ARRAY_SIZE(szModName))) { if (stricmp(getBaseName(szModName), szDllName) == 0) { hModule = phModules[i]; break; } } } free(phModules); if (!hModule) { debugPrintf("inject: error: failed to find %s module in the remote process\n", szDllName); return FALSE; } PTHREAD_START_ROUTINE lpStartAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("KERNEL32"), "FreeLibrary"); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, hModule, 0, NULL); if (!hThread) { logLastError("failed to create remote thread"); return FALSE; } WaitForSingleObject(hThread, INFINITE); DWORD bRet = 0; GetExitCodeThread(hThread, &bRet); if (!bRet) { debugPrintf("inject: error: failed to unload %s from the remote process\n", szDllPath); return FALSE; } return TRUE; }
bool Console::cmd_dumpdoorinfo(int argc, const char **argv) { if (argc == 3) { const uint8 sceneId = atoi(argv[1]); const uint8 doorId = atoi(argv[2]); Scene *const scene = _vm->getGame().getGameData().getScene(sceneId); if (scene) { Door *const door = scene->getDoor(doorId); if (door) { debugPrintf("Name: '%s'\n", convertToASCII(door->_name).c_str()); debugPrintf("DestSceneId: %u\n", (unsigned int) door->_destSceneId); debugPrintf("DestX: %u\n", (unsigned int) door->_destX); debugPrintf("DestY: %u\n", (unsigned int) door->_destY); debugPrintf("X: %u\n", (unsigned int) door->_x); debugPrintf("Y: %u\n", (unsigned int) door->_y); debugPrintf("Width: %u\n", (unsigned int) door->_width); debugPrintf("Height: %u\n", (unsigned int) door->_height); debugPrintf("WalkToX: %u\n", (unsigned int) door->_walkToX); debugPrintf("WalkToY: %u\n", (unsigned int) door->_walkToY); debugPrintf("SP: %u\n", (unsigned int) door->_SP); } else { debugPrintf("Door %u not found.\n", (unsigned int) doorId); } } else { debugPrintf("Scene %u not found.\n", (unsigned int) sceneId); } } else { debugPrintf("dumpdoorinfo <sceneid> <doorid>\n"); } return true; }
bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) { debugPrintf("Needed birthstone gems:\n"); for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i) debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); return true; }
bool Console::cmd_dumpobjectinfo(int argc, const char **argv) { if (argc == 3) { const uint8 sceneId = atoi(argv[1]); const uint8 objectId = atoi(argv[2]); Scene *const scene = _vm->getGame().getGameData().getScene(sceneId); if (scene) { Object *const object = scene->getObject(objectId); if (object) { debugPrintf("AC: %u\n", (unsigned int) object->_active); debugPrintf("FA: %u\n", (unsigned int) object->_firstFrame); debugPrintf("FR: %u\n", (unsigned int) object->_randomFrame); debugPrintf("NA: %u\n", (unsigned int) object->_numFrames); debugPrintf("FS: %u\n", (unsigned int) object->_roomFrameLSB); debugPrintf("Jump chance: %u\n", (unsigned int) object->_jumpChance); debugPrintf("CA: %u\n", (unsigned int) object->_currentFrame); debugPrintf("X: %u\n", (unsigned int) object->_x); debugPrintf("Y: %u\n", (unsigned int) object->_y); debugPrintf("XL: %u\n", (unsigned int) object->_width); debugPrintf("YL: %u\n", (unsigned int) object->_height); debugPrintf("WX: %u\n", (unsigned int) object->_WX); debugPrintf("WY: %u\n", (unsigned int) object->_roomFrameMSB); debugPrintf("SP: %u\n", (unsigned int) object->_SP); } else { debugPrintf("Object %u not found.\n", (unsigned int) objectId); } } else { debugPrintf("Scene %u not found.\n", (unsigned int) sceneId); } } else { debugPrintf("dumpobjectinfo <sceneid> <objectid>\n"); } return true; }
bool Debugger_EoB::cmdShowPosition(int, const char **) { debugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection); return true; }
bool Console::cmd_dumpstaticinfo(int argc, const char **argv) { if (argc == 3) { const uint8 sceneId = atoi(argv[1]); const uint8 staticId = atoi(argv[2]); Scene *const scene = _vm->getGame().getGameData().getScene(sceneId); if (scene) { Static *const stat = scene->getStatic(staticId, true); if (stat) { debugPrintf("Active: %u\n", (unsigned int) stat->_active); debugPrintf("Name: '%s'\n", convertToASCII(stat->_name).c_str()); debugPrintf("X: %u\n", (unsigned int) stat->_x); debugPrintf("Y: %u\n", (unsigned int) stat->_y); debugPrintf("Width: %u\n", (unsigned int) stat->_width); debugPrintf("Height: %u\n", (unsigned int) stat->_height); debugPrintf("WalkToX: %u\n", (unsigned int) stat->_walkToY); debugPrintf("WalkToY: %u\n", (unsigned int) stat->_walkToX); debugPrintf("WalkToFrame: %u\n", (unsigned int) stat->_walkToFrame); } else { debugPrintf("Static %u not found.\n", (unsigned int) staticId); } } else { debugPrintf("Scene %u not found.\n", (unsigned int) sceneId); } } else { debugPrintf("dumpstaticinfo <sceneid> <staticid>\n"); } return true; }
bool Console::cmdCurrentChapter(int argc, const char **argv) { debugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber()); return true; }
bool MystConsole::Cmd_CurStack(int argc, const char **argv) { debugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]); return true; }