- gpu.screen.src_x = data & 0x3ff;
- gpu.screen.src_y = (data >> 10) & 0x1ff;
- if (gpu.frameskip.set) {
- decide_frameskip_allow(gpu.ex_regs[3]);
- if (gpu.frameskip.last_flip_frame != *gpu.state.frame_count) {
- decide_frameskip();
- gpu.frameskip.last_flip_frame = *gpu.state.frame_count;
+ src_x = data & 0x3ff; src_y = (data >> 10) & 0x1ff;
+ if (src_x != gpu.screen.src_x || src_y != gpu.screen.src_y) {
+ gpu.screen.src_x = src_x;
+ gpu.screen.src_y = src_y;
+ renderer_notify_scanout_change(src_x, src_y);
+ if (gpu.frameskip.set) {
+ decide_frameskip_allow(gpu.ex_regs[3]);
+ if (gpu.frameskip.last_flip_frame != *gpu.state.frame_count) {
+ decide_frameskip();
+ gpu.frameskip.last_flip_frame = *gpu.state.frame_count;
+ }
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, // 60
1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, // 60
1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 80
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // a0
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define VRAM_MEM_XY(x, y) &gpu.vram[(y) * 1024 + (x)]
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define VRAM_MEM_XY(x, y) &gpu.vram[(y) * 1024 + (x)]
- gpu.dma_start.w, gpu.dma_start.h);
+ gpu.dma_start.w, gpu.dma_start.h, 0);
+ }
+ if (gpu.gpu_state_change)
+ gpu.gpu_state_change(PGS_VRAM_TRANSFER_END);
+}
+
+static void do_vram_copy(const uint32_t *params, int *cpu_cycles)
+{
+ const uint32_t sx = LE32TOH(params[0]) & 0x3FF;
+ const uint32_t sy = (LE32TOH(params[0]) >> 16) & 0x1FF;
+ const uint32_t dx = LE32TOH(params[1]) & 0x3FF;
+ const uint32_t dy = (LE32TOH(params[1]) >> 16) & 0x1FF;
+ uint32_t w = ((LE32TOH(params[2]) - 1) & 0x3FF) + 1;
+ uint32_t h = (((LE32TOH(params[2]) >> 16) - 1) & 0x1FF) + 1;
+ uint16_t msb = gpu.ex_regs[6] << 15;
+ uint16_t lbuf[128];
+ uint32_t x, y;
+
+ *cpu_cycles += gput_copy(w, h);
+ if (sx == dx && sy == dy && msb == 0)
+ return;
+
+ renderer_flush_queues();
+
+ if (unlikely((sx < dx && dx < sx + w) || sx + w > 1024 || dx + w > 1024 || msb))
+ {
+ for (y = 0; y < h; y++)
+ {
+ const uint16_t *src = VRAM_MEM_XY(0, (sy + y) & 0x1ff);
+ uint16_t *dst = VRAM_MEM_XY(0, (dy + y) & 0x1ff);
+ for (x = 0; x < w; x += ARRAY_SIZE(lbuf))
+ {
+ uint32_t x1, w1 = w - x;
+ if (w1 > ARRAY_SIZE(lbuf))
+ w1 = ARRAY_SIZE(lbuf);
+ for (x1 = 0; x1 < w1; x1++)
+ lbuf[x1] = src[(sx + x + x1) & 0x3ff];
+ for (x1 = 0; x1 < w1; x1++)
+ dst[(dx + x + x1) & 0x3ff] = lbuf[x1] | msb;
+ }
+ }
+ }
+ else
+ {
+ uint32_t sy1 = sy, dy1 = dy;
+ for (y = 0; y < h; y++, sy1++, dy1++)
+ memcpy(VRAM_MEM_XY(dx, dy1 & 0x1ff), VRAM_MEM_XY(sx, sy1 & 0x1ff), w * 2);
+ }
+
+ renderer_update_caches(dx, dy, w, h, 0);