diff options
Diffstat (limited to 'trunk/src/mame/drivers/ghosteo.c')
-rw-r--r-- | trunk/src/mame/drivers/ghosteo.c | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/ghosteo.c b/trunk/src/mame/drivers/ghosteo.c new file mode 100644 index 00000000000..5e511d1f387 --- /dev/null +++ b/trunk/src/mame/drivers/ghosteo.c @@ -0,0 +1,557 @@ +/************************************************************************ + +Eolith Ghost Hardware driver + +1. CPU +- 16/32bit RISC Microprocessor(ARM920T CPU core) +- Separate 16KB Instruction and 16KB Data Cache +- Operating Frequency : Up to 203MHz + +2. MEMORY +- Main Memory : 32Mbytes(Maximum 128Mbytes) SDRAM +- NAND FLASH : 16M,32M, 64M, 128M, 256Mbytes + +3. VIDEO +- RGB (5:6:5) format +- Supports 1,2,4 or 8 bpp(bit-per-pixel) palette color displays +- Supports 16 bpp non-palette true-color displays +- Supports multiple screen size +Typical actual screen size : 320*240, 640*480 +Maximum virtual screen size is 4Mbytes +Maximum virtual screen size in 64K color mode : 2048*1024 +- Rendering Performance : 480 Objects per sec.(256*256 sprite) + +4. SOUND +Internal Audio Engine or External System Available +TDA1519(Philips)Stereo Power AMP +- Internal Audio Engine : 1-ch IIS-bus for audio interface +Serial, 8-/16-bit per channel data transfers +128 Bytes (64-Byte + 64-Byte) FIFO for Tx/Rx +- External System(Option) : General MIDI Chipset QDSP1000 +MIDI 16th Channel(32 Poly) using as Effect +Effect EPROM : 512Kbyte or 1Mbyte +MIDI Background Music EPROM:512Kbyte + +5. Board Feature +- JAMMA Standard ( Application of PACK TYPE ) : 1P,2P ? Joystick (Up, Down, Left, Right), 4 Push Buttons, Start Button +- 1P,2P ? Coin, Coin Counter +- On Board Service Button, On Board Test Button +- Photo Gun : 1P, 2P Photo Gun (or Light Pen) (Option) +- ETC : Security System Available +Multi I/O Port Available +Coin Counter Available +Gun Shooting Effect Available (Option) +Hopper, Ticket Counter, Prize System (Option) + +6. Develoment +- On-chip ICEbreaker debug support with JTAG-based debugging solution +- MultiICE, OPENICE etc. +- Compiler : ADS, SDT + + +*/ + +#include "emu.h" +#include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" +#include "machine/s3c2410.h" +//#include "machine/smartmed.h" +#include "machine/i2cmem.h" + + +enum nand_mode_t +{ + NAND_M_INIT, // initial state + NAND_M_READ, // read page data +}; + +struct nand_t +{ + nand_mode_t mode; + int page_addr; + int byte_addr; + int addr_load_ptr; +}; + + +class ghosteo_state : public driver_device +{ +public: + ghosteo_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) { } + + UINT32 *m_system_memory; + UINT32 *m_steppingstone; + int m_security_count; + UINT32 m_bballoon_port[20]; + struct nand_t m_nand; +}; + + + +/* +Power management: +Normal, Idle, Slow & Power-off +4-ch 16 bit PWM ( Pulse Width Modulation), & 1-ch 16-bit timer for OS +RTC : 32.768 KHz, alarm interrupt +GPIO :117 (multiplexed I/O) +3-ch UARTs +4 ch DMA Controllers +8-ch 10-bit A/D (Max. 500KSPS), including TSP Controller +TFT LCD/STN LCD Controller (16bit, 640?480 maximum) +16-bit Watch-dog Timer +1-ch IIC-Bus Interface +IIS-Bus Interface +Screen Size: up to 640 x 480 +2-ch SPI (Synchronous Serial I/O) +SD Host/MMC (Multi Media Card) Interface +USB Host/Device Interface +Debug & TEST +NAND Flash Controller (4KB internal buffer) +24-ch external interrupts Controller (Wake-up source 16-ch) +*/ + +static const UINT8 security_data[] = { 0x01, 0xC4, 0xFF, 0x22 }; + + +static UINT32 s3c2410_gpio_port_r( device_t *device, int port) +{ + ghosteo_state *state = device->machine().driver_data<ghosteo_state>(); + UINT32 data = state->m_bballoon_port[port]; + switch (port) + { + case S3C2410_GPIO_PORT_F : + { + data = (data & ~0xFF) | security_data[state->m_security_count]; // bballoon security @ 0x3001BD68 + } + break; + case S3C2410_GPIO_PORT_G : + { + data = data ^ 0x20; + state->m_bballoon_port[port] = data; + } + break; + } + return data; +} + +static void s3c2410_gpio_port_w( device_t *device, int port, UINT32 data) +{ + ghosteo_state *state = device->machine().driver_data<ghosteo_state>(); + UINT32 old_value = state->m_bballoon_port[port]; + state->m_bballoon_port[port] = data; + switch (port) + { + case S3C2410_GPIO_PORT_F : + { + switch (data) + { + case 0x04 : state->m_security_count = 0; break; + case 0x44 : state->m_security_count = 2; break; + } + } + break; + case S3C2410_GPIO_PORT_G : + { + // 0 -> 1 + if (((data & 0x10) != 0) && ((old_value & 0x10) == 0)) + { + logerror( "security_count %d -> %d\n", state->m_security_count, state->m_security_count + 1); + state->m_security_count++; + if (state->m_security_count > 7) state->m_security_count = 0; + } + } + break; + } +} + +static WRITE8_DEVICE_HANDLER( s3c2410_nand_command_w ) +{ + ghosteo_state *state = device->machine().driver_data<ghosteo_state>(); + struct nand_t &nand = state->m_nand; +// device_t *nand = device->machine().device( "nand"); + logerror( "s3c2410_nand_command_w %02X\n", data); + switch (data) + { + case 0xFF : + { + nand.mode = NAND_M_INIT; + s3c2410_pin_frnb_w( device, 1); + } + break; + case 0x00 : + { + nand.mode = NAND_M_READ; + nand.page_addr = 0; + nand.addr_load_ptr = 0; + } + break; + } +} + +static WRITE8_DEVICE_HANDLER( s3c2410_nand_address_w ) +{ + ghosteo_state *state = device->machine().driver_data<ghosteo_state>(); + struct nand_t &nand = state->m_nand; +// device_t *nand = device->machine().device( "nand"); + logerror( "s3c2410_nand_address_w %02X\n", data); + switch (nand.mode) + { + case NAND_M_INIT : + { + logerror( "nand: unexpected address port write\n"); + } + break; + case NAND_M_READ : + { + if (nand.addr_load_ptr == 0) + { + nand.byte_addr = data; + } + else + { + nand.page_addr = (nand.page_addr & ~(0xFF << ((nand.addr_load_ptr - 1) * 8))) | (data << ((nand.addr_load_ptr - 1) * 8)); + } + nand.addr_load_ptr++; + if ((nand.mode == NAND_M_READ) && (nand.addr_load_ptr == 4)) + { + s3c2410_pin_frnb_w( device, 0); + s3c2410_pin_frnb_w( device, 1); + } + } + break; + } +} + +static READ8_DEVICE_HANDLER( s3c2410_nand_data_r ) +{ + ghosteo_state *state = device->machine().driver_data<ghosteo_state>(); + struct nand_t &nand = state->m_nand; +// device_t *nand = device->machine().device( "nand"); + UINT8 data = 0; + switch (nand.mode) + { + case NAND_M_INIT : + { + logerror( "nand: unexpected address port read\n"); + } + break; + case NAND_M_READ : + { + UINT8 *flash = (UINT8 *)device->machine().region( "user1")->base(); + if (nand.byte_addr < 0x200) + { + data = *(flash + nand.page_addr * 0x200 + nand.byte_addr); + } + else + { + if ((nand.byte_addr >= 0x200) && (nand.byte_addr < 0x204)) + { + UINT8 mecc[4]; + s3c2410_nand_calculate_mecc( flash + nand.page_addr * 0x200, 0x200, mecc); + data = mecc[nand.byte_addr-0x200]; + } + else + { + data = 0xFF; + } + } + nand.byte_addr++; + if (nand.byte_addr == 0x210) + { + nand.byte_addr = 0; + nand.page_addr++; + if (nand.page_addr == 0x10000) nand.page_addr = 0; + } + } + break; + } + logerror( "s3c2410_nand_data_r %02X\n", data); + return data; +} + +static WRITE8_DEVICE_HANDLER( s3c2410_nand_data_w ) +{ +// device_t *nand = device->machine().device( "nand"); + logerror( "s3c2410_nand_data_w %02X\n", data); +} + +static WRITE_LINE_DEVICE_HANDLER( s3c2410_i2c_scl_w ) +{ + device_t *i2cmem = device->machine().device( "i2cmem"); +// logerror( "s3c2410_i2c_scl_w %d\n", state ? 1 : 0); + i2cmem_scl_write( i2cmem, state); +} + +static READ_LINE_DEVICE_HANDLER( s3c2410_i2c_sda_r ) +{ + device_t *i2cmem = device->machine().device( "i2cmem"); + int state; + state = i2cmem_sda_read( i2cmem); +// logerror( "s3c2410_i2c_sda_r %d\n", state ? 1 : 0); + return state; +} + +static WRITE_LINE_DEVICE_HANDLER( s3c2410_i2c_sda_w ) +{ + device_t *i2cmem = device->machine().device( "i2cmem"); +// logerror( "s3c2410_i2c_sda_w %d\n", state ? 1 : 0); + i2cmem_sda_write( i2cmem, state); +} + +static WRITE32_HANDLER( sound_w ) +{ + if ((data >= 0x20) && (data <= 0x7F)) + { + logerror( "sound_w: music %d\n", data - 0x20); + } + else if ((data >= 0x80) && (data <= 0xFF)) + { + logerror( "sound_w: effect %d\n", data - 0x80); + } + else + { + logerror( "sound_w: unknown (%d)\n", data); + } +} + +static ADDRESS_MAP_START( bballoon_map, AS_PROGRAM, 32 ) + AM_RANGE(0x00000000, 0x00000fff) AM_RAM AM_BASE_MEMBER(ghosteo_state, m_steppingstone) AM_MIRROR(0x40000000) + AM_RANGE(0x10000000, 0x10000003) AM_READ_PORT("10000000") + AM_RANGE(0x10100000, 0x10100003) AM_READ_PORT("10100000") + AM_RANGE(0x10200000, 0x10200003) AM_READ_PORT("10200000") + AM_RANGE(0x10300000, 0x10300003) AM_WRITE(sound_w) + AM_RANGE(0x30000000, 0x31ffffff) AM_RAM AM_BASE_MEMBER(ghosteo_state, m_system_memory) AM_MIRROR(0x02000000) +ADDRESS_MAP_END + +/* +static INPUT_PORTS_START( bballoon ) + PORT_START("10000000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0xFFFFFFC0, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_START("10100000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0xFFFFFFC0, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_START("10200000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_START3 ) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_SERVICE1 ) // "test button" + PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_START4 ) + PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_SERVICE2 ) // "service button" + PORT_BIT( 0xFFFFFF00, IP_ACTIVE_LOW, IPT_START5 ) +INPUT_PORTS_END +*/ + +static INPUT_PORTS_START( bballoon ) + PORT_START("10000000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0xFFFFFFC0, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("10100000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0xFFFFFFC0, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("10200000") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_SERVICE2 ) + PORT_BIT( 0xFFFFFF50, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +/* +static NAND_INTERFACE( bballoon_nand_intf ) +{ + DEVCB_DEVICE_LINE("s3c2410", s3c2410_pin_frnb_w) +}; +*/ + +static const s3c2410_interface bballoon_s3c2410_intf = +{ + // GPIO (port read / port write) + { s3c2410_gpio_port_r, s3c2410_gpio_port_w }, + // I2C (scl write / sda read / sda write) + { s3c2410_i2c_scl_w, s3c2410_i2c_sda_r, s3c2410_i2c_sda_w }, + // ADC (data read) + { NULL }, + // I2S (data write) + { NULL }, + // NAND (command write, address write, data read, data write) + { s3c2410_nand_command_w, s3c2410_nand_address_w, s3c2410_nand_data_r, s3c2410_nand_data_w } +}; + +static const i2cmem_interface i2cmem_interface = +{ + I2CMEM_SLAVE_ADDRESS, 0, 256 +}; + + +device_t* s3c2410; + +static READ32_HANDLER( bballoon_speedup_r ) +{ + UINT32 ret = s3c2410_lcd_r(s3c2410, offset+0x10/4, mem_mask); + + + int pc = cpu_get_pc(&space->device()); + + // these are vblank waits + if (pc == 0x3001c0e4 || pc == 0x3001c0d8) + { + // BnB Arcade + device_spin_until_time(&space->device(), attotime::from_usec(20)); + } + else if (pc == 0x3002b580 || pc == 0x3002b550) + { + // Happy Tour + device_spin_until_time(&space->device(), attotime::from_usec(20)); + } + //else + // printf("speedup %08x %08x\n", pc, ret); + + return ret; +} + +static MACHINE_RESET( bballoon ) +{ + machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4d000010, 0x4d000013, FUNC(bballoon_speedup_r)); + s3c2410 = machine.device("s3c2410"); +} + +static MACHINE_CONFIG_START( bballoon, ghosteo_state ) + + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", ARM9, 200000000) + MCFG_CPU_PROGRAM_MAP(bballoon_map) + + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) + MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32) + MCFG_SCREEN_SIZE(455, 262) + MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 0, 256-1) + MCFG_SCREEN_UPDATE(s3c2410) + + MCFG_PALETTE_LENGTH(256) + + MCFG_MACHINE_RESET( bballoon ) + + MCFG_VIDEO_START(s3c2410) + + MCFG_S3C2410_ADD("s3c2410", 12000000, bballoon_s3c2410_intf) + +// MCFG_NAND_ADD("nand", 0xEC, 0x75) +// MCFG_DEVICE_CONFIG(bballoon_nand_intf) + +// MCFG_I2CMEM_ADD("i2cmem", 0xA0, 0, 0x100, NULL) + MCFG_I2CMEM_ADD("i2cmem", i2cmem_interface) + + /* sound hardware */ +MACHINE_CONFIG_END + +/* +Balloon & Balloon +Eolith, 2003 + +PCB Layout +---------- + +GHOST Ver1.1 2003.03.28 +|---------------------------------------------| +|TDA1519A B2.U20 LED RESET | +| QS1000 | +|DA1311A 24MHz LED| +| | +| | +| |---------| | +| QS1001A.U17 |ARM 312 | | +|J |SAMSUNG | | +|A B1.U16 |S3C2410 | IC42S16800 | +|M | | | +|M |---------| | +|A | +| IC42S16800 | +| 12MHz | +| M24CL16-S | +| | +| | +| * FLASH.U1| +| SERVICE | +|DSW1 TEST | +|---------------------------------------------| +Notes: + * - Unknown SOIC20 chip, surface scratched + FLASH.U1 - Samsung K9F5608U0B 256MBit NAND FlashROM (TSOP48) + U16 - 27C801 8MBit EPROM + U20 - 29F040 EEPROM + IC42S16800 - ISSI IC42S16800 4(2)M x 8(16) Bits x 4 Banks (128MBit) SDRAM + + QS1000 - QDSP QS1000 AdMOS 9638R, Wavetable Audio chip, clock input of 24.000MHz (QFP100) + QS1001A - QDSP QS1001A 512k x8 MaskROM (SOP32) + + qs1001a.u17 was not dumped from this PCB, but is a standard sample rom found on many Eolith games + see eolith.c and vegaeo.c drivers +*/ + +// The NAND dumps are missing the ECC data. We calculate it on the fly, because the games require it, but really it should be dumped hence the 'BAD DUMP' flags +ROM_START( bballoon ) + ROM_REGION( 0x2000000, "user1", 0 ) /* ARM 32 bit code */ + ROM_LOAD( "flash.u1", 0x000000, 0x2000000, BAD_DUMP CRC(73285634) SHA1(4d0210c1bebdf3113a99978ffbcd77d6ee854168) ) // missing ECC data + + // banked every 0x10000 bytes ? + ROM_REGION( 0x080000, "user2", 0 ) + ROM_LOAD( "b2.u20", 0x000000, 0x080000, CRC(0a12334c) SHA1(535b5b34f28435517218100d70147d87809f485a) ) + + ROM_REGION( 0x100000, "sfx", 0 ) /* QDSP samples (SFX) */ + ROM_LOAD( "b1.u16", 0x000000, 0x100000, CRC(c42c1c85) SHA1(e1f49d556ffd6bc27142a7784c3bb8e37999857d) ) + + ROM_REGION( 0x080000, "wavetable", 0 ) /* QDSP wavetable rom */ + ROM_LOAD( "qs1001a.u17", 0x000000, 0x80000, CRC(d13c6407) SHA1(57b14f97c7d4f9b5d9745d3571a0b7115fbe3176) ) +ROM_END + +ROM_START( hapytour ) /* Same hardware: GHOST Ver1.1 2003.03.28 */ + ROM_REGION( 0x2000000, "user1", 0 ) /* ARM 32 bit code */ + ROM_LOAD( "flash.u1", 0x000000, 0x2000000, BAD_DUMP CRC(49deb7f9) SHA1(708a27d7177cf6261a49ded975c2bbb6c2427742) ) // missing ECC data + + // banked every 0x10000 bytes ? + ROM_REGION( 0x080000, "user2", 0 ) + ROM_LOAD( "ht.u20", 0x000000, 0x080000, CRC(c0581fce) SHA1(dafce679002534ffabed249a92e6b83301b8312b) ) + + ROM_REGION( 0x100000, "sfx", 0 ) /* QDSP samples (SFX) */ + ROM_LOAD( "ht.u16", 0x000000, 0x100000, CRC(6a590a3a) SHA1(c1140f70c919661162334db66c6aa0ad656bfc47) ) + + ROM_REGION( 0x080000, "wavetable", 0 ) /* QDSP wavetable rom */ + ROM_LOAD( "qs1001a.u17", 0x000000, 0x80000, CRC(d13c6407) SHA1(57b14f97c7d4f9b5d9745d3571a0b7115fbe3176) ) +ROM_END + +static DRIVER_INIT( bballoon ) +{ + ghosteo_state *state = machine.driver_data<ghosteo_state>(); + memcpy( state->m_steppingstone, machine.region( "user1")->base(), 4 * 1024); +} + +GAME( 2003, bballoon, 0, bballoon, bballoon, bballoon, ROT0, "Eolith", "BnB Arcade", GAME_NO_SOUND ) +GAME( 2005, hapytour, 0, bballoon, bballoon, bballoon, ROT0, "GAV Company", "Happy Tour", GAME_NO_SOUND ) |