inform the emulator of the video timings

This commit is contained in:
starfrost013
2025-03-29 19:06:46 +00:00
parent c28a596a34
commit 7234b432ac
9 changed files with 131 additions and 96 deletions

View File

@@ -24,7 +24,7 @@ uint16_t nv3_render_read_pixel_16(nv3_position_16_t position, nv3_grobj_t grobj)
uint32_t nv3_render_read_pixel_32(nv3_position_16_t position, nv3_grobj_t grobj);
uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded);
nv3_color_expanded_t nv3_render_expand_color(nv3_grobj_t grobj, uint32_t color); // Convert a colour to full RGB10 format from the current working format.
nv3_color_expanded_t nv3_render_expand_color(uint32_t color, nv3_grobj_t grobj); // Convert a colour to full RGB10 format from the current working format.
uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t color); // Convert a colour from the current working format to RGB10 format.
/* Pattern */
@@ -34,9 +34,10 @@ uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool
void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj);
/* Chroma */
bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color);
bool nv3_render_chroma_test(uint32_t color, nv3_grobj_t grobj);
/* Blit */
void nv3_render_blit_image(uint32_t color, nv3_grobj_t grobj);
void nv3_render_blit_screen2screen(nv3_grobj_t grobj);
/* GDI */

View File

@@ -33,7 +33,7 @@ void nv3_class_003_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
switch (method_id)
{
case NV3_CHROMA_KEY:
nv3_color_expanded_t expanded_color = nv3_render_expand_color(grobj, param);
nv3_color_expanded_t expanded_color = nv3_render_expand_color(param, grobj);
nv3->pgraph.chroma_key = nv3_render_to_chroma(expanded_color);
break;

View File

@@ -60,11 +60,11 @@ void nv3_class_006_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
case NV3_PATTERN_UNUSED_DRIVER_BUG:
break;
case NV3_PATTERN_COLOR0:
nv3_color_expanded_t expanded_colour0 = nv3_render_expand_color(grobj, param);
nv3_color_expanded_t expanded_colour0 = nv3_render_expand_color(param, grobj);
nv3_render_set_pattern_color(expanded_colour0, false);
break;
case NV3_PATTERN_COLOR1:
nv3_color_expanded_t expanded_colour1 = nv3_render_expand_color(grobj, param);
nv3_color_expanded_t expanded_colour1 = nv3_render_expand_color(param, grobj);
nv3_render_set_pattern_color(expanded_colour1, true);
break;
case NV3_PATTERN_BITMAP_HIGH:

View File

@@ -49,6 +49,11 @@ void nv3_class_010_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
nv3->pgraph.blit.size.h = ((param >> 16) & 0xFFFF);
nv_log("Method Execution: S2SB Size %04x,%04x\n", nv3->pgraph.blit.point_in.x, nv3->pgraph.blit.point_in.y);
/* Some blits have (point_in == point_out) ???? */
if (nv3->pgraph.blit.point_in.x == nv3->pgraph.blit.point_out.x
&& nv3->pgraph.blit.point_in.y == nv3->pgraph.blit.point_out.y)
return;
nv3_render_blit_screen2screen(grobj);
break;

View File

@@ -28,19 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
/* Check the line bounds */
void nv3_class_011_check_line_bounds()
{
uint32_t relative_x = nv3->pgraph.image_current_position.x - nv3->pgraph.image.point.x;
//uint32_t relative_y = nv3->pgraph.image_current_position.y - nv3->pgraph.image.point.y;
/* In theory, relative_y should never be exceeded...because it only submits enough pixels to render the image*/
if (relative_x >= nv3->pgraph.image.size_in.w)
{
nv3->pgraph.image_current_position.y++;
nv3->pgraph.image_current_position.x = nv3->pgraph.image.point.x;
}
}
void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
@@ -65,71 +53,10 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
break;
default:
if (method_id >= NV3_IMAGE_COLOR_START && method_id <= NV3_IMAGE_COLOR_END)
{
// shift left by 2 because it's 4 bits per si\e..
{
uint32_t pixel_slot = (method_id - NV3_IMAGE_COLOR_START) >> 2;
uint32_t current_buffer = (nv3->pgraph.context_switch >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03;
nv_log("Method Execution: Pixel%d Colour%08x Format%x\n", pixel_slot, param, (grobj.grobj_0) & 0x07);
/* todo: a lot of stuff */
uint32_t pixel0 = 0, pixel1 = 0, pixel2 = 0, pixel3 = 0;
/* Some extra data is sent as padding, we need to clip it off using size_out */
uint16_t clip_x = nv3->pgraph.image_current_position.x + nv3->pgraph.image.size.w;
/* we need to unpack them - IF THIS IS USED SOMEWHERE ELSE, DO SOMETHING ELSE WITH IT */
/* the reverse order is due to the endianness */
switch (nv3->nvbase.svga.bpp)
{
// 4pixels packed into one param
case 8:
//pixel3
pixel3 = param & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel3, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel2 = (param >> 8) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel2, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel1 = (param >> 16) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel0 = (param >> 24) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
//2pixels packed into one param
case 15:
case 16:
pixel1 = (param) & 0xFFFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel0 = (param >> 16) & 0xFFFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
// just one pixel in 32bpp
case 32:
pixel0 = param;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
}
nv3_render_blit_image(param, grobj);
}
else
{

View File

@@ -29,6 +29,13 @@
nv3_t* nv3;
/* These are a ****PLACEHOLDER**** and are copied from 3dfx VoodooBanshee/Voodoo3*/
static video_timings_t timing_nv3_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 };
static video_timings_t timing_nv3_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 };
// Revision C
static video_timings_t timing_nv3t_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 };
static video_timings_t timing_nv3t_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 };
// Prototypes for functions only used in this translation unit
void nv3_init_mappings_mmio();
void nv3_init_mappings_svga();
@@ -492,9 +499,7 @@ void nv3_recalc_timings(svga_t* svga)
nv3_t* nv3 = (nv3_t*)svga->priv;
svga->ma_latch += (svga->crtc[NV3_CRTC_REGISTER_RPC0] & 0x1F) << 16;
svga->rowoffset += (svga->crtc[NV3_CRTC_REGISTER_RPC0] & 0xE0) << 2;
// should these actually use separate values?
@@ -530,7 +535,7 @@ void nv3_recalc_timings(svga_t* svga)
}
else
{
svga->bpp = 15; // HACK: DO NOT change this
svga->bpp = 15;
svga->lowres = 0;
svga->render = svga_render_15bpp_highres;
}
@@ -1085,6 +1090,12 @@ void* nv3_init(const device_t *info)
svga_init(&nv3_device_pci, &nv3->nvbase.svga, nv3, nv3->nvbase.vram_amount,
nv3_recalc_timings, nv3_svga_in, nv3_svga_out, nv3_draw_cursor, NULL);
if (nv3->nvbase.gpu_revision == NV3_PCI_CFG_REVISION_C00)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_nv3t_pci);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_nv3_pci);
}
else if (nv3->nvbase.bus_generation == nv_bus_agp_1x)
{
@@ -1094,6 +1105,11 @@ void* nv3_init(const device_t *info)
svga_init(&nv3_device_agp, &nv3->nvbase.svga, nv3, nv3->nvbase.vram_amount,
nv3_recalc_timings, nv3_svga_in, nv3_svga_out, nv3_draw_cursor, NULL);
if (nv3->nvbase.gpu_revision == NV3_PCI_CFG_REVISION_C00)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_nv3t_agp);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_nv3_agp);
}
// set vram

View File

@@ -29,9 +29,94 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
/* Check the line bounds */
void nv3_class_011_check_line_bounds()
{
uint32_t relative_x = nv3->pgraph.image_current_position.x - nv3->pgraph.image.point.x;
//uint32_t relative_y = nv3->pgraph.image_current_position.y - nv3->pgraph.image.point.y;
/* In theory, relative_y should never be exceeded...because it only submits enough pixels to render the image*/
if (relative_x >= nv3->pgraph.image.size_in.w)
{
nv3->pgraph.image_current_position.y++;
nv3->pgraph.image_current_position.x = nv3->pgraph.image.point.x;
}
}
/* Renders an image from cpu */
void nv3_render_blit_image(uint32_t color, nv3_grobj_t grobj)
{
// shift left by 2 because it's 4 bits per size..
uint32_t current_buffer = (nv3->pgraph.context_switch >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03;
/* todo: a lot of stuff */
uint32_t pixel0 = 0, pixel1 = 0, pixel2 = 0, pixel3 = 0;
/* Some extra data is sent as padding, we need to clip it off using size_out */
uint16_t clip_x = nv3->pgraph.image_current_position.x + nv3->pgraph.image.size.w;
/* we need to unpack them - IF THIS IS USED SOMEWHERE ELSE, DO SOMETHING ELSE WITH IT */
/* the reverse order is due to the endianness */
switch (nv3->nvbase.svga.bpp)
{
// 4pixels packed into one color
case 8:
//pixel3
pixel3 = color & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel3, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel2 = (color >> 8) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel2, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel1 = (color >> 16) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel0 = (color >> 24) & 0xFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
//2pixels packed into one color
case 15:
case 16:
pixel1 = (color) & 0xFFFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
pixel0 = (color >> 16) & 0xFFFF;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
// just one pixel in 32bpp
case 32:
pixel0 = color;
if (nv3->pgraph.image_current_position.x < clip_x) nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
break;
}
}
void nv3_render_blit_screen2screen(nv3_grobj_t grobj)
{
nv3_position_16_t old_position = nv3->pgraph.blit.point_in;
//nv3_position_16_t old_position = nv3->pgraph.blit.point_in + nv3->pgraph.blit.size.w;
nv3_position_16_t old_position = {0};
old_position.x = nv3->pgraph.blit.point_in.x + nv3->pgraph.blit.size.w;
old_position.y = nv3->pgraph.blit.point_in.y + nv3->pgraph.blit.size.h;
nv3_position_16_t new_position = nv3->pgraph.blit.point_out;
uint16_t end_x = (nv3->pgraph.blit.point_out.x + nv3->pgraph.blit.size.w);
@@ -63,7 +148,7 @@ void nv3_render_blit_screen2screen(nv3_grobj_t grobj)
old_position.y++;
new_position.y++;
for (int32_t x = nv3->pgraph.blit.point_out.x; x < end_x; x++)
for (int32_t x = nv3->pgraph.blit.point_out.x; x >= end_x; x++)
{
old_position.x++;
new_position.x++;
@@ -79,7 +164,7 @@ void nv3_render_blit_screen2screen(nv3_grobj_t grobj)
old_position.y++;
new_position.y++;
for (int32_t x = nv3->pgraph.blit.point_out.x; x < end_x; x++)
for (int32_t x = nv3->pgraph.blit.point_out.x; x >= end_x; x++)
{
old_position.x++;
new_position.x++;

View File

@@ -33,7 +33,7 @@
/* Expand a colour.
NOTE: THE GPU INTERNALLY OPERATES ON RGB10!!!!!!!!!!!
*/
nv3_color_expanded_t nv3_render_expand_color(nv3_grobj_t grobj, uint32_t color)
nv3_color_expanded_t nv3_render_expand_color(uint32_t color, nv3_grobj_t grobj)
{
// grobj0 = seems to share the format of PGRAPH_CONTEXT_SWITCH register.
@@ -113,7 +113,7 @@ uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t co
bool alpha_enabled = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_ALPHA) & 0x01;
#ifdef ENABLE_NV_LOG
nv_log("Downconverting Colour 0x%08x using pgraph_pixel_format 0x%x alpha enabled=%d", color, format, alpha_enabled);
nv_log("Downconverting Colour 0x%08x using pgraph_pixel_format 0x%x alpha enabled=%d\n", color, format, alpha_enabled);
#endif
uint32_t packed_color = 0x00;
@@ -156,7 +156,7 @@ uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t co
}
/* Runs the chroma key/color key test */
bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color)
bool nv3_render_chroma_test(uint32_t color, nv3_grobj_t grobj)
{
bool chroma_enabled = ((grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_CHROMA_KEY) & 0x01);
@@ -172,7 +172,7 @@ bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color)
nv3_grobj_t grobj_fake = {0};
grobj_fake.grobj_0 = 0x02; /* we don't care about any other bits */
nv3_color_expanded_t chroma_expanded = nv3_render_expand_color(grobj_fake, nv3->pgraph.chroma_key);
nv3_color_expanded_t chroma_expanded = nv3_render_expand_color(nv3->pgraph.chroma_key, grobj_fake);
uint32_t chroma_downconverted = nv3_render_downconvert_color(grobj, chroma_expanded);
@@ -315,7 +315,7 @@ void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grob
}
/* TODO: Plane Mask...*/
if (!nv3_render_chroma_test(grobj, color))
if (!nv3_render_chroma_test(color, grobj))
return;
uint32_t pixel_addr_vram = nv3_render_get_vram_address(position, grobj);

View File

@@ -341,14 +341,14 @@ void nv3_pramdac_write(uint32_t address, uint32_t value)
nv3->pramdac.vblank_end = value;
break;
case NV3_PRAMDAC_VBLANK_START:
nv3->nvbase.svga.vblankstart = value;
//nv3->nvbase.svga.vblankstart = value;
nv3->pramdac.vblank_start = value;
break;
case NV3_PRAMDAC_VEQU_START:
nv3->pramdac.vequ_start = value;
break;
case NV3_PRAMDAC_VTOTAL:
nv3->pramdac.vtotal = value;
//nv3->pramdac.vtotal = value;
nv3->nvbase.svga.vtotal = value;
break;
case NV3_PRAMDAC_HSYNC_WIDTH:
@@ -361,21 +361,22 @@ void nv3_pramdac_write(uint32_t address, uint32_t value)
nv3->pramdac.hburst_end = value;
break;
case NV3_PRAMDAC_HBLANK_START:
nv3->nvbase.svga.hblankstart = value;
//nv3->nvbase.svga.hblankstart = value;
nv3->pramdac.hblank_start = value;
break;
case NV3_PRAMDAC_HBLANK_END:
nv3->nvbase.svga.hblank_end_val = value;
//nv3->nvbase.svga.hblank_end_val = value;
nv3->pramdac.hblank_end = value;
break;
case NV3_PRAMDAC_HTOTAL:
nv3->pramdac.htotal = value;
nv3->nvbase.svga.htotal = value;
//nv3->nvbase.svga.htotal = value;
break;
case NV3_PRAMDAC_HEQU_WIDTH:
nv3->pramdac.hequ_width = value;
break;
case NV3_PRAMDAC_HSERR_WIDTH:
nv3->pramdac.hserr_width = value;
break;
}