From 440e546e3764bb948f2b68cf260d16cdf12bb57c Mon Sep 17 00:00:00 2001 From: ywy <12588017+y-ack@users.noreply.github.com> Date: Wed, 1 Mar 2023 10:37:44 -0800 Subject: taito/taito_f3_v.cpp: Improved line clipping effects and palette for landmakr/quizhuhu. (#10920) --- src/mame/taito/taito_f3.h | 14 +- src/mame/taito/taito_f3_v.cpp | 292 +++++++++++++++++++----------------------- 2 files changed, 135 insertions(+), 171 deletions(-) diff --git a/src/mame/taito/taito_f3.h b/src/mame/taito/taito_f3.h index 07f153f5c25..7631847bff5 100644 --- a/src/mame/taito/taito_f3.h +++ b/src/mame/taito/taito_f3.h @@ -184,8 +184,8 @@ protected: u8 *tsrc[256]{}, *tsrc_s[256]{}; int x_count[256]{}; u32 x_zoom[256]{}; - u32 clip0[256]{}; - u32 clip1[256]{}; + u32 clip_in[256]{}; + u32 clip_ex[256]{}; u16 pal_add[256]{}; }; @@ -194,12 +194,10 @@ protected: u16 alpha_level[256]{}; u16 spri[256]{}; u16 sprite_alpha[256]{}; - u32 sprite_clip0[256]{}; - u32 sprite_clip1[256]{}; - s16 clip0_l[256]{}; - s16 clip0_r[256]{}; - s16 clip1_l[256]{}; - s16 clip1_r[256]{}; + u32 sprite_clip_in[256]{}; + u32 sprite_clip_ex[256]{}; + s16 clip_l[4][256]{}; + s16 clip_r[4][256]{}; }; int m_game = 0; diff --git a/src/mame/taito/taito_f3_v.cpp b/src/mame/taito/taito_f3_v.cpp index c6a201ff44a..4ad95894d8e 100644 --- a/src/mame/taito/taito_f3_v.cpp +++ b/src/mame/taito/taito_f3_v.cpp @@ -77,13 +77,15 @@ Line ram memory map: Where bit 2 of x enables effect on playfield 3 Where bit 3 of x enables effect on playfield 4 + 0x1000: Unknown control word? + (usually 0x00f0; gseeker, spcinvdj, twinqix, puchicar set 0x0000) + 0x4000: Column scroll & clipping info - 0x5000: Clip plane 0 (low bits) - 0x5200: Clip plane 1 (low bits) - 0x5400: Unused? - 0x5600: Used by quizhuhu (taito logo and ingame text), and landmakr (winning text), - special clip used in tandem with b*00 bit 11? [unemulated] + 0x5000: Clip plane 0 (low bits (high in 4400)) + 0x5200: Clip plane 1 (low bits (high in 4400)) + 0x5400: Clip plane 2 (low bits (high in 4600)) + 0x5600: Clip plane 3 (low bits (high in 4600)) 0x6000: Sync register 0x6004: Sprite alpha control @@ -122,7 +124,7 @@ Line ram memory map: 0x7000: Pivot/vram layer enable 0x7200: Cram layer priority - 0x7400: Sprite clipping + 0x7400: Sprite clipping (like playfield priority clip bits but shifted) 0x7600: Sprite priority values 0xf000: Relative priority for sprites with pri value 0xc0 0x0f00: Relative priority for sprites with pri value 0x80 @@ -150,15 +152,17 @@ Line ram memory map: 0xb200: Playfield 2 priority 0xb400: Playfield 3 priority 0xb600: Playfield 4 priority - 0xf000 = Blend mode, 0x3000 = Normal, 0x7000 = Alpha A, 0xb000 = Alpha B, others disable line - 0x0800 = Clip line (totally disable line) - 0x0400 = Assumed unused - 0x0200 = If set enable clip plane 1 - 0x0100 = If set enable clip plane 0 - 0x00c0 = Assumed unused - 0x0020 = Enable clip inverse mode for plane 1 - 0x0010 = Enable clip inverse mode for plane 0 0x000f = Layer priority + 0x0010 = Clip inverse mode for plane 0 + 0x0020 = Clip inverse mode for plane 1 + 0x0040 = Clip inverse mode for plane 2 + 0x0080 = Clip inverse mode for plane 3 + 0x0100 = If set enable clip plane 0 + 0x0200 = If set enable clip plane 1 + 0x0400 = If set enable clip plane 2 + 0x0800 = If set enable clip plane 3 + 0x1000 = Affects interpretation of inverse mode bits. If on, 1 = invert. if off, 0 = invert. + 0xe000 = Blend mode, 0x3000 = Normal, 0x7000 = Alpha A, 0xb000 = Alpha B, others disable line 0xc000 - 0xffff: Unused. @@ -380,14 +384,28 @@ TILE_GET_INFO_MEMBER(taito_f3_state::get_tile_info) const u32 tile = (m_pf_data[Layer][tile_index * 2 + 0] << 16) | (m_pf_data[Layer][tile_index * 2 + 1] & 0xffff); const u8 abtype = (tile >> (16 + 9)) & 1; // tiles can be configured to use 4, 5, or 6 bpp data. - // if tiles use more than 4bpp, the bottom bits of the color code must be masked out. - // This fixes (at least) the rain in round 6 of Arabian Magic. const u8 extra_planes = ((tile >> (16 + 10)) & 3); // 0 = 4bpp, 1 = 5bpp, 2 = unused?, 3 = 6bpp - tileinfo.set(3, - tile & 0xffff, - (tile >> 16) & 0x1ff & (~extra_planes), - TILE_FLIPYX(tile >> 30)); + // FIXME: some (5bpp?) games need the bottom bits of the color code to be masked out. + // (mt00895 arabian magic stage 6 rain (color 0x105->104), mt01925 rayforce explosion, mt01917 rayforce ships, mt00900 kaiser knuckle azteca throw) + // however, there are (6bpp) cases which *don't* want any adjustment that this breaks: + // (quizhuhu fade palette 0x7, landmakrj win message palette 0xBE) + // special case until better understood. + if (m_game == LANDMAKR || m_game == QUIZHUHU) + { + tileinfo.set(3, + tile & 0xffff, + (tile >> 16) & 0x1ff, + TILE_FLIPYX(tile >> 30)); + } + else + { + tileinfo.set(3, + tile & 0xffff, + (tile >> 16) & 0x1ff & (~extra_planes), + TILE_FLIPYX(tile >> 30)); + } + tileinfo.category = abtype & 1; /* alpha blending type */ tileinfo.pen_mask = (extra_planes << 4) | 0x0f; } @@ -1284,10 +1302,10 @@ void taito_f3_state::init_alpha_blend_func() m_tsrc_s[pf_num] = line_tmp->tsrc_s[y]; \ m_x_count[pf_num] = line_tmp->x_count[y]; \ m_x_zoom[pf_num] = line_tmp->x_zoom[y]; \ - m_clip_al[pf_num] = line_tmp->clip0[y] & 0xffff; \ - m_clip_ar[pf_num] = line_tmp->clip0[y] >> 16; \ - m_clip_bl[pf_num] = line_tmp->clip1[y] & 0xffff; \ - m_clip_br[pf_num] = line_tmp->clip1[y] >> 16; \ + m_clip_al[pf_num] = line_tmp->clip_in[y] & 0xffff; \ + m_clip_ar[pf_num] = line_tmp->clip_in[y] >> 16; \ + m_clip_bl[pf_num] = line_tmp->clip_ex[y] & 0xffff; \ + m_clip_br[pf_num] = line_tmp->clip_ex[y] >> 16; \ m_pal_add[pf_num] = line_tmp->pal_add[y]; \ } @@ -1373,10 +1391,10 @@ inline void taito_f3_state::draw_scanlines( { int cx = 0; - clip_als = m_sa_line_inf[0].sprite_clip0[y] & 0xffff; - clip_ars = m_sa_line_inf[0].sprite_clip0[y] >> 16; - clip_bls = m_sa_line_inf[0].sprite_clip1[y] & 0xffff; - clip_brs = m_sa_line_inf[0].sprite_clip1[y] >> 16; + clip_als = m_sa_line_inf[0].sprite_clip_in[y] & 0xffff; + clip_ars = m_sa_line_inf[0].sprite_clip_in[y] >> 16; + clip_bls = m_sa_line_inf[0].sprite_clip_ex[y] & 0xffff; + clip_brs = m_sa_line_inf[0].sprite_clip_ex[y] >> 16; int length = xsize; u32 *dsti = dsti0; @@ -1520,108 +1538,49 @@ void taito_f3_state::visible_tile_check( /******************************************************************************/ -void taito_f3_state::calculate_clip(int y, u16 pri, u32 *clip0, u32 *clip1, int *line_enable) +void taito_f3_state::calculate_clip(int y, u16 pri, u32 *clip_in, u32 *clip_ex, int *line_enable) { - const f3_spritealpha_line_inf *sa_line_t = &m_sa_line_inf[0]; - - switch (pri) - { - case 0x0100: /* Clip plane 1 enable */ - { - if (sa_line_t->clip0_l[y] > sa_line_t->clip0_r[y]) - *line_enable = 0; - else - *clip0 = (sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y] << 16); - *clip1 = 0; - } - break; - case 0x0110: /* Clip plane 1 enable, inverted */ - { - *clip1 = (sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y] << 16); - *clip0 = 0x7fff0000; - } - break; - case 0x0200: /* Clip plane 2 enable */ - { - if (sa_line_t->clip1_l[y] > sa_line_t->clip1_r[y]) - *line_enable = 0; - else - *clip0 = (sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y] << 16); - *clip1 = 0; - } - break; - case 0x0220: /* Clip plane 2 enable, inverted */ - { - *clip1 = (sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y] << 16); - *clip0 = 0x7fff0000; - } - break; - case 0x0300: /* Clip plane 1 & 2 enable */ - { - int clipl = 0, clipr = 0; - - if (sa_line_t->clip1_l[y] > sa_line_t->clip0_l[y]) - clipl = sa_line_t->clip1_l[y]; - else - clipl = sa_line_t->clip0_l[y]; - - if (sa_line_t->clip1_r[y] < sa_line_t->clip0_r[y]) - clipr = sa_line_t->clip1_r[y]; - else - clipr = sa_line_t->clip0_r[y]; - - if (clipl > clipr) - *line_enable = 0; - else - *clip0 = (clipl) | (clipr << 16); - *clip1 = 0; - } - break; - case 0x0310: /* Clip plane 1 & 2 enable, plane 1 inverted */ - { - if (sa_line_t->clip1_l[y] > sa_line_t->clip1_r[y]) - line_enable = nullptr; - else - *clip0 = (sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y] << 16); - - *clip1 = (sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y] << 16); - } - break; - case 0x0320: /* Clip plane 1 & 2 enable, plane 2 inverted */ - { - if (sa_line_t->clip0_l[y] > sa_line_t->clip0_r[y]) - line_enable = nullptr; - else - *clip0 = (sa_line_t->clip0_l[y]) | (sa_line_t->clip0_r[y] << 16); - - *clip1 = (sa_line_t->clip1_l[y]) | (sa_line_t->clip1_r[y] << 16); - } - break; - case 0x0330: /* Clip plane 1 & 2 enable, both inverted */ - { - int clipl = 0, clipr = 0; - - if (sa_line_t->clip1_l[y] < sa_line_t->clip0_l[y]) - clipl = sa_line_t->clip1_l[y]; - else - clipl = sa_line_t->clip0_l[y]; - - if (sa_line_t->clip1_r[y] > sa_line_t->clip0_r[y]) - clipr = sa_line_t->clip1_r[y]; - else - clipr = sa_line_t->clip0_r[y]; - - if (clipl > clipr) - *line_enable = 0; - else - *clip1 = (clipl) | (clipr << 16); - *clip0 = 0x7fff0000; - } - break; - default: - // popmessage("Illegal clip mode"); - break; - } + const f3_spritealpha_line_inf *sa_line = &m_sa_line_inf[0]; + + /* landmakr and quizhuhu use clip planes 2 and 3, + commandw enables all clip planes. + only up to 2 valid clips ever used in existing games? */ + u16 normal_planes = (pri >> 8) & (pri >> 4); + u16 invert_planes = (pri >> 8) & ~(pri >> 4); + // when bit 0x1000 set, invert bit ON is normal clip, OFF is inverted + if (pri & 0x1000) + std::swap(normal_planes, invert_planes); + + s16 clipl = 0, clipr = 0x7fff; + + const auto calc_clip = [&sa_line, y, &clipl, &clipr](auto p) { + clipl = std::max(sa_line->clip_l[p][y], clipl); + clipr = std::min(sa_line->clip_r[p][y], clipr); + }; + const auto calc_clip_inv = [&sa_line, y, &clipl, &clipr](auto p) { + clipl = std::min(sa_line->clip_l[p][y], clipl); + clipr = std::max(sa_line->clip_r[p][y], clipr); + }; + + if (normal_planes & 0b0001) { calc_clip(0); }; + if (normal_planes & 0b0010) { calc_clip(1); }; + if (normal_planes & 0b0100) { calc_clip(2); }; + if (normal_planes & 0b1000) { calc_clip(3); }; + if (clipl > clipr) + *line_enable = 0; + else + *clip_in = clipl | (clipr << 16); + + // reset temp clip sides for the inverted/excluded window + clipl = 0x7fff; clipr = 0; + if (invert_planes & 0b0001) { calc_clip_inv(0); }; + if (invert_planes & 0b0010) { calc_clip_inv(1); }; + if (invert_planes & 0b0100) { calc_clip_inv(2); }; + if (invert_planes & 0b1000) { calc_clip_inv(3); }; + if (clipl > clipr) + *clip_ex = 0; + else + *clip_ex = clipl | (clipr << 16); } void taito_f3_state::get_spritealphaclip_info() @@ -1635,6 +1594,7 @@ void taito_f3_state::get_spritealphaclip_info() u16 spri = 0; u16 sprite_clip = 0; u16 clip0_low = 0, clip0_high = 0, clip1_low = 0; + u16 clip2_low = 0, clip2_high = 0, clip3_low = 0; int alpha_level = 0; u16 sprite_alpha = 0; @@ -1664,13 +1624,20 @@ void taito_f3_state::get_spritealphaclip_info() { /* The zoom, column and row values can latch according to control ram */ { - if (m_line_ram[0x100 + y] & 1) + if (m_line_ram[0x100 + y] & 1) // 5000 control playfield 1 clip0_low = (m_line_ram[clip_base_low / 2] >> 0) & 0xffff; - if (m_line_ram[0x000 + y] & 4) + if (m_line_ram[0x000 + y] & 4) // 4000 control clip0_high = (m_line_ram[clip_base_high / 2] >> 0) & 0xffff; - if (m_line_ram[0x100 + y] & 2) + if (m_line_ram[0x100 + y] & 2) // 5000 control playfield 2 clip1_low = (m_line_ram[(clip_base_low + 0x200) / 2] >> 0) & 0xffff; + if (m_line_ram[0x100 + y] & 4) // 5000 control playfield 3 + clip2_low = (m_line_ram[(clip_base_low + 0x400) / 2] >> 0) & 0xffff; + if (m_line_ram[0x000 + y] & 8) // 4000 control + clip2_high = (m_line_ram[(clip_base_high + 0x200) / 2] >> 0) & 0xffff; + if (m_line_ram[0x100 + y] & 8) // 5000 control playfield 4 + clip3_low = (m_line_ram[(clip_base_low + 0x600) / 2] >> 0) & 0xffff; + if (m_line_ram[(0x0600 / 2) + y] & 0x8) spri = m_line_ram[spri_base / 2] & 0xffff; if (m_line_ram[(0x0600 / 2) + y] & 0x4) @@ -1685,32 +1652,35 @@ void taito_f3_state::get_spritealphaclip_info() line_t->alpha_level[y] = alpha_level; line_t->spri[y] = spri; line_t->sprite_alpha[y] = sprite_alpha; - line_t->clip0_l[y] = ((clip0_low & 0xff) | ((clip0_high & 0x1000) >> 4)) - 47; - line_t->clip0_r[y] = (((clip0_low & 0xff00) >> 8) | ((clip0_high & 0x2000) >> 5)) - 48; - line_t->clip1_l[y] = ((clip1_low & 0xff) | ((clip0_high & 0x4000) >> 6)) - 47; - line_t->clip1_r[y] = (((clip1_low & 0xff00) >> 8) | ((clip0_high & 0x8000) >> 7)) - 48; - if (line_t->clip0_l[y] < 0) line_t->clip0_l[y] = 0; - if (line_t->clip0_r[y] < 0) line_t->clip0_r[y] = 0; - if (line_t->clip1_l[y] < 0) line_t->clip1_l[y] = 0; - if (line_t->clip1_r[y] < 0) line_t->clip1_r[y] = 0; + line_t->clip_l[0][y] = ((clip0_low & 0xff) | ((clip0_high & 0x1000) >> 4)) - 47; + line_t->clip_r[0][y] = (((clip0_low & 0xff00) >> 8) | ((clip0_high & 0x2000) >> 5)) - 48; + line_t->clip_l[1][y] = ((clip1_low & 0xff) | ((clip0_high & 0x4000) >> 6)) - 47; + line_t->clip_r[1][y] = (((clip1_low & 0xff00) >> 8) | ((clip0_high & 0x8000) >> 7)) - 48; + line_t->clip_l[2][y] = ((clip2_low & 0xff) | ((clip2_high & 0x1000) >> 4)) - 47; + line_t->clip_r[2][y] = (((clip2_low & 0xff00) >> 8) | ((clip2_high & 0x2000) >> 5)) - 48; + line_t->clip_l[3][y] = ((clip3_low & 0xff) | ((clip2_high & 0x4000) >> 6)) - 47; + line_t->clip_r[3][y] = (((clip3_low & 0xff00) >> 8) | ((clip2_high & 0x8000) >> 7)) - 48; + if (line_t->clip_l[0][y] < 0) line_t->clip_l[0][y] = 0; + if (line_t->clip_r[0][y] < 0) line_t->clip_r[0][y] = 0; + if (line_t->clip_l[1][y] < 0) line_t->clip_l[1][y] = 0; + if (line_t->clip_r[1][y] < 0) line_t->clip_r[1][y] = 0; + if (line_t->clip_l[2][y] < 0) line_t->clip_l[2][y] = 0; + if (line_t->clip_r[2][y] < 0) line_t->clip_r[2][y] = 0; + if (line_t->clip_l[3][y] < 0) line_t->clip_l[3][y] = 0; + if (line_t->clip_r[3][y] < 0) line_t->clip_r[3][y] = 0; /* Evaluate sprite clipping */ - if (sprite_clip & 0x080) - { - line_t->sprite_clip0[y] = 0x7fff7fff; - line_t->sprite_clip1[y] = 0; - } - else if (sprite_clip & 0x33) + if (sprite_clip & 0xf0) { int line_enable = 1; - calculate_clip(y, ((sprite_clip & 0x33) << 4), &line_t->sprite_clip0[y], &line_t->sprite_clip1[y], &line_enable); + calculate_clip(y, ((sprite_clip & 0x1ff) << 4), &line_t->sprite_clip_in[y], &line_t->sprite_clip_ex[y], &line_enable); if (line_enable == 0) - line_t->sprite_clip0[y] = 0x7fff7fff; + line_t->sprite_clip_in[y] = 0x7fff7fff; } else { - line_t->sprite_clip0[y] = 0x7fff0000; - line_t->sprite_clip1[y] = 0; + line_t->sprite_clip_in[y] = 0x7fff0000; + line_t->sprite_clip_ex[y] = 0; } spri_base += inc; @@ -1836,18 +1806,16 @@ void taito_f3_state::get_line_ram_info(tilemap_t *tmap, int sx, int sy, int pos, _y_zoom[y] = (line_zoom & 0xff) << 9; /* Evaluate clipping */ - if (pri & 0x0800) - line_enable = 0; - else if (pri & 0x0330) + if (pri & 0x0f00) { //fast path todo - remove line enable - calculate_clip(y, pri & 0x0330, &line_t->clip0[y], &line_t->clip1[y], &line_enable); + calculate_clip(y, pri & 0x1ff0, &line_t->clip_in[y], &line_t->clip_ex[y], &line_enable); } else { /* No clipping */ - line_t->clip0[y] = 0x7fff0000; - line_t->clip1[y] = 0; + line_t->clip_in[y] = 0x7fff0000; + line_t->clip_ex[y] = 0; } line_t->x_zoom[y] = 0x10000 - (line_zoom & 0xff00); @@ -1913,7 +1881,7 @@ void taito_f3_state::get_line_ram_info(tilemap_t *tmap, int sx, int sy, int pos, visible_tile_check(line_t, y, x_index_fx, y_index, pf_data_n); /* If clipping enabled for this line have to disable 'all opaque' optimisation */ - if (line_t->clip0[y] != 0x7fff0000 || line_t->clip1[y] != 0) + if (line_t->clip_in[y] != 0x7fff0000 || line_t->clip_ex[y] != 0) line_t->alpha_mode[y] &= ~0x80; /* set pixmap index */ @@ -1985,18 +1953,16 @@ void taito_f3_state::get_vram_info(tilemap_t *vram_tilemap, tilemap_t *pixel_til line_t->pri[y] = pri; /* Evaluate clipping */ - if (pri & 0x0800) - line_enable = 0; - else if (pri & 0x0330) + if (pri & 0x0f00) { //fast path todo - remove line enable - calculate_clip(y, pri & 0x0330, &line_t->clip0[y], &line_t->clip1[y], &line_enable); + calculate_clip(y, pri & 0x1ff0, &line_t->clip_in[y], &line_t->clip_ex[y], &line_enable); } else { /* No clipping */ - line_t->clip0[y] = 0x7fff0000; - line_t->clip1[y] = 0; + line_t->clip_in[y] = 0x7fff0000; + line_t->clip_ex[y] = 0; } line_t->x_zoom[y] = 0x10000; -- cgit v1.2.3