Added optional OSD (SDL)
This commit is contained in:
parent
3ed18a76da
commit
ebb0cb5e81
67
SDL/gui.c
67
SDL/gui.c
@ -198,11 +198,13 @@ static void draw_char(uint32_t *buffer, unsigned width, unsigned height, unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
static signed scroll = 0;
|
static signed scroll = 0;
|
||||||
static void draw_unbordered_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, signed y, const char *string, uint32_t color)
|
static void draw_unbordered_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, signed y, const char *string, uint32_t color, bool is_osd)
|
||||||
{
|
{
|
||||||
y -= scroll;
|
if (!is_osd) {
|
||||||
|
y -= scroll;
|
||||||
|
}
|
||||||
unsigned orig_x = x;
|
unsigned orig_x = x;
|
||||||
unsigned y_offset = (GB_get_screen_height(&gb) - 144) / 2;
|
unsigned y_offset = is_osd? 0 : (GB_get_screen_height(&gb) - 144) / 2;
|
||||||
while (*string) {
|
while (*string) {
|
||||||
if (*string == '\n') {
|
if (*string == '\n') {
|
||||||
x = orig_x;
|
x = orig_x;
|
||||||
@ -215,21 +217,39 @@ static void draw_unbordered_text(uint32_t *buffer, unsigned width, unsigned heig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_char(&buffer[(signed)(x + width * y)], width, height, *string, color, &buffer[width * y_offset], &buffer[width * (y_offset + 144)]);
|
draw_char(&buffer[(signed)(x + width * y)], width, height, *string, color, &buffer[width * y_offset], &buffer[width * (is_osd? GB_get_screen_height(&gb) : y_offset + 144)]);
|
||||||
x += GLYPH_WIDTH;
|
x += GLYPH_WIDTH;
|
||||||
string++;
|
string++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, signed y, const char *string, uint32_t color, uint32_t border)
|
void draw_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, signed y, const char *string, uint32_t color, uint32_t border, bool is_osd)
|
||||||
{
|
{
|
||||||
draw_unbordered_text(buffer, width, height, x - 1, y, string, border);
|
draw_unbordered_text(buffer, width, height, x - 1, y, string, border, is_osd);
|
||||||
draw_unbordered_text(buffer, width, height, x + 1, y, string, border);
|
draw_unbordered_text(buffer, width, height, x + 1, y, string, border, is_osd);
|
||||||
draw_unbordered_text(buffer, width, height, x, y - 1, string, border);
|
draw_unbordered_text(buffer, width, height, x, y - 1, string, border, is_osd);
|
||||||
draw_unbordered_text(buffer, width, height, x, y + 1, string, border);
|
draw_unbordered_text(buffer, width, height, x, y + 1, string, border, is_osd);
|
||||||
draw_unbordered_text(buffer, width, height, x, y, string, color);
|
draw_unbordered_text(buffer, width, height, x, y, string, color, is_osd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *osd_text = NULL;
|
||||||
|
unsigned osd_countdown = 0;
|
||||||
|
unsigned osd_text_lines = 1;
|
||||||
|
|
||||||
|
void show_osd_text(const char *text)
|
||||||
|
{
|
||||||
|
osd_text_lines = 1;
|
||||||
|
osd_text = text;
|
||||||
|
osd_countdown = 30;
|
||||||
|
while (*text++) {
|
||||||
|
if (*text == '\n') {
|
||||||
|
osd_text_lines++;
|
||||||
|
osd_countdown += 30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum decoration {
|
enum decoration {
|
||||||
DECORATION_NONE,
|
DECORATION_NONE,
|
||||||
DECORATION_SELECTION,
|
DECORATION_SELECTION,
|
||||||
@ -239,14 +259,14 @@ enum decoration {
|
|||||||
static void draw_text_centered(uint32_t *buffer, unsigned width, unsigned height, unsigned y, const char *string, uint32_t color, uint32_t border, enum decoration decoration)
|
static void draw_text_centered(uint32_t *buffer, unsigned width, unsigned height, unsigned y, const char *string, uint32_t color, uint32_t border, enum decoration decoration)
|
||||||
{
|
{
|
||||||
unsigned x = width / 2 - (unsigned) strlen(string) * GLYPH_WIDTH / 2;
|
unsigned x = width / 2 - (unsigned) strlen(string) * GLYPH_WIDTH / 2;
|
||||||
draw_text(buffer, width, height, x, y, string, color, border);
|
draw_text(buffer, width, height, x, y, string, color, border, false);
|
||||||
switch (decoration) {
|
switch (decoration) {
|
||||||
case DECORATION_SELECTION:
|
case DECORATION_SELECTION:
|
||||||
draw_text(buffer, width, height, x - GLYPH_WIDTH, y, SELECTION_STRING, color, border);
|
draw_text(buffer, width, height, x - GLYPH_WIDTH, y, SELECTION_STRING, color, border, false);
|
||||||
break;
|
break;
|
||||||
case DECORATION_ARROWS:
|
case DECORATION_ARROWS:
|
||||||
draw_text(buffer, width, height, x - GLYPH_WIDTH, y, LEFT_ARROW_STRING, color, border);
|
draw_text(buffer, width, height, x - GLYPH_WIDTH, y, LEFT_ARROW_STRING, color, border, false);
|
||||||
draw_text(buffer, width, height, width - x, y, RIGHT_ARROW_STRING, color, border);
|
draw_text(buffer, width, height, width - x, y, RIGHT_ARROW_STRING, color, border, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DECORATION_NONE:
|
case DECORATION_NONE:
|
||||||
@ -743,7 +763,7 @@ static void cycle_filter_backwards(unsigned index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const char *current_filter_name(unsigned index)
|
static const char *current_filter_name(unsigned index)
|
||||||
{
|
{
|
||||||
if (!uses_gl()) return "Requires OpenGL 3.2+";
|
if (!uses_gl()) return "Requires OpenGL 3.2+";
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
@ -782,13 +802,24 @@ static void cycle_blending_mode_backwards(unsigned index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *blending_mode_string(unsigned index)
|
static const char *blending_mode_string(unsigned index)
|
||||||
{
|
{
|
||||||
if (!uses_gl()) return "Requires OpenGL 3.2+";
|
if (!uses_gl()) return "Requires OpenGL 3.2+";
|
||||||
return (const char *[]){"Disabled", "Simple", "Accurate"}
|
return (const char *[]){"Disabled", "Simple", "Accurate"}
|
||||||
[configuration.blending_mode];
|
[configuration.blending_mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void toggle_osd(unsigned index)
|
||||||
|
{
|
||||||
|
osd_countdown = 0;
|
||||||
|
configuration.osd = !configuration.osd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *current_osd_mode(unsigned index)
|
||||||
|
{
|
||||||
|
return configuration.osd? "Enabled" : "Disabled";
|
||||||
|
}
|
||||||
|
|
||||||
static const struct menu_item graphics_menu[] = {
|
static const struct menu_item graphics_menu[] = {
|
||||||
{"Scaling Mode:", cycle_scaling, current_scaling_mode, cycle_scaling_backwards},
|
{"Scaling Mode:", cycle_scaling, current_scaling_mode, cycle_scaling_backwards},
|
||||||
{"Default Window Scale:", cycle_default_scale, current_default_scale, cycle_default_scale_backwards},
|
{"Default Window Scale:", cycle_default_scale, current_default_scale, cycle_default_scale_backwards},
|
||||||
@ -798,6 +829,8 @@ static const struct menu_item graphics_menu[] = {
|
|||||||
{"Frame Blending:", cycle_blending_mode, blending_mode_string, cycle_blending_mode_backwards},
|
{"Frame Blending:", cycle_blending_mode, blending_mode_string, cycle_blending_mode_backwards},
|
||||||
{"Mono Palette:", cycle_palette, current_palette, cycle_palette_backwards},
|
{"Mono Palette:", cycle_palette, current_palette, cycle_palette_backwards},
|
||||||
{"Display Border:", cycle_border_mode, current_border_mode, cycle_border_mode_backwards},
|
{"Display Border:", cycle_border_mode, current_border_mode, cycle_border_mode_backwards},
|
||||||
|
{"On-Screen Display:", toggle_osd, current_osd_mode, toggle_osd},
|
||||||
|
|
||||||
{"Back", return_to_root_menu},
|
{"Back", return_to_root_menu},
|
||||||
{NULL,}
|
{NULL,}
|
||||||
};
|
};
|
||||||
@ -1574,7 +1607,7 @@ void run_gui(bool is_running)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHOWING_HELP:
|
case SHOWING_HELP:
|
||||||
draw_text(pixels, width, height, 2 + x_offset, 2 + y_offset, help[current_help_page], gui_palette_native[3], gui_palette_native[0]);
|
draw_text(pixels, width, height, 2 + x_offset, 2 + y_offset, help[current_help_page], gui_palette_native[3], gui_palette_native[0], false);
|
||||||
break;
|
break;
|
||||||
case WAITING_FOR_KEY:
|
case WAITING_FOR_KEY:
|
||||||
draw_text_centered(pixels, width, height, 68 + y_offset, "Press a Key", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE);
|
draw_text_centered(pixels, width, height, 68 + y_offset, "Press a Key", gui_palette_native[3], gui_palette_native[0], DECORATION_NONE);
|
||||||
|
@ -119,6 +119,9 @@ typedef struct {
|
|||||||
char bootrom_path[4096];
|
char bootrom_path[4096];
|
||||||
uint8_t interference_volume;
|
uint8_t interference_volume;
|
||||||
GB_rtc_mode_t rtc_mode;
|
GB_rtc_mode_t rtc_mode;
|
||||||
|
|
||||||
|
/* v0.14.4 */
|
||||||
|
bool osd;
|
||||||
} configuration_t;
|
} configuration_t;
|
||||||
|
|
||||||
extern configuration_t configuration;
|
extern configuration_t configuration;
|
||||||
@ -140,4 +143,10 @@ static SDL_Scancode event_hotkey_code(SDL_Event *event)
|
|||||||
return event->key.keysym.scancode;
|
return event->key.keysym.scancode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, signed y, const char *string, uint32_t color, uint32_t border, bool is_osd);
|
||||||
|
void show_osd_text(const char *text);
|
||||||
|
extern const char *osd_text;
|
||||||
|
extern unsigned osd_countdown;
|
||||||
|
extern unsigned osd_text_lines;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
60
SDL/main.c
60
SDL/main.c
@ -191,7 +191,7 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
open_menu();
|
open_menu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_JOYAXISMOTION: {
|
case SDL_JOYAXISMOTION: {
|
||||||
static bool axis_active[2] = {false, false};
|
static bool axis_active[2] = {false, false};
|
||||||
@ -231,22 +231,21 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION: {
|
||||||
{
|
|
||||||
uint8_t value = event.jhat.value;
|
uint8_t value = event.jhat.value;
|
||||||
int8_t updown =
|
int8_t updown =
|
||||||
value == SDL_HAT_LEFTUP || value == SDL_HAT_UP || value == SDL_HAT_RIGHTUP ? -1 : (value == SDL_HAT_LEFTDOWN || value == SDL_HAT_DOWN || value == SDL_HAT_RIGHTDOWN ? 1 : 0);
|
value == SDL_HAT_LEFTUP || value == SDL_HAT_UP || value == SDL_HAT_RIGHTUP ? -1 : (value == SDL_HAT_LEFTDOWN || value == SDL_HAT_DOWN || value == SDL_HAT_RIGHTDOWN ? 1 : 0);
|
||||||
int8_t leftright =
|
int8_t leftright =
|
||||||
value == SDL_HAT_LEFTUP || value == SDL_HAT_LEFT || value == SDL_HAT_LEFTDOWN ? -1 : (value == SDL_HAT_RIGHTUP || value == SDL_HAT_RIGHT || value == SDL_HAT_RIGHTDOWN ? 1 : 0);
|
value == SDL_HAT_LEFTUP || value == SDL_HAT_LEFT || value == SDL_HAT_LEFTDOWN ? -1 : (value == SDL_HAT_RIGHTUP || value == SDL_HAT_RIGHT || value == SDL_HAT_RIGHTDOWN ? 1 : 0);
|
||||||
|
|
||||||
GB_set_key_state(gb, GB_KEY_LEFT, leftright == -1);
|
GB_set_key_state(gb, GB_KEY_LEFT, leftright == -1);
|
||||||
GB_set_key_state(gb, GB_KEY_RIGHT, leftright == 1);
|
GB_set_key_state(gb, GB_KEY_RIGHT, leftright == 1);
|
||||||
GB_set_key_state(gb, GB_KEY_UP, updown == -1);
|
GB_set_key_state(gb, GB_KEY_UP, updown == -1);
|
||||||
GB_set_key_state(gb, GB_KEY_DOWN, updown == 1);
|
GB_set_key_state(gb, GB_KEY_DOWN, updown == 1);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
switch (event_hotkey_code(&event)) {
|
switch (event_hotkey_code(&event)) {
|
||||||
@ -292,7 +291,7 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
#endif
|
#endif
|
||||||
GB_audio_set_paused(GB_audio_is_playing());
|
GB_audio_set_paused(GB_audio_is_playing());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_SCANCODE_F:
|
case SDL_SCANCODE_F:
|
||||||
if (event.key.keysym.mod & MODIFIER) {
|
if (event.key.keysym.mod & MODIFIER) {
|
||||||
@ -348,9 +347,14 @@ static void handle_events(GB_gameboy_t *gb)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
return SDL_MapRGB(pixel_format, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
static void vblank(GB_gameboy_t *gb)
|
static void vblank(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
@ -362,6 +366,26 @@ static void vblank(GB_gameboy_t *gb)
|
|||||||
clock_mutliplier += 1.0/16;
|
clock_mutliplier += 1.0/16;
|
||||||
GB_set_clock_multiplier(gb, clock_mutliplier);
|
GB_set_clock_multiplier(gb, clock_mutliplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (turbo_down) {
|
||||||
|
show_osd_text("Fast forward...");
|
||||||
|
}
|
||||||
|
else if (underclock_down) {
|
||||||
|
show_osd_text("Slow motion...");
|
||||||
|
}
|
||||||
|
else if (rewind_down) {
|
||||||
|
show_osd_text("Rewinding...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (osd_countdown && configuration.osd) {
|
||||||
|
unsigned width = GB_get_screen_width(gb);
|
||||||
|
unsigned height = GB_get_screen_height(gb);
|
||||||
|
draw_text(active_pixel_buffer,
|
||||||
|
width, height, 8, height - 8 - osd_text_lines * 12, osd_text,
|
||||||
|
rgb_encode(gb, 255, 255, 255), rgb_encode(gb, 0, 0, 0),
|
||||||
|
true);
|
||||||
|
osd_countdown--;
|
||||||
|
}
|
||||||
if (configuration.blending_mode) {
|
if (configuration.blending_mode) {
|
||||||
render_texture(active_pixel_buffer, previous_pixel_buffer);
|
render_texture(active_pixel_buffer, previous_pixel_buffer);
|
||||||
uint32_t *temp = active_pixel_buffer;
|
uint32_t *temp = active_pixel_buffer;
|
||||||
@ -376,12 +400,6 @@ static void vblank(GB_gameboy_t *gb)
|
|||||||
handle_events(gb);
|
handle_events(gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
|
||||||
{
|
|
||||||
return SDL_MapRGB(pixel_format, r, g, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rumble(GB_gameboy_t *gb, double amp)
|
static void rumble(GB_gameboy_t *gb, double amp)
|
||||||
{
|
{
|
||||||
SDL_HapticRumblePlay(haptic, amp, 250);
|
SDL_HapticRumblePlay(haptic, amp, 250);
|
||||||
@ -455,6 +473,9 @@ static bool handle_pending_command(void)
|
|||||||
false,
|
false,
|
||||||
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
|
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
|
||||||
success? "Notice" : "Error");
|
success? "Notice" : "Error");
|
||||||
|
if (success) {
|
||||||
|
show_osd_text(pending_command == GB_SDL_LOAD_STATE_COMMAND? "State loaded" : "State saved");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,6 +487,9 @@ static bool handle_pending_command(void)
|
|||||||
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
|
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
|
||||||
success? "Notice" : "Error");
|
success? "Notice" : "Error");
|
||||||
SDL_free(dropped_state_file);
|
SDL_free(dropped_state_file);
|
||||||
|
if (success) {
|
||||||
|
show_osd_text("State loaded");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case GB_SDL_NO_COMMAND:
|
case GB_SDL_NO_COMMAND:
|
||||||
@ -579,6 +603,12 @@ restart:
|
|||||||
}
|
}
|
||||||
end_capturing_logs(true, error, SDL_MESSAGEBOX_WARNING, "Warning");
|
end_capturing_logs(true, error, SDL_MESSAGEBOX_WARNING, "Warning");
|
||||||
|
|
||||||
|
static char start_text[64];
|
||||||
|
static char title[17];
|
||||||
|
GB_get_rom_title(&gb, title);
|
||||||
|
sprintf(start_text, "SameBoy v" GB_VERSION "\n%s\n%08X", title, GB_get_rom_crc32(&gb));
|
||||||
|
show_osd_text(start_text);
|
||||||
|
|
||||||
|
|
||||||
/* Configure battery */
|
/* Configure battery */
|
||||||
char battery_save_path[path_length + 5]; /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */
|
char battery_save_path[path_length + 5]; /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */
|
||||||
|
Loading…
Reference in New Issue
Block a user