+void renderer_finish(void)
+{
+ if (egpu.enhancement_buf_ptr != NULL) {
+ egpu.enhancement_buf_ptr -= 4096 / 2;
+ gpu.munmap(egpu.enhancement_buf_ptr, ENHANCEMENT_BUF_SIZE);
+ }
+ egpu.enhancement_buf_ptr = NULL;
+ egpu.enhancement_current_buf_ptr = NULL;
+ initialized = 0;
+}
+
+static __attribute__((noinline)) void
+sync_enhancement_buffers(int x, int y, int w, int h)
+{
+ const int step_x = 1024 / sizeof(egpu.enhancement_buf_by_x16);
+ int hres = egpu.saved_hres;
+ int x_buf, w1, s, fb_index;
+ u16 *src, *dst;
+
+ if (egpu.enhancement_buf_ptr == NULL)
+ return;
+
+ w += x & (step_x - 1);
+ x &= ~(step_x - 1);
+ w = (w + step_x - 1) & ~(step_x - 1);
+ if (y + h > 512)
+ h = 512 - y;
+
+ // find x_buf which is an offset into this enhancement_buf
+ fb_index = egpu.enhancement_buf_by_x16[x / step_x];
+ x_buf = x - egpu.enhancement_buf_start[fb_index];
+
+ while (w > 0) {
+ fb_index = egpu.enhancement_buf_by_x16[x / step_x];
+ for (w1 = 0; w > 0 && x_buf < hres; x_buf += step_x, w1++, w -= step_x)
+ if (fb_index != egpu.enhancement_buf_by_x16[x / step_x + w1])
+ break;
+ // skip further unneeded data, if any
+ for (s = 0; w > 0; s++, w -= step_x)
+ if (fb_index != egpu.enhancement_buf_by_x16[x / step_x + w1 + s])
+ break;
+
+ if (w1 > 0) {
+ src = gpu.vram + y * 1024 + x;
+ dst = select_enhancement_buf_ptr(&egpu, x);
+ dst += (y * 1024 + x) * 2;
+ scale2x_tiles8(dst, src, w1 * step_x / 8, h);
+ }
+
+ x += (w1 + s) * step_x;
+ x_buf = 0;
+ }
+}
+