Skip to content
This repository has been archived by the owner on Feb 14, 2024. It is now read-only.

Jipok/Nim-SDL2-and-Emscripten

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

I spent some time studying the work of SDL2 with Emscripten. Although in the end it turned out to be a bad idea(look at the end), I decided to post information that could help me in my time.

Warn:I'm very bad in English. Most of the text is translated by Google, do not be surprised.

How to make working SDL2 app for web?

All you need:

  1. nimble install sl2_nim jsbind
  2. make a working native application
  3. get sdl.nim and nim.cfg from this repo
  4. replace import sdl2/sdl to import sdl
  5. Change the main loop of your application using sdl.mainLoop.

for example:

while done:

to

sdl.mainLoop done:

  1. nim c -d:asmjs -d:release main.nim

That's all. (Your code still has be compilable for the native)

How it works?

Nothing complicated. Look at the code for the sdl.nim and nim.cfg. It all boils down to applying the necessary compilation settings and replacing the main application loop with the procedure that will be called by Emscrypton.

template mainLoop*(statement, actions: untyped): untyped =
  proc emscLoop{.cdecl.} =
    if statement:
      emscripten_cancel_main_loop()
      sdl.quit()
      system.quit()
    else:
      actions

passL %= "-s USE_SDL=2"

Any live demo?

I took examples from Vladar4/sdl2_nim. Not everything was made working.

Simply run nim e build.nims to build all examples.

If you experience problems with local launching of examples on the chromium-based browser, then start your browser with the allow-file-access-from-files key. Ex: chromium --allow-file-access-from-files

Other examples? SDL-net?

I was not interested in sdl-net. But below you can find information about it. See "Ports"

What about WebAssembly?

Although WebAssembly(wasm) is more efficient, but not supported by many browsers. Therefore by default (see nim.cfg) it compiles into asmjs. Just add -d:wasm to compiler for wasm.

ex: nim c -d:release -d:wasm ex208_framerate.nim

Live demo: wasm_ex208_framerate

If you're interested, the forum has a post with the benchmarks: Nim in the browser: some benchmarks

ex205_sdl_gfx_primitives

The module gfxPrimitives is not included in sdl2. Also it does not exist in other ports. I had to compile it myself. Just download the libSDL2_gfx.o and add the linker option(Already there in a nim.cfg):

passL %= "./libSDL2_gfx.o"

How to open external files?

Use preload-file. Then put the files in the assets directory. After compilation, all the files will be assembled into one, but accessible by the same path.

For example:

add to config file passL %= "--preload-file assets"

to your code image1.load(app.renderer, "assets/img1.png")

All available ports are located here: https://github.com/emscripten-ports

Also in $EMSCRIPTEN/tools/ports/ you can find scripts that download and build ports.

All ports are downloaded and unpacked in: $HOME/.emscripten_ports/

In $HOME/.emscripten_cache/asmjs/ the cache and compiled ports are stored.

You can easily connect the desired port by specifying a flag for the linker.

ex: passL %= "-s USE_TTF=2"

sdl-image

This port requires additionally indicate for linker which formats need to be included:

ex: passL %= "-s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS=\'[\"png\"]\'"

Also you can already use the version compiled by me(supports png and bmp). Download and add:

passL %= "./libSDL2_image-png.o"

How to build port yourself?

You can see the script code from Emscripten, but they are not always effective. Also some information can be found in the wiki or on the github.

Example of how to build SDL2:

git clone https://github.com/emscripten-ports/SDL2
cd SDL2-master
mkdir build
cd build
emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --disable-mmx --disable-sdltest --disable-shared --enable-cpuinfo=false CFLAGS="-O3"
emmake make

Similarly, a ttf and a mixer can be built with:

EMCONFIGURE_JS=1 emconfigure ../configure --disable-shared --disable-sdltest --disable-mmx
emmake make

Then you can collect the necessary name.o files using emcc.

ex: emcc ./freetype.bc ./*.o -o libSDL2_ttf.bc

tip: llvm-nm file.o Will show what names the file exports So you can build a library with only the required functionality.

sdl-mixer

There is no separate port for the mixer. The built-in functions of sdl seem to play only wav. There also lacks some functions. For example: SetDistance

I didn't build the mixer with the support of mp3.

Some tips and scripts you can find here: link

Why you shouldn't use SDL2 with Emscripten?

Because it has a large size(3 mb) and terrible architecture(port, not sdl).

At first I thought about dynamic linking. But this is an experimental feature(article) and I was not able to use SDL2 as side module.

In general, I spent a lot of time trying to reduce the size. But neither a myself builds with the necessary functionality, nor dynamic linking will not help. Just take a look at how the SDL-image works:

It uses native functions to load the file and the libpng library. This adds about 1 megabyte and a loss in performance. The correct way would be to use ready-made browser functions for working with images. The functions of SDL2 should have been just stubs that caused the corresponding functions on the js.

And a quick review of the code, shows that this is used everywhere. It's horrible. My perfectionism did not allow me to continue to use this option for cross-platform applications.

You can use sdl1. For emscripten there is a simple library that uses the correct method. Just take a look at her code: library_sdl.js

About

How to Start and explain some things.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published