+#ifdef PCSX
+
+// this thing has become such a PITA, should just handle the 2048 width really
+static void update_enhancement_buf_scanouts(psx_gpu_struct *psx_gpu,
+ int x, int y, int w, int h)
+{
+ int max_bufs = ARRAY_SIZE(psx_gpu->enhancement_scanouts);
+ struct psx_gpu_scanout *s;
+ int i, sel, right, bottom;
+ u32 tol_x = 48, tol_y = 16;
+ u32 intersection;
+
+ //w = (w + 15) & ~15;
+ psx_gpu->saved_hres = w;
+ assert(!(max_bufs & (max_bufs - 1)));
+ for (i = 0; i < max_bufs; i++) {
+ s = &psx_gpu->enhancement_scanouts[i];
+ if (s->x == x && s->y == y && w - s->w <= tol_x && h - s->h <= tol_y)
+ return;
+ }
+
+ // evict any scanout that intersects
+ right = x + w;
+ bottom = y + h;
+ for (i = 0, sel = -1; i < max_bufs; i++) {
+ s = &psx_gpu->enhancement_scanouts[i];
+ if (s->x >= right) continue;
+ if (s->x + s->w <= x) continue;
+ if (s->y >= bottom) continue;
+ if (s->y + s->h <= y) continue;
+ // ... but allow upto 16 pixels intersection that some games do
+ if ((intersection = s->x + s->w - x) - 1u <= tol_x) {
+ s->w -= intersection;
+ continue;
+ }
+ if ((intersection = s->y + s->h - y) - 1u <= tol_y) {
+ s->h -= intersection;
+ continue;
+ }
+ //printf("%4d%4d%4dx%d evicted\n", s->x, s->y, s->w, s->h);
+ s->w = 0;
+ sel = i;
+ break;
+ }
+ if (sel >= 0) {
+ // 2nd intersection check
+ for (i = 0; i < max_bufs; i++) {
+ s = &psx_gpu->enhancement_scanouts[i];
+ if (!s->w)
+ continue;
+ if ((intersection = right - s->x) - 1u <= tol_x) {
+ w -= intersection;
+ break;
+ }
+ if ((intersection = bottom - s->y) - 1u <= tol_y) {
+ h -= intersection;
+ break;
+ }
+ }
+ }
+ else
+ sel = psx_gpu->enhancement_scanout_eselect++;
+ psx_gpu->enhancement_scanout_eselect &= max_bufs - 1;
+ s = &psx_gpu->enhancement_scanouts[sel];
+ s->x = x;
+ s->y = y;
+ s->w = w;
+ s->h = h;
+
+ sync_enhancement_buffers(x, y, w, h);
+#if 0
+ printf("scanouts:\n");
+ for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
+ s = &psx_gpu->enhancement_scanouts[i];
+ if (s->w)
+ printf("%4d%4d%4dx%d\n", s->x, s->y, s->w, s->h);
+ }
+#endif
+}
+
+static int select_enhancement_buf_index(psx_gpu_struct *psx_gpu, s32 x, s32 y)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
+ const struct psx_gpu_scanout *s = &psx_gpu->enhancement_scanouts[i];
+ if (s->x <= x && x < s->x + s->w &&
+ s->y <= y && y < s->y + s->h)
+ return i;
+ }
+ return -1;
+}
+
+#define select_enhancement_buf_by_index(psx_gpu_, i_) \
+ ((psx_gpu_)->enhancement_buf_ptr + ((i_) << 20))
+
+static void *select_enhancement_buf_ptr(psx_gpu_struct *psx_gpu, s32 x, s32 y)
+{
+ int i = select_enhancement_buf_index(psx_gpu, x, y);
+ return i >= 0 ? select_enhancement_buf_by_index(psx_gpu, i) : NULL;
+}
+
+static void select_enhancement_buf(psx_gpu_struct *psx_gpu)
+{
+ s32 x = psx_gpu->saved_viewport_start_x + 16;
+ s32 y = psx_gpu->saved_viewport_start_y + 16;
+ psx_gpu->enhancement_current_buf_ptr = select_enhancement_buf_ptr(psx_gpu, x, y);
+}
+