summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/mystwarr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/mystwarr.c')
-rw-r--r--src/mame/video/mystwarr.c555
1 files changed, 555 insertions, 0 deletions
diff --git a/src/mame/video/mystwarr.c b/src/mame/video/mystwarr.c
new file mode 100644
index 00000000000..7fb14946d40
--- /dev/null
+++ b/src/mame/video/mystwarr.c
@@ -0,0 +1,555 @@
+#define MW_VERBOSE 0
+
+/*
+ * video/mystwarr.c - Konami "Pre-GX" video hardware (here there be dragons)
+ *
+ */
+
+#include "driver.h"
+#include "video/konamiic.h"
+#include "machine/konamigx.h"
+
+static int layer_colorbase[6];
+static int oinprion, cbparam;
+static int sprite_colorbase, sub1_colorbase, last_psac_colorbase, gametype;
+static int roz_enable, roz_rombank;
+static tilemap *ult_936_tilemap;
+static char *orig_roms;
+
+// do some trickery since we know the graphics decode doesn't touch the source data again
+// and we want the original data
+static void mystwarr_save_orig_tiles(void)
+{
+ UINT8 *s = memory_region(REGION_GFX1);
+ UINT8 *pFinish = s+memory_region_length(REGION_GFX1)-3;
+
+ orig_roms = malloc_or_die(memory_region_length(REGION_GFX1));
+ memcpy(orig_roms, s, memory_region_length(REGION_GFX1));
+
+ // now convert the data into a drawable format so we can decode it
+ while (s < pFinish)
+ {
+ /* convert the whole mess to 5bpp planar in System GX's format
+ (p3 p1 p2 p0 p5)
+ (the original ROMs are stored as chunky for the first 4 bits
+ and the 5th bit is planar, which is undecodable as-is) */
+ int d0 = ((s[0]&0x80) )|((s[0]&0x08)<<3)|((s[1]&0x80)>>2)|((s[1]&0x08)<<1)|
+ ((s[2]&0x80)>>4)|((s[2]&0x08)>>1)|((s[3]&0x80)>>6)|((s[3]&0x08)>>3);
+ int d1 = ((s[0]&0x40)<<1)|((s[0]&0x04)<<4)|((s[1]&0x40)>>1)|((s[1]&0x04)<<2)|
+ ((s[2]&0x40)>>3)|((s[2]&0x04) )|((s[3]&0x40)>>5)|((s[3]&0x04)>>2);
+ int d2 = ((s[0]&0x20)<<2)|((s[0]&0x02)<<5)|((s[1]&0x20) )|((s[1]&0x02)<<3)|
+ ((s[2]&0x20)>>2)|((s[2]&0x02)<<1)|((s[3]&0x20)>>4)|((s[3]&0x02)>>1);
+ int d3 = ((s[0]&0x10)<<3)|((s[0]&0x01)<<6)|((s[1]&0x10)<<1)|((s[1]&0x01)<<4)|
+ ((s[2]&0x10)>>1)|((s[2]&0x01)<<2)|((s[3]&0x10)>>3)|((s[3]&0x01) );
+
+ s[0] = d3;
+ s[1] = d1;
+ s[2] = d2;
+ s[3] = d0;
+
+ s += 5;
+ }
+}
+
+static void mystwarr_rest_orig_tiles(void)
+{
+ UINT8 *s = memory_region(REGION_GFX1);
+
+ // restore the original data so the ROM test can pass
+ memcpy(s, orig_roms, memory_region_length(REGION_GFX1));
+ free(orig_roms);
+}
+
+
+// Mystic Warriors requires tile based blending.
+static void mystwarr_tile_callback(int layer, int *code, int *color, int *flags)
+{
+ if (layer==1) {if ((*code&0xff00)+(*color)==0x4101) cbparam++; else cbparam--;} //* water hack (TEMPORARY)
+
+ *color = layer_colorbase[layer] | (*color>>1 & 0x1f);
+}
+
+// for games with 5bpp tile data
+static void game5bpp_tile_callback(int layer, int *code, int *color, int *flags)
+{
+ *color = layer_colorbase[layer] | (*color>>1 & 0x1f);
+}
+
+// for games with 4bpp tile data
+static void game4bpp_tile_callback(int layer, int *code, int *color, int *flags)
+{
+ *color = layer_colorbase[layer] | (*color>>2 & 0x0f);
+}
+
+static void mystwarr_sprite_callback(int *code, int *color, int *priority)
+{
+ int c = *color;
+
+ *color = sprite_colorbase | (c & 0x001f);
+ *priority = c & 0x00f0;
+}
+
+static void metamrph_sprite_callback(int *code, int *color, int *priority)
+{
+ int c = *color;
+ int attr = c;
+
+ c = (c & 0x1f) | sprite_colorbase;
+
+ // Bit8 & 9 are effect attributes. It is not known whether the effects are generated by external logic.
+ if ((attr & 0x300) != 0x300)
+ {
+ *color = c;
+ *priority = (attr & 0xe0) >> 2;
+ }
+ else
+ {
+ *color = c | 3<<K055555_MIXSHIFT | K055555_SKIPSHADOW; // reflection?
+ *priority = 0x1c;
+ }
+}
+
+static void gaiapols_sprite_callback(int *code, int *color, int *priority)
+{
+ int c = *color;
+
+ *color = sprite_colorbase | (c>>4 & 0x20) | (c & 0x001f);
+ *priority = c & 0x00e0;
+}
+
+static void martchmp_sprite_callback(int *code, int *color, int *priority)
+{
+ int c = *color;
+
+ // Bit8 & 9 are effect attributes. It is not known whether the effects are generated by external logic.
+ if ((c & 0x3ff) == 0x11f)
+ *color = K055555_FULLSHADOW;
+ else
+ *color = sprite_colorbase | (c & 0x1f);
+
+ if (oinprion & 0xf0)
+ *priority = cbparam; // use PCU2 internal priority
+ else
+ *priority = c & 0xf0; // use color implied priority
+}
+
+
+
+static TILE_GET_INFO( get_gai_936_tile_info )
+{
+ int tileno, colour;
+ UINT8 *ROM = memory_region(REGION_GFX4);
+ UINT8 *dat1 = ROM, *dat2 = ROM + 0x20000, *dat3 = ROM + 0x60000;
+
+ tileno = dat3[tile_index] | ((dat2[tile_index]&0x3f)<<8);
+
+ if (tile_index & 1)
+ colour = (dat1[tile_index>>1]&0xf);
+ else
+ colour = ((dat1[tile_index>>1]>>4)&0xf);
+
+ if (dat2[tile_index] & 0x80) colour |= 0x10;
+
+ colour |= sub1_colorbase << 4;
+
+ SET_TILE_INFO(0, tileno, colour, 0);
+}
+
+VIDEO_START(gaiapols)
+{
+ K055555_vh_start();
+ K054338_vh_start();
+
+ gametype = 0;
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, game4bpp_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 1, -61, -22, gaiapols_sprite_callback); // stage2 brick walls
+
+ konamigx_mixer_init(0);
+
+ K056832_set_LayerOffset(0, -2+2-1, 0-1);
+ K056832_set_LayerOffset(1, 0+2, 0);
+ K056832_set_LayerOffset(2, 2+2, 0);
+ K056832_set_LayerOffset(3, 3+2, 0);
+
+ K053936_wraparound_enable(0, 1);
+ K053936GP_set_offset(0, -10, 0); // floor tiles in demo loop2 (Elaine vs. boss)
+
+ ult_936_tilemap = tilemap_create(get_gai_936_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 16, 16, 512, 512);
+ tilemap_set_transparent_pen(ult_936_tilemap, 0);
+}
+
+static TILE_GET_INFO( get_ult_936_tile_info )
+{
+ int tileno, colour;
+ UINT8 *ROM = memory_region(REGION_GFX4);
+ UINT8 *dat1 = ROM, *dat2 = ROM + 0x40000;
+
+ tileno = dat2[tile_index] | ((dat1[tile_index]&0x1f)<<8);
+
+ colour = sub1_colorbase;
+
+ SET_TILE_INFO(0, tileno, colour, (dat1[tile_index]&0x40) ? TILE_FLIPX : 0);
+}
+
+VIDEO_START(dadandrn)
+{
+ K055555_vh_start();
+ K054338_vh_start();
+
+ gametype = 1;
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, game5bpp_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 0, -42, -22, gaiapols_sprite_callback);
+
+ konamigx_mixer_init(0);
+
+ konamigx_mixer_primode(1);
+
+ K056832_set_LayerOffset(0, -2+4, 0);
+ K056832_set_LayerOffset(1, 0+4, 0);
+ K056832_set_LayerOffset(2, 2+4, 0);
+ K056832_set_LayerOffset(3, 3+4, 0);
+
+ K053936_wraparound_enable(0, 1);
+ K053936GP_set_offset(0, -8, 0); // Brainy's laser
+
+ ult_936_tilemap = tilemap_create(get_ult_936_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 16, 16, 512, 512);
+ tilemap_set_transparent_pen(ult_936_tilemap, 0);
+}
+
+VIDEO_START(mystwarr)
+{
+ K055555_vh_start();
+ K054338_vh_start();
+
+ gametype = 0;
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, mystwarr_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 0, -48, -24, mystwarr_sprite_callback);
+
+ konamigx_mixer_init(0);
+
+ K056832_set_LayerOffset(0, -2-3, 0);
+ K056832_set_LayerOffset(1, 0-3, 0);
+ K056832_set_LayerOffset(2, 2-3, 0);
+ K056832_set_LayerOffset(3, 3-3, 0);
+
+ cbparam = 0;
+}
+
+VIDEO_START(metamrph)
+{
+ int rgn_250 = REGION_GFX3;
+
+ gametype = 0;
+
+ K055555_vh_start();
+ K054338_vh_start();
+ K053250_vh_start(1, &rgn_250);
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, game4bpp_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 1, -51, -22, metamrph_sprite_callback);
+
+ konamigx_mixer_init(0);
+
+ // other reference, floor at first boss
+ K056832_set_LayerOffset(0, -2+4, 0); // text
+ K056832_set_LayerOffset(1, 0+4, 0); // attract sea
+ K056832_set_LayerOffset(2, 2+4, 0); // attract red monster in background of sea
+ K056832_set_LayerOffset(3, 3+4, 0); // attract sky background to sea
+
+ K053250_set_LayerOffset(0, -7, 0);
+}
+
+VIDEO_START(viostorm)
+{
+ gametype = 0;
+
+ K055555_vh_start();
+ K054338_vh_start();
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, game4bpp_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 1, -62, -23, metamrph_sprite_callback);
+
+ konamigx_mixer_init(0);
+
+ K056832_set_LayerOffset(0, -2+1, 0);
+ K056832_set_LayerOffset(1, 0+1, 0);
+ K056832_set_LayerOffset(2, 2+1, 0);
+ K056832_set_LayerOffset(3, 3+1, 0);
+}
+
+VIDEO_START(martchmp)
+{
+ gametype = 0;
+
+ K055555_vh_start();
+ K054338_vh_start();
+
+ mystwarr_save_orig_tiles();
+
+ K056832_vh_start(machine, REGION_GFX1, K056832_BPP_5, 0, NULL, game5bpp_tile_callback, 0);
+
+ mystwarr_rest_orig_tiles();
+
+ K055673_vh_start(machine, REGION_GFX2, 0, -58, -23, martchmp_sprite_callback);
+
+ konamigx_mixer_init(0);
+
+ K056832_set_LayerOffset(0, -2-4, 0);
+ K056832_set_LayerOffset(1, 0-4, 0);
+ K056832_set_LayerOffset(2, 2-4, 0);
+ K056832_set_LayerOffset(3, 3-4, 0);
+
+ K054338_invert_alpha(0);
+}
+
+
+
+VIDEO_UPDATE(mystwarr)
+{
+ int i, old, blendmode=0;
+
+ if (cbparam<0) cbparam=0; else if (cbparam>=32) blendmode=(1<<16|GXMIX_BLEND_FORCE)<<2; //* water hack (TEMPORARY)
+
+ for (i = 0; i < 4; i++)
+ {
+ old = layer_colorbase[i];
+ layer_colorbase[i] = K055555_get_palette_index(i)<<4;
+ if( old != layer_colorbase[i] ) K056832_mark_plane_dirty(i);
+ }
+
+ sprite_colorbase = K055555_get_palette_index(4)<<5;
+
+ konamigx_mixer(machine, bitmap, cliprect, 0, 0, 0, 0, blendmode);
+ return 0;
+}
+
+VIDEO_UPDATE(metamrph)
+{
+ int i, old;
+
+ for (i = 0; i < 4; i++)
+ {
+ old = layer_colorbase[i];
+ layer_colorbase[i] = K055555_get_palette_index(i)<<4;
+ if (old != layer_colorbase[i]) K056832_mark_plane_dirty(i);
+ }
+
+ sprite_colorbase = K055555_get_palette_index(4)<<4;
+
+ konamigx_mixer(machine, bitmap, cliprect, 0, GXSUB_K053250 | GXSUB_4BPP, 0, 0, 0);
+ return 0;
+}
+
+VIDEO_UPDATE(martchmp)
+{
+ int i, old, blendmode;
+
+ for (i = 0; i < 4; i++)
+ {
+ old = layer_colorbase[i];
+ layer_colorbase[i] = K055555_get_palette_index(i)<<4;
+ if (old != layer_colorbase[i]) K056832_mark_plane_dirty(i);
+ }
+
+ sprite_colorbase = K055555_get_palette_index(4)<<5;
+
+ cbparam = K055555_read_register(K55_PRIINP_8);
+ oinprion = K055555_read_register(K55_OINPRI_ON);
+
+ // not quite right
+ blendmode = (oinprion==0xef && K054338_read_register(K338_REG_PBLEND)) ? ((1<<16|GXMIX_BLEND_FORCE)<<2) : 0;
+
+ konamigx_mixer(machine, bitmap, cliprect, 0, 0, 0, 0, blendmode);
+ return 0;
+}
+
+
+
+WRITE16_HANDLER(ddd_053936_enable_w)
+{
+ if (ACCESSING_MSB)
+ {
+ roz_enable = data & 0x0100;
+ roz_rombank = (data & 0xc000)>>14;
+ }
+}
+
+WRITE16_HANDLER(ddd_053936_clip_w)
+{
+ static UINT16 clip;
+ int old, clip_x, clip_y, size_x, size_y;
+ int minx, maxx, miny, maxy;
+
+ if (offset == 1)
+ {
+ if (ACCESSING_MSB) K053936GP_clip_enable(0, data & 0x0100);
+ }
+ else
+ {
+ old = clip;
+ COMBINE_DATA(&clip);
+ if (clip != old)
+ {
+ clip_x = (clip & 0x003f) >> 0;
+ clip_y = (clip & 0x0fc0) >> 6;
+ size_x = (clip & 0x3000) >> 12;
+ size_y = (clip & 0xc000) >> 14;
+
+ switch (size_x)
+ {
+ case 0x3: size_x = 1; break;
+ case 0x2: size_x = 2; break;
+ default: size_x = 4; break;
+ }
+
+ switch (size_y)
+ {
+ case 0x3: size_y = 1; break;
+ case 0x2: size_y = 2; break;
+ default: size_y = 4; break;
+ }
+
+ minx = clip_x << 7;
+ maxx = ((clip_x + size_x) << 7) - 1;
+ miny = clip_y << 7;
+ maxy = ((clip_y + size_y) << 7) - 1;
+
+ K053936GP_set_cliprect(0, minx, maxx, miny, maxy);
+ }
+ }
+}
+
+// reference: 223e5c in gaiapolis (ROMs 34j and 36m)
+READ16_HANDLER(gai_053936_tilerom_0_r)
+{
+ UINT8 *ROM1 = (UINT8 *)memory_region(REGION_GFX4);
+ UINT8 *ROM2 = (UINT8 *)memory_region(REGION_GFX4);
+
+ ROM1 += 0x20000;
+ ROM2 += 0x20000+0x40000;
+
+ return ((ROM1[offset]<<8) | ROM2[offset]);
+}
+
+READ16_HANDLER(ddd_053936_tilerom_0_r)
+{
+ UINT8 *ROM1 = (UINT8 *)memory_region(REGION_GFX4);
+ UINT8 *ROM2 = (UINT8 *)memory_region(REGION_GFX4);
+
+ ROM2 += 0x40000;
+
+ return ((ROM1[offset]<<8) | ROM2[offset]);
+}
+
+// reference: 223e1a in gaiapolis (ROM 36j)
+READ16_HANDLER(ddd_053936_tilerom_1_r)
+{
+ UINT8 *ROM = (UINT8 *)memory_region(REGION_GFX4);
+
+ return ROM[offset/2];
+}
+
+// reference: 223db0 in gaiapolis (ROMs 32n, 29n, 26n)
+READ16_HANDLER(gai_053936_tilerom_2_r)
+{
+ UINT8 *ROM = (UINT8 *)memory_region(REGION_GFX3);
+
+ offset += (roz_rombank * 0x100000);
+
+ return ROM[offset/2]<<8;
+}
+
+READ16_HANDLER(ddd_053936_tilerom_2_r)
+{
+ UINT8 *ROM = (UINT8 *)memory_region(REGION_GFX3);
+
+ offset += (roz_rombank * 0x100000);
+
+ return ROM[offset]<<8;
+}
+
+VIDEO_UPDATE(dadandrn) /* and gaiapols */
+{
+ int i, newbase, dirty, rozmode;
+
+ if (gametype == 0)
+ {
+ sprite_colorbase = (K055555_get_palette_index(4)<<4)&0x7f;
+ rozmode = GXSUB_4BPP;
+ }
+ else
+ {
+ sprite_colorbase = (K055555_get_palette_index(4)<<3)&0x7f;
+ rozmode = GXSUB_8BPP;
+ }
+
+ if (K056832_get_LayerAssociation())
+ {
+ for (i=0; i<4; i++)
+ {
+ newbase = K055555_get_palette_index(i)<<4;
+ if (layer_colorbase[i] != newbase)
+ {
+ layer_colorbase[i] = newbase;
+ K056832_mark_plane_dirty(i);
+ }
+ }
+ }
+ else
+ {
+ for (dirty=0, i=0; i<4; i++)
+ {
+ newbase = K055555_get_palette_index(i)<<4;
+ if (layer_colorbase[i] != newbase)
+ {
+ layer_colorbase[i] = newbase;
+ dirty = 1;
+ }
+ }
+ if (dirty) K056832_MarkAllTilemapsDirty();
+
+ }
+
+ last_psac_colorbase = sub1_colorbase;
+ sub1_colorbase = K055555_get_palette_index(5);
+
+ if (last_psac_colorbase != sub1_colorbase)
+ {
+ tilemap_mark_all_tiles_dirty(ult_936_tilemap);
+
+ #if MW_VERBOSE
+ popmessage("K053936: PSAC colorbase changed");
+ #endif
+ }
+
+ konamigx_mixer(machine, bitmap, cliprect, (roz_enable) ? ult_936_tilemap : 0, rozmode, 0, 0, 0);
+ return 0;
+}