taito/taito_f3_v.cpp: major rewrite (#11811) [ywy, 12Me21]

This commit is contained in:
ywy 2024-04-23 08:59:31 -07:00 committed by GitHub
parent 494ad05821
commit 563b63fabf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 1199 additions and 2652 deletions

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Bryan McPhail
// thanks-to: Shiriru
/***************************************************************************
Taito F3 Package System (aka F3 Cybercore System)
@ -9,25 +10,16 @@
Major thanks to Aaron Giles for sound info, figuring out the 68K/ES5505
rom interface and ES5505 emulator!
Thanks to Acho A. Tang for Kirameki Star Road sound banking info!
Thank you to Shiriru for the scanline rendering (including alpha blending),
sprite sync fixes, sprite zoom fixes and others!
Other Issues:
- Various hacks in video core that needs squashing;
- When playing space invaders dx in original mode, t.t. with overlay, the
alpha blending effect is wrong (see Taito B version of game)
- Bubble Symphony has an alpha transition effect that doesn't appear in Mame
- Various other missing blending effects (see Mametesters)
- Find how this HW drives the CRTC, and convert video timings to use screen raw params;
Feel free to report any other issues to me.
- Find how this HW drives the CRTC and verify timing of interrupts
Taito custom chips on motherboard:
TC0630FDP - Playfield generator? (Nearest tile roms)
TC0640FIO - I/O & watchdog?
TC0650FDA - Priority mixer? (Near paletteram & video output)
TC0660FCM - Sprites? (Nearest sprite roms)
TC0630FDP "Display Processor" - Graphics (sprites, playfields, prio, lineram...)
TC0640FIO "I/O" - I/O ports (buttons, eeprom, and watchdog)
TC0650FDA "Digital to Analog" - Blending and RGB output
TC0660FCM "Control Module?" - Misc. control/comm.?
***************************************************************************/
@ -66,40 +58,36 @@ u32 taito_f3_state::f3_control_r(offs_t offset)
void taito_f3_state::f3_control_w(offs_t offset, u32 data, u32 mem_mask)
{
switch (offset)
{
case 0x00: /* Watchdog */
m_watchdog->watchdog_reset();
return;
switch (offset) {
case 0x00: /* Watchdog */
m_watchdog->watchdog_reset();
return;
case 0x01: /* Coin counters & lockouts */
if (ACCESSING_BITS_24_31)
{
machine().bookkeeping().coin_lockout_w(0,~data & 0x01000000);
machine().bookkeeping().coin_lockout_w(1,~data & 0x02000000);
machine().bookkeeping().coin_counter_w(0, data & 0x04000000);
machine().bookkeeping().coin_counter_w(1, data & 0x08000000);
m_coin_word[0]=(data>>16)&0xffff;
}
return;
case 0x01: /* Coin counters & lockouts */
if (ACCESSING_BITS_24_31) {
machine().bookkeeping().coin_lockout_w(0,~data & 0x01000000);
machine().bookkeeping().coin_lockout_w(1,~data & 0x02000000);
machine().bookkeeping().coin_counter_w(0, data & 0x04000000);
machine().bookkeeping().coin_counter_w(1, data & 0x08000000);
m_coin_word[0]=(data>>16)&0xffff;
}
return;
case 0x04: /* Eeprom */
if (ACCESSING_BITS_0_7)
{
m_eepromout->write(data, 0xff);
}
return;
case 0x04: /* Eeprom */
if (ACCESSING_BITS_0_7) {
m_eepromout->write(data, 0xff);
}
return;
case 0x05: /* Player 3 & 4 coin counters */
if (ACCESSING_BITS_24_31)
{
machine().bookkeeping().coin_lockout_w(2,~data & 0x01000000);
machine().bookkeeping().coin_lockout_w(3,~data & 0x02000000);
machine().bookkeeping().coin_counter_w(2, data & 0x04000000);
machine().bookkeeping().coin_counter_w(3, data & 0x08000000);
m_coin_word[1]=(data>>16)&0xffff;
}
return;
case 0x05: /* Player 3 & 4 coin counters */
if (ACCESSING_BITS_24_31) {
machine().bookkeeping().coin_lockout_w(2,~data & 0x01000000);
machine().bookkeeping().coin_lockout_w(3,~data & 0x02000000);
machine().bookkeeping().coin_counter_w(2, data & 0x04000000);
machine().bookkeeping().coin_counter_w(3, data & 0x08000000);
m_coin_word[1]=(data>>16)&0xffff;
}
return;
}
logerror("CPU #0 PC %06x: warning - write unmapped control address %06x %08x\n",m_maincpu->pc(),offset,data);
}
@ -116,8 +104,7 @@ void taito_f3_state::sound_reset_1_w(u32 data)
void taito_f3_state::sound_bankswitch_w(offs_t offset, u32 data, u32 mem_mask)
{
if (m_game == KIRAMEKI)
{
if (m_game == KIRAMEKI) {
int idx = (offset << 1) & 0x1e;
if (ACCESSING_BITS_0_15)
idx += 1;
@ -126,19 +113,17 @@ void taito_f3_state::sound_bankswitch_w(offs_t offset, u32 data, u32 mem_mask)
idx -= 8;
/* Banks are 0x20000 bytes each, divide by two to get data16
pointer rather than byte pointer */
pointer rather than byte pointer */
m_taito_en->set_bank(1, idx);
}
else
{
} else {
logerror("Sound bankswitch in unsupported game\n");
}
}
void taito_f3_state::f3_unk_w(offs_t offset, u16 data)
void taito_f3_state::f3_timer_control_w(offs_t offset, u16 data)
{
/*
Several games writes a value here at POST, dunno what kind of config this is ...
TODO: Several games configure timer-based pseudo-hblank int5 here at POST
ringrage: 0x0000
arabianm: 0x0000
ridingf: (no init)
@ -188,7 +173,7 @@ void taito_f3_state::f3_map(address_map &map)
map(0x400000, 0x41ffff).mirror(0x20000).ram();
map(0x440000, 0x447fff).ram().w(FUNC(taito_f3_state::palette_24bit_w)).share("paletteram");
map(0x4a0000, 0x4a001f).rw(FUNC(taito_f3_state::f3_control_r), FUNC(taito_f3_state::f3_control_w));
map(0x4c0000, 0x4c0003).w(FUNC(taito_f3_state::f3_unk_w));
map(0x4c0000, 0x4c0003).w(FUNC(taito_f3_state::f3_timer_control_w));
map(0x600000, 0x60ffff).rw(FUNC(taito_f3_state::spriteram_r), FUNC(taito_f3_state::spriteram_w));
map(0x610000, 0x61bfff).rw(FUNC(taito_f3_state::pf_ram_r), FUNC(taito_f3_state::pf_ram_w));
map(0x61c000, 0x61dfff).rw(FUNC(taito_f3_state::textram_r), FUNC(taito_f3_state::textram_w));
@ -206,12 +191,9 @@ void taito_f3_state::bubsympb_oki_w(u8 data) // TODO: this is wrong. PCB referen
{
//printf("write %08x %08x\n",data,mem_mask);
const u8 bank = data & 0xf;
if (data < 5)
{
if (data < 5) {
m_okibank->set_entry(bank);
}
else
{
} else {
logerror("unknown oki bank write %02x at %08x\n", bank, m_maincpu->pc());
}
//printf("oki bank w %08x\n",data);
@ -226,7 +208,7 @@ void taito_f3_state::bubsympb_map(address_map &map)
map(0x4a0000, 0x4a001b).rw(FUNC(taito_f3_state::f3_control_r), FUNC(taito_f3_state::f3_control_w));
map(0x4a001d, 0x4a001d).w(FUNC(taito_f3_state::bubsympb_oki_w));
map(0x4a001f, 0x4a001f).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0x4c0000, 0x4c0003).w(FUNC(taito_f3_state::f3_unk_w));
map(0x4c0000, 0x4c0003).w(FUNC(taito_f3_state::f3_timer_control_w));
map(0x600000, 0x60ffff).rw(FUNC(taito_f3_state::spriteram_r), FUNC(taito_f3_state::spriteram_w));
map(0x610000, 0x61bfff).rw(FUNC(taito_f3_state::pf_ram_r), FUNC(taito_f3_state::pf_ram_w));
map(0x61c000, 0x61dfff).rw(FUNC(taito_f3_state::textram_r), FUNC(taito_f3_state::textram_w));
@ -368,8 +350,7 @@ INPUT_PORTS_END
/******************************************************************************/
static const gfx_layout charlayout =
{
static const gfx_layout charlayout = {
8,8,
256,
4,
@ -379,8 +360,7 @@ static const gfx_layout charlayout =
32*8
};
static const gfx_layout pivotlayout =
{
static const gfx_layout pivotlayout = {
8,8,
2048,
4,
@ -390,8 +370,7 @@ static const gfx_layout pivotlayout =
32*8
};
static const gfx_layout layout_6bpp_sprite_hi =
{
static const gfx_layout layout_6bpp_sprite_hi = {
16,16,
RGN_FRAC(1,1),
6,
@ -401,8 +380,7 @@ static const gfx_layout layout_6bpp_sprite_hi =
16*16*2
};
static const gfx_layout layout_6bpp_tile_hi =
{
static const gfx_layout layout_6bpp_tile_hi = {
16,16,
RGN_FRAC(1,1),
6,
@ -425,7 +403,9 @@ GFXDECODE_END
TIMER_CALLBACK_MEMBER(taito_f3_state::trigger_int3)
{
m_maincpu->set_input_line(3, HOLD_LINE); // some signal from video hardware?
// some signal from video hardware?
// vblank handler will wait until approximately end of vblank for it
m_maincpu->set_input_line(3, HOLD_LINE);
}
INTERRUPT_GEN_MEMBER(taito_f3_state::interrupt2)
@ -451,7 +431,7 @@ void taito_f3_state::machine_reset()
void taito_f3_state::f3(machine_config &config)
{
/* basic machine hardware */
M68EC020(config, m_maincpu, XTAL(16'000'000));
M68EC020(config, m_maincpu, F3_MAIN_CLK);
m_maincpu->set_addrmap(AS_PROGRAM, &taito_f3_state::f3_map);
m_maincpu->set_vblank_int("screen", FUNC(taito_f3_state::interrupt2));
@ -461,10 +441,15 @@ void taito_f3_state::f3(machine_config &config)
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(58.97);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(624)); /* 58.97 Hz, 624us vblank time */
m_screen->set_size(40*8+48*2, 32*8);
m_screen->set_visarea(46, 40*8-1 + 46, 24, 24+232-1);
// from taito z system and crystal on board
// and measurements from https://www.arcade-projects.com/threads/the-taito-f3-sync.12343/
m_screen->set_raw(
26.686_MHz_XTAL / 4,
432, 46, 320 + 46,
262, 24, 232 + 24
);
// refresh rate = 26686000/4/432/262 = 58.94..
m_screen->set_screen_update(FUNC(taito_f3_state::screen_update));
m_screen->screen_vblank().set(FUNC(taito_f3_state::screen_vblank));
@ -503,8 +488,7 @@ void taito_f3_state::f3_224c(machine_config &config)
m_screen->set_visarea(46, 40*8-1 + 46, 24, 24+224-1);
}
static const gfx_layout bubsympb_sprite_layout =
{
static const gfx_layout bubsympb_sprite_layout = {
16,16,
RGN_FRAC(1,6),
6,
@ -514,8 +498,7 @@ static const gfx_layout bubsympb_sprite_layout =
16*16
};
static const gfx_layout bubsympb_layout_5bpp_tile_hi =
{
static const gfx_layout bubsympb_layout_5bpp_tile_hi = {
16,16,
RGN_FRAC(1,1),
5,
@ -538,7 +521,7 @@ GFXDECODE_END
void taito_f3_state::bubsympb(machine_config &config)
{
/* basic machine hardware */
M68EC020(config, m_maincpu, XTAL(16'000'000));
M68EC020(config, m_maincpu, F3_MAIN_CLK);
m_maincpu->set_addrmap(AS_PROGRAM, &taito_f3_state::bubsympb_map);
m_maincpu->set_vblank_int("screen", FUNC(taito_f3_state::interrupt2));
@ -4335,8 +4318,7 @@ void taito_f3_state::tile_decode()
u8 *dest;
// all but bubsymphb (bootleg board with different sprite gfx layout), 2mindril (no sprite gfx roms)
if (m_gfxdecode->gfx(5) != nullptr)
{
if (m_gfxdecode->gfx(5) != nullptr) {
gfx_element *spr_gfx = m_gfxdecode->gfx(2);
gfx_element *spr_gfx_hi = m_gfxdecode->gfx(5);
@ -4345,14 +4327,12 @@ void taito_f3_state::tile_decode()
// loop over elements
dest = m_decoded_gfx5.get();
for (int c = 0; c < spr_gfx->elements(); c++)
{
for (int c = 0; c < spr_gfx->elements(); c++) {
const u8 *c1base = spr_gfx->get_data(c);
const u8 *c3base = spr_gfx_hi->get_data(c);
// loop over height
for (int y = 0; y < spr_gfx->height(); y++)
{
for (int y = 0; y < spr_gfx->height(); y++) {
const u8 *c1 = c1base;
const u8 *c3 = c3base;
@ -4369,8 +4349,7 @@ void taito_f3_state::tile_decode()
m_gfxdecode->set_gfx(5, nullptr);
}
if (m_gfxdecode->gfx(4) != nullptr)
{
if (m_gfxdecode->gfx(4) != nullptr) {
gfx_element *pf_gfx = m_gfxdecode->gfx(3);
gfx_element *pf_gfx_hi = m_gfxdecode->gfx(4);
@ -4379,14 +4358,12 @@ void taito_f3_state::tile_decode()
// loop over elements
dest = m_decoded_gfx4.get();
for (int c = 0; c < pf_gfx->elements(); c++)
{
for (int c = 0; c < pf_gfx->elements(); c++) {
const u8 *c0base = pf_gfx->get_data(c);
const u8 *c2base = pf_gfx_hi->get_data(c);
// loop over height
for (int y = 0; y < pf_gfx->height(); y++)
{
for (int y = 0; y < pf_gfx->height(); y++) {
const u8 *c0 = c0base;
const u8 *c2 = c2base;
@ -4722,7 +4699,7 @@ GAME( 1995, spcinv95, 0, f3_224a, f3, taito_f3_state, init_spcinv95, RO
GAME( 1995, spcinv95u, spcinv95, f3_224a, f3, taito_f3_state, init_spcinv95, ROT270, "Taito America Corporation", "Space Invaders '95: The Attack Of Lunar Loonies (Ver 2.5A 1995/06/14)", 0 )
GAME( 1995, akkanvdr, spcinv95, f3_224a, f3, taito_f3_state, init_spcinv95, ROT270, "Taito Corporation", "Akkanbeder (Ver 2.5J 1995/06/14)", 0 )
GAME( 1995, twinqix, 0, f3_224a, f3, taito_f3_state, init_twinqix, ROT0, "Taito America Corporation", "Twin Qix (Ver 1.0A 1995/01/17, prototype)", 0 )
GAME( 1995, quizhuhu, 0, f3, f3, taito_f3_state, init_quizhuhu, ROT0, "Taito Corporation", "Moriguchi Hiroko no Quiz de Hyuu!Hyuu! (Ver 2.2J 1995/05/25)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) // quiz text positioning, heavy sprite window usage
GAME( 1995, quizhuhu, 0, f3, f3, taito_f3_state, init_quizhuhu, ROT0, "Taito Corporation", "Moriguchi Hiroko no Quiz de Hyuu!Hyuu! (Ver 2.2J 1995/05/25)", 0 )
GAME( 1995, pbobble2, 0, f3, f3, taito_f3_state, init_pbobbl2p, ROT0, "Taito Corporation Japan", "Puzzle Bobble 2 (Ver 2.3O 1995/07/31)", 0 )
GAME( 1995, pbobble2o, pbobble2, f3, f3, taito_f3_state, init_pbobble2, ROT0, "Taito Corporation Japan", "Puzzle Bobble 2 (Ver 2.2O 1995/07/20)", 0 )
GAME( 1995, pbobble2j, pbobble2, f3, f3, taito_f3_state, init_pbobble2, ROT0, "Taito Corporation", "Puzzle Bobble 2 (Ver 2.2J 1995/07/20)", 0 )

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Bryan McPhail
// copyright-holders:Bryan McPhail, ywy, 12Me21
#ifndef MAME_TAITO_TAITO_F3_H
#define MAME_TAITO_TAITO_F3_H
@ -12,6 +12,7 @@
#include "emupal.h"
#include "screen.h"
#include "tilemap.h"
#include <bitset>
class taito_f3_state : public driver_device
{
@ -24,11 +25,11 @@ public:
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_eeprom(*this, "eeprom"),
m_textram(*this, "textram", 0x2000, ENDIANNESS_BIG),
m_spriteram(*this, "spriteram", 0x10000, ENDIANNESS_BIG),
m_pf_ram(*this, "pf_ram", 0xc000, ENDIANNESS_BIG),
m_textram(*this, "textram", 0x2000, ENDIANNESS_BIG),
m_charram(*this, "charram", 0x2000, ENDIANNESS_BIG),
m_line_ram(*this, "line_ram", 0x10000, ENDIANNESS_BIG),
m_pf_ram(*this, "pf_ram", 0xc000, ENDIANNESS_BIG),
m_pivot_ram(*this, "pivot_ram", 0x10000, ENDIANNESS_BIG),
m_input(*this, "IN.%u", 0),
m_dial(*this, "DIAL.%u", 0),
@ -90,8 +91,24 @@ public:
DECLARE_CUSTOM_INPUT_MEMBER(eeprom_read);
protected:
struct F3config;
using fixed8 = s32;
// should be 30.47618_MHz_XTAL / 2
static inline constexpr XTAL F3_MAIN_CLK = 16_MHz_XTAL;
static inline constexpr int H_TOTAL = 432;
static inline constexpr int H_VIS = 320;
static inline constexpr int H_START = 46;
static inline constexpr int V_TOTAL = 262;
static inline constexpr int V_VIS = 232;
static inline constexpr int V_START = 24;
static inline constexpr int NUM_PLAYFIELDS = 4;
static inline constexpr int NUM_TILEMAPS = 5;
static inline constexpr int NUM_SPRITEGROUPS = 4; // high 2 bits of color
static inline constexpr int NUM_CLIPPLANES = 4;
struct F3config;
/* This it the best way to allow game specific kludges until the system is fully understood */
enum {
/* Early F3 class games, these are not cartridge games and system features may be different */
@ -150,12 +167,14 @@ protected:
required_device<palette_device> m_palette;
optional_device<eeprom_serial_base_device> m_eeprom;
memory_share_creator<u16> m_textram;
memory_share_creator<u16> m_spriteram;
memory_share_creator<u16> m_pf_ram;
memory_share_creator<u16> m_textram;
memory_share_creator<u16> m_charram;
memory_share_creator<u16> m_line_ram;
memory_share_creator<u16> m_pf_ram;
memory_share_creator<u16> m_pivot_ram;
u16 m_control_0[8]{};
u16 m_control_1[8]{};
optional_ioport_array<6> m_input;
optional_ioport_array<2> m_dial;
@ -167,136 +186,213 @@ protected:
std::unique_ptr<u8[]> m_decoded_gfx4;
std::unique_ptr<u8[]> m_decoded_gfx5;
struct tempsprite
{
int code = 0;
u8 color = 0;
bool flipx = 0, flipy = 0;
int x = 0, y = 0;
u16 zoomx = 0, zoomy = 0;
u8 pri = 0;
struct tempsprite {
int code; // 17 bits
u8 color;
bool flip_x, flip_y;
fixed8 x, y;
fixed8 scale_x, scale_y;
u8 pri;
};
struct f3_playfield_line_inf
{
u8 alpha_mode[256]{};
u16 pri[256]{};
struct clip_plane_inf {
s16 l;
s16 r;
/* use for draw_scanlines */
u16 *src[256]{}, *src_s[256]{}, *src_e[256]{};
u8 *tsrc[256]{}, *tsrc_s[256]{};
int x_count[256]{};
u32 x_zoom[256]{};
u32 clip_in[256]{};
u32 clip_ex[256]{};
u16 pal_add[256]{};
clip_plane_inf() { l = 0; r = 0; }
clip_plane_inf(s16 left, s16 right)
{
l = left;
r = right;
}
clip_plane_inf& set_upper(s8 left, s8 right)
{
l = (l & 0xff) | left<<8;
r = (r & 0xff) | right<<8;
return *this;
}
clip_plane_inf& set_lower(u8 left, u8 right)
{
l = (l & 0x100) | left;
r = (r & 0x100) | right;
return *this;
}
};
struct f3_spritealpha_line_inf
{
u16 alpha_level[256]{};
u16 spri[256]{};
u16 sprite_alpha[256]{};
u32 sprite_clip_in[256]{};
u32 sprite_clip_ex[256]{};
s16 clip_l[4][256]{};
s16 clip_r[4][256]{};
struct draw_source {
draw_source() { };
draw_source(bitmap_ind16 *bitmap)
{
src = bitmap;
flags = nullptr;
}
draw_source(tilemap_t *tilemap)
{
if (!tilemap)
return;
src = &tilemap->pixmap();
flags = &tilemap->flagsmap();
};
bitmap_ind16 *src{nullptr};
bitmap_ind8 *flags{nullptr};
};
struct mix_pix { // per-pixel information for the blending circuit
u16 src_pal{0};
u16 dst_pal{0};
u8 src_blend{0x00};
u8 dst_blend{0xff};
};
struct f3_line_inf;
struct mixable {// layer compositing information
draw_source bitmap;
bool x_sample_enable{false};
u16 mix_value{0};
u8 prio{0};
void set_mix(u16 v) { mix_value = v; prio = v & 0xf; };
void set_prio(u8 p) { mix_value = (mix_value & 0xfff0) | p; prio = p; };
auto clip_inv() const { return std::bitset<4>(mix_value >> 4); };
auto clip_enable() const { return std::bitset<4>(mix_value >> 8); };
bool clip_inv_mode() const { return mix_value & 0x1000; };
inline bool layer_enable() const;
u8 blend_mask() const { return BIT(mix_value, 14, 2); };
bool blend_a() const { return mix_value & 0x4000; };
bool blend_b() const { return mix_value & 0x8000; };
inline bool operator<(const mixable &rhs) const noexcept { return this->prio < rhs.prio; };
inline bool operator>(const mixable &rhs) const noexcept { return this->prio > rhs.prio; };
u16 palette_adjust(u16 pal) const { return pal; };
inline int y_index(int y) const;
inline int x_index(int x) const;
bool blend_select(const u8 *line_flags, int x) const { return false; };
bool used(int y) const { return true; };
u8 debug_index{0};
const char *debug_name() { return "MX"; };
};
struct sprite_inf : mixable {
// alpha mode in 6000
// mosaic enable in 6400
// line enable, clip settings in 7400
// priority in 7600
bool blend_select_v{false}; // 7400 0xf000
bool blend_select(const u8 *line_flags, int x) const { return blend_select_v; };
inline bool layer_enable() const;
u8 (*sprite_pri_usage)[256]{nullptr};
bool used(int y) const { return (*sprite_pri_usage)[y] & (1<<debug_index); }
const char *debug_name() { return "SP"; };
};
struct pivot_inf : mixable {
u8 pivot_control{0}; // 6000
bool blend_select_v{false};
bool blend_select(const u8 *line_flags, int x) const { return blend_select_v; };
// mosaic enable in 6400
u16 pivot_enable{0}; // 7000 - what is in this word ?
// mix info from 7200
bool use_pix() const { return pivot_control & 0xa0; };
u16 reg_sx{0};
u16 reg_sy{0};
inline int y_index(int y) const;
inline int x_index(int x) const;
const char *debug_name() { return "PV"; };
};
struct playfield_inf : mixable {
u16 colscroll{0}; // 4000
bool alt_tilemap{false}; // 4000
// mosaic enable in 6400
fixed8 x_scale{0x80}; // 8000
fixed8 y_scale{0}; // 8000
u16 pal_add{0}; // 9000
fixed8 rowscroll{0}; // a000
fixed8 reg_sx{0};
fixed8 reg_sy{0};
fixed8 reg_fx_y{0};
fixed8 reg_fx_x{0};
u16 width_mask{0};
inline u16 palette_adjust(u16 pal) const;
inline int y_index(int y) const;
inline int x_index(int x) const;
bool blend_select(const u8 *line_flags, int x) const { return BIT(line_flags[x], 0); };
const char *debug_name() { return "PF"; };
};
struct pri_mode {
u8 src_prio{0};
u8 dst_prio{0};
u8 src_blendmode{0xff};
u8 dst_blendmode{0xff};
};
struct f3_line_inf {
int y{0};
int screen_y{0};
pri_mode pri_alp[432]{};
// 5000/4000
clip_plane_inf clip[NUM_CLIPPLANES];
// 6000 - pivot_control, sprite alpha
u16 maybe_sync_reg{0};
bool no_opaque_dest{false};
// 6200
u8 blend[4]{}; // less 0 - 8 more
// 6400
u8 x_sample{16 - 0}; // mosaic effect
u8 fx_6400{0}; // unemulated other effects (palette interpretation + unused bits)
// 6600
u16 bg_palette{0}; // always palette 0 in existing games
// 7200
pivot_inf pivot;
sprite_inf sp[NUM_SPRITEGROUPS];
playfield_inf pf[NUM_PLAYFIELDS];
};
int m_game = 0;
tilemap_t *m_tilemap[8]{};
tilemap_t *m_tilemap[8] = {nullptr};
tilemap_t *m_pixel_layer = nullptr;
tilemap_t *m_vram_layer = nullptr;
std::unique_ptr<u16[]> m_spriteram16_buffered;
u16 m_control_0[8]{};
u16 m_control_1[8]{};
bool m_flipscreen = false;
bool m_extend = false;
u8 m_sprite_extra_planes = 0;
u8 m_sprite_pen_mask = 0;
bool m_sprite_trails = false;
u16 *m_pf_data[8]{};
int m_sprite_lag = 0;
u8 m_sprite_pri_usage = 0;
u8 m_sprite_pri_row_usage[256]{};
bitmap_ind8 m_pri_alp_bitmap;
u8 m_alpha_level_2as = 0;
u8 m_alpha_level_2ad = 0;
u8 m_alpha_level_3as = 0;
u8 m_alpha_level_3ad = 0;
u8 m_alpha_level_2bs = 0;
u8 m_alpha_level_2bd = 0;
u8 m_alpha_level_3bs = 0;
u8 m_alpha_level_3bd = 0;
u16 m_alpha_level_last = 0;
bitmap_ind16 m_sprite_framebuffers[NUM_SPRITEGROUPS]{};
u16 m_width_mask = 0;
u8 m_twidth_mask = 0;
u8 m_twidth_mask_bit = 0;
std::unique_ptr<u8[]> m_tile_opaque_sp;
std::unique_ptr<u8[]> m_tile_opaque_pf[8];
int m_alpha_s_1_1 = 0;
int m_alpha_s_1_2 = 0;
int m_alpha_s_1_4 = 0;
int m_alpha_s_1_5 = 0;
int m_alpha_s_1_6 = 0;
int m_alpha_s_1_8 = 0;
int m_alpha_s_1_9 = 0;
int m_alpha_s_1_a = 0;
int m_alpha_s_2a_0 = 0;
int m_alpha_s_2a_4 = 0;
int m_alpha_s_2a_8 = 0;
int m_alpha_s_2b_0 = 0;
int m_alpha_s_2b_4 = 0;
int m_alpha_s_2b_8 = 0;
int m_alpha_s_3a_0 = 0;
int m_alpha_s_3a_1 = 0;
int m_alpha_s_3a_2 = 0;
int m_alpha_s_3b_0 = 0;
int m_alpha_s_3b_1 = 0;
int m_alpha_s_3b_2 = 0;
u32 m_dval = 0;
u8 m_pval = 0;
u8 m_tval = 0;
u8 m_pdest_2a = 0;
u8 m_pdest_2b = 0;
s8 m_tr_2a = 0;
s8 m_tr_2b = 0;
u8 m_pdest_3a = 0;
u8 m_pdest_3b = 0;
s8 m_tr_3a = 0;
s8 m_tr_3b = 0;
u16 *m_src[5]{};
u16 *m_src_s[5]{};
u16 *m_src_e[5]{};
u16 m_clip_al[5]{};
u16 m_clip_ar[5]{};
u16 m_clip_bl[5]{};
u16 m_clip_br[5]{};
u8 *m_tsrc[5]{};
u8 *m_tsrc_s[5]{};
u32 m_x_count[5]{};
u32 m_x_zoom[5]{};
u16 m_pal_add[5]{};
std::unique_ptr<tempsprite[]> m_spritelist;
const tempsprite *m_sprite_end = nullptr;
std::unique_ptr<f3_playfield_line_inf[]> m_pf_line_inf;
std::unique_ptr<f3_spritealpha_line_inf[]> m_sa_line_inf;
bool m_sprite_bank = 0;
//f3_line_inf m_line_inf;
const F3config *m_game_config = nullptr;
bool (taito_f3_state::*m_dpix_n[8][16])(u32 s_pix);
bool (taito_f3_state::**m_dpix_lp[5])(u32 s_pix);
bool (taito_f3_state::**m_dpix_sp[9])(u32 s_pix);
u16 pf_ram_r(offs_t offset);
void pf_ram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void control_0_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void control_1_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 spriteram_r(offs_t offset);
void spriteram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 pf_ram_r(offs_t offset);
void pf_ram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 textram_r(offs_t offset);
void textram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 charram_r(offs_t offset);
void charram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 pivot_r(offs_t offset);
void pivot_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 lineram_r(offs_t offset);
void lineram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 pivot_r(offs_t offset);
void pivot_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void control_0_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void control_1_w(offs_t offset, u16 data, u16 mem_mask = ~0);
template<unsigned Layer> TILE_GET_INFO_MEMBER(get_tile_info);
TILE_GET_INFO_MEMBER(get_tile_info_text);
@ -309,74 +405,20 @@ protected:
void tile_decode();
inline void f3_drawgfx(bitmap_rgb32 &dest_bmp, const rectangle &clip, gfx_element *gfx, int code, u8 color, bool flipx, bool flipy, int sx, int sy, u16 scalex, u16 scaley, u8 pri_dst);
void draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void get_sprite_info(const u16 *spriteram16_ptr);
void print_debug_info(bitmap_rgb32 &bitmap);
inline void alpha_set_level();
inline void alpha_blend32_s(int alphas, u32 s);
inline void alpha_blend32_d(int alphas, u32 s);
inline void alpha_blend_1_1(u32 s);
inline void alpha_blend_1_2(u32 s);
inline void alpha_blend_1_4(u32 s);
inline void alpha_blend_1_5(u32 s);
inline void alpha_blend_1_6(u32 s);
inline void alpha_blend_1_8(u32 s);
inline void alpha_blend_1_9(u32 s);
inline void alpha_blend_1_a(u32 s);
inline void alpha_blend_2a_0(u32 s);
inline void alpha_blend_2a_4(u32 s);
inline void alpha_blend_2a_8(u32 s);
inline void alpha_blend_2b_0(u32 s);
inline void alpha_blend_2b_4(u32 s);
inline void alpha_blend_2b_8(u32 s);
inline void alpha_blend_3a_0(u32 s);
inline void alpha_blend_3a_1(u32 s);
inline void alpha_blend_3a_2(u32 s);
inline void alpha_blend_3b_0(u32 s);
inline void alpha_blend_3b_1(u32 s);
inline void alpha_blend_3b_2(u32 s);
bool dpix_1_noalpha(u32 s_pix);
inline bool dpix_ret1(u32 s_pix);
inline bool dpix_ret0(u32 s_pix);
bool dpix_1_1(u32 s_pix);
bool dpix_1_2(u32 s_pix);
bool dpix_1_4(u32 s_pix);
bool dpix_1_5(u32 s_pix);
bool dpix_1_6(u32 s_pix);
bool dpix_1_8(u32 s_pix);
bool dpix_1_9(u32 s_pix);
bool dpix_1_a(u32 s_pix);
bool dpix_2a_0(u32 s_pix);
bool dpix_2a_4(u32 s_pix);
bool dpix_2a_8(u32 s_pix);
bool dpix_3a_0(u32 s_pix);
bool dpix_3a_1(u32 s_pix);
bool dpix_3a_2(u32 s_pix);
bool dpix_2b_0(u32 s_pix);
bool dpix_2b_4(u32 s_pix);
bool dpix_2b_8(u32 s_pix);
bool dpix_3b_0(u32 s_pix);
bool dpix_3b_1(u32 s_pix);
bool dpix_3b_2(u32 s_pix);
bool dpix_2_0(u32 s_pix);
bool dpix_2_4(u32 s_pix);
bool dpix_2_8(u32 s_pix);
bool dpix_3_0(u32 s_pix);
bool dpix_3_1(u32 s_pix);
bool dpix_3_2(u32 s_pix);
void dpix_1_sprite(u32 s_pix);
void dpix_bg(u32 bgcolor);
void init_alpha_blend_func();
void get_pixmap_pointer(int skip_layer_num, const f3_playfield_line_inf **line_t, int y);
void culc_pixmap_pointer(int skip_layer_num);
void draw_scanlines(bitmap_rgb32 &bitmap, int xsize, s16 *draw_line_num, const f3_playfield_line_inf **line_t, const u8 *sprite, u32 orient, int skip_layer_num);
void visible_tile_check(f3_playfield_line_inf *line_t, int line, u32 x_index_fx, u32 y_index, const u16 *pf_data_n);
void calculate_clip(int y, u16 pri, u32 &clip_in, u32 &clip_ex, u8 &line_enable);
void get_spritealphaclip_info();
void get_line_ram_info(tilemap_t *tmap, int sx, int sy, int pos, const u16 *pf_data_n);
void get_vram_info(tilemap_t *vram_tilemap, tilemap_t *pixel_tilemap, int sx, int sy);
void create_tilemaps(bool extend);
inline void f3_drawgfx(const tempsprite &sprite, const rectangle &cliprect);
void get_sprite_info();
void draw_sprites(const rectangle &cliprect);
void get_pf_scroll(int pf_num, fixed8 &reg_sx, fixed8 &reg_sy);
void read_line_ram(f3_line_inf &line, int y);
void render_line(pen_t *dst, const mix_pix (&z)[432]);
void scanline_draw(bitmap_rgb32 &bitmap, const rectangle &cliprect);
template<typename Mix>
std::vector<clip_plane_inf> calc_clip(const clip_plane_inf (&clip)[NUM_CLIPPLANES], const Mix line);
template<typename Mix>
bool mix_line(Mix *gfx, mix_pix *z, pri_mode *pri, const f3_line_inf &line, const clip_plane_inf &range);
private:
optional_device<taito_en_device> m_taito_en;
@ -388,7 +430,7 @@ private:
void bubsympb_oki_w(u8 data);
u32 f3_control_r(offs_t offset);
void f3_control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
void f3_unk_w(offs_t offset, u16 data);
void f3_timer_control_w(offs_t offset, u16 data);
void sound_reset_0_w(u32 data);
void sound_reset_1_w(u32 data);
void sound_bankswitch_w(offs_t offset, u32 data, u32 mem_mask = ~0);

File diff suppressed because it is too large Load Diff