From c6f0866509b3438cd9a1e7a791788f8d81fa3a5d Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sun, 5 Jan 2025 00:29:35 +0000 Subject: [PATCH] Define the rest of the object classes. --- .../86box/nv/classes/vid_nv3_classes.h | 563 +++++++++++++++++- src/include/86box/nv/vid_nv3.h | 3 +- 2 files changed, 548 insertions(+), 18 deletions(-) diff --git a/src/include/86box/nv/classes/vid_nv3_classes.h b/src/include/86box/nv/classes/vid_nv3_classes.h index 39aa600be..a22871beb 100644 --- a/src/include/86box/nv/classes/vid_nv3_classes.h +++ b/src/include/86box/nv/classes/vid_nv3_classes.h @@ -10,7 +10,8 @@ * 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 + * 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). * directly to the PHYSICAL PGRAPH REGISTERS while sitting in RAMHT!!!!. * * Also, these class IDs don't relate to the internal architecture of the GPU. @@ -57,13 +58,22 @@ typedef struct nv3_class_ctx_switch_method_s } nv3_class_ctx_switch_method_t; /* 32-bit BGRA format colour for 2D acceleration */ -typedef struct nv3_color_32_s +typedef struct nv3_color_bgra_32_s { uint8_t b; uint8_t g; uint8_t r; uint8_t a; -} nv3_color_32_t; +} nv3_color_bgra_32_t; + +/* 32-bit ARGB format colour for internal D3D5 stuff */ +typedef struct nv3_color_argb_32_s +{ + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +} nv3_color_argb_32_t; /* A4R4G4B4 */ typedef struct nv3_color_16_a4r4g4b4_s @@ -128,7 +138,7 @@ typedef struct nv3_size_16_s /* Generic 32-bit colour + 16-bit position */ typedef struct nv3_color_and_position_16_s { - uint32_t color; + nv3_color_argb_32_t color; nv3_position_16_t points; } nv3_color_and_position_16_t; @@ -248,9 +258,9 @@ typedef struct nv3_object_class_006 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 (BGRA?) - uint32_t color1; // BGRA? - uint32_t pattern[2]; // BGRA? + uint32_t color0; // Some 32-bit format (argb?) + uint32_t color1; // argb? + uint32_t pattern[2]; // argb? uint8_t reserved3[0x1CDF]; // needs to be 0x2000 bytes } nv3_pattern_t; @@ -262,11 +272,11 @@ typedef struct nv3_object_class_006 */ typedef struct nv3_object_class_007 { - nv3_class_ctx_switch_method_t set_notify_ctx_dma; // Set notifier context for DMA (context switch) + 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 + uint32_t set_notify; // Set notifier uint8_t reserved2[0x1FC]; - uint32_t color; // The colour + nv3_color_argb_32_t color; // The colour uint8_t reserved3[0xF8]; nv3_position_16_t position[16]; nv3_size_16_t size[16]; @@ -277,9 +287,8 @@ typedef struct nv3_object_class_007 /* In case your points weren't colourful enough */ typedef struct nv3_object_class_008_cpoint_s { - uint32_t color; - nv3_position_16_t position; - + nv3_color_argb_32_t color; // BGRA-format 32-bit color + nv3_position_16_t position; // } nv3_object_class_008_cpoint_t; /* @@ -294,7 +303,7 @@ typedef struct nv3_object_class_008 uint8_t reserved[0x100]; uint32_t set_notify; // Set notifier uint8_t reserved2[0x1FC]; - uint32_t color; // BGRA? + nv3_color_argb_32_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! @@ -334,7 +343,7 @@ typedef struct nv3_object_class_009 uint8_t reserved[0x100]; uint32_t set_notify; // Set notifier uint8_t reserved2[0x1FC]; - uint32_t color; // BGRA? + nv3_color_argb_32_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]; @@ -358,7 +367,7 @@ typedef struct nv3_object_class_00A uint8_t reserved[0x100]; uint32_t set_notify; // Set notifier uint8_t reserved2[0x1FC]; - uint32_t color; // BGRA? + nv3_color_argb_32_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]; @@ -381,7 +390,7 @@ typedef struct nv3_object_class_00B uint8_t reserved[0x100]; uint32_t set_notify; // Set notifier uint8_t reserved2[0x1FC]; - uint32_t color; // BGRA? + nv3_color_argb_32_t color; // argb? uint8_t reserved3[0x8]; // The points of the triangle. nv3_position_16_t points[3]; @@ -512,6 +521,514 @@ typedef struct nv3_object_class_00E 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_argb_32_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_argb_32_t color_0; + nv3_color_argb_32_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 (Not the same as a Zbuffer...) + 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_bgra_32_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; // "Measurement dimension" apparently, allows for more precise measurements. And curves + 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_argb_32_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 wer are rendering. + /* No placeholder needed, it really is that long. */ +} nv3_d3d5_accelerated_triangle_with_zeta_buffer_t; + +/* 0x18, 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? @@ -535,5 +1052,17 @@ typedef enum nv3_object_class_01C_pixel_format_e nv3_m2mt_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; + // TODO: PATCHCORDS!!!! TO LINK ALL OF THIS TOGETHER!!! #pragma pack(pop) // return packing to whatever it was before this disaster \ No newline at end of file diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index 0b6e6b0eb..72076b64b 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -183,7 +183,6 @@ extern const device_config_t nv3_config[]; #define NV3_PMC_ENABLE_PVIDEO 28 #define NV3_PMC_ENABLE_PVIDEO_ENABLED 0x1 - #define NV3_PMC_END 0xfff // overlaps with CIO #define NV3_CIO_START 0x3b0 // Legacy SVGA Emulation Subsystem #define NV3_CIO_END 0x3df @@ -194,8 +193,10 @@ extern const device_config_t nv3_config[]; #define NV3_PBUS_PCI_END 0x18FF // PCI mirror end #define NV3_PBUS_END 0x1FFF #define NV3_PFIFO_START 0x2000 // FIFO for DMA Object Submission (uses hashtable to store the objects) + #define NV3_PFIFO_INTR 0x2100 // FIFO - Interrupt Status #define NV3_PFIFO_INTR_EN 0x2140 // FIFO - Interrupt Enable + #define NV3_PFIFO_END 0x3FFF #define NV3_PRM_START 0x4000 // Real-Mode Device Support Subsystem #define NV3_PRM_INTR 0x4100