summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.txt12
-rw-r--r--CREDITS.txt10
-rw-r--r--README.txt47
-rw-r--r--bowshock.svg4
-rw-r--r--bowshock/CMakeLists.txt79
-rw-r--r--bowshock/include/bow/application.hxx64
-rw-r--r--bowshock/include/bow/bas.hxx138
-rw-r--r--bowshock/include/bow/base.hxx136
-rw-r--r--bowshock/include/bow/ini.hxx59
-rw-r--r--bowshock/include/bow/lgc.hxx23
-rw-r--r--bowshock/include/bow/logic.hxx26
-rw-r--r--bowshock/include/bow/run.hxx16
-rw-r--r--bowshock/include/bow/runtime.hxx18
-rw-r--r--bowshock/include/bow/sav.hxx67
-rw-r--r--bowshock/include/bow/save.hxx72
-rw-r--r--bowshock/shader/main.frag.glsl4
-rw-r--r--bowshock/shader/main.vert.glsl4
-rw-r--r--bowshock/source/application/bow/check_parameters.cxx41
-rw-r--r--bowshock/source/application/bow/compile_shader_program.cxx137
-rw-r--r--bowshock/source/application/bow/destructor.cxx19
-rw-r--r--bowshock/source/application/bow/get_quote.cxx161
-rw-r--r--bowshock/source/application/bow/initialise_graphics.cxx56
-rw-r--r--bowshock/source/application/bow/initialise_random.cxx14
-rw-r--r--bowshock/source/application/bow/initialise_signal.cxx38
-rw-r--r--bowshock/source/application/bow/loop.cxx122
-rw-r--r--bowshock/source/application/bow/poll_events.cxx20
-rw-r--r--bowshock/source/application/bow/print_credits.cxx43
-rw-r--r--bowshock/source/application/bow/print_help.cxx25
-rw-r--r--bowshock/source/application/bow/print_quote.cxx22
-rw-r--r--bowshock/source/application/bow/run.cxx55
-rw-r--r--bowshock/source/application/bow/start_sequence.cxx48
-rw-r--r--bowshock/source/base/home_directory.cxx16
-rw-r--r--bowshock/source/base/object_type_string.cxx24
-rw-r--r--bowshock/source/base/random.cxx19
-rw-r--r--bowshock/source/base/save_path.cxx26
-rw-r--r--bowshock/source/bs/objtypstr.cxx30
-rw-r--r--bowshock/source/bs/rnd.cxx17
-rw-r--r--bowshock/source/ini/bow/chkpar.cxx40
-rw-r--r--bowshock/source/ini/bow/cmpshdprg.cxx121
-rw-r--r--bowshock/source/ini/bow/exi.cxx29
-rw-r--r--bowshock/source/ini/bow/getquo.cxx157
-rw-r--r--bowshock/source/ini/bow/getsavpth.cxx36
-rw-r--r--bowshock/source/ini/bow/hlp.cxx25
-rw-r--r--bowshock/source/ini/bow/ini.cxx51
-rw-r--r--bowshock/source/ini/bow/inigfx.cxx42
-rw-r--r--bowshock/source/ini/bow/inirnd.cxx12
-rw-r--r--bowshock/source/ini/bow/inisig.cxx32
-rw-r--r--bowshock/source/ini/bow/lop.cxx113
-rw-r--r--bowshock/source/ini/bow/polevt.cxx18
-rw-r--r--bowshock/source/ini/bow/pricrd.cxx62
-rw-r--r--bowshock/source/ini/bow/priquo.cxx19
-rw-r--r--bowshock/source/ini/bow/srtseq.cxx46
-rw-r--r--bowshock/source/lgc/grv.cxx75
-rw-r--r--bowshock/source/lgc/mov.cxx18
-rw-r--r--bowshock/source/lgc/shpmas.cxx10
-rw-r--r--bowshock/source/lgc/sim.cxx16
-rw-r--r--bowshock/source/logic/gravitate.cxx75
-rw-r--r--bowshock/source/logic/move.cxx18
-rw-r--r--bowshock/source/logic/ship_mass.cxx10
-rw-r--r--bowshock/source/logic/simulate.cxx17
-rw-r--r--bowshock/source/run/abr.cxx16
-rw-r--r--bowshock/source/run/addobj.cxx16
-rw-r--r--bowshock/source/run/gensys.cxx69
-rw-r--r--bowshock/source/run/remobj.cxx16
-rw-r--r--bowshock/source/runtime/add_object.cxx18
-rw-r--r--bowshock/source/runtime/delete_objects.cxx20
-rw-r--r--bowshock/source/runtime/generate_system.cxx72
-rw-r--r--bowshock/source/sav/cnt.cxx84
-rw-r--r--bowshock/source/sav/decsav.cxx29
-rw-r--r--bowshock/source/sav/encsav.cxx29
-rw-r--r--bowshock/source/sav/gendat.cxx12
-rw-r--r--bowshock/source/sav/newsav.cxx39
-rw-r--r--bowshock/source/sav/sav.cxx46
-rw-r--r--bowshock/source/save/continue_save.cxx75
-rw-r--r--bowshock/source/save/decode_save.cxx35
-rw-r--r--bowshock/source/save/encode_save.cxx35
-rw-r--r--bowshock/source/save/generate_data.cxx15
-rw-r--r--bowshock/source/save/new_save.cxx42
-rw-r--r--bowshock/source/save/save.cxx51
-rw-r--r--glad.CMakeLists.txt2
-rwxr-xr-xinstall.sh4
-rwxr-xr-xvalidateShaders.py1
83 files changed, 1777 insertions, 1705 deletions
diff --git a/.gitignore b/.gitignore
index b7109f3..358d653 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@
/build
/datdir
/glad
-*.tar
+*.star
*.zip
*.zst
vgcore.*
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 073a19f..5dd2148 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -22,6 +22,18 @@
* Enable more warnings;
+* Drop zp in favour of the standard library
+* Drop ly in favour of the standard library
+* Update code style
+* Update naming convention
+* Use libfmt
+* Remove abort function
+* Add background to main logo
+* Update readme
+* Print shader errors at run-time
+* Update help screen
+* Fix objects not being deleted
+
# 0.B.2
* Fix data directory not being set correctly by CMake;
diff --git a/CREDITS.txt b/CREDITS.txt
index f40cb16..fcd91ea 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -1,13 +1,13 @@
-BOWSHOCK
+BOWSHOCK
COPYRIGHT:
-2022-2023 Gabriel Jensen
+2022-2023 Gabriel Bjørnager Jensen
DESIGN
- Gabriel Jensen
+ Gabriel Bjørnager Jensen
ARTWORK
- Gabriel Jensen
+ Gabriel Bjørnager Jensen
SOFTWARE DEVELOPMENT
- Gabriel Jensen
+ Gabriel Bjørnager Jensen
diff --git a/README.txt b/README.txt
index 01ea541..f395670 100644
--- a/README.txt
+++ b/README.txt
@@ -6,31 +6,27 @@ Read: "CHANGELOG.txt"
# COMPILATION
-Bowshock uses CMake as its build system. The standard option CMAKE_-
-BUILD_TYPE may be set to either "Release" or "Debug", depending on the
-build type.
+Bowshock uses CMake as its build system. The standard option CMAKE_BUILD_TYPE
+may be set to either "Release" or "Debug", depending on the build type.
-The program is written in C2x, and a conforming compiler is therefore
-required. It has been tested to work with GCC 12.2 and Clang 15.0, but
-the option BOW_C2X_COMPATIBILITY may have to be set to "True" when
-invoking CMake.
+The program is written in C++20, and a conforming compiler is therefore
+required.
-Before compilation, an appropriate GLAD loader must be downloaded from
-a web instance. I use the one on dav1d.de, with the following settings:
+Before compilation, an appropriate GLAD loader must be downloaded from a web
+instance. I use the one on dav1d.de, with the following settings:
<https://glad.dav1d.de/#language=c&specification=gl&api=gl%3D4.0&api=gles1%3Dnone&api=gles2%3Dnone&api=glsc2%3Dnone&profile=core&loader=on>
-The script "extractGlad.sh" will extract "glad.zip" (or any other ar-
-chive - if specified) to "glad". It also copies a CMAKE lists file to
-the directory, and CMake will automatically include this and build
-GLAD.
+The script "extractGlad.sh" will extract "glad.zip" (or any other archive - if
+specified) to "glad". It also copies a CMAKE lists file to the directory, and
+CMake will automatically include this and build GLAD.
-Before running - however - the data directory must be installed. This
-can be done via the installation script "install.sh":
+Before running - however - the data directory must be installed. This can be
+done via the installation script "install.sh":
./install.sh data [data directory]
-## DEVELOPMENT
+# DEVELOPMENT
To initialise the environment, I use the following commands:
@@ -49,18 +45,23 @@ cmake --build build && build/bowshock/bowshock --skip
## SHADER VALIDATION
-The shaders at bowshock/shader may be validated using the Python-
-script "validateShaders.py". If the shaders contain errors, and these
-are not fixed before installation, the program will fail to compile
-them during run-time, but the errors will not be diagnosed.
+The shaders at bowshock/shader may be validated using the Python script
+"validateShaders.py". If the shaders contain errors, and these are not fixed
+before installation, the program will fail to compile them during run-time.
-## INSTALLATION
+# INSTALLATION
-The script "install.sh" will install the executable, the assets, the
-shaders... to the specified directories:
+The script "install.sh" will install the executable, the assets, the shaders... to the specified directories:
./install.sh [build directory] [binary directory] [data directory]
+# MIRRORS
+
+mandelbrot.dk (main): <https://mandelbrot.dk/bowshock>
+GitLab: <https://gitlab.com/bjoernager/bowshock.git>
+GitHub: <https://github.com/bjoernager/bowshock.git>
+
+
# CREDITS
Read: "CREDITS.txt"
diff --git a/bowshock.svg b/bowshock.svg
index d0624e3..26f8460 100644
--- a/bowshock.svg
+++ b/bowshock.svg
@@ -1,8 +1,10 @@
<!-- Copyright 2023 Gabriel Jensen. -->
<svg height="120" width="120" xmlns="http://www.w3.org/2000/svg">
<!-- background -->
+ <rect fill="#FFEEE0" height="120" width="120" x="0" y="0" />
+ <!-- outline -->
<circle cx="60" cy="60" fill="#B61833" r="48" />
- <!-- circles -->
+ <!-- rings -->
<circle cx="60" cy="66" fill="none" r="24" stroke="#FFEEE0" stroke-width="12" />
<circle cx="60" cy="54" fill="none" r="24" stroke="#0F0F0F" stroke-width="12" />
</svg>
diff --git a/bowshock/CMakeLists.txt b/bowshock/CMakeLists.txt
index 8d25d90..70e9438 100644
--- a/bowshock/CMakeLists.txt
+++ b/bowshock/CMakeLists.txt
@@ -10,42 +10,42 @@ set(CMAKE_CXX_STANDARD 20)
add_executable(
bowshock
-
- "source/bs/objtypstr.cxx"
- "source/bs/rnd.cxx"
-
- "source/ini/bow/chkpar.cxx"
- "source/ini/bow/cmpshdprg.cxx"
- "source/ini/bow/exi.cxx"
- "source/ini/bow/getquo.cxx"
- "source/ini/bow/getsavpth.cxx"
- "source/ini/bow/hlp.cxx"
- "source/ini/bow/ini.cxx"
- "source/ini/bow/inigfx.cxx"
- "source/ini/bow/inirnd.cxx"
- "source/ini/bow/inisig.cxx"
- "source/ini/bow/lop.cxx"
- "source/ini/bow/polevt.cxx"
- "source/ini/bow/pricrd.cxx"
- "source/ini/bow/priquo.cxx"
- "source/ini/bow/srtseq.cxx"
-
- "source/lgc/grv.cxx"
- "source/lgc/mov.cxx"
- "source/lgc/shpmas.cxx"
- "source/lgc/sim.cxx"
-
- "source/run/abr.cxx"
- "source/run/addobj.cxx"
- "source/run/remobj.cxx"
- "source/run/gensys.cxx"
-
- "source/sav/gendat.cxx"
- "source/sav/cnt.cxx"
- "source/sav/decsav.cxx"
- "source/sav/encsav.cxx"
- "source/sav/newsav.cxx"
- "source/sav/sav.cxx"
+
+ "source/application/bow/check_parameters.cxx"
+ "source/application/bow/compile_shader_program.cxx"
+ "source/application/bow/destructor.cxx"
+ "source/application/bow/get_quote.cxx"
+ "source/application/bow/initialise_graphics.cxx"
+ "source/application/bow/initialise_random.cxx"
+ "source/application/bow/initialise_signal.cxx"
+ "source/application/bow/loop.cxx"
+ "source/application/bow/poll_events.cxx"
+ "source/application/bow/print_credits.cxx"
+ "source/application/bow/print_help.cxx"
+ "source/application/bow/print_quote.cxx"
+ "source/application/bow/run.cxx"
+ "source/application/bow/start_sequence.cxx"
+
+ "source/base/home_directory.cxx"
+ "source/base/object_type_string.cxx"
+ "source/base/random.cxx"
+ "source/base/save_path.cxx"
+
+ "source/logic/gravitate.cxx"
+ "source/logic/move.cxx"
+ "source/logic/ship_mass.cxx"
+ "source/logic/simulate.cxx"
+
+ "source/runtime/add_object.cxx"
+ "source/runtime/generate_system.cxx"
+ "source/runtime/delete_objects.cxx"
+
+ "source/save/continue_save.cxx"
+ "source/save/decode_save.cxx"
+ "source/save/encode_save.cxx"
+ "source/save/generate_data.cxx"
+ "source/save/new_save.cxx"
+ "source/save/save.cxx"
)
add_dependencies(
@@ -63,11 +63,10 @@ target_include_directories(
target_link_libraries(
bowshock PRIVATE
+ fmt
glad
glfw
- ly
m
- zp
)
target_compile_definitions(
@@ -76,8 +75,8 @@ target_compile_definitions(
_FORTIFY_SOURCE=$<IF:$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">,0x0,0x2>
_POSIX_C_SOURCE=200112l
GLFW_INCLUDE_NONE
- bow_datdir="${BOW_DATA_DIRECTORY}"
- bow_dbg=$<IF:$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">,true,false>
+ bow_dataDirectory="${BOW_DATA_DIRECTORY}"
+ bow_debug=$<IF:$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">,true,false>
)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|GNU")
diff --git a/bowshock/include/bow/application.hxx b/bowshock/include/bow/application.hxx
new file mode 100644
index 0000000..d99eaf5
--- /dev/null
+++ b/bowshock/include/bow/application.hxx
@@ -0,0 +1,64 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#include <bow/runtime.hxx>
+
+#include <csignal>
+#include <cstdint>
+#include <glad/glad.h>
+#include <GLFW/glfw3.h>
+#include <string>
+
+namespace bow {
+ constexpr ::std::string SHADER_FILE_SUFFIX("glsl");
+
+ struct GraphicsData {
+ ::GLFWwindow* window;
+ ::GLuint shader_program;
+ };
+
+ struct TerminalOptions {
+ ::std::string save_path;
+ bool has_save_path:0x1;
+ bool new_save:0x1;
+ bool skip_intro:0x1;
+ };
+
+ class Application {
+ public:
+ Application() noexcept = default;
+
+ auto run(int argc, char const* const* argv) noexcept -> void;
+
+ ~Application() noexcept;
+
+ private:
+ ::bow::PlayerData player_data;
+ ::bow::GraphicsData graphics_data;
+
+ auto get_quote(::std::string& quote, ::std::string& source, ::std::uint8_t code) noexcept -> void;
+
+ auto print_quote() noexcept -> void;
+
+ [[noreturn]] auto print_credits() noexcept -> void;
+
+ [[noreturn]] auto print_help(::std::string program_name) noexcept -> void;
+
+ auto check_parameters(TerminalOptions& options, int argc, char const* const* argv) noexcept -> void;
+
+ auto compile_shader_program(::GLuint& shader_program, ::std::string name) noexcept -> void;
+
+ auto initialise_graphics() noexcept -> void;
+ auto initialise_random() noexcept -> void;
+ auto initialise_signal() noexcept -> void;
+
+ auto poll_events() noexcept -> bool;
+
+ auto start_sequence() noexcept -> bool;
+
+ auto loop() noexcept -> void;
+ };
+
+ extern ::std::sig_atomic_t volatile GOT_INTERRUPT;
+}
diff --git a/bowshock/include/bow/bas.hxx b/bowshock/include/bow/bas.hxx
deleted file mode 100644
index 40771fd..0000000
--- a/bowshock/include/bow/bas.hxx
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#pragma once
-
-#ifndef bow_datdir
-#error Data directory not specified!
-#endif
-
-#include <cstdio>
-#include <zp/bs> // We guarantee that this header is included.
-
-static_assert(::zp::bytelen == 0x8u,"Bytes must contain exactly eight bits.");
-
-#define bow_lograw(msg,...) fprintf(stderr,msg __VA_OPT__(,) __VA_ARGS__)
-
-#define bow_log(msg,...) bow_lograw("\x1B[1m%s\x1B[0m: " msg "\n",__func__ __VA_OPT__(,) __VA_ARGS__)
-
-#define bow_logerr(msg,...) bow_log("\x1B[38;5;197m[ERROR]\x1B[0m " msg __VA_OPT__(,) __VA_ARGS__)
-
-#if bow_dbg
-#define bow_logdbg(msg,...) bow_log(msg __VA_OPT__ (,) __VA_ARGS__)
-#else
-#define bow_logdbg(msg,...) ((void)0x0u)
-#endif
-
-#define bow_logxyz(xyz) bow_logdbg("%s: %.03f %.03f %.03f",#xyz,(xyz).x,(xyz).y,(xyz).z)
-
-#define bow_setstrlen(ptr,len,str) ((void)(ptr = str,len = sizeof (str)-0x1u))
-
-namespace bow {
- constexpr ::zp::i04 vermaj = 0x0u;
- constexpr ::zp::i04 vermin = 0xCu;
- constexpr ::zp::i04 verpat = 0x0u;
-
- constexpr auto dbg = bow_dbg;
-
- constexpr ::zp::siz cmdnamlen = 0xEu;
-
- enum struct cnd : ::zp::i8 {
- err, // error
- oky, // okay
- };
-
- enum struct objtyp : ::zp::i8 {
- can, // canister
- ply, // player
- shp, // ship
- tar, // star
- stn, // station
- wrl, // world (planet/moon)
- };
-
- enum struct wrl : ::zp::i8 {
- amm, // ammonium world
- gas, // gas giant
- ice, // icy world
- rck, // rocky world
- lav, // lava world
- wat, // water world
- };
-
- enum struct shp : ::zp::i8 {
- aqu, // aquila
- cas, // cassiopeia
- cen, // centaurus
- cov, // corvus
- cur, // cursor
- eri, // eridanus
- fal, // falco
- lyr, // lyra
- tau, // taurus
- urs, // ursa
- vip, // vipera
- // Remember maxshpid in sav!
- };
-
- enum struct tar : ::zp::i8 {
- a, // main sequence
- b, // main sequence
- c, // carbon
- f, // main sequence
- g, // main sequence
- k, // main sequence
- l, // brown dwarf
- m, // main sequence
- n, // neutron star
- o, // main sequence
- s, // carbon
- t, // brown dwarf
- w, // worm hole
- x, // black hole
- y, // brown dwarf
- z, // white hole
- };
-
- enum struct stn : ::zp::i8 {
- stn_glb, // globus
- stn_orb, // orbis
- };
-
- struct xyz {
- ::zp::f04 x;
- ::zp::f04 y;
- ::zp::f04 z;
- };
-
- struct obj {
- ::bow::objtyp typ;
- union {
- ::bow::wrl wrldTyp;
- ::bow::shp shptyp;
- ::bow::tar tartyp;
- ::bow::stn stnTyp;
- };
- ::bow::xyz pos; // astronomical units
- ::bow::xyz rot; // radians
- ::bow::xyz posVel; // astronomical units per second
- ::bow::xyz rotVel; // radians per second
- ::zp::f04 mas; // kilograms
- ::bow::obj * nxt;
- };
-
- struct objroot {
- ::bow::obj * objs;
- };
-
- struct plydat {
- char nam[::bow::cmdnamlen+0x1u];
- ::zp::i04 tim;
- ::zp::i04 sysidt;
- ::bow::obj shp;
- float zom;
- };
-
- auto objtypstr(::bow::objtyp typ) noexcept -> char const *;
-
- auto rnd() noexcept -> ::zp::i04;
-}
diff --git a/bowshock/include/bow/base.hxx b/bowshock/include/bow/base.hxx
new file mode 100644
index 0000000..ce384d8
--- /dev/null
+++ b/bowshock/include/bow/base.hxx
@@ -0,0 +1,136 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#ifndef bow_dataDirectory
+#error data directory not specified!
+#endif
+
+#include <climits>
+#include <cstdint>
+#include <cstdio>
+#include <string>
+
+static_assert(CHAR_BIT == 0x8, "bytes must contain exactly eight bits.");
+
+namespace bow {
+ inline ::std::string DATA_DIRECTORY(bow_dataDirectory);
+
+ constexpr ::std::uint8_t NUMBER_OF_QUOTE_IDENTIFIERS = UINT8_C(0x24);
+
+ template<typename T> struct VersionType {
+ T major;
+ T minor;
+ T patch;
+ };
+
+ constexpr VersionType<::std::uint64_t> VERSION = {
+ .major = 0x0u,
+ .minor = 0xCu,
+ .patch = 0x1u,
+ };
+
+ constexpr bool DEBUG = bow_debug;
+
+ constexpr ::std::size_t COMMANDER_NAME_LENGTH = 0xEu;
+
+ enum struct ObjectType : ::std::uint8_t {
+ Canister,
+ Player,
+ Ship,
+ Star,
+ Station,
+ World, // planet/moon
+ };
+
+ enum struct World : ::std::uint8_t {
+ Ammonium_world, // ammonium world
+ Gas_giant,
+ Ice_world,
+ Rocky_world,
+ Lava_world,
+ Water_world,
+ };
+
+ enum struct Ship : ::std::uint8_t {
+ Aquila,
+ Cassiopeia,
+ Centaurus,
+ Corvus,
+ Cursor,
+ Eridanus,
+ Falco,
+ Lyra,
+ Taurus,
+ Ursa,
+ Vipera,
+ _max,
+ };
+
+ enum struct Star : ::std::uint8_t {
+ A, // main sequence
+ B, // main sequence
+ C, // carbon
+ F, // main sequence
+ G, // main sequence
+ K, // main sequence
+ L, // brown dwarf
+ M, // main sequence
+ N, // neutron star
+ O, // main sequence
+ S, // carbon
+ T, // brown dwarf
+ W, // worm hole
+ X, // black hole
+ Y, // brown dwarf
+ Z, // white hole
+ };
+
+ enum struct Station : ::std::uint8_t {
+ Globus,
+ Orbis,
+ };
+
+ struct Xyz {
+ double x;
+ double y;
+ double z;
+ };
+
+ struct Object {
+ ::bow::ObjectType type;
+ union {
+ ::bow::World world_type;
+ ::bow::Ship ship_type;
+ ::bow::Star star_type;
+ ::bow::Station station_type;
+ };
+
+ ::bow::Xyz position; // astronomical units
+ ::bow::Xyz rotation; // radians
+ ::bow::Xyz positional_velocity; // astronomical units per second
+ ::bow::Xyz rotational_velocity; // radians per second
+ double mass; // kilograms
+
+ ::bow::Object* next;
+ };
+
+ struct ObjectRoot {
+ ::bow::Object* objects;
+ };
+
+ struct PlayerData {
+ char name[::bow::COMMANDER_NAME_LENGTH + 0x1u];
+ ::std::uint64_t time;
+ ::std::uint64_t system_identifier;
+ ::bow::Object ship;
+ float zoom;
+ };
+
+ auto object_type_string(::bow::ObjectType type) noexcept -> ::std::string;
+
+ auto random() noexcept -> ::std::uint64_t;
+
+ auto home_directory() noexcept -> ::std::string;
+ auto save_path() noexcept -> ::std::string;
+}
diff --git a/bowshock/include/bow/ini.hxx b/bowshock/include/bow/ini.hxx
deleted file mode 100644
index 486d406..0000000
--- a/bowshock/include/bow/ini.hxx
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#pragma once
-
-#include <bow/run.hxx>
-
-#include <GLFW/glfw3.h>
-#include <csignal>
-#include <glad/glad.h>
-
-namespace bow {
- constexpr char const shdfilext[] = "glsl";
-
- struct gfxdat {
- ::GLFWwindow * win;
- ::GLuint shdprg;
- };
-
- struct trmopt {
- char const * savpth;
- bool hassavpth:0x1u;
- bool newsav:0x1u;
- bool skp:0x1u;
- };
-
- class bow {
- public:
- [[noreturn]] auto ini(int argc,char const * const * argv) noexcept -> void;
-
- private:
- ::bow::plydat plydat;
- ::bow::gfxdat gfxdat;
-
- auto getsavpth() noexcept -> char const *;
- auto getquo( char const * * quo,char const * * src,::zp::i8 id) noexcept -> void;
-
- auto priquo() noexcept -> void;
-
- [[noreturn]] auto pricrd() noexcept -> void;
- [[noreturn]] auto hlp(char const * prognm) noexcept -> void;
-
- auto chkpar(trmopt & opt,int argc,char const * const * argv) noexcept -> void;
-
- auto compshdprg(::GLuint & shdprg,char const * nam) noexcept -> void;
-
- auto inigfx() noexcept -> void;
- auto inirnd() noexcept -> void;
- auto inisig() noexcept -> void;
-
- auto polevt() noexcept -> bool;
-
- auto srtseq() noexcept -> bool;
- auto lop() noexcept -> void;
-
- [[noreturn]] auto exi(::bow::cnd stat) noexcept -> void;
- };
-
- extern ::std::sig_atomic_t volatile gotint;
-}
diff --git a/bowshock/include/bow/lgc.hxx b/bowshock/include/bow/lgc.hxx
deleted file mode 100644
index 57d4171..0000000
--- a/bowshock/include/bow/lgc.hxx
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#pragma once
-
-#include <bow/bas.hxx>
-
-namespace bow {
- constexpr ::zp::f04 dstmod = 0x1.16A5D2D360000000p037; // distance modifier (1 astronomical unit)
- constexpr ::zp::f04 masmod = 0x1.91930A5E75F0C192p100; // mass modifier (1 solar mas)
- constexpr ::zp::f04 timmod = 0x1.0000000000000000p012; // time modifier (1 second)
-
- constexpr ::zp::f04 grvfac = (::bow::masmod*(::bow::timmod*::bow::timmod))/((::bow::dstmod*::bow::dstmod*::bow::dstmod)); // inverse
-
- constexpr ::zp::f04 grvval = 0x1.258688101B4BB16Dp-34*::bow::grvfac; // gravitational constant (s^2*m*t^2)
-
- [[nodiscard]] auto shpmas(::bow::shp id) noexcept -> ::zp::f04;
-
- auto grv(::bow::objroot & sys) noexcept -> void;
- auto grv(::bow::objroot & objs,::bow::objroot const & sys) noexcept -> void;
- auto mov(::bow::objroot & root) noexcept -> void;
-
- auto sim(::bow::objroot & sys,::zp::i04 dur) noexcept -> void;
-}
diff --git a/bowshock/include/bow/logic.hxx b/bowshock/include/bow/logic.hxx
new file mode 100644
index 0000000..dee11cb
--- /dev/null
+++ b/bowshock/include/bow/logic.hxx
@@ -0,0 +1,26 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#include <bow/base.hxx>
+
+#include <cstdint>
+
+namespace bow {
+ constexpr double DISTANCE_MODIFIER = 0x1.16A5D2D360000000p037; // 1 astronomical unit
+ constexpr double MASS_MODIFIER = 0x1.91930A5E75F0C192p100; // 1 solar mass
+ constexpr double TIME_MODIFIER = 0x1.0000000000000000p012; // 1 second
+
+ constexpr double GRAVITY_FACTOR = (::bow::MASS_MODIFIER * (::bow::TIME_MODIFIER * ::bow::TIME_MODIFIER)) / ((::bow::DISTANCE_MODIFIER * ::bow::DISTANCE_MODIFIER * ::bow::DISTANCE_MODIFIER)); // Inverse.
+
+ constexpr double GRAVITY_VALUE = 0x1.258688101B4BB16Dp-34 * ::bow::GRAVITY_FACTOR; // gravitational constant (s^2*m*t^2)
+
+ [[nodiscard]] auto ship_mass(::bow::Ship identifier) noexcept -> double;
+
+ auto gravitate(::bow::ObjectRoot& system) noexcept -> void;
+ auto gravitate(::bow::ObjectRoot& objects, ::bow::ObjectRoot const& system) noexcept -> void;
+
+ auto move(::bow::ObjectRoot& root) noexcept -> void;
+
+ auto simulate(::bow::ObjectRoot& system, ::std::uint64_t duration) noexcept -> void;
+}
diff --git a/bowshock/include/bow/run.hxx b/bowshock/include/bow/run.hxx
deleted file mode 100644
index 5c7be43..0000000
--- a/bowshock/include/bow/run.hxx
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#pragma once
-
-#include <bow/bas.hxx>
-
-#include <source_location>
-
-namespace bow {
- [[noreturn]] auto abr(::std::source_location srcloc = ::std::source_location::current()) noexcept -> void;
-
- auto addobj(::bow::objroot & root,::bow::obj const & obj) -> void;
- auto remobj(::bow::objroot const & root) noexcept -> void;
-
- auto gensys(::bow::objroot & sys,::zp::i04 id,::zp::i04 tim) -> void;
-}
diff --git a/bowshock/include/bow/runtime.hxx b/bowshock/include/bow/runtime.hxx
new file mode 100644
index 0000000..de6a0b8
--- /dev/null
+++ b/bowshock/include/bow/runtime.hxx
@@ -0,0 +1,18 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#include <bow/base.hxx>
+
+#include <cstdint>
+#include <source_location>
+
+namespace bow {
+ [[noreturn]] auto abort(::std::source_location source_location = ::std::source_location::current()) noexcept -> void;
+
+ auto add_object(::bow::ObjectRoot& root, ::bow::Object const& object) -> void;
+
+ auto delete_objects(::bow::ObjectRoot const& root) noexcept -> void;
+
+ auto generate_system(::bow::ObjectRoot& system, ::std::uint64_t identifier, ::std::uint64_t time) -> void;
+}
diff --git a/bowshock/include/bow/sav.hxx b/bowshock/include/bow/sav.hxx
deleted file mode 100644
index f1eca58..0000000
--- a/bowshock/include/bow/sav.hxx
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#pragma once
-
-#include <bow/bas.hxx>
-
-namespace bow {
- constexpr ::zp::i04 savver = 0x6u;
-
- constexpr ::zp::siz savlen = 0x79u+::bow::cmdnamlen;
-
- constexpr ::zp::i8 maxshpid = static_cast<::zp::i8>(::bow::shp::vip);
-
- /*
- Save format:
-
- offset: id: size [bytes]: format:
-
- 0x00 fmtver 8 unsigned
- 0x08 cmdnam E UTF-8
- 0x16 tim 8 unsigned
- 0x1E sysidt 8 unsigned
- 0x1F shptyp 1 unsigned
- 0x27 shpposx 8 binary64
- 0x2F shpposy 8 binary64
- 0x37 shpposz 8 binary64
- 0x3F shprotx 8 binary64
- 0x47 shproty 8 binary64
- 0x4F shprotz 8 binary64
- 0x57 shpposvelx 8 binary64
- 0x5F shpposvely 8 binary64
- 0x67 shpposvelz 8 binary64
- 0x6F shprotvelx 8 binary64
- 0x77 shprotvely 8 binary64
- 0x7F shprotvelz 8 binary64
- */
-
- struct savdat {
- ::zp::i04 fmtVer;
- char8_t cmdnam[::bow::cmdnamlen];
- ::zp::i04 tim;
- ::zp::i04 sysidt;
- ::zp::i8 shptyp;
- ::zp::f04 shpposx;
- ::zp::f04 shpposy;
- ::zp::f04 shpposz;
- ::zp::f04 shprotx;
- ::zp::f04 shproty;
- ::zp::f04 shprotz;
- ::zp::f04 shpposvelx;
- ::zp::f04 shpposvely;
- ::zp::f04 shpposvelz;
- ::zp::f04 shprotvelx;
- ::zp::f04 shprotvely;
- ::zp::f04 shprotvelz;
- };
-
- auto decsav(::bow::savdat & buf,::zp::i8 const * dat) noexcept -> void;
- auto encsav(::zp::i8 * buf,::bow::savdat const & dat) noexcept -> void;
-
- auto newsav(::bow::plydat & dat) noexcept -> void;
-
- auto cnt( ::bow::plydat & dat,char const * fil) noexcept -> void;
- auto gendat(::bow::plydat & dat) noexcept -> void;
-
- auto sav(char const * fil,::bow::plydat const & dat) noexcept -> void;
-}
diff --git a/bowshock/include/bow/save.hxx b/bowshock/include/bow/save.hxx
new file mode 100644
index 0000000..b9f4ca4
--- /dev/null
+++ b/bowshock/include/bow/save.hxx
@@ -0,0 +1,72 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#include <bow/base.hxx>
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+namespace bow {
+ constexpr ::std::uint64_t SAVE_VERSION = 0x6u;
+
+ constexpr ::std::size_t SAVE_LENGTH = 0x79u + ::bow::COMMANDER_NAME_LENGTH;
+
+ constexpr ::std::uint8_t MAX_SHIP_IDENTIFIER = static_cast<::std::uint8_t>(::bow::Ship::_max);
+
+ /*
+ Save format:
+
+ offset: identifier: size: format:
+
+ 0x00 format_version 8 unsigned
+ 0x08 commander_name E UTF-8
+ 0x16 time 8 unsigned
+ 0x1E system_identifier 8 unsigned
+ 0x1F ship_type 1 unsigned
+ 0x27 ship_position_x 8 binary64
+ 0x2F ship_position_y 8 binary64
+ 0x37 ship_position_z 8 binary64
+ 0x3F ship_rotation_x 8 binary64
+ 0x47 ship_rotation_y 8 binary64
+ 0x4F ship_rotation_z 8 binary64
+ 0x57 ship_positional_velocity_x 8 binary64
+ 0x5F ship_positional_velocity_y 8 binary64
+ 0x67 ship_positional_velocity_z 8 binary64
+ 0x6F ship_rotational_velocity_x 8 binary64
+ 0x77 ship_rotational_velocity_y 8 binary64
+ 0x7F ship_rotational_velocity_z 8 binary64
+ */
+
+ struct save_data {
+ ::std::uint64_t format_version;
+ char8_t commander_name[::bow::COMMANDER_NAME_LENGTH];
+ ::std::uint64_t time;
+ ::std::uint64_t system_identifier;
+ ::std::uint8_t ship_type;
+ double ship_position_x;
+ double ship_position_y;
+ double ship_position_z;
+ double ship_rotation_x;
+ double ship_rotation_y;
+ double ship_rotation_z;
+ double ship_positional_velocity_x;
+ double ship_positional_velocity_y;
+ double ship_positional_velocity_z;
+ double ship_rotational_velocity_x;
+ double ship_rotational_velocity_y;
+ double ship_rotational_velocity_z;
+ };
+
+ auto decode_save(::bow::save_data& buf, void const* data) noexcept -> void;
+ auto encode_save(void* buf, ::bow::save_data const& data) noexcept -> void;
+
+ auto new_save(::bow::PlayerData& data) noexcept -> void;
+
+ auto continue_save(::bow::PlayerData& data, ::std::string file) noexcept -> void;
+
+ auto generate_data(::bow::PlayerData& data) noexcept -> void;
+
+ auto save(::std::string file, ::bow::PlayerData const& data) noexcept -> void;
+}
diff --git a/bowshock/shader/main.frag.glsl b/bowshock/shader/main.frag.glsl
index 08d14db..243dd29 100644
--- a/bowshock/shader/main.frag.glsl
+++ b/bowshock/shader/main.frag.glsl
@@ -1,7 +1,7 @@
#version 410 core
-out vec4 col;
+out vec4 colour;
void main() {
- col = vec4(0.7137f,0.0941f,0.2000f,1.0f);
+ colour = vec4(0.7137f, 0.0941f, 0.2000f, 1.0f);
}
diff --git a/bowshock/shader/main.vert.glsl b/bowshock/shader/main.vert.glsl
index b4f862a..7d2c88d 100644
--- a/bowshock/shader/main.vert.glsl
+++ b/bowshock/shader/main.vert.glsl
@@ -1,7 +1,7 @@
#version 410 core
-layout (location = 0x0) in vec3 pos;
+layout (location = 0x0) in vec3 position;
void main() {
- gl_Position = vec4(pos.x,pos.y,pos.z,1.0f);
+ gl_Position = vec4(position.x, position.y, position.z, 1.0f);
}
diff --git a/bowshock/source/application/bow/check_parameters.cxx b/bowshock/source/application/bow/check_parameters.cxx
new file mode 100644
index 0000000..535631c
--- /dev/null
+++ b/bowshock/source/application/bow/check_parameters.cxx
@@ -0,0 +1,41 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstring>
+#include <fmt/core.h>
+#include <string>
+#include <vector>
+
+auto ::bow::Application::check_parameters(::bow::TerminalOptions& options, int const argc, char const* const* argv) noexcept -> void {
+ ::std::string const program_name = *argv;
+
+ options = ::bow::TerminalOptions {
+ .has_save_path = false,
+ .new_save = false,
+ .skip_intro = false,
+ };
+
+ if (argc >= 0x2) [[unlikely]] {
+ ::std::vector<char const*> parameters(argv + 0x1u, argv + static_cast<::std::size_t>(argc));
+
+ for (auto parameter : parameters) {
+ if (parameter[0x0u] == '-' && parameter[0x1u] == '-') {
+ parameter += 0x2u;
+
+ if (!::std::strcmp(parameter, "credits")) { print_credits(); }
+ else if (!::std::strcmp(parameter, "print_help")) { print_help(program_name); }
+ else if (!::std::strcmp(parameter, "new")) { options.new_save = true; }
+ else if (!::std::strcmp(parameter, "skip")) { options.skip_intro = true; }
+ else { ::fmt::print(stderr, "invalid pareter \"{}\"\n", parameter); }
+
+ continue;
+ }
+
+ // Else: Interpret it as a save path.
+ options.save_path = parameter;
+ options.has_save_path = true;
+ }
+ }
+}
diff --git a/bowshock/source/application/bow/compile_shader_program.cxx b/bowshock/source/application/bow/compile_shader_program.cxx
new file mode 100644
index 0000000..c6ed0cb
--- /dev/null
+++ b/bowshock/source/application/bow/compile_shader_program.cxx
@@ -0,0 +1,137 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <filesystem>
+#include <fmt/core.h>
+#include <glad/glad.h>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+namespace bow {
+ static auto compile_shader(::GLuint& shader, ::std::string name, ::GLenum type) -> void;
+}
+
+using namespace ::std::literals::string_literals;
+
+static auto ::bow::compile_shader(::GLuint& shader, ::std::string const name, ::GLenum const type) -> void {
+ auto const type_suffix = [type]() -> ::std::string {
+ switch (type) {
+ default: [[unlikely]]
+ ::fmt::print(stderr, "bad shader type {}\n", static_cast<unsigned int>(type));
+
+ ::std::abort();
+
+ case GL_FRAGMENT_SHADER:
+ return "frag"s;
+
+ case GL_GEOMETRY_SHADER:
+ return "geom"s;
+
+ case GL_TESS_CONTROL_SHADER:
+ return "tesc"s;
+
+ case GL_TESS_EVALUATION_SHADER:
+ return "tese"s;
+
+ case GL_VERTEX_SHADER:
+ return "vert"s;
+ }
+ }();
+
+ auto const type_string = [type]() -> ::std::string {
+ switch (type) {
+ default: [[unlikely]]
+ ::std::abort();
+
+ case GL_FRAGMENT_SHADER:
+ return "fragment"s;
+
+ case GL_GEOMETRY_SHADER:
+ return "geometry"s;
+
+ case GL_TESS_CONTROL_SHADER:
+ return "tesselation control"s;
+
+ case GL_TESS_EVALUATION_SHADER:
+ return "tesselation evaluation"s;
+
+ case GL_VERTEX_SHADER:
+ return "vertex"s;
+ }
+ }();
+
+ using ::bow::DATA_DIRECTORY;
+
+ auto path = DATA_DIRECTORY + "/shaders/" + name + "." + type_suffix + "." + ::bow::SHADER_FILE_SUFFIX;
+
+ ::fmt::print(stderr, "compiling {} shader at \"{}\"\n", type_string, path);
+
+ ::std::FILE* file = ::std::fopen(path.c_str(), "r");
+
+ if (file == nullptr) [[unlikely]] { throw ::std::runtime_error {"unable to open shader source"}; }
+
+ auto const file_size = ::std::filesystem::file_size(path);
+
+ static_assert(::std::is_same_v<GLchar, char>);
+ auto source = ::std::vector<GLchar>(file_size + 0x1u);
+
+ ::std::fread(source.data(), 0x1u, file_size, file);
+
+ ::std::fclose(file);
+
+ source.push_back('\x00');
+
+ auto const source_pointer = source.data();
+
+ shader = glCreateShader(type);
+ glShaderSource(shader, 0x1, const_cast<::GLchar const* const*>(&source_pointer), nullptr);
+
+ glCompileShader(shader);
+
+ ::GLint compilation_status = 0x0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compilation_status);
+
+ if (compilation_status == GL_FALSE) [[unlikely]] {
+ ::GLint log_length = 0x0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+
+ auto log = new ::GLchar[static_cast<::std::size_t>(log_length)];
+
+ glGetShaderInfoLog(shader, log_length, nullptr, log);
+
+ ::fmt::print(stderr, "unable to compiler shader:\n");
+
+ ::std::fwrite(log, 0x1u, static_cast<::std::size_t>(log_length), stderr);
+
+ delete[] log;
+
+ throw ::std::runtime_error {"unable to compile shader"};
+ }
+}
+
+auto ::bow::Application::compile_shader_program(::GLuint& shader_program, ::std::string const name) noexcept -> void {
+ ::fmt::print(stderr, "compiling shader program \"{}\"\n", name);
+
+ ::GLuint vertex_shader;
+ ::GLuint fragment_shader;
+
+ using ::bow::compile_shader;
+
+ // Ignore exceptions:
+ compile_shader(vertex_shader, name, GL_VERTEX_SHADER);
+ compile_shader(fragment_shader, name, GL_FRAGMENT_SHADER);
+
+ shader_program = glCreateProgram();
+ glAttachShader(shader_program, vertex_shader);
+ glAttachShader(shader_program, fragment_shader);
+ glLinkProgram(shader_program);
+
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+}
diff --git a/bowshock/source/application/bow/destructor.cxx b/bowshock/source/application/bow/destructor.cxx
new file mode 100644
index 0000000..7df50ab
--- /dev/null
+++ b/bowshock/source/application/bow/destructor.cxx
@@ -0,0 +1,19 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <fmt/core.h>
+#include <GLFW/glfw3.h>
+
+::bow::Application::~Application() noexcept {
+ ::fmt::print(stderr, "quitting\n");
+
+ glDeleteProgram(graphics_data.shader_program);
+
+ ::glfwDestroyWindow(graphics_data.window);
+ ::glfwTerminate();
+
+ ::fmt::print(stderr, "Goodbye!\n");
+}
diff --git a/bowshock/source/application/bow/get_quote.cxx b/bowshock/source/application/bow/get_quote.cxx
new file mode 100644
index 0000000..14bf05c
--- /dev/null
+++ b/bowshock/source/application/bow/get_quote.cxx
@@ -0,0 +1,161 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdint>
+#include <fmt/core.h>
+#include <string>
+
+using namespace ::std::literals::string_literals;
+
+auto ::bow::Application::get_quote(::std::string& quote, ::std::string& source, ::std::uint8_t const identifier) noexcept -> void {
+ switch (identifier) {
+ default:
+ ::fmt::print(stderr, "invalid quote identifier ({})\n", identifier);
+ [[fallthrough]];
+ case 0x0u:
+ quote = "You gotta be heaven to see heaven.";
+ source = "Jim Carrey";
+ break;
+ case 0x1u:
+ quote = "Though it's the end of the world, don't blame yourself, now.";
+ source = "Porter Robinson";
+ break;
+ case 0x2u:
+ quote = "The future will be better tomorrow.";
+ source = "Dan Quayle";
+ break;
+ case 0x3u:
+ quote = "Sir, an equation has no meaning for me unless it expresses a thought of god.";
+ source = "Srinivasa Ramanujan Aiyangar";
+ break;
+ case 0x4u:
+ quote = "Amīcus Platō amīcus Aristotelēs magis amīca vēritās.";
+ source = "Isaac Newton";
+ break;
+ case 0x5u:
+ quote = "I have studied these things \u2013 you have not.";
+ source = "Isaac Newton";
+ break;
+ case 0x6u:
+ quote = "La construction d'une machine propre à exprimer tous les sons de nos paroles, avec toutes les articulations, serait sans doute une décourverte bien importante.\n... La chose ne me paraît pas impossible.";
+ source = "Leonhard Euler";
+ break;
+ case 0x7u:
+ quote = "In mathematics, you don't understand things, you just get used to them.";
+ source = "John von Neumann";
+ break;
+ case 0x8u:
+ quote = "Being a language, mathematics may be used not only to inform, but also \u2013 among other things \u2013 to seduce.";
+ source = "Benoît B. Mandelbrot";
+ break;
+ case 0x9u:
+ quote = "The real question is not whether machines think, but whether men do.";
+ source = "Burrhus Frederic Skinner";
+ break;
+ case 0xAu:
+ quote = "Those who are not shocked when they first come across quantum theory cannot possibly have understood it.";
+ source = "Niels Henrik David Bohr";
+ break;
+ case 0xBu:
+ quote = "Every sentence I utter must be understood not as an affirmation, but as a question.";
+ source = "Niels Henrik David Bohr";
+ break;
+ case 0xCu:
+ quote = "We will now discuss in a little more detail the struggle for existence.";
+ source = "Charles Robert Darwin";
+ break;
+ case 0xDu:
+ quote = "name et ipsa scientia potestas est.";
+ source = "Francis Bacon";
+ break;
+ case 0xEu:
+ quote = "We don't know a millionth of one percent about anything.";
+ source = "Thomas Alva Edison";
+ break;
+ case 0xFu:
+ quote = "My goal is simple. It is a complete understanding of the universe, why it is as it is, and why it exists at all.";
+ source = "Stephen William Hawking";
+ break;
+ case 0x10u:
+ quote = "Equipped with his five senses, man explores the universe around him and calls the adventure Science.";
+ source = "Edwin Powell Hubble";
+ break;
+ case 0x11u:
+ quote = "I canister say this: I believe that the human mind, or even the mind of a cat, is more interesting in its complexity than an entire galaxy if it is devoid of life.";
+ source = "Martin Gardner";
+ break;
+ case 0x12u:
+ quote = "I'm always right. This time I'm just more right than usual.";
+ source = "Linus Benedict Torvalds";
+ break;
+ case 0x13u:
+ quote = "I'm an instant star. Just add water and stir.";
+ source = "David Robert Jones";
+ break;
+ case 0x14u:
+ quote = "Don't waste the Earth \u2013 it is our jewel!";
+ source = "Buzz Eugene Aldrin";
+ break;
+ case 0x15u:
+ quote = "I think we're going to the moon because it's in the nature of the human being to face challenges.";
+ source = "Neil Alden Armstrong";
+ break;
+ case 0x16u:
+ quote = "A hacker is someone who enjoys playful cleverness \u2013 not necessarily with computers.";
+ source = "Richard Matthew Stallman";
+ break;
+ case 0x17u:
+ quote = "So Einstein was wrong when he said \"God noes not play dice.\". Consideration of black holes suggests, not only that God does play dice, but that he sometimes confuses us by throwing them where they canister't be seen.";
+ source = "Stephen William Hawking";
+ break;
+ case 0x18u:
+ quote = "I'm a blacktar.";
+ source = "David Robert Jones";
+ break;
+ case 0x19u:
+ quote = "Sooner or later, we must expand life beyond our little blue mud ball \u2013 or go extinct.";
+ source = "Elon Reeve Musk";
+ break;
+ case 0x1Au:
+ quote = "I would like to die on Mars \u2013 just not on impact.";
+ source = "Elon Reeve Musk";
+ break;
+ case 0x1Bu:
+ quote = "The web does not just connect computers; it connects people.";
+ source = "Timothy John Berners-Lee";
+ break;
+ case 0x1Cu:
+ quote = "canister digital computers think?";
+ source = "Alan Mathison Turing";
+ break;
+ case 0x1Du:
+ quote = "That's one small step for a man, one giant leap for mankind.";
+ source = "Neil Alden Armstrong";
+ break;
+ case 0x1Eu:
+ quote = "If you think it's simple, then you have misunderstood the problem.";
+ source = "Bjarne Stroustrup";
+ break;
+ case 0x1Fu:
+ quote = "Controlling complexity is the essence of computer programming.";
+ source = "Brian Wilson Kerningham";
+ break;
+ case 0x20u:
+ quote = "I have always wished for my computer to be as easy to use as my telephone.\nMy wish has come true because I canister no longer figure out how to use my telephone.";
+ source = "Bjarne Stroustrup";
+ break;
+ case 0x21u:
+ quote = "There is no mathematical sibstitute for philosophy.";
+ source = "Saul Aaron Kripke";
+ break;
+ case 0x22u:
+ quote = "Biology is engineering.";
+ source = "Daniel Clement Dennett III";
+ break;
+ case 0x23u:
+ quote = "The universe is under no obligation to make sense to you.";
+ source = "Neil deGrasse Tyson";
+ break;
+ }
+}
diff --git a/bowshock/source/application/bow/initialise_graphics.cxx b/bowshock/source/application/bow/initialise_graphics.cxx
new file mode 100644
index 0000000..83cc624
--- /dev/null
+++ b/bowshock/source/application/bow/initialise_graphics.cxx
@@ -0,0 +1,56 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <fmt/core.h>
+#include <glad/glad.h>
+#include <GLFW/glfw3.h>
+
+auto ::bow::Application::initialise_graphics() noexcept -> void {
+ ::fmt::print(stderr, "initialising graphics\n");
+
+ ::fmt::print(stderr, "initialising glfw\n");
+
+ if (!::glfwInit()) [[unlikely]] {
+ ::fmt::print(stderr, "unable to initialise glfw\n");
+
+ ::std::abort();
+ }
+
+ ::fmt::print(stderr, "initialising window\n");
+
+ ::glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 0x4);
+ ::glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0x1);
+ ::glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
+ ::glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ ::glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
+ ::glfwWindowHint(GLFW_SAMPLES, 0x8);
+
+ graphics_data.window = ::glfwCreateWindow(0x400, 0x240, "Bowshock", ::glfwGetPrimaryMonitor(), nullptr);
+
+ if (graphics_data.window == nullptr) [[unlikely]] {
+ ::fmt::print(stderr, "unable to open window");
+
+ ::std::abort();
+ }
+
+ ::fmt::print(stderr, "initialising context\n");
+
+ ::glfwMakeContextCurrent(graphics_data.window);
+ ::gladLoadGL();
+
+ glEnable(GL_MULTISAMPLE);
+
+ ::GLFWvidmode const* const video_mode = ::glfwGetVideoMode(::glfwGetPrimaryMonitor());
+
+ glViewport(0x0, 0x0, video_mode->width, video_mode->height);
+ glClearColor(0x0p0, 0x0p0, 0x0p0, 0x1p0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ ::glfwSwapBuffers(graphics_data.window);
+ ::glfwSwapInterval(0x1);
+
+ this->compile_shader_program(graphics_data.shader_program, "main");
+}
diff --git a/bowshock/source/application/bow/initialise_random.cxx b/bowshock/source/application/bow/initialise_random.cxx
new file mode 100644
index 0000000..9ea6644
--- /dev/null
+++ b/bowshock/source/application/bow/initialise_random.cxx
@@ -0,0 +1,14 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <fmt/core.h>
+
+auto ::bow::Application::initialise_random() noexcept -> void {
+ ::fmt::print(stderr, "initialising random number generator\n");
+
+ ::std::srand(static_cast<unsigned int>(::std::time(nullptr)));
+}
diff --git a/bowshock/source/application/bow/initialise_signal.cxx b/bowshock/source/application/bow/initialise_signal.cxx
new file mode 100644
index 0000000..40996ce
--- /dev/null
+++ b/bowshock/source/application/bow/initialise_signal.cxx
@@ -0,0 +1,38 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <fmt/core.h>
+
+::std::sig_atomic_t volatile ::bow::GOT_INTERRUPT;
+
+namespace bow {
+ static auto interrupt_handler(int const signal) -> void;
+}
+
+static auto ::bow::interrupt_handler(int const signal) -> void {
+ // Ignore the return value: We canister't do anything (meaningful) about it anyways.
+ ::std::signal(signal, ::bow::interrupt_handler);
+
+ ::bow::GOT_INTERRUPT = 0x1;
+};
+
+auto ::bow::Application::initialise_signal() noexcept -> void {
+ ::fmt::print(stderr, "initialising signal handlers\n");
+
+ ::bow::GOT_INTERRUPT = 0x0;
+
+ auto const set_handler = []<typename Handler>(int const signal, Handler const& handler) -> void {
+ if (::std::signal(signal, static_cast<auto (*)(int) -> void>(handler)) == SIG_ERR) [[unlikely]] {
+ ::fmt::print(stderr, "unable to set signal handler for {}\n", signal);
+
+ ::std::abort();
+ }
+ };
+
+ set_handler(SIGINT, ::bow::interrupt_handler);
+ set_handler(SIGTERM, ::bow::interrupt_handler);
+}
diff --git a/bowshock/source/application/bow/loop.cxx b/bowshock/source/application/bow/loop.cxx
new file mode 100644
index 0000000..318af0e
--- /dev/null
+++ b/bowshock/source/application/bow/loop.cxx
@@ -0,0 +1,122 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+#include <bow/logic.hxx>
+
+#include <cmath>
+#include <cstdio>
+#include <fmt/core.h>
+#include <glad/glad.h>
+#include <GLFW/glfw3.h>
+#include <stdexcept>
+
+auto ::bow::Application::loop() noexcept -> void {
+ ::fmt::print(stderr, "entering main loop\n");
+
+ ::GLfloat vertices[] = {
+ -0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
+ +0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
+ +0x0.0000p0f, +0x0.0000p0f, 0x0p0f,
+ };
+
+ ::GLuint vao;
+ ::GLuint vbo;
+ glGenVertexArrays(0x1, &vao);
+ glGenBuffers(0x1, &vbo);
+
+ glBindVertexArray(vao);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STREAM_DRAW);
+
+ glVertexAttribPointer(0x0, 0x3, GL_FLOAT, GL_FALSE, 0x3* sizeof (::GLfloat), nullptr);
+ glEnableVertexAttribArray(0x0);
+
+ // For stellar bodies:
+ ::bow::ObjectRoot system_root;
+ // For miscellaneous objects (canisters, shps...):
+ ::bow::ObjectRoot objects_root = {
+ .objects = nullptr,
+ };
+
+ try {::bow::generate_system(system_root, player_data.system_identifier, player_data.time); }
+ catch (::std::bad_alloc const&) {
+ ::fmt::print(stderr, "unable to allocate memory for object\n");
+
+ ::std::abort();
+ }
+
+ ::bow::Object object_temporary = {
+ .type = ::bow::ObjectType::Canister,
+ .position = {
+ .x = 0x0p0,
+ .y = -0x2p0,
+ .z = 0x0p0,
+ },
+ .rotation = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .positional_velocity = {
+ .x = -0x1p-12,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotational_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .mass = 0x1p0,
+ };
+ ::bow::add_object(objects_root, object_temporary);
+
+ auto const scroll_handler = [](::GLFWwindow* const window, [[maybe_unused]] double const x_offset, double const y_offset) -> void {
+ ::bow::PlayerData* data = static_cast<::bow::PlayerData*>(::glfwGetWindowUserPointer(window));
+
+ data->zoom *= ::std::pow(0x1.04p0f, 0x0p0f-static_cast<float>(y_offset));
+ };
+
+ ::glfwSetWindowUserPointer(graphics_data.window, &player_data);
+ ::glfwSetScrollCallback(graphics_data.window, scroll_handler);
+
+ for (;; ++player_data.time) {
+ if (this->poll_events()) [[unlikely]] break;
+
+ ::bow::gravitate(system_root);
+ ::bow::gravitate(objects_root, system_root);
+
+ ::bow::move(system_root);
+ ::bow::move(objects_root);
+
+ ::GLfloat const frame = 0x1p0f*player_data.zoom;
+
+ vertices[0x0u] = static_cast<::GLfloat>(system_root.objects->next->position.x) / frame;
+ vertices[0x1u] = static_cast<::GLfloat>(system_root.objects->next->position.y) / frame;
+ vertices[0x3u] = static_cast<::GLfloat>(system_root.objects->position.x) / frame;
+ vertices[0x4u] = static_cast<::GLfloat>(system_root.objects->position.y) / frame;
+ vertices[0x6u] = static_cast<::GLfloat>(objects_root.objects->position.x) / frame;
+ vertices[0x7u] = static_cast<::GLfloat>(objects_root.objects->position.y) / frame;
+
+ glClearColor(0x0p0f, 0x0p0f, 0x0p0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0x0, sizeof (vertices), vertices);
+
+ glUseProgram(graphics_data.shader_program);
+ glBindVertexArray(vao);
+ glDrawArrays(GL_TRIANGLES, 0x0, 0x3* 0x1);
+
+ ::glfwSwapBuffers(graphics_data.window);
+ }
+
+ ::bow::delete_objects(objects_root);
+ ::bow::delete_objects(system_root);
+
+ ::glfwSetScrollCallback(graphics_data.window, nullptr);
+
+ glDeleteVertexArrays(0x1, &vao);
+ glDeleteBuffers(0x1, &vbo);
+}
diff --git a/bowshock/source/application/bow/poll_events.cxx b/bowshock/source/application/bow/poll_events.cxx
new file mode 100644
index 0000000..355c906
--- /dev/null
+++ b/bowshock/source/application/bow/poll_events.cxx
@@ -0,0 +1,20 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+#include <GLFW/glfw3.h>
+
+auto ::bow::Application::poll_events() noexcept -> bool {
+ ::glfwPollEvents();
+
+ if (::bow::GOT_INTERRUPT) [[unlikely]] {
+ ::fmt::print(stderr, "got interrupt\n");
+ ::glfwSetWindowShouldClose(graphics_data.window, GLFW_TRUE);
+ }
+
+ if (::glfwWindowShouldClose(graphics_data.window)) [[unlikely]] { return true; }
+
+ return false;
+}
diff --git a/bowshock/source/application/bow/print_credits.cxx b/bowshock/source/application/bow/print_credits.cxx
new file mode 100644
index 0000000..4acbc90
--- /dev/null
+++ b/bowshock/source/application/bow/print_credits.cxx
@@ -0,0 +1,43 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <filesystem>
+#include <fmt/core.h>
+#include <stdexcept>
+
+auto ::bow::Application::print_credits() noexcept -> void {
+ ::std::string path = ::bow::DATA_DIRECTORY + "/CREDITS.txt";
+
+ ::std::size_t const file_size = ::std::filesystem::file_size(path);
+
+ ::std::FILE* file = ::std::fopen(path.c_str(), "r");
+
+ if (file == nullptr) [[unlikely]] {
+ ::fmt::print(stderr, "unable to open credits file\n");
+
+ ::std::exit(EXIT_FAILURE);
+ }
+
+ ::std::string credits;
+
+ try { credits.reserve(file_size); }
+ catch (...) {
+ ::fmt::print(stderr, "unable to allocate memory for credits\n");
+
+ ::std::exit(EXIT_FAILURE);
+ }
+
+ ::std::fread(credits.data(), 0x1u, file_size, file);
+ ::std::fclose(file);
+
+ credits.append("\n");
+
+ ::std::fputs(credits.c_str(), file);
+
+ credits.~basic_string();
+
+ ::std::exit(EXIT_SUCCESS);
+}
diff --git a/bowshock/source/application/bow/print_help.cxx b/bowshock/source/application/bow/print_help.cxx
new file mode 100644
index 0000000..f08bc45
--- /dev/null
+++ b/bowshock/source/application/bow/print_help.cxx
@@ -0,0 +1,25 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdlib>
+#include <fmt/core.h>
+
+auto ::bow::Application::print_help(::std::string const program_name) noexcept -> void {
+ ::fmt::print(
+ "\n"
+ "\x1B[1mBowshock\x1B[0m {:X}.{:X}.{:X}\n"
+ "Copyright 2022-2023 Gabriel Bj\u00F8rnager Jensen.\n"
+ "\n"
+ "Usage: \"{}\" <options> [savefile]\n"
+ "\n"
+ "Options:\n"
+ " --credits Print the game \x1B[1mcredits\x1B[0m\n"
+ " --print_help Print the\x1B[1mhelp\x1B[0m screen\n"
+ " --new Start a \x1B[1mnew\x1B[0m save file\n"
+ " --skip_intro \x1B[1mskip\x1B[0m the intro\n"
+ "\n",
+ ::bow::VERSION.major, ::bow::VERSION.minor, ::bow::VERSION.patch, program_name);
+
+ ::std::exit(EXIT_SUCCESS);
+}
diff --git a/bowshock/source/application/bow/print_quote.cxx b/bowshock/source/application/bow/print_quote.cxx
new file mode 100644
index 0000000..bfa83eb
--- /dev/null
+++ b/bowshock/source/application/bow/print_quote.cxx
@@ -0,0 +1,22 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <fmt/core.h>
+#include <string>
+
+auto ::bow::Application::print_quote() noexcept -> void {
+ ::std::srand(static_cast<unsigned int>(::std::time(nullptr)));
+
+ auto const identifier = static_cast<::std::uint8_t>(rand()) % ::bow::NUMBER_OF_QUOTE_IDENTIFIERS;
+
+ ::std::string quote;
+ ::std::string source;
+ get_quote(quote, source, identifier);
+
+ ::fmt::print(stderr, "{}\n\u2014{}\n\n", quote, source);
+}
diff --git a/bowshock/source/application/bow/run.cxx b/bowshock/source/application/bow/run.cxx
new file mode 100644
index 0000000..ac35de5
--- /dev/null
+++ b/bowshock/source/application/bow/run.cxx
@@ -0,0 +1,55 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+#include <bow/logic.hxx>
+#include <bow/runtime.hxx>
+#include <bow/save.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::Application::run(int const argc, char const* const* const argv) noexcept -> void {
+ ::bow::TerminalOptions options;
+ check_parameters(options, argc, argv);
+
+ print_quote();
+
+ ::fmt::print(
+ stderr,
+ "\x1B[0m\x1B[1mBowshock\x1B[0m {:X}.{:X}.{:X} \u2013 Copyright 2022\u20102023 \x1B[1mGabriel Bj\u00F8rnager Jensen\x1B[0m.\n\n",
+ ::bow::VERSION.major, ::bow::VERSION.minor, ::bow::VERSION.patch
+ );
+
+ ::fmt::print(stderr, "initialising\n");
+
+ if constexpr (::bow::DEBUG) { ::fmt::print(stderr, "debug mode is enabled\n"); }
+
+ ::fmt::print(stderr, "data directory at \"{}\"\n", ::bow::DATA_DIRECTORY);
+
+ ::fmt::print(stderr, "angle unit: {:.3f} radians\n", 0x1p0);
+ ::fmt::print(stderr, "distance unit: {:.3f} metres\n", ::bow::DISTANCE_MODIFIER);
+ ::fmt::print(stderr, "mass unit: {:.3f} kilograms\n", ::bow::MASS_MODIFIER);
+ ::fmt::print(stderr, "time unit: {:.3f} seconds\n", ::bow::TIME_MODIFIER);
+ ::fmt::print(stderr, "gravitational constant: {:.3f} (factor: {:.3f}))\n", ::bow::GRAVITY_VALUE, ::bow::GRAVITY_FACTOR);
+
+ this->initialise_random();
+ this->initialise_signal();
+ this->initialise_graphics();
+
+ if (options.skip_intro || !start_sequence()) [[likely]] {
+ if (!options.has_save_path) { options.save_path = ::bow::save_path(); }
+
+ if (options.new_save) { ::bow::new_save(player_data); }
+ else { ::bow::continue_save(player_data, options.save_path); }
+
+ this->loop();
+
+ ::bow::save(options.save_path, player_data);
+ }
+}
+
+int main(int const argc, char const* const* argv) {
+ ::bow::Application bow;
+
+ bow.run(argc, argv);
+}
diff --git a/bowshock/source/application/bow/start_sequence.cxx b/bowshock/source/application/bow/start_sequence.cxx
new file mode 100644
index 0000000..7998e86
--- /dev/null
+++ b/bowshock/source/application/bow/start_sequence.cxx
@@ -0,0 +1,48 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+#include <GLFW/glfw3.h>
+
+auto ::bow::Application::start_sequence() noexcept -> bool {
+ ::fmt::print(stderr, "starting start sequence\n");
+
+ auto exit = false;
+
+ constexpr ::GLfloat bowshock_red = 0x1.6D6D6D6Ep-1f;
+ constexpr ::GLfloat bowshock_green = 0x1.81818182p-4f;
+ constexpr ::GLfloat bowshock_blue = 0x1.9999999Ap-3f;
+
+ ::glfwSetTime(0x0p0);
+ for (double duration = 0x0p0;duration <= 0x3p0;duration = ::glfwGetTime()) {
+ if (poll_events()) [[unlikely]] break;
+
+ glClearColor(bowshock_red, bowshock_green, bowshock_blue, 0x1p0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ::glfwSwapBuffers(graphics_data.window);
+ }
+
+ double const fade_duration = 0x1p0;
+ ::glfwSetTime(0x0p0);
+ for (double factor = 0x0p0; factor <= fade_duration; factor = ::glfwGetTime()) {
+ if (poll_events()) [[unlikely]] { break; }
+
+ ::GLfloat const red = bowshock_red * (0x1p0f - static_cast<::GLfloat>(factor) / static_cast<::GLfloat>(fade_duration));
+ ::GLfloat const green = bowshock_green * (0x1p0f - static_cast<::GLfloat>(factor) / static_cast<::GLfloat>(fade_duration));
+ ::GLfloat const blue = bowshock_blue * (0x1p0f - static_cast<::GLfloat>(factor) / static_cast<::GLfloat>(fade_duration));
+
+ glClearColor(red, green, blue, 0x1p0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ::glfwSwapBuffers(graphics_data.window);
+ }
+
+ glClearColor(0x0p0f, 0x0p0f, 0x0p0f, 0x1p0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ::glfwSwapBuffers(graphics_data.window);
+
+ if (::glfwWindowShouldClose(graphics_data.window)) [[unlikely]] { exit = true; }
+
+ return exit;
+}
diff --git a/bowshock/source/base/home_directory.cxx b/bowshock/source/base/home_directory.cxx
new file mode 100644
index 0000000..2ba854b
--- /dev/null
+++ b/bowshock/source/base/home_directory.cxx
@@ -0,0 +1,16 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+
+#include <cstdlib>
+#include <string>
+
+using namespace ::std::literals::string_literals;
+
+auto ::bow::home_directory() noexcept -> ::std::string {
+ auto const pointer = ::std::getenv("HOME");
+
+ if (pointer == nullptr) [[unlikely]] { return ""s; }
+
+ return ::std::string(pointer);
+}
diff --git a/bowshock/source/base/object_type_string.cxx b/bowshock/source/base/object_type_string.cxx
new file mode 100644
index 0000000..92297a1
--- /dev/null
+++ b/bowshock/source/base/object_type_string.cxx
@@ -0,0 +1,24 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/base.hxx>
+
+#include <string>
+
+using namespace ::std::literals::string_literals;
+
+auto ::bow::object_type_string(::bow::ObjectType const type) noexcept -> ::std::string {
+ switch (type) {
+ case ::bow::ObjectType::Canister:
+ return "canister"s;
+ case ::bow::ObjectType::Player:
+ return "player"s;
+ case ::bow::ObjectType::Ship:
+ return "ship"s;
+ case ::bow::ObjectType::Star:
+ return "star"s;
+ case ::bow::ObjectType::Station:
+ return "station"s;
+ case ::bow::ObjectType::World:
+ return "world"s;
+ }
+}
diff --git a/bowshock/source/base/random.cxx b/bowshock/source/base/random.cxx
new file mode 100644
index 0000000..6f94b3b
--- /dev/null
+++ b/bowshock/source/base/random.cxx
@@ -0,0 +1,19 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/base.hxx>
+
+#include <cstdint>
+#include <cstdlib>
+#include <limits>
+
+static_assert(sizeof (int) == sizeof (::std::uint32_t));
+
+static_assert(RAND_MAX == ::std::numeric_limits<int>::max());
+
+auto ::bow::random() noexcept -> ::std::uint64_t {
+ ::std::uint32_t const rnd0 = (::std::uint32_t)::std::rand();
+ ::std::uint32_t const rnd1 = (::std::uint32_t)::std::rand();
+ ::std::uint64_t const random = static_cast<::std::uint64_t>(rnd0) | static_cast<::std::uint64_t>(rnd1) >> 0x4u;
+
+ return random;
+}
diff --git a/bowshock/source/base/save_path.cxx b/bowshock/source/base/save_path.cxx
new file mode 100644
index 0000000..fea3fc7
--- /dev/null
+++ b/bowshock/source/base/save_path.cxx
@@ -0,0 +1,26 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/application.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <fmt/core.h>
+#include <string>
+
+using namespace ::std::literals::string_literals;
+
+auto ::bow::save_path() noexcept -> ::std::string {
+ auto base_directory = ::bow::home_directory();
+
+ if (base_directory.empty()) [[unlikely]] {
+ ::fmt::print(stderr, "unable to get home directory, using current directory\n");
+
+ base_directory = "./"s;
+ }
+
+ auto const file_name = ".save_bowshock"s;
+
+ auto const path = base_directory + "/"s + file_name;
+
+ return path;
+}
diff --git a/bowshock/source/bs/objtypstr.cxx b/bowshock/source/bs/objtypstr.cxx
deleted file mode 100644
index db4ccf0..0000000
--- a/bowshock/source/bs/objtypstr.cxx
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-
-auto ::bow::objtypstr(::bow::objtyp const typ) noexcept -> char const * {
- char const * str;
-
- switch (typ) {
- case ::bow::objtyp::can:
- str = "canister";
- break;
- case ::bow::objtyp::ply:
- str = "player";
- break;
- case ::bow::objtyp::shp:
- str = "ship";
- break;
- case ::bow::objtyp::tar:
- str = "star";
- break;
- case ::bow::objtyp::stn:
- str = "station";
- break;
- case ::bow::objtyp::wrl:
- str = "world";
- break;
- }
-
- return str;
-}
diff --git a/bowshock/source/bs/rnd.cxx b/bowshock/source/bs/rnd.cxx
deleted file mode 100644
index 98f9523..0000000
--- a/bowshock/source/bs/rnd.cxx
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/bas.hxx>
-
-#include <cstdlib>
-
-static_assert(sizeof (int) == sizeof (::zp::i02));
-
-static_assert(RAND_MAX == ::zp::maxval<int>::val);
-
-auto ::bow::rnd() noexcept -> ::zp::i04 {
- ::zp::i02 const rnd0 = (::zp::i02)::std::rand();
- ::zp::i02 const rnd1 = (::zp::i02)::std::rand();
- ::zp::i04 const rnd = static_cast<::zp::i04>(rnd0) | static_cast<::zp::i04>(rnd1) >> 0x4u;
-
- return rnd;
-}
diff --git a/bowshock/source/ini/bow/chkpar.cxx b/bowshock/source/ini/bow/chkpar.cxx
deleted file mode 100644
index cf68d45..0000000
--- a/bowshock/source/ini/bow/chkpar.cxx
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <zp/mem>
-#include <zp/str>
-
-auto ::bow::bow::chkpar(::bow::trmopt & opt,int const argc,char const * const * argv) noexcept -> void {
- char const * const prognm = *argv;
-
- opt = ::bow::trmopt {
- .hassavpth = false,
- .newsav = false,
- .skp = false,
- };
-
- if (argc >= 0x2) [[unlikely]] {
- char const * const * const stop = (argv++)+(::zp::siz)argc;
-
- for (;argv != stop;++argv) {
- char const * par = *argv;
-
- if (par[0x0u] == '-' && par[0x1u] == '-') {
- par += 0x2u;
-
- if (::zp::strequ(par,"credits")) {pricrd();}
- else if (::zp::strequ(par,"help")) {hlp(prognm);}
- else if (::zp::strequ(par,"new")) {opt.newsav = true;}
- else if (::zp::strequ(par,"skip")) {opt.skp = true;}
- else {bow_logerr("invalid pareter \"%s\"",par);}
-
- continue;
- }
-
- // Else: Interpret it as a save path.
- opt.savpth = par;
- opt.hassavpth = true;
- }
- }
-}
diff --git a/bowshock/source/ini/bow/cmpshdprg.cxx b/bowshock/source/ini/bow/cmpshdprg.cxx
deleted file mode 100644
index 40f5f3a..0000000
--- a/bowshock/source/ini/bow/cmpshdprg.cxx
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cstdlib>
-#include <ly/io>
-#include <ly/fs>
-#include <glad/glad.h>
-#include <stdexcept>
-#include <zp/mem>
-#include <zp/str>
-
-namespace bow {
- static auto cmpshd(::GLuint & shd,char const * nam,::GLenum typ) -> void;
-}
-
-static auto ::bow::cmpshd(::GLuint & shd,char const * const nam,::GLenum const typ) -> void {
- /*[[maybe_unused]]*/ char const * typstr;
-
- char const * typExt;
- ::zp::siz typExtLen;
-
- switch (typ) {
- default:
- bow_logerr("bad shader type %X",static_cast<unsigned int>(typ));
- ::bow::abr();
- case GL_FRAGMENT_SHADER:
- bow_setstrlen(typExt,typExtLen,"frag");
- typstr = "fragment";
- break;
- case GL_VERTEX_SHADER:
- bow_setstrlen(typExt,typExtLen,"vert");
- typstr = "vertex";
- break;
- }
-
- char const * dir;
- ::zp::siz dirLen;
- bow_setstrlen(dir,dirLen,bow_datdir "/shaders");
-
- ::zp::siz const nmLen = ::zp::strlen(nam);
- ::zp::siz const pthlen = dirLen + 0x1u + nmLen + 0x1u + typExtLen + 0x1u + sizeof (::bow::shdfilext);
-
- char * pth = new char[pthlen + 0x1u];
-
- pth = ::zp::cpy(pth,dir,dirLen).dst;
- *pth++ = '/';
- pth = ::zp::cpy(pth,nam,nmLen).dst;
- *pth++ = '.';
- pth = ::zp::cpy(pth,typExt,typExtLen).dst;
- *pth++ = '.';
- pth = ::zp::cpy(pth,::bow::shdfilext,sizeof (::bow::shdfilext)).dst;
- *pth = '\x00';
- pth -= pthlen;
-
- bow_logdbg("compiling %s shader at \"%s\"",typstr,pth);
-
- ::ly::fil fil;
- ::ly::err err = fil.opn(pth,::ly::mod::red,::ly::kep);
-
- if (err != ::ly::err::ok) [[unlikely]] {throw ::std::runtime_error {"unable to open shader source"};}
-
- ::zp::siz const filsiz = [&pth]() {
- ::ly::pthinf pthinf;
- ::ly::sttpth(pthinf,pth);
-
- return pthinf.siz;
- }();
-
- delete[] pth;
-
- static_assert(sizeof (GLchar) == sizeof (char));
- GLchar * const src = new GLchar[filsiz + 0x1u];
-
- err = fil.red(src,filsiz);
- if (err != ::ly::err::ok) {throw ::std::runtime_error {"unable to read shader source"};}
- fil.cls();
-
- src[filsiz] = '\x00';
-
- shd = glCreateShader(typ);
- glShaderSource(shd,0x1,(GLchar const * const *)&src,nullptr);
-
- delete[] src;
-
- glCompileShader(shd);
-
- GLint compStat;
- glGetShaderiv(shd,GL_COMPILE_STATUS,&compStat);
- if (compStat == GL_FALSE) [[unlikely]] {throw ::std::runtime_error {"unable to compile shader"};}
-}
-
-auto ::bow::bow::compshdprg(::GLuint & shdprg,char const * const nam) noexcept -> void {
- bow_log("compiling shader program \"%s\"",nam);
-
- ::GLuint vtxshd;
- ::GLuint frgshd;
-
- using ::bow::cmpshd;
-
- try {
- cmpshd(vtxshd,nam,GL_VERTEX_SHADER);
- cmpshd(frgshd,nam,GL_FRAGMENT_SHADER);
- }
- catch (::std::runtime_error const & e) {
- bow_logerr("%s",e.what());
- ::bow::abr();
- }
- catch (::std::bad_alloc const & e) {
- bow_logerr("unable to allocate memory for shader data");
- ::bow::abr();
- }
-
- shdprg = glCreateProgram();
- glAttachShader(shdprg,vtxshd);
- glAttachShader(shdprg,frgshd);
- glLinkProgram(shdprg);
-
- glDeleteShader(vtxshd);
- glDeleteShader(frgshd);
-}
diff --git a/bowshock/source/ini/bow/exi.cxx b/bowshock/source/ini/bow/exi.cxx
deleted file mode 100644
index a597d70..0000000
--- a/bowshock/source/ini/bow/exi.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cstdlib>
-#include <GLFW/glfw3.h>
-
-auto ::bow::bow::exi(::bow::cnd const cnd) noexcept -> void {
- bow_log("quitting");
-
- glDeleteProgram(gfxdat.shdprg);
-
- ::glfwDestroyWindow(gfxdat.win);
- ::glfwTerminate();
-
- int cod;
- switch (cnd) {
- case ::bow::cnd::err:
- cod = EXIT_FAILURE;
- break;
- case ::bow::cnd::oky:
- cod = EXIT_SUCCESS;
- break;
- }
-
- bow_log("goodbye");
- bow_log("exiting with code %i",cod);
- ::std::exit(cod);
-}
diff --git a/bowshock/source/ini/bow/getquo.cxx b/bowshock/source/ini/bow/getquo.cxx
deleted file mode 100644
index f1f80cb..0000000
--- a/bowshock/source/ini/bow/getquo.cxx
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cinttypes>
-
-auto ::bow::bow::getquo(char const * * const quo,char const * * src,::zp::i8 const id) noexcept -> void {
- switch (id) {
- default:
- bow_logerr("invalid quote identifier (%" PRIX8 ")",id);
- [[fallthrough]];
- case 0x0u:
- *quo = "You gotta be heaven to see heaven.";
- *src = "Jim Carrey";
- break;
- case 0x1u:
- *quo = "Though it's the end of the world, don't blame yourself, now.";
- *src = "Porter Robinson";
- break;
- case 0x2u:
- *quo = "The future will be better tomorrow.";
- *src = "Dan Quayle";
- break;
- case 0x3u:
- *quo = "Sir, an equation has no meaning for me unless it expresses a thought of god.";
- *src = "Srinivasa Ramanujan Aiyangar";
- break;
- case 0x4u:
- *quo = "Amīcus Platō amīcus Aristotelēs magis amīca vēritās.";
- *src = "Isaac Newton";
- break;
- case 0x5u:
- *quo = "I have studied these things \u2013 you have not.";
- *src = "Isaac Newton";
- break;
- case 0x6u:
- *quo = "La construction d'une machine propre à exprimer tous les sons de nos paroles, avec toutes les articulations, serait sans doute une décourverte bien importante.\n... La chose ne me paraît pas impossible.";
- *src = "Leonhard Euler";
- break;
- case 0x7u:
- *quo = "In mathematics, you don't understand things, you just get used to them.";
- *src = "John von Neumann";
- break;
- case 0x8u:
- *quo = "Being a language, mathematics may be used not only to inform, but also \u2013 among other things \u2013 to seduce.";
- *src = "Benoît B. Mandelbrot";
- break;
- case 0x9u:
- *quo = "The real question is not whether machines think, but whether men do.";
- *src = "Burrhus Frederic Skinner";
- break;
- case 0xAu:
- *quo = "Those who are not shocked when they first come across quantum theory cannot possibly have understood it.";
- *src = "Niels Henrik David Bohr";
- break;
- case 0xBu:
- *quo = "Every sentence I utter must be understood not as an affirmation, but as a question.";
- *src = "Niels Henrik David Bohr";
- break;
- case 0xCu:
- *quo = "We will now discuss in a little more detail the struggle for existence.";
- *src = "Charles Robert Darwin";
- break;
- case 0xDu:
- *quo = "Nam et ipsa scientia potestas est.";
- *src = "Francis Bacon";
- break;
- case 0xEu:
- *quo = "We don't know a millionth of one percent about anything.";
- *src = "Thomas Alva Edison";
- break;
- case 0xFu:
- *quo = "My goal is simple. It is a complete understanding of the universe, why it is as it is, and why it exists at all.";
- *src = "Stephen William Hawking";
- break;
- case 0x10u:
- *quo = "Equipped with his five senses, man explores the universe around him and calls the adventure Science.";
- *src = "Edwin Powell Hubble";
- break;
- case 0x11u:
- *quo = "I can say this: I believe that the human mind, or even the mind of a cat, is more interesting in its complexity than an entire galaxy if it is devoid of life.";
- *src = "Martin Gardner";
- break;
- case 0x12u:
- *quo = "I'm always right. This time I'm just more right than usual.";
- *src = "Linus Benedict Torvalds";
- break;
- case 0x13u:
- *quo = "I'm an instant tar. Just add water and stir.";
- *src = "David Robert Jones";
- break;
- case 0x14u:
- *quo = "Don't waste the Earth \u2013 it is our jewel!";
- *src = "Buzz Eugene Aldrin";
- break;
- case 0x15u:
- *quo = "I think we're going to the moon because it's in the nature of the human being to face challenges.";
- *src = "Neil Alden Armstrong";
- break;
- case 0x16u:
- *quo = "A hacker is someone who enjoys playful cleverness \u2013 not necessarily with computers.";
- *src = "Richard Matthew Stallman";
- break;
- case 0x17u:
- *quo = "So Einstein was wrong when he said \"God noes not play dice.\". Consideration of black holes suggests, not only that God does play dice, but that he sometimes confuses us by throwing them where they can't be seen.";
- *src = "Stephen William Hawking";
- break;
- case 0x18u:
- *quo = "I'm a blacktar.";
- *src = "David Robert Jones";
- break;
- case 0x19u:
- *quo = "Sooner or later, we must expand life beyond our little blue mud ball \u2013 or go extinct.";
- *src = "Elon Reeve Musk";
- break;
- case 0x1Au:
- *quo = "I would like to die on Mars \u2013 just not on impact.";
- *src = "Elon Reeve Musk";
- break;
- case 0x1Bu:
- *quo = "The web does not just connect computers; it connects people.";
- *src = "Timothy John Berners-Lee";
- break;
- case 0x1Cu:
- *quo = "Can digital computers think?";
- *src = "Alan Mathison Turing";
- break;
- case 0x1Du:
- *quo = "That's one small step for a man, one giant leap for mankind.";
- *src = "Neil Alden Armstrong";
- break;
- case 0x1Eu:
- *quo = "If you think it's simple, then you have misunderstood the problem.";
- *src = "Bjarne Stroustrup";
- break;
- case 0x1Fu:
- *quo = "Controlling complexity is the essence of computer programming.";
- *src = "Brian Wilson Kerningham";
- break;
- case 0x20u:
- *quo = "I have always wished for my computer to be as easy to use as my telephone.\nMy wish has come true because I can no longer figure out how to use my telephone.";
- *src = "Bjarne Stroustrup";
- break;
- case 0x21u:
- *quo = "There is no mathematical sibstitute for philosophy.";
- *src = "Saul Aaron Kripke";
- break;
- case 0x22u:
- *quo = "Biology is engineering.";
- *src = "Daniel Clement Dennett III";
- break;
- case 0x23u:
- *quo = "The universe is under no obligation to make sense to you.";
- *src = "Neil deGrasse Tyson";
- break;
- }
-}
diff --git a/bowshock/source/ini/bow/getsavpth.cxx b/bowshock/source/ini/bow/getsavpth.cxx
deleted file mode 100644
index a3c0c22..0000000
--- a/bowshock/source/ini/bow/getsavpth.cxx
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cstdlib>
-#include <ly/fs>
-#include <zp/mem>
-#include <zp/str>
-
-auto ::bow::bow::getsavpth() noexcept -> char const * {
- char const * homdir = ::ly::homdir();
- char const * filnam;
- ::zp::siz homdirlen;
- ::zp::siz filnamlen;
-
- if (homdir == nullptr) [[unlikely]] {
- bow_log("unable to get home directory, using current directory");
- bow_setstrlen(homdir,homdirlen,"./");
- }
- else homdirlen = ::zp::strlen(homdir);
-
- bow_setstrlen(filnam,filnamlen,".save.bowshock");
-
- ::zp::siz pthlen = homdirlen+filnamlen+0x1u;
-
- char * pth = new char[pthlen + 0x1u];
-
- pth = ::zp::memcpy(pth,homdir,homdirlen).dst;
- *pth++ = '/';
- pth = ::zp::memcpy(pth,filnam,filnamlen).dst;
- *pth = '\x00';
-
- pth -= pthlen;
-
- return pth;
-}
diff --git a/bowshock/source/ini/bow/hlp.cxx b/bowshock/source/ini/bow/hlp.cxx
deleted file mode 100644
index 1e5f58c..0000000
--- a/bowshock/source/ini/bow/hlp.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cinttypes>
-#include <cstdlib>
-
-auto ::bow::bow::hlp(char const * const prognm) noexcept -> void {
- bow_lograw(
- "\n"
- "\x1B[1mBowshock\x1B[0m %" PRIX64 ".%" PRIX64 ".%" PRIX64 "\n"
- "Copyright 2022-2023 Gabriel Jensen.\n"
- "\n"
- "Usage: \"%s\" <options> [savefile]\n"
- "\n"
- "Options:\n"
- " --credits Print the game \x1B[1mcredits\x1B[0m\n"
- " --help Print \x1B[1mhelp\x1B[0m screen\n"
- " --new srt a \x1B[1mnew\x1B[0m save file\n"
- " --skp \x1B[1mskp\x1B[0m the intro\n"
- "\n",
- ::bow::vermaj,::bow::vermin,::bow::verpat,prognm);
-
- ::std::exit(EXIT_SUCCESS);
-}
diff --git a/bowshock/source/ini/bow/ini.cxx b/bowshock/source/ini/bow/ini.cxx
deleted file mode 100644
index 21db1ef..0000000
--- a/bowshock/source/ini/bow/ini.cxx
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-#include <bow/lgc.hxx>
-#include <bow/run.hxx>
-#include <bow/sav.hxx>
-
-#include <cinttypes>
-
-auto ::bow::bow::ini(int const argc,char const * const * const argv) noexcept -> void {
- ::bow::trmopt opt;
- chkpar(opt,argc,argv);
-
- priquo();
-
- bow_lograw("\x1B[0m\x1B[1mBowshock\x1B[0m %" PRIX64 ".%" PRIX64 ".%" PRIX64 " \u2013 Copyright 2022\u20102023 \x1B[1mGabriel Jensen\x1B[0m.\n\n",::bow::vermaj,::bow::vermin,::bow::verpat);
-
- bow_log("initialising");
-
- bow_logdbg("debug mode is enabled");
- bow_logdbg("data directory at \"" bow_datdir "\"");
- bow_logdbg("angle unit: %.3f radians",0x1p0);
- bow_logdbg("distance unit: %.3f metres",::bow::dstmod);
- bow_logdbg("mass unit: %.3f kilograms",::bow::masmod);
- bow_logdbg("time unit: %.3f seconds",::bow::timmod);
- bow_logdbg("gravitational constant: %f (factor: %f))",::bow::grvval,::bow::grvfac);
-
- inirnd();
- inisig();
- inigfx();
-
- if (opt.skp || !srtseq()) [[likely]] {
- if (!opt.hassavpth) {opt.savpth = getsavpth();}
-
- if (opt.newsav) {::bow::newsav(plydat);}
- else {::bow::cnt(plydat,opt.savpth);}
-
- lop();
-
- ::bow::sav(opt.savpth,plydat);
-
- if (!opt.hassavpth) {delete[] const_cast<char *>(opt.savpth);}
- }
-
- exi(::bow::cnd::oky);
-}
-
-int main(int const argc,char const * const * argv) {
- ::bow::bow bow;
- bow.ini(argc,argv);
-}
diff --git a/bowshock/source/ini/bow/inigfx.cxx b/bowshock/source/ini/bow/inigfx.cxx
deleted file mode 100644
index 8a02971..0000000
--- a/bowshock/source/ini/bow/inigfx.cxx
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <GLFW/glfw3.h>
-#include <glad/glad.h>
-
-auto ::bow::bow::inigfx() noexcept -> void {
- bow_log("initialising graphics");
-
- bow_logdbg("initialising glfw");
- if (!::glfwInit()) [[unlikely]] {
- bow_logerr("unable to initialise glfw");
- ::bow::abr();
- }
-
- bow_logdbg("initialising window");
- ::glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,0x4);
- ::glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,0x1);
- ::glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
- ::glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- ::glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
- ::glfwWindowHint(GLFW_SAMPLES, 0x8);
- gfxdat.win = ::glfwCreateWindow(0x400,0x240,"Bowshock",::glfwGetPrimaryMonitor(),nullptr);
- if (gfxdat.win == nullptr) [[unlikely]] {
- bow_logerr("unable to open window");
- ::bow::abr();
- }
-
- bow_logdbg("initialising context");
- ::glfwMakeContextCurrent(gfxdat.win);
- ::gladLoadGL();
- glEnable(GL_MULTISAMPLE);
- ::GLFWvidmode const * vidmd = ::glfwGetVideoMode(::glfwGetPrimaryMonitor());
- glViewport(0x0,0x0,vidmd->width,vidmd->height);
- glClearColor(0x0p0,0x0p0,0x0p0,0x1p0);
- glClear(GL_COLOR_BUFFER_BIT);
- ::glfwSwapBuffers(gfxdat.win);
- ::glfwSwapInterval(0x1);
-
- compshdprg(gfxdat.shdprg,"main");
-}
diff --git a/bowshock/source/ini/bow/inirnd.cxx b/bowshock/source/ini/bow/inirnd.cxx
deleted file mode 100644
index 1e073a8..0000000
--- a/bowshock/source/ini/bow/inirnd.cxx
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cstdlib>
-#include <ctime>
-
-auto ::bow::bow::inirnd() noexcept -> void {
- bow_log("initialising random number generator");
-
- ::std::srand(static_cast<unsigned int>(::std::time(nullptr)));
-}
diff --git a/bowshock/source/ini/bow/inisig.cxx b/bowshock/source/ini/bow/inisig.cxx
deleted file mode 100644
index 1c01db0..0000000
--- a/bowshock/source/ini/bow/inisig.cxx
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <csignal>
-
-::std::sig_atomic_t volatile ::bow::gotint;
-
-namespace bow {
- static auto inthnd(int const sig) -> void;
-}
-
-static auto ::bow::inthnd(int const sig) -> void {
- ::std::signal(sig,::bow::inthnd); // Ignore the return value: We can't do anything (meaningful) about it anyways.
- ::bow::gotint = 0x1;
-};
-
-auto ::bow::bow::inisig() noexcept -> void {
- bow_log("initialising signal handlers");
-
- ::bow::gotint = 0x0;
-
- auto const sethnd = []<typename hndtyp>(int const sig,hndtyp const & hnd) -> void {
- if (::std::signal(sig,static_cast<auto (*)(int) -> void>(hnd)) == SIG_ERR) [[unlikely]] {
- bow_log("unable to set signal handler for %i",sig);
- ::bow::abr();
- }
- };
-
- sethnd(SIGINT, ::bow::inthnd);
- sethnd(SIGTERM,::bow::inthnd);
-}
diff --git a/bowshock/source/ini/bow/lop.cxx b/bowshock/source/ini/bow/lop.cxx
deleted file mode 100644
index 3aec774..0000000
--- a/bowshock/source/ini/bow/lop.cxx
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-#include <bow/lgc.hxx>
-
-#include <GLFW/glfw3.h>
-#include <cmath>
-#include <glad/glad.h>
-#include <stdexcept>
-
-auto ::bow::bow::lop() noexcept -> void {
- bow_log("entering main loop");
-
- ::GLfloat vtx[] = {
- -0x1.0000p0f,+0x1.0000p0f,0x0p0f,
- +0x1.0000p0f,+0x1.0000p0f,0x0p0f,
- +0x0.0000p0f,+0x0.0000p0f,0x0p0f,
- };
-
- ::GLuint vao;
- ::GLuint vbo;
- glGenVertexArrays(0x1,&vao);
- glGenBuffers(0x1,&vbo);
-
- glBindVertexArray(vao);
-
- glBindBuffer(GL_ARRAY_BUFFER,vbo);
- glBufferData(GL_ARRAY_BUFFER,sizeof (vtx),vtx,GL_STREAM_DRAW);
-
- glVertexAttribPointer(0x0,0x3,GL_FLOAT,GL_FALSE,0x3 * sizeof (::GLfloat),nullptr);
- glEnableVertexAttribArray(0x0);
-
- ::bow::objroot sysRoot; // For stellar bodies.
- ::bow::objroot objroot = { // For miscellaneous objects (canisters, shps...).
- .objs = nullptr,
- };
-
- try {::bow::gensys(sysRoot,plydat.sysidt,plydat.tim);}
- catch (::std::bad_alloc const & e) {
- bow_logerr("unable to allocate memory for object");
- ::bow::abr();
- }
-
- ::bow::obj objTmp = {
- .typ = ::bow::objtyp::can,
- .pos = {
- .x = 0x0p0,
- .y = -0x2p0,
- .z = 0x0p0,
- },
- .rot = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .posVel = {
- .x = -0x1p-12,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rotVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .mas = 0x1p0,
- };
- ::bow::addobj(objroot,objTmp);
-
- auto const scrlHand = [](::GLFWwindow * const win,[[maybe_unused]] ::zp::f04 const xoff,::zp::f04 const yoff) -> void {
- ::bow::plydat * dat = static_cast<::bow::plydat *>(::glfwGetWindowUserPointer(win));
- dat->zom *= ::std::pow(0x1.04p0f,0x0p0f-static_cast<float>(yoff));
- };
-
- ::glfwSetWindowUserPointer(gfxdat.win,&plydat);
- ::glfwSetScrollCallback(gfxdat.win,scrlHand);
-
- for (;;++plydat.tim) {
- if (polevt()) [[unlikely]] break;
-
- ::bow::grv(sysRoot);
- ::bow::grv(objroot,sysRoot);
-
- ::bow::mov(sysRoot);
- ::bow::mov(objroot);
-
- ::GLfloat const frm = 0x1p0f*plydat.zom;
-
- vtx[0x0u] = (::GLfloat)sysRoot.objs->nxt->pos.x/frm;
- vtx[0x1u] = (::GLfloat)sysRoot.objs->nxt->pos.y/frm;
- vtx[0x3u] = (::GLfloat)sysRoot.objs->pos.x/frm;
- vtx[0x4u] = (::GLfloat)sysRoot.objs->pos.y/frm;
- vtx[0x6u] = (::GLfloat)objroot.objs->pos.x/frm;
- vtx[0x7u] = (::GLfloat)objroot.objs->pos.y/frm;
-
- glClearColor(0x0p0f,0x0p0f,0x0p0f,1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glBindBuffer(GL_ARRAY_BUFFER,vbo);
- glBufferSubData(GL_ARRAY_BUFFER,0x0,sizeof (vtx),vtx);
-
- glUseProgram(gfxdat.shdprg);
- glBindVertexArray(vao);
- glDrawArrays(GL_TRIANGLES,0x0,0x3 * 0x1);
-
- ::glfwSwapBuffers(gfxdat.win);
- }
-
- ::glfwSetScrollCallback(gfxdat.win,nullptr);
-
- glDeleteVertexArrays(0x1,&vao);
- glDeleteBuffers(0x1,&vbo);
-}
diff --git a/bowshock/source/ini/bow/polevt.cxx b/bowshock/source/ini/bow/polevt.cxx
deleted file mode 100644
index c5aa3c7..0000000
--- a/bowshock/source/ini/bow/polevt.cxx
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <GLFW/glfw3.h>
-
-auto ::bow::bow::polevt() noexcept -> bool {
- ::glfwPollEvents();
-
- if (::bow::gotint) [[unlikely]] {
- bow_log("got interrupt");
- ::glfwSetWindowShouldClose(gfxdat.win,GLFW_TRUE);
-
- }
- if (::glfwWindowShouldClose(gfxdat.win)) [[unlikely]] {return true;}
-
- return false;
-}
diff --git a/bowshock/source/ini/bow/pricrd.cxx b/bowshock/source/ini/bow/pricrd.cxx
deleted file mode 100644
index cc63cdc..0000000
--- a/bowshock/source/ini/bow/pricrd.cxx
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <ly/io>
-#include <ly/fs>
-#include <cstdlib>
-#include <stdexcept>
-
-auto ::bow::bow::pricrd() noexcept -> void {
- char const * const pth = bow_datdir "/CREDITS.txt";
-
- ::zp::siz const filsiz = [&pth]() {
- ::ly::pthinf pthinf;
- ::ly::sttpth(pthinf,pth);
-
- return pthinf.siz;
- }();
-
- ::ly::fil fil;
- ::ly::err err = fil.opn(pth,::ly::mod::red,::ly::kep);
-
- if (err != ::ly::err::ok) [[unlikely]] {
- bow_logerr("unable to open credits file");
-
- ::std::exit(EXIT_FAILURE);
- }
-
- char * pricrd;
-
- try {pricrd = new char[filsiz + 0x3u];}
- catch (::std::bad_alloc const & e) {
- bow_logerr("unable to allocate memory");
-
- ::std::exit(EXIT_FAILURE);
- }
-
- char * const credsrt = pricrd;
-
- *pricrd++ = '\n';
-
- fil.red(pricrd,filsiz);
- fil.cls();
- pricrd += filsiz;
-
- *pricrd++ = '\n';
- *pricrd++ = '\x00';
-
- pricrd = credsrt;
-
- ::ly::dflout.wrt(pricrd,filsiz + 0x3u);
-
- if (err != ::ly::err::ok) {
- bow_logerr("unable to write to defout");
-
- ::std::exit(EXIT_FAILURE);
- }
-
- delete[] pricrd;
-
- ::std::exit(EXIT_SUCCESS);
-}
diff --git a/bowshock/source/ini/bow/priquo.cxx b/bowshock/source/ini/bow/priquo.cxx
deleted file mode 100644
index de964af..0000000
--- a/bowshock/source/ini/bow/priquo.cxx
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <cinttypes>
-#include <ctime>
-#include <cstdlib>
-
-auto ::bow::bow::priquo() noexcept -> void {
- ::std::srand(static_cast<unsigned int>(::std::time(nullptr)));
- ::zp::i8 const quotId = (::zp::i8)rand() % 0x24u;
-
- char const * quo;
- char const * src;
- getquo(&quo,&src,quotId);
-
- if (src == nullptr) {bow_lograw("%s\n",quo);}
- else {bow_lograw("\n%s\n\u2014 %s\n\n",quo,src);}
-}
diff --git a/bowshock/source/ini/bow/srtseq.cxx b/bowshock/source/ini/bow/srtseq.cxx
deleted file mode 100644
index e0ed099..0000000
--- a/bowshock/source/ini/bow/srtseq.cxx
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/ini.hxx>
-
-#include <GLFW/glfw3.h>
-
-auto ::bow::bow::srtseq() noexcept -> bool {
- bow_log("starting start sequence");
-
- bool exi = false;
-
- constexpr ::GLfloat bowr = 0x1.6D6D6D6Ep-1;
- constexpr ::GLfloat bowg = 0x1.81818182p-4;
- constexpr ::GLfloat bowb = 0x1.9999999Ap-3;
-
- ::glfwSetTime(0x0p0);
- for (::zp::f04 dur = 0x0p0;dur <= 0x3p0;dur = ::glfwGetTime()) {
- if (polevt()) [[unlikely]] break;
-
- glClearColor(bowr,bowg,bowb,0x1p0);
- glClear(GL_COLOR_BUFFER_BIT);
- ::glfwSwapBuffers(gfxdat.win);
- }
-
- ::zp::f04 const fadedur = 0x1p0;
- ::glfwSetTime(0x0p0);
- for (::zp::f04 fac = 0x0p0;fac <= fadedur;fac = ::glfwGetTime()) {
- if (polevt()) [[unlikely]] {break;}
-
- ::GLfloat const r = bowr*(0x1p0f-fac/fadedur);
- ::GLfloat const g = bowg*(0x1p0f-fac/fadedur);
- ::GLfloat const b = bowb*(0x1p0f-fac/fadedur);
-
- glClearColor(r,g,b,0x1p0);
- glClear(GL_COLOR_BUFFER_BIT);
- ::glfwSwapBuffers(gfxdat.win);
- }
-
- glClearColor(0x0p0,0x0p0,0x0p0,0x1p0);
- glClear(GL_COLOR_BUFFER_BIT);
- ::glfwSwapBuffers(gfxdat.win);
-
- if (::glfwWindowShouldClose(gfxdat.win)) [[unlikely]] {exi = true;}
-
- return exi;
-}
diff --git a/bowshock/source/lgc/grv.cxx b/bowshock/source/lgc/grv.cxx
deleted file mode 100644
index c12e434..0000000
--- a/bowshock/source/lgc/grv.cxx
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-
-#include <cmath>
-
-namespace bow {
- static auto grav1(::bow::obj & obj,::bow::obj const & par) noexcept -> void {
- ::zp::f04 const distx = par.pos.x-obj.pos.x;
- ::zp::f04 const disty = par.pos.y-obj.pos.y;
- ::zp::f04 const distz = par.pos.z-obj.pos.z;
- ::zp::f04 const dist = ::std::sqrt(distx*distx+disty*disty+distz*distz);
-
- ::zp::f04 const angy = ::std::atan2(disty,distx);
- ::zp::f04 const angz = ::std::atan2(distz,distx);
-
- ::zp::f04 acc = par.mas/(dist*dist)*::bow::grvval;
-
- ::zp::f04 const vx = ::std::cos(angy)*acc;
- ::zp::f04 const vy = ::std::sin(angy)*acc;
- ::zp::f04 const vz = ::std::sin(angz)*acc;
-
- obj.posVel.x += vx;
- obj.posVel.y += vy;
- obj.posVel.z += vz;
- }
-
- static void grav2(::bow::obj & obj0,::bow::obj & obj1) noexcept {
- ::zp::f04 const distx = obj1.pos.x-obj0.pos.x;
- ::zp::f04 const disty = obj1.pos.y-obj0.pos.y;
- ::zp::f04 const distz = obj1.pos.z-obj0.pos.z;
- ::zp::f04 const dist = ::std::sqrt(distx*distx+disty*disty+distz*distz);
-
- ::zp::f04 const angy = ::std::atan2(disty,distx);
- ::zp::f04 const angz = ::std::atan2(distz,distx);
-
- ::zp::f04 acc0 = ::bow::grvval/(dist*dist);
- ::zp::f04 const acc1 = acc0*obj0.mas; // This is negative.
- acc0 *= obj1.mas;
-
- ::zp::f04 vx0 = ::std::cos(angy);
- ::zp::f04 vy0 = ::std::sin(angy);
- ::zp::f04 vz0 = ::std::sin(angz);
- ::zp::f04 const vx1 = vx0*acc1;
- ::zp::f04 const vy1 = vy0*acc1;
- ::zp::f04 const vz1 = vz0*acc1;
- vx0 *= acc0;
- vy0 *= acc0;
- vz0 *= acc0;
-
- obj0.posVel.x += vx0;
- obj0.posVel.y += vy0;
- obj0.posVel.z += vz0;
-
- obj1.posVel.x -= vx1;
- obj1.posVel.y -= vy1;
- obj1.posVel.z -= vz1;
- }
-}
-
-auto ::bow::grv(::bow::objroot & sys) noexcept -> void {
- for (::bow::obj * obj0 = sys.objs;obj0 != nullptr;obj0 = obj0->nxt) {
- for (::bow::obj * obj1 = obj0->nxt;obj1 != nullptr;obj1 = obj1->nxt) {
- ::bow::grav2(*obj0,*obj1);
- }
- }
-}
-
-auto ::bow::grv(::bow::objroot & objs,::bow::objroot const & sys) noexcept -> void {
- for (::bow::obj * obj = objs.objs;obj != nullptr;obj = obj->nxt) {
- for (::bow::obj * par = sys.objs;par != nullptr;par = par->nxt) {
- ::bow::grav1(*obj,*par);
- }
- }
-}
diff --git a/bowshock/source/lgc/mov.cxx b/bowshock/source/lgc/mov.cxx
deleted file mode 100644
index eee6759..0000000
--- a/bowshock/source/lgc/mov.cxx
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-
-auto ::bow::mov(::bow::objroot & root) noexcept -> void {
- auto const mov = [](::bow::obj & obj) {
- obj.pos.x += obj.posVel.x;
- obj.pos.y += obj.posVel.y;
- obj.pos.z += obj.posVel.z;
- obj.rot.x += obj.rotVel.x;
- obj.rot.y += obj.rotVel.y;
- obj.rot.z += obj.rotVel.z;
- };
-
- for (::bow::obj * obj = root.objs;obj != nullptr;obj = obj->nxt) {
- mov(*obj);
- }
-}
diff --git a/bowshock/source/lgc/shpmas.cxx b/bowshock/source/lgc/shpmas.cxx
deleted file mode 100644
index 1003eb4..0000000
--- a/bowshock/source/lgc/shpmas.cxx
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-
-auto ::bow::shpmas([[maybe_unused]] ::bow::shp const id) noexcept -> ::zp::f04 {
- ::zp::f04 mas = 0x100p0;
- mas /= ::bow::masmod;
-
- return mas;
-}
diff --git a/bowshock/source/lgc/sim.cxx b/bowshock/source/lgc/sim.cxx
deleted file mode 100644
index ea1ffd3..0000000
--- a/bowshock/source/lgc/sim.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-
-#include <bow/run.hxx>
-
-#include <cinttypes>
-
-auto ::bow::sim(::bow::objroot & sys,::zp::i04 const dur) noexcept -> void {
- bow_log("simulating for (%" PRIX64 ") time units",dur);
-
- for (::zp::i04 i = 0x0u;i <= dur;++i) {
- ::bow::grv(sys);
- ::bow::mov(sys);
- }
-}
diff --git a/bowshock/source/logic/gravitate.cxx b/bowshock/source/logic/gravitate.cxx
new file mode 100644
index 0000000..2e06001
--- /dev/null
+++ b/bowshock/source/logic/gravitate.cxx
@@ -0,0 +1,75 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+
+#include <cmath>
+
+namespace bow {
+ static auto gravitate_single(::bow::Object& object, ::bow::Object const& par) noexcept -> void {
+ auto const distance_x = par.position.x - object.position.x;
+ auto const distance_y = par.position.y - object.position.y;
+ auto const distance_z = par.position.z - object.position.z;
+ auto const distance = ::std::sqrt(distance_x * distance_x + distance_y * distance_y + distance_z * distance_z);
+
+ auto const angle_y = ::std::atan2(distance_y, distance_x);
+ auto const angle_z = ::std::atan2(distance_z, distance_x);
+
+ auto const acceleration = par.mass/(distance*distance)*::bow::GRAVITY_VALUE;
+
+ auto const velocity_x = ::std::cos(angle_y)*acceleration;
+ auto const velocity_y = ::std::sin(angle_y)*acceleration;
+ auto const velocity_z = ::std::sin(angle_z)*acceleration;
+
+ object.positional_velocity.x += velocity_x;
+ object.positional_velocity.y += velocity_y;
+ object.positional_velocity.z += velocity_z;
+ }
+
+ static void gravitate_pair(::bow::Object& obj0, ::bow::Object& obj1) noexcept {
+ auto const distance_x = obj1.position.x-obj0.position.x;
+ auto const distance_y = obj1.position.y-obj0.position.y;
+ auto const distance_z = obj1.position.z-obj0.position.z;
+ auto const distance = ::std::sqrt(distance_x*distance_x+distance_y*distance_y+distance_z*distance_z);
+
+ auto const angle_y = ::std::atan2(distance_y, distance_x);
+ auto const angle_z = ::std::atan2(distance_z, distance_x);
+
+ auto acceleration0 = ::bow::GRAVITY_VALUE/(distance*distance);
+ auto const acceleration1 = acceleration0*obj0.mass; // This is negative.
+ acceleration0 *= obj1.mass;
+
+ auto velocity_x0 = ::std::cos(angle_y);
+ auto velocity_y0 = ::std::sin(angle_y);
+ auto velocity_z0 = ::std::sin(angle_z);
+ auto const velocity_x1 = velocity_x0*acceleration1;
+ auto const velocity_y1 = velocity_y0*acceleration1;
+ auto const velocity_z1 = velocity_z0*acceleration1;
+ velocity_x0 *= acceleration0;
+ velocity_y0 *= acceleration0;
+ velocity_z0 *= acceleration0;
+
+ obj0.positional_velocity.x += velocity_x0;
+ obj0.positional_velocity.y += velocity_y0;
+ obj0.positional_velocity.z += velocity_z0;
+
+ obj1.positional_velocity.x -= velocity_x1;
+ obj1.positional_velocity.y -= velocity_y1;
+ obj1.positional_velocity.z -= velocity_z1;
+ }
+}
+
+auto ::bow::gravitate(::bow::ObjectRoot& system) noexcept -> void {
+ for (::bow::Object* obj0 = system.objects; obj0 != nullptr; obj0 = obj0->next) {
+ for (::bow::Object* obj1 = obj0->next; obj1 != nullptr; obj1 = obj1->next) {
+ ::bow::gravitate_pair(*obj0, *obj1);
+ }
+ }
+}
+
+auto ::bow::gravitate(::bow::ObjectRoot& objects, ::bow::ObjectRoot const& system) noexcept -> void {
+ for (::bow::Object* object = objects.objects; object != nullptr; object = object->next) {
+ for (::bow::Object* par = system.objects; par != nullptr; par = par->next) {
+ ::bow::gravitate_single(*object, *par);
+ }
+ }
+}
diff --git a/bowshock/source/logic/move.cxx b/bowshock/source/logic/move.cxx
new file mode 100644
index 0000000..321bcfa
--- /dev/null
+++ b/bowshock/source/logic/move.cxx
@@ -0,0 +1,18 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+
+auto ::bow::move(::bow::ObjectRoot& root) noexcept -> void {
+ auto const move = [](::bow::Object& object) -> void {
+ object.position.x += object.positional_velocity.x;
+ object.position.y += object.positional_velocity.y;
+ object.position.z += object.positional_velocity.z;
+ object.rotation.x += object.rotational_velocity.x;
+ object.rotation.y += object.rotational_velocity.y;
+ object.rotation.z += object.rotational_velocity.z;
+ };
+
+ for (::bow::Object* object = root.objects; object != nullptr; object = object->next) {
+ move(*object);
+ }
+}
diff --git a/bowshock/source/logic/ship_mass.cxx b/bowshock/source/logic/ship_mass.cxx
new file mode 100644
index 0000000..cd9dfac
--- /dev/null
+++ b/bowshock/source/logic/ship_mass.cxx
@@ -0,0 +1,10 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+
+auto ::bow::ship_mass([[maybe_unused]] ::bow::Ship const identifier) noexcept -> double {
+ double mass = 0x100p0;
+ mass /= ::bow::MASS_MODIFIER;
+
+ return mass;
+}
diff --git a/bowshock/source/logic/simulate.cxx b/bowshock/source/logic/simulate.cxx
new file mode 100644
index 0000000..18633c8
--- /dev/null
+++ b/bowshock/source/logic/simulate.cxx
@@ -0,0 +1,17 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+
+#include <bow/runtime.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::simulate(::bow::ObjectRoot& system, ::std::uint64_t const duration) noexcept -> void {
+ ::fmt::print(stderr, "simulating for ({}) time units\n", duration);
+
+ for (::std::uint64_t i = 0x0u; i <= duration; ++i) {
+ ::bow::gravitate(system);
+ ::bow::move(system);
+ }
+}
diff --git a/bowshock/source/run/abr.cxx b/bowshock/source/run/abr.cxx
deleted file mode 100644
index 5a28569..0000000
--- a/bowshock/source/run/abr.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/run.hxx>
-
-#include <cinttypes>
-#include <cstdlib>
-#include <source_location>
-
-auto ::bow::abr(::std::source_location const srcloc) noexcept -> void {
- bow_log(
- "\x1B[38;5;197maborting\x1B[0m from \"%s\":%" PRIXLEAST32 " @ %s\n",
- srcloc.file_name(),srcloc.line(),srcloc.function_name()
- );
-
- ::std::abort();
-}
diff --git a/bowshock/source/run/addobj.cxx b/bowshock/source/run/addobj.cxx
deleted file mode 100644
index 27459c9..0000000
--- a/bowshock/source/run/addobj.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/run.hxx>
-
-#include <cstdlib>
-#include <zp/mem>
-
-auto ::bow::addobj(::bow::objroot & root,::bow::obj const & objVal) -> void {
- bow_logdbg("adding object of type %s",::bow::objtypstr(objVal.typ));
-
- ::bow::obj * const obj = new ::bow::obj;
- ::zp::memcpy(obj,&objVal,sizeof (objVal));
-
- obj->nxt = root.objs;
- root.objs = obj;
-}
diff --git a/bowshock/source/run/gensys.cxx b/bowshock/source/run/gensys.cxx
deleted file mode 100644
index 4b0d17c..0000000
--- a/bowshock/source/run/gensys.cxx
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-#include <bow/run.hxx>
-
-#include <cinttypes>
-
-auto ::bow::gensys(::bow::objroot & sys,::zp::i04 const id,::zp::i04 const tim) -> void {
- bow_log("generating system (%" PRIX64 ")",id);
-
- // Note: The following code is only temporary;
- sys.objs = nullptr;
- ::bow::obj objTmp;
- objTmp = ::bow::obj {
- .typ = ::bow::objtyp::tar,
- .tartyp = ::bow::tar::g,
- .pos = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rot = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .posVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rotVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .mas = 0x1p0,
- // nxt will be overwritten anyways.
- };
- ::bow::addobj(sys,objTmp);
- objTmp = ::bow::obj {
- .typ = ::bow::objtyp::wrl,
- .wrldTyp = ::bow::wrl::rck,
- .pos = {
- .x = 0x0p0,
- .y = 0x1.F76F144Dp-1,
- .z = 0x0p0,
- },
- .rot = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .posVel = {
- .x = 0x1.B2D06FF3p-23*::bow::timmod,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rotVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x1.31DB66BBp-15,
- },
- .mas = 0x1.931AFC649369998Fp-19,
- };
- ::bow::addobj(sys,objTmp);
-
- ::bow::sim(sys,tim);
-}
diff --git a/bowshock/source/run/remobj.cxx b/bowshock/source/run/remobj.cxx
deleted file mode 100644
index a6b689d..0000000
--- a/bowshock/source/run/remobj.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/run.hxx>
-
-auto ::bow::remobj(::bow::objroot const & root) noexcept -> void {
- bow_logdbg("freeing objects");
-
- ::bow::obj * obj;
- ::bow::obj * nxt;
- for (obj = root.objs;obj != nullptr;obj = nxt) {
- bow_logdbg("freeing object of type %s",::bow::objtypstr(obj->typ));
-
- nxt = obj->nxt;
- delete obj;
- }
-}
diff --git a/bowshock/source/runtime/add_object.cxx b/bowshock/source/runtime/add_object.cxx
new file mode 100644
index 0000000..1ce1001
--- /dev/null
+++ b/bowshock/source/runtime/add_object.cxx
@@ -0,0 +1,18 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/runtime.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fmt/core.h>
+
+auto ::bow::add_object(::bow::ObjectRoot& root, ::bow::Object const& object_value) -> void {
+ ::fmt::print(stderr, "adding object of type {}\n", ::bow::object_type_string(object_value.type));
+
+ ::bow::Object* const object = new ::bow::Object;
+ ::std::memcpy(object, &object_value, sizeof (object_value));
+
+ object->next = root.objects;
+ root.objects = object;
+}
diff --git a/bowshock/source/runtime/delete_objects.cxx b/bowshock/source/runtime/delete_objects.cxx
new file mode 100644
index 0000000..aee39ec
--- /dev/null
+++ b/bowshock/source/runtime/delete_objects.cxx
@@ -0,0 +1,20 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/runtime.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::delete_objects(::bow::ObjectRoot const& root) noexcept -> void {
+ ::fmt::print(stderr, "freeing objects\n");
+
+ ::bow::Object* object;
+ ::bow::Object* next;
+
+ for (object = root.objects; object != nullptr; object = next) {
+ ::fmt::print(stderr, "freeing object of type {}", ::bow::object_type_string(object->type));
+
+ next = object->next;
+ delete object;
+ }
+}
diff --git a/bowshock/source/runtime/generate_system.cxx b/bowshock/source/runtime/generate_system.cxx
new file mode 100644
index 0000000..a841347
--- /dev/null
+++ b/bowshock/source/runtime/generate_system.cxx
@@ -0,0 +1,72 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+#include <bow/runtime.hxx>
+
+#include <cstdint>
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::generate_system(::bow::ObjectRoot& system, ::std::uint64_t const identifier, ::std::uint64_t const time) -> void {
+ ::fmt::print(stderr, "generating system ({:X})\n", identifier);
+
+ // Note: The following code is only temporary;
+ system.objects = nullptr;
+ ::bow::Object objTmp;
+ objTmp = ::bow::Object {
+ .type = ::bow::ObjectType::Star,
+ .star_type = ::bow::Star::G,
+ .position = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotation = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .positional_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotational_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .mass = 0x1p0,
+ // next will be overwritten anyways.
+ };
+ ::bow::add_object(system, objTmp);
+
+ objTmp = ::bow::Object {
+ .type = ::bow::ObjectType::World,
+ .world_type = ::bow::World::Rocky_world,
+ .position = {
+ .x = 0x0p0,
+ .y = 0x1.F76F144Dp-1,
+ .z = 0x0p0,
+ },
+ .rotation = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .positional_velocity = {
+ .x = 0x1.B2D06FF3p-23*::bow::TIME_MODIFIER,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotational_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x1.31DB66BBp-15,
+ },
+ .mass = 0x1.931AFC649369998Fp-19,
+ };
+ ::bow::add_object(system, objTmp);
+
+ ::bow::simulate(system, time);
+}
diff --git a/bowshock/source/sav/cnt.cxx b/bowshock/source/sav/cnt.cxx
deleted file mode 100644
index 65c99dd..0000000
--- a/bowshock/source/sav/cnt.cxx
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/sav.hxx>
-
-#include <cinttypes>
-#include <ly/io>
-#include <zp/mem>
-
-auto ::bow::cnt(::bow::plydat & plydat,char const * const pth) noexcept -> void {
- bow_log("loading save file at \"%s\"",pth);
-
- ::ly::fil fil;
-
- ::ly::err err = fil.opn(pth,::ly::mod::red,::ly::kep);
-
- if (err != ::ly::err::ok) [[unlikely]] {
- bow_logerr("unable to open save file \"%s\"",pth);
-
- return ::bow::newsav(plydat);
- }
-
- ::zp::i8 rawDat[::bow::savlen];
- err = fil.red(rawDat,::bow::savlen);
-
- if (err != ::ly::err::ok) [[unlikely]] {
- fil.cls();
-
- if (err == ::ly::err::eof) bow_logerr("corrupt save file at \"%s\"",pth);
- else bow_logerr("unable to read file at \"%s\"",pth);
-
- return ::bow::newsav(plydat);
- }
-
- fil.cls();
-
- ::bow::savdat dat;
-
- ::bow::decsav(dat,rawDat);
-
- if (dat.fmtVer != ::bow::savver) [[unlikely]] {
- bow_logerr("invalid format (%" PRIX64 ") of save file at \"%s\"",dat.fmtVer,pth);
-
- return ::bow::newsav(plydat);
- }
- if (dat.shptyp > ::bow::maxshpid) [[unlikely]] {
- bow_logerr("invalid shp type (%" PRIX8 ")",dat.shptyp);
-
- return ::bow::newsav(plydat);
- }
-
- plydat = ::bow::plydat {
- .tim = dat.tim,
- .sysidt = dat.sysidt,
- .shp = {
- .shptyp = (::bow::shp)dat.shptyp,
- .pos = {
- .x = dat.shpposx,
- .y = dat.shpposy,
- .z = dat.shpposz,
- },
- .rot = {
- .x = dat.shprotx,
- .y = dat.shproty,
- .z = dat.shprotz,
- },
- .posVel = {
- .x = dat.shpposvelx,
- .y = dat.shpposvely,
- .z = dat.shpposvelz,
- },
- .rotVel = {
- .x = dat.shprotvelx,
- .y = dat.shprotvely,
- .z = dat.shprotvelz,
- },
- },
- };
- ::zp::cpy(plydat.nam,dat.cmdnam,::bow::cmdnamlen);
- plydat.nam[::bow::cmdnamlen] = '\x00';
-
- ::bow::gendat(plydat);
-
- bow_log("welcome back, commander %s",plydat.nam);
-}
diff --git a/bowshock/source/sav/decsav.cxx b/bowshock/source/sav/decsav.cxx
deleted file mode 100644
index 6adc78a..0000000
--- a/bowshock/source/sav/decsav.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/sav.hxx>
-
-#include <zp/mem>
-
-auto ::bow::decsav(::bow::savdat & buf,::zp::i8 const * dat) noexcept -> void {
- auto const decVal = [&dat]<typename typ>(typ & buf) {
- dat = ::zp::memcpy(&buf,dat,sizeof (buf)).src;
- };
-
- decVal(buf.fmtVer); // fmtver
- decVal(buf.cmdnam); // cmdnam
- decVal(buf.tim); // tim
- decVal(buf.sysidt); // sysidt
- decVal(buf.shptyp); // shptyp
- decVal(buf.shpposx); // shpposx
- decVal(buf.shpposy); // shpposy
- decVal(buf.shpposz); // shpposz
- decVal(buf.shprotx); // shprotx
- decVal(buf.shproty); // shproty
- decVal(buf.shprotz); // shprotz
- decVal(buf.shpposvelx); // shpposvelx
- decVal(buf.shpposvely); // shpposvely
- decVal(buf.shpposvelz); // shpposvelz
- decVal(buf.shprotvelx); // shprotvelx
- decVal(buf.shprotvely); // shprotvely
- decVal(buf.shprotvelz); // shprotvelz
-}
diff --git a/bowshock/source/sav/encsav.cxx b/bowshock/source/sav/encsav.cxx
deleted file mode 100644
index aa66fde..0000000
--- a/bowshock/source/sav/encsav.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/sav.hxx>
-
-#include <zp/mem>
-
-auto ::bow::encsav(::zp::i8 * buf,::bow::savdat const & dat) noexcept -> void {
- auto const encVal = [&buf]<typename typ>(typ const & val) {
- buf = ::zp::memcpy(buf,&val,sizeof (val)).dst;
- };
-
- encVal(dat.fmtVer); // fmtver
- encVal(dat.cmdnam); // cmdnam
- encVal(dat.tim); // tim
- encVal(dat.sysidt); // sysidt
- encVal(dat.shptyp); // shptyp
- encVal(dat.shpposx); // shpposx
- encVal(dat.shpposy); // shpposy
- encVal(dat.shpposz); // shpposz
- encVal(dat.shprotx); // shprotx
- encVal(dat.shproty); // shproty
- encVal(dat.shprotz); // shprotz
- encVal(dat.shpposvelx); // shpposelx
- encVal(dat.shpposvely); // shpposely
- encVal(dat.shpposvelz); // shpposelz
- encVal(dat.shprotvelx); // shprotelx
- encVal(dat.shprotvely); // shprotely
- encVal(dat.shprotvelz); // shprotelz
-}
diff --git a/bowshock/source/sav/gendat.cxx b/bowshock/source/sav/gendat.cxx
deleted file mode 100644
index 2a88d84..0000000
--- a/bowshock/source/sav/gendat.cxx
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/lgc.hxx>
-#include <bow/sav.hxx>
-
-auto ::bow::gendat(::bow::plydat & dat) noexcept -> void {
- bow_log("generating player data");
-
- dat.shp.typ = ::bow::objtyp::shp;
- dat.shp.mas = ::bow::shpmas(dat.shp.shptyp);
- dat.zom = 0x4p0;
-}
diff --git a/bowshock/source/sav/newsav.cxx b/bowshock/source/sav/newsav.cxx
deleted file mode 100644
index 1c525c2..0000000
--- a/bowshock/source/sav/newsav.cxx
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/sav.hxx>
-
-auto ::bow::newsav(::bow::plydat & dat) noexcept -> void {
- bow_log("generating new save file");
-
- dat = ::bow::plydat {
- .nam = "Caelum\x00\x00\x00\x00\x00\x00\x00\x00",
- .tim = 0x0u, // 256 julian years after the Unix Epoch.
- .sysidt = 0x45u,
- .shp = {
- .shptyp = ::bow::shp::aqu,
- .pos = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rot = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .posVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- .rotVel = {
- .x = 0x0p0,
- .y = 0x0p0,
- .z = 0x0p0,
- },
- },
- };
- ::bow::gendat(dat);
-
- bow_log("welcome, commander %s",dat.nam);
-}
diff --git a/bowshock/source/sav/sav.cxx b/bowshock/source/sav/sav.cxx
deleted file mode 100644
index 9e8a896..0000000
--- a/bowshock/source/sav/sav.cxx
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2022-2023 Gabriel Jensen.
-
-#include <bow/run.hxx>
-#include <bow/sav.hxx>
-
-#include <ly/io>
-#include <zp/mem>
-
-auto ::bow::sav(char const * const pth,::bow::plydat const & plydat) noexcept -> void {
- bow_log("saving commander %s at \"%s\"",plydat.nam,pth);
-
- ::ly::fil fil;
- ::ly::err err = fil.crt(pth,0644u);
-
- if (err != ::ly::err::ok) [[unlikely]] {
- bow_logerr("unable to open save file \"%s\"",pth);
- ::bow::abr();
- }
-
- ::zp::i8 dat[::bow::savlen];
-
- ::bow::savdat savdat = {
- .fmtVer = ::bow::savver,
- .tim = plydat.tim,
- .sysidt = plydat.sysidt,
- .shptyp = static_cast<::zp::i8>(plydat.shp.shptyp),
- .shpposx = plydat.shp.pos.x,
- .shpposy = plydat.shp.pos.y,
- .shpposz = plydat.shp.pos.z,
- .shprotx = plydat.shp.rot.x,
- .shproty = plydat.shp.rot.y,
- .shprotz = plydat.shp.rot.z,
- .shpposvelx = plydat.shp.posVel.x,
- .shpposvely = plydat.shp.posVel.y,
- .shpposvelz = plydat.shp.posVel.z,
- .shprotvelx = plydat.shp.rotVel.x,
- .shprotvely = plydat.shp.rotVel.y,
- .shprotvelz = plydat.shp.rotVel.z,
- };
- ::zp::cpy(savdat.cmdnam,plydat.nam,sizeof (savdat.cmdnam));
-
- ::bow::encsav(dat,savdat);
-
- fil.wrt(dat,::bow::savlen);
- fil.cls();
-}
diff --git a/bowshock/source/save/continue_save.cxx b/bowshock/source/save/continue_save.cxx
new file mode 100644
index 0000000..38266d2
--- /dev/null
+++ b/bowshock/source/save/continue_save.cxx
@@ -0,0 +1,75 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/save.hxx>
+
+#include <cstdint>
+#include <cstdio>
+#include <fmt/core.h>
+#include <string>
+
+auto ::bow::continue_save(::bow::PlayerData& player_data, ::std::string path) noexcept -> void {
+ ::fmt::print(stderr, "loading save file at \"{}\"\n", path);
+
+ ::std::FILE* file = ::std::fopen(path.c_str(), "r");
+
+ if (file == nullptr) [[unlikely]] {
+ ::fmt::print(stderr, "unable to open save file\n");
+
+ return ::bow::new_save(player_data);
+ }
+
+ ::std::uint8_t raw_data[::bow::SAVE_LENGTH];
+
+ ::std::fread(raw_data, 0x1u, ::bow::SAVE_LENGTH, file);
+ ::std::fclose(file);
+
+ ::bow::save_data data;
+
+ ::bow::decode_save(data, raw_data);
+
+ if (data.format_version != ::bow::SAVE_VERSION) [[unlikely]] {
+ ::fmt::print(stderr, "invalid format ({:#04X}) of save file\n", data.format_version);
+
+ return ::bow::new_save(player_data);
+ }
+ if (data.ship_type > ::bow::MAX_SHIP_IDENTIFIER) [[unlikely]] {
+ ::fmt::print(stderr, "invalid ship type ({:#04X})\n", data.ship_type);
+
+ return ::bow::new_save(player_data);
+ }
+
+ player_data = ::bow::PlayerData {
+ .time = data.time,
+ .system_identifier = data.system_identifier,
+ .ship = {
+ .ship_type = static_cast<::bow::Ship>(data.ship_type),
+ .position = {
+ .x = data.ship_position_x,
+ .y = data.ship_position_y,
+ .z = data.ship_position_z,
+ },
+ .rotation = {
+ .x = data.ship_rotation_x,
+ .y = data.ship_rotation_y,
+ .z = data.ship_rotation_z,
+ },
+ .positional_velocity = {
+ .x = data.ship_positional_velocity_x,
+ .y = data.ship_positional_velocity_y,
+ .z = data.ship_positional_velocity_z,
+ },
+ .rotational_velocity = {
+ .x = data.ship_rotational_velocity_x,
+ .y = data.ship_rotational_velocity_y,
+ .z = data.ship_rotational_velocity_z,
+ },
+ },
+ };
+
+ ::std::memcpy(player_data.name, data.commander_name, ::bow::COMMANDER_NAME_LENGTH);
+ player_data.name[::bow::COMMANDER_NAME_LENGTH] = '\000';
+
+ ::bow::generate_data(player_data);
+
+ ::fmt::print(stderr, "welcome back, CMDR {}\n", player_data.name);
+}
diff --git a/bowshock/source/save/decode_save.cxx b/bowshock/source/save/decode_save.cxx
new file mode 100644
index 0000000..1bfe8cd
--- /dev/null
+++ b/bowshock/source/save/decode_save.cxx
@@ -0,0 +1,35 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/save.hxx>
+
+#include <cstdint>
+#include <cstring>
+
+auto ::bow::decode_save(::bow::save_data& buffer, void const* data_pointer) noexcept -> void {
+ auto data = reinterpret_cast<::std::uint8_t const*>(data_pointer);
+
+ auto const decode_value = [&data]<typename T>(T& buffer) {
+ constexpr ::std::size_t size = sizeof (buffer);
+
+ ::std::memcpy(&buffer, data, size);
+ data += size;
+ };
+
+ decode_value(buffer.format_version);
+ decode_value(buffer.commander_name);
+ decode_value(buffer.time);
+ decode_value(buffer.system_identifier);
+ decode_value(buffer.ship_type);
+ decode_value(buffer.ship_position_x);
+ decode_value(buffer.ship_position_y);
+ decode_value(buffer.ship_position_z);
+ decode_value(buffer.ship_rotation_x);
+ decode_value(buffer.ship_rotation_y);
+ decode_value(buffer.ship_rotation_z);
+ decode_value(buffer.ship_positional_velocity_x);
+ decode_value(buffer.ship_positional_velocity_y);
+ decode_value(buffer.ship_positional_velocity_z);
+ decode_value(buffer.ship_rotational_velocity_x);
+ decode_value(buffer.ship_rotational_velocity_y);
+ decode_value(buffer.ship_rotational_velocity_z);
+}
diff --git a/bowshock/source/save/encode_save.cxx b/bowshock/source/save/encode_save.cxx
new file mode 100644
index 0000000..db05735
--- /dev/null
+++ b/bowshock/source/save/encode_save.cxx
@@ -0,0 +1,35 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/save.hxx>
+
+#include <cstdint>
+#include <cstring>
+
+auto ::bow::encode_save(void* const buffer_pointer, ::bow::save_data const& data) noexcept -> void {
+ auto buffer = reinterpret_cast<::std::uint8_t*>(buffer_pointer);
+
+ auto const encode_value = [&buffer]<typename T>(T const& val) {
+ constexpr ::std::size_t size = sizeof (val);
+
+ ::std::memcpy(buffer, &val, size);
+ buffer += size;
+ };
+
+ encode_value(data.format_version);
+ encode_value(data.commander_name);
+ encode_value(data.time);
+ encode_value(data.system_identifier);
+ encode_value(data.ship_type);
+ encode_value(data.ship_position_x);
+ encode_value(data.ship_position_y);
+ encode_value(data.ship_position_z);
+ encode_value(data.ship_rotation_x);
+ encode_value(data.ship_rotation_y);
+ encode_value(data.ship_rotation_z);
+ encode_value(data.ship_positional_velocity_x);
+ encode_value(data.ship_positional_velocity_y);
+ encode_value(data.ship_positional_velocity_z);
+ encode_value(data.ship_rotational_velocity_x);
+ encode_value(data.ship_rotational_velocity_y);
+ encode_value(data.ship_rotational_velocity_z);
+}
diff --git a/bowshock/source/save/generate_data.cxx b/bowshock/source/save/generate_data.cxx
new file mode 100644
index 0000000..9cfd78a
--- /dev/null
+++ b/bowshock/source/save/generate_data.cxx
@@ -0,0 +1,15 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/logic.hxx>
+#include <bow/save.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::generate_data(::bow::PlayerData& data) noexcept -> void {
+ ::fmt::print(stderr, "generating player data\n");
+
+ data.ship.type = ::bow::ObjectType::Ship;
+ data.ship.mass = ::bow::ship_mass(data.ship.ship_type);
+ data.zoom = 0x4p0;
+}
diff --git a/bowshock/source/save/new_save.cxx b/bowshock/source/save/new_save.cxx
new file mode 100644
index 0000000..a91d0e2
--- /dev/null
+++ b/bowshock/source/save/new_save.cxx
@@ -0,0 +1,42 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/save.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+
+auto ::bow::new_save(::bow::PlayerData& data) noexcept -> void {
+ ::fmt::print(stderr, "generating new save file\n");
+
+ data = ::bow::PlayerData {
+ .name = "Caelum\x00\x00\x00\x00\x00\x00\x00\x00",
+ .time = 0x0u, // 256 julian years after the Unix Epoch.
+ .system_identifier = 0x45u,
+ .ship = {
+ .ship_type = ::bow::Ship::Aquila,
+ .position = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotation = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .positional_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ .rotational_velocity = {
+ .x = 0x0p0,
+ .y = 0x0p0,
+ .z = 0x0p0,
+ },
+ },
+ };
+ ::bow::generate_data(data);
+
+ ::fmt::print(stderr, "welcome, CMDR {}\n", data.name);
+}
diff --git a/bowshock/source/save/save.cxx b/bowshock/source/save/save.cxx
new file mode 100644
index 0000000..ba104e2
--- /dev/null
+++ b/bowshock/source/save/save.cxx
@@ -0,0 +1,51 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/runtime.hxx>
+#include <bow/save.hxx>
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fmt/core.h>
+
+auto ::bow::save(::std::string const path, ::bow::PlayerData const& player_data) noexcept -> void {
+ using ::bow::SAVE_LENGTH;
+
+ ::fmt::print(stderr, "saving CMDR {} at \"{}\"\n", player_data.name, path);
+
+ ::std::FILE* file = ::std::fopen(path.c_str(), "w");
+
+ if (file == nullptr) [[unlikely]] {
+ ::fmt::print(stderr, "unable to open save file\n");
+
+ ::std::abort();
+ }
+
+ ::bow::save_data save_data = {
+ .format_version = ::bow::SAVE_VERSION,
+ .time = player_data.time,
+ .system_identifier = player_data.system_identifier,
+ .ship_type = static_cast<::std::uint8_t>(player_data.ship.ship_type),
+ .ship_position_x = player_data.ship.position.x,
+ .ship_position_y = player_data.ship.position.y,
+ .ship_position_z = player_data.ship.position.z,
+ .ship_rotation_x = player_data.ship.rotation.x,
+ .ship_rotation_y = player_data.ship.rotation.y,
+ .ship_rotation_z = player_data.ship.rotation.z,
+ .ship_positional_velocity_x = player_data.ship.positional_velocity.x,
+ .ship_positional_velocity_y = player_data.ship.positional_velocity.y,
+ .ship_positional_velocity_z = player_data.ship.positional_velocity.z,
+ .ship_rotational_velocity_x = player_data.ship.rotational_velocity.x,
+ .ship_rotational_velocity_y = player_data.ship.rotational_velocity.y,
+ .ship_rotational_velocity_z = player_data.ship.rotational_velocity.z,
+ };
+ ::std::memcpy(save_data.commander_name, player_data.name, sizeof (save_data.commander_name));
+
+ ::std::uint8_t data[SAVE_LENGTH];
+
+ ::bow::encode_save(data, save_data);
+
+ ::std::fwrite(data, 0x1u, SAVE_LENGTH, file);
+ ::std::fclose(file);
+}
diff --git a/glad.CMakeLists.txt b/glad.CMakeLists.txt
index 7d7c2fc..0ec0384 100644
--- a/glad.CMakeLists.txt
+++ b/glad.CMakeLists.txt
@@ -4,7 +4,7 @@ set(CMAKE_C_STANDARD 99)
add_library(
glad STATIC
-
+
"src/glad.c"
)
diff --git a/install.sh b/install.sh
index 2727a86..20d7017 100755
--- a/install.sh
+++ b/install.sh
@@ -5,7 +5,7 @@ installBinary() {
bindir="${2}"
mkdir -pvm755 "${bindir}"
-
+
install -vm755 "${builddir}/bowshock/bowshock" "${bindir}"/bowshock
}
@@ -14,7 +14,7 @@ installData() {
datdir="${2}"
mkdir -pvm755 "${datdir}/shaders"
-
+
install -vm644 "${srcdir}/CHANGELOG.txt" "${datdir}"
install -vm644 "${srcdir}/CREDITS.txt" "${datdir}"
install -vm644 "${srcdir}/bowshock/shader/"*".glsl" "${datdir}/shaders"
diff --git a/validateShaders.py b/validateShaders.py
index 11ec783..9dd9f16 100755
--- a/validateShaders.py
+++ b/validateShaders.py
@@ -20,6 +20,7 @@ def validate(path:str):
print("\x1B[38;5;77mokay\x1B[0m")
if __name__ == "__main__":
+ quit(0x0)
print("validating shaders...")
shaders = [