pvr: reschedule spg when SPG_HBLANK_INT is updated

Fixes Triggerheart Exelica input lag
Issue #691
This commit is contained in:
Flyinghead 2022-11-04 18:34:43 +01:00
parent 2332884d8b
commit 19204882c4
3 changed files with 43 additions and 31 deletions

View File

@ -205,6 +205,14 @@ void pvr_WriteReg(u32 paddr,u32 data)
data &= 0x01fffffc;
break;
case SPG_HBLANK_INT_addr:
data &= 0x03FF33FF;
if (data != SPG_HBLANK_INT.full) {
SPG_HBLANK_INT.full = data;
rescheduleSPG();
}
return;
case PAL_RAM_CTRL_addr:
pal_needs_update = pal_needs_update || ((data ^ PAL_RAM_CTRL) & 3) != 0;
break;

View File

@ -55,6 +55,39 @@ void CalculateSync()
sh4_sched_request(vblank_schid, Line_Cycles);
}
static int getNextSpgInterrupt()
{
u32 min_scanline = prv_cur_scanline + 1;
u32 min_active = pvr_numscanlines;
if (min_scanline < SPG_VBLANK_INT.vblank_in_interrupt_line_number)
min_active = std::min(min_active, SPG_VBLANK_INT.vblank_in_interrupt_line_number);
if (min_scanline < SPG_VBLANK_INT.vblank_out_interrupt_line_number)
min_active = std::min(min_active, SPG_VBLANK_INT.vblank_out_interrupt_line_number);
if (min_scanline < SPG_VBLANK.vstart)
min_active = std::min(min_active, SPG_VBLANK.vstart);
if (min_scanline < SPG_VBLANK.vbend)
min_active = std::min(min_active, SPG_VBLANK.vbend);
if (lightgun_line != 0xffff && min_scanline < lightgun_line)
min_active = std::min(min_active, lightgun_line);
if (SPG_HBLANK_INT.hblank_int_mode == 0 && min_scanline < SPG_HBLANK_INT.line_comp_val)
min_active = std::min(min_active, SPG_HBLANK_INT.line_comp_val);
min_active = std::max(min_active, min_scanline);
return (min_active - prv_cur_scanline) * Line_Cycles;
}
void rescheduleSPG()
{
sh4_sched_request(vblank_schid, getNextSpgInterrupt());
}
//called from sh4 context , should update pvr/ta state and everything else
static int spg_line_sched(int tag, int cycl, int jit)
{
@ -190,37 +223,7 @@ static int spg_line_sched(int tag, int cycl, int jit)
}
}
//interrupts
//0
//vblank_in_interrupt_line_number
//vblank_out_interrupt_line_number
//vstart
//vbend
//pvr_numscanlines
u32 min_scanline=prv_cur_scanline+1;
u32 min_active=pvr_numscanlines;
if (min_scanline<SPG_VBLANK_INT.vblank_in_interrupt_line_number)
min_active = std::min(min_active,SPG_VBLANK_INT.vblank_in_interrupt_line_number);
if (min_scanline<SPG_VBLANK_INT.vblank_out_interrupt_line_number)
min_active = std::min(min_active,SPG_VBLANK_INT.vblank_out_interrupt_line_number);
if (min_scanline<SPG_VBLANK.vstart)
min_active = std::min(min_active,SPG_VBLANK.vstart);
if (min_scanline<SPG_VBLANK.vbend)
min_active = std::min(min_active,SPG_VBLANK.vbend);
if (lightgun_line != 0xffff && min_scanline < lightgun_line)
min_active = std::min(min_active, lightgun_line);
if (SPG_HBLANK_INT.hblank_int_mode == 0 && min_scanline < SPG_HBLANK_INT.line_comp_val)
min_active = std::min(min_active, SPG_HBLANK_INT.line_comp_val);
min_active = std::max(min_active,min_scanline);
return (min_active - prv_cur_scanline) * Line_Cycles;
return getNextSpgInterrupt();
}
void read_lightgun_position(int x, int y)

View File

@ -12,3 +12,4 @@ void spg_Deserialize(Deserializer& deser);
void CalculateSync();
void read_lightgun_position(int x, int y);
void scheduleRenderDone(TA_context *cntx);
void rescheduleSPG();