summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ville Linde <villelin@mamedev.org>2014-10-19 17:16:11 +0000
committer Ville Linde <villelin@mamedev.org>2014-10-19 17:16:11 +0000
commit167e6579be68c42ec5da55adaada19a628a0cd73 (patch)
treed0df568a44e886e8fad51c9ee9c456c17628be45
parente709ddbc33a53fcdef51108daa81f4d92369ddf6 (diff)
model3: More rendering improvements [Ville Linde]
- Draw transparent triangles in a separate pass - Implemented viewport priority
-rw-r--r--src/mame/drivers/model3.c8
-rw-r--r--src/mame/includes/model3.h9
-rw-r--r--src/mame/video/model3.c293
3 files changed, 231 insertions, 79 deletions
diff --git a/src/mame/drivers/model3.c b/src/mame/drivers/model3.c
index b22b366626a..fcf36e68424 100644
--- a/src/mame/drivers/model3.c
+++ b/src/mame/drivers/model3.c
@@ -26,11 +26,11 @@
vs29815 - massive memory trashing and page faults
vs2 - works
- harley - works, wrong textures in many places, correct textures uploaded when the game ends
+ harley - works
skichamp - boots after skipping the drive board errors, massive slowdowns
srally2/sraly2dx - works
von2/von254g - works
- fvipers2 - waiting for decrementer (same code as eca)
+ fvipers2 - crashes after player selection
vs298 - works, hangs with an onscreen error code
vs299/vs2v991 - works
oceanhun - same as daytona2
@@ -6005,8 +6005,8 @@ GAME( 1999, vs299, vs2v991, model3_20, model3, model3_state, vs299, ROT0
/* Model 3 Step 2.1 */
GAME( 1998, daytona2, 0, model3_21, daytona2, model3_state, daytona2, ROT0, "Sega", "Daytona USA 2 (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, dayto2pe, 0, model3_21, daytona2, model3_state, dayto2pe, ROT0, "Sega", "Daytona USA 2 Power Edition", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
-GAME( 1998, dirtdvls, 0, model3_21, model3, model3_state, dirtdvls, ROT0, "Sega", "Dirt Devils (set 1) (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
-GAME( 1998, dirtdvlsa, dirtdvls, model3_21, model3, model3_state, dirtdvls, ROT0, "Sega", "Dirt Devils (set 2) (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
+GAME( 1998, dirtdvls, 0, model3_21, scud, model3_state, dirtdvls, ROT0, "Sega", "Dirt Devils (set 1) (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
+GAME( 1998, dirtdvlsa, dirtdvls, model3_21, scud, model3_state, dirtdvls, ROT0, "Sega", "Dirt Devils (set 2) (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, swtrilgy, 0, model3_21, swtrilgy, model3_state, swtrilgy, ROT0, "Sega / LucasArts", "Star Wars Trilogy (Revision A)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, swtrilgya, swtrilgy, model3_21, swtrilgy, model3_state, swtrilga, ROT0, "Sega / LucasArts", "Star Wars Trilogy", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1998, spikeout, 0, model3_21, model3, model3_state, spikeout, ROT0, "Sega", "Spikeout (Revision C)", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
diff --git a/src/mame/includes/model3.h b/src/mame/includes/model3.h
index 895daefef9b..1473a9033d6 100644
--- a/src/mame/includes/model3.h
+++ b/src/mame/includes/model3.h
@@ -56,7 +56,6 @@ struct m3_triangle
cached_texture *texture;
int param;
int transparency;
- int intensity;
int color;
};
@@ -181,6 +180,12 @@ public:
cached_texture *m_texcache[2][1024/32][2048/32];
model3_renderer *m_renderer;
+ m3_triangle* m_tri_buffer;
+ m3_triangle* m_tri_alpha_buffer;
+ int m_tri_buffer_ptr;
+ int m_tri_alpha_buffer_ptr;
+ int m_viewport_tri_index[4];
+ int m_viewport_tri_alpha_index[4];
DECLARE_READ32_MEMBER(rtc72421_r);
DECLARE_WRITE32_MEMBER(rtc72421_w);
@@ -292,6 +297,8 @@ public:
TILE_GET_INFO_MEMBER(tile_info_layer1_8bit);
TILE_GET_INFO_MEMBER(tile_info_layer2_8bit);
TILE_GET_INFO_MEMBER(tile_info_layer3_8bit);
+ void reset_triangle_buffers();
+ m3_triangle* push_triangle(bool alpha);
void draw_layers(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int bitdepth, int sx, int sy);
void draw_3d_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect);
diff --git a/src/mame/video/model3.c b/src/mame/video/model3.c
index c31dfbac2fd..c9e995046ba 100644
--- a/src/mame/video/model3.c
+++ b/src/mame/video/model3.c
@@ -11,6 +11,9 @@
#define TRI_PARAM_TEXTURE_ENABLE 0x8
#define TRI_PARAM_ALPHA_TEST 0x10
+#define TRI_BUFFER_SIZE 35000
+#define TRI_ALPHA_BUFFER_SIZE 15000
+
struct model3_polydata
{
cached_texture *texture;
@@ -24,23 +27,25 @@ class model3_renderer : public poly_manager<float, model3_polydata, 6, 50000>
{
public:
model3_renderer(model3_state &state, int width, int height)
- : poly_manager<float, model3_polydata, 6, 50000>(state.machine())//, m_state(state)
+ : poly_manager<float, model3_polydata, 6, 50000>(state.machine())
{
m_fb = auto_bitmap_rgb32_alloc(state.machine(), width, height);
m_zb = auto_bitmap_ind32_alloc(state.machine(), width, height);
}
void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect);
- void draw_triangle(const m3_triangle* tri);
- void clear_buffers();
+ void draw_opaque_triangles(const m3_triangle* tris, int num_tris);
+ void draw_alpha_triangles(const m3_triangle* tris, int num_tris);
+ void clear_fb();
+ void clear_zb();
void draw_scanline_solid(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
void draw_scanline_tex(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
- void draw_scanline_contour(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
+ void draw_scanline_tex_contour(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
void draw_scanline_tex_trans(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
void draw_scanline_tex_alpha(INT32 scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
+ void wait_for_polys();
private:
- //model3_state &m_state;
bitmap_rgb32 *m_fb;
bitmap_ind32 *m_zb;
};
@@ -153,6 +158,9 @@ void model3_state::video_start()
m_renderer = auto_alloc(machine(), model3_renderer(*this, width, height));
+ m_tri_buffer = auto_alloc_array_clear(machine(), m3_triangle, TRI_BUFFER_SIZE);
+ m_tri_alpha_buffer = auto_alloc_array_clear(machine(), m3_triangle, TRI_ALPHA_BUFFER_SIZE);
+
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model3_state::model3_exit), this));
m_m3_char_ram = auto_alloc_array_clear(machine(), UINT64, 0x100000/8);
@@ -1007,9 +1015,42 @@ void model3_state::real3d_display_list_end()
}
m_texture_fifo_pos = 0;
- m_renderer->clear_buffers();
+ m_renderer->clear_fb();
+ reset_triangle_buffers();
real3d_traverse_display_list();
+
+ /*
+ m_renderer->draw_opaque_triangles(m_tri_buffer, m_tri_buffer_ptr);
+ m_renderer->draw_alpha_triangles(m_tri_alpha_buffer, m_tri_alpha_buffer_ptr);
+
+ m_renderer->wait_for_polys();
+ */
+
+ for (int i=0; i < 4; i++)
+ {
+ int ticount, tiacount;
+ int ti = m_viewport_tri_index[i];
+ int tia = m_viewport_tri_alpha_index[i];
+ if (i < 3)
+ {
+ ticount = m_viewport_tri_index[i+1] - ti;
+ tiacount = m_viewport_tri_alpha_index[i+1] - tia;
+ }
+ else
+ {
+ ticount = m_tri_buffer_ptr - ti;
+ tiacount = m_tri_alpha_buffer_ptr - tia;
+ }
+
+ if (ticount > 0 || tiacount > 0)
+ {
+ m_renderer->clear_zb();
+ m_renderer->draw_opaque_triangles(&m_tri_buffer[ti], ticount);
+ m_renderer->draw_alpha_triangles(&m_tri_alpha_buffer[tia], tiacount);
+ m_renderer->wait_for_polys();
+ }
+ }
}
void model3_state::real3d_display_list1_dma(UINT32 src, UINT32 dst, int length, int byteswap)
@@ -1273,6 +1314,42 @@ static int clip_polygon(const m3_clip_vertex *v, int num_vertices, m3_plane cp,
return clip_verts;
}
+void model3_state::reset_triangle_buffers()
+{
+ m_tri_buffer_ptr = 0;
+ m_tri_alpha_buffer_ptr = 0;
+}
+
+m3_triangle *model3_state::push_triangle(bool alpha)
+{
+ if (!alpha)
+ {
+ int i = m_tri_buffer_ptr;
+
+ if (m_tri_buffer_ptr >= TRI_BUFFER_SIZE)
+ {
+ return NULL;
+ //fatalerror("push_triangle: tri buffer max exceeded");
+ }
+
+ m_tri_buffer_ptr++;
+ return &m_tri_buffer[i];
+ }
+ else
+ {
+ int i = m_tri_alpha_buffer_ptr;
+
+ if (m_tri_alpha_buffer_ptr >= TRI_ALPHA_BUFFER_SIZE)
+ {
+ return NULL;
+ //fatalerror("push_triangle: tri alpha buffer max exceeded");
+ }
+
+ m_tri_alpha_buffer_ptr++;
+ return &m_tri_alpha_buffer[i];
+ }
+}
+
void model3_state::draw_model(UINT32 addr)
{
// Polygon RAM is mapped to the low 4MB of VROM
@@ -1311,8 +1388,6 @@ void model3_state::draw_model(UINT32 addr)
VECTOR3 normal;
VECTOR3 sn;
VECTOR p[4];
- m3_triangle tri;
- float dot;
int polygon_transparency;
for (i = 0; i < 7; i++)
@@ -1429,7 +1504,7 @@ void model3_state::draw_model(UINT32 addr)
float intensity;
if ((header[6] & 0x10000) == 0)
{
- dot = dot_product3(n, m_parallel_light);
+ float dot = dot_product3(n, m_parallel_light);
intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 255.0f;
if (intensity > 255.0f)
{
@@ -1500,23 +1575,28 @@ void model3_state::draw_model(UINT32 addr)
}
for (i=2; i < num_vertices; i++)
- {
- memcpy(&tri.v[0], &clip_vert[0], sizeof(m3_clip_vertex));
- memcpy(&tri.v[1], &clip_vert[i-1], sizeof(m3_clip_vertex));
- memcpy(&tri.v[2], &clip_vert[i], sizeof(m3_clip_vertex));
-
- tri.texture = texture;
- tri.transparency = polygon_transparency;
- tri.color = color;
-
- tri.param = 0;
- tri.param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0;
- tri.param |= (header[6] & 0x00000400) ? TRI_PARAM_TEXTURE_ENABLE : 0;
- tri.param |= (header[2] & 0x2) ? TRI_PARAM_TEXTURE_MIRROR_U : 0;
- tri.param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0;
- tri.param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0;
-
- m_renderer->draw_triangle(&tri);
+ {
+ bool alpha = (header[6] & 0x1) || (header[6] & 0x80000000); // put to alpha buffer if there's any transparency involved
+ m3_triangle* tri = push_triangle(alpha);
+
+ // bail out if tri buffer is maxed out (happens during harley boot)
+ if (!tri)
+ return;
+
+ memcpy(&tri->v[0], &clip_vert[0], sizeof(m3_clip_vertex));
+ memcpy(&tri->v[1], &clip_vert[i-1], sizeof(m3_clip_vertex));
+ memcpy(&tri->v[2], &clip_vert[i], sizeof(m3_clip_vertex));
+
+ tri->texture = texture;
+ tri->transparency = polygon_transparency;
+ tri->color = color;
+
+ tri->param = 0;
+ tri->param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0;
+ tri->param |= (header[6] & 0x00000400) ? TRI_PARAM_TEXTURE_ENABLE : 0;
+ tri->param |= (header[2] & 0x2) ? TRI_PARAM_TEXTURE_MIRROR_U : 0;
+ tri->param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0;
+ tri->param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0;
}
}
}
@@ -1714,9 +1794,9 @@ void model3_state::draw_viewport(int pri, UINT32 address)
/* TODO: where does node[23] point to ? LOD table ? */
/* set lighting parameters */
- m_parallel_light[0] = -*(float *)&node[5];
+ m_parallel_light[0] = *(float *)&node[5];
m_parallel_light[1] = *(float *)&node[6];
- m_parallel_light[2] = *(float *)&node[4];
+ m_parallel_light[2] = -*(float *)&node[4];
m_parallel_light_intensity = *(float *)&node[7];
m_ambient_light_intensity = (UINT8)(node[36] >> 8) / 256.0f;
@@ -1735,7 +1815,11 @@ void model3_state::real3d_traverse_display_list()
m_list_depth = 0;
for (int pri = 0; pri < 4; pri++)
+ {
+ m_viewport_tri_index[pri] = m_tri_buffer_ptr;
+ m_viewport_tri_alpha_index[pri] = m_tri_alpha_buffer_ptr;
draw_viewport(pri, 0x800000);
+ }
}
void model3_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -1757,7 +1841,7 @@ void model3_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
-void model3_renderer::clear_buffers()
+void model3_renderer::clear_fb()
{
rectangle cliprect;
cliprect.min_x = 0;
@@ -1766,12 +1850,26 @@ void model3_renderer::clear_buffers()
cliprect.max_y = 383;
m_fb->fill(0x00000000, cliprect);
+}
+void model3_renderer::clear_zb()
+{
+ rectangle cliprect;
+ cliprect.min_x = 0;
+ cliprect.min_y = 0;
+ cliprect.max_x = 495;
+ cliprect.max_y = 383;
+
float zvalue = 10000000000.0f;
m_zb->fill(*(int*)&zvalue, cliprect);
}
-void model3_renderer::draw_triangle(const m3_triangle *tri)
+void model3_renderer::wait_for_polys()
+{
+ wait();
+}
+
+void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tris)
{
rectangle cliprect;
cliprect.min_x = 0;
@@ -1779,62 +1877,111 @@ void model3_renderer::draw_triangle(const m3_triangle *tri)
cliprect.max_x = 495;
cliprect.max_y = 383;
+// printf("draw opaque: %d\n", num_tris);
+
vertex_t v[3];
- if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
+ for (int t=0; t < num_tris; t++)
{
- for (int i=0; i < 3; i++)
- {
- v[i].x = tri->v[i].x;
- v[i].y = tri->v[i].y;
- v[i].p[0] = tri->v[i].z;
- v[i].p[1] = 1.0f / tri->v[i].z;
- v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering
- v[i].p[3] = tri->v[i].v * 256.0f;
- v[i].p[4] = tri->v[i].i;
- }
+ const m3_triangle* tri = &tris[t];
- model3_polydata &extra = object_data_alloc();
- extra.texture = tri->texture;
- extra.transparency = tri->transparency;
- extra.intensity = tri->intensity;
- extra.texture_param = tri->param;
-
- render_delegate rd;
- if (tri->param & TRI_PARAM_ALPHA_TEST)
- {
- rd = render_delegate(FUNC(model3_renderer::draw_scanline_contour), this);
- }
- else if (extra.texture->alpha == 0xff)
+ if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
{
- if (tri->transparency >= 32)
- rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex), this);
- else
- rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_trans), this);
+ for (int i=0; i < 3; i++)
+ {
+ v[i].x = tri->v[i].x;
+ v[i].y = tri->v[i].y;
+ v[i].p[0] = tri->v[i].z;
+ v[i].p[1] = 1.0f / tri->v[i].z;
+ v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering
+ v[i].p[3] = tri->v[i].v * 256.0f;
+ v[i].p[4] = tri->v[i].i;
+ }
+
+ model3_polydata &extra = object_data_alloc();
+ extra.texture = tri->texture;
+ extra.transparency = tri->transparency;
+ extra.texture_param = tri->param;
+
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex), this), 5, v[0], v[1], v[2]);
}
else
{
- rd = render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this);
- }
+ for (int i=0; i < 3; i++)
+ {
+ v[i].x = tri->v[i].x;
+ v[i].y = tri->v[i].y;
+ v[i].p[0] = tri->v[i].z;
+ v[i].p[1] = tri->v[i].i;
+ }
+
+ model3_polydata &extra = object_data_alloc();
+ extra.color = tri->color;
- render_triangle(cliprect, rd, 5, v[0], v[1], v[2]);
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]);
+ }
}
- else
+}
+
+void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris)
+{
+ rectangle cliprect;
+ cliprect.min_x = 0;
+ cliprect.min_y = 0;
+ cliprect.max_x = 495;
+ cliprect.max_y = 383;
+
+// printf("draw alpha: %d\n", num_tris);
+
+ vertex_t v[3];
+
+ for (int t=num_tris-1; t >= 0; t--)
{
- for (int i=0; i < 3; i++)
+ const m3_triangle* tri = &tris[t];
+
+ if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
{
- v[i].x = tri->v[i].x;
- v[i].y = tri->v[i].y;
- v[i].p[0] = tri->v[i].z;
- v[i].p[1] = tri->v[i].i;
- }
+ for (int i=0; i < 3; i++)
+ {
+ v[i].x = tri->v[i].x;
+ v[i].y = tri->v[i].y;
+ v[i].p[0] = tri->v[i].z;
+ v[i].p[1] = 1.0f / tri->v[i].z;
+ v[i].p[2] = tri->v[i].u * 256.0f; // 8 bits of subtexel precision for bilinear filtering
+ v[i].p[3] = tri->v[i].v * 256.0f;
+ v[i].p[4] = tri->v[i].i;
+ }
+
+ model3_polydata &extra = object_data_alloc();
+ extra.texture = tri->texture;
+ extra.transparency = tri->transparency;
+ extra.texture_param = tri->param;
- model3_polydata &extra = object_data_alloc();
+ if (tri->param & TRI_PARAM_ALPHA_TEST)
+ {
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_contour), this), 5, v[0], v[1], v[2]);
+ }
+ else
+ {
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_tex_alpha), this), 5, v[0], v[1], v[2]);
+ }
+ }
+ else
+ {
+ for (int i=0; i < 3; i++)
+ {
+ v[i].x = tri->v[i].x;
+ v[i].y = tri->v[i].y;
+ v[i].p[0] = tri->v[i].z;
+ v[i].p[1] = tri->v[i].i;
+ }
- extra.intensity = tri->intensity;
- extra.color = tri->color;
+ model3_polydata &extra = object_data_alloc();
+ extra.color = tri->color;
- render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]);
+ // TODO: scanline renderer for solid /w transparency
+ render_triangle(cliprect, render_delegate(FUNC(model3_renderer::draw_scanline_solid), this), 2, v[0], v[1], v[2]);
+ }
}
}
@@ -1964,7 +2111,7 @@ void model3_renderer::draw_scanline_tex(INT32 scanline, const extent_t &extent,
}
}
-void model3_renderer::draw_scanline_contour(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
+void model3_renderer::draw_scanline_tex_contour(INT32 scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
{
UINT32 *fb = &m_fb->pix32(scanline);
float *zb = (float*)&m_zb->pix32(scanline);
@@ -2068,7 +2215,6 @@ void model3_renderer::draw_scanline_tex_trans(INT32 scanline, const extent_t &ex
b += ((orig & 0x000000ff) * desttrans) >> 5;
fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
- zb[x] = z;
}
ooz += dooz;
@@ -2131,7 +2277,6 @@ void model3_renderer::draw_scanline_tex_alpha(INT32 scanline, const extent_t &ex
b += ((orig & 0x000000ff) * minalpha) >> 8;
fb[x] = 0xff000000 | (r & 0xff0000) | (g & 0xff00) | (b & 0xff);
- zb[x] = z;
}
}