+ // initial linked list ptr (word)
+ size = 1;
+
+ do {
+ addr &= 0x1ffffc;
+
+ if (DMACommandCounter++ > 2000000) break;
+ if (CheckForEndlessLoop(addr, lUsedAddr)) break;
+
+ // # 32-bit blocks to transfer
+ size += psxMu8( addr + 3 );
+
+ // next 32-bit pointer
+ addr = psxMu32( addr & ~0x3 ) & 0xffffff;
+ size += 1;
+ } while (!(addr & 0x800000)); // contrary to some documentation, the end-of-linked-list marker is not actually 0xFF'FFFF
+ // any pointer with bit 23 set will do.
+
+ return size;
+}
+
+void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
+ u32 *ptr, madr_next, *madr_next_p, size;
+ u32 words, words_left, words_max, words_copy;
+ int do_walking;
+
+ madr &= ~3;
+ switch (chcr) {