Rewrote and modernize driver:

- correct colors -- in places different from the manual's description, but matches the flyer perfectly
- added speech
- fixed AY-8910 sounds
- odds and ends
- for now, broke Demon Eye X, but I wanted to get this out
This commit is contained in:
Zsolt Vasvari 2008-01-23 02:00:08 +00:00
parent 7d8f30ab32
commit 79dcd62c8a
5 changed files with 595 additions and 697 deletions

1
.gitattributes vendored
View File

@ -2246,6 +2246,7 @@ src/mame/includes/psx.h svneol=native#text/plain
src/mame/includes/qix.h svneol=native#text/plain
src/mame/includes/rampart.h svneol=native#text/plain
src/mame/includes/realbrk.h svneol=native#text/plain
src/mame/includes/redalert.h svneol=native#text/plain
src/mame/includes/relief.h svneol=native#text/plain
src/mame/includes/rescap.h svneol=native#text/plain
src/mame/includes/segag80r.h svneol=native#text/plain

View File

@ -1,121 +1,228 @@
/***************************************************************************
Irem Red Alert sound hardware
Irem Red Alert hardware
The manual lists two sets of sounds.
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
Analogue:
- Formation Aircraft
- Dive bombers
- Helicopters
- Launcher firing
- Explosion #1
- Explosion #2
- Explosion #3
Digital:
- Melody #1. Starting sound.
- Melody #2. Ending sound
- Time signal
- Chirping birds
- Alarm
- Excellent
- Coin insertion
- MIRV division
- Megaton bomb - long
- Megaton bomb - short
- Megaton bomb landing
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
***************************************************************************/
****************************************************************************/
#include "driver.h"
#include "cpu/m6502/m6502.h"
#include "rescap.h"
#include "cpu/i8085/i8085.h"
#include "sound/ay8910.h"
#include "sound/hc55516.h"
static int AY8910_A_input_data = 0;
static int c030_data = 0;
static int sound_register_IC1 = 0;
static int sound_register_IC2 = 0;
WRITE8_HANDLER( redalert_c030_w )
#define AUDIO_PCB_CLOCK (XTAL_12_5MHz)
#define AUDIO_CPU_CLOCK (AUDIO_PCB_CLOCK / 12)
#define AY8910_CLOCK (AUDIO_PCB_CLOCK / 6)
#define AUDIO_CPU_IRQ_FREQ (1.0 / attotime_to_double(PERIOD_OF_555_ASTABLE(RES_K(120), RES_K(2.7), CAP_U(0.01))))
#define VOICE_PCB_CLOCK (XTAL_6MHz)
#define VOICE_CPU_CLOCK (VOICE_PCB_CLOCK)
#define HC55516_CLOCK (VOICE_PCB_CLOCK / 256)
/*************************************
*
* Statics
*
*************************************/
static UINT8 audio_register_IC1;
static UINT8 audio_register_IC2;
/*************************************
*
* Analog sounds
*
*************************************/
static WRITE8_HANDLER( redalert_analog_w )
{
c030_data = data & 0x3F;
/* this port triggers analog sounds
D0 = Formation Aircraft?
D1 = Dive bombers?
D2 = Helicopters?
D3 = Launcher firing?
D4 = Explosion #1?
D5 = Explosion #2?
D6 = Explosion #3? */
/* Is this some type of sound command? */
if (data & 0x80)
/* Cause an NMI on the voice CPU here? */
cpunum_set_input_line(2,I8085_RST75_LINE,HOLD_LINE);
logerror("Analog: %02X\n",data);
}
READ8_HANDLER( redalert_voicecommand_r )
/*************************************
*
* Audio board
*
*************************************/
WRITE8_HANDLER( redalert_audio_command_w )
{
return c030_data;
/* the byte is connected to port A of the AY8910 */
soundlatch_w(0, data);
/* D7 is also connected to the NMI input of the CPU -
the NMI is actually toggled by a 74121 */
if ((data & 0x80) == 0x00)
cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
}
WRITE8_HANDLER( redalert_soundlatch_w )
{
/* The byte is connected to Port A of the AY8910 */
AY8910_A_input_data = data;
/* Bit D7 is also connected to the NMI input of the CPU */
if ((data & 0x80)!=0x80)
cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE);
}
READ8_HANDLER( redalert_AY8910_A_r )
{
return AY8910_A_input_data;
}
WRITE8_HANDLER( redalert_AY8910_w )
static WRITE8_HANDLER( redalert_AY8910_w )
{
/* BC2 is connected to a pull-up resistor, so BC2=1 always */
switch (data)
switch (data & 0x03)
{
/* BC1=0, BDIR=0 : inactive */
case 0x00:
/* BC1=0, BDIR=0 : INACTIVE */
break;
/* BC1=1, BDIR=0 : read from PSG */
case 0x01:
/* BC1=1, BDIR=0 : READ FROM PSG */
sound_register_IC1 = AY8910_read_port_0_r(offset);
audio_register_IC1 = AY8910_read_port_0_r(offset);
break;
/* BC1=0, BDIR=1 : write to PSG */
case 0x02:
/* BC1=0, BDIR=1 : WRITE TO PSG */
AY8910_write_port_0_w(offset,sound_register_IC2);
break;
case 0x03:
/* BC1=1, BDIR=1 : LATCH ADDRESS */
AY8910_control_port_0_w(offset,sound_register_IC2);
AY8910_write_port_0_w(offset, audio_register_IC2);
break;
/* BC1=1, BDIR=1 : latch address */
default:
logerror("Invalid Sound Command: %02X\n",data);
case 0x03:
AY8910_control_port_0_w(offset, audio_register_IC2);
break;
}
}
READ8_HANDLER( redalert_sound_register_IC1_r )
static READ8_HANDLER( audio_register_IC1_r )
{
return sound_register_IC1;
return audio_register_IC1;
}
WRITE8_HANDLER( redalert_sound_register_IC2_w )
static WRITE8_HANDLER( audio_register_IC2_w )
{
sound_register_IC2 = data;
audio_register_IC2 = data;
}
WRITE8_HANDLER( redalert_AY8910_B_w )
static const struct AY8910interface ay8910_interface =
{
/* I'm fairly certain this port triggers analog sounds */
logerror("Port B Trigger: %02X\n",data);
/* D0 = Formation Aircraft? */
/* D1 = Dive bombers? */
/* D2 = Helicopters? */
/* D3 = Launcher firing? */
/* D4 = Explosion #1? */
/* D5 = Explosion #2? */
/* D6 = Explosion #3? */
soundlatch_r, 0, /* port A/B read */
0, redalert_analog_w /* port A/B write */
};
static ADDRESS_MAP_START( redalert_audio_map, ADDRESS_SPACE_PROGRAM, 8 )
ADDRESS_MAP_FLAGS( AMEF_ABITS(15) )
AM_RANGE(0x0000, 0x03ff) AM_MIRROR(0x0c00) AM_RAM
AM_RANGE(0x1000, 0x1000) AM_MIRROR(0x0ffe) AM_READWRITE(MRA8_NOP, redalert_AY8910_w)
AM_RANGE(0x1001, 0x1001) AM_MIRROR(0x0ffe) AM_READWRITE(audio_register_IC1_r, audio_register_IC2_w)
AM_RANGE(0x2000, 0x6fff) AM_NOP
AM_RANGE(0x7000, 0x77ff) AM_MIRROR(0x0800) AM_ROM
ADDRESS_MAP_END
static SOUND_START( redalert_audio )
{
state_save_register_global(audio_register_IC1);
state_save_register_global(audio_register_IC2);
}
/*************************************
*
* Voice board
*
*************************************/
WRITE8_HANDLER( redalert_voice_command_w )
{
soundlatch2_w(0, (data & 0x78) >> 3);
cpunum_set_input_line(2, I8085_RST75_LINE, (~data & 0x80) ? ASSERT_LINE : CLEAR_LINE);
}
static void sod_callback(int data)
{
hc55516_digit_w(0, data);
}
static int sid_callback(void)
{
return hc55516_clock_state_r(0);
}
static SOUND_START( redalert_voice )
{
cpunum_set_info_fct(2, CPUINFO_PTR_I8085_SOD_CALLBACK, (void *)sod_callback);
cpunum_set_info_fct(2, CPUINFO_PTR_I8085_SID_CALLBACK, (void *)sid_callback);
}
static ADDRESS_MAP_START( redalert_voice_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x3fff) AM_ROM
AM_RANGE(0x4000, 0x7fff) AM_NOP
AM_RANGE(0x8000, 0x83ff) AM_MIRROR(0x3c00) AM_RAM
AM_RANGE(0xc000, 0xc000) AM_MIRROR(0x3fff) AM_READWRITE(soundlatch2_r, MWA8_NOP)
ADDRESS_MAP_END
/*************************************
*
* Audio start
*
*************************************/
static SOUND_START( redalert )
{
SOUND_START_CALL(redalert_audio);
SOUND_START_CALL(redalert_voice);
}
/*************************************
*
* Machine driver
*
*************************************/
MACHINE_DRIVER_START( redalert_audio )
MDRV_CPU_ADD(M6502, AUDIO_CPU_CLOCK)
MDRV_CPU_PROGRAM_MAP(redalert_audio_map,0)
MDRV_CPU_PERIODIC_INT(irq0_line_hold, AUDIO_CPU_IRQ_FREQ)
MDRV_CPU_ADD(8085A, VOICE_CPU_CLOCK)
MDRV_CPU_PROGRAM_MAP(redalert_voice_map,0)
MDRV_SOUND_START( redalert )
MDRV_SPEAKER_STANDARD_MONO("mono")
MDRV_SOUND_ADD(AY8910, AY8910_CLOCK)
MDRV_SOUND_CONFIG(ay8910_interface)
MDRV_SOUND_ROUTE(0, "mono", 0.50)
MDRV_SOUND_ROUTE(1, "mono", 0.50)
/* channel C is used a noise source and is not connected to a speaker */
MDRV_SOUND_ADD(HC55516, HC55516_CLOCK)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_DRIVER_END

View File

@ -1,181 +1,200 @@
/***************************************************************************
Irem Red Alert Driver
Irem Red Alert hardware
Everything in this driver is guesswork and speculation. If something
seems wrong, it probably is.
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
***************************************************************************/
********************************************************************
IREM 'DEMONEYE-X' proto 1981
proto sound board
8910
6821 8910
6802 sound6 sound7
3.579545MHz
main board M-27M-C
11.73MHz 6502 x x x xx
x x x on
4116 8
4116 -
4116 9
4116 6
4116 A
4116 7
4116 B
4116
sub board 1 M-27Sb
1a2
2114
2114
2114 <- two parts piggy-backed
2114 <- two parts piggy-backed
2114 2114
2114 2114
sub board 2 M-42-S
1a clr(missing)
2114
2114
2114
2114
2114
2114
*********************************************************************
Known issues/to-do's:
* Analog sounds
* DIP switches have a different meaning in test mode (see manual)
* Video timing from schematics
* Audio CPU NMI is generated by a 74121 multivibrator, the correct
pulse length is not emulated
****************************************************************************/
#include "driver.h"
#include "machine/6821pia.h"
#include "sound/ay8910.h"
/* video/redalert.c */
extern UINT8 *redalert_backram;
extern UINT8 *redalert_spriteram1;
extern UINT8 *redalert_spriteram2;
extern UINT8 *redalert_spriteram3;
extern UINT8 *redalert_characterram;
extern UINT8 *redalert_characterram2;
WRITE8_HANDLER( redalert_backram_w );
WRITE8_HANDLER( redalert_spriteram1_w );
WRITE8_HANDLER( redalert_spriteram2_w );
WRITE8_HANDLER( redalert_spriteram3_w );
WRITE8_HANDLER( redalert_spriteram4_w );
WRITE8_HANDLER( redalert_characterram_w );
WRITE8_HANDLER( redalert_characterram2_w );
extern VIDEO_UPDATE( redalert );
WRITE8_HANDLER( redalert_c040_w );
WRITE8_HANDLER( demoneye_c040_w );
WRITE8_HANDLER( redalert_backcolor_w );
#include "redalert.h"
/* audio/redalert.c */
WRITE8_HANDLER( redalert_c030_w );
READ8_HANDLER( redalert_voicecommand_r );
WRITE8_HANDLER( redalert_soundlatch_w );
READ8_HANDLER( redalert_AY8910_A_r );
WRITE8_HANDLER( redalert_AY8910_B_w );
WRITE8_HANDLER( redalert_AY8910_w );
READ8_HANDLER( redalert_sound_register_IC1_r );
WRITE8_HANDLER( redalert_sound_register_IC2_w );
#define MAIN_PCB_CLOCK (XTAL_12_5MHz)
#define MAIN_CPU_CLOCK (MAIN_PCB_CLOCK / 16)
static ADDRESS_MAP_START( redalert_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x01ff) AM_READ(MRA8_RAM) /* Zero page / stack */
AM_RANGE(0x0200, 0x0fff) AM_READ(MRA8_RAM) /* ? */
AM_RANGE(0x1000, 0x1fff) AM_READ(MRA8_RAM) /* Scratchpad video RAM */
AM_RANGE(0x2000, 0x4fff) AM_READ(MRA8_RAM) /* Video RAM */
AM_RANGE(0x5000, 0xbfff) AM_READ(MRA8_ROM)
AM_RANGE(0xc100, 0xc100) AM_READ(input_port_0_r)
AM_RANGE(0xc110, 0xc110) AM_READ(input_port_1_r)
AM_RANGE(0xc120, 0xc120) AM_READ(input_port_2_r)
AM_RANGE(0xc170, 0xc170) AM_READ(watchdog_reset_r)
AM_RANGE(0xf000, 0xffff) AM_READ(MRA8_ROM) /* remapped ROM for 6502 vectors */
ADDRESS_MAP_END
static ADDRESS_MAP_START( redalert_writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x01ff) AM_WRITE(MWA8_RAM)
AM_RANGE(0x0200, 0x0fff) AM_WRITE(MWA8_RAM) /* ? */
AM_RANGE(0x1000, 0x1fff) AM_WRITE(MWA8_RAM) /* Scratchpad video RAM */
AM_RANGE(0x2000, 0x3fff) AM_WRITE(redalert_backram_w) AM_BASE(&redalert_backram)
AM_RANGE(0x4000, 0x43ff) AM_WRITE(MWA8_RAM) AM_BASE(&videoram) AM_SIZE(&videoram_size)
AM_RANGE(0x4400, 0x47ff) AM_WRITE(redalert_spriteram1_w) AM_BASE(&redalert_spriteram1)
AM_RANGE(0x4800, 0x4bff) AM_WRITE(redalert_characterram_w) AM_BASE(&redalert_characterram)
AM_RANGE(0x4c00, 0x4fff) AM_WRITE(redalert_spriteram2_w) AM_BASE(&redalert_spriteram2)
AM_RANGE(0x5000, 0xbfff) AM_WRITE(MWA8_ROM)
AM_RANGE(0xc130, 0xc130) AM_WRITE(redalert_c030_w)
AM_RANGE(0xc140, 0xc140) AM_WRITE(redalert_c040_w)
AM_RANGE(0xc150, 0xc150) AM_WRITE(redalert_backcolor_w)
AM_RANGE(0xc160, 0xc160) AM_WRITE(redalert_soundlatch_w)
AM_RANGE(0xf000, 0xffff) AM_WRITE(MWA8_ROM)
ADDRESS_MAP_END
/* PIA 0, sound CPU */
static const pia6821_interface pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ 0, 0
};
static ADDRESS_MAP_START( redalert_sound_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x03ff) AM_READ(MRA8_RAM)
AM_RANGE(0x7800, 0x7fff) AM_READ(MRA8_ROM)
AM_RANGE(0xf800, 0xffff) AM_READ(MRA8_ROM)
AM_RANGE(0x1001, 0x1001) AM_READ(redalert_sound_register_IC1_r)
ADDRESS_MAP_END
static MACHINE_START( demoneye )
{
pia_config(0, &pia_0_intf);
}
static ADDRESS_MAP_START( redalert_sound_writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x03ff) AM_WRITE(MWA8_RAM)
AM_RANGE(0x7800, 0x7fff) AM_WRITE(MWA8_ROM)
AM_RANGE(0xf800, 0xffff) AM_WRITE(MWA8_ROM)
AM_RANGE(0x1000, 0x1000) AM_WRITE(redalert_AY8910_w)
AM_RANGE(0x1001, 0x1001) AM_WRITE(redalert_sound_register_IC2_w)
ADDRESS_MAP_END
static MACHINE_RESET( demoneye )
{
pia_reset();
}
static ADDRESS_MAP_START( redalert_voice_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x3fff) AM_READ(MRA8_ROM)
AM_RANGE(0x8000, 0x83ff) AM_READ(MRA8_RAM)
AM_RANGE(0xc000, 0xc000) AM_READ(redalert_voicecommand_r) /* reads command from D0-D5? */
ADDRESS_MAP_END
static ADDRESS_MAP_START( redalert_voice_writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x3fff) AM_WRITE(MWA8_ROM)
AM_RANGE(0x8000, 0x83ff) AM_WRITE(MWA8_RAM)
/*************************************
*
* Interrupt generation
*
*************************************/
static INTERRUPT_GEN( redalert_interrupt )
{
if( readinputport(3) )
cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
cpunum_set_input_line(0, 0, HOLD_LINE);
}
/*************************************
*
* Memory handlers
*
*************************************/
static ADDRESS_MAP_START( redalert_main_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x1fff) AM_RAM
AM_RANGE(0x2000, 0x3fff) AM_READWRITE(MRA8_RAM, redalert_bitmap_videoram_w) AM_BASE(&redalert_bitmap_videoram)
AM_RANGE(0x4000, 0x4fff) AM_RAM AM_BASE(&redalert_charmap_videoram)
AM_RANGE(0x5000, 0xbfff) AM_ROM
AM_RANGE(0xc000, 0xc000) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_0_r, MWA8_NOP)
AM_RANGE(0xc010, 0xc010) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_1_r, MWA8_NOP)
AM_RANGE(0xc020, 0xc020) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_2_r, MWA8_NOP)
AM_RANGE(0xc030, 0xc030) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, redalert_audio_command_w)
AM_RANGE(0xc040, 0xc040) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_RAM) AM_BASE(&redalert_video_control)
AM_RANGE(0xc050, 0xc050) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_RAM) AM_BASE(&redalert_bitmap_color)
AM_RANGE(0xc060, 0xc060) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, redalert_voice_command_w)
AM_RANGE(0xc070, 0xc070) AM_MIRROR(0x0f8f) AM_READWRITE(watchdog_reset_r, MWA8_NOP)
AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION(REGION_CPU1, 0x8000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( demoneye_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x01ff) AM_READ(MRA8_RAM) /* Zero page / stack */
AM_RANGE(0x0200, 0x0fff) AM_READ(MRA8_RAM) /* ? */
AM_RANGE(0x1000, 0x1fff) AM_READ(MRA8_RAM) /* Scratchpad video RAM */
AM_RANGE(0x2000, 0x4fff) AM_READ(MRA8_RAM) /* Video RAM */
AM_RANGE(0x5000, 0x5fff) AM_READ(MRA8_RAM)
AM_RANGE(0x6000, 0xbfff) AM_READ(MRA8_ROM)
AM_RANGE(0xc100, 0xc100) AM_READ(input_port_0_r)
AM_RANGE(0xc110, 0xc110) AM_READ(input_port_1_r)
AM_RANGE(0xc120, 0xc120) AM_READ(input_port_2_r)
AM_RANGE(0xf000, 0xffff) AM_READ(MRA8_ROM) /* remapped ROM for 6502 vectors */
static ADDRESS_MAP_START( demoneye_main_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x1fff) AM_RAM
AM_RANGE(0x2000, 0x3fff) AM_READWRITE(MRA8_RAM, redalert_bitmap_videoram_w) AM_BASE(&redalert_bitmap_videoram)
AM_RANGE(0x4000, 0x4fff) AM_RAM AM_BASE(&redalert_charmap_videoram)
AM_RANGE(0x5000, 0x5fff) AM_RAM
// AM_RANGE(0x5000, 0x53ff) AM_WRITE(MWA8_RAM) AM_BASE(&videoram) AM_SIZE(&videoram_size)
// AM_RANGE(0x5400, 0x57ff) AM_WRITE(MWA8_RAM) AM_BASE(&redalert_spriteram3)
// AM_RANGE(0x5800, 0x5bff) AM_WRITE(MWA8_RAM) //???
// AM_RANGE(0x5c00, 0x5fff) AM_WRITE(MWA8_RAM) //???
AM_RANGE(0x6000, 0xbfff) AM_ROM
AM_RANGE(0xc000, 0xc000) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_0_r, MWA8_NOP)
AM_RANGE(0xc010, 0xc010) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_1_r, MWA8_NOP)
AM_RANGE(0xc020, 0xc020) AM_MIRROR(0x0f8f) AM_READWRITE(input_port_2_r, MWA8_NOP)
AM_RANGE(0xc030, 0xc030) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_NOP)
AM_RANGE(0xc040, 0xc040) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_RAM) AM_BASE(&redalert_video_control)
AM_RANGE(0xc050, 0xc050) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_RAM) AM_BASE(&redalert_bitmap_color)
AM_RANGE(0xc060, 0xc060) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_NOP)
AM_RANGE(0xc070, 0xc070) AM_MIRROR(0x0f8f) AM_READWRITE(MRA8_NOP, MWA8_NOP)
AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION(REGION_CPU1, 0x8000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( demoneye_writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x01ff) AM_WRITE(MWA8_RAM)
AM_RANGE(0x0200, 0x0fff) AM_WRITE(MWA8_RAM) /* ? */
AM_RANGE(0x1000, 0x1fff) AM_WRITE(MWA8_RAM) /* Scratchpad video RAM */
AM_RANGE(0x2000, 0x3fff) AM_WRITE(redalert_backram_w) AM_BASE(&redalert_backram)
AM_RANGE(0x4000, 0x43ff) AM_WRITE(redalert_characterram_w) AM_BASE(&redalert_characterram)
AM_RANGE(0x4400, 0x47ff) AM_WRITE(redalert_spriteram1_w) AM_BASE(&redalert_spriteram1)
AM_RANGE(0x4800, 0x4bff) AM_WRITE(redalert_characterram2_w) AM_BASE(&redalert_characterram2)
AM_RANGE(0x4c00, 0x4fff) AM_WRITE(redalert_spriteram2_w) AM_BASE(&redalert_spriteram2)
AM_RANGE(0x5000, 0x53ff) AM_WRITE(MWA8_RAM) AM_BASE(&videoram) AM_SIZE(&videoram_size)
AM_RANGE(0x5400, 0x57ff) AM_WRITE(redalert_spriteram3_w) AM_BASE(&redalert_spriteram3)
AM_RANGE(0x5800, 0x5bff) AM_WRITE(MWA8_RAM) //???
AM_RANGE(0x5c00, 0x5fff) AM_WRITE(MWA8_RAM) //???
AM_RANGE(0x6000, 0xbfff) AM_WRITE(MWA8_ROM)
AM_RANGE(0xc130, 0xc130) AM_WRITE(MWA8_NOP)
AM_RANGE(0xc140, 0xc140) AM_WRITE(demoneye_c040_w)
AM_RANGE(0xc150, 0xc150) AM_WRITE(redalert_backcolor_w)
AM_RANGE(0xc160, 0xc160) AM_WRITE(MWA8_NOP)
AM_RANGE(0xc161, 0xc161) AM_WRITE(MWA8_NOP)
AM_RANGE(0xc162, 0xc162) AM_WRITE(watchdog_reset_w)
AM_RANGE(0xc163, 0xc163) AM_WRITE(MWA8_NOP)
AM_RANGE(0xc170, 0xc170) AM_WRITE(MWA8_NOP)
AM_RANGE(0xf000, 0xffff) AM_WRITE(MWA8_ROM)
ADDRESS_MAP_END
//static ADDRESS_MAP_START( demoneye_sound_readmem, ADDRESS_SPACE_PROGRAM, 8 )
// AM_RANGE(0x0000, 0x007f) AM_READ(MRA8_RAM)
// AM_RANGE(0x0500, 0x0503) AM_READ(pia_0_r)
// AM_RANGE(0x2000, 0x2fff) AM_READ(MRA8_ROM)
// AM_RANGE(0xf000, 0xffff) AM_READ(MRA8_ROM)
//ADDRESS_MAP_END
static ADDRESS_MAP_START( demoneye_sound_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x007f) AM_READ(MRA8_RAM)
AM_RANGE(0x0500, 0x0503) AM_READ(pia_0_r)
AM_RANGE(0x2000, 0x2fff) AM_READ(MRA8_ROM)
AM_RANGE(0xf000, 0xffff) AM_READ(MRA8_ROM)
ADDRESS_MAP_END
//static ADDRESS_MAP_START( demoneye_sound_writemem, ADDRESS_SPACE_PROGRAM, 8 )
// AM_RANGE(0x0000, 0x007f) AM_WRITE(MWA8_RAM)
// AM_RANGE(0x0500, 0x0503) AM_WRITE(pia_0_w)
// AM_RANGE(0x2000, 0x2fff) AM_WRITE(MWA8_ROM)
// AM_RANGE(0xf000, 0xffff) AM_WRITE(MWA8_ROM)
//ADDRESS_MAP_END
static ADDRESS_MAP_START( demoneye_sound_writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x007f) AM_WRITE(MWA8_RAM)
AM_RANGE(0x0500, 0x0503) AM_WRITE(pia_0_w)
AM_RANGE(0x2000, 0x2fff) AM_WRITE(MWA8_ROM)
AM_RANGE(0xf000, 0xffff) AM_WRITE(MWA8_ROM)
ADDRESS_MAP_END
/*************************************
*
* Port definitions
*
*************************************/
static INPUT_PORTS_START( redalert )
PORT_START /* DIP Switches */
PORT_DIPNAME( 0x03, 0x00, DEF_STR( Lives ) )
PORT_START
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_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_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_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_DIPNAME( 0x40, 0x40, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW:7")
PORT_DIPSETTING( 0x40, DEF_STR( Upright ) )
PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_SERVICE( 0x80, IP_ACTIVE_HIGH )
PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW:8" )
PORT_START /* IN1 */
PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_START1 )
@ -252,210 +271,49 @@ static INPUT_PORTS_START( demoneye )
INPUT_PORTS_END
static const gfx_layout backlayout =
{
8,8, /* 8*8 characters */
0x400, /* 1024 characters */
1, /* 1 bits per pixel */
{ 0 }, /* No info needed for bit offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
};
static const gfx_layout charlayout =
{
8,8, /* 8*8 characters */
128, /* 128 characters */
1, /* 1 bits per pixel */
{ 0 }, /* No info needed for bit offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
};
static const gfx_layout spritelayout =
{
8,8, /* 8*8 characters */
128, /* 128 characters */
2, /* 2 bits per pixel */
{ 0, 0x800*8 }, /* No info needed for bit offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 consecutive bytes */
};
static GFXDECODE_START( redalert )
GFXDECODE_ENTRY( 0, 0x3000, backlayout, 0, 8 ) /* the game dynamically modifies this */
GFXDECODE_ENTRY( 0, 0x4800, charlayout, 0, 8 ) /* the game dynamically modifies this */
GFXDECODE_ENTRY( 0, 0x4400, spritelayout,16, 4 ) /* the game dynamically modifies this */
GFXDECODE_END
static GFXDECODE_START( demoneye )
GFXDECODE_ENTRY( 0, 0x3000, backlayout, 0, 8 ) /* the game dynamically modifies this */
GFXDECODE_ENTRY( 0, 0x4800, spritelayout,16, 4 ) /* the game dynamically modifies this */
GFXDECODE_ENTRY( 0, 0x4400, spritelayout,16, 4 ) /* the game dynamically modifies this */
GFXDECODE_ENTRY( 0, 0x5400, spritelayout,16, 4 ) /* the game dynamically modifies this */
GFXDECODE_END
/* Arbitrary colortable */
static const UINT16 colortable_source[] =
{
0,7,
0,6,
0,2,
0,4,
0,3,
0,6,
0,1,
0,8,
0,8,8,8,
0,6,4,7,
0,6,4,1,
0,8,5,1,
};
static PALETTE_INIT( redalert )
{
/* Arbitrary colors */
palette_set_color(machine,0,MAKE_RGB(0x40,0x80,0xff)); /* Background */
palette_set_color(machine,1,MAKE_RGB(0x00,0x00,0xff)); /* Blue */
palette_set_color(machine,2,MAKE_RGB(0xff,0x00,0xff)); /* Magenta */
palette_set_color(machine,3,MAKE_RGB(0x00,0xff,0xff)); /* Cyan */
palette_set_color(machine,4,MAKE_RGB(0xff,0x00,0x00)); /* Red */
palette_set_color(machine,5,MAKE_RGB(0xff,0x80,0x00)); /* Orange */
palette_set_color(machine,6,MAKE_RGB(0xff,0xff,0x00)); /* Yellow */
palette_set_color(machine,7,MAKE_RGB(0xff,0xff,0xff)); /* White */
palette_set_color(machine,8,MAKE_RGB(0x00,0x00,0x00)); /* Black */
memcpy(colortable,colortable_source,sizeof(colortable_source));
}
static INTERRUPT_GEN( redalert_interrupt )
{
if( readinputport(3) )
{
cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
}
else
{
cpunum_set_input_line(0, 0, HOLD_LINE);
}
}
static const struct AY8910interface redalert_ay8910_interface =
{
redalert_AY8910_A_r, /* Port A Read */
0, /* Port B Read */
0, /* Port A Write */
redalert_AY8910_B_w /* Port B Write */
};
/*************************************
*
* Machine drivers
*
*************************************/
static MACHINE_DRIVER_START( redalert )
/* basic machine hardware */
MDRV_CPU_ADD(M6502, 1000000) /* ???? */
MDRV_CPU_PROGRAM_MAP(redalert_readmem,redalert_writemem)
MDRV_CPU_ADD(M6502, MAIN_CPU_CLOCK)
MDRV_CPU_PROGRAM_MAP(redalert_main_map,0)
MDRV_CPU_VBLANK_INT(redalert_interrupt,1)
MDRV_CPU_ADD(M6502, 1000000)
/* audio CPU */ /* 1 MHz */
MDRV_CPU_PROGRAM_MAP(redalert_sound_readmem,redalert_sound_writemem)
/* IRQ is hooked to a 555 timer, whose freq is 1150 Hz */
MDRV_CPU_PERIODIC_INT(irq0_line_hold,1150)
MDRV_CPU_ADD(8085A, 2000000)
/* audio CPU */ /* 1 MHz? */
MDRV_CPU_PROGRAM_MAP(redalert_voice_readmem,redalert_voice_writemem)
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION)
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 1*8, 31*8-1)
MDRV_GFXDECODE(redalert)
MDRV_PALETTE_LENGTH(9)
MDRV_COLORTABLE_LENGTH(sizeof(colortable_source) / sizeof(colortable_source[0]))
MDRV_IMPORT_FROM(redalert_video)
MDRV_PALETTE_INIT(redalert)
MDRV_VIDEO_START(generic)
MDRV_VIDEO_UPDATE(redalert)
/* sound hardware */
MDRV_SPEAKER_STANDARD_MONO("mono")
MDRV_SOUND_ADD(AY8910, 2000000)
MDRV_SOUND_CONFIG(redalert_ay8910_interface)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
/* audio hardware */
MDRV_IMPORT_FROM(redalert_audio)
MACHINE_DRIVER_END
/* PIA 0, sound CPU */
static const pia6821_interface pia_0_intf =
{
/*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
/*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
/*irqs : A/B */ 0, 0
};
static MACHINE_START( demoneye )
{
pia_config(0, &pia_0_intf);
}
static MACHINE_RESET( demoneye )
{
pia_reset();
}
static MACHINE_DRIVER_START( demoneye )
/* basic machine hardware */
MDRV_CPU_ADD(M6502, 11730000/2) /* 11.73MHz */
MDRV_CPU_PROGRAM_MAP(demoneye_readmem,demoneye_writemem)
MDRV_CPU_ADD(M6502, MAIN_CPU_CLOCK)
MDRV_CPU_PROGRAM_MAP(demoneye_main_map,0)
MDRV_CPU_VBLANK_INT(redalert_interrupt,1)
MDRV_CPU_ADD(M6802, 3579545) /* 3.579545 MHz */
/* audio CPU */
MDRV_CPU_PROGRAM_MAP(demoneye_sound_readmem,demoneye_sound_writemem)
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION)
MDRV_MACHINE_START(demoneye)
MDRV_MACHINE_RESET(demoneye)
MDRV_MACHINE_START( demoneye )
MDRV_MACHINE_RESET( demoneye )
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 1*8, 31*8-1)
MDRV_GFXDECODE(demoneye)
MDRV_PALETTE_LENGTH(9)
MDRV_COLORTABLE_LENGTH(sizeof(colortable_source) / sizeof(colortable_source[0]))
MDRV_PALETTE_INIT(redalert)
MDRV_VIDEO_START(generic)
MDRV_VIDEO_UPDATE(redalert)
/* sound hardware */
MDRV_SPEAKER_STANDARD_MONO("mono")
MDRV_SOUND_ADD(AY8910, 3579545)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MDRV_SOUND_ADD(AY8910, 3579545)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MDRV_IMPORT_FROM(redalert_video)
MACHINE_DRIVER_END
/***************************************************************************
Game ROMs
***************************************************************************/
/*************************************
*
* ROM definitions
*
*************************************/
ROM_START( redalert )
ROM_REGION( 0x10000, REGION_CPU1, 0 )
@ -463,14 +321,12 @@ ROM_START( redalert )
ROM_LOAD( "rag6", 0x6000, 0x1000, CRC(cb2a308c) SHA1(9f3bc22bad31165e080e81d4a3fb0ec2aad235fe) )
ROM_LOAD( "rag7n", 0x7000, 0x1000, CRC(82ab2dae) SHA1(f8328b048384afac245f1c16a2d0864ffe0b4741) )
ROM_LOAD( "rag8n", 0x8000, 0x1000, CRC(b80eece9) SHA1(d986449bdb1d94832187c7f953f01330391ef4c9) )
ROM_RELOAD( 0xf000, 0x1000 )
ROM_LOAD( "rag9", 0x9000, 0x1000, CRC(2b7d1295) SHA1(1498af0c55bd38fe79b91afc38921085102ebbc3) )
ROM_LOAD( "ragab", 0xa000, 0x1000, CRC(ab99f5ed) SHA1(a93713bb03d61cce64adc89b874b67adea7c53cd) )
ROM_LOAD( "ragb", 0xb000, 0x1000, CRC(8e0d1661) SHA1(bff4ddca761ddd70113490f50777e62c66813685) )
ROM_REGION( 0x10000, REGION_CPU2, 0 )
ROM_LOAD( "w3s1", 0x7800, 0x0800, CRC(4af956a5) SHA1(25368a40d7ebc60316fd2d78ec4c686e701b96dc) )
ROM_RELOAD( 0xf800, 0x0800 )
ROM_LOAD( "w3s1", 0x7000, 0x0800, CRC(4af956a5) SHA1(25368a40d7ebc60316fd2d78ec4c686e701b96dc) )
ROM_REGION( 0x10000, REGION_CPU3, 0 )
ROM_LOAD( "ras1b", 0x0000, 0x1000, CRC(ec690845) SHA1(26a84738bd45ed21dac6c8383ebd9c3b9831024a) )
@ -478,64 +334,16 @@ ROM_START( redalert )
ROM_LOAD( "ras3", 0x2000, 0x1000, CRC(20d56f3e) SHA1(5c32ee3365407e6d3f7ab5662e9ecbac437ed4cb) )
ROM_LOAD( "ras4", 0x3000, 0x1000, CRC(130e66db) SHA1(385b8f889fee08fddbb2f75a691af569109eacd1) )
ROM_REGION( 0x0200, REGION_PROMS, 0 ) /* unknow */
ROM_REGION( 0x0200, REGION_PROMS, 0 ) /* color PROM */
ROM_LOAD( "m-257sc.1a", 0x0000, 0x0200, CRC(b1aca792) SHA1(db37f99b9880cc3c434e2a55a0bbb017d9a72aa3) )
ROM_END
/********************************************************************
IREM 'DEMONEYE-X' proto 1981
proto sound board
8910
6821 8910
6802 sound6 sound7
3.579545MHz
main board M-27M-C
11.73MHz 6502 x x x xx
x x x on
4116 8
4116 -
4116 9
4116 6
4116 A
4116 7
4116 B
4116
sub board 1 M-27Sb
1a2
2114
2114
2114 <- two parts piggy-backed
2114 <- two parts piggy-backed
2114 2114
2114 2114
sub board 2 M-42-S
1a clr(missing)
2114
2114
2114
2114
2114
2114
*********************************************************************/
ROM_START( demoneye )
ROM_REGION( 0x10000, REGION_CPU1, 0 )
ROM_LOAD( "demoneye.6", 0x6000, 0x1000, CRC(b03ee3a9) SHA1(66b6115fbb4e8097152702022c59c464e8211e5a) )
ROM_LOAD( "demoneye.7", 0x7000, 0x1000, CRC(667a5de7) SHA1(c3ce7fbbc6c98250e9d5f85854e6887017ca5ff9) )
ROM_LOAD( "demoneye.8", 0x8000, 0x1000, CRC(257484d7) SHA1(3937cce546462a471adbdc1da63ddfc20cfc7b79) )
ROM_RELOAD( 0xf000, 0x1000 )
ROM_LOAD( "demoneye.9", 0x9000, 0x1000, CRC(bd8d79a8) SHA1(68c1443ef78b545eb9e612573b86515c3ad7f103) )
ROM_LOAD( "demoneye.a", 0xa000, 0x1000, CRC(a27d08aa) SHA1(659ad22778e852fc58f3951d62bc01151c973d36) )
ROM_LOAD( "demoneye.b", 0xb000, 0x1000, CRC(1fd3585b) SHA1(b1697b7b21b739499fda1e155530dbfab89f3358) )
@ -544,10 +352,18 @@ ROM_START( demoneye )
ROM_LOAD( "demoneye.7s", 0x2000, 0x1000, CRC(8fdc9364) SHA1(3fccb5b22f08d6a0cde85863c1ce5399c84f233e) )
ROM_LOAD( "demoneye.6s", 0xf000, 0x1000, CRC(0a23def9) SHA1(b52f52be312ec7810e3c9cbd3913e887f983b1ee) )
ROM_REGION( 0x0400, REGION_USER1, 0 ) /* unknow */
ROM_REGION( 0x0400, REGION_PROMS, 0 ) /* unknow */
ROM_LOAD( "demoneye.1a", 0x0000, 0x0200, CRC(d03488ea) SHA1(11027f502ad2a9255b2e5611ab2eee16ede1d704) )
ROM_LOAD( "demoneye.1a2", 0x0200, 0x0200, CRC(eaf5a66e) SHA1(d8ebe05ba5d75fbf6ad45f710e5bd27b6afad44b) )
ROM_END
GAME( 1981, redalert, 0, redalert, redalert, 0, ROT270, "Irem + GDI", "Red Alert", GAME_WRONG_COLORS | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
GAME( 1981, demoneye, 0, demoneye, demoneye, 0, ROT270, "Irem", "Demoneye-X", GAME_WRONG_COLORS | GAME_IMPERFECT_GRAPHICS | GAME_NO_SOUND )
/*************************************
*
* Game drivers
*
*************************************/
GAME( 1981, redalert, 0, redalert, redalert, 0, ROT270, "Irem + GDI", "Red Alert", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
GAME( 1981, demoneye, 0, demoneye, demoneye, 0, ROT270, "Irem", "Demoneye-X", GAME_WRONG_COLORS | GAME_IMPERFECT_GRAPHICS | GAME_NO_SOUND | GAME_SUPPORTS_SAVE )

View File

@ -0,0 +1,26 @@
/***************************************************************************
Irem Red Alert hardware
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
****************************************************************************/
/*----------- defined in audio/redalert.c -----------*/
WRITE8_HANDLER( redalert_audio_command_w );
WRITE8_HANDLER( redalert_voice_command_w );
MACHINE_DRIVER_EXTERN( redalert_audio );
/*----------- defined in video/redalert.c -----------*/
extern UINT8 *redalert_bitmap_videoram;
extern UINT8 *redalert_bitmap_color;
extern UINT8 *redalert_charmap_videoram;
extern UINT8 *redalert_video_control;
WRITE8_HANDLER( redalert_bitmap_videoram_w );
MACHINE_DRIVER_EXTERN( redalert_video );

View File

@ -1,289 +1,237 @@
/***************************************************************************
video.c
Irem Red Alert hardware
Functions to emulate the video hardware of the machine.
If you have any questions about how this driver works, don't hesitate to
ask. - Mike Balfour (mab22@po.cwru.edu)
***************************************************************************/
****************************************************************************/
#include "driver.h"
UINT8 *redalert_backram;
UINT8 *redalert_spriteram1;
UINT8 *redalert_spriteram2;
UINT8 *redalert_spriteram3;
UINT8 *redalert_characterram;
UINT8 *redalert_characterram2;
static UINT8 redalert_dirtyback[0x400];
static UINT8 redalert_dirtycharacter[0x100];
static UINT8 redalert_dirtycharacter2[0x100];
static UINT8 redalert_backcolor[0x400];
#include "video/resnet.h"
/* There might be a color PROM that dictates this? */
/* These guesses are based on comparing the color bars on the test
screen with the picture in the manual */
static const UINT8 color_lookup[] = {
1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,
1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
#define NUM_CHARMAP_PENS 0x200
#define NUM_BITMAP_PENS 8
1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
};
static int backcolor, flip=0;
WRITE8_HANDLER( redalert_c040_w )
/*************************************
*
* Global variables
*
*************************************/
UINT8 *redalert_bitmap_videoram;
UINT8 *redalert_bitmap_color;
UINT8 *redalert_charmap_videoram;
UINT8 *redalert_video_control;
/*************************************
*
* Local variable
*
*************************************/
static UINT8 *redalert_bitmap_colorram;
/*************************************
*
* Bitmap videoram write handler
*
*************************************/
WRITE8_HANDLER( redalert_bitmap_videoram_w )
{
/* Only seems to load D0-D3 into a flip-flop. */
/* D0/D1 seem to head off to unconnected circuits */
/* D2 connects to a "NL" line, and NOTted to a "NH" line */
/* D3 connects to a "YI" line */
/*
D0 == 1 -> 1 player
D1 == 1 and D0 == 1 -> 2 players
*/
flip = !(data & 0x04);
redalert_bitmap_videoram[offset ] = data;
redalert_bitmap_colorram[offset >> 3] = *redalert_bitmap_color & 0x07;
}
WRITE8_HANDLER( redalert_backcolor_w )
/*************************************
*
* Color generation
*
*************************************/
static void get_pens(pen_t *pens)
{
/* Only seems to load D0-D2 into a flip-flop. */
/* Outputs feed into RAM which seems to feed to RGB lines. */
backcolor = data & 0x07;
}
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 };
WRITE8_HANDLER( demoneye_c040_w )
{
/*
D0 == 1 -> 1 player
D1 == 1 and D0 == 1 -> 2 players
*/
flip = data & 0x04;
}
offs_t offs;
double scaler;
double bitmap_weight[1];
double charmap_rg_weights[3];
double charmap_b_weights[2];
double back_r_weight[1];
double back_gb_weight[1];
/***************************************************************************
redalert_backram_w
***************************************************************************/
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);
WRITE8_HANDLER( redalert_backram_w )
{
int charnum;
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, 0, 0, 0, 0);
charnum = offset / 8 % 0x400;
if ((redalert_backram[offset] != data) ||
(redalert_backcolor[charnum] != backcolor))
/* the character layer colors come from the PROM */
for (offs = 0; offs < NUM_CHARMAP_PENS; offs++)
{
redalert_dirtyback[charnum] = 1;
redalert_backcolor[charnum] = backcolor;
UINT8 data = memory_region(REGION_PROMS)[offs];
redalert_backram[offset] = data;
}
}
/* very strange mapping */
UINT8 r0_bit = (data >> 2) & 0x01;
UINT8 r1_bit = (data >> 6) & 0x01;
UINT8 r2_bit = (data >> 4) & 0x01;
UINT8 g0_bit = (data >> 1) & 0x01;
UINT8 g1_bit = (data >> 3) & 0x01;
UINT8 g2_bit = (data >> 5) & 0x01;
UINT8 b0_bit = (data >> 0) & 0x01;
UINT8 b1_bit = (data >> 7) & 0x01;
/***************************************************************************
redalert_spriteram1_w
***************************************************************************/
UINT8 r = combine_3_weights(charmap_rg_weights, r0_bit, r1_bit, r2_bit);
UINT8 g = combine_3_weights(charmap_rg_weights, g0_bit, g1_bit, g2_bit);
UINT8 b = combine_2_weights(charmap_b_weights, b0_bit, b1_bit);
WRITE8_HANDLER( redalert_spriteram1_w )
{
if (redalert_spriteram1[offset] != data)
{
redalert_dirtycharacter[((offset / 8) % 0x80) + 0x80] = 1;
redalert_spriteram1[offset] = data;
}
}
/***************************************************************************
redalert_spriteram2_w
***************************************************************************/
WRITE8_HANDLER( redalert_spriteram2_w )
{
if (redalert_spriteram2[offset] != data)
{
redalert_dirtycharacter[((offset / 8) % 0x80) + 0x80] = 1;
redalert_spriteram2[offset] = data;
}
}
/***************************************************************************
redalert_characterram_w
***************************************************************************/
WRITE8_HANDLER( redalert_characterram_w )
{
if (redalert_characterram[offset] != data)
{
redalert_dirtycharacter[((offset / 8) % 0x80)] = 1;
redalert_characterram[offset] = data;
}
}
WRITE8_HANDLER( redalert_characterram2_w )
{
if (redalert_characterram2[offset] != data)
{
redalert_dirtycharacter[((offset / 8) % 0x80)] = 1;
redalert_characterram2[offset] = data;
}
}
WRITE8_HANDLER( redalert_spriteram3_w )
{
if (redalert_spriteram3[offset] != data)
{
redalert_dirtycharacter2[((offset / 8) % 0x80) + 0x80] = 1;
redalert_spriteram3[offset] = data;
pens[offs] = MAKE_RGB(r, g, b);
}
/* the bitmap layer colors are directly mapped */
for (offs = 0; offs < NUM_BITMAP_PENS; offs++)
{
UINT8 r_bit = (offs >> 2) & 0x01;
UINT8 g_bit = (offs >> 1) & 0x01;
UINT8 b_bit = (offs >> 0) & 0x01;
UINT8 r = bitmap_weight[r_bit];
UINT8 g = bitmap_weight[g_bit];
UINT8 b = bitmap_weight[b_bit];
pens[NUM_CHARMAP_PENS + offs] = MAKE_RGB(r, g, b);
}
/* background color */
pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS] = MAKE_RGB(back_r_weight[0], back_gb_weight[0], back_gb_weight[0]);
}
VIDEO_UPDATE( redalert )
/*************************************
*
* Video hardware start
*
*************************************/
static VIDEO_START( redalert )
{
int offs,i;
redalert_bitmap_colorram = auto_malloc(0x0400);
/* for every character in the Video RAM */
for (offs = videoram_size - 1;offs >= 0;offs--)
state_save_register_global_pointer(redalert_bitmap_colorram, 0x0400);
}
/*************************************
*
* Video update
*
*************************************/
static VIDEO_UPDATE( redalert )
{
pen_t pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS + 1];
offs_t offs;
get_pens(pens);
for (offs = 0; offs < 0x2000; offs++)
{
int charcode;
int stat_transparent;
int sx,sy,color;
int i;
UINT8 charmap_data_1;
UINT8 charmap_data_2;
charcode = videoram[offs];
UINT8 y = offs & 0xff;
UINT8 x = (~offs >> 8) << 3;
/* decode modified background */
if (redalert_dirtyback[offs] == 1)
UINT8 bitmap_data = redalert_bitmap_videoram[offs];
UINT8 bitmap_color = redalert_bitmap_colorram[offs >> 3];
UINT8 charmap_code = redalert_charmap_videoram[offs >> 3];
offs_t charmap_data_base = ((charmap_code & 0x7f) << 3) | (offs & 0x07);
/* D7 of the char code selects the char set to use */
if (charmap_code & 0x80)
{
decodechar(machine->gfx[0],offs,redalert_backram);
redalert_dirtyback[offs] = 2;
charmap_data_1 = redalert_charmap_videoram[0x0400 | charmap_data_base];
charmap_data_2 = redalert_charmap_videoram[0x0c00 | charmap_data_base];
}
else
{
charmap_data_1 = 0; /* effectively disables A0 of the color PROM */
charmap_data_2 = redalert_charmap_videoram[0x0800 | charmap_data_base];
}
/* decode modified characters */
if (redalert_dirtycharacter[charcode] == 1)
for (i = 0; i < 8; i++)
{
if (charcode < 0x80)
decodechar(machine->gfx[1],charcode,redalert_characterram);
pen_t pen;
int bitmap_bit = bitmap_data & 0x80;
UINT8 color_prom_a0_a1 = ((charmap_data_2 & 0x80) >> 6) | ((charmap_data_1 & 0x80) >> 7);
/* determine priority */
if ((color_prom_a0_a1 == 0) || (bitmap_bit && ((charmap_code & 0xc0) == 0xc0)))
pen = bitmap_bit ? pens[NUM_CHARMAP_PENS + bitmap_color] : pens[NUM_CHARMAP_PENS + NUM_BITMAP_PENS];
else
decodechar(machine->gfx[2],charcode-0x80,redalert_spriteram1);
redalert_dirtycharacter[charcode] = 2;
}
pen = pens[((charmap_code & 0xfe) << 1) | color_prom_a0_a1];
if (redalert_dirtycharacter2[charcode] == 1)
{
decodechar(machine->gfx[3],charcode-0x80,redalert_spriteram3);
redalert_dirtycharacter2[charcode] = 2;
}
if (*redalert_video_control & 0x04)
*BITMAP_ADDR32(bitmap, y, x) = pen;
else
*BITMAP_ADDR32(bitmap, y ^ 0xff, x ^ 0xff) = pen;
sx = 31 - offs / 32;
sy = offs % 32;
stat_transparent = TRANSPARENCY_NONE;
/* First layer of color */
if (charcode >= 0xC0)
{
stat_transparent = TRANSPARENCY_COLOR;
color = color_lookup[charcode];
drawgfx(tmpbitmap,machine->gfx[2],
charcode-0x80,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,TRANSPARENCY_NONE,0);
if( redalert_dirtycharacter2[charcode] != 0 )
drawgfx(tmpbitmap,machine->gfx[3],
charcode-0x80,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,TRANSPARENCY_COLOR,0);
}
/* Second layer - background */
color = redalert_backcolor[offs];
drawgfx(tmpbitmap,machine->gfx[0],
offs,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,stat_transparent,0);
/* Third layer - alphanumerics & sprites */
if (charcode < 0x80)
{
color = color_lookup[charcode];
drawgfx(tmpbitmap,machine->gfx[1],
charcode,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,TRANSPARENCY_COLOR,0);
}
else if (charcode < 0xC0)
{
color = color_lookup[charcode];
drawgfx(tmpbitmap,machine->gfx[2],
charcode-0x80,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,TRANSPARENCY_COLOR,0);
if( redalert_dirtycharacter2[charcode] != 0 )
drawgfx(tmpbitmap,machine->gfx[3],
charcode-0x80,
color,
0,0,
8*sx,8*sy,
&machine->screen[0].visarea,TRANSPARENCY_COLOR,0);
/* next pixel */
x = x + 1;
bitmap_data = bitmap_data << 1;
charmap_data_1 = charmap_data_1 << 1;
charmap_data_2 = charmap_data_2 << 1;
}
}
for (i = 0;i < 256;i++)
{
if (redalert_dirtycharacter[i] == 2)
redalert_dirtycharacter[i] = 0;
if (redalert_dirtycharacter2[i] == 2)
redalert_dirtycharacter2[i] = 0;
}
for (i = 0;i < 0x400;i++)
{
if (redalert_dirtyback[i] == 2)
redalert_dirtyback[i] = 0;
}
/* copy the character mapped graphics */
copybitmap(bitmap,tmpbitmap,flip,flip,0,0,cliprect,TRANSPARENCY_NONE,0);
return 0;
}
/*************************************
*
* Machine driver
*
*************************************/
MACHINE_DRIVER_START( redalert_video )
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION)
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
MDRV_VIDEO_START(redalert)
MDRV_VIDEO_UPDATE(redalert)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 1*8, 31*8-1)
MACHINE_DRIVER_END