More refactoring + implement screen2screen blits

This commit is contained in:
starfrost013
2025-03-23 19:12:02 +00:00
parent 160e8a8071
commit 0b0e6c5256
10 changed files with 216 additions and 52 deletions

View File

@@ -113,6 +113,11 @@ typedef enum nv3_pgraph_class_e
#define NV3_RECTANGLE_MAX 16
#define NV3_RECTANGLE_END 0x0480
// blit
#define NV3_BLIT_POSITION_IN 0x0300
#define NV3_BLIT_POSITION_OUT 0x0304
#define NV3_BLIT_SIZE 0x0308
// image_from_cpu
#define NV3_IMAGE_START_POSITION 0x0304 // starting position of image from cpu
#define NV3_IMAGE_SIZE 0x0308

View File

@@ -18,15 +18,25 @@
#pragma once
/* Core */
void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj);
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);
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.
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 */
uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1);
/* Primitives */
void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj);
void nv3_render_chroma_test(nv3_grobj_t grobj);
/* Chroma */
void nv3_render_chroma_test(nv3_grobj_t grobj);
/* Blit */
void nv3_render_blit_screen2screen(nv3_grobj_t grobj);

View File

@@ -569,10 +569,10 @@ extern const device_config_t nv3_config[];
#define NV3_PGRAPH_SRC_CANVAS_MAX 0x400554 // Maximum Source Canvas for Blit, Y=30:16, X=10:0
#define NV3_PGRAPH_DST_CANVAS_MIN 0x400558 // Minimum Destination Canvas for Blit, Y=30:16, X=10:0
#define NV3_PGRAPH_DST_CANVAS_MAX 0x40055C // Maximum Destination Canvas for Blit, Y=30:16, X=10:0
#define NV3_PGRAPH_pattern_color_0_rgb 0x400600
#define NV3_PGRAPH_pattern_color_0_alpha 0x400604
#define NV3_PGRAPH_pattern_color_1_rgb 0x400608
#define NV3_PGRAPH_pattern_color_1_alpha 0x40060C // pattern color
#define NV3_PGRAPH_PATTERN_COLOR_0_RGB 0x400600
#define NV3_PGRAPH_PATTERN_COLOR_0_ALPHA 0x400604
#define NV3_PGRAPH_PATTERN_COLOR_1_RGB 0x400608
#define NV3_PGRAPH_PATTERN_COLOR_1_ALPHA 0x40060C // pattern color
#define NV3_PGRAPH_PATTERN_BITMAP_HIGH 0x400610 // pattern bitmap [31:0]
#define NV3_PGRAPH_PATTERN_BITMAP_LOW 0x400614 // pattern bitmap [63:32]
#define NV3_PGRAPH_PATTERN_SHAPE 0x400618
@@ -1183,7 +1183,7 @@ typedef struct nv3_pgraph_s
uint64_t pattern_bitmap; // pattern bitmap for blit. it's alwaus 64 bits to simplify pixel rendering code
uint32_t pattern_shape; // may need to be an enum - 0=8x8, 1=64x1, 2=1x64
uint32_t plane_mask; // only 7:0 relevant
uint32_t chroma_key; // color key
uint32_t chroma_key; // color key
uint32_t beta_factor;
nv3_pgraph_dma_settings_t dma_settings;
uint8_t rop; // Current GDI Ternary Render Operation

View File

@@ -128,7 +128,9 @@ add_library(vid OBJECT
nv/nv3/classes/nv3_class_01c_image_in_memory.c
nv/nv3/render/nv3_render_core.c
nv/nv3/render/nv3_render_primitives.c
nv/nv3/render/nv3_render_primitives.c
nv/nv3/render/nv3_render_blit.c
)
if(G100)

View File

@@ -32,6 +32,22 @@ void nv3_class_010_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
{
switch (method_id)
{
case NV3_BLIT_POSITION_IN:
nv3->pgraph.blit.point_in.x = (param & 0xFFFF);
nv3->pgraph.blit.point_in.y = ((param >> 16) & 0xFFFF);
break;
case NV3_BLIT_POSITION_OUT:
nv3->pgraph.blit.point_out.x = (param & 0xFFFF);
nv3->pgraph.blit.point_out.y = ((param >> 16) & 0xFFFF);
break;
case NV3_BLIT_SIZE:
/* This is the last one*/
nv3->pgraph.blit.size.w = (param & 0xFFFF);
nv3->pgraph.blit.size.h = ((param >> 16) & 0xFFFF);
nv3_render_blit_screen2screen(grobj);
break;
default:
nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id);
nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_SOFTWARE_METHOD_PENDING);

View File

@@ -81,22 +81,22 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
//pixel3
pixel3 = param & 0xFF;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel3, grobj);
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;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel2, grobj);
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;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
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;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
@@ -104,12 +104,12 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
//2pixels packed into 1
case 16:
pixel1 = (param) & 0xFFFF;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel1, grobj);
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;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();
@@ -117,7 +117,7 @@ void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
// just one
case 32:
pixel0 = param;
nv3_render_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3_render_write_pixel(nv3->pgraph.image_current_position, pixel0, grobj);
nv3->pgraph.image_current_position.x++;
nv3_class_011_check_line_bounds();

View File

@@ -0,0 +1,92 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* NV3 Core rendering code (Software version)
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
*
* Copyright 2024-2025 Connor Hyde
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/plat.h>
#include <86box/rom.h>
#include <86box/video.h>
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_render_blit_screen2screen(nv3_grobj_t grobj)
{
nv3_position_16_t old_position = nv3->pgraph.blit.point_in;
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);
uint16_t end_y = (nv3->pgraph.blit.point_out.y + nv3->pgraph.blit.size.h);
/* Read the old pixel */
switch (nv3->nvbase.svga.bpp)
{
case 8: //8bpp
for (int32_t y = nv3->pgraph.blit.point_out.y; y < end_y; y++)
{
old_position.y++;
new_position.y++;
for (int32_t x = nv3->pgraph.blit.point_out.x; x < end_x; x++)
{
old_position.x++;
new_position.x++;
uint32_t pixel_to_copy = nv3_render_read_pixel_8(old_position, grobj) & 0xFF;
nv3_render_write_pixel(new_position, pixel_to_copy, grobj);
}
}
break;
case 16: //16bpp
for (int32_t y = nv3->pgraph.blit.point_out.y; y < end_y; y++)
{
old_position.y++;
new_position.y++;
for (int32_t x = nv3->pgraph.blit.point_out.x; x < end_x; x++)
{
old_position.x++;
new_position.x++;
uint32_t pixel_to_copy = nv3_render_read_pixel_16(old_position, grobj) & 0xFFFF;
nv3_render_write_pixel(new_position, pixel_to_copy, grobj);
}
}
break;
case 32: //32bpp
for (int32_t y = nv3->pgraph.blit.point_out.y; y < end_y; y++)
{
old_position.y++;
new_position.y++;
for (int32_t x = nv3->pgraph.blit.point_out.x; x < end_x; x++)
{
old_position.x++;
new_position.x++;
uint32_t pixel_to_copy = nv3_render_read_pixel_32(old_position, grobj);
nv3_render_write_pixel(new_position, pixel_to_copy, grobj);
}
}
break;
}
}

View File

@@ -194,13 +194,71 @@ uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool
nv3->pgraph.pattern_color_1_rgb.g = pattern_colour.g;
nv3->pgraph.pattern_color_1_rgb.b = pattern_colour.b;
}
}
/* /* Combine the current buffer with the pitch to get the address in the framebuffer to draw from for a given position. */
uint32_t nv3_render_get_vram_address(nv3_position_16_t position, nv3_grobj_t grobj)
{
uint32_t vram_x = position.x;
uint32_t current_buffer = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03;
uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp;
// we have to multiply the x position by the number of bytes per pixel
switch (framebuffer_bpp)
{
case 8:
break;
case 16:
vram_x = position.x << 1;
break;
case 32:
vram_x = position.x << 2;
break;
}
uint32_t pixel_addr_vram = vram_x + (nv3->pgraph.bpitch[current_buffer] * position.y) + nv3->pgraph.boffset[current_buffer];
pixel_addr_vram &= nv3->nvbase.svga.vram_mask;
return pixel_addr_vram;
}
/* Read an 8bpp pixel from the framebuffer. */
uint8_t nv3_render_read_pixel_8(nv3_position_16_t position, nv3_grobj_t grobj)
{
// hope you call it with the right bit
uint32_t vram_address = nv3_render_get_vram_address(position, grobj);
return nv3->nvbase.svga.vram[vram_address];
}
/* Read an 16bpp pixel from the framebuffer. */
uint16_t nv3_render_read_pixel_16(nv3_position_16_t position, nv3_grobj_t grobj)
{
// hope you call it with the right bit
uint32_t vram_address = nv3_render_get_vram_address(position, grobj);
uint16_t* vram_16 = (uint16_t*)(nv3->nvbase.svga.vram);
vram_address >>= 1; //convert to 16bit pointer
return vram_16[vram_address];
}
/* Read an 16bpp pixel from the framebuffer. */
uint32_t nv3_render_read_pixel_32(nv3_position_16_t position, nv3_grobj_t grobj)
{
// hope you call it with the right bit
uint32_t vram_address = nv3_render_get_vram_address(position, grobj);
uint32_t* vram_32 = (uint32_t*)(nv3->nvbase.svga.vram);
vram_address >>= 1; //convert to 16bit pointer
return vram_32[vram_address];
}
/* Plots a pixel. */
void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj)
void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj)
{
uint8_t alpha = 0xFF;
@@ -213,7 +271,7 @@ void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t gr
#endif
bool alpha_enabled = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_ALPHA) & 0x01;
uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp; // maybe y16 too?
uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp; // maybe y16 too?z
uint32_t current_buffer = (nv3->pgraph.context_switch >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03;
/* doesn't seem*/
@@ -238,26 +296,7 @@ void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t gr
/* TODO: Chroma Key, Pattern, Plane Mask...*/
/* Combine the current buffer with the pitch to get the address in the framebuffer to draw from. */
uint32_t vram_x = position.x;
// we have to multiply the x position by the number of bytes per pixel
switch (framebuffer_bpp)
{
case 8:
break;
case 16:
vram_x = position.x << 1;
break;
case 32:
vram_x = position.x << 2;
break;
}
uint32_t pixel_addr_vram = vram_x + (nv3->pgraph.bpitch[current_buffer] * position.y) + nv3->pgraph.boffset[current_buffer];
pixel_addr_vram &= nv3->nvbase.svga.vram_mask;
uint32_t pixel_addr_vram = nv3_render_get_vram_address(position, grobj);
uint32_t rop_src = 0, rop_dst = 0, rop_pattern = 0;
uint8_t bit = 0x00;

View File

@@ -40,7 +40,7 @@ void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t co
{
current_pos.x = x;
nv3_render_pixel(current_pos, color, grobj);
nv3_render_write_pixel(current_pos, color, grobj);
}
}
}

View File

@@ -63,10 +63,10 @@ nv_register_t pgraph_registers[] = {
{ NV3_PGRAPH_SRC_CANVAS_MAX, "PGRAPH Source Canvas Maximum Coordinates (Bits 30:16 = Y, Bits 10:0 = X)", NULL, NULL},
{ NV3_PGRAPH_DST_CANVAS_MIN, "PGRAPH Destination Canvas Minimum Coordinates (Bits 30:16 = Y, Bits 10:0 = X)", NULL, NULL},
{ NV3_PGRAPH_DST_CANVAS_MAX, "PGRAPH Destination Canvas Maximum Coordinates (Bits 30:16 = Y, Bits 10:0 = X)", NULL, NULL},
{ NV3_PGRAPH_pattern_color_0_rgb, "PGRAPH Pattern Color 0_0 (Bits 29:20 = Red, Bits 19:10 = Green, Bits 9:0 = Blue)", NULL, NULL, },
{ NV3_PGRAPH_pattern_color_0_alpha, "PGRAPH Pattern Color 0_1 (Bits 7:0 = Alpha)", NULL, NULL, },
{ NV3_PGRAPH_pattern_color_1_rgb, "PGRAPH Pattern Color 1_0 (Bits 29:20 = Red, Bits 19:10 = Green, Bits 9:0 = Blue)", NULL, NULL, },
{ NV3_PGRAPH_pattern_color_1_alpha, "PGRAPH Pattern Color 1_1 (Bits 7:0 = Alpha)", NULL, NULL, },
{ NV3_PGRAPH_PATTERN_COLOR_0_RGB, "PGRAPH Pattern Color 0_0 (Bits 29:20 = Red, Bits 19:10 = Green, Bits 9:0 = Blue)", NULL, NULL, },
{ NV3_PGRAPH_PATTERN_COLOR_0_ALPHA, "PGRAPH Pattern Color 0_1 (Bits 7:0 = Alpha)", NULL, NULL, },
{ NV3_PGRAPH_PATTERN_COLOR_1_RGB, "PGRAPH Pattern Color 1_0 (Bits 29:20 = Red, Bits 19:10 = Green, Bits 9:0 = Blue)", NULL, NULL, },
{ NV3_PGRAPH_PATTERN_COLOR_1_ALPHA, "PGRAPH Pattern Color 1_1 (Bits 7:0 = Alpha)", NULL, NULL, },
{ NV3_PGRAPH_PATTERN_BITMAP_HIGH, "PGRAPH Pattern Bitmap (High 32bits)", NULL, NULL},
{ NV3_PGRAPH_PATTERN_BITMAP_LOW, "PGRAPH Pattern Bitmap (Low 32bits)", NULL, NULL},
{ NV3_PGRAPH_PATTERN_SHAPE, "PGRAPH Pattern Shape (1:0 - 0=8x8, 1=64x1, 2=1x64)", NULL, NULL},
@@ -185,16 +185,16 @@ uint32_t nv3_pgraph_read(uint32_t address)
ret = *(uint32_t*)&nv3->pgraph.src_canvas_max;
break;
// Pattern
case NV3_PGRAPH_pattern_color_0_rgb:
case NV3_PGRAPH_PATTERN_COLOR_0_RGB:
ret = *(uint32_t*)&nv3->pgraph.pattern_color_0_rgb;
break;
case NV3_PGRAPH_pattern_color_0_alpha:
case NV3_PGRAPH_PATTERN_COLOR_0_ALPHA:
ret = *(uint32_t*)&nv3->pgraph.pattern_color_0_alpha;
break;
case NV3_PGRAPH_pattern_color_1_rgb:
case NV3_PGRAPH_PATTERN_COLOR_1_RGB:
ret = *(uint32_t*)&nv3->pgraph.pattern_color_1_rgb;
break;
case NV3_PGRAPH_pattern_color_1_alpha:
case NV3_PGRAPH_PATTERN_COLOR_1_ALPHA:
ret = *(uint32_t*)&nv3->pgraph.pattern_color_1_alpha;
break;
case NV3_PGRAPH_PATTERN_BITMAP_HIGH:
@@ -388,16 +388,16 @@ void nv3_pgraph_write(uint32_t address, uint32_t value)
*(uint32_t*)&nv3->pgraph.src_canvas_max = value;
break;
// Pattern
case NV3_PGRAPH_pattern_color_0_rgb:
case NV3_PGRAPH_PATTERN_COLOR_0_RGB:
*(uint32_t*)&nv3->pgraph.pattern_color_0_rgb = value;
break;
case NV3_PGRAPH_pattern_color_0_alpha:
case NV3_PGRAPH_PATTERN_COLOR_0_ALPHA:
*(uint32_t*)&nv3->pgraph.pattern_color_0_alpha = value;
break;
case NV3_PGRAPH_pattern_color_1_rgb:
case NV3_PGRAPH_PATTERN_COLOR_1_RGB:
*(uint32_t*)&nv3->pgraph.pattern_color_1_rgb = value;
break;
case NV3_PGRAPH_pattern_color_1_alpha:
case NV3_PGRAPH_PATTERN_COLOR_1_ALPHA:
*(uint32_t*)&nv3->pgraph.pattern_color_1_alpha = value;
break;
case NV3_PGRAPH_PATTERN_BITMAP_HIGH: