+static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd)
+{
+ int cmd = 0, pos = 0, len, dummy;
+ int skip = 1;
+
+ gpu.frameskip.pending_fill[0] = 0;
+
+ // XXX: polylines are not properly handled
+ while (pos < count && skip) {
+ uint32_t *list = data + pos;
+ cmd = list[0] >> 24;
+ len = 1 + cmd_lengths[cmd];
+
+ if (cmd == 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);
+ }
+ else if ((cmd & 0xf4) == 0x24) {
+ // flat textured prim
+ gpu.ex_regs[1] &= ~0x1ff;
+ gpu.ex_regs[1] |= list[4] & 0x1ff;
+ }
+ else if ((cmd & 0xf4) == 0x34) {
+ // shaded textured prim
+ gpu.ex_regs[1] &= ~0x1ff;
+ gpu.ex_regs[1] |= list[5] & 0x1ff;
+ }
+ else if (cmd == 0xe3)
+ skip = decide_frameskip_allow(list[0]);
+
+ if ((cmd & 0xf8) == 0xe0)
+ gpu.ex_regs[cmd & 7] = list[0];
+
+ if (pos + len > count) {
+ cmd = -1;
+ break; // incomplete cmd
+ }
+ if (cmd == 0xa0 || cmd == 0xc0)
+ break; // image i/o
+ pos += len;
+ }
+
+ renderer_sync_ecmds(gpu.ex_regs);
+ *last_cmd = cmd;
+ return pos;
+}
+