atari/klax.cpp, atari/liberatr.cpp, atari/metalmx.cpp, atari/nitedrvr.cpp: consolidated drivers in single files

This commit is contained in:
Ivan Vangelista 2023-02-14 18:07:07 +01:00
parent 2913bbaaf8
commit 2b9da4a413
14 changed files with 1279 additions and 1334 deletions

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
Atari Klax hardware
@ -20,16 +21,208 @@
#include "emu.h"
#include "klax.h"
#include "atarimo.h"
#include "cpu/m68000/m68000.h"
#include "cpu/z80/z80.h"
#include "machine/eeprompar.h"
#include "machine/timer.h"
#include "machine/watchdog.h"
#include "sound/msm5205.h"
#include "sound/okim6295.h"
#include "emupal.h"
#include "speaker.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "tilemap.h"
namespace {
class klax_state : public driver_device
{
public:
klax_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_gfxdecode(*this, "gfxdecode")
, m_screen(*this, "screen")
, m_playfield_tilemap(*this, "playfield")
, m_mob(*this, "mob")
, m_p1(*this, "P1")
{ }
void klax(machine_config &config);
protected:
required_device<cpu_device> m_maincpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<screen_device> m_screen;
required_device<tilemap_device> m_playfield_tilemap;
required_device<atari_motion_objects_device> m_mob;
required_ioport m_p1;
static const atari_motion_objects_config s_mob_config;
void klax_base(machine_config &config);
TIMER_DEVICE_CALLBACK_MEMBER(scanline_update);
void interrupt_ack_w(u16 data = 0);
void latch_w(u16 data);
TILE_GET_INFO_MEMBER(get_playfield_tile_info);
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void klax_map(address_map &map);
};
class klax_bootleg_state : public klax_state
{
public:
klax_bootleg_state(const machine_config &mconfig, device_type type, const char *tag)
: klax_state(mconfig, type, tag)
, m_audiocpu(*this, "audiocpu")
, m_msm(*this, "msm%u", 1)
, m_rombank(*this, "rombank")
, m_audio_ram(*this, "audioram")
{ }
void klax5bl(machine_config &config);
protected:
virtual void machine_start() override;
private:
void m5205_int1(int state);
void bootleg_sound_map(address_map &map);
void klax5bl_map(address_map &map);
u16 audio_ram_r(offs_t offset);
void audio_ram_w(offs_t offset, u16 data);
void audio_sample_w(offs_t offset, u8 data);
void audio_ctrl_w(u8 data);
required_device<cpu_device> m_audiocpu;
required_device_array<msm5205_device, 2> m_msm;
required_memory_bank m_rombank;
required_shared_ptr<u8> m_audio_ram;
u8 m_audio_sample[2]{};
bool m_audio_nibble = false;
};
// video
/*************************************
*
* Tilemap callbacks
*
*************************************/
TILE_GET_INFO_MEMBER(klax_state::get_playfield_tile_info)
{
const u16 data1 = m_playfield_tilemap->basemem_read(tile_index);
const u16 data2 = m_playfield_tilemap->extmem_read(tile_index) >> 8;
const u32 code = data1 & 0x1fff;
const u32 color = data2 & 0x0f;
tileinfo.set(0, code, color, (data1 >> 15) & 1);
}
/*************************************
*
* Video system start
*
*************************************/
const atari_motion_objects_config klax_state::s_mob_config =
{
1, // index to which gfx system
1, // number of motion object banks
1, // are the entries linked?
0, // are the entries split?
0, // render in reverse order?
0, // render in swapped X/Y order?
0, // does the neighbor bit affect the next object?
8, // pixels per SLIP entry (0 for no-slip)
0, // pixel offset for SLIPs
0, // maximum number of links to visit/scanline (0=all)
0x000, // base palette entry
0x100, // maximum number of colors
0, // transparent pen index
{{ 0x00ff,0,0,0 }}, // mask for the link
{{ 0,0x0fff,0,0 }}, // mask for the code index
{{ 0,0,0x000f,0 }}, // mask for the color
{{ 0,0,0xff80,0 }}, // mask for the X position
{{ 0,0,0,0xff80 }}, // mask for the Y position
{{ 0,0,0,0x0070 }}, // mask for the width, in tiles
{{ 0,0,0,0x0007 }}, // mask for the height, in tiles
{{ 0,0,0,0x0008 }}, // mask for the horizontal flip
{{ 0 }}, // mask for the vertical flip
{{ 0 }}, // mask for the priority
{{ 0 }}, // mask for the neighbor
{{ 0 }}, // mask for absolute coordinates
{{ 0 }}, // mask for the special value
0 // resulting value to indicate "special"
};
/*************************************
*
* Latch write handler
*
*************************************/
void klax_state::latch_w(u16 data)
{
}
/*************************************
*
* Main refresh
*
*************************************/
u32 klax_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// start drawing
m_mob->draw_async(cliprect);
// draw the playfield
m_playfield_tilemap->draw(screen, bitmap, cliprect, 0, 0);
// draw and merge the MO
bitmap_ind16 &mobitmap = m_mob->bitmap();
for (const sparse_dirty_rect *rect = m_mob->first_dirty_rect(cliprect); rect != nullptr; rect = rect->next())
for (int y = rect->top(); y <= rect->bottom(); y++)
{
u16 const *const mo = &mobitmap.pix(y);
u16 *const pf = &bitmap.pix(y);
for (int x = rect->left(); x <= rect->right(); x++)
if (mo[x] != 0xffff)
{
/* verified from schematics:
PFPRI if (PFS7-4 == 0 || LBPIX3-0 == 0)
*/
if ((pf[x] & 0xf0) != 0xf0)
pf[x] = mo[x];
}
}
return 0;
}
// machine
/*************************************
*
@ -39,9 +232,9 @@
TIMER_DEVICE_CALLBACK_MEMBER(klax_state::scanline_update)
{
int scanline = param;
const int scanline = param;
/* generate 32V signals */
// generate 32V signals
if ((scanline & 32) == 0 && !m_screen->vblank() && !(m_p1->read() & 0x800))
m_maincpu->set_input_line(M68K_IRQ_4, ASSERT_LINE);
}
@ -78,10 +271,6 @@ void klax_bootleg_state::m5205_int1(int state)
*
*************************************/
void klax_state::machine_reset()
{
}
void klax_bootleg_state::machine_start()
{
m_rombank->configure_entries(0, 4, memregion("audiocpu")->base(), 0x8000);
@ -172,8 +361,8 @@ INPUT_PORTS_END
*************************************/
static GFXDECODE_START( gfx_klax )
GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x4_packed_msb, 256, 16 ) /* playfield */
GFXDECODE_ENTRY( "gfx2", 0, gfx_8x8x4_packed_msb, 0, 16 ) /* sprites */
GFXDECODE_ENTRY( "tiles", 0, gfx_8x8x4_packed_msb, 256, 16 )
GFXDECODE_ENTRY( "sprites", 0, gfx_8x8x4_packed_msb, 0, 16 )
GFXDECODE_END
static const gfx_layout bootleg_layout =
@ -188,8 +377,8 @@ static const gfx_layout bootleg_layout =
};
static GFXDECODE_START( gfx_klax5bl )
GFXDECODE_ENTRY( "gfx1", 0, bootleg_layout, 256, 16 ) /* playfield */
GFXDECODE_ENTRY( "gfx2", 0, gfx_8x8x4_packed_msb, 0, 16 ) /* sprites */
GFXDECODE_ENTRY( "tiles", 0, bootleg_layout, 256, 16 )
GFXDECODE_ENTRY( "sprites", 0, gfx_8x8x4_packed_msb, 0, 16 )
GFXDECODE_END
@ -201,13 +390,13 @@ GFXDECODE_END
void klax_state::klax_base(machine_config &config)
{
/* basic machine hardware */
M68000(config, m_maincpu, 14.318181_MHz_XTAL/2);
// basic machine hardware
M68000(config, m_maincpu, 14.318181_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &klax_state::klax_map);
EEPROM_2816(config, "eeprom").lock_after_write(true);
/* video hardware */
// video hardware
GFXDECODE(config, m_gfxdecode, "palette", gfx_klax);
PALETTE(config, "palette").set_format(palette_device::IRGB_1555, 512).set_membits(8);
@ -219,9 +408,9 @@ void klax_state::klax_base(machine_config &config)
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_video_attributes(VIDEO_UPDATE_BEFORE_VBLANK);
/* note: these parameters are from published specs, not derived */
/* the board uses an SOS-2 chip to generate video signals */
m_screen->set_raw(14.318181_MHz_XTAL/2, 456, 0, 336, 262, 0, 240);
/* note: these parameters are from published specs, not derived
the board uses an SOS-2 chip to generate video signals */
m_screen->set_raw(14.318181_MHz_XTAL / 2, 456, 0, 336, 262, 0, 240);
m_screen->set_screen_update(FUNC(klax_state::screen_update));
m_screen->set_palette("palette");
m_screen->screen_vblank().set_inputline(m_maincpu, M68K_IRQ_4, ASSERT_LINE);
@ -250,7 +439,7 @@ void klax_bootleg_state::bootleg_sound_map(address_map &map)
map(0x3800, 0x3800).nopw(); // ?
map(0x4f00, 0x4f7f).ram().share(m_audio_ram);
map(0x4f80, 0x4fff).ram();
map(0x8000, 0xffff).bankr("rombank");
map(0x8000, 0xffff).bankr(m_rombank);
}
void klax_bootleg_state::klax5bl(machine_config &config)
@ -259,40 +448,40 @@ void klax_bootleg_state::klax5bl(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &klax_bootleg_state::klax5bl_map);
Z80(config, m_audiocpu, 14.318181_MHz_XTAL / 2); /* ? */
Z80(config, m_audiocpu, 14.318181_MHz_XTAL / 2); // ?
m_audiocpu->set_addrmap(AS_PROGRAM, &klax_bootleg_state::bootleg_sound_map);
m_mob->set_origin(8, 7); // sprites are offset in bootlegs
m_gfxdecode->set_info(gfx_klax5bl);
MSM5205(config, m_msm[0], 384000); // clock speed / prescaler not verified
MSM5205(config, m_msm[0], 384'000); // clock speed / prescaler not verified
m_msm[0]->vck_callback().set(FUNC(klax_bootleg_state::m5205_int1));
m_msm[0]->set_prescaler_selector(msm5205_device::S64_4B); /* ? */
m_msm[0]->set_prescaler_selector(msm5205_device::S64_4B); // ?
m_msm[0]->add_route(ALL_OUTPUTS, "mono", 1.00);
MSM5205(config, m_msm[1], 384000);
MSM5205(config, m_msm[1], 384'000);
m_msm[1]->set_prescaler_selector(msm5205_device::S64_4B);
m_msm[1]->add_route(ALL_OUTPUTS, "mono", 1.00);
}
uint16_t klax_bootleg_state::audio_ram_r(offs_t offset)
u16 klax_bootleg_state::audio_ram_r(offs_t offset)
{
return (m_audio_ram[offset << 1] << 8) | m_audio_ram[(offset << 1) | 1];
}
void klax_bootleg_state::audio_ram_w(offs_t offset, uint16_t data)
void klax_bootleg_state::audio_ram_w(offs_t offset, u16 data)
{
m_audio_ram[offset << 1] = data >> 8;
m_audio_ram[(offset << 1) | 1] = data & 0xff;
}
void klax_bootleg_state::audio_sample_w(offs_t offset, uint8_t data)
void klax_bootleg_state::audio_sample_w(offs_t offset, u8 data)
{
if (offset & 2) m_audio_sample[0] = data;
if (offset & 1) m_audio_sample[1] = data;
}
void klax_bootleg_state::audio_ctrl_w(uint8_t data)
void klax_bootleg_state::audio_ctrl_w(u8 data)
{
m_rombank->set_entry(data & 3);
@ -311,27 +500,27 @@ void klax_bootleg_state::audio_ctrl_w(uint8_t data)
*************************************/
ROM_START( klax )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "136075-6006.3n", 0x00000, 0x10000, CRC(e8991709) SHA1(90d69b0712e68e842a8b946539f1f43ef165e8de) )
ROM_LOAD16_BYTE( "136075-6005.1n", 0x00001, 0x10000, CRC(72b8c510) SHA1(f79d3a2de4deaabbcec632e8be9a1d5f6c0c3740) )
ROM_LOAD16_BYTE( "136075-6008.3k", 0x20000, 0x10000, CRC(c7c91a9d) SHA1(9f79ca689ec635f8113a74162e81f253c88992f5) )
ROM_LOAD16_BYTE( "136075-6007.1k", 0x20001, 0x10000, CRC(d2021a88) SHA1(0f8a0dcc3bb5ca433601b1abfc796c98791facf6) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -341,27 +530,27 @@ ROM_END
ROM_START( klax5 )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "13607-5006.3n", 0x00000, 0x10000, CRC(05c98fc0) SHA1(84880d3d65c46c96c739063b3f61b1663989c56e) )
ROM_LOAD16_BYTE( "13607-5005.1n", 0x00001, 0x10000, CRC(d461e1ee) SHA1(73e8615a742555f74c1086c0b745afc7e94a478f) )
ROM_LOAD16_BYTE( "13607-5008.3k", 0x20000, 0x10000, CRC(f1b8e588) SHA1(080511f90aecb7526ab2107c196e73cb881a2bb5) )
ROM_LOAD16_BYTE( "13607-5007.1k", 0x20001, 0x10000, CRC(adbe33a8) SHA1(c6c4f9ea5224169dbf4dda1062954563ebab18d4) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -370,7 +559,7 @@ ROM_START( klax5 )
ROM_END
ROM_START( klax5bl ) // derived from 'klax5' set
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "6.bin", 0x00000, 0x10000, CRC(3cfd2748) SHA1(165c446bab9df6517746451d056330386cb5212c) )
ROM_LOAD16_BYTE( "2.bin", 0x00001, 0x10000, CRC(910e5bf9) SHA1(2b5af427e7cbad8d4ed2a202900f227295e1dea9) )
ROM_LOAD16_BYTE( "5.bin", 0x20000, 0x10000, CRC(4fcacf88) SHA1(4ad87b03ac4cdf763586f8bf5d54bee950b6779c) )
@ -380,19 +569,19 @@ ROM_START( klax5bl ) // derived from 'klax5' set
ROM_LOAD( "3.bin", 0x00000, 0x10000, CRC(b0441f1c) SHA1(edced52b86641ce6db934ba05435f1221a12809a) )
ROM_LOAD( "4.bin", 0x10000, 0x10000, CRC(a245e005) SHA1(8843edfa9deec405f491647d40007d0a38c25262) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD32_BYTE( "11.bin", 0x00000, 0x10000, CRC(ef7712fd) SHA1(9308b37a8b024837b32d10e358a5205fdc582214) )
ROM_LOAD32_BYTE( "12.bin", 0x00001, 0x10000, CRC(1e0c1262) SHA1(960d61b9751276e4d0dbfd3f07cadc1329079abc) )
ROM_LOAD32_BYTE( "9.bin", 0x00002, 0x10000, CRC(ebe4bd96) SHA1(31f941e39aeaed6a64b35827df4d234cd641b47d) )
ROM_LOAD32_BYTE( "10.bin", 0x00003, 0x10000, CRC(e7ad1cbd) SHA1(4b37cbe5d3168e532b00e8e34e7b8cf6d69e3487) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "7.bin", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "8.bin", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_END
ROM_START( klax5bl2 ) // derived from 'klax5' set, closer than klax5bl
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "3.ic31", 0x00000, 0x10000, CRC(e43699f3) SHA1(2a78959ad065e1c0f69cc2ba4146a50102ccfd7e) )
ROM_LOAD16_BYTE( "1.ic13", 0x00001, 0x10000, CRC(dc67f13a) SHA1(6021f48b53f9000983bcd786b8366ba8638174de) )
ROM_LOAD16_BYTE( "4.ic30", 0x20000, 0x10000, CRC(f1b8e588) SHA1(080511f90aecb7526ab2107c196e73cb881a2bb5) )
@ -402,13 +591,13 @@ ROM_START( klax5bl2 ) // derived from 'klax5' set, closer than klax5bl
ROM_LOAD( "6.ic22", 0x00000, 0x10000, CRC(edd4c42c) SHA1(22f992615afa24a7a671ed2f5cf08f25965d5b3a) ) // likely a bad dump of "3.bin" from klax5bl
ROM_LOAD( "5.ic23", 0x10000, 0x10000, CRC(a245e005) SHA1(8843edfa9deec405f491647d40007d0a38c25262) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD32_BYTE( "12.ic134", 0x00000, 0x10000, CRC(ef7712fd) SHA1(9308b37a8b024837b32d10e358a5205fdc582214) )
ROM_LOAD32_BYTE( "11.ic135", 0x00001, 0x10000, CRC(c2d8ce0c) SHA1(6b2f3c3f5f238dc00501646230dc8787dd862ed4) )
ROM_LOAD32_BYTE( "8.ic116", 0x00002, 0x10000, CRC(ebe4bd96) SHA1(31f941e39aeaed6a64b35827df4d234cd641b47d) )
ROM_LOAD32_BYTE( "7.ic117", 0x00003, 0x10000, CRC(3b79c0d3) SHA1(f6910f2526e1d92eae260b5eb73b1672db891f4b) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "10.ic101", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "9.ic102", 0x00001, 0x10000, CRC(29708e34) SHA1(6bea1527ad941fbb1abfad59ef3d78900dcd7f27) )
@ -420,7 +609,7 @@ ROM_START( klax5bl2 ) // derived from 'klax5' set, closer than klax5bl
ROM_END
ROM_START( klax5bl3 ) // almost identical to klax5bl2, only the first audiocpu ROM differs
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "3.ic31", 0x00000, 0x10000, CRC(e43699f3) SHA1(2a78959ad065e1c0f69cc2ba4146a50102ccfd7e) )
ROM_LOAD16_BYTE( "1.ic13", 0x00001, 0x10000, CRC(dc67f13a) SHA1(6021f48b53f9000983bcd786b8366ba8638174de) )
ROM_LOAD16_BYTE( "4.ic30", 0x20000, 0x10000, CRC(f1b8e588) SHA1(080511f90aecb7526ab2107c196e73cb881a2bb5) )
@ -430,13 +619,13 @@ ROM_START( klax5bl3 ) // almost identical to klax5bl2, only the first audiocpu R
ROM_LOAD( "6.ic22", 0x00000, 0x10000, CRC(d2c40941) SHA1(34d35d9333c315e116198aebc7db00fce6ccceb0) )
ROM_LOAD( "5.ic23", 0x10000, 0x10000, CRC(a245e005) SHA1(8843edfa9deec405f491647d40007d0a38c25262) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD32_BYTE( "12.ic134", 0x00000, 0x10000, CRC(ef7712fd) SHA1(9308b37a8b024837b32d10e358a5205fdc582214) )
ROM_LOAD32_BYTE( "11.ic135", 0x00001, 0x10000, CRC(c2d8ce0c) SHA1(6b2f3c3f5f238dc00501646230dc8787dd862ed4) )
ROM_LOAD32_BYTE( "8.ic116", 0x00002, 0x10000, CRC(ebe4bd96) SHA1(31f941e39aeaed6a64b35827df4d234cd641b47d) )
ROM_LOAD32_BYTE( "7.ic117", 0x00003, 0x10000, CRC(3b79c0d3) SHA1(f6910f2526e1d92eae260b5eb73b1672db891f4b) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "10.ic101", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "9.ic102", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
@ -451,27 +640,27 @@ ROM_START( klax5bl3 ) // almost identical to klax5bl2, only the first audiocpu R
ROM_END
ROM_START( klax4 )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "136075-5006.3n", 0x00000, 0x10000, CRC(65eb9a31) SHA1(3f47d58fe9eb154ab14ac282919f92679b5c7922) )
ROM_LOAD16_BYTE( "136075-5005.1n", 0x00001, 0x10000, CRC(7be27349) SHA1(79eef2b7f4a0fb6991d81f6543d5ae00de9f2452) )
ROM_LOAD16_BYTE( "136075-4008.3k", 0x20000, 0x10000, CRC(f3c79106) SHA1(c315159020d5bc6f919c3fb975fb8b228584f88c) )
ROM_LOAD16_BYTE( "136075-4007.1k", 0x20001, 0x10000, CRC(a23cde5d) SHA1(51afadc900524d73ff7906b003fdf801f5d1f1fd) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -480,27 +669,27 @@ ROM_START( klax4 )
ROM_END
ROM_START( klaxj4 )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "136075-4406.3n", 0x00000, 0x10000, CRC(fc4045ec) SHA1(58441ffeb58c1dc9ef18f3c6381eec52923ffe03) )
ROM_LOAD16_BYTE( "136075-4405.1n", 0x00001, 0x10000, CRC(f017461a) SHA1(a0acd66a48c2a964c3e8f2bdacd94908bfc84843) )
ROM_LOAD16_BYTE( "136075-4408.3k", 0x20000, 0x10000, CRC(23231159) SHA1(a0ac57d358078f7fbec95964a2608213f79e4b6f) )
ROM_LOAD16_BYTE( "136075-4407.1k", 0x20001, 0x10000, CRC(8d8158b2) SHA1(299570f16a6019c34f210bffe39ff8489f3f11f1) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -509,27 +698,27 @@ ROM_START( klaxj4 )
ROM_END
ROM_START( klaxj3 )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "136075-3406.3n", 0x00000, 0x10000, CRC(ab2aa50b) SHA1(0ebffc8b4724eb8c4423e0b1f62b0fff7cc30aab) )
ROM_LOAD16_BYTE( "136075-3405.1n", 0x00001, 0x10000, CRC(9dc9a590) SHA1(4c77b1ad9c083325f33520f2b6aa598dde247ad8) )
ROM_LOAD16_BYTE( "136075-2408.3k", 0x20000, 0x10000, CRC(89d515ce) SHA1(4991b859a53f34776671f660dbdb18a746259549) )
ROM_LOAD16_BYTE( "136075-2407.1k", 0x20001, 0x10000, CRC(48ce4edb) SHA1(014f879298408295a338c19c2d518524b41491cb) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -539,27 +728,27 @@ ROM_END
ROM_START( klaxd2 )
ROM_REGION( 0x40000, "maincpu", 0 ) /* 4*64k for 68000 code */
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
ROM_LOAD16_BYTE( "136075-2206.3n", 0x00000, 0x10000, CRC(9d1a713b) SHA1(6e60a43934bd8959c5c07dd12e087c63ea791bb9) )
ROM_LOAD16_BYTE( "136075-1205.1n", 0x00001, 0x10000, CRC(45065a5a) SHA1(77339ca04e54a04489ce9d6e11816475e57d1311) )
ROM_LOAD16_BYTE( "136075-1208.3k", 0x20000, 0x10000, CRC(b4019b32) SHA1(83fba82a9100af14cddd812be9f3dbd58d8511d2) )
ROM_LOAD16_BYTE( "136075-1207.1k", 0x20001, 0x10000, CRC(14550a75) SHA1(35599a339e6978682a09db4fb78c76bb3d3b6bc7) )
ROM_REGION( 0x40000, "gfx1", 0 )
ROM_REGION( 0x40000, "tiles", 0 )
ROM_LOAD16_BYTE( "136075-2010.17x", 0x00000, 0x10000, CRC(15290a0d) SHA1(e1338f3fb298aae19735548f4b597d1c33944960) )
ROM_LOAD16_BYTE( "136075-2009.17u", 0x00001, 0x10000, CRC(6368dbaf) SHA1(fa8b5cf6777108c0b1e38a3650ee4cdb2ec76810) )
ROM_LOAD16_BYTE( "136075-2012.12x", 0x20000, 0x10000, CRC(c0d9eb0f) SHA1(aa68b9ad435eeaa8b43693e237cc7f9a53d94dfc) )
ROM_LOAD16_BYTE( "136075-2011.12u", 0x20001, 0x10000, CRC(e83cca91) SHA1(45f1155d51ab3e2cc08aad1ec4e557d132085cc6) )
ROM_REGION( 0x20000, "gfx2", 0 )
ROM_REGION( 0x20000, "sprites", 0 )
ROM_LOAD16_BYTE( "136075-2014.17y", 0x00000, 0x10000, CRC(5c551e92) SHA1(cbff8fc4f4d370b6db2b4953ecbedd249916b891) )
ROM_LOAD16_BYTE( "136075-2013.17w", 0x00001, 0x10000, CRC(36764bbc) SHA1(5762996a327b5f7f93f42dad7eccb6297b3e4c0b) )
ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM data */
ROM_REGION( 0x40000, "oki", 0 ) // ADPCM data
ROM_LOAD( "136075-1015.14b", 0x00000, 0x10000, CRC(4d24c768) SHA1(da102105a4d8c552e3594b8ffb1903ecbaa69415) )
ROM_LOAD( "136075-1016.12b", 0x10000, 0x10000, CRC(12e9b4b7) SHA1(2447f116cd865e46e61022143a2668beca99d5d1) )
ROM_REGION( 0x00573, "pals", 0 ) /* Lattice GAL16V8A-25LP GAL's */
ROM_REGION( 0x00573, "pals", 0 ) // Lattice GAL16V8A-25LP GALs
ROM_LOAD( "136075-1000.11c.bin", 0x0000, 0x0117, CRC(fb86e94a) SHA1(b16f037c49766ab734e47c8e1b16b5178809b8a3) )
ROM_LOAD( "136075-1001.18l.bin", 0x0000, 0x0117, CRC(cd21acfe) SHA1(14bd9e2f1b50a1da550933e3fdc16e3f09b65e92) )
ROM_LOAD( "136075-1002.8w.bin", 0x0000, 0x0117, CRC(4a7b6c44) SHA1(9579e098af3e5cd19bd14c361d3b1c5cb9047171) )
@ -567,6 +756,8 @@ ROM_START( klaxd2 )
ROM_LOAD( "136075-1004.6w.bin", 0x0000, 0x0117, CRC(6cd3270d) SHA1(84854b5beee539a80fc94f6e4637aa1c2543a1cb) )
ROM_END
} // anonymous namespace
/*************************************
*

View File

@ -1,95 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*************************************************************************
Atari Klax hardware
*************************************************************************/
#ifndef MAME_ATARI_KLAX_H
#define MAME_ATARI_KLAX_H
#pragma once
#include "machine/timer.h"
#include "sound/msm5205.h"
#include "atarimo.h"
#include "screen.h"
#include "tilemap.h"
class klax_state : public driver_device
{
public:
klax_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_gfxdecode(*this, "gfxdecode")
, m_screen(*this, "screen")
, m_playfield_tilemap(*this, "playfield")
, m_mob(*this, "mob")
, m_p1(*this, "P1")
{ }
void klax_base(machine_config &config);
void klax(machine_config &config);
protected:
virtual void machine_reset() override;
TIMER_DEVICE_CALLBACK_MEMBER(scanline_update);
void interrupt_ack_w(u16 data = 0);
void latch_w(u16 data);
TILE_GET_INFO_MEMBER(get_playfield_tile_info);
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void klax_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<screen_device> m_screen;
required_device<tilemap_device> m_playfield_tilemap;
required_device<atari_motion_objects_device> m_mob;
required_ioport m_p1;
static const atari_motion_objects_config s_mob_config;
};
class klax_bootleg_state : public klax_state
{
public:
klax_bootleg_state(const machine_config &mconfig, device_type type, const char *tag)
: klax_state(mconfig, type, tag)
, m_audiocpu(*this, "audiocpu")
, m_msm(*this, "msm%u", 1)
, m_rombank(*this, "rombank")
, m_audio_ram(*this, "audioram")
{ }
void klax5bl(machine_config &config);
protected:
virtual void machine_start() override;
private:
void m5205_int1(int state);
void bootleg_sound_map(address_map &map);
void klax5bl_map(address_map &map);
uint16_t audio_ram_r(offs_t offset);
void audio_ram_w(offs_t offset, uint16_t data);
void audio_sample_w(offs_t offset, uint8_t data);
void audio_ctrl_w(uint8_t data);
required_device<cpu_device> m_audiocpu;
required_device_array<msm5205_device, 2> m_msm;
required_memory_bank m_rombank;
required_shared_ptr<uint8_t> m_audio_ram;
uint8_t m_audio_sample[2]{};
bool m_audio_nibble = false;
};
#endif // MAME_ATARI_KLAX_H

View File

@ -1,115 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
Atari Klax hardware
****************************************************************************/
#include "emu.h"
#include "atarimo.h"
#include "klax.h"
/*************************************
*
* Tilemap callbacks
*
*************************************/
TILE_GET_INFO_MEMBER(klax_state::get_playfield_tile_info)
{
const u16 data1 = m_playfield_tilemap->basemem_read(tile_index);
const u16 data2 = m_playfield_tilemap->extmem_read(tile_index) >> 8;
const u32 code = data1 & 0x1fff;
const u32 color = data2 & 0x0f;
tileinfo.set(0, code, color, (data1 >> 15) & 1);
}
/*************************************
*
* Video system start
*
*************************************/
const atari_motion_objects_config klax_state::s_mob_config =
{
1, /* index to which gfx system */
1, /* number of motion object banks */
1, /* are the entries linked? */
0, /* are the entries split? */
0, /* render in reverse order? */
0, /* render in swapped X/Y order? */
0, /* does the neighbor bit affect the next object? */
8, /* pixels per SLIP entry (0 for no-slip) */
0, /* pixel offset for SLIPs */
0, /* maximum number of links to visit/scanline (0=all) */
0x000, /* base palette entry */
0x100, /* maximum number of colors */
0, /* transparent pen index */
{{ 0x00ff,0,0,0 }}, /* mask for the link */
{{ 0,0x0fff,0,0 }}, /* mask for the code index */
{{ 0,0,0x000f,0 }}, /* mask for the color */
{{ 0,0,0xff80,0 }}, /* mask for the X position */
{{ 0,0,0,0xff80 }}, /* mask for the Y position */
{{ 0,0,0,0x0070 }}, /* mask for the width, in tiles*/
{{ 0,0,0,0x0007 }}, /* mask for the height, in tiles */
{{ 0,0,0,0x0008 }}, /* mask for the horizontal flip */
{{ 0 }}, /* mask for the vertical flip */
{{ 0 }}, /* mask for the priority */
{{ 0 }}, /* mask for the neighbor */
{{ 0 }}, /* mask for absolute coordinates */
{{ 0 }}, /* mask for the special value */
0 /* resulting value to indicate "special" */
};
/*************************************
*
* Latch write handler
*
*************************************/
void klax_state::latch_w(u16 data)
{
}
/*************************************
*
* Main refresh
*
*************************************/
u32 klax_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// start drawing
m_mob->draw_async(cliprect);
/* draw the playfield */
m_playfield_tilemap->draw(screen, bitmap, cliprect, 0, 0);
// draw and merge the MO
bitmap_ind16 &mobitmap = m_mob->bitmap();
for (const sparse_dirty_rect *rect = m_mob->first_dirty_rect(cliprect); rect != nullptr; rect = rect->next())
for (int y = rect->top(); y <= rect->bottom(); y++)
{
u16 const *const mo = &mobitmap.pix(y);
u16 *const pf = &bitmap.pix(y);
for (int x = rect->left(); x <= rect->right(); x++)
if (mo[x] != 0xffff)
{
/* verified from schematics:
PFPRI if (PFS7-4 == 0 || LBPIX3-0 == 0)
*/
if ((pf[x] & 0xf0) != 0xf0)
pf[x] = mo[x];
}
}
return 0;
}

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Stefan Jokisch
/***************************************************************************
Atari Liberator hardware
@ -137,12 +138,411 @@
#include "emu.h"
#include "liberatr.h"
#include "cpu/m6502/m6502.h"
#include "machine/74259.h"
#include "machine/er2055.h"
#include "machine/rescap.h"
#include "machine/watchdog.h"
#include "sound/pokey.h"
#include "screen.h"
#include "speaker.h"
#define MASTER_CLOCK 20000000 /* 20Mhz Main Clock Xtal */
namespace {
class liberatr_state : public driver_device
{
public:
liberatr_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_earom(*this, "earom")
, m_outlatch(*this, "outlatch")
, m_screen(*this, "screen")
, m_base_ram(*this, "base_ram")
, m_planet_frame(*this, "planet_frame")
, m_xcoord(*this, "xcoord")
, m_ycoord(*this, "ycoord")
, m_bitmapram(*this, "bitmapram")
, m_colorram(*this, "colorram")
, m_videoram(*this, "videoram", 0x10000, ENDIANNESS_LITTLE)
, m_fake(*this, "FAKE")
, m_in0(*this, "IN0")
, m_earom_data(0)
, m_earom_control(0)
{ }
void liberat2(machine_config &config);
void liberatr(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
private:
// vector and early raster EAROM interface
required_device<er2055_device> m_earom;
required_device<ls259_device> m_outlatch;
required_device<screen_device> m_screen;
required_shared_ptr<uint8_t> m_base_ram;
required_shared_ptr<uint8_t> m_planet_frame;
required_shared_ptr<uint8_t> m_xcoord;
required_shared_ptr<uint8_t> m_ycoord;
required_shared_ptr<uint8_t> m_bitmapram;
required_shared_ptr<uint8_t> m_colorram;
memory_share_creator<uint8_t> m_videoram;
required_ioport m_fake;
required_ioport m_in0;
uint8_t m_earom_data = 0U;
uint8_t m_earom_control = 0U;
uint8_t m_trackball_offset = 0U;
uint8_t m_ctrld = 0U;
bool m_planet_select = false;
// The following structure describes the (up to 32) line segments
// that make up one horizontal line (latitude) for one display frame of the planet.
// Note: this and the following structure are only used to collect the
// data before it is packed for actual use.
struct planet_frame_line
{
uint8_t segment_count; // the number of segments on this line
uint8_t max_x; // the maximum value of x_array for this line
uint8_t color_array[32]; // the color values
uint8_t x_array[32]; // and maximum x values for each segment
};
// The following structure describes the lines (latitudes)
// that make up one complete display frame of the planet.
// Note: this and the previous structure are only used to collect the
// data before it is packed for actual use.
struct planet_frame
{
planet_frame_line lines[0x80];
};
// The following structure collects the 256 frames of the
// planet (one per value of longitude).
// The data is packed segment_count,segment_start,color,length,color,length,... then
// segment_count,segment_start,color,length,color,length... for the next line, etc
// for the 128 lines.
struct planet
{
std::unique_ptr<uint8_t []> frames[256];
};
// The following array collects the 2 different planet
// descriptions, which are selected by planetbit
planet m_planets[2]{};
static constexpr uint8_t NUM_PENS = 0x18;
void output_latch_w(offs_t offset, uint8_t data);
DECLARE_WRITE_LINE_MEMBER(coin_counter_left_w);
DECLARE_WRITE_LINE_MEMBER(coin_counter_right_w);
DECLARE_WRITE_LINE_MEMBER(trackball_reset_w);
uint8_t port0_r();
void bitmap_w(offs_t offset, uint8_t data);
uint8_t bitmap_xy_r();
void bitmap_xy_w(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
// early raster EAROM interface
uint8_t earom_r();
void earom_w(offs_t offset, uint8_t data);
void earom_control_w(uint8_t data);
void liberat2_map(address_map &map);
void liberatr_map(address_map &map);
void init_planet(planet &liberatr_planet, uint8_t *planet_rom);
void get_pens(pen_t *pens);
void draw_planet(bitmap_rgb32 &bitmap, pen_t *pens);
void draw_bitmap(bitmap_rgb32 &bitmap, pen_t *pens);
};
// video
/***************************************************************************
Liberator's screen is 256 pixels by 256 pixels. The
round planet in the middle of the screen is 128 pixels
tall by 96 equivalent (192 at double pixel rate). The
emulator needs to account for the aspect ratio of 4/3
from the arcade video system in order to make the planet
appear round.
***************************************************************************/
void liberatr_state::bitmap_xy_w(uint8_t data)
{
m_videoram[(*m_ycoord << 8) | *m_xcoord] = data & 0xe0;
}
uint8_t liberatr_state::bitmap_xy_r()
{
return m_videoram[(*m_ycoord << 8) | *m_xcoord];
}
void liberatr_state::bitmap_w(offs_t offset, uint8_t data)
{
m_bitmapram[offset] = data;
offset += 3;
uint8_t const x = (offset & 0x3f) << 2;
uint8_t const y = offset >> 6;
data = data & 0xe0;
m_videoram[(y << 8) | x | 0] = data;
m_videoram[(y << 8) | x | 1] = data;
m_videoram[(y << 8) | x | 2] = data;
m_videoram[(y << 8) | x | 3] = data;
}
/********************************************************************************************
init_planet()
The data for the planet is stored in ROM using a run-length type of encoding. This
function does the conversion to the above structures and then a smaller
structure which is quicker to use in real time.
It's a multi-step process, reflecting the history of the code. Not quite as efficient
as it might be, but this is not realtime stuff, so who cares...
********************************************************************************************/
void liberatr_state::init_planet(planet &liberatr_planet, uint8_t *planet_rom)
{
const uint8_t *const latitude_scale = memregion("latitude_scaler")->base();
const uint8_t *const longitude_scale = memregion("longitude_scaler")->base();
// for each starting longitude
for (uint16_t longitude = 0; longitude < 0x100; longitude++)
{
planet_frame frame;
uint16_t total_segment_count = 0;
// for each latitude
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
uint8_t x_array[32], color_array[32], visible_array[32];
// point to the structure which will hold the data for this line
planet_frame_line *line = &frame.lines[latitude];
uint8_t latitude_scale_factor = latitude_scale[latitude];
// for this latitude, load the 32 segments into the arrays
for (uint8_t segment = 0; segment < 0x20; segment++)
{
// read the planet picture ROM and get the latitude and longitude scaled from the scaling PROMS
uint16_t address = (latitude << 5) + segment;
uint16_t const planet_data = (planet_rom[address] << 8) | planet_rom[address + 0x1000];
uint8_t const color = (planet_data >> 8) & 0x0f;
uint16_t const length = ((planet_data << 1) & 0x1fe) + ((planet_data >> 15) & 0x01);
// scale the longitude limit (adding the starting longitude)
address = longitude + (length >> 1) + (length & 1); // shift with rounding
visible_array[segment] = BIT(address, 8);
uint8_t longitude_scale_factor;
if (address & 0x80)
{
longitude_scale_factor = 0xff;
}
else
{
address = ((address & 0x7f) << 1) + (((length & 1) || visible_array[segment]) ? 0 : 1);
longitude_scale_factor = longitude_scale[address];
}
x_array[segment] = (((uint16_t)latitude_scale_factor * (uint16_t)longitude_scale_factor) + 0x80) >> 8; // round it
color_array[segment] = color;
}
// determine which segment is the western horizon and leave 'start_segment' indexing it.
uint8_t start_segment;
for (start_segment = 0; start_segment < 0x1f; start_segment++) // if not found, 'start_segment' = 0x1f
if (visible_array[start_segment]) break;
// transfer from the temporary arrays to the structure
line->max_x = (latitude_scale_factor * 0xc0) >> 8;
if (line->max_x & 1)
line->max_x += 1; // make it even
/*
as part of the quest to reduce memory usage (and to a lesser degree
execution time), stitch together segments that have the same color
*/
uint8_t segment = start_segment;
uint8_t segment_count = 0;
uint8_t i = 0;
uint8_t x = 0;
do
{
uint8_t color = color_array[segment];
while (color == color_array[segment])
{
x = x_array[segment];
segment = (segment + 1) & 0x1f;
if (segment == start_segment)
break;
}
line->color_array[i] = color;
line->x_array[i] = (x > line->max_x) ? line->max_x : x;
i++;
segment_count++;
} while ((i < 32) && (x <= line->max_x));
total_segment_count += segment_count;
line->segment_count = segment_count;
}
/* now that the all the lines have been processed, and we know how
many segments it will take to store the description, allocate the
space for it and copy the data to it.
*/
liberatr_planet.frames[longitude] = std::make_unique<uint8_t []>(2 * (128 + total_segment_count));
uint8_t *buffer = liberatr_planet.frames[longitude].get();
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
planet_frame_line *line = &frame.lines[latitude];
uint8_t const segment_count = line->segment_count;
*buffer++ = segment_count;
/* calculate the bitmap's x coordinate for the western horizon
center of bitmap - (the number of planet pixels) / 4 */
*buffer++ = (m_screen->width() / 2) - ((line->max_x + 2) / 4);
for (uint8_t i = 0, last_x = 0; i < segment_count; i++)
{
uint8_t const current_x = (line->x_array[i] + 1) / 2;
*buffer++ = line->color_array[i];
*buffer++ = current_x - last_x;
last_x = current_x;
}
}
}
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void liberatr_state::video_start()
{
// for each planet in the planet ROMs
init_planet(m_planets[0], &memregion("planet")->base()[0x2000]);
init_planet(m_planets[1], &memregion("planet")->base()[0x0000]);
save_item(NAME(m_planet_select));
}
void liberatr_state::get_pens(pen_t *pens)
{
for (offs_t i = 0; i < NUM_PENS; i++)
{
/* handle the hardware flip of the bit order from 765 to 576 that
hardware does between VRAM and color RAM */
static const offs_t penmap[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
0x10, 0x12, 0x14, 0x16, 0x11, 0x13, 0x15, 0x17 };
uint8_t const data = m_colorram[i];
// scale it from 0x00-0xff
uint8_t r = ((~data >> 3) & 0x07) * 0x24 + 3; if (r == 3) r = 0;
uint8_t g = ((~data >> 0) & 0x07) * 0x24 + 3; if (g == 3) g = 0;
uint8_t b = ((~data >> 5) & 0x06) * 0x24 + 3; if (b == 3) b = 0;
pens[penmap[i]] = rgb_t(r, g, b);
}
}
void liberatr_state::draw_planet(bitmap_rgb32 &bitmap, pen_t *pens)
{
uint8_t const *buffer = m_planets[m_planet_select].frames[*m_planet_frame].get();
// for each latitude
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
// grab the color value for the base (if any) at this latitude
uint8_t const base_color = m_base_ram[latitude >> 3] ^ 0x0f;
uint8_t const segment_count = *buffer++;
uint8_t x = *buffer++;
uint8_t const y = 64 + latitude;
// run through the segments, drawing its color until its x_array value comes up.
for (uint8_t segment = 0; segment < segment_count; segment++)
{
uint8_t color = *buffer++;
uint8_t const segment_length = *buffer++;
if ((color & 0x0c) == 0x0c)
color = base_color;
for (uint8_t i = 0; i < segment_length; i++, x++)
bitmap.pix(y, x) = pens[color];
}
}
}
void liberatr_state::draw_bitmap(bitmap_rgb32 &bitmap, pen_t *pens)
{
for (offs_t offs = 0; offs < 0x10000; offs++)
{
uint8_t const data = m_videoram[offs];
uint8_t const y = offs >> 8;
uint8_t const x = offs & 0xff;
if (data)
bitmap.pix(y, x) = pens[(data >> 5) | 0x10];
}
}
uint32_t liberatr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
pen_t pens[NUM_PENS];
get_pens(pens);
bitmap.fill(rgb_t::black(), cliprect);
draw_planet(bitmap, pens);
draw_bitmap(bitmap, pens);
return 0;
}
// machine
void liberatr_state::machine_start()
{
@ -151,7 +551,6 @@ void liberatr_state::machine_start()
save_item(NAME(m_trackball_offset));
save_item(NAME(m_ctrld));
save_item(NAME(m_videoram));
}
@ -197,12 +596,12 @@ WRITE_LINE_MEMBER(liberatr_state::coin_counter_right_w)
WRITE_LINE_MEMBER(liberatr_state::trackball_reset_w)
{
/* on the rising edge of /ctrld, the /ld signal on the LS191 is released and the value of the switches */
/* input becomes the starting point for the trackball counters */
/* on the rising edge of /ctrld, the /ld signal on the LS191 is released and the value of the switches
input becomes the starting point for the trackball counters */
if (!m_ctrld && state)
{
uint8_t trackball = ioport("FAKE")->read();
uint8_t switches = ioport("IN0")->read();
uint8_t const trackball = m_fake->read();
uint8_t const switches = m_in0->read();
m_trackball_offset = ((trackball & 0xf0) - (switches & 0xf0)) | ((trackball - switches) & 0x0f);
}
m_ctrld = state;
@ -211,16 +610,16 @@ WRITE_LINE_MEMBER(liberatr_state::trackball_reset_w)
uint8_t liberatr_state::port0_r()
{
/* if ctrld is high, the /ld signal on the LS191 is NOT set, meaning that the trackball is counting */
// if ctrld is high, the /ld signal on the LS191 is NOT set, meaning that the trackball is counting
if (m_ctrld)
{
uint8_t trackball = ioport("FAKE")->read();
uint8_t const trackball = m_fake->read();
return ((trackball & 0xf0) - (m_trackball_offset & 0xf0)) | ((trackball - m_trackball_offset) & 0x0f);
}
/* otherwise, the LS191 is simply passing through the raw switch inputs */
// otherwise, the LS191 is simply passing through the raw switch inputs
else
return ioport("IN0")->read();
return m_in0->read();
}
@ -276,18 +675,18 @@ void liberatr_state::earom_control_w(uint8_t data)
void liberatr_state::liberatr_map(address_map &map)
{
map(0x0000, 0x0000).ram().share("xcoord");
map(0x0001, 0x0001).ram().share("ycoord");
map(0x0000, 0x0000).ram().share(m_xcoord);
map(0x0001, 0x0001).ram().share(m_ycoord);
map(0x0002, 0x0002).rw(FUNC(liberatr_state::bitmap_xy_r), FUNC(liberatr_state::bitmap_xy_w));
map(0x0003, 0x3fff).ram().w(FUNC(liberatr_state::bitmap_w)).share("bitmapram");
map(0x0003, 0x3fff).ram().w(FUNC(liberatr_state::bitmap_w)).share(m_bitmapram);
map(0x4000, 0x403f).r(FUNC(liberatr_state::earom_r));
map(0x5000, 0x5000).r(FUNC(liberatr_state::port0_r));
map(0x5001, 0x5001).portr("IN1");
map(0x6000, 0x600f).nopr().writeonly().share("base_ram");
map(0x6200, 0x621f).nopr().writeonly().share("colorram");
map(0x6000, 0x600f).nopr().writeonly().share(m_base_ram);
map(0x6200, 0x621f).nopr().writeonly().share(m_colorram);
map(0x6400, 0x6400).nopw();
map(0x6600, 0x6600).w(FUNC(liberatr_state::earom_control_w));
map(0x6800, 0x6800).writeonly().share("planet_frame");
map(0x6800, 0x6800).writeonly().share(m_planet_frame);
map(0x6a00, 0x6a00).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x6c00, 0x6c07).w(FUNC(liberatr_state::output_latch_w));
map(0x6e00, 0x6e3f).nopr().w(FUNC(liberatr_state::earom_w));
@ -307,19 +706,19 @@ void liberatr_state::liberatr_map(address_map &map)
void liberatr_state::liberat2_map(address_map &map)
{
map(0x0000, 0x0000).ram().share("xcoord");
map(0x0001, 0x0001).ram().share("ycoord");
map(0x0000, 0x0000).ram().share(m_xcoord);
map(0x0001, 0x0001).ram().share(m_ycoord);
map(0x0002, 0x0002).rw(FUNC(liberatr_state::bitmap_xy_r), FUNC(liberatr_state::bitmap_xy_w));
map(0x0003, 0x3fff).ram().w(FUNC(liberatr_state::bitmap_w)).share("bitmapram");
map(0x0003, 0x3fff).ram().w(FUNC(liberatr_state::bitmap_w)).share(m_bitmapram);
map(0x4000, 0x4000).r(FUNC(liberatr_state::port0_r));
map(0x4001, 0x4001).portr("IN1");
map(0x4002, 0x400f).nopr();
map(0x4000, 0x400f).writeonly().share("base_ram");
map(0x4200, 0x421f).nopr().writeonly().share("colorram");
map(0x4000, 0x400f).writeonly().share(m_base_ram);
map(0x4200, 0x421f).nopr().writeonly().share(m_colorram);
map(0x4400, 0x4400).nopw();
map(0x4600, 0x4600).w(FUNC(liberatr_state::earom_control_w));
map(0x4800, 0x483f).r(FUNC(liberatr_state::earom_r));
map(0x4800, 0x4800).writeonly().share("planet_frame");
map(0x4800, 0x4800).writeonly().share(m_planet_frame);
map(0x4a00, 0x4a00).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x4c00, 0x4c07).w(FUNC(liberatr_state::output_latch_w));
map(0x4e00, 0x4e3f).nopr().w(FUNC(liberatr_state::earom_w));
@ -339,7 +738,7 @@ void liberatr_state::liberat2_map(address_map &map)
*************************************/
static INPUT_PORTS_START( liberatr )
PORT_START("IN0") /* IN0 - $5000 */
PORT_START("IN0") // IN0 - $5000
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 )
@ -351,7 +750,7 @@ static INPUT_PORTS_START( liberatr )
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_SERVICE( 0x80, IP_ACTIVE_LOW )
PORT_START("IN1") /* IN1 - $5001 */
PORT_START("IN1") // IN1 - $5001
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 )
@ -361,7 +760,7 @@ static INPUT_PORTS_START( liberatr )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_CUSTOM ) PORT_VBLANK("screen")
PORT_START("DSW1") /* IN2 - Game Option switches DSW @ D4 on PCB */
PORT_START("DSW1") // IN2 - Game Option switches DSW @ D4 on PCB
PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) )
PORT_DIPSETTING( 0x00, "4" )
PORT_DIPSETTING( 0x01, "5" )
@ -384,7 +783,7 @@ static INPUT_PORTS_START( liberatr )
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("DSW2") /* IN3 - Pricing Option switches DSW @ A4 on PCB */
PORT_START("DSW2") // IN3 - Pricing Option switches DSW @ A4 on PCB
PORT_DIPNAME( 0x03, 0x02, DEF_STR( Coinage ) )
PORT_DIPSETTING( 0x03, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x02, DEF_STR( 1C_1C ) )
@ -398,7 +797,7 @@ static INPUT_PORTS_START( liberatr )
PORT_DIPNAME( 0x10, 0x00, "Left Coin" )
PORT_DIPSETTING ( 0x00, "*1" )
PORT_DIPSETTING ( 0x10, "*2" )
/* TODO: verify the following settings */
// TODO: verify the following settings
PORT_DIPNAME( 0xe0, 0x00, "Bonus Coins" )
PORT_DIPSETTING ( 0x00, DEF_STR( None ) )
PORT_DIPSETTING ( 0x80, "1 each 5" )
@ -409,7 +808,7 @@ static INPUT_PORTS_START( liberatr )
PORT_DIPSETTING ( 0xc0, "Freeze Mode" )
PORT_DIPSETTING ( 0xe0, "Freeze Mode" )
PORT_START("FAKE") /* IN4 - FAKE - overlaps IN0 in the HW */
PORT_START("FAKE") // IN4 - FAKE - overlaps IN0 in the HW
PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(30) PORT_KEYDELTA(10)
PORT_BIT( 0xf0, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(30) PORT_KEYDELTA(10)
INPUT_PORTS_END
@ -423,8 +822,10 @@ INPUT_PORTS_END
void liberatr_state::liberatr(machine_config &config)
{
/* basic machine hardware */
m6502_device &maincpu(M6502(config, "maincpu", MASTER_CLOCK/16)); /* 1.25Mhz divided from 20Mhz master clock */
constexpr XTAL MASTER_CLOCK = 20_MHz_XTAL;
// basic machine hardware
m6502_device &maincpu(M6502(config, "maincpu", MASTER_CLOCK / 16)); // 1.25Mhz divided from 20Mhz master clock
maincpu.set_addrmap(AS_PROGRAM, &liberatr_state::liberatr_map);
maincpu.set_periodic_int(FUNC(liberatr_state::irq0_line_hold), attotime::from_hz(4*60));
@ -442,23 +843,23 @@ void liberatr_state::liberatr(machine_config &config)
WATCHDOG_TIMER(config, "watchdog");
/* video hardware */
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate
m_screen->set_screen_update(FUNC(liberatr_state::screen_update));
m_screen->set_size(256,256);
m_screen->set_size(256, 256);
m_screen->set_visarea(8, 247, 13, 244);
/* sound hardware */
// sound hardware
SPEAKER(config, "mono").front_center();
pokey_device &pokey1(POKEY(config, "pokey1", MASTER_CLOCK/16)); /* 1.25Mhz from Phi2 signal from 6502 */
pokey_device &pokey1(POKEY(config, "pokey1", MASTER_CLOCK / 16)); // 1.25Mhz from Phi2 signal from 6502
pokey1.allpot_r().set_ioport("DSW2");
pokey1.set_output_opamp_low_pass(RES_K(4.7), CAP_U(0.01), 5.0);
pokey1.add_route(ALL_OUTPUTS, "mono", 0.50);
pokey_device &pokey2(POKEY(config, "pokey2", MASTER_CLOCK/16)); /* 1.25Mhz from Phi2 signal from 6502 */
pokey_device &pokey2(POKEY(config, "pokey2", MASTER_CLOCK / 16)); // 1.25Mhz from Phi2 signal from 6502
pokey2.set_output_opamp_low_pass(RES_K(4.7), CAP_U(0.01), 5.0);
pokey2.allpot_r().set_ioport("DSW1");
pokey2.add_route(ALL_OUTPUTS, "mono", 0.50);
@ -468,7 +869,7 @@ void liberatr_state::liberat2(machine_config &config)
{
liberatr(config);
/* basic machine hardware */
// basic machine hardware
subdevice<m6502_device>("maincpu")->set_addrmap(AS_PROGRAM, &liberatr_state::liberat2_map);
}
@ -481,7 +882,7 @@ void liberatr_state::liberat2(machine_config &config)
*************************************/
ROM_START( liberatr )
ROM_REGION( 0x10000, "maincpu", 0 ) /* 64k for code and data */
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "136012.206", 0x8000, 0x1000, CRC(1a0cb4a0) SHA1(595828a07af729a84aab4e0b51e873046b56b419) )
ROM_LOAD( "136012.205", 0x9000, 0x1000, CRC(2f071920) SHA1(8764f3e78451c4968bffb7c7f72d1ed862f4b185) )
ROM_LOAD( "136012.204", 0xa000, 0x1000, CRC(bcc91827) SHA1(3bfbe1f1db58437ccd204a857e58695f56819649) )
@ -489,57 +890,58 @@ ROM_START( liberatr )
ROM_LOAD( "136012.202", 0xc000, 0x1000, CRC(569ba7ea) SHA1(4812b255886204192ab999d1370550d48438ea81) )
ROM_LOAD( "136012.201", 0xd000, 0x1000, CRC(d12cd6d0) SHA1(94474429cbcdbb406eb045152fb158e2a23cd26d) )
ROM_LOAD( "136012.200", 0xe000, 0x1000, CRC(1e98d21a) SHA1(92c7cc033c78ae0ce8127d49debe62263404feb1) )
ROM_RELOAD( 0xf000, 0x1000 ) /* for interrupt/reset vectors */
ROM_RELOAD( 0xf000, 0x1000 ) // for interrupt/reset vectors
ROM_REGION( 0x4000, "gfx1", 0 ) /* planet image, used at runtime */
ROM_REGION( 0x4000, "planet", 0 ) // used at runtime
ROM_LOAD( "136012.110", 0x0000, 0x1000, CRC(6eb11221) SHA1(355b71812a18cbb2ee4dc20b3622fca1c96e4570) )
ROM_LOAD( "136012.107", 0x1000, 0x1000, CRC(8a616a63) SHA1(76794cc4e11048bb6f2628bd8b84c9a7e2e82551) )
ROM_LOAD( "136012.108", 0x2000, 0x1000, CRC(3f8e4cf6) SHA1(a9d0feb0892f343687e00b96f05adb423ee4d659) )
ROM_LOAD( "136012.109", 0x3000, 0x1000, CRC(dda0c0ef) SHA1(6e547c07c1abd17383a4389b0b4ced442ed65ce7) )
ROM_REGION( 0x100, "user1", 0 ) /* latitude scaler */
ROM_REGION( 0x100, "latitude_scaler", 0 ) /* latitude scaler */
ROM_LOAD_NIB_LOW ( "136012.123", 0x0000, 0x0100, CRC(b8c806e0) SHA1(19b1b9796e1e9a42899a92ec53288d17d5d15fb3) )
ROM_LOAD_NIB_HIGH( "136012.124", 0x0000, 0x0100, CRC(e51ec78f) SHA1(224237370c418361a00d62a77d39fa494e7d8831) )
ROM_REGION( 0x100, "user2", 0 ) /* longitude scaler */
ROM_REGION( 0x100, "longitude_scaler", 0 ) /* longitude scaler */
ROM_LOAD_NIB_LOW ( "136012.125", 0x0000, 0x0100, CRC(52ac8dd9) SHA1(125d54b562d079b974f2562e71ab7c7a0b97e709) )
ROM_LOAD_NIB_HIGH( "136012.126", 0x0000, 0x0100, CRC(2e670aa6) SHA1(a6bcc49d0948d2dfe497c5e3ad4a834fa78f779a) )
ROM_REGION( 0x200, "proms", 0 )
ROM_LOAD( "136012.021", 0x0000, 0x0100, CRC(ffdcd7bc) SHA1(2ce733203d628e299ec4fb93db8be1598b49142c) ) /* write protect PROM */
ROM_LOAD( "136012.022", 0x0100, 0x0100, CRC(3353edce) SHA1(915308b11096fc1d02acf9b4af806a2a935dd748) ) /* sync PROM */
ROM_LOAD( "136012.021", 0x0000, 0x0100, CRC(ffdcd7bc) SHA1(2ce733203d628e299ec4fb93db8be1598b49142c) ) // write protect PROM
ROM_LOAD( "136012.022", 0x0100, 0x0100, CRC(3353edce) SHA1(915308b11096fc1d02acf9b4af806a2a935dd748) ) // sync PROM
ROM_END
ROM_START( liberatr2 )
ROM_REGION( 0x10000, "maincpu", 0 ) /* 64k for code and data */
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "l6.bin", 0x6000, 0x1000, CRC(78093d06) SHA1(0f6ca01e27b32aae384a6ab67a6f14eedd3f1d9c) )
ROM_LOAD( "l5.bin", 0x7000, 0x1000, CRC(988db636) SHA1(8fdd07b397d4bef108aafb10c06c2fd53fc1f99a) )
ROM_LOAD( "l4.bin", 0x8000, 0x1000, CRC(ec114540) SHA1(eb35510b59f5e9624c3d94fb16dacb4968349030) )
ROM_LOAD( "l3.bin", 0x9000, 0x1000, CRC(184c751f) SHA1(e020d2943be89f244c1aeeb34a28b7aa7dbc1454) )
ROM_LOAD( "l2.bin", 0xa000, 0x1000, CRC(c3f61f88) SHA1(a56ce094fe7374d3ac341d5eb9e06df083e16b1f) )
ROM_LOAD( "l1.bin", 0xb000, 0x1000, CRC(ef6e9f9e) SHA1(b1f7cc9e0a2ea08ec89428ad31161ac81e7faaaf) )
ROM_RELOAD( 0xf000, 0x1000 ) /* for interrupt/reset vectors */
ROM_RELOAD( 0xf000, 0x1000 ) // for interrupt/reset vectors
ROM_REGION( 0x4000, "gfx1", 0 ) /* planet image, used at runtime */
ROM_REGION( 0x4000, "planet", 0 ) // used at runtime
ROM_LOAD( "136012.110", 0x0000, 0x1000, CRC(6eb11221) SHA1(355b71812a18cbb2ee4dc20b3622fca1c96e4570) )
ROM_LOAD( "136012.107", 0x1000, 0x1000, CRC(8a616a63) SHA1(76794cc4e11048bb6f2628bd8b84c9a7e2e82551) )
ROM_LOAD( "136012.108", 0x2000, 0x1000, CRC(3f8e4cf6) SHA1(a9d0feb0892f343687e00b96f05adb423ee4d659) )
ROM_LOAD( "136012.109", 0x3000, 0x1000, CRC(dda0c0ef) SHA1(6e547c07c1abd17383a4389b0b4ced442ed65ce7) )
ROM_REGION( 0x100, "user1", 0 ) /* latitude scaler */
ROM_REGION( 0x100, "latitude_scaler", 0 )
ROM_LOAD_NIB_LOW ( "136012.123", 0x0000, 0x0100, CRC(b8c806e0) SHA1(19b1b9796e1e9a42899a92ec53288d17d5d15fb3) )
ROM_LOAD_NIB_HIGH( "136012.124", 0x0000, 0x0100, CRC(e51ec78f) SHA1(224237370c418361a00d62a77d39fa494e7d8831) )
ROM_REGION( 0x100, "user2", 0 ) /* longitude scaler */
ROM_REGION( 0x100, "longitude_scaler", 0 )
ROM_LOAD_NIB_LOW ( "136012.125", 0x0000, 0x0100, CRC(52ac8dd9) SHA1(125d54b562d079b974f2562e71ab7c7a0b97e709) )
ROM_LOAD_NIB_HIGH( "136012.126", 0x0000, 0x0100, CRC(2e670aa6) SHA1(a6bcc49d0948d2dfe497c5e3ad4a834fa78f779a) )
ROM_REGION( 0x200, "proms", 0 )
ROM_LOAD( "136012.021", 0x0000, 0x0100, CRC(ffdcd7bc) SHA1(2ce733203d628e299ec4fb93db8be1598b49142c) ) /* write protect PROM */
ROM_LOAD( "136012.022", 0x0100, 0x0100, CRC(3353edce) SHA1(915308b11096fc1d02acf9b4af806a2a935dd748) ) /* sync PROM */
ROM_LOAD( "136012.021", 0x0000, 0x0100, CRC(ffdcd7bc) SHA1(2ce733203d628e299ec4fb93db8be1598b49142c) ) // write protect PROM
ROM_LOAD( "136012.022", 0x0100, 0x0100, CRC(3353edce) SHA1(915308b11096fc1d02acf9b4af806a2a935dd748) ) // sync PROM
ROM_END
} // anonymous namespace
/*************************************
@ -548,5 +950,5 @@ ROM_END
*
*************************************/
GAME( 1982, liberatr, 0, liberatr, liberatr, liberatr_state, empty_init, ROT0, "Atari", "Liberator (set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
GAME( 1982, liberatr2,liberatr, liberat2, liberatr, liberatr_state, empty_init, ROT0, "Atari", "Liberator (set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
GAME( 1982, liberatr, 0, liberatr, liberatr, liberatr_state, empty_init, ROT0, "Atari", "Liberator (set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
GAME( 1982, liberatr2, liberatr, liberat2, liberatr, liberatr_state, empty_init, ROT0, "Atari", "Liberator (set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )

View File

@ -1,129 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Stefan Jokisch
/*************************************************************************
Atari Liberator hardware
*************************************************************************/
#ifndef MAME_ATARI_LIBERATR_H
#define MAME_ATARI_LIBERATR_H
#pragma once
#include "cpu/m6502/m6502.h"
#include "machine/74259.h"
#include "machine/er2055.h"
#include "machine/watchdog.h"
#include "sound/pokey.h"
#include "screen.h"
class liberatr_state : public driver_device
{
public:
liberatr_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_earom(*this, "earom")
, m_earom_data(0)
, m_earom_control(0)
, m_outlatch(*this, "outlatch")
, m_screen(*this, "screen")
, m_base_ram(*this, "base_ram")
, m_planet_frame(*this, "planet_frame")
, m_xcoord(*this, "xcoord")
, m_ycoord(*this, "ycoord")
, m_bitmapram(*this, "bitmapram")
, m_colorram(*this, "colorram")
{ }
void liberat2(machine_config &config);
void liberatr(machine_config &config);
private:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
void output_latch_w(offs_t offset, uint8_t data);
DECLARE_WRITE_LINE_MEMBER(coin_counter_left_w);
DECLARE_WRITE_LINE_MEMBER(coin_counter_right_w);
DECLARE_WRITE_LINE_MEMBER(trackball_reset_w);
uint8_t port0_r();
void bitmap_w(offs_t offset, uint8_t data);
uint8_t bitmap_xy_r();
void bitmap_xy_w(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
// early raster EAROM interface
uint8_t earom_r();
void earom_w(offs_t offset, uint8_t data);
void earom_control_w(uint8_t data);
void liberat2_map(address_map &map);
void liberatr_map(address_map &map);
// The following structure describes the (up to 32) line segments
// that make up one horizontal line (latitude) for one display frame of the planet.
// Note: this and the following structure is only used to collect the
// data before it is packed for actual use.
struct planet_frame_line
{
uint8_t segment_count; // the number of segments on this line
uint8_t max_x; // the maximum value of x_array for this line
uint8_t color_array[32]; // the color values
uint8_t x_array[32]; // and maximum x values for each segment
};
// The following structure describes the lines (latitudes)
// that make up one complete display frame of the planet.
// Note: this and the previous structure is only used to collect the
// data before it is packed for actual use.
struct planet_frame
{
planet_frame_line lines[0x80];
};
// The following structure collects the 256 frames of the
// planet (one per value of longitude).
// The data is packed segment_count,segment_start,color,length,color,length,... then
// segment_count,segment_start,color,length,color,length... for the next line, etc
// for the 128 lines.
struct planet
{
std::unique_ptr<uint8_t []> frames[256];
};
void init_planet(planet &liberatr_planet, uint8_t *planet_rom);
void get_pens(pen_t *pens);
void draw_planet(bitmap_rgb32 &bitmap, pen_t *pens);
void draw_bitmap(bitmap_rgb32 &bitmap, pen_t *pens);
// vector and early raster EAROM interface
required_device<er2055_device> m_earom;
uint8_t m_earom_data;
uint8_t m_earom_control;
required_device<ls259_device> m_outlatch;
required_device<screen_device> m_screen;
required_shared_ptr<uint8_t> m_base_ram;
required_shared_ptr<uint8_t> m_planet_frame;
required_shared_ptr<uint8_t> m_xcoord;
required_shared_ptr<uint8_t> m_ycoord;
required_shared_ptr<uint8_t> m_bitmapram;
required_shared_ptr<uint8_t> m_colorram;
uint8_t m_trackball_offset = 0U;
uint8_t m_ctrld = 0U;
uint8_t m_videoram[0x10000]{};
bool m_planet_select = false;
// The following array collects the 2 different planet
// descriptions, which are selected by planetbit
planet m_planets[2]{};
};
#endif // MAME_ATARI_LIBERATR_H

View File

@ -1,289 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Stefan Jokisch
/***************************************************************************
video/liberatr.c
Functions to emulate the video hardware of the machine.
Liberator's screen is 256 pixels by 256 pixels. The
round planet in the middle of the screen is 128 pixels
tall by 96 equivalent (192 at double pixel rate). The
emulator needs to account for the aspect ratio of 4/3
from the arcade video system in order to make the planet
appear round.
***************************************************************************/
#include "emu.h"
#include "liberatr.h"
#define NUM_PENS (0x18)
void liberatr_state::bitmap_xy_w(uint8_t data)
{
m_videoram[(*m_ycoord << 8) | *m_xcoord] = data & 0xe0;
}
uint8_t liberatr_state::bitmap_xy_r()
{
return m_videoram[(*m_ycoord << 8) | *m_xcoord];
}
void liberatr_state::bitmap_w(offs_t offset, uint8_t data)
{
uint8_t x, y;
m_bitmapram[offset] = data;
offset += 3;
x = (offset & 0x3f) << 2;
y = offset >> 6;
data = data & 0xe0;
m_videoram[(y << 8) | x | 0] = data;
m_videoram[(y << 8) | x | 1] = data;
m_videoram[(y << 8) | x | 2] = data;
m_videoram[(y << 8) | x | 3] = data;
}
/********************************************************************************************
liberatr_init_planet()
The data for the planet is stored in ROM using a run-length type of encoding. This
function does the conversion to the above structures and then a smaller
structure which is quicker to use in real time.
Its a multi-step process, reflecting the history of the code. Not quite as efficient
as it might be, but this is not realtime stuff, so who cares...
********************************************************************************************/
void liberatr_state::init_planet(planet &liberatr_planet, uint8_t *planet_rom)
{
const uint8_t *const latitude_scale = memregion("user1")->base();
const uint8_t *const longitude_scale = memregion("user2")->base();
// for each starting longitude
for (uint16_t longitude = 0; longitude < 0x100; longitude++)
{
planet_frame frame;
uint16_t total_segment_count = 0;
// for each latitude
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
uint8_t x_array[32], color_array[32], visible_array[32];
// point to the structure which will hold the data for this line
planet_frame_line *line = &frame.lines[latitude];
uint8_t latitude_scale_factor = latitude_scale[latitude];
// for this latitude, load the 32 segments into the arrays
for (uint8_t segment = 0; segment < 0x20; segment++)
{
uint16_t address;
// read the planet picture ROM and get the latitude and longitude scaled from the scaling PROMS
address = (latitude << 5) + segment;
uint16_t planet_data = (planet_rom[address] << 8) | planet_rom[address + 0x1000];
uint8_t color = (planet_data >> 8) & 0x0f;
uint16_t length = ((planet_data << 1) & 0x1fe) + ((planet_data >> 15) & 0x01);
// scale the longitude limit (adding the starting longitude)
address = longitude + (length >> 1) + (length & 1); // shift with rounding
visible_array[segment] = BIT(address, 8);
uint8_t longitude_scale_factor;
if (address & 0x80)
{
longitude_scale_factor = 0xff;
}
else
{
address = ((address & 0x7f) << 1) + (((length & 1) || visible_array[segment]) ? 0 : 1);
longitude_scale_factor = longitude_scale[address];
}
x_array[segment] = (((uint16_t)latitude_scale_factor * (uint16_t)longitude_scale_factor) + 0x80) >> 8; /* round it */
color_array[segment] = color;
}
// determine which segment is the western horizon and leave 'start_segment' indexing it.
uint8_t start_segment;
for (start_segment = 0; start_segment < 0x1f; start_segment++) // if not found, 'start_segment' = 0x1f
if (visible_array[start_segment]) break;
// transfer from the temporary arrays to the structure
line->max_x = (latitude_scale_factor * 0xc0) >> 8;
if (line->max_x & 1)
line->max_x += 1; // make it even
/*
as part of the quest to reduce memory usage (and to a lesser degree
execution time), stitch together segments that have the same color
*/
uint8_t segment = start_segment;
uint8_t segment_count = 0;
uint8_t i = 0;
uint8_t x = 0;
do
{
uint8_t color = color_array[segment];
while (color == color_array[segment])
{
x = x_array[segment];
segment = (segment+1) & 0x1f;
if (segment == start_segment)
break;
}
line->color_array[i] = color;
line->x_array[i] = (x > line->max_x) ? line->max_x : x;
i++;
segment_count++;
} while ((i < 32) && (x <= line->max_x));
total_segment_count += segment_count;
line->segment_count = segment_count;
}
/* now that the all the lines have been processed, and we know how
many segments it will take to store the description, allocate the
space for it and copy the data to it.
*/
liberatr_planet.frames[longitude] = std::make_unique<uint8_t []>(2 * (128 + total_segment_count));
uint8_t *buffer = liberatr_planet.frames[longitude].get();
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
planet_frame_line *line = &frame.lines[latitude];
uint8_t segment_count = line->segment_count;
*buffer++ = segment_count;
/* calculate the bitmap's x coordinate for the western horizon
center of bitmap - (the number of planet pixels) / 4 */
*buffer++ = (m_screen->width() / 2) - ((line->max_x + 2) / 4);
for (uint8_t i = 0, last_x = 0; i < segment_count; i++)
{
uint8_t current_x = (line->x_array[i] + 1) / 2;
*buffer++ = line->color_array[i];
*buffer++ = current_x - last_x;
last_x = current_x;
}
}
}
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void liberatr_state::video_start()
{
// for each planet in the planet ROMs
init_planet(m_planets[0], &memregion("gfx1")->base()[0x2000]);
init_planet(m_planets[1], &memregion("gfx1")->base()[0x0000]);
save_item(NAME(m_planet_select));
}
void liberatr_state::get_pens(pen_t *pens)
{
offs_t i;
for (i = 0; i < NUM_PENS; i++)
{
uint8_t r,g,b;
/* handle the hardware flip of the bit order from 765 to 576 that
hardware does between vram and color ram */
static const offs_t penmap[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
0x10, 0x12, 0x14, 0x16, 0x11, 0x13, 0x15, 0x17 };
uint8_t data = m_colorram[i];
/* scale it from 0x00-0xff */
r = ((~data >> 3) & 0x07) * 0x24 + 3; if (r == 3) r = 0;
g = ((~data >> 0) & 0x07) * 0x24 + 3; if (g == 3) g = 0;
b = ((~data >> 5) & 0x06) * 0x24 + 3; if (b == 3) b = 0;
pens[penmap[i]] = rgb_t(r, g, b);
}
}
void liberatr_state::draw_planet(bitmap_rgb32 &bitmap, pen_t *pens)
{
uint8_t const *buffer = m_planets[m_planet_select].frames[*m_planet_frame].get();
/* for each latitude */
for (uint8_t latitude = 0; latitude < 0x80; latitude++)
{
/* grab the color value for the base (if any) at this latitude */
uint8_t const base_color = m_base_ram[latitude >> 3] ^ 0x0f;
uint8_t const segment_count = *buffer++;
uint8_t x = *buffer++;
uint8_t const y = 64 + latitude;
/* run through the segments, drawing its color until its x_array value comes up. */
for (uint8_t segment = 0; segment < segment_count; segment++)
{
uint8_t color = *buffer++;
uint8_t segment_length = *buffer++;
if ((color & 0x0c) == 0x0c)
color = base_color;
for (uint8_t i = 0; i < segment_length; i++, x++)
bitmap.pix(y, x) = pens[color];
}
}
}
void liberatr_state::draw_bitmap(bitmap_rgb32 &bitmap, pen_t *pens)
{
for (offs_t offs = 0; offs < 0x10000; offs++)
{
uint8_t const data = m_videoram[offs];
uint8_t const y = offs >> 8;
uint8_t const x = offs & 0xff;
if (data)
bitmap.pix(y, x) = pens[(data >> 5) | 0x10];
}
}
uint32_t liberatr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
pen_t pens[NUM_PENS];
get_pens(pens);
bitmap.fill(rgb_t::black(), cliprect);
draw_planet(bitmap, pens);
draw_bitmap(bitmap, pens);
return 0;
}

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Philip Bennett
/***************************************************************************
Atari Metal Maniax
@ -256,12 +257,81 @@ Logic:
***************************************************************************/
#include "emu.h"
#include "metalmx.h"
#include "cage.h"
#include "cpu/adsp2100/adsp2100.h"
#include "cpu/m68000/m68020.h"
#include "cpu/tms34010/tms34010.h"
#include "cpu/dsp32/dsp32.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
namespace {
class metalmx_state : public driver_device
{
public:
metalmx_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_gsp(*this, "gsp"),
m_adsp(*this, "adsp"),
m_dsp32c(*this, "dsp32c_%u", 1U),
m_cage(*this, "cage"),
m_adsp_internal_program_ram(*this, "adsp_intprog"),
m_gsp_dram(*this, "gsp_dram"),
m_gsp_vram(*this, "gsp_vram")
{ }
void init_metalmx();
void metalmx(machine_config &config);
protected:
virtual void machine_reset() override;
virtual void video_start() override;
private:
required_device<m68ec020_device> m_maincpu;
required_device<tms34020_device> m_gsp;
required_device<adsp2105_device> m_adsp;
required_device_array<dsp32c_device, 2> m_dsp32c;
required_device<atari_cage_device> m_cage;
required_shared_ptr<uint32_t> m_adsp_internal_program_ram;
required_shared_ptr<uint32_t> m_gsp_dram;
required_shared_ptr<uint32_t> m_gsp_vram;
uint32_t unk_r();
uint32_t watchdog_r();
void shifter_w(uint32_t data);
void motor_w(uint32_t data);
void reset_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t sound_data_r(offs_t offset, uint32_t mem_mask = ~0);
void sound_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
template<int Chip> void dsp32c_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
template<int Chip> uint32_t dsp32c_r(offs_t offset, uint32_t mem_mask = ~0);
void host_gsp_w(offs_t offset, uint32_t data);
uint32_t host_gsp_r(offs_t offset);
uint32_t host_dram_r(offs_t offset);
void host_dram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t host_vram_r(offs_t offset);
void host_vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
void timer_w(offs_t offset, uint32_t data);
void cage_irq_callback(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void adsp_data_map(address_map &map);
void adsp_program_map(address_map &map);
void dsp32c_1_map(address_map &map);
void dsp32c_2_map(address_map &map);
void gsp_map(address_map &map);
void main_map(address_map &map);
};
/*************************************
*
* Forward definitions
@ -281,9 +351,9 @@ void metalmx_state::video_start()
{
}
uint32_t metalmx_state::screen_update_metalmx(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
uint32_t metalmx_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
/* TODO: TMS34020 should take care of this */
// TODO: TMS34020 should take care of this
// uint32_t *src_base = &gsp_vram[(vreg_base[0x40/4] & 0x40) ? 0x20000 : 0];
uint32_t const *const src_base = &m_gsp_vram[0];
@ -389,14 +459,12 @@ void metalmx_state::dsp32c_w(offs_t offset, uint32_t data, uint32_t mem_mask)
template<int Chip>
uint32_t metalmx_state::dsp32c_r(offs_t offset, uint32_t mem_mask)
{
uint32_t data;
offset <<= 1;
if (ACCESSING_BITS_0_15)
offset += 1;
data = m_dsp32c[Chip]->pio_r(offset);
uint32_t data = m_dsp32c[Chip]->pio_r(offset);
if (ACCESSING_BITS_16_31)
data <<= 16;
@ -481,22 +549,22 @@ void metalmx_state::main_map(address_map &map)
map(0x600000, 0x6fffff).rw(FUNC(metalmx_state::host_dram_r), FUNC(metalmx_state::host_dram_w));
map(0x700000, 0x7fffff).rw(FUNC(metalmx_state::host_vram_r), FUNC(metalmx_state::host_vram_w));
map(0x800000, 0x80001f).rw(FUNC(metalmx_state::dsp32c_r<1>), FUNC(metalmx_state::dsp32c_w<1>));
map(0x800020, 0x85ffff).noprw(); /* Unknown */
map(0x800020, 0x85ffff).noprw(); // Unknown
map(0x880000, 0x88001f).rw(FUNC(metalmx_state::dsp32c_r<0>), FUNC(metalmx_state::dsp32c_w<0>));
map(0x980000, 0x9800ff).w(FUNC(metalmx_state::reset_w));
map(0xb40000, 0xb40003).rw(FUNC(metalmx_state::sound_data_r), FUNC(metalmx_state::sound_data_w));
map(0xf00000, 0xf00003).ram(); /* Network message port */
map(0xf00000, 0xf00003).ram(); // Network message port
map(0xf02000, 0xf02003).rw(FUNC(metalmx_state::watchdog_r), FUNC(metalmx_state::shifter_w));
map(0xf03000, 0xf03003).portr("P1").w(FUNC(metalmx_state::motor_w));
map(0xf04000, 0xf04003).portr("P2");
map(0xf05000, 0xf05fff).nopw(); /* Lamps */ // f06000 = ADC // f01xxx = ADC
map(0xf19000, 0xf19003).nopw(); /* Network */
map(0xf05000, 0xf05fff).nopw(); // Lamps // f06000 = ADC // f01xxx = ADC
map(0xf19000, 0xf19003).nopw(); // Network
map(0xf1a000, 0xf1a003).nopw();
map(0xf1b000, 0xf1b003).nopw();
map(0xf1e000, 0xf1e003).ram(); /* Network status flags : 1000 = LIRQ 4000 = SFLAG 8000 = 68FLAG */
map(0xf1e000, 0xf1e003).ram(); // Network status flags : 1000 = LIRQ 4000 = SFLAG 8000 = 68FLAG
map(0xf20000, 0xf2ffff).w(FUNC(metalmx_state::timer_w));
map(0xfc0000, 0xfc1fff).ram(); /* Zero power RAM */
map(0xfd0000, 0xffffff).ram(); /* Scratch RAM */
map(0xfc0000, 0xfc1fff).ram(); // Zero power RAM
map(0xfd0000, 0xffffff).ram(); // Scratch RAM
}
@ -508,7 +576,7 @@ void metalmx_state::main_map(address_map &map)
void metalmx_state::adsp_program_map(address_map &map)
{
map(0x0000, 0x03ff).ram().share("adsp_intprog");
map(0x0000, 0x03ff).ram().share(m_adsp_internal_program_ram);
}
void metalmx_state::adsp_data_map(address_map &map)
@ -527,10 +595,10 @@ void metalmx_state::adsp_data_map(address_map &map)
void metalmx_state::gsp_map(address_map &map)
{
map(0x88800000, 0x8880001f).ram(); /* ? */
map(0x88c00000, 0x88c0001f).ram(); /* ? */
map(0xff000000, 0xff7fffff).ram().share("gsp_dram");
map(0xff800000, 0xffffffff).ram().share("gsp_vram");
map(0x88800000, 0x8880001f).ram(); // ?
map(0x88c00000, 0x88c0001f).ram(); // ?
map(0xff000000, 0xff7fffff).ram().share(m_gsp_dram);
map(0xff800000, 0xffffffff).ram().share(m_gsp_vram);
}
@ -545,11 +613,11 @@ void metalmx_state::dsp32c_1_map(address_map &map)
map.unmap_value_high();
map(0x000000, 0x03ffff).ram();
map(0x600000, 0x67ffff).ram();
map(0x700000, 0x700003).nopw(); /* LEDs? */
map(0x700000, 0x700003).nopw(); // LEDs?
map(0xa00000, 0xa00003).r(FUNC(metalmx_state::unk_r));
map(0xb00000, 0xb00003).r(FUNC(metalmx_state::unk_r));
map(0xc00000, 0xc00003).ram(); /* FIFO? */
map(0xf00000, 0xffffff).ram(); /* 3D registers */
map(0xc00000, 0xc00003).ram(); // FIFO?
map(0xf00000, 0xffffff).ram(); // 3D registers
}
/*************************************
@ -563,11 +631,11 @@ void metalmx_state::dsp32c_2_map(address_map &map)
map.unmap_value_high();
map(0x000000, 0x03ffff).ram();
map(0x600000, 0x67ffff).ram();
map(0x700000, 0x700003).nopw(); /* LEDs? */
map(0x700000, 0x700003).nopw(); // LEDs?
map(0xa00000, 0xa00003).r(FUNC(metalmx_state::unk_r));
map(0xb00000, 0xb00003).r(FUNC(metalmx_state::unk_r));
map(0xc00000, 0xc00003).ram(); /* FIFO? */
map(0xf00000, 0xffffff).ram(); /* 3D registers */
map(0xc00000, 0xc00003).ram(); // FIFO?
map(0xf00000, 0xffffff).ram(); // 3D registers
}
@ -596,7 +664,7 @@ static INPUT_PORTS_START( metalmx )
PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNKNOWN )
/* COINS */
// COINS
PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_COIN3 )
@ -606,7 +674,7 @@ static INPUT_PORTS_START( metalmx )
PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED )
/* AUX */
// AUX
PORT_BIT( 0x01000000, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x02000000, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x04000000, IP_ACTIVE_HIGH, IPT_UNKNOWN )
@ -667,17 +735,17 @@ void metalmx_state::metalmx(machine_config &config)
m_adsp->set_addrmap(AS_PROGRAM, &metalmx_state::adsp_program_map);
m_adsp->set_addrmap(AS_DATA, &metalmx_state::adsp_data_map);
TMS34020(config, m_gsp, 40000000); /* Unverified */
TMS34020(config, m_gsp, 40'000'000); // Unverified
m_gsp->set_addrmap(AS_PROGRAM, &metalmx_state::gsp_map);
m_gsp->set_halt_on_reset(true);
m_gsp->set_pixel_clock(4000000);
m_gsp->set_pixel_clock(4'000'000);
m_gsp->set_pixels_per_clock(2);
m_gsp->output_int().set_inputline("maincpu", 4);
DSP32C(config, m_dsp32c[0], 40000000); /* Unverified */
DSP32C(config, m_dsp32c[0], 40'000'000); // Unverified
m_dsp32c[0]->set_addrmap(AS_PROGRAM, &metalmx_state::dsp32c_1_map);
DSP32C(config, m_dsp32c[1], 40000000); /* Unverified */
DSP32C(config, m_dsp32c[1], 40'000'000); // Unverified
m_dsp32c[1]->set_addrmap(AS_PROGRAM, &metalmx_state::dsp32c_2_map);
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -685,7 +753,7 @@ void metalmx_state::metalmx(machine_config &config)
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
screen.set_size(512, 384);
screen.set_visarea(0, 511, 0, 383);
screen.set_screen_update(FUNC(metalmx_state::screen_update_metalmx));
screen.set_screen_update(FUNC(metalmx_state::screen_update));
screen.set_palette("palette");
PALETTE(config, "palette", palette_device::RGB_565);
@ -831,6 +899,8 @@ ROM_START( metalmx )
ROM_LOAD( "103-1116.bin", 0x000, 0x117, CRC(37edc36c) SHA1(be53131c52e84cb3fe055af5ca4e2f6aa5442ff0) )
ROM_END
} // anonymous namespace
/*************************************
*

View File

@ -1,72 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Philip Bennett
#ifndef MAME_ATARI_METALMX_H
#define MAME_ATARI_METALMX_H
#pragma once
#include "cage.h"
#include "cpu/adsp2100/adsp2100.h"
#include "cpu/m68000/m68020.h"
#include "cpu/tms34010/tms34010.h"
#include "cpu/dsp32/dsp32.h"
class metalmx_state : public driver_device
{
public:
metalmx_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_gsp(*this, "gsp"),
m_adsp(*this, "adsp"),
m_dsp32c(*this, "dsp32c_%u", 1U),
m_cage(*this, "cage"),
m_adsp_internal_program_ram(*this, "adsp_intprog"),
m_gsp_dram(*this, "gsp_dram"),
m_gsp_vram(*this, "gsp_vram")
{ }
void init_metalmx();
void metalmx(machine_config &config);
private:
uint32_t unk_r();
uint32_t watchdog_r();
void shifter_w(uint32_t data);
void motor_w(uint32_t data);
void reset_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t sound_data_r(offs_t offset, uint32_t mem_mask = ~0);
void sound_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
template<int Chip> void dsp32c_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
template<int Chip> uint32_t dsp32c_r(offs_t offset, uint32_t mem_mask = ~0);
void host_gsp_w(offs_t offset, uint32_t data);
uint32_t host_gsp_r(offs_t offset);
uint32_t host_dram_r(offs_t offset);
void host_dram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t host_vram_r(offs_t offset);
void host_vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
void timer_w(offs_t offset, uint32_t data);
void cage_irq_callback(uint8_t data);
virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update_metalmx(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void adsp_data_map(address_map &map);
void adsp_program_map(address_map &map);
void dsp32c_1_map(address_map &map);
void dsp32c_2_map(address_map &map);
void gsp_map(address_map &map);
void main_map(address_map &map);
required_device<m68ec020_device> m_maincpu;
required_device<tms34020_device> m_gsp;
required_device<adsp2105_device> m_adsp;
required_device_array<dsp32c_device, 2> m_dsp32c;
required_device<atari_cage_device> m_cage;
required_shared_ptr<uint32_t> m_adsp_internal_program_ram;
required_shared_ptr<uint32_t> m_gsp_dram;
required_shared_ptr<uint32_t> m_gsp_vram;
};
#endif // MAME_ATARI_METALMX_H

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/***************************************************************************
Atari Night Driver hardware
@ -37,15 +38,441 @@
***************************************************************************/
#include "emu.h"
#include "nitedrvr.h"
#include "nitedrvr_a.h"
#include "cpu/m6502/m6502.h"
#include "machine/rescap.h"
#include "machine/timer.h"
#include "machine/watchdog.h"
#include "sound/discrete.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
namespace {
class nitedrvr_state : public driver_device
{
public:
nitedrvr_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_discrete(*this, "discrete"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_videoram(*this, "videoram"),
m_hvc(*this, "hvc"),
m_steer(*this, "STEER"),
m_gears(*this, "GEARS"),
m_in0(*this, "IN0"),
m_dsw(*this, "DSW%u", 0U),
m_led(*this, "led"),
m_track_sel(*this, "track%u", 1U),
m_gear_sel(*this, "gear%u", 1U)
{ }
void nitedrvr(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
// devices
required_device<cpu_device> m_maincpu;
required_device<discrete_device> m_discrete;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
// memory pointers
required_shared_ptr<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_hvc;
// input
uint8_t m_gear = 0;
uint8_t m_track = 0;
int32_t m_steering_buf = 0;
int32_t m_steering_val = 0;
uint8_t m_crash_en = 0;
uint8_t m_crash_data = 0;
uint8_t m_crash_data_en = 0; // IC D8
uint8_t m_ac_line = 0;
int32_t m_last_steering_val = 0;
required_ioport m_steer, m_gears, m_in0;
required_ioport_array<3> m_dsw;
// output
output_finder<> m_led;
output_finder<3> m_track_sel;
output_finder<4> m_gear_sel;
uint8_t steering_reset_r();
void steering_reset_w(uint8_t data);
uint8_t in0_r(offs_t offset);
uint8_t in1_r(offs_t offset);
void out0_w(uint8_t data);
void out1_w(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(crash_toggle_callback);
void draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect, int bx, int by, int ex, int ey);
void draw_roadway(bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_tiles(bitmap_ind16 &bitmap, const rectangle &cliprect);
int steering();
void main_map(address_map &map);
};
// video
void nitedrvr_state::draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect, int bx, int by, int ex, int ey)
{
for (int y = by; y < ey; y++)
{
for (int x = bx; x < ex; x++)
if (cliprect.contains(x, y))
bitmap.pix(y, x) = 1;
}
}
void nitedrvr_state::draw_roadway(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int roadway = 0; roadway < 16; roadway++)
{
int const bx = m_hvc[roadway];
int const by = m_hvc[roadway + 16];
int const ex = bx + ((m_hvc[roadway + 32] & 0xf0) >> 4);
int const ey = by + (16 - (m_hvc[roadway + 32] & 0x0f));
draw_box(bitmap, cliprect, bx, by, ex, ey);
}
}
void nitedrvr_state::draw_tiles(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// draw tiles manually, note that tile rows are ignored on V&8, V&64, V&128
for (int offs = 0; offs < 0x80; offs++)
{
int const code = m_videoram[offs];
int const sx = (offs & 0x1f) * 8;
int const sy = (offs >> 5) * 2 * 8;
m_gfxdecode->gfx(0)->opaque(bitmap, cliprect, code, 0, 0, 0, sx, sy);
}
}
uint32_t nitedrvr_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
draw_tiles(bitmap, cliprect);
draw_roadway(bitmap, cliprect);
return 0;
}
// machine
/***************************************************************************
Steering
When D7 is high, the steering wheel has moved.
If D6 is low, it moved left. If D6 is high, it moved right.
Be sure to keep returning a direction until steering_reset is called,
because D6 and D7 are apparently checked at different times, and a
change in-between can affect the direction you move.
***************************************************************************/
int nitedrvr_state::steering()
{
int const this_val = m_steer->read();
int delta = this_val - m_last_steering_val;
m_last_steering_val = this_val;
if (delta > 128)
delta -= 256;
else if (delta < -128)
delta += 256;
// Divide by four to make our steering less sensitive
m_steering_buf += (delta / 4);
if (m_steering_buf > 0)
{
m_steering_buf--;
m_steering_val = 0xc0;
}
else if (m_steering_buf < 0)
{
m_steering_buf++;
m_steering_val = 0x80;
}
else
{
m_steering_val = 0x00;
}
return m_steering_val;
}
/***************************************************************************
steering_reset
***************************************************************************/
uint8_t nitedrvr_state::steering_reset_r()
{
m_steering_val = 0;
return 0;
}
void nitedrvr_state::steering_reset_w(uint8_t data)
{
m_steering_val = 0;
}
/***************************************************************************
in0_r
Night Driver looks for the following:
A: $00
D4 - OPT1
D5 - OPT2
D6 - OPT3
D7 - OPT4
A: $01
D4 - TRACK SET
D5 - BONUS TIME ALLOWED
D6 - VBLANK
D7 - !TEST
A: $02
D4 - !GEAR 1
D5 - !GEAR 2
D6 - !GEAR 3
D7 - SPARE
A: $03
D4 - SPARE
D5 - DIFFICULT BONUS
D6 - STEER A
D7 - STEER B
Fill in the steering and gear bits in a special way.
***************************************************************************/
uint8_t nitedrvr_state::in0_r(offs_t offset)
{
int const gear = m_gears->read();
if (gear & 0x10) m_gear = 1;
else if (gear & 0x20) m_gear = 2;
else if (gear & 0x40) m_gear = 3;
else if (gear & 0x80) m_gear = 4;
for (uint8_t i = 0; i < 4; i++)
m_gear_sel[i] = ((m_gear == (i + 1)) ? 1 : 0);
switch (offset & 0x03)
{
case 0x00: // No remapping necessary
return m_dsw[0]->read();
case 0x01: // No remapping necessary
return m_dsw[1]->read();
case 0x02: // Remap our gear shift
if (m_gear == 1)
return 0xe0;
else if (m_gear == 2)
return 0xd0;
else if (m_gear == 3)
return 0xb0;
else
return 0x70;
case 0x03: // Remap our steering
return (m_dsw[2]->read() | steering());
default:
return 0xff;
}
}
/***************************************************************************
in1_r
Night Driver looks for the following:
A: $00
D6 - SPARE
D7 - COIN 1
A: $01
D6 - SPARE
D7 - COIN 2
A: $02
D6 - SPARE
D7 - !START
A: $03
D6 - SPARE
D7 - !ACC
A: $04
D6 - SPARE
D7 - EXPERT
A: $05
D6 - SPARE
D7 - NOVICE
A: $06
D6 - SPARE
D7 - Special Alternating Signal
A: $07
D6 - SPARE
D7 - Ground
Fill in the track difficulty switch and special signal in a special way.
***************************************************************************/
uint8_t nitedrvr_state::in1_r(offs_t offset)
{
int const port = m_in0->read();
m_ac_line = (m_ac_line + 1) % 3;
if (port & 0x10) m_track = 0;
else if (port & 0x20) m_track = 1;
else if (port & 0x40) m_track = 2;
for (uint8_t i = 0; i < 3; i++)
m_track_sel[i] = (m_track == i ? 1 : 0);
switch (offset & 0x07)
{
case 0x00:
return ((port & 0x01) << 7);
case 0x01:
return ((port & 0x02) << 6);
case 0x02:
return ((port & 0x04) << 5);
case 0x03:
return ((port & 0x08) << 4);
case 0x04:
if (m_track == 1) return 0x80; else return 0x00;
case 0x05:
if (m_track == 0) return 0x80; else return 0x00;
case 0x06:
// TODO: fix alternating signal?
if (m_ac_line == 0) return 0x80; else return 0x00;
case 0x07:
return 0x00;
default:
return 0xff;
}
}
/***************************************************************************
out0_w
Sound bits:
D0 = !SPEED1
D1 = !SPEED2
D2 = !SPEED3
D3 = !SPEED4
D4 = SKID1
D5 = SKID2
***************************************************************************/
void nitedrvr_state::out0_w(uint8_t data)
{
m_discrete->write(NITEDRVR_MOTOR_DATA, data & 0x0f); // Motor freq data
m_discrete->write(NITEDRVR_SKID1_EN, data & 0x10); // Skid1 enable
m_discrete->write(NITEDRVR_SKID2_EN, data & 0x20); // Skid2 enable
}
/***************************************************************************
out1_w
D0 = !CRASH - also drives a video invert signal
D1 = ATTRACT
D2 = Spare (Not used)
D3 = Not used?
D4 = LED START
D5 = Spare (Not used)
***************************************************************************/
void nitedrvr_state::out1_w(uint8_t data)
{
m_led = BIT(data, 4);
m_crash_en = data & 0x01;
m_discrete->write(NITEDRVR_CRASH_EN, m_crash_en); // Crash enable
m_discrete->write(NITEDRVR_ATTRACT_EN, data & 0x02); // Attract enable (sound disable)
if (!m_crash_en)
{
// Crash reset, set counter high and enable output
m_crash_data_en = 1;
m_crash_data = 0x0f;
// Invert video
m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
}
m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data_en ? m_crash_data : 0); // Crash Volume
}
TIMER_DEVICE_CALLBACK_MEMBER(nitedrvr_state::crash_toggle_callback)
{
if (m_crash_en && m_crash_data_en)
{
m_crash_data--;
m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data); // Crash Volume
if (!m_crash_data)
m_crash_data_en = 0; // Done counting?
if (m_crash_data & 0x01)
{
// Invert video
m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
}
else
{
// Normal video
m_palette->set_pen_color(0, rgb_t(0x00,0x00,0x00)); // BLACK
m_palette->set_pen_color(1, rgb_t(0xff,0xff,0xff)); // WHITE
}
}
}
void nitedrvr_state::machine_start()
{
m_led.resolve();
m_track_sel.resolve();
m_gear_sel.resolve();
save_item(NAME(m_gear));
save_item(NAME(m_track));
save_item(NAME(m_steering_buf));
save_item(NAME(m_steering_val));
save_item(NAME(m_crash_en));
save_item(NAME(m_crash_data));
save_item(NAME(m_crash_data_en));
save_item(NAME(m_ac_line));
save_item(NAME(m_last_steering_val));
}
void nitedrvr_state::machine_reset()
{
m_gear = 1;
m_track = 0;
m_steering_buf = 0;
m_steering_val = 0;
m_crash_en = 0;
m_crash_data = 0x0f;
m_crash_data_en = 0;
m_ac_line = 0;
m_last_steering_val = 0;
}
// Memory Map
void nitedrvr_state::main_map(address_map &map)
@ -119,23 +546,10 @@ static INPUT_PORTS_START( nitedrvr )
PORT_ADJUSTER( 60, "Motor RPM" )
INPUT_PORTS_END
// Graphics Layouts
static const gfx_layout charlayout =
{
8, 8,
64,
1,
{ 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8
};
// Graphics Decode Information
static GFXDECODE_START( gfx_nitedrvr )
GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 1 )
GFXDECODE_ENTRY( "gfx", 0, gfx_8x8x1, 0, 1 )
GFXDECODE_END
// Machine Driver
@ -190,13 +604,16 @@ ROM_START( nitedrvr )
ROM_LOAD( "006570-01.f2", 0x9800, 0x0800, CRC(bf5d77b1) SHA1(6f603f8b0973bd89e0e721b66944aac8e9f904d9) ) // mask ROM 2
ROM_RELOAD( 0xf800, 0x0800 ) // vectors
ROM_REGION( 0x200, "gfx1", 0 )
ROM_REGION( 0x200, "gfx", 0 )
ROM_LOAD( "006568-01.p2", 0x0000, 0x0200, CRC(f80d8889) SHA1(ca573543dcce1221459d5693c476cef14bfac4f4) ) // PROM, Alpha-Numeric
ROM_REGION( 0x100, "proms", 0 )
ROM_REGION( 0x100, "sync_prom", 0 )
ROM_LOAD( "006559-01.h7", 0x0000, 0x0100, CRC(5a8d0e42) SHA1(772220c4c24f18769696ddba26db2bc2e5b0909d) ) // PROM, Sync
ROM_END
} // anonymous namespace
// Game Drivers
GAME( 1976, nitedrvr, 0, nitedrvr, nitedrvr, nitedrvr_state, empty_init, ROT0, "Atari", "Night Driver", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )

View File

@ -1,99 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/*************************************************************************
Atari Night Driver hardware
*************************************************************************/
#ifndef MAME_ATARI_NITEDRVR_H
#define MAME_ATARI_NITEDRVR_H
#pragma once
#include "machine/timer.h"
#include "sound/discrete.h"
#include "emupal.h"
// Discrete Sound Input Nodes
#define NITEDRVR_BANG_DATA NODE_01
#define NITEDRVR_SKID1_EN NODE_02
#define NITEDRVR_SKID2_EN NODE_03
#define NITEDRVR_MOTOR_DATA NODE_04
#define NITEDRVR_CRASH_EN NODE_05
#define NITEDRVR_ATTRACT_EN NODE_06
class nitedrvr_state : public driver_device
{
public:
nitedrvr_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_discrete(*this, "discrete"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_videoram(*this, "videoram"),
m_hvc(*this, "hvc"),
m_steer(*this, "STEER"),
m_gears(*this, "GEARS"),
m_in0(*this, "IN0"),
m_dsw(*this, "DSW%u", 0U),
m_led(*this, "led"),
m_track_sel(*this, "track%u", 1U),
m_gear_sel(*this, "gear%u", 1U)
{ }
void nitedrvr(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
uint8_t steering_reset_r();
void steering_reset_w(uint8_t data);
uint8_t in0_r(offs_t offset);
uint8_t in1_r(offs_t offset);
void out0_w(uint8_t data);
void out1_w(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(crash_toggle_callback);
void draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect, int bx, int by, int ex, int ey);
void draw_roadway(bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_tiles(bitmap_ind16 &bitmap, const rectangle &cliprect);
int steering();
void main_map(address_map &map);
// devices
required_device<cpu_device> m_maincpu;
required_device<discrete_device> m_discrete;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
// memory pointers
required_shared_ptr<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_hvc;
// input
uint8_t m_gear = 0;
uint8_t m_track = 0;
int32_t m_steering_buf = 0;
int32_t m_steering_val = 0;
uint8_t m_crash_en = 0;
uint8_t m_crash_data = 0;
uint8_t m_crash_data_en = 0; // IC D8
uint8_t m_ac_line = 0;
int32_t m_last_steering_val = 0;
required_ioport m_steer, m_gears, m_in0;
required_ioport_array<3> m_dsw;
// output
output_finder<> m_led;
output_finder<3> m_track_sel;
output_finder<4> m_gear_sel;
};
//----------- defined in audio/nitedrvr.cpp -----------
DISCRETE_SOUND_EXTERN( nitedrvr_discrete );
#endif // MAME_ATARI_NITEDRVR_H

View File

@ -1,13 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Derrick Renaud
/*************************************************************************
audio\nitedrvr.cpp
*************************************************************************/
#include "emu.h"
#include "nitedrvr.h"
#include "sound/discrete.h"
#include "nitedrvr_a.h"
// Discrete Sound Emulation

View File

@ -0,0 +1,27 @@
// license:BSD-3-Clause
// copyright-holders:Derrick Renaud
/***************************************************************************
Night Driver Audio
***************************************************************************/
#ifndef MAME_ATARI_NITEDRVR_A_H
#define MAME_ATARI_NITEDRVR_A_H
#pragma once
#include "sound/discrete.h"
// discrete sound input nodes
#define NITEDRVR_BANG_DATA NODE_01
#define NITEDRVR_SKID1_EN NODE_02
#define NITEDRVR_SKID2_EN NODE_03
#define NITEDRVR_MOTOR_DATA NODE_04
#define NITEDRVR_CRASH_EN NODE_05
#define NITEDRVR_ATTRACT_EN NODE_06
DISCRETE_SOUND_EXTERN( nitedrvr_discrete );
#endif // MAME_ATARI_NITEDRVR_A_H

View File

@ -1,308 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/***************************************************************************
Atari Night Driver hardware
***************************************************************************/
#include "emu.h"
#include "nitedrvr.h"
#include "sound/discrete.h"
/***************************************************************************
Steering
When D7 is high, the steering wheel has moved.
If D6 is low, it moved left. If D6 is high, it moved right.
Be sure to keep returning a direction until steering_reset is called,
because D6 and D7 are apparently checked at different times, and a
change in-between can affect the direction you move.
***************************************************************************/
int nitedrvr_state::steering()
{
int this_val = m_steer->read();
int delta = this_val - m_last_steering_val;
m_last_steering_val = this_val;
if (delta > 128)
delta -= 256;
else if (delta < -128)
delta += 256;
// Divide by four to make our steering less sensitive
m_steering_buf += (delta / 4);
if (m_steering_buf > 0)
{
m_steering_buf--;
m_steering_val = 0xc0;
}
else if (m_steering_buf < 0)
{
m_steering_buf++;
m_steering_val = 0x80;
}
else
{
m_steering_val = 0x00;
}
return m_steering_val;
}
/***************************************************************************
steering_reset
***************************************************************************/
uint8_t nitedrvr_state::steering_reset_r()
{
m_steering_val = 0;
return 0;
}
void nitedrvr_state::steering_reset_w(uint8_t data)
{
m_steering_val = 0;
}
/***************************************************************************
in0_r
Night Driver looks for the following:
A: $00
D4 - OPT1
D5 - OPT2
D6 - OPT3
D7 - OPT4
A: $01
D4 - TRACK SET
D5 - BONUS TIME ALLOWED
D6 - VBLANK
D7 - !TEST
A: $02
D4 - !GEAR 1
D5 - !GEAR 2
D6 - !GEAR 3
D7 - SPARE
A: $03
D4 - SPARE
D5 - DIFFICULT BONUS
D6 - STEER A
D7 - STEER B
Fill in the steering and gear bits in a special way.
***************************************************************************/
uint8_t nitedrvr_state::in0_r(offs_t offset)
{
int gear = m_gears->read();
if (gear & 0x10) m_gear = 1;
else if (gear & 0x20) m_gear = 2;
else if (gear & 0x40) m_gear = 3;
else if (gear & 0x80) m_gear = 4;
for (uint8_t i = 0; i < 4; i++)
m_gear_sel[i] = ((m_gear == (i + 1)) ? 1 : 0);
switch (offset & 0x03)
{
case 0x00: // No remapping necessary
return m_dsw[0]->read();
case 0x01: // No remapping necessary
return m_dsw[1]->read();
case 0x02: // Remap our gear shift
if (m_gear == 1)
return 0xe0;
else if (m_gear == 2)
return 0xd0;
else if (m_gear == 3)
return 0xb0;
else
return 0x70;
case 0x03: // Remap our steering
return (m_dsw[2]->read() | steering());
default:
return 0xff;
}
}
/***************************************************************************
in1_r
Night Driver looks for the following:
A: $00
D6 - SPARE
D7 - COIN 1
A: $01
D6 - SPARE
D7 - COIN 2
A: $02
D6 - SPARE
D7 - !START
A: $03
D6 - SPARE
D7 - !ACC
A: $04
D6 - SPARE
D7 - EXPERT
A: $05
D6 - SPARE
D7 - NOVICE
A: $06
D6 - SPARE
D7 - Special Alternating Signal
A: $07
D6 - SPARE
D7 - Ground
Fill in the track difficulty switch and special signal in a special way.
***************************************************************************/
uint8_t nitedrvr_state::in1_r(offs_t offset)
{
int port = m_in0->read();
m_ac_line = (m_ac_line + 1) % 3;
if (port & 0x10) m_track = 0;
else if (port & 0x20) m_track = 1;
else if (port & 0x40) m_track = 2;
for (uint8_t i = 0; i < 3; i++)
m_track_sel[i] = (m_track == i ? 1 : 0);
switch (offset & 0x07)
{
case 0x00:
return ((port & 0x01) << 7);
case 0x01:
return ((port & 0x02) << 6);
case 0x02:
return ((port & 0x04) << 5);
case 0x03:
return ((port & 0x08) << 4);
case 0x04:
if (m_track == 1) return 0x80; else return 0x00;
case 0x05:
if (m_track == 0) return 0x80; else return 0x00;
case 0x06:
// TODO: fix alternating signal?
if (m_ac_line==0) return 0x80; else return 0x00;
case 0x07:
return 0x00;
default:
return 0xff;
}
}
/***************************************************************************
out0_w
Sound bits:
D0 = !SPEED1
D1 = !SPEED2
D2 = !SPEED3
D3 = !SPEED4
D4 = SKID1
D5 = SKID2
***************************************************************************/
void nitedrvr_state::out0_w(uint8_t data)
{
m_discrete->write(NITEDRVR_MOTOR_DATA, data & 0x0f); // Motor freq data
m_discrete->write(NITEDRVR_SKID1_EN, data & 0x10); // Skid1 enable
m_discrete->write(NITEDRVR_SKID2_EN, data & 0x20); // Skid2 enable
}
/***************************************************************************
out1_w
D0 = !CRASH - also drives a video invert signal
D1 = ATTRACT
D2 = Spare (Not used)
D3 = Not used?
D4 = LED START
D5 = Spare (Not used)
***************************************************************************/
void nitedrvr_state::out1_w(uint8_t data)
{
m_led = BIT(data, 4);
m_crash_en = data & 0x01;
m_discrete->write(NITEDRVR_CRASH_EN, m_crash_en); // Crash enable
m_discrete->write(NITEDRVR_ATTRACT_EN, data & 0x02); // Attract enable (sound disable)
if (!m_crash_en)
{
// Crash reset, set counter high and enable output
m_crash_data_en = 1;
m_crash_data = 0x0f;
// Invert video
m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
}
m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data_en ? m_crash_data : 0); // Crash Volume
}
TIMER_DEVICE_CALLBACK_MEMBER(nitedrvr_state::crash_toggle_callback)
{
if (m_crash_en && m_crash_data_en)
{
m_crash_data--;
m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data); // Crash Volume
if (!m_crash_data)
m_crash_data_en = 0; // Done counting?
if (m_crash_data & 0x01)
{
// Invert video
m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
}
else
{
// Normal video
m_palette->set_pen_color(0, rgb_t(0x00,0x00,0x00)); // BLACK
m_palette->set_pen_color(1, rgb_t(0xff,0xff,0xff)); // WHITE
}
}
}
void nitedrvr_state::machine_start()
{
m_led.resolve();
m_track_sel.resolve();
m_gear_sel.resolve();
save_item(NAME(m_gear));
save_item(NAME(m_track));
save_item(NAME(m_steering_buf));
save_item(NAME(m_steering_val));
save_item(NAME(m_crash_en));
save_item(NAME(m_crash_data));
save_item(NAME(m_crash_data_en));
save_item(NAME(m_ac_line));
save_item(NAME(m_last_steering_val));
}
void nitedrvr_state::machine_reset()
{
m_gear = 1;
m_track = 0;
m_steering_buf = 0;
m_steering_val = 0;
m_crash_en = 0;
m_crash_data = 0x0f;
m_crash_data_en = 0;
m_ac_line = 0;
m_last_steering_val = 0;
}

View File

@ -1,56 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/***************************************************************************
Atari Night Driver hardware
***************************************************************************/
#include "emu.h"
#include "nitedrvr.h"
void nitedrvr_state::draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect, int bx, int by, int ex, int ey)
{
for (int y = by; y < ey; y++)
{
for (int x = bx; x < ex; x++)
if (cliprect.contains(x, y))
bitmap.pix(y, x) = 1;
}
}
void nitedrvr_state::draw_roadway(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int roadway = 0; roadway < 16; roadway++)
{
int bx = m_hvc[roadway];
int by = m_hvc[roadway + 16];
int ex = bx + ((m_hvc[roadway + 32] & 0xf0) >> 4);
int ey = by + (16 - (m_hvc[roadway + 32] & 0x0f));
draw_box(bitmap, cliprect, bx, by, ex, ey);
}
}
void nitedrvr_state::draw_tiles(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// draw tiles manually, note that tile rows are ignored on V&8, V&64, V&128
for (int offs = 0; offs < 0x80; offs++)
{
int code = m_videoram[offs];
int sx = (offs & 0x1f) * 8;
int sy = (offs >> 5) * 2 * 8;
m_gfxdecode->gfx(0)->opaque(bitmap, cliprect, code, 0, 0, 0, sx, sy);
}
}
uint32_t nitedrvr_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
draw_tiles(bitmap, cliprect);
draw_roadway(bitmap, cliprect);
return 0;
}