diff --git a/doc/nvidia_notes/NV128.xlsx b/doc/nvidia_notes/NV128.xlsx index 919297d56..fbf57c5eb 100644 Binary files a/doc/nvidia_notes/NV128.xlsx and b/doc/nvidia_notes/NV128.xlsx differ diff --git a/src/include/86box/nv/classes/vid_nv3_classes.h b/src/include/86box/nv/classes/vid_nv3_classes.h index f3788040e..b4f41fc30 100644 --- a/src/include/86box/nv/classes/vid_nv3_classes.h +++ b/src/include/86box/nv/classes/vid_nv3_classes.h @@ -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; diff --git a/src/include/86box/nv/render/vid_nv3_render.h b/src/include/86box/nv/render/vid_nv3_render.h index fd6ad8abf..58ecf9df5 100644 --- a/src/include/86box/nv/render/vid_nv3_render.h +++ b/src/include/86box/nv/render/vid_nv3_render.h @@ -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); \ 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 e5117366a..c1d0e3bdd 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -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); diff --git a/src/include/86box/utils/video_stdlib.h b/src/include/86box/utils/video_stdlib.h index 3605631f1..4434ef43f 100644 --- a/src/include/86box/utils/video_stdlib.h +++ b/src/include/86box/utils/video_stdlib.h @@ -17,4 +17,4 @@ /* ROP */ -int32_t video_rop_gdi_ternary(int32_t rop, int32_t dst, int32_t pattern, int32_t src); \ No newline at end of file +int32_t video_rop_gdi_ternary(int32_t rop, int32_t src, int32_t dst, int32_t pattern); \ No newline at end of file diff --git a/src/utils/video/video_rop.c b/src/utils/video/video_rop.c index 8bfdc9627..146822201 100644 --- a/src/utils/video/video_rop.c +++ b/src/utils/video/video_rop.c @@ -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; diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 4d9b7a25f..094b64440 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -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 ) diff --git a/src/video/nv/nv3/classes/nv3_class_001_beta_factor.c b/src/video/nv/nv3/classes/nv3_class_001_beta_factor.c index e21189213..2acf3a8f4 100644 --- a/src/video/nv/nv3/classes/nv3_class_001_beta_factor.c +++ b/src/video/nv/nv3/classes/nv3_class_001_beta_factor.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_002_rop.c b/src/video/nv/nv3/classes/nv3_class_002_rop.c index b771551d3..9286c180c 100644 --- a/src/video/nv/nv3/classes/nv3_class_002_rop.c +++ b/src/video/nv/nv3/classes/nv3_class_002_rop.c @@ -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); diff --git a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c index 73901d08d..06750521e 100644 --- a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c +++ b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c b/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c index 48a96ab96..10788b5ce 100644 --- a/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c +++ b/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c b/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c index 1119147e7..8ba698aa5 100644 --- a/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c +++ b/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c @@ -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); diff --git a/src/video/nv/nv3/classes/nv3_class_006_pattern.c b/src/video/nv/nv3/classes/nv3_class_006_pattern.c index c8c81066f..ee3348669 100644 --- a/src/video/nv/nv3/classes/nv3_class_006_pattern.c +++ b/src/video/nv/nv3/classes/nv3_class_006_pattern.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c index 69e66ca31..dd82030ca 100644 --- a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c +++ b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c @@ -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; } diff --git a/src/video/nv/nv3/classes/nv3_class_008_point.c b/src/video/nv/nv3/classes/nv3_class_008_point.c index 0cd44b8cd..8647b27cb 100644 --- a/src/video/nv/nv3/classes/nv3_class_008_point.c +++ b/src/video/nv/nv3/classes/nv3_class_008_point.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_009_line.c b/src/video/nv/nv3/classes/nv3_class_009_line.c index 8d71f4d5e..dddbf5719 100644 --- a/src/video/nv/nv3/classes/nv3_class_009_line.c +++ b/src/video/nv/nv3/classes/nv3_class_009_line.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_00a_lin.c b/src/video/nv/nv3/classes/nv3_class_00a_lin.c index 141a2422c..45f1c97b9 100644 --- a/src/video/nv/nv3/classes/nv3_class_00a_lin.c +++ b/src/video/nv/nv3/classes/nv3_class_00a_lin.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_00b_triangle.c b/src/video/nv/nv3/classes/nv3_class_00b_triangle.c index 91cbaa837..e3bbf9f07 100644 --- a/src/video/nv/nv3/classes/nv3_class_00b_triangle.c +++ b/src/video/nv/nv3/classes/nv3_class_00b_triangle.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c index 3ba352b3c..66eddee71 100644 --- a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c +++ b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c b/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c index 888ac89cf..687e1e763 100644 --- a/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c +++ b/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c b/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c index bf0286c20..f4bc8d6ee 100644 --- a/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c +++ b/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_010_blit.c b/src/video/nv/nv3/classes/nv3_class_010_blit.c index da2f16bda..c502bdd28 100644 --- a/src/video/nv/nv3/classes/nv3_class_010_blit.c +++ b/src/video/nv/nv3/classes/nv3_class_010_blit.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_011_image.c b/src/video/nv/nv3/classes/nv3_class_011_image.c index 4499693df..36679cb7f 100644 --- a/src/video/nv/nv3/classes/nv3_class_011_image.c +++ b/src/video/nv/nv3/classes/nv3_class_011_image.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_012_bitmap.c b/src/video/nv/nv3/classes/nv3_class_012_bitmap.c index ca8540b75..2ce3fb685 100644 --- a/src/video/nv/nv3/classes/nv3_class_012_bitmap.c +++ b/src/video/nv/nv3/classes/nv3_class_012_bitmap.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c b/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c index 6a18ff1d7..86be6a74a 100644 --- a/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c +++ b/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c b/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c index c8560ad0f..5b499b73d 100644 --- a/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c +++ b/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c b/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c index 951ba862d..4f1e73774 100644 --- a/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c +++ b/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c b/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c index 80f10797f..4829fafb9 100644 --- a/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c +++ b/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c @@ -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) { diff --git a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c index 30d6aee17..d55ee9511 100644 --- a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c +++ b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c @@ -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; diff --git a/src/video/nv/nv3/classes/nv3_class_shared_methods.c b/src/video/nv/nv3/classes/nv3_class_shared_methods.c index 2f24daa41..38d45f70e 100644 --- a/src/video/nv/nv3/classes/nv3_class_shared_methods.c +++ b/src/video/nv/nv3/classes/nv3_class_shared_methods.c @@ -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: diff --git a/src/video/nv/nv3/render/nv3_render_core.c b/src/video/nv/nv3/render/nv3_render_core.c index 57df42b39..4dff864e0 100644 --- a/src/video/nv/nv3/render/nv3_render_core.c +++ b/src/video/nv/nv3/render/nv3_render_core.c @@ -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; + +} \ No newline at end of file diff --git a/src/video/nv/nv3/render/nv3_render_primitives.c b/src/video/nv/nv3/render/nv3_render_primitives.c new file mode 100644 index 000000000..e44636acb --- /dev/null +++ b/src/video/nv/nv3/render/nv3_render_primitives.c @@ -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, I need a better email address ;^) +* +* Copyright 2024-2025 Connor Hyde +*/ + +#include +#include +#include +#include +#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); + } + } +} \ No newline at end of file