Picture this: Taking a game as classic as Pokemon Red and making it run in your web browser. This text describes the process of making a legacy game to run in the browser via compiler . Emscripten The code is executed on the client side, the main advantage being that no server is required, so it can be hosted for free on Gitlab or GitHub Pages. This approach is truly cross-platform, making it possible to play the same game on any device and architecture that supports browsers. Here you can try it yourself https://525073.gitlab-pages.ics.muni.cz/wasm-pokemon/ Source code: https://github.com/matejsmycka/gameboy-wasm-emulator How it works Old games need an emulator to be playable, which simulates the original hardware but as software on modern PCs. Emulators can be written in any language. However, in order to make it run on the client side, it has to be in a language that the browser runtime can execute. Historically, browsers could execute only JavaScript, but in recent years, all major browsers have implemented support for (WASM). Emulators, which are written in some compiled language like C, C++, Rust, or Go (Check out a here), can be compiled to WASM. You can then hardcode the game into the emulator itself. So when you visit the website, JavaScript will load WASM binary with an embedded emulator and game ROM. WebAssembly list Step 1. - Choosing a compiler There are quite a lot of compilers, however, I found Emscripten to be the best because it handles many things like automatic HTML and CSS generation for your WASM binary. --shell-file /usr/lib/emscripten/src/shell_minimal.htm You also can use many different templates. Step 2. - Choosing emulator There are a lot of limitations that will occur in porting, has its own interface , and unlike , you can't just read and write to files as you wish. All files that runtime can access have to be bundled in the binary itself. It also cannot call any external libraries. Everything has to be included in compile time. Fun fact, you can't even open a network socket in the . So, picking an emulator that is as lightweight as possible is crucial. WASM WASI POSIX WASM WASM Another thing is that you have to choose a graphic library that the compiler supports. Emscripten supports and , After trying multiple emulators, I chose because it supported both libraries and was lightweight. SDL2 Raylib GameBoy Emulator by David Jolly Step 3. Porting In this part, you have to load the legally obtained of the game directly to the code. I used a tool , that translates the binary directly into a huge C array, it is ugly but reliable. Remove any ARGS that have to be provided. It is not feasible to launch the binary with arguments, but it can be done in the javascript loader. Remove any features that are not mandatory for the emulator, like controller support. ROM xxd WASM Step 4. Compiling This is the part where I spend most of the time; modifying all compiler options is tedious work, and I couldn't get the to work. RayLib After a lot of time of googling and trying different options, I came up with the following command: emcc -o build/index.html $(find src -name "*.c" && find tool -name "*.c") -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result -Os -I. -Itool -I src/ -I src/system -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --shell-file /usr/lib/emscripten/src/shell_minimal.html -DPLATFORM_WEB -s "EXPORTED_FUNCTIONS=["_free","_malloc","_main"]" -s EXPORTED_RUNTIME_METHODS=ccall -DCLIENT_SDL2 -sUSE_SDL=2 -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=32MB It could be optimized like the header files could be imported automatically, the total memory is overkill, and some options might be redundant. After finishing the compile stage, the compiler will yield HTML, CSS, JS, and WASM files. Run to play the game locally. python -m http.server Step 5. Tinkering In this stage, you can alter the files above, like modifying the CSS to resize the play screen or modifying the HTML to alert the player how to play. Finally, deploy the project with some free services, below is an example of how easy it is to play the game on GitLab Pages: image: ruby:latest pages: stage: deploy script: - mkdir public - cp build/index.wasm ./public/ - cp index.html ./public/ - cp index.js ./public/ artifacts: paths: - public Resources 1: . GameBoy Emulator by David Jolly 2: Good resource: Cpp-Retro-Snake-Game-with-raylib 3: Article about SDL WASM support 4: WASMBOY, Similar project, but written in AssemblyScript Thank you for reading, feedback is appreciated.