2010-06-22 20:36:28 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
CDMA::CDMA(CFlashram & FlashRam, CSram & Sram) :
|
|
|
|
m_FlashRam(FlashRam),
|
|
|
|
m_Sram(Sram)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDMA::OnFirstDMA (void) {
|
|
|
|
switch (_Rom->CicChipID()) {
|
2010-06-29 02:11:22 +00:00
|
|
|
case 1: *(DWORD *)&((_MMU->Rdram())[0x318]) = _MMU->RdramSize(); break;
|
|
|
|
case 2: *(DWORD *)&((_MMU->Rdram())[0x318]) = _MMU->RdramSize(); break;
|
|
|
|
case 3: *(DWORD *)&((_MMU->Rdram())[0x318]) = _MMU->RdramSize(); break;
|
|
|
|
case 5: *(DWORD *)&((_MMU->Rdram())[0x3F0]) = _MMU->RdramSize(); break;
|
|
|
|
case 6: *(DWORD *)&((_MMU->Rdram())[0x318]) = _MMU->RdramSize(); break;
|
2012-09-29 13:52:06 +00:00
|
|
|
default: _Notify->DisplayError("Unhandled CicChip(%d) in first DMA",_Rom->CicChipID());
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDMA::PI_DMA_READ (void) {
|
|
|
|
// PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
|
|
|
|
|
2010-06-29 02:11:22 +00:00
|
|
|
if ( _Reg->PI_DRAM_ADDR_REG + _Reg->PI_RD_LEN_REG + 1 > _MMU->RdramSize()) {
|
2010-06-22 20:36:28 +00:00
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("PI_DMA_READ not in Memory");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _Reg->PI_CART_ADDR_REG >= 0x08000000 && _Reg->PI_CART_ADDR_REG <= 0x08010000) {
|
|
|
|
if (g_SaveUsing == SaveChip_Auto) { g_SaveUsing = SaveChip_Sram; }
|
|
|
|
if (g_SaveUsing == SaveChip_Sram) {
|
|
|
|
m_Sram.DmaToSram(
|
|
|
|
_MMU->Rdram() + _Reg->PI_DRAM_ADDR_REG,
|
|
|
|
_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
_Reg->PI_RD_LEN_REG + 1
|
|
|
|
);
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (g_SaveUsing == SaveChip_FlashRam) {
|
|
|
|
m_FlashRam.DmaToFlashram(
|
|
|
|
_MMU->Rdram()+_Reg->PI_DRAM_ADDR_REG,
|
|
|
|
_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
_Reg->PI_WR_LEN_REG + 1
|
|
|
|
);
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-06-30 21:35:44 +00:00
|
|
|
if (g_SaveUsing == SaveChip_FlashRam)
|
|
|
|
{
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("**** FLashRam DMA Read address %X *****",_Reg->PI_CART_ADDR_REG);
|
2010-06-22 20:36:28 +00:00
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("PI_DMA_READ where are you dmaing to ?");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDMA::PI_DMA_WRITE (void) {
|
|
|
|
|
|
|
|
_Reg->PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
|
2010-06-29 02:11:22 +00:00
|
|
|
if ( _Reg->PI_DRAM_ADDR_REG + _Reg->PI_WR_LEN_REG + 1 > _MMU->RdramSize())
|
2010-06-22 20:36:28 +00:00
|
|
|
{
|
2012-09-29 13:52:06 +00:00
|
|
|
if (_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { _Notify->DisplayError("PI_DMA_WRITE not in Memory"); }
|
2010-06-22 20:36:28 +00:00
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _Reg->PI_CART_ADDR_REG >= 0x08000000 && _Reg->PI_CART_ADDR_REG <= 0x08010000) {
|
|
|
|
if (g_SaveUsing == SaveChip_Auto) { g_SaveUsing = SaveChip_Sram; }
|
|
|
|
if (g_SaveUsing == SaveChip_Sram) {
|
|
|
|
m_Sram.DmaFromSram(
|
|
|
|
_MMU->Rdram()+_Reg->PI_DRAM_ADDR_REG,
|
|
|
|
_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
_Reg->PI_WR_LEN_REG + 1
|
|
|
|
);
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (g_SaveUsing == SaveChip_FlashRam) {
|
|
|
|
m_FlashRam.DmaFromFlashram(
|
|
|
|
_MMU->Rdram()+_Reg->PI_DRAM_ADDR_REG,
|
|
|
|
_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
_Reg->PI_WR_LEN_REG + 1
|
|
|
|
);
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-30 21:35:44 +00:00
|
|
|
if ( _Reg->PI_CART_ADDR_REG >= 0x10000000 && _Reg->PI_CART_ADDR_REG <= 0x1FBFFFFF)
|
|
|
|
{
|
2010-06-22 20:36:28 +00:00
|
|
|
DWORD i;
|
|
|
|
#ifdef tofix
|
|
|
|
#ifdef ROM_IN_MAPSPACE
|
|
|
|
if (WrittenToRom) {
|
|
|
|
DWORD OldProtect;
|
2012-09-30 12:24:07 +00:00
|
|
|
VirtualProtect(ROM,m_RomFileSize,PAGE_READONLY, &OldProtect);
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
BYTE * ROM = _Rom->GetRomAddress();
|
|
|
|
BYTE * RDRAM = _MMU->Rdram();
|
|
|
|
_Reg->PI_CART_ADDR_REG -= 0x10000000;
|
2012-09-30 12:24:07 +00:00
|
|
|
if (_Reg->PI_CART_ADDR_REG + _Reg->PI_WR_LEN_REG + 1 < _Rom->GetRomSize()) {
|
2010-06-22 20:36:28 +00:00
|
|
|
for (i = 0; i < _Reg->PI_WR_LEN_REG + 1; i ++) {
|
|
|
|
*(RDRAM+((_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM+((_Reg->PI_CART_ADDR_REG + i) ^ 3));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DWORD Len;
|
2012-09-30 12:24:07 +00:00
|
|
|
Len = _Rom->GetRomSize() - _Reg->PI_CART_ADDR_REG;
|
2010-06-22 20:36:28 +00:00
|
|
|
for (i = 0; i < Len; i ++) {
|
|
|
|
*(RDRAM+((_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM+((_Reg->PI_CART_ADDR_REG + i) ^ 3));
|
|
|
|
}
|
|
|
|
for (i = Len; i < _Reg->PI_WR_LEN_REG + 1 - Len; i ++) {
|
|
|
|
*(RDRAM+((_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_Reg->PI_CART_ADDR_REG += 0x10000000;
|
|
|
|
|
|
|
|
if (!_System->DmaUsed())
|
|
|
|
{
|
|
|
|
_System->SetDmaUsed(true);
|
|
|
|
OnFirstDMA();
|
|
|
|
}
|
|
|
|
if (_Recompiler && _Recompiler->bSMM_PIDMA())
|
|
|
|
{
|
|
|
|
_Recompiler->ClearRecompCode_Phys(_Reg->PI_DRAM_ADDR_REG, _Reg->PI_WR_LEN_REG,CRecompiler::Remove_DMA);
|
|
|
|
}
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
//ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9) + 50);
|
|
|
|
//ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-29 13:52:06 +00:00
|
|
|
if (_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { _Notify->DisplayError("PI_DMA_WRITE not in ROM"); }
|
2010-06-22 20:36:28 +00:00
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDMA::SP_DMA_READ (void) {
|
|
|
|
_Reg->SP_DRAM_ADDR_REG &= 0x1FFFFFFF;
|
|
|
|
|
2010-06-29 02:11:22 +00:00
|
|
|
if (_Reg->SP_DRAM_ADDR_REG > _MMU->RdramSize()) {
|
2010-06-22 20:36:28 +00:00
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("SP DMA\nSP_DRAM_ADDR_REG not in RDRam space");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_Reg->SP_RD_LEN_REG + 1 + (_Reg->SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
|
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("SP DMA\ncould not fit copy in memory segement");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-30 06:07:08 +00:00
|
|
|
if ((_Reg->SP_MEM_ADDR_REG & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
|
|
|
if ((_Reg->SP_DRAM_ADDR_REG & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
|
|
|
if (((_Reg->SP_RD_LEN_REG + 1) & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
2010-06-22 20:36:28 +00:00
|
|
|
|
|
|
|
memcpy( _MMU->Dmem() + (_Reg->SP_MEM_ADDR_REG & 0x1FFF), _MMU->Rdram() + _Reg->SP_DRAM_ADDR_REG,
|
|
|
|
_Reg->SP_RD_LEN_REG + 1 );
|
|
|
|
|
|
|
|
_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDMA::SP_DMA_WRITE (void) {
|
2010-06-29 02:11:22 +00:00
|
|
|
if (_Reg->SP_DRAM_ADDR_REG > _MMU->RdramSize()) {
|
2010-06-22 20:36:28 +00:00
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("SP DMA WRITE\nSP_DRAM_ADDR_REG not in RDRam space");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_Reg->SP_WR_LEN_REG + 1 + (_Reg->SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
|
|
|
|
#ifndef EXTERNAL_RELEASE
|
2012-09-29 13:52:06 +00:00
|
|
|
_Notify->DisplayError("SP DMA WRITE\ncould not fit copy in memory segement");
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-30 06:07:08 +00:00
|
|
|
if ((_Reg->SP_MEM_ADDR_REG & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
|
|
|
if ((_Reg->SP_DRAM_ADDR_REG & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
|
|
|
if (((_Reg->SP_WR_LEN_REG + 1) & 3) != 0) { _Notify->BreakPoint(__FILE__,__LINE__); }
|
2010-06-22 20:36:28 +00:00
|
|
|
|
|
|
|
memcpy( _MMU->Rdram() + _Reg->SP_DRAM_ADDR_REG, _MMU->Dmem() + (_Reg->SP_MEM_ADDR_REG & 0x1FFF),
|
|
|
|
_Reg->SP_WR_LEN_REG + 1);
|
|
|
|
|
|
|
|
_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
|
|
}
|
|
|
|
|