diff --git a/src/include/86box/nv/classes/vid_nv3_classes.h b/src/include/86box/nv/classes/vid_nv3_classes.h index e3a1bf7aa..3b6eb1411 100644 --- a/src/include/86box/nv/classes/vid_nv3_classes.h +++ b/src/include/86box/nv/classes/vid_nv3_classes.h @@ -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 */ diff --git a/src/include/86box/nv/render/vid_nv3_render.h b/src/include/86box/nv/render/vid_nv3_render.h index 048f3089a..567cf3cd4 100644 --- a/src/include/86box/nv/render/vid_nv3_render.h +++ b/src/include/86box/nv/render/vid_nv3_render.h @@ -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); diff --git a/src/include/86box/nv/vid_nv.h b/src/include/86box/nv/vid_nv.h index c26c51868..0b314d5f3 100644 --- a/src/include/86box/nv/vid_nv.h +++ b/src/include/86box/nv/vid_nv.h @@ -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 diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index dc6249346..482315e32 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -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; diff --git a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c index af488dc09..9e6a55310 100644 --- a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c +++ b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c @@ -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: diff --git a/src/video/nv/nv3/nv3_core.c b/src/video/nv/nv3/nv3_core.c index 610f8c500..78592160a 100644 --- a/src/video/nv/nv3/nv3_core.c +++ b/src/video/nv/nv3/nv3_core.c @@ -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; } diff --git a/src/video/nv/nv3/render/nv3_render_blit.c b/src/video/nv/nv3/render/nv3_render_blit.c index ad8c0e3f9..666a93482 100644 --- a/src/video/nv/nv3/render/nv3_render_blit.c +++ b/src/video/nv/nv3/render/nv3_render_blit.c @@ -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); } } \ No newline at end of file diff --git a/src/video/nv/nv3/render/nv3_render_core.c b/src/video/nv/nv3/render/nv3_render_core.c index dca2a6a6c..147ac8f6e 100644 --- a/src/video/nv/nv3/render/nv3_render_core.c +++ b/src/video/nv/nv3/render/nv3_render_core.c @@ -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; + } +} diff --git a/src/video/nv/nv3/subsystems/nv3_pfifo.c b/src/video/nv/nv3/subsystems/nv3_pfifo.c index 6195c0639..ea39b9135 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfifo.c +++ b/src/video/nv/nv3/subsystems/nv3_pfifo.c @@ -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);