Get rid of useless "reserved" stuff and also implement 8bpp indexed mode using CLUT.

This commit is contained in:
starfrost013
2025-04-13 18:36:48 +01:00
parent 801aa4a97d
commit afcb339224
8 changed files with 203 additions and 161 deletions

Binary file not shown.

View File

@@ -329,11 +329,8 @@ typedef struct nv3_position_32_s
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;
@@ -371,11 +368,8 @@ typedef enum nv3_render_operation_type_e
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;
/*
@@ -387,11 +381,8 @@ typedef struct nv3_object_class_002
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;
/*
@@ -403,11 +394,8 @@ typedef struct nv3_object_class_003
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;
/*
@@ -419,14 +407,11 @@ typedef struct nv3_object_class_004
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;
@@ -439,14 +424,11 @@ typedef struct nv3_object_class_005
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;
/*
@@ -458,22 +440,18 @@ 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)
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_position_16_t position[16]; // The positions of up to 16 rectangles.
nv3_size_16_t size[16]; // The sizes of up to 16 rectangles
} 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_color_expanded_t color; // argb-format 32-bit color
nv3_position_16_t position; // position
} nv3_object_class_008_cpoint_t;
/*
@@ -485,14 +463,11 @@ typedef struct nv3_object_class_008_cpoint_s
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... */
@@ -525,17 +500,13 @@ typedef struct nv3_object_class_009_line32_s
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;
/*
@@ -549,9 +520,9 @@ typedef struct nv3_object_class_009
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];
@@ -559,7 +530,6 @@ typedef struct nv3_object_class_00A
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;
/*
@@ -572,11 +542,8 @@ typedef struct nv3_object_class_00A
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];
@@ -592,7 +559,6 @@ typedef struct nv3_object_class_00B
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;
/*
@@ -605,31 +571,30 @@ typedef struct nv3_object_class_00B
*/
typedef struct nv3_object_class_00C
{
/* Unclipped rect (basically class 0x07 )*/
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_position_16_t rect_a_position[64];
nv3_size_16_t rect_a_size[64];
uint8_t reserved3[0x1F0];
/* Clipped rect */
nv3_clip_16_t clip_b;
uint32_t color_b; // Color for Clip B
nv3_clip_16_t clipped_rect[64];
uint8_t reserved4[0x1E8];
/* Unclipped transparent bitmap */
nv3_clip_16_t clip_c;
uint32_t color1_c;
nv3_size_16_t size_c;
nv3_position_16_t point_c;
uint32_t bitmap_c[128];
uint8_t reserved5[0x368];
/* Clipped transparent bitmap */
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 bitmap_d[128];
uint8_t reserved6[0x364];
/* Clipped 1bpp bitmap */
nv3_clip_16_t clip_e;
uint32_t color0_e;
uint32_t color1_e;
@@ -637,7 +602,6 @@ typedef struct nv3_object_class_00C
nv3_size_16_t size_out_e;
nv3_position_16_t point_e;
uint32_t bitmap_e[128];
uint8_t reserved7[0xB7F];
} nv3_win95_text_t;
@@ -651,9 +615,7 @@ typedef struct nv3_object_class_00C
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;
@@ -661,9 +623,7 @@ typedef struct nv3_object_class_00D
uint32_t line_length_in; // Stride?
uint32_t line_count;
uint8_t format; // input increment 1 2 or 4, output increment 1 2 or 4 (represented by << 8)
uint8_t reserved3[2];
uint32_t buffer_notify; // Notify the Buffedr
uint8_t reserved4[0x1CD3];
} nv3_memory_to_memory_format_t;
/*
@@ -676,9 +636,7 @@ typedef struct nv3_object_class_00D
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;
@@ -686,7 +644,6 @@ typedef struct nv3_object_class_00E
// 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;
@@ -697,7 +654,6 @@ typedef struct nv3_object_class_00E
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)
@@ -713,13 +669,10 @@ typedef struct nv3_object_class_00E
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;
/*
@@ -732,15 +685,11 @@ typedef struct nv3_object_class_010
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;
/*
@@ -754,16 +703,13 @@ typedef struct nv3_object_class_011
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
@@ -779,14 +725,11 @@ typedef struct nv3_object_class_012
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;
/*
@@ -800,17 +743,13 @@ typedef struct nv3_object_class_014
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;
@@ -1189,9 +1128,7 @@ typedef struct nv3_d3d5_coordinate_s
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;
@@ -1199,7 +1136,6 @@ typedef struct nv3_object_class_017
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;
@@ -1215,12 +1151,9 @@ typedef struct nv3_zeta_buffer_s
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;
@@ -1252,13 +1185,10 @@ typedef enum nv3_object_class_01C_pixel_format_e
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.

View File

@@ -23,21 +23,24 @@ void nv3_render_current_bpp_dfb_8(uint32_t address);
void nv3_render_current_bpp_dfb_16(uint32_t address);
void nv3_render_current_bpp_dfb_32(uint32_t address);
/* Pixel */
void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj);
uint8_t nv3_render_read_pixel_8(nv3_position_16_t position, nv3_grobj_t grobj);
uint16_t nv3_render_read_pixel_16(nv3_position_16_t position, nv3_grobj_t grobj);
uint32_t nv3_render_read_pixel_32(nv3_position_16_t position, nv3_grobj_t grobj);
/* Address */
uint32_t nv3_render_get_vram_address(nv3_position_16_t position, nv3_grobj_t grobj);
uint32_t nv3_render_get_vram_address_for_buffer(nv3_position_16_t position, nv3_grobj_t grobj, uint32_t buffer);
uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded);
/* Colour Conversion */
uint32_t nv3_render_get_palette_index(uint8_t index); // Get a colour for a palette index. (The colours are 24 bit RGB888 with a 0xFF alpha added for some purposes.)
uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded); // Convert a colour to A1R10G10B10 for chroma key purposes.
nv3_color_expanded_t nv3_render_expand_color(uint32_t color, nv3_grobj_t grobj); // Convert a colour to full RGB10 format from the current working format.
uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t color); // Convert a colour from the current working format to RGB10 format.
/* Pattern */
uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1);
void nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1);
/* Primitives */
void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj); // Render an A (unclipped) GDI rect

View File

@@ -14,7 +14,7 @@
* Also check the doc folder for some more notres
*
* vid_nv3.h: NV3 Architecture Hardware Reference (open-source)
* Last updated: 6 April 2025 (STILL WORKING ON IT!!!)
* Last updated: 12 April 2025 (STILL WORKING ON IT!!!)
*
* Authors: Connor Hyde <mario64crashed@gmail.com>
*
@@ -727,8 +727,16 @@ extern const device_config_t nv3_config[];
#define NV3_PRAMDAC_END 0x680FFF
#define NV3_PDAC_END 0x680FFF // OPTIONAL external DAC
#define NV3_VGA_DAC_START 0x6813C6
#define NV3_VGA_DAC_END 0x6813C9
#define NV3_USER_DAC_START 0x681200
#define NV3_USER_DAC_PALETTE_START 0x6813C6
#define NV3_USER_DAC_PIXEL_MASK 0x6813C6
#define NV3_USER_DAC_READ_MODE_ADDRESS 0x6813C7 //bit0=read/write mode?
#define NV3_USER_DAC_WRITE_MODE_ADDRESS 0x6813C8
#define NV3_USER_DAC_PALETTE_DATA 0x6813C9
#define NV3_USER_DAC_PALETTE_SIZE 768
#define NV3_USER_DAC_PALETTE_END 0x6813C9
#define NV3_USER_DAC_END 0x681FFF
#define NV3_USER_START 0x800000 // Mapping for the area where objects are submitted into the FIFO (up to 0x880000?)
#define NV3_USER_END 0xFFFFFF
@@ -1065,6 +1073,11 @@ typedef struct nv3_pramdac_s
uint32_t htotal; // horizontal total lines
uint32_t hequ_width; // horizontal equ width (not sure what this is)
uint32_t hserr_width; // horizontal sync error width
uint8_t user_pixel_mask; // pixel mask for DAC lookup
uint32_t user_read_mode_address; // user read mode address
uint32_t user_write_mode_address; // user write mode address
uint8_t palette[NV3_USER_DAC_PALETTE_SIZE]; // Palette Info/CLUT - 256 entriesxr,g,b = 768 bytes
} nv3_pramdac_t;
/* Holds DMA channel context information */
@@ -1133,7 +1146,7 @@ typedef struct nv3_pgraph_status_s
} nv3_pgraph_status_t;
/* All of this B* stuff is registers at 400630..40065c and 4006a8 in reality, easier to implement it like this
BPixel = Internal Binary Representation of the pixel within the architecture
BPixel = Buffer Pixel Format
*/
#define NV3_BPIXEL_FORMAT 0
#define NV3_BPIXEL_FORMAT_IS_VALID 2

View File

@@ -49,9 +49,9 @@ void nv3_svga_write(uint16_t addr, uint8_t val, void* priv);
bool nv3_is_svga_redirect_address(uint32_t addr)
{
return (addr >= NV3_PRMVIO_START && addr <= NV3_PRMVIO_END) // VGA
|| (addr >= NV3_PRMCIO_START && addr <= NV3_PRMCIO_END) // CRTC
|| (addr >= NV3_VGA_DAC_START && addr <= NV3_VGA_DAC_END); // Legacy RAMDAC support(?)
return (addr >= NV3_PRMVIO_START && addr <= NV3_PRMVIO_END) // VGA
|| (addr >= NV3_PRMCIO_START && addr <= NV3_PRMCIO_END) // CRTC
|| (addr >= NV3_USER_DAC_START && addr <= NV3_USER_DAC_END); // Note: 6813c6-6813c9 are ignored somewhere else
}
// All MMIO regs are 32-bit i believe internally
@@ -65,6 +65,14 @@ uint8_t nv3_mmio_read8(uint32_t addr, void* priv)
// Some of these addresses are Weitek VGA stuff and we need to mask it to this first because the weitek addresses are 8-bit aligned.
addr &= 0xFFFFFF;
// We need to specifically exclude this particular set of registers
// so we can write the 4/8bpp CLUT
if (addr >= NV3_USER_DAC_PALETTE_START && addr <= NV3_USER_DAC_PALETTE_END)
{
// Throw directly into PRAMDAC
return nv3_mmio_arbitrate_read(addr);
}
if (nv3_is_svga_redirect_address(addr))
{
// svga writes are not logged anyway rn
@@ -143,6 +151,15 @@ void nv3_mmio_write8(uint32_t addr, uint8_t val, void* priv)
{
addr &= 0xFFFFFF;
// We need to specifically exclude this particular set of registers
// so we can write the 4/8bpp CLUT
if (addr >= NV3_USER_DAC_PALETTE_START && addr <= NV3_USER_DAC_PALETTE_END)
{
// Throw directly into PRAMDAC
nv3_mmio_arbitrate_write(addr, val);
return;
}
// This is weitek vga stuff
// If we need to add more of these we can convert these to a switch statement
if (nv3_is_svga_redirect_address(addr))
@@ -474,7 +491,7 @@ void nv3_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
break;
default:
break;
}
}
@@ -493,31 +510,6 @@ void nv3_recalc_timings(svga_t* svga)
svga->ma_latch += (svga->crtc[NV3_CRTC_REGISTER_RPC0] & 0x1F) << 16;
// should these actually use separate values?
// i don't we should force the top 2 bits to 1...
// required for VESA resolutions, force parameters higher
// only fuck around with any of this in VGAmode?
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VDT10)) svga->vtotal += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VRS10)) svga->vblankstart += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VBS10)) svga->vsyncstart += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_HBE6)) svga->hdisp += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VDE10)) svga->dispend += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_HEB] & 0x01)
svga->hdisp += 0x100; // large screen bit
/*
if (pixel_mode == NV3_CRTC_REGISTER_PIXELMODE_VGA)
{
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VDT10)) svga->vtotal += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VRS10)) svga->vblankstart += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VBS10)) svga->vsyncstart += 0x400;
if (svga->crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_HBE6)) svga->hdisp += 0x400;
}
*/
/* Turn off override if we are in VGA mode */
svga->override = !(pixel_mode == NV3_CRTC_REGISTER_PIXELMODE_VGA);
@@ -698,7 +690,7 @@ void nv3_svga_write(uint16_t addr, uint8_t val, void* priv)
addr ^= 0x60;
uint8_t crtcreg = nv3->nvbase.svga.crtcreg;
uint8_t old_value;
uint8_t old_value = 0x00;
// todo:
// Pixel formats (8bit vs 555 vs 565)
@@ -747,12 +739,33 @@ void nv3_svga_write(uint16_t addr, uint8_t val, void* priv)
case NV3_CRTC_REGISTER_RMA:
nv3->pbus.rma.mode = val & NV3_CRTC_REGISTER_RMA_MODE_MAX;
break;
/* Handle some large screen stuff */
case NV3_CRTC_REGISTER_PIXELMODE:
if (val & 1 << (NV3_CRTC_REGISTER_FORMAT_VDT10))
nv3->nvbase.svga.vtotal += 0x400;
if (val & 1 << (NV3_CRTC_REGISTER_FORMAT_VRS10))
nv3->nvbase.svga.vblankstart += 0x400;
if (val & 1 << (NV3_CRTC_REGISTER_FORMAT_VBS10))
nv3->nvbase.svga.vsyncstart += 0x400;
if (val & 1 << (NV3_CRTC_REGISTER_FORMAT_HBE6))
nv3->nvbase.svga.hdisp += 0x400;
/* Make sure dispend and vblankstart are right if we are displaying above 1024 vert */
if (nv3->nvbase.svga.crtc[NV3_CRTC_REGISTER_PIXELMODE] & 1 << (NV3_CRTC_REGISTER_FORMAT_VDE10))
nv3->nvbase.svga.dispend += 0x400;
break;
case NV3_CRTC_REGISTER_HEB:
if (val & 0x01)
nv3->nvbase.svga.hdisp += 0x100;
break;
case NV3_CRTC_REGISTER_I2C_GPIO:
uint8_t scl = !!(val & 0x20);
uint8_t sda = !!(val & 0x10);
// Set an I2C GPIO register
i2c_gpio_set(nv3->nvbase.i2c, scl, sda);
break;
}
/* Recalculate the timings if we actually changed them
@@ -763,7 +776,7 @@ void nv3_svga_write(uint16_t addr, uint8_t val, void* priv)
// and in the words of an ex-Rendition/3dfx/NVIDIA engineer, "VGA was basically an undocumented bundle of steaming you-know-what.
// And it was essential that any cores the PC 3D startups acquired had to work with all the undocumented modes and timing tweaks (mode X, etc.)"
if (nv3->nvbase.svga.crtcreg < 0xE
&& nv3->nvbase.svga.crtcreg > 0x10)
|| nv3->nvbase.svga.crtcreg > 0x10)
{
nv3->nvbase.svga.fullchange = changeframecount;
nv3_recalc_timings(&nv3->nvbase.svga);

View File

@@ -58,9 +58,10 @@ uint32_t nv3_mmio_arbitrate_read(uint32_t address)
uint32_t ret = 0x00;
// note: some registers are byte aligned not dword aligned
// only very few are though, so they can be handled specially, using the register list most likely
address &= 0xFFFFFC;
// Ensure the addresses are dword aligned.
// I don't know why this is needed because writepriv32 is always to dword align, but it crashes if you don't do this.
if (!(address >= NV3_USER_DAC_PALETTE_START && address <= NV3_USER_DAC_PALETTE_END))
address &= 0xFFFFFC;
// gigantic set of if statements to send the write to the right subsystem
if (address >= NV3_PMC_START && address <= NV3_PMC_END)
@@ -97,7 +98,8 @@ uint32_t nv3_mmio_arbitrate_read(uint32_t address)
ret = nv3_prmcio_read(address);
else if (address >= NV3_PVIDEO_START && address <= NV3_PVIDEO_END)
ret = nv3_pvideo_read(address);
else if (address >= NV3_PRAMDAC_START && address <= NV3_PRAMDAC_END)
else if ((address >= NV3_PRAMDAC_START && address <= NV3_PRAMDAC_END)
|| (address >= NV3_USER_DAC_PALETTE_START && address <= NV3_USER_DAC_PALETTE_END)) //clut
ret = nv3_pramdac_read(address);
else if (address >= NV3_VRAM_START && address <= NV3_VRAM_END)
ret = nv3_dfb_read32(address & nv3->nvbase.svga.vram_mask, &nv3->nvbase.svga);
@@ -121,9 +123,12 @@ void nv3_mmio_arbitrate_write(uint32_t address, uint32_t value)
// Some of these addresses are Weitek VGA stuff and we need to mask it to this first because the weitek addresses are 8-bit aligned.
address &= 0xFFFFFF;
// note: some registers are byte aligned not dword aligned
// only very few are though, so they can be handled specially, using the register list most likely
address &= 0xFFFFFC;
// Ensure the addresses are dword aligned.
// I don't know why this is needed because writepriv32 is always to dword align, but it crashes if you don't do this.
// Exclude the 4bpp/8bpp CLUT for this purpose
if (!(address >= NV3_USER_DAC_PALETTE_START && address <= NV3_USER_DAC_PALETTE_END))
address &= 0xFFFFFC;
// gigantic set of if statements to send the write to the right subsystem
if (address >= NV3_PMC_START && address <= NV3_PMC_END)
@@ -158,7 +163,8 @@ void nv3_mmio_arbitrate_write(uint32_t address, uint32_t value)
nv3_prmcio_write(address, value);
else if (address >= NV3_PVIDEO_START && address <= NV3_PVIDEO_END)
nv3_pvideo_write(address, value);
else if (address >= NV3_PRAMDAC_START && address <= NV3_PRAMDAC_END)
else if ((address >= NV3_PRAMDAC_START && address <= NV3_PRAMDAC_END)
|| (address >= NV3_USER_DAC_PALETTE_START && address <= NV3_USER_DAC_PALETTE_END)) //clut
nv3_pramdac_write(address, value);
else if (address >= NV3_VRAM_START && address <= NV3_VRAM_END)
nv3_dfb_write32(address, value, &nv3->nvbase.svga);

View File

@@ -88,6 +88,7 @@ nv3_color_expanded_t nv3_render_expand_color(uint32_t color, nv3_grobj_t grobj)
break;
case nv3_pgraph_pixel_format_y8:
/* Indexed mode */
color_final.a = (color >> 8) & 0xFF;
// yuv
@@ -143,11 +144,11 @@ uint32_t nv3_render_downconvert_color(nv3_grobj_t grobj, nv3_color_expanded_t co
packed_color |= (color.g << 20);
packed_color |= (color.b << 10);
break;
case nv3_pgraph_pixel_format_y8:
warning("nv3_render_downconvert: Y8 not implemented");
case nv3_pgraph_pixel_format_y8: /* i think this is just indexed mode. since r=g=b we can just take the indexed from the r */
packed_color = nv3_render_get_palette_index((color.r >> 2) & 0xFF);
break;
case nv3_pgraph_pixel_format_y16:
//warning("nv3_render_downconvert: Y16 not implemented");
warning("nv3_render_downconvert: Y16 not implemented");
break;
default:
warning("nv3_render_downconvert_color unknown format %d", format);
@@ -189,15 +190,24 @@ uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded)
return !!expanded.a | (expanded.r << 30) | (expanded.b << 20) | (expanded.a << 10);
}
/* Convert a rgb10 colour to a pattern colour */
uint32_t nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1)
/* Get a colour for a palette index. (The colours are 24 bit RGB888 with a 0xFF alpha added for some purposes.) */
uint32_t nv3_render_get_palette_index(uint8_t index)
{
uint32_t red_index = index * 3;
uint32_t green_index = red_index + 1;
uint32_t blue_index = red_index + 2;
uint8_t red_colour = nv3->pramdac.palette[red_index];
uint8_t green_colour = nv3->pramdac.palette[green_index];
uint8_t blue_colour = nv3->pramdac.palette[blue_index];
/* Alpha is always 0xFF */
return (0xFF << 24) | ((red_colour) << 16) | ((green_colour) << 8) | blue_colour;
}
/* Convert a rgb10 colour to a pattern colour */
void nv3_render_set_pattern_color(nv3_color_expanded_t pattern_colour, bool use_color1)
{
/* reset the colour */
if (!use_color1)
nv3->pgraph.pattern_color_0_rgb.r = nv3->pgraph.pattern_color_0_rgb.g = nv3->pgraph.pattern_color_0_rgb.b = 0x00;
else
nv3->pgraph.pattern_color_1_rgb.r = nv3->pgraph.pattern_color_1_rgb.g = nv3->pgraph.pattern_color_1_rgb.b = 0x00;
/* select the right pattern colour, _rgb is already in RGB10 format, so we don't need to do any conversion */
if (!use_color1)
@@ -359,7 +369,6 @@ uint32_t nv3_render_read_pixel_32(nv3_position_16_t position, nv3_grobj_t grobj)
/* Plots a pixel. */
void nv3_render_write_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
@@ -372,12 +381,6 @@ void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grob
uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp; // maybe y16 too?z
/* 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;
@@ -507,7 +510,8 @@ void nv3_render_write_pixel(nv3_position_16_t position, uint32_t color, nv3_grob
/* Ensure the correct monitor size */
void nv3_render_ensure_screen_size(void)
{
bool changed = false; //doesn't check if the res is the same?
/* First check if hdisp == xsize and dispend == ysize. */
bool changed = false;
if (nv3->nvbase.svga.hdisp != nv3->nvbase.svga.monitor->mon_xsize)
{
@@ -521,9 +525,13 @@ void nv3_render_ensure_screen_size(void)
nv3->nvbase.svga.monitor->mon_ysize = nv3->nvbase.svga.dispend;
}
/*
if either changed:
-> set resolution
-> set refresh rate - this is just a rough estimation right now. we need it as we only blit what changes
*/
if (changed)
{
/* set refresh rate - this is just a rough estimation right now. we need it as we only blit what changes */
nv3->nvbase.refresh_time = 1 / (nv3->nvbase.pixel_clock_frequency / (double)ysize / (double)xsize); // rivatimers count in microseconds
set_screen_size(xsize, ysize);
}
@@ -534,7 +542,15 @@ void nv3_render_ensure_screen_size(void)
/* Blit to the monitor from DFB, 8bpp */
void nv3_render_current_bpp_dfb_8(uint32_t address)
{
nv3_size_16_t size = {0};
size.w = size.h = 1;
nv3_position_16_t pos = nv3_render_get_dfb_position(address);
uint32_t* p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
uint32_t data = *(uint32_t*)&(nv3->nvbase.svga.vram[address]);
*p = nv3_render_get_palette_index(data & 0xFF);
}
/* Blit to the monitor from DFB, 15/16bpp */
@@ -545,8 +561,6 @@ void nv3_render_current_bpp_dfb_16(uint32_t address)
nv3_position_16_t pos = nv3_render_get_dfb_position(address);
//pos.x >>= 1;
uint32_t* p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
uint32_t data = *(uint32_t*)&(nv3->nvbase.svga.vram[address]);
@@ -623,8 +637,8 @@ void nv3_render_current_bpp(svga_t *svga, nv3_position_16_t pos, nv3_size_16_t s
switch (nv3->nvbase.svga.bpp)
{
case 4:
/* Uh we should never be here because we're in the SVGA mode */
fatal("NV3 - Tried to render 4bpp in NV mode");
/* Uh we should never be here because we're in the SVGA mode(?) */
fatal("NV3 - 4bpp not implemented (not even sure if it's SVGA only)");
break;
case 8:
nv3_render_8bpp(pos, size, grobj);
@@ -648,7 +662,36 @@ void nv3_render_current_bpp(svga_t *svga, nv3_position_16_t pos, nv3_size_16_t s
void nv3_render_8bpp(nv3_position_16_t pos, nv3_size_16_t size, nv3_grobj_t grobj)
{
if (!nv3)
return;
uint32_t vram_base; //acquired for the start of each line
uint32_t* p;
uint32_t data;
uint32_t start_x = pos.x;
p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
for (uint32_t y = 0; y < size.h; y++)
{
/* re-set the vram address because we are basically "jumping" halfway across a line here */
vram_base = nv3_render_get_vram_address(pos, grobj) & nv3->nvbase.svga.vram_display_mask;
for (uint32_t x = 0; x < size.w; x++)
{
p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
data = *(uint32_t*)&nv3->nvbase.svga.vram[vram_base];
/* should just "tip over" to the next line */
*p = nv3_render_get_palette_index(data & 0xFF);
vram_base++;
pos.x++;
}
pos.x = start_x;
pos.y++;
}
}
/*
@@ -675,7 +718,6 @@ void nv3_render_15bpp(nv3_position_16_t pos, nv3_size_16_t size, nv3_grobj_t gro
for (uint32_t x = 0; x < size.w; x++)
{
p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
data = *(uint32_t*)&nv3->nvbase.svga.vram[vram_base];
/* should just "tip over" to the next line */
@@ -714,7 +756,6 @@ void nv3_render_16bpp(nv3_position_16_t pos, nv3_size_16_t size, nv3_grobj_t gro
for (uint32_t x = 0; x < size.w; x++)
{
p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
data = *(uint32_t*)&nv3->nvbase.svga.vram[vram_base];
/* should just "tip over" to the next line */
@@ -750,11 +791,9 @@ void nv3_render_32bpp(nv3_position_16_t pos, nv3_size_16_t size, nv3_grobj_t gro
/* re-get the vram address because we are basically "jumping" halfway across a line here */
vram_base = nv3_render_get_vram_address(pos, grobj) & nv3->nvbase.svga.vram_display_mask;
for (uint32_t x = 0; x < size.w; x++)
{
p = &nv3->nvbase.svga.monitor->target_buffer->line[pos.y][pos.x];
data = *(uint32_t*)&nv3->nvbase.svga.vram[vram_base];
/* should just "tip over" to the next line */

View File

@@ -225,6 +225,10 @@ nv_register_t pramdac_registers[] =
{ NV3_PRAMDAC_HTOTAL, "PRAMDAC - Total Horizontal Lines", NULL, NULL},
{ NV3_PRAMDAC_HEQU_WIDTH, "PRAMDAC - HEqu End", NULL, NULL},
{ NV3_PRAMDAC_HSERR_WIDTH, "PRAMDAC - Horizontal Sync Error", NULL, NULL},
{ NV3_USER_DAC_PIXEL_MASK, "PRAMDAC - User DAC Pixel Mask", NULL, NULL},
{ NV3_USER_DAC_READ_MODE_ADDRESS, "PRAMDAC - User DAC Read Mode Address", NULL, NULL},
{ NV3_USER_DAC_WRITE_MODE_ADDRESS, "PRAMDAC - User DAC Write Mode Address", NULL, NULL},
{ NV3_USER_DAC_PALETTE_DATA, "PRAMDAC - User DAC Palette Data", NULL, NULL},
{ NV_REG_LIST_END, NULL, NULL, NULL}, // sentinel value
};
@@ -301,6 +305,21 @@ uint32_t nv3_pramdac_read(uint32_t address)
case NV3_PRAMDAC_HSERR_WIDTH:
ret = nv3->pramdac.hserr_width;
break;
case NV3_USER_DAC_PIXEL_MASK:
ret = nv3->pramdac.user_pixel_mask;
break;
case NV3_USER_DAC_READ_MODE_ADDRESS:
ret = nv3->pramdac.user_read_mode_address;
break;
case NV3_USER_DAC_WRITE_MODE_ADDRESS:
ret = nv3->pramdac.user_write_mode_address;
break;
case NV3_USER_DAC_PALETTE_DATA:
/* I doubt NV actually read this in their drivers, but it's worth doing anyway */
/* Bit 1 is listed as "read or write mode" and 7:0 as "Write-only address", but NV only ever set this to 0 too, so i think this should be fine for now */
ret = nv3->pramdac.palette[nv3->pramdac.user_read_mode_address];
nv3->pramdac.user_read_mode_address++;
break;
}
}
@@ -390,8 +409,31 @@ void nv3_pramdac_write(uint32_t address, uint32_t value)
nv3->pramdac.hequ_width = value;
break;
case NV3_PRAMDAC_HSERR_WIDTH:
nv3->pramdac.hserr_width = value;
break;
case NV3_USER_DAC_PIXEL_MASK:
nv3->pramdac.user_pixel_mask = value;
break;
case NV3_USER_DAC_READ_MODE_ADDRESS:
nv3->pramdac.user_read_mode_address = value;
break;
case NV3_USER_DAC_WRITE_MODE_ADDRESS:
/*
This seems to get reset to 0 after 256 writes, but, the palette is 768 bytes in size.
Clearly there's some mechanism here, but I'm not sure what it is. So let's just reset if we reach 768.
*/
if (nv3->pramdac.user_write_mode_address >= NV3_USER_DAC_PALETTE_SIZE)
nv3->pramdac.user_write_mode_address = value;
break;
case NV3_USER_DAC_PALETTE_DATA:
/* I doubt NV actually read this in their drivers, but it's worth doing anyway */
/* Bit 1 is listed as "read or write mode" and 7:0 as "Write-only address", but NV only ever set this to 0 too, so i think this should be fine for now */
nv3->pramdac.palette[nv3->pramdac.user_write_mode_address] = value;
nv3->pramdac.user_write_mode_address++;
break;
}
}
@@ -407,7 +449,3 @@ void nv3_pramdac_write(uint32_t address, uint32_t value)
}
}
uint32_t nv3_pramdac_read_clut(void) //4bpp/8bpp
{
}