2012-12-19 09:30:18 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
2015-11-10 05:21:49 +00:00
|
|
|
* Project64 - A Nintendo 64 emulator. *
|
2012-12-19 09:30:18 +00:00
|
|
|
* http://www.pj64-emu.com/ *
|
|
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
|
|
* *
|
|
|
|
* License: *
|
|
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
2010-06-22 20:36:28 +00:00
|
|
|
#include "stdafx.h"
|
2016-01-13 11:20:34 +00:00
|
|
|
#include <Common/MemoryManagement.h>
|
2016-01-13 15:21:58 +00:00
|
|
|
|
2016-01-13 11:15:30 +00:00
|
|
|
#include <Project64-core/N64System/Mips/Dma.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
|
|
|
#include <Project64-core/N64System/N64RomClass.h>
|
2015-12-21 07:35:22 +00:00
|
|
|
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
2016-01-20 13:31:29 +00:00
|
|
|
#include <Project64-core/N64System/Mips/Disk.h>
|
2016-01-20 16:43:23 +00:00
|
|
|
#include <Project64-core/N64System/N64DiskClass.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/N64Class.h>
|
2010-06-22 20:36:28 +00:00
|
|
|
|
|
|
|
CDMA::CDMA(CFlashram & FlashRam, CSram & Sram) :
|
2016-01-13 11:20:34 +00:00
|
|
|
m_FlashRam(FlashRam),
|
|
|
|
m_Sram(Sram)
|
2010-06-22 20:36:28 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CDMA::OnFirstDMA()
|
2015-03-29 17:19:28 +00:00
|
|
|
{
|
2015-11-16 15:21:50 +00:00
|
|
|
int16_t offset;
|
2015-11-16 15:13:36 +00:00
|
|
|
const uint32_t base = 0x00000000;
|
2015-11-16 15:21:50 +00:00
|
|
|
const uint32_t rt = g_MMU->RdramSize();
|
2015-11-16 15:13:36 +00:00
|
|
|
|
2015-11-15 00:52:24 +00:00
|
|
|
switch (g_Rom->CicChipID())
|
|
|
|
{
|
2015-11-16 15:21:50 +00:00
|
|
|
case CIC_NUS_6101: offset = +0x0318; break;
|
|
|
|
case CIC_NUS_5167: offset = +0x0318; break;
|
2016-01-18 19:15:01 +00:00
|
|
|
case CIC_NUS_8303: offset = +0x0318; break;
|
2016-08-28 16:36:56 +00:00
|
|
|
case CIC_NUS_DDUS: offset = +0x0318; break;
|
2019-08-11 09:45:52 +00:00
|
|
|
case CIC_NUS_DDTL: offset = +0x0318; break;
|
2015-11-15 00:52:24 +00:00
|
|
|
case CIC_UNKNOWN:
|
2015-11-16 15:21:50 +00:00
|
|
|
case CIC_NUS_6102: offset = +0x0318; break;
|
|
|
|
case CIC_NUS_6103: offset = +0x0318; break;
|
|
|
|
case CIC_NUS_6105: offset = +0x03F0; break;
|
|
|
|
case CIC_NUS_6106: offset = +0x0318; break;
|
|
|
|
default:
|
2015-12-23 20:04:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Unhandled CicChip(%d) in first DMA", g_Rom->CicChipID()).c_str());
|
2015-11-16 15:21:50 +00:00
|
|
|
return;
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
2015-11-16 15:21:50 +00:00
|
|
|
g_MMU->SW_PAddr(base + offset, rt);
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CDMA::PI_DMA_READ()
|
2015-03-29 17:19:28 +00:00
|
|
|
{
|
2015-11-15 00:52:24 +00:00
|
|
|
// PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
|
|
|
|
uint32_t PI_RD_LEN_REG = ((g_Reg->PI_RD_LEN_REG) & 0x00FFFFFFul) + 1;
|
|
|
|
|
|
|
|
if ((PI_RD_LEN_REG & 1) != 0)
|
|
|
|
{
|
|
|
|
PI_RD_LEN_REG += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->PI_DRAM_ADDR_REG + PI_RD_LEN_REG > g_MMU->RdramSize())
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2015-12-23 20:04:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("PI_DMA_READ not in Memory: %08X", g_Reg->PI_DRAM_ADDR_REG + PI_RD_LEN_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-20 13:31:29 +00:00
|
|
|
//64DD Buffers Write
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG >= 0x05000000 && g_Reg->PI_CART_ADDR_REG <= 0x050003FF)
|
|
|
|
{
|
|
|
|
//64DD C2 Sectors (don't care)
|
2016-01-23 21:44:58 +00:00
|
|
|
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_RD_LEN_REG * 63) / 25, false);
|
2016-01-20 13:31:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG >= 0x05000400 && g_Reg->PI_CART_ADDR_REG <= 0x050004FF)
|
|
|
|
{
|
|
|
|
//64DD User Sector
|
|
|
|
uint32_t i;
|
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
2016-01-20 16:43:23 +00:00
|
|
|
uint8_t * DISK = g_Disk->GetDiskAddressBuffer();
|
2016-01-20 13:31:29 +00:00
|
|
|
for (i = 0; i < PI_RD_LEN_REG; i++)
|
|
|
|
{
|
2016-01-20 16:43:23 +00:00
|
|
|
*(DISK + (i ^ 3)) = *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3));
|
2016-01-20 13:31:29 +00:00
|
|
|
}
|
2016-01-23 21:44:58 +00:00
|
|
|
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_RD_LEN_REG * 63) / 25, false);
|
2016-01-20 13:31:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG >= 0x05000580 && g_Reg->PI_CART_ADDR_REG <= 0x050005BF)
|
|
|
|
{
|
|
|
|
//64DD MSEQ (don't care)
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-15 00:52:24 +00:00
|
|
|
//Write ROM Area (for 64DD Convert)
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG >= 0x10000000 && g_Reg->PI_CART_ADDR_REG <= 0x1FBFFFFF && g_Settings->LoadBool(Game_AllowROMWrites))
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
uint8_t * ROM = g_Rom->GetRomAddress();
|
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
|
|
|
|
2016-01-18 19:15:01 +00:00
|
|
|
ProtectMemory(ROM, g_Rom->GetRomSize(), MEM_READWRITE);
|
2015-11-15 00:52:24 +00:00
|
|
|
g_Reg->PI_CART_ADDR_REG -= 0x10000000;
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG + PI_RD_LEN_REG < g_Rom->GetRomSize())
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_RD_LEN_REG; i++)
|
|
|
|
{
|
|
|
|
*(ROM + ((g_Reg->PI_CART_ADDR_REG + i) ^ 3)) = *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t Len;
|
|
|
|
Len = g_Rom->GetRomSize() - g_Reg->PI_CART_ADDR_REG;
|
|
|
|
for (i = 0; i < Len; i++)
|
|
|
|
{
|
|
|
|
*(ROM + ((g_Reg->PI_CART_ADDR_REG + i) ^ 3)) = *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_Reg->PI_CART_ADDR_REG += 0x10000000;
|
|
|
|
|
|
|
|
if (!g_System->DmaUsed())
|
|
|
|
{
|
|
|
|
g_System->SetDmaUsed(true);
|
|
|
|
OnFirstDMA();
|
|
|
|
}
|
|
|
|
if (g_Recompiler && g_System->bSMM_PIDMA())
|
|
|
|
{
|
|
|
|
g_Recompiler->ClearRecompCode_Phys(g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_WR_LEN_REG, CRecompiler::Remove_DMA);
|
|
|
|
}
|
|
|
|
|
2016-01-18 19:15:01 +00:00
|
|
|
ProtectMemory(ROM, g_Rom->GetRomSize(), MEM_READONLY);
|
2015-11-15 00:52:24 +00:00
|
|
|
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->PI_CART_ADDR_REG >= 0x08000000 && g_Reg->PI_CART_ADDR_REG <= 0x08010000)
|
|
|
|
{
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_Auto)
|
|
|
|
{
|
|
|
|
g_System->m_SaveUsing = SaveChip_Sram;
|
|
|
|
}
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_Sram)
|
|
|
|
{
|
|
|
|
m_Sram.DmaToSram(
|
|
|
|
g_MMU->Rdram() + g_Reg->PI_DRAM_ADDR_REG,
|
|
|
|
g_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
PI_RD_LEN_REG
|
|
|
|
);
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_FlashRam)
|
|
|
|
{
|
|
|
|
m_FlashRam.DmaToFlashram(
|
|
|
|
g_MMU->Rdram() + g_Reg->PI_DRAM_ADDR_REG,
|
|
|
|
g_Reg->PI_CART_ADDR_REG - 0x08000000,
|
|
|
|
PI_RD_LEN_REG
|
|
|
|
);
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_FlashRam)
|
|
|
|
{
|
2015-12-23 20:04:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("**** FLashRam DMA Read address %08X *****", g_Reg->PI_CART_ADDR_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2015-12-23 20:04:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("PI_DMA_READ where are you dmaing to ? : %08X", g_Reg->PI_CART_ADDR_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CDMA::PI_DMA_WRITE()
|
2015-02-12 21:26:17 +00:00
|
|
|
{
|
2016-02-10 01:21:29 +00:00
|
|
|
/* rounding PI_WR_LEN_REG up to the nearest even number fixes AI Shougi 3, Doraemon 3, etc. */
|
2018-02-27 06:27:17 +00:00
|
|
|
uint32_t PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFEul) + 2;
|
2018-12-28 12:09:38 +00:00
|
|
|
uint32_t PI_CART_ADDR_REG = !g_Settings->LoadBool(Game_UnalignedDMA) ? g_Reg->PI_CART_ADDR_REG & ~1 : g_Reg->PI_CART_ADDR_REG;
|
2015-11-15 00:52:24 +00:00
|
|
|
|
|
|
|
g_Reg->PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
|
|
|
|
if (g_Reg->PI_DRAM_ADDR_REG + PI_WR_LEN_REG > g_MMU->RdramSize())
|
|
|
|
{
|
2020-03-31 23:54:10 +00:00
|
|
|
if (ShowUnhandledMemory()) { g_Notify->DisplayError(stdstr_f("PI_DMA_WRITE not in Memory: %08X", g_Reg->PI_DRAM_ADDR_REG + PI_WR_LEN_REG).c_str()); }
|
2015-11-15 00:52:24 +00:00
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-20 13:31:29 +00:00
|
|
|
//64DD Buffers Read
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x05000000 && PI_CART_ADDR_REG <= 0x050003FF)
|
2016-01-18 19:15:01 +00:00
|
|
|
{
|
2016-01-20 13:31:29 +00:00
|
|
|
//64DD C2 Sectors (just read 0)
|
2016-01-18 19:15:01 +00:00
|
|
|
uint32_t i;
|
2016-01-20 13:31:29 +00:00
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
|
|
|
{
|
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0;
|
|
|
|
}
|
2016-01-23 21:44:58 +00:00
|
|
|
|
|
|
|
//Timer is needed for Track Read
|
|
|
|
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_WR_LEN_REG * 63) / 25, false);
|
2016-01-20 13:31:29 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-01-18 19:15:01 +00:00
|
|
|
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x05000400 && PI_CART_ADDR_REG <= 0x050004FF)
|
2016-01-20 13:31:29 +00:00
|
|
|
{
|
|
|
|
//64DD User Sector
|
|
|
|
uint32_t i;
|
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
2016-01-20 16:43:23 +00:00
|
|
|
uint8_t * DISK = g_Disk->GetDiskAddressBuffer();
|
2016-01-20 13:31:29 +00:00
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
2016-01-18 19:15:01 +00:00
|
|
|
{
|
2016-01-20 16:43:23 +00:00
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(DISK + (i ^ 3));
|
2016-01-18 19:15:01 +00:00
|
|
|
}
|
2016-01-23 21:44:58 +00:00
|
|
|
|
|
|
|
//Timer is needed for Track Read
|
|
|
|
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_WR_LEN_REG * 63) / 25, false);
|
2016-01-20 13:31:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x05000580 && PI_CART_ADDR_REG <= 0x050005BF)
|
2016-01-20 13:31:29 +00:00
|
|
|
{
|
|
|
|
//64DD MSEQ (don't care)
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//64DD IPL ROM
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x06000000 && PI_CART_ADDR_REG <= 0x063FFFFF)
|
2016-01-20 13:31:29 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2016-01-18 19:15:01 +00:00
|
|
|
|
|
|
|
uint8_t * ROM = g_DDRom->GetRomAddress();
|
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG -= 0x06000000;
|
|
|
|
if (PI_CART_ADDR_REG + PI_WR_LEN_REG < g_DDRom->GetRomSize())
|
2016-01-18 19:15:01 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((PI_CART_ADDR_REG + i) ^ 3));
|
2016-01-18 19:15:01 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-27 06:27:17 +00:00
|
|
|
else if (PI_CART_ADDR_REG >= g_DDRom->GetRomSize())
|
2016-01-18 19:15:01 +00:00
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
uint32_t cart = PI_CART_ADDR_REG - g_DDRom->GetRomSize();
|
2016-01-18 19:15:01 +00:00
|
|
|
while (cart >= g_DDRom->GetRomSize())
|
|
|
|
{
|
|
|
|
cart -= g_DDRom->GetRomSize();
|
|
|
|
}
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
|
|
|
{
|
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((cart + i) ^ 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t Len;
|
2018-02-27 06:27:17 +00:00
|
|
|
Len = g_DDRom->GetRomSize() - PI_CART_ADDR_REG;
|
2016-01-18 19:15:01 +00:00
|
|
|
for (i = 0; i < Len; i++)
|
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((PI_CART_ADDR_REG + i) ^ 3));
|
2016-01-18 19:15:01 +00:00
|
|
|
}
|
|
|
|
for (i = Len; i < PI_WR_LEN_REG - Len; i++)
|
|
|
|
{
|
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0;
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG += 0x06000000;
|
2016-01-18 19:15:01 +00:00
|
|
|
|
|
|
|
if (!g_System->DmaUsed())
|
|
|
|
{
|
|
|
|
g_System->SetDmaUsed(true);
|
|
|
|
OnFirstDMA();
|
|
|
|
}
|
|
|
|
if (g_Recompiler && g_System->bSMM_PIDMA())
|
|
|
|
{
|
|
|
|
g_Recompiler->ClearRecompCode_Phys(g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_WR_LEN_REG, CRecompiler::Remove_DMA);
|
|
|
|
}
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
//ChangeTimer(PiTimer,(int32_t)(PI_WR_LEN_REG * 8.9) + 50);
|
|
|
|
//ChangeTimer(PiTimer,(int32_t)(PI_WR_LEN_REG * 8.9));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x08000000 && PI_CART_ADDR_REG <= 0x08088000)
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_Auto)
|
|
|
|
{
|
|
|
|
g_System->m_SaveUsing = SaveChip_Sram;
|
|
|
|
}
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_Sram)
|
|
|
|
{
|
|
|
|
m_Sram.DmaFromSram(
|
|
|
|
g_MMU->Rdram() + g_Reg->PI_DRAM_ADDR_REG,
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG - 0x08000000,
|
2015-11-15 00:52:24 +00:00
|
|
|
PI_WR_LEN_REG
|
|
|
|
);
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (g_System->m_SaveUsing == SaveChip_FlashRam)
|
|
|
|
{
|
|
|
|
m_FlashRam.DmaFromFlashram(
|
|
|
|
g_MMU->Rdram() + g_Reg->PI_DRAM_ADDR_REG,
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG - 0x08000000,
|
2015-11-15 00:52:24 +00:00
|
|
|
PI_WR_LEN_REG
|
|
|
|
);
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-27 06:27:17 +00:00
|
|
|
if (PI_CART_ADDR_REG >= 0x10000000 && PI_CART_ADDR_REG <= 0x1FFFFFFF)
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2015-05-14 12:34:45 +00:00
|
|
|
|
2015-12-15 06:01:06 +00:00
|
|
|
#ifdef legacycode
|
2010-06-22 20:36:28 +00:00
|
|
|
#ifdef ROM_IN_MAPSPACE
|
2015-11-15 00:52:24 +00:00
|
|
|
if (WrittenToRom)
|
|
|
|
{
|
|
|
|
uint32_t OldProtect;
|
|
|
|
VirtualProtect(ROM,m_RomFileSize,PAGE_READONLY, &OldProtect);
|
|
|
|
}
|
2010-06-22 20:36:28 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2015-05-14 12:34:45 +00:00
|
|
|
|
2015-11-15 00:52:24 +00:00
|
|
|
uint8_t * ROM = g_Rom->GetRomAddress();
|
|
|
|
uint8_t * RDRAM = g_MMU->Rdram();
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG -= 0x10000000;
|
|
|
|
if (PI_CART_ADDR_REG + PI_WR_LEN_REG < g_Rom->GetRomSize())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2016-02-10 02:13:21 +00:00
|
|
|
size_t alignment;
|
|
|
|
RDRAM += g_Reg->PI_DRAM_ADDR_REG;
|
2018-02-27 06:27:17 +00:00
|
|
|
ROM += PI_CART_ADDR_REG;
|
2016-02-10 02:13:21 +00:00
|
|
|
alignment = PI_WR_LEN_REG | (size_t)RDRAM | (size_t)ROM;
|
|
|
|
if ((alignment & 0x3) == 0)
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2016-02-10 02:13:21 +00:00
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i += 4)
|
|
|
|
{
|
|
|
|
*(uint32_t *)(RDRAM + i) = *(uint32_t *)(ROM + i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((alignment & 1) == 0)
|
|
|
|
{
|
|
|
|
if ((PI_WR_LEN_REG & 2) == 0)
|
|
|
|
{
|
|
|
|
if (((size_t)RDRAM & 2) == 0)
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i += 4)
|
|
|
|
{
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) + 2) = *(uint16_t *)(((size_t)ROM + i) - 2);
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) + 0) = *(uint16_t *)(((size_t)ROM + i) + 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (((size_t)ROM & 2) == 0)
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i += 4)
|
|
|
|
{
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) + 2);
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i += 4)
|
|
|
|
{
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) - 2) = *(uint16_t *)(((size_t)ROM + i) - 2);
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) + 4) = *(uint16_t *)(((size_t)ROM + i) + 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i += 2)
|
|
|
|
{
|
|
|
|
*(uint16_t *)(((size_t)RDRAM + i) ^ 2) = *(uint16_t *)(((size_t)ROM + i) ^ 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
|
|
|
{
|
|
|
|
*(uint8_t *)(((size_t)RDRAM + i) ^ 3) = *(uint8_t *)(((size_t)ROM + i) ^ 3);
|
|
|
|
}
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-27 06:27:17 +00:00
|
|
|
else if (PI_CART_ADDR_REG >= g_Rom->GetRomSize())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
uint32_t cart = PI_CART_ADDR_REG - g_Rom->GetRomSize();
|
2015-11-15 00:52:24 +00:00
|
|
|
while (cart >= g_Rom->GetRomSize())
|
|
|
|
{
|
|
|
|
cart -= g_Rom->GetRomSize();
|
|
|
|
}
|
|
|
|
for (i = 0; i < PI_WR_LEN_REG; i++)
|
|
|
|
{
|
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((cart + i) ^ 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t Len;
|
2018-02-27 06:27:17 +00:00
|
|
|
Len = g_Rom->GetRomSize() - PI_CART_ADDR_REG;
|
2015-11-15 00:52:24 +00:00
|
|
|
for (i = 0; i < Len; i++)
|
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM + ((PI_CART_ADDR_REG + i) ^ 3));
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
for (i = Len; i < PI_WR_LEN_REG - Len; i++)
|
|
|
|
{
|
|
|
|
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0;
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 06:27:17 +00:00
|
|
|
PI_CART_ADDR_REG += 0x10000000;
|
2015-11-15 00:52:24 +00:00
|
|
|
|
|
|
|
if (!g_System->DmaUsed())
|
|
|
|
{
|
|
|
|
g_System->SetDmaUsed(true);
|
|
|
|
OnFirstDMA();
|
|
|
|
}
|
|
|
|
if (g_Recompiler && g_System->bSMM_PIDMA())
|
|
|
|
{
|
|
|
|
g_Recompiler->ClearRecompCode_Phys(g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_WR_LEN_REG, CRecompiler::Remove_DMA);
|
|
|
|
}
|
2017-10-18 02:38:38 +00:00
|
|
|
|
2019-10-02 22:18:19 +00:00
|
|
|
if(g_System->bRandomizeSIPIInterrupts())
|
|
|
|
{
|
|
|
|
g_SystemTimer->SetTimer(g_SystemTimer->PiTimer, PI_WR_LEN_REG / 8 + (g_Random->next() % 0x40), false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
|
|
|
}
|
2015-11-15 00:52:24 +00:00
|
|
|
//ChangeTimer(PiTimer,(int32_t)(PI_WR_LEN_REG * 8.9) + 50);
|
|
|
|
//ChangeTimer(PiTimer,(int32_t)(PI_WR_LEN_REG * 8.9));
|
|
|
|
return;
|
|
|
|
}
|
2010-06-22 20:36:28 +00:00
|
|
|
|
2020-03-31 23:54:10 +00:00
|
|
|
if (ShowUnhandledMemory())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2018-02-27 06:27:17 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("PI_DMA_WRITE not in ROM: %08X", PI_CART_ADDR_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
|
|
|
g_Reg->CheckInterrupts();
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CDMA::SP_DMA_READ()
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
|
|
|
g_Reg->SP_DRAM_ADDR_REG &= 0x1FFFFFFF;
|
|
|
|
|
|
|
|
if (g_Reg->SP_DRAM_ADDR_REG > g_MMU->RdramSize())
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2016-01-13 11:20:34 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("%s\nSP_DRAM_ADDR_REG not in RDRam space : % 08X", __FUNCTION__, g_Reg->SP_DRAM_ADDR_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
g_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->SP_RD_LEN_REG + 1 + (g_Reg->SP_MEM_ADDR_REG & 0xFFF) > 0x1000)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2016-01-13 11:20:34 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("%s\nCould not fit copy in memory segment",__FUNCTION__).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2010-06-22 20:36:28 +00:00
|
|
|
|
2015-11-15 00:52:24 +00:00
|
|
|
if ((g_Reg->SP_MEM_ADDR_REG & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
if ((g_Reg->SP_DRAM_ADDR_REG & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
if (((g_Reg->SP_RD_LEN_REG + 1) & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(g_MMU->Dmem() + (g_Reg->SP_MEM_ADDR_REG & 0x1FFF), g_MMU->Rdram() + g_Reg->SP_DRAM_ADDR_REG,
|
|
|
|
g_Reg->SP_RD_LEN_REG + 1);
|
|
|
|
|
|
|
|
g_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
2010-06-22 20:36:28 +00:00
|
|
|
}
|
2015-11-15 00:52:24 +00:00
|
|
|
|
|
|
|
void CDMA::SP_DMA_WRITE()
|
|
|
|
{
|
|
|
|
if (g_Reg->SP_DRAM_ADDR_REG > g_MMU->RdramSize())
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2016-01-13 11:20:34 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("%s\nSP_DRAM_ADDR_REG not in RDRam space : %08X", __FUNCTION__, g_Reg->SP_DRAM_ADDR_REG).c_str());
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Reg->SP_WR_LEN_REG + 1 + (g_Reg->SP_MEM_ADDR_REG & 0xFFF) > 0x1000)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-15 00:52:24 +00:00
|
|
|
{
|
2015-12-23 20:04:36 +00:00
|
|
|
g_Notify->DisplayError("SP DMA WRITE\ncould not fit copy in memory segement");
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((g_Reg->SP_MEM_ADDR_REG & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((g_Reg->SP_DRAM_ADDR_REG & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
if (((g_Reg->SP_WR_LEN_REG + 1) & 3) != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 00:52:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(g_MMU->Rdram() + g_Reg->SP_DRAM_ADDR_REG, g_MMU->Dmem() + (g_Reg->SP_MEM_ADDR_REG & 0x1FFF),
|
|
|
|
g_Reg->SP_WR_LEN_REG + 1);
|
|
|
|
|
|
|
|
g_Reg->SP_DMA_BUSY_REG = 0;
|
|
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
|
|
}
|