diff options
Diffstat (limited to 'src/render.c')
| -rw-r--r-- | src/render.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/render.c b/src/render.c index 4f612ae..1f232d8 100644 --- a/src/render.c +++ b/src/render.c @@ -477,6 +477,24 @@ const u8 *render_capture_frame(GB *gb, int *w, int *h) { return &fb[0][0][0]; } +// ---- half-block live-display downscale (--shrink N) ------------------------ +// Purely a *display* concern: the LCD is decimated N x N before the +// half-block encode, so the pane takes 160/N cols x 72/N rows. Capture, +// recording and sixel are untouched (they read the full-res framebuffer). +// Decimation is MAX-LUMA PICK, not box-average: terminal fonts are 1px +// bright strokes on dark background, and averaging dims them into grey +// mush. Keeping the brightest source pixel of each block preserves both +// stroke brightness and hue (it's always a real pixel, never a blend). +static int shrink = 1; +static u8 shrink_fb[SCREEN_H][SCREEN_W][3]; + +void render_set_shrink(int n) { + if (n < 1) n = 1; + if (n > 4) n = 4; + shrink = n; + resized = 1; // force a clear + full repaint +} + void render_frame(GB *gb) { if (sixel_enabled) { if (chrome_enabled) render_frame_chrome(gb); @@ -485,6 +503,27 @@ void render_frame(GB *gb) { } PPU *p = &gb->ppu; u8 (*fb)[SCREEN_W][3] = lcd_fb(p); + int W = SCREEN_W, H = SCREEN_H; + if (shrink > 1) { + W = SCREEN_W / shrink; + H = (SCREEN_H / shrink) & ~1; // even, so rows pair into cells + for (int y = 0; y < H; y++) + for (int x = 0; x < W; x++) { + u8 *best = fb[y*shrink][x*shrink]; + int bl = -1; + for (int dy = 0; dy < shrink; dy++) + for (int dx = 0; dx < shrink; dx++) { + u8 *s = fb[y*shrink + dy][x*shrink + dx]; + // integer luma: 2R + 5G + B (~BT.601) + int l = 2*s[0] + 5*s[1] + s[2]; + if (l > bl) { bl = l; best = s; } + } + shrink_fb[y][x][0] = best[0]; + shrink_fb[y][x][1] = best[1]; + shrink_fb[y][x][2] = best[2]; + } + fb = shrink_fb; + } char *o = outbuf; if (resized) { resized = 0; need_full = true; o += sprintf(o, "\x1b[2J"); } @@ -496,9 +535,9 @@ void render_frame(GB *gb) { int PR = -1, PG = -1, PB = -1; // last-emitted bg int cur_row = -2, cur_col = -2; // terminal cell just written (0-indexed) - for (int y = 0; y < SCREEN_H; y += 2) { + for (int y = 0; y < H; y += 2) { int row = y / 2; - for (int x = 0; x < SCREEN_W; x++) { + for (int x = 0; x < W; x++) { u8 *top = fb[y][x]; u8 *bot = fb[y+1][x]; if (!need_full) { @@ -528,7 +567,7 @@ void render_frame(GB *gb) { if (need_full) { o += sprintf(o, "\x1b[0m\x1b[%d;1H\x1b[38;2;150;150;150m %.*s " "skip:%d%s [f]ast [ ][ ] q:quit\x1b[K", - SCREEN_H/2 + 1, 12, gb->cart.title, + H/2 + 1, 12, gb->cart.title, hud_frameskip, hud_turbo ? " TURBO" : ""); } |
