summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ivan Vangelista <mesgnet@yahoo.it>2022-08-25 17:27:32 +0200
committer Ivan Vangelista <mesgnet@yahoo.it>2022-08-25 17:27:32 +0200
commit278ebb10d53336d6bc458e62edd824ebb7cd6ac6 (patch)
treeb03cf49b21c82768f19a6f744e4ffdd14154c7b4
parent94afa5a44a2ad60c1a4131ebc418536b0f18dcda (diff)
sega/deniam.cpp, sega/kopunch.cpp, sega/stactics.cpp, sega/suprloco.cpp: consolidated drivers in single files, minor cleanups
-rw-r--r--src/mame/sega/deniam.cpp682
-rw-r--r--src/mame/sega/deniam.h95
-rw-r--r--src/mame/sega/deniam_v.cpp374
-rw-r--r--src/mame/sega/kopunch.cpp236
-rw-r--r--src/mame/sega/kopunch.h72
-rw-r--r--src/mame/sega/kopunch_v.cpp117
-rw-r--r--src/mame/sega/stactics.cpp604
-rw-r--r--src/mame/sega/stactics.h130
-rw-r--r--src/mame/sega/stactics_v.cpp431
-rw-r--r--src/mame/sega/suprloco.cpp393
-rw-r--r--src/mame/sega/suprloco.h60
-rw-r--r--src/mame/sega/suprloco_v.cpp256
12 files changed, 1692 insertions, 1758 deletions
diff --git a/src/mame/sega/deniam.cpp b/src/mame/sega/deniam.cpp
index 744677dfa14..73527138f34 100644
--- a/src/mame/sega/deniam.cpp
+++ b/src/mame/sega/deniam.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
+// copyright-holders: Nicola Salmoria
+
/***************************************************************************
Deniam games
@@ -44,84 +45,566 @@ Notes:
***************************************************************************/
#include "emu.h"
-#include "deniam.h"
#include "cpu/m68000/m68000.h"
#include "cpu/z80/z80.h"
+#include "machine/gen_latch.h"
#include "sound/okim6295.h"
#include "sound/ymopl.h"
+
+#include "emupal.h"
#include "screen.h"
#include "speaker.h"
+#include "tilemap.h"
+
+
+namespace {
+
+class deniamc_state : public driver_device
+{
+public:
+ deniamc_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_oki(*this, "oki"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_palette(*this, "palette"),
+ m_videoram(*this, "videoram"),
+ m_textram(*this, "textram"),
+ m_spriteram(*this, "spriteram"),
+ m_spritegfx(*this, "spritegfx")
+ { }
+
+ void deniam16c(machine_config &config);
+
+ void init_logicpro();
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void video_start() override;
+
+ // devices
+ required_device<cpu_device> m_maincpu;
+ required_device<okim6295_device> m_oki;
+
+ // configuration
+ u16 m_bg_scrollx_offs = 0;
+ u8 m_bg_scrolly_offs = 0;
+ u16 m_fg_scrollx_offs = 0;
+ u8 m_fg_scrolly_offs = 0;
+ u8 m_bg_scrollx_reg = 0;
+ u8 m_bg_scrolly_reg = 0;
+ u8 m_bg_page_reg = 0;
+ u8 m_fg_scrollx_reg = 0;
+ u8 m_fg_scrolly_reg = 0;
+ u8 m_fg_page_reg = 0;
+
+ void common_init();
+ void base_main_map(address_map &map);
+
+private:
+ // devices
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<palette_device> m_palette;
+
+ // memory pointers
+ required_shared_ptr<u16> m_videoram;
+ required_shared_ptr<u16> m_textram;
+ required_shared_ptr<u16> m_spriteram;
+
+ required_memory_region m_spritegfx;
+
+ // video-related
+ tilemap_t *m_fg_tilemap = nullptr;
+ tilemap_t *m_bg_tilemap = nullptr;
+ tilemap_t *m_tx_tilemap = nullptr;
+ u8 m_display_enable = 0;
+ int m_bg_page[4]{};
+ int m_fg_page[4]{};
+ u16 m_coinctrl = 0;
+
+ void irq_ack_w(u16 data);
+ void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ void textram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 coinctrl_r();
+ void coinctrl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ void oki_rom_bank_w(u8 data);
+ TILEMAP_MAPPER_MEMBER(scan_pages);
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+ TILE_GET_INFO_MEMBER(get_fg_tile_info);
+ TILE_GET_INFO_MEMBER(get_tx_tile_info);
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void set_bg_page(int page, int value);
+ void set_fg_page(int page, int value);
+ void main_map(address_map &map);
+};
+
+class deniamb_state : public deniamc_state
+{
+public:
+ deniamb_state(const machine_config &mconfig, device_type type, const char *tag) :
+ deniamc_state(mconfig, type, tag),
+ m_audiocpu(*this, "audiocpu"),
+ m_soundlatch(*this, "soundlatch")
+ { }
+
+ void deniam16b(machine_config &config);
+
+ void init_karianx();
+
+private:
+ // devices
+ required_device<cpu_device> m_audiocpu;
+ required_device<generic_latch_8_device> m_soundlatch;
+
+ void oki_rom_bank_w(u8 data);
+
+ void main_map(address_map &map);
+ void sound_io_map(address_map &map);
+ void sound_map(address_map &map);
+};
+
+
+// video
+
+void deniamc_state::common_init()
+{
+ m_bg_scrollx_reg = 0x00a4/2;
+ m_bg_scrolly_reg = 0x00a8/2;
+ m_bg_page_reg = 0x00ac/2;
+ m_fg_scrollx_reg = 0x00a2/2;
+ m_fg_scrolly_reg = 0x00a6/2;
+ m_fg_page_reg = 0x00aa/2;
+
+ m_display_enable = 0;
+ m_coinctrl = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_bg_page[i] = 0;
+ m_fg_page[i] = 0;
+ }
+}
+
+void deniamc_state::init_logicpro()
+{
+ common_init();
+
+ m_bg_scrollx_offs = 0x00d;
+ m_bg_scrolly_offs = 0x000;
+ m_fg_scrollx_offs = 0x009;
+ m_fg_scrolly_offs = 0x000;
+}
+
+void deniamb_state::init_karianx()
+{
+ common_init();
+
+ m_bg_scrollx_offs = 0x10d;
+ m_bg_scrolly_offs = 0x080;
+ m_fg_scrollx_offs = 0x109;
+ m_fg_scrolly_offs = 0x080;
+}
+
+
+
+/***************************************************************************
+
+ Callbacks for the TileMap code
+
+***************************************************************************/
+
+TILEMAP_MAPPER_MEMBER(deniamc_state::scan_pages)
+{
+ // logical (col,row) -> memory offset
+ return (col & 0x3f) + ((row & 0x1f) << 6) + ((col & 0x40) << 5) + ((row & 0x20) << 7);
+}
+
+TILE_GET_INFO_MEMBER(deniamc_state::get_bg_tile_info)
+{
+ const int page = tile_index >> 11;
+ const u16 attr = m_videoram[m_bg_page[page] * 0x0800 + (tile_index & 0x7ff)];
+ tileinfo.set(0,
+ attr,
+ (attr & 0x1fc0) >> 6,
+ 0);
+}
+TILE_GET_INFO_MEMBER(deniamc_state::get_fg_tile_info)
+{
+ const int page = tile_index >> 11;
+ const u16 attr = m_videoram[m_fg_page[page] * 0x0800 + (tile_index & 0x7ff)];
+ tileinfo.set(0,
+ attr,
+ (attr & 0x1fc0) >> 6,
+ 0);
+}
+
+TILE_GET_INFO_MEMBER(deniamc_state::get_tx_tile_info)
+{
+ const u16 attr = m_textram[tile_index];
+ tileinfo.set(0,
+ attr & 0xf1ff,
+ (attr & 0x0e00) >> 9,
+ 0);
+}
+
+
+
+/***************************************************************************
+
+ Start the video hardware emulation.
+
+***************************************************************************/
-void deniam_state::deniam16b_oki_rom_bank_w(u8 data)
+void deniamc_state::video_start()
+{
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniamc_state::scan_pages)), 8, 8, 128, 64);
+ m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniamc_state::scan_pages)), 8, 8, 128, 64);
+ m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
+
+ m_fg_tilemap->set_transparent_pen(0);
+ m_tx_tilemap->set_transparent_pen(0);
+}
+
+
+
+/***************************************************************************
+
+ Memory handlers
+
+***************************************************************************/
+
+void deniamc_state::videoram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_videoram[offset]);
+
+ const int page = offset >> 11;
+ for (int i = 0; i < 4; i++)
+ {
+ if (m_bg_page[i] == page)
+ m_bg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
+ if (m_fg_page[i] == page)
+ m_fg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
+ }
+}
+
+
+void deniamc_state::textram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_textram[offset]);
+ m_tx_tilemap->mark_tile_dirty(offset);
+}
+
+
+u16 deniamc_state::coinctrl_r()
+{
+ return m_coinctrl;
+}
+
+void deniamc_state::coinctrl_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_coinctrl);
+
+ // bit 0 is coin counter
+ machine().bookkeeping().coin_counter_w(0, m_coinctrl & 0x01);
+
+ // bit 6 is display enable (0 freezes screen)
+ m_display_enable = m_coinctrl & 0x20;
+
+ // other bits unknown (unused?)
+}
+
+
+
+/***************************************************************************
+
+ Display refresh
+
+***************************************************************************/
+
+/*
+ * Sprite Format
+ * ------------------
+ *
+ * Word | Bit(s) | Use
+ * -----+-fedcba9876543210-+----------------
+ * 0 | --------xxxxxxxx | display y start
+ * 0 | xxxxxxxx-------- | display y end
+ * 2 | -------xxxxxxxxx | x position
+ * 2 | ------x--------- | unknown (used in logicpr2, maybe just a bug?)
+ * 2 | xxxxxx---------- | unused?
+ * 4 | ---------xxxxxxx | width
+ * 4 | --------x------- | is this flip y like in System 16?
+ * 4 | -------x-------- | flip x
+ * 4 | xxxxxxx--------- | unused?
+ * 6 | xxxxxxxxxxxxxxxx | ROM address low bits
+ * 8 | ----------xxxxxx | color
+ * 8 | --------xx------ | priority
+ * 8 | ---xxxxx-------- | ROM address high bits
+ * 8 | xxx------------- | unused? (extra address bits for larger ROMs?)
+ * a | ---------------- | zoomx like in System 16?
+ * c | ---------------- | zoomy like in System 16?
+ * e | ---------------- |
+ */
+void deniamc_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ for (int offs = m_spriteram.bytes() / 2 - 8; offs >= 0; offs -= 8)
+ {
+ u8 *rom = m_spritegfx->base();
+
+ int sx = (m_spriteram[offs + 1] & 0x01ff) + 16 * 8 - 1;
+ if (sx >= 512) sx -= 512;
+ const int starty = m_spriteram[offs + 0] & 0xff;
+ const int endy = m_spriteram[offs + 0] >> 8;
+
+ const int width = m_spriteram[offs + 2] & 0x007f;
+ bool flipx = m_spriteram[offs + 2] & 0x0100;
+ if (flipx) sx++;
+
+ const u32 color = 0x40 + (m_spriteram[offs + 4] & 0x3f);
+
+ int primask = 8;
+ switch (m_spriteram[offs + 4] & 0xc0)
+ {
+ case 0x00: primask |= 4 | 2 | 1; break; // below everything
+ case 0x40: primask |= 4 | 2; break; // below fg and tx
+ case 0x80: primask |= 4; break; // below tx
+ case 0xc0: break; // above everything
+ }
+
+ const int start = m_spriteram[offs + 3] + ((m_spriteram[offs + 4] & 0x1f00) << 8);
+ rom += 2 * start;
+
+ for (int y = starty + 1; y <= endy; y++)
+ {
+ bool drawing = false;
+ int i = 0;
+
+ rom += 2 * width; // note that the first line is skipped
+ int x = 0;
+ while (i < 512) // safety check
+ {
+ if (flipx)
+ {
+ if ((rom[i] & 0x0f) == 0x0f)
+ {
+ if (!drawing) drawing = true;
+ else break;
+ }
+ else
+ {
+ if (rom[i] & 0x0f)
+ {
+ if (cliprect.contains(sx + x, y))
+ {
+ if ((screen.priority().pix(y, sx + x) & primask) == 0)
+ bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
+ screen.priority().pix(y, sx + x) = 8;
+ }
+ }
+ x++;
+ }
+
+ if ((rom[i] & 0xf0) == 0xf0)
+ {
+ if (!drawing) drawing = true;
+ else break;
+ }
+ else
+ {
+ if (rom[i] & 0xf0)
+ {
+ if (cliprect.contains(sx + x, y))
+ {
+ if ((screen.priority().pix(y, sx + x) & primask) == 0)
+ bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
+ screen.priority().pix(y, sx + x) = 8;
+ }
+ }
+ x++;
+ }
+
+ i--;
+ }
+ else
+ {
+ if ((rom[i] & 0xf0) == 0xf0)
+ {
+ if (!drawing) drawing = true;
+ else break;
+ }
+ else
+ {
+ if (rom[i] & 0xf0)
+ {
+ if (cliprect.contains(sx + x, y))
+ {
+ if ((screen.priority().pix(y, sx + x) & primask) == 0)
+ bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
+ screen.priority().pix(y, sx + x) = 8;
+ }
+ }
+ x++;
+ }
+
+ if ((rom[i] & 0x0f) == 0x0f)
+ {
+ if (!drawing) drawing = true;
+ else break;
+ }
+ else
+ {
+ if (rom[i] & 0x0f)
+ {
+ if (cliprect.contains(sx + x, y))
+ {
+ if ((screen.priority().pix(y, sx + x) & primask) == 0)
+ bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
+ screen.priority().pix(y, sx + x) = 8;
+ }
+ }
+ x++;
+ }
+
+ i++;
+ }
+ }
+ }
+ }
+}
+
+void deniamc_state::set_bg_page(int page, int value)
+{
+ if (m_bg_page[page] != value)
+ {
+ m_bg_page[page] = value;
+ for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
+ m_bg_tilemap->mark_tile_dirty(tile_index);
+ }
+}
+
+void deniamc_state::set_fg_page(int page, int value)
+{
+ if (m_fg_page[page] != value)
+ {
+ m_fg_page[page] = value;
+ for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
+ m_fg_tilemap->mark_tile_dirty(tile_index);
+ }
+}
+
+u32 deniamc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ int page;
+
+ if (!m_display_enable)
+ {
+ bitmap.fill(m_palette->black_pen(), cliprect);
+ return 0; /* don't update (freeze display) */
+ }
+
+ const int bg_scrollx = m_textram[m_bg_scrollx_reg] - m_bg_scrollx_offs;
+ const int bg_scrolly = (m_textram[m_bg_scrolly_reg] & 0xff) - m_bg_scrolly_offs;
+ page = m_textram[m_bg_page_reg];
+ set_bg_page(3, (page >>12) & 0x0f);
+ set_bg_page(2, (page >> 8) & 0x0f);
+ set_bg_page(1, (page >> 4) & 0x0f);
+ set_bg_page(0, (page >> 0) & 0x0f);
+
+ const int fg_scrollx = m_textram[m_fg_scrollx_reg] - m_fg_scrollx_offs;
+ const int fg_scrolly = (m_textram[m_fg_scrolly_reg] & 0xff) - m_fg_scrolly_offs;
+ page = m_textram[m_fg_page_reg];
+ set_fg_page(3, (page >>12) & 0x0f);
+ set_fg_page(2, (page >> 8) & 0x0f);
+ set_fg_page(1, (page >> 4) & 0x0f);
+ set_fg_page(0, (page >> 0) & 0x0f);
+
+ m_bg_tilemap->set_scrollx(0, bg_scrollx & 0x1ff);
+ m_bg_tilemap->set_scrolly(0, bg_scrolly & 0x0ff);
+ m_fg_tilemap->set_scrollx(0, fg_scrollx & 0x1ff);
+ m_fg_tilemap->set_scrolly(0, fg_scrolly & 0x0ff);
+
+ screen.priority().fill(0, cliprect);
+
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1);
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
+ m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 4);
+
+ draw_sprites(screen, bitmap, cliprect);
+ return 0;
+}
+
+
+// machine
+
+void deniamb_state::oki_rom_bank_w(u8 data)
{
m_oki->set_rom_bank((data >> 6) & 1);
}
-void deniam_state::deniam16c_oki_rom_bank_w(u8 data)
+void deniamc_state::oki_rom_bank_w(u8 data)
{
- if ((data&0xFE) != 0) popmessage("OKI bank was not 0 or 1! contact MAMEDEV!");
+ if ((data & 0xfe) != 0) popmessage("OKI bank was not 0 or 1! contact MAMEDEV!");
m_oki->set_rom_bank(data & 0x01);
}
-void deniam_state::irq_ack_w(u16 data)
+void deniamc_state::irq_ack_w(u16 data)
{
m_maincpu->set_input_line(4, CLEAR_LINE);
}
-void deniam_state::deniam16b_map(address_map &map)
+void deniamc_state::base_main_map(address_map &map)
{
map(0x000000, 0x0fffff).rom();
- map(0x400000, 0x40ffff).ram().w(FUNC(deniam_state::videoram_w)).share("videoram");
- map(0x410000, 0x410fff).ram().w(FUNC(deniam_state::textram_w)).share("textram");
- map(0x440000, 0x4407ff).writeonly().share("spriteram");
+ map(0x400000, 0x40ffff).ram().w(FUNC(deniamb_state::videoram_w)).share(m_videoram);
+ map(0x410000, 0x410fff).ram().w(FUNC(deniamb_state::textram_w)).share(m_textram);
+ map(0x440000, 0x4407ff).writeonly().share(m_spriteram);
map(0x840000, 0x840fff).w(m_palette, FUNC(palette_device::write16)).share("palette");
- map(0xc40000, 0xc40000).w(m_soundlatch, FUNC(generic_latch_8_device::write));
- map(0xc40002, 0xc40003).rw(FUNC(deniam_state::coinctrl_r), FUNC(deniam_state::coinctrl_w));
- map(0xc40004, 0xc40005).w(FUNC(deniam_state::irq_ack_w));
+ map(0xc40002, 0xc40003).rw(FUNC(deniamb_state::coinctrl_r), FUNC(deniamb_state::coinctrl_w));
+ map(0xc40004, 0xc40005).w(FUNC(deniamb_state::irq_ack_w));
map(0xc44000, 0xc44001).portr("SYSTEM");
map(0xc44002, 0xc44003).portr("P1");
map(0xc44004, 0xc44005).portr("P2").nopw();
- map(0xc44006, 0xc44007).nopr(); /* unused? */
- map(0xc4400a, 0xc4400b).portr("DSW");
map(0xff0000, 0xffffff).ram();
}
-void deniam_state::sound_map(address_map &map)
+void deniamb_state::main_map(address_map &map)
+{
+ base_main_map(map);
+
+ map(0xc40000, 0xc40000).w(m_soundlatch, FUNC(generic_latch_8_device::write));
+ map(0xc44006, 0xc44007).nopr(); // unused?
+ map(0xc4400a, 0xc4400b).portr("DSW");
+}
+
+void deniamb_state::sound_map(address_map &map)
{
map(0x0000, 0xf7ff).rom();
map(0xf800, 0xffff).ram();
}
-void deniam_state::sound_io_map(address_map &map)
+void deniamb_state::sound_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x01, 0x01).r(m_soundlatch, FUNC(generic_latch_8_device::read));
map(0x02, 0x03).w("ymsnd", FUNC(ym3812_device::write));
map(0x05, 0x05).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
- map(0x07, 0x07).w(FUNC(deniam_state::deniam16b_oki_rom_bank_w));
+ map(0x07, 0x07).w(FUNC(deniamb_state::oki_rom_bank_w));
}
-/* identical to 16b, but handles sound directly */
-void deniam_state::deniam16c_map(address_map &map)
+// identical to 16b, but handles sound directly
+void deniamc_state::main_map(address_map &map)
{
- map(0x000000, 0x0fffff).rom();
- map(0x400000, 0x40ffff).ram().w(FUNC(deniam_state::videoram_w)).share("videoram");
- map(0x410000, 0x410fff).ram().w(FUNC(deniam_state::textram_w)).share("textram");
- map(0x440000, 0x4407ff).writeonly().share("spriteram");
- map(0x840000, 0x840fff).w(m_palette, FUNC(palette_device::write16)).share("palette");
+ base_main_map(map);
+
map(0xc40001, 0xc40001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
- map(0xc40002, 0xc40003).rw(FUNC(deniam_state::coinctrl_r), FUNC(deniam_state::coinctrl_w));
- map(0xc40004, 0xc40005).w(FUNC(deniam_state::irq_ack_w));
- map(0xc40007, 0xc40007).w(FUNC(deniam_state::deniam16c_oki_rom_bank_w));
- map(0xc44000, 0xc44001).portr("SYSTEM");
- map(0xc44002, 0xc44003).portr("P1");
- map(0xc44004, 0xc44005).portr("P2");
- map(0xc44006, 0xc44007).nopr(); /* read unused? extra input port/dipswitches? */
+ map(0xc40007, 0xc40007).w(FUNC(deniamc_state::oki_rom_bank_w));
+ map(0xc44006, 0xc44007).nopr(); // read unused? extra input port/dipswitches?
map(0xc40008, 0xc4000b).w("ymsnd", FUNC(ym3812_device::write)).umask16(0xff00);
- map(0xc4400a, 0xc4400b).portr("DSW"); /* probably YM3812 input port */
- map(0xff0000, 0xffffff).ram();
+ map(0xc4400a, 0xc4400b).portr("DSW"); // probably YM3812 input port
}
@@ -201,32 +684,22 @@ INPUT_PORTS_END
static GFXDECODE_START( gfx_deniam )
- GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x3_planar, 0, 128 ) /* colors 0-1023 */
- /* sprites use colors 1024-2047 */
+ GFXDECODE_ENTRY( "chars", 0, gfx_8x8x3_planar, 0, 128 ) // colors 0-1023
+ // sprites use colors 1024-2047
GFXDECODE_END
-void deniam_state::machine_start()
+void deniamc_state::machine_start()
{
save_item(NAME(m_display_enable));
save_item(NAME(m_coinctrl));
- save_item(NAME(m_bg_scrollx_offs));
- save_item(NAME(m_bg_scrolly_offs));
- save_item(NAME(m_fg_scrollx_offs));
- save_item(NAME(m_fg_scrolly_offs));
- save_item(NAME(m_bg_scrollx_reg));
- save_item(NAME(m_bg_scrolly_reg));
- save_item(NAME(m_fg_scrollx_reg));
- save_item(NAME(m_fg_scrolly_reg));
- save_item(NAME(m_bg_page_reg));
- save_item(NAME(m_fg_page_reg));
save_item(NAME(m_bg_page));
save_item(NAME(m_fg_page));
}
-void deniam_state::machine_reset()
+void deniamc_state::machine_reset()
{
/* logicpr2 does not reset the bank base on startup, though it probably
doesn't matter since the coinup sfx (sample borrowed from 'tyrian' on PC)
@@ -235,72 +708,52 @@ void deniam_state::machine_reset()
m_oki->set_rom_bank(0);
}
-void deniam_state::deniam16b(machine_config &config)
+void deniamc_state::deniam16c(machine_config &config)
{
- /* basic machine hardware */
- M68000(config, m_maincpu, XTAL(25'000'000)/2); /* 12.5Mhz verified */
- m_maincpu->set_addrmap(AS_PROGRAM, &deniam_state::deniam16b_map);
- m_maincpu->set_vblank_int("screen", FUNC(deniam_state::irq4_line_assert));
+ // basic machine hardware
+ M68000(config, m_maincpu, XTAL(25'000'000) / 2); // 12.5Mhz verified
+ m_maincpu->set_addrmap(AS_PROGRAM, &deniamc_state::main_map);
+ m_maincpu->set_vblank_int("screen", FUNC(deniamb_state::irq4_line_assert));
- Z80(config, m_audiocpu, XTAL(25'000'000)/4); /* 6.25Mhz verified */
- m_audiocpu->set_addrmap(AS_PROGRAM, &deniam_state::sound_map);
- m_audiocpu->set_addrmap(AS_IO, &deniam_state::sound_io_map);
-
- /* 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));
screen.set_size(512, 256);
//screen.set_visarea(24*8, 64*8-1, 0*8, 28*8-1); // looks better but doesn't match hardware
screen.set_visarea(24*8-4, 64*8-5, 0*8, 28*8-1);
- screen.set_screen_update(FUNC(deniam_state::screen_update));
+ screen.set_screen_update(FUNC(deniamb_state::screen_update));
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_deniam);
- PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / hilight?
+ PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / highlight?
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "mono").front_center();
- GENERIC_LATCH_8(config, m_soundlatch);
- m_soundlatch->data_pending_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI);
-
- ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000)/6)); /* "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified */
- ymsnd.irq_handler().set_inputline(m_audiocpu, 0);
+ ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000) / 6)); // "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified
ymsnd.add_route(ALL_OUTPUTS, "mono", 0.60);
- OKIM6295(config, m_oki, XTAL(25'000'000)/24, okim6295_device::PIN7_HIGH); /* 1.041620 measured, = 1.0416666Mhz verified */
+ OKIM6295(config, m_oki, XTAL(25'000'000) / 24, okim6295_device::PIN7_HIGH); // 1.041620 measured, = 1.0416666Mhz verified
m_oki->add_route(ALL_OUTPUTS, "mono", 1.0);
}
-void deniam_state::deniam16c(machine_config &config)
+void deniamb_state::deniam16b(machine_config &config)
{
- /* basic machine hardware */
- M68000(config, m_maincpu, XTAL(25'000'000)/2); /* 12.5Mhz verified */
- m_maincpu->set_addrmap(AS_PROGRAM, &deniam_state::deniam16c_map);
- m_maincpu->set_vblank_int("screen", FUNC(deniam_state::irq4_line_assert));
-
- /* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
- screen.set_size(512, 256);
- //screen.set_visarea(24*8, 64*8-1, 0*8, 28*8-1); // looks better but doesn't match hardware
- screen.set_visarea(24*8-4, 64*8-5, 0*8, 28*8-1);
- screen.set_screen_update(FUNC(deniam_state::screen_update));
- screen.set_palette(m_palette);
+ deniam16c(config);
- GFXDECODE(config, m_gfxdecode, m_palette, gfx_deniam);
- PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / hilight?
+ // basic machine hardware
+ m_maincpu->set_addrmap(AS_PROGRAM, &deniamb_state::main_map);
- /* sound hardware */
- SPEAKER(config, "mono").front_center();
+ Z80(config, m_audiocpu, XTAL(25'000'000) / 4); // 6.25Mhz verified
+ m_audiocpu->set_addrmap(AS_PROGRAM, &deniamb_state::sound_map);
+ m_audiocpu->set_addrmap(AS_IO, &deniamb_state::sound_io_map);
- ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000)/6)); /* "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified) */
- ymsnd.add_route(ALL_OUTPUTS, "mono", 0.60);
+ // sound hardware
+ GENERIC_LATCH_8(config, m_soundlatch);
+ m_soundlatch->data_pending_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI);
- OKIM6295(config, m_oki, XTAL(25'000'000)/24, okim6295_device::PIN7_HIGH); /* 1.041620 measured, = 1.0416666Mhz verified */
- m_oki->add_route(ALL_OUTPUTS, "mono", 1.0);
+ subdevice<ym3812_device>("ymsnd")->irq_handler().set_inputline(m_audiocpu, 0);
}
@@ -316,20 +769,20 @@ ROM_START( croquis )
ROM_LOAD16_BYTE( "sys_e0", 0x00000, 0x40000, CRC(b74cd4a9) SHA1(350557377bc5815d0e7f48a96898eba6374f65dd) ) // 27C020
ROM_LOAD16_BYTE( "sys_o0", 0x00001, 0x40000, CRC(346e18f4) SHA1(0107ef7b5843a654f393d6f22ef6d52b5bf45fc0) ) // 27C020
- ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
+ ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) ) // 27C512 - silkscreened: DSS
- ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
+ ROM_REGION( 0x180000, "chars", 0 )
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) ) // 27C040 - silkscreened: BG(00)
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) ) // 27C040 - silkscreened: BG(01)
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) ) // 27C040 - silkscreened: BG(02)
- ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
+ ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) ) // 27C040 - silkscreened: OBJ(E0)
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) ) // 27C040 - silkscreened: OBJ(O0)
// OBJ(E1), OBJ(E2), OBJ(O1) & OBJ(O2) not populated
- ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
+ ROM_REGION( 0x100000, "oki", 0 )
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) ) // 27C040 - silkscreened: V_ROM0
// V_ROM1 not populated
ROM_END
@@ -339,19 +792,19 @@ ROM_START( croquisg )
ROM_LOAD16_BYTE( "r4.bin", 0x00000, 0x40000, CRC(03c9055e) SHA1(b1fa8e7a272887decca30eefe73ac782f296f0dd) )
ROM_LOAD16_BYTE( "r3.bin", 0x00001, 0x40000, CRC(a98ae4f6) SHA1(80fcedb4ee0f35eb2d0b4a248c15f872af2e08f2) )
- ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
+ ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) )
- ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
+ ROM_REGION( 0x180000, "chars", 0 )
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) )
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) )
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) )
- ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
+ ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) )
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) )
- ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
+ ROM_REGION( 0x100000, "oki", 0 )
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) )
ROM_END
@@ -360,19 +813,19 @@ ROM_START( logicpro )
ROM_LOAD16_BYTE( "logicpro.r4", 0x00000, 0x40000, CRC(c506d484) SHA1(5d662b109e1d2e09556bc4ecbc11bbf5ccb639d3) )
ROM_LOAD16_BYTE( "logicpro.r3", 0x00001, 0x40000, CRC(d5a4cf62) SHA1(138ea4f1629e453c1a00410eda7086d3633240e3) )
- ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
+ ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) )
- ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
+ ROM_REGION( 0x180000, "chars", 0 )
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) )
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) )
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) )
- ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
+ ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) )
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) )
- ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
+ ROM_REGION( 0x100000, "oki", 0 )
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) )
ROM_END
@@ -381,15 +834,15 @@ ROM_START( karianx )
ROM_LOAD16_BYTE( "even", 0x00000, 0x80000, CRC(fd0ce238) SHA1(4b727366c942c62187d8700666b42a85c059c060) )
ROM_LOAD16_BYTE( "odd", 0x00001, 0x80000, CRC(be173cdc) SHA1(13230b6129fd1910257624a69a3a4b74696e982e) )
- ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
+ ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "snd", 0x0000, 0x10000, CRC(fedd3375) SHA1(09fb2d5fc91704120f757acf9fa00d149f891a28) )
- ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
+ ROM_REGION( 0x180000, "chars", 0 )
ROM_LOAD( "bkg1", 0x000000, 0x080000, CRC(5cb8558a) SHA1(9c6024c70a0f0cd529a0e2e853e467ec8d8ab446) )
ROM_LOAD( "bkg2", 0x080000, 0x080000, CRC(95ff297c) SHA1(28f6c005e73e1680bd8be7ce355fa0d404827105) )
ROM_LOAD( "bkg3", 0x100000, 0x080000, CRC(6c81f1b2) SHA1(14ef907a9c381b7ef45441d480bb4ccb015e474b) )
- ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
+ ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
ROM_LOAD16_BYTE( "obj4", 0x000000, 0x080000, CRC(5f8d75a9) SHA1(0552d046742aeb2fee176887156e73480c75a1bd) )
ROM_LOAD16_BYTE( "obj1", 0x000001, 0x080000, CRC(967ee97d) SHA1(689f2da67eab86653b846fada39139792cd4aee2) )
ROM_LOAD16_BYTE( "obj5", 0x100000, 0x080000, CRC(e9fc22f9) SHA1(a1f7f779520346406949500e3224c0c42cbbe026) )
@@ -397,7 +850,7 @@ ROM_START( karianx )
ROM_LOAD16_BYTE( "obj6", 0x200000, 0x080000, CRC(c1ec35a5) SHA1(bf59f4c3de081c8cc398c825fc1f3e8577641f10) )
ROM_LOAD16_BYTE( "obj3", 0x200001, 0x080000, CRC(6ac1ac87) SHA1(1954e25ac5489a8eca137b86c89c415f1fed360c) )
- ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
+ ROM_REGION( 0x100000, "oki", 0 )
ROM_LOAD( "voi", 0x0000, 0x080000, CRC(c6506a80) SHA1(121229c501bd5678e55c7342619743c773a01a7e) )
ROM_END
@@ -406,22 +859,23 @@ ROM_START( logicpr2 )
ROM_LOAD16_BYTE( "lp2-2", 0x00000, 0x80000, CRC(cc1880bf) SHA1(5ea542b63947a570aaf924f7ab739e060e359af8) )
ROM_LOAD16_BYTE( "lp2-1", 0x00001, 0x80000, CRC(46d5e954) SHA1(7bf5ae19caeecd2123754698276bbc78d68984d9) )
- ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
+ ROM_REGION( 0x180000, "chars", 0 )
ROM_LOAD( "log2-b01", 0x000000, 0x080000, CRC(fe789e07) SHA1(c3d542564519fd807bc605029f5a2cca571eec9f) )
ROM_LOAD( "log2-b02", 0x080000, 0x080000, CRC(1e0c51cd) SHA1(c25b3259a173e77785dcee1407ddf191c3efad79) )
ROM_LOAD( "log2-b03", 0x100000, 0x080000, CRC(916f2928) SHA1(8c73408664dcd3de42cb27fac0d22b87b540bf52) )
- ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
+ ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
ROM_LOAD16_WORD_SWAP( "obj", 0x000000, 0x400000, CRC(f221f305) SHA1(aa1d3d86d13e009bfb44cbc6ff4401b811b19f97) )
- ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
+ ROM_REGION( 0x100000, "oki", 0 )
ROM_LOAD( "log2-s01", 0x0000, 0x100000, CRC(2875c435) SHA1(633538d9ac53228ea344605482ac387852c29193) )
ROM_END
+} // anonymous namespace
-GAME( 1996, croquis, 0, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Croquis (Korea)", MACHINE_SUPPORTS_SAVE )
-GAME( 1996, croquisg, croquis, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Croquis (Germany)", MACHINE_SUPPORTS_SAVE )
-GAME( 1996, logicpro, croquis, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Logic Pro (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1996, karianx, 0, deniam16b, karianx, deniam_state, init_karianx, ROT0, "Deniam", "Karian Cross (Rev. 1.0)", MACHINE_SUPPORTS_SAVE )
-GAME( 1997, logicpr2, 0, deniam16c, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Logic Pro 2 (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1996, croquis, 0, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Croquis (Korea)", MACHINE_SUPPORTS_SAVE )
+GAME( 1996, croquisg, croquis, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Croquis (Germany)", MACHINE_SUPPORTS_SAVE )
+GAME( 1996, logicpro, croquis, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Logic Pro (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1996, karianx, 0, deniam16b, karianx, deniamb_state, init_karianx, ROT0, "Deniam", "Karian Cross (Rev. 1.0)", MACHINE_SUPPORTS_SAVE )
+GAME( 1997, logicpr2, 0, deniam16c, logicpr2, deniamc_state, init_logicpro, ROT0, "Deniam", "Logic Pro 2 (Japan)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/sega/deniam.h b/src/mame/sega/deniam.h
deleted file mode 100644
index 58671596d11..00000000000
--- a/src/mame/sega/deniam.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
-
-/*************************************************************************
-
- Deniam games
-
-*************************************************************************/
-
-#include "machine/gen_latch.h"
-#include "sound/okim6295.h"
-#include "emupal.h"
-#include "tilemap.h"
-
-class deniam_state : public driver_device
-{
-public:
- deniam_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_videoram(*this, "videoram"),
- m_textram(*this, "textram"),
- m_spriteram(*this, "spriteram"),
- m_spritegfx(*this, "spritegfx"),
- m_maincpu(*this, "maincpu"),
- m_audiocpu(*this, "audiocpu"),
- m_oki(*this, "oki"),
- m_gfxdecode(*this, "gfxdecode"),
- m_palette(*this, "palette"),
- m_soundlatch(*this, "soundlatch")
- { }
-
- void deniam16c(machine_config &config);
- void deniam16b(machine_config &config);
-
- void init_karianx();
- void init_logicpro();
-
-private:
- /* memory pointers */
- required_shared_ptr<u16> m_videoram;
- required_shared_ptr<u16> m_textram;
- required_shared_ptr<u16> m_spriteram;
-
- required_memory_region m_spritegfx;
-
- /* video-related */
- tilemap_t *m_fg_tilemap = nullptr;
- tilemap_t *m_bg_tilemap = nullptr;
- tilemap_t *m_tx_tilemap = nullptr;
- int m_display_enable = 0;
- int m_bg_scrollx_offs = 0;
- int m_bg_scrolly_offs = 0;
- int m_fg_scrollx_offs = 0;
- int m_fg_scrolly_offs = 0;
- int m_bg_scrollx_reg = 0;
- int m_bg_scrolly_reg = 0;
- int m_bg_page_reg = 0;
- int m_fg_scrollx_reg = 0;
- int m_fg_scrolly_reg = 0;
- int m_fg_page_reg = 0;
- int m_bg_page[4]{};
- int m_fg_page[4]{};
- u16 m_coinctrl = 0;
-
- /* devices */
- void irq_ack_w(u16 data);
- void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
- void textram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
- u16 coinctrl_r();
- void coinctrl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
- void deniam16b_oki_rom_bank_w(u8 data);
- void deniam16c_oki_rom_bank_w(u8 data);
- TILEMAP_MAPPER_MEMBER(scan_pages);
- TILE_GET_INFO_MEMBER(get_bg_tile_info);
- TILE_GET_INFO_MEMBER(get_fg_tile_info);
- TILE_GET_INFO_MEMBER(get_tx_tile_info);
- virtual void machine_start() override;
- virtual void machine_reset() override;
- virtual void video_start() override;
- u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- void deniam_common_init( );
- void draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect );
- void set_bg_page( int page, int value );
- void set_fg_page( int page, int value );
- required_device<cpu_device> m_maincpu;
- optional_device<cpu_device> m_audiocpu; // system 16c does not have sound CPU
- required_device<okim6295_device> m_oki;
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<palette_device> m_palette;
- optional_device<generic_latch_8_device> m_soundlatch;
- void deniam16b_map(address_map &map);
- void deniam16c_map(address_map &map);
- void sound_io_map(address_map &map);
- void sound_map(address_map &map);
-};
diff --git a/src/mame/sega/deniam_v.cpp b/src/mame/sega/deniam_v.cpp
deleted file mode 100644
index 0dce18f1440..00000000000
--- a/src/mame/sega/deniam_v.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
-#include "emu.h"
-#include "deniam.h"
-#include "screen.h"
-
-
-void deniam_state::deniam_common_init( )
-{
- m_bg_scrollx_reg = 0x00a4/2;
- m_bg_scrolly_reg = 0x00a8/2;
- m_bg_page_reg = 0x00ac/2;
- m_fg_scrollx_reg = 0x00a2/2;
- m_fg_scrolly_reg = 0x00a6/2;
- m_fg_page_reg = 0x00aa/2;
-
- m_display_enable = 0;
- m_coinctrl = 0;
-
- for (int i = 0; i < 4; i++)
- {
- m_bg_page[i] = 0;
- m_fg_page[i] = 0;
- }
-}
-
-void deniam_state::init_logicpro()
-{
- deniam_common_init();
-
- m_bg_scrollx_offs = 0x00d;
- m_bg_scrolly_offs = 0x000;
- m_fg_scrollx_offs = 0x009;
- m_fg_scrolly_offs = 0x000;
-}
-
-void deniam_state::init_karianx()
-{
- deniam_common_init();
-
- m_bg_scrollx_offs = 0x10d;
- m_bg_scrolly_offs = 0x080;
- m_fg_scrollx_offs = 0x109;
- m_fg_scrolly_offs = 0x080;
-}
-
-
-
-/***************************************************************************
-
- Callbacks for the TileMap code
-
-***************************************************************************/
-
-TILEMAP_MAPPER_MEMBER(deniam_state::scan_pages)
-{
- /* logical (col,row) -> memory offset */
- return (col & 0x3f) + ((row & 0x1f) << 6) + ((col & 0x40) << 5) + ((row & 0x20) << 7);
-}
-
-TILE_GET_INFO_MEMBER(deniam_state::get_bg_tile_info)
-{
- const int page = tile_index >> 11;
- u16 attr = m_videoram[m_bg_page[page] * 0x0800 + (tile_index & 0x7ff)];
- tileinfo.set(0,
- attr,
- (attr & 0x1fc0) >> 6,
- 0);
-}
-
-TILE_GET_INFO_MEMBER(deniam_state::get_fg_tile_info)
-{
- const int page = tile_index >> 11;
- u16 attr = m_videoram[m_fg_page[page] * 0x0800 + (tile_index & 0x7ff)];
- tileinfo.set(0,
- attr,
- (attr & 0x1fc0) >> 6,
- 0);
-}
-
-TILE_GET_INFO_MEMBER(deniam_state::get_tx_tile_info)
-{
- u16 attr = m_textram[tile_index];
- tileinfo.set(0,
- attr & 0xf1ff,
- (attr & 0x0e00) >> 9,
- 0);
-}
-
-
-
-/***************************************************************************
-
- Start the video hardware emulation.
-
-***************************************************************************/
-
-void deniam_state::video_start()
-{
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniam_state::scan_pages)), 8, 8, 128, 64);
- m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniam_state::scan_pages)), 8, 8, 128, 64);
- m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
-
- m_fg_tilemap->set_transparent_pen(0);
- m_tx_tilemap->set_transparent_pen(0);
-}
-
-
-
-/***************************************************************************
-
- Memory handlers
-
-***************************************************************************/
-
-void deniam_state::videoram_w(offs_t offset, u16 data, u16 mem_mask)
-{
- COMBINE_DATA(&m_videoram[offset]);
-
- const int page = offset >> 11;
- for (int i = 0; i < 4; i++)
- {
- if (m_bg_page[i] == page)
- m_bg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
- if (m_fg_page[i] == page)
- m_fg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
- }
-}
-
-
-void deniam_state::textram_w(offs_t offset, u16 data, u16 mem_mask)
-{
- COMBINE_DATA(&m_textram[offset]);
- m_tx_tilemap->mark_tile_dirty(offset);
-}
-
-
-u16 deniam_state::coinctrl_r()
-{
- return m_coinctrl;
-}
-
-void deniam_state::coinctrl_w(offs_t offset, u16 data, u16 mem_mask)
-{
- COMBINE_DATA(&m_coinctrl);
-
- /* bit 0 is coin counter */
- machine().bookkeeping().coin_counter_w(0, m_coinctrl & 0x01);
-
- /* bit 6 is display enable (0 freezes screen) */
- m_display_enable = m_coinctrl & 0x20;
-
- /* other bits unknown (unused?) */
-}
-
-
-
-/***************************************************************************
-
- Display refresh
-
-***************************************************************************/
-
-/*
- * Sprite Format
- * ------------------
- *
- * Word | Bit(s) | Use
- * -----+-fedcba9876543210-+----------------
- * 0 | --------xxxxxxxx | display y start
- * 0 | xxxxxxxx-------- | display y end
- * 2 | -------xxxxxxxxx | x position
- * 2 | ------x--------- | unknown (used in logicpr2, maybe just a bug?)
- * 2 | xxxxxx---------- | unused?
- * 4 | ---------xxxxxxx | width
- * 4 | --------x------- | is this flip y like in System 16?
- * 4 | -------x-------- | flip x
- * 4 | xxxxxxx--------- | unused?
- * 6 | xxxxxxxxxxxxxxxx | ROM address low bits
- * 8 | ----------xxxxxx | color
- * 8 | --------xx------ | priority
- * 8 | ---xxxxx-------- | ROM address high bits
- * 8 | xxx------------- | unused? (extra address bits for larger ROMs?)
- * a | ---------------- | zoomx like in System 16?
- * c | ---------------- | zoomy like in System 16?
- * e | ---------------- |
- */
-void deniam_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect )
-{
- for (int offs = m_spriteram.bytes() / 2 - 8; offs >= 0; offs -= 8)
- {
- u8 *rom = m_spritegfx->base();
-
- int sx = (m_spriteram[offs + 1] & 0x01ff) + 16 * 8 - 1;
- if (sx >= 512) sx -= 512;
- const int starty = m_spriteram[offs + 0] & 0xff;
- const int endy = m_spriteram[offs + 0] >> 8;
-
- const int width = m_spriteram[offs + 2] & 0x007f;
- bool flipx = m_spriteram[offs + 2] & 0x0100;
- if (flipx) sx++;
-
- const u32 color = 0x40 + (m_spriteram[offs + 4] & 0x3f);
-
- int primask = 8;
- switch (m_spriteram[offs + 4] & 0xc0)
- {
- case 0x00: primask |= 4 | 2 | 1; break; /* below everything */
- case 0x40: primask |= 4 | 2; break; /* below fg and tx */
- case 0x80: primask |= 4; break; /* below tx */
- case 0xc0: break; /* above everything */
- }
-
- const int start = m_spriteram[offs + 3] + ((m_spriteram[offs + 4] & 0x1f00) << 8);
- rom += 2 * start;
-
- for (int y = starty + 1; y <= endy; y++)
- {
- bool drawing = false;
- int i = 0;
-
- rom += 2 * width; /* note that the first line is skipped */
- int x = 0;
- while (i < 512) /* safety check */
- {
- if (flipx)
- {
- if ((rom[i] & 0x0f) == 0x0f)
- {
- if (!drawing) drawing = true;
- else break;
- }
- else
- {
- if (rom[i] & 0x0f)
- {
- if (cliprect.contains(sx + x, y))
- {
- if ((screen.priority().pix(y, sx + x) & primask) == 0)
- bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
- screen.priority().pix(y, sx + x) = 8;
- }
- }
- x++;
- }
-
- if ((rom[i] & 0xf0) == 0xf0)
- {
- if (!drawing) drawing = true;
- else break;
- }
- else
- {
- if (rom[i] & 0xf0)
- {
- if (cliprect.contains(sx + x, y))
- {
- if ((screen.priority().pix(y, sx + x) & primask) == 0)
- bitmap.pix(y, sx + x) = color * 16+(rom[i] >> 4);
- screen.priority().pix(y, sx + x) = 8;
- }
- }
- x++;
- }
-
- i--;
- }
- else
- {
- if ((rom[i] & 0xf0) == 0xf0)
- {
- if (!drawing) drawing = true;
- else break;
- }
- else
- {
- if (rom[i] & 0xf0)
- {
- if (cliprect.contains(sx + x, y))
- {
- if ((screen.priority().pix(y, sx + x) & primask) == 0)
- bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
- screen.priority().pix(y, sx + x) = 8;
- }
- }
- x++;
- }
-
- if ((rom[i] & 0x0f) == 0x0f)
- {
- if (!drawing) drawing = true;
- else break;
- }
- else
- {
- if (rom[i] & 0x0f)
- {
- if (cliprect.contains(sx + x, y))
- {
- if ((screen.priority().pix(y, sx + x) & primask) == 0)
- bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
- screen.priority().pix(y, sx + x) = 8;
- }
- }
- x++;
- }
-
- i++;
- }
- }
- }
- }
-}
-
-void deniam_state::set_bg_page( int page, int value )
-{
- if (m_bg_page[page] != value)
- {
- m_bg_page[page] = value;
- for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
- m_bg_tilemap->mark_tile_dirty(tile_index);
- }
-}
-
-void deniam_state::set_fg_page( int page, int value )
-{
- if (m_fg_page[page] != value)
- {
- m_fg_page[page] = value;
- for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
- m_fg_tilemap->mark_tile_dirty(tile_index);
- }
-}
-
-u32 deniam_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- int page;
-
- if (!m_display_enable)
- {
- bitmap.fill(m_palette->black_pen(), cliprect);
- return 0; /* don't update (freeze display) */
- }
-
- int bg_scrollx = m_textram[m_bg_scrollx_reg] - m_bg_scrollx_offs;
- int bg_scrolly = (m_textram[m_bg_scrolly_reg] & 0xff) - m_bg_scrolly_offs;
- page = m_textram[m_bg_page_reg];
- set_bg_page(3, (page >>12) & 0x0f);
- set_bg_page(2, (page >> 8) & 0x0f);
- set_bg_page(1, (page >> 4) & 0x0f);
- set_bg_page(0, (page >> 0) & 0x0f);
-
- int fg_scrollx = m_textram[m_fg_scrollx_reg] - m_fg_scrollx_offs;
- int fg_scrolly = (m_textram[m_fg_scrolly_reg] & 0xff) - m_fg_scrolly_offs;
- page = m_textram[m_fg_page_reg];
- set_fg_page(3, (page >>12) & 0x0f);
- set_fg_page(2, (page >> 8) & 0x0f);
- set_fg_page(1, (page >> 4) & 0x0f);
- set_fg_page(0, (page >> 0) & 0x0f);
-
- m_bg_tilemap->set_scrollx(0, bg_scrollx & 0x1ff);
- m_bg_tilemap->set_scrolly(0, bg_scrolly & 0x0ff);
- m_fg_tilemap->set_scrollx(0, fg_scrollx & 0x1ff);
- m_fg_tilemap->set_scrolly(0, fg_scrolly & 0x0ff);
-
- screen.priority().fill(0, cliprect);
-
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1);
- m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
- m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 4);
-
- draw_sprites(screen, bitmap, cliprect);
- return 0;
-}
diff --git a/src/mame/sega/kopunch.cpp b/src/mame/sega/kopunch.cpp
index 586fc7ec30a..f966346fb2b 100644
--- a/src/mame/sega/kopunch.cpp
+++ b/src/mame/sega/kopunch.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
+// copyright-holders: Nicola Salmoria
+
/********************************************************
KO Punch (c) 1981 Sega
@@ -32,12 +33,195 @@
********************************************************/
#include "emu.h"
-#include "kopunch.h"
#include "cpu/i8085/i8085.h"
#include "machine/i8255.h"
+
+#include "emupal.h"
#include "screen.h"
+#include "tilemap.h"
+
+
+// configurable logging
+#define LOG_PORT34 (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL | LOG_PORT34)
+
+#include "logmacro.h"
+
+#define LOGPORT34(...) LOGMASKED(LOG_PORT34, __VA_ARGS__)
+
+
+namespace {
+
+class kopunch_state : public driver_device
+{
+public:
+ kopunch_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_gfxdecode(*this, "gfxdecode")
+ , m_vram_fg(*this, "vram_fg")
+ , m_vram_bg(*this, "vram_bg")
+ , m_system(*this, "SYSTEM")
+ , m_lamp(*this, "lamp0")
+ { }
+
+ void kopunch(machine_config &config);
+
+ DECLARE_INPUT_CHANGED_MEMBER(left_coin_inserted);
+ DECLARE_INPUT_CHANGED_MEMBER(right_coin_inserted);
+
+protected:
+ virtual void machine_start() override;
+ virtual void video_start() override;
+
+private:
+ uint8_t sensors1_r();
+ uint8_t sensors2_r();
+ void lamp_w(uint8_t data);
+ void coin_w(uint8_t data);
+ void vram_fg_w(offs_t offset, uint8_t data);
+ void vram_bg_w(offs_t offset, uint8_t data);
+ void scroll_x_w(uint8_t data);
+ void scroll_y_w(uint8_t data);
+ void gfxbank_w(uint8_t data);
+
+ TILE_GET_INFO_MEMBER(get_fg_tile_info);
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+ void palette(palette_device &palette) const;
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ void io_map(address_map &map);
+ void prg_map(address_map &map);
+
+ // devices
+ required_device<cpu_device> m_maincpu;
+ required_device<gfxdecode_device> m_gfxdecode;
+
+ // memory pointers
+ required_shared_ptr<uint8_t> m_vram_fg;
+ required_shared_ptr<uint8_t> m_vram_bg;
+
+ required_ioport m_system;
+ output_finder<> m_lamp;
+
+ // video-related
+ tilemap_t *m_bg_tilemap = nullptr;
+ tilemap_t *m_fg_tilemap = nullptr;
+ uint8_t m_gfxbank = 0U;
+ uint8_t m_scrollx = 0U;
+};
+
+
+// video
+
+void kopunch_state::palette(palette_device &palette) const
+{
+ const uint8_t *color_prom = memregion("proms")->base();
+
+ color_prom += 24; // first 24 colors are black
+
+ for (int i = 0; i < palette.entries(); i++)
+ {
+ int bit0, bit1, bit2;
+
+ // red component
+ bit0 = BIT(*color_prom, 0);
+ bit1 = BIT(*color_prom, 1);
+ bit2 = BIT(*color_prom, 2);
+ int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+ // green component
+ bit0 = BIT(*color_prom, 3);
+ bit1 = BIT(*color_prom, 4);
+ bit2 = BIT(*color_prom, 5);
+ int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+ // blue component
+ bit0 = 0;
+ bit1 = BIT(*color_prom, 6);
+ bit2 = BIT(*color_prom, 7);
+ int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+
+ palette.set_pen_color(i, rgb_t(r, g, b));
+ color_prom++;
+ }
+}
+
+void kopunch_state::vram_fg_w(offs_t offset, uint8_t data)
+{
+ m_vram_fg[offset] = data;
+ m_fg_tilemap->mark_tile_dirty(offset);
+}
+
+void kopunch_state::vram_bg_w(offs_t offset, uint8_t data)
+{
+ m_vram_bg[offset] = data;
+ m_bg_tilemap->mark_tile_dirty(offset);
+}
+
+void kopunch_state::scroll_x_w(uint8_t data)
+{
+ m_scrollx = data;
+ m_bg_tilemap->set_scrollx(0, data);
+}
+void kopunch_state::scroll_y_w(uint8_t data)
+{
+ m_bg_tilemap->set_scrolly(0, data);
+}
+
+void kopunch_state::gfxbank_w(uint8_t data)
+{
+ // d0-d2: bg gfx bank
+ if (m_gfxbank != (data & 0x07))
+ {
+ m_gfxbank = data & 0x07;
+ m_bg_tilemap->mark_all_dirty();
+ }
+
+ // d3: flip y, other bits: N/C
+ m_bg_tilemap->set_flip((data & 0x08) ? TILEMAP_FLIPY : 0);
+}
+
+TILE_GET_INFO_MEMBER(kopunch_state::get_fg_tile_info)
+{
+ int const code = m_vram_fg[tile_index];
+
+ tileinfo.set(0, code, 0, 0);
+}
+
+TILE_GET_INFO_MEMBER(kopunch_state::get_bg_tile_info)
+{
+ // note: highest bit is unused
+ int const code = (m_vram_bg[tile_index] & 0x7f) | m_gfxbank << 7;
+
+ tileinfo.set(1, code, 0, 0);
+}
+
+void kopunch_state::video_start()
+{
+ m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
+
+ m_fg_tilemap->set_transparent_pen(0);
+}
+
+uint32_t kopunch_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ // background does not wrap around horizontally
+ rectangle bg_clip = cliprect;
+ bg_clip.max_x = m_scrollx ^ 0xff;
+
+ m_bg_tilemap->draw(screen, bitmap, bg_clip, 0, 0);
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
+ return 0;
+}
+
+
+// machine
/********************************************************
@@ -66,17 +250,17 @@ INPUT_CHANGED_MEMBER(kopunch_state::right_coin_inserted)
********************************************************/
-void kopunch_state::kopunch_map(address_map &map)
+void kopunch_state::prg_map(address_map &map)
{
map(0x0000, 0x1fff).rom();
map(0x2000, 0x23ff).ram();
- map(0x6000, 0x63ff).ram().w(FUNC(kopunch_state::vram_fg_w)).share("vram_fg");
- map(0x7000, 0x70ff).ram().w(FUNC(kopunch_state::vram_bg_w)).share("vram_bg");
+ map(0x6000, 0x63ff).ram().w(FUNC(kopunch_state::vram_fg_w)).share(m_vram_fg);
+ map(0x7000, 0x70ff).ram().w(FUNC(kopunch_state::vram_bg_w)).share(m_vram_bg);
map(0x7100, 0x73ff).ram(); // unused vram
map(0x7400, 0x7bff).ram(); // more unused vram? or accidental writes?
}
-void kopunch_state::kopunch_io_map(address_map &map)
+void kopunch_state::io_map(address_map &map)
{
map(0x30, 0x33).rw("ppi8255_0", FUNC(i8255_device::read), FUNC(i8255_device::write));
map(0x34, 0x37).rw("ppi8255_1", FUNC(i8255_device::read), FUNC(i8255_device::write));
@@ -106,7 +290,7 @@ uint8_t kopunch_state::sensors2_r()
// d5: unknown sensor
// d6: unknown sensor
// d7: coin 1
- return (machine().rand() & 0x07) | ioport("SYSTEM")->read();
+ return (machine().rand() & 0x07) | m_system->read();
}
void kopunch_state::lamp_w(uint8_t data)
@@ -122,8 +306,8 @@ void kopunch_state::coin_w(uint8_t data)
if (!BIT(data, 6))
m_maincpu->set_input_line(I8085_RST55_LINE, CLEAR_LINE);
-// if ((data & 0x3f) != 0x3e)
-// printf("port 34 = %02x ",data);
+ if ((data & 0x3f) != 0x3e)
+ LOGPORT34("port 34 = %02x ", data);
}
/********************************************************
@@ -141,7 +325,7 @@ static INPUT_PORTS_START( kopunch )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // related to above startbuttons
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // related to above start buttons
PORT_START("SYSTEM")
PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_CUSTOM ) // punch strength (high 3 bits)
@@ -212,8 +396,8 @@ static const gfx_layout bg_layout =
};
static GFXDECODE_START( gfx_kopunch )
- GFXDECODE_ENTRY( "gfx1", 0, fg_layout, 0, 1 )
- GFXDECODE_ENTRY( "gfx2", 0, bg_layout, 0, 1 )
+ GFXDECODE_ENTRY( "fgtiles", 0, fg_layout, 0, 1 )
+ GFXDECODE_ENTRY( "bgtiles", 0, bg_layout, 0, 1 )
GFXDECODE_END
@@ -232,10 +416,10 @@ void kopunch_state::machine_start()
void kopunch_state::kopunch(machine_config &config)
{
- /* basic machine hardware */
- I8085A(config, m_maincpu, 4000000); // 4 MHz?
- m_maincpu->set_addrmap(AS_PROGRAM, &kopunch_state::kopunch_map);
- m_maincpu->set_addrmap(AS_IO, &kopunch_state::kopunch_io_map);
+ // basic machine hardware
+ I8085A(config, m_maincpu, 4'000'000); // 4 MHz?
+ m_maincpu->set_addrmap(AS_PROGRAM, &kopunch_state::prg_map);
+ m_maincpu->set_addrmap(AS_IO, &kopunch_state::io_map);
i8255_device &ppi0(I8255A(config, "ppi8255_0"));
// $30 - always $9b (PPI mode 0, ports A & B & C as input)
@@ -262,20 +446,20 @@ void kopunch_state::kopunch(machine_config &config)
ppi3.in_pc_callback().set_ioport("P2");
ppi3.out_pc_callback().set(FUNC(kopunch_state::gfxbank_w));
- /* 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));
screen.set_size(32*8, 32*8);
screen.set_visarea(0*8, 32*8-1, 2*8, 28*8-1);
- screen.set_screen_update(FUNC(kopunch_state::screen_update_kopunch));
+ screen.set_screen_update(FUNC(kopunch_state::screen_update));
screen.set_palette("palette");
screen.screen_vblank().set_inputline(m_maincpu, I8085_RST75_LINE);
GFXDECODE(config, m_gfxdecode, "palette", gfx_kopunch);
- PALETTE(config, "palette", FUNC(kopunch_state::kopunch_palette), 8);
+ PALETTE(config, "palette", FUNC(kopunch_state::palette), 8);
- /* sound hardware */
+ // sound hardware
// ...
}
@@ -292,12 +476,12 @@ ROM_START( kopunch )
ROM_LOAD( "epr1105.x", 0x0000, 0x1000, CRC(34ef5e79) SHA1(2827c68f4c902f447a304d3ab0258c7819a0e4ca) )
ROM_LOAD( "epr1106.x", 0x1000, 0x1000, CRC(25a5c68b) SHA1(9761418c6f3903f8aaceece658739fe5bf5c0803) )
- ROM_REGION( 0x1800, "gfx1", 0 )
+ ROM_REGION( 0x1800, "fgtiles", 0 )
ROM_LOAD( "epr1103", 0x0000, 0x0800, CRC(bae5e054) SHA1(95373123ab64543cdffb7ee9e02d0613c5c494bf) )
ROM_LOAD( "epr1104", 0x0800, 0x0800, CRC(7b119a0e) SHA1(454f01355fa9512a7442990cc92da7bc7a8d6b68) )
ROM_LOAD( "epr1102", 0x1000, 0x0800, CRC(8a52de96) SHA1(5abdaa83c6bfea81395cb190f5364b72811927ba) )
- ROM_REGION( 0x6000, "gfx2", 0 )
+ ROM_REGION( 0x6000, "bgtiles", 0 )
ROM_LOAD( "epr1107", 0x0000, 0x1000, CRC(ca00244d) SHA1(690931ea1bef9d80dcd7bd2ea2462b083c884a89) )
ROM_LOAD( "epr1108", 0x1000, 0x1000, CRC(cc17c5ed) SHA1(693df076e16cc3a3dd54f6680691e658da3942fe) )
ROM_LOAD( "epr1110", 0x2000, 0x1000, CRC(ae0aff15) SHA1(7f71c94bacdb444e5ed4f917c5a7de17012027a9) )
@@ -306,10 +490,12 @@ ROM_START( kopunch )
ROM_LOAD( "epr1111", 0x5000, 0x1000, CRC(28530ec9) SHA1(1a8782d37128cdb43133fc891cde93d2bdd5476b) )
ROM_REGION( 0x0060, "proms", 0 )
- ROM_LOAD( "epr1101", 0x0000, 0x0020, CRC(15600f5d) SHA1(130179f79761cb16316c544e3c689bc10431db30) ) /* palette */
- ROM_LOAD( "epr1099", 0x0020, 0x0020, CRC(fc58c456) SHA1(f27c3ad669dfdc33bcd7e0481fa01bf34973e816) ) /* unknown */
- ROM_LOAD( "epr1100", 0x0040, 0x0020, CRC(bedb66b1) SHA1(8e78bb205d900075b761e1baa5f5813174ff28ba) ) /* unknown */
+ ROM_LOAD( "epr1101", 0x0000, 0x0020, CRC(15600f5d) SHA1(130179f79761cb16316c544e3c689bc10431db30) ) // palette
+ ROM_LOAD( "epr1099", 0x0020, 0x0020, CRC(fc58c456) SHA1(f27c3ad669dfdc33bcd7e0481fa01bf34973e816) ) // unknown
+ ROM_LOAD( "epr1100", 0x0040, 0x0020, CRC(bedb66b1) SHA1(8e78bb205d900075b761e1baa5f5813174ff28ba) ) // unknown
ROM_END
+} // anonymous namespace
+
GAME( 1981, kopunch, 0, kopunch, kopunch, kopunch_state, empty_init, ROT270, "Sega", "KO Punch", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/sega/kopunch.h b/src/mame/sega/kopunch.h
deleted file mode 100644
index c7f5eed4108..00000000000
--- a/src/mame/sega/kopunch.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
-/*************************************************************************
-
- Sega KO Punch
-
-*************************************************************************/
-#ifndef MAME_INCLUDES_KOPUNCH_H
-#define MAME_INCLUDES_KOPUNCH_H
-
-#pragma once
-
-#include "emupal.h"
-#include "tilemap.h"
-
-class kopunch_state : public driver_device
-{
-public:
- kopunch_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag)
- , m_maincpu(*this, "maincpu")
- , m_gfxdecode(*this, "gfxdecode")
- , m_vram_fg(*this, "vram_fg")
- , m_vram_bg(*this, "vram_bg")
- , m_lamp(*this, "lamp0")
- { }
-
- void kopunch(machine_config &config);
-
- DECLARE_INPUT_CHANGED_MEMBER(left_coin_inserted);
- DECLARE_INPUT_CHANGED_MEMBER(right_coin_inserted);
-
-private:
- uint8_t sensors1_r();
- uint8_t sensors2_r();
- void lamp_w(uint8_t data);
- void coin_w(uint8_t data);
- void vram_fg_w(offs_t offset, uint8_t data);
- void vram_bg_w(offs_t offset, uint8_t data);
- void scroll_x_w(uint8_t data);
- void scroll_y_w(uint8_t data);
- void gfxbank_w(uint8_t data);
-
- TILE_GET_INFO_MEMBER(get_fg_tile_info);
- TILE_GET_INFO_MEMBER(get_bg_tile_info);
- void kopunch_palette(palette_device &palette) const;
- uint32_t screen_update_kopunch(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-
- void kopunch_io_map(address_map &map);
- void kopunch_map(address_map &map);
-
- virtual void machine_start() override;
- virtual void video_start() override;
-
- /* devices */
- required_device<cpu_device> m_maincpu;
- required_device<gfxdecode_device> m_gfxdecode;
-
- /* memory pointers */
- required_shared_ptr<uint8_t> m_vram_fg;
- required_shared_ptr<uint8_t> m_vram_bg;
-
- output_finder<> m_lamp;
-
- /* video-related */
- tilemap_t *m_bg_tilemap = nullptr;
- tilemap_t *m_fg_tilemap = nullptr;
- uint8_t m_gfxbank = 0U;
- uint8_t m_scrollx = 0U;
-};
-
-#endif // MAME_INCLUDES_KOPUNCH_H
diff --git a/src/mame/sega/kopunch_v.cpp b/src/mame/sega/kopunch_v.cpp
deleted file mode 100644
index 391d6bb2a17..00000000000
--- a/src/mame/sega/kopunch_v.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
-/*************************************************************************
-
- Sega KO Punch
-
- Functions to emulate the video hardware of the machine.
-
-*************************************************************************/
-
-#include "emu.h"
-#include "kopunch.h"
-
-
-void kopunch_state::kopunch_palette(palette_device &palette) const
-{
- const uint8_t *color_prom = memregion("proms")->base();
-
- color_prom += 24; // first 24 colors are black
-
- for (int i = 0; i < palette.entries(); i++)
- {
- int bit0, bit1, bit2;
-
- // red component
- bit0 = BIT(*color_prom, 0);
- bit1 = BIT(*color_prom, 1);
- bit2 = BIT(*color_prom, 2);
- int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
- // green component
- bit0 = BIT(*color_prom, 3);
- bit1 = BIT(*color_prom, 4);
- bit2 = BIT(*color_prom, 5);
- int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
- // blue component
- bit0 = 0;
- bit1 = BIT(*color_prom, 6);
- bit2 = BIT(*color_prom, 7);
- int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
-
- palette.set_pen_color(i, rgb_t(r, g, b));
- color_prom++;
- }
-}
-
-void kopunch_state::vram_fg_w(offs_t offset, uint8_t data)
-{
- m_vram_fg[offset] = data;
- m_fg_tilemap->mark_tile_dirty(offset);
-}
-
-void kopunch_state::vram_bg_w(offs_t offset, uint8_t data)
-{
- m_vram_bg[offset] = data;
- m_bg_tilemap->mark_tile_dirty(offset);
-}
-
-void kopunch_state::scroll_x_w(uint8_t data)
-{
- m_scrollx = data;
- m_bg_tilemap->set_scrollx(0, data);
-}
-
-void kopunch_state::scroll_y_w(uint8_t data)
-{
- m_bg_tilemap->set_scrolly(0, data);
-}
-
-void kopunch_state::gfxbank_w(uint8_t data)
-{
- // d0-d2: bg gfx bank
- if (m_gfxbank != (data & 0x07))
- {
- m_gfxbank = data & 0x07;
- m_bg_tilemap->mark_all_dirty();
- }
-
- // d3: flip y, other bits: N/C
- m_bg_tilemap->set_flip((data & 0x08) ? TILEMAP_FLIPY : 0);
-}
-
-TILE_GET_INFO_MEMBER(kopunch_state::get_fg_tile_info)
-{
- int code = m_vram_fg[tile_index];
-
- tileinfo.set(0, code, 0, 0);
-}
-
-TILE_GET_INFO_MEMBER(kopunch_state::get_bg_tile_info)
-{
- // note: highest bit is unused
- int code = (m_vram_bg[tile_index] & 0x7f) | m_gfxbank << 7;
-
- tileinfo.set(1, code, 0, 0);
-}
-
-void kopunch_state::video_start()
-{
- m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
-
- m_fg_tilemap->set_transparent_pen(0);
-}
-
-uint32_t kopunch_state::screen_update_kopunch(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- bitmap.fill(0, cliprect);
-
- // background does not wrap around horizontally
- rectangle bg_clip = cliprect;
- bg_clip.max_x = m_scrollx ^ 0xff;
-
- m_bg_tilemap->draw(screen, bitmap, bg_clip, 0, 0);
- m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
-
- return 0;
-}
diff --git a/src/mame/sega/stactics.cpp b/src/mame/sega/stactics.cpp
index 1dd061a1d1f..5081d78dd58 100644
--- a/src/mame/sega/stactics.cpp
+++ b/src/mame/sega/stactics.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Frank Palazzolo
+// copyright-holders: Frank Palazzolo
+
/****************************************************************************
Sega "Space Tactics" Driver
@@ -43,15 +44,534 @@ Verify Color PROM resistor values (Last 8 colors)
****************************************************************************/
#include "emu.h"
-#include "stactics.h"
+
#include "stactics.lh"
#include "cpu/i8085/i8085.h"
+#include "machine/74259.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+
+namespace {
+
+class stactics_state : public driver_device
+{
+public:
+ stactics_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_outlatch(*this, "outlatch"),
+ m_display_buffer(*this, "display_buffer"),
+ m_videoram_b(*this, "videoram_b"),
+ m_videoram_d(*this, "videoram_d"),
+ m_videoram_e(*this, "videoram_e"),
+ m_videoram_f(*this, "videoram_f"),
+ m_beam_region(*this, "beam"),
+ m_base_lamps(*this, "base_lamp%u", 0U),
+ m_beam_leds_left(*this, "beam_led_left%u", 0U),
+ m_beam_leds_right(*this, "beam_led_right%u", 0U),
+ m_score_digits(*this, "digit%u", 0U),
+ m_credit_leds(*this, "credit_led%u", 0U),
+ m_barrier_leds(*this, "barrier_led%u", 0U),
+ m_round_leds(*this, "round_led%u", 0U),
+ m_barrier_lamp(*this, "barrier_lamp"),
+ m_start_lamp(*this, "start_lamp"),
+ m_sight_led(*this, "sight_led"),
+ m_in3(*this, "IN3"),
+ m_fake(*this, "FAKE")
+ { }
+
+ void stactics(machine_config &config);
+
+ DECLARE_READ_LINE_MEMBER(frame_count_d3_r);
+ DECLARE_READ_LINE_MEMBER(shot_standby_r);
+ DECLARE_READ_LINE_MEMBER(not_shot_arrive_r);
+ DECLARE_READ_LINE_MEMBER(motor_not_ready_r);
+ DECLARE_CUSTOM_INPUT_MEMBER(get_rng);
+
+protected:
+ virtual void machine_start() override;
+ virtual void video_start() override;
+
+private:
+ uint8_t vert_pos_r();
+ uint8_t horiz_pos_r();
+ template <uint8_t Which> DECLARE_WRITE_LINE_MEMBER(coin_lockout_w);
+ DECLARE_WRITE_LINE_MEMBER(palette_bank_w);
+ void scroll_ram_w(offs_t offset, uint8_t data);
+ void speed_latch_w(uint8_t data);
+ void shot_trigger_w(uint8_t data);
+ void shot_flag_clear_w(uint8_t data);
+ DECLARE_WRITE_LINE_MEMBER(motor_w);
+
+ INTERRUPT_GEN_MEMBER(interrupt);
+
+ DECLARE_WRITE_LINE_MEMBER(barrier_lamp_w);
+ DECLARE_WRITE_LINE_MEMBER(start_lamp_w);
+ template <unsigned N> DECLARE_WRITE_LINE_MEMBER(base_lamp_w) { m_base_lamps[N] = state; }
+
+ void palette(palette_device &palette) const;
+
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void update_beam();
+ inline int get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll);
+ void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect);
+ template <unsigned N> void set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index);
+ void update_artwork();
+ void move_motor();
+
+ void main_map(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<ls259_device> m_outlatch;
+
+ required_shared_ptr<uint8_t> m_display_buffer;
+ required_shared_ptr<uint8_t> m_videoram_b;
+ required_shared_ptr<uint8_t> m_videoram_d;
+ required_shared_ptr<uint8_t> m_videoram_e;
+ required_shared_ptr<uint8_t> m_videoram_f;
+ required_region_ptr<uint8_t> m_beam_region;
+
+ output_finder<5> m_base_lamps;
+ output_finder<0x40> m_beam_leds_left;
+ output_finder<0x40> m_beam_leds_right;
+ output_finder<6> m_score_digits;
+ output_finder<8> m_credit_leds;
+ output_finder<12> m_barrier_leds;
+ output_finder<16> m_round_leds;
+ output_finder<> m_barrier_lamp;
+ output_finder<> m_start_lamp;
+ output_finder<> m_sight_led;
+
+ required_ioport m_in3;
+ required_ioport m_fake;
+
+ // machine state
+ int32_t m_vert_pos = 0;
+ int32_t m_horiz_pos = 0;
+ bool m_motor_on = false;
+
+ // video state
+ uint8_t m_y_scroll_d = 0;
+ uint8_t m_y_scroll_e = 0;
+ uint8_t m_y_scroll_f = 0;
+ uint8_t m_frame_count = 0;
+ uint8_t m_shot_standby = 0;
+ uint8_t m_shot_arrive = 0;
+ uint16_t m_beam_state = 0;
+ uint16_t m_old_beam_state = 0;
+ uint16_t m_beam_states_per_frame = 0;
+ uint8_t m_palette_bank = 0;
+};
+
+
+// video
+
+/****************************************************************************
+
+The Video system used in Space Tactics is unusual.
+Here are my notes on how the video system works:
+
+There are 4, 4K pages of Video RAM. (B,D,E & F)
+
+The first 1K of each VRAM page contains the following:
+0 0 V V V V V H H H H H offset value for each 8x8 bitmap
+ (v-tile) (h-tile)
+
+The offset values are used to generate an access into the
+last 2K of the VRAM page:
+1 D D D D D D D D V V V here we find 8x8 character data
+ (offset) (line)
+
+In addition, in Page B, the upper nibble of the offset is
+also used to select the color palette for the tile.
+
+Page B, D, E, and F all work similarly, except that pages
+D, E, and F can be offset from Page B by a given
+number of scanlines, based on the contents of the offset
+RAM
+
+The offset RAM is addressed in this format:
+1 0 0 0 P P P V V V V V V V V V
+ (Page) (scanline)
+Page 4=D, 5=E, 6=F
+
+Page D, E, and F are drawn offset from the top of the screen,
+starting on the first scanline which contains a 1 in the
+appropriate memory location
+
+---
+
+The composited monitor image is seen in a mirror. It appears
+to move when the player moves the handle, due to motors which
+tilt the mirror up and down, and the monitor left and right.
+
+---
+
+***************************************************************************/
+
+
+/*************************************
+ *
+ * Palette
+ *
+ *************************************/
+
+void stactics_state::palette(palette_device &palette) const
+{
+ uint8_t const *const color_prom = memregion("proms")->base();
+
+ for (int i = 0; i < 0x400; i++)
+ {
+ int const bit0 = BIT(color_prom[i], 0);
+ int const bit1 = BIT(color_prom[i], 1);
+ int const bit2 = BIT(color_prom[i], 2);
+ int const bit3 = BIT(color_prom[i], 3);
+
+ // red component
+ int const r = 0xff * bit0;
+
+ // green component
+ int const g = 0xff * bit1 - 0xcc * bit3;
+
+ // blue component
+ int const b = 0xff * bit2;
+
+ palette.set_pen_color(i, rgb_t(r, g, b));
+ }
+}
+
+
+WRITE_LINE_MEMBER(stactics_state::palette_bank_w)
+{
+ m_palette_bank = m_outlatch->q6_r() | (m_outlatch->q7_r() << 1);
+}
+
+
+
+/*************************************
+ *
+ * Scrolling
+ *
+ *************************************/
+
+void stactics_state::scroll_ram_w(offs_t offset, uint8_t data)
+{
+ if (data & 0x01)
+ {
+ switch (offset >> 8)
+ {
+ case 4: m_y_scroll_d = offset & 0xff; break;
+ case 5: m_y_scroll_e = offset & 0xff; break;
+ case 6: m_y_scroll_f = offset & 0xff; break;
+ }
+ }
+}
+
+
+
+/*************************************
+ *
+ * Frane counter
+ *
+ *************************************/
+
+READ_LINE_MEMBER(stactics_state::frame_count_d3_r)
+{
+ return (m_frame_count >> 3) & 0x01;
+}
+
+
+
+/*************************************
+ *
+ * Beam handling
+ *
+ *************************************/
+
+void stactics_state::speed_latch_w(uint8_t data)
+{
+ /* This writes to a shift register which is clocked by
+ a 555 oscillator. This value determines the speed of
+ the LED fire beams as follows:
+
+ 555_freq / bits_in_SR * edges_in_SR / states_in_PR67 / frame_rate
+ = num_led_states_per_frame
+ 36439 / 8 * x / 32 / 60 ~= 19/8*x
+
+ Here, we will count the number of rising edges in the shift register */
+
+ int num_rising_edges = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if ((((data >> i) & 0x01) == 1) && (((data >> ((i + 1) % 8)) & 0x01) == 0))
+ num_rising_edges++;
+ }
+
+ m_beam_states_per_frame = num_rising_edges * 19 / 8;
+}
+
+
+void stactics_state::shot_trigger_w(uint8_t data)
+{
+ m_shot_standby = 0;
+}
+
+
+void stactics_state::shot_flag_clear_w(uint8_t data)
+{
+ m_shot_arrive = 0;
+}
+
+
+READ_LINE_MEMBER(stactics_state::shot_standby_r)
+{
+ return m_shot_standby;
+}
+
+
+READ_LINE_MEMBER(stactics_state::not_shot_arrive_r)
+{
+ return !m_shot_arrive;
+}
+
+
+void stactics_state::update_beam()
+{
+ // first, update the firebeam state
+ m_old_beam_state = m_beam_state;
+ if (m_shot_standby == 0)
+ m_beam_state = m_beam_state + m_beam_states_per_frame;
+
+ /* These are thresholds for the two shots from the LED fire ROM
+ (Note: There are two more for sound triggers,
+ whenever that gets implemented) */
+ if ((m_old_beam_state < 0x8b) & (m_beam_state >= 0x8b))
+ m_shot_arrive = 1;
+
+ if ((m_old_beam_state < 0xca) & (m_beam_state >= 0xca))
+ m_shot_arrive = 1;
+
+ if (m_beam_state >= 0x100)
+ {
+ m_beam_state = 0;
+ m_shot_standby = 1;
+ }
+}
/*************************************
*
+ * Video drawing
+ *
+ *************************************/
+
+inline int stactics_state::get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll)
+{
+ // compute effective row
+ y = y - y_scroll;
+
+ // get the character code at the given pixel
+ uint8_t const code = videoram[((y >> 3) << 5) | (x >> 3)];
+
+ // get the gfx byte
+ uint8_t const gfx = videoram[0x800 | (code << 3) | (y & 0x07)];
+
+ // return the appropriate pixel within the byte
+ return (gfx >> (~x & 0x07)) & 0x01;
+}
+
+
+void stactics_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ // for every row
+ for (int y = 0; y < 0x100; y++)
+ {
+ // for every pixel on the row
+ for (int x = 0; x < 0x100; x++)
+ {
+ // get the pixels for the four planes
+ int const pixel_b = get_pixel_on_plane(m_videoram_b, y, x, 0);
+ int const pixel_d = get_pixel_on_plane(m_videoram_d, y, x, m_y_scroll_d);
+ int const pixel_e = get_pixel_on_plane(m_videoram_e, y, x, m_y_scroll_e);
+ int const pixel_f = get_pixel_on_plane(m_videoram_f, y, x, m_y_scroll_f);
+
+ // get the color for this pixel
+ uint8_t const color = m_videoram_b[((y >> 3) << 5) | (x >> 3)] >> 4;
+
+ // assemble the pen index
+ int const pen = color |
+ (pixel_b << 4) |
+ (pixel_f << 5) |
+ (pixel_e << 6) |
+ (pixel_d << 7) |
+ (m_palette_bank << 8);
+
+ /* compute the effective pixel coordinate after adjusting for the
+ mirror movement - this is mechanical on the real machine */
+ int const sy = y + m_vert_pos;
+ int const sx = x - m_horiz_pos;
+
+ // plot if visible
+ if ((sy >= 0) && (sy < 0x100) && (sx >= 0) && (sx < 0x100))
+ bitmap.pix(sy, sx) = pen;
+ }
+ }
+}
+
+
+
+/*************************************
+ *
+ * Non-video artwork
+ *
+ *************************************/
+
+// from 7448 datasheet
+static constexpr int to_7seg[0x10] =
+{
+ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07,
+ 0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0x00
+};
+
+
+template <unsigned N> void stactics_state::set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index)
+{
+ // decode the data
+ int const data = to_7seg[~m_display_buffer[offset] & 0x0f];
+
+ // set the 4 LEDs
+ outputs[base_index + 0] = BIT(data, 2);
+ outputs[base_index + 1] = BIT(data, 6);
+ outputs[base_index + 2] = BIT(data, 5);
+ outputs[base_index + 3] = BIT(data, 4);
+}
+
+
+WRITE_LINE_MEMBER(stactics_state::barrier_lamp_w)
+{
+ // this needs to flash on/off, not implemented
+ m_barrier_lamp = state;
+}
+
+
+WRITE_LINE_MEMBER(stactics_state::start_lamp_w)
+{
+ m_start_lamp = state;
+}
+
+
+void stactics_state::update_artwork()
+{
+ // laser beam - loop for each LED
+ for (int i = 0; i < 0x40; i++)
+ {
+ offs_t const beam_data_offs = ((i & 0x08) << 7) | ((i & 0x30) << 4) | m_beam_state;
+ uint8_t const beam_data = m_beam_region[beam_data_offs];
+ int const on = BIT(beam_data, i & 0x07);
+
+ m_beam_leds_left[i] = on;
+ m_beam_leds_right[i] = on;
+ }
+
+ // sight LED
+ m_sight_led = m_motor_on;
+
+ // score display
+ for (int i = 0x01; i < 0x07; i++)
+ m_score_digits[i - 1] = to_7seg[~m_display_buffer[i] & 0x0f];
+
+ // credits indicator
+ set_indicator_leds(0x07, m_credit_leds, 0x00);
+ set_indicator_leds(0x08, m_credit_leds, 0x04);
+
+ // barriers indicator
+ set_indicator_leds(0x09, m_barrier_leds, 0x00);
+ set_indicator_leds(0x0a, m_barrier_leds, 0x04);
+ set_indicator_leds(0x0b, m_barrier_leds, 0x08);
+
+ // rounds indicator
+ set_indicator_leds(0x0c, m_round_leds, 0x00);
+ set_indicator_leds(0x0d, m_round_leds, 0x04);
+ set_indicator_leds(0x0e, m_round_leds, 0x08);
+ set_indicator_leds(0x0f, m_round_leds, 0x0c);
+}
+
+
+
+/*************************************
+ *
+ * Start
+ *
+ *************************************/
+
+void stactics_state::video_start()
+{
+ m_base_lamps.resolve();
+ m_beam_leds_left.resolve();
+ m_beam_leds_right.resolve();
+ m_score_digits.resolve();
+ m_credit_leds.resolve();
+ m_barrier_leds.resolve();
+ m_round_leds.resolve();
+ m_barrier_lamp.resolve();
+ m_start_lamp.resolve();
+ m_sight_led.resolve();
+
+ m_y_scroll_d = 0;
+ m_y_scroll_e = 0;
+ m_y_scroll_f = 0;
+
+ m_frame_count = 0;
+ m_shot_standby = 1;
+ m_shot_arrive = 0;
+ m_beam_state = 0;
+ m_old_beam_state = 0;
+
+ m_palette_bank = 0;
+
+ save_item(NAME(m_y_scroll_d));
+ save_item(NAME(m_y_scroll_e));
+ save_item(NAME(m_y_scroll_f));
+ save_item(NAME(m_frame_count));
+ save_item(NAME(m_shot_standby));
+ save_item(NAME(m_shot_arrive));
+ save_item(NAME(m_beam_state));
+ save_item(NAME(m_old_beam_state));
+ save_item(NAME(m_beam_states_per_frame));
+ save_item(NAME(m_palette_bank));
+}
+
+
+
+/*************************************
+ *
+ * Update
+ *
+ *************************************/
+
+uint32_t stactics_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ update_beam();
+ draw_background(bitmap, cliprect);
+ update_artwork();
+
+ m_frame_count = (m_frame_count + 1) & 0x0f;
+
+ return 0;
+}
+
+
+// machine
+
+/*************************************
+ *
* Mirror motor handling
*
*************************************/
@@ -89,24 +609,24 @@ void stactics_state::move_motor()
const int in3 = m_in3->read();
const int in4 = m_fake->read();
- /* up */
+ // up
if (!(in4 & 0x01) && m_vert_pos > -128)
m_vert_pos--;
- /* down */
+ // down
if (!(in4 & 0x02) && m_vert_pos < 127)
m_vert_pos++;
- /* left */
+ // left
if (!(in3 & 0x20) && m_horiz_pos < 127)
m_horiz_pos++;
- /* right */
+ // right
if (!(in3 & 0x40) && m_horiz_pos > -128)
m_horiz_pos--;
}
- /* monitor motor under self-centering control */
+ // monitor motor under self-centering control
else
{
if (m_horiz_pos > 0)
@@ -131,7 +651,7 @@ void stactics_state::move_motor()
CUSTOM_INPUT_MEMBER(stactics_state::get_rng)
{
- /* this is a 555 timer, but cannot read one of the resistor values */
+ // this is a 555 timer, but cannot read one of the resistor values
return machine().rand() & 0x07;
}
@@ -143,15 +663,10 @@ CUSTOM_INPUT_MEMBER(stactics_state::get_rng)
*
*************************************/
-WRITE_LINE_MEMBER(stactics_state::coin_lockout_1_w)
+template <uint8_t Which>
+WRITE_LINE_MEMBER(stactics_state::coin_lockout_w)
{
- machine().bookkeeping().coin_lockout_w(0, !state);
-}
-
-
-WRITE_LINE_MEMBER(stactics_state::coin_lockout_2_w)
-{
- machine().bookkeeping().coin_lockout_w(1, !state);
+ machine().bookkeeping().coin_lockout_w(Which, !state);
}
@@ -189,20 +704,20 @@ void stactics_state::main_map(address_map &map)
map(0x6030, 0x6030).mirror(0x0f0f).w(FUNC(stactics_state::speed_latch_w));
map(0x6040, 0x6040).mirror(0x0f0f).w(FUNC(stactics_state::shot_trigger_w));
map(0x6050, 0x6050).mirror(0x0f0f).w(FUNC(stactics_state::shot_flag_clear_w));
- map(0x6060, 0x606f).mirror(0x0f00).writeonly().share("display_buffer");
+ map(0x6060, 0x606f).mirror(0x0f00).writeonly().share(m_display_buffer);
map(0x6070, 0x609f).mirror(0x0f00).nopw();
- /* map(0x60a0, 0x60ef).mirror(0x0f00).w(FUNC(stactics_state::sound2_w)); */
+ // map(0x60a0, 0x60ef).mirror(0x0f00).w(FUNC(stactics_state::sound2_w));
map(0x60f0, 0x60ff).mirror(0x0f00).nopw();
map(0x7000, 0x7000).mirror(0x0fff).portr("IN2");
map(0x8000, 0x8000).mirror(0x0fff).portr("IN3");
map(0x8000, 0x87ff).mirror(0x0800).w(FUNC(stactics_state::scroll_ram_w));
map(0x9000, 0x9000).mirror(0x0fff).r(FUNC(stactics_state::vert_pos_r));
map(0xa000, 0xa000).mirror(0x0fff).r(FUNC(stactics_state::horiz_pos_r));
- map(0xb000, 0xbfff).ram().share("videoram_b");
+ map(0xb000, 0xbfff).ram().share(m_videoram_b);
map(0xc000, 0xcfff).noprw();
- map(0xd000, 0xdfff).ram().share("videoram_d");
- map(0xe000, 0xefff).ram().share("videoram_e");
- map(0xf000, 0xffff).ram().share("videoram_f");
+ map(0xd000, 0xdfff).ram().share(m_videoram_d);
+ map(0xe000, 0xefff).ram().share(m_videoram_e);
+ map(0xf000, 0xffff).ram().share(m_videoram_f);
}
@@ -214,7 +729,7 @@ void stactics_state::main_map(address_map &map)
*************************************/
static INPUT_PORTS_START( stactics )
- PORT_START("IN0") /* IN0 */
+ PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON6 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON5 )
@@ -224,7 +739,7 @@ static INPUT_PORTS_START( stactics )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, motor_not_ready_r)
- PORT_START("IN1") /* IN1 */
+ PORT_START("IN1")
PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_B ) )
PORT_DIPSETTING( 0x01, DEF_STR( 4C_1C ) )
PORT_DIPSETTING( 0x05, DEF_STR( 2C_1C ) )
@@ -250,7 +765,7 @@ static INPUT_PORTS_START( stactics )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_START("IN2") /* IN2 */
+ PORT_START("IN2")
PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(stactics_state, get_rng)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, frame_count_d3_r)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
@@ -260,7 +775,7 @@ static INPUT_PORTS_START( stactics )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_SERVICE( 0x80, IP_ACTIVE_LOW )
- PORT_START("IN3") /* IN3 */
+ PORT_START("IN3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, shot_standby_r)
PORT_DIPNAME( 0x04, 0x04, "Number of Barriers" )
@@ -276,7 +791,7 @@ static INPUT_PORTS_START( stactics )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, not_shot_arrive_r)
- PORT_START("FAKE") /* FAKE */
+ PORT_START("FAKE")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
INPUT_PORTS_END
@@ -310,14 +825,14 @@ void stactics_state::machine_start()
void stactics_state::stactics(machine_config &config)
{
- /* basic machine hardware */
+ // basic machine hardware
I8080(config, m_maincpu, 15.46848_MHz_XTAL / 8); // divider not verified
m_maincpu->set_addrmap(AS_PROGRAM, &stactics_state::main_map);
m_maincpu->set_vblank_int("screen", FUNC(stactics_state::interrupt));
LS259(config, m_outlatch); // 50
- m_outlatch->q_out_cb<0>().set(FUNC(stactics_state::coin_lockout_1_w)); // COIN REJECT 1
- m_outlatch->q_out_cb<1>().set(FUNC(stactics_state::coin_lockout_2_w)); // COIN REJECT 2
+ m_outlatch->q_out_cb<0>().set(FUNC(stactics_state::coin_lockout_w<0>)); // COIN REJECT 1
+ m_outlatch->q_out_cb<1>().set(FUNC(stactics_state::coin_lockout_w<1>)); // COIN REJECT 2
m_outlatch->q_out_cb<6>().set(FUNC(stactics_state::palette_bank_w)); // FLM COL 0
m_outlatch->q_out_cb<7>().set(FUNC(stactics_state::palette_bank_w)); // FLM COL 1
@@ -340,10 +855,16 @@ void stactics_state::stactics(machine_config &config)
lamplatch.q_out_cb<5>().set(FUNC(stactics_state::start_lamp_w));
lamplatch.q_out_cb<6>().set(FUNC(stactics_state::barrier_lamp_w));
- /* video hardware */
- stactics_video(config);
+ // video hardware
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_video_attributes(VIDEO_ALWAYS_UPDATE);
+ screen.set_raw(15.46848_MHz_XTAL / 3, 328, 0, 256, 262, 0, 232);
+ screen.set_screen_update(FUNC(stactics_state::screen_update));
+ screen.set_palette("palette");
+
+ PALETTE(config, "palette", FUNC(stactics_state::palette), 0x400);
- /* audio hardware */
+ // audio hardware
}
@@ -364,16 +885,17 @@ ROM_START( stactics )
ROM_LOAD( "epr-223x", 0x2800, 0x0800, CRC(7fef0940) SHA1(5b2af55f75ef0130f9202b6a916a96dbd601fcfa) )
ROM_REGION( 0x1040, "proms", 0 )
- ROM_LOAD( "pr54", 0x0000, 0x0800, CRC(9640bd6e) SHA1(dd12952a6591f2056ac1b5688dca0a3a2ef69f2d) ) /* color/priority PROM */
- ROM_LOAD( "pr55", 0x0800, 0x0800, CRC(f162673b) SHA1(83743780b6c1f8014df24fa0650000b7cb137d92) ) /* timing PROM (unused) */
- ROM_LOAD( "pr65", 0x1000, 0x0020, CRC(a1506b9d) SHA1(037c3db2ea40eca459e8acba9d1506dd28d72d10) ) /* timing PROM (unused) */
- ROM_LOAD( "pr66", 0x1020, 0x0020, CRC(78dcf300) SHA1(37034cc0cfa4a8ec47937a2a34b77ec56b387a9b) ) /* timing PROM (unused) */
-
- ROM_REGION( 0x0820, "user1", 0 )
- ROM_LOAD( "epr-217", 0x0000, 0x0800, CRC(38259f5f) SHA1(1f4182ffc2d78fca22711526bb2ae2cfe040173c) ) /* LED fire beam data */
- ROM_LOAD( "pr67", 0x0800, 0x0020, CRC(b27874e7) SHA1(c24bc78c4b2ae01aaed5d994ce2e7c5e0f2eece8) ) /* LED timing ROM (unused) */
+ ROM_LOAD( "pr54", 0x0000, 0x0800, CRC(9640bd6e) SHA1(dd12952a6591f2056ac1b5688dca0a3a2ef69f2d) ) // color/priority PROM
+ ROM_LOAD( "pr55", 0x0800, 0x0800, CRC(f162673b) SHA1(83743780b6c1f8014df24fa0650000b7cb137d92) ) // timing PROM (unused)
+ ROM_LOAD( "pr65", 0x1000, 0x0020, CRC(a1506b9d) SHA1(037c3db2ea40eca459e8acba9d1506dd28d72d10) ) // timing PROM (unused)
+ ROM_LOAD( "pr66", 0x1020, 0x0020, CRC(78dcf300) SHA1(37034cc0cfa4a8ec47937a2a34b77ec56b387a9b) ) // timing PROM (unused)
+
+ ROM_REGION( 0x0820, "beam", 0 )
+ ROM_LOAD( "epr-217", 0x0000, 0x0800, CRC(38259f5f) SHA1(1f4182ffc2d78fca22711526bb2ae2cfe040173c) ) // LED fire beam data
+ ROM_LOAD( "pr67", 0x0800, 0x0020, CRC(b27874e7) SHA1(c24bc78c4b2ae01aaed5d994ce2e7c5e0f2eece8) ) // LED timing ROM (unused)
ROM_END
+} // anonymous namespace
/*************************************
diff --git a/src/mame/sega/stactics.h b/src/mame/sega/stactics.h
deleted file mode 100644
index adc7937a709..00000000000
--- a/src/mame/sega/stactics.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Frank Palazzolo
-/****************************************************************************
-
- Sega "Space Tactics" Driver
-
- Frank Palazzolo (palazzol@home.com)
-
-****************************************************************************/
-#ifndef MAME_INCLUDES_STACTICS_H
-#define MAME_INCLUDES_STACTICS_H
-
-#pragma once
-
-#include "machine/74259.h"
-#include "emupal.h"
-
-class stactics_state : public driver_device
-{
-public:
- stactics_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_outlatch(*this, "outlatch"),
- m_display_buffer(*this, "display_buffer"),
- m_videoram_b(*this, "videoram_b"),
- m_videoram_d(*this, "videoram_d"),
- m_videoram_e(*this, "videoram_e"),
- m_videoram_f(*this, "videoram_f"),
- m_base_lamps(*this, "base_lamp%u", 0U),
- m_beam_leds_left(*this, "beam_led_left%u", 0U),
- m_beam_leds_right(*this, "beam_led_right%u", 0U),
- m_score_digits(*this, "digit%u", 0U),
- m_credit_leds(*this, "credit_led%u", 0U),
- m_barrier_leds(*this, "barrier_led%u", 0U),
- m_round_leds(*this, "round_led%u", 0U),
- m_barrier_lamp(*this, "barrier_lamp"),
- m_start_lamp(*this, "start_lamp"),
- m_sight_led(*this, "sight_led"),
- m_in3(*this, "IN3"),
- m_fake(*this, "FAKE")
- { }
-
- void stactics(machine_config &config);
-
- DECLARE_READ_LINE_MEMBER(frame_count_d3_r);
- DECLARE_READ_LINE_MEMBER(shot_standby_r);
- DECLARE_READ_LINE_MEMBER(not_shot_arrive_r);
- DECLARE_READ_LINE_MEMBER(motor_not_ready_r);
- DECLARE_CUSTOM_INPUT_MEMBER(get_rng);
-
-private:
- uint8_t vert_pos_r();
- uint8_t horiz_pos_r();
- DECLARE_WRITE_LINE_MEMBER(coin_lockout_1_w);
- DECLARE_WRITE_LINE_MEMBER(coin_lockout_2_w);
- DECLARE_WRITE_LINE_MEMBER(palette_bank_w);
- void scroll_ram_w(offs_t offset, uint8_t data);
- void speed_latch_w(uint8_t data);
- void shot_trigger_w(uint8_t data);
- void shot_flag_clear_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
-
- INTERRUPT_GEN_MEMBER(interrupt);
-
- DECLARE_WRITE_LINE_MEMBER(barrier_lamp_w);
- DECLARE_WRITE_LINE_MEMBER(start_lamp_w);
- template <unsigned N> DECLARE_WRITE_LINE_MEMBER(base_lamp_w) { m_base_lamps[N] = state; }
- DECLARE_WRITE_LINE_MEMBER(base_2_lamp_w);
- DECLARE_WRITE_LINE_MEMBER(base_3_lamp_w);
- DECLARE_WRITE_LINE_MEMBER(base_4_lamp_w);
- DECLARE_WRITE_LINE_MEMBER(base_5_lamp_w);
-
- virtual void machine_start() override;
- virtual void video_start() override;
- void stactics_palette(palette_device &palette) const;
-
- uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- void update_beam();
- inline int get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll);
- void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect);
- template <unsigned N> void set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index);
- void update_artwork();
- void move_motor();
-
- void stactics_video(machine_config &config);
- void main_map(address_map &map);
-
- required_device<cpu_device> m_maincpu;
- required_device<ls259_device> m_outlatch;
-
- required_shared_ptr<uint8_t> m_display_buffer;
- required_shared_ptr<uint8_t> m_videoram_b;
- required_shared_ptr<uint8_t> m_videoram_d;
- required_shared_ptr<uint8_t> m_videoram_e;
- required_shared_ptr<uint8_t> m_videoram_f;
-
- output_finder<5> m_base_lamps;
- output_finder<0x40> m_beam_leds_left;
- output_finder<0x40> m_beam_leds_right;
- output_finder<6> m_score_digits;
- output_finder<8> m_credit_leds;
- output_finder<12> m_barrier_leds;
- output_finder<16> m_round_leds;
- output_finder<> m_barrier_lamp;
- output_finder<> m_start_lamp;
- output_finder<> m_sight_led;
-
- required_ioport m_in3;
- required_ioport m_fake;
-
- /* machine state */
- int m_vert_pos = 0;
- int m_horiz_pos = 0;
- bool m_motor_on = false;
-
- /* video state */
- uint8_t m_y_scroll_d = 0;
- uint8_t m_y_scroll_e = 0;
- uint8_t m_y_scroll_f = 0;
- uint8_t m_frame_count = 0;
- uint8_t m_shot_standby = 0;
- uint8_t m_shot_arrive = 0;
- uint16_t m_beam_state = 0;
- uint16_t m_old_beam_state = 0;
- uint16_t m_beam_states_per_frame = 0;
- uint8_t m_palette_bank = 0;
-};
-
-#endif // MAME_INCLUDES_STACTICS_H
diff --git a/src/mame/sega/stactics_v.cpp b/src/mame/sega/stactics_v.cpp
deleted file mode 100644
index 2f055e744d7..00000000000
--- a/src/mame/sega/stactics_v.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Frank Palazzolo
-/****************************************************************************
-
- Sega "Space Tactics" Driver
-
- Frank Palazzolo (palazzol@home.com)
-
-
-The Video system used in Space Tactics is unusual.
-Here are my notes on how the video system works:
-
-There are 4, 4K pages of Video RAM. (B,D,E & F)
-
-The first 1K of each VRAM page contains the following:
-0 0 V V V V V H H H H H offset value for each 8x8 bitmap
- (v-tile) (h-tile)
-
-The offset values are used to generate an access into the
-last 2K of the VRAM page:
-1 D D D D D D D D V V V here we find 8x8 character data
- (offset) (line)
-
-In addition, in Page B, the upper nibble of the offset is
-also used to select the color palette for the tile.
-
-Page B, D, E, and F all work similarly, except that pages
-D, E, and F can be offset from Page B by a given
-number of scanlines, based on the contents of the offset
-RAM
-
-The offset RAM is addressed in this format:
-1 0 0 0 P P P V V V V V V V V V
- (Page) (scanline)
-Page 4=D, 5=E, 6=F
-
-Page D, E, and F are drawn offset from the top of the screen,
-starting on the first scanline which contains a 1 in the
-appropriate memory location
-
----
-
-The composited monitor image is seen in a mirror. It appears
-to move when the player moves the handle, due to motors which
-tilt the mirror up and down, and the monitor left and right.
-
----
-
-***************************************************************************/
-
-#include "emu.h"
-#include "stactics.h"
-#include "screen.h"
-
-
-
-/*************************************
- *
- * Palette
- *
- *************************************/
-
-void stactics_state::stactics_palette(palette_device &palette) const
-{
- uint8_t const *const color_prom = memregion("proms")->base();
-
- for (int i = 0; i < 0x400; i++)
- {
- int const bit0 = BIT(color_prom[i], 0);
- int const bit1 = BIT(color_prom[i], 1);
- int const bit2 = BIT(color_prom[i], 2);
- int const bit3 = BIT(color_prom[i], 3);
-
- // red component
- int const r = 0xff * bit0;
-
- // green component
- int const g = 0xff * bit1 - 0xcc * bit3;
-
- // blue component
- int const b = 0xff * bit2;
-
- palette.set_pen_color(i, rgb_t(r, g, b));
- }
-}
-
-
-WRITE_LINE_MEMBER(stactics_state::palette_bank_w)
-{
- m_palette_bank = m_outlatch->q6_r() | (m_outlatch->q7_r() << 1);
-}
-
-
-
-/*************************************
- *
- * Scrolling
- *
- *************************************/
-
-void stactics_state::scroll_ram_w(offs_t offset, uint8_t data)
-{
- if (data & 0x01)
- {
- switch (offset >> 8)
- {
- case 4: m_y_scroll_d = offset & 0xff; break;
- case 5: m_y_scroll_e = offset & 0xff; break;
- case 6: m_y_scroll_f = offset & 0xff; break;
- }
- }
-}
-
-
-
-/*************************************
- *
- * Frane counter
- *
- *************************************/
-
-READ_LINE_MEMBER(stactics_state::frame_count_d3_r)
-{
- return (m_frame_count >> 3) & 0x01;
-}
-
-
-
-/*************************************
- *
- * Beam handling
- *
- *************************************/
-
-void stactics_state::speed_latch_w(uint8_t data)
-{
- /* This writes to a shift register which is clocked by */
- /* a 555 oscillator. This value determines the speed of */
- /* the LED fire beams as follows: */
-
- /* 555_freq / bits_in_SR * edges_in_SR / states_in_PR67 / frame_rate */
- /* = num_led_states_per_frame */
- /* 36439 / 8 * x / 32 / 60 ~= 19/8*x */
-
- /* Here, we will count the number of rising edges in the shift register */
-
- int i;
- int num_rising_edges = 0;
-
- for(i=0;i<8;i++)
- {
- if ( (((data>>i)&0x01) == 1) && (((data>>((i+1)%8))&0x01) == 0))
- num_rising_edges++;
- }
-
- m_beam_states_per_frame = num_rising_edges*19/8;
-}
-
-
-void stactics_state::shot_trigger_w(uint8_t data)
-{
- m_shot_standby = 0;
-}
-
-
-void stactics_state::shot_flag_clear_w(uint8_t data)
-{
- m_shot_arrive = 0;
-}
-
-
-READ_LINE_MEMBER(stactics_state::shot_standby_r)
-{
- return m_shot_standby;
-}
-
-
-READ_LINE_MEMBER(stactics_state::not_shot_arrive_r)
-{
- return !m_shot_arrive;
-}
-
-
-void stactics_state::update_beam()
-{
- /* first, update the firebeam state */
- m_old_beam_state = m_beam_state;
- if (m_shot_standby == 0)
- m_beam_state = m_beam_state + m_beam_states_per_frame;
-
- /* These are thresholds for the two shots from the LED fire ROM */
- /* (Note: There are two more for sound triggers, */
- /* whenever that gets implemented) */
- if ((m_old_beam_state < 0x8b) & (m_beam_state >= 0x8b))
- m_shot_arrive = 1;
-
- if ((m_old_beam_state < 0xca) & (m_beam_state >= 0xca))
- m_shot_arrive = 1;
-
- if (m_beam_state >= 0x100)
- {
- m_beam_state = 0;
- m_shot_standby = 1;
- }
-}
-
-
-
-/*************************************
- *
- * Video drawing
- *
- *************************************/
-
-inline int stactics_state::get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll)
-{
- /* compute effective row */
- y = y - y_scroll;
-
- /* get the character code at the given pixel */
- uint8_t code = videoram[((y >> 3) << 5) | (x >> 3)];
-
- /* get the gfx byte */
- uint8_t gfx = videoram[0x800 | (code << 3) | (y & 0x07)];
-
- /* return the appropriate pixel within the byte */
- return (gfx >> (~x & 0x07)) & 0x01;
-}
-
-
-void stactics_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- bitmap.fill(0, cliprect);
-
- /* for every row */
- for (int y = 0; y < 0x100; y++)
- {
- /* for every pixel on the row */
- for (int x = 0; x < 0x100; x++)
- {
- /* get the pixels for the four planes */
- int pixel_b = get_pixel_on_plane(m_videoram_b, y, x, 0);
- int pixel_d = get_pixel_on_plane(m_videoram_d, y, x, m_y_scroll_d);
- int pixel_e = get_pixel_on_plane(m_videoram_e, y, x, m_y_scroll_e);
- int pixel_f = get_pixel_on_plane(m_videoram_f, y, x, m_y_scroll_f);
-
- /* get the color for this pixel */
- uint8_t color = m_videoram_b[((y >> 3) << 5) | (x >> 3)] >> 4;
-
- /* assemble the pen index */
- int pen = color |
- (pixel_b << 4) |
- (pixel_f << 5) |
- (pixel_e << 6) |
- (pixel_d << 7) |
- (m_palette_bank << 8);
-
- /* compute the effective pixel coordinate after adjusting for the
- mirror movement - this is mechanical on the real machine */
- int sy = y + m_vert_pos;
- int sx = x - m_horiz_pos;
-
- /* plot if visible */
- if ((sy >= 0) && (sy < 0x100) && (sx >= 0) && (sx < 0x100))
- bitmap.pix(sy, sx) = pen;
- }
- }
-}
-
-
-
-/*************************************
- *
- * Non-video artwork
- *
- *************************************/
-
-/* from 7448 datasheet */
-static constexpr int to_7seg[0x10] =
-{
- 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07,
- 0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0x00
-};
-
-
-template <unsigned N> void stactics_state::set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index)
-{
- /* decode the data */
- int const data = to_7seg[~m_display_buffer[offset] & 0x0f];
-
- /* set the 4 LEDs */
- outputs[base_index + 0] = BIT(data, 2);
- outputs[base_index + 1] = BIT(data, 6);
- outputs[base_index + 2] = BIT(data, 5);
- outputs[base_index + 3] = BIT(data, 4);
-}
-
-
-WRITE_LINE_MEMBER(stactics_state::barrier_lamp_w)
-{
- // this needs to flash on/off, not implemented
- m_barrier_lamp = state;
-}
-
-
-WRITE_LINE_MEMBER(stactics_state::start_lamp_w)
-{
- m_start_lamp = state;
-}
-
-
-void stactics_state::update_artwork()
-{
- uint8_t *beam_region = memregion("user1")->base();
-
- /* laser beam - loop for each LED */
- for (int i = 0; i < 0x40; i++)
- {
- offs_t const beam_data_offs = ((i & 0x08) << 7) | ((i & 0x30) << 4) | m_beam_state;
- uint8_t const beam_data = beam_region[beam_data_offs];
- int const on = BIT(beam_data, i & 0x07);
-
- m_beam_leds_left[i] = on;
- m_beam_leds_right[i] = on;
- }
-
- /* sight LED */
- m_sight_led = m_motor_on;
-
- /* score display */
- for (int i = 0x01; i < 0x07; i++)
- m_score_digits[i - 1] = to_7seg[~m_display_buffer[i] & 0x0f];
-
- /* credits indicator */
- set_indicator_leds(0x07, m_credit_leds, 0x00);
- set_indicator_leds(0x08, m_credit_leds, 0x04);
-
- /* barriers indicator */
- set_indicator_leds(0x09, m_barrier_leds, 0x00);
- set_indicator_leds(0x0a, m_barrier_leds, 0x04);
- set_indicator_leds(0x0b, m_barrier_leds, 0x08);
-
- /* rounds indicator */
- set_indicator_leds(0x0c, m_round_leds, 0x00);
- set_indicator_leds(0x0d, m_round_leds, 0x04);
- set_indicator_leds(0x0e, m_round_leds, 0x08);
- set_indicator_leds(0x0f, m_round_leds, 0x0c);
-}
-
-
-
-/*************************************
- *
- * Start
- *
- *************************************/
-
-void stactics_state::video_start()
-{
- m_base_lamps.resolve();
- m_beam_leds_left.resolve();
- m_beam_leds_right.resolve();
- m_score_digits.resolve();
- m_credit_leds.resolve();
- m_barrier_leds.resolve();
- m_round_leds.resolve();
- m_barrier_lamp.resolve();
- m_start_lamp.resolve();
- m_sight_led.resolve();
-
- m_y_scroll_d = 0;
- m_y_scroll_e = 0;
- m_y_scroll_f = 0;
-
- m_frame_count = 0;
- m_shot_standby = 1;
- m_shot_arrive = 0;
- m_beam_state = 0;
- m_old_beam_state = 0;
-
- m_palette_bank = 0;
-
- save_item(NAME(m_y_scroll_d));
- save_item(NAME(m_y_scroll_e));
- save_item(NAME(m_y_scroll_f));
- save_item(NAME(m_frame_count));
- save_item(NAME(m_shot_standby));
- save_item(NAME(m_shot_arrive));
- save_item(NAME(m_beam_state));
- save_item(NAME(m_old_beam_state));
- save_item(NAME(m_beam_states_per_frame));
- save_item(NAME(m_palette_bank));
-}
-
-
-
-/*************************************
- *
- * Update
- *
- *************************************/
-
-uint32_t stactics_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- update_beam();
- draw_background(bitmap, cliprect);
- update_artwork();
-
- m_frame_count = (m_frame_count + 1) & 0x0f;
-
- return 0;
-}
-
-
-
-/*************************************
- *
- * Machine driver
- *
- *************************************/
-
-void stactics_state::stactics_video(machine_config &config)
-{
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_video_attributes(VIDEO_ALWAYS_UPDATE);
- screen.set_raw(15.46848_MHz_XTAL / 3, 328, 0, 256, 262, 0, 232);
- screen.set_screen_update(FUNC(stactics_state::screen_update));
- screen.set_palette("palette");
-
- PALETTE(config, "palette", FUNC(stactics_state::stactics_palette), 0x400);
-}
diff --git a/src/mame/sega/suprloco.cpp b/src/mame/sega/suprloco.cpp
index 162409dbc67..403341d8b40 100644
--- a/src/mame/sega/suprloco.cpp
+++ b/src/mame/sega/suprloco.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
+// copyright-holders: Zsolt Vasvari
+
/******************************************************************************
Super Locomotive
@@ -22,21 +23,324 @@ Sega PCB 834-5137
******************************************************************************/
#include "emu.h"
-#include "suprloco.h"
-#include "machine/segacrpt_device.h"
#include "cpu/z80/z80.h"
#include "machine/i8255.h"
+#include "machine/segacrpt_device.h"
#include "sound/sn76496.h"
+#include "emupal.h"
#include "screen.h"
#include "speaker.h"
+#include "tilemap.h"
+
+
+// configurable logging
+#define LOG_CTRLBIT4 (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL | LOG_CTRLBIT4)
+
+#include "logmacro.h"
+
+#define LOGCTRLBIT4(...) LOGMASKED(LOG_CTRLBIT4, __VA_ARGS__)
+
+
+namespace {
+
+class suprloco_state : public driver_device
+{
+public:
+ suprloco_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_audiocpu(*this, "audiocpu"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_spriteram(*this, "spriteram"),
+ m_videoram(*this, "videoram"),
+ m_scrollram(*this, "scrollram"),
+ m_decrypted_opcodes(*this, "decrypted_opcodes"),
+ m_sprites_rom(*this, "sprites")
+ { }
+
+ void suprloco(machine_config &config);
+
+ void init_suprloco();
+
+protected:
+ virtual void video_start() override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_audiocpu;
+ required_device<gfxdecode_device> m_gfxdecode;
+
+ required_shared_ptr<uint8_t> m_spriteram;
+ required_shared_ptr<uint8_t> m_videoram;
+ required_shared_ptr<uint8_t> m_scrollram;
+ required_shared_ptr<uint8_t> m_decrypted_opcodes;
+ required_region_ptr<uint8_t> m_sprites_rom;
+
+ tilemap_t *m_bg_tilemap = nullptr;
+ uint8_t m_control = 0;
+
+ enum
+ {
+ SPR_Y_TOP = 0,
+ SPR_Y_BOTTOM,
+ SPR_X,
+ SPR_COL,
+ SPR_SKIP_LO,
+ SPR_SKIP_HI,
+ SPR_GFXOFS_LO,
+ SPR_GFXOFS_HI
+ };
+
+ void videoram_w(offs_t offset, uint8_t data);
+ void scrollram_w(offs_t offset, uint8_t data);
+ void control_w(uint8_t data);
+
+ TILE_GET_INFO_MEMBER(get_tile_info);
+
+ void palette(palette_device &palette) const;
+
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ inline void draw_pixel(bitmap_ind16 &bitmap, const rectangle &cliprect, int x, int y, int color, int flip);
+ void draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int spr_number);
+ void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void decrypted_opcodes_map(address_map &map);
+ void main_map(address_map &map);
+ void sound_map(address_map &map);
+};
+
+
+// video
+
+/***************************************************************************
+
+ Convert the color PROMs into a more useable format.
+
+ I'm not sure about the resistor values, I'm using the Galaxian ones.
+
+***************************************************************************/
+void suprloco_state::palette(palette_device &palette) const
+{
+ const uint8_t *color_prom = memregion("proms")->base();
+
+ for (int i = 0; i < 512; i++)
+ {
+ int bit0, bit1, bit2;
+
+ // red component
+ bit0 = BIT(color_prom[i], 0);
+ bit1 = BIT(color_prom[i], 1);
+ bit2 = BIT(color_prom[i], 2);
+ int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+ // green component
+ bit0 = BIT(color_prom[i], 3);
+ bit1 = BIT(color_prom[i], 4);
+ bit2 = BIT(color_prom[i], 5);
+ int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+ // blue component
+ bit0 = 0;
+ bit1 = BIT(color_prom[i], 6);
+ bit2 = BIT(color_prom[i], 7);
+ int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
+
+ palette.set_pen_color(i, rgb_t(r, g, b));
+
+ // hack: generate a second bank of sprite palette with red changed to purple
+ if (i >= 256)
+ palette.set_pen_color(i + 256, rgb_t(r, g, ((i & 0x0f) == 0x09) ? 0xff : b));
+ }
+}
+
+
+
+/***************************************************************************
+
+ Callbacks for the TileMap code
+
+***************************************************************************/
+
+TILE_GET_INFO_MEMBER(suprloco_state::get_tile_info)
+{
+ uint8_t const attr = m_videoram[2 * tile_index + 1];
+ tileinfo.set(0,
+ m_videoram[2 * tile_index] | ((attr & 0x03) << 8),
+ (attr & 0x1c) >> 2,
+ 0);
+ tileinfo.category = (attr & 0x20) >> 5;
+}
+
+
+
+/***************************************************************************
+
+ Start the video hardware emulation.
+
+***************************************************************************/
+
+void suprloco_state::video_start()
+{
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(suprloco_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
+
+ m_bg_tilemap->set_scroll_rows(32);
+
+ save_item(NAME(m_control));
+}
+
+
+
+/***************************************************************************
+
+ Memory handlers
+
+***************************************************************************/
+
+void suprloco_state::videoram_w(offs_t offset, uint8_t data)
+{
+ m_videoram[offset] = data;
+ m_bg_tilemap->mark_tile_dirty(offset / 2);
+}
+void suprloco_state::scrollram_w(offs_t offset, uint8_t data)
+{
+ int const adj = flip_screen() ? -8 : 8;
+
+ m_scrollram[offset] = data;
+ m_bg_tilemap->set_scrollx(offset, data - adj);
+}
+
+void suprloco_state::control_w(uint8_t data)
+{
+ /* There is probably a palette select in here
+
+ Bit 0 - coin counter A
+ Bit 1 - coin counter B (only used if coinage differs from A)
+ Bit 2-3 - probably unused
+ Bit 4 - ???
+ Bit 5 - pulsated when loco turns "super"
+ Bit 6 - probably unused
+ Bit 7 - flip screen */
+
+ if ((m_control & 0x10) != (data & 0x10))
+ LOGCTRLBIT4("Bit 4 = %d\n", (data >> 4) & 1);
+
+ machine().bookkeeping().coin_counter_w(0, data & 0x01);
+ machine().bookkeeping().coin_counter_w(1, data & 0x02);
+
+ flip_screen_set(data & 0x80);
+
+ m_control = data;
+}
+
+
+
+inline void suprloco_state::draw_pixel(bitmap_ind16 &bitmap, const rectangle &cliprect, int x, int y, int color, int flip)
+{
+ if (flip)
+ {
+ x = bitmap.width() - x - 1;
+ y = bitmap.height() - y - 1;
+ }
+
+ if (cliprect.contains(x, y))
+ bitmap.pix(y, x) = color;
+}
+
+
+void suprloco_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int spr_number)
+{
+ int const flip = flip_screen();
+ int adjy, dy;
+
+ const uint8_t *spr_reg = m_spriteram + 0x10 * spr_number;
+
+ int src = spr_reg[SPR_GFXOFS_LO] + (spr_reg[SPR_GFXOFS_HI] << 8);
+ short const skip = spr_reg[SPR_SKIP_LO] + (spr_reg[SPR_SKIP_HI] << 8); // bytes to skip before drawing each row (can be negative)
+
+ int const height = spr_reg[SPR_Y_BOTTOM] - spr_reg[SPR_Y_TOP];
+ pen_t const pen_base = 0x100 + 0x10 * (spr_reg[SPR_COL] & 0x03) + ((m_control & 0x20) ? 0x100 : 0);
+ int const sx = spr_reg[SPR_X];
+ int const sy = spr_reg[SPR_Y_TOP] + 1;
+
+ if (!flip)
+ {
+ adjy = sy;
+ dy = 1;
+ }
+ else
+ {
+ adjy = sy + height - 1; // some of the sprites are still off by a pixel
+ dy = -1;
+ }
+
+ for (int row = 0; row < height; row++, adjy += dy)
+ {
+ int color1, color2;
+ uint8_t data;
+
+ src += skip;
+
+ int col = 0;
+
+ // get pointer to packed sprite data
+ const uint8_t *gfx = &(m_sprites_rom[src & 0x7fff]);
+ int const flipx = src & 0x8000; // flip x
+
+ while (1)
+ {
+ if (flipx) // flip x
+ {
+ data = *gfx--;
+ color1 = data & 0x0f;
+ color2 = data >> 4;
+ }
+ else
+ {
+ data = *gfx++;
+ color1 = data >> 4;
+ color2 = data & 0x0f;
+ }
+
+ if (color1 == 15) break;
+ if (color1)
+ draw_pixel(bitmap, cliprect,sx + col, adjy, pen_base + color1, flip);
+
+ if (color2 == 15) break;
+ if (color2)
+ draw_pixel(bitmap, cliprect,sx + col + 1, adjy, pen_base + color2, flip);
+
+ col += 2;
+ }
+ }
+}
+
+void suprloco_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ for (int spr_number = 0; spr_number < (m_spriteram.bytes() >> 4); spr_number++)
+ {
+ const uint8_t *spr_reg = m_spriteram + 0x10 * spr_number;
+ if (spr_reg[SPR_X] != 0xff)
+ draw_sprite(bitmap, cliprect, spr_number);
+ }
+}
+
+uint32_t suprloco_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ draw_sprites(bitmap, cliprect);
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 1, 0);
+ return 0;
+}
+
+
+// machine
void suprloco_state::main_map(address_map &map)
{
map(0x0000, 0xbfff).rom();
- map(0xc000, 0xc1ff).ram().share("spriteram");
+ map(0xc000, 0xc1ff).ram().share(m_spriteram);
map(0xc200, 0xc7ff).nopw();
map(0xc800, 0xc800).portr("SYSTEM");
map(0xd000, 0xd000).portr("P1");
@@ -44,15 +348,15 @@ void suprloco_state::main_map(address_map &map)
map(0xe000, 0xe000).portr("DSW1");
map(0xe001, 0xe001).portr("DSW2");
map(0xe800, 0xe803).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write));
- map(0xf000, 0xf6ff).ram().w(FUNC(suprloco_state::videoram_w)).share("videoram");
- map(0xf700, 0xf7df).ram(); /* unused */
- map(0xf7e0, 0xf7ff).ram().w(FUNC(suprloco_state::scrollram_w)).share("scrollram");
+ map(0xf000, 0xf6ff).ram().w(FUNC(suprloco_state::videoram_w)).share(m_videoram);
+ map(0xf700, 0xf7df).ram(); // unused
+ map(0xf7e0, 0xf7ff).ram().w(FUNC(suprloco_state::scrollram_w)).share(m_scrollram);
map(0xf800, 0xffff).ram();
}
void suprloco_state::decrypted_opcodes_map(address_map &map)
{
- map(0x0000, 0x7fff).rom().share("decrypted_opcodes");
+ map(0x0000, 0x7fff).rom().share(m_decrypted_opcodes);
map(0x8000, 0xbfff).rom().region("maincpu", 0x8000);
}
@@ -149,10 +453,10 @@ INPUT_PORTS_END
static const gfx_layout charlayout =
{
- 8,8, /* 8 by 8 */
- 1024, /* 1024 characters */
- 4, /* 4 bits per pixel */
- { 0, 1024*8*8, 2*1024*8*8, 3*1024*8*8 }, /* plane */
+ 8,8, // 8 by 8
+ 1024, // 1024 characters
+ 4, // 4 bits per pixel
+ { 0, 1024*8*8, 2*1024*8*8, 3*1024*8*8 }, // plane
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8
@@ -160,23 +464,23 @@ static const gfx_layout charlayout =
static GFXDECODE_START( gfx_suprloco )
- /* sprites use colors 256-511 + 512-767 */
- GFXDECODE_ENTRY( "gfx1", 0x6000, charlayout, 0, 16 )
+ // sprites use colors 256-511 + 512-767
+ GFXDECODE_ENTRY( "chars", 0x6000, charlayout, 0, 16 )
GFXDECODE_END
void suprloco_state::suprloco(machine_config &config)
{
- /* basic machine hardware */
- sega_315_5015_device &maincpu(SEGA_315_5015(config, m_maincpu, 4000000)); /* 4 MHz (?) */
+ // basic machine hardware
+ sega_315_5015_device &maincpu(SEGA_315_5015(config, m_maincpu, 4'000'000)); // 4 MHz (?)
maincpu.set_addrmap(AS_PROGRAM, &suprloco_state::main_map);
maincpu.set_addrmap(AS_OPCODES, &suprloco_state::decrypted_opcodes_map);
maincpu.set_vblank_int("screen", FUNC(suprloco_state::irq0_line_hold));
maincpu.set_decrypted_tag(":decrypted_opcodes");
- Z80(config, m_audiocpu, 4000000);
+ Z80(config, m_audiocpu, 4'000'000);
m_audiocpu->set_addrmap(AS_PROGRAM, &suprloco_state::sound_map);
- m_audiocpu->set_periodic_int(FUNC(suprloco_state::irq0_line_hold), attotime::from_hz(4*60)); /* NMIs are caused by the main CPU */
+ m_audiocpu->set_periodic_int(FUNC(suprloco_state::irq0_line_hold), attotime::from_hz(4 * 60)); // NMIs are caused by the main CPU
i8255_device &ppi(I8255A(config, "ppi"));
ppi.out_pb_callback().set(FUNC(suprloco_state::control_w));
@@ -184,7 +488,7 @@ void suprloco_state::suprloco(machine_config &config)
ppi.out_pc_callback().set_output("lamp0").bit(0).invert(); // set by 8255 bit mode when no credits inserted
ppi.out_pc_callback().append_inputline(m_audiocpu, INPUT_LINE_NMI).bit(7).invert();
- /* 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(5000));
@@ -194,14 +498,14 @@ void suprloco_state::suprloco(machine_config &config)
screen.set_palette("palette");
GFXDECODE(config, m_gfxdecode, "palette", gfx_suprloco);
- PALETTE(config, "palette", FUNC(suprloco_state::suprloco_palette), 512+256);
+ PALETTE(config, "palette", FUNC(suprloco_state::palette), 512 + 256);
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "mono").front_center();
- SN76496(config, "sn1", 4000000).add_route(ALL_OUTPUTS, "mono", 1.0);
+ SN76496(config, "sn1", 4'000'000).add_route(ALL_OUTPUTS, "mono", 1.0);
- SN76496(config, "sn2", 2000000).add_route(ALL_OUTPUTS, "mono", 1.0);
+ SN76496(config, "sn2", 2'000'000).add_route(ALL_OUTPUTS, "mono", 1.0);
}
@@ -213,66 +517,66 @@ void suprloco_state::suprloco(machine_config &config)
ROM_START( suprloco )
ROM_REGION( 0xc000, "maincpu", 0 )
- ROM_LOAD( "epr-5226a.37", 0x0000, 0x4000, CRC(33b02368) SHA1(c6e3116ad4b52bcc3174de5770f7a7ce024790d5) ) /* encrypted */
- ROM_LOAD( "epr-5227a.15", 0x4000, 0x4000, CRC(a5e67f50) SHA1(1dd52e4cf00ce414fe1db8259c9976cdc23513b4) ) /* encrypted */
+ ROM_LOAD( "epr-5226a.37", 0x0000, 0x4000, CRC(33b02368) SHA1(c6e3116ad4b52bcc3174de5770f7a7ce024790d5) ) // encrypted
+ ROM_LOAD( "epr-5227a.15", 0x4000, 0x4000, CRC(a5e67f50) SHA1(1dd52e4cf00ce414fe1db8259c9976cdc23513b4) ) // encrypted
ROM_LOAD( "epr-5228.28", 0x8000, 0x4000, CRC(a597828a) SHA1(61004d112591fd2d752c39df71c1304d9308daae) )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "epr-5222.64", 0x0000, 0x2000, CRC(0aa57207) SHA1(b29b533505cb5b47c90534f2f610baeb7265d030) )
- ROM_REGION( 0xe000, "gfx1", 0 )
+ ROM_REGION( 0xe000, "chars", 0 )
ROM_LOAD( "epr-5225.63", 0x0000, 0x2000, CRC(e571fe81) SHA1(ac2b5914a445b89b7456b2c4290e4630b525f05d) )
ROM_LOAD( "epr-5224.62", 0x2000, 0x2000, CRC(6130f93c) SHA1(ae0657f46c10e75eec994e75359a89b5d61baf68) )
ROM_LOAD( "epr-5223.61", 0x4000, 0x2000, CRC(3b03004e) SHA1(805b51cb14d3ace97f2e0f306db28921b2f5e322) )
- /* 0x6000- 0xe000 will be created by init_suprloco */
+ // 0x6000 - 0xe000 will be created by init_suprloco
- ROM_REGION( 0x8000, "gfx2", 0 ) /* 32k for sprites data used at runtime */
+ ROM_REGION( 0x8000, "sprites", 0 ) // used at runtime
ROM_LOAD( "epr-5229.55", 0x0000, 0x4000, CRC(ee2d3ed3) SHA1(593f3cd5c4e7f20b5e31e6bac8864774442e4b75) )
ROM_LOAD( "epr-5230.56", 0x4000, 0x2000, CRC(f04a4b50) SHA1(80363f0c508fb2a755bf684f9a6862c1e7285495) )
- /* 0x6000 empty */
+ // 0x6000 empty
ROM_REGION( 0x0620, "proms", 0 )
- ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) /* color PROM */
+ ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) // color PROM
ROM_CONTINUE( 0x0000, 0x0080 )
ROM_CONTINUE( 0x0180, 0x0080 )
ROM_CONTINUE( 0x0080, 0x0080 )
- ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) /* 3bpp to 4bpp table */
- ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) /* unknown */
+ ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) // 3bpp to 4bpp table
+ ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) // unknown
ROM_END
ROM_START( suprlocoo )
ROM_REGION( 0xc000, "maincpu", 0 )
- ROM_LOAD( "epr-5226.37", 0x0000, 0x4000, CRC(57f514dd) SHA1(707800b90a22547a56b01d1e11775e9ee5555d23) ) /* encrypted */
- ROM_LOAD( "epr-5227.15", 0x4000, 0x4000, CRC(5a1d2fb0) SHA1(fdb9416e5530718245fd597073a63feddb233c3c) ) /* encrypted */
+ ROM_LOAD( "epr-5226.37", 0x0000, 0x4000, CRC(57f514dd) SHA1(707800b90a22547a56b01d1e11775e9ee5555d23) ) // encrypted
+ ROM_LOAD( "epr-5227.15", 0x4000, 0x4000, CRC(5a1d2fb0) SHA1(fdb9416e5530718245fd597073a63feddb233c3c) ) // encrypted
ROM_LOAD( "epr-5228.28", 0x8000, 0x4000, CRC(a597828a) SHA1(61004d112591fd2d752c39df71c1304d9308daae) )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "epr-5222.64", 0x0000, 0x2000, CRC(0aa57207) SHA1(b29b533505cb5b47c90534f2f610baeb7265d030) )
- ROM_REGION( 0xe000, "gfx1", 0 )
+ ROM_REGION( 0xe000, "chars", 0 )
ROM_LOAD( "epr-5225.63", 0x0000, 0x2000, CRC(e571fe81) SHA1(ac2b5914a445b89b7456b2c4290e4630b525f05d) )
ROM_LOAD( "epr-5224.62", 0x2000, 0x2000, CRC(6130f93c) SHA1(ae0657f46c10e75eec994e75359a89b5d61baf68) )
ROM_LOAD( "epr-5223.61", 0x4000, 0x2000, CRC(3b03004e) SHA1(805b51cb14d3ace97f2e0f306db28921b2f5e322) )
- /* 0x6000- 0xe000 will be created by init_suprloco */
+ // 0x6000 - 0xe000 will be created by init_suprloco
- ROM_REGION( 0x8000, "gfx2", 0 ) /* 32k for sprites data used at runtime */
+ ROM_REGION( 0x8000, "sprites", 0 ) // used at runtime
ROM_LOAD( "epr-5229.55", 0x0000, 0x4000, CRC(ee2d3ed3) SHA1(593f3cd5c4e7f20b5e31e6bac8864774442e4b75) )
ROM_LOAD( "epr-5230.56", 0x4000, 0x2000, CRC(f04a4b50) SHA1(80363f0c508fb2a755bf684f9a6862c1e7285495) )
- /* 0x6000 empty */
+ // 0x6000 empty
ROM_REGION( 0x0620, "proms", 0 )
- ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) /* color PROM */
+ ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) // color PROM
ROM_CONTINUE( 0x0000, 0x0080 )
ROM_CONTINUE( 0x0180, 0x0080 )
ROM_CONTINUE( 0x0080, 0x0080 )
- ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) /* 3bpp to 4bpp table */
- ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) /* unknown */
+ ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) // 3bpp to 4bpp table
+ ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) // unknown
ROM_END
void suprloco_state::init_suprloco()
{
- /* convert graphics to 4bpp from 3bpp */
- uint8_t *source = memregion("gfx1")->base();
+ // convert graphics to 4bpp from 3bpp
+ uint8_t *source = memregion("chars")->base();
uint8_t *dest = source + 0x6000;
uint8_t *lookup = memregion("proms")->base() + 0x0200;
@@ -300,5 +604,8 @@ void suprloco_state::init_suprloco()
}
+} // anonymous namespace
+
+
GAME( 1982, suprloco, 0, suprloco, suprloco, suprloco_state, init_suprloco, ROT0, "Sega", "Super Locomotive (Rev.A)", MACHINE_SUPPORTS_SAVE )
GAME( 1982, suprlocoo, suprloco, suprloco, suprloco, suprloco_state, init_suprloco, ROT0, "Sega", "Super Locomotive", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/sega/suprloco.h b/src/mame/sega/suprloco.h
deleted file mode 100644
index 9229327f0f0..00000000000
--- a/src/mame/sega/suprloco.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
-#ifndef MAME_INCLUDES_SUPRLOCO_H
-#define MAME_INCLUDES_SUPRLOCO_H
-
-#pragma once
-
-#include "emupal.h"
-#include "tilemap.h"
-
-class suprloco_state : public driver_device
-{
-public:
- suprloco_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_audiocpu(*this, "audiocpu"),
- m_gfxdecode(*this, "gfxdecode"),
- m_spriteram(*this, "spriteram"),
- m_videoram(*this, "videoram"),
- m_scrollram(*this, "scrollram"),
- m_decrypted_opcodes(*this, "decrypted_opcodes")
- { }
-
- void suprloco(machine_config &config);
-
- void init_suprloco();
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device<cpu_device> m_audiocpu;
- required_device<gfxdecode_device> m_gfxdecode;
-
- required_shared_ptr<uint8_t> m_spriteram;
- required_shared_ptr<uint8_t> m_videoram;
- required_shared_ptr<uint8_t> m_scrollram;
- required_shared_ptr<uint8_t> m_decrypted_opcodes;
-
- tilemap_t *m_bg_tilemap = nullptr;
- int m_control = 0;
-
- void videoram_w(offs_t offset, uint8_t data);
- void scrollram_w(offs_t offset, uint8_t data);
- void control_w(uint8_t data);
-
- TILE_GET_INFO_MEMBER(get_tile_info);
-
- virtual void video_start() override;
- void suprloco_palette(palette_device &palette) const;
-
- uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- inline void draw_pixel(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int color,int flip);
- void draw_sprite(bitmap_ind16 &bitmap,const rectangle &cliprect,int spr_number);
- void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
- void decrypted_opcodes_map(address_map &map);
- void main_map(address_map &map);
- void sound_map(address_map &map);
-};
-
-#endif // MAME_INCLUDES_SUPRLOCO_H
diff --git a/src/mame/sega/suprloco_v.cpp b/src/mame/sega/suprloco_v.cpp
deleted file mode 100644
index 550b4049a78..00000000000
--- a/src/mame/sega/suprloco_v.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
-/***************************************************************************
-
- suprloco.c
-
- Functions to emulate the video hardware of the machine.
-
-***************************************************************************/
-
-#include "emu.h"
-#include "suprloco.h"
-
-
-
-#define SPR_Y_TOP 0
-#define SPR_Y_BOTTOM 1
-#define SPR_X 2
-#define SPR_COL 3
-#define SPR_SKIP_LO 4
-#define SPR_SKIP_HI 5
-#define SPR_GFXOFS_LO 6
-#define SPR_GFXOFS_HI 7
-
-
-/***************************************************************************
-
- Convert the color PROMs into a more useable format.
-
- I'm not sure about the resistor values, I'm using the Galaxian ones.
-
-***************************************************************************/
-void suprloco_state::suprloco_palette(palette_device &palette) const
-{
- const uint8_t *color_prom = memregion("proms")->base();
-
- for (int i = 0; i < 512; i++)
- {
- int bit0, bit1, bit2;
-
- // red component
- bit0 = BIT(color_prom[i], 0);
- bit1 = BIT(color_prom[i], 1);
- bit2 = BIT(color_prom[i], 2);
- int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
- // green component
- bit0 = BIT(color_prom[i], 3);
- bit1 = BIT(color_prom[i], 4);
- bit2 = BIT(color_prom[i], 5);
- int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
- // blue component
- bit0 = 0;
- bit1 = BIT(color_prom[i], 6);
- bit2 = BIT(color_prom[i], 7);
- int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
-
- palette.set_pen_color(i, rgb_t(r, g, b));
-
- // hack: generate a second bank of sprite palette with red changed to purple
- if (i >= 256)
- palette.set_pen_color(i + 256, rgb_t(r, g, ((i & 0x0f) == 0x09) ? 0xff : b));
- }
-}
-
-
-
-/***************************************************************************
-
- Callbacks for the TileMap code
-
-***************************************************************************/
-
-TILE_GET_INFO_MEMBER(suprloco_state::get_tile_info)
-{
- uint8_t attr = m_videoram[2*tile_index+1];
- tileinfo.set(0,
- m_videoram[2*tile_index] | ((attr & 0x03) << 8),
- (attr & 0x1c) >> 2,
- 0);
- tileinfo.category = (attr & 0x20) >> 5;
-}
-
-
-
-/***************************************************************************
-
- Start the video hardware emulation.
-
-***************************************************************************/
-
-void suprloco_state::video_start()
-{
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(suprloco_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,32);
-
- m_bg_tilemap->set_scroll_rows(32);
-
- save_item(NAME(m_control));
-}
-
-
-
-/***************************************************************************
-
- Memory handlers
-
-***************************************************************************/
-
-void suprloco_state::videoram_w(offs_t offset, uint8_t data)
-{
- m_videoram[offset] = data;
- m_bg_tilemap->mark_tile_dirty(offset/2);
-}
-
-void suprloco_state::scrollram_w(offs_t offset, uint8_t data)
-{
- int adj = flip_screen() ? -8 : 8;
-
- m_scrollram[offset] = data;
- m_bg_tilemap->set_scrollx(offset, data - adj);
-}
-
-void suprloco_state::control_w(uint8_t data)
-{
- /* There is probably a palette select in here */
-
- /* Bit 0 - coin counter A */
- /* Bit 1 - coin counter B (only used if coinage differs from A) */
- /* Bit 2-3 - probably unused */
- /* Bit 4 - ??? */
- /* Bit 5 - pulsated when loco turns "super" */
- /* Bit 6 - probably unused */
- /* Bit 7 - flip screen */
-
- if ((m_control & 0x10) != (data & 0x10))
- {
- /*logerror("Bit 4 = %d\n", (data >> 4) & 1); */
- }
-
- machine().bookkeeping().coin_counter_w(0, data & 0x01);
- machine().bookkeeping().coin_counter_w(1, data & 0x02);
-
- flip_screen_set(data & 0x80);
-
- m_control = data;
-}
-
-
-
-inline void suprloco_state::draw_pixel(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int color,int flip)
-{
- if (flip)
- {
- x = bitmap.width() - x - 1;
- y = bitmap.height() - y - 1;
- }
-
- if (cliprect.contains(x, y))
- bitmap.pix(y, x) = color;
-}
-
-
-void suprloco_state::draw_sprite(bitmap_ind16 &bitmap,const rectangle &cliprect,int spr_number)
-{
- int flip = flip_screen();
- int sx,sy,col,row,height,src,adjy,dy;
- uint8_t *spr_reg;
- uint8_t *gfx2;
- pen_t pen_base;
- short skip; /* bytes to skip before drawing each row (can be negative) */
-
-
- spr_reg = m_spriteram + 0x10 * spr_number;
-
- src = spr_reg[SPR_GFXOFS_LO] + (spr_reg[SPR_GFXOFS_HI] << 8);
- skip = spr_reg[SPR_SKIP_LO] + (spr_reg[SPR_SKIP_HI] << 8);
-
- height = spr_reg[SPR_Y_BOTTOM] - spr_reg[SPR_Y_TOP];
- pen_base = 0x100 + 0x10 * (spr_reg[SPR_COL]&0x03) + ((m_control & 0x20)?0x100:0);
- sx = spr_reg[SPR_X];
- sy = spr_reg[SPR_Y_TOP] + 1;
-
- if (!flip_screen())
- {
- adjy = sy;
- dy = 1;
- }
- else
- {
- adjy = sy + height - 1; /* some of the sprites are still off by a pixel */
- dy = -1;
- }
-
- gfx2 = memregion("gfx2")->base();
- for (row = 0;row < height;row++,adjy+=dy)
- {
- int color1,color2,flipx;
- uint8_t data;
- uint8_t *gfx;
-
- src += skip;
-
- col = 0;
-
- /* get pointer to packed sprite data */
- gfx = &(gfx2[src & 0x7fff]);
- flipx = src & 0x8000; /* flip x */
-
- while (1)
- {
- if (flipx) /* flip x */
- {
- data = *gfx--;
- color1 = data & 0x0f;
- color2 = data >> 4;
- }
- else
- {
- data = *gfx++;
- color1 = data >> 4;
- color2 = data & 0x0f;
- }
-
- if (color1 == 15) break;
- if (color1)
- draw_pixel(bitmap,cliprect,sx+col, adjy,pen_base + color1, flip);
-
- if (color2 == 15) break;
- if (color2)
- draw_pixel(bitmap,cliprect,sx+col+1,adjy,pen_base + color2, flip);
-
- col += 2;
- }
- }
-}
-
-void suprloco_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- int spr_number;
- uint8_t *spr_reg;
-
-
- for (spr_number = 0;spr_number < (m_spriteram.bytes() >> 4);spr_number++)
- {
- spr_reg = m_spriteram + 0x10 * spr_number;
- if (spr_reg[SPR_X] != 0xff)
- draw_sprite(bitmap, cliprect, spr_number);
- }
-}
-
-uint32_t suprloco_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0);
- draw_sprites(bitmap,cliprect);
- m_bg_tilemap->draw(screen, bitmap, cliprect, 1,0);
- return 0;
-}