Skip to content

Commit

Permalink
Receive GlkOte events
Browse files Browse the repository at this point in the history
Fix more WASM ABI issues
  • Loading branch information
curiousdannii committed Mar 4, 2024
1 parent 9eb640a commit c8d0354
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 17 deletions.
16 changes: 13 additions & 3 deletions remglk/src/glkapi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod windows;

use std::cmp::min;
use std::mem;
use mem::MaybeUninit;
use std::ops::DerefMut;
use std::str;
use std::time::SystemTime;
Expand Down Expand Up @@ -1563,8 +1564,16 @@ where S: Default + GlkSystem {

pub fn retain_array(&self, buf: &GlkBuffer) -> DispatchRock {
match buf {
GlkBuffer::U8(buf) => (self.retain_array_callbacks_u8.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Cn".as_ptr()),
GlkBuffer::U32(buf) => (self.retain_array_callbacks_u32.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Iu".as_ptr()),
GlkBuffer::U8(buf) => {
let mut disprock: MaybeUninit<DispatchRock> = MaybeUninit::uninit();
(self.retain_array_callbacks_u8.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Cn".as_ptr(), disprock.as_mut_ptr());
unsafe {disprock.assume_init()}
},
GlkBuffer::U32(buf) => {
let mut disprock: MaybeUninit<DispatchRock> = MaybeUninit::uninit();
(self.retain_array_callbacks_u32.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Iu".as_ptr(), disprock.as_mut_ptr());
unsafe {disprock.assume_init()}
},
}
}

Expand Down Expand Up @@ -1609,7 +1618,8 @@ pub struct GlkDate {
}

// Retained array callbacks
pub type RetainArrayCallback<T> = extern fn(*const T, u32, *const u8) -> DispatchRock;
// The WASM ABI means that we can't return a DispatchRock, so it must be set through an out parameter
pub type RetainArrayCallback<T> = extern fn(*const T, u32, *const u8, *mut DispatchRock);
pub type UnretainArrayCallback<T> = extern fn(*const T, u32, *const u8, DispatchRock);

pub struct RetainArrayCallbacks<T> {
Expand Down
16 changes: 12 additions & 4 deletions remglk/src/glkapi/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ https://github.com/curiousdannii/remglk-rs
*/

use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Weak};

Expand Down Expand Up @@ -128,8 +129,8 @@ where T: Default + GlkObjectClass, GlkObject<T>: Default + Eq {
obj.id = self.counter;
obj.rock = rock;
self.counter += 1;
if let Some(register_cb) = self.register_cb {
obj.disprock = Some(register_cb(obj_ptr, self.object_class));
if let Some(_) = self.register_cb {
obj.disprock = Some(self.register_callback(obj_ptr, self.object_class));
}
match self.first.as_ref() {
None => {
Expand All @@ -147,13 +148,19 @@ where T: Default + GlkObjectClass, GlkObject<T>: Default + Eq {
};
}

fn register_callback(&self, obj_ptr: *const Mutex<GlkObjectMetadata<T>>, object_class: u32) -> DispatchRock {
let mut disprock: MaybeUninit<DispatchRock> = MaybeUninit::uninit();
self.register_cb.unwrap()(obj_ptr, object_class, disprock.as_mut_ptr());
unsafe {disprock.assume_init()}
}

pub fn set_callbacks(&mut self, register_cb: DispatchRegisterCallback<T>, unregister_cb: DispatchUnregisterCallback<T>) {
self.register_cb = Some(register_cb);
self.unregister_cb = Some(unregister_cb);
for obj in self.store.iter() {
let obj_ptr = obj.as_ptr();
let mut obj = obj.lock().unwrap();
obj.disprock = Some(register_cb(obj_ptr, self.object_class));
obj.disprock = Some(self.register_callback(obj_ptr, self.object_class));
}
}

Expand Down Expand Up @@ -253,7 +260,8 @@ pub union DispatchRock {
ptr: *const DispatchRockPtr,
}

pub type DispatchRegisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32) -> DispatchRock;
// The WASM ABI means that we can't return a DispatchRock, so it must be set through an out parameter
pub type DispatchRegisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32, *mut DispatchRock);
pub type DispatchUnregisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32, DispatchRock);

pub trait GlkObjectClass {
Expand Down
10 changes: 6 additions & 4 deletions remglk_capi/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ use super::*;
use common::*;
use glkapi::*;

type RegisterCallbackGeneric = extern fn(*const c_void, u32) -> DispatchRock;
// The WASM ABI means that we can't return a DispatchRock, so it must be set through an out parameter
type RegisterCallbackGeneric = extern fn(*const c_void, u32, *mut DispatchRock);
type UnregisterCallbackGeneric = extern fn(*const c_void, u32, DispatchRock);

#[no_mangle]
pub unsafe extern "C" fn gidispatch_set_object_registry(register_cb: RegisterCallbackGeneric, unregister_cb: UnregisterCallbackGeneric) {
pub unsafe extern "C" fn gidispatch_set_object_registry_rs(register_cb: RegisterCallbackGeneric, unregister_cb: UnregisterCallbackGeneric) {
let mut glkapi = glkapi().lock().unwrap();
let register = mem::transmute::<RegisterCallbackGeneric, DispatchRegisterCallback<FileRef>>(register_cb);
let unregister = mem::transmute::<UnregisterCallbackGeneric, DispatchUnregisterCallback<FileRef>>(unregister_cb);
Expand Down Expand Up @@ -59,11 +60,12 @@ pub extern "C" fn gidispatch_get_objrock_window(ptr: WindowPtr, dispatchrock_ptr
write_ptr(dispatchrock_ptr, obj.disprock.unwrap());
}

type RetainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char) -> DispatchRock;
// The WASM ABI means that we can't return a DispatchRock, so it must be set through an out parameter
type RetainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char, *mut DispatchRock);
type UnretainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char, DispatchRock);

#[no_mangle]
pub unsafe extern "C" fn gidispatch_set_retained_registry(register_cb: RetainArrayCallbackGeneric, unregister_cb: UnretainArrayCallbackGeneric) {
pub unsafe extern "C" fn gidispatch_set_retained_registry_rs(register_cb: RetainArrayCallbackGeneric, unregister_cb: UnretainArrayCallbackGeneric) {
let mut glkapi = glkapi().lock().unwrap();
let retain = mem::transmute::<RetainArrayCallbackGeneric, RetainArrayCallback<u8>>(register_cb);
let unretain = mem::transmute::<UnretainArrayCallbackGeneric, UnretainArrayCallback<u8>>(unregister_cb);
Expand Down
28 changes: 28 additions & 0 deletions remglk_capi/src/glk/support.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ MIT licenced
#include "glk.h"
#include "support.h"

gidispatch_rock_t (*gli_register_arr)(void *array, glui32 len, char *typecode) = NULL;
gidispatch_rock_t (*gli_register_obj)(void *obj, glui32 objclass) = NULL;

gidispatch_rock_t gidispatch_get_objrock(void *obj, glui32 objclass) {
gidispatch_rock_t rock;
switch (objclass) {
Expand All @@ -30,6 +33,31 @@ gidispatch_rock_t gidispatch_get_objrock(void *obj, glui32 objclass) {
}
}

// Because of a WASM ABI issue, we call the VM's registry functions indirectly
void gidispatch_call_array_register(void *array, glui32 len, char *typecode, gidispatch_rock_t *rock_ptr) {
gidispatch_rock_t rock = gli_register_arr(array, len, typecode);
*rock_ptr = rock;
}
void gidispatch_call_object_register(void *obj, glui32 objclass, gidispatch_rock_t *rock_ptr) {
gidispatch_rock_t rock = gli_register_obj(obj, objclass);
*rock_ptr = rock;
}

void gidispatch_set_object_registry(
gidispatch_rock_t (*regi)(void *obj, glui32 objclass),
void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock))
{
gli_register_obj = regi;
gidispatch_set_object_registry_rs(gidispatch_call_object_register, unregi);
}
void gidispatch_set_retained_registry(
gidispatch_rock_t (*regi)(void *array, glui32 len, char *typecode),
void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock))
{
gli_register_arr = regi;
gidispatch_set_retained_registry_rs(gidispatch_call_array_register, unregi);
}

glkunix_argumentlist_t *glkunix_arguments_addr(void) {
return glkunix_arguments;
}
6 changes: 6 additions & 0 deletions remglk_capi/src/glk/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
extern void gidispatch_get_objrock_fileref(void *obj, gidispatch_rock_t *rock_ptr);
extern void gidispatch_get_objrock_stream(void *obj, gidispatch_rock_t *rock_ptr);
extern void gidispatch_get_objrock_window(void *obj, gidispatch_rock_t *rock_ptr);
extern void gidispatch_set_object_registry_rs(
void (*regi)(void *obj, glui32 objclass, gidispatch_rock_t *rock_ptr),
void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock));
extern void gidispatch_set_retained_registry_rs(
void (*regi)(void *array, glui32 len, char *typecode, gidispatch_rock_t *rock_ptr),
void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock));

#endif /* REMGLK_RS_SUPPORT_START_H */
16 changes: 14 additions & 2 deletions remglk_capi/src/systems/emglken.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use glkapi::protocol::{Event, SystemFileRef, Update};
extern "C" {
fn emglken_fileref_exists(filename_ptr: *const u8, filename_len: usize) -> bool;
fn emglken_fileref_read(filename_ptr: *const u8, filename_len: usize, buffer: &mut EmglkenBuffer) -> bool;
fn emglken_get_glkote_event(buffer: &mut EmglkenBuffer);
}

#[repr(C)]
Expand Down Expand Up @@ -72,7 +73,7 @@ impl GlkSystem for EmglkenSystem {
};
let result = unsafe {emglken_fileref_read(fileref.filename.as_ptr(), fileref.filename.len(), &mut buf)};
if result {
return unsafe {Some(Box::from_raw(slice::from_raw_parts_mut(buf.ptr, buf.len)))};
return Some(buffer_to_boxed_slice(&buf));
}
None
}
Expand All @@ -91,10 +92,21 @@ impl GlkSystem for EmglkenSystem {
}

fn get_glkote_event(&mut self) -> Option<Event> {
unimplemented!()
let mut buf = EmglkenBuffer {
ptr: ptr::null_mut(),
len: 0,
};
unsafe {emglken_get_glkote_event(&mut buf)};
let data = buffer_to_boxed_slice(&buf);
let event: Event = serde_json::from_slice(&data).unwrap();
return Some(event);
}

fn send_glkote_update(&mut self, _update: Update) {
unimplemented!()
}
}

fn buffer_to_boxed_slice(buffer: &EmglkenBuffer) -> Box<[u8]> {
unsafe {Box::from_raw(slice::from_raw_parts_mut(buffer.ptr, buffer.len))}
}
22 changes: 18 additions & 4 deletions remglk_capi/src/systems/library_emglken.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,29 @@ addToLibrary({
return false
},

emglken_fileref_read__deps: ['$writeBuffer'],
emglken_fileref_read(filename_ptr, filename_len, buffer) {
const name = UTF8ToString(filename_ptr, filename_len)
if (name === storyfile_name) {
const ptr = _malloc(storyfile_data.length)
HEAP8.set(storyfile_data, ptr)
{{{ makeSetValue('buffer', 0, 'ptr', 'i32') }}}
{{{ makeSetValue('buffer', 4, 'storyfile_data.length', 'i32') }}}
writeBuffer(buffer, storyfile_data)
return true
}
return false
},

emglken_get_glkote_event__async: true,
emglken_get_glkote_event__deps: ['$writeBuffer'],
emglken_get_glkote_event(buffer) {
return Asyncify.handleAsync(async () => {
await new Promise(resolve => { glkote_event_ready = resolve })
writeBuffer(buffer, glkote_event_data)
})
},

$writeBuffer(buffer, data) {
const ptr = _malloc(data.length)
HEAP8.set(data, ptr)
{{{ makeSetValue('buffer', 0, 'ptr', 'i32') }}}
{{{ makeSetValue('buffer', 4, 'data.length', 'i32') }}}
}
})

0 comments on commit c8d0354

Please sign in to comment.