midzeus.c: Further improvements: [Phil Bennett]
* Added alternate back-face culling method * Added additional blend modes * Added depth test and write enables * Slightly improved rasterization
This commit is contained in:
parent
780c76d9d2
commit
b97f446084
@ -27,10 +27,14 @@
|
||||
#define WAVERAM1_WIDTH 512
|
||||
#define WAVERAM1_HEIGHT 512
|
||||
|
||||
#define BLEND_OPAQUE 0x00000000
|
||||
#define BLEND_OPAQUE1 0x00000000
|
||||
#define BLEND_OPAQUE2 0x4b23cb00
|
||||
#define BLEND_ADD 0x40b68800
|
||||
#define BLEND_SUB 0x4093c800
|
||||
#define BLEND_OPAQUE3 0x4b23dd00
|
||||
#define BLEND_OPAQUE4 0x00004800
|
||||
#define BLEND_OPAQUE5 0xdd23dd00
|
||||
#define BLEND_ADD1 0x40b68800
|
||||
#define BLEND_ADD2 0xc9b78800
|
||||
#define BLEND_MUL1 0x4093c800
|
||||
|
||||
|
||||
/*************************************
|
||||
@ -41,18 +45,21 @@
|
||||
|
||||
struct mz_poly_extra_data
|
||||
{
|
||||
const void * palbase;
|
||||
const void * texbase;
|
||||
UINT16 solidcolor;
|
||||
UINT16 voffset;
|
||||
INT16 zoffset;
|
||||
UINT16 transcolor;
|
||||
UINT16 texwidth;
|
||||
UINT16 color;
|
||||
UINT32 alpha;
|
||||
const void * palbase;
|
||||
const void * texbase;
|
||||
UINT16 solidcolor;
|
||||
UINT16 voffset;
|
||||
INT16 zoffset;
|
||||
UINT16 transcolor;
|
||||
UINT16 texwidth;
|
||||
UINT16 color;
|
||||
UINT32 alpha;
|
||||
UINT32 ctrl_word;
|
||||
bool blend_enable;
|
||||
bool depth_test_enable;
|
||||
bool depth_write_enable;
|
||||
UINT32 blend;
|
||||
UINT8 (*get_texel)(const void *, int, int, int);
|
||||
UINT8 (*get_texel)(const void *, int, int, int);
|
||||
};
|
||||
|
||||
|
||||
@ -73,6 +80,7 @@ static INT32 zeus_point[3];
|
||||
static INT16 zeus_light[3];
|
||||
static void *zeus_renderbase;
|
||||
static UINT32 zeus_palbase;
|
||||
static UINT32 zeus_unkbase;
|
||||
static int zeus_enable_logging;
|
||||
static UINT32 zeus_objdata;
|
||||
static rectangle zeus_cliprect;
|
||||
@ -94,9 +102,7 @@ INLINE UINT8 get_texel_alt_4bit(const void *base, int y, int x, int width);
|
||||
INLINE UINT8 get_texel_8bit(const void *base, int y, int x, int width);
|
||||
INLINE UINT8 get_texel_alt_8bit(const void *base, int y, int x, int width);
|
||||
|
||||
static void render_poly_texture(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
|
||||
static void render_poly_shade(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
|
||||
static void render_poly_solid(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
|
||||
static void render_poly(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
|
||||
static void render_poly_solid_fixedz(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
|
||||
|
||||
|
||||
@ -172,12 +178,6 @@ INLINE void *waveram0_ptr_from_texture_addr(UINT32 addr, int width)
|
||||
*
|
||||
*************************************/
|
||||
|
||||
INLINE void waveram_plot(int y, int x, UINT16 color)
|
||||
{
|
||||
if (zeus_cliprect.contains(x, y))
|
||||
WAVERAM_WRITEPIX(zeus_renderbase, y, x, color);
|
||||
}
|
||||
|
||||
INLINE void waveram_plot_depth(int y, int x, UINT16 color, UINT16 depth)
|
||||
{
|
||||
if (zeus_cliprect.contains(x, y))
|
||||
@ -187,6 +187,13 @@ INLINE void waveram_plot_depth(int y, int x, UINT16 color, UINT16 depth)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED_FUNCTION
|
||||
INLINE void waveram_plot(int y, int x, UINT16 color)
|
||||
{
|
||||
if (zeus_cliprect.contains(x, y))
|
||||
WAVERAM_WRITEPIX(zeus_renderbase, y, x, color);
|
||||
}
|
||||
|
||||
INLINE void waveram_plot_check_depth(int y, int x, UINT16 color, UINT16 depth)
|
||||
{
|
||||
if (zeus_cliprect.contains(x, y))
|
||||
@ -200,7 +207,6 @@ INLINE void waveram_plot_check_depth(int y, int x, UINT16 color, UINT16 depth)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED_FUNCTION
|
||||
INLINE void waveram_plot_check_depth_nowrite(int y, int x, UINT16 color, UINT16 depth)
|
||||
{
|
||||
if (zeus_cliprect.contains(x, y))
|
||||
@ -219,33 +225,32 @@ INLINE void waveram_plot_check_depth_nowrite(int y, int x, UINT16 color, UINT16
|
||||
*
|
||||
*************************************/
|
||||
|
||||
INLINE UINT8 get_texel_8bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 2) * (width * 2) + ((x / 4) << 3) + ((y & 1) << 2) + (x & 3);
|
||||
return WAVERAM_READ8(base, byteoffs);
|
||||
}
|
||||
|
||||
|
||||
INLINE UINT8 get_texel_alt_8bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 4) * (width * 4) + ((x / 2) << 3) + ((y & 3) << 1) + (x & 1);
|
||||
return WAVERAM_READ8(base, byteoffs);
|
||||
}
|
||||
|
||||
|
||||
// 4x2 block size
|
||||
INLINE UINT8 get_texel_4bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 2) * (width * 2) + ((x / 8) << 3) + ((y & 1) << 2) + ((x / 2) & 3);
|
||||
return (WAVERAM_READ8(base, byteoffs) >> (4 * (x & 1))) & 0x0f;
|
||||
}
|
||||
|
||||
INLINE UINT8 get_texel_8bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 2) * (width * 2) + ((x / 4) << 3) + ((y & 1) << 2) + (x & 3);
|
||||
return WAVERAM_READ8(base, byteoffs);
|
||||
}
|
||||
|
||||
// 2x2 block size
|
||||
INLINE UINT8 get_texel_alt_4bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 4) * (width * 4) + ((x / 4) << 3) + ((y & 3) << 1) + ((x / 2) & 1);
|
||||
return (WAVERAM_READ8(base, byteoffs) >> (4 * (x & 1))) & 0x0f;
|
||||
}
|
||||
|
||||
INLINE UINT8 get_texel_alt_8bit(const void *base, int y, int x, int width)
|
||||
{
|
||||
UINT32 byteoffs = (y / 4) * (width * 4) + ((x / 2) << 3) + ((y & 3) << 1) + (x & 1);
|
||||
return WAVERAM_READ8(base, byteoffs);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video startup
|
||||
@ -490,6 +495,12 @@ void midzeus_state::zeus_pointer_w(UINT32 which, UINT32 data, int logit)
|
||||
zeus_palbase = data;
|
||||
break;
|
||||
|
||||
case 0x02c0f0:
|
||||
if (logit)
|
||||
logerror(" -- setptr(unkbase)\n");
|
||||
zeus_unkbase = data;
|
||||
break;
|
||||
|
||||
|
||||
// case 0x004040: -- set via FIFO command in mk4 (len=02)
|
||||
|
||||
@ -907,13 +918,12 @@ int midzeus_state::zeus_fifo_process(const UINT32 *data, int numwords)
|
||||
if (log_fifo)
|
||||
{
|
||||
log_fifo_command(data, numwords, "");
|
||||
logerror(" -- additional xyz = %d,%d,%d\n", (INT16)data[0], (INT16)(data[1] >> 16), (INT16)data[1]);
|
||||
|
||||
/* guessing this might be a light source? */
|
||||
zeus_light[0] = (INT16)data[0];
|
||||
zeus_light[1] = (INT16)(data[1] >> 16);
|
||||
zeus_light[2] = (INT16)data[1];
|
||||
logerror(" -- light xyz = %d,%d,%d\n", (INT16)data[1], (INT16)(data[1] >> 16), (INT16)data[0]);
|
||||
}
|
||||
|
||||
zeus_light[0] = (INT16)(data[1] & 0xffff);
|
||||
zeus_light[1] = (INT16)(data[1] >> 16);
|
||||
zeus_light[2] = (INT16)(data[0] & 0xffff);
|
||||
break;
|
||||
/* 0x25: display control? */
|
||||
/* 0x28: same for mk4b */
|
||||
@ -1092,58 +1102,22 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
mz_poly_extra_data *extra;
|
||||
poly_vertex clipvert[8];
|
||||
poly_vertex vert[4];
|
||||
float uscale, vscale;
|
||||
UINT32 ushift, vshift;
|
||||
float maxy, maxx;
|
||||
int val2, texbase, texwshift;
|
||||
int numverts;
|
||||
int i;
|
||||
INT16 normal[3];
|
||||
INT32 rotnormal[3];
|
||||
UINT32 texbase, texwshift;
|
||||
UINT32 numverts;
|
||||
|
||||
INT32 ctrl_word = databuffer[long_fmt ? 1 : 9];
|
||||
|
||||
/* look for interesting data patterns */
|
||||
if (
|
||||
(ctrl_word & 0xffffffff) != 0x200c0000 && /* mk4 sometimes */
|
||||
(ctrl_word & 0xfffe0000) != 0x21000000 && /* most of mk4 */
|
||||
(ctrl_word & 0xffffffff) != 0x008c0000 && /* invasn */
|
||||
(ctrl_word & 0xfffeffff) != 0x028c0000 && /* invasn */
|
||||
(ctrl_word & 0xfffe0000) != 0x21800000 && /* invasn */
|
||||
(ctrl_word & 0xfffe0000) != 0x23800000 && /* invasn */
|
||||
1)
|
||||
printf("zeus_draw_quad: ctrl_word = %08X\n", ctrl_word);
|
||||
|
||||
|
||||
/* do a simple backface cull; not sure if the hardware does it, but I see no other
|
||||
reason for a polygon normal here */
|
||||
|
||||
/* extract the polygon normal */
|
||||
normal[0] = (INT8)(databuffer[0] >> 0);
|
||||
normal[1] = (INT8)(databuffer[0] >> 8);
|
||||
normal[2] = (INT8)(databuffer[0] >> 16);
|
||||
|
||||
/* rotate the normal into camera view; we only need the Z coordinate */
|
||||
rotnormal[2] = normal[0] * zeus_matrix[2][0] + normal[1] * zeus_matrix[2][1] + normal[2] * zeus_matrix[2][2];
|
||||
|
||||
/* if we're pointing away from the camera, toss */
|
||||
if (rotnormal[2] > 0)
|
||||
{
|
||||
if (logit)
|
||||
logerror("quad (culled %08X)\n", rotnormal[2]);
|
||||
// if (machine().input().code_pressed(KEYCODE_COMMA))
|
||||
// return;
|
||||
}
|
||||
UINT32 ctrl_word = databuffer[long_fmt ? 1 : 9];
|
||||
|
||||
texbase = ((texdata >> 10) & 0x3f0000) | (texdata & 0xffff);
|
||||
val2 = (texdata >> 16) & 0x3ff;
|
||||
texwshift = (val2 >> 6) & 7;
|
||||
texwshift = (texdata >> 22) & 7;
|
||||
|
||||
uscale = (8 >> ((m_zeusbase[0x04] >> 4) & 3)) * 0.125f * 256.0f;
|
||||
vscale = (8 >> ((m_zeusbase[0x04] >> 6) & 3)) * 0.125f * 256.0f;
|
||||
ushift = 8 - ((m_zeusbase[0x04] >> 4) & 3);
|
||||
vshift = 8 - ((m_zeusbase[0x04] >> 6) & 3);
|
||||
|
||||
int xy_offset = long_fmt ? 2 : 1;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (UINT32 i = 0; i < 4; i++)
|
||||
{
|
||||
UINT32 ixy = databuffer[xy_offset + i*2];
|
||||
UINT32 iuvz = databuffer[xy_offset + 1 + i*2];
|
||||
@ -1152,41 +1126,64 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
INT32 zo = (INT16)iuvz;
|
||||
UINT8 u = iuvz >> 16;
|
||||
UINT8 v = iuvz >> 24;
|
||||
INT32 dotnormal = 0;
|
||||
INT64 x, y, z;
|
||||
|
||||
|
||||
x = (INT64)(xo * zeus_matrix[0][0]) + (INT64)(yo * zeus_matrix[0][1]) + (INT64)(zo * zeus_matrix[0][2]) + zeus_point[0];
|
||||
y = (INT64)(xo * zeus_matrix[1][0]) + (INT64)(yo * zeus_matrix[1][1]) + (INT64)(zo * zeus_matrix[1][2]) + zeus_point[1];
|
||||
z = (INT64)(xo * zeus_matrix[2][0]) + (INT64)(yo * zeus_matrix[2][1]) + (INT64)(zo * zeus_matrix[2][2]) + zeus_point[2];
|
||||
|
||||
// Rounding hack
|
||||
x = (x + 0x00004000) & ~0x00007fffULL;
|
||||
y = (y + 0x00004000) & ~0x00007fffULL;
|
||||
z = (z + 0x00004000) & ~0x00007fffULL;
|
||||
|
||||
// back face cull using polygon normal and first vertex
|
||||
if (i == 0)
|
||||
{
|
||||
INT16 normal[3];
|
||||
INT32 rotnormal[3];
|
||||
|
||||
normal[0] = (INT8)(databuffer[0] >> 0);
|
||||
normal[1] = (INT8)(databuffer[0] >> 8);
|
||||
normal[2] = (INT8)(databuffer[0] >> 16);
|
||||
|
||||
rotnormal[0] = normal[0] * zeus_matrix[0][0] + normal[1] * zeus_matrix[0][1] + normal[2] * zeus_matrix[0][2];
|
||||
rotnormal[1] = normal[0] * zeus_matrix[1][0] + normal[1] * zeus_matrix[1][1] + normal[2] * zeus_matrix[1][2];
|
||||
rotnormal[2] = normal[0] * zeus_matrix[2][0] + normal[1] * zeus_matrix[2][1] + normal[2] * zeus_matrix[2][2];
|
||||
|
||||
INT64 dot = rotnormal[0] * x + rotnormal[1] * y + rotnormal[2] * z;
|
||||
|
||||
if (dot >= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (long_fmt)
|
||||
{
|
||||
#if 0
|
||||
// TODO: Lighting
|
||||
UINT32 inormal = databuffer[10 + i];
|
||||
INT32 xn = (INT32)(inormal << 2) >> 20;
|
||||
INT32 yn = (INT32)(inormal << 12) >> 20;
|
||||
INT32 zn = (INT32)(inormal << 22) >> 20;
|
||||
|
||||
rotnormal[0] = ((INT64)(xn * zeus_matrix[0][0]) + (INT64)(yn * zeus_matrix[0][1]) + (INT64)(zn * zeus_matrix[0][2])) >> 14;
|
||||
rotnormal[1] = ((INT64)(xn * zeus_matrix[1][0]) + (INT64)(yn * zeus_matrix[1][1]) + (INT64)(zn * zeus_matrix[1][2])) >> 14;
|
||||
rotnormal[2] = ((INT64)(xn * zeus_matrix[2][0]) + (INT64)(yn * zeus_matrix[2][1]) + (INT64)(zn * zeus_matrix[2][2])) >> 14;
|
||||
|
||||
dotnormal = rotnormal[0] * ((x >> 16) + zeus_light[0]) + rotnormal[1] * ((y >> 16) + zeus_light[1]) + rotnormal[2] * ((z >> 16) + zeus_light[2]);
|
||||
INT32 xn = (INT32)(((inormal >> 0) & 0x3ff) << 22) >> 22;
|
||||
INT32 yn = (INT32)(((inormal >> 10) & 0x3ff) << 22) >> 22;
|
||||
INT32 zn = (INT32)(((inormal >> 20) & 0x3ff) << 22) >> 22;
|
||||
#endif
|
||||
}
|
||||
|
||||
vert[i].x = x;
|
||||
vert[i].y = y;
|
||||
vert[i].p[0] = z;
|
||||
vert[i].p[1] = u * uscale;
|
||||
vert[i].p[2] = v * vscale;
|
||||
vert[i].p[3] = dotnormal;
|
||||
vert[i].p[1] = u << ushift;
|
||||
vert[i].p[2] = v << vshift;
|
||||
vert[i].p[3] = 0xffff;
|
||||
|
||||
if (logit)
|
||||
{
|
||||
logerror("\t\t(%f,%f,%f) (%02X,%02X) (%03X,%03X,%03X) dot=%08X\n",
|
||||
logerror("\t\t(%f,%f,%f) UV:(%02X,%02X) UV_SCALE:(%02X,%02X) (%03X,%03X,%03X) dot=%08X\n",
|
||||
(double) vert[i].x * (1.0 / 65536.0), (double) vert[i].y * (1.0 / 65536.0), (double) vert[i].p[0] * (1.0 / 65536.0),
|
||||
(iuvz >> 16) & 0xff, (iuvz >> 24) & 0xff,
|
||||
(int)(vert[i].p[1] / 256.0f), (int)(vert[i].p[2] / 256.0f),
|
||||
(databuffer[10 + i] >> 20) & 0x3ff, (databuffer[10 + i] >> 10) & 0x3ff, (databuffer[10 + i] >> 0) & 0x3ff,
|
||||
dotnormal);
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1195,7 +1192,7 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
return;
|
||||
|
||||
maxx = maxy = -1000.0f;
|
||||
for (i = 0; i < numverts; i++)
|
||||
for (UINT32 i = 0; i < numverts; i++)
|
||||
{
|
||||
float ooz = 512.0f / clipvert[i].p[0];
|
||||
|
||||
@ -1206,10 +1203,11 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
|
||||
maxx = MAX(maxx, clipvert[i].x);
|
||||
maxy = MAX(maxy, clipvert[i].y);
|
||||
|
||||
if (logit)
|
||||
logerror("\t\t\tTranslated=(%f,%f)\n", (double) clipvert[i].x, (double) clipvert[i].y);
|
||||
logerror("\t\t\tTranslated=(%f,%f,%f)\n", (double) clipvert[i].x, (double) clipvert[i].y, (double) clipvert[i].p[0]);
|
||||
}
|
||||
for (i = 0; i < numverts; i++)
|
||||
for (UINT32 i = 0; i < numverts; i++)
|
||||
{
|
||||
if (clipvert[i].x == maxx)
|
||||
clipvert[i].x += 0.0005f;
|
||||
@ -1219,30 +1217,21 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
|
||||
extra = (mz_poly_extra_data *)poly_get_extra_data(poly);
|
||||
|
||||
if ((ctrl_word & 0x000c0000) == 0x000c0000)
|
||||
if (ctrl_word & 0x01000000)
|
||||
{
|
||||
callback = render_poly_solid;
|
||||
}
|
||||
else if (val2 == 0x182)
|
||||
{
|
||||
callback = render_poly_shade;
|
||||
}
|
||||
else if (ctrl_word & 0x01000000)
|
||||
{
|
||||
int tex_type = val2 & 3;
|
||||
|
||||
callback = render_poly_texture;
|
||||
UINT32 tex_type = (texdata >> 16) & 3;
|
||||
extra->texwidth = 512 >> texwshift;
|
||||
extra->voffset = ctrl_word & 0xffff;
|
||||
|
||||
extra->texbase = waveram0_ptr_from_texture_addr(texbase, extra->texwidth);
|
||||
|
||||
if (tex_type == 1)
|
||||
{
|
||||
extra->get_texel = (val2 & 0x20) ? get_texel_8bit : get_texel_4bit;
|
||||
extra->get_texel = texdata & 0x00200000 ? get_texel_8bit : get_texel_4bit;
|
||||
}
|
||||
else if (tex_type == 2)
|
||||
{
|
||||
extra->get_texel = (val2 & 0x20) ? get_texel_alt_8bit : get_texel_alt_4bit;
|
||||
extra->get_texel = texdata & 0x00200000 ? get_texel_alt_8bit : get_texel_alt_4bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1250,16 +1239,16 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown draw mode: %.8x\n", ctrl_word);
|
||||
return;
|
||||
}
|
||||
|
||||
callback = render_poly;
|
||||
|
||||
extra->ctrl_word = ctrl_word;
|
||||
extra->solidcolor = m_zeusbase[0x00] & 0x7fff;
|
||||
extra->zoffset = m_zeusbase[0x7e] >> 16;
|
||||
extra->alpha = m_zeusbase[0x4e];
|
||||
extra->blend = m_zeusbase[0x5c];
|
||||
extra->blend_enable = m_zeusbase[0x5c] == BLEND_ADD || m_zeusbase[0x5c] == BLEND_SUB;
|
||||
extra->depth_test_enable = !(m_zeusbase[0x04] & 0x800);
|
||||
extra->depth_write_enable = m_zeusbase[0x04] & 0x200;
|
||||
extra->transcolor = ((ctrl_word >> 16) & 1) ? 0 : 0x100;
|
||||
extra->palbase = waveram0_ptr_from_block_addr(zeus_palbase);
|
||||
|
||||
@ -1274,147 +1263,214 @@ void midzeus_state::zeus_draw_quad(int long_fmt, const UINT32 *databuffer, UINT3
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static void render_poly_texture(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
|
||||
static void render_poly(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
|
||||
{
|
||||
const mz_poly_extra_data *extra = (const mz_poly_extra_data *)extradata;
|
||||
INT32 curz = extent->param[0].start;
|
||||
INT32 curu = extent->param[1].start;
|
||||
INT32 curv = extent->param[2].start;
|
||||
//INT32 curi = extent->param[3].start;
|
||||
INT32 curi = extent->param[3].start;
|
||||
INT32 dzdx = extent->param[0].dpdx;
|
||||
INT32 dudx = extent->param[1].dpdx;
|
||||
INT32 dvdx = extent->param[2].dpdx;
|
||||
//INT32 didx = extent->param[3].dpdx;
|
||||
INT32 didx = extent->param[3].dpdx;
|
||||
const void *texbase = extra->texbase;
|
||||
const void *palbase = extra->palbase;
|
||||
UINT16 transcolor = extra->transcolor;
|
||||
int texwidth = extra->texwidth;
|
||||
int x;
|
||||
UINT32 texwidth = extra->texwidth;
|
||||
|
||||
for (x = extent->startx; x < extent->stopx; x++)
|
||||
for (UINT32 x = extent->startx; x < extent->stopx; x++)
|
||||
{
|
||||
UINT16 *depthptr = WAVERAM_PTRDEPTH(zeus_renderbase, scanline, x);
|
||||
INT32 depth = (curz >> 16) + extra->zoffset;
|
||||
if (depth > 0x7fff) depth = 0x7fff;
|
||||
if (depth >= 0 && depth <= *depthptr)
|
||||
|
||||
if (depth > 0x7fff)
|
||||
depth = 0x7fff;
|
||||
|
||||
UINT32 i8 = curi >> 8;
|
||||
|
||||
bool depth_pass;
|
||||
|
||||
if (extra->depth_test_enable)
|
||||
depth_pass = depth >= 0 && depth <= *depthptr;
|
||||
else
|
||||
depth_pass = true;
|
||||
|
||||
if (depth_pass)
|
||||
{
|
||||
int u0 = (curu >> 8);
|
||||
int v0 = (curv >> 8) + extra->voffset;
|
||||
int u1 = (u0 + 1);
|
||||
int v1 = (v0 + 1);
|
||||
UINT8 texel0 = extra->get_texel(texbase, v0, u0, texwidth);
|
||||
UINT8 texel1 = extra->get_texel(texbase, v0, u1, texwidth);
|
||||
UINT8 texel2 = extra->get_texel(texbase, v1, u0, texwidth);
|
||||
UINT8 texel3 = extra->get_texel(texbase, v1, u1, texwidth);
|
||||
if (texel0 != transcolor)
|
||||
rgb_t src=0;
|
||||
|
||||
bool src_valid = true;
|
||||
|
||||
if ((extra->ctrl_word & 0x000c0000) == 0x000c0000)
|
||||
{
|
||||
rgb_t color0 = WAVERAM_READ16(palbase, texel0);
|
||||
rgb_t color1 = WAVERAM_READ16(palbase, texel1);
|
||||
rgb_t color2 = WAVERAM_READ16(palbase, texel2);
|
||||
rgb_t color3 = WAVERAM_READ16(palbase, texel3);
|
||||
color0 = ((color0 & 0x7fe0) << 6) | (color0 & 0x1f);
|
||||
color1 = ((color1 & 0x7fe0) << 6) | (color1 & 0x1f);
|
||||
color2 = ((color2 & 0x7fe0) << 6) | (color2 & 0x1f);
|
||||
color3 = ((color3 & 0x7fe0) << 6) | (color3 & 0x1f);
|
||||
rgb_t filtered = rgbaint_t::bilinear_filter(color0, color1, color2, color3, curu, curv);
|
||||
src.set_r(pal5bit(extra->solidcolor >> 10));
|
||||
src.set_g(pal5bit(extra->solidcolor >> 5));
|
||||
src.set_b(pal5bit(extra->solidcolor));
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 u0 = curu >> 8;
|
||||
UINT32 v0 = extra->voffset + (curv >> 8);
|
||||
UINT32 u1 = u0 + 1;
|
||||
UINT32 v1 = v0 + 1;
|
||||
|
||||
if (extra->blend_enable)
|
||||
UINT8 texels[4];
|
||||
|
||||
texels[0] = extra->get_texel(texbase, v0, u0, texwidth);
|
||||
texels[1] = extra->get_texel(texbase, v0, u1, texwidth);
|
||||
texels[2] = extra->get_texel(texbase, v1, u0, texwidth);
|
||||
texels[3] = extra->get_texel(texbase, v1, u1, texwidth);
|
||||
|
||||
if (texels[0] != transcolor)
|
||||
{
|
||||
UINT16 dst = WAVERAM_READPIX(zeus_renderbase, scanline, x);
|
||||
INT32 dst_r = (dst >> 10) & 0x1f;
|
||||
INT32 dst_g = (dst >> 5) & 0x1f;
|
||||
INT32 dst_b = dst & 0x1f;
|
||||
rgb_t color[4];
|
||||
|
||||
INT32 src_r = filtered.r();
|
||||
INT32 src_g = filtered.g() >> 3;
|
||||
INT32 src_b = filtered.b();
|
||||
for (UINT32 i = 0; i < 4; ++i)
|
||||
{
|
||||
UINT16 pix = WAVERAM_READ16(palbase, texels[i]);
|
||||
|
||||
if (extra->blend == BLEND_ADD)
|
||||
{
|
||||
dst_r += src_r;
|
||||
dst_g += src_g;
|
||||
dst_b += src_b;
|
||||
dst_r = ((dst_r > 0x1f) ? 0x1f : dst_r);
|
||||
dst_g = ((dst_g > 0x1f) ? 0x1f : dst_g);
|
||||
dst_b = ((dst_b > 0x1f) ? 0x1f : dst_b);
|
||||
color[i].set_r(pal5bit(pix >> 10));
|
||||
color[i].set_g(pal5bit(pix >> 5));
|
||||
color[i].set_b(pal5bit(pix));
|
||||
}
|
||||
else if (extra->blend == BLEND_SUB)
|
||||
{
|
||||
dst_r -= src_r;
|
||||
dst_g -= src_g;
|
||||
dst_b -= src_b;
|
||||
dst_r = ((dst_r < 0) ? 0 : dst_r);
|
||||
dst_g = ((dst_g < 0) ? 0 : dst_g);
|
||||
dst_b = ((dst_b < 0) ? 0 : dst_b);
|
||||
}
|
||||
WAVERAM_WRITEPIX(zeus_renderbase, scanline, x, (dst_r << 10) | (dst_g << 5) | dst_b);
|
||||
|
||||
src = rgbaint_t::bilinear_filter(color[0], color[1], color[2], color[3], curu & 0xff, curv & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVERAM_WRITEPIX(zeus_renderbase, scanline, x, ((filtered >> 6) & 0x7fe0) | (filtered & 0x1f));
|
||||
src_valid = false;
|
||||
}
|
||||
*depthptr = depth;
|
||||
}
|
||||
|
||||
if (src_valid)
|
||||
{
|
||||
UINT32 srcr = src.r();
|
||||
UINT32 srcg = src.g();
|
||||
UINT32 srcb = src.b();
|
||||
|
||||
UINT32 dstr = 0;
|
||||
UINT32 dstg = 0;
|
||||
UINT32 dstb = 0;
|
||||
|
||||
UINT32 outr = 0;
|
||||
UINT32 outg = 0;
|
||||
UINT32 outb = 0;
|
||||
|
||||
UINT32 srca = extra->alpha & 0xff;
|
||||
UINT32 dsta = (extra->alpha >> 8) & 0xff;
|
||||
|
||||
// Destination enable?
|
||||
if (extra->blend & 0x00800000)
|
||||
{
|
||||
UINT16 dst = WAVERAM_READPIX(zeus_renderbase, scanline, x);
|
||||
|
||||
dstr = (dst >> 10) & 0x1f;
|
||||
dstg = (dst >> 5) & 0x1f;
|
||||
dstb = dst & 0x1f;
|
||||
|
||||
dstr = (dstr << 3) | (dstr >> 2);
|
||||
dstg = (dstg << 3) | (dstg >> 2);
|
||||
dstb = (dstb << 3) | (dstb >> 2);
|
||||
}
|
||||
|
||||
switch (extra->blend)
|
||||
{
|
||||
case BLEND_OPAQUE1:
|
||||
{
|
||||
outr = srcr;
|
||||
outg = srcg;
|
||||
outb = srcb;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_OPAQUE2:
|
||||
{
|
||||
outr = (srcr * i8) >> 8;
|
||||
outg = (srcg * i8) >> 8;
|
||||
outb = (srcb * i8) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_OPAQUE3:
|
||||
{
|
||||
outr = (srcr * i8) >> 8;
|
||||
outg = (srcg * i8) >> 8;
|
||||
outb = (srcb * i8) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_OPAQUE4:
|
||||
{
|
||||
outr = srcr;
|
||||
outg = srcg;
|
||||
outb = srcb;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_OPAQUE5:
|
||||
{
|
||||
// TODO: Fog factor?
|
||||
outr = (srcr * srca) >> 8;
|
||||
outg = (srcg * srca) >> 8;
|
||||
outb = (srcb * srca) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_ADD1:
|
||||
{
|
||||
outr = ((srcr * srca) >> 8) + dstr;
|
||||
outg = ((srcg * srca) >> 8) + dstg;
|
||||
outb = ((srcb * srca) >> 8) + dstb;
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_ADD2:
|
||||
{
|
||||
outr = ((srcr * srca) >> 8) + ((dstr * (dsta << 1)) >> 8);
|
||||
outg = ((srcg * srca) >> 8) + ((dstg * (dsta << 1)) >> 8);
|
||||
outb = ((srcb * srca) >> 8) + ((dstb * (dsta << 1)) >> 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLEND_MUL1:
|
||||
{
|
||||
outr = (((srcr * (srca << 1)) >> 8) * dstr) >> 8;
|
||||
outg = (((srcg * (srca << 1)) >> 8) * dstg) >> 8;
|
||||
outb = (((srcb * (srca << 1)) >> 8) * dstb) >> 8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
outr = srcr;
|
||||
outg = srcg;
|
||||
outb = srcb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
outr = outr > 0xff ? 0xff : outr;
|
||||
outg = outg > 0xff ? 0xff : outg;
|
||||
outb = outb > 0xff ? 0xff : outb;
|
||||
|
||||
outr >>= 3;
|
||||
outg >>= 3;
|
||||
outb >>= 3;
|
||||
|
||||
WAVERAM_WRITEPIX(zeus_renderbase, scanline, x, (outr << 10) | (outg << 5) | outb);
|
||||
|
||||
if (extra->depth_write_enable)
|
||||
*depthptr = depth;
|
||||
}
|
||||
}
|
||||
|
||||
curz += dzdx;
|
||||
curu += dudx;
|
||||
curv += dvdx;
|
||||
//curi += didx;
|
||||
curi += didx;
|
||||
}
|
||||
}
|
||||
|
||||
static void render_poly_shade(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
|
||||
{
|
||||
const mz_poly_extra_data *extra = (const mz_poly_extra_data *)extradata;
|
||||
int x;
|
||||
|
||||
for (x = extent->startx; x < extent->stopx; x++)
|
||||
{
|
||||
if (x >= 0 && x < 400)
|
||||
{
|
||||
if (extra->alpha <= 0x80)
|
||||
{
|
||||
UINT16 *ptr = WAVERAM_PTRPIX(zeus_renderbase, scanline, x);
|
||||
UINT16 pix = *ptr;
|
||||
|
||||
*ptr = ((((pix & 0x7c00) * extra->alpha) >> 7) & 0x7c00) |
|
||||
((((pix & 0x03e0) * extra->alpha) >> 7) & 0x03e0) |
|
||||
((((pix & 0x001f) * extra->alpha) >> 7) & 0x001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
waveram_plot(scanline, x, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void render_poly_solid(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
|
||||
{
|
||||
const mz_poly_extra_data *extra = (const mz_poly_extra_data *)extradata;
|
||||
UINT16 color = extra->solidcolor;
|
||||
INT32 curz = (INT32)(extent->param[0].start);
|
||||
INT32 curv = extent->param[2].start;
|
||||
INT32 dzdx = (INT32)(extent->param[0].dpdx);
|
||||
INT32 dvdx = extent->param[2].dpdx;
|
||||
int x;
|
||||
|
||||
for (x = extent->startx; x < extent->stopx; x++)
|
||||
{
|
||||
INT32 depth = (curz >> 16) + extra->zoffset;
|
||||
if (depth > 0x7fff) depth = 0x7fff;
|
||||
if (depth >= 0)
|
||||
{
|
||||
// UINT32 finalcolor = (((color & 0x7c00) * curv) & 0x7c000000) | (((color & 0x03e0) * curv) & 0x03e00000) | (((color & 0x001f) * curv) & 0x001f0000);
|
||||
// waveram_plot_check_depth(scanline, x, finalcolor >> 16, depth);
|
||||
waveram_plot_check_depth(scanline, x, color, depth);
|
||||
}
|
||||
curz += dzdx;
|
||||
curv += dvdx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void render_poly_solid_fixedz(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
|
||||
|
Loading…
Reference in New Issue
Block a user