diff --git a/.gitattributes b/.gitattributes index 8b3495af316..0b28f629516 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1727,6 +1727,7 @@ src/mame/drivers/pandoras.c svneol=native#text/plain src/mame/drivers/pangofun.c svneol=native#text/plain src/mame/drivers/panicr.c svneol=native#text/plain src/mame/drivers/paradise.c svneol=native#text/plain +src/mame/drivers/paranoia.c svneol=native#text/plain src/mame/drivers/parodius.c svneol=native#text/plain src/mame/drivers/pasha2.c svneol=native#text/plain src/mame/drivers/pass.c svneol=native#text/plain @@ -2025,6 +2026,7 @@ src/mame/drivers/twin16.c svneol=native#text/plain src/mame/drivers/twincobr.c svneol=native#text/plain src/mame/drivers/twins.c svneol=native#text/plain src/mame/drivers/tx1.c svneol=native#text/plain +src/mame/drivers/uapce.c svneol=native#text/plain src/mame/drivers/ultraman.c svneol=native#text/plain src/mame/drivers/ultratnk.c svneol=native#text/plain src/mame/drivers/ultrsprt.c svneol=native#text/plain @@ -2477,6 +2479,8 @@ src/mame/machine/nmk112.h svneol=native#text/plain src/mame/machine/nycaptor.c svneol=native#text/plain src/mame/machine/opwolf.c svneol=native#text/plain src/mame/machine/pacplus.c svneol=native#text/plain +src/mame/machine/pcecommn.c svneol=native#text/plain +src/mame/machine/pcecommn.h svneol=native#text/plain src/mame/machine/pckeybrd.c svneol=native#text/plain src/mame/machine/pckeybrd.h svneol=native#text/plain src/mame/machine/pcshare.c svneol=native#text/plain @@ -3206,6 +3210,8 @@ src/mame/video/usgames.c svneol=native#text/plain src/mame/video/vaportra.c svneol=native#text/plain src/mame/video/vastar.c svneol=native#text/plain src/mame/video/vball.c svneol=native#text/plain +src/mame/video/vdc.c svneol=native#text/plain +src/mame/video/vdc.h svneol=native#text/plain src/mame/video/vendetta.c svneol=native#text/plain src/mame/video/vertigo.c svneol=native#text/plain src/mame/video/vicdual.c svneol=native#text/plain diff --git a/src/mame/drivers/paranoia.c b/src/mame/drivers/paranoia.c new file mode 100644 index 00000000000..edd71a860b4 --- /dev/null +++ b/src/mame/drivers/paranoia.c @@ -0,0 +1,188 @@ +/**************************************************************************** + + Paranoia + Driver by Mariusz Wojcieszek + + Notes: + - jamma interface is not emulated, hence the game is marked as 'not working' + - rom mapping, memory maps and clocks for jamma interface cpus are probably not correct + +Paranoia by Naxat Soft 1990 + +CPU Z84C00A85 (Z80A CPU) + +Xtal : 18.000 Mhz + +Ram : GM76C28A (Goldstar) + +Ram : 2x W2416K-70 (Winbond) + +Else : + +Winbond WF19054 + +Sound : Nec D8085AHC + Nec D8155HC + +This board has also : + +HuC6260A (Hudson) +HuC6270 (Hudson) +HuC6280A (Hudson) +2x HSRM2564LM12 +1x HSRM2564LM10 + +****************************************************************************/ + +#include "driver.h" +#include "machine/pcecommn.h" +#include "video/vdc.h" +#include "cpu/h6280/h6280.h" +#include "sound/c6280.h" + +static INPUT_PORTS_START( paranoia ) + PORT_START_TAG( "IN" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* button I */ + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* button II */ + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* select */ + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) /* run */ + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) +INPUT_PORTS_END + +static ADDRESS_MAP_START( pce_mem , ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE( 0x000000, 0x03FFFF) AM_ROM + AM_RANGE( 0x1F0000, 0x1F1FFF) AM_RAM AM_MIRROR(0x6000) AM_BASE( &pce_user_ram ) + AM_RANGE( 0x1FE000, 0x1FE3FF) AM_READWRITE( vdc_0_r, vdc_0_w ) + AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w ) + AM_RANGE( 0x1FE800, 0x1FEBFF) AM_READWRITE( C6280_r, C6280_0_w ) + AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( H6280_timer_r, H6280_timer_w ) + AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w ) + AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( H6280_irq_status_r, H6280_irq_status_w ) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( pce_io , ADDRESS_SPACE_IO, 8) + AM_RANGE( 0x00, 0x03) AM_READWRITE( vdc_0_r, vdc_0_w ) +ADDRESS_MAP_END + +static WRITE8_HANDLER( paranoia_8085_d000_w ) +{ + //logerror( "D000 (8085) write %02x\n", data ); +} + +static WRITE8_HANDLER( paranoia_8085_8155_w ) +{ + switch( offset ) + { + case 0: logerror( "8155 Command register write %x, timer command = %x, interrupt enable = %x, ports = %x\n", data, (data >> 6) & 3, (data >> 4) & 3, data & 0xf ); break; + case 1: logerror( "8155 I/O Port A write %x\n", data ); break; + case 2: logerror( "8155 I/O Port B write %x\n", data ); break; + case 3: logerror( "8155 I/O Port C (or control) write %x\n", data ); break; + case 4: logerror( "8155 Timer low 8 bits write %x\n", data ); break; + case 5: logerror( "8155 Timer high 6 bits write %x, timer mode %x\n", data & 0x3f, (data >> 6) & 3); break; + } +} + +ADDRESS_MAP_START(paranoia_8085_map, ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE( 0x0000, 0x7fff) AM_ROM + AM_RANGE( 0x8000, 0x80ff) AM_RAM + AM_RANGE( 0x8100, 0x8105) AM_WRITE( paranoia_8085_8155_w ) + AM_RANGE( 0xd000, 0xd000) AM_WRITE( paranoia_8085_d000_w ) + AM_RANGE( 0xe000, 0xe1ff) AM_RAM +ADDRESS_MAP_END + +ADDRESS_MAP_START(paranoia_8085_io_map, ADDRESS_SPACE_IO, 8) +ADDRESS_MAP_END + +ADDRESS_MAP_START(paranoia_z80_map, ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE( 0x0000, 0x3fff) AM_ROM + AM_RANGE( 0x6000, 0x67ff) AM_RAM + AM_RANGE( 0x7000, 0x73ff) AM_RAM +ADDRESS_MAP_END + +static READ8_HANDLER(paranoia_z80_io_01_r) +{ + return 0; +} + +static READ8_HANDLER(paranoia_z80_io_02_r) +{ + return 0; +} + +static WRITE8_HANDLER(paranoia_z80_io_17_w) +{ +} + +static WRITE8_HANDLER(paranoia_z80_io_37_w) +{ +} + +ADDRESS_MAP_START(paranoia_z80_io_map, ADDRESS_SPACE_IO, 8) + ADDRESS_MAP_FLAGS( AMEF_ABITS(8) ) + AM_RANGE( 0x01, 0x01 ) AM_READ( paranoia_z80_io_01_r ) + AM_RANGE( 0x02, 0x02 ) AM_READ( paranoia_z80_io_02_r ) + AM_RANGE( 0x17, 0x17 ) AM_WRITE( paranoia_z80_io_17_w ) + AM_RANGE( 0x37, 0x37 ) AM_WRITE( paranoia_z80_io_37_w ) +ADDRESS_MAP_END + +static MACHINE_DRIVER_START( paranoia ) + /* basic machine hardware */ + MDRV_CPU_ADD(H6280, PCE_MAIN_CLOCK/3) + MDRV_CPU_PROGRAM_MAP(pce_mem, 0) + MDRV_CPU_IO_MAP(pce_io, 0) + MDRV_CPU_VBLANK_INT(pce_interrupt, VDC_LPF) + + MDRV_SCREEN_REFRESH_RATE(60) + MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) + MDRV_INTERLEAVE(1) + + MDRV_CPU_ADD(8085A, 18000000/6) + MDRV_CPU_PROGRAM_MAP(paranoia_8085_map,0) + MDRV_CPU_IO_MAP(paranoia_8085_io_map,0) + + MDRV_CPU_ADD(Z80, 18000000/6) + MDRV_CPU_PROGRAM_MAP(paranoia_z80_map,0) + MDRV_CPU_IO_MAP(paranoia_z80_io_map,0) + + /* video hardware */ + MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) + MDRV_SCREEN_ADD("main",0) + MDRV_SCREEN_RAW_PARAMS(PCE_MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242) + /* MDRV_GFXDECODE( pce_gfxdecodeinfo ) */ + MDRV_PALETTE_LENGTH(1024) + MDRV_PALETTE_INIT( vce ) + MDRV_COLORTABLE_LENGTH(1024) + + MDRV_VIDEO_START( pce ) + MDRV_VIDEO_UPDATE( pce ) + + MDRV_SPEAKER_STANDARD_STEREO("left","right") + MDRV_SOUND_ADD(C6280, PCE_MAIN_CLOCK/6) + MDRV_SOUND_ROUTE(0, "left", 1.00) + MDRV_SOUND_ROUTE(1, "right", 1.00) + +MACHINE_DRIVER_END + +ROM_START(paranoia) + ROM_REGION( 0x40000, REGION_CPU1, 0 ) + ROM_LOAD( "5.201", 0x00000, 0x40000, CRC(9893e0e6) SHA1(b3097e7f163e4a067cf32f290e59657a8b5e271b) ) + + ROM_REGION( 0x8000, REGION_CPU2, 0 ) + ROM_LOAD( "6.29", 0x0000, 0x8000, CRC(5517532e) SHA1(df8f1621abf1f0c65d86d406cd79d97ec233c378) ) + + ROM_REGION( 0x20000, REGION_CPU3, 0 ) + ROM_LOAD( "1.319", 0x00000, 0x8000, CRC(ef9f85d8) SHA1(951239042b56cd256daf1965ead2949e2bddcd8b) ) + ROM_LOAD( "2.318", 0x08000, 0x8000, CRC(a35fccca) SHA1(d50e9044a97fe77f31e3198bb6759ba451359069) ) + ROM_LOAD( "3.317", 0x10000, 0x8000, CRC(e3e48ec1) SHA1(299820d0e4fb2fd947c7a52f1c49e2e4d0dd050a) ) + ROM_LOAD( "4.352", 0x18000, 0x8000, CRC(11297fed) SHA1(17a294e65ba1c4806307602dee4c7c627ad1fcfd) ) +ROM_END + +static DRIVER_INIT(paranoia) +{ + driver_init_pce(machine); +}; + +GAME( 1990, paranoia, 0, paranoia, paranoia, paranoia, ROT0, "Naxat Soft", "Paranoia", GAME_IMPERFECT_SOUND | GAME_NOT_WORKING ) diff --git a/src/mame/drivers/stv.c b/src/mame/drivers/stv.c index 59fc19cc306..a1d0e9fb9f4 100644 --- a/src/mame/drivers/stv.c +++ b/src/mame/drivers/stv.c @@ -242,6 +242,7 @@ DRIVER_INIT(elandore); DRIVER_INIT(rsgun); DRIVER_INIT(ffreveng); DRIVER_INIT(decathlt); +DRIVER_INIT(nameclv3); /**************************************************************************************/ /*to be added into a stv Header file,remember to remove all the static...*/ @@ -3853,7 +3854,7 @@ GAME( 1995, suikoenb, stvbios, stv, stv, suikoenb, ROT0, "Data East", GAME( 1996, vfkids, stvbios, stv, stv, ic13, ROT0, "Sega", "Virtua Fighter Kids (JUET 960319 V0.000)", GAME_IMPERFECT_SOUND ) GAME( 1997, winterht, stvbios, stv, stv, winterht, ROT0, "Sega", "Winter Heat (JUET 971012 V1.000)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) GAME( 1997, znpwfv, stvbios, stv, stv, znpwfv, ROT0, "Sega", "Zen Nippon Pro-Wrestling Featuring Virtua (J 971123 V1.000)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) -GAME( 1997, nclubv3, stvbios, stv, stv, stv, ROT0, "Sega", "Name Club Ver.3", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) // seems to work, although it could do with speedups, and the printer isn't emulated.. +GAME( 1997, nclubv3, stvbios, stv, stv, nameclv3, ROT0, "Sega", "Name Club Ver.3 (J 970723 V1.000)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) // seems to work, although it could do with speedups, and the printer isn't emulated.. /* Almost */ GAME( 1997, vmahjong, stvbios, stv, stvmp,stv, ROT0, "Micronet", "Virtual Mahjong (J 961214 V1.000)", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS ) diff --git a/src/mame/drivers/stvinit.c b/src/mame/drivers/stvinit.c index e6832c4a157..44b865f5c87 100644 --- a/src/mame/drivers/stvinit.c +++ b/src/mame/drivers/stvinit.c @@ -1404,3 +1404,23 @@ DRIVER_INIT(decathlt) install_decathlt_protection(); driver_init_ic13(machine); } + +static READ32_HANDLER( nameclv3_speedup_r ) +{ + if (activecpu_get_pc()==0x601eb4e) cpu_spinuntil_time(ATTOTIME_IN_USEC(30)); + return stv_workram_h[0x0452c0/4]; +} + +static void nameclv3_slave_speedup( UINT32 data ) +{ + if ( activecpu_get_pc() == 0x0602B810 ) + if ( (data & 0x00800000) == 0 ) + cpunum_spinuntil_trigger(1, 1000); +} + +DRIVER_INIT(nameclv3) +{ + memory_install_read32_handler(0, ADDRESS_SPACE_PROGRAM, 0x60452c0, 0x60452c3, 0, 0, nameclv3_speedup_r ); + cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)nameclv3_slave_speedup ); + driver_init_stv(machine); +} diff --git a/src/mame/drivers/uapce.c b/src/mame/drivers/uapce.c new file mode 100644 index 00000000000..f745c276721 --- /dev/null +++ b/src/mame/drivers/uapce.c @@ -0,0 +1,230 @@ +/* + + United Amusement PC-Engine based hardware + Driver by Mariusz Wojcieszek + Thanks for Charles MacDonald for hardware docs + + Overview + + The system consists of a stock PC-Engine console, JAMMA interface board, + and several cables to connect certain pins from the PCE backplane connector + and pad connector to the interface board. + + History + + In 1989 United Amusement (a large operator of arcades in the US at that + time) developed a JAMMA interface for the PC-Engine with NEC's blessing. NEC + pulled funding for the project before mass production began, and it never + took off. + + Driver notes: + - game time is controlled using software loop - with current clock it takes lots + of time until credit expires. Should Z80 clock be raised? + - tone played by jamma if board is not emulated +*/ + +#include "driver.h" +#include "machine/pcecommn.h" +#include "video/vdc.h" +#include "cpu/h6280/h6280.h" +#include "sound/c6280.h" + +static UINT8 jamma_if_control_latch = 0; + +static WRITE8_HANDLER( jamma_if_control_latch_w ) +{ + UINT8 diff = data ^ jamma_if_control_latch; + jamma_if_control_latch = data; + + sound_global_enable( (data >> 7) & 1 ); + + if ( diff & 0x40 ) + { + cpunum_set_input_line(0, INPUT_LINE_RESET, (data & 0x40) ? CLEAR_LINE : ASSERT_LINE); + } + + // bit 3 - enable 752 Hz (D-3) square wave output + + logerror( "Writing control latch with %02X\n", data ); +}; + +static READ8_HANDLER( jamma_if_control_latch_r ) +{ + return jamma_if_control_latch & 0x08; +}; + +static READ8_HANDLER( jamma_if_read_dsw ) +{ + UINT8 dsw_val; + + dsw_val = readinputportbytag( "DSW" ); + + if ( BIT( offset, 7 ) == 0 ) + { + dsw_val >>= 7; + } + else if ( BIT( offset, 6 ) == 0 ) + { + dsw_val >>= 6; + } + else if ( BIT( offset, 5 ) == 0 ) + { + dsw_val >>= 5; + } + else if ( BIT( offset, 4 ) == 0 ) + { + dsw_val >>= 4; + } + else if ( BIT( offset, 3 ) == 0 ) + { + dsw_val >>= 3; + } + else if ( BIT( offset, 2 ) == 0 ) + { + dsw_val >>= 2; + } + else if ( BIT( offset, 1 ) == 0 ) + { + dsw_val >>= 1; + } + else if ( BIT( offset, 0 ) == 0 ) + { + dsw_val >>= 0; + } + + return dsw_val & 1; +}; + +static UINT8 jamma_if_read_joystick( void ) +{ + if ( jamma_if_control_latch & 0x10 ) + { + return readinputportbytag( "IN" ); + } + else + { + return readinputportbytag( "IN" ) | 0x08; + } +}; + +static MACHINE_RESET( uapce ) +{ + pce_set_joystick_readinputport_callback( jamma_if_read_joystick ); + jamma_if_control_latch = 0; +}; + +ADDRESS_MAP_START( z80_map, ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE( 0x0000, 0x07FF) AM_ROM + AM_RANGE( 0x0800, 0x0FFF) AM_RAM + AM_RANGE( 0x1000, 0x17FF) AM_WRITE( jamma_if_control_latch_w ) + AM_RANGE( 0x1800, 0x1FFF) AM_READ( jamma_if_read_dsw ) + AM_RANGE( 0x2000, 0x27FF) AM_READ( port_tag_to_handler8( "COIN" ) ) + AM_RANGE( 0x2800, 0x2FFF) AM_READ( jamma_if_control_latch_r ) +ADDRESS_MAP_END + + +static INPUT_PORTS_START( uapce ) + PORT_START_TAG( "IN" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* button I */ + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* button II */ + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* select */ + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) /* run */ + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + + PORT_START_TAG( "DSW" ) + PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coinage ) ) + PORT_DIPSETTING( 0x04, DEF_STR( 4C_1C ) ) + PORT_DIPSETTING( 0x05, DEF_STR( 3C_1C ) ) + PORT_DIPSETTING( 0x06, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x07, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x03, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0x02, DEF_STR( 1C_3C ) ) + PORT_DIPSETTING( 0x01, DEF_STR( 1C_4C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) ) + PORT_DIPNAME( 0x38, 0x00, "Game timer (?)" ) + PORT_DIPSETTING( 0x00, "Game timer setting 1" ) + PORT_DIPSETTING( 0x08, "Game timer setting 2" ) + PORT_DIPSETTING( 0x10, "Game timer setting 3" ) + PORT_DIPSETTING( 0x18, "Game timer setting 4" ) + PORT_DIPSETTING( 0x20, "Game timer setting 5" ) + PORT_DIPSETTING( 0x28, "Game timer setting 6" ) + PORT_DIPSETTING( 0x30, "Game timer setting 7" ) + PORT_DIPSETTING( 0x38, "Game timer setting 8" ) + PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START_TAG( "COIN" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1) +INPUT_PORTS_END + +static ADDRESS_MAP_START( pce_mem , ADDRESS_SPACE_PROGRAM, 8) + AM_RANGE( 0x000000, 0x09FFFF) AM_ROM + AM_RANGE( 0x1F0000, 0x1F1FFF) AM_RAM AM_MIRROR(0x6000) AM_BASE( &pce_user_ram ) + AM_RANGE( 0x1FE000, 0x1FE3FF) AM_READWRITE( vdc_0_r, vdc_0_w ) + AM_RANGE( 0x1FE400, 0x1FE7FF) AM_READWRITE( vce_r, vce_w ) + AM_RANGE( 0x1FE800, 0x1FEBFF) AM_READWRITE( C6280_r, C6280_0_w ) + AM_RANGE( 0x1FEC00, 0x1FEFFF) AM_READWRITE( H6280_timer_r, H6280_timer_w ) + AM_RANGE( 0x1FF000, 0x1FF3FF) AM_READWRITE( pce_joystick_r, pce_joystick_w ) + AM_RANGE( 0x1FF400, 0x1FF7FF) AM_READWRITE( H6280_irq_status_r, H6280_irq_status_w ) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( pce_io , ADDRESS_SPACE_IO, 8) + AM_RANGE( 0x00, 0x03) AM_READWRITE( vdc_0_r, vdc_0_w ) +ADDRESS_MAP_END + +static MACHINE_DRIVER_START( uapce ) + /* basic machine hardware */ + MDRV_CPU_ADD(H6280, PCE_MAIN_CLOCK/3) + MDRV_CPU_PROGRAM_MAP(pce_mem, 0) + MDRV_CPU_IO_MAP(pce_io, 0) + MDRV_CPU_VBLANK_INT(pce_interrupt, VDC_LPF) + + MDRV_CPU_ADD(Z80, 1400000) + MDRV_CPU_PROGRAM_MAP(z80_map, 0) + + MDRV_SCREEN_REFRESH_RATE(60) + MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) + MDRV_INTERLEAVE(1) + + MDRV_MACHINE_RESET( uapce ) + + /* video hardware */ + MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) + MDRV_SCREEN_ADD("main",0) + MDRV_SCREEN_RAW_PARAMS(PCE_MAIN_CLOCK/2, VDC_WPF, 70, 70 + 512 + 32, VDC_LPF, 14, 14+242) + /* MDRV_GFXDECODE( pce_gfxdecodeinfo ) */ + MDRV_PALETTE_LENGTH(1024) + MDRV_PALETTE_INIT( vce ) + MDRV_COLORTABLE_LENGTH(1024) + + MDRV_VIDEO_START( pce ) + MDRV_VIDEO_UPDATE( pce ) + + MDRV_SPEAKER_STANDARD_STEREO("left","right") + MDRV_SOUND_ADD(C6280, PCE_MAIN_CLOCK/6) + MDRV_SOUND_ROUTE(0, "left", 1.00) + MDRV_SOUND_ROUTE(1, "right", 1.00) + +MACHINE_DRIVER_END + +ROM_START(blazlaz) + ROM_REGION( 0x0a0000, REGION_CPU1, 0 ) + ROM_LOAD( "ic1.bin", 0x000000, 0x020000, CRC(c86d44fe) SHA1(070512918e4d305db48bbda374eaff2d121909c5) ) + ROM_LOAD( "ic2.bin", 0x020000, 0x020000, CRC(fb813309) SHA1(60d1ea45717a04d776b6837377467e81431f9bc6) ) + ROM_LOAD( "ic3.bin", 0x080000, 0x020000, CRC(d30a2ecf) SHA1(8328b303e2ffeb694b472719e59044d41471725f) ) + + ROM_REGION( 0x800, REGION_CPU2, 0 ) + ROM_LOAD( "u1.bin", 0x0000, 0x800, CRC(f5e538a9) SHA1(19ac9525c9ad6bea1789cc9e63cdb7fe949867d9) ) +ROM_END + +static DRIVER_INIT(uapce) +{ + driver_init_pce(machine); +}; + +GAME( 1989, blazlaz, 0, uapce, uapce, uapce, ROT0, "Hudson Soft", "Blazing Lazers", GAME_IMPERFECT_SOUND ) diff --git a/src/mame/machine/pcecommn.c b/src/mame/machine/pcecommn.c new file mode 100644 index 00000000000..79565d90d7b --- /dev/null +++ b/src/mame/machine/pcecommn.c @@ -0,0 +1,73 @@ + +#include "driver.h" +#include "machine/pcecommn.h" +#include "video/vdc.h" +#include "cpu/h6280/h6280.h" + +/* system RAM */ +unsigned char *pce_user_ram; /* scratch RAM at F8 */ + +struct pce_struct pce; + +/* joystick related data*/ + +#define JOY_CLOCK 0x01 +#define JOY_RESET 0x02 + +static int joystick_port_select; /* internal index of joystick ports */ +static int joystick_data_select; /* which nibble of joystick data we want */ + +static UINT8 (*pce_joystick_readinputport_callback)(void) = NULL; + +DRIVER_INIT( pce ) { + pce.io_port_options = PCE_JOY_SIG | CONST_SIG; +} + +MACHINE_RESET( pce ) { +} + +/* todo: how many input ports does the PCE have? */ +WRITE8_HANDLER ( pce_joystick_w ) +{ + h6280io_set_buffer(data); + /* bump counter on a low-to-high transition of bit 1 */ + if((!joystick_data_select) && (data & JOY_CLOCK)) + { + joystick_port_select = (joystick_port_select + 1) & 0x07; + } + + /* do we want buttons or direction? */ + joystick_data_select = data & JOY_CLOCK; + + /* clear counter if bit 2 is set */ + if(data & JOY_RESET) + { + joystick_port_select = 0; + } +} + +READ8_HANDLER ( pce_joystick_r ) +{ + UINT8 ret; + int data; + + if ( pce_joystick_readinputport_callback != NULL ) + { + data = pce_joystick_readinputport_callback(); + } + else + { + data = readinputport(0); + } + if(joystick_data_select) data >>= 4; + ret = (data & 0x0F) | pce.io_port_options; +#ifdef UNIFIED_PCE + ret &= ~0x40; +#endif + return (ret); +} + +void pce_set_joystick_readinputport_callback( UINT8 (*joy_read)(void)) +{ + pce_joystick_readinputport_callback = joy_read; +} diff --git a/src/mame/machine/pcecommn.h b/src/mame/machine/pcecommn.h new file mode 100644 index 00000000000..d0bda6d0bd6 --- /dev/null +++ b/src/mame/machine/pcecommn.h @@ -0,0 +1,34 @@ +/*************************************************************************** + + pcecommn.h + + Headers for the common stuff for NEC PC Engine/TurboGrafx16. + +***************************************************************************/ + +#ifndef PCECOMMON_H +#define PCECOMMON_H + +#define PCE_MAIN_CLOCK 21477270 + +extern unsigned char *pce_user_ram; /* scratch RAM at F8 */ +WRITE8_HANDLER ( pce_joystick_w ); + READ8_HANDLER ( pce_joystick_r ); + +#define TG_16_JOY_SIG 0x00 +#define PCE_JOY_SIG 0x40 +#define NO_CD_SIG 0x80 +#define CD_SIG 0x00 +/* these might be used to indicate something, but they always seem to return 1 */ +#define CONST_SIG 0x30 + +struct pce_struct +{ + UINT8 io_port_options; /*driver-specific options for the PCE*/ +}; +extern struct pce_struct pce; +DRIVER_INIT( pce ); +MACHINE_RESET( pce ); + +void pce_set_joystick_readinputport_callback( UINT8 (*joy_read)(void)); +#endif diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 47220f0dad7..f9f96424d0e 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -1616,6 +1616,7 @@ $(MAMEOBJ)/misc.a: \ $(DRIVERS)/vroulet.o \ $(DRIVERS)/wldarrow.o \ $(DRIVERS)/xyonix.o $(VIDEO)/xyonix.o \ + $(DRIVERS)/uapce.o $(DRIVERS)/paranoia.o $(VIDEO)/vdc.o $(MACHINE)/pcecommn.o \ #------------------------------------------------- diff --git a/src/mame/mamedriv.c b/src/mame/mamedriv.c index d3226b87bf6..f30535eeda2 100644 --- a/src/mame/mamedriv.c +++ b/src/mame/mamedriv.c @@ -7904,5 +7904,7 @@ Other Sun games DRIVER( gtipoker ) /* (c) 1983 GTI Inc */ DRIVER( gamecstl ) /* MAME based bootleg */ DRIVER( drw80pkr ) + DRIVER( blazlaz ) + DRIVER( paranoia ) #endif /* DRIVER_RECURSIVE */ diff --git a/src/mame/video/vdc.c b/src/mame/video/vdc.c new file mode 100644 index 00000000000..d3962fe92a7 --- /dev/null +++ b/src/mame/video/vdc.c @@ -0,0 +1,1090 @@ +#include "driver.h" +#include "video/vdc.h" + +/* VDC segments */ +#define STATE_VSW 0 +#define STATE_VDS 1 +#define STATE_VDW 2 +#define STATE_VCR 3 + +/* todo: replace this with the PAIR structure from 'osd_cpu.h' */ +typedef union +{ +#ifdef LSB_FIRST + struct { unsigned char l,h; } b; +#else + struct { unsigned char h,l; } b; +#endif + unsigned short int w; +}pair; + +/* the VDC context */ + +typedef struct +{ + int dvssr_write; /* Set when the DVSSR register has been written to */ + int physical_width; /* Width of the display */ + int physical_height; /* Height of the display */ + UINT16 sprite_ram[64*4]; /* Sprite RAM */ + int curline; /* the current scanline we're on */ + int current_segment; /* current segment of display */ + int current_segment_line; /* current line inside a segment of display */ + int vblank_triggered; /* to indicate whether vblank has been triggered */ + int raster_count; /* counter to compare RCR against */ + int satb_countdown; /* scanlines to wait to trigger the SATB irq */ + UINT8 *vram; + UINT8 inc; + UINT8 vdc_register; + UINT8 vdc_latch; + pair vdc_data[32]; + int status; + int y_scroll; +}VDC; + +typedef struct { + UINT8 vce_control; /* VCE control register */ + pair vce_address; /* Current address in the palette */ + pair vce_data[512]; /* Palette data */ + int current_bitmap_line; /* The current line in the display we are on */ + mame_bitmap *bmp; +}VCE; + +typedef struct { + UINT8 prio; + UINT8 vdc0_enabled; + UINT8 vdc1_enabled; +} VPC_PRIO; + +typedef struct { + VPC_PRIO vpc_prio[4]; + UINT8 prio_map[512]; /* Pre-calculated priority map */ + pair priority; /* Priority settings registers */ + pair window1; /* Window 1 setting */ + pair window2; /* Window 2 setting */ + UINT8 vdc_select; /* Which VDC do the ST0, ST1, and ST2 instructions write to */ +}VPC; + +static VDC vdc[2]; +static VCE vce; +static VPC vpc; + +/* Function prototypes */ + +static void vdc_advance_line(int which); +static void draw_black_line(int line); +static void draw_overscan_line(int line); +static void draw_sgx_overscan_line(int line); +static void pce_refresh_line(int which, int line, int external_input, UINT8 *drawn, UINT16 *line_buffer); +static void pce_refresh_sprites(int which, int line, UINT8 *drawn, UINT16 *line_buffer); +static void vdc_do_dma(int which); +static void vpc_init( void ); + +INTERRUPT_GEN( pce_interrupt ) +{ + /* Draw the last scanline */ + if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 ) { + /* We are in the active display area */ + /* First fill the line with the overscan color */ + draw_overscan_line( vce.current_bitmap_line ); + + /* Check if we need to draw more just the overscan color */ + if ( vdc[0].current_segment == STATE_VDW ) { + /* 0 - no sprite and background pixels drawn + 1 - background pixel drawn + otherwise is 2 + sprite# */ + UINT8 drawn[VDC_WPF]; + /* our line buffer */ + UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, vce.current_bitmap_line, 86 ); + + /* clear our priority/sprite collision detection buffer. */ + memset(drawn, 0, VDC_WPF); + + vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w : ( vdc[0].y_scroll + 1 ); + + /* Draw VDC #0 background layer */ + pce_refresh_line( 0, vdc[0].current_segment_line, 0, drawn, line_buffer ); + + /* Draw VDC #0 sprite layer */ + if(vdc[0].vdc_data[CR].w & CR_SB) { + pce_refresh_sprites(0, vdc[0].current_segment_line, drawn, line_buffer); + } + } + } else { + /* We are in one of the blanking areas */ + draw_black_line( vce.current_bitmap_line ); + } + + /* bump current scanline */ + vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF; + vdc_advance_line( 0 ); +} + +INTERRUPT_GEN( sgx_interrupt ) +{ + /* Draw the last scanline */ + if ( vce.current_bitmap_line >= 14 && vce.current_bitmap_line < 14 + 242 ) { + /* We are in the active display area */ + /* First fill the line with the overscan color */ + draw_sgx_overscan_line( vce.current_bitmap_line ); + + /* Check if we need to draw more just the overscan color */ + if ( vdc[0].current_segment == STATE_VDW ) { + /* 0 - no sprite and background pixels drawn + 1 - background pixel drawn + otherwise is 2 + sprite# */ + UINT8 drawn[2][512]; + UINT16 *line_buffer; + UINT16 temp_buffer[2][512]; + int i; + + /* clear our priority/sprite collision detection buffer. */ + memset( drawn, 0, sizeof(drawn) ); + + vdc[0].y_scroll = ( vdc[0].current_segment_line == 0 ) ? vdc[0].vdc_data[BYR].w : ( vdc[0].y_scroll + 1 ); + vdc[1].y_scroll = ( vdc[1].current_segment_line == 0 ) ? vdc[1].vdc_data[BYR].w : ( vdc[1].y_scroll + 1 ); + + /* Draw VDC #0 background layer */ + pce_refresh_line( 0, vdc[0].current_segment_line, 0, drawn[0], temp_buffer[0] ); + + /* Draw VDC #0 sprite layer */ + if(vdc[0].vdc_data[CR].w & CR_SB) { + pce_refresh_sprites( 0, vdc[0].current_segment_line, drawn[0], temp_buffer[0] ); + } + + /* Draw VDC #1 background layer */ + pce_refresh_line( 1, vdc[1].current_segment_line, 1, drawn[1], temp_buffer[1] ); + + /* Draw VDC #1 sprite layer */ + if ( vdc[1].vdc_data[CR].w & CR_SB ) { + pce_refresh_sprites( 1, vdc[1].current_segment_line, drawn[1], temp_buffer[1] ); + } + + line_buffer = BITMAP_ADDR16( vce.bmp, vce.current_bitmap_line, 86 ); + /* Combine the output of both VDCs */ + for( i = 0; i < 512; i++ ) { + int cur_prio = vpc.prio_map[i]; + + if ( vpc.vpc_prio[cur_prio].vdc0_enabled ) { + if ( vpc.vpc_prio[cur_prio].vdc1_enabled ) { + switch( vpc.vpc_prio[cur_prio].prio ) { + case 0: /* BG1 SP1 BG0 SP0 */ + if ( drawn[0][i] ) { + line_buffer[i] = temp_buffer[0][i]; + } else if ( drawn[1][i] ) { + line_buffer[i] = temp_buffer[1][i]; + } + break; + case 1: /* BG1 BG0 SP1 SP0 */ + if ( drawn[0][i] ) { + if ( drawn[0][i] > 1 ) { + line_buffer[i] = temp_buffer[0][i]; + } else { + if ( drawn[1][i] > 1 ) { + line_buffer[i] = temp_buffer[1][i]; + } else { + line_buffer[i] = temp_buffer[0][i]; + } + } + } else if ( drawn[1][i] ) { + line_buffer[i] = temp_buffer[1][i]; + } + break; + case 2: /* BG1 + SP1 => SP1 + BG0 + SP1 => BG0 + BG0 + BG1 => BG0 + BG0 + SP0 => SP0 + BG1 + SP0 => BG1 + SP0 + SP1 => SP0 */ + if ( drawn[0][i] ) { + if ( drawn[0][i] > 1 ) { + if ( drawn[1][i] == 1 ) { + line_buffer[i] = temp_buffer[1][i]; + } else { + line_buffer[i] = temp_buffer[0][i]; + } + } else { + line_buffer[i] = temp_buffer[0][i]; + } + } else if ( drawn[1][i] ) { + line_buffer[i] = temp_buffer[1][i]; + } + break; + } + } else { + if ( drawn[0][i] ) { + line_buffer[i] = temp_buffer[0][i]; + } + } + } else { + if ( vpc.vpc_prio[cur_prio].vdc1_enabled ) { + if ( drawn[1][i] ) { + line_buffer[i] = temp_buffer[1][i]; + } + } + } + } + } + } else { + /* We are in one of the blanking areas */ + draw_black_line( vce.current_bitmap_line ); + } + + /* bump current scanline */ + vce.current_bitmap_line = ( vce.current_bitmap_line + 1 ) % VDC_LPF; + vdc_advance_line( 0 ); + vdc_advance_line( 1 ); +} + +static void vdc_advance_line(int which) { + int ret = 0; + + vdc[which].curline += 1; + vdc[which].current_segment_line += 1; + vdc[which].raster_count += 1; + + if ( vdc[which].satb_countdown ) { + vdc[which].satb_countdown -= 1; + if ( vdc[which].satb_countdown == 0 ) { + if ( vdc[which].vdc_data[DCR].w & DCR_DSC ) { + vdc[which].status |= VDC_DS; /* set satb done flag */ + ret = 1; + } + } + } + + if ( vce.current_bitmap_line == 0 ) { + vdc[which].current_segment = STATE_VSW; + vdc[which].current_segment_line = 0; + vdc[which].vblank_triggered = 0; + vdc[which].curline = 0; + } + + if ( STATE_VSW == vdc[which].current_segment && vdc[which].current_segment_line >= ( vdc[which].vdc_data[VPR].b.l & 0x1F ) ) { + vdc[which].current_segment = STATE_VDS; + vdc[which].current_segment_line = 0; + } + + if ( STATE_VDS == vdc[which].current_segment && vdc[which].current_segment_line >= vdc[which].vdc_data[VPR].b.h ) { + vdc[which].current_segment = STATE_VDW; + vdc[which].current_segment_line = 0; + vdc[which].raster_count = 0x40; + } + + if ( STATE_VDW == vdc[which].current_segment && vdc[which].current_segment_line > ( vdc[which].vdc_data[VDW].w & 0x01FF ) ) { + vdc[which].current_segment = STATE_VCR; + vdc[which].current_segment_line = 0; + + /* Generate VBlank interrupt, sprite DMA */ + vdc[which].vblank_triggered = 1; + if ( vdc[which].vdc_data[CR].w & CR_VR ) { + vdc[which].status |= VDC_VD; + ret = 1; + } + + /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */ + if( ( vdc[which].vdc_data[DCR].w & DCR_DSR ) || vdc[which].dvssr_write ) { + int i; + + vdc[which].dvssr_write = 0; + + for( i = 0; i < 256; i++ ) { + vdc[which].sprite_ram[i] = ( vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w << 1 ) + i * 2 + 1 ] << 8 ) | vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w << 1 ) + i * 2 ]; + } + + /* generate interrupt if needed */ + if ( vdc[which].vdc_data[DCR].w & DCR_DSC ) { + vdc[which].satb_countdown = 4; + } + } + } + + if ( STATE_VCR == vdc[which].current_segment ) { + if ( vdc[which].current_segment_line >= 3 && vdc[which].current_segment_line >= vdc[which].vdc_data[VCR].b.l ) { + vdc[which].current_segment = STATE_VSW; + vdc[which].current_segment_line = 0; + vdc[which].curline = 0; + } + } + + /* generate interrupt on line compare if necessary */ + if ( vdc[which].raster_count == vdc[which].vdc_data[RCR].w && vdc[which].vdc_data[CR].w & CR_RC ) { + vdc[which].status |= VDC_RR; + ret = 1; + } + + /* handle frame events */ + if(vdc[which].curline == 261 && ! vdc[which].vblank_triggered ) { + + vdc[which].vblank_triggered = 1; + if(vdc[which].vdc_data[CR].w & CR_VR) { /* generate IRQ1 if enabled */ + vdc[which].status |= VDC_VD; /* set vblank flag */ + ret = 1; + } + + /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */ + if ( ( vdc[which].vdc_data[DCR].w & DCR_DSR ) || vdc[which].dvssr_write ) { + int i; + + vdc[which].dvssr_write = 0; +#ifdef MAME_DEBUG + assert(((vdc[which].vdc_data[DVSSR].w<<1) + 512) <= 0x10000); +#endif + for( i = 0; i < 256; i++ ) { + vdc[which].sprite_ram[i] = ( vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w << 1 ) + i * 2 + 1 ] << 8 ) | vdc[which].vram[ ( vdc[which].vdc_data[DVSSR].w << 1 ) + i * 2 ]; + } + + /* generate interrupt if needed */ + if(vdc[which].vdc_data[DCR].w & DCR_DSC) { + vdc[which].satb_countdown = 4; + } + } + } + + if (ret) + cpunum_set_input_line(0, 0, HOLD_LINE); +} + +VIDEO_START( pce ) +{ + logerror("*** pce_vh_start\n"); + + /* clear context */ + memset(&vdc, 0, sizeof(vdc)); + memset(&vce, 0, sizeof(vce)); + memset(&vpc, 0, sizeof(vpc)); + + /* allocate VRAM */ + vdc[0].vram = auto_malloc(0x10000); + vdc[1].vram = auto_malloc(0x10000); + memset(vdc[0].vram, 0, 0x10000); + memset(vdc[1].vram, 0, 0x10000); + + /* create display bitmap */ + vce.bmp = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format); + + vdc[0].inc = 1; + vdc[1].inc = 1; + + vpc_init(); +} + + +VIDEO_UPDATE( pce ) +{ + /* copy our rendering buffer to the display */ + copybitmap (bitmap,vce.bmp,0,0,0,0,cliprect,TRANSPARENCY_NONE,0); + return 0; +} + +static void draw_black_line(int line) +{ + int i; + + /* our line buffer */ + UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, line, 0 ); + + for( i=0; i< VDC_WPF; i++ ) + line_buffer[i] = get_black_pen( Machine ); +} + +static void draw_overscan_line(int line) +{ + int i; + + /* Are we in greyscale mode or in color mode? */ + int color_base = vce.vce_control & 0x80 ? 512 : 0; + + /* our line buffer */ + UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, line, 0 ); + + for ( i = 0; i < VDC_WPF; i++ ) + line_buffer[i] = Machine->pens[color_base + vce.vce_data[0x100].w]; +} + +static void draw_sgx_overscan_line(int line) { + int i; + + /* Are we in greyscale mode or in color mode? */ + int color_base = vce.vce_control & 0x80 ? 512 : 0; + + /* our line buffer */ + UINT16 *line_buffer = BITMAP_ADDR16( vce.bmp, line, 0 ); + + for ( i = 0; i < VDC_WPF; i++ ) + line_buffer[i] = Machine->pens[color_base + vce.vce_data[0].w]; +} + +static void vram_write(int which, offs_t offset, UINT8 data) +{ + if(offset & 0x10000) + { + logerror("VDC #%d: Write to VRAM offset %05X\n", which, offset); + return; + } + else + { + vdc[which].vram[offset] = data; + } +} + +static UINT8 vram_read(int which, offs_t offset) +{ + UINT8 temp; + + if(offset & 0x10000) + { + temp = vdc[which].vram[offset & 0xFFFF]; + } + else + { + temp = vdc[which].vram[offset]; + } + + return temp; +} + + +static void vdc_w( int which, offs_t offset, UINT8 data ) +{ + switch(offset&3) + { + case 0x00: /* VDC register select */ + vdc[which].vdc_register = (data & 0x1F); + break; + + case 0x02: /* VDC data (LSB) */ + vdc[which].vdc_data[vdc[which].vdc_register].b.l = data; + switch(vdc[which].vdc_register) + { + case VxR: /* LSB of data to write to VRAM */ + vdc[which].vdc_latch = data; + break; + + case BYR: + vdc[which].y_scroll=vdc[which].vdc_data[BYR].w; + break; + + case HDR: + vdc[which].physical_width = ((data & 0x003F) + 1) << 3; + break; + + case VDW: + vdc[which].physical_height &= 0xFF00; + vdc[which].physical_height |= (data & 0xFF); + vdc[which].physical_height &= 0x01FF; + break; + + case LENR: +// logerror("LENR LSB = %02X\n", data); + break; + case SOUR: +// logerror("SOUR LSB = %02X\n", data); + break; + case DESR: +// logerror("DESR LSB = %02X\n", data); + break; + } + break; + + case 0x03: /* VDC data (MSB) */ + vdc[which].vdc_data[vdc[which].vdc_register].b.h = data; + switch(vdc[which].vdc_register) + { + case VxR: /* MSB of data to write to VRAM */ + vram_write(which, vdc[which].vdc_data[MAWR].w*2+0, vdc[which].vdc_latch); + vram_write(which, vdc[which].vdc_data[MAWR].w*2+1, data); + vdc[which].vdc_data[MAWR].w += vdc[which].inc; + break; + + case CR: + { + static const unsigned char inctab[] = {1, 32, 64, 128}; + vdc[which].inc = inctab[(data >> 3) & 3]; + } + break; + + case VDW: + vdc[which].physical_height &= 0x00FF; + vdc[which].physical_height |= (data << 8); + vdc[which].physical_height &= 0x01FF; + break; + + case DVSSR: + /* Force VRAM <> SATB DMA for this frame */ + vdc[which].dvssr_write = 1; + break; + + case BYR: + vdc[which].y_scroll=vdc[which].vdc_data[BYR].w; + break; + + case LENR: + vdc_do_dma( which ); + break; + case SOUR: +// logerror("SOUR MSB = %02X\n", data); + break; + case DESR: +// logerror("DESR MSB = %02X\n", data); + break; + } + break; + } +} + +static UINT8 vdc_r( int which, offs_t offset ) +{ + int temp = 0; + switch(offset&3) + { + case 0x00: + temp = vdc[which].status; + vdc[which].status &= ~(VDC_VD | VDC_RR | VDC_CR | VDC_OR | VDC_DS); + cpunum_set_input_line(0,0,CLEAR_LINE); + break; + + case 0x02: + temp = vram_read(which, vdc[which].vdc_data[MARR].w*2+0); + break; + + case 0x03: + temp = vram_read(which, vdc[which].vdc_data[MARR].w*2+1); + if ( vdc[which].vdc_register ==VxR ) { + vdc[which].vdc_data[MARR].w += vdc[which].inc; + } + break; + } + return (temp); +} + +WRITE8_HANDLER( vdc_0_w ) { vdc_w( 0, offset, data ); } +WRITE8_HANDLER( vdc_1_w ) { vdc_w( 1, offset, data ); } +READ8_HANDLER( vdc_0_r ) { return vdc_r( 0, offset ); } +READ8_HANDLER( vdc_1_r ) { return vdc_r( 1, offset ); } + +PALETTE_INIT( vce ) { + int i; + + for( i = 0; i < 512; i++ ) { + int r = (( i >> 3) & 7) << 5; + int g = (( i >> 6) & 7) << 5; + int b = (( i ) & 7) << 5; + int y = ( ( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16; + palette_set_color_rgb(machine, i, r, g, b); + palette_set_color_rgb(machine, 512+i, y, y, y); + } +} + + READ8_HANDLER ( vce_r ) +{ + int temp = 0xFF; + switch(offset & 7) + { + case 0x04: /* color table data (LSB) */ + temp = vce.vce_data[vce.vce_address.w].b.l; + break; + + case 0x05: /* color table data (MSB) */ + temp = vce.vce_data[vce.vce_address.w].b.h; + temp |= 0xFE; + vce.vce_address.w = (vce.vce_address.w + 1) & 0x01FF; + break; + } + return (temp); +} + + +WRITE8_HANDLER ( vce_w ) +{ + switch(offset & 7) + { + case 0x00: /* control reg. */ + vce.vce_control = data; + break; + + case 0x02: /* color table address (LSB) */ + vce.vce_address.b.l = data; + vce.vce_address.w &= 0x1FF; + break; + + case 0x03: /* color table address (MSB) */ + vce.vce_address.b.h = data; + vce.vce_address.w &= 0x1FF; + break; + + case 0x04: /* color table data (LSB) */ + vce.vce_data[vce.vce_address.w].b.l = data; + break; + + case 0x05: /* color table data (MSB) */ + vce.vce_data[vce.vce_address.w].b.h = data & 0x01; + + /* bump internal address */ + vce.vce_address.w = (vce.vce_address.w + 1) & 0x01FF; + break; + } +} + + +static void pce_refresh_line(int which, int line, int external_input, UINT8 *drawn, UINT16 *line_buffer) +{ + static int width_table[4] = {5, 6, 7, 7}; + + int scroll_y = ( vdc[which].y_scroll & 0x01FF); + int scroll_x = (vdc[which].vdc_data[BXR].w & 0x03FF); + int nt_index; + + /* is virtual map 32 or 64 characters tall ? (256 or 512 pixels) */ + int v_line = (scroll_y) & (vdc[which].vdc_data[MWR].w & 0x0040 ? 0x1FF : 0x0FF); + + /* row within character */ + int v_row = (v_line & 7); + + /* row of characters in BAT */ + int nt_row = (v_line >> 3); + + /* virtual X size (# bits to shift) */ + int v_width = width_table[(vdc[which].vdc_data[MWR].w >> 4) & 3]; + + /* pointer to the name table (Background Attribute Table) in VRAM */ + UINT8 *bat = &(vdc[which].vram[nt_row << (v_width+1)]); + + /* Are we in greyscale mode or in color mode? */ + int color_base = vce.vce_control & 0x80 ? 512 : 0; + + int b0, b1, b2, b3; + int i0, i1, i2, i3; + int cell_pattern_index; + int cell_palette; + int x, c, i; + + /* character blanking bit */ + if(!(vdc[which].vdc_data[CR].w & CR_BB)) + { + return; + } + else + { + int pixel = 0; + int phys_x = - ( scroll_x & 0x07 ); + + for(i=0;i<(vdc[which].physical_width >> 3) + 1;i++) + { + nt_index = (i + (scroll_x >> 3)) & ((2 << (v_width-1))-1); + nt_index *= 2; + + /* get name table data: */ + + /* palette # = index from 0-15 */ + cell_palette = ( bat[nt_index + 1] >> 4 ) & 0x0F; + + /* This is the 'character number', from 0-0x0FFF */ + /* then it is shifted left 4 bits to form a VRAM address */ + /* and one more bit to convert VRAM word offset to a */ + /* byte-offset within the VRAM space */ + cell_pattern_index = ( ( ( bat[nt_index + 1] << 8 ) | bat[nt_index] ) & 0x0FFF) << 5; + + b0 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x00); + b1 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x01); + b2 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x10); + b3 = vram_read(which, (cell_pattern_index) + (v_row << 1) + 0x11); + + for(x=0;x<8;x++) + { + i0 = (b0 >> (7-x)) & 1; + i1 = (b1 >> (7-x)) & 1; + i2 = (b2 >> (7-x)) & 1; + i3 = (b3 >> (7-x)) & 1; + c = (cell_palette << 4 | i3 << 3 | i2 << 2 | i1 << 1 | i0); + + /* colour #0 always comes from palette #0 */ + if ( ! ( c & 0x0F ) ) + c &= 0x0F; + + if ( phys_x >= 0 && phys_x < vdc[which].physical_width ) { + drawn[ pixel ] = c ? 1 : 0; + if ( c || ! external_input ) + line_buffer[ pixel ] = Machine->pens[color_base + vce.vce_data[c].w]; + pixel++; + if ( vdc[which].physical_width != 512 ) { + while ( pixel < ( ( ( phys_x + 1 ) * 512 ) / vdc[which].physical_width ) ) { + drawn[ pixel ] = c ? 1 : 0; + if ( c || ! external_input ) + line_buffer[ pixel ] = Machine->pens[color_base + vce.vce_data[c].w]; + pixel++; + } + } + } + phys_x += 1; + } + } + } +} + + + +static void conv_obj(int which, int i, int l, int hf, int vf, char *buf) +{ + int b0, b1, b2, b3, i0, i1, i2, i3, x; + int xi; + int tmp; + + l &= 0x0F; + if(vf) l = (15 - l); + + tmp = l + ( i << 5); + + b0 = vram_read(which, (tmp + 0x00)<<1); + b0 |= vram_read(which, ((tmp + 0x00)<<1)+1)<<8; + b1 = vram_read(which, (tmp + 0x10)<<1); + b1 |= vram_read(which, ((tmp + 0x10)<<1)+1)<<8; + b2 = vram_read(which, (tmp + 0x20)<<1); + b2 |= vram_read(which, ((tmp + 0x20)<<1)+1)<<8; + b3 = vram_read(which, (tmp + 0x30)<<1); + b3 |= vram_read(which, ((tmp + 0x30)<<1)+1)<<8; + + for(x=0;x<16;x++) + { + if(hf) xi = x; else xi = (15 - x); + i0 = (b0 >> xi) & 1; + i1 = (b1 >> xi) & 1; + i2 = (b2 >> xi) & 1; + i3 = (b3 >> xi) & 1; + buf[x] = (i3 << 3 | i2 << 2 | i1 << 1 | i0); + } +} + +static void pce_refresh_sprites(int which, int line, UINT8 *drawn, UINT16 *line_buffer) +{ + int i; + UINT8 sprites_drawn=0; + + /* Are we in greyscale mode or in color mode? */ + int color_base = vce.vce_control & 0x80 ? 512 : 0; + + /* count up: Highest priority is Sprite 0 */ + for(i=0; i<64; i++) + { + static const int cgy_table[] = {16, 32, 64, 64}; + + int obj_y = (vdc[which].sprite_ram[(i<<2)+0] & 0x03FF) - 64; + int obj_x = (vdc[which].sprite_ram[(i<<2)+1] & 0x03FF) - 32; + int obj_i = (vdc[which].sprite_ram[(i<<2)+2] & 0x07FE); + int obj_a = (vdc[which].sprite_ram[(i<<2)+3]); + int cgx = (obj_a >> 8) & 1; /* sprite width */ + int cgy = (obj_a >> 12) & 3; /* sprite height */ + int hf = (obj_a >> 11) & 1; /* horizontal flip */ + int vf = (obj_a >> 15) & 1; /* vertical flip */ + int palette = (obj_a & 0x000F); + int priority = (obj_a >> 7) & 1; + int obj_h = cgy_table[cgy]; + int obj_l = (line - obj_y); + int cgypos; + char buf[16]; + + if ((obj_y == -64) || (obj_y > line)) continue; + if ((obj_x == -32) || (obj_x >= vdc[which].physical_width)) continue; + + /* no need to draw an object that's ABOVE where we are. */ + if((obj_y + obj_h) 16) { + vdc[which].status |= VDC_OR; + if(vdc[which].vdc_data[CR].w&CR_OV) + cpunum_set_input_line(0, 0, ASSERT_LINE); + continue; /* Should cause an interrupt */ + } + + cgypos = (obj_l >> 4); + if(vf) cgypos = ((obj_h - 1) >> 4) - cgypos; + + if(cgx == 0) + { + int x; + int pixel_x = ( ( obj_x * 512 ) / vdc[which].physical_width ); + + conv_obj(which, obj_i + (cgypos << 2), obj_l, hf, vf, buf); + + for(x=0;x<16;x++) + { + if(((obj_x + x)<(vdc[which].physical_width))&&((obj_x + x)>=0)) + { + if ( buf[x] ) { + if( drawn[pixel_x] < 2 ) { + if( priority || drawn[pixel_x] == 0 ) { + line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + if ( vdc[which].physical_width != 512 ) { + int dp = 1; + while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) ) { + drawn[pixel_x + dp] = i + 2; + line_buffer[pixel_x + dp] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + dp++; + } + } + } + drawn[pixel_x] = i + 2; + } + /* Check for sprite #0 collision */ + else if (drawn[pixel_x]==2) + { + if(vdc[which].vdc_data[CR].w&CR_CC) + cpunum_set_input_line(0, 0, ASSERT_LINE); + vdc[which].status|=VDC_CR; + } + } + } + if ( vdc[which].physical_width != 512 ) { + pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width; + } else { + pixel_x += 1; + } + } + } + else + { + int x; + int pixel_x = ( ( obj_x * 512 ) / vdc[which].physical_width ); + + conv_obj(which, obj_i + (cgypos << 2) + (hf ? 2 : 0), obj_l, hf, vf, buf); + + for(x=0;x<16;x++) + { + if(((obj_x + x)<(vdc[which].physical_width))&&((obj_x + x)>=0)) + { + if ( buf[x] ) { + if( drawn[pixel_x] < 2 ) { + if ( priority || drawn[pixel_x] == 0 ) { + line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + if ( vdc[which].physical_width != 512 ) { + int dp = 1; + while ( pixel_x + dp < ( ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width ) ) { + drawn[pixel_x + dp] = i + 2; + line_buffer[pixel_x + dp] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + dp++; + } + } + } + drawn[pixel_x] = i + 2; + } + /* Check for sprite #0 collision */ + else if ( drawn[pixel_x] == 2 ) { + if(vdc[which].vdc_data[CR].w&CR_CC) + cpunum_set_input_line(0, 0, ASSERT_LINE); + vdc[which].status|=VDC_CR; + } + } + } + if ( vdc[which].physical_width != 512 ) { + pixel_x = ( ( obj_x + x + 1 ) * 512 ) / vdc[which].physical_width; + } else { + pixel_x += 1; + } + } + + /* 32 pixel wide sprites are counted as 2 sprites and the right half + is only drawn if there are 2 open slots. + */ + sprites_drawn++; + if( sprites_drawn > 16 ) { + vdc[which].status |= VDC_OR; + if(vdc[which].vdc_data[CR].w&CR_OV) + cpunum_set_input_line(0, 0, ASSERT_LINE); + } else { + conv_obj(which, obj_i + (cgypos << 2) + (hf ? 0 : 2), obj_l, hf, vf, buf); + for(x=0;x<16;x++) + { + if(((obj_x + 0x10 + x)<(vdc[which].physical_width))&&((obj_x + 0x10 + x)>=0)) + { + if ( buf[x] ) { + if( drawn[pixel_x] < 2 ) { + if( priority || drawn[pixel_x] == 0 ) { + line_buffer[pixel_x] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + if ( vdc[which].physical_width != 512 ) { + int dp = 1; + while ( pixel_x + dp < ( ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width ) ) { + drawn[pixel_x + dp] = i + 2; + line_buffer[pixel_x + dp] = Machine->pens[color_base + vce.vce_data[0x100 + (palette << 4) + buf[x]].w]; + dp++; + } + } + } + drawn[pixel_x] = i + 2; + } + /* Check for sprite #0 collision */ + else if ( drawn[pixel_x]==2 ) { + if(vdc[which].vdc_data[CR].w&CR_CC) + cpunum_set_input_line(0, 0, ASSERT_LINE); + vdc[which].status|=VDC_CR; + } + } + } + if ( vdc[which].physical_width != 512 ) { + pixel_x = ( ( obj_x + x + 17 ) * 512 ) / vdc[which].physical_width; + } else { + pixel_x += 1; + } + } + } + } + } + } +} + +static void vdc_do_dma(int which) +{ + int src = vdc[which].vdc_data[SOUR].w; + int dst = vdc[which].vdc_data[DESR].w; + int len = vdc[which].vdc_data[LENR].w; + + int did = (vdc[which].vdc_data[DCR].w >> 3) & 1; + int sid = (vdc[which].vdc_data[DCR].w >> 2) & 1; + int dvc = (vdc[which].vdc_data[DCR].w >> 1) & 1; + + do { + UINT8 l, h; + + l = vram_read(which, src<<1); + h = vram_read(which, (src<<1) + 1); + + vram_write(which, dst<<1,l); + vram_write(which, 1+(dst<<1),h); + + if(sid) src = (src - 1) & 0xFFFF; + else src = (src + 1) & 0xFFFF; + + if(did) dst = (dst - 1) & 0xFFFF; + else dst = (dst + 1) & 0xFFFF; + + len = (len - 1) & 0xFFFF; + + } while (len != 0xFFFF); + + vdc[which].status |= VDC_DV; + vdc[which].vdc_data[SOUR].w = src; + vdc[which].vdc_data[DESR].w = dst; + vdc[which].vdc_data[LENR].w = len; + if(dvc) + { + cpunum_set_input_line(0, 0, ASSERT_LINE); + } + +} + +static void vpc_update_prio_map( void ) { + int i; + + for( i = 0; i < 512; i++ ) { + vpc.prio_map[i] = 0; + if ( vpc.window1.w < 0x40 || i > vpc.window1.w ) { + vpc.prio_map[i] |= 1; + } + if ( vpc.window2.w < 0x40 || i > vpc.window2.w ) { + vpc.prio_map[i] |= 2; + } + } +} + +WRITE8_HANDLER( vpc_w ) { +//if ( offset < 2 ) +//printf("VPC write offset %02X, data %02X\n", offset, data ); + switch( offset & 0x07 ) { + case 0x00: /* Priority register #0 */ + vpc.priority.b.l = data; + vpc.vpc_prio[0].prio = ( data >> 2 ) & 3; + vpc.vpc_prio[0].vdc0_enabled = data & 1; + vpc.vpc_prio[0].vdc1_enabled = data & 2; + vpc.vpc_prio[1].prio = ( data >> 6 ) & 3; + vpc.vpc_prio[1].vdc0_enabled = data & 0x10; + vpc.vpc_prio[1].vdc1_enabled = data & 0x20; + break; + case 0x01: /* Priority register #1 */ + vpc.priority.b.h = data; + vpc.vpc_prio[2].prio = ( data >> 2 ) & 3; + vpc.vpc_prio[2].vdc0_enabled = data & 1; + vpc.vpc_prio[2].vdc1_enabled = data & 2; + vpc.vpc_prio[3].prio = ( data >> 6 ) & 3; + vpc.vpc_prio[3].vdc0_enabled = data & 0x10; + vpc.vpc_prio[3].vdc1_enabled = data & 0x20; + break; + case 0x02: /* Window 1 LSB */ + vpc.window1.b.l = data; + vpc_update_prio_map(); + break; + case 0x03: /* Window 1 MSB */ + vpc.window1.b.h = data & 3; + vpc_update_prio_map(); + break; + case 0x04: /* Window 2 LSB */ + vpc.window2.b.l = data; + vpc_update_prio_map(); + break; + case 0x05: /* Window 2 MSB */ + vpc.window2.b.h = data & 3; + vpc_update_prio_map(); + break; + case 0x06: /* VDC I/O select */ + vpc.vdc_select = data & 1; + break; + } +} + +READ8_HANDLER( vpc_r ) { + UINT8 data = 0; + switch( offset & 0x07 ) { + case 0x00: /* Priority register #0 */ + data = vpc.priority.b.l; + break; + case 0x01: /* Priority register #1 */ + data = vpc.priority.b.h; + break; + case 0x02: /* Window 1 LSB */ + data = vpc.window1.b.l; + break; + case 0x03: /* Window 1 MSB; high bits are 0 or 1? */ + data = vpc.window1.b.h; + break; + case 0x04: /* Window 2 LSB */ + data = vpc.window2.b.l; + break; + case 0x05: /* Window 2 MSB; high bits are 0 or 1? */ + data = vpc.window2.b.h; + break; + } + return data; +} + +static void vpc_init( void ) { + vpc_w( 0, 0x11 ); + vpc_w( 1, 0x11 ); + vpc.window1.w = 0; + vpc.window2.w = 0; + vpc.vdc_select = 0; +} + +WRITE8_HANDLER( sgx_vdc_w ) { + if ( vpc.vdc_select ) { + vdc_1_w( offset, data ); + } else { + vdc_0_w( offset, data ); + } +} + +READ8_HANDLER( sgx_vdc_r ) { + return ( vpc.vdc_select ) ? vdc_1_r( offset ) : vdc_0_r( offset ); +} + diff --git a/src/mame/video/vdc.h b/src/mame/video/vdc.h new file mode 100644 index 00000000000..f4968b0882e --- /dev/null +++ b/src/mame/video/vdc.h @@ -0,0 +1,55 @@ + +#include "driver.h" +#include "video/generic.h" + +VIDEO_START( pce ); +VIDEO_UPDATE( pce ); +WRITE8_HANDLER ( vdc_0_w ); +WRITE8_HANDLER ( vdc_1_w ); + READ8_HANDLER ( vdc_0_r ); + READ8_HANDLER ( vdc_1_r ); +PALETTE_INIT( vce ); + READ8_HANDLER ( vce_r ); +WRITE8_HANDLER ( vce_w ); +WRITE8_HANDLER( vpc_w ); + READ8_HANDLER( vpc_r ); +WRITE8_HANDLER( sgx_vdc_w ); + READ8_HANDLER( sgx_vdc_r ); +INTERRUPT_GEN( pce_interrupt ); +INTERRUPT_GEN( sgx_interrupt ); + +/* Screen timing stuff */ + +#define VDC_WPF 684 /* width of a line in frame including blanking areas */ +#define VDC_LPF 262 /* number of lines in a single frame */ + +/* Bits in the VDC status register */ + +#define VDC_BSY 0x40 /* Set when the VDC accesses VRAM */ +#define VDC_VD 0x20 /* Set when in the vertical blanking period */ +#define VDC_DV 0x10 /* Set when a VRAM > VRAM DMA transfer is done */ +#define VDC_DS 0x08 /* Set when a VRAM > SATB DMA transfer is done */ +#define VDC_RR 0x04 /* Set when the current scanline equals the RCR register */ +#define VDC_OR 0x02 /* Set when there are more than 16 sprites on a line */ +#define VDC_CR 0x01 /* Set when sprite #0 overlaps with another sprite */ + +/* Bits in the CR register */ + +#define CR_BB 0x80 /* Background blanking */ +#define CR_SB 0x40 /* Object blanking */ +#define CR_VR 0x08 /* Interrupt on vertical blank enable */ +#define CR_RC 0x04 /* Interrupt on line compare enable */ +#define CR_OV 0x02 /* Interrupt on sprite overflow enable */ +#define CR_CC 0x01 /* Interrupt on sprite #0 collision enable */ + +/* Bits in the DCR regsiter */ + +#define DCR_DSR 0x10 /* VRAM > SATB auto-transfer enable */ +#define DCR_DID 0x08 /* Destination diretion */ +#define DCR_SID 0x04 /* Source direction */ +#define DCR_DVC 0x02 /* VRAM > VRAM EOT interrupt enable */ +#define DCR_DSC 0x01 /* VRAM > SATB EOT interrupt enable */ + +/* just to keep things simple... */ +enum vdc_regs {MAWR = 0, MARR, VxR, reg3, reg4, CR, RCR, BXR, BYR, MWR, HSR, HDR, VPR, VDW, VCR, DCR, SOUR, DESR, LENR, DVSSR }; + diff --git a/src/osd/windows/vconv.c b/src/osd/windows/vconv.c index f2431e9c073..1fd6c912c6c 100644 --- a/src/osd/windows/vconv.c +++ b/src/osd/windows/vconv.c @@ -56,7 +56,7 @@ static const translation_info gcc_translate[] = { 0, "-c", "/c~/Fo" }, { 0, "-E", "/c~/E >" }, { 0, "-S", "/c~/Fa" }, - { VS7, "-O0", "/Od /GS" }, + { VS7, "-O0", "/Od /GS /Oi" }, { 0, "-O0", "/Od" }, { 0, "-O1", "/O2" }, { 0, "-O2", "/O2" },