snesgfx-decode mode7 graphics

This commit is contained in:
zeromus 2012-09-21 17:21:21 +00:00
parent 600be3cc24
commit 3c6549a7bb
4 changed files with 116 additions and 72 deletions

View File

@ -342,48 +342,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
if (IsLagFrame)
LagCount++;
//SNESGraphicsDecoder dec = new SNESGraphicsDecoder();
//64x64 @ 4k
//var bw = new BinaryWriter(File.OpenWrite("c:\\dump\\tiles.raw"));
//var tiles = dec.FetchTilemap(0x4000, SNESGraphicsDecoder.ScreenSize.ABCD_64x64);
//foreach (var te in tiles)
//{
// bw.Write(te.tilenum);
// bw.Write((byte)0);
//}
//bw.Flush();
//bw.BaseStream.Close();
//render tilemap
//dec.CacheTiles();
//int[] bgScreen = new int[tiles.Length * 64];
//fixed (int* pbgScreen = &bgScreen[0])
//{
// dec.DecodeScreen(pbgScreen, tiles, 0x0000, SNESGraphicsDecoder.ScreenSize.ABCD_64x64, 4, false, 0);
// dec.Paletteize(pbgScreen, 0, 0, bgScreen.Length);
// dec.Colorize(pbgScreen, 0, bgScreen.Length);
//}
////dec.TrueDecodeTilesNBpp(4);
//dec.CacheTiles();
//var fs = File.OpenWrite("c:\\dump\\tiles.raw");
//for (int i = 0; i < bgScreen.Length; i++)
//{
// fs.WriteByte((byte)((bgScreen[i] >> 0) & 0xFF));
// fs.WriteByte((byte)((bgScreen[i] >> 8) & 0xFF));
// fs.WriteByte((byte)((bgScreen[i] >> 16) & 0xFF));
//}
//fs.Close();
//using (var bmp = new System.Drawing.Bitmap(16, 16))
//{
// for (int i = 0; i < 256; i++)
// {
// ushort u = dec.cgram[i];
// bmp.SetPixel(i % 16, i / 16, System.Drawing.Color.FromArgb(SNESGraphicsDecoder.colortable[491520 + u]));
// }
// bmp.Save("c:\\dump\\palette.png");
//}
}
//video provider

View File

@ -233,6 +233,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
Priority = 1, Horz = 2, Vert = 4,
}
/// <summary>
/// decodes a mode7 BG. youll still need to paletteize and colorize it.
/// </summary>
public void DecodeMode7BG(int* screen, int stride)
{
int[] tileCache = _tileCache[7];
for (int ty = 0, tidx = 0; ty < 128; ty++)
{
for (int tx = 0; tx < 128; tx++, tidx++)
{
int tileEntry = vram[tidx * 2];
int src = tileEntry * 64;
for (int py = 0, pix=src; py < 8; py++)
{
for (int px = 0; px < 8; px++, pix++)
{
int dst = (ty * 8 + py) * stride + (tx * 8 + px);
int srcData = tileCache[pix];
screen[dst] = srcData;
}
}
}
}
}
/// <summary>
/// decodes a BG. youll still need to paletteize and colorize it.
/// someone else has to take care of calculating the starting color from the mode and layer number.
@ -340,7 +365,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
int[][] _tileCache = new int[9][];
/// <summary>
/// Caches all tiles at the 2bpp, 4bpp, and 8bpp decoded states
/// Caches all tiles at the 2bpp, 4bpp, and 8bpp decoded states.
/// we COULD defer this til we need it, you know. sort of a cool idea, not too hard
/// </summary>
public void CacheTiles()
{
@ -356,6 +382,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
//merge 2bpp tiles into 4bpp and 8bpp
CacheTiles_Merge(2);
CacheTiles_Merge(4);
CacheTilesMode7();
}
public void CacheTilesMode7()
{
int numtiles = 256;
int[] tiles = new int[8 * 8 * numtiles];
_tileCache[7] = tiles;
for (int i = 0, j=0; i < numtiles; i++)
{
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++, j++)
tiles[j] = vram[j * 2 + 1];
}
}
/// <summary>
@ -373,10 +413,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
for (int i = 0; i < numtiles; i++)
{
if (i == 512)
{
int zzz = 9;
}
int srcAddr = i * 128;
int dstAddr = i * 64;
for (int p = 0; p < 64; p++)
@ -403,30 +439,46 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
}
public static Dimensions GetDimensionsForTileScreen(int bpp)
/// <summary>
/// renders the mode7 tiles to a screen with the predefined size.
/// </summary>
public void RenderMode7TilesToScreen(int* screen, int stride)
{
if (bpp == 2) return new Dimensions(512, 512);
if (bpp == 4) return new Dimensions(512, 256);
if (bpp == 8) return new Dimensions(256, 256);
throw new ApplicationException("weird");
int numTiles = 256;
int tilesWide = 16;
int[] tilebuf = _tileCache[7];
for (int i = 0; i < numTiles; i++)
{
int ty = i / tilesWide;
int tx = i % tilesWide;
int dstOfs = (ty * 8) * stride + tx * 8;
int srcOfs = i * 64;
for (int y = 0, p = 0; y < 8; y++)
for (int x = 0; x < 8; x++, p++)
{
screen[dstOfs + y * stride + x] = tilebuf[srcOfs + p];
}
}
int numPixels = numTiles * 8 * 8;
Paletteize(screen, 0, 0, numPixels);
Colorize(screen, 0, numPixels);
}
/// <summary>
/// renders the tiles to a screen with the predefined size
/// renders the tiles to a screen of the crudely specified size.
/// we might need 16x16 unscrambling and some other perks here eventually.
/// provide a start color to use as the basis for the palette
/// </summary>
public void RenderTilesToScreen(int* screen, int stride, int bpp, int startcolor)
public void RenderTilesToScreen(int* screen, int tilesWide, int tilesTall, int stride, int bpp, int startcolor)
{
var dims = GetDimensionsForTileScreen(bpp);
int tilesw = dims.Width / 8;
int numTiles = 8192 / bpp;
int[] tilebuf = _tileCache[bpp];
for (int i = 0; i < numTiles; i++)
{
int ty = i / tilesw;
int tx = i % tilesw;
int dstOfs = (ty*8) * stride + tx*8;
int ty = i / tilesWide;
int tx = i % tilesWide;
int dstOfs = (ty * 8) * stride + tx * 8;
int srcOfs = i * 64;
for (int y = 0,p=0; y < 8; y++)
for (int x = 0; x < 8; x++,p++)

View File

@ -113,6 +113,7 @@
this.label18 = new System.Windows.Forms.Label();
this.paletteViewer = new BizHawk.MultiClient.SNESGraphicsViewer();
this.viewer = new BizHawk.MultiClient.SNESGraphicsViewer();
this.radioButton15 = new System.Windows.Forms.RadioButton();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.menuStrip1.SuspendLayout();
@ -599,6 +600,7 @@
"Tiles as 2bpp",
"Tiles as 4bpp",
"Tiles as 8bpp",
"Tiles as Mode7",
"Tiles as 2bpp (@0K)",
"Tiles as 2bpp (@16K)",
"Tiles as 2bpp (@24K)",
@ -759,7 +761,7 @@
//
this.radioButton13.AutoSize = true;
this.radioButton13.Enabled = false;
this.radioButton13.Location = new System.Drawing.Point(157, 101);
this.radioButton13.Location = new System.Drawing.Point(169, 100);
this.radioButton13.Name = "radioButton13";
this.radioButton13.Size = new System.Drawing.Size(49, 17);
this.radioButton13.TabIndex = 31;
@ -852,6 +854,7 @@
//
// groupBox4
//
this.groupBox4.Controls.Add(this.radioButton15);
this.groupBox4.Controls.Add(this.radioButton14);
this.groupBox4.Controls.Add(this.radioButton9);
this.groupBox4.Controls.Add(this.comboDisplayType);
@ -1062,6 +1065,18 @@
this.viewer.TabIndex = 17;
this.viewer.TabStop = false;
//
// radioButton15
//
this.radioButton15.AutoSize = true;
this.radioButton15.Enabled = false;
this.radioButton15.Location = new System.Drawing.Point(169, 83);
this.radioButton15.Name = "radioButton15";
this.radioButton15.Size = new System.Drawing.Size(58, 17);
this.radioButton15.TabIndex = 33;
this.radioButton15.TabStop = true;
this.radioButton15.Text = "Mode7";
this.radioButton15.UseVisualStyleBackColor = true;
//
// SNESGraphicsDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -1185,5 +1200,6 @@
private System.Windows.Forms.TextBox txtPaletteDetailsIndex;
private System.Windows.Forms.Label lblDetailsOBJOrBG;
private System.Windows.Forms.TextBox txtPaletteDetailsIndexHex;
private System.Windows.Forms.RadioButton radioButton15;
}
}

View File

@ -138,35 +138,53 @@ namespace BizHawk.MultiClient
if (selection == "Tiles as 2bpp")
{
allocate(512, 512);
gd.RenderTilesToScreen(pixelptr, stride / 4, 2, 0);
gd.RenderTilesToScreen(pixelptr, 64, 64, stride / 4, 2, 0);
}
if (selection == "Tiles as 4bpp")
{
allocate(512, 512);
gd.RenderTilesToScreen(pixelptr, stride / 4, 4, 0);
gd.RenderTilesToScreen(pixelptr, 64, 32, stride / 4, 4, 0);
}
if (selection == "Tiles as 8bpp")
{
allocate(256, 256);
gd.RenderTilesToScreen(pixelptr, stride / 4, 8, 0);
gd.RenderTilesToScreen(pixelptr, 32, 32, stride / 4, 8, 0);
}
if (selection == "Tiles as Mode7")
{
//256 tiles
allocate(128, 128);
gd.RenderMode7TilesToScreen(pixelptr, stride / 4);
}
if (selection == "BG1" || selection == "BG2" || selection == "BG3" || selection == "BG4")
{
int bgnum = int.Parse(selection.Substring(2));
var si = gd.ScanScreenInfo();
var bg = si.BG[bgnum];
if (bg.Enabled)
{
var dims = bg.ScreenSizeInPixels;
allocate(dims.Width, dims.Height);
int numPixels = dims.Width * dims.Height;
System.Diagnostics.Debug.Assert(stride / 4 == dims.Width);
if (bgnum == 1 && si.Mode.MODE == 7)
{
allocate(1024, 1024);
gd.DecodeMode7BG(pixelptr, stride / 4);
int numPixels = 128 * 128 * 8 * 8;
gd.Paletteize(pixelptr, 0, 0, numPixels);
gd.Colorize(pixelptr, 0, numPixels);
}
else
{
var dims = bg.ScreenSizeInPixels;
allocate(dims.Width, dims.Height);
int numPixels = dims.Width * dims.Height;
System.Diagnostics.Debug.Assert(stride / 4 == dims.Width);
var map = gd.FetchTilemap(bg.ScreenAddr, bg.ScreenSize);
int paletteStart = 0;
gd.DecodeBG(pixelptr, stride / 4, map, bg.TiledataAddr, bg.ScreenSize, bg.Bpp, bg.TileSize, paletteStart);
gd.Paletteize(pixelptr, 0, 0, numPixels);
gd.Colorize(pixelptr, 0, numPixels);
var map = gd.FetchTilemap(bg.ScreenAddr, bg.ScreenSize);
int paletteStart = 0;
gd.DecodeBG(pixelptr, stride / 4, map, bg.TiledataAddr, bg.ScreenSize, bg.Bpp, bg.TileSize, paletteStart);
gd.Paletteize(pixelptr, 0, 0, numPixels);
gd.Colorize(pixelptr, 0, numPixels);
}
}
}