mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
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
This commit is contained in:
parent
753b54667f
commit
fa33564c68
@ -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"
|
||||
|
||||
|
||||
uint8_t aeroboto_state::aeroboto_201_r()
|
||||
// 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
|
||||
{
|
||||
/* 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 */
|
||||
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<uint8_t> m_mainram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_hscroll;
|
||||
required_shared_ptr<uint8_t> m_tilecolor;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_vscroll;
|
||||
required_shared_ptr<uint8_t> m_starx;
|
||||
required_shared_ptr<uint8_t> m_stary;
|
||||
required_shared_ptr<uint8_t> m_bgcolor;
|
||||
|
||||
// stars layout
|
||||
required_region_ptr<uint8_t> m_stars_rom;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_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<uint8_t> 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);
|
||||
|
||||
// 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
|
||||
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 )
|
||||
|
@ -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<uint8_t> m_mainram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_hscroll;
|
||||
required_shared_ptr<uint8_t> m_tilecolor;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_vscroll;
|
||||
required_shared_ptr<uint8_t> m_starx;
|
||||
required_shared_ptr<uint8_t> m_stary;
|
||||
required_shared_ptr<uint8_t> 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<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
void main_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_AEROBOTO_H
|
@ -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<uint8_t> 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;
|
||||
}
|
@ -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<uint8_t> m_main_ram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_region_ptr<uint8_t> m_maincpu_region;
|
||||
required_region_ptr<uint8_t> 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<uint16_t[]> m_background_gfx[4]{};
|
||||
uint8_t m_background_latches[13]{};
|
||||
|
||||
// protection?
|
||||
uint8_t m_porta = 0U;
|
||||
uint8_t m_portb = 0U;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_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<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[1] = std::make_unique<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[2] = std::make_unique<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[3] = std::make_unique<uint16_t[]>(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
|
||||
|
||||
|
||||
/*************************************
|
||||
|
@ -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<uint8_t> m_main_ram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_region_ptr<uint8_t> m_maincpu_region;
|
||||
required_region_ptr<uint8_t> 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<uint16_t[]> m_background_gfx[4]{};
|
||||
uint8_t m_background_latches[13]{};
|
||||
|
||||
// protection?
|
||||
uint8_t m_porta = 0U;
|
||||
uint8_t m_portb = 0U;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_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
|
@ -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<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[1] = std::make_unique<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[2] = std::make_unique<uint16_t[]>(256 * 256);
|
||||
m_background_gfx[3] = std::make_unique<uint16_t[]>(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;
|
||||
}
|
@ -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<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_spriteram;
|
||||
required_region_ptr<u8> m_bgdata_rom;
|
||||
required_region_ptr<u8> 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<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_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<u8> 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 )
|
||||
|
@ -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<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_spriteram;
|
||||
required_region_ptr<u8> m_bgdata_rom;
|
||||
required_region_ptr<u8> 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<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_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
|
@ -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;
|
||||
}
|
@ -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"
|
||||
|
||||
|
||||
#define MAIN_CLOCK XTAL(6'000'000)
|
||||
#define SOUND_CLOCK XTAL(3'579'545)
|
||||
// configurable logging
|
||||
#define LOG_VREGS (1U << 1)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL | LOG_VREGS)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGVREGS(...) LOGMASKED(LOG_VREGS, __VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
**
|
||||
** Main cpu data
|
||||
**
|
||||
*/
|
||||
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<u16> m_txtram;
|
||||
required_shared_ptr<u16> m_spriteram;
|
||||
required_shared_ptr<u16> m_vregs;
|
||||
required_shared_ptr<u16> m_fgram;
|
||||
|
||||
required_region_ptr<u8> 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<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<generic_latch_8_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);
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
|
||||
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 )
|
||||
|
@ -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<u16> m_txtram;
|
||||
required_shared_ptr<u16> m_spriteram;
|
||||
required_shared_ptr<u16> m_vregs;
|
||||
required_shared_ptr<u16> m_fgram;
|
||||
|
||||
required_region_ptr<u8> 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<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<generic_latch_8_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
|
@ -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;
|
||||
}
|
@ -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,14 +110,237 @@ 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 "speaker.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<cpu_device> m_maincpu;
|
||||
required_shared_ptr<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_spriteram;
|
||||
required_device<upd7756_device> m_d7756;
|
||||
optional_device<samples_device> m_samples;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_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
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@ -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?
|
||||
|
@ -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<cpu_device> m_maincpu;
|
||||
required_shared_ptr<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_spriteram;
|
||||
optional_device<upd7756_device> m_d7756;
|
||||
optional_device<samples_device> m_samples;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_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);
|
||||
};
|
@ -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;
|
||||
}
|
@ -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<u8> m_spriteram;
|
||||
required_shared_ptr<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_bg_scrolly;
|
||||
required_shared_ptr<u8> m_bg_scrollx;
|
||||
required_region_ptr<u8> m_bg_gfx;
|
||||
required_region_ptr<u8> m_bg_map;
|
||||
required_region_ptr<u8> m_bg_col_map;
|
||||
required_region_ptr<u8> m_fg_map;
|
||||
required_region_ptr<u8> m_proms;
|
||||
required_memory_bank m_bgbank;
|
||||
required_ioport m_io_fake;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_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 )
|
||||
|
@ -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<u8> m_spriteram;
|
||||
required_shared_ptr<u8> m_videoram;
|
||||
required_shared_ptr<u8> m_bg_scrolly;
|
||||
required_shared_ptr<u8> m_bg_scrollx;
|
||||
required_region_ptr<u8> m_bg_gfx;
|
||||
required_region_ptr<u8> m_bg_map;
|
||||
required_region_ptr<u8> m_bg_col_map;
|
||||
required_region_ptr<u8> m_fg_map;
|
||||
required_region_ptr<u8> 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<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
void momoko_map(address_map &map);
|
||||
void momoko_sound_map(address_map &map);
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_MOMOKO_H
|
@ -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;
|
||||
}
|
@ -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<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_bgram;
|
||||
required_region_ptr<uint8_t> 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
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
|
||||
[ 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_t> 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::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
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::output_w(offs_t offset, uint8_t data)
|
||||
void skyfox_state::bg_ctrl_w(uint8_t data)
|
||||
{
|
||||
// TODO: untangle
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
m_bg_ctrl = data;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_soundlatch->write(data);
|
||||
break;
|
||||
}
|
||||
m_bg_ctrl = data;
|
||||
}
|
||||
|
||||
void skyfox_state::skyfox_map(address_map &map)
|
||||
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 )
|
||||
|
@ -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<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> 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
|
@ -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_t> 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;
|
||||
}
|
@ -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"
|
||||
|
||||
|
||||
INTERRUPT_GEN_MEMBER(battlex_state::battlex_interrupt)
|
||||
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<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> 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);
|
||||
}
|
||||
|
||||
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 )
|
||||
|
@ -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<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> 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<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_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);
|
||||
};
|
@ -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;
|
||||
}
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user