From d90099fc75a8945da7e68652717ff971e5a9a609 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 19 Jan 2021 21:28:17 -0500 Subject: [PATCH] cosmicg: Driver overhaul - Separate driver from cosmic.cpp - Add MC6845 CRTC and use it for all video updates - Configure screen with raw parameters - Add support for display flipping in cocktail mode --- scripts/target/mame/arcade.lua | 1 + src/mame/arcade.flt | 1 + src/mame/drivers/cosmic.cpp | 276 +-------------------- src/mame/drivers/cosmicg.cpp | 433 +++++++++++++++++++++++++++++++++ src/mame/includes/cosmic.h | 57 ++--- src/mame/mame.lst | 6 +- src/mame/video/cosmic.cpp | 41 ---- 7 files changed, 465 insertions(+), 350 deletions(-) create mode 100644 src/mame/drivers/cosmicg.cpp diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index aaa8e53cf89..a98c4d94540 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -4450,6 +4450,7 @@ files { MAME_DIR .. "src/mame/drivers/cosmic.cpp", MAME_DIR .. "src/mame/includes/cosmic.h", MAME_DIR .. "src/mame/video/cosmic.cpp", + MAME_DIR .. "src/mame/drivers/cosmicg.cpp", MAME_DIR .. "src/mame/drivers/docastle.cpp", MAME_DIR .. "src/mame/includes/docastle.h", MAME_DIR .. "src/mame/machine/docastle.cpp", diff --git a/src/mame/arcade.flt b/src/mame/arcade.flt index d9a25abd7c5..63559f39cf3 100644 --- a/src/mame/arcade.flt +++ b/src/mame/arcade.flt @@ -260,6 +260,7 @@ cops.cpp copsnrob.cpp corona.cpp cosmic.cpp +cosmicg.cpp cowtipping.cpp cps1.cpp cps1bl_5205.cpp diff --git a/src/mame/drivers/cosmic.cpp b/src/mame/drivers/cosmic.cpp index 6b4eaae00d3..d4892f74393 100644 --- a/src/mame/drivers/cosmic.cpp +++ b/src/mame/drivers/cosmic.cpp @@ -27,10 +27,6 @@ a physical DSW B but only read when SWA:3,4 are both set to OFF. Currently, * In devzone, setting SWA:3,4 on anything but OFF,OFF results in no coins accepted at all -cosmicg - background should be blue -cosmicg - board can operate in b&w mode if there is no PROM, in this case - a colour overlay should be used. - ***************************************************************************/ @@ -127,67 +123,6 @@ void cosmic_state::panic_sound_output2_w(offs_t offset, uint8_t data) #endif } -void cosmic_state::cosmicg_output_w(offs_t offset, uint8_t data) -{ - /* Sound Enable / Disable */ - if (offset == 12) - { - int count; - - m_sound_enabled = data; - if (data == 0) - for (count = 0; count < 9; count++) - m_samples->stop(count); - } - - if (m_sound_enabled) - { - switch (offset) - { - /* The schematics show a direct link to the sound amp */ - /* as other cosmic series games, but it is toggled */ - /* once during game over. It is implemented for sake */ - /* of completeness. */ - case 1: m_dac->write(BIT(data, 0)); break; /* Game Over */ - case 2: if (data) m_samples->start(0, m_march_select); break; /* March Sound */ - case 3: m_march_select = (m_march_select & 0xfe) | data; break; - case 4: m_march_select = (m_march_select & 0xfd) | (data << 1); break; - case 5: m_march_select = (m_march_select & 0xfb) | (data << 2); break; - - case 6: if (data) /* Killer Attack (crawly thing at bottom of screen) */ - m_samples->start(1, 8, true); - else - m_samples->stop(1); - break; - - case 7: if (data) /* Bonus Chance & Got Bonus */ - { - m_samples->stop(4); - m_samples->start(4, 10); - } - break; - - case 8: if (data) - { - if (!m_samples->playing(4)) m_samples->start(4, 9, true); - } - else - m_samples->stop(4); - break; - - case 9: if (data) m_samples->start(3, 11); break; /* Got Ship */ - case 11: /* watchdog_reset_w(0, 0); */ break; /* Watchdog? only toggles during game play */ - case 13: if (data) m_samples->start(8, 13 - m_gun_die_select); break; /* Got Monster / Gunshot */ - case 14: m_gun_die_select = data; break; - case 15: if (data) m_samples->start(5, 14); break; /* Coin Extend (extra base) */ - } - } - - #ifdef MAME_DEBUG - if (offset != 11) logerror("cosmicg_output_w %x=%x\n", offset, data); - #endif -} - void cosmic_state::cosmica_sound_output_w(offs_t offset, uint8_t data) { @@ -313,20 +248,6 @@ uint8_t cosmic_state::cosmica_pixel_clock_r() return (m_screen->vpos() >> 2) & 0x3f; } -uint8_t cosmic_state::cosmicg_port_0_r(offs_t offset) -{ - /* The top four address lines from the CRTC are bits 0-3 */ - if (offset >= 4) - return BIT(m_in_ports[0]->read(), offset); - else - return BIT(m_screen->vpos(), offset + 4); -} - -uint8_t cosmic_state::cosmicg_port_1_r(offs_t offset) -{ - return BIT(m_in_ports[1]->read(), offset); -} - uint8_t cosmic_state::magspot_coinage_dip_r(offs_t offset) { return (m_dsw.read_safe(0) & (1 << (7 - offset))) ? 0 : 1; @@ -391,21 +312,6 @@ void cosmic_state::cosmica_map(address_map &map) } -void cosmic_state::cosmicg_map(address_map &map) -{ - map(0x0000, 0x1fff).rom(); - map(0x2000, 0x3fff).ram().share("videoram"); -} - -void cosmic_state::cosmicg_io_map(address_map &map) -{ - map(0x0000, 0x000f).r(FUNC(cosmic_state::cosmicg_port_0_r)); - map(0x0010, 0x001f).r(FUNC(cosmic_state::cosmicg_port_1_r)); - map(0x0000, 0x002b).w(FUNC(cosmic_state::cosmicg_output_w)); - map(0x002c, 0x002f).w(FUNC(cosmic_state::cosmic_color_register_w)); -} - - void cosmic_state::magspot_map(address_map &map) { map(0x0000, 0x2fff).rom(); @@ -537,58 +443,6 @@ static INPUT_PORTS_START( cosmica ) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, cosmic_state,cosmica_coin_inserted, 0) INPUT_PORTS_END -/* These are used for the CR handling - This can be used to */ -/* from 1 to 16 bits from any bit offset between 0 and 4096 */ - -/* Offsets are in BYTES, so bits 0-7 are at offset 0 etc. */ - -INPUT_CHANGED_MEMBER(cosmic_state::cosmicg_coin_inserted) -{ - m_maincpu->set_input_line(INT_9980A_LEVEL4, newval? ASSERT_LINE : CLEAR_LINE); -} - -static INPUT_PORTS_START( cosmicg ) - PORT_START("IN0") /* 4-7 */ - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) /* pixel clock */ - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY - - PORT_START("IN1") /* 8-15 */ - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_2WAY - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_2WAY PORT_COCKTAIL - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_2WAY PORT_COCKTAIL - PORT_DIPNAME( 0x30, 0x30, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW:2,1") - PORT_DIPSETTING( 0x10, "1000" ) - PORT_DIPSETTING( 0x20, "1500" ) - PORT_DIPSETTING( 0x30, "2000" ) - PORT_DIPSETTING( 0x00, DEF_STR( None ) ) - PORT_DIPNAME( 0x40, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW:3") - PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ) ) - PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) - PORT_DIPNAME( 0x80, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:4") - PORT_DIPSETTING( 0x00, "3" ) - PORT_DIPSETTING( 0x80, "5" ) - - PORT_START("IN2") /* Hard wired settings */ - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, cosmic_state,cosmicg_coin_inserted, 0) - - /* This dip switch is not read by the program at any time */ - /* but is wired to enable or disable the flip screen output */ - - PORT_DIPNAME( 0x02, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW:5") - PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Cocktail ) ) - - /* This odd setting is marked as shown on the schematic, */ - /* and again, is not read by the program, but wired into */ - /* the watchdog circuit. The book says to leave it off */ - - PORT_DIPUNUSED_DIPLOC( 0x04, 0x00, "SW:6" ) -INPUT_PORTS_END - INPUT_CHANGED_MEMBER(cosmic_state::coin_inserted_irq0) { m_maincpu->set_input_line(0, newval ? HOLD_LINE : CLEAR_LINE); @@ -935,68 +789,30 @@ static const char *const panic_sample_names[] = }; -static const char *const cosmicg_sample_names[] = -{ - "*cosmicg", - "cg_m0", /* 8 Different pitches of March Sound */ - "cg_m1", - "cg_m2", - "cg_m3", - "cg_m4", - "cg_m5", - "cg_m6", - "cg_m7", - "cg_att", /* Killer Attack */ - "cg_chnc", /* Bonus Chance */ - "cg_gotb", /* Got Bonus - have not got correct sound for */ - "cg_dest", /* Gun Destroy */ - "cg_gun", /* Gun Shot */ - "cg_gotm", /* Got Monster */ - "cg_ext", /* Coin Extend */ - nullptr -}; - - -MACHINE_START_MEMBER(cosmic_state,cosmic) +void cosmic_state::machine_start() { save_item(NAME(m_sound_enabled)); save_item(NAME(m_march_select)); save_item(NAME(m_gun_die_select)); save_item(NAME(m_dive_bomb_b_select)); - save_item(NAME(m_pixel_clock)); save_item(NAME(m_background_enable)); save_item(NAME(m_color_registers)); } -MACHINE_RESET_MEMBER(cosmic_state,cosmic) +void cosmic_state::machine_reset() { - m_pixel_clock = 0; m_background_enable = 0; m_color_registers[0] = 0; m_color_registers[1] = 0; m_color_registers[2] = 0; } -MACHINE_RESET_MEMBER(cosmic_state,cosmicg) -{ - m_pixel_clock = 0; - m_background_enable = 0; - m_color_registers[0] = 0; - m_color_registers[1] = 0; - m_color_registers[2] = 0; - m_maincpu->set_input_line(INT_9980A_RESET, ASSERT_LINE); - m_maincpu->set_input_line(INT_9980A_RESET, CLEAR_LINE); -} - void cosmic_state::cosmic(machine_config &config) { /* basic machine hardware */ Z80(config, m_maincpu, Z80_MASTER_CLOCK/6); /* 1.8026 MHz */ - MCFG_MACHINE_START_OVERRIDE(cosmic_state,cosmic) - MCFG_MACHINE_RESET_OVERRIDE(cosmic_state,cosmic) - /* video hardware */ SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); @@ -1064,38 +880,6 @@ void cosmic_state::cosmica(machine_config &config) m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); } -void cosmic_state::cosmicg(machine_config &config) -{ - /* basic machine hardware */ - TMS9980A(config, m_maincpu, COSMICG_MASTER_CLOCK); // 9.828 MHz Crystal - m_maincpu->set_addrmap(AS_PROGRAM, &cosmic_state::cosmicg_map); - m_maincpu->set_addrmap(AS_IO, &cosmic_state::cosmicg_io_map); - - MCFG_MACHINE_START_OVERRIDE(cosmic_state,cosmic) - MCFG_MACHINE_RESET_OVERRIDE(cosmic_state,cosmicg) - - /* video hardware */ - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(60); - m_screen->set_size(32*8, 32*8); - m_screen->set_visarea(0*8, 32*8-1, 4*8, 28*8-1); - m_screen->set_screen_update(FUNC(cosmic_state::screen_update_cosmicg)); - m_screen->set_palette(m_palette); - - PALETTE(config, m_palette, FUNC(cosmic_state::cosmicg_palette), 16); - - /* sound hardware */ - SPEAKER(config, "speaker").front_center(); - - SAMPLES(config, m_samples); - m_samples->set_channels(9); - m_samples->set_samples_names(cosmicg_sample_names); - m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); - - DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // NE556 - // Other DACs include 3-bit binary-weighted (100K/50K/25K) DAC combined with another NE556 for attack march -} - void cosmic_state::magspot(machine_config &config) { cosmic(config); @@ -1359,37 +1143,6 @@ ROM_START( cosmica3 ) // main: 7910-AII sub: 7910-BII sound: 7910-S ROM_LOAD( "8-8.ic10", 0x0000, 0x0400, CRC(acbd4e98) SHA1(d33fe8bdc77bb18a3ffb369ea692210d1b890771) ) ROM_END -ROM_START( cosmicg ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* 8k for code */ - ROM_LOAD( "cosmicg1.bin", 0x0000, 0x0400, CRC(e1b9f894) SHA1(bab7fd9b3db145a889542653191905b6efc5ce75) ) - ROM_LOAD( "cosmicg2.bin", 0x0400, 0x0400, CRC(35c75346) SHA1(4e50eaa0b50ab04802dc63992ad2600c227301ad) ) - ROM_LOAD( "cosmicg3.bin", 0x0800, 0x0400, CRC(82a49b48) SHA1(4cf9f684f3eb18b99a88ca879bb7083b1334f0cc) ) - ROM_LOAD( "cosmicg4.bin", 0x0c00, 0x0400, CRC(1c1c934c) SHA1(011b2b3ec4d31869fda13a3654c7bc51f3ce4dc2) ) - ROM_LOAD( "cosmicg5.bin", 0x1000, 0x0400, CRC(b1c00fbf) SHA1(136267f75e2d5b445695cabef4538f986e6f1b10) ) - ROM_LOAD( "cosmicg6.bin", 0x1400, 0x0400, CRC(f03454ce) SHA1(32c87f369475c7154fe3243d2c7be4a25444e530) ) - ROM_LOAD( "cosmicg7.bin", 0x1800, 0x0400, CRC(f33ebae7) SHA1(915bca53d5356e12c94ec765103ceced7306d1dd) ) - ROM_LOAD( "cosmicg8.bin", 0x1c00, 0x0400, CRC(472e4990) SHA1(d5797b9d89446aa6533f7515e6a5fc8368d82f91) ) - - ROM_REGION( 0x0400, "user1", 0 ) /* color map */ - ROM_LOAD( "cosmicg9.bin", 0x0000, 0x0400, CRC(689c2c96) SHA1(ddfdc3fd29c56fdebd3b1c3443a7c39f567d5355) ) -ROM_END - - -ROM_START( cosmicgi ) - ROM_REGION( 0x10000, "maincpu", 0 ) /* 8k for code */ - ROM_LOAD( "1g118.2h", 0x0000, 0x0400, CRC(4bda1711) SHA1(746fd15dbe08c9e2af74547c19a55a84f7b65303) ) - ROM_LOAD( "2g118.3h", 0x0400, 0x0400, CRC(3c10b2ba) SHA1(127a950d90420417a91aa3c8fabec7d7e7d526f5) ) - ROM_LOAD( "3.4h", 0x0800, 0x0400, CRC(82a49b48) SHA1(4cf9f684f3eb18b99a88ca879bb7083b1334f0cc) ) - ROM_LOAD( "4g118.5h", 0x0c00, 0x0400, CRC(42bb0611) SHA1(3894e4372f1443402ea7145b1101e1219fe2cde2) ) // changes in here cause trails when you move the ship, PCB does the same and ROM gives the same read every time, possible a bit has been flipped tho. check - ROM_LOAD( "5.6h", 0x1000, 0x0400, CRC(b1c00fbf) SHA1(136267f75e2d5b445695cabef4538f986e6f1b10) ) - ROM_LOAD( "6.7h", 0x1400, 0x0400, CRC(f03454ce) SHA1(32c87f369475c7154fe3243d2c7be4a25444e530) ) - ROM_LOAD( "7.8h", 0x1800, 0x0400, CRC(84656c97) SHA1(2180faa07dd5bc618c80ae033babfc1191a0b890) ) // standard label but different anyway? - ROM_LOAD( "8g128.9h", 0x1c00, 0x0400, CRC(7f48307c) SHA1(5929c131d790b0c8f9113730715531809c6840e2) ) - - ROM_REGION( 0x0400, "user1", 0 ) /* color map */ // population of this is optional, board runs as b&w without (this board didn't have it populated) - ROM_LOAD( "cosmicg9.bin", 0x0000, 0x0400, CRC(689c2c96) SHA1(ddfdc3fd29c56fdebd3b1c3443a7c39f567d5355) ) -ROM_END - /* rom 9 not dumped according to readme? */ ROM_START( magspot ) @@ -1533,29 +1286,6 @@ ROM_START( nomnlndg ) ROM_END -void cosmic_state::init_cosmicg() -{ - /* Program ROMs have data pins connected different from normal */ - offs_t len = memregion("maincpu")->bytes(); - uint8_t *rom = memregion("maincpu")->base(); - for (offs_t offs = 0; offs < len; offs++) - { - uint8_t scrambled = rom[offs]; - - uint8_t normal = (scrambled >> 3 & 0x11) - | (scrambled >> 1 & 0x22) - | (scrambled << 1 & 0x44) - | (scrambled << 3 & 0x88); - - rom[offs] = normal; - } - - m_sound_enabled = 0; - m_march_select = 0; - m_gun_die_select = 0; -} - - void cosmic_state::init_cosmica() { m_sound_enabled = 1; @@ -1583,8 +1313,6 @@ void cosmic_state::init_panic() } -GAME( 1979, cosmicg, 0, cosmicg, cosmicg, cosmic_state, init_cosmicg, ROT270, "Universal", "Cosmic Guerilla", MACHINE_IMPERFECT_SOUND | MACHINE_NO_COCKTAIL /*| MACHINE_SUPPORTS_SAVE */) -GAME( 1979, cosmicgi, cosmicg, cosmicg, cosmicg, cosmic_state, init_cosmicg, ROT270, "bootleg (Inder)", "Cosmic Guerilla (Spanish bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_NO_COCKTAIL /*| MACHINE_SUPPORTS_SAVE */) GAME( 1979, cosmica, 0, cosmica, cosmica, cosmic_state, init_cosmica, ROT270, "Universal", "Cosmic Alien (version II, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, cosmica3, cosmica, cosmica, cosmica, cosmic_state, init_cosmica, ROT270, "Universal", "Cosmic Alien (version II, set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, cosmica1, cosmica, cosmica, cosmica, cosmic_state, init_cosmica, ROT270, "Universal", "Cosmic Alien (first version)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/cosmicg.cpp b/src/mame/drivers/cosmicg.cpp new file mode 100644 index 00000000000..4de1a173f01 --- /dev/null +++ b/src/mame/drivers/cosmicg.cpp @@ -0,0 +1,433 @@ +// license:BSD-3-Clause +// copyright-holders:Nicola Salmoria, Lee Taylor, AJR +/*************************************************************************** + +Cosmic Guerilla by Universal (board number 7907A) + +Notes: +- background should be blue +- board can operate in b&w mode if there is no PROM, in this case + a colour overlay should be used. + +***************************************************************************/ + +#include "emu.h" + +#include "cpu/tms9900/tms9980a.h" +#include "sound/dac.h" +#include "sound/samples.h" +#include "video/mc6845.h" +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + + +class cosmicg_state : public driver_device +{ +public: + cosmicg_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_crtc(*this, "crtc") + , m_palette(*this, "palette") + , m_samples(*this, "samples") + , m_dac(*this, "dac") + , m_in_ports(*this, "IN%u", 0) + , m_videoram(*this, "videoram") + , m_colormap(*this, "colormap") + { + } + + void cosmicg(machine_config &config); + void init_cosmicg(); + + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + void cosmicg_palette(palette_device &palette); + MC6845_UPDATE_ROW(draw_scanline); + + void cosmicg_output_w(offs_t offset, u8 data); + u8 cosmicg_port_0_r(offs_t offset); + u8 cosmicg_port_1_r(offs_t offset); + void cosmic_color_register_w(offs_t offset, u8 data); + + void mem_map(address_map &map); + void cru_map(address_map &map); + + required_device m_maincpu; + required_device m_crtc; + required_device m_palette; + required_device m_samples; + required_device m_dac; + required_ioport_array<3> m_in_ports; + required_shared_ptr m_videoram; + required_region_ptr m_colormap; + + /* video-related */ + int m_color_registers[2]; + bool m_flip_screen; + + /* sound-related */ + int m_sound_enabled; + int m_march_select; + int m_gun_die_select; +}; + + +/* + * Cosmic guerilla table setup + * + * Use AA for normal, FF for Full Red + * Bit 0 = R, bit 1 = G, bit 2 = B, bit 4 = High Red + * + * It's possible that the background is dark gray and not black, as the + * resistor chain would never drop to zero, Anybody know ? + */ +void cosmicg_state::cosmicg_palette(palette_device &palette) +{ + for (int i = 0; i < palette.entries(); i++) + { + int const r = (i > 8) ? 0xff : 0xaa * BIT(i, 0); + int const g = 0xaa * BIT(i, 1); + int const b = 0xaa * BIT(i, 2); + + palette.set_pen_color(i, rgb_t(r, g, b)); + } +} + + +void cosmicg_state::cosmicg_output_w(offs_t offset, u8 data) +{ + /* Sound Enable / Disable */ + if (offset == 12) + { + int count; + + m_sound_enabled = data; + if (data == 0) + for (count = 0; count < 9; count++) + m_samples->stop(count); + } + if (m_sound_enabled) + { + switch (offset) + { + /* The schematics show a direct link to the sound amp */ + /* as other cosmic series games, but it is toggled */ + /* once during game over. It is implemented for sake */ + /* of completeness. */ + case 1: m_dac->write(BIT(data, 0)); break; /* Game Over */ + case 2: if (data) m_samples->start(0, m_march_select); break; /* March Sound */ + case 3: m_march_select = (m_march_select & 0xfe) | data; break; + case 4: m_march_select = (m_march_select & 0xfd) | (data << 1); break; + case 5: m_march_select = (m_march_select & 0xfb) | (data << 2); break; + + case 6: if (data) /* Killer Attack (crawly thing at bottom of screen) */ + m_samples->start(1, 8, true); + else + m_samples->stop(1); + break; + + case 7: if (data) /* Bonus Chance & Got Bonus */ + { + m_samples->stop(4); + m_samples->start(4, 10); + } + break; + + case 8: if (data) + { + if (!m_samples->playing(4)) m_samples->start(4, 9, true); + } + else + m_samples->stop(4); + break; + + case 9: if (data) m_samples->start(3, 11); break; /* Got Ship */ + case 11: /* watchdog_reset_w(0, 0); */ break; /* Watchdog? only toggles during game play */ + case 13: if (data) m_samples->start(8, 13 - m_gun_die_select); break; /* Got Monster / Gunshot */ + case 14: m_gun_die_select = data; break; + case 15: if (data) m_samples->start(5, 14); break; /* Coin Extend (extra base) */ + } + } + + if (offset == 10) + m_flip_screen = BIT(data, 0); + + #ifdef MAME_DEBUG + if (offset != 11) logerror("cosmicg_output_w %x=%x\n", offset, data); + #endif +} + +u8 cosmicg_state::cosmicg_port_0_r(offs_t offset) +{ + /* The top four address lines from the CRTC are bits 0-3 */ + if (offset >= 4) + return BIT(m_in_ports[0]->read(), offset); + else + return BIT(m_crtc->get_ma(), offset + 8); +} + +u8 cosmicg_state::cosmicg_port_1_r(offs_t offset) +{ + return BIT(m_in_ports[1]->read(), offset); +} + + +void cosmicg_state::cosmic_color_register_w(offs_t offset, u8 data) +{ + m_color_registers[offset] = data ? 1 : 0; +} + + +MC6845_UPDATE_ROW(cosmicg_state::draw_scanline) +{ + u32 *pix = &bitmap.pix(y); + u8 const *const colors = &m_colormap[m_color_registers[0] << 8 | m_color_registers[1] << 9]; + + // MA7-MA12 on schematics are actually MA6-MA11, with RA0 being nominal MA6 + if (m_flip_screen && BIT(m_in_ports[2]->read(), 1)) + { + while (x_count-- != 0) + { + u16 offs = (~ma & 0x001f) | (~ra & 1) << 5 | (~ma & 0x0fe0) << 1; + u8 data = (offs >= m_videoram.length()) ? 0 : m_videoram[offs]; + u8 color = colors[(~offs & 0x1e00) >> 5 | (~offs & 0x001e) >> 1] >> 4; + for (int n = 8; n != 0; n--) + { + *pix++ = m_palette->pen(BIT(data, 0) ? color : color & 0x08); + data >>= 1; + } + ma++; + } + } + else + { + while (x_count-- != 0) + { + u16 offs = (ma & 0x001f) | (ra & 1) << 5 | (ma & 0x0fe0) << 1; + u8 data = (offs >= m_videoram.length()) ? 0 : m_videoram[offs]; + u8 color = colors[(offs & 0x1e00) >> 5 | (offs & 0x001e) >> 1] & 0x0f; + for (int n = 8; n != 0; n--) + { + *pix++ = m_palette->pen(BIT(data, 7) ? color : color & 0x08); + data <<= 1; + } + ma++; + } + } +} + + +void cosmicg_state::mem_map(address_map &map) +{ + map(0x0000, 0x1fff).rom().region("program", 0); + map(0x2000, 0x3fff).ram().share("videoram"); + + // CRTC is accessed through a small hole in the video RAM area with A11 = RS, A12 = R/W & A13 = EN + map(0x3ff0, 0x3ff7).noprw(); + map(0x3ff1, 0x3ff1).w("crtc", FUNC(mc6845_device::address_w)); + map(0x3ff5, 0x3ff5).w("crtc", FUNC(mc6845_device::register_w)); + map(0x3ff7, 0x3ff7).r("crtc", FUNC(mc6845_device::register_r)); +} + +void cosmicg_state::cru_map(address_map &map) +{ + map(0x0000, 0x000f).r(FUNC(cosmicg_state::cosmicg_port_0_r)); + map(0x0010, 0x001f).r(FUNC(cosmicg_state::cosmicg_port_1_r)); + map(0x0000, 0x002b).w(FUNC(cosmicg_state::cosmicg_output_w)); + map(0x002c, 0x002f).w(FUNC(cosmicg_state::cosmic_color_register_w)); +} + + +/* These are used for the CR handling - This can be used to */ +/* from 1 to 16 bits from any bit offset between 0 and 4096 */ + +/* Offsets are in BYTES, so bits 0-7 are at offset 0 etc. */ + +INPUT_CHANGED_MEMBER(cosmicg_state::coin_inserted) +{ + m_maincpu->set_input_line(INT_9980A_LEVEL4, newval ? ASSERT_LINE : CLEAR_LINE); +} + +static INPUT_PORTS_START( cosmicg ) + PORT_START("IN0") /* 4-7 */ + PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) /* pixel clock */ + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY + + PORT_START("IN1") /* 8-15 */ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_2WAY + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_2WAY PORT_COCKTAIL + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_2WAY PORT_COCKTAIL + PORT_DIPNAME( 0x30, 0x30, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW:2,1") + PORT_DIPSETTING( 0x10, "1000" ) + PORT_DIPSETTING( 0x20, "1500" ) + PORT_DIPSETTING( 0x30, "2000" ) + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPNAME( 0x40, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW:3") + PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) + PORT_DIPNAME( 0x80, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:4") + PORT_DIPSETTING( 0x00, "3" ) + PORT_DIPSETTING( 0x80, "5" ) + + PORT_START("IN2") /* Hard wired settings */ + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, cosmicg_state, coin_inserted, 0) + + /* This dip switch is not read by the program at any time */ + /* but is wired to enable or disable the flip screen output */ + + PORT_DIPNAME( 0x02, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW:5") + PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Cocktail ) ) + + /* This odd setting is marked as shown on the schematic, */ + /* and again, is not read by the program, but wired into */ + /* the watchdog circuit. The book says to leave it off */ + + PORT_DIPUNUSED_DIPLOC( 0x04, 0x00, "SW:6" ) +INPUT_PORTS_END + + +static const char *const cosmicg_sample_names[] = +{ + "*cosmicg", + "cg_m0", /* 8 Different pitches of March Sound */ + "cg_m1", + "cg_m2", + "cg_m3", + "cg_m4", + "cg_m5", + "cg_m6", + "cg_m7", + "cg_att", /* Killer Attack */ + "cg_chnc", /* Bonus Chance */ + "cg_gotb", /* Got Bonus - have not got correct sound for */ + "cg_dest", /* Gun Destroy */ + "cg_gun", /* Gun Shot */ + "cg_gotm", /* Got Monster */ + "cg_ext", /* Coin Extend */ + nullptr +}; + + +void cosmicg_state::machine_start() +{ + save_item(NAME(m_sound_enabled)); + save_item(NAME(m_march_select)); + save_item(NAME(m_gun_die_select)); + + save_item(NAME(m_color_registers)); + save_item(NAME(m_flip_screen)); +} + +void cosmicg_state::machine_reset() +{ + m_color_registers[0] = 0; + m_color_registers[1] = 0; + m_flip_screen = false; + + m_maincpu->set_input_line(INT_9980A_RESET, ASSERT_LINE); + m_maincpu->set_input_line(INT_9980A_RESET, CLEAR_LINE); +} + + +void cosmicg_state::cosmicg(machine_config &config) +{ + /* basic machine hardware */ + TMS9980A(config, m_maincpu, 9.828_MHz_XTAL); + m_maincpu->set_addrmap(AS_PROGRAM, &cosmicg_state::mem_map); + m_maincpu->set_addrmap(AS_IO, &cosmicg_state::cru_map); + + /* video hardware */ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(9.828_MHz_XTAL / 2, 312, 0, 256, 263, 0, 192); + screen.set_screen_update(m_crtc, FUNC(mc6845_device::screen_update)); + + PALETTE(config, m_palette, FUNC(cosmicg_state::cosmicg_palette), 16); + + MC6845(config, m_crtc, 9.828_MHz_XTAL / 16); // character clock is phase-locked to CPU + m_crtc->set_screen("screen"); + m_crtc->set_show_border_area(false); + m_crtc->set_char_width(8); + m_crtc->set_update_row_callback(FUNC(cosmicg_state::draw_scanline)); + + /* sound hardware */ + SPEAKER(config, "speaker").front_center(); + + SAMPLES(config, m_samples); + m_samples->set_channels(9); + m_samples->set_samples_names(cosmicg_sample_names); + m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); + + DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // NE556 + // Other DACs include 3-bit binary-weighted (100K/50K/25K) DAC combined with another NE556 for attack march +} + + +ROM_START( cosmicg ) + ROM_REGION( 0x2000, "program", 0 ) /* 8k for code */ + ROM_LOAD( "cosmicg1.bin", 0x0000, 0x0400, CRC(e1b9f894) SHA1(bab7fd9b3db145a889542653191905b6efc5ce75) ) + ROM_LOAD( "cosmicg2.bin", 0x0400, 0x0400, CRC(35c75346) SHA1(4e50eaa0b50ab04802dc63992ad2600c227301ad) ) + ROM_LOAD( "cosmicg3.bin", 0x0800, 0x0400, CRC(82a49b48) SHA1(4cf9f684f3eb18b99a88ca879bb7083b1334f0cc) ) + ROM_LOAD( "cosmicg4.bin", 0x0c00, 0x0400, CRC(1c1c934c) SHA1(011b2b3ec4d31869fda13a3654c7bc51f3ce4dc2) ) + ROM_LOAD( "cosmicg5.bin", 0x1000, 0x0400, CRC(b1c00fbf) SHA1(136267f75e2d5b445695cabef4538f986e6f1b10) ) + ROM_LOAD( "cosmicg6.bin", 0x1400, 0x0400, CRC(f03454ce) SHA1(32c87f369475c7154fe3243d2c7be4a25444e530) ) + ROM_LOAD( "cosmicg7.bin", 0x1800, 0x0400, CRC(f33ebae7) SHA1(915bca53d5356e12c94ec765103ceced7306d1dd) ) + ROM_LOAD( "cosmicg8.bin", 0x1c00, 0x0400, CRC(472e4990) SHA1(d5797b9d89446aa6533f7515e6a5fc8368d82f91) ) + + ROM_REGION( 0x0400, "colormap", 0 ) /* color map */ + ROM_LOAD( "cosmicg9.bin", 0x0000, 0x0400, CRC(689c2c96) SHA1(ddfdc3fd29c56fdebd3b1c3443a7c39f567d5355) ) +ROM_END + + +ROM_START( cosmicgi ) + ROM_REGION( 0x2000, "program", 0 ) /* 8k for code */ + ROM_LOAD( "1g118.2h", 0x0000, 0x0400, CRC(4bda1711) SHA1(746fd15dbe08c9e2af74547c19a55a84f7b65303) ) + ROM_LOAD( "2g118.3h", 0x0400, 0x0400, CRC(3c10b2ba) SHA1(127a950d90420417a91aa3c8fabec7d7e7d526f5) ) + ROM_LOAD( "3.4h", 0x0800, 0x0400, CRC(82a49b48) SHA1(4cf9f684f3eb18b99a88ca879bb7083b1334f0cc) ) + ROM_LOAD( "4g118.5h", 0x0c00, 0x0400, CRC(42bb0611) SHA1(3894e4372f1443402ea7145b1101e1219fe2cde2) ) // changes in here cause trails when you move the ship, PCB does the same and ROM gives the same read every time, possible a bit has been flipped tho. check + ROM_LOAD( "5.6h", 0x1000, 0x0400, CRC(b1c00fbf) SHA1(136267f75e2d5b445695cabef4538f986e6f1b10) ) + ROM_LOAD( "6.7h", 0x1400, 0x0400, CRC(f03454ce) SHA1(32c87f369475c7154fe3243d2c7be4a25444e530) ) + ROM_LOAD( "7.8h", 0x1800, 0x0400, CRC(84656c97) SHA1(2180faa07dd5bc618c80ae033babfc1191a0b890) ) // standard label but different anyway? + ROM_LOAD( "8g128.9h", 0x1c00, 0x0400, CRC(7f48307c) SHA1(5929c131d790b0c8f9113730715531809c6840e2) ) + + ROM_REGION( 0x0400, "colormap", 0 ) /* color map */ // population of this is optional, board runs as b&w without (this board didn't have it populated) + ROM_LOAD( "cosmicg9.bin", 0x0000, 0x0400, CRC(689c2c96) SHA1(ddfdc3fd29c56fdebd3b1c3443a7c39f567d5355) ) +ROM_END + + +void cosmicg_state::init_cosmicg() +{ + /* Program ROMs have data pins connected different from normal */ + offs_t len = memregion("program")->bytes(); + u8 *rom = memregion("program")->base(); + for (offs_t offs = 0; offs < len; offs++) + { + u8 scrambled = rom[offs]; + + u8 normal = (scrambled >> 3 & 0x11) + | (scrambled >> 1 & 0x22) + | (scrambled << 1 & 0x44) + | (scrambled << 3 & 0x88); + + rom[offs] = normal; + } + + m_sound_enabled = 0; + m_march_select = 0; + m_gun_die_select = 0; +} + + +GAME( 1979, cosmicg, 0, cosmicg, cosmicg, cosmicg_state, init_cosmicg, ROT270, "Universal", "Cosmic Guerilla", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1979, cosmicgi, cosmicg, cosmicg, cosmicg, cosmicg_state, init_cosmicg, ROT270, "bootleg (Inder)", "Cosmic Guerilla (Spanish bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/includes/cosmic.h b/src/mame/includes/cosmic.h index 4f7a9e8b5be..7808f9651e4 100644 --- a/src/mame/includes/cosmic.h +++ b/src/mame/includes/cosmic.h @@ -16,7 +16,6 @@ #include "emupal.h" #include "screen.h" -#define COSMICG_MASTER_CLOCK XTAL(9'828'000) #define Z80_MASTER_CLOCK XTAL(10'816'000) @@ -37,9 +36,31 @@ public: m_palette(*this, "palette") { } + void cosmic(machine_config &config); + void cosmica(machine_config &config); + void nomnlnd(machine_config &config); + void devzone(machine_config &config); + void panic(machine_config &config); + void magspot(machine_config &config); + + void init_devzone(); + void init_nomnlnd(); + void init_cosmica(); + void init_panic(); + + DECLARE_WRITE_LINE_MEMBER(panic_coin_inserted); + DECLARE_INPUT_CHANGED_MEMBER(cosmica_coin_inserted); + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted_irq0); + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted_nmi); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: /* memory pointers */ required_shared_ptr m_videoram; - optional_shared_ptr m_spriteram; + required_shared_ptr m_spriteram; /* video-related */ typedef pen_t (cosmic_state::*color_func)(uint8_t x, uint8_t y); @@ -55,8 +76,6 @@ public: int m_dive_bomb_b_select; /* misc */ - uint32_t m_pixel_clock; - int m_ic_state; // for 9980 optional_ioport_array<4> m_in_ports; optional_ioport m_dsw; @@ -64,42 +83,24 @@ public: required_device m_maincpu; optional_device m_samples; optional_device m_dac; - optional_device m_gfxdecode; + required_device m_gfxdecode; required_device m_screen; required_device m_palette; void panic_sound_output_w(offs_t offset, uint8_t data); void panic_sound_output2_w(offs_t offset, uint8_t data); - void cosmicg_output_w(offs_t offset, uint8_t data); void cosmica_sound_output_w(offs_t offset, uint8_t data); void dac_w(uint8_t data); uint8_t cosmica_pixel_clock_r(); - uint8_t cosmicg_port_0_r(offs_t offset); - uint8_t cosmicg_port_1_r(offs_t offset); uint8_t magspot_coinage_dip_r(offs_t offset); uint8_t nomnlnd_port_0_1_r(offs_t offset); void flip_screen_w(uint8_t data); void cosmic_color_register_w(offs_t offset, uint8_t data); void cosmic_background_enable_w(uint8_t data); - DECLARE_WRITE_LINE_MEMBER(panic_coin_inserted); - DECLARE_INPUT_CHANGED_MEMBER(cosmica_coin_inserted); - DECLARE_INPUT_CHANGED_MEMBER(cosmicg_coin_inserted); - DECLARE_INPUT_CHANGED_MEMBER(coin_inserted_irq0); - DECLARE_INPUT_CHANGED_MEMBER(coin_inserted_nmi); - void init_devzone(); - void init_cosmicg(); - void init_nomnlnd(); - void init_cosmica(); - void init_panic(); - DECLARE_MACHINE_START(cosmic); - DECLARE_MACHINE_RESET(cosmic); - DECLARE_MACHINE_RESET(cosmicg); void panic_palette(palette_device &palette); void cosmica_palette(palette_device &palette); - void cosmicg_palette(palette_device &palette); void magspot_palette(palette_device &palette); void nomnlnd_palette(palette_device &palette); - uint32_t screen_update_cosmicg(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_panic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_cosmica(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_magspot(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -113,18 +114,8 @@ public: void nomnlnd_draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); pen_t panic_map_color(uint8_t x, uint8_t y); pen_t cosmica_map_color(uint8_t x, uint8_t y); - pen_t cosmicg_map_color(uint8_t x, uint8_t y); pen_t magspot_map_color(uint8_t x, uint8_t y); - void cosmic(machine_config &config); - void cosmica(machine_config &config); - void cosmicg(machine_config &config); - void nomnlnd(machine_config &config); - void devzone(machine_config &config); - void panic(machine_config &config); - void magspot(machine_config &config); void cosmica_map(address_map &map); - void cosmicg_io_map(address_map &map); - void cosmicg_map(address_map &map); void magspot_map(address_map &map); void panic_map(address_map &map); }; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 61f9f15639c..3bec4e8c53a 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -10698,8 +10698,6 @@ cosmica // 7910-AII (c) [1979] cosmica1 // 7910-A (c) [1979] cosmica2 // 7910 (c) 1979 cosmica3 // 7910-AII (c) [1979] -cosmicg // 7907 (c) 1979 -cosmicgi // bootleg (Inder) devzone // 8022 (c) [1980] devzone2 // 8022 (c) [1980] magspot // ???? (c) [1980] @@ -10712,6 +10710,10 @@ panic3 // 8015 (c) 1980 panicger // 8015 (c) 1980 panich // 8015 (c) 1980 +@source:cosmicg.cpp +cosmicg // 7907 (c) 1979 +cosmicgi // bootleg (Inder) + @source:cosmicos.cpp cosmicos // diff --git a/src/mame/video/cosmic.cpp b/src/mame/video/cosmic.cpp index 12a9f6c6673..7f7cc234e3d 100644 --- a/src/mame/video/cosmic.cpp +++ b/src/mame/video/cosmic.cpp @@ -40,15 +40,6 @@ pen_t cosmic_state::cosmica_map_color( uint8_t x, uint8_t y ) return pen & 0x07; } -pen_t cosmic_state::cosmicg_map_color( uint8_t x, uint8_t y ) -{ - offs_t offs = (m_color_registers[0] << 8) | (m_color_registers[1] << 9) | ((y >> 4) << 4) | (x >> 4); - pen_t pen = memregion("user1")->base()[offs]; - - /* the upper 4 bits are for cocktail mode support */ - return pen & 0x0f; -} - pen_t cosmic_state::magspot_map_color( uint8_t x, uint8_t y ) { offs_t offs = (m_color_registers[0] << 9) | ((x >> 3) << 4) | (y >> 4); @@ -130,30 +121,6 @@ void cosmic_state::cosmica_palette(palette_device &palette) } -/* - * Cosmic guerilla table setup - * - * Use AA for normal, FF for Full Red - * Bit 0 = R, bit 1 = G, bit 2 = B, bit 4 = High Red - * - * It's possible that the background is dark gray and not black, as the - * resistor chain would never drop to zero, Anybody know ? - */ -void cosmic_state::cosmicg_palette(palette_device &palette) -{ - for (int i = 0; i < palette.entries(); i++) - { - int const r = (i > 8) ? 0xff : 0xaa * BIT(i, 0); - int const g = 0xaa * BIT(i, 1); - int const b = 0xaa * BIT(i, 2); - - palette.set_pen_color(i, rgb_t(r, g, b)); - } - - m_map_color = &cosmic_state::cosmicg_map_color; -} - - void cosmic_state::magspot_palette(palette_device &palette) { uint8_t const *const color_prom = memregion("proms")->base(); @@ -498,14 +465,6 @@ void cosmic_state::nomnlnd_draw_background( screen_device &screen, bitmap_ind16 } -uint32_t cosmic_state::screen_update_cosmicg(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - bitmap.fill(0, cliprect); - draw_bitmap(bitmap, cliprect); - return 0; -} - - uint32_t cosmic_state::screen_update_panic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { bitmap.fill(0, cliprect);