From bafe542ce3682be9de19bfb834e18593751e6cc9 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Fri, 23 Jun 2017 22:17:14 +0100 Subject: [PATCH] Restore previous NV2A behavoir --- src/CxbxKrnl/EmuNV2A.cpp | 55 ++++++++++++++++++++++++++++++----- src/CxbxKrnl/EmuNV2A.h | 4 +-- src/CxbxKrnl/EmuX86.cpp | 62 +++++++++++++++++++++++++++++++++------- 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/src/CxbxKrnl/EmuNV2A.cpp b/src/CxbxKrnl/EmuNV2A.cpp index 2a73a4b7a..c2a616a3a 100644 --- a/src/CxbxKrnl/EmuNV2A.cpp +++ b/src/CxbxKrnl/EmuNV2A.cpp @@ -59,6 +59,7 @@ #include #include #include +#include //#include #define NV_PMC_ADDR 0x00000000 @@ -1235,28 +1236,68 @@ const NV2ABlockInfo* EmuNV2A_Block(xbaddr addr) return nullptr; } -uint32_t EmuNV2A_Read32(xbaddr addr) +uint32_t EmuNV2A_Read(xbaddr addr, int size) { const NV2ABlockInfo* block = EmuNV2A_Block(addr); if (block != nullptr) { - return block->read(addr - block->offset); + switch (size) { + case 8: + return block->read(addr - block->offset) & 0xFF; + case 16: + return block->read(addr - block->offset) & 0xFFFF; + case 32: + return block->read(addr - block->offset); + default: + EmuWarning("EmuNV2A_Read: Invalid read size: %d", size); + return 0; + } } - EmuWarning("EmuNV2A_Read32: Unhandled Read Address %08X", addr); + EmuWarning("EmuNV2A_Read%d: Unhandled Read Address %08X", size, addr); return 0; } -void EmuNV2A_Write32(xbaddr addr, uint32_t value) +void EmuNV2A_Write(xbaddr addr, uint32_t value, int size) { const NV2ABlockInfo* block = EmuNV2A_Block(addr); if (block != nullptr) { - block->write(addr - block->offset, value); - return; + int shift = 0; + xbaddr aligned_addr = 0; + uint32_t aligned_value = 0; + uint32_t mask = 0; + switch (size) { + case 8: + shift = (addr & 3) * 8; + aligned_addr = addr & ~3; + aligned_value = block->read(aligned_addr - block->offset); + mask = 0xFF << shift; + + // TODO : Must the second byte be written to the next DWORD? + block->write(aligned_addr - block->offset, (aligned_value & ~mask) | (value << shift)); + return; + case 16: + assert((addr & 1) == 0); + + shift = (addr & 2) * 16; + aligned_addr = addr & ~3; + aligned_value = block->read(addr - block->offset); + mask = 0xFFFF << shift; + + // TODO : Must the second byte be written to the next DWORD? + block->write(aligned_addr - block->offset, (aligned_value & ~mask) | (value << shift)); + return; + case 32: + block->write(addr - block->offset, value); + return; + default: + EmuWarning("EmuNV2A_Read: Invalid read size: %d", size); + return; + } } - EmuWarning("EmuNV2A_Write32: Unhandled Write Address %08X (value %08X)", addr, value); + EmuWarning("EmuNV2A_Write%d: Unhandled Write Address %08X (value %08X)", size, addr, value); return; } diff --git a/src/CxbxKrnl/EmuNV2A.h b/src/CxbxKrnl/EmuNV2A.h index e7eaef33f..b853c4942 100644 --- a/src/CxbxKrnl/EmuNV2A.h +++ b/src/CxbxKrnl/EmuNV2A.h @@ -40,8 +40,8 @@ #define NV2A_ADDR 0xFD000000 #define NV2A_SIZE 0x01000000 -uint32_t EmuNV2A_Read32(xbaddr addr); -void EmuNV2A_Write32(xbaddr addr, uint32_t value); +uint32_t EmuNV2A_Read(xbaddr addr, int size); +void EmuNV2A_Write(xbaddr addr, uint32_t value, int size); void InitOpenGLContext(); diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index d429c88d3..1afd23273 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -146,7 +146,7 @@ uint32_t EmuX86_Read32Aligned(xbaddr addr) } // Access NV2A regardless weither HLE is disabled or not - value = EmuNV2A_Read32(addr - NV2A_ADDR); + value = EmuNV2A_Read(addr - NV2A_ADDR, 32); // Note : EmuNV2A_Read32 does it's own logging } if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { value = EmuNVNet_Read(addr - NVNET_ADDR, 32); @@ -181,16 +181,23 @@ uint32_t EmuX86_Read32(xbaddr addr) uint16_t EmuX86_Read16(xbaddr addr) { uint16_t value; - - if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { + + if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) { + if (!bLLE_GPU) { + EmuWarning("EmuX86_Read32Aligned(0x%08X) Unexpected NV2A access, missing a HLE patch. " \ + "Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr); + } + + // Access NV2A regardless weither HLE is disabled or not + value = EmuNV2A_Read(addr - NV2A_ADDR, 16); + // Note : EmuNV2A_Read32 does it's own logging + } else if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { value = EmuNVNet_Read(addr - NVNET_ADDR, 16); - } - else { + } else { if (g_bEmuException) { EmuWarning("EmuX86_Read16(0x%08X) [Unknown address]", addr); value = 0; - } - else { + } else { // Outside EmuException, pass the memory-access through to normal memory : value = EmuX86_Mem_Read16(addr); } @@ -204,10 +211,18 @@ uint8_t EmuX86_Read8(xbaddr addr) { uint8_t value; - if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { + if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) { + if (!bLLE_GPU) { + EmuWarning("EmuX86_Read32Aligned(0x%08X) Unexpected NV2A access, missing a HLE patch. " \ + "Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr); + } + + // Access NV2A regardless weither HLE is disabled or not + value = EmuNV2A_Read(addr - NV2A_ADDR, 8); + // Note : EmuNV2A_Read32 does it's own logging + } else if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { value = EmuNVNet_Read(addr - NVNET_ADDR, 8); - } - else { + } else { if (g_bEmuException) { EmuWarning("EmuX86_Read8(0x%08X) [Unknown address]", addr); value = 0; @@ -233,7 +248,7 @@ void EmuX86_Write32Aligned(xbaddr addr, uint32_t value) } // Access NV2A regardless weither HLE is disabled or not - EmuNV2A_Write32(addr - NV2A_ADDR, value); + EmuNV2A_Write(addr - NV2A_ADDR, value, 32); // Note : EmuNV2A_Write32 does it's own logging return; } @@ -264,6 +279,18 @@ void EmuX86_Write32(xbaddr addr, uint32_t value) void EmuX86_Write16(xbaddr addr, uint16_t value) { + if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) { + if (!bLLE_GPU) { + EmuWarning("EmuX86_Write32Aligned(0x%08X, 0x%08X) Unexpected NV2A access, missing a HLE patch. " \ + "Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr); + } + + // Access NV2A regardless weither HLE is disabled or not + EmuNV2A_Write(addr - NV2A_ADDR, value, 16); + // Note : EmuNV2A_Write32 does it's own logging + return; + } + if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { EmuNVNet_Write(addr - NVNET_ADDR, value, 16); return; @@ -281,6 +308,19 @@ void EmuX86_Write16(xbaddr addr, uint16_t value) void EmuX86_Write8(xbaddr addr, uint8_t value) { + + if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) { + if (!bLLE_GPU) { + EmuWarning("EmuX86_Write32Aligned(0x%08X, 0x%08X) Unexpected NV2A access, missing a HLE patch. " \ + "Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr); + } + + // Access NV2A regardless weither HLE is disabled or not + EmuNV2A_Write(addr - NV2A_ADDR, value, 8); + // Note : EmuNV2A_Write32 does it's own logging + return; + } + if (addr >= NVNET_ADDR && addr < NVNET_ADDR + NVNET_SIZE) { EmuNVNet_Write(addr - NVNET_ADDR, value, 8); return;