Sent: Wednesday, August 12, 2009 4:27 PM
To: submit@mamedev.org
Subject: twin16 update
Hello,

Attached is an update for the Konami twin16 driver, see diff for details.
Functional changes:
- improved sprite status register, this fixed the rogue sprites problem in devilw
- added fround coin counters
- lowered k007232 volume
- added savestate support
- added shadows
- fixed devilw and gradius2 sprite lag
- added text layer x/y flipping
- reverted gradius2 sprite-background priority hack, this fixes severe priority problems in 
devilw, but reintroduces bugs on gradius2 level 7 and ending

affected mametesters bugs:
fixed: 02267, 00191, 02553
partial, due to revert: 02523 (intro is ok again, but old priority bugs are reintroduced), 
02268 (ok in-game, small priority problem in prologue)

Greets,
hap
This commit is contained in:
Aaron Giles 2009-08-13 05:17:16 +00:00
parent 5fae7c5093
commit 55480e3ce9
6 changed files with 428 additions and 358 deletions

View File

@ -204,7 +204,7 @@ void timer_device_adjust_periodic(const device_config *timer, attotime start_del
/* ----- anonymous timer management ----- */ /* ----- anonymous timer management ----- */
/* allocate a one-shot timer, which calls the callback after the given duration */ /* 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 */ /* 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); 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);

View File

@ -439,7 +439,7 @@ static void init_buffered_spriteram(running_machine *machine)
/* register for saving it */ /* register for saving it */
state_save_register_global_pointer(machine, buffered_spriteram, spriteram_size); 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) if (spriteram_2_size)
{ {
/* allocate memory */ /* allocate memory */

View File

@ -8,47 +8,38 @@ SOUND : YM2151 007232 uPD7759C
OSC. : 3.579545MHz 18432.00KHz OSC. : 3.579545MHz 18432.00KHz
Main processors are a pair of 68000 CPUs 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 Dark Adventure / Devil World / Majuu no Ohkoku
Vulcan Venture / Gradius II Vulcan Venture / Gradius II
Cuebrick Cuebrick
MIA (Japan) MIA (Japan)
Final Round / Hard Puncher (Japan) Final Round / Hard Puncher (Japan)
Known Issues:
- some rogue sprites in Devil World
- sprite-background priority is guessed
68000 Memory Map for Konami Twin System 68000 Memory Map for Konami Twin System
CPUA CPUB CPUA CPUB
0x000000..0x03ffff ROM 0x000000..0x03ffff 0x000000..0x03ffff ROM 0x000000..0x03ffff
0x040000..0x043fff communication RAM 0x040000..0x043fff (shared) 0x040000..0x043fff communication RAM 0x040000..0x043fff (shared)
0x060000..0x063fff work RAM 0x060000..0x063fff 0x060000..0x063fff work RAM 0x060000..0x063fff
0x080000..0x080fff palette 0x080000..0x080fff palette
0x080000..0x09ffff ROM (extra tile data) 0x080000..0x09ffff ROM (extra tile data)
0x0a0000..0x0a0001 IRQ control 0x0a0000..0x0a0001 0x0a0000..0x0a0001 IRQ control 0x0a0000..0x0a0001
0x0a0008..0x0a0009 sound command 0x0a0008..0x0a0009 sound command
0x0a0010..0xa00011 watchdog 0x0a0010..0xa00011 watchdog
0x0c0000..0x0c0001 screenflip 0x0c0000..0x0c0001 screenflip
0x0c0002..0x0c000f scroll registers 0x0c0002..0x0c000f scroll registers
0x100000..0x103fff FIXRAM (text layer) 0x100000..0x103fff FIXRAM (text layer)
0x120000..0x123fff VIDRAM (tilemaps) 0x480000..0x483fff (shared) 0x120000..0x123fff VIDRAM (tilemaps) 0x480000..0x483fff (shared)
0x140000..0x143fff OBJRAM (sprites) 0x400000..0x403fff (shared) 0x140000..0x143fff OBJRAM (sprites) 0x400000..0x403fff (shared)
ZIP RAM (tiles) 0x500000..0x53ffff ZIP RAM (tiles) 0x500000..0x53ffff
gfx ROM (banked) 0x600000..0x77ffff gfx ROM (banked) 0x600000..0x77ffff
sprite gfx RAM 0x780000..0x79ffff sprite gfx RAM 0x780000..0x79ffff
*/
/* Known Issues:
- repeated uPD7759C samples in fround, disconnecting reset helps but doesn't fix it
Konami Twin16 Hardware - see video/twin16.c for graphics related issues
TODO:
- mia reset crash
*/ */
@ -65,18 +56,17 @@ UINT16 twin16_custom_video;
UINT16 *twin16_gfx_rom; UINT16 *twin16_gfx_rom;
UINT16 *twin16_sprite_gfx_ram; UINT16 *twin16_sprite_gfx_ram;
UINT16 *twin16_tile_gfx_ram; UINT16 *twin16_tile_gfx_ram;
UINT16 *twin16_videoram2; /* text layer */ UINT16 *twin16_text_ram;
static UINT16 twin16_CPUA_register, twin16_CPUB_register; static UINT16 twin16_CPUA_register, twin16_CPUB_register;
#define CPUA_IRQ_ENABLE (twin16_CPUA_register & 0x20) #define CPUA_IRQ_ENABLE (twin16_CPUA_register & 0x20)
#define CPUB_IRQ_ENABLE (twin16_CPUB_register & 0x02) #define CPUB_IRQ_ENABLE (twin16_CPUB_register & 0x02)
static UINT8 twin16_soundlatch;
static UINT16 twin16_sound_command; static UINT16 twin16_sound_command;
static int cuebrckj_nvram_bank; static int cuebrickj_nvram_bank;
static UINT16 cuebrckj_nvram[0x400*0x20]; // 32k paged in a 1k window static UINT16 cuebrickj_nvram[0x400*0x20]; // 32k paged in a 1k window
int twin16_spriteram_process_enable( void ) int twin16_spriteram_process_enable( void )
@ -108,7 +98,7 @@ static READ16_HANDLER( extra_rom_r )
static READ16_HANDLER( twin16_gfx_rom1_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 ) 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 ); 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 ) static WRITE16_HANDLER( twin16_CPUA_register_w )
{ {
/* /*
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
? sprite protection disable X sprite processing disable
X IRQ5 enable (CPUA) X IRQ5 enable (CPUA)
X 0->1 trigger IRQ6 on CPUB X 0->1 trigger IRQ6 on CPUB
X 0->1 trigger IRQ on sound CPU X 0->1 trigger IRQ on sound CPU
x x x coin counters x x x coin counters
*/ */
UINT16 old = twin16_CPUA_register; UINT16 old = twin16_CPUA_register;
COMBINE_DATA(&twin16_CPUA_register); COMBINE_DATA(&twin16_CPUA_register);
if (twin16_CPUA_register != old) 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); cputag_set_input_line_and_vector(space->machine, "audiocpu", 0, HOLD_LINE, 0xff);
if ((old & 0x40) && (twin16_CPUA_register & 0x40) == 0) if ((old & 0x40) && (twin16_CPUA_register & 0x40) == 0)
twin16_spriteram_process(); twin16_spriteram_process(space->machine);
if ((old & 0x10) == 0 && (twin16_CPUA_register & 0x10)) if ((old & 0x10) == 0 && (twin16_CPUA_register & 0x10))
cputag_set_input_line(space->machine, "sub", M68K_IRQ_6, HOLD_LINE); 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 ) static WRITE16_HANDLER( twin16_CPUB_register_w )
{ {
/* /*
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
X gfx bank select X gfx bank select
X IRQ5 enable X IRQ5 enable
X 0->1 trigger IRQ6 on CPUA X 0->1 trigger IRQ6 on CPUA
*/ */
UINT16 old = twin16_CPUB_register; UINT16 old = twin16_CPUB_register;
COMBINE_DATA(&twin16_CPUB_register); COMBINE_DATA(&twin16_CPUB_register);
if( twin16_CPUB_register!=old ) if( twin16_CPUB_register!=old )
{ {
if ((old & 0x01) == 0 && (twin16_CPUB_register & 0x01)) if ((old & 0x01) == 0 && (twin16_CPUB_register & 0x01))
{
cputag_set_input_line(space->machine, "maincpu", M68K_IRQ_6, HOLD_LINE); cputag_set_input_line(space->machine, "maincpu", M68K_IRQ_6, HOLD_LINE);
}
} }
} }
static WRITE16_HANDLER( fround_CPU_register_w ) 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; UINT16 old = twin16_CPUA_register;
COMBINE_DATA(&twin16_CPUA_register); COMBINE_DATA(&twin16_CPUA_register);
if (twin16_CPUA_register != old) if (twin16_CPUA_register != old)
{ {
if ((old & 0x08) == 0 && (twin16_CPUA_register & 0x08)) 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 0x08: return input_port_read(space->machine, "DSW2");
case 0x09: return input_port_read(space->machine, "DSW1"); case 0x09: return input_port_read(space->machine, "DSW1");
case 0x0c: return input_port_read(space->machine, "DSW3"); case 0x0c: return input_port_read(space->machine, "DSW3");
default: break;
} }
return 0; 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(device, data & 2);
upd7759_reset_w(devtag_get_device(space->machine, "upd"), data & 0x02);
twin16_soundlatch = data;
} }
static WRITE8_DEVICE_HANDLER( twin16_upd_start_w ) 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); 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)]); cuebrickj_nvram_bank = (data >> 8);
}
static WRITE16_HANDLER( cuebrckj_nvram_bank_w )
{
cuebrckj_nvram_bank = (data >> 8);
} }
/* Memory Maps */ /* Memory Maps */
@ -251,19 +228,19 @@ static WRITE16_HANDLER( cuebrckj_nvram_bank_w )
static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 ) static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x7fff) AM_ROM AM_RANGE(0x0000, 0x7fff) AM_ROM
AM_RANGE(0x8000, 0x8fff) AM_RAM 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(0xa000, 0xa000) AM_READ(soundlatch_r)
AM_RANGE(0xb000, 0xb00d) AM_DEVREADWRITE("konami", k007232_r, k007232_w) AM_RANGE(0xb000, 0xb00d) AM_DEVREADWRITE("konami", k007232_r, k007232_w)
AM_RANGE(0xc000, 0xc001) AM_DEVREADWRITE("ym", ym2151_r, ym2151_w) AM_RANGE(0xc000, 0xc001) AM_DEVREADWRITE("ym", ym2151_r, ym2151_w)
AM_RANGE(0xd000, 0xd000) AM_DEVWRITE("upd", upd7759_port_w) AM_RANGE(0xd000, 0xd000) AM_DEVWRITE("upd", upd7759_port_w)
AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("upd", twin16_upd_start_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 ADDRESS_MAP_END
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM AM_RANGE(0x000000, 0x03ffff) AM_ROM
AM_RANGE(0x040000, 0x043fff) AM_READWRITE(COMRAM_r, COMRAM_w) 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(0x060000, 0x063fff) AM_RAM
AM_RANGE(0x080000, 0x080fff) AM_RAM_WRITE(twin16_paletteram_word_w) AM_BASE(&paletteram16) AM_RANGE(0x080000, 0x080fff) AM_RAM_WRITE(twin16_paletteram_word_w) AM_BASE(&paletteram16)
AM_RANGE(0x081000, 0x081fff) AM_WRITENOP 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(0x0a0000, 0x0a0001) AM_WRITE(twin16_CPUA_register_w)
AM_RANGE(0x0a0008, 0x0a0009) AM_WRITE(sound_command_w) AM_RANGE(0x0a0008, 0x0a0009) AM_WRITE(sound_command_w)
AM_RANGE(0x0a0010, 0x0a0011) AM_WRITE(watchdog_reset16_w) AM_RANGE(0x0a0010, 0x0a0011) AM_WRITE(watchdog_reset16_w)
AM_RANGE(0x0b0000, 0x0b03ff) AM_READWRITE(cuebrckj_nvram_r, cuebrckj_nvram_w) AM_RANGE(0x0b0000, 0x0b03ff) AM_READWRITE(cuebrickj_nvram_r, cuebrickj_nvram_w)
AM_RANGE(0x0b0400, 0x0b0401) AM_WRITE(cuebrckj_nvram_bank_w) AM_RANGE(0x0b0400, 0x0b0401) AM_WRITE(cuebrickj_nvram_bank_w)
AM_RANGE(0x0c0000, 0x0c000f) AM_WRITE(twin16_video_register_w) AM_RANGE(0x0c0000, 0x0c000f) AM_WRITE(twin16_video_register_w)
AM_RANGE(0x0c000e, 0x0c000f) AM_READ(twin16_sprite_status_r) 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(0x100000, 0x103fff) AM_RAM_WRITE(twin16_text_ram_w) AM_BASE(&twin16_text_ram)
AM_RANGE(0x104000, 0x105fff) AM_RAM // miaj // AM_RANGE(0x104000, 0x105fff) AM_NOP // miaj
AM_RANGE(0x120000, 0x123fff) AM_RAM AM_BASE(&videoram16) 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) AM_RANGE(0x140000, 0x143fff) AM_RAM AM_SHARE(1) AM_BASE(&spriteram16) AM_SIZE(&spriteram_size)
ADDRESS_MAP_END ADDRESS_MAP_END
@ -284,7 +261,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( sub_map, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( sub_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM AM_RANGE(0x000000, 0x03ffff) AM_ROM
AM_RANGE(0x040000, 0x043fff) AM_READWRITE(COMRAM_r, COMRAM_w) 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(0x060000, 0x063fff) AM_RAM
AM_RANGE(0x080000, 0x09ffff) AM_READ(extra_rom_r) AM_RANGE(0x080000, 0x09ffff) AM_READ(extra_rom_r)
AM_RANGE(0x0a0000, 0x0a0001) AM_WRITE(twin16_CPUB_register_w) 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(0x0c0000, 0x0c000f) AM_WRITE(twin16_video_register_w)
AM_RANGE(0x0c000e, 0x0c000f) AM_READ(twin16_sprite_status_r) AM_RANGE(0x0c000e, 0x0c000f) AM_READ(twin16_sprite_status_r)
AM_RANGE(0x0e0000, 0x0e0001) AM_WRITE(fround_gfx_bank_w) 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(0x120000, 0x123fff) AM_RAM AM_BASE(&videoram16)
AM_RANGE(0x140000, 0x143fff) AM_RAM AM_BASE(&spriteram16) AM_SIZE(&spriteram_size) AM_RANGE(0x140000, 0x143fff) AM_RAM AM_BASE(&spriteram16) AM_SIZE(&spriteram_size)
AM_RANGE(0x500000, 0x6fffff) AM_READ(twin16_gfx_rom1_r) 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_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P1") /* 0xa0003 */ 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 */ PORT_START("P2") /* 0xa0005 */
KONAMI8_B123_UNK(2) KONAMI8_B123_UNK(2)
@ -378,7 +355,7 @@ static INPUT_PORTS_START( darkadv )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE2 )
PORT_START("P1") /* 0xa0003 */ 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_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE3 )
PORT_START("P2") /* 0xa0005 */ PORT_START("P2") /* 0xa0005 */
@ -438,14 +415,14 @@ static INPUT_PORTS_START( vulcan )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) 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( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P1") /* 0xa0003 */ 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 */ PORT_START("P2") /* 0xa0005 */
KONAMI8_B123_UNK(2) KONAMI8_B123_UNK(2)
@ -509,14 +486,14 @@ static INPUT_PORTS_START( fround )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) 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( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P1") /* 0xa0003 */ 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 */ PORT_START("P2") /* 0xa0005 */
KONAMI8_B123_UNK(2) KONAMI8_B123_UNK(2)
@ -559,14 +536,14 @@ static INPUT_PORTS_START( miaj )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) 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( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P1") /* 0xa0003 */ 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 */ PORT_START("P2") /* 0xa0005 */
KONAMI8_B123_UNK(2) KONAMI8_B123_UNK(2)
@ -611,19 +588,19 @@ static INPUT_PORTS_START( miaj )
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END INPUT_PORTS_END
static INPUT_PORTS_START( cuebrckj ) static INPUT_PORTS_START( cuebrickj )
PORT_START("SYSTEM") /* 0xa0001 */ PORT_START("SYSTEM") /* 0xa0001 */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) 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( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P1") /* 0xa0003 */ 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 */ PORT_START("P2") /* 0xa0005 */
KONAMI8_B123_UNK(2) KONAMI8_B123_UNK(2)
@ -718,6 +695,25 @@ static INTERRUPT_GEN( CPUB_interrupt )
/* Machine Drivers */ /* 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 ) static MACHINE_DRIVER_START( twin16 )
// basic machine hardware // basic machine hardware
MDRV_CPU_ADD("maincpu", M68000, XTAL_18_432MHz/2) MDRV_CPU_ADD("maincpu", M68000, XTAL_18_432MHz/2)
@ -733,12 +729,15 @@ static MACHINE_DRIVER_START( twin16 )
MDRV_QUANTUM_TIME(HZ(6000)) MDRV_QUANTUM_TIME(HZ(6000))
MDRV_MACHINE_START(twin16)
MDRV_MACHINE_RESET(twin16)
// video hardware // video hardware
MDRV_VIDEO_ATTRIBUTES(VIDEO_BUFFERS_SPRITERAM) MDRV_VIDEO_ATTRIBUTES(VIDEO_HAS_SHADOWS | VIDEO_BUFFERS_SPRITERAM)
MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_ADD("screen", RASTER)
MDRV_SCREEN_REFRESH_RATE(((double)XTAL_18_432MHz / 2) / (576 * 264)) 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_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_SIZE(40*8, 32*8) MDRV_SCREEN_SIZE(40*8, 32*8)
MDRV_SCREEN_VISIBLE_AREA(0, 40*8-1, 2*8, 30*8-1) 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_ADD("konami", K007232, 3579545)
MDRV_SOUND_CONFIG(k007232_config) MDRV_SOUND_CONFIG(k007232_config)
MDRV_SOUND_ROUTE(0, "lspeaker", 0.20) MDRV_SOUND_ROUTE(0, "lspeaker", 0.12) // estimated with gradius2 OST
MDRV_SOUND_ROUTE(0, "rspeaker", 0.20) MDRV_SOUND_ROUTE(0, "rspeaker", 0.12)
MDRV_SOUND_ROUTE(1, "lspeaker", 0.20) MDRV_SOUND_ROUTE(1, "lspeaker", 0.12)
MDRV_SOUND_ROUTE(1, "rspeaker", 0.20) MDRV_SOUND_ROUTE(1, "rspeaker", 0.12)
MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK) MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20)
@ -771,7 +770,7 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( devilw ) static MACHINE_DRIVER_START( devilw )
MDRV_IMPORT_FROM(twin16) MDRV_IMPORT_FROM(twin16)
MDRV_QUANTUM_TIME(HZ(60000)) MDRV_QUANTUM_TIME(HZ(60000)) // watchdog reset otherwise
MACHINE_DRIVER_END MACHINE_DRIVER_END
static MACHINE_DRIVER_START( fround ) static MACHINE_DRIVER_START( fround )
@ -785,8 +784,11 @@ static MACHINE_DRIVER_START( fround )
MDRV_QUANTUM_TIME(HZ(6000)) MDRV_QUANTUM_TIME(HZ(6000))
MDRV_MACHINE_START(twin16)
MDRV_MACHINE_RESET(twin16)
/* video hardware */ /* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_BUFFERS_SPRITERAM) MDRV_VIDEO_ATTRIBUTES(VIDEO_HAS_SHADOWS | VIDEO_BUFFERS_SPRITERAM)
MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_ADD("screen", RASTER)
MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_REFRESH_RATE(60)
@ -798,7 +800,7 @@ static MACHINE_DRIVER_START( fround )
MDRV_GFXDECODE(twin16) MDRV_GFXDECODE(twin16)
MDRV_PALETTE_LENGTH(0x400) MDRV_PALETTE_LENGTH(0x400)
MDRV_VIDEO_START(fround) MDRV_VIDEO_START(twin16)
MDRV_VIDEO_UPDATE(twin16) MDRV_VIDEO_UPDATE(twin16)
MDRV_VIDEO_EOF(twin16) MDRV_VIDEO_EOF(twin16)
@ -811,33 +813,26 @@ static MACHINE_DRIVER_START( fround )
MDRV_SOUND_ADD("konami", K007232, 3579545) MDRV_SOUND_ADD("konami", K007232, 3579545)
MDRV_SOUND_CONFIG(k007232_config) MDRV_SOUND_CONFIG(k007232_config)
MDRV_SOUND_ROUTE(0, "lspeaker", 0.20) MDRV_SOUND_ROUTE(0, "lspeaker", 0.12)
MDRV_SOUND_ROUTE(0, "rspeaker", 0.20) MDRV_SOUND_ROUTE(0, "rspeaker", 0.12)
MDRV_SOUND_ROUTE(1, "lspeaker", 0.20) MDRV_SOUND_ROUTE(1, "lspeaker", 0.12)
MDRV_SOUND_ROUTE(1, "rspeaker", 0.20) MDRV_SOUND_ROUTE(1, "rspeaker", 0.12)
MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK) MDRV_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.20)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.20) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.20)
MACHINE_DRIVER_END MACHINE_DRIVER_END
static MACHINE_DRIVER_START( hpuncher )
MDRV_IMPORT_FROM(twin16)
MDRV_VIDEO_START(fround)
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( miaj ) static MACHINE_DRIVER_START( miaj )
MDRV_IMPORT_FROM(twin16) MDRV_IMPORT_FROM(twin16)
MDRV_SCREEN_MODIFY("screen") MDRV_SCREEN_MODIFY("screen")
MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1) MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1)
MDRV_VIDEO_START(fround)
MACHINE_DRIVER_END MACHINE_DRIVER_END
static MACHINE_DRIVER_START( cuebrckj ) static MACHINE_DRIVER_START( cuebrickj )
MDRV_IMPORT_FROM(twin16) MDRV_IMPORT_FROM(twin16)
MDRV_SCREEN_MODIFY("screen") MDRV_SCREEN_MODIFY("screen")
MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1) MDRV_SCREEN_VISIBLE_AREA(1*8, 39*8-1, 2*8, 30*8-1)
MDRV_VIDEO_START(fround)
MDRV_NVRAM_HANDLER(generic_0fill) MDRV_NVRAM_HANDLER(generic_0fill)
MACHINE_DRIVER_END MACHINE_DRIVER_END
@ -1201,7 +1196,7 @@ ROM_START( miaj )
ROM_REGION( 0x20000, "upd", ROMREGION_ERASE00 ) // samples ROM_REGION( 0x20000, "upd", ROMREGION_ERASE00 ) // samples
ROM_END ROM_END
ROM_START( cuebrckj ) ROM_START( cuebrickj )
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code (CPU A) 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_e05.6n", 0x00000, 0x10000, CRC(8b556220) SHA1(dbe24133e74018c4fe9332519394cbb882c4ed5a) )
ROM_LOAD16_BYTE( "903_e04.4n", 0x00001, 0x10000, CRC(bf9c7927) SHA1(3a594b8846f7e6074ca54f8cd5fe2ba3b64ba740) ) 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 ) static void gfx_untangle( running_machine *machine )
{ {
// sprite, tile data // sprite, tile data
int i; int i;
UINT16 *temp = alloc_array_or_die(UINT16, 0x200000/2); UINT16 *temp = alloc_array_or_die(UINT16, 0x200000/2);
twin16_gfx_rom = (UINT16 *)memory_region(machine, "gfx2"); twin16_gfx_rom = (UINT16 *)memory_region(machine, "gfx2");
memcpy( temp, twin16_gfx_rom, 0x200000 ); memcpy( temp, twin16_gfx_rom, 0x200000 );
for( i=0; i<0x080000; i++ ) for( i=0; i<0x080000; i++ )
{ {
twin16_gfx_rom[i*2+0] = temp[i+0x080000]; twin16_gfx_rom[i*2+0] = temp[i+0x080000];
twin16_gfx_rom[i*2+1] = temp[i]; twin16_gfx_rom[i*2+1] = temp[i];
} }
free( temp ); free( temp );
} }
static DRIVER_INIT( twin16 ) static DRIVER_INIT( twin16 )
@ -1266,33 +1260,26 @@ static DRIVER_INIT( fround )
twin16_custom_video = 1; twin16_custom_video = 1;
} }
static DRIVER_INIT( hpuncher ) static DRIVER_INIT( cuebrickj )
{ {
gfx_untangle(machine); gfx_untangle(machine);
twin16_custom_video = 2;
}
static DRIVER_INIT( cuebrckj ) generic_nvram = (UINT8 *)cuebrickj_nvram;
{
gfx_untangle(machine);
twin16_custom_video = 2;
generic_nvram = (UINT8 *)cuebrckj_nvram;
generic_nvram_size = 0x400*0x20; generic_nvram_size = 0x400*0x20;
} }
/* Game Drivers */ /* Game Drivers */
GAME( 1987, devilw, 0, devilw, devilw, twin16, ROT0, "Konami", "Devil World", 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", 0 ) 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", 0 ) 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", 0 ) 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.)", 0 ) 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.)", 0 ) 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.)", 0 ) 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, 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)", 0 ) GAME( 1988, froundl, fround, fround, fround, fround, ROT0, "Konami", "The Final Round (version L)", GAME_SUPPORTS_SAVE )
GAME( 1988, hpuncher, fround, hpuncher, fround, hpuncher, ROT0, "Konami", "Hard Puncher (Japan)", 0 ) GAME( 1988, hpuncher, fround, twin16, fround, twin16, ROT0, "Konami", "Hard Puncher (Japan)", GAME_SUPPORTS_SAVE )
GAME( 1989, miaj, mia, miaj, miaj, hpuncher, ROT0, "Konami", "M.I.A. - Missing in Action (Japan)", 0 ) GAME( 1989, miaj, mia, miaj, miaj, twin16, ROT0, "Konami", "M.I.A. - Missing in Action (Japan)", GAME_SUPPORTS_SAVE )
GAME( 1989, cuebrckj, cuebrick, cuebrckj, cuebrckj, cuebrckj, ROT0, "Konami", "Cue Brick (Japan)", 0 ) GAME( 1989, cuebrickj,cuebrick, cuebrickj, cuebrickj,cuebrickj,ROT0, "Konami", "Cue Brick (Japan)", GAME_SUPPORTS_SAVE )

View File

@ -2,7 +2,7 @@
extern UINT16 twin16_custom_video; extern UINT16 twin16_custom_video;
extern UINT16 *twin16_gfx_rom; extern UINT16 *twin16_gfx_rom;
extern UINT16 *twin16_videoram2; extern UINT16 *twin16_text_ram;
extern UINT16 *twin16_sprite_gfx_ram; extern UINT16 *twin16_sprite_gfx_ram;
extern UINT16 *twin16_tile_gfx_ram; extern UINT16 *twin16_tile_gfx_ram;
int twin16_spriteram_process_enable( void ); int twin16_spriteram_process_enable( void );
@ -10,14 +10,14 @@ int twin16_spriteram_process_enable( void );
/*----------- defined in video/twin16.c -----------*/ /*----------- defined in video/twin16.c -----------*/
WRITE16_HANDLER( twin16_videoram2_w ); WRITE16_HANDLER( twin16_text_ram_w );
WRITE16_HANDLER( twin16_paletteram_word_w ); WRITE16_HANDLER( twin16_paletteram_word_w );
WRITE16_HANDLER( fround_gfx_bank_w ); WRITE16_HANDLER( fround_gfx_bank_w );
WRITE16_HANDLER( twin16_video_register_w ); WRITE16_HANDLER( twin16_video_register_w );
READ16_HANDLER( twin16_sprite_status_r );
VIDEO_START( twin16 ); VIDEO_START( twin16 );
VIDEO_START( fround );
VIDEO_UPDATE( twin16 ); VIDEO_UPDATE( twin16 );
VIDEO_EOF( twin16 ); VIDEO_EOF( twin16 );
void twin16_spriteram_process( void ); void twin16_spriteram_process( running_machine* );

View File

@ -5312,7 +5312,7 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11
DRIVER( gradius2 ) /* GX785 (c) 1988 (Japan) */ DRIVER( gradius2 ) /* GX785 (c) 1988 (Japan) */
DRIVER( gradius2a ) /* GX785 (c) 1988 (Japan) */ DRIVER( gradius2a ) /* GX785 (c) 1988 (Japan) */
DRIVER( gradius2b ) /* 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( fround ) /* GX870 (c) 1988 */
DRIVER( froundl ) /* GX870 (c) 1988 */ DRIVER( froundl ) /* GX870 (c) 1988 */
DRIVER( hpuncher ) /* GX870 (c) 1988 (Japan) */ DRIVER( hpuncher ) /* GX870 (c) 1988 (Japan) */

View File

@ -5,17 +5,21 @@
TODO: TODO:
- convert background to tilemap - convert background to tilemap
- clean up sprite drawing - clean up sprite system
- sprite-background priorities - bad sprites in devilw, eg. odd colours for the mud/lava monster in the 1st level,
- sprite lag in devilw or wrong sprite-sprite priority sometimes -- check real arcade first
- sprite Y axis lag in vulcan - unsure about some sprite preprocessor attributes (see twin16_spriteram_process)
- add shadow sprites (alpha blending) to sprites in at least devilw
*/ */
#include "driver.h" #include "driver.h"
#include "includes/twin16.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 int need_process_spriteram;
static UINT16 gfx_bank; static UINT16 gfx_bank;
static UINT16 scrollx[3], scrolly[3]; static UINT16 scrollx[3], scrolly[3];
@ -23,19 +27,31 @@ static UINT16 video_register;
enum enum
{ {
TWIN16_SCREEN_FLIPY = 0x01, /* ? breaks devils world text layer */ TWIN16_SCREEN_FLIPY = 0x01,
TWIN16_SCREEN_FLIPX = 0x02, /* confirmed: Hard Puncher Intro */ TWIN16_SCREEN_FLIPX = 0x02, // confirmed: Hard Puncher Intro
TWIN16_UNKNOWN1 = 0x04, /* ?Hard Puncher uses this */ TWIN16_UNKNOWN1 = 0x04, // ? Hard Puncher uses this
TWIN16_PLANE_ORDER = 0x08, /* confirmed: Devil Worlds */ TWIN16_PLANE_ORDER = 0x08, // confirmed: Devil Worlds
TWIN16_TILE_FLIPY = 0x20 /* confirmed? Vulcan Venture */ TWIN16_TILE_FLIPX = 0x10, // unused?
TWIN16_TILE_FLIPY = 0x20 // confirmed? Vulcan Venture
}; };
static tilemap *fg_tilemap; enum
WRITE16_HANDLER( twin16_videoram2_w )
{ {
COMBINE_DATA(&twin16_videoram2[offset]); // user-defined priorities
tilemap_mark_tile_dirty(fg_tilemap, offset); 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 ) WRITE16_HANDLER( twin16_paletteram_word_w )
@ -60,11 +76,7 @@ WRITE16_HANDLER( twin16_video_register_w )
COMBINE_DATA( &video_register ); COMBINE_DATA( &video_register );
flip_screen_x_set(space->machine, video_register & TWIN16_SCREEN_FLIPX); flip_screen_x_set(space->machine, video_register & TWIN16_SCREEN_FLIPX);
flip_screen_y_set(space->machine, video_register & TWIN16_SCREEN_FLIPY);
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);
break; break;
@ -81,53 +93,75 @@ 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; // bit 0: busy, other bits: dunno
if( xpos>=320 ) xpos -= 65536; return twin16_sprite_busy;
if( ypos>=256 ) ypos -= 65536;
if (pri) pval=2; else pval=8;
for( y=0; y<height; y++ )
{
int sy = (flipy)?(ypos+height-1-y):(ypos+y);
if( sy>=16 && sy<256-16 )
{
UINT16 *dest = BITMAP_ADDR16(bitmap, sy, 0);
UINT8 *pdest = BITMAP_ADDR8(machine->priority_bitmap, sy, 0);
for( x=0; x<width; x++ )
{
int sx = (flipx)?(xpos+width-1-x):(xpos+x);
if( sx>=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]<pval)
{
dest[sx] = pal_base + pen;
}
pdest[sx]|=0x10;
}
}
}
}
pen_data += width/4;
}
} }
void twin16_spriteram_process( void ) static TIMER_CALLBACK( twin16_sprite_tick )
{
twin16_sprite_busy = 0;
}
static int twin16_set_sprite_timer( running_machine *machine )
{
if (twin16_sprite_busy) return 1;
// sprite system busy, maybe a dma? time is guessed, assume 4 scanlines
twin16_sprite_busy = 1;
timer_adjust_oneshot(twin16_sprite_timer, attotime_make(0,(((screen_config *)(machine->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 dx = scrollx[0];
UINT16 dy = scrolly[0]; UINT16 dy = scrolly[0];
@ -135,21 +169,47 @@ void twin16_spriteram_process( void )
const UINT16 *source = &spriteram16[0x0000]; const UINT16 *source = &spriteram16[0x0000];
const UINT16 *finish = &spriteram16[0x1800]; const UINT16 *finish = &spriteram16[0x1800];
memset( &spriteram16[0x1800], 0, 0x800 ); twin16_set_sprite_timer(machine);
memset(&spriteram16[0x1800],0xff,0x800*sizeof(UINT16));
while( source<finish ) while( source<finish )
{ {
UINT16 priority = source[0]; UINT16 priority = source[0];
if( priority & 0x8000 ) if( priority & 0x8000 )
{ {
UINT16 *dest = &spriteram16[0x1800 + 4*(priority&0xff)]; UINT16 *dest = &spriteram16[0x1800|(priority&0xff)<<2];
INT32 xpos = (0x10000*source[4])|source[5]; UINT32 xpos = (0x10000*source[4])|source[5];
INT32 ypos = (0x10000*source[6])|source[7]; UINT32 ypos = (0x10000*source[6])|source[7];
UINT16 attributes = source[2]&0x03ff; /* scale,size,color */ /* notes on uncertain attributes:
if( priority & 0x0200 ) attributes |= 0x4000; shadows: pen $F only (like other Konami hw), used in devilw, fround,
/* Todo: priority & 0x0100 is also used */ miaj? (shadows are solid in tmnt hw version),
attributes |= 0x8000; gradius2? (ship exhaust)
sprite-background priority: in devilw, most sprites look best at high priority,
in gradius2, most sprites look best at low priority. exceptions:
- devilw prologue: sprites behind crowd (maybe more, haven't completed the game)
- gradius2 intro showing earlier games: sprites above layers
currently using (priority&0x200), broken:
- devilw prologue: sprites should be behind crowd
- gradius2 level 7: bosses should be behind portal (ok except brain boss and mouth boss)
- gradius2 ending: sun should be behind planet
does TWIN16_PLANE_ORDER affect it?
more?
devilw monster dens exploding monochrome, players fading to white in prologue, and trees in
the 1st level shrinking with a solid green color look odd, maybe alpha blended?
fround, hpuncher, miaj, cuebrickj, don't use the preprocessor. all sprites are expected
to be high priority, and shadows are enabled
*/
UINT16 attributes = 0x8000| // enabled
(source[2]&0x03ff)| // scale,size,color
(source[2]&0x4000)>>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[0] = source[3]; /* gfx data */
dest[1] = ((xpos>>8) - dx)&0xffff; dest[1] = ((xpos>>8) - dx)&0xffff;
@ -161,34 +221,8 @@ void twin16_spriteram_process( void )
need_process_spriteram = 0; 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 ) static void draw_sprites( running_machine *machine, bitmap_t *bitmap )
{ {
int count = 0;
const UINT16 *source = 0x1800+buffered_spriteram16 + 0x800 - 4; const UINT16 *source = 0x1800+buffered_spriteram16 + 0x800 - 4;
const UINT16 *finish = 0x1800+buffered_spriteram16; const UINT16 *finish = 0x1800+buffered_spriteram16;
@ -201,6 +235,7 @@ static void draw_sprites( running_machine *machine, bitmap_t *bitmap )
{ {
int xpos = source[1]; int xpos = source[1];
int ypos = source[2]; int ypos = source[2];
int x,y;
int pal_base = ((attributes&0xf)+0x10)*16; int pal_base = ((attributes&0xf)+0x10)*16;
int height = 16<<((attributes>>6)&0x3); int height = 16<<((attributes>>6)&0x3);
@ -208,52 +243,41 @@ static void draw_sprites( running_machine *machine, bitmap_t *bitmap )
const UINT16 *pen_data = 0; const UINT16 *pen_data = 0;
int flipy = attributes&0x0200; int flipy = attributes&0x0200;
int flipx = attributes&0x0100; int flipx = attributes&0x0100;
int priority = (attributes&0x4000)?TWIN16_SPRITE_PRI_L1:TWIN16_SPRITE_PRI_L2;
if( twin16_custom_video == 1 ) if( twin16_custom_video ) {
{ /* fround board */
pen_data = twin16_gfx_rom + 0x80000; pen_data = twin16_gfx_rom + 0x80000;
} }
else else
{ {
switch( (code>>12)&0x3 ) switch( (code>>12)&0x3 )
{ /* bank select */ {
/* bank select */
case 0: case 0:
pen_data = twin16_gfx_rom; pen_data = twin16_gfx_rom;
break; break;
case 1: case 1:
pen_data = twin16_gfx_rom + 0x40000; pen_data = twin16_gfx_rom + 0x40000;
break; break;
case 2: case 2:
pen_data = twin16_gfx_rom + 0x80000; pen_data = twin16_gfx_rom + 0x80000;
if( code&0x4000 ) pen_data += 0x40000; if( code&0x4000 ) pen_data += 0x40000;
break; break;
case 3: case 3:
pen_data = twin16_sprite_gfx_ram; pen_data = twin16_sprite_gfx_ram;
break; break;
} }
code &= 0xfff; code &= 0xfff;
} }
/* some code masking */ /* some code masking */
if(height == 64 && width == 64) if ((height&width) == 64) code &= ~8; // gradius2 ending sequence 64*64
{ else if ((height&width) == 32) code &= ~3; // devilw 32*32
code &= ~8; // fixes bad sprites in vulcan ending sequence else if ((height|width) == 48) code &= ~1; // devilw 32*16 / 16*32
}
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
}
pen_data += code*0x40; pen_data += code*0x40;
@ -269,15 +293,56 @@ static void draw_sprites( running_machine *machine, bitmap_t *bitmap )
xpos = 320-xpos-width; xpos = 320-xpos-width;
flipx = !flipx; flipx = !flipx;
} }
if( xpos>=320 ) xpos -= 65536;
if( ypos>=256 ) ypos -= 65536;
//if( sprite_which==count || !input_code_pressed( KEYCODE_B ) ) /* slow slow slow, but it's ok for now */
draw_sprite( machine, bitmap, pen_data, pal_base, xpos, ypos, width, height, flipx, flipy, (attributes&0x4000) ); for( y=0; y<height; y++, pen_data += width/4 )
{
int sy = (flipy)?(ypos+height-1-y):(ypos+y);
if( sy>=16 && sy<256-16 )
{
UINT16 *dest = BITMAP_ADDR16(bitmap, sy, 0);
UINT8 *pdest = BITMAP_ADDR8(machine->priority_bitmap, sy, 0);
for( x=0; x<width; x++ )
{
int sx = (flipx)?(xpos+width-1-x):(xpos+x);
if( sx>=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]<priority) {
if (shadow) {
dest[sx] = machine->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)<priority) {
// shadow cast onto sprite below, evident in devilw lava level
dest[sx] = machine->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 ) static void draw_layer( running_machine *machine, bitmap_t *bitmap, int opaque )
{ {
const UINT16 *gfx_base; 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 i, xxor, yxor;
int bank_table[4]; int bank_table[4];
int dx, dy, palette; 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; 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; source += 0x1000;
dx = scrollx[2]; dx = scrollx[2];
dy = scrolly[2]; dy = scrolly[2];
palette = 1; palette = 1;
} }
else else {
{
source += 0x0000; source += 0x0000;
dx = scrollx[1]; dx = scrollx[1];
dy = scrolly[1]; dy = scrolly[1];
palette = 0; palette = 0;
} }
if( twin16_custom_video == 1 ) if( twin16_custom_video ) {
{ /* fround board */
gfx_base = twin16_gfx_rom; gfx_base = twin16_gfx_rom;
bank_table[3] = (gfx_bank>>(4*3))&0xf; bank_table[3] = (gfx_bank>>(4*3))&0xf;
bank_table[2] = (gfx_bank>>(4*2))&0xf; bank_table[2] = (gfx_bank>>(4*2))&0xf;
bank_table[1] = (gfx_bank>>(4*1))&0xf; bank_table[1] = (gfx_bank>>(4*1))&0xf;
bank_table[0] = (gfx_bank>>(4*0))&0xf; bank_table[0] = (gfx_bank>>(4*0))&0xf;
} }
else else {
{
gfx_base = twin16_tile_gfx_ram; gfx_base = twin16_tile_gfx_ram;
bank_table[0] = 0; bank_table[0] = 0;
bank_table[1] = 1; 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) if (x1 <= x2 && y1 <= y2)
{ {
int code = source[i]; int code = source[i];
/* /* fedcba9876543210
xxx------------- color xxx------------- color
---xx----------- tile bank ---xx----------- tile bank
-----xxxxxxxxxxx tile number -----xxxxxxxxxxx tile number
*/ */
const UINT16 *gfx_data = gfx_base + (code&0x7ff)*16 + bank_table[(code>>11)&0x3]*0x8000; const UINT16 *gfx_data = gfx_base + (code&0x7ff)*16 + bank_table[(code>>11)&0x3]*0x8000;
int color = (code>>13); int color = (code>>13);
int pal_base = 16*(0x20+color+8*palette); 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; int effx = (x - xpos) ^ xxor;
UINT16 data = gfxptr[effx / 4]; UINT16 data = gfxptr[effx / 4];
dest[x] = pal_base + ((data >> 4*(~effx & 3)) & 0x0f); 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) if (pen)
{ {
dest[x] = pal_base + 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]; int attr = source[tile_index];
/* fedcba9876543210
-x-------------- yflip
--x------------- xflip
---xxxx--------- color
-------xxxxxxxxx tile number
*/
int code = attr & 0x1ff; int code = attr & 0x1ff;
int color = (attr >> 9) & 0x0f; int color = (attr >> 9) & 0x0f;
int flags=0;
SET_TILE_INFO(0, code, color, 0); if (attr&0x2000) flags|=TILE_FLIPX;
if (attr&0x4000) flags|=TILE_FLIPY;
SET_TILE_INFO(0, code, color, flags);
} }
VIDEO_START( twin16 ) VIDEO_START( twin16 )
{ {
fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows_flip_y, 8, 8, 64, 32); text_tilemap = tilemap_create(machine, get_text_tile_info, tilemap_scan_rows, 8, 8, 64, 32);
tilemap_set_transparent_pen(text_tilemap, 0);
tilemap_set_transparent_pen(fg_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);
VIDEO_START( fround ) /* register for savestates */
{ state_save_register_global_array(machine, twin16_sprite_buffer);
fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows, 8, 8, 64, 32); state_save_register_global_array(machine, scrollx);
state_save_register_global_array(machine, scrolly);
tilemap_set_transparent_pen(fg_tilemap, 0); 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 ) 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); bitmap_fill(screen->machine->priority_bitmap,cliprect,0);
draw_layer( screen->machine, bitmap, 1 ); draw_layer( screen->machine, bitmap, 1 );
draw_layer( screen->machine, bitmap, 0 );
draw_sprites( screen->machine, bitmap );
if (twin16_custom_video) if (text_flip) tilemap_set_flip(text_tilemap, text_flip);
{ tilemap_draw(bitmap, cliprect, text_tilemap, 0, 0);
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);
return 0; return 0;
} }
VIDEO_EOF( twin16 ) VIDEO_EOF( twin16 )
{ {
const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); twin16_set_sprite_timer(machine);
if( twin16_spriteram_process_enable() && need_process_spriteram ) if (twin16_spriteram_process_enable()) {
twin16_spriteram_process(); if (need_process_spriteram) twin16_spriteram_process(machine);
need_process_spriteram = 1;
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
buffer_spriteram16_w(space,0,0,0xffff); 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);
}
} }