/************************************************************************
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 "driver.h"
#include "cpu/arm7/arm7core.h"
static UINT32 *system_memory;
static UINT32 *flash_regs;
static UINT32 *lcd_control;
static UINT32 *io_port;
//static UINT32 fifoh[16];
//static UINT32 fifol[12];
static struct lcd_config
{
int screen_type;
int bpp_mode;
int lcd_bank;
int lcd_base_u;
int lcd_base_sel;
int line_val;
int hoz_val;
int off_size;
int page_width;
} lcd;
static READ32_HANDLER( r1 )
{
// int pc = activecpu_get_pc();
// if(pc != 0x9a0 && pc != 0x7b4) printf("r1 @ %X\n",pc);
return 1;
}
static READ32_HANDLER( r2 )
{
// int pc = activecpu_get_pc();
// if(pc != 0xd64 && pc != 0xd3c ) printf("r2 @ %X\n",pc);
return 2;
}
static UINT32 flash_addr = 0;
static int flash_addr_step = 0;
#define ADDR_STEP_CONFIG 4
static WRITE32_HANDLER( flash_reg_w )
{
static int old[3];
COMBINE_DATA(&flash_regs[offset]);
if(old[offset] != flash_regs[offset])
{
old[offset] = flash_regs[offset];
// printf("reg %d) %02X\n",offset,old[offset] = flash_regs[offset]);
// logerror("reg %d) %02X\n",offset,old[offset] = flash_regs[offset]);
}
switch(offset)
{
case 0:
break;
case 1:
break;
case 2:
switch(flash_addr_step)
{
case 0: flash_addr = data << 0; break;
case 1: flash_addr |= data << 8; break;
case 2: flash_addr |= data << 16; break;
case 3: flash_addr |= data << 24; break;
}
if(flash_addr_step == (ADDR_STEP_CONFIG - 1))
{
flash_addr <<=1;
}
flash_addr_step = (flash_addr_step + 1) % ADDR_STEP_CONFIG;
break;
}
}
static READ32_HANDLER( flash_reg_r )
{
// always read back what it's written?
return flash_regs[offset];
}
static READ32_HANDLER( flash_r )
{
UINT8 *flash = (UINT8 *)memory_region(REGION_USER1);
UINT8 value = flash[flash_addr];
flash_addr = (flash_addr + 1) % memory_region_length(REGION_USER1);
return value;
}
static READ32_HANDLER( flash_ecc_r )
{
//TODO
return 0;
}
static WRITE32_HANDLER( debug_w )
{
#if 1
mame_printf_debug("%c",data & 0xff); //debug texts
#endif
}
/*
a) cpu #0 (PC=000007D0): unmapped program memory dword read from 4E000014 & 000000FF
b) cpu #0 (PC=000007D8): unmapped program memory dword read from 4E000014 & 0000FF00
c) cpu #0 (PC=000007E0): unmapped program memory dword read from 4E000014 & 00FF0000
1) read flash @ 0812
2) read flash @ 0813
3) read flash @ 0814
4) read flash @ 0815
5) read flash @ 0816
6) read flash @ 0817
a == 1
b == 2
c == 3
6 == 0xff
*/
// PC: 574 check -> jumps to execute code from ram
/*
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 READ32_HANDLER( lcd_control_r )
{
switch(offset)
{
case 0x00/4:
{
int line_val = video_screen_get_vpos(0) & 0x3ff;
return (lcd_control[offset] & ~(0x3ff << 18)) | ((lcd.line_val - line_val) << 18);
}
case 0x10/4:
{
//TODO: VSTATUS, HSTATUS
static int VSTATUS = 0;
VSTATUS ^= 0x18000;
return (lcd_control[offset] & ~0x18000) | VSTATUS;
}
default:
{
return lcd_control[offset];
}
}
}
static WRITE32_HANDLER( lcd_control_w )
{
COMBINE_DATA(&lcd_control[offset]);
switch(offset)
{
case 0x00/4:
{
int line_val = video_screen_get_vpos(0) & 0x3ff;
int bpp_mode = (lcd_control[offset] & 0x1e) >> 1;
int screen_type = (lcd_control[offset] & 0x60) >> 5;
lcd.screen_type = screen_type;
lcd.bpp_mode = bpp_mode;
if(bpp_mode != 12)
printf("bpp mode= %d\n",bpp_mode);
lcd_control[offset] = (lcd_control[offset] & ~(0x3ff << 18)) | ((lcd.line_val - line_val) << 18);
break;
}
case 0x04/4:
{
int line_val = (lcd_control[offset] >> 14) & 0x3ff;
lcd.line_val = line_val;
break;
}
case 0x08/4:
{
int hoz_val = (lcd_control[offset] >> 8) & 0x3ff;
lcd.hoz_val = hoz_val;
break;
}
case 0x10/4:
{
/*
int frm565 = (lcd_control[offset] >> 11) & 1;
int inv_vd = (lcd_control[offset] >> 7) & 1;
int bs_swp = (lcd_control[offset] >> 1) & 1;
int hw_swp = (lcd_control[offset] >> 0) & 1;
*/
break;
}
case 0x14/4:
{
int lcd_bank = (lcd_control[offset] >> 21) & 0x1ff;
int lcd_base_u = (lcd_control[offset] >> 0) & 0x1fffff;
lcd.lcd_bank = lcd_bank;
lcd.lcd_base_u = lcd_base_u;
break;
}
case 0x18/4:
{
int lcd_base_sel = (lcd_control[offset] >> 0) & 0x1fffff;
lcd.lcd_base_sel = lcd_base_sel;
break;
}
case 0x1c/4:
{
int off_size = (lcd_control[offset] >> 11) & 0x7ff;
int page_width = (lcd_control[offset] >> 0) & 0x7ff;
lcd.off_size = off_size;
lcd.page_width = page_width;
break;
}
}
}
static READ32_HANDLER( io_port_r )
{
switch(offset)
{
case 0x64/4:
{
static int input = 0;
input ^= 0x20;
// bits from 15-0 can be configured as input/output/...
//return input;
return (io_port[offset] & ~0x20) | input;
}
default:
{
return io_port[offset];
}
}
}
static WRITE32_HANDLER( io_port_w )
{
COMBINE_DATA(&io_port[offset]);
}
static ADDRESS_MAP_START( bballoon_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x00000fff) AM_ROM AM_REGION(REGION_USER1, 0)
AM_RANGE(0x30000000, 0x31ffffff) AM_RAM AM_BASE(&system_memory)
AM_RANGE(0x40000000, 0x40000fff) AM_ROM AM_REGION(REGION_USER1, 0) // mirror? seems so
AM_RANGE(0x48000000, 0x48000033) AM_RAM // memory controller
AM_RANGE(0x4d000000, 0x4d00001f) AM_READWRITE(lcd_control_r,lcd_control_w) AM_BASE(&lcd_control)
AM_RANGE(0x4e000000, 0x4e00000b) AM_READWRITE(flash_reg_r, flash_reg_w) AM_BASE(&flash_regs)
AM_RANGE(0x4e00000c, 0x4e00000f) AM_READ(flash_r)
AM_RANGE(0x4e000010, 0x4e000013) AM_READ(r1)
AM_RANGE(0x4e000014, 0x4e000017) AM_READ(flash_ecc_r)
AM_RANGE(0x50000010, 0x50000013) AM_READ(r2)
AM_RANGE(0x50000020, 0x50000023) AM_WRITE(debug_w)
//AM_RANGE(0x51000040, 0x51000043) AM_READ() // a timer...
AM_RANGE(0x56000000, 0x56000093) AM_READWRITE(io_port_r, io_port_w) AM_BASE(&io_port)
ADDRESS_MAP_END
static INPUT_PORTS_START( bballoon )
INPUT_PORTS_END
static int irq_en = 0;
static VIDEO_START( bballoon )
{
}
static int b=0;
static VIDEO_UPDATE( bballoon )
{
if(input_code_pressed_once(KEYCODE_Q))
{
irq_en ^= 1;
printf("en = %d\n",irq_en);
}
if(input_code_pressed_once(KEYCODE_W))
{
printf("b = %d\n",++b);
}
if(input_code_pressed_once(KEYCODE_E))
{
printf("b = %d\n",--b);
}
if(lcd_control[0] & 1)
{
// output enabled
//bballoon setup
//TFT 16bpp
//5:6:5 format
//normal
//bs swap disabled
//hw swap enabled
int start_addr = (lcd.lcd_bank << 22) - 0x30000000;
if(start_addr > 0x1ffffff)
printf("max = %X\n",start_addr);
else
{
//printf("addr = %X\n",start_addr + lcd.lcd_base_u);
UINT32* videoram = system_memory + start_addr/4 + lcd.lcd_base_u/4 + 0x10000*b;
int x,y,count;
// probably wrong...
count = 0;
for (y=0;y <= cliprect->max_y;y++)
{
for (x=0;x <= cliprect->max_x/2;x+=2)
{
UINT32 color;
UINT32 b;
UINT32 g;
UINT32 r;
color = (videoram[count] >> 16) & 0xffff;
b = (color & 0x001f) << 3;
g = (color & 0x07e0) >> 2;
r = (color & 0xf800) >> 6;
*BITMAP_ADDR32(bitmap, y, x*2+0) = b | (g<<8) | (r<<16);
color = videoram[count] & 0xffff;
b = (color & 0x001f) << 3;
g = (color & 0x07e0) >> 2;
r = (color & 0xf800) >> 6;
*BITMAP_ADDR32(bitmap, y, x*2+1) = b | (g<<8) | (r<<16);
count++;
}
}
}
}
else
{
// output disabled
}
return 0;
}
static INTERRUPT_GEN( bballoon_interrupt )
{
if(irq_en)
cpunum_set_input_line(0, ARM7_IRQ_LINE, PULSE_LINE);
//cpunum_set_input_line(0, ARM7_FIRQ_LINE, PULSE_LINE);
irq_en = 0;
}
static MACHINE_DRIVER_START( bballoon )
/* basic machine hardware */
MDRV_CPU_ADD(ARM7, 24000000)
MDRV_CPU_PROGRAM_MAP(bballoon_map,0)
MDRV_CPU_VBLANK_INT(bballoon_interrupt,1)
MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION)
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
MDRV_SCREEN_SIZE(1024, 1024)
MDRV_SCREEN_VISIBLE_AREA(0, 319, 0, 239)
MDRV_PALETTE_LENGTH(256)
MDRV_VIDEO_START(bballoon)
MDRV_VIDEO_UPDATE(bballoon)
/* sound hardware */
MACHINE_DRIVER_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
*/
ROM_START( bballoon )
ROM_REGION( 0x2000000, REGION_USER1, 0 ) /* ARM 32 bit code */
ROM_LOAD( "flash.u1", 0x000000, 0x2000000, CRC(73285634) SHA1(4d0210c1bebdf3113a99978ffbcd77d6ee854168) )
// banked every 0x10000 bytes ?
ROM_REGION( 0x080000, REGION_USER2, 0 )
ROM_LOAD( "b2.u20", 0x000000, 0x080000, CRC(0a12334c) SHA1(535b5b34f28435517218100d70147d87809f485a) )
ROM_REGION( 0x100000, REGION_SOUND2, 0 ) // sound wave
ROM_LOAD( "b1.u16", 0x000000, 0x100000, CRC(c42c1c85) SHA1(e1f49d556ffd6bc27142a7784c3bb8e37999857d) )
ROM_END
static DRIVER_INIT( bballoon )
{
UINT8 *flash = (UINT8 *)memory_region(REGION_USER1);
// nop flash ECC checks
flash[0x844+0] = 0x00;
flash[0x844+1] = 0x00;
flash[0x844+2] = 0xA0;
flash[0x844+3] = 0xE1;
flash[0x850+0] = 0x00;
flash[0x850+1] = 0x00;
flash[0x850+2] = 0xA0;
flash[0x850+3] = 0xE1;
flash[0x860+0] = 0x00;
flash[0x860+1] = 0x00;
flash[0x860+2] = 0xA0;
flash[0x860+3] = 0xE1;
flash[0x86c+0] = 0x00;
flash[0x86c+1] = 0x00;
flash[0x86c+2] = 0xA0;
flash[0x86c+3] = 0xE1;
}
GAME( 2003, bballoon, 0, bballoon, bballoon, bballoon, ROT0, "Eolith", "Balloon & Balloon", GAME_NO_SOUND | GAME_NOT_WORKING )