- galaxian/galaxold.cpp: updated clock for superbikg as per measurement

- olympia/dday.cpp, olympia/portrait.cpp: consolidated drivers in single files

- skeleton/elcirculo.cpp: added a basic memory map

- vtech/vsmilepro.cpp: demoted to MIS
This commit is contained in:
Ivan Vangelista 2024-05-21 18:12:17 +02:00
parent f1a11f8b23
commit 855efc855c
10 changed files with 821 additions and 832 deletions

View File

@ -1863,7 +1863,7 @@ void galaxold_state::superbikg(machine_config &config)
{
galaxold_base(config);
s2650_device &s2650(S2650(config.replace(), m_maincpu, PIXEL_CLOCK / 4));
s2650_device &s2650(S2650(config.replace(), m_maincpu, 1'500'000)); // 1.53292 MHz measured with logic analyzer
s2650.set_addrmap(AS_PROGRAM, &galaxold_state::superbikg_map);
s2650.set_addrmap(AS_IO, &galaxold_state::superbikg_io);
s2650.set_addrmap(AS_DATA, &galaxold_state::superbikg_data);

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Zsolt Vasvari
// copyright-holders: Zsolt Vasvari
/***************************************************************************
D-Day
@ -52,27 +53,399 @@ write:
***************************************************************************/
#include "emu.h"
#include "dday.h"
#include "cpu/z80/z80.h"
#include "sound/ay8910.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "tilemap.h"
void dday_state::dday_map(address_map &map)
namespace {
class dday_state : public driver_device
{
public:
dday_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_textvideoram(*this, "textvideoram"),
m_fgvideoram(*this, "fgvideoram"),
m_bgvideoram(*this, "bgvideoram"),
m_colorram(*this, "colorram"),
m_sl_map(*this, "sl_map"),
m_maincpu(*this, "maincpu"),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_ay1(*this, "ay1")
{ }
void dday(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
private:
required_shared_ptr<uint8_t> m_textvideoram;
required_shared_ptr<uint8_t> m_fgvideoram;
required_shared_ptr<uint8_t> m_bgvideoram;
required_shared_ptr<uint8_t> m_colorram;
required_region_ptr<uint8_t> m_sl_map;
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_device<ay8912_device> m_ay1;
tilemap_t *m_fg_tilemap = nullptr;
tilemap_t *m_bg_tilemap = nullptr;
tilemap_t *m_text_tilemap = nullptr;
tilemap_t *m_sl_tilemap = nullptr;
bitmap_ind16 m_main_bitmap = 0;
uint8_t m_control = 0;
uint8_t m_sl_image = 0;
uint8_t m_sl_enable = 0;
int8_t m_timer_value = 0;
emu_timer *m_countdown_timer = nullptr;
uint8_t countdown_timer_r();
void bgvideoram_w(offs_t offset, uint8_t data);
void fgvideoram_w(offs_t offset, uint8_t data);
void textvideoram_w(offs_t offset, uint8_t data);
void colorram_w(offs_t offset, uint8_t data);
uint8_t colorram_r(offs_t offset);
void sl_control_w(uint8_t data);
void control_w(uint8_t data);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
TILE_GET_INFO_MEMBER(get_text_tile_info);
TILE_GET_INFO_MEMBER(get_sl_tile_info);
void palette_init(palette_device &palette) const;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_CALLBACK_MEMBER(countdown_timer_callback);
void start_countdown_timer();
void program_map(address_map &map);
};
/* Note: There seems to be no way to reset this timer via hardware.
The game uses a difference method to reset it to 99.
Thanks Zwaxy for the timer info. */
uint8_t dday_state::countdown_timer_r()
{
return ((m_timer_value / 10) << 4) | (m_timer_value % 10);
}
TIMER_CALLBACK_MEMBER(dday_state::countdown_timer_callback)
{
m_timer_value--;
if (m_timer_value < 0)
m_timer_value = 99;
}
void dday_state::start_countdown_timer()
{
m_timer_value = 0;
m_countdown_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
}
/***************************************************************************
Convert the color PROMs into a more useable format.
***************************************************************************/
void dday_state::palette_init(palette_device &palette) const
{
uint8_t const *const color_prom = memregion("proms")->base();
palette.set_shadow_factor(1.0 / 8);
// create a lookup table for the palette
for (int i = 0; i < 0x100; i++)
{
int const r = pal4bit(color_prom[i + 0x000]);
int const g = pal4bit(color_prom[i + 0x100]);
int const b = pal4bit(color_prom[i + 0x200]);
palette.set_indirect_color(i, rgb_t(r, g, b));
}
for (int i = 0; i < 0x100; i++)
palette.set_pen_indirect(i, i);
// HACK!!! This table is handgenerated, but it matches the screenshot. I have no clue how it really works
palette.set_pen_indirect(0*8+0+0, 0x00);
palette.set_pen_indirect(0*8+0+1, 0x01);
palette.set_pen_indirect(0*8+0+2, 0x15);
palette.set_pen_indirect(0*8+0+3, 0x02);
palette.set_pen_indirect(0*8+4+0, 0x00);
palette.set_pen_indirect(0*8+4+1, 0x01);
palette.set_pen_indirect(0*8+4+2, 0x15);
palette.set_pen_indirect(0*8+4+3, 0x02);
palette.set_pen_indirect(1*8+0+0, 0x04);
palette.set_pen_indirect(1*8+0+1, 0x05);
palette.set_pen_indirect(1*8+0+2, 0x03);
palette.set_pen_indirect(1*8+0+3, 0x07);
palette.set_pen_indirect(1*8+4+0, 0x04);
palette.set_pen_indirect(1*8+4+1, 0x05);
palette.set_pen_indirect(1*8+4+2, 0x03);
palette.set_pen_indirect(1*8+4+3, 0x07);
palette.set_pen_indirect(2*8+0+0, 0x08);
palette.set_pen_indirect(2*8+0+1, 0x15);
palette.set_pen_indirect(2*8+0+2, 0x0a);
palette.set_pen_indirect(2*8+0+3, 0x03);
palette.set_pen_indirect(2*8+4+0, 0x08);
palette.set_pen_indirect(2*8+4+1, 0x15);
palette.set_pen_indirect(2*8+4+2, 0x0a);
palette.set_pen_indirect(2*8+4+3, 0x03);
palette.set_pen_indirect(3*8+0+0, 0x08);
palette.set_pen_indirect(3*8+0+1, 0x15);
palette.set_pen_indirect(3*8+0+2, 0x0a);
palette.set_pen_indirect(3*8+0+3, 0x03);
palette.set_pen_indirect(3*8+4+0, 0x08);
palette.set_pen_indirect(3*8+4+1, 0x15);
palette.set_pen_indirect(3*8+4+2, 0x0a);
palette.set_pen_indirect(3*8+4+3, 0x03);
palette.set_pen_indirect(4*8+0+0, 0x10);
palette.set_pen_indirect(4*8+0+1, 0x11);
palette.set_pen_indirect(4*8+0+2, 0x12);
palette.set_pen_indirect(4*8+0+3, 0x07);
palette.set_pen_indirect(4*8+4+0, 0x10);
palette.set_pen_indirect(4*8+4+1, 0x11);
palette.set_pen_indirect(4*8+4+2, 0x12);
palette.set_pen_indirect(4*8+4+3, 0x07);
palette.set_pen_indirect(5*8+0+0, 0x1d);
palette.set_pen_indirect(5*8+0+1, 0x15);
palette.set_pen_indirect(5*8+0+2, 0x16);
palette.set_pen_indirect(5*8+0+3, 0x1b);
palette.set_pen_indirect(5*8+4+0, 0x1d);
palette.set_pen_indirect(5*8+4+1, 0x15);
palette.set_pen_indirect(5*8+4+2, 0x16);
palette.set_pen_indirect(5*8+4+3, 0x1b);
palette.set_pen_indirect(6*8+0+0, 0x1d);
palette.set_pen_indirect(6*8+0+1, 0x15);
palette.set_pen_indirect(6*8+0+2, 0x1a);
palette.set_pen_indirect(6*8+0+3, 0x1b);
palette.set_pen_indirect(6*8+4+0, 0x1d);
palette.set_pen_indirect(6*8+4+1, 0x15);
palette.set_pen_indirect(6*8+4+2, 0x1a);
palette.set_pen_indirect(6*8+4+3, 0x1b);
palette.set_pen_indirect(7*8+0+0, 0x1d);
palette.set_pen_indirect(7*8+0+1, 0x02);
palette.set_pen_indirect(7*8+0+2, 0x04);
palette.set_pen_indirect(7*8+0+3, 0x1b);
palette.set_pen_indirect(7*8+4+0, 0x1d);
palette.set_pen_indirect(7*8+4+1, 0x02);
palette.set_pen_indirect(7*8+4+2, 0x04);
palette.set_pen_indirect(7*8+4+3, 0x1b);
}
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
TILE_GET_INFO_MEMBER(dday_state::get_bg_tile_info)
{
int const code = m_bgvideoram[tile_index];
tileinfo.set(0, code, code >> 5, 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_fg_tile_info)
{
int const flipx = m_colorram[tile_index & 0x03e0] & 0x01;
int const code = m_fgvideoram[flipx ? tile_index ^ 0x1f : tile_index];
tileinfo.set(2, code, code >> 5, flipx ? TILE_FLIPX : 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_text_tile_info)
{
int const code = m_textvideoram[tile_index];
tileinfo.set(1, code, code >> 5, 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_sl_tile_info)
{
uint8_t *sl_map = &m_sl_map[(m_sl_image & 0x07) * 0x0200];
int const flipx = (tile_index >> 4) & 0x01;
int const sl_flipx = (m_sl_image >> 3) & 0x01;
// bit 4 is really a flip indicator. Need to shift bits 5-9 to the right by 1
tile_index = ((tile_index & 0x03e0) >> 1) | (tile_index & 0x0f);
int code = sl_map[flipx ? tile_index ^ 0x0f : tile_index];
if ((sl_flipx != flipx) && (code & 0x80))
// no mirroring, draw dark spot
code = 1;
tileinfo.set(3, code & 0x3f, 0, flipx ? TILE_FLIPX : 0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void dday_state::video_start()
{
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_text_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_text_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_sl_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_sl_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_screen->register_screen_bitmap(m_main_bitmap);
m_bg_tilemap->set_transmask(0, 0x00f0, 0xff0f); // pens 0-3 have priority over the foreground layer
m_fg_tilemap->set_transparent_pen(0);
m_text_tilemap->set_transparent_pen(0);
m_countdown_timer = timer_alloc(FUNC(dday_state::countdown_timer_callback), this);
start_countdown_timer();
}
void dday_state::bgvideoram_w(offs_t offset, uint8_t data)
{
m_bgvideoram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
void dday_state::fgvideoram_w(offs_t offset, uint8_t data)
{
m_fgvideoram[offset] = data;
m_fg_tilemap->mark_tile_dirty(offset);
m_fg_tilemap->mark_tile_dirty(offset ^ 0x1f); // for flipx case
}
void dday_state::textvideoram_w(offs_t offset, uint8_t data)
{
m_textvideoram[offset] = data;
m_text_tilemap->mark_tile_dirty(offset);
}
void dday_state::colorram_w(offs_t offset, uint8_t data)
{
offset &= 0x03e0;
m_colorram[offset & 0x3e0] = data;
for (int i = 0; i < 0x20; i++)
m_fg_tilemap->mark_tile_dirty(offset + i);
}
uint8_t dday_state::colorram_r(offs_t offset)
{
return m_colorram[offset & 0x03e0];
}
void dday_state::sl_control_w(uint8_t data)
{
if (m_sl_image != data)
{
m_sl_image = data;
m_sl_tilemap->mark_all_dirty();
}
}
void dday_state::control_w(uint8_t data)
{
// if (data & 0xac) logerror("Control = %02X\n", data & 0xac);
// bit 0 is coin counter 1
machine().bookkeeping().coin_counter_w(0, data & 0x01);
// bit 1 is coin counter 2
machine().bookkeeping().coin_counter_w(1, data & 0x02);
// bit 4 is sound enable
if (!(data & 0x10) && (m_control & 0x10))
m_ay1->reset();
machine().sound().system_mute(!BIT(data, 4));
// bit 6 is search light enable
m_sl_enable = data & 0x40;
m_control = data;
}
/***************************************************************************
Display refresh
***************************************************************************/
uint32_t dday_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
m_bg_tilemap->draw(screen, m_main_bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
m_fg_tilemap->draw(screen, m_main_bitmap, cliprect, 0, 0);
m_bg_tilemap->draw(screen, m_main_bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
m_text_tilemap->draw(screen, m_main_bitmap, cliprect, 0, 0);
if (m_sl_enable)
{
// apply shadow
bitmap_ind16 &sl_bitmap = m_sl_tilemap->pixmap();
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
uint16_t src_pixel = m_main_bitmap.pix(y, x);
if (sl_bitmap.pix(y, x) == 0xff)
src_pixel += m_palette->entries();
bitmap.pix(y, x) = src_pixel;
}
}
else
copybitmap(bitmap, m_main_bitmap, 0, 0, 0, 0, cliprect);
return 0;
}
void dday_state::program_map(address_map &map)
{
map(0x0000, 0x3fff).rom();
map(0x4000, 0x4000).w(FUNC(dday_state::dday_sl_control_w));
map(0x5000, 0x53ff).ram().w(FUNC(dday_state::dday_textvideoram_w)).share("textvideoram");
map(0x5400, 0x57ff).ram().w(FUNC(dday_state::dday_fgvideoram_w)).share("fgvideoram");
map(0x5800, 0x5bff).ram().w(FUNC(dday_state::dday_bgvideoram_w)).share("bgvideoram");
map(0x5c00, 0x5fff).rw(FUNC(dday_state::dday_colorram_r), FUNC(dday_state::dday_colorram_w)).share("colorram");
map(0x4000, 0x4000).w(FUNC(dday_state::sl_control_w));
map(0x5000, 0x53ff).ram().w(FUNC(dday_state::textvideoram_w)).share(m_textvideoram);
map(0x5400, 0x57ff).ram().w(FUNC(dday_state::fgvideoram_w)).share(m_fgvideoram);
map(0x5800, 0x5bff).ram().w(FUNC(dday_state::bgvideoram_w)).share(m_bgvideoram);
map(0x5c00, 0x5fff).rw(FUNC(dday_state::colorram_r), FUNC(dday_state::colorram_w)).share(m_colorram);
map(0x6000, 0x63ff).ram();
map(0x6400, 0x6401).mirror(0x000e).w(m_ay1, FUNC(ay8912_device::address_data_w));
map(0x6800, 0x6801).w("ay2", FUNC(ay8912_device::address_data_w));
map(0x6c00, 0x6c00).portr("BUTTONS");
map(0x7000, 0x7000).portr("DSW0");
map(0x7400, 0x7400).portr("DSW1");
map(0x7800, 0x7800).rw(FUNC(dday_state::dday_countdown_timer_r), FUNC(dday_state::dday_control_w));
map(0x7800, 0x7800).rw(FUNC(dday_state::countdown_timer_r), FUNC(dday_state::control_w));
map(0x7c00, 0x7c00).portr("PADDLE");
}
@ -82,12 +455,12 @@ static INPUT_PORTS_START( dday )
PORT_START("BUTTONS")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) /* fire button */
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) // fire button
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START2 )
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* doesn't seem to be */
/* accessed */
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // doesn't seem to be accessed
PORT_START("DSW0")
PORT_DIPNAME( 0x03, 0x01, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW3:1,2")
PORT_DIPSETTING( 0x00, "2" ) PORT_CONDITION("DSW0", 0x80, EQUALS, 0x80)
@ -120,7 +493,7 @@ static INPUT_PORTS_START( dday )
PORT_START("DSW1")
PORT_DIPNAME( 0x0f, 0x0f, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3,4")
PORT_DIPSETTING( 0x0e, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x0c, DEF_STR( 2C_2C ) ) /* Not shown in manual */
PORT_DIPSETTING( 0x0c, DEF_STR( 2C_2C ) ) // Not shown in manual
PORT_DIPSETTING( 0x0f, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x0a, DEF_STR( 2C_3C ) )
PORT_DIPSETTING( 0x08, DEF_STR( 2C_4C ) )
@ -162,7 +535,7 @@ static INPUT_PORTS_START( ddayc )
PORT_MODIFY("BUTTONS")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) /* Distance Button */
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) // Distance Button
PORT_MODIFY("DSW0")
PORT_DIPNAME( 0x0c, 0x00, "Extended Play At" ) PORT_DIPLOCATION("SW3:3,4")
@ -198,42 +571,42 @@ INPUT_PORTS_END
static const gfx_layout layout_1bpp =
{
8,8, /* 8*8 characters */
RGN_FRAC(1,2), /* 256 characters */
1, /* 1 bit per pixel */
8,8, // 8*8 characters
RGN_FRAC(1,2), // 256 characters
1, // 1 bit per pixel
{ RGN_FRAC(0,1) },
{ 7, 6, 5, 4, 3, 2, 1, 0 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
8*8 // every char takes 8 consecutive bytes
};
static const gfx_layout layout_2bpp =
{
8,8, /* 8*8 characters */
RGN_FRAC(1,2), /* 256 characters */
2, /* 2 bits per pixel */
{ RGN_FRAC(0,2), RGN_FRAC(1,2) }, /* the bitplanes are separated */
8,8, // 8*8 characters
RGN_FRAC(1,2), // 256 characters
2, // 2 bits per pixel
{ RGN_FRAC(0,2), RGN_FRAC(1,2) }, // the bitplanes are separated
{ 7, 6, 5, 4, 3, 2, 1, 0 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
8*8 // every char takes 8 consecutive bytes
};
static const gfx_layout layout_3bpp =
{
8,8, /* 8*8 characters */
RGN_FRAC(1,3), /* 256 characters */
3, /* 3 bits per pixel */
{ RGN_FRAC(0,3), RGN_FRAC(1,3), RGN_FRAC(2,3) }, /* the bitplanes are separated */
8,8, // 8*8 characters
RGN_FRAC(1,3), // 256 characters
3, // 3 bits per pixel
{ RGN_FRAC(0,3), RGN_FRAC(1,3), RGN_FRAC(2,3) }, // the bitplanes are separated
{ 7, 6, 5, 4, 3, 2, 1, 0 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
8*8 // every char takes 8 consecutive bytes
};
static GFXDECODE_START( gfx_dday )
GFXDECODE_ENTRY( "gfx1", 0, layout_3bpp, 0, 256/8 ) /* background */
GFXDECODE_ENTRY( "gfx2", 0, layout_2bpp, 8*4, 8 ) /* foreground */
GFXDECODE_ENTRY( "gfx3", 0, layout_2bpp, 8*4+8*4, 8 ) /* text */
GFXDECODE_ENTRY( "gfx4", 0, layout_1bpp, 254, 1 ) /* searchlight */
GFXDECODE_ENTRY( "bgtiles", 0, layout_3bpp, 0, 256/8 )
GFXDECODE_ENTRY( "fgtiles", 0, layout_2bpp, 8*4, 8 )
GFXDECODE_ENTRY( "chars", 0, layout_2bpp, 8*4+8*4, 8 )
GFXDECODE_ENTRY( "searchlight", 0, layout_1bpp, 254, 1 )
GFXDECODE_END
@ -256,29 +629,29 @@ void dday_state::machine_reset()
void dday_state::dday(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, 2000000); /* 2 MHz ? */
m_maincpu->set_addrmap(AS_PROGRAM, &dday_state::dday_map);
// basic machine hardware
Z80(config, m_maincpu, 2'000'000); // 2 MHz ?
m_maincpu->set_addrmap(AS_PROGRAM, &dday_state::program_map);
/* video hardware */
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
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(32*8, 32*8);
m_screen->set_visarea(0*8, 32*8-1, 0*8, 28*8-1);
m_screen->set_screen_update(FUNC(dday_state::screen_update_dday));
m_screen->set_screen_update(FUNC(dday_state::screen_update));
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_dday);
PALETTE(config, m_palette, FUNC(dday_state::dday_palette), 256).enable_shadows();
PALETTE(config, m_palette, FUNC(dday_state::palette_init), 256).enable_shadows();
m_palette->set_indirect_entries(256); // HACK!!!
/* sound hardware */
// sound hardware
SPEAKER(config, "mono").front_center();
AY8912(config, m_ay1, 1000000).add_route(ALL_OUTPUTS, "mono", 0.25);
AY8912(config, "ay2", 1000000).add_route(ALL_OUTPUTS, "mono", 0.25);
AY8912(config, m_ay1, 1'000'000).add_route(ALL_OUTPUTS, "mono", 0.25);
AY8912(config, "ay2", 1'000'000).add_route(ALL_OUTPUTS, "mono", 0.25);
}
@ -296,29 +669,29 @@ ROM_START( dday )
ROM_LOAD( "e6_65co.bin", 0x2000, 0x1000, CRC(fe414a83) SHA1(1ca1d30b71b62af5230dfe862a67c4cff5a71f41) )
ROM_LOAD( "e5_66co.bin", 0x3000, 0x1000, CRC(fc9f7774) SHA1(1071d05e2f0ee8869eeeb46ad219303b417f4c90) )
ROM_REGION( 0x1800, "gfx1", 0 )
ROM_REGION( 0x1800, "bgtiles", 0 )
ROM_LOAD( "k4_73.bin", 0x0000, 0x0800, CRC(fa6237e4) SHA1(0dfe2a0079324a78b462203fe93f7fb186a42122) )
ROM_LOAD( "k2_71.bin", 0x0800, 0x0800, CRC(f85461de) SHA1(e2ed34e993cd657681124df5531e35afd7d8c34b) )
ROM_LOAD( "k3_72.bin", 0x1000, 0x0800, CRC(fdfe88b6) SHA1(cdc37d90500f4ce813b6efee31139e6776aa2bff) )
ROM_REGION( 0x1000, "gfx2", 0 )
ROM_REGION( 0x1000, "fgtiles", 0 )
ROM_LOAD( "j8_70co.bin", 0x0000, 0x0800, CRC(0c60e94c) SHA1(136df37b858a7fd399acc89e59917a068165d749) )
ROM_LOAD( "j9_69co.bin", 0x0800, 0x0800, CRC(ba341c10) SHA1(c2c7350f87d5e47ac47cb19020681f0e7340e427) )
ROM_REGION( 0x1000, "gfx3", 0 )
ROM_REGION( 0x1000, "chars", 0 )
ROM_LOAD( "k6_74o.bin", 0x0000, 0x0800, CRC(66719aea) SHA1(dd29f8d079868af3c7fd16dc8c383f1eba4543d2) )
ROM_LOAD( "k7_75o.bin", 0x0800, 0x0800, CRC(5f8772e2) SHA1(16194a02bc7d5248dea7a80bf6d6d263ec8a7fd6) )
ROM_REGION( 0x0800, "gfx4", 0 )
ROM_REGION( 0x0800, "searchlight", 0 )
ROM_LOAD( "d4_68.bin", 0x0000, 0x0800, CRC(f3649264) SHA1(5486a33fa1f7803e68d141992d6105206da1beba) )
ROM_REGION( 0x1000, "user1", 0 )
ROM_LOAD( "d2_67.bin", 0x0000, 0x1000, CRC(2b693e42) SHA1(e52b987cf929ddfc7916b05456b1114076956d12) ) /* search light map */
ROM_REGION( 0x1000, "sl_map", 0 )
ROM_LOAD( "d2_67.bin", 0x0000, 0x1000, CRC(2b693e42) SHA1(e52b987cf929ddfc7916b05456b1114076956d12) )
ROM_REGION( 0x0300, "proms", 0 )
ROM_LOAD( "dday.m11", 0x0000, 0x0100, CRC(aef6bbfc) SHA1(9e07729a4389221bc120af91d8275e1d05f3be7a) ) /* red component */
ROM_LOAD( "dday.m8", 0x0100, 0x0100, CRC(ad3314b9) SHA1(d103f4f6103987ea85f0791ffc66a1cf9c711031) ) /* green component */
ROM_LOAD( "dday.m3", 0x0200, 0x0100, CRC(e877ab82) SHA1(03e3905aee37f6743e7a4a87338f9504c832a55b) ) /* blue component */
ROM_LOAD( "dday.m11", 0x0000, 0x0100, CRC(aef6bbfc) SHA1(9e07729a4389221bc120af91d8275e1d05f3be7a) ) // red component
ROM_LOAD( "dday.m8", 0x0100, 0x0100, CRC(ad3314b9) SHA1(d103f4f6103987ea85f0791ffc66a1cf9c711031) ) // green component
ROM_LOAD( "dday.m3", 0x0200, 0x0100, CRC(e877ab82) SHA1(03e3905aee37f6743e7a4a87338f9504c832a55b) ) // blue component
ROM_END
ROM_START( ddayc )
@ -328,31 +701,33 @@ ROM_START( ddayc )
ROM_LOAD( "e6_65-c.bin", 0x2000, 0x1000, CRC(4c210686) SHA1(9d3110c4d1347f8a067c49b363a32d0f6a2c34c7) )
ROM_LOAD( "e5_66-c.bin", 0x3000, 0x1000, CRC(e7e832f9) SHA1(3cbd2f9197e934ba3eae329511886a30c09a1ac7) )
ROM_REGION( 0x1800, "gfx1", 0 )
ROM_REGION( 0x1800, "bgtiles", 0 )
ROM_LOAD( "k4_73.bin", 0x0000, 0x0800, CRC(fa6237e4) SHA1(0dfe2a0079324a78b462203fe93f7fb186a42122) )
ROM_LOAD( "k2_71.bin", 0x0800, 0x0800, CRC(f85461de) SHA1(e2ed34e993cd657681124df5531e35afd7d8c34b) )
ROM_LOAD( "k3_72.bin", 0x1000, 0x0800, CRC(fdfe88b6) SHA1(cdc37d90500f4ce813b6efee31139e6776aa2bff) )
ROM_REGION( 0x1000, "gfx2", 0 )
ROM_REGION( 0x1000, "fgtiles", 0 )
ROM_LOAD( "j8_70-c.bin", 0x0000, 0x0800, CRC(a0c6b86b) SHA1(8b30370f2d5d7e75b8ec2a68f4e408fcb8ed2c8f) )
ROM_LOAD( "j9_69-c.bin", 0x0800, 0x0800, CRC(d352a3d6) SHA1(4f1ba0b555f6b3dd539511bab8c55db45f719afc) )
ROM_REGION( 0x1000, "gfx3", 0 )
ROM_REGION( 0x1000, "chars", 0 )
ROM_LOAD( "k6_74.bin", 0x0000, 0x0800, CRC(d21a3e22) SHA1(9260353245f2ba2aca09fafd377c662ff508e5c0) )
ROM_LOAD( "k7_75.bin", 0x0800, 0x0800, CRC(a5e5058c) SHA1(312dd55902c7e16eeee0dfc42c17fe1440b26e40) )
ROM_REGION( 0x0800, "gfx4", 0 )
ROM_REGION( 0x0800, "searchlight", 0 )
ROM_LOAD( "d4_68.bin", 0x0000, 0x0800, CRC(f3649264) SHA1(5486a33fa1f7803e68d141992d6105206da1beba) )
ROM_REGION( 0x1000, "user1", 0 )
ROM_LOAD( "d2_67.bin", 0x0000, 0x1000, CRC(2b693e42) SHA1(e52b987cf929ddfc7916b05456b1114076956d12) ) /* search light map */
ROM_REGION( 0x1000, "sl_map", 0 )
ROM_LOAD( "d2_67.bin", 0x0000, 0x1000, CRC(2b693e42) SHA1(e52b987cf929ddfc7916b05456b1114076956d12) )
ROM_REGION( 0x0300, "proms", 0 )
ROM_LOAD( "dday.m11", 0x0000, 0x0100, CRC(aef6bbfc) SHA1(9e07729a4389221bc120af91d8275e1d05f3be7a) ) /* red component */
ROM_LOAD( "dday.m8", 0x0100, 0x0100, CRC(ad3314b9) SHA1(d103f4f6103987ea85f0791ffc66a1cf9c711031) ) /* green component */
ROM_LOAD( "dday.m3", 0x0200, 0x0100, CRC(e877ab82) SHA1(03e3905aee37f6743e7a4a87338f9504c832a55b) ) /* blue component */
ROM_LOAD( "dday.m11", 0x0000, 0x0100, CRC(aef6bbfc) SHA1(9e07729a4389221bc120af91d8275e1d05f3be7a) ) // red component
ROM_LOAD( "dday.m8", 0x0100, 0x0100, CRC(ad3314b9) SHA1(d103f4f6103987ea85f0791ffc66a1cf9c711031) ) // green component
ROM_LOAD( "dday.m3", 0x0200, 0x0100, CRC(e877ab82) SHA1(03e3905aee37f6743e7a4a87338f9504c832a55b) ) // blue component
ROM_END
} // anonymous namespace
GAME( 1982, dday, 0, dday, dday, dday_state, empty_init, ROT0, "Olympia", "D-Day", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE )
GAME( 1982, ddayc, dday, dday, ddayc, dday_state, empty_init, ROT0, "Olympia (Centuri license)", "D-Day (Centuri)", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE )

View File

@ -1,87 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Zsolt Vasvari
/*************************************************************************
D-Day
*************************************************************************/
#ifndef MAME_OLYMPIA_DDAY_H
#define MAME_OLYMPIA_DDAY_H
#pragma once
#include "emupal.h"
#include "screen.h"
#include "sound/ay8910.h"
#include "tilemap.h"
class dday_state : public driver_device
{
public:
dday_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_textvideoram(*this, "textvideoram"),
m_fgvideoram(*this, "fgvideoram"),
m_bgvideoram(*this, "bgvideoram"),
m_colorram(*this, "colorram"),
m_maincpu(*this, "maincpu"),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_ay1(*this, "ay1")
{ }
void dday(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_textvideoram;
required_shared_ptr<uint8_t> m_fgvideoram;
required_shared_ptr<uint8_t> m_bgvideoram;
required_shared_ptr<uint8_t> m_colorram;
/* video-related */
tilemap_t *m_fg_tilemap = nullptr;
tilemap_t *m_bg_tilemap = nullptr;
tilemap_t *m_text_tilemap = nullptr;
tilemap_t *m_sl_tilemap = nullptr;
bitmap_ind16 m_main_bitmap = 0;
int m_control = 0;
int m_sl_image = 0;
int m_sl_enable = 0;
int m_timer_value = 0;
emu_timer *m_countdown_timer = nullptr;
/* 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_device<ay8912_device> m_ay1;
uint8_t dday_countdown_timer_r();
void dday_bgvideoram_w(offs_t offset, uint8_t data);
void dday_fgvideoram_w(offs_t offset, uint8_t data);
void dday_textvideoram_w(offs_t offset, uint8_t data);
void dday_colorram_w(offs_t offset, uint8_t data);
uint8_t dday_colorram_r(offs_t offset);
void dday_sl_control_w(uint8_t data);
void dday_control_w(uint8_t data);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
TILE_GET_INFO_MEMBER(get_text_tile_info);
TILE_GET_INFO_MEMBER(get_sl_tile_info);
void dday_palette(palette_device &palette) const;
uint32_t screen_update_dday(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_CALLBACK_MEMBER(countdown_timer_callback);
void start_countdown_timer();
void dday_map(address_map &map);
};
#endif // MAME_OLYMPIA_DDAY_H

View File

@ -1,322 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Zsolt Vasvari
/***************************************************************************
video.c
Functions to emulate the video hardware of the machine.
Convention: "sl" stands for "searchlight"
***************************************************************************/
#include "emu.h"
#include "sound/ay8910.h"
#include "dday.h"
/* Note: There seems to be no way to reset this timer via hardware.
The game uses a difference method to reset it to 99.
Thanks Zwaxy for the timer info. */
uint8_t dday_state::dday_countdown_timer_r()
{
return ((m_timer_value / 10) << 4) | (m_timer_value % 10);
}
TIMER_CALLBACK_MEMBER(dday_state::countdown_timer_callback)
{
m_timer_value--;
if (m_timer_value < 0)
m_timer_value = 99;
}
void dday_state::start_countdown_timer()
{
m_timer_value = 0;
m_countdown_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
}
/***************************************************************************
Convert the color PROMs into a more useable format.
***************************************************************************/
void dday_state::dday_palette(palette_device &palette) const
{
uint8_t const *const color_prom = memregion("proms")->base();
palette.set_shadow_factor(1.0 / 8);
// create a lookup table for the palette
for (int i = 0; i < 0x100; i++)
{
int const r = pal4bit(color_prom[i + 0x000]);
int const g = pal4bit(color_prom[i + 0x100]);
int const b = pal4bit(color_prom[i + 0x200]);
palette.set_indirect_color(i, rgb_t(r, g, b));
}
for (int i = 0; i < 0x100; i++)
palette.set_pen_indirect(i, i);
// HACK!!! This table is handgenerated, but it matches the screenshot. I have no clue how it really works
palette.set_pen_indirect(0*8+0+0, 0x00);
palette.set_pen_indirect(0*8+0+1, 0x01);
palette.set_pen_indirect(0*8+0+2, 0x15);
palette.set_pen_indirect(0*8+0+3, 0x02);
palette.set_pen_indirect(0*8+4+0, 0x00);
palette.set_pen_indirect(0*8+4+1, 0x01);
palette.set_pen_indirect(0*8+4+2, 0x15);
palette.set_pen_indirect(0*8+4+3, 0x02);
palette.set_pen_indirect(1*8+0+0, 0x04);
palette.set_pen_indirect(1*8+0+1, 0x05);
palette.set_pen_indirect(1*8+0+2, 0x03);
palette.set_pen_indirect(1*8+0+3, 0x07);
palette.set_pen_indirect(1*8+4+0, 0x04);
palette.set_pen_indirect(1*8+4+1, 0x05);
palette.set_pen_indirect(1*8+4+2, 0x03);
palette.set_pen_indirect(1*8+4+3, 0x07);
palette.set_pen_indirect(2*8+0+0, 0x08);
palette.set_pen_indirect(2*8+0+1, 0x15);
palette.set_pen_indirect(2*8+0+2, 0x0a);
palette.set_pen_indirect(2*8+0+3, 0x03);
palette.set_pen_indirect(2*8+4+0, 0x08);
palette.set_pen_indirect(2*8+4+1, 0x15);
palette.set_pen_indirect(2*8+4+2, 0x0a);
palette.set_pen_indirect(2*8+4+3, 0x03);
palette.set_pen_indirect(3*8+0+0, 0x08);
palette.set_pen_indirect(3*8+0+1, 0x15);
palette.set_pen_indirect(3*8+0+2, 0x0a);
palette.set_pen_indirect(3*8+0+3, 0x03);
palette.set_pen_indirect(3*8+4+0, 0x08);
palette.set_pen_indirect(3*8+4+1, 0x15);
palette.set_pen_indirect(3*8+4+2, 0x0a);
palette.set_pen_indirect(3*8+4+3, 0x03);
palette.set_pen_indirect(4*8+0+0, 0x10);
palette.set_pen_indirect(4*8+0+1, 0x11);
palette.set_pen_indirect(4*8+0+2, 0x12);
palette.set_pen_indirect(4*8+0+3, 0x07);
palette.set_pen_indirect(4*8+4+0, 0x10);
palette.set_pen_indirect(4*8+4+1, 0x11);
palette.set_pen_indirect(4*8+4+2, 0x12);
palette.set_pen_indirect(4*8+4+3, 0x07);
palette.set_pen_indirect(5*8+0+0, 0x1d);
palette.set_pen_indirect(5*8+0+1, 0x15);
palette.set_pen_indirect(5*8+0+2, 0x16);
palette.set_pen_indirect(5*8+0+3, 0x1b);
palette.set_pen_indirect(5*8+4+0, 0x1d);
palette.set_pen_indirect(5*8+4+1, 0x15);
palette.set_pen_indirect(5*8+4+2, 0x16);
palette.set_pen_indirect(5*8+4+3, 0x1b);
palette.set_pen_indirect(6*8+0+0, 0x1d);
palette.set_pen_indirect(6*8+0+1, 0x15);
palette.set_pen_indirect(6*8+0+2, 0x1a);
palette.set_pen_indirect(6*8+0+3, 0x1b);
palette.set_pen_indirect(6*8+4+0, 0x1d);
palette.set_pen_indirect(6*8+4+1, 0x15);
palette.set_pen_indirect(6*8+4+2, 0x1a);
palette.set_pen_indirect(6*8+4+3, 0x1b);
palette.set_pen_indirect(7*8+0+0, 0x1d);
palette.set_pen_indirect(7*8+0+1, 0x02);
palette.set_pen_indirect(7*8+0+2, 0x04);
palette.set_pen_indirect(7*8+0+3, 0x1b);
palette.set_pen_indirect(7*8+4+0, 0x1d);
palette.set_pen_indirect(7*8+4+1, 0x02);
palette.set_pen_indirect(7*8+4+2, 0x04);
palette.set_pen_indirect(7*8+4+3, 0x1b);
}
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
TILE_GET_INFO_MEMBER(dday_state::get_bg_tile_info)
{
int code;
code = m_bgvideoram[tile_index];
tileinfo.set(0, code, code >> 5, 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_fg_tile_info)
{
int code, flipx;
flipx = m_colorram[tile_index & 0x03e0] & 0x01;
code = m_fgvideoram[flipx ? tile_index ^ 0x1f : tile_index];
tileinfo.set(2, code, code >> 5, flipx ? TILE_FLIPX : 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_text_tile_info)
{
int code;
code = m_textvideoram[tile_index];
tileinfo.set(1, code, code >> 5, 0);
}
TILE_GET_INFO_MEMBER(dday_state::get_sl_tile_info)
{
int code, sl_flipx, flipx;
uint8_t* sl_map;
sl_map = &memregion("user1")->base()[(m_sl_image & 0x07) * 0x0200];
flipx = (tile_index >> 4) & 0x01;
sl_flipx = (m_sl_image >> 3) & 0x01;
/* bit 4 is really a flip indicator. Need to shift bits 5-9 to the right by 1 */
tile_index = ((tile_index & 0x03e0) >> 1) | (tile_index & 0x0f);
code = sl_map[flipx ? tile_index ^ 0x0f : tile_index];
if ((sl_flipx != flipx) && (code & 0x80))
/* no mirroring, draw dark spot */
code = 1;
tileinfo.set(3, code & 0x3f, 0, flipx ? TILE_FLIPX : 0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void dday_state::video_start()
{
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_text_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_text_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_sl_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dday_state::get_sl_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_screen->register_screen_bitmap(m_main_bitmap);
m_bg_tilemap->set_transmask(0, 0x00f0, 0xff0f); /* pens 0-3 have priority over the foreground layer */
m_fg_tilemap->set_transparent_pen(0);
m_text_tilemap->set_transparent_pen(0);
m_countdown_timer = timer_alloc(FUNC(dday_state::countdown_timer_callback), this);
start_countdown_timer();
}
void dday_state::dday_bgvideoram_w(offs_t offset, uint8_t data)
{
m_bgvideoram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
void dday_state::dday_fgvideoram_w(offs_t offset, uint8_t data)
{
m_fgvideoram[offset] = data;
m_fg_tilemap->mark_tile_dirty(offset);
m_fg_tilemap->mark_tile_dirty(offset ^ 0x1f); /* for flipx case */
}
void dday_state::dday_textvideoram_w(offs_t offset, uint8_t data)
{
m_textvideoram[offset] = data;
m_text_tilemap->mark_tile_dirty(offset);
}
void dday_state::dday_colorram_w(offs_t offset, uint8_t data)
{
offset &= 0x03e0;
m_colorram[offset & 0x3e0] = data;
for (int i = 0; i < 0x20; i++)
m_fg_tilemap->mark_tile_dirty(offset + i);
}
uint8_t dday_state::dday_colorram_r(offs_t offset)
{
return m_colorram[offset & 0x03e0];
}
void dday_state::dday_sl_control_w(uint8_t data)
{
if (m_sl_image != data)
{
m_sl_image = data;
m_sl_tilemap->mark_all_dirty();
}
}
void dday_state::dday_control_w(uint8_t data)
{
//if (data & 0xac) logerror("Control = %02X\n", data & 0xac);
/* bit 0 is coin counter 1 */
machine().bookkeeping().coin_counter_w(0, data & 0x01);
/* bit 1 is coin counter 2 */
machine().bookkeeping().coin_counter_w(1, data & 0x02);
/* bit 4 is sound enable */
if (!(data & 0x10) && (m_control & 0x10))
m_ay1->reset();
machine().sound().system_mute(!BIT(data, 4));
/* bit 6 is search light enable */
m_sl_enable = data & 0x40;
m_control = data;
}
/***************************************************************************
Display refresh
***************************************************************************/
uint32_t dday_state::screen_update_dday(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
m_bg_tilemap->draw(screen, m_main_bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0);
m_fg_tilemap->draw(screen, m_main_bitmap, cliprect, 0, 0);
m_bg_tilemap->draw(screen, m_main_bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0);
m_text_tilemap->draw(screen, m_main_bitmap, cliprect, 0, 0);
if (m_sl_enable)
{
/* apply shadow */
bitmap_ind16 &sl_bitmap = m_sl_tilemap->pixmap();
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
uint16_t src_pixel = m_main_bitmap.pix(y, x);
if (sl_bitmap.pix(y, x) == 0xff)
src_pixel += m_palette->entries();
bitmap.pix(y, x) = src_pixel;
}
}
else
copybitmap(bitmap, m_main_bitmap, 0, 0, 0, 0, cliprect);
return 0;
}

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Steve Ellenoff, Pierpaolo Prazzoli, Angelo Salese
// copyright-holders: Steve Ellenoff, Pierpaolo Prazzoli, Angelo Salese
/**************************************************************************
Portraits
(c) 1983 Olympia
@ -96,18 +97,318 @@ DM81LS95 = TriState buffer
**************************************************************************/
#include "emu.h"
#include "portrait.h"
#include "cpu/mcs48/mcs48.h"
#include "cpu/z80/z80.h"
#include "machine/gen_latch.h"
#include "machine/nvram.h"
#include "machine/pit8253.h"
#include "sound/tms5220.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "tilemap.h"
namespace {
class portrait_state : public driver_device
{
public:
portrait_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_palette(*this, "palette")
, m_tms(*this, "tms")
, m_bgvideoram(*this, "bgvideoram")
, m_fgvideoram(*this, "fgvideoram")
, m_spriteram(*this, "spriteram")
, m_lamps(*this, "lamp%u", 0U)
, m_photo(*this, "photo")
{ }
static constexpr feature_type unemulated_features() { return feature::CAMERA; }
void portrait(machine_config &config);
protected:
virtual void machine_start() override { m_lamps.resolve(); m_photo.resolve(); }
virtual void video_start() override;
private:
void ctrl_w(uint8_t data);
void scroll_w(offs_t offset, uint8_t data);
void bgvideo_write(offs_t offset, uint8_t data);
void fgvideo_write(offs_t offset, uint8_t data);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
void palette_init(palette_device &palette) const;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
inline void get_tile_info(tile_data &tileinfo, int tile_index, const uint8_t *source);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t priority);
void main_program_map(address_map &map);
void audio_program_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<i8039_device> m_audiocpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_device<tms5200_device> m_tms;
required_shared_ptr<uint8_t> m_bgvideoram;
required_shared_ptr<uint8_t> m_fgvideoram;
required_shared_ptr<uint8_t> m_spriteram;
output_finder<2> m_lamps;
output_finder<> m_photo;
uint16_t m_scroll = 0;
tilemap_t *m_foreground = nullptr;
tilemap_t *m_background = nullptr;
};
void portrait_state::bgvideo_write(offs_t offset, uint8_t data)
{
m_background->mark_tile_dirty(offset / 2);
m_bgvideoram[offset] = data;
}
void portrait_state::fgvideo_write(offs_t offset, uint8_t data)
{
m_foreground->mark_tile_dirty(offset / 2);
m_fgvideoram[offset] = data;
}
// NB: undisplayed areas gets filled at POST but never really used
// $8x36-$8x3f / $8x76-$8x7f / $8xb6-$8xbf / $8xf6-$8xff
// given that tilemap doesn't really cope well with live editing your best bet in debugging this is
// potentially to subscribe these unused areas to a mark_all_dirty() fn.
inline void portrait_state::get_tile_info(tile_data &tileinfo, int tile_index, const uint8_t *source)
{
int const attr = source[tile_index * 2 + 0];
int tilenum = source[tile_index * 2 + 1];
int flags = 0;
int color = 0;
// TODO: always set with bit 4
if (attr & 0x20) flags = TILE_FLIPY;
if (attr & 1)
tilenum += 0x200;
if (attr & 2)
tilenum += 0x100;
if (attr & 4)
tilenum ^= 0x300;
// TODO: is the wild arrangement above related to how color upper banks should work?
// cfr. trees in stage 4 leaving holes against the other layer
// TODO: kludgy
// at worst this is modified at mixing time, outputting sprite color for the status bar.
if (tilenum < 0x100)
color = ((tilenum & 0xfe) >> 1) + 0x00;
else
color = ((tilenum & 0xfe) >> 1) + 0x80;
tileinfo.set(0, tilenum, color, flags);
}
TILE_GET_INFO_MEMBER(portrait_state::get_bg_tile_info)
{
get_tile_info(tileinfo, tile_index, m_bgvideoram);
}
TILE_GET_INFO_MEMBER(portrait_state::get_fg_tile_info)
{
get_tile_info(tileinfo, tile_index, m_fgvideoram);
}
void portrait_state::video_start()
{
m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(portrait_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(portrait_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
m_foreground->set_transparent_pen(7);
save_item(NAME(m_scroll));
}
/* tileattr ROM
this appears to be divided into 2 0x400 banks
0x000 - 0x3ff relates to tiles 0x000-0x0ff
0x400 - 0x7ff relates to tiles 0x100-0x1ff, 0x200-0x2ff, and 0x300-0x3ff
every 2 tiles are somehow related to 8 bytes in the data
so tiles 0x00 and 0x01 use bytes 0x000-0x007
0x02 0x008
0x04 0x010
0x06 0x018
0x08 0x020
0x0a 0x028
0x0c 0x030
0x0e 0x038
0x10 0x040
.......
0xfe and 0xff use bytes 0x3f8-0x3ff
etc.
it's probably some kind of lookup table for the colours (6bpp = 8 colours, maybe every 2 tiles share the same 8 colours)
I guess either the bank (0/1) can be selected, or bank 0 is hardcoded to tiles 0x000-0x0ff (because tilemaps can use
these tiles too, so it's not a case of it being a sprite/tilemap lookup split)
anyway.. this is why the portraits logo is broken across 3 areas (0x1f2, 0x2f2, 0x3f2) so that they can share the same
attributes from this ROM
*/
void portrait_state::palette_init(palette_device &palette) const
{
uint8_t const *const color_prom = memregion("proms")->base();
for (int i = 0; i < 0x20; i++)
{
int const data = (color_prom[i + 0] << 0) | (color_prom[i + 0x20] << 8);
// TODO: experimental workbench, not using pal*bit intentionally.
// 13 valid bits:
// [+0x00] bit 0-3, bit 6-4
// [+0x20] bit 0-2, bit 7-5
// Only bit 0-3 seems to have a valid color ramp, is the rest actually bit mixed?
int ii = (data >> 0) & 0x0f;
//int b = ((data >> 4) & 0x7) * ii;
//int r = ((data >> 8) & 0x7) * ii;
//int g = ((data >> 13) & 0x7) * ii;
int r = ii * 0x11;
int g = ii * 0x11;
int b = ii * 0x11;
palette.set_indirect_color(i, rgb_t(r, g, b));
ii = (data >> 1) & 0x0f;
r = ii * 0x11;
g = ii * 0x11;
b = ii * 0x11;
// ?? the lookup seems to reference 0x3f colours, unless 1 bit is something else (priority?)
palette.set_indirect_color(i + 0x20, rgb_t(r, g, b));
}
uint8_t const *const lookup = memregion("tileattr")->base();
for (int i = 0; i < 0x800; i++)
{
uint8_t const ctabentry = lookup[i] & 0x3f;
palette.set_pen_indirect(i, ctabentry);
}
}
/*
* [2]
* x--- ---- priority?
* -x-- ---- more priority?
* \- eagle sprite in stage 4 sets this only,
* drawing should really go above the fg layer mountains
* (missing tile category?)
* --x- ---- flipy
* ---x ---- ?
* ---- x--- msb Y position?
* ---- -x-- msb X position?
*/
void portrait_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t priority)
{
uint8_t const *source = m_spriteram;
uint8_t const *finish = source + 0x200;
// TODO: is anything beyond byte [3] really just work RAM buffer?
for (; source < finish; source += 0x10)
{
uint8_t const attr = source[2];
if (BIT(attr, 7) != priority)
continue;
uint16_t sy = source[0];
uint16_t sx = source[1];
uint8_t const tilenum = source[3];
// TODO: may be given by source[4] and/or source[5] instead
uint8_t color = ((tilenum & 0xff) >> 1) + 0x00;
int const fy = BIT(attr, 5);
if (BIT(attr, 2)) sx |= 0x100;
if (BIT(attr, 3)) sy |= 0x100;
sx += (source - m_spriteram) - 8;
sx &= 0x1ff;
// TODO: confirm Y calculation
// it expects to follow up whatever is the current scroll value (cfr. monkeys climbing trees in stage 1)
// but then there are various misc sprites that break this rule. Examples are:
// - player photo flash;
// - death animation sprites;
// - capturing photo frame in gameplay;
// PC=0x2828 is where all of these odd sprites happen, where:
// HL=ROM pointer for destination sprite pointer, IY=sprite pointer source
// where they copy the origin of the given sprite, read scroll buffer $9235-36 then apply offset,
// with [2] bits 7-6 set high and bits 5-4 copied from the source sprite.
// Note that this will break elsewhere by logically using any of the [2] bits,
// arguably SW does a very limited use to pinpoint what's the actual scroll disable condition,
// it just implicitly don't setup [4] to [7] ...
if ((source[5] & 0xf) == 0)
sy = (511 - 16) - sy;
else
sy = ((511 - m_scroll) - 16) - sy;
sy &= 0x1ff;
m_gfxdecode->gfx(0)->transpen(
bitmap, cliprect,
tilenum, color,
0, fy,
sx, sy,
7);
}
}
uint32_t portrait_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
rectangle cliprect_scroll, cliprect_no_scroll;
cliprect_scroll = cliprect_no_scroll = cliprect;
// TODO: make clipping areas more readable
cliprect_no_scroll.min_x = cliprect_no_scroll.max_x - 111;
cliprect_scroll.max_x = cliprect_scroll.min_x + 319;
// status bar
m_background->set_scrolly(0, 0);
m_foreground->set_scrolly(0, 0);
m_background->draw(screen, bitmap, cliprect_no_scroll, 0, 0);
m_foreground->draw(screen, bitmap, cliprect_no_scroll, 0, 0);
// playfield
m_background->set_scrolly(0, m_scroll);
m_foreground->set_scrolly(0, m_scroll);
m_background->draw(screen, bitmap, cliprect_scroll, 0, 0);
draw_sprites(bitmap, cliprect_scroll, 0);
m_foreground->draw(screen, bitmap, cliprect_scroll, 0, 0);
draw_sprites(bitmap, cliprect_scroll, 1);
return 0;
}
void portrait_state::ctrl_w(uint8_t data)
{
/* bits 4 and 5 are unknown */
// bits 4 and 5 are unknown
// TODO: condition for just displaying stored camera image
// 0xf8 when capturing for the hi-score new pic, 0xb0 when displaying it from attract mode.
@ -115,11 +416,11 @@ void portrait_state::ctrl_w(uint8_t data)
machine().bookkeeping().coin_counter_w(1, data & 0x02);
machine().bookkeeping().coin_counter_w(2, data & 0x04);
/* the 2 lamps near the camera */
// the 2 lamps near the camera
m_lamps[0] = BIT(data, 3);
m_lamps[1] = BIT(data, 6);
/* shows the black and white photo from the camera */
// shows the black and white photo from the camera
m_photo = BIT(data, 7);
}
@ -132,16 +433,15 @@ void portrait_state::scroll_w(offs_t offset, uint8_t data)
m_scroll += 256;
}
void portrait_state::portrait_map(address_map &map)
void portrait_state::main_program_map(address_map &map)
{
map(0x0000, 0x7fff).rom();
map(0x8000, 0x87ff).ram().w(FUNC(portrait_state::bgvideo_write)).share("bgvideoram");
map(0x8800, 0x8fff).ram().w(FUNC(portrait_state::fgvideo_write)).share("fgvideoram");
map(0x9000, 0x91ff).ram().share("spriteram");
map(0x8000, 0x87ff).ram().w(FUNC(portrait_state::bgvideo_write)).share(m_bgvideoram);
map(0x8800, 0x8fff).ram().w(FUNC(portrait_state::fgvideo_write)).share(m_fgvideoram);
map(0x9000, 0x91ff).ram().share(m_spriteram);
map(0x9200, 0x97ff).ram();
map(0xa000, 0xa000).w("soundlatch", FUNC(generic_latch_8_device::write));
map(0xa000, 0xa000).portr("DSW1").w("soundlatch", FUNC(generic_latch_8_device::write));
map(0xa010, 0xa010).nopw(); // more sound? Follows up whatever is happening on screen
map(0xa000, 0xa000).portr("DSW1");
map(0xa004, 0xa004).portr("DSW2");
map(0xa008, 0xa008).portr("SYSTEM").w(FUNC(portrait_state::ctrl_w));
map(0xa010, 0xa010).portr("INPUTS");
@ -153,7 +453,7 @@ void portrait_state::portrait_map(address_map &map)
}
void portrait_state::portrait_sound_map(address_map &map)
void portrait_state::audio_program_map(address_map &map)
{
map(0x0000, 0x0fff).rom();
}
@ -242,34 +542,36 @@ INPUT_PORTS_END
static const gfx_layout tile_layout =
{
16,16, /* tile width, height */
1024, /* number of characters */
3, /* bits per pixel */
{ 0x0000*8, 0x4000*8, 0x8000*8 }, /* bitplane offsets */
16,16, // tile width, height
1024, // number of characters
3, // bits per pixel
{ 0x0000*8, 0x4000*8, 0x8000*8 }, // bitplane offsets
{
RGN_FRAC(1,2)+7, RGN_FRAC(1,2)+6, RGN_FRAC(1,2)+5, RGN_FRAC(1,2)+4,
RGN_FRAC(1,2)+3, RGN_FRAC(1,2)+2, RGN_FRAC(1,2)+1, RGN_FRAC(1,2)+0,
0, 1, 2, 3, 4, 5, 6, 7
},
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 8*9, 8*10, 8*11, 8*12, 8*13, 8*14, 8*15 },
8*16 /* character offset */
8*16 // character offset
};
static GFXDECODE_START( gfx_portrait )
GFXDECODE_ENTRY( "gfx1", 0x00000, tile_layout, 0, 0x800/8 )
GFXDECODE_ENTRY( "tiles", 0x00000, tile_layout, 0, 0x800/8 )
GFXDECODE_END
void portrait_state::portrait(machine_config &config)
{
Z80(config, m_maincpu, 4000000); /* 4 MHz ? */
m_maincpu->set_addrmap(AS_PROGRAM, &portrait_state::portrait_map);
Z80(config, m_maincpu, 4'000'000); // 4 MHz ?
m_maincpu->set_addrmap(AS_PROGRAM, &portrait_state::main_program_map);
m_maincpu->set_vblank_int("screen", FUNC(portrait_state::irq0_line_hold));
I8039(config, m_audiocpu, 3120000); /* ? */
m_audiocpu->set_addrmap(AS_PROGRAM, &portrait_state::portrait_sound_map);
I8039(config, m_audiocpu, 3'120'000); // ?
m_audiocpu->set_addrmap(AS_PROGRAM, &portrait_state::audio_program_map);
// TODO: PIT8253
PIT8253(config, "pit0", 0); // TODO
PIT8253(config, "pit1", 0); // TODO
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
@ -282,19 +584,19 @@ void portrait_state::portrait(machine_config &config)
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_portrait);
PALETTE(config, m_palette, FUNC(portrait_state::portrait_palette), 0x800, 0x40);
PALETTE(config, m_palette, FUNC(portrait_state::palette_init), 0x800, 0x40);
/* sound hardware */
// sound hardware
SPEAKER(config, "mono").front_center();
GENERIC_LATCH_8(config, "soundlatch");
TMS5200(config, m_tms, 640000).add_route(ALL_OUTPUTS, "mono", 1.0);
TMS5200(config, m_tms, 640'000).add_route(ALL_OUTPUTS, "mono", 1.0);
}
ROM_START( portrait )
ROM_REGION( 0x10000, "maincpu", 0 ) /* 64k for the cpu */
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "prt-p0.bin", 0x0000, 0x2000, CRC(a21874fa) SHA1(3db863f465a35d7d14dd71b47aa7dfe7b39fccf0) )
ROM_LOAD( "prt-p1.bin", 0x2000, 0x2000, CRC(4d4d7793) SHA1(f828950ebbf285fc92c65f24421a20ceacef1cb9) )
ROM_LOAD( "prt-p2.bin", 0x4000, 0x2000, CRC(83d88c9c) SHA1(c876f72b66537a49620fa27a5cb8a4aecd378f0a) )
@ -304,7 +606,7 @@ ROM_START( portrait )
ROM_LOAD( "port_w.bin", 0x0000, 0x0800, CRC(d3a4e950) SHA1(0a399d43c7690d568874f3b1d55135f803fc223f) )
ROM_LOAD( "port_ma.bin", 0x0800, 0x0800, CRC(ee242e4f) SHA1(fb67e0d136927e04f4fa819f684c97b0d52ee48c) )
ROM_REGION( 0x20000, "gfx1", 0 )
ROM_REGION( 0x20000, "tiles", 0 )
ROM_LOAD( "port_00.a1", 0x00000, 0x2000, CRC(eb3e1c12) SHA1(2d38b66f52546b40553244c8a5c961279559f5b6) )
ROM_LOAD( "port_10.b1", 0x02000, 0x2000, CRC(0f44e377) SHA1(1955f9f4deab2166f637f43c1f326bd65fc90f6a) )
@ -326,7 +628,7 @@ ROM_START( portrait )
ROM_REGION( 0x0800, "user1", 0 ) // sound related?
ROM_LOAD( "port_sa.bin", 0x0000, 0x0800, CRC(50510897) SHA1(8af0f42699602a5b33500968c958e3784e03377f) )
ROM_REGION( 0x800, "tileattr", 0 ) // tile attributes
ROM_REGION( 0x800, "tileattr", 0 )
ROM_LOAD( "93z511.bin", 0x0000, 0x0800, CRC(d66d9036) SHA1(7a25efbd8f2f94a01aad9e2be9cb18da7b9ec1d1) )
ROM_REGION( 0x40, "proms", 0 ) // colors
@ -335,7 +637,7 @@ ROM_START( portrait )
ROM_END
ROM_START( portraita )
ROM_REGION( 0x10000, "maincpu", 0 ) /* 64k for the cpu */
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "portp0f.m1", 0x0000, 0x2000, CRC(333eace3) SHA1(8f02df09d8b50d7e37d5abf7d539624c59a7201e) )
ROM_LOAD( "portp0f.p1", 0x2000, 0x2000, CRC(fe258052) SHA1(f453eb05c68d61dfd644688732ff5c07366c68c0) )
ROM_LOAD( "portp2f.r1", 0x4000, 0x2000, CRC(bc0104d5) SHA1(7707b85cde2dc9bd95391d4e1dbed219c52618cd) )
@ -345,7 +647,7 @@ ROM_START( portraita )
ROM_LOAD( "port_w.bin", 0x0000, 0x0800, CRC(d3a4e950) SHA1(0a399d43c7690d568874f3b1d55135f803fc223f) )
ROM_LOAD( "port_ma.bin", 0x0800, 0x0800, CRC(ee242e4f) SHA1(fb67e0d136927e04f4fa819f684c97b0d52ee48c) )
ROM_REGION( 0x20000, "gfx1", 0 )
ROM_REGION( 0x20000, "tiles", 0 )
ROM_LOAD( "port_00.a1", 0x00000, 0x2000, CRC(eb3e1c12) SHA1(2d38b66f52546b40553244c8a5c961279559f5b6) )
ROM_LOAD( "port_10.b1", 0x02000, 0x2000, CRC(0f44e377) SHA1(1955f9f4deab2166f637f43c1f326bd65fc90f6a) )
ROM_LOAD( "port_02.d1", 0x04000, 0x2000, CRC(bd93a3f9) SHA1(9cb479b8840cafd6043ff0cb9d5ca031dcd332ba) )
@ -360,7 +662,7 @@ ROM_START( portraita )
ROM_LOAD( "port_05.g2", 0x18000, 0x2000, CRC(43ea7951) SHA1(df0ae7fa802365979514063e1d67cdd45ecada90) )
ROM_LOAD( "port_15.h2", 0x1a000, 0x2000, CRC(ab20b438) SHA1(ea5d60f6a9f06397bd0c6ee028b463c684090c01) )
ROM_REGION( 0x800, "tileattr", 0 ) // tile attributes (see notes)
ROM_REGION( 0x800, "tileattr", 0 ) // (see notes)
ROM_LOAD( "93z511.bin", 0x0000, 0x0800, CRC(d66d9036) SHA1(7a25efbd8f2f94a01aad9e2be9cb18da7b9ec1d1) )
ROM_REGION( 0x40, "proms", 0 ) // colors
@ -368,6 +670,8 @@ ROM_START( portraita )
ROM_LOAD( "port_pr2.n4", 0x20, 0x0020, CRC(008634f3) SHA1(7cde6b09ede672d562569866d944428198f2ba9c) )
ROM_END
} // anonymous namespace
GAME( 1983, portrait, 0, portrait, portrait, portrait_state, empty_init, ROT270, "Olympia", "Portraits (set 1)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE )
GAME( 1983, portraita,portrait, portrait, portrait, portrait_state, empty_init, ROT270, "Olympia", "Portraits (set 2)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE ) // harder set
GAME( 1983, portrait, 0, portrait, portrait, portrait_state, empty_init, ROT270, "Olympia", "Portraits (set 1)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE )
GAME( 1983, portraita, portrait, portrait, portrait, portrait_state, empty_init, ROT270, "Olympia", "Portraits (set 2)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE ) // harder set

View File

@ -1,72 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Steve Ellenoff, Pierpaolo Prazzoli, Angelo Salese
#ifndef MAME_OLYMPIA_PORTRAIT_H
#define MAME_OLYMPIA_PORTRAIT_H
#pragma once
#include "cpu/mcs48/mcs48.h"
#include "sound/tms5220.h"
#include "emupal.h"
#include "tilemap.h"
class portrait_state : public driver_device
{
public:
portrait_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_palette(*this, "palette")
, m_tms(*this, "tms")
, m_bgvideoram(*this, "bgvideoram")
, m_fgvideoram(*this, "fgvideoram")
, m_spriteram(*this, "spriteram")
, m_lamps(*this, "lamp%u", 0U)
, m_photo(*this, "photo")
{ }
static constexpr feature_type unemulated_features() { return feature::CAMERA; }
void portrait(machine_config &config);
protected:
virtual void machine_start() override { m_lamps.resolve(); m_photo.resolve(); }
virtual void video_start() override;
private:
void ctrl_w(uint8_t data);
void scroll_w(offs_t offset, uint8_t data);
void bgvideo_write(offs_t offset, uint8_t data);
void fgvideo_write(offs_t offset, uint8_t data);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
void portrait_palette(palette_device &palette) const;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
inline void get_tile_info( tile_data &tileinfo, int tile_index, const uint8_t *source );
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u8 priority);
void portrait_map(address_map &map);
void portrait_sound_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<i8039_device> m_audiocpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_device<tms5200_device> m_tms;
required_shared_ptr<uint8_t> m_bgvideoram;
required_shared_ptr<uint8_t> m_fgvideoram;
required_shared_ptr<uint8_t> m_spriteram;
output_finder<2> m_lamps;
output_finder<> m_photo;
int m_scroll = 0;
tilemap_t *m_foreground = nullptr;
tilemap_t *m_background = nullptr;
};
#endif // MAME_OLYMPIA_PORTRAIT_H

View File

@ -1,244 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Steve Ellenoff, Pierpaolo Prazzoli, Angelo Salese
/***************************************************************************
Portraits
video hardware emulation
***************************************************************************/
#include "emu.h"
#include "portrait.h"
void portrait_state::bgvideo_write(offs_t offset, uint8_t data)
{
m_background->mark_tile_dirty(offset/2);
m_bgvideoram[offset] = data;
}
void portrait_state::fgvideo_write(offs_t offset, uint8_t data)
{
m_foreground->mark_tile_dirty(offset/2);
m_fgvideoram[offset] = data;
}
// NB: undisplayed areas gets filled at POST but never really used
// $8x36-$8x3f / $8x76-$8x7f / $8xb6-$8xbf / $8xf6-$8xff
// given that tilemap doesn't really cope well with live editing your best bet in debugging this is
// potentially to subscribe these unused areas to a mark_all_dirty() fn.
inline void portrait_state::get_tile_info( tile_data &tileinfo, int tile_index, const uint8_t *source )
{
int attr = source[tile_index*2+0];
int tilenum = source[tile_index*2+1];
int flags = 0;
int color = 0;
// TODO: always set with bit 4
if( attr & 0x20 ) flags = TILE_FLIPY;
if (attr & 1)
tilenum += 0x200;
if (attr & 2)
tilenum += 0x100;
if (attr & 4)
tilenum ^= 0x300;
// TODO: is the wild arrangement above related to how color upper banks should work?
// cfr. trees in stage 4 leaving holes against the other layer
// TODO: kludgy
// at worst this is modified at mixing time, outputting sprite color for the status bar.
if (tilenum<0x100)
color = ((tilenum&0xfe) >> 1) + 0x00;
else
color = ((tilenum&0xfe) >> 1) + 0x80;
tileinfo.set(0, tilenum, color, flags );
}
TILE_GET_INFO_MEMBER(portrait_state::get_bg_tile_info)
{
get_tile_info(tileinfo, tile_index, m_bgvideoram );
}
TILE_GET_INFO_MEMBER(portrait_state::get_fg_tile_info)
{
get_tile_info(tileinfo, tile_index, m_fgvideoram );
}
void portrait_state::video_start()
{
m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(portrait_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(portrait_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
m_foreground->set_transparent_pen(7);
save_item(NAME(m_scroll));
}
/* tileattr rom
this appears to be divided into 2 0x400 banks
0x000 - 0x3ff relates to tiles 0x000-0x0ff
0x400 - 0x7ff relates to tiles 0x100-0x1ff, 0x200-0x2ff, and 0x300-0x3ff
every 2 tiles are somehow related to 8 bytes in the data
so tiles 0x00 and 0x01 use bytes 0x000-0x007
0x02 0x008
0x04 0x010
0x06 0x018
0x08 0x020
0x0a 0x028
0x0c 0x030
0x0e 0x038
0x10 0x040
.......
0xfe and 0xff use bytes 0x3f8-0x3ff
etc.
it's probably some kind of lookup table for the colours (6bpp = 8 colours, maybe every 2 tiles share the same 8 colours)
I guess either the bank (0/1) can be selected, or bank 0 is hardcoded to tiles 0x000-0x0ff (because tilemaps can use
these tiles too, so it's not a case of it being a sprite/tilemap lookup split)
anyway.. this is why the portraits logo is broken across 3 areas (0x1f2, 0x2f2, 0x3f2) so that they can share the same
attributes from this rom
*/
void portrait_state::portrait_palette(palette_device &palette) const
{
uint8_t const *const color_prom = memregion("proms")->base();
for (int i = 0; i < 0x20; i++)
{
int const data = (color_prom[i + 0] << 0) | (color_prom[i + 0x20] << 8);
// TODO: experimental workbench, not using pal*bit intentionally.
// 13 valid bits:
// [+0x00] bit 0-3, bit 6-4
// [+0x20] bit 0-2, bit 7-5
// Only bit 0-3 seems to have a valid color ramp, is the rest actually bit mixed?
int ii = (data >> 0) & 0x0f;
//int b = ((data >> 4) & 0x7) * ii;
//int r = ((data >> 8) & 0x7) * ii;
//int g = ((data >> 13) & 0x7) * ii;
int r = ii * 0x11;
int g = ii * 0x11;
int b = ii * 0x11;
palette.set_indirect_color(i, rgb_t(r, g, b));
ii = (data >> 1) & 0x0f;
r = ii * 0x11;
g = ii * 0x11;
b = ii * 0x11;
// ?? the lookup seems to reference 0x3f colours, unless 1 bit is something else (priority?)
palette.set_indirect_color(i + 0x20, rgb_t(r, g, b));
}
uint8_t const *const lookup = memregion("tileattr")->base();
for (int i = 0; i < 0x800; i++)
{
uint8_t const ctabentry = lookup[i] & 0x3f;
palette.set_pen_indirect(i, ctabentry);
}
}
/*
* [2]
* x--- ---- priority?
* -x-- ---- more priority?
* \- eagle sprite in stage 4 sets this only,
* drawing should really go above the fg layer mountains
* (missing tile category?)
* --x- ---- flipy
* ---x ---- ?
* ---- x--- msb Y position?
* ---- -x-- msb X position?
*/
void portrait_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u8 priority)
{
uint8_t *source = m_spriteram;
uint8_t *finish = source + 0x200;
// TODO: is anything beyond byte [3] really just work RAM buffer?
for( ; source < finish; source += 0x10 )
{
u8 attr = source[2];
if (BIT(attr, 7) != priority)
continue;
u16 sy = source[0];
u16 sx = source[1];
u8 tilenum = source[3];
// TODO: may be given by source[4] and/or source[5] instead
u8 color = ((tilenum&0xff)>>1)+0x00;
int fy = BIT(attr, 5);
if (BIT(attr, 2)) sx |= 0x100;
if (BIT(attr, 3)) sy |= 0x100;
sx += (source - m_spriteram) - 8;
sx &= 0x1ff;
// TODO: confirm Y calculation
// it expects to follow up whatever is the current scroll value (cfr. monkeys climbing trees in stage 1)
// but then there are various misc sprites that breaks this rule. Examples are:
// - player photo flash;
// - death animation sprites;
// - capturing photo frame in gameplay;
// PC=0x2828 is where all of these odd sprites happens, where:
// HL=ROM pointer for destination sprite pointer, IY=sprite pointer source
// where they copy the origin of the given sprite, read scroll buffer $9235-36 then apply offset,
// with [2] bits 7-6 set high and bits 5-4 copied from the source sprite.
// Note that this will break elsewhere by logically using any of the [2] bits,
// arguably SW does a very limited use to pinpoint what's the actual scroll disable condition,
// it just implicitly don't setup [4] to [7] ...
if ((source[5] & 0xf) == 0)
sy = (511 - 16) - sy;
else
sy = ((511 - m_scroll) - 16) - sy;
sy &= 0x1ff;
m_gfxdecode->gfx(0)->transpen(
bitmap, cliprect,
tilenum, color,
0, fy,
sx, sy,
7);
}
}
uint32_t portrait_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
rectangle cliprect_scroll, cliprect_no_scroll;
cliprect_scroll = cliprect_no_scroll = cliprect;
// TODO: make clipping areas more readable
cliprect_no_scroll.min_x = cliprect_no_scroll.max_x - 111;
cliprect_scroll.max_x = cliprect_scroll.min_x + 319;
// status bar
m_background->set_scrolly(0, 0);
m_foreground->set_scrolly(0, 0);
m_background->draw(screen, bitmap, cliprect_no_scroll, 0, 0);
m_foreground->draw(screen, bitmap, cliprect_no_scroll, 0, 0);
// playfield
m_background->set_scrolly(0, m_scroll);
m_foreground->set_scrolly(0, m_scroll);
m_background->draw(screen, bitmap, cliprect_scroll, 0, 0);
draw_sprites(bitmap, cliprect_scroll, 0);
m_foreground->draw(screen, bitmap, cliprect_scroll, 0, 0);
draw_sprites(bitmap, cliprect_scroll, 1);
return 0;
}

View File

@ -39,7 +39,7 @@
|_________________________________________________test_test___________________________________________|
-JMP3, JMP4, JMP8, JMP9, and JMP10 are for setting up the baud rate of each OKI M82C51A USART (you can
configuse 1200, 2400, 4800, 9600, 19200 or 38400 bps.
configure 1200, 2400, 4800, 9600, 19200 or 38400 bps.
****************************************************************************************/

View File

@ -50,7 +50,9 @@ LD15 (_)
****************************************************************************************************************/
#include "emu.h"
#include "cpu/m6502/m6504.h"
#include "speaker.h"
namespace {
@ -69,9 +71,40 @@ public:
private:
required_device<cpu_device> m_maincpu;
INTERRUPT_GEN_MEMBER(irq_gen);
void program_map(address_map &map);
};
INTERRUPT_GEN_MEMBER(elcirculo_state::irq_gen)
{
m_maincpu->set_input_line(M6504_IRQ_LINE, HOLD_LINE);
}
void elcirculo_state::program_map(address_map &map)
{
map.global_mask(0x1fff);
map(0x0000, 0x01ff).ram();
map(0x0200, 0x0200).portr("IN0");
map(0x0201, 0x0201).portr("DSW1");
// map(0x0400, 0x0401).w();
// map(0x0600, 0x0601).w();
map(0x1000, 0x17ff).mirror(0x800).rom().region("maincpu", 0);
}
INPUT_PORTS_START(elcirculo)
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("DSW1")
PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW1:1")
PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "SW1:2")
@ -86,15 +119,17 @@ INPUT_PORTS_END
void elcirculo_state::elcirculo(machine_config &config)
{
M6504(config, m_maincpu, 1'000'000); // R6504P, internal clock
m_maincpu->set_addrmap(AS_PROGRAM, &elcirculo_state::program_map);
m_maincpu->set_periodic_int(FUNC(elcirculo_state::irq_gen), attotime::from_hz(60)); // TODO: source of this
SPEAKER(config, "mono").front_center();
}
ROM_START(elcirculo)
ROM_REGION(0x800, "maincpu", 0)
ROM_LOAD("tms2716c.ic2", 0x000, 0x800, CRC(7b5ae97f) SHA1(e7276d5d97328628889d216beac0b04216bf82c7))
ROM_START( elcirculo )
ROM_REGION( 0x800, "maincpu", 0 )
ROM_LOAD( "tms2716c.ic2", 0x000, 0x800, CRC(7b5ae97f) SHA1(e7276d5d97328628889d216beac0b04216bf82c7) )
ROM_END
} // Anonymous namespace
} // anonymous namespace
GAME(1980, elcirculo, 0, elcirculo, elcirculo, elcirculo_state, empty_init, ROT0, "Inder", "El Circulo", MACHINE_IS_SKELETON)

View File

@ -13,7 +13,7 @@
In particular
- It uses a LSI Zevio 1020 CPU + peripherals which comprises ARM926EJ-S CPU,
ZSP400 DPS, 3D graphics processor & 2D graphics processor
ZSP400 DSP, 3D graphics processor & 2D graphics processor
- The CD controller is a Sony CXD3059AR
****************************************************************************/
@ -23,8 +23,8 @@
#include "cpu/arm7/arm7.h"
#include "imagedev/cdromimg.h"
#include "softlist.h"
#include "cdrom.h"
#include "softlist.h"
namespace {
@ -51,13 +51,13 @@ void vsmilpro_state::vsmilpro_map(address_map &map)
}
/* Input ports */
// Input ports
static INPUT_PORTS_START( vsmilpro )
INPUT_PORTS_END
void vsmilpro_state::vsmilpro(machine_config &config)
{
/* basic machine hardware */
// basic machine hardware
ARM9(config, m_maincpu, 150000000);
m_maincpu->set_addrmap(AS_PROGRAM, &vsmilpro_state::vsmilpro_map);
@ -66,7 +66,7 @@ void vsmilpro_state::vsmilpro(machine_config &config)
SOFTWARE_LIST(config, "cd_list").set_original("vsmile_cd");
}
/* ROM definition */
// ROM definition
ROM_START( vsmilpro )
ROM_REGION( 0x200000, "maincpu", 0 )
ROM_LOAD( "70004.bin", 0x000000, 0x200000, CRC(b9161eac) SHA1(8d75fdeda8c4e228a0b1efd35011f9f667f9fb23) )
@ -75,7 +75,7 @@ ROM_END
} // anonymous namespace
/* Driver */
// Driver
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 2007, vsmilpro, 0, 0, vsmilpro, vsmilpro, vsmilpro_state, empty_init, "VTech", "V.Smile Pro", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
COMP( 2007, vsmilpro, 0, 0, vsmilpro, vsmilpro, vsmilpro_state, empty_init, "VTech", "V.Smile Pro", MACHINE_IS_SKELETON )