mirror of https://github.com/bsnes-emu/bsnes.git
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 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);
|
||||
|
|
|
@ -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
|
||||
|
|
70
SDL/main.c
70
SDL/main.c
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue