diff --git a/build/win32/Cxbx.vcxproj b/build/win32/Cxbx.vcxproj
index c9092863b..4e104300a 100644
--- a/build/win32/Cxbx.vcxproj
+++ b/build/win32/Cxbx.vcxproj
@@ -355,6 +355,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/win32/Cxbx.vcxproj.filters b/build/win32/Cxbx.vcxproj.filters
index 3c42b3e7f..358179e2e 100644
--- a/build/win32/Cxbx.vcxproj.filters
+++ b/build/win32/Cxbx.vcxproj.filters
@@ -728,6 +728,69 @@
HLEDatabase\XOnline
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
+
+ Hardware
+
diff --git a/src/devices/video/EmuNV2A.cpp b/src/devices/video/EmuNV2A.cpp
index b4276b6f6..3bf947729 100644
--- a/src/devices/video/EmuNV2A.cpp
+++ b/src/devices/video/EmuNV2A.cpp
@@ -556,452 +556,7 @@ static void update_irq()
}
-#define DEBUG_START(DEV) \
-const char *DebugNV_##DEV##(xbaddr addr) \
-{ \
- switch (addr) {
-#define DEBUG_CASE(a) \
- case a: return #a;
-#define DEBUG_CASE_EX(a, c) \
- case a: return #a##c;
-#define DEBUG_END(DEV) \
- default: \
- return "Unknown " #DEV " Address"; \
- } \
-}
-
-DEBUG_START(PMC)
- DEBUG_CASE(NV_PMC_BOOT_0);
- DEBUG_CASE(NV_PMC_BOOT_1);
- DEBUG_CASE(NV_PMC_INTR_0);
- DEBUG_CASE(NV_PMC_INTR_EN_0);
- DEBUG_CASE(NV_PMC_ENABLE);
-DEBUG_END(PMC)
-
-DEBUG_START(PBUS)
- DEBUG_CASE(NV_PBUS_FBIO_RAM)
- DEBUG_CASE_EX(NV_PBUS_PCI_NV_0, ":VENDOR_ID");
- DEBUG_CASE(NV_PBUS_PCI_NV_1);
- DEBUG_CASE_EX(NV_PBUS_PCI_NV_2, ":REVISION_ID");
- DEBUG_CASE_EX(NV_PBUS_PCI_NV_3, ":LATENCY_TIMER");
- DEBUG_CASE(NV_PBUS_PCI_NV_4);
- DEBUG_CASE(NV_PBUS_PCI_NV_5);
- DEBUG_CASE(NV_PBUS_PCI_NV_6);
- DEBUG_CASE(NV_PBUS_PCI_NV_7);
- 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_13, ":CAP_PTR");
- DEBUG_CASE_EX(NV_PBUS_PCI_NV_14, ":RESERVED");
- DEBUG_CASE(NV_PBUS_PCI_NV_15);
- DEBUG_CASE_EX(NV_PBUS_PCI_NV_16, ":SUBSYSTEM");
- DEBUG_CASE(NV_PBUS_PCI_NV_17);
- 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_20, ":ROM_SHADOW");
- 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_23, ":DT_TIMEOUT");
- 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_26, ":RESERVED");
-DEBUG_END(PBUS)
-
-DEBUG_START(PFIFO)
- DEBUG_CASE(NV_PFIFO_DELAY_0);
- DEBUG_CASE(NV_PFIFO_DMA_TIMESLICE);
- DEBUG_CASE(NV_PFIFO_TIMESLICE);
- DEBUG_CASE(NV_PFIFO_INTR_0);
- DEBUG_CASE(NV_PFIFO_INTR_EN_0);
- DEBUG_CASE(NV_PFIFO_RAMHT);
- DEBUG_CASE(NV_PFIFO_RAMFC);
- DEBUG_CASE(NV_PFIFO_RAMRO);
- DEBUG_CASE(NV_PFIFO_RUNOUT_STATUS);
- DEBUG_CASE(NV_PFIFO_RUNOUT_PUT_ADDRESS);
- DEBUG_CASE(NV_PFIFO_RUNOUT_GET_ADDRESS);
- DEBUG_CASE(NV_PFIFO_CACHES);
- DEBUG_CASE(NV_PFIFO_MODE);
- DEBUG_CASE(NV_PFIFO_DMA);
- DEBUG_CASE(NV_PFIFO_SIZE)
- DEBUG_CASE(NV_PFIFO_CACHE0_PUSH0);
- DEBUG_CASE(NV_PFIFO_CACHE0_PULL0);
- DEBUG_CASE(NV_PFIFO_CACHE0_HASH);
- DEBUG_CASE(NV_PFIFO_CACHE1_PUSH0);
- DEBUG_CASE(NV_PFIFO_CACHE1_PUSH1);
- DEBUG_CASE(NV_PFIFO_CACHE1_PUT);
- DEBUG_CASE(NV_PFIFO_CACHE1_STATUS);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_PUSH);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_FETCH);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_STATE);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_INSTANCE);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_CTL);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_PUT);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_GET);
- DEBUG_CASE(NV_PFIFO_CACHE1_REF);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_SUBROUTINE);
- DEBUG_CASE(NV_PFIFO_CACHE1_PULL0);
- DEBUG_CASE(NV_PFIFO_CACHE1_PULL1);
- DEBUG_CASE(NV_PFIFO_CACHE1_HASH);
- DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_0);
- DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_1);
- DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_2);
- DEBUG_CASE(NV_PFIFO_CACHE1_SEMAPHORE);
- DEBUG_CASE(NV_PFIFO_CACHE1_GET);
- DEBUG_CASE(NV_PFIFO_CACHE1_ENGINE);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_DCOUNT);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_RSVD_SHADOW);
- DEBUG_CASE(NV_PFIFO_CACHE1_DMA_DATA_SHADOW);
-DEBUG_END(PFIFO)
-
-DEBUG_START(PRMA)
-DEBUG_END(PRMA)
-
-DEBUG_START(PVIDEO)
- DEBUG_CASE(NV_PVIDEO_DEBUG_2);
- DEBUG_CASE(NV_PVIDEO_DEBUG_3);
- DEBUG_CASE(NV_PVIDEO_INTR);
- DEBUG_CASE(NV_PVIDEO_INTR_EN);
- DEBUG_CASE(NV_PVIDEO_BUFFER);
- DEBUG_CASE(NV_PVIDEO_STOP);
- DEBUG_CASE(NV_PVIDEO_BASE(0));
- DEBUG_CASE(NV_PVIDEO_BASE(1));
- DEBUG_CASE(NV_PVIDEO_LIMIT(0));
- DEBUG_CASE(NV_PVIDEO_LIMIT(1));
- DEBUG_CASE(NV_PVIDEO_LUMINANCE(0));
- DEBUG_CASE(NV_PVIDEO_LUMINANCE(1));
- DEBUG_CASE(NV_PVIDEO_CHROMINANCE(0));
- DEBUG_CASE(NV_PVIDEO_CHROMINANCE(1));
- DEBUG_CASE(NV_PVIDEO_OFFSET(0));
- DEBUG_CASE(NV_PVIDEO_OFFSET(1));
- DEBUG_CASE(NV_PVIDEO_SIZE_IN(0));
- DEBUG_CASE(NV_PVIDEO_SIZE_IN(1));
- DEBUG_CASE(NV_PVIDEO_POINT_IN(0));
- DEBUG_CASE(NV_PVIDEO_POINT_IN(1));
- DEBUG_CASE(NV_PVIDEO_DS_DX(0));
- DEBUG_CASE(NV_PVIDEO_DS_DX(1));
- DEBUG_CASE(NV_PVIDEO_DT_DY(0));
- DEBUG_CASE(NV_PVIDEO_DT_DY(1));
- DEBUG_CASE(NV_PVIDEO_POINT_OUT(0));
- DEBUG_CASE(NV_PVIDEO_POINT_OUT(1));
- DEBUG_CASE(NV_PVIDEO_SIZE_OUT(0));
- DEBUG_CASE(NV_PVIDEO_SIZE_OUT(1));
- DEBUG_CASE(NV_PVIDEO_FORMAT(0));
- DEBUG_CASE(NV_PVIDEO_FORMAT(1));
-DEBUG_END(PVIDEO)
-
-DEBUG_START(PTIMER)
- DEBUG_CASE(NV_PTIMER_INTR_0);
- DEBUG_CASE(NV_PTIMER_INTR_EN_0);
- DEBUG_CASE(NV_PTIMER_NUMERATOR);
- DEBUG_CASE(NV_PTIMER_DENOMINATOR);
- DEBUG_CASE(NV_PTIMER_TIME_0);
- DEBUG_CASE(NV_PTIMER_TIME_1);
- DEBUG_CASE(NV_PTIMER_ALARM_0);
-DEBUG_END(PTIMER)
-
-DEBUG_START(PCOUNTER)
-DEBUG_END(PCOUNTER)
-
-DEBUG_START(PVPE)
-DEBUG_END(PVPE)
-
-DEBUG_START(PTV)
-DEBUG_END(PTV)
-
-DEBUG_START(PRMFB)
-DEBUG_END(PRMFB)
-
-DEBUG_START(PRMVIO)
-DEBUG_END(PRMVIO)
-
-DEBUG_START(PFB)
- DEBUG_CASE(NV_PFB_CFG0)
- DEBUG_CASE(NV_PFB_CFG1)
- DEBUG_CASE(NV_PFB_CSTATUS)
- DEBUG_CASE(NV_PFB_REFCTRL)
- DEBUG_CASE(NV_PFB_NVM) // NV_PFB_NVM_MODE_DISABLE
- DEBUG_CASE(NV_PFB_PIN)
- DEBUG_CASE(NV_PFB_PAD)
- DEBUG_CASE(NV_PFB_TIMING0)
- DEBUG_CASE(NV_PFB_TIMING1)
- DEBUG_CASE(NV_PFB_TIMING2)
- DEBUG_CASE(NV_PFB_TILE(0))
- DEBUG_CASE(NV_PFB_TLIMIT(0))
- DEBUG_CASE(NV_PFB_TSIZE(0))
- DEBUG_CASE(NV_PFB_TSTATUS(0))
- DEBUG_CASE(NV_PFB_TILE(1))
- DEBUG_CASE(NV_PFB_TLIMIT(1))
- DEBUG_CASE(NV_PFB_TSIZE(1))
- DEBUG_CASE(NV_PFB_TSTATUS(1))
- DEBUG_CASE(NV_PFB_TILE(2))
- DEBUG_CASE(NV_PFB_TLIMIT(2))
- DEBUG_CASE(NV_PFB_TSIZE(2))
- DEBUG_CASE(NV_PFB_TSTATUS(2))
- DEBUG_CASE(NV_PFB_TILE(3))
- DEBUG_CASE(NV_PFB_TLIMIT(3))
- DEBUG_CASE(NV_PFB_TSIZE(3))
- DEBUG_CASE(NV_PFB_TSTATUS(3))
- DEBUG_CASE(NV_PFB_TILE(4))
- DEBUG_CASE(NV_PFB_TLIMIT(4))
- DEBUG_CASE(NV_PFB_TSIZE(4))
- DEBUG_CASE(NV_PFB_TSTATUS(4))
- DEBUG_CASE(NV_PFB_TILE(5))
- DEBUG_CASE(NV_PFB_TLIMIT(5))
- DEBUG_CASE(NV_PFB_TSIZE(5))
- DEBUG_CASE(NV_PFB_TSTATUS(5))
- DEBUG_CASE(NV_PFB_TILE(6))
- DEBUG_CASE(NV_PFB_TLIMIT(6))
- DEBUG_CASE(NV_PFB_TSIZE(6))
- DEBUG_CASE(NV_PFB_TSTATUS(6))
- DEBUG_CASE(NV_PFB_TILE(7))
- DEBUG_CASE(NV_PFB_TLIMIT(7))
- DEBUG_CASE(NV_PFB_TSIZE(7))
- DEBUG_CASE(NV_PFB_TSTATUS(7))
- DEBUG_CASE(NV_PFB_MRS)
- DEBUG_CASE(NV_PFB_EMRS)
- DEBUG_CASE(NV_PFB_MRS_EXT)
- DEBUG_CASE(NV_PFB_EMRS_EXT)
- DEBUG_CASE(NV_PFB_REF)
- DEBUG_CASE(NV_PFB_PRE)
- DEBUG_CASE(NV_PFB_ZCOMP(0))
- DEBUG_CASE(NV_PFB_ZCOMP(1))
- DEBUG_CASE(NV_PFB_ZCOMP(2))
- DEBUG_CASE(NV_PFB_ZCOMP(3))
- DEBUG_CASE(NV_PFB_ZCOMP(4))
- DEBUG_CASE(NV_PFB_ZCOMP(5))
- DEBUG_CASE(NV_PFB_ZCOMP(6))
- DEBUG_CASE(NV_PFB_ZCOMP(7))
- DEBUG_CASE(NV_PFB_ZCOMP_OFFSET)
- DEBUG_CASE(NV_PFB_ARB_PREDIVIDER)
- DEBUG_CASE(NV_PFB_ARB_TIMEOUT)
- DEBUG_CASE(NV_PFB_ARB_XFER_REM)
- DEBUG_CASE(NV_PFB_ARB_DIFF_BANK)
- DEBUG_CASE(NV_PFB_CLOSE_PAGE0)
- DEBUG_CASE(NV_PFB_CLOSE_PAGE1)
- DEBUG_CASE(NV_PFB_CLOSE_PAGE2)
- DEBUG_CASE(NV_PFB_BPARB)
- DEBUG_CASE(NV_PFB_CMDQ0)
- DEBUG_CASE(NV_PFB_CMDQ1)
- DEBUG_CASE(NV_PFB_ILL_INSTR)
- DEBUG_CASE(NV_PFB_RT)
- DEBUG_CASE(NV_PFB_AUTOCLOSE)
- DEBUG_CASE(NV_PFB_WBC)
- DEBUG_CASE(NV_PFB_CMDQ_PRT)
- DEBUG_CASE(NV_PFB_CPU_RRQ)
- DEBUG_CASE(NV_PFB_BYPASS);
-DEBUG_END(PFB)
-
-DEBUG_START(PSTRAPS)
-DEBUG_END(PSTRAPS)
-
-DEBUG_START(PGRAPH)
- DEBUG_CASE(NV_PGRAPH_DEBUG_0);
- DEBUG_CASE(NV_PGRAPH_DEBUG_1);
- DEBUG_CASE(NV_PGRAPH_DEBUG_3);
- DEBUG_CASE(NV_PGRAPH_DEBUG_4);
- DEBUG_CASE(NV_PGRAPH_DEBUG_5);
- DEBUG_CASE(NV_PGRAPH_DEBUG_8);
- DEBUG_CASE(NV_PGRAPH_DEBUG_9);
- DEBUG_CASE(NV_PGRAPH_INTR);
- DEBUG_CASE(NV_PGRAPH_NSOURCE);
- DEBUG_CASE(NV_PGRAPH_INTR_EN);
- DEBUG_CASE(NV_PGRAPH_CTX_CONTROL);
- DEBUG_CASE(NV_PGRAPH_CTX_USER);
- DEBUG_CASE(NV_PGRAPH_CTX_SWITCH1);
- DEBUG_CASE(NV_PGRAPH_CTX_SWITCH2);
- DEBUG_CASE(NV_PGRAPH_CTX_SWITCH3);
- DEBUG_CASE(NV_PGRAPH_CTX_SWITCH4);
- DEBUG_CASE(NV_PGRAPH_STATUS);
- DEBUG_CASE(NV_PGRAPH_TRAPPED_ADDR);
- DEBUG_CASE(NV_PGRAPH_TRAPPED_DATA_LOW);
- DEBUG_CASE(NV_PGRAPH_SURFACE);
- DEBUG_CASE(NV_PGRAPH_INCREMENT);
- DEBUG_CASE(NV_PGRAPH_FIFO);
- DEBUG_CASE(NV_PGRAPH_RDI_INDEX);
- DEBUG_CASE(NV_PGRAPH_RDI_DATA);
- DEBUG_CASE(NV_PGRAPH_FFINTFC_ST2);
- DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_TABLE);
- DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_POINTER);
- DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_TRIGGER);
- DEBUG_CASE(NV_PGRAPH_DEBUG_2);
- DEBUG_CASE(NV_PGRAPH_TTILE(0));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(0));
- DEBUG_CASE(NV_PGRAPH_TSIZE(0));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(0));
- DEBUG_CASE(NV_PGRAPH_TTILE(1));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(1));
- DEBUG_CASE(NV_PGRAPH_TSIZE(1));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(1));
- DEBUG_CASE(NV_PGRAPH_TTILE(2));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(2));
- DEBUG_CASE(NV_PGRAPH_TSIZE(2));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(2));
- DEBUG_CASE(NV_PGRAPH_TTILE(3));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(3));
- DEBUG_CASE(NV_PGRAPH_TSIZE(3));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(3));
- DEBUG_CASE(NV_PGRAPH_TTILE(4));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(4));
- DEBUG_CASE(NV_PGRAPH_TSIZE(4));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(4));
- DEBUG_CASE(NV_PGRAPH_TTILE(5));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(5));
- DEBUG_CASE(NV_PGRAPH_TSIZE(5));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(5));
- DEBUG_CASE(NV_PGRAPH_TTILE(6));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(6));
- DEBUG_CASE(NV_PGRAPH_TSIZE(6));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(6));
- DEBUG_CASE(NV_PGRAPH_TTILE(7));
- DEBUG_CASE(NV_PGRAPH_TLIMIT(7));
- DEBUG_CASE(NV_PGRAPH_TSIZE(7));
- DEBUG_CASE(NV_PGRAPH_TSTATUS(7));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(0));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(1));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(2));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(3));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(4));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(5));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(6));
- DEBUG_CASE(NV_PGRAPH_ZCOMP(7));
- DEBUG_CASE(NV_PGRAPH_ZCOMP_OFFSET);
- DEBUG_CASE(NV_PGRAPH_FBCFG0);
- DEBUG_CASE(NV_PGRAPH_FBCFG1);
- DEBUG_CASE(NV_PGRAPH_DEBUG_6);
- DEBUG_CASE(NV_PGRAPH_DEBUG_7);
- DEBUG_CASE(NV_PGRAPH_DEBUG_10);
- DEBUG_CASE(NV_PGRAPH_CSV0_D);
- DEBUG_CASE(NV_PGRAPH_CSV0_C);
- DEBUG_CASE(NV_PGRAPH_CSV1_B);
- DEBUG_CASE(NV_PGRAPH_CSV1_A);
- DEBUG_CASE(NV_PGRAPH_CHEOPS_OFFSET);
- DEBUG_CASE(NV_PGRAPH_BLEND);
- DEBUG_CASE(NV_PGRAPH_BLENDCOLOR);
- DEBUG_CASE(NV_PGRAPH_BORDERCOLOR0);
- DEBUG_CASE(NV_PGRAPH_BORDERCOLOR1);
- DEBUG_CASE(NV_PGRAPH_BORDERCOLOR2);
- DEBUG_CASE(NV_PGRAPH_BORDERCOLOR3);
- DEBUG_CASE(NV_PGRAPH_BUMPOFFSET1);
- DEBUG_CASE(NV_PGRAPH_BUMPSCALE1);
- DEBUG_CASE(NV_PGRAPH_CLEARRECTX);
- DEBUG_CASE(NV_PGRAPH_CLEARRECTY);
- DEBUG_CASE(NV_PGRAPH_COLORCLEARVALUE);
- DEBUG_CASE(NV_PGRAPH_COMBINEFACTOR0);
- DEBUG_CASE(NV_PGRAPH_COMBINEFACTOR1);
- DEBUG_CASE(NV_PGRAPH_COMBINEALPHAI0);
- DEBUG_CASE(NV_PGRAPH_COMBINEALPHAO0);
- DEBUG_CASE(NV_PGRAPH_COMBINECOLORI0);
- DEBUG_CASE(NV_PGRAPH_COMBINECOLORO0);
- DEBUG_CASE(NV_PGRAPH_COMBINECTL);
- DEBUG_CASE(NV_PGRAPH_COMBINESPECFOG0);
- DEBUG_CASE(NV_PGRAPH_COMBINESPECFOG1);
- DEBUG_CASE(NV_PGRAPH_CONTROL_0);
- DEBUG_CASE(NV_PGRAPH_CONTROL_2);
- DEBUG_CASE(NV_PGRAPH_CONTROL_3);
- DEBUG_CASE(NV_PGRAPH_FOGCOLOR);
- DEBUG_CASE(NV_PGRAPH_FOGPARAM0);
- DEBUG_CASE(NV_PGRAPH_FOGPARAM1);
- DEBUG_CASE(NV_PGRAPH_SETUPRASTER);
- DEBUG_CASE(NV_PGRAPH_SHADERCLIPMODE);
- DEBUG_CASE(NV_PGRAPH_SHADERCTL);
- DEBUG_CASE(NV_PGRAPH_SHADERPROG);
- DEBUG_CASE(NV_PGRAPH_SHADOWZSLOPETHRESHOLD);
- DEBUG_CASE(NV_PGRAPH_SPECFOGFACTOR0);
- DEBUG_CASE(NV_PGRAPH_SPECFOGFACTOR1);
- DEBUG_CASE_EX(NV_PGRAPH_TEXADDRESS0, ":_ADDRV");
- DEBUG_CASE(NV_PGRAPH_TEXADDRESS1);
- DEBUG_CASE(NV_PGRAPH_TEXADDRESS2);
- DEBUG_CASE(NV_PGRAPH_TEXADDRESS3);
- DEBUG_CASE(NV_PGRAPH_TEXCTL0_0);
- DEBUG_CASE(NV_PGRAPH_TEXCTL0_1);
- DEBUG_CASE(NV_PGRAPH_TEXCTL0_2);
- DEBUG_CASE(NV_PGRAPH_TEXCTL0_3);
- DEBUG_CASE(NV_PGRAPH_TEXCTL1_0);
- DEBUG_CASE(NV_PGRAPH_TEXCTL1_1);
- DEBUG_CASE(NV_PGRAPH_TEXCTL1_2);
- DEBUG_CASE(NV_PGRAPH_TEXCTL1_3);
- DEBUG_CASE(NV_PGRAPH_TEXCTL2_0);
- DEBUG_CASE(NV_PGRAPH_TEXCTL2_1);
- DEBUG_CASE(NV_PGRAPH_TEXFILTER0);
- DEBUG_CASE(NV_PGRAPH_TEXFILTER1);
- DEBUG_CASE(NV_PGRAPH_TEXFILTER2);
- DEBUG_CASE(NV_PGRAPH_TEXFILTER3);
- DEBUG_CASE(NV_PGRAPH_TEXFMT0);
- DEBUG_CASE(NV_PGRAPH_TEXFMT1);
- DEBUG_CASE(NV_PGRAPH_TEXFMT2);
- DEBUG_CASE(NV_PGRAPH_TEXFMT3);
- DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT0);
- DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT1);
- DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT2);
- DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT3);
- DEBUG_CASE(NV_PGRAPH_TEXOFFSET0);
- DEBUG_CASE(NV_PGRAPH_TEXOFFSET1);
- DEBUG_CASE(NV_PGRAPH_TEXOFFSET2);
- DEBUG_CASE(NV_PGRAPH_TEXOFFSET3);
- DEBUG_CASE(NV_PGRAPH_TEXPALETTE0);
- DEBUG_CASE(NV_PGRAPH_TEXPALETTE1);
- DEBUG_CASE(NV_PGRAPH_TEXPALETTE2);
- DEBUG_CASE(NV_PGRAPH_TEXPALETTE3);
- DEBUG_CASE(NV_PGRAPH_ZSTENCILCLEARVALUE);
- DEBUG_CASE(NV_PGRAPH_ZCLIPMIN);
- DEBUG_CASE(NV_PGRAPH_ZOFFSETBIAS);
- DEBUG_CASE(NV_PGRAPH_ZOFFSETFACTOR);
- DEBUG_CASE(NV_PGRAPH_EYEVEC0);
- DEBUG_CASE(NV_PGRAPH_EYEVEC1);
- DEBUG_CASE(NV_PGRAPH_EYEVEC2);
- DEBUG_CASE(NV_PGRAPH_ZCLIPMAX);
-DEBUG_END(PGRAPH)
-
-DEBUG_START(PCRTC)
- DEBUG_CASE(NV_PCRTC_INTR_0);
- DEBUG_CASE(NV_PCRTC_INTR_EN_0);
- DEBUG_CASE(NV_PCRTC_START);
- DEBUG_CASE(NV_PCRTC_CONFIG);
-DEBUG_END(PCRTC)
-
-DEBUG_START(PRMCIO)
- DEBUG_CASE(VGA_CRT_DC);
- DEBUG_CASE(VGA_CRT_DM);
- DEBUG_CASE(VGA_ATT_R);
- DEBUG_CASE(VGA_ATT_W);
- DEBUG_CASE(VGA_GFX_D);
- DEBUG_CASE(VGA_SEQ_D);
- DEBUG_CASE(VGA_MIS_R);
- DEBUG_CASE(VGA_MIS_W);
- DEBUG_CASE(VGA_FTC_R);
- DEBUG_CASE(VGA_IS1_RC);
- DEBUG_CASE(VGA_IS1_RM);
- DEBUG_CASE(VGA_PEL_D);
- DEBUG_CASE(VGA_PEL_MSK);
- DEBUG_CASE(VGA_CRT_IC);
- DEBUG_CASE(VGA_CRT_IM);
- DEBUG_CASE(VGA_GFX_I);
- DEBUG_CASE(VGA_SEQ_I);
- DEBUG_CASE(VGA_PEL_IW);
- DEBUG_CASE(VGA_PEL_IR);
-DEBUG_END(PRMCIO)
-
-DEBUG_START(PRAMDAC)
- DEBUG_CASE(NV_PRAMDAC_NVPLL_COEFF);
- DEBUG_CASE(NV_PRAMDAC_MPLL_COEFF);
- DEBUG_CASE(NV_PRAMDAC_VPLL_COEFF);
- DEBUG_CASE(NV_PRAMDAC_PLL_TEST_COUNTER);
-
-DEBUG_END(PRAMDAC)
-
-DEBUG_START(PRMDIO)
-DEBUG_END(PRMDIO)
-
-DEBUG_START(PRAMIN)
-DEBUG_END(PRAMIN)
-
-DEBUG_START(USER)
- DEBUG_CASE(NV_USER_DMA_PUT);
- DEBUG_CASE(NV_USER_DMA_GET);
- DEBUG_CASE(NV_USER_REF);
-DEBUG_END(USER)
-
-
+#include "EmuNV2A_DEBUG.cpp"
#define DEBUG_READ32(DEV) DbgPrintf("X86 : Rd32 NV2A " #DEV "(0x%08X) = 0x%08X [Handled %s]\n", addr, result, DebugNV_##DEV##(addr))
@@ -1064,192 +619,6 @@ static void *nv_dma_map(xbaddr dma_obj_address, xbaddr *len)
return (void*)(MM_SYSTEM_PHYSICAL_MAP + dma.address);
}
-/* pusher should be fine to run from a mimo handler
-* whenever's it's convenient */
-static void pfifo_run_pusher() {
- uint8_t channel_id;
- ChannelControl *control;
- Cache1State *state;
- CacheEntry *command;
- uint8_t *dma;
- xbaddr dma_len;
- uint32_t word;
-
- /* TODO: How is cache1 selected? */
- state = &pfifo.cache1;
- channel_id = state->channel_id;
- control = &user.channel_control[channel_id];
-
- if (!state->push_enabled) return;
-
- /* only handling DMA for now... */
-
- /* Channel running DMA */
- uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
- assert(channel_modes & (1 << channel_id));
- assert(state->mode == FIFO_DMA);
-
- if (!state->dma_push_enabled) return;
- if (state->dma_push_suspended) return;
-
- /* We're running so there should be no pending errors... */
- assert(state->error == NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE);
-
- dma = (uint8_t*)nv_dma_map(state->dma_instance, &dma_len);
-
- printf("DMA pusher: max 0x%08X, 0x%08X - 0x%08X\n",
- dma_len, control->dma_get, control->dma_put);
-
- /* based on the convenient pseudocode in envytools */
- while (control->dma_get != control->dma_put) {
- if (control->dma_get >= dma_len) {
- state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION;
- break;
- }
-
- word = ldl_le_p((uint32_t*)(dma + control->dma_get));
- control->dma_get += 4;
-
- if (state->method_count) {
- /* data word of methods command */
- state->data_shadow = word;
-
- CacheEntry* command = (CacheEntry*)calloc(1, sizeof(CacheEntry));
- command->method = state->method;
- command->subchannel = state->subchannel;
- command->nonincreasing = state->method_nonincreasing;
- command->parameter = word;
-
- std::lock_guard lk(state->mutex);
- state->cache.push(command);
- state->cache_cond.notify_all();
-
- if (!state->method_nonincreasing) {
- state->method += 4;
- }
-
- state->method_count--;
- state->dcount++;
- } else {
- /* no command active - this is the first word of a new one */
- state->rsvd_shadow = word;
- /* match all forms */
- if ((word & 0xe0000003) == 0x20000000) {
- /* old jump */
- state->get_jmp_shadow = control->dma_get;
- control->dma_get = word & 0x1fffffff;
- printf("pb OLD_JMP 0x%08X\n", control->dma_get);
- }
- else if ((word & 3) == 1) {
- /* jump */
- state->get_jmp_shadow = control->dma_get;
- control->dma_get = word & 0xfffffffc;
- printf("pb JMP 0x%08X\n", control->dma_get);
- }
- else if ((word & 3) == 2) {
- /* call */
- if (state->subroutine_active) {
- state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL;
- break;
- }
- state->subroutine_return = control->dma_get;
- state->subroutine_active = true;
- control->dma_get = word & 0xfffffffc;
- printf("pb CALL 0x%08X\n", control->dma_get);
- }
- else if (word == 0x00020000) {
- /* return */
- if (!state->subroutine_active) {
- state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN;
- break;
- }
- control->dma_get = state->subroutine_return;
- state->subroutine_active = false;
- printf("pb RET 0x%08X\n", control->dma_get);
- }
- else if ((word & 0xe0030003) == 0) {
- /* increasing methods */
- state->method = word & 0x1fff;
- state->subchannel = (word >> 13) & 7;
- state->method_count = (word >> 18) & 0x7ff;
- state->method_nonincreasing = false;
- state->dcount = 0;
- }
- else if ((word & 0xe0030003) == 0x40000000) {
- /* non-increasing methods */
- state->method = word & 0x1fff;
- state->subchannel = (word >> 13) & 7;
- state->method_count = (word >> 18) & 0x7ff;
- state->method_nonincreasing = true;
- state->dcount = 0;
- }
- else {
- printf("pb reserved cmd 0x%08X - 0x%08X\n",
- control->dma_get, word);
- state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD;
- break;
- }
- }
- }
-
- printf("DMA pusher done: max 0x%08X, 0x%08X - 0x%08X\n",
- dma_len, control->dma_get, control->dma_put);
-
- if (state->error) {
- printf("pb error: %d\n", state->error);
- assert(false);
-
- state->dma_push_suspended = true;
-
- pfifo.pending_interrupts |= NV_PFIFO_INTR_0_DMA_PUSHER;
- update_irq();
- }
-}
-
-static uint32_t ramht_hash(uint32_t handle)
-{
- unsigned int ramht_size = 1 << (GET_MASK(pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
-
- /* XXX: Think this is different to what nouveau calculates... */
- unsigned int bits = ffs(ramht_size) - 2;
-
- uint32_t hash = 0;
- while (handle) {
- hash ^= (handle & ((1 << bits) - 1));
- handle >>= bits;
- }
- hash ^= pfifo.cache1.channel_id << (bits - 4);
-
- return hash;
-}
-
-
-static RAMHTEntry ramht_lookup(uint32_t handle)
-{
- unsigned int ramht_size = 1 << (GET_MASK(pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
-
- uint32_t hash = ramht_hash(handle);
- assert(hash * 8 < ramht_size);
-
- uint32_t ramht_address =
- GET_MASK(pfifo.regs[NV_PFIFO_RAMHT],
- NV_PFIFO_RAMHT_BASE_ADDRESS_MASK) << 12;
-
- uint8_t *entry_ptr = (uint8_t*)(NV2A_ADDR + NV_PRAMIN_ADDR + ramht_address + hash * 8);
-
- uint32_t entry_handle = ldl_le_p((uint32_t*)entry_ptr);
- uint32_t entry_context = ldl_le_p((uint32_t*)(entry_ptr + 4));
-
- RAMHTEntry entry;
- entry.handle = entry_handle;
- entry.instance = (entry_context & NV_RAMHT_INSTANCE) << 4;
- entry.engine = (FIFOEngine)((entry_context & NV_RAMHT_ENGINE) >> 16);
- entry.channel_id = (entry_context & NV_RAMHT_CHID) >> 24;
- entry.valid = entry_context & NV_RAMHT_STATUS;
-
- return entry;
-}
-
static void pgraph_context_switch(unsigned int channel_id)
{
bool valid = false;
@@ -2735,807 +2104,99 @@ DEVICE_WRITE32(PCOUNTER)
DEVICE_WRITE32_END(PCOUNTER);
}
-static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
-{
- union {
- uint64_t ll;
- struct {
- uint32_t low, high;
- } l;
- } u, res;
- uint64_t rl, rh;
-
- u.ll = a;
- rl = (uint64_t)u.l.low * (uint64_t)b;
- rh = (uint64_t)u.l.high * (uint64_t)b;
- rh += (rl >> 32);
- res.l.high = rh / c;
- res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
- return res.ll;
-}
-
-/* PIMTER - time measurement and time-based alarms */
-static uint32_t ptimer_get_clock()
-{
- // Get time in nanoseconds
- long int time = static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
-
- return muldiv64(time, pramdac.core_clock_freq * ptimer.numerator, CLOCKS_PER_SEC * ptimer.denominator);
-}
-
-DEVICE_READ32(PTIMER)
-{
- DEVICE_READ32_SWITCH() {
- case NV_PTIMER_INTR_0:
- result = ptimer.pending_interrupts;
- break;
- case NV_PTIMER_INTR_EN_0:
- result = ptimer.enabled_interrupts;
- break;
- case NV_PTIMER_NUMERATOR:
- result = ptimer.numerator;
- break;
- case NV_PTIMER_DENOMINATOR:
- result = ptimer.denominator;
- break;
- case NV_PTIMER_TIME_0:
- result = (ptimer_get_clock() & 0x7ffffff) << 5;
- break;
- case NV_PTIMER_TIME_1:
- result = (ptimer_get_clock() >> 27) & 0x1fffffff;
- break;
- default:
- result = 0;
- //DEVICE_READ32_REG(ptimer); // Was : DEBUG_READ32_UNHANDLED(PTIMER);
- break;
- }
-
- DEVICE_READ32_END(PTIMER);
-}
-
-
-DEVICE_WRITE32(PTIMER)
-{
- 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:
- //DEVICE_WRITE32_REG(ptimer); // Was : DEBUG_WRITE32_UNHANDLED(PTIMER);
- break;
- }
-
- DEVICE_WRITE32_END(PTIMER);
-}
-
-
-DEVICE_READ32(PVPE)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PVPE); // TODO : DEVICE_READ32_REG(pvpe);
- break;
- }
-
- DEVICE_READ32_END(PVPE);
-}
-
-
-DEVICE_WRITE32(PVPE)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PVPE); // TODO : DEVICE_WRITE32_REG(pvpe);
- break;
- }
-
- DEVICE_WRITE32_END(PVPE);
-}
-
-
-DEVICE_READ32(PTV)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PTV); // TODO : DEVICE_READ32_REG(ptv);
- break;
- }
-
- DEVICE_READ32_END(PTV);
-}
-
-DEVICE_WRITE32(PTV)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PTV); // TODO : DEVICE_WRITE32_REG(ptv);
- break;
- }
-
- DEVICE_WRITE32_END(PTV);
-}
-
-
-DEVICE_READ32(PRMFB)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PRMFB); // TODO : DEVICE_READ32_REG(prmfb);
- break;
- }
-
- DEVICE_READ32_END(PRMFB);
-}
-
-DEVICE_WRITE32(PRMFB)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PRMFB); // TODO : DEVICE_WRITE32_REG(prmfb);
- break;
- }
-
- DEVICE_WRITE32_END(PRMFB);
-}
-
-
-DEVICE_READ32(PRMVIO)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PRMVIO); // TODO : DEVICE_READ32_REG(prmvio);
- break;
- }
-
- DEVICE_READ32_END(PRMVIO);
-}
-
-DEVICE_WRITE32(PRMVIO)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PRMVIO); // TODO : DEVICE_WRITE32_REG(prmvio);
- break;
- }
-
- DEVICE_WRITE32_END(PRMVIO);
-}
-
-
-DEVICE_READ32(PFB)
-{
- DEVICE_READ32_SWITCH() {
- case NV_PFB_CFG0:
- result = 3; // = NV_PFB_CFG0_PART_4
- break;
- case NV_PFB_CSTATUS:
- {
- if (g_bIsChihiro || g_bIsDebug) { result = CONTIGUOUS_MEMORY_CHIHIRO_SIZE; break; }
- result = CONTIGUOUS_MEMORY_XBOX_SIZE;
- }
- break;
- case NV_PFB_WBC:
- result = 0; // = !NV_PFB_WBC_FLUSH
- break;
- default:
- DEVICE_READ32_REG(pfb);
- break;
- }
-
- DEVICE_READ32_END(PFB);
-}
-
-DEVICE_WRITE32(PFB)
-{
- switch (addr) {
- default:
- DEVICE_WRITE32_REG(pfb);
- break;
- }
-
- DEVICE_WRITE32_END(PFB);
-}
-
-
-DEVICE_READ32(PSTRAPS)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PSTRAPS);
- break;
- }
-
- DEVICE_READ32_END(PSTRAPS);
-}
-
-DEVICE_WRITE32(PSTRAPS)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PSTRAPS);
- break;
- }
-
- DEVICE_WRITE32_END(PSTRAPS);
-}
-
-
-DEVICE_READ32(PGRAPH)
-{
- std::lock_guard lk(pgraph.mutex);
-
- DEVICE_READ32_SWITCH() {
- case NV_PGRAPH_INTR:
- result = pgraph.pending_interrupts;
- break;
- case NV_PGRAPH_INTR_EN:
- result = pgraph.enabled_interrupts;
- break;
- case NV_PGRAPH_NSOURCE:
- result = pgraph.notify_source;
- break;
- case NV_PGRAPH_CTX_USER:
- SET_MASK(result, NV_PGRAPH_CTX_USER_CHANNEL_3D, pgraph.context[pgraph.channel_id].channel_3d);
- SET_MASK(result, NV_PGRAPH_CTX_USER_CHANNEL_3D_VALID, 1);
- SET_MASK(result, NV_PGRAPH_CTX_USER_SUBCH, pgraph.context[pgraph.channel_id].subchannel << 13);
- SET_MASK(result, NV_PGRAPH_CTX_USER_CHID, pgraph.channel_id);
- break;
- case NV_PGRAPH_TRAPPED_ADDR:
- SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_CHID, pgraph.trapped_channel_id);
- SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_SUBCH, pgraph.trapped_subchannel);
- SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_MTHD, pgraph.trapped_method);
- break;
- case NV_PGRAPH_TRAPPED_DATA_LOW:
- result = pgraph.trapped_data[0];
- break;
- case NV_PGRAPH_FIFO:
- SET_MASK(result, NV_PGRAPH_FIFO_ACCESS, pgraph.fifo_access);
- break;
- case NV_PGRAPH_CHANNEL_CTX_TABLE:
- result = pgraph.context_table >> 4;
- break;
- case NV_PGRAPH_CHANNEL_CTX_POINTER:
- result = pgraph.context_address >> 4;
- break;
- default:
- DEVICE_READ32_REG(pgraph); // Was : DEBUG_READ32_UNHANDLED(PGRAPH);
- }
-
- DEVICE_READ32_END(PGRAPH);
-}
-
-static void pgraph_set_context_user(uint32_t value)
-{
- pgraph.channel_id = (value & NV_PGRAPH_CTX_USER_CHID) >> 24;
- pgraph.context[pgraph.channel_id].channel_3d = GET_MASK(value, NV_PGRAPH_CTX_USER_CHANNEL_3D);
- pgraph.context[pgraph.channel_id].subchannel = GET_MASK(value, NV_PGRAPH_CTX_USER_SUBCH);
-}
-
-DEVICE_WRITE32(PGRAPH)
-{
- std::lock_guard lk(pgraph.mutex);
-
- switch (addr) {
- case NV_PGRAPH_INTR:
- pgraph.pending_interrupts &= ~value;
- pgraph.interrupt_cond.notify_all();
- break;
- case NV_PGRAPH_INTR_EN:
- pgraph.enabled_interrupts = value;
- break;
- case NV_PGRAPH_CTX_CONTROL:
- pgraph.channel_valid = (value & NV_PGRAPH_CTX_CONTROL_CHID);
- break;
- case NV_PGRAPH_CTX_USER:
- pgraph_set_context_user(value);
- break;
- case NV_PGRAPH_INCREMENT:
- if (value & NV_PGRAPH_INCREMENT_READ_3D) {
- SET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
- NV_PGRAPH_SURFACE_READ_3D,
- (GET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
- NV_PGRAPH_SURFACE_READ_3D) + 1)
- % GET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
- NV_PGRAPH_SURFACE_MODULO_3D));
-
- pgraph.flip_3d.notify_all();
- }
- break;
- case NV_PGRAPH_FIFO:
- pgraph.fifo_access = GET_MASK(value, NV_PGRAPH_FIFO_ACCESS);
- pgraph.fifo_access_cond.notify_all();
- break;
- case NV_PGRAPH_CHANNEL_CTX_TABLE:
- pgraph.context_table = (value & NV_PGRAPH_CHANNEL_CTX_TABLE_INST) << 4;
- break;
- case NV_PGRAPH_CHANNEL_CTX_POINTER:
- pgraph.context_address =
- (value & NV_PGRAPH_CHANNEL_CTX_POINTER_INST) << 4;
- break;
- case NV_PGRAPH_CHANNEL_CTX_TRIGGER:
- if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN) {
- printf("PGRAPH: read channel %d context from %0x08X\n",
- pgraph.channel_id, pgraph.context_address);
-
- uint8_t *context_ptr = (uint8_t*)(NV2A_ADDR + NV_PRAMIN_ADDR + pgraph.context_address);
- uint32_t context_user = ldl_le_p((uint32_t*)context_ptr);
-
- printf(" - CTX_USER = 0x%x\n", context_user);
-
-
- pgraph_set_context_user(context_user);
- }
- if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT) {
- /* do stuff ... */
- }
-
- break;
- default:
- DEVICE_WRITE32_REG(pgraph); // Was : DEBUG_WRITE32_UNHANDLED(PGRAPH);
- break;
- }
-
- DEVICE_WRITE32_END(PGRAPH);
-}
-
-
-DEVICE_READ32(PCRTC)
-{
- DEVICE_READ32_SWITCH() {
-
- case NV_PCRTC_INTR_0:
- result = pcrtc.pending_interrupts;
- break;
- case NV_PCRTC_INTR_EN_0:
- result = pcrtc.enabled_interrupts;
- break;
- case NV_PCRTC_START:
- result = pcrtc.start;
- break;
- default:
- result = 0;
- //DEVICE_READ32_REG(pcrtc); // Was : DEBUG_READ32_UNHANDLED(PCRTC);
- break;
- }
-
- DEVICE_READ32_END(PCRTC);
-}
-
-DEVICE_WRITE32(PCRTC)
-{
- 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:
- DEVICE_WRITE32_REG(pcrtc); // Was : DEBUG_WRITE32_UNHANDLED(PCRTC);
- break;
- }
-
- DEVICE_WRITE32_END(PCRTC);
-}
-
-
-DEVICE_READ32(PRMCIO)
-{
- DEVICE_READ32_SWITCH() {
- case VGA_CRT_IM:
- case VGA_CRT_IC:
- result = prmcio.cr_index;
- break;
- case VGA_CRT_DM:
- case VGA_CRT_DC:
- result = prmcio.cr[prmcio.cr_index];
-
- printf("vga: read CR%x = 0x%02x\n", prmcio.cr_index, result);
- break;
- default:
- DEBUG_READ32_UNHANDLED(PRMCIO);
- printf("vga: UNHANDLED ADDR %s\n", addr);
- break;
- }
-
- DEVICE_READ32_END(PRMCIO);
-}
-
-DEVICE_WRITE32(PRMCIO)
-{
- switch (addr) {
- case VGA_CRT_IM:
- case VGA_CRT_IC:
- prmcio.cr_index = value;
- break;
- case VGA_CRT_DM:
- case VGA_CRT_DC:
- printf("vga: write CR%x = 0x%02x\n", prmcio.cr_index, value);
-
- /* handle CR0-7 protection */
- if ((prmcio.cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
- prmcio.cr_index <= VGA_CRTC_OVERFLOW) {
- /* can always write bit 4 of CR7 */
- if (prmcio.cr_index == VGA_CRTC_OVERFLOW) {
- prmcio.cr[VGA_CRTC_OVERFLOW] = (prmcio.cr[VGA_CRTC_OVERFLOW] & ~0x10) |
- (value & 0x10);
- EmuWarning("TODO: vbe_update_vgaregs");
- //vbe_update_vgaregs();
- }
- return;
- }
-
- prmcio.cr[prmcio.cr_index] = value;
- EmuWarning("TODO: vbe_update_vgaregs");
- //vbe_update_vgaregs();
-
- switch (prmcio.cr_index) {
- case VGA_CRTC_H_TOTAL:
- case VGA_CRTC_H_SYNC_START:
- case VGA_CRTC_H_SYNC_END:
- case VGA_CRTC_V_TOTAL:
- case VGA_CRTC_OVERFLOW:
- case VGA_CRTC_V_SYNC_END:
- case VGA_CRTC_MODE:
- // TODO: s->update_retrace_info(s);
- EmuWarning("TODO: update_retrace_info");
- break;
- }
- break;
- default:
- DEBUG_WRITE32_UNHANDLED(PRMCIO); // TODO : DEVICE_WRITE32_REG(prmcio);
- break;
- }
-
- DEVICE_WRITE32_END(PRMCIO);
-}
-
-
-DEVICE_READ32(PRAMDAC)
-{
- DEVICE_READ32_SWITCH() {
-
- case NV_PRAMDAC_NVPLL_COEFF:
- result = pramdac.core_clock_coeff;
- break;
- case NV_PRAMDAC_MPLL_COEFF:
- result = pramdac.memory_clock_coeff;
- break;
- case NV_PRAMDAC_VPLL_COEFF:
- result = pramdac.video_clock_coeff;
- break;
- case NV_PRAMDAC_PLL_TEST_COUNTER:
- /* emulated PLLs locked instantly? */
- result = 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:
- //DEVICE_READ32_REG(pramdac); // Was : DEBUG_READ32_UNHANDLED(PRAMDAC);
- break;
- }
-
- DEVICE_READ32_END(PRAMDAC);
-}
-
-DEVICE_WRITE32(PRAMDAC)
-{
- switch (addr) {
-
- uint32_t m, n, p;
- case NV_PRAMDAC_NVPLL_COEFF:
- pramdac.core_clock_coeff = value;
-
- m = value & NV_PRAMDAC_NVPLL_COEFF_MDIV;
- n = (value & NV_PRAMDAC_NVPLL_COEFF_NDIV) >> 8;
- p = (value & NV_PRAMDAC_NVPLL_COEFF_PDIV) >> 16;
-
- if (m == 0) {
- pramdac.core_clock_freq = 0;
- }
- else {
- pramdac.core_clock_freq = (NV2A_CRYSTAL_FREQ * n)
- / (1 << p) / m;
- }
-
- break;
- case NV_PRAMDAC_MPLL_COEFF:
- pramdac.memory_clock_coeff = value;
- break;
- case NV_PRAMDAC_VPLL_COEFF:
- pramdac.video_clock_coeff = value;
- break;
-
- default:
- //DEVICE_WRITE32_REG(pramdac); // Was : DEBUG_WRITE32_UNHANDLED(PRAMDAC);
- break;
- }
-
- DEVICE_WRITE32_END(PRAMDAC);
-}
-
-
-DEVICE_READ32(PRMDIO)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEBUG_READ32_UNHANDLED(PRMDIO);
- break;
- }
-
- DEVICE_READ32_END(PRMDIO);
-}
-
-DEVICE_WRITE32(PRMDIO)
-{
- switch (addr) {
- default:
- DEBUG_WRITE32_UNHANDLED(PRMDIO);
- break;
- }
-
- DEVICE_WRITE32_END(PRMDIO);
-}
-
-
-DEVICE_READ32(PRAMIN)
-{
- DEVICE_READ32_SWITCH() {
- default:
- DEVICE_READ32_REG(pramin);
- break;
- }
-
- DEVICE_READ32_END(PRAMIN);
-}
-
-DEVICE_WRITE32(PRAMIN)
-{
- switch (addr) {
- default:
- DEVICE_WRITE32_REG(pramin);
- break;
- }
-
- DEVICE_WRITE32_END(PRAMIN);
-}
-
-
-DEVICE_READ32(USER)
-{
- unsigned int channel_id = addr >> 16;
- assert(channel_id < NV2A_NUM_CHANNELS);
-
- ChannelControl *control = &user.channel_control[channel_id];
- uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
-
- /* PIO Mode */
- if (!channel_modes & (1 << channel_id)) {
- assert(false);
- }
-
- /* DMA Mode */
- addr &= 0xFFFF;
- DEVICE_READ32_SWITCH() {
- case NV_USER_DMA_PUT:
- result = control->dma_put;
- break;
- case NV_USER_DMA_GET:
- result = control->dma_get;
- break;
- case NV_USER_REF:
- result = control->ref;
- break;
- default:
- DEBUG_READ32_UNHANDLED(USER);
- break;
- }
-
- DEVICE_READ32_END(USER);
-}
-
-DEVICE_WRITE32(USER)
-{
- unsigned int channel_id = addr >> 16;
- assert(channel_id < NV2A_NUM_CHANNELS);
-
- ChannelControl *control = &user.channel_control[channel_id];
-
- uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
-
- if (channel_modes & (1 << channel_id)) {
- /* DMA Mode */
- switch (addr & 0xFFFF) {
- case NV_USER_DMA_PUT:
- control->dma_put = value;
-
- if (pfifo.cache1.push_enabled) {
- pfifo_run_pusher();
- }
- break;
- case NV_USER_DMA_GET:
- control->dma_get = value;
- break;
- case NV_USER_REF:
- control->ref = value;
- break;
- default:
- DEBUG_WRITE32_UNHANDLED(USER);
- break;
- }
- }
- else {
- /* PIO Mode */
- assert(false);
- }
-
- DEVICE_WRITE32_END(USER);
-}
-
+#include "EmuNV2A_PMC.cpp"
+#include "EmuNV2A_PBUS.cpp"
+#include "EmuNV2A_PFIFO.cpp"
+#include "EmuNV2A_PRMA.cpp"
+#include "EmuNV2A_PVIDEO.cpp"
+#include "EmuNV2A_PCOUNTER.cpp"
+#include "EmuNV2A_PTIMER.cpp"
+#include "EmuNV2A_PVPE.cpp"
+#include "EmuNV2A_PTV.cpp"
+#include "EmuNV2A_PRMFB.cpp"
+#include "EmuNV2A_PRMVIO.cpp"
+#include "EmuNV2A_PFB.cpp"
+#include "EmuNV2A_PSTRAPS.cpp"
+#include "EmuNV2A_PGRAPH.cpp"
+#include "EmuNV2A_PCRTC.cpp"
+#include "EmuNV2A_PRMCIO.cpp"
+#include "EmuNV2A_PRAMDAC.cpp"
+#include "EmuNV2A_PRMDIO.cpp"
+#include "EmuNV2A_PRAMIN.cpp"
+#include "EmuNV2A_USER.cpp"
+
+typedef xbaddr hwaddr; // Compatibility; Cxbx uses xbaddr, xqemu and OpenXbox use hwaddr
+typedef uint32_t value_t; // Compatibility; Cxbx values are uint32_t (xqemu and OpenXbox use uint64_t)
+
+typedef value_t(*read_func)(/*void *opaque, */hwaddr addr); //, unsigned int size);
+typedef void(*write_func)(/*void *opaque, */hwaddr addr, value_t val); //, unsigned int size);
+
+typedef struct {
+ read_func read;
+ write_func write;
+} MemoryRegionOps;
typedef struct NV2ABlockInfo {
- uint32_t offset;
- uint32_t size;
- uint32_t(*read)(xbaddr addr);
- void(*write)(xbaddr addr, uint32_t value);
+ const char* name;
+ hwaddr offset;
+ uint64_t size;
+ MemoryRegionOps ops;
} NV2ABlockInfo;
-static const NV2ABlockInfo regions[] = {{
- /* card master control */
- NV_PMC_ADDR, // = 0x000000
- NV_PMC_SIZE, // = 0x001000
- EmuNV2A_PMC_Read32,
- EmuNV2A_PMC_Write32,
- }, {
- /* bus control */
- NV_PBUS_ADDR, // = 0x001000
- NV_PBUS_SIZE, // = 0x001000
- EmuNV2A_PBUS_Read32,
- EmuNV2A_PBUS_Write32,
- }, {
- /* MMIO and DMA FIFO submission to PGRAPH and VPE */
- NV_PFIFO_ADDR, // = 0x002000
- _NV_PFIFO_SIZE, // = 0x002000
- EmuNV2A_PFIFO_Read32,
- EmuNV2A_PFIFO_Write32,
- }, {
- /* access to BAR0/BAR1 from real mode */
- NV_PRMA_ADDR, // = 0x007000
- NV_PRMA_SIZE, // = 0x001000
- EmuNV2A_PRMA_Read32,
- EmuNV2A_PRMA_Write32,
- }, {
- /* video overlay */
- NV_PVIDEO_ADDR, // = 0x008000
- NV_PVIDEO_SIZE, // = 0x001000
- EmuNV2A_PVIDEO_Read32,
- EmuNV2A_PVIDEO_Write32,
- }, {
- /* time measurement and time-based alarms */
- NV_PTIMER_ADDR, // = 0x009000
- NV_PTIMER_SIZE, // = 0x001000
- EmuNV2A_PTIMER_Read32,
- EmuNV2A_PTIMER_Write32,
- }, {
- /* performance monitoring counters */
- NV_PCOUNTER_ADDR, // = 0x00a000
- NV_PCOUNTER_SIZE, // = 0x001000
- EmuNV2A_PCOUNTER_Read32,
- EmuNV2A_PCOUNTER_Write32,
- }, {
- /* MPEG2 decoding engine */
- NV_PVPE_ADDR, // = 0x00b000
- NV_PVPE_SIZE, // = 0x001000
- EmuNV2A_PVPE_Read32,
- EmuNV2A_PVPE_Write32,
- }, {
- /* TV encoder */
- NV_PTV_ADDR, // = 0x00d000
- NV_PTV_SIZE, // = 0x001000
- EmuNV2A_PTV_Read32,
- EmuNV2A_PTV_Write32,
- }, {
- /* aliases VGA memory window */
- NV_PRMFB_ADDR, // = 0x0a0000
- NV_PRMFB_SIZE, // = 0x020000
- EmuNV2A_PRMFB_Read32,
- EmuNV2A_PRMFB_Write32,
- }, {
- /* aliases VGA sequencer and graphics controller registers */
- NV_PRMVIO_ADDR, // = 0x0c0000
- NV_PRMVIO_SIZE, // = 0x008000 // Was 0x001000
- EmuNV2A_PRMVIO_Read32,
- EmuNV2A_PRMVIO_Write32,
- },{
- /* memory interface */
- NV_PFB_ADDR, // = 0x100000
- NV_PFB_SIZE, // = 0x001000
- EmuNV2A_PFB_Read32,
- EmuNV2A_PFB_Write32,
- }, {
- /* straps readout / override */
- NV_PSTRAPS_ADDR, // = 0x101000
- NV_PSTRAPS_SIZE, // = 0x001000
- EmuNV2A_PSTRAPS_Read32,
- EmuNV2A_PSTRAPS_Write32,
- }, {
- /* accelerated 2d/3d drawing engine */
- NV_PGRAPH_ADDR, // = 0x400000
- NV_PGRAPH_SIZE, // = 0x002000
- EmuNV2A_PGRAPH_Read32,
- EmuNV2A_PGRAPH_Write32,
- }, {
- /* more CRTC controls */
- NV_PCRTC_ADDR, // = 0x600000
- NV_PCRTC_SIZE, // = 0x001000
- EmuNV2A_PCRTC_Read32,
- EmuNV2A_PCRTC_Write32,
- }, {
- /* aliases VGA CRTC and attribute controller registers */
- NV_PRMCIO_ADDR, // = 0x601000
- NV_PRMCIO_SIZE, // = 0x001000
- EmuNV2A_PRMCIO_Read32,
- EmuNV2A_PRMCIO_Write32,
- }, {
- /* RAMDAC, cursor, and PLL control */
- NV_PRAMDAC_ADDR, // = 0x680000
- NV_PRAMDAC_SIZE, // = 0x001000
- EmuNV2A_PRAMDAC_Read32,
- EmuNV2A_PRAMDAC_Write32,
- }, {
- /* aliases VGA palette registers */
- NV_PRMDIO_ADDR, // = 0x681000
- NV_PRMDIO_SIZE, // = 0x001000
- EmuNV2A_PRMDIO_Read32,
- EmuNV2A_PRMDIO_Write32,
- }, {
- /* RAMIN access */
- NV_PRAMIN_ADDR, // = 0x700000
- NV_PRAMIN_SIZE, // = 0x100000
- EmuNV2A_PRAMIN_Read32,
- EmuNV2A_PRAMIN_Write32,
- },{
- /* PFIFO MMIO and DMA submission area */
- NV_USER_ADDR, // = 0x800000
- NV_USER_SIZE, // = 0x400000 // Was 0x800000
- EmuNV2A_USER_Read32,
- EmuNV2A_USER_Write32,
- }, {
- /* User area remapped? */
- NV_UREMAP_ADDR, // = 0xC00000
- NV_UREMAP_SIZE, // = 0x400000
- EmuNV2A_USER_Read32, // NOTE : Re-used (*not* EmuNV2A_UREMAP_Read32)
- EmuNV2A_USER_Write32, // NOTE : Re-used (*not* EmuNV2A_UREMAP_Write32)
- }, {
- 0xFFFFFFFF,
- 0,
- nullptr,
- nullptr,
- },
+const NV2ABlockInfo regions[] = { // blocktable
+
+// Note : Avoid designated initializers to facilitate C++ builds
+#define ENTRY(OFFSET, SIZE, NAME, RDFUNC, WRFUNC) \
+ { \
+ #NAME, OFFSET, SIZE, \
+ { RDFUNC, WRFUNC }, \
+ }, \
+
+ /* card master control */
+ ENTRY(0x000000, 0x001000, PMC, EmuNV2A_PMC_Read32, EmuNV2A_PMC_Write32)
+ /* bus control */
+ ENTRY(0x001000, 0x001000, PBUS, EmuNV2A_PBUS_Read32, EmuNV2A_PBUS_Write32)
+ /* MMIO and DMA FIFO submission to PGRAPH and VPE */
+ ENTRY(0x002000, 0x002000, PFIFO, EmuNV2A_PFIFO_Read32, EmuNV2A_PFIFO_Write32)
+ /* access to BAR0/BAR1 from real mode */
+ ENTRY(0x007000, 0x001000, PRMA, EmuNV2A_PRMA_Read32, EmuNV2A_PRMA_Write32)
+ /* video overlay */
+ ENTRY(0x008000, 0x001000, PVIDEO, EmuNV2A_PVIDEO_Read32, EmuNV2A_PVIDEO_Write32)
+ /* time measurement and time-based alarms */
+ ENTRY(0x009000, 0x001000, PTIMER, EmuNV2A_PTIMER_Read32, EmuNV2A_PTIMER_Write32)
+ /* performance monitoring counters */
+ ENTRY(0x00a000, 0x001000, PCOUNTER, EmuNV2A_PCOUNTER_Read32, EmuNV2A_PCOUNTER_Write32)
+ /* MPEG2 decoding engine */
+ ENTRY(0x00b000, 0x001000, PVPE, EmuNV2A_PVPE_Read32, EmuNV2A_PVPE_Write32)
+ /* TV encoder */
+ ENTRY(0x00d000, 0x001000, PTV, EmuNV2A_PTV_Read32, EmuNV2A_PTV_Write32)
+ /* aliases VGA memory window */
+ ENTRY(0x0a0000, 0x020000, PRMFB, EmuNV2A_PRMFB_Read32, EmuNV2A_PRMFB_Write32)
+ /* aliases VGA sequencer and graphics controller registers */
+ ENTRY(0x0c0000, 0x008000, PRMVIO, EmuNV2A_PRMVIO_Read32, EmuNV2A_PRMVIO_Write32) // Size was 0x001000
+ /* memory interface */
+ ENTRY(0x100000, 0x001000, PFB, EmuNV2A_PFB_Read32, EmuNV2A_PFB_Write32)
+ /* straps readout / override */
+ ENTRY(0x101000, 0x001000, PSTRAPS, EmuNV2A_PSTRAPS_Read32, EmuNV2A_PSTRAPS_Write32)
+ /* accelerated 2d/3d drawing engine */
+ ENTRY(0x400000, 0x002000, PGRAPH, EmuNV2A_PGRAPH_Read32, EmuNV2A_PGRAPH_Write32)
+ /* more CRTC controls */
+ ENTRY(0x600000, 0x001000, PCRTC, EmuNV2A_PCRTC_Read32, EmuNV2A_PCRTC_Write32)
+ /* aliases VGA CRTC and attribute controller registers */
+ ENTRY(0x601000, 0x001000, PRMCIO, EmuNV2A_PRMCIO_Read32, EmuNV2A_PRMCIO_Write32)
+ /* RAMDAC, cursor, and PLL control */
+ ENTRY(0x680000, 0x001000, PRAMDAC, EmuNV2A_PRAMDAC_Read32, EmuNV2A_PRAMDAC_Write32)
+ /* aliases VGA palette registers */
+ ENTRY(0x681000, 0x001000, PRMDIO, EmuNV2A_PRMDIO_Read32, EmuNV2A_PRMDIO_Write32)
+ /* RAMIN access */
+ ENTRY(0x700000, 0x100000, PRAMIN, EmuNV2A_PRAMIN_Read32, EmuNV2A_PRAMIN_Write32)
+ /* PFIFO MMIO and DMA submission area */
+ ENTRY(0x800000, 0x400000, USER, EmuNV2A_USER_Read32, EmuNV2A_USER_Write32) // Size was 0x800000
+ /* User area mirror - TODO : Confirm */
+ ENTRY(0xC00000, 0x400000, USER, EmuNV2A_USER_Read32, EmuNV2A_USER_Write32) // NOTE : Mirror of USER
+
+ ENTRY(0xFFFFFF, 0x000000, END, nullptr, nullptr)
+#undef ENTRY
};
const NV2ABlockInfo* EmuNV2A_Block(xbaddr addr)
@@ -3544,7 +2205,7 @@ const NV2ABlockInfo* EmuNV2A_Block(xbaddr addr)
const NV2ABlockInfo* block = ®ions[0];
int i = 0;
- while (block->read != nullptr) {
+ while (block->size > 0) {
if (addr >= block->offset && addr < block->offset + block->size) {
return block;
}
@@ -3562,11 +2223,11 @@ uint32_t EmuNV2A_Read(xbaddr addr, int size)
if (block != nullptr) {
switch (size) {
case sizeof(uint8_t):
- return block->read(addr - block->offset) & 0xFF;
+ return block->ops.read(addr - block->offset) & 0xFF;
case sizeof(uint16_t) :
- return block->read(addr - block->offset) & 0xFFFF;
+ return block->ops.read(addr - block->offset) & 0xFFFF;
case sizeof(uint32_t) :
- return block->read(addr - block->offset);
+ return block->ops.read(addr - block->offset);
default:
EmuWarning("EmuNV2A_Read: Invalid read size: %d", size);
return 0;
@@ -3590,25 +2251,25 @@ void EmuNV2A_Write(xbaddr addr, uint32_t value, int size)
case sizeof(uint8_t) :
shift = (addr & 3) * 8;
aligned_addr = addr & ~3;
- aligned_value = block->read(aligned_addr - block->offset);
+ aligned_value = block->ops.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));
+ block->ops.write(aligned_addr - block->offset, (aligned_value & ~mask) | (value << shift));
return;
case sizeof(uint16_t) :
assert((addr & 1) == 0);
shift = (addr & 2) * 16;
aligned_addr = addr & ~3;
- aligned_value = block->read(addr - block->offset);
+ aligned_value = block->ops.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));
+ block->ops.write(aligned_addr - block->offset, (aligned_value & ~mask) | (value << shift));
return;
case sizeof(uint32_t) :
- block->write(addr - block->offset, value);
+ block->ops.write(addr - block->offset, value);
return;
default:
EmuWarning("EmuNV2A_Read: Invalid read size: %d", size);
diff --git a/src/devices/video/EmuNV2A_DEBUG.cpp b/src/devices/video/EmuNV2A_DEBUG.cpp
new file mode 100644
index 000000000..18733e7c5
--- /dev/null
+++ b/src/devices/video/EmuNV2A_DEBUG.cpp
@@ -0,0 +1,446 @@
+#define DEBUG_START(DEV) \
+const char *DebugNV_##DEV##(xbaddr addr) \
+{ \
+ switch (addr) {
+#define DEBUG_CASE(a) \
+ case a: return #a;
+#define DEBUG_CASE_EX(a, c) \
+ case a: return #a##c;
+#define DEBUG_END(DEV) \
+ default: \
+ return "Unknown " #DEV " Address"; \
+ } \
+}
+
+DEBUG_START(PMC)
+ DEBUG_CASE(NV_PMC_BOOT_0);
+ DEBUG_CASE(NV_PMC_BOOT_1);
+ DEBUG_CASE(NV_PMC_INTR_0);
+ DEBUG_CASE(NV_PMC_INTR_EN_0);
+ DEBUG_CASE(NV_PMC_ENABLE);
+DEBUG_END(PMC)
+
+DEBUG_START(PBUS)
+ DEBUG_CASE(NV_PBUS_FBIO_RAM)
+ DEBUG_CASE_EX(NV_PBUS_PCI_NV_0, ":VENDOR_ID");
+ DEBUG_CASE(NV_PBUS_PCI_NV_1);
+ DEBUG_CASE_EX(NV_PBUS_PCI_NV_2, ":REVISION_ID");
+ DEBUG_CASE_EX(NV_PBUS_PCI_NV_3, ":LATENCY_TIMER");
+ DEBUG_CASE(NV_PBUS_PCI_NV_4);
+ DEBUG_CASE(NV_PBUS_PCI_NV_5);
+ DEBUG_CASE(NV_PBUS_PCI_NV_6);
+ DEBUG_CASE(NV_PBUS_PCI_NV_7);
+ 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_13, ":CAP_PTR");
+ DEBUG_CASE_EX(NV_PBUS_PCI_NV_14, ":RESERVED");
+ DEBUG_CASE(NV_PBUS_PCI_NV_15);
+ DEBUG_CASE_EX(NV_PBUS_PCI_NV_16, ":SUBSYSTEM");
+ DEBUG_CASE(NV_PBUS_PCI_NV_17);
+ 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_20, ":ROM_SHADOW");
+ 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_23, ":DT_TIMEOUT");
+ 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_26, ":RESERVED");
+DEBUG_END(PBUS)
+
+DEBUG_START(PFIFO)
+ DEBUG_CASE(NV_PFIFO_DELAY_0);
+ DEBUG_CASE(NV_PFIFO_DMA_TIMESLICE);
+ DEBUG_CASE(NV_PFIFO_TIMESLICE);
+ DEBUG_CASE(NV_PFIFO_INTR_0);
+ DEBUG_CASE(NV_PFIFO_INTR_EN_0);
+ DEBUG_CASE(NV_PFIFO_RAMHT);
+ DEBUG_CASE(NV_PFIFO_RAMFC);
+ DEBUG_CASE(NV_PFIFO_RAMRO);
+ DEBUG_CASE(NV_PFIFO_RUNOUT_STATUS);
+ DEBUG_CASE(NV_PFIFO_RUNOUT_PUT_ADDRESS);
+ DEBUG_CASE(NV_PFIFO_RUNOUT_GET_ADDRESS);
+ DEBUG_CASE(NV_PFIFO_CACHES);
+ DEBUG_CASE(NV_PFIFO_MODE);
+ DEBUG_CASE(NV_PFIFO_DMA);
+ DEBUG_CASE(NV_PFIFO_SIZE)
+ DEBUG_CASE(NV_PFIFO_CACHE0_PUSH0);
+ DEBUG_CASE(NV_PFIFO_CACHE0_PULL0);
+ DEBUG_CASE(NV_PFIFO_CACHE0_HASH);
+ DEBUG_CASE(NV_PFIFO_CACHE1_PUSH0);
+ DEBUG_CASE(NV_PFIFO_CACHE1_PUSH1);
+ DEBUG_CASE(NV_PFIFO_CACHE1_PUT);
+ DEBUG_CASE(NV_PFIFO_CACHE1_STATUS);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_PUSH);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_FETCH);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_STATE);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_INSTANCE);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_CTL);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_PUT);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_GET);
+ DEBUG_CASE(NV_PFIFO_CACHE1_REF);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_SUBROUTINE);
+ DEBUG_CASE(NV_PFIFO_CACHE1_PULL0);
+ DEBUG_CASE(NV_PFIFO_CACHE1_PULL1);
+ DEBUG_CASE(NV_PFIFO_CACHE1_HASH);
+ DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_0);
+ DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_1);
+ DEBUG_CASE(NV_PFIFO_CACHE1_ACQUIRE_2);
+ DEBUG_CASE(NV_PFIFO_CACHE1_SEMAPHORE);
+ DEBUG_CASE(NV_PFIFO_CACHE1_GET);
+ DEBUG_CASE(NV_PFIFO_CACHE1_ENGINE);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_DCOUNT);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_RSVD_SHADOW);
+ DEBUG_CASE(NV_PFIFO_CACHE1_DMA_DATA_SHADOW);
+DEBUG_END(PFIFO)
+
+DEBUG_START(PRMA)
+DEBUG_END(PRMA)
+
+DEBUG_START(PVIDEO)
+ DEBUG_CASE(NV_PVIDEO_DEBUG_2);
+ DEBUG_CASE(NV_PVIDEO_DEBUG_3);
+ DEBUG_CASE(NV_PVIDEO_INTR);
+ DEBUG_CASE(NV_PVIDEO_INTR_EN);
+ DEBUG_CASE(NV_PVIDEO_BUFFER);
+ DEBUG_CASE(NV_PVIDEO_STOP);
+ DEBUG_CASE(NV_PVIDEO_BASE(0));
+ DEBUG_CASE(NV_PVIDEO_BASE(1));
+ DEBUG_CASE(NV_PVIDEO_LIMIT(0));
+ DEBUG_CASE(NV_PVIDEO_LIMIT(1));
+ DEBUG_CASE(NV_PVIDEO_LUMINANCE(0));
+ DEBUG_CASE(NV_PVIDEO_LUMINANCE(1));
+ DEBUG_CASE(NV_PVIDEO_CHROMINANCE(0));
+ DEBUG_CASE(NV_PVIDEO_CHROMINANCE(1));
+ DEBUG_CASE(NV_PVIDEO_OFFSET(0));
+ DEBUG_CASE(NV_PVIDEO_OFFSET(1));
+ DEBUG_CASE(NV_PVIDEO_SIZE_IN(0));
+ DEBUG_CASE(NV_PVIDEO_SIZE_IN(1));
+ DEBUG_CASE(NV_PVIDEO_POINT_IN(0));
+ DEBUG_CASE(NV_PVIDEO_POINT_IN(1));
+ DEBUG_CASE(NV_PVIDEO_DS_DX(0));
+ DEBUG_CASE(NV_PVIDEO_DS_DX(1));
+ DEBUG_CASE(NV_PVIDEO_DT_DY(0));
+ DEBUG_CASE(NV_PVIDEO_DT_DY(1));
+ DEBUG_CASE(NV_PVIDEO_POINT_OUT(0));
+ DEBUG_CASE(NV_PVIDEO_POINT_OUT(1));
+ DEBUG_CASE(NV_PVIDEO_SIZE_OUT(0));
+ DEBUG_CASE(NV_PVIDEO_SIZE_OUT(1));
+ DEBUG_CASE(NV_PVIDEO_FORMAT(0));
+ DEBUG_CASE(NV_PVIDEO_FORMAT(1));
+DEBUG_END(PVIDEO)
+
+DEBUG_START(PTIMER)
+ DEBUG_CASE(NV_PTIMER_INTR_0);
+ DEBUG_CASE(NV_PTIMER_INTR_EN_0);
+ DEBUG_CASE(NV_PTIMER_NUMERATOR);
+ DEBUG_CASE(NV_PTIMER_DENOMINATOR);
+ DEBUG_CASE(NV_PTIMER_TIME_0);
+ DEBUG_CASE(NV_PTIMER_TIME_1);
+ DEBUG_CASE(NV_PTIMER_ALARM_0);
+DEBUG_END(PTIMER)
+
+DEBUG_START(PCOUNTER)
+DEBUG_END(PCOUNTER)
+
+DEBUG_START(PVPE)
+DEBUG_END(PVPE)
+
+DEBUG_START(PTV)
+DEBUG_END(PTV)
+
+DEBUG_START(PRMFB)
+DEBUG_END(PRMFB)
+
+DEBUG_START(PRMVIO)
+DEBUG_END(PRMVIO)
+
+DEBUG_START(PFB)
+ DEBUG_CASE(NV_PFB_CFG0)
+ DEBUG_CASE(NV_PFB_CFG1)
+ DEBUG_CASE(NV_PFB_CSTATUS)
+ DEBUG_CASE(NV_PFB_REFCTRL)
+ DEBUG_CASE(NV_PFB_NVM) // NV_PFB_NVM_MODE_DISABLE
+ DEBUG_CASE(NV_PFB_PIN)
+ DEBUG_CASE(NV_PFB_PAD)
+ DEBUG_CASE(NV_PFB_TIMING0)
+ DEBUG_CASE(NV_PFB_TIMING1)
+ DEBUG_CASE(NV_PFB_TIMING2)
+ DEBUG_CASE(NV_PFB_TILE(0))
+ DEBUG_CASE(NV_PFB_TLIMIT(0))
+ DEBUG_CASE(NV_PFB_TSIZE(0))
+ DEBUG_CASE(NV_PFB_TSTATUS(0))
+ DEBUG_CASE(NV_PFB_TILE(1))
+ DEBUG_CASE(NV_PFB_TLIMIT(1))
+ DEBUG_CASE(NV_PFB_TSIZE(1))
+ DEBUG_CASE(NV_PFB_TSTATUS(1))
+ DEBUG_CASE(NV_PFB_TILE(2))
+ DEBUG_CASE(NV_PFB_TLIMIT(2))
+ DEBUG_CASE(NV_PFB_TSIZE(2))
+ DEBUG_CASE(NV_PFB_TSTATUS(2))
+ DEBUG_CASE(NV_PFB_TILE(3))
+ DEBUG_CASE(NV_PFB_TLIMIT(3))
+ DEBUG_CASE(NV_PFB_TSIZE(3))
+ DEBUG_CASE(NV_PFB_TSTATUS(3))
+ DEBUG_CASE(NV_PFB_TILE(4))
+ DEBUG_CASE(NV_PFB_TLIMIT(4))
+ DEBUG_CASE(NV_PFB_TSIZE(4))
+ DEBUG_CASE(NV_PFB_TSTATUS(4))
+ DEBUG_CASE(NV_PFB_TILE(5))
+ DEBUG_CASE(NV_PFB_TLIMIT(5))
+ DEBUG_CASE(NV_PFB_TSIZE(5))
+ DEBUG_CASE(NV_PFB_TSTATUS(5))
+ DEBUG_CASE(NV_PFB_TILE(6))
+ DEBUG_CASE(NV_PFB_TLIMIT(6))
+ DEBUG_CASE(NV_PFB_TSIZE(6))
+ DEBUG_CASE(NV_PFB_TSTATUS(6))
+ DEBUG_CASE(NV_PFB_TILE(7))
+ DEBUG_CASE(NV_PFB_TLIMIT(7))
+ DEBUG_CASE(NV_PFB_TSIZE(7))
+ DEBUG_CASE(NV_PFB_TSTATUS(7))
+ DEBUG_CASE(NV_PFB_MRS)
+ DEBUG_CASE(NV_PFB_EMRS)
+ DEBUG_CASE(NV_PFB_MRS_EXT)
+ DEBUG_CASE(NV_PFB_EMRS_EXT)
+ DEBUG_CASE(NV_PFB_REF)
+ DEBUG_CASE(NV_PFB_PRE)
+ DEBUG_CASE(NV_PFB_ZCOMP(0))
+ DEBUG_CASE(NV_PFB_ZCOMP(1))
+ DEBUG_CASE(NV_PFB_ZCOMP(2))
+ DEBUG_CASE(NV_PFB_ZCOMP(3))
+ DEBUG_CASE(NV_PFB_ZCOMP(4))
+ DEBUG_CASE(NV_PFB_ZCOMP(5))
+ DEBUG_CASE(NV_PFB_ZCOMP(6))
+ DEBUG_CASE(NV_PFB_ZCOMP(7))
+ DEBUG_CASE(NV_PFB_ZCOMP_OFFSET)
+ DEBUG_CASE(NV_PFB_ARB_PREDIVIDER)
+ DEBUG_CASE(NV_PFB_ARB_TIMEOUT)
+ DEBUG_CASE(NV_PFB_ARB_XFER_REM)
+ DEBUG_CASE(NV_PFB_ARB_DIFF_BANK)
+ DEBUG_CASE(NV_PFB_CLOSE_PAGE0)
+ DEBUG_CASE(NV_PFB_CLOSE_PAGE1)
+ DEBUG_CASE(NV_PFB_CLOSE_PAGE2)
+ DEBUG_CASE(NV_PFB_BPARB)
+ DEBUG_CASE(NV_PFB_CMDQ0)
+ DEBUG_CASE(NV_PFB_CMDQ1)
+ DEBUG_CASE(NV_PFB_ILL_INSTR)
+ DEBUG_CASE(NV_PFB_RT)
+ DEBUG_CASE(NV_PFB_AUTOCLOSE)
+ DEBUG_CASE(NV_PFB_WBC)
+ DEBUG_CASE(NV_PFB_CMDQ_PRT)
+ DEBUG_CASE(NV_PFB_CPU_RRQ)
+ DEBUG_CASE(NV_PFB_BYPASS);
+DEBUG_END(PFB)
+
+DEBUG_START(PSTRAPS)
+DEBUG_END(PSTRAPS)
+
+DEBUG_START(PGRAPH)
+ DEBUG_CASE(NV_PGRAPH_DEBUG_0);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_1);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_3);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_4);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_5);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_8);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_9);
+ DEBUG_CASE(NV_PGRAPH_INTR);
+ DEBUG_CASE(NV_PGRAPH_NSOURCE);
+ DEBUG_CASE(NV_PGRAPH_INTR_EN);
+ DEBUG_CASE(NV_PGRAPH_CTX_CONTROL);
+ DEBUG_CASE(NV_PGRAPH_CTX_USER);
+ DEBUG_CASE(NV_PGRAPH_CTX_SWITCH1);
+ DEBUG_CASE(NV_PGRAPH_CTX_SWITCH2);
+ DEBUG_CASE(NV_PGRAPH_CTX_SWITCH3);
+ DEBUG_CASE(NV_PGRAPH_CTX_SWITCH4);
+ DEBUG_CASE(NV_PGRAPH_STATUS);
+ DEBUG_CASE(NV_PGRAPH_TRAPPED_ADDR);
+ DEBUG_CASE(NV_PGRAPH_TRAPPED_DATA_LOW);
+ DEBUG_CASE(NV_PGRAPH_SURFACE);
+ DEBUG_CASE(NV_PGRAPH_INCREMENT);
+ DEBUG_CASE(NV_PGRAPH_FIFO);
+ DEBUG_CASE(NV_PGRAPH_RDI_INDEX);
+ DEBUG_CASE(NV_PGRAPH_RDI_DATA);
+ DEBUG_CASE(NV_PGRAPH_FFINTFC_ST2);
+ DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_TABLE);
+ DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_POINTER);
+ DEBUG_CASE(NV_PGRAPH_CHANNEL_CTX_TRIGGER);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_2);
+ DEBUG_CASE(NV_PGRAPH_TTILE(0));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(0));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(0));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(0));
+ DEBUG_CASE(NV_PGRAPH_TTILE(1));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(1));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(1));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(1));
+ DEBUG_CASE(NV_PGRAPH_TTILE(2));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(2));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(2));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(2));
+ DEBUG_CASE(NV_PGRAPH_TTILE(3));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(3));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(3));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(3));
+ DEBUG_CASE(NV_PGRAPH_TTILE(4));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(4));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(4));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(4));
+ DEBUG_CASE(NV_PGRAPH_TTILE(5));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(5));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(5));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(5));
+ DEBUG_CASE(NV_PGRAPH_TTILE(6));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(6));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(6));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(6));
+ DEBUG_CASE(NV_PGRAPH_TTILE(7));
+ DEBUG_CASE(NV_PGRAPH_TLIMIT(7));
+ DEBUG_CASE(NV_PGRAPH_TSIZE(7));
+ DEBUG_CASE(NV_PGRAPH_TSTATUS(7));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(0));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(1));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(2));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(3));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(4));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(5));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(6));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP(7));
+ DEBUG_CASE(NV_PGRAPH_ZCOMP_OFFSET);
+ DEBUG_CASE(NV_PGRAPH_FBCFG0);
+ DEBUG_CASE(NV_PGRAPH_FBCFG1);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_6);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_7);
+ DEBUG_CASE(NV_PGRAPH_DEBUG_10);
+ DEBUG_CASE(NV_PGRAPH_CSV0_D);
+ DEBUG_CASE(NV_PGRAPH_CSV0_C);
+ DEBUG_CASE(NV_PGRAPH_CSV1_B);
+ DEBUG_CASE(NV_PGRAPH_CSV1_A);
+ DEBUG_CASE(NV_PGRAPH_CHEOPS_OFFSET);
+ DEBUG_CASE(NV_PGRAPH_BLEND);
+ DEBUG_CASE(NV_PGRAPH_BLENDCOLOR);
+ DEBUG_CASE(NV_PGRAPH_BORDERCOLOR0);
+ DEBUG_CASE(NV_PGRAPH_BORDERCOLOR1);
+ DEBUG_CASE(NV_PGRAPH_BORDERCOLOR2);
+ DEBUG_CASE(NV_PGRAPH_BORDERCOLOR3);
+ DEBUG_CASE(NV_PGRAPH_BUMPOFFSET1);
+ DEBUG_CASE(NV_PGRAPH_BUMPSCALE1);
+ DEBUG_CASE(NV_PGRAPH_CLEARRECTX);
+ DEBUG_CASE(NV_PGRAPH_CLEARRECTY);
+ DEBUG_CASE(NV_PGRAPH_COLORCLEARVALUE);
+ DEBUG_CASE(NV_PGRAPH_COMBINEFACTOR0);
+ DEBUG_CASE(NV_PGRAPH_COMBINEFACTOR1);
+ DEBUG_CASE(NV_PGRAPH_COMBINEALPHAI0);
+ DEBUG_CASE(NV_PGRAPH_COMBINEALPHAO0);
+ DEBUG_CASE(NV_PGRAPH_COMBINECOLORI0);
+ DEBUG_CASE(NV_PGRAPH_COMBINECOLORO0);
+ DEBUG_CASE(NV_PGRAPH_COMBINECTL);
+ DEBUG_CASE(NV_PGRAPH_COMBINESPECFOG0);
+ DEBUG_CASE(NV_PGRAPH_COMBINESPECFOG1);
+ DEBUG_CASE(NV_PGRAPH_CONTROL_0);
+ DEBUG_CASE(NV_PGRAPH_CONTROL_2);
+ DEBUG_CASE(NV_PGRAPH_CONTROL_3);
+ DEBUG_CASE(NV_PGRAPH_FOGCOLOR);
+ DEBUG_CASE(NV_PGRAPH_FOGPARAM0);
+ DEBUG_CASE(NV_PGRAPH_FOGPARAM1);
+ DEBUG_CASE(NV_PGRAPH_SETUPRASTER);
+ DEBUG_CASE(NV_PGRAPH_SHADERCLIPMODE);
+ DEBUG_CASE(NV_PGRAPH_SHADERCTL);
+ DEBUG_CASE(NV_PGRAPH_SHADERPROG);
+ DEBUG_CASE(NV_PGRAPH_SHADOWZSLOPETHRESHOLD);
+ DEBUG_CASE(NV_PGRAPH_SPECFOGFACTOR0);
+ DEBUG_CASE(NV_PGRAPH_SPECFOGFACTOR1);
+ DEBUG_CASE_EX(NV_PGRAPH_TEXADDRESS0, ":_ADDRV");
+ DEBUG_CASE(NV_PGRAPH_TEXADDRESS1);
+ DEBUG_CASE(NV_PGRAPH_TEXADDRESS2);
+ DEBUG_CASE(NV_PGRAPH_TEXADDRESS3);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL0_0);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL0_1);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL0_2);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL0_3);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL1_0);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL1_1);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL1_2);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL1_3);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL2_0);
+ DEBUG_CASE(NV_PGRAPH_TEXCTL2_1);
+ DEBUG_CASE(NV_PGRAPH_TEXFILTER0);
+ DEBUG_CASE(NV_PGRAPH_TEXFILTER1);
+ DEBUG_CASE(NV_PGRAPH_TEXFILTER2);
+ DEBUG_CASE(NV_PGRAPH_TEXFILTER3);
+ DEBUG_CASE(NV_PGRAPH_TEXFMT0);
+ DEBUG_CASE(NV_PGRAPH_TEXFMT1);
+ DEBUG_CASE(NV_PGRAPH_TEXFMT2);
+ DEBUG_CASE(NV_PGRAPH_TEXFMT3);
+ DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT0);
+ DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT1);
+ DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT2);
+ DEBUG_CASE(NV_PGRAPH_TEXIMAGERECT3);
+ DEBUG_CASE(NV_PGRAPH_TEXOFFSET0);
+ DEBUG_CASE(NV_PGRAPH_TEXOFFSET1);
+ DEBUG_CASE(NV_PGRAPH_TEXOFFSET2);
+ DEBUG_CASE(NV_PGRAPH_TEXOFFSET3);
+ DEBUG_CASE(NV_PGRAPH_TEXPALETTE0);
+ DEBUG_CASE(NV_PGRAPH_TEXPALETTE1);
+ DEBUG_CASE(NV_PGRAPH_TEXPALETTE2);
+ DEBUG_CASE(NV_PGRAPH_TEXPALETTE3);
+ DEBUG_CASE(NV_PGRAPH_ZSTENCILCLEARVALUE);
+ DEBUG_CASE(NV_PGRAPH_ZCLIPMIN);
+ DEBUG_CASE(NV_PGRAPH_ZOFFSETBIAS);
+ DEBUG_CASE(NV_PGRAPH_ZOFFSETFACTOR);
+ DEBUG_CASE(NV_PGRAPH_EYEVEC0);
+ DEBUG_CASE(NV_PGRAPH_EYEVEC1);
+ DEBUG_CASE(NV_PGRAPH_EYEVEC2);
+ DEBUG_CASE(NV_PGRAPH_ZCLIPMAX);
+DEBUG_END(PGRAPH)
+
+DEBUG_START(PCRTC)
+ DEBUG_CASE(NV_PCRTC_INTR_0);
+ DEBUG_CASE(NV_PCRTC_INTR_EN_0);
+ DEBUG_CASE(NV_PCRTC_START);
+ DEBUG_CASE(NV_PCRTC_CONFIG);
+DEBUG_END(PCRTC)
+
+DEBUG_START(PRMCIO)
+ DEBUG_CASE(VGA_CRT_DC);
+ DEBUG_CASE(VGA_CRT_DM);
+ DEBUG_CASE(VGA_ATT_R);
+ DEBUG_CASE(VGA_ATT_W);
+ DEBUG_CASE(VGA_GFX_D);
+ DEBUG_CASE(VGA_SEQ_D);
+ DEBUG_CASE(VGA_MIS_R);
+ DEBUG_CASE(VGA_MIS_W);
+ DEBUG_CASE(VGA_FTC_R);
+ DEBUG_CASE(VGA_IS1_RC);
+ DEBUG_CASE(VGA_IS1_RM);
+ DEBUG_CASE(VGA_PEL_D);
+ DEBUG_CASE(VGA_PEL_MSK);
+ DEBUG_CASE(VGA_CRT_IC);
+ DEBUG_CASE(VGA_CRT_IM);
+ DEBUG_CASE(VGA_GFX_I);
+ DEBUG_CASE(VGA_SEQ_I);
+ DEBUG_CASE(VGA_PEL_IW);
+ DEBUG_CASE(VGA_PEL_IR);
+DEBUG_END(PRMCIO)
+
+DEBUG_START(PRAMDAC)
+ DEBUG_CASE(NV_PRAMDAC_NVPLL_COEFF);
+ DEBUG_CASE(NV_PRAMDAC_MPLL_COEFF);
+ DEBUG_CASE(NV_PRAMDAC_VPLL_COEFF);
+ DEBUG_CASE(NV_PRAMDAC_PLL_TEST_COUNTER);
+
+DEBUG_END(PRAMDAC)
+
+DEBUG_START(PRMDIO)
+DEBUG_END(PRMDIO)
+
+DEBUG_START(PRAMIN)
+DEBUG_END(PRAMIN)
+
+DEBUG_START(USER)
+ DEBUG_CASE(NV_USER_DMA_PUT);
+ DEBUG_CASE(NV_USER_DMA_GET);
+ DEBUG_CASE(NV_USER_REF);
+DEBUG_END(USER)
+
+
diff --git a/src/devices/video/EmuNV2A_PBUS.cpp b/src/devices/video/EmuNV2A_PBUS.cpp
new file mode 100644
index 000000000..f44e483c4
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PBUS.cpp
@@ -0,0 +1,35 @@
+DEVICE_READ32(PBUS)
+{
+ DEVICE_READ32_SWITCH() {
+ case NV_PBUS_PCI_NV_0:
+ result = 0x10de; // PCI_VENDOR_ID_NVIDIA (?where to return PCI_DEVICE_ID_NVIDIA_NV2A = 0x01b7)
+
+ break;
+ case NV_PBUS_PCI_NV_1:
+ result = 1; // NV_PBUS_PCI_NV_1_IO_SPACE_ENABLED
+ break;
+ case NV_PBUS_PCI_NV_2:
+ result = (0x02 << 24) | 161; // PCI_CLASS_DISPLAY_3D (0x02) Rev 161 (0xA1)
+ break;
+
+ default:
+ DEBUG_READ32_UNHANDLED(PBUS); // TODO : DEVICE_READ32_REG(pbus);
+ break;
+ }
+
+ DEVICE_READ32_END(PBUS);
+}
+
+DEVICE_WRITE32(PBUS)
+{
+ 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)
+ break;
+ default:
+ DEBUG_WRITE32_UNHANDLED(PBUS); // TODO : DEVICE_WRITE32_REG(pbus);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PBUS);
+}
diff --git a/src/devices/video/EmuNV2A_PCOUNTER.cpp b/src/devices/video/EmuNV2A_PCOUNTER.cpp
new file mode 100644
index 000000000..1f31884ce
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PCOUNTER.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PCOUNTER)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PCOUNTER); // TODO : DEVICE_READ32_REG(pcounter);
+ break;
+ }
+
+ DEVICE_READ32_END(PCOUNTER);
+}
+
+DEVICE_WRITE32(PCOUNTER)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PCOUNTER); // TODO : DEVICE_WRITE32_REG(pcounter);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PCOUNTER);
+}
diff --git a/src/devices/video/EmuNV2A_PCRTC.cpp b/src/devices/video/EmuNV2A_PCRTC.cpp
new file mode 100644
index 000000000..46b59e634
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PCRTC.cpp
@@ -0,0 +1,45 @@
+DEVICE_READ32(PCRTC)
+{
+ DEVICE_READ32_SWITCH() {
+
+ case NV_PCRTC_INTR_0:
+ result = pcrtc.pending_interrupts;
+ break;
+ case NV_PCRTC_INTR_EN_0:
+ result = pcrtc.enabled_interrupts;
+ break;
+ case NV_PCRTC_START:
+ result = pcrtc.start;
+ break;
+ default:
+ result = 0;
+ //DEVICE_READ32_REG(pcrtc); // Was : DEBUG_READ32_UNHANDLED(PCRTC);
+ break;
+ }
+
+ DEVICE_READ32_END(PCRTC);
+}
+
+DEVICE_WRITE32(PCRTC)
+{
+ 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:
+ DEVICE_WRITE32_REG(pcrtc); // Was : DEBUG_WRITE32_UNHANDLED(PCRTC);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PCRTC);
+}
diff --git a/src/devices/video/EmuNV2A_PFB.cpp b/src/devices/video/EmuNV2A_PFB.cpp
new file mode 100644
index 000000000..03f6aa213
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PFB.cpp
@@ -0,0 +1,33 @@
+DEVICE_READ32(PFB)
+{
+ DEVICE_READ32_SWITCH() {
+ case NV_PFB_CFG0:
+ result = 3; // = NV_PFB_CFG0_PART_4
+ break;
+ case NV_PFB_CSTATUS:
+ {
+ if (g_bIsChihiro || g_bIsDebug) { result = CONTIGUOUS_MEMORY_CHIHIRO_SIZE; break; }
+ result = CONTIGUOUS_MEMORY_XBOX_SIZE;
+ }
+ break;
+ case NV_PFB_WBC:
+ result = 0; // = !NV_PFB_WBC_FLUSH
+ break;
+ default:
+ DEVICE_READ32_REG(pfb);
+ break;
+ }
+
+ DEVICE_READ32_END(PFB);
+}
+
+DEVICE_WRITE32(PFB)
+{
+ switch (addr) {
+ default:
+ DEVICE_WRITE32_REG(pfb);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PFB);
+}
diff --git a/src/devices/video/EmuNV2A_PFIFO.cpp b/src/devices/video/EmuNV2A_PFIFO.cpp
new file mode 100644
index 000000000..9c562e09d
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PFIFO.cpp
@@ -0,0 +1,461 @@
+DEVICE_READ32(PFIFO)
+{
+ DEVICE_READ32_SWITCH() {
+ case NV_PFIFO_RAMHT:
+ result = 0x03000100; // = NV_PFIFO_RAMHT_SIZE_4K | NV_PFIFO_RAMHT_BASE_ADDRESS(NumberOfPaddingBytes >> 12) | NV_PFIFO_RAMHT_SEARCH_128
+ break;
+ case NV_PFIFO_RAMFC:
+ result = 0x00890110; // = ? | NV_PFIFO_RAMFC_SIZE_2K | ?
+ break;
+ case NV_PFIFO_INTR_0:
+ result = pfifo.pending_interrupts;
+ break;
+ case NV_PFIFO_INTR_EN_0:
+ result = pfifo.enabled_interrupts;
+ break;
+ case NV_PFIFO_RUNOUT_STATUS:
+ result = NV_PFIFO_RUNOUT_STATUS_LOW_MARK; /* low mark empty */
+ break;
+ case NV_PFIFO_CACHE1_PUSH0:
+ result = pfifo.cache1.push_enabled;
+ break;
+ case NV_PFIFO_CACHE1_PUSH1:
+ SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_CHID, pfifo.cache1.channel_id);
+ SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_MODE, pfifo.cache1.mode);
+ break;
+ case NV_PFIFO_CACHE1_STATUS: {
+ std::lock_guard lk(pfifo.cache1.mutex);
+
+ if (pfifo.cache1.cache.empty()) {
+ result |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */
+ }
+
+ } break;
+ case NV_PFIFO_CACHE1_DMA_PUSH:
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS,
+ pfifo.cache1.dma_push_enabled);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_STATUS,
+ pfifo.cache1.dma_push_suspended);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_BUFFER, 1); /* buffer emoty */
+ break;
+ case NV_PFIFO_CACHE1_DMA_STATE:
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE,
+ pfifo.cache1.method_nonincreasing);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_STATE_METHOD,
+ pfifo.cache1.method >> 2);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL,
+ pfifo.cache1.subchannel);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT,
+ pfifo.cache1.method_count);
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_STATE_ERROR,
+ pfifo.cache1.error);
+ break;
+ case NV_PFIFO_CACHE1_DMA_INSTANCE:
+ SET_MASK(result, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS_MASK,
+ pfifo.cache1.dma_instance >> 4);
+ break;
+ case NV_PFIFO_CACHE1_DMA_PUT:
+ result = user.channel_control[pfifo.cache1.channel_id].dma_put;
+ break;
+ case NV_PFIFO_CACHE1_DMA_GET:
+ result = user.channel_control[pfifo.cache1.channel_id].dma_get;
+ break;
+ case NV_PFIFO_CACHE1_DMA_SUBROUTINE:
+ result = pfifo.cache1.subroutine_return
+ | pfifo.cache1.subroutine_active;
+ break;
+ case NV_PFIFO_CACHE1_PULL0: {
+ std::lock_guard lk(pfifo.cache1.mutex);
+ result = pfifo.cache1.pull_enabled;
+ } break;
+ case NV_PFIFO_CACHE1_ENGINE: {
+ std::lock_guard lk(pfifo.cache1.mutex);
+ for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
+ result |= pfifo.cache1.bound_engines[i] << (i * 2);
+ }
+
+ } break;
+ case NV_PFIFO_CACHE1_DMA_DCOUNT:
+ result = pfifo.cache1.dcount;
+ break;
+ case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW:
+ result = pfifo.cache1.get_jmp_shadow;
+ break;
+ case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW:
+ result = pfifo.cache1.rsvd_shadow;
+ break;
+ case NV_PFIFO_CACHE1_DMA_DATA_SHADOW:
+ result = pfifo.cache1.data_shadow;
+ break;
+ default:
+ DEVICE_READ32_REG(pfifo); // Was : DEBUG_READ32_UNHANDLED(PFIFO);
+ break;
+ }
+
+ DEVICE_READ32_END(PFIFO);
+}
+
+DEVICE_WRITE32(PFIFO)
+{
+ switch(addr) {
+ case NV_PFIFO_INTR_0:
+ pfifo.pending_interrupts &= ~value;
+ update_irq();
+ break;
+ case NV_PFIFO_INTR_EN_0:
+ pfifo.enabled_interrupts = value;
+ update_irq();
+ break;
+ case NV_PFIFO_CACHE1_PUSH0:
+ pfifo.cache1.push_enabled = value & NV_PFIFO_CACHE1_PUSH0_ACCESS;
+ break;
+ case NV_PFIFO_CACHE1_PUSH1:
+ pfifo.cache1.channel_id = GET_MASK(value, NV_PFIFO_CACHE1_PUSH1_CHID);
+ pfifo.cache1.mode = (FifoMode)GET_MASK(value, NV_PFIFO_CACHE1_PUSH1_MODE);
+ assert(pfifo.cache1.channel_id < NV2A_NUM_CHANNELS);
+ break;
+ case NV_PFIFO_CACHE1_DMA_PUSH:
+ pfifo.cache1.dma_push_enabled = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS);
+ if (pfifo.cache1.dma_push_suspended && !GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS)) {
+ pfifo.cache1.dma_push_suspended = false;
+ pfifo_run_pusher();
+ }
+ pfifo.cache1.dma_push_suspended = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS);
+ break;
+ case NV_PFIFO_CACHE1_DMA_STATE:
+ pfifo.cache1.method_nonincreasing = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE);
+ pfifo.cache1.method = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD) << 2;
+ pfifo.cache1.subchannel = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL);
+ pfifo.cache1.method_count = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT);
+ pfifo.cache1.error = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_ERROR);
+ break;
+ case NV_PFIFO_CACHE1_DMA_INSTANCE:
+ pfifo.cache1.dma_instance = GET_MASK(value, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS_MASK) << 4;
+ break;
+ case NV_PFIFO_CACHE1_DMA_PUT:
+ user.channel_control[pfifo.cache1.channel_id].dma_put = value;
+ break;
+ case NV_PFIFO_CACHE1_DMA_GET:
+ user.channel_control[pfifo.cache1.channel_id].dma_get = value;
+ break;
+ case NV_PFIFO_CACHE1_DMA_SUBROUTINE:
+ pfifo.cache1.subroutine_return = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_RETURN_OFFSET);
+ pfifo.cache1.subroutine_active = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
+ break;
+ case NV_PFIFO_CACHE1_PULL0: {
+ std::lock_guard lk(pfifo.cache1.mutex);
+
+ if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS)
+ && !pfifo.cache1.pull_enabled) {
+ pfifo.cache1.pull_enabled = true;
+
+ /* the puller thread should wake up */
+ pfifo.cache1.cache_cond.notify_all();
+ } else if (!(value & NV_PFIFO_CACHE1_PULL0_ACCESS)
+ && pfifo.cache1.pull_enabled) {
+ pfifo.cache1.pull_enabled = false;
+ }
+ } break;
+ case NV_PFIFO_CACHE1_ENGINE: {
+ std::lock_guard lk(pfifo.cache1.mutex);
+
+ for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
+ pfifo.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3);
+ }
+
+ } break;
+ case NV_PFIFO_CACHE1_DMA_DCOUNT:
+ pfifo.cache1.dcount = (value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE);
+ break;
+ case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW:
+ pfifo.cache1.get_jmp_shadow = (value & NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW_OFFSET);
+ break;
+ case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW:
+ pfifo.cache1.rsvd_shadow = value;
+ break;
+ case NV_PFIFO_CACHE1_DMA_DATA_SHADOW:
+ pfifo.cache1.data_shadow = value;
+ break;
+ default:
+ DEVICE_WRITE32_REG(pfifo); // Was : DEBUG_WRITE32_UNHANDLED(PFIFO);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PFIFO);
+}
+
+/* pusher should be fine to run from a mimo handler
+* whenever's it's convenient */
+static void pfifo_run_pusher() {
+ uint8_t channel_id;
+ ChannelControl *control;
+ Cache1State *state;
+ CacheEntry *command;
+ uint8_t *dma;
+ xbaddr dma_len;
+ uint32_t word;
+
+ /* TODO: How is cache1 selected? */
+ state = &pfifo.cache1;
+ channel_id = state->channel_id;
+ control = &user.channel_control[channel_id];
+
+ if (!state->push_enabled) return;
+
+ /* only handling DMA for now... */
+
+ /* Channel running DMA */
+ uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
+ assert(channel_modes & (1 << channel_id));
+ assert(state->mode == FIFO_DMA);
+
+ if (!state->dma_push_enabled) return;
+ if (state->dma_push_suspended) return;
+
+ /* We're running so there should be no pending errors... */
+ assert(state->error == NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE);
+
+ dma = (uint8_t*)nv_dma_map(state->dma_instance, &dma_len);
+
+ printf("DMA pusher: max 0x%08X, 0x%08X - 0x%08X\n",
+ dma_len, control->dma_get, control->dma_put);
+
+ /* based on the convenient pseudocode in envytools */
+ while (control->dma_get != control->dma_put) {
+ if (control->dma_get >= dma_len) {
+ state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION;
+ break;
+ }
+
+ word = ldl_le_p((uint32_t*)(dma + control->dma_get));
+ control->dma_get += 4;
+
+ if (state->method_count) {
+ /* data word of methods command */
+ state->data_shadow = word;
+
+ command = (CacheEntry*)calloc(1, sizeof(CacheEntry));
+ command->method = state->method;
+ command->subchannel = state->subchannel;
+ command->nonincreasing = state->method_nonincreasing;
+ command->parameter = word;
+
+ std::lock_guard lk(state->mutex);
+ state->cache.push(command);
+ state->cache_cond.notify_all();
+
+ if (!state->method_nonincreasing) {
+ state->method += 4;
+ }
+
+ state->method_count--;
+ state->dcount++;
+ } else {
+ /* no command active - this is the first word of a new one */
+ state->rsvd_shadow = word;
+ /* match all forms */
+ if ((word & 0xe0000003) == 0x20000000) {
+ /* old jump */
+ state->get_jmp_shadow = control->dma_get;
+ control->dma_get = word & 0x1fffffff;
+ printf("pb OLD_JMP 0x%08X\n", control->dma_get);
+ }
+ else if ((word & 3) == 1) {
+ /* jump */
+ state->get_jmp_shadow = control->dma_get;
+ control->dma_get = word & 0xfffffffc;
+ printf("pb JMP 0x%08X\n", control->dma_get);
+ }
+ else if ((word & 3) == 2) {
+ /* call */
+ if (state->subroutine_active) {
+ state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL;
+ break;
+ }
+ state->subroutine_return = control->dma_get;
+ state->subroutine_active = true;
+ control->dma_get = word & 0xfffffffc;
+ printf("pb CALL 0x%08X\n", control->dma_get);
+ }
+ else if (word == 0x00020000) {
+ /* return */
+ if (!state->subroutine_active) {
+ state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN;
+ break;
+ }
+ control->dma_get = state->subroutine_return;
+ state->subroutine_active = false;
+ printf("pb RET 0x%08X\n", control->dma_get);
+ }
+ else if ((word & 0xe0030003) == 0) {
+ /* increasing methods */
+ state->method = word & 0x1fff;
+ state->subchannel = (word >> 13) & 7;
+ state->method_count = (word >> 18) & 0x7ff;
+ state->method_nonincreasing = false;
+ state->dcount = 0;
+ }
+ else if ((word & 0xe0030003) == 0x40000000) {
+ /* non-increasing methods */
+ state->method = word & 0x1fff;
+ state->subchannel = (word >> 13) & 7;
+ state->method_count = (word >> 18) & 0x7ff;
+ state->method_nonincreasing = true;
+ state->dcount = 0;
+ }
+ else {
+ printf("pb reserved cmd 0x%08X - 0x%08X\n",
+ control->dma_get, word);
+ state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD;
+ break;
+ }
+ }
+ }
+
+ printf("DMA pusher done: max 0x%08X, 0x%08X - 0x%08X\n",
+ dma_len, control->dma_get, control->dma_put);
+
+ if (state->error) {
+ printf("pb error: %d\n", state->error);
+ assert(false);
+
+ state->dma_push_suspended = true;
+
+ pfifo.pending_interrupts |= NV_PFIFO_INTR_0_DMA_PUSHER;
+ update_irq();
+ }
+}
+
+static void* pfifo_puller_thread()
+{
+ Cache1State *state = &pfifo.cache1;
+
+ while (true) {
+ // Scope the lock so that it automatically unlocks at tne end of this block
+ {
+ std::unique_lock lk(state->mutex);
+
+ while (state->cache.empty() || !state->pull_enabled) {
+ state->cache_cond.wait(lk);
+ }
+
+ // Copy cache to working_cache
+ while (!state->cache.empty()) {
+ state->working_cache.push(state->cache.front());
+ state->cache.pop();
+ }
+ }
+
+ while (!state->working_cache.empty()) {
+ CacheEntry* command = state->working_cache.front();
+ state->working_cache.pop();
+
+ if (command->method == 0) {
+ // qemu_mutex_lock_iothread();
+ RAMHTEntry entry = ramht_lookup(command->parameter);
+ assert(entry.valid);
+
+ assert(entry.channel_id == state->channel_id);
+ // qemu_mutex_unlock_iothread();
+
+ switch (entry.engine) {
+ case ENGINE_GRAPHICS:
+ pgraph_context_switch(entry.channel_id);
+ pgraph_wait_fifo_access();
+ pgraph_method(command->subchannel, 0, entry.instance);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ /* the engine is bound to the subchannel */
+ std::lock_guard lk(pfifo.cache1.mutex);
+ state->bound_engines[command->subchannel] = entry.engine;
+ state->last_engine = entry.engine;
+ } else if (command->method >= 0x100) {
+ /* method passed to engine */
+
+ uint32_t parameter = command->parameter;
+
+ /* methods that take objects.
+ * TODO: Check this range is correct for the nv2a */
+ if (command->method >= 0x180 && command->method < 0x200) {
+ //qemu_mutex_lock_iothread();
+ RAMHTEntry entry = ramht_lookup(parameter);
+ assert(entry.valid);
+ assert(entry.channel_id == state->channel_id);
+ parameter = entry.instance;
+ //qemu_mutex_unlock_iothread();
+ }
+
+ // qemu_mutex_lock(&state->cache_lock);
+ enum FIFOEngine engine = state->bound_engines[command->subchannel];
+ // qemu_mutex_unlock(&state->cache_lock);
+
+ switch (engine) {
+ case ENGINE_GRAPHICS:
+ pgraph_wait_fifo_access();
+ pgraph_method(command->subchannel, command->method, parameter);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ // qemu_mutex_lock(&state->cache_lock);
+ state->last_engine = state->bound_engines[command->subchannel];
+ // qemu_mutex_unlock(&state->cache_lock);
+ }
+
+ free(command);
+ }
+ }
+
+ return NULL;
+}
+
+static uint32_t ramht_hash(uint32_t handle)
+{
+ unsigned int ramht_size = 1 << (GET_MASK(pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
+
+ /* XXX: Think this is different to what nouveau calculates... */
+ unsigned int bits = ffs(ramht_size) - 2;
+
+ uint32_t hash = 0;
+ while (handle) {
+ hash ^= (handle & ((1 << bits) - 1));
+ handle >>= bits;
+ }
+ hash ^= pfifo.cache1.channel_id << (bits - 4);
+
+ return hash;
+}
+
+
+static RAMHTEntry ramht_lookup(uint32_t handle)
+{
+ unsigned int ramht_size = 1 << (GET_MASK(pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
+
+ uint32_t hash = ramht_hash(handle);
+ assert(hash * 8 < ramht_size);
+
+ uint32_t ramht_address =
+ GET_MASK(pfifo.regs[NV_PFIFO_RAMHT],
+ NV_PFIFO_RAMHT_BASE_ADDRESS_MASK) << 12;
+
+ uint8_t *entry_ptr = (uint8_t*)(NV2A_ADDR + NV_PRAMIN_ADDR + ramht_address + hash * 8);
+
+ uint32_t entry_handle = ldl_le_p((uint32_t*)entry_ptr);
+ uint32_t entry_context = ldl_le_p((uint32_t*)(entry_ptr + 4));
+
+ RAMHTEntry entry;
+ entry.handle = entry_handle;
+ entry.instance = (entry_context & NV_RAMHT_INSTANCE) << 4;
+ entry.engine = (FIFOEngine)((entry_context & NV_RAMHT_ENGINE) >> 16);
+ entry.channel_id = (entry_context & NV_RAMHT_CHID) >> 24;
+ entry.valid = entry_context & NV_RAMHT_STATUS;
+
+ return entry;
+}
+
diff --git a/src/devices/video/EmuNV2A_PGRAPH.cpp b/src/devices/video/EmuNV2A_PGRAPH.cpp
new file mode 100644
index 000000000..b28efaaae
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PGRAPH.cpp
@@ -0,0 +1,117 @@
+DEVICE_READ32(PGRAPH)
+{
+ std::lock_guard lk(pgraph.mutex);
+
+ DEVICE_READ32_SWITCH() {
+ case NV_PGRAPH_INTR:
+ result = pgraph.pending_interrupts;
+ break;
+ case NV_PGRAPH_INTR_EN:
+ result = pgraph.enabled_interrupts;
+ break;
+ case NV_PGRAPH_NSOURCE:
+ result = pgraph.notify_source;
+ break;
+ case NV_PGRAPH_CTX_USER:
+ SET_MASK(result, NV_PGRAPH_CTX_USER_CHANNEL_3D, pgraph.context[pgraph.channel_id].channel_3d);
+ SET_MASK(result, NV_PGRAPH_CTX_USER_CHANNEL_3D_VALID, 1);
+ SET_MASK(result, NV_PGRAPH_CTX_USER_SUBCH, pgraph.context[pgraph.channel_id].subchannel << 13);
+ SET_MASK(result, NV_PGRAPH_CTX_USER_CHID, pgraph.channel_id);
+ break;
+ case NV_PGRAPH_TRAPPED_ADDR:
+ SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_CHID, pgraph.trapped_channel_id);
+ SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_SUBCH, pgraph.trapped_subchannel);
+ SET_MASK(result, NV_PGRAPH_TRAPPED_ADDR_MTHD, pgraph.trapped_method);
+ break;
+ case NV_PGRAPH_TRAPPED_DATA_LOW:
+ result = pgraph.trapped_data[0];
+ break;
+ case NV_PGRAPH_FIFO:
+ SET_MASK(result, NV_PGRAPH_FIFO_ACCESS, pgraph.fifo_access);
+ break;
+ case NV_PGRAPH_CHANNEL_CTX_TABLE:
+ result = pgraph.context_table >> 4;
+ break;
+ case NV_PGRAPH_CHANNEL_CTX_POINTER:
+ result = pgraph.context_address >> 4;
+ break;
+ default:
+ DEVICE_READ32_REG(pgraph); // Was : DEBUG_READ32_UNHANDLED(PGRAPH);
+ }
+
+ DEVICE_READ32_END(PGRAPH);
+}
+
+static void pgraph_set_context_user(uint32_t value)
+{
+ pgraph.channel_id = (value & NV_PGRAPH_CTX_USER_CHID) >> 24;
+ pgraph.context[pgraph.channel_id].channel_3d = GET_MASK(value, NV_PGRAPH_CTX_USER_CHANNEL_3D);
+ pgraph.context[pgraph.channel_id].subchannel = GET_MASK(value, NV_PGRAPH_CTX_USER_SUBCH);
+}
+
+DEVICE_WRITE32(PGRAPH)
+{
+ std::lock_guard lk(pgraph.mutex);
+
+ switch (addr) {
+ case NV_PGRAPH_INTR:
+ pgraph.pending_interrupts &= ~value;
+ pgraph.interrupt_cond.notify_all();
+ break;
+ case NV_PGRAPH_INTR_EN:
+ pgraph.enabled_interrupts = value;
+ break;
+ case NV_PGRAPH_CTX_CONTROL:
+ pgraph.channel_valid = (value & NV_PGRAPH_CTX_CONTROL_CHID);
+ break;
+ case NV_PGRAPH_CTX_USER:
+ pgraph_set_context_user(value);
+ break;
+ case NV_PGRAPH_INCREMENT:
+ if (value & NV_PGRAPH_INCREMENT_READ_3D) {
+ SET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
+ NV_PGRAPH_SURFACE_READ_3D,
+ (GET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
+ NV_PGRAPH_SURFACE_READ_3D) + 1)
+ % GET_MASK(pgraph.regs[NV_PGRAPH_SURFACE],
+ NV_PGRAPH_SURFACE_MODULO_3D));
+
+ pgraph.flip_3d.notify_all();
+ }
+ break;
+ case NV_PGRAPH_FIFO:
+ pgraph.fifo_access = GET_MASK(value, NV_PGRAPH_FIFO_ACCESS);
+ pgraph.fifo_access_cond.notify_all();
+ break;
+ case NV_PGRAPH_CHANNEL_CTX_TABLE:
+ pgraph.context_table = (value & NV_PGRAPH_CHANNEL_CTX_TABLE_INST) << 4;
+ break;
+ case NV_PGRAPH_CHANNEL_CTX_POINTER:
+ pgraph.context_address =
+ (value & NV_PGRAPH_CHANNEL_CTX_POINTER_INST) << 4;
+ break;
+ case NV_PGRAPH_CHANNEL_CTX_TRIGGER:
+ if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN) {
+ printf("PGRAPH: read channel %d context from %0x08X\n",
+ pgraph.channel_id, pgraph.context_address);
+
+ uint8_t *context_ptr = (uint8_t*)(NV2A_ADDR + NV_PRAMIN_ADDR + pgraph.context_address);
+ uint32_t context_user = ldl_le_p((uint32_t*)context_ptr);
+
+ printf(" - CTX_USER = 0x%x\n", context_user);
+
+
+ pgraph_set_context_user(context_user);
+ }
+ if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT) {
+ /* do stuff ... */
+ }
+
+ break;
+ default:
+ DEVICE_WRITE32_REG(pgraph); // Was : DEBUG_WRITE32_UNHANDLED(PGRAPH);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PGRAPH);
+}
diff --git a/src/devices/video/EmuNV2A_PMC.cpp b/src/devices/video/EmuNV2A_PMC.cpp
new file mode 100644
index 000000000..f21260070
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PMC.cpp
@@ -0,0 +1,45 @@
+DEVICE_READ32(PMC)
+{
+ DEVICE_READ32_SWITCH() {
+ case NV_PMC_BOOT_0: // chipset and stepping: NV2A, A02, Rev 0
+ result = 0x02A000A2;
+ break;
+ case NV_PMC_BOOT_1: // Selects big/little endian mode for the card
+ result = 0; // When read, returns 0 if in little-endian mode, 0x01000001 if in big-endian mode.
+ break;
+ case NV_PMC_INTR_0: // Shows which functional units have pending IRQ
+ result = pmc.pending_interrupts;
+ break;
+ case NV_PMC_INTR_EN_0: // Selects which functional units can cause IRQs
+ result = pmc.enabled_interrupts;
+ break;
+ default:
+ result = 0;
+ //DEVICE_READ32_REG(pmc); // Was : DEBUG_READ32_UNHANDLED(PMC);
+ break;
+ }
+
+ DEVICE_READ32_END(PMC);
+}
+
+DEVICE_WRITE32(PMC)
+{
+ 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:
+ //DEVICE_WRITE32_REG(pmc); // Was : DEBUG_WRITE32_UNHANDLED(PMC);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PMC);
+}
+
+
diff --git a/src/devices/video/EmuNV2A_PRAMDAC.cpp b/src/devices/video/EmuNV2A_PRAMDAC.cpp
new file mode 100644
index 000000000..b9e8f8b12
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRAMDAC.cpp
@@ -0,0 +1,64 @@
+DEVICE_READ32(PRAMDAC)
+{
+ DEVICE_READ32_SWITCH() {
+
+ case NV_PRAMDAC_NVPLL_COEFF:
+ result = pramdac.core_clock_coeff;
+ break;
+ case NV_PRAMDAC_MPLL_COEFF:
+ result = pramdac.memory_clock_coeff;
+ break;
+ case NV_PRAMDAC_VPLL_COEFF:
+ result = pramdac.video_clock_coeff;
+ break;
+ case NV_PRAMDAC_PLL_TEST_COUNTER:
+ /* emulated PLLs locked instantly? */
+ result = 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:
+ //DEVICE_READ32_REG(pramdac); // Was : DEBUG_READ32_UNHANDLED(PRAMDAC);
+ break;
+ }
+
+ DEVICE_READ32_END(PRAMDAC);
+}
+
+DEVICE_WRITE32(PRAMDAC)
+{
+ switch (addr) {
+
+ uint32_t m, n, p;
+ case NV_PRAMDAC_NVPLL_COEFF:
+ pramdac.core_clock_coeff = value;
+
+ m = value & NV_PRAMDAC_NVPLL_COEFF_MDIV;
+ n = (value & NV_PRAMDAC_NVPLL_COEFF_NDIV) >> 8;
+ p = (value & NV_PRAMDAC_NVPLL_COEFF_PDIV) >> 16;
+
+ if (m == 0) {
+ pramdac.core_clock_freq = 0;
+ }
+ else {
+ pramdac.core_clock_freq = (NV2A_CRYSTAL_FREQ * n)
+ / (1 << p) / m;
+ }
+
+ break;
+ case NV_PRAMDAC_MPLL_COEFF:
+ pramdac.memory_clock_coeff = value;
+ break;
+ case NV_PRAMDAC_VPLL_COEFF:
+ pramdac.video_clock_coeff = value;
+ break;
+
+ default:
+ //DEVICE_WRITE32_REG(pramdac); // Was : DEBUG_WRITE32_UNHANDLED(PRAMDAC);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRAMDAC);
+}
diff --git a/src/devices/video/EmuNV2A_PRAMIN.cpp b/src/devices/video/EmuNV2A_PRAMIN.cpp
new file mode 100644
index 000000000..389ec2735
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRAMIN.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PRAMIN)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEVICE_READ32_REG(pramin);
+ break;
+ }
+
+ DEVICE_READ32_END(PRAMIN);
+}
+
+DEVICE_WRITE32(PRAMIN)
+{
+ switch (addr) {
+ default:
+ DEVICE_WRITE32_REG(pramin);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRAMIN);
+}
diff --git a/src/devices/video/EmuNV2A_PRMA.cpp b/src/devices/video/EmuNV2A_PRMA.cpp
new file mode 100644
index 000000000..0c75aca3e
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRMA.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PRMA)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PRMA); // TODO : DEVICE_READ32_REG(prma);
+ break;
+ }
+
+ DEVICE_READ32_END(PRMA);
+}
+
+DEVICE_WRITE32(PRMA)
+{
+ switch(addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PRMA); // TODO : DEVICE_WRITE32_REG(prma);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRMA);
+}
diff --git a/src/devices/video/EmuNV2A_PRMCIO.cpp b/src/devices/video/EmuNV2A_PRMCIO.cpp
new file mode 100644
index 000000000..381e64132
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRMCIO.cpp
@@ -0,0 +1,70 @@
+DEVICE_READ32(PRMCIO)
+{
+ DEVICE_READ32_SWITCH() {
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
+ result = prmcio.cr_index;
+ break;
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
+ result = prmcio.cr[prmcio.cr_index];
+
+ printf("vga: read CR%x = 0x%02x\n", prmcio.cr_index, result);
+ break;
+ default:
+ DEBUG_READ32_UNHANDLED(PRMCIO);
+ printf("vga: UNHANDLED ADDR %s\n", addr);
+ break;
+ }
+
+ DEVICE_READ32_END(PRMCIO);
+}
+
+DEVICE_WRITE32(PRMCIO)
+{
+ switch (addr) {
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
+ prmcio.cr_index = value;
+ break;
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
+ printf("vga: write CR%x = 0x%02x\n", prmcio.cr_index, value);
+
+ /* handle CR0-7 protection */
+ if ((prmcio.cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
+ prmcio.cr_index <= VGA_CRTC_OVERFLOW) {
+ /* can always write bit 4 of CR7 */
+ if (prmcio.cr_index == VGA_CRTC_OVERFLOW) {
+ prmcio.cr[VGA_CRTC_OVERFLOW] = (prmcio.cr[VGA_CRTC_OVERFLOW] & ~0x10) |
+ (value & 0x10);
+ EmuWarning("TODO: vbe_update_vgaregs");
+ //vbe_update_vgaregs();
+ }
+ return;
+ }
+
+ prmcio.cr[prmcio.cr_index] = value;
+ EmuWarning("TODO: vbe_update_vgaregs");
+ //vbe_update_vgaregs();
+
+ switch (prmcio.cr_index) {
+ case VGA_CRTC_H_TOTAL:
+ case VGA_CRTC_H_SYNC_START:
+ case VGA_CRTC_H_SYNC_END:
+ case VGA_CRTC_V_TOTAL:
+ case VGA_CRTC_OVERFLOW:
+ case VGA_CRTC_V_SYNC_END:
+ case VGA_CRTC_MODE:
+ // TODO: s->update_retrace_info(s);
+ EmuWarning("TODO: update_retrace_info");
+ break;
+ }
+ break;
+ default:
+ DEBUG_WRITE32_UNHANDLED(PRMCIO); // TODO : DEVICE_WRITE32_REG(prmcio);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRMCIO);
+}
diff --git a/src/devices/video/EmuNV2A_PRMDIO.cpp b/src/devices/video/EmuNV2A_PRMDIO.cpp
new file mode 100644
index 000000000..3ddaaedec
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRMDIO.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PRMDIO)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PRMDIO);
+ break;
+ }
+
+ DEVICE_READ32_END(PRMDIO);
+}
+
+DEVICE_WRITE32(PRMDIO)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PRMDIO);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRMDIO);
+}
diff --git a/src/devices/video/EmuNV2A_PRMFB.cpp b/src/devices/video/EmuNV2A_PRMFB.cpp
new file mode 100644
index 000000000..b620b5897
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRMFB.cpp
@@ -0,0 +1,22 @@
+DEVICE_READ32(PRMFB)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PRMFB); // TODO : DEVICE_READ32_REG(prmfb);
+ break;
+ }
+
+ DEVICE_READ32_END(PRMFB);
+}
+
+DEVICE_WRITE32(PRMFB)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PRMFB); // TODO : DEVICE_WRITE32_REG(prmfb);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRMFB);
+}
+
diff --git a/src/devices/video/EmuNV2A_PRMVIO.cpp b/src/devices/video/EmuNV2A_PRMVIO.cpp
new file mode 100644
index 000000000..7527e00e4
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PRMVIO.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PRMVIO)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PRMVIO); // TODO : DEVICE_READ32_REG(prmvio);
+ break;
+ }
+
+ DEVICE_READ32_END(PRMVIO);
+}
+
+DEVICE_WRITE32(PRMVIO)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PRMVIO); // TODO : DEVICE_WRITE32_REG(prmvio);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PRMVIO);
+}
diff --git a/src/devices/video/EmuNV2A_PSTRAPS.cpp b/src/devices/video/EmuNV2A_PSTRAPS.cpp
new file mode 100644
index 000000000..773b6f54a
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PSTRAPS.cpp
@@ -0,0 +1,23 @@
+DEVICE_READ32(PSTRAPS)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PSTRAPS);
+ break;
+ }
+
+ DEVICE_READ32_END(PSTRAPS);
+}
+
+DEVICE_WRITE32(PSTRAPS)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PSTRAPS);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PSTRAPS);
+}
+
+
diff --git a/src/devices/video/EmuNV2A_PTIMER.cpp b/src/devices/video/EmuNV2A_PTIMER.cpp
new file mode 100644
index 000000000..46f1590f6
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PTIMER.cpp
@@ -0,0 +1,87 @@
+static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ union {
+ uint64_t ll;
+ struct {
+ uint32_t low, high;
+ } l;
+ } u, res;
+ uint64_t rl, rh;
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+}
+
+/* PIMTER - time measurement and time-based alarms */
+static uint32_t ptimer_get_clock()
+{
+ // Get time in nanoseconds
+ long int time = static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
+
+ return muldiv64(time, pramdac.core_clock_freq * ptimer.numerator, CLOCKS_PER_SEC * ptimer.denominator);
+}
+
+DEVICE_READ32(PTIMER)
+{
+ DEVICE_READ32_SWITCH() {
+ case NV_PTIMER_INTR_0:
+ result = ptimer.pending_interrupts;
+ break;
+ case NV_PTIMER_INTR_EN_0:
+ result = ptimer.enabled_interrupts;
+ break;
+ case NV_PTIMER_NUMERATOR:
+ result = ptimer.numerator;
+ break;
+ case NV_PTIMER_DENOMINATOR:
+ result = ptimer.denominator;
+ break;
+ case NV_PTIMER_TIME_0:
+ result = (ptimer_get_clock() & 0x7ffffff) << 5;
+ break;
+ case NV_PTIMER_TIME_1:
+ result = (ptimer_get_clock() >> 27) & 0x1fffffff;
+ break;
+ default:
+ result = 0;
+ //DEVICE_READ32_REG(ptimer); // Was : DEBUG_READ32_UNHANDLED(PTIMER);
+ break;
+ }
+
+ DEVICE_READ32_END(PTIMER);
+}
+
+
+DEVICE_WRITE32(PTIMER)
+{
+ 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:
+ //DEVICE_WRITE32_REG(ptimer); // Was : DEBUG_WRITE32_UNHANDLED(PTIMER);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PTIMER);
+}
diff --git a/src/devices/video/EmuNV2A_PTV.cpp b/src/devices/video/EmuNV2A_PTV.cpp
new file mode 100644
index 000000000..3c509d774
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PTV.cpp
@@ -0,0 +1,21 @@
+DEVICE_READ32(PTV)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PTV); // TODO : DEVICE_READ32_REG(ptv);
+ break;
+ }
+
+ DEVICE_READ32_END(PTV);
+}
+
+DEVICE_WRITE32(PTV)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PTV); // TODO : DEVICE_WRITE32_REG(ptv);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PTV);
+}
diff --git a/src/devices/video/EmuNV2A_PVIDEO.cpp b/src/devices/video/EmuNV2A_PVIDEO.cpp
new file mode 100644
index 000000000..595877a9d
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PVIDEO.cpp
@@ -0,0 +1,48 @@
+/*
+static void pvideo_vga_invalidate(NV2AState *d)
+{
+ int y1 = GET_MASK(d->pvideo.regs[NV_PVIDEO_POINT_OUT],
+ NV_PVIDEO_POINT_OUT_Y);
+ int y2 = y1 + GET_MASK(d->pvideo.regs[NV_PVIDEO_SIZE_OUT],
+ NV_PVIDEO_SIZE_OUT_HEIGHT);
+ NV2A_DPRINTF("pvideo_vga_invalidate %d %d\n", y1, y2);
+ vga_invalidate_scanlines(&d->vga, y1, y2);
+}
+
+*/
+DEVICE_READ32(PVIDEO)
+{
+ DEVICE_READ32_SWITCH() {
+
+ case NV_PVIDEO_STOP:
+ result = 0;
+ break;
+ default:
+ DEVICE_READ32_REG(pvideo);
+ break;
+ }
+
+ DEVICE_READ32_END(PVIDEO);
+}
+
+DEVICE_WRITE32(PVIDEO)
+{
+ switch (addr) {
+ case NV_PVIDEO_BUFFER:
+ pvideo.regs[addr] = value;
+ // TODO: vga.enable_overlay = true;
+ // pvideo_vga_invalidate(d);
+ break;
+ case NV_PVIDEO_STOP:
+ pvideo.regs[NV_PVIDEO_BUFFER] = 0;
+ // TODO: vga.enable_overlay = false;
+ //pvideo_vga_invalidate(d);
+ break;
+ default:
+ DEVICE_WRITE32_REG(pvideo);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PVIDEO);
+}
+
diff --git a/src/devices/video/EmuNV2A_PVPE.cpp b/src/devices/video/EmuNV2A_PVPE.cpp
new file mode 100644
index 000000000..8dabb82a0
--- /dev/null
+++ b/src/devices/video/EmuNV2A_PVPE.cpp
@@ -0,0 +1,23 @@
+DEVICE_READ32(PVPE)
+{
+ DEVICE_READ32_SWITCH() {
+ default:
+ DEBUG_READ32_UNHANDLED(PVPE); // TODO : DEVICE_READ32_REG(pvpe);
+ break;
+ }
+
+ DEVICE_READ32_END(PVPE);
+}
+
+
+DEVICE_WRITE32(PVPE)
+{
+ switch (addr) {
+ default:
+ DEBUG_WRITE32_UNHANDLED(PVPE); // TODO : DEVICE_WRITE32_REG(pvpe);
+ break;
+ }
+
+ DEVICE_WRITE32_END(PVPE);
+}
+
diff --git a/src/devices/video/EmuNV2A_USER.cpp b/src/devices/video/EmuNV2A_USER.cpp
new file mode 100644
index 000000000..c3435866c
--- /dev/null
+++ b/src/devices/video/EmuNV2A_USER.cpp
@@ -0,0 +1,70 @@
+DEVICE_READ32(USER)
+{
+ unsigned int channel_id = addr >> 16;
+ assert(channel_id < NV2A_NUM_CHANNELS);
+
+ ChannelControl *control = &user.channel_control[channel_id];
+
+ uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
+
+ /* PIO Mode */
+ if (!channel_modes & (1 << channel_id)) {
+ assert(false);
+ }
+
+ /* DMA Mode */
+ addr &= 0xFFFF;
+ DEVICE_READ32_SWITCH() {
+ case NV_USER_DMA_PUT:
+ result = control->dma_put;
+ break;
+ case NV_USER_DMA_GET:
+ result = control->dma_get;
+ break;
+ case NV_USER_REF:
+ result = control->ref;
+ break;
+ default:
+ DEBUG_READ32_UNHANDLED(USER);
+ break;
+ }
+
+ DEVICE_READ32_END(USER);
+}
+
+DEVICE_WRITE32(USER)
+{
+ unsigned int channel_id = addr >> 16;
+ assert(channel_id < NV2A_NUM_CHANNELS);
+
+ ChannelControl *control = &user.channel_control[channel_id];
+
+ uint32_t channel_modes = pfifo.regs[NV_PFIFO_MODE];
+ if (channel_modes & (1 << channel_id)) {
+ /* DMA Mode */
+ switch (addr & 0xFFFF) {
+ case NV_USER_DMA_PUT:
+ control->dma_put = value;
+
+ if (pfifo.cache1.push_enabled) {
+ pfifo_run_pusher();
+ }
+ break;
+ case NV_USER_DMA_GET:
+ control->dma_get = value;
+ break;
+ case NV_USER_REF:
+ control->ref = value;
+ break;
+ default:
+ DEBUG_WRITE32_UNHANDLED(USER);
+ break;
+ }
+ }
+ else {
+ /* PIO Mode */
+ assert(false);
+ }
+
+ DEVICE_WRITE32_END(USER);
+}