macro_rules! native_vm {
    ($ty:ident) => { ... };
}
Expand description

Create required extern "C" fns to load a impl NativeVM as shared library

Can only be used once per Rust lib. Each module (qagame etc.) needs its own shared library.

Examples

Also see examples/hello.rs of this crate.

Add the following section to your Cargo.toml:

[lib]
name = "q3hi"
crate-type = ["cdylib"]

Then implement a module by using the macro as such:

use std::ffi::CString;
use quake3_native_vm::*;

struct HelloQuake3 {
   syscall: Syscall,
}


/// See [ioquake3's `game/g_public.h`](https://github.com/ioquake/ioq3/blob/master/code/game/g_public.h)
const G_ERROR: ffi::intptr_t = 1;
const GAME_INIT: ffi::c_int = 0;
const GAME_SHUTDOWN: ffi::c_int = 1;

impl NativeVM for HelloQuake3 {
   fn dll_entry(syscall: Syscall) -> Box<HelloQuake3> {
       Box::new(HelloQuake3 { syscall: syscall })
   }

   fn vm_main(&self,
              command: ffi::c_int,
              arg0: ffi::c_int,
              arg1: ffi::c_int,
              arg2: ffi::c_int,
              arg3: ffi::c_int,
              arg4: ffi::c_int,
              arg5: ffi::c_int,
              arg6: ffi::c_int,
              arg7: ffi::c_int,
              arg8: ffi::c_int,
              arg9: ffi::c_int,
              arg10: ffi::c_int,
              arg11: ffi::c_int)
              -> ffi::intptr_t {
       match command {
           GAME_INIT => {
               let msg = CString::new("Hello, World!").unwrap();
               (self.syscall)(G_ERROR, msg.as_ptr());
               unreachable!()
           }
           GAME_SHUTDOWN => {
               // Just return a dummy value here for clean shutdown
               0
           },
           _ => panic!("Game command not implemented"),
       }
   }
}

native_vm!(HelloQuake3);

Finally build the shared library, put it in the right place for Quake 3 and load it:

cargo build
mkdir -p ~/.q3a/rust/
cp target/debug/libq3hi.so ~/.q3a/rust/qagamex86_64.so
ioq3ded +set fs_game rust +set vm_game 0 +map q3dm6

See Sys_LoadGameDll in ioquake3’s sys/sys_main.c.