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" -void deniam_state::deniam16b_oki_rom_bank_w(u8 data) +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 m_maincpu; + required_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 m_gfxdecode; + required_device m_palette; + + // memory pointers + required_shared_ptr m_videoram; + required_shared_ptr m_textram; + required_shared_ptr 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 m_audiocpu; + required_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 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)); + deniam16c(config); - /* 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); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &deniamb_state::main_map); - 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? + 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); - /* sound hardware */ - SPEAKER(config, "mono").front_center(); + // sound hardware + 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.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 */ - m_oki->add_route(ALL_OUTPUTS, "mono", 1.0); + subdevice("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 m_videoram; - required_shared_ptr m_textram; - required_shared_ptr 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 m_maincpu; - optional_device m_audiocpu; // system 16c does not have sound CPU - required_device m_oki; - required_device m_gfxdecode; - required_device m_palette; - optional_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 "screen.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 m_maincpu; + required_device m_gfxdecode; + + // memory pointers + required_shared_ptr m_vram_fg; + required_shared_ptr 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 m_maincpu; - required_device m_gfxdecode; - - /* memory pointers */ - required_shared_ptr m_vram_fg; - required_shared_ptr 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,12 +44,531 @@ 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 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 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 void set_indicator_leds(unsigned offset, output_finder &outputs, int base_index); + void update_artwork(); + void move_motor(); + + void main_map(address_map &map); + + required_device m_maincpu; + required_device m_outlatch; + + required_shared_ptr m_display_buffer; + required_shared_ptr m_videoram_b; + required_shared_ptr m_videoram_d; + required_shared_ptr m_videoram_e; + required_shared_ptr m_videoram_f; + required_region_ptr 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 void stactics_state::set_indicator_leds(unsigned offset, output_finder &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 /************************************* * @@ -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 +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"); - /* audio hardware */ + PALETTE(config, "palette", FUNC(stactics_state::palette), 0x400); + + // 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_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_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 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 void set_indicator_leds(unsigned offset, output_finder &outputs, int base_index); - void update_artwork(); - void move_motor(); - - void stactics_video(machine_config &config); - void main_map(address_map &map); - - required_device m_maincpu; - required_device m_outlatch; - - required_shared_ptr m_display_buffer; - required_shared_ptr m_videoram_b; - required_shared_ptr m_videoram_d; - required_shared_ptr m_videoram_e; - required_shared_ptr 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 void stactics_state::set_indicator_leds(unsigned offset, output_finder &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 m_maincpu; + required_device m_audiocpu; + required_device m_gfxdecode; + + required_shared_ptr m_spriteram; + required_shared_ptr m_videoram; + required_shared_ptr m_scrollram; + required_shared_ptr m_decrypted_opcodes; + required_region_ptr 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 m_maincpu; - required_device m_audiocpu; - required_device m_gfxdecode; - - required_shared_ptr m_spriteram; - required_shared_ptr m_videoram; - required_shared_ptr m_scrollram; - required_shared_ptr 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; -}