1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont, Phil Stroffolino, Acho A. Tang, Nicola Salmoria
3 #define MW_VERBOSE 0
4 
5 /*
6  * video/mystwarr.c - Konami "Pre-GX" video hardware (here there be dragons)
7  *
8  */
9 
10 #include "emu.h"
11 #include "includes/konamigx.h"
12 #include "includes/mystwarr.h"
13 
14 
15 // create a decoding buffer to hold decodable tiles so that the ROM test will pass by
16 // reading the original raw data
decode_tiles()17 void mystwarr_state::decode_tiles()
18 {
19 	uint8_t *s = memregion("k056832")->base();
20 	int len = memregion("k056832")->bytes();
21 	uint8_t *pFinish = s+len-3;
22 	uint8_t *d;
23 
24 	int gfxnum = m_k056832->get_gfx_num();
25 
26 	m_decoded = std::make_unique<uint8_t[]>(len);
27 	d = m_decoded.get();
28 
29 	// now convert the data into a drawable format so we can decode it
30 	while (s < pFinish)
31 	{
32 		/* convert the whole mess to 5bpp planar in System GX's format
33 		       (p3 p1 p2 p0 p5)
34 		       (the original ROMs are stored as chunky for the first 4 bits
35 		       and the 5th bit is planar, which is undecodable as-is) */
36 		int d0 = ((s[0]&0x80)   )|((s[0]&0x08)<<3)|((s[1]&0x80)>>2)|((s[1]&0x08)<<1)|
37 					((s[2]&0x80)>>4)|((s[2]&0x08)>>1)|((s[3]&0x80)>>6)|((s[3]&0x08)>>3);
38 		int d1 = ((s[0]&0x40)<<1)|((s[0]&0x04)<<4)|((s[1]&0x40)>>1)|((s[1]&0x04)<<2)|
39 					((s[2]&0x40)>>3)|((s[2]&0x04)   )|((s[3]&0x40)>>5)|((s[3]&0x04)>>2);
40 		int d2 = ((s[0]&0x20)<<2)|((s[0]&0x02)<<5)|((s[1]&0x20)   )|((s[1]&0x02)<<3)|
41 					((s[2]&0x20)>>2)|((s[2]&0x02)<<1)|((s[3]&0x20)>>4)|((s[3]&0x02)>>1);
42 		int d3 = ((s[0]&0x10)<<3)|((s[0]&0x01)<<6)|((s[1]&0x10)<<1)|((s[1]&0x01)<<4)|
43 					((s[2]&0x10)>>1)|((s[2]&0x01)<<2)|((s[3]&0x10)>>3)|((s[3]&0x01)   );
44 
45 		d[0] = d3;
46 		d[1] = d1;
47 		d[2] = d2;
48 		d[3] = d0;
49 		d[4] = s[4];
50 
51 		s += 5;
52 		d += 5;
53 	}
54 
55 	m_k056832->gfx(gfxnum)->set_source(m_decoded.get());
56 }
57 
58 
59 // Mystic Warriors requires tile based blending.
K056832_CB_MEMBER(mystwarr_state::mystwarr_tile_callback)60 K056832_CB_MEMBER(mystwarr_state::mystwarr_tile_callback)
61 {
62 	if (layer == 1) {if ((*code & 0xff00) + (*color) == 0x4101) m_cbparam++; else m_cbparam--;} //* water hack (TEMPORARY)
63 	*color = m_layer_colorbase[layer] | (*color >> 1 & 0x1e);
64 }
65 
66 // for games with 5bpp tile data
K056832_CB_MEMBER(mystwarr_state::game5bpp_tile_callback)67 K056832_CB_MEMBER(mystwarr_state::game5bpp_tile_callback)
68 {
69 	*color = m_layer_colorbase[layer] | (*color >> 1 & 0x1e);
70 }
71 
72 // for games with 4bpp tile data
K056832_CB_MEMBER(mystwarr_state::game4bpp_tile_callback)73 K056832_CB_MEMBER(mystwarr_state::game4bpp_tile_callback)
74 {
75 	*color = m_layer_colorbase[layer] | (*color >> 2 & 0x0f);
76 }
77 
K055673_CB_MEMBER(mystwarr_state::mystwarr_sprite_callback)78 K055673_CB_MEMBER(mystwarr_state::mystwarr_sprite_callback)
79 {
80 	int c = *color;
81 	*color = m_sprite_colorbase | (c & 0x001f);
82 	*priority_mask = c & 0x00f0;
83 }
84 
K055673_CB_MEMBER(mystwarr_state::metamrph_sprite_callback)85 K055673_CB_MEMBER(mystwarr_state::metamrph_sprite_callback)
86 {
87 	int c = *color;
88 	int attr = c;
89 
90 	c = (c & 0x1f) | m_sprite_colorbase;
91 
92 	// Bit8 & 9 are effect attributes. It is not known whether the effects are generated by external logic.
93 	if ((attr & 0x300) != 0x300)
94 	{
95 		*color = c;
96 		*priority_mask = (attr & 0xe0) >> 2;
97 	}
98 	else
99 	{
100 		*color = c | 3<<K055555_MIXSHIFT | K055555_SKIPSHADOW; // reflection?
101 		*priority_mask = 0x1c;
102 	}
103 }
104 
K055673_CB_MEMBER(mystwarr_state::gaiapols_sprite_callback)105 K055673_CB_MEMBER(mystwarr_state::gaiapols_sprite_callback)
106 {
107 	int c = *color;
108 
109 	*color = m_sprite_colorbase | (c>>4 & 0x20) | (c & 0x001f);
110 	*priority_mask = c & 0x00e0;
111 }
112 
K055673_CB_MEMBER(mystwarr_state::martchmp_sprite_callback)113 K055673_CB_MEMBER(mystwarr_state::martchmp_sprite_callback)
114 {
115 	int c = *color;
116 
117 	// Bit8 & 9 are effect attributes. It is not known whether the effects are generated by external logic.
118 	if ((c & 0x3ff) == 0x11f)
119 		*color = K055555_FULLSHADOW;
120 	else
121 		*color = m_sprite_colorbase | (c & 0x1f);
122 
123 	if (m_oinprion & 0xf0)
124 		*priority_mask = m_cbparam;  // use PCU2 internal priority
125 	else
126 		*priority_mask = c & 0xf0; // use color implied priority
127 }
128 
129 
130 
TILE_GET_INFO_MEMBER(mystwarr_state::get_gai_936_tile_info)131 TILE_GET_INFO_MEMBER(mystwarr_state::get_gai_936_tile_info)
132 {
133 	int tileno, colour;
134 	uint8_t *ROM = memregion("gfx4")->base();
135 	uint8_t *dat1 = ROM, *dat2 = ROM + 0x20000, *dat3 = ROM + 0x60000;
136 
137 	tileno = dat3[tile_index] | ((dat2[tile_index]&0x3f)<<8);
138 
139 	if (tile_index & 1)
140 		colour = (dat1[tile_index>>1]&0xf);
141 	else
142 		colour = ((dat1[tile_index>>1]>>4)&0xf);
143 
144 	if (dat2[tile_index] & 0x80) colour |= 0x10;
145 
146 	colour |= m_sub1_colorbase << 4;
147 
148 	tileinfo.set(0, tileno, colour, 0);
149 }
150 
VIDEO_START_MEMBER(mystwarr_state,gaiapols)151 VIDEO_START_MEMBER(mystwarr_state, gaiapols)
152 {
153 	m_gametype = 0;
154 
155 	decode_tiles();
156 
157 	konamigx_mixer_init(*m_screen, 0);
158 
159 	m_k056832->set_layer_offs(0, -2+2-1, 0-1);
160 	m_k056832->set_layer_offs(1,  0+2, 0);
161 	m_k056832->set_layer_offs(2,  2+2, 0);
162 	m_k056832->set_layer_offs(3,  3+2, 0);
163 
164 	K053936_wraparound_enable(0, 1);
165 	K053936GP_set_offset(0, -10,  0); // floor tiles in demo loop2 (Elaine vs. boss)
166 
167 	m_ult_936_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(mystwarr_state::get_gai_936_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 512, 512);
168 	m_ult_936_tilemap->set_transparent_pen(0);
169 }
170 
TILE_GET_INFO_MEMBER(mystwarr_state::get_ult_936_tile_info)171 TILE_GET_INFO_MEMBER(mystwarr_state::get_ult_936_tile_info)
172 {
173 	int tileno, colour;
174 	uint8_t *ROM = memregion("gfx4")->base();
175 	uint8_t *dat1 = ROM, *dat2 = ROM + 0x40000;
176 
177 	tileno = dat2[tile_index] | ((dat1[tile_index]&0x1f)<<8);
178 
179 	colour = m_sub1_colorbase;
180 
181 	tileinfo.set(0, tileno, colour, (dat1[tile_index]&0x40) ? TILE_FLIPX : 0);
182 }
183 
VIDEO_START_MEMBER(mystwarr_state,dadandrn)184 VIDEO_START_MEMBER(mystwarr_state, dadandrn)
185 {
186 	m_gametype = 1;
187 
188 	decode_tiles();
189 
190 	konamigx_mixer_init(*m_screen, 0);
191 
192 	konamigx_mixer_primode(1);
193 
194 	m_k056832->set_layer_offs(0, -2+4, 0);
195 	m_k056832->set_layer_offs(1,  0+4, 0);
196 	m_k056832->set_layer_offs(2,  2+4, 0);
197 	m_k056832->set_layer_offs(3,  3+4, 0);
198 
199 	K053936_wraparound_enable(0, 1);
200 	K053936GP_set_offset(0, -8, 0); // Brainy's laser
201 
202 	m_ult_936_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(mystwarr_state::get_ult_936_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 512, 512);
203 	m_ult_936_tilemap->set_transparent_pen(0);
204 }
205 
VIDEO_START_MEMBER(mystwarr_state,mystwarr)206 VIDEO_START_MEMBER(mystwarr_state, mystwarr)
207 {
208 	m_gametype = 0;
209 
210 	decode_tiles();
211 
212 	konamigx_mixer_init(*m_screen, 0);
213 
214 	m_k056832->set_layer_offs(0, -2-3, 0);
215 	m_k056832->set_layer_offs(1,  0-3, 0);
216 	m_k056832->set_layer_offs(2,  2-3, 0);
217 	m_k056832->set_layer_offs(3,  3-3, 0);
218 
219 	m_cbparam = 0;
220 }
221 
VIDEO_START_MEMBER(mystwarr_state,metamrph)222 VIDEO_START_MEMBER(mystwarr_state, metamrph)
223 {
224 	m_gametype = 0;
225 
226 	decode_tiles();
227 
228 	konamigx_mixer_init(*m_screen, 0);
229 
230 	// other reference, floor at first boss
231 	m_k056832->set_layer_offs(0, -2+4, 0); // text
232 	m_k056832->set_layer_offs(1,  0+4, 0); // attract sea
233 	m_k056832->set_layer_offs(2,  2+4, 0); // attract red monster in background of sea
234 	m_k056832->set_layer_offs(3,  3+4, 0); // attract sky background to sea
235 }
236 
VIDEO_START_MEMBER(mystwarr_state,viostorm)237 VIDEO_START_MEMBER(mystwarr_state, viostorm)
238 {
239 	m_gametype = 0;
240 
241 	decode_tiles();
242 
243 	konamigx_mixer_init(*m_screen, 0);
244 
245 	m_k056832->set_layer_offs(0, -2+1, 0);
246 	m_k056832->set_layer_offs(1,  0+1, 0);
247 	m_k056832->set_layer_offs(2,  2+1, 0);
248 	m_k056832->set_layer_offs(3,  3+1, 0);
249 }
250 
VIDEO_START_MEMBER(mystwarr_state,martchmp)251 VIDEO_START_MEMBER(mystwarr_state, martchmp)
252 {
253 	m_gametype = 0;
254 
255 	decode_tiles();
256 
257 	konamigx_mixer_init(*m_screen, 0);
258 
259 	m_k056832->set_layer_offs(0, -2-4, 0);
260 	m_k056832->set_layer_offs(1,  0-4, 0);
261 	m_k056832->set_layer_offs(2,  2-4, 0);
262 	m_k056832->set_layer_offs(3,  3-4, 0);
263 
264 	m_k054338->invert_alpha(0);
265 }
266 
267 
268 
screen_update_mystwarr(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)269 uint32_t mystwarr_state::screen_update_mystwarr(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
270 {
271 	int i, old, blendmode=0;
272 
273 	if (m_cbparam<0) m_cbparam=0; else if (m_cbparam>=32) blendmode=(1<<16|GXMIX_BLEND_FORCE)<<2; //* water hack (TEMPORARY)
274 
275 	for (i = 0; i < 4; i++)
276 	{
277 		old = m_layer_colorbase[i];
278 		m_layer_colorbase[i] = m_k055555->K055555_get_palette_index(i)<<4;
279 		if( old != m_layer_colorbase[i] ) m_k056832->mark_plane_dirty(i);
280 	}
281 
282 	m_sprite_colorbase = m_k055555->K055555_get_palette_index(4)<<5;
283 
284 	konamigx_mixer(screen, bitmap, cliprect, nullptr, 0, nullptr, 0, blendmode, nullptr, 0);
285 	return 0;
286 }
287 
screen_update_metamrph(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)288 uint32_t mystwarr_state::screen_update_metamrph(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
289 {
290 	int i, old;
291 
292 	for (i = 0; i < 4; i++)
293 	{
294 		old = m_layer_colorbase[i];
295 		m_layer_colorbase[i] = m_k055555->K055555_get_palette_index(i)<<4;
296 		if (old != m_layer_colorbase[i]) m_k056832->mark_plane_dirty(i);
297 	}
298 
299 	m_sprite_colorbase = m_k055555->K055555_get_palette_index(4)<<4;
300 
301 	konamigx_mixer(screen, bitmap, cliprect, nullptr, GXSUB_K053250 | GXSUB_4BPP, nullptr, 0, 0, nullptr, 0);
302 	return 0;
303 }
304 
screen_update_martchmp(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)305 uint32_t mystwarr_state::screen_update_martchmp(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
306 {
307 	int i, old, blendmode;
308 
309 	for (i = 0; i < 4; i++)
310 	{
311 		old = m_layer_colorbase[i];
312 		m_layer_colorbase[i] = m_k055555->K055555_get_palette_index(i)<<4;
313 		if (old != m_layer_colorbase[i]) m_k056832->mark_plane_dirty(i);
314 	}
315 
316 	m_sprite_colorbase = m_k055555->K055555_get_palette_index(4)<<5;
317 
318 	m_cbparam = m_k055555->K055555_read_register(K55_PRIINP_8);
319 	m_oinprion = m_k055555->K055555_read_register(K55_OINPRI_ON);
320 
321 	// not quite right
322 	blendmode = (m_oinprion==0xef && m_k054338->register_r(K338_REG_PBLEND)) ? ((1<<16|GXMIX_BLEND_FORCE)<<2) : 0;
323 
324 	konamigx_mixer(screen, bitmap, cliprect, nullptr, 0, nullptr, 0, blendmode, nullptr, 0);
325 	return 0;
326 }
327 
328 
329 
ddd_053936_enable_w(offs_t offset,uint16_t data,uint16_t mem_mask)330 void mystwarr_state::ddd_053936_enable_w(offs_t offset, uint16_t data, uint16_t mem_mask)
331 {
332 	if (ACCESSING_BITS_8_15)
333 	{
334 		m_roz_enable = data & 0x0100;
335 		m_roz_rombank = (data & 0xc000)>>14;
336 	}
337 }
338 
ddd_053936_clip_w(offs_t offset,uint16_t data,uint16_t mem_mask)339 void mystwarr_state::ddd_053936_clip_w(offs_t offset, uint16_t data, uint16_t mem_mask)
340 {
341 	int old, clip_x, clip_y, size_x, size_y;
342 	int minx, maxx, miny, maxy;
343 
344 	if (offset == 1)
345 	{
346 		if (ACCESSING_BITS_8_15) K053936GP_clip_enable(0, data & 0x0100);
347 	}
348 	else
349 	{
350 		old = m_clip;
351 		COMBINE_DATA(&m_clip);
352 		if (m_clip != old)
353 		{
354 			clip_x = (m_clip & 0x003f) >> 0;
355 			clip_y = (m_clip & 0x0fc0) >> 6;
356 			size_x = (m_clip & 0x3000) >> 12;
357 			size_y = (m_clip & 0xc000) >> 14;
358 
359 			switch (size_x)
360 			{
361 				case 0x3: size_x = 1; break;
362 				case 0x2: size_x = 2; break;
363 				default:  size_x = 4; break;
364 			}
365 
366 			switch (size_y)
367 			{
368 				case 0x3: size_y = 1; break;
369 				case 0x2: size_y = 2; break;
370 				default:  size_y = 4; break;
371 			}
372 
373 			minx = clip_x << 7;
374 			maxx = ((clip_x + size_x) << 7) - 1;
375 			miny = clip_y << 7;
376 			maxy = ((clip_y + size_y) << 7) - 1;
377 
378 			K053936GP_set_cliprect(0, minx, maxx, miny, maxy);
379 		}
380 	}
381 }
382 
383 // reference: 223e5c in gaiapolis (ROMs 34j and 36m)
gai_053936_tilerom_0_r(offs_t offset)384 uint16_t mystwarr_state::gai_053936_tilerom_0_r(offs_t offset)
385 {
386 	uint8_t *ROM1 = (uint8_t *)memregion("gfx4")->base();
387 	uint8_t *ROM2 = (uint8_t *)memregion("gfx4")->base();
388 
389 	ROM1 += 0x20000;
390 	ROM2 += 0x20000+0x40000;
391 
392 	return ((ROM1[offset]<<8) | ROM2[offset]);
393 }
394 
ddd_053936_tilerom_0_r(offs_t offset)395 uint16_t mystwarr_state::ddd_053936_tilerom_0_r(offs_t offset)
396 {
397 	uint8_t *ROM1 = (uint8_t *)memregion("gfx4")->base();
398 	uint8_t *ROM2 = (uint8_t *)memregion("gfx4")->base();
399 
400 	ROM2 += 0x40000;
401 
402 	return ((ROM1[offset]<<8) | ROM2[offset]);
403 }
404 
405 // reference: 223e1a in gaiapolis (ROM 36j)
ddd_053936_tilerom_1_r(offs_t offset)406 uint16_t mystwarr_state::ddd_053936_tilerom_1_r(offs_t offset)
407 {
408 	uint8_t *ROM = (uint8_t *)memregion("gfx4")->base();
409 
410 	return ROM[offset/2];
411 }
412 
413 // reference: 223db0 in gaiapolis (ROMs 32n, 29n, 26n)
gai_053936_tilerom_2_r(offs_t offset)414 uint16_t mystwarr_state::gai_053936_tilerom_2_r(offs_t offset)
415 {
416 	uint8_t *ROM = (uint8_t *)memregion("gfx3")->base();
417 
418 	offset += (m_roz_rombank * 0x100000);
419 
420 	return ROM[offset/2]<<8;
421 }
422 
ddd_053936_tilerom_2_r(offs_t offset)423 uint16_t mystwarr_state::ddd_053936_tilerom_2_r(offs_t offset)
424 {
425 	uint8_t *ROM = (uint8_t *)memregion("gfx3")->base();
426 
427 	offset += (m_roz_rombank * 0x100000);
428 
429 	return ROM[offset]<<8;
430 }
431 
screen_update_dadandrn(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)432 uint32_t mystwarr_state::screen_update_dadandrn(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)/* and gaiapols */
433 {
434 	int i, newbase, dirty, rozmode;
435 
436 	if (m_gametype == 0)
437 	{
438 		m_sprite_colorbase = (m_k055555->K055555_get_palette_index(4)<<4)&0x7f;
439 		rozmode = GXSUB_4BPP;
440 	}
441 	else
442 	{
443 		m_sprite_colorbase = (m_k055555->K055555_get_palette_index(4)<<3)&0x7f;
444 		rozmode = GXSUB_8BPP;
445 	}
446 
447 	if (m_k056832->get_layer_association())
448 	{
449 		for (i=0; i<4; i++)
450 		{
451 			newbase = m_k055555->K055555_get_palette_index(i)<<4;
452 			if (m_layer_colorbase[i] != newbase)
453 			{
454 				m_layer_colorbase[i] = newbase;
455 				m_k056832->mark_plane_dirty(i);
456 			}
457 		}
458 	}
459 	else
460 	{
461 		for (dirty=0, i=0; i<4; i++)
462 		{
463 			newbase = m_k055555->K055555_get_palette_index(i)<<4;
464 			if (m_layer_colorbase[i] != newbase)
465 			{
466 				m_layer_colorbase[i] = newbase;
467 				dirty = 1;
468 			}
469 		}
470 		if (dirty) m_k056832->mark_all_tilemaps_dirty();
471 
472 	}
473 
474 	m_last_psac_colorbase = m_sub1_colorbase;
475 	m_sub1_colorbase = m_k055555->K055555_get_palette_index(5);
476 
477 	if (m_last_psac_colorbase != m_sub1_colorbase)
478 	{
479 		m_ult_936_tilemap->mark_all_dirty();
480 
481 		if (MW_VERBOSE)
482 			popmessage("K053936: PSAC colorbase changed");
483 	}
484 
485 	konamigx_mixer(screen, bitmap, cliprect, (m_roz_enable) ? m_ult_936_tilemap : nullptr, rozmode, nullptr, 0, 0, nullptr, 0);
486 	return 0;
487 }
488