Files
86Box/src/include/86box/nv/classes/vid_nv3_classes.h
2025-03-23 19:12:02 +00:00

1210 lines
37 KiB
C

/*
* 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.
*
* Defines graphics objects for Nvidia NV3 architecture-based GPU (RIVA 128/RIVA 128 ZX),
* as well as for later GPUs if they use the same objects.
* Note: These uint32_ts are basically object methods that are being submitted
* They have different names so the user can use them more easily but different versions of the same class can be distinguished
* ALL of these structures HAVE(?) to be a size of exactly 0x2000 bytes because that's what the hashtable expects and they need to actually map into the vram address space
* (they are converted to pointers). In the case of NV3, these map directly to the PHYSICAL PGRAPH REGISTERS while sitting in RAMHT!!!!.
*
* Also, these class IDs don't relate to the internal architecture of the GPU.
* Effectively, the NVIDIA drivers are faking shit. There are only 16 classes but the drivers recognise many more. See nv3_object_classes_driver.txt for the list of
* classes recognised by the driver.
* This is why the Class IDs you see here are not the same as you may see in other places.
*
* Todo: Is reserved* actually needed?
*
*
* Authors: Connor Hyde <mario64crashed@gmail.com>
*
* Copyright 2024-2025 Connor Hyde
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
// This is slower, but these need to map *****EXACTLY***** to the registers in PGRAPH,
// or everything FUCKS UP
//
// DO NOT REMOVE! DO NOT REMOVE! DO NOT REMOVE!
#pragma pack(push, 1)
// CLass names for debugging
extern const char* nv3_class_names[];
/* Defines valid classes. */
typedef enum nv3_pgraph_class_e
{
nv3_pgraph_class01_beta_factor = 0x01,
nv3_pgraph_class02_rop = 0x02,
nv3_pgraph_class03_chroma_key = 0x03,
nv3_pgraph_class04_plane_mask = 0x04,
nv3_pgraph_class05_clipping_rectangle = 0x05,
nv3_pgraph_class06_pattern = 0x06,
nv3_pgraph_class07_rectangle = 0x07,
nv3_pgraph_class08_point = 0x08,
nv3_pgraph_class09_line = 0x09,
nv3_pgraph_class0a_lin = 0x0a,
nv3_pgraph_class0b_triangle = 0x0b,
nv3_pgraph_class0c_w95txt = 0x0c,
nv3_pgraph_class0d_m2mf = 0x0d,
nv3_pgraph_class0e_scaled_image_from_memory = 0x0e,
nv3_pgraph_class10_blit = 0x10,
nv3_pgraph_class11_image = 0x11,
nv3_pgraph_class12_bitmap = 0x12,
nv3_pgraph_class14_transfer2memory = 0x14,
nv3_pgraph_class15_stretched_image_from_cpu = 0x15,
nv3_pgraph_class17_d3d5tri_zeta_buffer = 0x17,
nv3_pgraph_class18_point_zeta_buffer = 0x18,
nv3_pgraph_class1c_image_in_memory = 0x1c,
} nv3_pgraph_class;
/*
OBJECT METHODS
*/
// Global stuff
#define NV3_ROOT_HI_IM_OBJECT_MCOBJECTYFACE 0x0 // I'm going insane at 00:48 14/02/2025
#define NV3_SET_NOTIFY_CONTEXT_FOR_DMA 0x0100 // Set object ctx for dma...see nv3_dma_context_t structure
#define NV3_SET_NOTIFY 0x0104
// Render OPeration
#define NV3_ROP_SET_ROP 0x0300 // Set GDI standard rop
// Beta Factor
#define NV3_BETA_FACTOR 0x0300
// Chroma Key
#define NV3_CHROMA_KEY 0x0304
// Clip
#define NV3_CLIP_POSITION 0x0300 // S16:S16, 0=topleft
#define NV3_CLIP_SIZE 0x0304 // U16:U16
// Blit Pattern
#define NV3_PATTERN_FORMAT 0x0304
#define NV3_PATTERN_SHAPE 0x0308
#define NV3_PATTERN_SHAPE_8X8 0
#define NV3_PATTERN_SHAPE_64X1 1
#define NV3_PATTERN_SHAPE_1X64 2
#define NV3_PATTERN_SHAPE_LAST_VALID NV3_PATTERN_SHAPE_1X64
#define NV3_PATTERN_COLOR0 0x0310
#define NV3_PATTERN_COLOR1 0x0314
#define NV3_PATTERN_BITMAP_HIGH 0x0318
#define NV3_PATTERN_BITMAP_LOW 0x031C
// Rect
#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_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
#define NV3_IMAGE_SIZE_IN 0x030C
#define NV3_IMAGE_COLOR_START 0x0400
#define NV3_IMAGE_COLOR_MAX 32
#define NV3_IMAGE_COLOR_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
#define NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET 0x030C
#define NV3_IMAGE_IN_MEMORY_TOP_LEFT_OFFSET_END 22
#define NV3_W95TXT_COLORA 0x03FC // It's the colour of the text. This is used to submit a dummy object so the notifier can be used to sync in Win2000 DDraw6 drivers.
/* Class context switch method */
typedef struct nv3_class_ctx_switch_method_s
{
union
{
uint32_t data;
uint16_t instance;
uint8_t channel : 6;
uint16_t reserved : 9;
bool reset_if_volatile; // ????
} set_notify_ctx_dma; // Set notifier context for DMA (context switch)
} nv3_class_ctx_switch_method_t;
/*
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_t;
/* Generic 16-bit position*/
typedef struct nv3_position_16_s
{
uint16_t y;
uint16_t x;
} nv3_position_16_t;
/* A big position format with 30:16 = y, 15:11 = nothing, 10:0 = x */
typedef struct nv3_position_16_bigy_s
{
// WHOSE IDEA WAS THIS?
uint16_t x : 11;
uint8_t reserved : 5;
uint16_t y : 15;
bool reserved2 : 1;
} nv3_position_16_bigy_t;
/* Generic 16-bit size */
typedef struct nv3_size_16_s
{
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_expanded_t color;
nv3_position_16_t points;
} nv3_color_and_position_16_t;
/* Generic 16-bit clip region */
typedef struct nv3_clip_16_s
{
// The bounds of the clipping area.
uint16_t left;
uint16_t top;
uint16_t right;
uint16_t bottom;
} nv3_clip_16_t;
/* In case your positions weren't HIGH PRECISION enough */
typedef struct nv3_position_32_s
{
uint32_t x;
uint32_t y;
} nv3_position_32_t;
// COLOUR FORMATS
/*
Object Class 0x01 (real hardware, also 0x41)
0x12 (drivers)
Beta factor
*/
typedef struct nv3_object_class_001
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100]; // Required for NV_CLASS Core Functionality
uint32_t set_notify;
uint8_t reserved2[0x1F8];
uint8_t set_beta_factor_1d31; // 31:31 (?) value, 30:21 fraction
uint8_t reserved3[0x1CFB]; // needs to be 0x2000 bytes
// Put the rest of it here
} nv3_beta_factor_t;
/* Note: This is not used in the class, there are "special" rops that do certain things. So they need to be defined for code readability. It all gets optimised away
by the compiler anyway */
typedef enum nv3_render_operation_type_e
{
// Black
nv3_rop_blackness = 0x00,
// dst = !src
nv3_rop_dstinvert = 0x55,
// pattern invert
nv3_rop_patinvert = 0x5A,
// src ^ dst
nv3_rop_xor = 0x66,
// src & dst
nv3_rop_srcand = 0x88,
// dst = src (?)
nv3_rop_dstcopy = 0xAA,
// src = dst (?)
nv3_rop_srccopy = 0xCC,
// paint source
nv3_rop_srcpaint = 0xEE,
// pattern copy
nv3_rop_patcopy = 0xF0,
// White
nv3_rop_whiteness = 0xFF,
} nv3_render_operation_type;
/*
Object class 0x02 (real hardware)
0x14/0x43 (drivers)
Also 0x42 in context IDs
Render operation used for things like blending. Appears to be 8-bit i.e. a ROP3 with 256 possible operations.
*/
typedef struct nv3_object_class_002
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1F8];
uint8_t rop; // ROP3 (ID = ????????)
uint8_t reserved3[0x1CFB]; // needs to be 0x2000 bytes
} nv3_render_operation_t;
/*
Object class 0x03 (real hardware)
0x15 (drivers)
Also 0x43 in context IDs
A chroma/color key, like in video editing
*/
typedef struct nv3_object_class_003
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1F8];
uint8_t color; // ROP3 (ID = ????????)
uint8_t reserved3[0x1CFB]; // needs to be 0x2000 bytes
} nv3_chroma_key_t;
/*
Object class 0x04 (real hardware)
0x15 (drivers)
Also 0x44 in context IDs
Plane mask
*/
typedef struct nv3_object_class_004
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1F8];
uint8_t color; // ROP3 (ID = ????????)
uint8_t reserved3[0x1CFB]; // needs to be 0x2000 bytes
} nv3_plane_mask_t;
/*
Object class 0x05 (real hardware)
0x19/0x1E/0x47 (drivers)
Also 0x45 in context IDs
Clipping rectangle used for various blitting operations
*/
typedef struct nv3_object_class_005
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0X100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1F4];
/* 16-bit precision */
nv3_position_16_t position;
nv3_size_16_t size;
uint8_t reserved3[0x1CFB]; // needs to be 0x2000 bytes
} nv3_clipping_rectangle_t;
/*
Object Class 0x06 (real hardware)
0x?? (drivers)
Also 0x46 in context IDs
A pattern used for blits. Wahey!
*/
typedef struct nv3_object_class_006
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x200];
uint32_t shape; // 0 = 8x8, 1 = 64x1, 2 = 1x64
uint32_t color0; // Some 32-bit format (argb?)
uint32_t color1; // bit0=color0, bit1=color1
uint32_t pattern[2]; // bit0=color0, bit1=color1
uint8_t reserved3[0x1CDF]; // needs to be 0x2000 bytes
} nv3_pattern_t;
/*
Object Class 0x07 (real hardware)
0x1E (drivers)
Also 0x47 in context IDs
A rectangle. Wahey!
*/
typedef struct nv3_object_class_007
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
uint32_t color; // The colour of the object.
uint8_t reserved3[0xF8];
nv3_position_16_t position[16];
nv3_size_16_t size[16];
uint8_t reserved4[0x1B7F];
} nv3_rectangle_t;
/* In case your points weren't colourful enough */
typedef struct nv3_object_class_008_cpoint_s
{
nv3_color_expanded_t color; // argb-format 32-bit color
nv3_position_16_t position; //
} nv3_object_class_008_cpoint_t;
/*
Object Class 0x08 (real hardware)
0x1A (drivers)
Also 0x48 in context IDs
A point: the revolutionary 3d graphics technique...
*/
typedef struct nv3_object_class_008
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
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!
uint8_t reserved3[0x1A7B];
} nv3_point_t;
/* Normal line... */
typedef struct nv3_object_class_009_line_s
{
nv3_position_16_t start; // presumably unless it's in reverse order...TODO: check the order
nv3_position_16_t end;
} nv3_object_class_009_line_t;
/* THIRTY TWO BIT PRECISION line */
typedef struct nv3_object_class_009_line32_s
{
uint32_t x0;
uint32_t x1;
uint32_t y0;
uint32_t y1;
} nv3_object_class_009_line32_t;
/* nv3_object_class_009_polyline_t not implemented because it's just a duplicate of nv3_object_class_009_line */
/* nv3_object_class_009_polyline32_t not implemented because it's just a duplicate of nv3_object_class_009_line32 */
/*
Object Class 0x09 (real hardware)
0x1B (drivers)
Also 0x49 in context IDs
It's a line, but also a polygon...
*/
typedef struct nv3_object_class_009
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
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];
nv3_object_class_009_line32_t polyline32[16];
nv3_color_and_position_16_t cpolyline[16]; // List of line points and colours.
uint8_t reserved3[0x197b];
} nv3_line_t;
/*
Object Class 0x0A (real hardware)
0x1c (drivers)
Also 0x4a in context IDs
This one is where nvidia reinvents the line, but without the starting or ending pixel.
Seriously.
*/
typedef struct nv3_object_class_00A
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
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];
nv3_object_class_009_line32_t polyline32[16];
nv3_color_and_position_16_t cpolyline[16]; // List of line points and colours.
uint8_t reserved3[0x197b];
} nv3_lin_t;
/*
Object Class 0x0B (real hardware)
0x?? (drivers)
Also 0x4b in context IDs.
This is a triangle but seems to be obsolete. It's replaced with UD3D0Z / D3D5 Accelerated Triangle with Zeta Buffer. Does it even exist?
*/
typedef struct nv3_object_class_00B
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
nv3_color_expanded_t color; // argb?
uint8_t reserved3[0x8];
// The points of the triangle.
nv3_position_16_t points[3];
// Another way of filling out the points of the triangle
uint32_t x0;
uint32_t y0;
uint32_t x1;
uint32_t y1;
uint32_t y2;
uint32_t x2;
nv3_position_16_t mesh[32]; // Some kind of mesh format. I guess a list of vertex positions?
nv3_position_32_t mesh32[16];
nv3_color_and_position_16_t ctriangle[3]; // Triangle with colour
nv3_color_and_position_16_t ctrimesh[16]; // Some kind of mesh format. I guess a list of vertex positions? with colours
uint8_t reserved4[0x19FB];
} nv3_triangle_t;
typedef struct nv3_object_class_00C_nclip_s
{
nv3_position_16_t position;
nv3_size_16_t size;
} nv3_object_class_00C_nclip_t;
/*
Object Class 0x0C (real hardware)
0x0C (drivers)
Also 0x4C in context IDs.
GDI text acceleration for Windows 95.
How the fuck does this even work?
*/
typedef struct nv3_object_class_00C
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x2F4];
uint32_t color_a; // Color for Clip A
nv3_object_class_00C_nclip_t rect_nclip[64];
uint8_t reserved3[0x1F0];
nv3_clip_16_t clip_b;
uint32_t color_b; // Color for Clip B
nv3_clip_16_t rect_clip[64];
uint8_t reserved4[0x1E8];
nv3_clip_16_t clip_c;
uint32_t color1_c;
nv3_size_16_t size_c;
nv3_position_16_t point_c;
uint32_t color1_c_bitmap[128];
uint8_t reserved5[0x368];
nv3_clip_16_t clip_d;
uint32_t color1_d;
nv3_size_16_t size_in_d;
nv3_size_16_t size_out_d;
nv3_position_16_t point_d;
uint32_t mono_color1_d[128];
uint8_t reserved6[0x364];
nv3_clip_16_t clip_e;
uint32_t color0_e;
uint32_t color1_e;
nv3_size_16_t size_in_e;
nv3_size_16_t size_out_e;
nv3_position_16_t point_e;
uint32_t mono_color1_e[128];
uint8_t reserved7[0xB7F];
} nv3_win95_text_t;
/*
Object Class 0x0D (real hardware)
0x?? (drivers)
Also 0x4D in context IDs.
Represents reformatting of an image in memory.
*/
typedef struct nv3_object_class_00D
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x204];
uint32_t offset_in;
uint32_t offset_out;
uint32_t pitch_in;
uint32_t pitch_out;
uint32_t line_length_in; // Stride?
uint32_t line_count;
uint8_t format_input_bits; // 1 2 or 4 to increment by bits
uint8_t format_output_bits; // 1 2 to 4 to increment by bits
uint8_t reserved3[2];
uint32_t buffer_notify; // Notify the Buffedr
uint8_t reserved4[0x1CD3];
} nv3_memory_to_memory_format_t;
/*
Object Class 0x0E (real hardware)
0x?? (drivers)
Also 0x4E in context IDs.
Represents a scaled image coming from memory.
*/
typedef struct nv3_object_class_00E
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x200];
nv3_position_16_t clip_0;
nv3_size_16_t clip_1;
nv3_position_16_t rectangle_out_0;
nv3_size_16_t rectangle_out_1;
// Calculus in a graphics card
uint32_t delta_du_dx;
uint32_t delta_dv_dy;
uint8_t reserved3[0xE0];
nv3_size_16_t size; // can be size_y if YUV420
uint32_t pitch;
uint32_t offset;
uint32_t point;
// YUV420 stuff
uint32_t pitch_yuv420;
uint32_t offset_y;
uint32_t offset_u;
uint32_t offset_v;
uint32_t point_yuv420;
uint8_t reserved4[0x1BE7]; // pad to 0x2000
} nv3_scaled_image_from_memory_t;
// (0x0F does not exist)
/*
Object Class 0x10 (real hardware)
0x?? (drivers)
Also 0x50 in context IDs.
Represents a blit.
*/
typedef struct nv3_object_class_010
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x1F8];
nv3_position_16_t point_in;
nv3_position_16_t point_out;
nv3_size_16_t size;
uint8_t reserved3[0x1CF3];
} nv3_blit_t;
/*
Object Class 0x11 (real hardware)
0x?? (drivers)
Also 0x51 in context IDs.
Represents an image from the cpu (i guess from system memory)
*/
typedef struct nv3_object_class_011
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x1FC];
nv3_position_16_t point;
nv3_size_16_t size;
nv3_size_16_t size_in;
uint8_t reserved3[0xF0];
nv3_color_expanded_t color[32]; // The colour to use
uint8_t reserved4[0x1B7F];
} nv3_image_t;
/*
Object Class 0x12 (real hardware)
0x?? (drivers)
Also 0x52 in context IDs.
Bitmap from CPU.
It seems the difference is that an image is colour but a
*/
typedef struct nv3_object_class_012
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x200];
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;
uint32_t monochrome_bitmap[32];
uint8_t reserved4[0x1B7F];
} nv3_bitmap_t;
// 0x13 doesn't exist
/*
Object Class 0x14 (real hardware)
0x?? (drivers)
Also 0x54 in context IDs.
Image Transfer to Memory
It seems the difference is that an image is colour but a bitmap is b&w
*/
typedef struct nv3_object_class_014
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x200];
nv3_position_16_t point;
nv3_size_16_t size;
uint32_t image_pitch; // bytes per row
uint32_t image_start;
uint8_t reserved3[0x1C37];
} nv3_image_to_memory_t;
/*
Object Class 0x15 (real hardware)
0x?? (drivers)
Also 0x55 in context IDs.
Stretched Image from CPU
Seems to be, by the very large color array, the main class used in 2d acceleration.
*/
typedef struct nv3_object_class_015
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x1FC];
nv3_size_16_t size_in;
uint32_t delta_dx_du;
uint32_t delta_dy_dv;
nv3_position_16_t clip_0;
nv3_size_16_t clip_1;
uint32_t point12d4; /* todo: fraction struct */
uint8_t reserved3[0xE4];
uint32_t color[1792];
// no reserve needed
} nv3_stretched_image_from_cpu_t;
// 0x16 invalid
/*
Object Class 0x17 (real hardware)
0x?? (drivers)
Also 0x57 in context IDs.
Direct3D 5.0 accelerated triangle with zeta buffer (combined z buffer and stencil buffer)
This is the final boss of this GPU. True horror stands below.
*/
//
// NV3 D3D5: TEXTURING & PIXEL FORMATS
//
typedef enum nv3_d3d5_texture_pixel_format_e
{
/*
16-Bit Pixel Format
5 bits red, 5 bits green, 5 bits alpha, "boolean" alpha
*/
nv3_d3d5_pixel_format_le_a1r5g5b5 = 0,
/*
15-Bit Pixel Format (represented as 16)
1 bit irrelevant, 5 bits red, 5 bits green, 5 bits alpha
*/
nv3_d3d5_pixel_format_le_x1r5g5b5 = 1,
/*
16-Bit Pixel Format
4 bits alpha, 4 bits red, 4 bits green, 4 bits blue
*/
nv3_d3d5_pixel_format_le_a4r4g4b4 = 2,
/*
16-Bit Pixel Format
5 bits red, 6 bits green, 5 bits blue
(Required nv3tweak...)
*/
nv3_d3d5_pixel_format_le_r5g6b5 = 3,
} nv3_d3d5_texture_pixel_format;
/* Output format
The output pixel format...I
*/
typedef enum nv3_d3d5_output_pixel_format_e
{
/*
32-Bit Pixel Format
8 bits irrelevant, 8 bits red, 8 bits green, 8 bits blue
*/
nv3_d3d5_output_pixel_format_le_x8r8g8b8 = 0,
/*
32-Bit Pixel Format
8 bits irrelevant, 8 bits red, 8 bits green, 8 bits blue
Is this even used?? The riva can't even do 32 bit colour in 3d...
*/
nv3_d3d5_output_pixel_format_le_a8r8g8b8 = 1,
} nv3_d3d5_output_pixel_format;
/* Texture size
NOTE: ONLY 256X256 OR LOWER ARE SUPPORTED! 2048X2048X16 TAKES UP ENTIRE VRAM OF RIVA 128 ZX...
I ASSUME THESE ARE INTERNALLY SCALED DOWN
*/
typedef enum nv3_d3d5_texture_size_e
{
nv3_d3d5_texture_size_1x1 = 0,
nv3_d3d5_texture_size_2x2 = 1,
nv3_d3d5_texture_size_4x4 = 2,
nv3_d3d5_texture_size_8x8 = 3,
nv3_d3d5_texture_size_16x16 = 4,
nv3_d3d5_texture_size_32x32 = 5,
nv3_d3d5_texture_size_64x64 = 6,
nv3_d3d5_texture_size_128x128 = 7,
// Highest size supported natively by hardware?
nv3_d3d5_texture_size_256x256 = 8,
nv3_d3d5_texture_size_512x512 = 9,
nv3_d3d5_texture_size_1024x1024 = 10,
nv3_d3d5_texture_size_2048x2048 = 11,
} nv3_d3d5_texture_size;
/* Texture Wrapping Mode for U/V Coordinate Overflow
*/
typedef enum nv3_d3d5_texture_wrap_mode_e
{
// Map textures in a cylindrical fashion.
nv3_d3d5_texture_wrap_mode_cylindrical = 0,
// Simply wrap back to the start.
nv3_d3d5_texture_wrap_mode_wrap = 1,
// Mirror the texture.
nv3_d3d5_texture_wrap_mode_mirror = 2,
// Clamp to the last border pixel.
nv3_d3d5_texture_wrap_mode_clamp = 3,
} nv3_d3d5_texture_wrap_mode;
/* This is blending but isn't really considered to be it in the GPU for some reason
What do we do with out input texel BEFORE processing it?
*/
typedef enum nv3_d3d5_dest_color_interpretation_e
{
// Do nothing
nv3_d3d5_source_color_normal = 0,
// Invert Colour
nv3_d3d5_source_color_inverse = 1,
// Invert Alpha before Processing
nv3_d3d5_source_color_alpha_inverse = 2,
// Take Alpha as 1
nv3_d3d5_source_color_alpha_one = 3,
} nv3_d3d5_dest_color_interpretation;
// The full texture format structure
typedef struct nv3_d3d5_texture_format_s
{
uint16_t color_key_color_mask;
bool color_key_enabled : 1;
nv3_d3d5_texture_pixel_format color_format : 2;
nv3_d3d5_texture_size size_min : 4;
nv3_d3d5_texture_size size_max : 4;
} nv3_d3d5_texture_format_t;
//
// NV3 D3D5: INTERPOLATION
//
/*
??????
Interpolating between mip levels? (or for texture blending)
*/
typedef enum nv3_d3d5_interpolator_algorithm_e
{
// Zero-order hold interpolation?
nv3_d3d5_interpolator_zoh = 0,
// Zero-order hold (microsoft variant)?
nv3_d3d5_interpolator_zoh_ms = 1,
// Full-order hold interpolation?
nv3_d3d5_interpolator_foh = 2,
} nv3_d3d5_interpolator_algorithm;
//
// NV3 D3D5: Z-BUFFER
//
/* Probably the sorting algorithm */
typedef enum nv3_d3d5_zbuffer_type_e
{
// Sort based on linear distance
nv3_d3d5_zbuffer_linear = 0,
// Sort based on distance from view frustum
nv3_d3d5_zbuffer_screen = 1,
} nv3_d3d5_zbuffer_type;
// NV3 D3D5: WRITE CONTROL (SHARED BETWEEN ZETA BUFFER AND ALPHA)
typedef enum nv3_d3d5_buffer_write_control_e
{
// Never write.
nv3_d3d5_buffer_write_control_never = 0,
// Only write the alpha.
nv3_d3d5_buffer_write_control_alpha = 1,
// Write both alpha and the zeta-buffer.
nv3_d3d5_buffer_write_control_alpha_zeta = 2,
// Write only the zeta-buffer
nv3_d3d5_buffer_write_control_zeta = 3,
// Write everything (alpha+z+zeta?)
nv3_d3d5_buffer_write_control_always = 4,
} nv3_d3d5_buffer_write_control;
//
// NV3 D3D5: BUFFER COMPARISON (SHARED BETWEEN ZETA BUFFER AND ALPHA CONTROL)
//
// Todo: Which direction? (i.e. is less than p1 < p2 or p2 < p1!)
typedef enum nv3_d3d5_buffer_comparison_type_e
{
// !!!ILLEGAL COMPARISON TYPE!!!!
nv3_d3d5_buffer_comparison_illegal = 0,
// The (depth?) test always fails.
nv3_d3d5_buffer_comparison_always_false = 1,
// True if less than fail.
nv3_d3d5_buffer_comparison_less_than = 2,
// The test succeeds if equal.
nv3_d3d5_buffer_comparison_equal = 3,
// The test succeeds if less or equal.
nv3_d3d5_buffer_comparison_less_or_equal = 4,
// The test succeeds if greater.
nv3_d3d5_buffer_comparison_greater = 5,
// The test succeeds if the two elements are equal.
nv3_d3d5_buffer_comparison_not_equal = 6,
// The test succeeds if greater or equal
nv3_d3d5_buffer_comparison_greater_or_equal = 7,
// The test always succeeds.
nv3_d3d5_buffer_comparison_always_true = 8,
} nv3_d3d5_buffer_comparison_type;
//
// NV3 D3D5: BLENDING
//
/* Render Operation for Blending */
typedef enum nv3_d3d5_blend_render_operation_e
{
nv3_d3d5_blend_render_operation_and = 0,
nv3_d3d5_blend_add_with_saturation = 1,
} nv3_d3d5_blend_render_operation;
typedef enum nv3_d3d5_blend_beta_factor_e
{
nv3_d3d5_blend_beta_factor_srcalpha = 0,
nv3_d3d5_blend_beta_factor_zero = 1,
} nv3_d3d5_blend_beta_factor;
typedef enum nv3_d3d5_blend_input0_e
{
nv3_d3d5_blend_input0_srcalpha = 0,
nv3_d3d5_blend_input0_zero = 1,
} nv3_d3d5_blend_input0;
typedef enum nv3_d3d5_blend_input1_e
{
nv3_d3d5_blend_input1_destalpha = 0,
nv3_d3d5_blend_input1_zero = 1,
} nv3_d3d5_blend_input1;
//
// NV3 D3D5: CULLING
//
typedef enum nv3_d3d5_culling_algorithm_e
{
// Don't cull
nv3_d3d5_culling_algorithm_none = 0,
// Cull Clockwise around view frustum?
nv3_d3d5_culling_algorithm_clockwise = 1,
// Cull counterclockwise around view frustum?
nv3_d3d5_culling_algorithm_counterclockwise = 2,
} nv3_d3d5_culling_algorithm;
/* Specular reflection parameters */
typedef struct nv3_d3d5_specular_s
{
uint8_t i0 : 4;
uint8_t i1 : 4;
uint8_t i2 : 4;
uint8_t i3 : 4;
uint8_t i4 : 4;
uint8_t i5 : 4;
uint8_t fog; //table fog emulation?
} nv3_d3d5_specular_t;
//
// NV3 D3D5: MISC
//
typedef struct nv3_d3d5_texture_filter_s
{
uint8_t spread_x;
uint8_t spread_y;
uint8_t mipmap;
uint8_t turbo;
} nv3_d3d5_texture_filter_t;
//
// NV3 D3D5: OUTPUT CONTROL STRUCTURE
//
/* Output Control for D3D5 Triangles */
typedef struct nv3_d3d5_control_out_s
{
nv3_d3d5_interpolator_algorithm ctrl_out_interpolator : 2;
uint8_t reserved : 2;
nv3_d3d5_texture_wrap_mode wrap_u : 2; // Controls wrapping mode of U texture coordinate
nv3_d3d5_texture_wrap_mode wrap_v : 2; // Controls wrapping move of V texture coordinate
nv3_d3d5_output_pixel_format output_pixel_format : 1;
bool reserved2 : 1;
nv3_d3d5_dest_color_interpretation dest_color_interpretation : 2;
nv3_d3d5_culling_algorithm culling_algorithm : 2;
bool reserved3 : 1;
nv3_d3d5_zbuffer_type zbuffer_type : 1;
nv3_d3d5_buffer_comparison_type zeta_buffer_compare : 4;
nv3_d3d5_buffer_write_control zeta_write : 3;
bool reserved4 : 1;
nv3_d3d5_buffer_write_control color_write : 3;
bool reserved5 : 1;
nv3_d3d5_blend_render_operation blend_rop : 1;
nv3_d3d5_blend_input0 blend_input0 : 1;
nv3_d3d5_blend_input1 blend_input1 : 1;
} nv3_d3d5_control_out_t;
typedef struct nv3_d3d5_alpha_control_s
{
uint8_t alpha_key;
nv3_d3d5_buffer_comparison_type zeta_buffer_compare : 4;
uint32_t reserved : 20;
} nv3_d3d5_alpha_control_t;
//
// NV3 D3D5: Triangle Coordinates
//
typedef struct nv3_d3d5_coordinate_s
{
nv3_d3d5_specular_t specular_reflection_parameters;
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...
float x; // X coordinate in 3d space of the triangle
float y; // Y coordinate in 3d space of the triangle
float z; // Z coordinate in 3d space of the triangle
float m; // 1/W for projection
float u; // U coordinate within texture for the (top left?) of the triangle where sampling starts.
float v; // V coordinate within texture for the (top left?) of the triangle where sampling starts.
} nv3_d3d5_coordinate_t;
typedef struct nv3_object_class_017
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1FC];
uint32_t texture_offset;
nv3_d3d5_texture_format_t texture_format;
nv3_d3d5_texture_filter_t texture_filter;
nv3_color_expanded_t fog_color; // Alpha is ignored here!
nv3_d3d5_control_out_t control_out;
nv3_d3d5_alpha_control_t alpha_control;
uint8_t reserved3[0xCE4];
nv3_d3d5_coordinate_t coordinate_points[128]; // The points we are rendering.
/* No placeholder needed, it really is that long. */
} nv3_d3d5_accelerated_triangle_with_zeta_buffer_t;
// Color and Zeta Buffer algorithm
typedef struct nv3_zeta_buffer_s
{
nv3_color_expanded_t color;
uint32_t zeta; // 16 bits z, 8 bits stenciul
} nv3_zeta_buffer_t;
typedef struct nv3_object_class_018
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma;
uint8_t reserved[0x100];
uint32_t set_notify;
uint8_t reserved2[0x1FC];
nv3_d3d5_control_out_t control_out;
nv3_d3d5_alpha_control_t alpha_control;
uint8_t reserved3[0x4F0];
nv3_position_16_t point;
nv3_zeta_buffer_t zeta[8];
} nv3_point_with_zeta_buffer_t;
/* 0x19, 0x1A, 0x1B don't exist */
/* WHY IS THE FORMAT DIFFERENT TO THE REST OF THE GPU?
They are making it look like a bitfield but it's hex?
THEY ARE ALL LITTLE ENDIAN
*/
typedef enum nv3_object_class_01C_pixel_format_e
{
// Y8P4
// 12-bits (Y8 - Planar YUV 8 bits (Y value only), 4 bits of indexed colour too?
nv3_image_in_memory_pixel_format_le_y8_p4 = 0x1010000,
// Y16P2
// 16-bits (Y16) - Planar YUV 16 bits (Y value only), 2 bits of indexed colour too?
nv3_image_in_memory_pixel_format_le_y16_p2 = 0x1010101,
/* 1 unused bit, 555 15-bit format, p2(?) */
nv3_image_in_memory_pixel_format_x1r5g5b5_p2 = 0x1000000,
// X8G8B8R8, 24-bit colour (or 24-bit colour with alpha)
nv3_image_in_memory_pixel_format_x8g8b8r8 = 0x1,
} nv3_object_class_01C_pixel_format;
typedef struct nv3_object_class_01C
{
nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch)
uint8_t reserved[0x100];
uint32_t set_notify; // Set notifier
uint8_t reserved2[0x1F8];
nv3_object_class_01C_pixel_format format; // Completely different from everything else
uint32_t pitch; // 16-bit
uint32_t linear_address; // 22-bit: Linear address in vram.
uint8_t reserved3[0x1C3F];
} nv3_image_in_memory_t;
// See envytools. This is where we finally end up after this mess, it allows parameters to be passed to the methods.
typedef struct nv3_grobj_s
{
uint32_t grobj_0;
uint32_t grobj_1;
uint32_t grobj_2;
uint32_t grobj_3;
} nv3_grobj_t;
// TODO: PATCHCORDS!!!! TO LINK ALL OF THIS TOGETHER!!!
#pragma pack(pop) // return packing to whatever it was before this disaster
// PIO Subchannel info
#define NV3_SUBCHANNEL_PIO_IS_PFIFO_FREE 0x0010
#define NV3_SUBCHANNEL_PIO_ALWAYS_ZERO_START 0x0012
#define NV3_SUBCHANNEL_PIO_ALWAYS_ZERO_END 0x0017