// Project64 - A Nintendo 64 emulator // http://www.pj64-emu.com/ // Copyright(C) 2001-2021 Project64 // Copyright(C) 2003-2009 Sergey 'Gonetz' Lipski // Copyright(C) 2002 Dave2001 // GNU/GPLv2 licensed: https://gnu.org/licenses/gpl-2.0.html #pragma once #include #include extern char out_buf[2048]; extern uint32_t frame_count; // frame counter //GlideHQ support #include "Ext_TxFilter.h" enum { MAX_CACHE = 1024 * 4, MAX_TRI_CACHE = 768, // this is actually # of vertices, not triangles MAX_VTX = 256, MAX_TMU = 2, }; #define MAXCMD 0x100000 const unsigned int maxCMDMask = MAXCMD - 1; #define TEXMEM_2MB_EDGE 2097152 // Supported flags #define SUP_TEXMIRROR 0x00000001 // Clipping flags #define CLIP_XMAX 0x00000001 #define CLIP_XMIN 0x00000002 #define CLIP_YMAX 0x00000004 #define CLIP_YMIN 0x00000008 #define CLIP_WMIN 0x00000010 #define CLIP_ZMAX 0x00000020 #define CLIP_ZMIN 0x00000040 // Flags #define ZBUF_ENABLED 0x00000001 #define ZBUF_DECAL 0x00000002 #define ZBUF_COMPARE 0x00000004 #define ZBUF_UPDATE 0x00000008 #define ALPHA_COMPARE 0x00000010 #define FORCE_BL 0x00000020 #define CULL_FRONT 0x00001000 // * must be here #define CULL_BACK 0x00002000 // * must be here #define FOG_ENABLED 0x00010000 #define CULLMASK 0x00003000 #define CULLSHIFT 12 // Update flags #define UPDATE_ZBUF_ENABLED 0x00000001 #define UPDATE_TEXTURE 0x00000002 // \ Same thing! #define UPDATE_COMBINE 0x00000002 // / #define UPDATE_CULL_MODE 0x00000004 #define UPDATE_LIGHTS 0x00000010 #define UPDATE_BIASLEVEL 0x00000020 #define UPDATE_ALPHA_COMPARE 0x00000040 #define UPDATE_VIEWPORT 0x00000080 #define UPDATE_MULT_MAT 0x00000100 #define UPDATE_SCISSOR 0x00000200 #define UPDATE_FOG_ENABLED 0x00010000 #define CMB_MULT 0x00000001 #define CMB_SET 0x00000002 #define CMB_SUB 0x00000004 #define CMB_ADD 0x00000008 #define CMB_A_MULT 0x00000010 #define CMB_A_SET 0x00000020 #define CMB_A_SUB 0x00000040 #define CMB_A_ADD 0x00000080 #define CMB_SETSHADE_SHADEALPHA 0x00000100 #define CMB_INTER 0x00000200 #define CMB_MULT_OWN_ALPHA 0x00000400 #define CMB_COL_SUB_OWN 0x00000800 #define uc(x) coord[x<<1] #define vc(x) coord[(x<<1)+1] #if defined(_MSC_VER) #define DECLAREALIGN16VAR(var) __declspec(align(16)) float var #elif defined(__GNUG__) #define DECLAREALIGN16VAR(var) float (var) __attribute__ ((aligned(16))) #endif // Clipping (scissors) typedef struct { uint32_t ul_x; uint32_t ul_y; uint32_t lr_x; uint32_t lr_y; } SCISSOR; typedef struct { uint16_t tile_ul_s; uint16_t tile_ul_t; uint16_t tile_width; uint16_t tile_height; uint16_t tex_width; uint16_t tex_size; uint32_t dxt; } LOAD_TILE_INFO; typedef struct { int gamma_correction; int32_t gamma_table_size; uint32_t *gamma_table_r; uint32_t *gamma_table_g; uint32_t *gamma_table_b; uint32_t tmem_ptr[MAX_TMU]; uint32_t tex_min_addr[MAX_TMU]; uint32_t tex_max_addr[MAX_TMU]; } VOODOO; // This structure is what is passed in by rdp:settextureimage typedef struct { uint8_t format; // format: ARGB, IA, ... uint8_t size; // size: 4,8,16, or 32 bit uint16_t width; // used in settextureimage uint32_t addr; // address in RDRAM to load the texture from int set_by; // 0-loadblock 1-loadtile } TEXTURE_IMAGE; // This structure is a tile descriptor (as used by rdp:settile and rdp:settilesize) typedef struct { // rdp:settile uint8_t format; // format: ARGB, IA, ... uint8_t size; // size: 4,8,16, or 32 bit uint16_t line; // size of one row (x axis) in 64 bit words uint16_t t_mem; // location in texture memory (in 64 bit words, max 512 (4MB)) uint8_t palette; // palette # to use uint8_t clamp_t; // clamp or wrap (y axis)? uint8_t mirror_t; // mirroring on (y axis)? uint8_t mask_t; // mask to wrap around (ex: 5 would wrap around 32) (y axis) uint8_t shift_t; // ??? (scaling) uint8_t clamp_s; // clamp or wrap (x axis)? uint8_t mirror_s; // mirroring on (x axis)? uint8_t mask_s; // mask to wrap around (x axis) uint8_t shift_s; // ??? (scaling) // rdp:settilesize uint16_t ul_s; // upper left s coordinate uint16_t ul_t; // upper left t coordinate uint16_t lr_s; // lower right s coordinate uint16_t lr_t; // lower right t coordinate float f_ul_s; float f_ul_t; // these are set by loadtile uint16_t t_ul_s; // upper left s coordinate uint16_t t_ul_t; // upper left t coordinate uint16_t t_lr_s; // lower right s coordinate uint16_t t_lr_t; // lower right t coordinate uint32_t width; uint32_t height; // uc0:texture uint8_t on; float s_scale; float t_scale; uint16_t org_s_scale; uint16_t org_t_scale; } TILE; // This structure forms the lookup table for cached textures typedef struct { uint32_t addr; // address in RDRAM uint32_t crc; // CRC check uint32_t palette; // Palette # uint32_t width; // width uint32_t height; // height uint32_t format; // format uint32_t size; // size uint32_t last_used; // what frame # was this texture last used (used for replacing) uint32_t line; uint32_t flags; // clamp/wrap/mirror flags uint32_t realwidth; // width of actual texture uint32_t realheight; // height of actual texture uint32_t lod; uint32_t aspect; uint8_t set_by; uint8_t texrecting; int f_mirror_s; int f_mirror_t; int f_wrap_s; int f_wrap_t; float scale_x; // texture scaling float scale_y; float scale; // general scale to 256 gfxTexInfo t_info; // texture info (glide) uint32_t tmem_addr; // addres in texture memory (glide) int uses; // 1 triangle that uses this texture int splits; // number of splits int splitheight; float c_off; // ul center texel offset (both x and y) float c_scl_x; // scale to lower-right center-texel x float c_scl_y; // scale to lower-right center-texel y uint32_t mod, mod_color, mod_color1, mod_color2, mod_factor; uint64_t ricecrc; int is_hires_tex; } CACHE_LUT; // Lights typedef struct { float r, g, b, a; // color float dir_x, dir_y, dir_z; // direction towards the light source float x, y, z, w; // light position float ca, la, qa; uint32_t nonblack; uint32_t nonzero; } LIGHT; typedef enum { ci_main, //0, main color image ci_zimg, //1, depth image ci_unknown, //2, status is unknown ci_useless, //3, status is unclear ci_old_copy, //4, auxiliary color image, copy of last color image from previous frame ci_copy, //5, auxiliary color image, copy of previous color image ci_copy_self, //6, main color image, it's content will be used to draw into itself ci_zcopy, //7, auxiliary color image, copy of depth image ci_aux, //8, auxiliary color image ci_aux_copy //9, auxiliary color image, partial copy of previous color image } CI_STATUS; // Frame buffers typedef struct { uint32_t addr; //color image address uint8_t format; uint8_t size; uint16_t width; uint16_t height; CI_STATUS status; int changed; } COLOR_IMAGE; typedef struct { gfxChipID_t tmu; uint32_t addr; //address of color image uint32_t end_addr; uint32_t tex_addr; //address in video memory uint32_t width; //width of color image uint32_t height; //height of color image uint8_t format; //format of color image uint8_t size; //format of color image uint8_t clear; //flag. texture buffer must be cleared uint8_t drawn; //flag. if equal to 1, this image was already drawn in current frame uint32_t crc; //checksum of the color image float scr_width; //width of rendered image float scr_height; //height of rendered image uint32_t tex_width; //width of texture buffer uint32_t tex_height; //height of texture buffer int tile; // uint16_t tile_uls; //shift from left bound of the texture uint16_t tile_ult; //shift from top of the texture uint32_t v_shift; //shift from top of the texture uint32_t u_shift; //shift from left of the texture float lr_u; float lr_v; float u_scale; //used to map vertex u,v coordinates into hires texture float v_scale; //used to map vertex u,v coordinates into hires texture CACHE_LUT * cache; //pointer to texture cache item gfxTexInfo info; uint16_t t_mem; } TBUFF_COLOR_IMAGE; typedef struct { gfxChipID_t tmu; uint32_t begin; //start of the block in video memory uint32_t end; //end of the block in video memory uint8_t count; //number of allocated texture buffers int clear_allowed; //stack of buffers can be cleared TBUFF_COLOR_IMAGE images[256]; } TEXTURE_BUFFER; #define NUMTEXBUF 92 class CRDP { public: CRDP(); ~CRDP(); bool init(); void free(); inline gfxVERTEX & vtx(int index) const { return m_vtx[index]; } inline TILE & tiles(int index) { return m_tiles[index]; } // Clipping int clip; // clipping flags gfxVERTEX *vtx1; //[256] copy vertex buffer #1 (used for clipping) gfxVERTEX *vtx2; //[256] copy vertex buffer #2 gfxVERTEX *vtxbuf; // current vertex buffer (reset to vtx, used to determine current vertex buffer) gfxVERTEX *vtxbuf2; int n_global; // Used to pass the number of vertices from clip_z to clip_tri int vtx_buffer; CACHE_LUT *cache[MAX_TMU]; //[MAX_CACHE] CACHE_LUT *cur_cache[MAX_TMU]; uint32_t cur_cache_n[MAX_TMU]; int n_cached[MAX_TMU]; // Vertices private: gfxVERTEX * m_vtx; //[MAX_VTX] public: int v0, vn; COLOR_IMAGE *frame_buffers; //[NUMTEXBUF+2] TEXTURE_BUFFER texbufs[2]; char RomName[21]; float vi_width; float vi_height; int window_changed; float offset_x, offset_y, offset_x_bak, offset_y_bak; float scale_x, scale_x_bak; float scale_y, scale_y_bak; float view_scale[3]; float view_trans[3]; float clip_min_x, clip_max_x, clip_min_y, clip_max_y; float clip_ratio; int updatescreen; uint32_t tri_n; // triangle counter uint32_t debug_n; // Program counter uint32_t pc[10]; // DList PC stack uint32_t pc_i; // current PC index in the stack int dl_count; // number of instructions before returning int LLE; // Segments uint32_t segment[16]; // Segment pointer // Marks the end of DList execution (done in uc?:enddl) bool halt; // Next command uint32_t cmd0; uint32_t cmd1; uint32_t cmd2; uint32_t cmd3; // Clipping SCISSOR scissor_o; SCISSOR scissor; int scissor_set; // Colors uint32_t fog_color; uint32_t fill_color; uint32_t prim_color; uint32_t blend_color; uint32_t env_color; uint32_t SCALE; uint32_t CENTER; uint32_t prim_lodmin, prim_lodfrac; uint16_t prim_depth; uint16_t prim_dz; uint8_t K4; uint8_t K5; enum { noise_none, noise_combine, noise_texture } noise; float col[4]; // color multiplier float coladd[4]; // color add/subtract float shade_factor; float col_2[4]; uint32_t cmb_flags, cmb_flags_2; // othermode_l flags int acmp; // 0 = none, 1 = threshold, 2 = dither int zsrc; // 0 = pixel, 1 = prim uint8_t alpha_dither_mode; // Matrices #pragma warning(push) #pragma warning(disable:4324) //structure was padded due to __declspec(align()) DECLAREALIGN16VAR(model[4][4]); #pragma warning(pop) DECLAREALIGN16VAR(proj[4][4]); DECLAREALIGN16VAR(combined[4][4]); DECLAREALIGN16VAR(dkrproj[3][4][4]); DECLAREALIGN16VAR(model_stack[32][4][4]); // 32 deep, will warn if overflow int model_i; // index in the model matrix stack int model_stack_size; // Textures TEXTURE_IMAGE timg; // 1 for each tmem address private: TILE m_tiles[8]; // 8 tile descriptors public: uint8_t tmem[4096]; // 4k tmem uint32_t addr[512]; // 512 addresses (used to determine address loaded from) LOAD_TILE_INFO load_info[512]; // 512 addresses. inforamation about tile loading. int cur_tile; // current tile int mipmap_level; int last_tile; // last tile set int last_tile_size; // last tile size set gfxChipID_t t0, t1; int best_tex; // if no 2-tmus, which texture? (0 or 1) int tex; int filter_mode; // Texture palette uint16_t pal_8[256]; uint32_t pal_8_crc[16]; uint32_t pal_256_crc; uint8_t tlut_mode; int LOD_en; int Persp_en; int persp_supported; int force_wrap; uint16_t pal_8_rice[512]; // Lighting uint32_t num_lights; LIGHT light[12]; float light_vector[12][3]; float lookat[2][3]; int use_lookat; // Combine modes uint32_t cycle1, cycle2, cycle_mode; uint8_t c_a0, c_b0, c_c0, c_d0, c_Aa0, c_Ab0, c_Ac0, c_Ad0; uint8_t c_a1, c_b1, c_c1, c_d1, c_Aa1, c_Ab1, c_Ac1, c_Ad1; uint8_t fbl_a0, fbl_b0, fbl_c0, fbl_d0; uint8_t fbl_a1, fbl_b1, fbl_c1, fbl_d1; uint8_t uncombined; // which is uncombined: 0x01=color 0x02=alpha 0x03=both // float YUV_C0, YUV_C1, YUV_C2, YUV_C3, YUV_C4; //YUV textures conversion coefficients // What needs updating uint32_t update; uint32_t flags; int first; uint32_t tex_ctr; // incremented every time textures are updated int allow_combine; // allow combine updating? int s2dex_tex_loaded; uint16_t bg_image_height; // Debug stuff uint32_t rm; // use othermode_l instead, this just as a check for changes uint32_t render_mode_changed; uint32_t geom_mode; uint32_t othermode_h; uint32_t othermode_l; // used to check if in texrect while loading texture uint8_t texrecting; //frame buffer related slots. Added by Gonetz uint32_t cimg, ocimg, zimg, tmpzimg, vi_org_reg; COLOR_IMAGE maincimg[2]; uint32_t last_drawn_ci_addr; uint32_t main_ci, main_ci_end, main_ci_bg, main_ci_last_tex_addr, zimg_end, last_bg; uint32_t ci_width, ci_height, ci_size, ci_end; uint32_t zi_width; int zi_lrx, zi_lry; uint8_t ci_count, num_of_ci, main_ci_index, copy_ci_index, copy_zi_index; int swap_ci_index, black_ci_index; uint32_t ci_upper_bound, ci_lower_bound; int motionblur, fb_drawn, fb_drawn_front, read_previous_ci, read_whole_frame; CI_STATUS ci_status; TBUFF_COLOR_IMAGE * cur_image; //image currently being drawn TBUFF_COLOR_IMAGE * tbuff_tex; //image, which corresponds to currently selected texture TBUFF_COLOR_IMAGE * aTBuffTex[2]; uint8_t cur_tex_buf; uint8_t acc_tex_buf; int skip_drawing; //rendering is not required. used for frame buffer emulation //fog related slots. Added by Gonetz float fog_multiplier, fog_offset; enum { fog_disabled, fog_enabled, fog_blend, fog_blend_inverse } fog_mode; }; void SetWireframeCol(); void ChangeSize(); void GoToFullScreen(); extern CRDP rdp; extern VOODOO voodoo; extern gfxTexInfo fontTex; extern gfxTexInfo cursorTex; extern uint32_t offset_font; extern uint32_t offset_cursor; extern uint32_t offset_textures; extern uint32_t offset_texbuf1; extern bool g_ucode_error_report; // RDP functions void rdp_reset(); extern const char *ACmp[]; extern const char *Mode0[]; extern const char *Mode1[]; extern const char *Mode2[]; extern const char *Mode3[]; extern const char *Alpha0[]; #define Alpha1 Alpha0 extern const char *Alpha2[]; #define Alpha3 Alpha0 extern const char *FBLa[]; extern const char *FBLb[]; extern const char *FBLc[]; extern const char *FBLd[]; extern const char *str_zs[]; extern const char *str_yn[]; extern const char *str_offon[]; extern const char *str_cull[]; // I=intensity probably extern const char *str_format[]; extern const char *str_size[]; extern const char *str_cm[]; extern const char *str_lod[]; extern const char *str_aspect[]; extern const char *str_filter[]; extern const char *str_tlut[]; extern const char *CIStatus[]; #define FBL_D_1 2 #define FBL_D_0 3 #ifndef maxval #define maxval(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef minval #define minval(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef HIWORD #define HIWORD(a) ((unsigned int)(a) >> 16) #endif #ifndef LOWORD #define LOWORD(a) ((a) & 0xFFFF) #endif // Convert from u0/v0/u1/v1 to the real coordinates without regard to tmu __inline void ConvertCoordsKeep(gfxVERTEX *v, int n) { for (int i = 0; i < n; i++) { v[i].uc(0) = v[i].u0; v[i].vc(0) = v[i].v0; v[i].uc(1) = v[i].u1; v[i].vc(1) = v[i].v1; } } // Convert from u0/v0/u1/v1 to the real coordinates based on the tmu they are on __inline void ConvertCoordsConvert(gfxVERTEX *v, int n) { for (int i = 0; i < n; i++) { v[i].uc(rdp.t0) = v[i].u0; v[i].vc(rdp.t0) = v[i].v0; v[i].uc(rdp.t1) = v[i].u1; v[i].vc(rdp.t1) = v[i].v1; } } __inline void AllowShadeMods(gfxVERTEX *v, int n) { for (int i = 0; i < n; i++) { v[i].shade_mod = 0; } } __inline void AddOffset(gfxVERTEX *v, int n) { for (int i = 0; i < n; i++) { v[i].x += rdp.offset_x; v[i].y += rdp.offset_y; } } __inline void CalculateFog(gfxVERTEX &v) { if (rdp.flags & FOG_ENABLED) { if (v.w < 0.0f) v.f = 0.0f; else v.f = minval(255.0f, maxval(0.0f, v.z_w * rdp.fog_multiplier + rdp.fog_offset)); v.a = (uint8_t)v.f; } else { v.f = 1.0f; } } void newSwapBuffers(); extern int SwapOK; // ** utility functions void load_palette(uint32_t addr, uint16_t start, uint16_t count); void setTBufTex(uint16_t t_mem, uint32_t cnt); // ** RDP graphics functions ** void undef(); void spnoop(); void rdp_noop(); void rdp_texrect(); //void rdp_texrectflip(); void rdp_loadsync(); void rdp_pipesync(); void rdp_tilesync(); void rdp_fullsync(); void rdp_setkeygb(); void rdp_setkeyr(); void rdp_setconvert(); void rdp_setscissor(); void rdp_setprimdepth(); void rdp_loadtlut(); void rdp_settilesize(); void rdp_loadblock(); void rdp_loadtile(); void rdp_settile(); void rdp_fillrect(); void rdp_setfillcolor(); void rdp_setfogcolor(); void rdp_setblendcolor(); void rdp_setprimcolor(); void rdp_setenvcolor(); void rdp_setcombine(); void rdp_settextureimage(); void rdp_setdepthimage(); void rdp_setcolorimage(); void rdp_setothermode(); void rdp_trifill(); void rdp_trishade(); void rdp_tritxtr(); void rdp_trishadetxtr(); void rdp_trifillz(); void rdp_trishadez(); void rdp_tritxtrz(); void rdp_trishadetxtrz(); void rdphalf_1(); void rdphalf_2(); void rdphalf_cont(); void rsp_reserved0(); void rsp_reserved1(); void rsp_reserved2(); void rsp_reserved3(); void ys_memrect(); void microcheck(); extern const char *str_dither[]; extern uint8_t microcode[4096];