diff --git a/main.um b/main.um index 742d806..041efe8 100644 --- a/main.um +++ b/main.um @@ -75,10 +75,10 @@ fn init*() { window::setViewport(th::Vf2{ 100, 100 }) var err: std::Err - loadedFont, err = font::load("etc/roboto.ttf", 16) + loadedFont, err = font::load("res://etc/roboto.ttf", 16) std::exitif(err) - logo, err = image::load("etc/logo/logo-normal-white.png") + logo, err = image::load("res://etc/logo/logo-normal-white.png") std::exitif(err) fg = 0xadadd5ff @@ -94,8 +94,8 @@ fn init*() { "", "PRESS ENTER TO", "OPEN THE", - "HOMEPAGE" } - + "HOMEPAGE" + } window::onFrame.register(onFrame) } diff --git a/src/bindings.c b/src/bindings.c index 027e704..68234bd 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -24,20 +24,47 @@ extern int th_em_modulenames_count; static char * conv_path(char *path) { - const char *RAW_PFX = "raw://"; - const int RAW_PFX_LEN = strlen(RAW_PFX); - - if (strncmp(path, RAW_PFX, RAW_PFX_LEN) == 0) { - char *out = malloc(strlen(path) - RAW_PFX_LEN + 1); - out[strlen(path) - RAW_PFX_LEN] = 0; - strcpy(out, path + RAW_PFX_LEN); - return out; + enum prefix + { + PFX_RAW, + PFX_RES, + PFX_DATA, + }; + + const char *prefixes[] = { + [PFX_RAW] = "raw://", + [PFX_RES] = "res://", + [PFX_DATA] = "data://", + }; + + const ssize_t path_len = strlen(path); + enum prefix pfx = PFX_RAW; + + for (int i = 0; i < sizeof(prefixes) / sizeof(prefixes[0]); ++i) { + const ssize_t prefix_len = strlen(prefixes[i]); + if (path_len >= prefix_len && memcmp(path, prefixes[i], prefix_len) == 0) { + pfx = i; + path += prefix_len; + break; + } + } + + char *out = NULL; + + switch (pfx) { + case PFX_RAW: out = strdup(path); break; + case PFX_RES: + out = calloc(1, strlen(thg->res_dir) + strlen(path) + 1); + strcpy(out, thg->res_dir); + strcat(out, path); + break; + case PFX_DATA: + out = calloc(1, strlen(thg->data_dir) + strlen(path) + 1); + strcpy(out, thg->data_dir); + strcat(out, path); + break; } - size_t len = strlen(thg->respath) + strlen(path); - char *out = malloc(len + 1); - out[len] = 0; - sprintf(out, "%s%s", thg->respath, path); return out; } @@ -48,6 +75,8 @@ umth_fopen(UmkaStackSlot *p, UmkaStackSlot *r) char *name = (char *)umkaGetParam(p, 0)->ptrVal; const char *mode = (const char *)umkaGetParam(p, 1)->ptrVal; + printf("fopen\n"); + char *path = conv_path(name); FILE *f = fopen(path, mode); free(path); @@ -1433,6 +1462,7 @@ _th_umka_bind(void *umka) { // etc umkaAddFunc(umka, "umth_fopen", &umth_fopen); + umkaAddFunc(umka, "rtlfopen", &umth_fopen); umkaAddFunc(umka, "umth_th_getglobal", &umth_th_getglobal); umkaAddFunc(umka, "umth_th_getfuncs", &umth_th_getfuncs); diff --git a/src/main.c b/src/main.c index c0c17ad..eb8c5a5 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,9 @@ #define __USE_MINGW_ANSI_STDIO 1 +#include +#include #include +#include #include #include "bindings.h" @@ -12,9 +15,10 @@ #include #ifdef _WIN32 #include +#include +#include +#define mkdir(p, m) mkdir(p) #else -#include -#include #endif #include @@ -23,6 +27,8 @@ #define TH_GITVER "" #endif +#define PATH_MAX 512 + th_global *thg; extern char *th_em_modulenames[]; @@ -41,6 +47,57 @@ warning(UmkaError *error) int th_init(const char *scriptpath, const char *script_src) { + { + thg->res_dir = strdup(scriptpath); + char *fname = strrchr(thg->res_dir, '/'); + ssize_t len = fname == NULL ? strlen(thg->res_dir) : strlen(fname) - 1; + thg->res_dir[strlen(thg->res_dir) - len] = '\0'; + } + + { + char *res_dir = thg->res_dir[0] == '\0' ? "./" : thg->res_dir; +#ifdef _WIN32 + char abs[PATH_MAX]; + GetFullPathNameA(res_dir, PATH_MAX - 1, abs, NULL); +#else + char *abs = realpath(res_dir, NULL); +#endif + char *dirname = strrchr(abs, '/'); + ssize_t dirlen = dirname == NULL ? 0 : strlen(dirname); + + bool data_path_allocd = 0; +#ifdef _WIN32 + char *data_path = getenv("APPDATA"); +#else + char *data_path = getenv("XDG_DATA_HOME"); + if (data_path == NULL) { + data_path = getenv("HOME"); + if (data_path == NULL) { + th_error("Could not find home directory"); + } + data_path_allocd = 1; + char *tmp = calloc(1, strlen(data_path) + strlen("/.local/share") + 1); + sprintf(tmp, "%s/.local/share", data_path); + data_path = tmp; + } +#endif + + thg->data_dir = calloc(1, strlen(data_path) + strlen("/tophat") + dirlen + 1); + strcpy(thg->data_dir, data_path); + + strcat(thg->data_dir, "/tophat"); + mkdir(thg->data_dir, 0777); + + strcat(thg->data_dir, dirname == NULL ? "" : dirname); + mkdir(thg->data_dir, 0777); + + if (data_path_allocd) + free(data_path); +#ifndef _WIN32 + free(abs); +#endif + } + char *mainmod_fmt = "import (mainmod = \"%s\"; \"window.um\")\n" "fn __th_init*() {\n" " _ := window::w\n" @@ -143,6 +200,9 @@ th_deinit() th_font_deinit(); th_image_deinit(); + free(thg->res_dir); + free(thg->data_dir); + free(thg); thg = NULL; } @@ -196,9 +256,6 @@ th_main(int argc, char *argv[]) thg->argc = argc; thg->argv = argv; - const char *respath = ""; - - thg->respath[0] = 0; const char *scriptpath = "main.um"; thg->argOffset = 1; @@ -281,14 +338,6 @@ th_main(int argc, char *argv[]) "\n%s\n", umkaGetVersion()); exit(0); - } else if (strcmp(argv[thg->argOffset], "-dir") == 0) { - if ((argc - thg->argOffset) < 2) { - th_error("dir takes 1 argument.\n"); - exit(1); - } - - respath = argv[thg->argOffset + 1]; - thg->argOffset += 2; } else if (strcmp(argv[thg->argOffset], "-help") == 0) { th_info("tophat - a minimalist game engine for making games in umka.\n" "Just launching tophat without flags will run main.um\n" @@ -300,7 +349,7 @@ th_main(int argc, char *argv[]) " -dpiaware - enable DPI awareness\n" " -help - show this help\n" " -license - print the license\n" - " -main - specify the main file (dir/main.um by default)\n" + " -main - specify the main file (./main.um by default)\n" " -modsrc - print source of a builtin module\n" " -prof - use the profiler\n" " -profjson - output profiler stuff as Google JSON profile\n" @@ -321,18 +370,6 @@ th_main(int argc, char *argv[]) char regularizedScriptPath[BUFSIZ]; th_regularize_path(scriptpath, "./", regularizedScriptPath, sizeof regularizedScriptPath); - th_regularize_path(respath, "./", thg->respath, sizeof thg->respath); - - size_t respath_len = strlen(thg->respath); - - if (respath_len > 0 && thg->respath[respath_len - 1] != '/' && thg->respath[0] != 0) { - if (respath_len == sizeof(thg->respath) - 1) { - th_error("Respath is too long"); - return 1; - } - - strncat(thg->respath, "/", sizeof(thg->respath) - 1); - } FILE *f; if ((f = fopen(regularizedScriptPath, "r"))) { diff --git a/src/tophat.h b/src/tophat.h index 85bb51d..d823e13 100644 --- a/src/tophat.h +++ b/src/tophat.h @@ -16,6 +16,14 @@ #include #include +#if _WIN32 || _WIN64 +#if _WIN64 +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif +#endif + #define PI 3.1415926535897932 #define INPUT_STRING_SIZE 256 @@ -276,7 +284,8 @@ typedef struct // struct holding all tophat's global variables. typedef struct { - char respath[4096]; + char *res_dir; + char *data_dir; fu scaling; th_vf2 offset; th_vf2 viewport;