diff options
| -rw-r--r-- | emcc.c | 23 | ||||
| -rw-r--r-- | emcclib.js | 9 | ||||
| -rw-r--r-- | emccpre.js | 21 |
3 files changed, 37 insertions, 16 deletions
@@ -99,6 +99,8 @@ extern void js_dialog_launch(void); extern void js_dialog_cleanup(void); extern void js_focus_canvas(void); +extern bool js_savefile_read(void *buf, int len); + /* * These functions are called from JavaScript, so their prototypes * need to be kept in sync with emccpre.js. @@ -112,7 +114,7 @@ void timer_callback(double tplus); void command(int n); char *get_save_file(void); void free_save_file(char *buffer); -void load_game(const char *buffer, int len); +void load_game(void); void dlg_return_sval(int index, const char *val); void dlg_return_ival(int index, int val); void resize_puzzle(int w, int h); @@ -904,23 +906,18 @@ struct savefile_read_ctx { static bool savefile_read(void *vctx, void *buf, int len) { - struct savefile_read_ctx *ctx = (struct savefile_read_ctx *)vctx; - if (ctx->len_remaining < len) - return false; - memcpy(buf, ctx->buffer, len); - ctx->len_remaining -= len; - ctx->buffer += len; - return true; + return js_savefile_read(buf, len); } -void load_game(const char *buffer, int len) +void load_game() { - struct savefile_read_ctx ctx; const char *err; - ctx.buffer = buffer; - ctx.len_remaining = len; - err = midend_deserialise(me, savefile_read, &ctx); + /* + * savefile_read_callback in JavaScript was set up by our caller + * as a closure that knows what file we're loading. + */ + err = midend_deserialise(me, savefile_read, NULL); if (err) { js_error_box(err); @@ -783,5 +783,14 @@ mergeInto(LibraryManager.library, { */ js_focus_canvas: function() { onscreen_canvas.focus(); + }, + + /* + * bool js_savefile_read(void *buf, int len); + * + * Read len bytes from the save file that we're currently loading. + */ + js_savefile_read: function(buf, len) { + return savefile_read_callback(buf, len); } }); @@ -135,6 +135,12 @@ var dlg_return_funcs = null; // pass back the final value in each dialog control. var dlg_return_sval, dlg_return_ival; +// Callback for reading from a savefile. This will be filled in with +// a suitable closure by the JS loading code and called by +// js_savefile_read(). This assumes that only one file can be in the +// process of loading at a time. +var savefile_read_callback; + // The <ul> object implementing the game-type drop-down, and a list of // the sub-lists inside it. Used by js_add_preset(). var gametypelist = document.getElementById("gametype"); @@ -423,7 +429,7 @@ function initPuzzle() { // 'number' is used for C pointers var get_save_file = Module.cwrap('get_save_file', 'number', []); var free_save_file = Module.cwrap('free_save_file', 'void', ['number']); - var load_game = Module.cwrap('load_game', 'void', ['array', 'number']); + var load_game = Module.cwrap('load_game', 'void', []); if (save_button) save_button.onclick = function(event) { if (dlg_dimmer === null) { @@ -457,8 +463,17 @@ function initPuzzle() { var file = input.files.item(0); var reader = new FileReader(); reader.addEventListener("loadend", function() { - var array = new Uint8Array(reader.result); - load_game(array, array.length); + var pos = 0; + savefile_read_callback = function(buf, len) { + if (pos + len > reader.result.byteLength) + return false; + writeArrayToMemory( + new Int8Array(reader.result, pos, len), buf); + pos += len; + return true; + } + load_game(); + savefile_read_callback = null; }); reader.readAsArrayBuffer(file); } |