1 /***************************************************************************
2 
3 	Video Hardware for Blood Brothers
4 
5 ***************************************************************************/
6 
7 #include "vidhrdw/generic.h"
8 
9 #define NUM_SPRITES 128
10 
11 unsigned char *textlayoutram;
12 static unsigned char *dirtybuffer2;
13 static struct osd_bitmap *tmpbitmap2;
14 extern unsigned char *dirtybuffer2;
15 unsigned char *bloodbro_videoram2;
16 unsigned char *bloodbro_scroll;
17 static struct sprite_list *sprite_list;
18 
19 
READ_HANDLER(bloodbro_background_r)20 READ_HANDLER( bloodbro_background_r ){
21 	return READ_WORD (&videoram[offset]);
22 }
23 
WRITE_HANDLER(bloodbro_background_w)24 WRITE_HANDLER( bloodbro_background_w ){
25 	int oldword = READ_WORD(&videoram[offset]);
26 	int newword = COMBINE_WORD(oldword,data);
27 	if( oldword != newword ){
28 		WRITE_WORD(&videoram[offset],newword);
29 		dirtybuffer[offset/2] = 1;
30 	}
31 }
32 
READ_HANDLER(bloodbro_foreground_r)33 READ_HANDLER( bloodbro_foreground_r ){
34 	return READ_WORD (&bloodbro_videoram2[offset]);
35 }
36 
WRITE_HANDLER(bloodbro_foreground_w)37 WRITE_HANDLER( bloodbro_foreground_w ){
38 	int oldword = READ_WORD(&bloodbro_videoram2[offset]);
39 	int newword = COMBINE_WORD(oldword,data);
40 	if( oldword != newword ){
41 		WRITE_WORD(&bloodbro_videoram2[offset],newword);
42 		dirtybuffer2[offset/2] = 1;
43 	}
44 }
45 
46 /**************************************************************************/
47 
bloodbro_vh_stop(void)48 void bloodbro_vh_stop(void) {
49 	if( tmpbitmap ) bitmap_free( tmpbitmap );
50 	if( tmpbitmap2 ) bitmap_free( tmpbitmap2 );
51 	free( dirtybuffer2 );
52 	free( dirtybuffer );
53 }
54 
bloodbro_vh_start(void)55 int bloodbro_vh_start(void) {
56 	tmpbitmap = bitmap_alloc(512,256);
57 	dirtybuffer = (unsigned char*)malloc(32*16);
58 	tmpbitmap2 = bitmap_alloc(512,256);
59 	dirtybuffer2 = (unsigned char*)malloc(32*16);
60 	sprite_list = sprite_list_create( NUM_SPRITES, SPRITE_LIST_FRONT_TO_BACK );
61 
62 	if( tmpbitmap && tmpbitmap2 && dirtybuffer && dirtybuffer2 ){
63 		memset( dirtybuffer, 1, 32*16 );
64 		memset( dirtybuffer2, 1, 32*16 );
65 		sprite_list->transparent_pen = 0xf;
66 		sprite_list->max_priority = 1;
67 		sprite_list->sprite_type = SPRITE_TYPE_STACK;
68 		return 0;
69 	}
70 	bloodbro_vh_stop();
71 	return 1;
72 }
73 
74 /**************************************************************************/
75 
draw_text(struct osd_bitmap * bitmap)76 static void draw_text( struct osd_bitmap *bitmap ){
77 	const struct rectangle *clip = &Machine->visible_area;
78 	const UINT16 *source = (const UINT16 *)textlayoutram;
79 	int sx, sy;
80 	for( sy=0; sy<32; sy++ ){
81 		for( sx=0; sx<32; sx++ ){
82 			UINT16 data = *source++;
83 
84 			drawgfx(bitmap,Machine->gfx[0],
85 					data&0xfff, /* tile number */
86 					data>>12, /* color */
87 					0,0,   /* no flip */
88 					8*sx,8*sy,
89 					clip,TRANSPARENCY_PEN,0xf);
90 		}
91 	}
92 }
93 
draw_background(struct osd_bitmap * bitmap)94 static void draw_background( struct osd_bitmap *bitmap ) {
95 	const struct GfxElement *gfx = Machine->gfx[1];
96 	const UINT16 *source = (UINT16 *)videoram;
97 	int offs;
98 	for( offs=0; offs<32*16; offs++ ){
99 		if( dirtybuffer[offs] ){
100 			int sx = 16*(offs%32);
101 			int sy = 16*(offs/32);
102 			UINT16 data = source[offs];
103 			dirtybuffer[offs] = 0;
104 
105 			drawgfx(tmpbitmap,gfx,
106 				data&0xfff, /* tile number */
107 				(data&0xf000)>>12, /* color */
108 				0,0, /* no flip */
109 				sx,sy,
110 				0,TRANSPARENCY_NONE,0);
111 		}
112     }
113     {
114 		int scrollx = -READ_WORD( &bloodbro_scroll[0x20] ); /** ? **/
115 		int scrolly = -READ_WORD( &bloodbro_scroll[0x22] ); /** ? **/
116 
117 		copyscrollbitmap(bitmap,tmpbitmap,
118 			1,&scrollx,1,&scrolly,
119 			&Machine->visible_area,
120               TRANSPARENCY_NONE,0);
121 	}
122 }
123 
draw_foreground(struct osd_bitmap * bitmap)124 static void draw_foreground( struct osd_bitmap *bitmap ) {
125 	struct rectangle r;
126 	const struct GfxElement *gfx = Machine->gfx[2];
127 	const UINT16 *source = (UINT16 *)bloodbro_videoram2;
128 	int offs;
129 	for( offs=0; offs<32*16; offs++ ){
130 		if( dirtybuffer2[offs] ){
131 			int sx = 16*(offs%32);
132 			int sy = 16*(offs/32);
133 			UINT16 data = source[offs];
134 			dirtybuffer2[offs] = 0;
135 
136 			/* Necessary to use TRANSPARENCY_PEN here */
137 			r.min_x = sx; r.max_x = sx+15;
138 			r.min_y = sy; r.max_y = sy+15;
139 			fillbitmap(tmpbitmap2,0xf,&r);
140 			/******************************************/
141 
142 			drawgfx( tmpbitmap2,gfx,
143 				data&0xfff, /* tile number */
144 				(data&0xf000)>>12, /* color */
145 				0,0,
146 				sx,sy,
147 				0,TRANSPARENCY_PEN,0xf);
148 		}
149 	}
150 	{
151 		int scrollx = -READ_WORD( &bloodbro_scroll[0x24] );
152 		int scrolly = -READ_WORD( &bloodbro_scroll[0x26] );
153 
154 		copyscrollbitmap(bitmap,tmpbitmap2,1,&scrollx,1,&scrolly,&Machine->visible_area,
155                 TRANSPARENCY_PEN,0xf );
156 	}
157 }
158 
159 /* SPRITE INFO (8 bytes)
160 
161    --F???SS SSSSCCCC
162    ---TTTTT TTTTTTTT
163    -------X XXXXXXXX
164    -------- YYYYYYYY */
get_sprite_info(void)165 static void get_sprite_info( void ){
166 	const struct GfxElement *gfx = Machine->gfx[3];
167 	const unsigned short *source = (const UINT16 *)spriteram;
168 	struct sprite *sprite = sprite_list->sprite;
169 	int count = NUM_SPRITES;
170 
171 	int attributes, flags, number, color, vertical_size, horizontal_size, i;
172 	while( count-- ){
173 		attributes = source[0];
174 		flags = 0;
175 		if( (attributes&0x8000)==0 ){
176 			flags |= SPRITE_VISIBLE;
177 			horizontal_size = 1 + ((attributes>>7)&7);
178 			vertical_size = 1 + ((attributes>>4)&7);
179 			sprite->priority = (attributes>>11)&1;
180 			number = source[1]&0x1fff;
181 			sprite->x = source[2]&0x1ff;
182 			sprite->y = source[3]&0x1ff;
183 
184 			/* wraparound - could be handled by Sprite Manager?*/
185 			if( sprite->x >= 256) sprite->x -= 512;
186 			if( sprite->y >= 256) sprite->y -= 512;
187 
188 			sprite->total_width = 16*horizontal_size;
189 			sprite->total_height = 16*vertical_size;
190 
191 			sprite->tile_width = 16;
192 			sprite->tile_height = 16;
193 			sprite->line_offset = 16;
194 
195 			if( attributes&0x2000 ) flags |= SPRITE_FLIPX;
196 			if( attributes&0x4000 ) flags |= SPRITE_FLIPY; /* ? */
197 			color = attributes&0xf;
198 
199 			sprite->pen_data = gfx->gfxdata + number * gfx->char_modulo;
200 			sprite->pal_data = &gfx->colortable[gfx->color_granularity * color];
201 
202 			sprite->pen_usage = 0;
203 			for( i=0; i<vertical_size*horizontal_size; i++ ){
204 				sprite->pen_usage |= gfx->pen_usage[number++];
205 			}
206 		}
207 		sprite->flags = flags;
208 
209 		sprite++;
210 		source+=4;
211 	}
212 }
213 
bloodbro_mark_used_colors(void)214 static void bloodbro_mark_used_colors(void){
215 	int offs,i;
216 	int code, color, colmask[0x80];
217 	int pal_base = Machine->drv->gfxdecodeinfo[0].color_codes_start;
218 
219 	/* Build the dynamic palette */
220 	palette_init_used_colors();
221 
222 	/* Text layer */
223 	pal_base = Machine->drv->gfxdecodeinfo[0].color_codes_start;
224 	for (color = 0;color < 16;color++) colmask[color] = 0;
225 	for (offs = 0;offs <0x800;offs += 2) {
226 		code = READ_WORD(&textlayoutram[offs]);
227 		color=code>>12;
228 		if ((code&0xfff)==0xd) continue;
229 		colmask[color] |= Machine->gfx[0]->pen_usage[code&0xfff];
230 	}
231 	for (color = 0;color < 16;color++)
232 	{
233 		for (i = 0;i < 15;i++)
234 		{
235 			if (colmask[color] & (1 << i))
236 				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
237 		}
238 	}
239 
240 	/* Tiles - bottom layer */
241 	pal_base = Machine->drv->gfxdecodeinfo[1].color_codes_start;
242 	for (offs=0; offs<256; offs++)
243 		palette_used_colors[pal_base + offs] = PALETTE_COLOR_USED;
244 
245 	/* Tiles - top layer */
246 	pal_base = Machine->drv->gfxdecodeinfo[2].color_codes_start;
247 	for (color = 0;color < 16;color++) colmask[color] = 0;
248 	for (offs = 0x0000;offs <0x400;offs += 2 )
249 	{
250 		code = READ_WORD(&bloodbro_videoram2[offs]);
251 		color= code>>12;
252 		colmask[color] |= Machine->gfx[2]->pen_usage[code&0xfff];
253 	}
254 
255 	for (color = 0;color < 16;color++){
256 		for (i = 0;i < 15;i++)
257 		{
258 			if (colmask[color] & (1 << i))
259 				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
260 		}
261 		/* kludge */
262 		palette_used_colors[pal_base + 16 * color +15] = PALETTE_COLOR_TRANSPARENT;
263 		palette_change_color(pal_base + 16 * color +15 ,0,0,0);
264 	}
265 }
266 
bloodbro_vh_screenrefresh(struct osd_bitmap * bitmap,int fullrefresh)267 void bloodbro_vh_screenrefresh( struct osd_bitmap *bitmap, int fullrefresh ){
268 	get_sprite_info();
269 
270 	bloodbro_mark_used_colors();
271 	sprite_update();
272 
273 	if (palette_recalc()) {
274 		memset(dirtybuffer,1,32*16);
275 		memset(dirtybuffer2,1,32*16);
276 	}
277 
278 	draw_background( bitmap );
279 	sprite_draw( sprite_list, 1 );
280 	draw_foreground( bitmap );
281 	sprite_draw( sprite_list, 0 );
282 	draw_text( bitmap );
283 }
284 
285 /* SPRITE INFO (8 bytes)
286 
287    -------- YYYYYYYY
288    ---TTTTT TTTTTTTT
289    CCCC--F? -?--????  Priority??
290    -------X XXXXXXXX
291 */
292 
weststry_draw_sprites(struct osd_bitmap * bitmap,int priority)293 static void weststry_draw_sprites( struct osd_bitmap *bitmap, int priority) {
294 	int offs;
295 	for( offs = 0x800-8; offs > 0; offs-=8 ){
296 		int data = READ_WORD( &spriteram[offs+4] );
297 		int data0 = READ_WORD( &spriteram[offs+0] );
298 		int tile_number = READ_WORD( &spriteram[offs+2] )&0x1fff;
299 		int sx = READ_WORD( &spriteram[offs+6] )&0xff;
300 		int sy = 0xf0-(data0&0xff);
301 		int flipx = (data&0x200)>>9;
302 		int datax = (READ_WORD( &spriteram[offs+6] )&0x100);
303 		int color = (data&0xf000)>>12;
304 
305 		/* Remap sprites */
306 		switch(tile_number&0x1800) {
307 			case 0x0000: break;
308 			case 0x0800: tile_number = (tile_number&0x7ff) | 0x1000; break;
309 			case 0x1000: tile_number = (tile_number&0x7ff) | 0x800; break;
310 			case 0x1800: break;
311 		}
312 
313 		if ((!(data0&0x8000)) && (!datax)) {
314 			drawgfx(bitmap,Machine->gfx[3],
315 				tile_number, color, flipx,0,
316 				sx,sy,
317 				&Machine->visible_area,TRANSPARENCY_PEN,0xf);
318 		}
319 	}
320 }
321 
weststry_mark_used_colors(void)322 static void weststry_mark_used_colors(void){
323 	int offs,i;
324 	int colmask[0x80],code,pal_base,color;
325 
326  	/* Build the dynamic palette */
327 	palette_init_used_colors();
328 
329 	/* Text layer */
330 	pal_base = Machine->drv->gfxdecodeinfo[0].color_codes_start;
331 	for (color = 0;color < 16;color++) colmask[color] = 0;
332 	for (offs = 0;offs <0x800;offs += 2) {
333 		code = READ_WORD(&textlayoutram[offs]);
334 		color=code>>12;
335 		if ((code&0xfff)==0xd) continue;
336 		colmask[color] |= Machine->gfx[0]->pen_usage[code&0xfff];
337 	}
338 	for (color = 0;color < 16;color++)
339 	{
340 		for (i = 0;i < 15;i++)
341 		{
342 			if (colmask[color] & (1 << i))
343 				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
344 		}
345 	}
346 
347 	/* Tiles - bottom layer */
348 	pal_base = Machine->drv->gfxdecodeinfo[1].color_codes_start;
349 	for (offs=0; offs<256; offs++)
350 		palette_used_colors[pal_base + offs] = PALETTE_COLOR_USED;
351 
352 	/* Tiles - top layer */
353 	pal_base = Machine->drv->gfxdecodeinfo[2].color_codes_start;
354 	for (color = 0;color < 16;color++) colmask[color] = 0;
355 	for (offs = 0x0000;offs <0x400;offs += 2 )
356 	{
357 		code = READ_WORD(&bloodbro_videoram2[offs]);
358 		color= code>>12;
359 		colmask[color] |= Machine->gfx[2]->pen_usage[code&0xfff];
360 	}
361 	for (color = 0;color < 16;color++)
362 	{
363 		for (i = 0;i < 15;i++)
364 		{
365 			if (colmask[color] & (1 << i))
366 				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
367 		}
368 
369                 /* kludge */
370                 palette_used_colors[pal_base + 16 * color +15] = PALETTE_COLOR_TRANSPARENT;
371                 palette_change_color(pal_base + 16 * color +15 ,0,0,0);
372 	}
373 
374 	/* Sprites */
375 	pal_base = Machine->drv->gfxdecodeinfo[3].color_codes_start;
376 	for (color = 0;color < 16;color++) colmask[color] = 0;
377 	for (offs = 0;offs <0x800;offs += 8 )
378 	{
379 		color = READ_WORD(&spriteram[offs+4])>>12;
380 		code = READ_WORD(&spriteram[offs+2])&0x1fff;
381                 /* Remap code 0x800 <-> 0x1000 */
382                 code = (code&0x7ff) | ((code&0x800)<<1) | ((code&0x1000)>>1);
383 
384 		colmask[color] |= Machine->gfx[3]->pen_usage[code];
385 	}
386 	for (color = 0;color < 16;color++)
387 	{
388 		for (i = 0;i < 15;i++)
389 		{
390 			if (colmask[color] & (1 << i))
391 				palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
392 		}
393 	}
394 
395 	if (palette_recalc()) {
396                 memset(dirtybuffer,1,32*16);
397                 memset(dirtybuffer2,1,32*16);
398 	}
399 }
400 
weststry_vh_screenrefresh(struct osd_bitmap * bitmap,int fullrefresh)401 void weststry_vh_screenrefresh( struct osd_bitmap *bitmap, int fullrefresh ){
402 	weststry_mark_used_colors();
403 
404 	draw_background( bitmap );
405 	//weststry_draw_sprites(bitmap,0);
406 	draw_foreground( bitmap );
407 	weststry_draw_sprites(bitmap,1);
408 	draw_text( bitmap );
409 }
410 
411