jaleco/citycon.cpp, meadows/lazercmd.cpp, meadows/meadows.cpp: consolidates drivers in single files

This commit is contained in:
Ivan Vangelista 2024-01-29 18:40:14 +01:00
parent 0e7986c58a
commit 63c77f65fb
10 changed files with 968 additions and 1093 deletions

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Mirko Buffoni
// copyright-holders: Mirko Buffoni
/***************************************************************************
City Connection (c) 1985 Jaleco
@ -10,50 +11,236 @@ Dip locations added from dip listing at crazykong.com
***************************************************************************/
#include "emu.h"
#include "citycon.h"
#include "cpu/m6809/m6809.h"
#include "machine/gen_latch.h"
#include "sound/ay8910.h"
#include "sound/ymopn.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "tilemap.h"
#define MASTER_CLOCK (20_MHz_XTAL)
#define PIXEL_CLOCK (MASTER_CLOCK/4) // guess
#define CPU_CLOCK (8_MHz_XTAL)
/* also a guess, need to extract PAL equations to get further answers */
#define HTOTAL (320)
#define HBEND (8)
#define HBSTART (248)
#define VTOTAL (262)
#define VBEND (16)
#define VBSTART (240)
namespace {
uint8_t citycon_state::citycon_in_r()
class citycon_state : public driver_device
{
return ioport(flip_screen() ? "P2" : "P1")->read();
public:
citycon_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_videoram(*this, "videoram"),
m_linecolor(*this, "linecolor"),
m_spriteram(*this, "spriteram"),
m_scroll(*this, "scroll"),
m_maincpu(*this, "maincpu"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_player(*this, "P%u", 1U)
{ }
void init_citycon();
void citycon(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_videoram;
required_shared_ptr<uint8_t> m_linecolor;
required_shared_ptr<uint8_t> m_spriteram;
required_shared_ptr<uint8_t> m_scroll;
required_device<cpu_device> m_maincpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_ioport_array<2> m_player;
// video-related
tilemap_t *m_bg_tilemap = nullptr;
tilemap_t *m_fg_tilemap = nullptr;
uint8_t m_bg_image = 0;
uint8_t in_r();
uint8_t irq_ack_r();
void videoram_w(offs_t offset, uint8_t data);
void background_w(uint8_t data);
TILEMAP_MAPPER_MEMBER(scan);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
inline void changecolor_RRRRGGGGBBBBxxxx(int color, int indx);
void main_map(address_map &map);
void sound_map(address_map &map);
};
// video
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
TILEMAP_MAPPER_MEMBER(citycon_state::scan)
{
// logical (col,row) -> memory offset
return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x60) << 5);
}
uint8_t citycon_state::citycon_irq_ack_r()
TILE_GET_INFO_MEMBER(citycon_state::get_fg_tile_info)
{
tileinfo.set(0,
m_videoram[tile_index],
(tile_index & 0x03e0) >> 5, // color depends on scanline only
0);
}
TILE_GET_INFO_MEMBER(citycon_state::get_bg_tile_info)
{
uint8_t *rom = memregion("bgtiles2")->base();
int const code = rom[0x1000 * m_bg_image + tile_index];
tileinfo.set(3 + m_bg_image,
code,
rom[0xc000 + 0x100 * m_bg_image + code],
0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void citycon_state::video_start()
{
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(citycon_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(citycon_state::scan)), 8, 8, 128, 32);
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(citycon_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(citycon_state::scan)), 8, 8, 128, 32);
m_fg_tilemap->set_transparent_pen(0);
m_fg_tilemap->set_scroll_rows(32);
}
/***************************************************************************
Memory handlers
***************************************************************************/
void citycon_state::videoram_w(offs_t offset, uint8_t data)
{
m_videoram[offset] = data;
m_fg_tilemap->mark_tile_dirty(offset);
}
void citycon_state::background_w(uint8_t data)
{
// bits 4-7 control the background image
if (m_bg_image != (data >> 4))
{
m_bg_image = (data >> 4);
m_bg_tilemap->mark_all_dirty();
}
// bit 0 flips screen
// it is also used to multiplex player 1 and player 2 controls
flip_screen_set(data & 0x01);
// bits 1-3 are unknown
// if ((data & 0x0e) != 0) logerror("background register = %02x\n", data);
}
void citycon_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
{
int sx = m_spriteram[offs + 3];
int sy = 239 - m_spriteram[offs];
int flipx = ~m_spriteram[offs + 2] & 0x10;
if (flip_screen())
{
sx = 240 - sx;
sy = 238 - sy;
flipx = !flipx;
}
m_gfxdecode->gfx(m_spriteram[offs + 1] & 0x80 ? 2 : 1)->transpen(bitmap, cliprect,
m_spriteram[offs + 1] & 0x7f,
m_spriteram[offs + 2] & 0x0f,
flipx, flip_screen(),
sx, sy, 0);
}
}
inline void citycon_state::changecolor_RRRRGGGGBBBBxxxx(int color, int indx)
{
int const data = m_palette->basemem().read8(2 * indx | 1) | (m_palette->basemem().read8(2 * indx) << 8);
m_palette->set_pen_color(color, pal4bit(data >> 12), pal4bit(data >> 8), pal4bit(data >> 4));
}
uint32_t citycon_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// Update the virtual palette to support text color code changing on every scanline.
for (int offs = 0; offs < 256; offs++)
{
int indx = m_linecolor[offs];
for (int i = 0; i < 4; i++)
changecolor_RRRRGGGGBBBBxxxx(640 + 4 * offs + i, 512 + 4 * indx + i);
}
int const scroll = m_scroll[0] * 256 + m_scroll[1];
m_bg_tilemap->set_scrollx(0, scroll >> 1);
for (int offs = 6; offs < 32; offs++)
m_fg_tilemap->set_scrollx(offs, scroll);
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, cliprect);
return 0;
}
// machine
uint8_t citycon_state::in_r()
{
return m_player[flip_screen()]->read();
}
uint8_t citycon_state::irq_ack_r()
{
m_maincpu->set_input_line(0, CLEAR_LINE);
return 0;
}
void citycon_state::citycon_map(address_map &map)
void citycon_state::main_map(address_map &map)
{
map(0x0000, 0x0fff).ram();
map(0x1000, 0x1fff).ram().w(FUNC(citycon_state::citycon_videoram_w)).share("videoram");
map(0x2000, 0x20ff).ram().w(FUNC(citycon_state::citycon_linecolor_w)).share("linecolor").mirror(0x0700);
map(0x2800, 0x28ff).ram().share("spriteram").mirror(0x0700); //0x2900-0x2fff cleared at post but unused
map(0x3000, 0x3000).r(FUNC(citycon_state::citycon_in_r)).w(FUNC(citycon_state::citycon_background_w)); /* player 1 & 2 inputs multiplexed */
map(0x1000, 0x1fff).ram().w(FUNC(citycon_state::videoram_w)).share(m_videoram);
map(0x2000, 0x20ff).ram().share(m_linecolor).mirror(0x0700);
map(0x2800, 0x28ff).ram().share(m_spriteram).mirror(0x0700); //0x2900-0x2fff cleared at post but unused
map(0x3000, 0x3000).r(FUNC(citycon_state::in_r)).w(FUNC(citycon_state::background_w)); // player 1 & 2 inputs multiplexed
map(0x3001, 0x3001).portr("DSW1").w("soundlatch", FUNC(generic_latch_8_device::write));
map(0x3002, 0x3002).portr("DSW2").w("soundlatch2", FUNC(generic_latch_8_device::write));
map(0x3004, 0x3005).nopr().writeonly().share("scroll");
map(0x3007, 0x3007).r(FUNC(citycon_state::citycon_irq_ack_r));
map(0x3004, 0x3005).nopr().writeonly().share(m_scroll);
map(0x3007, 0x3007).r(FUNC(citycon_state::irq_ack_r));
map(0x3800, 0x3cff).ram().w(m_palette, FUNC(palette_device::write8)).share("palette");
map(0x4000, 0xffff).rom();
}
@ -105,7 +292,7 @@ static INPUT_PORTS_START( citycon )
PORT_DIPNAME( 0x40, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW1:7")
PORT_DIPSETTING( 0x00, DEF_STR( Upright ) )
PORT_DIPSETTING( 0x40, DEF_STR( Cocktail ) )
/* the coin input must stay low for exactly 2 frames to be consistently recognized. */
// the coin input must stay low for exactly 2 frames to be consistently recognized.
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2)
PORT_START("DSW2")
@ -124,7 +311,7 @@ static INPUT_PORTS_START( citycon )
PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x00, "SW2:5" )
PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x00, "SW2:6" )
PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x00, "SW2:7" )
/* According to manual this is Flip Screen setting */
// According to manual this is Flip Screen setting
// PORT_DIPNAME( 0x80, 0x80, DEF_STR( Flip Screen ) ) PORT_DIPLOCATION("SW2:8")
// PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
// PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@ -146,45 +333,45 @@ static const gfx_layout charlayout =
static const gfx_layout tilelayout =
{
8,8, /* 8*8 characters */
256, /* 256 characters */
4, /* 4 bits per pixel */
8,8, // 8*8 characters
256, // 256 characters
4, // 4 bits per pixel */
{ 4, 0, 0xc000*8+4, 0xc000*8+0 },
{ 0, 1, 2, 3, 256*8*8+0, 256*8*8+1, 256*8*8+2, 256*8*8+3 },
{ 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 spritelayout =
{
8,16, /* 8*16 sprites */
128, /* 128 sprites */
4, /* 4 bits per pixel */
8,16, // 8*16 sprites
128, // 128 sprites
4, // 4 bits per pixel
{ 4, 0, 0x2000*8+4, 0x2000*8+0 },
{ 0, 1, 2, 3, 128*16*8+0, 128*16*8+1, 128*16*8+2, 128*16*8+3 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
16*8 /* every sprite takes 16 consecutive bytes */
16*8 // every sprite takes 16 consecutive bytes
};
static GFXDECODE_START( gfx_citycon )
// GFXDECODE_ENTRY( "gfx1", 0x00000, charlayout, 512, 32 ) /* colors 512-639 */
GFXDECODE_ENTRY( "gfx1", 0x00000, charlayout, 640, 32 ) /* colors 512-639 */
GFXDECODE_ENTRY( "gfx2", 0x00000, spritelayout, 0, 16 ) /* colors 0-255 */
GFXDECODE_ENTRY( "gfx2", 0x01000, spritelayout, 0, 16 )
GFXDECODE_ENTRY( "gfx3", 0x00000, tilelayout, 256, 16 ) /* colors 256-511 */
GFXDECODE_ENTRY( "gfx3", 0x01000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x02000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x03000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x04000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x05000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x06000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x07000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x08000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x09000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x0a000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "gfx3", 0x0b000, tilelayout, 256, 16 )
// GFXDECODE_ENTRY( "chars", 0x00000, charlayout, 512, 32 ) // colors 512-639
GFXDECODE_ENTRY( "chars", 0x00000, charlayout, 640, 32 ) // colors 512-639
GFXDECODE_ENTRY( "sprites", 0x00000, spritelayout, 0, 16 ) // colors 0-255
GFXDECODE_ENTRY( "sprites", 0x01000, spritelayout, 0, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x00000, tilelayout, 256, 16 ) // colors 256-511
GFXDECODE_ENTRY( "bgtiles1", 0x01000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x02000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x03000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x04000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x05000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x06000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x07000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x08000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x09000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x0a000, tilelayout, 256, 16 )
GFXDECODE_ENTRY( "bgtiles1", 0x0b000, tilelayout, 256, 16 )
GFXDECODE_END
void citycon_state::machine_start()
@ -200,25 +387,37 @@ void citycon_state::machine_reset()
void citycon_state::citycon(machine_config &config)
{
/* basic machine hardware */
constexpr XTAL MASTER_CLOCK = 20_MHz_XTAL;
constexpr XTAL PIXEL_CLOCK = MASTER_CLOCK / 4; // guess
constexpr XTAL CPU_CLOCK = 8_MHz_XTAL;
// also a guess, need to extract PAL equations to get further answers
constexpr int HTOTAL = 320;
constexpr int HBEND = 8;
constexpr int HBSTART = 248;
constexpr int VTOTAL = 262;
constexpr int VBEND = 16;
constexpr int VBSTART = 240;
// basic machine hardware
MC6809(config, m_maincpu, CPU_CLOCK); // HD68B09P
m_maincpu->set_addrmap(AS_PROGRAM, &citycon_state::citycon_map);
m_maincpu->set_addrmap(AS_PROGRAM, &citycon_state::main_map);
m_maincpu->set_vblank_int("screen", FUNC(citycon_state::irq0_line_assert));
mc6809e_device &audiocpu(MC6809E(config, "audiocpu", MASTER_CLOCK / 32)); // schematics allow for either a 6809 or 6809E; HD68A09EP found on one actual PCB
audiocpu.set_addrmap(AS_PROGRAM, &citycon_state::sound_map);
audiocpu.set_vblank_int("screen", FUNC(citycon_state::irq0_line_hold)); // actually unused, probably it was during development
/* video hardware */
// video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART);
screen.set_screen_update(FUNC(citycon_state::screen_update_citycon));
screen.set_screen_update(FUNC(citycon_state::screen_update));
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_citycon);
PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::RGBx_444, 640+1024); // 640 real palette + 1024 virtual palette
/* sound hardware */
// sound hardware
SPEAKER(config, "mono").front_center();
GENERIC_LATCH_8(config, "soundlatch");
@ -251,23 +450,23 @@ ROM_START( citycon )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "c1", 0x8000, 0x8000, CRC(1fad7589) SHA1(2e626bbbab8cffe11ee7de3e56aa1871c29d5fa9) )
ROM_REGION( 0x03000, "gfx1", 0 )
ROM_LOAD( "c4", 0x00000, 0x2000, CRC(a6b32fc6) SHA1(d99d5a527440e9a91525c1084b95b213e3b760ec) ) /* Characters */
ROM_REGION( 0x03000, "chars", 0 )
ROM_LOAD( "c4", 0x00000, 0x2000, CRC(a6b32fc6) SHA1(d99d5a527440e9a91525c1084b95b213e3b760ec) )
ROM_REGION( 0x04000, "gfx2", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) ) /* Sprites */
ROM_REGION( 0x04000, "sprites", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) )
ROM_LOAD( "c13", 0x02000, 0x2000, CRC(1819aafb) SHA1(8a5ffcd8866e09c5568879257384767d61796111) )
ROM_REGION( 0x18000, "gfx3", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) ) /* Background tiles */
ROM_REGION( 0x18000, "bgtiles1", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) )
ROM_LOAD( "c8", 0x08000, 0x4000, CRC(0d7a1eeb) SHA1(60b8d4124ce857a248d3c41fdb050f11be58549f) )
ROM_LOAD( "c6", 0x0c000, 0x8000, CRC(2246fe9d) SHA1(f7f8708d499bcbd1a583e1092b54425ad1105f94) )
ROM_LOAD( "c7", 0x14000, 0x4000, CRC(e8b97de9) SHA1(f4d1b7075f47ab4522c36281b97eaa02fe383814) )
ROM_REGION( 0xe000, "gfx4", 0 ) /* background tilemaps */
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) /* background maps */
ROM_REGION( 0xe000, "bgtiles2", 0 )
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) // background maps
ROM_LOAD( "c3", 0x8000, 0x4000, CRC(7ef3ac1b) SHA1(8a0497c4e4733f9c50d576f632210b82497a5e1c) )
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) /* color codes for the background */
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) // color codes for the background
ROM_END
ROM_START( citycona )
@ -278,25 +477,25 @@ ROM_START( citycona )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "c1", 0x8000, 0x8000, CRC(1fad7589) SHA1(2e626bbbab8cffe11ee7de3e56aa1871c29d5fa9) )
ROM_REGION( 0x03000, "gfx1", 0 )
ROM_LOAD( "c4", 0x00000, 0x2000, CRC(a6b32fc6) SHA1(d99d5a527440e9a91525c1084b95b213e3b760ec) ) /* Characters */
ROM_REGION( 0x03000, "chars", 0 )
ROM_LOAD( "c4", 0x00000, 0x2000, CRC(a6b32fc6) SHA1(d99d5a527440e9a91525c1084b95b213e3b760ec) )
ROM_REGION( 0x04000, "gfx2", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) ) /* Sprites */
ROM_REGION( 0x04000, "sprites", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) )
ROM_LOAD( "c13", 0x02000, 0x2000, CRC(1819aafb) SHA1(8a5ffcd8866e09c5568879257384767d61796111) )
ROM_REGION( 0x18000, "gfx3", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) ) /* Background tiles */
ROM_REGION( 0x18000, "bgtiles1", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) )
ROM_LOAD( "c8", 0x08000, 0x4000, CRC(0d7a1eeb) SHA1(60b8d4124ce857a248d3c41fdb050f11be58549f) )
ROM_LOAD( "c6", 0x0c000, 0x8000, CRC(2246fe9d) SHA1(f7f8708d499bcbd1a583e1092b54425ad1105f94) )
ROM_LOAD( "c7", 0x14000, 0x4000, CRC(e8b97de9) SHA1(f4d1b7075f47ab4522c36281b97eaa02fe383814) )
ROM_REGION( 0xe000, "gfx4", 0 ) /* background tilemaps */
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) /* background maps */
ROM_REGION( 0xe000, "bgtiles2", 0 )
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) // background maps
ROM_LOAD( "c3", 0x8000, 0x4000, CRC(7ef3ac1b) SHA1(8a0497c4e4733f9c50d576f632210b82497a5e1c) )
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) /* color codes for the background */
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) // color codes for the background
/* stuff below isn't used but loaded because it was on the board .. */
// stuff below isn't used but loaded because it was on the board ..
ROM_REGION( 0x0600, "proms", 0 )
ROM_LOAD( "citycon_82s123n.n5", 0x0000, 0x0020, CRC(5ae142a3) SHA1(ba25c9bcbc4936a6b7f402addab50b75dbe519ce) )
ROM_LOAD( "citycon_82s123n.r4", 0x0100, 0x0020, CRC(29221e13) SHA1(232fd02811f157197c7ce44716dc495ed49a80cc) )
@ -319,30 +518,30 @@ ROM_START( cruisin )
ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "c1", 0x8000, 0x8000, CRC(1fad7589) SHA1(2e626bbbab8cffe11ee7de3e56aa1871c29d5fa9) )
ROM_REGION( 0x03000, "gfx1", 0 )
ROM_LOAD( "cr4", 0x00000, 0x2000, CRC(8cd0308e) SHA1(7303b9e074bda557d64b39e04cef0f965a756be6) ) /* Characters */
ROM_REGION( 0x03000, "chars", 0 )
ROM_LOAD( "cr4", 0x00000, 0x2000, CRC(8cd0308e) SHA1(7303b9e074bda557d64b39e04cef0f965a756be6) )
ROM_REGION( 0x04000, "gfx2", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) ) /* Sprites */
ROM_REGION( 0x04000, "sprites", 0 )
ROM_LOAD( "c12", 0x00000, 0x2000, CRC(08eaaccd) SHA1(a970381e3ba22bcdea6df2d31cd8a10c4b2bc413) )
ROM_LOAD( "c13", 0x02000, 0x2000, CRC(1819aafb) SHA1(8a5ffcd8866e09c5568879257384767d61796111) )
ROM_REGION( 0x18000, "gfx3", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) ) /* Background tiles */
ROM_REGION( 0x18000, "bgtiles1", 0 )
ROM_LOAD( "c9", 0x00000, 0x8000, CRC(8aeb47e6) SHA1(bb09dbe6b37e1bd02abf3024ac4d954c8f0e70f2) )
ROM_LOAD( "c8", 0x08000, 0x4000, CRC(0d7a1eeb) SHA1(60b8d4124ce857a248d3c41fdb050f11be58549f) )
ROM_LOAD( "c6", 0x0c000, 0x8000, CRC(2246fe9d) SHA1(f7f8708d499bcbd1a583e1092b54425ad1105f94) )
ROM_LOAD( "c7", 0x14000, 0x4000, CRC(e8b97de9) SHA1(f4d1b7075f47ab4522c36281b97eaa02fe383814) )
ROM_REGION( 0xe000, "gfx4", 0 ) /* background tilemaps */
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) /* background maps */
ROM_REGION( 0xe000, "bgtiles2", 0 )
ROM_LOAD( "c2", 0x0000, 0x8000, CRC(f2da4f23) SHA1(5ea1a51c3ac283796f7eafb6719d88356767340d) ) // background maps
ROM_LOAD( "c3", 0x8000, 0x4000, CRC(7ef3ac1b) SHA1(8a0497c4e4733f9c50d576f632210b82497a5e1c) )
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) /* color codes for the background */
ROM_LOAD( "c5", 0xc000, 0x2000, CRC(c03d8b1b) SHA1(641c1eba334d36ea64b9293a20320b31c7c88858) ) // color codes for the background
ROM_END
void citycon_state::init_citycon()
{
uint8_t *rom = memregion("gfx1")->base();
uint8_t *rom = memregion("chars")->base();
/*
City Connection controls the text color code for each _scanline_, not
@ -362,8 +561,9 @@ void citycon_state::init_citycon()
}
}
} // anonymous namespace
GAME( 1985, citycon, 0, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco", "City Connection (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, citycona, citycon, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco", "City Connection (set 2)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, cruisin, citycon, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco (Kitkorp license)", "Cruisin", MACHINE_SUPPORTS_SAVE )
GAME( 1985, citycon, 0, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco", "City Connection (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, citycona, citycon, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco", "City Connection (set 2)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, cruisin, citycon, citycon, citycon, citycon_state, init_citycon, ROT0, "Jaleco (Kitkorp license)", "Cruisin", MACHINE_SUPPORTS_SAVE )

View File

@ -1,68 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mirko Buffoni
/*************************************************************************
City Connection
*************************************************************************/
#ifndef MAME_JALECO_CITYCON_H
#define MAME_JALECO_CITYCON_H
#pragma once
#include "emupal.h"
#include "tilemap.h"
class citycon_state : public driver_device
{
public:
citycon_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_videoram(*this, "videoram"),
m_linecolor(*this, "linecolor"),
m_spriteram(*this, "spriteram"),
m_scroll(*this, "scroll"),
m_maincpu(*this, "maincpu"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
{ }
void init_citycon();
void citycon(machine_config &config);
private:
/* memory pointers */
required_shared_ptr<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_linecolor;
required_shared_ptr<uint8_t> m_spriteram;
required_shared_ptr<uint8_t> m_scroll;
/* video-related */
tilemap_t *m_bg_tilemap = nullptr;
tilemap_t *m_fg_tilemap = nullptr;
int m_bg_image = 0;
/* devices */
required_device<cpu_device> m_maincpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
uint8_t citycon_in_r();
uint8_t citycon_irq_ack_r();
void citycon_videoram_w(offs_t offset, uint8_t data);
void citycon_linecolor_w(offs_t offset, uint8_t data);
void citycon_background_w(uint8_t data);
TILEMAP_MAPPER_MEMBER(citycon_scan);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update_citycon(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect );
inline void changecolor_RRRRGGGGBBBBxxxx( int color, int indx );
void citycon_map(address_map &map);
void sound_map(address_map &map);
};
#endif // MAME_JALECO_CITYCON_H

View File

@ -1,159 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mirko Buffoni
/***************************************************************************
video.c
Functions to emulate the video hardware of the machine.
***************************************************************************/
#include "emu.h"
#include "citycon.h"
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
TILEMAP_MAPPER_MEMBER(citycon_state::citycon_scan)
{
/* logical (col,row) -> memory offset */
return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x60) << 5);
}
TILE_GET_INFO_MEMBER(citycon_state::get_fg_tile_info)
{
tileinfo.set(0,
m_videoram[tile_index],
(tile_index & 0x03e0) >> 5, /* color depends on scanline only */
0);
}
TILE_GET_INFO_MEMBER(citycon_state::get_bg_tile_info)
{
uint8_t *rom = memregion("gfx4")->base();
int code = rom[0x1000 * m_bg_image + tile_index];
tileinfo.set(3 + m_bg_image,
code,
rom[0xc000 + 0x100 * m_bg_image + code],
0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void citycon_state::video_start()
{
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(citycon_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(citycon_state::citycon_scan)), 8, 8, 128, 32);
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(citycon_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(citycon_state::citycon_scan)), 8, 8, 128, 32);
m_fg_tilemap->set_transparent_pen(0);
m_fg_tilemap->set_scroll_rows(32);
}
/***************************************************************************
Memory handlers
***************************************************************************/
void citycon_state::citycon_videoram_w(offs_t offset, uint8_t data)
{
m_videoram[offset] = data;
m_fg_tilemap->mark_tile_dirty(offset);
}
void citycon_state::citycon_linecolor_w(offs_t offset, uint8_t data)
{
m_linecolor[offset] = data;
}
void citycon_state::citycon_background_w(uint8_t data)
{
/* bits 4-7 control the background image */
if (m_bg_image != (data >> 4))
{
m_bg_image = (data >> 4);
m_bg_tilemap->mark_all_dirty();
}
/* bit 0 flips screen */
/* it is also used to multiplex player 1 and player 2 controls */
flip_screen_set(data & 0x01);
/* bits 1-3 are unknown */
// if ((data & 0x0e) != 0) logerror("background register = %02x\n", data);
}
void citycon_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
{
int offs;
for (offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
{
int sx, sy, flipx;
sx = m_spriteram[offs + 3];
sy = 239 - m_spriteram[offs];
flipx = ~m_spriteram[offs + 2] & 0x10;
if (flip_screen())
{
sx = 240 - sx;
sy = 238 - sy;
flipx = !flipx;
}
m_gfxdecode->gfx(m_spriteram[offs + 1] & 0x80 ? 2 : 1)->transpen(bitmap,cliprect,
m_spriteram[offs + 1] & 0x7f,
m_spriteram[offs + 2] & 0x0f,
flipx,flip_screen(),
sx, sy, 0);
}
}
inline void citycon_state::changecolor_RRRRGGGGBBBBxxxx( int color, int indx )
{
int data = m_palette->basemem().read8(2 * indx | 1) | (m_palette->basemem().read8(2 * indx) << 8);
m_palette->set_pen_color(color, pal4bit(data >> 12), pal4bit(data >> 8), pal4bit(data >> 4));
}
uint32_t citycon_state::screen_update_citycon(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int offs, scroll;
/* Update the virtual palette to support text color code changing on every scanline. */
for (offs = 0; offs < 256; offs++)
{
int indx = m_linecolor[offs];
int i;
for (i = 0; i < 4; i++)
changecolor_RRRRGGGGBBBBxxxx(640 + 4 * offs + i, 512 + 4 * indx + i);
}
scroll = m_scroll[0] * 256 + m_scroll[1];
m_bg_tilemap->set_scrollx(0, scroll >> 1);
for (offs = 6; offs < 32; offs++)
m_fg_tilemap->set_scrollx(offs, scroll);
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, cliprect);
return 0;
}

View File

@ -1,5 +1,6 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
// copyright-holders: Juergen Buchmueller
/***************************************************************************
Lazer Command memory map (preliminary)
@ -234,7 +235,12 @@
***************************************************************************/
#include "emu.h"
#include "lazercmd.h"
#include "cpu/s2650/s2650.h"
#include "machine/timer.h"
#include "sound/dac.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
@ -242,10 +248,157 @@
#include "lazercmd.lh"
#include "medlanes.lh"
#define MASTER_CLOCK XTAL(8'000'000)
namespace {
class lazercmd_state : public driver_device
{
public:
lazercmd_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_dac(*this, "dac%u", 0U),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_videoram(*this, "videoram"),
m_in(*this, "IN%u", 0U),
m_dsw(*this, "DSW")
{ }
void bbonk(machine_config &config);
void medlanes(machine_config &config);
void lazercmd(machine_config &config);
void init_lazercmd();
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
required_device<s2650_device> m_maincpu;
optional_device_array<dac_bit_interface, 4> m_dac;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_shared_ptr<uint8_t> m_videoram;
required_ioport_array<4> m_in;
required_ioport m_dsw;
// video-related
static constexpr uint8_t HORZ_RES = 32;
static constexpr uint8_t VERT_RES = 24;
static constexpr uint8_t HORZ_CHR = 8;
static constexpr uint8_t VERT_CHR = 10;
static constexpr uint8_t VERT_FNT = 8;
uint8_t m_marker_x = 0U;
uint8_t m_marker_y = 0U;
// misc
uint16_t m_timer_count = 0U;
uint8_t m_sense_state = 0U;
uint8_t m_attract = 0U;
void ctrl_port_w(uint8_t data);
uint8_t ctrl_port_r();
void data_port_w(uint8_t data);
uint8_t data_port_r();
void lazercmd_hardware_w(offs_t offset, uint8_t data);
void medlanes_hardware_w(offs_t offset, uint8_t data);
void bbonk_hardware_w(offs_t offset, uint8_t data);
uint8_t hardware_r(offs_t offset);
void palette(palette_device &palette) const;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(lazercmd_timer);
TIMER_DEVICE_CALLBACK_MEMBER(bbonk_timer);
int vert_scale(int data);
void plot_pattern(bitmap_ind16 &bitmap, int x, int y);
void bbonk_map(address_map &map);
void lazercmd_map(address_map &map);
void medlanes_map(address_map &map);
void portmap(address_map &map);
};
// video
/* scale a marker's vertical position
the following table shows how the marker's
vertical position worked in hardware
marker_y lines marker_y lines
0 0 + 1 8 10 + 11
1 2 + 3 9 12 + 13
2 4 + 5 10 14 + 15
3 6 + 7 11 16 + 17
4 8 + 9 12 18 + 19 */
int lazercmd_state::vert_scale(int data)
{
return ((data & 0x07) << 1) + ((data & 0xf8) >> 3) * VERT_CHR;
}
/* plot a bitmap marker
hardware has 2 marker sizes (2x2 and 4x2) selected by jumper
Meadows Lanes normally uses 2x2 pixels and Lazer Command uses either */
void lazercmd_state::plot_pattern(bitmap_ind16 &bitmap, int x, int y)
{
int size = 2;
if (m_dsw->read() & 0x40)
{
size = 4;
}
for (int ybit = 0; ybit < 2; ybit++)
{
if (y + ybit < 0 || y + ybit >= VERT_RES * VERT_CHR)
return;
for (int xbit = 0; xbit < size; xbit++)
{
if (x + xbit < 0 || x + xbit >= HORZ_RES * HORZ_CHR)
continue;
bitmap.pix(y + ybit, x + xbit) = 4;
}
}
}
uint32_t lazercmd_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int const video_inverted = (m_dsw->read() ^ m_attract) & 0x20;
// The first row of characters are invisible
for (int i = 0; i < (VERT_RES - 1) * HORZ_RES; i++)
{
int sx = i % HORZ_RES;
int sy = i / HORZ_RES;
sx *= HORZ_CHR;
sy *= VERT_CHR;
m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
m_videoram[i], video_inverted ? 1 : 0,
0, 0,
sx, sy);
}
int const x = m_marker_x - 1; // normal video lags marker by 1 pixel
int const y = vert_scale(m_marker_y) - VERT_CHR; // first line used as scratch pad
plot_pattern(bitmap, x, y);
return 0;
}
// machine
/*************************************************************
* Interrupt for the cpu
* Interrupt for the CPU
* Fake something toggling the sense input line of the S2650
* The rate should be at about 1 Hz
*************************************************************/
@ -282,27 +435,27 @@ TIMER_DEVICE_CALLBACK_MEMBER(lazercmd_state::bbonk_timer)
*
*************************************************************/
/* triggered by WRTC,r opcode */
void lazercmd_state::lazercmd_ctrl_port_w(uint8_t data)
// triggered by WRTC,r opcode
void lazercmd_state::ctrl_port_w(uint8_t data)
{
}
/* triggered by REDC,r opcode */
uint8_t lazercmd_state::lazercmd_ctrl_port_r()
// triggered by REDC,r opcode
uint8_t lazercmd_state::ctrl_port_r()
{
uint8_t data = 0;
return data;
}
/* triggered by WRTD,r opcode */
void lazercmd_state::lazercmd_data_port_w(uint8_t data)
// triggered by WRTD,r opcode
void lazercmd_state::data_port_w(uint8_t data)
{
}
/* triggered by REDD,r opcode */
uint8_t lazercmd_state::lazercmd_data_port_r()
// triggered by REDD,r opcode
uint8_t lazercmd_state::data_port_r()
{
uint8_t data = ioport("DSW")->read() & 0x0f;
uint8_t data = m_dsw->read() & 0x0f;
return data;
}
@ -310,19 +463,19 @@ void lazercmd_state::lazercmd_hardware_w(offs_t offset, uint8_t data)
{
switch (offset)
{
case 0: /* audio channels */
m_dac0->write(BIT(data, 7));
m_dac1->write(BIT(data, 6));
m_dac2->write(BIT(data, 5));
m_dac3->write(BIT(data, 4));
case 0: // audio channels
m_dac[0]->write(BIT(data, 7));
m_dac[1]->write(BIT(data, 6));
m_dac[2]->write(BIT(data, 5));
m_dac[3]->write(BIT(data, 4));
break;
case 1: /* marker Y position */
case 1: // marker Y position
m_marker_y = data;
break;
case 2: /* marker X position */
case 2: // marker X position
m_marker_x = data;
break;
case 3: /* D4 clears coin detected and D0 toggles on attract mode */
case 3: // D4 clears coin detected and D0 toggles on attract mode
m_attract = data;
break;
}
@ -332,20 +485,20 @@ void lazercmd_state::medlanes_hardware_w(offs_t offset, uint8_t data)
{
switch (offset)
{
case 0: /* audio control */
/* bits 4 and 5 are used to control a sound board */
/* these could be used to control sound samples */
/* at the moment they are routed through the dac */
m_dac2->write(BIT(data, 5));
m_dac3->write(BIT(data, 4));
case 0: // audio control
/* bits 4 and 5 are used to control a sound board
these could be used to control sound samples
at the moment they are routed through the DAC */
m_dac[2]->write(BIT(data, 5));
m_dac[3]->write(BIT(data, 4));
break;
case 1: /* marker Y position */
case 1: // marker Y position
m_marker_y = data;
break;
case 2: /* marker X position */
case 2: // marker X position
m_marker_x = data;
break;
case 3: /* D4 clears coin detected and D0 toggles on attract mode */
case 3: // D4 clears coin detected and D0 toggles on attract mode
m_attract = data;
break;
}
@ -355,47 +508,47 @@ void lazercmd_state::bbonk_hardware_w(offs_t offset, uint8_t data)
{
switch (offset)
{
case 0: /* audio control */
/* bits 4 and 5 are used to control a sound board */
/* these could be used to control sound samples */
/* at the moment they are routed through the dac */
m_dac2->write(BIT(data, 5));
m_dac3->write(BIT(data, 4));
case 0: // audio control
/* bits 4 and 5 are used to control a sound board
these could be used to control sound samples
at the moment they are routed through the DAC */
m_dac[2]->write(BIT(data, 5));
m_dac[3]->write(BIT(data, 4));
break;
case 3: /* D5 inverts video?, D4 clears coin detected and D0 toggles on attract mode */
case 3: // D5 inverts video?, D4 clears coin detected and D0 toggles on attract mode
m_attract = data;
break;
}
}
uint8_t lazercmd_state::lazercmd_hardware_r(offs_t offset)
uint8_t lazercmd_state::hardware_r(offs_t offset)
{
uint8_t data = 0;
switch (offset)
{
case 0: /* player 1 joysticks */
data = ioport("IN0")->read();
case 0: // player 1 joysticks
data = m_in[0]->read();
break;
case 1: /* player 2 joysticks */
data = ioport("IN1")->read();
case 1: // player 2 joysticks
data = m_in[1]->read();
break;
case 2: /* player 1 + 2 buttons */
data = ioport("IN3")->read();
case 2: // player 1 + 2 buttons
data = m_in[3]->read();
break;
case 3: /* coin slot + start buttons */
data = ioport("IN2")->read();
case 3: // coin slot + start buttons
data = m_in[2]->read();
break;
case 4: /* vertical scan counter */
case 4: // vertical scan counter
data = ((m_timer_count & 0x10) >> 1) | ((m_timer_count & 0x20) >> 3) | ((m_timer_count & 0x40) >> 5) | ((m_timer_count & 0x80) >> 7);
break;
case 5: /* vertical scan counter */
case 5: // vertical scan counter
data = m_timer_count & 0x0f;
break;
case 6: /* 1f02 readback */
case 6: // 1f02 readback
data = m_marker_x;
break;
case 7: /* 1f01 readback */
case 7: // 1f01 readback
data = m_marker_y;
break;
}
@ -413,37 +566,33 @@ void lazercmd_state::lazercmd_map(address_map &map)
{
map(0x0000, 0x0bff).rom();
map(0x1c00, 0x1c1f).ram();
map(0x1c20, 0x1eff).ram().share("videoram");
map(0x1c20, 0x1eff).ram().share(m_videoram);
map(0x1f00, 0x1f03).w(FUNC(lazercmd_state::lazercmd_hardware_w));
map(0x1f00, 0x1f07).r(FUNC(lazercmd_state::lazercmd_hardware_r));
map(0x1f00, 0x1f07).r(FUNC(lazercmd_state::hardware_r));
}
void lazercmd_state::medlanes_map(address_map &map)
{
map(0x0000, 0x0bff).rom();
lazercmd_map(map);
map(0x1000, 0x17ff).rom();
map(0x1c00, 0x1c1f).ram();
map(0x1c20, 0x1eff).ram().share("videoram");
map(0x1f00, 0x1f03).w(FUNC(lazercmd_state::medlanes_hardware_w));
map(0x1f00, 0x1f07).r(FUNC(lazercmd_state::lazercmd_hardware_r));
}
void lazercmd_state::bbonk_map(address_map &map)
{
map(0x0000, 0x0bff).rom();
map(0x1c00, 0x1c1f).ram();
map(0x1c20, 0x1eff).ram().share("videoram");
lazercmd_map(map);
map(0x1f00, 0x1f03).w(FUNC(lazercmd_state::bbonk_hardware_w));
map(0x1f00, 0x1f07).r(FUNC(lazercmd_state::lazercmd_hardware_r));
}
void lazercmd_state::lazercmd_portmap(address_map &map)
void lazercmd_state::portmap(address_map &map)
{
map(S2650_CTRL_PORT, S2650_CTRL_PORT).rw(FUNC(lazercmd_state::lazercmd_ctrl_port_r), FUNC(lazercmd_state::lazercmd_ctrl_port_w));
map(S2650_DATA_PORT, S2650_DATA_PORT).rw(FUNC(lazercmd_state::lazercmd_data_port_r), FUNC(lazercmd_state::lazercmd_data_port_w));
map(S2650_CTRL_PORT, S2650_CTRL_PORT).rw(FUNC(lazercmd_state::ctrl_port_r), FUNC(lazercmd_state::ctrl_port_w));
map(S2650_DATA_PORT, S2650_DATA_PORT).rw(FUNC(lazercmd_state::data_port_r), FUNC(lazercmd_state::data_port_w));
}
@ -514,7 +663,7 @@ static INPUT_PORTS_START( medlanes )
PORT_DIPSETTING( 0x01, "3 seconds" )
PORT_DIPSETTING( 0x03, "5 seconds" )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
// PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) // dupe
PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) // dupe
PORT_BIT( 0x9C, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_DIPNAME( 0x20, 0x00, "Video Invert" )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
@ -581,20 +730,20 @@ INPUT_PORTS_END
static const gfx_layout charlayout =
{
8, 10, /* 8*10 characters */
4*64, /* 4 * 64 characters */
1, /* 1 bit per pixel */
{ 0 }, /* no bitplanes */
8, 10, // 8*10 characters
4*64, // 4 * 64 characters
1, // 1 bit per pixel
{ 0 }, // no bitplanes
{ 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, 9*8 },
10*8 /* every char takes 10 bytes */
10*8 // every char takes 10 bytes
};
static GFXDECODE_START( gfx_lazercmd )
GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 2 )
GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 2 )
GFXDECODE_END
void lazercmd_state::lazercmd_palette(palette_device &palette) const
void lazercmd_state::palette(palette_device &palette) const
{
palette.set_pen_color(0, rgb_t(0xb0, 0xb0, 0xb0)); // white
palette.set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // black
@ -625,98 +774,59 @@ void lazercmd_state::machine_reset()
}
void lazercmd_state::lazercmd(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/12); /* 666 kHz? */
/* Main Clock is 8MHz divided by 12
but memory and IO access is only possible
within the line and frame blanking period
thus requiring an extra loading of approx 3-5 */
m_maincpu->set_addrmap(AS_PROGRAM, &lazercmd_state::lazercmd_map);
m_maincpu->set_addrmap(AS_DATA, &lazercmd_state::lazercmd_portmap);
TIMER(config, "scantimer").configure_scanline(FUNC(lazercmd_state::lazercmd_timer), "screen", 0, 1);
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
screen.set_size(HORZ_RES * HORZ_CHR, VERT_RES * VERT_CHR + 16);
screen.set_visarea(0 * HORZ_CHR, HORZ_RES * HORZ_CHR - 1, 0 * VERT_CHR, (VERT_RES - 1) * VERT_CHR - 1);
screen.set_screen_update(FUNC(lazercmd_state::screen_update_lazercmd));
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_lazercmd);
PALETTE(config, m_palette, FUNC(lazercmd_state::lazercmd_palette), 5);
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac0, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac1, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac2, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac3, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
}
void lazercmd_state::medlanes(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/12); /* 666 kHz */
// basic machine hardware
S2650(config, m_maincpu, 8_MHz_XTAL / 12); // 666 kHz
/* Main Clock is 8MHz divided by 12
but memory and IO access is only possible
within the line and frame blanking period
thus requiring an extra loading of approx 3-5 */
m_maincpu->set_addrmap(AS_PROGRAM, &lazercmd_state::medlanes_map);
m_maincpu->set_addrmap(AS_DATA, &lazercmd_state::lazercmd_portmap);
m_maincpu->set_addrmap(AS_DATA, &lazercmd_state::portmap);
TIMER(config, "scantimer").configure_scanline(FUNC(lazercmd_state::lazercmd_timer), "screen", 0, 1);
/* video hardware */
// video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate
screen.set_size(HORZ_RES * HORZ_CHR, VERT_RES * VERT_CHR);
screen.set_visarea(0 * HORZ_CHR, HORZ_RES * HORZ_CHR - 1, 0 * VERT_CHR, VERT_RES * VERT_CHR - 1);
screen.set_screen_update(FUNC(lazercmd_state::screen_update_lazercmd));
screen.set_screen_update(FUNC(lazercmd_state::screen_update));
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_lazercmd);
PALETTE(config, m_palette, FUNC(lazercmd_state::lazercmd_palette), 5);
PALETTE(config, m_palette, FUNC(lazercmd_state::palette), 5);
/* sound hardware */
// sound hardware
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac2, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac3, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac[2], 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac[3], 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
}
void lazercmd_state::lazercmd(machine_config &config)
{
medlanes(config);
m_maincpu->set_addrmap(AS_PROGRAM, &lazercmd_state::lazercmd_map);
subdevice<screen_device>("screen")->set_size(HORZ_RES * HORZ_CHR, VERT_RES * VERT_CHR + 16);
subdevice<screen_device>("screen")->set_visarea(0 * HORZ_CHR, HORZ_RES * HORZ_CHR - 1, 0 * VERT_CHR, (VERT_RES - 1) * VERT_CHR - 1);
DAC_1BIT(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
}
void lazercmd_state::bbonk(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/12); /* 666 kHz */
/* Main Clock is 8MHz divided by 12
but memory and IO access is only possible
within the line and frame blanking period
thus requiring an extra loading of approx 3-5 */
medlanes(config);
m_maincpu->set_addrmap(AS_PROGRAM, &lazercmd_state::bbonk_map);
m_maincpu->set_addrmap(AS_DATA, &lazercmd_state::lazercmd_portmap);
TIMER(config, "scantimer").configure_scanline(FUNC(lazercmd_state::bbonk_timer), "screen", 0, 1);
TIMER(config.replace(), "scantimer").configure_scanline(FUNC(lazercmd_state::bbonk_timer), "screen", 0, 1);
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
screen.set_size(HORZ_RES * HORZ_CHR, VERT_RES * VERT_CHR);
screen.set_visarea(0 * HORZ_CHR, HORZ_RES * HORZ_CHR - 1, 0 * VERT_CHR, (VERT_RES - 1) * VERT_CHR - 1);
screen.set_screen_update(FUNC(lazercmd_state::screen_update_lazercmd));
screen.set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_lazercmd);
PALETTE(config, m_palette, FUNC(lazercmd_state::lazercmd_palette), 5);
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac2, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
DAC_1BIT(config, m_dac3, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
subdevice<screen_device>("screen")->set_visarea(0 * HORZ_CHR, HORZ_RES * HORZ_CHR - 1, 0 * VERT_CHR, (VERT_RES - 1) * VERT_CHR - 1);
}
/***************************************************************************
@ -726,7 +836,7 @@ void lazercmd_state::bbonk(machine_config &config)
***************************************************************************/
ROM_START( lazercmd )
ROM_REGION( 0x0c00, "maincpu", ROMREGION_INVERT ) /* 32K cpu, 4K for ROM/RAM */
ROM_REGION( 0x0c00, "maincpu", ROMREGION_INVERT ) // 32K cpu, 4K for ROM/RAM
ROM_LOAD_NIB_HIGH( "lc.e5", 0x0000, 0x0400, CRC(56dc7a40) SHA1(1324d5d6a44d7314723a0b5745d89f8e27f49d25) )
ROM_LOAD_NIB_LOW( "lc.f5", 0x0000, 0x0400, CRC(fc5b38a4) SHA1(bff670d7b78c6b9324d2bf4b2d8a4f9dbfe82158) )
ROM_LOAD_NIB_HIGH( "lc.e6", 0x0400, 0x0400, CRC(b1ef0aa2) SHA1(3edeaa4d4f4e18536066898284d430a1ac00512e) )
@ -734,12 +844,12 @@ ROM_START( lazercmd )
ROM_LOAD_NIB_HIGH( "lc.e7", 0x0800, 0x0400, CRC(8e6ffc97) SHA1(d5243ce88585db91573b6586d3d47d13b5b473c8) )
ROM_LOAD_NIB_LOW( "lc.f7", 0x0800, 0x0400, CRC(9ec3534d) SHA1(98f15c5828ad2743bf205f71b8e69abd4db78a58) )
ROM_REGION( 0x0c00, "gfx1", 0 )
ROM_REGION( 0x0c00, "chars", 0 )
ROM_LOAD( "lc.b8", 0x0a00, 0x0200, CRC(6d708edd) SHA1(85a45a292eb7bca288b06a118658bf754f828a92) )
ROM_END
ROM_START( medlanes )
ROM_REGION( 0x1800, "maincpu", ROMREGION_INVERT ) /* 32K cpu, 4K for ROM/RAM */
ROM_REGION( 0x1800, "maincpu", ROMREGION_INVERT ) // 32K cpu, 4K for ROM/RAM
ROM_LOAD_NIB_HIGH( "medlanes.2a", 0x0000, 0x0400, CRC(9c77566a) SHA1(60e1820012b47da8b86d54f00b6f60d2d0123745) )
ROM_LOAD_NIB_LOW( "medlanes.3a", 0x0000, 0x0400, CRC(22bc56a6) SHA1(7444170c19274d9d889df61796e6f61af2361f3e) )
ROM_LOAD_NIB_HIGH( "medlanes.2b", 0x0400, 0x0400, CRC(7841b1a9) SHA1(80621d30995dad42ae44c62494922ca8b75415cf) )
@ -751,29 +861,29 @@ ROM_START( medlanes )
ROM_LOAD_NIB_HIGH( "medlanes.1b", 0x1400, 0x0400, CRC(1d451630) SHA1(bf9de3096e98685355c906ab7e1dc2628dce79d6) )
ROM_LOAD_NIB_LOW( "medlanes.4b", 0x1400, 0x0400, CRC(a4abb5db) SHA1(a20da872b0f7d6b16b9551233af4269db9d1b55f) )
ROM_REGION( 0x0c00, "gfx1", 0 )
ROM_REGION( 0x0c00, "chars", 0 )
ROM_LOAD( "medlanes.8b", 0x0a00, 0x0200, CRC(44e5de8f) SHA1(fc797fa137f0c11a15caf9c0013aac668fd69a3c) )
ROM_END
ROM_START( bbonk )
ROM_REGION( 0x0c00, "maincpu", ROMREGION_INVERT ) /* 32K cpu, 4K for ROM/RAM */
ROM_REGION( 0x0c00, "maincpu", ROMREGION_INVERT ) // 32K cpu, 4K for ROM/RAM
ROM_LOAD_NIB_HIGH( "bbonk.e5", 0x0000, 0x0400, CRC(d032baa0) SHA1(09cba16f6a2b7d8a8c501db639bd5eeefb63dc0f) )
ROM_LOAD_NIB_LOW( "bbonk.f5", 0x0000, 0x0400, CRC(748e8c7f) SHA1(99e4e182ee41c246e31f656411a9f09d7b617f92) )
ROM_LOAD_NIB_HIGH( "bbonk.e6", 0x0400, 0x0400, CRC(71df0e25) SHA1(c2f78490816add1296923861a89df15be9822fed) )
ROM_LOAD_NIB_LOW( "bbonk.f6", 0x0400, 0x0400, CRC(5ce183ed) SHA1(7c78dfa463a37605e8423104426af2f5906fae24) )
ROM_REGION( 0x0c00, "gfx1", 0 )
ROM_REGION( 0x0c00, "chars", 0 )
ROM_LOAD( "bbonk.b8", 0x0a00, 0x0200, CRC(5ac34260) SHA1(7c2b1e378d2b9fed27117f9adab1381507f5d554) )
ROM_END
void lazercmd_state::init_lazercmd()
{
uint8_t *gfx = memregion("gfx1")->base();
uint8_t *gfx = memregion("chars")->base();
/******************************************************************
* To show the maze bit #6 and #7 of the video ram are used.
* To show the maze, bit #6 and #7 of the video RAM are used.
* Bit #7: add a vertical line to the right of the character
* Bit #6: add a horizontal line below the character
* The video logic generates 10 lines per character row, but the
@ -796,8 +906,9 @@ void lazercmd_state::init_lazercmd()
}
}
} // anonymous namespace
GAMEL( 1976, lazercmd, 0, lazercmd, lazercmd, lazercmd_state, init_lazercmd, ROT0, "Meadows Games, Inc.", "Lazer Command", MACHINE_SUPPORTS_SAVE, layout_lazercmd )
GAMEL( 1977, medlanes, 0, medlanes, medlanes, lazercmd_state, init_lazercmd, ROT0, "Meadows Games, Inc.", "Meadows Lanes", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE, layout_medlanes )
GAMEL( 1976, lazercmd, 0, lazercmd, lazercmd, lazercmd_state, init_lazercmd, ROT0, "Meadows Games, Inc.", "Lazer Command", MACHINE_SUPPORTS_SAVE, layout_lazercmd )
GAMEL( 1977, medlanes, 0, medlanes, medlanes, lazercmd_state, init_lazercmd, ROT0, "Meadows Games, Inc.", "Meadows Lanes", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE, layout_medlanes )
GAME( 1976, bbonk, 0, bbonk, bbonk, lazercmd_state, init_lazercmd, ROT0, "Meadows Games, Inc.", "Bigfoot Bonkers", MACHINE_SUPPORTS_SAVE )

View File

@ -1,97 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
#ifndef MAME_MEADOWS_LAZERCMD_H
#define MAME_MEADOWS_LAZERCMD_H
#pragma once
#include "cpu/s2650/s2650.h"
#include "machine/timer.h"
#include "sound/dac.h"
#include "emupal.h"
#define HORZ_RES 32
#define VERT_RES 24
#define HORZ_CHR 8
#define VERT_CHR 10
#define VERT_FNT 8
#define HORZ_BAR 0x40
#define VERT_BAR 0x80
#define MARKER_ACTIVE_L 0x03
#define MARKER_ACTIVE_R 0x04
#define MARKER_VERT_R 0x0a
#define MARKER_HORZ_L 0x0b
#define MARKER_VERT_L 0x0c
#define MARKER_HORZ_R 0x0d
#define MARKER_HORZ_ADJ -1
#define MARKER_VERT_ADJ -10
class lazercmd_state : public driver_device
{
public:
lazercmd_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_dac0(*this, "dac0"),
m_dac1(*this, "dac1"),
m_dac2(*this, "dac2"),
m_dac3(*this, "dac3"),
m_videoram(*this, "videoram"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
{ }
void bbonk(machine_config &config);
void medlanes(machine_config &config);
void lazercmd(machine_config &config);
void init_lazercmd();
private:
/* device */
required_device<s2650_device> m_maincpu;
optional_device<dac_bit_interface> m_dac0;
optional_device<dac_bit_interface> m_dac1;
required_device<dac_bit_interface> m_dac2;
required_device<dac_bit_interface> m_dac3;
/* memory pointers */
required_shared_ptr<uint8_t> m_videoram;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
/* video-related */
uint8_t m_marker_x = 0U;
uint8_t m_marker_y = 0U;
/* misc */
int m_timer_count = 0;
uint8_t m_sense_state = 0U;
uint8_t m_attract = 0U;
void lazercmd_ctrl_port_w(uint8_t data);
uint8_t lazercmd_ctrl_port_r();
void lazercmd_data_port_w(uint8_t data);
uint8_t lazercmd_data_port_r();
void lazercmd_hardware_w(offs_t offset, uint8_t data);
void medlanes_hardware_w(offs_t offset, uint8_t data);
void bbonk_hardware_w(offs_t offset, uint8_t data);
uint8_t lazercmd_hardware_r(offs_t offset);
virtual void machine_start() override;
virtual void machine_reset() override;
void lazercmd_palette(palette_device &palette) const;
uint32_t screen_update_lazercmd(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(lazercmd_timer);
TIMER_DEVICE_CALLBACK_MEMBER(bbonk_timer);
int vert_scale(int data);
void plot_pattern( bitmap_ind16 &bitmap, int x, int y );
void bbonk_map(address_map &map);
void lazercmd_map(address_map &map);
void lazercmd_portmap(address_map &map);
void medlanes_map(address_map &map);
};
#endif // MAME_MEADOWS_LAZERCMD_H

View File

@ -1,81 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
/*************************************************************/
/* */
/* Lazer Command video handler */
/* */
/*************************************************************/
#include "emu.h"
#include "lazercmd.h"
/* scale a markers vertical position */
/* the following table shows how the markers */
/* vertical position worked in hardware */
/* marker_y lines marker_y lines */
/* 0 0 + 1 8 10 + 11 */
/* 1 2 + 3 9 12 + 13 */
/* 2 4 + 5 10 14 + 15 */
/* 3 6 + 7 11 16 + 17 */
/* 4 8 + 9 12 18 + 19 */
int lazercmd_state::vert_scale(int data)
{
return ((data & 0x07) << 1) + ((data & 0xf8) >> 3) * VERT_CHR;
}
/* plot a bitmap marker */
/* hardware has 2 marker sizes 2x2 and 4x2 selected by jumper */
/* meadows lanes normaly use 2x2 pixels and lazer command uses either */
void lazercmd_state::plot_pattern( bitmap_ind16 &bitmap, int x, int y )
{
int size = 2;
if (ioport("DSW")->read() & 0x40)
{
size = 4;
}
for (int ybit = 0; ybit < 2; ybit++)
{
if (y + ybit < 0 || y + ybit >= VERT_RES * VERT_CHR)
return;
for (int xbit = 0; xbit < size; xbit++)
{
if (x + xbit < 0 || x + xbit >= HORZ_RES * HORZ_CHR)
continue;
bitmap.pix(y + ybit, x + xbit) = 4;
}
}
}
uint32_t lazercmd_state::screen_update_lazercmd(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int i, x, y;
int video_inverted = (ioport("DSW")->read() ^ m_attract) & 0x20;
/* The first row of characters are invisible */
for (i = 0; i < (VERT_RES - 1) * HORZ_RES; i++)
{
int sx, sy;
sx = i % HORZ_RES;
sy = i / HORZ_RES;
sx *= HORZ_CHR;
sy *= VERT_CHR;
m_gfxdecode->gfx(0)->opaque(bitmap,cliprect,
m_videoram[i], video_inverted ? 1 : 0,
0,0,
sx,sy);
}
x = m_marker_x - 1; /* normal video lags marker by 1 pixel */
y = vert_scale(m_marker_y) - VERT_CHR; /* first line used as scratch pad */
plot_pattern(bitmap, x, y);
return 0;
}

View File

@ -1,5 +1,6 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
// copyright-holders: Juergen Buchmueller
/***************************************************************************
Meadows S2650 driver
@ -42,7 +43,7 @@
2 coins 1 play 1 0
1 coin 2 plays 0 1
free play 1 1
D5 Attact music 0:off, 1:on
D5 Attract music 0:off, 1:on
D6-D7 Extended play D6 D7
none 0 0
5000 pts 1 0
@ -119,16 +120,315 @@
***************************************************************************/
#include "emu.h"
#include "meadows.h"
#include "cpu/s2650/s2650.h"
#include "sound/dac.h"
#include "sound/samples.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "tilemap.h"
#include "deadeye.lh"
#include "gypsyjug.lh"
#include "minferno.lh"
#define MASTER_CLOCK XTAL(5'000'000)
// configurable logging
#define LOG_AUDIO (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_AUDIO)
#include "logmacro.h"
#define LOGAUDIO(...) LOGMASKED(LOG_AUDIO, __VA_ARGS__)
namespace {
class meadows_state : public driver_device
{
public:
meadows_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_dac(*this, "dac"),
m_samples(*this, "samples"),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_spriteram(*this, "spriteram"),
m_videoram(*this, "videoram")
{
}
void bowl3d(machine_config &config);
void meadows(machine_config &config);
void minferno(machine_config &config);
void init_minferno();
void init_gypsyjug();
DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
protected:
virtual void machine_start() override;
virtual void video_start() override;
private:
required_device<s2650_device> m_maincpu;
optional_device<s2650_device> m_audiocpu;
optional_device<dac_8bit_r2r_device> m_dac;
optional_device<samples_device> m_samples;
required_device<gfxdecode_device> m_gfxdecode;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
optional_shared_ptr<uint8_t> m_spriteram;
required_shared_ptr<uint8_t> m_videoram;
uint8_t m_channel = 0; // TODO: always 0?
uint32_t m_freq1 = 0;
uint32_t m_freq2 = 0;
uint8_t m_latched_0c01 = 0;
uint8_t m_latched_0c02 = 0;
uint8_t m_latched_0c03 = 0;
uint8_t m_main_sense_state = 0;
uint8_t m_audio_sense_state = 0;
uint8_t m_0c00 = 0;
uint8_t m_0c01 = 0;
uint8_t m_0c02 = 0;
uint8_t m_0c03 = 0;
tilemap_t *m_bg_tilemap = nullptr;
uint8_t hsync_chain_r();
uint8_t vsync_chain_hi_r();
uint8_t vsync_chain_lo_r();
void audio_w(offs_t offset, uint8_t data);
void audio_hardware_w(offs_t offset, uint8_t data);
uint8_t audio_hardware_r(offs_t offset);
void videoram_w(offs_t offset, uint8_t data);
void spriteram_w(offs_t offset, uint8_t data);
TILE_GET_INFO_MEMBER(get_tile_info);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void meadows_vblank_irq(int state);
void minferno_vblank_irq(int state);
INTERRUPT_GEN_MEMBER(audio_interrupt);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip);
void sh_update();
SAMPLES_START_CB_MEMBER(sh_start);
void audio_map(address_map &map);
void bowl3d_main_map(address_map &map);
void meadows_main_map(address_map &map);
void minferno_data_map(address_map &map);
void minferno_main_map(address_map &map);
};
// audio
static constexpr uint32_t BASE_CTR1 = (5'000'000 / 256);
static constexpr uint32_t BASE_CTR2 = (5'000'000 / 32);
static constexpr uint8_t DIV2OR4_CTR2 = 0x01;
static constexpr uint8_t ENABLE_CTR2 = 0x02;
static constexpr uint8_t ENABLE_DAC = 0x04;
static constexpr uint8_t ENABLE_CTR1 = 0x08;
static const int16_t waveform[2] = { -120*256, 120*256 };
/************************************/
/* Sound handler start */
/************************************/
SAMPLES_START_CB_MEMBER(meadows_state::sh_start)
{
m_0c00 = m_0c01 = m_0c02 = m_0c03 = 0;
m_channel = 0;
m_freq1 = m_freq2 = 1000;
m_latched_0c01 = m_latched_0c02 = m_latched_0c03 = 0;
m_samples->set_volume(0, 0);
m_samples->start_raw(0, waveform, std::size(waveform), m_freq1, true);
m_samples->set_volume(1, 0);
m_samples->start_raw(1, waveform, std::size(waveform), m_freq2, true);
}
/************************************/
/* Sound handler update */
/************************************/
void meadows_state::sh_update()
{
if (m_latched_0c01 != m_0c01 || m_latched_0c03 != m_0c03)
{
/* amplitude is a combination of the upper 4 bits of 0c01
and bit 4 merged from S2650's flag output */
int amp = ((m_0c03 & ENABLE_CTR1) == 0) ? 0 : (m_0c01 & 0xf0) >> 1;
if( m_maincpu->state_int(S2650_FO) )
amp += 0x80;
/* calculate frequency for counter #1
bit 0..3 of 0c01 are ctr preset */
int const preset = (m_0c01 & 15) ^ 15;
if (preset)
m_freq1 = BASE_CTR1 / (preset + 1);
else amp = 0;
LOGAUDIO("meadows ctr1 channel #%d preset:%3d freq:%5d amp:%d\n", m_channel, preset, m_freq1, amp);
m_samples->set_frequency(0, m_freq1 * sizeof(waveform) / 2);
m_samples->set_volume(0, amp / 255.0);
}
if (m_latched_0c02 != m_0c02 || m_latched_0c03 != m_0c03)
{
/* calculate frequency for counter #2
0c02 is ctr preset, 0c03 bit 0 enables division by 2 */
int amp = ((m_0c03 & ENABLE_CTR2) != 0) ? 0xa0 : 0;
int const preset = m_0c02 ^ 0xff;
if (preset)
{
m_freq2 = BASE_CTR2 / (preset + 1) / 2;
if ((m_0c03 & DIV2OR4_CTR2) == 0)
m_freq2 >>= 1;
}
else amp = 0;
LOGAUDIO("meadows ctr2 channel #%d preset:%3d freq:%5d amp:%d\n", m_channel + 1, preset, m_freq2, amp);
m_samples->set_frequency(1, m_freq2 * sizeof(waveform));
m_samples->set_volume(1, amp / 255.0);
}
if (((m_latched_0c03 ^ m_0c03) & ENABLE_DAC) != 0)
{
m_dac->set_output_gain(ALL_OUTPUTS, (m_0c03 & ENABLE_DAC) != 0 ? 1.0 : 0.0);
}
m_latched_0c01 = m_0c01;
m_latched_0c02 = m_0c02;
m_latched_0c03 = m_0c03;
}
// video
// some constants to make life easier
static constexpr int8_t SPR_ADJUST_X = -18;
static constexpr int8_t SPR_ADJUST_Y = -14;
/*************************************
*
* Tilemap callbacks
*
*************************************/
TILE_GET_INFO_MEMBER(meadows_state::get_tile_info)
{
tileinfo.set(0, m_videoram[tile_index] & 0x7f, 0, 0);
}
/*************************************
*
* Video startup
*
*************************************/
void meadows_state::video_start()
{
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(meadows_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 30);
}
/*************************************
*
* Video RAM write
*
*************************************/
void meadows_state::videoram_w(offs_t offset, uint8_t data)
{
m_videoram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
/*************************************
*
* Sprite RAM write
*
*************************************/
void meadows_state::spriteram_w(offs_t offset, uint8_t data)
{
// m_screen->update_now();
m_screen->update_partial(m_screen->vpos());
m_spriteram[offset] = data;
}
/*************************************
*
* Sprite rendering
*
*************************************/
void meadows_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip)
{
for (int i = 0; i < 4; i++)
{
int const x = m_spriteram[i + 0] + SPR_ADJUST_X;
int const y = m_spriteram[i + 4] + SPR_ADJUST_Y;
int const code = m_spriteram[i + 8] & 0x0f; // bit #0 .. #3 select sprite
// int const bank = (m_spriteram[i + 8] >> 4) & 1; bit #4 selects PROM ???
int const bank = i; // that fixes it for now :-/
int const flip = m_spriteram[i + 8] >> 5; // bit #5 flip vertical flag
m_gfxdecode->gfx(bank + 1)->transpen(bitmap, clip, code, 0, flip, 0, x, y, 0);
}
}
/*************************************
*
* Primary video update
*
*************************************/
uint32_t meadows_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// draw the background
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
// draw the sprites
if (m_gfxdecode->gfx(1))
draw_sprites(bitmap, cliprect);
return 0;
}
// machine
void meadows_state::machine_start()
{
m_main_sense_state = 0;
// save_item(NAME(m_channel)); // commented out as it's always 0 right now
save_item(NAME(m_freq1));
save_item(NAME(m_freq2));
save_item(NAME(m_latched_0c01));
save_item(NAME(m_latched_0c02));
save_item(NAME(m_latched_0c03));
save_item(NAME(m_main_sense_state));
save_item(NAME(m_audio_sense_state));
save_item(NAME(m_0c00));
save_item(NAME(m_0c01));
save_item(NAME(m_0c02));
save_item(NAME(m_0c03));
}
/*************************************
@ -139,21 +439,21 @@
uint8_t meadows_state::hsync_chain_r()
{
uint8_t val = m_screen->hpos();
return bitswap<8>(val,0,1,2,3,4,5,6,7);
uint8_t const val = m_screen->hpos();
return bitswap<8>(val, 0, 1, 2, 3, 4, 5, 6, 7);
}
uint8_t meadows_state::vsync_chain_hi_r()
{
uint8_t val = m_screen->vpos();
uint8_t const val = m_screen->vpos();
return ((val >> 1) & 0x08) | ((val >> 3) & 0x04) | ((val >> 5) & 0x02) | (val >> 7);
}
uint8_t meadows_state::vsync_chain_lo_r()
{
uint8_t val = m_screen->vpos();
uint8_t const val = m_screen->vpos();
return val & 0x0f;
}
@ -165,27 +465,27 @@ uint8_t meadows_state::vsync_chain_lo_r()
*
*************************************/
void meadows_state::meadows_audio_w(offs_t offset, uint8_t data)
void meadows_state::audio_w(offs_t offset, uint8_t data)
{
switch (offset)
{
case 0:
if (m_0c00 == data)
break;
logerror("meadows_audio_w %d $%02x\n", offset, data);
LOGAUDIO("audio_w %d $%02x\n", offset, data);
m_0c00 = data;
break;
case 1:
logerror("meadows_audio_w %d $%02x\n", offset, data);
LOGAUDIO("audio_w %d $%02x\n", offset, data);
break;
case 2:
logerror("meadows_audio_w %d $%02x\n", offset, data);
LOGAUDIO("audio_w %d $%02x\n", offset, data);
break;
case 3:
/* S2650_Clear_Pending_Interrupts(); */
// S2650_Clear_Pending_Interrupts();
break;
}
}
@ -215,7 +515,7 @@ void meadows_state::meadows_vblank_irq(int state)
{
if (state)
{
/* fake something toggling the sense input line of the S2650 */
// fake something toggling the sense input line of the S2650
m_main_sense_state ^= 1;
m_maincpu->set_input_line(S2650_SENSE_LINE, m_main_sense_state ? ASSERT_LINE : CLEAR_LINE);
}
@ -250,32 +550,32 @@ void meadows_state::audio_hardware_w(offs_t offset, uint8_t data)
{
switch (offset & 3)
{
case 0: /* DAC */
case 0: // DAC
m_dac->write(data ^ 0xff);
break;
case 1: /* counter clk 5 MHz / 256 */
case 1: // counter clk 5 MHz / 256
if (data == m_0c01)
break;
logerror("audio_w ctr1 preset $%x amp %d\n", data & 15, data >> 4);
LOGAUDIO("audio_w ctr1 preset $%x amp %d\n", data & 15, data >> 4);
m_0c01 = data;
meadows_sh_update();
sh_update();
break;
case 2: /* counter clk 5 MHz / 32 (/ 2 or / 4) */
case 2: // counter clk 5 MHz / 32 (/ 2 or / 4)
if (data == m_0c02)
break;
logerror("audio_w ctr2 preset $%02x\n", data);
LOGAUDIO("audio_w ctr2 preset $%02x\n", data);
m_0c02 = data;
meadows_sh_update();
sh_update();
break;
case 3: /* audio enable */
case 3: // audio enable
if (data == m_0c03)
break;
logerror("audio_w enable ctr2/2:%d ctr2:%d dac:%d ctr1:%d\n", data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1);
LOGAUDIO("audio_w enable ctr2/2:%d ctr2:%d dac:%d ctr1:%d\n", data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1);
m_0c03 = data;
meadows_sh_update();
sh_update();
break;
}
}
@ -315,7 +615,7 @@ uint8_t meadows_state::audio_hardware_r(offs_t offset)
INTERRUPT_GEN_MEMBER(meadows_state::audio_interrupt)
{
/* fake something toggling the sense input line of the S2650 */
// fake something toggling the sense input line of the S2650
m_audio_sense_state ^= 1;
m_audiocpu->set_input_line(S2650_SENSE_LINE, m_audio_sense_state ? ASSERT_LINE : CLEAR_LINE);
}
@ -335,11 +635,11 @@ void meadows_state::meadows_main_map(address_map &map)
map(0x0c01, 0x0c01).portr("STICK");
map(0x0c02, 0x0c02).r(FUNC(meadows_state::hsync_chain_r));
map(0x0c03, 0x0c03).portr("DSW");
map(0x0c00, 0x0c03).w(FUNC(meadows_state::meadows_audio_w));
map(0x0d00, 0x0d0f).w(FUNC(meadows_state::meadows_spriteram_w)).share("spriteram");
map(0x0c00, 0x0c03).w(FUNC(meadows_state::audio_w));
map(0x0d00, 0x0d0f).w(FUNC(meadows_state::spriteram_w)).share(m_spriteram);
map(0x0e00, 0x0eff).ram();
map(0x1000, 0x1bff).rom();
map(0x1c00, 0x1fff).ram().w(FUNC(meadows_state::meadows_videoram_w)).share("videoram");
map(0x1c00, 0x1fff).ram().w(FUNC(meadows_state::videoram_w)).share(m_videoram);
}
void meadows_state::bowl3d_main_map(address_map &map)
@ -349,22 +649,22 @@ void meadows_state::bowl3d_main_map(address_map &map)
map(0x0c01, 0x0c01).portr("INPUTS2");
map(0x0c02, 0x0c02).r(FUNC(meadows_state::hsync_chain_r));
map(0x0c03, 0x0c03).portr("DSW");
map(0x0c00, 0x0c03).w(FUNC(meadows_state::meadows_audio_w));
map(0x0d00, 0x0d0f).w(FUNC(meadows_state::meadows_spriteram_w)).share("spriteram");
map(0x0c00, 0x0c03).w(FUNC(meadows_state::audio_w));
map(0x0d00, 0x0d0f).w(FUNC(meadows_state::spriteram_w)).share(m_spriteram);
map(0x0e00, 0x0eff).ram();
map(0x1000, 0x1bff).rom();
map(0x1c00, 0x1fff).ram().w(FUNC(meadows_state::meadows_videoram_w)).share("videoram");
map(0x1c00, 0x1fff).ram().w(FUNC(meadows_state::videoram_w)).share(m_videoram);
}
void meadows_state::minferno_main_map(address_map &map)
{
map(0x0000, 0x0bff).rom();
map(0x1c00, 0x1eff).ram().w(FUNC(meadows_state::meadows_videoram_w)).share("videoram");
map(0x1c00, 0x1eff).ram().w(FUNC(meadows_state::videoram_w)).share(m_videoram);
map(0x1f00, 0x1f00).portr("JOY1");
map(0x1f01, 0x1f01).portr("JOY2");
map(0x1f02, 0x1f02).portr("BUTTONS");
map(0x1f03, 0x1f03).portr("DSW1");
map(0x1f00, 0x1f03).w(FUNC(meadows_state::meadows_audio_w));
map(0x1f00, 0x1f03).w(FUNC(meadows_state::audio_w));
map(0x1f04, 0x1f04).r(FUNC(meadows_state::vsync_chain_hi_r));
map(0x1f05, 0x1f05).r(FUNC(meadows_state::vsync_chain_lo_r));
}
@ -537,12 +837,12 @@ static INPUT_PORTS_START( minferno )
PORT_DIPSETTING( 0x10, "20s" )
PORT_DIPSETTING( 0x20, "40s" )
PORT_DIPSETTING( 0x30, "60s" )
/* PORT_DIPNAME( 0x40, 0x00, DEF_STR( Unused ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x40, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unused ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x80, DEF_STR( On ) ) */
PORT_DIPNAME( 0x40, 0x00, DEF_STR( Unused ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x40, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unused ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
INPUT_PORTS_END
@ -555,41 +855,41 @@ INPUT_PORTS_END
static const gfx_layout charlayout =
{
8,8, /* 8*8 characters */
128, /* 128 characters ? */
1, /* 1 bit per pixel */
{ 0 }, /* no bitplanes */
{ 0, 1, 2, 3, 4, 5, 6, 7 }, /* pretty straight layout */
8,8, // 8*8 characters
128, // 128 characters ?
1, // 1 bit per pixel
{ 0 }, // no bitplanes
{ 0, 1, 2, 3, 4, 5, 6, 7 }, // pretty straight layout
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 bytes */
8*8 // every char takes 8 bytes
};
static const gfx_layout spritelayout =
{
16,16, /* 16*16 sprites ? */
32, /* 32 sprites */
1, /* 1 bits per pixel */
{ 0 }, /* 1 bitplane */
16,16, // 16*16 sprites ?
32, // 32 sprites
1, // 1 bits per pixel
{ 0 }, // 1 bitplane
{ 0, 1, 2, 3, 4, 5, 6, 7,
8, 9,10,11,12,13,14,15 }, /* pretty straight layout */
8, 9,10,11,12,13,14,15 }, // pretty straight layout
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
8*16, 9*16,10*16,11*16,12*16,13*16,14*16,15*16 },
16*2*8 /* every sprite takes 32 bytes */
16*2*8 // every sprite takes 32 bytes
};
static GFXDECODE_START( gfx_meadows )
GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 1 ) /* character generator */
GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 0, 1 ) /* sprite prom 1 */
GFXDECODE_ENTRY( "gfx3", 0, spritelayout, 0, 1 ) /* sprite prom 2 */
GFXDECODE_ENTRY( "gfx4", 0, spritelayout, 0, 1 ) /* sprite prom 3 (unused) */
GFXDECODE_ENTRY( "gfx5", 0, spritelayout, 0, 1 ) /* sprite prom 4 (unused) */
GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 1 ) // character generator
GFXDECODE_ENTRY( "sprites1", 0, spritelayout, 0, 1 ) // sprite PROM 1
GFXDECODE_ENTRY( "sprites2", 0, spritelayout, 0, 1 ) // sprite PROM 2
GFXDECODE_ENTRY( "sprites3", 0, spritelayout, 0, 1 ) // sprite PROM 3 (unused)
GFXDECODE_ENTRY( "sprites4", 0, spritelayout, 0, 1 ) // sprite PROM 4 (unused)
GFXDECODE_END
static GFXDECODE_START( gfx_minferno )
GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 4 )
GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 4 )
GFXDECODE_END
@ -603,12 +903,12 @@ GFXDECODE_END
static const char *const bowl3d_sample_names[] =
{
"*bowl3d",
"roll", /* "roll" */
"rollback", /* "roll back" */
"sweep", /* "sweep" */
"footstep", /* "foot sweep" */
"crash", /* "crash" */
"cheering", /* "cheering" */
"roll", // "roll"
"rollback", // "roll back"
"sweep", // "sweep"
"footstep", // "foot sweep"
"crash", // "crash"
"cheering", // "cheering"
nullptr
};
@ -620,95 +920,67 @@ static const char *const bowl3d_sample_names[] =
void meadows_state::meadows(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/8); /* 5MHz / 8 = 625 kHz */
// basic machine hardware
S2650(config, m_maincpu, 5_MHz_XTAL / 8); // 5MHz / 8 = 625 kHz
m_maincpu->set_addrmap(AS_PROGRAM, &meadows_state::meadows_main_map);
m_maincpu->intack_handler().set([]() { return 0x82; });
S2650(config, m_audiocpu, MASTER_CLOCK/8); /* 5MHz / 8 = 625 kHz */
S2650(config, m_audiocpu, 5_MHz_XTAL / 8); // 5MHz / 8 = 625 kHz
m_audiocpu->set_addrmap(AS_PROGRAM, &meadows_state::audio_map);
m_audiocpu->set_periodic_int(FUNC(meadows_state::audio_interrupt), attotime::from_hz((double)5000000/131072));
m_audiocpu->set_periodic_int(FUNC(meadows_state::audio_interrupt), attotime::from_hz((double)5000000 / 131072));
config.set_maximum_quantum(attotime::from_hz(600));
/* video hardware */
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_size(32*8, 30*8);
m_screen->set_visarea(0*8, 32*8-1, 2*8, 30*8-1);
m_screen->set_screen_update(FUNC(meadows_state::screen_update_meadows));
m_screen->set_screen_update(FUNC(meadows_state::screen_update));
m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(FUNC(meadows_state::meadows_vblank_irq)); // one interrupt per frame!?
GFXDECODE(config, m_gfxdecode, m_palette, gfx_meadows);
PALETTE(config, m_palette, palette_device::MONOCHROME);
/* audio hardware */
// audio hardware
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
SAMPLES(config, m_samples);
m_samples->set_channels(2);
m_samples->set_samples_start_callback(FUNC(meadows_state::meadows_sh_start));
m_samples->set_samples_start_callback(FUNC(meadows_state::sh_start));
m_samples->add_route(ALL_OUTPUTS, "speaker", 1.0);
}
void meadows_state::minferno(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/24); /* 5MHz / 8 / 3 = 208.33 kHz */
// basic machine hardware
S2650(config, m_maincpu, 5_MHz_XTAL / 24); // 5MHz / 8 / 3 = 208.33 kHz
m_maincpu->set_addrmap(AS_PROGRAM, &meadows_state::minferno_main_map);
m_maincpu->set_addrmap(AS_DATA, &meadows_state::minferno_data_map);
/* video hardware */
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_size(32*8, 32*8);
m_screen->set_visarea(0*8, 32*8-1, 1*8, 24*8-1);
m_screen->set_screen_update(FUNC(meadows_state::screen_update_meadows));
m_screen->set_screen_update(FUNC(meadows_state::screen_update));
m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(FUNC(meadows_state::minferno_vblank_irq));
GFXDECODE(config, m_gfxdecode, m_palette, gfx_minferno);
PALETTE(config, m_palette, palette_device::MONOCHROME);
/* audio hardware */
// audio hardware
// TODO
}
void meadows_state::bowl3d(machine_config &config)
{
/* basic machine hardware */
S2650(config, m_maincpu, MASTER_CLOCK/8); /* 5MHz / 8 = 625 kHz */
meadows(config);
m_maincpu->set_addrmap(AS_PROGRAM, &meadows_state::bowl3d_main_map);
m_maincpu->intack_handler().set([]() { return 0x82; });
S2650(config, m_audiocpu, MASTER_CLOCK/8); /* 5MHz / 8 = 625 kHz */
m_audiocpu->set_addrmap(AS_PROGRAM, &meadows_state::audio_map);
m_audiocpu->set_periodic_int(FUNC(meadows_state::audio_interrupt), attotime::from_hz((double)5000000/131072));
config.set_maximum_quantum(attotime::from_hz(600));
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_size(32*8, 30*8);
m_screen->set_visarea(0*8, 32*8-1, 2*8, 30*8-1);
m_screen->set_screen_update(FUNC(meadows_state::screen_update_meadows));
m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(FUNC(meadows_state::meadows_vblank_irq)); // one interrupt per frame!?
GFXDECODE(config, m_gfxdecode, m_palette, gfx_meadows);
PALETTE(config, m_palette, palette_device::MONOCHROME);
/* audio hardware */
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
SAMPLES(config, m_samples);
m_samples->set_channels(2);
m_samples->set_samples_start_callback(FUNC(meadows_state::meadows_sh_start));
m_samples->add_route(ALL_OUTPUTS, "speaker", 1.0);
samples_device &samples2(SAMPLES(config, "samples2"));
samples2.set_channels(1);
@ -731,19 +1003,19 @@ ROM_START( deadeye )
ROM_LOAD( "de5.12h", 0x1400, 0x0400, CRC(7bdb535c) SHA1(7bd2e261a22f5f3ffc60ea12ca5f38c445ec0030) )
ROM_LOAD( "de6.13h", 0x1800, 0x0400, CRC(847f9467) SHA1(253d386b76be99a1deef9e6b4cd906efdd9cf6d9) )
ROM_REGION( 0x0400, "gfx1", 0 )
ROM_REGION( 0x0400, "chars", 0 )
ROM_LOAD( "de_char.15e", 0x0000, 0x0400, CRC(b032bd8d) SHA1(130614d951c440a31c1262517cca0a133ddd1545) )
ROM_REGION( 0x0400, "gfx2", 0 )
ROM_REGION( 0x0400, "sprites1", 0 )
ROM_LOAD( "de_mov1.5a", 0x0000, 0x0400, CRC(c046b4c6) SHA1(3baa47a6c8962f6f66c08847b4ee4aa91580ad1a) )
ROM_REGION( 0x0400, "gfx3", 0 )
ROM_REGION( 0x0400, "sprites2", 0 )
ROM_LOAD( "de_mov2.13a", 0x0000, 0x0400, CRC(b89c5df9) SHA1(dd0eac9d646dd24575c7b61ce141fdc66994c188) )
ROM_REGION( 0x0400, "gfx4", ROMREGION_ERASEFF )
/* empty */
ROM_REGION( 0x0400, "gfx5", ROMREGION_ERASEFF )
/* empty */
ROM_REGION( 0x0400, "sprites3", ROMREGION_ERASEFF )
// empty
ROM_REGION( 0x0400, "sprites4", ROMREGION_ERASEFF )
// empty
ROM_REGION( 0x08000, "audiocpu", 0 )
ROM_LOAD( "de_sound_099c_m2-a1.0.4a", 0x0000, 0x0400, CRC(c10a1b1a) SHA1(779ea261d23360634081295a164cacbd819d8719) )
@ -759,27 +1031,27 @@ ROM_START( bowl3d )
ROM_LOAD( "b3d.h12", 0x1400, 0x0400, CRC(80a149d6) SHA1(ab4ca76d9f5aa5e02b9d5bf909af9548fe62f475) )
// h13 empty
/* Universal Game Logic according to schematics */
ROM_REGION( 0x08000, "audiocpu", 0 ) /* 2650 CPU at j8 */
ROM_LOAD( "82s115.a6", 0x0000, 0x0001, NO_DUMP ) /* 82s115 eprom */
ROM_LOAD( "82s115.c6", 0x0000, 0x0001, NO_DUMP ) /* 82s115 eprom */
// Universal Game Logic according to schematics
ROM_REGION( 0x08000, "audiocpu", 0 ) // 2650 CPU at j8
ROM_LOAD( "82s115.a6", 0x0000, 0x0001, NO_DUMP ) // 82s115 EPROM
ROM_LOAD( "82s115.c6", 0x0000, 0x0001, NO_DUMP ) // 82s115 EPROM
ROM_REGION( 0x0400, "gfx1", 0 )
ROM_REGION( 0x0400, "chars", 0 )
ROM_LOAD( "b3d.e15", 0x0000, 0x0400, CRC(4414e24f) SHA1(835c989143895848df7154c2d82a499dea79c1c5) )
ROM_REGION( 0x0400, "gfx2", 0 )
ROM_REGION( 0x0400, "sprites1", 0 )
ROM_LOAD( "b3d.a5", 0x0000, 0x0400, CRC(4b657f8a) SHA1(52eb90ff5048db30e9710e96793bad5e2c7ad6db) )
ROM_REGION( 0x0400, "gfx3", 0 )
ROM_REGION( 0x0400, "sprites2", 0 )
ROM_LOAD( "b3d.a13", 0x0000, 0x0400, CRC(ca7f33b9) SHA1(6c63a41be57e71d6a58112be13d77e695a0faa10) )
ROM_REGION( 0x0400, "gfx4", ROMREGION_ERASEFF )
/* empty */
ROM_REGION( 0x0400, "gfx5", ROMREGION_ERASEFF )
/* empty */
ROM_REGION( 0x0400, "sprites3", ROMREGION_ERASEFF )
// empty
ROM_REGION( 0x0400, "sprites4", ROMREGION_ERASEFF )
// empty
ROM_REGION( 0x0001, "proms", 0 )
ROM_LOAD( "82s123.r8", 0x0000, 0x0001, NO_DUMP ) /* 82s123 prom located on Universal Game Logic */
ROM_LOAD( "82s123.r8", 0x0000, 0x0001, NO_DUMP ) // 82s123 PROM located on Universal Game Logic
ROM_END
@ -791,20 +1063,20 @@ ROM_START( gypsyjug )
ROM_LOAD( "gj.4b", 0x1000, 0x0400, CRC(dca519c8) SHA1(7651aa8b2a8e53113eb08108a5b8fb20518ae185) )
ROM_LOAD( "gj.5b", 0x1400, 0x0400, CRC(7d83f9d0) SHA1(9aa8b281b5de7d913cf364a1159f2762fc69022d) )
ROM_REGION( 0x0400, "gfx1", 0 )
ROM_REGION( 0x0400, "chars", 0 )
ROM_LOAD( "gj.e15", 0x0000, 0x0400, CRC(adb25e13) SHA1(67b5a24a724310f3817a891a54d239d60fe80760) )
ROM_REGION( 0x0400, "gfx2", 0 )
ROM_REGION( 0x0400, "sprites1", 0 )
ROM_LOAD( "gj.a", 0x0000, 0x0400, CRC(d3725193) SHA1(5ea28c410a7b9532276fb98c7003b4c8f64d24c9) )
ROM_REGION( 0x0400, "gfx3", ROMREGION_ERASEFF )
/* empty (copied from 2) */
ROM_REGION( 0x0400, "sprites2", ROMREGION_ERASEFF )
// empty (copied from 2)
ROM_REGION( 0x0400, "gfx4", 0 )
ROM_LOAD( "gj.x", 0x0000, 0x0400, NO_DUMP ) /* missing */
ROM_REGION( 0x0400, "sprites3", 0 )
ROM_LOAD( "gj.x", 0x0000, 0x0400, NO_DUMP ) // missing
ROM_REGION( 0x0400, "gfx5", 0 )
ROM_LOAD( "gj.y", 0x0000, 0x0400, NO_DUMP ) /* missing */
ROM_REGION( 0x0400, "sprites4", 0 )
ROM_LOAD( "gj.y", 0x0000, 0x0400, NO_DUMP ) // missing
ROM_REGION( 0x08000, "audiocpu", 0 )
ROM_LOAD( "gj.a4s", 0x0000, 0x0400, CRC(17a116bc) SHA1(797ba0b292afa3ba7eec985b533014acc00ed47d) )
@ -822,7 +1094,7 @@ ROM_START( minferno )
ROM_LOAD_NIB_LOW ( "inferno.f7", 0x0800, 0x0400, CRC(73b4e9a3) SHA1(d9de88748a3009f3fc1f90c96bfc9732dc6a4a22) )
ROM_LOAD_NIB_HIGH( "inferno.e7", 0x0800, 0x0400, CRC(902d9b78) SHA1(3bebbba6c7d00bea2c687b965f59a9e55b430dfa) )
ROM_REGION( 0x00400, "gfx1", 0 )
ROM_REGION( 0x00400, "chars", 0 )
ROM_LOAD( "inferno.b8", 0x0200, 0x0200, CRC(1b06466b) SHA1(aef13ab84526ee7493837eef7f48d9ede65b8e62) )
ROM_END
@ -834,7 +1106,7 @@ ROM_END
*
*************************************/
/* A fake for the missing ball sprites #3 and #4 */
// A fake for the missing ball sprites #3 and #4
void meadows_state::init_gypsyjug()
{
static const uint8_t ball[16*2] =
@ -844,16 +1116,16 @@ void meadows_state::init_gypsyjug()
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
0x01,0x80, 0x03,0xc0, 0x03,0xc0, 0x01,0x80
};
uint8_t *gfx2 = memregion("gfx2")->base();
uint8_t *gfx3 = memregion("gfx3")->base();
uint8_t *gfx4 = memregion("gfx4")->base();
uint8_t *gfx5 = memregion("gfx5")->base();
int len3 = memregion("gfx3")->bytes();
int len4 = memregion("gfx4")->bytes();
uint8_t *gfx2 = memregion("sprites1")->base();
uint8_t *gfx3 = memregion("sprites2")->base();
uint8_t *gfx4 = memregion("sprites3")->base();
uint8_t *gfx5 = memregion("sprites4")->base();
int len3 = memregion("sprites2")->bytes();
int len4 = memregion("sprites3")->bytes();
memcpy(gfx3,gfx2,len3);
memcpy(gfx3, gfx2, len3);
for (int i = 0; i < len4; i += 16*2)
for (int i = 0; i < len4; i += 16 * 2)
{
memcpy(gfx4 + i, ball, sizeof(ball));
memcpy(gfx5 + i, ball, sizeof(ball));
@ -861,16 +1133,17 @@ void meadows_state::init_gypsyjug()
}
/* A fake for inverting the data bus */
// A fake for inverting the data bus
void meadows_state::init_minferno()
{
/* create an inverted copy of the graphics data */
uint8_t *mem = memregion("gfx1")->base();
int length = memregion("gfx1")->bytes();
// create an inverted copy of the graphics data
uint8_t *mem = memregion("chars")->base();
int length = memregion("chars")->bytes();
for (int i = 0; i < length / 2; i++)
mem[i] = ~mem[i + length / 2];
}
} // anonymous namespace
/*************************************
@ -879,7 +1152,7 @@ void meadows_state::init_minferno()
*
*************************************/
GAMEL( 1978, deadeye, 0, meadows, meadows, meadows_state, empty_init, ROT0, "Meadows Games, Inc.", "Dead Eye", 0, layout_deadeye )
GAME( 1978, bowl3d, 0, bowl3d, bowl3d, meadows_state, empty_init, ROT90, "Meadows Games, Inc.", "3-D Bowling", MACHINE_NO_SOUND )
GAMEL( 1978, gypsyjug, 0, meadows, meadows, meadows_state, init_gypsyjug, ROT0, "Meadows Games, Inc.", "Gypsy Juggler", MACHINE_IMPERFECT_GRAPHICS, layout_gypsyjug )
GAMEL( 1978, minferno, 0, minferno, minferno, meadows_state, init_minferno, ROT0, "Meadows Games, Inc.", "Inferno (Meadows)", MACHINE_NO_SOUND, layout_minferno )
GAMEL( 1978, deadeye, 0, meadows, meadows, meadows_state, empty_init, ROT0, "Meadows Games, Inc.", "Dead Eye", MACHINE_SUPPORTS_SAVE, layout_deadeye )
GAME( 1978, bowl3d, 0, bowl3d, bowl3d, meadows_state, empty_init, ROT90, "Meadows Games, Inc.", "3-D Bowling", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE)
GAMEL( 1978, gypsyjug, 0, meadows, meadows, meadows_state, init_gypsyjug, ROT0, "Meadows Games, Inc.", "Gypsy Juggler", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE, layout_gypsyjug )
GAMEL( 1978, minferno, 0, minferno, minferno, meadows_state, init_minferno, ROT0, "Meadows Games, Inc.", "Inferno (Meadows)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE, layout_minferno )

View File

@ -1,98 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
/*************************************************************************
Meadows S2650 hardware
*************************************************************************/
#ifndef MAME_MEADOWS_MEADOWS_H
#define MAME_MEADOWS_MEADOWS_H
#pragma once
#include "cpu/s2650/s2650.h"
#include "sound/dac.h"
#include "sound/samples.h"
#include "emupal.h"
#include "screen.h"
#include "tilemap.h"
class meadows_state : public driver_device
{
public:
meadows_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_dac(*this, "dac"),
m_samples(*this, "samples"),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_spriteram(*this, "spriteram"),
m_videoram(*this, "videoram")
{
}
void bowl3d(machine_config &config);
void meadows(machine_config &config);
void minferno(machine_config &config);
void init_minferno();
void init_gypsyjug();
DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
protected:
virtual void machine_start() override { m_main_sense_state = 0; }
virtual void video_start() override;
private:
required_device<s2650_device> m_maincpu;
optional_device<s2650_device> m_audiocpu;
optional_device<dac_8bit_r2r_device> m_dac;
optional_device<samples_device> m_samples;
required_device<gfxdecode_device> m_gfxdecode;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
optional_shared_ptr<uint8_t> m_spriteram;
required_shared_ptr<uint8_t> m_videoram;
int m_channel = 0;
int m_freq1 = 0;
int m_freq2 = 0;
uint8_t m_latched_0c01 = 0;
uint8_t m_latched_0c02 = 0;
uint8_t m_latched_0c03 = 0;
uint8_t m_main_sense_state = 0;
uint8_t m_audio_sense_state = 0;
uint8_t m_0c00 = 0;
uint8_t m_0c01 = 0;
uint8_t m_0c02 = 0;
uint8_t m_0c03 = 0;
tilemap_t *m_bg_tilemap = nullptr;
uint8_t hsync_chain_r();
uint8_t vsync_chain_hi_r();
uint8_t vsync_chain_lo_r();
void meadows_audio_w(offs_t offset, uint8_t data);
void audio_hardware_w(offs_t offset, uint8_t data);
uint8_t audio_hardware_r(offs_t offset);
void meadows_videoram_w(offs_t offset, uint8_t data);
void meadows_spriteram_w(offs_t offset, uint8_t data);
TILE_GET_INFO_MEMBER(get_tile_info);
uint32_t screen_update_meadows(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void meadows_vblank_irq(int state);
void minferno_vblank_irq(int state);
INTERRUPT_GEN_MEMBER(audio_interrupt);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip);
void meadows_sh_update();
SAMPLES_START_CB_MEMBER(meadows_sh_start);
void audio_map(address_map &map);
void bowl3d_main_map(address_map &map);
void meadows_main_map(address_map &map);
void minferno_data_map(address_map &map);
void minferno_main_map(address_map &map);
};
#endif // MAME_MEADOWS_MEADOWS_H

View File

@ -1,96 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
/***************************************************************************
meadows.c
Sound handler
Dead Eye, Gypsy Juggler
J. Buchmueller, June '98
****************************************************************************/
#include "emu.h"
#include "cpu/s2650/s2650.h"
#include "meadows.h"
#include "sound/samples.h"
#define BASE_CLOCK 5000000
#define BASE_CTR1 (BASE_CLOCK / 256)
#define BASE_CTR2 (BASE_CLOCK / 32)
#define DIV2OR4_CTR2 0x01
#define ENABLE_CTR2 0x02
#define ENABLE_DAC 0x04
#define ENABLE_CTR1 0x08
static const int16_t waveform[2] = { -120*256, 120*256 };
/************************************/
/* Sound handler start */
/************************************/
SAMPLES_START_CB_MEMBER(meadows_state::meadows_sh_start)
{
m_0c00 = m_0c01 = m_0c02 = m_0c03 = 0;
m_channel = 0;
m_freq1 = m_freq2 = 1000;
m_latched_0c01 = m_latched_0c02 = m_latched_0c03 = 0;
m_samples->set_volume(0,0);
m_samples->start_raw(0,waveform,std::size(waveform),m_freq1,true);
m_samples->set_volume(1,0);
m_samples->start_raw(1,waveform,std::size(waveform),m_freq2,true);
}
/************************************/
/* Sound handler update */
/************************************/
void meadows_state::meadows_sh_update()
{
int preset, amp;
if (m_latched_0c01 != m_0c01 || m_latched_0c03 != m_0c03)
{
/* amplitude is a combination of the upper 4 bits of 0c01 */
/* and bit 4 merged from S2650's flag output */
amp = ((m_0c03 & ENABLE_CTR1) == 0) ? 0 : (m_0c01 & 0xf0) >> 1;
if( m_maincpu->state_int(S2650_FO) )
amp += 0x80;
/* calculate frequency for counter #1 */
/* bit 0..3 of 0c01 are ctr preset */
preset = (m_0c01 & 15) ^ 15;
if (preset)
m_freq1 = BASE_CTR1 / (preset + 1);
else amp = 0;
logerror("meadows ctr1 channel #%d preset:%3d freq:%5d amp:%d\n", m_channel, preset, m_freq1, amp);
m_samples->set_frequency(0, m_freq1 * sizeof(waveform)/2);
m_samples->set_volume(0,amp/255.0);
}
if (m_latched_0c02 != m_0c02 || m_latched_0c03 != m_0c03)
{
/* calculate frequency for counter #2 */
/* 0c02 is ctr preset, 0c03 bit 0 enables division by 2 */
amp = ((m_0c03 & ENABLE_CTR2) != 0) ? 0xa0 : 0;
preset = m_0c02 ^ 0xff;
if (preset)
{
m_freq2 = BASE_CTR2 / (preset + 1) / 2;
if ((m_0c03 & DIV2OR4_CTR2) == 0)
m_freq2 >>= 1;
}
else amp = 0;
logerror("meadows ctr2 channel #%d preset:%3d freq:%5d amp:%d\n", m_channel+1, preset, m_freq2, amp);
m_samples->set_frequency(1, m_freq2 * sizeof(waveform));
m_samples->set_volume(1,amp/255.0);
}
if (((m_latched_0c03 ^ m_0c03) & ENABLE_DAC) != 0)
{
m_dac->set_output_gain(ALL_OUTPUTS, (m_0c03 & ENABLE_DAC) != 0 ? 1.0 : 0.0);
}
m_latched_0c01 = m_0c01;
m_latched_0c02 = m_0c02;
m_latched_0c03 = m_0c03;
}

View File

@ -1,110 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
/***************************************************************************
Meadows S2650 driver
****************************************************************************/
#include "emu.h"
#include "meadows.h"
/* some constants to make life easier */
#define SPR_ADJUST_X -18
#define SPR_ADJUST_Y -14
/*************************************
*
* Tilemap callbacks
*
*************************************/
TILE_GET_INFO_MEMBER(meadows_state::get_tile_info)
{
tileinfo.set(0, m_videoram[tile_index] & 0x7f, 0, 0);
}
/*************************************
*
* Video startup
*
*************************************/
void meadows_state::video_start()
{
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(meadows_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,30);
}
/*************************************
*
* Video RAM write
*
*************************************/
void meadows_state::meadows_videoram_w(offs_t offset, uint8_t data)
{
m_videoram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
/*************************************
*
* Sprite RAM write
*
*************************************/
void meadows_state::meadows_spriteram_w(offs_t offset, uint8_t data)
{
// m_screen->update_now();
m_screen->update_partial(m_screen->vpos());
m_spriteram[offset] = data;
}
/*************************************
*
* Sprite rendering
*
*************************************/
void meadows_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip)
{
for (int i = 0; i < 4; i++)
{
int x = m_spriteram[i+0] + SPR_ADJUST_X;
int y = m_spriteram[i+4] + SPR_ADJUST_Y;
int code = m_spriteram[i+8] & 0x0f; /* bit #0 .. #3 select sprite */
/* int bank = (m_spriteram[i+8] >> 4) & 1; bit #4 selects prom ??? */
int bank = i; /* that fixes it for now :-/ */
int flip = m_spriteram[i+8] >> 5; /* bit #5 flip vertical flag */
m_gfxdecode->gfx(bank + 1)->transpen(bitmap,clip, code, 0, flip, 0, x, y, 0);
}
}
/*************************************
*
* Primary video update
*
*************************************/
uint32_t meadows_state::screen_update_meadows(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
/* draw the background */
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
/* draw the sprites */
if (m_gfxdecode->gfx(1))
draw_sprites(bitmap, cliprect);
return 0;
}