MAME.Core/MAME.Unity/Assets/Plugins/UMAME/emu/Tilemap.cs
2025-01-16 11:51:17 +08:00

413 lines
14 KiB
C#

using System;
using System.Collections.Generic;
namespace MAME.Core
{
enum trans_t
{
WHOLLY_TRANSPARENT,
WHOLLY_OPAQUE,
MASKED
}
public struct RECT
{
public int min_x;
public int min_y;
public int max_x;
public int max_y;
}
public partial class Tmap
{
public int laynum;
public int rows;
public int cols;
public int tilewidth;
public int tileheight;
public int width;
public int height;
public int videoram_offset;
public bool enable;
public byte attributes;
public bool all_tiles_dirty;
public int palette_offset;
public byte priority;
public int scrollrows;
public int scrollcols;
public int[] rowscroll;
public int[] colscroll;
public int dx;
public int dx_flipped;
public int dy;
public int dy_flipped;
public ushort[] pixmap;
public byte[,] flagsmap;
public byte[,] tileflags;
public byte[,] pen_to_flags;
public byte[] pen_data;
public int mask, value;
public int total_elements;
public Action<int, int> tile_update3;
public Action<RECT, int, int> tilemap_draw_instance3;
public int effective_rowscroll(int index)
{
int value;
if ((attributes & Tilemap.TILEMAP_FLIPY) != 0)
{
index = scrollrows - 1 - index;
}
if ((attributes & Tilemap.TILEMAP_FLIPX) == 0)
{
value = dx - rowscroll[index];
}
else
{
value = Tilemap.screen_width - width - (dx_flipped - rowscroll[index]);
}
if (value < 0)
{
value = width - (-value) % width;
}
else
{
value %= width;
}
return value;
}
public int effective_colscroll(int index)
{
int value;
if ((attributes & Tilemap.TILEMAP_FLIPX) != 0)
{
index = scrollcols - 1 - index;
}
if ((attributes & Tilemap.TILEMAP_FLIPY) == 0)
{
value = dy - colscroll[index];
}
else
{
value = Tilemap.screen_height - height - (dy_flipped - colscroll[index]);
}
if (value < 0)
{
value = height - (-value) % height;
}
else
{
value %= height;
}
return value;
}
public void tilemap_set_palette_offset(int offset)
{
palette_offset = offset;
}
public static void tilemap_set_flip(Tmap tmap, byte _attributes)
{
if (tmap == null)
{
foreach (Tmap t1 in Tilemap.lsTmap)
{
if (t1.attributes != _attributes)
{
t1.attributes = _attributes;
}
}
}
else if (tmap.attributes != _attributes)
{
tmap.attributes = _attributes;
tmap.mappings_update();
}
}
public void get_row_col(int index, out int row, out int col)
{
if ((attributes & Tilemap.TILEMAP_FLIPX) != 0)
{
col = cols - 1 - index % cols;
}
else
{
col = index % cols;
}
if ((attributes & Tilemap.TILEMAP_FLIPY) != 0)
{
row = rows - 1 - index / cols;
}
else
{
row = index / cols;
}
}
public void tilemap_mark_tile_dirty(int row, int col)
{
tileflags[row, col] = Tilemap.TILE_FLAG_DIRTY;
}
public void tilemap_set_scroll_rows(int scroll_rows)
{
scrollrows = scroll_rows;
}
public void tilemap_set_scroll_cols(int scroll_cols)
{
scrollcols = scroll_cols;
}
public void tilemap_set_scrolldx(int _dx, int _dx2)
{
dx = _dx;
dx_flipped = _dx2;
}
public void tilemap_set_scrolldy(int _dy, int _dy2)
{
dy = _dy;
dy_flipped = _dy2;
}
public void tilemap_set_scrollx(int which, int value)
{
if (which < scrollrows)
{
rowscroll[which] = value;
}
}
public void tilemap_set_scrolly(int which, int value)
{
if (which < scrollcols)
{
colscroll[which] = value;
}
}
public RECT sect_rect(RECT dst, RECT src)
{
RECT dst2 = dst;
if (src.min_x > dst.min_x)
{
dst2.min_x = src.min_x;
}
if (src.max_x < dst.max_x)
{
dst2.max_x = src.max_x;
}
if (src.min_y > dst.min_y)
{
dst2.min_y = src.min_y;
}
if (src.max_y < dst.max_y)
{
dst2.max_y = src.max_y;
}
return dst2;
}
public void tilemap_draw_primask(RECT cliprect, int flags, byte _priority)
{
int xpos, ypos;
if (!enable)
{
return;
}
mask = 0x0f | flags;
value = flags;
priority = _priority;
if (all_tiles_dirty)
{
Array.Copy(Tilemap.bbFF, tileflags, cols * rows);
all_tiles_dirty = false;
}
if (scrollrows == 1 && scrollcols == 1)
{
int scrollx = effective_rowscroll(0);
int scrolly = effective_colscroll(0);
for (ypos = scrolly - height; ypos <= cliprect.max_y; ypos += height)
{
for (xpos = scrollx - width; xpos <= cliprect.max_x; xpos += width)
{
tilemap_draw_instance3(cliprect, xpos, ypos);
}
}
}
else if (scrollcols == 1)
{
RECT rect = cliprect;
int rowheight = height / scrollrows;
int scrolly = effective_colscroll(0);
int currow, nextrow;
for (ypos = scrolly - height; ypos <= cliprect.max_y; ypos += height)
{
int firstrow = Math.Max((cliprect.min_y - ypos) / rowheight, 0);
int lastrow = Math.Min((cliprect.max_y - ypos) / rowheight, scrollrows - 1);
for (currow = firstrow; currow <= lastrow; currow = nextrow)
{
int scrollx = effective_rowscroll(currow);
for (nextrow = currow + 1; nextrow <= lastrow; nextrow++)
{
if (effective_rowscroll(nextrow) != scrollx)
{
break;
}
}
rect.min_y = currow * rowheight + ypos;
rect.max_y = nextrow * rowheight - 1 + ypos;
rect = sect_rect(rect, cliprect);
for (xpos = scrollx - width; xpos <= cliprect.max_x; xpos += width)
{
tilemap_draw_instance3(rect, xpos, ypos);
}
}
}
}
else if (scrollrows == 1)
{
int i1 = 1;
}
}
public void mappings_update()
{
all_tiles_dirty = true;
}
}
public class Tilemap
{
public static List<Tmap> lsTmap = new List<Tmap>();
public static byte[,] priority_bitmap;
public static byte[,] bb00, bbFF;
public static byte[] bb0F;
public static int screen_width, screen_height;
private static int INVALID_LOGICAL_INDEX = -1;
public static byte TILEMAP_PIXEL_TRANSPARENT = 0x00;
private static byte TILEMAP_PIXEL_CATEGORY_MASK = 0x0f; /* category is stored in the low 4 bits */
public static byte TILE_FLAG_DIRTY = 0xff;
public static byte TILEMAP_PIXEL_LAYER0 = 0x10;
public static byte TILE_FLIPX = 0x01; /* draw this tile horizontally flipped */
public static byte TILE_FLIPY = 0x02; /* draw this tile vertically flipped */
public static byte TILEMAP_FLIPX = TILE_FLIPX; /* draw the tilemap horizontally flipped */
public static byte TILEMAP_FLIPY = TILE_FLIPY; /* draw the tilemap vertically flipped */
public static void tilemap_init()
{
int i, j;
switch (Machine.sBoard)
{
case "CPS-1":
case "CPS-1(QSound)":
case "CPS2":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
CPS.tilemap_init();
break;
case "Data East":
screen_width = 0x100;
screen_height = 0x100;
Dataeast.tilemap_init();
break;
case "Tehkan":
screen_width = 0x100;
screen_height = 0x100;
Tehkan.tilemap_init();
break;
case "Namco System 1":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
Namcos1.tilemap_init();
break;
case "PGM":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
PGM.tilemap_init();
break;
case "M72":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
M72.tilemap_init();
break;
case "M92":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
M92.tilemap_init();
break;
case "Taito":
screen_width = 0x140;
screen_height = 0x100;
priority_bitmap = new byte[0x100, 0x140];
Taito.tilemap_init();
break;
case "Taito B":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
Taitob.tilemap_init();
break;
case "Konami 68000":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
Konami68000.tilemap_init();
break;
case "Capcom":
screen_width = 0x200;
screen_height = 0x200;
priority_bitmap = new byte[0x200, 0x200];
Capcom.tilemap_init();
break;
}
switch (Machine.sBoard)
{
case "CPS-1":
case "CPS-1(QSound)":
case "CPS2":
case "Data East":
case "Tehkan":
case "Namco System 1":
case "PGM":
case "M72":
case "Taito":
case "Taito B":
case "Konami 68000":
bb0F = new byte[0x400];
bbFF = new byte[0x80, 0x40];
for (i = 0; i < 0x80; i++)
{
for (j = 0; j < 0x40; j++)
{
bbFF[i, j] = 0xff;
}
}
for (i = 0; i < 0x400; i++)
{
bb0F[i] = 0x0f;
}
break;
case "M92":
screen_height = 0x100;
bbFF = new byte[0x80, 0x40];
bb00 = new byte[0x200, 0x200];
for (i = 0; i < 0x200; i++)
{
for (j = 0; j < 0x200; j++)
{
bb00[i, j] = 0;
}
}
for (i = 0; i < 0x80; i++)
{
for (j = 0; j < 0x40; j++)
{
bbFF[i, j] = 0xff;
}
}
break;
case "Capcom":
bbFF = new byte[0x800, 0x10];
for (i = 0; i < 0x800; i++)
{
for (j = 0; j < 0x10; j++)
{
bbFF[i, j] = 0xff;
}
}
break;
}
}
}
}