📄 cabal.c
字号:
/******************************************************************
Cabal Bootleg
(c)1998 Red Corp
68000 + Z80
The original uses 2xYM3931 for sound
The bootleg uses YM2151 + 2xZ80 used as ADPCM players
MEMORY MAP
0x000000 - 0x03ffff ROM
0x040000 - 0x0437ff RAM
0x043800 - 0x0437ff VRAM (Sprites)
0x060000 - 0x0607ff VRAM (Tiles)
0x080000 - 0x0803ff VRAM (Background)
0x0A0000 - 0xA0000f Input Ports
0x0C0040 - 0x0c0040 Watchdog??
0x0C0080 - 0x0C0080 Watchdog??
0x0E0000 - 0x0E07ff COLORRAM (----BBBBGGGGRRRR)
0x0E8000 - 0x0E800f Output Ports/Input Ports
VRAM(Background)
0x80000 - 32 bytes (16 tiles)
0x80040 - 32 bytes (16 tiles)
0x80080 - 32 bytes (16 tiles)
0x800c0 - 32 bytes (16 tiles)
0x80100 - 32 bytes (16 tiles)
...
0x803c0 - 32 bytes (16 tiles)
VRAM(Tiles)
0x60000-0x607ff (1024 tiles 8x8 tiles, 2 bytes every tile)
VRAM(Sprites)
0x43800-0x43bff (128 sprites, 8 bytes every sprite)
COLORRAM(Colors)
0xe0000-0xe07ff (1024 colors, ----BBBBGGGGRRRR)
******************************************************************/
#include "driver.h"
#include "vidhrdw/generic.h"
#include "z80/z80.h"
static int cabal_sound_command1, cabal_sound_command2;
extern void cabal_vh_screenrefresh( struct osd_bitmap *bitmap, int fullrefresh );
static void cabal_init_machine( void ) {
cabal_sound_command1 = cabal_sound_command2 = 0xff;
}
static int cabal_background_r( int offset ){
return READ_WORD (&videoram[offset]);
}
static void cabal_background_w( int offset, int data ){
int oldword = READ_WORD(&videoram[offset]);
int newword = COMBINE_WORD(oldword,data);
if( oldword != newword ){
WRITE_WORD(&videoram[offset],newword);
dirtybuffer[offset/2] = 1;
}
}
/******************************************************************************************/
static struct YM2151interface ym2151_interface =
{
1, /* 1 chip */
3579580, /* 3.58 MHZ ? */ /* 4 MHZ in raine */
{ 80 },
{ 0 }
};
struct ADPCMinterface adpcm_interface =
{
2, /* total number of ADPCM decoders in the machine */
8000, /* playback frequency */
3, /* memory region where the samples come from */
0, /* initialization function */
{40,40}
};
static void cabal_play_adpcm( int channel, int which ){
if( which!=0xff ){
unsigned char *RAM = Machine->memory_region[3];
int offset = channel*0x10000;
int start, len;
which = which&0x7f;
if( which ){
which = which*2+0x100;
start = RAM[offset+which] + 256*RAM[offset+which+1];
len = (RAM[offset+start]*256 + RAM[offset+start+1])*2;
start+=2;
ADPCM_play( channel,offset+start,len );
}
}
}
static int cabal_coin_r( int offset ) {
static int coin = 0;
int val = readinputport( 3 );
if ( !( val & 0x04 ) ){
if ( coin == 0 ){
coin = 1;
return val;
}
} else {
coin = 0;
}
return val | 0x04;
}
static int cabal_io_r( int offset ) {
// if( errorlog ) fprintf( errorlog, "INPUT a000[%02x] \n", offset);
switch (offset){
case 0x0: return readinputport(4) + (readinputport(5)<<8); /* DIPSW */
case 0x8: return 0xff + (readinputport(0)<<8);/* IN0 */
case 0x10: return readinputport(1) + (readinputport(2)<<8); /* IN1,IN2 */
default: return (0xffff);
}
}
static void cabal_snd_w( int offset,int data ) {
switch (offset) {
case 0x0:
cabal_sound_command1 = data;
cpu_cause_interrupt( 1, Z80_NMI_INT );
break;
case 0x2: /* ?? */
cabal_sound_command2 = data & 0xff;
break;
case 0x8: /* ?? */
break;
}
}
static struct MemoryReadAddress readmem_cpu[] = {
{ 0x00000, 0x3ffff, MRA_ROM },
{ 0x40000, 0x437ff, MRA_RAM },
{ 0x43c00, 0x4ffff, MRA_RAM },
{ 0x43800, 0x43bff, MRA_RAM, &spriteram, &spriteram_size },
{ 0x60000, 0x607ff, MRA_BANK1,&colorram }, /* text layer */
{ 0x80000, 0x801ff, cabal_background_r, &videoram, &videoram_size }, /* background layer */
{ 0x80200, 0x803ff, MRA_BANK2 },
{ 0xa0000, 0xa0012, cabal_io_r },
{ 0xe0000, 0xe07ff, paletteram_word_r },
{ 0xe8000, 0xe800f, cabal_coin_r },
{ -1 }
};
static struct MemoryWriteAddress writemem_cpu[] = {
{ 0x00000, 0x3ffff, MWA_ROM },
{ 0x40000, 0x43bff, MWA_RAM },
{ 0x43c00, 0x4ffff, MWA_RAM },
{ 0x60000, 0x607ff, MWA_BANK1 },
{ 0x80000, 0x801ff, cabal_background_w },
{ 0x80200, 0x803ff, MWA_BANK2 },
{ 0xc0040, 0xc0041, MWA_NOP }, /* ??? */
{ 0xc0080, 0xc0081, MWA_NOP }, /* ??? */
{ 0xe0000, 0xe07ff, paletteram_xxxxBBBBGGGGRRRR_word_w, &paletteram},
{ 0xe8000, 0xe800f, cabal_snd_w },
{ -1 }
};
/*********************************************************************/
int cabal_snd_read(int offset){
switch(offset){
case 0x08: return cabal_sound_command2;
case 0x0a: return cabal_sound_command1;
default: return(0xff);
}
}
void cabal_snd_write(int offset,int data){
switch( offset ){
case 0x00: cabal_play_adpcm( 0, data ); break;
case 0x02: cabal_play_adpcm( 1, data ); break;
}
}
static struct MemoryReadAddress readmem_sound[] =
{
{ 0x0000, 0x1fff, MRA_ROM },
{ 0x2000, 0x2fff, MRA_RAM },
{ 0x4000, 0x400d, cabal_snd_read },
{ 0x400f, 0x400f, YM2151_status_port_0_r },
{ 0x8000, 0xffff, MRA_ROM },
{ -1 }
};
static struct MemoryWriteAddress writemem_sound[] =
{
{ 0x0000, 0x1fff, MWA_ROM },
{ 0x2000, 0x2fff, MWA_RAM },
{ 0x4000, 0x400d, cabal_snd_write },
{ 0x400e, 0x400e, YM2151_register_port_0_w },
{ 0x400f, 0x400f, YM2151_data_port_0_w },
{ 0x6000, 0x6000, MWA_NOP }, /*???*/
{ 0x8000, 0xffff, MWA_ROM },
{ -1 }
};
static struct MemoryReadAddress cabalbl_readmem_sound[] =
{
{ 0x0000, 0x1fff, MRA_ROM },
{ 0x2000, 0x2fff, MRA_RAM },
{ 0x4000, 0x400d, cabal_snd_read },
{ 0x400f, 0x400f, YM2151_status_port_0_r },
{ 0x8000, 0xffff, MRA_ROM },
{ -1 }
};
static struct MemoryWriteAddress cabalbl_writemem_sound[] =
{
{ 0x0000, 0x1fff, MWA_ROM },
{ 0x2000, 0x2fff, MWA_RAM },
{ 0x4000, 0x400d, cabal_snd_write },
{ 0x400e, 0x400e, YM2151_register_port_0_w },
{ 0x400f, 0x400f, YM2151_data_port_0_w },
{ 0x6000, 0x6000, MWA_NOP }, /*???*/
{ 0x8000, 0xffff, MWA_ROM },
{ -1 }
};
/* ADPCM CPU (common) */
static struct MemoryReadAddress cabalbl_readmem_adpcm[] = {
{ 0x0000, 0xffff, MRA_ROM },
{ -1 }
};
static struct MemoryWriteAddress cabalbl_writemem_adpcm[] = {
{ 0x0000, 0xffff, MWA_NOP },
{ -1 }
};
/***************************************************************************/
INPUT_PORTS_START( input_ports )
PORT_START /* IN0 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_8WAY)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_8WAY)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_8WAY)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_8WAY | IPF_PLAYER2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_8WAY | IPF_PLAYER2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_8WAY | IPF_PLAYER2 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY | IPF_PLAYER2 )
PORT_START /* IN1 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START /* IN2 */
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )
PORT_START /* IN3 */
PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START /* DIPSW1 */
PORT_DIPNAME( 0x0f, 0x0e, DEF_STR( Coinage ), IP_KEY_NONE )
PORT_DIPSETTING( 0x0a, DEF_STR( 3C_1C ) )
PORT_DIPSETTING( 0x0b, "3 Coins/1 Credit 5/2" )
PORT_DIPSETTING( 0x0c, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x0d, "2 Coins/1 Credit 3/2" )
PORT_DIPSETTING( 0x01, DEF_STR( 4C_3C ) )
PORT_DIPSETTING( 0x0e, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x03, "2 Coins/2 Credits 3/4" )
PORT_DIPSETTING( 0x02, "3 Coins/3 credits" )
PORT_DIPSETTING( 0x0f, DEF_STR( 1C_2C ) )
PORT_DIPSETTING( 0x04, DEF_STR( 1C_3C ) )
PORT_DIPSETTING( 0x09, DEF_STR( 1C_4C ) )
PORT_DIPSETTING( 0x08, DEF_STR( 1C_6C ) )
PORT_DIPSETTING( 0x07, DEF_STR( 1C_8C ) )
PORT_DIPSETTING( 0x06, "1 Coin/10 Credits" )
PORT_DIPSETTING( 0x05, "1 Coin/12 Credits" )
PORT_DIPSETTING( 0x00, "Free 99 Credits" )
/* 0x10 is different from the Free 99 Credits.
When you start the game the credits decrease using the Free 99,
while they stay at 99 using the 0x10 dip. */
PORT_DIPNAME( 0x10, 0x10, DEF_STR( Free_Play ), IP_KEY_NONE )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x20, 0x20, "Invert Buttons", IP_KEY_NONE )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ), IP_KEY_NONE )
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x80, 0x80, "Trackball", IP_KEY_NONE )
PORT_DIPSETTING( 0x80, "Small" )
PORT_DIPSETTING( 0x00, "Large" )
PORT_START /* DIPSW2 */
PORT_DIPNAME( 0x03, 0x03, DEF_STR( Lives ), IP_KEY_NONE )
PORT_DIPSETTING( 0x02, "2" )
PORT_DIPSETTING( 0x03, "3" )
PORT_DIPSETTING( 0x01, "5" )
PORT_BITX( 0, 0x00, IPT_DIPSWITCH_SETTING | IPF_CHEAT, "Infinite", IP_KEY_NONE, IP_JOY_NONE, 0 )
PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Bonus_Life ), IP_KEY_NONE )
PORT_DIPSETTING( 0x0c, "20k 50k" )
PORT_DIPSETTING( 0x08, "30k 100k" )
PORT_DIPSETTING( 0x04, "50k 150k" )
PORT_DIPSETTING( 0x00, "70K" )
PORT_DIPNAME( 0x30, 0x30, DEF_STR( Difficulty ), IP_KEY_NONE )
PORT_DIPSETTING( 0x30, "Easy" )
PORT_DIPSETTING( 0x20, "Normal" )
PORT_DIPSETTING( 0x10, "Hard" )
PORT_DIPSETTING( 0x00, "Very Hard" )
PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ), IP_KEY_NONE )
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -