summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt10
-rw-r--r--bowshock/CMakeLists.txt4
-rw-r--r--bowshock/include/bow/application.hxx23
-rw-r--r--bowshock/include/bow/base.hxx102
-rw-r--r--bowshock/include/bow/logic.hxx4
-rw-r--r--bowshock/include/bow/save.hxx10
-rw-r--r--bowshock/source/application/bow/compile_shader_program.cxx8
-rw-r--r--bowshock/source/application/bow/configure.cxx (renamed from bowshock/source/application/bow/check_parameters.cxx)15
-rw-r--r--bowshock/source/application/bow/get_quote.cxx4
-rw-r--r--bowshock/source/application/bow/loop.cxx2
-rw-r--r--bowshock/source/application/bow/print_credits.cxx2
-rw-r--r--bowshock/source/application/bow/print_help.cxx6
-rw-r--r--bowshock/source/application/bow/run.cxx25
-rw-r--r--bowshock/source/base/object_type_string.cxx5
-rw-r--r--bowshock/source/base/random.cxx2
-rw-r--r--bowshock/source/base/save_path.cxx8
-rw-r--r--bowshock/source/runtime/delete_objects.cxx2
-rw-r--r--bowshock/source/runtime/generate_system.cxx6
-rw-r--r--bowshock/source/save/continue_save.cxx35
-rw-r--r--bowshock/source/save/decode_save.cxx2
-rw-r--r--bowshock/source/save/encode_save.cxx2
-rw-r--r--bowshock/source/save/generate_data.cxx15
-rw-r--r--bowshock/source/save/new_save.cxx16
-rw-r--r--bowshock/source/save/save.cxx4
24 files changed, 209 insertions, 103 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index c64d228..a6b7a72 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -37,6 +37,16 @@
* Update readme
* Fix version constant
+* Check I/O results;
+* Fix credits print;
+* Add structure for wares;
+* Disable language extensions;
+* Don't overwrite save by default;
+* Load save file before start sequence;
+* Fix quotes;
+* Fix logs;
+* Fix save loader;
+
# 0.B.2
* Fix data directory not being set correctly by CMake;
diff --git a/bowshock/CMakeLists.txt b/bowshock/CMakeLists.txt
index 70e9438..30c19a0 100644
--- a/bowshock/CMakeLists.txt
+++ b/bowshock/CMakeLists.txt
@@ -7,12 +7,13 @@ if("${BOW_DATA_DIRECTORY}" STREQUAL "")
endif()
set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(
bowshock
- "source/application/bow/check_parameters.cxx"
"source/application/bow/compile_shader_program.cxx"
+ "source/application/bow/configure.cxx"
"source/application/bow/destructor.cxx"
"source/application/bow/get_quote.cxx"
"source/application/bow/initialise_graphics.cxx"
@@ -43,7 +44,6 @@ add_executable(
"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"
)
diff --git a/bowshock/include/bow/application.hxx b/bowshock/include/bow/application.hxx
index d99eaf5..4b61bca 100644
--- a/bowshock/include/bow/application.hxx
+++ b/bowshock/include/bow/application.hxx
@@ -6,11 +6,19 @@
#include <csignal>
#include <cstdint>
+#include <cstdio>
+#include <fmt/core.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <string>
namespace bow {
+ template<typename T> struct VersionType {
+ T major;
+ T minor;
+ T patch;
+ };
+
constexpr ::std::string SHADER_FILE_SUFFIX("glsl");
struct GraphicsData {
@@ -18,7 +26,7 @@ namespace bow {
::GLuint shader_program;
};
- struct TerminalOptions {
+ struct Configuration {
::std::string save_path;
bool has_save_path:0x1;
bool new_save:0x1;
@@ -34,8 +42,15 @@ namespace bow {
~Application() noexcept;
private:
- ::bow::PlayerData player_data;
- ::bow::GraphicsData graphics_data;
+ constexpr static ::bow::VersionType<::std::uint64_t> VERSION = {
+ .major = 0x0u,
+ .minor = 0xCu,
+ .patch = 0x0u,
+ };
+
+ ::bow::Configuration configuration;
+ ::bow::PlayerData player_data;
+ ::bow::GraphicsData graphics_data;
auto get_quote(::std::string& quote, ::std::string& source, ::std::uint8_t code) noexcept -> void;
@@ -45,7 +60,7 @@ namespace bow {
[[noreturn]] auto print_help(::std::string program_name) noexcept -> void;
- auto check_parameters(TerminalOptions& options, int argc, char const* const* argv) noexcept -> void;
+ auto configure(Configuration& configuration, int argc, char const* const* argv) noexcept -> void;
auto compile_shader_program(::GLuint& shader_program, ::std::string name) noexcept -> void;
diff --git a/bowshock/include/bow/base.hxx b/bowshock/include/bow/base.hxx
index 3c7589e..1f418bf 100644
--- a/bowshock/include/bow/base.hxx
+++ b/bowshock/include/bow/base.hxx
@@ -16,24 +16,12 @@ 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 = 0x0u,
- };
-
constexpr bool DEBUG = bow_debug;
constexpr ::std::size_t COMMANDER_NAME_LENGTH = 0xEu;
+ constexpr ::std::uint8_t NUMBER_OF_QUOTE_IDENTIFIERS = UINT8_C(0x24);
+
enum struct ObjectType : ::std::uint8_t {
Canister,
Player,
@@ -43,15 +31,6 @@ namespace bow {
World, // planet/moon
};
- enum struct World : ::std::uint8_t {
- Ammonium_world,
- Gas_giant,
- Ice_world,
- Rocky_world,
- Lava_world,
- Water_world,
- };
-
enum struct Ship : ::std::uint8_t {
Aquila,
Cassiopeia,
@@ -91,6 +70,80 @@ namespace bow {
Orbis,
};
+ enum struct Ware : ::std::uint8_t {
+ Air,
+ Aluminium,
+ AncientArtefacts,
+ AnimalFurs,
+ AnimalMeat,
+ AnimalSkins,
+ Atomics,
+ BattleWeapons,
+ Beer,
+ Biowaste,
+ Cheese,
+ ChemicalWaste,
+ Cobalt,
+ Coffee,
+ ComputerParts,
+ Computers,
+ Copper,
+ Cuttlery,
+ Dairy,
+ Explosives,
+ FruitsAndVegetables,
+ Gemstones,
+ Gold,
+ HandWeapons,
+ HullParts,
+ HydrogenFuel,
+ Iron,
+ Ivory,
+ Lasers,
+ Leather,
+ Liquor,
+ Lithium,
+ LiveAnimals,
+ LuxuryGoods,
+ Magnets,
+ Medicine,
+ Minerals,
+ Monitors,
+ NerveAgents,
+ OrganicDyes,
+ Paper,
+ Pearls,
+ Pesticides,
+ Platinum,
+ Plutonium,
+ Radioactives,
+ Robots,
+ Rockets,
+ Rubbish,
+ Silver,
+ Slaves,
+ StorageDevices,
+ Superconductors,
+ SyntheticMeat,
+ Tea,
+ Titanium,
+ Tobacco,
+ TritiumFuel,
+ Uranium,
+ Water,
+ Wine,
+ XenoRelics,
+ };
+
+ enum struct World : ::std::uint8_t {
+ AmmoniumWorld,
+ GasGiant,
+ IceWorld,
+ LavaWorld,
+ RockyWorld,
+ WaterWorld,
+ };
+
struct Xyz {
double x;
double y;
@@ -100,10 +153,11 @@ namespace bow {
struct Object {
::bow::ObjectType type;
union {
- ::bow::World world_type;
+ ::bow::Ware canister_content;
::bow::Ship ship_type;
::bow::Star star_type;
::bow::Station station_type;
+ ::bow::World world_type;
};
::bow::Xyz position; // astronomical units
diff --git a/bowshock/include/bow/logic.hxx b/bowshock/include/bow/logic.hxx
index dee11cb..9b7b9e3 100644
--- a/bowshock/include/bow/logic.hxx
+++ b/bowshock/include/bow/logic.hxx
@@ -8,8 +8,8 @@
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 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.
diff --git a/bowshock/include/bow/save.hxx b/bowshock/include/bow/save.hxx
index b9f4ca4..f4a5642 100644
--- a/bowshock/include/bow/save.hxx
+++ b/bowshock/include/bow/save.hxx
@@ -39,7 +39,7 @@ namespace bow {
0x7F ship_rotational_velocity_z 8 binary64
*/
- struct save_data {
+ struct SaveData {
::std::uint64_t format_version;
char8_t commander_name[::bow::COMMANDER_NAME_LENGTH];
::std::uint64_t time;
@@ -59,14 +59,12 @@ namespace bow {
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 decode_save(::bow::SaveData& buf, void const* data) noexcept -> void;
+ auto encode_save(void* buf, ::bow::SaveData 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 continue_save(::bow::PlayerData& data, ::std::string file) -> bool;
auto save(::std::string file, ::bow::PlayerData const& data) noexcept -> void;
}
diff --git a/bowshock/source/application/bow/compile_shader_program.cxx b/bowshock/source/application/bow/compile_shader_program.cxx
index c6ed0cb..57ad978 100644
--- a/bowshock/source/application/bow/compile_shader_program.cxx
+++ b/bowshock/source/application/bow/compile_shader_program.cxx
@@ -78,12 +78,12 @@ static auto ::bow::compile_shader(::GLuint& shader, ::std::string const name, ::
auto const file_size = ::std::filesystem::file_size(path);
- static_assert(::std::is_same_v<GLchar, char>);
+ static_assert(sizeof (GLchar) == sizeof (char));
auto source = ::std::vector<GLchar>(file_size + 0x1u);
- ::std::fread(source.data(), 0x1u, file_size, file);
-
- ::std::fclose(file);
+ if (::std::fread(source.data(), 0x1u, file_size, file) < file_size) [[unlikely]] {
+ throw ::std::runtime_error {"unable to read shader source"};
+ }
source.push_back('\x00');
diff --git a/bowshock/source/application/bow/check_parameters.cxx b/bowshock/source/application/bow/configure.cxx
index 535631c..41793c5 100644
--- a/bowshock/source/application/bow/check_parameters.cxx
+++ b/bowshock/source/application/bow/configure.cxx
@@ -8,10 +8,13 @@
#include <string>
#include <vector>
-auto ::bow::Application::check_parameters(::bow::TerminalOptions& options, int const argc, char const* const* argv) noexcept -> void {
+using namespace ::std::literals::string_literals;
+
+auto ::bow::Application::configure(::bow::Configuration& configuration, int const argc, char const* const* argv) noexcept -> void {
::std::string const program_name = *argv;
- options = ::bow::TerminalOptions {
+ configuration = ::bow::Configuration {
+ .save_path = ""s,
.has_save_path = false,
.new_save = false,
.skip_intro = false,
@@ -26,16 +29,16 @@ auto ::bow::Application::check_parameters(::bow::TerminalOptions& options, int c
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 if (!::std::strcmp(parameter, "new")) { configuration.new_save = true; }
+ else if (!::std::strcmp(parameter, "skip")) { configuration.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;
+ configuration.save_path = parameter;
+ configuration.has_save_path = true;
}
}
}
diff --git a/bowshock/source/application/bow/get_quote.cxx b/bowshock/source/application/bow/get_quote.cxx
index 14bf05c..610c21a 100644
--- a/bowshock/source/application/bow/get_quote.cxx
+++ b/bowshock/source/application/bow/get_quote.cxx
@@ -114,7 +114,7 @@ auto ::bow::Application::get_quote(::std::string& quote, ::std::string& source,
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.";
+ quote = "Sooner or later, we must expand life beyond our little blue mud ball\u2014or go extinct.";
source = "Elon Reeve Musk";
break;
case 0x1Au:
@@ -146,7 +146,7 @@ auto ::bow::Application::get_quote(::std::string& quote, ::std::string& source,
source = "Bjarne Stroustrup";
break;
case 0x21u:
- quote = "There is no mathematical sibstitute for philosophy.";
+ quote = "There is no mathematical substitute for philosophy.";
source = "Saul Aaron Kripke";
break;
case 0x22u:
diff --git a/bowshock/source/application/bow/loop.cxx b/bowshock/source/application/bow/loop.cxx
index 318af0e..99e22d8 100644
--- a/bowshock/source/application/bow/loop.cxx
+++ b/bowshock/source/application/bow/loop.cxx
@@ -48,6 +48,7 @@ auto ::bow::Application::loop() noexcept -> void {
::bow::Object object_temporary = {
.type = ::bow::ObjectType::Canister,
+ .canister_content = ::bow::Ware::Biowaste,
.position = {
.x = 0x0p0,
.y = -0x2p0,
@@ -69,6 +70,7 @@ auto ::bow::Application::loop() noexcept -> void {
.z = 0x0p0,
},
.mass = 0x1p0,
+ .next = nullptr,
};
::bow::add_object(objects_root, object_temporary);
diff --git a/bowshock/source/application/bow/print_credits.cxx b/bowshock/source/application/bow/print_credits.cxx
index 4acbc90..312048e 100644
--- a/bowshock/source/application/bow/print_credits.cxx
+++ b/bowshock/source/application/bow/print_credits.cxx
@@ -35,7 +35,7 @@ auto ::bow::Application::print_credits() noexcept -> void {
credits.append("\n");
- ::std::fputs(credits.c_str(), file);
+ ::std::fputs(credits.c_str(), stdout);
credits.~basic_string();
diff --git a/bowshock/source/application/bow/print_help.cxx b/bowshock/source/application/bow/print_help.cxx
index f08bc45..07cc267 100644
--- a/bowshock/source/application/bow/print_help.cxx
+++ b/bowshock/source/application/bow/print_help.cxx
@@ -11,15 +11,15 @@ auto ::bow::Application::print_help(::std::string const program_name) noexcept -
"\x1B[1mBowshock\x1B[0m {:X}.{:X}.{:X}\n"
"Copyright 2022-2023 Gabriel Bj\u00F8rnager Jensen.\n"
"\n"
- "Usage: \"{}\" <options> [savefile]\n"
+ "Usage: \"{}\" <configuration> [savefile]\n"
"\n"
- "Options:\n"
+ "configuration:\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);
+ ::bow::Application::VERSION.major, ::bow::Application::VERSION.minor, ::bow::Application::VERSION.patch, program_name);
::std::exit(EXIT_SUCCESS);
}
diff --git a/bowshock/source/application/bow/run.cxx b/bowshock/source/application/bow/run.cxx
index ac35de5..d661b03 100644
--- a/bowshock/source/application/bow/run.cxx
+++ b/bowshock/source/application/bow/run.cxx
@@ -9,15 +9,16 @@
#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);
+ configure(this->configuration, argc, argv);
+
+ if (!this->configuration.has_save_path) { this->configuration.save_path = ::bow::save_path(); }
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
+ ::bow::Application::VERSION.major, ::bow::Application::VERSION.minor, ::bow::Application::VERSION.patch
);
::fmt::print(stderr, "initialising\n");
@@ -36,15 +37,23 @@ auto ::bow::Application::run(int const argc, char const* const* const argv) noex
this->initialise_signal();
this->initialise_graphics();
- if (options.skip_intro || !start_sequence()) [[likely]] {
- if (!options.has_save_path) { options.save_path = ::bow::save_path(); }
+ auto invalid_save = false;
+
+ if (this->configuration.new_save) { ::bow::new_save(player_data); }
+ else { invalid_save = ::bow::continue_save(player_data, this->configuration.save_path); }
+
+ if (invalid_save) {
+ ::fmt::print(stderr, "aborting due to invalid save file\n");
+
+ return;
+ }
- if (options.new_save) { ::bow::new_save(player_data); }
- else { ::bow::continue_save(player_data, options.save_path); }
+ if (this->configuration.skip_intro || !start_sequence()) [[likely]] {
+ if (!this->configuration.has_save_path) { this->configuration.save_path = ::bow::save_path(); }
this->loop();
- ::bow::save(options.save_path, player_data);
+ ::bow::save(this->configuration.save_path, player_data);
}
}
diff --git a/bowshock/source/base/object_type_string.cxx b/bowshock/source/base/object_type_string.cxx
index 92297a1..2a52152 100644
--- a/bowshock/source/base/object_type_string.cxx
+++ b/bowshock/source/base/object_type_string.cxx
@@ -10,14 +10,19 @@ auto ::bow::object_type_string(::bow::ObjectType const type) noexcept -> ::std::
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
index 6f94b3b..503a31c 100644
--- a/bowshock/source/base/random.cxx
+++ b/bowshock/source/base/random.cxx
@@ -11,6 +11,8 @@ static_assert(sizeof (int) == sizeof (::std::uint32_t));
static_assert(RAND_MAX == ::std::numeric_limits<int>::max());
auto ::bow::random() noexcept -> ::std::uint64_t {
+ // TO-DO: Improve.
+
::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;
diff --git a/bowshock/source/base/save_path.cxx b/bowshock/source/base/save_path.cxx
index fea3fc7..aeddcbc 100644
--- a/bowshock/source/base/save_path.cxx
+++ b/bowshock/source/base/save_path.cxx
@@ -9,18 +9,18 @@
using namespace ::std::literals::string_literals;
+namespace { constexpr ::std::string file_name(".save_bowshock"); }
+
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;
+ base_directory = "."s;
}
- auto const file_name = ".save_bowshock"s;
-
- auto const path = base_directory + "/"s + file_name;
+ auto const path = base_directory + "/"s + ::file_name;
return path;
}
diff --git a/bowshock/source/runtime/delete_objects.cxx b/bowshock/source/runtime/delete_objects.cxx
index aee39ec..11550b5 100644
--- a/bowshock/source/runtime/delete_objects.cxx
+++ b/bowshock/source/runtime/delete_objects.cxx
@@ -12,7 +12,7 @@ auto ::bow::delete_objects(::bow::ObjectRoot const& root) noexcept -> void {
::bow::Object* next;
for (object = root.objects; object != nullptr; object = next) {
- ::fmt::print(stderr, "freeing object of type {}", ::bow::object_type_string(object->type));
+ ::fmt::print(stderr, "freeing object of type {}\n", ::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
index a841347..73bd1e3 100644
--- a/bowshock/source/runtime/generate_system.cxx
+++ b/bowshock/source/runtime/generate_system.cxx
@@ -37,13 +37,14 @@ auto ::bow::generate_system(::bow::ObjectRoot& system, ::std::uint64_t const ide
.z = 0x0p0,
},
.mass = 0x1p0,
- // next will be overwritten anyways.
+ // Will be overwritten anyways:
+ .next = nullptr,
};
::bow::add_object(system, objTmp);
objTmp = ::bow::Object {
.type = ::bow::ObjectType::World,
- .world_type = ::bow::World::Rocky_world,
+ .world_type = ::bow::World::RockyWorld,
.position = {
.x = 0x0p0,
.y = 0x1.F76F144Dp-1,
@@ -65,6 +66,7 @@ auto ::bow::generate_system(::bow::ObjectRoot& system, ::std::uint64_t const ide
.z = 0x1.31DB66BBp-15,
},
.mass = 0x1.931AFC649369998Fp-19,
+ .next = nullptr,
};
::bow::add_object(system, objTmp);
diff --git a/bowshock/source/save/continue_save.cxx b/bowshock/source/save/continue_save.cxx
index 38266d2..8bd56f5 100644
--- a/bowshock/source/save/continue_save.cxx
+++ b/bowshock/source/save/continue_save.cxx
@@ -1,13 +1,18 @@
// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+#include <bow/logic.hxx>
#include <bow/save.hxx>
+#include <array>
#include <cstdint>
#include <cstdio>
#include <fmt/core.h>
+#include <stdexcept>
#include <string>
-auto ::bow::continue_save(::bow::PlayerData& player_data, ::std::string path) noexcept -> void {
+auto ::bow::continue_save(::bow::PlayerData& player_data, ::std::string path) -> bool {
+ // Return true if save is invalid.
+
::fmt::print(stderr, "loading save file at \"{}\"\n", path);
::std::FILE* file = ::std::fopen(path.c_str(), "r");
@@ -15,33 +20,40 @@ auto ::bow::continue_save(::bow::PlayerData& player_data, ::std::string path) no
if (file == nullptr) [[unlikely]] {
::fmt::print(stderr, "unable to open save file\n");
- return ::bow::new_save(player_data);
+ ::bow::new_save(player_data);
+ return false;
}
- ::std::uint8_t raw_data[::bow::SAVE_LENGTH];
+ ::std::array<::std::uint8_t, ::bow::SAVE_LENGTH> raw;
+
+ if (::std::fread(raw.data(), 0x1u, ::bow::SAVE_LENGTH, file) < ::bow::SAVE_LENGTH) [[unlikely]] {
+ throw ::std::runtime_error {"unable to read save file"};
+ }
- ::std::fread(raw_data, 0x1u, ::bow::SAVE_LENGTH, file);
::std::fclose(file);
- ::bow::save_data data;
+ ::bow::SaveData data;
- ::bow::decode_save(data, raw_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);
+ return true;
}
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);
+ return true;
}
player_data = ::bow::PlayerData {
+ // Null-terminator is included:
+ .name = "\000\000\000\000\000\000\000\000\000\000\000\000\000",
.time = data.time,
.system_identifier = data.system_identifier,
.ship = {
+ .type = ::bow::ObjectType::Ship,
.ship_type = static_cast<::bow::Ship>(data.ship_type),
.position = {
.x = data.ship_position_x,
@@ -63,13 +75,16 @@ auto ::bow::continue_save(::bow::PlayerData& player_data, ::std::string path) no
.y = data.ship_rotational_velocity_y,
.z = data.ship_rotational_velocity_z,
},
+ .mass = ::bow::ship_mass(static_cast<::bow::Ship>(data.ship_type)),
+ .next = nullptr,
},
+ .zoom = 0x4p0,
};
::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);
+
+ return false;
}
diff --git a/bowshock/source/save/decode_save.cxx b/bowshock/source/save/decode_save.cxx
index 1bfe8cd..c2e3725 100644
--- a/bowshock/source/save/decode_save.cxx
+++ b/bowshock/source/save/decode_save.cxx
@@ -5,7 +5,7 @@
#include <cstdint>
#include <cstring>
-auto ::bow::decode_save(::bow::save_data& buffer, void const* data_pointer) noexcept -> void {
+auto ::bow::decode_save(::bow::SaveData& 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) {
diff --git a/bowshock/source/save/encode_save.cxx b/bowshock/source/save/encode_save.cxx
index db05735..db45bfe 100644
--- a/bowshock/source/save/encode_save.cxx
+++ b/bowshock/source/save/encode_save.cxx
@@ -5,7 +5,7 @@
#include <cstdint>
#include <cstring>
-auto ::bow::encode_save(void* const buffer_pointer, ::bow::save_data const& data) noexcept -> void {
+auto ::bow::encode_save(void* const buffer_pointer, ::bow::SaveData const& data) noexcept -> void {
auto buffer = reinterpret_cast<::std::uint8_t*>(buffer_pointer);
auto const encode_value = [&buffer]<typename T>(T const& val) {
diff --git a/bowshock/source/save/generate_data.cxx b/bowshock/source/save/generate_data.cxx
deleted file mode 100644
index 9cfd78a..0000000
--- a/bowshock/source/save/generate_data.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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
index a91d0e2..8d8b11d 100644
--- a/bowshock/source/save/new_save.cxx
+++ b/bowshock/source/save/new_save.cxx
@@ -1,18 +1,20 @@
// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+#include <bow/logic.hxx>
#include <bow/save.hxx>
#include <cstdio>
#include <fmt/core.h>
-auto ::bow::new_save(::bow::PlayerData& data) noexcept -> void {
+auto ::bow::new_save(::bow::PlayerData& buffer) noexcept -> void {
::fmt::print(stderr, "generating new save file\n");
- data = ::bow::PlayerData {
- .name = "Caelum\x00\x00\x00\x00\x00\x00\x00\x00",
+ buffer = ::bow::PlayerData {
+ .name = "Caelum\000\000\000\000\000\000\000\000",
.time = 0x0u, // 256 julian years after the Unix Epoch.
.system_identifier = 0x45u,
- .ship = {
+ .ship = {
+ .type = ::bow::ObjectType::Ship,
.ship_type = ::bow::Ship::Aquila,
.position = {
.x = 0x0p0,
@@ -34,9 +36,11 @@ auto ::bow::new_save(::bow::PlayerData& data) noexcept -> void {
.y = 0x0p0,
.z = 0x0p0,
},
+ .mass = ::bow::ship_mass(::bow::Ship::Aquila),
+ .next = nullptr,
},
+ .zoom = 0x4p0,
};
- ::bow::generate_data(data);
- ::fmt::print(stderr, "welcome, CMDR {}\n", data.name);
+ ::fmt::print(stderr, "welcome, CMDR {}\n", buffer.name);
}
diff --git a/bowshock/source/save/save.cxx b/bowshock/source/save/save.cxx
index ba104e2..f38c9ab 100644
--- a/bowshock/source/save/save.cxx
+++ b/bowshock/source/save/save.cxx
@@ -22,8 +22,10 @@ auto ::bow::save(::std::string const path, ::bow::PlayerData const& player_data)
::std::abort();
}
- ::bow::save_data save_data = {
+ ::bow::SaveData save_data = {
.format_version = ::bow::SAVE_VERSION,
+ // Null-terminator is included:
+ .commander_name = u8"\000\000\000\000\000\000\000\000\000\000\000\000\000",
.time = player_data.time,
.system_identifier = player_data.system_identifier,
.ship_type = static_cast<::std::uint8_t>(player_data.ship.ship_type),