/* Mupen64plus-video-jabo */ #include #include #include #include #include #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_common.h" #include "m64p_config.h" #include "main.h" #include "typedefs.h" #include "Config.h" #define LOG(x) { std::ofstream myfile; myfile.open ("jabo_wrapper_log.txt", std::ios::app); myfile << x << "\n"; myfile.close(); } namespace OldAPI { #include "jabo_api.h" ptr_InitiateGFX InitiateGFX = NULL; ptr_ProcessDList ProcessDList = NULL; ptr_ProcessRDPList ProcessRDPList = NULL; ptr_ShowCFB ShowCFB = NULL; ptr_ViStatusChanged ViStatusChanged = NULL; ptr_ViWidthChanged ViWidthChanged = NULL; ptr_RomOpen RomOpen = NULL; ptr_RomClosed RomClosed = NULL; ptr_CloseDLL CloseDLL = NULL; ptr_DrawScreen DrawScreen = NULL; ptr_MoveScreen MoveScreen = NULL; ptr_UpdateScreen UpdateScreen = NULL; ptr_DllConfig DllConfig = NULL; ptr_GetDllInfo GetDllInfo = NULL; } ptr_ConfigOpenSection ConfigOpenSection = NULL; ptr_ConfigSetParameter ConfigSetParameter = NULL; ptr_ConfigGetParameter ConfigGetParameter = NULL; ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; ptr_ConfigGetParamInt ConfigGetParamInt = NULL; ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; ptr_ConfigGetParamBool ConfigGetParamBool = NULL; ptr_ConfigGetParamString ConfigGetParamString = NULL; /* local variables */ static void (*l_DebugCallback)(void *, int, const char *) = NULL; static void *l_DebugCallContext = NULL; static int l_PluginInit = 0; HMODULE JaboDLL; HWND hWnd_jabo; HANDLE window_thread = NULL; HMODULE D3D8Dll; typedef void (*ptr_D3D8_SetRenderingCallback)(void (*callback)(int)); ptr_D3D8_SetRenderingCallback D3D8_SetRenderingCallback = NULL; typedef void (*ptr_D3D8_ReadScreen)(void *dest, int *width, int *height); ptr_D3D8_ReadScreen D3D8_ReadScreen = NULL; typedef void (*ptr_D3D8_CloseDLL)(); ptr_D3D8_CloseDLL D3D8_CloseDLL = NULL; DWORD old_options; DWORD old_initflags; void setup_jabo_functions() { JaboDLL = LoadLibrary("Jabotard_Direct3D8.dll"); if (JaboDLL != NULL) { OldAPI::InitiateGFX = (OldAPI::ptr_InitiateGFX)GetProcAddress(JaboDLL,"InitiateGFX"); OldAPI::ProcessDList = (OldAPI::ptr_ProcessDList)GetProcAddress(JaboDLL,"ProcessDList"); OldAPI::ProcessRDPList = (OldAPI::ptr_ProcessRDPList)GetProcAddress(JaboDLL,"ProcessRDPList"); OldAPI::ShowCFB = (OldAPI::ptr_ShowCFB)GetProcAddress(JaboDLL,"ShowCFB"); OldAPI::ViStatusChanged = (OldAPI::ptr_ViStatusChanged)GetProcAddress(JaboDLL,"ViStatusChanged"); OldAPI::ViWidthChanged = (OldAPI::ptr_ViWidthChanged)GetProcAddress(JaboDLL,"ViWidthChanged"); OldAPI::RomOpen = (OldAPI::ptr_RomOpen)GetProcAddress(JaboDLL,"RomOpen"); OldAPI::RomClosed = (OldAPI::ptr_RomClosed)GetProcAddress(JaboDLL,"RomClosed"); OldAPI::CloseDLL = (OldAPI::ptr_CloseDLL)GetProcAddress(JaboDLL,"CloseDLL"); OldAPI::DrawScreen = (OldAPI::ptr_DrawScreen)GetProcAddress(JaboDLL,"DrawScreen"); OldAPI::MoveScreen = (OldAPI::ptr_MoveScreen)GetProcAddress(JaboDLL,"MoveScreen"); OldAPI::UpdateScreen = (OldAPI::ptr_UpdateScreen)GetProcAddress(JaboDLL,"UpdateScreen"); OldAPI::DllConfig = (OldAPI::ptr_DllConfig)GetProcAddress(JaboDLL,"DllConfig"); OldAPI::GetDllInfo = (OldAPI::ptr_GetDllInfo)GetProcAddress(JaboDLL,"GetDllInfo"); } D3D8Dll = LoadLibrary("D3D8.dll"); if (D3D8Dll != NULL) { D3D8_SetRenderingCallback = (ptr_D3D8_SetRenderingCallback)GetProcAddress(D3D8Dll,"SetRenderingCallback"); D3D8_ReadScreen = (ptr_D3D8_ReadScreen)GetProcAddress(D3D8Dll,"ReadScreen"); D3D8_CloseDLL = (ptr_D3D8_CloseDLL)GetProcAddress(D3D8Dll,"CloseDLL"); } } BOOL readOptionsInitflags (DWORD* options_val, DWORD* initflags_val) { HKEY mainkey; if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\JaboSoft\\Project64 DLL\\Direct3D8 1.6.1",0,KEY_READ,&mainkey) != ERROR_SUCCESS) { // key doesn't exist, so we need to create it first if (RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\JaboSoft\\Project64 DLL\\Direct3D8 1.6.1",NULL,NULL,NULL,KEY_READ,NULL,&mainkey,NULL) != ERROR_SUCCESS) { // Couldn't create the key return (FALSE); } } // Key exists, try to find the Options Value DWORD type; DWORD cbData; int options_value; LSTATUS result = RegQueryValueEx(mainkey, "Options", NULL, &type, (LPBYTE)&options_value, &cbData); if (result != ERROR_SUCCESS) { options_value = 0; } *options_val = options_value; // Try to find the Direct3D init flags subkey Value int initflags_value; result = RegQueryValueEx(mainkey, "Direct3D8.InitFlags", NULL, &type, (LPBYTE)&initflags_value, &cbData); if (result != ERROR_SUCCESS) { initflags_value = 0x00e00000; } *initflags_val = initflags_value; RegCloseKey(mainkey); return(TRUE); } BOOL writeOptionsInitflags(DWORD options_val, DWORD initflags_val) { // Open the key for writing HKEY mainkey; if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\JaboSoft\\Project64 DLL\\Direct3D8 1.6.1",0,KEY_WRITE,&mainkey) != ERROR_SUCCESS) { //LOG("Failure to open key for write"); return (FALSE); } // Store our options value DWORD new_val = options_val; if (RegSetValueEx(mainkey, "Options", NULL, REG_DWORD, (BYTE *)&new_val, 4) != ERROR_SUCCESS) { //LOG("Couldn't write options value"); } // Store our init flags value new_val = initflags_val; if (RegSetValueEx(mainkey, "Direct3D8.InitFlags", NULL, REG_DWORD, (BYTE *)&new_val, 4) != ERROR_SUCCESS) { //LOG("Couldn't write init flags value"); } RegCloseKey(mainkey); return(TRUE); } /* Global functions */ static void DebugMessage(int level, const char *message, ...) { char msgbuf[1024]; va_list args; if (l_DebugCallback == NULL) return; va_start(args, message); vsprintf(msgbuf, message, args); (*l_DebugCallback)(l_DebugCallContext, level, msgbuf); va_end(args); } #pragma region (De-)Initialization /* Mupen64Plus plugin functions */ // TODO EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *, int, const char *)) { LOG("API WRAPPER:\t PluginStartup") setup_jabo_functions(); ptr_CoreGetAPIVersions CoreAPIVersionFunc; int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion; if (l_PluginInit) return M64ERR_ALREADY_INIT; /* first thing is to set the callback function for debug info */ l_DebugCallback = DebugCallback; l_DebugCallContext = Context; /* attach and call the CoreGetAPIVersions function, check Config API version for compatibility */ CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) GetProcAddress(CoreLibHandle, "CoreGetAPIVersions"); if (CoreAPIVersionFunc == NULL) { DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found."); return M64ERR_INCOMPATIBLE; } (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL); if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000)) { DebugMessage(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)", VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION)); return M64ERR_INCOMPATIBLE; } ConfigOpenSection = (ptr_ConfigOpenSection) GetProcAddress(CoreLibHandle, "ConfigOpenSection"); ConfigSetParameter = (ptr_ConfigSetParameter) GetProcAddress(CoreLibHandle, "ConfigSetParameter"); ConfigGetParameter = (ptr_ConfigGetParameter) GetProcAddress(CoreLibHandle, "ConfigGetParameter"); ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) GetProcAddress(CoreLibHandle, "ConfigSetDefaultInt"); ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) GetProcAddress(CoreLibHandle, "ConfigSetDefaultFloat"); ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) GetProcAddress(CoreLibHandle, "ConfigSetDefaultBool"); ConfigSetDefaultString = (ptr_ConfigSetDefaultString) GetProcAddress(CoreLibHandle, "ConfigSetDefaultString"); ConfigGetParamInt = (ptr_ConfigGetParamInt) GetProcAddress(CoreLibHandle, "ConfigGetParamInt"); ConfigGetParamFloat = (ptr_ConfigGetParamFloat) GetProcAddress(CoreLibHandle, "ConfigGetParamFloat"); ConfigGetParamBool = (ptr_ConfigGetParamBool) GetProcAddress(CoreLibHandle, "ConfigGetParamBool"); ConfigGetParamString = (ptr_ConfigGetParamString) GetProcAddress(CoreLibHandle, "ConfigGetParamString"); l_PluginInit = 1; return M64ERR_SUCCESS; } // TODO EXPORT m64p_error CALL PluginShutdown(void) { LOG("API WRAPPER:\t PluginShutdown") OldAPI::CloseDLL(); TerminateThread(window_thread,0); D3D8_CloseDLL(); FreeLibrary(D3D8Dll); FreeLibrary(JaboDLL); writeOptionsInitflags(old_options,old_initflags); if (!l_PluginInit) return M64ERR_NOT_INIT; /* reset some local variables */ l_DebugCallback = NULL; l_DebugCallContext = NULL; l_PluginInit = 0; return M64ERR_SUCCESS; } // TODO EXPORT int CALL RomOpen(void) { LOG("API WRAPPER:\t RomOpen") OldAPI::RomOpen(); if (!l_PluginInit) return 0; return 1; } // TODO EXPORT void CALL RomClosed( void ) { LOG("API WRAPPER:\t RomClosed") OldAPI::RomClosed(); if (!l_PluginInit) return; } #pragma endregion #pragma region Pluginversion EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities) { LOG("API WRAPPER:\t PluginGetVersion") OldAPI::PLUGIN_INFO info; OldAPI::GetDllInfo(&info); /* set version info */ if (PluginType != NULL) *PluginType = M64PLUGIN_GFX; if (PluginVersion != NULL) *PluginVersion = PLUGIN_VERSION; if (APIVersion != NULL) *APIVersion = VIDEO_PLUGIN_API_VERSION; if (PluginNamePtr != NULL) *PluginNamePtr = PLUGIN_NAME; if (Capabilities != NULL) { *Capabilities = 0; } return M64ERR_SUCCESS; } #pragma endregion // IGNORE EXPORT void CALL ChangeWindow (void) { LOG("API WRAPPER:\t ChangeWindow") } // NOTE: NEW GFX_INFO vs old EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info) { LOG("API WRAPPER:\t InitiateGFX") Config_Open(); SETTINGS settings; settings.anisotropic_level = (int)Config_ReadInt("anisotropic_level","ANISOTROPIC_FILTERING_LEVEL",0,TRUE,FALSE); settings.brightness = (int)Config_ReadInt("brightness","Brightness level",0,TRUE,FALSE); settings.antialiasing_level = (int)Config_ReadInt("antialiasing_level","Antialiasing level",0,TRUE,FALSE); settings.super2xsal = (BOOL)Config_ReadInt("super2xsal","Enables Super2xSal textures",FALSE); settings.texture_filter = (BOOL)Config_ReadInt("texture_filter","Always use texture filter",FALSE); settings.adjust_aspect_ratio = (BOOL)Config_ReadInt("adjust_aspect_ratio","Adjust game aspect ratio to match yours",FALSE); settings.legacy_pixel_pipeline = (BOOL)Config_ReadInt("legacy_pixel_pipeline","Use legacy pixel pipeline",FALSE); settings.alpha_blending = (BOOL)Config_ReadInt("alpha_blending","Force alpha blending",FALSE); settings.wireframe = (BOOL)Config_ReadInt("wireframe","Wireframe rendering",FALSE); settings.direct3d_transformation_pipeline = (BOOL)Config_ReadInt("direct3d_transformation_pipeline","Use Direct3D transformation pipeline",FALSE); settings.z_compare = (BOOL)Config_ReadInt("z_compare","Force Z Compare",FALSE); settings.copy_framebuffer = (BOOL)Config_ReadInt("copy_framebuffer","Copy framebuffer to RDRAM",FALSE); settings.resolution_width = (int)Config_ReadInt("resolution_width","Emulated Width",-1,TRUE,FALSE); settings.resolution_height = (int)Config_ReadInt("resolution_height","Emulated Height",-1,TRUE,FALSE); settings.clear_mode = (int)Config_ReadInt("clear_mode","Direct3D Clear Mode Height",0,TRUE,FALSE); DWORD new_options_val = 0; if (settings.copy_framebuffer == TRUE) { new_options_val |= 0x20000000; } if (settings.z_compare == TRUE) { new_options_val |= 0x10000000; } if (settings.legacy_pixel_pipeline == TRUE) { new_options_val |= 0x08000000; } if (settings.alpha_blending == TRUE) { new_options_val |= 0x04000000; } if (settings.adjust_aspect_ratio == TRUE) { new_options_val |= 0x02000000; } if (settings.texture_filter == TRUE) { new_options_val |= 0x01000000; } if (settings.super2xsal == TRUE) { new_options_val |= 0x00001000; } new_options_val |= (((settings.brightness - 100) / 3) & 0x1F) << 19; switch (settings.antialiasing_level) { case 1: new_options_val |= 0x00004004; break; case 2: new_options_val |= 0x00008004; break; case 3: new_options_val |= 0x00010004; break; } switch (settings.anisotropic_level) { case 1: new_options_val |= 0x00000024; break; case 2: new_options_val |= 0x00000044; break; case 3: new_options_val |= 0x00000084; break; case 4: new_options_val |= 0x00000104; break; } // Force 800x600 for now new_options_val |= 0x00000004; DWORD new_initflags_val = 0x00e00000; if (settings.direct3d_transformation_pipeline == TRUE) { new_initflags_val = 0x00a00000; } readOptionsInitflags(&old_options,&old_initflags); writeOptionsInitflags(new_options_val,new_initflags_val); OldAPI::GFX_INFO blah; blah.hWnd = hWnd_jabo; blah.hStatusBar = NULL; blah.MemoryBswaped = true; blah.HEADER = Gfx_Info.HEADER; blah.RDRAM = Gfx_Info.RDRAM; blah.DMEM = Gfx_Info.DMEM; blah.IMEM = Gfx_Info.IMEM; blah.MI_INTR_REG = (DWORD *)Gfx_Info.MI_INTR_REG; blah.DPC_START_REG = (DWORD *)Gfx_Info.DPC_START_REG; blah.DPC_END_REG = (DWORD *)Gfx_Info.DPC_END_REG; blah.DPC_CURRENT_REG = (DWORD *)Gfx_Info.DPC_CURRENT_REG; blah.DPC_STATUS_REG = (DWORD *)Gfx_Info.DPC_STATUS_REG; blah.DPC_CLOCK_REG = (DWORD *)Gfx_Info.DPC_CLOCK_REG; blah.DPC_BUFBUSY_REG = (DWORD *)Gfx_Info.DPC_BUFBUSY_REG; blah.DPC_PIPEBUSY_REG = (DWORD *)Gfx_Info.DPC_PIPEBUSY_REG; blah.DPC_TMEM_REG = (DWORD *)Gfx_Info.DPC_TMEM_REG; blah.VI_STATUS_REG = (DWORD *)Gfx_Info.VI_STATUS_REG; blah.VI_ORIGIN_REG = (DWORD *)Gfx_Info.VI_ORIGIN_REG; blah.VI_WIDTH_REG = (DWORD *)Gfx_Info.VI_WIDTH_REG; blah.VI_INTR_REG = (DWORD *)Gfx_Info.VI_INTR_REG; blah.VI_V_CURRENT_LINE_REG = (DWORD *)Gfx_Info.VI_V_CURRENT_LINE_REG; blah.VI_TIMING_REG = (DWORD *)Gfx_Info.VI_TIMING_REG; blah.VI_V_SYNC_REG = (DWORD *)Gfx_Info.VI_V_SYNC_REG; blah.VI_H_SYNC_REG = (DWORD *)Gfx_Info.VI_H_SYNC_REG; blah.VI_LEAP_REG = (DWORD *)Gfx_Info.VI_LEAP_REG; blah.VI_H_START_REG = (DWORD *)Gfx_Info.VI_H_START_REG; blah.VI_V_START_REG = (DWORD *)Gfx_Info.VI_V_START_REG; blah.VI_V_BURST_REG = (DWORD *)Gfx_Info.VI_V_BURST_REG; blah.VI_X_SCALE_REG = (DWORD *)Gfx_Info.VI_X_SCALE_REG; blah.VI_Y_SCALE_REG = (DWORD *)Gfx_Info.VI_Y_SCALE_REG; blah.CheckInterrupts = Gfx_Info.CheckInterrupts; OldAPI::InitiateGFX(blah); //OldAPI::DllConfig(hWnd_jabo); return(TRUE); } EXPORT void CALL MoveScreen (int xpos, int ypos) { LOG("API WRAPPER:\t MoveScreen") OldAPI::MoveScreen(xpos, ypos); } EXPORT void CALL ProcessDList(void) { LOG("API WRAPPER:\t ProcessDList") OldAPI::ProcessDList(); } EXPORT void CALL ProcessRDPList(void) { LOG("API WRAPPER:\t ProcessRDPList") OldAPI::ProcessRDPList(); } EXPORT void CALL ShowCFB(void) { LOG("API WRAPPER:\t ShowCFB") OldAPI::ShowCFB(); } EXPORT void CALL UpdateScreen(void) { LOG("API WRAPPER:\t UpdateScreen") OldAPI::UpdateScreen(); } EXPORT void CALL ViStatusChanged(void) { LOG("API WRAPPER:\t ViStatusChanged") OldAPI::ViStatusChanged(); } EXPORT void CALL ViWidthChanged(void) { LOG("API WRAPPER:\t ViWidthChanged") OldAPI::ViWidthChanged(); } // TODO EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int bFront) { LOG("API WRAPPER:\t ReadScreen2") if (D3D8_ReadScreen != NULL) { D3D8_ReadScreen(dest, width, height); } //*width = 800; //*height = 600; } // TODO EXPORT void CALL SetRenderingCallback(void (*callback)(int)) { LOG("API WRAPPER:\t SetRenderingCallback") if (D3D8_SetRenderingCallback != NULL) { D3D8_SetRenderingCallback(callback); } } // IMPLEMENT LATER? EXPORT void CALL FBRead(uint32 addr) { LOG("API WRAPPER:\t FBRead") } // IMPLEMENT LATER? EXPORT void CALL FBWrite(uint32 addr, uint32 size) { LOG("API WRAPPER:\t FBWrite") } // ??? EXPORT void CALL FBGetFrameBufferInfo(void *p) { LOG("API WRAPPER:\t FBGetFrameBufferInfo") //FrameBufferInfo * pinfo = (FrameBufferInfo *)p; } /* Simple Window code */ HINSTANCE inj_hModule; //Injected Modules Handle //WndProc for the new window LRESULT CALLBACK DLLWindowProc (HWND, UINT, WPARAM, LPARAM); //Register our windows Class BOOL RegisterDLLWindowClass(char szClassName[]) { WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof (WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = DLLWindowProc; wc.hInstance = inj_hModule; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) COLOR_WINDOW; wc.lpszClassName = szClassName; if (!RegisterClassEx (&wc)) return 0; return 0; } //The new thread DWORD WINAPI ThreadProc( LPVOID lpParam ) { MSG messages; char *pString = (char *)(lpParam); RegisterDLLWindowClass("InjectedDLLWindowClass"); hWnd_jabo = CreateWindowEx (0, "InjectedDLLWindowClass", pString, WS_OVERLAPPEDWINDOW, 300, 300, 400, 300, NULL, NULL,inj_hModule, NULL ); ShowWindow (hWnd_jabo, SW_SHOWNORMAL); while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return 1; } //Our new windows proc LRESULT CALLBACK DLLWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: break; case WM_DESTROY: PostQuitMessage (0); break; default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,LPVOID lpReserved) { if(ul_reason_for_call==DLL_PROCESS_ATTACH) { inj_hModule = hModule; window_thread = CreateThread(0, NULL, ThreadProc, (LPVOID)"Window Title", NULL, NULL); } return TRUE; }