📄 pang.c
字号:
/***************************************************************************
Pang (Mitchell Corp) / Buster Bros (Capcom)
Super Pang (Mitchell Corp)
Block Block (Capcom)
Driver submitted by Paul Leaman
Processor:
1xZ80 (40006psc)
Sound:
1xOKIM6295 (9Z002 VI) ADPCM chip
1xYM2413 FM Chip
***************************************************************************/
#include "driver.h"
#include "vidhrdw/generic.h"
/* in machine/kabuki.c */
void bbros_decode(void);
void spang_decode(void);
void block_decode(void);
int pang_vh_start(void);
void pang_vh_stop(void);
void pang_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
void pang_video_bank_w(int offset, int data);
void pang_videoram_w(int offset, int data);
int pang_videoram_r(int offset);
void pang_colorram_w(int offset, int data);
int pang_colorram_r(int offset);
void pang_palette_bank_w(int offset, int data);
void pang_paletteram_w(int offset, int data);
int pang_paletteram_r(int offset);
extern unsigned char *pang_videoram;
extern unsigned char *pang_colorram;
extern int pang_videoram_size;
extern int pang_colorram_size;
static int dial[2],dial_selected;
static void init_machine(void)
{
/* start with the dial disabled, it will be enabled only for Block Block */
dial_selected = 0;
}
int block_input_r(int offset)
{
if (dial_selected)
{
static int dir[2];
if (dial_selected == 1)
{
int delta;
delta = (readinputport(4 + offset) - dial[offset]) & 0xff;
if (delta & 0x80)
{
delta = (-delta) & 0xff;
if (dir[offset])
{
/* don't report movement on a direction change,otherwise it will stutter */
dir[offset] = 0;
delta = 0;
}
}
else if (delta > 0)
{
if (dir[offset] == 0)
{
/* don't report movement on a direction change,otherwise it will stutter */
dir[offset] = 1;
delta = 0;
}
}
if (delta > 0x3f) delta = 0x3f;
return delta << 2;
}
else
{
int res;
res = readinputport(1 + offset) & 0xf7;
if (dir[offset]) res |= 0x08;
return res;
}
}
else
return readinputport(1 + offset);
}
void block_dial_control_w(int offset,int data)
{
if (data == 0x08)
{
/* reset the dial counters */
dial[0] = readinputport(4);
dial[1] = readinputport(5);
}
else if (data == 0x80)
dial_selected = -1;
else
dial_selected = 1;
}
/***************************************************************************
EEPROM
***************************************************************************/
static int eeprom_serial_count,eeprom_serial_buffer[26];
static UINT16 eeprom_data[0x40],eeprom_data_bits;
static int pang_port_5_r(int offset)
{
int bit;
bit = (eeprom_data_bits & 0x8000) >> 8;
eeprom_data_bits = (eeprom_data_bits << 1) | 1;
return (input_port_3_r(0) & 0x7f) | bit;
}
static void pang_eeprom_start_w(int offset,int data)
{
static int last;
if (!data && last) eeprom_serial_count = 0;
last = data;
}
static void pang_eeprom_serial_w(int offset,int data)
{
if (eeprom_serial_count < 26)
{
eeprom_serial_buffer[eeprom_serial_count++] = data;
if (eeprom_serial_count == 10)
{
if (eeprom_serial_buffer[0] == 0x00 &&
eeprom_serial_buffer[1] == 0xff &&
eeprom_serial_buffer[2] == 0xff &&
eeprom_serial_buffer[3] == 0x00)
{
int i,address;
address = 0;
for (i = 4;i < 10;i++)
{
address <<= 1;
if (eeprom_serial_buffer[i]) address |= 1;
}
eeprom_data_bits = eeprom_data[address];
}
}
else if (eeprom_serial_count == 26)
{
if (eeprom_serial_buffer[0] == 0x00 &&
eeprom_serial_buffer[1] == 0xff &&
eeprom_serial_buffer[2] == 0x00 &&
eeprom_serial_buffer[3] == 0xff)
{
int i,address,edata;
address = 0;
for (i = 4;i < 10;i++)
{
address <<= 1;
if (eeprom_serial_buffer[i]) address |= 1;
}
edata = 0;
for (i = 10;i < 26;i++)
{
edata <<= 1;
if (eeprom_serial_buffer[i]) edata |= 1;
}
eeprom_data[address] = edata;
}
}
}
}
static int nvram_load(void)
{
void *f;
/* Try loading static RAM */
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0)
{
osd_fread_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fclose(f);
}
/* Invalidate the static RAM to force reset to factory settings */
else memset(eeprom_data,0xff,0x80);
return 1;
}
static void nvram_save(void)
{
void *f;
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,1)) != 0)
{
osd_fwrite_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fclose(f);
}
}
static int spang_nvram_load(void)
{
void *f;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
/* Try loading static RAM */
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0)
{
osd_fread_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fread(f,&RAM[0xe000],0x80); /* NVRAM */
osd_fclose(f);
}
/* Invalidate the static RAM to force reset to factory settings */
else memset(eeprom_data,0xff,0x80);
return 1;
}
static void spang_nvram_save(void)
{
void *f;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,1)) != 0)
{
osd_fwrite_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fwrite(f,&RAM[0xe000],0x80); /* NVRAM */
osd_fclose(f);
}
}
static int block_nvram_load(void)
{
void *f;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
/* Try loading static RAM */
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0)
{
osd_fread_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fread(f,&RAM[0xff80],0x80); /* NVRAM */
osd_fclose(f);
}
/* Invalidate the static RAM to force reset to factory settings */
else memset(eeprom_data,0xff,0x80);
return 1;
}
static void block_nvram_save(void)
{
void *f;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,1)) != 0)
{
osd_fwrite_msbfirst(f,eeprom_data,0x80); /* EEPROM */
osd_fwrite(f,&RAM[0xff80],0x80); /* NVRAM */
osd_fclose(f);
}
}
/***************************************************************************
Horrible bankswitch routine. Need to be able to read decrypted opcodes
from ROM. There must be a better way than this.
***************************************************************************/
static void pang_bankswitch_w(int offset,int data)
{
static int olddata=-1;
if (data != olddata)
{
int bankaddress;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
bankaddress = 0x10000 + (data & 0x0f) * 0x4000;
memcpy(ROM+0x8000, ROM+bankaddress, 0x4000);
memcpy(RAM+0x8000, RAM+bankaddress, 0x4000);
olddata=data;
}
}
/***************************************************************************
Memory handlers
***************************************************************************/
static struct MemoryReadAddress readmem[] =
{
{ 0x0000, 0xbfff, MRA_ROM },
{ 0xc000, 0xc7ff, pang_paletteram_r }, /* Banked palette RAM */
{ 0xc800, 0xcfff, pang_colorram_r }, /* Attribute RAM */
{ 0xd000, 0xdfff, pang_videoram_r }, /* Banked char / OBJ RAM */
{ 0xe000, 0xffff, MRA_RAM }, /* Work RAM */
{ -1 } /* end of table */
};
static struct MemoryWriteAddress writemem[] =
{
{ 0x0000, 0xbfff, MWA_ROM },
{ 0xc000, 0xc7ff, pang_paletteram_w },
{ 0xc800, 0xcfff, pang_colorram_w, &pang_colorram, &pang_colorram_size },
{ 0xd000, 0xdfff, pang_videoram_w, &pang_videoram, &pang_videoram_size },
{ 0xe000, 0xffff, MWA_RAMROM },
{ -1 } /* end of table */
};
static struct IOReadPort readport[] =
{
{ 0x00, 0x00, input_port_0_r },
{ 0x01, 0x02, block_input_r },
{ 0x05, 0x05, pang_port_5_r },
{ -1 } /* end of table */
};
static struct IOWritePort writeport[] =
{
{ 0x00, 0x00, pang_palette_bank_w }, /* Palette bank */
{ 0x01, 0x01, block_dial_control_w },
{ 0x02, 0x02, pang_bankswitch_w }, /* Code bank register */
{ 0x03, 0x03, YM2413_data_port_0_w },
{ 0x04, 0x04, YM2413_register_port_0_w },
{ 0x05, 0x05, OKIM6295_data_w },
{ 0x06, 0x06, MWA_NOP }, /* Watchdog ? */
{ 0x07, 0x07, pang_video_bank_w }, /* Video RAM bank register */
{ 0x08, 0x08, pang_eeprom_start_w },
{ 0x10, 0x10, MWA_NOP }, /* clocks the EEPROM, I think */
{ 0x18, 0x18, pang_eeprom_serial_w },
{ -1 } /* end of table */
};
INPUT_PORTS_START( pang_input_ports )
PORT_START /* IN0 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_START /* IN1 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_8WAY )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_8WAY )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_8WAY )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_8WAY )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -