Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Jujstme authored Oct 1, 2024
2 parents 79b67b3 + 086c851 commit 57f85c9
Show file tree
Hide file tree
Showing 50 changed files with 2,055 additions and 71 deletions.
42 changes: 16 additions & 26 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,21 @@ on:

jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
label:
- WebAssembly Unknown
- WebAssembly WASI

include:
- label: WebAssembly Unknown
target: wasm32-unknown-unknown
os: ubuntu-latest
install_target: true
- label: WebAssembly WASI
target: wasm32-wasi
os: ubuntu-latest
install_target: true

target: [wasm32-unknown-unknown, wasm32-wasip1]
toolchain: [stable, nightly]
steps:
- name: Checkout Commit
uses: actions/checkout@v4

- name: Install Rust
uses: hecrj/setup-rust-action@v2
with:
rust-version: ${{ matrix.toolchain || 'stable' }}

- name: Install Target
if: matrix.install_target != ''
run: rustup target add ${{ matrix.target }}
targets: ${{ matrix.target }}
rust-version: ${{ matrix.toolchain }}

- name: Build (No Default Features)
run: |
Expand All @@ -53,14 +38,19 @@ jobs:
run: |
cargo build --all-features --target ${{ matrix.target }}
- name: Test (Target, All Features)
run: |
cargo test --all-features
test:
name: Test (Host)
runs-on: ubuntu-latest
steps:
- name: Checkout Commit
uses: actions/checkout@v4

# Test on the host to also run the doc tests
- name: Test (Host, All Features)
- name: Install Rust
uses: hecrj/setup-rust-action@v2

- name: Test (All Features)
run: |
cargo test --target x86_64-unknown-linux-gnu --all-features
cargo test --all-features
clippy:
name: Check clippy lints
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
with:
components: rust-docs
rust-version: nightly
targets: wasm32-wasi
targets: wasm32-wasip1

- name: Build docs
run: RUSTDOCFLAGS="--cfg doc_cfg" cargo doc --all-features --target wasm32-wasi
run: RUSTDOCFLAGS="--cfg doc_cfg" cargo doc --all-features --target wasm32-wasip1

- name: Setup Pages
uses: actions/configure-pages@v3
Expand All @@ -61,12 +61,12 @@ jobs:
--exclude=.github \
.
env:
INPUT_PATH: target/wasm32-wasi/doc
INPUT_PATH: target/wasm32-wasip1/doc

- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: target/wasm32-wasi/doc
path: target/wasm32-wasip1/doc

- name: Deploy to GitHub Pages
id: deployment
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ signature = ["memchr"]
wasi-no-std = ["libm"]

# Game Engines
godot = []
unity = ["signature", "asr-derive?/unity"]
unreal = ["signature"]

Expand All @@ -41,3 +42,6 @@ ps1 = ["flags", "signature"]
ps2 = ["flags", "signature"]
sms = ["flags", "signature"]
wii = ["flags"]

[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(doc_cfg)'] }
88 changes: 48 additions & 40 deletions src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,25 +345,27 @@ macro_rules! async_main {
#[no_mangle]
pub unsafe extern "C" fn update() {
use core::{
cell::UnsafeCell,
future::Future,
pin::Pin,
ptr,
task::{Context, RawWaker, RawWakerVTable, Waker},
};

type MainFuture = impl Future<Output = ()>;
const fn main_type() -> MainFuture {
async {
main().await;
use $crate::sync::RacyCell;
mod fut {
pub type MainFuture = impl core::future::Future<Output = ()>;
pub const fn main_type() -> MainFuture {
async {
super::main().await;
}
}
}
static mut STATE: MainFuture = main_type();
static mut FINISHED: bool = false;

if unsafe { FINISHED } {
static STATE: RacyCell<fut::MainFuture> = RacyCell::new(fut::main_type());
static FINISHED: RacyCell<bool> = RacyCell::new(false);
if unsafe { *FINISHED.get() } {
return;
}

static VTABLE: RawWakerVTable = RawWakerVTable::new(
|_| RawWaker::new(ptr::null(), &VTABLE),
|_| {},
Expand All @@ -374,7 +376,9 @@ macro_rules! async_main {
let waker = unsafe { Waker::from_raw(raw_waker) };
let mut cx = Context::from_waker(&waker);
unsafe {
FINISHED = Pin::new_unchecked(&mut STATE).poll(&mut cx).is_ready();
*FINISHED.get_mut() = Pin::new_unchecked(&mut *STATE.get_mut())
.poll(&mut cx)
.is_ready();
}
}
};
Expand All @@ -385,17 +389,20 @@ macro_rules! async_main {
#[cfg(target_family = "wasm")]
pub unsafe extern "C" fn update() {
use core::{
cell::UnsafeCell,
future::Future,
mem::{self, ManuallyDrop},
pin::Pin,
ptr,
task::{Context, RawWaker, RawWakerVTable, Waker},
};
use $crate::sync::RacyCell;

static mut STATE: Option<Pin<&'static mut dyn Future<Output = ()>>> = None;
static mut FINISHED: bool = false;
static STATE: RacyCell<Option<Pin<&'static mut dyn Future<Output = ()>>>> =
RacyCell::new(None);
static FINISHED: RacyCell<bool> = RacyCell::new(false);

if unsafe { FINISHED } {
if unsafe { *FINISHED.get() } {
return;
}

Expand All @@ -409,35 +416,36 @@ macro_rules! async_main {
let waker = unsafe { Waker::from_raw(raw_waker) };
let mut cx = Context::from_waker(&waker);
unsafe {
FINISHED = Pin::new_unchecked(STATE.get_or_insert_with(|| {
fn allocate<F: Future<Output = ()> + 'static>(
f: ManuallyDrop<F>,
) -> Pin<&'static mut dyn Future<Output = ()>> {
unsafe {
let size = mem::size_of::<F>();
const PAGE_SIZE: usize = 64 << 10;
assert!(mem::align_of::<F>() <= PAGE_SIZE);
let pages = size.div_ceil(PAGE_SIZE);

#[cfg(target_arch = "wasm32")]
let old_page_count = core::arch::wasm32::memory_grow(0, pages);
#[cfg(target_arch = "wasm64")]
let old_page_count = core::arch::wasm64::memory_grow(0, pages);

let address = old_page_count * PAGE_SIZE;
let ptr = address as *mut ManuallyDrop<F>;
ptr::write(ptr, f);
let ptr = ptr.cast::<F>();
let future: &'static mut F = &mut *ptr;
let future: &'static mut dyn Future<Output = ()> = future;
Pin::static_mut(future)
*FINISHED.get_mut() =
Pin::new_unchecked((&mut *STATE.get_mut()).get_or_insert_with(|| {
fn allocate<F: Future<Output = ()> + 'static>(
f: ManuallyDrop<F>,
) -> Pin<&'static mut dyn Future<Output = ()>> {
unsafe {
let size = mem::size_of::<F>();
const PAGE_SIZE: usize = 64 << 10;
assert!(mem::align_of::<F>() <= PAGE_SIZE);
let pages = size.div_ceil(PAGE_SIZE);

#[cfg(target_arch = "wasm32")]
let old_page_count = core::arch::wasm32::memory_grow(0, pages);
#[cfg(target_arch = "wasm64")]
let old_page_count = core::arch::wasm64::memory_grow(0, pages);

let address = old_page_count * PAGE_SIZE;
let ptr = address as *mut ManuallyDrop<F>;
ptr::write(ptr, f);
let ptr = ptr.cast::<F>();
let future: &'static mut F = &mut *ptr;
let future: &'static mut dyn Future<Output = ()> = future;
Pin::static_mut(future)
}
}
}

allocate(ManuallyDrop::new(main()))
}))
.poll(&mut cx)
.is_ready();
allocate(ManuallyDrop::new(main()))
}))
.poll(&mut cx)
.is_ready();
};
}
};
Expand Down
11 changes: 11 additions & 0 deletions src/game_engine/godot/core/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mod object;
mod os;
mod string;
mod templates;
mod variant;

pub use object::*;
pub use os::*;
pub use string::*;
pub use templates::*;
pub use variant::*;
7 changes: 7 additions & 0 deletions src/game_engine/godot/core/object/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod object;
mod script_instance;
mod script_language;

pub use object::*;
pub use script_instance::*;
pub use script_language::*;
88 changes: 88 additions & 0 deletions src/game_engine/godot/core/object/object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! <https://github.com/godotengine/godot/blob/07cf36d21c9056fb4055f020949fb90ebd795afb/core/object/object.h>
use crate::{
game_engine::godot::{Ptr, VTable, VariantType},
Error, Process,
};

use super::ScriptInstance;

#[allow(unused)]
mod offsets {
// *const VTable
pub const VTABLE_PTR: u64 = 0x0;
// *const ObjectGDExtension
pub const EXTENSION: u64 = 0x8;
// GDExtensionClassInstancePtr
pub const EXTENSION_INSTANCE: u64 = 0x10;
// HashMap<StringName, SignalData>
pub const SIGNAL_MAP: u64 = 0x18;
// List<Connection>
pub const CONNECTIONS: u64 = 0x48;
// bool
pub const BLOCK_SIGNALS: u64 = 0x50;
// i32
pub const PREDELETE_OK: u64 = 0x54;
// ObjectID
pub const INSTANCE_ID: u64 = 0x58;
// bool
pub const CAN_TRANSLATE: u64 = 0x60;
// bool
pub const EMITTING: u64 = 0x61;
// *const ScriptInstance
pub const SCRIPT_INSTANCE: u64 = 0x68;
// Variant
pub const SCRIPT: u64 = 0x70;
// HashMap<StringName, Variant>
pub const METADATA: u64 = 0x88;
// HashMap<StringName, Variant*>
pub const METADATA_PROPERTIES: u64 = 0xb8;
// *const StringName
pub const CLASS_NAME_PTR: u64 = 0xe8;
}

/// Information about a property of a script. This is not publicly exposed in
/// Godot.
///
/// Check the [`Ptr<PropertyInfo>`] documentation to see all the methods you can
/// call on it.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct PropertyInfo;

impl Ptr<PropertyInfo> {
/// Returns the type of the property as a [`VariantType`].
pub fn get_variant_type(self, process: &Process) -> Result<VariantType, Error> {
self.read_at_byte_offset(0x0, process)
}
}

/// Base class for all other classes in the engine.
///
/// [`Object`](https://docs.godotengine.org/en/4.2/classes/class_object.html)
///
/// Check the [`Ptr<Object>`] documentation to see all the methods you can call
/// on it.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Object;

impl Ptr<Object> {
/// Returns a pointer to the object's virtual method table.
pub fn get_vtable(self, process: &Process) -> Result<Ptr<VTable>, Error> {
self.read_at_byte_offset(offsets::VTABLE_PTR, process)
}

/// Returns the object's Script instance, or [`None`] if no script is
/// attached.
///
/// [`Object.get_script`](https://docs.godotengine.org/en/4.2/classes/class_object.html#class-object-method-get-script)
pub fn get_script_instance(
self,
process: &Process,
) -> Result<Option<Ptr<ScriptInstance>>, Error> {
let ptr: Ptr<ScriptInstance> =
self.read_at_byte_offset(offsets::SCRIPT_INSTANCE, process)?;
Ok(if ptr.is_null() { None } else { Some(ptr) })
}
}
12 changes: 12 additions & 0 deletions src/game_engine/godot/core/object/script_instance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! <https://github.com/godotengine/godot/blob/07cf36d21c9056fb4055f020949fb90ebd795afb/core/object/script_instance.h>
/// An instance of a [`Script`](super::Script).
///
/// You need to cast this to a
/// [`GDScriptInstance`](crate::game_engine::godot::GDScriptInstance) or
/// [`CSharpScriptInstance`](crate::game_engine::godot::CSharpScriptInstance) to
/// do anything meaningful with it. Make sure to verify the script language
/// before casting.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct ScriptInstance;
12 changes: 12 additions & 0 deletions src/game_engine/godot/core/object/script_language.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! <https://github.com/godotengine/godot/blob/07cf36d21c9056fb4055f020949fb90ebd795afb/core/object/script_language.h>
/// A class stored as a resource.
///
/// [`Script`](https://docs.godotengine.org/en/4.2/classes/class_script.html)
///
/// You need to cast this to a [`GDScript`](crate::game_engine::godot::GDScript)
/// or [`CSharpScript`](crate::game_engine::godot::CSharpScript) to do anything
/// meaningful with it. Make sure to verify the script language before casting.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct Script;
11 changes: 11 additions & 0 deletions src/game_engine/godot/core/os/main_loop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! <https://github.com/godotengine/godot/blob/07cf36d21c9056fb4055f020949fb90ebd795afb/core/os/main_loop.h>
use crate::game_engine::godot::Object;

/// Abstract base class for the game's main loop.
///
/// [`MainLoop`](https://docs.godotengine.org/en/4.2/classes/class_mainloop.html)
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct MainLoop;
extends!(MainLoop: Object);
3 changes: 3 additions & 0 deletions src/game_engine/godot/core/os/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod main_loop;

pub use main_loop::*;
Loading

0 comments on commit 57f85c9

Please sign in to comment.