Sitemap

HoloCure Android notes

9 min readApr 4, 2024

--

Press enter or click to view image in full size

For a while now I have been meaning to write up some notes on how I did light modding for HoloCure to run on Android, as the project was a lot more popular than I expected, and additionally I may want to hand this over to someone else. While not a developer myself, I have heard many a time that documentation of a project can be the most tedious part. And, yet I can still resonate with this very slightly, namely in that these notes were meant to be written June 2022, but were instead relegated to the dustbin in favour of quite a few hours of Destiny 2 (sorry). Regardless, documentation is still the best practice for numerous reasons people in more qualified positions than I can give you reasons for, so I thought it might be prudent to push through with this “documentation” (read: rant) while I still have the willpower. (If you want straight forward instructions, I should have a different post on these).

Background
Back in June 2022, when I still watched HoloEN often, HoloCure was released and was a trailblazer as it was the first VTuber game that truely broke through into the international sphere, with multiple talents playing it after release, and even a whole subreddit dedicated to it (r/HoloCure, at over 30K followers at the time of writing). Now, don’t quote me on this, but I believe from my personal experience and talking with some vTuber fans that a good number of fans didn’t have full PCs, and I myself was randomly interested to see if I could get this game to work on mobile. What I didn’t envision however, was the amount of time and effort I had to put in — not too much but still much more than I expected.

GameMaker Studio 2
GameMaker Studio 2 is a game engine used by many (and as I hear, including many educational instutitions for teaching), and produces finished games in two forms, a compiled down form where all scripts and logic are compiled to native code, while the VM method (luckily used by HoloCure) uses a single “virtual machine” style binary (one unique binary for each platform, same binary for each game) to interpret a large .data file containing all assets and scripts, at the expense of slowdown. This VM binary importantly does not differ in implementation detail from platform to platform, with the idea being that this makes it easier for developers to develop cross-platform. According to MrPowerGamerBr, it is then theoretically possible to grab the .data file and stuff it into another platform along with the correct VM binary for that platform.
This was a good concept, until I realised that the .apk that MrPowerGamer provided unfortunately did not correspond to the correct version of the VM binary and would hence error out if I simply stuffed the binary inside. To alleviate this I needed to obtain a copy of GMS2 with the correct build tools, at the time paid, and luckily the lovely “GmsFtw” on cracked.io was able to provide a long list of instructions that allowed me to obtain the latest version by alternative methods (with a lot of time and .NET binary inspection tools, and to this day I still stand in awe of those willing to scrape through 100+ shared libraries to locate 20+ randomly named protection functions, often in the most obscure places possible). From then, I created a new Android project, and after more wrangling with Android Studio SDK installations, managed to create a “blank” .apk and insert the .data file (renamed to game.droid for some reason) with aapt (and align and sign etc.). This produced a game that would at least boot to the main screen on Android.

0.3
My first task afterwards was to get some controls working. I took the approach of MrPowerGamerBr in using a overlay app that showed buttons, that would simulate keyboard presses, easily downloadable from the Play Store. However, I found that the program would not respond to certain keys pressed (when I bound them on the overlay app), such as Esc and Ctrl. Using the handy modding tool UndertaleModTool, I solved this by changing some of the variables in the initialisation script of the “InputManager” object which, as its name suggests, controlled all the input events for the program (scripts are written in GML, similar to C# but with extremely lax syntax?).

Each number is the ascii value of a lowercase letter/key

I experimented to see which keys would work by checking the adb logcat of my device, which showed the debug logs for the application, and more importantly any key-down events that the program actually registered and what key they registered as. In the end, I found that Tab, Enter and Space were the only special keys that the program would register, and changed the above variables to some of them, and the overlay app bindings accordingly.
After putting the program out, there was a strange problem in that people running phones with Android 10 and above would error out (similar to me before), and u/CasualRangga did the heavy lifting of troubleshooting for me and found that it was for some reason due to targeting Android SDK 29 and above when building the blank .apk, easily solved by targeting 28 (still with the SDK 31 build tools, newest at the time). My biggest gripe with my “port” however was performance, and I looked at the code for a week to see if I could remove extra parts that were not required to run on Android. Unfortunately, most likely due to my inexperience, I could not find anything to optimise, and to this day the game still lags majorly further through the game.

0.4
Version 0.4 was more or less the same procedure, however around the time of release I decided that I had a lot of free time and wanted to try adding full touch control. I initially thought this would solely comprise of adding touch interactivity to each button, which it more or less did, but I greatly underestimated the time it would take to do so, and spent about ~10 hours purely planning and another ~20 hours implementing the changes. Even before this, I thought I would try to steal the touch button’s from MilesTheCreator’s Deltarune port as they looked fabulous, but I was not able to make them work within ~7–8 hours, and so I simply gave up and carried on with the original plan.

A small fraction of the sticky notes I wrote over the week.

In then end, I managed to break my task into a large list of “buttons”, which I then implemented as a large bit of code attached to the Gesture_64 event (a click, or on mobile, a touch):

Press enter or click to view image in full size
To this day I think this is my longest file of code, at 474 lines (I blame object oriented for not being able to write massive files) of basically if/else and switch. If you had asked me about optimising with hash maps or something else at the time, I would have probably just died on the spot.

There were also a couple issues with how the game window was drawn and resized up to fit the actual screen size, but as these are standard practice with most games, these issues were easily identified and fixed. I also had a couple problems with the modding software for decompiling and recompiling scripts, which I foolishly did not submit issues for, but instead just resorted to modifying the assembly code (good rundown here) and attempting not to touch any conditionals for fear of having to renumber half the labels in a script. [As a result, I now believe myself to be full qualified in the art of “abusing” the “bool is a subclass of int” nature of languages to turn conditionals into some stupid looking single-lines.]

Case and point: as GML asm has labels per short chunk of code, if I wanted to remove this conditional (bf [82]), I would have to modify all labels 1–82, giving myself a headache in the process considering I may have had to do this lots of times.
On an unrelated note, I had to copy this assembly chunk so many times as it would refuse to compile as code.

To top it all off, I ended up only sending this version to a couple of people for the intent of “beta testing”, with the idea that I would make some modifications, however I again randomly forgot that I would do that and ended up not doing any correction work, or even releasing this version to the general public. Oh well — at least for me, the moral of the story is to properly plan next time.

Get asda488’s stories in your inbox

Join Medium for free to get updates from this writer.

0.5, 0.6
Version 0.5 was again straight foward, with the only issue being me accidentally deleting Android Studio, building with a funny distribution of Java I found somewhere and then accidentally targeting SDK 31 (again), also quickly solved by reading my own comment that I had left in case this happened (again).

Version 0.6 was a bit more interesting however. When I opened the data.win file in UMT, I noticed that the binary version had changed, which meant I had to grab another more up to date version of GameMaker. Unfortunately, YoYo had switched about some of their UI code, so a good amount of the checks had shifted and I could not get the UI to work with the previous instructions. Thankfully however, the checks for the runtime build tools had kept roughly the same, which meant these worked but I would have to compile the blank .apk from the command line (this is now a non-issue, as it is now free!). Additionally, the developers had switched to a custom input library, Input 6.0.

This was both a blessing and a boon for me — it was a boon as it meant that I could not apply the touch screen patches from the 0.4 experimental release to it, which I was thinking about doing. However it was a blessing as some touch controls such as buttons were extremely simple to “activate” by changing a macro variable INPUT_TOUCHSCREEN_USES_MOUSE_SOURCE (defined in the package initalisation and referenced in the code in a few different places) to True from False, (referencing the source of the library, thankfully on GitHub, because the GML compiler apparently has a preprocessor and changed all instances of the variable to “False” or “0” in the actual code, strangely with minimal optimisation).

There was another bug caught by some Reddit users, and funnily enough I did not cause it this time. When launching the game offline, the Google Firebase integration polled the server for some information, and naturally this would cause an error, which would be ordinarily caught. However, for some reason the return type of the poll had changed, and the error handling function expected a list containing a string rather than what was actually returned, which was just a string.

The stuff that has stayed the same is in black, the few lines I added are in red

Thankfully also the integration had a GitHub page which I could submit a pull request to, so I did that, and surprisingly my pull request got accepted (and refactored), which was a surprising as this was such a large bug (to me at least) that I thought the extension maintainers would have had this reported/patched for next release.

Press enter or click to view image in full size
One of my first PRs!

Finally, I added a save coins on quit functionality, which I believe is the first additional feature I have added to the game (which means I only technically started modding then?).

Press enter or click to view image in full size
The script did not decompile so I added this long chunk of assembly, which looks intimidating but I believe is only a few lines of GML.

Future work
With the release of HoloxBreak, and the general consensus that HoloCure would wrap up soon, I am considering getting the full touch controls finally done, and the addition of a save file to clipboard importer/exporter (and perhaps a website for save editing to hone my non-existent HTML skills), and any other QoL changes that may come my way. While I haven’t played HoloxBreak yet, it appears to be a bit more resource intensive than HoloCure, so I’m not too sure how well it would run on mobile, but it’s definitely on a backlog somewhere, as I look to having hopefully more free time over April/May.
While I’m here, I would again like to thank the UMT team for development of their tool, as well as MrPowerGamerBr for the initial method, both which this port would not be able to exist without and once again Kay Yu and talented team for making this wonderful game in the first place — thank you!

Videos
As an addendum, apparently people have been using my port and even uploading videos to Youtube, which is simply amazing, and I’ll just share a couple of the videos (if you own these and don’t want them displayed, please message me and apologies in advance).
https://www.youtube.com/watch?v=9DRpI-ujpqQ
https://www.youtube.com/watch?v=1jlQGE-qQ3A
https://www.youtube.com/watch?v=2qCo7lqUJb8
Again, I am truly honored to be a part of this community, and thank you all so much for all the support!

--

--