summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author snickerbockers <chimerasaurusrex@gmail.com>2018-07-06 06:19:19 -0700
committer snickerbockers <chimerasaurusrex@gmail.com>2018-07-10 09:53:52 -0700
commitec325ef14f42a5373fa8ddb9995e6876f69afd8d (patch)
tree45017d43388b724bda32645ea5f8b2f5bc0db8c1
parentbda05083c2a450882211a639fbbfaf24413b6e5c (diff)
PowerVR2: implement color
PowerVR2 represents color using two components: a base color and an optional offset color. The base color is combined with the incoming texture sample (if any) according to the fixed-function specified by the tsinstruction in the per-polygon parameters, and then the offset is added to this color (with the exception of alpha; the offset color has an alpha component but it does not appear to ever be used). The base color and offset color can be specified on a per-vertex basis (as either a group of four 8-bit integers or a group of four single-precision floating points) or they can be specified on a per-polygon basis (in floating-point only) and then scaled based on per-vertex scalar values (also floating point).
-rw-r--r--src/mame/video/powervr2.cpp431
-rw-r--r--src/mame/video/powervr2.h52
2 files changed, 409 insertions, 74 deletions
diff --git a/src/mame/video/powervr2.cpp b/src/mame/video/powervr2.cpp
index aeafe861b6b..e0ae10e1e30 100644
--- a/src/mame/video/powervr2.cpp
+++ b/src/mame/video/powervr2.cpp
@@ -187,6 +187,54 @@ inline uint32_t powervr2_device::bls(uint32_t c1, uint32_t c2)
return cr1|(cr2 << 8);
}
+/*
+ * Add two colors with saturation, not including the alpha channel
+ * The only difference between this function and bls is that bls does not
+ * ignore alpha. The alpha will be cleared to zero by this instruction
+ */
+inline uint32_t powervr2_device::bls24(uint32_t c1, uint32_t c2)
+{
+ uint32_t cr1, cr2;
+ cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff);
+ if(cr1 & 0x0000ff00)
+ cr1 = (cr1 & 0xffff00ff) | 0x000000ff;
+ if(cr1 & 0xff000000)
+ cr1 = (cr1 & 0x00ffffff) | 0x00ff0000;
+
+ cr2 = ((c1 >> 8) & 0x000000ff) + ((c2 >> 8) & 0x000000ff);
+ if(cr2 & 0x0000ff00)
+ cr2 = (cr2 & 0xffff00ff) | 0x000000ff;
+ return cr1|(cr2 << 8);
+}
+
+inline uint32_t powervr2_device::float_argb_to_packed_argb(float argb[4]) {
+ int argb_int[4] = {
+ (int)(argb[0] * 256.0f),
+ (int)(argb[1] * 256.0f),
+ (int)(argb[2] * 256.0f),
+ (int)(argb[3] * 256.0f)
+ };
+
+ // clamp to [0, 255]
+ int idx;
+ for (idx = 0; idx < 4; idx++) {
+ if (argb_int[idx] < 0)
+ argb_int[idx] = 0;
+ else if (argb_int[idx] > 255)
+ argb_int[idx] = 255;
+ }
+
+ return (argb_int[0] << 24) | (argb_int[1] << 16) |
+ (argb_int[2] << 8) | argb_int[3];
+}
+
+inline void powervr2_device::packed_argb_to_float_argb(float dst[4], uint32_t in) {
+ dst[0] = (in >> 24) / 256.0f;
+ dst[1] = ((in >> 16) & 0xff) / 256.0f;
+ dst[2] = ((in >> 8) & 0xff) / 256.0f;
+ dst[3] = (in & 0xff) / 256.0f;
+}
+
// All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode
uint32_t powervr2_device::bl00(uint32_t s, uint32_t d) { return 0; }
uint32_t powervr2_device::bl01(uint32_t s, uint32_t d) { return d; }
@@ -456,16 +504,6 @@ uint32_t powervr2_device::tex_r_4444_vq(texinfo *t, float x, float y)
return cv_4444(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
}
-uint32_t powervr2_device::tex_r_nt_palint(texinfo *t, float x, float y)
-{
- return t->nontextured_pal_int;
-}
-
-uint32_t powervr2_device::tex_r_nt_palfloat(texinfo *t, float x, float y)
-{
- return (t->nontextured_fpal_a << 24) | (t->nontextured_fpal_r << 16) | (t->nontextured_fpal_g << 8) | (t->nontextured_fpal_b);
-}
-
uint32_t powervr2_device::tex_r_p4_1555_tw(texinfo *t, float x, float y)
{
int xt = t->u_func(x, t->sizex);
@@ -686,24 +724,13 @@ void powervr2_device::tex_get_info(texinfo *t)
t->vqbase = t->address;
t->blend = use_alpha ? blend_functions[t->blend_mode] : bl10;
+ t->coltype = coltype;
+ t->tsinstruction = tsinstruction;
+
// fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pal_ram_ctrl, t->mipmapped);
if(!t->textured)
{
- t->coltype = coltype;
- switch(t->coltype) {
- case 0: // packed color
- t->nontextured_pal_int = nontextured_pal_int;
- t->r = &powervr2_device::tex_r_nt_palint;
- break;
- case 1: // floating color
- /* TODO: might be converted even earlier I believe */
- t->nontextured_fpal_a = (uint8_t)(nontextured_fpal_a * 255.0f);
- t->nontextured_fpal_r = (uint8_t)(nontextured_fpal_r * 255.0f);
- t->nontextured_fpal_g = (uint8_t)(nontextured_fpal_g * 255.0f);
- t->nontextured_fpal_b = (uint8_t)(nontextured_fpal_b * 255.0f);
- t->r = &powervr2_device::tex_r_nt_palfloat;
- break;
- }
+ t->r = NULL;
}
else
{
@@ -1762,7 +1789,7 @@ void powervr2_device::process_ta_fifo()
volume=(objcontrol >> 6) & 1;
coltype=(objcontrol >> 4) & 3;
texture=(objcontrol >> 3) & 1;
- offfset=(objcontrol >> 2) & 1;
+ offset_color_enable=(objcontrol >> 2) & 1;
gouraud=(objcontrol >> 1) & 1;
uv16bit=(objcontrol >> 0) & 1;
}
@@ -1793,9 +1820,47 @@ void powervr2_device::process_ta_fifo()
return;
}
}
+ bool have_16_byte_header = tafifo_mask != 7;
tafifo_mask = 7;
// now we heve all the needed words
+
+ /*
+ * load per-polygon colors if color type is 2 or 3 or parameter type is
+ * 5 (quad). For color types 0 and 1, color is determined entirely on a
+ * per-vertex basis.
+ */
+ if (paratype == 4)
+ {
+ switch (coltype) {
+ case 2:
+ if (offset_color_enable) {
+ memcpy(poly_base_color, tafifo_buff + 8, 4 * sizeof(float));
+ memcpy(poly_offs_color, tafifo_buff + 12, 4 * sizeof(float));
+ } else {
+ memcpy(poly_base_color, tafifo_buff + 4, 4 * sizeof(float));
+ memset(poly_offs_color, 0, sizeof(poly_offs_color));
+ }
+ memcpy(poly_last_mode_2_base_color, poly_base_color, sizeof(poly_last_mode_2_base_color));
+ break;
+ case 3:
+ memcpy(poly_base_color, poly_last_mode_2_base_color, sizeof(poly_base_color));
+ memset(poly_offs_color, 0, sizeof(poly_offs_color));
+ break;
+ default:
+ memset(poly_base_color, 0, sizeof(poly_base_color));
+ memset(poly_offs_color, 0, sizeof(poly_offs_color));
+ break;
+ }
+ } else if (paratype == 5) {
+ packed_argb_to_float_argb(poly_base_color, tafifo_buff[4]);
+ if (offset_color_enable) {
+ packed_argb_to_float_argb(poly_offs_color, tafifo_buff[5]);
+ } else {
+ memset(poly_offs_color, 0, sizeof(poly_offs_color));
+ }
+ }
+
// here we should generate the data for the various tiles
// for now, just interpret their meaning
if (paratype == 0)
@@ -1967,6 +2032,14 @@ void powervr2_device::process_ta_fifo()
tv[2].u = tv[0].u+tv[3].u-tv[1].u;
tv[2].v = tv[0].v+tv[3].v-tv[1].v;
+ int idx;
+ for (idx = 0; idx < 4; idx++) {
+ memcpy(tv[idx].b, poly_base_color,
+ sizeof(tv[idx].b));
+ memcpy(tv[idx].o, poly_offs_color,
+ sizeof(tv[idx].o));
+ }
+
ts = &rd->strips[rd->strips_size++];
tex_get_info(&ts->ti);
ts->svert = rd->verts_size;
@@ -1985,6 +2058,56 @@ void powervr2_device::process_ta_fifo()
#endif
if (rd->verts_size <= 65530)
{
+ float vert_offset_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float vert_base_color[4];
+
+ float base_intensity, offs_intensity;
+
+ switch (coltype) {
+ case 0:
+ // packed color
+ packed_argb_to_float_argb(vert_base_color, tafifo_buff[6]);
+ break;
+ case 1:
+ // floating-point color
+ if (have_16_byte_header) {
+ memcpy(vert_base_color, tafifo_buff + 8,
+ sizeof(vert_base_color));
+ memcpy(vert_offset_color, tafifo_buff + 12,
+ sizeof(vert_offset_color));
+ } else {
+ memcpy(vert_base_color, tafifo_buff + 4,
+ sizeof(vert_base_color));
+ }
+ break;
+ case 2:
+ case 3:
+ /*
+ * base/offset color were previously
+ * specified on a per-polygon basis.
+ * To get the per-vertex base and
+ * offset colors, they are scaled by
+ * per-vertex scalar values.
+ */
+ memcpy(&base_intensity, tafifo_buff + 6, sizeof(base_intensity));
+ memcpy(&offs_intensity, tafifo_buff + 7, sizeof(offs_intensity));
+ vert_base_color[0] = poly_base_color[0] * base_intensity;
+ vert_base_color[1] = poly_base_color[1] * base_intensity;
+ vert_base_color[2] = poly_base_color[2] * base_intensity;
+ vert_base_color[3] = poly_base_color[3] * base_intensity;
+ if (offset_color_enable) {
+ vert_offset_color[0] = poly_offs_color[0] * offs_intensity;
+ vert_offset_color[1] = poly_offs_color[1] * offs_intensity;
+ vert_offset_color[2] = poly_offs_color[2] * offs_intensity;
+ vert_offset_color[3] = poly_offs_color[3] * offs_intensity;
+ }
+ break;
+ default:
+ // This will never actually happen, coltype is 2-bits.
+ logerror("line %d of %s - coltype is %d\n", coltype);
+ memset(vert_base_color, 0, sizeof(vert_base_color));
+ }
+
/* add a vertex to our list */
/* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */
/* -- this is also wildly inaccurate! */
@@ -1995,18 +2118,8 @@ void powervr2_device::process_ta_fifo()
tv->w=u2f(tafifo_buff[3]);
tv->u=u2f(tafifo_buff[4]);
tv->v=u2f(tafifo_buff[5]);
- if (texture == 0)
- {
- if(coltype == 0)
- nontextured_pal_int=tafifo_buff[6];
- else if(coltype == 1)
- {
- nontextured_fpal_a=u2f(tafifo_buff[4]);
- nontextured_fpal_r=u2f(tafifo_buff[5]);
- nontextured_fpal_g=u2f(tafifo_buff[6]);
- nontextured_fpal_b=u2f(tafifo_buff[7]);
- }
- }
+ memcpy(tv->b, vert_base_color, sizeof(tv->b));
+ memcpy(tv->o, vert_offset_color, sizeof(tv->o));
if((!rd->strips_size) ||
rd->strips[rd->strips_size-1].evert != -1)
@@ -2188,8 +2301,9 @@ void powervr2_device::computedilated()
dilatechose[(b << 3) + a]=3+(a < b ? a : b);
}
-void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr)
+void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr, float const bl_in[4], float const br_in[4], float const offl_in[4], float const offr_in[4])
{
+ int idx;
int xxl, xxr;
float dx, ddx, dudx, dvdx, dwdx;
uint32_t *tdata;
@@ -2198,6 +2312,10 @@ void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, flo
// untextured cases aren't handled
// if (!ti->textured) return;
+ float bl[4], offl[4];
+ memcpy(bl, bl_in, sizeof(bl));
+ memcpy(offl, offl_in, sizeof(offl));
+
if(xr < 0 || xl >= 640)
return;
@@ -2212,6 +2330,20 @@ void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, flo
dvdx = (vr-vl)/dx;
dwdx = (wr-wl)/dx;
+ float dbdx[4] = {
+ (br_in[0] - bl[0]) / dx,
+ (br_in[1] - bl[1]) / dx,
+ (br_in[2] - bl[2]) / dx,
+ (br_in[3] - bl[3]) / dx
+ };
+
+ float dodx[4] = {
+ (offr_in[0] - offl[0]) / dx,
+ (offr_in[1] - offl[1]) / dx,
+ (offr_in[2] - offl[2]) / dx,
+ (offr_in[3] - offl[3]) / dx
+ };
+
if(xxl < 0)
xxl = 0;
if(xxr > 640)
@@ -2222,29 +2354,69 @@ void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, flo
ul += ddx*dudx;
vl += ddx*dvdx;
wl += ddx*dwdx;
-
+ for (idx = 0; idx < 4; idx++) {
+ bl[idx] += ddx * dbdx[idx];
+ offl[idx] += ddx * dodx[idx];
+ }
tdata = &bitmap.pix32(y, xxl);
wbufline = &wbuffer[y][xxl];
while(xxl < xxr) {
if((wl >= *wbufline)) {
- uint32_t c;
float u = ul/wl;
float v = vl/wl;
- c = (this->*(ti->r))(ti, u, v);
+ /*
+ * TODO: Not sure if blending should be done in
+ * floating point or fixed point, or if it even matters.
+ */
+ uint32_t c;
+ uint32_t offset_color = float_argb_to_packed_argb(offl);
+ uint32_t base_color = float_argb_to_packed_argb(bl);
- // debug dip to turn on/off bilinear filtering, it's slooooow
- if (debug_dip_status&0x1)
- {
- if(ti->filter_mode >= TEX_FILTER_BILINEAR)
+ if (ti->textured) {
+ c = (this->*(ti->r))(ti, u, v);
+ // debug dip to turn on/off bilinear filtering, it's slooooow
+ if (debug_dip_status&0x1)
{
- uint32_t c1 = (this->*(ti->r))(ti, u+1.0f, v);
- uint32_t c2 = (this->*(ti->r))(ti, u+1.0f, v+1.0f);
- uint32_t c3 = (this->*(ti->r))(ti, u, v+1.0f);
- c = bilinear_filter(c, c1, c2, c3, u, v);
+ if(ti->filter_mode >= TEX_FILTER_BILINEAR)
+ {
+ uint32_t c1 = (this->*(ti->r))(ti, u+1.0f, v);
+ uint32_t c2 = (this->*(ti->r))(ti, u+1.0f, v+1.0f);
+ uint32_t c3 = (this->*(ti->r))(ti, u, v+1.0f);
+ c = bilinear_filter(c, c1, c2, c3, u, v);
+ }
+ }
+
+ uint32_t tmp;
+ switch (ti->tsinstruction) {
+ case 0:
+ // decal
+ c = bls24(c, offset_color) | (c & 0xff000000);
+ break;
+ case 1:
+ // modulate
+ tmp = blc(c, base_color);
+ tmp = bls24(tmp, offset_color);
+ tmp |= c & 0xff000000;
+ c = tmp;
+ break;
+ case 2:
+ // decal with alpha
+ tmp = bls24(bla(c, c), blia(base_color, c));
+ c = bls24(tmp, offset_color) | (base_color & 0xff000000);
+ break;
+ case 3:
+ // modulate with alpha
+ tmp = blc(c, base_color);
+ tmp = bls24(tmp, offset_color);
+ tmp |= (((c >> 24) * (base_color >> 24)) >> 8) << 24;
+ c = tmp;
+ break;
}
+ } else {
+ c = bls24(base_color, offset_color) | (base_color & 0xff000000);
}
if(c & 0xff000000) {
@@ -2258,6 +2430,10 @@ void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, flo
ul += dudx;
vl += dvdx;
wl += dwdx;
+ for (idx = 0; idx < 4; idx++) {
+ bl[idx] += dbdx[idx];
+ offl[idx] += dodx[idx];
+ }
xxl ++;
}
}
@@ -2268,11 +2444,16 @@ void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
float ul, float ur,
float vl, float vr,
float wl, float wr,
+ float const bl_in[4], float const br_in[4],
+ float const offl_in[4], float const offr_in[4],
float dxldy, float dxrdy,
float duldy, float durdy,
float dvldy, float dvrdy,
- float dwldy, float dwrdy)
+ float dwldy, float dwrdy,
+ float const dbldy[4], float const dbrdy[4],
+ float const doldy[4], float const dordy[4])
{
+ int idx;
float dy;
int yy0, yy1;
@@ -2281,6 +2462,12 @@ void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
if(y1 > 480)
y1 = 480;
+ float bl[4], br[4], offl[4], offr[4];
+ memcpy(bl, bl_in, sizeof(bl));
+ memcpy(br, br_in, sizeof(br));
+ memcpy(offl, offl_in, sizeof(offl));
+ memcpy(offr, offr_in, sizeof(offr));
+
if(y0 < 0) {
xl += -dxldy*y0;
xr += -dxrdy*y0;
@@ -2290,6 +2477,13 @@ void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
vr += -dvrdy*y0;
wl += -dwldy*y0;
wr += -dwrdy*y0;
+
+ for (idx = 0; idx < 4; idx++) {
+ bl[idx] += -dbldy[idx] * y0;
+ br[idx] += -dbrdy[idx] * y0;
+ offl[idx] += -doldy[idx] * y0;
+ offr[idx] += -dordy[idx] * y0;
+ }
y0 = 0;
}
@@ -2314,9 +2508,15 @@ void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
vr += dy*dvrdy;
wl += dy*dwldy;
wr += dy*dwrdy;
+ for (idx = 0; idx < 4; idx++) {
+ bl[idx] += dy * dbldy[idx];
+ br[idx] += dy * dbrdy[idx];
+ offl[idx] += dy * doldy[idx];
+ offr[idx] += dy * dordy[idx];
+ }
while(yy0 < yy1) {
- render_hline(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr);
+ render_hline(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr, bl, br, offl, offr);
xl += dxldy;
xr += dxrdy;
@@ -2326,6 +2526,13 @@ void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
vr += dvrdy;
wl += dwldy;
wr += dwrdy;
+ for (idx = 0; idx < 4; idx++) {
+ bl[idx] += dbldy[idx];
+ br[idx] += dbrdy[idx];
+ offl[idx] += doldy[idx];
+ offr[idx] += dordy[idx];
+ }
+
yy0 ++;
}
}
@@ -2370,10 +2577,94 @@ void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const
if(v0->y >= 480 || v2->y < 0)
return;
+ float db01[4] = {
+ v1->b[0] - v0->b[0],
+ v1->b[1] - v0->b[1],
+ v1->b[2] - v0->b[2],
+ v1->b[3] - v0->b[3]
+ };
+
+ float db02[4] = {
+ v2->b[0] - v0->b[0],
+ v2->b[1] - v0->b[1],
+ v2->b[2] - v0->b[2],
+ v2->b[3] - v0->b[3]
+ };
+
+ float db12[4] = {
+ v2->b[0] - v1->b[0],
+ v2->b[1] - v1->b[1],
+ v2->b[2] - v1->b[2],
+ v2->b[3] - v1->b[3]
+ };
+
+ float do01[4] = {
+ v1->o[0] - v0->o[0],
+ v1->o[1] - v0->o[1],
+ v1->o[2] - v0->o[2],
+ v1->o[3] - v0->o[3]
+ };
+
+ float do02[4] = {
+ v2->o[0] - v0->o[0],
+ v2->o[1] - v0->o[1],
+ v2->o[2] - v0->o[2],
+ v2->o[3] - v0->o[3]
+ };
+
+ float do12[4] = {
+ v2->o[0] - v1->o[0],
+ v2->o[1] - v1->o[1],
+ v2->o[2] - v1->o[2],
+ v2->o[3] - v1->o[3]
+ };
+
dy01 = v1->y - v0->y;
dy02 = v2->y - v0->y;
dy12 = v2->y - v1->y;
+ float db01dy[4] = {
+ dy01 ? db01[0]/dy01 : 0,
+ dy01 ? db01[1]/dy01 : 0,
+ dy01 ? db01[2]/dy01 : 0,
+ dy01 ? db01[3]/dy01 : 0
+ };
+
+ float db02dy[4] = {
+ dy01 ? db02[0]/dy02 : 0,
+ dy01 ? db02[1]/dy02 : 0,
+ dy01 ? db02[2]/dy02 : 0,
+ dy01 ? db02[3]/dy02 : 0
+ };
+
+ float db12dy[4] = {
+ dy01 ? db12[0]/dy12 : 0,
+ dy01 ? db12[1]/dy12 : 0,
+ dy01 ? db12[2]/dy12 : 0,
+ dy01 ? db12[3]/dy12 : 0
+ };
+
+ float do01dy[4] = {
+ dy01 ? do01[0]/dy01 : 0,
+ dy01 ? do01[1]/dy01 : 0,
+ dy01 ? do01[2]/dy01 : 0,
+ dy01 ? do01[3]/dy01 : 0
+ };
+
+ float do02dy[4] = {
+ dy01 ? do02[0]/dy02 : 0,
+ dy01 ? do02[1]/dy02 : 0,
+ dy01 ? do02[2]/dy02 : 0,
+ dy01 ? do02[3]/dy02 : 0
+ };
+
+ float do12dy[4] = {
+ dy01 ? do12[0]/dy12 : 0,
+ dy01 ? do12[1]/dy12 : 0,
+ dy01 ? do12[2]/dy12 : 0,
+ dy01 ? do12[3]/dy12 : 0
+ };
+
dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0;
dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0;
dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0;
@@ -2395,31 +2686,43 @@ void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const
return;
if(v1->x > v0->x)
- render_span(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy);
+ render_span(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, v0->b, v1->b, v0->o, v1->o, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy);
else
- render_span(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy);
+ render_span(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, v1->b, v0->b, v1->o, v0->o, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy);
} else if(!dy12) {
if(v2->x > v1->x)
- render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy);
+ render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy);
else
- render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy);
+ render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy);
} else {
+ float idk_b[4] = {
+ v0->b[0] + db02dy[0] * dy01,
+ v0->b[1] + db02dy[1] * dy01,
+ v0->b[2] + db02dy[2] * dy01,
+ v0->b[3] + db02dy[3] * dy01
+ };
+ float idk_o[4] = {
+ v0->o[0] + do02dy[0] * dy01,
+ v0->o[1] + do02dy[1] * dy01,
+ v0->o[2] + do02dy[2] * dy01,
+ v0->o[3] + do02dy[3] * dy01
+ };
if(dx01dy < dx02dy) {
render_span(bitmap, ti, v0->y, v1->y,
- v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w,
- dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy);
+ v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o,
+ dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy);
render_span(bitmap, ti, v1->y, v2->y,
- v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01,
- dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy);
+ v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, v1->b, idk_b, v1->o, idk_o,
+ dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy);
} else {
render_span(bitmap, ti, v0->y, v1->y,
- v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w,
- dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy);
+ v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o,
+ dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy);
render_span(bitmap, ti, v1->y, v2->y,
- v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w,
- dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy);
+ v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, idk_b, v1->b, idk_o, v1->o,
+ dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy);
}
}
}
diff --git a/src/mame/video/powervr2.h b/src/mame/video/powervr2.h
index 553bcc04281..19908a736c6 100644
--- a/src/mame/video/powervr2.h
+++ b/src/mame/video/powervr2.h
@@ -59,10 +59,35 @@ public:
// our implementation is not currently tile based, and thus the accumulation buffer is screen sized
std::unique_ptr<bitmap_rgb32> fake_accumulationbuffer_bitmap;
+ /*
+ * Per-polygon base and offset colors. These are scaled by per-vertex
+ * weights.
+ *
+ * These are only used if the colortype in the polygon header is 2
+ * or 3. If it is 0 or 1, then each vertex's base and offset colors are
+ * specified completely independently of one another in the per-vertex
+ * parameters.
+ *
+ * The base color is combined with the texture sample (if any) according
+ * to one of four fixed functions. The offset color is then added to
+ * the combined texture sample and base color with the exception of
+ * alpha.
+ *
+ * poly_offs_color is not always used. Not specifying a poly_offs_color
+ * is equivalent to using a poly_offs_color of 0.
+ *
+ * poly_last_mode_2_base_color is used to hold the last base color
+ * specified using color type 2. Color type 3 will always use the last
+ * base color specified using color type 2.
+ */
+ float poly_base_color[4], poly_offs_color[4],
+ poly_last_mode_2_base_color[4];
+
struct texinfo {
uint32_t address, vqbase;
- uint32_t nontextured_pal_int;
- uint8_t nontextured_fpal_a,nontextured_fpal_r,nontextured_fpal_g,nontextured_fpal_b;
+
+ uint32_t tsinstruction;
+
int textured, sizex, sizey, stride, sizes, pf, palette, mode, mipmapped, blend_mode, filter_mode;
int coltype;
@@ -76,6 +101,9 @@ public:
typedef struct
{
float x, y, w, u, v;
+
+ // base and offset colors
+ float b[4], o[4];
} vert;
struct strip
@@ -113,13 +141,11 @@ public:
int grabsellast;
uint32_t paracontrol,paratype,endofstrip,listtype,global_paratype,parameterconfig;
uint32_t groupcontrol,groupen,striplen,userclip;
- uint32_t objcontrol,shadow,volume,coltype,texture,offfset,gouraud,uv16bit;
+ uint32_t objcontrol,shadow,volume,coltype,texture,offset_color_enable,gouraud,uv16bit;
uint32_t texturesizes,textureaddress,scanorder,pixelformat;
uint32_t blend_mode, srcselect,dstselect,fogcontrol,colorclamp, use_alpha;
uint32_t ignoretexalpha,flipuv,clampuv,filtermode,sstexture,mmdadjust,tsinstruction;
uint32_t depthcomparemode,cullingmode,zwritedisable,cachebypass,dcalcctrl,volumeinstruction,mipmapped,vqcompressed,strideselect,paletteselector;
- uint32_t nontextured_pal_int;
- float nontextured_fpal_a,nontextured_fpal_r,nontextured_fpal_g,nontextured_fpal_b;
uint64_t *dc_texture_ram;
uint64_t *dc_framebuffer_ram;
@@ -321,6 +347,9 @@ private:
static int uv_flip(float uv, int size);
static int uv_clamp(float uv, int size);
+ static inline uint32_t float_argb_to_packed_argb(float argb[4]);
+ static inline void packed_argb_to_float_argb(float dst[4], uint32_t in);
+
static inline int32_t clamp(int32_t in, int32_t min, int32_t max);
static inline uint32_t bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v);
static inline uint32_t bla(uint32_t c, uint32_t a);
@@ -328,6 +357,8 @@ private:
static inline uint32_t blc(uint32_t c1, uint32_t c2);
static inline uint32_t blic(uint32_t c1, uint32_t c2);
static inline uint32_t bls(uint32_t c1, uint32_t c2);
+ static inline uint32_t bls24(uint32_t c1, uint32_t c2);
+
static uint32_t bl00(uint32_t s, uint32_t d);
static uint32_t bl01(uint32_t s, uint32_t d);
static uint32_t bl02(uint32_t s, uint32_t d);
@@ -428,23 +459,24 @@ private:
uint32_t tex_r_p8_8888_tw(texinfo *t, float x, float y);
uint32_t tex_r_p8_8888_vq(texinfo *t, float x, float y);
- uint32_t tex_r_nt_palint(texinfo *t, float x, float y);
- uint32_t tex_r_nt_palfloat(texinfo *t, float x, float y);
-
uint32_t tex_r_default(texinfo *t, float x, float y);
void tex_get_info(texinfo *t);
- void render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr);
+ void render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr, float const bl[4], float const br[4], float const offl[4], float const offr[4]);
void render_span(bitmap_rgb32 &bitmap, texinfo *ti,
float y0, float y1,
float xl, float xr,
float ul, float ur,
float vl, float vr,
float wl, float wr,
+ float const bl[4], float const br[4],
+ float const offl[4], float const offr[4],
float dxldy, float dxrdy,
float duldy, float durdy,
float dvldy, float dvrdy,
- float dwldy, float dwrdy);
+ float dwldy, float dwrdy,
+ float const dbldy[4], float const dbrdy[4],
+ float const doldy[4], float const dordy[4]);
void sort_vertices(const vert *v, int *i0, int *i1, int *i2);
void render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2);
void render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v);