Refactored LLE X86 and NV2A
Completed operand decoding Completed opcode ADD Redirected 8 and 16 bit memory accesses to 32 bit EmuX86 logging fixes and cleanup Partiall support for misaligned memory accesses NV2A macro cleanup Clearer NV2A logging Generic read/write on most NV2A components
This commit is contained in:
parent
659b5f992b
commit
80d9d528f3
|
@ -179,7 +179,7 @@ XBSYSAPI EXPORTNUM(168) xboxkrnl::PVOID NTAPI xboxkrnl::MmClaimGpuInstanceMemory
|
||||||
*NumberOfPaddingBytes = MI_CONVERT_PFN_TO_PHYSICAL(MM_64M_PHYSICAL_PAGE) -
|
*NumberOfPaddingBytes = MI_CONVERT_PFN_TO_PHYSICAL(MM_64M_PHYSICAL_PAGE) -
|
||||||
MI_CONVERT_PFN_TO_PHYSICAL(MM_INSTANCE_PHYSICAL_PAGE + MM_INSTANCE_PAGE_COUNT);
|
MI_CONVERT_PFN_TO_PHYSICAL(MM_INSTANCE_PHYSICAL_PAGE + MM_INSTANCE_PAGE_COUNT);
|
||||||
|
|
||||||
EmuWarning("*NumberOfPaddingBytes = 0x%08X", *NumberOfPaddingBytes);
|
DbgPrintf("MmClaimGpuInstanceMemory : *NumberOfPaddingBytes = 0x%08X\n", *NumberOfPaddingBytes);
|
||||||
|
|
||||||
if (NumberOfBytes != MAXULONG_PTR)
|
if (NumberOfBytes != MAXULONG_PTR)
|
||||||
{
|
{
|
||||||
|
|
|
@ -157,6 +157,7 @@ struct {
|
||||||
struct {
|
struct {
|
||||||
uint32_t pending_interrupts;
|
uint32_t pending_interrupts;
|
||||||
uint32_t enabled_interrupts;
|
uint32_t enabled_interrupts;
|
||||||
|
uint32_t regs[NV_PGRAPH_SIZE / sizeof(uint32_t)]; // TODO : union
|
||||||
} pgraph;
|
} pgraph;
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,11 +204,11 @@ static void update_irq()
|
||||||
|
|
||||||
if (pmc.pending_interrupts && pmc.enabled_interrupts) {
|
if (pmc.pending_interrupts && pmc.enabled_interrupts) {
|
||||||
// TODO Raise IRQ
|
// TODO Raise IRQ
|
||||||
EmuWarning("EmuNV2A update_irq() : Raise IRQ Not Implemented");
|
EmuWarning("NV2A update_irq() : Raise IRQ Not Implemented");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: Cancel IRQ
|
// TODO: Cancel IRQ
|
||||||
EmuWarning("EmuNV2A update_irq() : Cancel IRQ Not Implemented");
|
EmuWarning("NV2A update_irq() : Cancel IRQ Not Implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,30 +235,30 @@ DEBUG_START(PMC)
|
||||||
DEBUG_END(PMC)
|
DEBUG_END(PMC)
|
||||||
|
|
||||||
DEBUG_START(PBUS)
|
DEBUG_START(PBUS)
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_0, "_VENDOR_ID");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_0, ":VENDOR_ID");
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_1);
|
DEBUG_CASE(NV_PBUS_PCI_NV_1);
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_2, "_REVISION_ID");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_2, ":REVISION_ID");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_3, "_LATENCY_TIMER");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_3, ":LATENCY_TIMER");
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_4);
|
DEBUG_CASE(NV_PBUS_PCI_NV_4);
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_5);
|
DEBUG_CASE(NV_PBUS_PCI_NV_5);
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_6);
|
DEBUG_CASE(NV_PBUS_PCI_NV_6);
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_7);
|
DEBUG_CASE(NV_PBUS_PCI_NV_7);
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_11, "_SUBSYSTEM");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_11, ":SUBSYSTEM");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_12, "_ROM_BASE");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_12, ":ROM_BASE");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_13, "_CAP_PTR");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_13, ":CAP_PTR");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_14, "_RESERVED");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_14, ":RESERVED");
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_15);
|
DEBUG_CASE(NV_PBUS_PCI_NV_15);
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_16, "_SUBSYSTEM");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_16, ":SUBSYSTEM");
|
||||||
DEBUG_CASE(NV_PBUS_PCI_NV_17);
|
DEBUG_CASE(NV_PBUS_PCI_NV_17);
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_18, "_AGP_STATUS");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_18, ":AGP_STATUS");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_19, "_AGP_COMMAND");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_19, ":AGP_COMMAND");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_20, "_ROM_SHADOW");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_20, ":ROM_SHADOW");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_21, "_VGA");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_21, ":VGA");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_22, "_SCRATCH");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_22, ":SCRATCH");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_23, "_DT_TIMEOUT");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_23, ":DT_TIMEOUT");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_24, "_PME");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_24, ":PME");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_25, "_POWER_STATE");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_25, ":POWER_STATE");
|
||||||
DEBUG_CASE_EX(NV_PBUS_PCI_NV_26, "_RESERVED");
|
DEBUG_CASE_EX(NV_PBUS_PCI_NV_26, ":RESERVED");
|
||||||
DEBUG_END(PBUS)
|
DEBUG_END(PBUS)
|
||||||
|
|
||||||
DEBUG_START(PFIFO)
|
DEBUG_START(PFIFO)
|
||||||
|
@ -511,23 +512,25 @@ DEBUG_END(USER)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_READ32(DEV) DbgPrintf("EmuX86_Read32 NV2A_" #DEV "(0x%08X) = 0x%08X [Handled, %s]\n", addr, result, DebugNV_##DEV##(addr));
|
#define DEBUG_READ32(DEV) DbgPrintf("EmuX86 Read32 NV2A " #DEV "(0x%08X) = 0x%08X [Handled, %s]\n", addr, result, DebugNV_##DEV##(addr))
|
||||||
#define DEBUG_READ32_UNHANDLED(DEV) DbgPrintf("EmuX86_Read32 NV2A_" #DEV "(0x%08X) = 0x%08X [Unhandled, %s]\n", addr, result, DebugNV_##DEV##(addr));
|
#define DEBUG_READ32_UNHANDLED(DEV) { DbgPrintf("EmuX86 Read32 NV2A " #DEV "(0x%08X) = 0x%08X [Unhandled, %s]\n", addr, result, DebugNV_##DEV##(addr)); return result; }
|
||||||
|
|
||||||
#define DEBUG_WRITE32(DEV) DbgPrintf("EmuX86_Write32 NV2A_" #DEV "(0x%08X, 0x%08X) [Handled, %s]\n", addr, value, DebugNV_##DEV##(addr));
|
#define DEBUG_WRITE32(DEV) DbgPrintf("EmuX86 Write32 NV2A " #DEV "(0x%08X, 0x%08X) [Handled, %s]\n", addr, value, DebugNV_##DEV##(addr))
|
||||||
#define DEBUG_WRITE32_UNHANDLED(DEV) DbgPrintf("EmuX86_Write32 NV2A_" #DEV "(0x%08X, 0x%08X) [Unhandled, %s]\n", addr, value, DebugNV_##DEV##(addr));
|
#define DEBUG_WRITE32_UNHANDLED(DEV) { DbgPrintf("EmuX86 Write32 NV2A " #DEV "(0x%08X, 0x%08X) [Unhandled, %s]\n", addr, value, DebugNV_##DEV##(addr)); return; }
|
||||||
|
|
||||||
#define DEVICE_READ32(DEV) uint32_t EmuNV2A_##DEV##_Read32(xbaddr addr)
|
#define DEVICE_READ32(DEV) uint32_t EmuNV2A_##DEV##_Read32(xbaddr addr)
|
||||||
#define DEVICE_READ32_SWITCH(addr) uint32_t result = 0; switch (addr)
|
#define DEVICE_READ32_SWITCH() uint32_t result = 0; switch (addr)
|
||||||
|
#define DEVICE_READ32_REG(dev) result = dev.regs[addr / sizeof(uint32_t)]
|
||||||
#define DEVICE_READ32_END(DEV) DEBUG_READ32(DEV); return result
|
#define DEVICE_READ32_END(DEV) DEBUG_READ32(DEV); return result
|
||||||
|
|
||||||
#define DEVICE_WRITE32(DEV) void EmuNV2A_##DEV##_Write32(xbaddr addr, uint32_t value)
|
#define DEVICE_WRITE32(DEV) void EmuNV2A_##DEV##_Write32(xbaddr addr, uint32_t value)
|
||||||
#define DEVICE_WRITE32_SWITCH(DEV, addr) DEBUG_WRITE32(DEV); switch (addr)
|
#define DEVICE_WRITE32_REG(dev) dev.regs[addr / sizeof(uint32_t)] = value
|
||||||
|
#define DEVICE_WRITE32_END(DEV) DEBUG_WRITE32(DEV)
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PMC)
|
DEVICE_READ32(PMC)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
case NV_PMC_BOOT_0: // chipset and stepping: NV2A, A02, Rev 0
|
case NV_PMC_BOOT_0: // chipset and stepping: NV2A, A02, Rev 0
|
||||||
result = 0x02A000A2;
|
result = 0x02A000A2;
|
||||||
break;
|
break;
|
||||||
|
@ -541,7 +544,7 @@ DEVICE_READ32(PMC)
|
||||||
result = NV20_REG_BASE_KERNEL;
|
result = NV20_REG_BASE_KERNEL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PMC);
|
DEVICE_READ32_REG(pmc); // Was : DEBUG_READ32_UNHANDLED(PMC);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PMC);
|
DEVICE_READ32_END(PMC);
|
||||||
|
@ -549,7 +552,7 @@ DEVICE_READ32(PMC)
|
||||||
|
|
||||||
DEVICE_WRITE32(PMC)
|
DEVICE_WRITE32(PMC)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PMC, addr) {
|
switch(addr) {
|
||||||
case NV_PMC_INTR_0:
|
case NV_PMC_INTR_0:
|
||||||
pmc.pending_interrupts &= ~value;
|
pmc.pending_interrupts &= ~value;
|
||||||
update_irq();
|
update_irq();
|
||||||
|
@ -560,14 +563,16 @@ DEVICE_WRITE32(PMC)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PMC);
|
DEVICE_WRITE32_REG(pmc); // Was : DEBUG_WRITE32_UNHANDLED(PMC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PMC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PBUS)
|
DEVICE_READ32(PBUS)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
case NV_PBUS_PCI_NV_0:
|
case NV_PBUS_PCI_NV_0:
|
||||||
result = 0x10de; // PCI_VENDOR_ID_NVIDIA (?where to return PCI_DEVICE_ID_NVIDIA_NV2A = 0x01b7)
|
result = 0x10de; // PCI_VENDOR_ID_NVIDIA (?where to return PCI_DEVICE_ID_NVIDIA_NV2A = 0x01b7)
|
||||||
|
|
||||||
|
@ -580,7 +585,7 @@ DEVICE_READ32(PBUS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PBUS);
|
DEBUG_READ32_UNHANDLED(PBUS); // TODO : DEVICE_READ32_REG(pbus);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PBUS);
|
DEVICE_READ32_END(PBUS);
|
||||||
|
@ -588,23 +593,27 @@ DEVICE_READ32(PBUS)
|
||||||
|
|
||||||
DEVICE_WRITE32(PBUS)
|
DEVICE_WRITE32(PBUS)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PBUS, addr) {
|
switch(addr) {
|
||||||
|
case NV_PBUS_PCI_NV_1:
|
||||||
// TODO : Handle write on NV_PBUS_PCI_NV_1 with 1 (NV_PBUS_PCI_NV_1_IO_SPACE_ENABLED) + 4 (NV_PBUS_PCI_NV_1_BUS_MASTER_ENABLED)
|
// TODO : Handle write on NV_PBUS_PCI_NV_1 with 1 (NV_PBUS_PCI_NV_1_IO_SPACE_ENABLED) + 4 (NV_PBUS_PCI_NV_1_BUS_MASTER_ENABLED)
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PBUS);
|
DEBUG_WRITE32_UNHANDLED(PBUS); // TODO : DEVICE_WRITE32_REG(pbus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PBUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PFIFO)
|
DEVICE_READ32(PFIFO)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
case NV_PFIFO_RAMHT:
|
case NV_PFIFO_RAMHT:
|
||||||
result = 0x03000100; // = NV_PFIFO_RAMHT_SIZE_4K | NV_PFIFO_RAMHT_BASE_ADDRESS(NumberOfPaddingBytes >> 12) | NV_PFIFO_RAMHT_SEARCH_128
|
result = 0x03000100; // = NV_PFIFO_RAMHT_SIZE_4K | NV_PFIFO_RAMHT_BASE_ADDRESS(NumberOfPaddingBytes >> 12) | NV_PFIFO_RAMHT_SEARCH_128
|
||||||
case NV_PFIFO_RAMFC:
|
case NV_PFIFO_RAMFC:
|
||||||
result = 0x00890110; // = ? | NV_PFIFO_RAMFC_SIZE_2K | ?
|
result = 0x00890110; // = ? | NV_PFIFO_RAMFC_SIZE_2K | ?
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PFIFO);
|
DEVICE_READ32_REG(pfifo); // Was : DEBUG_READ32_UNHANDLED(PFIFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PFIFO);
|
DEVICE_READ32_END(PFIFO);
|
||||||
|
@ -612,18 +621,20 @@ DEVICE_READ32(PFIFO)
|
||||||
|
|
||||||
DEVICE_WRITE32(PFIFO)
|
DEVICE_WRITE32(PFIFO)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PFIFO, addr) {
|
switch(addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PFIFO);
|
DEVICE_WRITE32_REG(pfifo); // Was : DEBUG_WRITE32_UNHANDLED(PFIFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PFIFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRMA)
|
DEVICE_READ32(PRMA)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRMA);
|
DEBUG_READ32_UNHANDLED(PRMA); // TODO : DEVICE_READ32_REG(prma);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PRMA);
|
DEVICE_READ32_END(PRMA);
|
||||||
|
@ -631,22 +642,24 @@ DEVICE_READ32(PRMA)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRMA)
|
DEVICE_WRITE32(PRMA)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRMA, addr) {
|
switch(addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRMA);
|
DEBUG_WRITE32_UNHANDLED(PRMA); // TODO : DEVICE_WRITE32_REG(prma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PVIDEO)
|
DEVICE_READ32(PVIDEO)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
|
|
||||||
case NV_PVIDEO_STOP:
|
case NV_PVIDEO_STOP:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = pvideo.regs[addr];
|
DEVICE_READ32_REG(pvideo);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PVIDEO);
|
DEVICE_READ32_END(PVIDEO);
|
||||||
|
@ -654,17 +667,19 @@ DEVICE_READ32(PVIDEO)
|
||||||
|
|
||||||
DEVICE_WRITE32(PVIDEO)
|
DEVICE_WRITE32(PVIDEO)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PVIDEO, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
pvideo.regs[addr] = value;
|
DEVICE_WRITE32_REG(pvideo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PVIDEO);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32(PCOUNTER)
|
DEVICE_READ32(PCOUNTER)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PCOUNTER);
|
DEBUG_READ32_UNHANDLED(PCOUNTER); // TODO : DEVICE_READ32_REG(pcounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PCOUNTER);
|
DEVICE_READ32_END(PCOUNTER);
|
||||||
|
@ -672,16 +687,18 @@ DEVICE_READ32(PCOUNTER)
|
||||||
|
|
||||||
DEVICE_WRITE32(PCOUNTER)
|
DEVICE_WRITE32(PCOUNTER)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PCOUNTER, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PCOUNTER);
|
DEBUG_WRITE32_UNHANDLED(PCOUNTER); // TODO : DEVICE_WRITE32_REG(pcounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PCOUNTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PTIMER)
|
DEVICE_READ32(PTIMER)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
|
|
||||||
case NV_PTIMER_DENOMINATOR:
|
case NV_PTIMER_DENOMINATOR:
|
||||||
result = ptimer.denominator;
|
result = ptimer.denominator;
|
||||||
|
@ -693,7 +710,7 @@ DEVICE_READ32(PTIMER)
|
||||||
result = ptimer.alarm_time;
|
result = ptimer.alarm_time;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PTIMER);
|
DEVICE_READ32_REG(ptimer); // Was : DEBUG_READ32_UNHANDLED(PTIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PTIMER);
|
DEVICE_READ32_END(PTIMER);
|
||||||
|
@ -702,7 +719,7 @@ DEVICE_READ32(PTIMER)
|
||||||
|
|
||||||
DEVICE_WRITE32(PTIMER)
|
DEVICE_WRITE32(PTIMER)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PTIMER, addr) {
|
switch (addr) {
|
||||||
|
|
||||||
case NV_PTIMER_INTR_0:
|
case NV_PTIMER_INTR_0:
|
||||||
ptimer.pending_interrupts &= ~value;
|
ptimer.pending_interrupts &= ~value;
|
||||||
|
@ -723,16 +740,18 @@ DEVICE_WRITE32(PTIMER)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PTIMER);
|
DEVICE_WRITE32_REG(ptimer); // Was : DEBUG_WRITE32_UNHANDLED(PTIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PTIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PVPE)
|
DEVICE_READ32(PVPE)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PVPE);
|
DEBUG_READ32_UNHANDLED(PVPE); // TODO : DEVICE_READ32_REG(pvpe);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PVPE);
|
DEVICE_READ32_END(PVPE);
|
||||||
|
@ -741,18 +760,20 @@ DEVICE_READ32(PVPE)
|
||||||
|
|
||||||
DEVICE_WRITE32(PVPE)
|
DEVICE_WRITE32(PVPE)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PVPE, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PVPE);
|
DEBUG_WRITE32_UNHANDLED(PVPE); // TODO : DEVICE_WRITE32_REG(pvpe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PVPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PTV)
|
DEVICE_READ32(PTV)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PTV);
|
DEBUG_READ32_UNHANDLED(PTV); // TODO : DEVICE_READ32_REG(ptv);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PTV);
|
DEVICE_READ32_END(PTV);
|
||||||
|
@ -760,18 +781,20 @@ DEVICE_READ32(PTV)
|
||||||
|
|
||||||
DEVICE_WRITE32(PTV)
|
DEVICE_WRITE32(PTV)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PTV, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PTV);
|
DEBUG_WRITE32_UNHANDLED(PTV); // TODO : DEVICE_WRITE32_REG(ptv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PTV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRMFB)
|
DEVICE_READ32(PRMFB)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRMFB);
|
DEBUG_READ32_UNHANDLED(PRMFB); // TODO : DEVICE_READ32_REG(prmfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PRMFB);
|
DEVICE_READ32_END(PRMFB);
|
||||||
|
@ -779,18 +802,20 @@ DEVICE_READ32(PRMFB)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRMFB)
|
DEVICE_WRITE32(PRMFB)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRMFB, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRMFB);
|
DEBUG_WRITE32_UNHANDLED(PRMFB); // TODO : DEVICE_WRITE32_REG(prmfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRMFB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRMVIO)
|
DEVICE_READ32(PRMVIO)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRMVIO);
|
DEBUG_READ32_UNHANDLED(PRMVIO); // TODO : DEVICE_READ32_REG(prmvio);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PRMVIO);
|
DEVICE_READ32_END(PRMVIO);
|
||||||
|
@ -798,20 +823,22 @@ DEVICE_READ32(PRMVIO)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRMVIO)
|
DEVICE_WRITE32(PRMVIO)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRMVIO, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRMVIO);
|
DEBUG_WRITE32_UNHANDLED(PRMVIO); // TODO : DEVICE_WRITE32_REG(prmvio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRMVIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PFB)
|
DEVICE_READ32(PFB)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
case NV_PFB_CFG0:
|
case NV_PFB_CFG0:
|
||||||
result = 3; // = NV_PFB_CFG0_PART_4
|
result = 3; // = NV_PFB_CFG0_PART_4
|
||||||
default:
|
default:
|
||||||
result = pfb.regs[addr];
|
DEVICE_READ32_REG(pfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PFB);
|
DEVICE_READ32_END(PFB);
|
||||||
|
@ -819,16 +846,18 @@ DEVICE_READ32(PFB)
|
||||||
|
|
||||||
DEVICE_WRITE32(PFB)
|
DEVICE_WRITE32(PFB)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PFB, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
pfb.regs[addr] = value;
|
DEVICE_WRITE32_REG(pfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PFB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PSTRAPS)
|
DEVICE_READ32(PSTRAPS)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PSTRAPS);
|
DEBUG_READ32_UNHANDLED(PSTRAPS);
|
||||||
}
|
}
|
||||||
|
@ -838,16 +867,18 @@ DEVICE_READ32(PSTRAPS)
|
||||||
|
|
||||||
DEVICE_WRITE32(PSTRAPS)
|
DEVICE_WRITE32(PSTRAPS)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PSTRAPS, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PSTRAPS);
|
DEBUG_WRITE32_UNHANDLED(PSTRAPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PSTRAPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PGRAPH)
|
DEVICE_READ32(PGRAPH)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PGRAPH);
|
DEBUG_READ32_UNHANDLED(PGRAPH);
|
||||||
}
|
}
|
||||||
|
@ -857,7 +888,7 @@ DEVICE_READ32(PGRAPH)
|
||||||
|
|
||||||
DEVICE_WRITE32(PGRAPH)
|
DEVICE_WRITE32(PGRAPH)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PGRAPH, addr) {
|
switch (addr) {
|
||||||
case NV_PGRAPH_INTR:
|
case NV_PGRAPH_INTR:
|
||||||
pgraph.pending_interrupts &= ~value;
|
pgraph.pending_interrupts &= ~value;
|
||||||
update_irq();
|
update_irq();
|
||||||
|
@ -867,14 +898,16 @@ DEVICE_WRITE32(PGRAPH)
|
||||||
update_irq();
|
update_irq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PGRAPH);
|
DEVICE_WRITE32_REG(pgraph); // Was : DEBUG_WRITE32_UNHANDLED(PGRAPH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PGRAPH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PCRTC)
|
DEVICE_READ32(PCRTC)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
|
|
||||||
case NV_PCRTC_INTR_0:
|
case NV_PCRTC_INTR_0:
|
||||||
result = pcrtc.pending_interrupts;
|
result = pcrtc.pending_interrupts;
|
||||||
|
@ -886,7 +919,7 @@ DEVICE_READ32(PCRTC)
|
||||||
result = pcrtc.start;
|
result = pcrtc.start;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PCRTC);
|
DEVICE_READ32_REG(pcrtc); // Was : DEBUG_READ32_UNHANDLED(PCRTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PCRTC);
|
DEVICE_READ32_END(PCRTC);
|
||||||
|
@ -894,7 +927,7 @@ DEVICE_READ32(PCRTC)
|
||||||
|
|
||||||
DEVICE_WRITE32(PCRTC)
|
DEVICE_WRITE32(PCRTC)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PCRTC, addr) {
|
switch (addr) {
|
||||||
|
|
||||||
case NV_PCRTC_INTR_0:
|
case NV_PCRTC_INTR_0:
|
||||||
pcrtc.pending_interrupts &= ~value;
|
pcrtc.pending_interrupts &= ~value;
|
||||||
|
@ -909,14 +942,16 @@ DEVICE_WRITE32(PCRTC)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PCRTC);
|
DEVICE_WRITE32_REG(pcrtc); // Was : DEBUG_WRITE32_UNHANDLED(PCRTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PCRTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRMCIO)
|
DEVICE_READ32(PRMCIO)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRMCIO);
|
DEBUG_READ32_UNHANDLED(PRMCIO);
|
||||||
}
|
}
|
||||||
|
@ -926,16 +961,18 @@ DEVICE_READ32(PRMCIO)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRMCIO)
|
DEVICE_WRITE32(PRMCIO)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRMCIO, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRMCIO);
|
DEBUG_WRITE32_UNHANDLED(PRMCIO); // TODO : DEVICE_WRITE32_REG(prmcio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRMCIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRAMDAC)
|
DEVICE_READ32(PRAMDAC)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
|
|
||||||
case NV_PRAMDAC_NVPLL_COEFF:
|
case NV_PRAMDAC_NVPLL_COEFF:
|
||||||
result = pramdac.core_clock_coeff;
|
result = pramdac.core_clock_coeff;
|
||||||
|
@ -955,7 +992,7 @@ DEVICE_READ32(PRAMDAC)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRAMDAC);
|
DEVICE_READ32_REG(pramdac); // Was : DEBUG_READ32_UNHANDLED(PRAMDAC);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PRAMDAC);
|
DEVICE_READ32_END(PRAMDAC);
|
||||||
|
@ -963,7 +1000,7 @@ DEVICE_READ32(PRAMDAC)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRAMDAC)
|
DEVICE_WRITE32(PRAMDAC)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRAMDAC, addr) {
|
switch (addr) {
|
||||||
|
|
||||||
case NV_PRAMDAC_NVPLL_COEFF:
|
case NV_PRAMDAC_NVPLL_COEFF:
|
||||||
pramdac.core_clock_coeff = value;
|
pramdac.core_clock_coeff = value;
|
||||||
|
@ -976,14 +1013,16 @@ DEVICE_WRITE32(PRAMDAC)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRAMDAC);
|
DEVICE_WRITE32_REG(pramdac); // Was : DEBUG_WRITE32_UNHANDLED(PRAMDAC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRAMDAC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRMDIO)
|
DEVICE_READ32(PRMDIO)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(PRMDIO);
|
DEBUG_READ32_UNHANDLED(PRMDIO);
|
||||||
}
|
}
|
||||||
|
@ -993,18 +1032,20 @@ DEVICE_READ32(PRMDIO)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRMDIO)
|
DEVICE_WRITE32(PRMDIO)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRMDIO, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(PRMDIO);
|
DEBUG_WRITE32_UNHANDLED(PRMDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRMDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(PRAMIN)
|
DEVICE_READ32(PRAMIN)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
result = pramin.regs[addr];
|
DEVICE_READ32_REG(pramin);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_READ32_END(PRAMIN);
|
DEVICE_READ32_END(PRAMIN);
|
||||||
|
@ -1012,16 +1053,18 @@ DEVICE_READ32(PRAMIN)
|
||||||
|
|
||||||
DEVICE_WRITE32(PRAMIN)
|
DEVICE_WRITE32(PRAMIN)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(PRAMIN, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
pramin.regs[addr] = value;
|
DEVICE_WRITE32_REG(pramin);
|
||||||
}
|
/ }
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(PRAMIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVICE_READ32(USER)
|
DEVICE_READ32(USER)
|
||||||
{
|
{
|
||||||
DEVICE_READ32_SWITCH(addr) {
|
DEVICE_READ32_SWITCH() {
|
||||||
default:
|
default:
|
||||||
DEBUG_READ32_UNHANDLED(USER);
|
DEBUG_READ32_UNHANDLED(USER);
|
||||||
}
|
}
|
||||||
|
@ -1031,10 +1074,12 @@ DEVICE_READ32(USER)
|
||||||
|
|
||||||
DEVICE_WRITE32(USER)
|
DEVICE_WRITE32(USER)
|
||||||
{
|
{
|
||||||
DEVICE_WRITE32_SWITCH(USER, addr) {
|
switch (addr) {
|
||||||
default:
|
default:
|
||||||
DEBUG_WRITE32_UNHANDLED(USER);
|
DEBUG_WRITE32_UNHANDLED(USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_WRITE32_END(USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#include "EmuNV2A.h"
|
#include "EmuNV2A.h"
|
||||||
#include "HLEIntercept.h" // for bLLE_GPU
|
#include "HLEIntercept.h" // for bLLE_GPU
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read & write handlers handlers for I/O
|
// Read & write handlers handlers for I/O
|
||||||
//
|
//
|
||||||
|
@ -130,86 +132,138 @@ void EmuX86_Mem_Write8(xbaddr addr, uint8_t value)
|
||||||
// Read & write handlers for memory-mapped hardware devices
|
// Read & write handlers for memory-mapped hardware devices
|
||||||
//
|
//
|
||||||
|
|
||||||
uint32_t EmuX86_Read32(xbaddr addr)
|
uint32_t EmuX86_Read32Aligned(xbaddr addr)
|
||||||
{
|
{
|
||||||
// TODO : Should we assert ((addr & 3) == 0) here?
|
assert((addr & 3) == 0);
|
||||||
uint32_t value = 0;
|
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) {
|
if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) {
|
||||||
if (!bLLE_GPU) {
|
if (!bLLE_GPU) {
|
||||||
EmuWarning("EmuX86_Read32(0x%08X) Unexpected NV2A access, missing a HLE patch. " \
|
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);
|
"Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr);
|
||||||
} else
|
}
|
||||||
|
|
||||||
|
// Access NV2A regardless weither HLE is disabled or not
|
||||||
value = EmuNV2A_Read32(addr - NV2A_ADDR);
|
value = EmuNV2A_Read32(addr - NV2A_ADDR);
|
||||||
} else
|
// Note : EmuNV2A_Read32 does it's own logging
|
||||||
if (g_bEmuException)
|
} else {
|
||||||
EmuWarning("EmuX86_Read32(0x%08X) [Unknown address]", addr);
|
if (g_bEmuException) {
|
||||||
else
|
EmuWarning("EmuX86_Read32Aligned(0x%08X) [Unknown address]", addr);
|
||||||
|
value = 0;
|
||||||
|
} else {
|
||||||
// Outside EmuException, pass the memory-access through to normal memory :
|
// Outside EmuException, pass the memory-access through to normal memory :
|
||||||
value = EmuX86_Mem_Read32(addr);
|
value = EmuX86_Mem_Read32(addr);
|
||||||
|
}
|
||||||
|
DbgPrintf("EmuX86_Read32Aligned(0x%08X) = 0x%08X\n", addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EmuX86_Read32(xbaddr addr)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
if ((addr & 3) == 0)
|
||||||
|
value = EmuX86_Read32Aligned(addr);
|
||||||
|
else {
|
||||||
|
EmuWarning("EmuX86_Read32(0x%08X) [Unaligned unimplemented]", addr);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
DbgPrintf("EmuX86_Read32(0x%08X) = 0x%04X", addr, value);
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t EmuX86_Read16(xbaddr addr)
|
uint16_t EmuX86_Read16(xbaddr addr)
|
||||||
{
|
{
|
||||||
DbgPrintf("EmuX86_Read16(0x%08X) Forwarding to EmuX86_Read32...", addr);
|
DbgPrintf("EmuX86_Read16(0x%08X) Forwarding to EmuX86_Read32Aligned...\n", addr);
|
||||||
uint16_t value;
|
|
||||||
if (addr & 2)
|
|
||||||
value = (uint16_t)(EmuX86_Read32(addr - 2) >> 16);
|
|
||||||
else
|
|
||||||
value = (uint16_t)EmuX86_Read32(addr);
|
|
||||||
|
|
||||||
DbgPrintf("EmuX86_Read16(0x%08X) = 0x%04X", addr, value);
|
int shift = (addr & 3) * 8;
|
||||||
|
xbaddr aligned_addr = addr & ~3;
|
||||||
|
uint16_t value = (uint16_t)(EmuX86_Read32Aligned(aligned_addr) >> shift);
|
||||||
|
|
||||||
|
// Must the second byte be retrieved from the next DWORD?
|
||||||
|
if ((addr & 3) == 3)
|
||||||
|
value |= (uint16_t)((EmuX86_Read32Aligned(aligned_addr + 4) & 0xff) << 8);
|
||||||
|
|
||||||
|
DbgPrintf("EmuX86_Read16(0x%08X) = 0x%04X\n", addr, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t EmuX86_Read8(xbaddr addr)
|
uint8_t EmuX86_Read8(xbaddr addr)
|
||||||
{
|
{
|
||||||
DbgPrintf("EmuX86_Read8(0x%08X) Forwarding to EmuX86_Read16...", addr);
|
DbgPrintf("EmuX86_Read8(0x%08X) Forwarding to EmuX86_Read32Aligned...\n", addr);
|
||||||
uint8_t value;
|
|
||||||
if (addr & 1)
|
|
||||||
value = (uint8_t)(EmuX86_Read16(addr - 1) >> 8);
|
|
||||||
else
|
|
||||||
value = (uint8_t)EmuX86_Read16(addr);
|
|
||||||
|
|
||||||
DbgPrintf("EmuX86_Read8(0x%08X) = 0x%02X", addr, value);
|
int shift = (addr & 3) * 8;
|
||||||
|
xbaddr aligned_addr = addr & ~3;
|
||||||
|
uint8_t value = (uint8_t)(EmuX86_Read32Aligned(aligned_addr) >> shift);
|
||||||
|
|
||||||
|
DbgPrintf("EmuX86_Read8(0x%08X) = 0x%02X\n", addr, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuX86_Write32(xbaddr addr, uint32_t value)
|
void EmuX86_Write32Aligned(xbaddr addr, uint32_t value)
|
||||||
{
|
{
|
||||||
// TODO : Should we assert ((addr & 3) == 0) here?
|
assert((addr & 3) == 0);
|
||||||
|
|
||||||
if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) {
|
if (addr >= NV2A_ADDR && addr < NV2A_ADDR + NV2A_SIZE) {
|
||||||
if (!bLLE_GPU) {
|
if (!bLLE_GPU) {
|
||||||
EmuWarning("EmuX86_Write32(0x%08X, 0x%08X) Unexpected NV2A access, missing a HLE patch. " \
|
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);
|
"Please notify https://github.com/Cxbx-Reloaded/Cxbx-Reloaded which title raised this!", addr);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Access NV2A regardless weither HLE is disabled or not
|
||||||
EmuNV2A_Write32(addr - NV2A_ADDR, value);
|
EmuNV2A_Write32(addr - NV2A_ADDR, value);
|
||||||
|
// Note : EmuNV2A_Write32 does it's own logging
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_bEmuException) {
|
if (g_bEmuException) {
|
||||||
EmuWarning("EmuX86_Write32(0x%08X, 0x%08X) [Unknown address]", addr, value);
|
EmuWarning("EmuX86_Write32Aligned(0x%08X, 0x%08X) [Unknown address]", addr, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outside EmuException, pass the memory-access through to normal memory :
|
// Outside EmuException, pass the memory-access through to normal memory :
|
||||||
|
DbgPrintf("EmuX86_Write32Aligned(0x%08X, 0x%08X)\n", addr, value);
|
||||||
EmuX86_Mem_Write32(addr, value);
|
EmuX86_Mem_Write32(addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuX86_Write32(xbaddr addr, uint32_t value)
|
||||||
|
{
|
||||||
|
if ((addr & 3) == 0) {
|
||||||
|
EmuX86_Write32Aligned(addr, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
EmuWarning("EmuX86_Write32(0x%08X, 0x%08X) [Unaligned unimplemented]", addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
void EmuX86_Write16(xbaddr addr, uint16_t value)
|
void EmuX86_Write16(xbaddr addr, uint16_t value)
|
||||||
{
|
{
|
||||||
EmuWarning("EmuX86_Write16(0x%08X, 0x%04X) [Unknown address]", addr, value);
|
DbgPrintf("EmuX86_Write16(0x%08X, 0x%04X) Forwarding to EmuX86_Read32Aligned+EmuX86_Write32Aligned\n", addr, value);
|
||||||
// TODO : If decided to do so, read32, mask value in, and forward to write32
|
|
||||||
|
assert((addr & 1) == 0);
|
||||||
|
|
||||||
|
int shift = (addr & 2) * 16;
|
||||||
|
xbaddr aligned_addr = addr & ~3;
|
||||||
|
uint32_t aligned_value = EmuX86_Read32Aligned(aligned_addr);
|
||||||
|
uint32_t mask = 0xFFFF << shift;
|
||||||
|
|
||||||
|
// TODO : Must the second byte be written to the next DWORD?
|
||||||
|
|
||||||
|
EmuX86_Write32Aligned(aligned_addr, (aligned_value & ~mask) | (value << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuX86_Write8(xbaddr addr, uint8_t value)
|
void EmuX86_Write8(xbaddr addr, uint8_t value)
|
||||||
{
|
{
|
||||||
EmuWarning("EmuX86_Write8(0x%08X, 0x%02X) [Unknown address]", addr, value);
|
DbgPrintf("EmuX86_Write8(0x%08X, 0x%02X) Forwarding to EmuX86_Read32Aligned+EmuX86_Write32Aligned\n", addr, value);
|
||||||
// TODO : If decided to do so, read16, mask value in, and forward to write16
|
|
||||||
|
int shift = (addr & 3) * 8;
|
||||||
|
xbaddr aligned_addr = addr & ~3;
|
||||||
|
uint32_t aligned_value = EmuX86_Read32Aligned(aligned_addr);
|
||||||
|
uint32_t mask = 0xFF << shift;
|
||||||
|
|
||||||
|
EmuX86_Write32Aligned(aligned_addr, (aligned_value & ~mask) | (value << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 };
|
int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 };
|
||||||
|
@ -380,196 +434,154 @@ xbaddr EmuX86_Distorm_O_MEM_Addr(LPEXCEPTION_POINTERS e, _DInst& info, int opera
|
||||||
return base + index + (uint32_t)info.disp;
|
return base + index + (uint32_t)info.disp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuX86_Addr_Read(xbaddr srcAddr, uint16_t size, OUT uint32_t *value)
|
xbaddr EmuX86_Operand_Addr(LPEXCEPTION_POINTERS e, _DInst& info, int operand, bool &is_internal_addr)
|
||||||
{
|
|
||||||
switch (size) {
|
|
||||||
case 8:
|
|
||||||
*value = EmuX86_Read8(srcAddr);
|
|
||||||
return;
|
|
||||||
case 16:
|
|
||||||
*value = EmuX86_Read16(srcAddr);
|
|
||||||
return;
|
|
||||||
case 32:
|
|
||||||
*value = EmuX86_Read32(srcAddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuX86_Addr_Write(xbaddr destAddr, uint16_t size, uint32_t value)
|
|
||||||
{
|
|
||||||
switch (size) {
|
|
||||||
case 8:
|
|
||||||
EmuX86_Write8(destAddr, value & 0xFF);
|
|
||||||
return;
|
|
||||||
case 16:
|
|
||||||
EmuX86_Write16(destAddr, value & 0xFFFF);
|
|
||||||
return;
|
|
||||||
case 32:
|
|
||||||
EmuX86_Write32(destAddr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmuX86_Operand_Read(LPEXCEPTION_POINTERS e, _DInst& info, int operand, OUT uint32_t *value)
|
|
||||||
{
|
{
|
||||||
switch (info.ops[operand].type) {
|
switch (info.ops[operand].type) {
|
||||||
case O_NONE:
|
case O_NONE:
|
||||||
{
|
{
|
||||||
// ignore operand
|
// ignore operand
|
||||||
return true;
|
return (xbaddr)nullptr;
|
||||||
}
|
}
|
||||||
case O_REG:
|
case O_REG:
|
||||||
|
is_internal_addr = true;
|
||||||
|
return (xbaddr)EmuX86_GetRegisterPointer(e, info.ops[operand].index);
|
||||||
{
|
{
|
||||||
void* regAddr = EmuX86_GetRegisterPointer(e, info.ops[operand].index);
|
|
||||||
if (regAddr == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (info.ops[operand].size) {
|
|
||||||
case 8:
|
|
||||||
*value = *((uint8_t*)regAddr);
|
|
||||||
return true;
|
|
||||||
case 16:
|
|
||||||
*value = *((uint16_t*)regAddr);
|
|
||||||
return true;
|
|
||||||
case 32:
|
|
||||||
*value = *((uint32_t*)regAddr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
case O_IMM:
|
case O_IMM:
|
||||||
{
|
{
|
||||||
switch (info.ops[operand].size) {
|
is_internal_addr = true;
|
||||||
case 8:
|
return (xbaddr)(&info.imm);
|
||||||
*value = info.imm.byte;
|
|
||||||
return true;
|
|
||||||
case 16:
|
|
||||||
*value = info.imm.word;
|
|
||||||
return true;
|
|
||||||
case 32:
|
|
||||||
*value = info.imm.dword;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
case O_IMM1:
|
case O_IMM1:
|
||||||
{
|
{
|
||||||
// TODO
|
is_internal_addr = true;
|
||||||
return false;
|
return (xbaddr)(&info.imm.ex.i1);
|
||||||
}
|
}
|
||||||
case O_IMM2:
|
case O_IMM2:
|
||||||
{
|
{
|
||||||
// TODO
|
is_internal_addr = true;
|
||||||
return false;
|
return (xbaddr)(&info.imm.ex.i2);
|
||||||
}
|
}
|
||||||
case O_DISP:
|
case O_DISP:
|
||||||
{
|
{
|
||||||
xbaddr srcAddr = (xbaddr)info.disp;
|
is_internal_addr = false;
|
||||||
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
return (xbaddr)info.disp;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case O_SMEM:
|
case O_SMEM:
|
||||||
{
|
{
|
||||||
xbaddr srcAddr = EmuX86_Distorm_O_SMEM_Addr(e, info, operand);
|
is_internal_addr = false;
|
||||||
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
return EmuX86_Distorm_O_SMEM_Addr(e, info, operand);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case O_MEM:
|
case O_MEM:
|
||||||
{
|
{
|
||||||
xbaddr srcAddr = EmuX86_Distorm_O_MEM_Addr(e, info, operand);
|
is_internal_addr = false;
|
||||||
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
return EmuX86_Distorm_O_MEM_Addr(e, info, operand);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case O_PC:
|
case O_PC:
|
||||||
{
|
{
|
||||||
// TODO
|
is_internal_addr = false;
|
||||||
return false;
|
return (xbaddr)INSTRUCTION_GET_TARGET(&info);
|
||||||
}
|
}
|
||||||
case O_PTR:
|
case O_PTR:
|
||||||
{
|
{
|
||||||
// TODO
|
is_internal_addr = false;
|
||||||
return false;
|
return (xbaddr)info.imm.ptr.off; // TODO : What about info.imm.ptr.seg ?
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return (xbaddr)nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (xbaddr)nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Addr_Read(xbaddr srcAddr, bool is_internal_addr, uint16_t size, OUT uint32_t *value)
|
||||||
|
{
|
||||||
|
if (is_internal_addr)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
*value = *((uint8_t*)srcAddr);
|
||||||
|
return true;
|
||||||
|
case 16:
|
||||||
|
*value = *((uint16_t*)srcAddr);
|
||||||
|
return true;
|
||||||
|
case 32:
|
||||||
|
*value = *((uint32_t*)srcAddr);
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
*value = EmuX86_Read8(srcAddr);
|
||||||
|
return true;
|
||||||
|
case 16:
|
||||||
|
*value = EmuX86_Read16(srcAddr);
|
||||||
|
return true;
|
||||||
|
case 32:
|
||||||
|
*value = EmuX86_Read32(srcAddr);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Addr_Write(xbaddr destAddr, bool is_internal_addr, uint16_t size, uint32_t value)
|
||||||
|
{
|
||||||
|
if (is_internal_addr)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
*((uint8_t*)destAddr) = (uint8_t)value;
|
||||||
|
return true;
|
||||||
|
case 16:
|
||||||
|
*((uint16_t*)destAddr) = (uint16_t)value;
|
||||||
|
return true;
|
||||||
|
case 32:
|
||||||
|
*((uint32_t*)destAddr) = value;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
EmuX86_Write8(destAddr, value & 0xFF);
|
||||||
|
return true;
|
||||||
|
case 16:
|
||||||
|
EmuX86_Write16(destAddr, value & 0xFFFF);
|
||||||
|
return true;
|
||||||
|
case 32:
|
||||||
|
EmuX86_Write32(destAddr, value);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Operand_Read(LPEXCEPTION_POINTERS e, _DInst& info, int operand, OUT uint32_t *value)
|
||||||
|
{
|
||||||
|
bool is_internal_addr;
|
||||||
|
xbaddr srcAddr = EmuX86_Operand_Addr(e, info, operand, OUT is_internal_addr);
|
||||||
|
if (srcAddr != (xbaddr)nullptr)
|
||||||
|
return EmuX86_Addr_Read(srcAddr, is_internal_addr, info.ops[operand].size, value);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuX86_Operand_Write(LPEXCEPTION_POINTERS e, _DInst& info, int operand, uint32_t value)
|
bool EmuX86_Operand_Write(LPEXCEPTION_POINTERS e, _DInst& info, int operand, uint32_t value)
|
||||||
{
|
{
|
||||||
switch (info.ops[operand].type) {
|
bool is_internal_addr;
|
||||||
case O_NONE:
|
xbaddr destAddr = EmuX86_Operand_Addr(e, info, operand, OUT is_internal_addr);
|
||||||
{
|
if (destAddr != (xbaddr)nullptr)
|
||||||
// ignore operand
|
return EmuX86_Addr_Write(destAddr, is_internal_addr, info.ops[operand].size, value);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case O_REG:
|
|
||||||
{
|
|
||||||
void* regAddr = EmuX86_GetRegisterPointer(e, info.ops[operand].index);
|
|
||||||
if (regAddr == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (info.ops[operand].size) {
|
|
||||||
case 8:
|
|
||||||
*((uint8_t*)regAddr) = (uint8_t)value;
|
|
||||||
return true;
|
|
||||||
case 16:
|
|
||||||
*((uint16_t*)regAddr) = (uint16_t)value;
|
|
||||||
return true;
|
|
||||||
case 32:
|
|
||||||
*((uint32_t*)regAddr) = value;
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case O_IMM:
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case O_IMM1:
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case O_IMM2:
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case O_DISP:
|
|
||||||
{
|
|
||||||
xbaddr destAddr = (xbaddr)info.disp;
|
|
||||||
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case O_SMEM:
|
|
||||||
{
|
|
||||||
xbaddr destAddr = EmuX86_Distorm_O_SMEM_Addr(e, info, operand);
|
|
||||||
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case O_MEM:
|
|
||||||
{
|
|
||||||
xbaddr destAddr = EmuX86_Distorm_O_MEM_Addr(e, info, operand);
|
|
||||||
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case O_PC:
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case O_PTR:
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -582,9 +594,12 @@ bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// ADD reads and writes destination :
|
// ADD reads and writes destination :
|
||||||
xbaddr addr;
|
bool is_internal_addr;
|
||||||
// TODO : Implement EmuX86_Operand_Addr, then enable the following line :
|
xbaddr addr = EmuX86_Operand_Addr(e, info, 0, OUT is_internal_addr);
|
||||||
// if (!EmuX86_Operand_Addr(e, info, 0, &addr))
|
if (addr == (xbaddr)nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (is_internal_addr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO : Do this better
|
// TODO : Do this better
|
||||||
|
@ -776,6 +791,10 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
||||||
unsigned int decodedInstructionsCount = 0;
|
unsigned int decodedInstructionsCount = 0;
|
||||||
|
|
||||||
_CodeInfo ci;
|
_CodeInfo ci;
|
||||||
|
if (e->ContextRecord->Eip == 0x00023A8A)
|
||||||
|
// 00023A8A 03B2 28010000 add esi, [edx + $00000128]; CMiniport_SetDmaRange + 13E8
|
||||||
|
ci.code = (uint8_t*)e->ContextRecord->Eip;
|
||||||
|
else
|
||||||
ci.code = (uint8_t*)e->ContextRecord->Eip;
|
ci.code = (uint8_t*)e->ContextRecord->Eip;
|
||||||
ci.codeLen = 20;
|
ci.codeLen = 20;
|
||||||
ci.codeOffset = 0;
|
ci.codeOffset = 0;
|
||||||
|
|
Loading…
Reference in New Issue