diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 073d2ca3d..fe2f0b32c 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -314,7 +314,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/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 7a46dc860..d7f78bd05 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -1203,6 +1203,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*/ // banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); break; diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index 597c45051..9e1f9c61f 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -155,16 +155,19 @@ void voodoo_wait_for_swap_complete(voodoo_t *voodoo) static uint32_t cmdfifo_get(voodoo_t *voodoo) { uint32_t val; - - while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - } + + if (!voodoo->cmdfifo_in_sub) { + 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; // voodoo_fifo_log(" CMDFIFO get %08x\n", val); @@ -285,7 +288,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 = plat_timer_read(); uint64_t end_time; @@ -308,6 +311,18 @@ void voodoo_fifo_thread(void *param) case 0: /*NOP*/ break; + case 1: /*JSR*/ +// voodoo_fifo_log("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; // voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);