diff --git a/src/include/86box/nv/render/vid_nv3_render.h b/src/include/86box/nv/render/vid_nv3_render.h index 65541fa0d..fe429da74 100644 --- a/src/include/86box/nv/render/vid_nv3_render.h +++ b/src/include/86box/nv/render/vid_nv3_render.h @@ -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 */ diff --git a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c index fae6771e2..f2e575933 100644 --- a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c +++ b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c @@ -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; diff --git a/src/video/nv/nv3/classes/nv3_class_006_pattern.c b/src/video/nv/nv3/classes/nv3_class_006_pattern.c index f007d5fb8..b66db499e 100644 --- a/src/video/nv/nv3/classes/nv3_class_006_pattern.c +++ b/src/video/nv/nv3/classes/nv3_class_006_pattern.c @@ -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: diff --git a/src/video/nv/nv3/classes/nv3_class_010_blit.c b/src/video/nv/nv3/classes/nv3_class_010_blit.c index 5eea98f85..57184054d 100644 --- a/src/video/nv/nv3/classes/nv3_class_010_blit.c +++ b/src/video/nv/nv3/classes/nv3_class_010_blit.c @@ -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; diff --git a/src/video/nv/nv3/classes/nv3_class_011_image.c b/src/video/nv/nv3/classes/nv3_class_011_image.c index 523aadff7..c1d1200b9 100644 --- a/src/video/nv/nv3/classes/nv3_class_011_image.c +++ b/src/video/nv/nv3/classes/nv3_class_011_image.c @@ -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 { diff --git a/src/video/nv/nv3/nv3_core.c b/src/video/nv/nv3/nv3_core.c index 28c6edab5..1718b4e7f 100644 --- a/src/video/nv/nv3/nv3_core.c +++ b/src/video/nv/nv3/nv3_core.c @@ -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 diff --git a/src/video/nv/nv3/render/nv3_render_blit.c b/src/video/nv/nv3/render/nv3_render_blit.c index 539871884..9da3f05b1 100644 --- a/src/video/nv/nv3/render/nv3_render_blit.c +++ b/src/video/nv/nv3/render/nv3_render_blit.c @@ -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++; diff --git a/src/video/nv/nv3/render/nv3_render_core.c b/src/video/nv/nv3/render/nv3_render_core.c index 7ae00efd6..15c652e5b 100644 --- a/src/video/nv/nv3/render/nv3_render_core.c +++ b/src/video/nv/nv3/render/nv3_render_core.c @@ -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); diff --git a/src/video/nv/nv3/subsystems/nv3_pramdac.c b/src/video/nv/nv3/subsystems/nv3_pramdac.c index c640d5f10..fb83ffaf1 100644 --- a/src/video/nv/nv3/subsystems/nv3_pramdac.c +++ b/src/video/nv/nv3/subsystems/nv3_pramdac.c @@ -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; }