In hindsight my emscripten-ifdef (70d416a8f63f) is nonsense.
As fpcrtl_glShaderSource() would not be defined and lead to compiling issues.
So either it's 3 ifdefs (in pas2cRedo, pas2cSystem and misc.c),
in order to toggle between fpcrtl_ and the native function,
or alternatively have no ifdef for it at all.
I'm going with none at all,
which means emscripten will compile with the original (const) function prototype,
being wrapped by the fpcrtl_ function, same as non-emscripten builds.
#include "engine_instance.h"
#include <QDebug>
#include <QLibrary>
#include <QOpenGLFunctions>
#include <QSurface>
static QOpenGLContext* currentOpenglContext = nullptr;
extern "C" void (*getProcAddress(const char* fn))() {
if (!currentOpenglContext)
return nullptr;
else
return currentOpenglContext->getProcAddress(fn);
}
EngineInstance::EngineInstance(const QString& libraryPath, QObject* parent)
: QObject(parent) {
QLibrary hwlib(libraryPath);
if (!hwlib.load())
qWarning() << "Engine library not found" << hwlib.errorString();
hedgewars_engine_protocol_version =
reinterpret_cast<Engine::hedgewars_engine_protocol_version_t*>(
hwlib.resolve("hedgewars_engine_protocol_version"));
start_engine =
reinterpret_cast<Engine::start_engine_t*>(hwlib.resolve("start_engine"));
generate_preview = reinterpret_cast<Engine::generate_preview_t*>(
hwlib.resolve("generate_preview"));
dispose_preview = reinterpret_cast<Engine::dispose_preview_t*>(
hwlib.resolve("dispose_preview"));
cleanup = reinterpret_cast<Engine::cleanup_t*>(hwlib.resolve("cleanup"));
send_ipc = reinterpret_cast<Engine::send_ipc_t*>(hwlib.resolve("send_ipc"));
read_ipc = reinterpret_cast<Engine::read_ipc_t*>(hwlib.resolve("read_ipc"));
setup_current_gl_context =
reinterpret_cast<Engine::setup_current_gl_context_t*>(
hwlib.resolve("setup_current_gl_context"));
render_frame =
reinterpret_cast<Engine::render_frame_t*>(hwlib.resolve("render_frame"));
advance_simulation = reinterpret_cast<Engine::advance_simulation_t*>(
hwlib.resolve("advance_simulation"));
move_camera =
reinterpret_cast<Engine::move_camera_t*>(hwlib.resolve("move_camera"));
simple_event =
reinterpret_cast<Engine::simple_event_t*>(hwlib.resolve("simple_event"));
long_event =
reinterpret_cast<Engine::long_event_t*>(hwlib.resolve("long_event"));
positioned_event = reinterpret_cast<Engine::positioned_event_t*>(
hwlib.resolve("positioned_event"));
m_isValid = hedgewars_engine_protocol_version && start_engine &&
generate_preview && dispose_preview && cleanup && send_ipc &&
read_ipc && setup_current_gl_context && render_frame &&
advance_simulation && move_camera && simple_event && long_event &&
positioned_event;
emit isValidChanged(m_isValid);
if (isValid()) {
qDebug() << "Loaded engine library with protocol version"
<< hedgewars_engine_protocol_version();
m_instance = start_engine();
} else {
qDebug("Engine library load failed");
}
}
EngineInstance::~EngineInstance() {
if (m_isValid) cleanup(m_instance);
}
void EngineInstance::sendConfig(const GameConfig& config) {
for (auto b : config.config()) {
send_ipc(m_instance, reinterpret_cast<uint8_t*>(b.data()),
static_cast<size_t>(b.size()));
}
}
void EngineInstance::advance(quint32 ticks) {
advance_simulation(m_instance, ticks);
}
void EngineInstance::moveCamera(const QPoint& delta) {
move_camera(m_instance, delta.x(), delta.y());
}
void EngineInstance::simpleEvent(Engine::SimpleEventType event_type) {
simple_event(m_instance, event_type);
}
void EngineInstance::longEvent(Engine::LongEventType event_type,
Engine::LongEventState state) {
long_event(m_instance, event_type, state);
}
void EngineInstance::positionedEvent(Engine::PositionedEventType event_type,
qint32 x, qint32 y) {
positioned_event(m_instance, event_type, x, y);
}
void EngineInstance::renderFrame() { render_frame(m_instance); }
void EngineInstance::setOpenGLContext(QOpenGLContext* context) {
currentOpenglContext = context;
auto size = context->surface()->size();
setup_current_gl_context(m_instance, static_cast<quint16>(size.width()),
static_cast<quint16>(size.height()),
&getProcAddress);
}
QImage EngineInstance::generatePreview() {
Engine::PreviewInfo pinfo;
generate_preview(m_instance, &pinfo);
QVector<QRgb> colorTable;
colorTable.resize(256);
for (int i = 0; i < 256; ++i) colorTable[i] = qRgba(255, 255, 0, i);
QImage previewImage(pinfo.land, static_cast<int>(pinfo.width),
static_cast<int>(pinfo.height), QImage::Format_Indexed8);
previewImage.setColorTable(colorTable);
// Cannot use it here, since QImage refers to original bytes
// dispose_preview(m_instance);
return previewImage;
}
bool EngineInstance::isValid() const { return m_isValid; }