BASeTris has been upgraded to .NET 8

March 31, 2024 - .NET, C#, Programming

BASeTris, my Block-Puzzle Clone game, is still on .NET Framework 4.8. I tried upgrading things a few weeks ago, but had more trouble than I anticipated- I’d already converted the dependency projects, BASeScores and Elementizer, to .NET Standard, so I anticipated the conversion would be fairly easy. After all, the libraries I was using- OpenTK and SkiaSharp, had new versions that were compatible with .NET Core and newer .NET Versions.

When I attempted to do the conversion last week, I encountered issues revolving around the XInput Wrapper package I was using. I went to the github and effectively added the source directly to my project, but that didn’t work; there were a bunch of changes made to the library. I gave up at  that point as I wasn’t expecting that level of issue.

When  I revisited it yesterday, I effectively copied the BASeTris Project to a new BASeTrisCore project, so I could have the “old” copy for reference to compare. For the XInput Wrapper, I decided to find out what revision of the source the old package I was using was from, and instead put that into the BASeTris project directly. From my review of the new version it seemed in addition to refactoring the project repeatedly and changing names of things, some aspects like vibration/force feedback were no longer available. That actually resolved that issue.

I still had many compile errors, Mostly they were revolving around OpenTK changes as well as Ionic.Zip, which I was using previously, no longer being available. I ported over the applicable parts of the code to use the built-in Zip features in the BCL. I then went through and altered some of the names; The OpenTK Key enum had been moved to another namespace and it was called Keys, which conflicted with the enum from Windows Forms. Since the code in question was shared between both the OpenTK implementation as well as the SkiaSharp/OpenGL implementation, it had to work for both. I addressed this with an appropriate using to use it as TKKey instead, so that I didn’t have to resolve ambiguity by specifying OpenTK.Windowing.GraphicsLibraryFramework.Keys; every time it was referenced.

There were some event changes and alterations to how OpenTK worked, so I worked through those as well. I got it compiling and ran it.

The first issue I encountered when I ran the program was that it was trying to load 32-bit BASS dlls for the sound and it was running as a 64-bit process. I replaced the files with the 64-bit versions of those DLL files and it ran just fine beyond that point.

Now, however, the display was blank. For some reason, the code wasn’t able to create an SKSurface correctly, and kept getting null. I eventually referred to current example documentation for SkiaSharp and GL surfaces, and by using the example I copied the use of 2 samples and 8 stencil bits and that got it able to create a Surface. since there was no actual error I don’t actually know why it failed, and therefore also am not really sure why this change fixed it.

Now, though, I found it had issues in-game. The playfield was cut off about a half block and the status area was stretched. I had trouble figuring this out but eventually discovered it was actually my fault in the changes I had to make for OpenTK. I actually found this through code comparisons once I was able to isolate where things were going south. I’ve got a method to determine the size of the main area and the status bar based on the window size, and for some dumb reason the parameter order is Height then Width. OpenTK changed stuff so ClientSize was Vector with X and Y, so I had to convert that, and during conversion I had autopiloted X,Y into the parameters when converting one of the calls to the method.

Finally, everything seemed to be working- except that some state transitions would freeze the display, mem usage would spike, and they would seem to get “stuck” for quite a long time. This also took some digging to discover but this was the result of a SkiaSharp change/optimization. For mutable bitmaps, it now delegated to DrawImage, converting the SKBitmap to an SKImage. This caused the problem because these transitions were for example drawing large numbers of “blocks” of the new state image onto the old state image; so every call was converting the full state bitmap into an image, thus the memory spike and the performance problem. I was able to address this by having the affected states instead convert the Bitmap to an SKImage themselves before they perform their drawing loop, and use DrawImage instead, which got those fixed.

And everything seems to be working now, all converted over to .NET 8. I’ve replaced the Framework based BASeTris project and made the conversion commit to the main repository. I expect I may need to review my CI Server setup as well as the installers as I would be surprised if those managed to work as-is; the CI might work, but the installer script won’t be looking in the right locations anymore for the output files.

Have something to say about this post? Comment!

Leave a Reply

Your email address will not be published. Required fields are marked *