Compare commits

...

5 Commits

Author SHA1 Message Date
lightningterror
fbb3e4e2a9 GS/DX11: Align drawlist bounding box to 4 pixel boundaries.
Will be faster using Direct Memory Access, otherwise it may stall as more commands need to be issued.
2026-01-30 17:02:32 +01:00
TJnotJT
e82fa0bba5 GS/HW: Require 32 bit RT for accumulation blend on max blend. 2026-01-30 11:06:13 +01:00
Ziemas
45490d903a SPU: Slow down DMA 2026-01-29 22:26:28 -05:00
PCSX2 Bot
76dadf792a [ci skip] Qt: Update Base Translation. 2026-01-30 02:03:26 +01:00
wxvu
204829865d GameDB: Add fixes for Puchi Copter 2 2026-01-29 14:21:14 +01:00
5 changed files with 1109 additions and 1067 deletions

View File

@@ -24781,6 +24781,11 @@ SLES-53820:
SLES-53821:
name: "Radio Helicopter II"
region: "PAL-E"
patches:
9A695202:
content: |-
comment=Patch that nops a branch instruction causing a freeze.
patch=1,EE,001799AC,word,00000000
SLES-53824:
name: "Trapt"
region: "PAL-E"
@@ -40089,6 +40094,11 @@ SLPM-62624:
name-sort: "ぷちこぷたー2"
name-en: "Petit Copter 2"
region: "NTSC-J"
patches:
9A695202:
content: |-
comment=Patch that nops a branch instruction causing a freeze.
patch=1,EE,001799B8,word,00000000
SLPM-62625:
name: "鬼浜爆走愚連隊 激闘編"
name-sort: "おにはまばくそうぐれんたい げきとうへん"

File diff suppressed because it is too large Load Diff

View File

@@ -2847,6 +2847,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config, GSTexture* draw_rt_clo
{
const u32 draw_list_size = static_cast<u32>(config.drawlist->size());
const u32 indices_per_prim = config.indices_per_prim;
const GSVector4i rtsize(0, 0, draw_rt->GetWidth(), draw_rt->GetHeight());
pxAssert(config.drawlist && !config.drawlist->empty());
pxAssert(config.drawlist_bbox && static_cast<u32>(config.drawlist_bbox->size()) == draw_list_size);
@@ -2855,10 +2856,28 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config, GSTexture* draw_rt_clo
{
const u32 count = (*config.drawlist)[n] * indices_per_prim;
GSVector4i bbox = (*config.drawlist_bbox)[n].rintersect(config.drawarea);
const GSVector4i original_bbox = (*config.drawlist_bbox)[n].rintersect(config.drawarea);
GSVector4i snapped_bbox = original_bbox;
// Copy only the part needed by the draw.
CopyAndBind(bbox);
// We don't want the snapped box adjustments when the rect is empty as it might make the copy to pass.
// The empty rect itself needs to be handled in renderer properly.
if (!snapped_bbox.rempty())
{
// Aligning bbox to 4 pixel boundaries so copies will be faster using Direct Memory Access,
// otherwise it may stall as more commands need to be issued.
snapped_bbox.left &= ~3;
snapped_bbox.top &= ~3;
snapped_bbox.right = (snapped_bbox.right + 3) & ~3;
snapped_bbox.bottom = (snapped_bbox.bottom + 3) & ~3;
// Ensure the new sizes are within bounds.
snapped_bbox.left = std::max(0, snapped_bbox.left);
snapped_bbox.top = std::max(0, snapped_bbox.top);
snapped_bbox.right = std::min(snapped_bbox.right, rtsize.right);
snapped_bbox.bottom = std::min(snapped_bbox.bottom, rtsize.bottom);
}
CopyAndBind(snapped_bbox);
DrawIndexedPrimitive(p, count);
p += count;

View File

@@ -5910,6 +5910,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
{
case AccBlendLevel::Maximum:
sw_blending |= true;
accumulation_blend &= (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 32);
[[fallthrough]];
case AccBlendLevel::Full:
sw_blending |= m_conf.ps.blend_a != m_conf.ps.blend_b && alpha_c0_high_max_one;

View File

@@ -163,7 +163,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
if ((AutoDMACtrl & (Index + 1)) == 0)
{
ActiveTSA = 0x2000 + (Index << 10);
DMAICounter = size * 4;
DMAICounter = size * 48;
LastClock = psxRegs.cycle;
}
else if (size >= 256)
@@ -191,7 +191,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
if (SPU2::MsgToConsole())
SPU2::ConLog("ADMA%c Error Size of %x too small\n", GetDmaIndexChar(), size);
InputDataLeft = 0;
DMAICounter = size * 4;
DMAICounter = size * 48;
LastClock = psxRegs.cycle;
}
}
@@ -248,7 +248,7 @@ void V_Core::FinishDMAwrite()
DMA7LogWrite(DMAPtr, ReadSize << 1);
#endif
u32 buff1end = ActiveTSA + std::min(ReadSize, (u32)0x100 + std::abs(DMAICounter / 4));
u32 buff1end = ActiveTSA + std::min(ReadSize, (u32)0x100 + std::abs(DMAICounter / 48));
u32 buff2end = 0;
if (buff1end > 0x100000)
{
@@ -343,7 +343,7 @@ void V_Core::FinishDMAwrite()
DMAPtr += TDA - ActiveTSA;
ReadSize -= TDA - ActiveTSA;
DMAICounter = (DMAICounter - ReadSize) * 4;
DMAICounter = (DMAICounter - ReadSize) * 48;
CounterUpdate(DMAICounter);
@@ -354,7 +354,7 @@ void V_Core::FinishDMAwrite()
void V_Core::FinishDMAread()
{
u32 buff1end = ActiveTSA + std::min(ReadSize, (u32)0x100 + std::abs(DMAICounter / 4));
u32 buff1end = ActiveTSA + std::min(ReadSize, (u32)0x100 + std::abs(DMAICounter / 48));
u32 buff2end = 0;
if (buff1end > 0x100000)
@@ -426,9 +426,9 @@ void V_Core::FinishDMAread()
// DMA Reads are done AFTER the delay, so to get the timing right we need to scheule one last DMA to catch IRQ's
if (ReadSize)
DMAICounter = std::min(ReadSize, (u32)0x100) * 4;
DMAICounter = std::min(ReadSize, (u32)0x100) * 48;
else
DMAICounter = 4;
DMAICounter = 48;
CounterUpdate(DMAICounter);
@@ -446,7 +446,7 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
ReadSize = size;
IsDMARead = true;
LastClock = psxRegs.cycle;
DMAICounter = std::min(ReadSize, (u32)0x100) * 4;
DMAICounter = (std::min(ReadSize, (u32)0x100) * 48);
Regs.STATX &= ~0x80;
Regs.STATX |= 0x400;
//Regs.ATTR |= 0x30;
@@ -470,7 +470,7 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
{
Regs.STATX &= ~0x80;
//Regs.ATTR |= 0x30;
DMAICounter = 1 * 4;
DMAICounter = 1 * 48;
LastClock = psxRegs.cycle;
return;
}