#include "oboy.h" #include #include #include #include #include #include #include #include #include #include OBoy::OBoy(QObject *parent) : QObject(parent) { const QStringList args = QCoreApplication::arguments(); if (args.size() > 1) { const QUrl path = QUrl::fromLocalFile(args.at(1)); load(path); } } 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; } // https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html // http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/calling_ocaml.html QString OBoy::name() const { CAMLparam0(); static value * closure_f = fetch_caml_callback("oboy_name"); if (closure_f == nullptr) { CAMLdrop; return QString(""); } const char *str = String_val(caml_callback(*closure_f, Val_unit)); CAMLdrop; return QString(str); } QString OBoy::version() const { CAMLparam0(); static value * closure_f = fetch_caml_callback("oboy_version"); if (closure_f == nullptr) { CAMLdrop; return QString(""); } const char *str = String_val(caml_callback(*closure_f, Val_unit)); CAMLdrop; return QString(str); } bool OBoy::load(const QUrl &path) { CAMLparam0(); CAMLlocal1(ocaml_path) ; static value * closure_f = fetch_caml_callback("oboy_load"); if (closure_f == nullptr) { CAMLdrop; return false; } const QString local_path = path.toLocalFile(); const QByteArray ba = local_path.toLocal8Bit(); ocaml_path = caml_copy_string_of_os(ba.data()); _loaded = Bool_val(caml_callback(*closure_f, ocaml_path)); this->loadedChanged(_loaded); CAMLdrop; return _loaded; } bool OBoy::loaded() const { return _loaded; } QImage OBoy::backgroundMap(int index) const { CAMLparam0(); CAMLlocal1(ocaml_index); ocaml_index = index; static value * closure_f = fetch_caml_callback("oboy_bg_map"); if (closure_f == nullptr) { CAMLdrop; return QImage(0, 0, QImage::Format_Indexed8); } const auto bg_array = Caml_ba_array_val(caml_callback(*closure_f, Val_int(ocaml_index))); const auto bg_raw_data = static_cast(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 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; }