Began porting NV2A emulation from XQEMU.
This commit is contained in:
parent
d424f0b004
commit
588aa5745b
|
@ -28,6 +28,11 @@
|
|||
// *
|
||||
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
|
||||
// * (c) 2016 Luke Usher <luke.usher@outlook.com>
|
||||
// *
|
||||
// * EmuNV2A.cpp is heavily based on code from XQEMU
|
||||
// * (c) XQEMU Team
|
||||
// * https://github.com/espes/xqemu/blob/xbox/hw/xbox/nv2a.c
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
|
@ -41,9 +46,80 @@
|
|||
#include "EmuNV2A.h"
|
||||
#include "nv2a_int.h" // from https://github.com/espes/xqemu/tree/xbox/hw/xbox
|
||||
|
||||
struct {
|
||||
uint32_t pending_interrupts;
|
||||
uint32_t enabled_interrupts;
|
||||
} pmc;
|
||||
struct {
|
||||
uint32_t pending_interrupts;
|
||||
uint32_t enabled_interrupts;
|
||||
//TODO:
|
||||
// QemuThread puller_thread;
|
||||
// Cache1State cache1;
|
||||
uint32_t regs[0x2000];
|
||||
} pfifo;
|
||||
struct {
|
||||
uint32_t regs[0x1000];
|
||||
} pvideo;
|
||||
struct {
|
||||
uint32_t pending_interrupts;
|
||||
uint32_t enabled_interrupts;
|
||||
uint32_t numerator;
|
||||
uint32_t denominator;
|
||||
uint32_t alarm_time;
|
||||
} ptimer;
|
||||
|
||||
struct {
|
||||
uint32_t regs[0x1000];
|
||||
} pfb;
|
||||
struct {
|
||||
uint32_t pending_interrupts;
|
||||
uint32_t enabled_interrupts;
|
||||
uint32_t start;
|
||||
} pcrtc;
|
||||
struct {
|
||||
uint32_t core_clock_coeff;
|
||||
uint64_t core_clock_freq;
|
||||
uint32_t memory_clock_coeff;
|
||||
uint32_t video_clock_coeff;
|
||||
} pramdac;
|
||||
|
||||
static void update_irq()
|
||||
{
|
||||
/* PFIFO */
|
||||
if (pfifo.pending_interrupts & pfifo.enabled_interrupts) {
|
||||
pmc.pending_interrupts |= NV_PMC_INTR_0_PFIFO;
|
||||
}
else {
|
||||
pmc.pending_interrupts &= ~NV_PMC_INTR_0_PFIFO;
|
||||
}
|
||||
if (pcrtc.pending_interrupts & pcrtc.enabled_interrupts) {
|
||||
pmc.pending_interrupts |= NV_PMC_INTR_0_PCRTC;
|
||||
}
else {
|
||||
pmc.pending_interrupts &= ~NV_PMC_INTR_0_PCRTC;
|
||||
}
|
||||
/* TODO PGRAPH */
|
||||
/*
|
||||
if (pgraph.pending_interrupts & pgraph.enabled_interrupts) {
|
||||
pmc.pending_interrupts |= NV_PMC_INTR_0_PGRAPH;
|
||||
}
else {
|
||||
pmc.pending_interrupts &= ~NV_PMC_INTR_0_PGRAPH;
|
||||
} */
|
||||
if (pmc.pending_interrupts && pmc.enabled_interrupts) {
|
||||
// TODO Raise IRQ
|
||||
EmuWarning("EmuNV2A: Raise IRQ Not Implemented");
|
||||
}
else {
|
||||
// TODO: Cancel IRQ
|
||||
EmuWarning("EmuNV2A: Cancel IRQ Not Implemented");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuNV2A_PMC_Read32(uint32_t addr)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PMC_BOOT_0: // chipset and stepping: NV2A, A02, Rev 0
return 0x02A000A2;
|
||||
case NV_PMC_INTR_0:
return pmc.pending_interrupts;
|
||||
case NV_PMC_INTR_EN_0:
|
||||
return pmc.enabled_interrupts;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PMC_Read32: Unknown Read Address %08X", addr);
|
||||
}
|
||||
|
@ -57,7 +133,7 @@ uint32_t EmuNV2A_PBUS_Read32(uint32_t addr)
|
|||
case NV_PBUS_PCI_NV_0:
|
||||
return 0x10de; // PCI_VENDOR_ID_NVIDIA
|
||||
case NV_PBUS_PCI_NV_2:
|
||||
return 0x0; // NV_PBUS_PCI_NV_2_REVISION_ID ??
|
||||
return (0x02 << 24) | 161; // PCI_CLASS_DISPLAY_3D (0x02) Rev 161 (0xA1)
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PBUS_Read32: Unknown Read Address %08X", addr);
|
||||
}
|
||||
|
@ -98,8 +174,10 @@ uint32_t EmuNV2A_PRMA_Read32(uint32_t addr)
|
|||
uint32_t EmuNV2A_PVIDEO_Read32(uint32_t addr)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PVIDEO_STOP:
|
||||
return 0;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PVIDEO_Read32: Unknown Read Address %08X", addr);
|
||||
return pvideo.regs[addr];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -198,6 +276,12 @@ uint32_t EmuNV2A_PGRAPH_Read32(uint32_t addr)
|
|||
uint32_t EmuNV2A_PCRTC_Read32(uint32_t addr)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PCRTC_INTR_0:
|
||||
return pcrtc.pending_interrupts;
|
||||
case NV_PCRTC_INTR_EN_0:
|
||||
return pcrtc.enabled_interrupts;
|
||||
case NV_PCRTC_START:
|
||||
return pcrtc.start;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PCRTC_Read32: Unknown Read Address %08X", addr);
|
||||
}
|
||||
|
@ -217,11 +301,27 @@ uint32_t EmuNV2A_PRMCIO_Read32(uint32_t addr)
|
|||
|
||||
uint32_t EmuNV2A_PRAMDAC_Read32(uint32_t addr)
|
||||
{
|
||||
switch (addr) {
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PRAMDAC_Read32: Unknown Read Address %08X", addr);
|
||||
switch (addr & 3) {
|
||||
case NV_PRAMDAC_NVPLL_COEFF:
|
||||
return pramdac.core_clock_coeff;
|
||||
break;
|
||||
case NV_PRAMDAC_MPLL_COEFF:
|
||||
return pramdac.memory_clock_coeff;
|
||||
break;
|
||||
case NV_PRAMDAC_VPLL_COEFF:
|
||||
return pramdac.video_clock_coeff;
|
||||
break;
|
||||
case NV_PRAMDAC_PLL_TEST_COUNTER:
|
||||
/* emulated PLLs locked instantly? */
|
||||
return NV_PRAMDAC_PLL_TEST_COUNTER_VPLL2_LOCK
|
||||
| NV_PRAMDAC_PLL_TEST_COUNTER_NVPLL_LOCK
|
||||
| NV_PRAMDAC_PLL_TEST_COUNTER_MPLL_LOCK
|
||||
| NV_PRAMDAC_PLL_TEST_COUNTER_VPLL_LOCK;
|
||||
break;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PRAMDAC_Read32: Unknown Read Address %08X", addr);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -309,6 +409,13 @@ uint32_t EmuNV2A_Read32(uint32_t addr)
|
|||
void EmuNV2A_PMC_Write32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PMC_INTR_0:
pmc.pending_interrupts &= ~value;
|
||||
update_irq();
|
||||
break;
|
||||
case NV_PMC_INTR_EN_0:
|
||||
pmc.enabled_interrupts = value;
|
||||
update_irq();
|
||||
break;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PMC_Write32: Unknown Write Address %08X (value %08X)", addr, value);
|
||||
}
|
||||
|
@ -366,6 +473,23 @@ void EmuNV2A_PCOUNTER_Write32(uint32_t addr, uint32_t value)
|
|||
void EmuNV2A_PTIMER_Write32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PTIMER_INTR_0:
|
||||
ptimer.pending_interrupts &= ~value;
|
||||
update_irq();
|
||||
break;
|
||||
case NV_PTIMER_INTR_EN_0:
|
||||
ptimer.enabled_interrupts = value;
|
||||
update_irq();
|
||||
break;
|
||||
case NV_PTIMER_DENOMINATOR:
|
||||
ptimer.denominator = value;
|
||||
break;
|
||||
case NV_PTIMER_NUMERATOR:
|
||||
ptimer.numerator = value;
|
||||
break;
|
||||
case NV_PTIMER_ALARM_0:
|
||||
ptimer.alarm_time = value;
|
||||
break;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PTIMER_Write32: Unknown Write Address %08X (value %08X)", addr, value);
|
||||
}
|
||||
|
@ -406,8 +530,8 @@ void EmuNV2A_PRMVIO_Write32(uint32_t addr, uint32_t value)
|
|||
void EmuNV2A_PFB_Write32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
switch (addr) {
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PFB_Write32: Unknown Write Address %08X (value %08X)", addr, value);
|
||||
default:
|
||||
pfb.regs[addr] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,6 +554,16 @@ void EmuNV2A_PGRAPH_Write32(uint32_t addr, uint32_t value)
|
|||
void EmuNV2A_PCRTC_Write32(uint32_t addr, uint32_t value)
|
||||
{
|
||||
switch (addr) {
|
||||
case NV_PCRTC_INTR_0:
|
||||
pcrtc.pending_interrupts &= ~value;
|
||||
update_irq();
|
||||
break;
|
||||
case NV_PCRTC_INTR_EN_0:
|
||||
pcrtc.enabled_interrupts = value;
|
||||
update_irq();
|
||||
break;
|
||||
case NV_PCRTC_START:
pcrtc.start = value &= 0x07FFFFFF;
|
||||
break;
|
||||
default:
|
||||
EmuWarning("EmuNV2A_PCRTC_Write32: Unknown Write Address %08X (value %08X)", addr, value);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue