Macro quake3_qvm::native_qvm
[−]
[src]
macro_rules! native_qvm { ($ty:ident) => { ... }; }
Creates the required plumbing to use an impl QVM
as a native shared library.
Examples
Add the following section to your Cargo.toml
:
[lib]
name = "q3hi"
crate-type = ["cdylib"]
Then implement a QVM by using the macro as such:
#[macro_use] extern crate quake3_qvm; // Needed for C FFI extern crate libc; // Needed to initialize internal `static mut` until const-fns are stable #[macro_use] extern crate lazy_static; use std::ffi::CString; struct HelloQuake3 { syscall: Syscall, } use quake3_qvm::native::*; // See ioquake3's [game/g_public.h](https://github.com/ioquake/ioq3/blob/master/code/game/g_public.h) const G_ERROR: libc::intptr_t = 1; const GAME_INIT: libc::c_int = 0; const GAME_SHUTDOWN: libc::c_int = 1; impl QVM for HelloQuake3 { fn dll_entry(syscall: Syscall) -> Box<HelloQuake3> { Box::new(HelloQuake3 { syscall: syscall }) } fn vm_main(&self, command: libc::c_int, arg0: libc::c_int, arg1: libc::c_int, arg2: libc::c_int, arg3: libc::c_int, arg4: libc::c_int, arg5: libc::c_int, arg6: libc::c_int, arg7: libc::c_int, arg8: libc::c_int, arg9: libc::c_int, arg10: libc::c_int, arg11: libc::c_int) -> libc::intptr_t { match command { GAME_INIT => { (self.syscall)(G_ERROR, CString::new("Hello, World!").unwrap().as_ptr()); unreachable!() } GAME_SHUTDOWN => { // Just return a dummy value here for clean shutdown 0 }, _ => panic!("Game command not implemented"), } } } native_qvm!(HelloQuake3);
Finally build the QVM, 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