more steps towards hdmi support

This commit is contained in:
Shaun Inman 2023-03-02 22:15:22 -05:00
parent 6a7a06aba5
commit 9da9a8720d
5 changed files with 196 additions and 123 deletions

View file

@ -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;

View file

@ -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

View file

@ -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_ratio<target_ratio) {
target_w = CEIL_DIV(dst_h, ratio_right) * ratio_left;
target_h = src_h * scale;
}
sprintf(scaler_name, "AR_%iXD", scale);
else if (core.aspect_ratio>target_ratio) {
target_w = src_w * scale;
target_h = CEIL_DIV(dst_w, ratio_left) * ratio_right;
}
sprintf(scaler_name, "AR_%iXU", 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; i<end; i++,j++) {
MenuItem* item = &items[i];
SDL_Color text_color = COLOR_WHITE;
// int ox = (SCREEN_WIDTH - w) / 2; // if we're centering these (but I don't think we should after seeing it)
// int ox = (screen->w - 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; i<end; i++,j++) {
@ -3441,10 +3474,10 @@ static int Menu_options(MenuList* list) {
if (count>MAX_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 (end<count) GFX_blitAsset(ASSET_SCROLL_DOWN, NULL, screen, &(SDL_Rect){ox, SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE + BUTTON_SIZE) + oy});
if (end<count) GFX_blitAsset(ASSET_SCROLL_DOWN, NULL, screen, &(SDL_Rect){ox, screen->h - 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);
}

View file

@ -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;

View file

@ -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