snes-work on graphics tools. can now render typical BGs for mode 1. SLOWLY!!!!! this is definitely getting turned into c++ code

This commit is contained in:
zeromus 2012-09-08 20:03:04 +00:00
parent 3233d31e6c
commit 285b9581f2
4 changed files with 534 additions and 155 deletions

View File

@ -310,6 +310,48 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
//apparently this is one frame?
timeFrameCounter++;
LibsnesDll.snes_run();
//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

@ -1,4 +1,6 @@
//http://wiki.superfamicom.org/snes/show/Backgrounds
//http://board.zsnes.com/phpBB3/viewtopic.php?f=10&t=13029&start=75 yoshis island offset per tile demos. and other demos of advanced modes
//but we wont worry about offset per tile modes here.
using System;
using System.Linq;
@ -14,8 +16,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
{
public struct Dimensions
{
public Dimensions(int w, int h) { Width = (short)w; Height = (short)h; }
public short Width, Height;
public Dimensions(int w, int h) { Width = w; Height = h; }
public int Width, Height;
public override string ToString()
{
return string.Format("{0}x{1}", Width, Height);
@ -28,13 +30,21 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
public static Dimensions SizeInTilesForBGSize(ScreenSize size)
{
var ret = SizeInBlocksForBGSize(size);
ret.Width *= 32;
ret.Height *= 32;
return ret;
}
public static Dimensions SizeInBlocksForBGSize(ScreenSize size)
{
switch (size)
{
case ScreenSize.AAAA_32x32: return new Dimensions(32, 32);
case ScreenSize.ABAB_64x32: return new Dimensions(64, 32);
case ScreenSize.AABB_32x64: return new Dimensions(32, 64);
case ScreenSize.ABCD_64x64: return new Dimensions(64, 64);
case ScreenSize.AAAA_32x32: return new Dimensions(1, 1);
case ScreenSize.ABAB_64x32: return new Dimensions(2, 1);
case ScreenSize.AABB_32x64: return new Dimensions(1, 2);
case ScreenSize.ABCD_64x64: return new Dimensions(2, 2);
default: throw new Exception();
}
}
@ -59,7 +69,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
/// <summary>
/// the address of the tile data
/// </summary>
public int TiledataAddr { get { return SCADDR << 13; } }
public int TiledataAddr { get { return TDADDR << 13; } }
/// <summary>
/// Screen size (shape, really.)
@ -71,10 +81,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
/// </summary>
public int Bpp;
/// <summary>
/// value of the tilesize register; 1 implies 16x16 tiles
/// </summary>
public int TILESIZE;
/// <summary>
/// TileSize; 8 or 16
/// </summary>
public int TileSize { get { return TILESIZE == 1 ? 16 : 8; } }
/// <summary>
/// The size of the layer, in tiles
/// </summary>
public Dimensions ScreenSizeInTiles { get { return SizeInTilesForBGSize(ScreenSize); } }
/// <summary>
/// The size of the layer, in pixels. This has factored in the selection of 8x8 or 16x16 tiles
/// </summary>
public Dimensions ScreenSizeInPixels
{
get
{
return new Dimensions(ScreenSizeInTiles.Width * TileSize, ScreenSizeInTiles.Height * TileSize);
}
}
}
public class BGInfos
@ -125,6 +156,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
si.BG.BG3.Bpp = ModeBpps[si.Mode.MODE, 2];
si.BG.BG4.Bpp = ModeBpps[si.Mode.MODE, 3];
si.BG.BG1.TILESIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG1_TILESIZE);
si.BG.BG2.TILESIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG2_TILESIZE);
si.BG.BG3.TILESIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG3_TILESIZE);
si.BG.BG4.TILESIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG4_TILESIZE);
si.BG.BG1.SCSIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG1_SCSIZE);
si.BG.BG2.SCSIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG2_SCSIZE);
si.BG.BG3.SCSIZE = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG3_SCSIZE);
@ -133,13 +169,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
si.BG.BG2.SCADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG2_SCADDR);
si.BG.BG3.SCADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG3_SCADDR);
si.BG.BG4.SCADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG4_SCADDR);
si.BG.BG1.TDADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG1_TDADDR);
si.BG.BG2.TDADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG2_TDADDR);
si.BG.BG3.TDADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG3_TDADDR);
si.BG.BG4.TDADDR = LibsnesDll.snes_peek_logical_register(LibsnesDll.SNES_REG.BG4_TDADDR);
return si;
}
static int[] colortable = new int[16 * 32768];
//the same basic color table that libsnes uses to convert from snes 555 to rgba32
public static int[] colortable = new int[16 * 32768];
static SNESGraphicsDecoder()
{
for (int l = 0; l < 16; l++)
@ -167,7 +206,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
byte* vram;
ushort* cgram, vram16;
public ushort* cgram, vram16;
public SNESGraphicsDecoder()
{
IntPtr block = LibsnesDll.snes_get_memory_data(LibsnesDll.SNES_MEMORY.VRAM);
@ -177,7 +216,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
cgram = (ushort*)block.ToPointer();
}
public struct TileEnty
public struct TileEntry
{
public ushort tilenum;
public byte palette;
@ -190,21 +229,92 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
/// <summary>
/// fetches a normal BG 32x32 tilemap block into the supplied buffer and offset
/// 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.
/// </summary>
public void FetchTilemapBlock(TileEnty[] buf, int offset, int addr)
public void DecodeBG(int* screen, int stride, TileEntry[] map, int tiledataBaseAddr, ScreenSize size, int bpp, int tilesize, int paletteStart)
{
for (int y = 0, i = offset; y < 32; y++)
for (int x = 0; x < 32; x++, i++)
int ncolors = 1 << bpp;
int[] tileBuf = new int[16*16];
var dims = SizeInTilesForBGSize(size);
int count8x8 = tilesize / 8;
int tileSizeBytes = 8 * bpp;
int baseTileNum = tiledataBaseAddr / tileSizeBytes;
int[] tileCache = _tileCache[bpp];
int screenWidth = dims.Width * count8x8 * 8;
for (int mty = 0; mty < dims.Height; mty++)
{
for (int mtx = 0; mtx < dims.Height; mtx++)
{
ushort entry = *(ushort*)(vram + addr);
buf[i].tilenum = (ushort)(entry & 0x3FF);
buf[i].palette = (byte)((entry >> 10) & 7);
buf[i].flags = (TileEntryFlags)((entry >> 13) & 7);
addr += 2;
for (int tx = 0; tx < count8x8; tx++)
{
for (int ty = 0; ty < count8x8; ty++)
{
int mapIndex = (mty * count8x8 + ty) * dims.Width + mtx * count8x8 + tx;
var te = map[mapIndex];
int tileNum = te.tilenum + tx + ty * 16 + baseTileNum;
int srcOfs = tileNum * 64;
for (int i = 0, y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++, i++)
{
int px = x;
int py = y;
if (te.flags.HasFlag(TileEntryFlags.Horz)) px = 7 - x;
if (te.flags.HasFlag(TileEntryFlags.Vert)) py = 7 - y;
int dstX = (mtx * count8x8 + tx) * 8 + px;
int dstY = (mty * count8x8 + ty) * 8 + py;
int dstOfs = dstY * stride + dstX;
int color = tileCache[srcOfs++];
color += te.palette * ncolors;
color += paletteStart;
screen[dstOfs] = color;
}
}
}
}
}
}
}
/// <summary>
/// fetches a tilemap. this is simple; apparently only the screen size (shape) is a factor
/// </summary>
public TileEntry[] FetchTilemap(int addr, ScreenSize size)
{
var blockDims = SizeInBlocksForBGSize(size);
int blocksw = blockDims.Width;
int blocksh = blockDims.Height;
int width = blockDims.Width * 32;
int height = blockDims.Width * 32;
TileEntry[] buf = new TileEntry[width*height];
for (int by = 0; by < blocksh; by++)
{
for (int bx = 0; bx < blocksw; bx++)
{
for (int y = 0; y < 32; y++)
{
for (int x = 0; x < 32; x++)
{
int idx = (by * 32 + y) * width + bx * 32 + x;
ushort entry = *(ushort*)(vram + addr);
buf[idx].tilenum = (ushort)(entry & 0x3FF);
buf[idx].palette = (byte)((entry >> 10) & 7);
buf[idx].flags = (TileEntryFlags)((entry >> 13) & 7);
addr += 2;
}
}
}
}
return buf;
}
//TODO - paletteize and colorize could be in one step, for more speed
public void Paletteize(int* buf, int offset, int startcolor, int numpixels)
{
for (int i = 0; i < numpixels; i++)
@ -212,7 +322,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
buf[offset + i] = cgram[startcolor + buf[offset + i]];
}
}
public void Colorize(int* buf, int offset, int numpixels)
{
for (int i = 0; i < numpixels; i++)
@ -221,140 +330,109 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
}
public void Decode8x8x2bpp(int[] buf, int offset, int addr)
int[][] _tileCache = new int[9][];
/// <summary>
/// Caches all tiles at the 2bpp, 4bpp, and 8bpp decoded states
/// </summary>
public void CacheTiles()
{
for (int y = 0; y < 8; y++)
//generate 2bpp tiles
int numtiles = 8192;
int[] tiles = new int[8 * 8 * numtiles];
_tileCache[2] = tiles;
for (int i = 0; i < numtiles; i++)
{
byte val = vram[addr + 0];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = val >> (7 - x) & 1;
val = vram[addr + 1];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
addr += 2;
Decode8x8x2bpp(tiles, i * 64, 16 * i, 8);
}
//merge 2bpp tiles into 4bpp and 8bpp
CacheTiles_Merge(2);
CacheTiles_Merge(4);
}
public void Decode8x8x4bpp(int[] buf, int offset, int addr)
/// <summary>
/// merges one type of tiles with another to create the higher-order bitdepth.
/// TODO - templateize this when we change it to c++
/// </summary>
void CacheTiles_Merge(int fromBpp)
{
for (int y = 0; y < 8; y++)
{
byte val = vram[addr + 0];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = val >> (7 - x) & 1;
val = vram[addr + 1];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 16];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 17];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
addr += 2;
}
}
int toBpp = fromBpp * 2;
int shift = fromBpp;
int numtiles = 8192 / toBpp;
int[] tilesDst = new int[8 * 8 * numtiles];
_tileCache[toBpp] = tilesDst;
int[] tilesSrc = _tileCache[2];
public void Decode8x8x8bpp(int[] buf, int offset, int addr)
{
for (int y = 0; y < 8; y++)
for (int i = 0; i < numtiles; i++)
{
byte val = vram[addr + 0];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = val >> (7 - x) & 1;
val = vram[addr + 1];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 16];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 17];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 32];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 33];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 48];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
val = vram[addr + 49];
for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
addr += 2;
int srcAddr = i * 128;
int dstAddr = i * 64;
for (int p = 0; p < 64; p++)
{
int tileA = tilesSrc[srcAddr + p];
int tileB = tilesSrc[srcAddr + p + 64];
tilesDst[dstAddr + p] = tileA | (tileB << shift);
}
}
}
/// <summary>
/// decodes all the tiles in vram as if they were 2bpp tiles to a 64x64 tile (512x512 pixel) screen
/// decodes an 8x8 tile to a linear framebuffer type thing. fundamental unit of tile decoding.
/// </summary>
public void DecodeTiles2bpp(int* screen, int stride, int startcolor)
public void Decode8x8x2bpp(int[] buf, int offset, int addr, int stride=8)
{
//cant handle this with our speed optimized routines
Debug.Assert(stride == 512);
int[] tilebuf = new int[8 * 8];
for (int i = 0; i < 64 * 64; i++)
for (int y = 0; y < 8; y++)
{
Decode8x8x2bpp(tilebuf, 0, 16 * i);
int ty = i / 64;
int tx = i % 64;
ty *= 8;
tx *= 8;
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
screen[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
}
byte val = vram[addr + 1];
for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = val >> (7 - x) & 1;
val = vram[addr + 0];
for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = (buf[offset + y * stride + x] << 1) | (val >> (7 - x) & 1);
addr += 2;
}
}
Paletteize(screen, 0, startcolor, 64 * 64 * 8 * 8);
Colorize(screen, 0, 64 * 64 * 8 * 8);
public static Dimensions GetDimensionsForTileScreen(int bpp)
{
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");
}
/// <summary>
/// decodes all the tiles in vram as if they were 4bpp tiles to a 64x32 tile (512x256 pixel) screen
/// renders the tiles to a screen with the predefined 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 DecodeTiles4bpp(int* screen, int stride, int startcolor)
public void RenderTilesToScreen(int* screen, int stride, int bpp, int startcolor)
{
//cant handle this with our speed optimized routines
Debug.Assert(stride == 512);
int[] tilebuf = new int[8 * 8];
for (int i = 0; i < 64 * 32; i++)
var dims = GetDimensionsForTileScreen(bpp);
int tilesw = dims.Width / 8;
int numTiles = 8192 / bpp;
int[] tilebuf = _tileCache[bpp];
for (int i = 0; i < numTiles; i++)
{
Decode8x8x4bpp(tilebuf, 0, 32 * i);
int ty = i / 64;
int tx = i % 64;
ty *= 8;
tx *= 8;
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
int ty = i / tilesw;
int tx = i % tilesw;
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[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
screen[dstOfs+y*stride+x] = tilebuf[srcOfs + p];
}
}
Paletteize(screen, 0, startcolor, 64 * 32 * 8 * 8);
Colorize(screen, 0, 64 * 32 * 8 * 8);
int numPixels = numTiles * 8 * 8;
Paletteize(screen, 0, startcolor, numPixels);
Colorize(screen, 0, numPixels);
}
/// <summary>
/// decodes all the tiles in vram as if they were 4bpp tiles to a 32x32 tile (256x256 pixel) screen
/// </summary>
public void DecodeTiles8bpp(int* screen, int stride, int startcolor)
{
//cant handle this with our speed optimized routines
Debug.Assert(stride == 256);
int[] tilebuf = new int[8 * 8];
for (int i = 0; i < 32 * 32; i++)
{
Decode8x8x8bpp(tilebuf, 0, 64 * i);
int ty = i / 32;
int tx = i % 32;
ty *= 8;
tx *= 8;
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
screen[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
}
}
Paletteize(screen, 0, startcolor, 32 * 32 * 8 * 8);
Colorize(screen, 0, 32 * 32 * 8 * 8);
}
}
}
} //class SNESGraphicsDecoder
} //namespace
//GraphicsDecoder dec = new GraphicsDecoder();
@ -383,4 +461,125 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
// ms.WriteByte((byte)((i >> 16) & 0xFF));
//}
//File.WriteAllBytes("c:\\dump\\file" + ctr, ms.ToArray());
//ctr++;
//ctr++;
//public void Decode8x8x4bpp(int[] buf, int offset, int addr, int stride=8)
//{
// for (int y = 0; y < 8; y++)
// {
// byte val = vram[addr + 17];
// for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = val >> (7 - x) & 1;
// val = vram[addr + 16];
// for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = (buf[offset + y * stride + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 1];
// for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = (buf[offset + y * stride + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 0];
// for (int x = 0; x < 8; x++) buf[offset + y * stride + x] = (buf[offset + y * stride + x] << 1) | (val >> (7 - x) & 1);
// addr += 2;
// }
//}
//public void Decode8x8x8bpp(int[] buf, int offset, int addr, int stride=8)
//{
// for (int y = 0; y < 8; y++)
// {
// byte val = vram[addr + 49];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (val >> (7 - x) & 1);
// val = vram[addr + 48];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 33];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 32];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 17];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 16];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 1];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = (buf[offset + y * 8 + x] << 1) | (val >> (7 - x) & 1);
// val = vram[addr + 0];
// for (int x = 0; x < 8; x++) buf[offset + y * 8 + x] = val >> (7 - x) & 1;
// addr += 2;
// }
//}
///// <summary>
// /// decodes all the tiles in vram as if they were 2bpp tiles to a 64x64 tile (512x512 pixel) screen
// /// </summary>
// public void DecodeTiles2bpp(int* screen, int stride, int startcolor)
// {
// //cant handle this with our speed optimized routines
// Debug.Assert(stride == 512);
// int[] tilebuf = new int[8 * 8];
// for (int i = 0; i < 64 * 64; i++)
// {
// Decode8x8x2bpp(tilebuf, 0, 16 * i);
// int ty = i / 64;
// int tx = i % 64;
// ty *= 8;
// tx *= 8;
// for (int y = 0; y < 8; y++)
// for (int x = 0; x < 8; x++)
// {
// screen[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
// }
// }
// Paletteize(screen, 0, startcolor, 64 * 64 * 8 * 8);
// Colorize(screen, 0, 64 * 64 * 8 * 8);
// }
// /// <summary>
// /// decodes all the tiles in vram as if they were 4bpp tiles to a 64x32 tile (512x256 pixel) screen
// /// </summary>
// public void DecodeTiles4bpp(int* screen, int stride, int startcolor)
// {
// ////cant handle this with our speed optimized routines
// //Debug.Assert(stride == 512);
// //for (int i = 0; i < 64 * 32; i++)
// //{
// // int ty = i / 64;
// // int tx = i % 64;
// // ty *= 8;
// // tx *= 8;
// // for (int y = 0; y < 8; y++)
// // for (int x = 0; x < 8; x++)
// // {
// // screen[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
// // }
// //}
// //Paletteize(screen, 0, startcolor, 64 * 32 * 8 * 8);
// //Colorize(screen, 0, 64 * 32 * 8 * 8);
// }
// /// <summary>
// /// decodes all the tiles in vram as if they were 4bpp tiles to a 32x32 tile (256x256 pixel) screen
// /// </summary>
// public void DecodeTiles8bpp(int* screen, int stride, int startcolor)
// {
// ////cant handle this with our speed optimized routines
// //Debug.Assert(stride == 256);
// //int[] tilebuf = new int[8 * 8];
// //for (int i = 0; i < 32 * 32; i++)
// //{
// // Decode8x8x8bpp(tilebuf, 0, 64 * i);
// // int ty = i / 32;
// // int tx = i % 32;
// // ty *= 8;
// // tx *= 8;
// // for (int y = 0; y < 8; y++)
// // for (int x = 0; x < 8; x++)
// // {
// // screen[(ty + y) * stride + tx + x] = tilebuf[y * 8 + x];
// // }
// //}
// //Paletteize(screen, 0, startcolor, 32 * 32 * 8 * 8);
// //Colorize(screen, 0, 32 * 32 * 8 * 8);
// }

View File

@ -30,6 +30,9 @@
{
this.label1 = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.txtBG1TSizeDescr = new System.Windows.Forms.TextBox();
this.label15 = new System.Windows.Forms.Label();
this.txtBG1TSizeBits = new System.Windows.Forms.TextBox();
this.label13 = new System.Windows.Forms.Label();
this.txtBG1Colors = new System.Windows.Forms.TextBox();
this.txtBG1Bpp = new System.Windows.Forms.TextBox();
@ -57,6 +60,11 @@
this.txtScreenBG3Bpp = new System.Windows.Forms.TextBox();
this.txtScreenBG4Bpp = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label16 = new System.Windows.Forms.Label();
this.txtScreenBG4TSize = new System.Windows.Forms.TextBox();
this.txtScreenBG3TSize = new System.Windows.Forms.TextBox();
this.txtScreenBG2TSize = new System.Windows.Forms.TextBox();
this.txtScreenBG1TSize = new System.Windows.Forms.TextBox();
this.comboDisplayType = new System.Windows.Forms.ComboBox();
this.radioButton1 = new System.Windows.Forms.RadioButton();
this.radioButton2 = new System.Windows.Forms.RadioButton();
@ -88,6 +96,9 @@
//
// groupBox1
//
this.groupBox1.Controls.Add(this.txtBG1TSizeDescr);
this.groupBox1.Controls.Add(this.label15);
this.groupBox1.Controls.Add(this.txtBG1TSizeBits);
this.groupBox1.Controls.Add(this.label13);
this.groupBox1.Controls.Add(this.txtBG1Colors);
this.groupBox1.Controls.Add(this.txtBG1Bpp);
@ -106,15 +117,45 @@
this.groupBox1.Controls.Add(this.txtBG1SizeBits);
this.groupBox1.Location = new System.Drawing.Point(12, 102);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(327, 189);
this.groupBox1.Size = new System.Drawing.Size(230, 189);
this.groupBox1.TabIndex = 3;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "BG1";
//
// txtBG1TSizeDescr
//
this.txtBG1TSizeDescr.Location = new System.Drawing.Point(83, 43);
this.txtBG1TSizeDescr.Multiline = true;
this.txtBG1TSizeDescr.Name = "txtBG1TSizeDescr";
this.txtBG1TSizeDescr.ReadOnly = true;
this.txtBG1TSizeDescr.Size = new System.Drawing.Size(72, 18);
this.txtBG1TSizeDescr.TabIndex = 23;
this.txtBG1TSizeDescr.Text = "16x16";
//
// label15
//
this.label15.AutoSize = true;
this.label15.Location = new System.Drawing.Point(33, 46);
this.label15.Name = "label15";
this.label15.Size = new System.Drawing.Size(34, 13);
this.label15.TabIndex = 22;
this.label15.Text = "TSize";
//
// txtBG1TSizeBits
//
this.txtBG1TSizeBits.BackColor = System.Drawing.Color.LightGreen;
this.txtBG1TSizeBits.Location = new System.Drawing.Point(5, 42);
this.txtBG1TSizeBits.Multiline = true;
this.txtBG1TSizeBits.Name = "txtBG1TSizeBits";
this.txtBG1TSizeBits.ReadOnly = true;
this.txtBG1TSizeBits.Size = new System.Drawing.Size(25, 17);
this.txtBG1TSizeBits.TabIndex = 21;
this.txtBG1TSizeBits.Text = "00";
//
// label13
//
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(236, 24);
this.label13.Location = new System.Drawing.Point(156, 23);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(36, 13);
this.label13.TabIndex = 20;
@ -122,28 +163,28 @@
//
// txtBG1Colors
//
this.txtBG1Colors.Location = new System.Drawing.Point(205, 21);
this.txtBG1Colors.Location = new System.Drawing.Point(83, 21);
this.txtBG1Colors.Multiline = true;
this.txtBG1Colors.Name = "txtBG1Colors";
this.txtBG1Colors.ReadOnly = true;
this.txtBG1Colors.Size = new System.Drawing.Size(25, 17);
this.txtBG1Colors.Size = new System.Drawing.Size(72, 17);
this.txtBG1Colors.TabIndex = 19;
this.txtBG1Colors.Text = "00";
//
// txtBG1Bpp
//
this.txtBG1Bpp.Location = new System.Drawing.Point(150, 21);
this.txtBG1Bpp.Location = new System.Drawing.Point(6, 19);
this.txtBG1Bpp.Multiline = true;
this.txtBG1Bpp.Name = "txtBG1Bpp";
this.txtBG1Bpp.ReadOnly = true;
this.txtBG1Bpp.Size = new System.Drawing.Size(18, 17);
this.txtBG1Bpp.Size = new System.Drawing.Size(24, 17);
this.txtBG1Bpp.TabIndex = 18;
this.txtBG1Bpp.Text = "8";
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(170, 24);
this.label12.Location = new System.Drawing.Point(33, 21);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(32, 13);
this.label12.TabIndex = 17;
@ -151,7 +192,7 @@
//
// txtBG1TDAddrDescr
//
this.txtBG1TDAddrDescr.Location = new System.Drawing.Point(98, 86);
this.txtBG1TDAddrDescr.Location = new System.Drawing.Point(84, 135);
this.txtBG1TDAddrDescr.Multiline = true;
this.txtBG1TDAddrDescr.Name = "txtBG1TDAddrDescr";
this.txtBG1TDAddrDescr.ReadOnly = true;
@ -162,7 +203,7 @@
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(37, 91);
this.label11.Location = new System.Drawing.Point(34, 140);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(47, 13);
this.label11.TabIndex = 14;
@ -170,7 +211,7 @@
//
// txtBG1SCAddrDescr
//
this.txtBG1SCAddrDescr.Location = new System.Drawing.Point(98, 65);
this.txtBG1SCAddrDescr.Location = new System.Drawing.Point(84, 114);
this.txtBG1SCAddrDescr.Multiline = true;
this.txtBG1SCAddrDescr.Name = "txtBG1SCAddrDescr";
this.txtBG1SCAddrDescr.ReadOnly = true;
@ -181,7 +222,7 @@
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(277, 45);
this.label9.Location = new System.Drawing.Point(156, 92);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(34, 13);
this.label9.TabIndex = 9;
@ -189,7 +230,8 @@
//
// txtBG1TDAddrBits
//
this.txtBG1TDAddrBits.Location = new System.Drawing.Point(6, 88);
this.txtBG1TDAddrBits.BackColor = System.Drawing.Color.LightGreen;
this.txtBG1TDAddrBits.Location = new System.Drawing.Point(6, 137);
this.txtBG1TDAddrBits.Multiline = true;
this.txtBG1TDAddrBits.Name = "txtBG1TDAddrBits";
this.txtBG1TDAddrBits.ReadOnly = true;
@ -200,7 +242,7 @@
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(37, 68);
this.label10.Location = new System.Drawing.Point(34, 117);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(46, 13);
this.label10.TabIndex = 11;
@ -208,18 +250,18 @@
//
// txtBG1SizeInPixels
//
this.txtBG1SizeInPixels.Location = new System.Drawing.Point(205, 42);
this.txtBG1SizeInPixels.Location = new System.Drawing.Point(83, 89);
this.txtBG1SizeInPixels.Multiline = true;
this.txtBG1SizeInPixels.Name = "txtBG1SizeInPixels";
this.txtBG1SizeInPixels.ReadOnly = true;
this.txtBG1SizeInPixels.Size = new System.Drawing.Size(71, 19);
this.txtBG1SizeInPixels.Size = new System.Drawing.Size(72, 19);
this.txtBG1SizeInPixels.TabIndex = 8;
this.txtBG1SizeInPixels.Text = "1024z1024";
this.txtBG1SizeInPixels.Text = "1024x1024";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(170, 45);
this.label3.Location = new System.Drawing.Point(156, 70);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(32, 13);
this.label3.TabIndex = 7;
@ -227,7 +269,8 @@
//
// txtBG1SCAddrBits
//
this.txtBG1SCAddrBits.Location = new System.Drawing.Point(6, 65);
this.txtBG1SCAddrBits.BackColor = System.Drawing.Color.LightGreen;
this.txtBG1SCAddrBits.Location = new System.Drawing.Point(6, 114);
this.txtBG1SCAddrBits.Multiline = true;
this.txtBG1SCAddrBits.Name = "txtBG1SCAddrBits";
this.txtBG1SCAddrBits.ReadOnly = true;
@ -237,7 +280,7 @@
//
// txtBG1SizeInTiles
//
this.txtBG1SizeInTiles.Location = new System.Drawing.Point(98, 42);
this.txtBG1SizeInTiles.Location = new System.Drawing.Point(84, 67);
this.txtBG1SizeInTiles.Multiline = true;
this.txtBG1SizeInTiles.Name = "txtBG1SizeInTiles";
this.txtBG1SizeInTiles.ReadOnly = true;
@ -248,7 +291,7 @@
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(37, 45);
this.label2.Location = new System.Drawing.Point(34, 70);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(27, 13);
this.label2.TabIndex = 4;
@ -256,7 +299,8 @@
//
// txtBG1SizeBits
//
this.txtBG1SizeBits.Location = new System.Drawing.Point(6, 42);
this.txtBG1SizeBits.BackColor = System.Drawing.Color.LightGreen;
this.txtBG1SizeBits.Location = new System.Drawing.Point(6, 67);
this.txtBG1SizeBits.Multiline = true;
this.txtBG1SizeBits.Name = "txtBG1SizeBits";
this.txtBG1SizeBits.ReadOnly = true;
@ -266,6 +310,7 @@
//
// txtModeBits
//
this.txtModeBits.BackColor = System.Drawing.Color.LightGreen;
this.txtModeBits.Location = new System.Drawing.Point(6, 28);
this.txtModeBits.Multiline = true;
this.txtModeBits.Name = "txtModeBits";
@ -323,7 +368,7 @@
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(175, 30);
this.label8.Location = new System.Drawing.Point(170, 29);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(25, 13);
this.label8.TabIndex = 7;
@ -361,6 +406,11 @@
//
// groupBox2
//
this.groupBox2.Controls.Add(this.label16);
this.groupBox2.Controls.Add(this.txtScreenBG4TSize);
this.groupBox2.Controls.Add(this.txtScreenBG3TSize);
this.groupBox2.Controls.Add(this.txtScreenBG2TSize);
this.groupBox2.Controls.Add(this.txtScreenBG1TSize);
this.groupBox2.Controls.Add(this.txtScreenBG4Bpp);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.txtScreenBG3Bpp);
@ -379,6 +429,55 @@
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Screen";
//
// label16
//
this.label16.AutoSize = true;
this.label16.Location = new System.Drawing.Point(170, 53);
this.label16.Name = "label16";
this.label16.Size = new System.Drawing.Size(34, 13);
this.label16.TabIndex = 20;
this.label16.Text = "TSize";
//
// txtScreenBG4TSize
//
this.txtScreenBG4TSize.Location = new System.Drawing.Point(151, 51);
this.txtScreenBG4TSize.Multiline = true;
this.txtScreenBG4TSize.Name = "txtScreenBG4TSize";
this.txtScreenBG4TSize.ReadOnly = true;
this.txtScreenBG4TSize.Size = new System.Drawing.Size(18, 17);
this.txtScreenBG4TSize.TabIndex = 19;
this.txtScreenBG4TSize.Text = "16";
//
// txtScreenBG3TSize
//
this.txtScreenBG3TSize.Location = new System.Drawing.Point(126, 51);
this.txtScreenBG3TSize.Multiline = true;
this.txtScreenBG3TSize.Name = "txtScreenBG3TSize";
this.txtScreenBG3TSize.ReadOnly = true;
this.txtScreenBG3TSize.Size = new System.Drawing.Size(18, 17);
this.txtScreenBG3TSize.TabIndex = 18;
this.txtScreenBG3TSize.Text = "16";
//
// txtScreenBG2TSize
//
this.txtScreenBG2TSize.Location = new System.Drawing.Point(102, 51);
this.txtScreenBG2TSize.Multiline = true;
this.txtScreenBG2TSize.Name = "txtScreenBG2TSize";
this.txtScreenBG2TSize.ReadOnly = true;
this.txtScreenBG2TSize.Size = new System.Drawing.Size(18, 17);
this.txtScreenBG2TSize.TabIndex = 17;
this.txtScreenBG2TSize.Text = "16";
//
// txtScreenBG1TSize
//
this.txtScreenBG1TSize.Location = new System.Drawing.Point(78, 51);
this.txtScreenBG1TSize.Multiline = true;
this.txtScreenBG1TSize.Name = "txtScreenBG1TSize";
this.txtScreenBG1TSize.ReadOnly = true;
this.txtScreenBG1TSize.Size = new System.Drawing.Size(18, 17);
this.txtScreenBG1TSize.TabIndex = 16;
this.txtScreenBG1TSize.Text = "16";
//
// comboDisplayType
//
this.comboDisplayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@ -658,5 +757,13 @@
private System.Windows.Forms.RadioButton radioButton12;
private System.Windows.Forms.RadioButton radioButton13;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.TextBox txtBG1TSizeDescr;
private System.Windows.Forms.Label label15;
private System.Windows.Forms.TextBox txtBG1TSizeBits;
private System.Windows.Forms.Label label16;
private System.Windows.Forms.TextBox txtScreenBG4TSize;
private System.Windows.Forms.TextBox txtScreenBG3TSize;
private System.Windows.Forms.TextBox txtScreenBG2TSize;
private System.Windows.Forms.TextBox txtScreenBG1TSize;
}
}

View File

@ -50,11 +50,18 @@ namespace BizHawk.MultiClient
var si = gd.ScanScreenInfo();
txtModeBits.Text = si.Mode.MODE.ToString();
txtBG1Bpp.Text = txtScreenBG1Bpp.Text = FormatBpp(si.BG.BG1.Bpp);
txtScreenBG1Bpp.Text = FormatBpp(si.BG.BG1.Bpp);
txtScreenBG2Bpp.Text = FormatBpp(si.BG.BG2.Bpp);
txtScreenBG3Bpp.Text = FormatBpp(si.BG.BG3.Bpp);
txtScreenBG4Bpp.Text = FormatBpp(si.BG.BG4.Bpp);
txtScreenBG1TSize.Text = FormatBpp(si.BG.BG1.TileSize);
txtScreenBG2TSize.Text = FormatBpp(si.BG.BG2.TileSize);
txtScreenBG3TSize.Text = FormatBpp(si.BG.BG3.TileSize);
txtScreenBG4TSize.Text = FormatBpp(si.BG.BG4.TileSize);
txtBG1TSizeBits.Text = si.BG.BG1.TILESIZE.ToString();
txtBG1TSizeDescr.Text = string.Format("{0}x{0}", si.BG.BG1.TileSize);
txtBG1Bpp.Text = FormatBpp(si.BG.BG1.Bpp);
txtBG1SizeBits.Text = si.BG.BG1.SCSIZE.ToString();
txtBG1SizeInTiles.Text = FormatScreenSizeInTiles(si.BG.BG1.ScreenSize);
txtBG1SCAddrBits.Text = si.BG.BG1.SCADDR.ToString();
@ -62,6 +69,11 @@ namespace BizHawk.MultiClient
txtBG1Colors.Text = (1 << si.BG.BG1.Bpp).ToString();
txtBG1TDAddrBits.Text = si.BG.BG1.TDADDR.ToString();
txtBG1TDAddrDescr.Text = FormatVramAddress(si.BG.BG1.TDADDR << 13);
var sizeInPixels = SNESGraphicsDecoder.SizeInTilesForBGSize(si.BG.BG1.ScreenSize);
sizeInPixels.Width *= si.BG.BG1.TileSize;
sizeInPixels.Height *= si.BG.BG1.TileSize;
txtBG1SizeInPixels.Text = string.Format("{0}x{1}", sizeInPixels.Width, sizeInPixels.Height);
RenderView();
}
@ -83,21 +95,38 @@ namespace BizHawk.MultiClient
};
var gd = new SNESGraphicsDecoder();
gd.CacheTiles();
string selection = comboDisplayType.SelectedItem as string;
if (selection == "Tiles as 2bpp")
{
allocate(512, 512);
gd.DecodeTiles2bpp(pixelptr, stride / 4, 0);
gd.RenderTilesToScreen(pixelptr, stride / 4, 2, 0);
}
if (selection == "Tiles as 4bpp")
{
allocate(512, 512);
gd.DecodeTiles4bpp(pixelptr, stride / 4, 0);
gd.RenderTilesToScreen(pixelptr, stride / 4, 4, 0);
}
if (selection == "Tiles as 8bpp")
{
allocate(256, 256);
gd.DecodeTiles8bpp(pixelptr, stride / 4, 0);
gd.RenderTilesToScreen(pixelptr, stride / 4, 8, 0);
}
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];
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);
}
if (bmp != null)
@ -114,5 +143,7 @@ namespace BizHawk.MultiClient
}
}
}