More System 1 stuff, in addition to what was before:

* accurate collision detection in all games
 * correct full memory maps
 * hooked up 8255 and Z80 PIO correctly
 * unified many hacked variants into common hardware models
 * proper mixing using the mixing PROM
 * converted to tilemaps
 * fixed shtngmst sprites
 * correct Z80 timing
 * proper sound interrupt signaling and feedback
 * full description of video hardware

We now have:
 * proper input hookup in dakkochn
 * cleaned up rendering code
 * fixed cocktail mode in pretty much all games
 * fixed stuck sprites in some games
 * partial 8751 simulation for choplift
 * proper global muting (attract sound off works in older games)
This commit is contained in:
Aaron Giles 2009-04-09 15:53:51 +00:00
parent c9626a557a
commit b6af00c0ae
3 changed files with 474 additions and 342 deletions

View File

@ -7,8 +7,6 @@ driver by Jarek Parchanski, Nicola Salmoria, Mirko Buffoni
Issues:
* pitfall2 - missing title
* wmatch - stuck sprites
* what is P-0??
Up'n Down, Mister Viking, Flicky, SWAT, Water Match and Bull Fight are known
@ -18,9 +16,7 @@ DIP locations verified from manual for:
- wboy
- choplift
TODO: - background is misplaced in wbmlju
- sprites stick in Pitfall II
- remove patch in nobb if possible and fully understand the
TODO: - remove patch in nobb if possible and fully understand the
ports involved in the protection
*******************************************************************************
@ -211,12 +207,13 @@ Notes:
#define SOUND_CLOCK XTAL_8MHz
static void (*i8751_reset)(running_machine *machine);
static void (*i8751_run)(running_machine *machine, int init);
static void (*videomode_custom)(running_machine *machine, UINT8 data, UINT8 prevdata);
static UINT8 *system1_ram;
static UINT8 dakkochn_mux_data;
static UINT8 bank_bits;
static UINT8 videomode_prev;
static UINT8 i8751_active;
@ -361,14 +358,27 @@ static MACHINE_START( system1 )
memory_set_bank(machine, 1, 0);
z80_set_cycle_tables(cputag_get_cpu(machine, "maincpu"), cc_op, cc_cb, cc_ed, cc_xy, cc_xycb, cc_ex);
state_save_register_global(machine, dakkochn_mux_data);
state_save_register_global(machine, videomode_prev);
}
static MACHINE_RESET( system1 )
{
dakkochn_mux_data = 0;
if (i8751_reset != NULL)
(*i8751_reset)(machine);
i8751_active = FALSE;
if (i8751_run != NULL)
(*i8751_run)(machine, TRUE);
}
static INTERRUPT_GEN( vblank_irq )
{
irq0_line_hold(device);
if (i8751_run != NULL && i8751_active)
(*i8751_run)(device->machine, FALSE);
}
@ -379,13 +389,27 @@ static MACHINE_RESET( system1 )
*
*************************************/
static void choplift_i8751_reset(running_machine *machine)
static void choplift_i8751_run(running_machine *machine, int init)
{
const device_config *ppi = devtag_get_device(machine, "ppi");
if (init)
{
const device_config *ppi = devtag_get_device(machine, "ppi");
/* the 8751 seems to do the 8255 initialization among other things */
ppi8255_w(ppi, 3, 0xc0);
ppi8255_w(ppi, 2, 0x00);
/* the 8751 seems to do the 8255 initialization among other things */
ppi8255_w(ppi, 3, 0xc0);
ppi8255_w(ppi, 2, 0x00);
}
else
{
const UINT8 *rom = memory_region(machine, "maincpu");
system1_ram[0x88] = 0x01;
system1_ram[0x89] = 0xff;
memcpy(&system1_ram[0x90], &rom[0x1f8e], 16);
videoram[0x740] = 0x01;
videoram[0x742] = 0x01;
videoram[0x744] = 0x01;
videoram[0x746] = 0x01;
}
}
@ -436,23 +460,71 @@ static WRITE8_HANDLER(mcuenable_hack_w)
*
*************************************/
static void bank44_custom_w(running_machine *machine, UINT8 data, UINT8 prevdata)
{
/* bank bits are bits 6 and 2 */
memory_set_bank(machine, 1, ((data & 0x40) >> 5) | ((data & 0x04) >> 2));
}
static void bank0c_custom_w(running_machine *machine, UINT8 data, UINT8 prevdata)
{
/* bank bits are bits 3 and 2 */
memory_set_bank(machine, 1, (data & 0x0c) >> 2);
}
static WRITE8_HANDLER( videomode_w )
{
int curbit, accum;
/* find the appropriate bits in the data and update the bank */
accum = 0;
for (curbit = 7; curbit >= 0; curbit--)
if (bank_bits & (1 << curbit))
accum = (accum << 1) | ((data >> curbit) & 1);
memory_set_bank(space->machine, 1, accum);
if ((data & 0x40) && !(videomode_prev & 0x40))
i8751_active = TRUE;
/* handle any custom banking or other stuff */
if (videomode_custom != NULL)
(*videomode_custom)(space->machine, data, videomode_prev);
videomode_prev = data;
/* bit 0 is for the coin counters */
coin_counter_w(0, data & 1);
/* remaining signals are video-related */
system1_videomode_w(space, 0, data);
}
/*************************************
*
* DakkoChan House custom inputs
*
*************************************/
static CUSTOM_INPUT( dakkochn_mux_data_r )
{
static const char *ports[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6" };
return input_port_read(field->port->machine, ports[dakkochn_mux_data]);
}
static CUSTOM_INPUT( dakkochn_mux_status_r )
{
/* reads from here indicate which mux port is selected */
return 1 << (dakkochn_mux_data);
}
static void dakkochn_custom_w(running_machine *machine, UINT8 data, UINT8 prevdata)
{
/* bit 1 toggling on clocks the mux; we store the previous state in the high bit of dakkochn_mux_data */
if ((data & 0x02) && !(prevdata & 0x02))
dakkochn_mux_data = (dakkochn_mux_data + 1) % 7;
/* remaining stuff acts like bank0c */
bank0c_custom_w(machine, data, prevdata);
}
/*************************************
*
* Sound I/O
@ -462,8 +534,9 @@ static WRITE8_HANDLER( videomode_w )
static WRITE8_DEVICE_HANDLER( sound_control_w )
{
/* bit 0 = MUTE */
sound_global_enable(~(data & 1));
/* bit 6 = /P-0??? */
/* bit 6 = feedback from sound board that read occurrred */
/* bit 7 controls the sound CPU's NMI line */
cputag_set_input_line(device->machine, "soundcpu", INPUT_LINE_NMI, (data & 0x80) ? CLEAR_LINE : ASSERT_LINE);
@ -621,8 +694,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x7fff) AM_ROM
AM_RANGE(0x8000, 0x87ff) AM_MIRROR(0x1800) AM_RAM
AM_RANGE(0xa000, 0xa003) AM_MIRROR(0x1ffc) AM_DEVWRITE("sn1", sn76496_w) /* Choplifter writes to the four addresses */
AM_RANGE(0xc000, 0xc003) AM_MIRROR(0x1ffc) AM_DEVWRITE("sn2", sn76496_w) /* in sequence */
AM_RANGE(0xa000, 0xa003) AM_MIRROR(0x1fff) AM_DEVWRITE("sn1", sn76496_w)
AM_RANGE(0xc000, 0xc003) AM_MIRROR(0x1fff) AM_DEVWRITE("sn2", sn76496_w)
AM_RANGE(0xe000, 0xe000) AM_MIRROR(0x1fff) AM_READ(sound_data_r)
ADDRESS_MAP_END
@ -1750,13 +1823,13 @@ static INPUT_PORTS_START( dakkochn )
PORT_INCLUDE( choplift )
PORT_MODIFY("P1")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(dakkochn_mux_data_r, NULL)
PORT_MODIFY("P2")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(dakkochn_mux_status_r, NULL)
PORT_MODIFY("SYSTEM")
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) //start 1 & 2 not connected.
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) /* start 1 & 2 not connected. */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
/*TODO: Dip-Switches */
@ -1783,9 +1856,6 @@ static INPUT_PORTS_START( dakkochn )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("KEY0")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_A )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_B )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_MAHJONG_C )
@ -1793,21 +1863,21 @@ static INPUT_PORTS_START( dakkochn )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_LAST_CHANCE )
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY2")
PORT_START("KEY1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_E )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_F )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_MAHJONG_G )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_MAHJONG_H )
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY3")
PORT_START("KEY2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_I )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_J )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_MAHJONG_K )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_MAHJONG_L )
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY4")
PORT_START("KEY3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_M )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_N )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_MAHJONG_CHI )
@ -1815,16 +1885,19 @@ static INPUT_PORTS_START( dakkochn )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_MAHJONG_FLIP_FLOP )
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY5")
PORT_START("KEY4")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_BET )
PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY6")
PORT_START("KEY5")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_MAHJONG_KAN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_MAHJONG_REACH )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_MAHJONG_RON )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("KEY6")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
/*
@ -1934,7 +2007,7 @@ static MACHINE_DRIVER_START( sys1ppi )
MDRV_CPU_ADD("maincpu", Z80, MASTER_CLOCK) /* not really, see notes above */
MDRV_CPU_PROGRAM_MAP(system1_map,0)
MDRV_CPU_IO_MAP(system1_ppi_io_map,0)
MDRV_CPU_VBLANK_INT("screen", irq0_line_hold)
MDRV_CPU_VBLANK_INT("screen", vblank_irq)
MDRV_CPU_ADD("soundcpu", Z80, SOUND_CLOCK/2)
MDRV_CPU_PROGRAM_MAP(sound_map,0)
@ -1946,7 +2019,7 @@ static MACHINE_DRIVER_START( sys1ppi )
MDRV_PPI8255_ADD("ppi", ppi_interface)
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE)// hw collisions
MDRV_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE) /* needed for proper hardware collisions */
MDRV_SCREEN_ADD("screen", RASTER)
MDRV_SCREEN_REFRESH_RATE(60)
@ -2007,31 +2080,25 @@ MACHINE_DRIVER_END
/* main CPU hacked speed */
static MACHINE_DRIVER_START( pitfall2 )
MDRV_IMPORT_FROM( sys1pio )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys1pio )
MDRV_CPU_REPLACE( "maincpu", Z80, 3600000 )/* should be 4 MHz but that value makes the title screen disappear */
MACHINE_DRIVER_END
/* alternate program map with RAM/collision swapped */
static MACHINE_DRIVER_START( nob )
MDRV_IMPORT_FROM( sys1ppis )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys1ppi )
MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(nobo_map,0)
/* video hardware */
MDRV_SCREEN_MODIFY("screen")
MDRV_SCREEN_VISIBLE_AREA(1*8, 31*8-1, 0*8, 28*8-1)
MACHINE_DRIVER_END
/* system2 video */
static MACHINE_DRIVER_START( sys2 )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys1ppi )
/* video hardware */
@ -2039,9 +2106,8 @@ static MACHINE_DRIVER_START( sys2 )
MDRV_VIDEO_UPDATE(system2)
MACHINE_DRIVER_END
/* system 2 with small screen */
static MACHINE_DRIVER_START( sys2s )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys2 )
/* video hardware */
@ -2051,8 +2117,6 @@ MACHINE_DRIVER_END
/* system2 with rowscroll */
static MACHINE_DRIVER_START( sys2row )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys2 )
/* video hardware */
@ -2061,8 +2125,6 @@ MACHINE_DRIVER_END
/* rowscroll with small screen */
static MACHINE_DRIVER_START( sys2rows )
/* basic machine hardware */
MDRV_IMPORT_FROM( sys2row )
/* video hardware */
@ -4413,9 +4475,9 @@ ROM_END
*
*************************************/
static DRIVER_INIT( bank00 ) { i8751_reset = NULL; bank_bits = 0x00; }
static DRIVER_INIT( bank44 ) { i8751_reset = NULL; bank_bits = 0x44; }
static DRIVER_INIT( bank0c ) { i8751_reset = NULL; bank_bits = 0x0c; }
static DRIVER_INIT( bank00 ) { i8751_run = NULL; videomode_custom = NULL; }
static DRIVER_INIT( bank44 ) { i8751_run = NULL; videomode_custom = bank44_custom_w; }
static DRIVER_INIT( bank0c ) { i8751_run = NULL; videomode_custom = bank0c_custom_w; }
static DRIVER_INIT( regulus ) { DRIVER_INIT_CALL(bank00); regulus_decode(machine, "maincpu"); }
static DRIVER_INIT( mrviking ) { DRIVER_INIT_CALL(bank00); mrviking_decode(machine, "maincpu"); }
@ -4444,70 +4506,19 @@ static DRIVER_INIT( wbml ) { DRIVER_INIT_CALL(bank0c); mc8123_decrypt_rom(machi
static DRIVER_INIT( ufosensi ) { DRIVER_INIT_CALL(bank0c); mc8123_decrypt_rom(machine, "maincpu", "key", 1, 4); }
static DRIVER_INIT( wboysys2 ) { DRIVER_INIT_CALL(bank0c); astrofl_decode(machine, "maincpu"); }
static UINT8 dakkochn_control;
/*
This game doesn't seem to have any mux writes, so I'm assuming that the mux does HW auto-incrementing.
I need schematics to understand how it's properly mapped anyway, because it could be for example tied
with vblank/video bits.
The program flow is:
I/O $00 R
I/O $15 W 0xe
I/O $15 W 0xc
I/O $00 R
I/O $15 W 0xe
(and so on)
*/
static READ8_HANDLER( dakkochn_port_00_r )
{
static UINT8 res;
switch(dakkochn_mux_data)
{
case 0: res = input_port_read(space->machine, "KEY0"); break;
case 1: res = input_port_read(space->machine, "KEY1"); break;
case 2: res = input_port_read(space->machine, "KEY2"); break;
case 3: res = input_port_read(space->machine, "KEY3"); break;
case 4: res = input_port_read(space->machine, "KEY4"); break;
case 5: res = input_port_read(space->machine, "KEY5"); break;
case 6: res = input_port_read(space->machine, "KEY6"); break;
}
dakkochn_mux_data++;
if(dakkochn_mux_data >= 7)
dakkochn_mux_data = 0;
return res;
}
static READ8_HANDLER( dakkochn_port_03_r )
{
return 0;
}
static READ8_HANDLER( dakkochn_port_04_r )
{
return 0;
}
static WRITE8_HANDLER( dakkochn_port_15_w )
{
dakkochn_control = data; // check if any control multiplex bits are in here!
videomode_w(space,offset,data);
}
static DRIVER_INIT( dakkochn )
{
DRIVER_INIT_CALL(bank0c);
videomode_custom = dakkochn_custom_w;
mc8123_decrypt_rom(machine, "maincpu", "proms", 1, 4);
mc8123_decrypt_rom(machine, "maincpu", "key", 1, 4);
memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x00, 0x00, 0, 0, dakkochn_port_00_r);
memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x03, 0x03, 0, 0, dakkochn_port_03_r);
memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x04, 0x04, 0, 0, dakkochn_port_04_r);
// memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x00, 0x00, 0, 0, dakkochn_port_00_r);
// memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x03, 0x03, 0, 0, dakkochn_port_03_r);
// memory_install_read8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x04, 0x04, 0, 0, dakkochn_port_04_r);
memory_install_write8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x15, 0x15, 0, 0, dakkochn_port_15_w);
// memory_install_write8_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x15, 0x15, 0, 0, dakkochn_port_15_w);
}
@ -4607,7 +4618,7 @@ static DRIVER_INIT( bootlegb )
static DRIVER_INIT( choplift )
{
DRIVER_INIT_CALL(bank0c);
i8751_reset = choplift_i8751_reset;
i8751_run = choplift_i8751_run;
}
static DRIVER_INIT( shtngmst )
@ -4680,7 +4691,7 @@ GAME( 1986, wboyo, wboy, sys1pio, wboy, wboyo, ROT0, "Sega (
GAME( 1986, wboy3, wboy, sys1pio, wboy3, wboyo, ROT0, "Sega (Escape license)", "Wonder Boy (set 3, 315-5135)", GAME_SUPPORTS_SAVE )
GAME( 1986, wboy4, wboy, sys1pio, wboy, 4dwarrio, ROT0, "Sega (Escape license)", "Wonder Boy (315-5162, 4-D Warriors Conversion)", GAME_SUPPORTS_SAVE )
GAME( 1986, wboyu, wboy, sys1pio, wboyu, bank00, ROT0, "Sega (Escape license)", "Wonder Boy (not encrypted)", GAME_SUPPORTS_SAVE )
GAME( 1987, blockgal, 0, sys1pio, blockgal, blockgal, ROT90, "Sega / Vic Tokai", "Block Gal (MC-8123B, 317-0029)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE)
GAME( 1987, blockgal, 0, sys1pio, blockgal, blockgal, ROT90, "Sega / Vic Tokai", "Block Gal (MC-8123B, 317-0029)", GAME_SUPPORTS_SAVE)
/* PIO-based System 1 with ROM banking */
GAME( 1985, hvymetal, 0, sys1pio, hvymetal, hvymetal, ROT0, "Sega", "Heavy Metal (315-5135)", GAME_SUPPORTS_SAVE )
@ -4691,18 +4702,18 @@ GAME( 1986, brain, 0, sys1pio, brain, bank44, ROT0, "Corela
GAME( 1985, choplift, 0, sys2row, choplift, choplift, ROT0, "Sega", "Choplifter (8751 315-5151)", GAME_UNEMULATED_PROTECTION | GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1985, chopliftu, choplift, sys2row, choplift, bank0c, ROT0, "Sega", "Choplifter (unprotected)", GAME_SUPPORTS_SAVE )
GAME( 1985, chopliftbl, choplift, sys2row, choplift, bank0c, ROT0, "bootleg", "Choplifter (bootleg)", GAME_SUPPORTS_SAVE )
GAME( 1985, shtngmst, 0, sys2s, shtngmst, shtngmst, ROT0, "Sega", "Shooting Master (Rev A, 8751 315-5159a)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1985, shtngmst1, shtngmst, sys2s, shtngmst, shtngmst, ROT0, "Sega", "Shooting Master (8751 315-5159)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1985, shtngmsta, shtngmst, sys2s, shtngmst, shtngmst, ROT0, "Sega [EVG]", "Shooting Master (EVG, 8751 315-5159)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1986, gardiab, gardia, sys2, gardia, gardiab, ROT270, "bootleg", "Gardia (317-0007?, bootleg)", GAME_IMPERFECT_GRAPHICS | GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1985, shtngmst, 0, sys2s, shtngmst, shtngmst, ROT0, "Sega", "Shooting Master (Rev A, 8751 315-5159a)", GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1985, shtngmst1, shtngmst, sys2s, shtngmst, shtngmst, ROT0, "Sega", "Shooting Master (8751 315-5159)", GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1985, shtngmsta, shtngmst, sys2s, shtngmst, shtngmst, ROT0, "Sega [EVG]", "Shooting Master (EVG, 8751 315-5159)", GAME_SUPPORTS_SAVE | GAME_NOT_WORKING )
GAME( 1986, gardiab, gardia, sys2, gardia, gardiab, ROT270, "bootleg", "Gardia (317-0007?, bootleg)", GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE )
GAME( 1986, wboysys2, wboy, sys2, wboysys2, wboysys2, ROT0, "Sega (Escape license)", "Wonder Boy (system 2)", GAME_SUPPORTS_SAVE )
GAME( 1987, tokisens, 0, sys2, tokisens, bank0c, ROT90, "Sega", "Toki no Senshi - Chrono Soldier", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1987, wbml, 0, sys2, wbml, wbml, ROT0, "Sega / Westone", "Wonder Boy in Monster Land (Japan New Ver., MC-8123, 317-0043)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1987, wbmljo, wbml, sys2, wbml, wbml, ROT0, "Sega / Westone", "Wonder Boy in Monster Land (Japan Old Ver., MC-8123, 317-0043)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1987, wbmljb, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (Japan not encrypted)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1987, wbmlb, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (English bootleg)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE)
GAME( 1987, wbmlbg, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (Galaxy Electronics English bootleg)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE)
GAME( 1987, dakkochn, 0, sys2, dakkochn, dakkochn, ROT0, "Whiteboard", "DakkoChan House (MC-8123, 317-0014)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE | GAME_IMPERFECT_GRAPHICS )
GAME( 1987, blockgalb, blockgal, sys2, blockgal, bootleg, ROT90, "bootleg", "Block Gal (bootleg)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE )
GAME( 1987, tokisens, 0, sys2, tokisens, bank0c, ROT90, "Sega", "Toki no Senshi - Chrono Soldier", GAME_SUPPORTS_SAVE )
GAME( 1987, wbml, 0, sys2, wbml, wbml, ROT0, "Sega / Westone", "Wonder Boy in Monster Land (Japan New Ver., MC-8123, 317-0043)", GAME_SUPPORTS_SAVE )
GAME( 1987, wbmljo, wbml, sys2, wbml, wbml, ROT0, "Sega / Westone", "Wonder Boy in Monster Land (Japan Old Ver., MC-8123, 317-0043)", GAME_SUPPORTS_SAVE )
GAME( 1987, wbmljb, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (Japan not encrypted)", GAME_SUPPORTS_SAVE )
GAME( 1987, wbmlb, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (English bootleg)", GAME_SUPPORTS_SAVE)
GAME( 1987, wbmlbg, wbml, sys2, wbml, bootlegb, ROT0, "bootleg", "Wonder Boy in Monster Land (Galaxy Electronics English bootleg)", GAME_SUPPORTS_SAVE)
GAME( 1987, dakkochn, 0, sys2, dakkochn, dakkochn, ROT0, "Whiteboard", "DakkoChan House (MC-8123, 317-0014)", GAME_SUPPORTS_SAVE )
GAME( 1987, blockgalb, blockgal, sys2, blockgal, bootleg, ROT90, "bootleg", "Block Gal (bootleg)", GAME_SUPPORTS_SAVE )
GAME( 1988, ufosensi, 0, sys2rows, ufosensi, ufosensi, ROT0, "Sega", "Ufo Senshi Yohko Chan (MC-8123, 317-0064)", GAME_SUPPORTS_SAVE )
GAME( 1988, ufosensib, ufosensi, sys2rows, ufosensi, bootlegb, ROT0, "bootleg", "Ufo Senshi Yohko Chan (not encrypted)", GAME_SUPPORTS_SAVE )

View File

@ -34,9 +34,8 @@
pixel data and sprite index. During rendering, collisions are
checked between sprites and if one is found a bit is set in a
special 32x32x1 collision RAM indiciating which pair of sprites
collided. Note that the sprite color is not stored in the line
buffer, but it retrieved when the line buffer is read out on the
following scanline using the stored sprite index.
collided. Note that the sprite color is derived directly from the
sprite index, giving each sprite its own set of 16 colors.
The 11-bit output from the two tilemaps (3 bits of pixel data,
6 bits of color, 2 bits of priority), plus the 9-bit output from
@ -51,7 +50,7 @@
9 bits of data from the appropriate source are used as a lookup
into a palette RAM, and the lookup PROM's low 2 bits are used as
the upper 2 bits of the palette RAM address, providing 512
independent colors for each souce.
independent colors for each source.
The upper 2 bits of the lookup PROM are used for an additional
mixer collision detection. Bit 2 indicates that a collision
@ -91,14 +90,111 @@ static bitmap_t *sprite_bitmap;
static UINT8 system1_video_mode;
static UINT8 wbml_videoram_bank;
static int system1_sprite_xoffset;
static UINT8 videoram_bank;
static tilemap *tilemap_page[8];
static UINT8 tilemap_pages;
/*************************************
*
* Tile callback
*
*************************************/
static TILE_GET_INFO( tile_get_info )
{
UINT8 *rambase = param;
UINT32 tiledata = rambase[tile_index*2+0] | (rambase[tile_index*2+1] << 8);
UINT32 code = ((tiledata >> 4) & 0x800) | (tiledata & 0x7ff);
UINT32 color = (tiledata >> 5) & 0xff;
SET_TILE_INFO(0, code, color, 0);
}
/*************************************
*
* Video startup
*
*************************************/
static void video_start_common(running_machine *machine, int pagecount)
{
int pagenum;
/* allocate memory for the collision arrays */
mix_collide = auto_malloc(64);
memset(mix_collide, 0, 64);
sprite_collide = auto_malloc(1024);
memset(sprite_collide, 0, 1024);
/* allocate memory for videoram */
tilemap_pages = pagecount;
videoram = auto_malloc(0x800 * pagecount);
memset(videoram, 0, 0x800 * pagecount);
/* create the tilemap pages */
for (pagenum = 0; pagenum < pagecount; pagenum++)
{
tilemap_page[pagenum] = tilemap_create(machine, tile_get_info, tilemap_scan_rows, 8,8, 32,32);
tilemap_set_transparent_pen(tilemap_page[pagenum], 0);
tilemap_set_user_data(tilemap_page[pagenum], videoram + 0x800 * pagenum);
}
/* allocate a temporary bitmap for sprite rendering */
sprite_bitmap = auto_bitmap_alloc(256, 256, BITMAP_FORMAT_INDEXED16);
/* register for save stats */
state_save_register_global(machine, system1_video_mode);
state_save_register_global(machine, mix_collide_summary);
state_save_register_global(machine, sprite_collide_summary);
state_save_register_global_pointer(machine, videoram, 0x800 * pagecount);
state_save_register_global_pointer(machine, mix_collide, 64);
state_save_register_global_pointer(machine, sprite_collide, 1024);
}
VIDEO_START( system1 )
{
video_start_common(machine, 2);
}
VIDEO_START( system2 )
{
video_start_common(machine, 8);
}
/*************************************
*
* Video control
*
*************************************/
WRITE8_HANDLER( system1_videomode_w )
{
if (data & 0x6e) logerror("videomode = %02x\n",data);
/* bit 4 is screen blank */
system1_video_mode = data;
/* bit 7 is flip screen */
flip_screen_set(space->machine, data & 0x80);
}
/*************************************
*
* Mixer collision I/O
*
*************************************/
READ8_HANDLER( system1_mixer_collision_r )
{
video_screen_update_now(space->machine->primary_screen);
@ -117,6 +213,14 @@ WRITE8_HANDLER( system1_mixer_collision_reset_w )
mix_collide_summary = 0;
}
/*************************************
*
* Sprite collision I/O
*
*************************************/
READ8_HANDLER( system1_sprite_collision_r )
{
video_screen_update_now(space->machine->primary_screen);
@ -136,15 +240,22 @@ WRITE8_HANDLER( system1_sprite_collision_reset_w )
}
/*************************************
*
* Video RAM access
*
*************************************/
READ8_HANDLER( system1_videoram_r )
{
offset |= 0x1000 * ((wbml_videoram_bank >> 1) % (tilemap_pages / 2));
offset |= 0x1000 * ((videoram_bank >> 1) % (tilemap_pages / 2));
return videoram[offset];
}
WRITE8_HANDLER( system1_videoram_w )
{
offset |= 0x1000 * ((wbml_videoram_bank >> 1) % (tilemap_pages / 2));
offset |= 0x1000 * ((videoram_bank >> 1) % (tilemap_pages / 2));
videoram[offset] = data;
tilemap_mark_tile_dirty(tilemap_page[offset / 0x800], (offset % 0x800) / 2);
@ -156,38 +267,43 @@ WRITE8_HANDLER( system1_videoram_w )
WRITE8_DEVICE_HANDLER( system1_videoram_bank_w )
{
wbml_videoram_bank = data;
videoram_bank = data;
}
/***************************************************************************
There are two kind of color handling: in the System 1 games, values in the
palette RAM are directly mapped to colors with the usual BBGGGRRR format;
in the System 2 ones (Choplifter, WBML, etc.), the value in the palette RAM
is a lookup offset for three palette PROMs in RRRRGGGGBBBB format.
It's hard to tell for sure because they use resistor packs, but here's
what I think the values are from measurment with a volt meter:
Blue: .250K ohms
Blue: .495K ohms
Green:.250K ohms
Green:.495K ohms
Green:.995K ohms
Red: .495K ohms
Red: .250K ohms
Red: .995K ohms
accurate to +/- .003K ohms.
***************************************************************************/
/*************************************
*
* Palette RAM access
*
*************************************/
WRITE8_HANDLER( system1_paletteram_w )
{
const UINT8 *color_prom = memory_region(space->machine, "palette");
int val,r,g,b;
/*
There are two kind of color handling: in the System 1 games, values in the
palette RAM are directly mapped to colors with the usual BBGGGRRR format;
in the System 2 ones (Choplifter, WBML, etc.), the value in the palette RAM
is a lookup offset for three palette PROMs in RRRRGGGGBBBB format.
It's hard to tell for sure because they use resistor packs, but here's
what I think the values are from measurment with a volt meter:
Blue: .250K ohms
Blue: .495K ohms
Green:.250K ohms
Green:.495K ohms
Green:.995K ohms
Red: .495K ohms
Red: .250K ohms
Red: .995K ohms
accurate to +/- .003K ohms.
*/
paletteram[offset] = data;
if (color_prom != NULL)
@ -225,192 +341,145 @@ WRITE8_HANDLER( system1_paletteram_w )
palette_set_color(space->machine,offset,MAKE_RGB(r,g,b));
}
static TILE_GET_INFO( tile_get_info )
{
UINT8 *rambase = param;
UINT32 tiledata = rambase[tile_index*2+0] | (rambase[tile_index*2+1] << 8);
UINT32 code = ((tiledata >> 4) & 0x800) | (tiledata & 0x7ff); /* Heavy Metal only */
UINT32 color = (tiledata >> 5) & 0xff;
SET_TILE_INFO(0, code, color, 0);
}
static void video_start_common(running_machine *machine, int pagecount)
{
int pagenum;
/* allocate memory for the collision arrays */
mix_collide = auto_malloc(64);
memset(mix_collide, 0, 64);
sprite_collide = auto_malloc(1024);
memset(sprite_collide, 0, 1024);
/* allocate memory for videoram */
tilemap_pages = pagecount;
videoram = auto_malloc(0x800 * pagecount);
memset(videoram, 0, 0x800 * pagecount);
/* create the tilemap pages */
for (pagenum = 0; pagenum < pagecount; pagenum++)
{
tilemap_page[pagenum] = tilemap_create(machine, tile_get_info, tilemap_scan_rows, 8,8, 32,32);
tilemap_set_transparent_pen(tilemap_page[pagenum], 0);
tilemap_set_user_data(tilemap_page[pagenum], videoram + 0x800 * pagenum);
}
/* allocate a temporary bitmap for sprite rendering */
sprite_bitmap = auto_bitmap_alloc(256, 256, BITMAP_FORMAT_INDEXED16);
state_save_register_global(machine, system1_video_mode);
state_save_register_global_pointer(machine, videoram, 0x800 * pagecount);
}
VIDEO_START( system1 )
{
video_start_common(machine, 2);
system1_sprite_xoffset = 1;
}
VIDEO_START( system2 )
{
video_start_common(machine, 8);
system1_sprite_xoffset = 1+7*2;
}
WRITE8_HANDLER( system1_videomode_w )
{
if (data & 0x6e) logerror("videomode = %02x\n",data);
/* bit 0 is coin counter */
coin_counter_w(0, data & 1);
/* bit 4 is screen blank */
system1_video_mode = data;
/* bit 7 is flip screen */
flip_screen_set(space->machine, data & 0x80);
}
INLINE void draw_sprite_pixel(bitmap_t *bitmap, int x, int y, int spr_number, int color)
{
UINT16 *destpix = BITMAP_ADDR16(bitmap, y, x);
int prevpix = *destpix;
if ((prevpix & 0x0f) != 0)
sprite_collide[(prevpix >> 11) + 32 * spr_number] = sprite_collide_summary = 1;
*destpix = color | (spr_number << 11);
}
static void draw_sprite(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, int spr_number)
/*************************************
*
* Sprite rendering
*
*************************************/
static void draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, int xoffset)
{
UINT32 gfxbanks = memory_region_length(machine, "sprites") / 0x8000;
const UINT8 *gfxbase = memory_region(machine, "sprites");
int flipscreen = flip_screen_get(machine);
int sy,row,height,src,bank;
UINT8 *sprite_base;
int sprite_palette_base;
INT16 skip; /* bytes to skip before drawing each row (can be negative) */
UINT8 *gfx;
int spritenum;
sprite_base = spriteram + 0x10 * spr_number;
src = sprite_base[SPR_GFXOFS_LO] + (sprite_base[SPR_GFXOFS_HI] << 8);
bank = 0x8000 * (((sprite_base[SPR_X_HI] & 0x80) >> 7) + ((sprite_base[SPR_X_HI] & 0x40) >> 5) + ((sprite_base[SPR_X_HI] & 0x20) >> 3));
bank &= (memory_region_length(machine, "sprites")-1); /* limit to the range of available ROMs */
skip = sprite_base[SPR_SKIP_LO] + (sprite_base[SPR_SKIP_HI] << 8);
height = sprite_base[SPR_Y_BOTTOM] - sprite_base[SPR_Y_TOP];
sprite_palette_base = 0x10 * spr_number;
sy = sprite_base[SPR_Y_TOP] + 1;
/* graphics region #2 contains the packed sprite data */
gfx = &memory_region(machine, "sprites")[bank];
for (row = 0;row < height;row++)
/* up to 32 sprites total */
for (spritenum = 0; spritenum < 32; spritenum++)
{
int x,x_flipped;
int y,y_flipped;
int src2;
const UINT8 *spritedata = &spriteram[spritenum * 0x10];
UINT16 srcaddr = spritedata[6] + (spritedata[7] << 8);
UINT16 stride = spritedata[4] + (spritedata[5] << 8);
UINT8 bank = ((spritedata[3] & 0x80) >> 7) | ((spritedata[3] & 0x40) >> 5) | ((spritedata[3] & 0x20) >> 3);
int xstart = ((spritedata[2] + (spritedata[3] << 8)) & 0x1ff) / 2 + xoffset;
int bottom = spritedata[1] + 1;
int top = spritedata[0] + 1;
UINT16 palettebase = spritenum * 0x10;
const UINT8 *gfxbankbase;
int x, y;
/* writing an 0xff into the first byte of sprite RAM seems to disable all sprites;
not sure if this applies to each sprite or only to the first one; see pitfall2
and wmatch for examples where this is done */
if (spritedata[0] == 0xff)
return;
src = src2 = src + skip;
x = sprite_base[SPR_X_LO] + ((sprite_base[SPR_X_HI] & 0x01) << 8) + system1_sprite_xoffset;
x_flipped = x;
y = y_flipped = sy+row;
/* clamp the bank to the size of the sprite ROMs */
bank %= gfxbanks;
gfxbankbase = gfxbase + bank * 0x8000;
/* flip sprites vertically */
if (flipscreen)
{
y_flipped = 258 - sy - height + row;
x_flipped = (252*2) - x;
int temp = top;
top = 256 - bottom;
bottom = 256 - temp;
}
x /= 2; /* the hardware has sub-pixel placement, it seems */
x_flipped /= 2;
while (1)
/* iterate over all rows of the sprite */
for (y = top; y < bottom; y++)
{
int color1,color2,data;
data = gfx[src2 & 0x7fff];
if (src & 0x8000)
UINT16 *destbase = BITMAP_ADDR16(bitmap, y, 0);
UINT16 curaddr;
int addrdelta;
/* advance by the row counter */
srcaddr += stride;
/* skip if outside of our clipping area */
if (y < cliprect->min_y || y > cliprect->max_y)
continue;
/* iterate over X */
addrdelta = (srcaddr & 0x8000) ? -1 : 1;
for (x = xstart, curaddr = srcaddr; ; x += 2, curaddr += addrdelta)
{
src2--;
color1 = data & 0x0f;
color2 = data >> 4;
UINT8 color1, color2;
UINT8 data;
data = gfxbankbase[curaddr & 0x7fff];
/* non-flipped case */
if (!(curaddr & 0x8000))
{
color1 = data >> 4;
color2 = data & 0x0f;
}
else
{
color1 = data & 0x0f;
color2 = data >> 4;
}
/* stop when we see color 0x0f */
if (color1 == 0x0f)
break;
/* draw if non-transparent */
if (color1 != 0)
{
int effx = flipscreen ? 255 - (x + 0) : (x + 0);
if (effx >= cliprect->min_x && effx <= cliprect->max_x)
{
int prevpix = destbase[effx];
if ((prevpix & 0x0f) != 0)
sprite_collide[((prevpix >> 4) & 0x1f) + 32 * spritenum] = sprite_collide_summary = 1;
destbase[effx] = color1 | palettebase;
}
}
/* stop when we see color 0x0f */
if (color2 == 0x0f)
break;
/* draw if non-transparent */
if (color2 != 0)
{
int effx = flipscreen ? 255 - (x + 1) : (x + 1);
if (effx >= cliprect->min_x && effx <= cliprect->max_x)
{
int prevpix = destbase[effx];
if ((prevpix & 0x0f) != 0)
sprite_collide[((prevpix >> 4) & 0x1f) + 32 * spritenum] = sprite_collide_summary = 1;
destbase[effx] = color2 | palettebase;
}
}
}
else
{
src2++;
color1 = data >> 4;
color2 = data & 0x0f;
}
if (color1 == 15) break;
if (color1 != 0 && x_flipped >= cliprect->min_x && x_flipped <= cliprect->max_x && y_flipped >= cliprect->min_y && y_flipped <= cliprect->max_y)
draw_sprite_pixel(bitmap,x_flipped,y_flipped,spr_number,sprite_palette_base+color1);
x++;
x_flipped += flipscreen ? -1 : 1;
if (color2 == 15) break;
if (color2 != 0 && x_flipped >= cliprect->min_x && x_flipped <= cliprect->max_x && y_flipped >= cliprect->min_y && y_flipped <= cliprect->max_y)
draw_sprite_pixel(bitmap,x_flipped,y_flipped,spr_number,sprite_palette_base+color2);
x++;
x_flipped += flipscreen ? -1 : 1;
}
}
}
static void draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect)
{
int spr_number,sprite_bottom_y,sprite_top_y;
UINT8 *sprite_base;
for (spr_number = 0;spr_number < 32;spr_number++)
{
sprite_base = spriteram + 0x10 * spr_number;
sprite_top_y = sprite_base[SPR_Y_TOP];
sprite_bottom_y = sprite_base[SPR_Y_BOTTOM];
if (sprite_bottom_y && (sprite_bottom_y-sprite_top_y > 0))
draw_sprite(machine, bitmap, cliprect, spr_number);
}
}
/*************************************
*
* Generic update code
*
*************************************/
static void video_update_common(const device_config *screen, bitmap_t *bitmap, const rectangle *cliprect, bitmap_t *fgpixmap, bitmap_t **bgpixmaps, const int *bgrowscroll, int bgyscroll)
static void video_update_common(const device_config *screen, bitmap_t *bitmap, const rectangle *cliprect, bitmap_t *fgpixmap, bitmap_t **bgpixmaps, const int *bgrowscroll, int bgyscroll, int spritexoffs)
{
const UINT8 *lookup = memory_region(screen->machine, "proms");
int x, y;
/* first clear the sprite bitmap and draw sprites within this area */
bitmap_fill(sprite_bitmap, cliprect, 0);
draw_sprites(screen->machine, sprite_bitmap, cliprect);
draw_sprites(screen->machine, sprite_bitmap, cliprect, spritexoffs);
/* iterate over rows */
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
{
@ -420,7 +489,7 @@ static void video_update_common(const device_config *screen, bitmap_t *bitmap, c
int bgy = (y + bgyscroll) & 0x1ff;
int bgxscroll = bgrowscroll[y / 8];
UINT16 *bgbase[2];
/* get the base of the left and right pixmaps for the effective background Y */
bgbase[0] = BITMAP_ADDR16(bgpixmaps[(bgy >> 8) * 2 + 0], bgy & 0xff, 0);
bgbase[1] = BITMAP_ADDR16(bgpixmaps[(bgy >> 8) * 2 + 1], bgy & 0xff, 0);
@ -445,7 +514,7 @@ static void video_update_common(const device_config *screen, bitmap_t *bitmap, c
/* compute collisions based on two of the PROM bits */
if (!(lookup_value & 4))
mix_collide[((lookup_value & 8) << 2) | (sprpix >> 11)] = mix_collide_summary = 1;
mix_collide[((lookup_value & 8) << 2) | ((sprpix >> 4) & 0x1f)] = mix_collide_summary = 1;
/* the lower 2 PROM bits select the palette and which pixels */
lookup_value &= 3;
@ -462,40 +531,84 @@ static void video_update_common(const device_config *screen, bitmap_t *bitmap, c
}
/*************************************
*
* Board-specific update front-ends
*
*************************************/
VIDEO_UPDATE( system1 )
{
bitmap_t *bgpixmaps[4], *fgpixmap;
int bgrowscroll[32];
int xscroll, yscroll;
int y;
/* all 4 background pages are the same, fixed to page 0 */
bgpixmaps[0] = bgpixmaps[1] = bgpixmaps[2] = bgpixmaps[3] = tilemap_get_pixmap(tilemap_page[0]);
/* foreground is fixed to page 1 */
fgpixmap = tilemap_get_pixmap(tilemap_page[1]);
/* get fixed scroll offsets */
xscroll = (videoram[0xffc] | (videoram[0xffd] << 8)) / 2 + 14;
yscroll = videoram[0xfbd];
/* adjust for flipping */
if (flip_screen_get(screen->machine))
{
xscroll = 279 - xscroll;
yscroll = 256 - yscroll;
}
/* fill in the row scroll table */
for (y = 0; y < 32; y++)
bgrowscroll[y] = (videoram[0xffc] | (videoram[0xffd] << 8)) / 2 + 14;
bgrowscroll[y] = xscroll;
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, bgrowscroll, videoram[0xfbd]);
/* common update */
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, bgrowscroll, yscroll, 0);
return 0;
}
VIDEO_UPDATE( system2 )
{
int flip = flip_screen_get(screen->machine);
int xscrolloffs = flip ? 0x7f6 : 0x7c0;
int yscrolloffs = flip ? 0x784 : 0x7ba;
bitmap_t *bgpixmaps[4], *fgpixmap;
int rowscroll[32];
int xscroll, yscroll;
int sprxoffset;
int y;
/* 4 independent background pages */
bgpixmaps[0] = tilemap_get_pixmap(tilemap_page[videoram[0x740] & 7]);
bgpixmaps[1] = tilemap_get_pixmap(tilemap_page[videoram[0x742] & 7]);
bgpixmaps[2] = tilemap_get_pixmap(tilemap_page[videoram[0x744] & 7]);
bgpixmaps[3] = tilemap_get_pixmap(tilemap_page[videoram[0x746] & 7]);
fgpixmap = tilemap_get_pixmap(tilemap_page[0]);
for (y = 0; y < 32; y++)
rowscroll[y] = (((videoram[xscrolloffs + 0] | (videoram[xscrolloffs + 1] << 8)) / 2) & 0xff) - 256 + 5;
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, rowscroll, videoram[yscrolloffs]);
/* foreground is fixed to page 0 */
fgpixmap = tilemap_get_pixmap(tilemap_page[0]);
/* get scroll offsets */
if (!flip_screen_get(screen->machine))
{
xscroll = (((videoram[0x7c0] | (videoram[0x7c1] << 8)) / 2) & 0xff) - 256 + 5;
yscroll = videoram[0x7ba];
sprxoffset = 7;
}
else
{
xscroll = 262+256 - ((((videoram[0x7f6] | (videoram[0x7f7] << 8)) / 2) & 0xff) - 256 + 5);
yscroll = 256+256 - videoram[0x784];
sprxoffset = -7;
}
/* fill in the row scroll table */
for (y = 0; y < 32; y++)
rowscroll[y] = xscroll;
/* common update */
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, rowscroll, yscroll, sprxoffset);
return 0;
}
@ -504,16 +617,33 @@ VIDEO_UPDATE( system2_rowscroll )
{
bitmap_t *bgpixmaps[4], *fgpixmap;
int rowscroll[32];
int yscroll;
int y;
/* 4 independent background pages */
bgpixmaps[0] = tilemap_get_pixmap(tilemap_page[videoram[0x740] & 7]);
bgpixmaps[1] = tilemap_get_pixmap(tilemap_page[videoram[0x742] & 7]);
bgpixmaps[2] = tilemap_get_pixmap(tilemap_page[videoram[0x744] & 7]);
bgpixmaps[3] = tilemap_get_pixmap(tilemap_page[videoram[0x746] & 7]);
fgpixmap = tilemap_get_pixmap(tilemap_page[0]);
for (y = 0; y < 32; y++)
rowscroll[y] = (((videoram[0x7c0 + y * 2] | (videoram[0x7c1 + y * 2] << 8)) / 2) & 0xff) - 256 + 5;
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, rowscroll, videoram[0x7ba]);
/* foreground is fixed to page 0 */
fgpixmap = tilemap_get_pixmap(tilemap_page[0]);
/* get scroll offsets */
if (!flip_screen_get(screen->machine))
{
for (y = 0; y < 32; y++)
rowscroll[y] = (((videoram[0x7c0 + y * 2] | (videoram[0x7c1 + y * 2] << 8)) / 2) & 0xff) - 256 + 5;
yscroll = videoram[0x7ba];
}
else
{
for (y = 0; y < 32; y++)
rowscroll[y] = 262+256 - ((((videoram[0x7fe - y * 2] | (videoram[0x7ff - y * 2] << 8)) / 2) & 0xff) - 256 + 5);
yscroll = 256+256 - videoram[0x784];
}
/* common update */
video_update_common(screen, bitmap, cliprect, fgpixmap, bgpixmaps, rowscroll, yscroll, 7);
return 0;
}

View File

@ -1,15 +1,6 @@
#ifndef _system1_H_
#define _system1_H_
#define SPR_Y_TOP 0
#define SPR_Y_BOTTOM 1
#define SPR_X_LO 2
#define SPR_X_HI 3
#define SPR_SKIP_LO 4
#define SPR_SKIP_HI 5
#define SPR_GFXOFS_LO 6
#define SPR_GFXOFS_HI 7
VIDEO_START( system1 );
VIDEO_START( system2 );