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 // 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 If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu) 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 */ /* the byte is connected to port A of the AY8910 */
m_soundlatch->write(data); m_soundlatch->write(data);
m_sound_hs = 1;
/* D7 is also connected to the NMI input of the CPU - /* D7 is also connected to the NMI input of the CPU -
the NMI is actually toggled by a 74121 (R1=27K, C10=330p) */ 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 */ /* BC1=1, BDIR=0 : read from PSG */
case 0x01: case 0x01:
m_sound_hs = 0;
m_ay8910_latch_1 = m_ay8910->data_r(); m_ay8910_latch_1 = m_ay8910->data_r();
break; break;
@ -140,6 +142,15 @@ void redalert_state::redalert_audio_map(address_map &map)
map(0x7000, 0x77ff).mirror(0x0800).rom(); 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 * 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); 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_1));
save_item(NAME(m_ay8910_latch_2)); save_item(NAME(m_ay8910_latch_2));
} }
@ -259,6 +271,14 @@ void redalert_state::ww3_audio(machine_config &config)
redalert_audio_m37b(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 * Demoneye-X audio board

View File

@ -2,7 +2,7 @@
// copyright-holders:Mike Balfour // 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 If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu) ask. - Mike Balfour (mab22@po.cwru.edu)
@ -68,8 +68,11 @@
* Everything needs to be verified on real PCB or schematics * Everything needs to be verified on real PCB or schematics
Known issues/to-do's Panther: 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? * 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 IREM 'WW III' 1981
@ -91,6 +94,22 @@
M-37B (Sound board) M-37B (Sound board)
M-33 SUB-1 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" #include "emu.h"
@ -111,10 +130,6 @@
INTERRUPT_GEN_MEMBER(redalert_state::redalert_vblank_interrupt) 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); 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()) if (!machine().side_effects_disabled())
m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); 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(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram");
map(0x4000, 0x4fff).ram().share("charram"); map(0x4000, 0x4fff).ram().share("charram");
map(0x5000, 0xbfff).rom(); map(0x5000, 0xbfff).rom();
map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw();
map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw();
map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw();
map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); 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(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control");
map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); 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(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram");
map(0x4000, 0x4fff).ram().share("charram"); map(0x4000, 0x4fff).ram().share("charram");
map(0x5000, 0xbfff).rom(); map(0x5000, 0xbfff).rom();
map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw();
map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw();
map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw();
map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); 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(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control");
map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); 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(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram");
map(0x4000, 0x4fff).ram().share("charram"); map(0x4000, 0x4fff).ram().share("charram");
map(0x5000, 0xbfff).rom(); map(0x5000, 0xbfff).rom();
map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw();
map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw();
map(0xc020, 0xc020).mirror(0x0f8f).r(FUNC(redalert_state::panther_unk_r)); /* vblank? */ map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw();
map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::redalert_audio_command_w)); 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(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control");
map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); 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(0x2000, 0x3fff).ram().w(FUNC(redalert_state::redalert_bitmap_videoram_w)).share("bitmap_videoram");
map(0x4000, 0x5fff).ram().share("charram"); map(0x4000, 0x5fff).ram().share("charram");
map(0x6000, 0xbfff).rom(); map(0x6000, 0xbfff).rom();
map(0xc000, 0xc000).mirror(0x0f8f).portr("C000").nopw(); map(0xc000, 0xc000).mirror(0x0f8f).portr("DSW").nopw();
map(0xc010, 0xc010).mirror(0x0f8f).portr("C010").nopw(); map(0xc010, 0xc010).mirror(0x0f8f).portr("KEY1").nopw();
map(0xc020, 0xc020).mirror(0x0f8f).portr("C020").nopw(); map(0xc020, 0xc020).mirror(0x0f8f).portr("KEY2").nopw();
map(0xc030, 0xc030).mirror(0x0f8f).nopr().w(FUNC(redalert_state::demoneye_audio_command_w)); 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(0xc040, 0xc040).mirror(0x0f8f).nopr().writeonly().share("video_control");
map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color"); map(0xc050, 0xc050).mirror(0x0f8f).nopr().writeonly().share("bitmap_color");
map(0xc060, 0xc060).mirror(0x0f80).noprw(); /* unknown */ map(0xc060, 0xc063).mirror(0x0f80).w(FUNC(redalert_state::demoneye_bitmap_layer_w));
map(0xc061, 0xc061).mirror(0x0f80).noprw(); /* unknown */ map(0xc070, 0xc070).mirror(0x0f8f).rw(FUNC(redalert_state::redalert_interrupt_clear_r), FUNC(redalert_state::demoneye_bitmap_ypos_w));
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(0xf000, 0xffff).rom().region("maincpu", 0x8000); map(0xf000, 0xffff).rom().region("maincpu", 0x8000);
} }
@ -230,58 +245,54 @@ void redalert_state::demoneye_main_map(address_map &map)
* *
*************************************/ *************************************/
static INPUT_PORTS_START( redalert ) INPUT_CHANGED_MEMBER(redalert_state::coin_inserted)
PORT_START("C000") {
PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:1,2") // TODO: the service coin is connected to the CPU's RDY pin as well
PORT_DIPSETTING( 0x00, "3" ) m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE);
PORT_DIPSETTING( 0x01, "4" ) }
PORT_DIPSETTING( 0x02, "5" )
PORT_DIPSETTING( 0x03, "6" )
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")
PORT_DIPSETTING( 0x00, "5000" )
PORT_DIPSETTING( 0x08, "7000" )
PORT_DIPNAME( 0x30, 0x10, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW:5,6")
PORT_DIPSETTING( 0x30, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x10, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) )
PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
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") 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( 0x01, IP_ACTIVE_HIGH, IPT_START1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START2 )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 35 - N.C. */ // TODO: 2-way/4-way ...?
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 36 - N.C. */ 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( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */
PORT_START("C020") PORT_START("KEY2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) 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( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 33 - N.C. */ // TODO: 2-way/4-way ...?
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) /* pin 34 - N.C. */ 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( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ 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 INPUT_PORTS_END
static INPUT_PORTS_START( panther ) 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_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW:1,2")
PORT_DIPSETTING( 0x00, "3" ) PORT_DIPSETTING( 0x00, "3" )
PORT_DIPSETTING( 0x01, "4" ) PORT_DIPSETTING( 0x01, "4" )
@ -302,39 +313,52 @@ static INPUT_PORTS_START( panther )
PORT_DIPSETTING( 0x40, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x40, DEF_STR( Upright ) )
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW:8" ) PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW:8" )
INPUT_PORTS_END
PORT_START("C010") static INPUT_PORTS_START( panther )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) PORT_INCLUDE( m27_base )
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") // no p2
PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_MODIFY("KEY1")
PORT_BIT ( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* Meter */ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
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_MODIFY("KEY2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) PORT_BIT( 0x7c, IP_ACTIVE_HIGH, IPT_UNUSED )
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_START("DSW")
PORT_BIT( 0xff, 0x80, IPT_POSITIONAL ) PORT_SENSITIVITY(70) PORT_KEYDELTA(3) PORT_CENTERDELTA(0) 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" )
// 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")
PORT_DIPSETTING( 0x00, "5000" )
PORT_DIPSETTING( 0x08, "7000" )
PORT_DIPNAME( 0x30, 0x10, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW:5,6")
PORT_DIPSETTING( 0x30, DEF_STR( 2C_1C ) )
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("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 INPUT_PORTS_END
static INPUT_PORTS_START( demoneye ) static INPUT_PORTS_START( demoneye )
PORT_START("C000") PORT_INCLUDE( m27_base )
PORT_START("DSW")
PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) ) PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) )
PORT_DIPSETTING( 0x00, "3" ) PORT_DIPSETTING( 0x00, "3" )
PORT_DIPSETTING( 0x01, "4" ) PORT_DIPSETTING( 0x01, "4" )
@ -357,32 +381,6 @@ static INPUT_PORTS_START( demoneye )
PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unknown ) ) PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x80, DEF_STR( On ) ) 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 INPUT_PORTS_END
@ -432,7 +430,7 @@ void redalert_state::panther(machine_config &config)
panther_video(config); panther_video(config);
/* audio hardware */ /* audio hardware */
ww3_audio(config); panther_audio(config);
} }
void redalert_state::demoneye(machine_config &config) void redalert_state::demoneye(machine_config &config)
@ -459,13 +457,15 @@ void redalert_state::demoneye(machine_config &config)
ROM_START( panther ) ROM_START( panther )
ROM_REGION( 0x10000, "maincpu", 0 ) ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "qr-1.bin", 0x8000, 0x0800, CRC(406dc606) SHA1(c12b91145aa579813b7b0e8eb7933bf35e4a5b97) ) // TODO: marked as BAD_DUMP since these all fails ROM check
ROM_LOAD( "qr-2.bin", 0x8800, 0x0800, CRC(e7e64b11) SHA1(0fcfbce552b22edce9051b6fad0974f81ab44973) ) // we need a second set to counter-check exact identification
ROM_LOAD( "qr-3.bin", 0x9000, 0x0800, CRC(dfec33f2) SHA1(4e631a3a8c7873e8f51a81e8b73704729269ee01) ) 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-4.bin", 0x9800, 0x0800, CRC(60571aa0) SHA1(257474383ad7cb90e9e4f9236b3f865a991d688a) )
ROM_LOAD( "qr-5.bin", 0xa000, 0x0800, CRC(2ac19b54) SHA1(613a800179f9705df03967889eb23ef71baed493) ) 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-6.bin", 0xa800, 0x0800, BAD_DUMP CRC(02fbd9d9) SHA1(65b5875c78886b51c9bdfc75e730b9f67ce72cfc) )
ROM_LOAD( "qr-7.bin", 0xb000, 0x0800, CRC(b3e2d6cc) SHA1(7bb18f17d635196e617e8f68bf8d866134c362d1) ) ROM_LOAD( "qr-7.bin", 0xb000, 0x0800, BAD_DUMP CRC(b3e2d6cc) SHA1(7bb18f17d635196e617e8f68bf8d866134c362d1) )
ROM_REGION( 0x10000, "audiocpu", 0 ) ROM_REGION( 0x10000, "audiocpu", 0 )
ROM_LOAD( "q7a.bin", 0x7000, 0x0800, CRC(febd1674) SHA1(e122d0855ab6a352d741f9013c20ec31e0068248) ) 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, 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, 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 ) 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 // 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 If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu) ask. - Mike Balfour (mab22@po.cwru.edu)
@ -56,12 +56,16 @@ public:
void redalert_audio_voice(machine_config &config); void redalert_audio_voice(machine_config &config);
void redalert_audio(machine_config &config); void redalert_audio(machine_config &config);
void ww3_audio(machine_config &config); void ww3_audio(machine_config &config);
void panther_audio(machine_config &config);
void demoneye_audio(machine_config &config); void demoneye_audio(machine_config &config);
void demoneye(machine_config &config); void demoneye(machine_config &config);
void ww3(machine_config &config); void ww3(machine_config &config);
void panther(machine_config &config); void panther(machine_config &config);
void redalert(machine_config &config); void redalert(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
DECLARE_CUSTOM_INPUT_MEMBER(sound_status_r);
private: private:
required_shared_ptr<uint8_t> m_bitmap_videoram; required_shared_ptr<uint8_t> m_bitmap_videoram;
required_shared_ptr<uint8_t> m_charmap_videoram; required_shared_ptr<uint8_t> m_charmap_videoram;
@ -84,7 +88,6 @@ private:
uint8_t redalert_interrupt_clear_r(); uint8_t redalert_interrupt_clear_r();
void redalert_interrupt_clear_w(uint8_t data); void redalert_interrupt_clear_w(uint8_t data);
uint8_t panther_interrupt_clear_r(); uint8_t panther_interrupt_clear_r();
uint8_t panther_unk_r();
void redalert_bitmap_videoram_w(offs_t offset, uint8_t data); void redalert_bitmap_videoram_w(offs_t offset, uint8_t data);
void redalert_audio_command_w(uint8_t data); void redalert_audio_command_w(uint8_t data);
uint8_t redalert_ay8910_latch_1_r(); uint8_t redalert_ay8910_latch_1_r();
@ -93,6 +96,7 @@ private:
void demoneye_audio_command_w(uint8_t data); void demoneye_audio_command_w(uint8_t data);
DECLARE_VIDEO_START(redalert); DECLARE_VIDEO_START(redalert);
DECLARE_VIDEO_START(ww3); 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_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_demoneye(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t screen_update_panther(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); void demoneye_ay8910_latch_1_w(uint8_t data);
uint8_t demoneye_ay8910_latch_2_r(); uint8_t demoneye_ay8910_latch_2_r();
void demoneye_ay8910_data_w(uint8_t data); 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_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; virtual void sound_start() override;
@ -117,6 +124,7 @@ private:
void demoneye_main_map(address_map &map); void demoneye_main_map(address_map &map);
void redalert_audio_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 demoneye_audio_map(address_map &map);
void redalert_voice_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_1;
uint8_t m_ay8910_latch_2; 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 #endif // MAME_INCLUDES_REDALERT_H

View File

@ -2,7 +2,7 @@
// copyright-holders:Mike Balfour // 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 If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu) 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_bitmap[] = { 100 };
static const int resistances_charmap_rg[] = { 390, 220, 180 }; 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. */ /* this uses the same color hook-up between bitmap and chars. */
/* TODO: clean me up */
void redalert_state::get_panther_pens(pen_t *pens) void redalert_state::get_panther_pens(pen_t *pens)
{ {
static const int resistances_bitmap[] = { 100 }; static const int resistances_bitmap[] = { 100 };
@ -153,7 +153,71 @@ void redalert_state::get_panther_pens(pen_t *pens)
} }
/* background color */ /* 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; 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_MEMBER(redalert_state,ww3)
{ {
VIDEO_START_CALL_MEMBER( redalert ); 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]; pen_t pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS + 1];
offs_t offs; offs_t offs;
get_pens(pens); get_redalert_pens(pens);
for (offs = 0; offs < 0x2000; offs++) 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) 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]; pen_t pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS + 1];
offs_t offs; offs_t offs;
get_pens(pens); get_demoneye_pens(pens);
for (offs = 0; offs < 0x2000; offs++) 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 */ /* this is the mapping of the 3rd char set */
//charmap_data_1 = m_charmap_videoram[0x1400 | charmap_data_base]; //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++) for (i = 0; i < 8; i++)
{ {
@ -322,6 +413,59 @@ uint32_t redalert_state::screen_update_demoneye(screen_device &screen, bitmap_rg
} }
} }
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; return 0;
} }
@ -433,7 +577,7 @@ void redalert_state::ww3_video(machine_config &config)
void redalert_state::demoneye_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); redalert_video_common(config);