1 /* Macross Plus - Vidhrdw
2   see DRIVER file for notes */
3 
4 #include "driver.h"
5 #include "vidhrdw/generic.h"
6 
7 
8 data32_t *macrossp_scra_videoram, *macrossp_scra_videoregs;
9 data32_t *macrossp_scrb_videoram, *macrossp_scrb_videoregs;
10 data32_t *macrossp_scrc_videoram, *macrossp_scrc_videoregs;
11 data32_t *macrossp_text_videoram, *macrossp_text_videoregs;
12 data32_t *macrossp_spriteram;
13 
14 static data32_t *spriteram_old,*spriteram_old2;
15 
16 static struct tilemap  *macrossp_scra_tilemap, *macrossp_scrb_tilemap,*macrossp_scrc_tilemap, *macrossp_text_tilemap;
17 
18 
19 /*** SCR A LAYER ***/
20 
WRITE32_HANDLER(macrossp_scra_videoram_w)21 WRITE32_HANDLER( macrossp_scra_videoram_w )
22 {
23 	COMBINE_DATA(&macrossp_scra_videoram[offset]);
24 
25 	tilemap_mark_tile_dirty(macrossp_scra_tilemap,offset);
26 }
27 
28 
get_macrossp_scra_tile_info(int tile_index)29 static void get_macrossp_scra_tile_info(int tile_index)
30 {
31 	UINT32 attr,tileno,color;
32 
33 	attr = macrossp_scra_videoram[tile_index];
34 	tileno = attr & 0x0000ffff;
35 
36 	switch (macrossp_scra_videoregs[0] & 0x00000c00)
37 	{
38 		case 0x00000800:
39 			color = (attr & 0x000e0000) >> 15;
40 			break;
41 
42 		case 0x00000400:
43 			color = (attr & 0x003e0000) >> 17;
44 			break;
45 
46 		default:
47 			color = rand() & 7;
48 			break;
49 	}
50 
51 	SET_TILE_INFO(1,tileno,color,TILE_FLIPYX((attr & 0xc0000000) >> 30))
52 }
53 
54 /*** SCR B LAYER ***/
55 
WRITE32_HANDLER(macrossp_scrb_videoram_w)56 WRITE32_HANDLER( macrossp_scrb_videoram_w )
57 {
58 	COMBINE_DATA(&macrossp_scrb_videoram[offset]);
59 
60 	tilemap_mark_tile_dirty(macrossp_scrb_tilemap,offset);
61 }
62 
63 
get_macrossp_scrb_tile_info(int tile_index)64 static void get_macrossp_scrb_tile_info(int tile_index)
65 {
66 	UINT32 attr,tileno,color;
67 
68 	attr = macrossp_scrb_videoram[tile_index];
69 	tileno = attr & 0x0000ffff;
70 
71 	switch (macrossp_scrb_videoregs[0] & 0x00000c00)
72 	{
73 		case 0x00000800:
74 			color = (attr & 0x000e0000) >> 15;
75 			break;
76 
77 		case 0x00000400:
78 			color = (attr & 0x003e0000) >> 17;
79 			break;
80 
81 		default:
82 			color = rand() & 7;
83 			break;
84 	}
85 
86 	SET_TILE_INFO(2,tileno,color,TILE_FLIPYX((attr & 0xc0000000) >> 30))
87 }
88 
89 /*** SCR C LAYER ***/
90 
WRITE32_HANDLER(macrossp_scrc_videoram_w)91 WRITE32_HANDLER( macrossp_scrc_videoram_w )
92 {
93 	COMBINE_DATA(&macrossp_scrc_videoram[offset]);
94 
95 	tilemap_mark_tile_dirty(macrossp_scrc_tilemap,offset);
96 }
97 
98 
get_macrossp_scrc_tile_info(int tile_index)99 static void get_macrossp_scrc_tile_info(int tile_index)
100 {
101 	UINT32 attr,tileno,color;
102 
103 	attr = macrossp_scrc_videoram[tile_index];
104 	tileno = attr & 0x0000ffff;
105 
106 	switch (macrossp_scrc_videoregs[0] & 0x00000c00)
107 	{
108 		case 0x00000800:
109 			color = (attr & 0x000e0000) >> 15;
110 			break;
111 
112 		case 0x00000400:
113 			color = (attr & 0x003e0000) >> 17;
114 			break;
115 
116 		default:
117 			color = rand() & 7;
118 			break;
119 	}
120 
121 	SET_TILE_INFO(3,tileno,color,TILE_FLIPYX((attr & 0xc0000000) >> 30))
122 }
123 
124 /*** TEXT LAYER ***/
125 
WRITE32_HANDLER(macrossp_text_videoram_w)126 WRITE32_HANDLER( macrossp_text_videoram_w )
127 {
128 	COMBINE_DATA(&macrossp_text_videoram[offset]);
129 
130 	tilemap_mark_tile_dirty(macrossp_text_tilemap,offset);
131 }
132 
133 
get_macrossp_text_tile_info(int tile_index)134 static void get_macrossp_text_tile_info(int tile_index)
135 {
136 	UINT32 tileno, colour;
137 
138 	tileno = macrossp_text_videoram[tile_index] & 0x0000ffff;
139 	colour = (macrossp_text_videoram[tile_index] & 0x00fe0000) >> 17;
140 
141 	SET_TILE_INFO(4,tileno,colour,0)
142 }
143 
144 
145 
146 /*** VIDEO START / UPDATE ***/
147 
VIDEO_START(macrossp)148 VIDEO_START(macrossp)
149 {
150 	spriteram_old = auto_malloc(spriteram_size);
151 	spriteram_old2 = auto_malloc(spriteram_size);
152 
153 	if (!spriteram_old || !spriteram_old2)
154 		return 1;
155 
156 	memset(spriteram_old,0,spriteram_size);
157 	memset(spriteram_old2,0,spriteram_size);
158 
159 	macrossp_text_tilemap = tilemap_create(get_macrossp_text_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,64);
160 	macrossp_scra_tilemap = tilemap_create(get_macrossp_scra_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,64);
161 	macrossp_scrb_tilemap = tilemap_create(get_macrossp_scrb_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,64);
162 	macrossp_scrc_tilemap = tilemap_create(get_macrossp_scrc_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,64);
163 
164 	if (!macrossp_text_tilemap || !macrossp_scra_tilemap || !macrossp_scrb_tilemap || !macrossp_scrc_tilemap)
165 		return 1;
166 
167 	tilemap_set_transparent_pen(macrossp_text_tilemap,0);
168 	tilemap_set_transparent_pen(macrossp_scra_tilemap,0);
169 	tilemap_set_transparent_pen(macrossp_scrb_tilemap,0);
170 	tilemap_set_transparent_pen(macrossp_scrc_tilemap,0);
171 
172 	Machine->gfx[0]->color_granularity=64;
173 	Machine->gfx[1]->color_granularity=64;
174 	Machine->gfx[2]->color_granularity=64;
175 	Machine->gfx[3]->color_granularity=64;
176 
177 	alpha_set_level(0x80); /* guess */
178 
179 	return 0;
180 }
181 
182 
183 
macrossp_drawsprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int priority)184 static void macrossp_drawsprites( struct mame_bitmap *bitmap, const struct rectangle *cliprect, int priority )
185 {
186 	const struct GfxElement *gfx = Machine->gfx[0];
187 /*	data32_t *source = macrossp_spriteram;*/
188 	data32_t *source = spriteram_old2; /* buffers by two frames */
189 	data32_t *finish = source + spriteram_size/4;
190 
191 
192 	while( source<finish )
193 	{
194 
195 		/*
196 
197 		 --hh hhyy yyyy yyyy   CCww wwxx xxxx xxxx
198 
199 		 ---- --zz zzzz zzzz   ---- --ZZ ZZZZ ZZZZ
200 
201 		 fFa- pp-- cccc c---   tttt tttt tttt tttt
202 
203 		 */
204 
205 
206 		int wide = (source[0] & 0x00003c00) >> 10;
207 		int high = (source[0] & 0x3c000000) >> 26;
208 
209 		int xpos = (source[0] & 0x000003ff) >> 0;
210 		int ypos = (source[0] & 0x03ff0000) >> 16;
211 
212 		int xzoom = (source[1] & 0x000003ff) >> 0; /* 0x100 is zoom factor of 1.0 */
213 		int yzoom = (source[1] & 0x03ff0000) >> 16;
214 
215 		int col;
216 		int tileno = (source[2] & 0x0000ffff) >> 0;
217 
218 		int flipx = (source[2] & 0x40000000) >> 30;
219 		int flipy = (source[2] & 0x80000000) >> 31;
220 
221 		int trans = (source[2] & 0x20000000)?TRANSPARENCY_ALPHA:TRANSPARENCY_PEN; /* alpha blending enable? */
222 
223 		int loopno = 0;
224 
225 		int xcnt,ycnt;
226 		int xoffset,yoffset;
227 
228 		int pri = (source[2] & 0x0c000000) >> 26;
229 
230 		if (pri == priority)
231 		{
232 			switch (source[0] & 0x0000c000)
233 			{
234 				case 0x00008000:
235 					col = (source[2] & 0x00380000) >> 17;
236 					break;
237 
238 				case 0x00004000:
239 					col = (source[2] & 0x00f80000) >> 19;
240 					break;
241 
242 				default:
243 					col = rand();
244 					break;
245 			}
246 
247 
248 			if (xpos > 0x1ff) xpos -=0x400;
249 			if (ypos > 0x1ff) ypos -=0x400;
250 
251 			if (!flipx) {
252 				if (!flipy) { /* noxflip, noyflip */
253 					yoffset = 0; /* I'm doing this so rounding errors are cumulative, still looks a touch crappy when multiple sprites used together */
254 					for (ycnt = 0; ycnt <= high; ycnt++) {
255 						xoffset = 0;
256 						for (xcnt = 0; xcnt <= wide; xcnt++) {
257 							drawgfxzoom(bitmap,gfx,tileno+loopno,col,flipx,flipy,xpos+xoffset,ypos+yoffset,cliprect,trans,0,xzoom*0x100,yzoom*0x100);
258 
259 							xoffset += ((xzoom*16 + (1<<7)) >> 8);
260 							loopno++;
261 						}
262 						yoffset += ((yzoom*16 + (1<<7)) >> 8);
263 					}
264 				}else{ /* noxflip, flipy */
265 					yoffset = ((high*yzoom*16) >> 8);
266 					for (ycnt = high; ycnt >= 0; ycnt--) {
267 						xoffset = 0;
268 						for (xcnt = 0; xcnt <= wide; xcnt++) {
269 							drawgfxzoom(bitmap,gfx,tileno+loopno,col,flipx,flipy,xpos+xoffset,ypos+yoffset,cliprect,trans,0,xzoom*0x100,yzoom*0x100);
270 
271 							xoffset += ((xzoom*16 + (1<<7)) >> 8);
272 							loopno++;
273 						}
274 						yoffset -= ((yzoom*16 + (1<<7)) >> 8);
275 					}
276 				}
277 			}else{
278 				if (!flipy) { /* xflip, noyflip */
279 					yoffset = 0;
280 					for (ycnt = 0; ycnt <= high; ycnt++) {
281 						xoffset = ((wide*xzoom*16) >> 8);
282 						for (xcnt = wide; xcnt >= 0; xcnt--) {
283 							drawgfxzoom(bitmap,gfx,tileno+loopno,col,flipx,flipy,xpos+xoffset,ypos+yoffset,cliprect,trans,0,xzoom*0x100,yzoom*0x100);
284 
285 							xoffset -= ((xzoom*16 + (1<<7)) >> 8);
286 							loopno++;
287 						}
288 						yoffset += ((yzoom*16 + (1<<7)) >> 8);
289 					}
290 				}else{ /* xflip, yflip */
291 					yoffset = ((high*yzoom*16) >> 8);
292 					for (ycnt = high; ycnt >= 0; ycnt--) {
293 						xoffset = ((wide*xzoom*16) >> 8);
294 						for (xcnt = wide; xcnt >=0 ; xcnt--) {
295 							drawgfxzoom(bitmap,gfx,tileno+loopno,col,flipx,flipy,xpos+xoffset,ypos+yoffset,cliprect,trans,0,xzoom*0x100,yzoom*0x100);
296 
297 							xoffset -= ((xzoom*16 + (1<<7)) >> 8);
298 							loopno++;
299 						}
300 						yoffset -= ((yzoom*16 + (1<<7)) >> 8);
301 					}
302 				}
303 			}
304 		}
305 		source += 3;
306 	}
307 }
308 
309 
draw_layer(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int layer)310 static void draw_layer(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int layer)
311 {
312 	struct tilemap *tm;
313 	data32_t *vr;
314 
315 	switch (layer)
316 	{
317 		case 0:
318 		default:
319 			tm = macrossp_scra_tilemap;
320 			vr = macrossp_scra_videoregs;
321 			break;
322 
323 		case 1:
324 			tm = macrossp_scrb_tilemap;
325 			vr = macrossp_scrb_videoregs;
326 			break;
327 
328 		case 2:
329 			tm = macrossp_scrc_tilemap;
330 			vr = macrossp_scrc_videoregs;
331 			break;
332 	}
333 
334 	if ((vr[2] & 0xf0000000) == 0xe0000000)	/* zoom enable (guess, surely wrong) */
335 	{
336 		int startx,starty,inc;
337 
338 		startx = (vr[1] & 0x0000ffff) << 16;
339 		starty = (vr[1] & 0xffff0000) >> 0;
340 		inc = (vr[2] & 0x00ff0000) >> 6,
341 
342 		/* WRONG! */
343 		/* scroll register contain position relative to the center of the screen, so adjust */
344 		startx -= (368/2) * inc;
345 		starty -= (240/2) * inc;
346 
347 		tilemap_draw_roz(bitmap,cliprect,tm,
348 				startx,starty,inc,0,0,inc,
349 				1,	/* wraparound */
350 				0,0);
351 	}
352 	else
353 	{
354 		tilemap_set_scrollx( tm, 0, ((vr[0] & 0x000003ff) >> 0 ) );
355 		tilemap_set_scrolly( tm, 0, ((vr[0] & 0x03ff0000) >> 16) );
356 		tilemap_draw(bitmap,cliprect,tm,0,0);
357 	}
358 }
359 
360 /* useful function to sort the three tile layers by priority order */
sortlayers(int * layer,int * pri)361 static void sortlayers(int *layer,int *pri)
362 {
363 #define SWAP(a,b) \
364 	if (pri[a] >= pri[b]) \
365 	{ \
366 		int t; \
367 		t = pri[a]; pri[a] = pri[b]; pri[b] = t; \
368 		t = layer[a]; layer[a] = layer[b]; layer[b] = t; \
369 	}
370 
371 	SWAP(0,1)
372 	SWAP(0,2)
373 	SWAP(1,2)
374 }
375 
VIDEO_UPDATE(macrossp)376 VIDEO_UPDATE(macrossp)
377 {
378 	int layers[3],layerpri[3];
379 
380 
381 	fillbitmap(bitmap,get_black_pen(),cliprect);
382 
383 	layers[0] = 0;
384 	layerpri[0] = (macrossp_scra_videoregs[0] & 0x0000c000) >> 14;
385 	layers[1] = 1;
386 	layerpri[1] = (macrossp_scrb_videoregs[0] & 0x0000c000) >> 14;
387 	layers[2] = 2;
388 	layerpri[2] = (macrossp_scrc_videoregs[0] & 0x0000c000) >> 14;
389 
390 	sortlayers(layers, layerpri);
391 
392 	draw_layer(bitmap,cliprect,layers[0]);
393 	macrossp_drawsprites(bitmap,cliprect,0);
394 	draw_layer(bitmap,cliprect,layers[1]);
395 	macrossp_drawsprites(bitmap,cliprect,1);
396 	draw_layer(bitmap,cliprect,layers[2]);
397 	macrossp_drawsprites(bitmap,cliprect,2);
398 	macrossp_drawsprites(bitmap,cliprect,3);
399 	tilemap_draw(bitmap,cliprect,macrossp_text_tilemap,0,0);
400 
401 #if 0
402 usrintf_showmessage	("scra - %08x %08x %08x\nscrb - %08x %08x %08x\nscrc - %08x %08x %08x",
403 macrossp_scra_videoregs[0]&0xffff33ff, /* yyyyxxxx*/
404 macrossp_scra_videoregs[1], /* ??? more scrolling?*/
405 macrossp_scra_videoregs[2], /* 08 - 0b*/
406 
407 macrossp_scrb_videoregs[0]&0xffff33ff, /* 00 - 03*/
408 macrossp_scrb_videoregs[1], /* 04 - 07*/
409 macrossp_scrb_videoregs[2], /* 08 - 0b*/
410 
411 macrossp_scrc_videoregs[0]&0xffff33ff, /* 00 - 03*/
412 macrossp_scrc_videoregs[1], /* 04 - 07*/
413 macrossp_scrc_videoregs[2]);/* 08 - 0b*/
414 #endif
415 }
416 
VIDEO_EOF(macrossp)417 VIDEO_EOF( macrossp )
418 {
419 	/* looks like sprites are *two* frames ahead, like nmk16 */
420 	memcpy(spriteram_old2,spriteram_old,spriteram_size);
421 	memcpy(spriteram_old,macrossp_spriteram,spriteram_size);
422 }
423