Browse Source

Improve initialization logic

Provide default states for input and output.
feature/data-structs
TheoryOfNekomata 2 years ago
parent
commit
9417a20d9a
10 changed files with 127 additions and 84 deletions
  1. +2
    -2
      docs/reference/files/config.ini
  2. +3
    -1
      src/packages/game/input/IZ_joystick.c
  3. +23
    -17
      src/packages/game/input/IZ_joystick.h
  4. +2
    -1
      src/packages/game/input/IZ_keyboard.c
  5. +21
    -17
      src/packages/game/input/IZ_keyboard.h
  6. +2
    -1
      src/packages/game/input/IZ_midi.c
  7. +28
    -18
      src/packages/game/input/IZ_midi.h
  8. +10
    -10
      src/packages/game/input/input.test.c
  9. +22
    -15
      src/packages/game/output/IZ_video.c
  10. +14
    -2
      src/packages/game/output/IZ_video.h

+ 2
- 2
docs/reference/files/config.ini View File

@@ -1,6 +1,6 @@
[Video] [Video]
Width=640
Height=480
Width=320
Height=240
MaxFps=30 MaxFps=30
[Joystick.0.ControlMapping] [Joystick.0.ControlMapping]
Affirm=11 Affirm=11


+ 3
- 1
src/packages/game/input/IZ_joystick.c View File

@@ -101,7 +101,7 @@ void IZ_LoadJoystickConfig(const char* config_path, IZ_JoystickState(* state)[PL
state[player_index]->config.control_mapping[i] = ini_getl( state[player_index]->config.control_mapping[i] = ini_getl(
control_mapping_section_name, control_mapping_section_name,
ACTION_NAMES[i], ACTION_NAMES[i],
IZ_DEFAULT_JOYSTICK_CONTROLS[player_index][i],
IZ_DEFAULT_JOYSTICK_STATE[player_index].config.control_mapping[i],
config_path config_path
); );
} }
@@ -155,6 +155,8 @@ IZ_ProcedureResult IZ_SaveJoystickConfig(const char* config_path, IZ_JoystickSta
} }


IZ_ProcedureResult IZ_InitializeJoystickState(const char* config_path, IZ_JoystickState(* state)[PLAYERS]) { IZ_ProcedureResult IZ_InitializeJoystickState(const char* config_path, IZ_JoystickState(* state)[PLAYERS]) {
SDL_memcpy(state, &IZ_DEFAULT_JOYSTICK_STATE, sizeof(IZ_JoystickState));

IZ_LoadJoystickConfig(config_path, state); IZ_LoadJoystickConfig(config_path, state);
if (IZ_SaveJoystickConfig(config_path, state)) { if (IZ_SaveJoystickConfig(config_path, state)) {
return 1; return 1;


+ 23
- 17
src/packages/game/input/IZ_joystick.h View File

@@ -28,24 +28,30 @@ typedef struct {
IZ_JoystickConfig config; IZ_JoystickConfig config;
} IZ_JoystickState; } IZ_JoystickState;


static IZ_PadButton IZ_DEFAULT_JOYSTICK_CONTROLS[PLAYERS][CONTROLS] = {
static const IZ_JoystickState IZ_DEFAULT_JOYSTICK_STATE[PLAYERS] = {
{ {
255,
255,
255,
255,
11,
10,
1,
0,
4,
3,
6,
7,
8,
9,
13,
14,
.config = {
.control_mapping = {
255,
255,
255,
255,
11,
10,
1,
0,
4,
3,
6,
7,
8,
9,
13,
14,
},
.axis_threshold = 8000u,
.device_id = 0,
},
}, },
}; };




+ 2
- 1
src/packages/game/input/IZ_keyboard.c View File

@@ -51,7 +51,7 @@ void IZ_LoadKeyboardConfig(const char* config_path, IZ_KeyboardState(* state)[PL
ini_gets( ini_gets(
keyboard_section_name, keyboard_section_name,
ACTION_NAMES[i], ACTION_NAMES[i],
SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_CONTROLS[player_index][i]),
SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_STATE[player_index].config.control_mapping[i]),
buffer, buffer,
128, 128,
config_path config_path
@@ -63,6 +63,7 @@ void IZ_LoadKeyboardConfig(const char* config_path, IZ_KeyboardState(* state)[PL
} }


IZ_ProcedureResult IZ_InitializeKeyboardState(const char* config_path, IZ_KeyboardState(* state)[PLAYERS]) { IZ_ProcedureResult IZ_InitializeKeyboardState(const char* config_path, IZ_KeyboardState(* state)[PLAYERS]) {
SDL_memcpy(state, &IZ_DEFAULT_KEYBOARD_STATE, sizeof(IZ_KeyboardState));
IZ_LoadKeyboardConfig(config_path, state); IZ_LoadKeyboardConfig(config_path, state);
return IZ_SaveKeyboardConfig(config_path, state); return IZ_SaveKeyboardConfig(config_path, state);
} }

+ 21
- 17
src/packages/game/input/IZ_keyboard.h View File

@@ -14,24 +14,28 @@ typedef struct {
IZ_KeyboardConfig config; IZ_KeyboardConfig config;
} IZ_KeyboardState; } IZ_KeyboardState;


static const SDL_KeyCode IZ_DEFAULT_KEYBOARD_CONTROLS[PLAYERS][CONTROLS] = {
static const IZ_KeyboardState IZ_DEFAULT_KEYBOARD_STATE[PLAYERS] = {
{ {
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
.config = {
.control_mapping = {
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
},
},
}, },
}; };




+ 2
- 1
src/packages/game/input/IZ_midi.c View File

@@ -147,7 +147,7 @@ void IZ_LoadMIDIInputConfig(const char* config_path, IZ_MIDIInputState(* state)[
ini_gets( ini_gets(
control_mapping_section_name, control_mapping_section_name,
ACTION_NAMES[i], ACTION_NAMES[i],
IZ_GetMIDINoteName(IZ_DEFAULT_MIDI_INPUT_CONTROLS[player_index][i]),
IZ_GetMIDINoteName(IZ_DEFAULT_MIDI_INPUT_STATE[player_index].config.control_mapping[i]),
buffer, buffer,
128, 128,
config_path config_path
@@ -167,6 +167,7 @@ IZ_ProcedureResult IZ_InitializeMIDIInput(const char* config_path, IZ_MIDIInputS
return 1; return 1;
} }


SDL_memcpy(state, &IZ_DEFAULT_MIDI_INPUT_STATE, sizeof(IZ_MIDIInputState));
IZ_LoadMIDIInputConfig(config_path, state); IZ_LoadMIDIInputConfig(config_path, state);
if (IZ_SaveMIDIInputConfig(config_path, state)) { if (IZ_SaveMIDIInputConfig(config_path, state)) {
return 2; return 2;


+ 28
- 18
src/packages/game/input/IZ_midi.h View File

@@ -1,6 +1,7 @@
#ifndef IZ_MIDI_H #ifndef IZ_MIDI_H
#define IZ_MIDI_H #define IZ_MIDI_H


#include <SDL_stdinc.h>
#include <string.h> #include <string.h>
#include <portmidi.h> #include <portmidi.h>
#include <minIni.h> #include <minIni.h>
@@ -27,25 +28,34 @@ typedef struct {
PmEvent event_buffer[MIDI_EVENT_BUFFER_SIZE]; PmEvent event_buffer[MIDI_EVENT_BUFFER_SIZE];
} IZ_MIDIInputState; } IZ_MIDIInputState;


static const IZ_MIDINote IZ_DEFAULT_MIDI_INPUT_CONTROLS[PLAYERS][CONTROLS] = {
static const IZ_MIDIInputState IZ_DEFAULT_MIDI_INPUT_STATE[PLAYERS] = {
{ {
70,
72,
71,
69,
65,
64,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
}
.config = {
.control_mapping = {
70,
72,
71,
69,
65,
64,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
},
.device_id = 0,
.channel = 0,
},
.event_buffer = {},
.stream = NULL,
.device_info = NULL,
},
}; };


IZ_ProcedureResult IZ_SaveMIDIInputConfig(const char*, IZ_MIDIInputState(*)[PLAYERS]); IZ_ProcedureResult IZ_SaveMIDIInputConfig(const char*, IZ_MIDIInputState(*)[PLAYERS]);


+ 10
- 10
src/packages/game/input/input.test.c View File

@@ -228,8 +228,8 @@ spec("input") {
for (uint8_t i = 4; i < CONTROLS; i += 1) { for (uint8_t i = 4; i < CONTROLS; i += 1) {
it("handles %s action activation", ACTION_NAMES[i]) { it("handles %s action activation", ACTION_NAMES[i]) {
e.type = SDL_JOYBUTTONDOWN; e.type = SDL_JOYBUTTONDOWN;
e.jbutton.button = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i];
e.jbutton.button = IZ_DEFAULT_JOYSTICK_STATE[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[0][i];
action = 0; action = 0;


IZ_HandleJoystickEvents(e, &state, &action); IZ_HandleJoystickEvents(e, &state, &action);
@@ -241,8 +241,8 @@ spec("input") {


it("handles %s action deactivation", ACTION_NAMES[i]) { it("handles %s action deactivation", ACTION_NAMES[i]) {
e.type = SDL_JOYBUTTONUP; e.type = SDL_JOYBUTTONUP;
e.jbutton.button = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i];
e.jbutton.button = IZ_DEFAULT_JOYSTICK_STATE[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[0][i];
action = ~0; action = ~0;


IZ_HandleJoystickEvents(e, &state, &action); IZ_HandleJoystickEvents(e, &state, &action);
@@ -285,7 +285,7 @@ spec("input") {


before_each() { before_each() {
for (uint8_t i = 0; i < CONTROLS; i += 1) { for (uint8_t i = 0; i < CONTROLS; i += 1) {
config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i];
config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_STATE[0][i];
} }
} }


@@ -313,8 +313,8 @@ spec("input") {
for (uint8_t i = 0; i < CONTROLS; i += 1) { for (uint8_t i = 0; i < CONTROLS; i += 1) {
it("handles %s action activation", ACTION_NAMES[i]) { it("handles %s action activation", ACTION_NAMES[i]) {
e.type = SDL_KEYDOWN; e.type = SDL_KEYDOWN;
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i];
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_STATE[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[0][i];
action = 0; action = 0;


IZ_HandleKeyboardEvents(e, &state, &action); IZ_HandleKeyboardEvents(e, &state, &action);
@@ -326,8 +326,8 @@ spec("input") {


it("handles %s action deactivation", ACTION_NAMES[i]) { it("handles %s action deactivation", ACTION_NAMES[i]) {
e.type = SDL_KEYUP; e.type = SDL_KEYUP;
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i];
e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_STATE[0][i];
state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[0][i];
action = ~0; action = ~0;


IZ_HandleKeyboardEvents(e, &state, &action); IZ_HandleKeyboardEvents(e, &state, &action);
@@ -369,7 +369,7 @@ spec("input") {


before_each() { before_each() {
for (uint8_t i = 0; i < CONTROLS; i += 1) { for (uint8_t i = 0; i < CONTROLS; i += 1) {
config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i];
config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_STATE[0][i];
} }
} }




+ 22
- 15
src/packages/game/output/IZ_video.c View File

@@ -15,13 +15,13 @@ IZ_ProcedureResult IZ_SaveVideoConfig(const char* config_path, IZ_VideoConfig* c
} }


void IZ_LoadVideoConfig(const char* config_path, IZ_VideoConfig* config) { void IZ_LoadVideoConfig(const char* config_path, IZ_VideoConfig* config) {
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);
config->width = ini_getl("Video", "Width", IZ_DEFAULT_VIDEO_STATE.config.width, config_path);
config->height = ini_getl("Video", "Height", IZ_DEFAULT_VIDEO_STATE.config.height, config_path);
config->max_fps = ini_getl("Video", "MaxFps", IZ_DEFAULT_VIDEO_STATE.config.max_fps, config_path);
} }


IZ_ProcedureResult IZ_InitializeVideo(const char* config_path, IZ_VideoState* state) { IZ_ProcedureResult IZ_InitializeVideo(const char* config_path, IZ_VideoState* state) {
*state = (IZ_VideoState) {};
SDL_memcpy(state, &IZ_DEFAULT_VIDEO_STATE, sizeof(IZ_VideoState));


IZ_LoadVideoConfig(config_path, &state->config); IZ_LoadVideoConfig(config_path, &state->config);
if (IZ_SaveVideoConfig(config_path, &state->config)) { if (IZ_SaveVideoConfig(config_path, &state->config)) {
@@ -42,7 +42,7 @@ IZ_ProcedureResult IZ_InitializeVideo(const char* config_path, IZ_VideoState* st
return 1; return 1;
} }
state->window = window; state->window = window;
state->surface = SDL_GetWindowSurface(window);
state->renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);


return 0; return 0;
} }
@@ -50,22 +50,28 @@ IZ_ProcedureResult IZ_InitializeVideo(const char* config_path, IZ_VideoState* st
void IZ_UpdateVideo(IZ_VideoState* video_state, IZ_InputState* input_states, uint64_t ticks) { void IZ_UpdateVideo(IZ_VideoState* video_state, IZ_InputState* input_states, uint64_t ticks) {
if (ticks - video_state->last_update_at > 1000 / video_state->config.max_fps) { if (ticks - video_state->last_update_at > 1000 / video_state->config.max_fps) {
// Update window // Update window
SDL_FillRect(video_state->surface, NULL, SDL_MapRGB(video_state->surface->format, 0x00, 0x00, 0x00));
SDL_SetRenderDrawColor(video_state->renderer, 0x00, 0x00, 0x00, 0xff);
SDL_RenderClear(video_state->renderer);

SDL_SetRenderDrawColor(video_state->renderer, 0x00, 0xff, 0xff, 0xff);
uint64_t the_ticks = ticks;
for (uint8_t i = 0; i < 64; i += 1) { for (uint8_t i = 0; i < 64; i += 1) {
const uint8_t column = (64 - i) % 32;
const uint8_t column = i % 32;
const uint8_t row = i / 32; const uint8_t row = i / 32;
const uint64_t bitflag = (0x1lu << i);
const uint8_t size = 4; const uint8_t size = 4;
if (ticks & bitflag) {
SDL_FillRect(video_state->surface, &(SDL_Rect) {
column * size,

if (the_ticks & 0x1) {
SDL_RenderFillRectF(video_state->renderer, &(SDL_FRect) {
video_state->config.width - ((column + 1) * size),
video_state->config.height - ((row + 1) * size), video_state->config.height - ((row + 1) * size),
size, size,
size size
}, SDL_MapRGB(video_state->surface->format, 0x00, 0xff, 0xff));
});
} }
the_ticks >>= 1;
} }


SDL_SetRenderDrawColor(video_state->renderer, 0xff, 0xff, 0x00, 0xff);
// TODO refer to app's state // TODO refer to app's state
for (uint8_t p = 0; p < PLAYERS; p += 1) { for (uint8_t p = 0; p < PLAYERS; p += 1) {
for (uint8_t i = 0; i < CONTROLS; i += 1) { for (uint8_t i = 0; i < CONTROLS; i += 1) {
@@ -74,16 +80,17 @@ void IZ_UpdateVideo(IZ_VideoState* video_state, IZ_InputState* input_states, uin
const IZ_Action bitflag = (0x1 << i); const IZ_Action bitflag = (0x1 << i);
const uint8_t size = 4; const uint8_t size = 4;
if (input_states->action[p] & bitflag) { if (input_states->action[p] & bitflag) {
SDL_FillRect(video_state->surface, &(SDL_Rect) {
SDL_RenderFillRectF(video_state->renderer, &(SDL_FRect) {
column * size, column * size,
row * size, row * size,
size, size,
size size
}, SDL_MapRGB(video_state->surface->format, 0xff, 0xff, 0x00));
});
} }
} }
} }
SDL_UpdateWindowSurface(video_state->window);

SDL_RenderPresent(video_state->renderer);
video_state->last_update_at = ticks; video_state->last_update_at = ticks;
} }
} }


+ 14
- 2
src/packages/game/output/IZ_video.h View File

@@ -4,6 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <minIni.h> #include <minIni.h>
#include <SDL_video.h> #include <SDL_video.h>
#include <SDL_render.h>


// TODO move this out from video, refer to app's state instead // TODO move this out from video, refer to app's state instead
#include "../input/IZ_input.h" #include "../input/IZ_input.h"
@@ -12,7 +13,7 @@


typedef struct { typedef struct {
uint16_t width; uint16_t width;
uint16_t height;
uint16_t height;
uint8_t max_fps; uint8_t max_fps;
} IZ_VideoConfig; } IZ_VideoConfig;


@@ -20,9 +21,20 @@ typedef struct {
IZ_VideoConfig config; IZ_VideoConfig config;
uint64_t last_update_at; uint64_t last_update_at;
SDL_Window* window; SDL_Window* window;
SDL_Surface* surface;
SDL_Renderer* renderer;
} IZ_VideoState; } IZ_VideoState;


static const IZ_VideoState IZ_DEFAULT_VIDEO_STATE = {
.config = {
.width = 320u,
.height = 240u,
.max_fps = 30u,
},
.last_update_at = 0,
.renderer = NULL,
.window = NULL,
};

IZ_ProcedureResult IZ_InitializeVideo(const char*, IZ_VideoState*); IZ_ProcedureResult IZ_InitializeVideo(const char*, IZ_VideoState*);


IZ_ProcedureResult IZ_SaveVideoConfig(const char*, IZ_VideoConfig*); IZ_ProcedureResult IZ_SaveVideoConfig(const char*, IZ_VideoConfig*);


Loading…
Cancel
Save