oboy/src/qt/oboy.cpp

130 lines
3.1 KiB
C++
Raw Normal View History

2019-05-11 20:00:33 +02:00
#include "oboy.h"
2019-07-12 13:39:49 +02:00
#include <QCoreApplication>
2019-07-16 10:04:05 +02:00
#include <QUrl>
#include <QtGlobal>
2019-07-05 14:20:17 +02:00
2019-05-11 21:13:09 +02:00
#include <caml/mlvalues.h>
#include <caml/callback.h>
2019-05-15 14:03:53 +02:00
#include <caml/alloc.h>
2019-07-05 14:20:17 +02:00
#include <caml/bigarray.h>
2019-06-06 14:39:11 +02:00
#include <caml/memory.h>
2019-05-15 14:03:53 +02:00
#include <caml/misc.h>
#include <caml/osdeps.h>
2019-05-11 21:13:09 +02:00
2019-05-11 20:00:33 +02:00
OBoy::OBoy(QObject *parent) : QObject(parent)
{
2019-07-12 13:39:49 +02:00
const QStringList args = QCoreApplication::arguments();
if (args.size() > 1) {
2019-07-16 10:04:05 +02:00
const QUrl path = QUrl::fromLocalFile(args.at(1));
load(path);
2019-07-12 13:39:49 +02:00
}
2019-07-05 14:20:17 +02:00
}
2019-05-11 20:00:33 +02:00
2019-07-05 14:20:17 +02:00
value *fetch_caml_callback(const char *name) {
value * closure_f = caml_named_value(name);
if (closure_f == nullptr) {
qFatal("Cannot find OCaml function: %s", name);
}
return closure_f;
2019-05-11 20:00:33 +02:00
}
2019-05-11 21:13:09 +02:00
2019-06-06 14:39:11 +02:00
// https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html
// http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/calling_ocaml.html
2019-05-11 21:13:09 +02:00
QString OBoy::name() const
{
2019-06-06 14:39:11 +02:00
CAMLparam0();
2019-07-05 14:20:17 +02:00
static value * closure_f = fetch_caml_callback("oboy_name");
2019-05-11 21:13:09 +02:00
if (closure_f == nullptr) {
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-05-11 21:13:09 +02:00
return QString("<Unreachable>");
}
const char *str = String_val(caml_callback(*closure_f, Val_unit));
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-05-11 21:13:09 +02:00
return QString(str);
}
QString OBoy::version() const
{
2019-06-06 14:39:11 +02:00
CAMLparam0();
2019-07-05 14:20:17 +02:00
static value * closure_f = fetch_caml_callback("oboy_version");
2019-05-11 21:13:09 +02:00
if (closure_f == nullptr) {
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-05-11 21:13:09 +02:00
return QString("<Unreachable>");
}
const char *str = String_val(caml_callback(*closure_f, Val_unit));
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-05-11 21:13:09 +02:00
return QString(str);
}
2019-05-15 14:03:53 +02:00
2019-07-16 10:04:05 +02:00
bool OBoy::load(const QUrl &path) {
2019-06-06 14:39:11 +02:00
CAMLparam0();
CAMLlocal1(ocaml_path) ;
2019-07-05 14:20:17 +02:00
static value * closure_f = fetch_caml_callback("oboy_load");
2019-05-15 14:03:53 +02:00
if (closure_f == nullptr) {
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-05-15 14:03:53 +02:00
return false;
}
2019-07-16 10:04:05 +02:00
const QString local_path = path.toLocalFile();
const QByteArray ba = local_path.toLocal8Bit();
2019-06-06 14:39:11 +02:00
ocaml_path = caml_copy_string_of_os(ba.data());
2019-05-15 14:03:53 +02:00
2019-06-07 14:25:34 +02:00
_loaded = Bool_val(caml_callback(*closure_f, ocaml_path));
this->loadedChanged(_loaded);
2019-06-06 14:39:11 +02:00
CAMLdrop;
2019-06-07 14:25:34 +02:00
return _loaded;
}
bool OBoy::loaded() const
{
return _loaded;
2019-05-15 14:03:53 +02:00
}
2019-07-05 14:20:17 +02:00
2019-07-14 19:11:40 +02:00
QImage OBoy::backgroundMap(int index) const
2019-07-05 14:20:17 +02:00
{
CAMLparam0();
2019-07-14 19:11:40 +02:00
CAMLlocal1(ocaml_index);
ocaml_index = index;
2019-07-05 14:20:17 +02:00
static value * closure_f = fetch_caml_callback("oboy_bg_map");
if (closure_f == nullptr) {
CAMLdrop;
return QImage(0, 0, QImage::Format_Indexed8);
}
2019-07-14 19:11:40 +02:00
const auto bg_array = Caml_ba_array_val(caml_callback(*closure_f, Val_int(ocaml_index)));
2019-07-05 14:20:17 +02:00
const auto bg_raw_data = static_cast<caml_ba_uint8 *>(bg_array->data);
Q_ASSERT(bg_array->num_dims == 2);
Q_ASSERT(bg_array->flags & CAML_BA_UINT8);
const int width = bg_array->dim[0];
const int height = bg_array->dim[1];
QImage img(width, height, QImage::Format_Indexed8);
QVector<QRgb> green_palette = {
qRgb(15, 56, 15),
qRgb(48, 98, 48),
qRgb(139, 172, 15),
qRgb(155, 188, 15),
};
img.setColorTable(green_palette);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
img.setPixel(x, y, bg_raw_data[y * width + x] % 4);
}
}
CAMLdrop;
return img;
}