From b816a7d3796d57de961ac21241df2853a1835b8f Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 1 Dec 2024 20:56:42 +0000 Subject: [PATCH] Initial VBLANK draft. Still fucked up --- doc/NV_PFB_CONFIG_0.txt | 29 ++++++++++ doc/nv3 driver init status.txt | 6 ++- src/include/86box/nv/vid_nv.h | 3 ++ src/include/86box/nv/vid_nv3.h | 67 +++++++++++++++++------- src/video/nv/nv3/nv3_core_arbiter.c | 2 + src/video/nv/nv3/subsystems/nv3_pfb.c | 48 +++++++++++++++-- src/video/nv/nv3/subsystems/nv3_pgraph.c | 33 +++++++++--- src/video/nv/nv3/subsystems/nv3_pmc.c | 20 +++++-- 8 files changed, 171 insertions(+), 37 deletions(-) create mode 100644 doc/NV_PFB_CONFIG_0.txt diff --git a/doc/NV_PFB_CONFIG_0.txt b/doc/NV_PFB_CONFIG_0.txt new file mode 100644 index 000000000..dee3b646c --- /dev/null +++ b/doc/NV_PFB_CONFIG_0.txt @@ -0,0 +1,29 @@ +NV_PFB_CONFIG_0 + +Observed Valus: +Drivers 0x1000 +BIOS 0x1114 + +Bits +5:0 Resolution +9:8 Pixel depth +12:12 Tiling +13:13 Tiling Debug +14:14 Tiling Debug Tile Size +17:15 "Tetris" tiling +19:18 "Tetris" tiling shift +22:20 Bank Swap +23 Unused + +NV_PFB_CONFIG_1 +2:0 CAS Latency +3:3 NEC Mode (PC-98?) +7:4 RAS Default / 9 Cycles +10:8 RAS PCHG +14:12 RAS Low +18:16 MRS to RAS +22:20 Write to Read +26:24 RAS to CAS +30:28 Read to Write +31:31 Read to PCFg + diff --git a/doc/nv3 driver init status.txt b/doc/nv3 driver init status.txt index b6f470f92..6ac794588 100644 --- a/doc/nv3 driver init status.txt +++ b/doc/nv3 driver init status.txt @@ -98,8 +98,10 @@ rmInitRm -> initGrPatchPool Success rmInitRm -> initDmaListElementPool Success rmInitRm -> initDisplayInfo Success rmInitRm overall Success -NvFindAdapter Failing (EAX=87) +NvFindAdapter Success 17:32 27/11/2024 NvFindAdapter -> NvIsPresent Success 16:19 24/11/2024 NvFindAdapter -> NvMapMemoryRanges Success 19:15 26/11/2024 NvFindAdapter -> RmInitNvMapping Success 19:18 26/11/2024 -NvFindAdapter -> RmPostNvDevice +NvFindAdapter -> RmPostNvDevice Success 17:32 27/11/2024 +NvFindAdapter -> NVGetNVInfo Success 17:32 27/11/2024 +NvFindAdapter -> NVMapFrameBuffer Success 17:32 27/11/2024 diff --git a/src/include/86box/nv/vid_nv.h b/src/include/86box/nv/vid_nv.h index ca0922a44..cabd9f46b 100644 --- a/src/include/86box/nv/vid_nv.h +++ b/src/include/86box/nv/vid_nv.h @@ -158,6 +158,8 @@ typedef struct nv3_straps_s typedef struct nv3_pfb_s { uint32_t boot; + uint32_t config_0; + uint32_t config_1; } nv3_pfb_t; #define NV3_RMA_NUM_REGS 4 @@ -460,6 +462,7 @@ uint32_t nv3_pmc_handle_interrupts(bool send_now); // NV3 PGRAPH void nv3_pgraph_init(); +void nv3_pgraph_vblank_start(svga_t* svga); // NV3 PFIFO void nv3_pfifo_init(); diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index a9a4884d9..bd8d373b7 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -34,6 +34,8 @@ extern nv3_t* nv3; #define NV3_VBIOS_DIAMOND_V330_V162 "roms/video/nvidia/nv3/diamond_v330_rev-e.vbi" // Diamond Multimedia Systems, Inc. Viper V330 Version 1.62-CO #define NV3_VBIOS_ASUS_V3000_V151 "roms/video/nvidia/nv3/riva128_asus.vbi" // ASUS AGP/3DP-V3000 BIOS 1.51B #define NV3_VBIOS_STB_V128_V182 "roms/video/nvidia/nv3/riva128_stb.vbi" // STB Velocity 128 (RIVA 128) Ver.1.82 +#define NV3T_VBIOS_REFERENCE_CEK_V171 "roms/video/nvidia/nv3/BIOS_49_Riva 128" // Reference BIOS: RIVA 128 ZX BIOS - V1.71B-N (C) 1996-98 NVidia Corporation +#define NV3T_VBIOS_DIAMOND_V330_V182B "roms/video/nvidia/nv3/nv3t182b.rom" // Diamond Multimedia Viper V330 8M BIOS - Version 1.82B // Temporary, will be loaded from settings #define VRAM_SIZE_2MB 0x200000 // 2MB @@ -113,6 +115,7 @@ extern nv3_t* nv3; #define NV3_PMC_START 0x0 // Chip Master Control Subsystem #define NV3_PMC_BOOT 0x0 // Boot Configuration + #define NV3_PMC_INTERRUPT_STATUS 0x100 // Interrupt Control #define NV3_PMC_INTERRUPT_PAUDIO 0 // Unused, NV3A only #define NV3_PMC_INTERRUPT_PAUDIO_PENDING 0x1 // Unused, NV3A only @@ -138,6 +141,23 @@ extern nv3_t* nv3; #define NV3_PMC_INTERRUPT_ENABLE_HARDWARE 0x1 // Determines if hardware interrupts are enabled #define NV3_PMC_INTERRUPT_ENABLE_SOFTWARE 0x2 // Determinse if software interrupts were enabled #define NV3_PMC_ENABLE 0x200 // Determines which gpu subsystems were enabled +#define NV3_PMC_ENABLE_PAUDIO 0 // UNUSED - PAudio removed in NV3 Stepping B0 +#define NV3_PMC_ENABLE_PAUDIO_ENABLED 0x1 // UNUSED - PAudio removed in NV3 Stepping B0 +#define NV3_PMC_ENABLE_PMEDIA 4 +#define NV3_PMC_ENABLE_PMEDIA_ENABLED 0x1 +#define NV3_PMC_ENABLE_PFIFO 8 +#define NV3_PMC_ENABLE_PFIFO_ENABLED 0x1 +#define NV3_PMC_ENABLE_PGRAPH 12 // Determines if PGRAPH is enabled. +#define NV3_PMC_ENABLE_PGRAPH_ENABLED 0x1 +#define NV3_PMC_ENABLE_PPMI 16 +#define NV3_PMC_ENABLE_PPMI_ENABLED 0x1 +#define NV3_PMC_ENABLE_PFB 20 +#define NV3_PMC_ENABLE_PFB_ENABLED 0x1 +#define NV3_PMC_ENABLE_PCRTC 24 +#define NV3_PMC_ENABLE_PCRTC_ENABLED 0x1 +#define NV3_PMC_ENABLE_PVIDEO 28 +#define NV3_PMC_ENABLE_PVIDEO_ENABLED 0x1 + #define NV3_PMC_END 0xfff // overlaps with CIO #define NV3_CIO_START 0x3b0 // Legacy SVGA Emulation Subsystem @@ -189,6 +209,32 @@ extern nv3_t* nv3; #define NV3_PFB_BOOT_RAM_EXTENSION 5 #define NV3_PFB_BOOT_RAM_EXTENSION_NONE 0x0 #define NV3_PFB_BOOT_RAM_EXTENSION_8MB 0x1 +#define NV3_PFB_CONFIG_0 0x100200 // Framebuffer interface config register 0 +#define NV3_PFB_CONFIG_0_RESOLUTION 0 +// 1=40 horiz. resolution +// i assume it can be divided by some kind of divisor to produce the vertical resolution (e.g. 3/2 or multiply by 2/3) to get the final +// horiz is 32*value +// theoretically it should support resolutions from 40-2560 horiz + +// WHAT ARE THE TIMINGS: ARE THEY IN THE VBIOS? +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_320 0xA +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_400 0xD +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_480 0xF +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_512 0x10 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_640 0x14 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_800 0x19 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_960 0x1E +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_1024 0x20 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_1152 0x24 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_1280 0x28 +#define NV3_PFB_CONFIG_0_HORIZ_RESOLUTION_1600 0x32 + +#define NV3_PFB_CONFIG_0_PIXEL_DEPTH 8 +#define NV3_PFB_CONFIG_0_DEPTH_8BPP 0x1 +#define NV3_PFB_CONFIG_0_DEPTH_16BPP 0x2 +#define NV3_PFB_CONFIG_0_DEPTH_32BPP 0x3 + +#define NV3_PFB_CONFIG_1 0x100204 // Framebuffer interface config register 1 #define NV3_PFB_END 0x100FFF #define NV3_PEXTDEV_START 0x101000 // External Devices #define NV3_PSTRAPS 0x101000 // Straps Bits @@ -238,6 +284,7 @@ extern nv3_t* nv3; #define NV3_PGRAPH_INTR_0 0x400100 #define NV3_PGRAPH_INTR_1 0x400104 #define NV3_PGRAPH_INTR_EN_0 0x400140 // Interrupt Control for PGRAPH #1 +#define NV3_PGRAPH_INTR_EN_0_VBLANK 8 // Fired every frame //todo: add what this does #define NV3_PGRAPH_INTR_EN_1 0x400180 // Interrupt Control for PGRAPH #2 (it can receive two at onc) @@ -384,26 +431,6 @@ extern nv3_t* nv3; // Master Control -#define NV3_PMC_BOOT 0x0 -#define NV3_PMC_INTERRUPT 0x100 -#define NV3_PMC_INTERRUPT_ENABLE 0x140 -#define NV3_PMC_ENABLE 0x200 -#define NV3_PMC_ENABLE_PAUDIO 0 // UNUSED - PAudio removed in NV3 Stepping B0 -#define NV3_PMC_ENABLE_PAUDIO_ENABLED 0x1 // UNUSED - PAudio removed in NV3 Stepping B0 -#define NV3_PMC_ENABLE_PMEDIA 4 -#define NV3_PMC_ENABLE_PMEDIA_ENABLED 0x1 -#define NV3_PMC_ENABLE_PFIFO 8 -#define NV3_PMC_ENABLE_PFIFO_ENABLED 0x1 -#define NV3_PMC_ENABLE_PGRAPH 12 -#define NV3_PMC_ENABLE_PGRAPH_ENABLED 0x1 -#define NV3_PMC_ENABLE_PPMI 16 -#define NV3_PMC_ENABLE_PPMI_ENABLED 0x1 -#define NV3_PMC_ENABLE_PFB 20 -#define NV3_PMC_ENABLE_PFB_ENABLED 0x1 -#define NV3_PMC_ENABLE_PCRTC 24 -#define NV3_PMC_ENABLE_PCRTC_ENABLED 0x1 -#define NV3_PMC_ENABLE_PVIDEO 28 -#define NV3_PMC_ENABLE_PVIDEO_ENABLED 0x1 // CRTC/CIO (0x3b0-0x3df) diff --git a/src/video/nv/nv3/nv3_core_arbiter.c b/src/video/nv/nv3/nv3_core_arbiter.c index 0b307e84a..1ef1c0e36 100644 --- a/src/video/nv/nv3/nv3_core_arbiter.c +++ b/src/video/nv/nv3/nv3_core_arbiter.c @@ -67,6 +67,8 @@ uint32_t nv3_mmio_arbitrate_read(uint32_t address) ret = nv3_pci_read(0x00, address & 0xFF, NULL); else if (address >= NV3_PBUS_START && address <= NV3_PBUS_END) ret = nv3_pbus_read(address); + else if (address >= NV3_PFIFO_START && address <= NV3_PFIFO_END) + ret = nv3_pfifo_read(address); else if (address >= NV3_PFB_START && address <= NV3_PFB_END) ret = nv3_pfb_read(address); else if (address >= NV3_PRM_START && address <= NV3_PRM_END) diff --git a/src/video/nv/nv3/subsystems/nv3_pfb.c b/src/video/nv/nv3/subsystems/nv3_pfb.c index d644185a2..e1d1c8352 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfb.c +++ b/src/video/nv/nv3/subsystems/nv3_pfb.c @@ -28,8 +28,14 @@ #include <86Box/nv/vid_nv.h> #include <86Box/nv/vid_nv3.h> +// Functions only used in this translation unit +uint32_t nv3_pfb_config0_read(); +void nv3_pfb_config0_write(uint32_t val); + nv_register_t pfb_registers[] = { { NV3_PFB_BOOT, "PFB Boot Config", NULL, NULL}, + { NV3_PFB_CONFIG_0, "PFB Framebuffer Config 0", nv3_pfb_config0_read, nv3_pfb_config0_write }, + { NV3_PFB_CONFIG_1, "PFB Framebuffer Config 1", NULL, NULL }, { NV_REG_LIST_END, NULL, NULL, NULL}, // sentinel value }; @@ -78,7 +84,8 @@ uint32_t nv3_pfb_read(uint32_t address) { case NV3_PFB_BOOT: return nv3->pfb.boot; - break; + case NV3_PFB_CONFIG_1: + return nv3->pfb.config_1; } } } @@ -90,7 +97,7 @@ void nv3_pfb_write(uint32_t address, uint32_t value) { nv_register_t* reg = nv_get_register(address, pfb_registers, sizeof(pfb_registers)/sizeof(pfb_registers[0])); - nv_log("NV3: PFB Write 0x%08x -> 0x%08x\n", value, address); + nv_log("NV3: PFB Write 0x%08x -> 0x%08x", value, address); // if the register actually exists if (reg) @@ -103,7 +110,40 @@ void nv3_pfb_write(uint32_t address, uint32_t value) // on-read function if (reg->on_write) reg->on_write(value); - + else + { + switch (reg->address) + { + case NV3_PFB_CONFIG_1: // Config Register 1 + nv3->pfb.config_1 = value; + } + } } - +} + +uint32_t nv3_pfb_config0_read() +{ + return nv3->pfb.config_0; + +} + +void nv3_pfb_config0_write(uint32_t val) +{ + nv3->pfb.config_0 = val; + + // i think the actual size and pixel depth are set in PRAMDAC + // so we don't update things here for now + + uint32_t new_pfb_htotal = (nv3->pfb.config_0 & 0x3F) << 5; + uint32_t new_bit_depth = (nv3->pfb.config_0 >> 8) & 0x03; + nv_log("NV3: Framebuffer Config Change\n"); + nv_log("NV3: Horizontal Size=%d pixels\n", new_pfb_htotal); + + if (new_bit_depth == NV3_PFB_CONFIG_0_DEPTH_8BPP) + nv_log("NV3: Bit Depth=8bpp\n"); + else if (new_bit_depth == NV3_PFB_CONFIG_0_DEPTH_16BPP) + nv_log("NV3: Bit Depth=16bpp\n"); + else if (new_bit_depth == NV3_PFB_CONFIG_0_DEPTH_32BPP) + nv_log("NV3: Bit Depth=32bpp\n"); + } \ No newline at end of file diff --git a/src/video/nv/nv3/subsystems/nv3_pgraph.c b/src/video/nv/nv3/subsystems/nv3_pgraph.c index d37ccdf9f..ac2970e35 100644 --- a/src/video/nv/nv3/subsystems/nv3_pgraph.c +++ b/src/video/nv/nv3/subsystems/nv3_pgraph.c @@ -28,19 +28,20 @@ #include <86Box/nv/vid_nv.h> #include <86Box/nv/vid_nv3.h> -// Single unified write function... + +// Initialise the PGRAPH subsystem. +void nv3_pgraph_init() +{ + nv_log("NV3: Initialising PGRAPH..."); + // Set up the vblank interrupt + nv3->nvbase.svga.vblank_start = nv3_pgraph_vblank_start; + nv_log("Done!\n"); +} // // ****** PGRAPH register list START ****** // -void nv3_pgraph_init() -{ - nv_log("NV3: Initialising PGRAPH..."); - - nv_log("Done!\n"); -} - nv_register_t pgraph_registers[] = { { NV3_PGRAPH_INTR_0, "PGRAPH Interrupt Status 0", NULL, NULL }, { NV3_PGRAPH_INTR_EN_0, "PGRAPH Interrupt Enable 0", NULL, NULL }, @@ -141,11 +142,27 @@ void nv3_pgraph_write(uint32_t address, uint32_t value) // and only bit0-16 is defined in intr_1 case NV3_PGRAPH_INTR_EN_0: nv3->pgraph.interrupt_enable_0 = value & 0x11111111; + nv3_pmc_handle_interrupts(true); break; case NV3_PGRAPH_INTR_EN_1: nv3->pgraph.interrupt_enable_1 = value & 0x00011111; + nv3_pmc_handle_interrupts(true); + break; } } } +} + +// Fire a VALID Pgraph interrupt: num is the bit# of the interrupt in the GPU subsystem INTR_EN register. +void nv3_pgraph_interrupt_valid(uint32_t num) +{ + nv3->pgraph.interrupt_enable_0 |= (1 << num); + nv3_pmc_handle_interrupts(true); +} + +// VBlank. Fired every single frame. +void nv3_pgraph_vblank_start(svga_t* svga) +{ + nv3_pgraph_interrupt_valid(NV3_PGRAPH_INTR_EN_0_VBLANK); } \ No newline at end of file diff --git a/src/video/nv/nv3/subsystems/nv3_pmc.c b/src/video/nv/nv3/subsystems/nv3_pmc.c index 10717f7bc..63b37f11c 100644 --- a/src/video/nv/nv3/subsystems/nv3_pmc.c +++ b/src/video/nv/nv3/subsystems/nv3_pmc.c @@ -35,6 +35,7 @@ void nv3_pmc_init() nv_log("NV3: Initialising PMC....\n"); nv3->pmc.boot = NV3_BOOT_REG_DEFAULT; + nv3->pmc.interrupt_enable = NV3_PMC_INTERRUPT_ENABLE_HARDWARE | NV3_PMC_INTERRUPT_ENABLE_HARDWARE; nv_log("NV3: Initialising PMC: Done\n"); } @@ -113,11 +114,23 @@ uint32_t nv3_pmc_handle_interrupts(bool send_now) // If interrupts are disabled don't bother if (!nv3->pmc.interrupt_enable) + { nv3_pmc_clear_interrupts(); + return nv3->pmc.interrupt_status; + } + // if we actually need to send the interrupt (i.e. this is a write) send it now if (send_now) { + // no interrupts to send + if (!(nv3->pmc.interrupt_status) + || !(nv3->pmc.interrupt_status - 0x80000000)) + { + nv3_pmc_clear_interrupts(); + return nv3->pmc.interrupt_status; + } + if (!(nv3->pmc.interrupt_status & 0x7FFFFFFF)) { if (nv3->pmc.interrupt_enable & NV3_PMC_INTERRUPT_ENABLE_HARDWARE) @@ -213,8 +226,8 @@ void nv3_pmc_write(uint32_t address, uint32_t value) switch (reg->address) { case NV3_PMC_INTERRUPT_STATUS: - // this - if (!(nv3->pmc.interrupt_status & (NV3_PMC_INTERRUPT_SOFTWARE - 1))) + // This can only be done by software interrupts... + if (!(nv3->pmc.interrupt_status & 0x7FFFFFFF)) { nv_log("Huh? This is a hardware interrupt...Please use the INTR_EN registers of the GPU subsystem you want to trigger " " an interrupt on, rather than writing to NV3_PMC_INTERRUPT_STATUS (Or this is a bug)...NV3_PMC_INTERRUPT_STATUS=0x%08x)\n", nv3->pmc.interrupt_enable); @@ -225,7 +238,8 @@ void nv3_pmc_write(uint32_t address, uint32_t value) nv3->pmc.interrupt_status = value; break; case NV3_PMC_INTERRUPT_ENABLE: - nv3->pmc.interrupt_enable = value; + nv3->pmc.interrupt_enable = value & 0x03; + nv3_pmc_handle_interrupts(value != 0); break; case NV3_PMC_ENABLE: nv3->pmc.enable = value;