From 01171e2359cec767b4d5194aa8fc5169e123353c Mon Sep 17 00:00:00 2001 From: Ivan Vangelista Date: Fri, 19 May 2023 18:08:56 +0200 Subject: atari/cloak.cpp, atari/cloud9.cpp, atari/copsnrob.cpp: consolidated drivers in single files --- src/mame/atari/cloak.cpp | 388 ++++++++++++++++++++++++++++------ src/mame/atari/cloak.h | 78 ------- src/mame/atari/cloak_v.cpp | 222 -------------------- src/mame/atari/cloud9.cpp | 473 +++++++++++++++++++++++++++++++++++++----- src/mame/atari/cloud9.h | 88 -------- src/mame/atari/cloud9_v.cpp | 298 -------------------------- src/mame/atari/copsnrob.cpp | 272 ++++++++++++++++++++---- src/mame/atari/copsnrob.h | 73 ------- src/mame/atari/copsnrob_a.cpp | 61 +----- src/mame/atari/copsnrob_a.h | 32 +++ src/mame/atari/copsnrob_v.cpp | 128 ------------ 11 files changed, 1017 insertions(+), 1096 deletions(-) delete mode 100644 src/mame/atari/cloak.h delete mode 100644 src/mame/atari/cloak_v.cpp delete mode 100644 src/mame/atari/cloud9.h delete mode 100644 src/mame/atari/cloud9_v.cpp delete mode 100644 src/mame/atari/copsnrob.h create mode 100644 src/mame/atari/copsnrob_a.h delete mode 100644 src/mame/atari/copsnrob_v.cpp 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 m_maincpu; + required_device m_slave; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + required_shared_ptr m_videoram; + required_shared_ptr m_spriteram; + memory_share_array_creator m_bitmap_videoram; + std::unique_ptr 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 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(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 +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 m_videoram; - required_shared_ptr 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 m_bitmap_videoram1; - std::unique_ptr m_bitmap_videoram2; - uint8_t *m_current_bitmap_videoram_accessed = nullptr; - uint8_t *m_current_bitmap_videoram_displayed = nullptr; - std::unique_ptr m_palette_ram; - tilemap_t *m_bg_tilemap = nullptr; - - required_device m_maincpu; - required_device m_slave; - required_device m_gfxdecode; - required_device m_screen; - required_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(256*256); - m_bitmap_videoram2 = std::make_unique(256*256); - m_palette_ram = std::make_unique(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,22 +94,384 @@ ***************************************************************************/ #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 m_maincpu; + required_device m_nvram; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + required_device m_videolatch; + + // memory pointers + memory_share_creator m_videoram; + required_shared_ptr m_spriteram; + required_shared_ptr m_paletteram; + required_region_ptr m_syncprom; + required_region_ptr 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 @@ -117,34 +480,34 @@ 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 m_maincpu; - required_device m_nvram; - /* memory pointers */ - std::unique_ptr m_videoram; - required_shared_ptr m_spriteram; - required_shared_ptr m_paletteram; - - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - required_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(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 m_trucky; + required_shared_ptr m_truckram; + required_shared_ptr m_bulletsram; + required_shared_ptr m_carimage; + required_shared_ptr m_cary; + required_shared_ptr m_videoram; + + required_device m_discrete; + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_screen; + required_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)); + latch.q_out_cb<1>().set("discrete", FUNC(discrete_device::write_line)); + latch.q_out_cb<2>().set("discrete", FUNC(discrete_device::write_line)); + latch.q_out_cb<3>().set("discrete", FUNC(discrete_device::write_line)); + latch.q_out_cb<4>().set("discrete", FUNC(discrete_device::write_line)); + latch.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line)); + latch.q_out_cb<6>().set(FUNC(copsnrob_state::one_start_w)); + latch.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line)); } @@ -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 m_trucky; - required_shared_ptr m_truckram; - required_shared_ptr m_bulletsram; - required_shared_ptr m_carimage; - required_shared_ptr m_cary; - required_shared_ptr m_videoram; - required_device m_discrete; - - /* misc */ - uint8_t m_misc = 0U; - uint8_t m_ic_h3_data = 0U; - - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_screen; - required_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)); - latch.q_out_cb<1>().set("discrete", FUNC(discrete_device::write_line)); - latch.q_out_cb<2>().set("discrete", FUNC(discrete_device::write_line)); - latch.q_out_cb<3>().set("discrete", FUNC(discrete_device::write_line)); - latch.q_out_cb<4>().set("discrete", FUNC(discrete_device::write_line)); - latch.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line)); - latch.q_out_cb<6>().set(FUNC(copsnrob_state::one_start_w)); - latch.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line)); -} 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; -} -- cgit v1.2.3