diff --git a/src/emu/timer.h b/src/emu/timer.h index b2d26a40589..9c4ef6b4643 100644 --- a/src/emu/timer.h +++ b/src/emu/timer.h @@ -204,7 +204,7 @@ void timer_device_adjust_periodic(const device_config *timer, attotime start_del /* ----- anonymous timer management ----- */ /* allocate a one-shot timer, which calls the callback after the given duration */ -void _timer_set_internal(running_machine *machine, attotime druation, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func); +void _timer_set_internal(running_machine *machine, attotime duration, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func); /* allocate a pulse timer, which repeatedly calls the callback using the given period */ void _timer_pulse_internal(running_machine *machine, attotime period, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func); diff --git a/src/emu/video.c b/src/emu/video.c index a2eaf6f8faf..0c82361714a 100644 --- a/src/emu/video.c +++ b/src/emu/video.c @@ -439,7 +439,7 @@ static void init_buffered_spriteram(running_machine *machine) /* register for saving it */ state_save_register_global_pointer(machine, buffered_spriteram, spriteram_size); - /* do the same for the secon back buffer, if present */ + /* do the same for the second back buffer, if present */ if (spriteram_2_size) { /* allocate memory */ diff --git a/src/mame/drivers/twin16.c b/src/mame/drivers/twin16.c index 19576be6f28..19e80350990 100644 --- a/src/mame/drivers/twin16.c +++ b/src/mame/drivers/twin16.c @@ -8,47 +8,38 @@ SOUND : YM2151 007232 uPD7759C OSC. : 3.579545MHz 18432.00KHz Main processors are a pair of 68000 CPUs -Sounds are generated by a Z80, a Yamaha 2151 and 3012, a Konami custom IC and a UPD7759C +Sounds are generated by a Z80, a Yamaha 2151 and 3012, a Konami custom IC and a uPD7759C - Dark Adventure / Devil World / Majuu no Ohkoku - Vulcan Venture / Gradius II - Cuebrick - MIA (Japan) - Final Round / Hard Puncher (Japan) - -Known Issues: - - some rogue sprites in Devil World - - sprite-background priority is guessed + Dark Adventure / Devil World / Majuu no Ohkoku + Vulcan Venture / Gradius II + Cuebrick + MIA (Japan) + Final Round / Hard Puncher (Japan) 68000 Memory Map for Konami Twin System - CPUA CPUB - 0x000000..0x03ffff ROM 0x000000..0x03ffff - 0x040000..0x043fff communication RAM 0x040000..0x043fff (shared) - 0x060000..0x063fff work RAM 0x060000..0x063fff - 0x080000..0x080fff palette - 0x080000..0x09ffff ROM (extra tile data) - 0x0a0000..0x0a0001 IRQ control 0x0a0000..0x0a0001 - 0x0a0008..0x0a0009 sound command - 0x0a0010..0xa00011 watchdog - 0x0c0000..0x0c0001 screenflip - 0x0c0002..0x0c000f scroll registers + CPUA CPUB + 0x000000..0x03ffff ROM 0x000000..0x03ffff + 0x040000..0x043fff communication RAM 0x040000..0x043fff (shared) + 0x060000..0x063fff work RAM 0x060000..0x063fff + 0x080000..0x080fff palette + 0x080000..0x09ffff ROM (extra tile data) + 0x0a0000..0x0a0001 IRQ control 0x0a0000..0x0a0001 + 0x0a0008..0x0a0009 sound command + 0x0a0010..0xa00011 watchdog + 0x0c0000..0x0c0001 screenflip + 0x0c0002..0x0c000f scroll registers - 0x100000..0x103fff FIXRAM (text layer) - 0x120000..0x123fff VIDRAM (tilemaps) 0x480000..0x483fff (shared) - 0x140000..0x143fff OBJRAM (sprites) 0x400000..0x403fff (shared) - ZIP RAM (tiles) 0x500000..0x53ffff - gfx ROM (banked) 0x600000..0x77ffff - sprite gfx RAM 0x780000..0x79ffff -*/ + 0x100000..0x103fff FIXRAM (text layer) + 0x120000..0x123fff VIDRAM (tilemaps) 0x480000..0x483fff (shared) + 0x140000..0x143fff OBJRAM (sprites) 0x400000..0x403fff (shared) + ZIP RAM (tiles) 0x500000..0x53ffff + gfx ROM (banked) 0x600000..0x77ffff + sprite gfx RAM 0x780000..0x79ffff -/* - - Konami Twin16 Hardware - - TODO: - - - mia reset crash +Known Issues: +- repeated uPD7759C samples in fround, disconnecting reset helps but doesn't fix it +- see video/twin16.c for graphics related issues */ @@ -65,18 +56,17 @@ UINT16 twin16_custom_video; UINT16 *twin16_gfx_rom; UINT16 *twin16_sprite_gfx_ram; UINT16 *twin16_tile_gfx_ram; -UINT16 *twin16_videoram2; /* text layer */ +UINT16 *twin16_text_ram; static UINT16 twin16_CPUA_register, twin16_CPUB_register; #define CPUA_IRQ_ENABLE (twin16_CPUA_register & 0x20) #define CPUB_IRQ_ENABLE (twin16_CPUB_register & 0x02) -static UINT8 twin16_soundlatch; static UINT16 twin16_sound_command; -static int cuebrckj_nvram_bank; -static UINT16 cuebrckj_nvram[0x400*0x20]; // 32k paged in a 1k window +static int cuebrickj_nvram_bank; +static UINT16 cuebrickj_nvram[0x400*0x20]; // 32k paged in a 1k window int twin16_spriteram_process_enable( void ) @@ -108,7 +98,7 @@ static READ16_HANDLER( extra_rom_r ) static READ16_HANDLER( twin16_gfx_rom1_r ) { - return twin16_gfx_rom[offset]; + return twin16_gfx_rom[offset + ((twin16_CPUB_register&0x04)?0x40000:0)]; } static READ16_HANDLER( twin16_gfx_rom2_r ) @@ -122,29 +112,16 @@ static WRITE16_HANDLER( sound_command_w ) soundlatch_w( space, 0, twin16_sound_command&0xff ); } -static READ16_HANDLER( twin16_sprite_status_r ) -{ - /* - return value indicates whether the spriteram16-processing circuitry - is busy. - - for now, we'll just alternate the value every time it is read - */ - static int k; - k = 1-k; - return k; -} - static WRITE16_HANDLER( twin16_CPUA_register_w ) { /* - 7 6 5 4 3 2 1 0 - ? sprite protection disable - X IRQ5 enable (CPUA) - X 0->1 trigger IRQ6 on CPUB - X 0->1 trigger IRQ on sound CPU - x x x coin counters - */ + 7 6 5 4 3 2 1 0 + X sprite processing disable + X IRQ5 enable (CPUA) + X 0->1 trigger IRQ6 on CPUB + X 0->1 trigger IRQ on sound CPU + x x x coin counters + */ UINT16 old = twin16_CPUA_register; COMBINE_DATA(&twin16_CPUA_register); if (twin16_CPUA_register != old) @@ -153,7 +130,7 @@ static WRITE16_HANDLER( twin16_CPUA_register_w ) cputag_set_input_line_and_vector(space->machine, "audiocpu", 0, HOLD_LINE, 0xff); if ((old & 0x40) && (twin16_CPUA_register & 0x40) == 0) - twin16_spriteram_process(); + twin16_spriteram_process(space->machine); if ((old & 0x10) == 0 && (twin16_CPUA_register & 0x10)) cputag_set_input_line(space->machine, "sub", M68K_IRQ_6, HOLD_LINE); @@ -167,30 +144,36 @@ static WRITE16_HANDLER( twin16_CPUA_register_w ) static WRITE16_HANDLER( twin16_CPUB_register_w ) { /* - 7 6 5 4 3 2 1 0 - X gfx bank select - X IRQ5 enable - X 0->1 trigger IRQ6 on CPUA - */ + 7 6 5 4 3 2 1 0 + X gfx bank select + X IRQ5 enable + X 0->1 trigger IRQ6 on CPUA + */ UINT16 old = twin16_CPUB_register; COMBINE_DATA(&twin16_CPUB_register); if( twin16_CPUB_register!=old ) { if ((old & 0x01) == 0 && (twin16_CPUB_register & 0x01)) - { cputag_set_input_line(space->machine, "maincpu", M68K_IRQ_6, HOLD_LINE); - } } } static WRITE16_HANDLER( fround_CPU_register_w ) { + /* + 7 6 5 4 3 2 1 0 + X 0->1 trigger IRQ on sound CPU + x x coin counters + */ UINT16 old = twin16_CPUA_register; COMBINE_DATA(&twin16_CPUA_register); if (twin16_CPUA_register != old) { if ((old & 0x08) == 0 && (twin16_CPUA_register & 0x08)) - cputag_set_input_line_and_vector(space->machine, "audiocpu", 0, HOLD_LINE, 0xff); // trigger IRQ on sound CPU + cputag_set_input_line_and_vector(space->machine, "audiocpu", 0, HOLD_LINE, 0xff); + + coin_counter_w(0, twin16_CPUA_register & 0x01); + coin_counter_w(1, twin16_CPUA_register & 0x02); } } @@ -205,20 +188,19 @@ static READ16_HANDLER( twin16_input_r ) case 0x08: return input_port_read(space->machine, "DSW2"); case 0x09: return input_port_read(space->machine, "DSW1"); case 0x0c: return input_port_read(space->machine, "DSW3"); + default: break; } return 0; } -static READ8_HANDLER( twin16_sres_r ) +static READ8_DEVICE_HANDLER( twin16_upd_busy_r ) { - return twin16_soundlatch; + return upd7759_busy_r(device); } -static WRITE8_HANDLER( twin16_sres_w ) +static WRITE8_DEVICE_HANDLER( twin16_upd_reset_w ) { - /* bit 1 resets the UPD7795C sound chip */ - upd7759_reset_w(devtag_get_device(space->machine, "upd"), data & 0x02); - twin16_soundlatch = data; + upd7759_reset_w(device, data & 2); } static WRITE8_DEVICE_HANDLER( twin16_upd_start_w ) @@ -226,24 +208,19 @@ static WRITE8_DEVICE_HANDLER( twin16_upd_start_w ) upd7759_start_w(device, data & 1); } -static READ8_DEVICE_HANDLER( twin16_upd_busy_r ) +static READ16_HANDLER( cuebrickj_nvram_r ) { - return upd7759_busy_r(device) ? 1 : 0; + return cuebrickj_nvram[offset + (cuebrickj_nvram_bank * 0x400 / 2)]; } -static READ16_HANDLER( cuebrckj_nvram_r ) +static WRITE16_HANDLER( cuebrickj_nvram_w ) { - return cuebrckj_nvram[offset + (cuebrckj_nvram_bank * 0x400 / 2)]; + COMBINE_DATA(&cuebrickj_nvram[offset + (cuebrickj_nvram_bank * 0x400 / 2)]); } -static WRITE16_HANDLER( cuebrckj_nvram_w ) +static WRITE16_HANDLER( cuebrickj_nvram_bank_w ) { - COMBINE_DATA(&cuebrckj_nvram[offset + (cuebrckj_nvram_bank * 0x400 / 2)]); -} - -static WRITE16_HANDLER( cuebrckj_nvram_bank_w ) -{ - cuebrckj_nvram_bank = (data >> 8); + cuebrickj_nvram_bank = (data >> 8); } /* Memory Maps */ @@ -251,19 +228,19 @@ static WRITE16_HANDLER( cuebrckj_nvram_bank_w ) static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x7fff) AM_ROM AM_RANGE(0x8000, 0x8fff) AM_RAM - AM_RANGE(0x9000, 0x9000) AM_READWRITE(twin16_sres_r, twin16_sres_w) + AM_RANGE(0x9000, 0x9000) AM_DEVWRITE("upd", twin16_upd_reset_w) AM_RANGE(0xa000, 0xa000) AM_READ(soundlatch_r) AM_RANGE(0xb000, 0xb00d) AM_DEVREADWRITE("konami", k007232_r, k007232_w) AM_RANGE(0xc000, 0xc001) AM_DEVREADWRITE("ym", ym2151_r, ym2151_w) AM_RANGE(0xd000, 0xd000) AM_DEVWRITE("upd", upd7759_port_w) AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("upd", twin16_upd_start_w) - AM_RANGE(0xf000, 0xf000) AM_DEVREAD("upd", twin16_upd_busy_r) AM_WRITENOP // ??? write ??? + AM_RANGE(0xf000, 0xf000) AM_DEVREAD("upd", twin16_upd_busy_r) // miaj writes 0 to it ADDRESS_MAP_END static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 ) AM_RANGE(0x000000, 0x03ffff) AM_ROM AM_RANGE(0x040000, 0x043fff) AM_READWRITE(COMRAM_r, COMRAM_w) - AM_RANGE(0x044000, 0x04ffff) AM_RAM // miaj +// AM_RANGE(0x044000, 0x04ffff) AM_NOP // miaj AM_RANGE(0x060000, 0x063fff) AM_RAM AM_RANGE(0x080000, 0x080fff) AM_RAM_WRITE(twin16_paletteram_word_w) AM_BASE(&paletteram16) AM_RANGE(0x081000, 0x081fff) AM_WRITENOP @@ -271,12 +248,12 @@ static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 ) AM_RANGE(0x0a0000, 0x0a0001) AM_WRITE(twin16_CPUA_register_w) AM_RANGE(0x0a0008, 0x0a0009) AM_WRITE(sound_command_w) AM_RANGE(0x0a0010, 0x0a0011) AM_WRITE(watchdog_reset16_w) - AM_RANGE(0x0b0000, 0x0b03ff) AM_READWRITE(cuebrckj_nvram_r, cuebrckj_nvram_w) - AM_RANGE(0x0b0400, 0x0b0401) AM_WRITE(cuebrckj_nvram_bank_w) + AM_RANGE(0x0b0000, 0x0b03ff) AM_READWRITE(cuebrickj_nvram_r, cuebrickj_nvram_w) + AM_RANGE(0x0b0400, 0x0b0401) AM_WRITE(cuebrickj_nvram_bank_w) AM_RANGE(0x0c0000, 0x0c000f) AM_WRITE(twin16_video_register_w) AM_RANGE(0x0c000e, 0x0c000f) AM_READ(twin16_sprite_status_r) - AM_RANGE(0x100000, 0x103fff) AM_RAM_WRITE(twin16_videoram2_w) AM_BASE(&twin16_videoram2) - AM_RANGE(0x104000, 0x105fff) AM_RAM // miaj + AM_RANGE(0x100000, 0x103fff) AM_RAM_WRITE(twin16_text_ram_w) AM_BASE(&twin16_text_ram) +// AM_RANGE(0x104000, 0x105fff) AM_NOP // miaj AM_RANGE(0x120000, 0x123fff) AM_RAM AM_BASE(&videoram16) AM_RANGE(0x140000, 0x143fff) AM_RAM AM_SHARE(1) AM_BASE(&spriteram16) AM_SIZE(&spriteram_size) ADDRESS_MAP_END @@ -284,7 +261,7 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( sub_map, ADDRESS_SPACE_PROGRAM, 16 ) AM_RANGE(0x000000, 0x03ffff) AM_ROM AM_RANGE(0x040000, 0x043fff) AM_READWRITE(COMRAM_r, COMRAM_w) - AM_RANGE(0x044000, 0x04ffff) AM_RAM // miaj +// AM_RANGE(0x044000, 0x04ffff) AM_NOP // miaj AM_RANGE(0x060000, 0x063fff) AM_RAM AM_RANGE(0x080000, 0x09ffff) AM_READ(extra_rom_r) AM_RANGE(0x0a0000, 0x0a0001) AM_WRITE(twin16_CPUB_register_w) @@ -308,7 +285,7 @@ static ADDRESS_MAP_START( fround_map, ADDRESS_SPACE_PROGRAM, 16 ) AM_RANGE(0x0c0000, 0x0c000f) AM_WRITE(twin16_video_register_w) AM_RANGE(0x0c000e, 0x0c000f) AM_READ(twin16_sprite_status_r) AM_RANGE(0x0e0000, 0x0e0001) AM_WRITE(fround_gfx_bank_w) - AM_RANGE(0x100000, 0x103fff) AM_RAM_WRITE(twin16_videoram2_w) AM_BASE(&twin16_videoram2) + AM_RANGE(0x100000, 0x103fff) AM_RAM_WRITE(twin16_text_ram_w) AM_BASE(&twin16_text_ram) AM_RANGE(0x120000, 0x123fff) AM_RAM AM_BASE(&videoram16) AM_RANGE(0x140000, 0x143fff) AM_RAM AM_BASE(&spriteram16) AM_SIZE(&spriteram_size) AM_RANGE(0x500000, 0x6fffff) AM_READ(twin16_gfx_rom1_r) @@ -328,7 +305,7 @@ static INPUT_PORTS_START( devilw ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123_UNK(1) // button1 = start/powerup, button2 = attack, button3 = jump + KONAMI8_B123_UNK(1) // button1 = start/powerup, button2 = attack, button3 = jump PORT_START("P2") /* 0xa0005 */ KONAMI8_B123_UNK(2) @@ -378,7 +355,7 @@ static INPUT_PORTS_START( darkadv ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123(1) // button1 = start/jump, button2 = attack, button3 = dynamite + KONAMI8_B123(1) // button1 = start/jump, button2 = attack, button3 = dynamite PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_START("P2") /* 0xa0005 */ @@ -438,14 +415,14 @@ static INPUT_PORTS_START( vulcan ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123_UNK(1) // button1 = powerup, button2 = shoot, button3 = missile + KONAMI8_B123_UNK(1) // button1 = powerup, button2 = shoot, button3 = missile PORT_START("P2") /* 0xa0005 */ KONAMI8_B123_UNK(2) @@ -509,14 +486,14 @@ static INPUT_PORTS_START( fround ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123_UNK(1) // button1 = face punch, button2 = body punch, button3 = defend + KONAMI8_B123_UNK(1) // button1 = face punch, button2 = body punch, button3 = defend PORT_START("P2") /* 0xa0005 */ KONAMI8_B123_UNK(2) @@ -559,14 +536,14 @@ static INPUT_PORTS_START( miaj ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123_UNK(1) // button1 = knife, button2 = weapon, button3 = choice + KONAMI8_B123_UNK(1) // button1 = knife, button2 = weapon, button3 = choice PORT_START("P2") /* 0xa0005 */ KONAMI8_B123_UNK(2) @@ -611,19 +588,19 @@ static INPUT_PORTS_START( miaj ) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) INPUT_PORTS_END -static INPUT_PORTS_START( cuebrckj ) +static INPUT_PORTS_START( cuebrickj ) PORT_START("SYSTEM") /* 0xa0001 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) // advance through tests PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") /* 0xa0003 */ - KONAMI8_B123_UNK(1) // button1 = move, button2 = warp, button3 = stop + KONAMI8_B123_UNK(1) // button1 = move, button2 = warp, button3 = stop PORT_START("P2") /* 0xa0005 */ KONAMI8_B123_UNK(2) @@ -718,6 +695,25 @@ static INTERRUPT_GEN( CPUB_interrupt ) /* Machine Drivers */ +static MACHINE_RESET( twin16 ) +{ + ; +} + +static MACHINE_START( twin16 ) +{ + twin16_CPUA_register=0; + twin16_CPUB_register=0; + + /* register for savestates */ + state_save_register_global(machine, twin16_CPUA_register); + state_save_register_global(machine, twin16_CPUB_register); + + state_save_register_global(machine, twin16_sound_command); + state_save_register_global(machine, cuebrickj_nvram_bank); + state_save_register_global_array(machine, cuebrickj_nvram); +} + static MACHINE_DRIVER_START( twin16 ) // basic machine hardware MDRV_CPU_ADD("maincpu", M68000, XTAL_18_432MHz/2) @@ -732,13 +728,16 @@ static MACHINE_DRIVER_START( twin16 ) MDRV_CPU_PROGRAM_MAP(sound_map) MDRV_QUANTUM_TIME(HZ(6000)) - + + MDRV_MACHINE_START(twin16) + MDRV_MACHINE_RESET(twin16) + // video hardware - MDRV_VIDEO_ATTRIBUTES(VIDEO_BUFFERS_SPRITERAM) + MDRV_VIDEO_ATTRIBUTES(VIDEO_HAS_SHADOWS | VIDEO_BUFFERS_SPRITERAM) MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_REFRESH_RATE(((double)XTAL_18_432MHz / 2) / (576 * 264)) - MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) + MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2062)) // 32 lines MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) MDRV_SCREEN_SIZE(40*8, 32*8) MDRV_SCREEN_VISIBLE_AREA(0, 40*8-1, 2*8, 30*8-1) @@ -759,10 +758,10 @@ static MACHINE_DRIVER_START( twin16 ) MDRV_SOUND_ADD("konami", K007232, 3579545) MDRV_SOUND_CONFIG(k007232_config) - MDRV_SOUND_ROUTE(0, "lspeaker", 0.20) - MDRV_SOUND_ROUTE(0, "rspeaker", 0.20) - MDRV_SOUND_ROUTE(1, "lspeaker", 0.20) - MDRV_SOUND_ROUTE(1, "rspeaker", 0.20) + MDRV_SOUND_ROUTE(0, "lspeaker", 0.12) // estimated with gradius2 OST + MDRV_SOUND_ROUTE(0, "rspeaker", 0.12) + MDRV_SOUND_ROUTE(1, "lspeaker", 0.12) + MDRV_SOUND_ROUTE(1, "rspeaker", 0.12) MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20) @@ -771,7 +770,7 @@ MACHINE_DRIVER_END static MACHINE_DRIVER_START( devilw ) MDRV_IMPORT_FROM(twin16) - MDRV_QUANTUM_TIME(HZ(60000)) + MDRV_QUANTUM_TIME(HZ(60000)) // watchdog reset otherwise MACHINE_DRIVER_END static MACHINE_DRIVER_START( fround ) @@ -784,9 +783,12 @@ static MACHINE_DRIVER_START( fround ) MDRV_CPU_PROGRAM_MAP(sound_map) MDRV_QUANTUM_TIME(HZ(6000)) - + + MDRV_MACHINE_START(twin16) + MDRV_MACHINE_RESET(twin16) + /* video hardware */ - MDRV_VIDEO_ATTRIBUTES(VIDEO_BUFFERS_SPRITERAM) + MDRV_VIDEO_ATTRIBUTES(VIDEO_HAS_SHADOWS | VIDEO_BUFFERS_SPRITERAM) MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_REFRESH_RATE(60) @@ -798,7 +800,7 @@ static MACHINE_DRIVER_START( fround ) MDRV_GFXDECODE(twin16) MDRV_PALETTE_LENGTH(0x400) - MDRV_VIDEO_START(fround) + MDRV_VIDEO_START(twin16) MDRV_VIDEO_UPDATE(twin16) MDRV_VIDEO_EOF(twin16) @@ -811,33 +813,26 @@ static MACHINE_DRIVER_START( fround ) MDRV_SOUND_ADD("konami", K007232, 3579545) MDRV_SOUND_CONFIG(k007232_config) - MDRV_SOUND_ROUTE(0, "lspeaker", 0.20) - MDRV_SOUND_ROUTE(0, "rspeaker", 0.20) - MDRV_SOUND_ROUTE(1, "lspeaker", 0.20) - MDRV_SOUND_ROUTE(1, "rspeaker", 0.20) + MDRV_SOUND_ROUTE(0, "lspeaker", 0.12) + MDRV_SOUND_ROUTE(0, "rspeaker", 0.12) + MDRV_SOUND_ROUTE(1, "lspeaker", 0.12) + MDRV_SOUND_ROUTE(1, "rspeaker", 0.12) MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.20) MACHINE_DRIVER_END -static MACHINE_DRIVER_START( hpuncher ) - MDRV_IMPORT_FROM(twin16) - MDRV_VIDEO_START(fround) -MACHINE_DRIVER_END - static MACHINE_DRIVER_START( miaj ) MDRV_IMPORT_FROM(twin16) MDRV_SCREEN_MODIFY("screen") MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1) - MDRV_VIDEO_START(fround) MACHINE_DRIVER_END -static MACHINE_DRIVER_START( cuebrckj ) +static MACHINE_DRIVER_START( cuebrickj ) MDRV_IMPORT_FROM(twin16) MDRV_SCREEN_MODIFY("screen") MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1) - MDRV_VIDEO_START(fround) MDRV_NVRAM_HANDLER(generic_0fill) MACHINE_DRIVER_END @@ -1201,7 +1196,7 @@ ROM_START( miaj ) ROM_REGION( 0x20000, "upd", ROMREGION_ERASE00 ) // samples ROM_END -ROM_START( cuebrckj ) +ROM_START( cuebrickj ) ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code (CPU A) ROM_LOAD16_BYTE( "903_e05.6n", 0x00000, 0x10000, CRC(8b556220) SHA1(dbe24133e74018c4fe9332519394cbb882c4ed5a) ) ROM_LOAD16_BYTE( "903_e04.4n", 0x00001, 0x10000, CRC(bf9c7927) SHA1(3a594b8846f7e6074ca54f8cd5fe2ba3b64ba740) ) @@ -1239,19 +1234,18 @@ ROM_END static void gfx_untangle( running_machine *machine ) { // sprite, tile data - int i; UINT16 *temp = alloc_array_or_die(UINT16, 0x200000/2); - twin16_gfx_rom = (UINT16 *)memory_region(machine, "gfx2"); - memcpy( temp, twin16_gfx_rom, 0x200000 ); + twin16_gfx_rom = (UINT16 *)memory_region(machine, "gfx2"); + memcpy( temp, twin16_gfx_rom, 0x200000 ); - for( i=0; i<0x080000; i++ ) - { - twin16_gfx_rom[i*2+0] = temp[i+0x080000]; - twin16_gfx_rom[i*2+1] = temp[i]; - } - free( temp ); + for( i=0; i<0x080000; i++ ) + { + twin16_gfx_rom[i*2+0] = temp[i+0x080000]; + twin16_gfx_rom[i*2+1] = temp[i]; + } + free( temp ); } static DRIVER_INIT( twin16 ) @@ -1266,33 +1260,26 @@ static DRIVER_INIT( fround ) twin16_custom_video = 1; } -static DRIVER_INIT( hpuncher ) +static DRIVER_INIT( cuebrickj ) { gfx_untangle(machine); - twin16_custom_video = 2; -} -static DRIVER_INIT( cuebrckj ) -{ - gfx_untangle(machine); - twin16_custom_video = 2; - - generic_nvram = (UINT8 *)cuebrckj_nvram; + generic_nvram = (UINT8 *)cuebrickj_nvram; generic_nvram_size = 0x400*0x20; } /* Game Drivers */ -GAME( 1987, devilw, 0, devilw, devilw, twin16, ROT0, "Konami", "Devil World", 0 ) -GAME( 1987, majuu, devilw, devilw, devilw, twin16, ROT0, "Konami", "Majuu no Ohkoku", 0 ) -GAME( 1987, darkadv, devilw, devilw, darkadv, twin16, ROT0, "Konami", "Dark Adventure", 0 ) -GAME( 1988, vulcan, 0, twin16, vulcan, twin16, ROT0, "Konami", "Vulcan Venture", 0 ) -GAME( 1988, gradius2, vulcan, twin16, gradius2, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan New Ver.)", 0 ) -GAME( 1988, gradius2a,vulcan, twin16, vulcan, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan Old Ver.)", 0 ) -GAME( 1988, gradius2b,vulcan, twin16, vulcan, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan Older Ver.)", 0 ) +GAME( 1987, devilw, 0, devilw, devilw, twin16, ROT0, "Konami", "Devil World", GAME_SUPPORTS_SAVE ) +GAME( 1987, majuu, devilw, devilw, devilw, twin16, ROT0, "Konami", "Majuu no Ohkoku", GAME_SUPPORTS_SAVE ) +GAME( 1987, darkadv, devilw, devilw, darkadv, twin16, ROT0, "Konami", "Dark Adventure", GAME_SUPPORTS_SAVE ) +GAME( 1988, vulcan, 0, twin16, vulcan, twin16, ROT0, "Konami", "Vulcan Venture", GAME_SUPPORTS_SAVE ) +GAME( 1988, gradius2, vulcan, twin16, gradius2, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan New Ver.)", GAME_SUPPORTS_SAVE ) +GAME( 1988, gradius2a,vulcan, twin16, vulcan, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan Old Ver.)", GAME_SUPPORTS_SAVE ) +GAME( 1988, gradius2b,vulcan, twin16, vulcan, twin16, ROT0, "Konami", "Gradius II - GOFER no Yabou (Japan Older Ver.)", GAME_SUPPORTS_SAVE ) -GAME( 1988, fround, 0, fround, fround, fround, ROT0, "Konami", "The Final Round (version M)", 0 ) -GAME( 1988, froundl, fround, fround, fround, fround, ROT0, "Konami", "The Final Round (version L)", 0 ) -GAME( 1988, hpuncher, fround, hpuncher, fround, hpuncher, ROT0, "Konami", "Hard Puncher (Japan)", 0 ) -GAME( 1989, miaj, mia, miaj, miaj, hpuncher, ROT0, "Konami", "M.I.A. - Missing in Action (Japan)", 0 ) -GAME( 1989, cuebrckj, cuebrick, cuebrckj, cuebrckj, cuebrckj, ROT0, "Konami", "Cue Brick (Japan)", 0 ) +GAME( 1988, fround, 0, fround, fround, fround, ROT0, "Konami", "The Final Round (version M)", GAME_SUPPORTS_SAVE ) +GAME( 1988, froundl, fround, fround, fround, fround, ROT0, "Konami", "The Final Round (version L)", GAME_SUPPORTS_SAVE ) +GAME( 1988, hpuncher, fround, twin16, fround, twin16, ROT0, "Konami", "Hard Puncher (Japan)", GAME_SUPPORTS_SAVE ) +GAME( 1989, miaj, mia, miaj, miaj, twin16, ROT0, "Konami", "M.I.A. - Missing in Action (Japan)", GAME_SUPPORTS_SAVE ) +GAME( 1989, cuebrickj,cuebrick, cuebrickj, cuebrickj,cuebrickj,ROT0, "Konami", "Cue Brick (Japan)", GAME_SUPPORTS_SAVE ) diff --git a/src/mame/includes/twin16.h b/src/mame/includes/twin16.h index 654bc77cff6..05f6fc63270 100644 --- a/src/mame/includes/twin16.h +++ b/src/mame/includes/twin16.h @@ -2,7 +2,7 @@ extern UINT16 twin16_custom_video; extern UINT16 *twin16_gfx_rom; -extern UINT16 *twin16_videoram2; +extern UINT16 *twin16_text_ram; extern UINT16 *twin16_sprite_gfx_ram; extern UINT16 *twin16_tile_gfx_ram; int twin16_spriteram_process_enable( void ); @@ -10,14 +10,14 @@ int twin16_spriteram_process_enable( void ); /*----------- defined in video/twin16.c -----------*/ -WRITE16_HANDLER( twin16_videoram2_w ); +WRITE16_HANDLER( twin16_text_ram_w ); WRITE16_HANDLER( twin16_paletteram_word_w ); WRITE16_HANDLER( fround_gfx_bank_w ); WRITE16_HANDLER( twin16_video_register_w ); +READ16_HANDLER( twin16_sprite_status_r ); VIDEO_START( twin16 ); -VIDEO_START( fround ); VIDEO_UPDATE( twin16 ); VIDEO_EOF( twin16 ); -void twin16_spriteram_process( void ); +void twin16_spriteram_process( running_machine* ); diff --git a/src/mame/mamedriv.c b/src/mame/mamedriv.c index f221a9306cc..f41e8081160 100644 --- a/src/mame/mamedriv.c +++ b/src/mame/mamedriv.c @@ -5312,7 +5312,7 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11 DRIVER( gradius2 ) /* GX785 (c) 1988 (Japan) */ DRIVER( gradius2a ) /* GX785 (c) 1988 (Japan) */ DRIVER( gradius2b ) /* GX785 (c) 1988 (Japan) */ - DRIVER( cuebrckj ) /* GX903 (c) 1989 */ + DRIVER( cuebrickj ) /* GX903 (c) 1989 (Japan) */ DRIVER( fround ) /* GX870 (c) 1988 */ DRIVER( froundl ) /* GX870 (c) 1988 */ DRIVER( hpuncher ) /* GX870 (c) 1988 (Japan) */ diff --git a/src/mame/video/twin16.c b/src/mame/video/twin16.c index 292e8fc4b50..45032a11b44 100644 --- a/src/mame/video/twin16.c +++ b/src/mame/video/twin16.c @@ -5,17 +5,21 @@ TODO: - convert background to tilemap - - clean up sprite drawing - - sprite-background priorities - - sprite lag in devilw - - sprite Y axis lag in vulcan - - add shadow sprites (alpha blending) to sprites in at least devilw + - clean up sprite system + - bad sprites in devilw, eg. odd colours for the mud/lava monster in the 1st level, + or wrong sprite-sprite priority sometimes -- check real arcade first + - unsure about some sprite preprocessor attributes (see twin16_spriteram_process) */ #include "driver.h" #include "includes/twin16.h" +static UINT16 twin16_sprite_buffer[0x800]; +static TIMER_CALLBACK( twin16_sprite_tick ); +static emu_timer *twin16_sprite_timer; +static int twin16_sprite_busy; + static int need_process_spriteram; static UINT16 gfx_bank; static UINT16 scrollx[3], scrolly[3]; @@ -23,19 +27,31 @@ static UINT16 video_register; enum { - TWIN16_SCREEN_FLIPY = 0x01, /* ? breaks devils world text layer */ - TWIN16_SCREEN_FLIPX = 0x02, /* confirmed: Hard Puncher Intro */ - TWIN16_UNKNOWN1 = 0x04, /* ?Hard Puncher uses this */ - TWIN16_PLANE_ORDER = 0x08, /* confirmed: Devil Worlds */ - TWIN16_TILE_FLIPY = 0x20 /* confirmed? Vulcan Venture */ + TWIN16_SCREEN_FLIPY = 0x01, + TWIN16_SCREEN_FLIPX = 0x02, // confirmed: Hard Puncher Intro + TWIN16_UNKNOWN1 = 0x04, // ? Hard Puncher uses this + TWIN16_PLANE_ORDER = 0x08, // confirmed: Devil Worlds + TWIN16_TILE_FLIPX = 0x10, // unused? + TWIN16_TILE_FLIPY = 0x20 // confirmed? Vulcan Venture }; -static tilemap *fg_tilemap; - -WRITE16_HANDLER( twin16_videoram2_w ) +enum { - COMBINE_DATA(&twin16_videoram2[offset]); - tilemap_mark_tile_dirty(fg_tilemap, offset); + // user-defined priorities + TWIN16_BG_LAYER1 = 0x01, + TWIN16_SPRITE_PRI_L1 = 0x02, + TWIN16_BG_LAYER2 = 0x04, + TWIN16_SPRITE_PRI_L2 = 0x08, + TWIN16_SPRITE_OCCUPIED = 0x10, // sprite on screen pixel + TWIN16_SPRITE_CAST_SHADOW = 0x20 +}; + +static tilemap *text_tilemap; + +WRITE16_HANDLER( twin16_text_ram_w ) +{ + COMBINE_DATA(&twin16_text_ram[offset]); + tilemap_mark_tile_dirty(text_tilemap, offset); } WRITE16_HANDLER( twin16_paletteram_word_w ) @@ -60,12 +76,8 @@ WRITE16_HANDLER( twin16_video_register_w ) COMBINE_DATA( &video_register ); flip_screen_x_set(space->machine, video_register & TWIN16_SCREEN_FLIPX); - - if (twin16_custom_video) - flip_screen_y_set(space->machine, video_register & TWIN16_SCREEN_FLIPY); - else - flip_screen_y_set(space->machine, ~video_register & TWIN16_SCREEN_FLIPY); - + flip_screen_y_set(space->machine, video_register & TWIN16_SCREEN_FLIPY); + break; case 1: COMBINE_DATA( &scrollx[0] ); break; @@ -81,76 +93,124 @@ WRITE16_HANDLER( twin16_video_register_w ) } } -/* slow slow slow, but it's ok for now */ -static void draw_sprite( running_machine *machine, bitmap_t *bitmap,const UINT16 *pen_data, int pal_base, int xpos, int ypos, int width, int height, int flipx, int flipy, int pri ) +/* + * Sprite Format + * ---------------------------------- + * preprocessor (not much data to test with): + * Word | Bit(s) | Use + * -----+-fedcba9876543210-+---------------- + * 0 | x--------------- | enable + * 0 | -xxxxxxx-------- | ? + * 0 | --------xxxxxxxx | sprite-sprite priority + * -----+------------------+ + * 1 | xxxxxxxxxxxxxxxx | ? + * -----+------------------+ + * 2 | xxxxxx---------- | ? + * 2 | ------x--------- | yflip (devilw) + * 2 | -------x-------- | xflip + * 2 | --------xx------ | height + * 2 | ----------xx---- | width + * 2 | ------------xxxx | color + * -----+------------------+ + * 3 | -xxxxxxxxxxxxxxx | code + * -----+------------------+ + * 4 | -------xxxxxxxxx | xpos high, other bits probably no effect + * 5 | xxxxxxxx-------- | xpos low, other bits probably no effect + * 6 | -------xxxxxxxxx | xpos high, other bits probably no effect + * 7 | xxxxxxxx-------- | ypos low, other bits probably no effect + * + * ---------------------------------- + * normal/after preprocessing: + * Word | Bit(s) | Use + * -----+-fedcba9876543210-+---------------- + * 0 | -xxxxxxxxxxxxxxx | code + * -----+------------------+ + * 1 | -------xxxxxxxxx | ypos + * -----+------------------+ + * 2 | -------xxxxxxxxx | xpos + * -----+------------------+ + * 3 | x--------------- | enable + * 3 | -x-------------- | priority ? + * 3 | -----x---------- | no shadow ? + * 3 | ------x--------- | yflip ? + * 3 | -------x-------- | xflip + * 3 | --------xx------ | height + * 3 | ----------xx---- | width + * 3 | ------------xxxx | color + */ + +READ16_HANDLER( twin16_sprite_status_r ) { - int x,y,pval; - if( xpos>=320 ) xpos -= 65536; - if( ypos>=256 ) ypos -= 65536; - - if (pri) pval=2; else pval=8; - - for( y=0; y=16 && sy<256-16 ) - { - UINT16 *dest = BITMAP_ADDR16(bitmap, sy, 0); - UINT8 *pdest = BITMAP_ADDR8(machine->priority_bitmap, sy, 0); - - for( x=0; x=0 && sx<320 ) - { - UINT16 pen = pen_data[x/4]; - switch( x%4 ) - { - case 0: pen = pen>>12; break; - case 1: pen = (pen>>8)&0xf; break; - case 2: pen = (pen>>4)&0xf; break; - case 3: pen = pen&0xf; break; - } - - if( pen ) - { - if(pdest[sx]primary_screen)->inline_config)->refresh) / video_screen_get_height(machine->primary_screen) * 4), 0); + + return 0; +} + +void twin16_spriteram_process( running_machine *machine ) { UINT16 dx = scrollx[0]; UINT16 dy = scrolly[0]; - + const UINT16 *source = &spriteram16[0x0000]; const UINT16 *finish = &spriteram16[0x1800]; - - memset( &spriteram16[0x1800], 0, 0x800 ); + + twin16_set_sprite_timer(machine); + memset(&spriteram16[0x1800],0xff,0x800*sizeof(UINT16)); + while( source>4| // no-shadow? (gradius2 level 7 boss sets this bit and appears to expect pen $F to be solid) + (priority&0x200)<<5; // sprite-background priority? + dest[0] = source[3]; /* gfx data */ dest[1] = ((xpos>>8) - dx)&0xffff; dest[2] = ((ypos>>8) - dy)&0xffff; @@ -161,34 +221,8 @@ void twin16_spriteram_process( void ) need_process_spriteram = 0; } -/* - * Sprite Format - * ---------------------------------- - * - * Word | Bit(s) | Use - * -----+-fedcba9876543210-+---------------- - * 0 | --xxxxxxxxxxxxxx | code - * -----+------------------+ - * 1 | -------xxxxxxxxx | ypos - * -----+------------------+ - * 2 | -------xxxxxxxxx | xpos - * -----+------------------+ - * 3 | x--------------- | enble - * 3 | -x-------------- | priority? - * 3 | ------x--------- | yflip? - * 3 | -------x-------- | xflip - * 3 | --------xx------ | height - * 3 | ----------xx---- | width - * 3 | ------------xxxx | color - -shadow bit? - - */ - static void draw_sprites( running_machine *machine, bitmap_t *bitmap ) { - int count = 0; - const UINT16 *source = 0x1800+buffered_spriteram16 + 0x800 - 4; const UINT16 *finish = 0x1800+buffered_spriteram16; @@ -201,60 +235,50 @@ static void draw_sprites( running_machine *machine, bitmap_t *bitmap ) { int xpos = source[1]; int ypos = source[2]; - + int x,y; + int pal_base = ((attributes&0xf)+0x10)*16; int height = 16<<((attributes>>6)&0x3); int width = 16<<((attributes>>4)&0x3); const UINT16 *pen_data = 0; int flipy = attributes&0x0200; int flipx = attributes&0x0100; - - if( twin16_custom_video == 1 ) - { + int priority = (attributes&0x4000)?TWIN16_SPRITE_PRI_L1:TWIN16_SPRITE_PRI_L2; + + if( twin16_custom_video ) { + /* fround board */ pen_data = twin16_gfx_rom + 0x80000; } else { switch( (code>>12)&0x3 ) - { /* bank select */ + { + /* bank select */ case 0: - pen_data = twin16_gfx_rom; - break; + pen_data = twin16_gfx_rom; + break; case 1: - pen_data = twin16_gfx_rom + 0x40000; - break; + pen_data = twin16_gfx_rom + 0x40000; + break; case 2: - pen_data = twin16_gfx_rom + 0x80000; - if( code&0x4000 ) pen_data += 0x40000; - break; + pen_data = twin16_gfx_rom + 0x80000; + if( code&0x4000 ) pen_data += 0x40000; + break; case 3: - pen_data = twin16_sprite_gfx_ram; - break; + pen_data = twin16_sprite_gfx_ram; + break; } code &= 0xfff; } /* some code masking */ - if(height == 64 && width == 64) - { - code &= ~8; // fixes bad sprites in vulcan ending sequence - } - else if(height == 32 && width == 32) - { - code &= ~3; // fixes bad sprites in devilw - } - else if(height == 32 && width == 16) - { - code &= ~1; // fixes bad sprites in devilw - } - else if(height == 16 && width == 32) - { - code &= ~1; // fixes bad sprites in devilw - } - + if ((height&width) == 64) code &= ~8; // gradius2 ending sequence 64*64 + else if ((height&width) == 32) code &= ~3; // devilw 32*32 + else if ((height|width) == 48) code &= ~1; // devilw 32*16 / 16*32 + pen_data += code*0x40; if( video_register&TWIN16_SCREEN_FLIPY ) @@ -269,15 +293,56 @@ static void draw_sprites( running_machine *machine, bitmap_t *bitmap ) xpos = 320-xpos-width; flipx = !flipx; } - - //if( sprite_which==count || !input_code_pressed( KEYCODE_B ) ) - draw_sprite( machine, bitmap, pen_data, pal_base, xpos, ypos, width, height, flipx, flipy, (attributes&0x4000) ); + if( xpos>=320 ) xpos -= 65536; + if( ypos>=256 ) ypos -= 65536; + + /* slow slow slow, but it's ok for now */ + for( y=0; y=16 && sy<256-16 ) + { + UINT16 *dest = BITMAP_ADDR16(bitmap, sy, 0); + UINT8 *pdest = BITMAP_ADDR8(machine->priority_bitmap, sy, 0); + + for( x=0; x=0 && sx<320 ) + { + UINT16 pen = pen_data[x>>2]>>((~x&3)<<2)&0xf; + + if( pen ) + { + int shadow = (pen==0xf) & ((attributes&0x400)==0); + + if (pdest[sx]shadow_table[dest[sx]]; + pdest[sx]|=TWIN16_SPRITE_CAST_SHADOW; + } + else { + dest[sx] = pal_base + pen; + } + } + else if (!shadow && pdest[sx]&TWIN16_SPRITE_CAST_SHADOW && (pdest[sx]&0xf)shadow_table[pal_base + pen]; + pdest[sx]^=TWIN16_SPRITE_CAST_SHADOW; + } + + pdest[sx]|=TWIN16_SPRITE_OCCUPIED; + } + } + } + } + } } - - count++; } } + + static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) { const UINT16 *gfx_base; @@ -285,34 +350,31 @@ static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) int i, xxor, yxor; int bank_table[4]; int dx, dy, palette; - int tile_flipx = 0; // video_register&TWIN16_TILE_FLIPX; + int tile_flipx = video_register&TWIN16_TILE_FLIPX; int tile_flipy = video_register&TWIN16_TILE_FLIPY; - - if( ((video_register&TWIN16_PLANE_ORDER)?1:0) != opaque ) - { + + if( ((video_register&TWIN16_PLANE_ORDER)?1:0) != opaque ) { source += 0x1000; dx = scrollx[2]; dy = scrolly[2]; palette = 1; } - else - { + else { source += 0x0000; dx = scrollx[1]; dy = scrolly[1]; palette = 0; } - if( twin16_custom_video == 1 ) - { + if( twin16_custom_video ) { + /* fround board */ gfx_base = twin16_gfx_rom; bank_table[3] = (gfx_bank>>(4*3))&0xf; bank_table[2] = (gfx_bank>>(4*2))&0xf; bank_table[1] = (gfx_bank>>(4*1))&0xf; bank_table[0] = (gfx_bank>>(4*0))&0xf; } - else - { + else { gfx_base = twin16_tile_gfx_ram; bank_table[0] = 0; bank_table[1] = 1; @@ -358,11 +420,11 @@ static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) if (x1 <= x2 && y1 <= y2) { int code = source[i]; - /* - xxx------------- color - ---xx----------- tile bank - -----xxxxxxxxxxx tile number - */ + /* fedcba9876543210 + xxx------------- color + ---xx----------- tile bank + -----xxxxxxxxxxx tile number + */ const UINT16 *gfx_data = gfx_base + (code&0x7ff)*16 + bank_table[(code>>11)&0x3]*0x8000; int color = (code>>13); int pal_base = 16*(0x20+color+8*palette); @@ -381,7 +443,7 @@ static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) int effx = (x - xpos) ^ xxor; UINT16 data = gfxptr[effx / 4]; dest[x] = pal_base + ((data >> 4*(~effx & 3)) & 0x0f); - pdest[x] |= 1; + pdest[x] |= TWIN16_BG_LAYER1; } } } @@ -401,7 +463,7 @@ static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) if (pen) { dest[x] = pal_base + pen; - pdest[x] |= 4; + pdest[x] |= TWIN16_BG_LAYER2; } } } @@ -410,59 +472,80 @@ static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque ) } } -static TILE_GET_INFO( get_fg_tile_info ) +static TILE_GET_INFO( get_text_tile_info ) { - const UINT16 *source = twin16_videoram2; + const UINT16 *source = twin16_text_ram; int attr = source[tile_index]; + /* fedcba9876543210 + -x-------------- yflip + --x------------- xflip + ---xxxx--------- color + -------xxxxxxxxx tile number + */ int code = attr & 0x1ff; int color = (attr >> 9) & 0x0f; - - SET_TILE_INFO(0, code, color, 0); + int flags=0; + + if (attr&0x2000) flags|=TILE_FLIPX; + if (attr&0x4000) flags|=TILE_FLIPY; + + SET_TILE_INFO(0, code, color, flags); } VIDEO_START( twin16 ) { - fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows_flip_y, 8, 8, 64, 32); - - tilemap_set_transparent_pen(fg_tilemap, 0); -} - -VIDEO_START( fround ) -{ - fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows, 8, 8, 64, 32); - - tilemap_set_transparent_pen(fg_tilemap, 0); + text_tilemap = tilemap_create(machine, get_text_tile_info, tilemap_scan_rows, 8, 8, 64, 32); + tilemap_set_transparent_pen(text_tilemap, 0); + + memset(twin16_sprite_buffer,0xff,0x800*sizeof(UINT16)); + twin16_sprite_busy = 0; + twin16_sprite_timer = timer_alloc(machine, twin16_sprite_tick, NULL); + timer_adjust_oneshot(twin16_sprite_timer, attotime_never, 0); + + /* register for savestates */ + state_save_register_global_array(machine, twin16_sprite_buffer); + state_save_register_global_array(machine, scrollx); + state_save_register_global_array(machine, scrolly); + + state_save_register_global(machine, need_process_spriteram); + state_save_register_global(machine, gfx_bank); + state_save_register_global(machine, video_register); + state_save_register_global(machine, twin16_sprite_busy); } VIDEO_UPDATE( twin16 ) { + int text_flip=0; + if (video_register&TWIN16_SCREEN_FLIPX) text_flip|=TILEMAP_FLIPX; + if (video_register&TWIN16_SCREEN_FLIPY) text_flip|=TILEMAP_FLIPY; + bitmap_fill(screen->machine->priority_bitmap,cliprect,0); draw_layer( screen->machine, bitmap, 1 ); - - if (twin16_custom_video) - { - draw_layer( screen->machine, bitmap, 0 ); - draw_sprites( screen->machine, bitmap ); - } - else // devilw, vulcan - different priorities order? there should be an enable bit somewhere... - { - draw_sprites( screen->machine, bitmap ); - draw_layer( screen->machine, bitmap, 0 ); - } - - tilemap_draw(bitmap, cliprect, fg_tilemap, 0, 0); + draw_layer( screen->machine, bitmap, 0 ); + draw_sprites( screen->machine, bitmap ); + + if (text_flip) tilemap_set_flip(text_tilemap, text_flip); + tilemap_draw(bitmap, cliprect, text_tilemap, 0, 0); return 0; } VIDEO_EOF( twin16 ) { - const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); - - if( twin16_spriteram_process_enable() && need_process_spriteram ) - twin16_spriteram_process(); - - need_process_spriteram = 1; - - buffer_spriteram16_w(space,0,0,0xffff); + twin16_set_sprite_timer(machine); + + if (twin16_spriteram_process_enable()) { + if (need_process_spriteram) twin16_spriteram_process(machine); + need_process_spriteram = 1; + + /* if the sprite preprocessor is used, sprite ram is copied to an external buffer first, + as evidenced by 1-frame sprite lag in gradius2 and devilw otherwise, though there's probably + more to it than that */ + memcpy(&buffered_spriteram16[0x1800],twin16_sprite_buffer,0x800*sizeof(UINT16)); + memcpy(twin16_sprite_buffer,&spriteram16[0x1800],0x800*sizeof(UINT16)); + } + else { + const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); + buffer_spriteram16_w(space,0,0,0xffff); + } }