/*
Gals Panic 3
(c) Kaneko 1995
Driver by David Haywood
Original Skeleton driver by David Haywood
Early Progress by Sebastien Volpe
Check done by main code, as part of EEPROM data:
'Gals Panic 3 v0.96 95/08/29(Tue)'
Sprites are from Supernova
Backgrounds are 3x bitmap layers + some kind of priority / mask layer
The bitmaps have blitter devices to decompress RLE rom data into them
*/
/*
Gals Panic 3 (JPN Ver.)
(c)1995 Kaneko
CPU: 68000-16
Sound: YMZ280B-F
OSC: 28.6363MHz
33.3333MHz
EEPROM: 93C46
Chips.: GRAP2 x3 <- R/G/B Chips?
APRIO-GL
BABY004
GCNT2
TBSOP01 <- ToyBox NEC uPD78324 series MCU with 32K internal rom
CG24173 6186 <- Sprites, see suprnova.c
CG24143 4181 <- ^
G3P0J1.71 prg.
G3P1J1.102
GP340000.123 chr.
GP340100.122
GP340200.121
GP340300.120
G3G0J0.101
G3G1J0.100
G3D0X0.134
GP320000.1 OBJ chr.
GP310000.41 sound data
GP310100.40
--- Team Japump!!! ---
Dumped by Uki
10/22/2000
*/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "deprecat.h"
#include "sound/ymz280b.h"
#include "includes/kaneko16.h"
#include "video/sknsspr.h"
class galpani3_state : public kaneko16_state
{
public:
galpani3_state(const machine_config &mconfig, device_type type, const char *tag)
: kaneko16_state(mconfig, type, tag) { }
UINT16* m_priority_buffer;
UINT16* m_framebuffer1;
UINT16* m_framebuffer2;
UINT16* m_framebuffer3;
UINT16* m_framebuffer1_palette;
UINT16* m_framebuffer2_palette;
UINT16* m_framebuffer3_palette;
UINT16 m_framebuffer3_scrolly;
UINT16 m_framebuffer3_scrollx;
UINT16 m_framebuffer2_scrolly;
UINT16 m_framebuffer2_scrollx;
UINT16 m_framebuffer1_scrolly;
UINT16 m_framebuffer1_scrollx;
UINT16 m_priority_buffer_scrollx;
UINT16 m_priority_buffer_scrolly;
UINT16 m_framebuffer1_enable;
UINT16 m_framebuffer2_enable;
UINT16 m_framebuffer3_enable;
UINT16* m_framebuffer1_bgcol;
UINT16* m_framebuffer2_bgcol;
UINT16* m_framebuffer3_bgcol;
UINT16* m_framebuffer3_bright1;
UINT16* m_framebuffer3_bright2;
UINT16* m_framebuffer2_bright1;
UINT16* m_framebuffer2_bright2;
UINT16* m_framebuffer1_bright1;
UINT16* m_framebuffer1_bright2;
UINT16 *m_sprregs;
UINT16 *m_spriteram;
UINT32 *m_spriteram32;
UINT32 *m_spc_regs;
bitmap_t *m_sprite_bitmap_1;
UINT16 *m_mcu_ram;
UINT16 m_mcu_com[4];
int m_regs1_i;
int m_regs2_i;
int m_regs3_i;
UINT16 m_regs1_address_regs[0x20];
UINT16 m_regs2_address_regs[0x20];
UINT16 m_regs3_address_regs[0x20];
sknsspr_device* m_spritegen;
};
/***************************************************************************
video
***************************************************************************/
static INTERRUPT_GEN( galpani3_vblank ) // 2, 3, 5 ?
{
switch ( cpu_getiloops(device) )
{
case 2: device_set_input_line(device, 2, HOLD_LINE); break;
case 1: device_set_input_line(device, 3, HOLD_LINE); break;
case 0: device_set_input_line(device, 5, HOLD_LINE); break; // sound?
}
}
static VIDEO_START(galpani3)
{
galpani3_state *state = machine.driver_data<galpani3_state>();
/* so we can use suprnova.c */
state->m_spriteram32 = auto_alloc_array(machine, UINT32, 0x4000/4);
machine.generic.spriteram_size = 0x4000;
state->m_spc_regs = auto_alloc_array(machine, UINT32, 0x40/4);
state->m_sprite_bitmap_1 = auto_bitmap_alloc(machine,1024,1024,BITMAP_FORMAT_INDEXED16);
state->m_spritegen = machine.device<sknsspr_device>("spritegen");
state->m_spritegen->skns_sprite_kludge(0,0);
}
static int gp3_is_alpha_pen(running_machine &machine, int pen)
{
galpani3_state *state = machine.driver_data<galpani3_state>();
UINT16 dat = 0;
if (pen<0x4000)
{
dat = machine.generic.paletteram.u16[pen];
}
else if (pen<0x4100)
{
dat = state->m_framebuffer1_palette[pen&0xff];
}
else if (pen<0x4200)
{
dat = state->m_framebuffer2_palette[pen&0xff];
}
else if (pen<0x4300)
{
dat = state->m_framebuffer3_palette[pen&0xff];
}
else if (pen<0x4301)
{
dat = state->m_framebuffer1_bgcol[0];
}
else if (pen<0x4302)
{
dat = state->m_framebuffer2_bgcol[0];
}
else if (pen<0x4303)
{
dat = state->m_framebuffer3_bgcol[0];
}
if (dat&0x8000) return 1;
else return 0;
}
static SCREEN_UPDATE(galpani3)
{
galpani3_state *state = screen->machine().driver_data<galpani3_state>();
int x,y;
UINT16* src1;
UINT32* dst;
UINT16 pixdata1;
const pen_t *paldata = screen->machine().pens;
bitmap_fill(bitmap, cliprect, 0x0000);
{
int drawy, drawx;
for (drawy=0;drawy<512;drawy++)
{
int srcline1 = (drawy+state->m_framebuffer1_scrolly+11)&0x1ff;
int srcline2 = (drawy+state->m_framebuffer2_scrolly+11)&0x1ff;
int srcline3 = (drawy+state->m_framebuffer3_scrolly+11)&0x1ff;
int priline = (drawy+state->m_priority_buffer_scrolly+11)&0x1ff;
for (drawx=0;drawx<512;drawx++)
{
int srcoffs1 = (drawx+state->m_framebuffer1_scrollx+67)&0x1ff;
int srcoffs2 = (drawx+state->m_framebuffer2_scrollx+67)&0x1ff;
int srcoffs3 = (drawx+state->m_framebuffer3_scrollx+67)&0x1ff;
int prioffs = (drawx+state->m_priority_buffer_scrollx+66)&0x1ff;
UINT8 dat1 = state->m_framebuffer1[(srcline1*0x200)+srcoffs1];
UINT8 dat2 = state->m_framebuffer2[(srcline2*0x200)+srcoffs2];
UINT8 dat3 = state->m_framebuffer3[(srcline3*0x200)+srcoffs3];
UINT8 pridat = state->m_priority_buffer[(priline*0x200)+prioffs];
UINT32* dst = BITMAP_ADDR32(bitmap, drawy, drawx);
// this is all wrong
if (pridat==0x0f) // relates to the area you've drawn over
{
if (dat1 && state->m_framebuffer1_enable)
{
dst[0] = paldata[dat1+0x4000];
}
if (dat2 && state->m_framebuffer2_enable)
{
dst[0] = paldata[dat2+0x4100];
}
}
else if (pridat==0xcf) // the girl
{
dst[0] = paldata[0x4300];
}
else
{
/* this isn't right, but the registers have something to do with
alpha / mixing, and bit 0x8000 of the palette is DEFINITELY alpha
enable -- see fading in intro */
if (dat1 && state->m_framebuffer1_enable)
{
UINT16 pen = dat1+0x4000;
UINT32 pal = paldata[pen];
if (gp3_is_alpha_pen(screen->machine(), pen))
{
int r,g,b;
r = (pal & 0x00ff0000)>>16;
g = (pal & 0x0000ff00)>>8;
b = (pal & 0x000000ff)>>0;
r = (r * state->m_framebuffer1_bright2[0]) / 0xff;
g = (g * state->m_framebuffer1_bright2[0]) / 0xff;
b = (b * state->m_framebuffer1_bright2[0]) / 0xff;
pal = (r & 0x000000ff)<<16;
pal |=(g & 0x000000ff)<<8;
pal |=(b & 0x000000ff)<<0;
dst[0] = pal;
}
else
{
dst[0] = pal;
}
}
if (dat2 && state->m_framebuffer2_enable)
{
UINT16 pen = dat2+0x4100;
UINT32 pal = paldata[pen];
if (gp3_is_alpha_pen(screen->machine(), pen))
{
int r,g,b;
r = (pal & 0x00ff0000)>>16;
g = (pal & 0x0000ff00)>>8;
b = (pal & 0x000000ff)>>0;
r = (r * state->m_framebuffer2_bright2[0]) / 0xff;
g = (g * state->m_framebuffer2_bright2[0]) / 0xff;
b = (b * state->m_framebuffer2_bright2[0]) / 0xff;
pal = (r & 0x000000ff)<<16;
pal |=(g & 0x000000ff)<<8;
pal |=(b & 0x000000ff)<<0;
dst[0] |= pal;
}
else
{
dst[0] = pal;
}
}
if (dat3 && state->m_framebuffer3_enable)
{
dst[0] = paldata[dat3+0x4200];
}
}
/*
else if (pridat==0x2f) // area outside of the girl
{
//dst[0] = screen->machine().rand()&0x3fff;
}
else if (pridat==0x00) // the initial line / box that gets drawn
{
//dst[0] = screen->machine().rand()&0x3fff;
}
else if (pridat==0x30) // during the 'gals boxes' on the intro
{
//dst[0] = screen->machine().rand()&0x3fff;
}
else if (pridat==0x0c) // 'nice' at end of level
{
//dst[0] = screen->machine().rand()&0x3fff;
}
else
{
//printf("%02x, ",pridat);
}
*/
}
}
}
bitmap_fill(state->m_sprite_bitmap_1, cliprect, 0x0000);
state->m_spritegen->skns_draw_sprites(screen->machine(), state->m_sprite_bitmap_1, cliprect, state->m_spriteram32, screen->machine().generic.spriteram_size, screen->machine().region("gfx1")->base(), screen->machine().region ("gfx1")->bytes(), state->m_spc_regs );
// ignoring priority bits for now..
for (y=0;y<240;y++)
{
src1 = BITMAP_ADDR16(state->m_sprite_bitmap_1, y, 0);
dst = BITMAP_ADDR32(bitmap, y, 0);
for (x=0;x<320;x++)
{
pixdata1 = src1[x];
if (pixdata1 & 0x3fff)
{
dst[x] = paldata[(pixdata1 & 0x3fff)];
}
}
}
return 0;
}
static INPUT_PORTS_START( galpani3 )
PORT_START("P1")
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN ) // ?
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("P2")
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN ) // ?
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("COIN")
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2)
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(2)
PORT_SERVICE_NO_TOGGLE( 0x1000, IP_ACTIVE_LOW )
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_TILT )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("DSW") /* provided by the MCU - $200386.b <- $400200 */
PORT_DIPNAME( 0x0100, 0x0100, "Test Mode" )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Flip_Screen ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) // ?
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) // unused
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) // unused
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) // unused
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) // unused
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) // unused ?
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
static WRITE16_HANDLER( galpani3_suprnova_sprite32_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_spriteram[offset]);
offset>>=1;
state->m_spriteram32[offset]=(state->m_spriteram[offset*2+1]<<16) | (state->m_spriteram[offset*2]);
}
static WRITE16_HANDLER( galpani3_suprnova_sprite32regs_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_sprregs[offset]);
offset>>=1;
state->m_spc_regs[offset]=(state->m_sprregs[offset*2+1]<<16) | (state->m_sprregs[offset*2]);
}
/***************************************************************************
MCU Code Simulation
(follows the implementation of kaneko16.c)
***************************************************************************/
static void galpani3_mcu_run(running_machine &machine)
{
galpani3_state *state = machine.driver_data<galpani3_state>();
UINT16 mcu_command = state->m_mcu_ram[0x0010/2]; /* command nb */
UINT16 mcu_offset = state->m_mcu_ram[0x0012/2] / 2; /* offset in shared RAM where MCU will write */
UINT16 mcu_subcmd = state->m_mcu_ram[0x0014/2]; /* sub-command parameter, happens only for command #4 */
logerror("%s: MCU executed command : %04X %04X\n",machine.describe_context(),mcu_command,mcu_offset*2);
/* the only MCU commands found in program code are:
0x04: protection: provide code/data,
0x03: read DSW
0x02: load NVRAM settings \ ATMEL AT93C46 chip,
0x42: save NVRAM settings / 128 bytes serial EEPROM
*/
switch (mcu_command >> 8)
{
case 0x03: // DSW
{
state->m_mcu_ram[mcu_offset] = input_port_read(machine, "DSW");
logerror("%s : MCU executed command: %04X %04X (read DSW)\n", machine.describe_context(), mcu_command, mcu_offset*2);
}
break;
case 0x02: // $38950 - load NVRAM settings
{
/* NOTE: code @ $38B46 & $38ab8 does exactly what is checked after MCU command
so that's what we'll mimic here... probably the initial NVRAM settings */
int i;
/* MCU writes 128 bytes to shared ram: last byte is the byte-sum */
/* first 32 bytes (header): 0x8BE08E71.L, then the string "95/06/30 Gals Panic3Ver 0.95"; */
state->m_mcu_ram[mcu_offset + 0] = 0x8BE0; state->m_mcu_ram[mcu_offset + 1] = 0x8E71;
state->m_mcu_ram[mcu_offset + 2] = 0x3935; state->m_mcu_ram[mcu_offset + 3] = 0x2F30;
state->m_mcu_ram[mcu_offset + 4] = 0x362F; state->m_mcu_ram[mcu_offset + 5] = 0x3330;
state->m_mcu_ram[mcu_offset + 6] = 0x2047; state->m_mcu_ram[mcu_offset + 7] = 0x616C;
state->m_mcu_ram[mcu_offset + 8] = 0x7320; state->m_mcu_ram[mcu_offset + 9] = 0x5061;
state->m_mcu_ram[mcu_offset + 10] = 0x6E69; state->m_mcu_ram[mcu_offset + 11] = 0x6333;
state->m_mcu_ram[mcu_offset + 12] = 0x5665; state->m_mcu_ram[mcu_offset + 13] = 0x7220;
state->m_mcu_ram[mcu_offset + 14] = 0x302E; state->m_mcu_ram[mcu_offset + 15] = 0x3935;
/* next 11 bytes - initial NVRAM settings */
state->m_mcu_ram[mcu_offset + 16] = 0x0001; state->m_mcu_ram[mcu_offset + 17] = 0x0101;
state->m_mcu_ram[mcu_offset + 18] = 0x0100; state->m_mcu_ram[mcu_offset + 19] = 0x0208;
state->m_mcu_ram[mcu_offset + 20] = 0x02FF; state->m_mcu_ram[mcu_offset + 21] = 0x0000;
/* rest is zeroes */
for (i=22;i<63;i++)
state->m_mcu_ram[mcu_offset + i] = 0;
/* and sum is $0c.b */
state->m_mcu_ram[mcu_offset + 63] = 0x000c;
}
break;
case 0x04: // $38842 - provides code/data
{
toxboy_handle_04_subcommand(machine, mcu_subcmd, state->m_mcu_ram);
}
break;
case 0x42: // $389ee - save NVRAM settings
{
// found, TODO: trace call in code !!!
}
break;
default:
logerror("UNKNOWN COMMAND\n");
}
}
/*
MCU doesn't execute exactly as it is coded right know (ala jchan):
* com0=com1=0xFFFF -> command to execute
* com2=com3=0xFFFF -> status reading only
*/
INLINE void galpani3_mcu_com_w(address_space *space, offs_t offset, UINT16 data, UINT16 mem_mask, int _n_)
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_mcu_com[_n_]);
if (state->m_mcu_com[0] != 0xFFFF) return;
if (state->m_mcu_com[1] != 0xFFFF) return;
if (state->m_mcu_com[2] != 0xFFFF) return;
if (state->m_mcu_com[3] != 0xFFFF) return;
memset(state->m_mcu_com, 0, 4 * sizeof( UINT16 ) );
galpani3_mcu_run(space->machine());
}
static WRITE16_HANDLER( galpani3_mcu_com0_w ) { galpani3_mcu_com_w(space, offset, data, mem_mask, 0); }
static WRITE16_HANDLER( galpani3_mcu_com1_w ) { galpani3_mcu_com_w(space, offset, data, mem_mask, 1); }
static WRITE16_HANDLER( galpani3_mcu_com2_w ) { galpani3_mcu_com_w(space, offset, data, mem_mask, 2); }
static WRITE16_HANDLER( galpani3_mcu_com3_w ) { galpani3_mcu_com_w(space, offset, data, mem_mask, 3); }
static READ16_HANDLER( galpani3_mcu_status_r )
{
logerror("cpu '%s' (PC=%06X): read mcu status\n", space->device().tag(), cpu_get_previouspc(&space->device()));
return 0;
}
// might be blitter regs? - there are 3, probably GRAP2 chips
static READ16_HANDLER( galpani3_regs1_r )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
switch (offset)
{
case 0x2:
return state->m_framebuffer1_enable;
case 0xb:
{
state->m_regs1_i^=1;
if (state->m_regs1_i) return 0xfffe;
else return 0xffff;
}
default:
logerror("cpu '%s' (PC=%06X): galpani3_regs1_r %02x %04x\n", space->device().tag(), cpu_get_previouspc(&space->device()), offset, mem_mask);
break;
}
return 0x0000;
}
static READ16_HANDLER( galpani3_regs2_r )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
switch (offset)
{
case 0x2:
return state->m_framebuffer2_enable;
case 0xb:
{
state->m_regs2_i^=1;
if (state->m_regs2_i) return 0xfffe;
else return 0xffff;
}
default:
logerror("cpu '%s' (PC=%06X): galpani3_regs2_r %02x %04x\n", space->device().tag(), cpu_get_previouspc(&space->device()), offset, mem_mask);
break;
}
return 0x0000;
}
static READ16_HANDLER( galpani3_regs3_r )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
switch (offset)
{
case 0x2:
return state->m_framebuffer3_enable;
case 0xb:
{
state->m_regs3_i^=1;
if (state->m_regs3_i) return 0xfffe;
else return 0xffff;
}
default:
logerror("cpu '%s' (PC=%06X): galpani3_regs3_r %02x %04x\n", space->device().tag(), cpu_get_previouspc(&space->device()), offset, mem_mask);
break;
}
return 0x0000;
}
static void gp3_do_rle(UINT32 address, UINT16*framebuffer, UINT8* rledata)
{
int rle_count = 0;
int normal_count = 0;
UINT32 dstaddress = 0;
UINT8 thebyte;
while (dstaddress<0x40000)
{
if (rle_count==0 && normal_count==0) // we need a new code byte
{
thebyte = rledata[address];
if ((thebyte & 0x80)) // stream of normal bytes follows
{
normal_count = (thebyte & 0x7f)+1;
address++;
}
else // rle block
{
rle_count = (thebyte & 0x7f)+1;
address++;
}
}
else if (rle_count)
{
thebyte = rledata[address];
framebuffer[dstaddress] = thebyte;
dstaddress++;
rle_count--;
if (rle_count==0)
{
address++;
}
}
else if (normal_count)
{
thebyte = rledata[address];
framebuffer[dstaddress] = thebyte;
dstaddress++;
normal_count--;
address++;
}
}
}
static WRITE16_HANDLER( galpani3_regs1_address_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
logerror("galpani3_regs1_address_w %04x\n",data);
COMBINE_DATA(&state->m_regs1_address_regs[offset]);
}
static WRITE16_HANDLER( galpani3_regs1_go_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
UINT32 address = state->m_regs1_address_regs[1]| (state->m_regs1_address_regs[0]<<16);
UINT8* rledata = space->machine().region("gfx2")->base();
printf("galpani3_regs1_go_w? %08x\n",address );
if ((data==0x2000) || (data==0x3000)) gp3_do_rle(address, state->m_framebuffer1, rledata);
}
static WRITE16_HANDLER( galpani3_regs2_address_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
logerror("galpani3_regs2_address_w %04x\n",data);
COMBINE_DATA(&state->m_regs2_address_regs[offset]);
}
static WRITE16_HANDLER( galpani3_regs2_go_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
UINT32 address = state->m_regs2_address_regs[1]| (state->m_regs2_address_regs[0]<<16);
UINT8* rledata = space->machine().region("gfx2")->base();
printf("galpani3_regs2_go_w? %08x\n", address );
// hack to prevent title screen being corrupt - these might actually be size registers
// for the RLE request
if ((data==0x2000) || (data==0x3000)) gp3_do_rle(address, state->m_framebuffer2, rledata);
}
static WRITE16_HANDLER( galpani3_regs3_address_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
logerror("galpani3_regs3_address_w %04x\n",data);
COMBINE_DATA(&state->m_regs3_address_regs[offset]);
}
static WRITE16_HANDLER( galpani3_regs3_go_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
UINT32 address = state->m_regs3_address_regs[1]| (state->m_regs3_address_regs[0]<<16);
UINT8* rledata = space->machine().region("gfx2")->base();
printf("galpani3_regs3_go_w? %08x\n",address );
if ((data==0x2000) || (data==0x3000)) gp3_do_rle(address, state->m_framebuffer3, rledata);
}
static void set_color_555_gp3(running_machine &machine, pen_t color, int rshift, int gshift, int bshift, UINT16 data)
{
palette_set_color_rgb(machine, color, pal5bit(data >> rshift), pal5bit(data >> gshift), pal5bit(data >> bshift));
}
static WRITE16_HANDLER( galpani3_framebuffer1_palette_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer1_palette[offset]);
set_color_555_gp3(space->machine(), offset+0x4000, 5, 10, 0, state->m_framebuffer1_palette[offset]);
}
static WRITE16_HANDLER( galpani3_framebuffer2_palette_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer2_palette[offset]);
set_color_555_gp3(space->machine(), offset+0x4100, 5, 10, 0, state->m_framebuffer2_palette[offset]);
}
static WRITE16_HANDLER( galpani3_framebuffer3_palette_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer3_palette[offset]);
set_color_555_gp3(space->machine(), offset+0x4200, 5, 10, 0, state->m_framebuffer3_palette[offset]);
}
static WRITE16_HANDLER( galpani3_framebuffer3_scrolly_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer3_scrolly = data;
}
static WRITE16_HANDLER( galpani3_framebuffer3_scrollx_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer3_scrollx = data;
}
static WRITE16_HANDLER( galpani3_framebuffer2_scrolly_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer2_scrolly = data;
}
static WRITE16_HANDLER( galpani3_framebuffer2_scrollx_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer2_scrollx = data;
}
static WRITE16_HANDLER( galpani3_framebuffer1_scrolly_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer1_scrolly = data;
}
static WRITE16_HANDLER( galpani3_framebuffer1_scrollx_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer1_scrollx = data;
}
static WRITE16_HANDLER( galpani3_priority_buffer_scrollx_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_priority_buffer_scrollx = data;
}
static WRITE16_HANDLER( galpani3_priority_buffer_scrolly_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_priority_buffer_scrolly = data;
}
/* I'm not convinced these are enables */
static WRITE16_HANDLER( galpani3_framebuffer1_enable_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer1_enable = data;
}
static WRITE16_HANDLER( galpani3_framebuffer2_enable_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer2_enable = data;
}
static WRITE16_HANDLER( galpani3_framebuffer3_enable_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
state->m_framebuffer3_enable = data;
}
/* definitely looks like a cycling bg colour used for the girls */
static WRITE16_HANDLER( galpani3_framebuffer1_bgcol_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer1_bgcol[offset]);
set_color_555_gp3(space->machine(), offset+0x4300, 5, 10, 0, state->m_framebuffer1_bgcol[offset]);
}
static WRITE16_HANDLER( galpani3_framebuffer2_bgcol_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer2_bgcol[offset]);
set_color_555_gp3(space->machine(), offset+0x4301, 5, 10, 0, state->m_framebuffer2_bgcol[offset]);
}
static WRITE16_HANDLER( galpani3_framebuffer3_bgcol_w )
{
galpani3_state *state = space->machine().driver_data<galpani3_state>();
COMBINE_DATA(&state->m_framebuffer3_bgcol[offset]);
set_color_555_gp3(space->machine(), offset+0x4302, 5, 10, 0, state->m_framebuffer3_bgcol[offset]);
}
static ADDRESS_MAP_START( galpani3_map, AS_PROGRAM, 16 )
AM_RANGE(0x000000, 0x17ffff) AM_ROM
AM_RANGE(0x200000, 0x20ffff) AM_RAM // area [B] - Work RAM
AM_RANGE(0x280000, 0x287fff) AM_RAM_WRITE(paletteram16_xGGGGGRRRRRBBBBB_word_w) AM_BASE_GENERIC(paletteram) // area [A] - palette for sprites
AM_RANGE(0x300000, 0x303fff) AM_RAM_WRITE(galpani3_suprnova_sprite32_w) AM_BASE_MEMBER(galpani3_state, m_spriteram)
AM_RANGE(0x380000, 0x38003f) AM_RAM_WRITE(galpani3_suprnova_sprite32regs_w) AM_BASE_MEMBER(galpani3_state, m_sprregs)
AM_RANGE(0x400000, 0x40ffff) AM_RAM AM_BASE_MEMBER(galpani3_state, m_mcu_ram) // area [C]
AM_RANGE(0x580000, 0x580001) AM_WRITE(galpani3_mcu_com0_w) // ] see $387e8: these 2 locations are written (w.#$ffff)
AM_RANGE(0x600000, 0x600001) AM_WRITE(galpani3_mcu_com1_w) // ] then bit #0 of $780000.l is tested: 0 = OK!
AM_RANGE(0x680000, 0x680001) AM_WRITE(galpani3_mcu_com2_w) // ] see $387e8: these 2 locations are written (w.#$ffff)
AM_RANGE(0x700000, 0x700001) AM_WRITE(galpani3_mcu_com3_w) // ] then bit #0 of $780000.l is tested: 0 = OK!
AM_RANGE(0x780000, 0x780001) AM_READ(galpani3_mcu_status_r)
// GRAP2 1?
AM_RANGE(0x800000, 0x8003ff) AM_RAM // ??? see subroutine $39f42 (R?)
AM_RANGE(0x800400, 0x800401) AM_WRITE(galpani3_framebuffer1_scrollx_w) // scroll?
AM_RANGE(0x800800, 0x800bff) AM_RAM // ??? see subroutine $39f42 (R?)
AM_RANGE(0x800c00, 0x800c01) AM_WRITE(galpani3_framebuffer1_scrolly_w) // scroll?
AM_RANGE(0x800c02, 0x800c03) AM_WRITE(galpani3_framebuffer1_enable_w) // enable?
AM_RANGE(0x800c06, 0x800c07) AM_WRITE(galpani3_framebuffer1_bgcol_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer1_bgcol) // bg colour? cycles ingame, for girls?
AM_RANGE(0x800c10, 0x800c11) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer1_bright1) // brightness / blend amount?
AM_RANGE(0x800c12, 0x800c13) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer1_bright2) // similar.
AM_RANGE(0x800c18, 0x800c1b) AM_WRITE(galpani3_regs1_address_w) // ROM address of RLE data, in bytes
AM_RANGE(0x800c1e, 0x800c1f) AM_WRITE(galpani3_regs1_go_w) // ?
AM_RANGE(0x800c00, 0x800c1f) AM_READ(galpani3_regs1_r)// ? R layer regs ? see subroutine $3a03e
AM_RANGE(0x880000, 0x8801ff) AM_RAM_WRITE(galpani3_framebuffer1_palette_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer1_palette) // palette
AM_RANGE(0x900000, 0x97ffff) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer1)// area [D] - R area ? odd bytes only, initialized 00..ff,00..ff,...
// GRAP2 2?
AM_RANGE(0xa00000, 0xa003ff) AM_RAM // ??? see subroutine $39f42 (G?)
AM_RANGE(0xa00400, 0xa00401) AM_WRITE(galpani3_framebuffer2_scrollx_w)
AM_RANGE(0xa00800, 0xa00bff) AM_RAM // ??? see subroutine $39f42 (G?)
AM_RANGE(0xa00c00, 0xa00c01) AM_WRITE(galpani3_framebuffer2_scrolly_w)
AM_RANGE(0xa00c02, 0xa00c03) AM_WRITE(galpani3_framebuffer2_enable_w) // enable?
AM_RANGE(0xa00c06, 0xa00c07) AM_WRITE(galpani3_framebuffer2_bgcol_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer2_bgcol) // bg colour? same values as previous layer
AM_RANGE(0xa00c10, 0xa00c11) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer2_bright1) // similar..
AM_RANGE(0xa00c12, 0xa00c13) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer2_bright2) // brightness / blend amount?
AM_RANGE(0xa00c00, 0xa00c1f) AM_READ(galpani3_regs2_r) // ? G layer regs ? see subroutine $3a03e
AM_RANGE(0xa00c18, 0xa00c1b) AM_WRITE(galpani3_regs2_address_w) // ROM address of RLE data, in bytes
AM_RANGE(0xa00c1e, 0xa00c1f) AM_WRITE(galpani3_regs2_go_w) // ?
AM_RANGE(0xa80000, 0xa801ff) AM_RAM_WRITE(galpani3_framebuffer2_palette_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer2_palette) // palette
AM_RANGE(0xb00000, 0xb7ffff) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer2) // area [E] - G area ? odd bytes only, initialized 00..ff,00..ff,...
// GRAP2 3?
AM_RANGE(0xc00000, 0xc003ff) AM_RAM // row scroll??
AM_RANGE(0xc00400, 0xc00401) AM_WRITE(galpani3_framebuffer3_scrollx_w) // scroll?
AM_RANGE(0xc00800, 0xc00bff) AM_RAM // column scroll??
AM_RANGE(0xc00c00, 0xc00c01) AM_WRITE(galpani3_framebuffer3_scrolly_w) // scroll?
AM_RANGE(0xc00c02, 0xc00c03) AM_WRITE(galpani3_framebuffer3_enable_w) // enable?
AM_RANGE(0xc00c06, 0xc00c07) AM_WRITE(galpani3_framebuffer3_bgcol_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer3_bgcol) // bg colour? not used?
AM_RANGE(0xc00c10, 0xc00c11) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer3_bright1) // brightness / blend amount?
AM_RANGE(0xc00c12, 0xc00c13) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer3_bright2) // similar..
AM_RANGE(0xc00c18, 0xc00c1b) AM_WRITE(galpani3_regs3_address_w) // ROM address of RLE data, in bytes
AM_RANGE(0xc00c1e, 0xc00c1f) AM_WRITE(galpani3_regs3_go_w) // ?
AM_RANGE(0xc00c00, 0xc00c1f) AM_READ(galpani3_regs3_r) // ? B layer regs ? see subroutine $3a03e
AM_RANGE(0xc80000, 0xc801ff) AM_RAM_WRITE(galpani3_framebuffer3_palette_w) AM_BASE_MEMBER(galpani3_state, m_framebuffer3_palette) // palette
AM_RANGE(0xd00000, 0xd7ffff) AM_RAM AM_BASE_MEMBER(galpani3_state, m_framebuffer3) // area [F] - B area ? odd bytes only, initialized 00..ff,00..ff,...
// ?? priority / alpha buffer?
AM_RANGE(0xe00000, 0xe7ffff) AM_RAM AM_BASE_MEMBER(galpani3_state, m_priority_buffer) // area [J] - A area ? odd bytes only, initialized 00..ff,00..ff,..., then cleared
AM_RANGE(0xe80000, 0xe80001) AM_WRITE(galpani3_priority_buffer_scrollx_w) // scroll?
AM_RANGE(0xe80002, 0xe80003) AM_WRITE(galpani3_priority_buffer_scrolly_w) // scroll?
AM_RANGE(0xf00000, 0xf00001) AM_NOP // ? written once (2nd opcode, $1.b)
AM_RANGE(0xf00010, 0xf00011) AM_READ_PORT("P1")
AM_RANGE(0xf00012, 0xf00013) AM_READ_PORT("P2")
AM_RANGE(0xf00014, 0xf00015) AM_READ_PORT("COIN")
AM_RANGE(0xf00016, 0xf00017) AM_NOP // ? read, but overwritten
AM_RANGE(0xf00020, 0xf00023) AM_DEVWRITE8("ymz", ymz280b_w, 0x00ff) // sound
AM_RANGE(0xf00040, 0xf00041) AM_READWRITE(watchdog_reset16_r, watchdog_reset16_w) // watchdog
AM_RANGE(0xf00050, 0xf00051) AM_NOP // ? written once (3rd opcode, $30.b)
ADDRESS_MAP_END
static const ymz280b_interface ymz280b_intf =
{
0 // irq ?
};
static MACHINE_CONFIG_START( galpani3, galpani3_state )
MCFG_CPU_ADD("maincpu", M68000, 16000000) // ? (from which clock?)
MCFG_CPU_PROGRAM_MAP(galpani3_map)
MCFG_CPU_VBLANK_INT_HACK(galpani3_vblank, 3)
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_SIZE(64*8, 64*8)
MCFG_SCREEN_VISIBLE_AREA(0*8, 40*8-1, 0*8, 30*8-1)
//MCFG_SCREEN_VISIBLE_AREA(0*8, 64*8-1, 0*8, 64*8-1)
MCFG_SCREEN_UPDATE(galpani3)
MCFG_PALETTE_LENGTH(0x4303)
MCFG_VIDEO_START(galpani3)
MCFG_DEVICE_ADD("spritegen", SKNS_SPRITE, 0)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ymz", YMZ280B, 28636400 / 2)
MCFG_SOUND_CONFIG(ymz280b_intf)
MCFG_SOUND_ROUTE(0, "mono", 1.0)
MCFG_SOUND_ROUTE(1, "mono", 1.0)
MACHINE_CONFIG_END
ROM_START( galpani3 )
ROM_REGION( 0x180000, "maincpu", 0 ) /* 68000 Code */
ROM_LOAD16_BYTE( "g3p0j1.71", 0x000000, 0x080000, CRC(52893326) SHA1(78fdbf3436a4ba754d7608fedbbede5c719a4505) )
ROM_LOAD16_BYTE( "g3p1j1.102", 0x000001, 0x080000, CRC(05f935b4) SHA1(81e78875585bcdadad1c302614b2708e60563662) )
ROM_REGION( 0x200000, "gfx1", 0 ) /* Sprites - RLE encoded */
ROM_LOAD( "gp320000.1", 0x000000, 0x200000, CRC(a0112827) SHA1(0a6c78d71b75a1d78215aab3104176aa1769b14f) )
ROM_REGION( 0x1000000, "gfx2", 0 ) /* Backgrounds - RLE encoded */
ROM_LOAD( "gp340000.123", 0x000000, 0x200000, CRC(a58a26b1) SHA1(832d70cce1b4f04fa50fc221962ff6cc4287cb92) ) // 19950414GROMACap
ROM_LOAD( "gp340100.122", 0x200000, 0x200000, CRC(746fe4a8) SHA1(a5126ae9e83d556277d31b166296a708c311a902) ) // 19950414GROMBCap
ROM_LOAD( "gp340200.121", 0x400000, 0x200000, CRC(e9bc15c8) SHA1(2c6a10e768709d1937d9206970553f4101ce9016) ) // 19950414GROMCCap
ROM_LOAD( "gp340300.120", 0x600000, 0x200000, CRC(59062eef) SHA1(936977c20d83540c1e0f65d429c7ebea201ef991) ) // 19950414GROMDCap
ROM_LOAD16_BYTE( "g3g0j0.101", 0xe00000, 0x040000, CRC(fbb1e0dc) SHA1(14f6377afd93054aa5dc38af235ae12b932e847f) ) // 19950523GROMECap
ROM_LOAD16_BYTE( "g3g1j0.100", 0xe00001, 0x040000, CRC(18edb5f0) SHA1(5e2ed0105b3e6037f6116494d3b186a368824171) ) //
ROM_REGION( 0x300000, "ymz", 0 ) /* Samples */
ROM_LOAD( "gp310100.40", 0x000000, 0x200000, CRC(6a0b1d12) SHA1(11fed80b96d07fddb27599743991c58c12c048e0) )
ROM_LOAD( "gp310000.41", 0x200000, 0x100000, CRC(641062ef) SHA1(c8902fc46319eac94b3f95d18afa24bd895078d6) )
ROM_REGION( 0x20000, "mcudata", 0 ) /* MCU Code? */
ROM_LOAD16_WORD_SWAP( "g3d0x0.134", 0x000000, 0x020000, CRC(4ace10f9) SHA1(d19e4540d535ce10d23cb0844be03a3239b3402e) )
ROM_END
static DRIVER_INIT( galpani3 )
{
galpani3_state *state = machine.driver_data<galpani3_state>();
DRIVER_INIT_CALL( decrypt_toybox_rom );
memset(state->m_mcu_com, 0, 4 * sizeof( UINT16) );
}
GAME( 1995, galpani3, 0, galpani3, galpani3, galpani3, ROT90, "Kaneko", "Gals Panic 3", GAME_IMPERFECT_GRAPHICS )