mirror of https://github.com/PCSX2/pcsx2.git
MAJOR: All new hwRead and hwWrite handlers (expect regressions). Details:
* Writes via 16 and 8 bit ops now use 32-bit read/modify/write operations by default; which should enable nearly complete support for all such operations (instead of the formerly spotty coverage before). * Eliminated almost all former 8/16-bit specific register operations. All code shares the same 32 bit handlers now. * Completely revamped the developer trace logs for hardware registers! *ALL* registers are logged now, complete with address, name, and value being read/written (and nicely formatted!). * Handlers are now fully page-based using templated functions (minor speedup) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3704 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
1cac8d3948
commit
003da7d287
|
@ -165,7 +165,6 @@ set(pcsx2Sources
|
|||
Vif_Codes.cpp
|
||||
Vif_Transfer.cpp
|
||||
Vif_Unpack.cpp
|
||||
Vif_Unpack.inl
|
||||
vtlb.cpp
|
||||
VU0.cpp
|
||||
VUmicro.cpp
|
||||
|
@ -226,6 +225,7 @@ set(pcsx2Headers
|
|||
Vif_Dma.h
|
||||
Vif.h
|
||||
Vif_Unpack.h
|
||||
Vif_Unpack.inl
|
||||
vtlb.h
|
||||
VUflags.h
|
||||
VUmicro.h
|
||||
|
@ -295,7 +295,6 @@ set(pcsx2GuiSources
|
|||
gui/Panels/BaseApplicableConfigPanel.cpp
|
||||
gui/Panels/MemoryCardListView.cpp
|
||||
gui/Dialogs/BaseConfigurationDialog.cpp
|
||||
gui/Dialogs/BaseConfigurationDialog.inl
|
||||
gui/Dialogs/BiosSelectorDialog.cpp
|
||||
gui/Dialogs/ConfirmationDialogs.cpp
|
||||
gui/Dialogs/CreateMemoryCardDialog.cpp
|
||||
|
@ -353,6 +352,7 @@ set(pcsx2GuiHeaders
|
|||
gui/AppGameDatabase.h
|
||||
gui/ConsoleLogger.h
|
||||
gui/CpuUsageProvider.h
|
||||
gui/Dialogs/BaseConfigurationDialog.inl
|
||||
gui/Dialogs/ConfigurationDialog.h
|
||||
gui/Dialogs/LogOptionsDialog.h
|
||||
gui/Dialogs/ModalPopups.h
|
||||
|
@ -394,12 +394,15 @@ set(pcsx2LinuxHeaders
|
|||
set(pcsx2ps2Sources
|
||||
ps2/BiosTools.cpp
|
||||
ps2/GIFpath.cpp
|
||||
ps2/LegacyDmac.cpp
|
||||
ps2/Iop/IopHwRead.cpp
|
||||
ps2/Iop/IopHwWrite.cpp)
|
||||
|
||||
# ps2 headers
|
||||
set(pcsx2ps2Headers
|
||||
ps2/BiosTools.h
|
||||
ps2/eeHwTraceLog.inl
|
||||
ps2/HwInternal.inl
|
||||
ps2/Iop/IopHw_Internal.h)
|
||||
|
||||
# RDebug sources
|
||||
|
@ -495,20 +498,6 @@ set(pcsx2x86Sources
|
|||
x86/ix86-32/iR5900Shift.cpp
|
||||
x86/ix86-32/iR5900Templates.cpp
|
||||
x86/ix86-32/recVTLB.cpp
|
||||
x86/microVU_Alloc.inl
|
||||
x86/microVU_Analyze.inl
|
||||
x86/microVU_Branch.inl
|
||||
x86/microVU_Clamp.inl
|
||||
x86/microVU_Compile.inl
|
||||
x86/microVU.cpp
|
||||
x86/microVU_Execute.inl
|
||||
x86/microVU_Flags.inl
|
||||
x86/microVU_Log.inl
|
||||
x86/microVU_Lower.inl
|
||||
x86/microVU_Macro.inl
|
||||
x86/microVU_Misc.inl
|
||||
x86/microVU_Tables.inl
|
||||
x86/microVU_Upper.inl
|
||||
x86/newVif_Dynarec.cpp
|
||||
x86/newVif_Unpack.cpp
|
||||
x86/newVif_UnpackSSE.cpp
|
||||
|
@ -538,6 +527,20 @@ set(pcsx2x86Headers
|
|||
x86/microVU.h
|
||||
x86/microVU_IR.h
|
||||
x86/microVU_Misc.h
|
||||
x86/microVU_Alloc.inl
|
||||
x86/microVU_Analyze.inl
|
||||
x86/microVU_Branch.inl
|
||||
x86/microVU_Clamp.inl
|
||||
x86/microVU_Compile.inl
|
||||
x86/microVU.cpp
|
||||
x86/microVU_Execute.inl
|
||||
x86/microVU_Flags.inl
|
||||
x86/microVU_Log.inl
|
||||
x86/microVU_Lower.inl
|
||||
x86/microVU_Macro.inl
|
||||
x86/microVU_Misc.inl
|
||||
x86/microVU_Tables.inl
|
||||
x86/microVU_Upper.inl
|
||||
x86/newVif.h
|
||||
x86/newVif_BlockBuffer.h
|
||||
x86/newVif_HashBucket.h
|
||||
|
|
|
@ -428,7 +428,7 @@ void MTC0()
|
|||
}
|
||||
|
||||
int CPCOND0() {
|
||||
return ((dmacRegs->stat.CIS | ~dmacRegs->pcr.CPC) == 0x3ff);
|
||||
return ((dmacRegs.stat.CIS | ~dmacRegs.pcr.CPC) == 0x3ff);
|
||||
}
|
||||
|
||||
//#define CPCOND0 1
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "Common.h"
|
||||
#include "R3000A.h"
|
||||
#include "Counters.h"
|
||||
#include "IopCounters.h"
|
||||
|
@ -27,6 +27,8 @@
|
|||
#include "GS.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
|
||||
using namespace Threading;
|
||||
|
||||
extern u8 psxhblankgate;
|
||||
|
@ -45,6 +47,15 @@ SyncCounter vsyncCounter;
|
|||
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
|
||||
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
|
||||
|
||||
// Forward declarations needed because C/C++ both are wimpy single-pass compilers.
|
||||
|
||||
static void rcntStartGate(bool mode, u32 sCycle);
|
||||
static void rcntEndGate(bool mode, u32 sCycle);
|
||||
static void rcntWcount(int index, u32 value);
|
||||
static void rcntWmode(int index, u32 value);
|
||||
static void rcntWtarget(int index, u32 value);
|
||||
static void rcntWhold(int index, u32 value);
|
||||
|
||||
|
||||
void rcntReset(int index) {
|
||||
counters[index].count = 0;
|
||||
|
@ -575,7 +586,7 @@ static __fi void _rcntSetGate( int index )
|
|||
}
|
||||
|
||||
// mode - 0 means hblank source, 8 means vblank source.
|
||||
__fi void rcntStartGate(bool isVblank, u32 sCycle)
|
||||
static __fi void rcntStartGate(bool isVblank, u32 sCycle)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -636,7 +647,7 @@ __fi void rcntStartGate(bool isVblank, u32 sCycle)
|
|||
}
|
||||
|
||||
// mode - 0 means hblank signal, 8 means vblank signal.
|
||||
__fi void rcntEndGate(bool isVblank , u32 sCycle)
|
||||
static __fi void rcntEndGate(bool isVblank , u32 sCycle)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -677,7 +688,15 @@ __fi void rcntEndGate(bool isVblank , u32 sCycle)
|
|||
// rcntUpdate, since we're being called from there anyway.
|
||||
}
|
||||
|
||||
__fi void rcntWmode(int index, u32 value)
|
||||
static __fi u32 rcntCycle(int index)
|
||||
{
|
||||
if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
|
||||
return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
|
||||
else
|
||||
return counters[index].count;
|
||||
}
|
||||
|
||||
static __fi void rcntWmode(int index, u32 value)
|
||||
{
|
||||
if(counters[index].mode.IsCounting) {
|
||||
if(counters[index].mode.ClockSource != 0x3) {
|
||||
|
@ -711,7 +730,7 @@ __fi void rcntWmode(int index, u32 value)
|
|||
_rcntSet( index );
|
||||
}
|
||||
|
||||
__fi void rcntWcount(int index, u32 value)
|
||||
static __fi void rcntWcount(int index, u32 value)
|
||||
{
|
||||
EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target );
|
||||
|
||||
|
@ -737,7 +756,7 @@ __fi void rcntWcount(int index, u32 value)
|
|||
_rcntSet( index );
|
||||
}
|
||||
|
||||
__fi void rcntWtarget(int index, u32 value)
|
||||
static __fi void rcntWtarget(int index, u32 value)
|
||||
{
|
||||
EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);
|
||||
|
||||
|
@ -766,7 +785,7 @@ __fi void rcntWtarget(int index, u32 value)
|
|||
_rcntSet( index );
|
||||
}
|
||||
|
||||
__fi void rcntWhold(int index, u32 value)
|
||||
static __fi void rcntWhold(int index, u32 value)
|
||||
{
|
||||
EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);
|
||||
counters[index].hold = value;
|
||||
|
@ -787,14 +806,76 @@ __fi u32 rcntRcount(int index)
|
|||
return ret;
|
||||
}
|
||||
|
||||
__fi u32 rcntCycle(int index)
|
||||
template< uint page >
|
||||
__fi u16 rcntRead32( u32 mem )
|
||||
{
|
||||
if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
|
||||
return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
|
||||
else
|
||||
return counters[index].count;
|
||||
// Important DevNote:
|
||||
// Yes this uses a u16 return value on purpose! The upper bits 16 of the counter registers
|
||||
// are all fixed to 0, so we always truncate everything in these two pages using a u16
|
||||
// return value! --air
|
||||
|
||||
iswitch( mem ) {
|
||||
icase(RCNT0_COUNT) return (u16)rcntRcount(0);
|
||||
icase(RCNT0_MODE) return (u16)counters[0].modeval;
|
||||
icase(RCNT0_TARGET) return (u16)counters[0].target;
|
||||
icase(RCNT0_HOLD) return (u16)counters[0].hold;
|
||||
|
||||
icase(RCNT1_COUNT) return (u16)rcntRcount(1);
|
||||
icase(RCNT1_MODE) return (u16)counters[1].modeval;
|
||||
icase(RCNT1_TARGET) return (u16)counters[1].target;
|
||||
icase(RCNT1_HOLD) return (u16)counters[1].hold;
|
||||
|
||||
icase(RCNT2_COUNT) return (u16)rcntRcount(2);
|
||||
icase(RCNT2_MODE) return (u16)counters[2].modeval;
|
||||
icase(RCNT2_TARGET) return (u16)counters[2].target;
|
||||
|
||||
icase(RCNT3_COUNT) return (u16)rcntRcount(3);
|
||||
icase(RCNT3_MODE) return (u16)counters[3].modeval;
|
||||
icase(RCNT3_TARGET) return (u16)counters[3].target;
|
||||
}
|
||||
|
||||
return psHu16(mem);
|
||||
}
|
||||
|
||||
template< uint page >
|
||||
__fi bool rcntWrite32( u32 mem, mem32_t& value )
|
||||
{
|
||||
pxAssume( mem >= RCNT0_COUNT && mem < 0x10002000 );
|
||||
|
||||
// [TODO] : counters should actually just use the EE's hw register space for storing
|
||||
// count, mode, target, and hold. This will allow for a simplified handler for register
|
||||
// reads.
|
||||
|
||||
iswitch( mem ) {
|
||||
icase(RCNT0_COUNT) return rcntWcount(0, value), false;
|
||||
icase(RCNT0_MODE) return rcntWmode(0, value), false;
|
||||
icase(RCNT0_TARGET) return rcntWtarget(0, value), false;
|
||||
icase(RCNT0_HOLD) return rcntWhold(0, value), false;
|
||||
|
||||
icase(RCNT1_COUNT) return rcntWcount(1, value), false;
|
||||
icase(RCNT1_MODE) return rcntWmode(1, value), false;
|
||||
icase(RCNT1_TARGET) return rcntWtarget(1, value), false;
|
||||
icase(RCNT1_HOLD) return rcntWhold(1, value), false;
|
||||
|
||||
icase(RCNT2_COUNT) return rcntWcount(2, value), false;
|
||||
icase(RCNT2_MODE) return rcntWmode(2, value), false;
|
||||
icase(RCNT2_TARGET) return rcntWtarget(2, value), false;
|
||||
|
||||
icase(RCNT3_COUNT) return rcntWcount(3, value), false;
|
||||
icase(RCNT3_MODE) return rcntWmode(3, value), false;
|
||||
icase(RCNT3_TARGET) return rcntWtarget(3, value), false;
|
||||
}
|
||||
|
||||
// unhandled .. do memory writeback.
|
||||
return true;
|
||||
}
|
||||
|
||||
template u16 rcntRead32<0x00>( u32 mem );
|
||||
template u16 rcntRead32<0x01>( u32 mem );
|
||||
|
||||
template bool rcntWrite32<0x00>( u32 mem, mem32_t& value );
|
||||
template bool rcntWrite32<0x01>( u32 mem, mem32_t& value );
|
||||
|
||||
void SaveStateBase::rcntFreeze()
|
||||
{
|
||||
Freeze( counters );
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __COUNTERS_H__
|
||||
#define __COUNTERS_H__
|
||||
#pragma once
|
||||
|
||||
struct EECNT_MODE
|
||||
{
|
||||
|
@ -137,16 +136,10 @@ extern void rcntUpdate_vSync();
|
|||
extern void rcntUpdate();
|
||||
|
||||
extern void rcntInit();
|
||||
extern void rcntStartGate(bool mode, u32 sCycle);
|
||||
extern void rcntEndGate(bool mode, u32 sCycle);
|
||||
extern void rcntWcount(int index, u32 value);
|
||||
extern void rcntWmode(int index, u32 value);
|
||||
extern void rcntWtarget(int index, u32 value);
|
||||
extern void rcntWhold(int index, u32 value);
|
||||
extern u32 rcntRcount(int index);
|
||||
extern u32 rcntCycle(int index);
|
||||
template< uint page > extern bool rcntWrite32( u32 mem, mem32_t& value );
|
||||
template< uint page > extern u16 rcntRead32( u32 mem ); // returns u16 by design! (see implementation for details)
|
||||
|
||||
extern u32 UpdateVSyncRate();
|
||||
extern void frameLimitReset();
|
||||
|
||||
#endif /* __COUNTERS_H__ */
|
||||
|
|
20
pcsx2/Dmac.h
20
pcsx2/Dmac.h
|
@ -588,18 +588,26 @@ struct INTCregisters
|
|||
u32 _padding2[3];
|
||||
};
|
||||
|
||||
#define dmacRegs ((DMACregisters*)(eeHw+0xE000))
|
||||
#define intcRegs ((INTCregisters*)(eeHw+0xF000))
|
||||
|
||||
static DMACregisters& dmacRegs = (DMACregisters&)eeHw[0xE000];
|
||||
|
||||
// Various useful locations
|
||||
static DMACh& vif0ch = (DMACh&)eeHw[0x8000];
|
||||
static DMACh& vif1ch = (DMACh&)eeHw[0x9000];
|
||||
static DMACh& gifch = (DMACh&)eeHw[0xA000];
|
||||
static DMACh& spr0ch = (DMACh&)eeHw[0xD000];
|
||||
static DMACh& spr1ch = (DMACh&)eeHw[0xD400];
|
||||
|
||||
static __fi void throwBusError(const char *s)
|
||||
{
|
||||
Console.Error("%s BUSERR", s);
|
||||
dmacRegs->stat.BEIS = true;
|
||||
dmacRegs.stat.BEIS = true;
|
||||
}
|
||||
|
||||
static __fi void setDmacStat(u32 num)
|
||||
{
|
||||
dmacRegs->stat.set_flags(1 << num);
|
||||
dmacRegs.stat.set_flags(1 << num);
|
||||
}
|
||||
|
||||
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
|
||||
|
@ -670,6 +678,8 @@ extern void hwIntcIrq(int n);
|
|||
extern void hwDmacIrq(int n);
|
||||
|
||||
extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc);
|
||||
extern bool hwDmacSrcChainWithStack(DMACh *dma, int id);
|
||||
extern bool hwDmacSrcChain(DMACh *dma, int id);
|
||||
extern bool hwDmacSrcChainWithStack(DMACh& dma, int id);
|
||||
extern bool hwDmacSrcChain(DMACh& dma, int id);
|
||||
|
||||
template< uint page >
|
||||
extern bool dmacWrite32( u32 mem, mem32_t& value );
|
||||
|
|
|
@ -132,7 +132,7 @@ void iDumpRegisters(u32 startpc, u32 temp)
|
|||
DMACh* p = (DMACh*)(&eeHw[dmacs[i]]);
|
||||
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr);
|
||||
}
|
||||
__Log(L"dmac " + dmacRegs->ctrl.desc() + L" " + dmacRegs->stat.desc() + L" " + dmacRegs->rbsr.desc() + L" " + dmacRegs->rbor.desc());
|
||||
__Log(L"dmac " + dmacRegs.ctrl.desc() + L" " + dmacRegs.stat.desc() + L" " + dmacRegs.rbsr.desc() + L" " + dmacRegs.rbor.desc());
|
||||
__Log(L"intc " + intcRegs->stat.desc() + L" " + intcRegs->mask.desc());
|
||||
__Log("sif: %x %x %x %x %x", psHu32(SBUS_F200), psHu32(SBUS_F220), psHu32(SBUS_F230), psHu32(SBUS_F240), psHu32(SBUS_F260));
|
||||
#endif
|
||||
|
|
131
pcsx2/FiFo.cpp
131
pcsx2/FiFo.cpp
|
@ -28,8 +28,6 @@
|
|||
/////////////////////////// Quick & dirty FIFO :D ////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ** NOTE: cannot use XMM/MMX regs **
|
||||
|
||||
// Notes on FIFO implementation
|
||||
//
|
||||
// The FIFO consists of four separate pages of HW register memory, each mapped to a
|
||||
|
@ -40,167 +38,108 @@
|
|||
// 0x6000 - 0x7000 : GS (all registers map to 0x6000)
|
||||
// 0x7000 - 0x8000 : IPU (registers map to 0x7000 and 0x7010, respectively)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadFIFO Pages
|
||||
|
||||
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t* out)
|
||||
void __fastcall ReadFIFO_VIF1(mem128_t* out)
|
||||
{
|
||||
pxAssert( (mem >= VIF0_FIFO) && (mem < VIF1_FIFO) );
|
||||
|
||||
VIF_LOG("ReadFIFO/VIF0 0x%08X", mem);
|
||||
|
||||
CopyQWC( out, &psHu128(VIF0_FIFO) );
|
||||
}
|
||||
|
||||
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t* out)
|
||||
{
|
||||
pxAssert( (mem >= VIF1_FIFO) && (mem < GIF_FIFO) );
|
||||
|
||||
VIF_LOG("ReadFIFO/VIF1, addr=0x%08X", mem);
|
||||
|
||||
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
||||
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
||||
DevCon.Warning( "Reading from vif1 fifo when stalled" );
|
||||
|
||||
if(vif1Regs->stat.FQC == 0) Console.Warning("FQC = 0 on VIF FIFO READ!");
|
||||
if (vif1Regs->stat.FDR)
|
||||
pxAssertRel(vif1Regs.stat.FQC != 0, "FQC = 0 on VIF FIFO READ!");
|
||||
if (vif1Regs.stat.FDR)
|
||||
{
|
||||
if(vif1Regs->stat.FQC > vif1.GSLastDownloadSize)
|
||||
if(vif1Regs.stat.FQC > vif1.GSLastDownloadSize)
|
||||
{
|
||||
DevCon.Warning("Warning! GS Download size < FIFO count!");
|
||||
}
|
||||
if (vif1Regs->stat.FQC > 0)
|
||||
if (vif1Regs.stat.FQC > 0)
|
||||
{
|
||||
GetMTGS().WaitGS();
|
||||
GSreadFIFO(&psHu64(VIF1_FIFO));
|
||||
vif1.GSLastDownloadSize--;
|
||||
if (vif1.GSLastDownloadSize <= 16)
|
||||
gifRegs->stat.OPH = false;
|
||||
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
gifRegs.stat.OPH = false;
|
||||
vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
CopyQWC( out, &psHu128(VIF1_FIFO) );
|
||||
VIF_LOG("ReadFIFO/VIF1 -> %ls", out->ToString().c_str());
|
||||
}
|
||||
|
||||
void __fastcall ReadFIFO_page_6(u32 mem, mem128_t* out)
|
||||
{
|
||||
pxAssert( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) );
|
||||
|
||||
DevCon.Warning( "ReadFIFO/GIF, addr=0x%x", mem );
|
||||
|
||||
CopyQWC( out, &psHu128(GIF_FIFO) );
|
||||
}
|
||||
|
||||
// ReadFIFO_page_7 is contained in IPU_Fifo.cpp
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteFIFO Pages
|
||||
|
||||
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value)
|
||||
//
|
||||
void __fastcall WriteFIFO_VIF0(const mem128_t *value)
|
||||
{
|
||||
pxAssert( (mem >= VIF0_FIFO) && (mem < VIF1_FIFO) );
|
||||
|
||||
VIF_LOG("WriteFIFO/VIF0, addr=0x%08X", mem);
|
||||
VIF_LOG("WriteFIFO/VIF0 <- %ls", value->ToString().c_str());
|
||||
|
||||
CopyQWC(&psHu128(VIF0_FIFO), value);
|
||||
|
||||
vif0ch->qwc += 1;
|
||||
vif0ch.qwc += 1;
|
||||
if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!");
|
||||
bool ret = VIF0transfer((u32*)value, 4);
|
||||
|
||||
if (vif0.cmd)
|
||||
{
|
||||
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING;
|
||||
if(vif0.done && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
pxAssertDev( ret, "vif stall code not implemented" );
|
||||
}
|
||||
|
||||
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value)
|
||||
void __fastcall WriteFIFO_VIF1(const mem128_t *value)
|
||||
{
|
||||
pxAssert( (mem >= VIF1_FIFO) && (mem < GIF_FIFO) );
|
||||
|
||||
VIF_LOG("WriteFIFO/VIF1, addr=0x%08X", mem);
|
||||
VIF_LOG("WriteFIFO/VIF1 <- %ls", value->ToString().c_str());
|
||||
|
||||
CopyQWC(&psHu128(VIF1_FIFO), value);
|
||||
|
||||
if (vif1Regs->stat.FDR)
|
||||
if (vif1Regs.stat.FDR)
|
||||
DevCon.Warning("writing to fifo when fdr is set!");
|
||||
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
||||
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
||||
DevCon.Warning("writing to vif1 fifo when stalled");
|
||||
|
||||
vif1ch->qwc += 1;
|
||||
vif1ch.qwc += 1;
|
||||
if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!");
|
||||
bool ret = VIF1transfer((u32*)value, 4);
|
||||
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2)
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
|
||||
{
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
pxAssertDev( ret, "vif stall code not implemented" );
|
||||
}
|
||||
|
||||
// Dummy GIF-TAG Packet to Guarantee Count = 1
|
||||
__aligned16 u32 nloop0_packet[4] = {0, 0, 0, 0};
|
||||
__aligned16 u128 nloop0_packet;
|
||||
|
||||
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value)
|
||||
void __fastcall WriteFIFO_GIF(const mem128_t *value)
|
||||
{
|
||||
pxAssert( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) );
|
||||
GIF_LOG("WriteFIFO/GIF, addr=0x%08X", mem);
|
||||
GIF_LOG("WriteFIFO/GIF <- %ls", value->ToString().c_str());
|
||||
|
||||
CopyQWC(&psHu128(GIF_FIFO), value);
|
||||
CopyQWC(nloop0_packet, value);
|
||||
CopyQWC(&nloop0_packet, value);
|
||||
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_3, 1);
|
||||
GIFPath_CopyTag( GIF_PATH_3, (u128*)nloop0_packet, 1 );
|
||||
GIFPath_CopyTag( GIF_PATH_3, &nloop0_packet, 1 );
|
||||
GetMTGS().SendDataPacket();
|
||||
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH3 )
|
||||
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 )
|
||||
{
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value)
|
||||
{
|
||||
pxAssert( (mem >= IPUout_FIFO) && (mem < D0_CHCR) );
|
||||
|
||||
// All addresses in this page map to 0x7000 and 0x7010:
|
||||
mem &= 0x10;
|
||||
|
||||
IPU_LOG( "WriteFIFO, addr=0x%x", mem );
|
||||
|
||||
if( mem == 0 )
|
||||
{
|
||||
// Should this raise a PS2 exception or just ignore silently?
|
||||
Console.Warning( "WriteFIFO/IPUout (ignored)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
IPU_LOG("WriteFIFO in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X",
|
||||
mem/16, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
|
||||
|
||||
//committing every 16 bytes
|
||||
while( ipu_fifo.in.write((u32*)value, 1) == 0 )
|
||||
{
|
||||
Console.WriteLn("IPU sleeping");
|
||||
Threading::Timeslice();
|
||||
}
|
||||
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
}
|
||||
|
|
12
pcsx2/GS.cpp
12
pcsx2/GS.cpp
|
@ -56,9 +56,9 @@ extern u32 SIGNAL_Data_Pending[2];
|
|||
|
||||
void gsGIFReset()
|
||||
{
|
||||
gifRegs->stat.reset();
|
||||
gifRegs->ctrl.reset();
|
||||
gifRegs->mode.reset();
|
||||
gifRegs.stat.reset();
|
||||
gifRegs.ctrl.reset();
|
||||
gifRegs.mode.reset();
|
||||
}
|
||||
|
||||
void gsReset()
|
||||
|
@ -128,7 +128,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
|
|||
|
||||
SIGNAL_IMR_Pending = false;
|
||||
|
||||
if(gifRegs->stat.P1Q && gifRegs->stat.APATH <= GIF_APATH1) gsPath1Interrupt();
|
||||
if(gifRegs.stat.P1Q && gifRegs.stat.APATH <= GIF_APATH1) gsPath1Interrupt();
|
||||
}
|
||||
|
||||
if(csr.FINISH) CSRreg.FINISH = false;
|
||||
|
@ -286,9 +286,9 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
|
|||
//Only problem is it kills killzone :(.
|
||||
// (yes it *is* a complete hack; both lines here in fact --air)
|
||||
//=========================================================================
|
||||
//gifRegs->stat.OPH = true; // Bleach wants it, Killzone hates it.
|
||||
//gifRegs.stat.OPH = true; // Bleach wants it, Killzone hates it.
|
||||
|
||||
gifRegs->stat.DIR = (u32)value[0];
|
||||
gifRegs.stat.DIR = (u32)value[0];
|
||||
//=========================================================================
|
||||
// BUSDIR INSANITY !! MTGS FLUSH NEEDED
|
||||
//
|
||||
|
|
268
pcsx2/Gif.cpp
268
pcsx2/Gif.cpp
|
@ -54,9 +54,9 @@ void gsPath1Interrupt()
|
|||
|
||||
|
||||
|
||||
if((gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.IP3 == true && gifRegs->stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs->stat.PSE)
|
||||
if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE)
|
||||
{
|
||||
gifRegs->stat.P1Q = false;
|
||||
gifRegs.stat.P1Q = false;
|
||||
|
||||
if (uint size = (Path1WritePos - Path1ReadPos))
|
||||
{
|
||||
|
@ -70,8 +70,8 @@ void gsPath1Interrupt()
|
|||
|
||||
if(GSTransferStatus.PTH1 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
}
|
||||
GetMTGS().SendDataPacket();
|
||||
|
@ -84,8 +84,8 @@ void gsPath1Interrupt()
|
|||
}
|
||||
else
|
||||
{
|
||||
if(gifRegs->stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
|
||||
DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs->stat.IP3, gifRegs->stat.APATH, gifRegs->stat.OPH);
|
||||
if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
|
||||
DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
|
||||
//if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
|
||||
}
|
||||
|
||||
|
@ -104,25 +104,25 @@ __fi void gsInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH3 )
|
||||
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs.stat.OPH = false;
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
|
||||
|
||||
if (!(gif->chcr.STR))
|
||||
if (!(gifch.chcr.STR))
|
||||
{
|
||||
//Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done);
|
||||
//Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((gif->qwc > 0) || (!gspath3done))
|
||||
if ((gifch.qwc > 0) || (!gspath3done))
|
||||
{
|
||||
if (!dmacRegs->ctrl.DMAE)
|
||||
if (!dmacRegs.ctrl.DMAE)
|
||||
{
|
||||
Console.Warning("gs dma masked, re-scheduling...");
|
||||
// re-raise the int shortly in the future
|
||||
|
@ -136,14 +136,14 @@ __fi void gsInterrupt()
|
|||
|
||||
gspath3done = false;
|
||||
gscycles = 0;
|
||||
gif->chcr.STR = false;
|
||||
gifch.chcr.STR = false;
|
||||
|
||||
////
|
||||
/*gifRegs->stat.OPH = false;
|
||||
/*gifRegs.stat.OPH = false;
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;*/
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;*/
|
||||
////
|
||||
gifRegs->stat.clear_flags(GIF_STAT_FQC);
|
||||
gifRegs.stat.clear_flags(GIF_STAT_FQC);
|
||||
clearFIFOstuff(false);
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
//DevCon.Warning("GIF DMA end");
|
||||
|
@ -166,20 +166,20 @@ int _GIFchain()
|
|||
{
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
pMem = dmaGetAddr(gif->madr, false);
|
||||
pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
// reset path3, fixes dark cloud 2
|
||||
GIFPath_Clear( GIF_PATH_3 );
|
||||
|
||||
//must increment madr and clear qwc, else it loops
|
||||
gif->madr += gif->qwc * 16;
|
||||
gif->qwc = 0;
|
||||
gifch.madr += gifch.qwc * 16;
|
||||
gifch.qwc = 0;
|
||||
Console.Warning( "Hackfix - NULL GIFchain" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return WRITERING_DMA(pMem, gif->qwc);
|
||||
return WRITERING_DMA(pMem, gifch.qwc);
|
||||
}
|
||||
|
||||
static __fi void GIFchain()
|
||||
|
@ -187,12 +187,12 @@ static __fi void GIFchain()
|
|||
// qwc check now done outside this function
|
||||
// Voodoocycles
|
||||
// >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
|
||||
/*if (gif->qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
|
||||
/*if (gifch.qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
|
||||
}
|
||||
|
||||
static __fi bool checkTieBit(tDMA_TAG* &ptag)
|
||||
{
|
||||
if (gif->chcr.TIE && ptag->IRQ)
|
||||
if (gifch.chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
GIF_LOG("dmaIrq Set");
|
||||
gspath3done = true;
|
||||
|
@ -204,38 +204,38 @@ static __fi bool checkTieBit(tDMA_TAG* &ptag)
|
|||
|
||||
static __fi tDMA_TAG* ReadTag()
|
||||
{
|
||||
tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
|
||||
|
||||
if (!(gif->transfer("Gif", ptag))) return NULL;
|
||||
if (!(gifch.transfer("Gif", ptag))) return NULL;
|
||||
|
||||
gif->madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
gscycles += 2; // Add 1 cycles from the QW read for the tag
|
||||
|
||||
gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
|
||||
gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
|
||||
return ptag;
|
||||
}
|
||||
|
||||
static __fi tDMA_TAG* ReadTag2()
|
||||
{
|
||||
tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
|
||||
|
||||
gif->unsafeTransfer(ptag);
|
||||
gif->madr = ptag[1]._u32;
|
||||
gifch.unsafeTransfer(ptag);
|
||||
gifch.madr = ptag[1]._u32;
|
||||
|
||||
gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
|
||||
gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
|
||||
return ptag;
|
||||
}
|
||||
|
||||
bool CheckPaths(int Channel)
|
||||
{
|
||||
if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->mode.IMT)
|
||||
if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.mode.IMT)
|
||||
{
|
||||
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3))
|
||||
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
|
||||
{
|
||||
if((vif1.cmd & 0x7f) != 0x51 || gifRegs->stat.P1Q == true)
|
||||
if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true)
|
||||
{
|
||||
gifRegs->stat.IP3 = true;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
gifRegs.stat.IP3 = true;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return false;
|
||||
}
|
||||
|
@ -244,15 +244,15 @@ bool CheckPaths(int Channel)
|
|||
else if((GSTransferStatus.PTH3 == IDLE_MODE)|| (GSTransferStatus.PTH3 == STOPPED_MODE))
|
||||
{
|
||||
//This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
|
||||
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3))
|
||||
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
|
||||
{
|
||||
gifRegs->stat.IP3 = true;
|
||||
gifRegs.stat.IP3 = true;
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gifRegs->stat.IP3 = false;
|
||||
gifRegs.stat.IP3 = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,18 +262,18 @@ void GIFdma()
|
|||
|
||||
gscycles = prevcycles;
|
||||
|
||||
if (gifRegs->ctrl.PSE) // temporarily stop
|
||||
if (gifRegs.ctrl.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
|
||||
CPU_INT(DMAC_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dmacRegs->ctrl.STD == STD_GIF) && (prevcycles != 0))
|
||||
if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0))
|
||||
{
|
||||
//Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR));
|
||||
//Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
|
||||
|
||||
if ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR)
|
||||
if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
|
||||
{
|
||||
CPU_INT(DMAC_GIF, 4);
|
||||
gscycles = 0;
|
||||
|
@ -281,24 +281,24 @@ void GIFdma()
|
|||
}
|
||||
|
||||
prevcycles = 0;
|
||||
gif->qwc = 0;
|
||||
gifch.qwc = 0;
|
||||
}
|
||||
|
||||
clearFIFOstuff(true);
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
|
||||
|
||||
if (vif1Regs->mskpath3 || gifRegs->mode.M3R)
|
||||
if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
|
||||
{
|
||||
if (gif->qwc == 0)
|
||||
if (gifch.qwc == 0)
|
||||
{
|
||||
if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)
|
||||
if ((gifch.chcr.MOD == CHAIN_MODE) && gifch.chcr.STR)
|
||||
{
|
||||
//DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs->mskpath3);
|
||||
//DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs.mskpath3);
|
||||
ptag = ReadTag();
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
if (ptag == NULL) return;
|
||||
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
|
||||
|
||||
//Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
|
||||
|
@ -308,26 +308,26 @@ void GIFdma()
|
|||
|
||||
if (GSTransferStatus.PTH3 == IDLE_MODE)
|
||||
{
|
||||
GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gif->qwc);
|
||||
GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gifch.qwc);
|
||||
|
||||
//DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs->mskpath3);
|
||||
//DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs.mskpath3);
|
||||
|
||||
if(gif->qwc == 0) gsInterrupt();
|
||||
else gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
if(gifch.qwc == 0) gsInterrupt();
|
||||
else gifRegs.stat.set_flags(GIF_STAT_P3Q);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
//Check with Path3 masking games
|
||||
if (gif->qwc > 0) {
|
||||
gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
if (gifch.qwc > 0) {
|
||||
gifRegs.stat.set_flags(GIF_STAT_P3Q);
|
||||
if(CheckPaths(DMAC_GIF) == false) return;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
|
||||
gifRegs.stat.clear_flags(GIF_STAT_P3Q);
|
||||
GIF_LOG("PTH3 MASK Transferring");
|
||||
GIFchain();
|
||||
/*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH_IDLE)
|
||||
/*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH_IDLE)
|
||||
{
|
||||
GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
}*/
|
||||
|
@ -338,54 +338,54 @@ void GIFdma()
|
|||
}
|
||||
|
||||
// Transfer Dn_QWC from Dn_MADR to GIF
|
||||
if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode
|
||||
if ((gifch.chcr.MOD == NORMAL_MODE) || (gifch.qwc > 0)) // Normal Mode
|
||||
{
|
||||
|
||||
if ((dmacRegs->ctrl.STD == STD_GIF) && (gif->chcr.MOD == NORMAL_MODE))
|
||||
if ((dmacRegs.ctrl.STD == STD_GIF) && (gifch.chcr.MOD == NORMAL_MODE))
|
||||
{
|
||||
//Console.WriteLn("DMA Stall Control on GIF normal");
|
||||
}
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
//Check with Path3 masking games
|
||||
//DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs->mskpath3);
|
||||
//DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs.mskpath3);
|
||||
|
||||
|
||||
|
||||
if (gif->qwc > 0) {
|
||||
gifRegs->stat.set_flags(GIF_STAT_P3Q);
|
||||
if (gifch.qwc > 0) {
|
||||
gifRegs.stat.set_flags(GIF_STAT_P3Q);
|
||||
if(CheckPaths(DMAC_GIF) == false) return;
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P3Q);
|
||||
gifRegs.stat.clear_flags(GIF_STAT_P3Q);
|
||||
GIFchain(); //Transfers the data set by the switch
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
return;
|
||||
} else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gif->chcr._u32);
|
||||
} else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gifch.chcr._u32);
|
||||
|
||||
//else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
|
||||
}
|
||||
|
||||
if ((gif->chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
|
||||
if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
|
||||
{
|
||||
ptag = ReadTag();
|
||||
if (ptag == NULL) return;
|
||||
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs->mskpath3);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
if (dmacRegs->ctrl.STD == STD_GIF)
|
||||
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
if (dmacRegs.ctrl.STD == STD_GIF)
|
||||
{
|
||||
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
|
||||
if (!gspath3done && ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR) && (ptag->ID == TAG_REFS))
|
||||
// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
|
||||
if (!gspath3done && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) && (ptag->ID == TAG_REFS))
|
||||
{
|
||||
// stalled.
|
||||
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
|
||||
//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR));
|
||||
//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
|
||||
prevcycles = gscycles;
|
||||
//gif->tadr -= 16;
|
||||
//gifch.tadr -= 16;
|
||||
// Quake III revolution wants to see tadr move.
|
||||
// Simple Media System (homebrew) as well.
|
||||
// -16 also seems right (it shifts the bg image right if anything else).
|
||||
gif->tadr -= 16;
|
||||
gifch.tadr -= 16;
|
||||
// Next line also needs to be here, according to ref
|
||||
gif->qwc = 0;
|
||||
gifch.qwc = 0;
|
||||
hwDmacIrq(DMAC_STALL_SIS);
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
gscycles = 0;
|
||||
|
@ -394,7 +394,7 @@ void GIFdma()
|
|||
}
|
||||
|
||||
checkTieBit(ptag);
|
||||
/*if(gif->qwc == 0)
|
||||
/*if(gifch.qwc == 0)
|
||||
{
|
||||
gsInterrupt();
|
||||
return;
|
||||
|
@ -403,34 +403,34 @@ void GIFdma()
|
|||
|
||||
prevcycles = 0;
|
||||
CPU_INT(DMAC_GIF, gscycles);
|
||||
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||
}
|
||||
|
||||
void dmaGIF()
|
||||
{
|
||||
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
|
||||
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
|
||||
//DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
|
||||
//DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1);
|
||||
|
||||
gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||
|
||||
gifRegs->stat.FQC |= 0x10; // hack ;)
|
||||
gifRegs.stat.FQC |= 0x10; // hack ;)
|
||||
|
||||
if (gif->chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
gspath3done = true;
|
||||
}
|
||||
clearFIFOstuff(true);
|
||||
|
||||
if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0)
|
||||
if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
|
||||
{
|
||||
//DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc());
|
||||
if ((gif->chcr.tag().ID == TAG_REFE) || (gif->chcr.tag().ID == TAG_END))
|
||||
//DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
|
||||
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END))
|
||||
{
|
||||
gspath3done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmacRegs->ctrl.MFD == MFD_GIF) // GIF MFIFO
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
|
||||
{
|
||||
//Console.WriteLn("GIF MFIFO");
|
||||
gifMFIFOInterrupt();
|
||||
|
@ -443,7 +443,7 @@ void dmaGIF()
|
|||
// called from only one location, so forceinline it:
|
||||
static __fi bool mfifoGIFrbTransfer()
|
||||
{
|
||||
u32 mfifoqwc = min(gifqwc, (u32)gif->qwc);
|
||||
u32 mfifoqwc = min(gifqwc, (u32)gifch.qwc);
|
||||
u32 *src;
|
||||
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc);
|
||||
|
@ -453,21 +453,21 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
// memory similarly to how it wraps VU1 memory on PATH1.
|
||||
|
||||
/* Check if the transfer should wrap around the ring buffer */
|
||||
if ((gif->madr + mfifoqwc * 16) > (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16))
|
||||
if ((gifch.madr + mfifoqwc * 16) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
|
||||
{
|
||||
uint s1 = ((dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16) - gif->madr) >> 4;
|
||||
uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
|
||||
uint s2 = (mfifoqwc - s1);
|
||||
|
||||
/* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
|
||||
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
|
||||
|
||||
src = (u32*)PSM(gif->madr);
|
||||
src = (u32*)PSM(gifch.madr);
|
||||
if (src == NULL) return false;
|
||||
uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
|
||||
|
||||
if (copied == s1) // but only copy second if first didn't abort prematurely for some reason.
|
||||
{
|
||||
src = (u32*)PSM(dmacRegs->rbor.ADDR);
|
||||
src = (u32*)PSM(dmacRegs.rbor.ADDR);
|
||||
if (src == NULL) return false;
|
||||
copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
|
||||
}
|
||||
|
@ -476,11 +476,11 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
}
|
||||
else
|
||||
{
|
||||
/* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */
|
||||
src = (u32*)PSM(gif->madr);
|
||||
/* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
|
||||
src = (u32*)PSM(gifch.madr);
|
||||
if (src == NULL) return false;
|
||||
mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
|
||||
gif->madr = dmacRegs->rbor.ADDR + (gif->madr & dmacRegs->rbsr.RMSK);
|
||||
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
|
||||
}
|
||||
|
||||
GetMTGS().SendDataPacket();
|
||||
|
@ -493,10 +493,10 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
static __fi bool mfifoGIFchain()
|
||||
{
|
||||
/* Is QWC = 0? if so there is nothing to transfer */
|
||||
if (gif->qwc == 0) return true;
|
||||
if (gifch.qwc == 0) return true;
|
||||
|
||||
if (gif->madr >= dmacRegs->rbor.ADDR &&
|
||||
gif->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
|
||||
if (gifch.madr >= dmacRegs.rbor.ADDR &&
|
||||
gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK))
|
||||
{
|
||||
if (!mfifoGIFrbTransfer()) return false;
|
||||
}
|
||||
|
@ -504,10 +504,10 @@ static __fi bool mfifoGIFchain()
|
|||
{
|
||||
int mfifoqwc;
|
||||
|
||||
tDMA_TAG *pMem = dmaGetAddr(gif->madr, false);
|
||||
tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL) return false;
|
||||
|
||||
mfifoqwc = WRITERING_DMA(pMem, gif->qwc);
|
||||
mfifoqwc = WRITERING_DMA(pMem, gifch.qwc);
|
||||
mfifocycles += (mfifoqwc) * 2; /* guessing */
|
||||
}
|
||||
|
||||
|
@ -516,7 +516,7 @@ static __fi bool mfifoGIFchain()
|
|||
|
||||
static u32 qwctag(u32 mask)
|
||||
{
|
||||
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
|
||||
return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
|
||||
}
|
||||
|
||||
void mfifoGIFtransfer(int qwc)
|
||||
|
@ -536,16 +536,16 @@ void mfifoGIFtransfer(int qwc)
|
|||
gifempty = false;
|
||||
}
|
||||
|
||||
if (gifRegs->ctrl.PSE) // temporarily stop
|
||||
if (gifRegs.ctrl.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
CPU_INT(DMAC_MFIFO_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gif->qwc == 0)
|
||||
if (gifch.qwc == 0)
|
||||
{
|
||||
if (gif->tadr == spr0->madr)
|
||||
if (gifch.tadr == spr0ch.madr)
|
||||
{
|
||||
//if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);
|
||||
hwDmacIrq(DMAC_MFIFO_EMPTY);
|
||||
|
@ -554,55 +554,55 @@ void mfifoGIFtransfer(int qwc)
|
|||
return;
|
||||
}
|
||||
|
||||
gif->tadr = qwctag(gif->tadr);
|
||||
gifch.tadr = qwctag(gifch.tadr);
|
||||
|
||||
ptag = dmaGetAddr(gif->tadr, false);
|
||||
gif->unsafeTransfer(ptag);
|
||||
gif->madr = ptag[1]._u32;
|
||||
ptag = dmaGetAddr(gifch.tadr, false);
|
||||
gifch.unsafeTransfer(ptag);
|
||||
gifch.madr = ptag[1]._u32;
|
||||
|
||||
mfifocycles += 2;
|
||||
|
||||
GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
|
||||
ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr, gifqwc, spr0->madr);
|
||||
ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
|
||||
|
||||
gifqwc--;
|
||||
|
||||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_REFE: // Refe - Transfer Packet According to ADDR field
|
||||
gif->tadr = qwctag(gif->tadr + 16);
|
||||
gifch.tadr = qwctag(gifch.tadr + 16);
|
||||
gifstate = GIF_STATE_DONE; //End Transfer
|
||||
break;
|
||||
|
||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||
gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW after Tag
|
||||
gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data
|
||||
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW after Tag
|
||||
gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
|
||||
gifstate = GIF_STATE_READY;
|
||||
break;
|
||||
|
||||
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
|
||||
{
|
||||
u32 temp = gif->madr; //Temporarily Store ADDR
|
||||
gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW following the tag
|
||||
gif->tadr = temp; //Copy temporarily stored ADDR to Tag
|
||||
u32 temp = gifch.madr; //Temporarily Store ADDR
|
||||
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW following the tag
|
||||
gifch.tadr = temp; //Copy temporarily stored ADDR to Tag
|
||||
gifstate = GIF_STATE_READY;
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_REF: // Ref - Transfer QWC from ADDR field
|
||||
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
|
||||
gif->tadr = qwctag(gif->tadr + 16); //Set TADR to next tag
|
||||
gifch.tadr = qwctag(gifch.tadr + 16); //Set TADR to next tag
|
||||
gifstate = GIF_STATE_READY;
|
||||
break;
|
||||
|
||||
case TAG_END: // End - Transfer QWC following the tag
|
||||
gif->madr = qwctag(gif->tadr + 16); //Set MADR to data following the tag
|
||||
gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data
|
||||
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to data following the tag
|
||||
gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
|
||||
gifstate = GIF_STATE_DONE; //End Transfer
|
||||
break;
|
||||
}
|
||||
|
||||
if ((gif->chcr.TIE) && (ptag->IRQ))
|
||||
if ((gifch.chcr.TIE) && (ptag->IRQ))
|
||||
{
|
||||
SPR_LOG("dmaIrq Set");
|
||||
gifstate = GIF_STATE_DONE;
|
||||
|
@ -612,14 +612,14 @@ void mfifoGIFtransfer(int qwc)
|
|||
|
||||
if (!mfifoGIFchain())
|
||||
{
|
||||
Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gif->qwc, gif->madr, gif->tadr);
|
||||
Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
|
||||
gifstate = GIF_STATE_STALL;
|
||||
}
|
||||
|
||||
if ((gif->qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
|
||||
if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
|
||||
CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
|
||||
|
||||
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
|
||||
}
|
||||
|
||||
void gifMFIFOInterrupt()
|
||||
|
@ -634,16 +634,16 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH3 )
|
||||
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 )
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
|
||||
if(CheckPaths(11) == false) return;
|
||||
|
||||
if (!(gif->chcr.STR))
|
||||
if (!(gifch.chcr.STR))
|
||||
{
|
||||
Console.WriteLn("WTF GIFMFIFO");
|
||||
cpuRegs.interrupt &= ~(1 << 11);
|
||||
|
@ -659,7 +659,7 @@ void gifMFIFOInterrupt()
|
|||
gifstate |= GIF_STATE_EMPTY;
|
||||
gifempty = true;
|
||||
|
||||
gifRegs->stat.IMT = false;
|
||||
gifRegs.stat.IMT = false;
|
||||
return;
|
||||
}
|
||||
mfifoGIFtransfer(0);
|
||||
|
@ -667,7 +667,7 @@ void gifMFIFOInterrupt()
|
|||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((gifstate & GIF_STATE_READY) || (gif->qwc > 0))
|
||||
if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0))
|
||||
{
|
||||
Console.Error("gifMFIFO Panic > Shouldn't go here!");
|
||||
return;
|
||||
|
@ -679,10 +679,10 @@ void gifMFIFOInterrupt()
|
|||
gspath3done = false;
|
||||
gscycles = 0;
|
||||
|
||||
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
|
||||
gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
|
||||
|
||||
vif1Regs->stat.VGW = false;
|
||||
gif->chcr.STR = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
gifch.chcr.STR = false;
|
||||
gifstate = GIF_STATE_READY;
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
clearFIFOstuff(false);
|
||||
|
|
|
@ -277,7 +277,7 @@ struct GIFregisters
|
|||
u32 padding9[3];
|
||||
};
|
||||
|
||||
#define gifRegs ((GIFregisters*)(eeHw+0x3000))
|
||||
static GIFregisters& gifRegs = (GIFregisters&)eeHw[0x3000];
|
||||
|
||||
extern tGSTransferStatus GSTransferStatus;
|
||||
|
||||
|
|
86
pcsx2/Hw.cpp
86
pcsx2/Hw.cpp
|
@ -104,7 +104,7 @@ __fi void dmacInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1)
|
||||
if (!(dmacRegs.ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1)
|
||||
{
|
||||
//DevCon.Warning("DMAC Suspended or Disabled on interrupt");
|
||||
return;
|
||||
|
@ -131,7 +131,7 @@ void hwDmacIrq(int n)
|
|||
__ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
|
||||
{
|
||||
// all FIFO addresses should always be QWC-aligned.
|
||||
pxAssume((dmacRegs->rbor.ADDR & 15) == 0);
|
||||
pxAssume((dmacRegs.rbor.ADDR & 15) == 0);
|
||||
pxAssume((addr & 15) == 0);
|
||||
|
||||
// DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map
|
||||
|
@ -139,24 +139,24 @@ __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
|
|||
// valid/invalid page areas of ram, so realistically we only need to test the base address
|
||||
// of the FIFO for address validity.
|
||||
|
||||
if (u128* dst = (u128*)PSM(dmacRegs->rbor.ADDR))
|
||||
if (u128* dst = (u128*)PSM(dmacRegs.rbor.ADDR))
|
||||
{
|
||||
const u32 ringsize = (dmacRegs->rbsr.RMSK / 16) + 1;
|
||||
pxAssertMsg( PSM(dmacRegs->rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" );
|
||||
uint startpos = (addr & dmacRegs->rbsr.RMSK)/16;
|
||||
const u32 ringsize = (dmacRegs.rbsr.RMSK / 16) + 1;
|
||||
pxAssertMsg( PSM(dmacRegs.rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" );
|
||||
uint startpos = (addr & dmacRegs.rbsr.RMSK)/16;
|
||||
MemCopy_WrappedDest( data, dst, startpos, ringsize, qwc );
|
||||
}
|
||||
else
|
||||
{
|
||||
SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR );
|
||||
pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR) );
|
||||
SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR );
|
||||
pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
||||
__ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) {
|
||||
switch (id) {
|
||||
case TAG_REFE: // Refe - Transfer Packet According to ADDR field
|
||||
//End Transfer
|
||||
|
@ -164,49 +164,49 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
|||
|
||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||
// Set MADR to QW afer tag, and set TADR to QW following the data.
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma->tadr = dma->madr + (dma->qwc << 4);
|
||||
dma.madr = dma.tadr + 16;
|
||||
dma.tadr = dma.madr + (dma.qwc << 4);
|
||||
return false;
|
||||
|
||||
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
|
||||
{
|
||||
// Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
|
||||
u32 temp = dma->madr;
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma->tadr = temp;
|
||||
u32 temp = dma.madr;
|
||||
dma.madr = dma.tadr + 16;
|
||||
dma.tadr = temp;
|
||||
return false;
|
||||
}
|
||||
case TAG_REF: // Ref - Transfer QWC from ADDR field
|
||||
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
|
||||
//Set TADR to next tag
|
||||
dma->tadr += 16;
|
||||
dma.tadr += 16;
|
||||
return false;
|
||||
|
||||
case TAG_CALL: // Call - Transfer QWC following the tag, save succeeding tag
|
||||
{
|
||||
// Store the address in MADR in temp, and set MADR to the data following the tag.
|
||||
u32 temp = dma->madr;
|
||||
dma->madr = dma->tadr + 16;
|
||||
u32 temp = dma.madr;
|
||||
dma.madr = dma.tadr + 16;
|
||||
|
||||
if(temp == 0)
|
||||
{
|
||||
DevCon.Warning("DMA Chain CALL next tag error. Tag Addr = 0");
|
||||
dma->tadr = dma->madr + (dma->qwc << 4);
|
||||
dma.tadr = dma.madr + (dma.qwc << 4);
|
||||
return false;
|
||||
}
|
||||
// Stash an address on the address stack pointer.
|
||||
switch(dma->chcr.ASP)
|
||||
switch(dma.chcr.ASP)
|
||||
{
|
||||
case 0: //Check if ASR0 is empty
|
||||
// Store the succeeding tag in asr0, and mark chcr as having 1 address.
|
||||
dma->asr0 = dma->madr + (dma->qwc << 4);
|
||||
dma->chcr.ASP++;
|
||||
dma.asr0 = dma.madr + (dma.qwc << 4);
|
||||
dma.chcr.ASP++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Store the succeeding tag in asr1, and mark chcr as having 2 addresses.
|
||||
dma->asr1 = dma->madr + (dma->qwc << 4);
|
||||
dma->chcr.ASP++;
|
||||
dma.asr1 = dma.madr + (dma.qwc << 4);
|
||||
dma.chcr.ASP++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -215,48 +215,48 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
|||
}
|
||||
|
||||
// Set TADR to the address from MADR we stored in temp.
|
||||
dma->tadr = temp;
|
||||
dma.tadr = temp;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
|
||||
//Set MADR to data following the tag.
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma.madr = dma.tadr + 16;
|
||||
|
||||
// Snag an address from the address stack pointer.
|
||||
switch(dma->chcr.ASP)
|
||||
switch(dma.chcr.ASP)
|
||||
{
|
||||
case 2:
|
||||
// Pull asr1 from the stack, give it to TADR, and decrease the # of addresses.
|
||||
dma->tadr = dma->asr1;
|
||||
dma->asr1 = 0;
|
||||
dma->chcr.ASP--;
|
||||
dma.tadr = dma.asr1;
|
||||
dma.asr1 = 0;
|
||||
dma.chcr.ASP--;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Pull asr0 from the stack, give it to TADR, and decrease the # of addresses.
|
||||
dma->tadr = dma->asr0;
|
||||
dma->asr0 = 0;
|
||||
dma->chcr.ASP--;
|
||||
dma.tadr = dma.asr0;
|
||||
dma.asr0 = 0;
|
||||
dma.chcr.ASP--;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
// There aren't any addresses to pull, so end the transfer.
|
||||
//dma->tadr += 16; //Clear tag address - Kills Klonoa 2
|
||||
//dma.tadr += 16; //Clear tag address - Kills Klonoa 2
|
||||
return true;
|
||||
|
||||
default:
|
||||
// If ASR1 and ASR0 are messed up, end the transfer.
|
||||
//Console.Error("TAG_RET: ASR 1 & 0 == 1. This shouldn't happen!");
|
||||
//dma->tadr += 16; //Clear tag address - Kills Klonoa 2
|
||||
//dma.tadr += 16; //Clear tag address - Kills Klonoa 2
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case TAG_END: // End - Transfer QWC following the tag
|
||||
//Set MADR to data following the tag, and end the transfer.
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma.madr = dma.tadr + 16;
|
||||
//Don't Increment tadr; breaks Soul Calibur II and III
|
||||
return true;
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool hwDmacSrcChain(DMACh *dma, int id)
|
||||
bool hwDmacSrcChain(DMACh& dma, int id)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
|
@ -276,26 +276,26 @@ bool hwDmacSrcChain(DMACh *dma, int id)
|
|||
|
||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||
// Set MADR to QW after the tag, and TADR to QW following the data.
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma->tadr = dma->madr + (dma->qwc << 4);
|
||||
dma.madr = dma.tadr + 16;
|
||||
dma.tadr = dma.madr + (dma.qwc << 4);
|
||||
return false;
|
||||
|
||||
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
|
||||
// Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
|
||||
temp = dma->madr;
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma->tadr = temp;
|
||||
temp = dma.madr;
|
||||
dma.madr = dma.tadr + 16;
|
||||
dma.tadr = temp;
|
||||
return false;
|
||||
|
||||
case TAG_REF: // Ref - Transfer QWC from ADDR field
|
||||
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
|
||||
//Set TADR to next tag
|
||||
dma->tadr += 16;
|
||||
dma.tadr += 16;
|
||||
return false;
|
||||
|
||||
case TAG_END: // End - Transfer QWC following the tag
|
||||
//Set MADR to data following the tag, and end the transfer.
|
||||
dma->madr = dma->tadr + 16;
|
||||
dma.madr = dma.tadr + 16;
|
||||
//Don't Increment tadr; breaks Soul Calibur II and III
|
||||
return true;
|
||||
}
|
||||
|
|
235
pcsx2/Hw.h
235
pcsx2/Hw.h
|
@ -13,28 +13,84 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __HW_H__
|
||||
#define __HW_H__
|
||||
namespace EEMemoryMap
|
||||
{
|
||||
static const uint RCNT0_Start = 0x10000000;
|
||||
static const uint RCNT0_End = 0x10000800;
|
||||
static const uint RCNT1_Start = 0x10000800;
|
||||
static const uint RCNT1_End = 0x10001000;
|
||||
static const uint RCNT2_Start = 0x10001000;
|
||||
static const uint RCNT2_End = 0x10001800;
|
||||
static const uint RCNT3_Start = 0x10001800;
|
||||
static const uint RCNT3_End = 0x10002000;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Hardware FIFOs (128 bit access only!)
|
||||
//
|
||||
// VIF0 -- 0x10004000 -- eeHw[0x4000]
|
||||
// VIF1 -- 0x10005000 -- eeHw[0x5000]
|
||||
// GIF -- 0x10006000 -- eeHw[0x6000]
|
||||
// IPUout -- 0x10007000 -- eeHw[0x7000]
|
||||
// IPUin -- 0x10007010 -- eeHw[0x7010]
|
||||
static const uint IPU_Start = 0x10002000;
|
||||
static const uint IPU_End = 0x10003000;
|
||||
|
||||
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out);
|
||||
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out);
|
||||
void __fastcall ReadFIFO_page_6(u32 mem, mem128_t *out);
|
||||
void __fastcall ReadFIFO_page_7(u32 mem, mem128_t *out);
|
||||
static const uint GIF_Start = 0x10003000;
|
||||
static const uint GIF_End = 0x10003800;
|
||||
|
||||
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value);
|
||||
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value);
|
||||
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value);
|
||||
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value);
|
||||
static const uint VIF0_Start = 0x10003800;
|
||||
static const uint VIF0_End = 0x10003C00;
|
||||
static const uint VIF1_Start = 0x10003C00;
|
||||
static const uint VIF1_End = 0x10004000;
|
||||
|
||||
static const uint VIF0_FIFO_Start = 0x10004000;
|
||||
static const uint VIF0_FIFO_End = 0x10005000;
|
||||
static const uint VIF1_FIFO_Start = 0x10005000;
|
||||
static const uint VIF1_FIFO_End = 0x10006000;
|
||||
static const uint GIF_FIFO_Start = 0x10006000;
|
||||
static const uint GIF_FIFO_End = 0x10007000;
|
||||
static const uint IPU_FIFO_Start = 0x10007000;
|
||||
static const uint IPU_FIFO_End = 0x10008000;
|
||||
|
||||
static const uint VIF0dma_Start = 0x10008000;
|
||||
static const uint VIF0dma_End = 0x10009000;
|
||||
static const uint VIF1dma_Start = 0x10009000;
|
||||
static const uint VIF1dma_End = 0x1000A000;
|
||||
|
||||
static const uint GIFdma_Start = 0x1000A000;
|
||||
static const uint GIFdma_End = 0x1000B000;
|
||||
|
||||
static const uint fromIPU_Start = 0x1000B000;
|
||||
static const uint fromIPU_End = 0x1000B400;
|
||||
static const uint toIPU_Start = 0x1000B400;
|
||||
static const uint toIPU_End = 0x1000C000;
|
||||
|
||||
static const uint SIF0dma_Start = 0x1000C000;
|
||||
static const uint SIF0dma_End = 0x1000C400;
|
||||
static const uint SIF1dma_Start = 0x1000C400;
|
||||
static const uint SIF1dma_End = 0x1000C800;
|
||||
static const uint SIF2dma_Start = 0x1000C800;
|
||||
static const uint SIF2dma_End = 0x1000D000;
|
||||
|
||||
static const uint fromSPR_Start = 0x1000D000;
|
||||
static const uint fromSPR_End = 0x1000D400;
|
||||
static const uint toSPR_Start = 0x1000D400;
|
||||
static const uint toSPR_End = 0x1000E000;
|
||||
|
||||
static const uint DMAC_Start = 0x1000E000;
|
||||
static const uint DMAC_End = 0x1000F000;
|
||||
|
||||
static const uint INTC_Start = 0x1000F000;
|
||||
static const uint INTC_End = 0x1000F100;
|
||||
|
||||
static const uint SIO_Start = 0x1000F100;
|
||||
static const uint SIO_End = 0x1000F200;
|
||||
static const uint SBUS_Start = 0x1000F200;
|
||||
static const uint SBUS_End = 0x1000F400;
|
||||
|
||||
// MCH area -- Really not sure what this area is. Information is lacking.
|
||||
static const uint MCH_Start = 0x1000F400;
|
||||
static const uint MCH_End = 0x1000F500;
|
||||
|
||||
// Extended master control register area for DMAC.
|
||||
static const uint DMACext_Start = 0x1000F500;
|
||||
static const uint DMACext_End = 0x1000F600;
|
||||
|
||||
};
|
||||
|
||||
// HW defines
|
||||
enum EERegisterAddresses
|
||||
|
@ -86,14 +142,14 @@ enum EERegisterAddresses
|
|||
VIF0_ITOPS = 0x10003890,
|
||||
VIF0_ITOP = 0x100038d0,
|
||||
VIF0_TOP = 0x100038e0,
|
||||
VIF0_R0 = 0x10003900,
|
||||
VIF0_R1 = 0x10003910,
|
||||
VIF0_R2 = 0x10003920,
|
||||
VIF0_R3 = 0x10003930,
|
||||
VIF0_C0 = 0x10003940,
|
||||
VIF0_C1 = 0x10003950,
|
||||
VIF0_C2 = 0x10003960,
|
||||
VIF0_C3 = 0x10003970,
|
||||
VIF0_ROW0 = 0x10003900,
|
||||
VIF0_ROW1 = 0x10003910,
|
||||
VIF0_ROW2 = 0x10003920,
|
||||
VIF0_ROW3 = 0x10003930,
|
||||
VIF0_COL0 = 0x10003940,
|
||||
VIF0_COL1 = 0x10003950,
|
||||
VIF0_COL2 = 0x10003960,
|
||||
VIF0_COL3 = 0x10003970,
|
||||
|
||||
VIF1_STAT = 0x10003c00,
|
||||
VIF1_FBRST = 0x10003c10,
|
||||
|
@ -110,14 +166,14 @@ enum EERegisterAddresses
|
|||
VIF1_TOPS = 0x10003cc0,
|
||||
VIF1_ITOP = 0x10003cd0,
|
||||
VIF1_TOP = 0x10003ce0,
|
||||
VIF1_R0 = 0x10003d00,
|
||||
VIF1_R1 = 0x10003d10,
|
||||
VIF1_R2 = 0x10003d20,
|
||||
VIF1_R3 = 0x10003d30,
|
||||
VIF1_C0 = 0x10003d40,
|
||||
VIF1_C1 = 0x10003d50,
|
||||
VIF1_C2 = 0x10003d60,
|
||||
VIF1_C3 = 0x10003d70,
|
||||
VIF1_ROW0 = 0x10003d00,
|
||||
VIF1_ROW1 = 0x10003d10,
|
||||
VIF1_ROW2 = 0x10003d20,
|
||||
VIF1_ROW3 = 0x10003d30,
|
||||
VIF1_COL0 = 0x10003d40,
|
||||
VIF1_COL1 = 0x10003d50,
|
||||
VIF1_COL2 = 0x10003d60,
|
||||
VIF1_COL3 = 0x10003d70,
|
||||
|
||||
VIF0_FIFO = 0x10004000,
|
||||
VIF1_FIFO = 0x10005000,
|
||||
|
@ -134,6 +190,13 @@ enum EERegisterAddresses
|
|||
D0_ASR0 = 0x10008040,
|
||||
D0_ASR1 = 0x10008050,
|
||||
|
||||
VIF0_CHCR = 0x10008000,
|
||||
VIF0_MADR = 0x10008010,
|
||||
VIF0_QWC = 0x10008020,
|
||||
VIF0_TADR = 0x10008030,
|
||||
VIF0_ASR0 = 0x10008040,
|
||||
VIF0_ASR1 = 0x10008050,
|
||||
|
||||
//VIF1
|
||||
D1_CHCR = 0x10009000,
|
||||
D1_MADR = 0x10009010,
|
||||
|
@ -141,7 +204,13 @@ enum EERegisterAddresses
|
|||
D1_TADR = 0x10009030,
|
||||
D1_ASR0 = 0x10009040,
|
||||
D1_ASR1 = 0x10009050,
|
||||
D1_SADR = 0x10009080,
|
||||
|
||||
VIF1_CHCR = 0x10009000,
|
||||
VIF1_MADR = 0x10009010,
|
||||
VIF1_QWC = 0x10009020,
|
||||
VIF1_TADR = 0x10009030,
|
||||
VIF1_ASR0 = 0x10009040,
|
||||
VIF1_ASR1 = 0x10009050,
|
||||
|
||||
//GS
|
||||
D2_CHCR = 0x1000A000,
|
||||
|
@ -150,44 +219,82 @@ enum EERegisterAddresses
|
|||
D2_TADR = 0x1000A030,
|
||||
D2_ASR0 = 0x1000A040,
|
||||
D2_ASR1 = 0x1000A050,
|
||||
D2_SADR = 0x1000A080,
|
||||
|
||||
GIF_CHCR = 0x1000A000,
|
||||
GIF_MADR = 0x1000A010,
|
||||
GIF_QWC = 0x1000A020,
|
||||
GIF_TADR = 0x1000A030,
|
||||
GIF_ASR0 = 0x1000A040,
|
||||
GIF_ASR1 = 0x1000A050,
|
||||
|
||||
//fromIPU
|
||||
D3_CHCR = 0x1000B000,
|
||||
D3_MADR = 0x1000B010,
|
||||
D3_QWC = 0x1000B020,
|
||||
D3_TADR = 0x1000B030,
|
||||
D3_SADR = 0x1000B080,
|
||||
|
||||
fromIPU_CHCR = 0x1000B000,
|
||||
fromIPU_MADR = 0x1000B010,
|
||||
fromIPU_QWC = 0x1000B020,
|
||||
fromIPU_TADR = 0x1000B030,
|
||||
|
||||
//toIPU
|
||||
D4_CHCR = 0x1000B400,
|
||||
D4_MADR = 0x1000B410,
|
||||
D4_QWC = 0x1000B420,
|
||||
D4_TADR = 0x1000B430,
|
||||
D4_SADR = 0x1000B480,
|
||||
|
||||
toIPU_CHCR = 0x1000B400,
|
||||
toIPU_MADR = 0x1000B410,
|
||||
toIPU_QWC = 0x1000B420,
|
||||
toIPU_TADR = 0x1000B430,
|
||||
|
||||
//SIF0
|
||||
D5_CHCR = 0x1000C000,
|
||||
D5_MADR = 0x1000C010,
|
||||
D5_QWC = 0x1000C020,
|
||||
|
||||
SIF0_CHCR = 0x1000C000,
|
||||
SIF0_MADR = 0x1000C010,
|
||||
SIF0_QWC = 0x1000C020,
|
||||
|
||||
//SIF1
|
||||
D6_CHCR = 0x1000C400,
|
||||
D6_MADR = 0x1000C410,
|
||||
D6_QWC = 0x1000C420,
|
||||
D6_TADR = 0x1000C430,
|
||||
|
||||
SIF1_CHCR = 0x1000C400,
|
||||
SIF1_MADR = 0x1000C410,
|
||||
SIF1_QWC = 0x1000C420,
|
||||
SIF1_TADR = 0x1000C430,
|
||||
|
||||
//SIF2
|
||||
D7_CHCR = 0x1000C800,
|
||||
D7_MADR = 0x1000C810,
|
||||
D7_QWC = 0x1000C820,
|
||||
|
||||
SIF2_CHCR = 0x1000C800,
|
||||
SIF2_MADR = 0x1000C810,
|
||||
SIF2_QWC = 0x1000C820,
|
||||
|
||||
//fromSPR
|
||||
D8_CHCR = 0x1000D000,
|
||||
D8_MADR = 0x1000D010,
|
||||
D8_QWC = 0x1000D020,
|
||||
D8_SADR = 0x1000D080,
|
||||
D9_CHCR = 0x1000D400,
|
||||
|
||||
fromSPR_CHCR = 0x1000D000,
|
||||
fromSPR_MADR = 0x1000D010,
|
||||
fromSPR_QWC = 0x1000D020,
|
||||
|
||||
//toSPR
|
||||
D9_CHCR = 0x1000D400,
|
||||
D9_MADR = 0x1000D010,
|
||||
D9_QWC = 0x1000D020,
|
||||
|
||||
toSPR_CHCR = 0x1000D400,
|
||||
toSPR_MADR = 0x1000D410,
|
||||
toSPR_QWC = 0x1000D420,
|
||||
|
||||
DMAC_CTRL = 0x1000E000,
|
||||
DMAC_STAT = 0x1000E010,
|
||||
|
@ -264,53 +371,7 @@ union tGS_SMODE2
|
|||
bool IsInterlaced() const { return INT; }
|
||||
};
|
||||
|
||||
void hwReset();
|
||||
|
||||
// hw read functions
|
||||
extern mem8_t hwRead8 (u32 mem);
|
||||
extern mem16_t hwRead16(u32 mem);
|
||||
|
||||
extern mem32_t __fastcall hwRead32_page_00(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_page_01(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_page_02(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_page_0F(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_generic(u32 mem);
|
||||
|
||||
extern void __fastcall hwRead64_page_00(u32 mem, mem64_t* result );
|
||||
extern void __fastcall hwRead64_page_01(u32 mem, mem64_t* result );
|
||||
extern void __fastcall hwRead64_page_02(u32 mem, mem64_t* result );
|
||||
extern void __fastcall hwRead64_generic_INTC_HACK(u32 mem, mem64_t *out);
|
||||
extern void __fastcall hwRead64_generic(u32 mem, mem64_t* result );
|
||||
|
||||
extern void __fastcall hwRead128_page_00(u32 mem, mem128_t* result );
|
||||
extern void __fastcall hwRead128_page_01(u32 mem, mem128_t* result );
|
||||
extern void __fastcall hwRead128_page_02(u32 mem, mem128_t* result );
|
||||
extern void __fastcall hwRead128_generic(u32 mem, mem128_t *out);
|
||||
|
||||
// hw write functions
|
||||
extern void hwWrite8 (u32 mem, u8 value);
|
||||
extern void hwWrite16(u32 mem, u16 value);
|
||||
|
||||
extern void __fastcall hwWrite32_page_00( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_01( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_02( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_03( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_0B( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_0E( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_page_0F( u32 mem, mem32_t value );
|
||||
extern void __fastcall hwWrite32_generic( u32 mem, mem32_t value );
|
||||
|
||||
extern void __fastcall hwWrite64_page_00( u32 mem, const mem64_t* srcval );
|
||||
extern void __fastcall hwWrite64_page_01( u32 mem, const mem64_t* srcval );
|
||||
extern void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval );
|
||||
extern void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval );
|
||||
extern void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval );
|
||||
extern void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval );
|
||||
|
||||
extern void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval);
|
||||
extern void hwReset();
|
||||
|
||||
extern const int rdram_devices;
|
||||
extern int rdram_sdevid;
|
||||
|
||||
#endif /* __HW_H__ */
|
||||
|
|
618
pcsx2/HwRead.cpp
618
pcsx2/HwRead.cpp
|
@ -16,9 +16,11 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include "Hardware.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
#include "ps2/eeHwTraceLog.inl"
|
||||
|
||||
using namespace R5900;
|
||||
|
||||
static __fi void IntCHackCheck()
|
||||
|
@ -29,470 +31,272 @@ static __fi void IntCHackCheck()
|
|||
if( diff > 0 ) cpuRegs.cycle = g_nextBranchCycle;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware READ 8 bit
|
||||
static const uint HwF_VerboseConLog = 1<<0;
|
||||
static const uint HwF_IntcStatHack = 1<<1; // used for Reads only.
|
||||
|
||||
__fi mem8_t hwRead8(u32 mem)
|
||||
template< uint page, bool intcstathack >
|
||||
mem32_t __fastcall _hwRead32(u32 mem)
|
||||
{
|
||||
u8 ret;
|
||||
pxAssume( (mem & 0x03) == 0 );
|
||||
|
||||
const u16 masked_mem = mem & 0xffff;
|
||||
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||
// (implementation should be modelled after thee iopHWRead/iopHwWrite files)
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR )
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("8bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu8(mem) );
|
||||
#endif
|
||||
return psHu8(mem);
|
||||
}
|
||||
// DevCon.Warning("Unexpected hwRead8 from 0x%x", mem);
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
switch((mem >> 12) & 0xf)
|
||||
switch( page )
|
||||
{
|
||||
case 0x00: return rcntRead32<0x00>( mem );
|
||||
case 0x01: return rcntRead32<0x01>( mem );
|
||||
|
||||
case 0x02: return ipuRead32( mem );
|
||||
|
||||
case 0x03:
|
||||
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read8 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
|
||||
else HW_LOG("GIF Register Read8 at 0x%x, value=0x%x", mem, psHu32(mem) );
|
||||
if ((mem == GIF_STAT) && CHECK_OPHFLAGHACK)
|
||||
{
|
||||
gifRegs.stat.OPH = !gifRegs.stat.OPH;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
// [Ps2Confirm] Reading from FIFOs using non-128 bit reads is a complete mystery.
|
||||
// No game is known to attempt such a thing (yay!), so probably nothing for us to
|
||||
// worry about. Chances are, though, doing so is "legal" and yields some sort
|
||||
// of reproducible behavior. Candidate for real hardware testing.
|
||||
|
||||
// Current assumption: Reads 128 bits and discards the unused portion.
|
||||
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
DevCon.WriteLn( Color_Cyan, "Reading 32-bit FIFO data" );
|
||||
|
||||
HW_LOG("Hardware Read 8 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu8(mem) );
|
||||
ret = psHu8(mem);
|
||||
return ret;
|
||||
u128 out128;
|
||||
hwRead128<page>(mem, &out128);
|
||||
return out128._u32[(mem >> 2) & 0x3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (mem)
|
||||
{
|
||||
case RCNT0_COUNT: ret = (u8)rcntRcount(0); break;
|
||||
case RCNT0_MODE: ret = (u8)counters[0].modeval; break;
|
||||
case RCNT0_TARGET: ret = (u8)counters[0].target; break;
|
||||
case RCNT0_HOLD: ret = (u8)counters[0].hold; break;
|
||||
case RCNT0_COUNT + 1: ret = (u8)(rcntRcount(0)>>8); break;
|
||||
case RCNT0_MODE + 1: ret = (u8)(counters[0].modeval>>8); break;
|
||||
case RCNT0_TARGET + 1: ret = (u8)(counters[0].target>>8); break;
|
||||
case RCNT0_HOLD + 1: ret = (u8)(counters[0].hold>>8); break;
|
||||
|
||||
case RCNT1_COUNT: ret = (u8)rcntRcount(1); break;
|
||||
case RCNT1_MODE: ret = (u8)counters[1].modeval; break;
|
||||
case RCNT1_TARGET: ret = (u8)counters[1].target; break;
|
||||
case RCNT1_HOLD: ret = (u8)counters[1].hold; break;
|
||||
case RCNT1_COUNT + 1: ret = (u8)(rcntRcount(1)>>8); break;
|
||||
case RCNT1_MODE + 1: ret = (u8)(counters[1].modeval>>8); break;
|
||||
case RCNT1_TARGET + 1: ret = (u8)(counters[1].target>>8); break;
|
||||
case RCNT1_HOLD + 1: ret = (u8)(counters[1].hold>>8); break;
|
||||
|
||||
case RCNT2_COUNT: ret = (u8)rcntRcount(2); break;
|
||||
case RCNT2_MODE: ret = (u8)counters[2].modeval; break;
|
||||
case RCNT2_TARGET: ret = (u8)counters[2].target; break;
|
||||
case RCNT2_COUNT + 1: ret = (u8)(rcntRcount(2)>>8); break;
|
||||
case RCNT2_MODE + 1: ret = (u8)(counters[2].modeval>>8); break;
|
||||
case RCNT2_TARGET + 1: ret = (u8)(counters[2].target>>8); break;
|
||||
|
||||
case RCNT3_COUNT: ret = (u8)rcntRcount(3); break;
|
||||
case RCNT3_MODE: ret = (u8)counters[3].modeval; break;
|
||||
case RCNT3_TARGET: ret = (u8)counters[3].target; break;
|
||||
case RCNT3_COUNT + 1: ret = (u8)(rcntRcount(3)>>8); break;
|
||||
case RCNT3_MODE + 1: ret = (u8)(counters[3].modeval>>8); break;
|
||||
case RCNT3_TARGET + 1: ret = (u8)(counters[3].target>>8); break;
|
||||
|
||||
default:
|
||||
if ((mem & 0xffffff0f) == SBUS_F200)
|
||||
{
|
||||
switch (mem)
|
||||
{
|
||||
case SBUS_F240:
|
||||
ret = psHu32(mem);
|
||||
//psHu32(mem) &= ~0x4000;
|
||||
break;
|
||||
|
||||
case SBUS_F260:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = psHu32(mem);
|
||||
break;
|
||||
}
|
||||
return (u8)ret;
|
||||
}
|
||||
|
||||
ret = psHu8(mem);
|
||||
UnknownHW_LOG("Hardware Read 8 from 0x%x = 0x%x", mem, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware READ 16 bit
|
||||
|
||||
__fi mem16_t hwRead16(u32 mem)
|
||||
{
|
||||
u16 ret;
|
||||
const u16 masked_mem = mem & 0xffff;
|
||||
|
||||
// TODO re-implement this warning along with a *complete* logging of all hw activity.
|
||||
// (implementation should be modelled after the iopHWRead/iopHwWrite files)
|
||||
if( mem >= IPU_CMD && mem < D0_CHCR )
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("16 bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu16(mem) );
|
||||
#endif
|
||||
return psHu16(mem);
|
||||
}
|
||||
// Console.Warning("Unexpected hwRead16 from 0x%x", mem);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
switch((mem >> 12) & 0xf)
|
||||
{
|
||||
case 0x03:
|
||||
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read8 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
|
||||
else HW_LOG("GIF Register Read8 at 0x%x, value=0x%x", mem, psHu32(mem) );
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
|
||||
HW_LOG("Hardware Read16 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu16(mem) );
|
||||
ret = psHu16(mem);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (mem)
|
||||
{
|
||||
case RCNT0_COUNT: ret = (u16)rcntRcount(0); break;
|
||||
case RCNT0_MODE: ret = (u16)counters[0].modeval; break;
|
||||
case RCNT0_TARGET: ret = (u16)counters[0].target; break;
|
||||
case RCNT0_HOLD: ret = (u16)counters[0].hold; break;
|
||||
|
||||
case RCNT1_COUNT: ret = (u16)rcntRcount(1); break;
|
||||
case RCNT1_MODE: ret = (u16)counters[1].modeval; break;
|
||||
case RCNT1_TARGET: ret = (u16)counters[1].target; break;
|
||||
case RCNT1_HOLD: ret = (u16)counters[1].hold; break;
|
||||
|
||||
case RCNT2_COUNT: ret = (u16)rcntRcount(2); break;
|
||||
case RCNT2_MODE: ret = (u16)counters[2].modeval; break;
|
||||
case RCNT2_TARGET: ret = (u16)counters[2].target; break;
|
||||
|
||||
case RCNT3_COUNT: ret = (u16)rcntRcount(3); break;
|
||||
case RCNT3_MODE: ret = (u16)counters[3].modeval; break;
|
||||
case RCNT3_TARGET: ret = (u16)counters[3].target; break;
|
||||
|
||||
default:
|
||||
if ((mem & 0xffffff0f) == SBUS_F200)
|
||||
{
|
||||
switch (mem)
|
||||
{
|
||||
case SBUS_F240:
|
||||
ret = psHu16(mem) | 0x0102;
|
||||
psHu32(mem) &= ~0x4000; // not commented out like in bit mode?
|
||||
break;
|
||||
|
||||
case SBUS_F260:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = psHu32(mem);
|
||||
break;
|
||||
}
|
||||
return (u16)ret;
|
||||
}
|
||||
ret = psHu16(mem);
|
||||
UnknownHW_LOG("Hardware Read16 at 0x%x, value= 0x%x", ret, mem);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware READ 32 bit
|
||||
|
||||
// Reads hardware registers for page 0 (counters 0 and 1)
|
||||
mem32_t __fastcall hwRead32_page_00(u32 mem)
|
||||
{
|
||||
mem &= 0xffff;
|
||||
switch( mem )
|
||||
{
|
||||
case 0x00: return (u16)rcntRcount(0);
|
||||
case 0x10: return (u16)counters[0].modeval;
|
||||
case 0x20: return (u16)counters[0].target;
|
||||
case 0x30: return (u16)counters[0].hold;
|
||||
|
||||
case 0x800: return (u16)rcntRcount(1);
|
||||
case 0x810: return (u16)counters[1].modeval;
|
||||
case 0x820: return (u16)counters[1].target;
|
||||
case 0x830: return (u16)counters[1].hold;
|
||||
}
|
||||
|
||||
return *((u32*)&eeHw[mem]);
|
||||
}
|
||||
|
||||
// Reads hardware registers for page 1 (counters 2 and 3)
|
||||
mem32_t __fastcall hwRead32_page_01(u32 mem)
|
||||
{
|
||||
mem &= 0xffff;
|
||||
switch( mem )
|
||||
{
|
||||
case 0x1000: return (u16)rcntRcount(2);
|
||||
case 0x1010: return (u16)counters[2].modeval;
|
||||
case 0x1020: return (u16)counters[2].target;
|
||||
|
||||
case 0x1800: return (u16)rcntRcount(3);
|
||||
case 0x1810: return (u16)counters[3].modeval;
|
||||
case 0x1820: return (u16)counters[3].target;
|
||||
}
|
||||
|
||||
return *((u32*)&eeHw[mem]);
|
||||
}
|
||||
|
||||
// Reads hardware registers for page 15 (0x0F).
|
||||
// This is used internally to produce two inline versions, one with INTC_HACK, and one without.
|
||||
static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack )
|
||||
{
|
||||
// *Performance Warning* This function is called -A-LOT. Be wary when making changes. It
|
||||
// could impact FPS significantly.
|
||||
|
||||
mem &= 0xffff;
|
||||
|
||||
// INTC_STAT shortcut for heavy spinning.
|
||||
// Performance Note: Visual Studio handles this best if we just manually check for it here,
|
||||
// outside the context of the switch statement below. This is likely fixed by PGO also,
|
||||
// but it's an easy enough conditional to account for anyways.
|
||||
|
||||
static const uint ics = INTC_STAT & 0xffff;
|
||||
if( mem == ics ) // INTC_STAT
|
||||
{
|
||||
if( intchack ) IntCHackCheck();
|
||||
return *((u32*)&eeHw[ics]);
|
||||
}
|
||||
|
||||
switch( mem )
|
||||
{
|
||||
case 0xf010:
|
||||
HW_LOG("INTC_MASK Read32, value=0x%x", psHu32(INTC_MASK));
|
||||
break;
|
||||
|
||||
case 0xf130: // SIO_ISR
|
||||
case 0xf260: // SBUS_F260
|
||||
case 0xf410: // 0x1000f410
|
||||
case 0xf430: // MCH_RICM
|
||||
return 0;
|
||||
case 0x0f:
|
||||
{
|
||||
// INTC_STAT shortcut for heavy spinning.
|
||||
// Performance Note: Visual Studio handles this best if we just manually check for it here,
|
||||
// outside the context of the switch statement below. This is likely fixed by PGO also,
|
||||
// but it's an easy enough conditional to account for anyways.
|
||||
|
||||
case 0xf240: // SBUS_F240
|
||||
return psHu32(0xf240) | 0xF0000102;
|
||||
|
||||
case 0xf440: // MCH_DRD
|
||||
if( !((psHu32(0xf430) >> 6) & 0xF) )
|
||||
if (mem == INTC_STAT)
|
||||
{
|
||||
switch ((psHu32(0xf430)>>16) & 0xFFF)
|
||||
{
|
||||
//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
|
||||
if (intcstathack) IntCHackCheck();
|
||||
return psHu32(INTC_STAT);
|
||||
}
|
||||
|
||||
case 0x21://INIT
|
||||
if(rdram_sdevid < rdram_devices)
|
||||
{
|
||||
rdram_sdevid++;
|
||||
return 0x1F;
|
||||
}
|
||||
//if ((mem & 0x1000f200) == 0x1000f200)
|
||||
// Console.Error("SBUS");
|
||||
|
||||
switch( mem )
|
||||
{
|
||||
case SIO_ISR:
|
||||
case SBUS_F260:
|
||||
case 0x1000f410:
|
||||
case MCH_RICM:
|
||||
return 0;
|
||||
|
||||
case 0x23://CNFGA
|
||||
return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5
|
||||
case SBUS_F240:
|
||||
return psHu32(SBUS_F240) | 0xF0000102;
|
||||
|
||||
case 0x24://CNFGB
|
||||
//0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0
|
||||
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
|
||||
case MCH_DRD:
|
||||
if( !((psHu32(MCH_RICM) >> 6) & 0xF) )
|
||||
{
|
||||
switch ((psHu32(MCH_RICM)>>16) & 0xFFF)
|
||||
{
|
||||
//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
|
||||
|
||||
case 0x40://DEVID
|
||||
return psHu32(0xf430) & 0x1F; // =SDEV
|
||||
}
|
||||
case 0x21://INIT
|
||||
if(rdram_sdevid < rdram_devices)
|
||||
{
|
||||
rdram_sdevid++;
|
||||
return 0x1F;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0x23://CNFGA
|
||||
return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5
|
||||
|
||||
case 0x24://CNFGB
|
||||
//0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0
|
||||
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
|
||||
|
||||
case 0x40://DEVID
|
||||
return psHu32(MCH_RICM) & 0x1F; // =SDEV
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return *((u32*)&eeHw[mem]);
|
||||
|
||||
return psHu32(mem);
|
||||
}
|
||||
|
||||
mem32_t __fastcall hwRead32_page_0F(u32 mem)
|
||||
template< uint page >
|
||||
mem32_t __fastcall hwRead32(u32 mem)
|
||||
{
|
||||
return __hwRead32_page_0F( mem, false );
|
||||
mem32_t retval = _hwRead32<page,false>(mem);
|
||||
eeHwTraceLog( mem, retval, true );
|
||||
return retval;
|
||||
}
|
||||
|
||||
mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem)
|
||||
{
|
||||
return __hwRead32_page_0F( mem, true );
|
||||
mem32_t retval = _hwRead32<0x0f,true>(mem);
|
||||
eeHwTraceLog( mem, retval, true );
|
||||
return retval;
|
||||
}
|
||||
|
||||
mem32_t __fastcall hwRead32_page_02(u32 mem)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// hwRead8 / hwRead16 / hwRead64 / hwRead128
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
template< uint page >
|
||||
mem8_t __fastcall _hwRead8(u32 mem)
|
||||
{
|
||||
return ipuRead32( mem );
|
||||
u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
|
||||
return ((u8*)&ret32)[mem & 0x03];
|
||||
}
|
||||
|
||||
// Used for all pages not explicitly specified above.
|
||||
mem32_t __fastcall hwRead32_generic(u32 mem)
|
||||
template< uint page >
|
||||
mem8_t __fastcall hwRead8(u32 mem)
|
||||
{
|
||||
const u16 masked_mem = mem & 0xffff;
|
||||
mem8_t ret8 = _hwRead8<0x0f>(mem);
|
||||
eeHwTraceLog( mem, ret8, true );
|
||||
return ret8;
|
||||
}
|
||||
|
||||
switch( masked_mem>>12 ) // switch out as according to the 4k page of the access.
|
||||
template< uint page >
|
||||
mem16_t __fastcall _hwRead16(u32 mem)
|
||||
{
|
||||
pxAssume( (mem & 0x01) == 0 );
|
||||
|
||||
u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
|
||||
return ((u16*)&ret32)[(mem>>1) & 0x01];
|
||||
}
|
||||
|
||||
template< uint page >
|
||||
mem16_t __fastcall hwRead16(u32 mem)
|
||||
{
|
||||
u16 ret16 = _hwRead16<page>(mem);
|
||||
eeHwTraceLog( mem, ret16, true );
|
||||
return ret16;
|
||||
}
|
||||
|
||||
mem16_t __fastcall hwRead16_page_0F_INTC_HACK(u32 mem)
|
||||
{
|
||||
pxAssume( (mem & 0x01) == 0 );
|
||||
|
||||
u32 ret32 = _hwRead32<0x0f, true>(mem & ~0x03);
|
||||
u16 ret16 = ((u16*)&ret32)[(mem>>1) & 0x01];
|
||||
|
||||
eeHwTraceLog( mem, ret16, "Read" );
|
||||
return ret16;
|
||||
}
|
||||
|
||||
template< uint page >
|
||||
static void _hwRead64(u32 mem, mem64_t* result )
|
||||
{
|
||||
pxAssume( (mem & 0x07) == 0 );
|
||||
|
||||
switch (page)
|
||||
{
|
||||
case 0x03:
|
||||
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read32 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
|
||||
else HW_LOG("GIF Register Read32 at 0x%x, value=0x%x", mem, psHu32(mem) );
|
||||
|
||||
// Fixme: OPH hack. Toggle the flag on each GIF_STAT access. (rama)
|
||||
if (CHECK_OPHFLAGHACK)
|
||||
{
|
||||
if (masked_mem == 0x3020)
|
||||
gifRegs->stat.OPH = !gifRegs->stat.OPH;
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////////
|
||||
// Most of the following case handlers are for developer builds only (logging).
|
||||
// It'll all optimize to ziltch in public release builds.
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
case 0x02:
|
||||
*result = ipuRead64(mem);
|
||||
return;
|
||||
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
{
|
||||
const char* regName = "Unknown";
|
||||
// [Ps2Confirm] Reading from FIFOs using non-128 bit reads is a complete mystery.
|
||||
// No game is known to attempt such a thing (yay!), so probably nothing for us to
|
||||
// worry about. Chances are, though, doing so is "legal" and yields some sort
|
||||
// of reproducible behavior. Candidate for real hardware testing.
|
||||
|
||||
// Current assumption: Reads 128 bits and discards the unused portion.
|
||||
|
||||
switch( mem & 0xf0)
|
||||
{
|
||||
case 0x00: regName = "CHCR"; break;
|
||||
case 0x10: regName = "MADR"; break;
|
||||
case 0x20: regName = "QWC"; break;
|
||||
case 0x30: regName = "TADR"; break;
|
||||
case 0x40: regName = "ASR0"; break;
|
||||
case 0x50: regName = "ASR1"; break;
|
||||
case 0x80: regName = "SADDR"; break;
|
||||
}
|
||||
uint wordpart = (mem >> 3) & 0x1;
|
||||
DevCon.WriteLn( Color_Cyan, "Reading 64-bit FIFO data (%s 64 bits discarded)", wordpart ? "upper" : "lower" );
|
||||
|
||||
HW_LOG("Hardware Read32 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu32(mem) );
|
||||
u128 out128;
|
||||
_hwRead128<page>(mem, &out128);
|
||||
*result = out128._u64[wordpart];
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 0x0e:
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
HW_LOG("DMAC Control Regs addr=0x%x Read32, value=0x%x", mem, psHu32(mem));
|
||||
#else
|
||||
if( mem == DMAC_STAT)
|
||||
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
|
||||
#endif
|
||||
break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
return *((u32*)&eeHw[masked_mem]);
|
||||
*result = _hwRead32<page,false>( mem );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware READ 64 bit
|
||||
|
||||
void __fastcall hwRead64_page_00(u32 mem, mem64_t* result )
|
||||
template< uint page >
|
||||
void __fastcall hwRead64(u32 mem, mem64_t* result )
|
||||
{
|
||||
*result = hwRead32_page_00( mem );
|
||||
_hwRead64<page>( mem, result );
|
||||
eeHwTraceLog( mem, *result, true );
|
||||
}
|
||||
|
||||
void __fastcall hwRead64_page_01(u32 mem, mem64_t* result )
|
||||
template< uint page >
|
||||
void __fastcall _hwRead128(u32 mem, mem128_t* result )
|
||||
{
|
||||
*result = hwRead32_page_01( mem );
|
||||
pxAssume( (mem & 0x0f) == 0 );
|
||||
|
||||
// FIFOs are the only "legal" 128 bit registers, so we Handle them first.
|
||||
// All other registers fall back on the 64-bit handler (and from there
|
||||
// all non-IPU reads fall back to the 32-bit handler).
|
||||
|
||||
switch (page)
|
||||
{
|
||||
case 0x05:
|
||||
ReadFIFO_VIF1( result );
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
if (mem & 0x10)
|
||||
ZeroQWC( result ); // IPUin is write-only
|
||||
else
|
||||
ReadFIFO_IPUout( result );
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
// VIF0 and GIF are write-only.
|
||||
// [Ps2Confirm] Reads from these FIFOs (and IPUin) do one of the following:
|
||||
// return zero, leave contents of the dest register unchanged, or in some
|
||||
// indeterminate state. The actual behavior probably isn't important.
|
||||
ZeroQWC( result );
|
||||
break;
|
||||
|
||||
default:
|
||||
_hwRead64<page>( mem, &result->lo );
|
||||
result->hi = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall hwRead64_page_02(u32 mem, mem64_t* result )
|
||||
template< uint page >
|
||||
void __fastcall hwRead128(u32 mem, mem128_t* result )
|
||||
{
|
||||
*result = ipuRead64(mem);
|
||||
_hwRead128<page>( mem, result );
|
||||
eeHwTraceLog( mem, *result, true );
|
||||
}
|
||||
|
||||
void __fastcall hwRead64_generic_INTC_HACK(u32 mem, mem64_t* result )
|
||||
{
|
||||
if (mem == INTC_STAT) IntCHackCheck();
|
||||
#define InstantizeHwRead(pageidx) \
|
||||
template mem8_t __fastcall hwRead8<pageidx>(u32 mem); \
|
||||
template mem16_t __fastcall hwRead16<pageidx>(u32 mem); \
|
||||
template mem32_t __fastcall hwRead32<pageidx>(u32 mem); \
|
||||
template void __fastcall hwRead64<pageidx>(u32 mem, mem64_t* result ); \
|
||||
template void __fastcall hwRead128<pageidx>(u32 mem, mem128_t* result );
|
||||
|
||||
*result = psHu64(mem);
|
||||
UnknownHW_LOG("Hardware Read 64 at %x",mem);
|
||||
}
|
||||
|
||||
void __fastcall hwRead64_generic(u32 mem, mem64_t* result )
|
||||
{
|
||||
*result = psHu64(mem);
|
||||
UnknownHW_LOG("Hardware Read 64 at %x",mem);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Hardware READ 128 bit
|
||||
|
||||
void __fastcall hwRead128_page_00(u32 mem, mem128_t* result )
|
||||
{
|
||||
result->lo = hwRead32_page_00( mem );
|
||||
result->hi = 0;
|
||||
}
|
||||
|
||||
void __fastcall hwRead128_page_01(u32 mem, mem128_t* result )
|
||||
{
|
||||
result->lo = hwRead32_page_01( mem );
|
||||
result->hi = 0;
|
||||
}
|
||||
|
||||
void __fastcall hwRead128_page_02(u32 mem, mem128_t* result )
|
||||
{
|
||||
// IPU is currently unhandled in 128 bit mode.
|
||||
HW_LOG("Hardware Read 128 at %x (IPU)",mem);
|
||||
}
|
||||
|
||||
void __fastcall hwRead128_generic(u32 mem, mem128_t* out)
|
||||
{
|
||||
CopyQWC(out, &psHu128(mem));
|
||||
UnknownHW_LOG("Hardware Read 128 at %x",mem);
|
||||
}
|
||||
InstantizeHwRead(0x00); InstantizeHwRead(0x08);
|
||||
InstantizeHwRead(0x01); InstantizeHwRead(0x09);
|
||||
InstantizeHwRead(0x02); InstantizeHwRead(0x0a);
|
||||
InstantizeHwRead(0x03); InstantizeHwRead(0x0b);
|
||||
InstantizeHwRead(0x04); InstantizeHwRead(0x0c);
|
||||
InstantizeHwRead(0x05); InstantizeHwRead(0x0d);
|
||||
InstantizeHwRead(0x06); InstantizeHwRead(0x0e);
|
||||
InstantizeHwRead(0x07); InstantizeHwRead(0x0f);
|
||||
|
|
1492
pcsx2/HwWrite.cpp
1492
pcsx2/HwWrite.cpp
File diff suppressed because it is too large
Load Diff
|
@ -13,12 +13,6 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// PCH Warning! This file, when compiled with PCH + Optimizations, fails in very curious
|
||||
// and unexpected ways (most obvious is a freeze in the middle of the New Game video of
|
||||
// Final Fantasy XII). So make sure to force-disable PCH for this file at ALL times.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
|
||||
|
@ -307,7 +301,7 @@ void ipuSoftReset()
|
|||
//g_BP.bufferhasnew = 0;
|
||||
}
|
||||
|
||||
__fi void ipuWrite32(u32 mem, u32 value)
|
||||
__fi bool ipuWrite32(u32 mem, u32 value)
|
||||
{
|
||||
// Note: It's assumed that mem's input value is always in the 0x10002000 page
|
||||
// of memory (if not, it's probably bad code).
|
||||
|
@ -322,7 +316,7 @@ __fi void ipuWrite32(u32 mem, u32 value)
|
|||
ipucase(IPU_CMD): // IPU_CMD
|
||||
IPU_LOG("write32: IPU_CMD=0x%08X", value);
|
||||
IPUCMD_WRITE(value);
|
||||
break;
|
||||
return false;
|
||||
|
||||
ipucase(IPU_CTRL): // IPU_CTRL
|
||||
// CTRL = the first 16 bits of ctrl [0x8000ffff], + value for the next 16 bits,
|
||||
|
@ -337,16 +331,14 @@ __fi void ipuWrite32(u32 mem, u32 value)
|
|||
if (ipuRegs->ctrl.RST) ipuSoftReset(); // RESET
|
||||
|
||||
IPU_LOG("write32: IPU_CTRL=0x%08X", value);
|
||||
break;
|
||||
|
||||
default:
|
||||
IPU_LOG("write32: Unknown=%x", mem);
|
||||
*(u32*)((u8*)ipuRegs + mem) = value;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__fi void ipuWrite64(u32 mem, u64 value)
|
||||
// returns FALSE when the writeback is handled, TRUE if the caller should do the
|
||||
// writeback itself.
|
||||
__fi bool ipuWrite64(u32 mem, u64 value)
|
||||
{
|
||||
// Note: It's assumed that mem's input value is always in the 0x10002000 page
|
||||
// of memory (if not, it's probably bad code).
|
||||
|
@ -361,13 +353,10 @@ __fi void ipuWrite64(u32 mem, u64 value)
|
|||
ipucase(IPU_CMD):
|
||||
IPU_LOG("write64: IPU_CMD=0x%08X", value);
|
||||
IPUCMD_WRITE((u32)value);
|
||||
break;
|
||||
|
||||
default:
|
||||
IPU_LOG("write64: Unknown=%x", mem);
|
||||
*(u64*)((u8*)ipuRegs + mem) = value;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1309,7 +1298,7 @@ static __fi int IPU1chain() {
|
|||
// //Wait for all GS paths to be clear
|
||||
// if (GSTransferStatus._u32 != 0x2a)
|
||||
// {
|
||||
// if(GSTransferStatus.PTH3 != STOPPED_MODE && vif1Regs->mskpath3) return true;
|
||||
// if(GSTransferStatus.PTH3 != STOPPED_MODE && vif1Regs.mskpath3) return true;
|
||||
// IPU_LOG("Waiting for GS transfers to finish %x", GSTransferStatus._u32);
|
||||
// IPU_INT_TO(4);
|
||||
// return false;
|
||||
|
@ -1492,10 +1481,10 @@ int IPU0dma()
|
|||
|
||||
if (ipu0dma->qwc == 0)
|
||||
{
|
||||
if (dmacRegs->ctrl.STS == STS_fromIPU) // STS == fromIPU
|
||||
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU
|
||||
{
|
||||
dmacRegs->stadr.ADDR = ipu0dma->madr;
|
||||
switch (dmacRegs->ctrl.STD)
|
||||
dmacRegs.stadr.ADDR = ipu0dma->madr;
|
||||
switch (dmacRegs.ctrl.STD)
|
||||
{
|
||||
case NO_STD:
|
||||
break;
|
||||
|
@ -1624,7 +1613,7 @@ void ipu0Interrupt()
|
|||
// vif
|
||||
Console.Warning("IPU VIF Stall");
|
||||
g_nDMATransfer.VIFSTALL = false;
|
||||
//if (vif1ch->chcr.STR) dmaVIF1();
|
||||
//if (vif1ch.chcr.STR) dmaVIF1();
|
||||
}
|
||||
|
||||
if (g_nDMATransfer.SIFSTALL)
|
||||
|
|
|
@ -284,8 +284,8 @@ extern bool ipuCanFreeze();
|
|||
|
||||
extern u32 ipuRead32(u32 mem);
|
||||
extern u64 ipuRead64(u32 mem);
|
||||
extern void ipuWrite32(u32 mem,u32 value);
|
||||
extern void ipuWrite64(u32 mem,u64 value);
|
||||
extern bool ipuWrite32(u32 mem,u32 value);
|
||||
extern bool ipuWrite64(u32 mem,u64 value);
|
||||
|
||||
extern void IPUCMD_WRITE(u32 val);
|
||||
extern void ipuSoftReset();
|
||||
|
|
|
@ -170,29 +170,47 @@ void IPU_Fifo_Output::readsingle(void *value)
|
|||
|
||||
__fi bool decoder_t::ReadIpuData(u128* out)
|
||||
{
|
||||
if(decoder.ipu0_data == 0) return false;
|
||||
_mm_store_ps((float*)out, _mm_load_ps((float*)GetIpuDataPtr()));
|
||||
if(ipu0_data == 0)
|
||||
{
|
||||
IPU_LOG( "ReadFIFO/IPUout -> (fifo empty/no data available)" );
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyQWC(out, GetIpuDataPtr());
|
||||
|
||||
--ipu0_data;
|
||||
++ipu0_idx;
|
||||
|
||||
IPU_LOG( "ReadFIFO/IPUout -> %ls", out->ToString().c_str() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void __fastcall ReadFIFO_page_7(u32 mem, mem128_t* out)
|
||||
void __fastcall ReadFIFO_IPUout(mem128_t* out)
|
||||
{
|
||||
pxAssert( (mem >= IPUout_FIFO) && (mem < D0_CHCR) );
|
||||
// FIXME! When ReadIpuData() doesn't succeed (returns false), the EE should probably stall
|
||||
// until a value becomes available. This isn't exactly easy to do since the virtualized EE
|
||||
// in PCSX2 *has* to be running in order for the IPU DMA to upload new input data to allow
|
||||
// IPUout's FIFO to fill. Thus if we implement an EE stall, PCSX2 deadlocks. Grr. --air
|
||||
|
||||
// All addresses in this page map to 0x7000 and 0x7010:
|
||||
mem &= 0x10;
|
||||
|
||||
if (mem == 0) // IPUout_FIFO
|
||||
if (decoder.ReadIpuData(out))
|
||||
{
|
||||
if (decoder.ReadIpuData(out))
|
||||
{
|
||||
ipu_fifo.out.readpos = (ipu_fifo.out.readpos + 4) & 31;
|
||||
}
|
||||
ipu_fifo.out.readpos = (ipu_fifo.out.readpos + 4) & 31;
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall WriteFIFO_IPUin(const mem128_t* value)
|
||||
{
|
||||
IPU_LOG( "WriteFIFO/IPUin <- %ls", value->ToString().c_str() );
|
||||
|
||||
//committing every 16 bytes
|
||||
while( ipu_fifo.in.write((u32*)value, 1) == 0 )
|
||||
{
|
||||
// Legacy code from an older thread-based IPU. Current IPU is fixed to always
|
||||
// return non-zero from the above write function; but we'll leave this in place
|
||||
// for now in case we change our minds (again) and re-add threading. --air
|
||||
|
||||
Console.WriteLn("IPU sleeping");
|
||||
Threading::Timeslice();
|
||||
}
|
||||
else // IPUin_FIFO
|
||||
ipu_fifo.out.readsingle((void*)out);
|
||||
}
|
||||
|
|
|
@ -522,9 +522,11 @@
|
|||
<Unit filename="../ps2/BiosTools.cpp" />
|
||||
<Unit filename="../ps2/BiosTools.h" />
|
||||
<Unit filename="../ps2/GIFpath.cpp" />
|
||||
<Unit filename="../ps2/LegacyDmac.cpp" />
|
||||
<Unit filename="../ps2/Iop/IopHwRead.cpp" />
|
||||
<Unit filename="../ps2/Iop/IopHwWrite.cpp" />
|
||||
<Unit filename="../ps2/Iop/IopHw_Internal.h" />
|
||||
<Unit filename="../ps2/LegacyDmac.cpp" />
|
||||
<Unit filename="../vtlb.cpp" />
|
||||
<Unit filename="../vtlb.h" />
|
||||
<Unit filename="../x86/BaseblockEx.cpp" />
|
||||
|
|
121
pcsx2/Memory.cpp
121
pcsx2/Memory.cpp
|
@ -35,15 +35,14 @@ BIOS
|
|||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IopCommon.h"
|
||||
|
||||
#pragma warning(disable:4799) // No EMMS at end of function
|
||||
|
||||
#include <wx/file.h>
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "VUmicro.h"
|
||||
#include "GS.h"
|
||||
#include "System/PageFaultSource.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
#include "ps2/BiosTools.h"
|
||||
|
||||
#ifdef ENABLECACHE
|
||||
|
@ -154,7 +153,6 @@ void memMapPhy()
|
|||
vtlb_MapBlock(psxM,0x1c000000,0x00800000);
|
||||
|
||||
// Generic Handlers; These fallback to mem* stuff...
|
||||
vtlb_MapHandler(tlb_fallback_1,0x10000000,0x10000);
|
||||
vtlb_MapHandler(tlb_fallback_7,0x14000000,0x10000);
|
||||
vtlb_MapHandler(tlb_fallback_4,0x18000000,0x10000);
|
||||
vtlb_MapHandler(tlb_fallback_5,0x1a000000,0x10000);
|
||||
|
@ -166,17 +164,9 @@ void memMapPhy()
|
|||
|
||||
// Hardware Register Handlers : specialized/optimized per-page handling of HW register accesses
|
||||
// (note that hw_by_page handles are assigned in memReset prior to calling this function)
|
||||
vtlb_MapHandler(hw_by_page[0x0], 0x10000000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x1], 0x10001000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x2], 0x10002000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x3], 0x10003000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x4], 0x10004000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x5], 0x10005000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x6], 0x10006000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0x7], 0x10007000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0xb], 0x1000b000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0xe], 0x1000e000, 0x01000);
|
||||
vtlb_MapHandler(hw_by_page[0xf], 0x1000f000, 0x01000);
|
||||
|
||||
for( uint i=0; i<16; ++i)
|
||||
vtlb_MapHandler(hw_by_page[i], 0x10000000 + (0x01000 * i), 0x01000);
|
||||
|
||||
vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000);
|
||||
vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000);
|
||||
|
@ -256,8 +246,6 @@ static mem8_t __fastcall _ext_memRead8 (u32 mem)
|
|||
{
|
||||
switch (p)
|
||||
{
|
||||
case 1: // hwm
|
||||
return hwRead8(mem);
|
||||
case 3: // psh4
|
||||
return psxHw4Read8(mem);
|
||||
case 6: // gsm
|
||||
|
@ -280,8 +268,6 @@ static mem16_t __fastcall _ext_memRead16(u32 mem)
|
|||
{
|
||||
switch (p)
|
||||
{
|
||||
case 1: // hwm
|
||||
return hwRead16(mem);
|
||||
case 4: // b80
|
||||
MEM_LOG("b800000 Memory read16 address %x", mem);
|
||||
return 0;
|
||||
|
@ -358,9 +344,6 @@ template<int p>
|
|||
static void __fastcall _ext_memWrite8 (u32 mem, mem8_t value)
|
||||
{
|
||||
switch (p) {
|
||||
case 1: // hwm
|
||||
hwWrite8(mem, value);
|
||||
return;
|
||||
case 3: // psh4
|
||||
psxHw4Write8(mem, value); return;
|
||||
case 6: // gsm
|
||||
|
@ -379,9 +362,6 @@ template<int p>
|
|||
static void __fastcall _ext_memWrite16(u32 mem, mem16_t value)
|
||||
{
|
||||
switch (p) {
|
||||
case 1: // hwm
|
||||
hwWrite16(mem, value);
|
||||
return;
|
||||
case 5: // ba0
|
||||
MEM_LOG("ba00000 Memory write16 to address %x with data %x", mem, value);
|
||||
return;
|
||||
|
@ -632,12 +612,13 @@ void memBindConditionalHandlers()
|
|||
{
|
||||
if( hw_by_page[0xf] == -1 ) return;
|
||||
|
||||
vtlbMemR32FP* page0F32( EmuConfig.Speedhacks.IntcStat ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F );
|
||||
vtlbMemR64FP* page0F64( EmuConfig.Speedhacks.IntcStat ? hwRead64_generic_INTC_HACK : hwRead64_generic );
|
||||
vtlbMemR16FP* page0F16( EmuConfig.Speedhacks.IntcStat ? hwRead16_page_0F_INTC_HACK : hwRead16<0x0f> );
|
||||
vtlbMemR32FP* page0F32( EmuConfig.Speedhacks.IntcStat ? hwRead32_page_0F_INTC_HACK : hwRead32<0x0f> );
|
||||
//vtlbMemR64FP* page0F64( EmuConfig.Speedhacks.IntcStat ? hwRead64_generic_INTC_HACK : hwRead64<0x0f> );
|
||||
|
||||
vtlb_ReassignHandler( hw_by_page[0xf],
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, page0F32, page0F64, hwRead128_generic,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0F, hwWrite64_generic, hwWrite128_generic
|
||||
hwRead8<0x0f>, page0F16, page0F32, hwRead64<0x0f>, hwRead128<0x0f>,
|
||||
hwWrite8<0x0f>, hwWrite16<0x0f>, hwWrite32<0x0f>, hwWrite64<0x0f>, hwWrite128<0x0f>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -666,7 +647,6 @@ void memReset()
|
|||
tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
|
||||
tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);
|
||||
tlb_fallback_5 = vtlb_RegisterHandlerTempl1(_ext_mem,5);
|
||||
//tlb_fallback_6 = vtlb_RegisterHandlerTempl1(_ext_mem,6);
|
||||
tlb_fallback_7 = vtlb_RegisterHandlerTempl1(_ext_mem,7);
|
||||
tlb_fallback_8 = vtlb_RegisterHandlerTempl1(_ext_mem,8);
|
||||
|
||||
|
@ -703,68 +683,29 @@ void memReset()
|
|||
);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// psHw Optimized Mappings
|
||||
// The HW Registers have been split into pages to improve optimization.
|
||||
// Anything not explicitly mapped into one of the hw_by_page handlers will be handled
|
||||
// by the default/generic tlb_fallback_1 handler.
|
||||
|
||||
#define hwHandlerTmpl(page) \
|
||||
hwRead8<page>, hwRead16<page>, hwRead32<page>, hwRead64<page>, hwRead128<page>, \
|
||||
hwWrite8<page>, hwWrite16<page>,hwWrite32<page>,hwWrite64<page>,hwWrite128<page>
|
||||
|
||||
tlb_fallback_1 = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0x0] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_00, hwRead64_page_00, hwRead128_page_00,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_00, hwWrite64_page_00, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0x1] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_01, hwRead64_page_01, hwRead128_page_01,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_01, hwWrite64_page_01, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0x2] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_02, hwRead64_page_02, hwRead128_page_02,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_02, hwWrite64_page_02, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0x3] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_03, hwWrite64_page_03, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0x4] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_4,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_4
|
||||
);
|
||||
|
||||
hw_by_page[0x5] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_5,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_5
|
||||
);
|
||||
|
||||
hw_by_page[0x6] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_6,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_6
|
||||
);
|
||||
|
||||
hw_by_page[0x7] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_7,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_7
|
||||
);
|
||||
|
||||
hw_by_page[0xb] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0B, hwWrite64_generic, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0xe] = vtlb_RegisterHandler(
|
||||
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
|
||||
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic
|
||||
);
|
||||
|
||||
hw_by_page[0xf] = vtlb_NewHandler();
|
||||
hw_by_page[0x0] = vtlb_RegisterHandler( hwHandlerTmpl(0x00) );
|
||||
hw_by_page[0x1] = vtlb_RegisterHandler( hwHandlerTmpl(0x01) );
|
||||
hw_by_page[0x2] = vtlb_RegisterHandler( hwHandlerTmpl(0x02) );
|
||||
hw_by_page[0x3] = vtlb_RegisterHandler( hwHandlerTmpl(0x03) );
|
||||
hw_by_page[0x4] = vtlb_RegisterHandler( hwHandlerTmpl(0x04) );
|
||||
hw_by_page[0x5] = vtlb_RegisterHandler( hwHandlerTmpl(0x05) );
|
||||
hw_by_page[0x6] = vtlb_RegisterHandler( hwHandlerTmpl(0x06) );
|
||||
hw_by_page[0x7] = vtlb_RegisterHandler( hwHandlerTmpl(0x07) );
|
||||
hw_by_page[0x8] = vtlb_RegisterHandler( hwHandlerTmpl(0x08) );
|
||||
hw_by_page[0x9] = vtlb_RegisterHandler( hwHandlerTmpl(0x09) );
|
||||
hw_by_page[0xa] = vtlb_RegisterHandler( hwHandlerTmpl(0x0a) );
|
||||
hw_by_page[0xb] = vtlb_RegisterHandler( hwHandlerTmpl(0x0b) );
|
||||
hw_by_page[0xc] = vtlb_RegisterHandler( hwHandlerTmpl(0x0c) );
|
||||
hw_by_page[0xd] = vtlb_RegisterHandler( hwHandlerTmpl(0x0d) );
|
||||
hw_by_page[0xe] = vtlb_RegisterHandler( hwHandlerTmpl(0x0e) );
|
||||
hw_by_page[0xf] = vtlb_NewHandler(); // redefined later based on speedhacking prefs
|
||||
memBindConditionalHandlers();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -34,15 +34,12 @@ static __fi void ZeroQWC( void* dest )
|
|||
_mm_store_ps( (float*)dest, _mm_setzero_ps() );
|
||||
}
|
||||
|
||||
static __fi void ZeroQWC( u128& dest )
|
||||
{
|
||||
_mm_store_ps( (float*)&dest, _mm_setzero_ps() );
|
||||
}
|
||||
|
||||
// Various useful locations
|
||||
#define spr0 ((DMACh*)&eeHw[0xD000])
|
||||
#define spr1 ((DMACh*)&eeHw[0xD400])
|
||||
|
||||
#define gif ((DMACh*)&eeHw[0xA000])
|
||||
|
||||
#define vif0ch ((DMACh*)&eeHw[0x8000])
|
||||
#define vif1ch ((DMACh*)&eeHw[0x9000])
|
||||
|
||||
#define sif0dma ((DMACh*)&eeHw[0xc000])
|
||||
#define sif1dma ((DMACh*)&eeHw[0xc400])
|
||||
#define sif2dma ((DMACh*)&eeHw[0xc800])
|
||||
|
|
|
@ -289,7 +289,7 @@ static __fi void TESTINT( u8 n, void (*callback)() )
|
|||
|
||||
static __fi void _cpuTestInterrupts()
|
||||
{
|
||||
if (!dmacRegs->ctrl.DMAE || psHu8(DMAC_ENABLER+2) == 1)
|
||||
if (!dmacRegs.ctrl.DMAE || psHu8(DMAC_ENABLER+2) == 1)
|
||||
{
|
||||
//Console.Write("DMAC Disabled or suspended");
|
||||
return;
|
||||
|
|
180
pcsx2/SPR.cpp
180
pcsx2/SPR.cpp
|
@ -51,96 +51,96 @@ int _SPR0chain()
|
|||
{
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
if (spr0->qwc == 0) return 0;
|
||||
pMem = SPRdmaGetAddr(spr0->madr, true);
|
||||
if (spr0ch.qwc == 0) return 0;
|
||||
pMem = SPRdmaGetAddr(spr0ch.madr, true);
|
||||
if (pMem == NULL) return -1;
|
||||
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
switch (dmacRegs.ctrl.MFD)
|
||||
{
|
||||
case MFD_VIF1:
|
||||
case MFD_GIF:
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR)
|
||||
if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
|
||||
Console.WriteLn("SPR MFIFO Write outside MFIFO area");
|
||||
else
|
||||
mfifotransferred += spr0->qwc;
|
||||
mfifotransferred += spr0ch.qwc;
|
||||
|
||||
hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc);
|
||||
spr0->madr += spr0->qwc << 4;
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
|
||||
spr0ch.madr += spr0ch.qwc << 4;
|
||||
spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc);
|
||||
memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
|
||||
|
||||
// clear VU mem also!
|
||||
TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
|
||||
spr0->madr += spr0->qwc << 4;
|
||||
TestClearVUs(spr0ch.madr, spr0ch.qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
|
||||
spr0ch.madr += spr0ch.qwc << 4;
|
||||
break;
|
||||
}
|
||||
|
||||
spr0->sadr += spr0->qwc << 4;
|
||||
spr0ch.sadr += spr0ch.qwc << 4;
|
||||
|
||||
return (spr0->qwc); // bus is 1/2 the ee speed
|
||||
return (spr0ch.qwc); // bus is 1/2 the ee speed
|
||||
}
|
||||
|
||||
__fi void SPR0chain()
|
||||
{
|
||||
CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS);
|
||||
spr0->qwc = 0;
|
||||
spr0ch.qwc = 0;
|
||||
}
|
||||
|
||||
void _SPR0interleave()
|
||||
{
|
||||
int qwc = spr0->qwc;
|
||||
int sqwc = dmacRegs->sqwc.SQWC;
|
||||
int tqwc = dmacRegs->sqwc.TQWC;
|
||||
int qwc = spr0ch.qwc;
|
||||
int sqwc = dmacRegs.sqwc.SQWC;
|
||||
int tqwc = dmacRegs.sqwc.TQWC;
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
if (tqwc == 0) tqwc = qwc;
|
||||
//Console.WriteLn("dmaSPR0 interleave");
|
||||
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
|
||||
spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr);
|
||||
spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);
|
||||
|
||||
CPU_INT(DMAC_FROM_SPR, qwc / BIAS);
|
||||
|
||||
while (qwc > 0)
|
||||
{
|
||||
spr0->qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr0->qwc;
|
||||
pMem = SPRdmaGetAddr(spr0->madr, true);
|
||||
spr0ch.qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr0ch.qwc;
|
||||
pMem = SPRdmaGetAddr(spr0ch.madr, true);
|
||||
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
switch (dmacRegs.ctrl.MFD)
|
||||
{
|
||||
case MFD_VIF1:
|
||||
case MFD_GIF:
|
||||
hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc);
|
||||
mfifotransferred += spr0->qwc;
|
||||
hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
|
||||
mfifotransferred += spr0ch.qwc;
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
// clear VU mem also!
|
||||
TestClearVUs(spr0->madr, spr0->qwc << 2);
|
||||
memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc);
|
||||
TestClearVUs(spr0ch.madr, spr0ch.qwc << 2);
|
||||
memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
|
||||
break;
|
||||
}
|
||||
spr0->sadr += spr0->qwc * 16;
|
||||
spr0->madr += (sqwc + spr0->qwc) * 16;
|
||||
spr0ch.sadr += spr0ch.qwc * 16;
|
||||
spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
|
||||
}
|
||||
|
||||
spr0->qwc = 0;
|
||||
spr0ch.qwc = 0;
|
||||
}
|
||||
|
||||
static __fi void _dmaSPR0()
|
||||
{
|
||||
if (dmacRegs->ctrl.STS == STS_fromSPR)
|
||||
if (dmacRegs.ctrl.STS == STS_fromSPR)
|
||||
{
|
||||
Console.WriteLn("SPR0 stall %d", dmacRegs->ctrl.STS);
|
||||
Console.WriteLn("SPR0 stall %d", dmacRegs.ctrl.STS);
|
||||
}
|
||||
|
||||
// Transfer Dn_QWC from SPR to Dn_MADR
|
||||
switch(spr0->chcr.MOD)
|
||||
switch(spr0ch.chcr.MOD)
|
||||
{
|
||||
case NORMAL_MODE:
|
||||
{
|
||||
|
@ -153,23 +153,23 @@ static __fi void _dmaSPR0()
|
|||
tDMA_TAG *ptag;
|
||||
bool done = false;
|
||||
|
||||
if (spr0->qwc > 0)
|
||||
if (spr0ch.qwc > 0)
|
||||
{
|
||||
SPR0chain();
|
||||
return;
|
||||
}
|
||||
// Destination Chain Mode
|
||||
ptag = (tDMA_TAG*)&psSu32(spr0->sadr);
|
||||
spr0->sadr += 16;
|
||||
ptag = (tDMA_TAG*)&psSu32(spr0ch.sadr);
|
||||
spr0ch.sadr += 16;
|
||||
|
||||
spr0->unsafeTransfer(ptag);
|
||||
spr0ch.unsafeTransfer(ptag);
|
||||
|
||||
spr0->madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
spr0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
|
||||
SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr, spr0->sadr);
|
||||
ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr, spr0ch.sadr);
|
||||
|
||||
if (dmacRegs->ctrl.STS == STS_fromSPR) // STS == fromSPR
|
||||
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
|
||||
{
|
||||
Console.WriteLn("SPR stall control");
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ static __fi void _dmaSPR0()
|
|||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control)
|
||||
if (dmacRegs->ctrl.STS == STS_fromSPR) dmacRegs->stadr.ADDR = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register
|
||||
if (dmacRegs.ctrl.STS == STS_fromSPR) dmacRegs.stadr.ADDR = spr0ch.madr + (spr0ch.qwc * 16); //Copy MADR to DMAC_STADR stall addr register
|
||||
break;
|
||||
|
||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||
|
@ -191,7 +191,7 @@ static __fi void _dmaSPR0()
|
|||
|
||||
SPR0chain();
|
||||
|
||||
if (spr0->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (spr0ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
|
||||
{
|
||||
//Console.WriteLn("SPR0 TIE");
|
||||
done = true;
|
||||
|
@ -199,7 +199,7 @@ static __fi void _dmaSPR0()
|
|||
|
||||
spr0finished = done;
|
||||
SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr);
|
||||
ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr);
|
||||
break;
|
||||
}
|
||||
//case INTERLEAVE_MODE:
|
||||
|
@ -215,27 +215,27 @@ static __fi void _dmaSPR0()
|
|||
void SPRFROMinterrupt()
|
||||
{
|
||||
|
||||
if (!spr0finished || spr0->qwc > 0)
|
||||
if (!spr0finished || spr0ch.qwc > 0)
|
||||
{
|
||||
_dmaSPR0();
|
||||
|
||||
if(mfifotransferred != 0)
|
||||
{
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
switch (dmacRegs.ctrl.MFD)
|
||||
{
|
||||
case MFD_VIF1: // Most common case.
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr);
|
||||
if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
|
||||
spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr);
|
||||
mfifoVIF1transfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
break;
|
||||
}
|
||||
case MFD_GIF:
|
||||
{
|
||||
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
|
||||
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK);
|
||||
if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
|
||||
spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
mfifoGIFtransfer(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
|
@ -249,22 +249,22 @@ void SPRFROMinterrupt()
|
|||
}
|
||||
|
||||
|
||||
spr0->chcr.STR = false;
|
||||
spr0ch.chcr.STR = false;
|
||||
hwDmacIrq(DMAC_FROM_SPR);
|
||||
}
|
||||
|
||||
void dmaSPR0() // fromSPR
|
||||
{
|
||||
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
|
||||
spr0->chcr._u32, spr0->madr, spr0->qwc, spr0->sadr);
|
||||
spr0ch.chcr._u32, spr0ch.madr, spr0ch.qwc, spr0ch.sadr);
|
||||
|
||||
|
||||
spr0finished = false; //Init
|
||||
|
||||
if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0)
|
||||
if(spr0ch.chcr.MOD == CHAIN_MODE && spr0ch.qwc > 0)
|
||||
{
|
||||
//DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc());
|
||||
if (spr0->chcr.tag().ID == TAG_END) // but not TAG_REFE?
|
||||
//DevCon.Warning(L"SPR0 QWC on Chain " + spr0ch.chcr.desc());
|
||||
if (spr0ch.chcr.tag().ID == TAG_END) // but not TAG_REFE?
|
||||
{
|
||||
spr0finished = true;
|
||||
}
|
||||
|
@ -275,58 +275,58 @@ void dmaSPR0() // fromSPR
|
|||
|
||||
__fi static void SPR1transfer(const void* data, int qwc)
|
||||
{
|
||||
memcpy_qwc(&psSu128(spr1->sadr), data, qwc);
|
||||
spr1->sadr += qwc * 16;
|
||||
memcpy_qwc(&psSu128(spr1ch.sadr), data, qwc);
|
||||
spr1ch.sadr += qwc * 16;
|
||||
}
|
||||
|
||||
int _SPR1chain()
|
||||
{
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
if (spr1->qwc == 0) return 0;
|
||||
if (spr1ch.qwc == 0) return 0;
|
||||
|
||||
pMem = SPRdmaGetAddr(spr1->madr, false);
|
||||
pMem = SPRdmaGetAddr(spr1ch.madr, false);
|
||||
if (pMem == NULL) return -1;
|
||||
|
||||
SPR1transfer(pMem, spr1->qwc);
|
||||
spr1->madr += spr1->qwc * 16;
|
||||
SPR1transfer(pMem, spr1ch.qwc);
|
||||
spr1ch.madr += spr1ch.qwc * 16;
|
||||
|
||||
return (spr1->qwc);
|
||||
return (spr1ch.qwc);
|
||||
}
|
||||
|
||||
__fi void SPR1chain()
|
||||
{
|
||||
CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS);
|
||||
spr1->qwc = 0;
|
||||
spr1ch.qwc = 0;
|
||||
}
|
||||
|
||||
void _SPR1interleave()
|
||||
{
|
||||
int qwc = spr1->qwc;
|
||||
int sqwc = dmacRegs->sqwc.SQWC;
|
||||
int tqwc = dmacRegs->sqwc.TQWC;
|
||||
int qwc = spr1ch.qwc;
|
||||
int sqwc = dmacRegs.sqwc.SQWC;
|
||||
int tqwc = dmacRegs.sqwc.TQWC;
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
if (tqwc == 0) tqwc = qwc;
|
||||
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
|
||||
spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr);
|
||||
spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
|
||||
CPU_INT(DMAC_TO_SPR, qwc / BIAS);
|
||||
while (qwc > 0)
|
||||
{
|
||||
spr1->qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr1->qwc;
|
||||
pMem = SPRdmaGetAddr(spr1->madr, false);
|
||||
memcpy_qwc(&psSu128(spr1->sadr), pMem, spr1->qwc);
|
||||
spr1->sadr += spr1->qwc * 16;
|
||||
spr1->madr += (sqwc + spr1->qwc) * 16;
|
||||
spr1ch.qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr1ch.qwc;
|
||||
pMem = SPRdmaGetAddr(spr1ch.madr, false);
|
||||
memcpy_qwc(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc);
|
||||
spr1ch.sadr += spr1ch.qwc * 16;
|
||||
spr1ch.madr += (sqwc + spr1ch.qwc) * 16;
|
||||
}
|
||||
|
||||
spr1->qwc = 0;
|
||||
spr1ch.qwc = 0;
|
||||
}
|
||||
|
||||
void _dmaSPR1() // toSPR work function
|
||||
{
|
||||
switch(spr1->chcr.MOD)
|
||||
switch(spr1ch.chcr.MOD)
|
||||
{
|
||||
case NORMAL_MODE:
|
||||
{
|
||||
|
@ -341,39 +341,39 @@ void _dmaSPR1() // toSPR work function
|
|||
tDMA_TAG *ptag;
|
||||
bool done = false;
|
||||
|
||||
if (spr1->qwc > 0)
|
||||
if (spr1ch.qwc > 0)
|
||||
{
|
||||
SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1->qwc, spr1->madr, spr1->tadr, spr1->sadr);
|
||||
SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1ch.qwc, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
|
||||
// Transfer Dn_QWC from Dn_MADR to SPR1
|
||||
SPR1chain();
|
||||
return;
|
||||
}
|
||||
// Chain Mode
|
||||
|
||||
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
|
||||
ptag = SPRdmaGetAddr(spr1ch.tadr, false); //Set memory pointer to TADR
|
||||
|
||||
if (!spr1->transfer("SPR1 Tag", ptag))
|
||||
if (!spr1ch.transfer("SPR1 Tag", ptag))
|
||||
{
|
||||
done = true;
|
||||
spr1finished = done;
|
||||
}
|
||||
|
||||
spr1->madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
spr1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
|
||||
// Transfer dma tag if tte is set
|
||||
if (spr1->chcr.TTE)
|
||||
if (spr1ch.chcr.TTE)
|
||||
{
|
||||
SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32);
|
||||
SPR1transfer(ptag, 1); //Transfer Tag
|
||||
}
|
||||
|
||||
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr, spr1->tadr, spr1->sadr);
|
||||
ptag[1]._u32, ptag[0]._u32, spr1ch.qwc, ptag->ID, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
|
||||
|
||||
done = (hwDmacSrcChain(spr1, ptag->ID));
|
||||
done = (hwDmacSrcChain(spr1ch, ptag->ID));
|
||||
SPR1chain(); //Transfers the data set by the switch
|
||||
|
||||
if (spr1->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (spr1ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
|
||||
{
|
||||
SPR_LOG("dmaIrq Set");
|
||||
|
||||
|
@ -398,15 +398,15 @@ void dmaSPR1() // toSPR
|
|||
{
|
||||
SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
|
||||
" tadr = 0x%x, sadr = 0x%x",
|
||||
spr1->chcr._u32, spr1->madr, spr1->qwc,
|
||||
spr1->tadr, spr1->sadr);
|
||||
spr1ch.chcr._u32, spr1ch.madr, spr1ch.qwc,
|
||||
spr1ch.tadr, spr1ch.sadr);
|
||||
|
||||
spr1finished = false; //Init
|
||||
|
||||
if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0)
|
||||
if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0)
|
||||
{
|
||||
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc());
|
||||
if ((spr1->chcr.tag().ID == TAG_END) || (spr1->chcr.tag().ID == TAG_REFE))
|
||||
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc());
|
||||
if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE))
|
||||
{
|
||||
spr1finished = true;
|
||||
}
|
||||
|
@ -418,14 +418,14 @@ void dmaSPR1() // toSPR
|
|||
void SPRTOinterrupt()
|
||||
{
|
||||
SPR_LOG("SPR1 Interrupt");
|
||||
if (!spr1finished || spr1->qwc > 0)
|
||||
if (!spr1finished || spr1ch.qwc > 0)
|
||||
{
|
||||
_dmaSPR1();
|
||||
return;
|
||||
}
|
||||
|
||||
SPR_LOG("SPR1 End");
|
||||
spr1->chcr.STR = false;
|
||||
spr1ch.chcr.STR = false;
|
||||
hwDmacIrq(DMAC_TO_SPR);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,13 +104,13 @@ static __fi bool ProcessEETag()
|
|||
{
|
||||
case TAG_REFE:
|
||||
sif0.ee.end = true;
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
if (dmacRegs.ctrl.STS != NO_STS)
|
||||
dmacRegs.stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_REFS:
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
if (dmacRegs.ctrl.STS != NO_STS)
|
||||
dmacRegs.stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_END:
|
||||
|
@ -185,7 +185,7 @@ static __fi void HandleEETransfer()
|
|||
return;
|
||||
}
|
||||
|
||||
if (dmacRegs->ctrl.STS == STS_SIF0)
|
||||
if (dmacRegs.ctrl.STS == STS_SIF0)
|
||||
{
|
||||
DevCon.Warning("SIF0 stall control");
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ static __fi void HandleEETransfer()
|
|||
sif1.ee.busy = false;
|
||||
return;
|
||||
}
|
||||
if (dmacRegs->ctrl.STD == STD_SIF1)
|
||||
if (dmacRegs.ctrl.STD == STD_SIF1)
|
||||
{
|
||||
DevCon.Warning("SIF1 stall control"); // STD == fromSIF1
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ struct __aligned16 VURegs {
|
|||
|
||||
VIFregisters& GetVifRegs() const
|
||||
{
|
||||
return IsVU1() ? vif1RegsRef : vif0RegsRef;
|
||||
return IsVU1() ? vif1Regs : vif0Regs;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ void vu0ResetRegs()
|
|||
{
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0
|
||||
VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0
|
||||
vif0Regs->stat.VEW = false;
|
||||
vif0Regs.stat.VEW = false;
|
||||
}
|
||||
|
||||
void __fastcall vu0ExecMicro(u32 addr) {
|
||||
|
|
|
@ -155,7 +155,7 @@ static void _vu0Exec(VURegs* VU)
|
|||
if( VU->ebit-- == 1 ) {
|
||||
_vuFlushAll(VU);
|
||||
VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */
|
||||
vif0Regs->stat.VEW = false;
|
||||
vif0Regs.stat.VEW = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ void vu1ResetRegs()
|
|||
{
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1
|
||||
VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1
|
||||
vif1Regs->stat.VEW = false;
|
||||
vif1Regs.stat.VEW = false;
|
||||
}
|
||||
|
||||
void vu1Finish() {
|
||||
|
@ -56,7 +56,7 @@ void __fastcall vu1ExecMicro(u32 addr)
|
|||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
||||
|
||||
vif1Regs->stat.VEW = true;
|
||||
vif1Regs.stat.VEW = true;
|
||||
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
||||
_vuExecMicroDebug(VU1);
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ static void _vu1Exec(VURegs* VU)
|
|||
if( VU->ebit-- == 1 ) {
|
||||
_vuFlushAll(VU);
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0x100;
|
||||
vif1Regs->stat.VEW = false;
|
||||
vif1Regs.stat.VEW = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
166
pcsx2/Vif.cpp
166
pcsx2/Vif.cpp
|
@ -29,13 +29,13 @@ void vif0Reset()
|
|||
{
|
||||
/* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
|
||||
memzero(vif0);
|
||||
memzero(*vif0Regs);
|
||||
memzero(vif0Regs);
|
||||
|
||||
psHu64(VIF0_FIFO) = 0;
|
||||
psHu64(VIF0_FIFO + 8) = 0;
|
||||
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs->stat.FQC = 0;
|
||||
vif0Regs.stat.VPS = VPS_IDLE;
|
||||
vif0Regs.stat.FQC = 0;
|
||||
|
||||
vif0.done = false;
|
||||
|
||||
|
@ -46,13 +46,13 @@ void vif1Reset()
|
|||
{
|
||||
/* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
|
||||
memzero(vif1);
|
||||
memzero(*vif1Regs);
|
||||
memzero(vif1Regs);
|
||||
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs->stat.FQC = 0; // FQC=0
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.FQC = 0; // FQC=0
|
||||
|
||||
vif1.done = false;
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
|
@ -91,16 +91,16 @@ __fi void vif0FBRST(u32 value) {
|
|||
|
||||
if (value & 0x1) // Reset Vif.
|
||||
{
|
||||
//Console.WriteLn("Vif0 Reset %x", vif0Regs->stat._u32);
|
||||
//Console.WriteLn("Vif0 Reset %x", vif0Regs.stat._u32);
|
||||
|
||||
memzero(vif0);
|
||||
vif0ch->qwc = 0; //?
|
||||
vif0ch.qwc = 0; //?
|
||||
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
|
||||
psHu64(VIF0_FIFO) = 0;
|
||||
psHu64(VIF0_FIFO + 8) = 0;
|
||||
vif0.done = false;
|
||||
vif0Regs->err.reset();
|
||||
vif0Regs->stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
|
||||
vif0Regs.err.reset();
|
||||
vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
|
||||
}
|
||||
|
||||
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
|
||||
|
@ -109,8 +109,8 @@ __fi void vif0FBRST(u32 value) {
|
|||
{
|
||||
/* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
|
||||
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
|
||||
vif0Regs->stat.VFS = true;
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs.stat.VFS = true;
|
||||
vif0Regs.stat.VPS = VPS_IDLE;
|
||||
Console.WriteLn("vif0 force break");
|
||||
}
|
||||
|
||||
|
@ -118,8 +118,8 @@ __fi void vif0FBRST(u32 value) {
|
|||
{
|
||||
// Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of
|
||||
// just stoppin the VIF (linuz).
|
||||
vif0Regs->stat.VSS = true;
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs.stat.VSS = true;
|
||||
vif0Regs.stat.VPS = VPS_IDLE;
|
||||
vif0.vifstalled = true;
|
||||
}
|
||||
|
||||
|
@ -128,10 +128,10 @@ __fi void vif0FBRST(u32 value) {
|
|||
bool cancel = false;
|
||||
|
||||
/* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
|
||||
if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||
if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||
cancel = true;
|
||||
|
||||
vif0Regs->stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
|
||||
vif0Regs.stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
|
||||
VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1);
|
||||
if (cancel)
|
||||
{
|
||||
|
@ -140,8 +140,8 @@ __fi void vif0FBRST(u32 value) {
|
|||
g_vifCycles = 0;
|
||||
|
||||
// loop necessary for spiderman
|
||||
//vif0ch->chcr.STR = true;
|
||||
if(vif0ch->chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
//vif0ch.chcr.STR = true;
|
||||
if(vif0ch.chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,29 +154,29 @@ __fi void vif1FBRST(u32 value) {
|
|||
{
|
||||
memzero(vif1);
|
||||
//cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
vif1ch->qwc -= min((int)vif1ch->qwc, 16); //?
|
||||
vif1ch.qwc -= min((int)vif1ch.qwc, 16); //?
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
//vif1.done = false;
|
||||
|
||||
|
||||
//DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs->mskpath3);
|
||||
if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gif->chcr.STR == true)
|
||||
//DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs.mskpath3);
|
||||
if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true)
|
||||
{
|
||||
//DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs->mskpath3);
|
||||
//DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3);
|
||||
gsInterrupt();
|
||||
vif1Regs->mskpath3 = false;
|
||||
gifRegs->stat.M3P = 0;
|
||||
vif1Regs.mskpath3 = false;
|
||||
gifRegs.stat.M3P = 0;
|
||||
}
|
||||
|
||||
vif1Regs->mskpath3 = false;
|
||||
gifRegs->stat.M3P = 0;
|
||||
vif1Regs->err.reset();
|
||||
vif1Regs.mskpath3 = false;
|
||||
gifRegs.stat.M3P = 0;
|
||||
vif1Regs.err.reset();
|
||||
vif1.inprogress = 0;
|
||||
vif1.cmd = 0;
|
||||
vif1.vifstalled = false;
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs->stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
|
||||
vif1Regs.stat.FQC = 0;
|
||||
vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
|
||||
}
|
||||
|
||||
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
|
||||
|
@ -185,8 +185,8 @@ __fi void vif1FBRST(u32 value) {
|
|||
if (FBRST(value).FBK) // Forcebreak Vif.
|
||||
{
|
||||
/* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
|
||||
vif1Regs->stat.VFS = true;
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.VFS = true;
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
Console.WriteLn("vif1 force break");
|
||||
}
|
||||
|
@ -195,8 +195,8 @@ __fi void vif1FBRST(u32 value) {
|
|||
{
|
||||
// Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of
|
||||
// just stoppin the VIF (linuz).
|
||||
vif1Regs->stat.VSS = true;
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.VSS = true;
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
|
||||
vif1.vifstalled = true;
|
||||
}
|
||||
|
@ -206,12 +206,12 @@ __fi void vif1FBRST(u32 value) {
|
|||
bool cancel = false;
|
||||
|
||||
/* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
|
||||
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
vif1Regs->stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
|
||||
vif1Regs.stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
|
||||
VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1);
|
||||
|
||||
if (cancel)
|
||||
|
@ -220,22 +220,22 @@ __fi void vif1FBRST(u32 value) {
|
|||
{
|
||||
g_vifCycles = 0;
|
||||
// loop necessary for spiderman
|
||||
switch(dmacRegs->ctrl.MFD)
|
||||
switch(dmacRegs.ctrl.MFD)
|
||||
{
|
||||
case MFD_VIF1:
|
||||
//Console.WriteLn("MFIFO Stall");
|
||||
if(vif1ch->chcr.STR == true) CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
if(vif1ch.chcr.STR == true) CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
case MFD_GIF: // Wonder if this should be with VIF?
|
||||
// Gets the timing right - Flatout
|
||||
if(vif1ch->chcr.STR == true) CPU_INT(DMAC_VIF1, 0);
|
||||
if(vif1ch.chcr.STR == true) CPU_INT(DMAC_VIF1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
//vif1ch->chcr.STR = true;
|
||||
//vif1ch.chcr.STR = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,16 +245,16 @@ __fi void vif1STAT(u32 value) {
|
|||
VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
|
||||
|
||||
/* Only FDR bit is writable, so mask the rest */
|
||||
if ((vif1Regs->stat.FDR) ^ ((tVIF_STAT&)value).FDR) {
|
||||
if ((vif1Regs.stat.FDR) ^ ((tVIF_STAT&)value).FDR) {
|
||||
// different so can't be stalled
|
||||
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) {
|
||||
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) {
|
||||
DevCon.WriteLn("changing dir when vif1 fifo stalled");
|
||||
}
|
||||
}
|
||||
|
||||
vif1Regs->stat.FDR = VIF_STAT(value).FDR;
|
||||
vif1Regs.stat.FDR = VIF_STAT(value).FDR;
|
||||
|
||||
if (vif1Regs->stat.FDR) // Vif transferring to memory.
|
||||
if (vif1Regs.stat.FDR) // Vif transferring to memory.
|
||||
{
|
||||
// Hack but it checks this is true before transfer? (fatal frame)
|
||||
// Update Refraction: Use of this function has been investigated and understood.
|
||||
|
@ -263,7 +263,7 @@ __fi void vif1STAT(u32 value) {
|
|||
// As far as the GS is concerned, the transfer starts as soon as TRXDIR is accessed, which is why fatal frame
|
||||
// was expecting data, the GS should already be sending it over (buffering in the FIFO)
|
||||
|
||||
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize);
|
||||
|
||||
}
|
||||
|
@ -271,69 +271,65 @@ __fi void vif1STAT(u32 value) {
|
|||
{
|
||||
//Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it.
|
||||
//Other times it can read it off ;)
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs.stat.FQC = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define caseVif(x) (idx ? VIF1_##x : VIF0_##x)
|
||||
|
||||
_vifT void vifWrite32(u32 mem, u32 value) {
|
||||
// returns FALSE if no writeback is needed (or writeback is handled internally)
|
||||
// returns TRUE if the caller should writeback the value to the eeHw register map.
|
||||
_vifT __fi bool vifWrite32(u32 mem, u32 value) {
|
||||
switch (mem) {
|
||||
case caseVif(MARK):
|
||||
VIF_LOG("VIF%d_MARK write32 0x%8.8x", idx, value);
|
||||
vifXRegs->stat.MRK = false;
|
||||
vifXRegs->mark = value;
|
||||
break;
|
||||
//vifXRegs->mark = value;
|
||||
break;
|
||||
|
||||
case caseVif(FBRST):
|
||||
if (!idx) vif0FBRST(value);
|
||||
else vif1FBRST(value);
|
||||
break;
|
||||
|
||||
case caseVif(ERR):
|
||||
VIF_LOG("VIF%d_ERR write32 0x%8.8x", idx, value);
|
||||
vifXRegs->err.write(value);
|
||||
break;
|
||||
return false;
|
||||
|
||||
case caseVif(STAT):
|
||||
if (idx) { // Only Vif1 does this stuff?
|
||||
vif1STAT(value);
|
||||
}
|
||||
else {
|
||||
Console.WriteLn("Unknown Vif%d write to %x", idx, mem);
|
||||
psHu32(mem) = value;
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
|
||||
case caseVif(ERR):
|
||||
case caseVif(MODE):
|
||||
vifXRegs->mode = value;
|
||||
break;
|
||||
// standard register writes -- handled by caller.
|
||||
break;
|
||||
|
||||
case caseVif(R0):
|
||||
case caseVif(R1):
|
||||
case caseVif(R2):
|
||||
case caseVif(R3):
|
||||
if (!idx) g_vifmask.Row0[ (mem>>4)&3 ] = value;
|
||||
else g_vifmask.Row1[ (mem>>4)&3 ] = value;
|
||||
((u32*)&vifXRegs->r0) [((mem>>4)&3)*4] = value;
|
||||
break;
|
||||
case caseVif(ROW0):
|
||||
case caseVif(ROW1):
|
||||
case caseVif(ROW2):
|
||||
case caseVif(ROW3):
|
||||
// Here's a neat way to obfuscate code. This is a super-fancy-complicated version
|
||||
// of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
|
||||
//if (!idx) g_vifmask.Row0[ (mem>>4)&3 ] = value;
|
||||
//else g_vifmask.Row1[ (mem>>4)&3 ] = value;
|
||||
//((u32*)&vifXRegs->r0) [((mem>>4)&3)*4] = value;
|
||||
break;
|
||||
|
||||
case caseVif(C0):
|
||||
case caseVif(C1):
|
||||
case caseVif(C2):
|
||||
case caseVif(C3):
|
||||
if (!idx) g_vifmask.Col0[ (mem>>4)&3 ] = value;
|
||||
else g_vifmask.Col1[ (mem>>4)&3 ] = value;
|
||||
((u32*)&vifXRegs->c0) [((mem>>4)&3)*4] = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.WriteLn("Unknown Vif%d write to %x", idx, mem);
|
||||
psHu32(mem) = value;
|
||||
break;
|
||||
case caseVif(COL0):
|
||||
case caseVif(COL1):
|
||||
case caseVif(COL2):
|
||||
case caseVif(COL3):
|
||||
// Here's a neat way to obfuscate code. This is a super-fancy-complicated version
|
||||
// of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
|
||||
//if (!idx) g_vifmask.Col0[ (mem>>4)&3 ] = value;
|
||||
//else g_vifmask.Col1[ (mem>>4)&3 ] = value;
|
||||
//((u32*)&vifXRegs->c0) [((mem>>4)&3)*4] = value;
|
||||
break;
|
||||
}
|
||||
/* Other registers are read-only so do nothing for them */
|
||||
|
||||
// fall-through case: issue standard writeback behavior.
|
||||
return true;
|
||||
}
|
||||
|
||||
void vif0Write32(u32 mem, u32 value) { vifWrite32<0>(mem, value); }
|
||||
void vif1Write32(u32 mem, u32 value) { vifWrite32<1>(mem, value); }
|
||||
|
||||
template bool vifWrite32<0>(u32 mem, u32 value);
|
||||
template bool vifWrite32<1>(u32 mem, u32 value);
|
||||
|
|
|
@ -215,15 +215,13 @@ struct VIFregisters {
|
|||
|
||||
extern VIFregisters *vifRegs;
|
||||
|
||||
static VIFregisters& vif0RegsRef = (VIFregisters&)eeHw[0x3800];
|
||||
static VIFregisters& vif1RegsRef = (VIFregisters&)eeHw[0x3C00];
|
||||
#define vif0Regs (&vif0RegsRef)
|
||||
#define vif1Regs (&vif1RegsRef)
|
||||
static VIFregisters& vif0Regs = (VIFregisters&)eeHw[0x3800];
|
||||
static VIFregisters& vif1Regs = (VIFregisters&)eeHw[0x3C00];
|
||||
|
||||
#define _vifT template <int idx>
|
||||
#define GetVifX (idx ? (vif1) : (vif0))
|
||||
#define vifXch (idx ? (vif1ch) : (vif0ch))
|
||||
#define vifXRegs (idx ? (vif1Regs) : (vif0Regs))
|
||||
#define vifXRegs (idx ? (&vif1Regs): (&vif0Regs))
|
||||
|
||||
extern void dmaVIF0();
|
||||
extern void dmaVIF1();
|
||||
|
|
|
@ -54,28 +54,28 @@ bool _VIF0chain()
|
|||
{
|
||||
u32 *pMem;
|
||||
|
||||
if (vif0ch->qwc == 0)
|
||||
if (vif0ch.qwc == 0)
|
||||
{
|
||||
vif0.inprogress = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
pMem = (u32*)dmaGetAddr(vif0ch->madr, false);
|
||||
pMem = (u32*)dmaGetAddr(vif0ch.madr, false);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
vif0.cmd = 0;
|
||||
vif0.tag.size = 0;
|
||||
vif0ch->qwc = 0;
|
||||
vif0ch.qwc = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx",
|
||||
vif0ch->qwc, vif0ch->madr, vif0ch->tadr);
|
||||
vif0ch.qwc, vif0ch.madr, vif0ch.tadr);
|
||||
|
||||
if (vif0.vifstalled)
|
||||
return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset);
|
||||
return VIF0transfer(pMem + vif0.irqoffset, vif0ch.qwc * 4 - vif0.irqoffset);
|
||||
else
|
||||
return VIF0transfer(pMem, vif0ch->qwc * 4);
|
||||
return VIF0transfer(pMem, vif0ch.qwc * 4);
|
||||
}
|
||||
|
||||
__fi void vif0SetupTransfer()
|
||||
|
@ -91,21 +91,21 @@ __fi void vif0SetupTransfer()
|
|||
break;
|
||||
|
||||
case VIF_CHAIN_MODE:
|
||||
ptag = dmaGetAddr(vif0ch->tadr, false); //Set memory pointer to TADR
|
||||
ptag = dmaGetAddr(vif0ch.tadr, false); //Set memory pointer to TADR
|
||||
|
||||
if (!(vif0ch->transfer("vif0 Tag", ptag))) return;
|
||||
if (!(vif0ch.transfer("vif0 Tag", ptag))) return;
|
||||
|
||||
vif0ch->madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
vif0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
|
||||
|
||||
// Transfer dma tag if tte is set
|
||||
|
||||
VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr);
|
||||
ptag[1]._u32, ptag[0]._u32, vif0ch.qwc, ptag->ID, vif0ch.madr, vif0ch.tadr);
|
||||
|
||||
vif0.inprogress = 0;
|
||||
|
||||
if (vif0ch->chcr.TTE)
|
||||
if (vif0ch.chcr.TTE)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
|
@ -124,9 +124,9 @@ __fi void vif0SetupTransfer()
|
|||
vif0.irqoffset = 0;
|
||||
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
|
||||
|
||||
if(vif0ch->qwc > 0) vif0.inprogress = 1;
|
||||
if(vif0ch.qwc > 0) vif0.inprogress = 1;
|
||||
//Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (vif0ch->chcr.TIE && ptag->IRQ)
|
||||
if (vif0ch.chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
VIF_LOG("dmaIrq Set");
|
||||
|
||||
|
@ -144,29 +144,29 @@ __fi void vif0Interrupt()
|
|||
|
||||
g_vifCycles = 0;
|
||||
|
||||
if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32);
|
||||
if (!(vif0ch.chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch.chcr._u32);
|
||||
|
||||
if (vif0.cmd)
|
||||
{
|
||||
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING;
|
||||
if(vif0.done == true && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0Regs->stat.VPS = VPS_IDLE;
|
||||
vif0Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif0.irq && vif0.tag.size == 0)
|
||||
{
|
||||
vif0Regs->stat.INT = true;
|
||||
vif0Regs.stat.INT = true;
|
||||
hwIntcIrq(VIF0intc);
|
||||
--vif0.irq;
|
||||
if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||
if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||
{
|
||||
vif0Regs->stat.FQC = 0;
|
||||
vif0Regs.stat.FQC = 0;
|
||||
|
||||
// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
|
||||
//vif0ch->chcr.STR = false;
|
||||
if(vif0ch->qwc > 0 || !vif0.done) return;
|
||||
//vif0ch.chcr.STR = false;
|
||||
if(vif0ch.qwc > 0 || !vif0.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ __fi void vif0Interrupt()
|
|||
if (!vif0.done)
|
||||
{
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE))
|
||||
if (!(dmacRegs.ctrl.DMAE))
|
||||
{
|
||||
Console.WriteLn("vif0 dma masked");
|
||||
return;
|
||||
|
@ -199,22 +199,22 @@ __fi void vif0Interrupt()
|
|||
return; //Dont want to end if vif is stalled.
|
||||
}
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (vif0ch->qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
|
||||
if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
|
||||
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
|
||||
#endif
|
||||
|
||||
vif0ch->chcr.STR = false;
|
||||
vif0ch.chcr.STR = false;
|
||||
g_vifCycles = 0;
|
||||
hwDmacIrq(DMAC_VIF0);
|
||||
vif0Regs->stat.FQC = 0;
|
||||
vif0Regs.stat.FQC = 0;
|
||||
}
|
||||
|
||||
void dmaVIF0()
|
||||
{
|
||||
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
|
||||
" tadr = %lx, asr0 = %lx, asr1 = %lx",
|
||||
vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc,
|
||||
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
|
||||
vif0ch.chcr._u32, vif0ch.madr, vif0ch.qwc,
|
||||
vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
|
||||
|
||||
g_vifCycles = 0;
|
||||
g_vu0Cycles = 0;
|
||||
|
@ -224,18 +224,18 @@ void dmaVIF0()
|
|||
vif0.inprogress = 0;
|
||||
vif0.done = false;*/
|
||||
|
||||
if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode
|
||||
if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode
|
||||
{
|
||||
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
|
||||
vif0.done = false;
|
||||
|
||||
if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0)
|
||||
if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0)
|
||||
{
|
||||
vif0.dmamode = VIF_CHAIN_MODE;
|
||||
DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc());
|
||||
DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch.chcr.desc());
|
||||
|
||||
if ((vif0ch->chcr.tag().ID == TAG_REFE) || (vif0ch->chcr.tag().ID == TAG_END))
|
||||
if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END))
|
||||
{
|
||||
vif0.done = true;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ void dmaVIF0()
|
|||
vif0.done = false;
|
||||
}
|
||||
|
||||
vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc);
|
||||
vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
|
||||
|
||||
//Using a delay as Beyond Good and Evil does the DMA twice with 2 different TADR's (no checks in the middle, all one block of code),
|
||||
//the first bit it sends isnt required for it to work.
|
||||
|
|
|
@ -46,10 +46,10 @@ __fi void vif1FLUSH()
|
|||
//DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS);
|
||||
g_vifCycles += (VU1.cycle - _cycles) * BIAS;
|
||||
}
|
||||
if(gifRegs->stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17))
|
||||
if(gifRegs.stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17))
|
||||
{
|
||||
vif1.vifstalled = true;
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1Regs.stat.VGW = true;
|
||||
vif1.GifWaitState = 2;
|
||||
}
|
||||
|
||||
|
@ -58,16 +58,16 @@ __fi void vif1FLUSH()
|
|||
void vif1TransferToMemory()
|
||||
{
|
||||
u32 size;
|
||||
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr, false);
|
||||
u64* pMem = (u64*)dmaGetAddr(vif1ch.madr, false);
|
||||
|
||||
// VIF from gsMemory
|
||||
if (pMem == NULL) //Is vif0ptag empty?
|
||||
{
|
||||
Console.WriteLn("Vif1 Tag BUSERR");
|
||||
dmacRegs->stat.BEIS = true; //Bus Error
|
||||
vif1Regs->stat.FQC = 0;
|
||||
dmacRegs.stat.BEIS = true; //Bus Error
|
||||
vif1Regs.stat.FQC = 0;
|
||||
|
||||
vif1ch->qwc = 0;
|
||||
vif1ch.qwc = 0;
|
||||
vif1.done = true;
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
return; //An error has occurred.
|
||||
|
@ -76,8 +76,8 @@ void vif1TransferToMemory()
|
|||
// MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
|
||||
// stuff from the GS. The *only* way to handle this case safely is to flush the GS
|
||||
// completely and execute the transfer there-after.
|
||||
//Console.Warning("Real QWC %x", vif1ch->qwc);
|
||||
size = min((u32)vif1ch->qwc, vif1.GSLastDownloadSize);
|
||||
//Console.Warning("Real QWC %x", vif1ch.qwc);
|
||||
size = min((u32)vif1ch.qwc, vif1.GSLastDownloadSize);
|
||||
|
||||
if (GSreadFIFO2 == NULL)
|
||||
{
|
||||
|
@ -90,10 +90,10 @@ void vif1TransferToMemory()
|
|||
pMem[1] = psHu64(VIF1_FIFO + 8);
|
||||
pMem += 2;
|
||||
}
|
||||
if(vif1ch->qwc > vif1.GSLastDownloadSize)
|
||||
if(vif1ch.qwc > vif1.GSLastDownloadSize)
|
||||
{
|
||||
DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
|
||||
for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size)
|
||||
for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
|
||||
{
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
|
@ -112,10 +112,10 @@ void vif1TransferToMemory()
|
|||
psHu64(VIF1_FIFO) = pMem[2*size-2];
|
||||
psHu64(VIF1_FIFO + 8) = pMem[2*size-1];
|
||||
pMem += size * 2;
|
||||
if(vif1ch->qwc > vif1.GSLastDownloadSize)
|
||||
if(vif1ch.qwc > vif1.GSLastDownloadSize)
|
||||
{
|
||||
DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
|
||||
for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size)
|
||||
for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
|
||||
{
|
||||
psHu64(VIF1_FIFO) = 0;
|
||||
psHu64(VIF1_FIFO + 8) = 0;
|
||||
|
@ -127,27 +127,27 @@ void vif1TransferToMemory()
|
|||
}
|
||||
|
||||
|
||||
g_vifCycles += vif1ch->qwc * 2;
|
||||
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
|
||||
if(vif1.GSLastDownloadSize >= vif1ch->qwc)
|
||||
g_vifCycles += vif1ch.qwc * 2;
|
||||
vif1ch.madr += vif1ch.qwc * 16; // mgs3 scene changes
|
||||
if(vif1.GSLastDownloadSize >= vif1ch.qwc)
|
||||
{
|
||||
vif1.GSLastDownloadSize -= vif1ch->qwc;
|
||||
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
vif1.GSLastDownloadSize -= vif1ch.qwc;
|
||||
vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs.stat.FQC = 0;
|
||||
vif1.GSLastDownloadSize = 0;
|
||||
}
|
||||
|
||||
vif1ch->qwc = 0;
|
||||
vif1ch.qwc = 0;
|
||||
}
|
||||
|
||||
bool _VIF1chain()
|
||||
{
|
||||
u32 *pMem;
|
||||
|
||||
if (vif1ch->qwc == 0)
|
||||
if (vif1ch.qwc == 0)
|
||||
{
|
||||
vif1.inprogress &= ~1;
|
||||
vif1.irqoffset = 0;
|
||||
|
@ -162,22 +162,22 @@ bool _VIF1chain()
|
|||
return true;
|
||||
}
|
||||
|
||||
pMem = (u32*)dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
|
||||
pMem = (u32*)dmaGetAddr(vif1ch.madr, !vif1ch.chcr.DIR);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
vif1.cmd = 0;
|
||||
vif1.tag.size = 0;
|
||||
vif1ch->qwc = 0;
|
||||
vif1ch.qwc = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx",
|
||||
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
|
||||
vif1ch.qwc, vif1ch.madr, vif1ch.tadr);
|
||||
|
||||
if (vif1.vifstalled)
|
||||
return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset);
|
||||
return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset);
|
||||
else
|
||||
return VIF1transfer(pMem, vif1ch->qwc * 4);
|
||||
return VIF1transfer(pMem, vif1ch.qwc * 4);
|
||||
}
|
||||
|
||||
__fi void vif1SetupTransfer()
|
||||
|
@ -205,10 +205,10 @@ __fi void vif1SetupTransfer()
|
|||
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, vif1c.qwc, ptag->ID, vif1c.madr, vif1c.tadr);
|
||||
|
||||
if (!vif1.done && ((dmacRegs->ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
|
||||
if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
|
||||
{
|
||||
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
|
||||
if ((vif1c.madr + vif1c.qwc * 16) >= dmacRegs->stadr.ADDR)
|
||||
if ((vif1c.madr + vif1c.qwc * 16) >= dmacRegs.stadr.ADDR)
|
||||
{
|
||||
// stalled
|
||||
hwDmacIrq(DMAC_STALL_SIS);
|
||||
|
@ -262,73 +262,73 @@ extern bool SIGNAL_IMR_Pending;
|
|||
|
||||
bool CheckPath2GIF(EE_EventType channel)
|
||||
{
|
||||
if ((vif1Regs->stat.VGW))
|
||||
if ((vif1Regs.stat.VGW))
|
||||
{
|
||||
if( vif1.GifWaitState == 0 ) //DIRECT/HL Check
|
||||
{
|
||||
if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q)
|
||||
if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q)
|
||||
{
|
||||
if(gifRegs->stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs->stat.P1Q == false)
|
||||
if(gifRegs.stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs.stat.P1Q == false)
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 128);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
|
||||
{
|
||||
if (gifRegs->stat.P1Q)
|
||||
if (gifRegs.stat.P1Q)
|
||||
{
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 128);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GSTransferStatus.PTH3 < IDLE_MODE)
|
||||
{
|
||||
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs->stat.P1Q, gifRegs->stat.P3Q, gifRegs->stat.IP3 );
|
||||
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs.stat.P1Q, gifRegs.stat.P3Q, gifRegs.stat.IP3 );
|
||||
CPU_INT(channel, 8);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
|
||||
{
|
||||
if (gifRegs->ctrl.PSE)
|
||||
if (gifRegs.ctrl.PSE)
|
||||
{
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 128);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
}
|
||||
}
|
||||
else //Normal Flush
|
||||
{
|
||||
if (gifRegs->stat.P1Q)
|
||||
if (gifRegs.stat.P1Q)
|
||||
{
|
||||
//DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
//DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
|
||||
CPU_INT(channel, 128);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VGW = false;
|
||||
vif1Regs.stat.VGW = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,11 +346,11 @@ __fi void vif1Interrupt()
|
|||
|
||||
g_vifCycles = 0;
|
||||
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2)
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
}
|
||||
|
||||
if (schedulepath3msk & 0x10)
|
||||
|
@ -360,48 +360,48 @@ __fi void vif1Interrupt()
|
|||
return;
|
||||
}
|
||||
//Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
|
||||
if (dmacRegs->ctrl.MFD == MFD_VIF1)
|
||||
if (dmacRegs.ctrl.MFD == MFD_VIF1)
|
||||
{
|
||||
//Console.WriteLn("VIFMFIFO\n");
|
||||
// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
|
||||
if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32);
|
||||
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
if (vif1ch.chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch.chcr._u32);
|
||||
vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
|
||||
vifMFIFOInterrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
//We need to check the direction, if it is downloading from the GS, we handle that separately (KH2 for testing)
|
||||
if (vif1ch->chcr.DIR)
|
||||
if (vif1ch.chcr.DIR)
|
||||
{
|
||||
if (!CheckPath2GIF(DMAC_VIF1)) return;
|
||||
|
||||
vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||
//Simulated GS transfer time done, clear the flags
|
||||
}
|
||||
|
||||
if (!vif1ch->chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32);
|
||||
if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
|
||||
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if (vif1.done && (vif1ch->qwc == 0)) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
if (vif1.done && (vif1ch.qwc == 0)) vif1Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif1.irq && vif1.tag.size == 0)
|
||||
{
|
||||
vif1Regs->stat.INT = true;
|
||||
vif1Regs.stat.INT = true;
|
||||
hwIntcIrq(VIF1intc);
|
||||
--vif1.irq;
|
||||
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
//vif1Regs->stat.FQC = 0;
|
||||
//vif1Regs.stat.FQC = 0;
|
||||
|
||||
//NFSHPS stalls when the whole packet has gone across (it stalls in the last 32bit cmd)
|
||||
//In this case VIF will end
|
||||
if(vif1ch->qwc > 0 || !vif1.done) return;
|
||||
if(vif1ch.qwc > 0 || !vif1.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,7 +410,7 @@ __fi void vif1Interrupt()
|
|||
_VIF1chain();
|
||||
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
||||
// Timesplitters 2 depends on this beeing a bit higher than 128.
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||
// Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
|
||||
/*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
|
||||
else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/);
|
||||
|
@ -420,14 +420,14 @@ __fi void vif1Interrupt()
|
|||
if (!vif1.done)
|
||||
{
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE))
|
||||
if (!(dmacRegs.ctrl.DMAE))
|
||||
{
|
||||
Console.WriteLn("vif1 dma masked");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||
CPU_INT(DMAC_VIF1, g_vifCycles);
|
||||
return;
|
||||
}
|
||||
|
@ -439,17 +439,17 @@ __fi void vif1Interrupt()
|
|||
return; //Dont want to end if vif is stalled.
|
||||
}
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (vif1ch->qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch->qwc);
|
||||
if (vif1ch.qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch.qwc);
|
||||
if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
|
||||
#endif
|
||||
|
||||
if((vif1ch->chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
|
||||
if((vif1ch.chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
|
||||
{
|
||||
//Reverse fifo has finished and nothing is left, so lets clear the outputting flag
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs.stat.OPH = false;
|
||||
}
|
||||
|
||||
vif1ch->chcr.STR = false;
|
||||
vif1ch.chcr.STR = false;
|
||||
vif1.vifstalled = false;
|
||||
g_vifCycles = 0;
|
||||
g_vu1Cycles = 0;
|
||||
|
@ -462,8 +462,8 @@ void dmaVIF1()
|
|||
{
|
||||
VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
|
||||
" tadr = %lx, asr0 = %lx, asr1 = %lx",
|
||||
vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
|
||||
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
|
||||
vif1ch.chcr._u32, vif1ch.madr, vif1ch.qwc,
|
||||
vif1ch.tadr, vif1ch.asr0, vif1ch.asr1);
|
||||
|
||||
// vif1.done = false;
|
||||
|
||||
|
@ -475,19 +475,19 @@ void dmaVIF1()
|
|||
g_vu1Cycles = 0;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (dmacRegs->ctrl.STD == STD_VIF1)
|
||||
if (dmacRegs.ctrl.STD == STD_VIF1)
|
||||
{
|
||||
//DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
|
||||
if ((vif1ch.chcr.MOD == NORMAL_MODE) || vif1ch.qwc > 0) // Normal Mode
|
||||
{
|
||||
|
||||
if (dmacRegs->ctrl.STD == STD_VIF1)
|
||||
if (dmacRegs.ctrl.STD == STD_VIF1)
|
||||
Console.WriteLn("DMA Stall Control on VIF1 normal");
|
||||
|
||||
if (vif1ch->chcr.DIR) // to Memory
|
||||
if (vif1ch.chcr.DIR) // to Memory
|
||||
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
|
||||
else
|
||||
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
|
@ -495,12 +495,12 @@ void dmaVIF1()
|
|||
vif1.done = false;
|
||||
|
||||
// ignore tag if it's a GS download (Def Jam Fight for NY)
|
||||
if(vif1ch->chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE)
|
||||
if(vif1ch.chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE)
|
||||
{
|
||||
vif1.dmamode = VIF_CHAIN_MODE;
|
||||
DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc());
|
||||
DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc());
|
||||
|
||||
if ((vif1ch->chcr.tag().ID == TAG_REFE) || (vif1ch->chcr.tag().ID == TAG_END))
|
||||
if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END))
|
||||
{
|
||||
vif1.done = true;
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ void dmaVIF1()
|
|||
vif1.done = false;
|
||||
}
|
||||
|
||||
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
|
||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
|
||||
|
||||
// Chain Mode
|
||||
CPU_INT(DMAC_VIF1, 4);
|
||||
|
|
|
@ -33,26 +33,26 @@ extern u32 g_vifCycles;
|
|||
|
||||
static u32 qwctag(u32 mask)
|
||||
{
|
||||
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
|
||||
return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
|
||||
}
|
||||
|
||||
static __fi bool mfifoVIF1rbTransfer()
|
||||
{
|
||||
u32 maddr = dmacRegs->rbor.ADDR;
|
||||
u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16;
|
||||
u16 mfifoqwc = std::min(vif1ch->qwc, vifqwc);
|
||||
u32 maddr = dmacRegs.rbor.ADDR;
|
||||
u32 msize = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
|
||||
u16 mfifoqwc = std::min(vif1ch.qwc, vifqwc);
|
||||
u32 *src;
|
||||
bool ret;
|
||||
|
||||
/* Check if the transfer should wrap around the ring buffer */
|
||||
if ((vif1ch->madr + (mfifoqwc << 4)) > (msize))
|
||||
if ((vif1ch.madr + (mfifoqwc << 4)) > (msize))
|
||||
{
|
||||
int s1 = ((msize) - vif1ch->madr) >> 2;
|
||||
int s1 = ((msize) - vif1ch.madr) >> 2;
|
||||
|
||||
SPR_LOG("Split MFIFO");
|
||||
|
||||
/* it does, so first copy 's1' bytes from 'addr' to 'data' */
|
||||
src = (u32*)PSM(vif1ch->madr);
|
||||
src = (u32*)PSM(vif1ch.madr);
|
||||
if (src == NULL) return false;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
|
@ -60,18 +60,18 @@ static __fi bool mfifoVIF1rbTransfer()
|
|||
else
|
||||
ret = VIF1transfer(src, s1);
|
||||
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
vif1ch.madr = qwctag(vif1ch.madr);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
|
||||
vif1ch->madr = maddr;
|
||||
vif1ch.madr = maddr;
|
||||
|
||||
src = (u32*)PSM(maddr);
|
||||
if (src == NULL) return false;
|
||||
VIF1transfer(src, ((mfifoqwc << 2) - s1));
|
||||
}
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
vif1ch.madr = qwctag(vif1ch.madr);
|
||||
|
||||
}
|
||||
else
|
||||
|
@ -79,7 +79,7 @@ static __fi bool mfifoVIF1rbTransfer()
|
|||
SPR_LOG("Direct MFIFO");
|
||||
|
||||
/* it doesn't, so just transfer 'qwc*4' words */
|
||||
src = (u32*)PSM(vif1ch->madr);
|
||||
src = (u32*)PSM(vif1ch.madr);
|
||||
if (src == NULL) return false;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
|
@ -87,7 +87,7 @@ static __fi bool mfifoVIF1rbTransfer()
|
|||
else
|
||||
ret = VIF1transfer(src, mfifoqwc << 2);
|
||||
|
||||
vif1ch->madr = qwctag(vif1ch->madr);
|
||||
vif1ch.madr = qwctag(vif1ch.madr);
|
||||
|
||||
}
|
||||
return ret;
|
||||
|
@ -96,25 +96,25 @@ static __fi bool mfifoVIF1rbTransfer()
|
|||
static __fi void mfifo_VIF1chain()
|
||||
{
|
||||
/* Is QWC = 0? if so there is nothing to transfer */
|
||||
if ((vif1ch->qwc == 0))
|
||||
if ((vif1ch.qwc == 0))
|
||||
{
|
||||
vif1.inprogress &= ~1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vif1ch->madr >= dmacRegs->rbor.ADDR &&
|
||||
vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
|
||||
if (vif1ch.madr >= dmacRegs.rbor.ADDR &&
|
||||
vif1ch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK))
|
||||
{
|
||||
//Need to exit on mfifo locations, if the madr is matching the madr of spr, we dont have any data left :(
|
||||
|
||||
u16 startqwc = vif1ch->qwc;
|
||||
u16 startqwc = vif1ch.qwc;
|
||||
mfifoVIF1rbTransfer();
|
||||
vifqwc -= startqwc - vif1ch->qwc;
|
||||
vifqwc -= startqwc - vif1ch.qwc;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
|
||||
tDMA_TAG *pMem = dmaGetAddr(vif1ch.madr, !vif1ch.chcr.DIR);
|
||||
SPR_LOG("Non-MFIFO Location");
|
||||
|
||||
//No need to exit on non-mfifo as it is indirect anyway, so it can be transferring this while spr refills the mfifo
|
||||
|
@ -122,9 +122,9 @@ static __fi void mfifo_VIF1chain()
|
|||
if (pMem == NULL) return;
|
||||
|
||||
if (vif1.vifstalled)
|
||||
VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset);
|
||||
VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset);
|
||||
else
|
||||
VIF1transfer((u32*)pMem, vif1ch->qwc << 2);
|
||||
VIF1transfer((u32*)pMem, vif1ch.qwc << 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,23 +139,23 @@ void mfifoVIF1transfer(int qwc)
|
|||
if (qwc > 0)
|
||||
{
|
||||
vifqwc += qwc;
|
||||
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr._u32, vif1.vifstalled, vif1.done);
|
||||
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch.chcr._u32, vif1.vifstalled, vif1.done);
|
||||
if (vif1.inprogress & 0x10)
|
||||
{
|
||||
if(vif1ch->chcr.STR == true)CPU_INT(DMAC_MFIFO_VIF, 4);
|
||||
if(vif1ch.chcr.STR == true)CPU_INT(DMAC_MFIFO_VIF, 4);
|
||||
|
||||
vif1Regs->stat.FQC = 0x10; // FQC=16
|
||||
vif1Regs.stat.FQC = 0x10; // FQC=16
|
||||
}
|
||||
vif1.inprogress &= ~0x10;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (vif1ch->qwc == 0 && vifqwc > 0)
|
||||
if (vif1ch.qwc == 0 && vifqwc > 0)
|
||||
{
|
||||
ptag = dmaGetAddr(vif1ch->tadr, false);
|
||||
ptag = dmaGetAddr(vif1ch.tadr, false);
|
||||
|
||||
if (vif1ch->chcr.TTE)
|
||||
if (vif1ch.chcr.TTE)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
|
@ -173,62 +173,62 @@ void mfifoVIF1transfer(int qwc)
|
|||
|
||||
vif1.irqoffset = 0;
|
||||
|
||||
vif1ch->unsafeTransfer(ptag);
|
||||
vif1ch.unsafeTransfer(ptag);
|
||||
|
||||
vif1ch->madr = ptag[1]._u32;
|
||||
vif1ch.madr = ptag[1]._u32;
|
||||
vifqwc--;
|
||||
|
||||
SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
|
||||
ptag[1]._u32, ptag[0]._u32, vif1ch->qwc, ptag->ID, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr);
|
||||
ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr, vifqwc, spr0ch.madr);
|
||||
|
||||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_REFE: // Refe - Transfer Packet According to ADDR field
|
||||
vif1ch->tadr = qwctag(vif1ch->tadr + 16);
|
||||
vif1ch.tadr = qwctag(vif1ch.tadr + 16);
|
||||
vif1.done = true; //End Transfer
|
||||
break;
|
||||
|
||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW after Tag
|
||||
vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
|
||||
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW after Tag
|
||||
vif1ch.tadr = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
|
||||
vif1.done = false;
|
||||
break;
|
||||
|
||||
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
|
||||
{
|
||||
int temp = vif1ch->madr; //Temporarily Store ADDR
|
||||
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW following the tag
|
||||
vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag
|
||||
if ((temp & dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
|
||||
int temp = vif1ch.madr; //Temporarily Store ADDR
|
||||
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW following the tag
|
||||
vif1ch.tadr = temp; //Copy temporarily stored ADDR to Tag
|
||||
if ((temp & dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
|
||||
vif1.done = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case TAG_REF: // Ref - Transfer QWC from ADDR field
|
||||
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
|
||||
vif1ch->tadr = qwctag(vif1ch->tadr + 16); //Set TADR to next tag
|
||||
vif1ch.tadr = qwctag(vif1ch.tadr + 16); //Set TADR to next tag
|
||||
vif1.done = false;
|
||||
break;
|
||||
|
||||
case TAG_END: // End - Transfer QWC following the tag
|
||||
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to data following the tag
|
||||
vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data
|
||||
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to data following the tag
|
||||
vif1ch.tadr = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
|
||||
vif1.done = true; //End Transfer
|
||||
break;
|
||||
}
|
||||
|
||||
if (vif1ch->chcr.TIE && ptag->IRQ)
|
||||
if (vif1ch.chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
VIF_LOG("dmaIrq Set");
|
||||
vif1.done = true;
|
||||
}
|
||||
|
||||
vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
|
||||
vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||
vif1.inprogress |= 1;
|
||||
}
|
||||
|
||||
|
||||
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc);
|
||||
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr, vifqwc);
|
||||
}
|
||||
|
||||
void vifMFIFOInterrupt()
|
||||
|
@ -236,52 +236,52 @@ void vifMFIFOInterrupt()
|
|||
g_vifCycles = 0;
|
||||
VIF_LOG("vif mfifo interrupt");
|
||||
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2)
|
||||
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
|
||||
{
|
||||
GSTransferStatus.PTH2 = STOPPED_MODE;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.P1Q) gsPath1Interrupt();
|
||||
/*gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/
|
||||
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.P1Q) gsPath1Interrupt();
|
||||
/*gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;*/
|
||||
}
|
||||
|
||||
if (schedulepath3msk & 0x10) Vif1MskPath3();
|
||||
|
||||
if(vif1ch->chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) return;
|
||||
if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) return;
|
||||
//We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
|
||||
|
||||
//Simulated GS transfer time done, clear the flags
|
||||
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING;
|
||||
if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif1Regs->stat.VPS = VPS_IDLE;
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
||||
if (vif1.irq && vif1.tag.size == 0)
|
||||
{
|
||||
vif1Regs->stat.INT = true;
|
||||
vif1Regs.stat.INT = true;
|
||||
hwIntcIrq(INTC_VIF1);
|
||||
--vif1.irq;
|
||||
|
||||
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
/*vif1Regs->stat.FQC = 0; // FQC=0
|
||||
vif1ch->chcr.STR = false;*/
|
||||
if(vif1ch->qwc > 0 || !vif1.done) return;
|
||||
/*vif1Regs.stat.FQC = 0; // FQC=0
|
||||
vif1ch.chcr.STR = false;*/
|
||||
if(vif1ch.qwc > 0 || !vif1.done) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (vif1.done == false || vif1ch->qwc)
|
||||
if (vif1.done == false || vif1ch.qwc)
|
||||
{
|
||||
switch(vif1.inprogress & 1)
|
||||
{
|
||||
case 0: //Set up transfer
|
||||
if (vif1ch->tadr == spr0->madr)
|
||||
if (vif1ch.tadr == spr0ch.madr)
|
||||
{
|
||||
// Console.WriteLn("Empty 1");
|
||||
vifqwc = 0;
|
||||
|
@ -290,7 +290,7 @@ void vifMFIFOInterrupt()
|
|||
hwDmacIrq(DMAC_MFIFO_EMPTY);
|
||||
vif1.inprogress |= 0x10;
|
||||
}
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs.stat.FQC = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ void vifMFIFOInterrupt()
|
|||
|
||||
//FF7 Dirge of Cerberus seems to like the mfifo to tell it when it's empty, even if it's ending.
|
||||
//Doesn't seem to care about the vif1 dma interrupting (possibly disabled the interrupt?)
|
||||
if (vif1ch->tadr == spr0->madr)
|
||||
if (vif1ch.tadr == spr0ch.madr)
|
||||
{
|
||||
vifqwc = 0;
|
||||
if((vif1.inprogress & 0x10) == 0)
|
||||
|
@ -322,9 +322,9 @@ void vifMFIFOInterrupt()
|
|||
vif1.vifstalled = false;
|
||||
vif1.done = 1;
|
||||
g_vifCycles = 0;
|
||||
vif1ch->chcr.STR = false;
|
||||
vif1ch.chcr.STR = false;
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
VIF_LOG("vif mfifo dma end");
|
||||
|
||||
vif1Regs->stat.FQC = 0;
|
||||
vif1Regs.stat.FQC = 0;
|
||||
}
|
||||
|
|
|
@ -85,16 +85,16 @@ u8 schedulepath3msk = 0;
|
|||
|
||||
void Vif1MskPath3() {
|
||||
|
||||
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
|
||||
GIF_LOG("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH3);
|
||||
gifRegs->stat.M3P = vif1Regs->mskpath3;
|
||||
vif1Regs.mskpath3 = schedulepath3msk & 0x1;
|
||||
GIF_LOG("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs.mskpath3, gifch.chcr.STR, GSTransferStatus.PTH3);
|
||||
gifRegs.stat.M3P = vif1Regs.mskpath3;
|
||||
|
||||
if (!vif1Regs->mskpath3)
|
||||
if (!vif1Regs.mskpath3)
|
||||
{
|
||||
//if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE;
|
||||
//DevCon.Warning("Mask off");
|
||||
//if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE;
|
||||
if(gifRegs->stat.P3Q)
|
||||
if(gifRegs.stat.P3Q)
|
||||
{
|
||||
gsInterrupt();//gsInterrupt();
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ void Vif1MskPath3() {
|
|||
|
||||
vifOp(vifCode_Base) {
|
||||
vif1Only();
|
||||
pass1 { vif1Regs->base = vif1Regs->code & 0x3ff; vif1.cmd = 0; }
|
||||
pass1 { vif1Regs.base = vif1Regs.code & 0x3ff; vif1.cmd = 0; }
|
||||
pass3 { VifCodeLog("Base"); }
|
||||
return 0;
|
||||
}
|
||||
|
@ -120,15 +120,15 @@ extern bool SIGNAL_IMR_Pending;
|
|||
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
|
||||
pass1 {
|
||||
vif1Only();
|
||||
int vifImm = (u16)vif1Regs->code;
|
||||
int vifImm = (u16)vif1Regs.code;
|
||||
vif1.tag.size = vifImm ? (vifImm*4) : (65536*4);
|
||||
vif1.vifstalled = true;
|
||||
gifRegs->stat.P2Q = true;
|
||||
if (gifRegs->stat.PSE) // temporarily stop
|
||||
gifRegs.stat.P2Q = true;
|
||||
if (gifRegs.stat.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused? VIF DIRECT");
|
||||
vif1.GifWaitState = 3;
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1Regs.stat.VGW = true;
|
||||
}
|
||||
//Should cause this to split here to try and time PATH3 right.
|
||||
return 0;
|
||||
|
@ -136,18 +136,18 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
pass2 {
|
||||
vif1Only();
|
||||
|
||||
if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true)
|
||||
if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q == true)
|
||||
{
|
||||
if(gifRegs->stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs->stat.P1Q == false)
|
||||
if(gifRegs.stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs.stat.P1Q == false)
|
||||
{
|
||||
//Do nothing, allow it
|
||||
vif1Regs->stat.VGW = false;
|
||||
//if(gifRegs->stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q);
|
||||
vif1Regs.stat.VGW = false;
|
||||
//if(gifRegs.stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs.stat.APATH, gifRegs.stat.P1Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q);
|
||||
vif1Regs->stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT)
|
||||
//DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs.stat.APATH, gifRegs.stat.P1Q);
|
||||
vif1Regs.stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT)
|
||||
vif1.GifWaitState = 0;
|
||||
vif1.vifstalled = true;
|
||||
return 0;
|
||||
|
@ -159,19 +159,19 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
vif1.vifstalled = true;
|
||||
return 0;
|
||||
}
|
||||
if (gifRegs->stat.PSE) // temporarily stop
|
||||
if (gifRegs.stat.PSE) // temporarily stop
|
||||
{
|
||||
Console.WriteLn("Gif dma temp paused? VIF DIRECT");
|
||||
vif1.GifWaitState = 3;
|
||||
vif1.vifstalled = true;
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1Regs.stat.VGW = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// HACK ATTACK!
|
||||
// we shouldn't be clearing the queue flag here at all. Ideally, the queue statuses
|
||||
// should be checked, handled, and cleared from the EOP check in GIFPath only. --air
|
||||
gifRegs->stat.clear_flags(GIF_STAT_P2Q);
|
||||
gifRegs.stat.clear_flags(GIF_STAT_P2Q);
|
||||
|
||||
uint minSize = aMin(vif1.vifpacketsize, vif1.tag.size);
|
||||
uint ret;
|
||||
|
@ -260,12 +260,12 @@ vifOp(vifCode_FlushA) {
|
|||
pass1 {
|
||||
vifFlush(idx);
|
||||
// Gif is already transferring so wait for it.
|
||||
if (gifRegs->stat.P1Q || GSTransferStatus.PTH3 <= PENDINGSTOP_MODE) {
|
||||
//DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs->mskpath3);
|
||||
if (gifRegs.stat.P1Q || GSTransferStatus.PTH3 <= PENDINGSTOP_MODE) {
|
||||
//DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs.mskpath3);
|
||||
//
|
||||
|
||||
//DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
|
||||
vif1Regs->stat.VGW = true;
|
||||
vif1Regs.stat.VGW = true;
|
||||
vifX.GifWaitState = 1;
|
||||
vifX.vifstalled = true;
|
||||
} // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
|
||||
|
@ -373,12 +373,12 @@ vifOp(vifCode_MSCNT) {
|
|||
vifOp(vifCode_MskPath3) {
|
||||
vif1Only();
|
||||
pass1 {
|
||||
if (vif1ch->chcr.STR && vif1.lastcmd != 0x13) {
|
||||
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
|
||||
if (vif1ch.chcr.STR && vif1.lastcmd != 0x13) {
|
||||
schedulepath3msk = 0x10 | ((vif1Regs.code >> 15) & 0x1);
|
||||
vif1.vifstalled = true;
|
||||
}
|
||||
else {
|
||||
schedulepath3msk = (vif1Regs->code >> 15) & 0x1;
|
||||
schedulepath3msk = (vif1Regs.code >> 15) & 0x1;
|
||||
Vif1MskPath3();
|
||||
}
|
||||
vif1.cmd = 0;
|
||||
|
@ -414,9 +414,9 @@ vifOp(vifCode_Null) {
|
|||
vifOp(vifCode_Offset) {
|
||||
vif1Only();
|
||||
pass1 {
|
||||
vif1Regs->stat.DBF = false;
|
||||
vif1Regs->ofst = vif1Regs->code & 0x3ff;
|
||||
vif1Regs->tops = vif1Regs->base;
|
||||
vif1Regs.stat.DBF = false;
|
||||
vif1Regs.ofst = vif1Regs.code & 0x3ff;
|
||||
vif1Regs.tops = vif1Regs.base;
|
||||
vif1.cmd = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("Offset"); }
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vif.h"
|
||||
#include "Vif_Unpack.h"
|
||||
|
||||
struct vifCode {
|
||||
|
@ -84,13 +86,13 @@ extern vifStruct* vif;
|
|||
extern vifStruct vif0, vif1;
|
||||
extern u8 schedulepath3msk;
|
||||
|
||||
_vifT extern bool vifWrite32(u32 mem, u32 value);
|
||||
|
||||
extern void vif0Interrupt();
|
||||
extern void vif0Write32(u32 mem, u32 value);
|
||||
extern void vif0Reset();
|
||||
|
||||
extern void vif1Interrupt();
|
||||
extern void Vif1MskPath3();
|
||||
extern void vif1Write32(u32 mem, u32 value);
|
||||
extern void vif1Reset();
|
||||
|
||||
typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data);
|
||||
|
|
|
@ -135,10 +135,10 @@ _vifT static __fi bool vifTransfer(u32 *data, int size) {
|
|||
|
||||
transferred = transferred >> 2;
|
||||
|
||||
vifXch->madr +=(transferred << 4);
|
||||
vifXch->qwc -= transferred;
|
||||
vifXch.madr +=(transferred << 4);
|
||||
vifXch.qwc -= transferred;
|
||||
|
||||
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress &= ~0x1;
|
||||
if (!vifXch.qwc && !vifX.irqoffset) vifX.inprogress &= ~0x1;
|
||||
|
||||
if (vifX.irq && vifX.cmd == 0) {
|
||||
//DevCon.WriteLn("Vif IRQ!");
|
||||
|
@ -148,7 +148,7 @@ _vifT static __fi bool vifTransfer(u32 *data, int size) {
|
|||
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E?
|
||||
}
|
||||
|
||||
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress &= ~1;
|
||||
if (!vifXch.qwc && !vifX.irqoffset) vifX.inprogress &= ~1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ _vifT void vifUnpackSetup(const u32 *data) {
|
|||
}
|
||||
|
||||
u32 addr = vifXRegs->code;
|
||||
if (idx && ((addr>>15)&1)) addr += vif1Regs->tops;
|
||||
if (idx && ((addr>>15)&1)) addr += vif1Regs.tops;
|
||||
vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0);
|
||||
|
||||
VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size);
|
||||
|
|
|
@ -26,12 +26,12 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size) {
|
|||
|
||||
if (VIFdmanum == 0) {
|
||||
VU = &VU0;
|
||||
vifRegs = vif0Regs;
|
||||
vifRegs = &vif0Regs;
|
||||
vif = &vif0;
|
||||
}
|
||||
else {
|
||||
VU = &VU1;
|
||||
vifRegs = vif1Regs;
|
||||
vifRegs = &vif1Regs;
|
||||
vif = &vif1;
|
||||
}
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ static __fi void gsHandler(const u8* pMem)
|
|||
// games must take care to ensure transfer rectangles are exact multiples of a qword
|
||||
vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7;
|
||||
//DevCon.Warning("GS download in progress");
|
||||
gifRegs->stat.OPH = true;
|
||||
gifRegs.stat.OPH = true;
|
||||
}
|
||||
}
|
||||
if (reg >= 0x60)
|
||||
|
@ -602,7 +602,7 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
else GSTransferStatus.PTH2 = TRANSFER_MODE;
|
||||
break;
|
||||
case GIF_PATH_3:
|
||||
if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE)
|
||||
{
|
||||
GSTransferStatus.PTH3 = IDLE_MODE;
|
||||
|
||||
|
@ -618,8 +618,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
}
|
||||
if(GSTransferStatus.PTH3 < PENDINGSTOP_MODE || pathidx != 2)
|
||||
{
|
||||
gifRegs->stat.OPH = true;
|
||||
gifRegs->stat.APATH = pathidx + 1;
|
||||
gifRegs.stat.OPH = true;
|
||||
gifRegs.stat.APATH = pathidx + 1;
|
||||
}
|
||||
|
||||
if(pathidx == GIF_PATH_3)
|
||||
|
@ -645,8 +645,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
|
||||
break;
|
||||
}
|
||||
gifRegs->stat.APATH = pathidx + 1;
|
||||
gifRegs->stat.OPH = true;
|
||||
gifRegs.stat.APATH = pathidx + 1;
|
||||
gifRegs.stat.OPH = true;
|
||||
|
||||
switch(tag.FLG) {
|
||||
case GIF_FLG_PACKED:
|
||||
|
@ -809,10 +809,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
// FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active
|
||||
// drawing *and* image transfer actions must be finished before the IRQ raises.
|
||||
|
||||
if(gifRegs->stat.P1Q || gifRegs->stat.P2Q || gifRegs->stat.P3Q)
|
||||
if(gifRegs.stat.P1Q || gifRegs.stat.P2Q || gifRegs.stat.P3Q)
|
||||
{
|
||||
//GH3 and possibly others have path data queued waiting for another path to finish! we need to check they are done too
|
||||
//DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.P3Q);
|
||||
//DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.P3Q);
|
||||
}
|
||||
else if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
|
||||
{
|
||||
|
@ -835,8 +835,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
|
||||
if (tag.EOP && nloop == 0) {
|
||||
|
||||
/*if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;*/
|
||||
/*if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;*/
|
||||
switch(pathidx)
|
||||
{
|
||||
case GIF_PATH_1:
|
||||
|
@ -849,10 +849,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
//For huge chunks we may have delay problems, so we need to stall it till the interrupt, else we get desync (Lemmings)
|
||||
if(size > 8) GSTransferStatus.PTH3 = PENDINGSTOP_MODE;
|
||||
else GSTransferStatus.PTH3 = STOPPED_MODE;
|
||||
if (gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
|
||||
if (gifch.chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
|
||||
//GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3);
|
||||
gif->madr += size * 16;
|
||||
gif->qwc -= size;
|
||||
gifch.madr += size * 16;
|
||||
gifch.qwc -= size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -860,10 +860,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
|
|||
else if(pathidx == 2)
|
||||
{
|
||||
//if(nloop <= 16 && GSTransferStatus.PTH3 == IMAGE_MODE)GSTransferStatus.PTH3 = PENDINGIMAGE_MODE;
|
||||
if (gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
|
||||
if (gifch.chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
|
||||
//GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3);
|
||||
gif->madr += size * 16;
|
||||
gif->qwc -= size;
|
||||
gifch.madr += size * 16;
|
||||
gifch.qwc -= size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Hw.h"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// IsPageFor() / iswitch() / icase() [macros!]
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Page-granulated switch helpers: In order for the compiler to optimize hardware register
|
||||
// handlers, which dispatch registers along a series of switches, the compiler needs to know
|
||||
// that the case entry applies to the current page only. Under MSVC, I tried all manners of
|
||||
// bitmasks against the templated page value, and this was the only one that worked:
|
||||
//
|
||||
// Note: MSVC 2008 actually fails to optimize "switch" properly due to being overly aggressive
|
||||
// about trying to use its clever BSP-tree logic for long switches. It adds the BSP tree logic,
|
||||
// even though most of the "tree" is empty (resulting in several compare/jumps that do nothing).
|
||||
// Explained: Even though only one or two of the switch entires are valid, MSVC will still
|
||||
// compile in its BSP tree check (which divides the switch into 2 or 4 ranges of values). Three
|
||||
// of the ranges just link to "RET", while the fourth range contains the handler for the one
|
||||
// register operation contained in the templated page.
|
||||
|
||||
#define IsPageFor(_mem) ((page<<12) == (_mem&(0xf<<12)))
|
||||
#define icase(ugh) if(IsPageFor(ugh) && (mem==ugh))
|
||||
#define iswitch(mem)
|
||||
|
||||
// hw read functions
|
||||
template< uint page > extern mem8_t __fastcall hwRead8 (u32 mem);
|
||||
template< uint page > extern mem16_t __fastcall hwRead16 (u32 mem);
|
||||
template< uint page > extern mem32_t __fastcall hwRead32 (u32 mem);
|
||||
template< uint page > extern void __fastcall hwRead64 (u32 mem, mem64_t* out );
|
||||
template< uint page > extern void __fastcall hwRead128(u32 mem, mem128_t* out);
|
||||
|
||||
// Internal hwRead32 which does not log reads, used by hwWrite8/16 to perform
|
||||
// read-modify-write operations.
|
||||
template< uint page, bool intcstathack >
|
||||
mem32_t __fastcall _hwRead32(u32 mem);
|
||||
|
||||
extern mem16_t __fastcall hwRead16_page_0F_INTC_HACK(u32 mem);
|
||||
extern mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem);
|
||||
|
||||
|
||||
// hw write functions
|
||||
template<uint page> extern void __fastcall hwWrite8 (u32 mem, u8 value);
|
||||
template<uint page> extern void __fastcall hwWrite16 (u32 mem, u16 value);
|
||||
|
||||
template<uint page> extern void __fastcall hwWrite32 (u32 mem, mem32_t value);
|
||||
template<uint page> extern void __fastcall hwWrite64 (u32 mem, const mem64_t* srcval);
|
||||
template<uint page> extern void __fastcall hwWrite128(u32 mem, const mem128_t* srcval);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Hardware FIFOs (128 bit access only!)
|
||||
// --------------------------------------------------------------------------------------
|
||||
// VIF0 -- 0x10004000 -- eeHw[0x4000]
|
||||
// VIF1 -- 0x10005000 -- eeHw[0x5000]
|
||||
// GIF -- 0x10006000 -- eeHw[0x6000]
|
||||
// IPUout -- 0x10007000 -- eeHw[0x7000]
|
||||
// IPUin -- 0x10007010 -- eeHw[0x7010]
|
||||
|
||||
extern void __fastcall ReadFIFO_VIF1(mem128_t* out);
|
||||
extern void __fastcall ReadFIFO_IPUout(mem128_t* out);
|
||||
|
||||
extern void __fastcall WriteFIFO_VIF0(const mem128_t* value);
|
||||
extern void __fastcall WriteFIFO_VIF1(const mem128_t* value);
|
||||
extern void __fastcall WriteFIFO_GIF(const mem128_t* value);
|
||||
extern void __fastcall WriteFIFO_IPUin(const mem128_t* value);
|
|
@ -51,28 +51,28 @@ mem8_t __fastcall iopHwRead8_Page1( u32 addr )
|
|||
default:
|
||||
if( masked_addr >= 0x100 && masked_addr < 0x130 )
|
||||
{
|
||||
DevCon.Warning( "HwRead8 from Counter16 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
DevCon.Warning( "HwRead8 from Counter16 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
ret = psxHu8( addr );
|
||||
}
|
||||
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
|
||||
{
|
||||
DevCon.Warning( "HwRead8 from Counter32 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
DevCon.Warning( "HwRead8 from Counter32 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
ret = psxHu8( addr );
|
||||
}
|
||||
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
|
||||
{
|
||||
ret = USBread8( addr );
|
||||
PSXHW_LOG( "HwRead8 from USB, addr 0x%08x = 0x%02x", addr, ret );
|
||||
PSXHW_LOG( "HwRead8 from USB @ 0x%08x = 0x%02x", addr, ret );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = psxHu8(addr);
|
||||
PSXUnkHW_LOG( "HwRead8 from Unknown, addr 0x%08x = 0x%02x", addr, ret );
|
||||
PSXUnkHW_LOG( "HwRead8 from Unknown @ 0x%08x = 0x%02x", addr, ret );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IopHwTraceLog<mem8_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem8_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ mem8_t __fastcall iopHwRead8_Page3( u32 addr )
|
|||
else
|
||||
ret = psxHu8( addr );
|
||||
|
||||
IopHwTraceLog<mem8_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem8_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ mem8_t __fastcall iopHwRead8_Page8( u32 addr )
|
|||
else
|
||||
ret = psxHu8( addr );
|
||||
|
||||
IopHwTraceLog<mem8_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem8_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
|
|||
ret = SPU2read( addr );
|
||||
else
|
||||
{
|
||||
DevCon.Warning( "HwRead32 from SPU2? (addr=0x%08X) .. What manner of trickery is this?!", addr );
|
||||
DbgCon.Warning( "HwRead32 from SPU2? @ 0x%08X .. What manner of trickery is this?!", addr );
|
||||
ret = psxHu32(addr);
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
|
|||
}
|
||||
}
|
||||
|
||||
IopHwTraceLog<T>( addr, ret, "Read" );
|
||||
IopHwTraceLog<T>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,7 @@ mem16_t __fastcall iopHwRead16_Page3( u32 addr )
|
|||
jASSUME( (addr >> 12) == 0x1f803 );
|
||||
|
||||
mem16_t ret = psxHu16(addr);
|
||||
IopHwTraceLog<mem16_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem16_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ mem16_t __fastcall iopHwRead16_Page8( u32 addr )
|
|||
jASSUME( (addr >> 12) == 0x1f808 );
|
||||
|
||||
mem16_t ret = psxHu16(addr);
|
||||
IopHwTraceLog<mem16_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem16_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,7 @@ mem32_t __fastcall iopHwRead32_Page3( u32 addr )
|
|||
// all addresses are assumed to be prefixed with 0x1f803xxx:
|
||||
jASSUME( (addr >> 12) == 0x1f803 );
|
||||
const mem32_t ret = psxHu32(addr);
|
||||
IopHwTraceLog<mem32_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem32_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ mem32_t __fastcall iopHwRead32_Page8( u32 addr )
|
|||
}
|
||||
else ret = psxHu32(addr);
|
||||
|
||||
IopHwTraceLog<mem32_t>( addr, ret, "Read" );
|
||||
IopHwTraceLog<mem32_t>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ template< typename T >
|
|||
static __fi void _generic_write( u32 addr, T val )
|
||||
{
|
||||
//int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 );
|
||||
IopHwTraceLog<T>( addr, val, "Write" );
|
||||
IopHwTraceLog<T>( addr, val, false );
|
||||
psxHu(addr) = val;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ static __fi T _generic_read( u32 addr )
|
|||
//int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 );
|
||||
|
||||
T ret = psxHu(addr);
|
||||
IopHwTraceLog<T>( addr, ret, "Read" );
|
||||
IopHwTraceLog<T>( addr, ret, true );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -84,12 +84,12 @@ void __fastcall iopHwWrite8_Page1( u32 addr, mem8_t val )
|
|||
default:
|
||||
if( masked_addr >= 0x100 && masked_addr < 0x130 )
|
||||
{
|
||||
DevCon.Warning( "HwWrite8 to Counter16 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
DbgCon.Warning( "HwWrite8 to Counter16 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
psxHu8( addr ) = val;
|
||||
}
|
||||
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
|
||||
{
|
||||
DevCon.Warning( "HwWrite8 to Counter32 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
DbgCon.Warning( "HwWrite8 to Counter32 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
|
||||
psxHu8( addr ) = val;
|
||||
}
|
||||
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
|
||||
|
@ -103,7 +103,7 @@ void __fastcall iopHwWrite8_Page1( u32 addr, mem8_t val )
|
|||
break;
|
||||
}
|
||||
|
||||
IopHwTraceLog<mem8_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem8_t>( addr, val, false );
|
||||
}
|
||||
|
||||
void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val )
|
||||
|
@ -137,7 +137,7 @@ void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val )
|
|||
}
|
||||
|
||||
psxHu8( addr ) = val;
|
||||
IopHwTraceLog<mem8_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem8_t>( addr, val, false );
|
||||
}
|
||||
|
||||
void __fastcall iopHwWrite8_Page8( u32 addr, mem8_t val )
|
||||
|
@ -150,7 +150,7 @@ void __fastcall iopHwWrite8_Page8( u32 addr, mem8_t val )
|
|||
else
|
||||
psxHu8( addr ) = val;
|
||||
|
||||
IopHwTraceLog<mem8_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem8_t>( addr, val, false );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -244,7 +244,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
|
|||
SPU2write( addr, val );
|
||||
else
|
||||
{
|
||||
DevCon.Warning( "HwWrite32 to SPU2? (addr=0x%08X) .. What manner of trickery is this?!", addr );
|
||||
DbgCon.Warning( "HwWrite32 to SPU2? @ 0x%08X .. What manner of trickery is this?!", addr );
|
||||
//psxHu(addr) = val;
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
|
|||
}
|
||||
}
|
||||
|
||||
IopHwTraceLog<T>( addr, val, "Write" );
|
||||
IopHwTraceLog<T>( addr, val, false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -497,7 +497,7 @@ void __fastcall iopHwWrite16_Page3( u32 addr, mem16_t val )
|
|||
// all addresses are assumed to be prefixed with 0x1f803xxx:
|
||||
pxAssert( (addr >> 12) == 0x1f803 );
|
||||
psxHu16(addr) = val;
|
||||
IopHwTraceLog<mem16_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem16_t>( addr, val, false );
|
||||
}
|
||||
|
||||
void __fastcall iopHwWrite16_Page8( u32 addr, mem16_t val )
|
||||
|
@ -505,7 +505,7 @@ void __fastcall iopHwWrite16_Page8( u32 addr, mem16_t val )
|
|||
// all addresses are assumed to be prefixed with 0x1f808xxx:
|
||||
pxAssert( (addr >> 12) == 0x1f808 );
|
||||
psxHu16(addr) = val;
|
||||
IopHwTraceLog<mem16_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem16_t>( addr, val, false );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -520,7 +520,7 @@ void __fastcall iopHwWrite32_Page3( u32 addr, mem32_t val )
|
|||
// all addresses are assumed to be prefixed with 0x1f803xxx:
|
||||
pxAssert( (addr >> 12) == 0x1f803 );
|
||||
psxHu16(addr) = val;
|
||||
IopHwTraceLog<mem32_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem32_t>( addr, val, false );
|
||||
}
|
||||
|
||||
void __fastcall iopHwWrite32_Page8( u32 addr, mem32_t val )
|
||||
|
@ -567,7 +567,7 @@ void __fastcall iopHwWrite32_Page8( u32 addr, mem32_t val )
|
|||
}
|
||||
else psxHu32(addr) = val;
|
||||
|
||||
IopHwTraceLog<mem32_t>( addr, val, "Write" );
|
||||
IopHwTraceLog<mem32_t>( addr, val, false );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Internal {
|
|||
//
|
||||
|
||||
template< typename T>
|
||||
static __ri const char* _log_GetIopHwName( u32 addr, T val )
|
||||
static __ri const char* _ioplog_GetHwName( u32 addr, T val )
|
||||
{
|
||||
switch( addr )
|
||||
{
|
||||
|
@ -200,20 +200,31 @@ static __ri const char* _log_GetIopHwName( u32 addr, T val )
|
|||
}
|
||||
|
||||
template< typename T>
|
||||
static __ri void IopHwTraceLog( u32 addr, T val, const char* modestr )
|
||||
static __ri void IopHwTraceLog( u32 addr, T val, bool mode )
|
||||
{
|
||||
if( !EmuConfig.Trace.IOP.m_EnableRegisters ) return;
|
||||
if (!IsDevBuild) return;
|
||||
if (!EmuConfig.Trace.IOP.m_EnableRegisters) return;
|
||||
|
||||
static char *temp = "Hw%s%d from %s, addr 0x%08x = 0x%0*x";
|
||||
FastFormatAscii valStr;
|
||||
FastFormatAscii labelStr;
|
||||
labelStr.Write("Hw%s%u", mode ? "Read" : "Write", sizeof (T) * 8);
|
||||
|
||||
// Replace the * above with the operand size (this ensures nicely formatted
|
||||
// zero-fill hex values):
|
||||
temp[(sizeof temp)-3] = '0' + (sizeof(T)*2);
|
||||
switch( sizeof T )
|
||||
{
|
||||
case 1: valStr.Write("0x%02x", val); break;
|
||||
case 2: valStr.Write("0x%04x", val); break;
|
||||
case 4: valStr.Write("0x%08x", val); break;
|
||||
|
||||
if( const char* regname = _log_GetIopHwName<T>( addr, val ) )
|
||||
PSXHW_LOG( temp, modestr, (sizeof (T)) * 8, regname, addr, val );
|
||||
case 8: valStr.Write("0x%08x.%08x", ((u32*)&val)[1], ((u32*)&val)[0]); break;
|
||||
case 16: ((u128&)val).WriteTo(valStr);
|
||||
}
|
||||
|
||||
static const char* temp = "%-12s @ 0x%08X/%-16s %s %s";
|
||||
|
||||
if( const char* regname = _ioplog_GetHwName<T>( addr, val ) )
|
||||
PSXHW_LOG( temp, labelStr.c_str(), addr, regname, mode ? "->" : "<-", valStr.c_str() );
|
||||
else
|
||||
PSXUnkHW_LOG( temp, modestr, (sizeof (T)) * 8, "Unknown", addr, val );
|
||||
PSXUnkHW_LOG( temp, labelStr.c_str(), addr, "Unknown", mode ? "->" : "<-", valStr.c_str() );
|
||||
}
|
||||
|
||||
} };
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Common.h"
|
||||
#include "Hardware.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
|
||||
// Returns true if the DMA is enabled and executed successfully. Returns false if execution
|
||||
// was blocked (DMAE or master DMA enabler).
|
||||
static bool QuickDmaExec( void (*func)(), u32 mem)
|
||||
{
|
||||
bool ret = false;
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
func();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static tDMAC_QUEUE QueuedDMA(0);
|
||||
static u32 oldvalue = 0;
|
||||
|
||||
static void StartQueuedDMA()
|
||||
{
|
||||
if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); QueuedDMA.VIF0 = !QuickDmaExec(dmaVIF0, D0_CHCR); }
|
||||
if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); QueuedDMA.VIF1 = !QuickDmaExec(dmaVIF1, D1_CHCR); }
|
||||
if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); QueuedDMA.GIF = !QuickDmaExec(dmaGIF , D2_CHCR); }
|
||||
if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); QueuedDMA.IPU0 = !QuickDmaExec(dmaIPU0, D3_CHCR); }
|
||||
if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); QueuedDMA.IPU1 = !QuickDmaExec(dmaIPU1, D4_CHCR); }
|
||||
if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); QueuedDMA.SIF0 = !QuickDmaExec(dmaSIF0, D5_CHCR); }
|
||||
if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); QueuedDMA.SIF1 = !QuickDmaExec(dmaSIF1, D6_CHCR); }
|
||||
if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); QueuedDMA.SIF2 = !QuickDmaExec(dmaSIF2, D7_CHCR); }
|
||||
if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); QueuedDMA.SPR0 = !QuickDmaExec(dmaSPR0, D8_CHCR); }
|
||||
if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); QueuedDMA.SPR1 = !QuickDmaExec(dmaSPR1, D9_CHCR); }
|
||||
}
|
||||
|
||||
static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
|
||||
{
|
||||
DMACh *reg = &psH_DMACh(mem);
|
||||
tDMA_CHCR chcr(value);
|
||||
|
||||
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
|
||||
if (reg->chcr.STR)
|
||||
{
|
||||
const uint channel = ChannelNumber(mem);
|
||||
|
||||
if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
|
||||
{
|
||||
//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
|
||||
if(channel == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(channel == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( channel );
|
||||
QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
//Sanity Check for possible future bug fix0rs ;p
|
||||
//Spams on Persona 4 opening.
|
||||
//if(reg->chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
|
||||
//Here we update the LOWER CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode
|
||||
//But we need to preserve the existing tag for now
|
||||
reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
|
||||
return;
|
||||
}
|
||||
else //Else the DMA is running (Not Suspended), so we cant touch it!
|
||||
{
|
||||
//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
|
||||
//Also "The DMA may not stop properly just by writing 0 to STR"
|
||||
//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
|
||||
|
||||
if(chcr.STR == 0)
|
||||
{
|
||||
//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
|
||||
reg->chcr.STR = 0;
|
||||
//We need to clear any existing DMA loops that are in progress else they will continue!
|
||||
|
||||
if(channel == 1)
|
||||
{
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(channel == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
|
||||
cpuClearInt( channel );
|
||||
QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg->chcr._u32, chcr._u32, reg->qwc);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if(reg->chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
|
||||
|
||||
reg->chcr.set(value);
|
||||
|
||||
if (reg->chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
|
||||
{
|
||||
func();
|
||||
}
|
||||
else if(reg->chcr.STR)
|
||||
{
|
||||
//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
|
||||
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
|
||||
} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
|
||||
}
|
||||
|
||||
// DmaExec8 should only be called for the second byte of CHCR.
|
||||
// Testing Note: dark cloud 2 uses 8 bit DMAs register writes.
|
||||
static __fi void DmaExec8( void (*func)(), u32 mem, u8 value )
|
||||
{
|
||||
pxAssumeMsg( (mem & 0xf) == 1, "DmaExec8 should only be called for the second byte of CHCR" );
|
||||
|
||||
// The calling function calls this when the second byte (bits 8->15) is written. Only bit 8
|
||||
// is effective, and it is the STR (start) bit. :)
|
||||
DmaExec( func, mem & ~0xf, (u32)value<<8 );
|
||||
}
|
||||
|
||||
static __fi void DmaExec16( void (*func)(), u32 mem, u16 value )
|
||||
{
|
||||
DmaExec( func, mem, (u32)value );
|
||||
}
|
||||
|
||||
__fi u32 dmacRead32( u32 mem )
|
||||
{
|
||||
// Fixme: OPH hack. Toggle the flag on each GIF_STAT access. (rama)
|
||||
}
|
||||
|
||||
// Returns TRUE if the caller should do writeback of the register to eeHw; false if the
|
||||
// register has no writeback, or if the writeback is handled internally.
|
||||
template< uint page >
|
||||
__fi bool dmacWrite32( u32 mem, mem32_t& value )
|
||||
{
|
||||
if (IsPageFor(EEMemoryMap::VIF0_Start) && (mem >= EEMemoryMap::VIF0_Start))
|
||||
{
|
||||
return (mem >= EEMemoryMap::VIF1_Start)
|
||||
? vifWrite32<1>(mem, value)
|
||||
: vifWrite32<0>(mem, value);
|
||||
}
|
||||
|
||||
iswitch(mem) {
|
||||
icase(GIF_CTRL)
|
||||
{
|
||||
psHu32(mem) = value & 0x8;
|
||||
|
||||
if (value & 0x1)
|
||||
gsGIFReset();
|
||||
|
||||
if (value & 8)
|
||||
gifRegs.stat.PSE = true;
|
||||
else
|
||||
gifRegs.stat.PSE = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(GIF_MODE)
|
||||
{
|
||||
// need to set GIF_MODE (hamster ball)
|
||||
gifRegs.mode.write(value);
|
||||
|
||||
// set/clear bits 0 and 2 as per the GIF_MODE value.
|
||||
const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
|
||||
psHu32(GIF_STAT) &= ~bitmask;
|
||||
psHu32(GIF_STAT) |= (u32)value & bitmask;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D0_CHCR) // dma0 - vif0
|
||||
{
|
||||
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaVIF0, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D1_CHCR) // dma1 - vif1 - chcr
|
||||
{
|
||||
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaVIF1, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D2_CHCR) // dma2 - gif
|
||||
{
|
||||
DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaGIF, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D3_CHCR) // dma3 - fromIPU
|
||||
{
|
||||
DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
|
||||
DmaExec(dmaIPU0, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D4_CHCR) // dma4 - toIPU
|
||||
{
|
||||
DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
|
||||
DmaExec(dmaIPU1, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D5_CHCR) // dma5 - sif0
|
||||
{
|
||||
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaSIF0, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D6_CHCR) // dma6 - sif1
|
||||
{
|
||||
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaSIF1, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D7_CHCR) // dma7 - sif2
|
||||
{
|
||||
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
|
||||
DmaExec(dmaSIF2, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D8_CHCR) // dma8 - fromSPR
|
||||
{
|
||||
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
|
||||
DmaExec(dmaSPR0, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(D9_CHCR) // dma9 - toSPR
|
||||
{
|
||||
DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
|
||||
DmaExec(dmaSPR1, mem, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(DMAC_CTRL)
|
||||
{
|
||||
u32 oldvalue = psHu32(mem);
|
||||
|
||||
HW_LOG("DMAC_CTRL Write 32bit %x", value);
|
||||
|
||||
psHu32(mem) = value;
|
||||
//Check for DMAS that were started while the DMAC was disabled
|
||||
if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
if ((oldvalue & 0x30) != (value & 0x30))
|
||||
{
|
||||
DevCon.Warning("32bit Stall Source Changed to %x", (value & 0x30) >> 4);
|
||||
}
|
||||
if ((oldvalue & 0xC0) != (value & 0xC0))
|
||||
{
|
||||
DevCon.Warning("32bit Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(DMAC_STAT)
|
||||
{
|
||||
HW_LOG("DMAC_STAT Write 32bit %x", value);
|
||||
|
||||
// lower 16 bits: clear on 1
|
||||
// upper 16 bits: reverse on 1
|
||||
|
||||
psHu16(0xe010) &= ~(value & 0xffff);
|
||||
psHu16(0xe012) ^= (u16)(value >> 16);
|
||||
|
||||
cpuTestDMACInts();
|
||||
return false;
|
||||
}
|
||||
|
||||
icase(DMAC_ENABLEW)
|
||||
{
|
||||
HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
|
||||
oldvalue = psHu8(DMAC_ENABLEW + 2);
|
||||
psHu32(DMAC_ENABLEW) = value;
|
||||
psHu32(DMAC_ENABLER) = value;
|
||||
if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
|
||||
{
|
||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// fall-through: use the default writeback provided by caller.
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool dmacWrite32<0x00>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x01>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x02>( u32 mem, mem32_t& value );
|
||||
|
||||
template bool dmacWrite32<0x03>( u32 mem, mem32_t& value );
|
||||
|
||||
template bool dmacWrite32<0x04>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x05>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x06>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x07>( u32 mem, mem32_t& value );
|
||||
|
||||
template bool dmacWrite32<0x08>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x09>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x0a>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x0b>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x0c>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x0d>( u32 mem, mem32_t& value );
|
||||
template bool dmacWrite32<0x0e>( u32 mem, mem32_t& value );
|
||||
|
||||
template bool dmacWrite32<0x0f>( u32 mem, mem32_t& value );
|
|
@ -0,0 +1,268 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
template< typename T>
|
||||
static __ri const char* _eelog_GetHwName( u32 addr, T val )
|
||||
{
|
||||
#define EasyCase(label) case label: return #label
|
||||
|
||||
switch( addr )
|
||||
{
|
||||
// Counters!
|
||||
EasyCase(RCNT0_COUNT);
|
||||
EasyCase(RCNT0_MODE);
|
||||
EasyCase(RCNT0_TARGET);
|
||||
EasyCase(RCNT0_HOLD);
|
||||
|
||||
EasyCase(RCNT1_COUNT);
|
||||
EasyCase(RCNT1_MODE);
|
||||
EasyCase(RCNT1_TARGET);
|
||||
EasyCase(RCNT1_HOLD);
|
||||
|
||||
EasyCase(RCNT2_COUNT);
|
||||
EasyCase(RCNT2_MODE);
|
||||
EasyCase(RCNT2_TARGET);
|
||||
|
||||
EasyCase(RCNT3_COUNT);
|
||||
EasyCase(RCNT3_MODE);
|
||||
EasyCase(RCNT3_TARGET);
|
||||
|
||||
// IPU!
|
||||
EasyCase(IPU_CMD);
|
||||
EasyCase(IPU_CTRL);
|
||||
EasyCase(IPU_BP);
|
||||
EasyCase(IPU_TOP);
|
||||
|
||||
// GIF!
|
||||
EasyCase(GIF_CTRL);
|
||||
EasyCase(GIF_MODE);
|
||||
EasyCase(GIF_STAT);
|
||||
EasyCase(GIF_TAG0);
|
||||
EasyCase(GIF_TAG1);
|
||||
EasyCase(GIF_TAG2);
|
||||
EasyCase(GIF_TAG3);
|
||||
EasyCase(GIF_CNT);
|
||||
EasyCase(GIF_P3CNT);
|
||||
EasyCase(GIF_P3TAG);
|
||||
|
||||
// VIF!
|
||||
EasyCase(VIF0_STAT);
|
||||
EasyCase(VIF0_FBRST);
|
||||
EasyCase(VIF0_ERR);
|
||||
EasyCase(VIF0_MARK);
|
||||
EasyCase(VIF0_CYCLE);
|
||||
EasyCase(VIF0_MODE);
|
||||
EasyCase(VIF0_NUM);
|
||||
EasyCase(VIF0_MASK);
|
||||
EasyCase(VIF0_CODE);
|
||||
EasyCase(VIF0_ITOPS);
|
||||
EasyCase(VIF0_ITOP);
|
||||
EasyCase(VIF0_TOP);
|
||||
EasyCase(VIF0_ROW0);
|
||||
EasyCase(VIF0_ROW1);
|
||||
EasyCase(VIF0_ROW2);
|
||||
EasyCase(VIF0_ROW3);
|
||||
EasyCase(VIF0_COL0);
|
||||
EasyCase(VIF0_COL1);
|
||||
EasyCase(VIF0_COL2);
|
||||
EasyCase(VIF0_COL3);
|
||||
|
||||
EasyCase(VIF1_STAT);
|
||||
EasyCase(VIF1_FBRST);
|
||||
EasyCase(VIF1_ERR);
|
||||
EasyCase(VIF1_MARK);
|
||||
EasyCase(VIF1_CYCLE);
|
||||
EasyCase(VIF1_MODE);
|
||||
EasyCase(VIF1_NUM);
|
||||
EasyCase(VIF1_MASK);
|
||||
EasyCase(VIF1_CODE);
|
||||
EasyCase(VIF1_ITOPS);
|
||||
EasyCase(VIF1_BASE);
|
||||
EasyCase(VIF1_OFST);
|
||||
EasyCase(VIF1_TOPS);
|
||||
EasyCase(VIF1_ITOP);
|
||||
EasyCase(VIF1_TOP);
|
||||
EasyCase(VIF1_ROW0);
|
||||
EasyCase(VIF1_ROW1);
|
||||
EasyCase(VIF1_ROW2);
|
||||
EasyCase(VIF1_ROW3);
|
||||
EasyCase(VIF1_COL0);
|
||||
EasyCase(VIF1_COL1);
|
||||
EasyCase(VIF1_COL2);
|
||||
EasyCase(VIF1_COL3);
|
||||
|
||||
// VIF DMA!
|
||||
EasyCase(VIF0_CHCR);
|
||||
EasyCase(VIF0_MADR);
|
||||
EasyCase(VIF0_QWC);
|
||||
EasyCase(VIF0_TADR);
|
||||
EasyCase(VIF0_ASR0);
|
||||
EasyCase(VIF0_ASR1);
|
||||
|
||||
EasyCase(VIF1_CHCR);
|
||||
EasyCase(VIF1_QWC);
|
||||
EasyCase(VIF1_TADR);
|
||||
EasyCase(VIF1_ASR0);
|
||||
EasyCase(VIF1_ASR1);
|
||||
|
||||
// GIF DMA!
|
||||
EasyCase(GIF_CHCR);
|
||||
EasyCase(GIF_MADR);
|
||||
EasyCase(GIF_QWC);
|
||||
EasyCase(GIF_TADR);
|
||||
EasyCase(GIF_ASR0);
|
||||
EasyCase(GIF_ASR1);
|
||||
|
||||
// IPU DMA!
|
||||
EasyCase(fromIPU_CHCR);
|
||||
EasyCase(fromIPU_MADR);
|
||||
EasyCase(fromIPU_QWC);
|
||||
EasyCase(fromIPU_TADR);
|
||||
|
||||
EasyCase(toIPU_CHCR);
|
||||
EasyCase(toIPU_MADR);
|
||||
EasyCase(toIPU_QWC);
|
||||
EasyCase(toIPU_TADR);
|
||||
|
||||
// SIF DMA!
|
||||
EasyCase(SIF0_CHCR);
|
||||
EasyCase(SIF0_MADR);
|
||||
EasyCase(SIF0_QWC);
|
||||
|
||||
EasyCase(SIF1_CHCR);
|
||||
EasyCase(SIF1_MADR);
|
||||
EasyCase(SIF1_QWC);
|
||||
|
||||
EasyCase(SIF2_CHCR);
|
||||
EasyCase(SIF2_MADR);
|
||||
EasyCase(SIF2_QWC);
|
||||
|
||||
// Scratchpad DMA! (SPRdma)
|
||||
|
||||
EasyCase(fromSPR_CHCR);
|
||||
EasyCase(fromSPR_MADR);
|
||||
EasyCase(fromSPR_QWC);
|
||||
|
||||
EasyCase(toSPR_CHCR);
|
||||
EasyCase(toSPR_MADR);
|
||||
EasyCase(toSPR_QWC);
|
||||
|
||||
// DMAC!
|
||||
EasyCase(DMAC_CTRL);
|
||||
EasyCase(DMAC_STAT);
|
||||
EasyCase(DMAC_PCR);
|
||||
EasyCase(DMAC_SQWC);
|
||||
EasyCase(DMAC_RBSR);
|
||||
EasyCase(DMAC_RBOR);
|
||||
EasyCase(DMAC_STADR);
|
||||
EasyCase(DMAC_ENABLER);
|
||||
EasyCase(DMAC_ENABLEW);
|
||||
|
||||
// INTC!
|
||||
EasyCase(INTC_STAT);
|
||||
EasyCase(INTC_MASK);
|
||||
|
||||
// SIO
|
||||
EasyCase(SIO_LCR);
|
||||
EasyCase(SIO_LSR);
|
||||
EasyCase(SIO_IER);
|
||||
EasyCase(SIO_ISR);
|
||||
EasyCase(SIO_FCR);
|
||||
EasyCase(SIO_BGR);
|
||||
EasyCase(SIO_TXFIFO);
|
||||
EasyCase(SIO_RXFIFO);
|
||||
|
||||
// SBUS (terribly mysterious!)
|
||||
EasyCase(SBUS_F200);
|
||||
EasyCase(SBUS_F210);
|
||||
EasyCase(SBUS_F220);
|
||||
EasyCase(SBUS_F230);
|
||||
EasyCase(SBUS_F240);
|
||||
EasyCase(SBUS_F250);
|
||||
EasyCase(SBUS_F260);
|
||||
|
||||
// MCH (vaguely mysterious!)
|
||||
EasyCase(MCH_RICM);
|
||||
EasyCase(MCH_DRD);
|
||||
}
|
||||
|
||||
#define EasyZone(zone) \
|
||||
if ((addr >= EEMemoryMap::zone##_Start) && (addr < EEMemoryMap::zone##_End)) return #zone
|
||||
|
||||
#define EasyZoneR(zone) \
|
||||
EasyZone(zone) "_reserved"
|
||||
|
||||
// Nothing discovered/handled : Check for "zoned" registers -- registers mirrored
|
||||
// across large sections of memory (FIFOs mainly).
|
||||
|
||||
EasyZone(VIF0_FIFO); EasyZone(VIF1_FIFO); EasyZone(GIF_FIFO);
|
||||
|
||||
if( (addr >= EEMemoryMap::IPU_FIFO_Start) && (addr < EEMemoryMap::IPU_FIFO_End) )
|
||||
{
|
||||
return (addr & 0x10) ? "IPUin_FIFO" : "IPUout_FIFO";
|
||||
}
|
||||
|
||||
// Check for "reserved" regions -- registers that most likely discard writes and
|
||||
// return 0 when read. To assist in having useful logs, we determine the general
|
||||
// "zone" of the register address and return the zone name in the unknown string.
|
||||
|
||||
EasyZoneR(RCNT0); EasyZoneR(RCNT1);
|
||||
EasyZoneR(RCNT2); EasyZoneR(RCNT3);
|
||||
|
||||
EasyZoneR(IPU); EasyZoneR(GIF);
|
||||
EasyZoneR(VIF0); EasyZoneR(VIF1);
|
||||
EasyZoneR(VIF0dma); EasyZoneR(VIF1dma);
|
||||
EasyZoneR(GIFdma); EasyZoneR(fromIPU); EasyZoneR(toIPU);
|
||||
EasyZoneR(SIF0dma); EasyZoneR(SIF1dma); EasyZoneR(SIF2dma);
|
||||
EasyZoneR(fromSPR); EasyZoneR(toSPR);
|
||||
|
||||
EasyZoneR(DMAC); EasyZoneR(INTC);
|
||||
EasyZoneR(SIO); EasyZoneR(SBUS);
|
||||
EasyZoneR(MCH); EasyZoneR(DMACext);
|
||||
|
||||
// If we get this far it's an *unknown* register; plain and simple.
|
||||
|
||||
return NULL; //"Unknown";
|
||||
}
|
||||
|
||||
template< typename T>
|
||||
static __ri void eeHwTraceLog( u32 addr, T val, bool mode )
|
||||
{
|
||||
if (!IsDevBuild) return;
|
||||
if (!EmuConfig.Trace.EE.m_EnableRegisters) return;
|
||||
|
||||
FastFormatAscii valStr;
|
||||
FastFormatAscii labelStr;
|
||||
labelStr.Write("Hw%s%u", mode ? "Read" : "Write", sizeof (T) * 8);
|
||||
|
||||
switch( sizeof T )
|
||||
{
|
||||
case 1: valStr.Write("0x%02x", val); break;
|
||||
case 2: valStr.Write("0x%04x", val); break;
|
||||
case 4: valStr.Write("0x%08x", val); break;
|
||||
|
||||
case 8: valStr.Write("0x%08x.%08x", ((u32*)&val)[1], ((u32*)&val)[0]); break;
|
||||
case 16: ((u128&)val).WriteTo(valStr);
|
||||
}
|
||||
|
||||
static const char* temp = "%-12s @ 0x%08X/%-16s %s %s";
|
||||
|
||||
if( const char* regname = _eelog_GetHwName<T>( addr, val ) )
|
||||
HW_LOG( temp, labelStr.c_str(), addr, regname, mode ? "->" : "<-", valStr.c_str() );
|
||||
else
|
||||
UnknownHW_LOG( temp, labelStr.c_str(), addr, "Unknown", mode ? "->" : "<-", valStr.c_str() );
|
||||
}
|
|
@ -50,13 +50,13 @@ s32 PrepareEERead()
|
|||
{
|
||||
case TAG_REFE:
|
||||
sif0.ee.end = true;
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
if (dmacRegs.ctrl.STS != NO_STS)
|
||||
dmacRegs.stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_REFS:
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
if (dmacRegs.ctrl.STS != NO_STS)
|
||||
dmacRegs.stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_END:
|
||||
|
|
|
@ -513,6 +513,10 @@
|
|||
RelativePath="..\..\Dmac.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\ps2\eeHwTraceLog.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\FiFo.cpp"
|
||||
>
|
||||
|
@ -529,6 +533,10 @@
|
|||
RelativePath="..\..\Hw.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\ps2\HwInternal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\HwRead.cpp"
|
||||
>
|
||||
|
@ -753,6 +761,10 @@
|
|||
<Filter
|
||||
Name="DMAC"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\ps2\LegacyDmac.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Sif"
|
||||
>
|
||||
|
|
|
@ -21,11 +21,6 @@
|
|||
#include "iR5900.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
//#pragma warning(disable:4244)
|
||||
//#pragma warning(disable:4761)
|
||||
#endif
|
||||
|
||||
namespace R5900 {
|
||||
namespace Dynarec {
|
||||
namespace OpcodeImpl
|
||||
|
|
|
@ -1098,12 +1098,12 @@ void __fastcall mVU_XGKICK_(u32 addr) {
|
|||
u32 diff = 0x400 - addr;
|
||||
u32 size;
|
||||
|
||||
if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true) && SIGNAL_IMR_Pending == false)
|
||||
if(gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.APATH == GIF_APATH3 && gifRegs.stat.IP3 == true) && SIGNAL_IMR_Pending == false)
|
||||
{
|
||||
if(Path1WritePos != 0)
|
||||
{
|
||||
//Flush any pending transfers so things dont go up in the wrong order
|
||||
while(gifRegs->stat.P1Q == true) gsPath1Interrupt();
|
||||
while(gifRegs.stat.P1Q == true) gsPath1Interrupt();
|
||||
}
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_1, 0x400);
|
||||
size = GIFPath_CopyTag(GIF_PATH_1, (u128*)data, diff);
|
||||
|
@ -1111,13 +1111,13 @@ void __fastcall mVU_XGKICK_(u32 addr) {
|
|||
|
||||
if(GSTransferStatus.PTH1 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs.stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff);
|
||||
u8* pDest = &Path1Buffer[Path1WritePos*16];
|
||||
|
||||
|
@ -1134,8 +1134,8 @@ void __fastcall mVU_XGKICK_(u32 addr) {
|
|||
else {
|
||||
memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), size);
|
||||
}
|
||||
//if(!gifRegs->stat.P1Q) CPU_INT(28, 128);
|
||||
gifRegs->stat.P1Q = true;
|
||||
//if(!gifRegs.stat.P1Q) CPU_INT(28, 128);
|
||||
gifRegs.stat.P1Q = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,16 @@ struct mVU_Globals {
|
|||
|
||||
extern const __aligned(32) mVU_Globals mVUglob;
|
||||
|
||||
static const uint _Ibit_ = 1 << 31;
|
||||
static const uint _Ebit_ = 1 << 30;
|
||||
static const uint _Mbit_ = 1 << 29;
|
||||
static const uint _Dbit_ = 1 << 28;
|
||||
static const uint _Tbit_ = 1 << 27;
|
||||
static const uint _DTbit_ = 0; //( _Dbit_ | _Tbit_ ) // ToDo: Implement this stuff...
|
||||
|
||||
static const uint divI = 0x1040000;
|
||||
static const uint divD = 0x2080000;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Helper Macros
|
||||
//------------------------------------------------------------------
|
||||
|
@ -71,29 +81,11 @@ extern const __aligned(32) mVU_Globals mVUglob;
|
|||
#define _Fsf_ ((mVU->code >> 21) & 0x03)
|
||||
#define _Ftf_ ((mVU->code >> 23) & 0x03)
|
||||
|
||||
#if 0
|
||||
#define _Imm5_ (s16)(((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf))
|
||||
#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : (mVU->code & 0x3ff))
|
||||
#define _Imm12_ (((mVU->code >> 21) & 0x1) << 11) | (mVU->code & 0x7ff)
|
||||
#define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff))
|
||||
#define _Imm24_ (u32)(mVU->code & 0xffffff)
|
||||
#else
|
||||
#define _Imm5_ (mVU->Imm5())
|
||||
#define _Imm11_ (mVU->Imm11())
|
||||
#define _Imm12_ (mVU->Imm12())
|
||||
#define _Imm15_ (mVU->Imm15())
|
||||
#define _Imm24_ (mVU->Imm24())
|
||||
#endif
|
||||
|
||||
#define _Ibit_ (1<<31)
|
||||
#define _Ebit_ (1<<30)
|
||||
#define _Mbit_ (1<<29)
|
||||
#define _Dbit_ (1<<28)
|
||||
#define _Tbit_ (1<<27)
|
||||
#define _DTbit_ 0 //( _Dbit_ | _Tbit_ ) // ToDo: Implement this stuff...
|
||||
|
||||
#define divI 0x1040000
|
||||
#define divD 0x2080000
|
||||
|
||||
#define isCOP2 (mVU->cop2 != 0)
|
||||
#define isVU1 (mVU->index != 0)
|
||||
|
@ -208,15 +200,9 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define curI ((u32*)mVU->regs().Micro)[iPC] //mVUcurProg.data[iPC]
|
||||
#define setCode() { mVU->code = curI; }
|
||||
|
||||
#if 0
|
||||
#define incPC(x) { iPC = ((iPC + (x)) & (mVU->progSize-1)); setCode(); }
|
||||
#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
||||
#define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
|
||||
#else
|
||||
#define incPC(x) (mVU->advancePC(x))
|
||||
#define branchAddr mVU->getBranchAddr()
|
||||
#define branchAddrN mVU->getBranchAddrN()
|
||||
#endif
|
||||
|
||||
#define incPC2(x) { iPC = ((iPC + (x)) & mVU->progMemMask); }
|
||||
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8)
|
||||
|
|
|
@ -77,9 +77,9 @@ void resetNewVif(int idx)
|
|||
|
||||
nVif[idx].idx = idx;
|
||||
nVif[idx].VU = idx ? &VU1 : &VU0;
|
||||
nVif[idx].vif = idx ? &vif1 : &vif0;
|
||||
nVif[idx].vifRegs = idx ? vif1Regs : vif0Regs;
|
||||
nVif[idx].vuMemLimit = idx ? 0x3ff0 : 0xff0;
|
||||
nVif[idx].vif = &GetVifX;
|
||||
nVif[idx].vifRegs = vifXRegs;
|
||||
nVif[idx].bSize = 0;
|
||||
memzero(nVif[idx].buffer);
|
||||
|
||||
|
|
|
@ -1982,12 +1982,12 @@ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
|
|||
u32 size;
|
||||
u8* pDest;
|
||||
|
||||
if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true) && SIGNAL_IMR_Pending == false)
|
||||
if(gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.APATH == GIF_APATH3 && gifRegs.stat.IP3 == true) && SIGNAL_IMR_Pending == false)
|
||||
{
|
||||
if(Path1WritePos != 0)
|
||||
{
|
||||
//Flush any pending transfers so things dont go up in the wrong order
|
||||
while(gifRegs->stat.P1Q == true) gsPath1Interrupt();
|
||||
while(gifRegs.stat.P1Q == true) gsPath1Interrupt();
|
||||
}
|
||||
GetMTGS().PrepDataPacket(GIF_PATH_1, 0x400);
|
||||
size = GIFPath_CopyTag(GIF_PATH_1, (u128*)data, diff);
|
||||
|
@ -1995,13 +1995,13 @@ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
|
|||
|
||||
if(GSTransferStatus.PTH1 == STOPPED_MODE )
|
||||
{
|
||||
gifRegs->stat.OPH = false;
|
||||
gifRegs->stat.APATH = GIF_APATH_IDLE;
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
//DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs.stat.APATH, Path1WritePos, Path1ReadPos);
|
||||
size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff);
|
||||
pDest = &Path1Buffer[Path1WritePos*16];
|
||||
|
||||
|
@ -2017,8 +2017,8 @@ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
|
|||
else {
|
||||
memcpy_qwc(pDest, VU1.Mem + addr, size);
|
||||
}
|
||||
//if(!gifRegs->stat.P1Q) CPU_INT(28, 128);
|
||||
gifRegs->stat.P1Q = true;
|
||||
//if(!gifRegs.stat.P1Q) CPU_INT(28, 128);
|
||||
gifRegs.stat.P1Q = true;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue