diff --git a/BinxelviewForm.Designer.cs b/BinxelviewForm.Designer.cs index 51e8051..43df697 100644 --- a/BinxelviewForm.Designer.cs +++ b/BinxelviewForm.Designer.cs @@ -51,10 +51,8 @@ private void InitializeComponent() this.optionsMenuSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.gridOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.snapScrollOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.splitViewOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsMenuSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.twiddleZOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.twiddleNOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.optionsMenuSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.loadOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveCurrentOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -130,7 +128,9 @@ private void InitializeComponent() this.pixelsToPaletteContextItem = new System.Windows.Forms.ToolStripMenuItem(); this.pixelScroll = new System.Windows.Forms.VScrollBar(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.splitViewOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.advancedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.twiddleZAdvancedMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.twiddleNAdvancedMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStripMain.SuspendLayout(); this.tableTop.SuspendLayout(); this.groupPacking.SuspendLayout(); @@ -170,6 +170,7 @@ private void InitializeComponent() this.menuStripMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.presetToolStripMenuItem, + this.advancedToolStripMenuItem, this.optionsToolStripMenuItem, this.helpToolStripMenuItem}); this.menuStripMain.Location = new System.Drawing.Point(0, 0); @@ -244,21 +245,21 @@ private void InitializeComponent() // reloadPresetMenuItem // this.reloadPresetMenuItem.Name = "reloadPresetMenuItem"; - this.reloadPresetMenuItem.Size = new System.Drawing.Size(150, 22); + this.reloadPresetMenuItem.Size = new System.Drawing.Size(180, 22); this.reloadPresetMenuItem.Text = "&Reload"; this.reloadPresetMenuItem.Click += new System.EventHandler(this.reloadPresetMenuItem_Click); // // setDirectoryPresetMenuItem // this.setDirectoryPresetMenuItem.Name = "setDirectoryPresetMenuItem"; - this.setDirectoryPresetMenuItem.Size = new System.Drawing.Size(150, 22); + this.setDirectoryPresetMenuItem.Size = new System.Drawing.Size(180, 22); this.setDirectoryPresetMenuItem.Text = "Set &Directory..."; this.setDirectoryPresetMenuItem.Click += new System.EventHandler(this.setDirectoryPresetMenuItem_Click); // // presetMenuSeparator // this.presetMenuSeparator.Name = "presetMenuSeparator"; - this.presetMenuSeparator.Size = new System.Drawing.Size(147, 6); + this.presetMenuSeparator.Size = new System.Drawing.Size(177, 6); // // optionsToolStripMenuItem // @@ -273,9 +274,6 @@ private void InitializeComponent() this.snapScrollOptionsMenuItem, this.splitViewOptionsMenuItem, this.optionsMenuSeparator3, - this.twiddleZOptionsMenuItem, - this.twiddleNOptionsMenuItem, - this.optionsMenuSeparator4, this.loadOptionsMenuItem, this.saveOptionsMenuItem, this.saveCurrentOptionsMenuItem, @@ -345,30 +343,18 @@ private void InitializeComponent() this.snapScrollOptionsMenuItem.Text = "Sna&p scroll to next stride"; this.snapScrollOptionsMenuItem.Click += new System.EventHandler(this.snapScrollOptionsMenuItem_Click); // + // splitViewOptionsMenuItem + // + this.splitViewOptionsMenuItem.Name = "splitViewOptionsMenuItem"; + this.splitViewOptionsMenuItem.Size = new System.Drawing.Size(203, 22); + this.splitViewOptionsMenuItem.Text = "Pixel &Window"; + this.splitViewOptionsMenuItem.Click += new System.EventHandler(this.splitViewOptionsMenuItem_Click); + // // optionsMenuSeparator3 // this.optionsMenuSeparator3.Name = "optionsMenuSeparator3"; this.optionsMenuSeparator3.Size = new System.Drawing.Size(200, 6); // - // twiddleZOptionsMenuItem - // - this.twiddleZOptionsMenuItem.Name = "twiddleZOptionsMenuItem"; - this.twiddleZOptionsMenuItem.Size = new System.Drawing.Size(203, 22); - this.twiddleZOptionsMenuItem.Text = "Twiddle &Z"; - this.twiddleZOptionsMenuItem.Click += new System.EventHandler(this.twiddleZOptionsMenuItem_Click); - // - // twiddleNOptionsMenuItem - // - this.twiddleNOptionsMenuItem.Name = "twiddleNOptionsMenuItem"; - this.twiddleNOptionsMenuItem.Size = new System.Drawing.Size(203, 22); - this.twiddleNOptionsMenuItem.Text = "Twiddle &N"; - this.twiddleNOptionsMenuItem.Click += new System.EventHandler(this.twiddleNOptionsMenuItem_Click); - // - // optionsMenuSeparator4 - // - this.optionsMenuSeparator4.Name = "optionsMenuSeparator4"; - this.optionsMenuSeparator4.Size = new System.Drawing.Size(200, 6); - // // loadOptionsMenuItem // this.loadOptionsMenuItem.Name = "loadOptionsMenuItem"; @@ -1379,12 +1365,28 @@ private void InitializeComponent() this.pixelScroll.TabStop = true; this.pixelScroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.pixelScroll_Scroll); // - // splitViewOptionsMenuItem + // advancedToolStripMenuItem // - this.splitViewOptionsMenuItem.Name = "splitViewOptionsMenuItem"; - this.splitViewOptionsMenuItem.Size = new System.Drawing.Size(203, 22); - this.splitViewOptionsMenuItem.Text = "Pixel &Window"; - this.splitViewOptionsMenuItem.Click += new System.EventHandler(this.splitViewOptionsMenuItem_Click); + this.advancedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.twiddleZAdvancedMenuItem, + this.twiddleNAdvancedMenuItem}); + this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem"; + this.advancedToolStripMenuItem.Size = new System.Drawing.Size(72, 20); + this.advancedToolStripMenuItem.Text = "&Advanced"; + // + // twiddleZAdvancedMenuItem + // + this.twiddleZAdvancedMenuItem.Name = "twiddleZAdvancedMenuItem"; + this.twiddleZAdvancedMenuItem.Size = new System.Drawing.Size(180, 22); + this.twiddleZAdvancedMenuItem.Text = "Twiddle &Z"; + this.twiddleZAdvancedMenuItem.Click += new System.EventHandler(this.twiddleZAdvancedMenuItem_Click); + // + // twiddleNAdvancedMenuItem + // + this.twiddleNAdvancedMenuItem.Name = "twiddleNAdvancedMenuItem"; + this.twiddleNAdvancedMenuItem.Size = new System.Drawing.Size(180, 22); + this.twiddleNAdvancedMenuItem.Text = "Twiddle &N"; + this.twiddleNAdvancedMenuItem.Click += new System.EventHandler(this.twiddleNAdvancedMenuItem_Click); // // BinxelviewForm // @@ -1528,9 +1530,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem snapScrollOptionsMenuItem; private System.Windows.Forms.ToolStripMenuItem verticalLayoutOptionsMenuItem; private System.Windows.Forms.ToolStripMenuItem horizontalLayoutOptionsMenuItem; - private System.Windows.Forms.ToolStripMenuItem twiddleZOptionsMenuItem; - private System.Windows.Forms.ToolStripSeparator optionsMenuSeparator4; - private System.Windows.Forms.ToolStripMenuItem twiddleNOptionsMenuItem; private System.Windows.Forms.ToolStripSeparator optionsMenuSeparator3; private System.Windows.Forms.ToolStripMenuItem gridOptionsMenuItem; private System.Windows.Forms.ToolStripMenuItem exportBinaryChunkFileMenuItem; @@ -1548,6 +1547,9 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem saveOnExitOptionsMenuItem; private System.Windows.Forms.ToolStripMenuItem saveCurrentOptionsMenuItem; private System.Windows.Forms.ToolStripMenuItem splitViewOptionsMenuItem; + private System.Windows.Forms.ToolStripMenuItem advancedToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem twiddleZAdvancedMenuItem; + private System.Windows.Forms.ToolStripMenuItem twiddleNAdvancedMenuItem; } } diff --git a/BinxelviewForm.cs b/BinxelviewForm.cs index 1466060..912b685 100644 --- a/BinxelviewForm.cs +++ b/BinxelviewForm.cs @@ -16,7 +16,7 @@ public partial class BinxelviewForm : Form const string APPNAME = "Binxelview"; const string APPDATA_FOLDER = "Binxelview"; const int MAX_BPP = 32; - const int PRESET_VERSION = 2; + const int PRESET_VERSION = 3; const int PALETTE_BITS = 14; // maximum bits to fill 128 x 128 square const int PALETTE_DIM = 128; // should match paletteBox size const int ZOOM_MAX = 32; @@ -85,10 +85,6 @@ enum PaletteMode bool snap_scroll; bool horizontal_layout; bool split_view; - int twiddle; // Twiddle probably belongs in preset, but its use is very rare, and I didn't want it to take up panel space. - // If something more important needs a PRESET_VERSION 3, we should add it then to the preset. - // We could maybe place rare options like this into an "advanced" menu on the menu bar, - // instead of requiring UI panel space for it. string palette_path = ""; string preset_dir = ""; bool save_ini = true; // not changed by defaultOption @@ -114,6 +110,7 @@ struct Preset public int next_stride_byte; public int next_stride_bit; public bool next_stride_auto; + public int twiddle; public int tile_size_x; public int tile_stride_byte_x; public int tile_stride_bit_x; @@ -174,7 +171,7 @@ public bool saveFile(string path) using (StreamWriter sw = File.CreateText(path)) { sw.WriteLine(string.Format("{0}", PRESET_VERSION)); - sw.WriteLine(string.Format("{0} {1}", little_endian ? 1 : 0, chunky ? 1 : 0)); + sw.WriteLine(string.Format("{0} {1} {2}", little_endian ? 1 : 0, chunky ? 1 : 0, twiddle)); sw.WriteLine(string.Format("{0} {1} {2}", bpp, width, height)); sw.WriteLine(string.Format("{0} {1} {2}", pixel_stride_byte, row_stride_byte, next_stride_byte)); sw.WriteLine(string.Format("{0} {1} {2}", pixel_stride_bit, row_stride_bit, next_stride_bit)); @@ -203,6 +200,7 @@ public bool loadFile(string path) { Debug.WriteLine("Preset.loadFile(\""+path+"\")"); empty(); + int linecount = 0; try { // version @@ -219,7 +217,7 @@ public bool loadFile(string path) using (TextReader tr = File.OpenText(path)) { - string l = tr.ReadLine(); + string l = tr.ReadLine(); ++linecount; int v = int.Parse(l); if (v > PRESET_VERSION) { @@ -238,6 +236,8 @@ public bool loadFile(string path) bpp = int.Parse(ls[0]); width = int.Parse(ls[1]); height = int.Parse(ls[2]); + if (version >= 3) twiddle = int.Parse(ls[3]); + else twiddle = 0; l = tr.ReadLine(); ls = l.Split(' '); @@ -317,7 +317,7 @@ public bool loadFile(string path) } catch (Exception ex) { - last_error = ex.ToString(); + last_error = string.Format("Line {0}: ",linecount) + ex.ToString(); return false; } @@ -340,7 +340,6 @@ void defaultOption() snap_scroll = true; horizontal_layout = false; split_view = false; - twiddle = 0; palette_path = ""; preset_dir = ""; // note: save_ini is not changed, intentionally, default options shouldn't alter the current ini read-only state @@ -514,14 +513,6 @@ string parseOption(string optline, string base_path, bool ini_file) horizontal_layout = (v != 0); return ""; } - if (opt == "TWIDDLE") - { - int v; - if (!int.TryParse(val,out v)) return "Could not parse integer for twiddle: "+val; - if (v < 0 || v > 2) return "Twiddle value must be 0, 1 or 2: "+val; - twiddle = v; - return ""; - } return "Invalid option: "+optline; } @@ -605,7 +596,6 @@ string saveIni(string path) sw.WriteLine(string.Format("splitviewh={0}",split_view_form.Height)); } sw.WriteLine(string.Format("horizontal={0}",horizontal_layout ? 1 : 0)); - sw.WriteLine(string.Format("twiddle={0}",twiddle)); sw.WriteLine("# end"); } } @@ -683,11 +673,11 @@ void twiddleCacheCheck(int tw, int th) { // rebuild index of twiddle ordering if (twiddle_cache == null || - twiddle_cache_order != twiddle || + twiddle_cache_order != preset.twiddle || twiddle_cache_w != tw || twiddle_cache_h != th ) { - twiddle_cache_order = twiddle; + twiddle_cache_order = preset.twiddle; twiddle_cache_w = tw; twiddle_cache_h = th; twiddle_cache = new int[tw * th]; @@ -699,7 +689,7 @@ void twiddleCacheCheck(int tw, int th) int twy = y; int bit = 0; int twxy = 0; - if (twiddle == 2) // N instead of Z order + if (preset.twiddle == 2) // N instead of Z order { int temp = twx; twx = twy; @@ -833,7 +823,7 @@ void renderGrid(long pos, int gx, int gy, int padx, int pady, int minx, int miny if (tile_size_y == 0) tile_shift_y = 0; // tile stride is converted to a relative shift that is applied at the end of each tile - if (twiddle != 0) + if (preset.twiddle != 0) { twiddleCacheCheck(tw,th); } @@ -1595,6 +1585,9 @@ void redrawPreset() dataGridPixel.FirstDisplayedScrollingRowIndex = old_scroll; dataGridPixel.Enabled = !preset.chunky; + twiddleZAdvancedMenuItem.Checked = preset.twiddle == 1; + twiddleNAdvancedMenuItem.Checked = preset.twiddle == 2; + disable_pixel_redraw = old_disable_pixel_redraw; // restore pixel redraw } @@ -1636,8 +1629,6 @@ void redrawOptions() // make sure the UI state matches current options comboBoxPalette.SelectedIndex = (int)palette_mode - 1; verticalLayoutOptionsMenuItem.Checked = !horizontal_layout; horizontalLayoutOptionsMenuItem.Checked = horizontal_layout; - twiddleZOptionsMenuItem.Checked = twiddle == 1; - twiddleNOptionsMenuItem.Checked = twiddle == 2; bgBox.BackColor = background; saveOnExitOptionsMenuItem.Checked = save_ini; if (!split_view) @@ -1784,6 +1775,22 @@ void presetMenu_Select(object sender, EventArgs e) // clicking on a generated pr redrawPixels(); } + private void twiddleZAdvancedMenuItem_Click(object sender, EventArgs e) + { + if (preset.twiddle == 1) preset.twiddle = 0; + else preset.twiddle = 1; + redrawPreset(); + redrawPixels(); + } + + private void twiddleNAdvancedMenuItem_Click(object sender, EventArgs e) + { + if (preset.twiddle == 2) preset.twiddle = 0; + else preset.twiddle = 2; + redrawPreset(); + redrawPixels(); + } + private void decimalPositionOptionsMenuItem_Click(object sender, EventArgs e) { decimal_position = true; @@ -1833,22 +1840,6 @@ private void splitViewOptionsMenuItem_Click(object sender, EventArgs e) redrawPixels(); } - private void twiddleZOptionsMenuItem_Click(object sender, EventArgs e) - { - if (twiddle == 1) twiddle = 0; - else twiddle = 1; - redrawOptions(); - redrawPixels(); - } - - private void twiddleNOptionsMenuItem_Click(object sender, EventArgs e) - { - if (twiddle == 2) twiddle = 0; - else twiddle = 2; - redrawOptions(); - redrawPixels(); - } - private void loadOptionsMenuItem_Click(object sender, EventArgs e) { OpenFileDialog d = new OpenFileDialog(); @@ -2426,7 +2417,7 @@ public void pixelBox_MouseMove(object sender, MouseEventArgs e) int row_stride = (preset.row_stride_byte * 8) + preset.row_stride_bit; int pixel_stride = (preset.pixel_stride_byte * 8) + preset.pixel_stride_bit; - if (twiddle != 0) + if (preset.twiddle != 0) { twiddleCacheCheck(tw, th); int twoxy = twiddle_cache[ox + (oy * tw)]; diff --git a/readme.txt b/readme.txt index 80c8343..e3eb3ad 100644 --- a/readme.txt +++ b/readme.txt @@ -117,6 +117,13 @@ Pixel Formats Advance 16 bytes (D) from the start of the row, then read the second tile. The next row will begin again 1 byte (B) from the start of the previous row. +* Twiddle (Advanced menu) + This will rearrange the pixel X and Y within a tile to use a Morton (Z/N) ordering, + commonly seen in square textures "twiddled" or "swizzled" for GPU cache coherence. + Width and Height should be the same, and a power of two. + See: https://en.wikipedia.org/wiki/Z-order_curve + + Presets can be loaded and saved. The Preset menu is populated both from the current working directory, and also from the directory of the executable. This can be changed instead to one @@ -150,10 +157,6 @@ Other Notes Due to signed 32-bit integer limitations of C sharp, files must be less than 2GB in size. To inspect extremely large files, you may have to split them first. -The Twiddle options will rearrange the pixel X and Y within a tile to use a -Morton (Z/N) ordering, commonly seen in square textures "twiddled" or "swizzled" for -GPU cache coherence. - Command Line Options and INI Configuration Files ------------------------------------------------