From ae67b055fec6a8cc843554d8190e018a6ae9b89d Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 31 Mar 2021 21:14:54 +0000 Subject: Adds overscan scaler and fps display --- shell/menu/config.h | 1 + shell/menu/menu.c | 144 ++++++++++++++++++++++++++----------------- shell/menu/menu.h | 3 + shell/scalers/scaler.c | 61 +++++++++++++++--- shell/scalers/scaler.h | 3 +- shell/video/sdl/video_blit.c | 15 +++-- src/gfx16.c | 7 ++- 7 files changed, 162 insertions(+), 72 deletions(-) diff --git a/shell/menu/config.h b/shell/menu/config.h index 9b71fc2..b0c0711 100644 --- a/shell/menu/config.h +++ b/shell/menu/config.h @@ -5,6 +5,7 @@ typedef struct { int32_t fullscreen; /* For input remapping */ uint32_t config_buttons[6][19]; + uint32_t showfps; } t_config; extern t_config option; diff --git a/shell/menu/menu.c b/shell/menu/menu.c index 01d1e53..4cdd8c7 100644 --- a/shell/menu/menu.c +++ b/shell/menu/menu.c @@ -15,6 +15,8 @@ #include "config.h" #include "menu.h" #include "buttons.h" +#include "snes9x.h" +#include "cpuexec.h" t_config option; uint32_t emulator_state = 0; @@ -33,20 +35,20 @@ extern void SRAM_Save(char* path, uint_fast8_t state); static uint8_t selectpressed = 0; static uint8_t save_slot = 0; -static const int8_t upscalers_available = 2 +static const int8_t upscalers_available = 4 #ifdef SCALE2X_UPSCALER +1 #endif ; -static void SaveState_Menu(uint_fast8_t load_mode, uint_fast8_t slot) +void SaveState_Menu(uint_fast8_t load_mode, uint_fast8_t slot) { char tmp[512]; snprintf(tmp, sizeof(tmp), "%s/%s_%d.sts", save_path, GameName_emu, slot); SaveState(tmp,load_mode); } -static void SRAM_Menu(uint_fast8_t load_mode) +void SRAM_Menu(uint_fast8_t load_mode) { char tmp[512]; snprintf(tmp, sizeof(tmp), "%s/%s.srm", sram_path, GameName_emu); @@ -85,8 +87,10 @@ static void config_load() option.config_buttons[0][10] = BTN_START; option.config_buttons[0][11] = BTN_SELECT; - option.fullscreen = 0; + option.fullscreen = 3; + option.showfps = 0; } + if (option.showfps == 0) Settings.DisplayFrameRate = false; else Settings.DisplayFrameRate = true; } static void config_save() @@ -346,7 +350,7 @@ void Menu() /* Save sram settings each time we bring up the menu */ SRAM_Menu(0); - while (((currentselection != 1) && (currentselection != 6)) || (!pressed)) + while (((currentselection != 1) && (currentselection != 7) && (currentselection != 8)) || (!pressed)) { pressed = 0; @@ -354,34 +358,39 @@ void Menu() print_string("snes9x2002 - Built on " __DATE__, TextWhite, 0, 5, 15, backbuffer->pixels); - if (currentselection == 1) print_string("Continue", TextRed, 0, 5, 45, backbuffer->pixels); - else print_string("Continue", TextWhite, 0, 5, 45, backbuffer->pixels); +#define MENU_Y(y) 29 + (18*y) + + if (currentselection == 1) print_string("Continue", TextRed, 0, 5, MENU_Y(1), backbuffer->pixels); + else print_string("Continue", TextWhite, 0, 5, MENU_Y(1), backbuffer->pixels); snprintf(text, sizeof(text), "Load State %d", save_slot); - if (currentselection == 2) print_string(text, TextRed, 0, 5, 65, backbuffer->pixels); - else print_string(text, TextWhite, 0, 5, 65, backbuffer->pixels); + if (currentselection == 2) print_string(text, TextRed, 0, 5, MENU_Y(2), backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, MENU_Y(2), backbuffer->pixels); snprintf(text, sizeof(text), "Save State %d", save_slot); - if (currentselection == 3) print_string(text, TextRed, 0, 5, 85, backbuffer->pixels); - else print_string(text, TextWhite, 0, 5, 85, backbuffer->pixels); + if (currentselection == 3) print_string(text, TextRed, 0, 5, MENU_Y(3), backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, MENU_Y(3), backbuffer->pixels); if (currentselection == 4) { switch(option.fullscreen) { case 0: - print_string("Scaling : Native", TextRed, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : Native", TextRed, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 1: - print_string("Scaling : Stretched", TextRed, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : FS Sharp", TextRed, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 2: - print_string("Scaling : Bilinear", TextRed, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : FS Smooth", TextRed, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 3: - print_string("Scaling : EPX/Scale2x", TextRed, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : Bilinear", TextRed, 0, 5, MENU_Y(4), backbuffer->pixels); + break; + case 4: + print_string("Scaling : Overscan", TextRed, 0, 5, MENU_Y(4), backbuffer->pixels); break; } } @@ -390,25 +399,36 @@ void Menu() switch(option.fullscreen) { case 0: - print_string("Scaling : Native", TextWhite, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : Native", TextWhite, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 1: - print_string("Scaling : Stretched", TextWhite, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : FS Sharp", TextWhite, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 2: - print_string("Scaling : Bilinear", TextWhite, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : FS Smooth", TextWhite, 0, 5, MENU_Y(4), backbuffer->pixels); break; case 3: - print_string("Scaling : EPX/Scale2x", TextWhite, 0, 5, 105, backbuffer->pixels); + print_string("Scaling : Bilinear", TextWhite, 0, 5, MENU_Y(4), backbuffer->pixels); + break; + case 4: + print_string("Scaling : Overscan", TextWhite, 0, 5, MENU_Y(4), backbuffer->pixels); break; } } - if (currentselection == 5) print_string("Input remapping", TextRed, 0, 5, 125, backbuffer->pixels); - else print_string("Input remapping", TextWhite, 0, 5, 125, backbuffer->pixels); + if (option.showfps == 0) snprintf(text, sizeof(text), "Show FPS : OFF"); + else snprintf(text, sizeof(text), "Show FPS : ON"); + if (currentselection == 5) print_string(text, TextRed, 0, 5, MENU_Y(5), backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, MENU_Y(5), backbuffer->pixels); - if (currentselection == 6) print_string("Quit", TextRed, 0, 5, 145, backbuffer->pixels); - else print_string("Quit", TextWhite, 0, 5, 145, backbuffer->pixels); + if (currentselection == 6) print_string("Input remapping", TextRed, 0, 5, MENU_Y(6), backbuffer->pixels); + else print_string("Input remapping", TextWhite, 0, 5, MENU_Y(6), backbuffer->pixels); + + if (currentselection == 7) print_string("Reset", TextRed, 0, 5, MENU_Y(7), backbuffer->pixels); + else print_string("Reset", TextWhite, 0, 5, MENU_Y(7), backbuffer->pixels); + + if (currentselection == 8) print_string("Quit", TextRed, 0, 5, MENU_Y(8), backbuffer->pixels); + else print_string("Quit", TextWhite, 0, 5, MENU_Y(8), backbuffer->pixels); print_string("Frontend by gameblabla", TextWhite, 0, 5, 205, backbuffer->pixels); print_string("Credits: Snes9x dev team, libretro", TextWhite, 0, 5, 225, backbuffer->pixels); @@ -422,19 +442,19 @@ void Menu() case BTN_UP: currentselection--; if (currentselection == 0) - currentselection = 6; + currentselection = 8; break; case BTN_DOWN: currentselection++; - if (currentselection == 7) + if (currentselection == 9) currentselection = 1; break; case BTN_L2: case BTN_SELECT: case BTN_B: - pressed = 1; - currentselection = 1; - break; + pressed = 1; + currentselection = 1; + break; case BTN_A: case BTN_START: pressed = 1; @@ -444,13 +464,16 @@ void Menu() { case 2: case 3: - if (save_slot > 0) save_slot--; - break; + if (save_slot > 0) save_slot--; + break; case 4: - option.fullscreen--; - if (option.fullscreen < 0) - option.fullscreen = upscalers_available; - break; + option.fullscreen--; + if (option.fullscreen < 0) + option.fullscreen = upscalers_available; + break; + case 5: + option.showfps ^= 1; + break; } break; case BTN_RIGHT: @@ -458,15 +481,16 @@ void Menu() { case 2: case 3: - save_slot++; - if (save_slot == 10) - save_slot = 9; - break; + if (save_slot < 9) save_slot++; + break; case 4: - option.fullscreen++; - if (option.fullscreen > upscalers_available) - option.fullscreen = 0; - break; + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + case 5: + option.showfps ^= 1; + break; } break; default: @@ -475,7 +499,7 @@ void Menu() } else if (Event.type == SDL_QUIT) { - currentselection = 6; + currentselection = 8; pressed = 1; } } @@ -484,22 +508,28 @@ void Menu() { switch(currentselection) { - case 5: + case 7: + S9xReset(); + break; + case 6: Input_Remapping(); break; - case 4 : - option.fullscreen++; - if (option.fullscreen > upscalers_available) - option.fullscreen = 0; - break; - case 2 : - SaveState_Menu(1, save_slot); - currentselection = 1; - break; - case 3 : + case 5: + option.showfps ^= 1; + break; + case 4 : + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + case 3 : SaveState_Menu(0, save_slot); currentselection = 1; break; + case 2 : + SaveState_Menu(1, save_slot); + currentselection = 1; + break; default: break; } @@ -515,13 +545,11 @@ void Menu() SDL_Flip(sdl_screen); #endif - if (currentselection == 6) - { - exit_snes = 1; - } + if (currentselection == 8) exit_snes = 1; /* Switch back to emulator core */ config_save(); + if (option.showfps == 0) Settings.DisplayFrameRate = false; else Settings.DisplayFrameRate = true; emulator_state = 0; Set_Video_InGame(); } diff --git a/shell/menu/menu.h b/shell/menu/menu.h index 8b81ac3..9b8a7bb 100644 --- a/shell/menu/menu.h +++ b/shell/menu/menu.h @@ -15,4 +15,7 @@ extern uint32_t done; extern void Menu(void); extern void Init_Configuration(void); +extern void SaveState_Menu(uint_fast8_t load_mode, uint_fast8_t slot); +extern void SRAM_Menu(uint_fast8_t load_mode); + #endif diff --git a/shell/scalers/scaler.c b/shell/scalers/scaler.c index 8d85b8a..19c3cfd 100644 --- a/shell/scalers/scaler.c +++ b/shell/scalers/scaler.c @@ -27,6 +27,49 @@ // Halves #define Weight1_1(A, B) (Half(A) + Half(B) + Corr1_1(A, B)) +#define AVERAGE16(c1, c2) (((c1) + (c2) + (((c1) ^ (c2)) & 0x0821))>>1) //More accurate + +void upscale_240x208_to_320x240(uint16_t *dst, uint16_t *src) +{ + int Eh = 0; + int dh = 8; + int width = 320; + int vf = 0; + + for (int y = 0; y < 240; y++) + { + int source = dh * width + 8; + for (int x = 0; x < 320/4; x++) + { + register uint16_t a, b, c; + + a = src[source]; + b = src[source+1]; + c = src[source+2]; + + if(vf == 1){ + a = AVERAGE16(a, src[source+width]); + b = AVERAGE16(b, src[source+width+1]); + c = AVERAGE16(c, src[source+width+2]); + } + *dst++ = a; + *dst++ = (AVERAGE16(a,b) & 0b0000000000011111) | (b & 0b1111111111100000); + *dst++ = (b & 0b0000011111111111) | (AVERAGE16(b,c) & 0b1111100000000000); + *dst++ = c; + source+=3; + + } + Eh += 208; + if(Eh >= 240) { + Eh -= 240; + dh++; + vf = 0; + } + else + vf = 1; + } +} + void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height) { @@ -35,8 +78,10 @@ void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* re // There are 64 blocks of 4 pixels horizontally, and 239 of 1 vertically. // Each block of 4x1 becomes 5x1. uint32_t BlockX, BlockY; - uint16_t* BlockSrc; - uint16_t* BlockDst; + register uint16_t _1,_2,_3,_4; + register uint16_t* BlockSrc; + register uint16_t* BlockDst; + for (BlockY = 0; BlockY < height; BlockY++) { BlockSrc = Src16 + BlockY * width * 1; @@ -51,13 +96,13 @@ void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* re */ // -- Row 1 -- - uint16_t _1 = *(BlockSrc ); + _1 = *(BlockSrc ); *(BlockDst ) = _1; - uint16_t _2 = *(BlockSrc + 1); + _2 = *(BlockSrc + 1); *(BlockDst + 1) = Weight1_3( _1, _2); - uint16_t _3 = *(BlockSrc + 2); + _3 = *(BlockSrc + 2); *(BlockDst + 2) = Weight1_1( _2, _3); - uint16_t _4 = *(BlockSrc + 3); + _4 = *(BlockSrc + 3); *(BlockDst + 3) = Weight3_1( _3, _4); *(BlockDst + 4) = _4; @@ -67,9 +112,9 @@ void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* re } } -void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height) + +void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height, uint32_t midh) { - uint32_t midh = 240 / 2; uint32_t Eh = 0; uint32_t source; uint32_t dh = 0; diff --git a/shell/scalers/scaler.h b/shell/scalers/scaler.h index f220800..a3ae4c0 100644 --- a/shell/scalers/scaler.h +++ b/shell/scalers/scaler.h @@ -5,7 +5,8 @@ /* Generic */ extern void bitmap_scale(uint32_t startx, uint32_t starty, uint32_t viswidth, uint32_t visheight, uint32_t newwidth, uint32_t newheight,uint32_t pitchsrc,uint32_t pitchdest, uint16_t* restrict src, uint16_t* restrict dst); -extern void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height); +extern void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height, uint32_t midh); extern void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height); +extern void upscale_240x208_to_320x240(uint16_t *dst, uint16_t *src); #endif diff --git a/shell/video/sdl/video_blit.c b/shell/video/sdl/video_blit.c index 08aadcd..bf790bb 100644 --- a/shell/video/sdl/video_blit.c +++ b/shell/video/sdl/video_blit.c @@ -86,23 +86,30 @@ void Update_Video_Ingame(int width, int height) uint16_t *s, *d; uint32_t h, w; uint8_t PAL = !!(Memory.FillRAM[0x2133] & 4); + if (height == SNES_HEIGHT_EXTENDED) height++; // 239 to 240 SDL_LockSurface(sdl_screen); switch(option.fullscreen) { - case 0: + case 0: // Native s = (uint16_t*) GFX.Screen; d = (uint16_t*) sdl_screen->pixels + ((sdl_screen->w - width)/2 + (sdl_screen->h - height) * 160) - (PAL ? 0 : 2*320); for(uint8_t y = 0; y < height; y++, s += GFX_PITCH / 2, d += sdl_screen->w) memmove(d, s, width * 2); break; - case 1: - upscale_256xXXX_to_320x240((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, GFX_PITCH / 2, PAL ? 240 : 224); + case 1: // FS Sharp + upscale_256xXXX_to_320x240((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, GFX_PITCH / 2, height, height); break; - case 2: + case 2: // FS Smooth + upscale_256xXXX_to_320x240((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, GFX_PITCH / 2, height, 240/2); + break; + case 3: // Bilinear if (height == 240) upscale_256x240_to_320x240_bilinearish((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, GFX_PITCH / 2, 239); else upscale_256x240_to_320x240_bilinearish((uint32_t*) sdl_screen->pixels + (160*8), (uint32_t*) GFX.Screen, GFX_PITCH / 2, 224); break; + case 4: // Overscan + upscale_240x208_to_320x240((uint16_t*) sdl_screen->pixels, (uint16_t*) GFX.Screen); + break; } //bitmap_scale(0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, sdl_screen->w, sdl_screen->h, SNES_WIDTH*2, 0, GFX.Screen, sdl_screen->pixels); diff --git a/src/gfx16.c b/src/gfx16.c index 0c17f34..02ece3c 100644 --- a/src/gfx16.c +++ b/src/gfx16.c @@ -2534,11 +2534,16 @@ void DisplayChar(uint8* Screen, uint8 c) } } +#ifdef TRIMUI +#include "config.h" +#endif void S9xDisplayFrameRate() { char string[16]; uint8 *Screen = GFX.Screen; - +#ifdef TRIMUI + if (option.fullscreen == 4) Screen += GFX_PITCH *8 +16; // for Overscan +#endif sprintf(string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, (int)Memory.ROMFramesPerSecond); for (int i = 0; i < 5; i++) { -- cgit v1.2.3