summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/n64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/n64.c')
-rw-r--r--src/mame/video/n64.c3479
1 files changed, 3479 insertions, 0 deletions
diff --git a/src/mame/video/n64.c b/src/mame/video/n64.c
new file mode 100644
index 00000000000..31e54dbc5e5
--- /dev/null
+++ b/src/mame/video/n64.c
@@ -0,0 +1,3479 @@
+/*
+ Nintendo 64 Video Hardware
+*/
+
+#include "driver.h"
+#include "includes/n64.h"
+
+#define LOG_RDP_EXECUTION 0
+
+#if LOG_RDP_EXECUTION
+static FILE *rdp_exec;
+#endif
+
+/* defined in systems/n64.c */
+extern UINT32 *rdram;
+extern UINT32 *rsp_imem;
+extern UINT32 *rsp_dmem;
+extern void dp_full_sync(void);
+
+extern UINT32 vi_origin;
+extern UINT32 vi_width;
+extern UINT32 vi_control;
+
+extern UINT32 dp_start;
+extern UINT32 dp_end;
+extern UINT32 dp_current;
+extern UINT32 dp_status;
+
+static UINT32 rdp_cmd_data[0x1000];
+static int rdp_cmd_ptr = 0;
+static int rdp_cmd_cur = 0;
+
+typedef struct
+{
+ int lx, rx;
+ int s, ds;
+ int t, dt;
+ int w, dw;
+ int r, dr;
+ int g, dg;
+ int b, db;
+ int a, da;
+ int z, dz;
+} SPAN;
+
+static SPAN span[1024];
+
+/*****************************************************************************/
+
+#define BYTE_ADDR_XOR BYTE4_XOR_BE(0)
+#define WORD_ADDR_XOR (WORD_XOR_BE(0) >> 1)
+
+typedef struct
+{
+ UINT8 r, g, b, a;
+} COLOR;
+
+typedef struct
+{
+ UINT16 xl, yl, xh, yh; // 10.2 fixed-point
+} RECTANGLE;
+
+typedef struct
+{
+ int tilenum;
+ UINT16 xl, yl, xh, yh; // 10.2 fixed-point
+ INT16 s, t; // 10.5 fixed-point
+ INT16 dsdx, dtdy; // 5.10 fixed-point
+} TEX_RECTANGLE;
+
+typedef struct
+{
+ int format, size;
+ UINT32 line;
+ UINT32 tmem;
+ int palette;
+ // TODO: clamp & mirror parameters
+ int ct, mt, cs, ms;
+ int mask_t, shift_t, mask_s, shift_s;
+
+ UINT16 sl, tl, sh, th; // 10.2 fixed-point
+} TILE;
+
+typedef struct
+{
+ int sub_a_rgb0;
+ int sub_b_rgb0;
+ int mul_rgb0;
+ int add_rgb0;
+ int sub_a_a0;
+ int sub_b_a0;
+ int mul_a0;
+ int add_a0;
+
+ int sub_a_rgb1;
+ int sub_b_rgb1;
+ int mul_rgb1;
+ int add_rgb1;
+ int sub_a_a1;
+ int sub_b_a1;
+ int mul_a1;
+ int add_a1;
+} COMBINE_MODES;
+
+typedef struct
+{
+ int cycle_type;
+ int persp_tex_en;
+ int detail_tex_en;
+ int sharpen_tex_en;
+ int tex_lod_en;
+ int en_tlut;
+ int tlut_type;
+ int sample_type;
+ int mid_texel;
+ int bi_lerp0;
+ int bi_lerp1;
+ int convert_one;
+ int key_en;
+ int rgb_dither_sel;
+ int alpha_dither_sel;
+ int blend_m1a_0;
+ int blend_m1a_1;
+ int blend_m1b_0;
+ int blend_m1b_1;
+ int blend_m2a_0;
+ int blend_m2a_1;
+ int blend_m2b_0;
+ int blend_m2b_1;
+ int force_blend;
+ int alpha_cvg_select;
+ int cvg_times_alpha;
+ int z_mode;
+ int cvg_dest;
+ int color_on_cvg;
+ int image_read_en;
+ int z_update_en;
+ int z_compare_en;
+ int antialias_en;
+ int z_source_sel;
+ int dither_alpha_en;
+ int alpha_compare_en;
+} OTHER_MODES;
+
+/*****************************************************************************/
+
+#define PIXEL_SIZE_4BIT 0
+#define PIXEL_SIZE_8BIT 1
+#define PIXEL_SIZE_16BIT 2
+#define PIXEL_SIZE_32BIT 3
+
+#define CYCLE_TYPE_1 0
+#define CYCLE_TYPE_2 1
+#define CYCLE_TYPE_COPY 2
+#define CYCLE_TYPE_FILL 3
+
+static COMBINE_MODES combine;
+static OTHER_MODES other_modes;
+
+static COLOR blend_color;
+static COLOR prim_color;
+static COLOR env_color;
+static COLOR fog_color;
+static COLOR combined_color;
+static COLOR texel0_color;
+static COLOR texel1_color;
+static COLOR shade_color;
+
+static COLOR one_color = { 0xff, 0xff, 0xff, 0xff };
+static COLOR zero_color = { 0x00, 0x00, 0x00, 0x00 };
+
+// combiner inputs
+static UINT8 *combiner_rgbsub_a_r[2];
+static UINT8 *combiner_rgbsub_a_g[2];
+static UINT8 *combiner_rgbsub_a_b[2];
+static UINT8 *combiner_rgbsub_b_r[2];
+static UINT8 *combiner_rgbsub_b_g[2];
+static UINT8 *combiner_rgbsub_b_b[2];
+static UINT8 *combiner_rgbmul_r[2];
+static UINT8 *combiner_rgbmul_g[2];
+static UINT8 *combiner_rgbmul_b[2];
+static UINT8 *combiner_rgbadd_r[2];
+static UINT8 *combiner_rgbadd_g[2];
+static UINT8 *combiner_rgbadd_b[2];
+
+static UINT8 *combiner_alphasub_a[2];
+static UINT8 *combiner_alphasub_b[2];
+static UINT8 *combiner_alphamul[2];
+static UINT8 *combiner_alphaadd[2];
+
+// blender input
+static UINT8 *blender1a_r[2];
+static UINT8 *blender1a_g[2];
+static UINT8 *blender1a_b[2];
+static UINT8 *blender1b_a[2];
+static UINT8 *blender2a_r[2];
+static UINT8 *blender2a_g[2];
+static UINT8 *blender2a_b[2];
+static UINT8 *blender2b_a[2];
+
+
+static COLOR pixel_color;
+static COLOR inv_pixel_color;
+static COLOR blended_pixel_color;
+static COLOR memory_color;
+
+
+
+static UINT32 fill_color; // packed 16-bit or 32-bit, depending on framebuffer format
+
+static UINT16 primitive_z;
+static UINT16 primitive_delta_z;
+
+static int fb_format;
+static int fb_size;
+int fb_width;
+static UINT32 fb_address;
+
+static UINT32 zb_address;
+
+static int ti_format;
+static int ti_size;
+static int ti_width;
+static UINT32 ti_address;
+
+static TILE tile[8];
+
+static RECTANGLE clip;
+
+static UINT8 *texture_cache;
+static UINT32 tlut[256];
+
+#define CLAMP(S, T) \
+do \
+{ \
+ if (clamp_s) \
+ { \
+ if (S < (tsl >> 2)) S = (tsl >> 2); \
+ if (S > (tsh >> 2)) S = (tsh >> 2); \
+ } \
+ if (mirror_s) \
+ { \
+ if (S < (tsl >> 2)) S = abs(S - (tsl >> 2)); \
+ if (S > (tsh >> 2)) S = abs(S - (tsh >> 2)); \
+ } \
+ if (mask_s != 0) \
+ { \
+ S &= (((UINT32)(0xffffffff) >> (32-mask_s))); \
+ } \
+ if (clamp_t) \
+ { \
+ if (T < (ttl >> 2)) T = (ttl >> 2); \
+ if (T > (tth >> 2)) T = (tth >> 2); \
+ } \
+ if (mirror_t) \
+ { \
+ if (T < (ttl >> 2)) T = abs(T - (ttl >> 2)); \
+ if (T > (tth >> 2)) T = abs(T - (tth >> 2)); \
+ } \
+ if (mask_t != 0) \
+ { \
+ T &= (((UINT32)(0xffffffff) >> (32-mask_t))); \
+ } \
+} \
+while (0)
+
+/*****************************************************************************/
+
+
+
+VIDEO_START(n64)
+{
+#if LOG_RDP_EXECUTION
+ rdp_exec = fopen("rdp_execute.txt", "wt");
+#endif
+
+ texture_cache = auto_malloc(0x100000);
+
+ combiner_rgbsub_a_r[0] = combiner_rgbsub_a_r[1] = &one_color.r;
+ combiner_rgbsub_a_g[0] = combiner_rgbsub_a_g[1] = &one_color.g;
+ combiner_rgbsub_a_b[0] = combiner_rgbsub_a_b[1] = &one_color.b;
+ combiner_rgbsub_b_r[0] = combiner_rgbsub_b_r[1] = &one_color.r;
+ combiner_rgbsub_b_g[0] = combiner_rgbsub_b_g[1] = &one_color.g;
+ combiner_rgbsub_b_b[0] = combiner_rgbsub_b_b[1] = &one_color.b;
+ combiner_rgbmul_r[0] = combiner_rgbmul_r[1] = &one_color.r;
+ combiner_rgbmul_g[0] = combiner_rgbmul_g[1] = &one_color.g;
+ combiner_rgbmul_b[0] = combiner_rgbmul_b[1] = &one_color.b;
+ combiner_rgbadd_r[0] = combiner_rgbadd_r[1] = &one_color.r;
+ combiner_rgbadd_g[0] = combiner_rgbadd_g[1] = &one_color.g;
+ combiner_rgbadd_b[0] = combiner_rgbadd_b[1] = &one_color.b;
+
+ combiner_alphasub_a[0] = combiner_alphasub_a[1] = &one_color.a;
+ combiner_alphasub_b[0] = combiner_alphasub_b[1] = &one_color.a;
+ combiner_alphamul[0] = combiner_alphamul[1] = &one_color.a;
+ combiner_alphaadd[0] = combiner_alphaadd[1] = &one_color.a;
+
+ blender1a_r[0] = blender1a_r[1] = &pixel_color.r;
+ blender1a_g[0] = blender1a_g[1] = &pixel_color.r;
+ blender1a_b[0] = blender1a_b[1] = &pixel_color.r;
+ blender1b_a[0] = blender1b_a[1] = &pixel_color.r;
+ blender2a_r[0] = blender2a_r[1] = &pixel_color.r;
+ blender2a_g[0] = blender2a_g[1] = &pixel_color.r;
+ blender2a_b[0] = blender2a_b[1] = &pixel_color.r;
+ blender2b_a[0] = blender2b_a[1] = &pixel_color.r;
+}
+
+VIDEO_UPDATE(n64)
+{
+ int i, j;
+ int height = (vi_control & 0x40) ? 479 : 239;
+
+ switch (vi_control & 0x3)
+ {
+ case 0: // blank/no signal
+ {
+ break;
+ }
+
+ case 2: // RGBA5551
+ {
+ UINT16 *frame_buffer = (UINT16*)&rdram[vi_origin / 4];
+ if (frame_buffer)
+ {
+ for (j=0; j <height; j++)
+ {
+ UINT32 *d = BITMAP_ADDR32(bitmap, j, 0);
+ for (i=0; i < fb_width; i++)
+ {
+ UINT16 pix = *frame_buffer++;
+ int r = ((pix >> 11) & 0x1f) << 3;
+ int g = ((pix >> 6) & 0x1f) << 3;
+ int b = ((pix >> 1) & 0x1f) << 3;
+ d[i^1] = (r << 16) | (g << 8) | b;
+ }
+ }
+ }
+ break;
+ }
+
+ case 3: // RGBA8888
+ {
+ UINT32 *frame_buffer = (UINT32*)&rdram[vi_origin / 4];
+ if (frame_buffer)
+ {
+ for (j=0; j < height; j++)
+ {
+ UINT32 *d = BITMAP_ADDR32(bitmap, j, 0);
+ for (i=0; i < fb_width; i++)
+ {
+ UINT32 pix = *frame_buffer++;
+ *d++ = pix & 0xffffff;
+ }
+ }
+ }
+ break;
+ }
+
+ default: fatalerror("Unknown framebuffer format %d\n", vi_control & 0x3);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+
+INLINE void SET_SUBA_RGB_INPUT(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code)
+{
+ switch (code & 0xf)
+ {
+ case 0: *input_r = &combined_color.r; *input_g = &combined_color.g; *input_b = &combined_color.b; break;
+ case 1: *input_r = &texel0_color.r; *input_g = &texel0_color.g; *input_b = &texel0_color.b; break;
+ case 2: *input_r = &texel1_color.r; *input_g = &texel1_color.g; *input_b = &texel1_color.b; break;
+ case 3: *input_r = &prim_color.r; *input_g = &prim_color.g; *input_b = &prim_color.b; break;
+ case 4: *input_r = &shade_color.r; *input_g = &shade_color.g; *input_b = &shade_color.b; break;
+ case 5: *input_r = &env_color.r; *input_g = &env_color.g; *input_b = &env_color.b; break;
+ case 6: *input_r = &one_color.r; *input_g = &one_color.g; *input_b = &one_color.b; break;
+ case 7: break; //TODO fatalerror("SET_SUBA_RGB_INPUT: noise\n"); break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ {
+ *input_r = &zero_color.r; *input_g = &zero_color.g; *input_b = &zero_color.b; break;
+ }
+ }
+}
+
+INLINE void SET_SUBB_RGB_INPUT(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code)
+{
+ switch (code & 0xf)
+ {
+ case 0: *input_r = &combined_color.r; *input_g = &combined_color.g; *input_b = &combined_color.b; break;
+ case 1: *input_r = &texel0_color.r; *input_g = &texel0_color.g; *input_b = &texel0_color.b; break;
+ case 2: *input_r = &texel1_color.r; *input_g = &texel1_color.g; *input_b = &texel1_color.b; break;
+ case 3: *input_r = &prim_color.r; *input_g = &prim_color.g; *input_b = &prim_color.b; break;
+ case 4: *input_r = &shade_color.r; *input_g = &shade_color.g; *input_b = &shade_color.b; break;
+ case 5: *input_r = &env_color.r; *input_g = &env_color.g; *input_b = &env_color.b; break;
+ case 6: fatalerror("SET_SUBB_RGB_INPUT: key_center\n"); break;
+ case 7: fatalerror("SET_SUBB_RGB_INPUT: convert_k4\n"); break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ {
+ *input_r = &zero_color.r; *input_g = &zero_color.g; *input_b = &zero_color.b; break;
+ }
+ }
+}
+
+INLINE void SET_MUL_RGB_INPUT(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code)
+{
+ switch (code & 0x1f)
+ {
+ case 0: *input_r = &combined_color.r; *input_g = &combined_color.g; *input_b = &combined_color.b; break;
+ case 1: *input_r = &texel0_color.r; *input_g = &texel0_color.g; *input_b = &texel0_color.b; break;
+ case 2: *input_r = &texel1_color.r; *input_g = &texel1_color.g; *input_b = &texel1_color.b; break;
+ case 3: *input_r = &prim_color.r; *input_g = &prim_color.g; *input_b = &prim_color.b; break;
+ case 4: *input_r = &shade_color.r; *input_g = &shade_color.g; *input_b = &shade_color.b; break;
+ case 5: *input_r = &env_color.r; *input_g = &env_color.g; *input_b = &env_color.b; break;
+ case 6: fatalerror("SET_MUL_RGB_INPUT: key scale\n"); break;
+ case 7: *input_r = &combined_color.a; *input_g = &combined_color.a; *input_b = &combined_color.a; break;
+ case 8: *input_r = &texel0_color.a; *input_g = &texel0_color.a; *input_b = &texel0_color.a; break;
+ case 9: *input_r = &texel1_color.a; *input_g = &texel1_color.a; *input_b = &texel1_color.a; break;
+ case 10: *input_r = &prim_color.a; *input_g = &prim_color.a; *input_b = &prim_color.a; break;
+ case 11: *input_r = &shade_color.a; *input_g = &shade_color.a; *input_b = &shade_color.a; break;
+ case 12: *input_r = &env_color.a; *input_g = &env_color.a; *input_b = &env_color.a; break;
+ case 13: break;//TODO fatalerror("SET_MUL_RGB_INPUT: lod fraction\n"); break;
+ case 14: break;//TODO fatalerror("SET_MUL_RGB_INPUT: primitive lod fraction\n"); break;
+ case 15: break;//TODO fatalerror("SET_MUL_RGB_INPUT: convert k5\n"); break;
+ case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
+ case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31:
+ {
+ *input_r = &zero_color.r; *input_g = &zero_color.g; *input_b = &zero_color.b; break;
+ }
+ }
+}
+
+INLINE void SET_ADD_RGB_INPUT(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code)
+{
+ switch (code & 0x7)
+ {
+ case 0: *input_r = &combined_color.r; *input_g = &combined_color.g; *input_b = &combined_color.b; break;
+ case 1: *input_r = &texel0_color.r; *input_g = &texel0_color.g; *input_b = &texel0_color.b; break;
+ case 2: *input_r = &texel1_color.r; *input_g = &texel1_color.g; *input_b = &texel1_color.b; break;
+ case 3: *input_r = &prim_color.r; *input_g = &prim_color.g; *input_b = &prim_color.b; break;
+ case 4: *input_r = &shade_color.r; *input_g = &shade_color.g; *input_b = &shade_color.b; break;
+ case 5: *input_r = &env_color.r; *input_g = &env_color.g; *input_b = &env_color.b; break;
+ case 6: *input_r = &one_color.r; *input_g = &one_color.g; *input_b = &one_color.b; break;
+ case 7: *input_r = &zero_color.r; *input_g = &zero_color.g; *input_b = &zero_color.b; break;
+ }
+}
+
+INLINE void SET_SUB_ALPHA_INPUT(UINT8 **input, int code)
+{
+ switch (code & 0x7)
+ {
+ case 0: *input = &combined_color.a; break;
+ case 1: *input = &texel0_color.a; break;
+ case 2: *input = &texel1_color.a; break;
+ case 3: *input = &prim_color.a; break;
+ case 4: *input = &shade_color.a; break;
+ case 5: *input = &env_color.a; break;
+ case 6: *input = &one_color.a; break;
+ case 7: *input = &zero_color.a; break;
+ }
+}
+
+INLINE void SET_MUL_ALPHA_INPUT(UINT8 **input, int code)
+{
+ switch (code & 0x7)
+ {
+ case 0: break;//TODO fatalerror("SET_MUL_ALPHA_INPUT: lod fraction\n"); break;
+ case 1: *input = &texel0_color.a; break;
+ case 2: *input = &texel1_color.a; break;
+ case 3: *input = &prim_color.a; break;
+ case 4: *input = &shade_color.a; break;
+ case 5: *input = &env_color.a; break;
+ case 6: break;//TODO fatalerror("SET_MUL_ALPHA_INPUT: primitive lod fraction\n"); break;
+ case 7: *input = &zero_color.a; break;
+ }
+}
+
+
+
+INLINE COLOR COLOR_COMBINER(int cycle)
+{
+ COLOR c;
+ UINT32 r, g, b, a;
+
+ r = (((int)((UINT8)(*combiner_rgbsub_a_r[cycle]) - (UINT8)(*combiner_rgbsub_b_r[cycle])) *
+ *combiner_rgbmul_r[cycle]) >> 8) + *combiner_rgbadd_r[cycle];
+
+ g = (((int)((UINT8)(*combiner_rgbsub_a_g[cycle]) - (UINT8)(*combiner_rgbsub_b_g[cycle])) *
+ *combiner_rgbmul_g[cycle]) >> 8) + *combiner_rgbadd_g[cycle];
+
+ b = (((int)((UINT8)(*combiner_rgbsub_a_b[cycle]) - (UINT8)(*combiner_rgbsub_b_b[cycle])) *
+ *combiner_rgbmul_b[cycle]) >> 8) + *combiner_rgbadd_b[cycle];
+
+ a = (((int)((UINT8)(*combiner_alphasub_a[cycle]) - (UINT8)(*combiner_alphasub_b[cycle])) *
+ *combiner_alphamul[cycle]) >> 8) + *combiner_alphaadd[cycle];
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ if (a > 255) a = 255;
+
+ c.r = r; c.g = g; c.b = b; c.a = a;
+ return c;
+}
+
+
+
+INLINE void SET_BLENDER_INPUT(int cycle, int which, UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, UINT8 **input_a, int a, int b)
+{
+ switch (a & 0x3)
+ {
+ case 0:
+ {
+ if (cycle == 0)
+ {
+ *input_r = &pixel_color.r;
+ *input_g = &pixel_color.g;
+ *input_b = &pixel_color.b;
+ }
+ else
+ {
+ *input_r = &blended_pixel_color.r;
+ *input_g = &blended_pixel_color.g;
+ *input_b = &blended_pixel_color.b;
+ }
+ break;
+ }
+
+ case 1:
+ {
+ //fatalerror("SET_BLENDER_INPUT: cycle %d, input A: memory color\n", cycle);
+ // TODO
+ *input_r = &memory_color.r;
+ *input_g = &memory_color.g;
+ *input_b = &memory_color.b;
+ break;
+ }
+
+ case 2:
+ {
+ *input_r = &blend_color.r; *input_g = &blend_color.g; *input_b = &blend_color.b;
+ break;
+ }
+
+ case 3:
+ {
+ *input_r = &fog_color.r; *input_g = &fog_color.g; *input_b = &fog_color.b;
+ break;
+ }
+ }
+
+ if (which == 0)
+ {
+ switch (b & 0x3)
+ {
+ case 0: *input_a = &pixel_color.a; break;
+ case 1: *input_a = &one_color.a; break;
+ case 2: *input_a = &shade_color.a; break;
+ case 3: *input_a = &zero_color.a; break;
+ }
+ }
+ else
+ {
+ switch (b & 0x3)
+ {
+ case 0: *input_a = &inv_pixel_color.a; break;
+ case 1: *input_a = &memory_color.a; break;
+ case 2: *input_a = &one_color.a; break;
+ case 3: *input_a = &zero_color.a; break;
+ }
+ }
+}
+
+static const UINT8 dither_matrix_4x4[16] =
+{
+ 0, 8, 2, 10,
+ 12, 4, 14, 6,
+ 3, 11, 1, 9,
+ 15, 7, 13, 5
+};
+
+#define DITHER_RB(val,dith) ((((val) << 1) - ((val) >> 4) + ((val) >> 7) + (dith)) >> 1)
+#define DITHER_G(val,dith) ((((val) << 2) - ((val) >> 4) + ((val) >> 6) + (dith)) >> 2)
+
+INLINE void BLENDER1_16(UINT16 *fb, COLOR c, int dith)
+{
+ int r, g, b;
+
+ pixel_color.r = c.r; inv_pixel_color.r = 0xff - c.r;
+ pixel_color.g = c.g; inv_pixel_color.g = 0xff - c.g;
+ pixel_color.b = c.b; inv_pixel_color.b = 0xff - c.b;
+ pixel_color.a = c.a; inv_pixel_color.a = 0xff - c.a;
+
+
+
+ if (other_modes.image_read_en)
+ {
+ UINT16 mem = *fb;
+ memory_color.r = ((mem >> 11) & 0x1f) << 3;
+ memory_color.g = ((mem >> 6) & 0x1f) << 3;
+ memory_color.b = ((mem >> 1) & 0x1f) << 3;
+ memory_color.a = 0;
+ }
+
+ r = (((int)(*blender1a_r[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_r[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ g = (((int)(*blender1a_g[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_g[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ b = (((int)(*blender1a_b[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_b[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ //r = g = b = 0xff;
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ if (other_modes.rgb_dither_sel != 3)
+ {
+ r = DITHER_RB(r, dith);
+ g = DITHER_G (g, dith);
+ b = DITHER_RB(b, dith);
+ }
+
+ if (c.a != 0)
+ {
+ *fb = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1);
+ }
+}
+
+INLINE void BLENDER2_16(UINT16 *fb, COLOR c1, COLOR c2, int dith)
+{
+ int r, g, b;
+
+ pixel_color.r = c1.r; inv_pixel_color.r = 0xff - c1.r;
+ pixel_color.g = c1.g; inv_pixel_color.g = 0xff - c1.g;
+ pixel_color.b = c1.b; inv_pixel_color.b = 0xff - c1.b;
+ pixel_color.a = c1.a; inv_pixel_color.a = 0xff - c1.a;
+
+ if (other_modes.image_read_en)
+ {
+ UINT16 mem = *fb;
+ memory_color.r = ((mem >> 11) & 0x1f) << 3;
+ memory_color.g = ((mem >> 6) & 0x1f) << 3;
+ memory_color.b = ((mem >> 1) & 0x1f) << 3;
+ memory_color.a = 0;
+ }
+
+ r = (((int)(*blender1a_r[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_r[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ g = (((int)(*blender1a_g[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_g[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ b = (((int)(*blender1a_b[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_b[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ blended_pixel_color.r = r;
+ blended_pixel_color.g = g;
+ blended_pixel_color.b = b;
+
+ pixel_color.r = c2.r; inv_pixel_color.r = 0xff - c2.r;
+ pixel_color.g = c2.g; inv_pixel_color.g = 0xff - c2.g;
+ pixel_color.b = c2.b; inv_pixel_color.b = 0xff - c2.b;
+ pixel_color.a = c2.a; inv_pixel_color.a = 0xff - c2.a;
+
+ r = (((int)(*blender1a_r[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_r[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ g = (((int)(*blender1a_g[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_g[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ b = (((int)(*blender1a_b[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_b[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ r = c1.r;
+ g = c1.g;
+ b = c1.b;
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ if (other_modes.rgb_dither_sel != 3)
+ {
+ r = DITHER_RB(r, dith);
+ g = DITHER_G (g, dith);
+ b = DITHER_RB(b, dith);
+ }
+
+ {
+ *fb = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1);
+ }
+}
+
+/*****************************************************************************/
+
+static void fill_rectangle_16bit(RECTANGLE *rect)
+{
+ UINT16 *fb = (UINT16*)&rdram[(fb_address / 4)];
+ int index, i, j;
+ int x1 = rect->xh / 4;
+ int x2 = rect->xl / 4;
+ int y1 = rect->yh / 4;
+ int y2 = rect->yl / 4;
+ int clipx1, clipx2, clipy1, clipy2;
+
+ UINT16 fill_color1, fill_color2;
+ fill_color1 = (fill_color >> 16) & 0xffff;
+ fill_color2 = (fill_color >> 0) & 0xffff;
+
+ // TODO: clip
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ // clip
+ if (x1 < clipx1)
+ {
+ x1 = clipx1;
+ }
+ if (y1 < clipy1)
+ {
+ y1 = clipy1;
+ }
+ if (x2 >= clipx2)
+ {
+ x2 = clipx2-1;
+ }
+ if (y2 >= clipy2)
+ {
+ y2 = clipy2-1;
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_FILL)
+ {
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ fb[(index + i) ^ 1] = (i & 1) ? fill_color1 : fill_color2;
+ }
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ shade_color.r = prim_color.r;
+ shade_color.g = prim_color.g;
+ shade_color.b = prim_color.b;
+ shade_color.a = prim_color.a;
+
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ COLOR c = COLOR_COMBINER(0);
+
+ //BLENDER1_16(&fb[(index + i) ^ 1], c);
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ BLENDER1_16(&fb[(index + i) ^ WORD_ADDR_XOR], c, dith);
+ }
+ }
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ shade_color.r = prim_color.r;
+ shade_color.g = prim_color.g;
+ shade_color.b = prim_color.b;
+ shade_color.a = prim_color.a;
+
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ COLOR c1 = COLOR_COMBINER(0);
+ COLOR c2 = COLOR_COMBINER(1);
+
+ //BLENDER1_16(&fb[(index + i) ^ 1], c);
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ BLENDER2_16(&fb[(index + i) ^ WORD_ADDR_XOR], c1, c2, dith);
+ }
+ }
+ }
+ }
+ else
+ {
+ fatalerror("fill_rectangle_16bit: cycle type copy");
+ }
+}
+
+#define XOR_SWAP_BYTE 4
+#define XOR_SWAP_WORD 2
+#define XOR_SWAP_DWORD 1
+
+INLINE void FETCH_TEXEL(COLOR *color, int s, int t, UINT32 twidth, UINT32 tformat, UINT32 tsize, UINT32 tbase)
+{
+ if (t < 0) t = 0;
+ if (s < 0) s = 0;
+
+ switch (tformat)
+ {
+ case 0: // RGBA
+ {
+ switch (tsize)
+ {
+ case 0:
+ color->r = color->g = color->b = color->a = 0xff;
+ break;
+ case 1:
+ // FIXME?: Extreme-G 2 does this
+ color->r = color->g = color->b = color->a = 0xff;
+ break;
+ case PIXEL_SIZE_16BIT:
+ {
+ UINT16 *tc = (UINT16*)texture_cache;
+ int taddr = ((tbase/2) + ((t) * (twidth/2)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
+ UINT16 c = tc[taddr ^ WORD_ADDR_XOR];
+
+ color->r = ((c >> 11) & 0x1f) << 3;
+ color->g = ((c >> 6) & 0x1f) << 3;
+ color->b = ((c >> 1) & 0x1f) << 3;
+ color->a = (c & 1) ? 0xff : 0;
+ break;
+ }
+ case PIXEL_SIZE_32BIT:
+ {
+ UINT32 *tc = (UINT32*)texture_cache;
+ int taddr = ((tbase/4) + ((t) * (twidth/2)) + (s)) ^ ((t & 1) ? XOR_SWAP_DWORD : 0);
+ UINT32 c = tc[taddr];
+
+ color->r = ((c >> 24) & 0xff);
+ color->g = ((c >> 16) & 0xff);
+ color->b = ((c >> 8) & 0xff);
+ color->a = ((c >> 0) & 0xff);
+ break;
+ }
+ default:
+ color->r = color->g = color->b = color->a = 0xff;
+ fatalerror("FETCH_TEXEL: unknown RGBA texture size %d\n", tsize);
+ break;
+ }
+ break;
+ }
+ case 2: // Color Index
+ {
+ switch (tsize)
+ {
+ case PIXEL_SIZE_4BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
+ UINT16 c = tlut[p ^ WORD_ADDR_XOR];
+
+ if (other_modes.tlut_type == 0)
+ {
+ color->r = ((c >> 11) & 0x1f) << 3;
+ color->g = ((c >> 6) & 0x1f) << 3;
+ color->b = ((c >> 1) & 0x1f) << 3;
+ color->a = (c & 1) ? 0xff : 0;
+ }
+ else
+ {
+ color->r = color->g = color->b = (c >> 8) & 0xff;
+ color->a = c & 0xff;
+ }
+ break;
+ }
+ case PIXEL_SIZE_8BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 p = tc[taddr ^ BYTE_ADDR_XOR];
+ UINT16 c = tlut[p ^ WORD_ADDR_XOR];
+
+ if (other_modes.tlut_type == 0)
+ {
+ color->r = ((c >> 11) & 0x1f) << 3;
+ color->g = ((c >> 6) & 0x1f) << 3;
+ color->b = ((c >> 1) & 0x1f) << 3;
+ color->a = (c & 1) ? 0xff : 0;
+ }
+ else
+ {
+ color->r = color->g = color->b = (c >> 8) & 0xff;
+ color->a = c & 0xff;
+ }
+ break;
+ }
+ case 2:
+ // FIXME?: Clay Fighter Sculptor's Cut does this..
+ color->r = color->g = color->b = color->a = 0xff;
+ break;
+ default:
+ color->r = color->g = color->b = color->a = 0xff;
+ fatalerror("FETCH_TEXEL: unknown CI texture size %d\n", tsize);
+ break;
+ }
+ break;
+ }
+ case 3: // Intensity + Alpha
+ {
+ switch (tsize)
+ {
+ case PIXEL_SIZE_4BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
+ UINT8 i = ((p & 0xe) << 4) | ((p & 0xe) << 1) | (p & 0xe >> 2);
+
+ color->r = i;
+ color->g = i;
+ color->b = i;
+ color->a = (p & 0x1) ? 0xff : 0;
+ break;
+ }
+ case PIXEL_SIZE_8BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 p = tc[taddr ^ BYTE_ADDR_XOR];
+ UINT8 i = (p >> 4) | (p & 0xf0);
+
+ color->r = i;
+ color->g = i;
+ color->b = i;
+ color->a = (p & 0xf) | ((p << 4) & 0xf0);
+ break;
+ }
+ case PIXEL_SIZE_16BIT:
+ {
+ UINT16 *tc = (UINT16*)texture_cache;
+ int taddr = (tbase + ((t) * (twidth/2)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
+ UINT16 c = tc[taddr ^ WORD_ADDR_XOR];
+ UINT8 i = (c >> 8);
+
+ color->r = i;
+ color->g = i;
+ color->b = i;
+ color->a = c & 0xff;
+ break;
+ }
+ default:
+ color->r = color->g = color->b = color->a = 0xff;
+ fatalerror("FETCH_TEXEL: unknown IA texture size %d\n", tsize);
+ break;
+ }
+ break;
+ }
+ case 4: // Intensity
+ {
+ switch (tsize)
+ {
+ case PIXEL_SIZE_4BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 c = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
+ c |= (c << 4);
+
+ color->r = c;
+ color->g = c;
+ color->b = c;
+ color->a = c;
+ break;
+ }
+ case PIXEL_SIZE_8BIT:
+ {
+ UINT8 *tc = (UINT8*)texture_cache;
+ int taddr = (tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
+ UINT8 c = tc[taddr ^ BYTE_ADDR_XOR];
+
+ color->r = c;
+ color->g = c;
+ color->b = c;
+ color->a = c;
+ break;
+ }
+ default:
+ color->r = color->g = color->b = color->a = 0xff;
+ fatalerror("FETCH_TEXEL: unknown I texture size %d\n", tsize);
+ break;
+ }
+ break;
+ }
+ default:
+ {
+ color->r = color->g = color->b = color->a = 0xff;
+ fatalerror("FETCH_TEXEL: unknown texture format %d\n", tformat);
+ break;
+ }
+ }
+}
+
+#if 1
+#define TEXTURE_PIPELINE(TEX, SSS, SST, NOBILINEAR) \
+do \
+{ \
+ if (other_modes.sample_type && !NOBILINEAR) \
+ { \
+ COLOR t0, t1, t2, t3; \
+ int sss1, sst1, sss2, sst2; \
+ \
+ /* bilinear */ \
+ \
+ sss1 = (SSS >> 10) - (tsl >> 2); \
+ sss2 = sss1 + 1; \
+ \
+ sst1 = (SST >> 10) - (ttl >> 2); \
+ sst2 = sst1 + 1; \
+ \
+ CLAMP(sss1, sst1); \
+ CLAMP(sss2, sst2); \
+ \
+ FETCH_TEXEL(&t0, sss1, sst1, twidth, tformat, tsize, tbase); \
+ FETCH_TEXEL(&t1, sss2, sst1, twidth, tformat, tsize, tbase); \
+ FETCH_TEXEL(&t2, sss1, sst2, twidth, tformat, tsize, tbase); \
+ FETCH_TEXEL(&t3, sss2, sst2, twidth, tformat, tsize, tbase); \
+ \
+ TEX.r = (((( (t0.r * (0x3ff - (SSS & 0x3ff))) + (t1.r * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (((( (t2.r * (0x3ff - (SSS & 0x3ff))) + (t3.r * ((SSS & 0x3ff))) ) >> 10) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.g = (((( (t0.g * (0x3ff - (SSS & 0x3ff))) + (t1.g * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (((( (t2.g * (0x3ff - (SSS & 0x3ff))) + (t3.g * ((SSS & 0x3ff))) ) >> 10) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.b = (((( (t0.b * (0x3ff - (SSS & 0x3ff))) + (t1.b * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (((( (t2.b * (0x3ff - (SSS & 0x3ff))) + (t3.b * ((SSS & 0x3ff))) ) >> 10) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.a = (((( (t0.a * (0x3ff - (SSS & 0x3ff))) + (t1.a * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (((( (t2.a * (0x3ff - (SSS & 0x3ff))) + (t3.a * ((SSS & 0x3ff))) ) >> 10) * ((SST & 0x3ff))) >> 10); \
+ } \
+ else \
+ { \
+ int sss1, sst1; \
+ sss1 = (SSS >> 10) - (tsl >> 2); \
+ if ((SSS & 0x3ff) >= 0x200) sss1++; \
+ \
+ sst1 = (SST >> 10) - (ttl >> 2); \
+ if ((SST & 0x3ff) >= 0x200) sst1++; \
+ \
+ CLAMP(sss1, sst1); \
+ \
+ /* point sample */ \
+ FETCH_TEXEL(&TEX, sss1, sst1, twidth, tformat, tsize, tbase); \
+ } \
+} \
+while(0)
+#endif
+
+// This is the implementation with 3-sample bilinear filtering, which should be more correct, but not yet working properly
+// TODO: check the correct texel samples and weighting values
+
+#if 0
+#define TEXTURE_PIPELINE(TEX, SSS, SST, NOBILINEAR) \
+do \
+{ \
+ if (other_modes.sample_type && !NOBILINEAR) \
+ { \
+ COLOR t0, t1, t2; \
+ int sss1, sst1, sss2, sst2; \
+ \
+ /* bilinear */ \
+ \
+ sss1 = (SSS >> 10) - (tsl >> 2); \
+ sss2 = sss1 + 1; \
+ \
+ sst1 = (SST >> 10) - (ttl >> 2); \
+ sst2 = sst1 + 1; \
+ \
+ CLAMP(sss1, sst1); \
+ CLAMP(sss2, sst2); \
+ \
+ FETCH_TEXEL(&t0, sss1, sst1, twidth, tformat, tsize, tbase); \
+ FETCH_TEXEL(&t1, sss2, sst1, twidth, tformat, tsize, tbase); \
+ FETCH_TEXEL(&t2, sss2, sst2, twidth, tformat, tsize, tbase); \
+ \
+ TEX.r = (((( (t0.r * (0x3ff - (SSS & 0x3ff))) + (t1.r * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (( (t2.r) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.g = (((( (t0.g * (0x3ff - (SSS & 0x3ff))) + (t1.g * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (( (t2.g) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.b = (((( (t0.b * (0x3ff - (SSS & 0x3ff))) + (t1.b * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (( (t2.b) * ((SST & 0x3ff))) >> 10); \
+ \
+ TEX.a = (((( (t0.a * (0x3ff - (SSS & 0x3ff))) + (t1.a * ((SSS & 0x3ff))) ) >> 10) * (0x3ff - (SST & 0x3ff))) >> 10) + \
+ (( (t2.a) * ((SST & 0x3ff))) >> 10); \
+ } \
+ else \
+ { \
+ int sss1, sst1; \
+ sss1 = (SSS >> 10) - (tsl >> 2); \
+ if ((SSS & 0x3ff) >= 0x200) sss1++; \
+ \
+ sst1 = (SST >> 10) - (ttl >> 2); \
+ if ((SST & 0x3ff) >= 0x200) sst1++; \
+ \
+ CLAMP(sss1, sst1); \
+ \
+ /* point sample */ \
+ FETCH_TEXEL(&TEX, sss1, sst1, twidth, tformat, tsize, tbase); \
+ } \
+} \
+while(0)
+#endif
+
+#define TEXTURE_PIPELINE1(SSS, SST, NOBILINEAR) \
+do \
+{ \
+ TEXTURE_PIPELINE(texel0_color, SSS, SST, NOBILINEAR); \
+} \
+while(0)
+
+#define TEXTURE_PIPELINE2(SSS, SST, NOBILINEAR) \
+do \
+{ \
+ TEXTURE_PIPELINE(texel0_color, SSS, SST, NOBILINEAR); \
+ TEXTURE_PIPELINE(texel1_color, SSS, SST, NOBILINEAR); \
+} \
+while(0)
+
+
+
+static void texture_rectangle_16bit(TEX_RECTANGLE *rect)
+{
+ UINT16 *fb = (UINT16*)&rdram[(fb_address / 4)];
+ int i, j;
+ int x1, x2, y1, y2;
+ int tsl, tsh, ttl, tth;
+ int s, t;
+ int twidth, tformat, tsize, tbase;
+ int clamp_s, clamp_t, mask_s, mask_t, mirror_s, mirror_t;
+ int clipx1, clipx2, clipy1, clipy2;
+
+ x1 = (rect->xh / 4);
+ x2 = (rect->xl / 4);
+ y1 = (rect->yh / 4);
+ y2 = (rect->yl / 4);
+
+ if (other_modes.cycle_type == CYCLE_TYPE_FILL || other_modes.cycle_type == CYCLE_TYPE_COPY)
+ {
+ rect->dsdx /= 4;
+ x2 += 1;
+ y2 += 1;
+ }
+
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ // clip
+ if (x1 < clipx1)
+ {
+ x1 = clipx1;
+ }
+ if (y1 < clipy1)
+ {
+ y1 = clipy1;
+ }
+ if (x2 >= clipx2)
+ {
+ x2 = clipx2-1;
+ }
+ if (y2 >= clipy2)
+ {
+ y2 = clipy2-1;
+ }
+
+ tsl = tile[rect->tilenum].sl;
+ tsh = tile[rect->tilenum].sh;
+ ttl = tile[rect->tilenum].tl;
+ tth = tile[rect->tilenum].th;
+
+ twidth = tile[rect->tilenum].line;
+ tformat = tile[rect->tilenum].format;
+ tsize = tile[rect->tilenum].size;
+ tbase = tile[rect->tilenum].tmem;
+
+ // FIXME?: clamping breaks at least Rampage World Tour
+ clamp_t = 0; //tile[rect->tilenum].ct;
+ clamp_s = 0; //tile[rect->tilenum].cs;
+
+ mirror_t = tile[rect->tilenum].mt;
+ mirror_s = tile[rect->tilenum].ms;
+ mask_t = tile[rect->tilenum].mask_t;
+ mask_s = tile[rect->tilenum].mask_s;
+
+ t = (int)(rect->t) << 5;
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1 || other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ COLOR c;
+
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&texel0_color, ss, st, twidth, tformat, tsize, tbase);
+
+ TEXTURE_PIPELINE1(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ c = COLOR_COMBINER(0);
+
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ BLENDER1_16(&fb[(fb_index + i) ^ WORD_ADDR_XOR], c, dith);
+ }
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ COLOR c1, c2;
+
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&texel0_color, ss, st, twidth, tformat, tsize, tbase);
+ //FETCH_TEXEL(&texel1_color, ss, st, twidth, tformat, tsize, tbase);
+
+ TEXTURE_PIPELINE2(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ c1 = COLOR_COMBINER(0);
+ c2 = COLOR_COMBINER(1);
+
+ //BLENDER2_16(&fb[(fb_index + i) ^ WORD_ADDR_XOR], c1, c2);
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ BLENDER2_16(&fb[(fb_index + i) ^ WORD_ADDR_XOR], c1, c2, dith);
+ }
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_COPY)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ /*
+ if (clamp_s)
+ {
+ if (s < (tsl << 8)) s = (tsl << 8);
+ if (s > (tsh << 8)) s = (tsh << 8);
+ }
+ if (clamp_t)
+ {
+ if (t < (ttl << 8)) t = (ttl << 8);
+ if (t > (tth << 8)) t = (tth << 8);
+ }
+ if (mask_s)
+ {
+ s &= (((UINT32)(0xffffffff) >> (32-mask_s)) << 10) | 0x3ff;
+ }
+ if (mask_t)
+ {
+ t &= (((UINT32)(0xffffffff) >> (32-mask_t)) << 10) | 0x3ff;
+ }
+
+ FETCH_TEXEL(&c, (s-tile[rect->tilenum].sl) >> 10, (t-tile[rect->tilenum].tl) >> 10, twidth, tformat, tsize, tbase);
+ */
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&c, ss, st, twidth, tformat, tsize, tbase);
+
+ TEXTURE_PIPELINE1(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ if (texel0_color.a != 0)
+ {
+ fb[(fb_index + i) ^ WORD_ADDR_XOR] = ((texel0_color.r >> 3) << 11) | ((texel0_color.g >> 3) << 6) | ((texel0_color.b >> 3) << 1);
+ }
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else
+ {
+ fatalerror("texture_rectangle_16bit: unknown cycle type %d\n", other_modes.cycle_type);
+ }
+}
+
+/*****************************************************************************/
+
+INLINE void BLENDER1_32(UINT32 *fb, COLOR c)
+{
+ int r, g, b;
+
+ pixel_color.r = c.r; inv_pixel_color.r = 0xff - c.r;
+ pixel_color.g = c.g; inv_pixel_color.g = 0xff - c.g;
+ pixel_color.b = c.b; inv_pixel_color.b = 0xff - c.b;
+ pixel_color.a = c.a; inv_pixel_color.a = 0xff - c.a;
+
+ if (other_modes.image_read_en)
+ {
+ UINT32 mem = *fb;
+ memory_color.r = ((mem >> 16) & 0xff);
+ memory_color.g = ((mem >> 8) & 0xff);
+ memory_color.b = ((mem >> 0) & 0xff);
+ memory_color.a = 0;
+ }
+
+ r = (((int)(*blender1a_r[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_r[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ g = (((int)(*blender1a_g[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_g[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ b = (((int)(*blender1a_b[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_b[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ //r = g = b = 0xff;
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ *fb = (r << 16) | (g << 8) | b;
+}
+
+INLINE void BLENDER2_32(UINT32 *fb, COLOR c1, COLOR c2)
+{
+ int r, g, b;
+
+ pixel_color.r = c1.r; inv_pixel_color.r = 0xff - c1.r;
+ pixel_color.g = c1.g; inv_pixel_color.g = 0xff - c1.g;
+ pixel_color.b = c1.b; inv_pixel_color.b = 0xff - c1.b;
+ pixel_color.a = c1.a; inv_pixel_color.a = 0xff - c1.a;
+
+ if (other_modes.image_read_en)
+ {
+ UINT32 mem = *fb;
+ memory_color.r = ((mem >> 16) & 0xff);
+ memory_color.g = ((mem >> 8) & 0xff);
+ memory_color.b = ((mem >> 0) & 0xff);
+ memory_color.a = 0;
+ }
+
+ r = (((int)(*blender1a_r[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_r[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ g = (((int)(*blender1a_g[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_g[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ b = (((int)(*blender1a_b[0]) * (int)(*blender1b_a[0])) >> 8) +
+ (((int)(*blender2a_b[0]) * (int)(*blender2b_a[0])) >> 8);
+
+ blended_pixel_color.r = r;
+ blended_pixel_color.g = g;
+ blended_pixel_color.b = b;
+
+ pixel_color.r = c2.r; inv_pixel_color.r = 0xff - c2.r;
+ pixel_color.g = c2.g; inv_pixel_color.g = 0xff - c2.g;
+ pixel_color.b = c2.b; inv_pixel_color.b = 0xff - c2.b;
+ pixel_color.a = c2.a; inv_pixel_color.a = 0xff - c2.a;
+
+ r = (((int)(*blender1a_r[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_r[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ g = (((int)(*blender1a_g[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_g[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ b = (((int)(*blender1a_b[1]) * (int)(*blender1b_a[1])) >> 8) +
+ (((int)(*blender2a_b[1]) * (int)(*blender2b_a[1])) >> 8);
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ *fb = (r << 16) | (g << 8) | b;
+}
+
+static void fill_rectangle_32bit(RECTANGLE *rect)
+{
+ UINT32 *fb = (UINT32*)&rdram[(fb_address / 4)];
+ int index, i, j;
+ int x1 = rect->xh / 4;
+ int x2 = rect->xl / 4;
+ int y1 = rect->yh / 4;
+ int y2 = rect->yl / 4;
+ int clipx1, clipx2, clipy1, clipy2;
+
+ // TODO: clip
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ // clip
+ if (x1 < clipx1)
+ {
+ x1 = clipx1;
+ }
+ if (y1 < clipy1)
+ {
+ y1 = clipy1;
+ }
+ if (x2 >= clipx2)
+ {
+ x2 = clipx2-1;
+ }
+ if (y2 >= clipy2)
+ {
+ y2 = clipy2-1;
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_FILL)
+ {
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ fb[(index + i) ^ 1] = fill_color;
+ }
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ shade_color.r = prim_color.r;
+ shade_color.g = prim_color.g;
+ shade_color.b = prim_color.b;
+ shade_color.a = prim_color.a;
+
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ COLOR c = COLOR_COMBINER(0);
+
+ BLENDER1_32(&fb[(index + i)], c);
+ }
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ shade_color.r = prim_color.r;
+ shade_color.g = prim_color.g;
+ shade_color.b = prim_color.b;
+ shade_color.a = prim_color.a;
+
+ for (j=y1; j <= y2; j++)
+ {
+ index = j * fb_width;
+ for (i=x1; i <= x2; i++)
+ {
+ COLOR c1 = COLOR_COMBINER(0);
+ COLOR c2 = COLOR_COMBINER(1);
+
+ BLENDER2_32(&fb[(index + i)], c1, c2);
+ }
+ }
+ }
+ else
+ {
+ fatalerror("fill_rectangle_32bit: cycle type copy");
+ }
+}
+
+static void texture_rectangle_32bit(TEX_RECTANGLE *rect)
+{
+ UINT32 *fb = (UINT32*)&rdram[(fb_address / 4)];
+ int i, j;
+ int x1, x2, y1, y2;
+ int tsl, tsh, ttl, tth;
+ int s, t;
+ int twidth, tformat, tsize, tbase;
+ int clamp_s, clamp_t, mask_s, mask_t, mirror_s, mirror_t;
+ int clipx1, clipx2, clipy1, clipy2;
+
+ x1 = (rect->xh / 4);
+ x2 = (rect->xl / 4);
+ y1 = (rect->yh / 4);
+ y2 = (rect->yl / 4);
+
+ if (other_modes.cycle_type == CYCLE_TYPE_FILL || other_modes.cycle_type == CYCLE_TYPE_COPY)
+ {
+ rect->dsdx /= 4;
+ x2 += 1;
+ y2 += 1;
+ }
+
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ // clip
+ if (x1 < clipx1)
+ {
+ x1 = clipx1;
+ }
+ if (y1 < clipy1)
+ {
+ y1 = clipy1;
+ }
+ if (x2 >= clipx2)
+ {
+ x2 = clipx2-1;
+ }
+ if (y2 >= clipy2)
+ {
+ y2 = clipy2-1;
+ }
+
+ tsl = tile[rect->tilenum].sl;
+ tsh = tile[rect->tilenum].sh;
+ ttl = tile[rect->tilenum].tl;
+ tth = tile[rect->tilenum].th;
+
+ twidth = tile[rect->tilenum].line;
+ tformat = tile[rect->tilenum].format;
+ tsize = tile[rect->tilenum].size;
+ tbase = tile[rect->tilenum].tmem;
+
+ // FIXME?: clamping breaks at least Rampage World Tour
+ clamp_t = 0; //tile[rect->tilenum].ct;
+ clamp_s = 0; //tile[rect->tilenum].cs;
+
+ mirror_t = tile[rect->tilenum].mt;
+ mirror_s = tile[rect->tilenum].ms;
+ mask_t = tile[rect->tilenum].mask_t;
+ mask_s = tile[rect->tilenum].mask_s;
+
+ t = (int)(rect->t) << 5;
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1 || other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ COLOR c;
+
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&texel0_color, ss, st, twidth, tformat, tsize, tbase);
+
+ TEXTURE_PIPELINE1(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ c = COLOR_COMBINER(0);
+
+ BLENDER1_32(&fb[(fb_index + i)], c);
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ COLOR c1, c2;
+
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&texel0_color, ss, st, twidth, tformat, tsize, tbase);
+ //FETCH_TEXEL(&texel1_color, ss, st, twidth, tformat, tsize, tbase);
+
+ TEXTURE_PIPELINE2(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ c1 = COLOR_COMBINER(0);
+ c2 = COLOR_COMBINER(1);
+
+ BLENDER2_32(&fb[(fb_index + i)], c1, c2);
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_COPY)
+ {
+ for (j = y1; j < y2; j++)
+ {
+ int fb_index = j * fb_width;
+
+ s = (int)(rect->s) << 5;
+
+ for (i = x1; i < x2; i++)
+ {
+ /*
+ if (clamp_s)
+ {
+ if (s < (tsl << 8)) s = (tsl << 8);
+ if (s > (tsh << 8)) s = (tsh << 8);
+ }
+ if (clamp_t)
+ {
+ if (t < (ttl << 8)) t = (ttl << 8);
+ if (t > (tth << 8)) t = (tth << 8);
+ }
+ if (mask_s)
+ {
+ s &= (((UINT32)(0xffffffff) >> (32-mask_s)) << 10) | 0x3ff;
+ }
+ if (mask_t)
+ {
+ t &= (((UINT32)(0xffffffff) >> (32-mask_t)) << 10) | 0x3ff;
+ }
+
+ FETCH_TEXEL(&c, (s-tile[rect->tilenum].sl) >> 10, (t-tile[rect->tilenum].tl) >> 10, twidth, tformat, tsize, tbase);
+ */
+ //ss = (s >> 10) - (tsl >> 2);
+ //if ((s & 0x3ff) >= 0x200) ss++;
+ //st = (t >> 10) - (ttl >> 2);
+ //if ((t & 0x3ff) >= 0x200) st++;
+
+ TEXTURE_PIPELINE1(s, t, (rect->dsdx == (1 << 10)) && (rect->dtdy == (1 << 10)));
+
+ //CLAMP(ss, st);
+ //FETCH_TEXEL(&c, ss, st, twidth, tformat, tsize, tbase);
+
+ if (texel0_color.a != 0)
+ {
+ fb[(fb_index + i) ^ WORD_ADDR_XOR] = (texel0_color.r << 16) | (texel0_color.g << 8) | (texel0_color.b << 0);
+ }
+
+ s += rect->dsdx;
+ }
+
+ t += rect->dtdy;
+ }
+ }
+ else
+ {
+ fatalerror("texture_rectangle_32bit: unknown cycle type %d\n", other_modes.cycle_type);
+ }
+}
+
+
+static void render_spans_32(int start, int end, int tilenum, int shade, int texture, int zbuffer, int flip)
+{
+ UINT32 *fb = (UINT32*)&rdram[fb_address / 4];
+ UINT16 *zb = (UINT16*)&rdram[zb_address / 4];
+ int i, j;
+ int tsl, tsh, ttl, tth;
+ int twidth, tformat, tsize, tbase;
+ int clamp_s, clamp_t, mask_s, mask_t, mirror_s, mirror_t;
+
+ int clipx1, clipx2, clipy1, clipy2;
+
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ tsl = tile[tilenum].sl;
+ tsh = tile[tilenum].sh;
+ ttl = tile[tilenum].tl;
+ tth = tile[tilenum].th;
+
+ twidth = tile[tilenum].line;
+ tformat = tile[tilenum].format;
+ tsize = tile[tilenum].size;
+ tbase = tile[tilenum].tmem;
+
+ clamp_t = tile[tilenum].ct;
+ clamp_s = tile[tilenum].cs;
+ mirror_t = tile[tilenum].mt;
+ mirror_s = tile[tilenum].ms;
+ mask_t = tile[tilenum].mask_t;
+ mask_s = tile[tilenum].mask_s;
+
+ if (start < clipy1)
+ {
+ start = clipy1;
+ }
+ if (start >= clipy2)
+ {
+ start = clipy2-1;
+ }
+ if (end < clipy1)
+ {
+ end = clipy1;
+ }
+ if (end >= clipy2)
+ {
+ end = clipy2-1;
+ }
+
+ for (i=start; i <= end; i++)
+ {
+ int xstart = span[i].lx;
+ int xend = span[i].rx;
+ int r = span[i].r;
+ int g = span[i].g;
+ int b = span[i].b;
+ int a = span[i].a;
+ int z = span[i].z;
+ int s = span[i].s;
+ int t = span[i].t;
+ int w = span[i].w;
+ int dr = span[i].dr;
+ int dg = span[i].dg;
+ int db = span[i].db;
+ int da = span[i].da;
+ int dz = span[i].dz;
+ int ds = span[i].ds;
+ int dt = span[i].dt;
+ int dw = span[i].dw;
+ int drinc, dginc, dbinc, dainc, dzinc, dsinc, dtinc, dwinc;
+
+ int x;
+ int xinc;
+
+ int fb_index = fb_width * i;
+ int length;
+
+ drinc = flip ? (dr) : -dr;
+ dginc = flip ? (dg) : -dg;
+ dbinc = flip ? (db) : -db;
+ dainc = flip ? (da) : -da;
+ dzinc = flip ? (dz) : -dz;
+ dsinc = flip ? (ds) : -ds;
+ dtinc = flip ? (dt) : -dt;
+ dwinc = flip ? (dw) : -dw;
+
+ xinc = flip ? 1 : -1;
+ x = xend;
+
+ length = flip ? (xstart - xend) : (xend - xstart);
+
+ for (j=0; j <= length; j++)
+ {
+ int sr = r >> 16;
+ int sg = g >> 16;
+ int sb = b >> 16;
+ int sa = a >> 16;
+ int ss = s >> 16;
+ int st = t >> 16;
+ int sw = w >> 16;
+ UINT16 sz = z >> 16;
+ int oz;
+ int sss = 0, sst = 0;
+
+ if (x >= clipx1 && x < clipx2)
+ {
+ COLOR c1, c2;
+ c1.r = c1.g = c1.b = c1.a = 0;
+ c2.r = c2.g = c2.b = c2.a = 0;
+
+ if ((z & 0xffff) >= 0x8000) sz++;
+ if ((w & 0xffff) >= 0x8000) sw++;
+
+ if (other_modes.persp_tex_en)
+ {
+ if (sw != 0)
+ {
+ sss = (((INT64)(ss) << 20) / sw);
+ sst = (((INT64)(st) << 20) / sw);
+ }
+ }
+ else
+ {
+ sss = ss;
+ sst = st;
+ }
+
+ if (sr > 0xff) sr = 0xff; if (sg > 0xff) sg = 0xff; if (sb > 0xff) sb = 0xff;
+
+ shade_color.r = sr; shade_color.g = sg; shade_color.b = sb; shade_color.a = sa;
+
+ if (texture)
+ {
+ /*if (other_modes.sample_type)
+ {
+ // bilinear
+
+ sss1 = (sss >> 10) - (tsl >> 2);
+ sss2 = sss1 + 1;
+
+ sst1 = (sst >> 10) - (ttl >> 2);
+ sst2 = sst1 + 1;
+
+ CLAMP(sss1, sst1);
+ CLAMP(sss2, sst2);
+
+ FETCH_TEXEL(&t0, sss1, sst1, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t1, sss2, sst1, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t2, sss1, sst2, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t3, sss2, sst2, twidth, tformat, tsize, tbase);
+
+ texel0_color.r = (((( (t0.r * (0x3ff - (sss & 0x3ff))) + (t1.r * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.r * (0x3ff - (sss & 0x3ff))) + (t3.r * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.g = (((( (t0.g * (0x3ff - (sss & 0x3ff))) + (t1.g * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.g * (0x3ff - (sss & 0x3ff))) + (t3.g * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.b = (((( (t0.b * (0x3ff - (sss & 0x3ff))) + (t1.b * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.b * (0x3ff - (sss & 0x3ff))) + (t3.b * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.a = (((( (t0.a * (0x3ff - (sss & 0x3ff))) + (t1.a * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.a * (0x3ff - (sss & 0x3ff))) + (t3.a * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+ }
+ else
+ {
+ sss1 = (sss >> 10) - (tsl >> 2);
+ if ((sss & 0x3ff) >= 0x200) sss1++;
+
+ sst1 = (sst >> 10) - (ttl >> 2);
+ if ((sst & 0x3ff) >= 0x200) sst1++;
+
+ CLAMP(sss1, sst1);
+
+ // point sample
+ FETCH_TEXEL(&texel0_color, sss1, sst1, twidth, tformat, tsize, tbase);
+ }*/
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ TEXTURE_PIPELINE1(sss, sst, 0);
+ }
+ else
+ {
+ TEXTURE_PIPELINE2(sss, sst, 0);
+ }
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ c1 = COLOR_COMBINER(0);
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ c1 = COLOR_COMBINER(0);
+ c2 = COLOR_COMBINER(1);
+ }
+
+ oz = (UINT16)zb[(fb_index + x) ^ WORD_ADDR_XOR];
+ if (zbuffer)
+ {
+ if (sz < oz /*&& c.a != 0*/)
+ {
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ BLENDER1_32(&fb[(fb_index + x)], c1);
+ }
+ else
+ {
+ BLENDER2_32(&fb[(fb_index + x)], c1, c2);
+ }
+
+ if (other_modes.z_compare_en && other_modes.z_update_en)
+ {
+ zb[(fb_index + x) ^ WORD_ADDR_XOR] = sz;
+ }
+ }
+ }
+ else
+ {
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ BLENDER1_32(&fb[(fb_index + x)], c1);
+ }
+ else
+ {
+ BLENDER2_32(&fb[(fb_index + x)], c1, c2);
+ }
+ }
+ }
+
+ r += drinc;
+ g += dginc;
+ b += dbinc;
+ a += dainc;
+ z += dzinc;
+ s += dsinc;
+ t += dtinc;
+ w += dwinc;
+
+ x += xinc;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+
+
+static void render_spans_16(int start, int end, int tilenum, int shade, int texture, int zbuffer, int flip)
+{
+ UINT16 *fb = (UINT16*)&rdram[fb_address / 4];
+ UINT16 *zb = (UINT16*)&rdram[zb_address / 4];
+ int i, j;
+ int tsl, tsh, ttl, tth;
+ int twidth, tformat, tsize, tbase;
+ int clamp_s, clamp_t, mask_s, mask_t, mirror_s, mirror_t;
+
+ int clipx1, clipx2, clipy1, clipy2;
+
+ clipx1 = clip.xh / 4;
+ clipx2 = clip.xl / 4;
+ clipy1 = clip.yh / 4;
+ clipy2 = clip.yl / 4;
+
+ tsl = tile[tilenum].sl;
+ tsh = tile[tilenum].sh;
+ ttl = tile[tilenum].tl;
+ tth = tile[tilenum].th;
+
+ twidth = tile[tilenum].line;
+ tformat = tile[tilenum].format;
+ tsize = tile[tilenum].size;
+ tbase = tile[tilenum].tmem;
+
+ clamp_t = tile[tilenum].ct;
+ clamp_s = tile[tilenum].cs;
+ mirror_t = tile[tilenum].mt;
+ mirror_s = tile[tilenum].ms;
+ mask_t = tile[tilenum].mask_t;
+ mask_s = tile[tilenum].mask_s;
+
+ if (start < clipy1)
+ {
+ start = clipy1;
+ }
+ if (start >= clipy2)
+ {
+ start = clipy2-1;
+ }
+ if (end < clipy1)
+ {
+ end = clipy1;
+ }
+ if (end >= clipy2)
+ {
+ end = clipy2-1;
+ }
+
+ for (i=start; i <= end; i++)
+ {
+ int xstart = span[i].lx;
+ int xend = span[i].rx;
+ int r = span[i].r;
+ int g = span[i].g;
+ int b = span[i].b;
+ int a = span[i].a;
+ int z = span[i].z;
+ int s = span[i].s;
+ int t = span[i].t;
+ int w = span[i].w;
+ int dr = span[i].dr;
+ int dg = span[i].dg;
+ int db = span[i].db;
+ int da = span[i].da;
+ int dz = span[i].dz;
+ int ds = span[i].ds;
+ int dt = span[i].dt;
+ int dw = span[i].dw;
+ int drinc, dginc, dbinc, dainc, dzinc, dsinc, dtinc, dwinc;
+
+ int x;
+ int xinc;
+
+ int fb_index = fb_width * i;
+ int length;
+
+ drinc = flip ? (dr) : -dr;
+ dginc = flip ? (dg) : -dg;
+ dbinc = flip ? (db) : -db;
+ dainc = flip ? (da) : -da;
+ dzinc = flip ? (dz) : -dz;
+ dsinc = flip ? (ds) : -ds;
+ dtinc = flip ? (dt) : -dt;
+ dwinc = flip ? (dw) : -dw;
+
+ /*if (flip)
+ {
+ if (xend > clipx2)
+ {
+ int d = xend-clipx2;
+ r += d * drinc;
+ g += d * dginc;
+ b += d * dbinc;
+ a += d * dainc;
+ z += d * dzinc;
+ s += d * dsinc;
+ t += d * dtinc;
+ w += d * dwinc;
+
+ xend = clipx2;
+ }
+ if (xstart < clipx1)
+ {
+ xstart = clipx1;
+ }
+ }
+ else
+ {
+ if (xstart > clipx2)
+ {
+ int d = xstart-clipx2;
+ r += d * drinc;
+ g += d * dginc;
+ b += d * dbinc;
+ a += d * dainc;
+ z += d * dzinc;
+ s += d * dsinc;
+ t += d * dtinc;
+ w += d * dwinc;
+
+ xstart = clipx2;
+ }
+ if (xend < clipx1)
+ {
+ xend = clipx1;
+ }
+ }*/
+
+ xinc = flip ? 1 : -1;
+ x = xend;
+
+ length = flip ? (xstart - xend) : (xend - xstart);
+
+ for (j=0; j <= length; j++)
+ {
+ int sr = r >> 16;
+ int sg = g >> 16;
+ int sb = b >> 16;
+ int sa = a >> 16;
+ int ss = s >> 16;
+ int st = t >> 16;
+ int sw = w >> 16;
+ UINT16 sz = z >> 16;
+ int oz;
+ int sss = 0, sst = 0;
+ COLOR c1, c2;
+ c1.r = c1.g = c1.b = c1.a = 0;
+ c2.r = c2.g = c2.b = c2.a = 0;
+
+ if (x >= clipx1 && x < clipx2)
+ {
+ if ((z & 0xffff) >= 0x8000) sz++;
+ if ((w & 0xffff) >= 0x8000) sw++;
+
+ if (other_modes.persp_tex_en)
+ {
+ if (sw != 0)
+ {
+ sss = (((INT64)(ss) << 20) / sw);
+ sst = (((INT64)(st) << 20) / sw);
+ }
+ }
+ else
+ {
+ sss = ss;
+ sst = st;
+ }
+
+ if (sr > 0xff) sr = 0xff; if (sg > 0xff) sg = 0xff; if (sb > 0xff) sb = 0xff;
+
+ shade_color.r = sr; shade_color.g = sg; shade_color.b = sb; shade_color.a = sa;
+
+ if (texture)
+ {
+ /*if (other_modes.sample_type)
+ {
+ // bilinear
+
+ sss1 = (sss >> 10) - (tsl >> 2);
+ sss2 = sss1 + 1;
+
+ sst1 = (sst >> 10) - (ttl >> 2);
+ sst2 = sst1 + 1;
+
+ CLAMP(sss1, sst1);
+ CLAMP(sss2, sst2);
+
+ FETCH_TEXEL(&t0, sss1, sst1, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t1, sss2, sst1, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t2, sss1, sst2, twidth, tformat, tsize, tbase);
+ FETCH_TEXEL(&t3, sss2, sst2, twidth, tformat, tsize, tbase);
+
+ texel0_color.r = (((( (t0.r * (0x3ff - (sss & 0x3ff))) + (t1.r * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.r * (0x3ff - (sss & 0x3ff))) + (t3.r * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.g = (((( (t0.g * (0x3ff - (sss & 0x3ff))) + (t1.g * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.g * (0x3ff - (sss & 0x3ff))) + (t3.g * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.b = (((( (t0.b * (0x3ff - (sss & 0x3ff))) + (t1.b * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.b * (0x3ff - (sss & 0x3ff))) + (t3.b * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+
+ texel0_color.a = (((( (t0.a * (0x3ff - (sss & 0x3ff))) + (t1.a * ((sss & 0x3ff))) ) >> 10) * (0x3ff - (sst & 0x3ff))) >> 10) +
+ (((( (t2.a * (0x3ff - (sss & 0x3ff))) + (t3.a * ((sss & 0x3ff))) ) >> 10) * ((sst & 0x3ff))) >> 10);
+ }
+ else
+ {
+ sss1 = (sss >> 10) - (tsl >> 2);
+ if ((sss & 0x3ff) >= 0x200) sss1++;
+
+ sst1 = (sst >> 10) - (ttl >> 2);
+ if ((sst & 0x3ff) >= 0x200) sst1++;
+
+ CLAMP(sss1, sst1);
+
+ // point sample
+ FETCH_TEXEL(&texel0_color, sss1, sst1, twidth, tformat, tsize, tbase);
+ }*/
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ TEXTURE_PIPELINE1(sss, sst, 0);
+ }
+ else
+ {
+ TEXTURE_PIPELINE2(sss, sst, 0);
+ }
+ }
+
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ c1 = COLOR_COMBINER(0);
+ }
+ else if (other_modes.cycle_type == CYCLE_TYPE_2)
+ {
+ c1 = COLOR_COMBINER(0);
+ c2 = COLOR_COMBINER(1);
+ }
+
+ oz = (UINT16)zb[(fb_index + x) ^ WORD_ADDR_XOR];
+ if (zbuffer)
+ {
+ if (sz < oz /*&& c.a != 0*/)
+ {
+ //BLENDER1_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c);
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ BLENDER1_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c1, dith);
+ }
+ else
+ {
+ BLENDER2_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c1, c2, dith);
+ }
+ }
+
+ if (other_modes.z_compare_en && other_modes.z_update_en)
+ {
+ zb[(fb_index + x) ^ WORD_ADDR_XOR] = sz;
+ }
+ }
+ }
+ else
+ {
+ //BLENDER1_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c);
+
+ {
+ int dith = dither_matrix_4x4[(((j) & 3) << 2) + ((i^WORD_ADDR_XOR) & 3)];
+ if (other_modes.cycle_type == CYCLE_TYPE_1)
+ {
+ BLENDER1_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c1, dith);
+ }
+ else
+ {
+ BLENDER2_16(&fb[(fb_index + x) ^ WORD_ADDR_XOR], c1, c2, dith);
+ }
+ }
+ }
+ }
+
+ r += drinc;
+ g += dginc;
+ b += dbinc;
+ a += dainc;
+ z += dzinc;
+ s += dsinc;
+ t += dtinc;
+ w += dwinc;
+
+ x += xinc;
+ }
+ }
+}
+
+static void triangle(UINT32 w1, UINT32 w2, int shade, int texture, int zbuffer)
+{
+ int j;
+ int xleft, xright, xleft_inc, xright_inc;
+ int xstart, xend;
+ int r, g, b, a, z, s, t, w;
+ int dr, dg, db, da;
+ int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
+ int drdy = 0, dgdy = 0, dbdy = 0, dady = 0, dzdy = 0, dsdy = 0, dtdy = 0, dwdy = 0;
+ int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
+ int tile;
+ int flip = (w1 & 0x800000) ? 1 : 0;
+
+ INT32 yl, ym, yh;
+ INT32 xl, xm, xh;
+ INT64 dxldy, dxhdy, dxmdy;
+ UINT32 w3, w4, w5, w6, w7, w8;
+
+ int shade_base = rdp_cmd_cur + 8;
+ int texture_base = rdp_cmd_cur + 8;
+ int zbuffer_base = rdp_cmd_cur + 8;
+ if (shade)
+ {
+ texture_base += 16;
+ zbuffer_base += 16;
+ }
+ if (texture)
+ {
+ zbuffer_base += 16;
+ }
+
+ w3 = rdp_cmd_data[rdp_cmd_cur+2];
+ w4 = rdp_cmd_data[rdp_cmd_cur+3];
+ w5 = rdp_cmd_data[rdp_cmd_cur+4];
+ w6 = rdp_cmd_data[rdp_cmd_cur+5];
+ w7 = rdp_cmd_data[rdp_cmd_cur+6];
+ w8 = rdp_cmd_data[rdp_cmd_cur+7];
+
+ yl = (w1 & 0x3fff) >> 2;
+ ym = ((w2 >> 16) & 0x3fff) >> 2;
+ yh = ((w2 >> 0) & 0x3fff) >> 2;
+ xl = (INT32)(w3);
+ xh = (INT32)(w5);
+ xm = (INT32)(w7);
+ dxldy = (INT32)(w4);
+ dxhdy = (INT32)(w6);
+ dxmdy = (INT32)(w8);
+
+ if (yl & 0x800) yl |= 0xfffff000;
+ if (ym & 0x800) ym |= 0xfffff000;
+ if (yh & 0x800) yh |= 0xfffff000;
+
+ yl += (w1 >> 1) & 1;
+ ym += (w2 >> 17) & 1;
+ yh += (w2 >> 1) & 1;
+
+ tile = (w1 >> 16) & 0x7;
+
+ r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0; s = 0; t = 0; w = 0;
+ dr = 0; dg = 0; db = 0; da = 0;
+
+ if (shade)
+ {
+ r = (rdp_cmd_data[shade_base+0 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+4 ] >> 16) & 0x0000ffff);
+ g = ((rdp_cmd_data[shade_base+0 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+4 ] & 0x0000ffff);
+ b = (rdp_cmd_data[shade_base+1 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+5 ] >> 16) & 0x0000ffff);
+ a = ((rdp_cmd_data[shade_base+1 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+5 ] & 0x0000ffff);
+ drdx = (rdp_cmd_data[shade_base+2 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+6 ] >> 16) & 0x0000ffff);
+ dgdx = ((rdp_cmd_data[shade_base+2 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+6 ] & 0x0000ffff);
+ dbdx = (rdp_cmd_data[shade_base+3 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+7 ] >> 16) & 0x0000ffff);
+ dadx = ((rdp_cmd_data[shade_base+3 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+7 ] & 0x0000ffff);
+ drde = (rdp_cmd_data[shade_base+8 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+12] >> 16) & 0x0000ffff);
+ dgde = ((rdp_cmd_data[shade_base+8 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+12] & 0x0000ffff);
+ dbde = (rdp_cmd_data[shade_base+9 ] & 0xffff0000) | ((rdp_cmd_data[shade_base+13] >> 16) & 0x0000ffff);
+ dade = ((rdp_cmd_data[shade_base+9 ] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+13] & 0x0000ffff);
+ drdy = (rdp_cmd_data[shade_base+10] & 0xffff0000) | ((rdp_cmd_data[shade_base+14] >> 16) & 0x0000ffff);
+ dgdy = ((rdp_cmd_data[shade_base+10] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+14] & 0x0000ffff);
+ dbdy = (rdp_cmd_data[shade_base+11] & 0xffff0000) | ((rdp_cmd_data[shade_base+15] >> 16) & 0x0000ffff);
+ dady = ((rdp_cmd_data[shade_base+11] << 16) & 0xffff0000) | (rdp_cmd_data[shade_base+15] & 0x0000ffff);
+ }
+ if (texture)
+ {
+ s = (rdp_cmd_data[texture_base+0 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+4 ] >> 16) & 0x0000ffff);
+ t = ((rdp_cmd_data[texture_base+0 ] << 16) & 0xffff0000) | (rdp_cmd_data[texture_base+4 ] & 0x0000ffff);
+ w = (rdp_cmd_data[texture_base+1 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+5 ] >> 16) & 0x0000ffff);
+ dsdx = (rdp_cmd_data[texture_base+2 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+6 ] >> 16) & 0x0000ffff);
+ dtdx = ((rdp_cmd_data[texture_base+2 ] << 16) & 0xffff0000) | (rdp_cmd_data[texture_base+6 ] & 0x0000ffff);
+ dwdx = (rdp_cmd_data[texture_base+3 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+7 ] >> 16) & 0x0000ffff);
+ dsde = (rdp_cmd_data[texture_base+8 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+12] >> 16) & 0x0000ffff);
+ dtde = ((rdp_cmd_data[texture_base+8 ] << 16) & 0xffff0000) | (rdp_cmd_data[texture_base+12] & 0x0000ffff);
+ dwde = (rdp_cmd_data[texture_base+9 ] & 0xffff0000) | ((rdp_cmd_data[texture_base+13] >> 16) & 0x0000ffff);
+ dsdy = (rdp_cmd_data[texture_base+10] & 0xffff0000) | ((rdp_cmd_data[texture_base+14] >> 16) & 0x0000ffff);
+ dtdy = ((rdp_cmd_data[texture_base+10] << 16) & 0xffff0000) | (rdp_cmd_data[texture_base+14] & 0x0000ffff);
+ dwdy = (rdp_cmd_data[texture_base+11] & 0xffff0000) | ((rdp_cmd_data[texture_base+15] >> 16) & 0x0000ffff);
+ }
+ if (zbuffer)
+ {
+ z = rdp_cmd_data[zbuffer_base+0];
+ dzdx = rdp_cmd_data[zbuffer_base+1];
+ dzde = rdp_cmd_data[zbuffer_base+2];
+ dzdy = rdp_cmd_data[zbuffer_base+3];
+ }
+
+ xleft = xm;
+ xright = xh;
+ xleft_inc = dxmdy;
+ xright_inc = dxhdy;
+
+ for (j=yh; j < ym; j++)
+ {
+ xstart = xleft >> 16;
+ xend = xright >> 16;
+
+ if (j >= 0)
+ {
+ span[j].lx = xstart;
+ span[j].rx = xend;
+ span[j].s = s; span[j].ds = dsdx;
+ span[j].t = t; span[j].dt = dtdx;
+ span[j].w = w; span[j].dw = dwdx;
+ span[j].r = r; span[j].dr = drdx;
+ span[j].g = g; span[j].dg = dgdx;
+ span[j].b = b; span[j].db = dbdx;
+ span[j].a = a; span[j].da = dadx;
+ span[j].z = z; span[j].dz = dzdx;
+ }
+
+ xleft += xleft_inc;
+ xright += xright_inc;
+ s += dsde;
+ t += dtde;
+ w += dwde;
+ r += drde;
+ g += dgde;
+ b += dbde;
+ a += dade;
+ z += dzde;
+ }
+
+ xleft = xl;
+ xleft_inc = dxldy;
+ xright_inc = dxhdy;
+
+ for (j=ym; j <= yl; j++)
+ {
+ xstart = xleft >> 16;
+ xend = xright >> 16;
+
+ if (j >= 0)
+ {
+ span[j].lx = xstart;
+ span[j].rx = xend;
+ span[j].s = s; span[j].ds = dsdx;
+ span[j].t = t; span[j].dt = dtdx;
+ span[j].w = w; span[j].dw = dwdx;
+ span[j].r = r; span[j].dr = drdx;
+ span[j].g = g; span[j].dg = dgdx;
+ span[j].b = b; span[j].db = dbdx;
+ span[j].a = a; span[j].da = dadx;
+ span[j].z = z; span[j].dz = dzdx;
+ }
+
+ xleft += xleft_inc;
+ xright += xright_inc;
+ s += dsde;
+ t += dtde;
+ w += dwde;
+ r += drde;
+ g += dgde;
+ b += dbde;
+ a += dade;
+ z += dzde;
+ }
+
+ switch (fb_size)
+ {
+ case PIXEL_SIZE_16BIT: render_spans_16(yh, yl, tile, shade, texture, zbuffer, flip); break;
+ case PIXEL_SIZE_32BIT: render_spans_32(yh, yl, tile, shade, texture, zbuffer, flip); break;
+ }
+}
+
+/*****************************************************************************/
+
+INLINE UINT32 READ_RDP_DATA(UINT32 address)
+{
+ if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
+ {
+ return rsp_dmem[(address & 0xfff) / 4];
+ }
+ else
+ {
+ return rdram[(address / 4)];
+ }
+}
+
+#if LOG_RDP_EXECUTION
+static const char *image_format[] = { "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" };
+static const char *image_size[] = { "4-bit", "8-bit", "16-bit", "32-bit" };
+#endif
+
+static const int rdp_command_length[64] =
+{
+ 8, // 0x00, No Op
+ 8, // 0x01, ???
+ 8, // 0x02, ???
+ 8, // 0x03, ???
+ 8, // 0x04, ???
+ 8, // 0x05, ???
+ 8, // 0x06, ???
+ 8, // 0x07, ???
+ 32, // 0x08, Non-Shaded Triangle
+ 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
+ 32+64, // 0x0a, Textured Triangle
+ 32+64+16, // 0x0b, Textured, Z-Buffered Triangle
+ 32+64, // 0x0c, Shaded Triangle
+ 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
+ 32+64+64, // 0x0e, Shaded+Textured Triangle
+ 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
+ 8, // 0x10, ???
+ 8, // 0x11, ???
+ 8, // 0x12, ???
+ 8, // 0x13, ???
+ 8, // 0x14, ???
+ 8, // 0x15, ???
+ 8, // 0x16, ???
+ 8, // 0x17, ???
+ 8, // 0x18, ???
+ 8, // 0x19, ???
+ 8, // 0x1a, ???
+ 8, // 0x1b, ???
+ 8, // 0x1c, ???
+ 8, // 0x1d, ???
+ 8, // 0x1e, ???
+ 8, // 0x1f, ???
+ 8, // 0x20, ???
+ 8, // 0x21, ???
+ 8, // 0x22, ???
+ 8, // 0x23, ???
+ 16, // 0x24, Texture_Rectangle
+ 16, // 0x25, Texture_Rectangle_Flip
+ 8, // 0x26, Sync_Load
+ 8, // 0x27, Sync_Pipe
+ 8, // 0x28, Sync_Tile
+ 8, // 0x29, Sync_Full
+ 8, // 0x2a, Set_Key_GB
+ 8, // 0x2b, Set_Key_R
+ 8, // 0x2c, Set_Convert
+ 8, // 0x2d, Set_Scissor
+ 8, // 0x2e, Set_Prim_Depth
+ 8, // 0x2f, Set_Other_Modes
+ 8, // 0x30, Load_TLUT
+ 8, // 0x31, ???
+ 8, // 0x32, Set_Tile_Size
+ 8, // 0x33, Load_Block
+ 8, // 0x34, Load_Tile
+ 8, // 0x35, Set_Tile
+ 8, // 0x36, Fill_Rectangle
+ 8, // 0x37, Set_Fill_Color
+ 8, // 0x38, Set_Fog_Color
+ 8, // 0x39, Set_Blend_Color
+ 8, // 0x3a, Set_Prim_Color
+ 8, // 0x3b, Set_Env_Color
+ 8, // 0x3c, Set_Combine
+ 8, // 0x3d, Set_Texture_Image
+ 8, // 0x3e, Set_Mask_Image
+ 8 // 0x3f, Set_Color_Image
+};
+
+#if LOG_RDP_EXECUTION
+static int rdp_dasm(char *buffer)
+{
+ int i;
+ int tile;
+ const char *format, *size;
+ char sl[32], tl[32], sh[32], th[32];
+ char s[32], t[32], w[32];
+ char dsdx[32], dtdx[32], dwdx[32];
+ char dsdy[32], dtdy[32], dwdy[32];
+ char dsde[32], dtde[32], dwde[32];
+ char yl[32], yh[32], ym[32], xl[32], xh[32], xm[32];
+ char dxldy[32], dxhdy[32], dxmdy[32];
+ char rt[32], gt[32], bt[32], at[32];
+ char drdx[32], dgdx[32], dbdx[32], dadx[32];
+ char drdy[32], dgdy[32], dbdy[32], dady[32];
+ char drde[32], dgde[32], dbde[32], dade[32];
+ UINT32 r,g,b,a;
+
+ UINT32 cmd[64];
+ UINT32 length;
+ UINT32 command;
+
+ length = rdp_cmd_ptr * 4;
+ if (length < 8)
+ {
+ sprintf(buffer, "ERROR: length = %d\n", length);
+ return 0;
+ }
+
+ cmd[0] = rdp_cmd_data[rdp_cmd_cur+0];
+ cmd[1] = rdp_cmd_data[rdp_cmd_cur+1];
+
+ tile = (cmd[1] >> 24) & 0x7;
+ sprintf(sl, "%4.2f", (float)((cmd[0] >> 12) & 0xfff) / 4.0f);
+ sprintf(tl, "%4.2f", (float)((cmd[0] >> 0) & 0xfff) / 4.0f);
+ sprintf(sh, "%4.2f", (float)((cmd[1] >> 12) & 0xfff) / 4.0f);
+ sprintf(th, "%4.2f", (float)((cmd[1] >> 0) & 0xfff) / 4.0f);
+
+ format = image_format[(cmd[0] >> 21) & 0x7];
+ size = image_size[(cmd[0] >> 19) & 0x3];
+
+ r = (cmd[1] >> 24) & 0xff;
+ g = (cmd[1] >> 16) & 0xff;
+ b = (cmd[1] >> 8) & 0xff;
+ a = (cmd[1] >> 0) & 0xff;
+
+ command = (cmd[0] >> 24) & 0x3f;
+ switch (command)
+ {
+ case 0x00: sprintf(buffer, "No Op"); break;
+ case 0x08: // Tri_NoShade
+ {
+ int lft = (command >> 23) & 0x1;
+
+ if (length != rdp_command_length[command])
+ {
+ sprintf(buffer, "ERROR: Tri_NoShade length = %d\n", length);
+ return 0;
+ }
+
+ cmd[2] = rdp_cmd_data[rdp_cmd_cur+2];
+ cmd[3] = rdp_cmd_data[rdp_cmd_cur+3];
+ cmd[4] = rdp_cmd_data[rdp_cmd_cur+4];
+ cmd[5] = rdp_cmd_data[rdp_cmd_cur+5];
+ cmd[6] = rdp_cmd_data[rdp_cmd_cur+6];
+ cmd[7] = rdp_cmd_data[rdp_cmd_cur+7];
+
+ sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f));
+ sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f));
+ sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f));
+ sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f));
+ sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f));
+ sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f));
+
+ sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
+ break;
+ }
+ case 0x0a: // Tri_Tex
+ {
+ int lft = (command >> 23) & 0x1;
+
+ if (length < rdp_command_length[command])
+ {
+ sprintf(buffer, "ERROR: Tri_Tex length = %d\n", length);
+ return 0;
+ }
+
+ for (i=2; i < 24; i++)
+ {
+ cmd[i] = rdp_cmd_data[rdp_cmd_cur+i];
+ }
+
+ sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
+ sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
+ sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
+ sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
+ sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
+ sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
+
+ sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
+
+
+ buffer+=sprintf(buffer, "Tri_Tex %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
+ break;
+ }
+ case 0x0c: // Tri_Shade
+ {
+ int lft = (command >> 23) & 0x1;
+
+ if (length != rdp_command_length[command])
+ {
+ sprintf(buffer, "ERROR: Tri_Shade length = %d\n", length);
+ return 0;
+ }
+
+ for (i=2; i < 24; i++)
+ {
+ cmd[i] = rdp_cmd_data[i];
+ }
+
+ sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
+ sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
+ sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
+ sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
+ sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
+ sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
+ sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f);
+
+ buffer+=sprintf(buffer, "Tri_Shade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady);
+ break;
+ }
+ case 0x0e: // Tri_TexShade
+ {
+ int lft = (command >> 23) & 0x1;
+
+ if (length < rdp_command_length[command])
+ {
+ sprintf(buffer, "ERROR: Tri_TexShade length = %d\n", length);
+ return 0;
+ }
+
+ for (i=2; i < 40; i++)
+ {
+ cmd[i] = rdp_cmd_data[rdp_cmd_cur+i];
+ }
+
+ sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
+ sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
+ sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
+ sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
+ sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
+ sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
+ sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f);
+
+ sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f);
+
+
+ buffer+=sprintf(buffer, "Tri_TexShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady);
+
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde);
+ buffer+=sprintf(buffer, " ");
+ buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
+ break;
+ }
+ case 0x24:
+ case 0x25:
+ {
+ if (length < 16)
+ {
+ sprintf(buffer, "ERROR: Texture_Rectangle length = %d\n", length);
+ return 0;
+ }
+ cmd[2] = rdp_cmd_data[rdp_cmd_cur+2];
+ cmd[3] = rdp_cmd_data[rdp_cmd_cur+3];
+ sprintf(s, "%4.4f", (float)(INT16)((cmd[2] >> 16) & 0xffff) / 32.0f);
+ sprintf(t, "%4.4f", (float)(INT16)((cmd[2] >> 0) & 0xffff) / 32.0f);
+ sprintf(dsdx, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f);
+ sprintf(dtdy, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f);
+
+ if (command == 0x24)
+ sprintf(buffer, "Texture_Rectangle %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy);
+ else
+ sprintf(buffer, "Texture_Rectangle_Flip %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy);
+
+ break;
+ }
+ case 0x26: sprintf(buffer, "Sync_Load"); break;
+ case 0x27: sprintf(buffer, "Sync_Pipe"); break;
+ case 0x28: sprintf(buffer, "Sync_Tile"); break;
+ case 0x29: sprintf(buffer, "Sync_Full"); break;
+ case 0x2d: sprintf(buffer, "Set_Scissor %s, %s, %s, %s", sl, tl, sh, th); break;
+ case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", (cmd[1] >> 16) & 0xffff, cmd[1] & 0xffff); break;
+ case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", cmd[0], cmd[1]); break;
+ case 0x30: sprintf(buffer, "Load_TLUT %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
+ case 0x32: sprintf(buffer, "Set_Tile_Size %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
+ case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, (cmd[0] >> 12) & 0xfff, cmd[0] & 0xfff, (cmd[1] >> 12) & 0xfff, cmd[1] & 0xfff); break;
+ case 0x34: sprintf(buffer, "Load_Tile %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
+ case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, ((cmd[0] >> 9) & 0x1ff) * 8, (cmd[0] & 0x1ff) * 8); break;
+ case 0x36: sprintf(buffer, "Fill_Rectangle %s, %s, %s, %s", sh, th, sl, tl); break;
+ case 0x37: sprintf(buffer, "Set_Fill_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
+ case 0x38: sprintf(buffer, "Set_Fog_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
+ case 0x39: sprintf(buffer, "Set_Blend_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
+ case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", (cmd[0] >> 8) & 0x1f, cmd[0] & 0xff, r, g, b, a); break;
+ case 0x3b: sprintf(buffer, "Set_Env_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
+ case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", cmd[0], cmd[1]); break;
+ case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break;
+ case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", cmd[1]); break;
+ case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break;
+ default: sprintf(buffer, "??? (%08X %08X)", cmd[0], cmd[1]); break;
+ }
+
+ return rdp_command_length[command];
+}
+#endif
+
+/*****************************************************************************/
+
+////////////////////////
+// RDP COMMANDS
+////////////////////////
+
+static void rdp_invalid(UINT32 w1, UINT32 w2)
+{
+ fatalerror("RDP: invalid command %d, %08X %08X\n", (w1 >> 24) & 0x3f, w1, w2);
+}
+
+static void rdp_noop(UINT32 w1, UINT32 w2)
+{
+
+}
+
+static void rdp_tri_noshade(UINT32 w1, UINT32 w2)
+{
+ //fatalerror("RDP: unhandled command tri_noshade, %08X %08X\n", w1, w2);
+ triangle(w1, w2, 0, 0, 0);
+}
+
+static void rdp_tri_noshade_z(UINT32 w1, UINT32 w2)
+{
+ //fatalerror("RDP: unhandled command tri_noshade_z, %08X %08X\n", w1, w2);
+ triangle(w1, w2, 0, 0, 1);
+}
+
+static void rdp_tri_tex(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_tex, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 0, 1, 0);
+}
+
+static void rdp_tri_tex_z(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_tex_z, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 0, 1, 1);
+}
+
+static void rdp_tri_shade(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_shade, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 1, 0, 0);
+}
+
+static void rdp_tri_shade_z(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_shade_z, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 1, 0, 1);
+}
+
+static void rdp_tri_texshade(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_texshade, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 1, 1, 0);
+}
+
+static void rdp_tri_texshade_z(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command tri_texshade_z, %08X %08X\n", w1, w2);
+
+ triangle(w1, w2, 1, 1, 1);
+}
+
+static void rdp_tex_rect(UINT32 w1, UINT32 w2)
+{
+ UINT32 w3, w4;
+ TEX_RECTANGLE rect;
+
+ w3 = rdp_cmd_data[rdp_cmd_cur+2];
+ w4 = rdp_cmd_data[rdp_cmd_cur+3];
+
+ rect.tilenum = (w2 >> 24) & 0x7;
+ rect.xl = (w1 >> 12) & 0xfff;
+ rect.yl = (w1 >> 0) & 0xfff;
+ rect.xh = (w2 >> 12) & 0xfff;
+ rect.yh = (w2 >> 0) & 0xfff;
+ rect.s = (w3 >> 16) & 0xffff;
+ rect.t = (w3 >> 0) & 0xffff;
+ rect.dsdx = (w4 >> 16) & 0xffff;
+ rect.dtdy = (w4 >> 0) & 0xffff;
+
+ switch (fb_size)
+ {
+ case PIXEL_SIZE_16BIT: texture_rectangle_16bit(&rect); break;
+ case PIXEL_SIZE_32BIT: texture_rectangle_32bit(&rect); break;
+ }
+}
+
+static void rdp_tex_rect_flip(UINT32 w1, UINT32 w2)
+{
+ UINT32 w3, w4;
+ TEX_RECTANGLE rect;
+
+ w3 = rdp_cmd_data[rdp_cmd_cur+2];
+ w4 = rdp_cmd_data[rdp_cmd_cur+3];
+
+ rect.tilenum = (w2 >> 24) & 0x7;
+ rect.xl = (w1 >> 12) & 0xfff;
+ rect.yl = (w1 >> 0) & 0xfff;
+ rect.xh = (w2 >> 12) & 0xfff;
+ rect.yh = (w2 >> 0) & 0xfff;
+ rect.t = (w3 >> 16) & 0xffff;
+ rect.s = (w3 >> 0) & 0xffff;
+ rect.dtdy = (w4 >> 16) & 0xffff;
+ rect.dsdx = (w4 >> 0) & 0xffff;
+
+ switch (fb_size)
+ {
+ case PIXEL_SIZE_16BIT: texture_rectangle_16bit(&rect); break;
+ case PIXEL_SIZE_32BIT: texture_rectangle_32bit(&rect); break;
+ }
+}
+
+static void rdp_sync_load(UINT32 w1, UINT32 w2)
+{
+ // Nothing to do?
+}
+
+static void rdp_sync_pipe(UINT32 w1, UINT32 w2)
+{
+ // Nothing to do?
+}
+
+static void rdp_sync_tile(UINT32 w1, UINT32 w2)
+{
+ // Nothing to do?
+}
+
+static void rdp_sync_full(UINT32 w1, UINT32 w2)
+{
+ dp_full_sync();
+}
+
+static void rdp_set_key_gb(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command set_key_gb, %08X %08X\n", w1, w2);
+}
+
+static void rdp_set_key_r(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command set_key_r, %08X %08X\n", w1, w2);
+}
+
+static void rdp_set_convert(UINT32 w1, UINT32 w2)
+{
+ //osd_die("RDP: unhandled command set_convert, %08X %08X\n", w1, w2);
+}
+
+static void rdp_set_scissor(UINT32 w1, UINT32 w2)
+{
+ clip.xh = (w1 >> 12) & 0xfff;
+ clip.yh = (w1 >> 0) & 0xfff;
+ clip.xl = (w2 >> 12) & 0xfff;
+ clip.yl = (w2 >> 0) & 0xfff;
+
+ // TODO: handle f & o?
+}
+
+static void rdp_set_prim_depth(UINT32 w1, UINT32 w2)
+{
+ primitive_z = (UINT16)(w2 >> 16);
+ primitive_delta_z = (UINT16)(w1);
+}
+
+static void rdp_set_other_modes(UINT32 w1, UINT32 w2)
+{
+ other_modes.cycle_type = (w1 >> 20) & 0x3;
+ other_modes.persp_tex_en = (w1 & 0x80000) ? 1 : 0;
+ other_modes.detail_tex_en = (w1 & 0x40000) ? 1 : 0;
+ other_modes.sharpen_tex_en = (w1 & 0x20000) ? 1 : 0;
+ other_modes.tex_lod_en = (w1 & 0x10000) ? 1 : 0;
+ other_modes.en_tlut = (w1 & 0x08000) ? 1 : 0;
+ other_modes.tlut_type = (w1 & 0x04000) ? 1 : 0;
+ other_modes.sample_type = (w1 & 0x02000) ? 1 : 0;
+ other_modes.mid_texel = (w1 & 0x01000) ? 1 : 0;
+ other_modes.bi_lerp0 = (w1 & 0x00800) ? 1 : 0;
+ other_modes.bi_lerp1 = (w1 & 0x00400) ? 1 : 0;
+ other_modes.convert_one = (w1 & 0x00200) ? 1 : 0;
+ other_modes.key_en = (w1 & 0x00100) ? 1 : 0;
+ other_modes.rgb_dither_sel = (w1 >> 6) & 0x3;
+ other_modes.alpha_dither_sel = (w1 >> 4) & 0x3;
+ other_modes.blend_m1a_0 = (w2 >> 30) & 0x3;
+ other_modes.blend_m1a_1 = (w2 >> 28) & 0x3;
+ other_modes.blend_m1b_0 = (w2 >> 26) & 0x3;
+ other_modes.blend_m1b_1 = (w2 >> 24) & 0x3;
+ other_modes.blend_m2a_0 = (w2 >> 22) & 0x3;
+ other_modes.blend_m2a_1 = (w2 >> 20) & 0x3;
+ other_modes.blend_m2b_0 = (w2 >> 18) & 0x3;
+ other_modes.blend_m2b_1 = (w2 >> 16) & 0x3;
+ other_modes.force_blend = (w2 & 0x4000) ? 1 : 0;
+ other_modes.alpha_cvg_select = (w2 & 0x2000) ? 1 : 0;
+ other_modes.cvg_times_alpha = (w2 & 0x1000) ? 1 : 0;
+ other_modes.z_mode = (w2 >> 10) & 0x3;
+ other_modes.cvg_dest = (w2 >> 8) & 0x3;
+ other_modes.color_on_cvg = (w2 & 0x80) ? 1 : 0;
+ other_modes.image_read_en = (w2 & 0x40) ? 1 : 0;
+ other_modes.z_update_en = (w2 & 0x20) ? 1 : 0;
+ other_modes.z_compare_en = (w2 & 0x10) ? 1 : 0;
+ other_modes.antialias_en = (w2 & 0x08) ? 1 : 0;
+ other_modes.z_source_sel = (w2 & 0x04) ? 1 : 0;
+ other_modes.dither_alpha_en = (w2 & 0x02) ? 1 : 0;
+ other_modes.alpha_compare_en = (w2 & 0x01) ? 1 : 0;
+
+ SET_BLENDER_INPUT(0, 0, &blender1a_r[0], &blender1a_g[0], &blender1a_b[0], &blender1b_a[0],
+ other_modes.blend_m1a_0, other_modes.blend_m1b_0);
+ SET_BLENDER_INPUT(0, 1, &blender2a_r[0], &blender2a_g[0], &blender2a_b[0], &blender2b_a[0],
+ other_modes.blend_m2a_0, other_modes.blend_m2b_0);
+ SET_BLENDER_INPUT(1, 0, &blender1a_r[1], &blender1a_g[1], &blender1a_b[1], &blender1b_a[1],
+ other_modes.blend_m1a_1, other_modes.blend_m1b_1);
+ SET_BLENDER_INPUT(1, 1, &blender2a_r[1], &blender2a_g[1], &blender2a_b[1], &blender2b_a[1],
+ other_modes.blend_m2a_1, other_modes.blend_m2b_1);
+
+// mame_printf_debug("blend: m1a = %d, m1b = %d, m2a = %d, m2b = %d\n", other_modes.blend_m1a_0, other_modes.blend_m1b_0, other_modes.blend_m2a_0, other_modes.blend_m2b_0);
+
+ switch (other_modes.rgb_dither_sel)
+ {
+ case 0: break;
+ case 1: break; //fatalerror("bayer matrix dither\n"); break;
+ case 2: break; /////fatalerror("noise dither\n"); break;
+ case 3: break;
+ }
+}
+
+static void rdp_load_tlut(UINT32 w1, UINT32 w2)
+{
+ int i;
+ UINT16 sl, sh;
+// int tilenum = (w2 >> 24) & 0x7;
+
+ sl = ((w1 >> 12) & 0xfff) / 4;
+ sh = ((w2 >> 12) & 0xfff) / 4;
+
+ switch (ti_format)
+ {
+ case 0: // RGBA
+ {
+ switch (ti_size)
+ {
+ case PIXEL_SIZE_16BIT:
+ {
+ UINT16 *src = (UINT16*)&rdram[ti_address / 4];
+ // UINT16 *tlut = (UINT16*)&texture_cache[tile[tilenum].tmem/2];
+
+ for (i=sl; i <= sh; i++)
+ {
+ tlut[i] = src[i];
+ // mame_printf_debug("TLUT %d = %04X\n", i, tlut[i]);
+ }
+ break;
+ }
+ default: fatalerror("RDP: load_tlut: size = %d\n", ti_size);
+ }
+ break;
+ }
+
+ default: fatalerror("RDP: load_tlut: format = %d\n", ti_format);
+ }
+
+}
+
+static void rdp_set_tile_size(UINT32 w1, UINT32 w2)
+{
+ int tilenum = (w2 >> 24) & 0x7;
+
+ tile[tilenum].sl = (w1 >> 12) & 0xfff;
+ tile[tilenum].tl = (w1 >> 0) & 0xfff;
+ tile[tilenum].sh = (w2 >> 12) & 0xfff;
+ tile[tilenum].th = (w2 >> 0) & 0xfff;
+}
+
+static void rdp_load_block(UINT32 w1, UINT32 w2)
+{
+ int i, width;
+ UINT16 sl, sh, tl, dxt;
+ int tilenum = (w2 >> 24) & 0x7;
+ UINT32 *src, *tc;
+ int tb;
+
+ if (ti_format != tile[tilenum].format || ti_size != tile[tilenum].size)
+ fatalerror("RDP: load_block: format conversion required!\n");
+
+ sl = ((w1 >> 12) & 0xfff);
+ tl = ((w1 >> 0) & 0xfff) << 11;
+ sh = ((w2 >> 12) & 0xfff);
+ dxt = ((w2 >> 0) & 0xfff);
+
+ width = (sh - sl) + 1;
+
+ switch (ti_size)
+ {
+ case PIXEL_SIZE_4BIT: width >>= 1; break;
+ case PIXEL_SIZE_8BIT: break;
+ case PIXEL_SIZE_16BIT: width <<= 1; break;
+ case PIXEL_SIZE_32BIT: width <<= 2; break;
+ }
+
+
+ src = (UINT32*)&rdram[ti_address / 4];
+ tc = (UINT32*)texture_cache;
+ tb = tile[tilenum].tmem;
+
+ if (dxt != 0)
+ {
+ int j=0;
+ for (i=0; i < width; i+=2)
+ {
+ int t = j >> 11;
+
+ tc[((tb+i) + 0)] = src[((((tl * ti_width) / 4) + sl + i + 0) ^ ((t & 1) ? 1 : 0))];
+ tc[((tb+i) + 1)] = src[((((tl * ti_width) / 4) + sl + i + 1) ^ ((t & 1) ? 1 : 0))];
+
+ j += dxt;
+ }
+ }
+ else
+ {
+ for (i=0; i < width / 4; i++)
+ {
+ tc[(tb+i)] = src[((tl * ti_width) / 4) + sl + i];
+ }
+ }
+}
+
+static void rdp_load_tile(UINT32 w1, UINT32 w2)
+{
+ int i, j;
+ UINT16 sl, sh, tl, th;
+ int width, height;
+ int tilenum = (w2 >> 24) & 0x7;
+
+ if (ti_format != tile[tilenum].format || ti_size != tile[tilenum].size)
+ fatalerror("RDP: load_block: format conversion required!\n");
+
+ sl = ((w1 >> 12) & 0xfff) / 4;
+ tl = ((w1 >> 0) & 0xfff) / 4;
+ sh = ((w2 >> 12) & 0xfff) / 4;
+ th = ((w2 >> 0) & 0xfff) / 4;
+
+ width = (sh - sl) + 1;
+ height = (th - tl) + 1;
+
+ switch (ti_size)
+ {
+ case PIXEL_SIZE_8BIT:
+ {
+ UINT8 *src = (UINT8*)&rdram[ti_address / 4];
+ UINT8 *tc = (UINT8*)texture_cache;
+ int tb = tile[tilenum].tmem;
+
+ if (tb + (width * height) > 4096)
+ {
+ fatalerror("rdp_load_tile 8-bit: tmem %04X, width %d, height %d = %d\n", tile[tilenum].tmem, width, height, width*height);
+ }
+
+ for (j=0; j < height; j++)
+ {
+ int tline = tb + (tile[tilenum].line * j);
+ int s = ((j + tl) * ti_width) + sl;
+
+ for (i=0; i < width; i++)
+ {
+ tc[((tline+i) ^ BYTE_ADDR_XOR) ^ ((j & 1) ? 4 : 0)] = src[(s++) ^ BYTE_ADDR_XOR];
+ }
+ }
+ break;
+ }
+ case PIXEL_SIZE_16BIT:
+ {
+ UINT16 *src = (UINT16*)&rdram[ti_address / 4];
+ UINT16 *tc = (UINT16*)texture_cache;
+ int tb = (tile[tilenum].tmem / 2);
+
+ if (tb + (width * height) > 2048)
+ {
+ //fatalerror("rdp_load_tile 16-bit: tmem %04X, width %d, height %d = %d\n", tile[tilenum].tmem, width, height, width*height);
+ }
+
+ for (j=0; j < height; j++)
+ {
+ int tline = tb + ((tile[tilenum].line / 2) * j);
+ int s = ((j + tl) * ti_width) + sl;
+
+ for (i=0; i < width; i++)
+ {
+ tc[((tline+i) ^ WORD_ADDR_XOR) ^ ((j & 1) ? 2 : 0)] = src[(s++) ^ WORD_ADDR_XOR];
+ }
+ }
+ break;
+ }
+ case PIXEL_SIZE_32BIT:
+ {
+ UINT32 *src = (UINT32*)&rdram[ti_address / 4];
+ UINT32 *tc = (UINT32*)texture_cache;
+ int tb = (tile[tilenum].tmem / 4);
+
+ if (tb + (width * height) > 1024)
+ {
+ fatalerror("rdp_load_tile 32-bit: tmem %04X, width %d, height %d = %d\n", tile[tilenum].tmem, width, height, width*height);
+ }
+
+ for (j=0; j < height; j++)
+ {
+ int tline = tb + ((tile[tilenum].line / 4) * j);
+ int s = ((j + tl) * ti_width) + sl;
+
+ for (i=0; i < width; i++)
+ {
+ tc[(tline+i) ^ ((j & 1) ? 1 : 0)] = src[(s++)];
+ }
+ }
+ break;
+ }
+
+ default: fatalerror("RDP: load_tile: size = %d\n", ti_size);
+ }
+
+}
+
+static void rdp_set_tile(UINT32 w1, UINT32 w2)
+{
+ int tilenum = (w2 >> 24) & 0x7;
+
+ tile[tilenum].format = (w1 >> 21) & 0x7;
+ tile[tilenum].size = (w1 >> 19) & 0x3;
+ tile[tilenum].line = ((w1 >> 9) & 0x1ff) * 8;
+ tile[tilenum].tmem = ((w1 >> 0) & 0x1ff) * 8;
+ tile[tilenum].ct = (w2 >> 19) & 0x1;
+ tile[tilenum].mt = (w2 >> 18) & 0x1;
+ tile[tilenum].mask_t = (w2 >> 14) & 0xf;
+ tile[tilenum].shift_t = (w2 >> 10) & 0xf;
+ tile[tilenum].cs = (w2 >> 9) & 0x1;
+ tile[tilenum].ms = (w2 >> 8) & 0x1;
+ tile[tilenum].mask_s = (w2 >> 4) & 0xf;
+ tile[tilenum].shift_s = (w2 >> 0) & 0xf;
+
+ // TODO: clamp & mirror parameters
+}
+
+static void rdp_fill_rect(UINT32 w1, UINT32 w2)
+{
+ RECTANGLE rect;
+ rect.xl = (w1 >> 12) & 0xfff;
+ rect.yl = (w1 >> 0) & 0xfff;
+ rect.xh = (w2 >> 12) & 0xfff;
+ rect.yh = (w2 >> 0) & 0xfff;
+
+ switch (fb_size)
+ {
+ case PIXEL_SIZE_16BIT: fill_rectangle_16bit(&rect); break;
+ case PIXEL_SIZE_32BIT: fill_rectangle_32bit(&rect); break;
+ }
+}
+
+static void rdp_set_fill_color(UINT32 w1, UINT32 w2)
+{
+ fill_color = w2;
+}
+
+static void rdp_set_fog_color(UINT32 w1, UINT32 w2)
+{
+ fog_color.r = (w2 >> 24) & 0xff;
+ fog_color.g = (w2 >> 16) & 0xff;
+ fog_color.b = (w2 >> 8) & 0xff;
+ fog_color.a = (w2 >> 0) & 0xff;
+}
+
+static void rdp_set_blend_color(UINT32 w1, UINT32 w2)
+{
+ blend_color.r = (w2 >> 24) & 0xff;
+ blend_color.g = (w2 >> 16) & 0xff;
+ blend_color.b = (w2 >> 8) & 0xff;
+ blend_color.a = (w2 >> 0) & 0xff;
+}
+
+static void rdp_set_prim_color(UINT32 w1, UINT32 w2)
+{
+ // TODO: prim min level, prim_level
+ prim_color.r = (w2 >> 24) & 0xff;
+ prim_color.g = (w2 >> 16) & 0xff;
+ prim_color.b = (w2 >> 8) & 0xff;
+ prim_color.a = (w2 >> 0) & 0xff;
+}
+
+static void rdp_set_env_color(UINT32 w1, UINT32 w2)
+{
+ env_color.r = (w2 >> 24) & 0xff;
+ env_color.g = (w2 >> 16) & 0xff;
+ env_color.b = (w2 >> 8) & 0xff;
+ env_color.a = (w2 >> 0) & 0xff;
+}
+
+static void rdp_set_combine(UINT32 w1, UINT32 w2)
+{
+ combine.sub_a_rgb0 = (w1 >> 20) & 0xf;
+ combine.mul_rgb0 = (w1 >> 15) & 0x1f;
+ combine.sub_a_a0 = (w1 >> 12) & 0x7;
+ combine.mul_a0 = (w1 >> 9) & 0x7;
+ combine.sub_a_rgb1 = (w1 >> 5) & 0xf;
+ combine.mul_rgb1 = (w1 >> 0) & 0x1f;
+
+ combine.sub_b_rgb0 = (w2 >> 28) & 0xf;
+ combine.sub_b_rgb1 = (w2 >> 24) & 0xf;
+ combine.sub_a_a1 = (w2 >> 21) & 0x7;
+ combine.mul_a1 = (w2 >> 18) & 0x7;
+ combine.add_rgb0 = (w2 >> 15) & 0x7;
+ combine.sub_b_a0 = (w2 >> 12) & 0x7;
+ combine.add_a0 = (w2 >> 9) & 0x7;
+ combine.add_rgb1 = (w2 >> 6) & 0x7;
+ combine.sub_b_a1 = (w2 >> 3) & 0x7;
+ combine.add_a1 = (w2 >> 0) & 0x7;
+
+ SET_SUBA_RGB_INPUT(&combiner_rgbsub_a_r[0], &combiner_rgbsub_a_g[0], &combiner_rgbsub_a_b[0], combine.sub_a_rgb0);
+ SET_SUBB_RGB_INPUT(&combiner_rgbsub_b_r[0], &combiner_rgbsub_b_g[0], &combiner_rgbsub_b_b[0], combine.sub_b_rgb0);
+ SET_MUL_RGB_INPUT(&combiner_rgbmul_r[0], &combiner_rgbmul_g[0], &combiner_rgbmul_b[0], combine.mul_rgb0);
+ SET_ADD_RGB_INPUT(&combiner_rgbadd_r[0], &combiner_rgbadd_g[0], &combiner_rgbadd_b[0], combine.add_rgb0);
+ SET_SUB_ALPHA_INPUT(&combiner_alphasub_a[0], combine.sub_a_a0);
+ SET_SUB_ALPHA_INPUT(&combiner_alphasub_b[0], combine.sub_b_a0);
+ SET_MUL_ALPHA_INPUT(&combiner_alphamul[0], combine.mul_a0);
+ SET_SUB_ALPHA_INPUT(&combiner_alphaadd[0], combine.add_a0);
+
+ SET_SUBA_RGB_INPUT(&combiner_rgbsub_a_r[1], &combiner_rgbsub_a_g[1], &combiner_rgbsub_a_b[1], combine.sub_a_rgb1);
+ SET_SUBB_RGB_INPUT(&combiner_rgbsub_b_r[1], &combiner_rgbsub_b_g[1], &combiner_rgbsub_b_b[1], combine.sub_b_rgb1);
+ SET_MUL_RGB_INPUT(&combiner_rgbmul_r[1], &combiner_rgbmul_g[1], &combiner_rgbmul_b[1], combine.mul_rgb1);
+ SET_ADD_RGB_INPUT(&combiner_rgbadd_r[1], &combiner_rgbadd_g[1], &combiner_rgbadd_b[1], combine.add_rgb1);
+ SET_SUB_ALPHA_INPUT(&combiner_alphasub_a[1], combine.sub_a_a1);
+ SET_SUB_ALPHA_INPUT(&combiner_alphasub_b[1], combine.sub_b_a1);
+ SET_MUL_ALPHA_INPUT(&combiner_alphamul[1], combine.mul_a1);
+ SET_SUB_ALPHA_INPUT(&combiner_alphaadd[1], combine.add_a1);
+}
+
+static void rdp_set_texture_image(UINT32 w1, UINT32 w2)
+{
+ ti_format = (w1 >> 21) & 0x7;
+ ti_size = (w1 >> 19) & 0x3;
+ ti_width = (w1 & 0x3ff) + 1;
+ ti_address = w2 & 0x01ffffff;
+}
+
+static void rdp_set_mask_image(UINT32 w1, UINT32 w2)
+{
+ zb_address = w2 & 0x01ffffff;
+}
+
+static void rdp_set_color_image(UINT32 w1, UINT32 w2)
+{
+ fb_format = (w1 >> 21) & 0x7;
+ fb_size = (w1 >> 19) & 0x3;
+ fb_width = (w1 & 0x3ff) + 1;
+ fb_address = w2 & 0x01ffffff;
+
+ //if (fb_format != 0) fatalerror("rdp_set_color_image: format = %d\n", fb_format);
+ if (fb_format != 0) fb_format = 0;
+}
+
+/*****************************************************************************/
+
+static void (* rdp_command_table[64])(UINT32 w1, UINT32 w2) =
+{
+ /* 0x00 */
+ rdp_noop, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_tri_noshade, rdp_tri_noshade_z, rdp_tri_tex, rdp_tri_tex_z,
+ rdp_tri_shade, rdp_tri_shade_z, rdp_tri_texshade, rdp_tri_texshade_z,
+ /* 0x10 */
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ /* 0x20 */
+ rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
+ rdp_tex_rect, rdp_tex_rect_flip, rdp_sync_load, rdp_sync_pipe,
+ rdp_sync_tile, rdp_sync_full, rdp_set_key_gb, rdp_set_key_r,
+ rdp_set_convert, rdp_set_scissor, rdp_set_prim_depth, rdp_set_other_modes,
+ /* 0x30 */
+ rdp_load_tlut, rdp_invalid, rdp_set_tile_size, rdp_load_block,
+ rdp_load_tile, rdp_set_tile, rdp_fill_rect, rdp_set_fill_color,
+ rdp_set_fog_color, rdp_set_blend_color, rdp_set_prim_color, rdp_set_env_color,
+ rdp_set_combine, rdp_set_texture_image, rdp_set_mask_image, rdp_set_color_image
+};
+
+void rdp_process_list(void)
+{
+ int i;
+ UINT32 cmd, length, cmd_length;
+
+ length = dp_end - dp_current;
+
+ // load command data
+ for (i=0; i < length; i += 4)
+ {
+ rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i);
+ if (rdp_cmd_ptr >= 0x1000)
+ {
+ fatalerror("rdp_process_list: rdp_cmd_ptr overflow\n");
+ }
+ }
+
+ dp_current = dp_end;
+
+ cmd = (rdp_cmd_data[0] >> 24) & 0x3f;
+ cmd_length = (rdp_cmd_ptr + 1) * 4;
+
+ // check if more data is needed
+ if (cmd_length < rdp_command_length[cmd])
+ {
+ return;
+ }
+
+ while (rdp_cmd_cur < rdp_cmd_ptr)
+ {
+ cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
+ // if (((rdp_cmd_data[rdp_cmd_cur] >> 24) & 0xc0) != 0xc0)
+ // {
+ // fatalerror("rdp_process_list: invalid rdp command %08X at %08X\n", rdp_cmd_data[rdp_cmd_cur], dp_start+(rdp_cmd_cur * 4));
+ // }
+
+ if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd])
+ {
+ return;
+ //fatalerror("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", rdp_cmd_cur, rdp_cmd_ptr, rdp_command_length[cmd]);
+ }
+
+#if LOG_RDP_EXECUTION
+ {
+ char string[4000];
+ rdp_dasm(string);
+
+ fprintf(rdp_exec, "%08X: %08X %08X %s\n", dp_start+(rdp_cmd_cur * 4), rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1], string);
+ }
+#endif
+
+ // execute the command
+ rdp_command_table[cmd](rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1]);
+
+ rdp_cmd_cur += rdp_command_length[cmd] / 4;
+ };
+ rdp_cmd_ptr = 0;
+ rdp_cmd_cur = 0;
+
+ dp_start = dp_end;
+}