From 9da9a8720d1edf45569ea8aa143c026490808346 Mon Sep 17 00:00:00 2001 From: Shaun Inman Date: Thu, 2 Mar 2023 22:15:22 -0500 Subject: [PATCH] more steps towards hdmi support --- src/common/api.c | 35 +++---- src/common/api.h | 1 + src/minarch/main.c | 255 ++++++++++++++++++++++++++++----------------- src/minui/main.c | 19 +++- todo.txt | 9 +- 5 files changed, 196 insertions(+), 123 deletions(-) diff --git a/src/common/api.c b/src/common/api.c index 35542d7..425b207 100644 --- a/src/common/api.c +++ b/src/common/api.c @@ -31,17 +31,17 @@ void LOG_note(int level, const char* fmt, ...) { switch(level) { #ifdef DEBUG case LOG_DEBUG: - printf("DEBUG: %s", buf); + printf("[DEBUG] %s", buf); break; #endif case LOG_INFO: - printf("INFO: %s", buf); + printf("[INFO] %s", buf); break; case LOG_WARN: - fprintf(stderr, "WARN: %s", buf); + fprintf(stderr, "[WARN] %s", buf); break; case LOG_ERROR: - fprintf(stderr, "ERROR: %s", buf); + fprintf(stderr, "[ERROR] %s", buf); break; default: break; @@ -247,8 +247,8 @@ SDL_Surface* GFX_init(int mode) { ioctl(gfx.fb0_fd, FBIOGET_FSCREENINFO, &gfx.finfo); ioctl(gfx.fb0_fd, FBIOGET_VSCREENINFO, &gfx.vinfo); gfx.vinfo.bits_per_pixel = FIXED_DEPTH; - gfx.vinfo.xres = SCREEN_WIDTH; - gfx.vinfo.yres = SCREEN_HEIGHT; + gfx.vinfo.xres = FIXED_WIDTH; + gfx.vinfo.yres = FIXED_HEIGHT; gfx.vinfo.xres_virtual = VIRTUAL_WIDTH; gfx.vinfo.yres_virtual = VIRTUAL_HEIGHT; gfx.vinfo.xoffset = 0; @@ -275,7 +275,7 @@ SDL_Surface* GFX_init(int mode) { gfx.fb0_buffer = mmap(0, gfx.finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, gfx.fb0_fd, 0); memset(gfx.fb0_buffer, 0, VIRTUAL_SIZE); // clear both buffers - gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), SCREEN_WIDTH,SCREEN_HEIGHT, FIXED_DEPTH,SCREEN_PITCH, 0,0,0,0); + gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), FIXED_WIDTH,FIXED_HEIGHT, FIXED_DEPTH,FIXED_PITCH, 0,0,0,0); ////////////////////////////// @@ -329,10 +329,10 @@ void GFX_quit(void) { // restore for other binaries gfx.vinfo.bits_per_pixel = FIXED_DEPTH; - gfx.vinfo.xres = SCREEN_WIDTH; - gfx.vinfo.yres = SCREEN_HEIGHT; - gfx.vinfo.xres_virtual = SCREEN_WIDTH; - gfx.vinfo.yres_virtual = SCREEN_HEIGHT; + gfx.vinfo.xres = FIXED_WIDTH; + gfx.vinfo.yres = FIXED_HEIGHT; + gfx.vinfo.xres_virtual = FIXED_WIDTH; + gfx.vinfo.yres_virtual = FIXED_HEIGHT; gfx.vinfo.xoffset = 0; gfx.vinfo.yoffset = 0; if (ioctl(gfx.fb0_fd, FBIOPUT_VSCREENINFO, &gfx.vinfo)) LOG_info("FBIOPUT_VSCREENINFO failed %s\n", strerror(errno)); @@ -373,7 +373,6 @@ SDL_Surface* GFX_resize(int w, int h, int pitch) { if (gfx.screen) SDL_FreeSurface(gfx.screen); gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), w,h, FIXED_DEPTH,pitch, 0,0,0,0); - LOG_info("fb offset: %i end: %i all: %i\n", gfx.screen->pixels - gfx.fb0_buffer, gfx.screen->pixels - gfx.fb0_buffer + PAGE_SIZE, gfx.finfo.smem_len); memset(gfx.screen->pixels, 0, PAGE_SIZE); gfx.vinfo.xres = w; @@ -641,7 +640,7 @@ void GFX_blitButton(char* hint, char*button, SDL_Surface* dst, SDL_Rect* dst_rec SDL_FreeSurface(text); } void GFX_blitMessage(char* msg, SDL_Surface* dst, SDL_Rect* dst_rect) { - if (dst_rect==NULL) dst_rect = &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT}; + if (dst_rect==NULL) dst_rect = &(SDL_Rect){0,0,dst->w,dst->h}; SDL_Surface* text; #define TEXT_BOX_MAX_ROWS 16 @@ -696,7 +695,7 @@ int GFX_blitHardwareGroup(SDL_Surface* dst, int show_setting) { if (show_setting) { ow = SCALE1(PILL_SIZE + SETTINGS_WIDTH + PADDING + 4); - ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; + ox = dst->w - SCALE1(PADDING) - ow; oy = SCALE1(PADDING); GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){ ox, @@ -742,7 +741,7 @@ int GFX_blitHardwareGroup(SDL_Surface* dst, int show_setting) { } else { ow = SCALE1(PILL_SIZE); - ox = SCREEN_WIDTH - SCALE1(PADDING) - ow; + ox = dst->w - SCALE1(PADDING) - ow; oy = SCALE1(PADDING); GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){ ox, @@ -770,8 +769,8 @@ int GFX_blitButtonGroup(char** pairs, SDL_Surface* dst, int align_right) { int w = 0; // individual button dimension int h = 0; // hints index ow = 0; // full pill width - ox = align_right ? SCREEN_WIDTH - SCALE1(PADDING) : SCALE1(PADDING); - oy = SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE); + ox = align_right ? dst->w - SCALE1(PADDING) : SCALE1(PADDING); + oy = dst->h - SCALE1(PADDING + PILL_SIZE); for (int i=0; i<2; i++) { if (!pairs[i*2]) break; @@ -840,7 +839,7 @@ void GFX_sizeText(TTF_Font* font, char* str, int leading, int* w, int* h) { *w = mw; } void GFX_blitText(TTF_Font* font, char* str, int leading, SDL_Color color, SDL_Surface* dst, SDL_Rect* dst_rect) { - if (dst_rect==NULL) dst_rect = &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT}; + if (dst_rect==NULL) dst_rect = &(SDL_Rect){0,0,dst->w,dst->h}; char* lines[MAX_TEXT_LINES]; int count = 0; diff --git a/src/common/api.h b/src/common/api.h index 56f05b4..ab506ae 100644 --- a/src/common/api.h +++ b/src/common/api.h @@ -31,6 +31,7 @@ void LOG_note(int level, const char* fmt, ...); #define HDMI_HEIGHT 720 #define HDMI_PITCH HDMI_WIDTH * FIXED_BPP #define HDMI_SIZE HDMI_HEIGHT * HDMI_PITCH +#define HDMI_MENU_WIDTH 856 // FIXED_WIDTH * FIXED_HEIGHT / HDMI_HEIGHT rounded up to nearest 8 #define PAGE_COUNT 2 #define PAGE_SCALE 2 diff --git a/src/minarch/main.c b/src/minarch/main.c index 45c409e..6d5adcc 100644 --- a/src/minarch/main.c +++ b/src/minarch/main.c @@ -1500,7 +1500,7 @@ enum { #define DIGIT_SPACE DIGIT_COUNT static void MSG_init(void) { // TODO: scale - digits = SDL_CreateRGBSurface(SDL_SWSURFACE,DIGIT_WIDTH*DIGIT_COUNT,DIGIT_HEIGHT,SCREEN_DEPTH, 0,0,0,0); + digits = SDL_CreateRGBSurface(SDL_SWSURFACE,DIGIT_WIDTH*DIGIT_COUNT,DIGIT_HEIGHT,FIXED_DEPTH, 0,0,0,0); SDL_FillRect(digits, NULL, RGB_BLACK); SDL_Surface* digit; @@ -1610,9 +1610,9 @@ static void scale1x(void* __restrict src, void* __restrict dst, uint32_t w, uint // eg. gb has a 160 pixel wide image but // gambatte uses a 256 pixel wide buffer // (only matters when using memcpy) - int src_pitch = w * SCREEN_BPP; - int src_stride = pitch / SCREEN_BPP; - int dst_stride = dst_pitch / SCREEN_BPP; + int src_pitch = w * FIXED_BPP; + int src_stride = pitch / FIXED_BPP; + int dst_stride = dst_pitch / FIXED_BPP; int cpy_pitch = MIN(src_pitch, dst_pitch); uint16_t* restrict src_row = (uint16_t*)src; @@ -1629,9 +1629,9 @@ static void scale1x_scanline(void* __restrict src, void* __restrict dst, uint32_ // eg. gb has a 160 pixel wide image but // gambatte uses a 256 pixel wide buffer // (only matters when using memcpy) - int src_pitch = w * SCREEN_BPP; - int src_stride = 2 * pitch / SCREEN_BPP; - int dst_stride = 2 * dst_pitch / SCREEN_BPP; + int src_pitch = w * FIXED_BPP; + int src_stride = 2 * pitch / FIXED_BPP; + int dst_stride = 2 * dst_pitch / FIXED_BPP; int cpy_pitch = MIN(src_pitch, dst_pitch); uint16_t k = 0x0000; @@ -1661,8 +1661,8 @@ static void scale2x(void* __restrict src, void* __restrict dst, uint32_t w, uint *(dst_row + 1 ) = s; // row 2 - *(dst_row + SCREEN_WIDTH ) = s; - *(dst_row + SCREEN_WIDTH + 1) = s; + *(dst_row + PAGE_WIDTH ) = s; + *(dst_row + PAGE_WIDTH + 1) = s; src_row += 1; dst_row += 2; @@ -1683,8 +1683,8 @@ static void scale2x_lcd(void* __restrict src, void* __restrict dst, uint32_t w, *(dst_row ) = r; *(dst_row + 1 ) = b; - *(dst_row + SCREEN_WIDTH * 1 ) = g; - *(dst_row + SCREEN_WIDTH * 1 + 1) = k; + *(dst_row + PAGE_WIDTH * 1 ) = g; + *(dst_row + PAGE_WIDTH * 1 + 1) = k; src_row += 1; dst_row += 2; @@ -1703,8 +1703,8 @@ static void scale2x_scanline(void* __restrict src, void* __restrict dst, uint32_ *(dst_row ) = c1; *(dst_row + 1 ) = c1; - *(dst_row + SCREEN_WIDTH ) = c2; - *(dst_row + SCREEN_WIDTH + 1) = c2; + *(dst_row + PAGE_WIDTH ) = c2; + *(dst_row + PAGE_WIDTH + 1) = c2; src_row += 1; dst_row += 2; @@ -1723,8 +1723,8 @@ static void scale2x_grid(void* __restrict src, void* __restrict dst, uint32_t w, *(dst_row ) = c2; *(dst_row + 1 ) = c2; - *(dst_row + SCREEN_WIDTH ) = c2; - *(dst_row + SCREEN_WIDTH + 1) = c1; + *(dst_row + PAGE_WIDTH ) = c2; + *(dst_row + PAGE_WIDTH + 1) = c1; src_row += 1; dst_row += 2; @@ -1732,7 +1732,7 @@ static void scale2x_grid(void* __restrict src, void* __restrict dst, uint32_t w, } } static void scale3x(void* __restrict src, void* __restrict dst, uint32_t w, uint32_t h, uint32_t pitch, uint32_t dst_pitch) { - int row3 = SCREEN_WIDTH * 2; + int row3 = PAGE_WIDTH * 2; for (unsigned y = 0; y < h; y++) { uint16_t* restrict src_row = (void*)src + y * pitch; uint16_t* restrict dst_row = (void*)dst + y * dst_pitch * 3; @@ -1745,9 +1745,9 @@ static void scale3x(void* __restrict src, void* __restrict dst, uint32_t w, uint *(dst_row + 2) = s; // row 2 - *(dst_row + SCREEN_WIDTH ) = s; - *(dst_row + SCREEN_WIDTH + 1) = s; - *(dst_row + SCREEN_WIDTH + 2) = s; + *(dst_row + PAGE_WIDTH ) = s; + *(dst_row + PAGE_WIDTH + 1) = s; + *(dst_row + PAGE_WIDTH + 2) = s; // row 3 *(dst_row + row3 ) = s; @@ -1761,7 +1761,7 @@ static void scale3x(void* __restrict src, void* __restrict dst, uint32_t w, uint } static void scale3x_lcd(void* __restrict src, void* __restrict dst, uint32_t w, uint32_t h, uint32_t pitch, uint32_t dst_pitch) { uint16_t k = 0x0000; - int row3 = SCREEN_WIDTH * 2; + int row3 = PAGE_WIDTH * 2; for (unsigned y = 0; y < h; y++) { uint16_t* restrict src_row = (void*)src + y * pitch; uint16_t* restrict dst_row = (void*)dst + y * dst_pitch * 3; @@ -1777,9 +1777,9 @@ static void scale3x_lcd(void* __restrict src, void* __restrict dst, uint32_t w, *(dst_row + 2) = k; // row 2 - *(dst_row + SCREEN_WIDTH ) = r; - *(dst_row + SCREEN_WIDTH + 1) = g; - *(dst_row + SCREEN_WIDTH + 2) = b; + *(dst_row + PAGE_WIDTH ) = r; + *(dst_row + PAGE_WIDTH + 1) = g; + *(dst_row + PAGE_WIDTH + 2) = b; // row 3 *(dst_row + row3 ) = r; @@ -1793,7 +1793,7 @@ static void scale3x_lcd(void* __restrict src, void* __restrict dst, uint32_t w, } static void scale3x_dmg(void* __restrict src, void* __restrict dst, uint32_t w, uint32_t h, uint32_t pitch, uint32_t dst_pitch) { uint16_t g = 0xffff; - int row3 = SCREEN_WIDTH * 2; + int row3 = PAGE_WIDTH * 2; for (unsigned y = 0; y < h; y++) { uint16_t* restrict src_row = (void*)src + y * pitch; uint16_t* restrict dst_row = (void*)dst + y * dst_pitch * 3; @@ -1808,9 +1808,9 @@ static void scale3x_dmg(void* __restrict src, void* __restrict dst, uint32_t w, *(dst_row + 2) = a; // row 2 - *(dst_row + SCREEN_WIDTH ) = b; - *(dst_row + SCREEN_WIDTH + 1) = a; - *(dst_row + SCREEN_WIDTH + 2) = a; + *(dst_row + PAGE_WIDTH ) = b; + *(dst_row + PAGE_WIDTH + 1) = a; + *(dst_row + PAGE_WIDTH + 2) = a; // row 3 *(dst_row + row3 ) = c; @@ -1837,14 +1837,14 @@ static void scale3x_scanline(void* __restrict src, void* __restrict dst, uint32_ *(dst_row + 2) = c2; // row 2 - *(dst_row + SCREEN_WIDTH * 1 ) = c1; - *(dst_row + SCREEN_WIDTH * 1 + 1) = c1; - *(dst_row + SCREEN_WIDTH * 1 + 2) = c1; + *(dst_row + PAGE_WIDTH * 1 ) = c1; + *(dst_row + PAGE_WIDTH * 1 + 1) = c1; + *(dst_row + PAGE_WIDTH * 1 + 2) = c1; // row 3 - *(dst_row + SCREEN_WIDTH * 2 ) = c1; - *(dst_row + SCREEN_WIDTH * 2 + 1) = c1; - *(dst_row + SCREEN_WIDTH * 2 + 2) = c1; + *(dst_row + PAGE_WIDTH * 2 ) = c1; + *(dst_row + PAGE_WIDTH * 2 + 1) = c1; + *(dst_row + PAGE_WIDTH * 2 + 2) = c1; src_row += 1; dst_row += 3; @@ -1867,14 +1867,14 @@ static void scale3x_grid(void* __restrict src, void* __restrict dst, uint32_t w, *(dst_row + 2) = c1; // row 2 - *(dst_row + SCREEN_WIDTH * 1 ) = c2; - *(dst_row + SCREEN_WIDTH * 1 + 1) = c1; - *(dst_row + SCREEN_WIDTH * 1 + 2) = c1; + *(dst_row + PAGE_WIDTH * 1 ) = c2; + *(dst_row + PAGE_WIDTH * 1 + 1) = c1; + *(dst_row + PAGE_WIDTH * 1 + 2) = c1; // row 3 - *(dst_row + SCREEN_WIDTH * 2 ) = c3; - *(dst_row + SCREEN_WIDTH * 2 + 1) = c2; - *(dst_row + SCREEN_WIDTH * 2 + 2) = c2; + *(dst_row + PAGE_WIDTH * 2 ) = c3; + *(dst_row + PAGE_WIDTH * 2 + 1) = c2; + *(dst_row + PAGE_WIDTH * 2 + 2) = c2; src_row += 1; dst_row += 3; @@ -1882,8 +1882,8 @@ static void scale3x_grid(void* __restrict src, void* __restrict dst, uint32_t w, } } static void scale4x(void* __restrict src, void* __restrict dst, uint32_t w, uint32_t h, uint32_t pitch, uint32_t dst_pitch) { - int row3 = SCREEN_WIDTH * 2; - int row4 = SCREEN_WIDTH * 3; + int row3 = PAGE_WIDTH * 2; + int row4 = PAGE_WIDTH * 3; for (unsigned y = 0; y < h; y++) { uint16_t* restrict src_row = (void*)src + y * pitch; uint16_t* restrict dst_row = (void*)dst + y * dst_pitch * 4; @@ -1897,10 +1897,10 @@ static void scale4x(void* __restrict src, void* __restrict dst, uint32_t w, uint *(dst_row + 3) = s; // row 2 - *(dst_row + SCREEN_WIDTH ) = s; - *(dst_row + SCREEN_WIDTH + 1) = s; - *(dst_row + SCREEN_WIDTH + 2) = s; - *(dst_row + SCREEN_WIDTH + 3) = s; + *(dst_row + PAGE_WIDTH ) = s; + *(dst_row + PAGE_WIDTH + 1) = s; + *(dst_row + PAGE_WIDTH + 2) = s; + *(dst_row + PAGE_WIDTH + 3) = s; // row 3 *(dst_row + row3 ) = s; @@ -1920,8 +1920,8 @@ static void scale4x(void* __restrict src, void* __restrict dst, uint32_t w, uint } } static void scale4x_scanline(void* __restrict src, void* __restrict dst, uint32_t w, uint32_t h, uint32_t pitch, uint32_t dst_pitch) { - int row3 = SCREEN_WIDTH * 2; - int row4 = SCREEN_WIDTH * 3; + int row3 = PAGE_WIDTH * 2; + int row4 = PAGE_WIDTH * 3; uint16_t k = 0x0000; for (unsigned y = 0; y < h; y++) { uint16_t* restrict src_row = (void*)src + y * pitch; @@ -1937,10 +1937,10 @@ static void scale4x_scanline(void* __restrict src, void* __restrict dst, uint32_ *(dst_row + 3) = c1; // row 2 - *(dst_row + SCREEN_WIDTH ) = c2; - *(dst_row + SCREEN_WIDTH + 1) = c2; - *(dst_row + SCREEN_WIDTH + 2) = c2; - *(dst_row + SCREEN_WIDTH + 3) = c2; + *(dst_row + PAGE_WIDTH ) = c2; + *(dst_row + PAGE_WIDTH + 1) = c2; + *(dst_row + PAGE_WIDTH + 2) = c2; + *(dst_row + PAGE_WIDTH + 3) = c2; // row 3 *(dst_row + row3 ) = c1; @@ -1964,7 +1964,7 @@ static void scaleNN(void* __restrict src, void* __restrict dst, uint32_t w, uint int dy = -renderer.dst_h; unsigned lines = h; bool copy = false; - size_t cpy_w = renderer.dst_w * SCREEN_BPP; + size_t cpy_w = renderer.dst_w * FIXED_BPP; while (lines) { int dx = -renderer.dst_w; @@ -2041,7 +2041,7 @@ static void scaleNN_text(void* __restrict src, void* __restrict dst, uint32_t w, unsigned lines = h; bool copy = false; - size_t cpy_w = renderer.dst_w * SCREEN_BPP; + size_t cpy_w = renderer.dst_w * FIXED_BPP; int safe = w - 1; // don't look behind when there's nothing to see uint16_t l1,l2; @@ -2053,8 +2053,8 @@ static void scaleNN_text(void* __restrict src, void* __restrict dst, uint32_t w, if (copy) { copy = false; - memcpy(dst, dst - SCREEN_PITCH, cpy_w); - dst += SCREEN_PITCH; + memcpy(dst, dst - FIXED_PITCH, cpy_w); + dst += FIXED_PITCH; dy += h; } else if (dy < 0) { int col = w; @@ -2085,7 +2085,7 @@ static void scaleNN_text(void* __restrict src, void* __restrict dst, uint32_t w, psrc16++; } - dst += SCREEN_PITCH; + dst += FIXED_PITCH; dy += h; } @@ -2157,13 +2157,18 @@ static void scaleNN_text_scanline(void* __restrict src, void* __restrict dst, ui static SDL_Surface* scaler_surface; static void selectScaler_PAR(int width, int height, int pitch) { + int has_hdmi = GetHDMI(); + int device_width = has_hdmi ? HDMI_WIDTH : SCREEN_WIDTH; + int device_height = has_hdmi ? HDMI_HEIGHT : SCREEN_HEIGHT; + int device_pitch = has_hdmi ? HDMI_PITCH : SCREEN_PITCH; + renderer.scaler = scaleNull; - renderer.dst_p = SCREEN_PITCH; + renderer.dst_p = device_pitch; int use_nearest = 0; - int scale_x = SCREEN_WIDTH / width; - int scale_y = SCREEN_HEIGHT / height; + int scale_x = device_width / width; + int scale_y = device_height / height; int scale = MIN(scale_x,scale_y); // this is not an aspect ratio but rather the ratio between @@ -2194,11 +2199,11 @@ static void selectScaler_PAR(int width, int height, int pitch) { renderer.dst_w -= renderer.dst_w % 2; } - if (renderer.dst_w>SCREEN_WIDTH) { - renderer.dst_w = SCREEN_WIDTH; + if (renderer.dst_w>device_width) { + renderer.dst_w = device_width; renderer.dst_h = renderer.dst_w / core.aspect_ratio; renderer.dst_h -= renderer.dst_w % 2; - if (renderer.dst_h>SCREEN_HEIGHT) renderer.dst_h = SCREEN_HEIGHT; + if (renderer.dst_h>device_height) renderer.dst_h = device_height; } } else if (scale_x>scale_y) { @@ -2216,11 +2221,11 @@ static void selectScaler_PAR(int width, int height, int pitch) { renderer.dst_h -= renderer.dst_w % 2; } - if (renderer.dst_h>SCREEN_HEIGHT) { - renderer.dst_h = SCREEN_HEIGHT; + if (renderer.dst_h>device_height) { + renderer.dst_h = device_height; renderer.dst_w = renderer.dst_h * core.aspect_ratio; renderer.dst_w -= renderer.dst_w % 2; - if (renderer.dst_w>SCREEN_WIDTH) renderer.dst_w = SCREEN_WIDTH; + if (renderer.dst_w>device_width) renderer.dst_w = device_width; } } else { @@ -2245,11 +2250,11 @@ static void selectScaler_PAR(int width, int height, int pitch) { } } - if (renderer.dst_w>SCREEN_WIDTH) { - renderer.dst_w = SCREEN_WIDTH; + if (renderer.dst_w>device_width) { + renderer.dst_w = device_width; } - if (renderer.dst_h>SCREEN_HEIGHT) { - renderer.dst_h = SCREEN_HEIGHT; + if (renderer.dst_h>device_height) { + renderer.dst_h = device_height; } } } @@ -2259,9 +2264,9 @@ static void selectScaler_PAR(int width, int height, int pitch) { renderer.dst_h = height * scale; } - int ox = (SCREEN_WIDTH - renderer.dst_w) / 2; - int oy = (SCREEN_HEIGHT - renderer.dst_h) / 2; - renderer.dst_offset = (oy * SCREEN_PITCH) + (ox * SCREEN_BPP); + int ox = (device_width - renderer.dst_w) / 2; + int oy = (device_height - renderer.dst_h) / 2; + renderer.dst_offset = (oy * device_pitch) + (ox * FIXED_BPP); if (use_nearest) if (show_scanlines) renderer.scaler = optimize_text ? scaleNN_text_scanline : scaleNN_scanline; @@ -2270,6 +2275,8 @@ static void selectScaler_PAR(int width, int height, int pitch) { sprintf(scaler_name, "%iX", scale); if (show_scanlines) { switch (scale) { + case 6: renderer.scaler = scaleNN_scanline; break; + case 5: renderer.scaler = scaleNN_scanline; break; case 4: renderer.scaler = scale4x_scanline; break; case 3: renderer.scaler = scale3x_grid; break; case 2: renderer.scaler = scale2x_scanline; break; @@ -2278,6 +2285,8 @@ static void selectScaler_PAR(int width, int height, int pitch) { } else { switch (scale) { + case 6: renderer.scaler = scale6x_n16; break; + case 5: renderer.scaler = scale5x_n16; break; case 4: renderer.scaler = scale4x_n16; break; case 3: renderer.scaler = scale3x_n16; break; case 2: renderer.scaler = scale2x_n16; break; @@ -2302,7 +2311,7 @@ static void selectScaler_PAR(int width, int height, int pitch) { if (scaler_surface) SDL_FreeSurface(scaler_surface); scaler_surface = TTF_RenderUTF8_Blended(font.tiny, scaler_name, COLOR_WHITE); - screen = GFX_resize(SCREEN_WIDTH,SCREEN_HEIGHT, SCREEN_PITCH); + screen = GFX_resize(device_width,device_height, device_pitch); } static void selectScaler_AR(int width, int height, int pitch) { renderer.scaler = scaleNull; @@ -2339,13 +2348,18 @@ static void selectScaler_AR(int width, int height, int pitch) { double target_ratio = has_hdmi ? SIXTEEN_NINE : FOUR_THREE; + // TODO: sotn moon is busted 512x240 ends up 2x but targeting 864x480 + if (screen_scaling==1) { sprintf(scaler_name, "AR_%iX%s", scale, has_hdmi?"W":"R"); if (core.aspect_ratio==target_ratio) { - // LOG("already correct ratio\n"); + LOG_info("already correct ratio\n"); } else { // TODO: is this ignoring the core's desired aspect ratio? + // see snes or SotN + // I think it's acting more like PAR + sprintf(scaler_name, "AR_%iX%sR", scale, has_hdmi?"W":"R"); int ratio_left = target_ratio==SIXTEEN_NINE ? 16 : 4; int ratio_right = target_ratio==SIXTEEN_NINE ? 9 : 3; @@ -2364,15 +2378,26 @@ static void selectScaler_AR(int width, int height, int pitch) { // TODO: if (target_w > PAGE_WIDTH) { - target_h = CEIL_DIV(PAGE_WIDTH, ratio_left) * ratio_right; target_w = PAGE_WIDTH; + target_h = CEIL_DIV(PAGE_WIDTH, ratio_left) * ratio_right; if (dst_h > target_h) { scale -= 1; dst_w = src_w * scale; dst_h = src_h * scale; + + // adjust again... (copy/pasted with modifications from above) + if (core.aspect_ratiotarget_ratio) { + target_w = src_w * scale; + target_h = CEIL_DIV(dst_w, ratio_left) * ratio_right; + } + sprintf(scaler_name, "AR_%iXU", scale); } - sprintf(scaler_name, "AR_%iXD", scale); + else sprintf(scaler_name, "AR_%iXD", scale); LOG_warn("target: %ix%i (%i) page: %ix%i (%i) \n", target_w,target_h, target_w*target_h*FIXED_BPP, PAGE_WIDTH,PAGE_HEIGHT,PAGE_SIZE); } @@ -2436,6 +2461,14 @@ static void video_refresh_callback(const void *data, unsigned width, unsigned he if (!data) return; + // force resize when hdmi status changes + static int had_hdmi = -1; + int has_hdmi = GetHDMI(); + if (had_hdmi!=has_hdmi) { + renderer.src_w = 0; + had_hdmi = has_hdmi; + } + fps_ticks += 1; if (width!=renderer.src_w || height!=renderer.src_h) { @@ -2680,7 +2713,7 @@ typedef struct __attribute__((__packed__)) uint24_t { uint8_t a,b,c; } uint24_t; static SDL_Surface* Menu_thumbnail(SDL_Surface* src_img) { - SDL_Surface* dst_img = SDL_CreateRGBSurface(0,SCREEN_WIDTH/2, SCREEN_HEIGHT/2,src_img->format->BitsPerPixel,src_img->format->Rmask,src_img->format->Gmask,src_img->format->Bmask,src_img->format->Amask); + SDL_Surface* dst_img = SDL_CreateRGBSurface(0,FIXED_WIDTH/2, FIXED_HEIGHT/2,src_img->format->BitsPerPixel,src_img->format->Rmask,src_img->format->Gmask,src_img->format->Bmask,src_img->format->Amask); uint8_t* src_px = src_img->pixels; uint8_t* dst_px = dst_img->pixels; @@ -2713,7 +2746,7 @@ static SDL_Surface* Menu_thumbnail(SDL_Surface* src_img) { } void Menu_init(void) { - menu.overlay = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, 0, 0, 0, 0); + menu.overlay = SDL_CreateRGBSurface(SDL_SWSURFACE, HDMI_WIDTH, HDMI_HEIGHT, FIXED_DEPTH, 0, 0, 0, 0); SDL_SetAlpha(menu.overlay, SDL_SRCALPHA, 0x80); SDL_FillRect(menu.overlay, NULL, 0); } @@ -3263,17 +3296,17 @@ static int Menu_options(MenuList* list) { if (w>mw) mw = w; } // cache the result - list->max_width = mw = MIN(mw, SCREEN_WIDTH - SCALE1(PADDING *2)); + list->max_width = mw = MIN(mw, screen->w - SCALE1(PADDING *2)); } - int ox = (SCREEN_WIDTH - mw) / 2; + int ox = (screen->w - mw) / 2; int oy = SCALE1(PADDING + PILL_SIZE); int selected_row = selected - start; for (int i=start,j=0; iw - w) / 2; // if we're centering these (but I don't think we should after seeing it) if (j==selected_row) { // move out of conditional if centering int w = 0; @@ -3300,7 +3333,7 @@ static int Menu_options(MenuList* list) { } else if (type==MENU_FIXED) { // NOTE: no need to calculate max width - int mw = SCREEN_WIDTH - SCALE1(PADDING*2); + int mw = screen->w - SCALE1(PADDING*2); int lw,rw; lw = rw = mw / 2; int ox,oy; @@ -3384,10 +3417,10 @@ static int Menu_options(MenuList* list) { } fflush(stdout); // cache the result - list->max_width = mw = MIN(mw, SCREEN_WIDTH - SCALE1(PADDING *2)); + list->max_width = mw = MIN(mw, screen->w - SCALE1(PADDING *2)); } - int ox = (SCREEN_WIDTH - mw) / 2; + int ox = (screen->w - mw) / 2; int oy = SCALE1(PADDING + PILL_SIZE); int selected_row = selected - start; for (int i=start,j=0; iMAX_VISIBLE_OPTIONS) { #define SCROLL_WIDTH 24 #define SCROLL_HEIGHT 4 - int ox = (SCREEN_WIDTH - SCALE1(SCROLL_WIDTH))/2; + int ox = (screen->w - SCALE1(SCROLL_WIDTH))/2; int oy = SCALE1((PILL_SIZE - SCROLL_HEIGHT) / 2); if (start>0) GFX_blitAsset(ASSET_SCROLL_UP, NULL, screen, &(SDL_Rect){ox, SCALE1(PADDING) + oy}); - if (endh - SCALE1(PADDING + PILL_SIZE + BUTTON_SIZE) + oy}); } if (!desc && list->desc) desc = list->desc; @@ -3453,8 +3486,8 @@ static int Menu_options(MenuList* list) { int w,h; GFX_sizeText(font.tiny, desc, SCALE1(12), &w,&h); GFX_blitText(font.tiny, desc, SCALE1(12), COLOR_WHITE, screen, &(SDL_Rect){ - (SCREEN_WIDTH - w) / 2, - SCREEN_HEIGHT - SCALE1(PADDING) - h, + (screen->w - w) / 2, + screen->h - SCALE1(PADDING) - h, w,h }); } @@ -3491,14 +3524,38 @@ static void downsample(void* __restrict src, void* __restrict dst, uint32_t w, u static void Menu_loop(void) { // current screen is on the previous buffer + + // TODO: can we use renderer.src_w/h to reverse the stretch regardless of HDMI status? + // because we need an undeformed copy for save state screenshots SDL_Surface* backing = GFX_getBufferCopy(); - SDL_Surface* resized = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_DEPTH,0,0,0,0); - if (backing->w==SCREEN_WIDTH && backing->h==SCREEN_HEIGHT) SDL_BlitSurface(backing, NULL, resized, NULL); + SDL_Surface* resized = SDL_CreateRGBSurface(SDL_SWSURFACE, FIXED_WIDTH,FIXED_HEIGHT,FIXED_DEPTH,0,0,0,0); + + if (backing->w==FIXED_WIDTH && backing->h==FIXED_HEIGHT) { + SDL_BlitSurface(backing, NULL, resized, NULL); + } else { - downsample(backing->pixels,resized->pixels,backing->w,backing->h,backing->pitch,SCREEN_PITCH); + downsample(backing->pixels,resized->pixels,backing->w,backing->h,backing->pitch,resized->pitch); + } + + // TODO: move this to right before if (dirty) {} like in minui.elf + // TODO: could move to a GFX_autosize(&dirty) -> has_hdmi + int has_hdmi = GetHDMI(); + + int target_w = has_hdmi ? HDMI_MENU_WIDTH : FIXED_WIDTH; // 640 * 480 / 720 rounded up to nearest 8 + int target_h = FIXED_HEIGHT; + int target_p = target_w * FIXED_BPP; + + LOG_info("hdmi: %i %ix%i (%i)\n", has_hdmi,target_w,target_h,target_p); + + if (has_hdmi && (screen->w!=target_w || screen->h!=target_h)) { + screen = GFX_resize(target_w,target_h,target_p); + } + else if (screen->w!=SCREEN_WIDTH || screen->h!=SCREEN_HEIGHT) { screen = GFX_resize(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_PITCH); } + // TODO: attempt to draw menu in center of screen when in hdmi + POW_warn(0); POW_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly GFX_setVsync(VSYNC_STRICT); @@ -3711,12 +3768,13 @@ static void Menu_loop(void) { POW_update(&dirty, &show_setting, Menu_beforeSleep, Menu_afterSleep); if (dirty) { + SDL_FillRect(screen, NULL, 0); SDL_BlitSurface(resized, NULL, screen, NULL); SDL_BlitSurface(menu.overlay, NULL, screen, NULL); int ox, oy; int ow = GFX_blitHardwareGroup(screen, show_setting); - int max_width = SCREEN_WIDTH - SCALE1(PADDING * 2) - ow; + int max_width = screen->w - SCALE1(PADDING * 2) - ow; char display_name[256]; int text_width = GFX_truncateText(font.large, rom_name, display_name, max_width); @@ -3760,12 +3818,12 @@ static void Menu_loop(void) { GFX_blitPill(ASSET_DARK_GRAY_PILL, screen, &(SDL_Rect){ SCALE1(PADDING), SCALE1(oy + PADDING), - SCREEN_WIDTH - SCALE1(PADDING * 2), + screen->w - SCALE1(PADDING * 2), SCALE1(PILL_SIZE) }); text = TTF_RenderUTF8_Blended(font.large, disc_name, COLOR_WHITE); SDL_BlitSurface(text, NULL, screen, &(SDL_Rect){ - SCREEN_WIDTH - SCALE1(PADDING + BUTTON_PADDING) - text->w, + screen->w - SCALE1(PADDING + BUTTON_PADDING) - text->w, SCALE1(oy + PADDING + 4) }); SDL_FreeSurface(text); @@ -3808,8 +3866,8 @@ static void Menu_loop(void) { // unscaled ox = 146; oy = 54; - int hw = SCREEN_WIDTH / 2; - int hh = SCREEN_HEIGHT / 2; + int hw = FIXED_WIDTH / 2; + int hh = FIXED_HEIGHT / 2; // preview window // GFX_blitWindow(screen, Screen.menu.preview.x, Screen.menu.preview.y, Screen.menu.preview.width, Screen.menu.preview.height, 1); @@ -3857,7 +3915,10 @@ static void Menu_loop(void) { GFX_clearAll(); if (!quit) { - if (backing->w!=SCREEN_WIDTH || backing->h!=SCREEN_HEIGHT) { + if (GetHDMI() && screen_scaling==SCALE_NATIVE) { + screen = GFX_resize(HDMI_WIDTH,HDMI_HEIGHT, HDMI_PITCH); + } + else if (backing->w!=FIXED_WIDTH || backing->h!=FIXED_HEIGHT) { screen = GFX_resize(renderer.dst_w,renderer.dst_h, renderer.dst_p); } diff --git a/src/minui/main.c b/src/minui/main.c index 8f972c1..1116ca8 100644 --- a/src/minui/main.c +++ b/src/minui/main.c @@ -1325,8 +1325,21 @@ int main (int argc, char *argv[]) { POW_update(&dirty, &show_setting, NULL, NULL); + static int had_hdmi = -1; + int has_hdmi = GetHDMI(); + if (had_hdmi!=has_hdmi) dirty = 1; + if (dirty) { - GFX_clear(screen); + if (had_hdmi!=has_hdmi) { + if (has_hdmi) { + screen = GFX_resize(HDMI_MENU_WIDTH,FIXED_HEIGHT,HDMI_MENU_WIDTH*FIXED_BPP); + } + else { + screen = GFX_resize(FIXED_WIDTH,FIXED_HEIGHT,FIXED_PITCH); + } + had_hdmi = has_hdmi; + } + else GFX_clear(screen); // resizing clears the screen int ox; int oy; @@ -1388,7 +1401,7 @@ int main (int argc, char *argv[]) { SDL_FreeSurface(key_txt); SDL_FreeSurface(val_txt); } - SDL_BlitSurface(version, NULL, screen, &(SDL_Rect){(SCREEN_WIDTH-version->w)/2,(SCREEN_HEIGHT-version->h)/2}); + SDL_BlitSurface(version, NULL, screen, &(SDL_Rect){(screen->w-version->w)/2,(screen->h-version->h)/2}); // buttons (duped and trimmed from below) if (show_setting) { @@ -1409,7 +1422,7 @@ int main (int argc, char *argv[]) { Entry* entry = top->entries->items[i]; char* entry_name = entry->name; char* entry_unique = entry->unique; - int available_width = SCREEN_WIDTH - SCALE1(PADDING * 2); + int available_width = screen->w - SCALE1(PADDING * 2); if (i==top->start) available_width -= ow; SDL_Color text_color = COLOR_WHITE; diff --git a/todo.txt b/todo.txt index 885d5f2..d2037ff 100644 --- a/todo.txt +++ b/todo.txt @@ -24,12 +24,11 @@ create a clean image to flash and install over add most recent uImage/kernel changes hdmi - for now I could add to a user auto.sh - cat /sys/class/switch/hdmi/state - echo 1 > /sys/class/graphics/fb0/mirror_to_hdmi - if connected to hdmi switch to aspect (if native) - and resize to address stretching 640x480 to 1280x720 ignore brightness shortcut when on hdmi + figure out how to handle renderng the menus + 856x480 will get round circles but it's still blurry... + it would be better if we could just go the full 1280x720 and change SCREEN_SCALE to 3... + audio minarch figure out how to handle different button mappings for cores with different modes