source: Daodan/src/Daodan.c@ 837

Last change on this file since 837 was 837, checked in by alloc, 12 years ago

Daodan:

  • Fixes #21
  • Fixes #31
  • Prepends "Daodan: " to every daodan related output on startup.txt
File size: 29.4 KB
RevLine 
[692]1#include <windows.h>
[346]2#include <string.h>
3
[272]4#include "Daodan.h"
5#include "Daodan_Patch.h"
6#include "Daodan_Utility.h"
[323]7#include "Daodan_Win32.h"
[339]8#include "Daodan_Cheater.h"
9#include "Daodan_Persistence.h"
[439]10#include "Daodan_BSL.h"
[476]11#include "Daodan_Console.h"
[349]12
[273]13#include "Oni.h"
[339]14
[692]15#include "Oni_GL.h"
16#include "Daodan_GL.h"
[272]17
[692]18#include "Inifile_Reader.h"
[297]19
[272]20HMODULE DDrDLLModule;
21HMODULE DDrONiModule;
22
[347]23bool patch_fonttexturecache = true;
24bool patch_largetextures = true;
[349]25bool patch_levelplugins = true;
[347]26bool patch_pathfinding = true;
27bool patch_projaware = true;
[348]28bool patch_directinput = true;
[347]29bool patch_wpfadetime = true;
30bool patch_kickguns = false;
31bool patch_cooldowntimer = true;
32bool patch_throwtest = false;
33bool patch_alttab = true;
34bool patch_particledisablebit = false;
[422]35bool patch_multibyte = false;
[347]36bool patch_cheattable = true;
[426]37bool patch_argb8888 = true;
[459]38bool patch_killvtune = true;
[466]39bool patch_getcmdline = true;
40bool patch_disablecmdline = true;
[693]41bool patch_optionsvisible = true;
[347]42
[705]43bool patch_binkplay = true;
[347]44bool patch_safeprintf = true;
45bool patch_daodandisplayenum = true;
46bool patch_usegettickcount = true;
[348]47bool patch_cheatsenabled = true;
[705]48bool patch_usedaodangl = true;
49bool patch_clipcursor = true;
[439]50bool patch_daodaninit = true;
[447]51bool patch_bsl = true;
[452]52bool patch_cheater = true;
[677]53bool patch_newweapon = true;
[439]54bool opt_usedaodanbsl = true;
[468]55bool opt_border = true;
56bool opt_topmost = false;
[705]57bool opt_gamma = true;
[439]58
[705]59typedef int (__cdecl *CHINESEPROC)(DWORD ThreadId);
60bool patch_chinese = true;
[693]61
62
[705]63// Hooked WMrSlider_SetRange() in ONiOGU_Options_InitDialog. Disables a gamma
64// slider in windowed mode.
65static void ONICALL DD_ONiOGU_GammaSlider_SetRange(WMtWindow* window, int min_value, int max_value)
[693]66{
[705]67 WMrWindow_SetEnabled(window, M3gResolutionSwitch && opt_gamma);
68 WMrSlider_SetRange(window, min_value, max_value);
69}
70
71void ONICALL DDrShowResumeButton(WMtWindow* window, int visibility)
72{
[693]73 if (visibility)
74 WMrWindow_SetLocation(window, 150, 350);
75 WMrWindow_SetVisible(window, visibility);
76}
77
78
79/* Options always visible patch */
[705]80void ONICALL DDrShowOptionsButton(WMtWindow* window, int visibility)
[693]81{
82 WMrWindow_SetVisible(window, 1);
83}
84
85
86
[272]87bool DDrPatch_Init()
88{
[837]89 DDrStartupMessage("Daodan: Patching engine");
[342]90
[272]91 // Font texture cache doubled
[347]92 if (patch_fonttexturecache)
93 {
[689]94 DDrPatch_Byte((char*)(OniExe + 0x00020ea7), 0x20);
95 DDrPatch_Byte((char*)(OniExe + 0x00020f4a), 0x40);
[347]96 }
[272]97
98 // Now supports textures up to 512x512
[347]99 if (patch_largetextures)
[689]100 DDrPatch_Byte ((char*)(OniExe + 0x00005251), 0x10);
[272]101
102 // Non-"_Final" levels are now valid
[348]103 if (patch_levelplugins)
[689]104 DDrPatch_Byte ((char*)(OniExe + 0x000206a8), 0x01);
[272]105
106 // Pathfinding grid cache size x8
[347]107 if (patch_pathfinding)
108 {
[689]109 const unsigned char pathfinding[2] = {0x90 , 0xE9 };
110 DDrPatch_Byte ((char*)(OniExe + 0x0010b03b), 0x20);
111 DDrPatch_Byte ((char*)(OniExe + 0x0010b04c), 0x20);
[677]112
113 //other stuff
[689]114 DDrPatch_Const((char*)(OniExe + 0x00040789), pathfinding);
[347]115 }
[272]116
117 // Projectile awareness fixed
[347]118 if (patch_projaware)
119 {
[689]120 DDrPatch_Byte ((char*)(OniExe + 0x0009c07c), 0x6c);
121 DDrPatch_Byte ((char*)(OniExe + 0x0009c080), 0x70);
122 DDrPatch_Byte ((char*)(OniExe + 0x0009c084), 0x74);
123 DDrPatch_Byte ((char*)(OniExe + 0x0009c110), 0x6c);
[347]124 }
[272]125
126 // Forced DirectInput (for Windows NT)
[348]127 if (patch_directinput)
[689]128 DDrPatch_Byte((char*)(OniExe + 0x00002e6d), 0xeb);
[677]129
[347]130 if (patch_wpfadetime)
131 {
132 // Makes wp_fadetime actually have a function
[689]133 const unsigned char fadetime_patch[] = { 0x66, 0x8B, 0x1D, 0xC4, 0x7D, 0x62, 0x00, 0x66, 0x89, 0x5E, 0x46, 0x5B, 0x5E, 0x83, 0xC4, 0x14, 0xC3 };
134 DDrPatch_Const ((char*)(OniExe + 0x0011a889), fadetime_patch);
135 DDrPatch_Byte ((char*)(OniExe + 0x0011a560), 0x31);
[347]136
137 // Sets the fadetime to 4800 by default
[689]138 DDrPatch_Int16 ((short*)(OniExe + 0x0011ab0e), 0x12c0);
[347]139 }
[272]140
[677]141 // FIXME: add switches
142 //pathfinding fix
143
[272]144
[677]145
146
[272]147 // Hackish fix for Konoko not kicking guns
[677]148 // Don't use this, it breaks stairs.
[347]149 if (patch_kickguns)
150 {
[689]151 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 };
152 DDrPatch_Const ((char*)(OniExe + 0x000dc420), kickgun_patch);
[347]153 }
[272]154
155 // Cooldown timer exploit fix ^_^
[347]156 if (patch_cooldowntimer)
157 {
[689]158 const unsigned char cooldown_patch[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
159 DDrPatch_Const ((char*)(OniExe + 0x0011a825), cooldown_patch);
[347]160 }
[272]161
[347]162 if (patch_throwtest)
163 {
[689]164 const unsigned char throwtest_patch[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
165 DDrPatch_Const((char*)(OniExe + 0x000dc190), throwtest_patch);
[347]166 }
[272]167
[322]168 // 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.
[347]169 if (patch_alttab)
170 {
[690]171 // 0xC3 = ret, so makes those functions just have a "ret" instruction at their start
[689]172 DDrPatch_Byte ((char*)UUrPlatform_Initialize, 0xC3);
173 DDrPatch_Byte ((char*)UUrPlatform_Terminate, 0xC3);
[347]174 }
[322]175
176 // Unlocks particle action disabling/enabling bits for all events. (Will be controlled by a command line switch when I figure out how to do that without Win32 hacks.)
[347]177 if (patch_particledisablebit)
[689]178 DDrPatch_Int16 ((short*)(OniExe + 0x001b184), 0x9090);
[322]179
[329]180 // Multi-byte patch (multiple language support)
[422]181 if (!patch_multibyte)
[347]182 {
[689]183 DDrPatch_Byte ((char*)(OniExe + 0x0002d8f8), 0xeb);
184 DDrPatch_Byte ((char*)(OniExe + 0x0002d9ad), 0xeb);
185 DDrPatch_Byte ((char*)(OniExe + 0x0002dbe2), 0xeb);
186 DDrPatch_Byte ((char*)(OniExe + 0x0002dec3), 0xeb);
187 DDrPatch_Byte ((char*)(OniExe + 0x0002e2ab), 0xeb);
188 DDrPatch_Byte ((char*)(OniExe + 0x0002e2c4), 0xeb);
189 DDrPatch_Byte ((char*)(OniExe + 0x0002e379), 0xeb);
190 DDrPatch_Byte ((char*)(OniExe + 0x0002e48c), 0xeb);
191 DDrPatch_Byte ((char*)(OniExe + 0x0002e4d0), 0xeb);
192 DDrPatch_Byte ((char*)(OniExe + 0x0002e4f4), 0xeb);
193 DDrPatch_Byte ((char*)(OniExe + 0x0002e646), 0xeb);
194 DDrPatch_Byte ((char*)(OniExe + 0x0002e695), 0xeb);
195 DDrPatch_Byte ((char*)(OniExe + 0x0002e944), 0xeb);
196 DDrPatch_Byte ((char*)(OniExe + 0x0002e95d), 0xeb);
197 DDrPatch_Byte ((char*)(OniExe + 0x0002e98e), 0xeb);
198 DDrPatch_Byte ((char*)(OniExe + 0x0002e9dc), 0xeb);
[347]199 }
[329]200
[339]201 // Cheat table patch
[347]202 if (patch_cheattable)
203 {
[689]204 DDrPatch_Int32 ((int*)(OniExe + 0x000f616b), (int)&DDr_CheatTable[0].name);
205 DDrPatch_Int32 ((int*)(OniExe + 0x000f617a), (int)&DDr_CheatTable[0].message_on);
[347]206 }
[339]207
[459]208 // ARGB8888 textures
[426]209 if (patch_argb8888)
210 {
[689]211 DDrPatch_Byte ((char*)(OniExe + 0x00135af0), 0x07);
212 DDrPatch_Byte ((char*)(OniExe + 0x00135af4), 0x0B);
[426]213 }
[473]214
215 //Test newweap patch
[677]216 if (patch_newweapon) {
[476]217
[739]218 //Makes it always say "Received weapon_name."
[476]219 //Needs check for loc_4DFC66
[689]220 //DDrPatch_NOOP((char*)(OniExe + 0x000E4DF8),2);
[476]221
222 //Adds Weapon name and ammo meter to pickup autoprompt
[689]223 DDrPatch_NOOP((char*)(OniExe + 0x000FAC73), 9);
224 DDrPatch_NOOP((char*)(OniExe + 0x000FAC80), 5);
225 DDrPatch_MakeCall((void*)(OniExe + 0xFAC85), (void*)DDrWeapon2Message);
[476]226
227 //Moves location of colors
[689]228 //DDrPatch_Int32((int*)(OniExe + 0x0002E3D5), (int)&DDrDSayColors );
229 //DDrPatch_Int32((int*)(OniExe + 0x0002E3DA), (int)&DDrDSayColors );
[677]230 }
[426]231
[459]232 // Disable loading the vtuneapi.dll
[677]233 //if (patch_killvtune)
[689]234 //DDrPatch_Byte ((char*)(OniExe + 0x00026340), 0xC3);
[459]235
[466]236 // Disable Oni's internal CLrGetCommandLine function (to eventually replace it with our own)
237 if (patch_getcmdline)
[689]238 DDrPatch_NOOP ((char*)(OniExe + 0x000d3280), 51);
[466]239
240 // Disable Oni's command line parser so it doesn't interfere with ours
241 if (patch_disablecmdline)
[689]242 DDrPatch_Int32 ((int*)(OniExe + 0x000d3570), 0xc3c03366);
[466]243
[677]244 if (patch_bsl)
245 {
246 //Calculating the value of the needed offset is much more reliable when the compiler does it for you.
247
248 //TODO: fix moonshadow.
249 Character * Chr = 0;
250 int NoPath = (int)&(Chr[0].RegenHax) & 0x000000FF;
[689]251 const unsigned char regen_patch[] =
[677]252 {0x90, 0x90, 0x90, 0x90, 0x90, // mov al, _WPgRegenerationCheat -> NOOP
253 0x90, 0x90, // test al, al -> NOOP
254 0x90, 0x90, // jz short loc_51BB98 -> NOOP
255 0x8B, 0x86, (char)NoPath, 0x01, 0x00, 0x00, // mov eax, [esi+Character.field_1E8]
256 // -> mov eax, [esi+Character.RegenHax]
257 0x85, 0xC0, // test eax, eax
258 0x74, 0x21 // jnz 0x21 -> jz 0x21
259 };
[689]260 DDrPatch_Const((char*)(OniExe + 0x0011BB64), regen_patch);
[677]261 }
262
263 if(patch_chinese)
264 {
[837]265 if (GetFileAttributes("xfhsm_oni.dll") != INVALID_FILE_ATTRIBUTES)
266 {
267 HMODULE dll;
268 DWORD err;
[705]269
[837]270 DDrStartupMessage("Daodan: Loading chinese DLL");
271 dll = LoadLibrary("xfhsm_oni.dll");
272 err = GetLastError();
273 if( dll )
[677]274 {
[837]275 void* proc = GetProcAddress( dll, "InstallHook" );
276 if(proc)
277 {
278 ((CHINESEPROC)proc)(GetCurrentThreadId());
279 }
280 } else {
281 char msg[100];
282 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, msg, 100, NULL);
283 DDrStartupMessage("Daodan: Loading DLL failed with error %i: %s", err, msg);
[677]284 }
285 }
286 }
287
288 //Fix crappy ai2_shownames
289 if(1)
290 {
291 //Set distance above head to 4.0
[689]292 DDrPatch_Int32((int*)(OniExe + 0x0008C998), 0x005296C8);
[677]293 //texture height
[689]294 DDrPatch_Byte((char*)(OniExe + 0x0008C9DF), 0x3F );
[677]295 //texture width
[689]296 DDrPatch_NOOP((char*)(OniExe + 0x0008C9CA), 6 );
[677]297 //Set the text color to whatever we like ;)
[689]298 DDrPatch_NOOP((char*)(OniExe + 0x0008C898), 6 );
299 DDrPatch_Byte((char*)(OniExe + 0x0008C898), 0x8B );
300 DDrPatch_Byte((char*)(OniExe + 0x0008C899), 0xCE );
301//FLATLINE? DDrPatch_MakeCall((void*)(OniExe + 0x0008C8A3), FLrHook_DebugNameShadeHack);
[677]302
303 //Make the background black for additive blending
[689]304//FLATLINE? DDrPatch_MakeCall((void*)(OniExe + 0x0008C802), FLrHook_DebugNameTextureInit );
[677]305 }
306
307 if(1)
308 {
[689]309 //DDrPatch_NOOP((char*)(OniExe + 0x000E1957), 6 );
310 //DDrPatch_MakeCall((void*)(OniExe + 0x000E17F6), FLrHook_Lasers );
[677]311 }
312
313 //Flatline related stuff
[689]314// DDrPatch_MakeCall((void*)(OniExe + 0x000FBCEA), DDrText_Hook);
[677]315
[689]316//FLATLINE? DDrPatch_Int32((int*)(OniExe + 0x000B24D2), FLrSpawnHack);
[677]317
[689]318//FLATLINE? DDrPatch_NOOP((char*)(OniExe + 0x000C26CB), 6);
[677]319
[689]320//FLATLINE? DDrPatch_MakeCall((void*)(OniExe + 0x000C26CB), FLrHook_DoorOpen);
321//FLATLINE? DDrPatch_MakeCall((void*)(OniExe + 0x000EE3CF), FLrHook_ConsoleActivate);
[693]322
323
324 // Fix options not visible in main menu when a game was started
325 if(patch_optionsvisible)
326 {
327 DDrPatch_MakeCall((void*)(OniExe + 0x000d2d2d), DDrShowOptionsButton);
328 DDrPatch_MakeCall((void*)(OniExe + 0x000d2d43), DDrShowResumeButton);
329 }
330
[705]331 // Fix BinkBufferInit() call in BKrMovie_Play() to use GDI (DIB) blitting
332 // instead of DirectDraw; patch ONiRunGame to use the same method to play
333 // outro (ie., BKrMovie_Play() instead of ONrMovie_Play_Hardware() as the
334 // latter has problems on WINE).
335 if (patch_binkplay)
336 {
337 // push BINKBUFFERAUTO -> push BINKBUFFERDIBSECTION.
338 DDrPatch_Byte((void*)(OniExe + 0x0008829b + 1), 0x02);
339 // call ONrMovie_Play_Hardware -> call ONrMovie_Play
340 DDrPatch_MakeCall((void*)(OniExe + 0x000d496f), ONrMovie_Play);
341 }
342
343 // Patch a gamma slider in Options dialog (unconditionally).
344 // ONiOGU_Options_InitDialog: replace WMrSlider_SetRange(gammaSliderWindow, ...)
345 // call with our hook function.
346 DDrPatch_MakeCall((void*)(OniExe + 0x000d262c), (void*)DD_ONiOGU_GammaSlider_SetRange);
347
[272]348 return true;
349}
350
[693]351
[445]352enum {s_unknown, s_options, s_patch, s_bsl, s_language} ini_section;
[346]353
354bool DDrIniCallback(char* section, bool newsection, char* name, char* value)
355{
356 if (newsection)
357 {
[677]358 if (!_stricmp(section, "options"))
[439]359 ini_section = s_options;
[677]360 else if (!_stricmp(section, "patch"))
[347]361 ini_section = s_patch;
[677]362 else if (!_stricmp(section, "bsl"))
[445]363 ini_section = s_bsl;
[677]364 else if (!_stricmp(section, "language"))
[346]365 ini_section = s_language;
366 else
367 {
368 ini_section = s_unknown;
[837]369 DDrStartupMessage("Daodan: Unrecognised ini section \"%s\"", section);
[346]370 }
371 }
372
373 switch (ini_section)
374 {
[439]375 case s_options:
[677]376 if (!_stricmp(name, "usedaodanbsl"))
377 opt_usedaodanbsl = !_stricmp(inifile_cleanstr(value), "true");
378 else if (!_stricmp(name, "border"))
379 opt_border = !_stricmp(inifile_cleanstr(value), "true");
380 else if (!_stricmp(name, "topmost"))
381 opt_topmost = !_stricmp(inifile_cleanstr(value), "true");
382 else if (!_stricmp(name, "multibyte"))
383 patch_multibyte = !_stricmp(inifile_cleanstr(value), "true");
384 else if (!_stricmp(name, "debug"))
385 AKgDebug_DebugMaps = !_stricmp(inifile_cleanstr(value), "true");
386 else if (!_stricmp(name, "debugfiles"))
387 BFgDebugFileEnable = !_stricmp(inifile_cleanstr(value), "true");
388 else if (!_stricmp(name, "findsounds"))
389 SSgSearchOnDisk = !_stricmp(inifile_cleanstr(value), "true");
390 else if (!_stricmp(name, "ignore_private_data"))
391 opt_ignore_private_data = !_stricmp(inifile_cleanstr(value), "true");
392 else if (!_stricmp(name, "sound"))
393 opt_sound = !_stricmp(inifile_cleanstr(value), "true");
394 else if (!_stricmp(name, "switch"))
395 M3gResolutionSwitch = !_stricmp(inifile_cleanstr(value), "true");
[705]396 else if (!_stricmp(name, "gamma"))
397 opt_gamma = !_stricmp(inifile_cleanstr(value), "true");
[466]398 else
[837]399 DDrStartupMessage("Daodan: Unrecognised ini option \"%s\"", name);
[439]400 break;
[347]401 case s_patch:
[677]402 if (!_stricmp(name, "fonttexturecache"))
403 patch_fonttexturecache = !_stricmp(inifile_cleanstr(value), "true");
404 else if (!_stricmp(name, "largetextures"))
405 patch_largetextures = !_stricmp(inifile_cleanstr(value), "true");
406 else if (!_stricmp(name, "levelplugins"))
407 patch_levelplugins = !_stricmp(inifile_cleanstr(value), "true");
408 else if (!_stricmp(name, "pathfinding"))
409 patch_pathfinding = !_stricmp(inifile_cleanstr(value), "true");
410 else if (!_stricmp(name, "projaware"))
411 patch_projaware = !_stricmp(inifile_cleanstr(value), "true");
412 else if (!_stricmp(name, "directinput"))
413 patch_directinput = !_stricmp(inifile_cleanstr(value), "true");
414 else if (!_stricmp(name, "wpfadetime"))
415 patch_wpfadetime = !_stricmp(inifile_cleanstr(value), "true");
416 else if (!_stricmp(name, "kickguns"))
417 patch_kickguns = !_stricmp(inifile_cleanstr(value), "true");
418 else if (!_stricmp(name, "cooldowntimer"))
419 patch_cooldowntimer = !_stricmp(inifile_cleanstr(value), "true");
420 else if (!_stricmp(name, "throwtest"))
421 patch_throwtest = !_stricmp(inifile_cleanstr(value), "true");
422 else if (!_stricmp(name, "alttab"))
423 patch_alttab = !_stricmp(inifile_cleanstr(value), "true");
424 else if (!_stricmp(name, "particledisablebit"))
425 patch_particledisablebit = !_stricmp(inifile_cleanstr(value), "true");
426 else if (!_stricmp(name, "multibyte"))
427 patch_multibyte = !_stricmp(inifile_cleanstr(value), "true");
428 else if (!_stricmp(name, "cheattable"))
429 patch_cheattable = !_stricmp(inifile_cleanstr(value), "true");
430 else if (!_stricmp(name, "argb8888"))
431 patch_argb8888 = !_stricmp(inifile_cleanstr(value), "true");
432 else if (!_stricmp(name, "killvtune"))
433 patch_killvtune = !_stricmp(inifile_cleanstr(value), "true");
434 else if (!_stricmp(name, "getcmdline"))
435 patch_getcmdline = !_stricmp(inifile_cleanstr(value), "true");
436 else if (!_stricmp(name, "disablecmdline"))
437 patch_disablecmdline = !_stricmp(inifile_cleanstr(value), "true");
438 else if (!_stricmp(name, "safeprintf"))
439 patch_safeprintf = !_stricmp(inifile_cleanstr(value), "true");
440 else if (!_stricmp(name, "daodandisplayenum"))
441 patch_daodandisplayenum = !_stricmp(inifile_cleanstr(value), "true");
442 else if (!_stricmp(name, "usegettickcount"))
443 patch_usegettickcount = !_stricmp(inifile_cleanstr(value), "true");
444 else if (!_stricmp(name, "cheatsenabled"))
445 patch_cheatsenabled = !_stricmp(inifile_cleanstr(value), "true");
446 else if (!_stricmp(name, "usedaodangl"))
447 patch_usedaodangl = !_stricmp(inifile_cleanstr(value), "true");
[705]448 else if (!_stricmp(name, "clipcursor"))
449 patch_clipcursor = !_stricmp(inifile_cleanstr(value), "true");
[677]450 else if (!_stricmp(name, "daodaninit"))
451 patch_daodaninit = !_stricmp(inifile_cleanstr(value), "true");
452 else if (!_stricmp(name, "bsl"))
453 patch_bsl = !_stricmp(inifile_cleanstr(value), "true");
454 else if (!_stricmp(name, "cheater"))
455 patch_cheater = !_stricmp(inifile_cleanstr(value), "true");
456 else if (!_stricmp(name, "newweap"))
457 patch_newweapon = !_stricmp(inifile_cleanstr(value), "true");
[693]458 else if (!_stricmp(name, "optionsvisible"))
459 patch_optionsvisible = !_stricmp(inifile_cleanstr(value), "true");
[705]460 else if (!_stricmp(name, "binkplay"))
461 patch_binkplay = !_stricmp(inifile_cleanstr(value), "true");
[347]462 else
[837]463 DDrStartupMessage("Daodan: Unrecognised ini patch \"%s\"", name);
[347]464 break;
[346]465 case s_language:
[677]466 if (!_stricmp(name, "chinese"))
467 patch_chinese = true;
468 else if (!_stricmp(name, "savepoint"))
[346]469 {
[677]470 char* str = _strdup(value);
[689]471 DDrPatch_Int32((int*)(OniExe + 0x000fd730), (int)str);
472 DDrPatch_Int32((int*)(OniExe + 0x000fd738), (int)str);
[346]473 }
[677]474 else if (!_stricmp(name, "syndicatewarehouse"))
[346]475 {
[677]476 char* str = _strdup(value);
[689]477 DDrPatch_Int32((int*)(OniExe + 0x000fd71a), (int)str);
478 DDrPatch_Int32((int*)(OniExe + 0x0010ef75), (int)str);
[346]479 }
[677]480 else if (!_stricmp(name, "damn"))
[689]481 DDrPatch__strdup((int*)(OniExe + 0x0010fb6e), value);
[677]482 else if (!_stricmp(name, "blam"))
[689]483 DDrPatch__strdup((int*)(OniExe + 0x0010fb73), value);
[677]484 else if (!_stricmp(name, "shapeshifter_on"))
485 DDr_CheatTable[0].message_on = _strdup(value);
486 else if (!_stricmp(name, "shapeshifter_off"))
487 DDr_CheatTable[0].message_off = _strdup(value);
488 else if (!_stricmp(name, "liveforever_on"))
489 DDr_CheatTable[1].message_on = _strdup(value);
490 else if (!_stricmp(name, "liveforever_off"))
491 DDr_CheatTable[1].message_off = _strdup(value);
492 else if (!_stricmp(name, "touchofdeath_on"))
493 DDr_CheatTable[2].message_on = _strdup(value);
494 else if (!_stricmp(name, "touchofdeath_off"))
495 DDr_CheatTable[2].message_off = _strdup(value);
496 else if (!_stricmp(name, "canttouchthis_on"))
497 DDr_CheatTable[3].message_on = _strdup(value);
498 else if (!_stricmp(name, "canttouchthis_off"))
499 DDr_CheatTable[3].message_off = _strdup(value);
500 else if (!_stricmp(name, "fatloot_on"))
501 DDr_CheatTable[4].message_on = _strdup(value);
502 else if (!_stricmp(name, "glassworld_on"))
503 DDr_CheatTable[5].message_on = _strdup(value);
504 else if (!_stricmp(name, "glassworld_off"))
505 DDr_CheatTable[5].message_off = _strdup(value);
506 else if (!_stricmp(name, "winlevel_on"))
507 DDr_CheatTable[6].message_on = _strdup(value);
508 else if (!_stricmp(name, "loselevel_on"))
509 DDr_CheatTable[7].message_on = _strdup(value);
510 else if (!_stricmp(name, "bighead_on"))
511 DDr_CheatTable[8].message_on = _strdup(value);
512 else if (!_stricmp(name, "bighead_off"))
513 DDr_CheatTable[8].message_off = _strdup(value);
514 else if (!_stricmp(name, "minime_on"))
515 DDr_CheatTable[9].message_on = _strdup(value);
516 else if (!_stricmp(name, "minime_off"))
517 DDr_CheatTable[9].message_off = _strdup(value);
518 else if (!_stricmp(name, "superammo_on"))
519 DDr_CheatTable[10].message_on = _strdup(value);
520 else if (!_stricmp(name, "superammo_off"))
521 DDr_CheatTable[10].message_off = _strdup(value);
522 else if (!_stricmp(name, "devmode_on"))
[349]523 {
[677]524 char* str = _strdup(value);
[349]525 DDr_CheatTable[11].message_on = str;
[452]526 DDr_CheatTable[cheat_x].message_on = str;
[349]527 }
[677]528 else if (!_stricmp(name, "devmode_off"))
[349]529 {
[677]530 char* str = _strdup(value);
[349]531 DDr_CheatTable[11].message_off = str;
[452]532 DDr_CheatTable[cheat_x].message_off = str;
[349]533 }
[677]534 else if (!_stricmp(name, "reservoirdogs_on"))
535 DDr_CheatTable[12].message_on = _strdup(value);
536 else if (!_stricmp(name, "reservoirdogs_off"))
537 DDr_CheatTable[12].message_off = _strdup(value);
538 else if (!_stricmp(name, "roughjustice_on"))
539 DDr_CheatTable[13].message_on = _strdup(value);
540 else if (!_stricmp(name, "roughjustice_off"))
541 DDr_CheatTable[13].message_off = _strdup(value);
542 else if (!_stricmp(name, "chenille_on"))
543 DDr_CheatTable[14].message_on = _strdup(value);
544 else if (!_stricmp(name, "chenille_off"))
545 DDr_CheatTable[14].message_off = _strdup(value);
546 else if (!_stricmp(name, "behemoth_on"))
547 DDr_CheatTable[15].message_on = _strdup(value);
548 else if (!_stricmp(name, "behemoth_off"))
549 DDr_CheatTable[15].message_off = _strdup(value);
550 else if (!_stricmp(name, "elderrune_on"))
551 DDr_CheatTable[16].message_on = _strdup(value);
552 else if (!_stricmp(name, "elderrune_off"))
553 DDr_CheatTable[16].message_off = _strdup(value);
554 else if (!_stricmp(name, "moonshadow_on"))
555 DDr_CheatTable[17].message_on = _strdup(value);
556 else if (!_stricmp(name, "moonshadow_off"))
557 DDr_CheatTable[17].message_off = _strdup(value);
558 else if (!_stricmp(name, "munitionfrenzy_on"))
559 DDr_CheatTable[18].message_on = _strdup(value);
560 else if (!_stricmp(name, "fistsoflegend_on"))
561 DDr_CheatTable[19].message_on = _strdup(value);
562 else if (!_stricmp(name, "fistsoflegend_off"))
563 DDr_CheatTable[19].message_off = _strdup(value);
564 else if (!_stricmp(name, "killmequick_on"))
565 DDr_CheatTable[20].message_on = _strdup(value);
566 else if (!_stricmp(name, "killmequick_off"))
567 DDr_CheatTable[20].message_off = _strdup(value);
568 else if (!_stricmp(name, "carousel_on"))
569 DDr_CheatTable[21].message_on = _strdup(value);
570 else if (!_stricmp(name, "carousel_off"))
571 DDr_CheatTable[21].message_off = _strdup(value);
[346]572 else
[837]573 DDrStartupMessage("Daodan: Unrecognised ini language item \"%s\"", name);
[346]574 break;
[451]575 case s_bsl:
[346]576 default:
577 break;
578 }
579
580 return true;
581}
582
583void DDrConfig()
584{
[677]585
[346]586 if (GetFileAttributes("daodan.ini") == INVALID_FILE_ATTRIBUTES)
587 {
[677]588 FILE* fp;
[837]589 DDrStartupMessage("Daodan: daodan.ini doesn't exist, creating");
[677]590 fp = fopen("daodan.ini", "w");
[346]591 if (fp)
592 {
593 fputs("[Options]\n", fp);
594 fclose(fp);
595 }
596 }
597
[837]598 DDrStartupMessage("Daodan: Parsing daodan.ini...");
[346]599 if (!inifile_read("daodan.ini", DDrIniCallback))
[837]600 DDrStartupMessage("Daodan: Error reading daodan.ini, check your syntax!");
601 DDrStartupMessage("Daodan: Finished parsing");
[346]602}
603
[439]604void ONICALL DDrGame_Init()
605{
606 if (opt_usedaodanbsl)
[739]607 SLrDaodan_Initialize();
[439]608}
609
[677]610void DDrException() {
611 int* i = 0;
612 *i = 1;
613}
614#include <stdio.h>
615
616//this was broken
617FILE** _UUgError_WarningFile = (FILE**)0x005711B4;
618FILE *__fastcall DDrPrintWarning(int filename, int linenumber, unsigned __int16 errornum, int message)
619{
620
621 FILE *v4; // eax@1
622 FILE *result; // eax@4
623 char v6[512]; // [sp+0h] [bp-100h]@1
624 FILE* UUgError_WarningFile = *_UUgError_WarningFile;
625
[689]626 if (filename && message && (strlen((const char*)filename)+strlen((const char*)message))<420) {
[681]627 sprintf(
628 v6,
629 "Error %x reported from File: %s, Line: %d (message follows) \r\n%s",
630 errornum,
[689]631 (const char*)filename,
[681]632 linenumber,
[689]633 (const char*)message);
[681]634
635 if ( UUgError_WarningFile
636 || (UUgError_WarningFile = oni_fopen("debugger.txt", "wb"), UUgError_WarningFile ) )
637 {
638 oni_fprintf(UUgError_WarningFile, "%s\r\n", v6);
639 oni_fflush(UUgError_WarningFile);
640 }
[677]641 }
642 //oni_fprintf(stdout, v6);
643 //sprintf(&v6, "%s", message);
644 *_UUgError_WarningFile = UUgError_WarningFile;
645 result = UUgError_WarningFile;
646 return result;
647}
648
[274]649void __cdecl DDrMain(int argc, char* argv[])
[273]650{
[677]651 int i;
652 char* section;
653 char* option;
654 bool falseoption;
655
[837]656 DDrStartupMessage("Daodan: Daodan attached!");
[466]657
[690]658 // Tell Oni to not load non levelX_final-files by default:
[466]659 opt_ignore_private_data = false;
[690]660
661 // Enable sound by default:
[466]662 opt_sound = true;
663
[346]664 DDrConfig();
[837]665 DDrStartupMessage("Daodan: Parsing command line...");
[466]666 for (i = 1; i < argc; i ++)
667 {
668 if (argv[i][0] == '-')
669 {
670 section = argv[i] + 1;
671 if ((option = strchr(argv[i], '.')))
672 {
673 *option = '\0';
674 falseoption = (option[1] == 'n' || option[1] == 'N') && (option[2] = 'o' || option[2] == 'O');
675 if (i < (argc - 1) && argv[i + 1][0] != '-')
[467]676 DDrIniCallback(section, true, option + 1, argv[++i]);
[466]677 else
678 DDrIniCallback(section, true, option + (falseoption ? 3 : 1), (falseoption ? "false" : "true"));
679 *option = '.';
680 }
681 else
682 {
683 falseoption = (section[0] == 'n' || section[0] == 'N') && (section[1] = 'o' || section[1] == 'O');
684 ini_section = s_options;
685 if (i < (argc - 1) && argv[i + 1][0] != '-')
[467]686 DDrIniCallback(NULL, false, section, argv[++i]);
[466]687 else
688 DDrIniCallback(NULL, false, section + (falseoption ? 2 : 0), (falseoption ? "false" : "true"));
689 }
690 }
691 else
692 {
[837]693 DDrStartupMessage("Daodan: Parse error \"%s\"", argv[i]);
[466]694 break;
695 }
696 }
[837]697 DDrStartupMessage("Daodan: Finished parsing");
[273]698 DDrPatch_Init();
699
700 // Safe startup message printer
[347]701 if (patch_safeprintf)
[689]702 DDrPatch_MakeJump((void*)UUrStartupMessage, (void*)DDrStartupMessage);
[273]703
[297]704 // Daodan device mode enumeration function
[347]705 if (patch_daodandisplayenum)
[705]706 DDrPatch_MakeJump((void*)gl_enumerate_valid_display_modes, (void*)DD_GLrEnumerateDisplayModes);
[297]707
708 // Performance patch
[347]709 if (patch_usegettickcount)
710 {
[689]711 DDrPatch_MakeJump((void*)UUrMachineTime_High, (void*)DDrMachineTime_High);
712 DDrPatch_MakeJump((void*)UUrMachineTime_High_Frequency, (void*)DDrMachineTime_High_Frequency);
713 DDrPatch_MakeJump((void*)UUrMachineTime_Sixtieths, (void*)DDrMachineTime_Sixtieths);
[347]714 }
[677]715
[339]716 // Cheats always enabled
[348]717 if (patch_cheatsenabled)
[689]718 DDrPatch_MakeJump((void*)ONrPersist_GetWonGame, (void*)DDrPersist_GetWonGame);
[677]719
[705]720 // DaodanGL with windowed mode support.
[347]721 if (patch_usedaodangl)
722 {
[705]723 // LIrPlatform_Mode_Set: GetWindowRect -> GetClientRect.
724 DDrPatch_NOOP((char*) OniExe + 0x00002dd6, 6);
725 DDrPatch_MakeCall((char*) OniExe + 0x00002dd6, (void*) GetClientRect);
726
727 // UUrWindow_GetSize: GetWindowRect -> GetClientRect.
728 DDrPatch_NOOP((char*) OniExe + 0x0002651c, 6);
729 DDrPatch_MakeCall((char*) OniExe + 0x0002651c, (void*) GetClientRect);
730
731 // LIrPlatform_PollInputForAction: fix GetCursorPos call to return client coordinates.
732 DDrPatch_NOOP((char*) OniExe + 0x000032cc, 6);
733 DDrPatch_MakeCall((char*) OniExe + 0x000032cc, (void*) DD_GetCursorPos);
734
735 // LIrPlatform_InputEvent_GetMouse: fix GetCursorPos call to return client coordinates.
736 DDrPatch_NOOP((char*) OniExe + 0x00002cc2, 6);
737 DDrPatch_MakeCall((char*) OniExe + 0x00002cc2, (void*) DD_GetCursorPos);
738
739 // LIrPlatform_PollInputForAction: translate SetCursorPos position to screen coordinates.
740 DDrPatch_NOOP((char*) OniExe + 0x000032b7, 6);
741 DDrPatch_MakeCall((char*) OniExe + 0x000032b7, (void*) DD_SetCursorPos);
742
743 // LIrPlatform_PollInputForAction: translate SetCursorPos position to screen coordinates.
744 DDrPatch_NOOP((char*) OniExe + 0x00003349, 6);
745 DDrPatch_MakeCall((char*) OniExe + 0x00003349, (void*) DD_SetCursorPos);
746
747 // Replace ONrPlatformInitialize.
748 DDrPatch_MakeJump((void*) ONrPlatform_Initialize, (void*) DD_ONrPlatform_Initialize);
749
750 // Replace gl_platform_initialize.
751 DDrPatch_MakeJump((void*) gl_platform_initialize, (void*) DD_GLrPlatform_Initialize);
752
753 // Replace gl_platform_dispose.
754 DDrPatch_MakeJump((void *) gl_platform_dispose, (void*) DD_GLrPlatform_Dispose);
755 }
756
757 if (patch_clipcursor)
758 {
759 // LIrMode_Set: replace LIrPlatform_Mode_Set call with our hook.
760 DDrPatch_MakeCall((void*)(OniExe + 0x00003f9f), (void*) DD_LIrPlatform_Mode_Set);
761
762 // LIrMode_Set_Internal: replace LIrPlatform_Mode_Set call with our hook.
763 DDrPatch_MakeCall((void*)(OniExe + 0x00003fff), (void*) DD_LIrPlatform_Mode_Set);
764
765 // LIrTermiante: replace LIrPlatform_Terminate call with our hook.
766 DDrPatch_MakeCall((void*)(OniExe + 0x000004cb8), (void*) DD_LIrPlatform_Terminate);
[347]767 }
[705]768
[349]769
[439]770 if (patch_daodaninit)
[689]771 DDrPatch_MakeCall((void*)(OniExe + 0x000d345a), (void*)DDrGame_Init);
[439]772
[447]773 // Patches for existing BSL functions
774 if (patch_bsl)
775 SLrDaodan_Patch();
[677]776
[452]777 if (patch_cheater)
[455]778 {
[689]779 DDrPatch_MakeCall((void*)(OniExe + 0x000f618f), (void*)DDrCheater);
780 DDrPatch_Int16((short*)(OniExe + 0x000deb45), 0x5590);
[677]781#if 1
[689]782 DDrPatch_MakeCall((void*)(OniExe + 0x000deb47), (void*)FallingFrames);
[677]783#endif
[689]784 DDrPatch_MakeJump((void*)(OniExe + 0x0010f021), (void*)DDrCheater_LevelLoad);
[455]785 }
[677]786
[689]787 DDrPatch_MakeJump((void*)(OniExe + 0x000245A0), (void*)DDrPrintWarning);
[452]788
[705]789 ONiMain(argc, argv);
[273]790}
[465]791/*
792void DDrWrongExe()
793{
794 switch (MessageBox(NULL, "This version of the Daodan DLL is incompatible with your Oni.exe.\n"
795 "Click OK for more information. To continue using Oni without the patch, replace the downloaded binkw32.dll with the original.", "Daodan", MB_OKCANCEL | MB_ICONERROR))
796 {
797 case IDOK:
798 {
799 STARTUPINFO si;
800 PROCESS_INFORMATION pi;
801 FillMemory(&si, 0, sizeof(si));
802 FillMemory(&pi, 0, sizeof(pi));
803 si.cb = sizeof(si);
804 if (!CreateProcess(NULL, "cmd /c \"start http://wiki.oni2.net/Daodan_DLL\"", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
805 MessageBox(NULL, "", "", 0);
806 CloseHandle(pi.hProcess);
807 CloseHandle(pi.hThread);
808 }
809 default:
810 ExitProcess(0);
811 }
812}
813*/
[272]814BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
815{
816 switch (fdwReason)
817 {
818 case DLL_PROCESS_ATTACH:
819 DDrDLLModule = hinstDLL;
820 DDrONiModule = GetModuleHandle(NULL);
821
[677]822 if (*(uint32_t*)(OniExe + 0x0011acd0) == 0x09d36852)
[689]823 DDrPatch_MakeCall((void*)(OniExe + 0x0010fb49), (void*)DDrMain);
[465]824 else
825 ExitProcess(0);
[272]826 break;
827 }
828 return TRUE;
829}
Note: See TracBrowser for help on using the repository browser.