Skip to content

Commit

Permalink
Godot 3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
ashtonmeuser committed Sep 2, 2023
1 parent 2158378 commit abba1ac
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 122 deletions.
51 changes: 42 additions & 9 deletions SConstruct
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
#!python
import os
from utils import download_wasmer, download_wasmtime, WASMER_VER_DEFAULT, WASMTIME_VER_DEFAULT

# Initial options inheriting from CLI args
opts = Variables([], ARGUMENTS)

# Define options
opts.Add(EnumVariable("target", "Compilation target", "release", ["debug", "release"], {"d": "debug"}))
opts.Add(EnumVariable("platform", "Platform", "", ["", "windows", "linux", "osx"], {"x11": "linux", "macos": "osx"}))
opts.Add(BoolVariable("use_llvm", "Use LLVM/Clang compiler", "no"))
opts.Add(EnumVariable("wasm_runtime", "Wasm runtime used", "wasmer", ["wasmer", "wasmtime"]))
opts.Add(BoolVariable("download_runtime", "(Re)download runtime library", "no"))
opts.Add("runtime_version", "Runtime library version", None)

# SConstruct environment from Godot CPP
env = SConscript("godot-cpp/SConstruct")
opts.Update(env)
# Standard flags CC, CCX, etc. with options
env = DefaultEnvironment(variables=opts)

# Process some arguments
if env["platform"] == "":
exit("Invalid platform selected")

if env["use_llvm"]:
env["CC"] = "clang"
env["CXX"] = "clang++"

# Download runtime if required
if env["wasm_runtime"] == "wasmer":
Expand All @@ -20,7 +31,19 @@ elif env["wasm_runtime"] == "wasmtime":
download_wasmtime(env, env["download_runtime"], env.get("runtime_version", WASMTIME_VER_DEFAULT))

# Check platform specifics
if env["platform"] == "windows":
if env["platform"] in ["osx", "macos"]:
env.Prepend(CFLAGS=["-std=gnu11"])
env.Prepend(CXXFLAGS=["-std=gnu++14"])
env.Append(CCFLAGS=["-arch", "x86_64", "-Wall", "-g", "-O3"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-framework", "Security"])
elif env["platform"] == "linux":
env.Prepend(CFLAGS=["-std=gnu11"])
env.Prepend(CXXFLAGS=["-std=gnu++14"])
env.Append(CCFLAGS=["-fPIC", "-g", "-O3"])
elif env["platform"] == "windows":
env.Prepend(CCFLAGS=["/std:c++14", "-W3", "-GR", "-O2", "-EHsc", "-MD"])
env.Append(ENV=os.environ) # Keep session env variables to support VS 2017 prompt
env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS", "NDEBUG"])
if env.get("use_mingw"): # MinGW
env["LIBRUNTIMESUFFIX"] = ".a"
env.Append(LIBS=["userenv"])
Expand All @@ -29,10 +52,11 @@ if env["platform"] == "windows":
# Force Windows SDK library suffix (see https://github.com/godotengine/godot/issues/23687)
env.Append(LINKFLAGS=["bcrypt.lib", "userenv.lib", "ws2_32.lib", "advapi32.lib"])

# Defines for GDExtension specific API
env.Append(CPPDEFINES=["GDEXTENSION"])
# Defines for GDNative specific API
env.Append(CPPDEFINES=["GDNATIVE"])

# Explicit static libraries
cpp_lib = env.File("godot-cpp/bin/libgodot-cpp.{}.{}.64{}".format(env["platform"], env["target"], env["LIBSUFFIX"]))
runtime_lib = env.File(
"{runtime}/lib/{prefix}{runtime}{suffix}".format(
runtime=env["wasm_runtime"],
Expand All @@ -42,11 +66,20 @@ runtime_lib = env.File(
)

# CPP includes and libraries
env.Append(CPPPATH=[".", "{}/include".format(env["wasm_runtime"])])
env.Append(LIBS=[runtime_lib])
env.Append(
CPPPATH=[
".",
"godot-cpp/godot-headers",
"godot-cpp/include",
"{}/include".format(env["wasm_runtime"]),
"godot-cpp/include/core",
"godot-cpp/include/gen",
]
)
env.Append(LIBS=[cpp_lib, runtime_lib])

# Godot Wasm sources
source = ["register_types.cpp", env.Glob("src/*.cpp")]
source = [env.Glob("src/*.cpp")]

# Builders
library = env.SharedLibrary(target="addons/godot-wasm/bin/{}/godot-wasm".format(env["platform"]), source=source)
Expand Down
8 changes: 8 additions & 0 deletions addons/godot-wasm/Wasm.gdns
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://addons/godot-wasm/godot-wasm.gdnlib" type="GDNativeLibrary" id=1]

[resource]
class_name = "Wasm"
library = ExtResource( 1 )
script_class_name = "Wasm"
8 changes: 8 additions & 0 deletions addons/godot-wasm/WasmMemory.gdns
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://addons/godot-wasm/godot-wasm.gdnlib" type="GDNativeLibrary" id=1]

[resource]
class_name = "WasmMemory"
library = ExtResource( 1 )
script_class_name = "WasmMemory"
14 changes: 0 additions & 14 deletions addons/godot-wasm/godot-wasm.gdextension

This file was deleted.

19 changes: 19 additions & 0 deletions addons/godot-wasm/godot-wasm.gdnlib
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[general]

singleton=false
load_once=true
symbol_prefix="wasm_"
reloadable=true

[entry]

OSX.64="res://addons/godot-wasm/bin/osx/libgodot-wasm.dylib"
Windows.64="res://addons/godot-wasm/bin/windows/godot-wasm.dll"
X11.64="res://addons/godot-wasm/bin/linux/libgodot-wasm.so"
Server.64="res://addons/godot-wasm/bin/linux/libgodot-wasm.so"

[dependencies]

OSX.64=[ ]
Windows.64=[ ]
X11.64=[ ]
2 changes: 1 addition & 1 deletion godot-cpp
Submodule godot-cpp updated 194 files
35 changes: 7 additions & 28 deletions register_types.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
#ifdef GODOT_MODULE

#include "register_types.h"
#include "core/class_db.h"
#include "src/godot-wasm.h"
#include "src/wasm-memory.h"

using namespace godot;

void initialize_wasm_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}

ClassDB::register_class<Wasm>();
ClassDB::register_class<WasmMemory>();
}

void uninitialize_wasm_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
void register_wasm_types() {
ClassDB::register_class<godot::Wasm>();
ClassDB::register_class<godot::WasmMemory>();
}

#ifndef GODOT_MODULE

extern "C" {
GDExtensionBool GDE_EXPORT wasm_library_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);

init_obj.register_initializer(initialize_wasm_module);
init_obj.register_terminator(uninitialize_wasm_module);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);

return init_obj.init();
}
}
void unregister_wasm_types() { }

#endif
15 changes: 2 additions & 13 deletions register_types.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
#ifndef GODOT_WASM_REGISTER_TYPES_H
#define GODOT_WASM_REGISTER_TYPES_H

// This define is only needed because the GODOT_MODULE define isn't detected here
// May be related to https://github.com/godotengine/godot/issues/75914
#ifdef GDEXTENSION
#define NS godot
#include <godot_cpp/core/class_db.hpp>
#else
#define NS
#include "modules/register_module_types.h"
#include "core/object/class_db.h"
#endif

void initialize_wasm_module(NS::ModuleInitializationLevel p_level);
void uninitialize_wasm_module(NS::ModuleInitializationLevel p_level);
void register_wasm_types();
void unregister_wasm_types();

#endif
40 changes: 23 additions & 17 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@

#ifdef GODOT_MODULE // Godot includes when building module
#include "core/os/os.h"
#include "core/os/time.h"
#include "core/crypto/crypto.h"
#include "core/io/stream_peer.h"
#else // Godot addon includes
#include "godot_cpp/classes/ref_counted.hpp"
#include "godot_cpp/classes/os.hpp"
#include "godot_cpp/classes/time.hpp"
#include "godot_cpp/classes/crypto.hpp"
#include "godot_cpp/classes/stream_peer_extension.hpp"
#include "godot_cpp/variant/utility_functions.hpp"
#include <Godot.hpp>
#include <OS.hpp>
#include <Crypto.hpp>
#include <StreamPeerGDNative.hpp>
#endif

#ifdef GODOT_MODULE
Expand All @@ -22,19 +19,28 @@
#define REGISTRATION_METHOD _bind_methods
#define RANDOM_BYTES(n) Crypto::create()->generate_random_bytes(n)
#else
#define PRINT(message) UtilityFunctions::print(String(message))
#define PRINT_ERROR(message) _err_print_error(__FUNCTION__, __FILE__, __LINE__, "Godot Wasm: " + String(message))
#define godot_error Error
#define REGISTRATION_METHOD _bind_methods
#define RANDOM_BYTES(n) Crypto().generate_random_bytes(n)
#define OK GODOT_OK
#define FAILED GODOT_FAILED
#define ERR_INVALID_DATA GODOT_ERR_INVALID_DATA
#define ERR_COMPILATION_FAILED GODOT_ERR_COMPILATION_FAILED
#define ERR_CANT_CREATE GODOT_ERR_CANT_CREATE
#define ERR_PARAMETER_RANGE_ERROR GODOT_ERR_PARAMETER_RANGE_ERROR
#define PRINT(message) Godot::print(String(message))
#define PRINT_ERROR(message) Godot::print_error("Godot Wasm: " + String(message), __func__, __FILE__, __LINE__)
#define GDCLASS GODOT_CLASS
#define REGISTRATION_METHOD _register_methods
#define RANDOM_BYTES(n) Crypto::_new()->generate_random_bytes(n)
#endif
#define FLOAT REAL
#define RefCounted Reference
#define PackedByteArray PoolByteArray
#define FAIL(message, ret) do { PRINT_ERROR(message); return ret; } while (0)
#define FAIL_IF(cond, message, ret) if (unlikely(cond)) FAIL(message, ret)
#define INSTANTIATE_REF(ref) ref.instantiate()
#define BYTE_ARRAY_POINTER(array) array.ptr()
#define CMDLINE_ARGS OS::get_singleton()->get_cmdline_user_args()
#define TIME_REALTIME Time::get_singleton()->get_unix_time_from_system() * 1000000000
#define TIME_MONOTONIC Time::get_singleton()->get_ticks_usec() * 1000
#define INSTANTIATE_REF(ref) ref.instance()
#define BYTE_ARRAY_POINTER(array) array.read().ptr()
#define CMDLINE_ARGS PoolStringArray() // User CLI args unsupported in Godot 3
#define TIME_REALTIME OS::get_singleton()->get_system_time_msecs() * 1000000
#define TIME_MONOTONIC OS::get_singleton()->get_ticks_usec() * 1000
#define NULL_VARIANT Variant()
#define PAGE_SIZE 65536

Expand Down
21 changes: 21 additions & 0 deletions src/godot-library.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef GODOT_MODULE

#include "godot-wasm.h"
#include "wasm-memory.h"

extern "C" void GDN_EXPORT wasm_gdnative_init(godot_gdnative_init_options *o) {
godot::Godot::gdnative_init(o);
}

extern "C" void GDN_EXPORT wasm_gdnative_terminate(godot_gdnative_terminate_options *o) {
godot::Godot::gdnative_terminate(o);
}

extern "C" void GDN_EXPORT wasm_nativescript_init(void *handle) {
godot::Godot::nativescript_init(handle);

godot::register_class<godot::Wasm>();
godot::register_class<godot::WasmMemory>();
}

#endif
32 changes: 9 additions & 23 deletions src/wasm-memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,48 +86,34 @@ namespace godot {
return pointer;
}

godot_error WasmMemory::INTERFACE_GET_DATA {
godot_error WasmMemory::get_data(uint8_t *buffer, int bytes) {
FAIL_IF(memory == NULL, "Invalid memory", ERR_INVALID_DATA);
byte_t* data = wasm_memory_data(memory) + pointer;
memcpy(buffer, data, bytes);
pointer += bytes;
#ifndef GODOT_MODULE
*received = bytes;
#endif
return OK;
}

godot_error WasmMemory::INTERFACE_GET_PARTIAL_DATA {
#ifdef GODOT_MODULE
received = bytes;
return get_data(buffer, bytes);
#else
return _get_data(buffer, bytes, received);
#endif
godot_error WasmMemory::get_partial_data(uint8_t *buffer, int bytes, int &received) {
received = bytes;
return get_data(buffer, bytes);
}

godot_error WasmMemory::INTERFACE_PUT_DATA {
godot_error WasmMemory::put_data(const uint8_t *buffer, int bytes) {
FAIL_IF(memory == NULL, "Invalid memory", ERR_INVALID_DATA);
if (bytes <= 0) return OK;
byte_t* data = wasm_memory_data(memory) + pointer;
memcpy(data, buffer, bytes);
pointer += bytes;
#ifndef GODOT_MODULE
*sent = bytes;
#endif
return OK;
}

godot_error WasmMemory::INTERFACE_PUT_PARTIAL_DATA {
#ifdef GODOT_MODULE
sent = bytes;
return put_data(buffer, bytes);
#else
return _put_data(buffer, bytes, sent);
#endif
godot_error WasmMemory::put_partial_data(const uint8_t *buffer, int bytes, int &sent) {
sent = bytes;
return put_data(buffer, bytes);
}

int32_t WasmMemory::INTERFACE_GET_AVAILABLE_BYTES {
int WasmMemory::get_available_bytes() const {
return 0; // Not relevant
}
}
24 changes: 7 additions & 17 deletions src/wasm-memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,9 @@
#ifdef GODOT_MODULE
#define SUPER_CLASS StreamPeer
#define INTERFACE_DECLARE
#define INTERFACE_GET_DATA get_data(uint8_t *buffer, int32_t bytes)
#define INTERFACE_GET_PARTIAL_DATA get_partial_data(uint8_t *buffer, int32_t bytes, int32_t &received)
#define INTERFACE_PUT_DATA put_data(const uint8_t *buffer, int32_t bytes)
#define INTERFACE_PUT_PARTIAL_DATA put_partial_data(const uint8_t *buffer, int bytes, int32_t &sent)
#define INTERFACE_GET_AVAILABLE_BYTES get_available_bytes() const
#else
#define SUPER_CLASS StreamPeerExtension
#define INTERFACE_DECLARE
#define INTERFACE_GET_DATA _get_data(uint8_t *buffer, int32_t bytes, int32_t *received)
#define INTERFACE_GET_PARTIAL_DATA _get_partial_data(uint8_t *buffer, int32_t bytes, int32_t *received)
#define INTERFACE_PUT_DATA _put_data(const uint8_t *buffer, int32_t bytes, int32_t *sent)
#define INTERFACE_PUT_PARTIAL_DATA _put_partial_data(const uint8_t *buffer, int32_t bytes, int32_t *sent)
#define INTERFACE_GET_AVAILABLE_BYTES _get_available_bytes() const
#define SUPER_CLASS StreamPeerGDNative
#define INTERFACE_DECLARE godot_net_stream_peer interface
#endif

namespace godot {
Expand All @@ -41,11 +31,11 @@ namespace godot {
godot_error grow(uint32_t pages);
Ref<WasmMemory> seek(int p_pos);
uint32_t get_position() const;
godot_error INTERFACE_GET_DATA override;
godot_error INTERFACE_GET_PARTIAL_DATA override;
godot_error INTERFACE_PUT_DATA override;
godot_error INTERFACE_PUT_PARTIAL_DATA override;
int32_t INTERFACE_GET_AVAILABLE_BYTES override;
godot_error get_data(uint8_t* buffer, int bytes);
godot_error get_partial_data(uint8_t* buffer, int bytes, int& received);
godot_error put_data(const uint8_t* buffer, int bytes);
godot_error put_partial_data(const uint8_t* buffer, int bytes, int& sent);
int get_available_bytes() const;
};
}

Expand Down

0 comments on commit abba1ac

Please sign in to comment.