1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-26 06:49:19 +00:00
6502bench/SourceGen/SGTestData/2022-extension-scripts-a.cs
Andy McFadden 365864ccdf More progress on visualization
Implemented Apple II hi-res bitmap conversion.  Supports B&W and
color.  Uses essentially the same algorithm as CiderPress.

Experimented with displaying non-text items in ListView.  I assumed
it would work, since it's the sort of thing WPF is designed to do,
but it's always wise to approach with caution.  Visualization Sets
now show a 64x64 button as a placeholder for the eventual thumbnail.

Some things were being flaky, which turned out to be because I
wasn't Prepare()ing the plugins before using them from Edit
Visualization.  To make this a deterministic failure I added an
Unprepare() call that tells the plugin that we're all done.

NOTE: this breaks all existing plugins.
2019-11-30 18:02:03 -08:00

164 lines
6.7 KiB
C#

// Copyright 2019 faddenSoft. All Rights Reserved.
// See the LICENSE.txt file for distribution terms (Apache 2.0).
using System;
using System.Collections.Generic;
using PluginCommon;
namespace RuntimeData.Test2022 {
public class Test2022A : MarshalByRefObject, IPlugin, IPlugin_SymbolList,
IPlugin_InlineJsr, IPlugin_InlineJsl {
private IApplication mAppRef;
private byte[] mFileData;
private int mInline8StringAddr; // jsr
private int mInlineRev8StringAddr; // jsr
private int mInlineNullStringAddr; // jsr
private int mInlineL1StringAddr; // jsl
private int mInlineL2StringAddr; // jsl
private int mInlineDciStringAddr; // jsl
public string Identifier {
get {
return "Test 2022-extension-scripts A";
}
}
public void Prepare(IApplication appRef, byte[] fileData, AddressTranslate addrTrans) {
mAppRef = appRef;
mFileData = fileData;
mAppRef.DebugLog("Test2022-A(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
}
public void Unprepare() {
mAppRef = null;
mFileData = null;
}
public void UpdateSymbolList(List<PlSymbol> plSyms) {
foreach (PlSymbol sym in plSyms) {
switch (sym.Label) {
case "PrintInline8String":
mInline8StringAddr = sym.Value;
break;
case "PrintInlineRev8String":
mInlineRev8StringAddr = sym.Value;
break;
case "PrintInlineNullString":
mInlineNullStringAddr = sym.Value;
break;
case "PrintInlineL1String":
mInlineL1StringAddr = sym.Value;
break;
case "PrintInlineL2String":
mInlineL2StringAddr = sym.Value;
break;
case "PrintInlineDciString":
mInlineDciStringAddr = sym.Value;
break;
}
}
}
public bool IsLabelSignificant(string beforeLabel, string afterLabel) {
const string PREFIX = "PrintInline"; // all interesting labels start with this
return (beforeLabel.StartsWith(PREFIX) || afterLabel.StartsWith(PREFIX));
}
public void CheckJsr(int offset, int operand, out bool noContinue) {
noContinue = false;
if (operand == mInline8StringAddr) {
if (offset + 3 + 8 > mFileData.Length) {
mAppRef.DebugLog("8string ran off end at +" +
(offset + 3).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 3, 8,
DataType.StringGeneric, DataSubType.Ascii, null);
} else if (operand == mInlineRev8StringAddr) {
if (offset + 3 + 8 > mFileData.Length) {
mAppRef.DebugLog("rev8string ran off end at +" +
(offset + 3).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 3, 8,
DataType.StringReverse, DataSubType.Ascii, null);
} else if (operand == mInlineNullStringAddr) {
// look for the terminating null byte
int nullOff = offset + 3;
while (nullOff < mFileData.Length) {
if (mFileData[nullOff] == 0) {
break;
}
nullOff++;
}
if (nullOff == mFileData.Length) {
mAppRef.DebugLog("Unable to find end of null-terminated string at +" +
(offset+3).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 3, nullOff - (offset + 3) + 1,
DataType.StringNullTerm, DataSubType.Ascii, null);
}
}
public void CheckJsl(int offset, int operand, out bool noContinue) {
noContinue = false;
if (operand == mInlineL1StringAddr) {
// 0 1 2 3 4 5
// 22 00 10 01 01 66
if (offset + 4 >= mFileData.Length) {
return; // length byte is off end
}
int len = mFileData[offset + 4]; // 1-byte len in first byte past 4-byte JSL
if (offset + 5 + len > mFileData.Length) {
// ran off the end
mAppRef.DebugLog("L1 string ran off end of file at +" +
(offset + 4).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 4, len + 1,
DataType.StringL8, DataSubType.Ascii, null);
} else if (operand == mInlineL2StringAddr) {
if (offset + 5 >= mFileData.Length) {
return; // length word is off end
}
int len = Util.GetWord(mFileData, offset + 4, 2, false);
if (offset + 6 + len > mFileData.Length) {
// ran off the end
mAppRef.DebugLog("L2 string ran off end of file at +" +
(offset+4).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 4, len + 2,
DataType.StringL16, DataSubType.Ascii, null);
} else if (operand == mInlineDciStringAddr) {
// look for the first byte whose high bit doesn't match the first byte's bit
// 0 1 2 3 4 5
// 22 00 30 01 66 c1
if (offset + 3 + 2 >= mFileData.Length) {
// need at least two bytes
return;
}
byte firstBit = (byte) (mFileData[offset + 4] & 0x80);
int endOff = offset + 5;
while (endOff < mFileData.Length) {
if ((mFileData[endOff] & 0x80) != firstBit) {
break;
}
endOff++;
}
if (endOff == mFileData.Length) {
mAppRef.DebugLog("Unable to find end of DCI string at +" +
(offset+4).ToString("x6"));
return;
}
mAppRef.SetInlineDataFormat(offset + 4, endOff - (offset + 4) + 1,
DataType.StringDci, DataSubType.Ascii, null);
}
}
}
}