diff --git a/src/libretro/input.cpp b/src/libretro/input.cpp index 5d710f8c79..ca4aaba053 100644 --- a/src/libretro/input.cpp +++ b/src/libretro/input.cpp @@ -32,7 +32,7 @@ void update_input(InputState *state) for (i = 0; i < (RETRO_DEVICE_ID_JOYPAD_R3 + 1); i++) joypad_bits |= input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i) ? (1 << i) : 0; } - + ADD_KEY_TO_MASK(RETRO_DEVICE_ID_JOYPAD_A, 0, joypad_bits); ADD_KEY_TO_MASK(RETRO_DEVICE_ID_JOYPAD_B, 1, joypad_bits); ADD_KEY_TO_MASK(RETRO_DEVICE_ID_JOYPAD_SELECT, 2, joypad_bits); @@ -83,7 +83,12 @@ void update_input(InputState *state) int16_t pointer_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); int16_t pointer_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); - unsigned int touch_scale = screen_layout_data.displayed_layout == ScreenLayout::HybridBottom ? screen_layout_data.hybrid_ratio : 1; + unsigned int touch_scale = 1; + if (screen_layout_data.displayed_layout == ScreenLayout::HybridBottom) { + touch_scale = screen_layout_data.hybrid_ratio_large; + } else if (screen_layout_data.displayed_layout == ScreenLayout::HybridTop) { + touch_scale = screen_layout_data.hybrid_ratio_small; + } unsigned int x = ((int)pointer_x + 0x8000) * screen_layout_data.buffer_width / 0x10000 / touch_scale; unsigned int y = ((int)pointer_y + 0x8000) * screen_layout_data.buffer_height / 0x10000 / touch_scale; diff --git a/src/libretro/libretro.cpp b/src/libretro/libretro.cpp index 2207849bfa..3599548113 100644 --- a/src/libretro/libretro.cpp +++ b/src/libretro/libretro.cpp @@ -380,10 +380,13 @@ static void check_variables(bool init) var.key = "melonds_hybrid_ratio"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != NULL) { - screen_layout_data.hybrid_ratio = std::stoi(var.value); + // value is a string like "2:1", cut it apart and convert to number + screen_layout_data.hybrid_ratio_large = var.value[0] - '0'; + screen_layout_data.hybrid_ratio_small = var.value[2] - '0'; } #else - screen_layout_data.hybrid_ratio = 2; + screen_layout_data.hybrid_ratio_large = 2; + screen_layout_data.hybrid_ratio_small = 1; #endif var.key = "melonds_hybrid_small_screen"; @@ -723,11 +726,11 @@ void retro_run(void) refresh_opengl = true; } - swapped_screens = input_state.swap_screens_btn; + swapped_screens = input_state.swap_screens_btn; } else { - swapped_screens = input_state.swap_screens_btn; + swapped_screens = input_state.swap_screens_btn; update_screenlayout(current_screen_layout, &screen_layout_data, enable_opengl, swapped_screens); refresh_opengl = true; } @@ -900,7 +903,7 @@ static bool _handle_load_game(unsigned type, const struct retro_game_info *info) NDS::SetConsoleType(Config::ConsoleType); Frontend::LoadBIOS(); NDS::LoadROM((u8*)info->data, info->size, save_path.c_str(), Config::DirectBoot); - + if (type == SLOT_1_2_BOOT) { char gba_game_name[256]; diff --git a/src/libretro/libretro_core_options.h b/src/libretro/libretro_core_options.h index e50715cd8c..a1b096ba57 100644 --- a/src/libretro/libretro_core_options.h +++ b/src/libretro/libretro_core_options.h @@ -503,15 +503,17 @@ struct retro_core_option_v2_definition option_defs_us[] = { "melonds_hybrid_ratio", "Hybrid Ratio (OpenGL Only)", NULL, - NULL, + "Choose the ratio of the size of large screen : small screen when using 'hybrid' mode", NULL, "screen", { - { "2", NULL }, - { "3", NULL }, + { "2:1", NULL }, + { "3:1", NULL }, + { "4:1", NULL }, + { "3:2", NULL }, { NULL, NULL }, }, - "2" + "2:1" }, #endif #ifdef JIT_ENABLED diff --git a/src/libretro/opengl.cpp b/src/libretro/opengl.cpp index 3806c75af2..68d204f666 100644 --- a/src/libretro/opengl.cpp +++ b/src/libretro/opengl.cpp @@ -225,8 +225,8 @@ void setup_opengl_frame_state(void) top_screen_y = screen_height; // ditto break; case ScreenLayout::HybridTop: - primary_x = screen_width * screen_layout_data.hybrid_ratio; - primary_y = screen_height * screen_layout_data.hybrid_ratio; + primary_x = screen_width * screen_layout_data.hybrid_ratio_large; + primary_y = screen_height * screen_layout_data.hybrid_ratio_large; primary_tex_v0_x = 0.0f; primary_tex_v0_y = 0.0f; @@ -243,8 +243,8 @@ void setup_opengl_frame_state(void) break; case ScreenLayout::HybridBottom: - primary_x = screen_width * screen_layout_data.hybrid_ratio; - primary_y = screen_height * screen_layout_data.hybrid_ratio; + primary_x = screen_width * screen_layout_data.hybrid_ratio_large; + primary_y = screen_height * screen_layout_data.hybrid_ratio_large; primary_tex_v0_x = 0.0f; primary_tex_v0_y = 0.5f + pixel_pad; @@ -283,51 +283,51 @@ void setup_opengl_frame_state(void) if(screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenTop && screen_layout_data.displayed_layout == ScreenLayout::HybridTop) { SETVERTEX(6, primary_x, 0.0f, 0.0f, 0.5f + pixel_pad); // top left - SETVERTEX(7, primary_x, 0.0f + screen_height, 0.0f, 1.0f); // bottom left - SETVERTEX(8, primary_x + screen_width, 0.0f + screen_height, 1.0f, 1.0f); // bottom right + SETVERTEX(7, primary_x, 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 1.0f); // bottom left + SETVERTEX(8, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 1.0f); // bottom right SETVERTEX(9, primary_x, 0.0f, 0.0f, 0.5f + pixel_pad); // top left - SETVERTEX(10, primary_x + screen_width, 0.0f, 1.0f, 0.5f + pixel_pad); // top right - SETVERTEX(11, primary_x + screen_width, 0.0f + screen_height, 1.0f, 1.0f); // bottom right + SETVERTEX(10, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f, 1.0f, 0.5f + pixel_pad); // top right + SETVERTEX(11, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 1.0f); // bottom right } else if (screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenDuplicate || (screen_layout_data.displayed_layout == ScreenLayout::HybridBottom && screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenTop)) { SETVERTEX(6, primary_x, 0.0f, 0.0f, 0.0f); // top left - SETVERTEX(7, primary_x, 0.0f + screen_height, 0.0f, 0.5f - pixel_pad); // bottom left - SETVERTEX(8, primary_x + screen_width, 0.0f + screen_height, 1.0f, 0.5f - pixel_pad); // bottom right + SETVERTEX(7, primary_x, 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.5f - pixel_pad); // bottom left + SETVERTEX(8, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 0.5f - pixel_pad); // bottom right SETVERTEX(9, primary_x, 0.0f, 0.0f, 0.0f); // top left - SETVERTEX(10, primary_x + screen_width, 0.0f, 1.0f, 0.0f); // top right - SETVERTEX(11, primary_x + screen_width, 0.0f + screen_height, 1.0f, 0.5f - pixel_pad); // bottom right + SETVERTEX(10, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f, 1.0f, 0.0f); // top right + SETVERTEX(11, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), 0.0f + (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 0.5f - pixel_pad); // bottom right } - + //Bottom Screen if(screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenBottom && screen_layout_data.displayed_layout == ScreenLayout::HybridTop) { - SETVERTEX(6, primary_x, primary_y - screen_height, 0.0f, 0.5f + pixel_pad); // top left + SETVERTEX(6, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.5f + pixel_pad); // top left SETVERTEX(7, primary_x, primary_y, 0.0f, 1.0f); // bottom left - SETVERTEX(8, primary_x + screen_width, primary_y, 1.0f, 1.0f); // bottom right - SETVERTEX(9, primary_x, primary_y - screen_height, 0.0f, 0.5f + pixel_pad); // top left - SETVERTEX(10, primary_x + screen_width, primary_y - screen_height, 1.0f, 0.5f + pixel_pad); // top right - SETVERTEX(11, primary_x + screen_width, primary_y, 1.0f, 1.0f); // bottom right + SETVERTEX(8, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 1.0f); // bottom right + SETVERTEX(9, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.5f + pixel_pad); // top left + SETVERTEX(10, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 0.5f + pixel_pad); // top right + SETVERTEX(11, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 1.0f); // bottom right } else if(screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenBottom && screen_layout_data.displayed_layout == ScreenLayout::HybridBottom) { - SETVERTEX(6, primary_x, primary_y - screen_height, 0.0f, 0.0f); // top left + SETVERTEX(6, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.0f); // top left SETVERTEX(7, primary_x, primary_y, 0.0f, 0.5f - pixel_pad); // bottom left - SETVERTEX(8, primary_x + screen_width, primary_y, 1.0f, 0.5f - pixel_pad); // bottom right - SETVERTEX(9, primary_x, primary_y - screen_height, 0.0f, 0.0f); // top left - SETVERTEX(10, primary_x + screen_width, primary_y - screen_height, 1.0f, 0.0f); // top right - SETVERTEX(11, primary_x + screen_width, primary_y, 1.0f, 0.5f - pixel_pad); // bottom right + SETVERTEX(8, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 0.5f - pixel_pad); // bottom right + SETVERTEX(9, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.0f); // top left + SETVERTEX(10, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 0.0f); // top right + SETVERTEX(11, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 0.5f - pixel_pad); // bottom right } else if (screen_layout_data.hybrid_small_screen == SmallScreenLayout::SmallScreenDuplicate) { - SETVERTEX(12, primary_x, primary_y - screen_height, 0.0f, 0.5f + pixel_pad); // top left + SETVERTEX(12, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.5f + pixel_pad); // top left SETVERTEX(13, primary_x, primary_y, 0.0f, 1.0f); // bottom left - SETVERTEX(14, primary_x + screen_width, primary_y, 1.0f, 1.0f); // bottom right - SETVERTEX(15, primary_x, primary_y - screen_height, 0.0f, 0.5f + pixel_pad); // top left - SETVERTEX(16, primary_x + screen_width, primary_y - screen_height, 1.0f, 0.5f + pixel_pad); // top right - SETVERTEX(17, primary_x + screen_width, primary_y, 1.0f, 1.0f); // bottom right + SETVERTEX(14, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 1.0f); // bottom right + SETVERTEX(15, primary_x, primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 0.0f, 0.5f + pixel_pad); // top left + SETVERTEX(16, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y - (screen_height * screen_layout_data.hybrid_ratio_small), 1.0f, 0.5f + pixel_pad); // top right + SETVERTEX(17, primary_x + (screen_width * screen_layout_data.hybrid_ratio_small), primary_y, 1.0f, 1.0f); // bottom right } } else diff --git a/src/libretro/screenlayout.cpp b/src/libretro/screenlayout.cpp index faf9d1f54a..11cc29d74c 100644 --- a/src/libretro/screenlayout.cpp +++ b/src/libretro/screenlayout.cpp @@ -9,7 +9,8 @@ ScreenLayoutData screen_layout_data; void initialize_screnlayout_data(ScreenLayoutData *data) { data->buffer_ptr = nullptr; - data->hybrid_ratio = 2; + data->hybrid_ratio_large = 2; + data->hybrid_ratio_small = 1; } void update_screenlayout(ScreenLayout layout, ScreenLayoutData *data, bool opengl, bool swap_screens) @@ -174,14 +175,14 @@ void update_screenlayout(ScreenLayout layout, ScreenLayoutData *data, bool openg data->hybrid = true; - data->buffer_width = (data->screen_width * data->hybrid_ratio) + data->screen_width + (data->hybrid_ratio * 2); - data->buffer_height = (data->screen_height * data->hybrid_ratio); + data->buffer_width = (data->screen_width * data->hybrid_ratio_large) + (data->screen_width * data->hybrid_ratio_small) + (data->hybrid_ratio_large * 2); + data->buffer_height = (data->screen_height * data->hybrid_ratio_large); data->buffer_stride = data->buffer_width * pixel_size; if (layout == ScreenLayout::HybridTop) { - data->touch_offset_x = (data->screen_width * data->hybrid_ratio) + (data->hybrid_ratio / 2); - data->touch_offset_y = (data->screen_height * (data->hybrid_ratio - 1)); + data->touch_offset_x = (data->screen_width * data->hybrid_ratio_large) + (data->hybrid_ratio_large / 2); + data->touch_offset_y = (data->screen_height * (data->hybrid_ratio_large - 1)); } else { diff --git a/src/libretro/screenlayout.h b/src/libretro/screenlayout.h index c3788218eb..0558cb02ac 100644 --- a/src/libretro/screenlayout.h +++ b/src/libretro/screenlayout.h @@ -59,7 +59,8 @@ struct ScreenLayoutData bool hybrid; SmallScreenLayout hybrid_small_screen; - unsigned hybrid_ratio; + unsigned hybrid_ratio_large; + unsigned hybrid_ratio_small; unsigned buffer_width; unsigned buffer_height; diff --git a/src/libretro/utils.cpp b/src/libretro/utils.cpp index 61c55836ce..5e41df1b8c 100644 --- a/src/libretro/utils.cpp +++ b/src/libretro/utils.cpp @@ -29,19 +29,19 @@ void copy_hybrid_screen(ScreenLayoutData *data, uint32_t* src, ScreenId screen_i unsigned buffer_y, buffer_x; unsigned x, y, pixel; uint32_t pixel_data; - unsigned buffer_height = data->screen_height * data->hybrid_ratio; - unsigned buffer_width = data->screen_width * data->hybrid_ratio; + unsigned buffer_height = data->screen_height * data->hybrid_ratio_large; + unsigned buffer_width = data->screen_width * data->hybrid_ratio_large; for (buffer_y = 0; buffer_y < buffer_height; buffer_y++) { - y = buffer_y / data->hybrid_ratio; + y = buffer_y / data->hybrid_ratio_large; for (buffer_x = 0; buffer_x < buffer_width; buffer_x++) { - x = buffer_x / data->hybrid_ratio; + x = buffer_x / data->hybrid_ratio_large; pixel_data = *(uint32_t*)(src + (y * data->screen_width) + x); - for (pixel = 0; pixel < data->hybrid_ratio; pixel++) + for (pixel = 0; pixel < data->hybrid_ratio_large; pixel++) { *(uint32_t *)(data->buffer_ptr + (buffer_y * data->buffer_stride / 2) + pixel * 2 + (buffer_x * 2)) = pixel_data; } @@ -55,7 +55,7 @@ void copy_hybrid_screen(ScreenLayoutData *data, uint32_t* src, ScreenId screen_i { memcpy((uint16_t *)data->buffer_ptr // X - + ((data->screen_width * data->hybrid_ratio * 2) + (data->hybrid_ratio % 2 == 0 ? data->hybrid_ratio : ((data->hybrid_ratio / 2) * 4))) + + ((data->screen_width * data->hybrid_ratio_large * 2) + (data->hybrid_ratio_large % 2 == 0 ? data->hybrid_ratio_large : ((data->hybrid_ratio_large / 2) * 4))) // Y + (y * data->buffer_stride / 2), src + (y * data->screen_width), (data->screen_width) * data->pixel_size); @@ -68,9 +68,9 @@ void copy_hybrid_screen(ScreenLayoutData *data, uint32_t* src, ScreenId screen_i { memcpy((uint16_t *)data->buffer_ptr // X - + ((data->screen_width * data->hybrid_ratio * 2) + (data->hybrid_ratio % 2 == 0 ? data->hybrid_ratio : ((data->hybrid_ratio / 2) * 4))) + + ((data->screen_width * data->hybrid_ratio_large * 2) + (data->hybrid_ratio_large % 2 == 0 ? data->hybrid_ratio_large : ((data->hybrid_ratio_large / 2) * 4))) // Y - + ((y + (data->screen_height * (data->hybrid_ratio - 1))) * data->buffer_stride / 2), + + ((y + (data->screen_height * (data->hybrid_ratio_large - 1))) * data->buffer_stride / 2), src + (y * data->screen_width), (data->screen_width) * data->pixel_size); } } @@ -80,7 +80,12 @@ void draw_cursor(ScreenLayoutData *data, int32_t x, int32_t y) { uint32_t* base_offset = (uint32_t*)data->buffer_ptr; - uint32_t scale = data->displayed_layout == ScreenLayout::HybridBottom ? data->hybrid_ratio : 1; + uint32_t scale = 1; + if (data->displayed_layout == ScreenLayout::HybridBottom) { + scale = screen_layout_data.hybrid_ratio_large; + } else if (data->displayed_layout == ScreenLayout::HybridTop) { + scale = screen_layout_data.hybrid_ratio_small; + } uint32_t start_y = Clamp(y - CURSOR_SIZE, 0, data->screen_height) * scale; uint32_t end_y = Clamp(y + CURSOR_SIZE, 0, data->screen_height) * scale;