summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2026-04-27 23:58:03 +0200
committer hap <happppp@users.noreply.github.com>2026-04-27 23:58:22 +0200
commit032b35e2dcb9eff47aaf01bfb134ae44af0762ca (patch)
tree9a0e9ab43c0392f87f4c4e5557a8c6c9b0b6f5a3
parentbd41899f978566e8320a497e582a3ee70b23eaa2 (diff)
namcos21_c67: small improvement to sprite layer 0 priority
-rw-r--r--src/mame/namco/namcos21_3d.cpp31
-rw-r--r--src/mame/namco/namcos21_3d.h4
-rw-r--r--src/mame/namco/namcos21_c67.cpp105
3 files changed, 84 insertions, 56 deletions
diff --git a/src/mame/namco/namcos21_3d.cpp b/src/mame/namco/namcos21_3d.cpp
index fdb15b8a8f0..0ad76bd087f 100644
--- a/src/mame/namco/namcos21_3d.cpp
+++ b/src/mame/namco/namcos21_3d.cpp
@@ -127,12 +127,12 @@ void namcos21_3d_device::renderscanline_flat(const edge *e1, const edge *e2, int
int depth = 0;
if (m_depth_reverse)
{
- depth = (zz >> m_zz_shift)*m_zzmult;
+ depth = (zz >> m_zz_shift) * m_zzmult;
pen += depth;
}
else
{
- depth = (zz >> m_zz_shift)*m_zzmult;
+ depth = (zz >> m_zz_shift) * m_zzmult;
pen -= depth;
}
}
@@ -267,26 +267,17 @@ void namcos21_3d_device::blit_single_quad(int sx[4], int sy[4], int zcode[4], u1
color = base | (color & 0xff);
}
- n21_vertex a, b, c, d;
+ n21_vertex v[4];
- a.x = sx[0];
- a.y = sy[0];
- a.z = zcode[0];
-
- b.x = sx[1];
- b.y = sy[1];
- b.z = zcode[1];
-
- c.x = sx[2];
- c.y = sy[2];
- c.z = zcode[2];
-
- d.x = sx[3];
- d.y = sy[3];
- d.z = zcode[3];
+ for (int i = 0; i < 4; i++)
+ {
+ v[i].x = sx[i];
+ v[i].y = sy[i];
+ v[i].z = zcode[i] & 0x7fff;
+ }
- rendertri(&a, &b, &c, color, depthcueenable);
- rendertri(&c, &d, &a, color, depthcueenable);
+ rendertri(&v[0], &v[1], &v[2], color, depthcueenable);
+ rendertri(&v[2], &v[3], &v[0], color, depthcueenable);
}
void namcos21_3d_device::draw_direct_quad(const u16 *source, u16 color)
diff --git a/src/mame/namco/namcos21_3d.h b/src/mame/namco/namcos21_3d.h
index dad4f59cc60..239aa139283 100644
--- a/src/mame/namco/namcos21_3d.h
+++ b/src/mame/namco/namcos21_3d.h
@@ -22,8 +22,12 @@ public:
m_framebuffer_size_in_bytes = sizeof(u16) * m_poly_frame_width * m_poly_frame_height;
}
+ int width() { return m_poly_frame_width; }
+ int height() { return m_poly_frame_height; }
+
void copy_visible_poly_framebuffer(bitmap_ind16 &bitmap, const rectangle &cliprect, int zlo, int zhi);
void swap_and_clear_poly_framebuffer();
+ u16 *get_visible_zbuffer() { return m_mpPolyFrameBufferZ2.get(); }
void draw_direct_quad(const u16 *source, u16 color);
void draw_quads(const u16 *source, const u8 *pointram, const u32 ptram_size, u32 quad_idx);
diff --git a/src/mame/namco/namcos21_c67.cpp b/src/mame/namco/namcos21_c67.cpp
index 20814fdbb97..2afd8167a50 100644
--- a/src/mame/namco/namcos21_c67.cpp
+++ b/src/mame/namco/namcos21_c67.cpp
@@ -8,18 +8,15 @@ TODO:
- lamp/vibration outputs, from MCU? (particularly starblad);
- verify DSP clocks, they should be 40MHz, currently underclocked on purpose on MAME, otherwise polygons
may disappear on some frames (try playing starblad until after the asteroids), tightening quantum by
- a factor of 40/24 does not fix it, actually it also happens when underclocked, but less;
+ a factor of 40/24 does not fix it (actually it also happens when underclocked, but less);
- verify video timing, pixel clock is from 38.76922?;
-- verify audiocpu irq frequency;
-- is m_layer0_pivot software-controlled and if so, where? (solvalou sprite layer 0 is further back than
- starblad and cybsled);
+- mix_layer0_sprites can be improved when namcos21_3d_device removes the z-buffer, there are currently
+ glitches in cybsled, eg. missile pickups behind pillars;
- wrong global sprite layer offsets in service mode for all games except aircomb, it's fine in-game though;
- aircomb: z-fighting issue on attract mode with the plane renders (after the first title screen),
and on pilot parachuting with a time over;
- aircomb: missing background on attract mode ranking screen (masking? cfr. shared/namco_c355spr.cpp);
- aircomb: bad sprite colors on debriefing medal screen;
-- cybsled: sprite priority issues with explosions, and eg. missile pick-ups, is it related to unemulated
- z-sorted polygons, and/or from m_layer0_pivot?;
- solvalou: service mode polygon test is crashy when testing invalid polygons (the good old IDC overflow);
- solvalou: sprite blend is wrong during water stages (look at the blaster/score panel), the palette
bank for the water is at 0x2200, but the blend palette is at 0x6000 instead of 0x6200?;
@@ -52,29 +49,32 @@ The memory map below reflects DSP RAM as seen by the 68000 CPUs.
0x2000a0: B-M:
0x2000b0: P-M:
0x2000c0: S-M:
- 0x200100 status: 2=upload needed, 4=error (abort)
- 0x200102 status
- 0x200104 0x0002
- 0x200106 addr written by main cpu
- 0x20010a point rom checksum (starblade expects 0xed53)
- 0x20010c point rom checksum (starblade expects 0xd5df)
- 0x20010e 1: upload-code-to-dsp request trigger
- 0x200110 status
- 0x200112 status
- 0x200114 master dsp code size
- 0x200116 slave dsp code size
- 0x200120 upload source1 addr hi
- 0x200122 upload source1 addr lo
- 0x200124 upload source2 addr hi
- 0x200126 upload source2 addr lo
- 0x200200 enable
- 0x200202 status
- 0x200206 work page select
- 0x200208 0xa2c2 (air combat)
- 0x208000..0x2080ff camera attributes for page#0
- 0x208200..0x208fff 3d object attribute display list for page#0
- 0x20c000..0x20c0ff camera attributes for page#1
- 0x20c200..0x20cfff 3d object attribute display list for page#1
+
+ 0x200100: status: 2=upload needed, 4=error (abort)
+ 0x200102: status
+ 0x200104: 0x0002
+ 0x200106: addr written by main cpu
+ 0x20010a: point rom checksum (starblade expects 0xed53)
+ 0x20010c: point rom checksum (starblade expects 0xd5df)
+ 0x20010e: 1: upload-code-to-dsp request trigger
+ 0x200110: status
+ 0x200112: status
+ 0x200114: master dsp code size
+ 0x200116: slave dsp code size
+ 0x200120: upload source1 addr hi
+ 0x200122: upload source1 addr lo
+ 0x200124: upload source2 addr hi
+ 0x200126: upload source2 addr lo
+
+ 0x200200: enable
+ 0x200202: status
+ 0x200206: work page select
+ 0x200208: 0xa2c2 (air combat)
+
+ 0x208000..0x2080ff: camera attributes for page#0
+ 0x208200..0x208fff: 3d object attribute display list for page#0
+ 0x20c000..0x20c0ff: camera attributes for page#1
+ 0x20c200..0x20cfff: 3d object attribute display list for page#1
Starblade Cybersled AirCombat22 Solvalou
[400]:= 00 0000 00 0000 00 0000 00 0000
@@ -331,6 +331,7 @@ public:
void init_solvalou();
protected:
+ virtual void video_start() override ATTR_COLD;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
@@ -354,8 +355,8 @@ private:
required_device<namcos21_3d_device> m_namcos21_3d;
required_device<namcos21_dsp_c67_device> m_namcos21_dsp_c67;
- u16 m_layer0_pivot = 0x800;
u16 m_video_enable = 0;
+ bitmap_ind16 m_mix_layer0_bitmap;
u16 video_enable_r();
void video_enable_w(offs_t offset, u16 data, u16 mem_mask = ~0);
@@ -377,6 +378,7 @@ private:
TIMER_DEVICE_CALLBACK_MEMBER(screen_scanline);
bool sprite_mix_callback(u16 &dest, u8 &destpri, u16 colbase, u16 src, int srcpri, int pri);
+ void mix_layer0_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void common_map(address_map &map) ATTR_COLD;
@@ -388,6 +390,13 @@ private:
};
+void namcos21_c67_state::video_start()
+{
+ m_screen->register_screen_bitmap(m_mix_layer0_bitmap);
+
+ save_item(NAME(m_video_enable));
+}
+
bool namcos21_c67_state::sprite_mix_callback(u16 &dest, u8 &destpri, u16 colbase, u16 src, int srcpri, int pri)
{
if ((srcpri & 3) == pri)
@@ -427,6 +436,34 @@ bool namcos21_c67_state::sprite_mix_callback(u16 &dest, u8 &destpri, u16 colbase
return false;
}
+void namcos21_c67_state::mix_layer0_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ copybitmap(m_mix_layer0_bitmap, bitmap, 0, 0, 0, 0, cliprect);
+ m_c355spr->draw(screen, m_mix_layer0_bitmap, cliprect, 0);
+
+ assert(cliprect.bottom < m_namcos21_3d->height() && cliprect.right() < m_namcos21_3d->width());
+
+ // create priority table, this is not accurate
+ u16 pri[0x10];
+ for (int i = 0; i < 0x10; i++)
+ pri[i] = (i == 0) ? 0x7fc0 : pri[i - 1] / 1.25;
+
+ // mix layer 0 sprites with polygons
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
+ {
+ const u16 *z = m_namcos21_3d->get_visible_zbuffer() + m_namcos21_3d->width() * y;
+ const u16 *src = &m_mix_layer0_bitmap.pix(y);
+ u16 *dest = &bitmap.pix(y);
+
+ for (int x = cliprect.left(); x <= cliprect.right(); x++)
+ {
+ // priority is from sprite high palette bits
+ if ((src[x] & 0x5000 && pri[src[x] >> 8 & 0xf] <= z[x]) || src[x] < 0x1000)
+ dest[x] = src[x];
+ }
+ }
+}
+
u32 namcos21_c67_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0xff, cliprect);
@@ -452,9 +489,8 @@ u32 namcos21_c67_state::screen_update(screen_device &screen, bitmap_ind16 &bitma
break;
case 4: // default gameplay for all games, aircomb attract mode
default:
- m_namcos21_3d->copy_visible_poly_framebuffer(bitmap, cliprect, m_layer0_pivot, 0x7ffe);
- m_c355spr->draw(screen, bitmap, cliprect, 0);
- m_namcos21_3d->copy_visible_poly_framebuffer(bitmap, cliprect, 0, m_layer0_pivot - 1);
+ m_namcos21_3d->copy_visible_poly_framebuffer(bitmap, cliprect, 0, 0x7ffe);
+ mix_layer0_sprites(screen, bitmap, cliprect);
break;
}
@@ -773,8 +809,6 @@ void namcos21_c67_state::machine_start()
u32 max = memregion("audiocpu")->bytes() / 0x4000;
for (int i = 0; i < 0x10; i++)
m_audiobank->configure_entry(i, memregion("audiocpu")->base() + (i % max) * 0x4000);
-
- save_item(NAME(m_video_enable));
}
TIMER_DEVICE_CALLBACK_MEMBER(namcos21_c67_state::screen_scanline)
@@ -912,7 +946,6 @@ void namcos21_c67_state::solvalou(machine_config &config)
m_namcos21_3d->set_fixed_palbase(0x3f00);
m_namcos21_3d->set_zz_shift_mult(10, 0x100);
- m_layer0_pivot = 0x7fc0;
}