summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/k001005.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/k001005.cpp')
-rw-r--r--src/mame/video/k001005.cpp1718
1 files changed, 471 insertions, 1247 deletions
diff --git a/src/mame/video/k001005.cpp b/src/mame/video/k001005.cpp
index d6728ec7281..bbefdb30af0 100644
--- a/src/mame/video/k001005.cpp
+++ b/src/mame/video/k001005.cpp
@@ -15,9 +15,8 @@
/*
TODO:
- - Fog equation and parameters are probably not accurate.
- Winding Heat (and maybe others) have slight Z-fighting problems.
- - 3D in Solar Assault title isn't properly turned off (the SHARC keeps rendering 3D).
+ - Player car shadow not visible in Winding Heat. Hidden by road, needs polygon priority or something similar?
*/
@@ -74,12 +73,22 @@ k001005_renderer::k001005_renderer(device_t &parent, screen_device &screen, devi
parent.save_item(NAME(m_fog_g));
parent.save_item(NAME(m_fog_b));
parent.save_item(NAME(m_far_z));
-
+ parent.save_item(NAME(m_fog_start_z));
+ parent.save_item(NAME(m_fog_end_z));
+ parent.save_item(NAME(m_reg_fog_start));
+ parent.save_item(NAME(m_viewport_min_x));
+ parent.save_item(NAME(m_viewport_max_x));
+ parent.save_item(NAME(m_viewport_min_y));
+ parent.save_item(NAME(m_viewport_max_y));
+ parent.save_item(NAME(m_viewport_center_x));
+ parent.save_item(NAME(m_viewport_center_y));
}
void k001005_renderer::reset()
{
m_3dfifo_ptr = 0;
+
+ m_vertexb_ptr = 0;
}
void k001005_renderer::push_data(uint32_t data)
@@ -108,1352 +117,558 @@ bool k001005_renderer::fifo_filled()
return m_3dfifo_ptr > 0;
}
-void k001005_renderer::set_param(k001005_param param, uint32_t value)
-{
- switch (param)
- {
- case K001005_LIGHT_R: m_light_r = value; break;
- case K001005_LIGHT_G: m_light_g = value; break;
- case K001005_LIGHT_B: m_light_b = value; break;
- case K001005_AMBIENT_R: m_ambient_r = value; break;
- case K001005_AMBIENT_G: m_ambient_g = value; break;
- case K001005_AMBIENT_B: m_ambient_b = value; break;
- case K001005_FOG_R: m_fog_r = value; break;
- case K001005_FOG_G: m_fog_g = value; break;
- case K001005_FOG_B: m_fog_b = value; break;
- case K001005_FAR_Z:
- {
- uint32_t fz = value << 11;
- m_far_z = *(float*)&fz;
- if (m_far_z == 0.0f) // just in case...
- m_far_z = 1.0f;
- break;
- }
- }
-}
-void k001005_renderer::render_polygons()
+template<bool UseTexture, bool UseVertexColor>
+void k001005_renderer::draw_scanline_generic(int32_t scanline, const extent_t& extent, const k001005_polydata& extradata, int threadid)
{
- vertex_t v[4];
- int poly_type;
- int brightness;
+ float u, v, w, du, dv, dw;
+ float r, g, b, a, dr, dg, db, da;
- vertex_t *vertex1;
- vertex_t *vertex2;
- vertex_t *vertex3;
- vertex_t *vertex4;
-
- uint32_t *fifo = m_3dfifo.get();
+ k001006_device* k001006 = downcast<k001006_device*>(m_k001006);
- int index = 0;
+ uint32_t* const fb = &m_fb[m_fb_page]->pix(scanline);
+ float* const zb = (float*)&m_zb->pix(scanline);
- float fog_density = 1.5f;
+ float z = extent.param[POLY_Z].start;
+ float dz = extent.param[POLY_Z].dpdx;
+ float diff = extent.param[POLY_DIFF].start;
+ float ddiff = extent.param[POLY_DIFF].dpdx;
+ float fog = extent.param[POLY_FOG].start;
+ float dfog = extent.param[POLY_FOG].dpdx;
- render_delegate rd_scan_2d = render_delegate(&k001005_renderer::draw_scanline_2d, this);
- render_delegate rd_scan_tex2d = render_delegate(&k001005_renderer::draw_scanline_2d_tex, this);
- render_delegate rd_scan = render_delegate(&k001005_renderer::draw_scanline, this);
- render_delegate rd_scan_tex = render_delegate(&k001005_renderer::draw_scanline_tex, this);
- render_delegate rd_scan_gour_blend = render_delegate(&k001005_renderer::draw_scanline_gouraud_blend, this);
- render_delegate rd_scan_tex_gouraud = render_delegate(&k001005_renderer::draw_scanline_tex_gouraud, this);
+ if (UseTexture)
+ {
+ u = extent.param[POLY_U].start;
+ v = extent.param[POLY_V].start;
+ w = extent.param[POLY_W].start;
+ du = extent.param[POLY_U].dpdx;
+ dv = extent.param[POLY_V].dpdx;
+ dw = extent.param[POLY_W].dpdx;
+ }
- do
+ if (UseVertexColor)
{
- uint32_t cmd = fifo[index++];
+ r = extent.param[POLY_R].start;
+ dr = extent.param[POLY_R].dpdx;
+ g = extent.param[POLY_G].start;
+ dg = extent.param[POLY_G].dpdx;
+ b = extent.param[POLY_B].start;
+ db = extent.param[POLY_B].dpdx;
+ a = extent.param[POLY_A].start;
+ da = extent.param[POLY_A].dpdx;
+ }
- // Current guesswork on the command word bits:
- // 0x01: Z-buffer disable?
- // 0x02: Almost always set (only exception is 0x80000020 in Thunder Hurricane attract mode)
- // 0x04:
- // 0x08:
- // 0x10: Texture mirror enable
- // 0x20: Gouraud shading enable?
- // 0x40: Unused?
- // 0x80: Used by textured polygons.
- // 0x100: Alpha blending? Only used by Winding Heat car selection so far.
-
- if (cmd == 0x800000ae || cmd == 0x8000008e || cmd == 0x80000096 || cmd == 0x800000b6 ||
- cmd == 0x8000002e || cmd == 0x8000000e || cmd == 0x80000016 || cmd == 0x80000036 ||
- cmd == 0x800000aa || cmd == 0x800000a8 || cmd == 0x800000b2 || cmd == 0x8000009e ||
- cmd == 0x80000092 || cmd == 0x8000008a || cmd == 0x80000094 || cmd == 0x8000009a ||
- cmd == 0x8000009c || cmd == 0x8000008c || cmd == 0x800000ac || cmd == 0x800000b4)
- {
- // 0x00: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Command
- //
- // 0x01: xxxx---- -------- -------- -------- Texture palette
- // 0x01: ----xx-- -------- -------- -------- Unknown flags, set by commands 0x7b...0x7e
- // 0x01: ------xx x------- -------- -------- Texture width / 8 - 1
- // 0x01: -------- -xxx---- -------- -------- Texture height / 8 - 1
- // 0x01: -------- -------x xxxx---- -------- Texture page
- // 0x01: -------- -------- ----x-x- x-x-x-x- Texture X / 8
- // 0x01: -------- -------- -----x-x -x-x-x-x Texture Y / 8
-
- // texture, Z
-
- int tex_x, tex_y;
- uint32_t color = 0;
- k001005_polydata &extra = object_data_alloc();
-
- uint32_t header = fifo[index++];
-
- int last_vertex = 0;
- int vert_num = 0;
- do
- {
- int x, y, z;
- int16_t tu, tv;
+ rgbaint_t ambient_color(extradata.ambient_light);
+ rgbaint_t diffuse_color(extradata.diffuse_light);
+ rgbaint_t fog_color(extradata.fog_color);
- x = (fifo[index] >> 0) & 0x3fff;
- y = (fifo[index] >> 16) & 0x1fff;
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
+ rgbaint_t poly_color(extradata.poly_color);
+ int poly_color_a = (extradata.poly_color >> 24) & 0xff;
- poly_type = fifo[index] & 0x4000; // 0 = triangle, 1 = quad
- last_vertex = fifo[index] & 0x8000;
- index++;
+ int texture_mirror_x = extradata.texture_mirror;
+ int texture_mirror_y = extradata.texture_mirror;
+ int texture_x = extradata.texture_x * 8;
+ int texture_y = extradata.texture_y * 8;
+ int texture_width = extradata.texture_width;
+ int texture_height = extradata.texture_height;
+ int tex_page = extradata.texture_page * 0x40000;
+ int palette_index = extradata.texture_palette * 256;
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
- index++;
+ int* x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
+ int* y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
- if (last_vertex)
- {
- color = fifo[index++];
- }
+ bool UseZCompare = (extradata.cmd & 4) != 0;
+ bool UseFBBlend = (extradata.cmd & 2) == 0;
+ bool UseFog = extradata.fog_enable;
- tu = (fifo[index] >> 16) & 0xffff;
- tv = (fifo[index] & 0xffff);
- index++;
+ bool WriteZ = true;
+ bool UseBilinear = k001006->bilinear_enabled();
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_W] = 1.0f / v[vert_num].p[POLY_Z];
- v[vert_num].p[POLY_U] = tu * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_V] = tv * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_BRI] = brightness;
- v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
- //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
- if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
- if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
- vert_num++;
- }
- while (!last_vertex && vert_num < 4);
-
- tex_y = ((header & 0x400) >> 5) |
- ((header & 0x100) >> 4) |
- ((header & 0x040) >> 3) |
- ((header & 0x010) >> 2) |
- ((header & 0x004) >> 1) |
- ((header & 0x001) >> 0);
-
- tex_x = ((header & 0x800) >> 6) |
- ((header & 0x200) >> 5) |
- ((header & 0x080) >> 4) |
- ((header & 0x020) >> 3) |
- ((header & 0x008) >> 2) |
- ((header & 0x002) >> 1);
-
- extra.texture_x = tex_x * 8;
- extra.texture_y = tex_y * 8;
- extra.texture_width = (header >> 23) & 0x7;
- extra.texture_height = (header >> 20) & 0x7;
- extra.texture_page = (header >> 12) & 0x1f;
- extra.texture_palette = (header >> 28) & 0xf;
- extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);
- extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);
- extra.color = color;
- extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
- extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
- extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
- extra.flags = cmd;
-
- if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
- {
- v[0].p[POLY_BRI] = brightness;
- v[1].p[POLY_BRI] = brightness;
- }
+ uint32_t texel = 0;
+ uint32_t texel_alpha = 0;
- if (poly_type == 0) // triangle
+ for (int x = extent.startx; x < extent.stopx; x++)
+ {
+ if (z <= zb[x] || !UseZCompare)
+ {
+ if (UseTexture)
{
- if (vert_num == 1)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- }
- else if (vert_num == 2)
- {
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
- }
- else
- {
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
- }
+ float oow = 1.0f / w;
- render_triangle<6>(m_cliprect, rd_scan_tex, *vertex1, *vertex2, *vertex3);
+ int iu = (int)(u * oow);
+ int iv = (int)(v * oow);
- memcpy(&m_prev_v[1], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex3, sizeof(vertex_t));
- }
- else // quad
- {
- if (vert_num == 1)
+ if (!UseBilinear)
{
- vertex1 = &m_prev_v[1];
- vertex2 = &m_prev_v[2];
- vertex3 = &m_prev_v[3];
- vertex4 = &v[0];
- }
- else if (vert_num == 2)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- vertex4 = &v[1];
- }
- else if (vert_num == 3)
- {
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
- vertex4 = &v[2];
+ int texel_u = texture_x + x_mirror_table[(iu >> 4) & 0x7f];
+ int texel_v = texture_y + y_mirror_table[(iv >> 4) & 0x7f];
+
+ texel = k001006->fetch_texel(tex_page, palette_index, texel_u, texel_v);
+ texel_alpha = texel >> 24;
}
else
{
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
- vertex4 = &v[3];
- }
+ // sub-texel bias to avoid seams
+ iu -= 7;
+ iv -= 7;
- render_triangle<6>(m_cliprect, rd_scan_tex, *vertex1, *vertex2, *vertex3);
- render_triangle<6>(m_cliprect, rd_scan_tex, *vertex3, *vertex4, *vertex1);
+ int ufrac = iu & 0xf;
+ int vfrac = iv & 0xf;
+ int texel_u0 = texture_x + x_mirror_table[(iu >> 4) & 0x7f];
+ int texel_u1 = texture_x + x_mirror_table[((iu >> 4) + 1) & 0x7f];
+ int texel_v0 = texture_y + y_mirror_table[(iv >> 4) & 0x7f];
+ int texel_v1 = texture_y + y_mirror_table[((iv >> 4) + 1) & 0x7f];
- memcpy(&m_prev_v[0], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[1], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex3, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex4, sizeof(vertex_t));
- }
+ uint32_t tex00 = k001006->fetch_texel(tex_page, palette_index, texel_u0, texel_v0);
+ uint32_t tex01 = k001006->fetch_texel(tex_page, palette_index, texel_u1, texel_v0);
+ uint32_t tex10 = k001006->fetch_texel(tex_page, palette_index, texel_u0, texel_v1);
+ uint32_t tex11 = k001006->fetch_texel(tex_page, palette_index, texel_u1, texel_v1);
- while ((fifo[index] & 0xffffff00) != 0x80000000 && index < m_3dfifo_ptr)
- {
- k001005_polydata &extra = object_data_alloc();
- int new_verts = 0;
+ texel = rgbaint_t::bilinear_filter(tex00, tex01, tex10, tex11, ufrac * 16, vfrac * 16);
+ texel_alpha = tex00 >> 24;
+ }
+ }
- memcpy(&v[0], &m_prev_v[2], sizeof(vertex_t));
- memcpy(&v[1], &m_prev_v[3], sizeof(vertex_t));
+ int idiff = std::clamp((int)(diff), 0, 255);
+ int ifog = std::clamp((int)(fog), 0, 255);
- last_vertex = 0;
- vert_num = 2;
- do
- {
- int x, y, z;
- int16_t tu, tv;
- x = ((fifo[index] >> 0) & 0x3fff);
- y = ((fifo[index] >> 16) & 0x1fff);
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
+ rgbaint_t light_color(extradata.diffuse_light);
+ light_color.scale_imm_and_clamp(idiff);
+ light_color.add(ambient_color);
+ light_color.clamp_to_uint8();
- poly_type = fifo[index] & 0x4000;
- last_vertex = fifo[index] & 0x8000;
- index++;
+ if (UseVertexColor)
+ {
+ int ir = std::clamp((int)(r), 0, 255);
+ int ig = std::clamp((int)(g), 0, 255);
+ int ib = std::clamp((int)(b), 0, 255);
+ int ia = std::clamp((int)(a), 0, 255);
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
- index++;
+ if (ia != 0)
+ {
+ rgbaint_t color(ia, ir, ig, ib);
- if (last_vertex)
- {
- color = fifo[index++];
+ if (UseTexture && texel_alpha != 0)
+ {
+ color.set(texel);
}
- tu = (fifo[index] >> 16) & 0xffff;
- tv = (fifo[index] >> 0) & 0xffff;
- index++;
-
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_W] = 1.0f / v[vert_num].p[POLY_Z];
- v[vert_num].p[POLY_U] = tu * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_V] = tv * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_BRI] = brightness;
- v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
- //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
- if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
- if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
-
- vert_num++;
- new_verts++;
- }
- while (!last_vertex && vert_num < 4);
-
- extra.texture_x = tex_x * 8;
- extra.texture_y = tex_y * 8;
- extra.texture_width = (header >> 23) & 0x7;
- extra.texture_height = (header >> 20) & 0x7;
-
- extra.texture_page = (header >> 12) & 0x1f;
- extra.texture_palette = (header >> 28) & 0xf;
-
- extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);// & ((header & 0x00400000) ? 0x1 : 0);
- extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);// & ((header & 0x00400000) ? 0x1 : 0);
-
- extra.color = color;
- extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
- extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
- extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
- extra.flags = cmd;
-
- if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
- {
- v[0].p[POLY_BRI] = brightness;
- v[1].p[POLY_BRI] = brightness;
- }
+ color.scale_and_clamp(light_color);
- if (new_verts == 1)
- {
- render_triangle<6>(m_cliprect, rd_scan_tex, v[0], v[1], v[2]);
+ if (UseFog)
+ {
+ color.blend(fog_color, ifog);
+ }
- memcpy(&m_prev_v[1], &v[0], sizeof(vertex_t));
- memcpy(&m_prev_v[2], &v[1], sizeof(vertex_t));
- memcpy(&m_prev_v[3], &v[2], sizeof(vertex_t));
- }
- else if (new_verts == 2)
- {
- render_triangle<6>(m_cliprect, rd_scan_tex, v[0], v[1], v[2]);
- render_triangle<6>(m_cliprect, rd_scan_tex, v[2], v[3], v[0]);
+ // framebuffer blend
+ if (UseFBBlend)
+ {
+ rgbaint_t fb_color(fb[x]);
+ color.blend(fb_color, ia);
+ }
- memcpy(&m_prev_v[0], &v[0], sizeof(vertex_t));
- memcpy(&m_prev_v[1], &v[1], sizeof(vertex_t));
- memcpy(&m_prev_v[2], &v[2], sizeof(vertex_t));
- memcpy(&m_prev_v[3], &v[3], sizeof(vertex_t));
+ fb[x] = color.to_rgba();
+ if (WriteZ)
+ zb[x] = z;
}
- };
- }
- else if (cmd == 0x80000006 || cmd == 0x80000026 || cmd == 0x80000002 || cmd == 0x80000020 || cmd == 0x80000022)
- {
- // no texture, Z
-
- k001005_polydata &extra = object_data_alloc();
- uint32_t color;
- int r, g, b, a;
-
- int last_vertex = 0;
- int vert_num = 0;
- do
- {
- int x, y, z;
-
- x = (fifo[index] >> 0) & 0x3fff;
- y = (fifo[index] >> 16) & 0x1fff;
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
-
- poly_type = fifo[index] & 0x4000; // 0 = triangle, 1 = quad
- last_vertex = fifo[index] & 0x8000;
- index++;
-
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
- index++;
-
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_BRI] = brightness;
- v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
- //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
- if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
- if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
- vert_num++;
- }
- while (!last_vertex && vert_num < 4);
-
- r = (fifo[index] >> 0) & 0xff;
- g = (fifo[index] >> 8) & 0xff;
- b = (fifo[index] >> 16) & 0xff;
- a = (fifo[index] >> 24) & 0xff;
- color = (a << 24) | (r << 16) | (g << 8) | (b);
- index++;
-
- extra.color = color;
- extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
- extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
- extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
- extra.flags = cmd;
-
- if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
- {
- v[0].p[POLY_BRI] = brightness;
- v[1].p[POLY_BRI] = brightness;
}
-
- if (poly_type == 0) // triangle
+ else
{
- if (vert_num == 1)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- }
- else if (vert_num == 2)
+ if (UseTexture)
{
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
+ if (texel_alpha != 0)
+ {
+ rgbaint_t texel_color(texel);
+ texel_color.scale_and_clamp(light_color);
+
+ // TODO: is there a toggle for texture blending? cmd bit 0x02 doesn't seem like it
+ if (UseBilinear && texel_alpha < 0xff)
+ {
+ rgbaint_t fb_color(fb[x]);
+ texel_color.blend(fb_color, texel_alpha);
+ }
+
+ if (UseFog)
+ {
+ texel_color.blend(fog_color, ifog);
+ }
+
+ if (UseFBBlend)
+ {
+ rgbaint_t fb_color(fb[x]);
+ texel_color.blend(fb_color, poly_color_a);
+ }
+
+ fb[x] = texel_color.to_rgba();
+ if (WriteZ)
+ zb[x] = z;
+ }
}
else
{
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
+ //if (poly_color_a != 0)
+ {
+ rgbaint_t color(extradata.poly_color);
+ color.scale_and_clamp(light_color);
+
+ if (UseFog)
+ {
+ color.blend(fog_color, ifog);
+ }
+
+ // framebuffer blend
+ if (UseFBBlend)
+ {
+ rgbaint_t fb_color(fb[x]);
+ color.blend(fb_color, poly_color_a);
+ }
+
+ fb[x] = color.to_rgba();
+ if (WriteZ)
+ zb[x] = z;
+ }
}
-
- render_triangle<3>(m_cliprect, rd_scan, *vertex1, *vertex2, *vertex3);
-
- memcpy(&m_prev_v[1], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex3, sizeof(vertex_t));
}
- else // quad
- {
- if (vert_num == 1)
- {
- vertex1 = &m_prev_v[1];
- vertex2 = &m_prev_v[2];
- vertex3 = &m_prev_v[3];
- vertex4 = &v[0];
- }
- else if (vert_num == 2)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- vertex4 = &v[1];
- }
- else if (vert_num == 3)
- {
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
- vertex4 = &v[2];
- }
- else
- {
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
- vertex4 = &v[3];
- }
- render_triangle<3>(m_cliprect, rd_scan, *vertex1, *vertex2, *vertex3);
- render_triangle<3>(m_cliprect, rd_scan, *vertex3, *vertex4, *vertex1);
+ }
- memcpy(&m_prev_v[0], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[1], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex3, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex4, sizeof(vertex_t));
- }
+ z += dz;
+ diff += ddiff;
+ fog += dfog;
- while ((fifo[index] & 0xffffff00) != 0x80000000 && index < m_3dfifo_ptr)
- {
- int new_verts = 0;
+ if (UseVertexColor)
+ {
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
- memcpy(&v[0], &m_prev_v[2], sizeof(vertex_t));
- memcpy(&v[1], &m_prev_v[3], sizeof(vertex_t));
+ if (UseTexture)
+ {
+ u += du;
+ v += dv;
+ w += dw;
+ }
+ }
+}
- last_vertex = 0;
- vert_num = 2;
- do
- {
- int x, y, z;
- x = ((fifo[index] >> 0) & 0x3fff);
- y = ((fifo[index] >> 16) & 0x1fff);
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
+/*
+ Command
+ 0x00: xxxxxxxx xxxxxxxx xxxxxxx- -------- 0x80000000 (exact number of bits unknown)
+ 0x00: -------- -------- -------x -------- 0 = per-poly color, 1 = per-vertex color
+ 0x00: -------- -------- -------- x------- ? Texture related
+ 0x00: -------- -------- -------- -x------ Unused?
+ 0x00: -------- -------- -------- --x----- 1 = enable smooth shading?
+ 0x00: -------- -------- -------- ---x---- 1 = texture mirroring
+ 0x00: -------- -------- -------- ----x--- ? Texture related
+ 0x00: -------- -------- -------- -----x-- 1 = enable Z-buffer read
+ 0x00: -------- -------- -------- ------x- 0 = blend enabled, 1 = disabled
+ 0x00: -------- -------- -------- -------x 0 = per-vertex Z, 1 = per-poly Z (0x80000121 seems like an exception)
+
+ Texture header
+ 0x01: -xxx---- -------- -------- -------- Texture palette
+ 0x01: ----xx-- -------- -------- -------- Unknown flags, set by commands 0x7b...0x7e. Used mostly on polygons further away from camera. Some kind of depth-based effect?
+ 0x01: ------xx x------- -------- -------- Texture width / 8 - 1
+ 0x01: -------- -xxx---- -------- -------- Texture height / 8 - 1
+ 0x01: -------- -------x xxxx---- -------- Texture page
+ 0x01: -------- -------- ----x-x- x-x-x-x- Texture X / 8
+ 0x01: -------- -------- -----x-x -x-x-x-x Texture Y / 8
+*/
- poly_type = fifo[index] & 0x4000;
- last_vertex = fifo[index] & 0x8000;
- index++;
+int k001005_renderer::parse_polygon(int index, uint32_t cmd)
+{
+ render_delegate rd_scan_tex = render_delegate(&k001005_renderer::draw_scanline_generic<true, false>, this);
+ render_delegate rd_scan_vertex_color = render_delegate(&k001005_renderer::draw_scanline_generic<false, true>, this);
+ render_delegate rd_scan_vertex_color_tex = render_delegate(&k001005_renderer::draw_scanline_generic<true, true>, this);
+ render_delegate rd_scan_color = render_delegate(&k001005_renderer::draw_scanline_generic<false, false>, this);
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
- index++;
+ int viewport_min_x = std::clamp(256 + m_viewport_min_x + m_viewport_center_x, m_cliprect.min_x, m_cliprect.max_x);
+ int viewport_max_x = std::clamp(256 + m_viewport_max_x + m_viewport_center_x + 1, m_cliprect.min_x, m_cliprect.max_x);
+ int viewport_min_y = std::clamp(200 + m_viewport_min_y - m_viewport_center_y, m_cliprect.min_y, m_cliprect.max_y);
+ int viewport_max_y = std::clamp(200 + m_viewport_max_y - m_viewport_center_y + 1, m_cliprect.min_y, m_cliprect.max_y);
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_BRI] = brightness;
- v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
- //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
- if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
- if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
-
- vert_num++;
- new_verts++;
- }
- while (!last_vertex && vert_num < 4);
+ rectangle cliprect(viewport_min_x, viewport_max_x, viewport_min_y, viewport_max_y);
+
- r = (fifo[index] >> 0) & 0xff;
- g = (fifo[index] >> 8) & 0xff;
- b = (fifo[index] >> 16) & 0xff;
- a = (fifo[index] >> 24) & 0xff;
- color = (a << 24) | (r << 16) | (g << 8) | (b);
- index++;
+ int start_index = index;
- extra.color = color;
- extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
- extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
- extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
- extra.flags = cmd;
+ uint32_t* fifo = m_3dfifo.get();
- if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
- {
- v[0].p[POLY_BRI] = brightness;
- v[1].p[POLY_BRI] = brightness;
- }
+ bool has_texture = (cmd & 0x18) != 0;
+ bool has_vertex_color = (cmd & 0x100) != 0;
+ bool has_vertex_z = !(cmd & 1) || has_vertex_color; // command 0x121 breaks the logic here, maybe vertex color enforces vertex z too?
- if (new_verts == 1)
- {
- render_triangle<3>(m_cliprect, rd_scan, v[0], v[1], v[2]);
+ uint32_t texture_x = 0;
+ uint32_t texture_y = 0;
+ uint32_t texture_width = 0;
+ uint32_t texture_height = 0;
+ uint32_t texture_page = 0;
+ uint32_t texture_palette = 0;
- memcpy(&m_prev_v[1], &v[0], sizeof(vertex_t));
- memcpy(&m_prev_v[2], &v[1], sizeof(vertex_t));
- memcpy(&m_prev_v[3], &v[2], sizeof(vertex_t));
- }
- else if (new_verts == 2)
- {
- render_triangle<3>(m_cliprect, rd_scan, v[0], v[1], v[2]);
- render_triangle<3>(m_cliprect, rd_scan, v[2], v[3], v[0]);
+ uint32_t tex_header = 0;
- memcpy(&m_prev_v[0], &v[0], sizeof(vertex_t));
- memcpy(&m_prev_v[1], &v[1], sizeof(vertex_t));
- memcpy(&m_prev_v[2], &v[2], sizeof(vertex_t));
- memcpy(&m_prev_v[3], &v[3], sizeof(vertex_t));
- }
- }
- }
- else if (cmd == 0x80000003 || cmd == 0x80000001)
- {
- // no texture, no Z
+ // texture header - only for textured polys
+ if (has_texture)
+ {
+ tex_header = fifo[index++];
- k001005_polydata &extra = object_data_alloc();
- int r, g, b, a;
- uint32_t color;
+ texture_x = (((tex_header >> 6) & 0x20) | ((tex_header >> 5) & 0x10) | ((tex_header >> 4) & 0x8) |
+ ((tex_header >> 3) & 0x4) | ((tex_header >> 2) & 0x2) | ((tex_header >> 1) & 0x1));
- int last_vertex = 0;
- int vert_num = 0;
- do
- {
- int x, y;
+ texture_y = (((tex_header >> 5) & 0x20) | ((tex_header >> 4) & 0x10) | ((tex_header >> 3) & 0x8) |
+ ((tex_header >> 2) & 0x4) | ((tex_header >> 1) & 0x2) | (tex_header & 0x1));
- x = ((fifo[index] >> 0) & 0x3fff);
- y = ((fifo[index] >> 16) & 0x1fff);
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
+ texture_width = (tex_header >> 23) & 0x7;
+ texture_height = (tex_header >> 20) & 0x7;
+ texture_page = (tex_header >> 12) & 0x1f;
+ texture_palette = (tex_header >> 28) & 0x7;
+ }
- poly_type = fifo[index] & 0x4000;
- last_vertex = fifo[index] & 0x8000;
- index++;
+ while ((fifo[index] & 0xffff0000) != 0x80000000 && index < m_3dfifo_ptr)
+ {
+ k001005_polydata& extra = object_data_alloc();
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- vert_num++;
- }
- while (!last_vertex && vert_num < 4);
+ bool last_vertex = false;
+ bool is_quad = false;
- // unknown word
- index++;
+ uint32_t polygon_color = 0;
+ float polygon_z = 0.0f;
+ uint32_t polygon_diffuse = 0;
- r = (fifo[index] >> 0) & 0xff;
- g = (fifo[index] >> 8) & 0xff;
- b = (fifo[index] >> 16) & 0xff;
- a = (fifo[index] >> 24) & 0xff;
- color = (a << 24) | (r << 16) | (g << 8) | (b);
- index++;
+ int num_new_verts = 0;
- extra.color = color;
- extra.flags = cmd;
+ do
+ {
+ // X/Y coords, flags - all polys have this
+ // -------------------------------------------------------------------------
+ int x = fifo[index] & 0x3fff;
+ x |= ((x & 0x2000) ? 0xffffc000 : 0);
+ int y = (fifo[index] >> 16) & 0x1fff;
+ y |= ((y & 0x1000) ? 0xffffe000 : 0);
+
+ m_vertexb[m_vertexb_ptr].x = ((float)(x) / 16.0f) + 256.0f;
+ m_vertexb[m_vertexb_ptr].y = ((float)(-y) / 16.0f) + 200.0f;
+
+ is_quad = (fifo[index] & 0x4000) != 0;
+ last_vertex = (fifo[index] & 0x8000) != 0;
+ index++;
- if (poly_type == 0)
+ // Z + diffuse intensity - if Z enabled
+ // -------------------------------------------------------------------------
+ if (has_vertex_z)
{
- render_triangle<0>(m_cliprect, rd_scan_2d, v[0], v[1], v[2]);
+ uint32_t z = fifo[index] & 0xffffff00; // 32-bit float with low 8-bits of mantissa masked out
+ int diffuse = fifo[index] & 0xff;
+ index++;
+
+ m_vertexb[m_vertexb_ptr].p[POLY_Z] = u2f(z);
+ m_vertexb[m_vertexb_ptr].p[POLY_DIFF] = diffuse;
+ m_vertexb[m_vertexb_ptr].p[POLY_W] = 1.0f / m_vertexb[m_vertexb_ptr].p[POLY_Z];
}
else
{
- render_triangle<0>(m_cliprect, rd_scan_2d, v[0], v[1], v[2]);
- render_triangle<0>(m_cliprect, rd_scan_2d, v[2], v[3], v[0]);
+ m_vertexb[m_vertexb_ptr].p[POLY_W] = 1.0f;
}
- }
- else if (cmd == 0x8000008b)
- {
- // texture, no Z
- int tex_x, tex_y;
- k001005_polydata &extra = object_data_alloc();
- int r, g, b, a;
- uint32_t color = 0;
-
- uint32_t header = fifo[index++];
-
- int last_vertex = 0;
- int vert_num = 0;
- do
+ // textured polygons have a polygon color field after last vertex data, but before the last UV coords
+ // -------------------------------------------------------------------------
+ if (last_vertex && has_texture)
{
- int x, y;
- int16_t tu, tv;
-
- x = ((fifo[index] >> 0) & 0x3fff);
- y = ((fifo[index] >> 16) & 0x1fff);
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
-
- poly_type = fifo[index] & 0x4000;
- last_vertex = fifo[index] & 0x8000;
- index++;
-
- if (last_vertex)
+ // polygon Z comes before the last UV coords for textured polygons
+ if (!has_vertex_z)
{
- // unknown word
+ uint32_t z = (fifo[index] & 0x07ffff00) | 0x48000000; // like fog values, these seem to be missing the 4 upper bits of exponent
+ polygon_diffuse = fifo[index] & 0xff;
index++;
-
- color = fifo[index++];
+ polygon_z = u2f(z);
}
- tu = (fifo[index] >> 16) & 0xffff;
- tv = (fifo[index] & 0xffff);
- index++;
-
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_U] = tu;
- v[vert_num].p[POLY_V] = tv;
- vert_num++;
- }
- while (!last_vertex && vert_num < 4);
-
- r = (color >> 0) & 0xff;
- g = (color >> 8) & 0xff;
- b = (color >> 16) & 0xff;
- a = (color >> 24) & 0xff;
- extra.color = (a << 24) | (r << 16) | (g << 8) | (b);
- extra.flags = cmd;
-
- tex_y = ((header & 0x400) >> 5) |
- ((header & 0x100) >> 4) |
- ((header & 0x040) >> 3) |
- ((header & 0x010) >> 2) |
- ((header & 0x004) >> 1) |
- ((header & 0x001) >> 0);
-
- tex_x = ((header & 0x800) >> 6) |
- ((header & 0x200) >> 5) |
- ((header & 0x080) >> 4) |
- ((header & 0x020) >> 3) |
- ((header & 0x008) >> 2) |
- ((header & 0x002) >> 1);
-
- extra.texture_x = tex_x * 8;
- extra.texture_y = tex_y * 8;
- extra.texture_width = (header >> 23) & 0x7;
- extra.texture_height = (header >> 20) & 0x7;
-
- extra.texture_page = (header >> 12) & 0x1f;
- extra.texture_palette = (header >> 28) & 0xf;
-
- extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);
- extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);
-
- if (poly_type == 0)
- {
- render_triangle<5>(m_cliprect, rd_scan_tex2d, v[0], v[1], v[2]);
- }
- else
- {
- render_triangle<5>(m_cliprect, rd_scan_tex2d, v[0], v[1], v[2]);
- render_triangle<5>(m_cliprect, rd_scan_tex2d, v[2], v[3], v[0]);
+ if (!has_vertex_color)
+ {
+ polygon_color = fifo[index];
+ index++;
+ }
}
- }
- else if (cmd == 0x80000106 || cmd == 0x80000121 || cmd == 0x80000126)
- {
- // no texture, color gouraud, Z
- k001005_polydata &extra = object_data_alloc();
- uint32_t color;
-
- int last_vertex = 0;
- int vert_num = 0;
- do
+ // vertex color
+ if (has_vertex_color)
{
- int x, y, z;
-
- x = ((fifo[index] >> 0) & 0x3fff);
- y = ((fifo[index] >> 16) & 0x1fff);
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
-
- poly_type = fifo[index] & 0x4000;
- last_vertex = fifo[index] & 0x8000;
+ uint32_t vertex_color = fifo[index];
index++;
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
- index++;
+ m_vertexb[m_vertexb_ptr].p[POLY_A] = (vertex_color >> 24) & 0xff;
+ m_vertexb[m_vertexb_ptr].p[POLY_B] = (vertex_color >> 16) & 0xff;
+ m_vertexb[m_vertexb_ptr].p[POLY_G] = (vertex_color >> 8) & 0xff;
+ m_vertexb[m_vertexb_ptr].p[POLY_R] = vertex_color & 0xff;
+
+ }
- color = fifo[index];
+ // UV coords - only for texture polys
+ if (has_texture)
+ {
+ int32_t tu = (int16_t)(fifo[index] >> 16);
+ int32_t tv = (int16_t)(fifo[index] & 0xffff);
index++;
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_B] = (color >> 16) & 0xff;
- v[vert_num].p[POLY_G] = (color >> 8) & 0xff;
- v[vert_num].p[POLY_R] = color & 0xff;
- v[vert_num].p[POLY_A] = (color >> 24) & 0xff;
- vert_num++;
+ m_vertexb[m_vertexb_ptr].p[POLY_U] = (float)(tu) * m_vertexb[m_vertexb_ptr].p[POLY_W];
+ m_vertexb[m_vertexb_ptr].p[POLY_V] = (float)(tv) * m_vertexb[m_vertexb_ptr].p[POLY_W];
}
- while (!last_vertex && vert_num < 4);
-
- extra.color = color;
- extra.flags = cmd;
- if (poly_type == 0)
+ // fog
+ if (m_reg_fog_start == 0xffff)
{
- render_triangle<6>(m_cliprect, rd_scan_gour_blend, v[0], v[1], v[2]);
+ // max fog start value means fog is off
+ m_vertexb[m_vertexb_ptr].p[POLY_FOG] = 0.0f;
}
else
{
- render_triangle<6>(m_cliprect, rd_scan_gour_blend, v[0], v[1], v[2]);
- render_triangle<6>(m_cliprect, rd_scan_gour_blend, v[2], v[3], v[0]);
+ float fog_factor = (m_fog_end_z - m_vertexb[m_vertexb_ptr].p[POLY_Z]) / (m_fog_end_z - m_fog_start_z);
+ m_vertexb[m_vertexb_ptr].p[POLY_FOG] = fog_factor * 255.0f;
}
- // TODO: can this poly type form strips?
+ num_new_verts++;
+ m_vertexb_ptr = (m_vertexb_ptr + 1) & 3;
}
- else if (cmd == 0x8000010e)
- {
- // texture, color gouraud, Z (color gouraud is shown where texture is transparent, used by midnrun/windheat CG board test)
- int tex_x, tex_y;
- uint32_t color = 0;
- k001005_polydata& extra = object_data_alloc();
+ while (!last_vertex && num_new_verts < 4);
- uint32_t header = fifo[index++];
-
- int last_vertex = 0;
- int vert_num = 0;
- do
+ // for non-textured polygons, polygon color comes after vertex data
+ if (!has_texture)
+ {
+ // polygon Z
+ if (!has_vertex_z)
{
- int x, y, z;
- int16_t tu, tv;
-
- x = (fifo[index] >> 0) & 0x3fff;
- y = (fifo[index] >> 16) & 0x1fff;
- x |= ((x & 0x2000) ? 0xffffc000 : 0);
- y |= ((y & 0x1000) ? 0xffffe000 : 0);
-
- poly_type = fifo[index] & 0x4000; // 0 = triangle, 1 = quad
- last_vertex = fifo[index] & 0x8000;
- index++;
-
- z = fifo[index] & 0xffffff00;
- brightness = fifo[index] & 0xff;
+ uint32_t z = (fifo[index] & 0x07ffff00) | 0x48000000; // like fog values, these seem to be missing the 4 upper bits of exponent
+ polygon_diffuse = fifo[index] & 0xff;
index++;
- color = fifo[index];
- index++;
-
- tu = (fifo[index] >> 16) & 0xffff;
- tv = (fifo[index] & 0xffff);
- index++;
-
- v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
- v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
- v[vert_num].p[POLY_Z] = *(float*)(&z);
- v[vert_num].p[POLY_W] = 1.0f / v[vert_num].p[POLY_Z];
- v[vert_num].p[POLY_U] = tu * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_V] = tv * v[vert_num].p[POLY_W];
- v[vert_num].p[POLY_BRI] = brightness;
- v[vert_num].p[POLY_FOG] = (1.0f / (exp(((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z)))) * 65536.0f;
- //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
- if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
- if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
- v[vert_num].p[POLY_ALTB] = (color >> 16) & 0xff;
- v[vert_num].p[POLY_ALTG] = (color >> 8) & 0xff;
- v[vert_num].p[POLY_ALTR] = color & 0xff;
- v[vert_num].p[POLY_ALTA] = (color >> 24) & 0xff;
- vert_num++;
- } while (!last_vertex && vert_num < 4);
-
- tex_y = ((header & 0x400) >> 5) |
- ((header & 0x100) >> 4) |
- ((header & 0x040) >> 3) |
- ((header & 0x010) >> 2) |
- ((header & 0x004) >> 1) |
- ((header & 0x001) >> 0);
-
- tex_x = ((header & 0x800) >> 6) |
- ((header & 0x200) >> 5) |
- ((header & 0x080) >> 4) |
- ((header & 0x020) >> 3) |
- ((header & 0x008) >> 2) |
- ((header & 0x002) >> 1);
-
- extra.texture_x = tex_x * 8;
- extra.texture_y = tex_y * 8;
- extra.texture_width = (header >> 23) & 0x7;
- extra.texture_height = (header >> 20) & 0x7;
- extra.texture_page = (header >> 12) & 0x1f;
- extra.texture_palette = (header >> 28) & 0xf;
- extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);
- extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);
- extra.color = 0xffffffff;
- extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
- extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
- extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
- extra.flags = cmd;
-
- if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
- {
- v[0].p[POLY_BRI] = brightness;
- v[1].p[POLY_BRI] = brightness;
+ polygon_z = u2f(z);
}
- if (poly_type == 0) // triangle
+ // polygon color
+ if (!has_vertex_color)
{
- if (vert_num == 1)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- }
- else if (vert_num == 2)
- {
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
- }
- else
- {
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
- }
-
- render_triangle<10>(m_cliprect, rd_scan_tex_gouraud, *vertex1, *vertex2, *vertex3);
-
- memcpy(&m_prev_v[1], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex3, sizeof(vertex_t));
- }
- else // quad
- {
- if (vert_num == 1)
- {
- vertex1 = &m_prev_v[1];
- vertex2 = &m_prev_v[2];
- vertex3 = &m_prev_v[3];
- vertex4 = &v[0];
- }
- else if (vert_num == 2)
- {
- vertex1 = &m_prev_v[2];
- vertex2 = &m_prev_v[3];
- vertex3 = &v[0];
- vertex4 = &v[1];
- }
- else if (vert_num == 3)
- {
- vertex1 = &m_prev_v[3];
- vertex2 = &v[0];
- vertex3 = &v[1];
- vertex4 = &v[2];
- }
- else
- {
- vertex1 = &v[0];
- vertex2 = &v[1];
- vertex3 = &v[2];
- vertex4 = &v[3];
- }
-
- render_triangle<10>(m_cliprect, rd_scan_tex_gouraud, *vertex1, *vertex2, *vertex3);
- render_triangle<10>(m_cliprect, rd_scan_tex_gouraud, *vertex3, *vertex4, *vertex1);
-
- memcpy(&m_prev_v[0], vertex1, sizeof(vertex_t));
- memcpy(&m_prev_v[1], vertex2, sizeof(vertex_t));
- memcpy(&m_prev_v[2], vertex3, sizeof(vertex_t));
- memcpy(&m_prev_v[3], vertex4, sizeof(vertex_t));
+ polygon_color = fifo[index];
+ index++;
}
}
- else if (cmd == 0x80000000)
- {
- }
- else if (cmd == 0x80000018)
- {
- }
- else if ((cmd & 0xffff0000) == 0x80000000)
- {
- /*
- osd_printf_debug("Unknown polygon type %08X:\n", fifo[index-1]);
- for (int i=0; i < 0x20; i++)
- {
- osd_printf_debug(" %02X: %08X\n", i, fifo[index+i]);
- }
- osd_printf_debug("\n");
- */
- printf("Unknown polygon type %08X:\n", fifo[index-1]);
- for (int i=0; i < 0x20; i++)
+ // apply constant Z to all verts if needed
+ if (!has_vertex_z)
+ {
+ for (auto j = 0; j < 4; j++)
{
- printf(" %02X: %08X\n", i, fifo[index+i]);
+ m_vertexb[j].p[POLY_Z] = polygon_z;
+ m_vertexb[j].p[POLY_DIFF] = polygon_diffuse;
}
- printf("\n");
}
- else
- {
- }
- }
- while (index < m_3dfifo_ptr);
-
-#if LOG_POLY_FIFO
- printf("\nrender %d\n", K001005_3d_fifo_ptr);
- printf("------------------------------------\n");
-#endif
-
- m_3dfifo_ptr = 0;
- wait();
-}
-
-
-void k001005_renderer::draw_scanline_2d(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
-{
- uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
- float *const zb = (float*)&m_zb->pix(scanline);
- uint32_t color = extradata.color;
-
- for (int x = extent.startx; x < extent.stopx; x++)
- {
- if (color & 0xff000000)
- {
- fb[x] = color;
- zb[x] = FLT_MAX; // FIXME
- }
- }
-}
-
-void k001005_renderer::draw_scanline_2d_tex(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
-{
- // int pal_chip = (extradata.texture_palette & 0x8) ? 1 : 0;
- k001006_device *k001006 = downcast<k001006_device*>(m_k001006);
-
- int tex_page = extradata.texture_page * 0x40000;
- int palette_index = (extradata.texture_palette & 0x7) * 256;
- float u = extent.param[POLY_U].start;
- float v = extent.param[POLY_V].start;
- float du = extent.param[POLY_U].dpdx;
- float dv = extent.param[POLY_V].dpdx;
- uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
- float *const zb = (float*)&m_zb->pix(scanline);
- uint32_t color = extradata.color;
- int texture_mirror_x = extradata.texture_mirror_x;
- int texture_mirror_y = extradata.texture_mirror_y;
- int texture_x = extradata.texture_x;
- int texture_y = extradata.texture_y;
- int texture_width = extradata.texture_width;
- int texture_height = extradata.texture_height;
-
- int *x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
- int *y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
-
- for (int x = extent.startx; x < extent.stopx; x++)
- {
- int iu = (int)(u * 0.0625f);
- int iv = (int)(v * 0.0625f);
- int iiv, iiu;
+ extra.texture_x = texture_x;
+ extra.texture_y = texture_y;
+ extra.texture_width = texture_width;
+ extra.texture_height = texture_height;
+ extra.texture_page = texture_page;
+ extra.texture_palette = texture_palette;
+ extra.texture_mirror = (cmd & 0x10);
+ extra.diffuse_light = rgb_t(m_light_r, m_light_g, m_light_b);
+ extra.ambient_light = rgb_t(m_ambient_r, m_ambient_g, m_ambient_b);
+ extra.fog_color = rgb_t(m_fog_r, m_fog_g, m_fog_b);
+ extra.fog_enable = m_reg_fog_start != 0xffff;
+ extra.cmd = cmd;
+
+ extra.poly_color = rgb_t((polygon_color >> 24) & 0xff, polygon_color & 0xff, (polygon_color >> 8) & 0xff, (polygon_color >> 16) & 0xff);
+
+
+ // If 4 new vertices were found, but no last vertex tag - we're reading garbage.
+ // Midnrun writes garbage after a 0x80000003 command. The data comes directly from the display list, so it seems intentional.
+ if (num_new_verts >= 4 && !last_vertex)
+ break;
- iiu = texture_x + x_mirror_table[iu & 0x7f];
- iiv = texture_y + y_mirror_table[iv & 0x7f];
- color = k001006->fetch_texel(tex_page, palette_index, iiu, iiv);
+ // The vertex buffer is a 4-entry circular buffer.
+ // Each polygon has at least one new vertex. 0-3 vertices are reused based on how many new vertices were inserted.
+ int v0 = (m_vertexb_ptr - 4) & 3;
+ int v1 = (m_vertexb_ptr - 3) & 3;
+ int v2 = (m_vertexb_ptr - 2) & 3;
+ int v3 = (m_vertexb_ptr - 1) & 3;
- if (color & 0xff000000)
+
+ // This fixes shading issues in the Konami logo in Solar Assault.
+ // Some triangle strips have different shading values compared to reused vertices, causing unintended smooth shading.
+ // This ensures all vertices have the same shading value.
+ // Bit 0x20 could be a select between flat shading and gouraud shading.
+ if ((cmd & 0x20) == 0 && num_new_verts < 3)
{
- fb[x] = color;
- zb[x] = FLT_MAX; // FIXME
+ int last_diffuse = m_vertexb[v3].p[POLY_DIFF];
+ m_vertexb[v0].p[POLY_DIFF] = last_diffuse;
+ m_vertexb[v1].p[POLY_DIFF] = last_diffuse;
+ m_vertexb[v2].p[POLY_DIFF] = last_diffuse;
}
- u += du;
- v += dv;
- }
-}
-
-void k001005_renderer::draw_scanline(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
-{
- float z = extent.param[POLY_Z].start;
- float dz = extent.param[POLY_Z].dpdx;
- float bri = extent.param[POLY_BRI].start;
- float dbri = extent.param[POLY_BRI].dpdx;
- float fog = extent.param[POLY_FOG].start;
- float dfog = extent.param[POLY_FOG].dpdx;
- uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
- float *const zb = (float*)&m_zb->pix(scanline);
- uint32_t color = extradata.color;
-
- int poly_light_r = extradata.light_r + extradata.ambient_r;
- int poly_light_g = extradata.light_g + extradata.ambient_g;
- int poly_light_b = extradata.light_b + extradata.ambient_b;
- if (poly_light_r > 255) poly_light_r = 255;
- if (poly_light_g > 255) poly_light_g = 255;
- if (poly_light_b > 255) poly_light_b = 255;
- int poly_fog_r = extradata.fog_r;
- int poly_fog_g = extradata.fog_g;
- int poly_fog_b = extradata.fog_b;
-
- for (int x = extent.startx; x < extent.stopx; x++)
- {
- int ibri = (int)(bri);
- int ifog = (int)(fog);
-
- if (ibri < 0) ibri = 0;
- if (ibri > 255) ibri = 255;
- if (ifog < 0) ifog = 0;
- if (ifog > 65536) ifog = 65536;
-
- if (z <= zb[x])
+ // No texture, constant color: Z, Fog, Diffuse
+ // Texture, constant color: Z, Fog, Diffuse, U, V, W
+ // Per-vertex color: Z, Fog, Diffuse, U, V, W, R, G, B, A
+ if (is_quad)
{
- if (color & 0xff000000)
+ if (has_vertex_color)
+ {
+ render_triangle<10>(cliprect, has_texture ? rd_scan_vertex_color_tex : rd_scan_vertex_color, m_vertexb[v0], m_vertexb[v1], m_vertexb[v2]);
+ render_triangle<10>(cliprect, has_texture ? rd_scan_vertex_color_tex : rd_scan_vertex_color, m_vertexb[v2], m_vertexb[v3], m_vertexb[v0]);
+ }
+ else if (has_texture)
{
- int r = (color >> 16) & 0xff;
- int g = (color >> 8) & 0xff;
- int b = color & 0xff;
-
- r = ((((r * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
- g = ((((g * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
- b = ((((b * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
-
- if (r < 0) r = 0;
- if (r > 255) r = 255;
- if (g < 0) g = 0;
- if (g > 255) g = 255;
- if (b < 0) b = 0;
- if (b > 255) b = 255;
-
- fb[x] = (color & 0xff000000) | (r << 16) | (g << 8) | b;
- zb[x] = z;
+ render_triangle<6>(cliprect, rd_scan_tex, m_vertexb[v0], m_vertexb[v1], m_vertexb[v2]);
+ render_triangle<6>(cliprect, rd_scan_tex, m_vertexb[v2], m_vertexb[v3], m_vertexb[v0]);
}
- }
-
- z += dz;
- bri += dbri;
- fog += dfog;
- }
-}
-
-void k001005_renderer::draw_scanline_tex(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
-{
-// int pal_chip = (extradata.texture_palette & 0x8) ? 1 : 0;
- k001006_device *k001006 = downcast<k001006_device*>(m_k001006);
-
- int tex_page = extradata.texture_page * 0x40000;
- int palette_index = (extradata.texture_palette & 0x7) * 256;
- float z = extent.param[POLY_Z].start;
- float u = extent.param[POLY_U].start;
- float v = extent.param[POLY_V].start;
- float w = extent.param[POLY_W].start;
- float dz = extent.param[POLY_Z].dpdx;
- float du = extent.param[POLY_U].dpdx;
- float dv = extent.param[POLY_V].dpdx;
- float dw = extent.param[POLY_W].dpdx;
- float bri = extent.param[POLY_BRI].start;
- float dbri = extent.param[POLY_BRI].dpdx;
- float fog = extent.param[POLY_FOG].start;
- float dfog = extent.param[POLY_FOG].dpdx;
- int texture_mirror_x = extradata.texture_mirror_x;
- int texture_mirror_y = extradata.texture_mirror_y;
- int texture_x = extradata.texture_x;
- int texture_y = extradata.texture_y;
- int texture_width = extradata.texture_width;
- int texture_height = extradata.texture_height;
-
- int poly_light_r = extradata.light_r + extradata.ambient_r;
- int poly_light_g = extradata.light_g + extradata.ambient_g;
- int poly_light_b = extradata.light_b + extradata.ambient_b;
- if (poly_light_r > 255) poly_light_r = 255;
- if (poly_light_g > 255) poly_light_g = 255;
- if (poly_light_b > 255) poly_light_b = 255;
- int poly_fog_r = extradata.fog_r;
- int poly_fog_g = extradata.fog_g;
- int poly_fog_b = extradata.fog_b;
-
- uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
- float *const zb = (float*)&m_zb->pix(scanline);
-
- int *x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
- int *y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
-
- for (int x = extent.startx; x < extent.stopx; x++)
- {
- int ibri = (int)(bri);
- int ifog = (int)(fog);
-
- if (ibri < 0) ibri = 0;
- if (ibri > 255) ibri = 255;
- if (ifog < 0) ifog = 0;
- if (ifog > 65536) ifog = 65536;
-
- if (z <= zb[x])
- {
- float oow = 1.0f / w;
- uint32_t color;
- int iu, iv;
- int iiv, iiu;
-
- iu = u * oow * 0.0625f;
- iv = v * oow * 0.0625f;
-
- iiu = texture_x + x_mirror_table[iu & 0x7f];
- iiv = texture_y + y_mirror_table[iv & 0x7f];
-
- color = k001006->fetch_texel(tex_page, palette_index, iiu, iiv);
-
- if (color & 0xff000000)
+ else
{
- int r = (color >> 16) & 0xff;
- int g = (color >> 8) & 0xff;
- int b = color & 0xff;
-
- r = ((((r * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
- g = ((((g * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
- b = ((((b * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
-
- if (r < 0) r = 0;
- if (r > 255) r = 255;
- if (g < 0) g = 0;
- if (g > 255) g = 255;
- if (b < 0) b = 0;
- if (b > 255) b = 255;
-
- fb[x] = 0xff000000 | (r << 16) | (g << 8) | b;
- zb[x] = z;
+ render_triangle<3>(cliprect, rd_scan_color, m_vertexb[v0], m_vertexb[v1], m_vertexb[v2]);
+ render_triangle<3>(cliprect, rd_scan_color, m_vertexb[v2], m_vertexb[v3], m_vertexb[v0]);
}
}
-
- u += du;
- v += dv;
- z += dz;
- w += dw;
- bri += dbri;
- fog += dfog;
- }
-}
-
-void k001005_renderer::draw_scanline_gouraud_blend(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
-{
- float z = extent.param[POLY_Z].start;
- float dz = extent.param[POLY_Z].dpdx;
- float r = extent.param[POLY_R].start;
- float dr = extent.param[POLY_R].dpdx;
- float g = extent.param[POLY_G].start;
- float dg = extent.param[POLY_G].dpdx;
- float b = extent.param[POLY_B].start;
- float db = extent.param[POLY_B].dpdx;
- float a = extent.param[POLY_A].start;
- float da = extent.param[POLY_A].dpdx;
- uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
- float *const zb = (float*)&m_zb->pix(scanline);
-
- for (int x = extent.startx; x < extent.stopx; x++)
- {
- if (z <= zb[x])
- {
- int ir = (int)(r);
- int ig = (int)(g);
- int ib = (int)(b);
- int ia = (int)(a);
-
- if (ia > 0)
+ else
+ {
+ if (has_vertex_color)
{
- if (ia != 0xff)
- {
- int sr = (fb[x] >> 16) & 0xff;
- int sg = (fb[x] >> 8) & 0xff;
- int sb = fb[x] & 0xff;
-
- ir = ((ir * ia) >> 8) + ((sr * (0xff-ia)) >> 8);
- ig = ((ig * ia) >> 8) + ((sg * (0xff-ia)) >> 8);
- ib = ((ib * ia) >> 8) + ((sb * (0xff-ia)) >> 8);
- }
-
- if (ir < 0) ir = 0;
- if (ir > 255) ir = 255;
- if (ig < 0) ig = 0;
- if (ig > 255) ig = 255;
- if (ib < 0) ib = 0;
- if (ib > 255) ib = 255;
-
- fb[x] = 0xff000000 | (ir << 16) | (ig << 8) | ib;
- zb[x] = z;
+ render_triangle<10>(cliprect, has_texture ? rd_scan_vertex_color_tex : rd_scan_vertex_color, m_vertexb[v1], m_vertexb[v2], m_vertexb[v3]);
+ }
+ else if (has_texture)
+ {
+ render_triangle<6>(cliprect, rd_scan_tex, m_vertexb[v1], m_vertexb[v2], m_vertexb[v3]);
+ }
+ else
+ {
+ render_triangle<3>(cliprect, rd_scan_color, m_vertexb[v1], m_vertexb[v2], m_vertexb[v3]);
}
}
-
- z += dz;
- r += dr;
- g += dg;
- b += db;
- a += da;
}
+ return index - start_index;
}
-void k001005_renderer::draw_scanline_tex_gouraud(int32_t scanline, const extent_t& extent, const k001005_polydata& extradata, int threadid)
+void k001005_renderer::render_polygons()
{
- k001006_device* k001006 = downcast<k001006_device*>(m_k001006);
-
- int tex_page = extradata.texture_page * 0x40000;
- int palette_index = (extradata.texture_palette & 0x7) * 256;
- float z = extent.param[POLY_Z].start;
- float u = extent.param[POLY_U].start;
- float v = extent.param[POLY_V].start;
- float w = extent.param[POLY_W].start;
- float dz = extent.param[POLY_Z].dpdx;
- float du = extent.param[POLY_U].dpdx;
- float dv = extent.param[POLY_V].dpdx;
- float dw = extent.param[POLY_W].dpdx;
- float bri = extent.param[POLY_BRI].start;
- float dbri = extent.param[POLY_BRI].dpdx;
- float fog = extent.param[POLY_FOG].start;
- float dfog = extent.param[POLY_FOG].dpdx;
- float r = extent.param[POLY_ALTR].start;
- float dr = extent.param[POLY_ALTR].dpdx;
- float g = extent.param[POLY_ALTG].start;
- float dg = extent.param[POLY_ALTG].dpdx;
- float b = extent.param[POLY_ALTB].start;
- float db = extent.param[POLY_ALTB].dpdx;
- float a = extent.param[POLY_ALTA].start;
- float da = extent.param[POLY_ALTA].dpdx;
- int texture_mirror_x = extradata.texture_mirror_x;
- int texture_mirror_y = extradata.texture_mirror_y;
- int texture_x = extradata.texture_x;
- int texture_y = extradata.texture_y;
- int texture_width = extradata.texture_width;
- int texture_height = extradata.texture_height;
-
- int poly_light_r = extradata.light_r + extradata.ambient_r;
- int poly_light_g = extradata.light_g + extradata.ambient_g;
- int poly_light_b = extradata.light_b + extradata.ambient_b;
- if (poly_light_r > 255) poly_light_r = 255;
- if (poly_light_g > 255) poly_light_g = 255;
- if (poly_light_b > 255) poly_light_b = 255;
- int poly_fog_r = extradata.fog_r;
- int poly_fog_g = extradata.fog_g;
- int poly_fog_b = extradata.fog_b;
-
- uint32_t* const fb = &m_fb[m_fb_page]->pix(scanline);
- float* const zb = (float*)&m_zb->pix(scanline);
-
- int* x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
- int* y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
+ uint32_t* fifo = m_3dfifo.get();
+ int index = 0;
- for (int x = extent.startx; x < extent.stopx; x++)
+ do
{
- int ibri = (int)(bri);
- int ifog = (int)(fog);
-
- if (ibri < 0) ibri = 0;
- if (ibri > 255) ibri = 255;
- if (ifog < 0) ifog = 0;
- if (ifog > 65536) ifog = 65536;
-
- int ir = (int)(r);
- int ig = (int)(g);
- int ib = (int)(b);
- int ia = (int)(a);
+ uint32_t cmd = fifo[index++];
- if (z <= zb[x])
+ if (cmd == 0x80000000 || cmd == 0x80000018)
{
- float oow = 1.0f / w;
- uint32_t color;
- int iu, iv;
- int iiv, iiu;
-
- iu = u * oow * 0.0625f;
- iv = v * oow * 0.0625f;
-
- iiu = texture_x + x_mirror_table[iu & 0x7f];
- iiv = texture_y + y_mirror_table[iv & 0x7f];
-
- color = k001006->fetch_texel(tex_page, palette_index, iiu, iiv);
-
- if (color & 0xff000000)
- {
- // texture
- int r = (color >> 16) & 0xff;
- int g = (color >> 8) & 0xff;
- int b = color & 0xff;
-
- r = ((((r * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
- g = ((((g * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
- b = ((((b * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
-
- if (r < 0) r = 0;
- if (r > 255) r = 255;
- if (g < 0) g = 0;
- if (g > 255) g = 255;
- if (b < 0) b = 0;
- if (b > 255) b = 255;
-
- fb[x] = 0xff000000 | (r << 16) | (g << 8) | b;
- zb[x] = z;
- }
- else
- {
- // gouraud color
- if (ia != 0xff)
- {
- int sr = (fb[x] >> 16) & 0xff;
- int sg = (fb[x] >> 8) & 0xff;
- int sb = fb[x] & 0xff;
-
- ir = ((ir * ia) >> 8) + ((sr * (0xff - ia)) >> 8);
- ig = ((ig * ia) >> 8) + ((sg * (0xff - ia)) >> 8);
- ib = ((ib * ia) >> 8) + ((sb * (0xff - ia)) >> 8);
- }
-
- ir = ((((ir * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
- ig = ((((ig * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
- ib = ((((ib * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
-
- if (ir < 0) ir = 0;
- if (ir > 255) ir = 255;
- if (ig < 0) ig = 0;
- if (ig > 255) ig = 255;
- if (ib < 0) ib = 0;
- if (ib > 255) ib = 255;
-
- fb[x] = 0xff000000 | (ir << 16) | (ig << 8) | ib;
- zb[x] = z;
- }
}
-
- u += du;
- v += dv;
- z += dz;
- w += dw;
- bri += dbri;
- fog += dfog;
- r += dr;
- g += dg;
- b += db;
- a += da;
+ else if ((cmd & 0xffff0000) == 0x80000000)
+ {
+ index += parse_polygon(index, cmd);
+ }
}
+ while (index < m_3dfifo_ptr);
+
+ m_3dfifo_ptr = 0;
+ wait();
}
@@ -1472,6 +687,7 @@ void k001005_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
}
+
}
@@ -1487,7 +703,6 @@ k001005_device::k001005_device(const machine_config &mconfig, const char *tag, d
, m_ram_ptr(0)
, m_fifo_read_ptr(0)
, m_fifo_write_ptr(0)
- , m_reg_far_z(0)
{
m_ram[0] = nullptr;
m_ram[1] = nullptr;
@@ -1513,7 +728,6 @@ void k001005_device::device_start()
save_item(NAME(m_ram_ptr));
save_item(NAME(m_fifo_read_ptr));
save_item(NAME(m_fifo_write_ptr));
- save_item(NAME(m_reg_far_z));
}
//-------------------------------------------------
@@ -1603,7 +817,7 @@ uint32_t k001005_device::read(address_space &space, offs_t offset, uint32_t mem_
return m_ram[0][(m_ram_ptr++) & 0x3fffff];
}
- default:
+ default:
//osd_printf_debug("%s m_r: %08X, %08X\n", machine().describe_context(), offset, mem_mask);
break;
}
@@ -1642,16 +856,6 @@ void k001005_device::write(address_space &space, offs_t offset, uint32_t data, u
m_renderer->push_data(data);
-#if LOG_POLY_FIFO
- printf("0x%08X, ", data);
- count++;
- if (count >= 8)
- {
- count = 0;
- printf("\n");
- }
-#endif
-
// !!! HACK to get past the FIFO B test (GTI Club & Thunder Hurricane) !!!
if (dsp->pc() == 0x201ee)
{
@@ -1670,39 +874,59 @@ void k001005_device::write(address_space &space, offs_t offset, uint32_t data, u
case 0x100: break;
- case 0x101: break; // viewport x and width?
- case 0x102: break; // viewport y and height?
+ case 0x101: break; // framebuffer width?
+ case 0x102: break; // framebuffer height?
- case 0x104: break; // viewport center x? (usually 0xff)
- case 0x105: break; // viewport center y? (usually 0xbf)
+ case 0x103: m_renderer->m_viewport_min_x = data & 0xffff; break;
+ case 0x104: m_renderer->m_viewport_max_x = data & 0xffff; break;
+ case 0x105: m_renderer->m_viewport_max_y = data & 0xffff; break;
+ case 0x106: m_renderer->m_viewport_min_y = data & 0xffff; break;
- case 0x108: // far Z value, 4 exponent bits?
- {
- // this register seems to hold the 4 missing exponent bits...
- m_reg_far_z = (m_reg_far_z & 0x0000ffff) | ((data & 0xf) << 16);
- m_renderer->set_param(K001005_FAR_Z, m_reg_far_z);
- break;
- }
+ case 0x107: m_renderer->m_viewport_center_x = data & 0xffff; break;
+ case 0x108: m_renderer->m_viewport_center_y = data & 0xffff; break;
case 0x109: // far Z value
{
- // the SHARC code throws away the bottom 11 bits of mantissa and the top 5 bits (to fit in a 16-bit register?)
- m_reg_far_z = (m_reg_far_z & 0xffff0000) | (data & 0xffff);
- m_renderer->set_param(K001005_FAR_Z, m_reg_far_z);
+ // the SHARC code throws away the bottom 11 bits of mantissa and the top 5 bits (to fit in a 16-bit register?)
+ m_renderer->m_far_z = u2f((data & 0xffff) << 11);
break;
}
- case 0x10a: m_renderer->set_param(K001005_LIGHT_R, data & 0xff); break;
- case 0x10b: m_renderer->set_param(K001005_LIGHT_G, data & 0xff); break;
- case 0x10c: m_renderer->set_param(K001005_LIGHT_B, data & 0xff); break;
+ case 0x10a: m_renderer->m_light_r = data & 0xff; break;
+ case 0x10b: m_renderer->m_light_g = data & 0xff; break;
+ case 0x10c: m_renderer->m_light_b = data & 0xff; break;
- case 0x10d: m_renderer->set_param(K001005_AMBIENT_R, data & 0xff); break;
- case 0x10e: m_renderer->set_param(K001005_AMBIENT_G, data & 0xff); break;
- case 0x10f: m_renderer->set_param(K001005_AMBIENT_B, data & 0xff); break;
+ case 0x10d: m_renderer->m_ambient_r = data & 0xff; break;
+ case 0x10e: m_renderer->m_ambient_g = data & 0xff; break;
+ case 0x10f: m_renderer->m_ambient_b = data & 0xff; break;
- case 0x110: m_renderer->set_param(K001005_FOG_R, data & 0xff); break;
- case 0x111: m_renderer->set_param(K001005_FOG_G, data & 0xff); break;
- case 0x112: m_renderer->set_param(K001005_FOG_B, data & 0xff); break;
+ case 0x110: m_renderer->m_fog_r = data & 0xff; break;
+ case 0x111: m_renderer->m_fog_g = data & 0xff; break;
+ case 0x112: m_renderer->m_fog_b = data & 0xff; break;
+
+ case 0x117: // linear fog start Z
+ {
+ // 4 bits exponent + 12 bits mantissa, similar to far Z value
+ // value of 0xffff is used to effectively turn off fog
+
+ // reconstruct float from 16-bit data
+ // assuming implicit exponent 1001xxxx, sign bit 0 (z-values are all positive)
+ m_renderer->m_reg_fog_start = data & 0xffff;
+ m_renderer->m_fog_start_z = u2f((0x90000 | (data & 0xffff)) << 11);
+ break;
+ }
+ case 0x118: // linear fog end Z
+ {
+ // 4 bits exponent + 12 bits mantissa, similar to far Z value
+ m_renderer->m_fog_end_z = u2f((0x90000 | (data & 0xffff)) << 11);
+ break;
+ }
+
+ case 0x119: // 1 / (end_fog - start_fog) ?
+ {
+ // 5 bits exponent + 11 bits mantissa
+ break;
+ }
case 0x11a: