summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/atari/cloak.cpp388
-rw-r--r--src/mame/atari/cloak.h78
-rw-r--r--src/mame/atari/cloak_v.cpp222
-rw-r--r--src/mame/atari/cloud9.cpp473
-rw-r--r--src/mame/atari/cloud9.h88
-rw-r--r--src/mame/atari/cloud9_v.cpp298
-rw-r--r--src/mame/atari/copsnrob.cpp272
-rw-r--r--src/mame/atari/copsnrob.h73
-rw-r--r--src/mame/atari/copsnrob_a.cpp61
-rw-r--r--src/mame/atari/copsnrob_a.h32
-rw-r--r--src/mame/atari/copsnrob_v.cpp128
11 files changed, 1017 insertions, 1096 deletions
diff --git a/src/mame/atari/cloak.cpp b/src/mame/atari/cloak.cpp
index b94e285235f..7f485ac418e 100644
--- a/src/mame/atari/cloak.cpp
+++ b/src/mame/atari/cloak.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Dan Boris, Mirko Buffoni
+// copyright-holders: Dan Boris, Mirko Buffoni
+
/***************************************************************************
Atari Cloak & Dagger hardware
@@ -111,22 +112,276 @@
TODO:
- is bitmap drawing in service mode correct?
- - real cpu speeds (pokey speeds verified with comparison to recording)
+ - real CPU speeds (Pokey speeds verified with comparison to recording)
- custom write
*/
#include "emu.h"
-#include "cloak.h"
#include "cpu/m6502/m6502.h"
-#include "sound/pokey.h"
#include "machine/74259.h"
#include "machine/nvram.h"
#include "machine/rescap.h"
#include "machine/watchdog.h"
+#include "sound/pokey.h"
+#include "video/resnet.h"
+
+#include "emupal.h"
+#include "screen.h"
#include "speaker.h"
+#include "tilemap.h"
+
+
+namespace {
+
+class cloak_state : public driver_device
+{
+public:
+ cloak_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_slave(*this, "slave"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_videoram(*this, "videoram"),
+ m_spriteram(*this, "spriteram"),
+ m_bitmap_videoram(*this, "bitmap_videoram%u", 1U, 256U * 256U, ENDIANNESS_LITTLE)
+ { }
+
+ void cloak(machine_config &config);
+
+protected:
+ virtual void video_start() override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_slave;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_shared_ptr<uint8_t> m_videoram;
+ required_shared_ptr<uint8_t> m_spriteram;
+ memory_share_array_creator<uint8_t, 2> m_bitmap_videoram;
+ std::unique_ptr<uint16_t[]> m_palette_ram;
+
+ uint8_t m_nvram_enabled = 0;
+ uint8_t m_bitmap_videoram_selected = 0;
+ uint8_t m_bitmap_videoram_address_x = 0;
+ uint8_t m_bitmap_videoram_address_y = 0;
+ tilemap_t *m_bg_tilemap = nullptr;
+
+ template <uint8_t Which> DECLARE_WRITE_LINE_MEMBER(coin_counter_w);
+ void custom_w(uint8_t data);
+ void irq_reset_0_w(uint8_t data);
+ void irq_reset_1_w(uint8_t data);
+ void nvram_enable_w(uint8_t data);
+ void paletteram_w(offs_t offset, uint8_t data);
+ void clearbmp_w(uint8_t data);
+ uint8_t graph_processor_r(offs_t offset);
+ void graph_processor_w(offs_t offset, uint8_t data);
+ void videoram_w(offs_t offset, uint8_t data);
+ void adjust_xy(int offset);
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void set_pen(int i);
+ void draw_bitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void master_map(address_map &map);
+ void slave_map(address_map &map);
+};
+
+
+// video
+
+/***************************************************************************
+
+ CLOAK & DAGGER uses RAM to dynamically
+ create the palette. The resolution is 9 bit (3 bits per gun). The palette
+ contains 64 entries, but it is accessed through a memory windows 128 bytes
+ long: writing to the first 64 bytes sets the MSB of the red component to 0,
+ while writing to the last 64 bytes sets it to 1.
+
+ Colors 0-15 Character mapped graphics
+ Colors 16-31 Bitmapped graphics (2 palettes selected by 128H)
+ Colors 32-47 Sprites
+ Colors 48-63 not used
+
+ These are the exact resistor values from the schematics:
+
+ bit 8 -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- RED
+ -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- RED
+ -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- RED
+ -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- GREEN
+ -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- GREEN
+ -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- GREEN
+ -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- BLUE
+ -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- BLUE
+ bit 0 -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- BLUE
+***************************************************************************/
+
+void cloak_state::paletteram_w(offs_t offset, uint8_t data)
+{
+ m_palette_ram[offset & 0x3f] = ((offset & 0x40) << 2) | data;
+ set_pen(offset & 0x3f);
+}
+
+
+void cloak_state::set_pen(int i)
+{
+ static const int resistances[3] = { 10000, 4700, 2200 };
+ double weights[3];
+
+ // compute the color output resistor weights
+ compute_resistor_weights(0, 255, -1.0,
+ 3, resistances, weights, 0, 1000,
+ 0, nullptr, nullptr, 0, 0,
+ 0, nullptr, nullptr, 0, 0);
+
+ int bit0, bit1, bit2;
+
+ // red component
+ bit0 = (~m_palette_ram[i] >> 6) & 0x01;
+ bit1 = (~m_palette_ram[i] >> 7) & 0x01;
+ bit2 = (~m_palette_ram[i] >> 8) & 0x01;
+ int const r = combine_weights(weights, bit0, bit1, bit2);
+
+ // green component
+ bit0 = (~m_palette_ram[i] >> 3) & 0x01;
+ bit1 = (~m_palette_ram[i] >> 4) & 0x01;
+ bit2 = (~m_palette_ram[i] >> 5) & 0x01;
+ int const g = combine_weights(weights, bit0, bit1, bit2);
+
+ // blue component
+ bit0 = (~m_palette_ram[i] >> 0) & 0x01;
+ bit1 = (~m_palette_ram[i] >> 1) & 0x01;
+ bit2 = (~m_palette_ram[i] >> 2) & 0x01;
+ int const b = combine_weights(weights, bit0, bit1, bit2);
+
+ m_palette->set_pen_color(i, rgb_t(r, g, b));
+}
+
+void cloak_state::clearbmp_w(uint8_t data)
+{
+// m_screen->update_now();
+ m_screen->update_partial(m_screen->vpos());
+
+ m_bitmap_videoram_selected = data & 0x01;
+
+ if (data & 0x02) // clear
+ memset(m_bitmap_videoram[m_bitmap_videoram_selected], 0, 256*256);
+}
+
+void cloak_state::adjust_xy(int offset)
+{
+ switch (offset)
+ {
+ case 0x00: m_bitmap_videoram_address_x--; m_bitmap_videoram_address_y++; break;
+ case 0x01: m_bitmap_videoram_address_y--; break;
+ case 0x02: m_bitmap_videoram_address_x--; break;
+ case 0x04: m_bitmap_videoram_address_x++; m_bitmap_videoram_address_y++; break;
+ case 0x05: m_bitmap_videoram_address_y++; break;
+ case 0x06: m_bitmap_videoram_address_x++; break;
+ }
+}
+
+uint8_t cloak_state::graph_processor_r(offs_t offset)
+{
+ uint8_t const ret = m_bitmap_videoram[!m_bitmap_videoram_selected][(m_bitmap_videoram_address_y << 8) | m_bitmap_videoram_address_x];
+
+ adjust_xy(offset);
+
+ return ret;
+}
+
+void cloak_state::graph_processor_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0x03: m_bitmap_videoram_address_x = data; break;
+ case 0x07: m_bitmap_videoram_address_y = data; break;
+ default:
+ m_bitmap_videoram[m_bitmap_videoram_selected][(m_bitmap_videoram_address_y << 8) | m_bitmap_videoram_address_x] = data & 0x0f;
+
+ adjust_xy(offset);
+ break;
+ }
+}
+
+void cloak_state::videoram_w(offs_t offset, uint8_t data)
+{
+ m_videoram[offset] = data;
+ m_bg_tilemap->mark_tile_dirty(offset);
+}
+
+TILE_GET_INFO_MEMBER(cloak_state::get_bg_tile_info)
+{
+ int const code = m_videoram[tile_index];
+
+ tileinfo.set(0, code, 0, 0);
+}
+
+void cloak_state::video_start()
+{
+ constexpr uint8_t NUM_PENS = 0x40;
+
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(cloak_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
+
+ m_palette_ram = std::make_unique<uint16_t[]>(NUM_PENS);
+
+ save_item(NAME(m_bitmap_videoram_address_x));
+ save_item(NAME(m_bitmap_videoram_address_y));
+ save_item(NAME(m_bitmap_videoram_selected));
+ save_pointer(NAME(m_palette_ram), NUM_PENS);
+ // save_item(NAME(m_nvram_enabled));
+}
+
+void cloak_state::draw_bitmap(bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
+ for (int x = cliprect.left(); x <= cliprect.right(); x++)
+ {
+ pen_t const pen = m_bitmap_videoram[!m_bitmap_videoram_selected][(y << 8) | x] & 0x07;
+
+ if (pen)
+ bitmap.pix(y, (x - 6) & 0xff) = 0x10 | ((x & 0x80) >> 4) | pen;
+ }
+}
+
+void cloak_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ for (int offs = (0x100 / 4) - 1; offs >= 0; offs--)
+ {
+ int const code = m_spriteram[offs + 64] & 0x7f;
+ int flipx = m_spriteram[offs + 64] & 0x80;
+ int flipy = 0;
+ int sx = m_spriteram[offs + 192];
+ int sy = 240 - m_spriteram[offs];
+
+ if (flip_screen())
+ {
+ sx -= 9;
+ sy = 240 - sy;
+ flipx = !flipx;
+ flipy = !flipy;
+ }
+
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, code, 0, flipx, flipy, sx, sy, 0);
+ }
+}
+
+uint32_t cloak_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ draw_bitmap(bitmap, cliprect);
+ draw_sprites(bitmap, cliprect);
+ return 0;
+}
+
+
+// machine
/*************************************
*
@@ -134,33 +389,29 @@
*
*************************************/
-WRITE_LINE_MEMBER(cloak_state::coin_counter_l_w)
-{
- machine().bookkeeping().coin_counter_w(0, state);
-}
-
-WRITE_LINE_MEMBER(cloak_state::coin_counter_r_w)
+template <uint8_t Which>
+WRITE_LINE_MEMBER(cloak_state::coin_counter_w)
{
- machine().bookkeeping().coin_counter_w(1, state);
+ machine().bookkeeping().coin_counter_w(Which, state);
}
-void cloak_state::cloak_custom_w(uint8_t data)
+void cloak_state::custom_w(uint8_t data)
{
}
-void cloak_state::cloak_irq_reset_0_w(uint8_t data)
+void cloak_state::irq_reset_0_w(uint8_t data)
{
m_maincpu->set_input_line(0, CLEAR_LINE);
}
-void cloak_state::cloak_irq_reset_1_w(uint8_t data)
+void cloak_state::irq_reset_1_w(uint8_t data)
{
m_slave->set_input_line(0, CLEAR_LINE);
}
-void cloak_state::cloak_nvram_enable_w(uint8_t data)
+void cloak_state::nvram_enable_w(uint8_t data)
{
- m_nvram_enabled = data & 0x01;
+ m_nvram_enabled = data & 0x01; // TODO: set but never used?
}
@@ -174,22 +425,22 @@ void cloak_state::cloak_nvram_enable_w(uint8_t data)
void cloak_state::master_map(address_map &map)
{
map(0x0000, 0x03ff).ram();
- map(0x0400, 0x07ff).ram().w(FUNC(cloak_state::cloak_videoram_w)).share("videoram");
- map(0x0800, 0x0fff).ram().share("share1");
- map(0x1000, 0x100f).rw("pokey1", FUNC(pokey_device::read), FUNC(pokey_device::write)); /* DSW0 also */
- map(0x1800, 0x180f).rw("pokey2", FUNC(pokey_device::read), FUNC(pokey_device::write)); /* DSW1 also */
+ map(0x0400, 0x07ff).ram().w(FUNC(cloak_state::videoram_w)).share(m_videoram);
+ map(0x0800, 0x0fff).ram().share("shared_ram");
+ map(0x1000, 0x100f).rw("pokey1", FUNC(pokey_device::read), FUNC(pokey_device::write)); // DSW0 also
+ map(0x1800, 0x180f).rw("pokey2", FUNC(pokey_device::read), FUNC(pokey_device::write)); // DSW1 also
map(0x2000, 0x2000).portr("P1");
map(0x2200, 0x2200).portr("P2");
map(0x2400, 0x2400).portr("SYSTEM");
- map(0x2600, 0x2600).w(FUNC(cloak_state::cloak_custom_w));
+ map(0x2600, 0x2600).w(FUNC(cloak_state::custom_w));
map(0x2800, 0x29ff).ram().share("nvram");
map(0x2f00, 0x2fff).noprw();
- map(0x3000, 0x30ff).ram().share("spriteram");
- map(0x3200, 0x327f).w(FUNC(cloak_state::cloak_paletteram_w));
+ map(0x3000, 0x30ff).ram().share(m_spriteram);
+ map(0x3200, 0x327f).w(FUNC(cloak_state::paletteram_w));
map(0x3800, 0x3807).w("outlatch", FUNC(ls259_device::write_d7));
map(0x3a00, 0x3a00).w("watchdog", FUNC(watchdog_timer_device::reset_w));
- map(0x3c00, 0x3c00).w(FUNC(cloak_state::cloak_irq_reset_0_w));
- map(0x3e00, 0x3e00).w(FUNC(cloak_state::cloak_nvram_enable_w));
+ map(0x3c00, 0x3c00).w(FUNC(cloak_state::irq_reset_0_w));
+ map(0x3e00, 0x3e00).w(FUNC(cloak_state::nvram_enable_w));
map(0x4000, 0xffff).rom();
}
@@ -205,10 +456,10 @@ void cloak_state::slave_map(address_map &map)
map(0x0000, 0x0007).ram();
map(0x0008, 0x000f).rw(FUNC(cloak_state::graph_processor_r), FUNC(cloak_state::graph_processor_w));
map(0x0010, 0x07ff).ram();
- map(0x0800, 0x0fff).ram().share("share1");
- map(0x1000, 0x1000).w(FUNC(cloak_state::cloak_irq_reset_1_w));
- map(0x1200, 0x1200).w(FUNC(cloak_state::cloak_clearbmp_w));
- map(0x1400, 0x1400).w(FUNC(cloak_state::cloak_custom_w));
+ map(0x0800, 0x0fff).ram().share("shared_ram");
+ map(0x1000, 0x1000).w(FUNC(cloak_state::irq_reset_1_w));
+ map(0x1200, 0x1200).w(FUNC(cloak_state::clearbmp_w));
+ map(0x1400, 0x1400).w(FUNC(cloak_state::custom_w));
map(0x2000, 0xffff).rom();
}
@@ -303,8 +554,8 @@ static const gfx_layout spritelayout =
};
static GFXDECODE_START( gfx_cloak )
- GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 1 )
- GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 32, 1 )
+ GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 1 )
+ GFXDECODE_ENTRY( "sprites", 0, spritelayout, 32, 1 )
GFXDECODE_END
@@ -316,12 +567,12 @@ GFXDECODE_END
void cloak_state::cloak(machine_config &config)
{
- /* basic machine hardware */
- M6502(config, m_maincpu, 1000000); /* 1 MHz ???? */
+ // basic machine hardware
+ M6502(config, m_maincpu, 1'000'000); // 1 MHz ????
m_maincpu->set_addrmap(AS_PROGRAM, &cloak_state::master_map);
m_maincpu->set_periodic_int(FUNC(cloak_state::irq0_line_hold), attotime::from_hz(4*60));
- M6502(config, m_slave, 1250000); /* 1.25 MHz ???? */
+ M6502(config, m_slave, 1'250'000); // 1.25 MHz ????
m_slave->set_addrmap(AS_PROGRAM, &cloak_state::slave_map);
m_slave->set_periodic_int(FUNC(cloak_state::irq0_line_hold), attotime::from_hz(2*60));
@@ -330,37 +581,37 @@ void cloak_state::cloak(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
ls259_device &outlatch(LS259(config, "outlatch")); // 10B
- outlatch.q_out_cb<0>().set(FUNC(cloak_state::coin_counter_r_w));
- outlatch.q_out_cb<1>().set(FUNC(cloak_state::coin_counter_l_w));
- outlatch.q_out_cb<3>().set(FUNC(cloak_state::cocktail_w));
+ outlatch.q_out_cb<0>().set(FUNC(cloak_state::coin_counter_w<1>)); // right
+ outlatch.q_out_cb<1>().set(FUNC(cloak_state::coin_counter_w<0>)); // left
+ outlatch.q_out_cb<3>().set(FUNC(cloak_state::flip_screen_set));
outlatch.q_out_cb<5>().set_nop(); // ???
outlatch.q_out_cb<6>().set_output("led1").invert(); // START LED 2
outlatch.q_out_cb<7>().set_output("led0").invert(); // START LED 1
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_size(32*8, 32*8);
m_screen->set_visarea(0*8, 32*8-1, 3*8, 32*8-1);
- m_screen->set_screen_update(FUNC(cloak_state::screen_update_cloak));
+ m_screen->set_screen_update(FUNC(cloak_state::screen_update));
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_cloak);
PALETTE(config, m_palette).set_entries(64);
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "mono").front_center();
- /* more low pass filters ==> DISCRETE processing */
- pokey_device &pokey1(POKEY(config, "pokey1", XTAL(10'000'000)/8)); /* Accurate to recording */
+ // more low pass filters ==> DISCRETE processing
+ pokey_device &pokey1(POKEY(config, "pokey1", XTAL(10'000'000) / 8)); // Accurate to recording
pokey1.allpot_r().set_ioport("START");
pokey1.set_output_opamp_low_pass(RES_K(1), CAP_U(0.047), 5.0);
pokey1.add_route(ALL_OUTPUTS, "mono", 0.50);
- pokey_device &pokey2(POKEY(config, "pokey2", XTAL(10'000'000)/8)); /* Accurate to recording */
+ pokey_device &pokey2(POKEY(config, "pokey2", XTAL(10'000'000) / 8)); // Accurate to recording
pokey2.allpot_r().set_ioport("DSW");
pokey2.set_output_opamp_low_pass(RES_K(1), CAP_U(0.022), 5.0);
pokey2.add_route(ALL_OUTPUTS, "mono", 0.50);
@@ -390,16 +641,16 @@ ROM_START( cloak )
ROM_LOAD( "136023-514.bin", 0xc000, 0x2000, CRC(6f8c7991) SHA1(bd6f838b224abed78fbdb7da17baa892289fc2f2) )
ROM_LOAD( "136023-515.bin", 0xe000, 0x2000, CRC(835438a0) SHA1(27f320b74e7bdb29d4bc505432c96284f482cacc) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136023-105.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136023-106.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136023-107.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136023-108.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -419,16 +670,16 @@ ROM_START( cloaksp )
ROM_LOAD( "136023-514.bin", 0xc000, 0x2000, CRC(6f8c7991) SHA1(bd6f838b224abed78fbdb7da17baa892289fc2f2) )
ROM_LOAD( "136023-515.bin", 0xe000, 0x2000, CRC(835438a0) SHA1(27f320b74e7bdb29d4bc505432c96284f482cacc) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136023-105.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136023-106.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136023-107.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136023-108.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -448,16 +699,16 @@ ROM_START( cloakfr )
ROM_LOAD( "136023-514.bin", 0xc000, 0x2000, CRC(6f8c7991) SHA1(bd6f838b224abed78fbdb7da17baa892289fc2f2) )
ROM_LOAD( "136023-515.bin", 0xe000, 0x2000, CRC(835438a0) SHA1(27f320b74e7bdb29d4bc505432c96284f482cacc) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136023-105.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136023-106.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136023-107.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136023-108.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -477,16 +728,16 @@ ROM_START( cloakgr )
ROM_LOAD( "136023-514.bin", 0xc000, 0x2000, CRC(6f8c7991) SHA1(bd6f838b224abed78fbdb7da17baa892289fc2f2) )
ROM_LOAD( "136023-515.bin", 0xe000, 0x2000, CRC(835438a0) SHA1(27f320b74e7bdb29d4bc505432c96284f482cacc) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136023-105.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136023-106.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136023-107.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136023-108.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -506,16 +757,16 @@ ROM_START( agentx4 )
ROM_LOAD( "136414-023.bin", 0xc000, 0x2000, CRC(cadf9ab0) SHA1(d5c4c86124033f21e065e5cd9cf7a1b31d3c11a6) )
ROM_LOAD( "136415-023.bin", 0xe000, 0x2000, CRC(f5024961) SHA1(99a8b02932b497588a011fe051465407531f8a0f) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136105-023.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136106-023.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136107-023.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136108-023.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -535,16 +786,16 @@ ROM_START( agentx3 )
ROM_LOAD( "136314-023.bin", 0xc000, 0x2000, CRC(3138a3b2) SHA1(553f247a72fce176d80db7e4c7624cdb73c8c078) )
ROM_LOAD( "136315-023.bin", 0xe000, 0x2000, CRC(d12f5523) SHA1(53a7e4e360bd8c21c0e9bf408b6dd231f4fe025c) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136105-023.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136106-023.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136107-023.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136108-023.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -564,16 +815,16 @@ ROM_START( agentx2 )
ROM_LOAD( "136214-023.bin", 0xc000, 0x2000, CRC(dba311ec) SHA1(a825f013211e6eaac4c18a589b38a416dc633954) )
ROM_LOAD( "136215-023.bin", 0xe000, 0x2000, CRC(dc20c185) SHA1(5a1d3e65e543fe295c2f179f8b5c2193065af581) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136105-023.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136106-023.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136107-023.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136108-023.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
@@ -593,18 +844,19 @@ ROM_START( agentx1 )
ROM_LOAD( "136114-023.bin", 0xc000, 0x2000, CRC(7c7c905d) SHA1(eb417c5e80f1a3169c1385d7c843a3defa584b6e) )
ROM_LOAD( "136115-023.bin", 0xe000, 0x2000, CRC(7f36710c) SHA1(6d412f22e723999c641dde18a47c8d90d2ed07a3) )
- ROM_REGION( 0x2000, "gfx1", 0 )
+ ROM_REGION( 0x2000, "chars", 0 )
ROM_LOAD( "136105-023.bin", 0x0000, 0x1000, CRC(ee443909) SHA1(802c5839be9e9e33c75ca7318043ecdb7b82f721) )
ROM_LOAD( "136106-023.bin", 0x1000, 0x1000, CRC(d708b132) SHA1(d57acdcfb7b3de65f0162bdc041efff4c7eeff18) )
- ROM_REGION( 0x2000, "gfx2", 0 )
+ ROM_REGION( 0x2000, "sprites", 0 )
ROM_LOAD( "136107-023.bin", 0x0000, 0x1000, CRC(c42c84a4) SHA1(6f241e772f8b46c8d3acad2e967f1ab530886b11) )
ROM_LOAD( "136108-023.bin", 0x1000, 0x1000, CRC(4fe13d58) SHA1(b21a32b2ff5363ab35fd1438344a04deb4077dbc) )
ROM_REGION( 0x100, "proms", 0 )
- ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) /* 82S129 Vertical timing PROM */
+ ROM_LOAD( "136023-116.3n", 0x000, 0x100, CRC(ef2668e5) SHA1(442df346a40b1e20d599ed9877c699e00ab518ba) ) // 82S129 Vertical timing PROM
ROM_END
+} // anonymous namespace
/*************************************
diff --git a/src/mame/atari/cloak.h b/src/mame/atari/cloak.h
deleted file mode 100644
index 3574ee15557..00000000000
--- a/src/mame/atari/cloak.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Dan Boris, Mirko Buffoni
-/*************************************************************************
-
- Atari Cloak & Dagger hardware
-
-*************************************************************************/
-#ifndef MAME_ATARI_CLOAK_H
-#define MAME_ATARI_CLOAK_H
-
-#pragma once
-
-#include "emupal.h"
-#include "screen.h"
-#include "tilemap.h"
-
-class cloak_state : public driver_device
-{
-public:
- cloak_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_videoram(*this, "videoram"),
- m_spriteram(*this, "spriteram"),
- m_maincpu(*this, "maincpu"),
- m_slave(*this, "slave"),
- m_gfxdecode(*this, "gfxdecode"),
- m_screen(*this, "screen"),
- m_palette(*this, "palette")
- { }
-
- void cloak(machine_config &config);
-
-protected:
- DECLARE_WRITE_LINE_MEMBER(coin_counter_l_w);
- DECLARE_WRITE_LINE_MEMBER(coin_counter_r_w);
- void cloak_custom_w(uint8_t data);
- void cloak_irq_reset_0_w(uint8_t data);
- void cloak_irq_reset_1_w(uint8_t data);
- void cloak_nvram_enable_w(uint8_t data);
- void cloak_paletteram_w(offs_t offset, uint8_t data);
- void cloak_clearbmp_w(uint8_t data);
- uint8_t graph_processor_r(offs_t offset);
- void graph_processor_w(offs_t offset, uint8_t data);
- void cloak_videoram_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(cocktail_w);
- void set_current_bitmap_videoram_pointer();
- void adjust_xy(int offset);
- TILE_GET_INFO_MEMBER(get_bg_tile_info);
- virtual void video_start() override;
- uint32_t screen_update_cloak(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- void set_pen(int i);
- void draw_bitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
- void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
- void master_map(address_map &map);
- void slave_map(address_map &map);
-
-private:
- required_shared_ptr<uint8_t> m_videoram;
- required_shared_ptr<uint8_t> m_spriteram;
- int m_nvram_enabled = 0;
- uint8_t m_bitmap_videoram_selected = 0;
- uint8_t m_bitmap_videoram_address_x = 0;
- uint8_t m_bitmap_videoram_address_y = 0;
- std::unique_ptr<uint8_t[]> m_bitmap_videoram1;
- std::unique_ptr<uint8_t[]> m_bitmap_videoram2;
- uint8_t *m_current_bitmap_videoram_accessed = nullptr;
- uint8_t *m_current_bitmap_videoram_displayed = nullptr;
- std::unique_ptr<uint16_t[]> m_palette_ram;
- tilemap_t *m_bg_tilemap = nullptr;
-
- required_device<cpu_device> m_maincpu;
- required_device<cpu_device> m_slave;
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<screen_device> m_screen;
- required_device<palette_device> m_palette;
-};
-
-#endif // MAME_ATARI_CLOAK_H
diff --git a/src/mame/atari/cloak_v.cpp b/src/mame/atari/cloak_v.cpp
deleted file mode 100644
index ad06c20a283..00000000000
--- a/src/mame/atari/cloak_v.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Dan Boris, Mirko Buffoni
-/***************************************************************************
-
- Atari Cloak & Dagger hardware
-
-***************************************************************************/
-
-#include "emu.h"
-#include "video/resnet.h"
-#include "cloak.h"
-
-
-#define NUM_PENS (0x40)
-
-/***************************************************************************
-
- CLOAK & DAGGER uses RAM to dynamically
- create the palette. The resolution is 9 bit (3 bits per gun). The palette
- contains 64 entries, but it is accessed through a memory windows 128 bytes
- long: writing to the first 64 bytes sets the MSB of the red component to 0,
- while writing to the last 64 bytes sets it to 1.
-
- Colors 0-15 Character mapped graphics
- Colors 16-31 Bitmapped graphics (2 palettes selected by 128H)
- Colors 32-47 Sprites
- Colors 48-63 not used
-
- These are the exact resistor values from the schematics:
-
- bit 8 -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- RED
- -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- RED
- -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- RED
- -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- GREEN
- -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- GREEN
- -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- GREEN
- -- diode |< -- pullup 1 kohm -- 2.2 kohm resistor -- pulldown 100 pf -- BLUE
- -- diode |< -- pullup 1 kohm -- 4.7 kohm resistor -- pulldown 100 pf -- BLUE
- bit 0 -- diode |< -- pullup 1 kohm -- 10 kohm resistor -- pulldown 100 pf -- BLUE
-
-***************************************************************************/
-
-void cloak_state::cloak_paletteram_w(offs_t offset, uint8_t data)
-{
- m_palette_ram[offset & 0x3f] = ((offset & 0x40) << 2) | data;
- set_pen(offset & 0x3f);
-}
-
-
-void cloak_state::set_pen(int i)
-{
- uint16_t *palette_ram = m_palette_ram.get();
- static const int resistances[3] = { 10000, 4700, 2200 };
- double weights[3];
-
- /* compute the color output resistor weights */
- compute_resistor_weights(0, 255, -1.0,
- 3, resistances, weights, 0, 1000,
- 0, nullptr, nullptr, 0, 0,
- 0, nullptr, nullptr, 0, 0);
-
- int r, g, b;
- int bit0, bit1, bit2;
-
- /* red component */
- bit0 = (~palette_ram[i] >> 6) & 0x01;
- bit1 = (~palette_ram[i] >> 7) & 0x01;
- bit2 = (~palette_ram[i] >> 8) & 0x01;
- r = combine_weights(weights, bit0, bit1, bit2);
-
- /* green component */
- bit0 = (~palette_ram[i] >> 3) & 0x01;
- bit1 = (~palette_ram[i] >> 4) & 0x01;
- bit2 = (~palette_ram[i] >> 5) & 0x01;
- g = combine_weights(weights, bit0, bit1, bit2);
-
- /* blue component */
- bit0 = (~palette_ram[i] >> 0) & 0x01;
- bit1 = (~palette_ram[i] >> 1) & 0x01;
- bit2 = (~palette_ram[i] >> 2) & 0x01;
- b = combine_weights(weights, bit0, bit1, bit2);
-
- m_palette->set_pen_color(i, rgb_t(r, g, b));
-}
-
-
-void cloak_state::set_current_bitmap_videoram_pointer()
-{
- m_current_bitmap_videoram_accessed = m_bitmap_videoram_selected ? m_bitmap_videoram1.get() : m_bitmap_videoram2.get();
- m_current_bitmap_videoram_displayed = m_bitmap_videoram_selected ? m_bitmap_videoram2.get() : m_bitmap_videoram1.get();
-}
-
-void cloak_state::cloak_clearbmp_w(uint8_t data)
-{
-// m_screen->update_now();
- m_screen->update_partial(m_screen->vpos());
-
- m_bitmap_videoram_selected = data & 0x01;
- set_current_bitmap_videoram_pointer();
-
- if (data & 0x02) /* clear */
- memset(m_current_bitmap_videoram_accessed, 0, 256*256);
-}
-
-void cloak_state::adjust_xy(int offset)
-{
- switch (offset)
- {
- case 0x00: m_bitmap_videoram_address_x--; m_bitmap_videoram_address_y++; break;
- case 0x01: m_bitmap_videoram_address_y--; break;
- case 0x02: m_bitmap_videoram_address_x--; break;
- case 0x04: m_bitmap_videoram_address_x++; m_bitmap_videoram_address_y++; break;
- case 0x05: m_bitmap_videoram_address_y++; break;
- case 0x06: m_bitmap_videoram_address_x++; break;
- }
-}
-
-uint8_t cloak_state::graph_processor_r(offs_t offset)
-{
- uint8_t ret = m_current_bitmap_videoram_displayed[(m_bitmap_videoram_address_y << 8) | m_bitmap_videoram_address_x];
-
- adjust_xy(offset);
-
- return ret;
-}
-
-void cloak_state::graph_processor_w(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x03: m_bitmap_videoram_address_x = data; break;
- case 0x07: m_bitmap_videoram_address_y = data; break;
- default:
- m_current_bitmap_videoram_accessed[(m_bitmap_videoram_address_y << 8) | m_bitmap_videoram_address_x] = data & 0x0f;
-
- adjust_xy(offset);
- break;
- }
-}
-
-void cloak_state::cloak_videoram_w(offs_t offset, uint8_t data)
-{
- m_videoram[offset] = data;
- m_bg_tilemap->mark_tile_dirty(offset);
-}
-
-WRITE_LINE_MEMBER(cloak_state::cocktail_w)
-{
- flip_screen_set(state);
-}
-
-TILE_GET_INFO_MEMBER(cloak_state::get_bg_tile_info)
-{
- uint8_t *videoram = m_videoram;
- int code = videoram[tile_index];
-
- tileinfo.set(0, code, 0, 0);
-}
-
-void cloak_state::video_start()
-{
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(cloak_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
-
- m_bitmap_videoram1 = std::make_unique<uint8_t[]>(256*256);
- m_bitmap_videoram2 = std::make_unique<uint8_t[]>(256*256);
- m_palette_ram = std::make_unique<uint16_t[]>(NUM_PENS);
-
- set_current_bitmap_videoram_pointer();
-
- save_item(NAME(m_bitmap_videoram_address_x));
- save_item(NAME(m_bitmap_videoram_address_y));
- save_item(NAME(m_bitmap_videoram_selected));
- save_pointer(NAME(m_bitmap_videoram1), 256*256);
- save_pointer(NAME(m_bitmap_videoram2), 256*256);
- save_pointer(NAME(m_palette_ram), NUM_PENS);
- machine().save().register_postload(save_prepost_delegate(FUNC(cloak_state::set_current_bitmap_videoram_pointer), this));
-}
-
-void cloak_state::draw_bitmap(bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
- for (int x = cliprect.left(); x <= cliprect.right(); x++)
- {
- pen_t const pen = m_current_bitmap_videoram_displayed[(y << 8) | x] & 0x07;
-
- if (pen)
- bitmap.pix(y, (x - 6) & 0xff) = 0x10 | ((x & 0x80) >> 4) | pen;
- }
-}
-
-void cloak_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- uint8_t *spriteram = m_spriteram;
- int offs;
-
- for (offs = (0x100 / 4) - 1; offs >= 0; offs--)
- {
- int code = spriteram[offs + 64] & 0x7f;
- int flipx = spriteram[offs + 64] & 0x80;
- int flipy = 0;
- int sx = spriteram[offs + 192];
- int sy = 240 - spriteram[offs];
-
- if (flip_screen())
- {
- sx -= 9;
- sy = 240 - sy;
- flipx = !flipx;
- flipy = !flipy;
- }
-
- m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, code, 0, flipx, flipy, sx, sy, 0);
- }
-}
-
-uint32_t cloak_state::screen_update_cloak(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
- draw_bitmap(bitmap, cliprect);
- draw_sprites(bitmap, cliprect);
- return 0;
-}
diff --git a/src/mame/atari/cloud9.cpp b/src/mame/atari/cloud9.cpp
index f9a03634530..72af2e89619 100644
--- a/src/mame/atari/cloud9.cpp
+++ b/src/mame/atari/cloud9.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Mike Balfour, Aaron Giles
+// copyright-holders: Mike Balfour, Aaron Giles
+
/***************************************************************************
Atari Cloud 9 (prototype) hardware
@@ -17,7 +18,7 @@
Horizontal sync chain:
- Appears to be the same as Crystal Castles. See ccastles.c for
+ Appears to be the same as Crystal Castles. See ccastles.cpp for
details.
Pixel clock = 5MHz
@@ -93,58 +94,420 @@
***************************************************************************/
#include "emu.h"
-#include "cloud9.h"
#include "cpu/m6502/m6502.h"
+#include "machine/74259.h"
#include "machine/watchdog.h"
+#include "machine/x2212.h"
#include "sound/pokey.h"
+#include "video/resnet.h"
+
+#include "emupal.h"
+#include "screen.h"
#include "speaker.h"
-#define MASTER_CLOCK (10000000)
+namespace {
+
+class cloud9_state : public driver_device
+{
+public:
+ cloud9_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_nvram(*this, "nvram"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_videolatch(*this, "videolatch"),
+ m_videoram(*this, "videoram", 0x8000U, ENDIANNESS_LITTLE),
+ m_spriteram(*this, "spriteram"),
+ m_paletteram(*this, "paletteram"),
+ m_syncprom(*this, "syncprom"),
+ m_wpprom(*this, "wpprom"),
+ m_track(*this, "TRACK%c", 'X')
+ { }
+
+ DECLARE_READ_LINE_MEMBER(vblank_r);
+ void cloud9(machine_config &config);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void video_start() override;
+
+private:
+ // devices
+ required_device<m6502_device> m_maincpu;
+ required_device<x2212_device> m_nvram;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_device<ls259_device> m_videolatch;
+
+ // memory pointers
+ memory_share_creator<uint8_t> m_videoram;
+ required_shared_ptr<uint8_t> m_spriteram;
+ required_shared_ptr<uint8_t> m_paletteram;
+ required_region_ptr<uint8_t> m_syncprom;
+ required_region_ptr<uint8_t> m_wpprom;
+
+ required_ioport_array<2> m_track;
+
+ // video-related
+ bitmap_ind16 m_spritebitmap = 0;
+ double m_rweights[3]{};
+ double m_gweights[3]{};
+ double m_bweights[3]{};
+ uint8_t m_bitmode_addr[2]{};
+
+ // misc
+ int m_vblank_start = 0;
+ int m_vblank_end = 0;
+ emu_timer *m_irq_timer = nullptr;
+ uint8_t m_irq_state = 0U;
+
+ void irq_ack_w(uint8_t data);
+ uint8_t leta_r(offs_t offset);
+ void nvram_recall_w(uint8_t data);
+ void nvram_store_w(uint8_t data);
+ void paletteram_w(offs_t offset, uint8_t data);
+ void videoram_w(offs_t offset, uint8_t data);
+ uint8_t bitmode_r();
+ void bitmode_w(uint8_t data);
+ void bitmode_addr_w(offs_t offset, uint8_t data);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ TIMER_CALLBACK_MEMBER(clock_irq);
+ inline void write_vram(uint16_t addr, uint8_t data, uint8_t bitmd, uint8_t pixba);
+ inline void bitmode_autoinc();
+ inline void schedule_next_irq(int curscanline);
+ void program_map(address_map &map);
+};
+
+
+// video
+
+/*************************************
+ *
+ * Video startup
+ *
+ *************************************/
+
+void cloud9_state::video_start()
+{
+ static const int resistances[3] = { 22000, 10000, 4700 };
+
+ // allocate second bank of videoram
+ membank("videoram_bank")->set_base(m_videoram.target());
+
+ // compute the color output resistor weights at startup
+ compute_resistor_weights(0, 255, -1.0,
+ 3, resistances, m_rweights, 1000, 0,
+ 3, resistances, m_gweights, 1000, 0,
+ 3, resistances, m_bweights, 1000, 0);
+
+ // allocate a bitmap for drawing sprites
+ m_screen->register_screen_bitmap(m_spritebitmap);
+
+ // register for savestates
+ save_item(NAME(m_bitmode_addr));
+}
+
+
+
+/*************************************
+ *
+ * Palette RAM accesses
+ *
+ *************************************/
+
+void cloud9_state::paletteram_w(offs_t offset, uint8_t data)
+{
+ int bit0, bit1, bit2;
+
+ // extract the raw RGB bits
+ int r = (data & 0xe0) >> 5;
+ int g = (data & 0x1c) >> 2;
+ int b = ((data & 0x03) << 1) | ((offset & 0x40) >> 6);
+
+ // red component (inverted)
+ bit0 = (~r >> 0) & 0x01;
+ bit1 = (~r >> 1) & 0x01;
+ bit2 = (~r >> 2) & 0x01;
+ r = combine_weights(m_rweights, bit0, bit1, bit2);
+
+ // green component (inverted)
+ bit0 = (~g >> 0) & 0x01;
+ bit1 = (~g >> 1) & 0x01;
+ bit2 = (~g >> 2) & 0x01;
+ g = combine_weights(m_gweights, bit0, bit1, bit2);
+
+ // blue component (inverted)
+ bit0 = (~b >> 0) & 0x01;
+ bit1 = (~b >> 1) & 0x01;
+ bit2 = (~b >> 2) & 0x01;
+ b = combine_weights(m_bweights, bit0, bit1, bit2);
+
+ m_palette->set_pen_color(offset & 0x3f, rgb_t(r, g, b));
+}
+
+
+
+/*************************************
+ *
+ * Video RAM access via the write
+ * protect PROM
+ *
+ *************************************/
+
+inline void cloud9_state::write_vram(uint16_t addr, uint8_t data, uint8_t bitmd, uint8_t pixba)
+{
+ uint8_t *dest = &m_videoram[0x0000 | (addr & 0x3fff)];
+ uint8_t *dest2 = &m_videoram[0x4000 | (addr & 0x3fff)];
+ uint8_t promaddr = 0;
+
+ /*
+ Inputs to the write-protect PROM:
+
+ Bit 7 = BITMD
+ Bit 6 = video_control[4]
+ Bit 5 = video_control[6]
+ Bit 4 = 1 if (A15-A12 != 4)
+ Bit 3 = !(A13 | A12 | A11)
+ Bit 2 = A9 & A10
+ Bit 1 = PIXB
+ Bit 0 = PIXA
+ */
+ promaddr |= bitmd << 7;
+ promaddr |= m_videolatch->q4_r() << 6;
+ promaddr |= m_videolatch->q6_r() << 5;
+ promaddr |= ((addr & 0xf000) != 0x4000) << 4;
+ promaddr |= ((addr & 0x3800) == 0x0000) << 3;
+ promaddr |= ((addr & 0x0600) == 0x0600) << 2;
+ promaddr |= (pixba << 0);
+
+ // look up the PROM result
+ uint8_t const wpbits = m_wpprom[promaddr];
+
+ // write to the appropriate parts of VRAM depending on the result
+ if (!(wpbits & 1))
+ dest2[0] = (dest2[0] & 0x0f) | (data & 0xf0);
+ if (!(wpbits & 2))
+ dest2[0] = (dest2[0] & 0xf0) | (data & 0x0f);
+ if (!(wpbits & 4))
+ dest[0] = (dest[0] & 0x0f) | (data & 0xf0);
+ if (!(wpbits & 8))
+ dest[0] = (dest[0] & 0xf0) | (data & 0x0f);
+}
+
+
+
+/*************************************
+ *
+ * Autoincrement control for bit mode
+ *
+ *************************************/
+
+inline void cloud9_state::bitmode_autoinc()
+{
+ // auto increment in the x-direction if it's enabled
+ if (!m_videolatch->q0_r()) // /AX
+ m_bitmode_addr[0]++;
+
+ // auto increment in the y-direction if it's enabled
+ if (!m_videolatch->q1_r()) // /AY
+ m_bitmode_addr[1]++;
+}
+
+
-#define PIXEL_CLOCK (MASTER_CLOCK/2)
-#define HTOTAL (320)
-#define VTOTAL (256)
+/*************************************
+ *
+ * Standard video RAM access
+ *
+ *************************************/
+
+void cloud9_state::videoram_w(offs_t offset, uint8_t data)
+{
+ // direct writes to VRAM go through the write protect PROM as well
+ write_vram(offset, data, 0, 0);
+}
/*************************************
*
+ * Bit mode video RAM access
+ *
+ *************************************/
+
+uint8_t cloud9_state::bitmode_r()
+{
+ // in bitmode, the address comes from the autoincrement latches
+ uint16_t const addr = (m_bitmode_addr[1] << 6) | (m_bitmode_addr[0] >> 2);
+
+ // the appropriate pixel is selected into the upper 4 bits
+ uint8_t const result = m_videoram[((~m_bitmode_addr[0] & 2) << 13) | addr] << ((m_bitmode_addr[0] & 1) * 4);
+
+ // autoincrement because /BITMD was selected
+ bitmode_autoinc();
+
+ // the upper 4 bits of the data lines are not driven so make them all 1's
+ return (result >> 4) | 0xf0;
+}
+
+
+void cloud9_state::bitmode_w(uint8_t data)
+{
+ // in bitmode, the address comes from the autoincrement latches
+ uint16_t const addr = (m_bitmode_addr[1] << 6) | (m_bitmode_addr[0] >> 2);
+
+ // the lower 4 bits of data are replicated to the upper 4 bits
+ data = (data & 0x0f) | (data << 4);
+
+ // write through the generic VRAM routine, passing the low 2 X bits as PIXB/PIXA
+ write_vram(addr, data, 1, m_bitmode_addr[0] & 3);
+
+ // autoincrement because /BITMD was selected
+ bitmode_autoinc();
+}
+
+
+void cloud9_state::bitmode_addr_w(offs_t offset, uint8_t data)
+{
+ // write through to video RAM and also to the addressing latches
+ write_vram(offset, data, 0, 0);
+ m_bitmode_addr[offset] = data;
+}
+
+
+
+/*************************************
+ *
+ * Video updating
+ *
+ *************************************/
+
+uint32_t cloud9_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ uint8_t const *const spriteaddr = m_spriteram;
+ int const flip = m_videolatch->q5_r() ? 0xff : 0x00; // PLAYER2
+ pen_t const black = m_palette->black_pen();
+
+ // draw the sprites
+ m_spritebitmap.fill(0x00, cliprect);
+ for (int offs = 0; offs < 0x20; offs++)
+ if (spriteaddr[offs + 0x00] != 0)
+ {
+ int const x = spriteaddr[offs + 0x60];
+ int const y = 256 - 15 - spriteaddr[offs + 0x00];
+ int const xflip = spriteaddr[offs + 0x40] & 0x80;
+ int const yflip = spriteaddr[offs + 0x40] & 0x40;
+ int const which = spriteaddr[offs + 0x20];
+ int const color = 0;
+
+ m_gfxdecode->gfx(0)->transpen(m_spritebitmap, cliprect, which, color, xflip, yflip, x, y, 0);
+ if (x >= 256 - 16)
+ m_gfxdecode->gfx(0)->transpen(m_spritebitmap, cliprect, which, color, xflip, yflip, x - 256, y, 0);
+ }
+
+ // draw the bitmap to the screen, looping over Y
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
+ {
+ uint16_t *const dst = &bitmap.pix(y);
+
+ // if we're in the VBLANK region, just fill with black
+ if (~m_syncprom[y] & 2)
+ {
+ for (int x = cliprect.left(); x <= cliprect.right(); x++)
+ dst[x] = black;
+ }
+
+ // non-VBLANK region: merge the sprites and the bitmap
+ else
+ {
+ uint16_t const *const mosrc = &m_spritebitmap.pix(y);
+ int const effy = y ^ flip;
+
+ // two videoram arrays
+ uint8_t const *const src[2]{ &m_videoram[0x4000 | (effy * 64)], &m_videoram[0x0000 | (effy * 64)] };
+
+ // loop over X
+ for (int x = cliprect.left(); x <= cliprect.right(); x++)
+ {
+ // if we're in the HBLANK region, just store black
+ if (x >= 256)
+ dst[x] = black;
+
+ // otherwise, process normally
+ else
+ {
+ int const effx = x ^ flip;
+
+ // low 4 bits = left pixel, high 4 bits = right pixel
+ uint8_t pix = (src[(effx >> 1) & 1][effx / 4] >> ((~effx & 1) * 4)) & 0x0f;
+ uint8_t const mopix = mosrc[x];
+
+ // sprites have priority if sprite pixel != 0 or some other condition
+ if (mopix != 0)
+ pix = mopix | 0x10;
+
+ // the high bit is the bank select
+ pix |= m_videolatch->q7_r() << 5;
+
+ // store the pixel value and also a priority value based on the topmost bit
+ dst[x] = pix;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+// machine
+
+static constexpr double MASTER_CLOCK = 10'000'000;
+static constexpr double PIXEL_CLOCK = MASTER_CLOCK / 2;
+static constexpr uint16_t HTOTAL = 320;
+static constexpr uint16_t VTOTAL = 256;
+
+/*************************************
+ *
* VBLANK and IRQ generation
*
*************************************/
inline void cloud9_state::schedule_next_irq(int curscanline)
{
- /* IRQ is clocked by /32V, so every 64 scanlines */
+ // IRQ is clocked by /32V, so every 64 scanlines
curscanline = (curscanline + 64) & 255;
- /* next one at the start of this scanline */
+ // next one at the start of this scanline
m_irq_timer->adjust(m_screen->time_until_pos(curscanline), curscanline);
}
TIMER_CALLBACK_MEMBER(cloud9_state::clock_irq)
{
- /* assert the IRQ if not already asserted */
+ // assert the IRQ if not already asserted
if (!m_irq_state)
{
m_maincpu->set_input_line(0, ASSERT_LINE);
m_irq_state = 1;
}
- /* force an update now */
+ // force an update now
m_screen->update_partial(m_screen->vpos());
- /* find the next edge */
+ // find the next edge
schedule_next_irq(param);
}
READ_LINE_MEMBER(cloud9_state::vblank_r)
{
- int scanline = m_screen->vpos();
+ int const scanline = m_screen->vpos();
return (~m_syncprom[scanline & 0xff] >> 1) & 1;
}
@@ -160,34 +523,31 @@ void cloud9_state::machine_start()
{
rectangle visarea;
- /* initialize globals */
- m_syncprom = memregion("proms")->base() + 0x000;
-
- /* find the start of VBLANK in the SYNC PROM */
+ // find the start of VBLANK in the SYNC PROM
for (m_vblank_start = 0; m_vblank_start < 256; m_vblank_start++)
if ((m_syncprom[(m_vblank_start - 1) & 0xff] & 2) != 0 && (m_syncprom[m_vblank_start] & 2) == 0)
break;
if (m_vblank_start == 0)
m_vblank_start = 256;
- /* find the end of VBLANK in the SYNC PROM */
+ // find the end of VBLANK in the SYNC PROM
for (m_vblank_end = 0; m_vblank_end < 256; m_vblank_end++)
if ((m_syncprom[(m_vblank_end - 1) & 0xff] & 2) == 0 && (m_syncprom[m_vblank_end] & 2) != 0)
break;
- /* can't handle the wrapping case */
+ // can't handle the wrapping case
assert(m_vblank_end < m_vblank_start);
- /* reconfigure the visible area to match */
+ // reconfigure the visible area to match
visarea.set(0, 255, m_vblank_end + 1, m_vblank_start);
m_screen->configure(320, 256, visarea, HZ_TO_ATTOSECONDS(PIXEL_CLOCK) * VTOTAL * HTOTAL);
- /* create a timer for IRQs and set up the first callback */
+ // create a timer for IRQs and set up the first callback
m_irq_timer = timer_alloc(FUNC(cloud9_state::clock_irq), this);
m_irq_state = 0;
- schedule_next_irq(0-64);
+ schedule_next_irq(0 - 64);
- /* setup for save states */
+ // setup for save states
save_item(NAME(m_irq_state));
}
@@ -218,7 +578,7 @@ void cloud9_state::irq_ack_w(uint8_t data)
uint8_t cloud9_state::leta_r(offs_t offset)
{
- return ioport(offset ? "TRACKX" : "TRACKY")->read();
+ return offset ? m_track[0]->read() : m_track[1]->read();
}
@@ -252,15 +612,15 @@ void cloud9_state::nvram_store_w(uint8_t data)
*
*************************************/
-void cloud9_state::cloud9_map(address_map &map)
+void cloud9_state::program_map(address_map &map)
{
- map(0x0000, 0x4fff).bankr("bank1").w(FUNC(cloud9_state::cloud9_videoram_w));
- map(0x0000, 0x0001).w(FUNC(cloud9_state::cloud9_bitmode_addr_w));
- map(0x0002, 0x0002).rw(FUNC(cloud9_state::cloud9_bitmode_r), FUNC(cloud9_state::cloud9_bitmode_w));
- map(0x5000, 0x53ff).ram().share("spriteram");
+ map(0x0000, 0x4fff).bankr("videoram_bank").w(FUNC(cloud9_state::videoram_w));
+ map(0x0000, 0x0001).w(FUNC(cloud9_state::bitmode_addr_w));
+ map(0x0002, 0x0002).rw(FUNC(cloud9_state::bitmode_r), FUNC(cloud9_state::bitmode_w));
+ map(0x5000, 0x53ff).ram().share(m_spriteram);
map(0x5400, 0x547f).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x5480, 0x54ff).w(FUNC(cloud9_state::irq_ack_w));
- map(0x5500, 0x557f).ram().w(FUNC(cloud9_state::cloud9_paletteram_w)).share("paletteram");
+ map(0x5500, 0x557f).ram().w(FUNC(cloud9_state::paletteram_w)).share(m_paletteram);
map(0x5580, 0x5587).mirror(0x0078).w(m_videolatch, FUNC(ls259_device::write_d7)); // video control registers
map(0x5600, 0x5607).mirror(0x0078).w("outlatch", FUNC(ls259_device::write_d7));
map(0x5680, 0x56ff).w(FUNC(cloud9_state::nvram_store_w));
@@ -382,7 +742,7 @@ INPUT_PORTS_END
*************************************/
static GFXDECODE_START( gfx_cloud9 )
- GFXDECODE_ENTRY( "gfx1", 0x0000, gfx_16x16x4_planar, 0, 4 )
+ GFXDECODE_ENTRY( "sprites", 0x0000, gfx_16x16x4_planar, 0, 4 )
GFXDECODE_END
@@ -394,9 +754,9 @@ GFXDECODE_END
void cloud9_state::cloud9(machine_config &config)
{
- /* basic machine hardware */
- M6502(config, m_maincpu, MASTER_CLOCK/8);
- m_maincpu->set_addrmap(AS_PROGRAM, &cloud9_state::cloud9_map);
+ // basic machine hardware
+ M6502(config, m_maincpu, MASTER_CLOCK / 8);
+ m_maincpu->set_addrmap(AS_PROGRAM, &cloud9_state::program_map);
ls259_device &outlatch(LS259(config, "outlatch"));
outlatch.q_out_cb<0>().set([this] (int state) { machine().bookkeeping().coin_counter_w(0, state); });
@@ -408,27 +768,27 @@ void cloud9_state::cloud9(machine_config &config)
X2212(config, "nvram").set_auto_save(true);
- /* video hardware */
+ // video hardware
GFXDECODE(config, m_gfxdecode, m_palette, gfx_cloud9);
PALETTE(config, m_palette).set_entries(64);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz((double)PIXEL_CLOCK / (double)VTOTAL / (double)HTOTAL);
m_screen->set_size(HTOTAL, VTOTAL);
- m_screen->set_vblank_time(0); /* VBLANK is handled manually */
+ m_screen->set_vblank_time(0); // VBLANK is handled manually
m_screen->set_visarea(0, 255, 0, 231);
- m_screen->set_screen_update(FUNC(cloud9_state::screen_update_cloud9));
+ m_screen->set_screen_update(FUNC(cloud9_state::screen_update));
m_screen->set_palette(m_palette);
LS259(config, m_videolatch);
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "mono").front_center();
- pokey_device &pokey1(POKEY(config, "pokey1", MASTER_CLOCK/8));
+ pokey_device &pokey1(POKEY(config, "pokey1", MASTER_CLOCK / 8));
pokey1.add_route(ALL_OUTPUTS, "mono", 0.50);
- pokey_device &pokey2(POKEY(config, "pokey2", MASTER_CLOCK/8));
+ pokey_device &pokey2(POKEY(config, "pokey2", MASTER_CLOCK / 8));
pokey2.allpot_r().set_ioport("DSW");
pokey2.add_route(ALL_OUTPUTS, "mono", 0.50);
}
@@ -449,17 +809,21 @@ ROM_START( cloud9 )
ROM_LOAD( "c9_c000.bin", 0xc000, 0x2000, CRC(26a4d7df) SHA1(8eef0a5f5d1ff13eec75d0c50f5a5dea28486ae5) )
ROM_LOAD( "c9_e000.bin", 0xe000, 0x2000, CRC(6e663bce) SHA1(4f4a5dc57ba6bc38a17973a6644849f6f5a2dfd1) )
- ROM_REGION( 0x4000, "gfx1", 0 )
+ ROM_REGION( 0x4000, "sprites", 0 )
ROM_LOAD( "c9_gfx0.bin", 0x0000, 0x1000, CRC(d01a8019) SHA1(a77d6125b116ab4bf9446e3b99469dad2719f7e5) )
ROM_LOAD( "c9_gfx1.bin", 0x1000, 0x1000, CRC(514ac009) SHA1(f05081d8da47e650b0bd12cd00460c98a4f745b1) )
ROM_LOAD( "c9_gfx2.bin", 0x2000, 0x1000, CRC(930c1ade) SHA1(ba22cb7b105da2ab8c40574e70f18d594d833452) )
ROM_LOAD( "c9_gfx3.bin", 0x3000, 0x1000, CRC(27e9b88d) SHA1(a1d27e62eea9cdff662a3c160f650bbdb32b7f47) )
- ROM_REGION( 0x400, "proms", 0 )
- ROM_LOAD( "63s141.e10", 0x0000, 0x0100, BAD_DUMP CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) ) /* Sync PROM */
- ROM_LOAD( "63s141.m10", 0x0100, 0x0100, BAD_DUMP CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) ) /* ??? PROM */
- ROM_LOAD( "82s129.p3", 0x0200, 0x0100, BAD_DUMP CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) ) /* VRAM Write Protect PROM */
- ROM_LOAD( "63s141.m8", 0x0300, 0x0100, BAD_DUMP CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) ) /* ??? PROM */
+ ROM_REGION( 0x100, "syncprom", 0 )
+ ROM_LOAD( "63s141.e10", 0x0000, 0x0100, BAD_DUMP CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) ) // Sync PROM
+
+ ROM_REGION( 0x100, "wpprom", 0 )
+ ROM_LOAD( "82s129.p3", 0x0000, 0x0100, BAD_DUMP CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) ) // VRAM Write Protect PROM
+
+ ROM_REGION( 0x200, "unkproms", 0 )
+ ROM_LOAD( "63s141.m10", 0x0000, 0x0100, BAD_DUMP CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) ) // ??? PROM
+ ROM_LOAD( "63s141.m8", 0x0100, 0x0100, BAD_DUMP CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) ) // ??? PROM
ROM_END
@@ -472,19 +836,24 @@ ROM_START( firebeas )
ROM_LOAD( "e000.p2", 0xe000, 0x1000, CRC(8e5045ab) SHA1(8e5e8dd7710dc5ec68602f069dfc30e1bcaf7411) )
ROM_RELOAD( 0xf000, 0x1000 )
- ROM_REGION( 0x8000, "gfx1", 0 )
+ ROM_REGION( 0x8000, "sprites", 0 )
ROM_LOAD( "mo0000.r12", 0x0000, 0x2000, CRC(5246c979) SHA1(a975ede0a6c2c91f4373ecba1e2f61f1aedcee62) )
ROM_LOAD( "mo2000.p12", 0x2000, 0x2000, CRC(1a3b6d57) SHA1(d9015140e69fdc3f73113f0afc3be2579197017a) )
ROM_LOAD( "mo4000.n12", 0x4000, 0x2000, CRC(69e18319) SHA1(3bf3cbe4ea06ea71928eff8a57c2ef7dc6e6716a) )
ROM_LOAD( "mo6000.m12", 0x6000, 0x2000, CRC(b722997f) SHA1(65a2618ecd8b4923f30f59c1fb95124cf0391964) )
- ROM_REGION( 0x400, "proms", 0 )
- ROM_LOAD( "63s141.e10", 0x0000, 0x0100, CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) ) /* Sync PROM */
- ROM_LOAD( "63s141.m10", 0x0100, 0x0100, CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) ) /* ??? PROM */
- ROM_LOAD( "82s129.p3", 0x0200, 0x0100, CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) ) /* VRAM Write Protect PROM */
- ROM_LOAD( "63s141.m8", 0x0300, 0x0100, CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) ) /* ??? PROM */
+ ROM_REGION( 0x100, "syncprom", 0 )
+ ROM_LOAD( "63s141.e10", 0x0000, 0x0100, CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) ) // Sync PROM
+
+ ROM_REGION( 0x100, "wpprom", 0 )
+ ROM_LOAD( "82s129.p3", 0x0000, 0x0100, CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) ) // VRAM Write Protect PROM
+
+ ROM_REGION( 0x200, "unkproms", 0 )
+ ROM_LOAD( "63s141.m10", 0x0000, 0x0100, CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) ) // ??? PROM
+ ROM_LOAD( "63s141.m8", 0x0100, 0x0100, CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) ) // ??? PROM
ROM_END
+} // anonymous namespace
/*************************************
diff --git a/src/mame/atari/cloud9.h b/src/mame/atari/cloud9.h
deleted file mode 100644
index 71823175513..00000000000
--- a/src/mame/atari/cloud9.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Balfour, Aaron Giles
-/*************************************************************************
-
- Atari Cloud 9 (prototype) hardware
-
-*************************************************************************/
-#ifndef MAME_ATARI_CLOUD9_H
-#define MAME_ATARI_CLOUD9_H
-
-#pragma once
-
-#include "cpu/m6502/m6502.h"
-#include "machine/74259.h"
-#include "machine/x2212.h"
-#include "emupal.h"
-#include "screen.h"
-
-class cloud9_state : public driver_device
-{
-public:
- cloud9_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_nvram(*this, "nvram") ,
- m_spriteram(*this, "spriteram"),
- m_paletteram(*this, "paletteram"),
- m_gfxdecode(*this, "gfxdecode"),
- m_screen(*this, "screen"),
- m_palette(*this, "palette"),
- m_videolatch(*this, "videolatch")
- { }
-
- DECLARE_READ_LINE_MEMBER(vblank_r);
- void cloud9(machine_config &config);
-
-protected:
- void irq_ack_w(uint8_t data);
- uint8_t leta_r(offs_t offset);
- void nvram_recall_w(uint8_t data);
- void nvram_store_w(uint8_t data);
- void cloud9_paletteram_w(offs_t offset, uint8_t data);
- void cloud9_videoram_w(offs_t offset, uint8_t data);
- uint8_t cloud9_bitmode_r();
- void cloud9_bitmode_w(uint8_t data);
- void cloud9_bitmode_addr_w(offs_t offset, uint8_t data);
- virtual void machine_start() override;
- virtual void machine_reset() override;
- virtual void video_start() override;
- uint32_t screen_update_cloud9(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- TIMER_CALLBACK_MEMBER(clock_irq);
- inline void cloud9_write_vram( uint16_t addr, uint8_t data, uint8_t bitmd, uint8_t pixba );
- inline void bitmode_autoinc();
- inline void schedule_next_irq(int curscanline);
- void cloud9_map(address_map &map);
-
-private:
- /* devices */
- required_device<m6502_device> m_maincpu;
- required_device<x2212_device> m_nvram;
- /* memory pointers */
- std::unique_ptr<uint8_t[]> m_videoram;
- required_shared_ptr<uint8_t> m_spriteram;
- required_shared_ptr<uint8_t> m_paletteram;
-
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<screen_device> m_screen;
- required_device<palette_device> m_palette;
- required_device<ls259_device> m_videolatch;
-
- /* video-related */
- const uint8_t *m_syncprom = nullptr;
- const uint8_t *m_wpprom = nullptr;
- const uint8_t *m_priprom = nullptr;
- bitmap_ind16 m_spritebitmap = 0;
- double m_rweights[3]{};
- double m_gweights[3]{};
- double m_bweights[3]{};
- uint8_t m_bitmode_addr[2]{};
-
- /* misc */
- int m_vblank_start = 0;
- int m_vblank_end = 0;
- emu_timer *m_irq_timer = nullptr;
- uint8_t m_irq_state = 0U;
-};
-
-#endif // MAME_ATARI_CLOUD9_H
diff --git a/src/mame/atari/cloud9_v.cpp b/src/mame/atari/cloud9_v.cpp
deleted file mode 100644
index a95b0d5ab36..00000000000
--- a/src/mame/atari/cloud9_v.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Balfour, Aaron Giles
-/***************************************************************************
-
- Atari Cloud 9 (prototype) hardware
-
-***************************************************************************/
-
-#include "emu.h"
-#include "cloud9.h"
-#include "video/resnet.h"
-
-
-/*************************************
- *
- * Video startup
- *
- *************************************/
-
-void cloud9_state::video_start()
-{
- static const int resistances[3] = { 22000, 10000, 4700 };
-
- /* allocate second bank of videoram */
- m_videoram = std::make_unique<uint8_t[]>(0x8000);
- membank("bank1")->set_base(m_videoram.get());
-
- /* get pointers to our PROMs */
- m_syncprom = memregion("proms")->base() + 0x000;
- m_wpprom = memregion("proms")->base() + 0x200;
- m_priprom = memregion("proms")->base() + 0x300;
-
- /* compute the color output resistor weights at startup */
- compute_resistor_weights(0, 255, -1.0,
- 3, resistances, m_rweights, 1000, 0,
- 3, resistances, m_gweights, 1000, 0,
- 3, resistances, m_bweights, 1000, 0);
-
- /* allocate a bitmap for drawing sprites */
- m_screen->register_screen_bitmap(m_spritebitmap);
-
- /* register for savestates */
- save_pointer(NAME(m_videoram), 0x8000);
- save_item(NAME(m_bitmode_addr));
-}
-
-
-
-/*************************************
- *
- * Palette RAM accesses
- *
- *************************************/
-
-void cloud9_state::cloud9_paletteram_w(offs_t offset, uint8_t data)
-{
- int bit0, bit1, bit2;
- int r, g, b;
-
- /* extract the raw RGB bits */
- r = (data & 0xe0) >> 5;
- g = (data & 0x1c) >> 2;
- b = ((data & 0x03) << 1) | ((offset & 0x40) >> 6);
-
- /* red component (inverted) */
- bit0 = (~r >> 0) & 0x01;
- bit1 = (~r >> 1) & 0x01;
- bit2 = (~r >> 2) & 0x01;
- r = combine_weights(m_rweights, bit0, bit1, bit2);
-
- /* green component (inverted) */
- bit0 = (~g >> 0) & 0x01;
- bit1 = (~g >> 1) & 0x01;
- bit2 = (~g >> 2) & 0x01;
- g = combine_weights(m_gweights, bit0, bit1, bit2);
-
- /* blue component (inverted) */
- bit0 = (~b >> 0) & 0x01;
- bit1 = (~b >> 1) & 0x01;
- bit2 = (~b >> 2) & 0x01;
- b = combine_weights(m_bweights, bit0, bit1, bit2);
-
- m_palette->set_pen_color(offset & 0x3f, rgb_t(r, g, b));
-}
-
-
-
-/*************************************
- *
- * Video RAM access via the write
- * protect PROM
- *
- *************************************/
-
-inline void cloud9_state::cloud9_write_vram( uint16_t addr, uint8_t data, uint8_t bitmd, uint8_t pixba )
-{
- uint8_t *dest = &m_videoram[0x0000 | (addr & 0x3fff)];
- uint8_t *dest2 = &m_videoram[0x4000 | (addr & 0x3fff)];
- uint8_t promaddr = 0;
- uint8_t wpbits;
-
- /*
- Inputs to the write-protect PROM:
-
- Bit 7 = BITMD
- Bit 6 = video_control[4]
- Bit 5 = video_control[6]
- Bit 4 = 1 if (A15-A12 != 4)
- Bit 3 = !(A13 | A12 | A11)
- Bit 2 = A9 & A10
- Bit 1 = PIXB
- Bit 0 = PIXA
- */
- promaddr |= bitmd << 7;
- promaddr |= m_videolatch->q4_r() << 6;
- promaddr |= m_videolatch->q6_r() << 5;
- promaddr |= ((addr & 0xf000) != 0x4000) << 4;
- promaddr |= ((addr & 0x3800) == 0x0000) << 3;
- promaddr |= ((addr & 0x0600) == 0x0600) << 2;
- promaddr |= (pixba << 0);
-
- /* look up the PROM result */
- wpbits = m_wpprom[promaddr];
-
- /* write to the appropriate parts of VRAM depending on the result */
- if (!(wpbits & 1))
- dest2[0] = (dest2[0] & 0x0f) | (data & 0xf0);
- if (!(wpbits & 2))
- dest2[0] = (dest2[0] & 0xf0) | (data & 0x0f);
- if (!(wpbits & 4))
- dest[0] = (dest[0] & 0x0f) | (data & 0xf0);
- if (!(wpbits & 8))
- dest[0] = (dest[0] & 0xf0) | (data & 0x0f);
-}
-
-
-
-/*************************************
- *
- * Autoincrement control for bit mode
- *
- *************************************/
-
-inline void cloud9_state::bitmode_autoinc( )
-{
- /* auto increment in the x-direction if it's enabled */
- if (!m_videolatch->q0_r()) /* /AX */
- m_bitmode_addr[0]++;
-
- /* auto increment in the y-direction if it's enabled */
- if (!m_videolatch->q1_r()) /* /AY */
- m_bitmode_addr[1]++;
-}
-
-
-
-/*************************************
- *
- * Standard video RAM access
- *
- *************************************/
-
-void cloud9_state::cloud9_videoram_w(offs_t offset, uint8_t data)
-{
- /* direct writes to VRAM go through the write protect PROM as well */
- cloud9_write_vram(offset, data, 0, 0);
-}
-
-
-
-/*************************************
- *
- * Bit mode video RAM access
- *
- *************************************/
-
-uint8_t cloud9_state::cloud9_bitmode_r()
-{
- /* in bitmode, the address comes from the autoincrement latches */
- uint16_t addr = (m_bitmode_addr[1] << 6) | (m_bitmode_addr[0] >> 2);
-
- /* the appropriate pixel is selected into the upper 4 bits */
- uint8_t result = m_videoram[((~m_bitmode_addr[0] & 2) << 13) | addr] << ((m_bitmode_addr[0] & 1) * 4);
-
- /* autoincrement because /BITMD was selected */
- bitmode_autoinc();
-
- /* the upper 4 bits of the data lines are not driven so make them all 1's */
- return (result >> 4) | 0xf0;
-}
-
-
-void cloud9_state::cloud9_bitmode_w(uint8_t data)
-{
- /* in bitmode, the address comes from the autoincrement latches */
- uint16_t addr = (m_bitmode_addr[1] << 6) | (m_bitmode_addr[0] >> 2);
-
- /* the lower 4 bits of data are replicated to the upper 4 bits */
- data = (data & 0x0f) | (data << 4);
-
- /* write through the generic VRAM routine, passing the low 2 X bits as PIXB/PIXA */
- cloud9_write_vram(addr, data, 1, m_bitmode_addr[0] & 3);
-
- /* autoincrement because /BITMD was selected */
- bitmode_autoinc();
-}
-
-
-void cloud9_state::cloud9_bitmode_addr_w(offs_t offset, uint8_t data)
-{
- /* write through to video RAM and also to the addressing latches */
- cloud9_write_vram(offset, data, 0, 0);
- m_bitmode_addr[offset] = data;
-}
-
-
-
-/*************************************
- *
- * Video updating
- *
- *************************************/
-
-uint32_t cloud9_state::screen_update_cloud9(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- uint8_t const *const spriteaddr = m_spriteram;
- int const flip = m_videolatch->q5_r() ? 0xff : 0x00; /* PLAYER2 */
- pen_t const black = m_palette->black_pen();
-
- /* draw the sprites */
- m_spritebitmap.fill(0x00, cliprect);
- for (int offs = 0; offs < 0x20; offs++)
- if (spriteaddr[offs + 0x00] != 0)
- {
- int const x = spriteaddr[offs + 0x60];
- int const y = 256 - 15 - spriteaddr[offs + 0x00];
- int const xflip = spriteaddr[offs + 0x40] & 0x80;
- int const yflip = spriteaddr[offs + 0x40] & 0x40;
- int const which = spriteaddr[offs + 0x20];
- int const color = 0;
-
- m_gfxdecode->gfx(0)->transpen(m_spritebitmap,cliprect, which, color, xflip, yflip, x, y, 0);
- if (x >= 256 - 16)
- m_gfxdecode->gfx(0)->transpen(m_spritebitmap,cliprect, which, color, xflip, yflip, x - 256, y, 0);
- }
-
- /* draw the bitmap to the screen, looping over Y */
- for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
- {
- uint16_t *const dst = &bitmap.pix(y);
-
- /* if we're in the VBLANK region, just fill with black */
- if (~m_syncprom[y] & 2)
- {
- for (int x = cliprect.left(); x <= cliprect.right(); x++)
- dst[x] = black;
- }
-
- /* non-VBLANK region: merge the sprites and the bitmap */
- else
- {
- uint16_t const *const mosrc = &m_spritebitmap.pix(y);
- int const effy = y ^ flip;
-
- /* two videoram arrays */
- uint8_t const *const src[2]{ &m_videoram[0x4000 | (effy * 64)], &m_videoram[0x0000 | (effy * 64)] };
-
- /* loop over X */
- for (int x = cliprect.left(); x <= cliprect.right(); x++)
- {
- /* if we're in the HBLANK region, just store black */
- if (x >= 256)
- dst[x] = black;
-
- /* otherwise, process normally */
- else
- {
- int const effx = x ^ flip;
-
- /* low 4 bits = left pixel, high 4 bits = right pixel */
- uint8_t pix = (src[(effx >> 1) & 1][effx / 4] >> ((~effx & 1) * 4)) & 0x0f;
- uint8_t const mopix = mosrc[x];
-
- /* sprites have priority if sprite pixel != 0 or some other condition */
- if (mopix != 0)
- pix = mopix | 0x10;
-
- /* the high bit is the bank select */
- pix |= m_videolatch->q7_r() << 5;
-
- /* store the pixel value and also a priority value based on the topmost bit */
- dst[x] = pix;
- }
- }
- }
- }
- return 0;
-}
diff --git a/src/mame/atari/copsnrob.cpp b/src/mame/atari/copsnrob.cpp
index f037fdc5368..4305ba46adc 100644
--- a/src/mame/atari/copsnrob.cpp
+++ b/src/mame/atari/copsnrob.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
+// copyright-holders: Zsolt Vasvari
+
/***************************************************************************
Atari Cops'n Robbers hardware
@@ -57,28 +58,218 @@ Added Dip locations according to manual.
***************************************************************************/
#include "emu.h"
-#include "copsnrob.h"
+
+#include "copsnrob_a.h"
#include "cpu/m6502/m6502.h"
+#include "machine/74259.h"
+#include "sound/discrete.h"
+
+#include "emupal.h"
+#include "screen.h"
+#include "speaker.h"
#include "copsnrob.lh"
+namespace {
+
+class copsnrob_state : public driver_device
+{
+public:
+ copsnrob_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_trucky(*this, "trucky"),
+ m_truckram(*this, "truckram"),
+ m_bulletsram(*this, "bulletsram"),
+ m_carimage(*this, "carimage"),
+ m_cary(*this, "cary"),
+ m_videoram(*this, "videoram"),
+ m_discrete(*this, "discrete"),
+ m_maincpu(*this, "maincpu"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_leds(*this, "led%u", 0U)
+ { }
+
+ void copsnrob(machine_config &config);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+private:
+ required_shared_ptr<uint8_t> m_trucky;
+ required_shared_ptr<uint8_t> m_truckram;
+ required_shared_ptr<uint8_t> m_bulletsram;
+ required_shared_ptr<uint8_t> m_carimage;
+ required_shared_ptr<uint8_t> m_cary;
+ required_shared_ptr<uint8_t> m_videoram;
+
+ required_device<discrete_device> m_discrete;
+ required_device<cpu_device> m_maincpu;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+
+ output_finder<2> m_leds;
+
+ uint8_t m_misc = 0U;
+
+ void main_map(address_map &map);
+
+ uint8_t misc_r();
+ void misc2_w(uint8_t data);
+ DECLARE_WRITE_LINE_MEMBER(one_start_w);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+};
+
+
+// video
+
+uint32_t copsnrob_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ // redrawing the entire display is faster in this case
+ for (int offs = 0; offs < m_videoram.bytes(); offs++)
+ {
+ int const sx = 31 - (offs % 32);
+ int const sy = offs / 32;
+
+ m_gfxdecode->gfx(0)->opaque(bitmap, cliprect,
+ m_videoram[offs] & 0x3f, 0,
+ 0, 0,
+ 8 * sx, 8 * sy);
+ }
+
+
+ // Draw the cars. Positioning was based on a screen shot
+ if (m_cary[0])
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
+ m_carimage[0], 0,
+ 1, 0,
+ 0xe4, 256 - m_cary[0], 0);
+
+ if (m_cary[1])
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
+ m_carimage[1], 0,
+ 1, 0,
+ 0xc4, 256 - m_cary[1], 0);
+
+ if (m_cary[2])
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
+ m_carimage[2], 0,
+ 0, 0,
+ 0x24, 256 - m_cary[2], 0);
+
+ if (m_cary[3])
+ m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
+ m_carimage[3], 0,
+ 0, 0,
+ 0x04, 256 - m_cary[3], 0);
+
+
+ /* Draw the beer truck. Positioning was based on a screen shot.
+ We scan the truck's window RAM for a location whose bit is set and
+ which corresponds either to the truck's front end or the truck's back
+ end (based on the value of the truck image line sync register). We
+ then draw a truck image in the proper place and continue scanning.
+ This is not a perfect emulation of the game hardware, but it should
+ suffice for the way the game software uses the hardware. It does take
+ care of the problem of displaying multiple beer trucks and of scrolling
+ truck images smoothly off the top of the screen. */
+
+ for (int y = 0; y < 256; y++)
+ {
+ /* y is going up the screen, but the truck window RAM locations
+ go down the screen. */
+
+ if (m_truckram[255 - y])
+ {
+ /* The hardware only uses the low 5 bits of the truck image line
+ sync register. */
+ if ((m_trucky[0] & 0x1f) == ((y + 31) & 0x1f))
+ {
+ /* We've hit a truck's back end, so draw the truck. The front
+ end may be off the top of the screen, but we don't care. */
+ m_gfxdecode->gfx(2)->transpen(bitmap, cliprect,
+ 0, 0,
+ 0, 0,
+ 0x80, 256 - (y + 31), 0);
+ /* Skip past this truck's front end so we don't draw this
+ truck twice. */
+ y += 31;
+ }
+ else if ((m_trucky[0] & 0x1f) == (y & 0x1f))
+ {
+ /* We missed a truck's back end (it was off the bottom of the
+ screen) but have hit its front end, so draw the truck. */
+ m_gfxdecode->gfx(2)->transpen(bitmap, cliprect,
+ 0, 0,
+ 0, 0,
+ 0x80, 256 - y, 0);
+ }
+ }
+ }
+
+
+ /* Draw the bullets.
+ They are flickered on/off every frame by the software, so don't
+ play it with frameskip 1 or 3, as they could become invisible */
+
+ for (int x = 0; x < 256; x++)
+ {
+ int const val = m_bulletsram[x];
+
+ // Check for the most common case
+ if (!(val & 0x0f))
+ continue;
+
+ int mask1 = 0x01;
+ int mask2 = 0x10;
+
+ // Check each bullet
+ for (int bullet = 0; bullet < 4; bullet++)
+ {
+ if (val & mask1)
+ {
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
+ if (m_bulletsram[y] & mask2)
+ bitmap.pix(y, 256 - x) = 1;
+ }
+
+ mask1 <<= 1;
+ mask2 <<= 1;
+ }
+ }
+ return 0;
+}
+
+
+// machine
+
+
+WRITE_LINE_MEMBER(copsnrob_state::one_start_w)
+{
+ // One Start
+ m_leds[0] = state ? 0 :1;
+}
+
/*************************************
*
* I/O
*
*************************************/
-uint8_t copsnrob_state::copsnrob_misc_r()
+uint8_t copsnrob_state::misc_r()
{
return m_screen->vblank() ? 0x00 : 0x80;
}
-void copsnrob_state::copsnrob_misc2_w(uint8_t data)
+void copsnrob_state::misc2_w(uint8_t data)
{
- m_misc = data & 0x7f;
- /* Multi Player Start */
+ m_misc = data & 0x7f; // TODO: never used?
+ // Multi Player Start
m_leds[1] = BIT(~data, 6);
}
@@ -95,15 +286,15 @@ void copsnrob_state::main_map(address_map &map)
map.global_mask(0x1fff);
map(0x0000, 0x01ff).ram();
map(0x0500, 0x0507).w("latch", FUNC(f9334_device::write_d0));
- map(0x0600, 0x0600).writeonly().share("trucky");
- map(0x0700, 0x07ff).writeonly().share("truckram");
- map(0x0800, 0x08ff).ram().share("bulletsram");
- map(0x0900, 0x0903).writeonly().share("carimage");
- map(0x0a00, 0x0a03).writeonly().share("cary");
+ map(0x0600, 0x0600).writeonly().share(m_trucky);
+ map(0x0700, 0x07ff).writeonly().share(m_truckram);
+ map(0x0800, 0x08ff).ram().share(m_bulletsram);
+ map(0x0900, 0x0903).writeonly().share(m_carimage);
+ map(0x0a00, 0x0a03).writeonly().share(m_cary);
map(0x0b00, 0x0bff).ram();
- map(0x0c00, 0x0fff).ram().share("videoram");
- map(0x1000, 0x1000).r(FUNC(copsnrob_state::copsnrob_misc_r));
- map(0x1000, 0x1000).w(FUNC(copsnrob_state::copsnrob_misc2_w));
+ map(0x0c00, 0x0fff).ram().share(m_videoram);
+ map(0x1000, 0x1000).r(FUNC(copsnrob_state::misc_r));
+ map(0x1000, 0x1000).w(FUNC(copsnrob_state::misc2_w));
map(0x1002, 0x1002).portr("CTRL1");
map(0x1006, 0x1006).portr("CTRL2");
map(0x100a, 0x100a).portr("CTRL3");
@@ -174,18 +365,6 @@ INPUT_PORTS_END
*
*************************************/
-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
-};
-
-
static const gfx_layout carlayout =
{
32,32,
@@ -221,9 +400,9 @@ static const gfx_layout trucklayout =
static GFXDECODE_START( gfx_copsnrob )
- GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 1 )
- GFXDECODE_ENTRY( "gfx2", 0, carlayout, 0, 1 )
- GFXDECODE_ENTRY( "gfx3", 0, trucklayout, 0, 1 )
+ GFXDECODE_ENTRY( "chars", 0, gfx_8x8x1, 0, 1 )
+ GFXDECODE_ENTRY( "car", 0, carlayout, 0, 1 )
+ GFXDECODE_ENTRY( "truck", 0, trucklayout, 0, 1 )
GFXDECODE_END
@@ -236,37 +415,51 @@ GFXDECODE_END
void copsnrob_state::machine_start()
{
- save_item(NAME(m_ic_h3_data));
save_item(NAME(m_misc));
m_leds.resolve();
}
void copsnrob_state::machine_reset()
{
- m_ic_h3_data = 0;
m_misc = 0;
}
void copsnrob_state::copsnrob(machine_config &config)
{
- /* basic machine hardware */
- M6502(config, m_maincpu, 14.318181_MHz_XTAL / 16); /* 894886.25 kHz */
+ // basic machine hardware
+ M6502(config, m_maincpu, 14.318181_MHz_XTAL / 16); // 894'886.25 kHz
m_maincpu->set_addrmap(AS_PROGRAM, &copsnrob_state::main_map);
- /* video hardware */
+ // video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(14.318181_MHz_XTAL / 2, 457, 0, 256, 261, 0, 200);
// H RESET (synchronous) = 256H & 8H & 64H & 128H
// V RESET (synchronous) = 256V & 4V
// H BLANK signal should begin at 304, but 256H gates all relevant graphics
- m_screen->set_screen_update(FUNC(copsnrob_state::screen_update_copsnrob));
+ m_screen->set_screen_update(FUNC(copsnrob_state::screen_update));
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_copsnrob);
PALETTE(config, m_palette, palette_device::MONOCHROME);
- copsnrob_audio(config);
+ // sound hardware
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+
+ discrete_sound_device &discrete(DISCRETE(config, "discrete", copsnrob_discrete));
+ discrete.add_route(0, "lspeaker", 1.0);
+ discrete.add_route(1, "rspeaker", 1.0);
+
+ f9334_device &latch(F9334(config, "latch")); // H3 on audio board
+ latch.q_out_cb<0>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR3_INV>));
+ latch.q_out_cb<1>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR2_INV>));
+ latch.q_out_cb<2>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR1_INV>));
+ latch.q_out_cb<3>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR0_INV>));
+ latch.q_out_cb<4>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_SCREECH_INV>));
+ latch.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_CRASH_INV>));
+ latch.q_out_cb<6>().set(FUNC(copsnrob_state::one_start_w));
+ latch.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_AUDIO_ENABLE>));
}
@@ -287,16 +480,16 @@ ROM_START( copsnrob )
ROM_LOAD( "5772.d7", 0x1c00, 0x0200, CRC(8d26afdc) SHA1(367f7e25c08a79277550d018681fffcdbd578029) )
ROM_LOAD( "5771.b7", 0x1e00, 0x0200, CRC(d61758d6) SHA1(7ce9ad1096405126a8bf57c1f8bad1afa178b751) )
- ROM_REGION( 0x0200, "gfx1", 0 )
+ ROM_REGION( 0x0200, "chars", 0 )
ROM_LOAD( "5782.m3", 0x0000, 0x0200, CRC(82b86852) SHA1(17cf6698ceeb3b917d8ef13ed8242062d3bd57b8) )
- ROM_REGION( 0x0800, "gfx2", 0 )
+ ROM_REGION( 0x0800, "car", 0 )
ROM_LOAD( "5778.p1", 0x0000, 0x0200, CRC(78bff86a) SHA1(8bba352ff5e320abda9c897cac4c898862f3c3f5) )
ROM_LOAD( "5779.m1", 0x0200, 0x0200, CRC(8b1d0d83) SHA1(3e45f55ddf10c7e9a221736c1f5a4cc5b4c8a317) )
ROM_LOAD( "5780.l1", 0x0400, 0x0200, CRC(6f4c6bab) SHA1(88d4ce8e86116cabd6e522360c01538930268074) )
ROM_LOAD( "5781.j1", 0x0600, 0x0200, CRC(c87f2f13) SHA1(18f31f46a3c7795e5d31ee55e8c98adc4c400328) )
- ROM_REGION( 0x0100, "gfx3", 0 )
+ ROM_REGION( 0x0100, "truck", 0 )
ROM_LOAD( "5770.m2", 0x0000, 0x0100, CRC(b00bbe77) SHA1(3fd6113aa3a572ec9f5ff248ba1bf53fc9225dfb) )
ROM_REGION( 0x0260, "proms", 0 ) /* misc. PROMs */
@@ -307,6 +500,7 @@ ROM_START( copsnrob )
ROM_LOAD( "5769.d5", 0x0160, 0x0100, CRC(75081a5a) SHA1(c7d60fc4c44cf9c160b874de92d37600c079e7b6) ) // vertical timing
ROM_END
+} // anonymous namespace
/*************************************
diff --git a/src/mame/atari/copsnrob.h b/src/mame/atari/copsnrob.h
deleted file mode 100644
index 2a958b2dc23..00000000000
--- a/src/mame/atari/copsnrob.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
-/*************************************************************************
-
- Atari Cops'n Robbers hardware
-
-*************************************************************************/
-#ifndef MAME_ATARI_COPSNROB_H
-#define MAME_ATARI_COPSNROB_H
-
-#pragma once
-
-#include "machine/74259.h"
-#include "sound/discrete.h"
-#include "emupal.h"
-#include "screen.h"
-
-
-class copsnrob_state : public driver_device
-{
-public:
- copsnrob_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_trucky(*this, "trucky"),
- m_truckram(*this, "truckram"),
- m_bulletsram(*this, "bulletsram"),
- m_carimage(*this, "carimage"),
- m_cary(*this, "cary"),
- m_videoram(*this, "videoram"),
- m_discrete(*this, "discrete"),
- m_maincpu(*this, "maincpu"),
- m_gfxdecode(*this, "gfxdecode"),
- m_screen(*this, "screen"),
- m_palette(*this, "palette"),
- m_leds(*this, "led%u", 0U)
- { }
-
- void copsnrob(machine_config &config);
-
-protected:
- virtual void machine_start() override;
- virtual void machine_reset() override;
- void copsnrob_audio(machine_config &config);
- void main_map(address_map &map);
-
- uint8_t copsnrob_misc_r();
- void copsnrob_misc2_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(one_start_w);
- uint32_t screen_update_copsnrob(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-
-private:
- /* memory pointers */
- required_shared_ptr<uint8_t> m_trucky;
- required_shared_ptr<uint8_t> m_truckram;
- required_shared_ptr<uint8_t> m_bulletsram;
- required_shared_ptr<uint8_t> m_carimage;
- required_shared_ptr<uint8_t> m_cary;
- required_shared_ptr<uint8_t> m_videoram;
- required_device<discrete_device> m_discrete;
-
- /* misc */
- uint8_t m_misc = 0U;
- uint8_t m_ic_h3_data = 0U;
-
- required_device<cpu_device> m_maincpu;
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<screen_device> m_screen;
- required_device<palette_device> m_palette;
-
- output_finder<2> m_leds;
-};
-
-#endif // MAME_ATARI_COPSNROB_H
diff --git a/src/mame/atari/copsnrob_a.cpp b/src/mame/atari/copsnrob_a.cpp
index 47df37d824d..576c79575cd 100644
--- a/src/mame/atari/copsnrob_a.cpp
+++ b/src/mame/atari/copsnrob_a.cpp
@@ -1,25 +1,15 @@
// license:BSD-3-Clause
-// copyright-holders:Derrick Renaud
+// copyright-holders: Derrick Renaud
+
/************************************************************************
* copsnrob Sound System Analog emulation
* Nov 2010, Derrick Renaud
************************************************************************/
-#include "emu.h"
-#include "copsnrob.h"
-#include "sound/discrete.h"
-#include "speaker.h"
-
-
-/* Discrete Sound Input Nodes */
-#define COPSNROB_MOTOR0_INV NODE_01
-#define COPSNROB_MOTOR1_INV NODE_02
-#define COPSNROB_MOTOR2_INV NODE_03
-#define COPSNROB_MOTOR3_INV NODE_04
-#define COPSNROB_ZINGS_INV NODE_05
-#define COPSNROB_FIRES_INV NODE_06
-#define COPSNROB_CRASH_INV NODE_07
-#define COPSNROB_SCREECH_INV NODE_08
-#define COPSNROB_AUDIO_ENABLE NODE_09
+
+ #include "emu.h"
+
+#include "copsnrob_a.h"
+
/* Discrete Sound Output Nodes */
#define COPSNROB_MOTOR0_SND NODE_11
@@ -391,10 +381,10 @@ DISCRETE_STEP(copsnrob_zings_555_monostable)
double x_time = 0;
/* From testing a real IC */
- /* Trigger going low overides everything. It forces the FF/Output high.
+ /* Trigger going low overrides everything. It forces the FF/Output high.
* If Threshold is high, the output will still go high as long as trigger is low.
- * The output will then go low when trigger rises above it's 1/3VCC value.
- * If threshold is below it's 2/3VCC value, the output will remain high.
+ * The output will then go low when trigger rises above its 1/3VCC value.
+ * If threshold is below its 2/3VCC value, the output will remain high.
*/
if (ff_set)
{
@@ -590,7 +580,7 @@ DISCRETE_RESET(copsnrob_zings_555_astable)
************************************************/
-static DISCRETE_SOUND_START(copsnrob_discrete)
+DISCRETE_SOUND_START(copsnrob_discrete)
/************************************************
* Input register mapping
@@ -686,32 +676,3 @@ static DISCRETE_SOUND_START(copsnrob_discrete)
DISCRETE_OUTPUT(NODE_90, 32767.0*3.5)
DISCRETE_OUTPUT(NODE_91, 32767.0*3.5)
DISCRETE_SOUND_END
-
-
-WRITE_LINE_MEMBER(copsnrob_state::one_start_w)
-{
- /* One Start */
- m_leds[0] = state ? 0 :1;
-}
-
-
-void copsnrob_state::copsnrob_audio(machine_config &config)
-{
- /* sound hardware */
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
-
- discrete_sound_device &discrete(DISCRETE(config, "discrete", copsnrob_discrete));
- discrete.add_route(0, "lspeaker", 1.0);
- discrete.add_route(1, "rspeaker", 1.0);
-
- f9334_device &latch(F9334(config, "latch")); // H3 on audio board
- latch.q_out_cb<0>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR3_INV>));
- latch.q_out_cb<1>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR2_INV>));
- latch.q_out_cb<2>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR1_INV>));
- latch.q_out_cb<3>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_MOTOR0_INV>));
- latch.q_out_cb<4>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_SCREECH_INV>));
- latch.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_CRASH_INV>));
- latch.q_out_cb<6>().set(FUNC(copsnrob_state::one_start_w));
- latch.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line<COPSNROB_AUDIO_ENABLE>));
-}
diff --git a/src/mame/atari/copsnrob_a.h b/src/mame/atari/copsnrob_a.h
new file mode 100644
index 00000000000..69ad7abd6a7
--- /dev/null
+++ b/src/mame/atari/copsnrob_a.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders: Derrick Renaud
+
+/***************************************************************************
+
+Cops'n Rob audio
+
+***************************************************************************/
+
+#ifndef MAME_ATARI_COPSNROB_A_H
+#define MAME_ATARI_COPSNROB_A_H
+
+#pragma once
+
+#include "sound/discrete.h"
+
+// discrete sound input nodes
+
+#define COPSNROB_MOTOR0_INV NODE_01
+#define COPSNROB_MOTOR1_INV NODE_02
+#define COPSNROB_MOTOR2_INV NODE_03
+#define COPSNROB_MOTOR3_INV NODE_04
+#define COPSNROB_ZINGS_INV NODE_05
+#define COPSNROB_FIRES_INV NODE_06
+#define COPSNROB_CRASH_INV NODE_07
+#define COPSNROB_SCREECH_INV NODE_08
+#define COPSNROB_AUDIO_ENABLE NODE_09
+
+
+DISCRETE_SOUND_EXTERN( copsnrob_discrete );
+
+#endif // MAME_ATARI_COPSNROB_A_H
diff --git a/src/mame/atari/copsnrob_v.cpp b/src/mame/atari/copsnrob_v.cpp
deleted file mode 100644
index e99577b4acf..00000000000
--- a/src/mame/atari/copsnrob_v.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Zsolt Vasvari
-/***************************************************************************
-
- Atari Cops'n Robbers hardware
-
-***************************************************************************/
-
-#include "emu.h"
-#include "copsnrob.h"
-
-
-uint32_t copsnrob_state::screen_update_copsnrob(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- /* redrawing the entire display is faster in this case */
- for (int offs = 0; offs < m_videoram.bytes(); offs++)
- {
- int const sx = 31 - (offs % 32);
- int const sy = offs / 32;
-
- m_gfxdecode->gfx(0)->opaque(bitmap,cliprect,
- m_videoram[offs] & 0x3f,0,
- 0,0,
- 8*sx,8*sy);
- }
-
-
- /* Draw the cars. Positioning was based on a screen shot */
- if (m_cary[0])
- m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
- m_carimage[0],0,
- 1,0,
- 0xe4,256 - m_cary[0],0);
-
- if (m_cary[1])
- m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
- m_carimage[1],0,
- 1,0,
- 0xc4,256 - m_cary[1],0);
-
- if (m_cary[2])
- m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
- m_carimage[2],0,
- 0,0,
- 0x24,256 - m_cary[2],0);
-
- if (m_cary[3])
- m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
- m_carimage[3],0,
- 0,0,
- 0x04,256 - m_cary[3],0);
-
-
- /* Draw the beer truck. Positioning was based on a screen shot.
- We scan the truck's window RAM for a location whose bit is set and
- which corresponds either to the truck's front end or the truck's back
- end (based on the value of the truck image line sync register). We
- then draw a truck image in the proper place and continue scanning.
- This is not a perfect emulation of the game hardware, but it should
- suffice for the way the game software uses the hardware. It does take
- care of the problem of displaying multiple beer trucks and of scrolling
- truck images smoothly off the top of the screen. */
-
- for (int y = 0; y < 256; y++)
- {
- /* y is going up the screen, but the truck window RAM locations
- go down the screen. */
-
- if (m_truckram[255 - y])
- {
- /* The hardware only uses the low 5 bits of the truck image line
- sync register. */
- if ((m_trucky[0] & 0x1f) == ((y + 31) & 0x1f))
- {
- /* We've hit a truck's back end, so draw the truck. The front
- end may be off the top of the screen, but we don't care. */
- m_gfxdecode->gfx(2)->transpen(bitmap,cliprect,
- 0,0,
- 0,0,
- 0x80,256 - (y + 31),0);
- /* Skip past this truck's front end so we don't draw this
- truck twice. */
- y += 31;
- }
- else if ((m_trucky[0] & 0x1f) == (y & 0x1f))
- {
- /* We missed a truck's back end (it was off the bottom of the
- screen) but have hit its front end, so draw the truck. */
- m_gfxdecode->gfx(2)->transpen(bitmap,cliprect,
- 0,0,
- 0,0,
- 0x80,256 - y,0);
- }
- }
- }
-
-
- /* Draw the bullets.
- They are flickered on/off every frame by the software, so don't
- play it with frameskip 1 or 3, as they could become invisible */
-
- for (int x = 0; x < 256; x++)
- {
- int const val = m_bulletsram[x];
-
- // Check for the most common case
- if (!(val & 0x0f))
- continue;
-
- int mask1 = 0x01;
- int mask2 = 0x10;
-
- // Check each bullet
- for (int bullet = 0; bullet < 4; bullet++)
- {
- if (val & mask1)
- {
- for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
- if (m_bulletsram[y] & mask2)
- bitmap.pix(y, 256 - x) = 1;
- }
-
- mask1 <<= 1;
- mask2 <<= 1;
- }
- }
- return 0;
-}