diff --git a/allegro.js b/allegro.js
index e0dadf7..e66feaf 100644
--- a/allegro.js
+++ b/allegro.js
@@ -1867,7 +1867,9 @@ function log(string)
{
if (ALLEGRO_CONSOLE && console) console.log(string);
if (!_debug_enabled) return;
- _debug_element.innerHTML = _debug_element.innerHTML + string + "
";
+ if (_debug_element.nodeName.toLowerCase() == "textarea") _debug_element.value = _debug_element.value + string + "\n";
+ else _debug_element.innerHTML = _debug_element.innerHTML + string + "
";
+ _debug_element.scrollTop = _debug_element.scrollHeight;
}
/// Wipes the debug console
@@ -1875,7 +1877,8 @@ function log(string)
function wipe_log()
{
if (!_debug_enabled) return;
- _debug_element.innerHTML = "";
+ if (_debug_element.nodeName.toLowerCase() == "textarea") _debug_element.value = "";
+ else _debug_element.innerHTML = "";
}
//@}
diff --git a/emscripten/README.md b/emscripten/README.md
new file mode 100644
index 0000000..dceb059
--- /dev/null
+++ b/emscripten/README.md
@@ -0,0 +1,35 @@
+## A lousy C port of a lousy JS port of a C library
+
+*Allegro have been to JS and back*
+
+**You think you're a hardcore allegro programmer? PROVE IT!**
+
+### How do I make a C game for allegro.js?
+
+1. Clone this repository
+2. Install emscripten
+3. Read `allegro.h`
+4. Read and understand the examples
+5. Write code
+6. Compile-it
+7. Enjoy
+
+You don't need to write a single line of Javascript or HTML ! !
+
+### How different is it from allegro.js
+
+There is several tiny differences:
+* All globals are functions (because emscripten)
+* Because of name clash, rand and log have been renamed to rand16 and logmsg
+* When passing an array parameter, you'll also have to pass its length
+* There is no such thing as default parameters, closures, etc. (this is C programming, for real)
+
+### How to compile C code into an HTML+Javascript program?
+
+Compile your code with `emcc`:
+```bash
+emcc --pre-js ../allegro.js --js-library ../allegro.js --js-library library.js -I. -o my_game.html my_game.c
+```
+
+Open the created html file with your favorite JS enabled internet browser.
+
diff --git a/emscripten/allegro.h b/emscripten/allegro.h
new file mode 100644
index 0000000..e09e8de
--- /dev/null
+++ b/emscripten/allegro.h
@@ -0,0 +1,201 @@
+/**
+ I'm the C header, #include me!
+**/
+
+#ifndef _ALLEGRO_JS_H
+#define _ALLEGRO_JS_H
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CONFIGURATION ROUTINES */
+extern void install_allegro(void);
+extern void allegro_init(void);
+extern void allegro_init_all(const char *canvas_id, int w, int h, int menu, const int *enable_keys, int enable_keys_len);
+#define END_OF_MAIN()
+
+/* MOUSE ROUTINES */
+extern int mouse_b(void);
+extern int mouse_pressed(void);
+extern int mouse_released(void);
+extern int mouse_x(void);
+extern int mouse_y(void);
+extern int mouse_z(void);
+extern int mouse_mx(void);
+extern int mouse_my(void);
+extern int mouse_mz(void);
+
+extern int install_mouse(int menu);
+extern int remove_mouse(void);
+extern int show_mouse(void);
+extern int hide_mouse(void);
+
+/* TOUCH ROUTINES */
+typedef struct {
+ int x, y, mx, my, px, py, sx, sy, id, age, dead;
+} TOUCH_OBJECT;
+extern TOUCH_OBJECT* touch(int *len);
+extern TOUCH_OBJECT* touch_pressed(int *len);
+extern TOUCH_OBJECT* touch_released(int *len);
+extern void install_touch(void);
+extern void remove_touch(void);
+
+/* TIMER ROUTINES */
+#define SECS_TO_TIMER(secs) ( secs*1000 )
+#define MSEC_TO_TIMER(msec) ( msec )
+#define BPS_TO_TIMER(bps) ( 1000./(float)bps )
+#define BPM_TO_TIMER(bpm) ( 60*1000./(float)bpm )
+typedef void (*procedure)(void);
+typedef void (*bar)(float progress);
+extern void install_timer(void);
+extern long altime(void);
+extern void install_int(procedure p, long msec);
+extern void install_int_ex(procedure p, long speed);
+extern void loop(procedure p, long speed);
+extern void loading_bar(float progress);
+extern void ready(procedure p, bar b);
+extern void remove_int(procedure p);
+extern void remove_all_ints(void);
+
+/* KEYBOARD ROUTINES */
+const char KEY_A = 0x41, KEY_B = 0x42, KEY_C = 0x43, KEY_D = 0x44, KEY_E = 0x45, KEY_F = 0x46, KEY_G = 0x47,
+ KEY_H = 0x48, KEY_I = 0x49, KEY_J = 0x4A, KEY_K = 0x4B, KEY_L = 0x4C, KEY_M = 0x4D, KEY_N = 0x4E,
+ KEY_O = 0x4F, KEY_P = 0x50, KEY_Q = 0x51, KEY_R = 0x52, KEY_S = 0x53, KEY_T = 0x54, KEY_U = 0x55,
+ KEY_V = 0x56, KEY_W = 0x57, KEY_X = 0x58, KEY_Y = 0x59, KEY_Z = 0x5A,
+ KEY_0 = 0x30, KEY_1 = 0x31, KEY_2 = 0x32, KEY_3 = 0x33, KEY_4 = 0x34, KEY_5 = 0x35, KEY_6 = 0x36,
+ KEY_7 = 0x37, KEY_8 = 0x38, KEY_9 = 0x39,
+ KEY_0_PAD = 0x60, KEY_1_PAD = 0x61, KEY_2_PAD = 0x62, KEY_3_PAD = 0x63, KEY_4_PAD = 0x64, KEY_5_PAD = 0x65,
+ KEY_6_PAD = 0x66, KEY_7_PAD = 0x67, KEY_8_PAD = 0x68, KEY_9_PAD = 0x69,
+ KEY_F1 = 0x70, KEY_F2 = 0x71, KEY_F3 = 0x72, KEY_F4 = 0x73, KEY_F5 = 0x74, KEY_F6 = 0x75, KEY_F7 = 0x76,
+ KEY_F8 = 0x77, KEY_F9 = 0x78, KEY_F10 = 0x79, KEY_F11 = 0x7a, KEY_F12 = 0x7b,
+ KEY_ESC = 0x1B, KEY_TILDE = 0xc0, KEY_MINUS = 0xbd, KEY_EQUALS = 0xbb, KEY_BACKSPACE = 0x08, KEY_TAB = 0x09,
+ KEY_OPENBRACE = 0xdb, KEY_CLOSEBRACE = 0xdd, KEY_ENTER = 0x0D, KEY_COLON = 0xba, KEY_QUOTE = 0xde,
+ KEY_BACKSLASH = 0xdc, KEY_COMMA = 0xbc, KEY_STOP = 0xbe, KEY_SLASH = 0xBF, KEY_SPACE = 0x20,
+ KEY_INSERT = 0x2D, KEY_DEL = 0x2E, KEY_HOME = 0x24, KEY_END = 0x23, KEY_PGUP = 0x21, KEY_PGDN = 0x22,
+ KEY_LEFT = 0x25, KEY_RIGHT = 0x27, KEY_UP = 0x26, KEY_DOWN = 0x28, KEY_SLASH_PAD = 0x6F, KEY_ASTERISK = 0x6A,
+ KEY_MINUS_PAD = 0x6D, KEY_PLUS_PAD = 0x6B, KEY_ENTER_PAD = 0x0D, KEY_PRTSCR = 0x2C, KEY_PAUSE = 0x13,
+ KEY_EQUALS_PAD = 0x0C, KEY_LSHIFT = 0x10, KEY_RSHIFT = 0x10, KEY_LCONTROL = 0x11, KEY_RCONTROL = 0x11,
+ KEY_ALT = 0x12, KEY_ALTGR = 0x12, KEY_LWIN = 0x5b, KEY_RWIN = 0x5c, KEY_MENU = 0x5d, KEY_SCRLOCK = 0x9d,
+ KEY_NUMLOCK = 0x90, KEY_CAPSLOCK = 0x14;
+extern int* key(void);
+extern int* pressed(void);
+extern int* released(void);
+extern int install_keyboard(const int *enable_keys, int enable_keys_len);
+extern int remove_keyboard(void);
+
+/* BITMAP ROUTINES */
+typedef struct {
+ int handle;
+ int w, h;
+} BITMAP_OBJECT;
+extern BITMAP_OBJECT* create_bitmap(int width, int height);
+extern BITMAP_OBJECT* load_bitmap(const char *filename);
+extern BITMAP_OBJECT* load_bmp(const char *filename);
+extern BITMAP_OBJECT** load_sheet(const char *filename, int w, int h, int *len);
+
+/* GRAPHICS MODES */
+extern BITMAP_OBJECT* canvas(void);
+extern int SCREEN_W(void);
+extern int SCREEN_H(void);
+extern int set_gfx_mode(const char *canvas_id, int width, int height, int smooth);
+
+/* DRAWING PRIMITIVES */
+#define PI = 3.14159265
+#define PI2 = 6.2831853
+#define PI_2 = 1.570796325
+#define PI_3 = 1.04719755
+#define PI_4 = 0.7853981625
+#define RAD(d) ( -d*PI/180.0 )
+#define DEG(r) ( -r*180.0/PI )
+extern int makecol(char r, char g, char b, char a);
+extern int makecolf(float r, float g, float b, float a);
+extern char getr(int colour);
+extern char getg(int colour);
+extern char getb(int colour);
+extern char geta(int colour);
+extern float getrf(int colour);
+extern float getgf(int colour);
+extern float getbf(int colour);
+extern float getaf(int colour);
+extern int getpixel(BITMAP_OBJECT *bitmap, int x, int y);
+extern void putpixel(BITMAP_OBJECT *bitmap, int x, int y, int colour);
+extern void clear_bitmap(BITMAP_OBJECT *bitmap);
+extern void clear_to_color(BITMAP_OBJECT *bitmap, int colour);
+extern void line(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int colour, int width);
+extern void vline(BITMAP_OBJECT *bitmap, int x, int y1, int y2, int colour, int width);
+extern void hline(BITMAP_OBJECT *bitmap, int x1, int y, int x2, int colour, int width);
+extern void triangle(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int x3, int y3, int colour, int width);
+extern void trianglefill(BITMAP_OBJECT *bitmap, int x1, int y1, int x2, int y2, int x3, int y3, int colour);
+extern void polygon(BITMAP_OBJECT *bitmap, int vertices, const int *points, int colour, int width);
+extern void polygonfill(BITMAP_OBJECT *bitmap, int vertices, const int *points, int colour);
+extern void rect(BITMAP_OBJECT *bitmap, int x, int y, int w, int h, int colour, int width);
+extern void rectfill(BITMAP_OBJECT *bitmap, int x, int y, int w, int h, int colour);
+extern void circle(BITMAP_OBJECT *bitmap, int x, int y, int radius, int colour, int width);
+extern void circlefill(BITMAP_OBJECT *bitmap, int x, int y, int radius, int colour);
+extern void arc(BITMAP_OBJECT *bitmap, int x, int y, float ang1, float ang2, int radius, int colour, int width);
+extern void arcfill(BITMAP_OBJECT *bitmap, int x, int y, float ang1, float ang2, int radius, int colour);
+
+/* BLITTING AND SPRITES */
+extern void draw_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y);
+extern void scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float sx, float sy);
+extern void rotate_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float angle);
+extern void pivot_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, int cx, int cy, float angle);
+extern void rotate_scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, float angle, float sx, float sy);
+extern void pivot_scaled_sprite(BITMAP_OBJECT *bmp, BITMAP_OBJECT *sprite, int x, int y, int cx, int cy, float angle, float sx, float sy);
+extern void blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int sx, int sy, int dx, int dy, int w, int h);
+extern void simple_blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int x, int y);
+extern void stretch_blit(BITMAP_OBJECT *source, BITMAP_OBJECT *dest, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
+
+/* TEXT OUTPUT */
+typedef int FONT_OBJECT;
+extern FONT_OBJECT* font(void);
+extern FONT_OBJECT* load_base64_font(char *data);
+extern FONT_OBJECT* load_font(char *filename);
+extern FONT_OBJECT* create_font(char *family);
+extern void textout(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width);
+extern void textout_centre(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width);
+extern void textout_right(BITMAP_OBJECT *bitmap, FONT_OBJECT *font, const char *string, int x, int y, int size, int colour, int outline, int width);
+
+/* SOUND ROUTINES */
+typedef int SAMPLE_OBJECT;
+extern void install_sound(void);
+extern void set_volume(float volume);
+extern float get_volume(void);
+extern SAMPLE_OBJECT* load_sample(char *filename);
+extern void destroy_sample(char *filename);
+extern void play_sample(SAMPLE_OBJECT *sample, float vol, float freq, int loop);
+extern void adjust_sample(SAMPLE_OBJECT *sample, float vol, float freq, int loop);
+extern void stop_sample(SAMPLE_OBJECT *sample);
+extern void pause_sample(SAMPLE_OBJECT *sample);
+
+/* HELPER MATH FUNCTIONS */
+extern unsigned short rand16(void);
+extern int rand32(void);
+extern float frand(void);
+#define abs(a) ( (a<0)?(-a):(a) )
+extern float length(float x, float y);
+extern float distance(float x1, float y1, float x2, float y2);
+extern float distance2(float x1, float y1, float x2, float y2);
+extern float linedist(float ex1, float ey1, float ex2, float ey2, float x, float y);
+extern float lerp(float from, float to, float progress);
+extern float dot(float x1, float y1, float x2, float y2);
+extern int sgn(float a);
+extern float angle(float x1, float y1, float x2, float y2);
+extern float anglediff(float a, float b);
+extern float clamp(float value, float min, float max);
+extern float scale(float value, float min, float max, float min2, float max2);
+extern float scaleclamp(float value, float min, float max, float min2, float max2);
+
+/* DEBUG FUNCTIONS */
+extern int ALLEGRO_CONSOLE;
+extern void enable_debug(const char *id);
+extern void logmsg(const char *string);
+extern void wipe_log(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALLEGRO_JS_H */
diff --git a/emscripten/examples/exbmp.c b/emscripten/examples/exbmp.c
new file mode 100644
index 0000000..0078658
--- /dev/null
+++ b/emscripten/examples/exbmp.c
@@ -0,0 +1,26 @@
+#include
+#include
+
+// Globally declared bitmap object
+BITMAP_OBJECT *logo;
+
+void when_ready(void) {
+ // Renders the loaded image on the screen
+ stretch_blit(logo, canvas(), 0, 0, logo->w, logo->h, 0, 0, SCREEN_W(), SCREEN_H());
+}
+
+int main(void) {
+ // Initialises allegro.js
+ allegro_init();
+
+ // Installs graphics at given canvas in 640x480 resolution
+ set_gfx_mode("canvas", 640, 480, 1);
+
+ // Loads an image into the bitmap object
+ logo = load_bmp("data/allegro.png");
+
+ ready(when_ready, NULL);
+
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/exbounce.c b/emscripten/examples/exbounce.c
new file mode 100644
index 0000000..d1927bd
--- /dev/null
+++ b/emscripten/examples/exbounce.c
@@ -0,0 +1,94 @@
+#include
+#include
+
+// bitmap objects
+BITMAP_OBJECT *clouds, *ball;
+
+// sample object
+SAMPLE_OBJECT *bounce;
+
+// size and speed of the ball
+const int size=64, speed=5;
+
+// positon of the ball
+float cx=100, cy=100;
+
+// velocity of the ball
+float vx=speed, vy=speed;
+
+// drawing function
+void draw(void)
+{
+ // draw allegro clouds background
+ stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H());
+
+ // draws the ball centered
+ draw_sprite(canvas(), ball, cx, cy);
+}
+
+// update game logic
+void update(void) {
+ // did the ball bounce off the wall this turn?
+ int bounced = 0;
+
+ // if the ball is going to collide with screen bounds
+ // after applying velocity, if so, reverse velocity
+ // and remember that it bonced
+ if (cx+vx > SCREEN_W()) { vx = -speed; bounced=1; }
+ if (cy+vy > SCREEN_H()) { vy = -speed*3; bounced=1; }
+ if (cx+vx < 0) { vx = speed; bounced=1; }
+ if (cy+vy < 0) { vy = speed; bounced=1; }
+
+ // move the ball
+ cx += vx;
+ cy += vy;
+
+ // if it bounced, play a sound
+ if (bounced) play_sample(bounce, 1., 1., 0);
+
+ // add gravity
+ vy += .3;
+}
+
+void in_loop(void) {
+ // clear screen
+ clear_to_color(canvas(), makecol(255, 255, 255, 255));
+
+ // update game logic
+ update();
+
+ // render everything
+ draw();
+}
+
+void when_ready(void) {
+ loop(in_loop, BPS_TO_TIMER(60));
+}
+
+// entry point of our example
+int main(void) {
+ // enable debugging to console element
+ enable_debug("output");
+
+ // put allegro in canvas with id="canvas"
+ // make the dimesnions 640x480
+ set_gfx_mode("canvas", 640, 480, 1);
+
+ install_sound();
+
+ // load ball image
+ ball = load_bmp("data/planet.png");
+
+ // load background image
+ clouds = load_bmp("data/clouds.png");
+
+ // load the bounce sound
+ bounce = load_sample("data/bounce.mp3");
+
+ // make sure everything has loaded
+ ready(when_ready, NULL);
+
+ // the end
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/exgame.c b/emscripten/examples/exgame.c
new file mode 100644
index 0000000..6a7149a
--- /dev/null
+++ b/emscripten/examples/exgame.c
@@ -0,0 +1,85 @@
+#include
+#include
+#include
+
+//bitmap objects
+BITMAP_OBJECT *man, *apple, *bg;
+
+// munching soudn evffect
+SAMPLE_OBJECT *munch;
+
+// apple position
+float apple_x = 200, apple_y = 200;
+
+// player position
+float player_x = 100, player_y = 100;
+
+// score
+int score = 0;
+
+// rendering function
+void draw(void) {
+ // draw background
+ simple_blit(bg, canvas(), 0, 0);
+
+ // draw player
+ draw_sprite(canvas(), man, player_x, player_y);
+
+ // draw the apple
+ draw_sprite(canvas(), apple, apple_x, apple_y);
+
+ // print out current score
+ char str[25];
+ snprintf(str, 25, "Score: %d", score);
+ textout(canvas(), font(), str, 10, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1);
+}
+
+// update game logic
+void update(void) {
+ // check for keypresses and move the player accordingly
+ if (key()[KEY_UP]) player_y -= 4;
+ if (key()[KEY_DOWN]) player_y += 4;
+ if (key()[KEY_LEFT]) player_x -= 4;
+ if (key()[KEY_RIGHT]) player_x += 4;
+
+ // if player is touching the apple...
+ if (distance(player_x, player_y, apple_x, apple_y) < 20)
+ {
+ // play muching sound
+ play_sample(munch, 1., 1., 0);
+
+ // move apple to a new spot, making it look like it's
+ // a breand new apple
+ apple_x = rand16() % (SCREEN_W()-32);
+ apple_y = rand16() % (SCREEN_H()-32);
+
+ // increase score
+ score++;
+
+ // log success to console
+ logmsg("Apple eaten!");
+ }
+}
+
+void in_loop(void) {
+ update();
+ draw();
+}
+
+void when_ready(void) {
+ loop(in_loop, BPS_TO_TIMER(60));
+}
+
+int main(void) {
+ enable_debug("output");
+ allegro_init_all("canvas", 640, 480, 0, NULL, 0);
+ man = load_bmp("data/man.png");
+ apple = load_bmp("data/apple.png");
+ bg = load_bmp("data/grass.jpg");
+ munch = load_sample("data/munch.mp3");
+
+ ready(when_ready, NULL);
+
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/exhello.c b/emscripten/examples/exhello.c
new file mode 100644
index 0000000..7c0e5b3
--- /dev/null
+++ b/emscripten/examples/exhello.c
@@ -0,0 +1,18 @@
+#include
+
+int main(void) {
+ // Initialising allegro.js
+ allegro_init();
+
+ // Selecting canvas element adn setting it up for display at 640x480
+ set_gfx_mode("canvas", 640, 480, 1);
+
+ // Clears the screen to white
+ clear_to_color(canvas(), makecol(255, 255, 255, 255));
+
+ // Typoes 'Hello World!' message to the centre of the screen
+ textout_centre(canvas(), font(), "Hello World!", SCREEN_W()/2, SCREEN_H()/2, 24, makecol(0, 0, 0, 255), 0, 0);
+
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/extouch.c b/emscripten/examples/extouch.c
new file mode 100755
index 0000000..50c4691
--- /dev/null
+++ b/emscripten/examples/extouch.c
@@ -0,0 +1,35 @@
+#include
+#include
+
+BITMAP_OBJECT *clouds, *ball;
+
+void draw(void) {
+ clear_to_color(canvas(), makecol(255, 255, 255, 255));
+ stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H());
+
+ int touch_len;
+ TOUCH_OBJECT *touchp = touch(&touch_len);
+ for (int c=0; c
+#include
+#include
+
+#define SPRITE_MAX 65536
+
+int num = 0, speed = 3;
+float x[SPRITE_MAX], y[SPRITE_MAX], vx[SPRITE_MAX], vy[SPRITE_MAX];
+long last_time = 0;
+BITMAP_OBJECT *bmp, *buffer;
+
+void in_loop(void) {
+ clear_to_color(buffer, makecol(255,255,255,255));
+
+ for(int c=0; c SCREEN_W()) vx[c] = -abs(vx[c]);
+ if (y[c]+vy[c] > SCREEN_H()) vy[c] = -abs(vy[c]);
+ if (x[c]+vx[c] < -64) vx[c] = abs(vx[c]);
+ if (y[c]+vy[c] < -64) vy[c] = abs(vy[c]);
+ x[c] += vx[c];
+ y[c] += vy[c];
+ }
+
+ if (num < SPRITE_MAX) {
+ x[num] = rand16() % SCREEN_W();
+ y[num] = rand16() % SCREEN_H();
+ vx[num] = frand()*2 -1;
+ vy[num] = frand()*2 -1;
+ num++;
+ }
+ long msec = (altime()-last_time)-1;
+
+ char str[256];
+ snprintf(str, 256, "Sprites: %d took %ld msec ( %ld fps)", num, msec, 1000/msec);
+ textout(canvas(), font(), str, 20, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1);
+
+ last_time = altime();
+}
+
+void when_ready(void) {
+ loop(in_loop, MSEC_TO_TIMER(1));
+}
+
+int main(void) {
+ enable_debug("output");
+ set_gfx_mode("canvas", 640, 480, 1);
+ bmp = load_bmp("data/planet.png");
+ buffer = create_bitmap(SCREEN_W(), SCREEN_H());
+ ready(when_ready, NULL);
+
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/stress.c b/emscripten/examples/stress.c
new file mode 100644
index 0000000..e745fdb
--- /dev/null
+++ b/emscripten/examples/stress.c
@@ -0,0 +1,53 @@
+#include
+#include
+#include
+
+#define SPRITE_MAX 65536
+
+int num = 0, speed = 3;
+float x[SPRITE_MAX], y[SPRITE_MAX], vx[SPRITE_MAX], vy[SPRITE_MAX];
+long last_time = 0;
+BITMAP_OBJECT *bmp;
+
+void in_loop(void) {
+ clear_to_color(canvas(), makecol(255,255,255,255));
+
+ for(int c=0; c SCREEN_W()) vx[c] = -abs(vx[c]);
+ if (y[c]+vy[c] > SCREEN_H()) vy[c] = -abs(vy[c]);
+ if (x[c]+vx[c] < -64) vx[c] = abs(vx[c]);
+ if (y[c]+vy[c] < -64) vy[c] = abs(vy[c]);
+ x[c] += vx[c];
+ y[c] += vy[c];
+ }
+
+ if (num < SPRITE_MAX) {
+ x[num] = rand16() % SCREEN_W();
+ y[num] = rand16() % SCREEN_H();
+ vx[num] = frand()*2 -1;
+ vy[num] = frand()*2 -1;
+ num++;
+ }
+ long msec = (altime()-last_time)-1;
+
+ char str[256];
+ snprintf(str, 256, "Sprites: %d took %ld msec ( %ld fps)", num, msec, 1000/msec);
+ textout(canvas(), font(), str, 20, 30, 24, makecol(255,255,255,255), makecol(0,0,0,255), 1);
+
+ last_time = altime();
+}
+
+void when_ready(void) {
+ loop(in_loop, MSEC_TO_TIMER(1));
+}
+
+int main(void) {
+ enable_debug("output");
+ set_gfx_mode("canvas", 640, 480, 1);
+ bmp = load_bmp("data/planet.png");
+
+ ready(when_ready, NULL);
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/examples/unittest.c b/emscripten/examples/unittest.c
new file mode 100644
index 0000000..001aac3
--- /dev/null
+++ b/emscripten/examples/unittest.c
@@ -0,0 +1,266 @@
+#include
+#include
+#include
+
+BITMAP_OBJECT *clouds, *ball;
+SAMPLE_OBJECT *beep;
+
+int stage = -1;
+float delay = 0;
+char *title = "allegro.js test";
+const char *subtitle = "press space";
+
+int timercolor;
+int timers = 0;
+int width = 13;
+
+void callback1(void) {
+ circlefill(canvas(), 100, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void callback2(void) {
+ circlefill(canvas(), 200, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void callback3(void) {
+ circlefill(canvas(), 300, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void callback4(void) {
+ circlefill(canvas(), 400, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void callback5(void) {
+ circlefill(canvas(), 500, 100, 100, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void sound_callback(void) {
+ play_sample(beep, frand(), frand()+.5, 0);
+ circlefill(canvas(), SCREEN_W()/2, SCREEN_H()/2, 200, makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+}
+
+void draw(void) {
+
+ if (stage==0) {
+ title = "progress_bar";
+ loading_bar(delay/200.);
+ }
+ else if (stage==1) {
+ title = "blit";
+ blit(ball, canvas(), 0, 0, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w+1, rand16()%ball->h+1);
+ }
+ else if (stage==2) {
+ title = "stretch_blit";
+ stretch_blit(ball, canvas(), 0, 0, rand16()%ball->w+1, rand16()%ball->h+1, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W()+1, rand16()%SCREEN_H()+1);
+ }
+ else if (stage==3) {
+ title = "draw_sprite";
+ draw_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H());
+ }
+ else if (stage==4) {
+ title = "scaled_sprite";
+ scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), frand()*2+.1, frand()*2+.1);
+ }
+ else if (stage==5) {
+ title = "rotate_sprite";
+ rotate_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%360);
+ }
+ else if (stage==6) {
+ title = "pivot_sprite";
+ pivot_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w, rand16()%ball->h, rand16()%360);
+ }
+ else if (stage==7) {
+ title = "rotate_scaled_sprite";
+ rotate_scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%360, frand()*2+.1, frand()*2+.1);
+ }
+ else if (stage==8) {
+ title = "pivot_scaled_sprite";
+ pivot_scaled_sprite(canvas(), ball, rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%ball->w, rand16()%ball->h, rand16()%360, frand()*2+.1, frand()*2+.1);
+ }
+ else if (stage==9) {
+ title = "textout";
+ textout(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5);
+ }
+ else if (stage==10) {
+ title = "textout_centre";
+ textout_centre(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5);
+ }
+ else if (stage==11) {
+ title = "textout_right";
+ textout_right(canvas(), font(), "Hello World!", rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%48+8, makecol(rand16()%255, rand16()%255, rand16()%255, 255), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%5);
+ }
+ else if (stage==12) {
+ title = "getpixel";
+ int x = rand16()%SCREEN_W();
+ int y = rand16()%SCREEN_H();
+ char str[16];
+ snprintf(str, 16, "%d", getpixel(canvas(), x, y));
+ textout(canvas(), font(), str, x, y, 24, getpixel(canvas(), x, y), 0, 0);
+ }
+ else if (stage==13) {
+ title = "putpixel";
+ putpixel(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+ }
+ else if (stage==14) {
+ title = "clear_to_color";
+ clear_to_color(canvas(), makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+ }
+ else if (stage==15) {
+ title = "line";
+ line(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8);
+ }
+ else if (stage==16) {
+ title = "vline";
+ vline(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8);
+ }
+ else if (stage==17) {
+ title = "hline";
+ hline(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8);
+ }
+ else if (stage==18) {
+ title = "triangle";
+ triangle(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255), 1+rand16()%8);
+ }
+ else if (stage==19) {
+ title = "trianglefill";
+ trianglefill(canvas(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), rand16()%SCREEN_W(), rand16()%SCREEN_H(), makecol(rand16()%255, rand16()%255, rand16()%255, 255));
+ }
+ else if (stage==20) {
+ title = "polygon";
+ int n = rand16()%10+3;
+ int p[30];
+ for (int c=0; c>3)*24, (c&0xf)*24, 20, 20, makecol(255, 255, 255, 255));
+ }
+ else if (released()[c]) {
+ rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(255, 255, 0, 255));
+ }
+ else if (key()[c]) {
+ rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(255, 0, 0, 255));
+ }
+ else {
+ rectfill(canvas(), (c>>3)*24, (c&0xf)*24, 20, 20, makecol(0, 0, 0, 255));
+ }
+ }
+ }
+ else if (stage==30) {
+ title = "timer";
+ stage=31;
+ timers=1;
+ install_int_ex(callback1, SECS_TO_TIMER(1));
+ install_int_ex(callback2, MSEC_TO_TIMER(500));
+ install_int_ex(callback3, BPS_TO_TIMER(3));
+ install_int_ex(callback4, BPM_TO_TIMER(60));
+ install_int(callback5, 1500);
+ }
+ else if (stage==31) {
+ title = "timer";
+ }
+ else if (stage==32) {
+ stage=33;
+ title = "sound";
+ remove_all_ints();
+ install_int_ex(sound_callback, SECS_TO_TIMER(2));
+ }
+ else if (stage==33) {
+ title = "sound";
+ }
+ else if (stage==34) {
+ title = "The End";
+ remove_all_ints();
+ stage++;
+ }
+
+ textout_centre(canvas(), font(), title, SCREEN_W()/2, 64, 64, makecol(255, 255, 255, 255), makecol(0, 0, 0, 255), 2);
+ textout(canvas(), font(), subtitle, 10, SCREEN_H()-10, 24, makecol(255, 255, 255, 255), makecol(0, 0, 0, 255), 1);
+ delay++;
+ if (key()[KEY_SPACE] && delay>10)
+ {
+ stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H());
+ stage++;
+ delay=0;
+ }
+}
+
+void in_loop(void) {
+ draw();
+}
+
+void when_ready(void) {
+ stretch_blit(clouds, canvas(), 0, 0, clouds->w, clouds->h, 0, 0, SCREEN_W(), SCREEN_H());
+ loop(in_loop, BPS_TO_TIMER(60));
+}
+
+int main(void) {
+ enable_debug("output");
+ allegro_init_all("canvas", 640, 480, 0, NULL, 0);
+ timercolor = makecol(192, 168, 1, 254);
+ clouds = load_bmp("data/clouds.png");
+ ball = load_bmp("data/planet.png");
+ beep = load_sample("data/dtmf.mp3");
+
+ ready(when_ready, NULL);
+ return 0;
+}
+END_OF_MAIN()
diff --git a/emscripten/library.js b/emscripten/library.js
new file mode 100755
index 0000000..6a32698
--- /dev/null
+++ b/emscripten/library.js
@@ -0,0 +1,451 @@
+/**
+ You must concatenate allegro.js and this file before you try to use
+ this file as an emscripten JS library.
+ cat ../allegro.js > lib.js && cat library.js >> lib.js
+
+ I'm an emscripten library, the “glue” code between C and JS
+**/
+
+var AllegroJS = {
+ // PRIVATE STUFF
+ $ALLEG: {
+ // HANDLERS
+ // Index 0 is reserved for default values
+ bitmaps: [null],
+ bitmap_addrs: [null],
+ samples: [null],
+ fonts: [null],
+ // POINTER TO CANVAS
+ canvas: null,
+ // C ARRAY POINTERS
+ key: null,
+ pressed: null,
+ released: null,
+ touch: null,
+ touch_pressed: null,
+ touch_released: null,
+
+ // PRIVATE FUNCTIONS
+ // Writes `array`(array of integers) to memory at address `buffer`
+ writeArray32ToMemory: function(array, buffer) {
+ for (var i=0; i>2)] = array[i];
+ }
+ },
+ // Reads `length` integers from memory at address `buffer`
+ ReadArray32FromMemory: function(buffer, length) {
+ var res = [];
+ for (var i=0; i>2)]);
+ }
+ return res;
+ },
+ // Creates C arrays storing key statuses
+ post_install_keyboard: function() {
+ ALLEG.key = _malloc(4 * key.length);
+ ALLEG.pressed = _malloc(4 * pressed.length);
+ ALLEG.released = _malloc(4 * released.length);
+ },
+ // Creates C arrays storing touch structures
+ post_install_touch: function() {
+ // limitation: maximum 32 touch object
+ ALLEG.touch = _malloc(4*11*32);
+ ALLEG.touch_pressed = _malloc(4*11*32);
+ ALLEG.touch_released = _malloc(4*11*32);
+ },
+ // Deletes C arrays storing key statuses
+ post_remove_keyboard: function() {
+ _free(ALLEG.key);
+ _free(ALLEG.pressed);
+ _free(ALLEG.released);
+ ALLEG.key = null;
+ ALLEG.pressed = null;
+ ALLEG.released = null;
+ },
+ // Deletes C arrays storing touch structures
+ post_remove_touch: function() {
+ _free(ALLEG.touch);
+ _free(ALLEG.touch_pressed);
+ _free(ALLEG.touch_released);
+ ALLEG.touch = null;
+ ALLEG.touch_pressed = null;
+ ALLEG.touch_released = null;
+ },
+ // Writes JS key arrays to C memory
+ copy_key_statuses: function() {
+ ALLEG.writeArray32ToMemory(key, ALLEG.key);
+ ALLEG.writeArray32ToMemory(pressed, ALLEG.pressed);
+ ALLEG.writeArray32ToMemory(released, ALLEG.released);
+ },
+ // Writes JS touch arrays to C memory
+ copy_touch_structs: function() {
+ var write_touch_array = function(array, buffer) {
+ for (var i=0; (i>2)] = array[i].x;
+ HEAP32[((buffer + i*11*4 + 4)>>2)] = array[i].y;
+ HEAP32[((buffer + i*11*4 + 2*4)>>2)] = array[i].mx;
+ HEAP32[((buffer + i*11*4 + 3*4)>>2)] = array[i].my;
+ HEAP32[((buffer + i*11*4 + 4*4)>>2)] = array[i].px;
+ HEAP32[((buffer + i*11*4 + 5*4)>>2)] = array[i].py;
+ HEAP32[((buffer + i*11*4 + 6*4)>>2)] = array[i].sx;
+ HEAP32[((buffer + i*11*4 + 7*4)>>2)] = array[i].sy;
+ HEAP32[((buffer + i*11*4 + 8*4)>>2)] = array[i].id;
+ HEAP32[((buffer + i*11*4 + 9*4)>>2)] = array[i].age;
+ HEAP32[((buffer + i*11*4 + 10*4)>>2)] = array[i].dead;
+ }
+ };
+ write_touch_array(touch, ALLEG.touch);
+ write_touch_array(touch_pressed, ALLEG.touch_pressed);
+ write_touch_array(touch_released, ALLEG.touch_released);
+ },
+ // Creates `canvas` and `font` C globals
+ post_set_gfx_mode: function() {
+ ALLEG.bitmaps[0] = canvas;
+ ALLEG.fonts[0] = font;
+ ALLEG.canvas = ALLEG.alloc_pack_bitmap(0);
+ },
+ // Stores bitmap infomations in a C bitmap struct
+ pack_bitmap: function(handle) {
+ var addr = ALLEG.bitmap_addrs[handle];
+ setValue(addr, handle, "i32");
+ setValue(addr+4, ALLEG.bitmaps[handle].w, "i32");
+ setValue(addr+8, ALLEG.bitmaps[handle].h, "i32");
+ },
+ // Allocates and packs a bitmap for C
+ alloc_pack_bitmap: function(handle) {
+ var res = _malloc(3*4);
+ ALLEG.bitmap_addrs[handle] = res;
+ ALLEG.pack_bitmap(handle);
+ return res;
+ },
+ // Repacks every bitmaps (because bitmap loading is asynchronous) called by _ready
+ repack_bitmaps: function() {
+ for (var it=1; it
+
+
+ allegro.js examples
+
+
+
+
+
+
+
+
+
+ Download source!
+
+
\ No newline at end of file
diff --git a/examples/extouch.js b/examples/extouch.js
new file mode 100755
index 0000000..5c462cc
--- /dev/null
+++ b/examples/extouch.js
@@ -0,0 +1,33 @@
+var clouds,ball;
+
+function draw()
+{
+ clear_to_color(canvas, makecol(255, 255, 255));
+ stretch_blit(clouds,canvas,0,0,clouds.w,clouds.h,0,0,SCREEN_W,SCREEN_H);
+
+ for (var c=0; c