mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-29 08:29:52 +00:00
Add an Applesoft to HTML converter
This is not an official thing, so I'm hiding it in the DEBUG menu for now.
This commit is contained in:
parent
eb99a716f1
commit
8505a5cdd4
@ -3813,6 +3813,33 @@ namespace SourceGen {
|
|||||||
ScriptManager.UseKeepAliveHack = !ScriptManager.UseKeepAliveHack;
|
ScriptManager.UseKeepAliveHack = !ScriptManager.UseKeepAliveHack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Debug_ApplesoftToHtml() {
|
||||||
|
OpenFileDialog fileDlg = new OpenFileDialog() {
|
||||||
|
Filter = Res.Strings.FILE_FILTER_ALL,
|
||||||
|
FilterIndex = 1
|
||||||
|
};
|
||||||
|
if (fileDlg.ShowDialog() != true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data;
|
||||||
|
string basPathName = Path.GetFullPath(fileDlg.FileName);
|
||||||
|
try {
|
||||||
|
data = File.ReadAllBytes(basPathName);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// not expecting this to happen
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tools.ApplesoftToHtml conv = new Tools.ApplesoftToHtml();
|
||||||
|
string html = conv.Convert(data);
|
||||||
|
|
||||||
|
Tools.WpfGui.ShowText showTextDlg = new Tools.WpfGui.ShowText(mMainWin, html);
|
||||||
|
showTextDlg.Title = "Applesoft to HTML";
|
||||||
|
showTextDlg.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Debug features
|
#endregion Debug features
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
<Compile Include="Tests\WpfGui\GenTestRunner.xaml.cs">
|
<Compile Include="Tests\WpfGui\GenTestRunner.xaml.cs">
|
||||||
<DependentUpon>GenTestRunner.xaml</DependentUpon>
|
<DependentUpon>GenTestRunner.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Tools\ApplesoftToHtml.cs" />
|
||||||
<Compile Include="Tools\VirtualHexDump.cs" />
|
<Compile Include="Tools\VirtualHexDump.cs" />
|
||||||
<Compile Include="Tools\WpfGui\InstructionChart.xaml.cs">
|
<Compile Include="Tools\WpfGui\InstructionChart.xaml.cs">
|
||||||
<DependentUpon>InstructionChart.xaml</DependentUpon>
|
<DependentUpon>InstructionChart.xaml</DependentUpon>
|
||||||
|
249
SourceGen/Tools/ApplesoftToHtml.cs
Normal file
249
SourceGen/Tools/ApplesoftToHtml.cs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 faddenSoft
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
using CommonUtil;
|
||||||
|
|
||||||
|
namespace SourceGen.Tools {
|
||||||
|
/// <summary>
|
||||||
|
/// Convert Applesoft BASIC to HTML.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is essentially a port of the CiderPress converter
|
||||||
|
/// (https://github.com/fadden/ciderpress/blob/master/reformat/BASIC.cpp).
|
||||||
|
/// </remarks>
|
||||||
|
public class ApplesoftToHtml {
|
||||||
|
/*
|
||||||
|
* Applesoft BASIC file format:
|
||||||
|
*
|
||||||
|
* <16-bit file length> [DOS 3.3 only; not visible here]
|
||||||
|
* <line> ...
|
||||||
|
* <EOF marker ($0000)>
|
||||||
|
*
|
||||||
|
* Each line consists of:
|
||||||
|
* <16-bit address of next line (relative to start)>
|
||||||
|
* <16-bit line number, usually 0-63999>
|
||||||
|
* <tokens | characters> ...
|
||||||
|
* <EOL marker ($00)>
|
||||||
|
*
|
||||||
|
* All values are little-endian. Numbers are stored as characters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static readonly string[] TOKENS = new string[128] {
|
||||||
|
"END", "FOR", "NEXT", "DATA", "INPUT", "DEL", "DIM", "READ",
|
||||||
|
"GR", "TEXT", "PR#", "IN#", "CALL", "PLOT", "HLIN", "VLIN",
|
||||||
|
"HGR2", "HGR", "HCOLOR=", "HPLOT", "DRAW", "XDRAW", "HTAB", "HOME",
|
||||||
|
"ROT=", "SCALE=", "SHLOAD", "TRACE", "NOTRACE", "NORMAL", "INVERSE", "FLASH",
|
||||||
|
"COLOR=", "POP", "VTAB", "HIMEM:", "LOMEM:", "ONERR", "RESUME", "RECALL",
|
||||||
|
"STORE", "SPEED=", "LET", "GOTO", "RUN", "IF", "RESTORE", "&",
|
||||||
|
"GOSUB", "RETURN", "REM", "STOP", "ON", "WAIT", "LOAD", "SAVE",
|
||||||
|
"DEF", "POKE", "PRINT", "CONT", "LIST", "CLEAR", "GET", "NEW",
|
||||||
|
"TAB(", "TO", "FN", "SPC(", "THEN", "AT", "NOT", "STEP",
|
||||||
|
"+", "-", "*", "/", "^", "AND", "OR", ">",
|
||||||
|
"=", "<", "SGN", "INT", "ABS", "USR", "FRE", "SCRN(",
|
||||||
|
"PDL", "POS", "SQR", "RND", "LOG", "EXP", "COS", "SIN",
|
||||||
|
"TAN", "ATN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$",
|
||||||
|
"LEFT$", "RIGHT$", "MID$", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR",
|
||||||
|
"ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR",
|
||||||
|
"ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR"
|
||||||
|
};
|
||||||
|
private const int TOK_REM = 0xb2;
|
||||||
|
|
||||||
|
private Color mDefaultColor = Color.FromArgb(0xff, 0x40, 0x40, 0x40); // Dark Grey
|
||||||
|
private Color mLineNumColor = Color.FromArgb(0xff, 0x40, 0x40, 0x40); // Dark Grey
|
||||||
|
private Color mKeywordColor = Color.FromArgb(0xff, 0x00, 0x00, 0x00); // Black
|
||||||
|
private Color mCommentColor = Color.FromArgb(0xff, 0x00, 0x80, 0x00); // Medium Green
|
||||||
|
private Color mStringColor = Color.FromArgb(0xff, 0x00, 0x00, 0x80); // Medium Blue
|
||||||
|
private Color mColonColor = Color.FromArgb(0xff, 0xff, 0x00, 0x00); // Red
|
||||||
|
|
||||||
|
private Color mCurrentColor;
|
||||||
|
private bool mInSpan;
|
||||||
|
|
||||||
|
public ApplesoftToHtml() {
|
||||||
|
// maybe do something with alternate color maps?
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a buffer with an Applesoft program into colorful HTML.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Applesoft program.</param>
|
||||||
|
/// <returns>String with formatted text.</returns>
|
||||||
|
public string Convert(byte[] data) {
|
||||||
|
Debug.WriteLine("Conversion starting");
|
||||||
|
|
||||||
|
if (data.Length < 2) {
|
||||||
|
return "BAS truncated?";
|
||||||
|
}
|
||||||
|
|
||||||
|
InitColor();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append("<div>\r\n");
|
||||||
|
|
||||||
|
// Set the default color in the <pre> style.
|
||||||
|
sb.Append("<pre style=\"");
|
||||||
|
OutputHtmlColor(mDefaultColor, sb);
|
||||||
|
sb.Append("\">");
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
while (offset < data.Length) {
|
||||||
|
int nextAddr, lineNum;
|
||||||
|
bool inQuote = false;
|
||||||
|
bool inRem = false;
|
||||||
|
|
||||||
|
nextAddr = Read16(data, ref offset);
|
||||||
|
if (nextAddr == 0) {
|
||||||
|
if (data.Length - offset > 1) {
|
||||||
|
Debug.WriteLine("WARNING: BAS ended early, at +" + offset.ToString("x6"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print line number
|
||||||
|
lineNum = Read16(data, ref offset);
|
||||||
|
SetColor(mLineNumColor, sb);
|
||||||
|
sb.Append(' ');
|
||||||
|
sb.Append(lineNum);
|
||||||
|
sb.Append(' ');
|
||||||
|
SetColor(mDefaultColor, sb);
|
||||||
|
|
||||||
|
while (offset < data.Length && data[offset] != 0) {
|
||||||
|
char tokVal = (char)data[offset];
|
||||||
|
if ((tokVal & 0x80) != 0) {
|
||||||
|
// token
|
||||||
|
SetColor(mKeywordColor, sb);
|
||||||
|
sb.Append(' ');
|
||||||
|
sb.Append(TOKENS[tokVal & 0x7f]);
|
||||||
|
sb.Append(' ');
|
||||||
|
SetColor(mDefaultColor, sb);
|
||||||
|
|
||||||
|
if (tokVal == TOK_REM) {
|
||||||
|
// REM -- do rest of line in green
|
||||||
|
SetColor(mCommentColor, sb);
|
||||||
|
inRem = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// non-token character
|
||||||
|
if (tokVal == '"' && !inRem) {
|
||||||
|
if (!inQuote) {
|
||||||
|
SetColor(mStringColor, sb);
|
||||||
|
sb.Append(tokVal);
|
||||||
|
} else {
|
||||||
|
sb.Append(tokVal);
|
||||||
|
SetColor(mDefaultColor, sb);
|
||||||
|
}
|
||||||
|
inQuote = !inQuote;
|
||||||
|
} else if (tokVal == ':' && !inRem && !inQuote) {
|
||||||
|
SetColor(mColonColor, sb);
|
||||||
|
sb.Append(tokVal);
|
||||||
|
SetColor(mDefaultColor, sb);
|
||||||
|
} else if (inRem && tokVal == '\r') {
|
||||||
|
sb.Append("\r\n"); // embedded CR
|
||||||
|
} else if (tokVal < 0x20) {
|
||||||
|
// control character, in string or REM
|
||||||
|
//sb.Append("•");
|
||||||
|
// output with Unicode "control pictures" block
|
||||||
|
sb.Append("&#x");
|
||||||
|
sb.Append((tokVal + 0x2400).ToString("x4"));
|
||||||
|
sb.Append(";");
|
||||||
|
} else {
|
||||||
|
// Output as ASCII value.
|
||||||
|
sb.Append(tokVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetColor(mDefaultColor, sb);
|
||||||
|
inQuote = inRem = false;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
sb.Append("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append("</pre>\r\n");
|
||||||
|
sb.Append("</div>\r\n");
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the color management.
|
||||||
|
/// </summary>
|
||||||
|
private void InitColor() {
|
||||||
|
mCurrentColor = mDefaultColor;
|
||||||
|
mInSpan = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the current text color. Does nothing if the new color is the same as the
|
||||||
|
/// old color. Special-cases the default color.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This approach is sub-optimal -- if we have two tokens in a row they'll be put
|
||||||
|
/// in separate spans. It works well enough for now.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="newColor">Color to change to.</param>
|
||||||
|
/// <param name="sb">StringBuilder that holds output.</param>
|
||||||
|
private void SetColor(Color newColor, StringBuilder sb) {
|
||||||
|
if (newColor == mCurrentColor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mInSpan) {
|
||||||
|
sb.Append("</span>");
|
||||||
|
mInSpan = false;
|
||||||
|
}
|
||||||
|
if (newColor != mDefaultColor) {
|
||||||
|
sb.Append("<span style=\"");
|
||||||
|
OutputHtmlColor(newColor, sb);
|
||||||
|
sb.Append("\">");
|
||||||
|
mInSpan = true;
|
||||||
|
}
|
||||||
|
mCurrentColor = newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Outputs a color in the form "#rrggbb".
|
||||||
|
/// </summary>
|
||||||
|
private void OutputHtmlColor(Color color, StringBuilder sb) {
|
||||||
|
sb.Append("color:#");
|
||||||
|
sb.Append(color.R.ToString("x2"));
|
||||||
|
sb.Append(color.G.ToString("x2"));
|
||||||
|
sb.Append(color.B.ToString("x2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads 16 bits of little-endian data from the buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">Data buffer.</param>
|
||||||
|
/// <param name="offset">Initial offset. Will be increased by two on a successful
|
||||||
|
/// read.</param>
|
||||||
|
/// <returns>A value between 0 and 65535, or -1 if we ran off the end.</returns>
|
||||||
|
private static int Read16(byte[] data, ref int offset) {
|
||||||
|
if (offset + 2 > data.Length) {
|
||||||
|
Debug.WriteLine("ERROR: overran Applesoft");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
offset += 2;
|
||||||
|
return data[offset-2] | (data[offset - 1] << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -174,6 +174,7 @@ limitations under the License.
|
|||||||
</RoutedUICommand.InputGestures>
|
</RoutedUICommand.InputGestures>
|
||||||
</RoutedUICommand>
|
</RoutedUICommand>
|
||||||
|
|
||||||
|
<RoutedUICommand x:Key="Debug_ApplesoftToHtmlCmd" Text="Applesoft to HTML..."/>
|
||||||
<RoutedUICommand x:Key="Debug_ExtensionScriptInfoCmd" Text="Extension Script Info..."/>
|
<RoutedUICommand x:Key="Debug_ExtensionScriptInfoCmd" Text="Extension Script Info..."/>
|
||||||
<RoutedUICommand x:Key="Debug_ShowAnalysisTimersCmd" Text="Show Analysis Timers"/>
|
<RoutedUICommand x:Key="Debug_ShowAnalysisTimersCmd" Text="Show Analysis Timers"/>
|
||||||
<RoutedUICommand x:Key="Debug_ShowAnalyzerOutputCmd" Text="Show Analyzer Output"/>
|
<RoutedUICommand x:Key="Debug_ShowAnalyzerOutputCmd" Text="Show Analyzer Output"/>
|
||||||
@ -290,6 +291,8 @@ limitations under the License.
|
|||||||
|
|
||||||
<CommandBinding Command="Refresh"
|
<CommandBinding Command="Refresh"
|
||||||
CanExecute="IsProjectOpen" Executed="Debug_RefreshCmd_Executed"/>
|
CanExecute="IsProjectOpen" Executed="Debug_RefreshCmd_Executed"/>
|
||||||
|
<CommandBinding Command="{StaticResource Debug_ApplesoftToHtmlCmd}"
|
||||||
|
Executed="Debug_ApplesoftToHtmlCmd_Executed"/>
|
||||||
<CommandBinding Command="{StaticResource Debug_ExtensionScriptInfoCmd}"
|
<CommandBinding Command="{StaticResource Debug_ExtensionScriptInfoCmd}"
|
||||||
CanExecute="IsProjectOpen" Executed="Debug_ExtensionScriptInfoCmd_Executed"/>
|
CanExecute="IsProjectOpen" Executed="Debug_ExtensionScriptInfoCmd_Executed"/>
|
||||||
<CommandBinding Command="{StaticResource Debug_ShowAnalysisTimersCmd}"
|
<CommandBinding Command="{StaticResource Debug_ShowAnalysisTimersCmd}"
|
||||||
@ -385,12 +388,14 @@ limitations under the License.
|
|||||||
<MenuItem Header="_DEBUG" Name="DebugMenu" SubmenuOpened="DebugMenu_SubmenuOpened"
|
<MenuItem Header="_DEBUG" Name="DebugMenu" SubmenuOpened="DebugMenu_SubmenuOpened"
|
||||||
Visibility="{Binding ShowDebugMenu, Converter={StaticResource BoolToVis}}">
|
Visibility="{Binding ShowDebugMenu, Converter={StaticResource BoolToVis}}">
|
||||||
<MenuItem Command="Refresh" Header="Re-analyze"/>
|
<MenuItem Command="Refresh" Header="Re-analyze"/>
|
||||||
<MenuItem Name ="debugUndoRedoHistoryMenuItem"
|
<MenuItem Command="{StaticResource Debug_SourceGenerationTestsCmd}"/>
|
||||||
Command="{StaticResource Debug_ShowUndoRedoHistoryCmd}" IsCheckable="True"/>
|
<Separator/>
|
||||||
<MenuItem Name="debugAnalyzerOutputMenuItem"
|
<MenuItem Name="debugAnalyzerOutputMenuItem"
|
||||||
Command="{StaticResource Debug_ShowAnalyzerOutputCmd}" IsCheckable="True"/>
|
Command="{StaticResource Debug_ShowAnalyzerOutputCmd}" IsCheckable="True"/>
|
||||||
<MenuItem Name="debugAnalysisTimersMenuItem"
|
<MenuItem Name="debugAnalysisTimersMenuItem"
|
||||||
Command="{StaticResource Debug_ShowAnalysisTimersCmd}" IsCheckable="True"/>
|
Command="{StaticResource Debug_ShowAnalysisTimersCmd}" IsCheckable="True"/>
|
||||||
|
<MenuItem Name ="debugUndoRedoHistoryMenuItem"
|
||||||
|
Command="{StaticResource Debug_ShowUndoRedoHistoryCmd}" IsCheckable="True"/>
|
||||||
<MenuItem Command="{StaticResource Debug_ExtensionScriptInfoCmd}"/>
|
<MenuItem Command="{StaticResource Debug_ExtensionScriptInfoCmd}"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Name="debugCommentRulersMenuItem"
|
<MenuItem Name="debugCommentRulersMenuItem"
|
||||||
@ -398,7 +403,7 @@ limitations under the License.
|
|||||||
<MenuItem Name="debugKeepAliveHackMenuItem"
|
<MenuItem Name="debugKeepAliveHackMenuItem"
|
||||||
Command="{StaticResource Debug_ToggleKeepAliveHackCmd}" IsCheckable="True"/>
|
Command="{StaticResource Debug_ToggleKeepAliveHackCmd}" IsCheckable="True"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Command="{StaticResource Debug_SourceGenerationTestsCmd}"/>
|
<MenuItem Command="{StaticResource Debug_ApplesoftToHtmlCmd}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
|
@ -1277,7 +1277,12 @@ namespace SourceGen.WpfGui {
|
|||||||
mMainCtrl.UndoChanges();
|
mMainCtrl.UndoChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Debug_ExtensionScriptInfoCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
private void Debug_ApplesoftToHtmlCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
|
||||||
|
mMainCtrl.Debug_ApplesoftToHtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Debug_ExtensionScriptInfoCmd_Executed(object sender,
|
||||||
|
ExecutedRoutedEventArgs e) {
|
||||||
mMainCtrl.Debug_ExtensionScriptInfo();
|
mMainCtrl.Debug_ExtensionScriptInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user