/** * 吉里吉里に対して例外通知 */ void JSEXCEPTION(Isolate* isolate, TryCatch *try_catch) { HandleScope handle_scope(isolate); //HandleScope handle_scope; String::Value exception(try_catch->Exception()); Local<Message> message = try_catch->Message(); if (!message.IsEmpty()) { // 例外表示 String::Value filename(message->GetScriptResourceName()); ttstr msg; msg += *filename; msg += ":"; msg += tTJSVariant(message->GetLineNumber()); msg += ":"; msg += *exception; TVPAddLog(msg); // Print (filename):(line number): (message). String::Value sourceline(message->GetSourceLine()); TVPAddLog(ttstr(*sourceline)); // エラー行表示 ttstr wavy; int start = message->GetStartColumn(); for (int i = 0; i < start; i++) { wavy += " "; } int end = message->GetEndColumn(); for (int i = start; i < end; i++) { wavy +="^"; } TVPAddLog(wavy); // スタックトレース表示 String::Value stack_trace(try_catch->StackTrace()); if (stack_trace.length() > 0) { TVPAddLog(ttstr(*stack_trace)); } } TVPThrowExceptionMessage(*exception); }
void tTVPApplication::CheckDigitizer() { // Windows 7 以降でのみ有効 OSVERSIONINFOEX ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); ::GetVersionEx((OSVERSIONINFO*)&ovi); if( ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion >= 6 && ovi.dwMinorVersion >= 1 ) { int value = ::GetSystemMetrics(SM_DIGITIZER); if( value == 0 ) return; TVPAddLog( (const tjs_char*)TVPEnableDigitizer ); if( value & NID_INTEGRATED_TOUCH ) { TVPAddLog( (const tjs_char*)TVPTouchIntegratedTouch ); } if( value & NID_EXTERNAL_TOUCH ) { TVPAddLog( (const tjs_char*)TVPTouchExternalTouch ); } if( value & NID_INTEGRATED_PEN ) { TVPAddLog( (const tjs_char*)TVPTouchIntegratedPen ); } if( value & NID_EXTERNAL_PEN ) { TVPAddLog( (const tjs_char*)TVPTouchExternalPen ); } if( value & NID_MULTI_INPUT ) { TVPAddLog( (const tjs_char*)TVPTouchMultiInput ); } if( value & NID_READY ) { TVPAddLog( (const tjs_char*)TVPTouchReady ); } } }
static void log(const tjs_char *format, ...) { va_list args; va_start(args, format); tjs_char msg[1024]; _vsnwprintf(msg, 1024, format, args); TVPAddLog(msg); va_end(args); }
//--------------------------------------------------------------------------- void tTJSNI_VideoOverlay::SetRectangleToVideoOverlay() { // set Rectangle to video overlay if(VideoOverlay && OwnerWindow) { tjs_int ofsx, ofsy; Window->GetVideoOffset(ofsx, ofsy); tjs_int l = Rect.left; tjs_int t = Rect.top; tjs_int r = Rect.right; tjs_int b = Rect.bottom; TVPAddLog(TJS_W("Video zoom: (") + ttstr(l) + TJS_W(",") + ttstr(t) + TJS_W(")-(") + ttstr(r) + TJS_W(",") + ttstr(b) + TJS_W(") ->")); Window->ZoomRectangle(l, t, r, b); TVPAddLog(TJS_W("(") + ttstr(l) + TJS_W(",") + ttstr(t) + TJS_W(")-(") + ttstr(r) + TJS_W(",") + ttstr(b) + TJS_W(")")); RECT rect = {l + ofsx, t + ofsy, r + ofsx, b + ofsy}; VideoOverlay->SetRect(&rect); } }
//--------------------------------------------------------------------------- extern "C" HRESULT _stdcall _export V2Unlink() { // 吉里吉里側から、プラグインを解放しようとするときに呼ばれる関数。 // もし何らかの条件でプラグインを解放できない場合は // この時点で E_FAIL を返すようにする。 // ここでは、TVPPluginGlobalRefCount が GlobalRefCountAtInit よりも // 大きくなっていれば失敗ということにする。 TVPAddLog(TVPPluginGlobalRefCount); if(TVPPluginGlobalRefCount > GlobalRefCountAtInit) return E_FAIL; // E_FAIL が帰ると、Plugins.unlink メソッドは偽を返す // TJS のグローバルオブジェクトに登録した drawFFTGraph 関数を削除する // - まず、TJS のグローバルオブジェクトを取得する iTJSDispatch2 * global = TVPGetScriptDispatch(); // - global の DeleteMember メソッドを用い、オブジェクトを削除する if(global) { // TJS 自体が既に解放されていたときなどは // global は NULL になり得るので global が NULL でない // ことをチェックする global->DeleteMember( 0, // フラグ ( 0 でよい ) TJS_W("drawFFTGraph"), // メンバ名 NULL, // ヒント global // コンテキスト ); // 登録した関数が複数ある場合は これを繰り返す } // - global を Release する if(global) global->Release(); // スタブの使用終了(必ず記述する) TVPUninitImportStub(); // その他の処理 if(SampleBuffer) delete [] SampleBuffer, SampleBuffer = NULL; if(FFTData) delete [] FFTData, FFTData = NULL; if(WindowData) delete [] WindowData, WindowData = NULL; if(fft_ip) delete [] fft_ip, fft_ip = NULL; if(fft_w) delete[] fft_w, fft_w = NULL; if(BandData) delete [] BandData, BandData = NULL; if(BandPeakData) delete [] BandPeakData, BandPeakData = NULL; if(BandPeakCount) delete [] BandPeakCount, BandPeakCount = NULL; if(BandStart) delete [] BandStart, BandStart = NULL; if(BandEnd) delete [] BandEnd, BandEnd = NULL; return S_OK; }
extern "C" HRESULT _stdcall _export V2Link(iTVPFunctionExporter *exporter) { // スタブの初期化(必ず記述する) TVPInitImportStub(exporter); // TestFunction の作成と登録 tTJSVariant val; // TJS のグローバルオブジェクトを取得する iTJSDispatch2 * global = TVPGetScriptDispatch(); // 1 まずオブジェクトを作成 DrawFFTGraphFunction = new tDrawFFTGraphFunction(); // 2 DrawFFTGraphFunction を tTJSVariant 型に変換 val = tTJSVariant(DrawFFTGraphFunction); // 3 すでに val が DrawFFTGraphFunction を保持しているので、 // DrawFFTGraphFunction は Release する DrawFFTGraphFunction->Release(); // 4 global の PropSet メソッドを用い、オブジェクトを登録する global->PropSet( TJS_MEMBERENSURE, // メンバがなかった場合には作成するようにするフラグ TJS_W("drawFFTGraph"), // メンバ名 ( かならず TJS_W( ) で囲む ) NULL, // ヒント ( 本来はメンバ名のハッシュ値だが、NULL でもよい ) &val, // 登録する値 global // コンテキスト ( global でよい ) ); // - global を Release する global->Release(); // val をクリアする。 // これは必ず行う。そうしないと val が保持しているオブジェクト // が Release されず、次に使う TVPPluginGlobalRefCount が正確にならない。 val.Clear(); // この時点での TVPPluginGlobalRefCount の値を GlobalRefCountAtInit = TVPPluginGlobalRefCount; TVPAddLog(TVPPluginGlobalRefCount); // として控えておく。TVPPluginGlobalRefCount はこのプラグイン内で // 管理されている tTJSDispatch 派生オブジェクトの参照カウンタの総計で、 // 解放時にはこれと同じか、これよりも少なくなってないとならない。 // そうなってなければ、どこか別のところで関数などが参照されていて、 // プラグインは解放できないと言うことになる。 return S_OK; }
/** * 結果XMLから tTJSVariantを取得 * @param var 結果格納先 * @param xml 結果XML */ bool getVariantFromXML(tTJSVariant &var, tjs_char *xml) { try { xml_document doc; doc.parse<0>(xml); getVariantFromNode(var, doc.first_node()); return true; } catch(rapidxml::parse_error &err) { ttstr msg = ttstr(L"xml parse error:") + err.what(); TVPAddLog(msg); } return false; }
//--------------------------------------------------------------------------- tjs_error TJS_INTF_METHOD tTVPCrossFadeTransHandler:: StartProcess(tjs_uint64 tick) { // notifies starting of the update if(First) { First = false; StartTick = tick; } // compute phase ( 0 thru 255 ) Phase = (tick - StartTick) * PhaseMax / Time; if(Phase >= PhaseMax) Phase = PhaseMax; #ifdef TVP_TRANS_SHOW_FPS if((tick-StartTick) >= Time/2) { if(Count) { TVPAddLog(TJS_W("update count : ") + ttstr(Count)); TVPAddLog(TJS_W("trans time : ") + ttstr((tjs_int)(tick-StartTick))); TVPAddLog(TJS_W("process time : ") + ttstr((tjs_int)ProcessTime)); TVPAddLog(TJS_W("process time / trans time (%) : ") + ttstr((tjs_int)(ProcessTime*100/(tick-StartTick)))); TVPAddLog(TJS_W("blend time / trans time (%) : ") + ttstr((tjs_int)(BlendTime*100/(tick-StartTick)))); // TVPAddLog(TJS_W("blt time / trans time (%) : ") + // ttstr((tjs_int)(acctime*100/(tick-StartTick)))); tjs_int avgtime; avgtime = ProcessTime / Count; TVPAddLog(TJS_W("process time / update count : ") + ttstr(avgtime)); tjs_int fps = Count * 1000 / (tick - StartTick); TVPAddLog(TJS_W("fps : ") + ttstr(fps)); Count = 0; } } else { Count++; } ProcessTick = TVPGetRoughTickCount32(); #endif return TJS_S_TRUE; }
/** * シグナル送信 */ bool sendSignal(bool type) { if (process != INVALID_HANDLE_VALUE) { DWORD id = ::GetProcessId(process); DWORD ev = type ? CTRL_BREAK_EVENT : CTRL_C_EVENT; BOOL r = ::GenerateConsoleCtrlEvent(ev, id); if (!r) { if (::AttachConsole(id)) { r = ::GenerateConsoleCtrlEvent(ev, id); ::FreeConsole(); } else { ttstr err; getLastError(err); TVPAddLog(err.c_str()); } } return !!r; } return false; }
/** * サンプル値の取得(新方式) * getVisBuffer(buf, sampleCount, 1, sampleAhead)でサンプルを取得し, * (value/32768)^2の最大値を取得します。(0〜1の実数で返ります) * ※このプロパティを読み出すと暗黙でuseVisBuffer=trueに設定されます */ double getSampleValue() { memset(buf, 0, counts*sizeof(short)); tTJSVariant result; tjs_error r = objthis->FuncCall(0, TJS_W("getVisBuffer"), &hint, &result, 4, params, objthis); if (r != TJS_S_OK) TVPAddLog(ttstr(TJS_W("getVisBuffer failed: "))+ttstr(r)); int cnt = (int)result.AsInteger(); if (cnt > counts || cnt < 0) cnt = counts; // サンプルの二乗中の最大値を返す double max = 0; for (int i=cnt-1;i>=0;i--) { double s = ((double)buf[i]) / +32768.0; s *= s; if (max < s) max = s; } return max; }
//--------------------------------------------------------------------------- bool TJS_INTF_METHOD tTVPDrawDevice::SwitchToFullScreen( HWND window, tjs_uint w, tjs_uint h, tjs_uint bpp, tjs_uint color, bool changeresolution ) { // ChangeDisplaySettings を使用したフルスクリーン化 bool success = false; DEVMODE dm; ZeroMemory(&dm, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); dm.dmPelsWidth = w; dm.dmPelsHeight = h; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; dm.dmBitsPerPel = bpp; LONG ret = ::ChangeDisplaySettings((DEVMODE*)&dm, CDS_FULLSCREEN); switch(ret) { case DISP_CHANGE_SUCCESSFUL: ::SetWindowPos(window, HWND_TOP, 0, 0, w, h, SWP_SHOWWINDOW); success = true; break; case DISP_CHANGE_RESTART: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_RESTART") ); break; case DISP_CHANGE_BADFLAGS: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_BADFLAGS") ); break; case DISP_CHANGE_BADPARAM: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_BADPARAM") ); break; case DISP_CHANGE_FAILED: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_FAILED") ); break; case DISP_CHANGE_BADMODE: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_BADMODE") ); break; case DISP_CHANGE_NOTUPDATED: TVPAddLog( TJS_W("ChangeDisplaySettings failed: DISP_CHANGE_NOTUPDATED") ); break; default: TVPAddLog( TVPFormatMessage(TJS_W("ChangeDisplaySettings 失敗: 不明な理由 (%1)"),ttstr((tjs_int)ret)) ); break; } return success; }
/** * 実行用のXMLを生成する * @param XML文字列格納先 * @param numparams パラメータ数(1つ以上必要) * @param params パラメータ * @return 成功なら true */ bool createInvokeXML(std::wstring &xml, tjs_int numparams, tTJSVariant **params) { try { xml_document doc; xml_node *invoke = doc.allocate_node(rapidxml::node_element, L"invoke"); invoke->append_attribute(doc.allocate_attribute(L"name", params[0]->GetString())); invoke->append_attribute(doc.allocate_attribute(L"returntype", L"xml")); xml_node *args = doc.allocate_node(rapidxml::node_element, L"arguments"); for (int i=1;i<numparams;i++) { args->append_node(createNodeFromVariant(*params[i], doc)); } invoke->append_node(args); doc.append_node(invoke); rapidxml::print(std::back_inserter(xml), doc, rapidxml::print_no_indenting); return true; } catch(rapidxml::parse_error &err) { ttstr msg = ttstr("xml parse error:") + err.what(); TVPAddLog(msg); } return false; }
WaveSoundBufferAdd(iTJSDispatch2 *objthis) : objthis(objthis), counts(defaultCounts), aheads(defaultAheads), hint(0) { buf = new short[counts]; // useVisBuffer = true; にする tTJSVariant val(1); tjs_error r = objthis->PropSet(0, TJS_W("useVisBuffer"), NULL, &val, objthis); if (r != TJS_S_OK) TVPAddLog(ttstr(TJS_W("useVisBuffer=1 failed: ")) + ttstr(r)); // getVisBuffer用の引数を作る vBuffer = (tjs_int)buf; vChannel = 1; vNumSamples = counts; vAheads = aheads; params[0] = &vBuffer; params[1] = &vNumSamples; params[2] = &vChannel; params[3] = &vAheads; }
//--------------------------------------------------------------------------- void tTVPSusieArchivePlugin::GetFileList(std::wstring localname, std::vector<tTVPSusieFileRecord> &dest) { // retrieve file list TVPAddLog( TVPFormatMessage(TVPInfoListingFiles, ttstr(localname.c_str()) ) ); HLOCAL infohandle = NULL; int errorcode = 0xff&GetArchiveInfo(const_cast<LPSTR>(ttstr(localname).AsNarrowStdString().c_str()), 0, 0x00, &infohandle); if(infohandle == NULL) { TVPThrowExceptionMessage(TVPSusiePluginError, ttstr(TJS_W("tTVPSusieArchivePlugin::GetArchiveInfo failed, errorcode = ")) + ttstr((tjs_int)errorcode)); } else { if(errorcode != 0) { TVPAddLog(TJS_W("Warning : invalid errorcode ") + ttstr((tjs_int)errorcode) + TJS_W(" was returned from tTVPSusieArchivePlugin::GetArchiveInfo, ") TJS_W("continuing anyway.")); } } const tTVPSusieFileInfo *info = (const tTVPSusieFileInfo*)LocalLock(infohandle); if(info == NULL) { TVPThrowExceptionMessage(TVPSusiePluginError, ttstr(TJS_W("tTVPSusieArchivePlugin::GetArchiveInfo failed : invalid memory block."))); } try { while(info->method[0]) { if(info->filename[0]) { char buf[401]; TJS_nstrcpy(buf, info->path); TJS_nstrcat(buf, "/"); TJS_nstrcat(buf, info->filename); tTVPSusieFileRecord record; record.Name = buf; tTVPArchive::NormalizeInArchiveStorageName(record.Name); record.Position = info->position; record.Size = info->filesize; dest.push_back(record); } info++; } // sort item vector by its name (required for tTVPArchive specification) std::stable_sort(dest.begin(), dest.end()); } catch(...) { LocalUnlock(infohandle); LocalFree(infohandle); throw; } LocalUnlock(infohandle); LocalFree(infohandle); TVPAddLog(TJS_W("(info) ") + ttstr((tjs_int)dest.size()) + TJS_W(" files found.")); }
//--------------------------------------------------------------------------- void TVPDumpHWException() { // dump latest hardware exception if it exists if(!TVPHWExcRaised) return; TVPHWExcRaised = false; TVPOnError(); tjs_char buf[256]; tTVPHWExceptionData * d = &TVPLastHWExceptionData; TVPAddLog(ttstr(TVPHardwareExceptionRaised)); ttstr line; line = TJS_W("Exception : "); tjs_char *p = NULL; switch(d->Code) { case 3: p = TJS_W("Divide By Zero"); break; case 4: p = TJS_W("Range Error"); break; case 5: p = TJS_W("Integer Overflow"); break; case 6: p = TJS_W("Invalid Operation"); break; case 7: p = TJS_W("Zero Divide"); break; case 8: p = TJS_W("Overflow"); break; case 9: p = TJS_W("Underflow"); break; case 10: p = TJS_W("Invalid Cast"); break; case 11: p = TJS_W("Access Violation"); break; case 12: p = TJS_W("Privilege Violation"); break; case 13: p = TJS_W("Control C"); break; case 14: p = TJS_W("Stack Overflow"); break; } if(p) line += p; if(d->Code == 11) { // EAccessViolation const tjs_char *mode = TJS_W("unknown"); if(d->AccessFlag == 0) mode = TJS_W("read"); else if(d->AccessFlag == 1) mode = TJS_W("write"); else if(d->AccessFlag == 8) mode = TJS_W("execute"); TJS_sprintf(buf, TJS_W("(%ls access to 0x%p)"), mode, d->AccessTarget); line += buf; } TJS_sprintf(buf, TJS_W(" at EIP = 0x%p ESP = 0x%p"), d->EIP, d->ESP); line += buf; if(d->Module[0]) { line += TJS_W(" in ") + ttstr(d->Module); } TVPAddLog(line); // dump OS context TVPDumpOSContext(d->Context); // dump codes at EIP line = TJS_W("Codes at EIP : "); for(tjs_int i = 0; i<d->CodesAtEIPLen; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->CodesAtEIP[i]); line += buf; } TVPAddLog(line); TVPAddLog(TJS_W("Stack data and data pointed by each stack data :")); // dump stack and data for(tjs_int s = 0; s<d->StackAtESPLen; s++) { TJS_sprintf(buf, TJS_W("0x%p (ESP+%3d) : 0x%p : "), (DWORD)d->ESP + s*sizeof(tjs_uint32), s*sizeof(tjs_uint32), d->StackAtESP[s]); line = buf; for(tjs_int i = 0; i<d->StackDumpsLen[s]; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->StackDumps[s][i]); line += buf; } TVPAddLog(line); } // dump call trace TVPAddLog(TJS_W("Call Trace :")); for(tjs_int s = 0; s<d->CallTraceLen; s++) { TJS_sprintf(buf, TJS_W("0x%p : "), d->CallTrace[s]); line = buf; for(tjs_int i = 0; i<d->CallTraceDumpsLen[s]; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->CallTraceDumps[s][i]); line += buf; } MEMORY_BASIC_INFORMATION mbi; VirtualQuery((void*)d->CallTrace[s], &mbi, sizeof(mbi)); if(mbi.State == MEM_COMMIT) { char module[MAX_PATH]; if(GetModuleFileName((HMODULE)mbi.AllocationBase, module, MAX_PATH)) { line += ttstr(ExtractFileName(module).c_str()); TJS_sprintf(buf, TJS_W(" base 0x%p"), mbi.AllocationBase); line += buf; } } TVPAddLog(line); } }
//--------------------------------------------------------------------------- void TVPDumpOSContext(const CONTEXT &ctx) { // dump OS context block tjs_char buf[256]; // mask FP exception TJSSetFPUE(); // - context flags ttstr line; TJS_sprintf(buf, TJS_W("Context Flags : 0x%08X [ "), ctx.ContextFlags); line += buf; if(ctx.ContextFlags & CONTEXT_DEBUG_REGISTERS) line += TJS_W("CONTEXT_DEBUG_REGISTERS "); if(ctx.ContextFlags & CONTEXT_FLOATING_POINT) line += TJS_W("CONTEXT_FLOATING_POINT "); if(ctx.ContextFlags & CONTEXT_SEGMENTS) line += TJS_W("CONTEXT_SEGMENTS "); if(ctx.ContextFlags & CONTEXT_INTEGER) line += TJS_W("CONTEXT_INTEGER "); if(ctx.ContextFlags & CONTEXT_CONTROL) line += TJS_W("CONTEXT_CONTROL "); if(ctx.ContextFlags & CONTEXT_EXTENDED_REGISTERS) line += TJS_W("CONTEXT_EXTENDED_REGISTERS "); line += TJS_W("]"); TVPAddLog(line); // - debug registers TJS_sprintf(buf, TJS_W( "Debug Registers : " "0:0x%08X " "1:0x%08X " "2:0x%08X " "3:0x%08X " "6:0x%08X " "7:0x%08X "), ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr6, ctx.Dr7); TVPAddLog(buf); // - Segment registers TJS_sprintf(buf, TJS_W("Segment Registers : GS:0x%04X FS:0x%04X ES:0x%04X DS:0x%04X CS:0x%04X SS:0x%04X"), ctx.SegGs, ctx.SegFs, ctx.SegEs, ctx.SegDs, ctx.SegCs, ctx.SegSs); TVPAddLog(buf); // - Generic Integer Registers TJS_sprintf(buf, TJS_W("Integer Registers : EAX:0x%08X EBX:0x%08X ECX:0x%08X EDX:0x%08X"), ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx); TVPAddLog(buf); // - Index Registers TJS_sprintf(buf, TJS_W("Index Registers : ESI:0x%08X EDI:0x%08X"), ctx.Esi, ctx.Edi); TVPAddLog(buf); // - Pointer Registers TJS_sprintf(buf, TJS_W("Pointer Registers : EBP:0x%08X ESP:0x%08X EIP:0x%08X"), ctx.Ebp, ctx.Esp, ctx.Eip); TVPAddLog(buf); // - Flag Register TJS_sprintf(buf, TJS_W("Flag Register : 0x%08X [ "), ctx.EFlags); line = buf; TVPDumpCPUFlags(line, ctx.EFlags, (1<< 0), TJS_W("CF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 2), TJS_W("PF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 4), TJS_W("AF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 6), TJS_W("ZF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 7), TJS_W("SF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 8), TJS_W("TF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 9), TJS_W("IF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<10), TJS_W("DF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<11), TJS_W("OF")); TJS_sprintf(buf, TJS_W("IO%d "), (ctx.EFlags >> 12) & 0x03); line += buf; TVPDumpCPUFlags(line, ctx.EFlags, (1<<14), TJS_W("NF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<16), TJS_W("RF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<17), TJS_W("VM")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<18), TJS_W("AC")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<19), TJS_W("VF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<20), TJS_W("VP")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<21), TJS_W("ID")); line += TJS_W("]"); TVPAddLog(line); // - FP registers // -- control words TJS_sprintf(buf, TJS_W("FP Control Word : 0x%08X FP Status Word : 0x%08X FP Tag Word : 0x%08X"), ctx.FloatSave.ControlWord, ctx.FloatSave.StatusWord, ctx.FloatSave.TagWord); TVPAddLog(buf); // -- offsets/selectors TJS_sprintf(buf, TJS_W("FP Error Offset : 0x%08X FP Error Selector : 0x%08X"), ctx.FloatSave.ErrorOffset, ctx.FloatSave.ErrorSelector); TJS_sprintf(buf, TJS_W("FP Data Offset : 0x%08X FP Data Selector : 0x%08X"), ctx.FloatSave.DataOffset, ctx.FloatSave.DataSelector); // -- registers long double *ptr = (long double *)&(ctx.FloatSave.RegisterArea[0]); for(tjs_int i = 0; i < 8; i++) { TJS_sprintf(buf, TJS_W("FP ST(%d) : %28.20Lg 0x%04X%016I64X"), i, ptr[i], (unsigned int)*(tjs_uint16*)(((tjs_uint8*)(ptr + i)) + 8), *(tjs_uint64*)(ptr + i)); TVPAddLog(buf); } // -- Cr0NpxState TJS_sprintf(buf, TJS_W("FP CR0 NPX State : 0x%08X"), ctx.FloatSave.Cr0NpxState); TVPAddLog(buf); // -- SSE/SSE2 registers if(ctx.ContextFlags & CONTEXT_EXTENDED_REGISTERS) { // ExtendedRegisters is a area which meets fxsave and fxrstor instruction? #pragma pack(push,1) union xmm_t { struct { float sA; float sB; float sC; float sD; }; struct { double dA; double dB; }; struct { tjs_uint64 i64A; tjs_uint64 i64B; }; }; #pragma pack(pop) for(tjs_int i = 0; i < 8; i++) { xmm_t * xmm = (xmm_t *)(ctx.ExtendedRegisters + i * 16+ 0xa0); TJS_sprintf(buf, TJS_W("XMM %d : [ %15.8g %15.8g %15.8g %15.8g ] [ %24.16lg %24.16lg ] [ 0x%016I64X-0x%016I64X ]"), i, xmm->sD, xmm->sC, xmm->sB, xmm->sA, xmm->dB, xmm->dA, xmm->i64B, xmm->i64A); TVPAddLog(buf); } TJS_sprintf(buf, TJS_W("MXCSR : 0x%08X"), *(DWORD*)(ctx.ExtendedRegisters + 0x18)); TVPAddLog(buf); } }