From e424adb362864854a86d966d5765eef59b762a44 Mon Sep 17 00:00:00 2001 From: Zsolt Vasvari Date: Mon, 28 Jan 2008 06:06:27 +0000 Subject: [PATCH] - Driver clean-up, including driver state - Tried improving on the ROM mirroring, without any success. Maybe somebody could look into it -- right now it requires all kinds of trickery and even a memcpy ;) All I know is that everything that's there right now is needed otherwise either the game fails the ROM test, or Galaga crashes --- .gitattributes | 1 + src/mame/drivers/20pacgal.c | 315 +++++++++++++++------------- src/mame/includes/20pacgal.h | 29 +++ src/mame/video/20pacgal.c | 386 +++++++++++++++++++++++------------ 4 files changed, 457 insertions(+), 274 deletions(-) create mode 100644 src/mame/includes/20pacgal.h diff --git a/.gitattributes b/.gitattributes index bc899a03725..0429aabf774 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2093,6 +2093,7 @@ src/mame/drivers/zodiack.c svneol=native#text/plain src/mame/drivers/zr107.c svneol=native#text/plain src/mame/etc/fd1094dp.c svneol=native#text/plain src/mame/etc/jrcrypt.c svneol=native#text/plain +src/mame/includes/20pacgal.h svneol=native#text/plain src/mame/includes/8080bw.h svneol=native#text/plain src/mame/includes/amiga.h svneol=native#text/plain src/mame/includes/appoooh.h svneol=native#text/plain diff --git a/src/mame/drivers/20pacgal.c b/src/mame/drivers/20pacgal.c index facfcdf2839..766ef19f75c 100644 --- a/src/mame/drivers/20pacgal.c +++ b/src/mame/drivers/20pacgal.c @@ -1,73 +1,101 @@ /*************************************************************************** -Ms.Pac-Man/Galaga - 20 Year Reunion + Ms.Pac-Man/Galaga - 20 Year Reunion hardware -driver by Nicola Salmoria + driver by Nicola Salmoria -Notes: -- There are four start buttons: the first two are for Ms. Pac-Man, the other two - for Galaga. + Notes: + * There are four start buttons: the first two are for Ms. Pac-Man, the other two + for Galaga. + * To play Pac-Man instead of Ms. Pac-Man, insert coins then enter the following + sequence: U U U D D D L R L R L. A sound will play and the ghost will change + from red to pink. + * Writes to the Z180 ASCI port: + MS PAC-MAN/GALAGA + arcade video system + version 1.01 + (c) 2000 Cosmodog, Ltd. + > + and it listens for incoming characters. -- To play Pac-Man instead of Ms. Pac-Man, insert coins then enter the following - sequence: U U U D D D L R L R L. A sound will play and the ghost will change - from red to pink. - -- Writes to the Z180 ASCI port: - MS PAC-MAN/GALAGA - arcade video system - version 1.01 - (c) 2000 Cosmodog, Ltd. - > - and it listens for incoming characters. - - -TODO: -- Starfield. - -- Convert to tilemaps & optimize video rendering, I was just too lazy to do it for now. - -- Check the ASCI interface, there probably is fully working debug code. - -- The timed interrupt is a kludge; it is supposed to be generated internally by - the Z180, but the cpu core doesn't support that yet. - -- Correct CPU speed... Zilog says Z180 comes in 6, 8, 10, 20 & 33MHz. - 20MHz is used as it "seems" right based on the music in Galaga + Known issues/to-do's: + * Crashed on reset - Z180 core problem? + * ROM banking is not understood. Shouldn't require copying and other + trickey + * Starfield missing + * Check the ASCI interface, there probably is fully working debug code. + * The timed interrupt is a kludge; it is supposed to be generated internally by + the Z180, but the cpu core doesn't support that yet. + * Correct CPU speed... Zilog says Z180 comes in 6, 8, 10, 20 & 33MHz. + 20MHz is used as it "seems" right based on the music in Galaga ***************************************************************************/ #include "driver.h" #include "deprecat.h" #include "machine/eeprom.h" -#include "cpu/z180/z180.h" -#include "pacman.h" #include "sound/namco.h" #include "sound/dac.h" - -extern UINT8 *pacgal_charram,*pacgal_sprram; -extern UINT8 *pacgal_videoram,*pacgal_videoram2; -PALETTE_INIT( 20pacgal ); -VIDEO_START( 20pacgal ); -WRITE8_HANDLER( pacgal_lookup_w ); -WRITE8_HANDLER( pacgal_active_game_w ); -WRITE8_HANDLER( pacgal_videoram2_w ); -WRITE8_HANDLER( pacgal_charram_w ); -WRITE8_HANDLER( pacgal_sprram_w ); -VIDEO_UPDATE( 20pacgal ); +#include "20pacgal.h" +/************************************* + * + * Interrupt system + * + *************************************/ + +static WRITE8_HANDLER( irqack_w ) +{ + int bit = data & 1; + + cpu_interrupt_enable(0, bit); + + if (!bit) + cpunum_set_input_line(Machine, 0, 0, CLEAR_LINE ); +} + + + +/************************************* + * + * Audio + * + *************************************/ + +static const struct namco_interface namco_interface = +{ + 3, /* number of voices */ + -1, /* memory region */ +}; + + +static WRITE8_HANDLER( _20pacgal_dac_w ) +{ + DAC_signed_data_w(0, data); +} + + + +/************************************* + * + * Non-volatile memory + * + *************************************/ + static const struct EEPROM_interface eeprom_interface = { 7, /* address bits */ 8, /* data bits */ - "*110", /* read command */ + "*110", /* read command */ "*101", /* write command */ 0, /* erase command */ "*10000xxxxx", /* lock command */ "*10011xxxxx", /* unlock command */ }; + static NVRAM_HANDLER( eeprom ) { if (read_or_write) @@ -81,15 +109,14 @@ static NVRAM_HANDLER( eeprom ) } } + static READ8_HANDLER( eeprom_r ) { - int res; - /* bit 7 is EEPROM data */ - res = EEPROM_read_bit() << 7; - return res; + return EEPROM_read_bit() << 7; } + static WRITE8_HANDLER( eeprom_w ) { /* bit 7 is data */ @@ -100,50 +127,85 @@ static WRITE8_HANDLER( eeprom_w ) EEPROM_set_clock_line((data & 0x40) ? ASSERT_LINE : CLEAR_LINE); } -static WRITE8_HANDLER( irqack_w ) -{ - int bit = data & 1; - cpu_interrupt_enable(0,bit); - if (!bit) - cpunum_set_input_line(Machine, 0, 0, CLEAR_LINE ); -} -static WRITE8_HANDLER( flipscreen_w ) -{ - flip_screen_set(data & 1); -} -static WRITE8_HANDLER( pacgal_dac_w ) -{ - DAC_signed_data_w(0, data); -} +/************************************* + * + * Coin counter + * + *************************************/ -static WRITE8_HANDLER( coin_w ) +static WRITE8_HANDLER( _20pacgal_coin_counter_w ) { - coin_counter_w(0,data & 1); + coin_counter_w(0, data & 1); } +/************************************* + * + * ROM banking - FIXME + * + *************************************/ + +WRITE8_HANDLER( rom_bank_select_w ) +{ + _20pacgal_state *state = Machine->driver_data; + + state->game_selected = data & 1; + + if (state->game_selected == 0) + memcpy(memory_region(REGION_CPU1)+0x48000, memory_region(REGION_CPU1)+0x8000, 0x2000); +} + + +WRITE8_HANDLER( rom_48000_w ) +{ + _20pacgal_state *state = Machine->driver_data; + + if (state->game_selected) + { + if (offset < 0x0800) + state->video_ram[offset & 0x07ff] = data; + + memory_region(REGION_CPU1)[0x48000 + offset] = data; + } +} + + + +/************************************* + * + * Memory handlers + * + *************************************/ + static ADDRESS_MAP_START( 20pacgal_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x00000, 0x03fff) AM_ROM AM_RANGE(0x08000, 0x09fff) AM_ROM AM_RANGE(0x0a000, 0x0ffff) AM_MIRROR(0x40000) AM_ROM AM_RANGE(0x10000, 0x3ffff) AM_ROM - AM_RANGE(0x44000, 0x447ff) AM_RAM AM_BASE(&pacgal_videoram) // mspacman tilemap + AM_RANGE(0x44000, 0x447ff) AM_RAM AM_BASE_MEMBER(_20pacgal_state, video_ram) AM_RANGE(0x45040, 0x4505f) AM_WRITE(pacman_sound_w) AM_BASE(&namco_soundregs) AM_RANGE(0x44800, 0x45eff) AM_RAM - AM_RANGE(0x45f00, 0x45fff) AM_WRITE(_20pacgal_wavedata_w) AM_BASE(&namco_wavedata) // sound wave data - AM_RANGE(0x46000, 0x46fff) AM_WRITE(pacgal_charram_w) AM_BASE(&pacgal_charram) // char gfx data - AM_RANGE(0x47100, 0x47100) AM_RAM // leftover from original Galaga code - AM_RANGE(0x48000, 0x49fff) AM_ROM AM_BASE(&pacgal_videoram2) - AM_RANGE(0x48000, 0x49fff) AM_WRITE(pacgal_videoram2_w) // ROM or galaga tilemap (banked) - AM_RANGE(0x4c000, 0x4dfff) AM_WRITE(pacgal_sprram_w) AM_BASE(&pacgal_sprram) // sprite gfx data - AM_RANGE(0x4e000, 0x4e17f) AM_WRITE(MWA8_RAM) AM_BASE(&spriteram) // sprite registers - AM_RANGE(0x4ff00, 0x4ffff) AM_WRITE(pacgal_lookup_w) // sprite color lookup table + AM_RANGE(0x45f00, 0x45fff) AM_WRITE(_20pacgal_wavedata_w) AM_BASE(&namco_wavedata) + AM_RANGE(0x46000, 0x46fff) AM_WRITE(MWA8_RAM) AM_BASE_MEMBER(_20pacgal_state, char_gfx_ram) + AM_RANGE(0x47100, 0x47100) AM_RAM /* leftover from original Galaga code */ + AM_RANGE(0x48000, 0x49fff) AM_READWRITE(MRA8_ROM, rom_48000_w) /* this should be a mirror of 08000-09ffff */ + AM_RANGE(0x4c000, 0x4dfff) AM_WRITE(MWA8_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_gfx_ram) + AM_RANGE(0x4e000, 0x4e17f) AM_WRITE(MWA8_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_ram) + AM_RANGE(0x4ff00, 0x4ffff) AM_WRITE(MWA8_RAM) AM_BASE_MEMBER(_20pacgal_state, sprite_color_lookup) ADDRESS_MAP_END -static ADDRESS_MAP_START( 20pacgal_port, ADDRESS_SPACE_IO, 8 ) + + +/************************************* + * + * I/O port handlers + * + *************************************/ + +static ADDRESS_MAP_START( 20pacgal_io_map, ADDRESS_SPACE_IO, 8 ) ADDRESS_MAP_FLAGS( AMEF_ABITS(8) ) AM_RANGE(0x00, 0x3f) AM_NOP /* Z180 internal registers */ AM_RANGE(0x40, 0x7f) AM_NOP /* Z180 internal registers */ @@ -151,19 +213,25 @@ static ADDRESS_MAP_START( 20pacgal_port, ADDRESS_SPACE_IO, 8 ) AM_RANGE(0x81, 0x81) AM_READ(input_port_1_r) AM_RANGE(0x82, 0x82) AM_READ(input_port_2_r) AM_RANGE(0x80, 0x80) AM_WRITE(watchdog_reset_w) - AM_RANGE(0x81, 0x81) AM_WRITE(MWA8_NOP) // ??? pulsed by the timer irq + AM_RANGE(0x81, 0x81) AM_WRITE(MWA8_NOP) /* ??? pulsed by the timer irq */ AM_RANGE(0x82, 0x82) AM_WRITE(irqack_w) - AM_RANGE(0x85, 0x86) AM_WRITE(MWA8_NOP) // stars: rng seed (lo/hi) + AM_RANGE(0x85, 0x86) AM_WRITE(MWA8_NOP) /* stars: rng seed (lo/hi) */ AM_RANGE(0x87, 0x87) AM_READWRITE(eeprom_r, eeprom_w) - AM_RANGE(0x88, 0x88) AM_WRITE(pacgal_active_game_w) - AM_RANGE(0x89, 0x89) AM_WRITE(pacgal_dac_w) - AM_RANGE(0x8a, 0x8a) AM_WRITE(MWA8_NOP) // stars: bits 3-4 = active set; bit 5 = enable - AM_RANGE(0x8b, 0x8b) AM_WRITE(flipscreen_w) - AM_RANGE(0x8f, 0x8f) AM_WRITE(coin_w) // coin counter + AM_RANGE(0x88, 0x88) AM_WRITE(rom_bank_select_w) + AM_RANGE(0x89, 0x89) AM_WRITE(_20pacgal_dac_w) + AM_RANGE(0x8a, 0x8a) AM_WRITE(MWA8_NOP) /* stars: bits 3-4 = active set; bit 5 = enable */ + AM_RANGE(0x8b, 0x8b) AM_WRITE(MWA8_RAM) AM_BASE_MEMBER(_20pacgal_state, flip_screen) + AM_RANGE(0x8f, 0x8f) AM_WRITE(_20pacgal_coin_counter_w) ADDRESS_MAP_END +/************************************* + * + * Port definitions + * + *************************************/ + static INPUT_PORTS_START( 20pacgal ) PORT_START PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) @@ -180,10 +248,10 @@ static INPUT_PORTS_START( 20pacgal ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_COCKTAIL - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START3 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START4 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START3 ) PORT_NAME( "Right 1 Player Start" ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME( "Left 1 Player Start" ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME( "Left 2 Players Start" ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START4 ) PORT_NAME( "Right 2 Players Start" ) PORT_START PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) @@ -198,65 +266,26 @@ INPUT_PORTS_END -static const gfx_layout charlayout = -{ - 8,8, - 256, - 2, - { 0, 4 }, - { 8*8+0, 8*8+1, 8*8+2, 8*8+3, 0, 1, 2, 3 }, - { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, - 16*8 -}; - - -static const gfx_layout spritelayout = -{ - 16,16, - 128, - 2, - { 0, 1 }, - { 0*2, 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 7*2, 8*2, 9*2, 10*2, 11*2, 12*2, 13*2, 14*2, 15*2 }, - { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 }, - 16*32 -}; - -static GFXDECODE_START( 20pacgal ) - /* the game dynamically modifies these */ - GFXDECODE_ENTRY( 0, 0, charlayout, 0, 64 ) - GFXDECODE_ENTRY( 0, 0, spritelayout, 0, 64 ) -GFXDECODE_END - -static const struct namco_interface namco_interface = -{ - 3, /* number of voices */ - -1, /* memory region */ -}; +/************************************* + * + * Machine driver + * + *************************************/ static MACHINE_DRIVER_START( 20pacgal ) + MDRV_DRIVER_DATA(_20pacgal_state) + /* basic machine hardware */ MDRV_CPU_ADD(Z180,20000000) /* 20MHz ??? Needs to be verified! */ MDRV_CPU_PROGRAM_MAP(20pacgal_map,0) - MDRV_CPU_IO_MAP(20pacgal_port,0) + MDRV_CPU_IO_MAP(20pacgal_io_map,0) MDRV_CPU_VBLANK_INT(irq0_line_assert,1) - MDRV_SCREEN_REFRESH_RATE(60) - MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION) - MDRV_NVRAM_HANDLER(eeprom) /* video hardware */ - MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) - MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) - MDRV_SCREEN_SIZE(36*8, 28*8) - MDRV_SCREEN_VISIBLE_AREA(0*8, 36*8-1, 0*8, 28*8-1) - MDRV_GFXDECODE(20pacgal) - MDRV_PALETTE_LENGTH(0x1000) - MDRV_COLORTABLE_LENGTH(0x100) - MDRV_PALETTE_INIT(20pacgal) - MDRV_VIDEO_START(20pacgal) - MDRV_VIDEO_UPDATE(20pacgal) + MDRV_IMPORT_FROM(20pacgal_video) /* sound hardware */ MDRV_SPEAKER_STANDARD_MONO("mono") @@ -271,14 +300,14 @@ MACHINE_DRIVER_END -/*************************************************************************** - - Game driver(s) - -***************************************************************************/ +/************************************* + * + * ROM definition + * + *************************************/ ROM_START( 20pacgal ) - ROM_REGION( 0x100000, REGION_CPU1, 0 ) /* 1024k for Z180 address space */ + ROM_REGION( 0x100000, REGION_CPU1, 0 ) ROM_LOAD( "20th_101.u13", 0x00000, 0x40000, CRC(77159582) SHA1(c05e005a941cbdc806dcd76b315069362c792a72) ) ROM_REGION( 0x8000, REGION_PROMS, 0 ) /* palette */ @@ -287,4 +316,10 @@ ROM_END +/************************************* + * + * Game driver + * + *************************************/ + GAME( 2000, 20pacgal, 0, 20pacgal, 20pacgal, 0, ROT90, "Namco", "Ms. Pac-Man/Galaga - 20 Year Reunion", GAME_IMPERFECT_GRAPHICS ) diff --git a/src/mame/includes/20pacgal.h b/src/mame/includes/20pacgal.h new file mode 100644 index 00000000000..7de9eb61519 --- /dev/null +++ b/src/mame/includes/20pacgal.h @@ -0,0 +1,29 @@ +/*************************************************************************** + + Ms.Pac-Man/Galaga - 20 Year Reunion hardware + + driver by Nicola Salmoria + +***************************************************************************/ + + +typedef struct __20pacgal_state _20pacgal_state; +struct __20pacgal_state +{ + /* memory pointers */ + UINT8 *char_gfx_ram; + UINT8 *sprite_gfx_ram; + UINT8 *video_ram; + UINT8 *sprite_ram; + UINT8 *sprite_color_lookup; + UINT8 *flip_screen; + + /* machine state */ + UINT8 game_selected; /* 0 = Ms. Pac-Man, 1 = Galaga */ +}; + + + +/*----------- defined in video/20pacgal.c -----------*/ + +MACHINE_DRIVER_EXTERN( 20pacgal_video ); diff --git a/src/mame/video/20pacgal.c b/src/mame/video/20pacgal.c index 9b6737769e2..06f35ef4211 100644 --- a/src/mame/video/20pacgal.c +++ b/src/mame/video/20pacgal.c @@ -1,204 +1,322 @@ +/*************************************************************************** + + Ms.Pac-Man/Galaga - 20 Year Reunion hardware + + driver by Nicola Salmoria + +***************************************************************************/ + #include "driver.h" -#include "deprecat.h" +#include "20pacgal.h" + + +#define SCREEN_HEIGHT (224) +#define SCREEN_WIDTH (288) +#define NUM_PENS (0x1000) -UINT8 *pacgal_charram,*pacgal_sprram; -UINT8 *pacgal_videoram,*pacgal_videoram2; +/************************************* + * + * Palette handling + * + *************************************/ -static mame_bitmap *chr_bitmap; -static int palbank; -static int active_game; - - - -static void switch_palette(running_machine *machine) +static void get_pens(const _20pacgal_state *state, pen_t *pens) { - int i; - UINT8 *color_prom = memory_region(REGION_PROMS) + 0x1000 * palbank; + offs_t offs; + UINT8 *color_prom = memory_region(REGION_PROMS) + (NUM_PENS * state->game_selected); - for (i = 0;i < machine->drv->total_colors;i++) + for (offs = 0; offs < NUM_PENS ;offs++) { int bit0,bit1,bit2,r,g,b; - /* red component */ bit0 = (*color_prom >> 0) & 0x01; bit1 = (*color_prom >> 1) & 0x01; bit2 = (*color_prom >> 2) & 0x01; r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + /* green component */ bit0 = (*color_prom >> 3) & 0x01; bit1 = (*color_prom >> 4) & 0x01; bit2 = (*color_prom >> 5) & 0x01; g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + /* blue component */ bit0 = 0; bit1 = (*color_prom >> 6) & 0x01; bit2 = (*color_prom >> 7) & 0x01; b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; - palette_set_color(machine,i,MAKE_RGB(r,g,b)); + pens[offs] = MAKE_RGB(r, g, b); + color_prom++; } } -PALETTE_INIT( 20pacgal ) + + static void do_pen_lookup(const _20pacgal_state *state, mame_bitmap *bitmap, const rectangle *cliprect) { - palbank = 0; - switch_palette(machine); + int y, x; + pen_t pens[NUM_PENS]; + + get_pens(state, pens); + + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + for(x = cliprect->min_x; x <= cliprect->max_x; x++) + *BITMAP_ADDR32(bitmap, y, x) = pens[*BITMAP_ADDR32(bitmap, y, x)]; } -VIDEO_START( 20pacgal ) +/************************************* + * + * Sprite drawing + * + *************************************/ + +static void draw_sprite(const _20pacgal_state *state, mame_bitmap *bitmap, int y, int x, + UINT8 code, UINT8 color, int flip_y, int flip_x) { - chr_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,machine->screen[0].format); -} + int sy; + offs_t pen_base = (color & 0x3f) << 2; + if (flip_y) + y = y + 0x0f; -WRITE8_HANDLER( pacgal_lookup_w ) -{ - /* palette hacks! */ - ((UINT16 *)Machine->game_colortable)[offset] = data & 0x0f; - ((pen_t *)Machine->remapped_colortable)[offset] = Machine->pens[data & 0x0f]; -} + if (flip_x) + x = x + 0x0f; -WRITE8_HANDLER( pacgal_active_game_w ) -{ - active_game = data & 1; - - if (!active_game) - memcpy(pacgal_videoram2,memory_region(REGION_CPU1)+0x8000,0x2000); - - if (palbank != active_game) + /* for each row in the sprite */ + for (sy = 0; sy < 0x10; sy++) { - palbank = active_game; - switch_palette(Machine); + int x_sav = x; + + if ((y >= 0) && (y < SCREEN_HEIGHT)) + { + int sx; + UINT32 data; + + offs_t gfx_offs = ((code & 0x7f) << 6) | (sy << 2); + + /* address mangling */ + gfx_offs = (gfx_offs & 0x1f83) | ((gfx_offs & 0x003c) << 1) | ((gfx_offs & 0x0040) >> 4); + + data = (state->sprite_gfx_ram[gfx_offs + 0] << 24) | + (state->sprite_gfx_ram[gfx_offs + 1] << 16) | + (state->sprite_gfx_ram[gfx_offs + 2] << 8) | + (state->sprite_gfx_ram[gfx_offs + 3] << 0); + + /* for each pixel in the row */ + for (sx = 0; sx < 0x10; sx++) + { + if ((x >= 0) && (x < SCREEN_WIDTH)) + { + offs_t pen = (data & 0xc0000000) >> 30; + UINT8 col; + + col = state->sprite_color_lookup[pen_base | pen] & 0x0f; + + /* pen bits A0-A3 */ + if (col) + *BITMAP_ADDR32(bitmap, y, x) = (*BITMAP_ADDR32(bitmap, y, x) & 0xff0) | col; + } + + /* next pixel */ + if (flip_x) + x = x - 1; + else + x = x + 1; + + data = data << 2; + } + } + + /* next row */ + if (flip_y) + y = y - 1; + else + y = y + 1; + + x = x_sav; } } -WRITE8_HANDLER( pacgal_videoram2_w ) -{ - if (active_game) - pacgal_videoram2[offset] = data; -} -WRITE8_HANDLER( pacgal_charram_w ) -{ - pacgal_charram[offset] = data; - - decodechar(Machine->gfx[0],offset/16,pacgal_charram); -} - -WRITE8_HANDLER( pacgal_sprram_w ) -{ - offset = (offset & 0x1f83) | ((offset & 0x078) >> 1) | ((offset & 0x004) << 4); - pacgal_sprram[offset] = data; - - decodechar(Machine->gfx[1],offset/64,pacgal_sprram); -} - - - -static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect ) +static void draw_sprites(const _20pacgal_state *state, mame_bitmap *bitmap) { int offs; - - for (offs = 0x80-2;offs >= 0;offs-=2) + for (offs = 0x80 - 2; offs >= 0; offs -= 2) { - static const int gfx_offs[2][2] = + static const int code_offs[2][2] = { { 0, 1 }, { 2, 3 } }; - int sprite = spriteram[offs + 0x000] & 0x7f; - int color = spriteram[offs + 0x001] & 0x3f; - int sx = spriteram[offs + 0x081] - 41 + 0x100*(spriteram[offs + 0x101] & 3); - int sy = 256 - spriteram[offs + 0x080] + 1; - int flipx = (spriteram[offs + 0x100] & 0x01); - int flipy = (spriteram[offs + 0x100] & 0x02) >> 1; - int sizex = (spriteram[offs + 0x100] & 0x04) >> 2; - int sizey = (spriteram[offs + 0x100] & 0x08) >> 3; - int x,y; + int x, y; - if (flip_screen) + UINT8 code = state->sprite_ram[offs + 0x000]; + UINT8 color = state->sprite_ram[offs + 0x001]; + + int sx = state->sprite_ram[offs + 0x081] - 41 + 0x100*(state->sprite_ram[offs + 0x101] & 3); + int sy = 256 - state->sprite_ram[offs + 0x080] + 1; + + int flip_x = (state->sprite_ram[offs + 0x100] & 0x01) >> 0; + int flip_y = (state->sprite_ram[offs + 0x100] & 0x02) >> 1; + int size_x = (state->sprite_ram[offs + 0x100] & 0x04) >> 2; + int size_y = (state->sprite_ram[offs + 0x100] & 0x08) >> 3; + + sy = sy - (16 * size_y); + sy = (sy & 0xff) - 32; /* fix wraparound */ + + /* only Galaga appears to be effected by the global flip state */ + if (state->game_selected && (state->flip_screen[0] & 0x01)) { - flipx ^= 1; - flipy ^= 1; + flip_x = !flip_x; + flip_y = !flip_y; } - sy -= 16 * sizey; - sy = (sy & 0xff) - 32; // fix wraparound + for (y = 0; y <= size_y; y++) + for (x = 0; x <= size_x; x++) + draw_sprite(state, bitmap, + sy + (16 * y), sx + (16 * x), + code + code_offs[y ^ (size_y * flip_y)][x ^ (size_x * flip_x)], + color, + flip_y, flip_x); + } +} - for (y = 0;y <= sizey;y++) + + +/************************************* + * + * Character map drawing + * + *************************************/ + +static void draw_chars(const _20pacgal_state *state, mame_bitmap *bitmap) +{ + offs_t offs; + + int flip = state->flip_screen[0] & 0x01; + + /* for each byte in the video RAM */ + for (offs = 0; offs < 0x400; offs++) + { + int sy; + int y, x; + + UINT8 *gfx = &state->char_gfx_ram[state->video_ram[0x0000 | offs] << 4]; + UINT32 color_base = (state->video_ram[0x0400 | offs] & 0x3f) << 2; + + /* map the offset to (x, y) character coordinates */ + if ((offs & 0x03c0) == 0) { - for (x = 0;x <= sizex;x++) + y = (offs & 0x1f) - 2; + x = (offs >> 5) + 34; + } + else if ((offs & 0x03c0) == 0x3c0) + { + y = (offs & 0x1f) - 2; + x = (offs >> 5) - 30; + } + else + { + y = (offs >> 5) - 2; + x = (offs & 0x1f) + 2; + } + + if ((y < 0) || (y > 27)) continue; + + /* conver to pixel coordinates */ + y = y << 3; + x = x << 3; + + if (flip) + { + y = SCREEN_HEIGHT - 1 - y; + x = SCREEN_WIDTH - 1 - x; + } + + /* for each row in the character */ + for (sy = 0; sy < 8; sy++) + { + int sx; + int x_sav = x; + + UINT16 data = (gfx[8] << 8) | gfx[0]; + + /* for each pixel in the row */ + for (sx = 0; sx < 8; sx++) { - drawgfx(bitmap,machine->gfx[1], - sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)], - color, - flipx,flipy, - sx + 16*x, sy + 16*y, - cliprect,TRANSPARENCY_COLOR,0); + UINT32 col = ((data & 0x8000) >> 14) | ((data & 0x0800) >> 11); + + /* pen bits A4-A11 */ + *BITMAP_ADDR32(bitmap, y, x) = (color_base | col) << 4; + + /* next pixel */ + if (flip) + x = x - 1; + else + x = x + 1; + + if (sx == 0x03) + data = data << 5; + else + data = data << 1; } + + /* next row */ + if (flip) + y = y - 1; + else + y = y + 1; + + x = x_sav; + + gfx = gfx + 1; } } } -VIDEO_UPDATE( 20pacgal ) + + +/************************************* + * + * Video update + * + *************************************/ + +static VIDEO_UPDATE( 20pacgal ) { - int x,y; + const _20pacgal_state *state = machine->driver_data; - for (y = 0;y < 32;y++) - { - for (x = 0;x < 32;x++) - { - int sx,sy; - if (y < 2) - { - sy = x-2; - sx = 34+y; - } - else if (y >= 30) - { - sy = x-2; - sx = y-30; - } - else - { - sy = y-2; - sx = x+2; - } - - if (active_game) - { - drawgfx(chr_bitmap,machine->gfx[0], - pacgal_videoram2[y*32 + x] + 0xa00, - (pacgal_videoram2[0x400 + y*32 + x] & 0x3f) * 4, - 0,0, - 8*sx,8*sy, - cliprect,TRANSPARENCY_NONE_RAW,0); - } - else - { - drawgfx(chr_bitmap,machine->gfx[0], - pacgal_videoram[y*32 + x] + 0xa00, - (pacgal_videoram[0x400 + y*32 + x] & 0x3f) * 4, - 0,0, - 8*sx,8*sy, - cliprect,TRANSPARENCY_NONE_RAW,0); - } - } - } - - fillbitmap(bitmap,0,NULL); - - draw_sprites(machine,bitmap,cliprect); - - copybitmap(bitmap, chr_bitmap, flip_screen, flip_screen, 0, 0, cliprect, TRANSPARENCY_BLEND_RAW, 4); + draw_chars(state, bitmap); + draw_sprites(state, bitmap); + do_pen_lookup(state, bitmap, cliprect); return 0; } + + + +/************************************* + * + * Machine driver + * + *************************************/ + +MACHINE_DRIVER_START( 20pacgal_video ) + + MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) + MDRV_VIDEO_UPDATE(20pacgal) + + MDRV_SCREEN_REFRESH_RATE(60) + MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32) + MDRV_SCREEN_SIZE(SCREEN_WIDTH, SCREEN_HEIGHT) + MDRV_SCREEN_VISIBLE_AREA(0, SCREEN_WIDTH - 1, 0, SCREEN_HEIGHT - 1) +MACHINE_DRIVER_END