fix crossbuffer blit, use custom render functions

This commit is contained in:
starfrost013
2025-04-06 18:08:42 +01:00
parent c9f6f87fcc
commit c1506772de
9 changed files with 186 additions and 18 deletions

View File

@@ -270,8 +270,8 @@ typedef struct nv3_color_argb_s
/* Generic 16-bit position*/
typedef struct nv3_position_16_s
{
uint16_t y;
uint16_t x;
uint16_t y;
} nv3_position_16_t;
/* A big position format with 30:16 = y, 15:11 = nothing, 10:0 = x */
@@ -287,8 +287,8 @@ typedef struct nv3_position_16_bigy_s
/* Generic 16-bit size */
typedef struct nv3_size_16_s
{
uint16_t h;
uint16_t w;
uint16_t h;
} nv3_size_16_t;
/* Generic 32-bit colour + 16-bit position */

View File

@@ -18,6 +18,9 @@
#pragma once
/* Core */
void nv3_render_15bpp(svga_t *svga);
void nv3_render_16bpp(svga_t *svga);
void nv3_render_32bpp(svga_t *svga);
void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj);
uint8_t nv3_render_read_pixel_8(nv3_position_16_t position, nv3_grobj_t grobj, bool use_destination);
uint16_t nv3_render_read_pixel_16(nv3_position_16_t position, nv3_grobj_t grobj, bool use_destination);

View File

@@ -121,6 +121,7 @@ typedef struct nv_base_s
bool memory_clock_enabled; // Memory Clock Enabled - stupid crap used to prevent us eanbling the timer multiple times
void* i2c; // I2C for monitor EDID
void* ddc; // Display Data Channel for EDID
uint32_t last_buffer_address; // Last buffer address.
} nv_base_t;
#define NV_REG_LIST_END 0xD15EA5E

View File

@@ -1194,8 +1194,8 @@ typedef struct nv3_pgraph_s
nv3_pgraph_dma_settings_t dma_settings;
uint8_t rop; // Current GDI Ternary Render Operation
// SURFACE STUFF - PGRAPH CAN OPERATE ON 4 SURFACES/BUFFERS AT A TIME
uint32_t boffset[NV3_PGRAPH_MAX_BUFFERS]; // 22-bit linear VRAM offset for the start of a surface.
uint16_t bpitch[NV3_PGRAPH_MAX_BUFFERS]; // 12-bit linear VRAM offset for the pitch of a surfac.e
uint32_t boffset[NV3_PGRAPH_MAX_BUFFERS]; // 22-bit linear VRAM offset for the start of a buffer.
uint16_t bpitch[NV3_PGRAPH_MAX_BUFFERS]; // 12-bit linear VRAM offset for the pitch of a buffer
uint32_t bpixel[NV3_PGRAPH_MAX_BUFFERS]; // Pixel format for each possible surfaces.
// CLIP
nv3_pgraph_clip_misc_settings_t clip_misc_settings;

View File

@@ -77,8 +77,13 @@ void nv3_class_01c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
break;
/* Byte offset in GPU VRAM of top left pixel (22:0) */
case NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET:
nv3->pgraph.boffset[src_buffer_id] = param & ((1 << NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET_END) - 0x10);
if (nv3->nvbase.gpu_revision == NV3_PCI_CFG_REVISION_C00) // RIVA 128ZX
nv3->pgraph.boffset[src_buffer_id] = param & 0x7FFFFF;
else
nv3->pgraph.boffset[src_buffer_id] = param & 0x3FFFFF;
nv3->nvbase.last_buffer_address = nv3->pgraph.boffset[src_buffer_id];
nv_log("Method Execution: Image in Memory BUF%d TOP_LEFT_OFFSET=0x%08x\n", src_buffer_id, nv3->pgraph.boffset[src_buffer_id]);
break;
default:

View File

@@ -523,30 +523,27 @@ void nv3_recalc_timings(svga_t* svga)
break;
case NV3_CRTC_REGISTER_PIXELMODE_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 */
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 *ReactOS* of all things */
if ((svga->crtc[NV3_CRTC_REGISTER_VRETRACESTART] >> 1) & 0x01)
{
svga->rowoffset += (svga->crtc[NV3_CRTC_REGISTER_RPC0] & 0xE0) << 2;
}
else
{
svga->rowoffset += (svga->crtc[NV3_CRTC_REGISTER_RPC0] & 0xE0) << 3;
}
/* sometimes it really renders in 15bpp, so you need to do this */
if ((nv3->pramdac.general_control >> NV3_PRAMDAC_GENERAL_CONTROL_565_MODE) & 0x01)
{
svga->bpp = 16;
svga->lowres = 0;
svga->render = svga_render_16bpp_highres;
svga->render = nv3_render_16bpp;
}
else
{
svga->bpp = 15;
svga->lowres = 0;
svga->render = svga_render_15bpp_highres;
svga->render = nv3_render_15bpp;
// fixes win2000, but breaks 9x?!
}
break;
@@ -555,7 +552,7 @@ void nv3_recalc_timings(svga_t* svga)
svga->bpp = 32;
svga->lowres = 0;
svga->render = svga_render_32bpp_highres;
svga->render = nv3_render_32bpp;
break;
}

View File

@@ -164,12 +164,13 @@ void nv3_render_blit_screen2screen(nv3_grobj_t grobj)
memcpy(&nv3_s2sb_line_buffer[buf_position], &nv3->nvbase.svga.vram[vram_position], size_x);
}
/* simply write it all back to vram */
for (int32_t y = 0; y < nv3->pgraph.blit.size.h; y++)
{
buf_position = (nv3->pgraph.blit.size.w * y);
new_position.y = nv3->pgraph.blit.point_out.y + y;
vram_position = nv3_render_get_vram_address(new_position, grobj, false);
vram_position = nv3_render_get_vram_address(new_position, grobj, true);
memcpy(&nv3->nvbase.svga.vram[vram_position], &nv3_s2sb_line_buffer[buf_position], size_x);
}
}

View File

@@ -436,3 +436,164 @@ void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grob
break;
}
}
/*
Modified SVGA Core functions
Done, to facilitate the buffer changing around stuff.
TODO: Do we need a custom 8bpp function?
*/
void nv3_render_15bpp(svga_t *svga)
{
int x;
uint32_t *p;
uint32_t dat;
uint32_t changed_addr;
uint32_t addr;
/* "force_old_addr" code path removed, since we don't need it */
if ((svga->displine + svga->y_add) < 0)
return;
changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) {
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
}
svga->ma += x << 1;
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[(addr) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void nv3_render_16bpp(svga_t *svga)
{
int x;
uint32_t *p;
uint32_t dat;
uint32_t changed_addr;
uint32_t addr;
if ((svga->displine + svga->y_add) < 0)
return;
changed_addr = svga->remap_func(svga, svga->ma);
/* "force_old_addr" code path removed, since we don't need it */
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) {
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += x << 1;
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[(addr) & svga->vram_display_mask]);
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}
void nv3_render_32bpp(svga_t *svga)
{
int x;
uint32_t *p;
uint32_t dat;
uint32_t changed_addr;
uint32_t addr;
if ((svga->displine + svga->y_add) < 0)
return;
/* "force_old_addr" code path removed, since we don't need it */
changed_addr = svga->remap_func(svga, svga->ma);
if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) {
p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = svga_lookup_lut_ram(svga, dat & 0xffffff);
}
svga->ma += (x * 4);
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = svga_lookup_lut_ram(svga, dat & 0xffffff);
svga->ma += 4;
}
}
svga->ma &= svga->vram_display_mask;
}
}

View File

@@ -873,7 +873,7 @@ void nv3_pfifo_cache1_push(uint32_t addr, uint32_t param)
uint32_t next_put_address = nv3_pfifo_cache1_gray2normal(current_put_index);
next_put_address++;
if (nv3->nvbase.gpu_revision >= NV3_BOOT_REG_REV_C00) // RIVA 128ZX#
if (nv3->nvbase.gpu_revision >= NV3_PCI_CFG_REVISION_C00) // RIVA 128ZX#
next_put_address &= (NV3_PFIFO_CACHE1_SIZE_REV_C - 1);
else
next_put_address &= (NV3_PFIFO_CACHE1_SIZE_REV_AB - 1);
@@ -931,7 +931,7 @@ void nv3_pfifo_cache1_pull()
// start by incrementing
uint32_t next_get_address = nv3_pfifo_cache1_gray2normal(get_index) + 1;
if (nv3->nvbase.gpu_revision >= NV3_BOOT_REG_REV_C00) // RIVA 128ZX#
if (nv3->nvbase.gpu_revision >= NV3_PCI_CFG_REVISION_C00) // RIVA 128ZX
next_get_address &= (NV3_PFIFO_CACHE1_SIZE_REV_C - 1);
else
next_get_address &= (NV3_PFIFO_CACHE1_SIZE_REV_AB - 1);