mirror of
https://github.com/hch12907/orbum.git
synced 2024-06-02 19:38:16 -04:00
Definitely getting somewhere with the SPU2.STATX - starting to see the IOP waiting for the spu to finish reciving data in a timing loop.
This commit is contained in:
parent
6999a7772a
commit
e937f2ec11
|
@ -72,12 +72,12 @@ void BitfieldRegister16_t::registerField(const int fieldIndex, const char* field
|
|||
|
||||
u16 BitfieldRegister16_t::getFieldValue(const Context_t context, const int fieldIndex)
|
||||
{
|
||||
return MathUtil::extractMaskedValue16(readHword(context), mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength);
|
||||
return MathUtil::extractMaskedValue16(UH, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength);
|
||||
}
|
||||
|
||||
void BitfieldRegister16_t::setFieldValue(const Context_t context, const int fieldIndex, const u16 value)
|
||||
{
|
||||
writeHword(context, MathUtil::insertMaskedValue16(readHword(context), value, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength));
|
||||
writeHword(context, MathUtil::insertMaskedValue16(UH, value, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength));
|
||||
}
|
||||
|
||||
void BitfieldRegister16_t::logDebugAllFields() const
|
||||
|
|
|
@ -94,17 +94,16 @@ void BitfieldRegister32_t::registerField(const int fieldIndex, const char* field
|
|||
|
||||
u32 BitfieldRegister32_t::getFieldValue(const Context_t context, const int fieldIndex)
|
||||
{
|
||||
return MathUtil::extractMaskedValue32(readWord(context), mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength);
|
||||
return MathUtil::extractMaskedValue32(UW, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength);
|
||||
}
|
||||
|
||||
void BitfieldRegister32_t::setFieldValue(const Context_t context, const int fieldIndex, const u32 value)
|
||||
{
|
||||
writeWord(context, MathUtil::insertMaskedValue32(readWord(context), value, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength));
|
||||
writeWord(context, MathUtil::insertMaskedValue32(UW, value, mFields[fieldIndex].mStartPosition, mFields[fieldIndex].mLength));
|
||||
}
|
||||
|
||||
void BitfieldRegister32_t::logDebugAllFields() const
|
||||
{
|
||||
// Using UW directly is OK here - we are not modifying anything, and it can only ever be called from within a VM "context" (ie: always called from get/setFieldValue()).
|
||||
for (auto& field : mFields)
|
||||
{
|
||||
#if DEBUG_LOG_VALUE_AS_HEX
|
||||
|
|
|
@ -88,5 +88,5 @@ void SPU2CoreRegister_ATTR_t::writeHword(const Context_t context, const u16 valu
|
|||
SPU2CoreRegister_STATX_t::SPU2CoreRegister_STATX_t(const char* mnemonic, const bool debugReads, const bool debugWrites) :
|
||||
BitfieldRegister16_t(mnemonic, debugReads, debugWrites)
|
||||
{
|
||||
registerField(Fields::NeedData, "NeedData", 7, 1, 1);
|
||||
registerField(Fields::NeedData, "NeedData", 7, 1, 0);
|
||||
}
|
||||
|
|
|
@ -134,9 +134,8 @@ public:
|
|||
|
||||
/*
|
||||
The SPU2 Core STATX register.
|
||||
TODO: I don't fully understand this, the PCSX2 code is hard to read. Seems to be related to a "need data for processing" thing.
|
||||
Set to 0x80 on "need data", set to 0 otherwise?
|
||||
Might actually be a "ready" flag - IOPCore loops on reading this register if set to 0x80...
|
||||
It is set to 0x80 when the SPU2 DMA requires data (to write), cleared otherwise.
|
||||
TODO: Check this is true for SPU2 DMA reading, it is unhandled for now.
|
||||
*/
|
||||
class SPU2CoreRegister_STATX_t : public BitfieldRegister16_t
|
||||
{
|
||||
|
|
|
@ -164,7 +164,7 @@ SPU2Core_C0_t::SPU2Core_C0_t(const std::shared_ptr<FIFOQueue_t> & fifoQueue) :
|
|||
VMIXER0 = std::make_shared<SPU2CoreRegister_CHAN0_t>("SPU2 C0 VMIXER0", false, false);
|
||||
VMIXER1 = std::make_shared<SPU2CoreRegister_CHAN1_t>("SPU2 C0 VMIXER1", false, false);
|
||||
MMIX = std::make_shared<SPU2CoreRegister_MMIX_t>("SPU2 C0 MMIX", false, false);
|
||||
ATTR = std::make_shared<SPU2CoreRegister_ATTR_t>("SPU2 C0 ATTR", false, true);
|
||||
ATTR = std::make_shared<SPU2CoreRegister_ATTR_t>("SPU2 C0 ATTR", false, false);
|
||||
IRQAH = std::make_shared<Register16_t>("SPU2 C0 IRQAH", false, true);
|
||||
IRQAL = std::make_shared<PairRegister16_t>("SPU2 C0 IRQAL", false, true, IRQAH);
|
||||
KON0 = std::make_shared<SPU2CoreRegister_CHAN0_t>("SPU2 C0 KON0", false, false);
|
||||
|
@ -226,7 +226,7 @@ SPU2Core_C0_t::SPU2Core_C0_t(const std::shared_ptr<FIFOQueue_t> & fifoQueue) :
|
|||
EEAL = std::make_shared<Register16_t>("SPU2 C0 EEAL", false, false);
|
||||
ENDX0 = std::make_shared<Register16_t>("SPU2 C0 ENDX0", false, false);
|
||||
ENDX1 = std::make_shared<Register16_t>("SPU2 C0 ENDX1", false, false);
|
||||
STATX = std::make_shared<SPU2CoreRegister_STATX_t>("SPU2 C0 STATX", false, false);
|
||||
STATX = std::make_shared<SPU2CoreRegister_STATX_t>("SPU2 C0 STATX", true, false);
|
||||
MVOLL = std::make_shared<SPU2CoreRegister_VOL_t>("SPU2 C0 MVOLL", false, false);
|
||||
MVOLR = std::make_shared<SPU2CoreRegister_VOL_t>("SPU2 C0 MVOLR", false, false);
|
||||
EVOLL = std::make_shared<Register16_t>("SPU2 C0 EVOLL", false, false);
|
||||
|
@ -313,7 +313,7 @@ SPU2Core_C1_t::SPU2Core_C1_t(const std::shared_ptr<FIFOQueue_t> & fifoQueue):
|
|||
VMIXER0 = std::make_shared<SPU2CoreRegister_CHAN0_t>("SPU2 C1 VMIXER0", false, false);
|
||||
VMIXER1 = std::make_shared<SPU2CoreRegister_CHAN1_t>("SPU2 C1 VMIXER1", false, false);
|
||||
MMIX = std::make_shared<SPU2CoreRegister_MMIX_t>("SPU2 C1 MMIX", false, false);
|
||||
ATTR = std::make_shared<SPU2CoreRegister_ATTR_t>("SPU2 C1 ATTR", false, true);
|
||||
ATTR = std::make_shared<SPU2CoreRegister_ATTR_t>("SPU2 C1 ATTR", false, false);
|
||||
IRQAH = std::make_shared<Register16_t>("SPU2 C1 IRQAH", false, true);
|
||||
IRQAL = std::make_shared<PairRegister16_t>("SPU2 C1 IRQAL", false, true, IRQAH);
|
||||
KON0 = std::make_shared<SPU2CoreRegister_CHAN0_t>("SPU2 C1 KON0", false, false);
|
||||
|
@ -375,7 +375,7 @@ SPU2Core_C1_t::SPU2Core_C1_t(const std::shared_ptr<FIFOQueue_t> & fifoQueue):
|
|||
EEAL = std::make_shared<Register16_t>("SPU2 C1 EEAL", false, false);
|
||||
ENDX0 = std::make_shared<Register16_t>("SPU2 C1 ENDX0", false, false);
|
||||
ENDX1 = std::make_shared<Register16_t>("SPU2 C1 ENDX1", false, false);
|
||||
STATX = std::make_shared<SPU2CoreRegister_STATX_t>("SPU2 C1 STATX", false, false);
|
||||
STATX = std::make_shared<SPU2CoreRegister_STATX_t>("SPU2 C1 STATX", true, false);
|
||||
MVOLL = std::make_shared<SPU2CoreRegister_VOL_t>("SPU2 C1 MVOLL", false, false);
|
||||
MVOLR = std::make_shared<SPU2CoreRegister_VOL_t>("SPU2 C1 MVOLR", false, false);
|
||||
EVOLL = std::make_shared<Register16_t>("SPU2 C1 EVOLL", false, false);
|
||||
|
|
|
@ -47,7 +47,7 @@ int IOPCoreInterpreter_s::step(const Event_t & event)
|
|||
mIOPCoreInstruction = IOPCoreInstruction_t(mByteMMU->readWord(getContext(), physicalAddress));
|
||||
|
||||
#if defined(BUILD_DEBUG)
|
||||
static u64 DEBUG_LOOP_BREAKPOINT = 0x100000998269;
|
||||
static u64 DEBUG_LOOP_BREAKPOINT = 0x100000437406;
|
||||
static u32 DEBUG_PC_BREAKPOINT = 0x0;
|
||||
static u32 DEBUG_INST_VAL_BREAKPOINT = 0x42000010; // COP0 RFE
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ SPU2_s::SPU2_s(VM * vm) :
|
|||
|
||||
void SPU2_s::initialise()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int SPU2_s::step(const Event_t & event)
|
||||
|
@ -82,29 +81,57 @@ bool SPU2_s::handleDMATransfer()
|
|||
throw std::runtime_error("SPU2 ATTR DMABits field set to non-zero. What is this for?");
|
||||
|
||||
int dmaCount = 0;
|
||||
bool updateSTATX = false;
|
||||
switch (mCore->ATTR->getFieldValue(getContext(), SPU2CoreRegister_ATTR_t::Fields::DMAMode))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
// Auto DMA write mode.
|
||||
if (mCore->isADMAEnabled(getContext()))
|
||||
{
|
||||
dmaCount = transferData_ADMA_Write();
|
||||
updateSTATX = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Auto DMA read mode.
|
||||
if (mCore->isADMAEnabled(getContext()))
|
||||
{
|
||||
dmaCount = transferData_ADMA_Read();
|
||||
updateSTATX = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// Manual DMA write mode.
|
||||
dmaCount = transferData_MDMA_Write();
|
||||
updateSTATX = true;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// Manual DMA read mode.
|
||||
dmaCount = transferData_MDMA_Read();
|
||||
updateSTATX = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw std::runtime_error("SPU2 could not determine DMA mode. Please fix.");
|
||||
}
|
||||
}
|
||||
|
||||
// Update STATX only if DMA attemped to run, and if there was FIFO data available.
|
||||
if (updateSTATX)
|
||||
{
|
||||
if (mCore->FIFOQueue->getReadAvailable() > 0)
|
||||
mCore->STATX->setFieldValue(getContext(), SPU2CoreRegister_STATX_t::Fields::NeedData, 0);
|
||||
else
|
||||
mCore->STATX->setFieldValue(getContext(), SPU2CoreRegister_STATX_t::Fields::NeedData, 1);
|
||||
}
|
||||
|
||||
return (dmaCount > 0);
|
||||
}
|
||||
|
@ -114,19 +141,6 @@ bool SPU2_s::handleSoundGeneration()
|
|||
// Check if core is enabled and do sound generation.
|
||||
if (mCore->ATTR->getFieldValue(getContext(), SPU2CoreRegister_ATTR_t::Fields::CoreEnable))
|
||||
{
|
||||
// Check if we are running out of data - that the end of data is less than 0x200 hwords away. Set STATX on this condition and send an interrupt (or clear it otherwise).
|
||||
// TODO: Check the logic and implement. Might need to set the IOP DMAC interrupt bit for the current core (a bit weird)? See SPU2-X/ReadInput.cpp (V_Core::ReadInput()).
|
||||
static int hackCount = 0;
|
||||
if ((++hackCount) % 2000 < 1000)
|
||||
{
|
||||
mCore->STATX->setFieldValue(getContext(), SPU2CoreRegister_STATX_t::Fields::NeedData, 1);
|
||||
// mDMAC->ICR{0,1}->setFieldValue(getContext(), IOPDmacRegister_ICR{0,1}_t::Fields::TCI{...}, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCore->STATX->setFieldValue(getContext(), SPU2CoreRegister_STATX_t::Fields::NeedData, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -196,12 +210,7 @@ int SPU2_s::transferData_MDMA_Write() const
|
|||
// Check for incoming data and read it in, otherwise exit early as theres nothing to do.
|
||||
u16 data;
|
||||
if (!mCore->FIFOQueue->read(getContext(), reinterpret_cast<u8*>(&data), Constants::NUMBER_BYTES_IN_HWORD))
|
||||
{
|
||||
// TODO: check this especially!!!
|
||||
// Need to also clear the STATX.NeedData bit when out of data.
|
||||
mCore->STATX->setFieldValue(getContext(), SPU2CoreRegister_STATX_t::Fields::NeedData, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate write address. Make sure address is not outside 2MB limit (remember, we are addressing by hwords).
|
||||
u32 address = (mCore->TSAL->readPairWord(getContext()) + mCore->ATTR->mDMAOffset) % 0x100000;
|
||||
|
|
Loading…
Reference in a new issue