#include "oslib\oslib.h" #include "oslib\audiostream_rif.h" #define _WIN32_WINNT 0x0500 #include PCHAR* CommandLineToArgvA( PCHAR CmdLine, int* _argc ) { PCHAR* argv; PCHAR _argv; ULONG len; ULONG argc; CHAR a; ULONG i, j; BOOLEAN in_QM; BOOLEAN in_TEXT; BOOLEAN in_SPACE; len = strlen(CmdLine); i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID); argv = (PCHAR*)GlobalAlloc(GMEM_FIXED, i + (len+2)*sizeof(CHAR)); _argv = (PCHAR)(((PUCHAR)argv)+i); argc = 0; argv[argc] = _argv; in_QM = FALSE; in_TEXT = FALSE; in_SPACE = TRUE; i = 0; j = 0; while( a = CmdLine[i] ) { if(in_QM) { if(a == '\"') { in_QM = FALSE; } else { _argv[j] = a; j++; } } else { switch(a) { case '\"': in_QM = TRUE; in_TEXT = TRUE; if(in_SPACE) { argv[argc] = _argv+j; argc++; } in_SPACE = FALSE; break; case ' ': case '\t': case '\n': case '\r': if(in_TEXT) { _argv[j] = '\0'; j++; } in_TEXT = FALSE; in_SPACE = TRUE; break; default: in_TEXT = TRUE; if(in_SPACE) { argv[argc] = _argv+j; argc++; } _argv[j] = a; j++; in_SPACE = FALSE; break; } } i++; } _argv[j] = '\0'; argv[argc] = NULL; (*_argc) = argc; return argv; } bool VramLockedWrite(u8* address); bool ngen_Rewrite(unat& addr,unat retadr,unat acc); bool BM_LockedWrite(u8* address); int ExeptionHandler(u32 dwCode, void* pExceptionPointers) { EXCEPTION_POINTERS* ep=(EXCEPTION_POINTERS*)pExceptionPointers; EXCEPTION_RECORD* pExceptionRecord=ep->ExceptionRecord; if (dwCode != EXCEPTION_ACCESS_VIOLATION) return EXCEPTION_CONTINUE_SEARCH; u8* address=(u8*)pExceptionRecord->ExceptionInformation[1]; if (VramLockedWrite(address)) { return EXCEPTION_CONTINUE_EXECUTION; } else if (BM_LockedWrite(address)) { return EXCEPTION_CONTINUE_EXECUTION; } else if ( ngen_Rewrite((unat&)ep->ContextRecord->Eip,*(unat*)ep->ContextRecord->Esp,ep->ContextRecord->Eax) ) { //remove the call from call stack ep->ContextRecord->Esp+=4; //restore the addr from eax to ecx so its valid again ep->ContextRecord->Ecx=ep->ContextRecord->Eax; return EXCEPTION_CONTINUE_EXECUTION; } else { printf("[GPF]Unhandled access to : 0x%X\n",address); } return EXCEPTION_CONTINUE_SEARCH; } void SetupPath() { char fname[512]; GetModuleFileName(0,fname,512); string fn=string(fname); fn=fn.substr(0,fn.find_last_of('\\')); SetHomeDir(fn); } int msgboxf(const wchar* text,unsigned int type,...) { va_list args; wchar temp[2048]; va_start(args, type); vsprintf(temp, text, args); va_end(args); return MessageBox(NULL,temp,VER_SHORTNAME,type | MB_TASKMODAL); } u16 kcode[4]; u32 vks[4]; s8 joyx[4],joyy[4]; u8 rt[4],lt[4]; #define key_CONT_C (1 << 0) #define key_CONT_B (1 << 1) #define key_CONT_A (1 << 2) #define key_CONT_START (1 << 3) #define key_CONT_DPAD_UP (1 << 4) #define key_CONT_DPAD_DOWN (1 << 5) #define key_CONT_DPAD_LEFT (1 << 6) #define key_CONT_DPAD_RIGHT (1 << 7) #define key_CONT_Z (1 << 8) #define key_CONT_Y (1 << 9) #define key_CONT_X (1 << 10) #define key_CONT_D (1 << 11) #define key_CONT_DPAD2_UP (1 << 12) #define key_CONT_DPAD2_DOWN (1 << 13) #define key_CONT_DPAD2_LEFT (1 << 14) #define key_CONT_DPAD2_RIGHT (1 << 15) void UpdateInputState(u32 port) { //joyx[port]=pad.Lx; //joyy[port]=pad.Ly; lt[port]=GetAsyncKeyState('A')?255:0; rt[port]=GetAsyncKeyState('S')?255:0; joyx[port]=joyy[port]=0; if (GetAsyncKeyState('J')) joyx[port]-=126; if (GetAsyncKeyState('L')) joyx[port]+=126; if (GetAsyncKeyState('I')) joyy[port]-=126; if (GetAsyncKeyState('K')) joyy[port]+=126; kcode[port]=0xFFFF; if (GetAsyncKeyState('V')) kcode[port]&=~key_CONT_A; if (GetAsyncKeyState('C')) kcode[port]&=~key_CONT_B; if (GetAsyncKeyState('X')) kcode[port]&=~key_CONT_Y; if (GetAsyncKeyState('Z')) kcode[port]&=~key_CONT_X; if (GetAsyncKeyState(VK_SHIFT)) kcode[port]&=~key_CONT_START; if (GetAsyncKeyState(VK_UP)) kcode[port]&=~key_CONT_DPAD_UP; if (GetAsyncKeyState(VK_DOWN)) kcode[port]&=~key_CONT_DPAD_DOWN; if (GetAsyncKeyState(VK_LEFT)) kcode[port]&=~key_CONT_DPAD_LEFT; if (GetAsyncKeyState(VK_RIGHT)) kcode[port]&=~key_CONT_DPAD_RIGHT; if (GetAsyncKeyState('1')) settings.pvr.ta_skip = 1; if (GetAsyncKeyState('2')) settings.pvr.ta_skip = 0; } LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { /* Here we are handling 2 system messages: screen saving and monitor power. They are especially relevent on mobile devices. */ case WM_SYSCOMMAND: { switch (wParam) { case SC_SCREENSAVE: // Screensaver trying to start ? case SC_MONITORPOWER: // Monitor trying to enter powersave ? return 0; // Prevent this from happening } break; } // Handles the close message when a user clicks the quit icon of the window case WM_CLOSE: PostQuitMessage(0); return 1; default: break; } // Calls the default window procedure for messages we did not handle return DefWindowProc(hWnd, message, wParam, lParam); } // Windows class name to register #define WINDOW_CLASS "nilDC" // Width and height of the window #define WINDOW_WIDTH 1024 #define WINDOW_HEIGHT 512 void* window_win; void os_CreateWindow() { WNDCLASS sWC; sWC.style = CS_HREDRAW | CS_VREDRAW; sWC.lpfnWndProc = WndProc2; sWC.cbClsExtra = 0; sWC.cbWndExtra = 0; sWC.hInstance = (HINSTANCE)GetModuleHandle(0); sWC.hIcon = 0; sWC.hCursor = 0; sWC.lpszMenuName = 0; sWC.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); sWC.lpszClassName = WINDOW_CLASS; unsigned int nWidth = WINDOW_WIDTH; unsigned int nHeight = WINDOW_HEIGHT; ATOM registerClass = RegisterClass(&sWC); if (!registerClass) { MessageBox(0, ("Failed to register the window class"), ("Error"), MB_OK | MB_ICONEXCLAMATION); } // Create the eglWindow RECT sRect; SetRect(&sRect, 0, 0, nWidth, nHeight); AdjustWindowRectEx(&sRect, WS_CAPTION | WS_SYSMENU, false, 0); HWND hWnd = CreateWindow( WINDOW_CLASS, VER_FULLNAME, WS_VISIBLE | WS_SYSMENU, 0, 0, sRect.right-sRect.left, sRect.bottom-sRect.top, NULL, NULL, sWC.hInstance, NULL); window_win=hWnd; void os_InitAudio(); os_InitAudio(); } void* libPvr_GetRenderTarget() { return window_win; } void* libPvr_GetRenderSurface() { return GetDC((HWND)window_win); } BOOL CtrlHandler( DWORD fdwCtrlType ) { switch( fdwCtrlType ) { case CTRL_SHUTDOWN_EVENT: case CTRL_LOGOFF_EVENT: // Pass other signals to the next handler. case CTRL_BREAK_EVENT: // CTRL-CLOSE: confirm that the user wants to exit. case CTRL_CLOSE_EVENT: // Handle the CTRL-C signal. case CTRL_C_EVENT: SendMessageA((HWND)libPvr_GetRenderTarget(),WM_CLOSE,0,0); //FIXEM return( TRUE ); default: return FALSE; } } void os_SetWindowText(const char* text) { if (GetWindowLong((HWND)libPvr_GetRenderTarget(),GWL_STYLE)&WS_BORDER) { SetWindowText((HWND)libPvr_GetRenderTarget(), text); } } void os_MakeExecutable(void* ptr, u32 sz) { DWORD old; VirtualProtect(ptr,sizeof(sz),PAGE_EXECUTE_READWRITE,&old); } u64 cycl_glob; cResetEvent evt_hld(false,true); double speed_load_mspdf; extern double full_rps; void os_wait_cycl(u32 cycl) { if (cycl>8*1000*1000) cycl=8*1000*1000; static double trolol=os_GetSeconds(); double newt=os_GetSeconds(); double ets=(newt-trolol)*200*1000*1000; bool fast_enough=ets < cycl; bool wait = full_rps >5 && (fast_enough || os_IsAudioBufferedLots()); speed_load_mspdf=(speed_load_mspdf*0.96235 + ets/cycl*10)/1.96235; if (wait && os_IsAudioBuffered()) { while (cycl_globcycl) InterlockedExchangeSubtract(&cycl_glob,cycl); } else //if (os_IsAudioBufferedLots()) { //cycl_glob=0; } static int last_fe=fast_enough; if (!fast_enough || !last_fe) printf("Speed %.2f (%.2f%%) (%d)\n",ets/cycl*10,cycl/ets*100,os_getusedSamples()); last_fe=fast_enough; trolol=os_GetSeconds(); } void os_consume(double t) { double cyc=t*190*1000*1000; if ((cycl_glob+cyc)<10*1000*1000) { InterlockedExchangeAdd(&cycl_glob,cyc); } else cycl_glob=10*1000*1000; evt_hld.Set(); } void* tick_th(void* p) { SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL); double old=os_GetSeconds(); for(;;) { Sleep(4); double newt=os_GetSeconds(); os_consume(newt-old); old=newt; } } cThread tick_thd(&tick_th,0); int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShowCmd) { tick_thd.Start(); int argc=0; wchar* cmd_line=GetCommandLineA(); wchar** argv=CommandLineToArgvA(cmd_line,&argc); if(strstr(cmd_line,"NoConsole")==0) { if (AllocConsole()) { freopen("CON","w",stdout); freopen("CON","w",stderr); freopen("CON","r",stdin); } SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ); } SetupPath(); __try { int dc_init(int argc,wchar* argv[]); void dc_run(); void dc_term(); dc_init(argc,argv); dc_run(); dc_term(); } __except( (EXCEPTION_CONTINUE_EXECUTION==ExeptionHandler( GetExceptionCode(), (GetExceptionInformation()))) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH ) { printf("Unhandled exeption ; Emulation thread halted...\n"); } return 0; } LARGE_INTEGER qpf; double qpfd; //Helper functions double os_GetSeconds() { static bool initme = (QueryPerformanceFrequency(&qpf), qpfd=1/(double)qpf.QuadPart); LARGE_INTEGER time_now; QueryPerformanceCounter(&time_now); return time_now.QuadPart*qpfd; } //#include "plugins/plugin_manager.h" void os_DoEvents() { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // If the message is WM_QUIT, exit the while loop if (msg.message == WM_QUIT) { sh4_cpu.Stop(); } // Translate the message and dispatch it to WindowProc() TranslateMessage(&msg); DispatchMessage(&msg); } } //Windoze Code implementation of commong classes from here and after .. //Thread class cThread::cThread(ThreadEntryFP* function,void* prm) { Entry=function; param=prm; } void cThread::Start() { hThread=CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)Entry,param,0,NULL); ResumeThread(hThread); } void cThread::WaitToEnd() { WaitForSingleObject(hThread,INFINITE); } //End thread class //cResetEvent Calss cResetEvent::cResetEvent(bool State,bool Auto) { hEvent = CreateEvent( NULL, // default security attributes Auto?FALSE:TRUE, // auto-reset event? State?TRUE:FALSE, // initial state is State NULL // unnamed object ); } cResetEvent::~cResetEvent() { //Destroy the event object ? CloseHandle(hEvent); } void cResetEvent::Set()//Signal { SetEvent(hEvent); } void cResetEvent::Reset()//reset { ResetEvent(hEvent); } void cResetEvent::Wait(u32 msec)//Wait for signal , then reset { WaitForSingleObject(hEvent,msec); } void cResetEvent::Wait()//Wait for signal , then reset { WaitForSingleObject(hEvent,(u32)-1); } //End AutoResetEvent void VArray2::LockRegion(u32 offset,u32 size) { //verify(offset+sizesize); verify(size!=0); DWORD old; VirtualProtect(((u8*)data)+offset , size, PAGE_READONLY,&old); } void VArray2::UnLockRegion(u32 offset,u32 size) { //verify(offset+size<=this->size); verify(size!=0); DWORD old; VirtualProtect(((u8*)data)+offset , size, PAGE_READWRITE,&old); }