mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
laserbat.cpp: Quantise area effect 2/shell effect for catnmous. (#7964)
This commit is contained in:
parent
6b8a176ac2
commit
a1a6ff7087
@ -130,7 +130,7 @@ void laserbat_state_base::csound2_w(uint8_t data)
|
||||
void laserbat_state::csound2_w(uint8_t data)
|
||||
{
|
||||
// there are a bunch of edge-triggered things, so grab changes
|
||||
unsigned const diff = data ^ m_csound2;
|
||||
uint8_t const diff = data ^ m_csound2;
|
||||
|
||||
// SN76477 and distortion control
|
||||
if (data & diff & 0x01)
|
||||
@ -317,10 +317,10 @@ void catnmous_state::csound1_w(uint8_t data)
|
||||
void catnmous_state::csound2_w(uint8_t data)
|
||||
{
|
||||
// the bottom bit is used for sprite banking, of all things
|
||||
m_gfx2 = memregion("gfx2")->base() + ((data & 0x01) ? 0x0800 : 0x0000);
|
||||
m_gfx2_base = uint16_t(BIT(data, 0)) << 11;
|
||||
|
||||
// the top bit is called RESET on the wiring diagram
|
||||
m_audiopcb->reset_w((data & 0x80) ? 1 : 0);
|
||||
m_audiopcb->reset_w(BIT(data, 7));
|
||||
|
||||
m_csound2 = data;
|
||||
}
|
||||
|
@ -65,6 +65,11 @@
|
||||
* The sprite ROM is twice the size as Laser Battle with the bank
|
||||
selected using bit 9 of the 16-bit sound interface (there's a wire
|
||||
making this connection visible on the component side of the PCB)
|
||||
* At least some boards have IC13I pins 8, 9, 10 and 11 bent out of
|
||||
the socket, tied together, and pulled high via a 4k7 resistor,
|
||||
which quantises the shell/area effect 2 to four-pixel boundaries
|
||||
(implemented as m_eff2_mask) - would be good to see whether this
|
||||
mod is present on all boards
|
||||
* If demo sounds are enabled (using DIP switches), background music
|
||||
is played every sixth time through the attract loop
|
||||
* Sound board emulation is based on tracing the program and guessing
|
||||
@ -412,9 +417,14 @@ INTERRUPT_GEN_MEMBER(laserbat_state_base::laserbat_interrupt)
|
||||
m_maincpu->set_input_line(0, ASSERT_LINE);
|
||||
}
|
||||
|
||||
void laserbat_state_base::init_laserbat()
|
||||
void laserbat_state_base::machine_start()
|
||||
{
|
||||
// start rendering scanlines
|
||||
m_screen->register_screen_bitmap(m_bitmap);
|
||||
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(1, 0));
|
||||
|
||||
save_item(NAME(m_gfx2_base));
|
||||
|
||||
save_item(NAME(m_input_mux));
|
||||
save_item(NAME(m_mpx_p_1_2));
|
||||
@ -436,10 +446,10 @@ void laserbat_state_base::init_laserbat()
|
||||
save_item(NAME(m_neg1));
|
||||
save_item(NAME(m_neg2));
|
||||
|
||||
save_item(NAME(m_csound1));
|
||||
save_item(NAME(m_csound2));
|
||||
save_item(NAME(m_rhsc));
|
||||
save_item(NAME(m_whsc));
|
||||
save_item(NAME(m_csound1));
|
||||
save_item(NAME(m_csound2));
|
||||
}
|
||||
|
||||
void laserbat_state::machine_start()
|
||||
@ -732,7 +742,7 @@ ROM_START( catnmousa )
|
||||
ROM_END
|
||||
|
||||
|
||||
GAME( 1981, laserbat, 0, laserbat, laserbat, laserbat_state, init_laserbat, ROT0, "Zaccaria", "Laser Battle", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1981, lazarian, laserbat, laserbat, lazarian, laserbat_state, init_laserbat, ROT0, "Zaccaria (Bally Midway license)", "Lazarian", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1982, catnmous, 0, catnmous, catnmous, catnmous_state, init_laserbat, ROT90, "Zaccaria", "Cat and Mouse (type 02 program)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1982, catnmousa, catnmous, catnmous, catnmous, catnmous_state, init_laserbat, ROT90, "Zaccaria", "Cat and Mouse (type 01 program)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1981, laserbat, 0, laserbat, laserbat, laserbat_state, empty_init, ROT0, "Zaccaria", "Laser Battle", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1981, lazarian, laserbat, laserbat, lazarian, laserbat_state, empty_init, ROT0, "Zaccaria (Bally Midway license)", "Lazarian", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1982, catnmous, 0, catnmous, catnmous, catnmous_state, empty_init, ROT90, "Zaccaria", "Cat and Mouse (type 02 program)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1982, catnmousa, catnmous, catnmous, catnmous, catnmous_state, empty_init, ROT90, "Zaccaria", "Cat and Mouse (type 01 program)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -29,7 +29,14 @@
|
||||
class laserbat_state_base : public driver_device
|
||||
{
|
||||
public:
|
||||
laserbat_state_base(const machine_config &mconfig, device_type type, const char *tag)
|
||||
void laserbat_base(machine_config &config);
|
||||
void laserbat_io_map(address_map &map);
|
||||
void laserbat_map(address_map &map);
|
||||
|
||||
protected:
|
||||
enum { TIMER_SCANLINE };
|
||||
|
||||
laserbat_state_base(const machine_config &mconfig, device_type type, const char *tag, uint8_t eff2_mask)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_mux_ports(*this, {"ROW0", "ROW1", "SW1", "SW2"})
|
||||
, m_row1(*this, "ROW1")
|
||||
@ -40,39 +47,12 @@ public:
|
||||
, m_gfxmix(*this, "gfxmix")
|
||||
, m_pvi(*this, "pvi%u", 1U)
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_scanline_timer(nullptr)
|
||||
, m_gfx1(nullptr)
|
||||
, m_gfx2(nullptr)
|
||||
, m_input_mux(0)
|
||||
, m_mpx_p_1_2(false)
|
||||
, m_mpx_bkeff(false)
|
||||
, m_nave(false)
|
||||
, m_clr_lum(0)
|
||||
, m_shp(0)
|
||||
, m_wcoh(0)
|
||||
, m_wcov(0)
|
||||
, m_abeff1(false)
|
||||
, m_abeff2(false)
|
||||
, m_mpx_eff2_sh(false)
|
||||
, m_coleff(0)
|
||||
, m_neg1(false)
|
||||
, m_neg2(false)
|
||||
, m_rhsc(0)
|
||||
, m_whsc(0)
|
||||
, m_csound1(0)
|
||||
, m_csound2(0)
|
||||
, m_gfx1(*this, "gfx1")
|
||||
, m_gfx2(*this, "gfx2")
|
||||
, m_eff2_mask(eff2_mask)
|
||||
{
|
||||
}
|
||||
|
||||
void init_laserbat();
|
||||
|
||||
void laserbat_base(machine_config &config);
|
||||
void laserbat_io_map(address_map &map);
|
||||
void laserbat_map(address_map &map);
|
||||
|
||||
protected:
|
||||
enum { TIMER_SCANLINE };
|
||||
|
||||
// control ports
|
||||
void ct_io_w(uint8_t data);
|
||||
uint8_t rrowx_r();
|
||||
@ -93,7 +73,7 @@ protected:
|
||||
virtual void csound2_w(uint8_t data);
|
||||
|
||||
// running the video
|
||||
virtual void video_start() override;
|
||||
virtual void machine_start() override;
|
||||
uint32_t screen_update_laserbat(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
@ -102,55 +82,57 @@ protected:
|
||||
TIMER_CALLBACK_MEMBER(video_line);
|
||||
|
||||
// input lines
|
||||
required_ioport_array<4> m_mux_ports;
|
||||
required_ioport m_row1;
|
||||
required_ioport m_row2;
|
||||
required_ioport_array<4> m_mux_ports;
|
||||
required_ioport m_row1;
|
||||
required_ioport m_row2;
|
||||
|
||||
// main CPU device
|
||||
required_device<s2650_device> m_maincpu;
|
||||
required_device<s2650_device> m_maincpu;
|
||||
|
||||
// video devices
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<pla_device> m_gfxmix;
|
||||
required_device_array<s2636_device, 3> m_pvi;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<pla_device> m_gfxmix;
|
||||
required_device_array<s2636_device, 3> m_pvi;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
|
||||
// stuff for rendering video
|
||||
emu_timer *m_scanline_timer;
|
||||
bitmap_ind16 m_bitmap;
|
||||
uint8_t const *m_gfx1;
|
||||
uint8_t const *m_gfx2;
|
||||
required_region_ptr<uint8_t> m_gfx1;
|
||||
required_region_ptr<uint8_t> m_gfx2;
|
||||
emu_timer *m_scanline_timer = nullptr;
|
||||
bitmap_ind16 m_bitmap;
|
||||
uint16_t m_gfx2_base = 0;
|
||||
uint8_t const m_eff2_mask;
|
||||
|
||||
// control lines
|
||||
unsigned m_input_mux;
|
||||
uint8_t m_input_mux;
|
||||
bool m_mpx_p_1_2;
|
||||
|
||||
// RAM used by TTL video hardware, writable by CPU
|
||||
uint8_t m_bg_ram[0x400]; // background tilemap
|
||||
uint8_t m_eff_ram[0x400]; // per-scanline effects (A8 not wired meaning only half is usable)
|
||||
bool m_mpx_bkeff; // select between writing background and effects memory
|
||||
uint8_t m_bg_ram[0x400]; // background tilemap
|
||||
uint8_t m_eff_ram[0x400]; // per-scanline effects (A8 not wired meaning only half is usable)
|
||||
bool m_mpx_bkeff = false; // select between writing background and effects memory
|
||||
|
||||
// signals affecting the TTL-generated 32x32 sprite
|
||||
bool m_nave; // 1-bit enable
|
||||
unsigned m_clr_lum; // 3-bit colour/luminance
|
||||
unsigned m_shp; // 3-bit shape
|
||||
unsigned m_wcoh; // 8-bit offset horizontal
|
||||
unsigned m_wcov; // 8-bit offset vertical
|
||||
bool m_nave = false; // 1-bit enable
|
||||
uint8_t m_clr_lum = 0; // 3-bit colour/luminance
|
||||
uint8_t m_shp = 0; // 3-bit shape
|
||||
uint8_t m_wcoh = 0; // 8-bit offset horizontal
|
||||
uint8_t m_wcov = 0; // 8-bit offset vertical
|
||||
|
||||
// video effects signals
|
||||
bool m_abeff1; // 1-bit effect enable
|
||||
bool m_abeff2; // 1-bit effect enable
|
||||
bool m_mpx_eff2_sh; // 1-bit effect selection
|
||||
unsigned m_coleff; // 2-bit colour effect
|
||||
bool m_neg1; // 1-bit area selection
|
||||
bool m_neg2; // 1-bit area selection
|
||||
bool m_abeff1 = false; // 1-bit effect enable
|
||||
bool m_abeff2 = false; // 1-bit effect enable
|
||||
bool m_mpx_eff2_sh = false; // 1-bit effect selection
|
||||
uint8_t m_coleff = 0; // 2-bit colour effect
|
||||
bool m_neg1 = false; // 1-bit area selection
|
||||
bool m_neg2 = false; // 1-bit area selection
|
||||
|
||||
// sound board I/O signals
|
||||
unsigned m_rhsc; // 8-bit input from J7
|
||||
unsigned m_whsc; // 8-bit output to J7
|
||||
unsigned m_csound1; // bits 1-8 on J3
|
||||
unsigned m_csound2; // bits 9-16 on J3
|
||||
uint8_t m_rhsc = 0; // 8-bit input from J7
|
||||
uint8_t m_whsc = 0; // 8-bit output to J7
|
||||
uint8_t m_csound1 = 0; // bits 1-8 on J3
|
||||
uint8_t m_csound2 = 0; // bits 9-16 on J3
|
||||
};
|
||||
|
||||
|
||||
@ -158,11 +140,10 @@ class laserbat_state : public laserbat_state_base
|
||||
{
|
||||
public:
|
||||
laserbat_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: laserbat_state_base(mconfig, type, tag)
|
||||
: laserbat_state_base(mconfig, type, tag, 0x00)
|
||||
, m_csg(*this, "csg")
|
||||
, m_synth_low(*this, "synth_low")
|
||||
, m_synth_high(*this, "synth_high")
|
||||
, m_keys(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -184,7 +165,7 @@ protected:
|
||||
required_device<tms3615_device> m_synth_high;
|
||||
|
||||
// register state
|
||||
unsigned m_keys; // low octave keys 1-13 and high octave keys 2-12 (24 bits)
|
||||
uint32_t m_keys = 0; // low octave keys 1-13 and high octave keys 2-12 (24 bits)
|
||||
};
|
||||
|
||||
|
||||
@ -192,7 +173,7 @@ class catnmous_state : public laserbat_state_base
|
||||
{
|
||||
public:
|
||||
catnmous_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: laserbat_state_base(mconfig, type, tag)
|
||||
: laserbat_state_base(mconfig, type, tag, 0x03)
|
||||
, m_audiopcb(*this, "audiopcb")
|
||||
{
|
||||
}
|
||||
|
@ -157,18 +157,6 @@ void laserbat_state_base::cnt_nav_w(uint8_t data)
|
||||
}
|
||||
|
||||
|
||||
void laserbat_state_base::video_start()
|
||||
{
|
||||
// we render straight from ROM
|
||||
m_gfx1 = memregion("gfx1")->base();
|
||||
m_gfx2 = memregion("gfx2")->base();
|
||||
|
||||
// start rendering scanlines
|
||||
m_screen->register_screen_bitmap(m_bitmap);
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(1, 0));
|
||||
}
|
||||
|
||||
|
||||
uint32_t laserbat_state_base::screen_update_laserbat(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bool const flip_y = flip_screen_y(), flip_x = flip_screen_x();
|
||||
@ -281,16 +269,14 @@ TIMER_CALLBACK_MEMBER(laserbat_state_base::video_line)
|
||||
for (int x = 0, px = x_offset; max_x >= px; x++)
|
||||
{
|
||||
// calculate area effects
|
||||
// I have no idea where the magical x offset comes from but it's necessary
|
||||
bool const right_half = bool((x + 0) & 0x80);
|
||||
bool const eff1_cmp = right_half ? (uint8_t((x + 0) & 0x7f) < (eff1_val & 0x7f)) : (uint8_t((x + 0) & 0x7f) > (~eff1_val & 0x7f));
|
||||
bool const eff2_cmp = right_half ? (uint8_t((x + 0) & 0x7f) < (eff2_val & 0x7f)) : (uint8_t((x + 0) & 0x7f) > (~eff2_val & 0x7f));
|
||||
bool const right_half = bool(x & 0x80);
|
||||
bool const eff1_cmp = right_half ? (uint8_t(x & 0x7f) < (eff1_val & 0x7f)) : (uint8_t(x & 0x7f) > (~eff1_val & 0x7f));
|
||||
bool const eff2_cmp = right_half ? ((uint8_t(x & 0x7f) | m_eff2_mask) < ((eff2_val & 0x7f) | m_eff2_mask)) : ((uint8_t(x & 0x7f) | m_eff2_mask) > ((~eff2_val & 0x7f) | m_eff2_mask));
|
||||
bool const eff1 = m_abeff1 && (m_neg1 ? !eff1_cmp : eff1_cmp);
|
||||
bool const eff2 = m_abeff2 && (m_neg2 ? !eff2_cmp : eff2_cmp) && m_mpx_eff2_sh;
|
||||
|
||||
// calculate shell point effect
|
||||
// using the same magical offset as the area effects
|
||||
bool const shell = m_abeff2 && (uint8_t((x + 0) & 0xff) == (eff2_val & 0xff)) && !m_mpx_eff2_sh;
|
||||
bool const shell = m_abeff2 && ((uint8_t(x & 0xff) | m_eff2_mask) == ((eff2_val & 0xff) | m_eff2_mask)) && !m_mpx_eff2_sh;
|
||||
|
||||
// set effect bits, and mix in PVI graphics while we're here
|
||||
uint16_t const effect_bits = (shell ? 0x0800 : 0x0000) | (eff1 ? 0x1000 : 0x0000) | (eff2 ? 0x2000 : 0x0000);
|
||||
@ -305,7 +291,7 @@ TIMER_CALLBACK_MEMBER(laserbat_state_base::video_line)
|
||||
}
|
||||
|
||||
// render the TTL-generated sprite
|
||||
// more magic offsets here I don't understand the source of
|
||||
// magic offsets here I don't understand the source of
|
||||
if (m_nave)
|
||||
{
|
||||
int const sprite_row = y + y_offset - ((256 - m_wcov) & 0x0ff);
|
||||
@ -313,7 +299,7 @@ TIMER_CALLBACK_MEMBER(laserbat_state_base::video_line)
|
||||
{
|
||||
for (unsigned byte = 0, x = x_offset + (3 * ((256 - m_wcoh + 5) & 0x0ff)); 8 > byte; byte++)
|
||||
{
|
||||
uint8_t bits = m_gfx2[((m_shp << 8) & 0x700) | ((sprite_row << 3) & 0x0f8) | (byte & 0x07)];
|
||||
uint8_t bits = m_gfx2[m_gfx2_base | ((m_shp << 8) & 0x700) | ((sprite_row << 3) & 0x0f8) | (byte & 0x07)];
|
||||
for (unsigned pixel = 0; 4 > pixel; pixel++, bits <<= 2)
|
||||
{
|
||||
if (max_x >= x) row[x++] |= (bits >> 6) & 0x03;
|
||||
|
Loading…
Reference in New Issue
Block a user