From 3c6549a7bb9ac4168f0a2819b5cdf8be8a82f541 Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 21 Sep 2012 17:21:21 +0000 Subject: [PATCH] snesgfx-decode mode7 graphics --- .../Consoles/Nintendo/SNES/LibsnesCore.cs | 42 --------- .../Nintendo/SNES/SNESGraphicsDecoder.cs | 86 +++++++++++++++---- .../SNESGraphicsDebugger.Designer.cs | 18 +++- .../SNESTools/SNESGraphicsDebugger.cs | 42 ++++++--- 4 files changed, 116 insertions(+), 72 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs index c54132a48e..22851655bb 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -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 diff --git a/BizHawk.Emulation/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs b/BizHawk.Emulation/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs index 3740c220f7..7ccbdd9106 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs @@ -233,6 +233,31 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES Priority = 1, Horz = 2, Vert = 4, } + /// + /// decodes a mode7 BG. youll still need to paletteize and colorize it. + /// + 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; + } + } + } + } + } + /// /// 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][]; /// - /// 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 /// 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]; + } } /// @@ -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) + /// + /// renders the mode7 tiles to a screen with the predefined size. + /// + 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); } /// - /// 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 /// - 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++) diff --git a/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.Designer.cs b/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.Designer.cs index dec193ba2b..adf6e55e49 100644 --- a/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.Designer.cs +++ b/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.Designer.cs @@ -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; } } \ No newline at end of file diff --git a/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.cs b/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.cs index 95ceccd7b9..c66c187dfb 100644 --- a/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.cs +++ b/BizHawk.MultiClient/SNESTools/SNESGraphicsDebugger.cs @@ -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); + } } }