📄 blockade.c
字号:
/****************************************************************************
Blockade/Comotion/Blasto/Hustle Memory MAP
Frank Palazzolo (palazzol@home.com)
CPU - Intel 8080A
Memory Address (Upper/Lower)
0xxx 00aa aaaa aaaa ROM U2/U3 R 1K for Blockade/Comotion/Blasto
0xxx 01aa aaaa aaaa ROM U4/U5 R 1K for Comotion/Blasto/Hustle Only
xxx1 xxxx aaaa aaaa RAM R/W 256 bytes
1xx0 xxaa aaaa aaaa VRAM 1K playfield
CHAR ROM U29/U43 256 bytes for Blockade/Comotion
512 for Blasto/Hustle
Ports In Out
1 Controls bit 7 = Coin Latch Reset
bit 5 = Pin 19?
2 Controls Square Wave Pitch Register
4 Controls Noise On
8 N/A Noise Off
Notes: Support is complete with the exception of the square wave generator
and noise generator. I have not created a sample for the noise
generator, but any BOOM sound as a sample will do for now for
Blockade & Comotion, at least.
****************************************************************************/
#include "driver.h"
#include "vidhrdw/generic.h"
/* #define BLOCKADE_LOG 1 */
/* in vidhrdw */
void blockade_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
void comotion_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
void blasto_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
void hustle_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
void blockade_coin_latch_w(int offset, int data);
void blockade_sound_freq_w(int offset, int data);
void blockade_env_on_w(int offset, int data);
void blockade_env_off_w(int offset, int data);
/* These are used to simulate coin latch circuitry */
static int coin_latch; /* Active Low */
static int just_been_reset;
void blockade_init(void)
{
int i;
/* Merge nibble-wide roms together,
and load them into 0x0000-0x0400 */
for(i=0;i<0x0400;i++)
{
ROM[0x0000+i] = (ROM[0x1000+i]<<4)+ROM[0x1400+i];
}
/* Initialize the coin latch state here */
coin_latch = 1;
just_been_reset = 0;
}
void comotion_init(void)
{
int i;
/* Merge nibble-wide roms together,
and load them into 0x0000-0x0800 */
for(i=0;i<0x0400;i++)
{
ROM[0x0000+i] = (ROM[0x1000+i]<<4)+ROM[0x1400+i];
ROM[0x0400+i] = (ROM[0x1800+i]<<4)+ROM[0x1c00+i];
}
/* They also need to show up here for comotion/blasto */
for(i=0;i<2048;i++)
{
ROM[0x4000+i] = ROM[0x0000+i];
}
/* Initialize the coin latch state here */
coin_latch = 1;
just_been_reset = 0;
}
/*************************************************************/
/* */
/* Inserting a coin should work like this: */
/* 1) Reset the CPU */
/* 2) CPU Sets the coin latch */
/* 3) Finally the CPU coin latch is Cleared by the hardware */
/* (by the falling coin..?) */
/* */
/* I am faking this by keeping the CPU from Setting */
/* the coin latch if we have just been reset. */
/* */
/*************************************************************/
/* Need to check for a coin on the interrupt, */
/* This will reset the cpu */
int blockade_interrupt(void)
{
/* release the cpu in case it's been halted */
timer_suspendcpu(0, 0);
if ((input_port_0_r(0) & 0x80) == 0)
{
just_been_reset = 1;
cpu_reset(0);
}
return ignore_interrupt();
}
int blockade_input_port_0_r(int offset)
{
/* coin latch is bit 7 */
int temp = (input_port_0_r(0)&0x7f);
return (coin_latch<<7) | (temp);
}
void blockade_coin_latch_w(int offset, int data)
{
if (data & 0x80)
{
#ifdef BLOCKADE_LOG
printf("Reset Coin Latch\n");
#endif
if (just_been_reset)
{
just_been_reset = 0;
coin_latch = 0;
}
else
coin_latch = 1;
}
if (data & 0x20)
{
#ifdef BLOCKADE_LOG
printf("Pin 19 High\n");
#endif
}
else
{
#ifdef BLOCKADE_LOG
printf("Pin 19 Low\n");
#endif
}
return;
}
void blockade_sound_freq_w(int offset, int data)
{
#ifdef BLOCKADE_LOG
printf("Sound Freq Write: %d\n",data);
#endif
return;
}
void blockade_env_on_w(int offset, int data)
{
#ifdef BLOCKADE_LOG
printf("Boom Start\n");
#endif
sample_start(0,0,0);
return;
}
void blockade_env_off_w(int offset, int data)
{
#ifdef BLOCKADE_LOG
printf("Boom End\n");
#endif
return;
}
static void blockade_videoram_w(int offset, int data)
{
videoram_w(offset, data);
if (input_port_3_r(0) & 0x80)
{
cpu_spinuntil_int();
}
}
static struct MemoryReadAddress readmem[] =
{
{ 0x0000, 0x07ff, MRA_ROM },
{ 0x4000, 0x47ff, MRA_ROM }, /* same image */
{ 0xe000, 0xe3ff, videoram_r, &videoram, &videoram_size },
{ 0xff00, 0xffff, MRA_RAM },
{ -1 } /* end of table */
};
static struct MemoryWriteAddress writemem[] =
{
{ 0x0000, 0x07ff, MWA_ROM },
{ 0x4000, 0x47ff, MWA_ROM }, /* same image */
{ 0xe000, 0xe3ff, blockade_videoram_w, &videoram, &videoram_size },
{ 0xff00, 0xffff, MWA_RAM },
{ -1 } /* end of table */
};
static struct IOReadPort readport[] =
{
{ 0x01, 0x01, blockade_input_port_0_r },
{ 0x02, 0x02, input_port_1_r },
{ 0x04, 0x04, input_port_2_r },
{ -1 } /* end of table */
};
static struct IOWritePort writeport[] =
{
{ 0x01, 0x01, blockade_coin_latch_w },
{ 0x02, 0x02, blockade_sound_freq_w },
{ 0x04, 0x04, blockade_env_on_w },
{ 0x08, 0x08, blockade_env_off_w },
{ -1 } /* end of table */
};
/* These are not dip switches, they are mapped to */
/* connectors on the board. Different games had */
/* different harnesses which plugged in here, and */
/* some pins were unused. */
INPUT_PORTS_START( blockade_input_ports )
PORT_START /* IN0 */
PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_COIN1 | IPF_IMPULSE,
"Coin", IP_KEY_DEFAULT, IP_JOY_DEFAULT, 1 )
/* this is really used for the coin latch, */
/* see blockade_interrupt() */
PORT_DIPNAME ( 0x70, 0x70, "Lives", IP_KEY_NONE )
PORT_DIPSETTING ( 0x70, "6 Crashes" )
PORT_DIPSETTING ( 0x30, "5 Crashes" )
PORT_DIPSETTING ( 0x50, "4 Crashes" )
PORT_DIPSETTING ( 0x60, "3 Crashes" )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_DIPNAME ( 0x04, 0x04, "Boom Switch", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "Off" )
PORT_DIPSETTING ( 0x04, "On" )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START /* IN1 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER2 )
PORT_START /* IN2 */
PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START /* IN3 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_VBLANK )
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
INPUT_PORTS_START( comotion_input_ports )
PORT_START /* IN0 */
PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_COIN1 | IPF_IMPULSE,
"Coin", IP_KEY_DEFAULT, IP_JOY_DEFAULT, 1 )
/* this is really used for the coin latch, */
/* see blockade_interrupt() */
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
PORT_DIPNAME( 0x08, 0x08, "Lives", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "3 Crashes" )
PORT_DIPSETTING ( 0x08, "4 Crashes" )
PORT_DIPNAME ( 0x04, 0x04, "Boom Switch", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "Off" )
PORT_DIPSETTING ( 0x04, "On" )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START /* IN1 */
/* Right Player */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER2 )
PORT_START /* IN2 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER3 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER3 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER3 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER3 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER4 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER4 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER4 )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER4 )
PORT_START /* IN3 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_VBLANK )
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
INPUT_PORTS_START( blasto_input_ports )
PORT_START /* IN0 */
PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_COIN1 | IPF_IMPULSE,
"Coin", IP_KEY_DEFAULT, IP_JOY_DEFAULT, 1 )
/* this is really used for the coin latch, */
/* see blockade_interrupt() */
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_DIPNAME ( 0x08, 0x08, "Game Time", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "70 Secs" )
PORT_DIPSETTING ( 0x08, "90 Secs" )
PORT_DIPNAME ( 0x04, 0x04, "Boom Switch", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "Off" )
PORT_DIPSETTING ( 0x04, "On" )
PORT_DIPNAME ( 0x03, 0x03, "Coins", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "4 Coins" )
PORT_DIPSETTING ( 0x01, "3 Coins" )
PORT_DIPSETTING ( 0x02, "2 Coins" )
PORT_DIPSETTING ( 0x03, "1 Coin" )
PORT_START /* IN1 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_START /* IN2 */
/* Right Player */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP | IPF_4WAY )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT | IPF_4WAY )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN | IPF_4WAY )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT | IPF_4WAY )
/* Left Player */
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP | IPF_4WAY )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_4WAY )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN | IPF_4WAY )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_4WAY )
PORT_START /* IN3 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_VBLANK )
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
INPUT_PORTS_START( hustle_input_ports )
PORT_START /* IN0 */
PORT_BITX(0x80, IP_ACTIVE_LOW, IPT_COIN1 | IPF_IMPULSE,
"Coin", IP_KEY_DEFAULT, IP_JOY_DEFAULT, 1 )
/* this is really used for the coin latch, */
/* see blockade_interrupt() */
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_DIPNAME ( 0x04, 0x04, "Game Time", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "1.5 mins" )
PORT_DIPSETTING ( 0x04, "2 mins" )
PORT_DIPNAME ( 0x03, 0x03, "Coins", IP_KEY_NONE )
PORT_DIPSETTING ( 0x00, "4 Coins" )
PORT_DIPSETTING ( 0x01, "3 Coins" )
PORT_DIPSETTING ( 0x02, "2 Coins" )
PORT_DIPSETTING ( 0x03, "1 Coin" )
PORT_START /* IN1 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER2 )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER2 )
PORT_START /* IN2 */
PORT_DIPNAME ( 0xf1, 0xf0, "Free Game", IP_KEY_NONE )
PORT_DIPSETTING ( 0x71, "11000" )
PORT_DIPSETTING ( 0xb1, "13000" )
PORT_DIPSETTING ( 0xd1, "15000" )
PORT_DIPSETTING ( 0xe1, "17000" )
PORT_DIPSETTING ( 0xf0, "Disabled" )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START /* IN3 */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_VBLANK )
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -