From fa33564c68b90dda55f0f87de3d65c3e8e6602f9 Mon Sep 17 00:00:00 2001 From: Ivan Vangelista Date: Tue, 6 Sep 2022 07:16:15 +0200 Subject: jaleco/aeroboto.cpp, jaleco/exerion.cpp, jaleco/ginganin.cpp, jaleco/homerun.cpp, jaleco/momoko.cpp, jaleco/skyfox.cpp, omori/popper.cpp: consolidated drivers in single files, minor cleanups --- src/mame/jaleco/aeroboto.cpp | 413 +++++++++++++++++++++++++++----- src/mame/jaleco/aeroboto.h | 89 ------- src/mame/jaleco/aeroboto_v.cpp | 212 ----------------- src/mame/jaleco/exerion.cpp | 523 ++++++++++++++++++++++++++++++++++++++++- src/mame/jaleco/exerion.h | 103 -------- src/mame/jaleco/exerion_v.cpp | 403 ------------------------------- src/mame/jaleco/fcombat.cpp | 461 +++++++++++++++++++++++++++++------- src/mame/jaleco/fcombat.h | 102 -------- src/mame/jaleco/fcombat_v.cpp | 201 ---------------- src/mame/jaleco/ginganin.cpp | 482 +++++++++++++++++++++++++++++++------ src/mame/jaleco/ginganin.h | 81 ------- src/mame/jaleco/ginganin_v.cpp | 280 ---------------------- src/mame/jaleco/homerun.cpp | 302 ++++++++++++++++++++---- src/mame/jaleco/homerun.h | 79 ------- src/mame/jaleco/homerun_v.cpp | 157 ------------- src/mame/jaleco/momoko.cpp | 523 +++++++++++++++++++++++++++++++++++------ src/mame/jaleco/momoko.h | 89 ------- src/mame/jaleco/momoko_v.cpp | 289 ----------------------- src/mame/jaleco/skyfox.cpp | 394 ++++++++++++++++++++++++++----- src/mame/jaleco/skyfox.h | 63 ----- src/mame/jaleco/skyfox_v.cpp | 240 ------------------- src/mame/omori/battlex.cpp | 297 +++++++++++++++++++---- src/mame/omori/battlex.h | 62 ----- src/mame/omori/battlex_v.cpp | 122 ---------- src/mame/omori/popper.cpp | 8 +- 25 files changed, 2950 insertions(+), 3025 deletions(-) delete mode 100644 src/mame/jaleco/aeroboto.h delete mode 100644 src/mame/jaleco/aeroboto_v.cpp delete mode 100644 src/mame/jaleco/exerion.h delete mode 100644 src/mame/jaleco/exerion_v.cpp delete mode 100644 src/mame/jaleco/fcombat.h delete mode 100644 src/mame/jaleco/fcombat_v.cpp delete mode 100644 src/mame/jaleco/ginganin.h delete mode 100644 src/mame/jaleco/ginganin_v.cpp delete mode 100644 src/mame/jaleco/homerun.h delete mode 100644 src/mame/jaleco/homerun_v.cpp delete mode 100644 src/mame/jaleco/momoko.h delete mode 100644 src/mame/jaleco/momoko_v.cpp delete mode 100644 src/mame/jaleco/skyfox.h delete mode 100644 src/mame/jaleco/skyfox_v.cpp delete mode 100644 src/mame/omori/battlex.h delete mode 100644 src/mame/omori/battlex_v.cpp diff --git a/src/mame/jaleco/aeroboto.cpp b/src/mame/jaleco/aeroboto.cpp index 7c80398df2d..068dd16ebfa 100644 --- a/src/mame/jaleco/aeroboto.cpp +++ b/src/mame/jaleco/aeroboto.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Carlos A. Lozano, Uki +// copyright-holders: Carlos A. Lozano, Uki + /**************************************************************************** Formation Z / Aeroboto @@ -14,7 +15,7 @@ TODO: - The color of stars: at 1st title screen = neutral tints of blue and aqua (1 color only) at 2nd title screen and attract mode (purple surface) = light & dark aqua - This color will not be affected by scroll. Leftmost 8pixels are light, next + This color will not be affected by scroll. Leftmost 8 pixels are light, next 16 pixels are dark, the next 16 pixels are light, and so on. - Verify CPU clocks again. Main CPU is a HD68B09P, and next to it is a 8 MHz XTAL. @@ -26,23 +27,321 @@ Revisions: ****************************************************************************/ #include "emu.h" -#include "aeroboto.h" #include "cpu/m6809/m6809.h" #include "machine/gen_latch.h" #include "sound/ay8910.h" +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +// configurable logging +#define LOG_3004 (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_3004) + +#include "logmacro.h" + +#define LOG3004(...) LOGMASKED(LOG_3004, __VA_ARGS__) + + +namespace { + +class aeroboto_state : public driver_device +{ +public: + aeroboto_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_mainram(*this, "mainram"), + m_videoram(*this, "videoram"), + m_hscroll(*this, "hscroll"), + m_tilecolor(*this, "tilecolor"), + m_spriteram(*this, "spriteram"), + m_vscroll(*this, "vscroll"), + m_starx(*this, "starx"), + m_stary(*this, "stary"), + m_bgcolor(*this, "bgcolor"), + m_stars_rom(*this, "starfield_data"), + m_maincpu(*this, "maincpu"), + m_audiocpu(*this, "audiocpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_p(*this, "P%u", 1U) + { } + + void formatz(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + // memory pointers + required_shared_ptr m_mainram; + required_shared_ptr m_videoram; + required_shared_ptr m_hscroll; + required_shared_ptr m_tilecolor; + required_shared_ptr m_spriteram; + required_shared_ptr m_vscroll; + required_shared_ptr m_starx; + required_shared_ptr m_stary; + required_shared_ptr m_bgcolor; + + // stars layout + required_region_ptr m_stars_rom; + + // devices + required_device m_maincpu; + required_device m_audiocpu; + required_device m_gfxdecode; + required_device m_palette; + + // I/O + required_ioport_array<2> m_p; + + // video-related + tilemap_t *m_bg_tilemap = nullptr; + uint8_t m_charbank = 0U; + uint8_t m_starsoff = 0U; + uint8_t m_sx = 0U; + uint8_t m_sy = 0U; + uint8_t m_ox = 0U; + uint8_t m_oy = 0U; + + // misc + uint32_t m_count = 0U; + uint8_t m_disable_irq = 0U; + + uint8_t _201_r(); + uint8_t irq_ack_r(); + uint8_t _2973_r(); + void _1a2_w(uint8_t data); + uint8_t in0_r(); + void _3000_w(uint8_t data); + void videoram_w(offs_t offset, uint8_t data); + void tilecolor_w(offs_t offset, uint8_t data); + TILE_GET_INFO_MEMBER(get_tile_info); + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(vblank_irq); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + + void main_map(address_map &map); + void sound_map(address_map &map); +}; + + +// video + +// how the starfield ROM is interpreted: 0 = 256 x 256 x 1 linear bitmap, 1 = 8 x 8 x 1 x 1024 tilemap +static constexpr uint8_t STARS_LAYOUT = 1; + +// scroll speed of the stars: 1 = normal, 2 = half, 3 = one-third...etc. (positive integers only) +static constexpr uint8_t SCROLL_SPEED = 1; + +/*************************************************************************** + + Callbacks for the TileMap code + +***************************************************************************/ + +TILE_GET_INFO_MEMBER(aeroboto_state::get_tile_info) +{ + uint8_t const code = m_videoram[tile_index]; + tileinfo.set(0, + code + (m_charbank << 8), + m_tilecolor[code], + (m_tilecolor[code] >= 0x33) ? 0 : TILE_FORCE_LAYER0); +} +// transparency should only affect tiles with color 0x33 or higher + + +/*************************************************************************** + + Start the video hardware emulation. + +***************************************************************************/ + +void aeroboto_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(aeroboto_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 64); + m_bg_tilemap->set_transparent_pen(0); + m_bg_tilemap->set_scroll_rows(64); + + save_item(NAME(m_charbank)); + save_item(NAME(m_starsoff)); + save_item(NAME(m_sx)); + save_item(NAME(m_sy)); + save_item(NAME(m_ox)); + save_item(NAME(m_oy)); + + if (STARS_LAYOUT) + { + int len = m_stars_rom.bytes(); + std::vector temp(len); + memcpy(&temp[0], &m_stars_rom[0], len); + + for (int i = 0; i < len; i++) + m_stars_rom[(i & ~0xff) + (i << 5 & 0xe0) + (i >> 3 & 0x1f)] = temp[i]; + } +} + + + +/*************************************************************************** + + Memory handlers + +***************************************************************************/ + +uint8_t aeroboto_state::in0_r() +{ + return flip_screen() ? m_p[1]->read() : m_p[0]->read(); +} + +void aeroboto_state::_3000_w(uint8_t data) +{ + // bit 0 selects both flip screen and player1 / player2 controls + flip_screen_set(data & 0x01); + + // bit 1 = char bank select + if (m_charbank != ((data & 0x02) >> 1)) + { + m_bg_tilemap->mark_all_dirty(); + m_charbank = (data & 0x02) >> 1; + } + + // bit 2 = disable star field? + m_starsoff = data & 0x04; +} + +void aeroboto_state::videoram_w(offs_t offset, uint8_t data) +{ + m_videoram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset); +} + +void aeroboto_state::tilecolor_w(offs_t offset, uint8_t data) +{ + if (m_tilecolor[offset] != data) + { + m_tilecolor[offset] = data; + m_bg_tilemap->mark_all_dirty(); + } +} + + + +/*************************************************************************** + + Display refresh + +***************************************************************************/ + +void aeroboto_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int offs = 0; offs < m_spriteram.bytes(); offs += 4) + { + int x = m_spriteram[offs + 3]; + int y = 240 - m_spriteram[offs]; + + if (flip_screen()) + { + x = 248 - x; + y = 240 - y; + } + + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, + m_spriteram[offs + 1], + m_spriteram[offs + 2] & 0x07, + flip_screen(), flip_screen(), + ((x + 8) & 0xff) - 8, y, 0); + } +} + + +uint32_t aeroboto_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + rectangle const splitrect1(0, 255, 0, 39); + rectangle const splitrect2(0, 255, 40, 255); + + int star_color = *m_bgcolor << 2; + int sky_color = *m_bgcolor << 2; + + // the star field is supposed to be seen through tile pen 0 when active + if (!m_starsoff) + { + if (star_color < 0xd0) + { + star_color = 0xd0; + sky_color = 0; + } + + star_color += 2; + + bitmap.fill(sky_color, cliprect); + + // actual scroll speed is unknown but it can be adjusted by changing the SCROLL_SPEED constant + m_sx += char(*m_starx - m_ox); + m_ox = *m_starx; + int const x = m_sx / SCROLL_SPEED; + + if (*m_vscroll != 0xff) + m_sy += char(*m_stary - m_oy); + m_oy = *m_stary; + int const y = m_sy / SCROLL_SPEED; + + for (int i = 0; i < 256; i++) + { + int src_offsx = (x + i) & 0xff; + int const src_colmask = 1 << (src_offsx & 7); + src_offsx >>= 3; + uint8_t const *const src_colptr = &m_stars_rom[src_offsx]; + int const pen = star_color + ((i + 8) >> 4 & 1); + + for (int j = 0; j < 256; j++) + { + uint8_t const *const src_rowptr = src_colptr + (((y + j) & 0xff) << 5 ); + if (!((unsigned)*src_rowptr & src_colmask)) + bitmap.pix(j, i) = pen; + } + } + } + else + { + m_sx = m_ox = *m_starx; + m_sy = m_oy = *m_stary; + bitmap.fill(sky_color, cliprect); + } + + for (int y = 0; y < 64; y++) + m_bg_tilemap->set_scrollx(y, m_hscroll[y]); + + // the playfield is part of a splitscreen and should not overlap with status display + m_bg_tilemap->set_scrolly(0, *m_vscroll); + m_bg_tilemap->draw(screen, bitmap, splitrect2, 0, 0); + draw_sprites(bitmap, cliprect); -uint8_t aeroboto_state::aeroboto_201_r() + // the status display behaves more closely to a 40-line splitscreen than an overlay + m_bg_tilemap->set_scrolly(0, 0); + m_bg_tilemap->draw(screen, bitmap, splitrect1, 0, 0); + return 0; +} + + +// machine + +uint8_t aeroboto_state::_201_r() { - /* if you keep a button pressed during boot, the game will expect this */ - /* serie of values to be returned from 3004, and display "PASS 201" if it is */ + /* if you keep a button pressed during boot, the game will expect this + series of values to be returned from 3004, and display "PASS 201" if it is */ static const uint8_t res[4] = { 0xff, 0x9f, 0x1b, 0x03 }; - logerror("PC %04x: read 3004\n", m_maincpu->pc()); + LOG3004("PC %04x: read 3004\n", m_maincpu->pc()); return res[(m_count++) & 3]; } @@ -60,19 +359,19 @@ WRITE_LINE_MEMBER(aeroboto_state::vblank_irq) } } -uint8_t aeroboto_state::aeroboto_irq_ack_r() +uint8_t aeroboto_state::irq_ack_r() { m_maincpu->set_input_line(0, CLEAR_LINE); return 0xff; } -uint8_t aeroboto_state::aeroboto_2973_r() +uint8_t aeroboto_state::_2973_r() { m_mainram[0x02be] = 0; return 0xff; } -void aeroboto_state::aeroboto_1a2_w(uint8_t data) +void aeroboto_state::_1a2_w(uint8_t data) { m_mainram[0x01a2] = data; if (data) @@ -81,26 +380,26 @@ void aeroboto_state::aeroboto_1a2_w(uint8_t data) void aeroboto_state::main_map(address_map &map) { - map(0x0000, 0x07ff).ram().share("mainram"); // main RAM - map(0x01a2, 0x01a2).w(FUNC(aeroboto_state::aeroboto_1a2_w)); // affects IRQ line (more protection?) + map(0x0000, 0x07ff).ram().share(m_mainram); + map(0x01a2, 0x01a2).w(FUNC(aeroboto_state::_1a2_w)); // affects IRQ line (more protection?) map(0x0800, 0x08ff).ram(); // tile color buffer; copied to 0x2000 map(0x0900, 0x09ff).writeonly().share("colors2"); // a backup of default tile colors - map(0x1000, 0x17ff).ram().w(FUNC(aeroboto_state::aeroboto_videoram_w)).share("videoram"); // tile RAM - map(0x1800, 0x183f).ram().share("hscroll"); // horizontal scroll regs + map(0x1000, 0x17ff).ram().w(FUNC(aeroboto_state::videoram_w)).share(m_videoram); + map(0x1800, 0x183f).ram().share(m_hscroll); map(0x1840, 0x27ff).nopw(); // cleared during custom LSI test - map(0x2000, 0x20ff).ram().w(FUNC(aeroboto_state::aeroboto_tilecolor_w)).share("tilecolor"); // tile color RAM - map(0x2800, 0x28ff).ram().share("spriteram"); // sprite RAM + map(0x2000, 0x20ff).ram().w(FUNC(aeroboto_state::tilecolor_w)).share(m_tilecolor); + map(0x2800, 0x28ff).ram().share(m_spriteram); map(0x2900, 0x2fff).nopw(); // cleared along with sprite RAM - map(0x2973, 0x2973).r(FUNC(aeroboto_state::aeroboto_2973_r)); // protection read - map(0x3000, 0x3000).rw(FUNC(aeroboto_state::aeroboto_in0_r), FUNC(aeroboto_state::aeroboto_3000_w)); + map(0x2973, 0x2973).r(FUNC(aeroboto_state::_2973_r)); // protection read + map(0x3000, 0x3000).rw(FUNC(aeroboto_state::in0_r), FUNC(aeroboto_state::_3000_w)); map(0x3001, 0x3001).portr("DSW1").w("soundlatch", FUNC(generic_latch_8_device::write)); map(0x3002, 0x3002).portr("DSW2").w("soundlatch2", FUNC(generic_latch_8_device::write)); - map(0x3003, 0x3003).writeonly().share("vscroll"); - map(0x3004, 0x3004).r(FUNC(aeroboto_state::aeroboto_201_r)).writeonly().share("starx"); - map(0x3005, 0x3005).writeonly().share("stary"); // usable but probably wrong - map(0x3006, 0x3006).writeonly().share("bgcolor"); - map(0x3800, 0x3800).r(FUNC(aeroboto_state::aeroboto_irq_ack_r)); // watchdog or IRQ ack - map(0x4000, 0xffff).rom(); // main ROM + map(0x3003, 0x3003).writeonly().share(m_vscroll); + map(0x3004, 0x3004).r(FUNC(aeroboto_state::_201_r)).writeonly().share(m_starx); + map(0x3005, 0x3005).writeonly().share(m_stary); // usable but probably wrong + map(0x3006, 0x3006).writeonly().share(m_bgcolor); + map(0x3800, 0x3800).r(FUNC(aeroboto_state::irq_ack_r)); // watchdog or IRQ ack + map(0x4000, 0xffff).rom(); } void aeroboto_state::sound_map(address_map &map) @@ -147,7 +446,7 @@ static INPUT_PORTS_START( formatz ) PORT_DIPSETTING( 0x08, "40000" ) PORT_DIPSETTING( 0x04, "70000" ) PORT_DIPSETTING( 0x00, "100000" ) - PORT_DIPUNUSED_DIPLOC( 0x10, 0x00, "SW1:5" ) /* Listed as "Unused" */ + PORT_DIPUNUSED_DIPLOC( 0x10, 0x00, "SW1:5" ) // Listed as "Unused" PORT_DIPNAME( 0x20, 0x20, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:6") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x20, DEF_STR( On ) ) @@ -174,9 +473,9 @@ static INPUT_PORTS_START( formatz ) PORT_DIPSETTING( 0x08, DEF_STR( Normal ) ) PORT_DIPSETTING( 0x10, DEF_STR( Medium ) ) PORT_DIPSETTING( 0x18, DEF_STR( Hard ) ) - PORT_DIPUNUSED_DIPLOC( 0x20, 0x00, "SW2:6" ) /* Listed as "Unused" */ - PORT_DIPUNUSED_DIPLOC( 0x40, 0x00, "SW2:7" ) /* Listed as "Unused" */ - PORT_DIPUNUSED_DIPLOC( 0x80, 0x00, "SW2:8" ) /* Listed as "Unused" */ + PORT_DIPUNUSED_DIPLOC( 0x20, 0x00, "SW2:6" ) // Listed as "Unused" + PORT_DIPUNUSED_DIPLOC( 0x40, 0x00, "SW2:7" ) // Listed as "Unused" + PORT_DIPUNUSED_DIPLOC( 0x80, 0x00, "SW2:8" ) // Listed as "Unused" INPUT_PORTS_END @@ -217,16 +516,13 @@ static const gfx_layout spritelayout = }; static GFXDECODE_START( gfx_aeroboto ) - GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 64 ) /* chars */ -// GFXDECODE_ENTRY( "gfx2", 0, starlayout, 0, 128 ) /* sky */ - GFXDECODE_ENTRY( "gfx3", 0, spritelayout, 0, 8 ) + GFXDECODE_ENTRY( "tiles", 0, charlayout, 0, 64 ) +// GFXDECODE_ENTRY( "starfield_data", 0, starlayout, 0, 128 ) + GFXDECODE_ENTRY( "sprites", 0, spritelayout, 0, 8 ) GFXDECODE_END void aeroboto_state::machine_start() { - m_stars_rom = memregion("gfx2")->base(); - m_stars_length = memregion("gfx2")->bytes(); - save_item(NAME(m_disable_irq)); save_item(NAME(m_count)); } @@ -246,20 +542,20 @@ void aeroboto_state::machine_reset() void aeroboto_state::formatz(machine_config &config) { - /* basic machine hardware */ - MC6809(config, m_maincpu, XTAL(10'000'000)/2); /* verified on pcb */ + // basic machine hardware + MC6809(config, m_maincpu, XTAL(10'000'000) / 2); // verified on PCB m_maincpu->set_addrmap(AS_PROGRAM, &aeroboto_state::main_map); - MC6809(config, m_audiocpu, XTAL(10'000'000)/4); /* verified on pcb */ + MC6809(config, m_audiocpu, XTAL(10'000'000) / 4); // verified on PCB m_audiocpu->set_addrmap(AS_PROGRAM, &aeroboto_state::sound_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(32*8, 32*8); screen.set_visarea(0*8, 31*8-1, 2*8, 30*8-1); - screen.set_screen_update(FUNC(aeroboto_state::screen_update_aeroboto)); + screen.set_screen_update(FUNC(aeroboto_state::screen_update)); screen.set_palette(m_palette); screen.screen_vblank().set(FUNC(aeroboto_state::vblank_irq)); @@ -267,18 +563,18 @@ void aeroboto_state::formatz(machine_config &config) PALETTE(config, m_palette, palette_device::RGB_444_PROMS, "proms", 256); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); GENERIC_LATCH_8(config, "soundlatch"); GENERIC_LATCH_8(config, "soundlatch2"); - ay8910_device &ay1(AY8910(config, "ay1", XTAL(10'000'000)/8)); /* verified on pcb */ + ay8910_device &ay1(AY8910(config, "ay1", XTAL(10'000'000) / 8)); // verified on PCB ay1.port_a_read_callback().set("soundlatch", FUNC(generic_latch_8_device::read)); ay1.port_b_read_callback().set("soundlatch2", FUNC(generic_latch_8_device::read)); ay1.add_route(ALL_OUTPUTS, "mono", 0.25); - AY8910(config, "ay2", XTAL(10'000'000)/16).add_route(ALL_OUTPUTS, "mono", 0.25); /* verified on pcb */ + AY8910(config, "ay2", XTAL(10'000'000) / 16).add_route(ALL_OUTPUTS, "mono", 0.25); // verified on PCB } @@ -298,16 +594,16 @@ ROM_START( formatz ) ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "format_z.9", 0xf000, 0x1000, CRC(6b9215ad) SHA1(3ab416d070bf6b9a8be3e19d4dbc3a399d9ab5cb) ) - ROM_REGION( 0x2000, "gfx1", 0 ) - ROM_LOAD( "format_z.5", 0x0000, 0x2000, CRC(ba50be57) SHA1(aa37b644e8c1944b4c0ba81164d5a52be8ab491f) ) /* characters */ + ROM_REGION( 0x2000, "tiles", 0 ) + ROM_LOAD( "format_z.5", 0x0000, 0x2000, CRC(ba50be57) SHA1(aa37b644e8c1944b4c0ba81164d5a52be8ab491f) ) - ROM_REGION( 0x2000, "gfx2", 0 ) // starfield data - ROM_LOAD( "format_z.4", 0x0000, 0x2000, CRC(910375a0) SHA1(1044e0f45ce34c15986d9ab520c0e7d08fd46dde) ) /* characters */ + ROM_REGION( 0x2000, "starfield_data", 0 ) // starfield data + ROM_LOAD( "format_z.4", 0x0000, 0x2000, CRC(910375a0) SHA1(1044e0f45ce34c15986d9ab520c0e7d08fd46dde) ) - ROM_REGION( 0x3000, "gfx3", 0 ) - ROM_LOAD( "format_z.1", 0x0000, 0x1000, CRC(5739afd2) SHA1(3a645bc8a5ac69f1dc878a589c580f2bf033d3cb) ) /* sprites */ - ROM_LOAD( "format_z.2", 0x1000, 0x1000, CRC(3a821391) SHA1(476507ba5e5d64ca3729244590beadb9b3a6a018) ) /* sprites */ - ROM_LOAD( "format_z.3", 0x2000, 0x1000, CRC(7d1aec79) SHA1(bb19d6c91a14df26706226cfe22853bb8383c63d) ) /* sprites */ + ROM_REGION( 0x3000, "sprites", 0 ) + ROM_LOAD( "format_z.1", 0x0000, 0x1000, CRC(5739afd2) SHA1(3a645bc8a5ac69f1dc878a589c580f2bf033d3cb) ) + ROM_LOAD( "format_z.2", 0x1000, 0x1000, CRC(3a821391) SHA1(476507ba5e5d64ca3729244590beadb9b3a6a018) ) + ROM_LOAD( "format_z.3", 0x2000, 0x1000, CRC(7d1aec79) SHA1(bb19d6c91a14df26706226cfe22853bb8383c63d) ) ROM_REGION( 0x0300, "proms", 0 ) ROM_LOAD( "10c", 0x0000, 0x0100, CRC(b756dd6d) SHA1(ea79f87f84ded2f0a66458af24cbc792e5ff77e3) ) @@ -324,16 +620,16 @@ ROM_START( aeroboto ) ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "format_z.9", 0xf000, 0x1000, CRC(6b9215ad) SHA1(3ab416d070bf6b9a8be3e19d4dbc3a399d9ab5cb) ) - ROM_REGION( 0x2000, "gfx1", 0 ) - ROM_LOAD( "aeroboto.5", 0x0000, 0x2000, CRC(32fc00f9) SHA1(fd912fe2ab0101057c15c846f0cc4259cd94b035) ) /* characters */ + ROM_REGION( 0x2000, "tiles", 0 ) + ROM_LOAD( "aeroboto.5", 0x0000, 0x2000, CRC(32fc00f9) SHA1(fd912fe2ab0101057c15c846f0cc4259cd94b035) ) - ROM_REGION( 0x2000, "gfx2", 0 ) // starfield data - ROM_LOAD( "format_z.4", 0x0000, 0x2000, CRC(910375a0) SHA1(1044e0f45ce34c15986d9ab520c0e7d08fd46dde) ) /* characters */ + ROM_REGION( 0x2000, "starfield_data", 0 ) // starfield data + ROM_LOAD( "format_z.4", 0x0000, 0x2000, CRC(910375a0) SHA1(1044e0f45ce34c15986d9ab520c0e7d08fd46dde) ) - ROM_REGION( 0x3000, "gfx3", 0 ) - ROM_LOAD( "aeroboto.1", 0x0000, 0x1000, CRC(7820eeaf) SHA1(dedd15295bb02f417d0f51a29df686b66b94dee1) ) /* sprites */ - ROM_LOAD( "aeroboto.2", 0x1000, 0x1000, CRC(c7f81a3c) SHA1(21476a4146d5c57e2b15125c304fc61d82edf4af) ) /* sprites */ - ROM_LOAD( "aeroboto.3", 0x2000, 0x1000, CRC(5203ad04) SHA1(d16eb370de9033793a502e23c82a3119cd633aa9) ) /* sprites */ + ROM_REGION( 0x3000, "sprites", 0 ) + ROM_LOAD( "aeroboto.1", 0x0000, 0x1000, CRC(7820eeaf) SHA1(dedd15295bb02f417d0f51a29df686b66b94dee1) ) + ROM_LOAD( "aeroboto.2", 0x1000, 0x1000, CRC(c7f81a3c) SHA1(21476a4146d5c57e2b15125c304fc61d82edf4af) ) + ROM_LOAD( "aeroboto.3", 0x2000, 0x1000, CRC(5203ad04) SHA1(d16eb370de9033793a502e23c82a3119cd633aa9) ) ROM_REGION( 0x0300, "proms", 0 ) ROM_LOAD( "10c", 0x0000, 0x0100, CRC(b756dd6d) SHA1(ea79f87f84ded2f0a66458af24cbc792e5ff77e3) ) @@ -341,6 +637,7 @@ ROM_START( aeroboto ) ROM_LOAD( "10a", 0x0200, 0x0100, CRC(e8733c8f) SHA1(105b44c9108ee173a417f8c79ec8381f824dd675) ) ROM_END +} // anonymous namespace GAME( 1984, formatz, 0, formatz, formatz, aeroboto_state, empty_init, ROT0, "Jaleco", "Formation Z", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/jaleco/aeroboto.h b/src/mame/jaleco/aeroboto.h deleted file mode 100644 index 30610b7c0ed..00000000000 --- a/src/mame/jaleco/aeroboto.h +++ /dev/null @@ -1,89 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carlos A. Lozano, Uki -/*************************************************************************** - - Aeroboto - -***************************************************************************/ -#ifndef MAME_INCLUDES_AEROBOTO_H -#define MAME_INCLUDES_AEROBOTO_H - -#pragma once - -#include "emupal.h" -#include "tilemap.h" - -class aeroboto_state : public driver_device -{ -public: - aeroboto_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_mainram(*this, "mainram"), - m_videoram(*this, "videoram"), - m_hscroll(*this, "hscroll"), - m_tilecolor(*this, "tilecolor"), - m_spriteram(*this, "spriteram"), - m_vscroll(*this, "vscroll"), - m_starx(*this, "starx"), - m_stary(*this, "stary"), - m_bgcolor(*this, "bgcolor"), - m_maincpu(*this, "maincpu"), - m_audiocpu(*this, "audiocpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette") - { } - - void formatz(machine_config &config); - -private: - /* memory pointers */ - required_shared_ptr m_mainram; - required_shared_ptr m_videoram; - required_shared_ptr m_hscroll; - required_shared_ptr m_tilecolor; - required_shared_ptr m_spriteram; - required_shared_ptr m_vscroll; - required_shared_ptr m_starx; - required_shared_ptr m_stary; - required_shared_ptr m_bgcolor; - - /* stars layout */ - uint8_t * m_stars_rom = 0U; - int m_stars_length = 0; - - /* video-related */ - tilemap_t *m_bg_tilemap = nullptr; - int m_charbank = 0; - int m_starsoff = 0; - int m_sx = 0; - int m_sy = 0; - uint8_t m_ox = 0U; - uint8_t m_oy = 0U; - - /* misc */ - int m_count = 0; - int m_disable_irq = 0; - uint8_t aeroboto_201_r(); - uint8_t aeroboto_irq_ack_r(); - uint8_t aeroboto_2973_r(); - void aeroboto_1a2_w(uint8_t data); - uint8_t aeroboto_in0_r(); - void aeroboto_3000_w(uint8_t data); - void aeroboto_videoram_w(offs_t offset, uint8_t data); - void aeroboto_tilecolor_w(offs_t offset, uint8_t data); - TILE_GET_INFO_MEMBER(get_tile_info); - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - uint32_t screen_update_aeroboto(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(vblank_irq); - void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ); - required_device m_maincpu; - required_device m_audiocpu; - required_device m_gfxdecode; - required_device m_palette; - void main_map(address_map &map); - void sound_map(address_map &map); -}; - -#endif // MAME_INCLUDES_AEROBOTO_H diff --git a/src/mame/jaleco/aeroboto_v.cpp b/src/mame/jaleco/aeroboto_v.cpp deleted file mode 100644 index 42e3a5070a3..00000000000 --- a/src/mame/jaleco/aeroboto_v.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carlos A. Lozano, Uki -/*************************************************************************** - - video/aeroboto.c - -***************************************************************************/ - - -#include "emu.h" -#include "aeroboto.h" - - -// how the starfield ROM is interpreted: 0=256x256x1 linear bitmap, 1=8x8x1x1024 tilemap -#define STARS_LAYOUT 1 - -// scroll speed of the stars: 1=normal, 2=half, 3=one-third...etc.(possitive integers only) -#define SCROLL_SPEED 1 - -/*************************************************************************** - - Callbacks for the TileMap code - -***************************************************************************/ - -TILE_GET_INFO_MEMBER(aeroboto_state::get_tile_info) -{ - uint8_t code = m_videoram[tile_index]; - tileinfo.set(0, - code + (m_charbank << 8), - m_tilecolor[code], - (m_tilecolor[code] >= 0x33) ? 0 : TILE_FORCE_LAYER0); -} -// transparency should only affect tiles with color 0x33 or higher - - -/*************************************************************************** - - Start the video hardware emulation. - -***************************************************************************/ - -void aeroboto_state::video_start() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(aeroboto_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 64); - m_bg_tilemap->set_transparent_pen(0); - m_bg_tilemap->set_scroll_rows(64); - - save_item(NAME(m_charbank)); - save_item(NAME(m_starsoff)); - save_item(NAME(m_sx)); - save_item(NAME(m_sy)); - save_item(NAME(m_ox)); - save_item(NAME(m_oy)); - - #if STARS_LAYOUT - { - int i; - - std::vector temp(m_stars_length); - memcpy(&temp[0], m_stars_rom, m_stars_length); - - for (i = 0; i < m_stars_length; i++) - m_stars_rom[(i & ~0xff) + (i << 5 & 0xe0) + (i >> 3 & 0x1f)] = temp[i]; - } - #endif -} - - - -/*************************************************************************** - - Memory handlers - -***************************************************************************/ - -uint8_t aeroboto_state::aeroboto_in0_r() -{ - return ioport(flip_screen() ? "P2" : "P1")->read(); -} - -void aeroboto_state::aeroboto_3000_w(uint8_t data) -{ - /* bit 0 selects both flip screen and player1/player2 controls */ - flip_screen_set(data & 0x01); - - /* bit 1 = char bank select */ - if (m_charbank != ((data & 0x02) >> 1)) - { - m_bg_tilemap->mark_all_dirty(); - m_charbank = (data & 0x02) >> 1; - } - - /* bit 2 = disable star field? */ - m_starsoff = data & 0x4; -} - -void aeroboto_state::aeroboto_videoram_w(offs_t offset, uint8_t data) -{ - m_videoram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset); -} - -void aeroboto_state::aeroboto_tilecolor_w(offs_t offset, uint8_t data) -{ - if (m_tilecolor[offset] != data) - { - m_tilecolor[offset] = data; - m_bg_tilemap->mark_all_dirty(); - } -} - - - -/*************************************************************************** - - Display refresh - -***************************************************************************/ - -void aeroboto_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) -{ - for (int offs = 0; offs < m_spriteram.bytes(); offs += 4) - { - int x = m_spriteram[offs + 3]; - int y = 240 - m_spriteram[offs]; - - if (flip_screen()) - { - x = 248 - x; - y = 240 - y; - } - - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - m_spriteram[offs + 1], - m_spriteram[offs + 2] & 0x07, - flip_screen(), flip_screen(), - ((x + 8) & 0xff) - 8, y, 0); - } -} - - -uint32_t aeroboto_state::screen_update_aeroboto(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - rectangle const splitrect1(0, 255, 0, 39); - rectangle const splitrect2(0, 255, 40, 255); - int sky_color, star_color; - - sky_color = star_color = *m_bgcolor << 2; - - // the star field is supposed to be seen through tile pen 0 when active - if (!m_starsoff) - { - if (star_color < 0xd0) - { - star_color = 0xd0; - sky_color = 0; - } - - star_color += 2; - - bitmap.fill(sky_color, cliprect); - - // actual scroll speed is unknown but it can be adjusted by changing the SCROLL_SPEED constant - m_sx += char(*m_starx - m_ox); - m_ox = *m_starx; - int const x = m_sx / SCROLL_SPEED; - - if (*m_vscroll != 0xff) - m_sy += char(*m_stary - m_oy); - m_oy = *m_stary; - int const y = m_sy / SCROLL_SPEED; - - uint8_t const *const src_base = m_stars_rom; - - for (int i = 0; i < 256; i++) - { - int src_offsx = (x + i) & 0xff; - int const src_colmask = 1 << (src_offsx & 7); - src_offsx >>= 3; - uint8_t const *const src_colptr = src_base + src_offsx; - int const pen = star_color + ((i + 8) >> 4 & 1); - - for (int j = 0; j < 256; j++) - { - uint8_t const *const src_rowptr = src_colptr + (((y + j) & 0xff) << 5 ); - if (!((unsigned)*src_rowptr & src_colmask)) - bitmap.pix(j, i) = pen; - } - } - } - else - { - m_sx = m_ox = *m_starx; - m_sy = m_oy = *m_stary; - bitmap.fill(sky_color, cliprect); - } - - for (int y = 0; y < 64; y++) - m_bg_tilemap->set_scrollx(y, m_hscroll[y]); - - // the playfield is part of a splitscreen and should not overlap with status display - m_bg_tilemap->set_scrolly(0, *m_vscroll); - m_bg_tilemap->draw(screen, bitmap, splitrect2, 0, 0); - - draw_sprites(bitmap, cliprect); - - // the status display behaves more closely to a 40-line splitscreen than an overlay - m_bg_tilemap->set_scrolly(0, 0); - m_bg_tilemap->draw(screen, bitmap, splitrect1, 0, 0); - return 0; -} diff --git a/src/mame/jaleco/exerion.cpp b/src/mame/jaleco/exerion.cpp index 430cf7c00af..b2cf80f0065 100644 --- a/src/mame/jaleco/exerion.cpp +++ b/src/mame/jaleco/exerion.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders: Aaron Giles + /*************************************************************************** Jaleco Exerion hardware @@ -44,15 +45,15 @@ Stephh's notes (based on the games Z80 code and some tests) : to 0x4dff (code at 0x07d8) if 1st score in the high-score table is >= 80000. If checksum doesn't match the hardcoded value (0x63), you get 255 credits ! Notice that the displayed number of credits won't be correct as the game - isn't suppose to allow more than 9 credits. - - In a 2 players game, when player changes, if player it was player 2 turn, + isn't supposed to allow more than 9 credits. + - In a 2 players game, when player changes, if it was player 2 turn, values from 0x6030 to 0x6032 (see above) are compared with hard-coded values (code at 0x04c8). If they don't match respectively 0xfe, 0xb3 and 0x4c, and if 9th score in the high-score table is not 0, the game resets ! - Before entering player's initials, a checksum is computed from 0x5f00 to 0x5fff (code at 0x5bd0) if player has reached level 6 (2nd kind of enemies after bonus stage). If checksum doesn't match the hardcoded value (0x9a), the game resets ! - - There is sort of protection routine at 0x4120 which has an effect when + - There is a sort of protection routine at 0x4120 which has an effect when player loses a life on reaching first bonus stage or after. If values read from 0x6008 to 0x600b don't match values from ROM area 0x33c0-0x33ff, the game resets. See 'protection_r' read handler. @@ -120,14 +121,509 @@ Stephh's notes (based on the games Z80 code and some tests) : ***************************************************************************/ #include "emu.h" -#include "exerion.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" #include "sound/ay8910.h" +#include "video/resnet.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +// configurable logging +#define LOG_AYPORTB (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_AYPORTB) + +#include "logmacro.h" + +#define LOGAYPORTB(...) LOGMASKED(LOG_AYPORTB, __VA_ARGS__) + + +namespace { + +class exerion_state : public driver_device +{ +public: + exerion_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_main_ram(*this, "main_ram"), + m_videoram(*this, "videoram"), + m_spriteram(*this, "spriteram"), + m_maincpu_region(*this, "maincpu"), + m_background_mixer(*this, "bg_char_mixer_prom"), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_inputs(*this, "P%u", 1U) + { } + + void exerion(machine_config &config); + void irion(machine_config &config); + + void init_exerion(); + void init_exerionb(); + void init_irion(); + + DECLARE_CUSTOM_INPUT_MEMBER(controls_r); + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + // memory pointers + required_shared_ptr m_main_ram; + required_shared_ptr m_videoram; + required_shared_ptr m_spriteram; + required_region_ptr m_maincpu_region; + required_region_ptr m_background_mixer; + + // video-related + uint8_t m_cocktail_flip = 0U; + uint8_t m_char_palette = 0U; + uint8_t m_sprite_palette = 0U; + uint8_t m_char_bank = 0U; + std::unique_ptr m_background_gfx[4]{}; + uint8_t m_background_latches[13]{}; + + // protection? + uint8_t m_porta = 0U; + uint8_t m_portb = 0U; + + // devices + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + + required_ioport_array<2> m_inputs; + + uint8_t protection_r(offs_t offset); + void videoreg_w(uint8_t data); + void video_latch_w(offs_t offset, uint8_t data); + uint8_t video_timing_r(); + uint8_t porta_r(); + void portb_w(uint8_t data); + void palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect); + void main_map(address_map &map); + void sub_map(address_map &map); +}; + + +// video + +static constexpr XTAL MASTER_CLOCK = XTAL(19'968'000); // verified on PCB +static constexpr XTAL CPU_CLOCK = MASTER_CLOCK / 6; +static constexpr XTAL AY8910_CLOCK = CPU_CLOCK / 2; +static constexpr XTAL PIXEL_CLOCK = MASTER_CLOCK / 3; +static constexpr int HCOUNT_START = 0x58; +static constexpr int HTOTAL = 512 - HCOUNT_START; +static constexpr int HBEND = 12 * 8; // ?? +static constexpr int HBSTART = 52 * 8; // ?? +static constexpr int VTOTAL = 256; +static constexpr int VBEND = 16; +static constexpr int VBSTART = 240; + +static constexpr int BACKGROUND_X_START = 32; + +static constexpr int VISIBLE_X_MIN = 12 * 8; +static constexpr int VISIBLE_X_MAX = 52 * 8; +static constexpr int VISIBLE_Y_MIN = 2 * 8; +static constexpr int VISIBLE_Y_MAX = 30 * 8; + + +/*************************************************************************** + + Convert the color PROMs into a more useable format. + + The palette PROM is connected to the RGB output this way: + + bit 7 -- 220 ohm resistor -- BLUE + -- 470 ohm resistor -- BLUE + -- 220 ohm resistor -- GREEN + -- 470 ohm resistor -- GREEN + -- 1 kohm resistor -- GREEN + -- 220 ohm resistor -- RED + -- 470 ohm resistor -- RED + bit 0 -- 1 kohm resistor -- RED + +***************************************************************************/ + +void exerion_state::palette(palette_device &palette) const +{ + const uint8_t *color_prom = memregion("proms")->base(); + static constexpr int resistances_rg[3] = { 1000, 470, 220 }; + static constexpr int resistances_b [2] = { 470, 220 }; + + // compute the color output resistor weights + double rweights[3], gweights[3], bweights[2]; + compute_resistor_weights(0, 255, -1.0, + 3, &resistances_rg[0], rweights, 0, 0, + 3, &resistances_rg[0], gweights, 0, 0, + 2, &resistances_b[0], bweights, 0, 0); + + // create a lookup table for the palette + for (int i = 0; i < 0x20; 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 = combine_weights(rweights, bit0, bit1, bit2); + + // green component + bit0 = BIT(color_prom[i], 3); + bit1 = BIT(color_prom[i], 4); + bit2 = BIT(color_prom[i], 5); + int const g = combine_weights(gweights, bit0, bit1, bit2); + + // blue component + bit0 = BIT(color_prom[i], 6); + bit1 = BIT(color_prom[i], 7); + int const b = combine_weights(bweights, bit0, bit1); + + palette.set_indirect_color(i, rgb_t(r, g, b)); + } + + // color_prom now points to the beginning of the lookup table + color_prom += 0x20; + + // fg chars and sprites + for (int i = 0; i < 0x200; i++) + { + uint8_t const ctabentry = 0x10 | (color_prom[(i & 0x1c0) | ((i & 3) << 4) | ((i >> 2) & 0x0f)] & 0x0f); + palette.set_pen_indirect(i, ctabentry); + } + + // bg chars (this is not the full story... there are four layers mixed using another PROM) + for (int i = 0x200; i < 0x300; i++) + { + uint8_t const ctabentry = color_prom[i] & 0x0f; + palette.set_pen_indirect(i, ctabentry); + } +} + + + +/************************************* + * + * Video system startup + * + *************************************/ + +void exerion_state::video_start() +{ + // allocate memory for the decoded background graphics + m_background_gfx[0] = std::make_unique(256 * 256); + m_background_gfx[1] = std::make_unique(256 * 256); + m_background_gfx[2] = std::make_unique(256 * 256); + m_background_gfx[3] = std::make_unique(256 * 256); + + save_pointer(NAME(m_background_gfx[0]), 256 * 256); + save_pointer(NAME(m_background_gfx[1]), 256 * 256); + save_pointer(NAME(m_background_gfx[2]), 256 * 256); + save_pointer(NAME(m_background_gfx[3]), 256 * 256); + + m_cocktail_flip = 0; + + /*--------------------------------- + * Decode the background graphics + * + * We decode the 4 background layers separately, but shuffle the bits so that + * we can OR all four layers together. Each layer has 2 bits per pixel. Each + * layer is decoded into the following bit patterns: + * + * 000a 0000 00AA + * 00b0 0000 BB00 + * 0c00 00CC 0000 + * d000 DD00 0000 + * + * Where AA,BB,CC,DD are the 2bpp data for the pixel,and a,b,c,d are the OR + * of these two bits together. + */ + uint8_t *gfx = memregion("bgdata")->base(); + for (int i = 0; i < 4; i++) + { + uint8_t *src = gfx + i * 0x2000; + uint16_t *dst = m_background_gfx[i].get(); + + for (int y = 0; y < 0x100; y++) + { + int x; + + for (x = 0; x < 0x80; x += 4) + { + uint8_t data = *src++; + uint16_t val; + + val = ((data >> 3) & 2) | ((data >> 0) & 1); + if (val) val |= 0x100 >> i; + *dst++ = val << (2 * i); + + val = ((data >> 4) & 2) | ((data >> 1) & 1); + if (val) val |= 0x100 >> i; + *dst++ = val << (2 * i); + + val = ((data >> 5) & 2) | ((data >> 2) & 1); + if (val) val |= 0x100 >> i; + *dst++ = val << (2 * i); + + val = ((data >> 6) & 2) | ((data >> 3) & 1); + if (val) val |= 0x100 >> i; + *dst++ = val << (2 * i); + } + + for (; x < 0x100; x++) + *dst++ = 0; + } + } +} + + + +/************************************* + * + * Video register I/O + * + *************************************/ + +void exerion_state::videoreg_w(uint8_t data) +{ + // bit 0 = flip screen and joystick input multiplexer + m_cocktail_flip = data & 1; + + // bits 1-2 char lookup table bank + m_char_palette = (data & 0x06) >> 1; + + // bits 3 char bank + m_char_bank = (data & 0x08) >> 3; + + // bits 4-5 unused + + // bits 6-7 sprite lookup table bank + m_sprite_palette = (data & 0xc0) >> 6; +} + + +void exerion_state::video_latch_w(offs_t offset, uint8_t data) +{ + int const scanline = m_screen->vpos(); + if (scanline > 0) + m_screen->update_partial(scanline - 1); + m_background_latches[offset] = data; +} + + +uint8_t exerion_state::video_timing_r() +{ + // bit 0 is the SNMI signal, which is the negated value of H6, if H7=1 & H8=1 & VBLANK=0, otherwise 1 + // bit 1 is VBLANK + + uint16_t const hcounter = m_screen->hpos() + HCOUNT_START; + uint8_t snmi = 1; + + if (((hcounter & 0x180) == 0x180) && !m_screen->vblank()) + snmi = !((hcounter >> 6) & 0x01); + + return (m_screen->vblank() << 1) | snmi; +} + + +/************************************* + * + * Background rendering + * + *************************************/ + +void exerion_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // loop over all visible scanlines + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + uint16_t const *src0 = &m_background_gfx[0][m_background_latches[1] * 256]; + uint16_t const *src1 = &m_background_gfx[1][m_background_latches[3] * 256]; + uint16_t const *src2 = &m_background_gfx[2][m_background_latches[5] * 256]; + uint16_t const *src3 = &m_background_gfx[3][m_background_latches[7] * 256]; + int xoffs0 = m_background_latches[0]; + int xoffs1 = m_background_latches[2]; + int xoffs2 = m_background_latches[4]; + int xoffs3 = m_background_latches[6]; + int start0 = m_background_latches[8] & 0x0f; + int start1 = m_background_latches[9] & 0x0f; + int start2 = m_background_latches[10] & 0x0f; + int start3 = m_background_latches[11] & 0x0f; + int stop0 = m_background_latches[8] >> 4; + int stop1 = m_background_latches[9] >> 4; + int stop2 = m_background_latches[10] >> 4; + int stop3 = m_background_latches[11] >> 4; + uint8_t *const mixer = &m_background_mixer[(m_background_latches[12] << 4) & 0xf0]; + uint16_t scanline[VISIBLE_X_MAX]; + pen_t const pen_base = 0x200 + ((m_background_latches[12] >> 4) << 4); + + // the cocktail flip flag controls whether we count up or down in X + if (!m_cocktail_flip) + { + // skip processing anything that's not visible + for (int x = BACKGROUND_X_START; x < cliprect.min_x; x++) + { + if (!(++xoffs0 & 0x1f)) start0++, stop0++; + if (!(++xoffs1 & 0x1f)) start1++, stop1++; + if (!(++xoffs2 & 0x1f)) start2++, stop2++; + if (!(++xoffs3 & 0x1f)) start3++, stop3++; + } + + // draw the rest of the scanline fully + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + uint16_t combined = 0; + + // the output enable is controlled by the carries on the start/stop counters + // they are only active when the start has carried but the stop hasn't + if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff]; + if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff]; + if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff]; + if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff]; + + // bits 8-11 of the combined value contains the lookup for the mixer PROM + uint8_t const lookupval = mixer[combined >> 8] & 3; + + // the color index comes from the looked up value combined with the pixel data + scanline[x] = pen_base | (lookupval << 2) | ((combined >> (2 * lookupval)) & 3); + + // the start/stop counters are clocked when the low 5 bits of the X counter overflow + if (!(++xoffs0 & 0x1f)) start0++, stop0++; + if (!(++xoffs1 & 0x1f)) start1++, stop1++; + if (!(++xoffs2 & 0x1f)) start2++, stop2++; + if (!(++xoffs3 & 0x1f)) start3++, stop3++; + } + } + else + { + // skip processing anything that's not visible + for (int x = BACKGROUND_X_START; x < cliprect.min_x; x++) + { + if (!(xoffs0-- & 0x1f)) start0++, stop0++; + if (!(xoffs1-- & 0x1f)) start1++, stop1++; + if (!(xoffs2-- & 0x1f)) start2++, stop2++; + if (!(xoffs3-- & 0x1f)) start3++, stop3++; + } + + // draw the rest of the scanline fully + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + uint16_t combined = 0; + + // the output enable is controlled by the carries on the start/stop counters + // they are only active when the start has carried but the stop hasn't + if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff]; + if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff]; + if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff]; + if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff]; + + // bits 8-11 of the combined value contains the lookup for the mixer PROM + uint8_t const lookupval = mixer[combined >> 8] & 3; + + // the color index comes from the looked up value combined with the pixel data + scanline[x] = pen_base | (lookupval << 2) | ((combined >> (2 * lookupval)) & 3); + + // the start/stop counters are clocked when the low 5 bits of the X counter overflow + if (!(xoffs0-- & 0x1f)) start0++, stop0++; + if (!(xoffs1-- & 0x1f)) start1++, stop1++; + if (!(xoffs2-- & 0x1f)) start2++, stop2++; + if (!(xoffs3-- & 0x1f)) start3++, stop3++; + } + } + + // draw the scanline + draw_scanline16(bitmap, cliprect.min_x, y, cliprect.width(), &scanline[cliprect.min_x], nullptr); + } +} + + +/************************************* + * + * Core refresh routine + * + *************************************/ + +uint32_t exerion_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // draw background + draw_background(bitmap, cliprect); + + // draw sprites + for (int i = 0; i < m_spriteram.bytes(); i += 4) + { + int const flags = m_spriteram[i + 0]; + int y = m_spriteram[i + 1] ^ 255; + int code = m_spriteram[i + 2]; + int x = m_spriteram[i + 3] * 2 + 72; + + int xflip = flags & 0x80; + int yflip = flags & 0x40; + int const doubled = flags & 0x10; + int const wide = flags & 0x08; + int code2 = code; + + int const color = ((flags >> 1) & 0x03) | ((code >> 5) & 0x04) | (code & 0x08) | (m_sprite_palette * 16); + gfx_element *gfx = doubled ? m_gfxdecode->gfx(2) : m_gfxdecode->gfx(1); + + if (m_cocktail_flip) + { + x = 64 * 8 - gfx->width() - x; + y = 32 * 8 - gfx->height() - y; + if (wide) y -= gfx->height(); + xflip = !xflip; + yflip = !yflip; + } + + if (wide) + { + if (yflip) + code |= 0x10, code2 &= ~0x10; + else + code &= ~0x10, code2 |= 0x10; + + gfx->transmask(bitmap, cliprect, code2, color, xflip, yflip, x, y + gfx->height(), + m_palette->transpen_mask(*gfx, color, 0x10)); + } + + gfx->transmask(bitmap, cliprect, code, color, xflip, yflip, x, y, + m_palette->transpen_mask(*gfx, color, 0x10)); + + if (doubled) i += 4; + } + + // draw the visible text layer + for (int sy = cliprect.min_y / 8; sy <= cliprect.max_y / 8; sy++) + for (int sx = VISIBLE_X_MIN / 8; sx < VISIBLE_X_MAX / 8; sx++) + { + int const x = m_cocktail_flip ? (63 * 8 - 8 * sx) : 8 * sx; + int const y = m_cocktail_flip ? (31 * 8 - 8 * sy) : 8 * sy; + + int const offs = sx + sy * 64; + m_gfxdecode->gfx(0)->transpen(bitmap, cliprect, + m_videoram[offs] + 256 * m_char_bank, + ((m_videoram[offs] & 0xf0) >> 4) + m_char_palette * 16, + m_cocktail_flip, m_cocktail_flip, x, y, 0); + } + + return 0; +} + + +// machine + /************************************* * * Interrupts & inputs @@ -170,7 +666,7 @@ void exerion_state::portb_w(uint8_t data) m_porta = m_maincpu_region[0x5f76]; m_portb = data; - logerror("Port B = %02X\n", data); + LOGAYPORTB("Port B = %02X\n", data); } @@ -371,30 +867,30 @@ void exerion_state::machine_reset() void exerion_state::exerion(machine_config &config) { - Z80(config, m_maincpu, EXERION_CPU_CLOCK); + Z80(config, m_maincpu, CPU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &exerion_state::main_map); - z80_device &sub(Z80(config, "sub", EXERION_CPU_CLOCK)); + z80_device &sub(Z80(config, "sub", CPU_CLOCK)); sub.set_addrmap(AS_PROGRAM, &exerion_state::sub_map); // video hardware SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(EXERION_PIXEL_CLOCK, EXERION_HTOTAL, EXERION_HBEND, EXERION_HBSTART, EXERION_VTOTAL, EXERION_VBEND, EXERION_VBSTART); + m_screen->set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART); m_screen->set_screen_update(FUNC(exerion_state::screen_update)); m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_exerion); - PALETTE(config, m_palette, FUNC(exerion_state::palette), 256*3, 32); + PALETTE(config, m_palette, FUNC(exerion_state::palette), 256 * 3, 32); // audio hardware SPEAKER(config, "mono").front_center(); GENERIC_LATCH_8(config, "soundlatch"); - AY8910(config, "ay1", EXERION_AY8910_CLOCK).add_route(ALL_OUTPUTS, "mono", 0.30); + AY8910(config, "ay1", AY8910_CLOCK).add_route(ALL_OUTPUTS, "mono", 0.30); - ay8910_device &ay2(AY8910(config, "ay2", EXERION_AY8910_CLOCK)); + ay8910_device &ay2(AY8910(config, "ay2", AY8910_CLOCK)); ay2.port_a_read_callback().set(FUNC(exerion_state::porta_r)); ay2.port_b_write_callback().set(FUNC(exerion_state::portb_w)); ay2.add_route(ALL_OUTPUTS, "mono", 0.30); @@ -673,7 +1169,7 @@ void exerion_state::init_exerionb() void exerion_state::init_irion() { - // convert the gfx and cpu roms like in ExerionB + // convert the gfx and cpu ROMS like in ExerionB init_exerionb(); // a further unscramble of gfx2 @@ -689,6 +1185,7 @@ void exerion_state::init_irion() } } +} // anonymous namespace /************************************* diff --git a/src/mame/jaleco/exerion.h b/src/mame/jaleco/exerion.h deleted file mode 100644 index cc4c4b41ab0..00000000000 --- a/src/mame/jaleco/exerion.h +++ /dev/null @@ -1,103 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/************************************************************************* - - Jaleco Exerion - -*************************************************************************/ -#ifndef MAME_INCLUDES_EXERION_H -#define MAME_INCLUDES_EXERION_H - -#pragma once - -#include "emupal.h" -#include "screen.h" - - -#define EXERION_MASTER_CLOCK (XTAL(19'968'000)) /* verified on pcb */ -#define EXERION_CPU_CLOCK (EXERION_MASTER_CLOCK / 6) -#define EXERION_AY8910_CLOCK (EXERION_CPU_CLOCK / 2) -#define EXERION_PIXEL_CLOCK (EXERION_MASTER_CLOCK / 3) -#define EXERION_HCOUNT_START (0x58) -#define EXERION_HTOTAL (512-EXERION_HCOUNT_START) -#define EXERION_HBEND (12*8) /* ?? */ -#define EXERION_HBSTART (52*8) /* ?? */ -#define EXERION_VTOTAL (256) -#define EXERION_VBEND (16) -#define EXERION_VBSTART (240) - - -class exerion_state : public driver_device -{ -public: - exerion_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_main_ram(*this, "main_ram"), - m_videoram(*this, "videoram"), - m_spriteram(*this, "spriteram"), - m_maincpu_region(*this, "maincpu"), - m_background_mixer(*this, "bg_char_mixer_prom"), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_inputs(*this, "P%u", 1U) - { } - - void exerion(machine_config &config); - void irion(machine_config &config); - - void init_exerion(); - void init_exerionb(); - void init_irion(); - - DECLARE_CUSTOM_INPUT_MEMBER(controls_r); - DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - -private: - // memory pointers - required_shared_ptr m_main_ram; - required_shared_ptr m_videoram; - required_shared_ptr m_spriteram; - required_region_ptr m_maincpu_region; - required_region_ptr m_background_mixer; - - // video-related - uint8_t m_cocktail_flip = 0U; - uint8_t m_char_palette = 0U; - uint8_t m_sprite_palette = 0U; - uint8_t m_char_bank = 0U; - std::unique_ptr m_background_gfx[4]{}; - uint8_t m_background_latches[13]{}; - - // protection? - uint8_t m_porta = 0U; - uint8_t m_portb = 0U; - - // devices - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - - required_ioport_array<2> m_inputs; - - uint8_t protection_r(offs_t offset); - void videoreg_w(uint8_t data); - void video_latch_w(offs_t offset, uint8_t data); - uint8_t video_timing_r(); - uint8_t porta_r(); - void portb_w(uint8_t data); - void palette(palette_device &palette) const; - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_background( bitmap_ind16 &bitmap, const rectangle &cliprect); - void main_map(address_map &map); - void sub_map(address_map &map); -}; - -#endif // MAME_INCLUDES_EXERION_H diff --git a/src/mame/jaleco/exerion_v.cpp b/src/mame/jaleco/exerion_v.cpp deleted file mode 100644 index 78e85b78e9d..00000000000 --- a/src/mame/jaleco/exerion_v.cpp +++ /dev/null @@ -1,403 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - Jaleco Exerion - -***************************************************************************/ - -#include "emu.h" -#include "video/resnet.h" -#include "exerion.h" - - -#define BACKGROUND_X_START 32 - -#define VISIBLE_X_MIN (12*8) -#define VISIBLE_X_MAX (52*8) -#define VISIBLE_Y_MIN (2*8) -#define VISIBLE_Y_MAX (30*8) - - -/*************************************************************************** - - Convert the color PROMs into a more useable format. - - The palette PROM is connected to the RGB output this way: - - bit 7 -- 220 ohm resistor -- BLUE - -- 470 ohm resistor -- BLUE - -- 220 ohm resistor -- GREEN - -- 470 ohm resistor -- GREEN - -- 1 kohm resistor -- GREEN - -- 220 ohm resistor -- RED - -- 470 ohm resistor -- RED - bit 0 -- 1 kohm resistor -- RED - -***************************************************************************/ - -void exerion_state::palette(palette_device &palette) const -{ - const uint8_t *color_prom = memregion("proms")->base(); - static constexpr int resistances_rg[3] = { 1000, 470, 220 }; - static constexpr int resistances_b [2] = { 470, 220 }; - - // compute the color output resistor weights - double rweights[3], gweights[3], bweights[2]; - compute_resistor_weights(0, 255, -1.0, - 3, &resistances_rg[0], rweights, 0, 0, - 3, &resistances_rg[0], gweights, 0, 0, - 2, &resistances_b[0], bweights, 0, 0); - - // create a lookup table for the palette - for (int i = 0; i < 0x20; 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 = combine_weights(rweights, bit0, bit1, bit2); - - // green component - bit0 = BIT(color_prom[i], 3); - bit1 = BIT(color_prom[i], 4); - bit2 = BIT(color_prom[i], 5); - int const g = combine_weights(gweights, bit0, bit1, bit2); - - // blue component - bit0 = BIT(color_prom[i], 6); - bit1 = BIT(color_prom[i], 7); - int const b = combine_weights(bweights, bit0, bit1); - - palette.set_indirect_color(i, rgb_t(r, g, b)); - } - - // color_prom now points to the beginning of the lookup table - color_prom += 0x20; - - // fg chars and sprites - for (int i = 0; i < 0x200; i++) - { - uint8_t const ctabentry = 0x10 | (color_prom[(i & 0x1c0) | ((i & 3) << 4) | ((i >> 2) & 0x0f)] & 0x0f); - palette.set_pen_indirect(i, ctabentry); - } - - // bg chars (this is not the full story... there are four layers mixed using another PROM - for (int i = 0x200; i < 0x300; i++) - { - uint8_t const ctabentry = color_prom[i] & 0x0f; - palette.set_pen_indirect(i, ctabentry); - } -} - - - -/************************************* - * - * Video system startup - * - *************************************/ - -void exerion_state::video_start() -{ - // allocate memory for the decoded background graphics - m_background_gfx[0] = std::make_unique(256 * 256); - m_background_gfx[1] = std::make_unique(256 * 256); - m_background_gfx[2] = std::make_unique(256 * 256); - m_background_gfx[3] = std::make_unique(256 * 256); - - save_pointer(NAME(m_background_gfx[0]), 256 * 256); - save_pointer(NAME(m_background_gfx[1]), 256 * 256); - save_pointer(NAME(m_background_gfx[2]), 256 * 256); - save_pointer(NAME(m_background_gfx[3]), 256 * 256); - - m_cocktail_flip = 0; - - /*--------------------------------- - * Decode the background graphics - * - * We decode the 4 background layers separately, but shuffle the bits so that - * we can OR all four layers together. Each layer has 2 bits per pixel. Each - * layer is decoded into the following bit patterns: - * - * 000a 0000 00AA - * 00b0 0000 BB00 - * 0c00 00CC 0000 - * d000 DD00 0000 - * - * Where AA,BB,CC,DD are the 2bpp data for the pixel,and a,b,c,d are the OR - * of these two bits together. - */ - uint8_t *gfx = memregion("bgdata")->base(); - for (int i = 0; i < 4; i++) - { - uint8_t *src = gfx + i * 0x2000; - uint16_t *dst = m_background_gfx[i].get(); - - for (int y = 0; y < 0x100; y++) - { - int x; - - for (x = 0; x < 0x80; x += 4) - { - uint8_t data = *src++; - uint16_t val; - - val = ((data >> 3) & 2) | ((data >> 0) & 1); - if (val) val |= 0x100 >> i; - *dst++ = val << (2 * i); - - val = ((data >> 4) & 2) | ((data >> 1) & 1); - if (val) val |= 0x100 >> i; - *dst++ = val << (2 * i); - - val = ((data >> 5) & 2) | ((data >> 2) & 1); - if (val) val |= 0x100 >> i; - *dst++ = val << (2 * i); - - val = ((data >> 6) & 2) | ((data >> 3) & 1); - if (val) val |= 0x100 >> i; - *dst++ = val << (2 * i); - } - - for (; x < 0x100; x++) - *dst++ = 0; - } - } -} - - - -/************************************* - * - * Video register I/O - * - *************************************/ - -void exerion_state::videoreg_w(uint8_t data) -{ - // bit 0 = flip screen and joystick input multiplexer - m_cocktail_flip = data & 1; - - // bits 1-2 char lookup table bank - m_char_palette = (data & 0x06) >> 1; - - // bits 3 char bank - m_char_bank = (data & 0x08) >> 3; - - // bits 4-5 unused - - // bits 6-7 sprite lookup table bank - m_sprite_palette = (data & 0xc0) >> 6; -} - - -void exerion_state::video_latch_w(offs_t offset, uint8_t data) -{ - int scanline = m_screen->vpos(); - if (scanline > 0) - m_screen->update_partial(scanline - 1); - m_background_latches[offset] = data; -} - - -uint8_t exerion_state::video_timing_r() -{ - // bit 0 is the SNMI signal, which is the negated value of H6, if H7=1 & H8=1 & VBLANK=0, otherwise 1 - // bit 1 is VBLANK - - uint16_t hcounter = m_screen->hpos() + EXERION_HCOUNT_START; - uint8_t snmi = 1; - - if (((hcounter & 0x180) == 0x180) && !m_screen->vblank()) - snmi = !((hcounter >> 6) & 0x01); - - return (m_screen->vblank() << 1) | snmi; -} - - -/************************************* - * - * Background rendering - * - *************************************/ - -void exerion_state::draw_background( bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - // loop over all visible scanlines - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - uint16_t *src0 = &m_background_gfx[0][m_background_latches[1] * 256]; - uint16_t *src1 = &m_background_gfx[1][m_background_latches[3] * 256]; - uint16_t *src2 = &m_background_gfx[2][m_background_latches[5] * 256]; - uint16_t *src3 = &m_background_gfx[3][m_background_latches[7] * 256]; - int xoffs0 = m_background_latches[0]; - int xoffs1 = m_background_latches[2]; - int xoffs2 = m_background_latches[4]; - int xoffs3 = m_background_latches[6]; - int start0 = m_background_latches[8] & 0x0f; - int start1 = m_background_latches[9] & 0x0f; - int start2 = m_background_latches[10] & 0x0f; - int start3 = m_background_latches[11] & 0x0f; - int stop0 = m_background_latches[8] >> 4; - int stop1 = m_background_latches[9] >> 4; - int stop2 = m_background_latches[10] >> 4; - int stop3 = m_background_latches[11] >> 4; - uint8_t *mixer = &m_background_mixer[(m_background_latches[12] << 4) & 0xf0]; - uint16_t scanline[VISIBLE_X_MAX]; - pen_t pen_base = 0x200 + ((m_background_latches[12] >> 4) << 4); - - // the cocktail flip flag controls whether we count up or down in X - if (!m_cocktail_flip) - { - // skip processing anything that's not visible - for (int x = BACKGROUND_X_START; x < cliprect.min_x; x++) - { - if (!(++xoffs0 & 0x1f)) start0++, stop0++; - if (!(++xoffs1 & 0x1f)) start1++, stop1++; - if (!(++xoffs2 & 0x1f)) start2++, stop2++; - if (!(++xoffs3 & 0x1f)) start3++, stop3++; - } - - // draw the rest of the scanline fully - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - uint16_t combined = 0; - uint8_t lookupval; - - // the output enable is controlled by the carries on the start/stop counters - // they are only active when the start has carried but the stop hasn't - if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff]; - if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff]; - if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff]; - if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff]; - - // bits 8-11 of the combined value contains the lookup for the mixer PROM - lookupval = mixer[combined >> 8] & 3; - - // the color index comes from the looked up value combined with the pixel data - scanline[x] = pen_base | (lookupval << 2) | ((combined >> (2 * lookupval)) & 3); - - // the start/stop counters are clocked when the low 5 bits of the X counter overflow - if (!(++xoffs0 & 0x1f)) start0++, stop0++; - if (!(++xoffs1 & 0x1f)) start1++, stop1++; - if (!(++xoffs2 & 0x1f)) start2++, stop2++; - if (!(++xoffs3 & 0x1f)) start3++, stop3++; - } - } - else - { - // skip processing anything that's not visible - for (int x = BACKGROUND_X_START; x < cliprect.min_x; x++) - { - if (!(xoffs0-- & 0x1f)) start0++, stop0++; - if (!(xoffs1-- & 0x1f)) start1++, stop1++; - if (!(xoffs2-- & 0x1f)) start2++, stop2++; - if (!(xoffs3-- & 0x1f)) start3++, stop3++; - } - - // draw the rest of the scanline fully - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - uint16_t combined = 0; - uint8_t lookupval; - - // the output enable is controlled by the carries on the start/stop counters - // they are only active when the start has carried but the stop hasn't - if ((start0 ^ stop0) & 0x10) combined |= src0[xoffs0 & 0xff]; - if ((start1 ^ stop1) & 0x10) combined |= src1[xoffs1 & 0xff]; - if ((start2 ^ stop2) & 0x10) combined |= src2[xoffs2 & 0xff]; - if ((start3 ^ stop3) & 0x10) combined |= src3[xoffs3 & 0xff]; - - // bits 8-11 of the combined value contains the lookup for the mixer PROM - lookupval = mixer[combined >> 8] & 3; - - // the color index comes from the looked up value combined with the pixel data - scanline[x] = pen_base | (lookupval << 2) | ((combined >> (2 * lookupval)) & 3); - - // the start/stop counters are clocked when the low 5 bits of the X counter overflow - if (!(xoffs0-- & 0x1f)) start0++, stop0++; - if (!(xoffs1-- & 0x1f)) start1++, stop1++; - if (!(xoffs2-- & 0x1f)) start2++, stop2++; - if (!(xoffs3-- & 0x1f)) start3++, stop3++; - } - } - - // draw the scanline - draw_scanline16(bitmap, cliprect.min_x, y, cliprect.width(), &scanline[cliprect.min_x], nullptr); - } -} - - -/************************************* - * - * Core refresh routine - * - *************************************/ - -uint32_t exerion_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - // draw background - draw_background(bitmap, cliprect); - - // draw sprites - for (int i = 0; i < m_spriteram.bytes(); i += 4) - { - int flags = m_spriteram[i + 0]; - int y = m_spriteram[i + 1] ^ 255; - int code = m_spriteram[i + 2]; - int x = m_spriteram[i + 3] * 2 + 72; - - int xflip = flags & 0x80; - int yflip = flags & 0x40; - int doubled = flags & 0x10; - int wide = flags & 0x08; - int code2 = code; - - int color = ((flags >> 1) & 0x03) | ((code >> 5) & 0x04) | (code & 0x08) | (m_sprite_palette * 16); - gfx_element *gfx = doubled ? m_gfxdecode->gfx(2) : m_gfxdecode->gfx(1); - - if (m_cocktail_flip) - { - x = 64*8 - gfx->width() - x; - y = 32*8 - gfx->height() - y; - if (wide) y -= gfx->height(); - xflip = !xflip; - yflip = !yflip; - } - - if (wide) - { - if (yflip) - code |= 0x10, code2 &= ~0x10; - else - code &= ~0x10, code2 |= 0x10; - - gfx->transmask(bitmap,cliprect, code2, color, xflip, yflip, x, y + gfx->height(), - m_palette->transpen_mask(*gfx, color, 0x10)); - } - - gfx->transmask(bitmap,cliprect, code, color, xflip, yflip, x, y, - m_palette->transpen_mask(*gfx, color, 0x10)); - - if (doubled) i += 4; - } - - // draw the visible text layer - for (int sy = cliprect.min_y/8; sy <= cliprect.max_y/8; sy++) - for (int sx = VISIBLE_X_MIN/8; sx < VISIBLE_X_MAX/8; sx++) - { - int x = m_cocktail_flip ? (63*8 - 8*sx) : 8*sx; - int y = m_cocktail_flip ? (31*8 - 8*sy) : 8*sy; - - int offs = sx + sy * 64; - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, - m_videoram[offs] + 256 * m_char_bank, - ((m_videoram[offs] & 0xf0) >> 4) + m_char_palette * 16, - m_cocktail_flip, m_cocktail_flip, x, y, 0); - } - - return 0; -} diff --git a/src/mame/jaleco/fcombat.cpp b/src/mame/jaleco/fcombat.cpp index 214beff41a4..ae2b1f8c9af 100644 --- a/src/mame/jaleco/fcombat.cpp +++ b/src/mame/jaleco/fcombat.cpp @@ -1,11 +1,11 @@ // license:BSD-3-Clause -// copyright-holders:Tomasz Slanina +// copyright-holders: Tomasz Slanina /* Field Combat (c)1985 Jaleco TS 2004.10.22. - fixed sprite issues - - added backgrounds and terrain info (external roms) + - added backgrounds and terrain info (external ROMs) (press buttons 1+2 at the same time, to release 'army' ;) @@ -32,26 +32,326 @@ inputs + notes by stephh */ #include "emu.h" -#include "fcombat.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" #include "sound/ay8910.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +// configurable logging +#define LOG_PALETTEBANK (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_PALETTEBANK) + +#include "logmacro.h" + +#define LOGPALETTEBANK(...) LOGMASKED(LOG_PALETTEBANK, __VA_ARGS__) + + +namespace { + +class fcombat_state : public driver_device +{ +public: + fcombat_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_videoram(*this, "videoram"), + m_spriteram(*this, "spriteram"), + m_bgdata_rom(*this, "bgdata"), + m_terrain_rom(*this, "terrain_info"), + m_io_in(*this, "IN%u", 0U), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette") + { } + + void fcombat(machine_config &config); + + void init_fcombat(); + + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + /* memory pointers */ + required_shared_ptr m_videoram; + required_shared_ptr m_spriteram; + required_region_ptr m_bgdata_rom; + required_region_ptr m_terrain_rom; + + required_ioport_array<2> m_io_in; + + // video-related + tilemap_t *m_bgmap = nullptr; + u8 m_cocktail_flip = 0U; + u8 m_char_palette = 0U; + u8 m_sprite_palette = 0U; + u8 m_char_bank = 0U; + + // misc + u8 m_fcombat_sh = 0; + u16 m_fcombat_sv = 0; + u8 m_tx = 0; + u8 m_ty = 0; + + // devices + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_palette; + + u8 protection_r(); + u8 port01_r(); + void e900_w(u8 data); + void ea00_w(u8 data); + void eb00_w(u8 data); + void ec00_w(u8 data); + void ed00_w(u8 data); + u8 e300_r(); + void ee00_w(u8 data); + void videoreg_w(u8 data); + TILE_GET_INFO_MEMBER(get_bg_tile_info); + void fcombat_palette(palette_device &palette) const; + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void audio_map(address_map &map); + void main_map(address_map &map); +}; + + +// video + +// this is copied from Exerion, but it should be correct +static constexpr XTAL MASTER_CLOCK = 20_MHz_XTAL; +static constexpr XTAL CPU_CLOCK = MASTER_CLOCK / 6; +static constexpr XTAL AY8910_CLOCK = CPU_CLOCK / 2; +static constexpr XTAL PIXEL_CLOCK = MASTER_CLOCK / 3; +static constexpr int HCOUNT_START = 0x58; +static constexpr int HTOTAL = 512 - HCOUNT_START; +static constexpr int HBEND = 12 * 8; // ?? +static constexpr int HBSTART = 52 * 8; // +static constexpr int VTOTAL = 256; +static constexpr int VBEND = 16; +static constexpr int VBSTART = 240; + +static constexpr int BACKGROUND_X_START = 32; +static constexpr int BACKGROUND_X_START_FLIP = 72; + +static constexpr int VISIBLE_X_MIN = 12 * 8; +static constexpr int VISIBLE_X_MAX = 52 * 8; +static constexpr int VISIBLE_Y_MIN = 2 * 8; +static constexpr int VISIBLE_Y_MAX = 30 * 8; + + +TILE_GET_INFO_MEMBER(fcombat_state::get_bg_tile_info) +{ + //int palno = (tile_index - (tile_index / 32 * 16) * 32 * 16) / 32; + + const int tileno = m_bgdata_rom[tile_index]; + const int palno = 0x18; //m_terrain_rom[tile_index] >> 3; + tileinfo.set(2, tileno, palno, 0); +} + + +/*************************************************************************** + + Convert the color PROMs into a more useable format. + + The palette PROM is connected to the RGB output this way: + + bit 7 -- 220 ohm resistor -- BLUE + -- 470 ohm resistor -- BLUE + -- 220 ohm resistor -- GREEN + -- 470 ohm resistor -- GREEN + -- 1 kohm resistor -- GREEN + -- 220 ohm resistor -- RED + -- 470 ohm resistor -- RED + bit 0 -- 1 kohm resistor -- RED + +***************************************************************************/ + +void fcombat_state::fcombat_palette(palette_device &palette) const +{ + const u8 *color_prom = memregion("proms")->base(); + + // create a lookup table for the palette + for (int i = 0; i < 0x20; 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); + const u8 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); + const u8 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + // blue component + bit0 = 0; + bit1 = BIT(color_prom[i], 6); + bit2 = BIT(color_prom[i], 7); + const u8 b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + palette.set_indirect_color(i, rgb_t(r, g, b)); + } + + // color_prom now points to the beginning of the lookup table + color_prom += 0x20; + + // fg chars/sprites + for (int i = 0; i < 0x200; i++) + { + const u8 ctabentry = (color_prom[(i & 0x1c0) | ((i & 3) << 4) | ((i >> 2) & 0x0f)] & 0x0f) | 0x10; + palette.set_pen_indirect(i, ctabentry); + } + + // bg chars (this is not the full story... there are four layers mixed using another PROM) + for (int i = 0x200; i < 0x300; i++) + { + const u8 ctabentry = color_prom[i] & 0x0f; + palette.set_pen_indirect(i, ctabentry); + } +} + + +/************************************* + * + * Video system startup + * + *************************************/ +void fcombat_state::video_start() +{ + m_bgmap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fcombat_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32 * 8 * 2, 32); +} + + +/************************************* + * + * Video register I/O + * + *************************************/ + +void fcombat_state::videoreg_w(u8 data) +{ + // bit 0 = flip screen and joystick input multiplexer + m_cocktail_flip = data & 1; + + // bits 1-2 char lookup table bank + m_char_palette = (data & 0x06) >> 1; + + // bits 3 char bank + m_char_bank = (data & 0x08) >> 3; + + // bits 4-5 unused + + // bits 6-7 sprite lookup table bank + m_sprite_palette = 0; //(data & 0xc0) >> 6; + LOGPALETTEBANK("sprite palette bank: %02x", data); +} + + +u32 fcombat_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // draw background + m_bgmap->set_scrolly(0, m_fcombat_sh); + m_bgmap->set_scrollx(0, m_fcombat_sv - 24); + + m_bgmap->mark_all_dirty(); + m_bgmap->draw(screen, bitmap, cliprect, 0, 0); + //draw_background(bitmap, cliprect); + + // draw sprites + for (int i = 0; i < m_spriteram.bytes(); i += 4) + { + const int flags = m_spriteram[i + 0]; + int y = m_spriteram[i + 1] ^ 255; + int code = m_spriteram[i + 2] + ((flags & 0x20) << 3); + int x = m_spriteram[i + 3] * 2 + 72; + + int xflip = flags & 0x80; + int yflip = flags & 0x40; + const bool doubled = false;// flags & 0x10; + const bool wide = flags & 0x08; + int code2 = code; + + const int color = ((flags >> 1) & 0x03) | ((code >> 5) & 0x04) | (code & 0x08) | (m_sprite_palette * 16); + gfx_element *gfx = m_gfxdecode->gfx(1); + + if (m_cocktail_flip) + { + x = 64 * 8 - gfx->width() - x; + y = 32 * 8 - gfx->height() - y; + if (wide) y -= gfx->height(); + xflip = !xflip; + yflip = !yflip; + } + + if (wide) + { + if (yflip) + code |= 0x10, code2 &= ~0x10; + else + code &= ~0x10, code2 |= 0x10; + + gfx->transpen(bitmap, cliprect, code2, color, xflip, yflip, x, y + gfx->height(), 0); + } + + if (flags & 0x10) + { + gfx->transpen(bitmap, cliprect, code2 + 16, color, xflip, yflip, x, y + gfx->height(), 0); + gfx->transpen(bitmap, cliprect, code2 + 16 * 2, color, xflip, yflip, x, y + 2 * gfx->height(), 0); + gfx->transpen(bitmap, cliprect, code2 + 16 * 3, color, xflip, yflip, x, y + 3 * gfx->height(), 0); + + } + + gfx->transpen(bitmap, cliprect, code, color, xflip, yflip, x, y, 0); + + if (doubled) i += 4; + } + + // draw the visible text layer + for (int sy = VISIBLE_Y_MIN / 8; sy < VISIBLE_Y_MAX / 8; sy++) + for (int sx = VISIBLE_X_MIN / 8; sx < VISIBLE_X_MAX / 8; sx++) + { + const int x = m_cocktail_flip ? (63 * 8 - 8 * sx) : 8 * sx; + const int y = m_cocktail_flip ? (31 * 8 - 8 * sy) : 8 * sy; + + const int offs = sx + sy * 64; + m_gfxdecode->gfx(0)->transpen(bitmap, cliprect, + m_videoram[offs] + 256 * m_char_bank, + ((m_videoram[offs] & 0xf0) >> 4) + m_char_palette * 16, + m_cocktail_flip, m_cocktail_flip, x, y, 0); + } + return 0; +} + + +// machine INPUT_CHANGED_MEMBER(fcombat_state::coin_inserted) { - /* coin insertion causes an NMI */ + // coin insertion causes an NMI m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); } -/* is it protection? */ +// is it protection? u8 fcombat_state::protection_r() { - /* Must match ONE of these values after a "and $3E" intruction : + /* Must match ONE of these values after a "and $3E" instruction : 76F0: 1E 04 2E 26 34 32 3A 16 3E 36 @@ -61,11 +361,11 @@ u8 fcombat_state::protection_r() } -/* same as exerion again */ +// same as exerion again u8 fcombat_state::port01_r() { - /* the cocktail flip bit muxes between ports 0 and 1 */ + // the cocktail flip bit muxes between ports 0 and 1 return m_io_in[m_cocktail_flip ? 1 : 0]->read(); } @@ -88,7 +388,7 @@ void fcombat_state::eb00_w(u8 data) } -// terrain info (ec00=x, ed00=y, return val in e300 +// terrain info (ec00=x, ed00=y, return val in e300) void fcombat_state::ec00_w(u8 data) { @@ -105,7 +405,7 @@ u8 fcombat_state::e300_r() const int wx = (m_tx + m_fcombat_sh) / 16; const int wy = (m_ty * 2 + m_fcombat_sv) / 16; - return m_user2_region[wx * 32 * 16 + wy]; + return m_terrain_rom[wx * 32 * 16 + wy]; } void fcombat_state::ee00_w(u8 data) @@ -116,14 +416,14 @@ void fcombat_state::main_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0xc000, 0xc7ff).ram(); - map(0xd000, 0xd7ff).ram().share("videoram"); - map(0xd800, 0xd8ff).ram().share("spriteram"); + map(0xd000, 0xd7ff).ram().share(m_videoram); + map(0xd800, 0xd8ff).ram().share(m_spriteram); map(0xe000, 0xe000).r(FUNC(fcombat_state::port01_r)); map(0xe100, 0xe100).portr("DSW0"); map(0xe200, 0xe200).portr("DSW1"); map(0xe300, 0xe300).r(FUNC(fcombat_state::e300_r)); map(0xe400, 0xe400).r(FUNC(fcombat_state::protection_r)); // protection? - map(0xe800, 0xe800).w(FUNC(fcombat_state::videoreg_w)); // at least bit 0 for flip screen and joystick input multiplexor + map(0xe800, 0xe800).w(FUNC(fcombat_state::videoreg_w)); // at least bit 0 for flip screen and joystick input multiplexer map(0xe900, 0xe900).w(FUNC(fcombat_state::e900_w)); map(0xea00, 0xea00).w(FUNC(fcombat_state::ea00_w)); map(0xeb00, 0xeb00).w(FUNC(fcombat_state::eb00_w)); @@ -155,7 +455,7 @@ void fcombat_state::audio_map(address_map &map) *************************************/ static INPUT_PORTS_START( fcombat ) - PORT_START("IN0") /* player 1 inputs (muxed on 0xe000) */ + PORT_START("IN0") // player 1 inputs (muxed on 0xe000) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) @@ -165,7 +465,7 @@ static INPUT_PORTS_START( fcombat ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 ) - PORT_START("IN1") /* player 2 inputs (muxed on 0xe000) */ + PORT_START("IN1") // player 2 inputs (muxed on 0xe000) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) @@ -175,7 +475,7 @@ static INPUT_PORTS_START( fcombat ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 ) - PORT_START("DSW0") /* dip switches (0xe100) */ + PORT_START("DSW0") // dip switches (0xe100) PORT_DIPNAME( 0x07, 0x02, DEF_STR( Lives ) ) PORT_DIPSETTING( 0x00, "1" ) PORT_DIPSETTING( 0x01, "2" ) @@ -198,7 +498,7 @@ static INPUT_PORTS_START( fcombat ) PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x80, DEF_STR( Cocktail ) ) - PORT_START("DSW1") /* dip switches/VBLANK (0xe200) */ + PORT_START("DSW1") // dip switches/VBLANK (0xe200) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen") PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) ) // related to vblank PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) @@ -211,7 +511,7 @@ static INPUT_PORTS_START( fcombat ) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, fcombat_state,coin_inserted, 0) + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, fcombat_state, coin_inserted, 0) INPUT_PORTS_END @@ -247,9 +547,9 @@ static const gfx_layout spritelayout = static GFXDECODE_START( gfx_fcombat ) - GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 64 ) - GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 256, 64 ) - GFXDECODE_ENTRY( "gfx3", 0, spritelayout, 512, 64 ) + GFXDECODE_ENTRY( "fgtiles", 0, charlayout, 0, 64 ) + GFXDECODE_ENTRY( "sprites", 0, spritelayout, 256, 64 ) + GFXDECODE_ENTRY( "bgtiles", 0, spritelayout, 512, 64 ) GFXDECODE_END @@ -286,32 +586,32 @@ void fcombat_state::machine_reset() void fcombat_state::fcombat(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, 10000000/3); + // basic machine hardware + Z80(config, m_maincpu, CPU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &fcombat_state::main_map); - z80_device &audiocpu(Z80(config, "audiocpu", 10000000/3)); + z80_device &audiocpu(Z80(config, "audiocpu", CPU_CLOCK)); audiocpu.set_addrmap(AS_PROGRAM, &fcombat_state::audio_map); - /* video hardware */ + // video hardware screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(FCOMBAT_PIXEL_CLOCK, FCOMBAT_HTOTAL, FCOMBAT_HBEND, FCOMBAT_HBSTART, FCOMBAT_VTOTAL, FCOMBAT_VBEND, FCOMBAT_VBSTART); + screen.set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART); screen.set_screen_update(FUNC(fcombat_state::screen_update)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_fcombat); - PALETTE(config, m_palette, FUNC(fcombat_state::fcombat_palette), 256*3, 32); + PALETTE(config, m_palette, FUNC(fcombat_state::fcombat_palette), 256 * 3, 32); - /* audio hardware */ + // audio hardware SPEAKER(config, "mono").front_center(); GENERIC_LATCH_8(config, "soundlatch"); - YM2149(config, "ay1", 1500000).add_route(ALL_OUTPUTS, "mono", 0.12); + YM2149(config, "ay1", 1'500'000).add_route(ALL_OUTPUTS, "mono", 0.12); // TODO: should this and the following be CPU_CLOCK / 2? - YM2149(config, "ay2", 1500000).add_route(ALL_OUTPUTS, "mono", 0.12); + YM2149(config, "ay2", 1'500'000).add_route(ALL_OUTPUTS, "mono", 0.12); - YM2149(config, "ay3", 1500000).add_route(ALL_OUTPUTS, "mono", 0.12); + YM2149(config, "ay3", 1'500'000).add_route(ALL_OUTPUTS, "mono", 0.12); } /************************************* @@ -322,65 +622,65 @@ void fcombat_state::fcombat(machine_config &config) void fcombat_state::init_fcombat() { - /* allocate some temporary space */ + // allocate some temporary space std::vector temp(0x10000); - /* make a temporary copy of the character data */ + // make a temporary copy of the character data u8 *src = &temp[0]; - u8 *dst = memregion("gfx1")->base(); - u32 length = memregion("gfx1")->bytes(); + u8 *dst = memregion("fgtiles")->base(); + u32 length = memregion("fgtiles")->bytes(); memcpy(src, dst, length); - /* decode the characters */ - /* the bits in the ROM are ordered: n8-n7 n6 n5 n4-v2 v1 v0 n3-n2 n1 n0 h2 */ - /* we want them ordered like this: n8-n7 n6 n5 n4-n3 n2 n1 n0-v2 v1 v0 h2 */ + /* decode the characters + the bits in the ROM are ordered: n8-n7 n6 n5 n4-v2 v1 v0 n3-n2 n1 n0 h2 + we want them ordered like this: n8-n7 n6 n5 n4-n3 n2 n1 n0-v2 v1 v0 h2 */ for (u32 oldaddr = 0; oldaddr < length; oldaddr++) { - u32 newaddr = ((oldaddr ) & 0x1f00) | /* keep n8-n4 */ - ((oldaddr << 3) & 0x00f0) | /* move n3-n0 */ - ((oldaddr >> 4) & 0x000e) | /* move v2-v0 */ - ((oldaddr ) & 0x0001); /* keep h2 */ + u32 newaddr = ((oldaddr ) & 0x1f00) | // keep n8-n4 + ((oldaddr << 3) & 0x00f0) | // move n3-n0 + ((oldaddr >> 4) & 0x000e) | // move v2-v0 + ((oldaddr ) & 0x0001); // keep h2 dst[newaddr] = src[oldaddr]; } - /* make a temporary copy of the sprite data */ + // make a temporary copy of the sprite data src = &temp[0]; - dst = memregion("gfx2")->base(); - length = memregion("gfx2")->bytes(); + dst = memregion("sprites")->base(); + length = memregion("sprites")->bytes(); memcpy(src, dst, length); - /* decode the sprites */ - /* the bits in the ROMs are ordered: n9 n8 n3 n7-n6 n5 n4 v3-v2 v1 v0 n2-n1 n0 h3 h2 */ - /* we want them ordered like this: n9 n8 n7 n6-n5 n4 n3 n2-n1 n0 v3 v2-v1 v0 h3 h2 */ + /* decode the sprites + the bits in the ROMs are ordered: n9 n8 n3 n7-n6 n5 n4 v3-v2 v1 v0 n2-n1 n0 h3 h2 + we want them ordered like this: n9 n8 n7 n6-n5 n4 n3 n2-n1 n0 v3 v2-v1 v0 h3 h2 */ for (u32 oldaddr = 0; oldaddr < length; oldaddr++) { - u32 newaddr = ((oldaddr << 1) & 0x3c00) | /* move n7-n4 */ - ((oldaddr >> 4) & 0x0200) | /* move n3 */ - ((oldaddr << 4) & 0x01c0) | /* move n2-n0 */ - ((oldaddr >> 3) & 0x003c) | /* move v3-v0 */ - ((oldaddr ) & 0xc003); /* keep n9-n8 h3-h2 */ + u32 newaddr = ((oldaddr << 1) & 0x3c00) | // move n7-n4 + ((oldaddr >> 4) & 0x0200) | // move n3 + ((oldaddr << 4) & 0x01c0) | // move n2-n0 + ((oldaddr >> 3) & 0x003c) | // move v3-v0 + ((oldaddr ) & 0xc003); // keep n9-n8 h3-h2 dst[newaddr] = src[oldaddr]; } - /* make a temporary copy of the character data */ + // make a temporary copy of the character data src = &temp[0]; - dst = memregion("gfx3")->base(); - length = memregion("gfx3")->bytes(); + dst = memregion("bgtiles")->base(); + length = memregion("bgtiles")->bytes(); memcpy(src, dst, length); - /* decode the characters */ - /* the bits in the ROM are ordered: n8-n7 n6 n5 n4-v2 v1 v0 n3-n2 n1 n0 h2 */ - /* we want them ordered like this: n8-n7 n6 n5 n4-n3 n2 n1 n0-v2 v1 v0 h2 */ + /* decode the characters + the bits in the ROM are ordered: n8-n7 n6 n5 n4-v2 v1 v0 n3-n2 n1 n0 h2 + we want them ordered like this: n8-n7 n6 n5 n4-n3 n2 n1 n0-v2 v1 v0 h2 */ for (u32 oldaddr = 0; oldaddr < length; oldaddr++) { - u32 newaddr = ((oldaddr << 1) & 0x3c00) | /* move n7-n4 */ - ((oldaddr >> 4) & 0x0200) | /* move n3 */ - ((oldaddr << 4) & 0x01c0) | /* move n2-n0 */ - ((oldaddr >> 3) & 0x003c) | /* move v3-v0 */ - ((oldaddr ) & 0xc003); /* keep n9-n8 h3-h2 */ + u32 newaddr = ((oldaddr << 1) & 0x3c00) | // move n7-n4 + ((oldaddr >> 4) & 0x0200) | // move n3 + ((oldaddr << 4) & 0x01c0) | // move n2-n0 + ((oldaddr >> 3) & 0x003c) | // move v3-v0 + ((oldaddr ) & 0xc003); // keep n9-n8 h3-h2 dst[newaddr] = src[oldaddr]; } @@ -397,8 +697,8 @@ void fcombat_state::init_fcombat() src = &temp[0]; - dst = memregion("user2")->base(); - length = memregion("user2")->bytes(); + dst = memregion("terrain_info")->base(); + length = memregion("terrain_info")->bytes(); memcpy(src, dst, length); for (u32 oldaddr = 0; oldaddr < 32; oldaddr++) @@ -413,31 +713,34 @@ ROM_START( fcombat ) ROM_LOAD( "fcombat2.t9", 0x0000, 0x4000, CRC(30cb0c14) SHA1(8b5b6a4efaca2f138709184725e9e0e0b9cfc4c7) ) ROM_LOAD( "fcombat3.10t", 0x4000, 0x4000, CRC(e8511da0) SHA1(bab5c9244c970b97c025381c37ad372aa3b5cddf) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* 64k for the second CPU */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "fcombat1.t5", 0x0000, 0x4000, CRC(a0cc1216) SHA1(3a8963ffde2ff4a3f428369133f94bb37717cae5) ) - ROM_REGION( 0x02000, "gfx1", 0 ) - ROM_LOAD( "fcombat7.l11", 0x00000, 0x2000, CRC(401061b5) SHA1(09dd23e86a56db8021e14432aced0eaf013fefe2) ) /* fg chars */ + ROM_REGION( 0x02000, "fgtiles", 0 ) + ROM_LOAD( "fcombat7.l11", 0x00000, 0x2000, CRC(401061b5) SHA1(09dd23e86a56db8021e14432aced0eaf013fefe2) ) - ROM_REGION( 0x0c000, "gfx2", 0 ) - ROM_LOAD( "fcombat8.d10", 0x00000, 0x4000, CRC(e810941e) SHA1(19ae85af0bf245caf3afe10d65e618cfb47d33c2) ) /* sprites */ + ROM_REGION( 0x0c000, "sprites", 0 ) + ROM_LOAD( "fcombat8.d10", 0x00000, 0x4000, CRC(e810941e) SHA1(19ae85af0bf245caf3afe10d65e618cfb47d33c2) ) ROM_LOAD( "fcombat9.d11", 0x04000, 0x4000, CRC(f95988e6) SHA1(25876652decca7ec1e9b37a16536c15ca2d1cb12) ) ROM_LOAD( "fcomba10.d12", 0x08000, 0x4000, CRC(908f154c) SHA1(b3761ee60d4a5ea36376759875105d23c57b4bf2) ) - ROM_REGION( 0x04000, "gfx3", 0 ) + ROM_REGION( 0x04000, "bgtiles", 0 ) ROM_LOAD( "fcombat6.f3", 0x00000, 0x4000, CRC(97282729) SHA1(72db0593551c2d15631341bf621b96013b46ce72) ) ROM_REGION( 0x04000, "bgdata", 0 ) - ROM_LOAD( "fcombat5.l3", 0x00000, 0x4000, CRC(96194ca7) SHA1(087d6ac8f93f087cb5e378dbe9a8cfcffa2cdddc) ) /* bg data */ + ROM_LOAD( "fcombat5.l3", 0x00000, 0x4000, CRC(96194ca7) SHA1(087d6ac8f93f087cb5e378dbe9a8cfcffa2cdddc) ) - ROM_REGION( 0x04000, "user2", 0 ) - ROM_LOAD( "fcombat4.p3", 0x00000, 0x4000, CRC(efe098ab) SHA1(fe64a5e9170835d242368109b1b221b0f8090e7e) ) /* terrain info */ + ROM_REGION( 0x04000, "terrain_info", 0 ) + ROM_LOAD( "fcombat4.p3", 0x00000, 0x4000, CRC(efe098ab) SHA1(fe64a5e9170835d242368109b1b221b0f8090e7e) ) ROM_REGION( 0x0420, "proms", 0 ) - ROM_LOAD( "fcprom_a.c2", 0x0000, 0x0020, CRC(7ac480f0) SHA1(f491fe4da19d8c037e3733a5836de35cc438907e) ) /* palette */ - ROM_LOAD( "fcprom_d.k12", 0x0020, 0x0100, CRC(9a348250) SHA1(faf8db4c42adee07795d06bea20704f8c51090ff) ) /* fg char lookup table */ - ROM_LOAD( "fcprom_b.c4", 0x0120, 0x0100, CRC(ac9049f6) SHA1(57aa5b5df3e181bad76149745a422c3dd1edad49) ) /* sprite lookup table */ - ROM_LOAD( "fcprom_c.a9", 0x0220, 0x0100, CRC(768ac120) SHA1(ceede1d6cbeae08da96ef52bdca2718a839d88ab) ) /* bg char mixer */ + ROM_LOAD( "fcprom_a.c2", 0x0000, 0x0020, CRC(7ac480f0) SHA1(f491fe4da19d8c037e3733a5836de35cc438907e) ) // palette + ROM_LOAD( "fcprom_d.k12", 0x0020, 0x0100, CRC(9a348250) SHA1(faf8db4c42adee07795d06bea20704f8c51090ff) ) // fg char lookup table + ROM_LOAD( "fcprom_b.c4", 0x0120, 0x0100, CRC(ac9049f6) SHA1(57aa5b5df3e181bad76149745a422c3dd1edad49) ) // sprite lookup table + ROM_LOAD( "fcprom_c.a9", 0x0220, 0x0100, CRC(768ac120) SHA1(ceede1d6cbeae08da96ef52bdca2718a839d88ab) ) // bg char mixer ROM_END +} // anonymous namespace + + GAME( 1985, fcombat, 0, fcombat, fcombat, fcombat_state, init_fcombat, ROT90, "Jaleco", "Field Combat", MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/jaleco/fcombat.h b/src/mame/jaleco/fcombat.h deleted file mode 100644 index 7189e3159dc..00000000000 --- a/src/mame/jaleco/fcombat.h +++ /dev/null @@ -1,102 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -#ifndef MAME_INCLUDES_FCOMBAT_H -#define MAME_INCLUDES_FCOMBAT_H - -#pragma once - -#include "emupal.h" -#include "tilemap.h" - - -// this is copied from Exerion, but it should be correct -#define FCOMBAT_MASTER_CLOCK (20000000) -#define FCOMBAT_CPU_CLOCK (FCOMBAT_MASTER_CLOCK / 6) -#define FCOMBAT_AY8910_CLOCK (FCOMBAT_CPU_CLOCK / 2) -#define FCOMBAT_PIXEL_CLOCK (FCOMBAT_MASTER_CLOCK / 3) -#define FCOMBAT_HCOUNT_START (0x58) -#define FCOMBAT_HTOTAL (512-FCOMBAT_HCOUNT_START) -#define FCOMBAT_HBEND (12*8) // ?? -#define FCOMBAT_HBSTART (52*8) // -#define FCOMBAT_VTOTAL (256) -#define FCOMBAT_VBEND (16) -#define FCOMBAT_VBSTART (240) - -#define BACKGROUND_X_START 32 -#define BACKGROUND_X_START_FLIP 72 - -#define VISIBLE_X_MIN (12*8) -#define VISIBLE_X_MAX (52*8) -#define VISIBLE_Y_MIN (2*8) -#define VISIBLE_Y_MAX (30*8) - - -class fcombat_state : public driver_device -{ -public: - fcombat_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_videoram(*this, "videoram"), - m_spriteram(*this, "spriteram"), - m_bgdata_rom(*this, "bgdata"), - m_user2_region(*this, "user2"), - m_io_in(*this, "IN%u", 0U), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette") - { } - - void fcombat(machine_config &config); - - void init_fcombat(); - - DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); - -private: - /* memory pointers */ - required_shared_ptr m_videoram; - required_shared_ptr m_spriteram; - required_region_ptr m_bgdata_rom; - required_region_ptr m_user2_region; - - required_ioport_array<2> m_io_in; - - /* video-related */ - tilemap_t *m_bgmap = nullptr; - u8 m_cocktail_flip = 0U; - u8 m_char_palette = 0U; - u8 m_sprite_palette = 0U; - u8 m_char_bank = 0U; - - /* misc */ - int m_fcombat_sh = 0; - int m_fcombat_sv = 0; - int m_tx = 0; - int m_ty = 0; - - /* devices */ - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - - u8 protection_r(); - u8 port01_r(); - void e900_w(u8 data); - void ea00_w(u8 data); - void eb00_w(u8 data); - void ec00_w(u8 data); - void ed00_w(u8 data); - u8 e300_r(); - void ee00_w(u8 data); - void videoreg_w(u8 data); - TILE_GET_INFO_MEMBER(get_bg_tile_info); - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - void fcombat_palette(palette_device &palette) const; - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void audio_map(address_map &map); - void main_map(address_map &map); -}; - -#endif // MAME_INCLUDES_FCOMBAT_H diff --git a/src/mame/jaleco/fcombat_v.cpp b/src/mame/jaleco/fcombat_v.cpp deleted file mode 100644 index 5491f184732..00000000000 --- a/src/mame/jaleco/fcombat_v.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -/*************************************************************************** - - Jaleco fcombat - -***************************************************************************/ - -#include "emu.h" -#include "fcombat.h" - - -TILE_GET_INFO_MEMBER(fcombat_state::get_bg_tile_info) -{ - int tileno, palno; //32*16 x 32 - - //palno = (tile_index - (tile_index / 32 * 16) * 32 * 16) / 32; - - tileno = m_bgdata_rom[tile_index]; - palno = 0x18; //m_user2_region[tile_index] >> 3; - tileinfo.set(2, tileno, palno, 0); -} - - -/*************************************************************************** - - Convert the color PROMs into a more useable format. - - The palette PROM is connected to the RGB output this way: - - bit 7 -- 220 ohm resistor -- BLUE - -- 470 ohm resistor -- BLUE - -- 220 ohm resistor -- GREEN - -- 470 ohm resistor -- GREEN - -- 1 kohm resistor -- GREEN - -- 220 ohm resistor -- RED - -- 470 ohm resistor -- RED - bit 0 -- 1 kohm resistor -- RED - -***************************************************************************/ - -void fcombat_state::fcombat_palette(palette_device &palette) const -{ - const u8 *color_prom = memregion("proms")->base(); - - // create a lookup table for the palette - for (int i = 0; i < 0x20; 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); - const u8 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); - const u8 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - - // blue component - bit0 = 0; - bit1 = BIT(color_prom[i], 6); - bit2 = BIT(color_prom[i], 7); - const u8 b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - - palette.set_indirect_color(i, rgb_t(r, g, b)); - } - - // color_prom now points to the beginning of the lookup table - color_prom += 0x20; - - // fg chars/sprites - for (int i = 0; i < 0x200; i++) - { - const u8 ctabentry = (color_prom[(i & 0x1c0) | ((i & 3) << 4) | ((i >> 2) & 0x0f)] & 0x0f) | 0x10; - palette.set_pen_indirect(i, ctabentry); - } - - // bg chars (this is not the full story... there are four layers mixed using another PROM - for (int i = 0x200; i < 0x300; i++) - { - const u8 ctabentry = color_prom[i] & 0x0f; - palette.set_pen_indirect(i, ctabentry); - } -} - - -/************************************* - * - * Video system startup - * - *************************************/ - -void fcombat_state::video_start() -{ - m_bgmap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(fcombat_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32 * 8 * 2, 32); -} - - -/************************************* - * - * Video register I/O - * - *************************************/ - -void fcombat_state::videoreg_w(u8 data) -{ - /* bit 0 = flip screen and joystick input multiplexor */ - m_cocktail_flip = data & 1; - - /* bits 1-2 char lookup table bank */ - m_char_palette = (data & 0x06) >> 1; - - /* bits 3 char bank */ - m_char_bank = (data & 0x08) >> 3; - - /* bits 4-5 unused */ - - /* bits 6-7 sprite lookup table bank */ - m_sprite_palette = 0;//(data & 0xc0) >> 6; - //popmessage("%08x",data); -} - - -u32 fcombat_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - /* draw background */ - m_bgmap->set_scrolly(0, m_fcombat_sh); - m_bgmap->set_scrollx(0, m_fcombat_sv - 24); - - m_bgmap->mark_all_dirty(); - m_bgmap->draw(screen, bitmap, cliprect, 0, 0); - //draw_background(bitmap, cliprect); - - /* draw sprites */ - for (int i = 0; i < m_spriteram.bytes(); i += 4) - { - int flags = m_spriteram[i + 0]; - int y = m_spriteram[i + 1] ^ 255; - int code = m_spriteram[i + 2] + ((flags & 0x20) << 3); - int x = m_spriteram[i + 3] * 2 + 72; - - int xflip = flags & 0x80; - int yflip = flags & 0x40; - bool doubled = false;// flags & 0x10; - const bool wide = flags & 0x08; - int code2 = code; - - int color = ((flags >> 1) & 0x03) | ((code >> 5) & 0x04) | (code & 0x08) | (m_sprite_palette * 16); - gfx_element *gfx = m_gfxdecode->gfx(1); - - if (m_cocktail_flip) - { - x = 64 * 8 - gfx->width() - x; - y = 32 * 8 - gfx->height() - y; - if (wide) y -= gfx->height(); - xflip = !xflip; - yflip = !yflip; - } - - if (wide) - { - if (yflip) - code |= 0x10, code2 &= ~0x10; - else - code &= ~0x10, code2 |= 0x10; - - gfx->transpen(bitmap,cliprect, code2, color, xflip, yflip, x, y + gfx->height(), 0); - } - - if (flags & 0x10) - { - gfx->transpen(bitmap,cliprect, code2 + 16, color, xflip, yflip, x, y + gfx->height(), 0); - gfx->transpen(bitmap,cliprect, code2 + 16 * 2, color, xflip, yflip, x, y + 2 * gfx->height(), 0); - gfx->transpen(bitmap,cliprect, code2 + 16 * 3, color, xflip, yflip, x, y + 3 * gfx->height(), 0); - - } - - gfx->transpen(bitmap,cliprect, code, color, xflip, yflip, x, y, 0); - - if (doubled) i += 4; - } - - /* draw the visible text layer */ - for (int sy = VISIBLE_Y_MIN/8; sy < VISIBLE_Y_MAX/8; sy++) - for (int sx = VISIBLE_X_MIN/8; sx < VISIBLE_X_MAX/8; sx++) - { - int x = m_cocktail_flip ? (63 * 8 - 8 * sx) : 8 * sx; - int y = m_cocktail_flip ? (31 * 8 - 8 * sy) : 8 * sy; - - const int offs = sx + sy * 64; - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, - m_videoram[offs] + 256 * m_char_bank, - ((m_videoram[offs] & 0xf0) >> 4) + m_char_palette * 16, - m_cocktail_flip, m_cocktail_flip, x, y, 0); - } - return 0; -} diff --git a/src/mame/jaleco/ginganin.cpp b/src/mame/jaleco/ginganin.cpp index f8521aaffac..fefacb2847d 100644 --- a/src/mame/jaleco/ginganin.cpp +++ b/src/mame/jaleco/ginganin.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Luca Elia +// copyright-holders: Luca Elia + /*************************************************************************** Ginga NinkyouDen @@ -13,7 +14,7 @@ OSC. : 6.000MHz 3.579545MHz * CTC uses MB-8873E (MC-6840) - Interesting routines (main cpu) + Interesting routines (main CPU) ------------------------------- Interrupts: 1-7] d17a: clears 20018 etc. @@ -22,7 +23,7 @@ f4b2 print string: a1->(char)*,0x25(%) d7.w=color a0->screen (30000) f5d6 print 7 digit BCD number: d0.l to (a1)+ color $3000 - Interesting locations (main cpu) + Interesting locations (main CPU) -------------------------------- 20014 # of players (1-2) @@ -57,28 +58,371 @@ f5d6 print 7 digit BCD number: d0.l to (a1)+ color $3000 ***************************************************************************/ #include "emu.h" -#include "ginganin.h" #include "cpu/m68000/m68000.h" #include "cpu/m6809/m6809.h" #include "machine/6840ptm.h" +#include "machine/gen_latch.h" #include "sound/ay8910.h" #include "sound/ymopl.h" +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +// configurable logging +#define LOG_VREGS (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_VREGS) + +#include "logmacro.h" + +#define LOGVREGS(...) LOGMASKED(LOG_VREGS, __VA_ARGS__) + + +namespace { + +class ginganin_state : public driver_device +{ +public: + ginganin_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_txtram(*this, "txtram"), + m_spriteram(*this, "spriteram"), + m_vregs(*this, "vregs"), + m_fgram(*this, "fgram"), + m_bgrom(*this, "bgrom"), + m_maincpu(*this, "maincpu"), + m_audiocpu(*this, "audiocpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_soundlatch(*this, "soundlatch") + { } + + void ginganin(machine_config &config); + + void init_ginganin(); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + // memory pointers + required_shared_ptr m_txtram; + required_shared_ptr m_spriteram; + required_shared_ptr m_vregs; + required_shared_ptr m_fgram; + + required_region_ptr m_bgrom; + + // video-related + tilemap_t *m_bg_tilemap = nullptr; + tilemap_t *m_fg_tilemap = nullptr; + tilemap_t *m_tx_tilemap = nullptr; + u16 m_layers_ctrl = 0; + u8 m_flipscreen = 0; +#ifdef MAME_DEBUG + int m_posx = 0; + int m_posy = 0; +#endif + + // devices + required_device m_maincpu; + required_device m_audiocpu; + required_device m_gfxdecode; + required_device m_palette; + required_device m_soundlatch; + + void fgram_w(offs_t offset, u16 data, u16 mem_mask = ~0); + void txtram_w(offs_t offset, u16 data, u16 mem_mask = ~0); + void vregs_w(offs_t offset, u16 data, u16 mem_mask = ~0); + TILE_GET_INFO_MEMBER(get_bg_tile_info); + TILE_GET_INFO_MEMBER(get_fg_tile_info); + TILE_GET_INFO_MEMBER(get_txt_tile_info); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void main_map(address_map &map); + void sound_map(address_map &map); +}; + + +// video + +/************************************************************************** + +Note: if MAME_DEBUG is defined, pressing Z with: + + Q shows background + W shows foreground + E shows frontmost (text) layer + A shows sprites + + Keys can be used together! + + +[Screen] + Visible Size: 256H x 240V + Dynamic Colors: 256 x 4 + Color Space: 16R x 16G x 16B + +[Scrolling layers] + Format (all layers): Offset: 0x400 0x000 + Bit: fedc---- -------- Color + ----ba98 76543210 Code + + [Background] + Size: 8192 x 512 (static: stored in ROM) + Scrolling: X,Y (registers: $60006.w, $60004.w) + Tiles Size: 16 x 16 + Tiles Number: $400 + Colors: $300-$3ff + + [Foreground] + Size: 4096 x 512 + Scrolling: X,Y (registers: $60002.w, $60000.w) + Tiles Size: 16 x 16 + Tiles Number: $400 + Colors: $200-$2ff + + [Frontmost] + Size: 256 x 256 + Scrolling: - + Tiles Size: 8 x 8 + Tiles Number: $200 + Colors: $000-$0ff + + +[Sprites] + On Screen: 256 + In ROM: $a00 + Colors: $100-$1ff + Format: See Below + + +**************************************************************************/ + +/*************************************************************************** + + Callbacks for the TileMap code + +***************************************************************************/ + + +// Background - Resides in ROM + +static constexpr u8 BG_GFX = 0; +static constexpr u16 BG_NX = (16 * 32); +static constexpr u8 BG_NY = (16 * 2); + +TILE_GET_INFO_MEMBER(ginganin_state::get_bg_tile_info) +{ + const u32 code = m_bgrom[2 * tile_index + 0] * 256 + m_bgrom[2 * tile_index + 1]; + tileinfo.set(BG_GFX, + code, + code >> 12, + 0); +} + + +// Foreground - Resides in RAM + +static constexpr u8 FG_GFX = 1; +static constexpr u16 FG_NX = (16 * 16); +static constexpr u8 FG_NY = (16 * 2); + +TILE_GET_INFO_MEMBER(ginganin_state::get_fg_tile_info) +{ + const u16 code = m_fgram[tile_index]; + tileinfo.set(FG_GFX, + code, + code >> 12, + 0); +} + +void ginganin_state::fgram_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_fgram[offset]); + m_fg_tilemap->mark_tile_dirty(offset); +} + + +// Frontmost (text) Layer - Resides in RAM + +static constexpr u8 TXT_GFX = 2; +static constexpr u8 TXT_NX = 32; +static constexpr u8 TXT_NY = 32; + +TILE_GET_INFO_MEMBER(ginganin_state::get_txt_tile_info) +{ + const u16 code = m_txtram[tile_index]; + tileinfo.set(TXT_GFX, + code, + code >> 12, + 0); +} + +void ginganin_state::txtram_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_txtram[offset]); + m_tx_tilemap->mark_tile_dirty(offset); +} -#define MAIN_CLOCK XTAL(6'000'000) -#define SOUND_CLOCK XTAL(3'579'545) +void ginganin_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_bg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, BG_NX, BG_NY); + m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_fg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, FG_NX, FG_NY); + m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_txt_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, TXT_NX, TXT_NY); + + m_fg_tilemap->set_transparent_pen(15); + m_tx_tilemap->set_transparent_pen(15); +} + + +void ginganin_state::vregs_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_vregs[offset]); + data = m_vregs[offset]; + + switch (offset) + { + case 0: + m_fg_tilemap->set_scrolly(0, data); + break; + case 1: + m_fg_tilemap->set_scrollx(0, data); + break; + case 2: + m_bg_tilemap->set_scrolly(0, data); + break; + case 3: + m_bg_tilemap->set_scrollx(0, data); + break; + case 4: + m_layers_ctrl = data; + break; +/* case 5: + * break; + */ + case 6: + m_flipscreen = !(data & 1); + machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0); + break; + case 7: + m_soundlatch->write(data); + m_audiocpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); + break; + default: + LOGVREGS("CPU #0 PC %06X : Warning, videoreg %04X <- %04X\n", m_maincpu->pc(), offset, data); + } +} + + + +/* --------------------------[ Sprites Format ]---------------------------- +Offset: Values: Format: -/* -** -** Main cpu data -** -*/ +0000.w y position fedc ba9- ---- ---- unused + ---- ---8 ---- ---- subtract 256 + ---- ---- 7654 3210 position +0002.w x position See above + +0004.w code f--- ---- ---- ---- y flip + -e-- ---- ---- ---- x flip + --dc ---- ---- ---- unused? + ---- ba98 7654 3210 code + +0006.w colour fedc ---- ---- ---- colour code + ---- ba98 7654 3210 unused? + +------------------------------------------------------------------------ */ + +void ginganin_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int offs = 0; offs < (m_spriteram.bytes() >> 1); offs += 4) + { + int y = m_spriteram[offs + 0]; + int x = m_spriteram[offs + 1]; + const u32 code = m_spriteram[offs + 2]; + const u16 attr = m_spriteram[offs + 3]; + int flipx = code & 0x4000; + int flipy = code & 0x8000; + + x = (x & 0xff) - (x & 0x100); + y = (y & 0xff) - (y & 0x100); + + if (m_flipscreen) + { + x = 240 - x; + y = 240 - y; + flipx = !flipx; + flipy = !flipy; + } + + m_gfxdecode->gfx(3)->transpen(bitmap, cliprect, + code & 0x3fff, + attr >> 12, + flipx, flipy, + x, y, 15); + + } +} + + +u32 ginganin_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + int layers_ctrl1 = m_layers_ctrl; + +#ifdef MAME_DEBUG +if (machine().input().code_pressed(KEYCODE_Z)) +{ + int msk = 0; + + if (machine().input().code_pressed(KEYCODE_Q)) { msk |= 0xfff1;} + if (machine().input().code_pressed(KEYCODE_W)) { msk |= 0xfff2;} + if (machine().input().code_pressed(KEYCODE_E)) { msk |= 0xfff4;} + if (machine().input().code_pressed(KEYCODE_A)) { msk |= 0xfff8;} + if (msk != 0) layers_ctrl1 &= msk; + +#define SETSCROLL \ + m_bg_tilemap->set_scrollx(0, m_posx); \ + m_bg_tilemap->set_scrolly(0, m_posy); \ + m_fg_tilemap->set_scrollx(0, m_posx); \ + m_fg_tilemap->set_scrolly(0, m_posy); \ + popmessage("B>%04X:%04X F>%04X:%04X",m_posx%(BG_NX*16),m_posy%(BG_NY*16),m_posx%(FG_NX*16),m_posy%(FG_NY*16)); + + if (machine().input().code_pressed(KEYCODE_L)) { m_posx +=8; SETSCROLL } + if (machine().input().code_pressed(KEYCODE_J)) { m_posx -=8; SETSCROLL } + if (machine().input().code_pressed(KEYCODE_K)) { m_posy +=8; SETSCROLL } + if (machine().input().code_pressed(KEYCODE_I)) { m_posy -=8; SETSCROLL } + if (machine().input().code_pressed(KEYCODE_H)) { m_posx = m_posy = 0; SETSCROLL } + +} +#endif + + if (layers_ctrl1 & 1) + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + else + bitmap.fill(0, cliprect); + + if (layers_ctrl1 & 2) + m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + if (layers_ctrl1 & 8) + draw_sprites(bitmap, cliprect); + if (layers_ctrl1 & 4) + m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); + + return 0; +} + + +// machine void ginganin_state::main_map(address_map &map) { @@ -86,22 +430,16 @@ void ginganin_state::main_map(address_map &map) // looks a debugging left-over for GFX patching (causes state garbage if hooked as RAM write mirror) map(0x000000, 0x01ffff).rom().nopw(); map(0x020000, 0x023fff).ram(); - map(0x030000, 0x0307ff).ram().w(FUNC(ginganin_state::txtram_w)).share("txtram"); - map(0x040000, 0x0407ff).ram().share("spriteram"); + map(0x030000, 0x0307ff).ram().w(FUNC(ginganin_state::txtram_w)).share(m_txtram); + map(0x040000, 0x0407ff).ram().share(m_spriteram); map(0x050000, 0x0507ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); - map(0x060000, 0x06000f).ram().w(FUNC(ginganin_state::vregs_w)).share("vregs"); - map(0x068000, 0x06bfff).ram().w(FUNC(ginganin_state::fgram_w)).share("fgram"); + map(0x060000, 0x06000f).ram().w(FUNC(ginganin_state::vregs_w)).share(m_vregs); + map(0x068000, 0x06bfff).ram().w(FUNC(ginganin_state::fgram_w)).share(m_fgram); map(0x070000, 0x070001).portr("P1_P2"); map(0x070002, 0x070003).portr("DSW"); } -/* -** -** Sound cpu data -** -*/ - void ginganin_state::sound_map(address_map &map) { map(0x0000, 0x07ff).ram(); @@ -113,10 +451,8 @@ void ginganin_state::sound_map(address_map &map) } -/* Input Ports */ - static INPUT_PORTS_START( ginganin ) - PORT_START("P1_P2") /* 70000.w */ + PORT_START("P1_P2") // 70000.w PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY @@ -134,7 +470,7 @@ static INPUT_PORTS_START( ginganin ) PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_START2 ) - PORT_START("DSW") /* 70002.w */ + PORT_START("DSW") // 70002.w PORT_DIPNAME( 0x0007, 0x0007, DEF_STR( Coin_A ) ) PORT_DIPSETTING( 0x0000, DEF_STR( 5C_1C ) ) PORT_DIPSETTING( 0x0004, DEF_STR( 4C_1C ) ) @@ -171,10 +507,10 @@ static INPUT_PORTS_START( ginganin ) PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Cabinet ) ) PORT_DIPSETTING( 0x0000, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x0800, DEF_STR( Cocktail ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) /* probably unused */ + PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) // probably unused PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) /* it does something */ + PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) // it does something PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Flip_Screen ) ) @@ -187,18 +523,11 @@ INPUT_PORTS_END -/* -** -** Gfx data -** -*/ - - static GFXDECODE_START( gfx_ginganin ) - GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*3, 16 ) /* [0] bg */ - GFXDECODE_ENTRY( "gfx2", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*2, 16 ) /* [1] fg */ - GFXDECODE_ENTRY( "gfx3", 0, gfx_8x8x4_packed_msb, 256*0, 16 ) /* [2] txt */ - GFXDECODE_ENTRY( "gfx4", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*1, 16 ) /* [3] sprites */ + GFXDECODE_ENTRY( "bgtiles", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*3, 16 ) + GFXDECODE_ENTRY( "fgtiles", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*2, 16 ) + GFXDECODE_ENTRY( "txttiles", 0, gfx_8x8x4_packed_msb, 256*0, 16 ) + GFXDECODE_ENTRY( "sprites", 0, gfx_8x8x4_col_2x2_group_packed_msb, 256*1, 16 ) GFXDECODE_END @@ -214,27 +543,24 @@ void ginganin_state::machine_reset() m_flipscreen = 0; } -WRITE_LINE_MEMBER(ginganin_state::ptm_irq) -{ - m_audiocpu->set_input_line(0, state ? ASSERT_LINE : CLEAR_LINE); -} - - void ginganin_state::ginganin(machine_config &config) { - /* basic machine hardware */ + static constexpr XTAL MAIN_CLOCK = XTAL(6'000'000); + static constexpr XTAL SOUND_CLOCK = XTAL(3'579'545); + + // basic machine hardware M68000(config, m_maincpu, MAIN_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &ginganin_state::main_map); - m_maincpu->set_vblank_int("screen", FUNC(ginganin_state::irq1_line_hold)); /* ? (vectors 1-7 contain the same address) */ + m_maincpu->set_vblank_int("screen", FUNC(ginganin_state::irq1_line_hold)); // ? (vectors 1-7 contain the same address) MC6809(config, m_audiocpu, SOUND_CLOCK); // MBL68B09? m_audiocpu->set_addrmap(AS_PROGRAM, &ginganin_state::sound_map); - ptm6840_device &ptm(PTM6840(config, "6840ptm", SOUND_CLOCK/2)); + ptm6840_device &ptm(PTM6840(config, "6840ptm", SOUND_CLOCK / 2)); ptm.set_external_clocks(0, 0, 0); - ptm.o1_callback().set(FUNC(ginganin_state::ptm_irq)); + ptm.o1_callback().set_inputline(m_audiocpu, 0); - /* 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)); @@ -246,14 +572,14 @@ void ginganin_state::ginganin(machine_config &config) GFXDECODE(config, m_gfxdecode, m_palette, gfx_ginganin); PALETTE(config, m_palette).set_format(palette_device::RGBx_444, 1024); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); GENERIC_LATCH_8(config, m_soundlatch); YM2149(config, "psg", SOUND_CLOCK / 2).add_route(ALL_OUTPUTS, "mono", 0.10); - Y8950(config, "ymsnd", SOUND_CLOCK).add_route(ALL_OUTPUTS, "mono", 1.0); /* The Y8950 is basically a YM3526 with ADPCM built in */ + Y8950(config, "ymsnd", SOUND_CLOCK).add_route(ALL_OUTPUTS, "mono", 1.0); // The Y8950 is basically a YM3526 with ADPCM built in } @@ -265,70 +591,70 @@ void ginganin_state::ginganin(machine_config &config) ***************************************************************************/ ROM_START( ginganin ) - ROM_REGION( 0x20000, "maincpu", 0 ) /* main cpu */ + ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD16_BYTE( "gn_02.bin", 0x00000, 0x10000, CRC(4a4e012f) SHA1(7c94a5b6b71e037af355f3aa4623be1f585db8dc) ) ROM_LOAD16_BYTE( "gn_01.bin", 0x00001, 0x10000, CRC(30256fcb) SHA1(dc15e0da88ae5cabe0150f7290508c3d58c06c11) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound cpu */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "gn_05.bin", 0x00000, 0x10000, CRC(e76e10e7) SHA1(b16f10a1a01b7b04221c9bf1b0d157e936bc5fb5) ) - ROM_REGION( 0x20000, "gfx1", 0 ) - ROM_LOAD( "gn_15.bin", 0x000000, 0x10000, CRC(1b8ac9fb) SHA1(1e5ee2a565fa262f1e48c1088d84c6f42d84b4e3) ) /* bg */ + ROM_REGION( 0x20000, "bgtiles", 0 ) + ROM_LOAD( "gn_15.bin", 0x000000, 0x10000, CRC(1b8ac9fb) SHA1(1e5ee2a565fa262f1e48c1088d84c6f42d84b4e3) ) ROM_LOAD( "gn_14.bin", 0x010000, 0x10000, CRC(e73fe668) SHA1(fa39fddd7448d3fc6b539506e33b951db205afa1) ) - ROM_REGION( 0x20000, "gfx2", 0 ) - ROM_LOAD( "gn_12.bin", 0x000000, 0x10000, CRC(c134a1e9) SHA1(8bace0f0169e61f1b7254393fa9cad6dca09c335) ) /* fg */ + ROM_REGION( 0x20000, "fgtiles", 0 ) + ROM_LOAD( "gn_12.bin", 0x000000, 0x10000, CRC(c134a1e9) SHA1(8bace0f0169e61f1b7254393fa9cad6dca09c335) ) ROM_LOAD( "gn_13.bin", 0x010000, 0x10000, CRC(1d3bec21) SHA1(305823c78cad9288f918178e1c24cb0459ba2a6e) ) - ROM_REGION( 0x04000, "gfx3", 0 ) - ROM_LOAD( "gn_10.bin", 0x000000, 0x04000, CRC(ae371b2d) SHA1(d5e03b085586ed2bf40713f432bcf12e07318226) ) /* txt */ + ROM_REGION( 0x04000, "txttiles", 0 ) + ROM_LOAD( "gn_10.bin", 0x000000, 0x04000, CRC(ae371b2d) SHA1(d5e03b085586ed2bf40713f432bcf12e07318226) ) - ROM_REGION( 0x50000, "gfx4", 0 ) - ROM_LOAD( "gn_06.bin", 0x000000, 0x10000, CRC(bdc65835) SHA1(53222fc3ec15e641289abb754657b0d59b88b66b) ) /* sprites */ + ROM_REGION( 0x50000, "sprites", 0 ) + ROM_LOAD( "gn_06.bin", 0x000000, 0x10000, CRC(bdc65835) SHA1(53222fc3ec15e641289abb754657b0d59b88b66b) ) ROM_CONTINUE( 0x040000, 0x10000 ) ROM_LOAD( "gn_07.bin", 0x010000, 0x10000, CRC(c2b8eafe) SHA1(a042a200efd4e7361e9ab516085c9fc8067e28b4) ) ROM_LOAD( "gn_08.bin", 0x020000, 0x10000, CRC(f7c73c18) SHA1(102700e2217bcd1532af56ee6a00ad608c8217db) ) ROM_LOAD( "gn_09.bin", 0x030000, 0x10000, CRC(a5e07c3b) SHA1(cdda02cd847330575612cb33d1bb38a5d50a3e6d) ) - ROM_REGION( 0x08000, "bgrom", 0 ) /* background tilemaps */ + ROM_REGION( 0x08000, "bgrom", 0 ) ROM_LOAD( "gn_11.bin", 0x00000, 0x08000, CRC(f0d0e605) SHA1(0c541e8e036573be1d99ecb71fdb4568ca8cc269) ) - ROM_REGION( 0x20000, "ymsnd", 0 ) /* samples */ + ROM_REGION( 0x20000, "ymsnd", 0 ) ROM_LOAD( "gn_04.bin", 0x00000, 0x10000, CRC(0ed9133b) SHA1(77f628e8ec28016efac2d906146865ca4ec54bd5) ) ROM_LOAD( "gn_03.bin", 0x10000, 0x10000, CRC(f1ba222c) SHA1(780c0bd0045bac1e1bb3209576383db90504fbf3) ) ROM_END ROM_START( ginganina ) - ROM_REGION( 0x20000, "maincpu", 0 ) /* main cpu */ + ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD16_BYTE( "2.bin", 0x00000, 0x10000, CRC(6da1d8a3) SHA1(ea81f2934fa7901563e886f3d600edd08ec0ea24) ) ROM_LOAD16_BYTE( "1.bin", 0x00001, 0x10000, CRC(0bd32d59) SHA1(5ab2c0e4a1d9cafbd3448d981103508debd7ed96) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound cpu */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "gn_05.bin", 0x00000, 0x10000, CRC(e76e10e7) SHA1(b16f10a1a01b7b04221c9bf1b0d157e936bc5fb5) ) - ROM_REGION( 0x20000, "gfx1", 0 ) - ROM_LOAD( "gn_15.bin", 0x000000, 0x10000, CRC(1b8ac9fb) SHA1(1e5ee2a565fa262f1e48c1088d84c6f42d84b4e3) ) /* bg */ + ROM_REGION( 0x20000, "bgtiles", 0 ) + ROM_LOAD( "gn_15.bin", 0x000000, 0x10000, CRC(1b8ac9fb) SHA1(1e5ee2a565fa262f1e48c1088d84c6f42d84b4e3) ) ROM_LOAD( "gn_14.bin", 0x010000, 0x10000, CRC(e73fe668) SHA1(fa39fddd7448d3fc6b539506e33b951db205afa1) ) - ROM_REGION( 0x20000, "gfx2", 0 ) - ROM_LOAD( "gn_12.bin", 0x000000, 0x10000, CRC(c134a1e9) SHA1(8bace0f0169e61f1b7254393fa9cad6dca09c335) ) /* fg */ + ROM_REGION( 0x20000, "fgtiles", 0 ) + ROM_LOAD( "gn_12.bin", 0x000000, 0x10000, CRC(c134a1e9) SHA1(8bace0f0169e61f1b7254393fa9cad6dca09c335) ) ROM_LOAD( "gn_13.bin", 0x010000, 0x10000, CRC(1d3bec21) SHA1(305823c78cad9288f918178e1c24cb0459ba2a6e) ) - ROM_REGION( 0x04000, "gfx3", 0 ) - ROM_LOAD( "10.bin", 0x000000, 0x04000, CRC(48a20745) SHA1(69855b0402feca4ba9632142e569c652ca05b9fa) ) /* txt */ + ROM_REGION( 0x04000, "txttiles", 0 ) + ROM_LOAD( "10.bin", 0x000000, 0x04000, CRC(48a20745) SHA1(69855b0402feca4ba9632142e569c652ca05b9fa) ) - ROM_REGION( 0x50000, "gfx4", 0 ) - ROM_LOAD( "gn_06.bin", 0x000000, 0x10000, CRC(bdc65835) SHA1(53222fc3ec15e641289abb754657b0d59b88b66b) ) /* sprites */ + ROM_REGION( 0x50000, "sprites", 0 ) + ROM_LOAD( "gn_06.bin", 0x000000, 0x10000, CRC(bdc65835) SHA1(53222fc3ec15e641289abb754657b0d59b88b66b) ) ROM_CONTINUE( 0x040000, 0x10000 ) ROM_LOAD( "gn_07.bin", 0x010000, 0x10000, CRC(c2b8eafe) SHA1(a042a200efd4e7361e9ab516085c9fc8067e28b4) ) ROM_LOAD( "gn_08.bin", 0x020000, 0x10000, CRC(f7c73c18) SHA1(102700e2217bcd1532af56ee6a00ad608c8217db) ) ROM_LOAD( "gn_09.bin", 0x030000, 0x10000, CRC(a5e07c3b) SHA1(cdda02cd847330575612cb33d1bb38a5d50a3e6d) ) - ROM_REGION( 0x08000, "bgrom", 0 ) /* background tilemaps */ + ROM_REGION( 0x08000, "bgrom", 0 ) ROM_LOAD( "gn_11.bin", 0x00000, 0x08000, CRC(f0d0e605) SHA1(0c541e8e036573be1d99ecb71fdb4568ca8cc269) ) - ROM_REGION( 0x20000, "ymsnd", 0 ) /* samples */ + ROM_REGION( 0x20000, "ymsnd", 0 ) ROM_LOAD( "gn_04.bin", 0x00000, 0x10000, CRC(0ed9133b) SHA1(77f628e8ec28016efac2d906146865ca4ec54bd5) ) ROM_LOAD( "gn_03.bin", 0x10000, 0x10000, CRC(f1ba222c) SHA1(780c0bd0045bac1e1bb3209576383db90504fbf3) ) ROM_END @@ -337,13 +663,15 @@ ROM_END void ginganin_state::init_ginganin() { // pending full removal of this patch ... - /* main cpu patches */ + /* main CPU patches */ // u16 *rom = (u16 *)memregion("maincpu")->base(); - /* avoid writes to rom getting to the log */ + /* avoid writes to ROM getting to the log */ // rom[0x408 / 2] = 0x6000; // rom[0x40a / 2] = 0x001c; } +} // anonymous namespace + GAME( 1987, ginganin, 0, ginganin, ginganin, ginganin_state, init_ginganin, ROT0, "Jaleco", "Ginga NinkyouDen (set 1)", MACHINE_SUPPORTS_SAVE ) GAME( 1987, ginganina, ginganin, ginganin, ginganin, ginganin_state, init_ginganin, ROT0, "Jaleco", "Ginga NinkyouDen (set 2)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/jaleco/ginganin.h b/src/mame/jaleco/ginganin.h deleted file mode 100644 index 7e29df2468d..00000000000 --- a/src/mame/jaleco/ginganin.h +++ /dev/null @@ -1,81 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Luca Elia -/************************************************************************* - - Ginga NinkyouDen - -*************************************************************************/ -#ifndef MAME_INCLUDES_GINGANIN_H -#define MAME_INCLUDES_GINGANIN_H - -#pragma once - -#include "machine/gen_latch.h" -#include "emupal.h" -#include "tilemap.h" - -class ginganin_state : public driver_device -{ -public: - ginganin_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_txtram(*this, "txtram"), - m_spriteram(*this, "spriteram"), - m_vregs(*this, "vregs"), - m_fgram(*this, "fgram"), - m_bgrom(*this, "bgrom"), - m_maincpu(*this, "maincpu"), - m_audiocpu(*this, "audiocpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette"), - m_soundlatch(*this, "soundlatch") - { } - - void ginganin(machine_config &config); - - void init_ginganin(); - -private: - /* memory pointers */ - required_shared_ptr m_txtram; - required_shared_ptr m_spriteram; - required_shared_ptr m_vregs; - required_shared_ptr m_fgram; - - required_region_ptr m_bgrom; - - /* video-related */ - tilemap_t *m_bg_tilemap = nullptr; - tilemap_t *m_fg_tilemap = nullptr; - tilemap_t *m_tx_tilemap = nullptr; - int m_layers_ctrl = 0; - int m_flipscreen = 0; -#ifdef MAME_DEBUG - int m_posx = 0; - int m_posy = 0; -#endif - - /* devices */ - required_device m_maincpu; - required_device m_audiocpu; - required_device m_gfxdecode; - required_device m_palette; - required_device m_soundlatch; - - void fgram_w(offs_t offset, u16 data, u16 mem_mask = ~0); - void txtram_w(offs_t offset, u16 data, u16 mem_mask = ~0); - void vregs_w(offs_t offset, u16 data, u16 mem_mask = ~0); - DECLARE_WRITE_LINE_MEMBER(ptm_irq); - TILE_GET_INFO_MEMBER(get_bg_tile_info); - TILE_GET_INFO_MEMBER(get_fg_tile_info); - TILE_GET_INFO_MEMBER(get_txt_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 draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect); - void main_map(address_map &map); - void sound_map(address_map &map); -}; - -#endif // MAME_INCLUDES_GINGANIN_H diff --git a/src/mame/jaleco/ginganin_v.cpp b/src/mame/jaleco/ginganin_v.cpp deleted file mode 100644 index bf1b095feb3..00000000000 --- a/src/mame/jaleco/ginganin_v.cpp +++ /dev/null @@ -1,280 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Luca Elia -/************************************************************************** - - Ginga NinkyouDen - (C) 1987 Jaleco - - driver by Luca Elia (l.elia@tin.it) - - -Note: if MAME_DEBUG is defined, pressing Z with: - - Q shows background - W shows foreground - E shows frontmost (text) layer - A shows sprites - - Keys can be used togheter! - - -[Screen] - Visible Size: 256H x 240V - Dynamic Colors: 256 x 4 - Color Space: 16R x 16G x 16B - -[Scrolling layers] - Format (all layers): Offset: 0x400 0x000 - Bit: fedc---- -------- Color - ----ba98 76543210 Code - - [Background] - Size: 8192 x 512 (static: stored in ROM) - Scrolling: X,Y (registers: $60006.w, $60004.w) - Tiles Size: 16 x 16 - Tiles Number: $400 - Colors: $300-$3ff - - [Foreground] - Size: 4096 x 512 - Scrolling: X,Y (registers: $60002.w, $60000.w) - Tiles Size: 16 x 16 - Tiles Number: $400 - Colors: $200-$2ff - - [Frontmost] - Size: 256 x 256 - Scrolling: - - Tiles Size: 8 x 8 - Tiles Number: $200 - Colors: $000-$0ff - - -[Sprites] - On Screen: 256 - In ROM: $a00 - Colors: $100-$1ff - Format: See Below - - -**************************************************************************/ - -#include "emu.h" -#include "ginganin.h" - - -/*************************************************************************** - - Callbacks for the TileMap code - -***************************************************************************/ - - -/* Background - Resides in ROM */ - -#define BG_GFX (0) -#define BG_NX (16*32) -#define BG_NY (16*2) - -TILE_GET_INFO_MEMBER(ginganin_state::get_bg_tile_info) -{ - const u32 code = m_bgrom[2 * tile_index + 0] * 256 + m_bgrom[2 * tile_index + 1]; - tileinfo.set(BG_GFX, - code, - code >> 12, - 0); -} - - -/* Foreground - Resides in RAM */ - -#define FG_GFX (1) -#define FG_NX (16*16) -#define FG_NY (16*2) - -TILE_GET_INFO_MEMBER(ginganin_state::get_fg_tile_info) -{ - const u16 code = m_fgram[tile_index]; - tileinfo.set(FG_GFX, - code, - code >> 12, - 0); -} - -void ginganin_state::fgram_w(offs_t offset, u16 data, u16 mem_mask) -{ - COMBINE_DATA(&m_fgram[offset]); - m_fg_tilemap->mark_tile_dirty(offset); -} - - -/* Frontmost (text) Layer - Resides in RAM */ - -#define TXT_GFX (2) -#define TXT_NX (32) -#define TXT_NY (32) - -TILE_GET_INFO_MEMBER(ginganin_state::get_txt_tile_info) -{ - const u16 code = m_txtram[tile_index]; - tileinfo.set(TXT_GFX, - code, - code >> 12, - 0); -} - -void ginganin_state::txtram_w(offs_t offset, u16 data, u16 mem_mask) -{ - COMBINE_DATA(&m_txtram[offset]); - m_tx_tilemap->mark_tile_dirty(offset); -} - - -void ginganin_state::video_start() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_bg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, BG_NX, BG_NY); - m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_fg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, FG_NX, FG_NY); - m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(ginganin_state::get_txt_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, TXT_NX, TXT_NY); - - m_fg_tilemap->set_transparent_pen(15); - m_tx_tilemap->set_transparent_pen(15); -} - - -void ginganin_state::vregs_w(offs_t offset, u16 data, u16 mem_mask) -{ - COMBINE_DATA(&m_vregs[offset]); - data = m_vregs[offset]; - - switch (offset) - { - case 0: - m_fg_tilemap->set_scrolly(0, data); - break; - case 1: - m_fg_tilemap->set_scrollx(0, data); - break; - case 2: - m_bg_tilemap->set_scrolly(0, data); - break; - case 3: - m_bg_tilemap->set_scrollx(0, data); - break; - case 4: - m_layers_ctrl = data; - break; -/* case 5: - * break; - */ - case 6: - m_flipscreen = !(data & 1); - machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0); - break; - case 7: - m_soundlatch->write(data); - m_audiocpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); - break; - default: - logerror("CPU #0 PC %06X : Warning, videoreg %04X <- %04X\n", m_maincpu->pc(), offset, data); - } -} - - - -/* --------------------------[ Sprites Format ]---------------------------- - -Offset: Values: Format: - -0000.w y position fedc ba9- ---- ---- unused - ---- ---8 ---- ---- subtract 256 - ---- ---- 7654 3210 position - -0002.w x position See above - -0004.w code f--- ---- ---- ---- y flip - -e-- ---- ---- ---- x flip - --dc ---- ---- ---- unused? - ---- ba98 7654 3210 code - -0006.w colour fedc ---- ---- ---- colour code - ---- ba98 7654 3210 unused? - ------------------------------------------------------------------------- */ - -void ginganin_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect) -{ - for (int offs = 0; offs < (m_spriteram.bytes() >> 1); offs += 4) - { - int y = m_spriteram[offs + 0]; - int x = m_spriteram[offs + 1]; - const u32 code = m_spriteram[offs + 2]; - const u16 attr = m_spriteram[offs + 3]; - int flipx = code & 0x4000; - int flipy = code & 0x8000; - - x = (x & 0xff) - (x & 0x100); - y = (y & 0xff) - (y & 0x100); - - if (m_flipscreen) - { - x = 240 - x; - y = 240 - y; - flipx = !flipx; - flipy = !flipy; - } - - m_gfxdecode->gfx(3)->transpen(bitmap,cliprect, - code & 0x3fff, - attr >> 12, - flipx, flipy, - x,y,15); - - } -} - - -u32 ginganin_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int layers_ctrl1 = m_layers_ctrl; - -#ifdef MAME_DEBUG -if (machine().input().code_pressed(KEYCODE_Z)) -{ - int msk = 0; - - if (machine().input().code_pressed(KEYCODE_Q)) { msk |= 0xfff1;} - if (machine().input().code_pressed(KEYCODE_W)) { msk |= 0xfff2;} - if (machine().input().code_pressed(KEYCODE_E)) { msk |= 0xfff4;} - if (machine().input().code_pressed(KEYCODE_A)) { msk |= 0xfff8;} - if (msk != 0) layers_ctrl1 &= msk; - -#define SETSCROLL \ - m_bg_tilemap->set_scrollx(0, m_posx); \ - m_bg_tilemap->set_scrolly(0, m_posy); \ - m_fg_tilemap->set_scrollx(0, m_posx); \ - m_fg_tilemap->set_scrolly(0, m_posy); \ - popmessage("B>%04X:%04X F>%04X:%04X",m_posx%(BG_NX*16),m_posy%(BG_NY*16),m_posx%(FG_NX*16),m_posy%(FG_NY*16)); - - if (machine().input().code_pressed(KEYCODE_L)) { m_posx +=8; SETSCROLL } - if (machine().input().code_pressed(KEYCODE_J)) { m_posx -=8; SETSCROLL } - if (machine().input().code_pressed(KEYCODE_K)) { m_posy +=8; SETSCROLL } - if (machine().input().code_pressed(KEYCODE_I)) { m_posy -=8; SETSCROLL } - if (machine().input().code_pressed(KEYCODE_H)) { m_posx = m_posy = 0; SETSCROLL } - -} -#endif - - if (layers_ctrl1 & 1) - m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - else - bitmap.fill(0, cliprect); - - if (layers_ctrl1 & 2) - m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - if (layers_ctrl1 & 8) - draw_sprites(bitmap, cliprect); - if (layers_ctrl1 & 4) - m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); - - return 0; -} diff --git a/src/mame/jaleco/homerun.cpp b/src/mame/jaleco/homerun.cpp index 35e33c55ef6..538c3ff691b 100644 --- a/src/mame/jaleco/homerun.cpp +++ b/src/mame/jaleco/homerun.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Tomasz Slanina +// copyright-holders: Tomasz Slanina + /* Moero!! Pro Yakyuu Homerun Kyousou - (c) 1988 Jaleco Dynamic Shoot Kyousou - (c) 1988 Jaleco @@ -16,7 +17,7 @@ homerun, dynashot and ganjaja use an extra soundchip for playing voice/samples Todo : - - Dump homerun and dynashot sample rom + - Dump homerun and dynashot sample ROM - Improve controls/DIP switches - Fix sprite glitches in ganjaja Hop Step & Jump - Fix sample playing in ganjaja Saisho wa Goo. The words 'rock', 'paper', scissors' are not played? @@ -109,15 +110,238 @@ This version of Homerun is not dumped. */ #include "emu.h" -#include "homerun.h" #include "cpu/z80/z80.h" #include "machine/i8255.h" #include "sound/samples.h" +#include "sound/upd7759.h" #include "sound/ymopn.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { + +class homerun_state : public driver_device +{ +public: + homerun_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_videoram(*this, "videoram"), + m_spriteram(*this, "spriteram"), + m_d7756(*this, "d7756"), + m_samples(*this, "samples"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_mainbank(*this, "mainbank") + { } + + void ganjaja(machine_config &config); + void dynashot(machine_config &config); + void homerun(machine_config &config); + + DECLARE_READ_LINE_MEMBER(sprite0_r); + DECLARE_READ_LINE_MEMBER(homerun_d7756_busy_r); + DECLARE_CUSTOM_INPUT_MEMBER(ganjaja_hopper_status_r); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + required_device m_maincpu; + required_shared_ptr m_videoram; + required_shared_ptr m_spriteram; + required_device m_d7756; + optional_device m_samples; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + + required_memory_bank m_mainbank; + + u8 m_control = 0; + u8 m_sample = 0; + + tilemap_t *m_tilemap = nullptr; + u8 m_gfx_ctrl = 0; + u16 m_scrollx = 0; + u16 m_scrolly = 0; + + void control_w(u8 data); + void d7756_sample_w(u8 data); + void videoram_w(offs_t offset, u8 data); + void scrollhi_w(u8 data); + void scrolly_w(u8 data); + void scrollx_w(u8 data); + + static rgb_t homerun_RGB332(u32 raw); + TILE_GET_INFO_MEMBER(get_tile_info); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void banking_w(u8 data); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void io_map(address_map &map); + void mem_map(address_map &map); +}; + + +// video + +/**************************************************************************/ + +READ_LINE_MEMBER(homerun_state::sprite0_r) +{ + // sprite-0 vs background collision status, similar to NES + return (m_screen->vpos() > (m_spriteram[0] - 16 + 1)) ? 1 : 0; +} + +void homerun_state::scrollhi_w(u8 data) +{ + // d0: scroll y high bit + // d1: scroll x high bit + // other bits: ? + m_scrolly = (m_scrolly & 0xff) | (data << 8 & 0x100); + m_scrollx = (m_scrollx & 0xff) | (data << 7 & 0x100); +} + +void homerun_state::scrolly_w(u8 data) +{ + m_scrolly = (m_scrolly & 0xff00) | data; +} + +void homerun_state::scrollx_w(u8 data) +{ + m_scrollx = (m_scrollx & 0xff00) | data; +} + +void homerun_state::banking_w(u8 data) +{ + u8 const old = m_gfx_ctrl; + if (old ^ data) + { + if ((old ^ data) & 3) + { + // games do mid-screen gfx bank switching + int vpos = m_screen->vpos(); + m_screen->update_partial(vpos); + } + + // d0-d1: gfx bank + // d2-d4: ? + // d5-d7: prg bank + m_gfx_ctrl = data; + if ((old ^ m_gfx_ctrl) & 1) + m_tilemap->mark_all_dirty(); + + if ((old ^ m_gfx_ctrl) >> 5 & 7) + m_mainbank->set_entry(m_gfx_ctrl >> 5 & 7); + + } +} + +void homerun_state::videoram_w(offs_t offset, u8 data) +{ + m_videoram[offset] = data; + m_tilemap->mark_tile_dirty(offset & 0xfff); +} + +rgb_t homerun_state::homerun_RGB332(u32 raw) +{ + /* from PCB photo: + bit 7: 470 ohm resistor \ + bit 6: 220 ohm resistor - --> 470 ohm resistor --> blue + bit 5: 470 ohm resistor \ + bit 4: 220 ohm resistor - --> 470 ohm resistor --> green + bit 3: 1 kohm resistor / + bit 2: 470 ohm resistor \ + bit 1: 220 ohm resistor - --> 470 ohm resistor --> red + bit 0: 1 kohm resistor / + */ + + // let's implement it the old fashioned way until it's found out how exactly the resnet is hooked up + u8 bit0, bit1, bit2; + + bit0 = (raw >> 0) & 0x01; + bit1 = (raw >> 1) & 0x01; + bit2 = (raw >> 2) & 0x01; + int r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + bit0 = (raw >> 3) & 0x01; + bit1 = (raw >> 4) & 0x01; + bit2 = (raw >> 5) & 0x01; + int g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + bit0 = 0; + bit1 = (raw >> 6) & 0x01; + bit2 = (raw >> 7) & 0x01; + int b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + return rgb_t(r, g, b); +} + +/**************************************************************************/ + +TILE_GET_INFO_MEMBER(homerun_state::get_tile_info) +{ + u32 const tileno = (m_videoram[tile_index]) | ((m_videoram[tile_index | 0x1000] & 0x38) << 5) | ((m_gfx_ctrl & 1) << 11); + u16 const palno = (m_videoram[tile_index | 0x1000] & 0x07); + + tileinfo.set(0, tileno, palno, 0); +} +void homerun_state::video_start() +{ + m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(homerun_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); + + save_item(NAME(m_gfx_ctrl)); + save_item(NAME(m_scrolly)); + save_item(NAME(m_scrollx)); +} + + +void homerun_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4) + { + if (m_spriteram[offs + 0] == 0) + continue; + + int const sy = m_spriteram[offs + 0] - 16 + 1; + int const sx = m_spriteram[offs + 3]; + u32 const code = (m_spriteram[offs + 1]) | ((m_spriteram[offs + 2] & 0x8) << 5) | ((m_gfx_ctrl & 3) << 9); + u32 const color = (m_spriteram[offs + 2] & 0x07) | 8; + bool const flipx = (m_spriteram[offs + 2] & 0x40) >> 6; + bool const flipy = (m_spriteram[offs + 2] & 0x80) >> 7; + + if (sy >= 0) + { + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, sx, sy, 0); + + // wraparound x + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, sx - 256 , sy, 0); + } + } +} + +u32 homerun_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + m_tilemap->set_scrolly(0, m_scrolly); + m_tilemap->set_scrollx(0, m_scrollx); + + m_tilemap->draw(screen, bitmap, cliprect, 0, 0); + draw_sprites(bitmap, cliprect); + + return 0; +} + + +// machine + /*************************************************************************** I/O / Memory @@ -137,7 +361,7 @@ void homerun_state::control_w(u8 data) } if (m_samples != nullptr) { - // play MAME sample if a dump of the internal rom does not exist + // play MAME sample if a dump of the internal ROM does not exist if (data & 0x20 & ~m_control) m_samples->stop(0); @@ -164,9 +388,9 @@ void homerun_state::d7756_sample_w(u8 data) void homerun_state::mem_map(address_map &map) { map(0x0000, 0x3fff).rom(); - map(0x4000, 0x7fff).bankr("mainbank"); - map(0x8000, 0x9fff).ram().w(FUNC(homerun_state::videoram_w)).share("videoram"); - map(0xa000, 0xa0ff).ram().share("spriteram"); + map(0x4000, 0x7fff).bankr(m_mainbank); + map(0x8000, 0x9fff).ram().w(FUNC(homerun_state::videoram_w)).share(m_videoram); + map(0xa000, 0xa0ff).ram().share(m_spriteram); map(0xb000, 0xb03f).ram().w(m_palette, FUNC(palette_device::write8)).share("palette"); map(0xc000, 0xdfff).ram(); } @@ -189,11 +413,6 @@ READ_LINE_MEMBER(homerun_state::homerun_d7756_busy_r) return m_samples->playing(0) ? 0 : 1; } -READ_LINE_MEMBER(homerun_state::ganjaja_d7756_busy_r) -{ - return m_d7756->busy_r(); -} - CUSTOM_INPUT_MEMBER(homerun_state::ganjaja_hopper_status_r) { // gives hopper error if not 0 @@ -251,7 +470,7 @@ static INPUT_PORTS_START( homerun ) PORT_DIPSETTING( 0x80, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_2C ) ) -// The manuals shows the following DIPs but they don't appear to do anything +// The manual shows the following DIPs but they don't appear to do anything // so this could be for a different version which is not dumped. //..PORT_DIPNAME( 0x70, 0x70, "Difficulty" ) PORT_DIPLOCATION("DIPSW:5,6,7") //..PORT_DIPSETTING( 0x70, "1" ) @@ -313,7 +532,7 @@ static INPUT_PORTS_START( ganjaja ) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // ? PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(homerun_state, sprite0_r) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(homerun_state, ganjaja_d7756_busy_r) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("d7756", upd7756_device, busy_r) PORT_BIT( 0x36, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_START("IN1") @@ -357,7 +576,7 @@ INPUT_PORTS_END ***************************************************************************/ // homerun samples, taken from the Famicom version of Moero!! Pro Yakyuu -// note that this is the complete rom contents; not all samples are used in this game +// note that this is the complete ROM contents; not all samples are used in this game static const char *const homerun_sample_names[] = { "*homerun", @@ -405,8 +624,8 @@ static const gfx_layout spritelayout = }; static GFXDECODE_START( gfx_homerun ) - GFXDECODE_ENTRY( "gfx1", 0, gfxlayout, 0, 16 ) - GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 0, 16 ) + GFXDECODE_ENTRY( "tiles", 0, gfxlayout, 0, 16 ) + GFXDECODE_ENTRY( "sprites", 0, spritelayout, 0, 16 ) GFXDECODE_END @@ -435,8 +654,8 @@ void homerun_state::machine_reset() void homerun_state::dynashot(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(20'000'000)/4); + // basic machine hardware + Z80(config, m_maincpu, XTAL(20'000'000) / 4); m_maincpu->set_addrmap(AS_PROGRAM, &homerun_state::mem_map); m_maincpu->set_addrmap(AS_IO, &homerun_state::io_map); m_maincpu->set_vblank_int("screen", FUNC(homerun_state::irq0_line_hold)); @@ -446,32 +665,31 @@ void homerun_state::dynashot(machine_config &config) ppi.out_pb_callback().set(FUNC(homerun_state::scrolly_w)); ppi.out_pc_callback().set(FUNC(homerun_state::scrollx_w)); - /* video hardware */ + // video hardware SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(XTAL(20'000'000)/4,328,0,256,253,0,240); + m_screen->set_raw(XTAL(20'000'000) / 4, 328, 0, 256, 253, 0, 240); m_screen->set_screen_update(FUNC(homerun_state::screen_update)); m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_homerun); - PALETTE(config, m_palette).set_format(1, &homerun_state::homerun_RGB332, 16*4); + PALETTE(config, m_palette).set_format(1, &homerun_state::homerun_RGB332, 16 * 4); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); - ym2203_device &ymsnd(YM2203(config, "ymsnd", XTAL(20'000'000)/8)); + ym2203_device &ymsnd(YM2203(config, "ymsnd", XTAL(20'000'000) / 8)); ymsnd.port_a_read_callback().set_ioport("DSW"); ymsnd.port_b_write_callback().set(FUNC(homerun_state::banking_w)); ymsnd.add_route(ALL_OUTPUTS, "mono", 0.50); + + UPD7756(config, m_d7756); + m_d7756->add_route(ALL_OUTPUTS, "mono", 0.75); } void homerun_state::homerun(machine_config &config) { dynashot(config); - /* sound hardware */ - UPD7756(config, m_d7756); - m_d7756->add_route(ALL_OUTPUTS, "mono", 0.75); - SAMPLES(config, m_samples); m_samples->set_channels(1); m_samples->set_samples_names(homerun_sample_names); @@ -482,12 +700,8 @@ void homerun_state::ganjaja(machine_config &config) { dynashot(config); - /* basic machine hardware */ - m_maincpu->set_periodic_int(FUNC(homerun_state::irq0_line_hold), attotime::from_hz(4*60)); // ? - - /* sound hardware */ - UPD7756(config, m_d7756); - m_d7756->add_route(ALL_OUTPUTS, "mono", 0.75); + // basic machine hardware + m_maincpu->set_periodic_int(FUNC(homerun_state::irq0_line_hold), attotime::from_hz(4 * 60)); // ? } @@ -498,10 +712,10 @@ ROM_START( homerun ) ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD( "homerun.ic43", 0x00000, 0x20000, CRC(e759e476) SHA1(ad4f356ff26209033320a3e6353e4d4d9beb59c1) ) - ROM_REGION( 0x10000, "gfx1", 0 ) + ROM_REGION( 0x10000, "tiles", 0 ) ROM_LOAD( "homerun.ic60", 0x00000, 0x10000, CRC(69a720d1) SHA1(0f0a4877578f358e9e829ece8c31e23f01adcf83) ) - ROM_REGION( 0x20000, "gfx2", 0 ) + ROM_REGION( 0x20000, "sprites", 0 ) ROM_LOAD( "homerun.ic120", 0x00000, 0x20000, CRC(52f0709b) SHA1(19e675bcccadb774f60ec5929fc1fb5cf0d3f617) ) ROM_REGION( 0x08000, "d7756", ROMREGION_ERASE00 ) @@ -512,10 +726,10 @@ ROM_START( nhomerun ) ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD( "1.ic43", 0x00000, 0x20000, CRC(aed96d6d) SHA1(5cb3932f4cfa3f6c0134ac20a1747c562db31a65) ) - ROM_REGION( 0x10000, "gfx1", 0 ) + ROM_REGION( 0x10000, "tiles", 0 ) ROM_LOAD( "3.ic60", 0x00000, 0x10000, CRC(69a720d1) SHA1(0f0a4877578f358e9e829ece8c31e23f01adcf83) ) - ROM_REGION( 0x20000, "gfx2", 0 ) + ROM_REGION( 0x20000, "sprites", 0 ) ROM_LOAD( "2.ic120", 0x00000, 0x20000, CRC(57e9b757) SHA1(8190d690721005407a5b06d13d64e70301d1e925) ) ROM_REGION( 0x08000, "d7756", ROMREGION_ERASE00 ) @@ -526,10 +740,10 @@ ROM_START( dynashot ) ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD( "1.ic43", 0x00000, 0x20000, CRC(bf3c9586) SHA1(439effbda305f5fa265e5897c81dc1447e5d867d) ) - ROM_REGION( 0x10000, "gfx1", 0 ) + ROM_REGION( 0x10000, "tiles", 0 ) ROM_LOAD( "3.ic60", 0x00000, 0x10000, CRC(77d6a608) SHA1(a31ff343a5d4d6f20301c030ecc2e252149bcf9d) ) - ROM_REGION( 0x20000, "gfx2", 0 ) + ROM_REGION( 0x20000, "sprites", 0 ) ROM_LOAD( "2.ic120", 0x00000, 0x20000, CRC(bedf7b98) SHA1(cb6c5fcaf8df5f5c7636c3c8f79b9dda78e30c2e) ) ROM_REGION( 0x08000, "d7756", ROMREGION_ERASE00 ) @@ -541,16 +755,18 @@ ROM_START( ganjaja ) ROM_REGION( 0x20000, "maincpu", 0 ) ROM_LOAD( "1.ic43", 0x00000, 0x20000, CRC(dad57543) SHA1(dbd8b5cee33756ee5e3c41bf84c0f7141d3466dc) ) - ROM_REGION( 0x10000, "gfx1", 0 ) + ROM_REGION( 0x10000, "tiles", 0 ) ROM_LOAD( "ic60", 0x00000, 0x10000, CRC(855f6b28) SHA1(386411e88cf9bed54fe2073f0828d579cb1d04ee) ) - ROM_REGION( 0x20000, "gfx2", 0 ) + ROM_REGION( 0x20000, "sprites", 0 ) ROM_LOAD( "2.ic120", 0x00000, 0x20000, CRC(e65d4d57) SHA1(2ec9e5bdaa94b808573313b6eca657d798004b53) ) ROM_REGION( 0x08000, "d7756", 0 ) - ROM_LOAD( "d77p56cr.ic98", 0x00000, 0x08000, CRC(06a234ac) SHA1(b4ceff3f9f78551cf4a085642e162e33b266f067) ) /* D77P56CR OTP rom (One-Time Programmable, note the extra P) */ + ROM_LOAD( "d77p56cr.ic98", 0x00000, 0x08000, CRC(06a234ac) SHA1(b4ceff3f9f78551cf4a085642e162e33b266f067) ) // D77P56CR OTP rom (One-Time Programmable, note the extra P) ROM_END +} // anonymous namespace + // YEAR NAME PARENT MACHINE INPUT STATE INIT ROT COMPANY FULLNAME FLAGS GAME( 1988, nhomerun, 0, homerun, homerun, homerun_state, empty_init, ROT0, "Jaleco", "NEW Moero!! Pro Yakyuu Homerun Kyousou", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // same as below but harder? diff --git a/src/mame/jaleco/homerun.h b/src/mame/jaleco/homerun.h deleted file mode 100644 index 59ac37893d1..00000000000 --- a/src/mame/jaleco/homerun.h +++ /dev/null @@ -1,79 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -/************************************************************************* - - Jaleco Moero Pro Yakyuu Homerun hardware - -*************************************************************************/ - -#include "sound/upd7759.h" -#include "sound/samples.h" -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - -class homerun_state : public driver_device -{ -public: - homerun_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_videoram(*this, "videoram"), - m_spriteram(*this, "spriteram"), - m_d7756(*this, "d7756"), - m_samples(*this, "samples"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_mainbank(*this, "mainbank") - { } - - void ganjaja(machine_config &config); - void dynashot(machine_config &config); - void homerun(machine_config &config); - - DECLARE_READ_LINE_MEMBER(sprite0_r); - DECLARE_READ_LINE_MEMBER(homerun_d7756_busy_r); - DECLARE_READ_LINE_MEMBER(ganjaja_d7756_busy_r); - DECLARE_CUSTOM_INPUT_MEMBER(ganjaja_hopper_status_r); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - -private: - required_device m_maincpu; - required_shared_ptr m_videoram; - required_shared_ptr m_spriteram; - optional_device m_d7756; - optional_device m_samples; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - - required_memory_bank m_mainbank; - - u8 m_control = 0; - u8 m_sample = 0; - - tilemap_t *m_tilemap = nullptr; - int m_gfx_ctrl = 0; - int m_scrollx = 0; - int m_scrolly = 0; - - void control_w(u8 data); - void d7756_sample_w(u8 data); - void videoram_w(offs_t offset, u8 data); - void scrollhi_w(u8 data); - void scrolly_w(u8 data); - void scrollx_w(u8 data); - - static rgb_t homerun_RGB332(u32 raw); - TILE_GET_INFO_MEMBER(get_tile_info); - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void banking_w(u8 data); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void io_map(address_map &map); - void mem_map(address_map &map); -}; diff --git a/src/mame/jaleco/homerun_v.cpp b/src/mame/jaleco/homerun_v.cpp deleted file mode 100644 index bea65f63d29..00000000000 --- a/src/mame/jaleco/homerun_v.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tomasz Slanina -/************************************************************************* - - Jaleco Moero Pro Yakyuu Homerun hardware - -*************************************************************************/ - -#include "emu.h" -#include "homerun.h" - - -/**************************************************************************/ - -READ_LINE_MEMBER(homerun_state::sprite0_r) -{ - // sprite-0 vs background collision status, similar to NES - return (m_screen->vpos() > (m_spriteram[0] - 16 + 1)) ? 1 : 0; -} - -void homerun_state::scrollhi_w(u8 data) -{ - // d0: scroll y high bit - // d1: scroll x high bit - // other bits: ? - m_scrolly = (m_scrolly & 0xff) | (data << 8 & 0x100); - m_scrollx = (m_scrollx & 0xff) | (data << 7 & 0x100); -} - -void homerun_state::scrolly_w(u8 data) -{ - m_scrolly = (m_scrolly & 0xff00) | data; -} - -void homerun_state::scrollx_w(u8 data) -{ - m_scrollx = (m_scrollx & 0xff00) | data; -} - -void homerun_state::banking_w(u8 data) -{ - u8 const old = m_gfx_ctrl; - if (old ^ data) - { - if ((old ^ data) & 3) - { - // games do mid-screen gfx bank switching - int vpos = m_screen->vpos(); - m_screen->update_partial(vpos); - } - - // d0-d1: gfx bank - // d2-d4: ? - // d5-d7: prg bank - m_gfx_ctrl = data; - if ((old ^ m_gfx_ctrl) & 1) - m_tilemap->mark_all_dirty(); - - if ((old ^ m_gfx_ctrl) >> 5 & 7) - m_mainbank->set_entry(m_gfx_ctrl >> 5 & 7); - - } -} - -void homerun_state::videoram_w(offs_t offset, u8 data) -{ - m_videoram[offset] = data; - m_tilemap->mark_tile_dirty(offset & 0xfff); -} - -rgb_t homerun_state::homerun_RGB332(u32 raw) -{ - /* from PCB photo: - bit 7: 470 ohm resistor \ - bit 6: 220 ohm resistor - --> 470 ohm resistor --> blue - bit 5: 470 ohm resistor \ - bit 4: 220 ohm resistor - --> 470 ohm resistor --> green - bit 3: 1 kohm resistor / - bit 2: 470 ohm resistor \ - bit 1: 220 ohm resistor - --> 470 ohm resistor --> red - bit 0: 1 kohm resistor / - */ - - // let's implement it the old fashioned way until it's found out how exactly the resnet is hooked up - u8 bit0, bit1, bit2; - - bit0 = (raw >> 0) & 0x01; - bit1 = (raw >> 1) & 0x01; - bit2 = (raw >> 2) & 0x01; - int r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - bit0 = (raw >> 3) & 0x01; - bit1 = (raw >> 4) & 0x01; - bit2 = (raw >> 5) & 0x01; - int g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - bit0 = 0; - bit1 = (raw >> 6) & 0x01; - bit2 = (raw >> 7) & 0x01; - int b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - - return rgb_t(r, g, b); -} - -/**************************************************************************/ - -TILE_GET_INFO_MEMBER(homerun_state::get_tile_info) -{ - u32 const tileno = (m_videoram[tile_index]) | ((m_videoram[tile_index | 0x1000] & 0x38) << 5) | ((m_gfx_ctrl & 1) << 11); - u16 const palno = (m_videoram[tile_index | 0x1000] & 0x07); - - tileinfo.set(0, tileno, palno, 0); -} - - -void homerun_state::video_start() -{ - m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(homerun_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); - - save_item(NAME(m_gfx_ctrl)); - save_item(NAME(m_scrolly)); - save_item(NAME(m_scrollx)); -} - - -void homerun_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - for (int offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4) - { - if (m_spriteram[offs + 0] == 0) - continue; - - int const sy = m_spriteram[offs + 0] - 16 + 1; - int const sx = m_spriteram[offs + 3]; - u32 const code = (m_spriteram[offs + 1]) | ((m_spriteram[offs + 2] & 0x8) << 5) | ((m_gfx_ctrl & 3) << 9); - u32 const color = (m_spriteram[offs + 2] & 0x07) | 8; - bool const flipx = (m_spriteram[offs + 2] & 0x40) >> 6; - bool const flipy = (m_spriteram[offs + 2] & 0x80) >> 7; - - if (sy >= 0) - { - m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, sx, sy, 0); - - // wraparound x - m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, color, flipx, flipy, sx - 256 , sy, 0); - } - } -} - -u32 homerun_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - m_tilemap->set_scrolly(0, m_scrolly); - m_tilemap->set_scrollx(0, m_scrollx); - - m_tilemap->draw(screen, bitmap, cliprect, 0, 0); - draw_sprites(bitmap, cliprect); - - return 0; -} diff --git a/src/mame/jaleco/momoko.cpp b/src/mame/jaleco/momoko.cpp index dc7901cc926..70af846da76 100644 --- a/src/mame/jaleco/momoko.cpp +++ b/src/mame/jaleco/momoko.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Uki +// copyright-holders: Uki + /***************************************************************************** Momoko 120% (c) 1986 Jaleco @@ -12,18 +13,18 @@ Notes -Real machine has some bugs.(escalator bug, sprite garbage) -It is not emulation bug. +The real machine has some bugs(escalator bug, sprite garbage). +They are not emulation bugs. Flipped screen looks wrong, but it is correct. Note that the game-breaking escalator bug only happens on an 8-way joystick, -it's safe to assume that this game dedicated cpanel was 4-way. +it's safe to assume that this game dedicated control panel was 4-way. Stephh's notes (based on the game Z80 code and some tests) : - Accoding to the "initialisation" routine (code at 0x2a23), - the "Bonus Life" Dip Switches shall be coded that way : + the "Bonus Life" Dip Switches shall be coded this way : PORT_DIPNAME( 0x03, 0x03, "1st Bonus Life" ) PORT_DIPSETTING( 0x01, "20k" ) @@ -46,16 +47,385 @@ Stephh's notes (based on the game Z80 code and some tests) : *****************************************************************************/ #include "emu.h" -#include "momoko.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" #include "machine/watchdog.h" #include "sound/ymopn.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" +namespace { + +class momoko_state : public driver_device +{ +public: + momoko_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_spriteram(*this, "spriteram"), + m_videoram(*this, "videoram"), + m_bg_scrolly(*this, "bg_scrolly"), + m_bg_scrollx(*this, "bg_scrollx"), + m_bg_gfx(*this, "bg_gfx"), + m_bg_map(*this, "bg_map"), + m_bg_col_map(*this, "bg_col_map"), + m_fg_map(*this, "fg_map"), + m_proms(*this, "proms"), + m_bgbank(*this, "bgbank"), + m_io_fake(*this, "FAKE"), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette") + { } + + void momoko(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + // memory pointers + required_shared_ptr m_spriteram; + required_shared_ptr m_videoram; + required_shared_ptr m_bg_scrolly; + required_shared_ptr m_bg_scrollx; + required_region_ptr m_bg_gfx; + required_region_ptr m_bg_map; + required_region_ptr m_bg_col_map; + required_region_ptr m_fg_map; + required_region_ptr m_proms; + required_memory_bank m_bgbank; + required_ioport m_io_fake; + + // devices + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_palette; + + // video-related + u8 m_fg_scrollx = 0; + u8 m_fg_scrolly = 0; + u8 m_fg_select = 0; + u8 m_text_scrolly = 0; + u8 m_text_mode = 0; + u8 m_bg_select = 0; + u8 m_bg_priority = 0; + u8 m_bg_mask = 0; + u8 m_fg_mask = 0; + u8 m_flipscreen = 0; + + void bg_read_bank_w(u8 data); + void fg_scrollx_w(u8 data); + void fg_scrolly_w(u8 data); + void fg_select_w(u8 data); + void text_scrolly_w(u8 data); + void text_mode_w(u8 data); + void bg_scrollx_w(offs_t offset, u8 data); + void bg_scrolly_w(offs_t offset, u8 data); + void bg_select_w(u8 data); + void bg_priority_w(u8 data); + void flipscreen_w(u8 data); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_bg_pri(bitmap_ind16 &bitmap, int chr, int col, int flipx, int flipy, int x, int y, int pri); + void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int start, int end, int flip); + void draw_text_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip); + void draw_fg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip); + void draw_bg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip, bool high); + + void main_map(address_map &map); + void sound_map(address_map &map); +}; + + +// video + +/******************************************************************************* + + Video consists of + - Sprites + - 2x ROM based tilemaps (bg and fg) with priority over some sprites + - 1x RAM based tilemap (text layer) (no wrapping?) + + TODO: + - update to use tilemap system? + - check if any of this is common Jaleco/NMK etc. hardware and use shared + devices if possible + +*******************************************************************************/ + +void momoko_state::fg_scrollx_w(u8 data) +{ + m_fg_scrollx = data; +} + +void momoko_state::fg_scrolly_w(u8 data) +{ + m_fg_scrolly = data; +} + +void momoko_state::fg_select_w(u8 data) +{ + m_fg_select = data & 0x0f; + m_fg_mask = data & 0x10; +} + +void momoko_state::text_scrolly_w(u8 data) +{ + m_text_scrolly = data; +} + +void momoko_state::text_mode_w(u8 data) +{ + m_text_mode = data; +} + +void momoko_state::bg_scrollx_w(offs_t offset, u8 data) +{ + m_bg_scrollx[offset] = data; +} + +void momoko_state::bg_scrolly_w(offs_t offset, u8 data) +{ + m_bg_scrolly[offset] = data; +} + +void momoko_state::bg_select_w(u8 data) +{ + m_bg_select = data & 0x0f; + m_bg_mask = data & 0x10; +} + +void momoko_state::bg_priority_w(u8 data) +{ + m_bg_priority = data & 0x01; +} + +void momoko_state::flipscreen_w(u8 data) +{ + m_flipscreen = data & 0x01; +} + +/****************************************************************************/ + +void momoko_state::draw_bg_pri(bitmap_ind16 &bitmap, int chr, int col, int flipx, int flipy, int x, int y, int pri) +{ + for (int sy = 0; sy < 8; sy++) + { + const u32 gfxadr = chr * 16 + sy * 2; + for (int xx = 0; xx < 2; xx++) + { + u8 d0 = m_bg_gfx[gfxadr + xx * 4096]; + u8 d1 = m_bg_gfx[gfxadr + xx * 4096 + 1]; + + for (int sx = 0; sx < 4; sx++) + { + const u8 dot = (d0 & 0x08) | ((d0 & 0x80) >> 5) | ((d1 & 0x08) >> 2) | ((d1 & 0x80) >> 7); + const int px = (flipx == 0) ? (sx + xx * 4 + x) : (7 - sx - xx * 4 + x); + const int py = (flipy == 0) ? (sy + y) : (7 - sy + y); + + if (dot >= pri) + bitmap.pix(py, px) = col * 16 + dot + 256; + + d0 <<= 1; + d1 <<= 1; + } + } + } +} + + +void momoko_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int start, int end, int flip) +{ + for (int offs = start; offs < end; offs += 4) + { + int px, py; + u32 chr = m_spriteram[offs + 1] | ((m_spriteram[offs + 2] & 0x60) << 3); + chr = ((chr & 0x380) << 1) | (chr & 0x7f); + const int col = m_spriteram[offs + 2] & 0x07; + const int fx = ((m_spriteram[offs + 2] & 0x10) >> 4) ^ flip; + const int fy = ((m_spriteram[offs + 2] & 0x08) >> 3) ^ flip; // ??? + const int x = m_spriteram[offs + 3]; + const int y = m_spriteram[offs + 0]; + + if (flip == 0) + { + px = x; + py = 239 - y; + } + else + { + px = 248 - x; + py = y + 1; + } + m_gfxdecode->gfx(3)->transpen(bitmap, cliprect, + chr, + col, + !fx, fy, + px, py, 0); + } +} + +void momoko_state::draw_text_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip) +{ + for (int y = 16; y < 240; y++) + { + for (int x = 0; x < 32; x++) + { + int px, py, col; + int sy = y; + if (m_text_mode == 0) + col = m_proms[(sy >> 3) + 0x100] & 0x0f; + else + { + if (m_proms[y] < 0x08) + sy += m_text_scrolly; + col = (m_proms[y] & 0x07) + 0x10; + } + const int dy = sy & 7; + if (flip == 0) + { + px = x * 8; + py = y; + } + else + { + px = 248 - x * 8; + py = 255 - y; + } + const int ramoffset = (sy >> 3) * 32 + x; + + if (ramoffset < 0x400) // high score table, no wrapping? + m_gfxdecode->gfx(0)->transpen(bitmap, cliprect, + m_videoram[ramoffset] * 8 + dy, + col, + flip, 0, + px, py, 0); + } + } +} + +void momoko_state::draw_fg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip) +{ + const int dx = (7 - m_fg_scrollx) & 7; + const int dy = (7 - m_fg_scrolly) & 7; + const int rx = m_fg_scrollx >> 3; + const int ry = m_fg_scrolly >> 3; + + for (int y = 0; y < 29; y++) + { + for (int x = 0; x < 32; x++) + { + int px, py; + const int radr = ((ry + y + 34) & 0x3f) * 0x20 + ((rx + x) & 0x1f) + (m_fg_select & 3) * 0x800; + const u32 chr = m_fg_map[radr]; + if (flip == 0) + { + px = 8 * x + dx - 6; + py = 8 * y + dy + 9; + } + else + { + px = 248 - (8 * x + dx - 8); + py = 248 - (8 * y + dy + 9); + } + m_gfxdecode->gfx(2)->transpen(bitmap, cliprect, + chr, + 0, // color + flip, flip, // flip + px, py, 0); + } + } +} + +void momoko_state::draw_bg_romtilemap(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int flip, bool high) +{ + const int dx = (7 - m_bg_scrollx[0]) & 7; + const int dy = (7 - m_bg_scrolly[0]) & 7; + const int rx = (m_bg_scrollx[0] + m_bg_scrollx[1] * 256) >> 3; + const int ry = (m_bg_scrolly[0] + m_bg_scrolly[1] * 256) >> 3; + + for (int y = 0; y < 29; y++) + { + for (int x = 0; x < 32; x++) + { + int px, py; + const int radr = ((ry + y + 2) & 0x3ff) * 128 + ((rx + x) & 0x7f); + u32 chr = m_bg_map[radr]; + int col = m_bg_col_map[chr + m_bg_select * 512 + m_bg_priority * 256]; + chr = chr + m_bg_select * 512; + + if (flip == 0) + { + px = 8 * x + dx - 6; + py = 8 * y + dy + 9; + } + else + { + px = 248 - (8 * x + dx - 8); + py = 248 - (8 * y + dy + 9); + } + + if (!high) + { + m_gfxdecode->gfx(1)->opaque(bitmap, cliprect, + chr, + col, + flip, flip, + px, py); + } + else + { + const u8 pri = (col & 0x10) >> 1; + if (pri != 0) + { + col = col & 0x0f; + draw_bg_pri(bitmap, chr, col, flip, flip, px, py, pri); + } + } + } + } +} + +/****************************************************************************/ + +u32 momoko_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const int flip = m_flipscreen ^ (m_io_fake->read() & 0x01); + + // draw BG layer - all tiles + + if (m_bg_mask == 0) + draw_bg_romtilemap(screen, bitmap, cliprect, flip, false); + else + bitmap.fill(256, cliprect); + + // draw sprites (momoko) + draw_sprites(screen, bitmap, cliprect, 0, 9 * 4, flip); + + // draw BG layer - high priority tiles + if (m_bg_mask == 0) + draw_bg_romtilemap(screen, bitmap, cliprect, flip, true); + + // draw sprites (others) + draw_sprites(screen, bitmap, cliprect, 9 * 4, m_spriteram.bytes(), flip); + + // draw text layer + draw_text_tilemap(screen, bitmap, cliprect, flip); + + // draw FG layer + if (m_fg_mask == 0) + draw_fg_romtilemap(screen, bitmap, cliprect, flip); + + return 0; +} + + +// machine + void momoko_state::bg_read_bank_w(u8 data) { m_bgbank->set_entry(data & 0x1f); @@ -63,12 +433,12 @@ void momoko_state::bg_read_bank_w(u8 data) /****************************************************************************/ -void momoko_state::momoko_map(address_map &map) +void momoko_state::main_map(address_map &map) { map(0x0000, 0xbfff).rom(); map(0xc000, 0xcfff).ram(); - map(0xd064, 0xd0ff).ram().share("spriteram"); - map(0xd400, 0xd400).portr("IN0").nopw(); /* interrupt ack? */ + map(0xd064, 0xd0ff).ram().share(m_spriteram); + map(0xd400, 0xd400).portr("IN0").nopw(); // interrupt ack? map(0xd402, 0xd402).portr("IN1").w(FUNC(momoko_state::flipscreen_w)); map(0xd404, 0xd404).w("watchdog", FUNC(watchdog_timer_device::reset_w)); map(0xd406, 0xd406).portr("DSW0").w("soundlatch", FUNC(generic_latch_8_device::write)); @@ -77,24 +447,24 @@ void momoko_state::momoko_map(address_map &map) map(0xdc00, 0xdc00).w(FUNC(momoko_state::fg_scrolly_w)); map(0xdc01, 0xdc01).w(FUNC(momoko_state::fg_scrollx_w)); map(0xdc02, 0xdc02).w(FUNC(momoko_state::fg_select_w)); - map(0xe000, 0xe3ff).ram().share("videoram"); + map(0xe000, 0xe3ff).ram().share(m_videoram); map(0xe800, 0xe800).w(FUNC(momoko_state::text_scrolly_w)); map(0xe801, 0xe801).w(FUNC(momoko_state::text_mode_w)); - map(0xf000, 0xffff).bankr("bgbank"); - map(0xf000, 0xf001).w(FUNC(momoko_state::bg_scrolly_w)).share("bg_scrolly"); - map(0xf002, 0xf003).w(FUNC(momoko_state::bg_scrollx_w)).share("bg_scrollx"); + map(0xf000, 0xffff).bankr(m_bgbank); + map(0xf000, 0xf001).w(FUNC(momoko_state::bg_scrolly_w)).share(m_bg_scrolly); + map(0xf002, 0xf003).w(FUNC(momoko_state::bg_scrollx_w)).share(m_bg_scrollx); map(0xf004, 0xf004).w(FUNC(momoko_state::bg_read_bank_w)); map(0xf006, 0xf006).w(FUNC(momoko_state::bg_select_w)); map(0xf007, 0xf007).w(FUNC(momoko_state::bg_priority_w)); } -void momoko_state::momoko_sound_map(address_map &map) +void momoko_state::sound_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0x87ff).ram(); - map(0x9000, 0x9000).nopw(); /* unknown */ + map(0x9000, 0x9000).nopw(); // unknown map(0xa000, 0xa001).rw("ym1", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); - map(0xb000, 0xb000).nopw(); /* unknown */ + map(0xb000, 0xb000).nopw(); // unknown map(0xc000, 0xc001).rw("ym2", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); } @@ -145,13 +515,13 @@ static INPUT_PORTS_START( momoko ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_START("DSW1") - PORT_DIPNAME( 0x03, 0x03, DEF_STR( Bonus_Life ) ) /* see notes */ + PORT_DIPNAME( 0x03, 0x03, DEF_STR( Bonus_Life ) ) // see notes PORT_DIPSETTING( 0x01, "20k" ) PORT_DIPSETTING( 0x03, "30k" ) PORT_DIPSETTING( 0x02, "50k" ) PORT_DIPSETTING( 0x00, "100k" ) - PORT_DIPUNUSED( 0x04, IP_ACTIVE_LOW ) /* see notes */ - PORT_DIPUNUSED( 0x08, IP_ACTIVE_LOW ) /* see notes */ + PORT_DIPUNUSED( 0x04, IP_ACTIVE_LOW ) // see notes + PORT_DIPUNUSED( 0x08, IP_ACTIVE_LOW ) // see notes PORT_DIPNAME( 0x10, 0x00, DEF_STR( Cabinet ) ) PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x10, DEF_STR( Cocktail ) ) @@ -171,9 +541,9 @@ INPUT_PORTS_END static const gfx_layout charlayout = { - 8,8, /* 8*8 characters */ - 256, /* 256 characters */ - 2, /* 2 bits per pixel */ + 8,8, // 8*8 characters + 256, // 256 characters + 2, // 2 bits per pixel {4, 0}, {0, 1, 2, 3, 256*8*8+0, 256*8*8+1, 256*8*8+2, 256*8*8+3}, {8*0, 8*1, 8*2, 8*3, 8*4, 8*5, 8*6, 8*7}, @@ -182,9 +552,9 @@ static const gfx_layout charlayout = static const gfx_layout spritelayout = { - 8,16, /* 8*16 characters */ - 2048-128, /* 1024 sprites ( ccc 0ccccccc ) */ - 4, /* 4 bits per pixel */ + 8,16, // 8*16 characters + 2048-128, // 1024 sprites ( ccc 0ccccccc ) + 4, // 4 bits per pixel {12,8,4,0}, {0, 1, 2, 3, 4096*8+0, 4096*8+1, 4096*8+2, 4096*8+3}, {0, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, @@ -194,9 +564,9 @@ static const gfx_layout spritelayout = static const gfx_layout tilelayout = { - 8,8, /* 8*8 characters */ - 8192-256, /* 4096 tiles ( cccc0 cccccccc ) */ - 4, /* 4 bits per pixel */ + 8,8, // 8*8 characters + 8192-256, // 4096 tiles ( cccc0 cccccccc ) + 4, // 4 bits per pixel {4,0,12,8}, {0, 1, 2, 3, 4096*8+0, 4096*8+1, 4096*8+2, 4096*8+3}, {0, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16}, @@ -205,9 +575,9 @@ static const gfx_layout tilelayout = static const gfx_layout charlayout1 = { - 8,1, /* 8*1 characters */ - 256*8, /* 2048 characters */ - 2, /* 2 bits per pixel */ + 8,1, // 8*1 characters + 256*8, // 2048 characters + 2, // 2 bits per pixel {4, 0}, {0, 1, 2, 3, 256*8*8+0, 256*8*8+1, 256*8*8+2, 256*8*8+3}, {8*0}, @@ -215,10 +585,10 @@ static const gfx_layout charlayout1 = }; static GFXDECODE_START( gfx_momoko ) - GFXDECODE_ENTRY( "text", 0x0000, charlayout1, 0, 24 ) /* TEXT */ - GFXDECODE_ENTRY( "bg_gfx", 0x0000, tilelayout, 256, 16 ) /* BG */ - GFXDECODE_ENTRY( "fg_gfx", 0x0000, charlayout, 0, 1 ) /* FG */ - GFXDECODE_ENTRY( "spr_gfx", 0x0000, spritelayout, 128, 8 ) /* sprite */ + GFXDECODE_ENTRY( "text", 0x0000, charlayout1, 0, 24 ) + GFXDECODE_ENTRY( "bg_gfx", 0x0000, tilelayout, 256, 16 ) + GFXDECODE_ENTRY( "fg_gfx", 0x0000, charlayout, 0, 1 ) + GFXDECODE_ENTRY( "spr_gfx", 0x0000, spritelayout, 128, 8 ) GFXDECODE_END /****************************************************************************/ @@ -255,20 +625,20 @@ void momoko_state::machine_reset() void momoko_state::momoko(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(10'000'000)/2); /* 5.0MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &momoko_state::momoko_map); + // basic machine hardware + Z80(config, m_maincpu, XTAL(10'000'000) / 2); // 5.0MHz + m_maincpu->set_addrmap(AS_PROGRAM, &momoko_state::main_map); m_maincpu->set_vblank_int("screen", FUNC(momoko_state::irq0_line_hold)); - z80_device &audiocpu(Z80(config, "audiocpu", XTAL(10'000'000)/4)); /* 2.5MHz */ - audiocpu.set_addrmap(AS_PROGRAM, &momoko_state::momoko_sound_map); + z80_device &audiocpu(Z80(config, "audiocpu", XTAL(10'000'000) / 4)); // 2.5MHz + audiocpu.set_addrmap(AS_PROGRAM, &momoko_state::sound_map); WATCHDOG_TIMER(config, "watchdog"); - /* 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(2500) /* not accurate */); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate screen.set_size(32*8, 32*8); screen.set_visarea(1*8, 31*8-1, 2*8, 29*8-1); screen.set_screen_update(FUNC(momoko_state::screen_update)); @@ -278,18 +648,18 @@ void momoko_state::momoko(machine_config &config) PALETTE(config, m_palette).set_format(palette_device::xRGB_444, 512); m_palette->set_endianness(ENDIANNESS_BIG); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); GENERIC_LATCH_8(config, "soundlatch"); - ym2203_device &ym1(YM2203(config, "ym1", XTAL(10'000'000)/8)); + ym2203_device &ym1(YM2203(config, "ym1", XTAL(10'000'000) / 8)); ym1.add_route(0, "mono", 0.15); ym1.add_route(1, "mono", 0.15); ym1.add_route(2, "mono", 0.15); ym1.add_route(3, "mono", 0.40); - ym2203_device &ym2(YM2203(config, "ym2", XTAL(10'000'000)/8)); + ym2203_device &ym2(YM2203(config, "ym2", XTAL(10'000'000) / 8)); ym2.port_a_read_callback().set("soundlatch", FUNC(generic_latch_8_device::read)); ym2.add_route(0, "mono", 0.15); ym2.add_route(1, "mono", 0.15); @@ -300,128 +670,131 @@ void momoko_state::momoko(machine_config &config) /****************************************************************************/ ROM_START( momoko ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* main CPU */ + ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD( "momoko03.m6", 0x0000, 0x8000, CRC(386e26ed) SHA1(ad746ed1b87bafc5b4df9a28aade58cf894f4e7b) ) // age progression text in Japanese ROM_LOAD( "momoko02.m5", 0x8000, 0x4000, CRC(4255e351) SHA1(27a0e8d8aea223d2128139582e3b66106f3608ef) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound CPU */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "momoko01.u4", 0x0000, 0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) ) - ROM_REGION( 0x2000, "text", 0 ) /* text */ + ROM_REGION( 0x2000, "text", 0 ) ROM_LOAD( "momoko13.u4", 0x0000, 0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) ) // On the FP-8631 PCB - ROM_REGION( 0x2000, "fg_gfx", 0 ) /* FG */ + ROM_REGION( 0x2000, "fg_gfx", 0 ) ROM_LOAD( "momoko14.p2", 0x0000, 0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) ) - ROM_REGION( 0x10000, "spr_gfx", 0 ) /* sprite */ + ROM_REGION( 0x10000, "spr_gfx", 0 ) ROM_LOAD16_BYTE( "momoko16.e5", 0x0000, 0x8000, CRC(fc6876fc) SHA1(b2d06bc01ef9f4db9bf8902d67f31ccbb0fea61a) ) // On the FP-8631 PCB ROM_LOAD16_BYTE( "momoko17.e6", 0x0001, 0x8000, CRC(45dc0247) SHA1(1b2bd4197ab7d237966e037c249b5bd623646c0b) ) // On the FP-8631 PCB - ROM_REGION( 0x20000, "bg_gfx", 0 ) /* BG */ + ROM_REGION( 0x20000, "bg_gfx", 0 ) ROM_LOAD16_BYTE( "momoko09.e8", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) ) ROM_LOAD16_BYTE( "momoko11.c8", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) ) ROM_LOAD16_BYTE( "momoko10.d8", 0x10000, 0x8000, CRC(ae17e74b) SHA1(f52657ea6b6ac518b70fd7b811d9699da27f67d9) ) ROM_LOAD16_BYTE( "momoko12.a8", 0x10001, 0x8000, CRC(1e29c9c4) SHA1(d78f102cefc9852b529dd317a76c7003ec2ad3d5) ) - ROM_REGION( 0x20000, "bg_map", 0 ) /* BG map */ + ROM_REGION( 0x20000, "bg_map", 0 ) ROM_LOAD( "momoko04.r8", 0x0000, 0x8000, CRC(3ab3c2c3) SHA1(d4a0d7f83bf64769e90a2c264c6114ac308cb8b5) ) ROM_LOAD( "momoko05.p8", 0x8000, 0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) ) ROM_LOAD( "momoko06.n8", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) ) ROM_LOAD( "momoko07.l8", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) ) - ROM_REGION( 0x2000, "bg_col_map", 0 ) /* BG color/priority table */ + ROM_REGION( 0x2000, "bg_col_map", 0 ) ROM_LOAD( "momoko08.h8", 0x0000, 0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) ) - ROM_REGION( 0x4000, "fg_map", 0 ) /* FG map */ + ROM_REGION( 0x4000, "fg_map", 0 ) ROM_LOAD( "momoko15.k2", 0x0000, 0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) ) // On the FP-8631 PCB - ROM_REGION( 0x0120, "proms", 0 ) /* TEXT color */ + ROM_REGION( 0x0120, "proms", 0 ) // text color ROM_LOAD( "momoko-c.bin", 0x0000, 0x0100, CRC(f35ccae0) SHA1(60b99dd3c96637dacba7e96a143b1a2d6ffd28b9) ) ROM_LOAD( "momoko-b.bin", 0x0100, 0x0020, CRC(427b0e5c) SHA1(aa2797b899571527cc96013fd3420b841954ee67) ) ROM_END ROM_START( momokoe ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* main CPU */ + ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD( "3.m6", 0x0000, 0x8000, CRC(84053a7d) SHA1(6e8fb22bb48954f4fed2530991ebe5b872c9c089) ) // age progression text in English ROM_LOAD( "2.m5", 0x8000, 0x4000, CRC(98ad397b) SHA1(b7ae218d0d397b1e258ec6d1f836cb998f984092) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound CPU */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "momoko01.u4", 0x0000, 0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) ) - ROM_REGION( 0x2000, "text", 0 ) /* text */ + ROM_REGION( 0x2000, "text", 0 ) ROM_LOAD( "momoko13.u4", 0x0000, 0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) ) // On the FP-8631 PCB - ROM_REGION( 0x2000, "fg_gfx", 0 ) /* FG */ + ROM_REGION( 0x2000, "fg_gfx", 0 ) ROM_LOAD( "momoko14.p2", 0x0000, 0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) ) - ROM_REGION( 0x10000, "spr_gfx", 0 ) /* sprite */ + ROM_REGION( 0x10000, "spr_gfx", 0 ) ROM_LOAD16_BYTE( "momoko16.e5", 0x0000, 0x8000, CRC(fc6876fc) SHA1(b2d06bc01ef9f4db9bf8902d67f31ccbb0fea61a) ) // On the FP-8631 PCB ROM_LOAD16_BYTE( "momoko17.e6", 0x0001, 0x8000, CRC(45dc0247) SHA1(1b2bd4197ab7d237966e037c249b5bd623646c0b) ) // On the FP-8631 PCB - ROM_REGION( 0x20000, "bg_gfx", 0 ) /* BG */ + ROM_REGION( 0x20000, "bg_gfx", 0 ) ROM_LOAD16_BYTE( "momoko09.e8", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) ) ROM_LOAD16_BYTE( "momoko11.c8", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) ) ROM_LOAD16_BYTE( "momoko10.d8", 0x10000, 0x8000, CRC(ae17e74b) SHA1(f52657ea6b6ac518b70fd7b811d9699da27f67d9) ) ROM_LOAD16_BYTE( "momoko12.a8", 0x10001, 0x8000, CRC(1e29c9c4) SHA1(d78f102cefc9852b529dd317a76c7003ec2ad3d5) ) - ROM_REGION( 0x20000, "bg_map", 0 ) /* BG map */ + ROM_REGION( 0x20000, "bg_map", 0 ) ROM_LOAD( "momoko04.r8", 0x0000, 0x8000, CRC(3ab3c2c3) SHA1(d4a0d7f83bf64769e90a2c264c6114ac308cb8b5) ) ROM_LOAD( "momoko05.p8", 0x8000, 0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) ) ROM_LOAD( "momoko06.n8", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) ) ROM_LOAD( "momoko07.l8", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) ) - ROM_REGION( 0x2000, "bg_col_map", 0 ) /* BG color/priority table */ + ROM_REGION( 0x2000, "bg_col_map", 0 ) ROM_LOAD( "momoko08.h8", 0x0000, 0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) ) - ROM_REGION( 0x4000, "fg_map", 0 ) /* FG map */ + ROM_REGION( 0x4000, "fg_map", 0 ) ROM_LOAD( "momoko15.k2", 0x0000, 0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) ) // On the FP-8631 PCB - ROM_REGION( 0x0120, "proms", 0 ) /* TEXT color */ + ROM_REGION( 0x0120, "proms", 0 ) // text color ROM_LOAD( "momoko-c.bin", 0x0000, 0x0100, CRC(f35ccae0) SHA1(60b99dd3c96637dacba7e96a143b1a2d6ffd28b9) ) ROM_LOAD( "momoko-b.bin", 0x0100, 0x0020, CRC(427b0e5c) SHA1(aa2797b899571527cc96013fd3420b841954ee67) ) ROM_END ROM_START( momokob ) // bootleg board, almost exact copy of an original one - ROM_REGION( 0x10000, "maincpu", 0 ) /* main CPU */ + ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD( "3.bin", 0x0000, 0x8000, CRC(a18d7e78) SHA1(5d2dd498be3e22b5e8fc5ffe17e1ef463c1e9a02) ) // age progression text in Engrish, title screen in English ROM_LOAD( "2.bin", 0x8000, 0x4000, CRC(2dcf50ed) SHA1(6d02cb86fce031859bc0a5a26ecf7a8c8b89dea3) ) - ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound CPU */ + ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "momoko01.u4", 0x0000, 0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) ) - ROM_REGION( 0x2000, "text", 0 ) /* text */ + ROM_REGION( 0x2000, "text", 0 ) ROM_LOAD( "momoko13.u4", 0x0000, 0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) ) - ROM_REGION( 0x2000, "fg_gfx", 0 ) /* FG */ + ROM_REGION( 0x2000, "fg_gfx", 0 ) ROM_LOAD( "momoko14.p2", 0x0000, 0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) ) - ROM_REGION( 0x10000, "spr_gfx", 0 ) /* sprite */ + ROM_REGION( 0x10000, "spr_gfx", 0 ) ROM_LOAD16_BYTE( "16.bin", 0x0000, 0x8000, CRC(49de49a1) SHA1(b4954286cba50332d4366a8160e9fbfd574c60ed) ) ROM_LOAD16_BYTE( "17.bin", 0x0001, 0x8000, CRC(f06a3d1a) SHA1(f377ffad958fdc9cff2baee70ce4ba9080b5fe0d) ) - ROM_REGION( 0x20000, "bg_gfx", 0 ) /* BG */ + ROM_REGION( 0x20000, "bg_gfx", 0 ) ROM_LOAD16_BYTE( "momoko09.e8", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) ) ROM_LOAD16_BYTE( "momoko11.c8", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) ) ROM_LOAD16_BYTE( "10.bin", 0x10000, 0x8000, CRC(68b9156d) SHA1(e157434d7ee33837ba35e720d221bf1eb21b7020) ) ROM_LOAD16_BYTE( "12.bin", 0x10001, 0x8000, CRC(c32f5e19) SHA1(488da565e20bf002ff3dffca1efedbdf29e6e559) ) - ROM_REGION( 0x20000, "bg_map", 0 ) /* BG map */ + ROM_REGION( 0x20000, "bg_map", 0 ) ROM_LOAD( "4.bin", 0x0000, 0x8000, CRC(1f0226d5) SHA1(6411e85c51e23dfe6c643692987dc7eeef37538f) ) ROM_LOAD( "momoko05.p8", 0x8000, 0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) ) ROM_LOAD( "momoko06.n8", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) ) ROM_LOAD( "momoko07.l8", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) ) - ROM_REGION( 0x2000, "bg_col_map", 0 ) /* BG color/priority table */ + ROM_REGION( 0x2000, "bg_col_map", 0 ) ROM_LOAD( "momoko08.h8", 0x0000, 0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) ) - ROM_REGION( 0x4000, "fg_map", 0 ) /* FG map */ + ROM_REGION( 0x4000, "fg_map", 0 ) ROM_LOAD( "momoko15.k2", 0x0000, 0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) ) - ROM_REGION( 0x0120, "proms", 0 ) /* TEXT color */ + ROM_REGION( 0x0120, "proms", 0 ) // text color ROM_LOAD( "momoko-c.bin", 0x0000, 0x0100, CRC(f35ccae0) SHA1(60b99dd3c96637dacba7e96a143b1a2d6ffd28b9) ) ROM_LOAD( "momoko-b.bin", 0x0100, 0x0020, CRC(427b0e5c) SHA1(aa2797b899571527cc96013fd3420b841954ee67) ) ROM_END +} // anonymous namespace + + GAME( 1986, momoko, 0, momoko, momoko, momoko_state, empty_init, ROT0, "Jaleco", "Momoko 120% (Japanese text)", MACHINE_SUPPORTS_SAVE ) GAME( 1986, momokoe, momoko, momoko, momoko, momoko_state, empty_init, ROT0, "Jaleco", "Momoko 120% (English text)", MACHINE_SUPPORTS_SAVE ) GAME( 1986, momokob, momoko, momoko, momoko, momoko_state, empty_init, ROT0, "bootleg", "Momoko 120% (bootleg)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/jaleco/momoko.h b/src/mame/jaleco/momoko.h deleted file mode 100644 index 787f98a2776..00000000000 --- a/src/mame/jaleco/momoko.h +++ /dev/null @@ -1,89 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Uki -/************************************************************************* - - Momoko 120% - -*************************************************************************/ -#ifndef MAME_INCLUDES_MOMOKO_H -#define MAME_INCLUDES_MOMOKO_H - -#pragma once - -#include "emupal.h" - -class momoko_state : public driver_device -{ -public: - momoko_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_spriteram(*this, "spriteram"), - m_videoram(*this, "videoram"), - m_bg_scrolly(*this, "bg_scrolly"), - m_bg_scrollx(*this, "bg_scrollx"), - m_bg_gfx(*this, "bg_gfx"), - m_bg_map(*this, "bg_map"), - m_bg_col_map(*this, "bg_col_map"), - m_fg_map(*this, "fg_map"), - m_proms(*this, "proms"), - m_bgbank(*this, "bgbank"), - m_io_fake(*this, "FAKE"), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette") - { } - - void momoko(machine_config &config); - -private: - /* memory pointers */ - required_shared_ptr m_spriteram; - required_shared_ptr m_videoram; - required_shared_ptr m_bg_scrolly; - required_shared_ptr m_bg_scrollx; - required_region_ptr m_bg_gfx; - required_region_ptr m_bg_map; - required_region_ptr m_bg_col_map; - required_region_ptr m_fg_map; - required_region_ptr m_proms; - required_memory_bank m_bgbank; - required_ioport m_io_fake; - - /* video-related */ - u8 m_fg_scrollx = 0; - u8 m_fg_scrolly = 0; - u8 m_fg_select = 0; - u8 m_text_scrolly = 0; - u8 m_text_mode = 0; - u8 m_bg_select = 0; - u8 m_bg_priority = 0; - u8 m_bg_mask = 0; - u8 m_fg_mask = 0; - u8 m_flipscreen = 0; - void bg_read_bank_w(u8 data); - void fg_scrollx_w(u8 data); - void fg_scrolly_w(u8 data); - void fg_select_w(u8 data); - void text_scrolly_w(u8 data); - void text_mode_w(u8 data); - void bg_scrollx_w(offs_t offset, u8 data); - void bg_scrolly_w(offs_t offset, u8 data); - void bg_select_w(u8 data); - void bg_priority_w(u8 data); - void flipscreen_w(u8 data); - virtual void machine_start() override; - virtual void machine_reset() override; - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_bg_pri(bitmap_ind16 &bitmap, int chr, int col, int flipx, int flipy, int x, int y, int pri); - void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int start, int end, int flip); - void draw_text_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip); - void draw_fg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip); - void draw_bg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip, bool high); - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - void momoko_map(address_map &map); - void momoko_sound_map(address_map &map); -}; - -#endif // MAME_INCLUDES_MOMOKO_H diff --git a/src/mame/jaleco/momoko_v.cpp b/src/mame/jaleco/momoko_v.cpp deleted file mode 100644 index 1d319fc26fb..00000000000 --- a/src/mame/jaleco/momoko_v.cpp +++ /dev/null @@ -1,289 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Uki -/******************************************************************************* - - Momoko 120% (c) 1986 Jaleco - - Video hardware driver by Uki 02/Mar/2001 - - Video consists of - - Sprites - - 2x ROM based tilemaps (bg and fg) with priority over some sprites - - 1x RAM based tilemap (text layer) (no wrapping?) - - TODO: - - update to use tilemap system? - - check if any of this is common Jaleco/NMK etc. hardware and use shared - devices if possible - -*******************************************************************************/ - -#include "emu.h" -#include "momoko.h" - - -void momoko_state::fg_scrollx_w(u8 data) -{ - m_fg_scrollx = data; -} - -void momoko_state::fg_scrolly_w(u8 data) -{ - m_fg_scrolly = data; -} - -void momoko_state::fg_select_w(u8 data) -{ - m_fg_select = data & 0x0f; - m_fg_mask = data & 0x10; -} - -void momoko_state::text_scrolly_w(u8 data) -{ - m_text_scrolly = data; -} - -void momoko_state::text_mode_w(u8 data) -{ - m_text_mode = data; -} - -void momoko_state::bg_scrollx_w(offs_t offset, u8 data) -{ - m_bg_scrollx[offset] = data; -} - -void momoko_state::bg_scrolly_w(offs_t offset, u8 data) -{ - m_bg_scrolly[offset] = data; -} - -void momoko_state::bg_select_w(u8 data) -{ - m_bg_select = data & 0x0f; - m_bg_mask = data & 0x10; -} - -void momoko_state::bg_priority_w(u8 data) -{ - m_bg_priority = data & 0x01; -} - -void momoko_state::flipscreen_w(u8 data) -{ - m_flipscreen = data & 0x01; -} - -/****************************************************************************/ - -void momoko_state::draw_bg_pri(bitmap_ind16 &bitmap, int chr, int col, int flipx, int flipy, int x, int y, int pri) -{ - for (int sy = 0; sy < 8; sy++) - { - const u32 gfxadr = chr * 16 + sy * 2; - for (int xx = 0; xx < 2; xx++) - { - u8 d0 = m_bg_gfx[gfxadr + xx * 4096]; - u8 d1 = m_bg_gfx[gfxadr + xx * 4096 + 1]; - - for (int sx = 0; sx < 4; sx++) - { - const u8 dot = (d0 & 0x08) | ((d0 & 0x80) >> 5) | ((d1 & 0x08) >> 2) | ((d1 & 0x80) >> 7); - const int px = (flipx == 0) ? (sx + xx * 4 + x) : (7 - sx - xx * 4 + x); - const int py = (flipy == 0) ? (sy + y) : (7 - sy + y); - - if (dot >= pri) - bitmap.pix(py, px) = col * 16 + dot + 256; - - d0 <<= 1; - d1 <<= 1; - } - } - } -} - - -void momoko_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int start, int end, int flip) -{ - for (int offs = start; offs < end; offs += 4) - { - int px, py; - u32 chr = m_spriteram[offs + 1] | ((m_spriteram[offs + 2] & 0x60) << 3); - chr = ((chr & 0x380) << 1) | (chr & 0x7f); - int col = m_spriteram[offs + 2] & 0x07; - const int fx = ((m_spriteram[offs + 2] & 0x10) >> 4) ^ flip; - const int fy = ((m_spriteram[offs + 2] & 0x08) >> 3) ^ flip; /* ??? */ - int x = m_spriteram[offs + 3]; - int y = m_spriteram[offs + 0]; - - if (flip == 0) - { - px = x; - py = 239 - y; - } - else - { - px = 248 - x; - py = y + 1; - } - m_gfxdecode->gfx(3)->transpen(bitmap, cliprect, - chr, - col, - !fx, fy, - px, py, 0); - } -} - -void momoko_state::draw_text_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip) -{ - for (int y = 16; y < 240; y++) - { - for (int x = 0; x < 32; x++) - { - int px, py, col; - int sy = y; - if (m_text_mode == 0) - col = m_proms[(sy >> 3) + 0x100] & 0x0f; - else - { - if (m_proms[y] < 0x08) - sy += m_text_scrolly; - col = (m_proms[y] & 0x07) + 0x10; - } - int dy = sy & 7; - if (flip == 0) - { - px = x * 8; - py = y; - } - else - { - px = 248 - x * 8; - py = 255 - y; - } - int ramoffset = (sy >> 3) * 32 + x; - - if (ramoffset < 0x400) // high score table, no wrapping? - m_gfxdecode->gfx(0)->transpen(bitmap, cliprect, - m_videoram[ramoffset] * 8 + dy, - col, - flip, 0, - px, py, 0); - } - } -} - -void momoko_state::draw_fg_romtilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int flip) -{ - int dx = (7 - m_fg_scrollx) & 7; - int dy = (7 - m_fg_scrolly) & 7; - int rx = m_fg_scrollx >> 3; - int ry = m_fg_scrolly >> 3; - - for (int y = 0; y < 29; y++) - { - for (int x = 0; x < 32; x++) - { - int px, py; - const int radr = ((ry + y + 34) & 0x3f) * 0x20 + ((rx + x) & 0x1f) + (m_fg_select & 3) * 0x800; - const u32 chr = m_fg_map[radr]; - if (flip == 0) - { - px = 8 * x + dx - 6; - py = 8 * y + dy + 9; - } - else - { - px = 248 - (8 * x + dx - 8); - py = 248 - (8 * y + dy + 9); - } - m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, - chr, - 0, /* color */ - flip,flip, /* flip */ - px,py,0); - } - } -} - -void momoko_state::draw_bg_romtilemap(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int flip, bool high) -{ - int dx = (7 - m_bg_scrollx[0]) & 7; - int dy = (7 - m_bg_scrolly[0]) & 7; - int rx = (m_bg_scrollx[0] + m_bg_scrollx[1] * 256) >> 3; - int ry = (m_bg_scrolly[0] + m_bg_scrolly[1] * 256) >> 3; - - for (int y = 0; y < 29; y++) - { - for (int x = 0; x < 32; x++) - { - int px, py; - const int radr = ((ry + y + 2) & 0x3ff) * 128 + ((rx + x) & 0x7f); - u32 chr = m_bg_map[radr]; - int col = m_bg_col_map[chr + m_bg_select * 512 + m_bg_priority * 256]; - chr = chr + m_bg_select * 512; - - if (flip == 0) - { - px = 8 * x + dx - 6; - py = 8 * y + dy + 9; - } - else - { - px = 248 - (8 * x + dx - 8); - py = 248 - (8 * y + dy + 9); - } - - if (!high) - { - m_gfxdecode->gfx(1)->opaque(bitmap,cliprect, - chr, - col, - flip,flip, - px,py); - } - else - { - const u8 pri = (col & 0x10) >> 1; - if (pri != 0) - { - col = col & 0x0f; - draw_bg_pri(bitmap, chr, col, flip, flip, px, py, pri); - } - } - } - } -} - -/****************************************************************************/ - -u32 momoko_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - const int flip = m_flipscreen ^ (m_io_fake->read() & 0x01); - - /* draw BG layer - all tiles */ - - if (m_bg_mask == 0) - draw_bg_romtilemap(screen, bitmap, cliprect, flip, false); - else - bitmap.fill(256, cliprect); - - /* draw sprites (momoko) */ - draw_sprites(screen, bitmap, cliprect, 0, 9 * 4, flip); - - /* draw BG layer - high priority tiles */ - if (m_bg_mask == 0) - draw_bg_romtilemap(screen, bitmap, cliprect, flip, true); - - /* draw sprites (others) */ - draw_sprites(screen, bitmap, cliprect, 9*4, m_spriteram.bytes(), flip); - - /* draw text layer */ - draw_text_tilemap(screen, bitmap, cliprect, flip); - - /* draw FG layer */ - if (m_fg_mask == 0) - draw_fg_romtilemap(screen, bitmap, cliprect, flip); - - return 0; -} diff --git a/src/mame/jaleco/skyfox.cpp b/src/mame/jaleco/skyfox.cpp index eb453f8848a..b5bce3b0977 100644 --- a/src/mame/jaleco/skyfox.cpp +++ b/src/mame/jaleco/skyfox.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Luca Elia +// copyright-holders: Luca Elia + /*************************************************************************** -= Sky Fox / Exerizer =- @@ -24,46 +25,325 @@ Verified Dip locations and recommended settings with manual ***************************************************************************/ #include "emu.h" -#include "skyfox.h" #include "cpu/z80/z80.h" +#include "machine/gen_latch.h" #include "sound/ymopn.h" +#include "video/resnet.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +namespace { + +class skyfox_state : public driver_device +{ +public: + skyfox_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_screen(*this, "screen"), + m_palette(*this, "palette"), + m_spriteram(*this, "spriteram"), + m_bgram(*this, "bgram"), + m_bgrom(*this, "tiles") + { } + + void skyfox(machine_config &config); + + void init_skyfox(); + + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + // devices/memory pointers + required_device m_maincpu; + required_device m_audiocpu; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + required_shared_ptr m_spriteram; + required_shared_ptr m_bgram; + required_region_ptr m_bgrom; + + uint8_t m_bg_ctrl = 0; + + void bg_ctrl_w(uint8_t data); + void palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect); + + void main_map(address_map &map); + void sound_map(address_map &map); +}; + + +// video + /*************************************************************************** - Main CPU + + [ 1 Background ] + + The stars in the background are not tile based (I think!) and + their rendering is entirely guesswork for now.. + + I draw a star for each horizontal line using 2 bytes in the + background ROM: + + - the first byte seems a color / shape info + - the second byte seems a position info + + The ROM holds 4 chunks of $2000 bytes. Most of the data does not + change between chunks, while the remaining part (which is rendered + to what seems a "milky way") pulsates in color and/or shape + to simulate the shimmering of stars (?!) if we draw one chunk only + and cycle through the four. Indeed, there's a register cycling + through 4 values. + + Since the result kind of matches a screenshot we have, I feel the + drawn result is not that far from reality. On the other hand we + have a random arrangement of stars, so it's hard to tell for sure.. + + [ 256 Sprites ] + + Sprites are 8 planes deep and can be 8x8, 16x16 or 32x32 pixels + in size. They are stored as 32x32x8 tiles in the ROMs. + + +***************************************************************************/ + +/*************************************************************************** + + Convert the color PROMs into a more useable format. + + There are three 256x4 palette PROMs (one per gun). + The palette PROMs are connected to the RGB output this way: + + bit 3 -- 110 ohm resistor -- RED/GREEN/BLUE + -- 220 ohm resistor -- RED/GREEN/BLUE + -- 680 ohm resistor -- RED/GREEN/BLUE + bit 0 -- 1.2kohm resistor -- RED/GREEN/BLUE + +***************************************************************************/ + +static constexpr res_net_decode_info decode_info = +{ + 1, + 0, 255, // start/end + // R, G, B, + { 0, 0x100, 0x200, }, // offsets + { 0, 0, 0, }, // shifts + { 0xf, 0xf, 0xf, } // masks +}; + +static constexpr res_net_info net_info = +{ + RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT, + { + { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } }, + { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } }, + { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } } + } +}; + +void skyfox_state::palette(palette_device &palette) const +{ + uint8_t const *const color_prom = memregion("proms")->base(); + std::vector rgb; + + compute_res_net_all(rgb, color_prom, decode_info, net_info); + palette.set_pen_colors(0, rgb); +} + + +/*************************************************************************** + + Sprites Drawing + +Offset: Value: + +03 Code: selects one of the 32x32 tiles in the ROMs. + (Tiles $80-ff are bankswitched to cover $180 tiles) + +02 Code + Attr + + 7654 ---- Code (low 4 bits) + 8x8 sprites use bits 7654 (since there are 16 8x8 tiles in the 32x32 one) + 16x16 sprites use bits --54 (since there are 4 16x16 tiles in the 32x32 one) + 32x32 sprites use no bits (since the 32x32 tile is already selected) + + 7--- 3--- Size + 1--- 1--- : 32x32 sprites + 0--- 1--- : 16x16 sprites + 8x8 sprites otherwise + + ---- -2-- Flip Y + ---- --1- Flip X + ---- ---0 X Low Bit + +00 Y + +01 X (High 8 Bits) ***************************************************************************/ -void skyfox_state::output_w(offs_t offset, uint8_t data) +void skyfox_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) { - // TODO: untangle - switch (offset) + gfx_element *gfx = m_gfxdecode->gfx(0); + int const width = m_screen->width(); + int const height = m_screen->height(); + + // The 32x32 tiles in the 80-ff range are bankswitched + int const shift = (m_bg_ctrl & 0x80) ? (4 - 1) : 4; + + for (int offs = 0; offs < m_spriteram.bytes(); offs += 4) { - case 0: - m_bg_ctrl = data; - break; + int code = m_spriteram[offs + 3] << 8 | m_spriteram[offs + 2]; + int flipx = code & 0x2; + int flipy = code & 0x4; + int y = m_spriteram[offs + 0]; + int x = m_spriteram[offs + 1] << 1 | (code & 1); + + int const high_code = ((code >> 4) & 0x7f0) + ((code & 0x8000) >> shift); + + int low_code, n; + + switch (code & 0x88) + { + case 0x88: n = 4; low_code = 0; break; + case 0x08: n = 2; low_code = (code & 0x20) >> 2 | (code & 0x10) >> 3; break; + default: n = 1; low_code = (code >> 4) & 0xf; break; + } + + if (m_bg_ctrl & 1) // flipscreen + { + x = width - x - n * 8; + y = height - y - n * 8; + flipx = !flipx; + flipy = !flipy; + } + + int xstart, ystart, xend, yend, xinc, yinc; + + if (flipx) { xstart = n - 1; xend = -1; xinc = -1; } + else { xstart = 0; xend = n; xinc = +1; } + + if (flipy) { ystart = n - 1; yend = -1; yinc = -1; } + else { ystart = 0; yend = n; yinc = +1; } + + + code = low_code + high_code; + + for (int dy = ystart; dy != yend; dy += yinc) + { + for (int dx = xstart; dx != xend; dx += xinc, code++) + { + gfx->transpen(bitmap, cliprect, code, 0, flipx, flipy, dx * 8 + x, dy * 8 + y, 0xff); + + // wraparound y - BTANB: large sprites exiting the screen sometimes reappear on the other edge + gfx->transpen(bitmap, cliprect, code, 0, flipx, flipy, dx * 8 + x, dy * 8 + y - 256, 0xff); + } + + if (n == 2) + code += 2; + } + } +} + + + +/*************************************************************************** + + Background Rendering + +***************************************************************************/ + +void skyfox_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // Blinking stops until the first star moves after turning on the power + bool const blinking = (m_bg_ctrl & 0x8); + /* Star pattern change. This will change when all star clusters go out of screen or when the player restarts. + When it changes, it will change color of the star clusters. */ + int const pattern = (m_bg_ctrl & 0x6) >> 1; - case 1: - m_soundlatch->write(data); - break; + for (int i = 0; i < 0x1000; i++) + { + // contains the position of stars from 0xd4e0 in RAM + int const ramoffset = 0xe0 + (i & 0xf) * 2; + int const pos = m_bgram[ramoffset + 1] * 2 + ((m_bgram[ramoffset] & 0x80) ? 1 : 0); + + // ROM offset of star pattern + int const offs = (i * 2) % 0x2000 + pattern * 0x2000; + + /* Adjusted with 1 pixel accuracy compared to PCB. + Confirmed that pixel and color pattern match in the "1UP START" screen. */ + int const pen = m_bgrom[offs]; + int const x = m_bgrom[offs + 1] * 2 + pos + 0x5b; + int const y = (i >> 4) + 1; + + /* When flipscreen is enabled, scroll direction is flipped by only in-game subroutine. + This PCB does not seem to support background flip. */ + + /* This looks perfect at first glance. + but when strict compared on "1UP START" screen, + it seems the blinking pattern in each star may be different. */ + if (((m_bg_ctrl >> 4) & 3) != (pen & 3) || !blinking) + bitmap.pix(y % 256, x % 512) = pen; } } -void skyfox_state::skyfox_map(address_map &map) + +/*************************************************************************** + + Screen Drawing + +***************************************************************************/ + +uint32_t skyfox_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0xff, cliprect); // the bg is black + draw_background(bitmap, cliprect); + draw_sprites(bitmap, cliprect); + return 0; +} + + +// machine + +/*************************************************************************** + + Main CPU + +***************************************************************************/ + +void skyfox_state::bg_ctrl_w(uint8_t data) +{ + m_bg_ctrl = data; +} + +void skyfox_state::main_map(address_map &map) { map(0x0000, 0xbfff).rom(); map(0xc000, 0xcfff).ram(); - map(0xd000, 0xd3ff).ram().share("spriteram"); - map(0xd400, 0xd4ff).ram().share("bgram"); // For background stars + map(0xd000, 0xd3ff).ram().share(m_spriteram); + map(0xd400, 0xd4ff).ram().share(m_bgram); // For background stars // TODO: verify if A11 is unconnected map(0xd500, 0xdfff).ram(); map(0xe000, 0xe000).portr("INPUTS"); map(0xe001, 0xe001).portr("DSW0"); map(0xe002, 0xe002).portr("DSW1"); - map(0xe008, 0xe009).w(FUNC(skyfox_state::output_w)); + map(0xe008, 0xe008).w(FUNC(skyfox_state::bg_ctrl_w)); + map(0xe009, 0xe009).w("soundlatch", FUNC(generic_latch_8_device::write)); // map(0xe00a, 0xe00e) // POST only? map(0xe00f, 0xe00f).nopw(); // DMA trigger map(0xf001, 0xf001).portr("DSW2"); @@ -76,7 +356,7 @@ void skyfox_state::skyfox_map(address_map &map) ***************************************************************************/ -void skyfox_state::skyfox_sound_map(address_map &map) +void skyfox_state::sound_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0x87ff).ram(); @@ -84,7 +364,7 @@ void skyfox_state::skyfox_sound_map(address_map &map) map(0xa000, 0xa001).rw("ym1", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); // map(0xb000, 0xb001).nopw(); // ?? map(0xc000, 0xc001).rw("ym2", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); - map(0xb000, 0xb000).r(m_soundlatch, FUNC(generic_latch_8_device::read)); + map(0xb000, 0xb000).r("soundlatch", FUNC(generic_latch_8_device::read)); } @@ -146,7 +426,7 @@ static INPUT_PORTS_START( skyfox ) PORT_DIPSETTING( 0x04, DEF_STR( 1C_2C ) ) PORT_DIPSETTING( 0x08, DEF_STR( 1C_3C ) ) PORT_DIPSETTING( 0x0c, DEF_STR( 1C_4C ) ) - /* According to manual, there is also "SW2:4" which has to be always OFF */ + // According to manual, there is also "SW2:4" which has to be always OFF PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) @@ -169,8 +449,8 @@ static INPUT_PORTS_START( skyfox ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("COINS") // Fake input port, coins are directly connected on NMI line - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, skyfox_state,coin_inserted, 0) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, skyfox_state,coin_inserted, 0) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, skyfox_state, coin_inserted, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, skyfox_state, coin_inserted, 0) INPUT_PORTS_END @@ -187,7 +467,7 @@ INPUT_PORTS_END support 8x8, 16x16 and 32x32 sprites. */ static GFXDECODE_START( gfx_skyfox ) - GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x8_raw, 0, 1 ) // [0] Sprites + GFXDECODE_ENTRY( "sprites", 0, gfx_8x8x8_raw, 0, 1 ) GFXDECODE_END @@ -209,35 +489,35 @@ void skyfox_state::machine_reset() void skyfox_state::skyfox(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(8'000'000)/2); /* Verified at 4MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &skyfox_state::skyfox_map); + // basic machine hardware + Z80(config, m_maincpu, XTAL(8'000'000) / 2); // Verified at 4MHz + m_maincpu->set_addrmap(AS_PROGRAM, &skyfox_state::main_map); // IM0, never enables ei opcode - Z80(config, m_audiocpu, XTAL(14'318'181)/8); /* Verified at 1.789772MHz */ - m_audiocpu->set_addrmap(AS_PROGRAM, &skyfox_state::skyfox_sound_map); + Z80(config, m_audiocpu, XTAL(14'318'181) / 8); // Verified at 1.789772MHz + m_audiocpu->set_addrmap(AS_PROGRAM, &skyfox_state::sound_map); - /* video hardware */ + // video hardware SCREEN(config, m_screen, SCREEN_TYPE_RASTER); // TODO: legacy screen configuration with no vblank irq m_screen->set_refresh_hz(62.65); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate m_screen->set_size(512, 256); m_screen->set_visarea(0+0x60, 320-1+0x60, 0+16, 256-1-16); // from $30*2 to $CC*2+8 - m_screen->set_screen_update(FUNC(skyfox_state::screen_update_skyfox)); + m_screen->set_screen_update(FUNC(skyfox_state::screen_update)); m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_skyfox); - PALETTE(config, m_palette, FUNC(skyfox_state::skyfox_palette), 256); // 256 static colors + PALETTE(config, m_palette, FUNC(skyfox_state::palette), 256); // 256 static colors - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); - GENERIC_LATCH_8(config, m_soundlatch); + GENERIC_LATCH_8(config, "soundlatch"); - YM2203(config, "ym1", XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "mono", 0.80); /* Verified at 1.789772MHz */ + YM2203(config, "ym1", XTAL(14'318'181) / 8).add_route(ALL_OUTPUTS, "mono", 0.80); // Verified at 1.789772MHz - YM2203(config, "ym2", XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "mono", 0.80); /* Verified at 1.789772MHz */ + YM2203(config, "ym2", XTAL(14'318'181) / 8).add_route(ALL_OUTPUTS, "mono", 0.80); // Verified at 1.789772MHz } @@ -308,14 +588,14 @@ Video Board: Jaleco made in japan ER-8737 ROM_START( skyfox ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* Main Z80 Code */ + ROM_REGION( 0x10000, "maincpu", 0 ) // Z80 code ROM_LOAD( "skyfox1.bin", 0x00000, 0x8000, CRC(b4d4bb6f) SHA1(ed1cf6d91ca7170cb7d1c80b586c11164430fd49) ) ROM_LOAD( "skyfox2.bin", 0x08000, 0x8000, CRC(e15e0263) SHA1(005934327834aed46b17161aef82117ee508e9c4) ) // identical halves - ROM_REGION( 0x10000, "audiocpu", 0 ) /* Sound Z80 Code */ + ROM_REGION( 0x10000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "skyfox9.bin", 0x00000, 0x8000, CRC(0b283bf5) SHA1(5b14d0beea689ee7e9174017e5a127435df4fbe3) ) - ROM_REGION( 0x60000, "gfx1", 0 ) /* Sprites */ + ROM_REGION( 0x60000, "sprites", 0 ) ROM_LOAD( "skyfox3.bin", 0x00000, 0x10000, CRC(3a17a929) SHA1(973fb36af416161e04a83d7869819d9b13df18cd) ) ROM_LOAD( "skyfox4.bin", 0x10000, 0x10000, CRC(358053bb) SHA1(589e3270eda0d44e73fbc7ac06e782f332920b39) ) ROM_LOAD( "skyfox5.bin", 0x20000, 0x10000, CRC(c1215a6e) SHA1(5ca30be8a68ac6a00907cc9e47ede0acec980f46) ) @@ -323,24 +603,24 @@ ROM_START( skyfox ) ROM_LOAD( "skyfox7.bin", 0x40000, 0x10000, CRC(fa2ab5b4) SHA1(c0878b25dae28f7d49e14376ff885d1d4e3d5dfe) ) ROM_LOAD( "skyfox8.bin", 0x50000, 0x10000, CRC(0e3edc49) SHA1(3d1c59ecaabe1c9517203b7e814db41d5cff0cd4) ) - ROM_REGION( 0x08000, "gfx2", 0 ) /* Background */ + ROM_REGION( 0x08000, "tiles", 0 ) ROM_LOAD( "skyfox10.bin", 0x0000, 0x8000, CRC(19f58f9c) SHA1(6887216243b47152129448cbb4c7d52309feed03) ) - ROM_REGION( 0x300, "proms", 0 ) /* Color Proms */ + ROM_REGION( 0x300, "proms", 0 ) // colors ROM_LOAD( "sfoxrprm.bin", 0x000, 0x100, CRC(79913c7f) SHA1(e64e6a3eb55f37984cb2597c8ffba6bc3bad49c7) ) // R ROM_LOAD( "sfoxgprm.bin", 0x100, 0x100, CRC(fb73d434) SHA1(4a9bd61fbdce9441753c5921f95ead5c4655957e) ) // G ROM_LOAD( "sfoxbprm.bin", 0x200, 0x100, CRC(60d2ab41) SHA1(e58a54f2aaee5c07136d5437e513d61fb18fbd9f) ) // B ROM_END ROM_START( exerizer ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* Main Z80 Code */ + ROM_REGION( 0x10000, "maincpu", 0 ) // Z80 code ROM_LOAD( "1.2v", 0x00000, 0x8000, CRC(5df72a5d) SHA1(ca35ac06f3702fd650a584da2f442fbc61c00fce) ) ROM_LOAD( "2.3v", 0x08000, 0x8000, CRC(e15e0263) SHA1(005934327834aed46b17161aef82117ee508e9c4) ) // 1-b - ROM_REGION( 0x10000, "audiocpu", 0 ) /* Sound Z80 Code */ + ROM_REGION( 0x10000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "9.5n", 0x00000, 0x8000, CRC(0b283bf5) SHA1(5b14d0beea689ee7e9174017e5a127435df4fbe3) ) // 1-i - ROM_REGION( 0x60000, "gfx1", 0 ) /* Sprites */ + ROM_REGION( 0x60000, "sprites", 0 ) ROM_LOAD( "3-1.7w", 0x00000, 0x10000, CRC(3a17a929) SHA1(973fb36af416161e04a83d7869819d9b13df18cd) ) ROM_LOAD( "4.7u", 0x10000, 0x10000, CRC(358053bb) SHA1(589e3270eda0d44e73fbc7ac06e782f332920b39) ) // 1-d ROM_LOAD( "5-1.7t", 0x20000, 0x10000, CRC(c1215a6e) SHA1(5ca30be8a68ac6a00907cc9e47ede0acec980f46) ) @@ -348,24 +628,24 @@ ROM_START( exerizer ) ROM_LOAD( "7.7p", 0x40000, 0x10000, CRC(c9bbfe5c) SHA1(ce3f7d32baa8bb0bfc110877b5b5f4648ee959ac) ) ROM_LOAD( "8.7n", 0x50000, 0x10000, CRC(0e3edc49) SHA1(3d1c59ecaabe1c9517203b7e814db41d5cff0cd4) ) // 1-h - ROM_REGION( 0x08000, "gfx2", 0 ) /* Background */ + ROM_REGION( 0x08000, "tiles", 0 ) ROM_LOAD( "10.5e", 0x0000, 0x8000, CRC(19f58f9c) SHA1(6887216243b47152129448cbb4c7d52309feed03) ) // 1-j - ROM_REGION( 0x300, "proms", 0 ) /* Color Proms */ + ROM_REGION( 0x300, "proms", 0 ) // colors ROM_LOAD( "r.1c", 0x000, 0x100, CRC(79913c7f) SHA1(e64e6a3eb55f37984cb2597c8ffba6bc3bad49c7) ) // 2-bpr ROM_LOAD( "g.1b", 0x100, 0x100, CRC(fb73d434) SHA1(4a9bd61fbdce9441753c5921f95ead5c4655957e) ) // 3-bpr ROM_LOAD( "b.1d", 0x200, 0x100, CRC(60d2ab41) SHA1(e58a54f2aaee5c07136d5437e513d61fb18fbd9f) ) // 1-bpr ROM_END ROM_START( exerizerb ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* Main Z80 Code */ + ROM_REGION( 0x10000, "maincpu", 0 ) // Z80 code ROM_LOAD( "1-a", 0x00000, 0x8000, CRC(5df72a5d) SHA1(ca35ac06f3702fd650a584da2f442fbc61c00fce) ) ROM_LOAD( "skyfox2.bin", 0x08000, 0x8000, CRC(e15e0263) SHA1(005934327834aed46b17161aef82117ee508e9c4) ) // 1-b - ROM_REGION( 0x10000, "audiocpu", 0 ) /* Sound Z80 Code */ + ROM_REGION( 0x10000, "audiocpu", 0 ) // Z80 code ROM_LOAD( "skyfox9.bin", 0x00000, 0x8000, CRC(0b283bf5) SHA1(5b14d0beea689ee7e9174017e5a127435df4fbe3) ) // 1-i - ROM_REGION( 0x60000, "gfx1", 0 ) /* Sprites */ + ROM_REGION( 0x60000, "sprites", 0 ) ROM_LOAD( "1-c", 0x00000, 0x10000, CRC(450e9381) SHA1(f99b2ca73f1e4ba91b8066bb6d28d33b66a3ee81) ) ROM_LOAD( "skyfox4.bin", 0x10000, 0x10000, CRC(358053bb) SHA1(589e3270eda0d44e73fbc7ac06e782f332920b39) ) // 1-d ROM_LOAD( "1-e", 0x20000, 0x10000, CRC(50a38c60) SHA1(a4b8d530914d6c85b15940a7821b4365068de668) ) @@ -373,21 +653,21 @@ ROM_START( exerizerb ) ROM_LOAD( "1-g", 0x40000, 0x10000, CRC(c9bbfe5c) SHA1(ce3f7d32baa8bb0bfc110877b5b5f4648ee959ac) ) ROM_LOAD( "skyfox8.bin", 0x50000, 0x10000, CRC(0e3edc49) SHA1(3d1c59ecaabe1c9517203b7e814db41d5cff0cd4) ) // 1-h - ROM_REGION( 0x08000, "gfx2", 0 ) /* Background */ + ROM_REGION( 0x08000, "tiles", 0 ) ROM_LOAD( "skyfox10.bin", 0x0000, 0x8000, CRC(19f58f9c) SHA1(6887216243b47152129448cbb4c7d52309feed03) ) // 1-j - ROM_REGION( 0x300, "proms", 0 ) /* Color Proms */ + ROM_REGION( 0x300, "proms", 0 ) // colors ROM_LOAD( "sfoxrprm.bin", 0x000, 0x100, CRC(79913c7f) SHA1(e64e6a3eb55f37984cb2597c8ffba6bc3bad49c7) ) // 2-bpr ROM_LOAD( "sfoxgprm.bin", 0x100, 0x100, CRC(fb73d434) SHA1(4a9bd61fbdce9441753c5921f95ead5c4655957e) ) // 3-bpr ROM_LOAD( "sfoxbprm.bin", 0x200, 0x100, CRC(60d2ab41) SHA1(e58a54f2aaee5c07136d5437e513d61fb18fbd9f) ) // 1-bpr ROM_END -/* Untangle the graphics: cut each 32x32x8 tile in 16 8x8x8 tiles */ +// Untangle the graphics: cut each 32x32x8 tile in 16 8x8x8 tiles void skyfox_state::init_skyfox() { - uint8_t *rom = memregion("gfx1")->base(); - uint8_t *end = rom + memregion("gfx1")->bytes(); + uint8_t *rom = memregion("sprites")->base(); + uint8_t *end = rom + memregion("sprites")->bytes(); uint8_t buf[32 * 32]; while (rom < end) @@ -400,7 +680,9 @@ void skyfox_state::init_skyfox() } } +} // anonymous namespace + -GAME( 1987, skyfox, 0, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "Jaleco (Nichibutsu USA license)", "Sky Fox", MACHINE_SUPPORTS_SAVE ) -GAME( 1987, exerizer, skyfox, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "Jaleco", "Exerizer (Japan)", MACHINE_SUPPORTS_SAVE ) -GAME( 1987, exerizerb, skyfox, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "bootleg", "Exerizer (bootleg)", MACHINE_SUPPORTS_SAVE ) +GAME( 1987, skyfox, 0, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "Jaleco (Nichibutsu USA license)", "Sky Fox", MACHINE_SUPPORTS_SAVE ) +GAME( 1987, exerizer, skyfox, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "Jaleco", "Exerizer (Japan)", MACHINE_SUPPORTS_SAVE ) +GAME( 1987, exerizerb, skyfox, skyfox, skyfox, skyfox_state, init_skyfox, ROT90, "bootleg", "Exerizer (bootleg)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/jaleco/skyfox.h b/src/mame/jaleco/skyfox.h deleted file mode 100644 index 234a31eb31f..00000000000 --- a/src/mame/jaleco/skyfox.h +++ /dev/null @@ -1,63 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Luca Elia -/************************************************************************* - - Skyfox - -*************************************************************************/ -#ifndef MAME_INCLUDES_SKYFOX_H -#define MAME_INCLUDES_SKYFOX_H - -#pragma once - -#include "machine/gen_latch.h" -#include "emupal.h" -#include "screen.h" - -class skyfox_state : public driver_device -{ -public: - skyfox_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_screen(*this, "screen"), - m_palette(*this, "palette"), - m_soundlatch(*this, "soundlatch"), - m_spriteram(*this, "spriteram"), - m_bgram(*this, "bgram") - { } - - void skyfox(machine_config &config); - - void init_skyfox(); - - DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); - -private: - /* devices/memory pointers */ - required_device m_maincpu; - required_device m_audiocpu; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - required_device m_soundlatch; - required_shared_ptr m_spriteram; - required_shared_ptr m_bgram; - - int m_bg_ctrl = 0; - - void output_w(offs_t offset, uint8_t data); - virtual void machine_start() override; - virtual void machine_reset() override; - void skyfox_palette(palette_device &palette) const; - uint32_t screen_update_skyfox(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ); - void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect); - - void skyfox_map(address_map &map); - void skyfox_sound_map(address_map &map); -}; - -#endif // MAME_INCLUDES_SKYFOX_H diff --git a/src/mame/jaleco/skyfox_v.cpp b/src/mame/jaleco/skyfox_v.cpp deleted file mode 100644 index 22c10647343..00000000000 --- a/src/mame/jaleco/skyfox_v.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Luca Elia -/*************************************************************************** - - -= Sky Fox / Exerizer =- - - driver by Luca Elia (l.elia@tin.it) - - - [ 1 Background ] - - The stars in the background are not tile based (I think!) and - their rendering is entirely guesswork for now.. - - I draw a star for each horizontal line using 2 bytes in the - background rom: - - - the first byte seems a color / shape info - - the second byte seems a position info - - The rom holds 4 chunks of $2000 bytes. Most of the data does not - change between chunks, while the remaining part (which is rendered - to what seems a "milky way") pulsates in color and/or shape - to simulate the shimmering of stars (?!) if we draw one chunk only - and cycle through the four. Indeed, there's a register cycling - through 4 values. - - Since the result kind of matches a screenshot we have, I feel the - drawn result is not that far from reality. On the other hand we - have a random arrangement of stars, so it's hard to tell for sure.. - - [ 256 Sprites ] - - Sprites are 8 planes deep and can be 8x8, 16x16 or 32x32 pixels - in size. They are stored as 32x32x8 tiles in the ROMs. - - -***************************************************************************/ - -#include "emu.h" -#include "video/resnet.h" -#include "skyfox.h" - - -/*************************************************************************** - - Convert the color PROMs into a more useable format. - - There are three 256x4 palette PROMs (one per gun). - The palette PROMs are connected to the RGB output this way: - - bit 3 -- 110 ohm resistor -- RED/GREEN/BLUE - -- 220 ohm resistor -- RED/GREEN/BLUE - -- 680 ohm resistor -- RED/GREEN/BLUE - bit 0 -- 1.2kohm resistor -- RED/GREEN/BLUE - -***************************************************************************/ - -static constexpr res_net_decode_info skyfox_decode_info = -{ - 1, - 0, 255, // start/end - // R, G, B, - { 0, 0x100, 0x200, }, // offsets - { 0, 0, 0, }, // shifts - { 0xf, 0xf, 0xf, } // masks -}; - -static constexpr res_net_info skyfox_net_info = -{ - RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT, - { - { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } }, - { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } }, - { RES_NET_AMP_NONE, 0, 0, 4, { 1200, 680, 220, 110 } } - } -}; - -void skyfox_state::skyfox_palette(palette_device &palette) const -{ - uint8_t const *const color_prom = memregion("proms")->base(); - std::vector rgb; - - compute_res_net_all(rgb, color_prom, skyfox_decode_info, skyfox_net_info); - palette.set_pen_colors(0, rgb); -} - - -/*************************************************************************** - - Sprites Drawing - -Offset: Value: - -03 Code: selects one of the 32x32 tiles in the ROMs. - (Tiles $80-ff are bankswitched to cover $180 tiles) - -02 Code + Attr - - 7654 ---- Code (low 4 bits) - 8x8 sprites use bits 7654 (since there are 16 8x8 tiles in the 32x32 one) - 16x16 sprites use bits --54 (since there are 4 16x16 tiles in the 32x32 one) - 32x32 sprites use no bits (since the 32x32 tile is already selected) - - 7--- 3--- Size - 1--- 1--- : 32x32 sprites - 0--- 1--- : 16x16 sprites - 8x8 sprites otherwise - - ---- -2-- Flip Y - ---- --1- Flip X - ---- ---0 X Low Bit - -00 Y - -01 X (High 8 Bits) - -***************************************************************************/ - -void skyfox_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) -{ - gfx_element *gfx = m_gfxdecode->gfx(0); - int width = m_screen->width(); - int height = m_screen->height(); - - /* The 32x32 tiles in the 80-ff range are bankswitched */ - int shift = (m_bg_ctrl & 0x80) ? (4 - 1) : 4; - - for (int offs = 0; offs < m_spriteram.bytes(); offs += 4) - { - int xstart, ystart, xend, yend; - int xinc, yinc, dx, dy; - int low_code, high_code, n; - - int code = m_spriteram[offs + 3] << 8 | m_spriteram[offs + 2]; - int flipx = code & 0x2; - int flipy = code & 0x4; - int y = m_spriteram[offs + 0]; - int x = m_spriteram[offs + 1] << 1 | (code & 1); - - high_code = ((code >> 4) & 0x7f0) + ((code & 0x8000) >> shift); - - switch (code & 0x88) - { - case 0x88: n = 4; low_code = 0; break; - case 0x08: n = 2; low_code = (code & 0x20) >> 2 | (code & 0x10) >> 3; break; - default: n = 1; low_code = (code >> 4) & 0xf; break; - } - - if (m_bg_ctrl & 1) // flipscreen - { - x = width - x - n * 8; - y = height - y - n * 8; - flipx = !flipx; - flipy = !flipy; - } - - if (flipx) { xstart = n - 1; xend = -1; xinc = -1; } - else { xstart = 0; xend = n; xinc = +1; } - - if (flipy) { ystart = n - 1; yend = -1; yinc = -1; } - else { ystart = 0; yend = n; yinc = +1; } - - - code = low_code + high_code; - - for (dy = ystart; dy != yend; dy += yinc) - { - for (dx = xstart; dx != xend; dx += xinc, code++) - { - gfx->transpen(bitmap, cliprect, code, 0, flipx, flipy, dx*8 + x, dy*8 + y, 0xff); - - // wraparound y - BTANB: large sprites exiting the screen sometimes reappear on the other edge - gfx->transpen(bitmap, cliprect, code, 0, flipx, flipy, dx*8 + x, dy*8 + y - 256, 0xff); - } - - if (n == 2) - code += 2; - } - } -} - - - -/*************************************************************************** - - Background Rendering - -***************************************************************************/ - -void skyfox_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - uint8_t *rom = memregion("gfx2")->base(); - - /* Blinking stops until the first star moves after turning on the power */ - bool blinking = (m_bg_ctrl & 0x8); - /* Star pattern change. This will change at when all star clusters to out of screen or when player restart. - When it changes, will change color of star clusters. */ - int pattern = (m_bg_ctrl & 0x6) >> 1; - - for (int i = 0; i < 0x1000; i++) - { - /* contains the position of stars from 0xd4e0 in RAM */ - int ramoffset = 0xe0 + (i & 0xf) * 2; - int pos = m_bgram[ramoffset + 1] * 2 + ((m_bgram[ramoffset] & 0x80) ? 1 : 0); - - /* ROM offset of star pattern */ - int offs = (i * 2) % 0x2000 + pattern * 0x2000; - - /* Adjusted with 1 pixel accuracy compared to PCB. - Confirmed that pixel and color pattern match in the "1UP START" screen. */ - int pen = rom[offs]; - int x = rom[offs + 1] * 2 + pos + 0x5b; - int y = (i >> 4) + 1; - - /* When flipscreen is enabled, scroll direction is flipped by only in-game subroutine. - This PCB seems does not support background flip. */ - - /* This looks perfect at first glance. - but when strict compared on "1UP START" screen, - it seems the blinking pattern in each star may be different. */ - if (((m_bg_ctrl >> 4) & 3) != (pen & 3) || !blinking) - bitmap.pix(y % 256, x % 512) = pen; - } -} - - -/*************************************************************************** - - Screen Drawing - -***************************************************************************/ - -uint32_t skyfox_state::screen_update_skyfox(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - bitmap.fill(0xff, cliprect); // the bg is black - draw_background(bitmap, cliprect); - draw_sprites(bitmap, cliprect); - return 0; -} diff --git a/src/mame/omori/battlex.cpp b/src/mame/omori/battlex.cpp index a2f77aae534..d096fb7e779 100644 --- a/src/mame/omori/battlex.cpp +++ b/src/mame/omori/battlex.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:David Haywood +// copyright-holders: David Haywood + /*************************************************************************** Omori Battle Cross @@ -12,7 +13,7 @@ Its effect is the following : * you need to insert at least one credit and start a game * when the game is over, you can start another games WITHOUT - inserting another coins + inserting another coin Note that the number of credits is decremented though. Credits are BCD coded on 3 bytes (0x000000-0x999999) at addresses 0xa039 (LSB), 0xa03a and 0xa03b (MSB), but only the LSB is displayed. @@ -25,7 +26,7 @@ Each 8x8 BG tile is defined by: - 1 bit 8x8 mask (one tile - 8 consecutive bytes - user2 region) - - 4+4 bits of color ( one tile - 8 consecutive bytes - user1 region) + - 4+4 bits of color (one tile - 8 consecutive bytes - user1 region) - bit 3 of color = brightness ? Single mask byte defines one row of tile pixels (FG or BG) @@ -57,13 +58,13 @@ - missing starfield - - game speed, its seems to be controlled by the IRQ's, how fast should it - be? firing seems frustratingly inconsistant (better with PORT_IMPULSE) + - game speed, it seems to be controlled by the IRQ's, how fast should it + be? firing seems frustratingly inconsistent (better with PORT_IMPULSE) - - BG tilemap palette bits (in most cases paltte 0 is used, - only highlights ( battlex logo, hiscore table) uses different palettes(?). + - BG tilemap palette bits (in most cases palette 0 is used, + only highlights (battlex logo, hiscore table) use different palettes(?). Current implementation gives different highlight colors than on real - hardware (i.e. battlex logo should have yellow highights) + hardware (i.e. battlex logo should have yellow highlights) **************************************************************************** @@ -82,21 +83,215 @@ #include "emu.h" -#include "battlex.h" #include "cpu/z80/z80.h" #include "sound/ay8910.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { + +class battlex_state : public driver_device +{ +public: + battlex_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_palette(*this, "palette"), + m_videoram(*this, "videoram"), + m_spriteram(*this, "spriteram") + { } + + void init_battlex(); + + void battlex(machine_config &config); + + DECLARE_CUSTOM_INPUT_MEMBER(in0_b4_r); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + + // devices + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_palette; + + // memory pointers + required_shared_ptr m_videoram; + required_shared_ptr m_spriteram; + + tilemap_t *m_bg_tilemap = nullptr; + + void io_map(address_map &map); + +private: + // video-related + uint8_t m_scroll_lsb = 0U; + uint8_t m_scroll_msb = 0U; + uint8_t m_starfield_enabled = 0U; + + uint8_t m_in0_b4 = 0U; + + void palette_w(offs_t offset, uint8_t data); + void scroll_x_lsb_w(uint8_t data); + void scroll_x_msb_w(uint8_t data); + void scroll_starfield_w(uint8_t data); + void videoram_w(offs_t offset, uint8_t data); + void flipscreen_w(uint8_t data); + TILE_GET_INFO_MEMBER(get_bg_tile_info); + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + INTERRUPT_GEN_MEMBER(interrupt); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + + void main_map(address_map &map); +}; + +class dodgeman_state : public battlex_state +{ +public: + using battlex_state::battlex_state; + + void dodgeman(machine_config &config); + +protected: + virtual void video_start() override; + +private: + TILE_GET_INFO_MEMBER(get_bg_tile_info); + + void io_map(address_map &map); +}; + +// video + +void battlex_state::palette_w(offs_t offset, uint8_t data) +{ + int const palette_num = offset / 8; + int const color_num = offset & 7; + + m_palette->set_pen_color(offset, pal1bit(data >> 0), pal1bit(data >> 2), pal1bit(data >> 1)); + // set darker colors + m_palette->set_pen_color(64 + palette_num * 16 + color_num, pal1bit(data >> 0), pal1bit(data >> 2), pal1bit(data >> 1)); + m_palette->set_pen_color(64 + palette_num * 16 + color_num + 8, pal2bit((data >> 0) & 1), pal2bit((data >> 2) & 1), pal2bit((data >> 1) & 1)); +} + +void battlex_state::scroll_x_lsb_w(uint8_t data) +{ + m_scroll_lsb = data; +} + +void battlex_state::scroll_x_msb_w(uint8_t data) +{ + m_scroll_msb = data; +} + +void battlex_state::scroll_starfield_w(uint8_t data) +{ +} + +void battlex_state::videoram_w(offs_t offset, uint8_t data) +{ + m_videoram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset / 2); +} + +void battlex_state::flipscreen_w(uint8_t data) +{ + m_starfield_enabled = data & 0x10; + + if (flip_screen() != (data >> 7)) + { + flip_screen_set(data & 0x80); + machine().tilemap().mark_all_dirty(); + } +} + + +TILE_GET_INFO_MEMBER(battlex_state::get_bg_tile_info) +{ + int const tile = m_videoram[tile_index * 2] | (((m_videoram[tile_index * 2 + 1] & 0x01)) << 8); + int const color = (m_videoram[tile_index * 2 + 1] & 0x0e) >> 1; // high bits unused + + tileinfo.set(0, tile, color, 0); +} + +TILE_GET_INFO_MEMBER(dodgeman_state::get_bg_tile_info) +{ + int const tile = m_videoram[tile_index * 2] | (((m_videoram[tile_index * 2 + 1] & 0x03)) << 8); + int const color = (m_videoram[tile_index * 2 + 1] & 0x0c) >> 2; // high bits unused + tileinfo.set(0, tile, color, 0); +} -INTERRUPT_GEN_MEMBER(battlex_state::battlex_interrupt) +void battlex_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(battlex_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); +} + +void dodgeman_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dodgeman_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); +} + +void battlex_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + gfx_element *gfx = m_gfxdecode->gfx(1); + uint8_t const *source = m_spriteram; + uint8_t const *finish = m_spriteram + 0x200; + + while (source < finish) + { + int sx = (source[0] & 0x7f) * 2 - (source[0] & 0x80) * 2; + int sy = source[3]; + int const tile = source[2] ; // dodgeman has 0x100 sprites + int const color = source[1] & 0x07; // bits 3, 4, 5 also used during explosions + int flipy = source[1] & 0x80; + int flipx = source[1] & 0x40; + + if (flip_screen()) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + gfx->transpen(bitmap, cliprect, tile, color, flipx, flipy, sx, sy, 0); + source += 4; + } + +} + +uint32_t battlex_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (!flip_screen()) + m_bg_tilemap->set_scrollx(0, m_scroll_lsb | (m_scroll_msb << 8)); + else + m_bg_tilemap->set_scrollx(0, m_scroll_lsb | (m_scroll_msb << 3)); + + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + draw_sprites(bitmap, cliprect); + + return 0; +} + + +// machine + +INTERRUPT_GEN_MEMBER(battlex_state::interrupt) { m_in0_b4 = 1; device.execute().set_input_line(0, ASSERT_LINE); } -CUSTOM_INPUT_MEMBER(battlex_state::battlex_in0_b4_r) +CUSTOM_INPUT_MEMBER(battlex_state::in0_b4_r) { uint32_t ret = m_in0_b4; if (m_in0_b4) @@ -115,13 +310,13 @@ CUSTOM_INPUT_MEMBER(battlex_state::battlex_in0_b4_r) * *************************************/ -void battlex_state::battlex_map(address_map &map) +void battlex_state::main_map(address_map &map) { map(0x0000, 0x5fff).rom(); - map(0x8000, 0x8fff).ram().w(FUNC(battlex_state::battlex_videoram_w)).share("videoram"); - map(0x9000, 0x91ff).ram().share("spriteram"); + map(0x8000, 0x8fff).ram().w(FUNC(battlex_state::videoram_w)).share(m_videoram); + map(0x9000, 0x91ff).ram().share(m_spriteram); map(0xa000, 0xa3ff).ram(); - map(0xe000, 0xe03f).ram().w(FUNC(battlex_state::battlex_palette_w)); + map(0xe000, 0xe03f).ram().w(FUNC(battlex_state::palette_w)); } @@ -132,18 +327,18 @@ void battlex_state::io_map(address_map &map) map(0x01, 0x01).portr("SYSTEM"); map(0x02, 0x02).portr("INPUTS"); map(0x03, 0x03).portr("DSW2"); - map(0x10, 0x10).w(FUNC(battlex_state::battlex_flipscreen_w)); + map(0x10, 0x10).w(FUNC(battlex_state::flipscreen_w)); - /* verify all of these */ + // verify all of these map(0x22, 0x23).w("ay1", FUNC(ay8910_device::data_address_w)); - map(0x30, 0x30).w(FUNC(battlex_state::battlex_scroll_starfield_w)); - map(0x32, 0x32).w(FUNC(battlex_state::battlex_scroll_x_lsb_w)); - map(0x33, 0x33).w(FUNC(battlex_state::battlex_scroll_x_msb_w)); + map(0x30, 0x30).w(FUNC(battlex_state::scroll_starfield_w)); + map(0x32, 0x32).w(FUNC(battlex_state::scroll_x_lsb_w)); + map(0x33, 0x33).w(FUNC(battlex_state::scroll_x_msb_w)); } -void battlex_state::dodgeman_io_map(address_map &map) +void dodgeman_state::io_map(address_map &map) { - io_map(map); + battlex_state::io_map(map); map(0x26, 0x27).w("ay2", FUNC(ay8910_device::data_address_w)); } @@ -154,7 +349,7 @@ void battlex_state::dodgeman_io_map(address_map &map) *************************************/ static INPUT_PORTS_START( battlex ) - PORT_START("DSW1") /* IN0 */ + PORT_START("DSW1") // IN0 PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coin_A ) ) PORT_DIPSETTING( 0x02, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) @@ -166,7 +361,7 @@ static INPUT_PORTS_START( battlex ) PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(battlex_state, battlex_in0_b4_r) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(battlex_state, in0_b4_r) PORT_DIPNAME( 0x20, 0x20, DEF_STR( Cabinet ) ) PORT_DIPSETTING( 0x20, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) @@ -175,7 +370,7 @@ static INPUT_PORTS_START( battlex ) PORT_DIPSETTING( 0x40, DEF_STR( On ) ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_START("SYSTEM") /* IN1 */ + PORT_START("SYSTEM") // IN1 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) // TODO: PORT_IMPULSE? @@ -186,7 +381,7 @@ static INPUT_PORTS_START( battlex ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_START("INPUTS") /* IN2 */ + PORT_START("INPUTS") // IN2 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY @@ -196,7 +391,7 @@ static INPUT_PORTS_START( battlex ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL - PORT_START("DSW2") /* IN3 */ + PORT_START("DSW2") // IN3 PORT_DIPNAME( 0x07, 0x00, DEF_STR( Coin_B ) ) PORT_DIPSETTING( 0x07, DEF_STR( 3C_1C ) ) PORT_DIPSETTING( 0x05, DEF_STR( 2C_1C ) ) @@ -252,8 +447,8 @@ static const gfx_layout battlex_spritelayout = }; static GFXDECODE_START( gfx_battlex ) - GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x4_packed_msb, 64, 8 ) - GFXDECODE_ENTRY( "gfx2", 0, battlex_spritelayout, 0, 8 ) + GFXDECODE_ENTRY( "tiles", 0, gfx_8x8x4_packed_msb, 64, 8 ) + GFXDECODE_ENTRY( "sprites", 0, battlex_spritelayout, 0, 8 ) GFXDECODE_END @@ -265,7 +460,7 @@ GFXDECODE_END void battlex_state::machine_start() { - /* register for save states */ + // register for save states save_item(NAME(m_scroll_lsb)); save_item(NAME(m_scroll_msb)); save_item(NAME(m_starfield_enabled)); @@ -282,39 +477,38 @@ void battlex_state::machine_reset() void battlex_state::battlex(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(10'000'000)/4 ); // ? - m_maincpu->set_addrmap(AS_PROGRAM, &battlex_state::battlex_map); + // basic machine hardware + Z80(config, m_maincpu, XTAL(10'000'000) / 4 ); // divider not verified + m_maincpu->set_addrmap(AS_PROGRAM, &battlex_state::main_map); m_maincpu->set_addrmap(AS_IO, &battlex_state::io_map); - m_maincpu->set_periodic_int(FUNC(battlex_state::battlex_interrupt), attotime::from_hz(400)); /* controls game speed? */ + m_maincpu->set_periodic_int(FUNC(battlex_state::interrupt), attotime::from_hz(400)); // controls game speed? - /* 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, 30*8-1); - screen.set_screen_update(FUNC(battlex_state::screen_update_battlex)); + screen.set_screen_update(FUNC(battlex_state::screen_update)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_battlex); PALETTE(config, m_palette).set_entries(64 + 128); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); - AY8910(config, "ay1", XTAL(10'000'000)/8).add_route(ALL_OUTPUTS, "mono", 0.40); // ? + AY8910(config, "ay1", XTAL(10'000'000) / 8).add_route(ALL_OUTPUTS, "mono", 0.40); // divider not verified } -void battlex_state::dodgeman(machine_config &config) +void dodgeman_state::dodgeman(machine_config &config) { battlex(config); - m_maincpu->set_addrmap(AS_IO, &battlex_state::dodgeman_io_map); + m_maincpu->set_addrmap(AS_IO, &dodgeman_state::io_map); - MCFG_VIDEO_START_OVERRIDE(battlex_state, dodgeman) - AY8910(config, "ay2", XTAL(10'000'000)/8).add_route(ALL_OUTPUTS, "mono", 0.40); // ? + AY8910(config, "ay2", XTAL(10'000'000) / 8).add_route(ALL_OUTPUTS, "mono", 0.40); // divider not verified } @@ -333,9 +527,9 @@ ROM_START( battlex ) ROM_LOAD( "p-rom5.2", 0x4000, 0x1000, CRC(ceb63d38) SHA1(92cab905d009c59115f52172ba7d01c8ff8991d7) ) ROM_LOAD( "p-rom6.1", 0x5000, 0x1000, CRC(6923f601) SHA1(e6c33cbd8d8679299d7b2c568d56f96ed3073971) ) - ROM_REGION( 0x4000, "gfx1", ROMREGION_ERASE00 ) // filled in later + ROM_REGION( 0x4000, "tiles", ROMREGION_ERASE00 ) // filled in later - ROM_REGION( 0x3000, "gfx2", 0 ) + ROM_REGION( 0x3000, "sprites", 0 ) ROM_LOAD( "1a_f.6f", 0x0000, 0x1000, CRC(2b69287a) SHA1(30c0edaec44118b95ec390bd41c1bd49a2802451) ) ROM_LOAD( "1a_h.6h", 0x1000, 0x1000, CRC(9f4c3bdd) SHA1(e921ecafefe54c033d05d9cd289808e971ac7940) ) ROM_LOAD( "1a_j.6j", 0x2000, 0x1000, CRC(c1345b05) SHA1(17194c8ec961990222bd295ff1d036a64f497b0e) ) @@ -356,9 +550,9 @@ ROM_START( dodgeman ) ROM_LOAD( "dg4.2f", 0x4000, 0x001000, CRC(14169361) SHA1(86d3cd1fa0aa4f21029daea2eba99bdaa34372e8) ) ROM_LOAD( "dg5.1f", 0x5000, 0x001000, CRC(8f83ae2f) SHA1(daad41b61ba3d55531021d444bbe4acfc275cfc9) ) - ROM_REGION( 0x8000, "gfx1", ROMREGION_ERASE00 ) // filled in later + ROM_REGION( 0x8000, "tiles", ROMREGION_ERASE00 ) // filled in later - ROM_REGION( 0x6000, "gfx2", ROMREGION_ERASE00 ) + ROM_REGION( 0x6000, "sprites", ROMREGION_ERASE00 ) ROM_LOAD( "f.6f", 0x0000, 0x002000, CRC(dfaaf4c8) SHA1(1e09f1d72e7e5e6782d73ae60bca7982fc04df0e) ) ROM_LOAD( "h.6h", 0x2000, 0x002000, CRC(e2525ffe) SHA1(a17b608b4089014be381b26f16597b83d4a66ebd) ) ROM_LOAD( "j.6j", 0x4000, 0x002000, CRC(2731ee46) SHA1(15b9350e19f31b1cea99deb9935543777644e6a8) ) @@ -381,8 +575,8 @@ void battlex_state::init_battlex() { uint8_t *colormask = memregion("user1")->base(); uint8_t *gfxdata = memregion("user2")->base(); - uint8_t *dest = memregion("gfx1")->base(); - int tile_size = memregion("gfx1")->bytes() / 32; + uint8_t *dest = memregion("tiles")->base(); + int tile_size = memregion("tiles")->bytes() / 32; int offset = 0; for (int tile = 0; tile < tile_size; tile++) @@ -409,11 +603,14 @@ void battlex_state::init_battlex() } } +} // anonymous namespace + + /************************************* * * Game driver * *************************************/ -GAME( 1982, battlex, 0, battlex, battlex, battlex_state, init_battlex, ROT180, "Omori Electric Co., Ltd.", "Battle Cross", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL ) -GAME( 1983, dodgeman, 0, dodgeman, dodgeman, battlex_state, init_battlex, ROT180, "Omori Electric Co., Ltd.", "Dodge Man", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL ) +GAME( 1982, battlex, 0, battlex, battlex, battlex_state, init_battlex, ROT180, "Omori Electric Co., Ltd.", "Battle Cross", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL ) +GAME( 1983, dodgeman, 0, dodgeman, dodgeman, dodgeman_state, init_battlex, ROT180, "Omori Electric Co., Ltd.", "Dodge Man", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL ) diff --git a/src/mame/omori/battlex.h b/src/mame/omori/battlex.h deleted file mode 100644 index 3f5aca57b59..00000000000 --- a/src/mame/omori/battlex.h +++ /dev/null @@ -1,62 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/*************************************************************************** - - Battle Cross - -***************************************************************************/ - -#include "emupal.h" -#include "tilemap.h" - -class battlex_state : public driver_device -{ -public: - battlex_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_videoram(*this, "videoram"), - m_spriteram(*this, "spriteram"), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette") { } - - void init_battlex(); - void dodgeman(machine_config &config); - void battlex(machine_config &config); - DECLARE_CUSTOM_INPUT_MEMBER(battlex_in0_b4_r); - -private: - uint8_t m_in0_b4 = 0U; - - /* memory pointers */ - required_shared_ptr m_videoram; - required_shared_ptr m_spriteram; - - /* video-related */ - tilemap_t *m_bg_tilemap = nullptr; - uint8_t m_scroll_lsb = 0U; - uint8_t m_scroll_msb = 0U; - uint8_t m_starfield_enabled = 0U; - void battlex_palette_w(offs_t offset, uint8_t data); - void battlex_scroll_x_lsb_w(uint8_t data); - void battlex_scroll_x_msb_w(uint8_t data); - void battlex_scroll_starfield_w(uint8_t data); - void battlex_videoram_w(offs_t offset, uint8_t data); - void battlex_flipscreen_w(uint8_t data); - TILE_GET_INFO_MEMBER(get_bg_tile_info); - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - uint32_t screen_update_battlex(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - INTERRUPT_GEN_MEMBER(battlex_interrupt); - void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ); - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - - DECLARE_VIDEO_START(dodgeman); - TILE_GET_INFO_MEMBER(get_dodgeman_bg_tile_info); - void battlex_map(address_map &map); - void dodgeman_io_map(address_map &map); - void io_map(address_map &map); -}; diff --git a/src/mame/omori/battlex_v.cpp b/src/mame/omori/battlex_v.cpp deleted file mode 100644 index 899376181dd..00000000000 --- a/src/mame/omori/battlex_v.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/*************************************************************************** - - Video emulation for Omori Battle Cross - -***************************************************************************/ - -#include "emu.h" -#include "battlex.h" - - -void battlex_state::battlex_palette_w(offs_t offset, uint8_t data) -{ - int palette_num = offset / 8; - int color_num = offset & 7; - - m_palette->set_pen_color(offset, pal1bit(data >> 0), pal1bit(data >> 2), pal1bit(data >> 1)); - /* set darker colors */ - m_palette->set_pen_color(64+palette_num*16+color_num, pal1bit(data >> 0), pal1bit(data >> 2), pal1bit(data >> 1)); - m_palette->set_pen_color(64+palette_num*16+color_num+8, pal2bit((data >> 0)&1), pal2bit((data >> 2)&1), pal2bit( (data >> 1) &1)); -} - -void battlex_state::battlex_scroll_x_lsb_w(uint8_t data) -{ - m_scroll_lsb = data; -} - -void battlex_state::battlex_scroll_x_msb_w(uint8_t data) -{ - m_scroll_msb = data; -} - -void battlex_state::battlex_scroll_starfield_w(uint8_t data) -{ -} - -void battlex_state::battlex_videoram_w(offs_t offset, uint8_t data) -{ - m_videoram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset / 2); -} - -void battlex_state::battlex_flipscreen_w(uint8_t data) -{ - m_starfield_enabled = data & 0x10; - - if (flip_screen() != (data >> 7)) - { - flip_screen_set(data & 0x80); - machine().tilemap().mark_all_dirty(); - } -} - - -TILE_GET_INFO_MEMBER(battlex_state::get_bg_tile_info) -{ - int tile = m_videoram[tile_index * 2] | (((m_videoram[tile_index * 2 + 1] & 0x01)) << 8); - int color = (m_videoram[tile_index * 2 + 1] & 0x0e) >> 1; // high bits unused - - tileinfo.set(0, tile, color, 0); -} - -TILE_GET_INFO_MEMBER(battlex_state::get_dodgeman_bg_tile_info) -{ - int tile = m_videoram[tile_index * 2] | (((m_videoram[tile_index * 2 + 1] & 0x03)) << 8); - int color = (m_videoram[tile_index * 2 + 1] & 0x0c) >> 2; // high bits unused - - tileinfo.set(0, tile, color, 0); -} - -void battlex_state::video_start() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(battlex_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); -} - -void battlex_state::video_start_dodgeman() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(battlex_state::get_dodgeman_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); -} - -void battlex_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) -{ - gfx_element *gfx = m_gfxdecode->gfx(1); - uint8_t *source = m_spriteram; - uint8_t *finish = m_spriteram + 0x200; - - while (source < finish) - { - int sx = (source[0] & 0x7f) * 2 - (source[0] & 0x80) * 2; - int sy = source[3]; - int tile = source[2] ; /* dodgeman has 0x100 sprites */ - int color = source[1] & 0x07; /* bits 3,4,5 also used during explosions */ - int flipy = source[1] & 0x80; - int flipx = source[1] & 0x40; - - if (flip_screen()) - { - sx = 240 - sx; - sy = 240 - sy; - flipx = !flipx; - flipy = !flipy; - } - - gfx->transpen(bitmap,cliprect, tile, color, flipx, flipy, sx, sy, 0); - source += 4; - } - -} - -uint32_t battlex_state::screen_update_battlex(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - if (!flip_screen()) - m_bg_tilemap->set_scrollx(0, m_scroll_lsb | (m_scroll_msb << 8)); - else - m_bg_tilemap->set_scrollx(0, m_scroll_lsb | (m_scroll_msb << 3)); - - m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - draw_sprites(bitmap, cliprect); - - return 0; -} diff --git a/src/mame/omori/popper.cpp b/src/mame/omori/popper.cpp index e9e696fa2c2..63a6cd1f1fd 100644 --- a/src/mame/omori/popper.cpp +++ b/src/mame/omori/popper.cpp @@ -48,6 +48,8 @@ #include "tilemap.h" +namespace { + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -590,10 +592,12 @@ ROM_START( popper ) ROM_LOAD("p.m4", 0x20, 0x20, CRC(384de5c1) SHA1(892c89a01c11671c5708113b4e4c27b84be37ea6)) ROM_END +} // anonymous namespace + //************************************************************************** // SYSTEM DRIVERS //************************************************************************** -// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROTATION COMPANY FULLNAME FLAGS -GAME( 1983, popper, 0, popper, popper, popper_state, empty_init, ROT90, "Omori", "Popper", MACHINE_SUPPORTS_SAVE ) +// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROTATION COMPANY FULLNAME FLAGS +GAME( 1983, popper, 0, popper, popper, popper_state, empty_init, ROT90, "Omori Electric Co., Ltd.", "Popper", MACHINE_SUPPORTS_SAVE ) -- cgit v1.2.3