📄 dec8.c
字号:
/***************************************************************************
Various Data East 8 bit games:
Cobra Command (c) 1988 Data East Corporation (6809)
The Real Ghostbusters (2p) (c) 1987 Data East USA (6809 + I8751)
The Real Ghostbusters (3p) (c) 1987 Data East USA (6809 + I8751)
Mazehunter (c) 1987 Data East Corporation (6809 + I8751)
Super Real Darwin (c) 1987 Data East Corporation (6809 + I8751)
Psycho-Nics Oscar (c) 1988 Data East USA (2*6809 + I8751)
Psycho-Nics Oscar (Japan) (c) 1987 Data East Corporation (2*6809 + I8751)
Gondomania (c) 1987 Data East USA (6809 + I8751)
Mekyo Sensi (c) 1987 Data East Corporation (6809 + I8751)
Last Mission (rev 6) (c) 1986 Data East USA (2*6809 + I8751)
Last Mission (rev 5) (c) 1986 Data East USA (2*6809 + I8751)
Shackled (c) 1986 Data East USA (2*6809 + I8751)
Breywood (c) 1986 Data East Corporation (2*6809 + I8751)
Captain Silver (Japan) (c) 1987 Data East Corporation (2*6809 + I8751)
All games use a 6502 for sound (some are encrypted), all games except Cobracom
use an Intel 8751 for protection & coinage. For these games the coinage dip
switch is not currently supported, they are fixed at 1 coin 1 credit.
Emulation by Bryan McPhail, mish@tendril.force9.net
Recent fixes:
Ghostbusters kludge removed
Priority added to Oscar
Oscar speed fixed.
SRD fixed
New games added
To do:
Slight graphics glitches in Captain Silver, Breywood, Shackled.
Weird cpu race condition in Last Mission.
Support coinage options for all i8751 emulations.
Captain Silver/Cobra Command probably have some sprite/playfield priorities
Wrong sprite colours in Super Real Darwin
Cobra Command probably has missing graphics later on in the game.
Dips needed to be worked on several games
Emulation Notes:
* Dip switches confirmed for Oscar, Ghostbusters & Gondomania, the others seem reasonable.
* Maze Hunter is using Ghostbusters colour proms for now...
* Breywood sprites are not currently dumped, a Breywood Rev 2 rom set is known
to exist..
***************************************************************************/
#include "driver.h"
#include "vidhrdw/generic.h"
#include "M6809/m6809.h"
#include "M6502/m6502.h"
int dec8_video_r(int offset);
void dec8_video_w(int offset, int data);
void dec8_pf1_w(int offset, int data);
void dec8_pf2_w(int offset, int data);
void dec8_scroll1_w(int offset, int data);
void dec8_scroll2_w(int offset, int data);
void dec8_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void ghostb_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void srdarwin_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void gondo_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void lastmiss_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void oscar_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
int dec8_vh_start(void);
void dec8_vh_stop(void);
void srdarwin_control_w(int offset, int data);
void gondo_scroll_w(int offset, int data);
void lastmiss_control_w(int offset, int data);
void lastmiss_scrollx_w(int offset, int data);
void lastmiss_scrolly_w(int offset, int data);
void dec8_bac06_0_w(int offset, int data);
void dec8_bac06_1_w(int offset, int data);
void ghostb_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom);
/******************************************************************************/
static unsigned char *dec8_shared_ram,*dec8_shared2_ram;
extern unsigned char *dec8_row;
static int nmi_enable,int_enable;
static int i8751_return, i8751_value;
/******************************************************************************/
static int i8751_h_r(int offset)
{
return i8751_return>>8; /* MSB */
}
static int i8751_l_r(int offset)
{
return i8751_return&0xff; /* LSB */
}
static void i8751_reset_w(int offset, int data)
{
i8751_return=0;
}
/******************************************************************************/
static int gondo_player_1_r(int offset)
{
switch (offset) {
case 0: /* Rotary low byte */
return ~((1 << (readinputport(5) * 12 / 256))&0xff);
case 1: /* Joystick = bottom 4 bits, rotary = top 4 */
return ((~((1 << (readinputport(5) * 12 / 256))>>4))&0xf0) | (readinputport(0)&0xf);
}
return 0xff;
}
static int gondo_player_2_r(int offset)
{
switch (offset) {
case 0: /* Rotary low byte */
return ~((1 << (readinputport(6) * 12 / 256))&0xff);
case 1: /* Joystick = bottom 4 bits, rotary = top 4 */
return ((~((1 << (readinputport(6) * 12 / 256))>>4))&0xf0) | (readinputport(1)&0xf);
}
return 0xff;
}
/******************************************************************************/
static void ghostb_i8751_w(int offset, int data)
{
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
if (i8751_value==0x00aa) i8751_return=0x655;
if (i8751_value==0x021a) i8751_return=0x6e5; /* Ghostbusters ID */
if (i8751_value==0x021b) i8751_return=0x6e4; /* Mazehunter ID */
}
static void srdarwin_i8751_w(int offset, int data)
{
static int coins,latch;
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
if (i8751_value==0x0000) {i8751_return=0;coins=0;}
if (i8751_value==0x3063) i8751_return=0x9c; /* Protection */
if ((i8751_value&0xff00)==0x4000) i8751_return=i8751_value; /* Coinage settings */
if (i8751_value==0x5000) i8751_return=coins; /* Coin request */
if (i8751_value==0x6000) {i8751_value=-1; coins--; } /* Coin clear */
/* Nb: Command 0x4000 for setting coinage options is not supported */
if ((readinputport(1)&1)==1) latch=1;
if ((readinputport(1)&1)!=1 && latch) {coins++; latch=0;}
/* This next value is the index to a series of tables,
each table controls the end of level bad guy, wrong values crash the
cpu right away via a bogus jump.
Level number requested is in low byte, I'm assuming the
table values are stored in sequential order (ie, level 1 is the
first table, level 2 is the second, etc).
See location 0xf580 in rom dy_01.rom
A real board would be nice to check against :)
*/
if ((i8751_value&0xff00)==0x8000)
i8751_return=0xf580 + ((i8751_value&0xff)*2);
}
static void gondo_i8751_w(int offset, int data)
{
static int coin1,coin2,latch,snd;
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
if (int_enable) cpu_cause_interrupt (0, M6809_INT_IRQ); /* IRQ on *high* byte only */
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
/* Coins are controlled by the i8751 */
if ((readinputport(4)&3)==3) latch=1;
if ((readinputport(4)&1)!=1 && latch) {coin1++; snd=1; latch=0;}
if ((readinputport(4)&2)!=2 && latch) {coin2++; snd=1; latch=0;}
/* Work out return values */
if (i8751_value==0x0000) {i8751_return=0; coin1=coin2=snd=0;}
if (i8751_value==0x038a) i8751_return=0x375; /* Mekyo Sensi ID */
if (i8751_value==0x038b) i8751_return=0x374; /* Gondomania ID */
if ((i8751_value>>8)==0x04) i8751_return=0x40f; /* Coinage settings (Not supported) */
if ((i8751_value>>8)==0x05) {i8751_return=0x500 | coin1; } /* Coin 1 */
if ((i8751_value>>8)==0x06 && coin1 && !offset) {i8751_return=0x600; coin1--; } /* Coin 1 clear */
if ((i8751_value>>8)==0x07) {i8751_return=0x700 | coin2; } /* Coin 2 */
if ((i8751_value>>8)==0x08 && coin2 && !offset) {i8751_return=0x800; coin2--; } /* Coin 2 clear */
/* Commands 0x9xx do nothing */
if ((i8751_value>>8)==0x0a) {i8751_return=0xa00 | snd; if (snd) snd=0; }
}
static void shackled_i8751_w(int offset, int data)
{
static int coin1,coin2,latch=0;
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
cpu_cause_interrupt (1, M6809_INT_FIRQ); /* Signal main cpu */
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
/* Coins are controlled by the i8751 */
if (/*(readinputport(2)&3)==3*/!latch) {latch=1;coin1=coin2=0;}
if ((readinputport(2)&1)!=1 && latch) {coin1=1; latch=0;}
if ((readinputport(2)&2)!=2 && latch) {coin2=1; latch=0;}
if (i8751_value==0x0050) i8751_return=0; /* Breywood ID */
if (i8751_value==0x0051) i8751_return=0; /* Shackled ID */
if (i8751_value==0x0102) i8751_return=0; /* ?? */
if (i8751_value==0x0101) i8751_return=0; /* ?? */
if (i8751_value==0x8101) i8751_return=coin2 | (coin1<<8); /* Coins */
}
static void lastmiss_i8751_w(int offset, int data)
{
static int coin,latch=0,snd;
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
cpu_cause_interrupt (0, M6809_INT_FIRQ); /* Signal main cpu */
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
/* Coins are controlled by the i8751 */
if ((readinputport(2)&3)==3 && !latch) latch=1;
if ((readinputport(2)&3)!=3 && latch) {coin++; latch=0;snd=0x400;}
if (i8751_value==0x007b) i8751_return=0x0184;
if (i8751_value==0x0000) {i8751_return=0x0184; coin=snd=0;}
if (i8751_value==0x0401) i8751_return=0x0184;
if ((i8751_value>>8)==0x01) i8751_return=0x0184; /* Coinage setup */
if ((i8751_value>>8)==0x02) {i8751_return=snd | coin; snd=0;} /* Coin return */
if ((i8751_value>>8)==0x03) {i8751_return=0; coin--; } /* Coin clear */
}
static void csilver_i8751_w(int offset, int data)
{
static int coin,latch=0,snd;
i8751_return=0;
switch (offset) {
case 0: /* High byte */
i8751_value=(i8751_value&0xff) | (data<<8);
cpu_cause_interrupt (0, M6809_INT_FIRQ); /* Signal main cpu */
break;
case 1: /* Low byte */
i8751_value=(i8751_value&0xff00) | data;
break;
}
/* Coins are controlled by the i8751 */
if ((readinputport(2)&3)==3 && !latch) latch=1;
if ((readinputport(2)&3)!=3 && latch) {coin++; latch=0;snd=0x1200;}
if (i8751_value==0x054a) {i8751_return=~(0x4a); coin=0; snd=0;} /* Captain Silver ID */
if ((i8751_value>>8)==0x01) i8751_return=0; /* Coinage - Not Supported */
if ((i8751_value>>8)==0x02) {i8751_return=snd | coin; snd=0; } /* Coin Return */
if (i8751_value==0x0003 && coin) {i8751_return=0; coin--;} /* Coin Clear */
/* Todo: Coin insert sound doesn't seem to work...*/
}
/******************************************************************************/
static void dec8_bank_w(int offset, int data)
{
int bankaddress;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
bankaddress = 0x10000 + (data & 0x0f) * 0x4000;
cpu_setbank(1,&RAM[bankaddress]);
}
/* Used by Ghostbusters, Mazehunter & Gondomania */
static void ghostb_bank_w(int offset, int data)
{
int bankaddress;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
/* Bit 0: Interrupt enable/disable (I think..)
Bit 1: NMI enable/disable
Bit 2: ??
Bit 3: Screen flip (not supported)
Bits 4-7: Bank switch
*/
bankaddress = 0x10000 + (data >> 4) * 0x4000;
cpu_setbank(1,&RAM[bankaddress]);
if (data&1) int_enable=1; else int_enable=0;
if (data&2) nmi_enable=1; else nmi_enable=0;
}
void csilver_control_w(int offset, int data)
{
int bankaddress;
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];
/* Bottom 4 bits - bank switch */
bankaddress = 0x10000 + (data & 0x0f) * 0x4000;
cpu_setbank(1,&RAM[bankaddress]);
/* There are unknown bits in the top half of the byte! */
}
static void dec8_sound_w(int offset, int data)
{
soundlatch_w(0,data);
cpu_cause_interrupt(1,M6502_INT_NMI);
}
static void oscar_sound_w(int offset, int data)
{
soundlatch_w(0,data);
cpu_cause_interrupt(2,M6502_INT_NMI);
}
static void csilver_adpcm_int(int data)
{
static int toggle;
toggle = 1 - toggle;
if (toggle)
cpu_cause_interrupt(2,M6502_INT_IRQ);
}
static int csilver_adpcm_reset_r(int offset)
{
MSM5205_reset_w(0,0);
return 0;
}
static void csilver_adpcm_data_w(int offset,int data)
{
MSM5205_data_w(offset,data >> 4);
MSM5205_data_w(offset,data);
}
static void csilver_sound_bank_w(int offset,int data)
{
unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[2].memory_region];
if (data&8) { cpu_setbank(3,&RAM[0x14000]); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -