#include #include "../Daodan.h" #include "BSL.h" #include "Cheater.h" #include "../Daodan_Config.h" #include "GL.h" #include "Input.h" #include "../Daodan_Patch.h" #include "Utility.h" #include "Win32.h" #include "../Oni/Oni.h" typedef int (__cdecl *CHINESEPROC)(DWORD ThreadId); // Hooked WMrSlider_SetRange() in ONiOGU_Options_InitDialog. Disables a gamma // slider in windowed mode. static void ONICALL DD_ONiOGU_GammaSlider_SetRange(void* window, int min_value, int max_value) { ConfigOption_t* co = DDrConfig_GetOptOfType("graphics.gamma", C_BOOL); WMrWindow_SetEnabled(window, M3gResolutionSwitch && co->value.intBoolVal); WMrSlider_SetRange(window, min_value, max_value); } void ONICALL DD_M3rDraw_BigBitmap(M3tTextureMap_Big* inBigBitmap, const M3tPointScreen* inDestPoint, UUtUns16 inWidth, UUtUns16 inHeight, UUtUns32 inShade, UUtUns16 inAlpha) /* 0 - M3cMaxAlpha */ { UUtUns16 x; UUtUns16 y; UUtUns16 index; UUtUns16 remaining_width; UUtUns16 remaining_height; M3tPointScreen dest_point; dest_point.z = inDestPoint->z; dest_point.invW = inDestPoint->invW; index = 0; remaining_height = inHeight; dest_point.y = (UUtInt16)((UUtUns16)inDestPoint->y); for (y = 0; y < inBigBitmap->num_y; y++) { remaining_width = inWidth; dest_point.x = (UUtInt16)((UUtUns16)inDestPoint->x); for (x = 0; x < inBigBitmap->num_x; x++) { UUtUns16 width; UUtUns16 height; width = 256 < remaining_width ? 256 : remaining_width; height = 256 < remaining_height ? 256 : remaining_height; M3rDraw_Bitmap(inBigBitmap->textures[index], &dest_point, width, height, inShade, inAlpha); dest_point.x += 256; remaining_width -= 256; index++; } dest_point.y += 256; remaining_height -= 256; } } uint8_t ONICALL DDrPersist_GetWonGame() { return 1; } void ONICALL DDrShowResumeButton(void* window, int visibility) { if (visibility) WMrWindow_SetLocation(window, 150, 350); WMrWindow_SetVisible(window, visibility); } /* Options always visible patch */ void ONICALL DDrShowOptionsButton(void* window, int visibility) { WMrWindow_SetVisible(window, 1); } void ONICALL DDrGame_Init() { if (DDrConfig_GetOptOfType("modding.daodanbsl", C_BOOL)->value.intBoolVal) SLrDaodan_Initialize(); } //this was broken FILE** _UUgError_WarningFile = (FILE**)0x005711B4; FILE* ONICALL DDrPrintWarning(int filename, int linenumber, unsigned __int16 errornum, int message) { FILE *v4; // eax@1 FILE *result; // eax@4 char v6[512]; // [sp+0h] [bp-100h]@1 FILE* UUgError_WarningFile = *_UUgError_WarningFile; if (filename && message && (strlen((const char*)filename)+strlen((const char*)message))<420) { sprintf( v6, "Error %x reported from File: %s, Line: %d (message follows) \r\n%s", errornum, (const char*)filename, linenumber, (const char*)message); if ( UUgError_WarningFile || (UUgError_WarningFile = oni_fopen("debugger.txt", "wb"), UUgError_WarningFile ) ) { oni_fprintf(UUgError_WarningFile, "%s\r\n", v6); oni_fflush(UUgError_WarningFile); } } //oni_fprintf(stdout, v6); //sprintf(&v6, "%s", message); *_UUgError_WarningFile = UUgError_WarningFile; result = UUgError_WarningFile; return result; } _COrTextArea_Resize Oni_COrTextArea_Resize = (_COrTextArea_Resize)0; int16_t ONICALL DD_COrTextArea_Resize(void* inTextArea, UUtRect* inBounds, int16_t inNumTextEntries) { if (inTextArea == COgCommandLine) { inBounds->top -= 10; } else if (inTextArea == COgConsoleLines) { inBounds->bottom -= 10; } return Oni_COrTextArea_Resize(inTextArea, inBounds, inNumTextEntries); } #define IMcShade_Red (0xFFFF0000) #define IMcShade_Green (0xFF00FF00) #define IMcShade_Blue (0xFF0000FF) void ONICALL DD_OBJiTriggerVolume_Draw(OBJtObject* inObject, uint32_t inDrawFlags) { UUtUns32 itr; OBJtOSD_All *inOSD = (OBJtOSD_All *) inObject->object_data; OBJtOSD_TriggerVolume *trigger_osd = &inOSD->osd.trigger_volume_osd; M3tPoint3D *points = trigger_osd->volume.worldPoints; UUtUns32 shade = 0xFFFFFF; if (!OBJgTriggerVolume_Visible) { return; } if (OBJrTriggerVolume_IntersectsCharacter(inObject, trigger_osd->team_mask, ONgGameState->PlayerCharacter)) { shade = IMcShade_Red; } else { shade = IMcShade_Blue; } M3rGeom_Line_Light(points + 0, points + 1, shade); M3rGeom_Line_Light(points + 1, points + 3, shade); M3rGeom_Line_Light(points + 3, points + 2, shade); M3rGeom_Line_Light(points + 2, points + 0, shade); M3rGeom_Line_Light(points + 4, points + 5, shade); M3rGeom_Line_Light(points + 5, points + 7, shade); M3rGeom_Line_Light(points + 7, points + 6, shade); M3rGeom_Line_Light(points + 6, points + 4, shade); M3rGeom_Line_Light(points + 0, points + 4, shade); M3rGeom_Line_Light(points + 1, points + 5, shade); M3rGeom_Line_Light(points + 3, points + 7, shade); M3rGeom_Line_Light(points + 2, points + 6, shade); } _ONrMechanics_Register Oni_ONrMechanics_Register = (_ONrMechanics_Register)0; int16_t ONICALL DD_ONrMechanics_Register(uint32_t inObjectType, uint32_t inObjectTypeIndex, char* inGroupName, uint32_t inSizeInMemory, OBJtMethods* inObjectMethods, uint32_t inFlags, void* inMechanicsMethods) { if (strcmp("Trigger Volume", inGroupName) == 0) { inObjectMethods->rDraw = DD_OBJiTriggerVolume_Draw; } return Oni_ONrMechanics_Register(inObjectType, inObjectTypeIndex, inGroupName, inSizeInMemory, inObjectMethods, inFlags, inMechanicsMethods); } // Enables d_regen script command. Instead of one global flag to only regenerate player each char has a flag to enable local regeneration void DD_Patch_Regeneration() { // In: WPrInventory_Update Character * Chr = 0; int NoPath = (int)&(Chr[0].RegenHax) & 0x000000FF; const unsigned char regen_patch[] = {0x90, 0x90, 0x90, 0x90, 0x90, // mov al, _WPgRegenerationCheat -> NOOP 0x90, 0x90, // test al, al -> NOOP 0x90, 0x90, // jz short loc_51BB98 -> NOOP 0x8B, 0x86, (char)NoPath, 0x01, 0x00, 0x00, // mov eax, [esi+Character.field_1E8] // -> mov eax, [esi+Character.RegenHax] 0x85, 0xC0, // test eax, eax 0x74, 0x21 // jnz 0x21 -> jz 0x21 }; DDrPatch_Const((char*)(OniExe + 0x0011BB64), regen_patch); } // Load chinese font DLL if available void DD_Patch_Chinese() { if (GetFileAttributes("xfhsm_oni.dll") != INVALID_FILE_ATTRIBUTES) { HMODULE dll; DWORD err; STARTUPMESSAGE("Loading chinese DLL", 0); dll = LoadLibrary("xfhsm_oni.dll"); err = GetLastError(); if( dll ) { void* proc = GetProcAddress( dll, "InstallHook" ); if(proc) { ((CHINESEPROC)proc)(GetCurrentThreadId()); } } else { char msg[100]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, msg, 100, NULL); STARTUPMESSAGE("Loading DLL failed with error %i: %s", err, msg); } } } int DD_Patch_DebugNameTextureInit(short width, short height, int type, int allocated, int flags, char* name, void** output) { //flags = (1 << 10); type = 1; //DDrPatch_Byte( 0x005EB83C + 3, 0xff ); DDrPatch_Int32((int*)(OniExe + 0x001EB83C), 0xFF000000 ); return M3rTextureMap_New(width, height, type, allocated, flags, name, output); } short DD_Patch_DebugNameShadeHack( Character* Char ) { return TSrContext_SetShade(*(void**)(OniExe + 0x001EB844), ONrCharacter_GetHealthShade( Char->Health, Char->MaxHealth )); } //Fix crappy ai2_shownames void DD_Patch_ShowNames() { //Set distance above head to 4.0 DDrPatch_Int32((int*)(OniExe + 0x0008C998), 0x005296C8); //texture height DDrPatch_Byte((char*)(OniExe + 0x0008C9DF), 0x3F ); //texture width DDrPatch_NOOP((char*)(OniExe + 0x0008C9CA), 6 ); /* // Crashes game. //Set the text color to whatever we like ;) DDrPatch_NOOP((char*)(OniExe + 0x0008C898), 6 ); DDrPatch_Byte((char*)(OniExe + 0x0008C898), 0x8B ); DDrPatch_Byte((char*)(OniExe + 0x0008C899), 0xCE ); DDrPatch_MakeCall((void*)(OniExe + 0x0008C8A3), DD_Patch_DebugNameShadeHack); //Make the background black for additive blending DDrPatch_MakeCall((void*)(OniExe + 0x0008C802), DD_Patch_DebugNameTextureInit ); */ } void DD_Patch_CharacterAwareness() { const unsigned char patch[] = { 0x52, // 0: push edx 0xBA, 0xA0, 0x16, 0x00, 0x00, // 1: mov edx,0x16a0 0x89, 0xF8, // 6: mov eax,edi 0xF7, 0xE2, // 8: mul edx 0x89, 0xC2, // a: mov edx,eax 0xE8, 0x00, 0x00, 0x00, 0x00, // c: call ONrGameState_LivingCharacterList_Get (-> OniExe + 0x000fca90) 0x8B, 0x00, // 11: mov eax,[eax] 0x01, 0xD0, // 13: add eax,edx 0x89, 0xC6, // 15: mov esi,eax 0x5A, // 17: pop edx 0x8B, 0x46, 0x04, // 18: (ORIG) mov eax, dword [ds:esi+0x4] 0xF6, 0xC4, 0x80 // 1b: (ORIG) test ah, 0x80 }; void* newCode = DDrPatch_ExecutableASM((char*)(OniExe + 0x0009A609), (char*)(OniExe + 0x0009A60F), patch, sizeof(patch)); if ((int)newCode > 0) { DDrPatch_MakeCall((char*)(newCode+0xC), (char*)(OniExe + 0x000FCA90)); DDrPatch_NOOP((char*)(OniExe + 0x0009A60E), 1); } } bool DD_Patch_Init() { STARTUPMESSAGE("Patching engine", 0); // Disable UUrPlatform_Initalize/Terminate, this enables the Alt-Tab and the // Windows key but has the possible side effect of allowing the screensaver // to enable itself in-game. if (DDrConfig_GetOptOfType("windows.alttab", C_BOOL)->value.intBoolVal) { // 0xC3 = ret, so makes those functions just have a "ret" instruction at their start DDrPatch_Byte((char*)UUrPlatform_Initialize, 0xC3); DDrPatch_Byte((char*)UUrPlatform_Terminate, 0xC3); } // Textures using ARGB8888 can be used if (DDrConfig_GetOptOfType("modding.argb8888", C_BOOL)->value.intBoolVal) { // Update conversion lookups in IMgConvertPixelType_List DDrPatch_Byte((char*)(OniExe + 0x00135af0), 0x07); DDrPatch_Byte((char*)(OniExe + 0x00135af4), 0x0B); } // Fix BinkBufferInit() call in BKrMovie_Play() to use GDI (DIB) blitting // instead of DirectDraw; patch ONiRunGame to use the same method to play // outro (ie., BKrMovie_Play() instead of ONrMovie_Play_Hardware() as the // latter has problems on WINE). if (DDrConfig_GetOptOfType("graphics.binkplay", C_BOOL)->value.intBoolVal) { // push BINKBUFFERAUTO -> push BINKBUFFERDIBSECTION. DDrPatch_Byte((void*)(OniExe + 0x0008829b + 1), 0x02); // call ONrMovie_Play_Hardware -> call ONrMovie_Play DDrPatch_MakeCall((void*)(OniExe + 0x000d496f), ONrMovie_Play); } if (DDrConfig_GetOptOfType("modding.d_regen", C_BOOL)->value.intBoolVal) DD_Patch_Regeneration(); if (DDrConfig_GetOptOfType("gameplay.characterawareness", C_BOOL)->value.intBoolVal) DD_Patch_CharacterAwareness(); // Cheats always enabled if (DDrConfig_GetOptOfType("gameplay.cheatsenabled", C_BOOL)->value.intBoolVal) { DDrPatch_MakeJump((void*)ONrPersist_GetWonGame, (void*)DDrPersist_GetWonGame); } // Use Daodan's own cheattable if (DDrConfig_GetOptOfType("gameplay.cheattable", C_BOOL)->value.intBoolVal) { // In ONrGameState_HandleCheats: Replace pointers to orig cheattable DDrPatch_Int32 ((int*)(OniExe + 0x000f616b), (int)&DDr_CheatTable[0].name); DDrPatch_Int32 ((int*)(OniExe + 0x000f617a), (int)&DDr_CheatTable[0].message_on); // ONrGameState_HandleCheats: Replace call to ONrCheater DDrPatch_MakeCall((void*)(OniExe + 0x000f618f), (void*)DDrCheater); // In: ONrGameState_DoCharacterFrame // -> NOP; PUSH ebp; CALL FallingFrames // Replace fall height frame counter (actually in-air frame counter) increase by a // conditional one (only counted when inc_fallingframes) DDrPatch_Int16((short*)(OniExe + 0x000deb45), 0x5590); DDrPatch_MakeCall((void*)(OniExe + 0x000deb47), (void*)FallingFrames); // At end of ONrUnlockLevel to init values on level loading DDrPatch_MakeJump((void*)(OniExe + 0x0010f021), (void*)DDrCheater_LevelLoad); if (DDrConfig_GetOptOfType("gameplay.bindablecheats", C_BOOL)->value.intBoolVal) { InitBindableCheats(); } } if (DDrConfig_GetOptOfType("language.chinese", C_BOOL)->value.intBoolVal) DD_Patch_Chinese(); // Disables weapon cooldown exploit if (DDrConfig_GetOptOfType("gameplay.cooldowntimer", C_BOOL)->value.intBoolVal) { // In WPrRelease: NoOp 4 MOVs DDrPatch_NOOP((char*)(OniExe + 0x0011a825), 22); } // Daodan device mode enumeration function if (DDrConfig_GetOptOfType("graphics.displayenum", C_BOOL)->value.intBoolVal) { DDrPatch_MakeJump((void*)gl_enumerate_valid_display_modes, (void*)DD_GLrEnumerateDisplayModes); } if (DDrConfig_GetOptOfType("windows.daodaninput", C_BOOL)->value.intBoolVal) { DDrInput_PatchDaodanInput(); } else { // The following patches aren't compatible with, or are superseded by // Daodan input // Limit cursor to Oni's window if (DDrConfig_GetOptOfType("windows.clipcursor", C_BOOL)->value.intBoolVal) { // LIrMode_Set: replace LIrPlatform_Mode_Set call with our hook. DDrPatch_MakeCall((void*)(OniExe + 0x00003f9f), (void*) DD_LIrPlatform_Mode_Set); // LIrMode_Set_Internal: replace LIrPlatform_Mode_Set call with our hook. DDrPatch_MakeCall((void*)(OniExe + 0x00003fff), (void*) DD_LIrPlatform_Mode_Set); // LIrTerminate: replace LIrPlatform_Terminate call with our hook. DDrPatch_MakeCall((void*)(OniExe + 0x000004cb8), (void*) DD_LIrPlatform_Terminate); } // Forced DirectInput (for Windows NT) if (DDrConfig_GetOptOfType("windows.directinput", C_BOOL)->value.intBoolVal) { // LIrPlatform_Initialize: replace conditional jump by unconditional DDrPatch_Byte((char*)(OniExe + 0x00002e6d), 0xeb); } } // Disable Oni's command line parser so it doesn't interfere with ours if (DDrConfig_GetOptOfType("windows.disablecmdline", C_BOOL)->value.intBoolVal) { // Replace start of OniParseCommandLine with XOR eax,eax; RET DDrPatch_Int32 ((int*)(OniExe + 0x000d3570), 0x00c3c033); // NoOp first 51 byte in ONiMain, including tests and conditional exec of CLrGetCommandLine DDrPatch_NOOP((char*)(OniExe + 0x000d3280), 51); } // Font texture cache doubled if (DDrConfig_GetOptOfType("language.fonttexturecache", C_BOOL)->value.intBoolVal) { // Double two values in TMrGame_Initialize DDrPatch_Byte((char*)(OniExe + 0x00020ea7), 0x20); DDrPatch_Byte((char*)(OniExe + 0x00020f4a), 0x40); } // Allow HD screens on resolutions < 1024*768 if (DDrConfig_GetOptOfType("modding.hdscreens_lowres", C_BOOL)->value.intBoolVal) { DDrPatch_MakeJump((void*)M3rDraw_BigBitmap, (void*)DD_M3rDraw_BigBitmap); } // Allow for console to show on higher resolutions if (DDrConfig_GetOptOfType("devmode.highres_console", C_BOOL)->value.intBoolVal) { Oni_COrTextArea_Resize = DDrPatch_MakeDetour((void*)COrTextArea_Resize, (void*)DD_COrTextArea_Resize); } // Allow custom actions to be bound through Daodan if (DDrConfig_GetOptOfType("gameplay.customactions", C_BOOL)->value.intBoolVal) DDrInput_PatchCustomActions(); // Hackish fix for Konoko not kicking guns // Don't use this, it breaks stairs. if (DDrConfig_GetOptOfType("gameplay.kickguns", C_BOOL)->value.intBoolVal) { // In ONrCharacter_EnablePhysics: Load different values to same addresses as before const unsigned char kickgun_patch[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0xC7, 0x05, 0x1C, 0xC9, 0x5E, 0x00, 0x70, 0xB8, 0x43, 0x00, 0xC7, 0x05, 0x20, 0xC9, 0x5E, 0x00, 0x20, 0xBE, 0x43 }; DDrPatch_Const ((char*)(OniExe + 0x000dc420), kickgun_patch); } // Disable loading the vtuneapi.dll if (DDrConfig_GetOptOfType("windows.killvtune", C_BOOL)->value.intBoolVal) { // Instantly return from UUrLoadVtuneAPI DDrPatch_Byte((char*)(OniExe + 0x00026340), 0xC3); } // Now supports textures up to 512x512 if (DDrConfig_GetOptOfType("modding.largetextures", C_BOOL)->value.intBoolVal) { DDrPatch_Byte((char*)(OniExe + 0x00005251), 0x10); } // Non-"_Final" levels are now valid if (DDrConfig_GetOptOfType("modding.levelplugins", C_BOOL)->value.intBoolVal) { // Patch in TMrUtility_LevelInfo_Get: DDrPatch_Byte((char*)(OniExe + 0x000206a8), 0x01); } // Weapon on ground shown with name and magazine contents if (DDrConfig_GetOptOfType("graphics.newweap", C_BOOL)->value.intBoolVal) { //Makes it always say "Received weapon_name." //Needs check for loc_4DFC66 //DDrPatch_NOOP((char*)(OniExe + 0x000E4DF8),2); //Adds Weapon name and ammo meter to pickup autoprompt (patches to ONrGameState_ProcessHeartbeat) // Do not call WPrHasAmmo and ignore conditional jump: DDrPatch_NOOP((char*)(OniExe + 0x000FAC73), 9); // Do not load ecx with some magic value? DDrPatch_NOOP((char*)(OniExe + 0x000FAC80), 5); // Replace call to ONiGameState_FindAutoPromptMessage DDrPatch_MakeCall((void*)(OniExe + 0xFAC85), (void*)DDrWeapon2Message); //Moves location of colors //DDrPatch_Int32((int*)(OniExe + 0x0002E3D5), (int)&DDrDSayColors ); //DDrPatch_Int32((int*)(OniExe + 0x0002E3DA), (int)&DDrDSayColors ); } // Disable Multi-byte character awareness patch (multiple language support) if (DDrConfig_GetOptOfType("language.nomultibyte", C_BOOL)->value.intBoolVal) { // TSiContext_DrawLine: Replace conditional jumps by unconditional ones DDrPatch_Byte ((char*)(OniExe + 0x0002d8f8), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002d9ad), 0xeb); // TSiContext_DrawTextLine: same DDrPatch_Byte ((char*)(OniExe + 0x0002dbe2), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002dec3), 0xeb); // TSrContext_FormatString: same DDrPatch_Byte ((char*)(OniExe + 0x0002e2ab), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e2c4), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e379), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e48c), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e4d0), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e4f4), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e646), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e695), 0xeb); // TSrContext_GetStringRect: same DDrPatch_Byte ((char*)(OniExe + 0x0002e944), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e95d), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e98e), 0xeb); DDrPatch_Byte ((char*)(OniExe + 0x0002e9dc), 0xeb); } // Fix options not visible in main menu when a game was started if (DDrConfig_GetOptOfType("graphics.optionsvisible", C_BOOL)->value.intBoolVal) { // replace WMrWindow_SetVisible calls DDrPatch_MakeCall((void*)(OniExe + 0x000d2d2d), DDrShowOptionsButton); DDrPatch_MakeCall((void*)(OniExe + 0x000d2d43), DDrShowResumeButton); } // Pathfinding grid cache size x8 if (DDrConfig_GetOptOfType("gameplay.pathfinding", C_BOOL)->value.intBoolVal) { // Replaces conditional jump (je) with unconditional jump const unsigned char pathfinding[2] = {0x90 , 0xE9 }; DDrPatch_Byte ((char*)(OniExe + 0x0010b03b), 0x20); DDrPatch_Byte ((char*)(OniExe + 0x0010b04c), 0x20); //other stuff DDrPatch_Const((char*)(OniExe + 0x00040789), pathfinding); } // Projectile awareness fixed if (DDrConfig_GetOptOfType("gameplay.projaware", C_BOOL)->value.intBoolVal) { DDrPatch_Byte ((char*)(OniExe + 0x0009c07c), 0x6c); DDrPatch_Byte ((char*)(OniExe + 0x0009c080), 0x70); DDrPatch_Byte ((char*)(OniExe + 0x0009c084), 0x74); DDrPatch_Byte ((char*)(OniExe + 0x0009c110), 0x6c); } // Safe startup message printer if (DDrConfig_GetOptOfType("windows.safeprintf", C_BOOL)->value.intBoolVal) { DDrPatch_MakeJump((void*)UUrStartupMessage, (void*)DDrStartupMessage); } // Show all (also enemies') lasersights if (DDrConfig_GetOptOfType("graphics.showalllasersights", C_BOOL)->value.intBoolVal) { DDrPatch_NOOP((char*)(OniExe + 0x000E1957), 6 ); } // Allow bsl-var show_triggervolumes or ctrl+shift+x (devmode) to work if (DDrConfig_GetOptOfType("devmode.showtriggervolumes", C_BOOL)->value.intBoolVal) { DDrInput_PatchUtilityInput(); Oni_ONrMechanics_Register = DDrPatch_MakeDetour((void*)ONrMechanics_Register, (void*)DD_ONrMechanics_Register); } // Experiment with allowing enemies to be thrown over railings if (DDrConfig_GetOptOfType("gameplay.throwtest", C_BOOL)->value.intBoolVal) { DDrPatch_NOOP((char*)(OniExe + 0x000dc190), 10); } // DaodanGL with windowed mode support if (DDrConfig_GetOptOfType("graphics.daodangl", C_BOOL)->value.intBoolVal) { // LIrPlatform_Mode_Set: GetWindowRect -> GetClientRect. DDrPatch_NOOP((char*) OniExe + 0x00002dd6, 6); DDrPatch_MakeCall((char*) OniExe + 0x00002dd6, (void*) GetClientRect); // UUrWindow_GetSize: GetWindowRect -> GetClientRect. DDrPatch_NOOP((char*) OniExe + 0x0002651c, 6); DDrPatch_MakeCall((char*) OniExe + 0x0002651c, (void*) GetClientRect); // Note: Daodan input makes the following GetCursorPos and SetCursorPos // patches unnecessary // LIrPlatform_PollInputForAction: fix GetCursorPos call to return client coordinates. DDrPatch_NOOP((char*) OniExe + 0x000032cc, 6); DDrPatch_MakeCall((char*) OniExe + 0x000032cc, (void*) DD_GetCursorPos); // LIrPlatform_InputEvent_GetMouse: fix GetCursorPos call to return client coordinates. DDrPatch_NOOP((char*) OniExe + 0x00002cc2, 6); DDrPatch_MakeCall((char*) OniExe + 0x00002cc2, (void*) DD_GetCursorPos); // LIrPlatform_PollInputForAction: translate SetCursorPos position to screen coordinates. DDrPatch_NOOP((char*) OniExe + 0x000032b7, 6); DDrPatch_MakeCall((char*) OniExe + 0x000032b7, (void*) DD_SetCursorPos); // LIrPlatform_PollInputForAction: translate SetCursorPos position to screen coordinates. DDrPatch_NOOP((char*) OniExe + 0x00003349, 6); DDrPatch_MakeCall((char*) OniExe + 0x00003349, (void*) DD_SetCursorPos); // Replace ONrPlatformInitialize. DDrPatch_MakeJump((void*) ONrPlatform_Initialize, (void*) DD_ONrPlatform_Initialize); // Replace gl_platform_initialize. DDrPatch_MakeJump((void*) gl_platform_initialize, (void*) DD_GLrPlatform_Initialize); // Replace gl_platform_dispose. DDrPatch_MakeJump((void *) gl_platform_dispose, (void*) DD_GLrPlatform_Dispose); } // Performance patch if (DDrConfig_GetOptOfType("windows.usegettickcount", C_BOOL)->value.intBoolVal) { DDrPatch_MakeJump((void*)UUrMachineTime_High, (void*)DDrMachineTime_High); DDrPatch_MakeJump((void*)UUrMachineTime_High_Frequency, (void*)DDrMachineTime_High_Frequency); DDrPatch_MakeJump((void*)UUrMachineTime_Sixtieths, (void*)DDrMachineTime_Sixtieths); } // Fix displaying the talking portraits in widescreen modes if (DDrConfig_GetOptOfType("graphics.widescreenportraits", C_BOOL)->value.intBoolVal) { SLrDaodan_Patch(); } // Adds working function for existing BSL command wp_fadetime, sets fade time to 4800 if (DDrConfig_GetOptOfType("gameplay.wpfadetime", C_BOOL)->value.intBoolVal) { // Makes wp_fadetime actually have a function (changes within WPrRelease) // Patches end of function to instead of use a constant value for fadetime (12c0 = 4800) actually use value of wp_fadetime: // orig: MOV [esi+0x46], 0x12c0 ; POP ebx ; POP esi ; ADD esp, 0x14 ; RET // new: MOV bx, [0x627dc4] ; MOV [esi+0x46], bx ; POP ebx ; POP esi ; ADD esp, 0x14 ; RET const unsigned char fadetime_patch[] = { 0x66, 0x8B, 0x1D, 0xC4, 0x7D, 0x62, 0x00, 0x66, 0x89, 0x5E, 0x46, 0x5B, 0x5E, 0x83, 0xC4, 0x14, 0xC3 }; DDrPatch_Const ((char*)(OniExe + 0x0011a889), fadetime_patch); // Fixes jump because of new length of code in patch DDrPatch_Byte ((char*)(OniExe + 0x0011a560), 0x31); // Sets the fadetime to 4800 by default (in WPrInitialize) DDrPatch_Int16 ((short*)(OniExe + 0x0011ab0e), 4800); } // Adds new BSL functions // Replaces an early unused call (OBJrLevel_Unload_Unknown_2) in ONiMain DDrPatch_MakeCall((void*)(OniExe + 0x000d345a), (void*)DDrGame_Init); // Disable gamma slider in options in windowed mode // In ONiOGU_Options_Callback: Replace WMrSlider_SetRange DDrPatch_MakeCall((void*)(OniExe + 0x000d262c), (void*)DD_ONiOGU_GammaSlider_SetRange); // Fix the warning print method // Replace UUrError_Report_Internal DDrPatch_MakeJump((void*)(OniExe + 0x000245A0), (void*)DDrPrintWarning); DD_Patch_ShowNames(); return true; }