emoose / OutRun2006Tweaks

Turning and spinning and spinning and turning, woah!
MIT License
21 stars 0 forks source link

[Feature Request] Texture dumping/injection #12

Closed DonelBueno closed 1 week ago

DonelBueno commented 2 weeks ago

This would solve a lot of problems at the same time:

As a bonust, it would also make it possible to mod the environmental textures for higher quality ones.

@emoose gave this feature a go at #7, said it lacked UI dumping capability and a cache for reducing/eliminating stutters.

emoose commented 2 weeks ago

Got a little further with UI, seems they just use a slightly different D3DXCreateTextureFromFileInMemory function to load in (as opposed to the D3DXCreateTextureFromFileInMemoryEx that I was modifying before)

Sadly seems UI textures are usually stored in a single texture file all next to each other as a large texture atlas, eg:

image

Once upscaled the game doesn't seem to have anything to handle texture resolution being different, and just tries loading the texture from whatever original position it was at before, making everything look pretty broken:

24-06-17_16-20-12-138_OR2006C2C

Hoping maybe the game keeps the X/Y/width/height of each texture in the atlas somewhere next to the texture itself, could probably just add some code to rescale those based on originalWidthHeight / newWidthHeight, haven't had any luck with it yet though :/ (in worst case, the game might be keeping those in the code, doing something like drawSprite(X, Y, width, height) whenever it wants to draw them - might still be possible to work something for that though...)

DonelBueno commented 2 weeks ago

Do you have a test build with dumping/injecting capabilities so I can test?

Hope you can solve the UI scaling issue.

emoose commented 2 weeks ago

Aha mostly have the texture atlas stuff figured out now:

24-06-18_00-20-10-707_OR2006C2C

24-06-18_00-20-24-655_OR2006C2C

24-06-18_01-40-38-221_OR2006C2C

Seems game used both ways of addressing individual textures, the texture file had x/y/width/height for each sprite inside, but code could also override those (and usually did...) There's also some alternate way which uses a matrix transform instead of x/y/width/height which I didn't really understand that well, but was able to get something working for it eventually.

Only issue I've noticed so far is pause menu textures break if they're upscaled, seems they do some weird thing with the x/y stuff to stretch those textures out which breaks it, not really sure why yet, haven't noticed anything else broken yet.

Code is still pretty messy for this, but should be fine to test out (E: v2 in next post): Outrun2006Tweaks-0.2.5-uiTextureReplace.zip (forgot to add in that zip, but 4gb patching the EXE can help it load bigger textures too)

With that DLL it'll write out UI textures into [game folder]\textures\dump\[texture-package-name]\ folder as they load in, and loads in any replacements from [game folder]\textures\load\ if they exist.

(UI textures only atm since we don't really need to worry about caching for those.. hopefully can get something working for stage textures soon)

Subfolders in \load\ should work if they match the original texture-package-name that was written into dump (eg. texture that was dumped to dump\spr_sprani_game_cvt_Exst\C4A2937B_1024x1024.dds can load in from either load\C4A2937B_1024x1024.dds or load\spr_sprani_game_cvt_Exst\C4A2937B_1024x1024.dds)

With AutoCrispy you can point it to the dump & load folders and it can upscale textures for you automatically as they dump in, pretty neat, not really sure what the best model to use is though, the one I tried turned some of the O2SP textures into soup...

24-06-18_01-41-29-976_OR2006C2C

emoose commented 2 weeks ago

Cleaned up code a little bit, found a slightly better way to handle looking up scaling amount, and seems that fixed the issue with pause menu textures 😸

New build here (includes 4GB patched exe): Outrun2006Tweaks-0.2.5-uiTextureReplace-v2.zip

E: here's a pack of some UI textures ran through ESRGAN, improves some of them but also makes some like O2SP arcade menus pretty ugly, hopefully someone that knows how to scale textures properly can look at it. https://pixeldrain.com/u/uxotusNQ

DonelBueno commented 2 weeks ago

Great work, bro, you rock!

I have some experience with ESRGAN, I'm gonna give it a try and compare with your results. Thanks!

EDIT: made a comparison between your textures and vanilla textures and yours are pretty decent, only the speedometer and the writing of some keys (e.g. ESC) need rework, the rest is great.

BTW, with your textures on the load folder, no textures were dumped at all. Can you make so it only dumps the textures you're not injecting? That's how most emulators work in this regard.

emoose commented 2 weeks ago

BTW, with your textures on the load folder, no textures were dumped at all. Can you make so it only dumps the texture you're not injecting? That's how most emulators work in this regard.

Hm that should be how it's doing it I think, if replacement exists inside load/ then it'll skip dumping it, but if no replacement exists then it'll save the original texture into dump/. ATM it's only loading/dumping UI textures, that pack probably replaces most of them already so it'd skip dumping them, if you remove some of the ones from load/ it should hopefully write original into dump/

DonelBueno commented 2 weeks ago

Oh, that makes sense, I thought it was supposed to dump environmental textures too.

Do the environmental textures cause stutters even on an SSD?

emoose commented 2 weeks ago

The stutter isn't really as bad as I thought, but with uncompressed textures it can dip a lot when going through loading zones, though recompressing to DXT5 (about 1/5th the size) does seem to help it a bit. I've only really tried it with SSD, imagine with HDD it would probably be even worse :/

Here's a build which can dump/replace them, INI has some options added under [Graphics] about whether to enable replacing/dumping: Outrun2006Tweaks-0.2.5-allTextureReplace.zip

Not really sure how much I'll be able to improve it though, it might end up better to just edit the game files instead for the scene textures, since games loader seems to handle loading them without stutter pretty well. There is https://www.mediafire.com/?pttdepqy6gd2zl2 tool which can extract some of them and seems to be able to repack, but haven't really tried it yet.

DonelBueno commented 2 weeks ago

Which upcaling model did you use with autocrispy?

Is it possible to implement a way to toggle between vanilla textures and inject ones on the fly during gameplay?

emoose commented 2 weeks ago

IIRC it was https://openmodeldb.info/models/4x-HDCube3 & the ESRGAN from https://github.com/WalkerMx/ESRGAN_Python_Embedded/releases/tag/v1.4

If you extract that esrgan into esrgan folder next to autocrispy, and put the HDCube model into esrgan\models\, they should show up in the selectors You might need to download texconv from https://github.com/Microsoft/DirectXTex/releases/latest/download/texconv.exe and put that next to autocrispy.exe too Folder layout for me was

\autocrispy.exe
\texconv.exe
\esrgan\esrgan.exe
\esrgan\models\4xHDcube3_500k.pth

After that you can go to autocrispy chaining menu, then pick TexConv from dropdown and change it to DDS input, press Add button, then pick ESRGAN and choose the model, Add, then pick TexConv again and set it to DDS Output with Force Dx9 checked & Add

This portable.xml might work too if you extract it next to autocrispy.exe (might need to edit the paths inside it though): portable.zip

If new textures are added into load during gameplay they should get loaded in whenever game tries to load the texture next, shouldn't have to restart or anything. (this is no longer the case, tweaks will cache a list of all the available textures on startup now so we don't have to check filesystem for every texture, so a game restart would be needed)

A toggle between the old & new would be neat, think the game does have some stuff that re-loads textures when D3D device loss happens, maybe could be repurposed somehow...

E: also after it's upscaled you can convert uncompressed to DXT5 with this batch script, it'll convert any dds in same folder and put them into a "new" folder.

@echo off
mkdir new
FOR %%i IN (*.dds) DO (
  "C:\path to\texconv.exe" -f DXT5 -nologo -dx9 "%%i" -o new
)

(think autocrispy might be able to do this itself too, but when I tried it just stopped doing anything some reason)

DonelBueno commented 2 weeks ago

I saw you created minimaps for the UI textures, even though the original ones don't have, since it doesn't make sense. Maybe you could save some size by removing them.

Good model, I didn't know it.

About DXT5 compression, if I remember correctly, DXT1 is better for textures with no alpha channel while DXT5 is better for textures with alpha channel. Did you try both algorithms?

emoose commented 2 weeks ago

Ah looks like texconv defaults to all mipmaps, -m 1 parameter should remove them, maybe can help reduce load time for the UI.

DXT1 seems supported by game, think I saw some textures were using DXT3 as well, haven't really done much texture work before though so not sure how to know which is best, looks like alpha does get used in a lot of textures though.

Had a look into adding caching too, tried copying how game does it by having a separate loading thread and making game skip drawing model till texture was done, but even that still gave stutter with uncompressed stage textures :/ Not sure if much could be done for those, will try checking HDD soon to see if this caching is even helping at all.

DonelBueno commented 1 week ago

Well, I'm going to close this one, thank you for all the hard work =)

The only thing missing is a better caching system, but the main work is done.