+static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd)
+{
+ int cmd = 0, pos = 0, len, dummy, v;
+ int skip = 1;
+
+ gpu.frameskip.pending_fill[0] = 0;
+
+ while (pos < count && skip) {
+ uint32_t *list = data + pos;
+ cmd = list[0] >> 24;
+ len = 1 + cmd_lengths[cmd];
+
+ switch (cmd) {
+ case 0x02:
+ if ((list[2] & 0x3ff) > gpu.screen.w || ((list[2] >> 16) & 0x1ff) > gpu.screen.h)
+ // clearing something large, don't skip
+ do_cmd_list(list, 3, &dummy);
+ else
+ memcpy(gpu.frameskip.pending_fill, list, 3 * 4);
+ break;
+ case 0x24 ... 0x27:
+ case 0x2c ... 0x2f:
+ case 0x34 ... 0x37:
+ case 0x3c ... 0x3f:
+ gpu.ex_regs[1] &= ~0x1ff;
+ gpu.ex_regs[1] |= list[4 + ((cmd >> 4) & 1)] & 0x1ff;
+ break;
+ case 0x48 ... 0x4F:
+ for (v = 3; pos + v < count; v++)
+ {
+ if ((list[v] & 0xf000f000) == 0x50005000)
+ break;
+ }
+ len += v - 3;
+ break;
+ case 0x58 ... 0x5F:
+ for (v = 4; pos + v < count; v += 2)
+ {
+ if ((list[v] & 0xf000f000) == 0x50005000)
+ break;
+ }
+ len += v - 4;
+ break;
+ default:
+ if (cmd == 0xe3)
+ skip = decide_frameskip_allow(list[0]);
+ if ((cmd & 0xf8) == 0xe0)
+ gpu.ex_regs[cmd & 7] = list[0];
+ break;
+ }
+
+ if (pos + len > count) {
+ cmd = -1;
+ break; // incomplete cmd
+ }
+ if (0xa0 <= cmd && cmd <= 0xdf)
+ break; // image i/o
+
+ pos += len;
+ }
+
+ renderer_sync_ecmds(gpu.ex_regs);
+ *last_cmd = cmd;
+ return pos;
+}
+