Compiling CSE2 Emscripten

Jun 25, 2021 at 2:00 AM
Junior Member
"Wow! The more I drink of this magical beverage, the more games I can play! Wheee!"
Join Date: Jun 18, 2021
Location: Earth, Mars, or somewhere in between...
Posts: 20
Disclaimer:
I can safely say that I know computer languages about as well as Cookie Monster knows vegetables, so there may be something obvious or stupid that I have neglected to understand. Please expect mistakes of newbie proportions.


If you are here to build this port for yourself and not hear me complain about my troubles, please scroll down. I've posted the solution below.


Over the past several months, I have been interested in modifying Cave Story, particularly CSE2. Thanks to the diligent work of the reverse-engineers, the engine’s source code is quite readable and relatively easy to modify (coming from me, that says something), and the engine (at least according to my observations) functions perfectly congruent to the original 2004 game, a sharp contrast to the NXEngine, where I have found many variations in NPC and game mechanics. Of course, due to RetroArch, the NXEngine has CSE2 beaten when it comes to ports.
I wish to take my completed mod and distribute it as widely as possible (port it to as many devices as I can, particularly iOS), and in my quest for portability, stumbled upon the emscripten port of Cave Story. Not much can be found about this port, other than several comments on the CSE2 main thread, the branch’s readme, and the small description on the showcase website, all of them stating the challenge of porting the game because of its lack of mainloop functions. I found this port interesting particularly because of its browser compatibility in that almost any device with an internet connection can play the game (even mobile devices, if they have an external keyboard).
After finding the emscripten engine, I spent some time figuring out how to build it. I followed the instructions in the readme.md file, though not without a few hitches. I first had to install the emSDK to use the “emcmake” command. The first issue I ran into related to cmake not finding the files it needed to continue:

emcmake cmake .. -DCMAKE_BUILD_TYPE=Release
I received an error along the lines of: no rule to make target (bin2h), needed by (Wave.dat.h).

I checked in the directory referenced by the error script, and found a file of the correct name, but it possessed an .exe extension. I deleted the extension from the file, and the compilation continued relatively uneventfully (though I had to move it to my root directory because my username has a space in it, and some of the cmake commands can’t handle that). In the end, I was presented with 3 files in the ‘game’ directory: CSE2.jar, CSE2.wasm, and CSE2.data. To implement them, I curl’ed the cave.html from Clownacy’s demo website, and uploaded the 4 files to my github.io page. The result did not work. (I also first tried launching the .html locally, but it returned to the console “blocked by CORS policy.”)

To further test things, I also pulled the 3 other files from the sonicsearch site and set them up in a different directory. This result did work.

Confused, I tried combinations of the home-compiled files and the ones from @Clownacy, though none of them worked. The CSE2.data file was the exact same size for both programs, so I did not test these. I don’t know why, but the CSE2.jar for the home compiled version was significantly smaller (about ½ the size) than its working counterpart. I also noticed that my version of this file was only 1 very long line, while the one I pulled from the demo site was much more readable. The CSE2.wasm binaries also varied slightly in size, with the one from the working demo being slightly larger.

I assumed it might have been some issue with VS2019’s environment being involved, so I created a fresh directory and attempted the same compilation directly from the cmd prompt. It produced a non-working set of files exactly the same as the others.

To be completely thorough, I attempted to compile the program in Linux (Ubuntu, to be specific). The compilation completed the emcmake sequence without the bin2h error much to my surprise, though when running
cmake --build . --config Release, it ran into an error at around 6%, where it assumed the SHELL-s command was a directory:

em++: error: SHELL:-s USE_SDL=2: No such file or directory ("SHELL:-s USE_SDL=2" was expected to be an input file, based on the commandline arguments provided)


Curious about the bin2h issue, I compared the one generated under Linux to the one under Windows. Linux version had both no .exe extension and it was actually smaller than the one made by windows, being about ⅕ the size. To test the impact the different files had on the result, I once again compiled under Windows, this time replacing the original bin2h file with the one made by Linux. The result, disappointingly, yielded 3 files congruent with my 1st attempt.

I also wanted to see if compiling under MSYS2 would have any effect, but, up to now, I have had lots of trouble setting up this environment in the first place.


[UPDATE]:
I tried to build this port with MacOS, and to my surprise, was the only operating system that was able to complete a build without any sort of error. (Actually, I had 1 error with linking the executable, and it was related to a space in the file folder directory, removing this eliminated the issue). Emscripten as well as all the other dependencies were straightforward to install with 'Brew', the MacOS 3rd party package manager.

I tried this port in the same manner as the other, and to my disappointment, it failed as well, due to the same error:
Uncaught ReferenceError: IDBFS is not defined


I traced the location in the CSE2.js file
(a real pain, since the thing is only 1 line long, which leads into my other revelation, that the Clownacy CSE2.js file is just spaced out for better user readability, though the Alula one is spaced in the same manner, leading me to believe that these were also compiler-generated, but what settings resulted in this?)
The function lines that seemed to be causing the error were as follows:

FS.mkdir("/offline"); FS.mount(IDBFS,{},"/offline");

A quick google search led me to this error report on Github.
It seems that IDBFS is no longer linked by default. [Odd this would be an unaddressed issue since the last push to Github was made in late 2020, and this emscripten update was made 1 year prior, unless an outdated environment was used to build the branch.]

Another side note: Sifting through the Github changelogs leads me to infer that the port was originally built on Arch linux.

~~~~~~~~~~~~
The big question:

Has anyone else been successful in producing the emscripten port? (I assume at least 1 person has, hence the demo site) If so, what settings/environment was used for this endeavor?


The big Answer:
I have! Pick me!


All joking aside, though. I really HAVE figured this interesting port out.

It turns out, I was right. The cmake file WAS indeed deprecated, but the Makefile.emscripten wasn't.
Contrary to what the Readme says, the only way to correctly compile this port is with Make.
(cmake neglected to include -lidbfs.js, the utility essential for storing the offline save files in your browser, as well as produce a less eye-friendly CSE2.js script)


You DO need to install 2 dependencies, however.
The emscripten SDK and pkg-config


On MacOS, this process is very simple with Brew:
just use the following commands:

brew install emscripten
then type
brew install pkg-config



On Ubuntu, the process is a tad bit more challenging.

pkg-config can be installed with APT:
sudo apt-get install pkg-config

BUT the emscripten SDK cannot.
The version of emscripten stored on Ubuntu's website is too old to properly build this port, so it will have to be obtained from the source.
I used the process described here. It was the quickest and most hassle-free way of installing emscripten.
Personally, I had to copy/paste the bash code locally and run it with bash ./filename.sh, as the curl command produced privilege errors when run directly.
Either way, this should put the emscripten SDK in your home directory.

Of course, if you close your current shell session, emcc will not work anymore.
To have it added to the terminal environment by default, put the following line in ~/home/.bashrc:
source "/home/[YOUR USERNAME HERE]/.emsdk/emsdk_env.sh"
(Of course, if for some reason the .emsdk folder is elsewhere, adjust the directory accordingly.)
Important note: this will add emcc to your user ONLY. Using 'sudo' will yield a "command not found" error

For Windows users:
You're on your own here.
Sorry. I normally use windows as my primary OS, but I sank waaaaay too much time into
making it work on this platform. I had machines running the other operating systems, so I just went with them.

If you are like me and have no computer skills at all, you could either make a live USB, Dual-boot, or make a VM if you don't already have a Linux machine sitting around.


Update: I gained another precious ounce of computer skill and learned how to make this work


You need MSYS2 to build this on Windows. It creates an arch linux-like shell within the operating system.

I knew about this program for a bit, and had seen it talked about on these forums, but I was less acquainted with this flavor of linux (I normally use Ubuntu with apt).
I hit issues at seemingly every turn, even with things as simple as installing packages. You can call me an idiot. Even if you don't, I'll call myself one. In order to get to building anything in MSYS2 from a fresh install, several packages must be downloaded and updated.

For all of this, use the MSYS2x64 version (should have a light blue icon)

Right off the bat, it is suggested to do an environment update with
pacman -Syu
(for those who are new to this (I.E me), pacman is the package manager that comes bundled with MSYS2. It is the service through which most packages are obtained.)
After updating everything at a basic level, the c++ toolset must be installed.
I used the tutorial described here to do so.
This tutorial has the added benefit in that it also installs pkg-config and python(because emscripten is written in python) for you, so you don't need to install any other packages (other than, of course, emscripten itself).


With the basics set up, it is time to install emscripten.
First, run cd ~ (to go to your home directory)
Then run steps outlined on the emsdk website.
(Note: Do NOT follow anything in the steps that are for Windows users. These only apply if you are using the Windows native cmd to install emscripten. Remember, MSYS2 is a linux shell.)

Once all of the steps are run, you can test and see that emscripten is installed by typing
emsdk list

There is a hitch, though. Much like the Ubuntu guide above, emscripten will not be active if you close and reopen the shell session, and must be reactivated by running the emsdk_env.sh script again. To get this on every startup, we need to do similar to what is described above.

The .bashrc file is located in C:\msys64\home\[YOUR USERNAME]\
You can edit this file with a text editor of your choice (I personally use Notepad++)

At the bottom of the file, add these lines (the comment is optional):
#initialize emcc source "emsdk/emsdk_env.sh"

Save the file and relaunch MSYS2x64. If all goes right, the first lines to appear in the terminal window will say something like
Adding directories to PATH: PATH += /...

You can now use the emsdk without having to run the setup script every time a new window is opened.





With your dependencies added to your computer environment, it is time to make some code!

The specific command needed to actually build the program is the following:
make -f Makefile.emscripten
or use any of the arguments listed in the readme file to change the build:
* `RELEASE=1` - Compile a release build (optimised, stripped, etc.)
* `STATIC=1` - Produce a statically-linked executable (good for Windows builds, so you don't need to bundle DLL files)
* `JAPANESE=1` - Enable the Japanese-language build (instead of the unofficial Aeon Genesis English translation)
* `FIX_BUGS=1` - Fix bugs in the game (see [src/Bug Fixes.txt](src/Bug%20Fixes.txt))
* `WINDOWS=1` - Enable Windows-only features like a unique file/taskbar icon, and system font loading (needed for the font setting in Config.dat to do anything)
* `RASPBERRY_PI=1` - Enable tweaks to improve performance on Raspberry Pis
* `NONPORTABLE=1` - Enable bits of code that aren't portable, but are what the original game used
Example:
make -f Makefile.emscripten RELEASE=1
will produce a production build of this port.

The end product will be 5 files in your "Build" folder. These 5 files are all you need to have a 100% functioning website capable of playing cave story.
[Special note, however: You cannot simply click on the HTML. You have to host it somewhere in order to use it. I hosted mine on github.]


[Another special note: If you have more than 1 of these programs hosted on your website, they WILL SHARE the Profile.dat, so if you save in one instance of CS and load up another, it will try to
load and save to that same Profile.dat.

To fix this, change the name of "Profile.dat" in Profile.cpp (Located in /src, alter the text at Line 32) to something unique. (For instance, I named mine ProfileHH.dat)
]




To further prove my point, I ported my 1st mod of CS to emscripten, Gregg Story. Give it a try!
Like all first mods, this one has some rough spots. There are numerous text window format errors, as well as a hearty helping of typos
and grammar mistakes (I am useless without the help of a spellchecker). In fact, the browser version is slightly improved from the offline version; I found several spelling mistakes while working to port it over.

As for the mod itself, you can check out that original offline version on Doukutsu Club as well as a description on what it is about.
hhgregghh.png



Happy Compiling! :)
 
Last edited:
Aug 14, 2021 at 3:39 AM
Junior Member
"Wow! The more I drink of this magical beverage, the more games I can play! Wheee!"
Join Date: Jun 18, 2021
Location: Earth, Mars, or somewhere in between...
Posts: 20
I am shamelessly bumping this post. The reason for me doing so is because I found the solution to my question. I've figured out how to build the Emscripten port.

If anyone else wishes to do the same, please refer to the lower half of the original post.
 
Aug 14, 2021 at 6:14 PM
Senior Member
"Fly, Fly, Fly!"
Join Date: Feb 4, 2015
Location: Nibel
Posts: 136
Age: 18
Woah! This is really cool :0
Tried a little bit of both your port of Gregg Story and the original Cave Story, they both seem to run with no issues
 
Top