Skip to content

Commit

Permalink
【Frontend】Added NDS screen layout settings
Browse files Browse the repository at this point in the history
  • Loading branch information
skylersaleh committed Jan 11, 2024
1 parent 7ecc881 commit c176358
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 20 deletions.
2 changes: 2 additions & 0 deletions src/localization.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
// - "Fast Forward"
// - "Save File"
// - ICON_FK_CROSSHAIRS " Located Files"
// - "Auto\0Vertical\0Horizontal\0Hybrid Large Top\0Hybrid Large Bottom\0Vertical Large Top\0Vertical Large Bottom\0Horizontal Large Top\0Horizontal Large Bottom\0\0"
// - "NDS Screen Layout"

// Strings removed in v4:
// - "Controller"
Expand Down
162 changes: 142 additions & 20 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ typedef struct{
uint32_t avoid_overlaping_touchscreen;
float custom_font_scale;
uint32_t hardcore_mode;
uint32_t padding[228];
uint32_t nds_layout;
uint32_t padding[227];
}persistent_settings_t;
_Static_assert(sizeof(persistent_settings_t)==1024, "persistent_settings_t must be exactly 1024 bytes");
#define SE_STATS_GRAPH_DATA 256
Expand Down Expand Up @@ -348,6 +349,16 @@ typedef struct{
#define SE_THEME_DREW_SCREEN 0x2
#define SE_THEME_DREW_CONTROLLER 0x4

#define SE_NDS_LAYOUT_AUTO 0
#define SE_NDS_LAYOUT_VERTICAL 1
#define SE_NDS_LAYOUT_HORIZONTAL 2
#define SE_NDS_LAYOUT_HYBRID_LARGE_TOP 3
#define SE_NDS_LAYOUT_HYBRID_LARGE_BOTTOM 4
#define SE_NDS_LAYOUT_VERTICAL_LARGE_TOP 5
#define SE_NDS_LAYOUT_VERTICAL_LARGE_BOTTOM 6
#define SE_NDS_LAYOUT_HORIZONTAL_LARGE_TOP 7
#define SE_NDS_LAYOUT_HORIZONTAL_LARGE_BOTTOM 8

typedef struct{
uint16_t start_pixel;
uint16_t end_pixel;
Expand Down Expand Up @@ -539,8 +550,8 @@ static bool se_load_theme_from_file(const char * filename);
static int se_draw_theme_region(int region, float x, float y, float w, float h);
static int se_draw_theme_region_tint(int region, float x, float y, float w, float h,uint32_t tint);
static int se_draw_theme_region_tint_partial(int region, float x, float y, float w, float h, float w_ratio, float h_ratio, uint32_t tint);
static void se_compute_draw_lcd_rect(float *lcd_render_w, float *lcd_render_h, bool *hybrid_nds);
static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lcd_render_w, float lcd_render_h, bool hybrid_nds);
static void se_compute_draw_lcd_rect(float *lcd_render_w, float *lcd_render_h, int* nds_layout);
static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lcd_render_w, float lcd_render_h, int nds_layout);
const char* se_get_pref_path(){
#if defined(EMSCRIPTEN)
return "/offline/";
Expand Down Expand Up @@ -2521,7 +2532,7 @@ static void se_draw_emulated_system_screen(bool preview){
scr_w *=se_dpi_scale();
scr_h *=se_dpi_scale();
}
bool hybrid_nds=false;
int nds_layout=gui_state.settings.nds_layout;
float rotation = gui_state.settings.screen_rotation*0.5*3.14159;
//Don't hide menubar if it doesn't make the screen smaller
if(!gui_state.touch_controls.request_taller_region){
Expand All @@ -2535,16 +2546,16 @@ static void se_draw_emulated_system_screen(bool preview){
if(!touch_controller_active)min_dim = 0;

float native_w = dims[0], native_h = dims[1];
se_compute_draw_lcd_rect(&native_w, &native_h, &hybrid_nds);
se_compute_draw_lcd_rect(&native_w, &native_h, &nds_layout);

bool portrait= (dims[0]-min_dim)/native_w<(dims[1]-min_dim)/native_h;
ImVec2 win_pos;
igGetWindowPos(&win_pos);
int result = se_draw_theme_region(portrait?SE_REGION_BEZEL_PORTRAIT:SE_REGION_BEZEL_LANDSCAPE, win_pos.x,win_pos.y,dims[0],dims[1]);
if(!result){
float render_w = dims[0], render_h = dims[1];
se_compute_draw_lcd_rect(&render_w, &render_h, &hybrid_nds);
se_draw_lcd_in_rect(win_pos.x+dims[0]*0.5,win_pos.y+dims[1]*0.5,render_w,render_h,hybrid_nds);
se_compute_draw_lcd_rect(&render_w, &render_h, &nds_layout);
se_draw_lcd_in_rect(win_pos.x+dims[0]*0.5,win_pos.y+dims[1]*0.5,render_w,render_h,nds_layout);
}
float pad_x = scr_h/se_dpi_scale()*0.025;
if(!(result&SE_THEME_DREW_CONTROLLER)&&(!gui_state.block_touchscreen||preview))se_draw_onscreen_controller(&emu_state, SE_GAMEPAD_BOTH,win_pos.x+pad_x,win_pos.y+pad_x, scr_w/se_dpi_scale()-pad_x*2, scr_h/se_dpi_scale()-pad_x*2, preview);
Expand Down Expand Up @@ -5756,7 +5767,6 @@ void se_draw_menu_panel(){
int color_correct = gui_state.settings.gba_color_correction_mode;
se_text("GBA Color Correction Type");igSameLine(180,0);
se_combo_str("##ColorAlgorithm",&color_correct,"SkyEmu\0Higan\0",0);
igPopItemWidth();
gui_state.settings.gba_color_correction_mode=color_correct;
{
bool b = gui_state.settings.ghosting;
Expand All @@ -5773,6 +5783,14 @@ void se_draw_menu_panel(){
se_checkbox("Stretch Screen to Fit", &b);
gui_state.settings.stretch_to_fit = b;
}
{
se_text("NDS Screen Layout");
int layout = gui_state.settings.nds_layout;
igSameLine(SE_FIELD_INDENT,0);
se_combo_str("##NDSLayout",&layout,"Auto\0Vertical\0Horizontal\0Hybrid Large Top\0Hybrid Large Bottom\0Vertical Large Top\0Vertical Large Bottom\0Horizontal Large Top\0Horizontal Large Bottom\0\0",0);
gui_state.settings.nds_layout=layout;
}
igPopItemWidth();
se_text("Game Boy Color Palette");
for(int i=0;i<4;++i){
igPushIDInt(i);
Expand Down Expand Up @@ -6926,6 +6944,7 @@ void se_load_settings(){
if(gui_state.settings.settings_file_version<3){
gui_state.settings.settings_file_version = 3;
gui_state.settings.hardcore_mode=0;
gui_state.settings.nds_layout = 0;
}
if(gui_state.settings.custom_font_scale<0.5)gui_state.settings.custom_font_scale=1.0;
if(gui_state.settings.custom_font_scale>2.0)gui_state.settings.custom_font_scale=1.0;
Expand All @@ -6945,22 +6964,44 @@ void se_load_settings(){
}
}
}
static void se_compute_draw_lcd_rect(float *lcd_render_w, float *lcd_render_h, bool *hybrid_nds){
*hybrid_nds = false;
static void se_compute_draw_lcd_rect(float *lcd_render_w, float *lcd_render_h, int* nds_layout){
float rotation = gui_state.settings.screen_rotation*0.5*3.14159;
if(!gui_state.settings.stretch_to_fit){
float scr_w = *lcd_render_w;
float scr_h = *lcd_render_h;
float native_w = SB_LCD_W;
float native_h = SB_LCD_H;
bool touch_controller_active = gui_state.last_touch_time>=0||gui_state.settings.auto_hide_touch_controls==false;
*nds_layout= gui_state.settings.nds_layout;
if(emu_state.system==SYSTEM_GBA){native_w = GBA_LCD_W; native_h = GBA_LCD_H;}
else if(emu_state.system==SYSTEM_NDS){
native_w = NDS_LCD_W; native_h = NDS_LCD_H*2;
if(scr_w/scr_h>1&&!touch_controller_active){
native_w = NDS_LCD_W+NDS_LCD_W*0.5;
native_h = NDS_LCD_H;
*hybrid_nds=true;
if(*nds_layout==SE_NDS_LAYOUT_AUTO){
*nds_layout = SE_NDS_LAYOUT_VERTICAL;
if(scr_w/scr_h>1&&!touch_controller_active)*nds_layout = SE_NDS_LAYOUT_HYBRID_LARGE_TOP;
}
switch(*nds_layout){
case SE_NDS_LAYOUT_VERTICAL:
native_w = NDS_LCD_W; native_h = NDS_LCD_H*2;
break;
case SE_NDS_LAYOUT_HORIZONTAL:
native_w = NDS_LCD_W*2; native_h = NDS_LCD_H;
break;
case SE_NDS_LAYOUT_HYBRID_LARGE_TOP:
case SE_NDS_LAYOUT_HYBRID_LARGE_BOTTOM:
native_w = NDS_LCD_W+NDS_LCD_W*0.5;
native_h = NDS_LCD_H;
break;
case SE_NDS_LAYOUT_VERTICAL_LARGE_BOTTOM:
case SE_NDS_LAYOUT_VERTICAL_LARGE_TOP:
native_w = NDS_LCD_W; native_h = NDS_LCD_H*1.5;
break;
case SE_NDS_LAYOUT_HORIZONTAL_LARGE_BOTTOM:
case SE_NDS_LAYOUT_HORIZONTAL_LARGE_TOP:
native_w = NDS_LCD_W*1.5; native_h = NDS_LCD_H;
break;
default:
gui_state.settings.nds_layout = SE_NDS_LAYOUT_AUTO;
break;
}
}
float lcd_aspect= native_h/native_w;
Expand Down Expand Up @@ -7000,7 +7041,7 @@ static void se_compute_draw_lcd_rect(float *lcd_render_w, float *lcd_render_h, b
}
}
}
static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lcd_render_w, float lcd_render_h, bool hybrid_nds){
static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lcd_render_w, float lcd_render_h, int nds_layout){
float dpi_scale = se_dpi_scale();
float lx = lcd_render_x*dpi_scale;
float ly = lcd_render_y*dpi_scale;
Expand All @@ -7017,7 +7058,7 @@ static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lc
if(emu_state.system==SYSTEM_GBA){
se_draw_lcd_defer(core.gba.framebuffer,GBA_LCD_W,GBA_LCD_H,lx,ly, lw, lh,rotation,false);
}else if (emu_state.system==SYSTEM_NDS){
if(hybrid_nds){
if(nds_layout==SE_NDS_LAYOUT_HYBRID_LARGE_TOP){
float p[6]={
0.3333* lw,- lh*0.25,
0.3333* lw, lh*0.25,
Expand All @@ -7032,6 +7073,86 @@ static void se_draw_lcd_in_rect(float lcd_render_x, float lcd_render_y, float lc
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw/3, lh*0.5,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw/3, lh*0.5,rotation,true);
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[4],ly+p[5], lw*2/3, lh,rotation,false);
}else if(nds_layout==SE_NDS_LAYOUT_HYBRID_LARGE_BOTTOM){
float p[6]={
0.3333* lw,- lh*0.25,
0.3333* lw, lh*0.25,
-0.1666* lw,0,
};
for(int i=0;i<3;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw/3, lh*0.5,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw/3, lh*0.5,rotation,true);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[4],ly+p[5], lw*2/3, lh,rotation,true);
}else if(nds_layout==SE_NDS_LAYOUT_HORIZONTAL){
float p[4]={
0.25* lw,0,
-0.25* lw,0,
};
for(int i=0;i<2;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw/2, lh,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw/2, lh,rotation,true);
}else if(nds_layout==SE_NDS_LAYOUT_HORIZONTAL_LARGE_TOP){
float p[4]={
-0.166666* lw,0,
0.3333333* lw,0,
};
for(int i=0;i<2;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw*2/3, lh,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw/3, lh*0.5,rotation,true);
}else if(nds_layout==SE_NDS_LAYOUT_HORIZONTAL_LARGE_BOTTOM){
float p[4]={
-0.3333333* lw,0,
0.166666* lw,0,
};
for(int i=0;i<2;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw/3, lh*0.5,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw*2/3, lh,rotation,true);
}else if(nds_layout==SE_NDS_LAYOUT_VERTICAL_LARGE_TOP){
float p[4]={
0,-0.1666666*lh,
0, 0.33333333*lh,
};
for(int i=0;i<2;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw, lh*2/3,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw*0.5, lh/3,rotation,true);
}else if(nds_layout==SE_NDS_LAYOUT_VERTICAL_LARGE_BOTTOM){
float p[4]={
0,-0.333333*lh,
0,0.16666666*lh,
};
for(int i=0;i<2;++i){
float x = p[i*2+0];
float y = p[i*2+1];
p[i*2+0] = x*cos(-rotation)+y*sin(-rotation);
p[i*2+1] = x*-sin(-rotation)+y*cos(-rotation);
}
se_draw_lcd_defer(core.nds.framebuffer_top,NDS_LCD_W,NDS_LCD_H,lx+p[0],ly+p[1], lw*0.5, lh/3,rotation,false);
se_draw_lcd_defer(core.nds.framebuffer_bottom,NDS_LCD_W,NDS_LCD_H,lx+p[2],ly+p[3], lw, lh*2/3,rotation,true);
}else{
float p[4]={
0,- lh*0.25,
Expand Down Expand Up @@ -7115,8 +7236,9 @@ static int se_draw_theme_region_tint_partial(int region, float x, float y, float
}
}

bool hybrid_nds = false;
se_compute_draw_lcd_rect(&lcd_dims[0],&lcd_dims[1],&hybrid_nds);
int nds_layout = gui_state.settings.nds_layout;
se_compute_draw_lcd_rect(&lcd_dims[0],&lcd_dims[1],&nds_layout);

float lcd_non_fixed_scale[2];
SE_RPT2 lcd_non_fixed_scale[r]=(lcd_dims[r]-fixed_screen_pixels[r])/(screen_pixels[r]-fixed_screen_pixels[r]);

Expand Down Expand Up @@ -7174,7 +7296,7 @@ static int se_draw_theme_region_tint_partial(int region, float x, float y, float
first_screen = false;
float dpi_scale = se_dpi_scale();
float lcd_pos[2] = {ceil((pmin.x+lcd_dims[0]*0.5)*dpi_scale)/dpi_scale,ceil((pmin.y+lcd_dims[1]*0.5)*dpi_scale)/dpi_scale};
se_draw_lcd_in_rect(lcd_pos[0],lcd_pos[1],lcd_dims[0],lcd_dims[1],hybrid_nds);
se_draw_lcd_in_rect(lcd_pos[0],lcd_pos[1],lcd_dims[0],lcd_dims[1],nds_layout);
}

int t = 0xff000000;
Expand Down

0 comments on commit c176358

Please sign in to comment.