diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | .gitmodules | 6 | ||||
-rw-r--r-- | build.zig | 4 | ||||
m--------- | lib/ini | 0 | ||||
m--------- | lib/loca | 0 | ||||
m--------- | lib/zeal | 0 | ||||
-rw-r--r-- | src/Game.h | 4 | ||||
-rw-r--r-- | src/GameInitDispose.cpp | 82 | ||||
-rw-r--r-- | src/config.h | 21 | ||||
-rw-r--r-- | src/config.zig | 117 | ||||
-rw-r--r-- | src/main.zig | 20 |
11 files changed, 181 insertions, 74 deletions
diff --git a/.gitignore b/.gitignore index 2f12ded..21f8acc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ zig-cache/ zig-out/ -config.txt highscore.txt diff --git a/.gitmodules b/.gitmodules index e0c1036..1c3b457 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "lib/zeal"] path = lib/zeal url = https://git.sr.ht/~cnx/zeal +[submodule "lib/loca"] + path = lib/loca + url = https://git.sr.ht/~cnx/zig-loca +[submodule "lib/ini"] + path = lib/ini + url = https://github.com/ziglibs/ini diff --git a/build.zig b/build.zig index ada71ad..86a81db 100644 --- a/build.zig +++ b/build.zig @@ -26,7 +26,9 @@ pub fn build(b: *std.build.Builder) void { exe.addCSourceFile("src/Timer.cpp", &cxxflags); exe.addCSourceFile("src/Textures.cpp", &cxxflags); - exe.addPackage(.{ .name = "zeal", .path = "lib/zeal/src/main.zig" }); + exe.addPackage(.{ .name = "ini", .path = "lib/ini/src/ini.zig" }); + exe.addPackage(.{ .name = "loca", .path = "lib/loca/src/main.zig" }); + exe.addPackage(.{ .name = "zeal", .path = "lib/zeal/src/zeal.zig" }); exe.linkSystemLibrary("GL"); exe.linkSystemLibrary("GLU"); exe.linkSystemLibrary("SDL"); diff --git a/lib/ini b/lib/ini new file mode 160000 +Subproject cceafc18d7f72a532224be80b36ea1b3b9e2bfd diff --git a/lib/loca b/lib/loca new file mode 160000 +Subproject d88de4ac1b70517be1de905d62f11ae74353166 diff --git a/lib/zeal b/lib/zeal -Subproject a0238a32993194b121d2f32845e4a20c667b75f +Subproject 735e9aff1d1443abc8107a9895d4b71e43fdf63 diff --git a/src/Game.h b/src/Game.h index b4dbcc5..0d819c6 100644 --- a/src/Game.h +++ b/src/Game.h @@ -22,6 +22,8 @@ #ifndef BLACKSHADES_GAME_H #define BLACKSHADES_GAME_H +#include "config.h" + #ifdef __cplusplus #include <GL/gl.h> #include <GL/glu.h> @@ -205,7 +207,7 @@ typedef struct Game Game; #ifdef __cplusplus extern "C" { #endif // __cplusplus - Game* makeGame(); + Game* makeGame(struct Config config); void initGl(Game*); void initGame(Game*); void eventLoop(Game*); diff --git a/src/GameInitDispose.cpp b/src/GameInitDispose.cpp index 782cf6a..b208df5 100644 --- a/src/GameInitDispose.cpp +++ b/src/GameInitDispose.cpp @@ -22,6 +22,7 @@ #include <AL/alc.h> +#include "config.h" #include "Textures.h" #include "Game.h" @@ -57,9 +58,21 @@ extern int aimkey; extern int psychicaimkey; extern int psychickey; -Game* makeGame() +Game* makeGame(Config config) { - return new Game(); + auto game = new Game(); + game->screenwidth = config.screen_width; + game->screenheight = config.screen_height; + game->usermousesensitivity = config.mouse_sensitivity; + game->debug = config.debug; + game->vblsync = config.vsync; + blood = config.blood; + game->blurness = config.blur; + game->mainmenuness = config.menu; + game->customlevels = config.custom_levels; + game->musictoggle = config.music; + game->azertykeyboard = config.azerty; + return game; } void LoadSounds(bool musictoggle) @@ -1781,69 +1794,6 @@ void initGl(Game* game) // Config game->mousesensitivity = 1.0f; if (!game->initialized) { - ifstream ipstream {"config.txt"}; - // If no config, write one - if (!ipstream) { - ofstream opstream("config.txt"); - opstream << "Screenwidth:\n"; - opstream << (game->screenwidth = 640); - opstream << "\nScreenheight:\n"; - opstream << (game->screenheight = 480); - opstream << "\nMouse sensitivity:\n"; - opstream << (game->usermousesensitivity = 0.7f); - opstream << "\nShow fps and other info:\n"; - opstream << (game->debug = false); - opstream << "\nVBL sync:\n"; - opstream << (game->vblsync = true); - opstream << "\nBlood:\n"; - opstream << (blood = true); - opstream << "\nBlur:\n"; - opstream << (game->blurness = false); - opstream << "\nMain Menu:\n"; - opstream << (game->mainmenuness = true); - opstream << "\nCustom levels:\n"; - opstream << (game->customlevels = false); - opstream << "\nMusic:\n"; - opstream << (game->musictoggle = true); - opstream << "\azerty keyboard:\n"; - opstream << (game->azertykeyboard = false) << endl; - opstream.close(); - } else { - ipstream.ignore(256,'\n'); - ipstream >> game->screenwidth; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->screenheight; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->usermousesensitivity; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->debug; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->vblsync; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> blood; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->blurness; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->mainmenuness; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->customlevels; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->musictoggle; - ipstream.ignore(256,'\n'); - ipstream.ignore(256,'\n'); - ipstream >> game->azertykeyboard; - ipstream.close(); - } - // TODO: Read high score ifstream ipstream2 {"highscore.txt"}; if (!ipstream2) { @@ -1853,7 +1803,7 @@ void initGl(Game* game) opstream.close(); } else { ipstream2 >> game->highscore; - ipstream.ignore(256,'\n'); + ipstream2.ignore(256,'\n'); ipstream2 >> game->beatgame; ipstream2.close(); } diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..fa456b2 --- /dev/null +++ b/src/config.h @@ -0,0 +1,21 @@ +#ifndef BLACKSHADES_CONFIG_H +#define BLACKSHADES_CONFIG_H + +#include <stdbool.h> +#include <stdint.h> + +struct Config { + int screen_width; + int screen_height; + float mouse_sensitivity; + bool debug; + bool vsync; + bool blood; + bool blur; + bool menu; + bool custom_levels; + bool music; + bool azerty; +}; + +#endif // BLACKSHADES_CONFIG_H diff --git a/src/config.zig b/src/config.zig new file mode 100644 index 0000000..4bde82c --- /dev/null +++ b/src/config.zig @@ -0,0 +1,117 @@ +// Configuration parser +// Copyright (C) 2021 Nguyễn Gia Phong +// +// This file is part of Black Shades. +// +// Black Shades is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Black Shades is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Black Shades. If not, see <https://www.gnu.org/licenses/>. + +const Allocator = std.mem.Allocator; +const createFile = std.fs.createFileAbsolute; +const eql = std.mem.eql; +const ini = @import("ini"); +const join = std.fs.path.join; +const mkdir = std.os.mkdir; +const openFile = std.fs.openFileAbsolute; +const parseFloat = std.fmt.parseFloat; +const parseInt = std.fmt.parseInt; +const std = @import("std"); + +/// Game configuration. +pub const Config = extern struct { + screen_width: c_int = 640, + screen_height: c_int = 480, + mouse_sensitivity: f32 = 0.7, + debug: bool = false, + vsync: bool = true, + blood: bool = true, + blur: bool = false, + menu: bool = true, + custom_levels: bool = false, + music: bool = true, + azerty: bool = false, +}; + +/// Parse boolean values. +fn parseBool(s: []const u8) !bool { + if (eql(u8, s, "false")) + return false; + if (eql(u8, s, "true")) + return true; + return error.InvalidCharacter; +} + +/// Parse settings.ini in the given base directory. +pub fn parse(allocator: *Allocator, base_dir: []const u8) !Config { + const config_dir = try join(allocator, &.{ base_dir, "blackshades" }); + defer allocator.free(config_dir); + const path = try join(allocator, &.{ config_dir, "settings.ini" }); + defer allocator.free(path); + + var config = Config{}; + const input = openFile(path, .{}) catch { + mkdir(config_dir, 0o644) catch |err| switch (err) { + error.PathAlreadyExists => {}, + else => return err, + }; + const output = try createFile(path, .{}); + defer output.close(); + const writer = output.writer(); + try writer.print("screen width = {}\n", .{ config.screen_width }); + try writer.print("screen height = {}\n", .{ config.screen_height }); + try writer.print("mouse sensitivity = {d:.1}\n", + .{ config.mouse_sensitivity }); + try writer.print("debug = {}\n", .{ config.debug }); + try writer.print("vsync = {}\n", .{ config.vsync }); + try writer.print("blood = {}\n", .{ config.blood }); + try writer.print("blur = {}\n", .{ config.blur }); + try writer.print("menu = {}\n", .{ config.menu }); + try writer.print("custom levels = {}\n", .{ config.custom_levels }); + try writer.print("music = {}\n", .{ config.music }); + try writer.print("azerty = {}\n", .{ config.azerty }); + return config; + }; + defer input.close(); + + var parser = ini.parse(allocator, input.reader()); + defer parser.deinit(); + + while (try parser.next()) |record| + switch (record) { + .property => |kv| if (eql(u8, kv.key, "screen width")) { + config.screen_width = try parseInt(c_int, kv.value, 10); + } else if (eql(u8, kv.key, "screen height")) { + config.screen_height = try parseInt(c_int, kv.value, 10); + } else if (eql(u8, kv.key, "mouse_sensitivity")) { + config.mouse_sensitivity = try parseFloat(f32, kv.value); + } else if (eql(u8, kv.key, "debug")) { + config.debug = try parseBool(kv.value); + } else if (eql(u8, kv.key, "vsync")) { + config.vsync = try parseBool(kv.value); + } else if (eql(u8, kv.key, "blood")) { + config.blood = try parseBool(kv.value); + } else if (eql(u8, kv.key, "blur")) { + config.blur = try parseBool(kv.value); + } else if (eql(u8, kv.key, "menu")) { + config.menu = try parseBool(kv.value); + } else if (eql(u8, kv.key, "custom levels")) { + config.custom_levels = try parseBool(kv.value); + } else if (eql(u8, kv.key, "music")) { + config.music = try parseBool(kv.value); + } else if (eql(u8, kv.key, "azerty")) { + config.azerty = try parseBool(kv.value); + }, + else => unreachable, + }; + return config; +} diff --git a/src/main.zig b/src/main.zig index 34e3844..baca0e0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,14 +16,24 @@ // You should have received a copy of the GNU General Public License // along with Black Shades. If not, see <https://www.gnu.org/licenses/>. -const legacy = @cImport({ @cInclude("Game.h"); }); -const al = @import("zeal"); +const Loca = @import("loca").Loca; +const allocator = @import("std").heap.c_allocator; +const legacy = @cImport(@cInclude("Game.h")); +const configuration = @import("config.zig"); +const zeal = @import("zeal"); pub fn main() !void { - try al.init(null); - defer al.deinit() catch unreachable; + const loca = try Loca.init(allocator, .{}); + defer loca.deinit(); + const config = try configuration.parse(allocator, loca.user_config); - const game = legacy.makeGame(); + const device = try zeal.Device.init(null); + defer device.deinit() catch unreachable; + const context = try zeal.Context.init(device, &.{ }); + defer context.deinit() catch unreachable; + try zeal.useContext(context); + + const game = legacy.makeGame(@bitCast(legacy.Config, config)); legacy.initGl(game); legacy.initGame(game); defer legacy.closeGame(game); |