Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for arbitrary scaling ratios in hybrid display mode #192

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/libretro/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Comment on lines -86 to +91
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see the PR description, this edit makes sense to me but must be wrong somehow. Before this edit, the touch registers but not where you touched, and after this edit the touch doesn't register at all)


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;
Expand Down
13 changes: 8 additions & 5 deletions src/libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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];
Expand Down
10 changes: 6 additions & 4 deletions src/libretro/libretro_core_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
56 changes: 28 additions & 28 deletions src/libretro/opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
11 changes: 6 additions & 5 deletions src/libretro/screenlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
{
Expand Down
3 changes: 2 additions & 1 deletion src/libretro/screenlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 14 additions & 9 deletions src/libretro/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
Expand All @@ -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);
}
}
Expand All @@ -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;
Expand Down