summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2025-01-01 20:48:58 +0100
committer hap <happppp@users.noreply.github.com>2025-01-01 21:39:27 +0100
commita4b4ef9af8a93dcfe21dcab3cc2e603189b24f58 (patch)
treea4c9e5e86084aac6ecd5748909d96a9bef3056a6
parentfa893c6871bca0d57069100979b70d237c5d5b8c (diff)
scyclone: small cleanup (no functional changes),
konamim2: clarify gun switch
-rw-r--r--src/mame/konami/konamim2.cpp9
-rw-r--r--src/mame/taito/scyclone.cpp478
2 files changed, 275 insertions, 212 deletions
diff --git a/src/mame/konami/konamim2.cpp b/src/mame/konami/konamim2.cpp
index 10449202150..6cfb2cd5c5d 100644
--- a/src/mame/konami/konamim2.cpp
+++ b/src/mame/konami/konamim2.cpp
@@ -288,7 +288,7 @@ public:
void init_btltryst();
void init_hellngt();
- template<int N> ioport_value evilngt_aim_up() { return m_guny[N]->read() ? 0 : 1; }
+ template<int N> ioport_value evilngt_aim_up();
protected:
virtual void machine_start() override ATTR_COLD;
@@ -425,6 +425,13 @@ void konamim2_state::ata_int(int state)
*
*************************************/
+template<int N>
+ioport_value konamim2_state::evilngt_aim_up()
+{
+ // when P1/P3 gun is aimed up, it triggers a mercury switch inside the gun
+ return (m_guny[N]->read() > 0) ? 0 : 1;
+}
+
uint16_t konamim2_state::konami_io0_r(offs_t offset)
{
// printf("IO R: %08X\n", offset);
diff --git a/src/mame/taito/scyclone.cpp b/src/mame/taito/scyclone.cpp
index 34d5326c53d..02f4345f915 100644
--- a/src/mame/taito/scyclone.cpp
+++ b/src/mame/taito/scyclone.cpp
@@ -59,10 +59,13 @@ public:
scyclone_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
+ m_subcpu(*this, "subcpu"),
m_gfxdecode(*this, "gfxdecode"),
m_stars(*this, "stars"),
m_gfx1pal(*this, "gfx1pal"),
m_palette(*this, "palette"),
+ m_snsnd(*this, "snsnd%u", 0),
+ m_dac(*this, "dac%u", 0),
m_soundlatch(*this, "soundlatch")
{ }
@@ -70,47 +73,32 @@ public:
int collision_r();
-private:
- void vidctrl_w(uint8_t data);
-
- void sprite_xpos_w(uint8_t data);
- void sprite_ypos_w(uint8_t data);
- void sprite_colour_w(uint8_t data);
- void sprite_tile_w(uint8_t data);
- void starscroll_w(uint8_t data);
- void port0e_w(uint8_t data);
- void port06_w(uint8_t data);
- void videomask1_w(uint8_t data);
- void videomask2_w(uint8_t data);
- void vram_w(offs_t offset, uint8_t data);
- uint8_t vram_r(offs_t offset);
- void snd_3001_w(uint8_t data);
-// void snd_3003_w(uint8_t data);
-// void snd_3004_w(uint8_t data);
- void snd_3005_w(uint8_t data);
-
- uint32_t screen_update_scyclone(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- INTERRUPT_GEN_MEMBER(irq);
-
-
- void scyclone_iomap(address_map &map) ATTR_COLD;
- void scyclone_map(address_map &map) ATTR_COLD;
- void scyclone_sub_iomap(address_map &map) ATTR_COLD;
- void scyclone_sub_map(address_map &map) ATTR_COLD;
-
+protected:
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
virtual void video_start() override ATTR_COLD;
+private:
+ // devices
required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_subcpu;
required_device<gfxdecode_device> m_gfxdecode;
required_region_ptr<uint8_t> m_stars;
required_region_ptr<uint8_t> m_gfx1pal;
required_device<palette_device> m_palette;
+ required_device_array<sn76477_device, 2> m_snsnd;
+ required_device_array<dac_byte_interface, 2> m_dac;
required_device<generic_latch_8_device> m_soundlatch;
- /* memory pointers */
+ void scyclone_iomap(address_map &map) ATTR_COLD;
+ void scyclone_map(address_map &map) ATTR_COLD;
+ void scyclone_sub_iomap(address_map &map) ATTR_COLD;
+ void scyclone_sub_map(address_map &map) ATTR_COLD;
+
+ INTERRUPT_GEN_MEMBER(main_irq);
+ INTERRUPT_GEN_MEMBER(sound_irq);
+
+ // video-related
std::unique_ptr<uint8_t[]> m_vram;
uint8_t m_videowritemask = 0;
@@ -126,18 +114,38 @@ private:
uint8_t m_hascollided = 0;
- /* video-related */
const uint8_t get_sprite_pixel(int x, int y);
const uint8_t get_bitmap_pixel(int x, int y);
uint32_t draw_starfield(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t draw_bitmap_and_sprite(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ uint32_t screen_update_scyclone(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ void vidctrl_w(uint8_t data);
+ void sprite_xpos_w(uint8_t data);
+ void sprite_ypos_w(uint8_t data);
+ void sprite_colour_w(uint8_t data);
+ void sprite_tile_w(uint8_t data);
+ void starscroll_w(uint8_t data);
+ void port0e_w(uint8_t data);
+ void port06_w(uint8_t data);
+ void videomask1_w(uint8_t data);
+ void videomask2_w(uint8_t data);
+ void vram_w(offs_t offset, uint8_t data);
+ uint8_t vram_r(offs_t offset);
+
+ // sound related
+ void snd_3001_w(uint8_t data);
+ void snd_3003_w(uint8_t data);
+ void snd_3004_w(uint8_t data);
+ void snd_3005_w(uint8_t data);
};
/***************************************************************************
- Start the video hardware emulation.
+ Video hardware
***************************************************************************/
@@ -146,9 +154,6 @@ void scyclone_state::video_start()
m_vram = std::make_unique<uint8_t []>(0x3800*3);
save_pointer(&m_vram[0], "m_vram", 0x3800*3);
- m_videowritemask = 0x00;
- m_videowritemask2 = 0x00;
-
for (int i = 0; i < 8; i++)
m_palette->set_pen_color(i, rgb_t(pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2)));
@@ -161,15 +166,15 @@ void scyclone_state::video_start()
const uint8_t scyclone_state::get_sprite_pixel(int x, int y)
{
- int minx = 0xe0-m_sprite_xpos;
- int miny = 0xe0-m_sprite_ypos;
+ int minx = 0xe0 - m_sprite_xpos;
+ int miny = 0xe0 - m_sprite_ypos;
int col = m_sprite_colour & 3;
int code = m_sprite_tile & 7;
int maxx = minx + 32;
int maxy = miny + 32;
- /* if we're not even inside the sprite, return nothing */
+ // if we're not even inside the sprite, return nothing
if (x < minx || x >= maxx)
return 0;
@@ -181,7 +186,7 @@ const uint8_t scyclone_state::get_sprite_pixel(int x, int y)
const uint8_t* srcdata = m_gfxdecode->gfx(0)->get_data(code);
- uint8_t pix = srcdata[spry*32 + sprx] + col*4;
+ uint8_t pix = srcdata[spry * 32 + sprx] + col * 4;
return pix;
}
@@ -189,9 +194,9 @@ const uint8_t scyclone_state::get_sprite_pixel(int x, int y)
const uint8_t scyclone_state::get_bitmap_pixel(int x, int y)
{
- const uint8_t video_data0 = m_vram[(y*32+(x/8))];
- const uint8_t video_data1 = m_vram[(y*32+(x/8))+0x3800];
- const uint8_t video_data2 = m_vram[(y*32+(x/8))+0x3800+0x3800];
+ const uint8_t video_data0 = m_vram[(y * 32 + (x / 8))];
+ const uint8_t video_data1 = m_vram[(y * 32 + (x / 8)) + 0x3800];
+ const uint8_t video_data2 = m_vram[(y * 32 + (x / 8)) + 0x3800 + 0x3800];
int const bit(x & 0x07);
@@ -199,7 +204,7 @@ const uint8_t scyclone_state::get_bitmap_pixel(int x, int y)
const uint8_t plane1(BIT(video_data1, bit));
const uint8_t plane2(BIT(video_data2, bit));
- const uint8_t pal = plane0 | (plane1<<1) | (plane2<<2);
+ const uint8_t pal = plane0 | (plane1 << 1) | (plane2 << 2);
return pal;
}
@@ -208,23 +213,21 @@ uint32_t scyclone_state::draw_starfield(screen_device &screen, bitmap_rgb32 &bit
{
const pen_t *paldata = m_palette->pens();
- // this is not correct, but the first 0x80 bytes of the PROM are blank suggesting that this
- // part is for the non-visible 32 rows at least, so it should be something like this
- // blinking and colours are not understood at all
-
-
+ // This is not correct, but the first 0x80 bytes of the PROM are blank suggesting that this
+ // part is for the non-visible 32 rows at least, so it should be something like this.
+ // Blinking and colours are not understood at all.
- for (int strip=0;strip<16;strip++)
+ for (int strip = 0; strip < 16; strip++)
{
- for (int x=0;x<256;x++)
+ for (int x = 0; x < 256; x++)
{
- const uint8_t star = m_stars[((x+m_starscroll) & 0x3f)+(strip*0x40)];
+ const uint8_t star = m_stars[((x + m_starscroll) & 0x3f) + (strip * 0x40)];
- for (int y=0;y<16;y++)
+ for (int y = 0; y < 16; y++)
{
- const int ypos = (y+16*strip)-32;
+ const int ypos = (y + 16 * strip) - 32;
- if (ypos>=0 && ypos<256)
+ if (ypos >= 0 && ypos < 256)
{
int noclipped = 0;
@@ -233,7 +236,6 @@ uint32_t scyclone_state::draw_starfield(screen_device &screen, bitmap_rgb32 &bit
else
noclipped = x >= 64;
-
if (y == star && star != 0 && noclipped)
bitmap.pix(ypos, x) = paldata[7];
else
@@ -251,19 +253,19 @@ uint32_t scyclone_state::draw_bitmap_and_sprite(screen_device &screen, bitmap_rg
const pen_t *paldata = m_palette->pens();
m_hascollided = 0;
- for (int y=0;y<256-32;y++)
+ for (int y = 0; y < 256-32; y++)
{
- for (int x=0;x<256/8;x++)
+ for (int x = 0; x < 256/8; x++)
{
- for (int i=0;i<8;i++)
+ for (int i = 0; i < 8; i++)
{
int realx = 0;
int realy = 0;
if (m_vidctrl & 0x08)
{
- realx = 255 - ((x*8)+i);
- realy = 255-32-y;
+ realx = 255 - ((x*8) + i);
+ realy = 255 - 32 - y;
}
else
{
@@ -271,16 +273,15 @@ uint32_t scyclone_state::draw_bitmap_and_sprite(screen_device &screen, bitmap_rg
realy = y;
}
-
uint8_t pal = get_bitmap_pixel(realx, realy);
- if (pal) bitmap.pix(y, (x*8)+i) = paldata[pal];
+ if (pal) bitmap.pix(y, (x*8) + i) = paldata[pal];
uint8_t pal2 = get_sprite_pixel(realx, realy);
if (pal2 & 0x3)
{
- bitmap.pix(y, (x*8)+i) = paldata[8+pal2];
+ bitmap.pix(y, (x*8) + i) = paldata[8 + pal2];
if (pal == 0x7) m_hascollided = 1;
}
}
@@ -302,113 +303,16 @@ uint32_t scyclone_state::screen_update_scyclone(screen_device &screen, bitmap_rg
}
-
-void scyclone_state::scyclone_map(address_map &map)
-{
- map(0x0000, 0x2fff).rom();
- map(0x4000, 0x43ff).ram();
- map(0x4400, 0x5fff).rw(FUNC(scyclone_state::vram_r), FUNC(scyclone_state::vram_w));
- map(0x6000, 0x60ff).noprw(); // this just seems to be overflow from the VRAM writes, probably goes nowhere
-}
-
-
-void scyclone_state::scyclone_iomap(address_map &map)
-{
- map.global_mask(0xff);
- map(0x00, 0x00).r("mb14241", FUNC(mb14241_device::shift_result_r)).w("mb14241", FUNC(mb14241_device::shift_count_w));
- map(0x01, 0x01).portr("IN0").w("mb14241", FUNC(mb14241_device::shift_data_w));
- map(0x02, 0x02).portr("IN1");
- map(0x03, 0x03).portr("DSW0").w(FUNC(scyclone_state::vidctrl_w));
- map(0x04, 0x04).w(FUNC(scyclone_state::sprite_xpos_w));
- map(0x05, 0x05).w(FUNC(scyclone_state::sprite_ypos_w));
- map(0x06, 0x06).w(FUNC(scyclone_state::port06_w)); // possible watchdog, unlikely to be twinkle related.
- map(0x08, 0x08).w(FUNC(scyclone_state::sprite_colour_w));
- map(0x09, 0x09).w(FUNC(scyclone_state::sprite_tile_w));
- map(0x0a, 0x0a).w(FUNC(scyclone_state::starscroll_w));
- map(0x0e, 0x0e).w(FUNC(scyclone_state::port0e_w));
- map(0x0f, 0x0f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
- map(0x40, 0x40).w(FUNC(scyclone_state::videomask1_w));
- map(0x80, 0x80).w(FUNC(scyclone_state::videomask2_w));
-}
-
-
-void scyclone_state::scyclone_sub_map(address_map &map)
-{
- map(0x0000, 0x1fff).rom();
- map(0x2000, 0x23ff).ram();
-
- map(0x3000, 0x3000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w("dac", FUNC(dac_byte_interface::data_w)); // music
- map(0x3001, 0x3001).w(FUNC(scyclone_state::snd_3001_w)); // written at the same time, with the same data as 0x3005
- map(0x3002, 0x3002).w("dac2", FUNC(dac_byte_interface::data_w)); // speech
-// map(0x3003, 0x3003).w(FUNC(scyclone_state::snd_3003_w)); // writes 02 or 00
-// map(0x3004, 0x3004).w(FUNC(scyclone_state::snd_3004_w)); // always writes 00?
- map(0x3005, 0x3005).w(FUNC(scyclone_state::snd_3005_w)); // written at the same time, with the same data as 0x3001
-}
-
-void scyclone_state::scyclone_sub_iomap(address_map &map)
-{
- map.global_mask(0xff);
-}
-
-
-// appears to be when a white bitmap pixel (col 0x7) collides with a large sprite?
-// if you simply set it to 1 and shoot in the left corner, the game gets stuck
-// but if you have it set to 0 there are no collisions with large objects
-int scyclone_state::collision_r()
-{
- return m_hascollided;
-}
-
-
-static INPUT_PORTS_START( scyclone )
- PORT_START("IN0")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_TILT )
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_START2 )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN1 )
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 )
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY
-
- PORT_START("IN1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(FUNC(scyclone_state::collision_r)) // hw collision?
- // maybe these 4 are the 4xdsw bank?
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL PORT_CONDITION("DSW0",0x04,EQUALS,0x00)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_COCKTAIL PORT_CONDITION("DSW0",0x04,EQUALS,0x00)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_COCKTAIL PORT_CONDITION("DSW0",0x04,EQUALS,0x00)
-
- PORT_START("DSW0")
- PORT_DIPNAME( 0x03, 0x01, DEF_STR( Lives ) ) PORT_DIPLOCATION("DSW0:1,2")
- PORT_DIPSETTING( 0x00, "2" )
- PORT_DIPSETTING( 0x01, "3" )
- PORT_DIPSETTING( 0x02, "4" )
- PORT_DIPSETTING( 0x03, "5" )
- PORT_DIPNAME( 0x04, 0x04, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("DSW0:3")
- PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
- PORT_DIPSETTING( 0x04, DEF_STR( Upright ) )
- PORT_DIPNAME( 0x08, 0x00, "Disable Collision (Buggy!)" ) PORT_DIPLOCATION("DSW0:4") // this causes the game to malfunction, likely leftover debug feature
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x08, DEF_STR( On ) )
- PORT_DIPNAME( 0x10, 0x00, "Show Copyright Date" ) PORT_DIPLOCATION("DSW0:5")
- PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "DSW0:6" )
- PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "DSW0:7" )
- PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "DSW0:8" )
-INPUT_PORTS_END
+// Memory handlers
uint8_t scyclone_state::vram_r(offs_t offset)
{
uint8_t ret = 0;
+
// not sure, collisions depend on readback
ret |= m_vram[offset];
- ret |= m_vram[offset+0x3800];
- ret |= m_vram[offset+0x3800+0x3800];
+ ret |= m_vram[offset + 0x3800];
+ ret |= m_vram[offset + 0x3800 + 0x3800];
return ret;
}
@@ -421,12 +325,12 @@ void scyclone_state::vram_w(offs_t offset, uint8_t data)
// this is used when drawing the pointing stick, need closeup reference
// 0x40 and 0x80 ports always seem equal tho
- if ((m_videowritemask & 0xf) != ((m_videowritemask>>4) & 0xf))
+ if ((m_videowritemask & 0xf) != ((m_videowritemask >> 4) & 0xf))
{
logerror("m_videowritemask halves not equal %02x\n", m_videowritemask);
}
- if ((m_videowritemask2 & 0xf) != ((m_videowritemask2>>4) & 0xf))
+ if ((m_videowritemask2 & 0xf) != ((m_videowritemask2 >> 4) & 0xf))
{
logerror("m_videowritemask2 halves not equal %02x\n", m_videowritemask2);
}
@@ -437,27 +341,26 @@ void scyclone_state::vram_w(offs_t offset, uint8_t data)
}
#endif
-
- for (int i=0; i<8; i++)
+ for (int i = 0; i < 8; i++)
{
- const uint8_t databit = data & (1<<i);
- const uint8_t nodatabit = (1<<i);
+ const uint8_t databit = data & (1 << i);
+ const uint8_t nodatabit = (1 << i);
uint8_t videowritemask = 0;
- if (i>=6) videowritemask = (m_videowritemask>>4) & 0x0f;
- else if (i>=4) videowritemask = (m_videowritemask>>0) & 0x0f;
- else if (i>=2) videowritemask = (m_videowritemask2>>4) & 0x0f;
- else videowritemask = (m_videowritemask2>>0) & 0x0f;
+ if (i >= 6) videowritemask = (m_videowritemask >> 4) & 0x0f;
+ else if (i >= 4) videowritemask = (m_videowritemask >> 0) & 0x0f;
+ else if (i >= 2) videowritemask = (m_videowritemask2 >> 4) & 0x0f;
+ else videowritemask = (m_videowritemask2 >> 0) & 0x0f;
if (!(videowritemask & 1) && databit) m_vram[offset] |= databit;
else m_vram[offset] &= ~nodatabit;
- if (!(videowritemask & 2) && databit) m_vram[offset+0x3800] |= databit;
- else m_vram[offset+0x3800] &= ~nodatabit;
+ if (!(videowritemask & 2) && databit) m_vram[offset + 0x3800] |= databit;
+ else m_vram[offset + 0x3800] &= ~nodatabit;
- if (!(videowritemask & 4) && databit) m_vram[offset+0x3800+0x3800] |= databit;
- else m_vram[offset+0x3800+0x3800] &= ~nodatabit;
+ if (!(videowritemask & 4) && databit) m_vram[offset + 0x3800 + 0x3800] |= databit;
+ else m_vram[offset + 0x3800 + 0x3800] &= ~nodatabit;
}
}
@@ -528,7 +431,22 @@ void scyclone_state::videomask2_w(uint8_t data)
m_videowritemask2 = data;
}
-// Sound CPU handlers
+
+int scyclone_state::collision_r()
+{
+ // Appears to be when a white bitmap pixel (col 0x7) collides with a large sprite?
+ // If you simply set it to 1 and shoot in the left corner, the game gets stuck,
+ // but if you have it set to 0 there are no collisions with large objects.
+ return m_hascollided;
+}
+
+
+
+/***************************************************************************
+
+ Sound hardware
+
+***************************************************************************/
void scyclone_state::snd_3001_w(uint8_t data)
{
@@ -538,32 +456,156 @@ void scyclone_state::snd_3001_w(uint8_t data)
m_soundlatch->clear_w();
}
-/*
void scyclone_state::snd_3003_w(uint8_t data)
{
-// m_soundlatch->clear_w();
}
void scyclone_state::snd_3004_w(uint8_t data)
{
-// m_soundlatch->clear_w();
+ // always writes 00?
}
-*/
void scyclone_state::snd_3005_w(uint8_t data)
{
-// m_soundlatch->clear_w();
+ // written at the same time, with the same data as 0x3001
+}
+
+INTERRUPT_GEN_MEMBER(scyclone_state::sound_irq)
+{
+ m_subcpu->set_input_line(0, HOLD_LINE);
+}
+
+
+
+/***************************************************************************
+
+ Address maps
+
+***************************************************************************/
+
+void scyclone_state::scyclone_map(address_map &map)
+{
+ map(0x0000, 0x2fff).rom();
+ map(0x4000, 0x43ff).ram();
+ map(0x4400, 0x5fff).rw(FUNC(scyclone_state::vram_r), FUNC(scyclone_state::vram_w));
+ map(0x6000, 0x60ff).noprw(); // this just seems to be overflow from the VRAM writes, probably goes nowhere
}
+void scyclone_state::scyclone_iomap(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x00).r("mb14241", FUNC(mb14241_device::shift_result_r)).w("mb14241", FUNC(mb14241_device::shift_count_w));
+ map(0x01, 0x01).portr("IN0").w("mb14241", FUNC(mb14241_device::shift_data_w));
+ map(0x02, 0x02).portr("IN1");
+ map(0x03, 0x03).portr("DSW0").w(FUNC(scyclone_state::vidctrl_w));
+ map(0x04, 0x04).w(FUNC(scyclone_state::sprite_xpos_w));
+ map(0x05, 0x05).w(FUNC(scyclone_state::sprite_ypos_w));
+ map(0x06, 0x06).w(FUNC(scyclone_state::port06_w)); // possible watchdog, unlikely to be twinkle related.
+ map(0x08, 0x08).w(FUNC(scyclone_state::sprite_colour_w));
+ map(0x09, 0x09).w(FUNC(scyclone_state::sprite_tile_w));
+ map(0x0a, 0x0a).w(FUNC(scyclone_state::starscroll_w));
+ map(0x0e, 0x0e).w(FUNC(scyclone_state::port0e_w));
+ map(0x0f, 0x0f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
+ map(0x40, 0x40).w(FUNC(scyclone_state::videomask1_w));
+ map(0x80, 0x80).w(FUNC(scyclone_state::videomask2_w));
+}
+
+
+void scyclone_state::scyclone_sub_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom();
+ map(0x2000, 0x23ff).ram();
+
+ map(0x3000, 0x3000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w(m_dac[0], FUNC(dac_byte_interface::data_w)); // music
+ map(0x3001, 0x3001).w(FUNC(scyclone_state::snd_3001_w));
+ map(0x3002, 0x3002).w(m_dac[1], FUNC(dac_byte_interface::data_w)); // speech
+ map(0x3003, 0x3003).w(FUNC(scyclone_state::snd_3003_w));
+ map(0x3004, 0x3004).w(FUNC(scyclone_state::snd_3004_w));
+ map(0x3005, 0x3005).w(FUNC(scyclone_state::snd_3005_w));
+}
+
+void scyclone_state::scyclone_sub_iomap(address_map &map)
+{
+ map.global_mask(0xff);
+}
+
+
+
+/***************************************************************************
+
+ Input ports
+
+***************************************************************************/
+
+static INPUT_PORTS_START( scyclone )
+ PORT_START("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_TILT )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_START2 )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN1 )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY
+
+ PORT_START("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(FUNC(scyclone_state::collision_r)) // hw collision?
+ // maybe these 4 are the 4xdsw bank?
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL PORT_CONDITION("DSW0", 0x04, EQUALS, 0x00)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_COCKTAIL PORT_CONDITION("DSW0", 0x04, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_COCKTAIL PORT_CONDITION("DSW0", 0x04, EQUALS, 0x00)
+
+ PORT_START("DSW0")
+ PORT_DIPNAME( 0x03, 0x01, DEF_STR( Lives ) ) PORT_DIPLOCATION("DSW0:1,2")
+ PORT_DIPSETTING( 0x00, "2" )
+ PORT_DIPSETTING( 0x01, "3" )
+ PORT_DIPSETTING( 0x02, "4" )
+ PORT_DIPSETTING( 0x03, "5" )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("DSW0:3")
+ PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Upright ) )
+ PORT_DIPNAME( 0x08, 0x00, "Disable Collision (Buggy!)" ) PORT_DIPLOCATION("DSW0:4") // this causes the game to malfunction, likely leftover debug feature
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x00, "Show Copyright Date" ) PORT_DIPLOCATION("DSW0:5")
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "DSW0:6" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "DSW0:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "DSW0:8" )
+INPUT_PORTS_END
+
+
+
+/***************************************************************************
+
+ GFX Layouts
+
+***************************************************************************/
+
static const gfx_layout tiles32x32_layout =
{
32,32,
RGN_FRAC(1,1),
2,
{ 0, 4 },
- { 0, 1, 2, 3, 256+0, 256+1, 256+2, 256+3, 512+0, 512+1, 512+2, 512+3, 768+0, 768+1, 768+2, 768+3, 1024+0, 1024+1, 1024+2, 1024+3, 1280+0, 1280+1, 1280+2, 1280+3, 1536+0, 1536+1, 1536+2, 1536+3, 1792+0, 1792+1, 1792+2, 1792+3 },
- { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8, 16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8, 24*8, 25*8, 26*8, 27*8, 28*8, 29*8, 30*8, 31*8 },
+ {
+ 0, 1, 2, 3, 256+0, 256+1, 256+2, 256+3,
+ 512+0, 512+1, 512+2, 512+3, 768+0, 768+1, 768+2, 768+3,
+ 1024+0, 1024+1, 1024+2, 1024+3, 1280+0, 1280+1, 1280+2, 1280+3,
+ 1536+0, 1536+1, 1536+2, 1536+3, 1792+0, 1792+1, 1792+2, 1792+3
+ },
+ {
+ 0*8, 1*8, 2*8 , 3*8, 4*8, 5*8, 6*8, 7*8,
+ 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8,
+ 16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8,
+ 24*8, 25*8, 26*8, 27*8, 28*8, 29*8, 30*8, 31*8
+ },
8*32*8
};
@@ -573,6 +615,12 @@ GFXDECODE_END
+/***************************************************************************
+
+ Machine initialization
+
+***************************************************************************/
+
void scyclone_state::machine_start()
{
save_item(NAME(m_videowritemask));
@@ -601,34 +649,37 @@ void scyclone_state::machine_reset()
-INTERRUPT_GEN_MEMBER(scyclone_state::irq)
+/***************************************************************************
+
+ Machine configs
+
+***************************************************************************/
+
+INTERRUPT_GEN_MEMBER(scyclone_state::main_irq)
{
// CPU runs in IM0
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xd7); /* Z80 - RST 10h */
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xd7); // Z80 - RST 10h
}
-
void scyclone_state::scyclone(machine_config &config)
{
- /* basic machine hardware */
- Z80(config, m_maincpu, 5000000/2); // MOSTEK Z80-CPU ? MHz (there's also a 9.987MHz XTAL) intermissions seem driven directly by CPU speed for reference
+ // basic machine hardware
+ Z80(config, m_maincpu, 5_MHz_XTAL/2); // MOSTEK Z80-CPU 2.5MHz? (there's also a 9.987MHz XTAL), intermissions seem driven directly by CPU speed for reference
m_maincpu->set_addrmap(AS_PROGRAM, &scyclone_state::scyclone_map);
m_maincpu->set_addrmap(AS_IO, &scyclone_state::scyclone_iomap);
- m_maincpu->set_vblank_int("screen", FUNC(scyclone_state::irq));
+ m_maincpu->set_vblank_int("screen", FUNC(scyclone_state::main_irq));
- // sound ?
- z80_device &subcpu(Z80(config, "subcpu", 5000000/2)); // LH0080 Z80-CPU SHARP ? MHz (5Mhz XTAL on this sub-pcb)
- subcpu.set_addrmap(AS_PROGRAM, &scyclone_state::scyclone_sub_map);
- subcpu.set_addrmap(AS_IO, &scyclone_state::scyclone_sub_iomap);
+ Z80(config, m_subcpu, 5_MHz_XTAL/2); // LH0080 Z80-CPU SHARP 2.5MHz (5Mhz XTAL on this sub-pcb)
+ m_subcpu->set_addrmap(AS_PROGRAM, &scyclone_state::scyclone_sub_map);
+ m_subcpu->set_addrmap(AS_IO, &scyclone_state::scyclone_sub_iomap);
// no idea, but it does wait on an irq in places, irq0 increases a register checked in the wait loop so without it sound dies after a while
- subcpu.set_periodic_int(FUNC(scyclone_state::irq0_line_hold), attotime::from_hz(400*60));
+ m_subcpu->set_periodic_int(FUNC(scyclone_state::sound_irq), attotime::from_hz(400*60));
GENERIC_LATCH_8(config, m_soundlatch);
- /* add shifter */
MB14241(config, "mb14241");
- /* video hardware */
+ // video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
@@ -640,23 +691,28 @@ void scyclone_state::scyclone(machine_config &config)
GFXDECODE(config, m_gfxdecode, m_palette, gfx_scyclone);
PALETTE(config, m_palette).set_entries(8 + 4*4);
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "speaker").front_center();
- sn76477_device &snsnd0(SN76477(config, "snsnd0"));
- snsnd0.set_enable(1);
- snsnd0.add_route(ALL_OUTPUTS, "speaker", 0.2);
+ SN76477(config, m_snsnd[0]);
+ m_snsnd[0]->set_enable(1);
+ m_snsnd[0]->add_route(ALL_OUTPUTS, "speaker", 0.2);
+
+ SN76477(config, m_snsnd[1]);
+ m_snsnd[1]->set_enable(1);
+ m_snsnd[1]->add_route(ALL_OUTPUTS, "speaker", 0.2);
- sn76477_device &snsnd1(SN76477(config, "snsnd1"));
- snsnd1.set_enable(1);
- snsnd1.add_route(ALL_OUTPUTS, "speaker", 0.2);
+ DAC_8BIT_R2R(config, m_dac[0]).add_route(ALL_OUTPUTS, "speaker", 0.25); // unknown DAC
+ DAC_8BIT_R2R(config, m_dac[1]).add_route(ALL_OUTPUTS, "speaker", 0.25); // unknown DAC
+}
- // this is just taken from route16.cpp
- DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); // unknown DAC
- DAC_8BIT_R2R(config, "dac2", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); // unknown DAC
-}
+/***************************************************************************
+
+ ROM definitions
+
+***************************************************************************/
ROM_START( scyclone )
ROM_REGION( 0x3000, "maincpu", 0 )
@@ -690,4 +746,4 @@ ROM_END
} // anonymous namespace
-GAME( 1980, scyclone, 0, scyclone, scyclone, scyclone_state, empty_init, ROT270, "Taito Corporation", "Space Cyclone", MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1980, scyclone, 0, scyclone, scyclone, scyclone_state, empty_init, ROT270, "Taito Corporation", "Space Cyclone", MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )