Skip to content

Commit fd47182

Browse files
committed
[emscripten] Initialise VFS from zip image.
1 parent d575e74 commit fd47182

6 files changed

Lines changed: 271 additions & 0 deletions

File tree

engine/engine-sources.gypi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,9 @@
737737
'src/em-preamble.js',
738738
'src/em-resolution.cpp',
739739
'src/em-stack.cpp',
740+
'src/em-standalone.h',
741+
'src/em-standalone.cpp',
742+
'src/em-standalone.js',
740743
'src/em-surface.h',
741744
'src/em-surface.cpp',
742745
'src/em-system.h',

engine/engine.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@
779779
'src/em-surface.js',
780780
'src/em-url.js',
781781
'boot',
782+
'src/em-standalone.js',
782783
],
783784

784785
'outputs':
@@ -799,6 +800,7 @@
799800
'src/em-event.js',
800801
'src/em-surface.js',
801802
'src/em-url.js',
803+
'src/em-standalone.js',
802804
],
803805
},
804806
],

engine/src/em-dc-mainloop.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
1818

1919
#include "em-dc-mainloop.h"
2020
#include "em-dc.h"
21+
#include "em-standalone.h"
2122
#include "em-util.h"
2223

2324
#include "globals.h"
@@ -170,6 +171,16 @@ X_init(int argc,
170171
}
171172
MCEmscriptenCreateArgCountVar(argc);
172173

174+
/* ---------- Initialise the filesystem */
175+
176+
/* We have to unpack the standalone data here rather than in
177+
* MCDispatch::startup() because we have to have font data
178+
* available in the VFS before calling X_open(). */
179+
if (!MCEmscriptenStandaloneUnpack())
180+
{
181+
return false;
182+
}
183+
173184
/* ---------- Continue booting... */
174185
return X_open(argc, argv, envp);
175186
}

engine/src/em-standalone.cpp

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/* -*-c++-*-
2+
3+
Copyright (C) 2003-2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
#include "prefix.h"
20+
21+
#include <foundation.h>
22+
23+
#include "em-standalone.h"
24+
25+
#include "globdefs.h"
26+
#include "parsedef.h"
27+
#include "scriptpt.h"
28+
#include "globals.h"
29+
#include "variable.h"
30+
#include "mcio.h"
31+
#include "osspec.h"
32+
#include "minizip.h"
33+
34+
/* ----------------------------------------------------------------
35+
* Functions implemented in em-standalone.js
36+
* ---------------------------------------------------------------- */
37+
38+
extern "C" int MCEmscriptenStandaloneGetDataJS(void **r_buffer, int *r_length);
39+
40+
/* ---------------------------------------------------------------- */
41+
42+
static bool
43+
__MCEmscriptenStandaloneUnpackWrite(void *context,
44+
const void *p_data,
45+
uint32_t p_data_length,
46+
uint32_t p_data_offset,
47+
uint32_t p_data_total)
48+
{
49+
IO_handle t_handle = static_cast<IO_handle>(context);
50+
const char *t_buffer = static_cast<const char *>(p_data);
51+
52+
/* Write the extracted data */
53+
return (IO_NORMAL == MCS_write(t_buffer + p_data_offset,
54+
p_data_length, 1, t_handle));
55+
}
56+
57+
static bool
58+
__MCEmscriptenStandaloneUnpackExtract(void *context,
59+
MCStringRef p_name)
60+
{
61+
bool t_success = true;
62+
63+
MCLog(" %@", p_name);
64+
65+
MCMiniZipRef t_zip = static_cast<MCMiniZipRef>(context);
66+
67+
/* If the zip file item is a directory, create it */
68+
if (MCStringEndsWithCString(p_name, (const char_t *) "/",
69+
kMCStringOptionCompareExact))
70+
{
71+
t_success = (MCS_mkdir(p_name) ||
72+
MCS_exists(p_name, false));
73+
}
74+
else
75+
{
76+
/* Otherwise, extract it to file */
77+
IO_handle t_handle = NULL;
78+
if (t_success)
79+
{
80+
t_handle = MCS_open(p_name, kMCOpenFileModeWrite, false, false, 0);
81+
t_success = (NULL != t_handle);
82+
}
83+
84+
if (t_success)
85+
{
86+
t_success = MCMiniZipExtractItem(t_zip, p_name,
87+
__MCEmscriptenStandaloneUnpackWrite,
88+
t_handle);
89+
}
90+
91+
if (t_handle != NULL)
92+
{
93+
MCS_close(t_handle);
94+
}
95+
}
96+
97+
return t_success;
98+
}
99+
100+
bool
101+
MCEmscriptenStandaloneUnpack()
102+
{
103+
/* Note that because this function is called before X_open(), it's
104+
* not possible to store diagnostic information in MCresult on
105+
* failure. */
106+
bool t_success = true;
107+
108+
MCLog("Unpacking standalone...");
109+
110+
/* Fetch downloaded standalone data */
111+
void *t_buffer = NULL;
112+
int t_buffer_len = -1;
113+
114+
if (t_success)
115+
{
116+
if (!MCEmscriptenStandaloneGetDataJS(&t_buffer, &t_buffer_len))
117+
{
118+
MCLog("failed to download standalone data");
119+
t_success = false;
120+
}
121+
}
122+
123+
/* Unpack the VFS image to the filesystem root */
124+
MCMiniZipRef t_zip = NULL;
125+
126+
if (t_success)
127+
{
128+
t_success = MCS_setcurdir(MCSTR("/"));
129+
}
130+
131+
if (t_success)
132+
{
133+
MCAssert(0 < t_buffer_len);
134+
MCAssert(NULL != t_buffer);
135+
if (!MCMiniZipOpen(t_buffer, t_buffer_len, t_zip))
136+
{
137+
MCLog("failed to open standalone data as zip archive");
138+
t_success = false;
139+
}
140+
}
141+
142+
if (t_success)
143+
{
144+
if (!MCMiniZipListItems(t_zip,
145+
__MCEmscriptenStandaloneUnpackExtract,
146+
t_zip))
147+
{
148+
MCLog("failed to extract standalone files");
149+
t_success = false;
150+
}
151+
}
152+
153+
/* ---------- 4. Cleanup */
154+
if (NULL != t_zip)
155+
{
156+
MCMiniZipClose(t_zip);
157+
}
158+
if (NULL != t_buffer)
159+
{
160+
free(t_buffer);
161+
}
162+
163+
return t_success;
164+
}

engine/src/em-standalone.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* -*-c++-*-
2+
3+
Copyright (C) 2003-2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
#ifndef __MC_EMSCRIPTEN_STANDALONE_H__
20+
#define __MC_EMSCRIPTEN_STANDALONE_H__
21+
22+
/* Unpack the standalone data into the filesystem. Returns true on
23+
* success. */
24+
bool MCEmscriptenStandaloneUnpack(void);
25+
26+
#endif /* !__MC_EMSCRIPTEN_STANDALONE_H__ */

engine/src/em-standalone.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/* -*-Javascript-*-
2+
3+
Copyright (C) 2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
mergeInto(LibraryManager.library, {
20+
21+
// Return the standalone capsule data. This should have been
22+
// downloaded before the engine started (see em-preamble.js).
23+
//
24+
// bufferPtr -> pointer at which to store the data buffer
25+
// lengthPtr -> pointer at which to store the data length
26+
//
27+
// Returns false if for some reason the standalone capsule is
28+
// missing.
29+
MCEmscriptenStandaloneGetDataJS: function(bufferPtr, lengthPtr) {
30+
31+
// Check that the data was downloaded
32+
var xhr = Module['livecodeStandaloneRequest'];
33+
34+
if (!xhr ||
35+
!xhr.response ||
36+
typeof xhr.response !== 'object' ||
37+
!xhr.response.byteLength) {
38+
console.error('LiveCode standalone data is missing!');
39+
return false;
40+
}
41+
42+
// Copy the data into the C++ heap
43+
// FIXME maybe this needs a helper function in LiveCodeUtil
44+
var dataStack = new Uint8Array(xhr.response);
45+
var dataLength = dataStack.length;
46+
var dataPtr = Module._malloc(dataLength *
47+
dataStack.BYTES_PER_ELEMENT);
48+
var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr,
49+
dataLength);
50+
dataHeap.set(dataStack);
51+
52+
// Set the return parameters
53+
{{{ makeSetValue('bufferPtr', '0', 'dataPtr', 'i32') }}};
54+
{{{ makeSetValue('lengthPtr', '0', 'dataLength', 'i32') }}};
55+
56+
return true;
57+
},
58+
});
59+
60+
/*
61+
* Local Variables:
62+
* tab-width: 4
63+
* indent-tabs-mode: t
64+
* End:
65+
*/

0 commit comments

Comments
 (0)