diff --git a/src/vid_voodoo_banshee.c b/src/vid_voodoo_banshee.c index 15ac43e..769d9de 100644 --- a/src/vid_voodoo_banshee.c +++ b/src/vid_voodoo_banshee.c @@ -1163,6 +1163,8 @@ static void banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_size = val; voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); voodoo->cmdfifo_enabled = val & 0x100; + if (!voodoo->cmdfifo_enabled) + voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/ // pclog("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); break; diff --git a/src/vid_voodoo_common.h b/src/vid_voodoo_common.h index cf62410..d8ca533 100644 --- a/src/vid_voodoo_common.h +++ b/src/vid_voodoo_common.h @@ -301,7 +301,8 @@ typedef struct voodoo_t volatile int params_read_idx[4], params_write_idx; uint32_t cmdfifo_base, cmdfifo_end, cmdfifo_size; - int cmdfifo_rp; + int cmdfifo_rp, cmdfifo_ret_addr; + int cmdfifo_in_sub; volatile int cmdfifo_depth_rd, cmdfifo_depth_wr; volatile int cmdfifo_enabled; uint32_t cmdfifo_amin, cmdfifo_amax; diff --git a/src/vid_voodoo_fifo.c b/src/vid_voodoo_fifo.c index 472df3f..59861f3 100644 --- a/src/vid_voodoo_fifo.c +++ b/src/vid_voodoo_fifo.c @@ -113,15 +113,19 @@ static uint32_t cmdfifo_get(voodoo_t *voodoo) { uint32_t val; - while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) + if (!voodoo->cmdfifo_in_sub) { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); + while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) + { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + } } val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; - voodoo->cmdfifo_depth_rd++; + if (!voodoo->cmdfifo_in_sub) + voodoo->cmdfifo_depth_rd++; voodoo->cmdfifo_rp += 4; // pclog(" CMDFIFO get %08x\n", val); @@ -242,7 +246,7 @@ void voodoo_fifo_thread(void *param) voodoo->time += end_time - start_time; } - while (voodoo->cmdfifo_enabled && voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) + while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) { uint64_t start_time = timer_read(); uint64_t end_time; @@ -265,6 +269,18 @@ void voodoo_fifo_thread(void *param) case 0: /*NOP*/ break; + case 1: /*JSR*/ +// pclog("JSR %08x\n", (header >> 4) & 0xfffffc); + voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp; + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_sub = 1; + break; + + case 2: /*RET*/ + voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr; + voodoo->cmdfifo_in_sub = 0; + break; + case 3: /*JMP local frame buffer*/ voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; // pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);