~evantj/hare-raylib

3ea8b9d2fe0630e8adbaed5376c01f5bb30db49a — Ember Sawady 1 year, 28 days ago 6880e3e
update for types::c

also get rid of c_bool, since we fixed that abi incompatibility
2 files changed, 287 insertions(+), 489 deletions(-)

M hare-raylib.py
M raylib/raylib.ha
M hare-raylib.py => hare-raylib.py +12 -28
@@ 14,20 14,20 @@ types = {
    "int": ("int", "uint"),
    "float": "f32",
    "double": "f64",
    "short": ("i16", "u16"),
    "long": ("i64", "u64"),
    "char": ("c::schar", "c::uchar"),
    "short": ("c::short", "c::ushort"),
    "long": ("c::long", "c::ulong"),
    "va_list": "valist",
    "bool": "c_bool",
}

keywords = [
    "abort", "alloc", "append", "as", "assert", "bool", "break", "case",
    "char", "const", "continue", "def", "defer", "delete", "else", "enum",
    "export", "f32", "f64", "false", "fn", "for", "free", "i16", "i32", "i64",
    "i8", "if", "insert", "int", "is", "len", "let", "match", "null",
    "nullable", "offset", "return", "rune", "size", "static", "str", "struct",
    "switch", "true", "type", "u16", "u32", "u64", "u8", "uint", "uintptr",
    "union", "use", "void",
    "const", "continue", "def", "defer", "delete", "else", "enum", "export",
    "f32", "f64", "false", "fn", "for", "free", "i16", "i32", "i64", "i8", "if",
    "insert", "int", "is", "len", "let", "match", "null", "nullable", "offset",
    "return", "rune", "size", "static", "str", "struct", "switch", "true",
    "type", "u16", "u32", "u64", "u8", "uint", "uintptr", "union", "use",
    "void",
]

def name(value):


@@ 44,8 44,6 @@ def ctype_to_hare(ctype, unsigned = False, wrapping = False, pointer_array = Fal
        return 'const ' + ctype_to_hare(ctype[6:], unsigned = unsigned, wrapping = wrapping)
    if wrapping and is_string(ctype):
        return "str"
    if wrapping and ctype == "bool":
        return "bool"
    if ctype.startswith('unsigned'):
        return ctype_to_hare(ctype[9:], unsigned = True)
    if ctype[-1] == ']':


@@ 147,18 145,14 @@ def wrapper(function):
    if "params" in function:
        for p in function["params"]:
            if is_string(p["type"]):
                print("\tlet %s_cstring: *char = strings::to_c(%s);" % (name(p), name(p)))
                print("\tlet %s_cstring: *c::char = c::fromstr(%s);" % (name(p), name(p)))
                print("\tdefer free(%s_cstring);" % name(p))
                args += ["%s_cstring" % name(p)]
            elif p["type"] == "bool":
                args += ["if (%s) c_bool::TRUE else c_bool::FALSE" % name(p)]
            else:
                args += [name(p)]
    result = "%s(%s)" % ("_" + function["name"], ', '.join(args))
    if is_string(function["returnType"]):
        result = "strings::fromc(" + result + ")!"
    if function["returnType"] == "bool":
        result = result + " == c_bool::TRUE"
        result = "c::tostr(" + result + ")!"
    print("\treturn %s;" % result)
    print("};\n")



@@ 168,10 162,6 @@ def should_wrap(function):
            return False
        if True in [is_string(p["type"]) for p in function["params"]]:
            return True
        if "bool" in [p["type"] for p in function["params"]]:
            return True
    if function["returnType"] == "bool":
        return True
    if is_string(function["returnType"]):
        return True
    return False


@@ 192,13 182,7 @@ f = open(sys.argv[1], "r")
api = json.load(f)
print(
"""
use strings;

// c boolean
export type c_bool = enum u8 {
	FALSE = 0,
	TRUE = 1,
};
use types::c;

// internal to raudio
export type rAudioProcessor = void;

M raylib/raylib.ha => raylib/raylib.ha +275 -461
@@ 1,11 1,5 @@

use strings;

// c boolean
export type c_bool = enum u8 {
	FALSE = 0,
	TRUE = 1,
};
use types::c;

// internal to raudio
export type rAudioProcessor = void;


@@ 169,13 163,13 @@ export type Matrix = struct {
// Color, 4 components, R8G8B8A8 (32bit)
export type Color = struct {
	// Color red value
	r: char,
	r: c::uchar,
	// Color green value
	g: char,
	g: c::uchar,
	// Color blue value
	b: char,
	b: c::uchar,
	// Color alpha value
	a: char,
	a: c::uchar,
};

// Rectangle, 4 components


@@ 317,15 311,15 @@ export type Mesh = struct {
	// Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
	tangents: *[*]f32,
	// Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
	colors: *char,
	colors: *c::uchar,
	// Vertex indices (in case vertex data comes indexed)
	indices: *u16,
	indices: *c::ushort,
	// Animated vertex positions (after bones transformations)
	animVertices: *[*]f32,
	// Animated normals (after bones transformations)
	animNormals: *[*]f32,
	// Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning)
	boneIds: *char,
	boneIds: *c::uchar,
	// Vertex bone weight, up to 4 bones influence by vertex (skinning)
	boneWeights: *[*]f32,
	// OpenGL Vertex Array Object id


@@ 375,7 369,7 @@ export type Transform = struct {
// Bone, skeletal animation bone
export type BoneInfo = struct {
	// Bone name
	name: [32]char,
	name: [32]c::schar,
	// Bone parent
	parent: int,
};


@@ 425,7 419,7 @@ export type Ray = struct {
// RayCollision, ray hit information
export type RayCollision = struct {
	// Did the ray hit something?
	hit: c_bool,
	hit: bool,
	// Distance to nearest hit
	distance: f32,
	// Point of nearest hit


@@ 483,7 477,7 @@ export type Music = struct {
	// Total number of frames (considering channels)
	frameCount: uint,
	// Music looping enable
	looping: c_bool,
	looping: bool,
	// Type of music context (audio filetype)
	ctxType: int,
	// Audio context data, depends on type


@@ 1216,94 1210,58 @@ export type NPatchLayout = enum {
};

// Logging: Redirect trace log messages
export type TraceLogCallback = *fn(logLevel: int, text: const *char, args: valist) void;
export type TraceLogCallback = *fn(logLevel: int, text: const *c::schar, args: valist) void;

// FileIO: Load binary data
export type LoadFileDataCallback = *fn(fileName: const *char, bytesRead: *uint) *char;
export type LoadFileDataCallback = *fn(fileName: const *c::schar, bytesRead: *uint) *c::uchar;

// FileIO: Save binary data
export type SaveFileDataCallback = *fn(fileName: const *char, data: *void, bytesToWrite: uint) c_bool;
export type SaveFileDataCallback = *fn(fileName: const *c::schar, data: *void, bytesToWrite: uint) bool;

// FileIO: Load text data
export type LoadFileTextCallback = *fn(fileName: const *char) *char;
export type LoadFileTextCallback = *fn(fileName: const *c::schar) *c::schar;

// FileIO: Save text data
export type SaveFileTextCallback = *fn(fileName: const *char, text: *char) c_bool;
export type SaveFileTextCallback = *fn(fileName: const *c::schar, text: *c::schar) bool;

@symbol("InitWindow") fn _InitWindow(width: int, height: int, title: const *char) void;
@symbol("InitWindow") fn _InitWindow(width: int, height: int, title: const *c::schar) void;

// Initialize window and OpenGL context
export fn InitWindow(width: int, height: int, title: const str) void = {
	let title_cstring: *char = strings::to_c(title);
	let title_cstring: *c::char = c::fromstr(title);
	defer free(title_cstring);
	return _InitWindow(width, height, title_cstring);
};

@symbol("WindowShouldClose") fn _WindowShouldClose() c_bool;

// Check if KEY_ESCAPE pressed or Close icon pressed
export fn WindowShouldClose() bool = {
	return _WindowShouldClose() == c_bool::TRUE;
};
export @symbol("WindowShouldClose") fn WindowShouldClose() bool;

// Close window and unload OpenGL context
export @symbol("CloseWindow") fn CloseWindow() void;

@symbol("IsWindowReady") fn _IsWindowReady() c_bool;

// Check if window has been initialized successfully
export fn IsWindowReady() bool = {
	return _IsWindowReady() == c_bool::TRUE;
};

@symbol("IsWindowFullscreen") fn _IsWindowFullscreen() c_bool;
export @symbol("IsWindowReady") fn IsWindowReady() bool;

// Check if window is currently fullscreen
export fn IsWindowFullscreen() bool = {
	return _IsWindowFullscreen() == c_bool::TRUE;
};

@symbol("IsWindowHidden") fn _IsWindowHidden() c_bool;
export @symbol("IsWindowFullscreen") fn IsWindowFullscreen() bool;

// Check if window is currently hidden (only PLATFORM_DESKTOP)
export fn IsWindowHidden() bool = {
	return _IsWindowHidden() == c_bool::TRUE;
};

@symbol("IsWindowMinimized") fn _IsWindowMinimized() c_bool;
export @symbol("IsWindowHidden") fn IsWindowHidden() bool;

// Check if window is currently minimized (only PLATFORM_DESKTOP)
export fn IsWindowMinimized() bool = {
	return _IsWindowMinimized() == c_bool::TRUE;
};

@symbol("IsWindowMaximized") fn _IsWindowMaximized() c_bool;
export @symbol("IsWindowMinimized") fn IsWindowMinimized() bool;

// Check if window is currently maximized (only PLATFORM_DESKTOP)
export fn IsWindowMaximized() bool = {
	return _IsWindowMaximized() == c_bool::TRUE;
};

@symbol("IsWindowFocused") fn _IsWindowFocused() c_bool;
export @symbol("IsWindowMaximized") fn IsWindowMaximized() bool;

// Check if window is currently focused (only PLATFORM_DESKTOP)
export fn IsWindowFocused() bool = {
	return _IsWindowFocused() == c_bool::TRUE;
};

@symbol("IsWindowResized") fn _IsWindowResized() c_bool;
export @symbol("IsWindowFocused") fn IsWindowFocused() bool;

// Check if window has been resized last frame
export fn IsWindowResized() bool = {
	return _IsWindowResized() == c_bool::TRUE;
};

@symbol("IsWindowState") fn _IsWindowState(flag: uint) c_bool;
export @symbol("IsWindowResized") fn IsWindowResized() bool;

// Check if one specific window flag is enabled
export fn IsWindowState(flag: uint) bool = {
	return _IsWindowState(flag) == c_bool::TRUE;
};
export @symbol("IsWindowState") fn IsWindowState(flag: uint) bool;

// Set window configuration state using flags
export @symbol("SetWindowState") fn SetWindowState(flags: uint) void;


@@ 1326,11 1284,11 @@ export @symbol("RestoreWindow") fn RestoreWindow() void;
// Set icon for window (only PLATFORM_DESKTOP)
export @symbol("SetWindowIcon") fn SetWindowIcon(image: Image) void;

@symbol("SetWindowTitle") fn _SetWindowTitle(title: const *char) void;
@symbol("SetWindowTitle") fn _SetWindowTitle(title: const *c::schar) void;

// Set title for window (only PLATFORM_DESKTOP)
export fn SetWindowTitle(title: const str) void = {
	let title_cstring: *char = strings::to_c(title);
	let title_cstring: *c::char = c::fromstr(title);
	defer free(title_cstring);
	return _SetWindowTitle(title_cstring);
};


@@ 1386,27 1344,27 @@ export @symbol("GetWindowPosition") fn GetWindowPosition() Vector2;
// Get window scale DPI factor
export @symbol("GetWindowScaleDPI") fn GetWindowScaleDPI() Vector2;

@symbol("GetMonitorName") fn _GetMonitorName(monitor: int) const *char;
@symbol("GetMonitorName") fn _GetMonitorName(monitor: int) const *c::schar;

// Get the human-readable, UTF-8 encoded name of the primary monitor
export fn GetMonitorName(monitor: int) const str = {
	return strings::fromc(_GetMonitorName(monitor))!;
	return c::tostr(_GetMonitorName(monitor))!;
};

@symbol("SetClipboardText") fn _SetClipboardText(text: const *char) void;
@symbol("SetClipboardText") fn _SetClipboardText(text: const *c::schar) void;

// Set clipboard text content
export fn SetClipboardText(text: const str) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _SetClipboardText(text_cstring);
};

@symbol("GetClipboardText") fn _GetClipboardText() const *char;
@symbol("GetClipboardText") fn _GetClipboardText() const *c::schar;

// Get clipboard text content
export fn GetClipboardText() const str = {
	return strings::fromc(_GetClipboardText())!;
	return c::tostr(_GetClipboardText())!;
};

// Swap back buffer with front buffer (screen drawing)


@@ 1424,12 1382,8 @@ export @symbol("ShowCursor") fn ShowCursor() void;
// Hides cursor
export @symbol("HideCursor") fn HideCursor() void;

@symbol("IsCursorHidden") fn _IsCursorHidden() c_bool;

// Check if cursor is not visible
export fn IsCursorHidden() bool = {
	return _IsCursorHidden() == c_bool::TRUE;
};
export @symbol("IsCursorHidden") fn IsCursorHidden() bool;

// Enables cursor (unlock cursor)
export @symbol("EnableCursor") fn EnableCursor() void;


@@ 1437,12 1391,8 @@ export @symbol("EnableCursor") fn EnableCursor() void;
// Disables cursor (lock cursor)
export @symbol("DisableCursor") fn DisableCursor() void;

@symbol("IsCursorOnScreen") fn _IsCursorOnScreen() c_bool;

// Check if cursor is on the screen
export fn IsCursorOnScreen() bool = {
	return _IsCursorOnScreen() == c_bool::TRUE;
};
export @symbol("IsCursorOnScreen") fn IsCursorOnScreen() bool;

// Set background color (framebuffer clear color)
export @symbol("ClearBackground") fn ClearBackground(color: Color) void;


@@ 1501,42 1451,42 @@ export @symbol("LoadVrStereoConfig") fn LoadVrStereoConfig(device: VrDeviceInfo)
// Unload VR stereo config
export @symbol("UnloadVrStereoConfig") fn UnloadVrStereoConfig(config: VrStereoConfig) void;

@symbol("LoadShader") fn _LoadShader(vsFileName: const *char, fsFileName: const *char) Shader;
@symbol("LoadShader") fn _LoadShader(vsFileName: const *c::schar, fsFileName: const *c::schar) Shader;

// Load shader from files and bind default locations
export fn LoadShader(vsFileName: const str, fsFileName: const str) Shader = {
	let vsFileName_cstring: *char = strings::to_c(vsFileName);
	let vsFileName_cstring: *c::char = c::fromstr(vsFileName);
	defer free(vsFileName_cstring);
	let fsFileName_cstring: *char = strings::to_c(fsFileName);
	let fsFileName_cstring: *c::char = c::fromstr(fsFileName);
	defer free(fsFileName_cstring);
	return _LoadShader(vsFileName_cstring, fsFileName_cstring);
};

@symbol("LoadShaderFromMemory") fn _LoadShaderFromMemory(vsCode: const *char, fsCode: const *char) Shader;
@symbol("LoadShaderFromMemory") fn _LoadShaderFromMemory(vsCode: const *c::schar, fsCode: const *c::schar) Shader;

// Load shader from code strings and bind default locations
export fn LoadShaderFromMemory(vsCode: const str, fsCode: const str) Shader = {
	let vsCode_cstring: *char = strings::to_c(vsCode);
	let vsCode_cstring: *c::char = c::fromstr(vsCode);
	defer free(vsCode_cstring);
	let fsCode_cstring: *char = strings::to_c(fsCode);
	let fsCode_cstring: *c::char = c::fromstr(fsCode);
	defer free(fsCode_cstring);
	return _LoadShaderFromMemory(vsCode_cstring, fsCode_cstring);
};

@symbol("GetShaderLocation") fn _GetShaderLocation(shader: Shader, uniformName: const *char) int;
@symbol("GetShaderLocation") fn _GetShaderLocation(shader: Shader, uniformName: const *c::schar) int;

// Get shader uniform location
export fn GetShaderLocation(shader: Shader, uniformName: const str) int = {
	let uniformName_cstring: *char = strings::to_c(uniformName);
	let uniformName_cstring: *c::char = c::fromstr(uniformName);
	defer free(uniformName_cstring);
	return _GetShaderLocation(shader, uniformName_cstring);
};

@symbol("GetShaderLocationAttrib") fn _GetShaderLocationAttrib(shader: Shader, attribName: const *char) int;
@symbol("GetShaderLocationAttrib") fn _GetShaderLocationAttrib(shader: Shader, attribName: const *c::schar) int;

// Get shader attribute location
export fn GetShaderLocationAttrib(shader: Shader, attribName: const str) int = {
	let attribName_cstring: *char = strings::to_c(attribName);
	let attribName_cstring: *c::char = c::fromstr(attribName);
	defer free(attribName_cstring);
	return _GetShaderLocationAttrib(shader, attribName_cstring);
};


@@ 1595,11 1545,11 @@ export @symbol("GetRandomValue") fn GetRandomValue(min: int, max: int) int;
// Set the seed for the random number generator
export @symbol("SetRandomSeed") fn SetRandomSeed(seed: uint) void;

@symbol("TakeScreenshot") fn _TakeScreenshot(fileName: const *char) void;
@symbol("TakeScreenshot") fn _TakeScreenshot(fileName: const *c::schar) void;

// Takes a screenshot of current screen (filename extension defines format)
export fn TakeScreenshot(fileName: const str) void = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _TakeScreenshot(fileName_cstring);
};


@@ 1608,7 1558,7 @@ export fn TakeScreenshot(fileName: const str) void = {
export @symbol("SetConfigFlags") fn SetConfigFlags(flags: uint) void;

// Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
export @symbol("TraceLog") fn TraceLog(logLevel: int, text: const *char, ...) void;
export @symbol("TraceLog") fn TraceLog(logLevel: int, text: const *c::schar, ...) void;

// Set the current threshold (minimum) log level
export @symbol("SetTraceLogLevel") fn SetTraceLogLevel(logLevel: int) void;


@@ 1637,142 1587,142 @@ export @symbol("SetLoadFileTextCallback") fn SetLoadFileTextCallback(callback: L
// Set custom file text data saver
export @symbol("SetSaveFileTextCallback") fn SetSaveFileTextCallback(callback: SaveFileTextCallback) void;

@symbol("LoadFileData") fn _LoadFileData(fileName: const *char, bytesRead: *uint) *char;
@symbol("LoadFileData") fn _LoadFileData(fileName: const *c::schar, bytesRead: *uint) *c::uchar;

// Load file data as byte array (read)
export fn LoadFileData(fileName: const str, bytesRead: *uint) *char = {
	let fileName_cstring: *char = strings::to_c(fileName);
export fn LoadFileData(fileName: const str, bytesRead: *uint) *c::uchar = {
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadFileData(fileName_cstring, bytesRead);
};

// Unload file data allocated by LoadFileData()
export @symbol("UnloadFileData") fn UnloadFileData(data: *char) void;
export @symbol("UnloadFileData") fn UnloadFileData(data: *c::uchar) void;

@symbol("SaveFileData") fn _SaveFileData(fileName: const *char, data: *void, bytesToWrite: uint) c_bool;
@symbol("SaveFileData") fn _SaveFileData(fileName: const *c::schar, data: *void, bytesToWrite: uint) bool;

// Save data to file from byte array (write), returns true on success
export fn SaveFileData(fileName: const str, data: *void, bytesToWrite: uint) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _SaveFileData(fileName_cstring, data, bytesToWrite) == c_bool::TRUE;
	return _SaveFileData(fileName_cstring, data, bytesToWrite);
};

@symbol("LoadFileText") fn _LoadFileText(fileName: const *char) *char;
@symbol("LoadFileText") fn _LoadFileText(fileName: const *c::schar) *c::schar;

// Load text data from file (read), returns a '\0' terminated string
export fn LoadFileText(fileName: const str) str = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return strings::fromc(_LoadFileText(fileName_cstring))!;
	return c::tostr(_LoadFileText(fileName_cstring))!;
};

@symbol("UnloadFileText") fn _UnloadFileText(text: *char) void;
@symbol("UnloadFileText") fn _UnloadFileText(text: *c::schar) void;

// Unload file text data allocated by LoadFileText()
export fn UnloadFileText(text: str) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _UnloadFileText(text_cstring);
};

@symbol("SaveFileText") fn _SaveFileText(fileName: const *char, text: *char) c_bool;
@symbol("SaveFileText") fn _SaveFileText(fileName: const *c::schar, text: *c::schar) bool;

// Save text data to file (write), string must be '\0' terminated, returns true on success
export fn SaveFileText(fileName: const str, text: str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _SaveFileText(fileName_cstring, text_cstring) == c_bool::TRUE;
	return _SaveFileText(fileName_cstring, text_cstring);
};

@symbol("FileExists") fn _FileExists(fileName: const *char) c_bool;
@symbol("FileExists") fn _FileExists(fileName: const *c::schar) bool;

// Check if file exists
export fn FileExists(fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _FileExists(fileName_cstring) == c_bool::TRUE;
	return _FileExists(fileName_cstring);
};

@symbol("DirectoryExists") fn _DirectoryExists(dirPath: const *char) c_bool;
@symbol("DirectoryExists") fn _DirectoryExists(dirPath: const *c::schar) bool;

// Check if a directory path exists
export fn DirectoryExists(dirPath: const str) bool = {
	let dirPath_cstring: *char = strings::to_c(dirPath);
	let dirPath_cstring: *c::char = c::fromstr(dirPath);
	defer free(dirPath_cstring);
	return _DirectoryExists(dirPath_cstring) == c_bool::TRUE;
	return _DirectoryExists(dirPath_cstring);
};

@symbol("IsFileExtension") fn _IsFileExtension(fileName: const *char, ext: const *char) c_bool;
@symbol("IsFileExtension") fn _IsFileExtension(fileName: const *c::schar, ext: const *c::schar) bool;

// Check file extension (including point: .png, .wav)
export fn IsFileExtension(fileName: const str, ext: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	let ext_cstring: *char = strings::to_c(ext);
	let ext_cstring: *c::char = c::fromstr(ext);
	defer free(ext_cstring);
	return _IsFileExtension(fileName_cstring, ext_cstring) == c_bool::TRUE;
	return _IsFileExtension(fileName_cstring, ext_cstring);
};

@symbol("GetFileExtension") fn _GetFileExtension(fileName: const *char) const *char;
@symbol("GetFileExtension") fn _GetFileExtension(fileName: const *c::schar) const *c::schar;

// Get pointer to extension for a filename string (includes dot: '.png')
export fn GetFileExtension(fileName: const str) const str = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return strings::fromc(_GetFileExtension(fileName_cstring))!;
	return c::tostr(_GetFileExtension(fileName_cstring))!;
};

@symbol("GetFileName") fn _GetFileName(filePath: const *char) const *char;
@symbol("GetFileName") fn _GetFileName(filePath: const *c::schar) const *c::schar;

// Get pointer to filename for a path string
export fn GetFileName(filePath: const str) const str = {
	let filePath_cstring: *char = strings::to_c(filePath);
	let filePath_cstring: *c::char = c::fromstr(filePath);
	defer free(filePath_cstring);
	return strings::fromc(_GetFileName(filePath_cstring))!;
	return c::tostr(_GetFileName(filePath_cstring))!;
};

@symbol("GetFileNameWithoutExt") fn _GetFileNameWithoutExt(filePath: const *char) const *char;
@symbol("GetFileNameWithoutExt") fn _GetFileNameWithoutExt(filePath: const *c::schar) const *c::schar;

// Get filename string without extension (uses static string)
export fn GetFileNameWithoutExt(filePath: const str) const str = {
	let filePath_cstring: *char = strings::to_c(filePath);
	let filePath_cstring: *c::char = c::fromstr(filePath);
	defer free(filePath_cstring);
	return strings::fromc(_GetFileNameWithoutExt(filePath_cstring))!;
	return c::tostr(_GetFileNameWithoutExt(filePath_cstring))!;
};

@symbol("GetDirectoryPath") fn _GetDirectoryPath(filePath: const *char) const *char;
@symbol("GetDirectoryPath") fn _GetDirectoryPath(filePath: const *c::schar) const *c::schar;

// Get full path for a given fileName with path (uses static string)
export fn GetDirectoryPath(filePath: const str) const str = {
	let filePath_cstring: *char = strings::to_c(filePath);
	let filePath_cstring: *c::char = c::fromstr(filePath);
	defer free(filePath_cstring);
	return strings::fromc(_GetDirectoryPath(filePath_cstring))!;
	return c::tostr(_GetDirectoryPath(filePath_cstring))!;
};

@symbol("GetPrevDirectoryPath") fn _GetPrevDirectoryPath(dirPath: const *char) const *char;
@symbol("GetPrevDirectoryPath") fn _GetPrevDirectoryPath(dirPath: const *c::schar) const *c::schar;

// Get previous directory path for a given path (uses static string)
export fn GetPrevDirectoryPath(dirPath: const str) const str = {
	let dirPath_cstring: *char = strings::to_c(dirPath);
	let dirPath_cstring: *c::char = c::fromstr(dirPath);
	defer free(dirPath_cstring);
	return strings::fromc(_GetPrevDirectoryPath(dirPath_cstring))!;
	return c::tostr(_GetPrevDirectoryPath(dirPath_cstring))!;
};

@symbol("GetWorkingDirectory") fn _GetWorkingDirectory() const *char;
@symbol("GetWorkingDirectory") fn _GetWorkingDirectory() const *c::schar;

// Get current working directory (uses static string)
export fn GetWorkingDirectory() const str = {
	return strings::fromc(_GetWorkingDirectory())!;
	return c::tostr(_GetWorkingDirectory())!;
};

@symbol("GetDirectoryFiles") fn _GetDirectoryFiles(dirPath: const *char, count: *int) **char;
@symbol("GetDirectoryFiles") fn _GetDirectoryFiles(dirPath: const *c::schar, count: *int) **c::schar;

// Get filenames in a directory path (memory should be freed)
export fn GetDirectoryFiles(dirPath: const str, count: *int) **char = {
	let dirPath_cstring: *char = strings::to_c(dirPath);
export fn GetDirectoryFiles(dirPath: const str, count: *int) **c::schar = {
	let dirPath_cstring: *c::char = c::fromstr(dirPath);
	defer free(dirPath_cstring);
	return _GetDirectoryFiles(dirPath_cstring, count);
};


@@ 1780,99 1730,75 @@ export fn GetDirectoryFiles(dirPath: const str, count: *int) **char = {
// Clear directory files paths buffers (free memory)
export @symbol("ClearDirectoryFiles") fn ClearDirectoryFiles() void;

@symbol("ChangeDirectory") fn _ChangeDirectory(dir: const *char) c_bool;
@symbol("ChangeDirectory") fn _ChangeDirectory(dir: const *c::schar) bool;

// Change working directory, return true on success
export fn ChangeDirectory(dir: const str) bool = {
	let dir_cstring: *char = strings::to_c(dir);
	let dir_cstring: *c::char = c::fromstr(dir);
	defer free(dir_cstring);
	return _ChangeDirectory(dir_cstring) == c_bool::TRUE;
	return _ChangeDirectory(dir_cstring);
};

@symbol("IsFileDropped") fn _IsFileDropped() c_bool;

// Check if a file has been dropped into window
export fn IsFileDropped() bool = {
	return _IsFileDropped() == c_bool::TRUE;
};
export @symbol("IsFileDropped") fn IsFileDropped() bool;

// Get dropped files names (memory should be freed)
export @symbol("GetDroppedFiles") fn GetDroppedFiles(count: *int) **char;
export @symbol("GetDroppedFiles") fn GetDroppedFiles(count: *int) **c::schar;

// Clear dropped files paths buffer (free memory)
export @symbol("ClearDroppedFiles") fn ClearDroppedFiles() void;

@symbol("GetFileModTime") fn _GetFileModTime(fileName: const *char) i64;
@symbol("GetFileModTime") fn _GetFileModTime(fileName: const *c::schar) c::long;

// Get file modification time (last write time)
export fn GetFileModTime(fileName: const str) i64 = {
	let fileName_cstring: *char = strings::to_c(fileName);
export fn GetFileModTime(fileName: const str) c::long = {
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _GetFileModTime(fileName_cstring);
};

// Compress data (DEFLATE algorithm)
export @symbol("CompressData") fn CompressData(data: *char, dataLength: int, compDataLength: *int) *char;
export @symbol("CompressData") fn CompressData(data: *c::uchar, dataLength: int, compDataLength: *int) *c::uchar;

// Decompress data (DEFLATE algorithm)
export @symbol("DecompressData") fn DecompressData(compData: *char, compDataLength: int, dataLength: *int) *char;
export @symbol("DecompressData") fn DecompressData(compData: *c::uchar, compDataLength: int, dataLength: *int) *c::uchar;

@symbol("EncodeDataBase64") fn _EncodeDataBase64(data: const *char, dataLength: int, outputLength: *int) *char;
@symbol("EncodeDataBase64") fn _EncodeDataBase64(data: const *c::uchar, dataLength: int, outputLength: *int) *c::schar;

// Encode data to Base64 string
export fn EncodeDataBase64(data: const *char, dataLength: int, outputLength: *int) str = {
	return strings::fromc(_EncodeDataBase64(data, dataLength, outputLength))!;
export fn EncodeDataBase64(data: const *c::uchar, dataLength: int, outputLength: *int) str = {
	return c::tostr(_EncodeDataBase64(data, dataLength, outputLength))!;
};

// Decode Base64 string data
export @symbol("DecodeDataBase64") fn DecodeDataBase64(data: *char, outputLength: *int) *char;

@symbol("SaveStorageValue") fn _SaveStorageValue(position: uint, value: int) c_bool;
export @symbol("DecodeDataBase64") fn DecodeDataBase64(data: *c::uchar, outputLength: *int) *c::uchar;

// Save integer value to storage file (to defined position), returns true on success
export fn SaveStorageValue(position: uint, value: int) bool = {
	return _SaveStorageValue(position, value) == c_bool::TRUE;
};
export @symbol("SaveStorageValue") fn SaveStorageValue(position: uint, value: int) bool;

// Load integer value from storage file (from defined position)
export @symbol("LoadStorageValue") fn LoadStorageValue(position: uint) int;

@symbol("OpenURL") fn _OpenURL(url: const *char) void;
@symbol("OpenURL") fn _OpenURL(url: const *c::schar) void;

// Open URL with default system browser (if available)
export fn OpenURL(url: const str) void = {
	let url_cstring: *char = strings::to_c(url);
	let url_cstring: *c::char = c::fromstr(url);
	defer free(url_cstring);
	return _OpenURL(url_cstring);
};

@symbol("IsKeyPressed") fn _IsKeyPressed(key: int) c_bool;

// Check if a key has been pressed once
export fn IsKeyPressed(key: int) bool = {
	return _IsKeyPressed(key) == c_bool::TRUE;
};

@symbol("IsKeyDown") fn _IsKeyDown(key: int) c_bool;
export @symbol("IsKeyPressed") fn IsKeyPressed(key: int) bool;

// Check if a key is being pressed
export fn IsKeyDown(key: int) bool = {
	return _IsKeyDown(key) == c_bool::TRUE;
};

@symbol("IsKeyReleased") fn _IsKeyReleased(key: int) c_bool;
export @symbol("IsKeyDown") fn IsKeyDown(key: int) bool;

// Check if a key has been released once
export fn IsKeyReleased(key: int) bool = {
	return _IsKeyReleased(key) == c_bool::TRUE;
};

@symbol("IsKeyUp") fn _IsKeyUp(key: int) c_bool;
export @symbol("IsKeyReleased") fn IsKeyReleased(key: int) bool;

// Check if a key is NOT being pressed
export fn IsKeyUp(key: int) bool = {
	return _IsKeyUp(key) == c_bool::TRUE;
};
export @symbol("IsKeyUp") fn IsKeyUp(key: int) bool;

// Set a custom key to exit program (default is ESC)
export @symbol("SetExitKey") fn SetExitKey(key: int) void;


@@ 1883,47 1809,27 @@ export @symbol("GetKeyPressed") fn GetKeyPressed() int;
// Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
export @symbol("GetCharPressed") fn GetCharPressed() int;

@symbol("IsGamepadAvailable") fn _IsGamepadAvailable(gamepad: int) c_bool;

// Check if a gamepad is available
export fn IsGamepadAvailable(gamepad: int) bool = {
	return _IsGamepadAvailable(gamepad) == c_bool::TRUE;
};
export @symbol("IsGamepadAvailable") fn IsGamepadAvailable(gamepad: int) bool;

@symbol("GetGamepadName") fn _GetGamepadName(gamepad: int) const *char;
@symbol("GetGamepadName") fn _GetGamepadName(gamepad: int) const *c::schar;

// Get gamepad internal name id
export fn GetGamepadName(gamepad: int) const str = {
	return strings::fromc(_GetGamepadName(gamepad))!;
	return c::tostr(_GetGamepadName(gamepad))!;
};

@symbol("IsGamepadButtonPressed") fn _IsGamepadButtonPressed(gamepad: int, button: int) c_bool;

// Check if a gamepad button has been pressed once
export fn IsGamepadButtonPressed(gamepad: int, button: int) bool = {
	return _IsGamepadButtonPressed(gamepad, button) == c_bool::TRUE;
};

@symbol("IsGamepadButtonDown") fn _IsGamepadButtonDown(gamepad: int, button: int) c_bool;
export @symbol("IsGamepadButtonPressed") fn IsGamepadButtonPressed(gamepad: int, button: int) bool;

// Check if a gamepad button is being pressed
export fn IsGamepadButtonDown(gamepad: int, button: int) bool = {
	return _IsGamepadButtonDown(gamepad, button) == c_bool::TRUE;
};

@symbol("IsGamepadButtonReleased") fn _IsGamepadButtonReleased(gamepad: int, button: int) c_bool;
export @symbol("IsGamepadButtonDown") fn IsGamepadButtonDown(gamepad: int, button: int) bool;

// Check if a gamepad button has been released once
export fn IsGamepadButtonReleased(gamepad: int, button: int) bool = {
	return _IsGamepadButtonReleased(gamepad, button) == c_bool::TRUE;
};

@symbol("IsGamepadButtonUp") fn _IsGamepadButtonUp(gamepad: int, button: int) c_bool;
export @symbol("IsGamepadButtonReleased") fn IsGamepadButtonReleased(gamepad: int, button: int) bool;

// Check if a gamepad button is NOT being pressed
export fn IsGamepadButtonUp(gamepad: int, button: int) bool = {
	return _IsGamepadButtonUp(gamepad, button) == c_bool::TRUE;
};
export @symbol("IsGamepadButtonUp") fn IsGamepadButtonUp(gamepad: int, button: int) bool;

// Get the last gamepad button pressed
export @symbol("GetGamepadButtonPressed") fn GetGamepadButtonPressed() int;


@@ 1934,42 1840,26 @@ export @symbol("GetGamepadAxisCount") fn GetGamepadAxisCount(gamepad: int) int;
// Get axis movement value for a gamepad axis
export @symbol("GetGamepadAxisMovement") fn GetGamepadAxisMovement(gamepad: int, axis: int) f32;

@symbol("SetGamepadMappings") fn _SetGamepadMappings(mappings: const *char) int;
@symbol("SetGamepadMappings") fn _SetGamepadMappings(mappings: const *c::schar) int;

// Set internal gamepad mappings (SDL_GameControllerDB)
export fn SetGamepadMappings(mappings: const str) int = {
	let mappings_cstring: *char = strings::to_c(mappings);
	let mappings_cstring: *c::char = c::fromstr(mappings);
	defer free(mappings_cstring);
	return _SetGamepadMappings(mappings_cstring);
};

@symbol("IsMouseButtonPressed") fn _IsMouseButtonPressed(button: int) c_bool;

// Check if a mouse button has been pressed once
export fn IsMouseButtonPressed(button: int) bool = {
	return _IsMouseButtonPressed(button) == c_bool::TRUE;
};

@symbol("IsMouseButtonDown") fn _IsMouseButtonDown(button: int) c_bool;
export @symbol("IsMouseButtonPressed") fn IsMouseButtonPressed(button: int) bool;

// Check if a mouse button is being pressed
export fn IsMouseButtonDown(button: int) bool = {
	return _IsMouseButtonDown(button) == c_bool::TRUE;
};

@symbol("IsMouseButtonReleased") fn _IsMouseButtonReleased(button: int) c_bool;
export @symbol("IsMouseButtonDown") fn IsMouseButtonDown(button: int) bool;

// Check if a mouse button has been released once
export fn IsMouseButtonReleased(button: int) bool = {
	return _IsMouseButtonReleased(button) == c_bool::TRUE;
};

@symbol("IsMouseButtonUp") fn _IsMouseButtonUp(button: int) c_bool;
export @symbol("IsMouseButtonReleased") fn IsMouseButtonReleased(button: int) bool;

// Check if a mouse button is NOT being pressed
export fn IsMouseButtonUp(button: int) bool = {
	return _IsMouseButtonUp(button) == c_bool::TRUE;
};
export @symbol("IsMouseButtonUp") fn IsMouseButtonUp(button: int) bool;

// Get mouse position X
export @symbol("GetMouseX") fn GetMouseX() int;


@@ 2016,12 1906,8 @@ export @symbol("GetTouchPointCount") fn GetTouchPointCount() int;
// Enable a set of gestures using flags
export @symbol("SetGesturesEnabled") fn SetGesturesEnabled(flags: uint) void;

@symbol("IsGestureDetected") fn _IsGestureDetected(gesture: int) c_bool;

// Check if a gesture have been detected
export fn IsGestureDetected(gesture: int) bool = {
	return _IsGestureDetected(gesture) == c_bool::TRUE;
};
export @symbol("IsGestureDetected") fn IsGestureDetected(gesture: int) bool;

// Get latest detected gesture
export @symbol("GetGestureDetected") fn GetGestureDetected() int;


@@ 2173,97 2059,65 @@ export @symbol("DrawPolyLines") fn DrawPolyLines(center: Vector2, sides: int, ra
// Draw a polygon outline of n sides with extended parameters
export @symbol("DrawPolyLinesEx") fn DrawPolyLinesEx(center: Vector2, sides: int, radius: f32, rotation: f32, lineThick: f32, color: Color) void;

@symbol("CheckCollisionRecs") fn _CheckCollisionRecs(rec1: Rectangle, rec2: Rectangle) c_bool;

// Check collision between two rectangles
export fn CheckCollisionRecs(rec1: Rectangle, rec2: Rectangle) bool = {
	return _CheckCollisionRecs(rec1, rec2) == c_bool::TRUE;
};

@symbol("CheckCollisionCircles") fn _CheckCollisionCircles(center1: Vector2, radius1: f32, center2: Vector2, radius2: f32) c_bool;
export @symbol("CheckCollisionRecs") fn CheckCollisionRecs(rec1: Rectangle, rec2: Rectangle) bool;

// Check collision between two circles
export fn CheckCollisionCircles(center1: Vector2, radius1: f32, center2: Vector2, radius2: f32) bool = {
	return _CheckCollisionCircles(center1, radius1, center2, radius2) == c_bool::TRUE;
};

@symbol("CheckCollisionCircleRec") fn _CheckCollisionCircleRec(center: Vector2, radius: f32, rec: Rectangle) c_bool;
export @symbol("CheckCollisionCircles") fn CheckCollisionCircles(center1: Vector2, radius1: f32, center2: Vector2, radius2: f32) bool;

// Check collision between circle and rectangle
export fn CheckCollisionCircleRec(center: Vector2, radius: f32, rec: Rectangle) bool = {
	return _CheckCollisionCircleRec(center, radius, rec) == c_bool::TRUE;
};

@symbol("CheckCollisionPointRec") fn _CheckCollisionPointRec(point: Vector2, rec: Rectangle) c_bool;
export @symbol("CheckCollisionCircleRec") fn CheckCollisionCircleRec(center: Vector2, radius: f32, rec: Rectangle) bool;

// Check if point is inside rectangle
export fn CheckCollisionPointRec(point: Vector2, rec: Rectangle) bool = {
	return _CheckCollisionPointRec(point, rec) == c_bool::TRUE;
};

@symbol("CheckCollisionPointCircle") fn _CheckCollisionPointCircle(point: Vector2, center: Vector2, radius: f32) c_bool;
export @symbol("CheckCollisionPointRec") fn CheckCollisionPointRec(point: Vector2, rec: Rectangle) bool;

// Check if point is inside circle
export fn CheckCollisionPointCircle(point: Vector2, center: Vector2, radius: f32) bool = {
	return _CheckCollisionPointCircle(point, center, radius) == c_bool::TRUE;
};

@symbol("CheckCollisionPointTriangle") fn _CheckCollisionPointTriangle(point: Vector2, p1: Vector2, p2: Vector2, p3: Vector2) c_bool;
export @symbol("CheckCollisionPointCircle") fn CheckCollisionPointCircle(point: Vector2, center: Vector2, radius: f32) bool;

// Check if point is inside a triangle
export fn CheckCollisionPointTriangle(point: Vector2, p1: Vector2, p2: Vector2, p3: Vector2) bool = {
	return _CheckCollisionPointTriangle(point, p1, p2, p3) == c_bool::TRUE;
};

@symbol("CheckCollisionLines") fn _CheckCollisionLines(startPos1: Vector2, endPos1: Vector2, startPos2: Vector2, endPos2: Vector2, collisionPoint: *Vector2) c_bool;
export @symbol("CheckCollisionPointTriangle") fn CheckCollisionPointTriangle(point: Vector2, p1: Vector2, p2: Vector2, p3: Vector2) bool;

// Check the collision between two lines defined by two points each, returns collision point by reference
export fn CheckCollisionLines(startPos1: Vector2, endPos1: Vector2, startPos2: Vector2, endPos2: Vector2, collisionPoint: *Vector2) bool = {
	return _CheckCollisionLines(startPos1, endPos1, startPos2, endPos2, collisionPoint) == c_bool::TRUE;
};

@symbol("CheckCollisionPointLine") fn _CheckCollisionPointLine(point: Vector2, p1: Vector2, p2: Vector2, threshold: int) c_bool;
export @symbol("CheckCollisionLines") fn CheckCollisionLines(startPos1: Vector2, endPos1: Vector2, startPos2: Vector2, endPos2: Vector2, collisionPoint: *Vector2) bool;

// Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
export fn CheckCollisionPointLine(point: Vector2, p1: Vector2, p2: Vector2, threshold: int) bool = {
	return _CheckCollisionPointLine(point, p1, p2, threshold) == c_bool::TRUE;
};
export @symbol("CheckCollisionPointLine") fn CheckCollisionPointLine(point: Vector2, p1: Vector2, p2: Vector2, threshold: int) bool;

// Get collision rectangle for two rectangles collision
export @symbol("GetCollisionRec") fn GetCollisionRec(rec1: Rectangle, rec2: Rectangle) Rectangle;

@symbol("LoadImage") fn _LoadImage(fileName: const *char) Image;
@symbol("LoadImage") fn _LoadImage(fileName: const *c::schar) Image;

// Load image from file into CPU memory (RAM)
export fn LoadImage(fileName: const str) Image = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadImage(fileName_cstring);
};

@symbol("LoadImageRaw") fn _LoadImageRaw(fileName: const *char, width: int, height: int, format: int, headerSize: int) Image;
@symbol("LoadImageRaw") fn _LoadImageRaw(fileName: const *c::schar, width: int, height: int, format: int, headerSize: int) Image;

// Load image from RAW file data
export fn LoadImageRaw(fileName: const str, width: int, height: int, format: int, headerSize: int) Image = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadImageRaw(fileName_cstring, width, height, format, headerSize);
};

@symbol("LoadImageAnim") fn _LoadImageAnim(fileName: const *char, frames: *int) Image;
@symbol("LoadImageAnim") fn _LoadImageAnim(fileName: const *c::schar, frames: *int) Image;

// Load image sequence from file (frames appended to image.data)
export fn LoadImageAnim(fileName: const str, frames: *int) Image = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadImageAnim(fileName_cstring, frames);
};

@symbol("LoadImageFromMemory") fn _LoadImageFromMemory(fileType: const *char, fileData: const *char, dataSize: int) Image;
@symbol("LoadImageFromMemory") fn _LoadImageFromMemory(fileType: const *c::schar, fileData: const *c::uchar, dataSize: int) Image;

// Load image from memory buffer, fileType refers to extension: i.e. '.png'
export fn LoadImageFromMemory(fileType: const str, fileData: const *char, dataSize: int) Image = {
	let fileType_cstring: *char = strings::to_c(fileType);
export fn LoadImageFromMemory(fileType: const str, fileData: const *c::uchar, dataSize: int) Image = {
	let fileType_cstring: *c::char = c::fromstr(fileType);
	defer free(fileType_cstring);
	return _LoadImageFromMemory(fileType_cstring, fileData, dataSize);
};


@@ 2277,22 2131,22 @@ export @symbol("LoadImageFromScreen") fn LoadImageFromScreen() Image;
// Unload image from CPU memory (RAM)
export @symbol("UnloadImage") fn UnloadImage(image: Image) void;

@symbol("ExportImage") fn _ExportImage(image: Image, fileName: const *char) c_bool;
@symbol("ExportImage") fn _ExportImage(image: Image, fileName: const *c::schar) bool;

// Export image data to file, returns true on success
export fn ExportImage(image: Image, fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _ExportImage(image, fileName_cstring) == c_bool::TRUE;
	return _ExportImage(image, fileName_cstring);
};

@symbol("ExportImageAsCode") fn _ExportImageAsCode(image: Image, fileName: const *char) c_bool;
@symbol("ExportImageAsCode") fn _ExportImageAsCode(image: Image, fileName: const *c::schar) bool;

// Export image as code file defining an array of bytes, returns true on success
export fn ExportImageAsCode(image: Image, fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _ExportImageAsCode(image, fileName_cstring) == c_bool::TRUE;
	return _ExportImageAsCode(image, fileName_cstring);
};

// Generate image: plain color


@@ 2322,20 2176,20 @@ export @symbol("ImageCopy") fn ImageCopy(image: Image) Image;
// Create an image from another image piece
export @symbol("ImageFromImage") fn ImageFromImage(image: Image, rec: Rectangle) Image;

@symbol("ImageText") fn _ImageText(text: const *char, fontSize: int, color: Color) Image;
@symbol("ImageText") fn _ImageText(text: const *c::schar, fontSize: int, color: Color) Image;

// Create an image from text (default font)
export fn ImageText(text: const str, fontSize: int, color: Color) Image = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _ImageText(text_cstring, fontSize, color);
};

@symbol("ImageTextEx") fn _ImageTextEx(font: Font, text: const *char, fontSize: f32, spacing: f32, tint: Color) Image;
@symbol("ImageTextEx") fn _ImageTextEx(font: Font, text: const *c::schar, fontSize: f32, spacing: f32, tint: Color) Image;

// Create an image from text (custom sprite font)
export fn ImageTextEx(font: Font, text: const str, fontSize: f32, spacing: f32, tint: Color) Image = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _ImageTextEx(font, text_cstring, fontSize, spacing, tint);
};


@@ 2460,29 2314,29 @@ export @symbol("ImageDrawRectangleLines") fn ImageDrawRectangleLines(dst: *Image
// Draw a source image within a destination image (tint applied to source)
export @symbol("ImageDraw") fn ImageDraw(dst: *Image, src: Image, srcRec: Rectangle, dstRec: Rectangle, tint: Color) void;

@symbol("ImageDrawText") fn _ImageDrawText(dst: *Image, text: const *char, posX: int, posY: int, fontSize: int, color: Color) void;
@symbol("ImageDrawText") fn _ImageDrawText(dst: *Image, text: const *c::schar, posX: int, posY: int, fontSize: int, color: Color) void;

// Draw text (using default font) within an image (destination)
export fn ImageDrawText(dst: *Image, text: const str, posX: int, posY: int, fontSize: int, color: Color) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _ImageDrawText(dst, text_cstring, posX, posY, fontSize, color);
};

@symbol("ImageDrawTextEx") fn _ImageDrawTextEx(dst: *Image, font: Font, text: const *char, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void;
@symbol("ImageDrawTextEx") fn _ImageDrawTextEx(dst: *Image, font: Font, text: const *c::schar, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void;

// Draw text (custom sprite font) within an image (destination)
export fn ImageDrawTextEx(dst: *Image, font: Font, text: const str, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _ImageDrawTextEx(dst, font, text_cstring, position, fontSize, spacing, tint);
};

@symbol("LoadTexture") fn _LoadTexture(fileName: const *char) Texture2D;
@symbol("LoadTexture") fn _LoadTexture(fileName: const *c::schar) Texture2D;

// Load texture from file into GPU memory (VRAM)
export fn LoadTexture(fileName: const str) Texture2D = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadTexture(fileName_cstring);
};


@@ 2583,20 2437,20 @@ export @symbol("GetPixelDataSize") fn GetPixelDataSize(width: int, height: int, 
// Get the default Font
export @symbol("GetFontDefault") fn GetFontDefault() Font;

@symbol("LoadFont") fn _LoadFont(fileName: const *char) Font;
@symbol("LoadFont") fn _LoadFont(fileName: const *c::schar) Font;

// Load font from file into GPU memory (VRAM)
export fn LoadFont(fileName: const str) Font = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadFont(fileName_cstring);
};

@symbol("LoadFontEx") fn _LoadFontEx(fileName: const *char, fontSize: int, fontChars: *int, glyphCount: int) Font;
@symbol("LoadFontEx") fn _LoadFontEx(fileName: const *c::schar, fontSize: int, fontChars: *int, glyphCount: int) Font;

// Load font from file with extended parameters
export fn LoadFontEx(fileName: const str, fontSize: int, fontChars: *int, glyphCount: int) Font = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadFontEx(fileName_cstring, fontSize, fontChars, glyphCount);
};


@@ 2604,17 2458,17 @@ export fn LoadFontEx(fileName: const str, fontSize: int, fontChars: *int, glyphC
// Load font from Image (XNA style)
export @symbol("LoadFontFromImage") fn LoadFontFromImage(image: Image, key: Color, firstChar: int) Font;

@symbol("LoadFontFromMemory") fn _LoadFontFromMemory(fileType: const *char, fileData: const *char, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int) Font;
@symbol("LoadFontFromMemory") fn _LoadFontFromMemory(fileType: const *c::schar, fileData: const *c::uchar, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int) Font;

// Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
export fn LoadFontFromMemory(fileType: const str, fileData: const *char, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int) Font = {
	let fileType_cstring: *char = strings::to_c(fileType);
export fn LoadFontFromMemory(fileType: const str, fileData: const *c::uchar, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int) Font = {
	let fileType_cstring: *c::char = c::fromstr(fileType);
	defer free(fileType_cstring);
	return _LoadFontFromMemory(fileType_cstring, fileData, dataSize, fontSize, fontChars, glyphCount);
};

// Load font data for further use
export @symbol("LoadFontData") fn LoadFontData(fileData: const *char, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int, _type: int) *GlyphInfo;
export @symbol("LoadFontData") fn LoadFontData(fileData: const *c::uchar, dataSize: int, fontSize: int, fontChars: *int, glyphCount: int, _type: int) *GlyphInfo;

// Generate image font atlas using chars info
export @symbol("GenImageFontAtlas") fn GenImageFontAtlas(chars: const *GlyphInfo, recs: **Rectangle, glyphCount: int, fontSize: int, padding: int, packMethod: int) Image;


@@ 2628,29 2482,29 @@ export @symbol("UnloadFont") fn UnloadFont(font: Font) void;
// Draw current FPS
export @symbol("DrawFPS") fn DrawFPS(posX: int, posY: int) void;

@symbol("DrawText") fn _DrawText(text: const *char, posX: int, posY: int, fontSize: int, color: Color) void;
@symbol("DrawText") fn _DrawText(text: const *c::schar, posX: int, posY: int, fontSize: int, color: Color) void;

// Draw text (using default font)
export fn DrawText(text: const str, posX: int, posY: int, fontSize: int, color: Color) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _DrawText(text_cstring, posX, posY, fontSize, color);
};

@symbol("DrawTextEx") fn _DrawTextEx(font: Font, text: const *char, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void;
@symbol("DrawTextEx") fn _DrawTextEx(font: Font, text: const *c::schar, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void;

// Draw text using font and additional parameters
export fn DrawTextEx(font: Font, text: const str, position: Vector2, fontSize: f32, spacing: f32, tint: Color) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _DrawTextEx(font, text_cstring, position, fontSize, spacing, tint);
};

@symbol("DrawTextPro") fn _DrawTextPro(font: Font, text: const *char, position: Vector2, origin: Vector2, rotation: f32, fontSize: f32, spacing: f32, tint: Color) void;
@symbol("DrawTextPro") fn _DrawTextPro(font: Font, text: const *c::schar, position: Vector2, origin: Vector2, rotation: f32, fontSize: f32, spacing: f32, tint: Color) void;

// Draw text using Font and pro parameters (rotation)
export fn DrawTextPro(font: Font, text: const str, position: Vector2, origin: Vector2, rotation: f32, fontSize: f32, spacing: f32, tint: Color) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _DrawTextPro(font, text_cstring, position, origin, rotation, fontSize, spacing, tint);
};


@@ 2658,20 2512,20 @@ export fn DrawTextPro(font: Font, text: const str, position: Vector2, origin: Ve
// Draw one character (codepoint)
export @symbol("DrawTextCodepoint") fn DrawTextCodepoint(font: Font, codepoint: int, position: Vector2, fontSize: f32, tint: Color) void;

@symbol("MeasureText") fn _MeasureText(text: const *char, fontSize: int) int;
@symbol("MeasureText") fn _MeasureText(text: const *c::schar, fontSize: int) int;

// Measure string width for default font
export fn MeasureText(text: const str, fontSize: int) int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _MeasureText(text_cstring, fontSize);
};

@symbol("MeasureTextEx") fn _MeasureTextEx(font: Font, text: const *char, fontSize: f32, spacing: f32) Vector2;
@symbol("MeasureTextEx") fn _MeasureTextEx(font: Font, text: const *c::schar, fontSize: f32, spacing: f32) Vector2;

// Measure string size for Font
export fn MeasureTextEx(font: Font, text: const str, fontSize: f32, spacing: f32) Vector2 = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _MeasureTextEx(font, text_cstring, fontSize, spacing);
};


@@ 2685,11 2539,11 @@ export @symbol("GetGlyphInfo") fn GetGlyphInfo(font: Font, codepoint: int) Glyph
// Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
export @symbol("GetGlyphAtlasRec") fn GetGlyphAtlasRec(font: Font, codepoint: int) Rectangle;

@symbol("LoadCodepoints") fn _LoadCodepoints(text: const *char, count: *int) *int;
@symbol("LoadCodepoints") fn _LoadCodepoints(text: const *c::schar, count: *int) *int;

// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
export fn LoadCodepoints(text: const str, count: *int) *int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _LoadCodepoints(text_cstring, count);
};


@@ 2697,177 2551,177 @@ export fn LoadCodepoints(text: const str, count: *int) *int = {
// Unload codepoints data from memory
export @symbol("UnloadCodepoints") fn UnloadCodepoints(codepoints: *int) void;

@symbol("GetCodepointCount") fn _GetCodepointCount(text: const *char) int;
@symbol("GetCodepointCount") fn _GetCodepointCount(text: const *c::schar) int;

// Get total number of codepoints in a UTF-8 encoded string
export fn GetCodepointCount(text: const str) int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _GetCodepointCount(text_cstring);
};

@symbol("GetCodepoint") fn _GetCodepoint(text: const *char, bytesProcessed: *int) int;
@symbol("GetCodepoint") fn _GetCodepoint(text: const *c::schar, bytesProcessed: *int) int;

// Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
export fn GetCodepoint(text: const str, bytesProcessed: *int) int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _GetCodepoint(text_cstring, bytesProcessed);
};

@symbol("CodepointToUTF8") fn _CodepointToUTF8(codepoint: int, byteSize: *int) const *char;
@symbol("CodepointToUTF8") fn _CodepointToUTF8(codepoint: int, byteSize: *int) const *c::schar;

// Encode one codepoint into UTF-8 byte array (array length returned as parameter)
export fn CodepointToUTF8(codepoint: int, byteSize: *int) const str = {
	return strings::fromc(_CodepointToUTF8(codepoint, byteSize))!;
	return c::tostr(_CodepointToUTF8(codepoint, byteSize))!;
};

@symbol("TextCodepointsToUTF8") fn _TextCodepointsToUTF8(codepoints: *int, length: int) *char;
@symbol("TextCodepointsToUTF8") fn _TextCodepointsToUTF8(codepoints: *int, length: int) *c::schar;

// Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
export fn TextCodepointsToUTF8(codepoints: *int, length: int) str = {
	return strings::fromc(_TextCodepointsToUTF8(codepoints, length))!;
	return c::tostr(_TextCodepointsToUTF8(codepoints, length))!;
};

@symbol("TextCopy") fn _TextCopy(dst: *char, src: const *char) int;
@symbol("TextCopy") fn _TextCopy(dst: *c::schar, src: const *c::schar) int;

// Copy one string to another, returns bytes copied
export fn TextCopy(dst: str, src: const str) int = {
	let dst_cstring: *char = strings::to_c(dst);
	let dst_cstring: *c::char = c::fromstr(dst);
	defer free(dst_cstring);
	let src_cstring: *char = strings::to_c(src);
	let src_cstring: *c::char = c::fromstr(src);
	defer free(src_cstring);
	return _TextCopy(dst_cstring, src_cstring);
};

@symbol("TextIsEqual") fn _TextIsEqual(text1: const *char, text2: const *char) c_bool;
@symbol("TextIsEqual") fn _TextIsEqual(text1: const *c::schar, text2: const *c::schar) bool;

// Check if two text string are equal
export fn TextIsEqual(text1: const str, text2: const str) bool = {
	let text1_cstring: *char = strings::to_c(text1);
	let text1_cstring: *c::char = c::fromstr(text1);
	defer free(text1_cstring);
	let text2_cstring: *char = strings::to_c(text2);
	let text2_cstring: *c::char = c::fromstr(text2);
	defer free(text2_cstring);
	return _TextIsEqual(text1_cstring, text2_cstring) == c_bool::TRUE;
	return _TextIsEqual(text1_cstring, text2_cstring);
};

@symbol("TextLength") fn _TextLength(text: const *char) uint;
@symbol("TextLength") fn _TextLength(text: const *c::schar) uint;

// Get text length, checks for '\0' ending
export fn TextLength(text: const str) uint = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _TextLength(text_cstring);
};

// Text formatting with variables (sprintf() style)
export @symbol("TextFormat") fn TextFormat(text: const *char, ...) const *char;
export @symbol("TextFormat") fn TextFormat(text: const *c::schar, ...) const *c::schar;

@symbol("TextSubtext") fn _TextSubtext(text: const *char, position: int, length: int) const *char;
@symbol("TextSubtext") fn _TextSubtext(text: const *c::schar, position: int, length: int) const *c::schar;

// Get a piece of a text string
export fn TextSubtext(text: const str, position: int, length: int) const str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return strings::fromc(_TextSubtext(text_cstring, position, length))!;
	return c::tostr(_TextSubtext(text_cstring, position, length))!;
};

@symbol("TextReplace") fn _TextReplace(text: *char, replace: const *char, by: const *char) *char;
@symbol("TextReplace") fn _TextReplace(text: *c::schar, replace: const *c::schar, by: const *c::schar) *c::schar;

// Replace text string (WARNING: memory must be freed!)
export fn TextReplace(text: str, replace: const str, by: const str) str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	let replace_cstring: *char = strings::to_c(replace);
	let replace_cstring: *c::char = c::fromstr(replace);
	defer free(replace_cstring);
	let by_cstring: *char = strings::to_c(by);
	let by_cstring: *c::char = c::fromstr(by);
	defer free(by_cstring);
	return strings::fromc(_TextReplace(text_cstring, replace_cstring, by_cstring))!;
	return c::tostr(_TextReplace(text_cstring, replace_cstring, by_cstring))!;
};

@symbol("TextInsert") fn _TextInsert(text: const *char, _insert: const *char, position: int) *char;
@symbol("TextInsert") fn _TextInsert(text: const *c::schar, _insert: const *c::schar, position: int) *c::schar;

// Insert text in a position (WARNING: memory must be freed!)
export fn TextInsert(text: const str, _insert: const str, position: int) str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	let _insert_cstring: *char = strings::to_c(_insert);
	let _insert_cstring: *c::char = c::fromstr(_insert);
	defer free(_insert_cstring);
	return strings::fromc(_TextInsert(text_cstring, _insert_cstring, position))!;
	return c::tostr(_TextInsert(text_cstring, _insert_cstring, position))!;
};

@symbol("TextJoin") fn _TextJoin(textList: const **char, count: int, delimiter: const *char) const *char;
@symbol("TextJoin") fn _TextJoin(textList: const **c::schar, count: int, delimiter: const *c::schar) const *c::schar;

// Join text strings with delimiter
export fn TextJoin(textList: const **char, count: int, delimiter: const str) const str = {
	let delimiter_cstring: *char = strings::to_c(delimiter);
export fn TextJoin(textList: const **c::schar, count: int, delimiter: const str) const str = {
	let delimiter_cstring: *c::char = c::fromstr(delimiter);
	defer free(delimiter_cstring);
	return strings::fromc(_TextJoin(textList, count, delimiter_cstring))!;
	return c::tostr(_TextJoin(textList, count, delimiter_cstring))!;
};

@symbol("TextSplit") fn _TextSplit(text: const *char, delimiter: char, count: *int) const **char;
@symbol("TextSplit") fn _TextSplit(text: const *c::schar, delimiter: c::schar, count: *int) const **c::schar;

// Split text into multiple strings
export fn TextSplit(text: const str, delimiter: char, count: *int) const **char = {
	let text_cstring: *char = strings::to_c(text);
export fn TextSplit(text: const str, delimiter: c::schar, count: *int) const **c::schar = {
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _TextSplit(text_cstring, delimiter, count);
};

@symbol("TextAppend") fn _TextAppend(text: *char, _append: const *char, position: *int) void;
@symbol("TextAppend") fn _TextAppend(text: *c::schar, _append: const *c::schar, position: *int) void;

// Append text at specific position and move cursor!
export fn TextAppend(text: str, _append: const str, position: *int) void = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	let _append_cstring: *char = strings::to_c(_append);
	let _append_cstring: *c::char = c::fromstr(_append);
	defer free(_append_cstring);
	return _TextAppend(text_cstring, _append_cstring, position);
};

@symbol("TextFindIndex") fn _TextFindIndex(text: const *char, find: const *char) int;
@symbol("TextFindIndex") fn _TextFindIndex(text: const *c::schar, find: const *c::schar) int;

// Find first text occurrence within a string
export fn TextFindIndex(text: const str, find: const str) int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	let find_cstring: *char = strings::to_c(find);
	let find_cstring: *c::char = c::fromstr(find);
	defer free(find_cstring);
	return _TextFindIndex(text_cstring, find_cstring);
};

@symbol("TextToUpper") fn _TextToUpper(text: const *char) const *char;
@symbol("TextToUpper") fn _TextToUpper(text: const *c::schar) const *c::schar;

// Get upper case version of provided string
export fn TextToUpper(text: const str) const str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return strings::fromc(_TextToUpper(text_cstring))!;
	return c::tostr(_TextToUpper(text_cstring))!;
};

@symbol("TextToLower") fn _TextToLower(text: const *char) const *char;
@symbol("TextToLower") fn _TextToLower(text: const *c::schar) const *c::schar;

// Get lower case version of provided string
export fn TextToLower(text: const str) const str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return strings::fromc(_TextToLower(text_cstring))!;
	return c::tostr(_TextToLower(text_cstring))!;
};

@symbol("TextToPascal") fn _TextToPascal(text: const *char) const *char;
@symbol("TextToPascal") fn _TextToPascal(text: const *c::schar) const *c::schar;

// Get Pascal case notation version of provided string
export fn TextToPascal(text: const str) const str = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return strings::fromc(_TextToPascal(text_cstring))!;
	return c::tostr(_TextToPascal(text_cstring))!;
};

@symbol("TextToInteger") fn _TextToInteger(text: const *char) int;
@symbol("TextToInteger") fn _TextToInteger(text: const *c::schar) int;

// Get integer value from text (negative values not supported)
export fn TextToInteger(text: const str) int = {
	let text_cstring: *char = strings::to_c(text);
	let text_cstring: *c::char = c::fromstr(text);
	defer free(text_cstring);
	return _TextToInteger(text_cstring);
};


@@ 2935,11 2789,11 @@ export @symbol("DrawRay") fn DrawRay(ray: Ray, color: Color) void;
// Draw a grid (centered at (0, 0, 0))
export @symbol("DrawGrid") fn DrawGrid(slices: int, spacing: f32) void;

@symbol("LoadModel") fn _LoadModel(fileName: const *char) Model;
@symbol("LoadModel") fn _LoadModel(fileName: const *c::schar) Model;

// Load model from files (meshes and materials)
export fn LoadModel(fileName: const str) Model = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadModel(fileName_cstring);
};


@@ 2980,12 2834,8 @@ export @symbol("DrawBillboardRec") fn DrawBillboardRec(camera: Camera, texture: 
// Draw a billboard texture defined by source and rotation
export @symbol("DrawBillboardPro") fn DrawBillboardPro(camera: Camera, texture: Texture2D, source: Rectangle, position: Vector3, up: Vector3, _size: Vector2, origin: Vector2, rotation: f32, tint: Color) void;

@symbol("UploadMesh") fn _UploadMesh(mesh: *Mesh, dynamic: c_bool) void;

// Upload mesh vertex data in GPU and provide VAO/VBO ids
export fn UploadMesh(mesh: *Mesh, dynamic: bool) void = {
	return _UploadMesh(mesh, if (dynamic) c_bool::TRUE else c_bool::FALSE);
};
export @symbol("UploadMesh") fn UploadMesh(mesh: *Mesh, dynamic: bool) void;

// Update mesh vertex data in GPU for a specific buffer index
export @symbol("UpdateMeshBuffer") fn UpdateMeshBuffer(mesh: Mesh, index: int, data: *void, dataSize: int, _offset: int) void;


@@ 2999,13 2849,13 @@ export @symbol("DrawMesh") fn DrawMesh(mesh: Mesh, material: Material, transform
// Draw multiple mesh instances with material and different transforms
export @symbol("DrawMeshInstanced") fn DrawMeshInstanced(mesh: Mesh, material: Material, transforms: *Matrix, instances: int) void;

@symbol("ExportMesh") fn _ExportMesh(mesh: Mesh, fileName: const *char) c_bool;
@symbol("ExportMesh") fn _ExportMesh(mesh: Mesh, fileName: const *c::schar) bool;

// Export mesh data to file, returns true on success
export fn ExportMesh(mesh: Mesh, fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _ExportMesh(mesh, fileName_cstring) == c_bool::TRUE;
	return _ExportMesh(mesh, fileName_cstring);
};

// Compute mesh bounding box limits


@@ 3050,11 2900,11 @@ export @symbol("GenMeshHeightmap") fn GenMeshHeightmap(heightmap: Image, _size: 
// Generate cubes-based map mesh from image data
export @symbol("GenMeshCubicmap") fn GenMeshCubicmap(cubicmap: Image, cubeSize: Vector3) Mesh;

@symbol("LoadMaterials") fn _LoadMaterials(fileName: const *char, materialCount: *int) *Material;
@symbol("LoadMaterials") fn _LoadMaterials(fileName: const *c::schar, materialCount: *int) *Material;

// Load materials from model file
export fn LoadMaterials(fileName: const str, materialCount: *int) *Material = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadMaterials(fileName_cstring, materialCount);
};


@@ 3071,11 2921,11 @@ export @symbol("SetMaterialTexture") fn SetMaterialTexture(material: *Material, 
// Set material for a mesh
export @symbol("SetModelMeshMaterial") fn SetModelMeshMaterial(model: *Model, meshId: int, materialId: int) void;

@symbol("LoadModelAnimations") fn _LoadModelAnimations(fileName: const *char, animCount: *uint) *ModelAnimation;
@symbol("LoadModelAnimations") fn _LoadModelAnimations(fileName: const *c::schar, animCount: *uint) *ModelAnimation;

// Load model animations from file
export fn LoadModelAnimations(fileName: const str, animCount: *uint) *ModelAnimation = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadModelAnimations(fileName_cstring, animCount);
};


@@ 3089,33 2939,17 @@ export @symbol("UnloadModelAnimation") fn UnloadModelAnimation(anim: ModelAnimat
// Unload animation array data
export @symbol("UnloadModelAnimations") fn UnloadModelAnimations(animations: *ModelAnimation, count: uint) void;

@symbol("IsModelAnimationValid") fn _IsModelAnimationValid(model: Model, anim: ModelAnimation) c_bool;

// Check model animation skeleton match
export fn IsModelAnimationValid(model: Model, anim: ModelAnimation) bool = {
	return _IsModelAnimationValid(model, anim) == c_bool::TRUE;
};

@symbol("CheckCollisionSpheres") fn _CheckCollisionSpheres(center1: Vector3, radius1: f32, center2: Vector3, radius2: f32) c_bool;
export @symbol("IsModelAnimationValid") fn IsModelAnimationValid(model: Model, anim: ModelAnimation) bool;

// Check collision between two spheres
export fn CheckCollisionSpheres(center1: Vector3, radius1: f32, center2: Vector3, radius2: f32) bool = {
	return _CheckCollisionSpheres(center1, radius1, center2, radius2) == c_bool::TRUE;
};

@symbol("CheckCollisionBoxes") fn _CheckCollisionBoxes(box1: BoundingBox, box2: BoundingBox) c_bool;
export @symbol("CheckCollisionSpheres") fn CheckCollisionSpheres(center1: Vector3, radius1: f32, center2: Vector3, radius2: f32) bool;

// Check collision between two bounding boxes
export fn CheckCollisionBoxes(box1: BoundingBox, box2: BoundingBox) bool = {
	return _CheckCollisionBoxes(box1, box2) == c_bool::TRUE;
};

@symbol("CheckCollisionBoxSphere") fn _CheckCollisionBoxSphere(box: BoundingBox, center: Vector3, radius: f32) c_bool;
export @symbol("CheckCollisionBoxes") fn CheckCollisionBoxes(box1: BoundingBox, box2: BoundingBox) bool;

// Check collision between box and sphere
export fn CheckCollisionBoxSphere(box: BoundingBox, center: Vector3, radius: f32) bool = {
	return _CheckCollisionBoxSphere(box, center, radius) == c_bool::TRUE;
};
export @symbol("CheckCollisionBoxSphere") fn CheckCollisionBoxSphere(box: BoundingBox, center: Vector3, radius: f32) bool;

// Get collision info between ray and sphere
export @symbol("GetRayCollisionSphere") fn GetRayCollisionSphere(ray: Ray, center: Vector3, radius: f32) RayCollision;


@@ 3141,39 2975,35 @@ export @symbol("InitAudioDevice") fn InitAudioDevice() void;
// Close the audio device and context
export @symbol("CloseAudioDevice") fn CloseAudioDevice() void;

@symbol("IsAudioDeviceReady") fn _IsAudioDeviceReady() c_bool;

// Check if audio device has been initialized successfully
export fn IsAudioDeviceReady() bool = {
	return _IsAudioDeviceReady() == c_bool::TRUE;
};
export @symbol("IsAudioDeviceReady") fn IsAudioDeviceReady() bool;

// Set master volume (listener)
export @symbol("SetMasterVolume") fn SetMasterVolume(volume: f32) void;

@symbol("LoadWave") fn _LoadWave(fileName: const *char) Wave;
@symbol("LoadWave") fn _LoadWave(fileName: const *c::schar) Wave;

// Load wave data from file
export fn LoadWave(fileName: const str) Wave = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadWave(fileName_cstring);
};

@symbol("LoadWaveFromMemory") fn _LoadWaveFromMemory(fileType: const *char, fileData: const *char, dataSize: int) Wave;
@symbol("LoadWaveFromMemory") fn _LoadWaveFromMemory(fileType: const *c::schar, fileData: const *c::uchar, dataSize: int) Wave;

// Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
export fn LoadWaveFromMemory(fileType: const str, fileData: const *char, dataSize: int) Wave = {
	let fileType_cstring: *char = strings::to_c(fileType);
export fn LoadWaveFromMemory(fileType: const str, fileData: const *c::uchar, dataSize: int) Wave = {
	let fileType_cstring: *c::char = c::fromstr(fileType);
	defer free(fileType_cstring);
	return _LoadWaveFromMemory(fileType_cstring, fileData, dataSize);
};

@symbol("LoadSound") fn _LoadSound(fileName: const *char) Sound;
@symbol("LoadSound") fn _LoadSound(fileName: const *c::schar) Sound;

// Load sound from file
export fn LoadSound(fileName: const str) Sound = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadSound(fileName_cstring);
};


@@ 3190,22 3020,22 @@ export @symbol("UnloadWave") fn UnloadWave(wave: Wave) void;
// Unload sound
export @symbol("UnloadSound") fn UnloadSound(sound: Sound) void;

@symbol("ExportWave") fn _ExportWave(wave: Wave, fileName: const *char) c_bool;
@symbol("ExportWave") fn _ExportWave(wave: Wave, fileName: const *c::schar) bool;

// Export wave data to file, returns true on success
export fn ExportWave(wave: Wave, fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _ExportWave(wave, fileName_cstring) == c_bool::TRUE;
	return _ExportWave(wave, fileName_cstring);
};

@symbol("ExportWaveAsCode") fn _ExportWaveAsCode(wave: Wave, fileName: const *char) c_bool;
@symbol("ExportWaveAsCode") fn _ExportWaveAsCode(wave: Wave, fileName: const *c::schar) bool;

// Export wave sample data to code (.h), returns true on success
export fn ExportWaveAsCode(wave: Wave, fileName: const str) bool = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _ExportWaveAsCode(wave, fileName_cstring) == c_bool::TRUE;
	return _ExportWaveAsCode(wave, fileName_cstring);
};

// Play a sound


@@ 3229,12 3059,8 @@ export @symbol("StopSoundMulti") fn StopSoundMulti() void;
// Get number of sounds playing in the multichannel
export @symbol("GetSoundsPlaying") fn GetSoundsPlaying() int;

@symbol("IsSoundPlaying") fn _IsSoundPlaying(sound: Sound) c_bool;

// Check if a sound is currently playing
export fn IsSoundPlaying(sound: Sound) bool = {
	return _IsSoundPlaying(sound) == c_bool::TRUE;
};
export @symbol("IsSoundPlaying") fn IsSoundPlaying(sound: Sound) bool;

// Set volume for a sound (1.0 is max level)
export @symbol("SetSoundVolume") fn SetSoundVolume(sound: Sound, volume: f32) void;


@@ 3257,20 3083,20 @@ export @symbol("LoadWaveSamples") fn LoadWaveSamples(wave: Wave) *f32;
// Unload samples data loaded with LoadWaveSamples()
export @symbol("UnloadWaveSamples") fn UnloadWaveSamples(samples: *f32) void;

@symbol("LoadMusicStream") fn _LoadMusicStream(fileName: const *char) Music;
@symbol("LoadMusicStream") fn _LoadMusicStream(fileName: const *c::schar) Music;

// Load music stream from file
export fn LoadMusicStream(fileName: const str) Music = {
	let fileName_cstring: *char = strings::to_c(fileName);
	let fileName_cstring: *c::char = c::fromstr(fileName);
	defer free(fileName_cstring);
	return _LoadMusicStream(fileName_cstring);
};

@symbol("LoadMusicStreamFromMemory") fn _LoadMusicStreamFromMemory(fileType: const *char, data: *char, dataSize: int) Music;
@symbol("LoadMusicStreamFromMemory") fn _LoadMusicStreamFromMemory(fileType: const *c::schar, data: *c::uchar, dataSize: int) Music;

// Load music stream from data
export fn LoadMusicStreamFromMemory(fileType: const str, data: *char, dataSize: int) Music = {
	let fileType_cstring: *char = strings::to_c(fileType);
export fn LoadMusicStreamFromMemory(fileType: const str, data: *c::uchar, dataSize: int) Music = {
	let fileType_cstring: *c::char = c::fromstr(fileType);
	defer free(fileType_cstring);
	return _LoadMusicStreamFromMemory(fileType_cstring, data, dataSize);
};


@@ 3281,12 3107,8 @@ export @symbol("UnloadMusicStream") fn UnloadMusicStream(music: Music) void;
// Start music playing
export @symbol("PlayMusicStream") fn PlayMusicStream(music: Music) void;

@symbol("IsMusicStreamPlaying") fn _IsMusicStreamPlaying(music: Music) c_bool;

// Check if music is playing
export fn IsMusicStreamPlaying(music: Music) bool = {
	return _IsMusicStreamPlaying(music) == c_bool::TRUE;
};
export @symbol("IsMusicStreamPlaying") fn IsMusicStreamPlaying(music: Music) bool;

// Updates buffers for music streaming
export @symbol("UpdateMusicStream") fn UpdateMusicStream(music: Music) void;


@@ 3324,12 3146,8 @@ export @symbol("UnloadAudioStream") fn UnloadAudioStream(stream: AudioStream) vo
// Update audio stream buffers with data
export @symbol("UpdateAudioStream") fn UpdateAudioStream(stream: AudioStream, data: const *void, frameCount: int) void;

@symbol("IsAudioStreamProcessed") fn _IsAudioStreamProcessed(stream: AudioStream) c_bool;

// Check if any audio stream buffers requires refill
export fn IsAudioStreamProcessed(stream: AudioStream) bool = {
	return _IsAudioStreamProcessed(stream) == c_bool::TRUE;
};
export @symbol("IsAudioStreamProcessed") fn IsAudioStreamProcessed(stream: AudioStream) bool;

// Play audio stream
export @symbol("PlayAudioStream") fn PlayAudioStream(stream: AudioStream) void;


@@ 3340,12 3158,8 @@ export @symbol("PauseAudioStream") fn PauseAudioStream(stream: AudioStream) void
// Resume audio stream
export @symbol("ResumeAudioStream") fn ResumeAudioStream(stream: AudioStream) void;

@symbol("IsAudioStreamPlaying") fn _IsAudioStreamPlaying(stream: AudioStream) c_bool;

// Check if audio stream is playing
export fn IsAudioStreamPlaying(stream: AudioStream) bool = {
	return _IsAudioStreamPlaying(stream) == c_bool::TRUE;
};
export @symbol("IsAudioStreamPlaying") fn IsAudioStreamPlaying(stream: AudioStream) bool;

// Stop audio stream
export @symbol("StopAudioStream") fn StopAudioStream(stream: AudioStream) void;