summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2015-01-12 12:03:46 +1100
committerskidau <skidau@gmail.com>2015-01-12 12:03:46 +1100
commit7105e5a8f01120f459300a81841e287fa6bbeec2 (patch)
treec64f25f92658758568084b3fce84c927c45d06c6 /Source/Core
parentb0d5c3cd99d9d68679fe28e2b2092eb5bd0315fb (diff)
parent9b0bf34d00b8ebd7bd99f964a73a67ef0104697e (diff)
Merge pull request #1863 from magumagu/dma-efb
Allow locked L1 DMA to write to the EFB
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/Memmap.cpp38
-rw-r--r--Source/Core/Core/HW/MemmapFunctions.cpp106
2 files changed, 92 insertions, 52 deletions
diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp
index d97aff3a2f..fc8dc39f34 100644
--- a/Source/Core/Core/HW/Memmap.cpp
+++ b/Source/Core/Core/HW/Memmap.cpp
@@ -243,44 +243,6 @@ void ClearCacheLine(const u32 address)
Write_U64(0, address + i);
}
-void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
-{
- const u8* src = m_pL1Cache + (cacheAddr & 0x3FFFF);
- u8* dst = GetPointer(memAddr);
-
- if ((dst != nullptr) && (src != nullptr) && (memAddr & 3) == 0 && (cacheAddr & 3) == 0)
- {
- memcpy(dst, src, 32 * numBlocks);
- }
- else
- {
- for (u32 i = 0; i < 32 * numBlocks; i++)
- {
- u8 Temp = Read_U8(cacheAddr + i);
- Write_U8(Temp, memAddr + i);
- }
- }
-}
-
-void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
-{
- const u8* src = GetPointer(memAddr);
- u8* dst = m_pL1Cache + (cacheAddr & 0x3FFFF);
-
- if ((dst != nullptr) && (src != nullptr) && (memAddr & 3) == 0 && (cacheAddr & 3) == 0)
- {
- memcpy(dst, src, 32 * numBlocks);
- }
- else
- {
- for (u32 i = 0; i < 32 * numBlocks; i++)
- {
- u8 Temp = Read_U8(memAddr + i);
- Write_U8(Temp, cacheAddr + i);
- }
- }
-}
-
std::string GetString(u32 em_address, size_t size)
{
const char* ptr = reinterpret_cast<const char*>(GetPointer(em_address));
diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp
index b97b2f632e..f8380ac183 100644
--- a/Source/Core/Core/HW/MemmapFunctions.cpp
+++ b/Source/Core/Core/HW/MemmapFunctions.cpp
@@ -90,6 +90,24 @@ static u32 EFB_Read(const u32 addr)
return var;
}
+static void EFB_Write(u32 data, u32 addr)
+{
+ int x = (addr & 0xfff) >> 2;
+ int y = (addr >> 12) & 0x3ff;
+
+ if (addr & 0x00400000)
+ {
+ g_video_backend->Video_AccessEFB(POKE_Z, x, y, data);
+ DEBUG_LOG(MEMMAP, "EFB Z Write %08x @ %i, %i", data, x, y);
+ }
+ else
+ {
+ g_video_backend->Video_AccessEFB(POKE_COLOR, x, y, data);
+ DEBUG_LOG(MEMMAP, "EFB Color Write %08x @ %i, %i", data, x, y);
+ }
+}
+
+
static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
template <XCheckTLBFlag flag, typename T>
@@ -193,20 +211,8 @@ __forceinline void WriteToHardware(u32 em_address, const T data)
{
if (em_address < 0xcc000000)
{
- int x = (em_address & 0xfff) >> 2;
- int y = (em_address >> 12) & 0x3ff;
-
- // TODO figure out a way to send data without falling into the template trap
- if (em_address & 0x00400000)
- {
- g_video_backend->Video_AccessEFB(POKE_Z, x, y, (u32)data);
- DEBUG_LOG(MEMMAP, "EFB Z Write %08x @ %i, %i", (u32)data, x, y);
- }
- else
- {
- g_video_backend->Video_AccessEFB(POKE_COLOR, x, y, (u32)data);
- DEBUG_LOG(MEMMAP, "EFB Color Write %08x @ %i, %i", (u32)data, x, y);
- }
+ // TODO: This only works correctly for 32-bit writes.
+ EFB_Write((u32)data, em_address);
return;
}
else
@@ -460,6 +466,78 @@ void WriteUnchecked_U32(const u32 var, const u32 address)
WriteToHardware<FLAG_NO_EXCEPTION, u32>(address, var);
}
+void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
+{
+ // TODO: It's not completely clear this is the right spot for this code;
+ // what would happen if, for example, the DVD drive tried to write to the EFB?
+ // TODO: This is terribly slow.
+ // TODO: Refactor.
+ // Avatar: The Last Airbender (GC) uses this for videos.
+ if ((memAddr & 0x0F000000) == 0x08000000)
+ {
+ for (u32 i = 0; i < 32 * numBlocks; i+=4)
+ {
+ u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)));
+ EFB_Write(data, memAddr + i);
+ }
+ return;
+ }
+
+ // No known game uses this; here for completeness.
+ // TODO: Refactor.
+ if ((memAddr & 0x0F000000) == 0x0C000000)
+ {
+ for (u32 i = 0; i < 32 * numBlocks; i += 4)
+ {
+ u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)));
+ mmio_mapping->Write(memAddr + i, data);
+ }
+ return;
+ }
+
+ const u8* src = Memory::m_pL1Cache + (cacheAddr & 0x3FFFF);
+ u8* dst = Memory::GetPointer(memAddr);
+ if (dst == nullptr)
+ return;
+
+ memcpy(dst, src, 32 * numBlocks);
+}
+
+void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
+{
+ const u8* src = Memory::GetPointer(memAddr);
+ u8* dst = Memory::m_pL1Cache + (cacheAddr & 0x3FFFF);
+
+ // No known game uses this; here for completeness.
+ // TODO: Refactor.
+ if ((memAddr & 0x0F000000) == 0x08000000)
+ {
+ for (u32 i = 0; i < 32 * numBlocks; i += 4)
+ {
+ u32 data = EFB_Read(memAddr + i);
+ *(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)) = bswap(data);
+ }
+ return;
+ }
+
+ // No known game uses this.
+ // TODO: Refactor.
+ if ((memAddr & 0x0F000000) == 0x0C000000)
+ {
+ for (u32 i = 0; i < 32 * numBlocks; i += 4)
+ {
+ u32 data = mmio_mapping->Read<u32>(memAddr + i);
+ *(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)) = bswap(data);
+ }
+ return;
+ }
+
+ if (src == nullptr)
+ return;
+
+ memcpy(dst, src, 32 * numBlocks);
+}
+
// *********************************************************************************
// Warning: Test Area
//