diff --git a/.gitignore b/.gitignore index fd2c5b0..5d6929d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ test/bin/cpp/* .vscode/ .zed/ + +ndlls/*/bin +ndlls/*/obj + !test/bin/cpp/images/ !test/bin/cpp/sound/ \ No newline at end of file diff --git a/build_ndlls.bat b/build_ndlls.bat new file mode 100644 index 0000000..e8697e7 --- /dev/null +++ b/build_ndlls.bat @@ -0,0 +1 @@ +lime rebuild ndlls/memory windows \ No newline at end of file diff --git a/extraParams.hxml b/extraParams.hxml index 3b8e083..dee1905 100644 --- a/extraParams.hxml +++ b/extraParams.hxml @@ -1 +1 @@ ---macro raylib.macros.GlobalMetadata.run() +--macro raylib.macros.GlobalMetadata.run() \ No newline at end of file diff --git a/haxelib.json b/haxelib.json index ab548b5..10e85c3 100644 --- a/haxelib.json +++ b/haxelib.json @@ -1,12 +1,24 @@ { - "name": "flixel-raylib", - "url" : "https://github.com/Vortex2Oblivion/flixel-raylib", - "license": "MIT", - "tags": ["flixel", "haxeflixel", "bindings", "raylib", "game", "development"], - "description": "Rewrite of flixel with a raylib backend.", - "version": "1.0.0", - "releasenote": "", - "contributors": ["Vortex"], - "dependencies": {"hxcpp": ""}, - "classPath": "src" - } \ No newline at end of file + "name": "flixel-raylib", + "url": "https://github.com/Vortex2Oblivion/flixel-raylib", + "license": "MIT", + "tags": [ + "flixel", + "haxeflixel", + "bindings", + "raylib", + "game", + "development" + ], + "description": "Rewrite of flixel with a raylib backend.", + "version": "1.0.0", + "releasenote": "", + "contributors": [ + "Vortex" + ], + "dependencies": { + "hxcpp": "", + "lime": "" + }, + "classPath": "src" +} \ No newline at end of file diff --git a/ndlls/memory/common/ExternalInterface.cpp b/ndlls/memory/common/ExternalInterface.cpp new file mode 100644 index 0000000..d5c49bc --- /dev/null +++ b/ndlls/memory/common/ExternalInterface.cpp @@ -0,0 +1,160 @@ +#ifndef STATIC_LINK +#define IMPLEMENT_API +#endif + +#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX) +#define NEKO_COMPATIBLE +#endif + +#if defined(HX_WINDOWS) +#include +#include + +#pragma comment(lib, "Dwmapi") +#endif + + +#include +#include +#include "memory.h" + + +// Helpers +inline bool val_is_raw_object(value inVal) { return val_type(inVal)==valtObject; } +inline bool val_is_enum(value inVal) { return val_type(inVal)==valtEnum; } +inline bool val_is_class(value inVal) { return val_type(inVal)==valtClass; } + +// Allocating: +// alloc_null() == generate haxe null / or use val_null +// alloc_bool(bool) == generate haxe bool +// alloc_int(int) == generate haxe int +// alloc_float(double) == generate haxe float +// alloc_empty_object() == generate haxe anon obj +// alloc_string(const char *) == generate haxe string +// alloc_array(int) == generate haxe array with a size + +// Getting: +// val_int(value) == get int from haxe object +// val_bool(value) == get bool from haxe object +// val_float(value) == get double from haxe object +// val_string(value) == get const char * from haxe object + +// Checking +// val_is_null(value) == checks if the value is null +// val_is_int(value) == checks if the value is int +// val_is_bool(value) == checks if the value is bool +// val_is_float(value) == checks if the value is float +// val_is_string(value) == checks if the value is string +// val_is_function(value) == checks if the value is function +// val_is_array(value) == checks if the value is array +// val_is_abstract(value) == checks if the value is abstract? unsure +// val_is_kind(value, vkind) == checks if the value is kind? unsure +// val_is_number(value) == checks if the value is int or float +// val_is_object(value) == checks if the value is int or float +// val_is_raw_object(value) == checks if the value is an anon obj (Custom) +// val_is_enum(value) == checks if the value is enum (Custom) +// val_is_class(value) == checks if the value is class (Custom) + +// Arrays: +// val_array_size(value) == get length of array +// val_array_i(value, int) == get item from index from array, you need to use the val_ functions to prepare the value +// val_array_set_i(value, int, value) == set item at index in array, you need to use alloc_ function to prepare the value +// val_array_set_size(value, int) == sets the length of the array +// val_array_push(value, value) == pushes a value to an array, you need to use the val_ functions to prepare the value +// alloc_array(int) == idk what the int does + +// Functions: +// you need to use the val_ functions to prepare the values +// add o before the call function (val_ocall0) to call a object field, and add an int value for the field, unsure what this is for +// val_call0(value) == call haxe function with 0 args +// val_call1(value, value) == call haxe function with 1 args +// val_call2(value, value, value) == call haxe function with 2 args +// val_call3(value, value, value, value) == call haxe function with 3 args +// val_callN(value, value*, int) == calls haxe function with n args, based on the int and the array, Usage below + +/* +int num_args = 4; +value *args = new value[num_args]; +args[0] = alloc_bool(false); +args[1] = alloc_bool(true); +args[2] = alloc_int(5); +args[3] = alloc_int(15); +value result = val_callN(root->get(), args, num_args); +*/ + +// Objects +// idk it uses an int for the field i have no clue +// tho theres val_field_name(field) no clue how this is used +// setting a field: alloc_field(value, val_id(val_string(value)), value); +// setting a field with cstring: alloc_field(value, val_id(const char*), value); +// getting a field: val_field(value, val_id(val_string(value))); +// getting a field with cstring: val_field(value, val_id(const char*)); +// TODO: finish this + +// Misc: +// val_gc(value, c++ func) == sets a finalizer for a object, warning very limited, trying to allocate haxe memory crashes +// val_fun_nargs(value) == get total args of function, -1 for Reflect.makeVarArgs +// val_strlen(value) == get length of string + +// Check https://github.com/HaxeFoundation/hxcpp/blob/master/src/hx/CFFI.cpp for the code, and more functions + +// Defining functions for the ndll: +// the prefix isnt needed it can completely just be set_window_transparent if you want +// n can be from 0 to 15 +// DEFINE_PRIMEn(function) == define function that returns +// DEFINE_PRIMEnv(function) == define void function + +// FYI: if the type is bool or int or double (haxe float) then it does the conversion automatically + +#if defined(HX_WINDOWS) + +static value get_memory_usage() { + return alloc_float(getCurrentRSS()); +} +DEFINE_PRIME0 (get_memory_usage); + +static value get_memory_peak() { + return alloc_float(getPeakRSS()); +} +DEFINE_PRIME0 (get_memory_peak); + +#else + +static value get_memory_usage () { + return alloc_float(0); +} +DEFINE_PRIME0 (get_memory_usage); + +static value get_memory_peak () { + return alloc_float(0); +} +DEFINE_PRIME0 (get_memory_peak) + +#endif + +// Examples +/* +static value memory_sample_method (value inputValue) { + int returnValue = val_int(inputValue); + return alloc_int(returnValue); +} +DEFINE_PRIME1 (memory_sample_method); + +static void memory_sample_method_void (value inputValue) { + int returnValue = val_int(inputValue); +} +DEFINE_PRIME1v (memory_sample_method_void); +*/ + + + +extern "C" void memory_main () { + + val_int(0); // Fix Neko init + +} +DEFINE_ENTRY_POINT (memory_main); + + + +extern "C" int memory_register_prims () { return 0; } \ No newline at end of file diff --git a/ndlls/memory/common/memory.h b/ndlls/memory/common/memory.h new file mode 100644 index 0000000..eba75e0 --- /dev/null +++ b/ndlls/memory/common/memory.h @@ -0,0 +1,114 @@ +/* + * Author: David Robert Nadeau + * Site: http://NadeauSoftware.com/ + * License: Creative Commons Attribution 3.0 Unported License + * http://creativecommons.org/licenses/by/3.0/deed.en_US + */ + +#if defined(_WIN32) +#include +#include + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) +#include +#include + +#if defined(__APPLE__) && defined(__MACH__) +#include + +#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) +#include +#include + +#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) +#include + +#endif + +#else +#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS." +#endif + +/** + * Returns the peak (maximum so far) resident set size (physical + * memory use) measured in bytes, or zero if the value cannot be + * determined on this OS. + */ +size_t getPeakRSS() +{ +#if defined(_WIN32) + /* Windows -------------------------------------------------- */ + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); + return (size_t)info.PeakWorkingSetSize; + +#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) + /* AIX and Solaris ------------------------------------------ */ + struct psinfo psinfo; + int fd = -1; + if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) + return (size_t)0L; /* Can't open? */ + if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) + { + close(fd); + return (size_t)0L; /* Can't read? */ + } + close(fd); + return (size_t)(psinfo.pr_rssize * 1024L); + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) + /* BSD, Linux, and OSX -------------------------------------- */ + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); +#if defined(__APPLE__) && defined(__MACH__) + return (size_t)rusage.ru_maxrss; +#else + return (size_t)(rusage.ru_maxrss * 1024L); +#endif + +#else + /* Unknown OS ----------------------------------------------- */ + return (size_t)0L; /* Unsupported. */ +#endif +} + +/** + * Returns the current resident set size (physical memory use) measured + * in bytes, or zero if the value cannot be determined on this OS. + */ +size_t getCurrentRSS() +{ +#if defined(_WIN32) + /* Windows -------------------------------------------------- */ + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); + return (size_t)info.WorkingSetSize; + +#elif defined(__APPLE__) && defined(__MACH__) + /* OSX ------------------------------------------------------ */ + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, + (task_info_t)&info, &infoCount) != KERN_SUCCESS) + return (size_t)0L; /* Can't access? */ + return (size_t)info.resident_size; + +#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) + /* Linux ---------------------------------------------------- */ + long rss = 0L; + FILE *fp = NULL; + if ((fp = fopen("/proc/self/statm", "r")) == NULL) + return (size_t)0L; /* Can't open? */ + if (fscanf(fp, "%*s%ld", &rss) != 1) + { + fclose(fp); + return (size_t)0L; /* Can't read? */ + } + fclose(fp); + return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE); + +#else + /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ + return (size_t)0L; /* Unsupported. */ +#endif +} \ No newline at end of file diff --git a/src/Build.xml b/src/Build.xml index 87375ce..7dc74c3 100644 --- a/src/Build.xml +++ b/src/Build.xml @@ -57,4 +57,7 @@ + + + \ No newline at end of file diff --git a/src/flixel/FlxG.hx b/src/flixel/FlxG.hx index 99f8faa..937577e 100644 --- a/src/flixel/FlxG.hx +++ b/src/flixel/FlxG.hx @@ -1,5 +1,6 @@ package flixel; +import flixel.util.FlxMemory; import flixel.FlxCamera; import flixel.system.frontEnds.CameraFrontEnd; import flixel.system.frontEnds.SoundFrontEnd; @@ -41,8 +42,10 @@ class FlxG { return getFrameTime(); } - @:allow(flixel.FlxGame.new) static function init(game:FlxGame, width:Int, height:Int) { + @:allow(flixel.FlxGame.new) + static function init(game:FlxGame, width:Int, height:Int) { Log.trace = (v:Dynamic, ?infos:PosInfos) -> untyped __cpp__("std::cout << {0}", '${Log.formatOutput(v, infos)}\n'); + FlxMemory.init(); initialWidth = width; initialHeight = height; cameras.reset(); diff --git a/src/flixel/FlxGame.hx b/src/flixel/FlxGame.hx index 26cd34a..be5d078 100644 --- a/src/flixel/FlxGame.hx +++ b/src/flixel/FlxGame.hx @@ -1,5 +1,10 @@ package flixel; +import flixel.util.FlxStringUtil; +import flixel.util.FlxMemory; +import raylib.Colors; +//import external.memory.Memory; + class FlxGame { public function new(gameWidth:Int = 0, gameHeight:Int = 0, initialState:FlxState, updateFramerate:Int = 60) { initWindow(gameWidth, gameHeight, "FlxProject"); @@ -25,6 +30,7 @@ class FlxGame { } } drawFPS(1, 1); + drawText("\n"+FlxStringUtil.formatBytes(FlxMemory.getMemory()) +" / " + FlxStringUtil.formatBytes(FlxMemory.getPeakMemory()), 1, 1, 20, Colors.LIME); endDrawing(); } closeAudioDevice(); diff --git a/src/flixel/math/FlxMath.hx b/src/flixel/math/FlxMath.hx new file mode 100644 index 0000000..108d641 --- /dev/null +++ b/src/flixel/math/FlxMath.hx @@ -0,0 +1,11 @@ +package flixel.math; + +class FlxMath { + public static function roundDecimal(value:Float, precision:Int):Float { + var mult:Float = 1; + for (i in 0...precision) { + mult *= 10; + } + return Math.fround(value * mult) / mult; + } +} diff --git a/src/flixel/util/FlxMemory.hx b/src/flixel/util/FlxMemory.hx new file mode 100644 index 0000000..aa2b874 --- /dev/null +++ b/src/flixel/util/FlxMemory.hx @@ -0,0 +1,20 @@ +package flixel.util; + +import cpp.Lib; + +class FlxMemory{ + @:allow(flixel.FlxG.init) + private static function init() { + getMemory = Lib.load("memory.ndll", "get_memory_usage", 0); + + getPeakMemory = Lib.load("memory.ndll", "get_memory_peak", 0); + } + + public static dynamic function getMemory():Float { + return 0; + } + + public static dynamic function getPeakMemory():Float { + return 0; + } +} \ No newline at end of file diff --git a/src/flixel/util/FlxStringUtil.hx b/src/flixel/util/FlxStringUtil.hx new file mode 100644 index 0000000..67a4cba --- /dev/null +++ b/src/flixel/util/FlxStringUtil.hx @@ -0,0 +1,15 @@ +package flixel.util; + +import flixel.math.FlxMath; + +class FlxStringUtil { + public static function formatBytes(bytes:Float, precision:Int = 2):String { + var units:Array = ["Bytes", "kB", "MB", "GB", "TB", "PB"]; + var curUnit = 0; + while (bytes >= 1024 && curUnit < units.length - 1) { + bytes /= 1024; + curUnit++; + } + return FlxMath.roundDecimal(bytes, precision) + units[curUnit]; + } +}