# HG changeset patch # User Mike Pavone # Date 1568619948 25200 # Node ID 55198fc9cc1f283dcba336b98adbbf01ef02f2e3 # Parent e77f7a7c79a57832c8faf7ff1ef371dd3ef363c7 Don't render lines that are cropped by overscan. Allows submitting frame earlier when bottom overscan is non-zero which can reduce latency in some cases diff -r e77f7a7c79a5 -r 55198fc9cc1f libblastem.c --- a/libblastem.c Sat Sep 07 22:18:09 2019 -0700 +++ b/libblastem.c Mon Sep 16 00:45:48 2019 -0700 @@ -316,6 +316,16 @@ return 1; } +uint32_t render_overscan_top() +{ + return 0; +} + +uint32_t render_overscan_bot() +{ + return 0; +} + void process_events() { static int16_t prev_state[2][RETRO_DEVICE_ID_JOYPAD_L2]; diff -r e77f7a7c79a5 -r 55198fc9cc1f render.h --- a/render.h Sat Sep 07 22:18:09 2019 -0700 +++ b/render.h Mon Sep 16 00:45:48 2019 -0700 @@ -126,6 +126,7 @@ uint32_t render_emulated_width(); uint32_t render_emulated_height(); uint32_t render_overscan_top(); +uint32_t render_overscan_bot(); uint32_t render_overscan_left(); uint32_t render_elapsed_ms(void); void render_sleep_ms(uint32_t delay); diff -r e77f7a7c79a5 -r 55198fc9cc1f render_sdl.c --- a/render_sdl.c Sat Sep 07 22:18:09 2019 -0700 +++ b/render_sdl.c Mon Sep 16 00:45:48 2019 -0700 @@ -1624,6 +1624,11 @@ return overscan_top[video_standard]; } +uint32_t render_overscan_bot() +{ + return overscan_bot[video_standard]; +} + void render_wait_quit(void) { SDL_Event event; diff -r e77f7a7c79a5 -r 55198fc9cc1f vdp.c --- a/vdp.c Sat Sep 07 22:18:09 2019 -0700 +++ b/vdp.c Mon Sep 16 00:45:48 2019 -0700 @@ -70,28 +70,36 @@ {127, 0, 127} //Sprites }; +static uint32_t calc_crop(uint32_t crop, uint32_t border) +{ + return crop >= border ? 0 : border - crop; +} + static void update_video_params(vdp_context *context) { + uint32_t top_crop = render_overscan_top(); + uint32_t bot_crop = render_overscan_bot(); + uint32_t border_top; if (context->regs[REG_MODE_2] & BIT_MODE_5) { if (context->regs[REG_MODE_2] & BIT_PAL) { if (context->flags2 & FLAG2_REGION_PAL) { context->inactive_start = PAL_INACTIVE_START; - context->border_top = BORDER_TOP_V30_PAL; - context->border_bot = BORDER_BOT_V30_PAL; + border_top = BORDER_TOP_V30_PAL; + context->border_bot = calc_crop(bot_crop, BORDER_BOT_V30_PAL); } else { //the behavior here is rather weird and needs more investigation context->inactive_start = 0xF0; - context->border_top = 1; - context->border_bot = 3; + border_top = 1; + context->border_bot = calc_crop(bot_crop, 3); } } else { context->inactive_start = NTSC_INACTIVE_START; if (context->flags2 & FLAG2_REGION_PAL) { - context->border_top = BORDER_TOP_V28_PAL; - context->border_bot = BORDER_BOT_V28_PAL; + border_top = BORDER_TOP_V28_PAL; + context->border_bot = calc_crop(bot_crop, BORDER_BOT_V28_PAL); } else { - context->border_top = BORDER_TOP_V28; - context->border_bot = BORDER_TOP_V28; + border_top = BORDER_TOP_V28; + context->border_bot = calc_crop(bot_crop, BORDER_BOT_V28); } } if (context->regs[REG_MODE_4] & BIT_H40) { @@ -112,11 +120,11 @@ } else { context->inactive_start = MODE4_INACTIVE_START; if (context->flags2 & FLAG2_REGION_PAL) { - context->border_top = BORDER_TOP_V24_PAL; - context->border_bot = BORDER_BOT_V24_PAL; + border_top = BORDER_TOP_V24_PAL; + context->border_bot = calc_crop(bot_crop, BORDER_BOT_V24_PAL); } else { - context->border_top = BORDER_TOP_V24; - context->border_bot = BORDER_BOT_V24; + border_top = BORDER_TOP_V24; + context->border_bot = calc_crop(bot_crop, BORDER_BOT_V24); } if (!(context->regs[REG_MODE_1] & BIT_MODE_4)){ context->state = INACTIVE; @@ -130,6 +138,8 @@ } } } + context->border_top = calc_crop(top_crop, border_top); + context->top_offset = border_top - context->border_top; } static uint8_t color_map_init_done; @@ -138,8 +148,8 @@ { vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE); if (headless) { - context->output = malloc(LINEBUF_SIZE * sizeof(uint32_t)); - context->output_pitch = 0; + context->fb = malloc(512 * LINEBUF_SIZE * sizeof(uint32_t)); + context->output_pitch = LINEBUF_SIZE * sizeof(uint32_t); } else { context->cur_buffer = FRAMEBUFFER_ODD; context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); @@ -235,9 +245,7 @@ context->flags2 |= FLAG2_REGION_PAL; } update_video_params(context); - if (!headless) { - context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * context->border_top); - } + context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * context->border_top); return context; } @@ -2018,9 +2026,7 @@ void vdp_force_update_framebuffer(vdp_context *context) { - uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) - ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL - : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; + uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; uint16_t to_fill = lines_max - context->output_lines; memset( @@ -2035,52 +2041,47 @@ static void advance_output_line(vdp_context *context) { - if (headless) { - if (context->vcounter == context->inactive_start) { - context->frame++; - } - context->vcounter &= 0x1FF; - } else { - uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) - ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL - : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; + uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; - if (context->output_lines == lines_max) { + if (context->output_lines == lines_max) { + if (!headless) { render_framebuffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER)); context->cur_buffer = context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD; context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); - vdp_update_per_frame_debug(context); - context->h40_lines = 0; - context->frame++; + } + vdp_update_per_frame_debug(context); + context->h40_lines = 0; + context->frame++; + context->output_lines = 0; + } + uint32_t output_line = context->vcounter; + if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { + //vcounter increment occurs much later in Mode 4 + output_line++; + } + if (output_line < context->inactive_start + context->border_bot && context->output_lines > 0) { + output_line = context->output_lines++;//context->border_top + context->vcounter; + } else if (output_line >= 0x200 - context->border_top || (!context->border_top && !output_line)) { + if (output_line == 0x200 - context->border_top || (!context->border_top && !output_line)) { + //We're at the top of the display, force context->output_lines to be zero to avoid + //potential screen rolling if the mode is changed at an inopportune time context->output_lines = 0; } - uint32_t output_line = context->vcounter; - if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { - //vcounter increment occurs much later in Mode 4 - output_line++; - } - if (output_line < context->inactive_start + context->border_bot && context->output_lines > 0) { - output_line = context->output_lines++;//context->border_top + context->vcounter; - } else if (output_line >= 0x200 - context->border_top) { - if (output_line == 0x200 - context->border_top) { - //We're at the top of the display, force context->output_lines to be zero to avoid - //potential screen rolling if the mode is changed at an inopportune time - context->output_lines = 0; - } - output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); - } else { - context->output = NULL; - } - context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); + output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); + } else { + context->output = NULL; + return; + } + output_line += context->top_offset; + context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); #ifdef DEBUG_FB_FILL - for (int i = 0; i < LINEBUF_SIZE; i++) - { - context->output[i] = 0xFFFF00FF; - } + for (int i = 0; i < LINEBUF_SIZE; i++) + { + context->output[i] = 0xFFFF00FF; + } #endif - if (context->output && (context->regs[REG_MODE_4] & BIT_H40)) { - context->h40_lines++; - } + if (context->output && (context->regs[REG_MODE_4] & BIT_H40)) { + context->h40_lines++; } } @@ -2093,11 +2094,9 @@ void vdp_reacquire_framebuffer(vdp_context *context) { context->fb = render_get_framebuffer(context->cur_buffer, &context->output_pitch); - uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) - ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL - : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; + uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top; if (context->output_lines <= lines_max && context->output_lines > 0) { - context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1)); + context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1 + context->top_offset)); } else { context->output = NULL; } diff -r e77f7a7c79a5 -r 55198fc9cc1f vdp.h --- a/vdp.h Sat Sep 07 22:18:09 2019 -0700 +++ b/vdp.h Mon Sep 16 00:45:48 2019 -0700 @@ -185,6 +185,7 @@ uint32_t cycles; uint32_t pending_vint_start; uint32_t pending_hint_start; + uint32_t top_offset; uint16_t vsram[VSRAM_SIZE]; uint16_t vscroll_latch[2]; uint16_t vcounter;