Added optional OSD (SDL)

This commit is contained in:
Lior Halphon 2021-05-30 23:39:59 +03:00
parent 3ed18a76da
commit ebb0cb5e81
3 changed files with 109 additions and 37 deletions

View File

@ -198,11 +198,13 @@ static void draw_char(uint32_t *buffer, unsigned width, unsigned height, unsigne
}
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 y_offset = (GB_get_screen_height(&gb) - 144) / 2;
unsigned y_offset = is_osd? 0 : (GB_get_screen_height(&gb) - 144) / 2;
while (*string) {
if (*string == '\n') {
x = orig_x;
@ -215,21 +217,39 @@ static void draw_unbordered_text(uint32_t *buffer, unsigned width, unsigned heig
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;
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);
draw_unbordered_text(buffer, width, height, x, y - 1, string, border);
draw_unbordered_text(buffer, width, height, x, y + 1, string, border);
draw_unbordered_text(buffer, width, height, x, y, string, color);
draw_unbordered_text(buffer, width, height, x - 1, y, string, border, is_osd);
draw_unbordered_text(buffer, width, height, x + 1, y, string, border, is_osd);
draw_unbordered_text(buffer, width, height, x, y - 1, string, border, is_osd);
draw_unbordered_text(buffer, width, height, x, y + 1, string, border, is_osd);
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 {
DECORATION_NONE,
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)
{
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) {
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;
case DECORATION_ARROWS:
draw_text(buffer, width, height, x - GLYPH_WIDTH, y, LEFT_ARROW_STRING, color, border);
draw_text(buffer, width, height, width - x, y, RIGHT_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, false);
break;
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+";
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+";
return (const char *[]){"Disabled", "Simple", "Accurate"}
[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[] = {
{"Scaling Mode:", cycle_scaling, current_scaling_mode, cycle_scaling_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},
{"Mono Palette:", cycle_palette, current_palette, cycle_palette_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},
{NULL,}
};
@ -1574,7 +1607,7 @@ void run_gui(bool is_running)
}
break;
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;
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);

View File

@ -119,6 +119,9 @@ typedef struct {
char bootrom_path[4096];
uint8_t interference_volume;
GB_rtc_mode_t rtc_mode;
/* v0.14.4 */
bool osd;
} configuration_t;
extern configuration_t configuration;
@ -140,4 +143,10 @@ static SDL_Scancode event_hotkey_code(SDL_Event *event)
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

View File

@ -141,7 +141,7 @@ static void open_menu(void)
static void handle_events(GB_gameboy_t *gb)
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
pending_command = GB_SDL_QUIT_COMMAND;
@ -191,7 +191,7 @@ static void handle_events(GB_gameboy_t *gb)
open_menu();
}
}
break;
break;
case SDL_JOYAXISMOTION: {
static bool axis_active[2] = {false, false};
@ -231,22 +231,21 @@ static void handle_events(GB_gameboy_t *gb)
}
}
}
break;
case SDL_JOYHATMOTION:
{
break;
case SDL_JOYHATMOTION: {
uint8_t value = event.jhat.value;
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 =
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_RIGHT, leftright == 1);
GB_set_key_state(gb, GB_KEY_UP, updown == -1);
GB_set_key_state(gb, GB_KEY_DOWN, updown == 1);
break;
};
};
case SDL_KEYDOWN:
switch (event_hotkey_code(&event)) {
@ -276,7 +275,7 @@ static void handle_events(GB_gameboy_t *gb)
}
break;
}
case SDL_SCANCODE_P:
if (event.key.keysym.mod & MODIFIER) {
paused = !paused;
@ -292,14 +291,14 @@ static void handle_events(GB_gameboy_t *gb)
#endif
GB_audio_set_paused(GB_audio_is_playing());
}
break;
break;
case SDL_SCANCODE_F:
if (event.key.keysym.mod & MODIFIER) {
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == false) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
else {
else {
SDL_SetWindowFullscreen(window, 0);
}
update_viewport();
@ -348,9 +347,14 @@ static void handle_events(GB_gameboy_t *gb)
break;
default:
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)
{
@ -362,6 +366,26 @@ static void vblank(GB_gameboy_t *gb)
clock_mutliplier += 1.0/16;
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) {
render_texture(active_pixel_buffer, previous_pixel_buffer);
uint32_t *temp = active_pixel_buffer;
@ -376,12 +400,6 @@ static void vblank(GB_gameboy_t *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)
{
SDL_HapticRumblePlay(haptic, amp, 250);
@ -455,6 +473,9 @@ static bool handle_pending_command(void)
false,
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
success? "Notice" : "Error");
if (success) {
show_osd_text(pending_command == GB_SDL_LOAD_STATE_COMMAND? "State loaded" : "State saved");
}
return false;
}
@ -466,6 +487,9 @@ static bool handle_pending_command(void)
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
success? "Notice" : "Error");
SDL_free(dropped_state_file);
if (success) {
show_osd_text("State loaded");
}
return false;
case GB_SDL_NO_COMMAND:
@ -579,6 +603,12 @@ restart:
}
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 */
char battery_save_path[path_length + 5]; /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */