mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
New working clones
------------------ Transporter the Rescue (LA-1) [Scott Charles, PinMAME] - dataeast/lemmings.cpp: consolidated driver in single file
This commit is contained in:
parent
3e4ed5d6fe
commit
8e95e766ef
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Bryan McPhail
|
||||
// copyright-holders: Bryan McPhail
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Lemmings (c) 1991 Data East USA (DE-0357)
|
||||
@ -11,74 +12,308 @@
|
||||
arcade hardware.
|
||||
|
||||
As prototype software it seems to have a couple of non-critical bugs,
|
||||
the palette ram check and vram check both overrun their actual ramsize.
|
||||
the palette RAM check and VRAM check both overrun their actual RAM size.
|
||||
|
||||
Emulation by Bryan McPhail, mish@tendril.co.uk
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "lemmings.h"
|
||||
|
||||
#include "deco146.h"
|
||||
#include "decospr.h"
|
||||
|
||||
#include "cpu/m6809/m6809.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "machine/gen_latch.h"
|
||||
#include "sound/okim6295.h"
|
||||
#include "sound/ymopm.h"
|
||||
#include "video/bufsprite.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
void lemmings_state::lemmings_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
namespace {
|
||||
|
||||
class lemmings_state : public driver_device
|
||||
{
|
||||
/* Offset==0 Pixel layer X scroll */
|
||||
public:
|
||||
lemmings_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_bitmap0(2048, 256)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_audiocpu(*this, "audiocpu")
|
||||
, m_deco146(*this, "ioprot")
|
||||
, m_spriteram(*this, "spriteram%u", 1)
|
||||
, m_sprgen(*this, "spritegen%u", 1)
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_palette(*this, "palette")
|
||||
, m_soundlatch(*this, "soundlatch")
|
||||
, m_control_data(*this, "control_data")
|
||||
, m_vram_data(*this, "vram_data")
|
||||
, m_pixel_data(*this, "pixel_%u_data", 0)
|
||||
, m_trackball_io(*this, "AN%u", 0)
|
||||
{
|
||||
}
|
||||
|
||||
void lemmings(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
// video-related
|
||||
bitmap_ind16 m_bitmap0{};
|
||||
tilemap_t *m_vram_tilemap = nullptr;
|
||||
std::unique_ptr<uint16_t[]> m_sprite_triple_buffer[2]{};
|
||||
std::unique_ptr<uint8_t[]> m_vram_buffer{};
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<deco146_device> m_deco146;
|
||||
required_device_array<buffered_spriteram16_device, 2> m_spriteram;
|
||||
required_device_array<decospr_device, 2> m_sprgen;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<uint16_t> m_control_data;
|
||||
required_shared_ptr<uint16_t> m_vram_data;
|
||||
required_shared_ptr_array<uint16_t, 2> m_pixel_data;
|
||||
|
||||
required_ioport_array<4> m_trackball_io;
|
||||
|
||||
void control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t trackball_r(offs_t offset);
|
||||
void pixel_0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void pixel_1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void screen_vblank(int state);
|
||||
void copy_bitmap(bitmap_rgb32 &bitmap, int *xscroll, int *yscroll, const rectangle &cliprect);
|
||||
|
||||
uint16_t protection_region_0_146_r(offs_t offset);
|
||||
void protection_region_0_146_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void main_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
There are two sets of sprites, the combination of custom chips 52 & 71.
|
||||
There is a background pixel layer implemented with discrete logic
|
||||
rather than a custom chip and a foreground VRAM tilemap layer that the
|
||||
game mostly uses as a pixel layer (the VRAM format is arranged as
|
||||
sequential pixels, rather than sequential characters).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(lemmings_state::get_tile_info)
|
||||
{
|
||||
uint16_t const tile = m_vram_data[tile_index];
|
||||
|
||||
tileinfo.set(2,
|
||||
tile & 0x7ff,
|
||||
(tile >> 12) & 0xf,
|
||||
0);
|
||||
}
|
||||
|
||||
void lemmings_state::video_start()
|
||||
{
|
||||
m_vram_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lemmings_state::get_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 64, 32);
|
||||
|
||||
m_vram_tilemap->set_transparent_pen(0);
|
||||
m_bitmap0.fill(0x100);
|
||||
|
||||
m_vram_buffer = make_unique_clear<uint8_t[]>(2048 * 64); // 64 bytes per VRAM character
|
||||
m_gfxdecode->gfx(2)->set_source(m_vram_buffer.get());
|
||||
|
||||
m_sprgen[0]->alloc_sprite_bitmap();
|
||||
m_sprgen[1]->alloc_sprite_bitmap();
|
||||
|
||||
m_sprite_triple_buffer[0] = make_unique_clear<uint16_t[]>(0x800 / 2);
|
||||
m_sprite_triple_buffer[1] = make_unique_clear<uint16_t[]>(0x800 / 2);
|
||||
|
||||
save_item(NAME(m_bitmap0));
|
||||
save_pointer(NAME(m_vram_buffer), 2048 * 64);
|
||||
save_pointer(NAME(m_sprite_triple_buffer[0]), 0x800 / 2, 0);
|
||||
save_pointer(NAME(m_sprite_triple_buffer[1]), 0x800 / 2, 1);
|
||||
}
|
||||
|
||||
void lemmings_state::screen_vblank(int state)
|
||||
{
|
||||
// rising edge
|
||||
if (state)
|
||||
{
|
||||
for (int chip = 0; chip < 2; chip++)
|
||||
std::copy_n(&m_spriteram[chip]->buffer()[0], 0x800 / 2, &m_sprite_triple_buffer[chip][0]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// RAM based
|
||||
void lemmings_state::pixel_0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
int const old = m_pixel_data[0][offset];
|
||||
COMBINE_DATA(&m_pixel_data[0][offset]);
|
||||
int const src = m_pixel_data[0][offset];
|
||||
if (old == src)
|
||||
return;
|
||||
|
||||
int const sy = (offset << 1) >> 11;
|
||||
int const sx = (offset << 1) & 0x7ff;
|
||||
|
||||
if (sx > 2047 || sy > 255)
|
||||
return;
|
||||
|
||||
m_bitmap0.pix(sy, sx + 0) = ((src >> 8) & 0xf) | 0x100;
|
||||
m_bitmap0.pix(sy, sx + 1) = ((src >> 0) & 0xf) | 0x100;
|
||||
}
|
||||
|
||||
// RAM based tiles for the FG tilemap
|
||||
void lemmings_state::pixel_1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pixel_data[1][offset]);
|
||||
int const src = m_pixel_data[1][offset];
|
||||
|
||||
int const sy = (offset << 1) >> 9;
|
||||
int sx = (offset << 1) & 0x1ff;
|
||||
|
||||
// Copy pixel to buffer for easier decoding later
|
||||
int const tile = ((sx / 8) * 32) + (sy / 8);
|
||||
m_gfxdecode->gfx(2)->mark_dirty(tile);
|
||||
m_vram_buffer[(tile * 64) + ((sx & 7)) + ((sy & 7) * 8)] = (src >> 8) & 0xf;
|
||||
|
||||
sx += 1; // Update both pixels in the word
|
||||
m_vram_buffer[(tile * 64) + ((sx & 7)) + ((sy & 7) * 8)] = (src >> 0) & 0xf;
|
||||
}
|
||||
|
||||
void lemmings_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_vram_data[offset]);
|
||||
m_vram_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
|
||||
void lemmings_state::copy_bitmap(bitmap_rgb32 &bitmap, int *xscroll, int *yscroll, const rectangle &cliprect)
|
||||
{
|
||||
pen_t const *const paldata = m_palette->pens();
|
||||
|
||||
for (int y = cliprect.top(); y < cliprect.bottom(); y++)
|
||||
{
|
||||
uint32_t *const dst = &bitmap.pix(y, 0);
|
||||
|
||||
for (int x = cliprect.left(); x < cliprect.right(); x++)
|
||||
{
|
||||
uint16_t const src = m_bitmap0.pix((y - *yscroll) & 0xff, (x - *xscroll) & 0x7ff);
|
||||
|
||||
if (src != 0x100)
|
||||
dst[x] = paldata[src];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lemmings_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int x1 = -m_control_data[0];
|
||||
int x0 = -m_control_data[2];
|
||||
int y = 0;
|
||||
rectangle rect(0, 0, cliprect.top(), cliprect.bottom());
|
||||
|
||||
// sprites are flipped relative to tilemaps
|
||||
m_sprgen[0]->set_flip_screen(true);
|
||||
m_sprgen[1]->set_flip_screen(true);
|
||||
m_sprgen[0]->draw_sprites(bitmap, cliprect, m_sprite_triple_buffer[1].get(), 0x400);
|
||||
m_sprgen[1]->draw_sprites(bitmap, cliprect, m_sprite_triple_buffer[0].get(), 0x400);
|
||||
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
m_sprgen[0]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0800, 0x0800, 0x300, 0xff);
|
||||
|
||||
// Pixel layer can be windowed in hardware (two player mode)
|
||||
if ((m_control_data[6] & 2) == 0)
|
||||
{
|
||||
copy_bitmap(bitmap, &x1, &y, cliprect);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.setx(0, 159);
|
||||
copy_bitmap(bitmap, &x0, &y, rect);
|
||||
|
||||
rect.setx(160, 319);
|
||||
copy_bitmap(bitmap, &x1, &y, rect);
|
||||
}
|
||||
|
||||
m_sprgen[1]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0800, 0x0800, 0x200, 0xff);
|
||||
m_sprgen[0]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0800, 0x300, 0xff);
|
||||
m_vram_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
m_sprgen[1]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0800, 0x200, 0xff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
void lemmings_state::control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
// Offset==0 Pixel layer X scroll
|
||||
if (offset == 4)
|
||||
return; /* Watchdog or IRQ ack */
|
||||
return; // Watchdog or IRQ ack
|
||||
COMBINE_DATA(&m_control_data[offset]);
|
||||
}
|
||||
|
||||
uint16_t lemmings_state::lemmings_trackball_r(offs_t offset)
|
||||
uint16_t lemmings_state::trackball_r(offs_t offset)
|
||||
{
|
||||
if ((offset & 2) == 0)
|
||||
return m_trackball_io[(offset & 1) | ((offset & 4) >> 1)]->read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t lemmings_state::lem_protection_region_0_146_r(offs_t offset)
|
||||
uint16_t lemmings_state::protection_region_0_146_r(offs_t offset)
|
||||
{
|
||||
int real_address = 0 + (offset *2);
|
||||
int deco146_addr = bitswap<32>(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
|
||||
int const real_address = 0 + (offset *2);
|
||||
int const deco146_addr = bitswap<32>(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
|
||||
uint8_t cs = 0;
|
||||
uint16_t data = m_deco146->read_data( deco146_addr, cs );
|
||||
uint16_t data = m_deco146->read_data(deco146_addr, cs);
|
||||
return data;
|
||||
}
|
||||
|
||||
void lemmings_state::lem_protection_region_0_146_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
void lemmings_state::protection_region_0_146_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
int real_address = 0 + (offset *2);
|
||||
int deco146_addr = bitswap<32>(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
|
||||
int const real_address = 0 + (offset *2);
|
||||
int const deco146_addr = bitswap<32>(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
|
||||
uint8_t cs = 0;
|
||||
m_deco146->write_data( deco146_addr, data, mem_mask, cs );
|
||||
m_deco146->write_data(deco146_addr, data, mem_mask, cs);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void lemmings_state::lemmings_map(address_map &map)
|
||||
void lemmings_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x0fffff).rom();
|
||||
map(0x100000, 0x10ffff).ram();
|
||||
map(0x120000, 0x1207ff).ram().share("spriteram1");
|
||||
map(0x140000, 0x1407ff).ram().share("spriteram2");
|
||||
map(0x160000, 0x160fff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
|
||||
map(0x170000, 0x17000f).ram().w(FUNC(lemmings_state::lemmings_control_w)).share("control_data");
|
||||
map(0x190000, 0x19000f).r(FUNC(lemmings_state::lemmings_trackball_r));
|
||||
map(0x1a0000, 0x1a3fff).rw(FUNC(lemmings_state::lem_protection_region_0_146_r), FUNC(lemmings_state::lem_protection_region_0_146_w)).share("prot16ram"); /* Protection device */
|
||||
map(0x1c0000, 0x1c0001).w(m_spriteram[0], FUNC(buffered_spriteram16_device::write)); /* 1 written once a frame */
|
||||
map(0x1e0000, 0x1e0001).w(m_spriteram[1], FUNC(buffered_spriteram16_device::write)); /* 1 written once a frame */
|
||||
map(0x200000, 0x201fff).ram().w(FUNC(lemmings_state::lemmings_vram_w)).share("vram_data");
|
||||
map(0x170000, 0x17000f).ram().w(FUNC(lemmings_state::control_w)).share(m_control_data);
|
||||
map(0x190000, 0x19000f).r(FUNC(lemmings_state::trackball_r));
|
||||
map(0x1a0000, 0x1a3fff).rw(FUNC(lemmings_state::protection_region_0_146_r), FUNC(lemmings_state::protection_region_0_146_w)).share("prot16ram"); // Protection device
|
||||
map(0x1c0000, 0x1c0001).w(m_spriteram[0], FUNC(buffered_spriteram16_device::write)); // 1 written once a frame
|
||||
map(0x1e0000, 0x1e0001).w(m_spriteram[1], FUNC(buffered_spriteram16_device::write)); // 1 written once a frame
|
||||
map(0x200000, 0x201fff).ram().w(FUNC(lemmings_state::vram_w)).share(m_vram_data);
|
||||
map(0x202000, 0x202fff).ram();
|
||||
map(0x300000, 0x37ffff).ram().w(FUNC(lemmings_state::lemmings_pixel_0_w)).share("pixel_0_data");
|
||||
map(0x380000, 0x39ffff).ram().w(FUNC(lemmings_state::lemmings_pixel_1_w)).share("pixel_1_data");
|
||||
map(0x300000, 0x37ffff).ram().w(FUNC(lemmings_state::pixel_0_w)).share(m_pixel_data[0]);
|
||||
map(0x380000, 0x39ffff).ram().w(FUNC(lemmings_state::pixel_1_w)).share(m_pixel_data[1]);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -202,28 +437,24 @@ static const gfx_layout sprite_layout =
|
||||
};
|
||||
|
||||
static GFXDECODE_START( gfx_lemmings )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, sprite_layout, 512, 16 ) /* Sprites 16x16 */
|
||||
GFXDECODE_ENTRY( "gfx2", 0, sprite_layout, 768, 16 ) /* Sprites 16x16 */
|
||||
GFXDECODE_ENTRY( nullptr,0, charlayout, 0, 16 ) /* Dynamically modified */
|
||||
GFXDECODE_ENTRY( "sprites1", 0, sprite_layout, 512, 16 ) // Sprites 16x16
|
||||
GFXDECODE_ENTRY( "sprites2", 0, sprite_layout, 768, 16 ) // Sprites 16x16
|
||||
GFXDECODE_ENTRY( nullptr, 0, charlayout, 0, 16 ) // Dynamically modified
|
||||
GFXDECODE_END
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void lemmings_state::machine_start()
|
||||
{
|
||||
}
|
||||
|
||||
void lemmings_state::lemmings(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
// basic machine hardware
|
||||
M68000(config, m_maincpu, 28_MHz_XTAL / 2); // Data East 59
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &lemmings_state::lemmings_map);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &lemmings_state::main_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(lemmings_state::irq6_line_hold));
|
||||
|
||||
MC6809E(config, m_audiocpu, 32.22_MHz_XTAL / 24); // MC68B09EP; clock not verified
|
||||
m_audiocpu->set_addrmap(AS_PROGRAM, &lemmings_state::sound_map);
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
BUFFERED_SPRITERAM16(config, m_spriteram[0]);
|
||||
BUFFERED_SPRITERAM16(config, m_spriteram[1]);
|
||||
|
||||
@ -232,8 +463,8 @@ void lemmings_state::lemmings(machine_config &config)
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(529));
|
||||
screen.set_size(40*8, 32*8);
|
||||
screen.set_visarea(0*8, 40*8-1, 2*8, 30*8-1);
|
||||
screen.set_screen_update(FUNC(lemmings_state::screen_update_lemmings));
|
||||
screen.screen_vblank().set(FUNC(lemmings_state::screen_vblank_lemmings));
|
||||
screen.set_screen_update(FUNC(lemmings_state::screen_update));
|
||||
screen.screen_vblank().set(FUNC(lemmings_state::screen_vblank));
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_lemmings);
|
||||
PALETTE(config, m_palette).set_format(palette_device::xBGR_888, 1024);
|
||||
@ -253,7 +484,7 @@ void lemmings_state::lemmings(machine_config &config)
|
||||
m_deco146->set_use_magic_read_address_xor(true);
|
||||
m_deco146->soundlatch_irq_cb().set_inputline(m_audiocpu, M6809_FIRQ_LINE);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
|
||||
@ -272,7 +503,7 @@ void lemmings_state::lemmings(machine_config &config)
|
||||
/******************************************************************************/
|
||||
|
||||
ROM_START( lemmings )
|
||||
ROM_REGION( 0x100000, "maincpu", 0 ) /* 68000 code */
|
||||
ROM_REGION( 0x100000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "lemmings.5", 0x00000, 0x20000, CRC(e9a2b439) SHA1(873723a06d71bb41772951f451a75578b30267d5) )
|
||||
ROM_LOAD16_BYTE( "lemmings.1", 0x00001, 0x20000, CRC(bf52293b) SHA1(47a1ed64bf02776db086fdce80997b8a0c068791) )
|
||||
ROM_LOAD16_BYTE( "lemmings.6", 0x40000, 0x20000, CRC(0e3dc0ea) SHA1(533abf66ca4b578d03566d5de922dc5828c26eca) )
|
||||
@ -282,23 +513,26 @@ ROM_START( lemmings )
|
||||
ROM_LOAD16_BYTE( "lemmings.8", 0xc0000, 0x20000, CRC(9166ce09) SHA1(7f0970cc07ebdbfc9a738342259d07d37b397161) )
|
||||
ROM_LOAD16_BYTE( "lemmings.4", 0xc0001, 0x20000, CRC(aa845488) SHA1(d17ec80f43d2a0123e93fad83d4e1319eb18d7c7) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 ) /* Sound CPU */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "lemmings.15", 0x00000, 0x10000, CRC(f0b24a35) SHA1(1aaeb1e6faee04d2e433161fd7aa965b58e3b8a7) )
|
||||
|
||||
ROM_REGION( 0x40000, "gfx1", ROMREGION_ERASE00 ) /* 3bpp data but sprite chip expects 4 */
|
||||
ROM_REGION( 0x40000, "sprites1", ROMREGION_ERASE00 ) // 3bpp data but sprite chip expects 4
|
||||
ROM_LOAD32_BYTE( "lemmings.9", 0x000003, 0x10000, CRC(e06442f5) SHA1(d9c8b681cce1d0257a0446bc820c7d679e2a1168) )
|
||||
ROM_LOAD32_BYTE( "lemmings.10", 0x000002, 0x10000, CRC(36398848) SHA1(6c6956607f889c35367e6df4a32359042fad695e) )
|
||||
ROM_LOAD32_BYTE( "lemmings.11", 0x000001, 0x10000, CRC(b46a54e5) SHA1(53b053346f80357aecff4ab888a8562f99cb318f) )
|
||||
|
||||
ROM_REGION( 0x40000, "gfx2", ROMREGION_ERASE00 ) /* 3bpp data but sprite chip expects 4 */
|
||||
ROM_REGION( 0x40000, "sprites2", ROMREGION_ERASE00 ) // 3bpp data but sprite chip expects 4
|
||||
ROM_LOAD32_BYTE( "lemmings.12", 0x000003, 0x10000, CRC(dc9047ff) SHA1(1bbe573fa51127a9e8b970a353f3cceab00f486a) )
|
||||
ROM_LOAD32_BYTE( "lemmings.13", 0x000002, 0x10000, CRC(7cc15491) SHA1(73c1c11b2738f6679c70cae8ac4c55cdc9b8fc27) )
|
||||
ROM_LOAD32_BYTE( "lemmings.14", 0x000001, 0x10000, CRC(c162788f) SHA1(e1f669efa59699cd1b7da71b112701ee79240c18) )
|
||||
|
||||
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM samples */
|
||||
ROM_REGION( 0x40000, "oki", 0 )
|
||||
ROM_LOAD( "lemmings.16", 0x00000, 0x20000, CRC(f747847c) SHA1(00880fa6dff979e5d15daea61938bd18c768c92f) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
GAME( 1991, lemmings, 0, lemmings, lemmings, lemmings_state, empty_init, ROT0, "Data East USA", "Lemmings (US prototype)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,73 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Bryan McPhail
|
||||
#include "video/bufsprite.h"
|
||||
#include "decospr.h"
|
||||
#include "deco146.h"
|
||||
#include "machine/gen_latch.h"
|
||||
#include "emupal.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class lemmings_state : public driver_device
|
||||
{
|
||||
public:
|
||||
lemmings_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_bitmap0(2048, 256)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_audiocpu(*this, "audiocpu")
|
||||
, m_deco146(*this, "ioprot")
|
||||
, m_spriteram(*this, "spriteram%u", 1)
|
||||
, m_sprgen(*this, "spritegen%u", 1)
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_palette(*this, "palette")
|
||||
, m_soundlatch(*this, "soundlatch")
|
||||
, m_control_data(*this, "control_data")
|
||||
, m_vram_data(*this, "vram_data")
|
||||
, m_pixel_data(*this, "pixel_%u_data", 0)
|
||||
, m_trackball_io(*this, "AN%u", 0)
|
||||
{
|
||||
}
|
||||
|
||||
void lemmings(machine_config &config);
|
||||
|
||||
private:
|
||||
/* video-related */
|
||||
bitmap_ind16 m_bitmap0{};
|
||||
tilemap_t *m_vram_tilemap = nullptr;
|
||||
std::unique_ptr<uint16_t[]> m_sprite_triple_buffer[2]{};
|
||||
std::unique_ptr<uint8_t[]> m_vram_buffer{};
|
||||
|
||||
/* devices */
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<deco146_device> m_deco146;
|
||||
required_device_array<buffered_spriteram16_device, 2> m_spriteram;
|
||||
required_device_array<decospr_device, 2> m_sprgen;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
|
||||
/* memory pointers */
|
||||
required_shared_ptr<uint16_t> m_control_data;
|
||||
required_shared_ptr<uint16_t> m_vram_data;
|
||||
required_shared_ptr_array<uint16_t, 2> m_pixel_data;
|
||||
|
||||
required_ioport_array<4> m_trackball_io;
|
||||
|
||||
void lemmings_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t lemmings_trackball_r(offs_t offset);
|
||||
void lemmings_pixel_0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void lemmings_pixel_1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void lemmings_vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
uint32_t screen_update_lemmings(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void screen_vblank_lemmings(int state);
|
||||
void lemmings_copy_bitmap(bitmap_rgb32& bitmap, int* xscroll, int* yscroll, const rectangle& cliprect);
|
||||
|
||||
uint16_t lem_protection_region_0_146_r(offs_t offset);
|
||||
void lem_protection_region_0_146_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void lemmings_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
@ -1,167 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Bryan McPhail
|
||||
/***************************************************************************
|
||||
|
||||
Lemmings video emulation - Bryan McPhail, mish@tendril.co.uk
|
||||
|
||||
*********************************************************************
|
||||
|
||||
There are two sets of sprites, the combination of custom chips 52 & 71.
|
||||
There is a background pixel layer implemented with discrete logic
|
||||
rather than a custom chip and a foreground VRAM tilemap layer that the
|
||||
game mostly uses as a pixel layer (the vram format is arranged as
|
||||
sequential pixels, rather than sequential characters).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "lemmings.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(lemmings_state::get_tile_info)
|
||||
{
|
||||
uint16_t tile = m_vram_data[tile_index];
|
||||
|
||||
tileinfo.set(2,
|
||||
tile&0x7ff,
|
||||
(tile>>12)&0xf,
|
||||
0);
|
||||
}
|
||||
|
||||
void lemmings_state::video_start()
|
||||
{
|
||||
m_vram_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lemmings_state::get_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 64, 32);
|
||||
|
||||
m_vram_tilemap->set_transparent_pen(0);
|
||||
m_bitmap0.fill(0x100);
|
||||
|
||||
m_vram_buffer = make_unique_clear<uint8_t[]>(2048 * 64); // 64 bytes per VRAM character
|
||||
m_gfxdecode->gfx(2)->set_source(m_vram_buffer.get());
|
||||
|
||||
m_sprgen[0]->alloc_sprite_bitmap();
|
||||
m_sprgen[1]->alloc_sprite_bitmap();
|
||||
|
||||
m_sprite_triple_buffer[0] = make_unique_clear<uint16_t[]>(0x800/2);
|
||||
m_sprite_triple_buffer[1] = make_unique_clear<uint16_t[]>(0x800/2);
|
||||
|
||||
save_item(NAME(m_bitmap0));
|
||||
save_pointer(NAME(m_vram_buffer), 2048 * 64);
|
||||
save_pointer(NAME(m_sprite_triple_buffer[0]), 0x800/2, 0);
|
||||
save_pointer(NAME(m_sprite_triple_buffer[1]), 0x800/2, 1);
|
||||
}
|
||||
|
||||
void lemmings_state::screen_vblank_lemmings(int state)
|
||||
{
|
||||
// rising edge
|
||||
if (state)
|
||||
{
|
||||
for (int chip = 0; chip < 2; chip++)
|
||||
std::copy_n(&m_spriteram[chip]->buffer()[0], 0x800/2, &m_sprite_triple_buffer[chip][0]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// RAM based
|
||||
void lemmings_state::lemmings_pixel_0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
int const old = m_pixel_data[0][offset];
|
||||
COMBINE_DATA(&m_pixel_data[0][offset]);
|
||||
int const src = m_pixel_data[0][offset];
|
||||
if (old == src)
|
||||
return;
|
||||
|
||||
int const sy = (offset << 1) >> 11;
|
||||
int const sx = (offset << 1) & 0x7ff;
|
||||
|
||||
if (sx > 2047 || sy > 255)
|
||||
return;
|
||||
|
||||
m_bitmap0.pix(sy, sx + 0) = ((src >> 8) & 0xf) | 0x100;
|
||||
m_bitmap0.pix(sy, sx + 1) = ((src >> 0) & 0xf) | 0x100;
|
||||
}
|
||||
|
||||
// RAM based tiles for the FG tilemap
|
||||
void lemmings_state::lemmings_pixel_1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
int sx, sy, src, tile;
|
||||
|
||||
COMBINE_DATA(&m_pixel_data[1][offset]);
|
||||
src = m_pixel_data[1][offset];
|
||||
|
||||
sy = (offset << 1) >> 9;
|
||||
sx = (offset << 1) & 0x1ff;
|
||||
|
||||
/* Copy pixel to buffer for easier decoding later */
|
||||
tile = ((sx / 8) * 32) + (sy / 8);
|
||||
m_gfxdecode->gfx(2)->mark_dirty(tile);
|
||||
m_vram_buffer[(tile * 64) + ((sx & 7)) + ((sy & 7) * 8)] = (src >> 8) & 0xf;
|
||||
|
||||
sx += 1; /* Update both pixels in the word */
|
||||
m_vram_buffer[(tile * 64) + ((sx & 7)) + ((sy & 7) * 8)] = (src >> 0) & 0xf;
|
||||
}
|
||||
|
||||
void lemmings_state::lemmings_vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_vram_data[offset]);
|
||||
m_vram_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
|
||||
void lemmings_state::lemmings_copy_bitmap(bitmap_rgb32& bitmap, int* xscroll, int* yscroll, const rectangle& cliprect)
|
||||
{
|
||||
pen_t const *const paldata = m_palette->pens();
|
||||
|
||||
for (int y=cliprect.top(); y<cliprect.bottom();y++)
|
||||
{
|
||||
uint32_t *const dst = &bitmap.pix(y,0);
|
||||
|
||||
for (int x=cliprect.left(); x<cliprect.right();x++)
|
||||
{
|
||||
uint16_t const src = m_bitmap0.pix((y-*yscroll)&0xff,(x-*xscroll)&0x7ff);
|
||||
|
||||
if (src!=0x100)
|
||||
dst[x] = paldata[src];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lemmings_state::screen_update_lemmings(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int x1 = -m_control_data[0];
|
||||
int x0 = -m_control_data[2];
|
||||
int y = 0;
|
||||
rectangle rect(0, 0, cliprect.top(), cliprect.bottom());
|
||||
|
||||
// sprites are flipped relative to tilemaps
|
||||
m_sprgen[0]->set_flip_screen(true);
|
||||
m_sprgen[1]->set_flip_screen(true);
|
||||
m_sprgen[0]->draw_sprites(bitmap, cliprect, m_sprite_triple_buffer[1].get(), 0x400);
|
||||
m_sprgen[1]->draw_sprites(bitmap, cliprect, m_sprite_triple_buffer[0].get(), 0x400);
|
||||
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
m_sprgen[0]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0800, 0x0800, 0x300, 0xff);
|
||||
|
||||
/* Pixel layer can be windowed in hardware (two player mode) */
|
||||
if ((m_control_data[6] & 2) == 0)
|
||||
{
|
||||
lemmings_copy_bitmap(bitmap, &x1, &y, cliprect);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.setx(0, 159);
|
||||
lemmings_copy_bitmap(bitmap, &x0, &y, rect);
|
||||
|
||||
rect.setx(160, 319);
|
||||
lemmings_copy_bitmap(bitmap, &x1, &y, rect);
|
||||
}
|
||||
|
||||
m_sprgen[1]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0800, 0x0800, 0x200, 0xff);
|
||||
m_sprgen[0]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0800, 0x300, 0xff);
|
||||
m_vram_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
m_sprgen[1]->inefficient_copy_sprite_bitmap(bitmap, cliprect, 0x0000, 0x0800, 0x200, 0xff);
|
||||
return 0;
|
||||
}
|
@ -887,7 +887,7 @@ maclc // 1990 Apple Macintosh LC
|
||||
maclc2 // 1991 Apple Macintosh LC II
|
||||
macclas2 // 1991 Apple Macintosh Classic II
|
||||
maccclas // 1993 Apple Macintosh Color Classic
|
||||
mactv // 1994 Apple Macintosh TV
|
||||
mactv // 1994 Apple Macintosh TV
|
||||
|
||||
@source:apple/maclc3.cpp
|
||||
maclc3 // 1993 Apple Macintosh LC III
|
||||
@ -37009,6 +37009,7 @@ taxi_l4 //
|
||||
taxi_lg1 //
|
||||
taxi_lu1 //
|
||||
taxi_p5 //
|
||||
tsptr_l1 //
|
||||
tsptr_l3 //
|
||||
whirl_l2 //
|
||||
whirl_l3 //
|
||||
|
@ -1563,6 +1563,28 @@ ROM_START(tsptr_l3)
|
||||
ROM_RELOAD(0x58000,0x8000)
|
||||
ROM_END
|
||||
|
||||
ROM_START(tsptr_l1)
|
||||
ROM_REGION(0x10000, "maincpu", 0)
|
||||
ROM_LOAD("transporter-la1-u26-checksumb412.l1", 0x4000, 0x4000, CRC(3504300f) SHA1(1a8b779b7375e4087e42b31c1aa17a8a32c6d6aa))
|
||||
ROM_LOAD("transporter-la1-u27-checksum01cf.l1", 0x8000, 0x8000, CRC(49635399) SHA1(8cdc700c501f0d611152010d5ae28bcd84d06861))
|
||||
ROM_REGION(0x10000, "audiocpu", ROMREGION_ERASEFF)
|
||||
ROM_LOAD("transporter-u21-checksumca54.l1", 0x8000, 0x8000, CRC(2b194ca6) SHA1(20cb956143622409a7f4b918ab1699db1b6e6b07))
|
||||
ROM_LOAD("transporter-u22-checksumd84c.l1", 0x0000, 0x8000, CRC(4c7ba6d7) SHA1(0134dce454c29c572c4ee0e0139a8ad5f0249b99))
|
||||
ROM_REGION(0x80000, "bg:cpu", ROMREGION_ERASEFF)
|
||||
ROM_LOAD("transporter-u4-checksum58b0.l1", 0x00000, 0x8000, CRC(63e92f8b) SHA1(57f2841419415fc3560d46a63119c76f98cade9b))
|
||||
ROM_RELOAD(0x08000,0x8000)
|
||||
ROM_RELOAD(0x10000,0x8000)
|
||||
ROM_RELOAD(0x18000,0x8000)
|
||||
ROM_LOAD("transporter-u19-checksumc7af.l1", 0x20000, 0x8000, CRC(3cfde8b0) SHA1(7bdc71ba1ba4fd337f052354323c86fd97b2b881)) // only common ROM with L3
|
||||
ROM_RELOAD(0x28000,0x8000)
|
||||
ROM_RELOAD(0x30000,0x8000)
|
||||
ROM_RELOAD(0x38000,0x8000)
|
||||
ROM_LOAD("transporter-u20-checksum21ae.l1", 0x40000, 0x8000, CRC(fabddaaf) SHA1(7c014bb5b1ac8da61ffd265ba98bcb8256c5f666))
|
||||
ROM_RELOAD(0x48000,0x8000)
|
||||
ROM_RELOAD(0x50000,0x8000)
|
||||
ROM_RELOAD(0x58000,0x8000)
|
||||
ROM_END
|
||||
|
||||
/*-----------------------
|
||||
/ Whirlwind 4/90 (#574)
|
||||
/-----------------------*/
|
||||
@ -1735,6 +1757,7 @@ GAME(1988, taxi_lu1, taxi_l4, s11b, s11b, s11b_state, init_s11bi7, R
|
||||
GAME(1988, taxi_lg1, taxi_l4, s11b, s11b, s11b_state, init_s11bi7, ROT0, "Williams", "Taxi (Marilyn) (L-1) Germany", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1988, taxi_p5, taxi_l4, s11b, s11b, s11b_state, init_s11bi7, ROT0, "Williams", "Taxi (P-5)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1989, tsptr_l3, 0, s11b, s11b, s11b_state, init_s11bin, ROT0, "Bally", "Transporter the Rescue (L-3)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1989, tsptr_l1, tsptr_l3, s11b, s11b, s11b_state, init_s11bin, ROT0, "Bally", "Transporter the Rescue (LA-1)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1990, whirl_l3, 0, s11b, s11b, s11b_state, init_s11bin, ROT0, "Williams", "Whirlwind (LA-3)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1990, whirl_l2, whirl_l3, s11b, s11b, s11b_state, init_s11bin, ROT0, "Williams", "Whirlwind (LU-2)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
GAME(1990, whirl_lg3, whirl_l3, s11b, s11b, s11b_state, init_s11bin, ROT0, "Williams", "Whirlwind (LG-3)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
|
Loading…
Reference in New Issue
Block a user