From aa41c57db67522d6cce99b014d477bf03d6cd051 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Mon, 9 May 2022 19:12:29 +0800 Subject: [PATCH] Add ini parser, setup custom config We use minIni to parse ini files instead of implementing our own. This is useful for config modifiable by the user, such as controls. However, we haven't implemented a fault-tolerant config that writes to the config when the existing file is corrupted or non-existent. We will have to define a "save" as soon as we have all values defined for our in-memory config, regardless if we have retrieved the values successfully or provided default hardcoded values. Since we use an external dependency to manage our configs, the CMake config must be modified and the source files included in the build. How do we organize the dependencies from other Git repositories moving forward? --- CMakeLists.txt | 17 ++++++- assets/config.ini | 21 +++++++++ dependencies.txt | 1 + src/packages/game/main.c | 96 ++++++++++++++++++++++++++++++++-------- 4 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 assets/config.ini create mode 100644 dependencies.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 90d8c05..fd5ad92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,10 @@ project(izanagi C) set(CMAKE_C_STANDARD 11) -include_directories("${PROJECT_SOURCE_DIR}/dependencies/SDL2/include") +include_directories( + "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" + "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" +) if (WIN32) if (CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -16,7 +19,12 @@ if (WIN32) endif () link_directories("${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}") -add_executable(izanagi src/packages/game/main.c) +add_executable( + izanagi + dependencies/minIni/dev/minIni.h + dependencies/minIni/dev/minIni.c + src/packages/game/main.c +) target_link_libraries(izanagi SDL2main SDL2) if (WIN32) @@ -25,3 +33,8 @@ if (WIN32) "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}/SDL2.dll" # <--this is in-file $) # <--this is out-file path endif () + +add_custom_command(TARGET izanagi POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${PROJECT_SOURCE_DIR}/assets/config.ini" # <--this is in-file + $) # <--this is out-file path \ No newline at end of file diff --git a/assets/config.ini b/assets/config.ini new file mode 100644 index 0000000..d18aa37 --- /dev/null +++ b/assets/config.ini @@ -0,0 +1,21 @@ +[Video] +Width=640 +Height=480 + +[Controls.0.Keyboard] +Right=Right +Down=Down +Left=Left +Up=Up +Affirm=Return +Negate=Backspace +Action0=A +Action1=S +Action2=D +Action3=F +Action4=Z +Action5=X +Action6=C +Action7=V +Action8=W +Action9=E diff --git a/dependencies.txt b/dependencies.txt new file mode 100644 index 0000000..b28f68d --- /dev/null +++ b/dependencies.txt @@ -0,0 +1 @@ +https://github.com/compuphase/minIni diff --git a/src/packages/game/main.c b/src/packages/game/main.c index a6c98aa..2f053a7 100644 --- a/src/packages/game/main.c +++ b/src/packages/game/main.c @@ -1,14 +1,14 @@ #include #include #include +#include +#include const char* APP_NAME = "SDL2"; -const unsigned int SCREEN_WIDTH = 640; -const unsigned int SCREEN_HEIGHT = 480; +static const unsigned char CONTROLS = 16; +static const unsigned char PLAYERS = 1; -const unsigned char CONTROLS = 16; - -const SDL_KeyCode KEYBOARD_CONTROLS[CONTROLS] = { +static const SDL_KeyCode KEYBOARD_CONTROLS[CONTROLS] = { SDLK_RIGHT, SDLK_DOWN, SDLK_LEFT, @@ -27,9 +27,69 @@ const SDL_KeyCode KEYBOARD_CONTROLS[CONTROLS] = { SDLK_e, // action9 }; +static const char* ACTION_NAMES[CONTROLS] = { + "Right", + "Down", + "Left", + "Up", + "Affirm", + "Negate", + "Action0", + "Action1", + "Action2", + "Action3", + "Action4", + "Action5", + "Action6", + "Action7", + "Action8", + "Action9", +}; + +typedef struct { + unsigned int width; + unsigned int height; +} IZ_VideoConfig; + +typedef SDL_KeyCode IZ_KeyCode; + +typedef int IZ_PadButton; + +typedef struct { + IZ_KeyCode keyboard[CONTROLS]; + IZ_PadButton gamepad[CONTROLS]; +} IZ_ControlsConfig; + +typedef struct { + IZ_VideoConfig video; + IZ_ControlsConfig controls[PLAYERS]; +} IZ_Config; + +static void IZ_GetConfigPath(char* config_path) { + //const char* config_path_dir = SDL_GetPrefPath("Modal Studios", APP_NAME); + const char* config_path_dir = SDL_GetBasePath(); + memcpy_s(config_path, 128, config_path_dir, 128); + strcat_s(config_path, 128, "config.ini"); +} + +static void IZ_LoadConfig(IZ_Config* config) { + static char config_path[128]; + IZ_GetConfigPath(config_path); + // TODO check if file exists first + config->video.width = ini_getl("Video", "Width", 640l, config_path); + config->video.height = ini_getl("Video", "Height", 480l, config_path); + char buffer[128]; + for (int i = 0; i < CONTROLS; i += 1) { + ini_gets("Controls.0.Keyboard", ACTION_NAMES[i], SDL_GetKeyName(KEYBOARD_CONTROLS[i]), buffer, 128, config_path); + config->controls[0].keyboard[i] = SDL_GetKeyFromName(buffer); + } +} + int main(int argc, char* args[]) { SDL_Window* window = NULL; - SDL_Surface* screenSurface = NULL; + SDL_Surface* screen_surface = NULL; + IZ_Config config; + IZ_LoadConfig(&config); if (SDL_Init( SDL_INIT_VIDEO @@ -42,10 +102,10 @@ int main(int argc, char* args[]) { window = SDL_CreateWindow( APP_NAME, - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - SCREEN_WIDTH, - SCREEN_HEIGHT, + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + config.video.width, + config.video.height, SDL_WINDOW_SHOWN ); @@ -56,11 +116,11 @@ int main(int argc, char* args[]) { bool quit = false; SDL_Event e; - screenSurface = SDL_GetWindowSurface(window); + screen_surface = SDL_GetWindowSurface(window); unsigned short action = 0; while (!quit) { - SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00)); + SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00)); uint64_t ticks = SDL_GetTicks64(); for (unsigned char i = 0; i < 64; i += 1) { const unsigned char column = (64 - i) % 32; @@ -68,12 +128,12 @@ int main(int argc, char* args[]) { const uint64_t bitflag = (0x1lu << i); const unsigned char size = 4; if (ticks & bitflag) { - SDL_FillRect(screenSurface, &(SDL_Rect) { + SDL_FillRect(screen_surface, &(SDL_Rect) { column * size, - SCREEN_HEIGHT - ((row + 1) * size), + config.video.height - ((row + 1) * size), size, size - }, SDL_MapRGB(screenSurface->format, 0x00, 0xff, 0xff)); + }, SDL_MapRGB(screen_surface->format, 0x00, 0xff, 0xff)); } } @@ -84,7 +144,7 @@ int main(int argc, char* args[]) { for (unsigned char i = 0; i < CONTROLS; i += 1) { // TODO do same for gamepad - if (e.key.keysym.sym == KEYBOARD_CONTROLS[i]) { + if (e.key.keysym.sym == config.controls[0].keyboard[i]) { const unsigned short bitflag = (0x1 << i); if (e.type == SDL_KEYDOWN) { action |= bitflag; @@ -100,12 +160,12 @@ int main(int argc, char* args[]) { const unsigned short bitflag = (0x1 << i); const unsigned char size = 4; if (action & bitflag) { - SDL_FillRect(screenSurface, &(SDL_Rect) { + SDL_FillRect(screen_surface, &(SDL_Rect) { column * size, row * size, size, size - }, SDL_MapRGB(screenSurface->format, 0xff, 0xff, 0x00)); + }, SDL_MapRGB(screen_surface->format, 0xff, 0xff, 0x00)); } }