@@ -1,6 +1,6 @@ | |||
[Video] | |||
Width=640 | |||
Height=480 | |||
Width=320 | |||
Height=240 | |||
MaxFps=30 | |||
[Joystick.0.ControlMapping] | |||
Affirm=11 | |||
@@ -101,7 +101,7 @@ void IZ_LoadJoystickConfig(const char* config_path, IZ_JoystickState(* state)[PL | |||
state[player_index]->config.control_mapping[i] = ini_getl( | |||
control_mapping_section_name, | |||
ACTION_NAMES[i], | |||
IZ_DEFAULT_JOYSTICK_CONTROLS[player_index][i], | |||
IZ_DEFAULT_JOYSTICK_STATE[player_index].config.control_mapping[i], | |||
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]) { | |||
SDL_memcpy(state, &IZ_DEFAULT_JOYSTICK_STATE, sizeof(IZ_JoystickState)); | |||
IZ_LoadJoystickConfig(config_path, state); | |||
if (IZ_SaveJoystickConfig(config_path, state)) { | |||
return 1; | |||
@@ -28,24 +28,30 @@ typedef struct { | |||
IZ_JoystickConfig config; | |||
} 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, | |||
}, | |||
}, | |||
}; | |||
@@ -51,7 +51,7 @@ void IZ_LoadKeyboardConfig(const char* config_path, IZ_KeyboardState(* state)[PL | |||
ini_gets( | |||
keyboard_section_name, | |||
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, | |||
128, | |||
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]) { | |||
SDL_memcpy(state, &IZ_DEFAULT_KEYBOARD_STATE, sizeof(IZ_KeyboardState)); | |||
IZ_LoadKeyboardConfig(config_path, state); | |||
return IZ_SaveKeyboardConfig(config_path, state); | |||
} |
@@ -14,24 +14,28 @@ typedef struct { | |||
IZ_KeyboardConfig config; | |||
} 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 | |||
}, | |||
}, | |||
}, | |||
}; | |||
@@ -147,7 +147,7 @@ void IZ_LoadMIDIInputConfig(const char* config_path, IZ_MIDIInputState(* state)[ | |||
ini_gets( | |||
control_mapping_section_name, | |||
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, | |||
128, | |||
config_path | |||
@@ -167,6 +167,7 @@ IZ_ProcedureResult IZ_InitializeMIDIInput(const char* config_path, IZ_MIDIInputS | |||
return 1; | |||
} | |||
SDL_memcpy(state, &IZ_DEFAULT_MIDI_INPUT_STATE, sizeof(IZ_MIDIInputState)); | |||
IZ_LoadMIDIInputConfig(config_path, state); | |||
if (IZ_SaveMIDIInputConfig(config_path, state)) { | |||
return 2; | |||
@@ -1,6 +1,7 @@ | |||
#ifndef IZ_MIDI_H | |||
#define IZ_MIDI_H | |||
#include <SDL_stdinc.h> | |||
#include <string.h> | |||
#include <portmidi.h> | |||
#include <minIni.h> | |||
@@ -27,25 +28,34 @@ typedef struct { | |||
PmEvent event_buffer[MIDI_EVENT_BUFFER_SIZE]; | |||
} 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]); | |||
@@ -228,8 +228,8 @@ spec("input") { | |||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||
it("handles %s action activation", ACTION_NAMES[i]) { | |||
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; | |||
IZ_HandleJoystickEvents(e, &state, &action); | |||
@@ -241,8 +241,8 @@ spec("input") { | |||
it("handles %s action deactivation", ACTION_NAMES[i]) { | |||
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; | |||
IZ_HandleJoystickEvents(e, &state, &action); | |||
@@ -285,7 +285,7 @@ spec("input") { | |||
before_each() { | |||
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) { | |||
it("handles %s action activation", ACTION_NAMES[i]) { | |||
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; | |||
IZ_HandleKeyboardEvents(e, &state, &action); | |||
@@ -326,8 +326,8 @@ spec("input") { | |||
it("handles %s action deactivation", ACTION_NAMES[i]) { | |||
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; | |||
IZ_HandleKeyboardEvents(e, &state, &action); | |||
@@ -369,7 +369,7 @@ spec("input") { | |||
before_each() { | |||
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]; | |||
} | |||
} | |||
@@ -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) { | |||
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) { | |||
*state = (IZ_VideoState) {}; | |||
SDL_memcpy(state, &IZ_DEFAULT_VIDEO_STATE, sizeof(IZ_VideoState)); | |||
IZ_LoadVideoConfig(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; | |||
} | |||
state->window = window; | |||
state->surface = SDL_GetWindowSurface(window); | |||
state->renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); | |||
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) { | |||
if (ticks - video_state->last_update_at > 1000 / video_state->config.max_fps) { | |||
// 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) { | |||
const uint8_t column = (64 - i) % 32; | |||
const uint8_t column = i % 32; | |||
const uint8_t row = i / 32; | |||
const uint64_t bitflag = (0x1lu << i); | |||
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), | |||
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 | |||
for (uint8_t p = 0; p < PLAYERS; p += 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 uint8_t size = 4; | |||
if (input_states->action[p] & bitflag) { | |||
SDL_FillRect(video_state->surface, &(SDL_Rect) { | |||
SDL_RenderFillRectF(video_state->renderer, &(SDL_FRect) { | |||
column * size, | |||
row * 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; | |||
} | |||
} | |||
@@ -4,6 +4,7 @@ | |||
#include <stdio.h> | |||
#include <minIni.h> | |||
#include <SDL_video.h> | |||
#include <SDL_render.h> | |||
// TODO move this out from video, refer to app's state instead | |||
#include "../input/IZ_input.h" | |||
@@ -12,7 +13,7 @@ | |||
typedef struct { | |||
uint16_t width; | |||
uint16_t height; | |||
uint16_t height; | |||
uint8_t max_fps; | |||
} IZ_VideoConfig; | |||
@@ -20,9 +21,20 @@ typedef struct { | |||
IZ_VideoConfig config; | |||
uint64_t last_update_at; | |||
SDL_Window* window; | |||
SDL_Surface* surface; | |||
SDL_Renderer* renderer; | |||
} 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_SaveVideoConfig(const char*, IZ_VideoConfig*); | |||