1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-11 17:29:29 +00:00

Expand C64 sprite visualizer

Added fonts and sprite sheets.  Updated documentation.
This commit is contained in:
Andy McFadden 2022-05-01 11:07:56 -07:00
parent 663a3d0230
commit 8b1e70fa58
2 changed files with 308 additions and 88 deletions

View File

@ -13,12 +13,23 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
//#define SHOW_BORDER
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using PluginCommon; using PluginCommon;
namespace RuntimeData.Commodore { namespace RuntimeData.Commodore {
/// <summary>
/// Visualizer for C64 sprites and fonts.
/// </summary>
/// <remarks>
/// References:
/// https://www.c64-wiki.com/wiki/Sprite
/// http://sta.c64.org/cbm64disp.html
/// http://unusedino.de/ec64/technical/misc/vic656x/colors/
/// </remarks>
public class VisC64 : MarshalByRefObject, IPlugin, IPlugin_Visualizer { public class VisC64 : MarshalByRefObject, IPlugin, IPlugin_Visualizer {
// IPlugin // IPlugin
public string Identifier { public string Identifier {
@ -30,9 +41,14 @@ namespace RuntimeData.Commodore {
// Visualization identifiers; DO NOT change or projects that use them will break. // Visualization identifiers; DO NOT change or projects that use them will break.
private const string VIS_GEN_HI_RES_SPRITE = "c64-hi-res-sprite"; private const string VIS_GEN_HI_RES_SPRITE = "c64-hi-res-sprite";
private const string VIS_GEN_HI_RES_SPRITE_GRID = "c64-hi-res-sprite-grid";
private const string VIS_GEN_MULTI_COLOR_SPRITE = "c64-multi-color-sprite"; private const string VIS_GEN_MULTI_COLOR_SPRITE = "c64-multi-color-sprite";
private const string VIS_GEN_MULTI_COLOR_SPRITE_GRID = "c64-multi-color-sprite-grid";
private const string VIS_GEN_HI_RES_FONT = "c64-hi-res-font";
private const string VIS_GEN_MULTI_COLOR_FONT = "c64-multi-color-font";
private const string P_OFFSET = "offset"; private const string P_OFFSET = "offset";
private const string P_COUNT = "count";
private const string P_DOUBLE_WIDE = "doubleWide"; private const string P_DOUBLE_WIDE = "doubleWide";
private const string P_DOUBLE_HIGH = "doubleHigh"; private const string P_DOUBLE_HIGH = "doubleHigh";
private const string P_COLOR = "color"; // sprite color (hi-res or multi-color) private const string P_COLOR = "color"; // sprite color (hi-res or multi-color)
@ -40,9 +56,10 @@ namespace RuntimeData.Commodore {
private const string P_COLOR_11 = "color11"; // multi-color 2 private const string P_COLOR_11 = "color11"; // multi-color 2
private const int MAX_COLOR = 15; private const int MAX_COLOR = 15;
private const int BYTE_WIDTH = 3; private const int SPRITE_BYTE_WIDTH = 3;
private const int HEIGHT = 21; private const int SPRITE_HEIGHT = 21;
private const int SPRITE_SIZE = BYTE_WIDTH * HEIGHT; // 63 private const int SPRITE_SIZE = SPRITE_BYTE_WIDTH * SPRITE_HEIGHT; // 63
private const int SPRITE_STRIDE = 64; // hardware sprites are 64-byte aligned
// Visualization descriptors. // Visualization descriptors.
private VisDescr[] mDescriptors = new VisDescr[] { private VisDescr[] mDescriptors = new VisDescr[] {
@ -72,6 +89,50 @@ namespace RuntimeData.Commodore {
new VisParamDescr("Double high", new VisParamDescr("Double high",
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false), P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
}), }),
new VisDescr(VIS_GEN_HI_RES_SPRITE_GRID, "C64 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("Number of items",
P_COUNT, typeof(int), 1, 1024, 0, 16),
new VisParamDescr("Sprite color",
P_COLOR, typeof(int), 0, 15, 0, 0),
new VisParamDescr("Double wide",
P_DOUBLE_WIDE, typeof(bool), 0, 0, 0, false),
new VisParamDescr("Double high",
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
}),
new VisDescr(VIS_GEN_MULTI_COLOR_SPRITE_GRID, "C64 Multi-Color Sprite Sheet", VisDescr.VisType.Bitmap,
new VisParamDescr[] {
new VisParamDescr("File offset (hex)",
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
new VisParamDescr("Number of items",
P_COUNT, typeof(int), 1, 1024, 0, 16),
new VisParamDescr("Sprite color",
P_COLOR, typeof(int), 0, 15, 0, 1),
new VisParamDescr("Multi-color 1",
P_COLOR_01, typeof(int), 0, 15, 0, 0),
new VisParamDescr("Multi-color 2",
P_COLOR_11, typeof(int), 0, 15, 0, 2),
new VisParamDescr("Double wide",
P_DOUBLE_WIDE, typeof(bool), 0, 0, 0, false),
new VisParamDescr("Double high",
P_DOUBLE_HIGH, typeof(bool), 0, 0, 0, false),
}),
new VisDescr(VIS_GEN_HI_RES_FONT, "C64 Hi-Res Font", VisDescr.VisType.Bitmap,
new VisParamDescr[] {
new VisParamDescr("File offset (hex)",
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
new VisParamDescr("Number of items",
P_COUNT, typeof(int), 1, 256, 0, 96),
}),
new VisDescr(VIS_GEN_MULTI_COLOR_FONT, "C64 Multi-Color Font", VisDescr.VisType.Bitmap,
new VisParamDescr[] {
new VisParamDescr("File offset (hex)",
P_OFFSET, typeof(int), 0, 0x00ffffff, VisParamDescr.SpecialMode.Offset, 0),
new VisParamDescr("Number of items",
P_COUNT, typeof(int), 1, 256, 0, 96),
}),
}; };
@ -104,74 +165,36 @@ namespace RuntimeData.Commodore {
ReadOnlyDictionary<string, object> parms) { ReadOnlyDictionary<string, object> parms) {
switch (descr.Ident) { switch (descr.Ident) {
case VIS_GEN_HI_RES_SPRITE: case VIS_GEN_HI_RES_SPRITE:
return GenerateHiResSprite(parms); return GenerateSprite(parms, false);
case VIS_GEN_MULTI_COLOR_SPRITE: case VIS_GEN_MULTI_COLOR_SPRITE:
return GenerateMultiColorSprite(parms); return GenerateSprite(parms, true);
case VIS_GEN_HI_RES_SPRITE_GRID:
return GenerateSpriteGrid(parms, false);
case VIS_GEN_MULTI_COLOR_SPRITE_GRID:
return GenerateSpriteGrid(parms, true);
case VIS_GEN_HI_RES_FONT:
return GenerateFont(parms, false);
case VIS_GEN_MULTI_COLOR_FONT:
return GenerateFont(parms, true);
default: default:
mAppRef.ReportError("Unknown ident " + descr.Ident); mAppRef.ReportError("Unknown ident " + descr.Ident);
return null; return null;
} }
} }
private IVisualization2d GenerateHiResSprite(ReadOnlyDictionary<string, object> parms) { private IVisualization2d GenerateSprite(ReadOnlyDictionary<string, object> parms,
bool isMultiColor) {
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0); int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0); byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false); bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false); bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
byte color01 = 0;
if (offset < 0 || offset >= mFileData.Length || color < 0 || color > MAX_COLOR) { byte color11 = 0;
// the UI should flag these based on range (and ideally wouldn't have called us) if (isMultiColor) {
mAppRef.ReportError("Invalid parameter"); color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
return null; color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
} }
int lastOffset = offset + SPRITE_SIZE - 1;
if (lastOffset >= mFileData.Length) {
mAppRef.ReportError("Sprite runs off end of file (last offset +" +
lastOffset.ToString("x6") + ")");
return null;
}
int xwide = isDoubleWide ? 2 : 1;
int xhigh = isDoubleHigh ? 2 : 1;
VisBitmap8 vb = new VisBitmap8(BYTE_WIDTH * 8 * xwide, HEIGHT * xhigh);
SetPalette(vb);
// Clear all pixels to transparent, then just draw the non-transparent ones.
vb.SetAllPixelIndices(TRANSPARENT);
for (int row = 0; row < HEIGHT; row++) {
for (int col = 0; col < BYTE_WIDTH; col++) {
byte val = mFileData[offset + row * BYTE_WIDTH + col];
for (int bit = 0; bit < 8; bit++) {
if ((val & 0x80) != 0) {
int xc = (col * 8 + bit) * xwide;
int yc = row * xhigh;
vb.SetPixelIndex(xc, yc, color);
if (isDoubleWide || isDoubleHigh) {
// Draw doubled pixels. If we're only doubled in one dimension
// this will draw pixels twice.
vb.SetPixelIndex(xc + xwide - 1, yc, color);
vb.SetPixelIndex(xc, yc + xhigh - 1, color);
vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, color);
}
}
val <<= 1;
}
}
}
return vb;
}
private IVisualization2d GenerateMultiColorSprite(ReadOnlyDictionary<string, object> parms) {
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
byte color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
byte color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
if (offset < 0 || offset >= mFileData.Length || if (offset < 0 || offset >= mFileData.Length ||
color < 0 || color > MAX_COLOR || color < 0 || color > MAX_COLOR ||
color01 < 0 || color01 > MAX_COLOR || color01 < 0 || color01 > MAX_COLOR ||
@ -180,7 +203,6 @@ namespace RuntimeData.Commodore {
mAppRef.ReportError("Invalid parameter"); mAppRef.ReportError("Invalid parameter");
return null; return null;
} }
int lastOffset = offset + SPRITE_SIZE - 1; int lastOffset = offset + SPRITE_SIZE - 1;
if (lastOffset >= mFileData.Length) { if (lastOffset >= mFileData.Length) {
mAppRef.ReportError("Sprite runs off end of file (last offset +" + mAppRef.ReportError("Sprite runs off end of file (last offset +" +
@ -191,13 +213,196 @@ namespace RuntimeData.Commodore {
int xwide = isDoubleWide ? 2 : 1; int xwide = isDoubleWide ? 2 : 1;
int xhigh = isDoubleHigh ? 2 : 1; int xhigh = isDoubleHigh ? 2 : 1;
VisBitmap8 vb = new VisBitmap8(BYTE_WIDTH * 8 * xwide, HEIGHT * xhigh); VisBitmap8 vb = new VisBitmap8(SPRITE_BYTE_WIDTH * 8 * xwide, SPRITE_HEIGHT * xhigh);
SetPalette(vb); SetPalette(vb);
vb.SetAllPixelIndices(TRANSPARENT); vb.SetAllPixelIndices(TRANSPARENT);
for (int row = 0; row < HEIGHT; row++) { if (isMultiColor) {
for (int col = 0; col < BYTE_WIDTH; col++) { RenderMultiColorBitmap(offset, SPRITE_BYTE_WIDTH, SPRITE_HEIGHT,
byte val = mFileData[offset + row * BYTE_WIDTH + col]; isDoubleWide, isDoubleHigh, color, color01, color11, vb, 0, 0);
} else {
RenderHiResBitmap(offset, SPRITE_BYTE_WIDTH, SPRITE_HEIGHT,
isDoubleWide, isDoubleHigh, color, vb, 0, 0);
}
return vb;
}
private IVisualization2d GenerateSpriteGrid(ReadOnlyDictionary<string, object> parms,
bool isMultiColor) {
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
int count = Util.GetFromObjDict(parms, P_COUNT, 16);
byte color = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);
byte color01 = 0;
byte color11 = 0;
if (isMultiColor) {
color01 = (byte)Util.GetFromObjDict(parms, P_COLOR_01, 0);
color11 = (byte)Util.GetFromObjDict(parms, P_COLOR_11, 0);
}
if (offset < 0 || offset >= mFileData.Length ||
color < 0 || color > MAX_COLOR ||
color01 < 0 || color01 > MAX_COLOR ||
color11 < 0 || color11 > MAX_COLOR) {
// the UI should flag these based on range (and ideally wouldn't have called us)
mAppRef.ReportError("Invalid parameter");
return null;
}
int lastOffset = offset + SPRITE_STRIDE * count - 1;
if (lastOffset >= mFileData.Length) {
mAppRef.ReportError("Sprite set runs off end of file (last offset +" +
lastOffset.ToString("x6") + ")");
return null;
}
int xwide = isDoubleWide ? 2 : 1;
int xhigh = isDoubleHigh ? 2 : 1;
// Try to make it square, unless there's a large number of them. Limit the width
// to 16 sprites (384 pixels + padding).
int hcells;
if (count * xwide > 64) {
hcells = 16 / xwide;
} else if (count * xwide >= 32) {
hcells = 8 / xwide;
} else {
hcells = (int)Math.Sqrt(count * xwide + 1);
}
int vcells = (count + hcells - 1) / hcells;
VisBitmap8 vb = new VisBitmap8(1 + hcells * SPRITE_BYTE_WIDTH * 8 * xwide + hcells,
1 + vcells * SPRITE_HEIGHT * xhigh + vcells);
SetPalette(vb);
vb.SetAllPixelIndices(BORDER_COLOR);
int cellX = 1;
int cellY = 1;
for (int idx = 0; idx < count; idx++) {
if (isMultiColor) {
RenderMultiColorBitmap(offset + idx * SPRITE_STRIDE,
SPRITE_BYTE_WIDTH, SPRITE_HEIGHT, isDoubleWide, isDoubleHigh,
color, color01, color11, vb, cellX, cellY);
} else {
RenderHiResBitmap(offset + idx * SPRITE_STRIDE,
SPRITE_BYTE_WIDTH, SPRITE_HEIGHT, isDoubleWide, isDoubleHigh,
color, vb, cellX, cellY);
}
cellX += SPRITE_BYTE_WIDTH * 8 * xwide + 1;
if (cellX == vb.Width) {
cellX = 1;
cellY += SPRITE_HEIGHT * xhigh + 1;
}
}
return vb;
}
private IVisualization2d GenerateFont(ReadOnlyDictionary<string, object> parms,
bool isMultiColor) {
int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
int count = Util.GetFromObjDict(parms, P_COUNT, 96);
if (offset < 0 || offset >= mFileData.Length) {
mAppRef.ReportError("Invalid parameter");
return null;
}
int lastOffset = offset + count - 1;
if (lastOffset >= mFileData.Length) {
mAppRef.ReportError("Font runs off end of file (last offset +" +
lastOffset.ToString("x6") + ")");
return null;
}
// Set the number of horizontal cells. For small counts we try to make it square,
// for larger counts we use a reasonable power of 2.
int hcells;
if (count > 128) {
hcells = 32;
} else if (count > 64) {
hcells = 16;
} else if (count >= 32) {
hcells = 8;
} else {
hcells = (int)Math.Sqrt(count + 1);
}
int vcells = (count + hcells - 1) / hcells;
const int FONT_BYTE_WIDTH = 1;
const int FONT_HEIGHT = 8;
const int CELL_STRIDE = FONT_BYTE_WIDTH * FONT_HEIGHT;
// Create a bitmap with room for each cell, plus a 1-pixel boundary
// between them and around the edges.
VisBitmap8 vb = new VisBitmap8(1 + hcells * FONT_BYTE_WIDTH * 8 + hcells,
1 + vcells * FONT_HEIGHT + vcells);
SetPalette(vb);
vb.SetAllPixelIndices(BORDER_COLOR);
int cellX = 1;
int cellY = 1;
byte color = 0; /* black */
byte color01 = 11; /* dark grey */
byte color11 = 15; /* light grey */
for (int idx = 0; idx < count; idx++) {
if (isMultiColor) {
RenderMultiColorBitmap(offset + idx * CELL_STRIDE, FONT_BYTE_WIDTH, FONT_HEIGHT,
false, false, color, color01, color11, vb, cellX, cellY);
} else {
RenderHiResBitmap(offset + idx * CELL_STRIDE, FONT_BYTE_WIDTH, FONT_HEIGHT,
false, false, color, vb, cellX, cellY);
}
cellX += FONT_BYTE_WIDTH * 8 + 1;
if (cellX == vb.Width) {
cellX = 1;
cellY += FONT_HEIGHT + 1;
}
}
return vb;
}
private void RenderHiResBitmap(int offset, int byteWidth, int height,
bool isDoubleWide, bool isDoubleHigh,
byte color, VisBitmap8 vb, int startx, int starty) {
int xwide = isDoubleWide ? 2 : 1;
int xhigh = isDoubleHigh ? 2 : 1;
for (int row = 0; row < height; row++) {
for (int col = 0; col < byteWidth; col++) {
byte val = mFileData[offset + row * byteWidth + col];
for (int bit = 0; bit < 8; bit++) {
byte pixColor;
if ((val & 0x80) == 0) {
pixColor = TRANSPARENT;
} else {
pixColor = color;
}
int xc = startx + (col * 8 + bit) * xwide;
int yc = starty + row * xhigh;
vb.SetPixelIndex(xc, yc, pixColor);
if (isDoubleWide || isDoubleHigh) {
// Draw doubled pixels. If we're only doubled in one dimension
// this will draw some pixels twice.
vb.SetPixelIndex(xc + xwide - 1, yc, pixColor);
vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, pixColor);
}
val <<= 1;
}
}
}
}
private void RenderMultiColorBitmap(int offset, int byteWidth, int height,
bool isDoubleWide, bool isDoubleHigh,
byte color, byte color01, byte color11, VisBitmap8 vb, int startx, int starty) {
int xwide = isDoubleWide ? 2 : 1;
int xhigh = isDoubleHigh ? 2 : 1;
for (int row = 0; row < height; row++) {
for (int col = 0; col < byteWidth; col++) {
byte val = mFileData[offset + row * byteWidth + col];
for (int bit = 0; bit < 8; bit += 2) { for (int bit = 0; bit < 8; bit += 2) {
byte pixColor = 0; byte pixColor = 0;
switch (val & 0xc0) { switch (val & 0xc0) {
@ -206,13 +411,14 @@ namespace RuntimeData.Commodore {
case 0x40: pixColor = color01; break; case 0x40: pixColor = color01; break;
case 0xc0: pixColor = color11; break; case 0xc0: pixColor = color11; break;
} }
int xc = (col * 8 + bit) * xwide; int xc = startx + (col * 8 + bit) * xwide;
int yc = row * xhigh; int yc = starty + row * xhigh;
// Set two adjacent pixels.
vb.SetPixelIndex(xc, yc, pixColor); vb.SetPixelIndex(xc, yc, pixColor);
vb.SetPixelIndex(xc+1, yc, pixColor); vb.SetPixelIndex(xc+1, yc, pixColor);
if (isDoubleWide || isDoubleHigh) { if (isDoubleWide || isDoubleHigh) {
// Draw doubled pixels. If we're only doubled in one dimension // Draw doubled pixels. If we're only doubled in one dimension
// this will draw pixels twice. // this will draw some pixels twice.
vb.SetPixelIndex(xc + xwide*2 - 2, yc, pixColor); vb.SetPixelIndex(xc + xwide*2 - 2, yc, pixColor);
vb.SetPixelIndex(xc + xwide*2 - 1, yc, pixColor); vb.SetPixelIndex(xc + xwide*2 - 1, yc, pixColor);
vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor); vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
@ -224,31 +430,36 @@ namespace RuntimeData.Commodore {
} }
} }
} }
return vb;
} }
private const byte TRANSPARENT = 16; private const byte TRANSPARENT = 16;
private const byte BORDER_COLOR = 17;
// C64 colors, from http://unusedino.de/ec64/technical/misc/vic656x/colors/ // C64 colors, from http://unusedino.de/ec64/technical/misc/vic656x/colors/
// (the ones on https://www.c64-wiki.com/wiki/Color looked wrong) // (the ones on https://www.c64-wiki.com/wiki/Color looked wrong)
private void SetPalette(VisBitmap8 vb) { private void SetPalette(VisBitmap8 vb) {
vb.AddColor(0xff, 0x00, 0x00, 0x00); // 0=black vb.SetColor(0, 0xff, 0x00, 0x00, 0x00); // 0=black
vb.AddColor(0xff, 0xff, 0xff, 0xff); // 1=white vb.SetColor(1, 0xff, 0xff, 0xff, 0xff); // 1=white
vb.AddColor(0xff, 0x68, 0x37, 0x2b); // 2=red vb.SetColor(2, 0xff, 0x68, 0x37, 0x2b); // 2=red
vb.AddColor(0xff, 0x70, 0xa4, 0xb2); // 3=cyan vb.SetColor(3, 0xff, 0x70, 0xa4, 0xb2); // 3=cyan
vb.AddColor(0xff, 0x6f, 0x3d, 0x86); // 4=purple vb.SetColor(4, 0xff, 0x6f, 0x3d, 0x86); // 4=purple
vb.AddColor(0xff, 0x58, 0x8d, 0x43); // 5=green vb.SetColor(5, 0xff, 0x58, 0x8d, 0x43); // 5=green
vb.AddColor(0xff, 0x35, 0x28, 0x79); // 6=blue vb.SetColor(6, 0xff, 0x35, 0x28, 0x79); // 6=blue
vb.AddColor(0xff, 0xb8, 0xc7, 0x6f); // 7=yellow vb.SetColor(7, 0xff, 0xb8, 0xc7, 0x6f); // 7=yellow
vb.AddColor(0xff, 0x6f, 0x4f, 0x25); // 8=orange vb.SetColor(8, 0xff, 0x6f, 0x4f, 0x25); // 8=orange
vb.AddColor(0xff, 0x43, 0x39, 0x00); // 9-brown vb.SetColor(9, 0xff, 0x43, 0x39, 0x00); // 9-brown
vb.AddColor(0xff, 0x9a, 0x67, 0x59); // 10=light red vb.SetColor(10, 0xff, 0x9a, 0x67, 0x59); // 10=light red
vb.AddColor(0xff, 0x44, 0x44, 0x44); // 11=dark grey vb.SetColor(11, 0xff, 0x44, 0x44, 0x44); // 11=dark grey
vb.AddColor(0xff, 0x6c, 0x6c, 0x6c); // 12=grey vb.SetColor(12, 0xff, 0x6c, 0x6c, 0x6c); // 12=grey
vb.AddColor(0xff, 0x9a, 0xd2, 0x84); // 13=light green vb.SetColor(13, 0xff, 0x9a, 0xd2, 0x84); // 13=light green
vb.AddColor(0xff, 0x6c, 0x5e, 0xb5); // 14=light blue vb.SetColor(14, 0xff, 0x6c, 0x5e, 0xb5); // 14=light blue
vb.AddColor(0xff, 0x95, 0x95, 0x95); // 15=light grey vb.SetColor(15, 0xff, 0x95, 0x95, 0x95); // 15=light grey
vb.AddColor(0, 0, 0, 0); // 16=transparent vb.SetColor(16, 0, 0, 0, 0); // 16=transparent
#if SHOW_BORDER
vb.SetColor(17, 0xff, 0x00, 0xd6, 0xff); // 17=grid border
#else
vb.SetColor(17, 0, 0, 0, 0); // 17=grid border
#endif
} }
} }
} }

View File

@ -251,16 +251,17 @@ straightforward fashion.</p>
repeated as-is or flipped.</li> repeated as-is or flipped.</li>
</ul> </ul>
<h3>Atari Arcade : Atari/VisAVG</h3> <h3>Atari Arcade : Atari/VisAVG and Atari/VisDVG</h3>
<p>Different versions of Atari's Analog Vector Graphics were used in <p>Different versions of Atari's Analog Vector Graphics and
several games, notably Battlezone, Tempest, and Star Wars. The commands Digital Vector Graphics were used in several games, notably Asteroids,
Battlezone, Tempest, and Star Wars. The commands
drove a vector display monitor. SourceGen visualizes them as 2D drove a vector display monitor. SourceGen visualizes them as 2D
wireframes, which isn't a perfect fit since they can describe points as wireframes, which isn't a perfect fit since they can describe points as
well as lines, but works fine for annotating a disassembly.</p> well as lines, but works fine for annotating a disassembly.</p>
<p>The visualizer takes two arguments: the offset of the start of <p>The visualizer takes two arguments: the offset of the start of
the commands to visualize, and the base address of vector RAM. The latter the commands to visualize, and the base address of vector RAM. The latter
is necessary to convert AVG JMP/JSR commands into offsets.</p> is needed to convert vector JMP/JSR commands into offsets.</p>
<h3>Commodore 64 : Commodore/VisC64</h3> <h3>Commodore 64 : Commodore/VisC64</h3>
@ -297,6 +298,14 @@ It comes in two basic varieties:</p>
a sprite that is doubled in both width and height will look exactly like a sprite that is doubled in both width and height will look exactly like
a sprite that is not doubled at all.</p> a sprite that is not doubled at all.</p>
<p>If multiple sprites are defined consecutively, at 64-byte intervals,
they can be combined into a sprite sheet. A single set of parameters
for color and scaling is applied to all sprites.</p>
<p>The visualizer also handles high-resolution and multi-color fonts,
which are displayed in a grid.</p>
<h3>Nintendo Entertainment System : Nintendo/VisNES</h3> <h3>Nintendo Entertainment System : Nintendo/VisNES</h3>
<p>NES PPU pattern tables hold 8x8 tiles with 2 bits of color per pixel. <p>NES PPU pattern tables hold 8x8 tiles with 2 bits of color per pixel.