[ion/simulator] Misc build fixes

This commit is contained in:
Romain Goyet
2019-09-25 15:41:23 +02:00
committed by EmilieNumworks
parent 5796a0d930
commit 6082a011ee
12 changed files with 28 additions and 412 deletions

View File

@@ -1,15 +0,0 @@
executables += epsilon.packed simulator
extensions += zip
$(BUILD_DIR)/epsilon.packed.js: LDFLAGS += --memory-init-file 0
$(BUILD_DIR)/epsilon.packed.js: $(call object_for,$(all_epsilon_default_src))
$(BUILD_DIR)/simulator.zip: $(BUILD_DIR)/epsilon.packed.js
@rm -rf $(basename $@)
@mkdir -p $(basename $@)
@cp $^ $(basename $@)/epsilon.js
@cp ion/src/emscripten/background.jpg $(basename $@)/
@cp ion/src/emscripten/simulator.html $(basename $@)/
@echo "ZIP $@"
@zip -r -9 -j $@ $(basename $@) > /dev/null
@rm -rf $(basename $@)

View File

@@ -0,0 +1,2 @@
$(BUILD_DIR)/epsilon.packed.js: LDFLAGS += --memory-init-file 0
$(BUILD_DIR)/epsilon.packed.js: $(call object_for,$(all_epsilon_default_src))

View File

@@ -4,7 +4,8 @@ ion_src += $(addprefix ion/src/simulator/android/src/cpp/, \
)
ion_src += $(addprefix ion/src/simulator/shared/, \
language_dummy.cpp \
dummy/callback.cpp \
dummy/language.cpp \
)
$(call object_for,ion/src/simulator/shared/main.cpp) : SFLAGS += -DEPSILON_SDL_FULLSCREEN=1

View File

@@ -4,6 +4,7 @@ ion_src += $(addprefix ion/src/simulator/macos/, \
ion_src += $(addprefix ion/src/simulator/shared/, \
apple/language.m \
dummy/callback.cpp \
dummy/telemetry.cpp \
)

View File

@@ -19,3 +19,15 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
dummy/language.cpp \
dummy/telemetry.cpp \
)
DEFAULT = $(BUILD_DIR)/simulator.zip
$(BUILD_DIR)/simulator.zip: $(BUILD_DIR)/epsilon.packed.js
@rm -rf $(basename $@)
@mkdir -p $(basename $@)
@cp $^ $(basename $@)/epsilon.js
@cp ion/src/simulator/assets/background.jpg $(basename $@)/
@cp ion/src/simulator/web/simulator.html $(basename $@)/
$(call rule_label,ZIP)
@zip -r -9 -j $@ $(basename $@) > /dev/null
@rm -rf $(basename $@)

View File

@@ -1,67 +0,0 @@
#include "display.h"
#include <kandinsky.h>
extern "C" {
#include <SDL/SDL.h>
#include <assert.h>
#include <stdlib.h>
#include <emscripten.h>
}
SDL_Surface * screen = nullptr;
static KDColor sPixels[Ion::Display::Width*Ion::Display::Height];
static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height));
namespace Ion {
namespace Display {
void pushRect(KDRect r, const KDColor * pixels) {
sFrameBuffer.pushRect(r, pixels);
}
void pushRectUniform(KDRect r, KDColor c) {
sFrameBuffer.pushRectUniform(r, c);
}
void pullRect(KDRect r, KDColor * pixels) {
sFrameBuffer.pullRect(r, pixels);
}
}
}
namespace Ion {
namespace Display {
namespace Emscripten {
void init() {
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(Ion::Display::Width, Ion::Display::Height, 32, SDL_SWSURFACE);
EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;");
}
void refresh() {
// Simply push the whole buffer to the surface
if (SDL_MUSTLOCK(screen)) {
SDL_LockSurface(screen);
}
int pixelNumber = 0;
for (int j=0; j<Ion::Display::Height; j++) {
for (int i=0; i<Ion::Display::Width; i++) {
KDColor c = sPixels[pixelNumber++];
*((Uint32*)screen->pixels + j * Ion::Display::Width + i) = SDL_MapRGB(screen->format, c.red(), c.green(), c.blue());
}
}
if (SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}
SDL_UpdateRect(screen, 0, 0, Ion::Display::Width, Ion::Display::Height);
// notify screen rendring
EM_ASM(if (typeof Module.onDisplayRefresh === "function") { Module.onDisplayRefresh(); });
}
}
}
}

View File

@@ -1,17 +0,0 @@
#ifndef ION_EMSCRIPTEN_DISPLAY_H
#define ION_EMSCRIPTEN_DISPLAY_H
#include <ion/display.h>
namespace Ion {
namespace Display {
namespace Emscripten {
void init();
void refresh();
}
}
}
#endif

View File

@@ -1,258 +0,0 @@
#include <ion/events.h>
#include "events_keyboard.h"
#include "display.h"
extern "C" {
#include <SDL/SDL.h>
}
#include <emscripten.h>
template<typename T, int N>
class Queue {
public:
Queue() : m_first(&m_elements[0]), m_last(&m_elements[0]) {}
int size() {
if (m_last >= m_first) {
return m_last - m_first;
} else {
return m_last - (m_first - N);
}
}
void enqueue(T element) {
if (size() > N) {
// Queue is full
return;
}
*m_last = element;
m_last = next(m_last);
}
T dequeue() {
if (size() <= 0) {
// Dequeueing an empty queue
return T();
}
T e = *m_first;
m_first = next(m_first);
return e;
}
private:
T * next(T * p) {
if (p >= m_elements + N) {
return m_elements;
} else {
return p + 1;
}
}
T * m_first;
T * m_last;
T m_elements[N];
};
static Queue<Ion::Events::Event, 1024> sEventQueue;
Ion::Keyboard::State sKeyboardState;
void IonEventsEmscriptenKeyDown(int keyNumber) {
Ion::Keyboard::Key key = static_cast<Ion::Keyboard::Key>(keyNumber);
sKeyboardState.setKey(key);
/* Note: This uses the *current* modifier state to generate the event. If some
* other modifiers were in the queue before, those won't be taken into account
* when the event corresponding to this key is dequeued.
* In practice, this should not happen because we push keys one by one. */
Ion::Events::Event event = Ion::Events::Event(key, Ion::Events::isShiftActive(), Ion::Events::isAlphaActive());
sEventQueue.enqueue(event);
}
void IonEventsEmscriptenKeyUp(int keyNumber) {
Ion::Keyboard::Key key = static_cast<Ion::Keyboard::Key>(keyNumber);
sKeyboardState.clearKey(key);
}
void IonEventsEmscriptenPushEvent(int eventNumber) {
sEventQueue.enqueue(Ion::Events::Event(eventNumber));
}
Ion::Keyboard::State Ion::Keyboard::scan() {
/* The following call to emscripten_sleep gives the JS VM a chance to do a run
* loop iteration. This in turns gives the browser an opportunity to call the
* IonEventsEmscriptenPushKey function, therefore modifying the sKeyboardState
* global variable before it is returned by this Ion::Keyboard::scan.
* On Emterpreter-async, emscripten_sleep is actually a wrapper around the JS
* function setTimeout, which can be called with a value of zero. Doing so
* puts the callback at the end of the queue of callbacks to be processed. */
emscripten_sleep(0);
/* Grab this opporunity to refresh the display. In practice, this routine is
* called from micropython_port_vm_hook_loop once in a while, so this gives us
* an opportunity to refresh the display during the execution of a
* long-running Python script. */
Ion::Display::Emscripten::refresh();
return sKeyboardState;
}
namespace Ion {
namespace Events {
static constexpr Event sEventForASCIICharAbove32[95] = {
Space, Exclamation, DoubleQuotes, None, None, None, None, None,
LeftParenthesis, RightParenthesis, Multiplication, Plus, Comma, Minus, Dot, Division,
Zero, One, Two, Three, Four, Five, Six, Seven,
Eight, Nine, Colon, SemiColon, Lower, Equal, Greater, Question,
None, UpperA, UpperB, UpperC, UpperD, UpperE, UpperF, UpperG,
UpperH, UpperI, UpperJ, UpperK, UpperL, UpperM, UpperN, UpperO,
UpperP, UpperQ, UpperR, UpperS, UpperT, UpperU, UpperV, UpperW,
UpperX, UpperY, UpperZ, LeftBracket, None, RightBracket, Power, Underscore,
None, LowerA, LowerB, LowerC, LowerD, LowerE, LowerF, LowerG,
LowerH, LowerI, LowerJ, LowerK, LowerL, LowerM, LowerN, LowerO,
LowerP, LowerQ, LowerR, LowerS, LowerT, LowerU, LowerV, LowerW,
LowerX, LowerY, LowerZ, LeftBrace, None, RightBrace, None
};
static bool sleepWithTimeout(int duration, int * timeout) {
if (*timeout >= duration) {
emscripten_sleep(duration);
*timeout -= duration;
return false;
} else {
emscripten_sleep(*timeout);
*timeout = 0;
return true;
}
}
static Event eventFromSDLEvent(SDL_Event sdlEvent) {
if (sdlEvent.type != SDL_KEYDOWN) {
return None;
}
if (sdlEvent.key.keysym.mod & KMOD_CTRL) {
switch (sdlEvent.key.keysym.sym) {
case SDLK_BACKSPACE:
return Clear;
case SDLK_x:
return Cut;
case SDLK_c:
return Copy;
case SDLK_v:
return Paste;
}
}
if (sdlEvent.key.keysym.mod & KMOD_ALT) {
if (sdlEvent.key.keysym.mod & KMOD_SHIFT) {
switch (sdlEvent.key.keysym.sym) {
case SDLK_s:
return Arcsine;
case SDLK_c:
return Arccosine;
case SDLK_t:
return Arctangent;
}
}
switch (sdlEvent.key.keysym.sym) {
case SDLK_ESCAPE:
return Home;
case SDLK_RETURN:
return OK;
case SDLK_v:
return Var;
case SDLK_BACKSPACE:
return Clear;
case SDLK_x:
return Exp;
case SDLK_n:
return Ln;
case SDLK_l:
return Log;
case SDLK_i:
return Imaginary;
case SDLK_EQUALS:
return Sto;
case SDLK_s:
return Sine;
case SDLK_c:
return Cosine;
case SDLK_t:
return Tangent;
case SDLK_p:
return Pi;
case SDLK_r:
return Sqrt;
case SDLK_2:
return Square;
case SDLK_e:
return EE;
case SDLK_a:
return Ans;
}
}
switch(sdlEvent.key.keysym.sym) {
case SDLK_UP:
return Up;
case SDLK_DOWN:
return Down;
case SDLK_LEFT:
return Left;
case SDLK_RIGHT:
return Right;
case SDLK_RETURN:
return EXE;
case SDLK_ESCAPE:
return Back;
case SDLK_TAB:
return Toolbox;
case SDLK_BACKSPACE:
return Backspace;
}
if (sdlEvent.key.keysym.unicode >= 32 && sdlEvent.key.keysym.unicode < 127) {
return sEventForASCIICharAbove32[sdlEvent.key.keysym.unicode-32];
}
return None;
}
Event getEvent(int * timeout) {
// If multiple events are in the queue, don't waste time refreshing the display
if (sEventQueue.size() <= 1) {
Ion::Display::Emscripten::refresh();
}
while (true) {
// Look up events in the queue
if (sEventQueue.size() > 0) {
Event event = sEventQueue.dequeue();
if (event.isKeyboardEvent()) {
updateModifiersFromEvent(event);
}
return event;
}
// Or directly from browser events, converted to SDL events by Emscripten
SDL_Event sdlEvent;
SDL_PollEvent(&sdlEvent);
Event eventFromSDL = eventFromSDLEvent(sdlEvent);
if (eventFromSDL != None) {
return eventFromSDL;
}
if (sleepWithTimeout(10, timeout)) {
return None;
}
}
return None;
}
}
}
namespace Ion {
namespace Events {
namespace Emscripten {
void init() {
SDL_EnableUNICODE(1); // We're using Unicode values from Keyboard input
}
}
}
}

View File

@@ -1,22 +0,0 @@
#ifndef ION_EMSCRIPTEN_EVENTS_KEYBOARD_H
#define ION_EMSCRIPTEN_EVENTS_KEYBOARD_H
#include <ion/events.h>
extern "C" {
void IonEventsEmscriptenKeyUp(int keyNumber);
void IonEventsEmscriptenKeyDown(int keyNumber);
void IonEventsEmscriptenPushEvent(int eventNumber);
}
namespace Ion {
namespace Events {
namespace Emscripten {
void init();
}
}
}
#endif

View File

@@ -0,0 +1,9 @@
#include <ion.h>
extern "C" const char * IonSoftwareVersion() {
return Ion::softwareVersion();
}
extern "C" const char * IonPatchLevel() {
return Ion::patchLevel();
}

View File

@@ -1,32 +0,0 @@
#include <ion.h>
#include "display.h"
#include "events_keyboard.h"
#include <emscripten.h>
#include <stdlib.h>
extern "C" {
const char * IonSoftwareVersion();
const char * IonPatchLevel();
}
const char * IonSoftwareVersion() { return Ion::softwareVersion(); }
const char * IonPatchLevel() { return Ion::patchLevel(); }
int main(int argc, char * argv[]) {
Ion::Display::Emscripten::init();
Ion::Events::Emscripten::init();
// Set the seed for random using the current time
srand(emscripten_get_now());
ion_main(argc, argv);
return 0;
}
void Ion::Timing::msleep(uint32_t ms) {
emscripten_sleep(ms);
}
void Ion::Timing::usleep(uint32_t us) {
emscripten_sleep(us/1000);
}

View File

@@ -3,7 +3,9 @@ ion_src += $(addprefix ion/src/simulator/windows/, \
language.cpp \
resources.rc \
)
ion_src += $(addprefix ion/src/simulator/shared/, \
dummy/callback.cpp \
dummy/telemetry.cpp \
)