From 656bcf026028cc396b50f35e6a4bec8523b5ad60 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Wed, 18 May 2022 10:35:54 +0800 Subject: [PATCH] Isolate input/output handling Make device handling opt-in. --- CMakeLists.txt | 18 +-- dependencies.txt | 1 + docs/reference/files/config.ini | 21 +++- src/packages/game/IZ_app.c | 14 ++- src/packages/game/IZ_app.h | 12 +- src/packages/game/IZ_common.h | 2 + src/packages/game/IZ_config.c | 8 ++ src/packages/game/IZ_config.h | 9 ++ src/packages/game/config/IZ_config.c | 65 ----------- src/packages/game/config/IZ_config.h | 86 --------------- src/packages/game/input/IZ_joystick.c | 103 ++++++++++++++++++ src/packages/game/input/IZ_joystick.h | 50 +++++++++ src/packages/game/input/IZ_keyboard.c | 47 ++++++++ src/packages/game/input/IZ_keyboard.h | 45 ++++++++ src/packages/game/main.c | 99 +++-------------- .../output/IZ_config.test.c} | 19 +--- src/packages/game/output/IZ_video.c | 19 ++++ src/packages/game/output/IZ_video.h | 18 +++ src/packages/test/IZ_mock.h | 14 +++ 19 files changed, 379 insertions(+), 271 deletions(-) create mode 100644 src/packages/game/IZ_config.c create mode 100644 src/packages/game/IZ_config.h delete mode 100644 src/packages/game/config/IZ_config.c delete mode 100644 src/packages/game/config/IZ_config.h create mode 100644 src/packages/game/input/IZ_joystick.c create mode 100644 src/packages/game/input/IZ_joystick.h create mode 100644 src/packages/game/input/IZ_keyboard.c create mode 100644 src/packages/game/input/IZ_keyboard.h rename src/packages/{game-test/config/IZ_config.c => game/output/IZ_config.test.c} (88%) create mode 100644 src/packages/game/output/IZ_video.c create mode 100644 src/packages/game/output/IZ_video.h create mode 100644 src/packages/test/IZ_mock.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e4efedb..18fd467 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) # Set your project name here project(izanagi C) @@ -9,6 +9,7 @@ include_directories( "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" + "${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" ) if (WIN32) @@ -21,20 +22,21 @@ endif () link_directories( "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" + "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release" ) add_executable( game dependencies/minIni/dev/minIni.h dependencies/minIni/dev/minIni.c - src/packages/game/config/IZ_config.h - src/packages/game/config/IZ_config.c + src/packages/game/output/IZ_video.h + src/packages/game/output/IZ_video.c src/packages/game/IZ_common.h src/packages/game/IZ_action.h src/packages/game/IZ_app.h src/packages/game/IZ_app.c src/packages/game/main.c -) + src/packages/game/input/IZ_joystick.c src/packages/game/input/IZ_joystick.h src/packages/game/input/IZ_keyboard.c src/packages/game/input/IZ_keyboard.h src/packages/game/IZ_config.c src/packages/game/IZ_config.h) target_link_libraries( game SDL2main @@ -43,11 +45,11 @@ target_link_libraries( add_executable( game-test - src/packages/game/config/IZ_config.h - src/packages/game/config/IZ_config.c dependencies/bdd-for-c/bdd-for-c.h - src/packages/game-test/config/IZ_config.c -) + src/packages/game/output/IZ_video.h + src/packages/game/output/IZ_video.c + src/packages/game/output/IZ_config.test.c + src/packages/test/IZ_mock.h) if (WIN32) add_custom_command(TARGET game POST_BUILD diff --git a/dependencies.txt b/dependencies.txt index 7837476..903de93 100644 --- a/dependencies.txt +++ b/dependencies.txt @@ -1,2 +1,3 @@ https://github.com/compuphase/minIni https://github.com/grassator/bdd-for-c +https://github.com/PortMidi/portmidi diff --git a/docs/reference/files/config.ini b/docs/reference/files/config.ini index 4c793cc..768586f 100644 --- a/docs/reference/files/config.ini +++ b/docs/reference/files/config.ini @@ -1,12 +1,12 @@ [Video] Width=640 Height=480 - -[Controls.0.Keyboard] +MaxFps=30 +[Keyboard.0.ControlMapping] +Up=Up Right=Right Down=Down Left=Left -Up=Up Affirm=Return Negate=Backspace Action0=A @@ -19,3 +19,18 @@ Action6=C Action7=V Action8=W Action9=E +[Joystick.0.ControlMapping] +Affirm=11 +Negate=10 +Action0=1 +Action1=0 +Action2=4 +Action3=3 +Action4=6 +Action5=7 +Action6=8 +Action7=9 +Action8=13 +Action9=14 +[Joystick.0] +AxisThreshold=8000 diff --git a/src/packages/game/IZ_app.c b/src/packages/game/IZ_app.c index 786deda..5d7fead 100644 --- a/src/packages/game/IZ_app.c +++ b/src/packages/game/IZ_app.c @@ -1,15 +1,19 @@ #include "IZ_app.h" int IZ_InitializeApp(IZ_App* app) { - IZ_LoadConfig(&app->config); - IZ_SaveConfig(&app->config); + IZ_LoadVideoConfig(&app->video_config); + IZ_SaveVideoConfig(&app->video_config); + app->video_update_at = 0u; for (uint8_t p = 0; p < PLAYERS; p += 1) { - app->assigned_joysticks[p] = NULL; + IZ_LoadKeyboardConfig(&app->keyboard_state->config, p); + IZ_SaveKeyboardConfig(&app->keyboard_state->config, p); + + IZ_LoadJoystickConfig(&app->joystick_state->config, p); + IZ_SaveJoystickConfig(&app->joystick_state->config, p); + app->actions[p] = 0; } - app->video_update_at = 0u; - return 0; } diff --git a/src/packages/game/IZ_app.h b/src/packages/game/IZ_app.h index 9ac3f5c..4a3eff0 100644 --- a/src/packages/game/IZ_app.h +++ b/src/packages/game/IZ_app.h @@ -1,17 +1,17 @@ #ifndef IZ_APP_H #define IZ_APP_H -#include - -#include "config/IZ_config.h" +#include "input/IZ_keyboard.h" +#include "input/IZ_joystick.h" +#include "output/IZ_video.h" #include "IZ_action.h" typedef struct { - IZ_Config config; + IZ_VideoConfig video_config; IZ_Action actions[PLAYERS]; - - SDL_Joystick* assigned_joysticks[PLAYERS]; + IZ_KeyboardState keyboard_state[PLAYERS]; + IZ_JoystickState joystick_state[PLAYERS]; uint64_t video_update_at; } IZ_App; diff --git a/src/packages/game/IZ_common.h b/src/packages/game/IZ_common.h index 9649560..a0d26ec 100644 --- a/src/packages/game/IZ_common.h +++ b/src/packages/game/IZ_common.h @@ -8,4 +8,6 @@ static const char* APP_NAME = "SDL2"; +typedef uint8_t IZ_ProcedureResult; + #endif diff --git a/src/packages/game/IZ_config.c b/src/packages/game/IZ_config.c new file mode 100644 index 0000000..f1dda1f --- /dev/null +++ b/src/packages/game/IZ_config.c @@ -0,0 +1,8 @@ +#include "IZ_config.h" + +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"); +} diff --git a/src/packages/game/IZ_config.h b/src/packages/game/IZ_config.h new file mode 100644 index 0000000..10fb5b6 --- /dev/null +++ b/src/packages/game/IZ_config.h @@ -0,0 +1,9 @@ +#ifndef IZ_CONFIG_H +#define IZ_CONFIG_H + +#include +#include + +void IZ_GetConfigPath(char* config_path); + +#endif diff --git a/src/packages/game/config/IZ_config.c b/src/packages/game/config/IZ_config.c deleted file mode 100644 index 06683e7..0000000 --- a/src/packages/game/config/IZ_config.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "IZ_config.h" - -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"); -} - -void IZ_SaveConfig(IZ_Config* config) { - char config_path[128]; - IZ_GetConfigPath(config_path); - FILE* fp; - fopen_s(&fp, config_path, "w"); - fprintf_s(fp, "[Video]\n"); - fprintf_s(fp, "Width=%u\n", config->video.width); - fprintf_s(fp, "Height=%u\n", config->video.height); - fprintf_s(fp, "MaxFps=%u\n", config->video.max_fps); - fprintf_s(fp, "\n"); - - fprintf_s(fp, "[Input]\n"); - fprintf_s(fp, "GamepadAxisThreshold=%u\n", config->input.gamepad_axis_threshold); - fprintf_s(fp, "\n"); - - for (uint8_t p = 0; p < PLAYERS; p += 1) { - fprintf_s(fp, "[Controls.%u.Keyboard]\n", p); - for (uint8_t i = 0; i < CONTROLS; i += 1) { - fprintf_s(fp, "%s=%s\n", ACTION_NAMES[i], SDL_GetKeyName(config->controls[p].keyboard[i])); - } - - fprintf_s(fp, "\n"); - fprintf_s(fp, "[Controls.%u.Joystick]\n", p); - for (uint8_t i = 4; i < CONTROLS; i += 1) { - fprintf_s(fp, "%s=%d\n", ACTION_NAMES[i], config->controls[p].gamepad[i]); - } - } -} - -void IZ_LoadConfig(IZ_Config* config) { - char config_path[128]; - IZ_GetConfigPath(config_path); - config->video.width = ini_getl("Video", "Width", 640l, config_path); - config->video.height = ini_getl("Video", "Height", 480l, config_path); - config->video.max_fps = ini_getl("Video", "MaxFps", 30, config_path); - config->input.gamepad_axis_threshold = ini_getl("Input", "GamepadAxisThreshold", 8000, config_path); - char buffer[128]; - char keyboard_section_name[20] = "Controls.0.Keyboard"; - for (uint8_t p = 0; p < PLAYERS; p += 1) { - keyboard_section_name[9] = (char) (48 + p); - for (uint8_t i = 0; i < CONTROLS; i += 1) { - ini_gets(keyboard_section_name, ACTION_NAMES[i], SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_CONTROLS[p][i]), buffer, 128, - config_path); - config->controls[p].keyboard[i] = SDL_GetKeyFromName(buffer); - } - } - - char joystick_section_name[20] = "Controls.0.Joystick"; - for (uint8_t p = 0; p < PLAYERS; p += 1) { - joystick_section_name[9] = (char) (48 + p); - - for (uint8_t i = 4; i < CONTROLS; i += 1) { - config->controls[p].gamepad[i] = ini_getl(joystick_section_name, ACTION_NAMES[i], IZ_DEFAULT_JOYSTICK_CONTROLS[p][i], config_path); - } - } -} diff --git a/src/packages/game/config/IZ_config.h b/src/packages/game/config/IZ_config.h deleted file mode 100644 index 5b170e7..0000000 --- a/src/packages/game/config/IZ_config.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef IZ_CONFIG_H -#define IZ_CONFIG_H - -#include -#include -#include -#include -#include - -#include "../IZ_common.h" -#include "../IZ_action.h" - -typedef struct { - uint16_t width; - uint16_t height; - uint8_t max_fps; -} IZ_VideoConfig; - -typedef struct { - uint16_t gamepad_axis_threshold; -} IZ_InputConfig; - -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_InputConfig input; - IZ_ControlsConfig controls[PLAYERS]; -} IZ_Config; - -static const IZ_KeyCode IZ_DEFAULT_KEYBOARD_CONTROLS[PLAYERS][CONTROLS] = { - { - SDLK_UP, - SDLK_RIGHT, - SDLK_DOWN, - SDLK_LEFT, - SDLK_RETURN, // yes - SDLK_BACKSPACE, // no - SDLK_a, // action0 - SDLK_s, // action1 - SDLK_d, // action2 - SDLK_f, // action3 - SDLK_z, // action4 - SDLK_x, // action5 - SDLK_c, // action6 - SDLK_v, // action7 - SDLK_w, // action8 - SDLK_e, // action9 - }, -}; - -static const uint8_t IZ_DEFAULT_JOYSTICK_CONTROLS[PLAYERS][CONTROLS] = { - { - 255, - 255, - 255, - 255, - 11, - 10, - 1, - 0, - 4, - 3, - 6, - 7, - 8, - 9, - 13, - 14, - }, -}; - -void IZ_GetConfigPath(char* config_path); - -void IZ_SaveConfig(IZ_Config* config); - -void IZ_LoadConfig(IZ_Config* config); - -#endif diff --git a/src/packages/game/input/IZ_joystick.c b/src/packages/game/input/IZ_joystick.c new file mode 100644 index 0000000..25584f6 --- /dev/null +++ b/src/packages/game/input/IZ_joystick.c @@ -0,0 +1,103 @@ +#include "IZ_joystick.h" + +void IZ_HandleJoystickDeviceEvents(SDL_Event e, IZ_JoystickState* state) { + if (e.type == SDL_JOYDEVICEADDED) { + if (SDL_NumJoysticks() <= PLAYERS && !state->joystick_instance) { + state->joystick_instance = SDL_JoystickOpen(e.jdevice.which); + } + } + + if (e.type == SDL_JOYDEVICEREMOVED) { + if ( + state->joystick_instance + && SDL_JoystickInstanceID(state->joystick_instance) == e.jdevice.which + ) { + state->joystick_instance = NULL; + } + } +} + +void IZ_HandleJoystickAxisEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { + if (e.type == SDL_JOYAXISMOTION) { + if (e.jaxis.axis == 0 || e.jaxis.axis == 3) { + *action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); + *action &= ~(0x1 << IZ_ACTION_INDEX_LEFT); + if (e.jaxis.value > state->config.axis_threshold) { + *action |= (0x1 << IZ_ACTION_INDEX_RIGHT); + } else if (e.jaxis.value <= -state->config.axis_threshold) { + *action |= (0x1 << IZ_ACTION_INDEX_LEFT); + } + } + if (e.jaxis.axis == 1 || e.jaxis.axis == 4) { + *action &= ~(0x1 << IZ_ACTION_INDEX_UP); + *action &= ~(0x1 << IZ_ACTION_INDEX_DOWN); + if (e.jaxis.value > -state->config.axis_threshold) { + *action |= (0x1 << IZ_ACTION_INDEX_DOWN); + } else if (e.jaxis.value <= -state->config.axis_threshold) { + *action |= (0x1 << IZ_ACTION_INDEX_UP); + } + } + } +} + +void IZ_HandleJoystickHatEvents(SDL_Event e, IZ_Action* action) { + if (e.type == SDL_JOYHATMOTION) { + *action &= ~(0x1 << IZ_ACTION_INDEX_UP); + *action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); + *action &= ~(0x1 << IZ_ACTION_INDEX_DOWN); + *action &= ~(0x1 << IZ_ACTION_INDEX_LEFT); + if (e.jhat.value != 0) { + *action |= e.jhat.value; + } + } +} + +void IZ_HandleJoystickButtonEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { + for (uint8_t i = 4; i < CONTROLS; i += 1) { + if (e.jbutton.button == state->config.control_mapping[i]) { + const uint16_t bitflag = (0x1 << i); + if (e.type == SDL_JOYBUTTONDOWN) { + *action |= bitflag; + } else if (e.type == SDL_JOYBUTTONUP) { + *action &= ~bitflag; + } + } + } +} + +void IZ_HandleJoystickEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { + IZ_HandleJoystickDeviceEvents(e, state); + IZ_HandleJoystickAxisEvents(e, state, action); + IZ_HandleJoystickHatEvents(e, action); + IZ_HandleJoystickButtonEvents(e, state, action); +} + +void IZ_LoadJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; + joystick_control_mapping_section_name[9] = (char) (48 + p); + for (uint8_t i = 4; i < CONTROLS; i += 1) { + config->control_mapping[i] = ini_getl(joystick_control_mapping_section_name, ACTION_NAMES[i], IZ_DEFAULT_JOYSTICK_CONTROLS[p][i], config_path); + } + + char joystick_section_name[] = "Joystick.0"; + joystick_section_name[9] = (char) (48 + p); + config->axis_threshold = ini_getl(joystick_section_name, "AxisThreshold", 8000, config_path); +} + +void IZ_SaveJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; + joystick_control_mapping_section_name[9] = (char) (48 + p); + for (uint8_t i = 4; i < CONTROLS; i += 1) { + ini_putl(joystick_control_mapping_section_name, ACTION_NAMES[i], config->control_mapping[i], config_path); + } + + char joystick_section_name[] = "Joystick.0"; + joystick_section_name[9] = (char) (48 + p); + ini_putl(joystick_section_name, "AxisThreshold", config->axis_threshold, config_path); +} diff --git a/src/packages/game/input/IZ_joystick.h b/src/packages/game/input/IZ_joystick.h new file mode 100644 index 0000000..ce43f35 --- /dev/null +++ b/src/packages/game/input/IZ_joystick.h @@ -0,0 +1,50 @@ +#ifndef IZ_JOYSTICK_H +#define IZ_JOYSTICK_H + +#include +#include +#include +#include "../IZ_action.h" +#include "../IZ_config.h" + +typedef uint8_t IZ_PadButton; + +typedef struct { + uint16_t axis_threshold; + IZ_PadButton control_mapping[CONTROLS]; +} IZ_JoystickConfig; + +typedef struct { + SDL_Joystick* joystick_instance; + + IZ_JoystickConfig config; +} IZ_JoystickState; + +static IZ_PadButton IZ_DEFAULT_JOYSTICK_CONTROLS[PLAYERS][CONTROLS] = { + { + 255, + 255, + 255, + 255, + 11, + 10, + 1, + 0, + 4, + 3, + 6, + 7, + 8, + 9, + 13, + 14, + }, +}; + +void IZ_LoadJoystickConfig(IZ_JoystickConfig*, uint8_t); + +void IZ_SaveJoystickConfig(IZ_JoystickConfig*, uint8_t); + +void IZ_HandleJoystickEvents(SDL_Event, IZ_JoystickState*, IZ_Action*); + +#endif diff --git a/src/packages/game/input/IZ_keyboard.c b/src/packages/game/input/IZ_keyboard.c new file mode 100644 index 0000000..dd2a983 --- /dev/null +++ b/src/packages/game/input/IZ_keyboard.c @@ -0,0 +1,47 @@ +#include "IZ_keyboard.h" + +void IZ_HandleKeyboardEvents(SDL_Event e, IZ_KeyboardState* state, IZ_Action* action) { + for (uint8_t i = 0; i < CONTROLS; i += 1) { + if (e.key.keysym.sym == state->config.control_mapping[i]) { + const uint16_t bitflag = (0x1 << i); + if (e.type == SDL_KEYDOWN) { + *action |= bitflag; + } else if (e.type == SDL_KEYUP) { + *action &= ~bitflag; + } + } + } +} + +void IZ_SaveKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + char keyboard_section_name[] = "Keyboard.0.ControlMapping"; + keyboard_section_name[9] = (char) (48 + p); + + for (uint8_t i = 0; i < CONTROLS; i += 1) { + ini_puts(keyboard_section_name, ACTION_NAMES[i], SDL_GetKeyName(config->control_mapping[i]), config_path); + } +} + +void IZ_LoadKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + char buffer[128]; + char keyboard_section_name[] = "Keyboard.0.ControlMapping"; + keyboard_section_name[9] = (char) (48 + p); + for (uint8_t i = 0; i < CONTROLS; i += 1) { + ini_gets( + keyboard_section_name, + ACTION_NAMES[i], + SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_CONTROLS[p][i]), + buffer, + 128, + config_path + ); + + config->control_mapping[i] = SDL_GetKeyFromName(buffer); + } +} diff --git a/src/packages/game/input/IZ_keyboard.h b/src/packages/game/input/IZ_keyboard.h new file mode 100644 index 0000000..e023b73 --- /dev/null +++ b/src/packages/game/input/IZ_keyboard.h @@ -0,0 +1,45 @@ +#ifndef IZ_KEYBOARD_H +#define IZ_KEYBOARD_H + +#include +#include +#include +#include "../IZ_action.h" +#include "../IZ_config.h" + +typedef struct { + SDL_KeyCode control_mapping[CONTROLS]; +} IZ_KeyboardConfig; + +typedef struct { + IZ_KeyboardConfig config; +} IZ_KeyboardState; + +static const SDL_KeyCode IZ_DEFAULT_KEYBOARD_CONTROLS[PLAYERS][CONTROLS] = { + { + SDLK_UP, + SDLK_RIGHT, + SDLK_DOWN, + SDLK_LEFT, + SDLK_RETURN, // yes + SDLK_BACKSPACE, // no + SDLK_a, // action0 + SDLK_s, // action1 + SDLK_d, // action2 + SDLK_f, // action3 + SDLK_z, // action4 + SDLK_x, // action5 + SDLK_c, // action6 + SDLK_v, // action7 + SDLK_w, // action8 + SDLK_e, // action9 + }, +}; + +void IZ_LoadKeyboardConfig(IZ_KeyboardConfig*, uint8_t); + +void IZ_SaveKeyboardConfig(IZ_KeyboardConfig*, uint8_t); + +void IZ_HandleKeyboardEvents(SDL_Event, IZ_KeyboardState*, IZ_Action*); + +#endif diff --git a/src/packages/game/main.c b/src/packages/game/main.c index 55e5347..b56a220 100644 --- a/src/packages/game/main.c +++ b/src/packages/game/main.c @@ -11,7 +11,6 @@ int main(int argc, char* args[]) { IZ_App app; IZ_InitializeApp(&app); - if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER @@ -25,16 +24,14 @@ int main(int argc, char* args[]) { APP_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - app.config.video.width, - app.config.video.height, + app.video_config.width, + app.video_config.height, SDL_WINDOW_SHOWN ); - if (window == NULL) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); return -2; } - screen_surface = SDL_GetWindowSurface(window); bool quit = false; @@ -43,84 +40,20 @@ int main(int argc, char* args[]) { while (true) { uint64_t ticks = SDL_GetTicks64(); + // TODO do audio processing + + // TODO do networking? + + // process events while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; break; } - // Handle joystick events - for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { - if (e.type == SDL_JOYDEVICEADDED) { - if (SDL_NumJoysticks() <= PLAYERS && !app.assigned_joysticks[current_player]) { - app.assigned_joysticks[current_player] = SDL_JoystickOpen(e.jdevice.which); - } - } - - if (e.type == SDL_JOYDEVICEREMOVED) { - if ( - app.assigned_joysticks[current_player] - && SDL_JoystickInstanceID(app.assigned_joysticks[current_player]) == e.jdevice.which - ) { - app.assigned_joysticks[current_player] = NULL; - } - } - - if (e.type == SDL_JOYAXISMOTION) { - if (e.jaxis.axis == 0 || e.jaxis.axis == 3) { - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_LEFT); - if (e.jaxis.value > app.config.input.gamepad_axis_threshold) { - app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_RIGHT); - } else if (e.jaxis.value <= -app.config.input.gamepad_axis_threshold) { - app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_LEFT); - } - } - if (e.jaxis.axis == 1 || e.jaxis.axis == 4) { - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_UP); - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_DOWN); - if (e.jaxis.value > app.config.input.gamepad_axis_threshold) { - app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_DOWN); - } else if (e.jaxis.value <= -app.config.input.gamepad_axis_threshold) { - app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_UP); - } - } - } - - if (e.type == SDL_JOYHATMOTION) { - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_UP); - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_DOWN); - app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_LEFT); - if (e.jhat.value != 0) { - app.actions[current_player] |= e.jhat.value; - } - } - } - - // Handle keyboard events - for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { - for (uint8_t i = 0; i < CONTROLS; i += 1) { - if (e.key.keysym.sym == app.config.controls[current_player].keyboard[i]) { - const uint16_t bitflag = (0x1 << i); - if (e.type == SDL_KEYDOWN) { - app.actions[current_player] |= bitflag; - } else if (e.type == SDL_KEYUP) { - app.actions[current_player] &= ~bitflag; - } - } - - if (i >= 4) { - if (e.jbutton.button == app.config.controls[current_player].gamepad[i]) { - const uint16_t bitflag = (0x1 << i); - if (e.type == SDL_JOYBUTTONDOWN) { - app.actions[current_player] |= bitflag; - } else if (e.type == SDL_JOYBUTTONUP) { - app.actions[current_player] &= ~bitflag; - } - } - } - } + for (uint8_t p = 0; p < PLAYERS; p += 1) { + IZ_HandleJoystickEvents(e, &(app.joystick_state[p]), &app.actions[p]); + IZ_HandleKeyboardEvents(e, &(app.keyboard_state[p]), &app.actions[p]); } } @@ -128,10 +61,9 @@ int main(int argc, char* args[]) { break; } - if (ticks - app.video_update_at > 1000 / app.config.video.max_fps) { + if (ticks - app.video_update_at > 1000 / app.video_config.max_fps) { // Update window SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00)); - for (uint8_t i = 0; i < 64; i += 1) { const uint8_t column = (64 - i) % 32; const uint8_t row = i / 32; @@ -140,20 +72,20 @@ int main(int argc, char* args[]) { if (ticks & bitflag) { SDL_FillRect(screen_surface, &(SDL_Rect) { column * size, - app.config.video.height - ((row + 1) * size), + app.video_config.height - ((row + 1) * size), size, size }, SDL_MapRGB(screen_surface->format, 0x00, 0xff, 0xff)); } } - for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { + for (uint8_t p = 0; p < PLAYERS; p += 1) { for (uint8_t i = 0; i < CONTROLS; i += 1) { - const uint8_t column = i % 4; + const uint8_t column = (i % 4) + (p * 4); const uint8_t row = i / 4; const IZ_Action bitflag = (0x1 << i); const uint8_t size = 4; - if (app.actions[current_player] & bitflag) { + if (app.actions[p] & bitflag) { SDL_FillRect(screen_surface, &(SDL_Rect) { column * size, row * size, @@ -164,7 +96,6 @@ int main(int argc, char* args[]) { } } SDL_UpdateWindowSurface(window); - app.video_update_at = ticks; } } diff --git a/src/packages/game-test/config/IZ_config.c b/src/packages/game/output/IZ_config.test.c similarity index 88% rename from src/packages/game-test/config/IZ_config.c rename to src/packages/game/output/IZ_config.test.c index 6ca8537..590b5d7 100644 --- a/src/packages/game-test/config/IZ_config.c +++ b/src/packages/game/output/IZ_config.test.c @@ -1,15 +1,6 @@ -#include "bdd-for-c.h" -#include "../../game/config/IZ_config.h" - -#define mock_call_count_t uint8_t - -#define mock(X) static mock_call_count_t calls_##X = 0; - -#define mock_return(X) calls_##X += 1; return - -#define mock_reset(X) calls_##X = 0 - -#define mock_calls(X) ((mock_call_count_t) (calls_##X)) +#include +#include "../../test/IZ_mock.h" +#include "IZ_video.h" mock(SDL_GetBasePath) char* SDL_GetBasePath() { mock_return(SDL_GetBasePath) ""; @@ -68,7 +59,7 @@ spec("config") { } it("should load default config values") { - IZ_LoadConfig(&config); + IZ_LoadVideoConfig(&config); check( mock_calls(SDL_GetBasePath) > 0, @@ -100,7 +91,7 @@ spec("config") { ); check( - config.input.gamepad_axis_threshold == 8000, + config.input.axis_threshold == 8000, "Default value for Input.GamepadAxisThreshold is not loaded." ); diff --git a/src/packages/game/output/IZ_video.c b/src/packages/game/output/IZ_video.c new file mode 100644 index 0000000..cc50c71 --- /dev/null +++ b/src/packages/game/output/IZ_video.c @@ -0,0 +1,19 @@ +#include "IZ_video.h" + +void IZ_SaveVideoConfig(IZ_VideoConfig* config) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + ini_putl("Video", "Width", config->width, config_path); + ini_putl("Video", "Height", config->height, config_path); + ini_putl("Video", "MaxFps", config->max_fps, config_path); +} + +void IZ_LoadVideoConfig(IZ_VideoConfig* config) { + char config_path[128]; + IZ_GetConfigPath(config_path); + + config->width = ini_getl("Video", "Width", 640l, config_path); + config->height = ini_getl("Video", "Height", 480l, config_path); + config->max_fps = ini_getl("Video", "MaxFps", 30, config_path); +} diff --git a/src/packages/game/output/IZ_video.h b/src/packages/game/output/IZ_video.h new file mode 100644 index 0000000..8b8833b --- /dev/null +++ b/src/packages/game/output/IZ_video.h @@ -0,0 +1,18 @@ +#ifndef IZ_VIDEO_H +#define IZ_VIDEO_H + +#include +#include +#include "../IZ_config.h" + +typedef struct { + uint16_t width; + uint16_t height; + uint8_t max_fps; +} IZ_VideoConfig; + +void IZ_SaveVideoConfig(IZ_VideoConfig* config); + +void IZ_LoadVideoConfig(IZ_VideoConfig* config); + +#endif diff --git a/src/packages/test/IZ_mock.h b/src/packages/test/IZ_mock.h new file mode 100644 index 0000000..1ea5731 --- /dev/null +++ b/src/packages/test/IZ_mock.h @@ -0,0 +1,14 @@ +#ifndef IZ_MOCK_H +#define IZ_MOCK_H + +#define mock_call_count_t uint8_t + +#define mock(X) static mock_call_count_t calls_##X = 0; + +#define mock_return(X) calls_##X += 1; return + +#define mock_reset(X) calls_##X = 0 + +#define mock_calls(X) ((mock_call_count_t) (calls_##X)) + +#endif