diff --git a/dist/gcw0/default.gcw0.desktop b/dist/gcw0/default.gcw0.desktop index fce4190..b89435a 100644 --- a/dist/gcw0/default.gcw0.desktop +++ b/dist/gcw0/default.gcw0.desktop @@ -8,4 +8,4 @@ StartupNotify=true Icon=gambatte_dms Categories=emulators; X-OD-Manual=manual.txt -MimeType=application/x-gameboy-rom;application/x-gbc-rom;application/x-gzip;application/zip;application/gzip; +MimeType=application/x-gameboy-rom;application/x-gbc-rom;application/x-gameboy-color-rom;application/x-gzip;application/zip;application/gzip; diff --git a/gambatte_sdl/builddate.h b/gambatte_sdl/builddate.h index 0a3832c..4f83586 100644 --- a/gambatte_sdl/builddate.h +++ b/gambatte_sdl/builddate.h @@ -1 +1 @@ -#define BUILDDATE "20200805-211631" +#define BUILDDATE "20201120-000643" diff --git a/gambatte_sdl/menu.cpp b/gambatte_sdl/menu.cpp index 2dfe96a..1f07819 100644 --- a/gambatte_sdl/menu.cpp +++ b/gambatte_sdl/menu.cpp @@ -1200,7 +1200,17 @@ static void callback_scaler(menu_t *caller_menu) { menu_entry_set_text(menu_entry, "Hw FullScreen"); menu_add_entry(menu, menu_entry); menu_entry->callback = callback_selectedscaler; -#ifdef VGA_SCREEN +#ifdef OGA_SCREEN + menu_entry = new_menu_entry(0); + menu_entry_set_text(menu_entry, "Dot Matrix 2x"); + menu_add_entry(menu, menu_entry); + menu_entry->callback = callback_selectedscaler; + + menu_entry = new_menu_entry(0); + menu_entry_set_text(menu_entry, "CRT 2x"); + menu_add_entry(menu, menu_entry); + menu_entry->callback = callback_selectedscaler; +#elif VGA_SCREEN menu_entry = new_menu_entry(0); menu_entry_set_text(menu_entry, "Dot Matrix 3x"); menu_add_entry(menu, menu_entry); diff --git a/gambatte_sdl/scaler.c b/gambatte_sdl/scaler.c index ae8e0f3..8b61030 100644 --- a/gambatte_sdl/scaler.c +++ b/gambatte_sdl/scaler.c @@ -10,6 +10,19 @@ # define prefetch(x, y) #endif +uint16_t hexcolor_to_rgb565(const uint32_t color) +{ + uint8_t colorr = ((color >> 16) & 0xFF); + uint8_t colorg = ((color >> 8) & 0xFF); + uint8_t colorb = ((color) & 0xFF); + + uint16_t r = ((colorr >> 3) & 0x1f) << 11; + uint16_t g = ((colorg >> 2) & 0x3f) << 5; + uint16_t b = (colorb >> 3) & 0x1f; + + return (uint16_t) (r | g | b); +} + /* Ayla's fullscreen upscaler */ /* Upscale from 160x144 to 320x240 */ void fullscreen_upscale(uint32_t *to, uint32_t *from) @@ -855,21 +868,177 @@ void scale166x_pseudobilinear(uint32_t* dst, uint32_t* src) } } -#ifdef VGA_SCREEN +#ifdef OGA_SCREEN -uint16_t hexcolor_to_rgb565(const uint32_t color) +/* Upscales a 160x144 image to 320x288 using a grid-looking upscaler algorithm. + * + * Input: + * src: A packed 160x144 pixel image. The pixel format of this image is RGB 565. + * gridcolor: An hexadecimal color. The format of this color is 0xRRGGBB. + * Output: + * dst: A packed 320x288 pixel image. The pixel format of this image is RGB 565. + */ + +void scale2x_dotmatrix(uint32_t* dst, uint32_t* src, const uint32_t gridcolor) { - uint8_t colorr = ((color >> 16) & 0xFF); - uint8_t colorg = ((color >> 8) & 0xFF); - uint8_t colorb = ((color) & 0xFF); + uint16_t* Src16 = (uint16_t*) src; + uint16_t* Dst16 = (uint16_t*) dst; + uint16_t gcolor = hexcolor_to_rgb565(gridcolor); - uint16_t r = ((colorr >> 3) & 0x1f) << 11; - uint16_t g = ((colorg >> 2) & 0x3f) << 5; - uint16_t b = (colorb >> 3) & 0x1f; + // There are 160 pixels horizontally, and 144 vertically. + // Each pixel becomes 2x2 with an added grid pattern. - return (uint16_t) (r | g | b); + uint32_t BlockX, BlockY; + uint16_t* BlockSrc; + uint16_t* BlockDst; + for (BlockY = 0; BlockY < 144; BlockY++) + { + BlockSrc = Src16 + BlockY * 160 * 1; + BlockDst = Dst16 + BlockY * 480 * 2; + for (BlockX = 0; BlockX < 160; BlockX++) + { + // Before: After: + // (a) (2)(1) + // (3)(2) + + uint16_t _1 = *(BlockSrc); + uint16_t _2 = Weight2_1( _1, gcolor); + uint16_t _3 = Weight1_1( _1, gcolor); + + // -- Row 1 -- + *(BlockDst ) = _2; + *(BlockDst + 1) = _1; + + // -- Row 2 -- + *(BlockDst + 480 * 1 ) = _3; + *(BlockDst + 480 * 1 + 1) = _2; + + BlockSrc += 1; + BlockDst += 2; + } + } +} + +/* Upscales a 160x144 image to 320x288 using a CRT-looking upscaler algorithm. + * + * Input: + * src: A packed 160x144 pixel image. The pixel format of this image is RGB 565. + * gridcolor: An hexadecimal color. The format of this color is 0xRRGGBB. + * Output: + * dst: A packed 320x288 pixel image. The pixel format of this image is RGB 565. + */ + +void scale2x_crt(uint32_t* dst, uint32_t* src) +{ + uint16_t* Src16 = (uint16_t*) src; + uint16_t* Dst16 = (uint16_t*) dst; + uint16_t gcolor = hexcolor_to_rgb565(0x000000); + + // There are 160 pixels horizontally, and 144 vertically. + // Each pixel becomes 2x2 with an added scanline pattern. + + uint32_t BlockX, BlockY; + uint16_t* BlockSrc; + uint16_t* BlockDst; + for (BlockY = 0; BlockY < 144; BlockY++) + { + BlockSrc = Src16 + BlockY * 160 * 1; + BlockDst = Dst16 + BlockY * 480 * 2; + for (BlockX = 0; BlockX < 160; BlockX++) + { + // Before: After: + // (a) (1)(1) + // (2)(2) + + uint16_t _1 = *(BlockSrc); + uint16_t _2 = Weight2_1( _1, gcolor); + + // -- Row 1 -- + *(BlockDst ) = _1; + *(BlockDst + 1) = _1; + + // -- Row 2 -- + *(BlockDst + 480 * 1 ) = _2; + *(BlockDst + 480 * 1 + 1) = _2; + + BlockSrc += 1; + BlockDst += 2; + } + } +} + +void scaleborder2x(uint32_t* dst, uint32_t* src) +{ + uint16_t* Src16 = (uint16_t*) src; + uint16_t* Dst16 = (uint16_t*) dst; + + uint32_t BlockX, BlockY; + uint16_t* BlockSrc; + uint16_t* BlockDst; + for (BlockY = 0; BlockY < 160; BlockY++) + { + BlockSrc = Src16 + BlockY * 240 * 1; + BlockDst = Dst16 + BlockY * 480 * 2; + for (BlockX = 0; BlockX < 240; BlockX++) + { + // Before: After: + // (a) (a)(a) + // (a)(a) + + uint16_t _1 = *(BlockSrc); + + // -- Row 1 -- + *(BlockDst ) = _1; + *(BlockDst + 1) = _1; + + // -- Row 2 -- + *(BlockDst + 480 * 1 ) = _1; + *(BlockDst + 480 * 1 + 1) = _1; + + BlockSrc += 1; + BlockDst += 2; + } + } +} + +void scaleborder2x_crt(uint32_t* dst, uint32_t* src) +{ + uint16_t* Src16 = (uint16_t*) src; + uint16_t* Dst16 = (uint16_t*) dst; + uint16_t gcolor = hexcolor_to_rgb565(0x000000); + + uint32_t BlockX, BlockY; + uint16_t* BlockSrc; + uint16_t* BlockDst; + for (BlockY = 0; BlockY < 160; BlockY++) + { + BlockSrc = Src16 + BlockY * 240 * 1; + BlockDst = Dst16 + BlockY * 480 * 2; + for (BlockX = 0; BlockX < 240; BlockX++) + { + // Before: After: + // (a) (1)(1) + // (2)(2) + + uint16_t _1 = *(BlockSrc); + uint16_t _2 = Weight2_1( _1, gcolor); + + // -- Row 1 -- + *(BlockDst ) = _1; + *(BlockDst + 1) = _1; + + // -- Row 2 -- + *(BlockDst + 480 * 1 ) = _2; + *(BlockDst + 480 * 1 + 1) = _2; + + BlockSrc += 1; + BlockDst += 2; + } + } } +#elif VGA_SCREEN + /* Upscales a 160x144 image to 480x432 using a grid-looking upscaler algorithm. * * Input: diff --git a/gambatte_sdl/scaler.h b/gambatte_sdl/scaler.h index f5d05d6..fb40568 100644 --- a/gambatte_sdl/scaler.h +++ b/gambatte_sdl/scaler.h @@ -19,7 +19,12 @@ void fullscreen_upscale(uint32_t *to, uint32_t *from); void fullscreen_upscale_pseudobilinear(uint32_t* dst, uint32_t* src); void scaleborder15x(uint32_t* dst, uint32_t* src); void scaleborder166x(uint32_t* dst, uint32_t* src); -#ifdef VGA_SCREEN +#ifdef OGA_SCREEN +void scale2x_dotmatrix(uint32_t* dst, uint32_t* src, const uint32_t gridcolor); +void scale2x_crt(uint32_t* dst, uint32_t* src); +void scaleborder2x(uint32_t* dst, uint32_t* src); +void scaleborder2x_crt(uint32_t* dst, uint32_t* src); +#elif VGA_SCREEN void scale3x_dotmatrix(uint32_t* dst, uint32_t* src, const uint32_t gridcolor); void scale3x_crt(uint32_t* dst, uint32_t* src); void fullscreen_crt(uint32_t* dst, uint32_t* src); diff --git a/gambatte_sdl/src/sdlblitter.cpp b/gambatte_sdl/src/sdlblitter.cpp index 77f729e..a5243a2 100644 --- a/gambatte_sdl/src/sdlblitter.cpp +++ b/gambatte_sdl/src/sdlblitter.cpp @@ -27,6 +27,7 @@ #include #include #include +#include SDL_Surface *lastframe; SDL_Surface *currframe; @@ -91,15 +92,17 @@ void init_border(SDL_Surface *dst){ void SdlBlitter::CheckIPU(){ FILE *aspect_ratio_file = NULL; - std::string ipu_OpenDingux = ("/sys/devices/platform/jz-lcd.0/keep_aspect_ratio"); + DIR *ipu_dir = NULL; + std::string ipu_OpenDinguxLegacy = ("/sys/devices/platform/jz-lcd.0/keep_aspect_ratio"); std::string ipu_RetroFW10 = ("/proc/jz/ipu_ratio"); std::string ipu_RetroFW20 = ("/proc/jz/ipu"); + std::string ipu_OpenDingux = ("/sys/devices/platform/13080000.ipu"); - aspect_ratio_file = fopen(ipu_OpenDingux.c_str(), "r+"); + aspect_ratio_file = fopen(ipu_OpenDinguxLegacy.c_str(), "r+"); if (aspect_ratio_file != NULL) { fclose(aspect_ratio_file); - ipuscaling = ipu_OpenDingux; - printf("Detected IPU scaling - OpenDingux\n"); + ipuscaling = ipu_OpenDinguxLegacy; + printf("Detected IPU scaling - OpenDinguxLegacy\n"); return; } aspect_ratio_file = fopen(ipu_RetroFW10.c_str(), "r+"); @@ -116,6 +119,13 @@ void SdlBlitter::CheckIPU(){ printf("Detected IPU scaling - RetroFW 2.X\n"); return; } + ipu_dir = opendir("/sys/devices/platform/13080000.ipu"); + if (ipu_dir != NULL) { + closedir(ipu_dir); + ipuscaling = "NEW_OD_IPU"; + printf("Detected IPU scaling - OpenDingux\n"); + return; + } printf("Could not detect IPU scaling\n"); return; } @@ -137,8 +147,10 @@ void SdlBlitter::setBufferDimensions() { FILE* aspect_ratio_file = fopen(ipuscaling.c_str(), "w"); #ifdef VGA_SCREEN FILE* sharpness_file = fopen("/sys/devices/platform/jz-lcd.0/sharpness_upscaling", "w"); - fwrite("1", 1, 1, sharpness_file); - fclose(sharpness_file); + if (sharpness_file) { + fwrite("1", 1, 1, sharpness_file); + fclose(sharpness_file); + } #endif switch(selectedscaler) { case 0: /* no scaler */ @@ -212,8 +224,10 @@ void SdlBlitter::setScreenRes() { FILE* aspect_ratio_file = fopen(ipuscaling.c_str(), "w"); #ifdef VGA_SCREEN FILE* sharpness_file = fopen("/sys/devices/platform/jz-lcd.0/sharpness_upscaling", "w"); - fwrite("1", 1, 1, sharpness_file); - fclose(sharpness_file); + if (sharpness_file) { + fwrite("1", 1, 1, sharpness_file); + fclose(sharpness_file); + } #endif switch(selectedscaler) { case 0: /* no scaler */