summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/decocomn.c
blob: ec581505a0c2d33bf20d95d217cfb5a209bd7d01 (plain) (tree)
1
2
3

                                                                                            
                                                                                             


































                                                                                 
                                                                    












                                                                              
                                                                        

                               


                                                                               
 
                                                                          





                                                          
                                                                        






                                                          
                                                       







                                                       


                                                                                              
 
                                                                                 














































                                                                                                                      

                                                                                                                        





































































                                                                                                            
                                                                                 


                                            
                                                                                                                       
 

                                                                                                        









































                                                                                                                                                              
/* Common DECO video functions (general, not sorted by IC) */
/* I think most of this stuff is driver specific and really shouldn't be in a device at all.
   It was only put here because I wanted to split deco_tilegen1 to just be the device for the
   tilemap chips, and not contain all this extra unrelated stuff */


#include "emu.h"
#include "video/decocomn.h"
#include "ui.h"


typedef struct _decocomn_state decocomn_state;
struct _decocomn_state
{
	screen_device *screen;
	UINT16 *raster_display_list;
	UINT8 *dirty_palette;
	bitmap_t *sprite_priority_bitmap;
	UINT16 priority;
	int raster_display_position;
};

/*****************************************************************************
    INLINE FUNCTIONS
*****************************************************************************/

INLINE decocomn_state *get_safe_token( device_t *device )
{
	assert(device != NULL);
	assert(device->type() == DECOCOMN);

	return (decocomn_state *)downcast<legacy_device_base *>(device)->token();
}

INLINE const decocomn_interface *get_interface( device_t *device )
{
	assert(device != NULL);
	assert((device->type() == DECOCOMN));
	return (const decocomn_interface *) device->static_config();
}

/*****************************************************************************
    DEVICE HANDLERS
*****************************************************************************/

/* Later games have double buffered paletteram - the real palette ram is
only updated on a DMA call */

WRITE16_DEVICE_HANDLER( decocomn_nonbuffered_palette_w )
{
	int r,g,b;

	COMBINE_DATA(&device->machine().generic.paletteram.u16[offset]);
	if (offset&1) offset--;

	b = (device->machine().generic.paletteram.u16[offset] >> 0) & 0xff;
	g = (device->machine().generic.paletteram.u16[offset + 1] >> 8) & 0xff;
	r = (device->machine().generic.paletteram.u16[offset + 1] >> 0) & 0xff;

	palette_set_color(device->machine(), offset / 2, MAKE_RGB(r,g,b));
}

WRITE16_DEVICE_HANDLER( decocomn_buffered_palette_w )
{
	decocomn_state *decocomn = get_safe_token(device);

	COMBINE_DATA(&device->machine().generic.paletteram.u16[offset]);

	decocomn->dirty_palette[offset / 2] = 1;
}

WRITE16_DEVICE_HANDLER( decocomn_palette_dma_w )
{
	decocomn_state *decocomn = get_safe_token(device);
	const int m = device->machine().total_colors();
	int r, g, b, i;

	for (i = 0; i < m; i++)
	{
		if (decocomn->dirty_palette[i])
		{
			decocomn->dirty_palette[i] = 0;

			b = (device->machine().generic.paletteram.u16[i * 2] >> 0) & 0xff;
			g = (device->machine().generic.paletteram.u16[i * 2 + 1] >> 8) & 0xff;
			r = (device->machine().generic.paletteram.u16[i * 2 + 1] >> 0) & 0xff;

			palette_set_color(device->machine(), i, MAKE_RGB(r,g,b));
		}
	}
}

/*****************************************************************************************/

/* */
READ16_DEVICE_HANDLER( decocomn_71_r )
{
	return 0xffff;
}

WRITE16_DEVICE_HANDLER( decocomn_priority_w )
{
	decocomn_state *decocomn = get_safe_token(device);
	decocomn->priority = data;
}

READ16_DEVICE_HANDLER( decocomn_priority_r )
{
	decocomn_state *decocomn = get_safe_token(device);
	return decocomn->priority;
}


/******************************************************************************/

/*****************************************************************************************/

void decocomn_clear_sprite_priority_bitmap( device_t *device )
{
	decocomn_state *decocomn = get_safe_token(device);

	if (decocomn->sprite_priority_bitmap)
		bitmap_fill(decocomn->sprite_priority_bitmap, NULL, 0);
}

/* A special pdrawgfx z-buffered sprite renderer that is needed to properly draw multiple sprite sources with alpha */
void decocomn_pdrawgfx(
		device_t *device,
		bitmap_t *dest, const rectangle *clip, const gfx_element *gfx,
		UINT32 code, UINT32 color, int flipx, int flipy, int sx, int sy,
		int transparent_color, UINT32 pri_mask, UINT32 sprite_mask, UINT8 write_pri, UINT8 alpha)
{
	decocomn_state *decocomn = get_safe_token(device);
	int ox, oy, cx, cy;
	int x_index, y_index, x, y;
	bitmap_t *priority_bitmap = gfx->machine().priority_bitmap;
	const pen_t *pal = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
	const UINT8 *code_base = gfx_element_get_data(gfx, code % gfx->total_elements);

	/* check bounds */
	ox = sx;
	oy = sy;

	if (sx > 319 || sy > 247 || sx < -15 || sy < -7)
		return;

	if (sy < 0) sy = 0;
	if (sx < 0) sx = 0;

	if (sx > 319) cx = 319;
	else cx = ox + 16;

	cy = (sy - oy);

	if (flipy) y_index = 15 - cy; else y_index = cy;

	for (y = 0; y < 16 - cy; y++)
	{
		const UINT8 *source = code_base + (y_index * gfx->line_modulo);
		UINT32 *destb = BITMAP_ADDR32(dest, sy, 0);
		UINT8 *pri = BITMAP_ADDR8(priority_bitmap, sy, 0);
		UINT8 *spri = BITMAP_ADDR8(decocomn->sprite_priority_bitmap, sy, 0);

		if (sy >= 0 && sy < 248)
		{
			if (flipx) { source += 15 - (sx - ox); x_index = -1; }
			else       { source += (sx - ox); x_index = 1; }

			for (x = sx; x < cx; x++)
			{
				int c = *source;
				if (c != transparent_color && x >= 0 && x < 320)
				{
					if (pri_mask>pri[x] && sprite_mask>spri[x])
					{
						if (alpha != 0xff)
							destb[x] = alpha_blend_r32(destb[x], pal[c], alpha);
						else
							destb[x] = pal[c];
						if (write_pri)
							pri[x] |= pri_mask;
					}
					spri[x] |= sprite_mask;
				}
				source += x_index;
			}
		}

		sy++;
		if (sy > 247)
			return;
		if (flipy) y_index--; else y_index++;
	}
}

/*****************************************************************************************/

/*****************************************************************************
    DEVICE INTERFACE
*****************************************************************************/

static DEVICE_START( decocomn )
{
	decocomn_state *decocomn = get_safe_token(device);
	const decocomn_interface *intf = get_interface(device);
	int width, height;

	decocomn->screen = device->machine().device<screen_device>(intf->screen);
	width = decocomn->screen->width();
	height = decocomn->screen->height();

	decocomn->sprite_priority_bitmap = auto_bitmap_alloc(device->machine(), width, height, BITMAP_FORMAT_INDEXED8);

	decocomn->dirty_palette = auto_alloc_array_clear(device->machine(), UINT8, 4096);
	decocomn->raster_display_list = auto_alloc_array_clear(device->machine(), UINT16, 20 * 256 / 2);



	device->save_item(NAME(decocomn->priority));
	device->save_item(NAME(decocomn->raster_display_position));
	device->save_pointer(NAME(decocomn->dirty_palette), 4096);
	device->save_pointer(NAME(decocomn->raster_display_list), 20 * 256 / 2);
}

static DEVICE_RESET( decocomn )
{
	decocomn_state *decocomn = get_safe_token(device);

	decocomn->raster_display_position = 0;

	decocomn->priority = 0;
}


DEVICE_GET_INFO( decocomn )
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */
		case DEVINFO_INT_TOKEN_BYTES:			info->i = sizeof(decocomn_state);					break;

		/* --- the following bits of info are returned as pointers to data or functions --- */
		case DEVINFO_FCT_START:					info->start = DEVICE_START_NAME(decocomn);		break;
		case DEVINFO_FCT_STOP:					/* Nothing */									break;
		case DEVINFO_FCT_RESET:					info->reset = DEVICE_RESET_NAME(decocomn);		break;

		/* --- the following bits of info are returned as NULL-terminated strings --- */
		case DEVINFO_STR_NAME:					strcpy(info->s, "Data East Common Video Functions");				break;
		case DEVINFO_STR_FAMILY:				strcpy(info->s, "Data East Video IC");					break;
		case DEVINFO_STR_VERSION:				strcpy(info->s, "1.0");							break;
		case DEVINFO_STR_SOURCE_FILE:			strcpy(info->s, __FILE__);						break;
		case DEVINFO_STR_CREDITS:				strcpy(info->s, "Copyright MAME Team");			break;
	}
}


DEFINE_LEGACY_DEVICE(DECOCOMN, decocomn);