mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2025-04-02 10:52:35 -04:00
3508 lines
104 KiB
C++
3508 lines
104 KiB
C++
/*
|
|
Nintendo 64 Video Hardware
|
|
|
|
Written by Ville Linde
|
|
*/
|
|
|
|
// #include "driver.h"
|
|
// #include "includes/n64.h"
|
|
#include "Gfx #1.3.h"
|
|
#include "z64.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
inline void fatalerror(const char * err, ...)
|
|
{
|
|
fprintf(stderr, "%s\n", err);
|
|
//exit(0);
|
|
}
|
|
|
|
#define INLINE inline
|
|
|
|
#define LOG_RDP_EXECUTION 0
|
|
|
|
#if LOG_RDP_EXECUTION
|
|
static FILE *rdp_exec;
|
|
#endif
|
|
|
|
/* defined in systems/n64.c */
|
|
#define rdram ((UINT32*)gfx.RDRAM)
|
|
//extern UINT32 *rdram;
|
|
#define rsp_imem ((UINT32*)gfx.IMEM)
|
|
//extern UINT32 *rsp_imem;
|
|
#define rsp_dmem ((UINT32*)gfx.DMEM)
|
|
//extern UINT32 *rsp_dmem;
|
|
//extern void dp_full_sync(void);
|
|
|
|
#define vi_origin (*(UINT32*)gfx.VI_ORIGIN_REG)
|
|
//extern UINT32 vi_origin;
|
|
#define vi_width (*(UINT32*)gfx.VI_WIDTH_REG)
|
|
//extern UINT32 vi_width;
|
|
#define vi_control (*(UINT32*)gfx.VI_STATUS_REG)
|
|
//extern UINT32 vi_control;
|
|
|
|
#define dp_start (*(UINT32*)gfx.DPC_START_REG)
|
|
//extern UINT32 dp_start;
|
|
#define dp_end (*(UINT32*)gfx.DPC_END_REG)
|
|
//extern UINT32 dp_end;
|
|
#define dp_current (*(UINT32*)gfx.DPC_CURRENT_REG)
|
|
//extern UINT32 dp_current;
|
|
#define dp_status (*(UINT32*)gfx.DPC_STATUS_REG)
|
|
//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];
|
|
|
|
/*****************************************************************************/
|
|
|
|
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;
|
|
static 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[0x100000]; // *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)
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
int rdp_init()
|
|
{
|
|
#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;
|
|
return 0;
|
|
}
|
|
|
|
int rdp_update()
|
|
{
|
|
int i, j;
|
|
int height = (vi_control & 0x40) ? 479 : 239;
|
|
|
|
static UINT32 old_vi_origin;
|
|
|
|
if (old_vi_origin == vi_origin) {
|
|
printf("same\n");
|
|
//return 0;
|
|
}
|
|
old_vi_origin = vi_origin;
|
|
|
|
SDL_LockSurface(sdl_Screen);
|
|
|
|
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);
|
|
UINT32 * d = (UINT32 *) ((char*)sdl_Screen->pixels + j*sdl_Screen->pitch);
|
|
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);
|
|
UINT32 * d = (UINT32 *) ((char*)sdl_Screen->pixels + j*sdl_Screen->pitch);
|
|
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);
|
|
}
|
|
|
|
SDL_UnlockSurface(sdl_Screen);
|
|
SDL_Flip(sdl_Screen);
|
|
//SDL_GL_SwapBuffers();
|
|
|
|
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);
|
|
|
|
// VP ?????
|
|
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_colors[2] = {
|
|
(fill_color >> 0) & 0xffff,
|
|
(fill_color >> 16) & 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] = fill_colors[i & 1];
|
|
}
|
|
}
|
|
}
|
|
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: break;
|
|
case 1: break; // FIXME?: Extreme-G 2 does this
|
|
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: 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: break; // FIXME?: Clay Fighter Sculptor's Cut does this..
|
|
default: 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: 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: fatalerror("FETCH_TEXEL: unknown I texture size %d\n", tsize); break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
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 1
|
|
#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;
|
|
|
|
// VP ??????
|
|
*fb = (c1.r << 16) | (c1.g << 8) | c1.b;
|
|
//*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)];
|
|
}
|
|
}
|
|
|
|
static const char *image_format[] = { "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" };
|
|
static const char *image_size[] = { "4-bit", "8-bit", "16-bit", "32-bit" };
|
|
|
|
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
|
|
};
|
|
|
|
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];
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
////////////////////////
|
|
// 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)
|
|
{
|
|
// VP ?
|
|
//dp_full_sync();
|
|
printf("full sync\n");
|
|
rdp_update();
|
|
|
|
*gfx.MI_INTR_REG |= 0x20;
|
|
gfx.CheckInterrupts();
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
if (dp_end <= dp_current) return;
|
|
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)
|
|
{
|
|
printf("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
dp_status &= ~0x0002;
|
|
}
|