diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | CHANGELOG.txt | 3 | ||||
-rw-r--r-- | procyon/GNUmakefile | 60 | ||||
-rw-r--r-- | procyon/include/acm/bs.h | 103 | ||||
-rw-r--r-- | procyon/include/acm/gfx.h | 8 | ||||
-rw-r--r-- | procyon/source/bs/cont.c | 79 | ||||
-rw-r--r-- | procyon/source/bs/dbglog.c | 11 | ||||
-rw-r--r-- | procyon/source/bs/exit.c | 15 | ||||
-rw-r--r-- | procyon/source/bs/init.c | 51 | ||||
-rw-r--r-- | procyon/source/bs/sav.c | 35 | ||||
-rw-r--r-- | procyon/source/bs/shipnm.c | 70 | ||||
-rw-r--r-- | procyon/source/gfx/initgfx.c | 22 | ||||
-rw-r--r-- | procyon/source/main.c | 24 |
13 files changed, 484 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d0d1241 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.elf +*.exe +*.o diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..6c184dd --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,3 @@ +# 0 + +* Initial; diff --git a/procyon/GNUmakefile b/procyon/GNUmakefile new file mode 100644 index 0000000..b54c12f --- /dev/null +++ b/procyon/GNUmakefile @@ -0,0 +1,60 @@ +# TOOLS + +# TOOL FLAGS + +CFLAGS := \ + -D_POSIX_C_SOURCE=200809L \ + -Iinclude \ + -O3 \ + -Wall \ + -Wextra \ + -Wpedantic \ + -g \ + -march=native \ + -std=c2x + +ifeq "$(debug)" "true" +CFLAGS := \ + $(CFLAGS) \ + -Dacm_dbg +endif + +LDLIBS := \ + -lGL \ + -lflux \ + -lglfw \ + -lzap + +# HEADERS + +HDRS := \ + include/acm/bs.h + +# BINARIES + +OBJS := \ + source/bs/cont.o \ + source/bs/dbglog.o \ + source/bs/exit.o \ + source/bs/init.o \ + source/bs/sav.o \ + source/bs/shipnm.o \ + source/gfx/initgfx.o \ + source/main.o + +BIN := procyon.elf + +# TARGETS + +.PHONY: clean purge + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o$(@) $(^) $(LDLIBS) + +$(OBJS): $(HDRS) + +clean: + $(RM) $(OBJS) + +purge: clean + $(RM) $(LIB) diff --git a/procyon/include/acm/bs.h b/procyon/include/acm/bs.h new file mode 100644 index 0000000..58acdcf --- /dev/null +++ b/procyon/include/acm/bs.h @@ -0,0 +1,103 @@ +#if !defined(acm_hdr_bs) +#define acm_hdr_bs + +#include <GLFW/glfw3.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <zap/bs.h> + +#define acm_ver ((uint_least64_t)+0x0) +#define acm_savver ((uint_least64_t)+0x0) + +#define acm_plnmlen ((zap_sz)+0x10u) + +#define acm_dflplnm ("Jameson\x0\x0\x0\x0\x0\x0\x0\x0") + +#if defined(acm_dbg) +#define acm_log(...) (acm_dbglog(__VA_ARGS__)) +#else +#define acm_log(...) ((void)0x0u) +#endif + +typedef enum { + acm_ship_add, + acm_ship_ana, + acm_ship_asp, + acm_ship_boa, + acm_ship_cob, + acm_ship_con, + acm_ship_cou, + acm_ship_cyg, + acm_ship_dov, + acm_ship_eag, + acm_ship_falc, + acm_ship_fer, + acm_ship_frei, + acm_ship_geck, + acm_ship_haul, + acm_ship_hawk, + acm_ship_keel, + acm_ship_kes, + acm_ship_krait, + acm_ship_lift, + acm_ship_lion, + acm_ship_mamba, + acm_ship_moray, + acm_ship_osp, + acm_ship_pan, + acm_ship_puma, + acm_ship_py, + acm_ship_shut, + acm_ship_side, + acm_ship_tran, + acm_ship_vip, + acm_ship_vult, +} acm_ship; + +typedef enum { + acm_stat_err, + acm_stat_ok, +} acm_stat; + +typedef struct { + uint_least64_t rx; /* Rotation data */ + uint_least64_t ry; + uint_least64_t rz; + uint_least64_t px; /* Position data */ + uint_least64_t py; + uint_least64_t pz; + uint_least64_t vx; /* Velocity data */ + uint_least64_t vy; + uint_least64_t vz; +} acm_objpos; + +typedef struct { + acm_objpos pos; +} acm_obj; + +typedef struct { + char nm[acm_plnmlen + 0x1u]; + uint_least16_t heat; + acm_objpos pos; + acm_ship ship; + uint_least64_t tm; +} acm_pldat; + +extern struct { + bool gfxisinit; + acm_pldat pldat; + char const * savloc; + GLFWwindow * win; +} acm_dat; + +extern sig_atomic_t volatile acm_gotintr; + + void acm_cont( acm_pldat * pldat); + void acm_dbglog(char const * fmt,...); + void acm_init( void); +[[noreturn]] void acm_exit( acm_stat stat); + void acm_sav( acm_pldat const * pldat); + char const * acm_shipnm(acm_ship ship); + +#endif diff --git a/procyon/include/acm/gfx.h b/procyon/include/acm/gfx.h new file mode 100644 index 0000000..c3fdc15 --- /dev/null +++ b/procyon/include/acm/gfx.h @@ -0,0 +1,8 @@ +#if !defined(acm_hdr_gfx) +#define acm_hdr_gfx + +#include <acm/bs.h> + +void acm_initgfx(void); + +#endif diff --git a/procyon/source/bs/cont.c b/procyon/source/bs/cont.c new file mode 100644 index 0000000..61907fc --- /dev/null +++ b/procyon/source/bs/cont.c @@ -0,0 +1,79 @@ +#include <acm/bs.h> + +#include <flux.h> +#include <inttypes.h> +#include <zap/mem.h> + +static_assert(sizeof (acm_dflplnm) == acm_plnmlen); + +void acm_cont(acm_pldat * const _pldat) { + acm_log("Continuing\n"); + acm_pldat pldat; + uint_least64_t savver; + flux_err fluxerr; + flux_fil savfil; + fluxerr = flux_op(&savfil,acm_dat.savloc,flux_md_rd,flux_keep); + if (fluxerr) { + acm_log("Unable to open save file, starting new game: %s\n",flux_errstr(fluxerr)); + goto new; + } + fluxerr = flux_rd(savfil,sizeof (savver),&savver,nullptr); + if (!fluxerr) { + fluxerr = flux_rd(savfil,sizeof (pldat),&pldat,nullptr); + } + flux_cl(savfil); + if (fluxerr) { + acm_log("Unable to read save file, starting new game: %s\n",flux_errstr(fluxerr)); + goto new; + } + if (savver != acm_savver) { + printf("Old save version (%" PRIXLEAST64 "), starting new game: %s\n",savver,flux_errstr(fluxerr)); + goto new; + } + acm_log("Validating commander name\n"); + bool validnm = false; + for (zap_sz n = 0x0u;n < acm_plnmlen + 0x1u;++n) { + if (pldat.nm[n] == '\x0') { + if (n == 0x0u) { + break; + } + validnm = true; + break; + } + } + if (!validnm) { + acm_log("Invalid commander name (corrupt save file), starting new game\n"); + acm_log( + "Commander name:\n" + " %hhX %hhX %hhX %hhX\n" + " %hhX %hhX %hhX %hhX\n" + " %hhX %hhX %hhX %hhX\n" + " %hhX %hhX %hhX %hhX\n" + " %hhX\n", + pldat.nm[0x0u],pldat.nm[0x1u],pldat.nm[0x2u],pldat.nm[0x3u], + pldat.nm[0x4u],pldat.nm[0x5u],pldat.nm[0x6u],pldat.nm[0x7u], + pldat.nm[0x8u],pldat.nm[0x9u],pldat.nm[0xAu],pldat.nm[0xBu], + pldat.nm[0xCu],pldat.nm[0xDu],pldat.nm[0xEu],pldat.nm[0xFu], + pldat.nm[0x10u] + ); + goto new; + } + printf("Loaded CMDR %s, %s @ %" PRIiLEAST64 "\n",pldat.nm,acm_shipnm(pldat.ship),pldat.tm); + *_pldat = pldat; + return; +new:; + pldat.heat = 0x120u; /* 288K */ + pldat.pos.px = 0x0u; + pldat.pos.py = 0x0u; + pldat.pos.pz = 0x0u; + pldat.pos.rx = 0x0u; + pldat.pos.ry = 0x0u; + pldat.pos.rz = 0x0u; + pldat.pos.vx = 0x0u; + pldat.pos.vy = 0x0u; + pldat.pos.vz = 0x0u; + pldat.ship = acm_ship_side; + pldat.tm = 0x9679C2B40u; /* 3250-01-01T12:00:00Z */ + zap_memcp(acm_dflplnm,acm_plnmlen + 0x1u,pldat.nm); + *_pldat = pldat; +} diff --git a/procyon/source/bs/dbglog.c b/procyon/source/bs/dbglog.c new file mode 100644 index 0000000..d04174f --- /dev/null +++ b/procyon/source/bs/dbglog.c @@ -0,0 +1,11 @@ +#include <acm/bs.h> + +#include <stdarg.h> +#include <stdio.h> + +void acm_dbglog(char const * const _fmt,...) { + va_list args; + va_start(args,_fmt); + vfprintf(stderr,_fmt,args); + va_end(args); +} diff --git a/procyon/source/bs/exit.c b/procyon/source/bs/exit.c new file mode 100644 index 0000000..e49dfc9 --- /dev/null +++ b/procyon/source/bs/exit.c @@ -0,0 +1,15 @@ +#include <acm/bs.h> + +#include <GLFW/glfw3.h> +#include <stdlib.h> + +void acm_exit(acm_stat const _stat) { + int const cstat = _stat == acm_stat_ok ? EXIT_SUCCESS : EXIT_FAILURE; + free((void *)acm_dat.savloc); + if (acm_dat.gfxisinit) { + glfwDestroyWindow(acm_dat.win); + glfwTerminate(); + } + acm_log("Done (%X)\n",cstat); + exit(cstat); +} diff --git a/procyon/source/bs/init.c b/procyon/source/bs/init.c new file mode 100644 index 0000000..1f4c57e --- /dev/null +++ b/procyon/source/bs/init.c @@ -0,0 +1,51 @@ +#include <acm/gfx.h> + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <zap/mem.h> + +sig_atomic_t volatile acm_gotintr; + +typeof (acm_dat) acm_dat; + +static char * acm_getsavloc(void) { + char const * const hmdir = getenv("HOME"); + if (hmdir == nullptr) { + fprintf(stderr,"Unable to get home directory (HOME not set)\n"); + acm_exit(acm_stat_err); + } + char const * const savfilnm = ".procyon-save"; + zap_sz const hmdirlen = zap_strlen(hmdir); + zap_sz const savfilnmlen = zap_strlen(savfilnm); + zap_sz const savloclen = hmdirlen + 0x1u + savfilnmlen; + char * savloc = malloc(savloclen + 0x1u); + if (savloc == nullptr) { + fprintf(stderr,"Unable allocate memory\n"); + acm_exit(acm_stat_err); + } + zap_memcp(hmdir,hmdirlen,savloc); + savloc[hmdirlen] = '/'; + zap_memcp(savfilnm,savfilnmlen,savloc + hmdirlen + 0x1u); + savloc[savloclen] = 0x0u; + return savloc; +} + +static void acm_intrhandl(int const _sig) { + signal(_sig,acm_intrhandl); /* Ignore the return value. */ + acm_gotintr = 0x1; +} + +void acm_init(void) { + acm_gotintr = 0x0; + acm_dat.gfxisinit = false; + acm_dat.win = nullptr; + acm_log("Initialising data\n"); + acm_dat.savloc = acm_getsavloc(); + acm_log("Initialising signal handlers\n"); + if (signal(SIGINT,acm_intrhandl) == SIG_ERR) { + fprintf(stderr,"Unable to set SIGINT handler\n"); + acm_exit(acm_stat_err); + } + acm_initgfx(); +} diff --git a/procyon/source/bs/sav.c b/procyon/source/bs/sav.c new file mode 100644 index 0000000..1e0b226 --- /dev/null +++ b/procyon/source/bs/sav.c @@ -0,0 +1,35 @@ +#include <acm/bs.h> + +#include <flux.h> +#include <stdio.h> + +void acm_sav(acm_pldat const * const _pldat) { + acm_log("Saving\n"); + flux_err fluxerr; + flux_fil savfil; + fluxerr = flux_mkfil(&savfil,acm_dat.savloc,0644u); + if (fluxerr) { + if (fluxerr != flux_err_exist) { + fprintf(stderr,"Unable to create save file (\"%s\"): %s\n",acm_dat.savloc,flux_errstr(fluxerr)); + acm_exit(acm_stat_err); + } + acm_log("Save file already exists, overwritting\n"); + fluxerr = flux_op(&savfil,acm_dat.savloc,flux_md_wr,flux_disc); + if (fluxerr) { + fprintf(stderr,"Unable to open save file: %s\n",flux_errstr(fluxerr)); + acm_exit(acm_stat_err); + } + } + { + uint_least64_t const savver = acm_savver; + fluxerr = flux_wr(savfil,&savver,sizeof (savver)); + } + if (!fluxerr) { + fluxerr = flux_wr(savfil,_pldat,sizeof (*_pldat)); + } + if (fluxerr) { + fprintf(stderr,"Unable to write to save file: %s\n",flux_errstr(fluxerr)); + acm_exit(acm_stat_err); + } + flux_cl(savfil); +} diff --git a/procyon/source/bs/shipnm.c b/procyon/source/bs/shipnm.c new file mode 100644 index 0000000..dcbd6fb --- /dev/null +++ b/procyon/source/bs/shipnm.c @@ -0,0 +1,70 @@ +#include <acm/bs.h> + +char const * acm_shipnm(acm_ship const _ship) { + switch (_ship) { + case acm_ship_add: + return "Adder"; + case acm_ship_ana: + return "Anaconda"; + case acm_ship_asp: + return "Asp"; + case acm_ship_boa: + return "Boa"; + case acm_ship_cob: + return "Cobra"; + case acm_ship_con: + return "Constrictor"; + case acm_ship_cou: + return "Courier"; + case acm_ship_cyg: + return "Cygnus"; + case acm_ship_dov: + return "Dove"; + case acm_ship_eag: + return "Eagle"; + case acm_ship_falc: + return "Falcon"; + case acm_ship_fer: + return "Fer-de-lance"; + case acm_ship_frei: + return "Freighter"; + case acm_ship_geck: + return "Gecko"; + case acm_ship_haul: + return "Hauler"; + case acm_ship_hawk: + return "Hawk"; + case acm_ship_keel: + return "Keelback"; + case acm_ship_kes: + return "Kestral"; + case acm_ship_krait: + return "Krait"; + case acm_ship_lift: + return "Lifter"; + case acm_ship_lion: + return "Lion"; + case acm_ship_mamba: + return "Mamba"; + case acm_ship_moray: + return "Moray"; + case acm_ship_osp: + return "Osprey"; + case acm_ship_pan: + return "Panther"; + case acm_ship_puma: + return "Puma"; + case acm_ship_py: + return "Python"; + case acm_ship_shut: + return "Shuttle"; + case acm_ship_side: + return "Sidewinder"; + case acm_ship_tran: + return "Transporter"; + case acm_ship_vip: + return "Viper"; + case acm_ship_vult: + return "Vulture"; + } +} diff --git a/procyon/source/gfx/initgfx.c b/procyon/source/gfx/initgfx.c new file mode 100644 index 0000000..d60e393 --- /dev/null +++ b/procyon/source/gfx/initgfx.c @@ -0,0 +1,22 @@ +#include <acm/gfx.h> + +#include <GLFW/glfw3.h> + +void acm_initgfx(void) { + acm_log("Initialising graphics\n"); + if (!glfwInit()) { + fprintf(stderr,"Unable to initialise GLFW\n"); + acm_exit(acm_stat_err); + } + GLFWwindow * win = glfwCreateWindow(0x300,0x200,"Procyon",nullptr,nullptr); + if (win == nullptr) { + fprintf(stderr,"Unable to open window\n"); + goto abrt; + } + glfwMakeContextCurrent(win); + acm_dat.win = win; + return; +abrt:; + glfwTerminate(); + acm_exit(acm_stat_err); +} diff --git a/procyon/source/main.c b/procyon/source/main.c new file mode 100644 index 0000000..84168ba --- /dev/null +++ b/procyon/source/main.c @@ -0,0 +1,24 @@ +#include <acm/bs.h> + +#include <flux.h> +#include <inttypes.h> +#include <stdio.h> + +int main(int const argc,[[maybe_unused]] char const * const * const argv) { + acm_dat.gfxisinit = false; + if (argc > 0x1) { + fprintf(stderr,"Ignoring terminal options\n"); + } + printf("Procyon, %" PRIxLEAST64 " - Copyright 2022 Gabriel Jensen.\n",acm_ver); + acm_init(); + acm_cont(&acm_dat.pldat); + acm_log("Ready\n"); + while (!glfwWindowShouldClose(acm_dat.win)) { + if (acm_gotintr) { + fprintf(stderr,"Got interrupt, stopping\n"); + glfwSetWindowShouldClose(acm_dat.win,0x1); + } + } + acm_sav(&acm_dat.pldat); + acm_exit(acm_stat_ok); +} |