mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
RIVA TNT Video BIOS now runs.
This commit is contained in:
@@ -505,6 +505,7 @@
|
||||
#define NV4_PBUS_PCI_DEVICE_ID 0x1802
|
||||
#define NV4_PBUS_PCI_DEVICE_ID_NV4 0x0020 // Chip (19:17)= NV4, Func = VGA
|
||||
#define NV4_PBUS_PCI_COMMAND 0x1804
|
||||
#define NV4_PBUS_PCI_COMMAND_H 0x1805
|
||||
#define NV4_PBUS_PCI_COMMAND_IO_SPACE 0
|
||||
#define NV4_PBUS_PCI_COMMAND_IO_SPACE_ENABLED 0x1
|
||||
#define NV4_PBUS_PCI_COMMAND_MEMORY_SPACE 1
|
||||
@@ -568,9 +569,12 @@
|
||||
#define NV4_PBUS_PCI_BAR0_UNUSED2 0x1812
|
||||
#define NV4_PBUS_PCI_BAR0_BASE_31_TO_24 0x1813 // Must align to 16MByte
|
||||
#define NV4_PBUS_PCI_BAR1_INFO 0x1814
|
||||
#define NV4_PBUS_PCI_BAR1_UNUSED1 0x1814
|
||||
#define NV4_PBUS_PCI_BAR1_UNUSED2 0x1815
|
||||
#define NV4_PBUS_PCI_BAR1_BASE_31_TO_24 0x1816 // Must align to 16MByte
|
||||
#define NV4_PBUS_PCI_BAR1_UNUSED1 0x1815
|
||||
#define NV4_PBUS_PCI_BAR1_UNUSED2 0x1816
|
||||
#define NV4_PBUS_PCI_BAR1_BASE_31_TO_24 0x1817 // Must align to 16MByte
|
||||
#define NV4_PBUS_PCI_BAR_RESERVED_START 0x1818
|
||||
#define NV4_PBUS_PCI_BAR_RESERVED_END 0x182B
|
||||
|
||||
//BAR2-5 reserved
|
||||
#define NV4_PBUS_PCI_SUBSYSTEM_VENDOR_ID 0x182C
|
||||
#define NV4_PBUS_PCI_SUBSYSTEM_ID 0x182E
|
||||
|
||||
@@ -137,7 +137,6 @@ uint32_t nv3_mmio_read32(uint32_t addr, void* priv)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nv3_mmio_arbitrate_read(addr);
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ void nv4_init_mappings_svga(void)
|
||||
{
|
||||
nv_log("Initialising SVGA core memory mapping\n");
|
||||
// setup the svga mappings
|
||||
|
||||
mem_mapping_add(&nv4->nvbase.framebuffer_mapping, 0, 0,
|
||||
nv4_dfb_read8,
|
||||
nv4_dfb_read16,
|
||||
@@ -198,14 +199,18 @@ bool nv4_init()
|
||||
/* Set log device name based on card model */
|
||||
const char* log_device_name = "NV4";
|
||||
|
||||
|
||||
/* Just hardcode full logging */
|
||||
|
||||
if (device_get_config_int("nv_debug_fulllog"))
|
||||
nv4->nvbase.log = log_open("NV4");
|
||||
nv4->nvbase.log = log_open(log_device_name);
|
||||
else
|
||||
nv4->nvbase.log = log_open_cyclic("NV4");
|
||||
nv4->nvbase.log = log_open_cyclic(log_device_name);
|
||||
|
||||
nv_log_set_device(nv4->nvbase.log);
|
||||
|
||||
nv4->nvbase.bus_generation = nv_bus_agp_2x;
|
||||
|
||||
nv_log_set_device(nv4->nvbase.log);
|
||||
// Figure out which vbios the user selected
|
||||
// This depends on the bus we are using and if the gpu is rev a/b or rev c
|
||||
|
||||
@@ -260,11 +265,82 @@ void nv4_draw_cursor(svga_t* svga, int32_t drawline)
|
||||
|
||||
}
|
||||
|
||||
void nv4_recalc_timings(svga_t* svga)
|
||||
{
|
||||
|
||||
//
|
||||
// SVGA functions
|
||||
//
|
||||
void nv4_recalc_timings(svga_t* svga)
|
||||
{
|
||||
// sanity check
|
||||
if (!nv4)
|
||||
return;
|
||||
|
||||
|
||||
nv4_t* nv4 = (nv4_t*)svga->priv;
|
||||
|
||||
// TODO: Everything, this code sucks, incl. NV4_PRAMDAC_GENERAL_CONTROL_BPC and the OFFSET register
|
||||
uint32_t pixel_mode = svga->crtc[NV4_CIO_CRE_PIXEL_INDEX] & 0x03;
|
||||
|
||||
svga->memaddr_latch += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0x1F) << 16;
|
||||
|
||||
/* Turn off override if we are in VGA mode */
|
||||
svga->override = !(pixel_mode == NV4_CIO_CRE_PIXEL_FORMAT_VGA);
|
||||
|
||||
/* NOTE: The RIVA 128 draws in a way almost completely separate to any other 86Box GPU.
|
||||
|
||||
Basically, we only blit to buffer32 when something changes and we don't even bother using a timer. We only render when there is something to actually render.
|
||||
|
||||
This is because there is no linear relationship between the contents of VRAM and the contents of the display which 86box's SVGA subsystem cannot tolerate.
|
||||
In fact, the position in VRAM and pitch can be changed at any time via an NV_IMAGE_IN_MEMORY object.
|
||||
|
||||
Therefore, we need to completely bypass it using svga->override and draw our own rendering functions. This allows us to use a neat optimisation trick
|
||||
to only ever actually draw when we need to do something. This shouldn't be a problem in games, because the drivers will read the current refresh rate from
|
||||
the Windows settings, and then, just submit objects at that pace for anything that changes on the screen.
|
||||
*/
|
||||
|
||||
// Set the pixel mode
|
||||
switch (pixel_mode)
|
||||
{
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_8BPP:
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 1; // ?????
|
||||
svga->bpp = 8;
|
||||
svga->lowres = 0;
|
||||
svga->map8 = svga->pallook;
|
||||
break;
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_16BPP:
|
||||
/* This is some sketchy shit that is an attempt at an educated guess
|
||||
at pixel clock differences between 9x and NT only in 16bpp. If there is ever an error on 9x with "interlaced" looking graphics,
|
||||
this is what's causing it. Possibly fucking up the drivers under *ReactOS* of all things */
|
||||
if ((svga->crtc[NV4_CIO_CR_VRS_INDEX] >> 1) & 0x01)
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 2;
|
||||
else
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 3;
|
||||
|
||||
// 15bpp mode is removed on NV4
|
||||
// TODO: Not svga
|
||||
svga->bpp = 16;
|
||||
svga->lowres = 0;
|
||||
|
||||
break;
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_32BPP:
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 3;
|
||||
|
||||
svga->bpp = 32;
|
||||
svga->lowres = 0;
|
||||
//svga->render = nv4_render_32bpp;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (((svga->miscout >> 2) & 2) == 2)
|
||||
{
|
||||
// set clocks
|
||||
//nv4_pramdac_set_pixel_clock();
|
||||
//nv4_pramdac_set_vram_clock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nv4_force_redraw(void* priv)
|
||||
{
|
||||
|
||||
@@ -281,7 +357,7 @@ int32_t nv4_available(void)
|
||||
// 8MB or 16MB VRAM
|
||||
const device_t nv4_device_agp =
|
||||
{
|
||||
.name = "nVIDIA RIVA TNT [STB Velocity 4400]",
|
||||
.name = "nVIDIA RIVA TNT (STB Velocity 4400)",
|
||||
.internal_name = "nv4_stb4400",
|
||||
.flags = DEVICE_AGP,
|
||||
.local = 0,
|
||||
|
||||
@@ -438,7 +438,7 @@ uint8_t nv4_pci_read(int32_t func, int32_t addr, void* priv)
|
||||
|
||||
// We only need to return 0x30 since the VGA class code is 0x30000
|
||||
case NV4_PBUS_PCI_CLASS_CODE:
|
||||
ret = (NV4_PBUS_PCI_CLASS_CODE_VGA) >> 12; // CLASS_CODE_VGA
|
||||
ret = (NV4_PBUS_PCI_CLASS_CODE_VGA) >> 16; // CLASS_CODE_VGA
|
||||
break;
|
||||
|
||||
|
||||
@@ -462,6 +462,15 @@ uint8_t nv4_pci_read(int32_t func, int32_t addr, void* priv)
|
||||
case NV4_PBUS_PCI_BAR1_BASE_31_TO_24:
|
||||
ret = nv4->nvbase.bar1_lfb_base >> 24; //8bit value
|
||||
break;
|
||||
|
||||
case NV4_PBUS_PCI_BAR_RESERVED_START ... NV4_PBUS_PCI_BAR_RESERVED_END:
|
||||
case NV4_PBUS_PCI_BAR0_UNUSED1:
|
||||
case NV4_PBUS_PCI_BAR0_UNUSED2:
|
||||
case NV4_PBUS_PCI_BAR1_UNUSED1:
|
||||
case NV4_PBUS_PCI_BAR1_UNUSED2:
|
||||
|
||||
ret = 0x00; // hard lock
|
||||
break;
|
||||
|
||||
case NV4_PBUS_PCI_ROM:
|
||||
ret = nv4->nvbase.pci_config.vbios_enabled;
|
||||
@@ -504,6 +513,7 @@ uint8_t nv4_pci_read(int32_t func, int32_t addr, void* priv)
|
||||
case NV4_PBUS_PCI_SUBSYSTEM_ID_WRITABLE + 1:
|
||||
ret = nv4->nvbase.pci_config.pci_regs[NV4_PBUS_PCI_SUBSYSTEM_ID + (addr & 0x03)];
|
||||
break;
|
||||
|
||||
case NV4_PBUS_AGP_CAPABILITIES:
|
||||
ret = NV4_PBUS_AGP_CAPABILITY_AGP; // AGP capable device
|
||||
break;
|
||||
@@ -529,7 +539,7 @@ uint8_t nv4_pci_read(int32_t func, int32_t addr, void* priv)
|
||||
|
||||
}
|
||||
|
||||
nv_log("nv4_pci_read func=0x%04x addr=0x%04x ret=0x%04x\n", func, addr, ret);
|
||||
nv_log("nv4_pci_read func=0x%04x addr=0x%04x ret=0x%04x\n", func, addr & 0xFF, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -550,28 +560,28 @@ void nv4_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
|
||||
&& addr == NV4_PBUS_PCI_BAR1_UNUSED1 || addr == NV4_PBUS_PCI_BAR1_UNUSED2)
|
||||
return;
|
||||
|
||||
nv_log("nv4_pci_write func=0x%04x addr=0x%04x val=0x%04x\n", func, addr, val);
|
||||
nv_log("nv4_pci_write func=0x%04x addr=0x%04x val=0x%04x\n", func, addr & 0xFF, val);
|
||||
|
||||
nv4->nvbase.pci_config.pci_regs[addr] = val;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
// standard pci command stuff
|
||||
case PCI_REG_COMMAND_L:
|
||||
case NV4_PBUS_PCI_COMMAND:
|
||||
nv4->nvbase.pci_config.pci_regs[PCI_REG_COMMAND_L] = val;
|
||||
// actually update the mappings
|
||||
nv4_update_mappings();
|
||||
break;
|
||||
case PCI_REG_COMMAND_H:
|
||||
case NV4_PBUS_PCI_COMMAND_H:
|
||||
nv4->nvbase.pci_config.pci_regs[PCI_REG_COMMAND_H] = val;
|
||||
// actually update the mappings
|
||||
nv4_update_mappings();
|
||||
break;
|
||||
// pci status register
|
||||
case PCI_REG_STATUS_L:
|
||||
case NV4_PBUS_PCI_STATUS:
|
||||
nv4->nvbase.pci_config.pci_regs[PCI_REG_STATUS_L] = val | (NV4_PBUS_PCI_STATUS_66MHZ_CAPABLE << NV4_PBUS_PCI_STATUS_66MHZ);
|
||||
break;
|
||||
case PCI_REG_STATUS_H:
|
||||
case NV4_PBUS_PCI_STATUS_2:
|
||||
nv4->nvbase.pci_config.pci_regs[PCI_REG_STATUS_H] = val | (NV4_PBUS_PCI_STATUS_2_DEVSEL_TIMING_FAST << NV4_PBUS_PCI_STATUS_2_DEVSEL_TIMING);
|
||||
break;
|
||||
//TODO: ACTUALLY REMAP THE MMIO AND NV_USER
|
||||
@@ -583,6 +593,7 @@ void nv4_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
|
||||
nv4->nvbase.bar1_lfb_base = val << 24;
|
||||
nv4_update_mappings();
|
||||
break;
|
||||
|
||||
case NV4_PBUS_PCI_ROM:
|
||||
case NV4_PBUS_PCI_ROM_BASE:
|
||||
|
||||
@@ -601,13 +612,16 @@ void nv4_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
|
||||
{
|
||||
uint32_t old_addr = nv4->nvbase.vbios.mapping.base;
|
||||
// 9bit register
|
||||
uint32_t new_addr = nv4->nvbase.pci_config.pci_regs[NV4_PBUS_PCI_ROM + 1] << 24 |
|
||||
nv4->nvbase.pci_config.pci_regs[NV4_PBUS_PCI_ROM] << 16;
|
||||
uint32_t new_addr = nv4->nvbase.pci_config.pci_regs[NV4_PBUS_PCI_ROM + 3] << 24 |
|
||||
nv4->nvbase.pci_config.pci_regs[NV4_PBUS_PCI_ROM + 2] << 16;
|
||||
|
||||
// only bits 31;22 matter
|
||||
//new_addr &= 0xFFC00000;
|
||||
|
||||
// move it
|
||||
mem_mapping_set_addr(&nv4->nvbase.vbios.mapping, new_addr, 0x8000);
|
||||
|
||||
nv_log("...i like to move it move it (VBIOS Relocation) 0x%04x -> 0x%04x\n", old_addr, new_addr);
|
||||
nv_log("...i like to move it move it (VBIOS Relocation) 0x%x -> 0x%x\n", old_addr, new_addr);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -643,80 +657,6 @@ void nv4_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SVGA functions
|
||||
//
|
||||
void nv4_recalc_timings(svga_t* svga)
|
||||
{
|
||||
// sanity check
|
||||
if (!nv4)
|
||||
return;
|
||||
|
||||
|
||||
nv4_t* nv4 = (nv4_t*)svga->priv;
|
||||
|
||||
// TODO: Everything, this code sucks, incl. NV4_PRAMDAC_GENERAL_CONTROL_BPC and the OFFSET register
|
||||
uint32_t pixel_mode = svga->crtc[NV4_CIO_CRE_PIXEL_INDEX] & 0x03;
|
||||
|
||||
svga->memaddr_latch += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0x1F) << 16;
|
||||
|
||||
/* Turn off override if we are in VGA mode */
|
||||
svga->override = !(pixel_mode == NV4_CIO_CRE_PIXEL_FORMAT_VGA);
|
||||
|
||||
/* NOTE: The RIVA 128 draws in a way almost completely separate to any other 86Box GPU.
|
||||
|
||||
Basically, we only blit to buffer32 when something changes and we don't even bother using a timer. We only render when there is something to actually render.
|
||||
|
||||
This is because there is no linear relationship between the contents of VRAM and the contents of the display which 86box's SVGA subsystem cannot tolerate.
|
||||
In fact, the position in VRAM and pitch can be changed at any time via an NV_IMAGE_IN_MEMORY object.
|
||||
|
||||
Therefore, we need to completely bypass it using svga->override and draw our own rendering functions. This allows us to use a neat optimisation trick
|
||||
to only ever actually draw when we need to do something. This shouldn't be a problem in games, because the drivers will read the current refresh rate from
|
||||
the Windows settings, and then, just submit objects at that pace for anything that changes on the screen.
|
||||
*/
|
||||
|
||||
// Set the pixel mode
|
||||
switch (pixel_mode)
|
||||
{
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_8BPP:
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 1; // ?????
|
||||
svga->bpp = 8;
|
||||
svga->lowres = 0;
|
||||
svga->map8 = svga->pallook;
|
||||
break;
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_16BPP:
|
||||
/* This is some sketchy shit that is an attempt at an educated guess
|
||||
at pixel clock differences between 9x and NT only in 16bpp. If there is ever an error on 9x with "interlaced" looking graphics,
|
||||
this is what's causing it. Possibly fucking up the drivers under *ReactOS* of all things */
|
||||
if ((svga->crtc[NV4_CIO_CR_VRS_INDEX] >> 1) & 0x01)
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 2;
|
||||
else
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 3;
|
||||
|
||||
// 15bpp mode is removed on NV4
|
||||
// TODO: Not svga
|
||||
svga->bpp = 16;
|
||||
svga->lowres = 0;
|
||||
|
||||
break;
|
||||
case NV4_CIO_CRE_PIXEL_FORMAT_32BPP:
|
||||
svga->rowoffset += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0xE0) << 3;
|
||||
|
||||
svga->bpp = 32;
|
||||
svga->lowres = 0;
|
||||
//svga->render = nv4_render_32bpp;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (((svga->miscout >> 2) & 2) == 2)
|
||||
{
|
||||
// set clocks
|
||||
//nv4_pramdac_set_pixel_clock();
|
||||
//nv4_pramdac_set_vram_clock();
|
||||
}
|
||||
}
|
||||
|
||||
void nv4_speed_changed(void* priv)
|
||||
{
|
||||
// sanity check
|
||||
@@ -888,9 +828,6 @@ uint8_t nv4_svga_read(uint16_t addr, void* priv)
|
||||
{
|
||||
// CR = CRTC Controller
|
||||
// CRE = CRTC Controller Extended (weitek)
|
||||
|
||||
nv4_t* nv4 = (nv4_t*)priv;
|
||||
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
// sanity check
|
||||
@@ -947,6 +884,8 @@ uint8_t nv4_svga_read(uint16_t addr, void* priv)
|
||||
break;
|
||||
}
|
||||
|
||||
nv_log("SVGA read 0x%04x value 0x%02x\n", addr, ret);
|
||||
|
||||
return ret; //TEMP
|
||||
}
|
||||
|
||||
@@ -1090,6 +1029,7 @@ void nv4_svga_write(uint16_t addr, uint8_t val, void* priv)
|
||||
break;
|
||||
}
|
||||
|
||||
nv_log("SVGA write 0x%04x value 0x%02x\n", addr, val);
|
||||
}
|
||||
|
||||
/* DFB, sets up a dumb framebuffer */
|
||||
|
||||
Reference in New Issue
Block a user