November 23, 2016

The Method Rewrite Post

While I was taking my Uber back from the Postmodern Jukebox concert, I figured out how I was going to "fix" Terraria and allow myself to release an update for RomTerraria at the same time: I'm going to rewrite the method that is introducing the issue.

I've patched bugs in the base game before. For the longest time, if you didn't have a My Games/Terraria folder in your Documents folder, the game would crash when trying to create the settings file.  I patched that with the original releases of RomTerraria.

Fortunately, I've got a good place to handle injecting my replacement method.  LiquidRenderer.PrepareDraw just calls the internal method.

I'm going to do this patch in two phases.

Phase one will be out tomorrow on Thanksgiving assuming nothing else blows up and will simply make PrepareDraw be a no-op.  This will allow everything else to work as is EXCEPT for the new water effects.

Phase two will take significantly longer.  I'm going to rewrite LiquidRenderer.InternalPrepareDraw.  It's a bit over 400 lines of, well, not good code.  I mean, it's dereferencing to memory before a pointer.  If I was going to be a total dick, I could craft a world file that could potentially turn into a native code exploit.  Fortunately, I'm not a total dick.  This will take me a lot longer to do and may end up moot if they fix the issue before my rewrite is done.

I've only got this weekend to do this, so here goes nothing.

Update 11/24/2016, 11:57am: Well, it's not going to happen this morning, but I am working on it...

Update 11/24/2016, 12:20pm: I've gotten the replacement class building as a standalone DLL.  I've got to do IL-patches to replace 14 instances of the class in six methods in two classes.  I'm going to try to get that done before I have to leave for my afternoon social obligation.

Update 11/24/2016, 4:38pm: I'm back from my social obligation and am resuming my coding.  I've almost got the replacement working.

Update 11/24/2016, 9:57pm: Stopping for the night.  I've got my replacement class patched in and am working on debugging, but I'm exhausted.  That said, making PrepareDraw a no-op has other side effects and isn't a good solution, so I'm dropping that part of the plan.

Update 11/25/2016, 12:18pm: Taking a lunch break.  Since I'm afraid I'm going to have to do this kind of thing again in the future, I've created a general purpose class replacement system. Will resume testing once I am fed.

Update 11/25/2016, 1:03pm: I'm now able to reproduce the crash inside my custom class inside the debugger.  Should help me fix it.

Update 11/25/2016, 1:09pm: Well, it's good that I made the class replacement system generic, because the crash is NOT caused by the code I suspected.  It appears that something else is running amok around memory.  Give me a bit of time to figure out the appropriate memory layout so I can figure out which object is immediately before this one in the heap.

Update 11/25/2016, 1:30pm: I've got a 1.2GB memory dump that I'm manually going through.  I'd be going faster, but the .NET memory tools require a minimum .NET version of 4.5 and Terraria is compiled to 4.0.

Update 11/25/2016, 2:25pm: Good news: managed to stop the game from crashing. Bad news: filled blocks of water aren't rendering.  Still going.

Update 11/25/2016, 3:53pm: I've checked my current code into Github.  Still trying to figure out why full blocks don't render.  Note that this doesn't truly fix the memory overwrite, but it leaves the old 160KB object around as a "safety buffer."  I'm going to try for another hour, then call it a day.  I've still got work to do around the house.

Update 11/25/2016, 5:51pm: Part of the problem is that the version of Telerik JustDecompile that I'm using doesn't properly decompile unsafe code evidently.  Testing a fix now.

Update 11/25/2016 6:00pm: Adding padding around the wave bank let me run with water effects for almost ten seconds before the game crashed in a spectacular fashion.  Looks like something is hardcoded with a max resolution and when you go above that resolution, it starts walking over memory it shouldn't.  Dinner shortly, then more research

Update 11/25/2016 6:09pm: Here's a test version.  This is not guaranteed to work, but appears to be working in my limited testing.  Please let me know if it crashes for you.

Update 12/6/2016 1:13pm: v1.3.4.4 was just released.  The test version was compiled and tested against v1.3.4.3, and may not work with v1.3.4.4.  I'm at work for several more hours.  Let me know if I need to address anything after the fix.

Update 12/19/2016 9:35pm: Added LAA support code.  Trying to fix an issue with rendering water that surfaced at certain resolutions for v1.3.4.4 before releasing an update.

Update 12/25/2016 3:58pm: Build for v1.3.4.4 here.  You'll have to set up your settings again.


Russell said...

Appreciate your efforts. Thanks for posting and keeping us in the loop.

Taylor youngreen said...


Unknown said...

Hey man, just wanted to say thanks.

Ace170780 said...

I tried to test it out this morning. Not sure what i'm missing but here are the Windows Events details. Crashes on Startup.




C:\Program Files (x86)\Steam\steamapps\common\Terraria\Terraria.exe





Application: Terraria.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException at System.Runtime.CompilerServices.RuntimeHelpers._PrepareMethod(System.IRuntimeMethodInfo, IntPtr*, Int32) at Terraria.Program.ForceJITOnAssembly(System.Reflection.Assembly) at Terraria.Program.ForceLoadThread(System.Object) at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()


Here is the screenshot of the error on crash

Michael Russell said...

Ace, did you copy over ReplacementLiquidRenderer.dll and RTHooks.dll?

Ace170780 said...

That did it. Was missing the ReplacementLiquid dll.

BlackPhoenix30 said...

Everything seems to work for me!
Thanks for all the work you put in to this mod!

filipe serpa said...
This comment has been removed by the author.
arrigo gianan said...

Just tried the test version and it seems that I cannot go above my normal resolution. Still 1366x768.

At first I thought it was something that had to be done manually so I changed the resolution in the config.json file but it still didn't work. I've also tried ticking the cooperative thing.

Michael Russell said...


If your monitor won't go above 1366x768, this mod will do nothing. This mod allows resolutions above 1920x1200 if you are on a monitor that will allow it (e.g. 2560x1440, 3840x2160).

Ryan D said...

I followed the instructions perfectly for the test version and I get "Please launch the game from your Steam client."

filipe serpa said...

So after creating a new world i kept getting low fps, tinkered with the water settings etc but no luck still low FPS. i'm running a pretty hefty PC so i know its not that but something is happening.

Nipun Wittayasooporn said...

Played for a couple of days and it's working great so far (at 2560x1440). Thank you for all your work.

@Ryan Try restarting steam. A lot of games and software that tries to detect steam doesn't work sometimes.

Ryan D said...

@Nipun Thanks! Now it works perfectly :) wish I woulda thought to do that haha..

VV3 said...

The tool cannot hook up with my Terraria (GOG).
Still says the usual "Unable to find Terraria."

Ran it once, executed the tool - no results.
Running it actively, executing the tool - no results.
Both in UAC mode - no results.

chevas said...
This comment has been removed by the author.
Ace170780 said...

Tested with and it seems to launch fine.

MasterFerret1 said...

I had to recopy over the files because updating it broke it, but after recopying it worksd fine.

Benjamin Van Het Bolscher said... Seems to be working. I noticed before though that the background gradient doesn't follow the player properly when moving upwards into space leaving a blank space at the bottom of the screen.

Taylor youngreen said...

it seems laggy. it wasn't laggy in previous versions. but it's only a test version so I'm not surprised. I turned down all the graphics settings and it didn't do much. I usually play at ultra settings without lag.

MasterFerret1 said...

I'm actually experiencing some heavy lag in some places, and some game crashes, as well as some system crashes that I think are associated with the game.

Russell said...

Still no working map in terraria using your fix. pressing tab or m does nothing except make a clicking noise

John Waldron said...

I notice as of the Terraria release, the game launches fine however the water isn't rendering correctly, which is understandable since it is only a test release. And areas where a lot of water is causes the game to crash under a render error (possibly from too many "blocks" not being visible and them overwriting each other?). But keep up the good work, I love this patcher/trainer as it has made my Terraria experiences quite enjoyable.

Jacob Sargent said...

Thank you so much!