Implement Voodoo CMDFIFO JSR/RET. Fixed "Bad CMDFIFO0" seen sometimes,

particularly when running OpenGL games windowed.
This commit is contained in:
SarahW 2020-11-21 09:44:46 +00:00
commit 87524de18b
3 changed files with 25 additions and 6 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);