Compiling CSE2 Emscripten

Jun 25, 2021 at 2:00 AM
Neophyte Member
"Fresh from the Bakery"
Join Date: Jun 18, 2021
Location: Earth, Mars, or somewhere in between...
Posts: 4
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 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 To implement them, I curl’ed the cave.html from Clownacy’s demo website, and uploaded the 4 files to my 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 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.

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 ./, 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/"
(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 want to spend the time to figure this out, all the better. Perhaps you could even post your process here so others could follow (like yours truly).

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.

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
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.

Happy Compiling! :)
Last edited:
Aug 14, 2021 at 3:39 AM
Neophyte Member
"Fresh from the Bakery"
Join Date: Jun 18, 2021
Location: Earth, Mars, or somewhere in between...
Posts: 4
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
"Master using it, and you can have this!"
Join Date: Feb 4, 2015
Location: a place that exists
Posts: 73
Age: 16
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