mattiasgustavsson / dos-like

Engine for making things with a MS-DOS feel, but for modern platforms
Other
1k stars 49 forks source link

LuaJIT bindings #28

Closed LJNIC closed 2 years ago

LJNIC commented 2 years ago

Hello, I am trying to get some bindings for this going with LuaJIT. I've compiled dos.h using this:

gcc -shared -fPIC -o dos.so source/dos.c `sdl2-config --libs --cflags` -lGLEW -lGL -lm -lpthread

and I am trying to test some initial graphics functions with the following LuaJIT code:

local ffi = require "ffi"
ffi.cdef[[
   void circle( int x, int y, int r );
   enum videomode_t {
    videomode_40x25_8x8,
    videomode_40x25_9x16,
    videomode_80x25_8x8,
    videomode_80x25_8x16,
    videomode_80x25_9x16,
    videomode_80x43_8x8,
    videomode_80x50_8x8,
    videomode_320x200,
    videomode_320x240,
    videomode_320x400,
    videomode_640x200,
    videomode_640x350,
    videomode_640x400,
    videomode_640x480,
   };

   void setvideomode( enum videomode_t mode );
   void setdoublebuffer( int enabled );
]]

local dos = ffi.load("~/dos-like/libdos.so", true)

This works, but trying to call any dos functions fails with a segfault, assumedly because the initialization stuff isn't being called. Do you have any suggestions for connecting LuaJIT to the app_proc function?

mattiasgustavsson commented 2 years ago

I don’t really know anything about LuaJIT, so not sure if I can help much. But dos-like is not designed to be used as a dynamic library, it definitely needs to have the main function called, as both the initialization and main loop happens there. I don’t know if LuaJIT poses any particular linitations, but in the past I have used regular Lua and its C integration api, and for that I would recommend putting the Lua code in the main function, have it set the environment up and expose engine functions using the C api, and at that point all the dos-like system is already up and running. I don’t know if that is possible with LuaJIT though, in the way it is with regular Lua C interface

LJNIC commented 2 years ago

Thank you for the swift response. I gave up on Lua and instead switched to Nim, which worked great! I did the setup and main loop in C, and defined a Nim function that gets called every time through the loop.

#include <stdlib.h>
#include <string.h>
#include "dos.h"
#include "term.h"

int main(int argc, char* argv[]) {
   NimMain();
   setvideomode(videomode_320x200);

   unsigned char* screen = screenbuffer();

   while(!shuttingdown()) {
      waitvbl();
      memset(screen, 0, screenwidth() * screenheight());

      if (tick() != 0) break;
   }

   return 0;
}
proc circle(x, y, r: cint) {.importc.}

proc tick(): cint {.exportc.} =
  circle(50, 50, 30)
  return 0
mattiasgustavsson commented 2 years ago

Yeah, that looks like a good way of doing it 🙂