[Disk] Put Mecha Interrupt management in DiskCommand(), delay seek times

This commit is contained in:
LuigiBlood 2020-06-05 14:36:49 +02:00
parent 0512e7199a
commit b428c14a27
5 changed files with 41 additions and 18 deletions

View File

@ -62,23 +62,28 @@ void DiskCommand()
uint8_t second = (uint8_t)(((result.tm_sec / 10) << 4) | (result.tm_sec % 10));
#endif
//Used for seek times
bool isSeek = false;
switch (cmd & 0xFFFF0000)
{
case 0x00010000:
//Seek Read
g_Reg->ASIC_CUR_TK = g_Reg->ASIC_DATA | 0x60000000;
dd_write = false;
isSeek = true;
break;
case 0x00020000:
//Seek Write
g_Reg->ASIC_CUR_TK = g_Reg->ASIC_DATA | 0x60000000;
dd_write = true;
isSeek = true;
break;
case 0x00080000:
//Unset Disk Changed Bit
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break;
case 0x00090000:
//Unset Reset Bit
//Unset Reset & Disk Changed bit Bit
g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE;
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG;
//F-Zero X + Expansion Kit fix so it doesn't enable "swapping" at boot
@ -99,6 +104,19 @@ void DiskCommand()
//Disk Inquiry
g_Reg->ASIC_DATA = 0x00000000; break;
}
if (isSeek)
{
//Emulate Seek Times, send interrupt later
g_SystemTimer->SetTimer(g_SystemTimer->DDSeekTimer, 0x400000, false);
}
else
{
//Other commands are basically instant
g_Reg->ASIC_STATUS |= DD_STATUS_MECHA_INT;
g_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP3;
g_Reg->CheckInterrupts();
}
}
void DiskReset(void)
@ -157,6 +175,9 @@ void DiskBMControl(void)
void DiskGapSectorCheck()
{
//On 64DD Status Register Read
//Buffer Manager Interrupt, Gap Sector Check
if (g_Reg->ASIC_STATUS & DD_STATUS_BM_INT)
{
if (SECTORS_PER_BLOCK < dd_current)
@ -168,6 +189,7 @@ void DiskGapSectorCheck()
}
}
//Delay Disk Swapping by removing the disk for a certain amount of time, then insert the newly loaded disk (after 50 Status Register reads, here).
if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL && g_Settings->LoadBool(GameRunning_LoadingInProgress) == false)
{
dd_swapdelay++;
@ -190,12 +212,14 @@ void DiskBMUpdate()
//Write Data
if (dd_current < SECTORS_PER_BLOCK)
{
//User Sector
if (!DiskBMReadWrite(true))
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
dd_current += 1;
}
else if (dd_current < SECTORS_PER_BLOCK + 1)
{
//C2 Sector
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
{
dd_start_block = 1 - dd_start_block;
@ -222,25 +246,27 @@ void DiskBMUpdate()
//Read Data
if (((g_Reg->ASIC_CUR_TK >> 16) & 0x1FFF) == 6 && g_Reg->ASIC_CUR_SECTOR == 0 && g_Disk->GetCountry() != Country::UnknownCountry)
{
//Copy Protection
//Copy Protection if Retail Disk
g_Reg->ASIC_STATUS &= ~DD_STATUS_DATA_RQ;
g_Reg->ASIC_BM_STATUS |= DD_BM_STATUS_MICRO;
}
else if (dd_current < SECTORS_PER_BLOCK)
{
//User Sector
if (!DiskBMReadWrite(false))
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
dd_current += 1;
}
else if (dd_current < SECTORS_PER_BLOCK + 4)
{
//READ C2 (00!)
//C2 sectors (All 00s)
dd_current += 1;
if (dd_current == SECTORS_PER_BLOCK + 4)
g_Reg->ASIC_STATUS |= DD_STATUS_C2_XFER;
}
else if (dd_current == SECTORS_PER_BLOCK + 4)
{
//Gap Sector
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
{
dd_start_block = 1 - dd_start_block;

View File

@ -2157,9 +2157,6 @@ void CMipsMemoryVM::Write32CartridgeDomain2Address1(void)
case 0x05000508:
g_Reg->ASIC_CMD = m_MemLookupValue.UW[0];
DiskCommand();
g_Reg->ASIC_STATUS |= DD_STATUS_MECHA_INT;
g_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP3;
g_Reg->CheckInterrupts();
break;
case 0x05000510:
//ASIC_BM_STATUS_CTL

View File

@ -221,6 +221,16 @@ void CSystemTimer::TimerDone()
m_Reg.MI_INTR_REG |= MI_INTR_PI;
m_Reg.CheckInterrupts();
break;
case CSystemTimer::DDSeekTimer:
g_SystemTimer->StopTimer(CSystemTimer::DDSeekTimer);
g_Reg->ASIC_STATUS |= DD_STATUS_MECHA_INT;
g_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP3;
g_Reg->CheckInterrupts();
break;
case CSystemTimer::DDMotorTimer:
g_SystemTimer->StopTimer(CSystemTimer::DDMotorTimer);
g_Reg->ASIC_STATUS &= ~DD_STATUS_MTR_N_SPIN;
break;
case CSystemTimer::ViTimer:
try
{

View File

@ -32,6 +32,8 @@ public:
RspTimer,
RSPTimerDlist,
DDPiTimer,
DDSeekTimer,
DDMotorTimer,
MaxTimer
};

View File

@ -11783,18 +11783,6 @@ void CX86RecompilerOps::SW_Register(x86Reg Reg, uint32_t VAddr)
MoveX86regToVariable(Reg, &g_Reg->ASIC_CMD, "ASIC_CMD");
m_RegWorkingSet.BeforeCallDirect();
Call_Direct(AddressOf(&DiskCommand), "DiskCommand");
m_RegWorkingSet.AfterCallDirect();
OrConstToVariable((uint32_t)DD_STATUS_MECHA_INT, &g_Reg->ASIC_STATUS, "ASIC_STATUS");
OrConstToVariable((uint32_t)CAUSE_IP3, &g_Reg->FAKE_CAUSE_REGISTER, "FAKE_CAUSE_REGISTER");
m_RegWorkingSet.BeforeCallDirect();
#ifdef _MSC_VER
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
#else
PushImm32((uint32_t)g_Reg);
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
AddConstToX86Reg(x86_ESP, 4);
#endif
m_RegWorkingSet.AfterCallDirect();
break;
}