mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
various logging/pfifo fixes, add pfifo ctx
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
Object classes
|
||||
|
||||
NOT represented by the GPU. These are the ones the drivers recognise. Most of them are faked.
|
||||
|
||||
Version 0.77_win95 (!!!)
|
||||
|
||||
object class 1 = "general" methods shared across all objects
|
||||
object class 2 = DMA from memory
|
||||
object class 3 = DMA to memory
|
||||
object class 4 = timer
|
||||
object class 5 = chip ID
|
||||
object class 6 = "context ordinal"
|
||||
object class 10/0Ah = patchcord (links objects together)
|
||||
object class 11/0Bh = video sink
|
||||
object class 12/0Ch = video switch
|
||||
object class 13/0Dh = video colormap
|
||||
object class 14/0Eh = patchcord...again
|
||||
object class 15/0Fh = image to video
|
||||
object class 16/10h = image stencil buffer
|
||||
object class 17/11h = image blending methods
|
||||
object class 18/12h = beta solid
|
||||
object class 19/13h = image -> render operation
|
||||
object class 20/14h = ROP5 (2^5 = 32bit rop)
|
||||
object class 21/15h = color key
|
||||
object class 22/16h = plane switch
|
||||
object class 23/17h = "solid image"
|
||||
object class 24/18h = pattern
|
||||
object class 25/19h = black rectangle
|
||||
object class 26/1Ah = solid point
|
||||
object class 27/1Bh = solid line
|
||||
object class 28/1Ch = solid lin (line without its ending or starting pixel)
|
||||
object class 29/1Dh = triangle
|
||||
object class 30/1Eh = solid rectangle
|
||||
object class 31/1Fh = blit image
|
||||
object class 33/21h = get image from cpu
|
||||
object class 34/22h = get image from cpu, monochrome
|
||||
object class 37/25h = get image from local GPU memory
|
||||
object class 49/31h and 51/33h = patchcord, again
|
||||
object class 54/36h = get image from cpu, stretched
|
||||
object class 55/37h = get image from vram, scaled
|
||||
object class 56/38h = get image from vram, scaled, YUV 420 color space (probably internal colour space used for rendering)
|
||||
object class 57/39h = convert image(?) between formats in place in vram, allows you to set an in and out buffer and all that jazz
|
||||
object class 61/3Dh = In-Memory DMA (vram to vram?)
|
||||
object class 62/3Eh = get image from vram
|
||||
object class 63/3Fh = get video from vram
|
||||
object class 64/40h = video scaler
|
||||
object class 65/41h = video color key (as opposed to image)
|
||||
object class 66/42h = capture video to memory
|
||||
object class 67/43h = Solid ROP5
|
||||
object class 68/44h = zeta buffer (combined z and stencil buffer) from CPU(?)
|
||||
object class 69/45h = zeta buffer in VRAM
|
||||
object class 70/46h = zeta buffer patchcord
|
||||
object class 71/47h = render solid point into zeta buffer (Also rectangle0
|
||||
object class 72/48h = render Direct3D 5.x ("D3D0") accelerated triangle into zeta buffer
|
||||
object class 73/49h = render Direct3D 5.x ("D3D0") accelerated triangle
|
||||
object class 74/4Ah = video source
|
||||
object class 75/4Bh = render Windows GDI accelerated rectangle and text
|
||||
@@ -14,7 +14,7 @@
|
||||
* Also check the doc folder for some more notres
|
||||
*
|
||||
* vid_nv3.h: NV3 Architecture Hardware Reference (open-source)
|
||||
* Last updated: 30 January 2025 (STILL WORKING ON IT!!!)
|
||||
* Last updated: 2 February 2025 (STILL WORKING ON IT!!!)
|
||||
*
|
||||
* Authors: Connor Hyde <mario64crashed@gmail.com>
|
||||
*
|
||||
@@ -272,11 +272,14 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CONTROL 0x3040
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED 0
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CONTROL_HASH_FAILURE 4
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD 8
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD 8
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CTX_IS_DIRTY 0x3050
|
||||
#define NV3_PFIFO_CACHE0_PULLER_CTX_IS_DIRTY_BOOL 4 // 1=dirty 0=clean
|
||||
#define NV3_PFIFO_CACHE0_GET 0x3070
|
||||
#define NV3_PFIFO_CACHE0_GET_ADDRESS 2 // 1 bit
|
||||
// Current channel context - cache1
|
||||
#define NV3_PFIFO_CACHE0_CTX 0x3080
|
||||
|
||||
#define NV3_PFIFO_CACHE0_METHOD 0x3100
|
||||
#define NV3_PFIFO_CACHE0_METHOD_ADDRESS 2 // 12:2
|
||||
#define NV3_PFIFO_CACHE0_METHOD_SUBCHANNEL 13 // 15:13
|
||||
@@ -306,6 +309,11 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_PFIFO_CACHE1_PULLER_CTX_IS_DIRTY 4
|
||||
#define NV3_PFIFO_CACHE1_GET 0x3270
|
||||
#define NV3_PFIFO_CACHE1_GET_ADDRESS 2 // 6:2
|
||||
|
||||
// Current channel context - cache1
|
||||
#define NV3_PFIFO_CACHE1_CTX_START 0x3280
|
||||
#define NV3_PFIFO_CACHE1_CTX_END 0x32F0
|
||||
|
||||
#define NV3_PFIFO_CACHE1_METHOD 0x3300
|
||||
#define NV3_PFIFO_CACHE1_METHOD_ADDRESS 2 // 12:2
|
||||
#define NV3_PFIFO_CACHE1_METHOD_SUBCHANNEL 13 // 15:13
|
||||
@@ -797,11 +805,11 @@ typedef struct nv3_pfifo_cache_s
|
||||
bool access_enabled; // Can we even access this cache?
|
||||
uint8_t put_address; // Trigger a DMA into the value you put here.
|
||||
uint8_t get_address; // Trigger a DMA from the value you put here into where you were going.
|
||||
uint8_t channel; // The DMA channel ID of this cache.
|
||||
uint8_t channel; // The DMA channel ID of this cache.
|
||||
uint32_t status;
|
||||
uint32_t puller_control;
|
||||
uint32_t control;
|
||||
uint32_t context[NV3_DMA_SUBCHANNELS_PER_CHANNEL];
|
||||
uint32_t context[NV3_DMA_SUBCHANNELS_PER_CHANNEL]; // Only one of these exists for cache0
|
||||
|
||||
/* cache1 only
|
||||
do we even need to emulate this?
|
||||
|
||||
@@ -75,7 +75,7 @@ uint32_t nv3_pbus_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ uint32_t nv3_pextdev_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ uint32_t nv3_pfb_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ nv_register_t pfifo_registers[] = {
|
||||
{ NV3_PFIFO_CONFIG_RAMFC, "PFIFO - RAMIN RAMFC Config", NULL, NULL },
|
||||
{ NV3_PFIFO_CONFIG_RAMHT, "PFIFO - RAMIN RAMHT Config", NULL, NULL },
|
||||
{ NV3_PFIFO_CONFIG_RAMRO, "PFIFO - RAMIN RAMRO Config", NULL, NULL },
|
||||
{ NV3_PFIFO_CACHE_REASSIGNMENT, "PFIFO - Allow Cache Channel Reassignment", NULL, NULL },
|
||||
{ NV3_PFIFO_CACHE0_PULLER_CONTROL, "PFIFO - Cache0 Puller Control", NULL, NULL},
|
||||
{ NV3_PFIFO_CACHE1_PULLER_CONTROL, "PFIFO - Cache1 Puller Control"},
|
||||
{ NV3_PFIFO_CACHE0_PULLER_CTX_IS_DIRTY, "PFIFO - Cache0 Puller State1 (Is context clean?)", NULL, NULL},
|
||||
@@ -231,21 +232,34 @@ uint32_t nv3_pfifo_read(uint32_t address)
|
||||
case NV3_PFIFO_CACHE1_DMA_TLB_TAG:
|
||||
ret = nv3->pfifo.cache1_settings.dma_tlb_tag;
|
||||
break;
|
||||
// Runout
|
||||
case NV3_PFIFO_RUNOUT_GET:
|
||||
ret = nv3->pfifo.runout_get;
|
||||
break;
|
||||
case NV3_PFIFO_RUNOUT_PUT:
|
||||
ret = nv3->pfifo.runout_put;
|
||||
break;
|
||||
/* Cache1 is handled below */
|
||||
case NV3_PFIFO_CACHE0_CTX:
|
||||
ret = nv3->pfifo.cache0_settings.context[0];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s\n", reg->friendly_name);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
/* Handle some special memory areas */
|
||||
else if (address >= NV3_PFIFO_CACHE1_CTX_START && address <= NV3_PFIFO_CACHE1_CTX_END)
|
||||
{
|
||||
uint32_t ctx_entry_id = ((address - NV3_PFIFO_CACHE1_CTX_START) / 16) % 8;
|
||||
ret = nv3->pfifo.cache1_settings.context[ctx_entry_id];
|
||||
|
||||
nv_log("PFIFO Cache1 CTX Read Entry=%d Value=0x%04x", ctx_entry_id, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_log(": Unknown register read (address=0x%08x), returning 0x00\n", address);
|
||||
@@ -267,16 +281,11 @@ void nv3_pfifo_write(uint32_t address, uint32_t value)
|
||||
|
||||
nv_register_t* reg = nv_get_register(address, pfifo_registers, sizeof(pfifo_registers)/sizeof(pfifo_registers[0]));
|
||||
|
||||
nv_log("NV3: PFIFO Write 0x%08x -> 0x%08x\n", value, address);
|
||||
nv_log("NV3: PFIFO Write 0x%08x -> 0x%08x", value, address);
|
||||
|
||||
// if the register actually exists
|
||||
if (reg)
|
||||
{
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s\n", reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
|
||||
// on-read function
|
||||
if (reg->on_write)
|
||||
reg->on_write(value);
|
||||
@@ -293,9 +302,15 @@ void nv3_pfifo_write(uint32_t address, uint32_t value)
|
||||
case NV3_PFIFO_INTR:
|
||||
nv3->pfifo.interrupt_status &= ~value;
|
||||
nv3_pmc_clear_interrupts();
|
||||
|
||||
// update the internal cache error state
|
||||
if (!nv3->pfifo.interrupt_status & NV3_PFIFO_INTR_CACHE_ERROR)
|
||||
nv3->pfifo.debug_0 &= ~NV3_PFIFO_INTR_CACHE_ERROR;
|
||||
|
||||
break;
|
||||
case NV3_PFIFO_INTR_EN:
|
||||
nv3->pbus.interrupt_enable = value & 0x00001111;
|
||||
nv3->pfifo.interrupt_enable = value & 0x00001111;
|
||||
nv3_pmc_handle_interrupts(true);
|
||||
break;
|
||||
case NV3_PFIFO_DELAY_0:
|
||||
nv3->pfifo.dma_delay_retry = value;
|
||||
@@ -426,10 +441,26 @@ void nv3_pfifo_write(uint32_t address, uint32_t value)
|
||||
else
|
||||
nv3->pfifo.runout_put = ((value & 0x3FF) << 3);
|
||||
break;
|
||||
/* Cache1 is handled below */
|
||||
case NV3_PFIFO_CACHE0_CTX:
|
||||
nv3->pfifo.cache0_settings.context[0] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s\n", reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
/* Handle some special memory areas */
|
||||
else if (address >= NV3_PFIFO_CACHE1_CTX_START && address <= NV3_PFIFO_CACHE1_CTX_END)
|
||||
{
|
||||
uint32_t ctx_entry_id = ((address - NV3_PFIFO_CACHE1_CTX_START) / 16) % 8;
|
||||
nv3->pfifo.cache1_settings.context[ctx_entry_id] = value;
|
||||
|
||||
nv_log("PFIFO Cache1 CTX Write Entry=%d value=0x%04x", ctx_entry_id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -140,9 +140,11 @@ uint32_t nv3_pgraph_read(uint32_t address)
|
||||
break;
|
||||
case NV3_PGRAPH_INTR_EN_0:
|
||||
ret = nv3->pgraph.interrupt_enable_0;
|
||||
nv3_pmc_handle_interrupts(true);
|
||||
break;
|
||||
case NV3_PGRAPH_INTR_EN_1:
|
||||
ret = nv3->pgraph.interrupt_enable_1;
|
||||
nv3_pmc_handle_interrupts(true);
|
||||
break;
|
||||
// A lot of this is currently a temporary implementation so that we can just debug what the current state looks like
|
||||
// during the driver initialisation process
|
||||
@@ -243,7 +245,7 @@ uint32_t nv3_pgraph_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
@@ -457,5 +459,5 @@ void nv3_pgraph_vblank_start(svga_t* svga)
|
||||
|
||||
void nv3_pgraph_submit()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@@ -211,7 +211,7 @@ uint32_t nv3_pmc_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ uint32_t nv3_pme_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ uint32_t nv3_pramdac_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -76,14 +76,11 @@ void nv3_ptimer_tick(double real_time)
|
||||
|
||||
double current_time = freq_base * ((double)nv3->ptimer.clock_numerator * NV3_86BOX_TIMER_SYSTEM_FIX_QUOTIENT) / (double)nv3->ptimer.clock_denominator; // *10.0?
|
||||
|
||||
// Logging is suppressed when reading this register because it is read many times
|
||||
// So we only log when we update.
|
||||
|
||||
// truncate it
|
||||
nv3->ptimer.time += (uint64_t)current_time;
|
||||
|
||||
|
||||
nv_log("PTIMER time ticked (The value is now 0x%08x)\n", nv3->ptimer.time);
|
||||
// Only log on ptimer alarm. Otherwise, it's too much spam.
|
||||
//nv_log("PTIMER time ticked (The value is now 0x%08x)\n", nv3->ptimer.time);
|
||||
|
||||
// Check if the alarm has actually triggered...
|
||||
if (nv3->ptimer.time >= nv3->ptimer.alarm)
|
||||
@@ -153,7 +150,7 @@ uint32_t nv3_ptimer_read(uint32_t address)
|
||||
&& reg->address != NV3_PTIMER_TIME_1_NSEC)
|
||||
{
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ uint32_t nv3_pvideo_read(uint32_t address)
|
||||
}
|
||||
|
||||
if (reg->friendly_name)
|
||||
nv_log(": %s (value = 0x%08x)\n", reg->friendly_name, ret);
|
||||
nv_log(": 0x%08x <- %s\n", ret, reg->friendly_name);
|
||||
else
|
||||
nv_log("\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user