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:
Jake.Stine 2010-08-31 05:22:26 +00:00
parent 1cac8d3948
commit 003da7d287
53 changed files with 2282 additions and 2665 deletions

View File

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

View File

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

View File

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

View File

@ -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__ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -277,7 +277,7 @@ struct GIFregisters
u32 padding9[3];
};
#define gifRegs ((GIFregisters*)(eeHw+0x3000))
static GIFregisters& gifRegs = (GIFregisters&)eeHw[0x3000];
extern tGSTransferStatus GSTransferStatus;

View File

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

View File

@ -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__ */

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -168,7 +168,7 @@ struct __aligned16 VURegs {
VIFregisters& GetVifRegs() const
{
return IsVU1() ? vif1RegsRef : vif0RegsRef;
return IsVU1() ? vif1Regs : vif0Regs;
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

79
pcsx2/ps2/HwInternal.h Normal file
View File

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

View File

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

View File

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

View File

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

348
pcsx2/ps2/LegacyDmac.cpp Normal file
View File

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

268
pcsx2/ps2/eeHwTraceLog.inl Normal file
View File

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

View File

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

View File

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

View File

@ -21,11 +21,6 @@
#include "iR5900.h"
#ifdef _WIN32
//#pragma warning(disable:4244)
//#pragma warning(disable:4761)
#endif
namespace R5900 {
namespace Dynarec {
namespace OpcodeImpl

View File

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

View File

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

View File

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

View File

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