diff --git a/src/mame/audio/redalert.cpp b/src/mame/audio/redalert.cpp index 5b8e32652a9..2e295da68e0 100644 --- a/src/mame/audio/redalert.cpp +++ b/src/mame/audio/redalert.cpp @@ -2,7 +2,7 @@ // copyright-holders:Mike Balfour /*************************************************************************** - Irem Red Alert hardware + Irem M27 hardware If you have any questions about how this driver works, don't hesitate to ask. - Mike Balfour (mab22@po.cwru.edu) @@ -86,6 +86,7 @@ void redalert_state::redalert_audio_command_w(uint8_t data) { /* the byte is connected to port A of the AY8910 */ m_soundlatch->write(data); + m_sound_hs = 1; /* D7 is also connected to the NMI input of the CPU - the NMI is actually toggled by a 74121 (R1=27K, C10=330p) */ @@ -105,6 +106,7 @@ void redalert_state::redalert_AY8910_w(uint8_t data) /* BC1=1, BDIR=0 : read from PSG */ case 0x01: + m_sound_hs = 0; m_ay8910_latch_1 = m_ay8910->data_r(); break; @@ -140,6 +142,15 @@ void redalert_state::redalert_audio_map(address_map &map) map(0x7000, 0x77ff).mirror(0x0800).rom(); } +void redalert_state::panther_audio_map(address_map &map) +{ + redalert_audio_map(map); + // Panther maps these two to $2000 while Red Alert to $1000, different PAL addressing? + map(0x1000, 0x1fff).unmaprw(); + map(0x2000, 0x2000).mirror(0x0ffe).nopr().w(FUNC(redalert_state::redalert_AY8910_w)); + map(0x2001, 0x2001).mirror(0x0ffe).rw(FUNC(redalert_state::redalert_ay8910_latch_1_r), FUNC(redalert_state::redalert_ay8910_latch_2_w)); +} + /************************************* * * Red Alert audio board @@ -153,6 +164,7 @@ void redalert_state::sound_start() m_audio_irq_on_timer->adjust(REDALERT_AUDIO_CPU_IRQ_FREQ, 0, REDALERT_AUDIO_CPU_IRQ_FREQ); + save_item(NAME(m_sound_hs)); save_item(NAME(m_ay8910_latch_1)); save_item(NAME(m_ay8910_latch_2)); } @@ -259,6 +271,14 @@ void redalert_state::ww3_audio(machine_config &config) redalert_audio_m37b(config); } +void redalert_state::panther_audio(machine_config &config) +{ + SPEAKER(config, "mono").front_center(); + + redalert_audio_m37b(config); + m_audiocpu->set_addrmap(AS_PROGRAM, &redalert_state::panther_audio_map); +} + /************************************* * * Demoneye-X audio board diff --git a/src/mame/drivers/redalert.cpp b/src/mame/drivers/redalert.cpp index fbddf189d8d..162775d3c84 100644 --- a/src/mame/drivers/redalert.cpp +++ b/src/mame/drivers/redalert.cpp @@ -2,7 +2,7 @@ // copyright-holders:Mike Balfour /*************************************************************************** - redalert.c, Irem M27 hardware + Irem M27 hardware If you have any questions about how this driver works, don't hesitate to ask. - Mike Balfour (mab22@po.cwru.edu) @@ -68,8 +68,11 @@ * Everything needs to be verified on real PCB or schematics Known issues/to-do's Panther: - * Sound comms doesn't work + * Analog sounds (same as Red Alert?) + * AY sounds needs an actual ref, they are dubious at best * No title screen? + * Fails ROM check in service mode with "ROM ERR 0", bootleg/prototype set? + * Likewise sports corrupted words in input test ******************************************************************** IREM 'WW III' 1981 @@ -91,6 +94,22 @@ M-37B (Sound board) M-33 SUB-1 + ******************************************************************** + Panther notes: + - Hold start 1 on boot, press coin chutes or service button to cycle: + -> RAM/ROM check + -> Continous Video drawing check (only if above is success) + -> (NMI again goes to PROM check and beyond) + - Hold start 2 on boot: + -> PROM check? + -> Input check + -> Freeze + - Notes on "ROM ERR 0": + PC=b482 ROM check main routine + PC=b5cc SUM16 individual ROM chunk (ROM 0 -> 8000-87ff, ROM 1 -> 8800-8fff ...) + PC=b5b4 Taking the branch -> failed check + + ****************************************************************************/ #include "emu.h" @@ -111,10 +130,6 @@ INTERRUPT_GEN_MEMBER(redalert_state::redalert_vblank_interrupt) { - if( ioport("COIN")->read() ) - /* the service coin as conntected to the CPU's RDY pin as well */ - device.execute().pulse_input_line(INPUT_LINE_NMI, attotime::zero); - device.execute().set_input_line(M6502_IRQ_LINE, ASSERT_LINE); } @@ -140,12 +155,14 @@ uint8_t redalert_state::panther_interrupt_clear_r() if (!machine().side_effects_disabled()) m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); - return ioport("STICK0")->read(); + return ioport("VOLUM")->read(); } -uint8_t redalert_state::panther_unk_r() +void redalert_state::demoneye_bitmap_ypos_w(u8 data) { - return ((machine().rand() & 0x01) | (ioport("C020")->read() & 0xfe)); + // TODO: sound irq ack most likely don't belong here + m_demoneye_bitmap_yoffs = data; + m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); } /************************************* @@ -160,9 +177,9 @@ void redalert_state::redalert_main_map(address_map &map) map(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram"); map(0x4000, 0x4fff).ram().share("charram"); map(0x5000, 0xbfff).rom(); - map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); - map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); - map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); + map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw(); + map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw(); + map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw(); map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); map(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control"); map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); @@ -177,9 +194,9 @@ void redalert_state::ww3_main_map(address_map &map) map(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram"); map(0x4000, 0x4fff).ram().share("charram"); map(0x5000, 0xbfff).rom(); - map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); - map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); - map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); + map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw(); + map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw(); + map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw(); map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); map(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control"); map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); @@ -193,9 +210,9 @@ void redalert_state::panther_main_map(address_map &map) map(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram"); map(0x4000, 0x4fff).ram().share("charram"); map(0x5000, 0xbfff).rom(); - map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); - map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); - map(0xc020, 0xc020).mirror(0x0f8f).r(FUNC(redalert_state::panther_unk_r)); /* vblank? */ + map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw(); + map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw(); + map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw(); map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); map(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control"); map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); @@ -209,16 +226,14 @@ void redalert_state::demoneye_main_map(address_map &map) map(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram"); map(0x4000, 0x5fff).ram().share("charram"); map(0x6000, 0xbfff).rom(); - map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); - map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); - map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); + map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw(); + map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw(); + map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw(); map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::demoneye_audio_command_w)); map(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control"); map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); - map(0xc060, 0xc060).mirror(0x0f80).noprw(); /* unknown */ - map(0xc061, 0xc061).mirror(0x0f80).noprw(); /* unknown */ - map(0xc062, 0xc062).mirror(0x0f80).noprw(); /* unknown */ - map(0xc070, 0xc070).mirror(0x0f8f).rw(FUNC(redalert_state::redalert_interrupt_clear_r), FUNC(redalert_state::redalert_interrupt_clear_w)); /* probably not correct */ + map(0xc060, 0xc063).mirror(0x0f80).w(FUNC(redalert_state::demoneye_bitmap_layer_w)); + map(0xc070, 0xc070).mirror(0x0f8f).rw(FUNC(redalert_state::redalert_interrupt_clear_r), FUNC(redalert_state::demoneye_bitmap_ypos_w)); map(0xf000, 0xffff).rom().region("maincpu", 0x8000); } @@ -230,8 +245,54 @@ void redalert_state::demoneye_main_map(address_map &map) * *************************************/ +INPUT_CHANGED_MEMBER(redalert_state::coin_inserted) +{ + // TODO: the service coin is connected to the CPU's RDY pin as well + m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); +} + +CUSTOM_INPUT_MEMBER(redalert_state::sound_status_r) +{ + // communication handshake between host and sound CPU + // at least Panther uses it, unconfirmed for Red Alert and Demoneye-X + return m_sound_hs; +} + +static INPUT_PORTS_START( m27_base ) + // port names comes from Panther input test + PORT_START("COIN") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) PORT_CHANGED_MEMBER(DEVICE_SELF, redalert_state, coin_inserted, 0) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1) PORT_CHANGED_MEMBER(DEVICE_SELF, redalert_state, coin_inserted, 0) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_IMPULSE(1) PORT_CHANGED_MEMBER(DEVICE_SELF, redalert_state, coin_inserted, 0) + PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KEY1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) + // TODO: 2-way/4-way ...? + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ + + PORT_START("KEY2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(redalert_state, sound_status_r) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL + // TODO: 2-way/4-way ...? + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ +INPUT_PORTS_END + static INPUT_PORTS_START( redalert ) - PORT_START("C000") + PORT_INCLUDE( m27_base ) + + PORT_START("DSW") PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:1,2") PORT_DIPSETTING( 0x00, "3" ) PORT_DIPSETTING( 0x01, "4" ) @@ -252,42 +313,26 @@ static INPUT_PORTS_START( redalert ) PORT_DIPSETTING( 0x40, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW:8" ) - - PORT_START("C010") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 35 - N.C. */ - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 36 - N.C. */ - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - - PORT_START("C020") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 33 - N.C. */ - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 34 - N.C. */ - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - - PORT_START("COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_IMPULSE(1) - PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END static INPUT_PORTS_START( panther ) - PORT_START("C000") + PORT_INCLUDE( m27_base ) + + // no p2 + PORT_MODIFY("KEY1") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_MODIFY("KEY2") + PORT_BIT( 0x7c, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("DSW") PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:1,2") PORT_DIPSETTING( 0x00, "3" ) PORT_DIPSETTING( 0x01, "4" ) PORT_DIPSETTING( 0x02, "5" ) PORT_DIPSETTING( 0x03, "6" ) - PORT_DIPNAME( 0x04, 0x00, "Cabinet in Service Mode" ) PORT_DIPLOCATION("SW:3") + // actually just flips input test text if enabled, everything else is unaffected + PORT_DIPNAME( 0x04, 0x00, "Cabinet in Service Mode" ) PORT_DIPLOCATION("SW:3") PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x04, DEF_STR( Cocktail ) ) PORT_DIPNAME( 0x08, 0x00, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW:4") @@ -298,43 +343,22 @@ static INPUT_PORTS_START( panther ) PORT_DIPSETTING( 0x10, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) ) PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) + // TODO: unused for this set? PORT_DIPNAME( 0x40, 0x40, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW:7") PORT_DIPSETTING( 0x40, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW:8" ) - PORT_START("C010") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON2 ) /* pin 35 - N.C. */ - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON3 ) /* pin 36 - N.C. */ - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON4 ) /* Meter */ - - PORT_START("C020") - PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - PORT_BIT ( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL - PORT_BIT ( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL - PORT_BIT ( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL - PORT_BIT ( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - - PORT_START("COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_IMPULSE(1) - PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED ) - - PORT_START("STICK0") - PORT_BIT( 0xff, 0x80, IPT_POSITIONAL ) PORT_SENSITIVITY(70) PORT_KEYDELTA(3) PORT_CENTERDELTA(0) + PORT_START("VOLUM") + // vertical lever according to cabinet pic, no centering + // TODO: more akin to AD_STICK_Z? Verify in-game ranges + PORT_BIT( 0xff, 0x80, IPT_POSITIONAL_V ) PORT_SENSITIVITY(70) PORT_KEYDELTA(3) PORT_CENTERDELTA(0) INPUT_PORTS_END static INPUT_PORTS_START( demoneye ) - PORT_START("C000") + PORT_INCLUDE( m27_base ) + + PORT_START("DSW") PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPSETTING( 0x00, "3" ) PORT_DIPSETTING( 0x01, "4" ) @@ -357,32 +381,6 @@ static INPUT_PORTS_START( demoneye ) PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x80, DEF_STR( On ) ) - - PORT_START("C010") - PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) - PORT_BIT ( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) - PORT_BIT ( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) - PORT_BIT ( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) - PORT_BIT ( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) - PORT_BIT ( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - - PORT_START("C020") - PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - PORT_BIT ( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL - PORT_BIT ( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) - PORT_BIT ( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL - PORT_BIT ( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL - PORT_BIT ( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ - - PORT_START("COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_IMPULSE(1) - PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END @@ -432,7 +430,7 @@ void redalert_state::panther(machine_config &config) panther_video(config); /* audio hardware */ - ww3_audio(config); + panther_audio(config); } void redalert_state::demoneye(machine_config &config) @@ -459,13 +457,15 @@ void redalert_state::demoneye(machine_config &config) ROM_START( panther ) ROM_REGION( 0x10000, "maincpu", 0 ) - ROM_LOAD( "qr-1.bin", 0x8000, 0x0800, CRC(406dc606) SHA1(c12b91145aa579813b7b0e8eb7933bf35e4a5b97) ) - ROM_LOAD( "qr-2.bin", 0x8800, 0x0800, CRC(e7e64b11) SHA1(0fcfbce552b22edce9051b6fad0974f81ab44973) ) - ROM_LOAD( "qr-3.bin", 0x9000, 0x0800, CRC(dfec33f2) SHA1(4e631a3a8c7873e8f51a81e8b73704729269ee01) ) + // TODO: marked as BAD_DUMP since these all fails ROM check + // we need a second set to counter-check exact identification + ROM_LOAD( "qr-1.bin", 0x8000, 0x0800, BAD_DUMP CRC(406dc606) SHA1(c12b91145aa579813b7b0e8eb7933bf35e4a5b97) ) + ROM_LOAD( "qr-2.bin", 0x8800, 0x0800, BAD_DUMP CRC(e7e64b11) SHA1(0fcfbce552b22edce9051b6fad0974f81ab44973) ) + ROM_LOAD( "qr-3.bin", 0x9000, 0x0800, BAD_DUMP CRC(dfec33f2) SHA1(4e631a3a8c7873e8f51a81e8b73704729269ee01) ) ROM_LOAD( "qr-4.bin", 0x9800, 0x0800, CRC(60571aa0) SHA1(257474383ad7cb90e9e4f9236b3f865a991d688a) ) ROM_LOAD( "qr-5.bin", 0xa000, 0x0800, CRC(2ac19b54) SHA1(613a800179f9705df03967889eb23ef71baed493) ) - ROM_LOAD( "qr-6.bin", 0xa800, 0x0800, CRC(02fbd9d9) SHA1(65b5875c78886b51c9bdfc75e730b9f67ce72cfc) ) - ROM_LOAD( "qr-7.bin", 0xb000, 0x0800, CRC(b3e2d6cc) SHA1(7bb18f17d635196e617e8f68bf8d866134c362d1) ) + ROM_LOAD( "qr-6.bin", 0xa800, 0x0800, BAD_DUMP CRC(02fbd9d9) SHA1(65b5875c78886b51c9bdfc75e730b9f67ce72cfc) ) + ROM_LOAD( "qr-7.bin", 0xb000, 0x0800, BAD_DUMP CRC(b3e2d6cc) SHA1(7bb18f17d635196e617e8f68bf8d866134c362d1) ) ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_LOAD( "q7a.bin", 0x7000, 0x0800, CRC(febd1674) SHA1(e122d0855ab6a352d741f9013c20ec31e0068248) ) @@ -544,7 +544,7 @@ ROM_END * *************************************/ -GAME( 1981, panther, 0, panther, panther, redalert_state, empty_init, ROT270, "Irem", "Panther", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1981, panther, 0, panther, panther, redalert_state, empty_init, ROT270, "Irem", "Panther (bootleg?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, redalert, 0, redalert, redalert, redalert_state, empty_init, ROT270, "Irem (GDI license)", "Red Alert", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, ww3, redalert, ww3, redalert, redalert_state, empty_init, ROT270, "Irem", "WW III", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, demoneye, 0, demoneye, demoneye, redalert_state, empty_init, ROT270, "Irem", "Demoneye-X", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/includes/redalert.h b/src/mame/includes/redalert.h index 9afbcb6708d..12d72f6b3d7 100644 --- a/src/mame/includes/redalert.h +++ b/src/mame/includes/redalert.h @@ -2,7 +2,7 @@ // copyright-holders:Mike Balfour /*************************************************************************** - Irem Red Alert hardware + Irem M27 hardware If you have any questions about how this driver works, don't hesitate to ask. - Mike Balfour (mab22@po.cwru.edu) @@ -56,12 +56,16 @@ public: void redalert_audio_voice(machine_config &config); void redalert_audio(machine_config &config); void ww3_audio(machine_config &config); + void panther_audio(machine_config &config); void demoneye_audio(machine_config &config); void demoneye(machine_config &config); void ww3(machine_config &config); void panther(machine_config &config); void redalert(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(coin_inserted); + DECLARE_CUSTOM_INPUT_MEMBER(sound_status_r); + private: required_shared_ptr m_bitmap_videoram; required_shared_ptr m_charmap_videoram; @@ -84,7 +88,6 @@ private: uint8_t redalert_interrupt_clear_r(); void redalert_interrupt_clear_w(uint8_t data); uint8_t panther_interrupt_clear_r(); - uint8_t panther_unk_r(); void redalert_bitmap_videoram_w(offs_t offset, uint8_t data); void redalert_audio_command_w(uint8_t data); uint8_t redalert_ay8910_latch_1_r(); @@ -93,6 +96,7 @@ private: void demoneye_audio_command_w(uint8_t data); DECLARE_VIDEO_START(redalert); DECLARE_VIDEO_START(ww3); + DECLARE_VIDEO_START(demoneye); uint32_t screen_update_redalert(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); uint32_t screen_update_demoneye(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); uint32_t screen_update_panther(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -106,8 +110,11 @@ private: void demoneye_ay8910_latch_1_w(uint8_t data); uint8_t demoneye_ay8910_latch_2_r(); void demoneye_ay8910_data_w(uint8_t data); - void get_pens(pen_t *pens); + void get_redalert_pens(pen_t *pens); void get_panther_pens(pen_t *pens); + void get_demoneye_pens(pen_t *pens); + WRITE8_MEMBER(demoneye_bitmap_layer_w); + void demoneye_bitmap_ypos_w(u8 data); virtual void sound_start() override; @@ -117,6 +124,7 @@ private: void demoneye_main_map(address_map &map); void redalert_audio_map(address_map &map); + void panther_audio_map(address_map &map); void demoneye_audio_map(address_map &map); void redalert_voice_map(address_map &map); @@ -126,6 +134,9 @@ private: uint8_t m_ay8910_latch_1; uint8_t m_ay8910_latch_2; + u8 m_demoneye_bitmap_reg[4]; + u8 m_demoneye_bitmap_yoffs; + u8 m_sound_hs; }; #endif // MAME_INCLUDES_REDALERT_H diff --git a/src/mame/video/redalert.cpp b/src/mame/video/redalert.cpp index b5789ec232c..6041845e370 100644 --- a/src/mame/video/redalert.cpp +++ b/src/mame/video/redalert.cpp @@ -2,7 +2,7 @@ // copyright-holders:Mike Balfour /*************************************************************************** - Irem Red Alert hardware + Irem M27 hardware If you have any questions about how this driver works, don't hesitate to ask. - Mike Balfour (mab22@po.cwru.edu) @@ -38,7 +38,8 @@ void redalert_state::redalert_bitmap_videoram_w(offs_t offset, uint8_t data) * *************************************/ -void redalert_state::get_pens(pen_t *pens) +// TODO: clean these functions, add F4 viewer, initialize on boot? +void redalert_state::get_redalert_pens(pen_t *pens) { static const int resistances_bitmap[] = { 100 }; static const int resistances_charmap_rg[] = { 390, 220, 180 }; @@ -102,7 +103,6 @@ void redalert_state::get_pens(pen_t *pens) } /* this uses the same color hook-up between bitmap and chars. */ -/* TODO: clean me up */ void redalert_state::get_panther_pens(pen_t *pens) { static const int resistances_bitmap[] = { 100 }; @@ -153,7 +153,71 @@ void redalert_state::get_panther_pens(pen_t *pens) } /* background color */ - pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS] = rgb_t(back_r_weight[0], back_gb_weight[0], back_gb_weight[0]); + // TODO: verify if really black + pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS] = rgb_t(0, 0, 0); +} + +void redalert_state::get_demoneye_pens(pen_t *pens) +{ + static const int resistances_bitmap[] = { 100 }; + static const int resistances_charmap_rg[] = { 390, 220, 180 }; + static const int resistances_charmap_b[] = { 220, 100 }; + static const int resistances_back_r[] = { 1000 + 100 }; + static const int resistances_back_gb[] = { 100 + 470 }; + + offs_t offs; + double scaler; + double bitmap_weight[2]; + double charmap_rg_weights[3]; + double charmap_b_weights[2]; + double back_r_weight[1]; + double back_gb_weight[1]; + const uint8_t *prom = memregion("proms")->base(); + + scaler = compute_resistor_weights(0, 0xff, -1, + 1, resistances_bitmap, bitmap_weight, 470, 0, + 3, resistances_charmap_rg, charmap_rg_weights, 470, 0, + 2, resistances_charmap_b, charmap_b_weights, 470, 0); + + compute_resistor_weights(0, 0xff, scaler, + 1, resistances_back_r, back_r_weight, 470, 0, + 1, resistances_back_gb, back_gb_weight, 470, 0, + 0, nullptr, nullptr, 0, 0); + + /* the character layer colors come from the PROM */ + for (offs = 0; offs < NUM_CHARMAP_PENS; offs++) + { + uint8_t data = prom[offs]; + + /* very strange mapping */ + uint8_t r0_bit = (data >> 2) & 0x01; + uint8_t r1_bit = (data >> 6) & 0x01; + uint8_t r2_bit = (data >> 4) & 0x01; + uint8_t g0_bit = (data >> 1) & 0x01; + uint8_t g1_bit = (data >> 3) & 0x01; + uint8_t g2_bit = (data >> 5) & 0x01; + uint8_t b0_bit = (data >> 0) & 0x01; + uint8_t b1_bit = (data >> 7) & 0x01; + + uint8_t r = combine_weights(charmap_rg_weights, r0_bit, r1_bit, r2_bit); + uint8_t g = combine_weights(charmap_rg_weights, g0_bit, g1_bit, g2_bit); + uint8_t b = combine_weights(charmap_b_weights, b0_bit, b1_bit); + + pens[offs] = rgb_t(r, g, b); + } + + /* the bitmap layer colors are directly mapped */ + for (offs = 0; offs < NUM_BITMAP_PENS; offs++) + { + uint8_t r = bitmap_weight[(offs >> 2) & 0x01]; + uint8_t g = bitmap_weight[(offs >> 1) & 0x01]; + uint8_t b = bitmap_weight[(offs >> 0) & 0x01]; + + pens[NUM_CHARMAP_PENS + offs] = rgb_t(r, g, b); + } + + /* background color */ + pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS] = rgb_t(0,0,0);//rgb_t(back_r_weight[0], back_gb_weight[0], back_gb_weight[0]); } /************************************* @@ -171,6 +235,14 @@ VIDEO_START_MEMBER(redalert_state,redalert) m_control_xor = 0x00; } +VIDEO_START_MEMBER(redalert_state,demoneye) +{ + VIDEO_START_CALL_MEMBER( redalert ); + + save_pointer(NAME(m_demoneye_bitmap_reg), 4); + save_item(NAME(m_demoneye_bitmap_yoffs)); +} + VIDEO_START_MEMBER(redalert_state,ww3) { VIDEO_START_CALL_MEMBER( redalert ); @@ -190,7 +262,7 @@ uint32_t redalert_state::screen_update_redalert(screen_device &screen, bitmap_rg pen_t pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS + 1]; offs_t offs; - get_pens(pens); + get_redalert_pens(pens); for (offs = 0; offs < 0x2000; offs++) { @@ -257,12 +329,31 @@ uint32_t redalert_state::screen_update_redalert(screen_device &screen, bitmap_rg * *************************************/ +/* + [0] + xxxx xxxx X position + [1] + -??x ---- tile bank * 0x20 (?) + ---- xx-- + ---- --x- (1) 8x8 tile width 4, (0) 4x4 + ---- ---x enable layer + [2] + ---- x--- boss second form, + ---- --xx tile bank * 0x100 (?) + [3] + ---- --xx <3 on normal/first form boss, 1 on second form> +*/ +WRITE8_MEMBER(redalert_state::demoneye_bitmap_layer_w) +{ + m_demoneye_bitmap_reg[offset] = data; +} + uint32_t redalert_state::screen_update_demoneye(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { pen_t pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS + 1]; offs_t offs; - get_pens(pens); + get_demoneye_pens(pens); for (offs = 0; offs < 0x2000; offs++) { @@ -293,7 +384,7 @@ uint32_t redalert_state::screen_update_demoneye(screen_device &screen, bitmap_rg /* this is the mapping of the 3rd char set */ //charmap_data_1 = m_charmap_videoram[0x1400 | charmap_data_base]; - //charmap_data_2 = m_charmap_videoram[0x1c00 | charmap_data_base]; + //charmap_data_2 = m_charmap_videoram[0x1800 | charmap_data_base]; for (i = 0; i < 8; i++) { @@ -321,7 +412,60 @@ uint32_t redalert_state::screen_update_demoneye(screen_device &screen, bitmap_rg charmap_data_2 = charmap_data_2 << 1; } } + + u8 x = m_demoneye_bitmap_reg[0]; + u8 y = m_demoneye_bitmap_yoffs; + u8 control = m_demoneye_bitmap_reg[1]; + + if(control&1) + { + // TODO: pinpoint what the unknown bits are for (more zooming? color offset?) + // TODO: layer is offset wrt bullets collision + // Note: boss second form has even more offsetted collision (hence bigger?) + int width = (control&2)?8:4; + int base = 0x1400; + base += (control & 0x10) ? 0x20 : 0; + base += (m_demoneye_bitmap_reg[2] & 3) * 0x100; + + for(int x_block=0; x_block<8; ++x_block) + { + for(int y_block=0; y_block<8; ++y_block) + { + if(y_block>5) | ((l1&0x80)>>6) | ((l2&0x80)>>7); + if(ccc) + { + // both are clearly reversed, + // cfr. boss first form (when opens the eye) + // or second form (follows player position) + int y_dst = 8*width - (y_block*8+iy); + int x_dst = 8*width - (x_block*8+7-ix); + ccc=pens[NUM_CHARMAP_PENS+ccc]; + bitmap.pix32(y+y_dst, x+x_dst) = ccc; + } + + l0<<=1; + l1<<=1; + l2<<=1; + } + } + } + + base+=8; + } + } + } + + //popmessage("%02x: %02x %02x %02x %02x %04x",m_demoneye_bitmap_yoffs, m_demoneye_bitmap_reg[0], m_demoneye_bitmap_reg[1], m_demoneye_bitmap_reg[2], m_demoneye_bitmap_reg[3], test); return 0; } @@ -433,7 +577,7 @@ void redalert_state::ww3_video(machine_config &config) void redalert_state::demoneye_video(machine_config &config) { - MCFG_VIDEO_START_OVERRIDE(redalert_state,redalert) + MCFG_VIDEO_START_OVERRIDE(redalert_state,demoneye) redalert_video_common(config);