redalert.cpp: various fixes [Tomasz Slanina, Angelo Salese] (#6706)

* Panther: fix input labels, mark ROMs as bad, volum (sic) lever is vertical not horizontal

* Reduce input defs

* Panther: communication hand-shake, fix audio mapping, emits a few sounds

* Quick QA

* Demoneye-X: better colors

* Demoneye-X: add bitmap layer

* Demoneye-X: fix drawing order, fix tile banking
This commit is contained in:
Angelo Salese 2020-05-16 20:42:33 +02:00 committed by GitHub
parent 26209df0b3
commit 79f08d5431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 303 additions and 128 deletions

View File

@ -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

View File

@ -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 )

View File

@ -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<uint8_t> m_bitmap_videoram;
required_shared_ptr<uint8_t> 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

View File

@ -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-- <used, unknown purpose>
---- --x- (1) 8x8 tile width 4, (0) 4x4
---- ---x enable layer
[2]
---- x--- boss second form, <unknown purpose>
---- --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<width && x_block<width)
{
for(int iy=0;iy<8;++iy)
{
int l0 = m_charmap_videoram[base+iy];
int l1 = m_charmap_videoram[base+0x400+iy];
int l2 = m_charmap_videoram[base+0x800+iy];
for(int ix=0;ix<8;++ix)
{
int ccc = ((l0&0x80)>>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);