diff options
author | Olivier Galibert <galibert@pobox.com> | 2010-04-03 09:53:40 +0000 |
---|---|---|
committer | Olivier Galibert <galibert@pobox.com> | 2010-04-03 09:53:40 +0000 |
commit | 7eddf047eee3cc4e45d2ee05b8757fd992bf0051 (patch) | |
tree | da87c6ebb33f2f9279c28cdbda0c3cb08d3497b7 | |
parent | d0b704dbb778cf3ce778f99ce7e8b67c11ec6db0 (diff) |
namcos23: First stab at z-sorting [O. Galibert]
-rw-r--r-- | src/mame/drivers/namcos23.c | 186 |
1 files changed, 129 insertions, 57 deletions
diff --git a/src/mame/drivers/namcos23.c b/src/mame/drivers/namcos23.c index f1266bb47b6..624ebf10e99 100644 --- a/src/mame/drivers/namcos23.c +++ b/src/mame/drivers/namcos23.c @@ -1160,6 +1160,7 @@ Notes: */ #include "emu.h" +#include <float.h> #include "video/poly.h" #include "cpu/mips/mips3.h" #include "cpu/h83002/h8.h" @@ -1619,24 +1620,40 @@ static READ32_HANDLER( s23_unk_status_r ) // 3D hardware, to throw at least in part in video/namcos23.c +enum { MODEL, FLUSH }; + struct namcos23_render_entry { - UINT16 model; - INT16 m[9]; - INT32 v[3]; - float scaling; + int type; + + union { + struct { + UINT16 model; + INT16 m[9]; + INT32 v[3]; + float scaling; + } model; + }; }; -enum { RENDER_MAX_ENTRIES = 10000 }; -static namcos23_render_entry render_entries[2][RENDER_MAX_ENTRIES]; -static int render_count[2], render_cur; -static poly_manager *polymgr; -static float wbuffer[480][640]; - struct namcos23_render_data { const pen_t *pens; UINT32 (*texture_lookup)(const pen_t *pens, float x, float y); }; +struct namcos23_poly_entry { + namcos23_render_data rd; + float zkey; + int vertex_count; + poly_vertex pv[16]; +}; + +enum { RENDER_MAX_ENTRIES = 1000, POLY_MAX_ENTRIES = 10000 }; +static namcos23_render_entry render_entries[2][RENDER_MAX_ENTRIES]; +static namcos23_poly_entry render_polys[POLY_MAX_ENTRIES]; +static int render_poly_order[POLY_MAX_ENTRIES]; +static int render_count[2], render_cur, render_poly_count; +static poly_manager *polymgr; + static inline INT32 u32_to_s24(UINT32 v) { return v & 0x800000 ? v | 0xff000000 : v & 0xffffff; @@ -1689,21 +1706,17 @@ static void render_scanline(void *dest, INT32 scanline, const poly_extent *exten float dl = extent->param[3].dpdx; bitmap_t *bitmap = (bitmap_t *)dest; UINT32 *img = BITMAP_ADDR32(bitmap, scanline, extent->startx); - float *wbuf = &wbuffer[scanline][extent->startx]; for(int x = extent->startx; x < extent->stopx; x++) { - if(w > *wbuf) { - *wbuf = w; - float z = w ? 1/w : 0; - UINT32 pcol = rd->texture_lookup(rd->pens, u*z, v*z); - float ll = l*z; - *img = (light(pcol >> 16, ll) << 16) | (light(pcol >> 8, ll) << 8) | light(pcol, ll); - } + float z = w ? 1/w : 0; + UINT32 pcol = rd->texture_lookup(rd->pens, u*z, v*z); + float ll = l*z; + *img = (light(pcol >> 16, ll) << 16) | (light(pcol >> 8, ll) << 8) | light(pcol, ll); + w += dw; u += du; v += dv; l += dl; - wbuf++; img++; } } @@ -1847,21 +1860,35 @@ static void p3d_render(const UINT16 *p, int size, bool use_scaling) const INT32 *v = p3d_getv(p[2]); namcos23_render_entry *re = render_entries[render_cur] + render_count[render_cur]; - re->model = p[0]; - re->scaling = use_scaling ? scaling / 16384.0 : 1.0; - memcpy(re->m, m, sizeof(re->m)); - memcpy(re->v, v, sizeof(re->v)); + re->type = MODEL; + re->model.model = p[0]; + re->model.scaling = use_scaling ? scaling / 16384.0 : 1.0; + memcpy(re->model.m, m, sizeof(re->model.m)); + memcpy(re->model.v, v, sizeof(re->model.v)); if(0) fprintf(stderr, "Render %04x (%f %f %f %f %f %f %f %f %f) (%f %f %f)\n", - re->model, - re->m[0]/16384.0, re->m[1]/16384.0, re->m[2]/16384.0, - re->m[3]/16384.0, re->m[4]/16384.0, re->m[5]/16384.0, - re->m[6]/16384.0, re->m[7]/16384.0, re->m[8]/16384.0, - re->v[0]/16384.0, re->v[1]/16384.0, re->v[2]/16384.0); + re->model.model, + re->model.m[0]/16384.0, re->model.m[1]/16384.0, re->model.m[2]/16384.0, + re->model.m[3]/16384.0, re->model.m[4]/16384.0, re->model.m[5]/16384.0, + re->model.m[6]/16384.0, re->model.m[7]/16384.0, re->model.m[8]/16384.0, + re->model.v[0]/16384.0, re->model.v[1]/16384.0, re->model.v[2]/16384.0); render_count[render_cur]++; } + +static void p3d_flush(const UINT16 *p, int size) +{ + if(size != 0) { + logerror("WARNING: p3d_flush with size %d\n", size); + return; + } + + namcos23_render_entry *re = render_entries[render_cur] + render_count[render_cur]; + re->type = FLUSH; + render_count[render_cur]++; +} + static void p3d_dma(const address_space *space, UINT32 adr, UINT32 size) { adr &= 0x1fffffff; @@ -1901,6 +1928,7 @@ static void p3d_dma(const address_space *space, UINT32 adr, UINT32 size) case 0x4400: p3d_scaling_set(buffer, psize); break; case 0x8000: p3d_render(buffer, psize, false); break; case 0x8080: p3d_render(buffer, psize, true); break; + case 0xc000: p3d_flush(buffer, psize); break; default: { if(0) { logerror("p3d - [%04x] %04x", h1, h); @@ -1943,16 +1971,16 @@ static WRITE32_HANDLER( p3d_w) static void render_apply_transform(INT32 xi, INT32 yi, INT32 zi, const namcos23_render_entry *re, poly_vertex &pv) { - pv.x = (INT32((re->m[0]*INT64(xi) + re->m[3]*INT64(yi) + re->m[6]*INT64(zi)) >> 14)*re->scaling + re->v[0])/16384.0; - pv.y = (INT32((re->m[1]*INT64(xi) + re->m[4]*INT64(yi) + re->m[7]*INT64(zi)) >> 14)*re->scaling + re->v[1])/16384.0; - pv.p[0] = (INT32((re->m[2]*INT64(xi) + re->m[5]*INT64(yi) + re->m[8]*INT64(zi)) >> 14)*re->scaling + re->v[2])/16384.0; + pv.x = (INT32((re->model.m[0]*INT64(xi) + re->model.m[3]*INT64(yi) + re->model.m[6]*INT64(zi)) >> 14)*re->model.scaling + re->model.v[0])/16384.0; + pv.y = (INT32((re->model.m[1]*INT64(xi) + re->model.m[4]*INT64(yi) + re->model.m[7]*INT64(zi)) >> 14)*re->model.scaling + re->model.v[1])/16384.0; + pv.p[0] = (INT32((re->model.m[2]*INT64(xi) + re->model.m[5]*INT64(yi) + re->model.m[8]*INT64(zi)) >> 14)*re->model.scaling + re->model.v[2])/16384.0; } static void render_apply_matrot(INT32 xi, INT32 yi, INT32 zi, const namcos23_render_entry *re, INT32 &x, INT32 &y, INT32 &z) { - x = (re->m[0]*xi + re->m[3]*yi + re->m[6]*zi) >> 14; - y = (re->m[1]*xi + re->m[4]*yi + re->m[7]*zi) >> 14; - z = (re->m[2]*xi + re->m[5]*yi + re->m[8]*zi) >> 14; + x = (re->model.m[0]*xi + re->model.m[3]*yi + re->model.m[6]*zi) >> 14; + y = (re->model.m[1]*xi + re->model.m[4]*yi + re->model.m[7]*zi) >> 14; + z = (re->model.m[2]*xi + re->model.m[5]*yi + re->model.m[8]*zi) >> 14; } static void render_project(poly_vertex &pv) @@ -1968,18 +1996,16 @@ static void render_project(poly_vertex &pv) pv.p[0] = w; } -static void render_one_model(running_machine *machine, const namcos23_render_entry *re, bitmap_t *bitmap) +static void render_one_model(running_machine *machine, const namcos23_render_entry *re) { - rectangle scissor = { 0, 639, 0, 479 }; - - UINT32 adr = ptrom[re->model]; + UINT32 adr = ptrom[re->model.model]; if(adr >= ptrom_limit) { - logerror("WARNING: model %04x base address %08x out-of-bounds - pointram?\n", re->model, adr); + logerror("WARNING: model %04x base address %08x out-of-bounds - pointram?\n", re->model.model, adr); return; } while(adr < ptrom_limit) { - poly_vertex pv[15], pvc[8]; + poly_vertex pv[15]; UINT32 type = ptrom[adr++]; UINT32 h = ptrom[adr++]; @@ -2003,6 +2029,9 @@ static void render_one_model(running_machine *machine, const namcos23_render_ent } else light = ptrom[adr++]; + float minz = FLT_MAX; + float maxz = FLT_MIN; + for(int i=0; i<ne; i++) { UINT32 v1 = ptrom[adr++]; UINT32 v2 = ptrom[adr++]; @@ -2012,6 +2041,11 @@ static void render_one_model(running_machine *machine, const namcos23_render_ent pv[i].p[1] = (((v1 >> 20) & 0xf00) | ((v2 >> 24 & 0xff))) + 0.5; pv[i].p[2] = (((v1 >> 16) & 0xf00) | ((v3 >> 24 & 0xff))) + 0.5 + tbase; + if(pv[i].p[0] > maxz) + maxz = pv[i].p[0]; + if(pv[i].p[0] < minz) + minz = pv[i].p[0]; + switch(lmode) { case 0: case 1: pv[i].p[3] = ((light >> (8*(3-i))) & 0xff) / 64.0; @@ -2038,21 +2072,22 @@ static void render_one_model(running_machine *machine, const namcos23_render_ent } } - int cv = poly_zclip_if_less(ne, pv, pvc, 4, 0.0001); + namcos23_poly_entry *p = render_polys + render_poly_count; + + p->vertex_count = poly_zclip_if_less(ne, pv, p->pv, 4, 0.0001); - if(cv >= 3) { - for(int i=0; i<cv; i++) { - render_project(pvc[i]); - float w = pvc[i].p[0]; - pvc[i].p[1] *= w; - pvc[i].p[2] *= w; - pvc[i].p[3] *= w; + if(p->vertex_count >= 3) { + for(int i=0; i<p->vertex_count; i++) { + render_project(p->pv[i]); + float w = p->pv[i].p[0]; + p->pv[i].p[1] *= w; + p->pv[i].p[2] *= w; + p->pv[i].p[3] *= w; } - namcos23_render_data *rd = (namcos23_render_data *)poly_get_extra_data(polymgr); - rd->texture_lookup = texture_lookup_nocache_point; - rd->pens = machine->pens + (color << 8); - - poly_render_triangle_fan(polymgr, bitmap, &scissor, render_scanline, 4, cv, pvc); + p->zkey = 0.5*(minz+maxz); + p->rd.texture_lookup = texture_lookup_nocache_point; + p->rd.pens = machine->pens + (color << 8); + render_poly_count++; } if(type & 0x000010000) @@ -2060,13 +2095,50 @@ static void render_one_model(running_machine *machine, const namcos23_render_ent } } -static void render_run(running_machine *machine, bitmap_t *bitmap) +static int render_poly_compare(const void *i1, const void *i2) { - memset(wbuffer, 0, sizeof(wbuffer)); + const namcos23_poly_entry *p1 = render_polys + *(const int *)i1; + const namcos23_poly_entry *p2 = render_polys + *(const int *)i2; + return p1->zkey < p2->zkey ? 1 : p1->zkey > p2->zkey ? -1 : 0; +} + +static void render_flush(running_machine *machine, bitmap_t *bitmap) +{ + if(!render_poly_count) + return; + + for(int i=0; i<render_poly_count; i++) + render_poly_order[i] = i; + + qsort(render_poly_order, render_poly_count, sizeof(int), render_poly_compare); + const static rectangle scissor = { 0, 639, 0, 479 }; + + for(int i=0; i<render_poly_count; i++) { + const namcos23_poly_entry *p = render_polys + render_poly_order[i]; + namcos23_render_data *rd = (namcos23_render_data *)poly_get_extra_data(polymgr); + *rd = p->rd; + poly_render_triangle_fan(polymgr, bitmap, &scissor, render_scanline, 4, p->vertex_count, p->pv); + } + render_poly_count = 0; +} + +static void render_run(running_machine *machine, bitmap_t *bitmap) +{ + render_poly_count = 0; const namcos23_render_entry *re = render_entries[!render_cur]; - for(int i=0; i<render_count[!render_cur]; i++) - render_one_model(machine, re++, bitmap); + for(int i=0; i<render_count[!render_cur]; i++) { + switch(re->type) { + case MODEL: + render_one_model(machine, re); + break; + case FLUSH: + render_flush(machine, bitmap); + break; + } + re++; + } + render_flush(machine, bitmap); poly_wait(polymgr, "render_run"); } |