aboutsummaryrefslogtreecommitdiffstats
path: root/src/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render.c')
-rw-r--r--src/render.c45
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" : "");
}