Giter Club home page Giter Club logo

re4_tweaks's People

Contributors

codingsquirrel avatar emoose avatar kodi-patterson avatar laymonage avatar lioncky avatar nipkownix avatar pas-de-2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

re4_tweaks's Issues

Crash logging

It might be useful if some kind of crash logging can be added in, just in case some patch might interfere badly with something we haven't tried yet, might also help to track down some CTD issues like the ones reported in the #25 PR which might be caused by something in users config, making it hard for us to trigger on our end.

Windows default for app crashes is pretty bad now too, just ending the program with no indication that there was even any crash (the x has stopped working dialog has been disabled since Win10 for some incredibly stupid reason...)

IIRC SetUnhandledExceptionFilter can be used to set a function that receives info about the exception like exception code/address it happened/etc, was able to use that before in another project to write info about crashes into a log file.

I wouldn't be surprised if there was some lib somewhere that can handle this for us nicely, maybe even with minidump support, but haven't seen anything like that yet.

Suggestion: auto detect movie resolution

Might be nice if the movie-resolution patch could be automated based on the movie resolution, instead of needing to be specified in the winmm.ini, seeing as using 1080p in the winmm.ini also makes the original 512x336 movies play in a tiny screen, and also looks like the default 512x336 can cause a crash if the movie is in 1080p :/

At 0x6CD16D (1.1.0) there's a call to cSofdec::SetupResolution with the movie resolution passed over to it AFAIK (with movie resolution read by mwPlyGetHdrInf), maybe hooking that SetupResolution func & patching game based on it could work.
Maybe this is only ran after the part you patch for the resolution though, haven't really looked into it that much yet.

Post-processing issues

Mentioned at #4 (comment), the PC version may have some broken post-processing effects.

Seems there's a GXDoPostProcess func at 0x94AC20 in 1.1.0 EXE, that calls into PrepareBloom (0x9495E0), which then eventually calls DrawBloom (0x9374E0)

I tried nopping out the main call to these funcs at 0x6E9F81 (part of Render function), but didn't notice any change in the image, but maybe the area I was in didn't make use of it or something

Looking at the PS2/GC versions it seemed they didn't have any GXDoPostProcess function at all, is it that X360 first added the bloom but then it got broken during PC port? (I'm not really even sure how the bloom is broken atm...)

The game does have some other blurring effects called Filters, eg. Filter09 etc. haven't tried messing with those at all yet, but those were in PS2/GC too, could be that one of those was broken during the port.

btw I found that the GC debug build also included symbols in some weird format, much more than PS2 version, managed to dump them & get them loaded into IDA, I've upped the IDB for GC & PS2 here, along with 1.1.0 with some func names copied over:
re4_ps2_gc_symbols+pc_incomplete_idb.7z.zip (remove zip extension)
(for anyone just finding this, updated IDBs can be found in the posts below)

E: found a little more about the GC symbols, there's files for other things besides the main GC exe like Bio4.wep09.sym, which contain even more funcs that aren't in the main GC exe.
These seem to be for rel type files, which are kinda like windows DLLs, game only loads in code for what's actually being played, old game consoles were pretty big on "overlay" files like this, looks like the PC build has all these build into the EXEs though thankfully.

Some of the sym files do have rel files that go with them, like Tools.rel, but wep09 only has a drs file for it...
This confused me for a while, but turned out the drs actually contains the rel inside it - had to dig pretty far to find a tool that'd extract drs, since this was only used on GC it seems most didn't really care about them, not a whole lot of surviving info/tools for them...

Eventually found "BioHazard 4 File Archive Tool" inside a 400MB+ zip of RE modding tools, EXE name is bio4fat.exe, seems to work fine for extracting the debug build drs files, none of the extracted files have names though, but the last file extracted seems to usually be the .rel.

With that you can just use something like https://github.com/heinermann/ida-wii-loaders to load the rel into IDA properly, then apply the .sym for it on top (and I'd suggest making an IDA script for labelling the imports from the main EXE too)

"Assertion failed", can't run the game (cracked ver.)

Well, when I pasted the “Bio32” folder into the game folder, I started up the game and then this happened:
https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/272603883_239074528381694_683445978681698889_n.png?_nc_cat=101&ccb=1-5&_nc_sid=ae9488&_nc_ohc=LVm7lj23MpIAX8DDOOI&_nc_ht=scontent.fsgn2-4.fna&oh=03_AVJ7pHfVUrjRrfjf98R4KEnkbceKBUJ-85pNoX6R5XTpAA&oe=622046B8.
My game version is a non-steam one so I really don’t know if that version can run the HD Project. And I also used the 4gb patch then it still gave the same result.

JP-only camera angles restoration?

Not sure how well known it is, but JP version contains alternate fixed camera angles during Ashley's segment: https://www.youtube.com/watch?v=duf2zTBL9_0

TCRF mentions that it's still included in other versions (and there's even a way to trigger one of the cameras with noclip), wonder if it could be restored with a patch or something like that. Hopefully it might just be something in the EXE changing it, and not anything game-data related.

Haven't found any mentions of existing mods to add this, I guess since it's such a minor thing, but could be neat if we can find some way to add it back.

Startup Crash

Win 10 21H2
Steam Version: RE4 1.1.0
Video Card: MSI 3060TI
Memory 32GB.
CPU: 5800x

I have installed the RE4HD project files and patch the manually the 4gb patch tool https://ntcore.com/?page_id=371 I load any save it crashes, try to start a new game same issue crashes after the intro video.

X3DAudio1_7_HRTF support

Haven't seen this mentioned anywhere else, but seems https://github.com/kosumosu/x3daudio1_7_hrtf works with RE4 - compiled the latest commit of that (need to edit the DirectX-SDK-June-2010.props files with path to DX9 SDK), copied the compiled x3daudio1_7.dll to Bin32 folder, and with the *.mhr files from hrtf\KEMAR folder placed at hrtf\ next to BIO4\ folder, it should start up & work fine.

(if mhr files aren't placed at correct folder then DLL will cause an exception and show a non-helpful "runtime asked to exit" error, might be why PCGW currently lists RE4 as incompatible with it)

I'm not that great at telling how well the 3D audio is working there though, but seems to be fine for me, no obvious issues with it when I tried it out at least.

The log file the HRTF dll creates mentions that HRTF is missing datasets for certain sample rates though, 12000Hz, 18000Hz & 28000Hz were mentioned in my quick testing, would probably work even better if there was some way to create datasets for them (or maybe convert the audio to a different sample-rate that HRTF supports?)

E: ah seems it's not too hard to create custom MHR files, that PCGW page has a guide for it in the OpenAL Soft section.

Unfortunately the OpenAL-Soft tool for creating them has a lower-limit of 32000Hz built into it tho, but apparently others have been able to just edit the limit in the code for that tool & built MHR files with lower rates fine... I've asked on OpenAL-Soft's github page about it.

E2: Ah well it was a good thing I asked, seems it's likely HRTF wouldn't be as effective at lower sample rates like those. Ideally the x3daudio hook would resample audio first before applying HRTF to it, but doesn't look like it has any support for that. Unfortunately it hasn't been updated in over 3 years now, so not sure how much chance there'd be of adding that in :(

Second best option would be resampling the audio files themselves, assuming nothing is hardcoded in the EXE it should be possible I think, not sure if there's much info about modding RE4's audio files though, will try looking into it some more.

winmm.dll vs. dinput8.dll

I thought there was going to be a tremendous conflict with the new name of the DLL, but I just read the README and see now that we can renamed the RE4 Tweaks:

"If you use Raz0r's "Ultimate Trainer Companion", you will notice both mods use the same "dinput8" name. In this case, for them to work together, rename re4_tweaks's files to either "winmm" or "xinput1_3"

Thanks for keeping these two projects compatible! You can delete this issue now if you like.

Thanks!

`D3DCREATE_MULTITHREADED` flag removal

E: here's a build if anyone wants to try this out, should give some performance improvement, might help if you struggle to reach 60 - game might crash on launch sometimes (it's usually been fine for me lately though), but if you manage to load in it should hopefully be stable:
re4_tweaks1.7.4-RemoveD3DCREATE_MULTITHREADED.zip


Like mentioned at #5 (comment), the game uses the D3DCREATE_MULTITHREADED flag when creating the D3D9 device, which adds extra thread safety to the D3D funcs at a cost of performance.

Removing games frame cap showed removing this flag allowed going from 220FPS to 270FPS in one area, would probably be good for people that struggle running the game at 60 and end up with game slowdown due to it.

Unfortunately the game seems pretty unstable with this flag removed, obviously they didn't bother making it thread safe on Windows - however, it seems the game does have a pair of nullsubs around certain graphics-threading related things, kinda seems like they were meant to be a pair of funcs for locking/unlocking a mutex, but that's just a guess.

(On X360 the D3DCREATE_MULTITHREADED flag is apparently non-functional, not sure if that means X360 always had thread-safety stuff added, or maybe X360 devs had to be more careful with threading, which would explain the nullsub pair - but doesn't explain why they removed the code inside ;_;)


So I did another one of my experiments, hooked the two nullsubs to call lock()/unlock() on a std::recursive_mutex - sadly this resulted in a crash on boot, seems the UnlockMutex hook was being called before LockMutex for some reason, maybe the code for locking it got removed or something, just got around that by adding a hack to skip first call to it. (E: no longer needed)

Then the game just started hanging before intro movie, one thread was waiting on the mutex lock to get unlocked by another first, some reason there's a few LockMutex calls in the game without accompanying UnlockMutex after it - likely an accident, since the func for locking mutex also returns the D3D pointer, they probably added some Win32 specific code and needed a way to get D3D device, and didn't bother adding UnlockMutex afterward since Win32 didn't actually need it. (seems this missing UnlockMutex only happens around calls to D3DXCreateTextureFromFileInMemoryEx - guessing that func was probably added for Windows)

Hooking the calls to that D3DX func & making it use UnlockMutex afterwards seems to let it continue though, managed to load into a game fine with it, + haven't had any crashes yet (besides a crash on exit, probably not too hard to fix though)

(not sure how proper that fix is though, game seems to be doing something with a ptr returned from that D3DX func, so maybe it should only be unlocking after it's done with the ptr, instead of right after calling D3DX, not sure...)

Need to do more testing with it (only tried like 5 minutes in game so far), might need to make Imgui make use of those mutex funcs too if that also uses the D3D device.
(also need to check performance with it now, could be adding this mutex stuff slows it down the same as the thread flag)

Code:

#include <mutex>
[...]

std::recursive_mutex g_D3DMutex;

void __cdecl D3D_LockMutex_Hook() // hooks 0x9391C0
{
	g_D3DMutex.lock();
}

void __cdecl D3D_UnlockMutex_Hook() // hooks 0x9391D0
{
	g_D3DMutex.unlock();
}

int(__stdcall* D3DXCreateTextureFromFileInMemoryEx_Orig)(
	int a1,
	int a2,
	int a3,
	int a4,
	int a5,
	int a6,
	int a7,
	int a8,
	int a9,
	int a10,
	int a11,
	int a12,
	int a13,
	int a14,
	int a15);

int __stdcall D3DXCreateTextureFromFileInMemoryEx_Hook(
	int a1,
	int a2,
	int a3,
	int a4,
	int a5,
	int a6,
	int a7,
	int a8,
	int a9,
	int a10,
	int a11,
	int a12,
	int a13,
	int a14,
	int a15)
{
	auto ret = D3DXCreateTextureFromFileInMemoryEx_Orig(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
	D3D_UnlockMutex_Hook();
	return ret;
}

void ThreadFix_Hook()
{
	const int D3DCREATE_MULTITHREADED = 4;
	// Clear D3DCREATE_MULTITHREADED flag from D3D CreateDevice call
	auto pattern = hook::pattern("68 ? ? ? ? 68 ? ? ? ? 6A 44 56 8B 35");
	auto ptr_CreateDevice_BehaviorFlags = pattern.count(1).get(0).get<uint8_t>(0xB);
	Patch(ptr_CreateDevice_BehaviorFlags, uint8_t(*ptr_CreateDevice_BehaviorFlags & ~D3DCREATE_MULTITHREADED));

	// Game has a pair of nullsubs that are always called just before graphics-threading related code is used
	// Kinda seems like they were meant to be a pair of funcs for locking/unlocking a mutex, but that's just a guess.
	// Restore these so that flag removal above can be made more stable
	pattern = hook::pattern("E8 ? ? ? ? A1 ? ? ? ? A3 ? ? ? ? 89 1D ? ? ? ? A3 ? ? ? ? E8 ? ? ? ? 8B 35");
	auto ptr_D3D_LockMutex = injector::GetBranchDestination(pattern.count(1).get(0).get<uint32_t>(0)).as_int();
	InjectHook(ptr_D3D_LockMutex, D3D_LockMutex_Hook);

	pattern = hook::pattern("E8 ? ? ? ? 68 ? ? ? ? FF 15 ? ? ? ? A1 ? ? ? ? 50 FF 15");
	auto ptr_D3D_UnlockMutex = injector::GetBranchDestination(pattern.count(1).get(0).get<uint32_t>(0)).as_int();
	InjectHook(ptr_D3D_UnlockMutex, D3D_UnlockMutex_Hook);

	// Game calls D3D_LockDevice before D3DXCreateTextureFromFileInMemoryEx
	// LockDevice returns pointer to D3D device, so they probably used that as a quick way to retrieve it, but forgot/didn't care about using UnlockDevice afterward
	// Hook the misbehaving calls so we can add UnlockMutex calls to them
	// (not sure if this is safest way to do it though - game seems to do something with the ptr returned by D3DXCreate...
	// maybe UnlockMutex should be after it's finished with that ptr, would be harder to patch in tho...)
	pattern = hook::pattern("53 E8 ? ? ? ? 50 E8 ? ? ? ? 8B 36 8B 0E 8D 55 ?");
	auto ptr_caller1 = pattern.count(1).get(0).get<uint32_t>(7); // 0x98009D
	ReadCall(ptr_caller1, D3DXCreateTextureFromFileInMemoryEx_Orig);
	InjectHook(ptr_caller1, D3DXCreateTextureFromFileInMemoryEx_Hook);

	pattern = hook::pattern("57 E8 ? ? ? ? 50 E8 ? ? ? ? 8B 06 8B 10 8B 52 ? 8D 4D ?"); // 0x980234 & 0x981049
	InjectHook(pattern.count(2).get(0).get<uint32_t>(7), D3DXCreateTextureFromFileInMemoryEx_Hook);
	InjectHook(pattern.count(2).get(1).get<uint32_t>(7), D3DXCreateTextureFromFileInMemoryEx_Hook);

	pattern = hook::pattern("53 E8 ? ? ? ? 50 E8 ? ? ? ? 8B 36 8B 0E 8D 55 ? 52"); // 0x9E4B82, unused?
	InjectHook(pattern.count(1).get(0).get<uint32_t>(7), D3DXCreateTextureFromFileInMemoryEx_Hook);

	pattern = hook::pattern("57 E8 ? ? ? ? 50 E8 ? ? ? ? 8D 4D ? 8B F8 8B 06 8B 10 8B 52 ?"); // 0x9E6619
	InjectHook(pattern.count(1).get(0).get<uint32_t>(7), D3DXCreateTextureFromFileInMemoryEx_Hook);

	// Lone UnlockMutex call at 0x955792 - doesn't have a LockMutex call before it for some reason
	// this would cause game crash on startup, and skipping it caused game crash on exit - nopping it instead seems to fix both
	pattern = hook::pattern("89 0D ? ? ? ? A3 ? ? ? ? 89 99 ? ? ? ? 89 99 ? ? ? ? E8 ? ? ? ?");
	Nop(pattern.count(1).get(0).get<uint8_t>(0x17), 5);
}

Random crash, possibly related to RaiseInventoryAlloc

@emoose Looks like we might have to delay that release we talked about.
Albert sent me the latest version of his ss_pzzl work for me to check out a glitch he was having, which is this one:

image

Appears to be some vertex explosion situation, maybe? Can't check if it happens with the other .dll because that one can't handle a ss_pzzl this big.

I failed to reproduce the issue on my end, but when I tried to go back to the main menu to quit the game, it crashed.
Apprently it crashed inside a function called cDataUnit::checkMallocRelease, hence why I think it must be related to RaiseInventoryAlloc.

Here's the log + dump:
CrashDumps.zip

And here's the ss_pzzl albert sent me:
https://files.catbox.moe/366ogh.rar

I've done some investigation of my own, but I'm stumped. The memory-related stuff is kinda too complicated for me, I guess.

Crash when starting application and trying to patch the executable

When starting RE4_tweaks with www.re4hd.com's mod, and starting the game I get the message that it wants to patch it to support more than 2GB of RAM.

However the screen almost instantly freezes and I cannot select the option to do it. Tried moving mouse, hitting the Enter key or using the arrows and cannot get any response; I have to force open task manager and force close the application in order to free up my system.

https://ntcore.com/?page_id=371 This manual patcher instantly worked and was able to play using the mod right away

AMD Ryzen 5 2600
16.0 GB RAM
GTX 1080 TI
16 GIG RAM
No other mods
BIO4 37.4 GB, 6804 files
BIN32 3.92 MB, 4 files
No issues before install

Feature Request - Fix lag spike when custom enemies are loaded

Has anyone else noticed that custom enemies with lots of vertex data cause a short lag spike when we first load a room? This lag spike only happens when we are NOT initially facing the enemies as the room loads, but happens when we first turn around to face them.

I was speaking about this with an experienced RE4 modder who does custom rigging and he noticed the same issue when running some tests. The issue is not because of the number of polygons per se, but the amount of varying vertex weights. With smaller amounts of weights assigned to a mesh it seems to be ok, but when using weight blending and larger amounts of weight data, the lag spikes happen.

I am wondering if your team would be willing to observe this phenomenon and see if you could figure out why its happening and try to fix it? Otherwise we are stuck with creating really simple rigs on custom enemy models.

Thanks!

Game prompts for 4gb patch, crashes after 1998...

What are your system specifications? Win10x64 21H2 -i3 10100, 1060 3GB
When does the crash or visual bug take place? After loading new game, prompts for 4gb patch, select yes or no, game crashes at 1998... intro 
In which language are you playing the game? English
Did you install other mods? None, fresh install 
What is the total file size and number of files inside the BIO4 folder? 37.4gb, 6,804 files
What is the total file size and number of files inside the Bin32 folder? 21.4mb, 7 files
Was the issue there before installing the HD project? (We can’t do anything if you already experienced the issue with the original game.) Never played game before, purchased today, installed, rebooted, installed re4hd, rebooted, issue. 
A screenshot or video of the issue (if possible). I'm sure you've seen the Windows "we've encountered an error" screen, so I wont include. 

Bugfix request: make retry/load menu actually keep the selected option

On the retry/load menu you have a few options, retry from checkpoint, load save, or exit to main menu.
After selecting one the game asks if you're sure, and you have to choose yes/no - except during the yes/no selection your mouse cursor can actually change what option you selected, so you might choose retry from checkpoint, then accidentally hover over exit to main menu before choosing yes to continue, making the game actually exit back to main menu, even though retry from checkpoint was what you selected >.>

This bug bit me a couple times during my main RE4 playthrough, would be nice if option could be "locked-in" once you pick it instead.
Using mouse cursor to pick yes/no is kinda buggy as it is, moving over the text doesn't choose it, you have to put it somewhere just nearby instead - maybe would be better to just disable mouse cursor on this screen after an option is picked.

Those menus seem coded pretty differently to GC build so don't have much named for it in my IDB, OptionScreen::move calls into retry_load_menu, but that func is way different to GC version - maybe should take a look at PS2 one instead...

re4tweaks glitches certain cutscenes

Not sure how to word it, but installing re4_tweaks (latest stable version, 1.5) seems to glitch out multiple cutscenes. The audio still plays, but the screen displays as pure black until it ends.

Attached: The bug affecting the first Ada's Report (it's only a few seconds before I skip it with ESC because of gamebar recording's abysmal compression), but I've also seen it happen to:
Separate Ways Prologue
Separate Ways Chapter 1 End

Resident.Evil.4.2021-11-06.07-27-54.mp4

For reference, Ada's Report 1 is supposed to play out like this.

Binocular zoom has almost no blur when using mousewheel

Some reason using mouse scrollwheel to zoom the binoculars only results in very minor blurring, while controller has a much stronger effect, must be something to do with how the mousewheel zoom was implemented - seems mousewheel makes it snap to different zoom levels, while controller stick lets it go smoothly between them.

I guess blurring effect is kept active while controller is going between them until controller stick is released, while with mousewheel maybe it's being treated as "released" as soon as it's snapped to a level, not really sure how much could be done to improve this, if anyone has any ideas please let me know.

Debug menu navigation with controller

Hey friends. Just want to say great work so far. I am hoping to draw some attention to the Debug Menu when using a controller. It seems the input is EXTREMELY sensitive to controller input (one light press on the D-pad would equate to holding down the arrow button on a keyboard for at least a full second). This results in not being able to navigate the menu with a controller (id love to not have to use my keyboard at all).

Can anyone confirm this is happening? I am using a DS4 controller that is emulating an XBOX controller with DS4Windows build 3.0.9

Thanks!

Add option to set a custom refresh rate

The game defaults to 60 Hz even if you're running a modern display with 120 Hz or higher refresh rates. Any idea if you can add a refresh rate Hz option. Thanks

RaiseInventoryAlloc: Invisible models for unknown reasons

Example from one user:

image

Seems to be the same issue from a while ago. I sadly still can't reproduce this issue for some reason. Tried starting Mercenaries with wesker on all stages, but the silencer was always visible.

Gotta admit I'm stumped here. Hopefully @emoose could have some idea.

If anyone experiences this issue and can help us testing possible workarounds, please let us know.

Feature Request - toggle DLL

While testing various issues I often have to move or rename the DLL to activate/deactivate it. Would it be possible that you could put a kill switch in the winmm.ini with something like:

[ACTIVATE]
; Use this DLL
UseThisDLL = True

This way users could simply add true false in Notepad ++ and switch back and forth without having to rename or move any files.

Thanks!

Feature Request: Turning off Mouse acceleration (if possible)

Aside from adjusting sensitivity RE4 has two options for Mouse aiming "Classic", which gives you negative mouse acceleration, and "Modern", which gives you positive mouse acceleration and... yeah no option for no mouse acceleration. In fact changing that option just changes the value of MOUSE_ACC to 0 or 1 respectively. I don't know how feasible turning it off is; I hope the fact that there are two forms of mouse acceleration is helpful for finding where the value is applied so that it can be changed. Just listing this as an issue that's been bothering me (throws off my gyro aiming control setup) that I'm not sure is very visible or not.

Crash opening options from main menu

Using latest 1.7.2 release with the included dinput8.ini & clean 1.1.0 bio4.exe, game crashes when opening options menu - removing dinput8.dll allows it to open it fine though, so don't think it's an issue with my games config.ini or anything.

Log file:
bio4.exe.20220129221113.log

Seems to be something to do with the resolution chooser again, I used NV control panel to add 90Hz option for my resolution, so I have both 90Hz & 60Hz for the same res, maybe that's something to do with it (my desktop is at 90Hz, but maybe it's only exposing 60Hz to D3D or something weird)

Jogo não inicia depois da instalação hd project

Ryzen 5 3350g
16gb de ram
video integrado vega 11

Método de instalação por torrent, manual e automatico

Após a instalação da modificação o jogo não inicia, o que não acontecia antes com instalação limpa

plXX.udas memory increase

Got a request on residentevilmodding forum about increasing memory size for the plXX.udas files, which might be needed to let people use higher-poly models, apparently the other dll has something for increasing this, so should be possible for us to fix it too.

Haven't looked into it yet but hopefully it's just something related to the addrs setup by SystemMemInit, like ss_pzzl was, or maybe it's something polygon/Prim related again.

Asked them if they can send a plXX.udas that game doesn't work with atm, I'll edit this if I get hold of one.

E: seems ReadPlayerData does try to read into a PL00_ADDR ptr (name from VR symbols), which gets setup by SystemMemInit as somePool+0x2A8D000, seems that area only has 0x1E8000 bytes until it enters the next addr setup by SystemMemInit (DRTEMP_ADDR), so I'd guess this might be the problem with it (for reference, largest plXX.udas in vanilla game seems to be 0x1B9EA0)

E2: I think hooking the DvdReadN call inside ReadPlayerData might let us change the ptr & size of PL00_ADDR dynamically, looks like filename is passed over to DvdReadN, so we could check size of the file being read in first, then could probably overwrite PL00_ADDR ptr with a new malloc'd array.

There is another function Event::ExeBeginEvt that does something with PL00_ADDR though, either reading some tpl files into it, or maybe just reading some value from inside it instead, not sure, hopefully just the latter.

Allow savegame transfers

Game seems to check for SteamID inside savegame00.sav file, and refuses to load if it's different... Seems to have an ID at 0x1E40, and I guess there's a checksum/hash somewhere that it checks too since editing that ID doesn't seem to work.

Probably wouldn't be too hard to remove SteamID check.

E: seems to be two checks inside CRCVerifyCRC, 0x83DB95 & 0x83DBA4, with those two nopped it seems to load saves from other people fine.

Subtitles don't show up with AllowHighResolutionSFD

It doesn't seem to happen on videos from Separate Ways (maybe because SW uses a different code path), but can be seen on the main game's intro video.

It also only happens if the video is in HD, which doesn't seem to make a lot of sense. This probably means that none of our code is broken, but this code path is expecting the 512x336 resolution for something related to subtitles, maybe?

How to reproduce: simply change the game's language to Spanish on Steam and start a new game.

Edit: looks like they work in the movie browser, but not in-game.

Framerate slowdown & 60FPS issues

So the rifle/bow 30FPS reload animation is brought up a lot, I've tried naming & looking into all the sniper/Wep09 related funcs in my IDB, but couldn't really find much to help with it so far.

Looks like animations are stored as FCV format files, usually inside the weapons BIO4/Em/wepXX.udas.lfs file.
Apparently the FCV stores things like frame numbers & counts inside it, but does the EXE have anything to interpolate that to work with different framerates, or is that data just used directly?

Handgun/shotgun/etc reloading seems fine at both 60 & 30FPS, did they update the FCV to work at 60 for those, or is there just code somewhere to make it work at 60? (maybe the 120FPS-without-slowdown hack from #5 can help give some insight here)
(also if the FCV data for those was updated to 60, does that mean playing at 30FPS makes it run fast or something?)

If it is just FCV-data related I would have thought someone would have made a mod to fix it by now, which makes me think it's probably something code related too, that's just a wild guess though.

Maybe comparing code for Handgun/shotgun against GC could reveal something.

FOVAdditional causes crash on first level?

Hi, seems re4_tweaks causes a crash for me on the first level for some reason, I wrote some more about it on the NM page: https://www.nexusmods.com/residentevil4/mods/101?tab=posts

Some reason I keep running into a crash right at the start of the game though, after starting new game skip through the intro movies, then when you spawn in the map just run forward, always seems to crash for me just before reaching the signpost :/

Strange thing is I'm sure I got passed the signpost before, with the exact same settings etc. Not sure what could have changed that made it start crashing...

If I rename winmm.dll to disable it the crashing goes away, so seems it's probably something that re4_tweaks added in. (should probably mention, I'm using the re4hd pack too)

E: ah might be caused by FOVAdditional, I was using 20 for the above, but changing it to 0 seems to get rid of the crashing.
Unfortunately the FOV changes is mostly what I used re4_tweaks for though... I could use a save to skip past the area that crashes & use 20 with that, but not sure if there's still a chance of something else also crashing later on due to it :/

EDIT: seems it's not just the first level, have had crashes loading from saves too :/ changing back to FOVAdditional = 0 stops the crashes from happening though.

game won't show

i installed it as instructed and even manually patched the games exe

but it won't show anything, i hear sounds from the game and my cursor dissapears, but the screen is just my desktop

core I5 8600k
amd rx 5600 xt
32 gb ram

Suggestion: Modern control movement

Well, i know that game is classic, but "tank" control very old scheme. If you could make optional quality of life for game (how it was for re1hd), it will be cool!
What came to mind right away:
Is possible to make strafe ? So that the character can walk left and right
Standard crosshair instead of laser (like in wii version, but always centered, like in re 5).
Moving the camera in walking with the mouse (i mean not like now, for looking around. Make mouse use for rotation when character is moving ).

Seperate fov option for ashley?

hello i was wondering if maybe u could add a seperate fov setting for ashley, the one i use pulls itself too far back when ashley is in the party so i have to lower it when she joins

Game crashing when opening up the map (modded version)

Whenever I open the map the game crashes, but it should be noted that I have a modified version of the map_obj1_07.MAP file (which I have replaced with a custom file). I have tested this with and without your DLL, and it works fine without it.

I'm not sure if you can check this out on your own and try to figure out how to fix this for me, but it would be a great help for my project as I would really like to preserve the functionality of my mod with your DLL. I asked my engineer to look at why the crash was happening but he could not find any causes. Perhaps you might have better luck.

Could you load up this file with and without your DLL and tell me what you think? You should load the game in the village to make the correct map file is loading (the modified version of the file only loads in the Village areas, eg r1xx.udas)

My theory: The modified version of this map file contains too many vertices, and has something to do with one of your memory patches (just a theory).

remix1
remix2
As you can see, the modified version has many more vertices than the original below:
remix3

Here is what it should look like (ignore the lightning effect)
https://www.youtube.com/watch?v=R7QN1sQFZiA

FPS gets locked to 32 in some particular cutscenes in 60 FPS mode

One particular scene in one of the cutscene gets locked to 32 FPS while playing in 60 FPS mode. This particular problem doesn’t seem to be on system specs since the fps gets locked to 32 even with lowest resolution [800×600] from the settings menu and GPU utilization doesn’t even max out.

The fps lock occurs only when Saddler is talking before Leon gets injected with the plagas. Once he’s done talking, the FPS goes right back to 60.

The real issue here is that, that momentarily fps lock causes the Audio to loose sync for rest of the cutscene [where Leon talks with Luis].

Here’s screenshot of the particular scene:
https://cdn.discordapp.com/attachments/288942291677216768/938389525321904128/Resident_Evil_4_Biohazard_4_Screenshot_2022.02.02_-_16.58.48.13.png

The lock is specifically 32 FPS, not even more or less, not even 30. So this is not related to double buffer vsync fps drop. But I tested with Vsync off to make sure it really wasn’t the case.

.
.
.
.
.
.
These are my system specs:

GPU- 980 Ti
CPU- i7 6700k
RAM- 16 gb [2400mhz]

Tested resolutions for this bug:
800×600, 1280×720, 1920×1080, 3840×2160
.
.
.
Also it's worth mentioning, the drop only occurs after installing the latest version of the HD mod.

I tried the latest version of re4_tweaks with unmodded game, and with the previously released 2018 version of the texture mod and the fps stays intact on those.

4GB-patch indicator

Might be a good idea to indicate to user whether they have 4GB patch active or not somehow, like the other DLL does, been a few times now that I've ran an EXE that wasn't patched & had issues because of it >.>

Doesn't seem like there's any way to 4GB patch it at runtime unfortunately - I wonder if we might be able to edit the EXE itself if the user hasn't already patched it though, hmm...

(also the way the other DLL checks for 4GB patch is wrong, seems they're checking for a constant 0x122 Characteristics value, when they should only be checking for the 0x20 bit, if you have the Relocations stripped flag active that adds 0x1 to it, so it's 0x123, making that DLL think it isn't 4GB patched 😆)

E: did a quick experiment, looks like on Windows you can't open the running EXE with fopen for writing, but you can move it!
Probably wouldn't be too hard to just copy the existing EXE + edit the Characteristics flags, then move them around so the patched EXE will be launched by user next time.

I'm not sure if being in Program Files could mess that up at all though, pretty sure I heard Steam sets up permissions on SteamApps dir to allow changes, but not 100% sure about that.

a couple of questions from a seasoned modder

Greetings. I have just come across your project and am quite interested in a couple of features. I was wondering if you could tell me about two things for now:

1 - Film grain
THis effect is present in many rooms, and is often edited by people by simply applying alpha to the 0193.dds inside 07000000.pack file. While this is the easiest way to accomplish the film grain removal, it is also brutal in the sense that it destroys the efficacy of other effects that rely on this texture. This leads me to ask, does your code use the same method of essentially nulling this texture or does it a more robust approach of editing the effect in the EFF file? I would be happy to lend you my expertise to accomplish this in a less destructive way if you are simply nulling the texture.

2 - Transparency overlay
This interests me deeply. You see there is a small texture inside 07000000.pack file (0236.dds) that is used for several overlays, one of which is in the examine window. It essentially blacks out the middle of the screen, while there is another texture used for gradients on either side of the middle. This texture is also used for the black under the numbers in the inventory case (the numbers used to count ammo amounts etc). So my question is, how does your transparency edit work? Does it alter a texture?

Happy Modding!

winmm.dll sometimes is not loaded properly

Is there any situation where Windows would ignore winmm completely? Or maybe force it to only load from System32/SysWOW64?

I've seen reports of people saying re4_tweaks would simply not load after placing the files next to the .exe
I've also confirmed with at least one of these people that wrapping dinput8 instead (by just renaming winmm to dinput8) works just fine.
The reason I've initially gone with winmm instead of dinput8 is because that's what raz0r's dll uses, and I didn't want to make people choose between the two. But now that this winmm issue is a thing.. we might have to change the default wrapped dll?

Save Feature from Debug issues

So I'm having two issues with the debug menu option to save the game, which I am not sure are related or not. The first issue is that while I'm saving using the Debug menu the game overlay seems to combine two separate pages. As seen in the image below, you can see that the Options page menu options are overlaid on top of the typewriter. In this circumstance the Options page is what receives controller input, and not the typewriter. This means that I am unable to scroll up and down inside the typewriter while this Options page is overlaid on top of if.

dll save

After I exit the save, this happens:
dll save2
The red circle in the bottom right bugs out rapidly loading different textures and the Options page is transparent over the game.

The second issue I am having is about how the game handles the save that is created. It was my understanding that you could save anywhere in a room, but it seems that all my saves place the player at the default starting position of the room. When I asked another user to check into this they told me they were able to save anywhere in a room and that when they load that save it would load from the exact position in the room they saved at, but that is not the case for me. I am wondering if anyone else has experienced this issue of the save location being set to the default area of the room.

The game froze once at the beginning (1.1.0, English, No Mods, New Game, Normal, Standart Costume)

The game froze when I tried to ‘check’ the broken bridge after the ambush at the beginning of the game. I could Alt+Tab, but I couldn’t actually switch windows or do anything at all. Even the mouse cursor disappeared. Alt+F4 didn’t work, too. So, I had to restart a PC.

The second time went perfectly fine. What’s interesting, during the first attempt there were no button prompts for actions (‘Check’, ‘Take’, etc.). After the restart of a PC, they appeared. I don’t know if this is connected to freezing.

And another thing: when the game froze, the sound was still on, but not from the cutscene with Leon looking down, but the ambient one.

Win10 (64-bit)
750 Ti
i5-3450 3.10Ghz
8,0 GB RAM
SSD
The game played on Steam

BIO4: 6,804 files; 37,4 GB (40 241 926 498 bytes [size]/40 254 124 032 bytes [size on disk])
Bin32: 7 files; 21,4 MB (22 498 912 bytes [size]/22 511 616 bytes [size on disk])

LFS compression format

I saw Albert mentioned on twitter a few weeks ago that part of reason for RE4HD's large filesize is due to .lfs not being able to be re-packed atm: https://twitter.com/re4hdproject/status/1454153402787708931

Might be nice to look into that, if anyone knows about any existing tools for it please let me know, only thing I've found so far is a quickbms script, but that does give some useful info:

comtype xmemdecompress
get name basename
log MEMORY_FILE 0 0 
goto 0x10
get chunks long
append
for i = 0 < chunks
get zsize short
get size short
if size = 0 
    math size = 0x10000
endif
get offset long
math offset + 0x13
clog MEMORY_FILE offset zsize size
next i
append
get size asize MEMORY_FILE
log name 0x00 size MEMORY_FILE

Seems they use the XMemDecompress xbox360-api for compression, pretty sure I've seen tools for compressing that around before, maybe just a matter of adding on whatever weird header lfs files start with.

E: ah okay format is pretty simple, hardest bit is probably the weird way they store offsets to each compressed chunk (seems to be aligned to each 0x14 bytes or something stupid)
Unfortunately couldn't find any working XMemCompress code on the net, but luckily I had some old code from messing about on x360 stuff that does seem to work, will try putting something together soon.

Physics / Animations

I'm opening this issue so we can track these better.

Albert mentioned some issues related to animations and physics:

  • Missing facial expressions in-game (Leon's expression when he's hurt or dies should change)
  • Physics not working inside the inventory screen (causes clipping issues with Leon's jacket and the absence of Ada's black ribbon in the inventory)
  • Leon's physics when he's wearing the tactical vest (pl09) are gone (static hair).

About the inventory physics issue, albert mentioned it was a working in the bio4 demo (for the GC i guess), but they disabled it/removed for the final version.

I've been looking at this, and it appears there's a function for each character that controls these physics.
For Leon, it is cPlLeon::moveCloth.
Noping it's call makes it look like it does in inventory screen:

image

It is called by the cPlayer::move, which itself is inside gameMainLoop.
gameMainLoop isn't called while inside the inventory screen, so we get static cloth.
Not sure this would simply be fixed by having cPl**::moveCloth inside the inventory screen's main loop, but who knows?

About the tactical vest stuff: I do know the game applies different physics/cloth parameters based on what player model you're using. It is not something store inside the model itself (in this case pl09), but instead some type of table inside the .exe.
That other dll fixed the issue, as far as I can tell.

Feature request: allow setting window position in windowed mode

Would be nice if window position could be set in winmm.ini or something, as I have my taskbar-on-top the game seems to have a bad habit of drawing the screen behind it, so the first 50 pixels or so have my taskbar icons on top of it :/

I think window position can be set when CreateWindow is used, might be able to specify borderless-window by changing CreateWindow params too, remember doing something like that for sh2proxy anyway.

(or maybe there's a way to make the game move itself after the taskbar automatically - in other apps that render behind taskbar, usually I can get them to move by just dragging bottom-right & resizing the window, doing that usually gets Windows to automatically move it, wonder if that works programmatically too)

Even better would be some way of saving where the user dragged the window to, Windows might be able to handle that itself, but I think game does something at startup that moves to 0,0 :/

E: wow, it took 4 different patches to completely stop game from moving the window:

  SafeWrite(GameAddress + 0x54B7D5, uint8_t(0x90), 6);
  SafeWrite(GameAddress + 0x53A219, uint8_t(0x90), 6);
  SafeWrite(GameAddress + 0x53A226, uint8_t(0x90), 6);
  SafeWrite(GameAddress + 0x53A243, uint8_t(0x90), 6);

I think only the last one would need to be hooked there, but maybe nopping all those + hooking CreateWindowExA could be a nice idea, could set the location once so the window won't have to move/snap itself to a position after initing like it currently does.

E: got something working, with borderless windows too :) gonna try making some sigs for it now.

Issue with missing buttons in game. About aspect ratio

The problem is very old (from the release), it seems to be somehow related to the language that is used in the system. I noticed that it manifests itself if you start using, for example, the Russian language, the Taiwanese language, perhaps some other. The buttons disappear completely, although I use the English version, they are not there when the context menu appears.
Screenshots are attached.
And also, is it possible to correct aspect ratio for 4:3, 5:4, and for other non-standard resolutions? The old permissions even at that time were greatly curtailed by cinematic black bars.
Launched a game with Russian in the system:
20220202181359_1
Launched a game with English in the system:
20220202181532_1
Launched a game with Russian in the system:
20220202181801_1
Launched a game with English in the system:
20220202181601_1

Modded ss_pzzl crash

Seems modded ss_pzzl can still cause a crash when a note/file item is being read, not sure if it's all note items, but the one in Salazar Castle just outside the knight room loading door seems to always crash for me.

Original ss_pzzl works fine, so it's probably not related to buffer being relocated, guess it's probably overloading something else.

E: strange, this only seems to happen when launched through steam, running Bio4.exe itself (eg. through IDA's debugger) seems to stop it crashing, weird.

Debug/"tool menu" restoration

Seems a lot of the code for the "tool menu" found in the asia_debug build is still in the final EXE too, at least the 1.1.0 version.

Final build is mostly just missing a call into the handler function for it, and a func that displays debug text to screen (luckily for me a lot of the code for writing the text was still in the EXE though :)

// Button definitions used by tool menus
enum class GamePadButton
{
  DPad_Left = 1,
  DPad_Right = 2,
  DPad_Down = 4,
  DPad_Up = 8,
  RT = 0x10,
  RB = 0x20,
  LB = 0x40,
  LT = 0x80,
  A = 0x100,
  B = 0x200,
  X = 0x400,
  Y = 0x800,
  Start = 0x1000,
  Back = 0x2000,
  RS = 0x4000,
  LS = 0x8000,
  LS_Left = 0x10000,
  LS_Right = 0x20000,
  LS_Down = 0x40000,
  LS_Up = 0x80000,
  RS_Left = 0x100000,
  RS_Right = 0x200000,
  RS_Down = 0x400000,
  RS_Up = 0x800000,
};

uintptr_t pG_ptr = 0;
uintptr_t pSys_ptr = 0;

// recreate gameDebug function from debug EXE, opens tool menu when button combo is pressed
// 0x63C610 into debug EXE
typedef void(__cdecl* DbMenuExec_Fn)();
DbMenuExec_Fn DbMenuExec = nullptr;
uint32_t* PadButtonStates = nullptr;
uint32_t PrevKeyboardState = 0;
typedef void(__cdecl* GameTask_callee_Fn)(void* a1);
GameTask_callee_Fn GameTask_callee_Orig = nullptr; // func we patched call to
void __cdecl gameDebug_recreation(void* a1)
{
  // Check pressed keys & emulate controller presses for tool-menu
  uint32_t keyboardState = 0;
  if (GetAsyncKeyState(VK_HOME))
    keyboardState |= uint32_t(GamePadButton::LT);
  if (GetAsyncKeyState(VK_END))
    keyboardState |= uint32_t(GamePadButton::LS);

  // Only emulate main keys if tool-menu is actually open
  uint8_t* pG = *(uint8_t**)pG_ptr;
  bool inDebugMenu = (*(uint32_t*)(pG + 0x60) & 0x80000000) != 0;
  if (inDebugMenu)
  {
    if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
      keyboardState |= uint32_t(GamePadButton::DPad_Up);
    if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S'))
      keyboardState |= uint32_t(GamePadButton::DPad_Down);
    if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
      keyboardState |= uint32_t(GamePadButton::DPad_Left);
    if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
      keyboardState |= uint32_t(GamePadButton::DPad_Right);
    if (GetAsyncKeyState(VK_RETURN) || GetAsyncKeyState('F'))
      keyboardState |= uint32_t(GamePadButton::A);
    if (GetAsyncKeyState(VK_ESCAPE) || GetAsyncKeyState(VK_BACK))
      keyboardState |= uint32_t(GamePadButton::B);
    if (GetAsyncKeyState(VK_DELETE) || GetAsyncKeyState('Q'))
      keyboardState |= uint32_t(GamePadButton::LB);
    if (GetAsyncKeyState(VK_NEXT) || GetAsyncKeyState('E')) // pagedown
      keyboardState |= uint32_t(GamePadButton::RB);
  }

  if (keyboardState != PrevKeyboardState)
  {
    PadButtonStates[0] |= keyboardState;

    // toolmenu funcs check [4], [3] & [1] for some reason
    PadButtonStates[4] = PadButtonStates[3] = PadButtonStates[1] = PadButtonStates[0];

    PrevKeyboardState = keyboardState;
  }

  // Check for LS + LT buttons
  // (make sure they're the only ones pressed - if player opens a UI at same time it'll likely cause a hang...)
  bool isOnlyDebugComboPressed = PadButtonStates[0] == (uint32_t(GamePadButton::LT) | uint32_t(GamePadButton::LS));
  if (isOnlyDebugComboPressed)
  {
    // Only run DbMenuExec if debug menu isn't open already
    if (!inDebugMenu)
      DbMenuExec();
  }

  GameTask_callee_Orig(a1);
}

// restore code that loads dbgfont.tga texture
// 0x6DB765 into debug EXE
// DbgFont var doesn't seem to be anywhere in non-dbg EXE, so we'll define our own here
// the dbg EXE includes code in titleExit to unload DbgFont (at 0x6DD944), but we probably don't need to bother with it
void* DbgFont = nullptr;
typedef void* (__cdecl* GXLoadImage_Fn)(const char* path);
GXLoadImage_Fn GXLoadImage = nullptr;

typedef void* (__cdecl* titleInit_Fn)(void* a1);
titleInit_Fn titleInit_Orig = nullptr;
void* __cdecl titleInit_Hook(void* a1)
{
  void* ret = titleInit_Orig(a1);

  DbgFont = GXLoadImage("sv\\dbgfont.tga");

  return ret;
}

// restore screen-display part of eprintf
// calls into some GX-layer related function, luckily that func was left (unused) in the final EXE, seems to work fine
// 0x6DDC30 into debug EXE
typedef void(__cdecl* GX_ScreenDisp_Fn)(void* a1, float a2, float a3, float a4, float a5, float a6, float a7, float a8, float a9, int a10);
GX_ScreenDisp_Fn GX_ScreenDisp = nullptr;
void __cdecl eprintf_ScreenDisp(const char* str, float x, float y, int color)
{
  int length = strlen(str);

  double v7 = 0.9900000095367432;
  double v8 = 0.1428571492433548;
  double v9 = 0.0625;
  for (int i = 0; i < length; i++)
  {
    char ch = str[i] - 0x20;
    if ((uint8_t)ch > 0x61)
      continue;

    float v21 = (float)(ch / 0x10);
    float v15 = (float)(ch & 0xF);

    float v18 = v15 * v9;
    float v17 = v21 * v8;
    float v16 = (v15 + v7) * v9;
    float v20 = (v21 + v7) * v8;

    GX_ScreenDisp(DbgFont, x + (i * 8), y, 12.0, 18.0, v18, v17, v16, v20, color);
  }
}

// 0x6B1D70 into debug EXE
// (this reimplements the eprintf func due to the va_args stuff...)
int* DbgFontColorArray = nullptr;
char eprintf_buffer[0x80];
void eprintf_Hook(int a1, int a2, int a3, int a4, char* Format, ...)
{
  va_list va;
  va_start(va, Format);

  vsprintf_s(eprintf_buffer, Format, va);

  eprintf_ScreenDisp(eprintf_buffer, (float)a1, (float)(a2 + 64), DbgFontColorArray[a3]);
}

// Hook FlagEdit so only new button presses are detected
uint32_t* FlagEdit_PadButtonState = nullptr;
uint32_t PrevButtons = 0;

typedef void(__cdecl* FlagEdit_main_Fn)(void* a1);
FlagEdit_main_Fn FlagEdit_main_Orig = nullptr;
void FlagEdit_main_Hook(void* a1)
{
  uint32_t curButtons = *FlagEdit_PadButtonState;
  *FlagEdit_PadButtonState = 0;

  if (PrevButtons != curButtons)
    *FlagEdit_PadButtonState = curButtons;

  FlagEdit_main_Orig(a1);

  PrevButtons = curButtons;
  *FlagEdit_PadButtonState = curButtons;
}

// hook bzero inside WinMain
// that bzero clears debug flags part of pG for some reason, the debug EXE doesn't seem to have it
// (the call to bzero can't be nopped since re4_tweaks seems to use the call as part of a signature for something)
void bzero_hook(void* addr, uint32_t size)
{
  // nop
}

// Add code to read debug/roominfo.dat file into roomInfoAddr variable
// (debug EXE is missing this code, which stops AREA JUMP from working on that!)
// unfortunately the roominfo.dat provided with RE4 steam is missing the strings for some reason
// however, roominfo.gc contains the exact strings needed, even at the correct offsets etc!
// that file is endian-swapped though so can't be used directly...
// but the strings can be easily copied over by copying 0x2984-EOF over to roominfo.dat :)

// this hook can be removed if roominfo.dat is built into the DLL instead, just need to write roomInfoAddr to point to the data for the file
// would probably be better than asking users to overwrite their data files too
typedef uint32_t(__cdecl* DvdReadN_Fn)(const char* a1, int a2, int a3, int a4, int a5, __int16 a6);
typedef int(__fastcall* cDvd__ReadCheck_Fn)(void* thisptr, void* unused, uint32_t a2, void* a3, void* a4, void* a5);
DvdReadN_Fn DvdReadN = nullptr;
cDvd__ReadCheck_Fn cDvd__ReadCheck = nullptr;
void* cDvd = nullptr;
uint32_t* roomInfoAddr = nullptr; // name from RE4 GC

typedef void(*systemRestartInit_Fn)();
systemRestartInit_Fn systemRestartInit_Orig = nullptr;
void systemRestartInit_Hook()
{
  systemRestartInit_Orig();

  uint32_t handle = DvdReadN("debug/roomInfo.dat", 0, 0, 0, 0, 5);
  if (cDvd__ReadCheck(cDvd, 0, handle, 0, 0, roomInfoAddr) < 0)
    *roomInfoAddr = 0;
}

// Hook MenuTask (task for tool-menu), since it seems the menu can sometimes be shown without the pG+0x60 flag being set, eg. when backing out of area-jump menu
// (which could make game hang if this causes us to try opening tool-menu when it's already open...)
typedef void(*MenuTask_Fn)();
MenuTask_Fn MenuTask_Orig = nullptr;
void MenuTask_Hook()
{
  uint8_t* pG = *(uint8_t**)pG_ptr;
  *(uint32_t*)(pG + 0x60) |= 0x80000000;

  MenuTask_Orig();
}

// Reimplement some tool-menu entries

// ToolMenu_EntryEnd lets us cleanly return from the entry call, without this game would hang :(
typedef void(*FlagEdit_die_Fn)();
FlagEdit_die_Fn FlagEdit_die = nullptr;
uint32_t* FlagEdit_Backup_pG = nullptr;
void ToolMenu_EntryEnd()
{
  uint8_t* pG = *(uint8_t**)pG_ptr;

  // Exit tool-menu state via FlagEdit_die
  // FlagEdit_die overwrites pG+0x170 with contents of 0xC6D008, so we need to write that first...
  *FlagEdit_Backup_pG = *(uint32_t*)(pG + 0x170);
  FlagEdit_die();

  // alternatively "TaskChain(MenuTask, 0);" should return us to tool-menu
  // but that requires another funcptr to track...
}

void ToolMenu_GoldMax()
{
  uint8_t* pG = *(uint8_t**)pG_ptr;
  *(uint32_t*)(pG + 0x4FA8) = 99999999;

  ToolMenu_EntryEnd();
}

void ToolMenu_SecretOpen()
{
  uint8_t* pSys = *(uint8_t**)pSys_ptr;
  uint32_t flag = *(uint32_t*)(pSys + 4);
  flag |= 0x80000000; // debug exe ORs these seperately, probably part of an enum or something
  flag |= 0x40000000;
  flag |= 0x20000000;
  flag |= 0x10000000;
  flag |= 0x8000000;
  flag |= 0x4000000;
  flag |= 0x2000000;
  flag |= 0x1000000;
  flag |= 0x800000;
  flag |= 0x400000;
  flag |= 0x200000;
  flag |= 0x100000;
  flag |= 0x80000;
  flag |= 0x40000;
  flag |= 0x20000;
  flag |= 0x10000;
  *(uint32_t*)(pSys + 4) = flag;

  ToolMenu_EntryEnd();
}

void ToolMenu_MercenariesAllOpen()
{
  uint8_t* pSys = *(uint8_t**)pSys_ptr;
  uint32_t flag = *(uint32_t*)(pSys + 4);
  flag |= 0x80000000;
  flag |= 0x8000000;
  flag |= 0x4000000;
  flag |= 0x2000000;
  *(uint32_t*)(pSys + 4) = flag;

  ToolMenu_EntryEnd();
}

const char* ToolMenu_ToggleHUDName = "TOGGLE HUD";
uint32_t* pFlags_DISP = nullptr;
void ToolMenu_ToggleHUD()
{
  *pFlags_DISP ^= 0x10000; // DPF_COCKPIT

  ToolMenu_EntryEnd();
}

void Plugin_Attach()
{
  GameModule = GetModuleHandleA(nullptr);
  GameAddress = reinterpret_cast<uintptr_t>(GameModule);

  pG_ptr = GameAddress + 0x806F3C;
  pSys_ptr = GameAddress + 0x806F40;

  GameTask_callee_Orig = (GameTask_callee_Fn)(GameAddress + 0xA844);
  DbMenuExec = (DbMenuExec_Fn)(GameAddress + 0x1A83E0);
  GXLoadImage = (GXLoadImage_Fn)(GameAddress + 0x53D3D0);
  GX_ScreenDisp = (GX_ScreenDisp_Fn)(GameAddress + 0x558880);
  DbgFontColorArray = (int*)(GameAddress + 0x8129F8);
  PadButtonStates = (uint32_t*)(GameAddress + 0x86301C);
  FlagEdit_PadButtonState = (uint32_t*)(GameAddress + 0x863028);
  FlagEdit_Backup_pG = (uint32_t*)(GameAddress + 0x86D008);
  DvdReadN = (DvdReadN_Fn)(GameAddress + 0x1ACBD0);
  cDvd__ReadCheck = (cDvd__ReadCheck_Fn)(GameAddress + 0x1AC550);
  cDvd = (void*)(GameAddress + 0x853118);
  roomInfoAddr = (uint32_t*)(GameAddress + 0x863A1C);
  FlagEdit_die = (FlagEdit_die_Fn)(GameAddress + 0x2D19D0);
  pFlags_DISP = (uint32_t*)(GameAddress + 0x85A7B8);

  // hook GameTask_callee to call our gameDebug recreation
  PatchCall((void*)(GameAddress + 0x23EA51), (void*)&gameDebug_recreation);

  // Remove bzero call that clears debug flags every frame for some reason
  // (seems this breaks some signature that re4_tweaks is looking for though - so patch it to call a nullsub instead of nopping)
  PatchCall((void*)(GameAddress + 0x254B6A), (void*)&bzero_hook);

  MH_Initialize();

  MH_CreateHook((LPVOID)(GameAddress + 0x1A8330), MenuTask_Hook, (LPVOID*)&MenuTask_Orig);

  MH_CreateHook((LPVOID)(GameAddress + 0x253680), systemRestartInit_Hook, (LPVOID*)&systemRestartInit_Orig);

  MH_CreateHook((LPVOID)(GameAddress + 0x2AF870), eprintf_Hook, NULL);
  MH_CreateHook((LPVOID)(GameAddress + 0x2D5A00), titleInit_Hook, (LPVOID*)&titleInit_Orig);

  // Hook FlagEdit so we can slow it down by only exposing buttons when the button state actually changes
  MH_CreateHook((LPVOID)(GameAddress + 0x2D1A90), FlagEdit_main_Hook, (LPVOID*)&FlagEdit_main_Orig);

  MH_EnableHook(MH_ALL_HOOKS);

  // Allow tool-menu selection with X / A
  SafeWrite(GameAddress + 0x1A8016 + 6, uint32_t(GamePadButton::X) | uint32_t(GamePadButton::A));
  SafeWrite(GameAddress + 0x1A7FE9 + 6, uint32_t(GamePadButton::Back) | uint32_t(GamePadButton::B)); // Change exit button

  // Allow flag toggle with X / A
  SafeWrite(GameAddress + 0x2D1D80 + 6, uint32_t(GamePadButton::X) | uint32_t(GamePadButton::A));
  SafeWrite(GameAddress + 0x2D1E21 + 6, uint32_t(GamePadButton::B) | uint32_t(GamePadButton::Back)); // Change exit button

  // Allow area jump with X / A / Start
  SafeWrite(GameAddress + 0x2AFFE4 + 6, uint32_t(GamePadButton::X) | uint32_t(GamePadButton::A) | uint32_t(GamePadButton::Start));
  SafeWrite(GameAddress + 0x2AFFF3 + 6, uint32_t(GamePadButton::B) | uint32_t(GamePadButton::Back)); // Change exit button

  // FlagEdit displays flags in wrong order, each 16-bits is displayed on the wrong line
  // (to be expected from a port from a big-endian machine like GC/Wii)
  // it reads flags in as 16-bit words, and then seems to have code to handle swapping the bits inside
  // since the flags are actually 32-bits, it reads the wrong part of that 32-bit dword
  // we can fix that by a simple xor though :)

  // very fortunately for us there's a useless instruction just before flag-reading code
  // patch it to "mov eax, edi; xor edi, 1; nop", to swap which part of 32-bit dword to read from
  uint8_t patchBytes[] = { 0x89, 0xf8, 0x83, 0xf0, 0x01, 0x90 };
  SafeWrite(GameAddress + 0x2D1C7A, patchBytes, 6);
  SafeWrite(GameAddress + 0x2D1C86 + 3, uint8_t(0x41)); // patch read code to use eax register instead of edi
  SafeWrite(GameAddress + 0x2D1D19 + 2, uint8_t(0x5B)); // patch loop to jump to start of our patched code

  // Fixes for off-screen FlagEdit text
  SafeWrite(GameAddress + 0x2D1DCF + 1, uint8_t(13)); // reposition FlagEdit category label
  SafeWrite(GameAddress + 0x2D1DE8 + 1, uint8_t(13 + 13)); // reposition FlagEdit flag idx
  SafeWrite(GameAddress + 0x2D1E12 + 1, uint8_t(13 + 13)); // reposition FlagEdit flag name
  SafeWrite(GameAddress + 0x2D1CE8 + 3, uint8_t(3)); // reposition FlagEdit flag display
  SafeWrite(GameAddress + 0x2D1D4E + 3, uint8_t(3)); // reposition FlagEdit current-flag display

  // Allow RoomJump to access stage 0 (test stages)
  SafeWrite(GameAddress + 0x2AFE89, uint8_t(0x7C)); // JLE -> JL

  struct ToolMenuEntry
  {
    const char* Name;
    uint32_t Unk4;
    void* FuncPtr;
    uint32_t UnkC;
  };

  ToolMenuEntry* toolMenuEntries = (ToolMenuEntry*)(GameAddress + 0x7FC260);

  // Overwrite tool-menu funcptrs with our replacements
  toolMenuEntries[1].FuncPtr = &ToolMenu_GoldMax;
  toolMenuEntries[15].FuncPtr = &ToolMenu_SecretOpen;
  toolMenuEntries[17].FuncPtr = nullptr; // "DEBUG OPTION" entry points to nullsub which hangs game, null it out to prevent that
  toolMenuEntries[29].FuncPtr = &ToolMenu_MercenariesAllOpen;

  // Replace non-functional tool-menu entries with our own
  toolMenuEntries[2].Name = ToolMenu_ToggleHUDName;
  toolMenuEntries[2].FuncPtr = &ToolMenu_ToggleHUD;
}

With that, just press LT+LS when ingame, and the tool menu should display:
05_11_21_22_34_02_bio4

Seems to only work with controller, pressing X selects an option, apparently the debug EXE would let you access this by pressing LS+LT (which I think would set the byte I mentioned above)

Not sure if you'd want to include this in your DLL or not, since most of it seems non-functional atm (FLAG EDIT is the only thing I've seen have any effect, even then it seems kinda buggy though, 60FPS makes it run too fast to edit properly I guess)

Still figured it was worth posting about - maybe some more comparing with the debug EXE could get some of the options working.

E: updated with hooks that should let the LT+LS button-combo to open this work

E2: improved the eprintf fixes a little, and updated with some fixes for FLAG EDIT menu, inputs to it should be slowed down a lot now, and it'll now actually display the flags in correct order (E: and should now stop drawing text off-screen)

Quite a lot of interesting things in that menu:
06_11_21_08_27_38_bio4

E3: fixed the AREA JUMP option too, previously would crash when selecting it (even on the debug EXE!), seems game was just missing code to read in the debug/roominfo.dat file.

Sadly the roominfo.dat in the steam release is missing all the strings for this option, but some reason the steam version does include a roominfo.gc file which does have the strings.

Looking at the two files it seems roominfo.dat is mostly just an endian-swapped version of roominfo.gc, all the offsets for stuff are the same, so strings can just be copied over by copying 0x2984-EOF over to roominfo.dat 😄
(for everyones convenience: roominfo.zip)

(roominfo.dat does have some sections nulled out compared to roominfo.gc though, not sure what's up with that...)

E4: managed to merge/endian-swap the missing GC sections into roominfo.dat too, seems to mostly be test rooms, and night maps: roominfo_merged.zip
(some of the test/E3 maps actually load up too! never saw those documented before, at least TCRF doesn't mention them - not every map loads in though, wonder if the debug depot has the files for them?)

Also reimplemented 3 of the tool-menu options, and stopped DEBUG OPTION entry from hanging the game.

Maybe could replace some of the other options with simple flag toggles instead, to save people needing to navigate to FLAG EDIT, could probably add some cheats like infinite health etc. (E: added "TOGGLE HUD" option to try this out, seems to work well, not sure how many of the FLAG EDIT flags might be useful to add here though - non-debug EXE seems to ignore a lot of them...)

Add FixQTE under 60 FPS fixes

Hi and thanks for the latest release :)

Just a minor nitpick/question, but would it make sense to add the FixQTE together with the other 60FPSFixes? So there is only one option, and not two? Let me know what you think.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.