diff options
Diffstat (limited to 'md')
| -rw-r--r-- | md/writeup.md | 2 | ||||
| -rw-r--r-- | md/writeup/web_assembly_sdl_example.md | 208 | 
2 files changed, 209 insertions, 1 deletions
diff --git a/md/writeup.md b/md/writeup.md index 73f5124..ff0ead0 100644 --- a/md/writeup.md +++ b/md/writeup.md @@ -21,7 +21,7 @@ title: Writeup page  <!--[Write hello world with stm32](writeup/hello_world_stm32.md)  -->  [C macro tricks](writeup/c_macro_tricks.md)    [STM32F4 SDRAM configuration](writeup/stm32f4_sdram_configuration.md)   - +[WebAssembly SDL example](writeup/web_assembly_sdl_example.md)    ## Projects diff --git a/md/writeup/web_assembly_sdl_example.md b/md/writeup/web_assembly_sdl_example.md new file mode 100644 index 0000000..c6f475b --- /dev/null +++ b/md/writeup/web_assembly_sdl_example.md @@ -0,0 +1,208 @@ +title: WebAssembly SDL example +keywords:c,webassembly,js,SDL + +# WebAssembly SDL example + +## Intro + +There is many examples of how to compile SDL for webassembly, but many of them isnt  +minimal as necessary, so here tried to make just bare minimum for application +that can be compiled for 2 targets webassembly and pc. + +## How things works + +Webassembly is virtual machine that you can run in your browser, it allows you to run compiled code. +Its not 100% like real pc virtual machine and more oriented on web. But its close enough to just +port and run you C/C++ or any other language that supports LLVM as backend.  + +There need to be included emscripten header that gives callback for javascript to be runned. + +```c +#include <emscripten/emscripten.h> +``` + +And as all this going to be compiled to webassembly byte code then you can _just_ load compiled file. +There is many ways how wasm bytecode going to be runned. We registed our code so its runes specified +number of frames per second. Check functions docs for better description.  + +```c +void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop) +``` + +Porting requiring to define loop that will be registered for webassembly engine and thats all.  +There need to be covered more things if there is need to use some fonts,images or files. But for +now its minimal example that will draw SDL window in your browser ;] + +## Source + + + +```c +#include <stdio.h> +#include <stdlib.h> + +#if __EMSCRIPTEN__ +#include <emscripten/emscripten.h> +#include <SDL2/SDL.h> +#include <SDL/SDL_ttf.h> +#else +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> +#endif + +#define SCREEN_WIDTH 200 +#define SCREEN_HEIGHT 200 + +SDL_Window *window = NULL; +SDL_Surface *screen = NULL; +SDL_Surface *blank = NULL; + +#define MAX(a,b) ((a) > (b) ? a : b) +#define MIN(a,b) ((a) < (b) ? a : b) + +void render() +{ +	SDL_Rect r_scr; +	r_scr.x = 10; +	r_scr.y = 20; +	r_scr.w = 10; +	r_scr.h = 10; +	SDL_Rect r_im; +	r_im.x = 0; +	r_im.y = 0; +	r_im.w = 16; +	r_im.h = 16; +	SDL_BlitSurface(blank, NULL, screen, &r_scr); +} + +#if __EMSCRIPTEN__ +void main_tick() { +#else +int main_tick() { +#endif +     +	SDL_UpdateWindowSurface(window); + + +	#if !__EMSCRIPTEN__ +	return 1; +	#endif +} + +void main_loop() +{ +	 + + +#if __EMSCRIPTEN__ +	emscripten_set_main_loop(main_tick, -1, 1); +#else +	int quit = 0; +	SDL_Event event; +	 + +	while (quit==0) +	{ +		 +		while (SDL_PollEvent(&event)) +		{ +			switch (event.type) +			{ +			case SDL_QUIT: +				quit = 1; +				break; +			} +			quit = main_tick(); +		} +		printf("Loop\n"); +	} +#endif +} + +int main() +{ +	SDL_Init(SDL_INIT_VIDEO); + +	window = SDL_CreateWindow( +		"WEBASM", +		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, +		SCREEN_WIDTH, SCREEN_HEIGHT, +		SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); +	screen = SDL_GetWindowSurface(window); +	SDL_GL_SetSwapInterval(1); + +	blank = SDL_CreateRGBSurface(0, 16, 16, 32, 0, 255, 255, 50); +	Uint32 color = SDL_MapRGB(blank->format, 50, 0 , 0); +	for (int x = 0; x < 16; x++) +	{ +		for (int y = 0; y < 16; y++) +		{ +			Uint32 *bufp; +			bufp = (Uint32 *)blank->pixels + y*blank->pitch/4 + x; +			*bufp = color; +		} +	} + +	main_loop(); + +	SDL_DestroyWindow(window); +    SDL_Quit(); + +	return 0; +} +``` + + +```js +<html> +    <head> +    	<meta charset="utf-8"> +    	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +    </head> +    <body> +    	<script type='text/javascript'> +	      var Module = {}; +	      fetch('index.wasm') +	        .then(response => +	          response.arrayBuffer() +	        ).then(buffer => { +	          Module.canvas = document.getElementById("canvas"); +	          Module.wasmBinary = buffer; +	          var script = document.createElement('script'); +	          script.src = "index.js"; +	          script.onload = function() { +	            console.log("Emscripten boilerplate loaded.") +	          } +	          document.body.appendChild(script); +	        }); +	    </script> +	    <canvas id="canvas" style="width:100%; height:100%"></canvas> + +	</body> +</html> +``` + +```makefile +CC=gcc +CFALGS= +LDFLAGS=-lSDL2 -lSDL2_ttf + +EM_ENV=LLVM=/usr/bin NODE_JS=node EMSCRIPTEN_ROOT=/usr/lib/emscripten +EM_CC=emcc +EM_CFLAGS=-s WASM=1 -O3 +EM_LDFALGS=-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' -s USE_SDL_TTF=2 + +pc: +	$(CC) $(CFLAGS) $(LDFLAGS) main.c -o main + +em: +	$(EM_CC) main.c $(EM_CFLAGS) $(EM_LDFALGS) -o index.js -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'   +``` + +## Links + +1. https://wiki.libsdl.org/CategoryAPI +2. https://developer.mozilla.org/en-US/docs/WebAssembly/C_to_wasm +3. https://github.com/kvark/wasm-triangle/blob/master/src/main.rs +4. https://github.com/belen-albeza/space-shooter-wasm/blob/master/src/main.c +5. https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html
\ No newline at end of file  | 
