📄 lastduel.c
字号:
/**************************************************************************
* Last Duel ('American' set) - Capcom, 1988
* Last Duel (Bootleg set) - Capcom, 1988
* Mad Gear (aka Led Storm) - Capcom, 1989
Emulation by Bryan McPhail, mish@tendril.force9.net
Issues:
* American Last Duel set is missing 1 set of tile roms, the roms from
the bootleg set are used.
* Strange bug in Last Duel, American set - the 'y' at the far right of
the screen from the copyright message is not cleared. Weird...
* Wrong dip switches for Mad Gear (service mode is in there somewhere..)
* No tile roms for Mad Gear!
**************************************************************************/
#include "driver.h"
#include "vidhrdw/generic.h"
#include "z80/z80.h"
extern int lastduel_vram_r(int offset);
extern void lastduel_vram_w(int offset,int value);
extern int lastduel_scroll2_r(int offset);
extern void lastduel_scroll2_w(int offset,int value);
extern int lastduel_scroll1_r(int offset);
extern void lastduel_scroll1_w(int offset,int value);
extern int lastduel_sprites_r(int offset);
extern void lastduel_sprites_w(int offset,int value);
extern int lastduel_vh_start(void);
extern void lastduel_vh_stop(void);
extern void lastduel_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);
extern void lastduel_scroll_w( int offset, int data );
#if 0
extern void lastduel_set_dirty(void);
#endif
extern unsigned char *lastduel_ram;
extern unsigned char *lastduel_vram;
extern unsigned char *lastduel_scroll2;
extern unsigned char *lastduel_scroll1;
extern unsigned char *lastduel_sprites;
/******************************************************************************/
static int madgear_inputs_r(int offset)
{
switch (offset) {
case 4: /* Player 1 & Player 2 controls */
return(readinputport(0)<<8)+readinputport(1);
case 2: /* COINS in top two bits of byte 3 */
return(readinputport(2)<<8)+readinputport(3);
case 6: /* Start + coins */
return(readinputport(2)<<8)+readinputport(3);
case 0:
return(readinputport(0)<<8)+readinputport(1);
}
return 0xffff;
}
static int lastduel_inputs_r(int offset)
{
switch (offset) {
case 0: /* Player 1 & Player 2 controls */
return(readinputport(0)<<8)+readinputport(1);
case 2: /* Coins & Service switch */
return readinputport(2);
case 4: /* Dips */
return (readinputport(3)<<8)+readinputport(4);
case 6: /* Dips, flip */
return readinputport(5);
}
return 0xffff;
}
static void lastduel_sound_w( int offset, int data )
{
switch( offset )
{
case 0:
break;
case 2:
soundlatch_w(offset,data & 0xff);
break;
}
}
/******************************************************************************/
static struct MemoryReadAddress lastduel_readmem[] =
{
{ 0x000000, 0x05ffff, MRA_ROM },
{ 0xfc4000, 0xfc4007, lastduel_inputs_r },
{ 0xfc0800, 0xfc0cff, lastduel_sprites_r },
{ 0xfcc000, 0xfcdfff, lastduel_vram_r },
{ 0xfd0000, 0xfd3fff, lastduel_scroll1_r },
{ 0xfd4000, 0xfd7fff, lastduel_scroll2_r },
{ 0xfd8000, 0xfd87ff, paletteram_word_r },
{ 0xfe0000, 0xffffff, MRA_BANK1 },
{ -1 } /* end of table */
};
static struct MemoryWriteAddress lastduel_writemem[] =
{
{ 0x000000, 0x05ffff, MWA_ROM },
{ 0xfc0000, 0xfc0003, MWA_NOP }, /* Written rarely */
{ 0xfc4000, 0xfc4003, lastduel_sound_w },
{ 0xfc8000, 0xfc800f, lastduel_scroll_w },
{ 0xfc0800, 0xfc0d07, lastduel_sprites_w, &lastduel_sprites },
{ 0xfcc000, 0xfcdfff, lastduel_vram_w, &lastduel_vram },
{ 0xfd0000, 0xfd3fff, lastduel_scroll1_w, &lastduel_scroll1 },
{ 0xfd4000, 0xfd7fff, lastduel_scroll2_w, &lastduel_scroll2 },
{ 0xfd8000, 0xfd87ff, paletteram_RRRRGGGGBBBBIIII_word_w, &paletteram },
{ 0xfe0000, 0xffffff, MWA_BANK1, &lastduel_ram },
{ -1 } /* end of table */
};
static struct MemoryReadAddress madgear_readmem[] =
{
{ 0x000000, 0x07ffff, MRA_ROM },
{ 0xfc4000, 0xfc4007, madgear_inputs_r },
{ 0xfc1800, 0xfc1fff, lastduel_sprites_r },
{ 0xfc8000, 0xfc9fff, lastduel_vram_r },
{ 0xfcc000, 0xfcc7ff, paletteram_word_r },
{ 0xfd4000, 0xfd7fff, lastduel_scroll1_r },
{ 0xfd8000, 0xfdffff, lastduel_scroll2_r },
{ 0xff0000, 0xffffff, MRA_BANK1 },
{ -1 } /* end of table */
};
static struct MemoryWriteAddress madgear_writemem[] =
{
{ 0x000000, 0x07ffff, MWA_ROM },
{ 0xfc4000, 0xfc4003, lastduel_sound_w },
{ 0xfd0000, 0xfd000f, lastduel_scroll_w },
{ 0xfc1800, 0xfc1fff, lastduel_sprites_w, &lastduel_sprites },
{ 0xfc8000, 0xfc9fff, lastduel_vram_w, &lastduel_vram },
{ 0xfcc000, 0xfcc7ff, paletteram_RRRRGGGGBBBBIIII_word_w, &paletteram },
{ 0xfd4000, 0xfd7fff, lastduel_scroll1_w, &lastduel_scroll1 },
{ 0xfd8000, 0xfdffff, lastduel_scroll2_w, &lastduel_scroll2 },
{ 0xff0000, 0xffffff, MWA_BANK1 },
{ -1 } /* end of table */
};
static struct MemoryReadAddress sound_readmem[] =
{
{ 0x0000, 0xdfff, MRA_ROM },
{ 0xe000, 0xe7ff, MRA_RAM },
{ 0xe800, 0xe800, YM2203_status_port_0_r },
{ 0xf000, 0xf000, YM2203_status_port_1_r },
{ 0xf800, 0xf800, soundlatch_r },
{ -1 } /* end of table */
};
static struct MemoryWriteAddress sound_writemem[] =
{
{ 0x0000, 0xdfff, MWA_ROM },
{ 0xe000, 0xe7ff, MWA_RAM },
{ 0xe800, 0xe800, YM2203_control_port_0_w },
{ 0xe801, 0xe801, YM2203_write_port_0_w },
{ 0xf000, 0xf000, YM2203_control_port_1_w },
{ 0xf001, 0xf001, YM2203_write_port_1_w },
{ -1 } /* end of table */
};
static struct MemoryReadAddress mg_sound_readmem[] =
{
{ 0x0000, 0xcfff, MRA_ROM },
{ 0xd000, 0xd7ff, MRA_RAM },
{ 0xf000, 0xf000, YM2203_status_port_0_r },
{ 0xf002, 0xf002, YM2203_status_port_1_r },
{ 0xf006, 0xf006, soundlatch_r },
{ -1 } /* end of table */
};
static struct MemoryWriteAddress mg_sound_writemem[] =
{
{ 0x0000, 0xcfff, MWA_ROM },
{ 0xd000, 0xd7ff, MWA_RAM },
{ 0xf000, 0xf000, YM2203_control_port_0_w },
{ 0xf001, 0xf001, YM2203_write_port_0_w },
{ 0xf002, 0xf002, YM2203_control_port_1_w },
{ 0xf003, 0xf003, YM2203_write_port_1_w },
{ 0xf00a, 0xf00a, MWA_NOP },
{ -1 } /* end of table */
};
/******************************************************************************/
static struct GfxLayout sprites =
{
16,16, /* 16*16 sprites */
4096, /* 32 bytes per sprite, 0x20000 per plane so 4096 sprites */
4, /* 4 bits per pixel */
{ 0x00000*8, 0x20000*8, 0x40000*8, 0x60000*8 },
{
0,1,2,3,4,5,6,7,
(16*8)+0,(16*8)+1,(16*8)+2,(16*8)+3,
(16*8)+4,(16*8)+5,(16*8)+6,(16*8)+7
},
{
0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8,
},
32*8 /* every sprite takes 32 consecutive bits */
};
static struct GfxLayout text_layout =
{
8,8, /* 8*8 characters */
2048, /* 2048 character */
2, /* 2 bitplanes */
{ 4,0 },
{
0,1,2,3,8,9,10,11
},
{
0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16
},
16*8 /* every character takes 16 consecutive bytes */
};
static struct GfxLayout scroll1layout =
{
16,16, /* 16*16 tiles */
2048, /* 2048 tiles */
4, /* 4 bits per pixel */
{ 4,0,(0x020000*8)+4,0x020000*8, },
{
0,1,2,3,8,9,10,11,
(8*4*8)+0,(8*4*8)+1,(8*4*8)+2,(8*4*8)+3,
(8*4*8)+8,(8*4*8)+9,(8*4*8)+10,(8*4*8)+11
},
{
0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16
},
64*8 /* each tile takes 64 consecutive bytes */
};
static struct GfxLayout scroll2layout =
{
16,16, /* 16*16 tiles */
4096, /* 4096 tiles */
4, /* 4 bits per pixel */
{ 4,0,(0x040000*8)+4,0x040000*8, },
{
0,1,2,3,8,9,10,11,
(8*4*8)+0,(8*4*8)+1,(8*4*8)+2,(8*4*8)+3,
(8*4*8)+8,(8*4*8)+9,(8*4*8)+10,(8*4*8)+11
},
{
0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16
},
64*8 /* each tile takes 64 consecutive bytes */
};
static struct GfxDecodeInfo lastduel_gfxdecodeinfo[] =
{
{ 1, 0x40000,&sprites, 512, 16 }, /* colors 512-767 */
{ 1, 0xc0000,&text_layout, 768, 16 }, /* colors 768-831 */
{ 1, 0x00000,&scroll1layout, 0, 16 }, /* colors 0-255 */
{ 1, 0xc8000,&scroll2layout, 256, 16 }, /* colors 256-511 */
{ -1 }
};
/******************************************************************************
Save States - shall be used someday ;) */
#if 0
extern int MC68000_State_Load(void *f);
extern int MC68000_State_Save(void *f);
static void LoadState(void)
{
void *f;
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0) {
MC68000_State_Load(f);
osd_fread(f,lastduel_ram,0x20000);
osd_fread(f,lastduel_sprites,0x506);
osd_fread(f,lastduel_vram,0x2000);
osd_fread(f,lastduel_scroll1,0x4000);
osd_fread(f,lastduel_scroll2,0x4000);
osd_fread(f,paletteram,0x800);
osd_fclose(f);
lastduel_set_dirty();
}
}
static void SaveState(void)
{
void *f;
if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,1)) != 0) {
MC68000_State_Save(f);
osd_fwrite(f,lastduel_ram,0x20000);
osd_fwrite(f,lastduel_sprites,0x506);
osd_fwrite(f,lastduel_vram,0x2000);
osd_fwrite(f,lastduel_scroll1,0x4000);
osd_fwrite(f,lastduel_scroll2,0x4000);
osd_fwrite(f,paletteram,0x800);
osd_fclose(f);
}
}
#endif
/******************************************************************************/
/* handler called by the 2203 emulator when the internal timers cause an IRQ */
static void irqhandler(void)
{
cpu_cause_interrupt(1,0xff);
}
static struct YM2203interface ym2203_interface =
{
2, /* 2 chips */
3500000, /* 3.5 MHz ? */
{ YM2203_VOL(140,255), YM2203_VOL(140,255) },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ irqhandler }
};
int lastduel_interrupt(void)
{
if (cpu_getiloops() == 0) return 2;
else return 4;
}
int madgear_interrupt(void)
{
if (cpu_getiloops() == 0) return 5;
else return 6;
}
static struct MachineDriver lastduel_machine_driver =
{
/* basic machine hardware */
{
{
CPU_M68000,
8000000,
0,
lastduel_readmem, lastduel_writemem, 0,0,
lastduel_interrupt,6 /* ??? */
},
{
CPU_Z80 | CPU_AUDIO_CPU,
3579000,
2,
sound_readmem,sound_writemem,0,0,
ignore_interrupt,0 /* IRQs are caused by the YM2203 */
}
},
60, DEFAULT_60HZ_VBLANK_DURATION,
1,
0,
/* video hardware */
512, 256, { 63, 455, 0, 255 },
lastduel_gfxdecodeinfo,
1024, 1024,
0,
VIDEO_TYPE_RASTER | VIDEO_MODIFIES_PALETTE,
0,
lastduel_vh_start,
lastduel_vh_stop,
lastduel_vh_screenrefresh,
/* sound hardware */
0,0,0,0,
{
{
SOUND_YM2203,
&ym2203_interface
}
}
};
static struct MachineDriver madgear_machine_driver =
{
/* basic machine hardware */
{
{
CPU_M68000,
8000000,
0,
madgear_readmem, madgear_writemem, 0,0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -