From: Mamesick [mailto:mamesick@libero.it]

Sent: Tuesday, December 23, 2008 7:49 AM
To: submit@mamedev.org
Subject: Submissions

* ddragon.diff:
- converted scanline timer to be a device
- corrected M6809 CPU frequencies, they are supposed to be internally divided by 4 but
  there's no internal divider in the core

* gstream.diff:
- improved oki banking (educated guesswork, see notes in the driver)
- replaced CPU_EAT_CYCLES hack with CPU_SPINUNTIL_INT because the first cause the video
  completely out of sync with audio. I think the game is really so slow on the PCB too

* vball.diff:
- converted driver to be fully scanlines based using timers
- hooked up interrupts
- updated driver to new video screen raw parameters (based on ddragon.c driver)

* xain.diff:
- converted driver to be fully scanlines based using timers
- fixed ID 02742
- updated driver to new video screen raw parameters (based on ddragon.c driver)
This commit is contained in:
Aaron Giles 2008-12-26 06:46:32 +00:00
parent 4ed7452ceb
commit cafa7fc102
10 changed files with 244 additions and 198 deletions

View File

@ -81,7 +81,8 @@ Dip locations verified with manual for ddragon & ddragon2
#define MAIN_CLOCK XTAL_12MHz
#define SOUND_CLOCK XTAL_3_579545MHz
#define MCU_CLOCK XTAL_4MHz
#define MCU_CLOCK MAIN_CLOCK / 3
#define PIXEL_CLOCK MAIN_CLOCK / 2
/* from video */
@ -97,8 +98,6 @@ extern UINT8 *ddragon_spriteram;
extern UINT8 technos_video_hw;
/* end of extern code & data */
static emu_timer *scanline_timer;
/* private globals */
static UINT8 dd_sub_cpu_busy;
static UINT8 sprite_irq, sound_irq, ym_irq;
@ -141,30 +140,24 @@ INLINE int scanline_to_vcount(int scanline)
return (vcount - 0x18) | 0x100;
}
static TIMER_CALLBACK( ddragon_scanline_callback )
static TIMER_DEVICE_CALLBACK( ddragon_scanline )
{
int scanline = param;
int screen_height = video_screen_get_height(machine->primary_screen);
int screen_height = video_screen_get_height(timer->machine->primary_screen);
int vcount_old = scanline_to_vcount((scanline == 0) ? screen_height - 1 : scanline - 1);
int vcount = scanline_to_vcount(scanline);
/* update to the current point */
if (scanline > 0)
video_screen_update_partial(machine->primary_screen, scanline - 1);
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
/* on the rising edge of VBLK (vcount == F8), signal an NMI */
if (vcount == 0xf8)
cpu_set_input_line(machine->cpu[0], INPUT_LINE_NMI, ASSERT_LINE);
cpu_set_input_line(timer->machine->cpu[0], INPUT_LINE_NMI, ASSERT_LINE);
/* set 1ms signal on rising edge of vcount & 8 */
if (!(vcount_old & 8) && (vcount & 8))
cpu_set_input_line(machine->cpu[0], M6809_FIRQ_LINE, ASSERT_LINE);
/* adjust for next scanline */
if (++scanline >= screen_height)
scanline = 0;
timer_adjust_oneshot(scanline_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline, 0), scanline);
cpu_set_input_line(timer->machine->cpu[0], M6809_FIRQ_LINE, ASSERT_LINE);
}
@ -180,9 +173,6 @@ static MACHINE_START( ddragon )
/* configure banks */
memory_configure_bank(machine, 1, 0, 8, memory_region(machine, "main") + 0x10000, 0x4000);
/* allocate timer for scanlines */
scanline_timer = timer_alloc(machine, ddragon_scanline_callback, NULL);
/* determine the sound CPU index */
snd_cpu = cputag_get_cpu(machine, "sound");
@ -201,7 +191,6 @@ static MACHINE_RESET( ddragon )
adpcm_end[0] = adpcm_end[1] = 0;
adpcm_idle[0] = adpcm_idle[1] = 1;
adpcm_data[0] = adpcm_data[1] = -1;
timer_adjust_oneshot(scanline_timer, video_screen_get_time_until_pos(machine->primary_screen, 0, 0), 0);
}
@ -978,16 +967,17 @@ static const msm5205_interface msm5205_config =
static MACHINE_DRIVER_START( ddragon )
/* basic machine hardware */
MDRV_CPU_ADD("main", HD6309, MAIN_CLOCK) /* 12MHz / 4 internally */
MDRV_CPU_ADD("main", HD6309, MAIN_CLOCK) /* 12 MHz / 4 internally */
MDRV_CPU_PROGRAM_MAP(ddragon_map,0)
MDRV_TIMER_ADD_SCANLINE("scantimer", ddragon_scanline, "main", 0, 1)
MDRV_CPU_ADD("sub", HD63701, MAIN_CLOCK/2) /* 6Mhz / 4 internally */
MDRV_CPU_ADD("sub", HD63701, MAIN_CLOCK / 2) /* 6 MHz / 4 internally */
MDRV_CPU_PROGRAM_MAP(sub_map,0)
MDRV_CPU_ADD("sound", M6809, MAIN_CLOCK/2) /* 6MHz / 4 internally */
MDRV_CPU_ADD("sound", M6809, MAIN_CLOCK / 8) /* 1.5 MHz */
MDRV_CPU_PROGRAM_MAP(sound_map,0)
MDRV_QUANTUM_TIME(HZ(60000)) /* heavy interleaving to sync up sprite<->main cpu's */
MDRV_QUANTUM_TIME(HZ(60000)) /* heavy interleaving to sync up sprite<->main cpu's */
MDRV_MACHINE_START(ddragon)
MDRV_MACHINE_RESET(ddragon)
@ -998,7 +988,7 @@ static MACHINE_DRIVER_START( ddragon )
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, 384, 0, 256, 272, 0, 240)
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 384, 0, 256, 272, 0, 240)
MDRV_VIDEO_START(ddragon)
MDRV_VIDEO_UPDATE(ddragon)
@ -1025,7 +1015,7 @@ static MACHINE_DRIVER_START( ddragonb )
MDRV_IMPORT_FROM(ddragon)
/* basic machine hardware */
MDRV_CPU_REPLACE("sub", M6809, MAIN_CLOCK/2) /* 6Mhz / 4 internally */
MDRV_CPU_REPLACE("sub", M6809, MAIN_CLOCK / 8) /* 1.5Mhz */
MDRV_CPU_PROGRAM_MAP(sub_map,0)
MACHINE_DRIVER_END
@ -1034,7 +1024,7 @@ static MACHINE_DRIVER_START( ddragnba )
MDRV_IMPORT_FROM(ddragon)
/* basic machine hardware */
MDRV_CPU_REPLACE("sub", M6803, MAIN_CLOCK/2) /* 6Mhz / 4 internally */
MDRV_CPU_REPLACE("sub", M6803, MAIN_CLOCK / 2) /* 6Mhz / 4 internally */
MDRV_CPU_PROGRAM_MAP(ddragnba_sub_map,0)
MDRV_CPU_IO_MAP(ddragnba_sub_portmap,0)
MACHINE_DRIVER_END
@ -1043,13 +1033,14 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( ddgn6809 )
/* basic machine hardware */
MDRV_CPU_ADD("main", M6809, MAIN_CLOCK) /* 12MHz / 4 internally */
MDRV_CPU_ADD("main", M6809, MAIN_CLOCK / 8) /* 1.5 MHz */
MDRV_CPU_PROGRAM_MAP(ddragon_map,0)
MDRV_TIMER_ADD_SCANLINE("scantimer", ddragon_scanline, "main", 0, 1)
MDRV_CPU_ADD("sub", M6809, MAIN_CLOCK/2) /* 6Mhz / 4 internally */
MDRV_CPU_ADD("sub", M6809, MAIN_CLOCK / 8) /* 1.5 Mhz */
MDRV_CPU_PROGRAM_MAP(sub_map,0)
MDRV_CPU_ADD("sound", M6809, MAIN_CLOCK/2) /* 6MHz / 4 internally */
MDRV_CPU_ADD("sound", M6809, MAIN_CLOCK / 8) /* 1.5 MHz */
MDRV_CPU_PROGRAM_MAP(sound_map,0)
MDRV_QUANTUM_TIME(HZ(60000)) /* heavy interleaving to sync up sprite<->main cpu's */
@ -1063,7 +1054,7 @@ static MACHINE_DRIVER_START( ddgn6809 )
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, 384, 0, 256, 272, 0, 240)
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 384, 0, 256, 272, 0, 240)
MDRV_VIDEO_START(ddragon)
MDRV_VIDEO_UPDATE(ddragon)
@ -1089,10 +1080,11 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( ddragon2 )
/* basic machine hardware */
MDRV_CPU_ADD("main", HD6309, MAIN_CLOCK) /* 12MHz / 4 internally */
MDRV_CPU_ADD("main", HD6309, MAIN_CLOCK) /* 12 MHz / 4 internally */
MDRV_CPU_PROGRAM_MAP(dd2_map,0)
MDRV_TIMER_ADD_SCANLINE("scantimer", ddragon_scanline, "main", 0, 1)
MDRV_CPU_ADD("sub", Z80, MAIN_CLOCK / 3) /* 4 MHz */
MDRV_CPU_ADD("sub", Z80, MAIN_CLOCK / 3) /* 4 MHz */
MDRV_CPU_PROGRAM_MAP(dd2_sub_map,0)
MDRV_CPU_ADD("sound", Z80, 3579545)
@ -1109,7 +1101,7 @@ static MACHINE_DRIVER_START( ddragon2 )
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_RAW_PARAMS(MAIN_CLOCK/2, 384, 0, 256, 272, 0, 240)
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 384, 0, 256, 272, 0, 240)
MDRV_VIDEO_START(ddragon)
MDRV_VIDEO_UPDATE(ddragon)
@ -2005,9 +1997,6 @@ GAME( 1987, ddragonb, ddragon, ddragonb, ddragon, ddragon, ROT0, "bootleg", "
GAME( 1987, ddragnba, ddragon, ddragnba, ddragon, ddragon, ROT0, "bootleg", "Double Dragon (bootleg with M6803)", GAME_SUPPORTS_SAVE )
GAME( 1987, ddgn6809, ddragon, ddgn6809, ddragon, ddgn6809, ROT0, "bootleg", "Double Dragon (bootleg with 3xM6809, set 1)", GAME_NOT_WORKING )
GAME( 1987, dd6809a, ddragon, ddgn6809, ddragon, ddgn6809, ROT0, "bootleg", "Double Dragon (bootleg with 3xM6809, set 2)", GAME_NOT_WORKING )
GAME( 1988, ddragon2, 0, ddragon2, ddragon2, ddragon2, ROT0, "Technos", "Double Dragon II - The Revenge (World)", GAME_SUPPORTS_SAVE )
GAME( 1988, ddragn2u, ddragon2, ddragon2, ddragon2, ddragon2, ROT0, "Technos", "Double Dragon II - The Revenge (US)", GAME_SUPPORTS_SAVE )

View File

@ -602,12 +602,6 @@ static TIMER_DEVICE_CALLBACK( ddragon3_scanline )
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
cpu_set_input_line(timer->machine->cpu[0], 6, ASSERT_LINE);
}
/* Adjust for next scanline */
if (++scanline >= video_screen_get_height(timer->machine->primary_screen))
{
scanline = 0;
}
}
/*************************************

View File

@ -200,36 +200,71 @@ static READ32_HANDLER( gstream_oki_1_r ) { return okim6295_status_1_r(space, 0);
static WRITE32_HANDLER( gstream_oki_0_w ) { okim6295_data_0_w(space, 0, data & 0xff); }
static WRITE32_HANDLER( gstream_oki_1_w ) { okim6295_data_1_w(space, 0, data & 0xff); }
static WRITE32_HANDLER( gstream_oki_4030_w )
static WRITE32_HANDLER( gstream_oki_banking_w )
{
/*
// the only nibbles that are written are: 0x6 0x7 0x9 0xa 0xb 0xe 0xd 0xf which should map to the 8 oki banks
/* OKI BANKING (still far from perfect, based on game behaviour)
static const int bank_lookup[16] = { -1, -1, -1, -1, -1, -1, 0, 1, -1, 2, 3, 4, -1, 5, 6, 7 };
The two okis can indifferently play music or samples and are switched on the fly during game
This is a preliminary table of the banks:
static int old_bank_0 = -1;
static int old_bank_1 = -1;
BANK MUSIC SAMPLES
0 X
1 X
2 X
3 X
4 X
5 X
6 X
7 X
if(bank_lookup[data & 0xf] != old_bank_0)
{
old_bank_0 = bank_lookup[data & 0xf];
Two nibbles are used in this handler: (data & 0xf) and ((data >> 4) & 0xf)
The values for the first nibble are the followings and should map the 8 oki banks:
- 0x6, 0x7, 0x9, 0xa, 0xb, 0xd, 0xe, 0xf
The values for the second nibble are the followings and should probably be used too:
- 0x6, 0x9, 0xa
if(old_bank_0 != -1)
okim6295_set_bank_base(0, old_bank_0 * 0x40000);
else
logerror("oki_0 banking value = %X\n",data & 0xf);
}
Same values are redudant, for example:
level 2: data = 0x99
level 6: data = 0x99
(this means same background music for the two levels - it could be correct, though)
if(bank_lookup[(data >> 4) & 0xf] != old_bank_1)
{
old_bank_1 = bank_lookup[(data >> 4) & 0xf];
Also with current implementation, using only (data & 0xf), we have to force some values
manually, because the correspondent places in the table are already used
if(old_bank_1 != -1)
okim6295_set_bank_base(1, old_bank_1 * 0x40000);
else
logerror("oki_1 banking value = %X\n",(data >> 4) & 0xf);
}
*/
Musics order is completely guessed but close to what the original PCB game should be */
static const int bank_table_0[16] = { -1, -1, -1, -1, -1, -1, 0, 0, -1, 6, 0, 5, -1, 0, 0, 0 };
static const int bank_table_1[16] = { -1, -1, -1, -1, -1, -1, 2, 2, -1, 0, 0, 4, -1, 1, 1, 1 };
static int bank_0 = 0;
static int bank_1 = 0;
//popmessage("oki_0 banking value = %X\noki_1 banking value = %X\n",data & 0xf,(data >> 4) & 0xf);
bank_0 = bank_table_0[data & 0xf];
bank_1 = bank_table_1[data & 0xf]; // (data >> 4) & 0xf ??
/* some values are already used in the table, so we force them manually */
if ((data == 0x6f) || (data == 0x6e))
{
bank_0 = 0; // level 3b-5a samples
bank_1 = 6; // level 3b-5a music
}
if (data == 0x9b)
{
bank_0 = 7; // level 7 music
bank_1 = 0; // level 7 samples
}
if (data == 0x9f)
{
bank_0 = 0; // end sequence samples
bank_1 = 3; // end sequence music
}
okim6295_set_bank_base(0, bank_0 * 0x40000);
okim6295_set_bank_base(1, bank_1 * 0x40000);
}
static WRITE32_HANDLER( gstream_oki_4040_w )
@ -240,11 +275,11 @@ static WRITE32_HANDLER( gstream_oki_4040_w )
static ADDRESS_MAP_START( gstream_io, ADDRESS_SPACE_IO, 32 )
AM_RANGE(0x4000, 0x4003) AM_READ_PORT("IN0")
AM_RANGE(0x4010, 0x4013) AM_READ_PORT("IN1")
AM_RANGE(0x4020, 0x4023) AM_READ_PORT("IN2") // extra coin switches etc
AM_RANGE(0x4030, 0x4033) AM_WRITE(gstream_oki_4030_w) // ??
AM_RANGE(0x4040, 0x4043) AM_WRITE(gstream_oki_4040_w) // ??
AM_RANGE(0x4050, 0x4053) AM_READWRITE(gstream_oki_1_r, gstream_oki_1_w) // music
AM_RANGE(0x4060, 0x4063) AM_READWRITE(gstream_oki_0_r, gstream_oki_0_w) // samples
AM_RANGE(0x4020, 0x4023) AM_READ_PORT("IN2") // extra coin switches etc
AM_RANGE(0x4030, 0x4033) AM_WRITE(gstream_oki_banking_w) // oki banking
AM_RANGE(0x4040, 0x4043) AM_WRITE(gstream_oki_4040_w) // ??
AM_RANGE(0x4050, 0x4053) AM_READWRITE(gstream_oki_1_r, gstream_oki_1_w) // music and samples
AM_RANGE(0x4060, 0x4063) AM_READWRITE(gstream_oki_0_r, gstream_oki_0_w) // music and samples
ADDRESS_MAP_END
static INPUT_PORTS_START( gstream )
@ -434,12 +469,12 @@ static MACHINE_DRIVER_START( gstream )
MDRV_SPEAKER_STANDARD_MONO("mono")
MDRV_SOUND_ADD("oki1", OKIM6295, 1000000) /* 1 Mhz? */
MDRV_SOUND_CONFIG(okim6295_interface_pin7low) // pin 7 not verified
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MDRV_SOUND_CONFIG(okim6295_interface_pin7high) // pin 7 not verified
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MDRV_SOUND_ADD("oki2", OKIM6295, 1000000) /* 1 Mhz? */
MDRV_SOUND_CONFIG(okim6295_interface_pin7low) // pin 7 not verified
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MDRV_SOUND_CONFIG(okim6295_interface_pin7high) // pin 7 not verified
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MACHINE_DRIVER_END
ROM_START( gstream )
@ -481,7 +516,7 @@ static READ32_HANDLER( gstream_speedup_r )
{
if (cpu_get_pc(space->cpu)==0xc0001592)
{
cpu_eat_cycles(space->cpu, 50);
cpu_spinuntil_int(space->cpu);
}
return gstream_workram[0xd1ee0/4];
@ -492,4 +527,5 @@ static DRIVER_INIT( gstream )
memory_install_read32_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_PROGRAM), 0xd1ee0, 0xd1ee3, 0, 0, gstream_speedup_r );
}
GAME( 2002, gstream, 0, gstream, gstream, gstream, ROT270, "Oriental Soft Japan", "G-Stream G2020", GAME_IMPERFECT_SOUND )

View File

@ -311,12 +311,6 @@ static TIMER_DEVICE_CALLBACK( shadfrce_scanline )
cpu_set_input_line(timer->machine->cpu[0], 3, ASSERT_LINE);
}
}
/* Adjust for next scanline */
if (++scanline >= video_screen_get_height(timer->machine->primary_screen))
{
scanline = 0;
}
}

View File

@ -95,6 +95,61 @@ VBlank = 58Hz
#include "sound/okim6295.h"
#include "includes/vball.h"
#define MAIN_CLOCK XTAL_12MHz
#define CPU_CLOCK MAIN_CLOCK / 6
#define PIXEL_CLOCK MAIN_CLOCK / 2
/* Based on ddragon driver */
INLINE int scanline_to_vcount(int scanline)
{
int vcount = scanline + 8;
if (vcount < 0x100)
return vcount;
else
return (vcount - 0x18) | 0x100;
}
static TIMER_DEVICE_CALLBACK( vball_scanline )
{
int scanline = param;
int screen_height = video_screen_get_height(timer->machine->primary_screen);
int vcount_old = scanline_to_vcount((scanline == 0) ? screen_height - 1 : scanline - 1);
int vcount = scanline_to_vcount(scanline);
/* Update to the current point */
if (scanline > 0)
{
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
}
/* IRQ fires every on every 8th scanline */
if (!(vcount_old & 8) && (vcount & 8))
{
cpu_set_input_line(timer->machine->cpu[0], M6502_IRQ_LINE, ASSERT_LINE);
}
/* NMI fires on scanline 248 (VBL) and is latched */
if (vcount == 0xf8)
{
cpu_set_input_line(timer->machine->cpu[0], INPUT_LINE_NMI, ASSERT_LINE);
}
/* Save the scroll x register value */
if (scanline < 256)
{
scrollx[255 - scanline] = (vb_scrollx_hi + vb_scrollx_lo+4);
}
}
static WRITE8_HANDLER( vball_irq_ack_w )
{
if (offset == 0)
cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, CLEAR_LINE);
else
cpu_set_input_line(space->machine->cpu[0], M6502_IRQ_LINE, CLEAR_LINE);
}
/* bit 0 = bank switch
bit 1 = ?
@ -118,8 +173,6 @@ static WRITE8_HANDLER( vb_bankswitch_w )
}
/* The sound system comes all but verbatim from Double Dragon */
static WRITE8_HANDLER( cpu_sound_command_w ) {
soundlatch_w( space, offset, data );
cpu_set_input_line(space->machine->cpu[1], INPUT_LINE_NMI, PULSE_LINE );
@ -144,6 +197,13 @@ static WRITE8_HANDLER( vb_scrollx_hi_w )
//logerror("%04x: vb_scrollx_hi = %d\n",cpu_get_previouspc(space->cpu), vb_scrollx_hi);
}
static WRITE8_HANDLER(vb_scrollx_lo_w)
{
vb_scrollx_lo = data;
//logerror("%04x: vb_scrollx_lo =%d\n",cpu_get_previouspc(space->cpu), vb_scrollx_lo);
}
static ADDRESS_MAP_START( readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x0fff) AM_READ(SMH_RAM)
AM_RANGE(0x1000, 0x1000) AM_READ_PORT("P1")
@ -170,20 +230,13 @@ static ADDRESS_MAP_START( vball2pj_readmem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x8000, 0xffff) AM_READ(SMH_ROM)
ADDRESS_MAP_END
static WRITE8_HANDLER(vb_scrollx_lo_w)
{
vb_scrollx_lo = data;
//logerror("%04x: vb_scrollx_lo =%d\n",cpu_get_previouspc(space->cpu), vb_scrollx_lo);
}
//Cheaters note: Scores are stored in ram @ 0x57-0x58 (though the space is used for other things between matches)
static ADDRESS_MAP_START( writemem, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x07ff) AM_WRITE(SMH_RAM)
AM_RANGE(0x0800, 0x08ff) AM_WRITE(SMH_RAM) AM_BASE(&spriteram) AM_SIZE(&spriteram_size)
AM_RANGE(0x1008, 0x1008) AM_WRITE(vb_scrollx_hi_w)
AM_RANGE(0x1009, 0x1009) AM_WRITE(vb_bankswitch_w)
AM_RANGE(0x100a, 0x100a) AM_WRITE(SMH_RAM)
AM_RANGE(0x100b, 0x100b) AM_WRITE(SMH_RAM) //Counts from 0 to 7 continuously
AM_RANGE(0x100a, 0x100b) AM_WRITE(vball_irq_ack_w) /* is there a scanline counter here? */
AM_RANGE(0x100c, 0x100c) AM_WRITE(vb_scrollx_lo_w)
AM_RANGE(0x100d, 0x100d) AM_WRITE(cpu_sound_command_w)
AM_RANGE(0x100e, 0x100e) AM_WRITE(SMH_RAM) AM_BASE(&vb_scrolly_lo)
@ -369,6 +422,7 @@ static GFXDECODE_START( vb )
GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 128, 8 ) /* 16x16 sprites */
GFXDECODE_END
static void vball_irq_handler(running_machine *machine, int irq)
{
cpu_set_input_line(machine->cpu[1], 0 , irq ? ASSERT_LINE : CLEAR_LINE );
@ -379,23 +433,22 @@ static const ym2151_interface ym2151_config =
vball_irq_handler
};
static MACHINE_DRIVER_START( vball )
/* basic machine hardware */
MDRV_CPU_ADD("main", M6502, 2000000) /* 2 MHz - measured by guru but it makes the game far far too slow ?! */
MDRV_CPU_ADD("main", M6502, CPU_CLOCK) /* 2 MHz - measured by guru but it makes the game far far too slow ?! */
MDRV_CPU_PROGRAM_MAP(readmem,writemem)
MDRV_CPU_VBLANK_INT_HACK(vball_interrupt,32) /* ??1 IRQ every 8 visible scanlines, plus NMI for vblank?? */
MDRV_TIMER_ADD_SCANLINE("scantimer", vball_scanline, "main", 0, 1)
MDRV_CPU_ADD("audio", Z80, 3579545) /* 3.579545 MHz */
MDRV_CPU_PROGRAM_MAP(sound_readmem,sound_writemem)
/* video hardware */
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(1*8, 31*8-1, 1*8, 31*8-1) /* 240 x 240 */
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 384, 0, 256, 272, 8, 248) /* based on ddragon driver */
MDRV_GFXDECODE(vb)
MDRV_PALETTE_LENGTH(256)
@ -418,41 +471,10 @@ static MACHINE_DRIVER_START( vball )
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( vball2pj )
MDRV_IMPORT_FROM(vball)
/* basic machine hardware */
MDRV_CPU_ADD("main", M6502, 2000000) /* 2.0 MHz */
MDRV_CPU_MODIFY("main")
MDRV_CPU_PROGRAM_MAP(vball2pj_readmem,writemem)
MDRV_CPU_VBLANK_INT_HACK(vball_interrupt,32) /* ??1 IRQ every 8 visible scanlines, plus NMI for vblank?? */
MDRV_CPU_ADD("audio", Z80, 3579545) /* 3.579545 MHz */
MDRV_CPU_PROGRAM_MAP(sound_readmem,sound_writemem)
/* video hardware */
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(1*8, 31*8-1, 1*8, 31*8-1) /* 240 x 240 */
MDRV_GFXDECODE(vb)
MDRV_PALETTE_LENGTH(256)
MDRV_VIDEO_START(vb)
MDRV_VIDEO_UPDATE(vb)
/* sound hardware */
MDRV_SPEAKER_STANDARD_STEREO("left", "right")
MDRV_SOUND_ADD("ym", YM2151, 3579545)
MDRV_SOUND_CONFIG(ym2151_config)
MDRV_SOUND_ROUTE(0, "left", 0.60)
MDRV_SOUND_ROUTE(1, "right", 0.60)
MDRV_SOUND_ADD("oki", OKIM6295, 1056000)
MDRV_SOUND_CONFIG(okim6295_interface_pin7high)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "left", 1.0)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "right", 1.0)
MACHINE_DRIVER_END

View File

@ -278,12 +278,6 @@ static TIMER_DEVICE_CALLBACK( wwfsstar_scanline )
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
cpu_set_input_line(timer->machine->cpu[0], 6, ASSERT_LINE);
}
/* Adjust for next scanline */
if (++scanline >= video_screen_get_height(timer->machine->primary_screen))
{
scanline = 0;
}
}
static CUSTOM_INPUT( wwfsstar_vblank_r )

View File

@ -361,12 +361,6 @@ static TIMER_DEVICE_CALLBACK( wwfwfest_scanline )
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
cpu_set_input_line(timer->machine->cpu[0], 3, ASSERT_LINE);
}
/* Adjust for next scanline */
if (++scanline >= video_screen_get_height(timer->machine->primary_screen))
{
scanline = 0;
}
}
/*******************************************************************************

View File

@ -147,6 +147,11 @@ TODO:
#include "cpu/m6805/m6805.h"
#include "sound/2203intf.h"
#define MASTER_CLOCK XTAL_12MHz
#define CPU_CLOCK MASTER_CLOCK / 8
#define MCU_CLOCK MASTER_CLOCK / 4
#define PIXEL_CLOCK MASTER_CLOCK / 2
static UINT8 *xain_sharedram;
static int vblank;
@ -164,6 +169,66 @@ WRITE8_HANDLER( xain_flipscreen_w );
extern UINT8 *xain_charram, *xain_bgram0, *xain_bgram1, xain_pri;
/*
Based on the Solar Warrior schematics, vertical timing counts as follows:
08,09,0A,0B,...,FC,FD,FE,FF,E8,E9,EA,EB,...,FC,FD,FE,FF,
08,09,....
Thus, it counts from 08 to FF, then resets to E8 and counts to FF again.
This gives (256 - 8) + (256 - 232) = 248 + 24 = 272 total scanlines.
VBLK is signalled starting when the counter hits F8, and continues through
the reset to E8 and through until the next reset to 08 again.
Since MAME's video timing is 0-based, we need to convert this.
*/
INLINE int scanline_to_vcount(int scanline)
{
int vcount = scanline + 8;
if (vcount < 0x100)
return vcount;
else
return (vcount - 0x18) | 0x100;
}
static TIMER_DEVICE_CALLBACK( xain_scanline )
{
int scanline = param;
int screen_height = video_screen_get_height(timer->machine->primary_screen);
int vcount_old = scanline_to_vcount((scanline == 0) ? screen_height - 1 : scanline - 1);
int vcount = scanline_to_vcount(scanline);
/* update to the current point */
if (scanline > 0)
{
video_screen_update_partial(timer->machine->primary_screen, scanline - 1);
}
/* FIRQ (IMS) fires every on every 8th scanline (except 0) */
if (!(vcount_old & 8) && (vcount & 8))
{
cpu_set_input_line(timer->machine->cpu[0], M6809_FIRQ_LINE, ASSERT_LINE);
}
/* NMI fires on scanline 248 (VBL) and is latched */
if (vcount == 0xf8)
{
cpu_set_input_line(timer->machine->cpu[0], INPUT_LINE_NMI, ASSERT_LINE);
}
/* VBLANK input bit is held high from scanlines 248-255 */
if (vcount >= 248-1) // -1 is a hack - see notes above
{
vblank = 1;
}
else
{
vblank = 0;
}
}
static READ8_HANDLER( xain_sharedram_r )
{
return xain_sharedram[offset];
@ -248,24 +313,6 @@ static CUSTOM_INPUT( xain_vblank_r )
return vblank;
}
static INTERRUPT_GEN( xain_interrupt )
{
int scanline = 255 - cpu_getiloops(device);
/* FIRQ (IMS) fires every on every 8th scanline (except 0) */
if (scanline & 0x08)
cpu_set_input_line(device, M6809_FIRQ_LINE, ASSERT_LINE);
/* NMI fires on scanline 248 (VBL) and is latched */
if (scanline == 248)
cpu_set_input_line(device, INPUT_LINE_NMI, ASSERT_LINE);
/* VBLANK input bit is held high from scanlines 248-255 */
if (scanline >= 248-1) // -1 is a hack - see notes above
vblank = 1;
else
vblank = 0;
}
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x1fff) AM_READWRITE(xain_sharedram_r, xain_sharedram_w) AM_BASE(&xain_sharedram)
@ -293,7 +340,7 @@ static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x3c00, 0x3dff) AM_WRITE(paletteram_xxxxBBBBGGGGRRRR_split1_w) AM_BASE(&paletteram)
AM_RANGE(0x3e00, 0x3fff) AM_WRITE(paletteram_xxxxBBBBGGGGRRRR_split2_w) AM_BASE(&paletteram_2)
AM_RANGE(0x4000, 0x7fff) AM_READ(SMH_BANK1)
AM_RANGE(0x4000, 0xffff) AM_ROM
AM_RANGE(0x8000, 0xffff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cpu_map_B, ADDRESS_SPACE_PROGRAM, 8 )
@ -302,7 +349,7 @@ static ADDRESS_MAP_START( cpu_map_B, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x2800, 0x2800) AM_WRITE(xain_irqB_clear_w)
AM_RANGE(0x3000, 0x3000) AM_WRITE(xainCPUB_bankswitch_w)
AM_RANGE(0x4000, 0x7fff) AM_READ(SMH_BANK2)
AM_RANGE(0x4000, 0xffff) AM_ROM
AM_RANGE(0x8000, 0xffff) AM_ROM
ADDRESS_MAP_END
#if 0
@ -322,6 +369,7 @@ static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x4000, 0xffff) AM_ROM
ADDRESS_MAP_END
static INPUT_PORTS_START( xsleena )
PORT_START("P1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
@ -399,7 +447,6 @@ static INPUT_PORTS_START( xsleena )
INPUT_PORTS_END
static const gfx_layout charlayout =
{
8,8,
@ -430,7 +477,6 @@ static GFXDECODE_START( xain )
GFXDECODE_END
/* handler called by the 2203 emulator when the internal timers cause an IRQ */
static void irqhandler(running_machine *machine, int irq)
{
@ -447,30 +493,29 @@ static const ym2203_interface ym2203_config =
irqhandler
};
static MACHINE_START( xsleena )
{
const address_space *space = cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_PROGRAM);
const address_space *space_main = cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_PROGRAM);
const address_space *space_sub = cpu_get_address_space(machine->cpu[1], ADDRESS_SPACE_PROGRAM);
/* initialize the bank pointers */
xainCPUA_bankswitch_w(space,0,0);
xainCPUB_bankswitch_w(space,0,0);
xainCPUA_bankswitch_w(space_main,0,0);
xainCPUB_bankswitch_w(space_sub,0,0);
}
static MACHINE_DRIVER_START( xsleena )
/* basic machine hardware */
MDRV_CPU_ADD("main", M6809, 1500000) /* Confirmed 1.5MHz */
MDRV_CPU_ADD("main", M6809, CPU_CLOCK) /* Confirmed 1.5MHz */
MDRV_CPU_PROGRAM_MAP(main_map,0)
MDRV_CPU_VBLANK_INT_HACK(xain_interrupt,256)
MDRV_TIMER_ADD_SCANLINE("scantimer", xain_scanline, "main", 0, 1)
MDRV_CPU_ADD("sub", M6809, 1500000) /* Confirmed 1.5MHz */
MDRV_CPU_ADD("sub", M6809, CPU_CLOCK) /* Confirmed 1.5MHz */
MDRV_CPU_PROGRAM_MAP(cpu_map_B,0)
MDRV_CPU_ADD("audio", M6809, 1500000) /* Confirmed 1.5MHz */
MDRV_CPU_ADD("audio", M6809, CPU_CLOCK) /* Confirmed 1.5MHz */
MDRV_CPU_PROGRAM_MAP(sound_map,0)
// MDRV_CPU_ADD("mcu", M68705, 3000000) /* Confirmed 3MHz */
// MDRV_CPU_ADD("mcu", M68705, MCU_CLOCK) /* Confirmed 3MHz */
// MDRV_CPU_PROGRAM_MAP(mcu_map,0)
MDRV_MACHINE_START(xsleena)
@ -479,11 +524,8 @@ static MACHINE_DRIVER_START( xsleena )
/* video hardware */
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(57)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(32*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 384, 0, 256, 272, 8, 248) /* based on ddragon driver */
MDRV_GFXDECODE(xain)
MDRV_PALETTE_LENGTH(512)
@ -509,7 +551,6 @@ static MACHINE_DRIVER_START( xsleena )
MACHINE_DRIVER_END
/***************************************************************************
Game driver(s)
@ -676,7 +717,6 @@ ROM_START( solarwar )
ROM_END
static DRIVER_INIT( xsleena )
{
UINT8 *RAM = memory_region(machine, "main");
@ -704,7 +744,6 @@ static DRIVER_INIT( solarwar )
}
GAME( 1986, xsleena, 0, xsleena, xsleena, xsleena, ROT0, "Technos", "Xain'd Sleena", 0 )
GAME( 1986, xsleenab, xsleena, xsleena, xsleena, 0, ROT0, "bootleg", "Xain'd Sleena (bootleg)", 0 )
GAME( 1986, solarwar, xsleena, xsleena, xsleena, solarwar, ROT0, "[Technos] Taito (Memetron license)", "Solar-Warrior", 0 )

View File

@ -7,6 +7,7 @@ extern int vb_scrollx_hi;
extern int vb_scrolly_hi;
extern int vb_scrollx_lo;
extern int vball_gfxset;
extern int scrollx[256];
VIDEO_START( vb );
VIDEO_UPDATE( vb );
@ -15,5 +16,3 @@ void vb_spprombank_w(running_machine *machine, int bank);
WRITE8_HANDLER( vb_attrib_w );
WRITE8_HANDLER( vb_videoram_w );
void vb_mark_all_dirty(void);
INTERRUPT_GEN( vball_interrupt );

View File

@ -14,6 +14,7 @@
int vb_scrollx_hi=0;
int vb_scrollx_lo=0;
int vb_scrolly_hi=0;
int scrollx[256];
UINT8 *vb_scrolly_lo;
UINT8 *vb_videoram;
@ -23,7 +24,6 @@ static int vb_bgprombank=0xff;
static int vb_spprombank=0xff;
static tilemap *bg_tilemap;
static int scrollx[32];
/***************************************************************************
@ -168,7 +168,7 @@ VIDEO_UPDATE( vb )
tilemap_set_scrolly(bg_tilemap,0,vb_scrolly_hi + *vb_scrolly_lo);
/*To get linescrolling to work properly, we must ignore the 1st two scroll values, no idea why! -SJE */
for (i = 2;i < 32;i++) {
for (i = 2; i < 256; i++) {
tilemap_set_scrollx(bg_tilemap,i,scrollx[i-2]);
//logerror("scrollx[%d] = %d\n",i,scrollx[i]);
}
@ -176,18 +176,3 @@ VIDEO_UPDATE( vb )
draw_sprites(screen->machine,bitmap,cliprect);
return 0;
}
/*I don't really understand what the proper timing of this should be,
but after TONS of testing, the tilemap individual line scrolling works as long as flip screen is not set -SJE
*/
INTERRUPT_GEN( vball_interrupt )
{
int line = 31 - cpu_getiloops(device);
if (line < 13)
cpu_set_input_line(device, M6502_IRQ_LINE, HOLD_LINE);
else if (line == 13)
cpu_set_input_line(device, INPUT_LINE_NMI, PULSE_LINE);
//save the scroll x register value
if(line<32) scrollx[31-line] = (vb_scrollx_hi + vb_scrollx_lo+4);
}