mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-01 07:50:37 +00:00
Improve Apple II hi-res visualizer
Added a new category "sprite sheet", which is essentially a more generalized version of the bitmap font renderer. It has the full set of options for col/row/cell stride and colors. (Issue #74, issue #75) Added a flag that flips the high bits on bitmaps. Sometimes data is stored with the high bit clear, but the high bit is set as it's rendered. (Issue #76) Also, fixed the keyboard shortcuts in the Edit Visualization Set window, which were 'N' for both "New ___" items. (Issue #57)
This commit is contained in:
parent
b0278c9c51
commit
07d477fc70
@ -30,6 +30,7 @@ namespace RuntimeData.Apple {
|
||||
|
||||
// Visualization identifiers; DO NOT change or projects that use them will break.
|
||||
private const string VIS_GEN_BITMAP = "apple2-hi-res-bitmap";
|
||||
private const string VIS_GEN_BITMAP_GRID = "apple2-hi-res-bitmap-grid";
|
||||
private const string VIS_GEN_BITMAP_FONT = "apple2-hi-res-bitmap-font";
|
||||
private const string VIS_GEN_HR_SCREEN = "apple2-hi-res-screen";
|
||||
|
||||
@ -38,8 +39,10 @@ namespace RuntimeData.Apple {
|
||||
private const string P_HEIGHT = "height";
|
||||
private const string P_COL_STRIDE = "colStride";
|
||||
private const string P_ROW_STRIDE = "rowStride";
|
||||
private const string P_CELL_STRIDE = "cellStride";
|
||||
private const string P_IS_COLOR = "isColor";
|
||||
private const string P_IS_FIRST_ODD = "isFirstOdd";
|
||||
private const string P_IS_HIGH_BIT_FLIPPED = "isHighBitFlipped";
|
||||
private const string P_COLOR_CONV_MODE = "colorConvMode";
|
||||
private const string P_ITEM_BYTE_WIDTH = "itemByteWidth";
|
||||
private const string P_ITEM_HEIGHT = "itemHeight";
|
||||
@ -54,23 +57,48 @@ namespace RuntimeData.Apple {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Width (in bytes)",
|
||||
P_BYTE_WIDTH, typeof(int), 1, 40, 0, 1),
|
||||
P_BYTE_WIDTH, typeof(int), 1, 256, 0, 1),
|
||||
new VisParamDescr("Height",
|
||||
P_HEIGHT, typeof(int), 1, 192, 0, 1),
|
||||
P_HEIGHT, typeof(int), 1, 1024, 0, 1),
|
||||
new VisParamDescr("Column stride (bytes)",
|
||||
P_COL_STRIDE, typeof(int), 0, 256, 0, 0),
|
||||
P_COL_STRIDE, typeof(int), 0, 1024, 0, 0),
|
||||
new VisParamDescr("Row stride (bytes)",
|
||||
P_ROW_STRIDE, typeof(int), 0, 256, 0, 0),
|
||||
P_ROW_STRIDE, typeof(int), 0, 1024, 0, 0),
|
||||
new VisParamDescr("Color",
|
||||
P_IS_COLOR, typeof(bool), 0, 0, 0, true),
|
||||
new VisParamDescr("First col odd",
|
||||
P_IS_FIRST_ODD, typeof(bool), 0, 0, 0, false),
|
||||
new VisParamDescr("High bit flipped",
|
||||
P_IS_HIGH_BIT_FLIPPED, typeof(bool), 0, 0, 0, false),
|
||||
//new VisParamDescr("Color conv mode",
|
||||
// P_COLOR_CONV_MODE, typeof(int), (int)ColorMode.SimpleColor,
|
||||
// (int)ColorMode.IIgsRGB, 0, (int)ColorMode.SimpleColor),
|
||||
//new VisParamDescr("Test Float",
|
||||
// "floaty", typeof(float), -5.0f, 5.0f, 0, 0.1f),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_BITMAP_GRID, "Apple II Hi-Res Sprite Sheet", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
|
||||
new VisParamDescr("Cell width (in bytes)",
|
||||
P_ITEM_BYTE_WIDTH, typeof(int), 1, 40, 0, 1),
|
||||
new VisParamDescr("Cell height",
|
||||
P_ITEM_HEIGHT, typeof(int), 1, 192, 0, 1),
|
||||
new VisParamDescr("Column stride (bytes)",
|
||||
P_COL_STRIDE, typeof(int), 0, 1024, 0, 0),
|
||||
new VisParamDescr("Row stride (bytes)",
|
||||
P_ROW_STRIDE, typeof(int), 0, 1024, 0, 0),
|
||||
new VisParamDescr("Cell stride (bytes)",
|
||||
P_CELL_STRIDE, typeof(int), 0, 4096, 0, 0),
|
||||
new VisParamDescr("Number of items",
|
||||
P_COUNT, typeof(int), 1, 1024, 0, 64),
|
||||
new VisParamDescr("Color",
|
||||
P_IS_COLOR, typeof(bool), 0, 0, 0, true),
|
||||
new VisParamDescr("First col odd",
|
||||
P_IS_FIRST_ODD, typeof(bool), 0, 0, 0, false),
|
||||
new VisParamDescr("High bit flipped",
|
||||
P_IS_HIGH_BIT_FLIPPED, typeof(bool), 0, 0, 0, false),
|
||||
}),
|
||||
new VisDescr(VIS_GEN_BITMAP_FONT, "Apple II Hi-Res Bitmap Font", VisDescr.VisType.Bitmap,
|
||||
new VisParamDescr[] {
|
||||
new VisParamDescr("File offset (hex)",
|
||||
@ -122,6 +150,8 @@ namespace RuntimeData.Apple {
|
||||
switch (descr.Ident) {
|
||||
case VIS_GEN_BITMAP:
|
||||
return GenerateBitmap(parms);
|
||||
case VIS_GEN_BITMAP_GRID:
|
||||
return GenerateBitmapGrid(parms);
|
||||
case VIS_GEN_BITMAP_FONT:
|
||||
return GenerateBitmapFont(parms);
|
||||
case VIS_GEN_HR_SCREEN:
|
||||
@ -140,6 +170,7 @@ namespace RuntimeData.Apple {
|
||||
int rowStride = Util.GetFromObjDict(parms, P_ROW_STRIDE, 0);
|
||||
bool isColor = Util.GetFromObjDict(parms, P_IS_COLOR, true);
|
||||
bool isFirstOdd = Util.GetFromObjDict(parms, P_IS_FIRST_ODD, false);
|
||||
bool isHighBitFlipped = Util.GetFromObjDict(parms, P_IS_HIGH_BIT_FLIPPED, false);
|
||||
int colorConvMode = !isColor ? (int)ColorMode.Mono :
|
||||
Util.GetFromObjDict(parms, P_COLOR_CONV_MODE, (int)ColorMode.SimpleColor);
|
||||
|
||||
@ -178,25 +209,74 @@ namespace RuntimeData.Apple {
|
||||
SetHiResPalette(vb);
|
||||
|
||||
RenderBitmap(mFileData, offset, byteWidth, height, colStride, rowStride,
|
||||
(ColorMode)colorConvMode, isFirstOdd, vb, 0, 0);
|
||||
(ColorMode)colorConvMode, isFirstOdd, isHighBitFlipped, vb, 0, 0);
|
||||
return vb;
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateBitmapGrid(ReadOnlyDictionary<string, object> parms) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
int itemByteWidth = Util.GetFromObjDict(parms, P_ITEM_BYTE_WIDTH, 1);
|
||||
int itemHeight = Util.GetFromObjDict(parms, P_ITEM_HEIGHT, 8);
|
||||
int colStride = Util.GetFromObjDict(parms, P_COL_STRIDE, 0);
|
||||
int rowStride = Util.GetFromObjDict(parms, P_ROW_STRIDE, 0);
|
||||
int cellStride = Util.GetFromObjDict(parms, P_CELL_STRIDE, 0);
|
||||
int count = Util.GetFromObjDict(parms, P_COUNT, 96);
|
||||
bool isColor = Util.GetFromObjDict(parms, P_IS_COLOR, true);
|
||||
bool isFirstOdd = Util.GetFromObjDict(parms, P_IS_FIRST_ODD, false);
|
||||
bool isHighBitFlipped = Util.GetFromObjDict(parms, P_IS_HIGH_BIT_FLIPPED, false);
|
||||
|
||||
ColorMode colorConvMode = !isColor ? ColorMode.Mono :
|
||||
(ColorMode)Util.GetFromObjDict(parms, P_COLOR_CONV_MODE, (int)ColorMode.SimpleColor);
|
||||
|
||||
return GenerateGrid(offset, itemByteWidth, itemHeight, colStride, rowStride,
|
||||
cellStride, count, colorConvMode, isFirstOdd, isHighBitFlipped);
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateBitmapFont(ReadOnlyDictionary<string, object> parms) {
|
||||
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
|
||||
int itemByteWidth = Util.GetFromObjDict(parms, P_ITEM_BYTE_WIDTH, 1);
|
||||
int itemHeight = Util.GetFromObjDict(parms, P_ITEM_HEIGHT, 8);
|
||||
int count = Util.GetFromObjDict(parms, P_COUNT, 96);
|
||||
|
||||
return GenerateGrid(offset, itemByteWidth, itemHeight, 0, 0, 0, count,
|
||||
ColorMode.Mono, false, false);
|
||||
}
|
||||
|
||||
private IVisualization2d GenerateGrid(int offset, int itemByteWidth, int itemHeight,
|
||||
int colStride, int rowStride, int cellStride, int count,
|
||||
ColorMode colorConvMode, bool isFirstOdd, bool isHighBitFlipped) {
|
||||
|
||||
// We allow the stride entries to be zero to indicate a "dense" bitmap.
|
||||
if (colStride == 0) {
|
||||
colStride = 1;
|
||||
}
|
||||
if (rowStride == 0) {
|
||||
rowStride = itemByteWidth * colStride;
|
||||
}
|
||||
if (cellStride == 0) {
|
||||
cellStride = rowStride * itemHeight;
|
||||
}
|
||||
|
||||
if (offset < 0 || offset >= mFileData.Length ||
|
||||
itemByteWidth <= 0 || itemByteWidth > MAX_DIM ||
|
||||
itemHeight <= 0 || itemHeight > MAX_DIM) {
|
||||
itemHeight <= 0 || itemHeight > MAX_DIM ||
|
||||
count <= 0 || count > MAX_DIM) {
|
||||
// should be caught by editor
|
||||
mAppRef.ReportError("Invalid parameter");
|
||||
return null;
|
||||
}
|
||||
|
||||
int lastOffset = offset + itemByteWidth * itemHeight * count - 1;
|
||||
if (colStride <= 0 || colStride > MAX_DIM) {
|
||||
mAppRef.ReportError("Invalid column stride");
|
||||
return null;
|
||||
}
|
||||
if (rowStride < itemByteWidth * colStride - (colStride - 1) || rowStride > MAX_DIM) {
|
||||
mAppRef.ReportError("Invalid row stride");
|
||||
return null;
|
||||
}
|
||||
|
||||
int lastOffset = offset + (cellStride * (count - 1)) +
|
||||
rowStride * itemHeight - (colStride - 1) - 1;
|
||||
if (lastOffset >= mFileData.Length) {
|
||||
mAppRef.ReportError("Bitmap runs off end of file (last offset +" +
|
||||
lastOffset.ToString("x6") + ")");
|
||||
@ -221,18 +301,10 @@ namespace RuntimeData.Apple {
|
||||
|
||||
int cellx = 1;
|
||||
int celly = 1;
|
||||
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
|
||||
//byte color = (byte)(1 + idx % 6);
|
||||
//for (int y = 0; y < itemHeight; y++) {
|
||||
// for (int x = 0; x < itemByteWidth * 7; x++) {
|
||||
// vb.SetPixelIndex(cellx + x, celly + y, color);
|
||||
// }
|
||||
//}
|
||||
RenderBitmap(mFileData, offset + idx * itemByteWidth * itemHeight,
|
||||
itemByteWidth, itemHeight, 1, itemByteWidth,
|
||||
ColorMode.Mono, false,
|
||||
RenderBitmap(mFileData, offset + idx * cellStride,
|
||||
itemByteWidth, itemHeight, colStride, rowStride,
|
||||
colorConvMode, isFirstOdd, isHighBitFlipped,
|
||||
vb, cellx, celly);
|
||||
|
||||
cellx += itemByteWidth * 7 + 1;
|
||||
@ -296,7 +368,7 @@ namespace RuntimeData.Apple {
|
||||
VisBitmap8 vb = new VisBitmap8(HR_WIDTH, HR_HEIGHT);
|
||||
SetHiResPalette(vb);
|
||||
RenderBitmap(buf, 0, HR_BYTE_WIDTH, HR_HEIGHT, 1, HR_BYTE_WIDTH,
|
||||
isColor ? ColorMode.SimpleColor : ColorMode.Mono, false,
|
||||
isColor ? ColorMode.SimpleColor : ColorMode.Mono, false, false,
|
||||
vb, 0, 0);
|
||||
return vb;
|
||||
}
|
||||
@ -319,12 +391,14 @@ namespace RuntimeData.Apple {
|
||||
/// <param name="colorMode">Color conversion mode.</param>
|
||||
/// <param name="isFirstOdd">If true, render as if we're starting on an odd column.
|
||||
/// This affects the colors.</param>
|
||||
/// <param name="isHighBitFlipped">If true, render as if the high bit has the
|
||||
/// opposite value. This affects the colors.</param>
|
||||
/// <param name="vb">Output bitmap object.</param>
|
||||
/// <param name="xstart">Initial X position in the output.</param>
|
||||
/// <param name="ystart">Initial Y position in the output.</param>
|
||||
private void RenderBitmap(byte[] data, int offset, int byteWidth, int height,
|
||||
int colStride, int rowStride, ColorMode colorMode, bool isFirstOdd,
|
||||
VisBitmap8 vb, int xstart, int ystart) {
|
||||
bool isHighBitFlipped, VisBitmap8 vb, int xstart, int ystart) {
|
||||
int bx = xstart;
|
||||
int by = ystart;
|
||||
switch (colorMode) {
|
||||
@ -372,7 +446,7 @@ namespace RuntimeData.Apple {
|
||||
bool hiBitSet = (val & 0x80) != 0;
|
||||
|
||||
for (int bit = 0; bit < 7; bit++) {
|
||||
hiFlags[idx] = hiBitSet;
|
||||
hiFlags[idx] = hiBitSet ^ isHighBitFlipped;
|
||||
lineBits[idx] = (val & 0x01) != 0;
|
||||
idx++;
|
||||
val >>= 1;
|
||||
@ -448,7 +522,7 @@ namespace RuntimeData.Apple {
|
||||
bool hiBitSet = (val & 0x80) != 0;
|
||||
|
||||
for (int bit = 0; bit < 7; bit++) {
|
||||
hiFlags[idx] = hiBitSet;
|
||||
hiFlags[idx] = hiBitSet ^ isHighBitFlipped;
|
||||
lineBits[idx] = (val & 0x01) != 0;
|
||||
idx++;
|
||||
val >>= 1;
|
||||
|
@ -131,15 +131,20 @@ height as parameters. Offsets are handled as they are elsewhere, i.e.
|
||||
always in hexadecimal, with a leading '+'.
|
||||
Some less-common parameters include:</p>
|
||||
<ul>
|
||||
<li><b>Row stride</b> - number of bytes used to hold a row. This
|
||||
is used when a row has padding on the end, e.g. a bitmap that's
|
||||
7 bytes wide might be padded to 8 for easy indexing. If you set
|
||||
this to zero the visualizer will default to no padding
|
||||
(stride == width).</li>
|
||||
<li><b>Column stride</b> - number of bytes used to hold a column.
|
||||
This is uncommon, but could be used if (say) a pair of bitmaps
|
||||
was stored with interleaved bytes. If you set this to zero the
|
||||
visualizer will default to no interleave (stride == 1).</li>
|
||||
visualizer will default to no interleave (col_stride = 1).</li>
|
||||
<li><b>Row stride</b> - number of bytes between the start of each
|
||||
row. This is used when a row has padding on the end, e.g. a
|
||||
bitmap that's 7 bytes wide might be padded to 8 for easy indexing,
|
||||
or when bitmap data is interleaved. If you set this to zero the
|
||||
visualizer will default to no padding
|
||||
(row_stride = width * column_stride).</li>
|
||||
<li><b>Cell stride</b> - for multi-bitmap data like a font or sprite
|
||||
sheet, this determines the number of bytes between the start of
|
||||
one item and the next. If set to zero a "dense" arrangement is
|
||||
assumed (cell_stride = row_stride * item_height).</li>
|
||||
</ul>
|
||||
|
||||
<p>Remember that this is a disassembler, not an image converter. The
|
||||
@ -147,19 +152,23 @@ results do not need to be perfectly accurate to be useful when disassembling
|
||||
code.</p>
|
||||
|
||||
|
||||
<h3>Apple II - Apple/VisHiRes</h3>
|
||||
<h3>Apple II - Apple/VisHiRes and Apple/VisShapeTable</h3>
|
||||
|
||||
<p>There is no standard format for small hi-res bitmaps, but certain
|
||||
arrangements are common. The script defines three generators:</p>
|
||||
arrangements are common. The VisHiRes script defines four generators:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Hi-Res Bitmap</b> - converts an MxN row-major bitmap.</li>
|
||||
<li><b>Hi-Res Bitmap Font</b> - converts a series of MxN row-major
|
||||
bitmaps. This is intended for hi-res fonts, which are typically
|
||||
8 bytes per entry, stored one after another. These are always
|
||||
converted as monochrome, and have a 1-pixel transparent gap
|
||||
between elements. (This also works for Apple /// fonts, but
|
||||
currently ignores the high bit in each byte.)</li>
|
||||
<li><b>Hi-Res Sprite Sheet</b> - converts a series of bitmaps and
|
||||
renders them in a grid. Useful for games that use cell
|
||||
animation. The generated bitmap has a 1-pixel transparent gap
|
||||
between elements.</li>
|
||||
<li><b>Hi-Res Bitmap Font</b> - a simplified version of the
|
||||
Sprite Sheet, intended for the common 7x8 monochrome fonts.
|
||||
Most fonts have 96 or 128 glyphs, though some drop the last
|
||||
character.
|
||||
(This also works for Apple /// fonts, but currently ignores
|
||||
the high bit in each byte.)</li>
|
||||
<li><b>Hi-Res Screen Image</b> - used for 8KiB screen images. The
|
||||
data is linearized and converted to a 280x192 bitmap. Because
|
||||
images are relatively large, the generator does not require them
|
||||
@ -172,12 +181,19 @@ arrangements are common. The script defines three generators:</p>
|
||||
pixels (with some hand-waving).</p>
|
||||
|
||||
<p>In addition to offset, dimensions, and stride values, the bitmap
|
||||
converter has a checkbox for monochrome or color, and a checkbox that
|
||||
will cause the first byte to be treated as an odd column rather than
|
||||
an event one. The odd/even setting affects green/purple and orange/blue,
|
||||
but has no effect on black or white.</p>
|
||||
converter has a checkbox for monochrome or color, and two checkboxes
|
||||
that affect the color. The first causes the first byte to be treated
|
||||
as being in an odd column rather than an even one, which affects
|
||||
green vs. purple and orange vs. blue. The second flips the high bits
|
||||
on every byte, switching green vs. orange and purple vs. blue.
|
||||
Neither has any effect on black & white bitmaps.</p>
|
||||
<p>The converter generates one output pixel for every source pixel, so
|
||||
half-pixel shifts are not rendered.</p>
|
||||
half-pixel shifts are not represented.</p>
|
||||
|
||||
<p>The VisShapeTable script renders Applesoft shape tables, which can
|
||||
have multiple vector shapes. The only parameter other than the offset
|
||||
is the shape number.</p>
|
||||
|
||||
|
||||
<h3>Atari 2600 - Atari/Vis2600</h3>
|
||||
|
||||
|
@ -90,9 +90,9 @@ limitations under the License.
|
||||
</DataGrid>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.Row="1">
|
||||
<Button Width="110" Height="36" Margin="4" Content="_New Bitmap..."
|
||||
<Button Width="110" Height="36" Margin="4" Content="New _Bitmap..."
|
||||
IsEnabled="{Binding HasVisPlugins}" Click="NewBitmapButton_Click"/>
|
||||
<Button Width="110" Margin="4" Content="_New Bitmap
Animation..."
|
||||
<Button Width="110" Margin="4" Content="New Bitmap
_Animation..."
|
||||
Click="NewBitmapAnimationButton_Click"/>
|
||||
|
||||
<Button Width="110" Margin="4,20,4,4" Content="_Edit..."
|
||||
|
Loading…
Reference in New Issue
Block a user