Rename name to param to represent that it is the parameter. Add pixel writing code, add rectangle rendering code. Implement ROP, Rectangle and Clip class methods. However, the drivers BSOD.

This commit is contained in:
starfrost013
2025-03-21 00:50:29 +00:00
parent 97e85efffb
commit 69c4b11f7b
32 changed files with 395 additions and 89 deletions

Binary file not shown.

View File

@@ -77,6 +77,19 @@ typedef enum nv3_pgraph_class_e
#define NV3_SET_NOTIFY_CONTEXT_FOR_DMA 0x0100 // Set object ctx for dma...see nv3_dma_context_t structure
#define NV3_SET_NOTIFY 0x0104
#define NV3_ROP_SET_ROP 0x0300 // Set GDI standard rop
#define NV3_CLIP_POSITION 0x0300 // S16:S16, 0=topleft
#define NV3_CLIP_SIZE 0x0304 // U16:U16
#define NV3_RECTANGLE_COLOR 0x0304
// 16 possible rectangles. 8 byte structure, first 4 bytes = position, second 2 = size.
#define NV3_RECTANGLE_START 0x0400
#define NV3_RECTANGLE_MAX 16
#define NV3_RECTNAGLE_END 0x0480
#define NV3_IMAGE_IN_MEMORY_COLOR_FORMAT 0x0300
#define NV3_IMAGE_IN_MEMORY_IN_MEMORY_DMA_CTX_TYPE 0x0304
#define NV3_IMAGE_IN_MEMORY_PITCH 0x0308
@@ -100,20 +113,59 @@ typedef struct nv3_class_ctx_switch_method_s
} nv3_class_ctx_switch_method_t;
/* 32-bit ARGB format colour for internal D3D5 stuff */
typedef struct nv3_color_argb_32_s
/*
enumerates color formats
there are some other colour formats that are only used in certain areas which are defined below
*/
typedef enum nv3_pgraph_pixel_format_e
{
nv3_pgraph_pixel_format_r5g5b5 = 0,
nv3_pgraph_pixel_format_r8g8b8 = 1,
nv3_pgraph_pixel_format_r10g10b10 = 2,
nv3_pgraph_pixel_format_y8 = 3,
nv3_pgraph_pixel_format_y16 = 4,
nv3_pgraph_pixel_format_v8y8u8y18 = 5, // "18"? NV wtf?
nv3_pgraph_pixel_format_y18v8y8u8 = 6, // "18"? NV wtf?
nv3_pgraph_pixel_format_y420 = 7, // YUV 420
} nv3_pgraph_pixel_format;
/* Main color format */
typedef struct nv3_color_expanded_s
{
uint8_t a;
/* WARNING: The internal format is 10-bit RGB! */
uint16_t r : 10;
uint16_t g : 10;
uint16_t b : 10;
// Indexed colour
union
{
uint16_t i16;
uint8_t i16_high;
uint8_t i8;
};
// the pixel format
nv3_pgraph_pixel_format pixel_format;
} nv3_color_expanded_t;
/* A simple ARGB format colour */
typedef struct nv3_color_argb_s
{
uint8_t a;
uint8_t r;
uint8_t g;
uint8_t b;
} nv3_color_argb_32_t;
} nv3_color_argb_t;
/* 30-bit colour format for internal PGRAPH use */
typedef struct nv3_color_x2a10g10b10_s
{
uint8_t reserved : 1;
bool alpha_if_chroma_key_otherwise_reserved2 : 1; // 1-bit ALPHA if chroma key, OTHERWISE USELESS and IGNORE
bool a : 1; // 1-bit ALPHA if chroma key, OTHERWISE USELESS and IGNORE
uint16_t r : 10;
uint16_t g : 10;
uint16_t b : 10;
@@ -150,17 +202,8 @@ typedef struct nv3_color_16_r5g6b5_s
/* Generic 16-bit position*/
typedef struct nv3_position_16_s
{
union
{
uint32_t pos;
struct
{
uint16_t y;
uint16_t x;
};
} position;
uint16_t y;
uint16_t x;
} nv3_position_16_t;
/* A big position format with 30:16 = y, 15:11 = nothing, 10:0 = x */
@@ -176,23 +219,14 @@ typedef struct nv3_position_16_bigy_s
/* Generic 16-bit size */
typedef struct nv3_size_16_s
{
union
{
uint32_t size;
struct
{
uint16_t h;
uint16_t w;
};
} size;
uint16_t h;
uint16_t w;
} nv3_size_16_t;
/* Generic 32-bit colour + 16-bit position */
typedef struct nv3_color_and_position_16_s
{
nv3_color_argb_32_t color;
nv3_color_expanded_t color;
nv3_position_16_t points;
} nv3_color_and_position_16_t;
@@ -355,7 +389,7 @@ typedef struct nv3_object_class_007
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_argb_32_t color; // The colour
uint32_t color; // The colour of the object.
uint8_t reserved3[0xF8];
nv3_position_16_t position[16];
nv3_size_16_t size[16];
@@ -366,7 +400,7 @@ typedef struct nv3_object_class_007
/* In case your points weren't colourful enough */
typedef struct nv3_object_class_008_cpoint_s
{
nv3_color_argb_32_t color; // argb-format 32-bit color
nv3_color_expanded_t color; // argb-format 32-bit color
nv3_position_16_t position; //
} nv3_object_class_008_cpoint_t;
@@ -382,7 +416,7 @@ typedef struct nv3_object_class_008
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_argb_32_t color; // argb?
nv3_color_expanded_t color; // argb?
nv3_position_16_t point[16]; // Boring points
nv3_position_32_t point32[16]; // Allows you to have points with full 32-bit precision
nv3_object_class_008_cpoint_t cpoint[16]; // Allows you to have c o l o r f u l points!
@@ -422,7 +456,7 @@ typedef struct nv3_object_class_009
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_argb_32_t color; // argb?
nv3_color_expanded_t color; // argb?
nv3_object_class_009_line_t line[16]; // List of line points (...)
nv3_object_class_009_line32_t line32[8];
nv3_object_class_009_line_t polyline[32];
@@ -446,7 +480,7 @@ typedef struct nv3_object_class_00A
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_argb_32_t color; // argb?
nv3_color_expanded_t color; // argb?
nv3_object_class_009_line_t line[16]; // List of line points (...)
nv3_object_class_009_line32_t line32[8];
nv3_object_class_009_line_t polyline[32];
@@ -469,7 +503,7 @@ typedef struct nv3_object_class_00B
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_argb_32_t color; // argb?
nv3_color_expanded_t color; // argb?
uint8_t reserved3[0x8];
// The points of the triangle.
nv3_position_16_t points[3];
@@ -639,7 +673,7 @@ typedef struct nv3_object_class_011
nv3_size_16_t size;
nv3_size_16_t size_in;
uint8_t reserved3[0xF0];
nv3_color_argb_32_t color[32]; // The colour to use
nv3_color_expanded_t color[32]; // The colour to use
uint8_t reserved4[0x1B7F];
} nv3_image_t;
@@ -657,8 +691,8 @@ typedef struct nv3_object_class_012
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x200];
nv3_color_argb_32_t color_0;
nv3_color_argb_32_t color_1;
nv3_color_expanded_t color_0;
nv3_color_expanded_t color_1;
nv3_position_16_t point; // Top left(?) of the bitmap
nv3_size_16_t size;
nv3_size_16_t size_in;
@@ -1074,7 +1108,7 @@ typedef struct nv3_d3d5_alpha_control_s
typedef struct nv3_d3d5_coordinate_s
{
nv3_d3d5_specular_t specular_reflection_parameters;
nv3_color_argb_32_t color; // YOU HAVE TO FLIP THE ENDIANNESS. NVIDIA??? WHAT???
nv3_color_expanded_t color; // YOU HAVE TO FLIP THE ENDIANNESS. NVIDIA??? WHAT???
// Seems more plausible for these specifically to be floats.
// Also makes my life easier...
@@ -1095,7 +1129,7 @@ typedef struct nv3_object_class_017
uint32_t texture_offset;
nv3_d3d5_texture_format_t texture_format;
nv3_d3d5_texture_filter_t texture_filter;
nv3_color_argb_32_t fog_color; // Alpha is ignored here!
nv3_color_expanded_t fog_color; // Alpha is ignored here!
nv3_d3d5_control_out_t control_out;
nv3_d3d5_alpha_control_t alpha_control;
@@ -1108,7 +1142,7 @@ typedef struct nv3_object_class_017
// Color and Zeta Buffer algorithm
typedef struct nv3_zeta_buffer_s
{
nv3_color_argb_32_t color;
nv3_color_expanded_t color;
uint32_t zeta; // 16 bits z, 8 bits stenciul
} nv3_zeta_buffer_t;

View File

@@ -17,3 +17,8 @@
#pragma once
/* Core */
void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj);
/* Primitives */
void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj);

View File

@@ -1127,7 +1127,8 @@ typedef struct nv3_pgraph_status_s
BPixel = Internal Binary Representation of the pixel within the architecture
*/
#define NV3_BPIXEL_FORMAT 0
#define NV3_BPIXEL_FORMAT_IS_VALID 2
#define NV3_BPIXEL_FORMAT_IS_VALID 2
#define NV3_BPIXEL_DEPTH 4
typedef enum nv3_pgraph_bpixel_format_e
{
@@ -1137,7 +1138,7 @@ typedef enum nv3_pgraph_bpixel_format_e
bpixel_fmt_8bit = 1,
// 16-bit colour
bpixel_fmt_16bit = 2,
// 32-bit colour (BGRA/ARGB)
// 32-bit colour (ARGB)
bpixel_fmt_32bit = 3,
} nv3_pgraph_bpixel_format;
@@ -1192,11 +1193,15 @@ typedef struct nv3_pgraph_s
nv3_pgraph_clip_misc_settings_t clip_misc_settings;
uint32_t notifier;
bool notify_pending; // Determines if a notification is pending.
/* Are these even used */
nv3_position_16_bigy_t clip0_min;
nv3_position_16_bigy_t clip0_max;
nv3_position_16_bigy_t clip1_min;
nv3_position_16_bigy_t clip1_max;
uint32_t fifo_access; // Determines if PGRAPH can access PFIFO.
/* idk */
nv3_position_16_t clip_start; // Start of the clipping region
nv3_position_16_t clip_size; // Size of the clipping region.
bool fifo_access; // Determines if PGRAPH can access PFIFO.
nv3_pgraph_status_t status; // Current status of the 3D engine.
uint32_t trapped_address;
uint32_t trapped_data;
@@ -1547,29 +1552,29 @@ void nv3_pgraph_submit(uint32_t param, uint16_t method, uint8_t channel,
// PGRAPH class methods
// this should be in "vid_nv3_classes.h", but before that can happen, some things need to be rejigged
void nv3_generic_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_001_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_002_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_003_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_004_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_005_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_006_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_007_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_008_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_009_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00a_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00b_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00c_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00d_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00e_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_010_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_011_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_012_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_014_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_015_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_017_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_018_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_01c_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_generic_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_001_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_002_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_003_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_004_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_005_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_006_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_007_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_008_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_009_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00a_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00b_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00d_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_00e_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_010_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_012_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_014_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_015_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_017_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_018_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
void nv3_class_01c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj);
// Notification Engine
void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t context,nv3_grobj_t grobj);

View File

@@ -17,4 +17,4 @@
/* ROP */
int32_t video_rop_gdi_ternary(int32_t rop, int32_t dst, int32_t pattern, int32_t src);
int32_t video_rop_gdi_ternary(int32_t rop, int32_t src, int32_t dst, int32_t pattern);

View File

@@ -10,7 +10,7 @@
This is currently used in the following graphics cards: Tseng Labs ET4000/32p, Cirrus Logic CL-GD54xx, 3dfx Voodoo Banshee/Voodoo 3, Trident TGUI9440,
S3 ViRGE, C&T 69000, ATI Mach64, and NVidia RIVA 128
*/
int32_t video_rop_gdi_ternary(int32_t rop, int32_t dst, int32_t pattern, int32_t src)
int32_t video_rop_gdi_ternary(int32_t rop, int32_t src, int32_t dst, int32_t pattern)
{
uint32_t out = 0x00;

View File

@@ -128,6 +128,7 @@ 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
)

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_001_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_001_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,10 +28,13 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_002_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_002_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{
case NV3_ROP_SET_ROP:
nv3->pgraph.rop = param & 0xFF;
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_INVALID_METHOD);

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_003_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_003_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_004_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_004_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -27,10 +27,20 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_005_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_005_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{
case NV3_CLIP_POSITION:
nv3->pgraph.clip_start.x = (param >> 16) & 0xFFFF;
nv3->pgraph.clip_start.y = (param) & 0xFFFF;
nv_log("Clip Position: %d,%d", nv3->pgraph.clip_start.x, nv3->pgraph.clip_start.y);
break;
case NV3_CLIP_SIZE:
nv3->pgraph.clip_size.x = (param >> 16) & 0xFFFF;
nv3->pgraph.clip_size.y = (param) & 0xFFFF;
nv_log("Clip Size: %d,%d", nv3->pgraph.clip_start.x, nv3->pgraph.clip_start.y);
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_INVALID_METHOD);

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_006_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_006_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,12 +28,41 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_007_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_007_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{
case NV3_RECTANGLE_COLOR:
nv3->pgraph.rectangle.color = param;
break;
default:
nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id);
/* Check for any rectangle point or size method. */
if (method_id >= NV3_RECTANGLE_START && method_id <= NV3_RECTNAGLE_END)
{
uint32_t index = (method_id - NV3_RECTANGLE_START) / 8;
// If the size is submitted, render it.
if (method_id & 0x04)
{
nv3->pgraph.rectangle.size[index].w = (param >> 16) & 0xFFFF;
nv3->pgraph.rectangle.size[index].h = param & 0xFFFF;
nv_log("Rect%d Size=%d,%d\n", index, nv3->pgraph.rectangle.size[index].w, nv3->pgraph.rectangle.size[index].h);
nv3_render_rect(nv3->pgraph.rectangle.position[index], nv3->pgraph.rectangle.size[index], nv3->pgraph.rectangle.color, grobj);
}
else // position
{
nv3->pgraph.rectangle.position[index].x = (param >> 16) & 0xFFFF;
nv3->pgraph.rectangle.position[index].y = param & 0xFFFF;
nv_log("Rect%d Position=%d,%d\n", index, nv3->pgraph.rectangle.position[index].x, nv3->pgraph.rectangle.position[index].y);
}
return;
}
nv_log("%s: Invalid or Unimplemented method 0x%04x\n", nv3_class_names[context.class_id & 0x1F], method_id);
nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_INVALID_METHOD);
return;
}

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_008_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_008_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_009_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_009_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -29,7 +29,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_00a_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_00a_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_00b_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_00b_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_00c_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_00d_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_00d_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_00e_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_00e_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_010_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_010_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_011_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -29,7 +29,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_012_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_012_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -29,7 +29,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_014_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_014_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_015_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_015_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -28,7 +28,7 @@
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
void nv3_class_017_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_017_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -30,7 +30,7 @@
struct nv3_object_class_018 nv3_d3d5_point_zeta_buffer;
void nv3_class_018_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
void nv3_class_018_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj)
{
switch (method_id)
{

View File

@@ -60,6 +60,7 @@ void nv3_class_01c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
/* Set the format */
nv3->pgraph.bpixel[src_buffer_id] = ((real_format & 0x03) | NV3_BPIXEL_FORMAT_IS_VALID);
nv_log("Image in Memory BUF%d COLOR_FORMAT=0x%04x", src_buffer_id, param);
break;

View File

@@ -157,6 +157,7 @@ void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t
/* send the notification off */
nv_log("About to send hardware notification to 0x%08x (Check target)\n", final_address);
switch (info_notification_target)
{
case NV3_NOTIFICATION_TARGET_NVM:

View File

@@ -35,3 +35,174 @@ uint32_t nv3_perform_rop(uint32_t src, uint32_t dst, uint32_t pattern, nv3_rende
return video_rop_gdi_ternary(rop, dst, pattern, src);
}
/* 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)
{
// grobj0 = seems to share the format of PGRAPH_CONTEXT_SWITCH register.
uint8_t format = (grobj.grobj_0 & 0x07);
bool alpha_enabled = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_ALPHA) & 0x01;
nv3_color_expanded_t color_final;
// set the pixel format
color_final.pixel_format = format;
#ifdef ENABLE_NV_LOG
nv_log("Expanding Colour 0x%08x using pgraph_pixel_format 0x%x alpha enabled=%d", color, format, alpha_enabled);
#endif
// default to fully opaque in case alpha is disabled
color_final.a = 0xFF;
switch (format)
{
// ALL OF THESE TYPES ARE 32 BITS IN SIZE
// 555
case nv3_pgraph_pixel_format_r5g5b5:
nv3_color_16_a1r5g5b5_t new_color = *(nv3_color_16_a1r5g5b5_t*)&color;
// "stretch out" the colour
color_final.r = new_color.r * 0x20;
color_final.g = new_color.g * 0x20;
color_final.b = new_color.b * 0x20;
if (alpha_enabled)
color_final.a = new_color.a;
break;
// 888 (standard colour + 8-bit alpha)
case nv3_pgraph_pixel_format_r8g8b8:
if (alpha_enabled)
color_final.a = ((color >> 24) & 0xFF) * 4;
color_final.r = ((color >> 16) & 0xFF) * 4;
color_final.g = ((color >> 8) & 0xFF) * 4;
color_final.b = (color & 0xFF) * 4;
if (alpha_enabled)
color_final.a = new_color.a;
break;
case nv3_pgraph_pixel_format_r10g10b10:
nv3_color_x2a10g10b10_t new_color_rgb10 = *(nv3_color_x2a10g10b10_t*)&color;
color_final.r = new_color_rgb10.r;
color_final.g = new_color_rgb10.g;
color_final.b = new_color_rgb10.b;
if (alpha_enabled)
color_final.a = new_color.a;
break;
case nv3_pgraph_pixel_format_y8:
color_final.a = (color >> 8) & 0xFF;
// yuv
color_final.r = color_final.g = color_final.b = (color & 0xFF) * 4; // convert to rgb10
break;
case nv3_pgraph_pixel_format_y16:
color_final.a = (color >> 16) & 0xFFFF;
// yuv
color_final.r = color_final.g = color_final.b = (color & 0xFFFF) * 4; // convert to rgb10
break;
default:
}
// i8 is a union under i16
color_final.i16 = (color & 0xFFFF);
return color_final;
}
/* Convert expanded colour format to chroma key format */
uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded)
{
// convert the alpha to 1 bit. then return packed rgb10
return !!expanded.a | (expanded.r << 30) | (expanded.b << 20) | (expanded.a << 10);
}
/* Plots a pixel. */
void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj)
{
uint8_t alpha = 0xFF;
// PFB_0 is always set to hardcoded "NO_TILING" value of 0x1114.
// It seems, you are meant to
/* put this here for debugging + it may be needed later. */
#ifdef DEBUG
uint8_t color_format_object = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_COLOR_FORMAT) & 0x07;
#endif
uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp; // maybe y16 too?
uint32_t current_buffer = (nv3->pgraph.context_switch >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03;
/* doesn't seem*/
nv3_color_argb_t color_data = *(nv3_color_argb_t*)&color;
if (framebuffer_bpp == 32)
alpha = color_data.a;
int32_t clip_end_x = nv3->pgraph.clip_start.x + nv3->pgraph.clip_size.x;
int32_t clip_end_y = nv3->pgraph.clip_start.y + nv3->pgraph.clip_size.y;
/* First, check our current buffer. */
/* Then do the clip. */
if (position.x < nv3->pgraph.clip_start.x
|| position.y < nv3->pgraph.clip_start.y
|| position.x > clip_end_x
|| position.y > clip_end_y)
{
// DO NOT DRAW THE PIXEL
return;
}
/* 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 pixel_addr_vram = position.x + (nv3->pgraph.bpitch[current_buffer]) * position.y + nv3->pgraph.boffset[current_buffer];
pixel_addr_vram &= nv3->nvbase.svga.vram_mask;
/* Go to vram and do the final ROP for a basic bitblit.
It seems we can skip the downconversion step *for now*, since (framebuffer bits per pixel) == (object bits per pixel)
I'm not sure how games will react. But it depends on how the D3D drivers operate, we may need ro convert texture formats to the current bpp internally.
TODO: MOVE TO BPIXEL DEPTH or GROBJ0 to determine this, once we figure out how to get the bpixel depth.
*/
uint32_t src = 0, dst = 0;
switch (framebuffer_bpp)
{
case 8:
src = color & 0xFF;
dst = nv3->nvbase.svga.vram[pixel_addr_vram];
nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00);
break;
case 16:
uint16_t* vram_16 = (uint16_t*)(nv3->nvbase.svga.vram);
pixel_addr_vram >>= 1;
src = color & 0xFFFF;
dst = vram_16[pixel_addr_vram];
nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00);
break;
case 32:
uint32_t* vram_32 = (uint32_t*)(nv3->nvbase.svga.vram);
pixel_addr_vram >>= 2;
src = color;
dst = vram_32[pixel_addr_vram];
nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00);
break;
}
nv3->nvbase.svga.changedvram[pixel_addr_vram >> 12] = changeframecount;
}

View File

@@ -0,0 +1,46 @@
/*
* 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 code to render basic objects.
*
*
*
* 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/rom.h>
#include <86box/video.h>
#include <86box/nv/vid_nv.h>
#include <86box/nv/vid_nv3.h>
#include <86box/utils/video_stdlib.h>
void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj)
{
nv3_position_16_t current_pos = {0};
for (int32_t y = position.y; y < (position.y + size.h); y++)
{
current_pos.y = y;
for (int32_t x = position.x; x < (position.x + size.w); x++)
{
current_pos.x = x;
nv3_render_pixel(current_pos, color, grobj);
}
}
}