From b6af00c0ae61b350f64504a85266d49ad891216f Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Thu, 9 Apr 2009 15:53:51 +0000 Subject: [PATCH] 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) --- src/mame/drivers/system1.c | 265 +++++++++--------- src/mame/video/system1.c | 542 +++++++++++++++++++++++-------------- src/mame/video/system1.h | 9 - 3 files changed, 474 insertions(+), 342 deletions(-) diff --git a/src/mame/drivers/system1.c b/src/mame/drivers/system1.c index dd4c59971d9..aba2f5c41db 100644 --- a/src/mame/drivers/system1.c +++ b/src/mame/drivers/system1.c @@ -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 ) diff --git a/src/mame/video/system1.c b/src/mame/video/system1.c index 0d19cdc38b2..ac773355ed9 100644 --- a/src/mame/video/system1.c +++ b/src/mame/video/system1.c @@ -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; } diff --git a/src/mame/video/system1.h b/src/mame/video/system1.h index b6e9d9336ff..315907e23b3 100644 --- a/src/mame/video/system1.h +++ b/src/mame/video/system1.h @@ -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 );