mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-27 10:32:31 +00:00
Optionally treat BRKs as two-byte instructions
Early data sheets listed BRK as one byte, but RTI after a BRK skips the following byte, effectively making BRK a 2-byte instruction. Sometimes, such as when diassembling Apple /// SOS code, it's handy to treat it that way explicitly. This change makes two-byte BRKs optional, controlled by a checkbox in the project settings. In the system definitions it defaults to true for Apple ///, false for all others. ACME doesn't allow BRK to have an arg, and cc65 only allows it for 65816 code (?), so it's emitted as a hex blob for those assemblers. Anyone wishing to target those assemblers should stick to 1-byte mode. Extension scripts have to switch between formatting one byte of inline data and formatting an instruction with a one-byte operand. A helper function has been added to the plugin Util class. To get some regression test coverage, 2022-extension-scripts has been configured to use two-byte BRK. Also, added/corrected some SOS constants. See also issue #44.
This commit is contained in:
parent
b8e11215fa
commit
dfd5bcab1b
@ -146,7 +146,8 @@ namespace Asm65 {
|
||||
/// <param name="includeUndocumented">Set to true if "undocumented" opcodes should
|
||||
/// be included in the definition.</param>
|
||||
/// <returns>Best CpuDef.</returns>
|
||||
public static CpuDef GetBestMatch(CpuType type, bool includeUndocumented) {
|
||||
public static CpuDef GetBestMatch(CpuType type, bool includeUndocumented,
|
||||
bool twoByteBrk) {
|
||||
// Many 65xx variants boil down to a 6502, 65C02, or 65816, at least as far as
|
||||
// a disassembler needs to know. These do not, and would need full definitions:
|
||||
//
|
||||
@ -190,6 +191,16 @@ namespace Asm65 {
|
||||
cpuDef = stripped;
|
||||
}
|
||||
|
||||
// If we want two-byte BRKs, replace the entry with the StackInt form. Copy the rest.
|
||||
if (twoByteBrk) {
|
||||
CpuDef bigBrkDef = new CpuDef(cpuDef);
|
||||
bigBrkDef.mOpDefs[0] = OpDef.OpBRK_StackInt;
|
||||
for (int i = 1; i < 256; i++) {
|
||||
bigBrkDef.mOpDefs[i] = cpuDef.mOpDefs[i];
|
||||
}
|
||||
cpuDef = bigBrkDef;
|
||||
}
|
||||
|
||||
cpuDef.HasUndocumented = includeUndocumented;
|
||||
|
||||
return cpuDef;
|
||||
|
@ -733,7 +733,7 @@ namespace Asm65 {
|
||||
case AddressMode.DP:
|
||||
case AddressMode.PCRel:
|
||||
case AddressMode.PCRelLong: // BRL
|
||||
case AddressMode.StackInt: // COP
|
||||
case AddressMode.StackInt: // COP and two-byte BRK
|
||||
case AddressMode.StackPCRelLong: // PER
|
||||
case AddressMode.WDM:
|
||||
fmt = wdisStr + "{0}";
|
||||
|
@ -1478,15 +1478,16 @@ namespace Asm65 {
|
||||
AddrMode = AddressMode.Unknown
|
||||
};
|
||||
|
||||
public static readonly OpDef OpBRK_Implied = new OpDef(OpBRK) {
|
||||
public static readonly OpDef OpBRK_Implied = new OpDef(OpBRK) { // 1-byte form
|
||||
Opcode = 0x00,
|
||||
// There should arguably be OpBRK_Implied for 6502/65C02 and OpBRK_StackInt for
|
||||
// 65816, but in practice hardly any assemblers prefer (or even allow) it to be
|
||||
// a two-byte instruction. The BRK does *act* like a two-byte instruction, but
|
||||
// code rarely reflects this usage.
|
||||
AddrMode = AddressMode.Implied,
|
||||
CycDef = 7 | (int)(CycleMod.OneIfE0)
|
||||
};
|
||||
public static readonly OpDef OpBRK_StackInt = new OpDef(OpBRK) { // 2-byte form
|
||||
Opcode = 0x00,
|
||||
AddrMode = AddressMode.StackInt,
|
||||
CycDef = 7 | (int)(CycleMod.OneIfE0)
|
||||
};
|
||||
public static readonly OpDef OpORA_DPIndexXInd = new OpDef(OpORA) {
|
||||
Opcode = 0x01,
|
||||
AddrMode = AddressMode.DPIndexXInd,
|
||||
|
@ -83,8 +83,9 @@ namespace PluginCommon {
|
||||
/// The file data is only guaranteed to hold the BRK opcode byte.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of the BRK instruction.</param>
|
||||
/// <param name="isTwoBytes">True if the CPU is configured for two-byte BRKs.</param>
|
||||
/// <param name="noContinue">Set to true if the BRK doesn't actually return.</param>
|
||||
void CheckBrk(int offset, out bool noContinue);
|
||||
void CheckBrk(int offset, bool isTwoBytes, out bool noContinue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -123,7 +123,8 @@ namespace PluginCommon {
|
||||
dict.Add(ps.Value, ps);
|
||||
} catch (ArgumentException) {
|
||||
appRef.DebugLog("WARNING: GenerateValueList: multiple entries with " +
|
||||
"value " + ps.Value.ToString("x4"));
|
||||
"value " + ps.Value.ToString("x4") + ": " + dict[ps.Value].Label +
|
||||
" and " + ps.Label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,5 +58,31 @@ namespace PluginCommon {
|
||||
public static uint ComputeBufferCRC(byte[] data) {
|
||||
return CRC32.OnBuffer(0, data, 0, data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats the byte that follows a BRK instruction. How we do this depends on
|
||||
/// whether the system is configured for two-byte BRKs.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We can actually apply the format both ways and let the app ignore the one it
|
||||
/// doesn't like, but this is cleaner.
|
||||
/// </remarks>
|
||||
/// <param name="appRef">Reference to application object.</param>
|
||||
/// <param name="twoByteBrk">True if BRKs are handled as two-byte instructions.</param>
|
||||
/// <param name="brkOffset">Offset of BRK instruction.</param>
|
||||
/// <param name="type">Data type to apply.</param>
|
||||
/// <param name="subType">Data sub-type to apply.</param>
|
||||
/// <param name="label">Label, for subType=Symbol.</param>
|
||||
public static void FormatBrkByte(IApplication appRef, bool twoByteBrk, int brkOffset,
|
||||
DataSubType subType, string label) {
|
||||
if (twoByteBrk) {
|
||||
// Two-byte BRK, so we want to apply the format to the instruction itself.
|
||||
appRef.SetOperandFormat(brkOffset, subType, label);
|
||||
} else {
|
||||
// Single-byte BRK, so we want to format the byte that follows the
|
||||
// instruction as inline data.
|
||||
appRef.SetInlineDataFormat(brkOffset + 1, 1, DataType.NumericLE, subType, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,8 +314,8 @@ namespace SourceGen.AsmGen {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (op == OpDef.OpWDM_WDM) {
|
||||
// ACME doesn't like this to have an operand. Output as hex.
|
||||
if (op == OpDef.OpWDM_WDM || op == OpDef.OpBRK_StackInt) {
|
||||
// ACME doesn't like these to have an operand. Output as hex.
|
||||
return null;
|
||||
}
|
||||
return string.Empty; // indicate original is fine
|
||||
|
@ -325,8 +325,9 @@ namespace SourceGen.AsmGen {
|
||||
|
||||
// IGenerator
|
||||
public string ModifyOpcode(int offset, OpDef op) {
|
||||
if ((op == OpDef.OpWDM_WDM) && mAsmVersion < V2_18) {
|
||||
if (op == OpDef.OpBRK_StackInt || (op == OpDef.OpWDM_WDM && mAsmVersion < V2_18)) {
|
||||
// cc65 v2.17 doesn't support WDM, and assembles BRK <arg> to opcode $05.
|
||||
// cc65 v2.18 only supports two-byte BRK on 65816 code.
|
||||
// https://github.com/cc65/cc65/issues/715
|
||||
// https://github.com/cc65/cc65/issues/716
|
||||
return null;
|
||||
|
@ -672,7 +672,7 @@ namespace SourceGen {
|
||||
|
||||
// On first visit, check for BRK inline call.
|
||||
if (firstVisit) {
|
||||
if (op == OpDef.OpBRK_Implied) {
|
||||
if (op == OpDef.OpBRK_Implied || op == OpDef.OpBRK_StackInt) {
|
||||
bool noContinue = CheckForInlineCall(op, offset, !doContinue);
|
||||
if (!noContinue) {
|
||||
// We're expected to continue execution past the BRK.
|
||||
@ -951,8 +951,10 @@ namespace SourceGen {
|
||||
} else if (op == OpDef.OpJSR_AbsLong && (mPluginCaps[i] & PluginCap.JSL) != 0) {
|
||||
((IPlugin_InlineJsl)script).CheckJsl(offset, out bool noCont);
|
||||
noContinue |= noCont;
|
||||
} else if (op == OpDef.OpBRK_Implied && (mPluginCaps[i] & PluginCap.BRK) != 0) {
|
||||
((IPlugin_InlineBrk)script).CheckBrk(offset, out bool noCont);
|
||||
} else if ((op == OpDef.OpBRK_Implied || op == OpDef.OpBRK_StackInt) &&
|
||||
(mPluginCaps[i] & PluginCap.BRK) != 0) {
|
||||
((IPlugin_InlineBrk)script).CheckBrk(offset, op == OpDef.OpBRK_StackInt,
|
||||
out bool noCont);
|
||||
noContinue &= noCont;
|
||||
}
|
||||
} catch (PluginException plex) {
|
||||
|
@ -239,6 +239,7 @@ namespace SourceGen {
|
||||
// system definition.
|
||||
ProjectProps.CpuType = CpuDef.CpuType.Cpu65816;
|
||||
ProjectProps.IncludeUndocumentedInstr = false;
|
||||
ProjectProps.TwoByteBrk = false;
|
||||
UpdateCpuDef();
|
||||
}
|
||||
|
||||
@ -281,7 +282,8 @@ namespace SourceGen {
|
||||
public void ApplySystemDef(SystemDef sysDef) {
|
||||
CpuDef.CpuType cpuType = CpuDef.GetCpuTypeFromName(sysDef.Cpu);
|
||||
bool includeUndoc = SystemDefaults.GetUndocumentedOpcodes(sysDef);
|
||||
CpuDef tmpDef = CpuDef.GetBestMatch(cpuType, includeUndoc);
|
||||
bool twoByteBrk = SystemDefaults.GetTwoByteBrk(sysDef);
|
||||
CpuDef tmpDef = CpuDef.GetBestMatch(cpuType, includeUndoc, twoByteBrk);
|
||||
|
||||
// Store the best-matched CPU in properties, rather than whichever was originally
|
||||
// requested. This way the behavior of the project is the same for everyone, even
|
||||
@ -289,6 +291,7 @@ namespace SourceGen {
|
||||
// originally-specified CPU.
|
||||
ProjectProps.CpuType = tmpDef.Type;
|
||||
ProjectProps.IncludeUndocumentedInstr = includeUndoc;
|
||||
ProjectProps.TwoByteBrk = twoByteBrk;
|
||||
UpdateCpuDef();
|
||||
|
||||
ProjectProps.AnalysisParams.DefaultTextScanMode =
|
||||
@ -325,7 +328,7 @@ namespace SourceGen {
|
||||
|
||||
public void UpdateCpuDef() {
|
||||
CpuDef = CpuDef.GetBestMatch(ProjectProps.CpuType,
|
||||
ProjectProps.IncludeUndocumentedInstr);
|
||||
ProjectProps.IncludeUndocumentedInstr, ProjectProps.TwoByteBrk);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -188,6 +188,7 @@ namespace SourceGen {
|
||||
public class SerProjectProperties {
|
||||
public string CpuName { get; set; }
|
||||
public bool IncludeUndocumentedInstr { get; set; }
|
||||
public bool TwoByteBrk { get; set; }
|
||||
public int EntryFlags { get; set; }
|
||||
public string AutoLabelStyle { get; set; }
|
||||
public SerAnalysisParameters AnalysisParams { get; set; }
|
||||
@ -199,6 +200,7 @@ namespace SourceGen {
|
||||
public SerProjectProperties(ProjectProperties props) {
|
||||
CpuName = Asm65.CpuDef.GetCpuNameFromType(props.CpuType);
|
||||
IncludeUndocumentedInstr = props.IncludeUndocumentedInstr;
|
||||
TwoByteBrk = props.TwoByteBrk;
|
||||
EntryFlags = props.EntryFlags.AsInt;
|
||||
AutoLabelStyle = props.AutoLabelStyle.ToString();
|
||||
AnalysisParams = new SerAnalysisParameters(props.AnalysisParams);
|
||||
@ -495,6 +497,7 @@ namespace SourceGen {
|
||||
// Deserialize ProjectProperties: misc items.
|
||||
proj.ProjectProps.CpuType = Asm65.CpuDef.GetCpuTypeFromName(spf.ProjectProps.CpuName);
|
||||
proj.ProjectProps.IncludeUndocumentedInstr = spf.ProjectProps.IncludeUndocumentedInstr;
|
||||
proj.ProjectProps.TwoByteBrk = spf.ProjectProps.TwoByteBrk;
|
||||
proj.ProjectProps.EntryFlags = Asm65.StatusFlags.FromInt(spf.ProjectProps.EntryFlags);
|
||||
if (Enum.TryParse<AutoLabel.Style>(spf.ProjectProps.AutoLabelStyle,
|
||||
out AutoLabel.Style als)) {
|
||||
|
@ -80,6 +80,11 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
public bool IncludeUndocumentedInstr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we treat BRK instructions as 2 bytes?
|
||||
/// </summary>
|
||||
public bool TwoByteBrk { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initial status flags at entry points.
|
||||
/// </summary>
|
||||
@ -129,6 +134,7 @@ namespace SourceGen {
|
||||
public ProjectProperties(ProjectProperties src) : this() {
|
||||
CpuType = src.CpuType;
|
||||
IncludeUndocumentedInstr = src.IncludeUndocumentedInstr;
|
||||
TwoByteBrk = src.TwoByteBrk;
|
||||
EntryFlags = src.EntryFlags;
|
||||
AutoLabelStyle = src.AutoLabelStyle;
|
||||
|
||||
|
@ -54,7 +54,7 @@ namespace RuntimeData.Apple {
|
||||
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, SOS_MLI_TAG, appRef);
|
||||
}
|
||||
|
||||
public void CheckBrk(int offset, out bool noContinue) {
|
||||
public void CheckBrk(int offset, bool twoByteBrk, out bool noContinue) {
|
||||
noContinue = true;
|
||||
if (offset + 4 >= mFileData.Length) {
|
||||
// ran off the end
|
||||
@ -75,8 +75,7 @@ namespace RuntimeData.Apple {
|
||||
if (!mFunctionList.TryGetValue(req, out sym)) {
|
||||
return;
|
||||
}
|
||||
mAppRef.SetInlineDataFormat(offset + 1, 1, DataType.NumericLE,
|
||||
DataSubType.Symbol, sym.Label);
|
||||
Util.FormatBrkByte(mAppRef, twoByteBrk, offset, DataSubType.Symbol, sym.Label);
|
||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||
DataSubType.Address, null);
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Source: SOS programmer's guide
|
||||
; SOS Reference Manual, Volume 2 (Apple 1982)
|
||||
|
||||
*SYNOPSIS SOS constants.
|
||||
*SYNOPSIS Apple /// Sophisticated Operating System constants.
|
||||
|
||||
; SOS MLI function codes.
|
||||
*TAG SOS-MLI-Functions
|
||||
@ -15,11 +16,17 @@ SOS_GET_SEG_INFO = $43
|
||||
SOS_GET_SEG_NUM = $44
|
||||
SOS_RELEASE_SEG = $45
|
||||
|
||||
SOS_SET_FENCE = $60
|
||||
SOS_GET_FENCE = $61
|
||||
SOS_SET_TIME = $62
|
||||
SOS_GET_TIME = $63
|
||||
SOS_GET_ANALOG = $64
|
||||
; SOS ref: "TERMINATE"
|
||||
; SOS ref: "No errors are possible. This is an excellent call for beginners."
|
||||
SOS_QUIT = $65
|
||||
|
||||
SOS_READBLOCK = $80
|
||||
SOS_WRITEBLOCK = $81
|
||||
SOS_GET_TIME = $82
|
||||
SOS_D_STATUS = $82
|
||||
SOS_D_CONTROL = $83
|
||||
SOS_GET_DEV_NUM = $84
|
||||
@ -35,7 +42,9 @@ SOS_SET_PREFIX = $C6
|
||||
SOS_GET_PREFIX = $C7
|
||||
SOS_OPEN = $C8
|
||||
SOS_NEWLINE = $C9
|
||||
; SOS ref: "READ"
|
||||
SOS_READFILE = $CA
|
||||
; SOS ref: "WRITE"
|
||||
SOS_WRITEFILE = $CB
|
||||
SOS_CLOSE = $CC
|
||||
SOS_FLUSH = $CD
|
||||
|
@ -196,7 +196,7 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||
outside bank zero cannot be assembled. SourceGen currently deals with
|
||||
this by outputting the entire file as a hex dump.</li>
|
||||
<li>Undocumented opcode $AB (<code>LAX #imm</code>) generates an error.</li>
|
||||
<li>WDM is not allowed to have an operand.</li>
|
||||
<li>BRK and WDM are not allowed to have operands.</li>
|
||||
</ul>
|
||||
|
||||
<p>Quirks:</p>
|
||||
@ -231,6 +231,7 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||
<p>Bugs:</p>
|
||||
<ul>
|
||||
<li>PC relative branches don't wrap around at bank boundaries.</li>
|
||||
<li>BRK can only be given an argument in 65816 mode.</li>
|
||||
<li>[Fixed in v2.18] The arguments to <code>MVN</code>/<code>MVP</code> are reversed.</li>
|
||||
<li>[Fixed in v2.18] <code>BRK <arg></code> is assembled to opcode
|
||||
$05 rather than $00.</li>
|
||||
|
@ -93,7 +93,8 @@
|
||||
"RT:Apple/SOS.cs"
|
||||
],
|
||||
"Parameters" : {
|
||||
"load-address":"0x2000"
|
||||
"load-address":"0x2000",
|
||||
"two-byte-brk":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ namespace RuntimeData.Test2022 {
|
||||
mAppRef.DebugLog("Test2022-B(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
||||
}
|
||||
|
||||
public void CheckBrk(int offset, out bool noContinue) {
|
||||
public void CheckBrk(int offset, bool twoByteBrk, out bool noContinue) {
|
||||
noContinue = true;
|
||||
|
||||
// need BRK, function byte, and two-byte address
|
||||
@ -39,8 +39,7 @@ namespace RuntimeData.Test2022 {
|
||||
return;
|
||||
}
|
||||
|
||||
mAppRef.SetInlineDataFormat(offset + 1, 1, DataType.NumericLE,
|
||||
DataSubType.Hex, null);
|
||||
Util.FormatBrkByte(mAppRef, twoByteBrk, offset, DataSubType.Hex, null);
|
||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||
DataSubType.Address, null);
|
||||
noContinue = false;
|
||||
|
@ -1,7 +1,7 @@
|
||||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":2,"FileDataLength":203,"FileDataCrc32":-1621468157,"ProjectProps":{
|
||||
"CpuName":"65816","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
|
||||
"CpuName":"65816","IncludeUndocumentedInstr":false,"TwoByteBrk":true,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
|
||||
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true},
|
||||
"PlatformSymbolFileIdentifiers":["PROJ:2022-extension-scripts.sym65"],"ExtensionScriptFileIdentifiers":["PROJ:2022-extension-scripts-a.cs","PROJ:2022-extension-scripts-b.cs"],"ProjectSyms":{
|
||||
"PrintInlineDciString":{
|
||||
|
@ -28,11 +28,9 @@ PrintInlineDciString = $013000
|
||||
jsr L10AB
|
||||
jsr L110F
|
||||
jsr L1108
|
||||
brk
|
||||
.byte $01
|
||||
brk #$01
|
||||
.word data01
|
||||
brk
|
||||
.byte $02
|
||||
brk #$02
|
||||
.word data02
|
||||
rts
|
||||
|
||||
@ -80,9 +78,7 @@ L10AB jsr PrintInlineNullString
|
||||
|
||||
L1108 jsl PrintInlineL2String
|
||||
asl a
|
||||
brk
|
||||
|
||||
.byte $60
|
||||
brk #$60
|
||||
|
||||
L110F jsr PrintInlineNullString
|
||||
adc $6e
|
||||
|
@ -21,11 +21,9 @@ PrintInlineDciString equ $013000
|
||||
jsr L10AB
|
||||
jsr L110F
|
||||
jsr L1108
|
||||
brk
|
||||
dfb $01
|
||||
brk $01
|
||||
dw data01
|
||||
brk
|
||||
dfb $02
|
||||
brk $02
|
||||
dw data02
|
||||
rts
|
||||
|
||||
@ -71,9 +69,7 @@ L10AB jsr PrintInlineNullString
|
||||
|
||||
L1108 jsl PrintInlineL2String
|
||||
asl A
|
||||
brk
|
||||
|
||||
dfb $60
|
||||
brk $60
|
||||
|
||||
L110F jsr PrintInlineNullString
|
||||
adc $6e
|
||||
|
@ -24,11 +24,9 @@ PrintInlineDciString = $013000
|
||||
jsr L10AB
|
||||
jsr L110F
|
||||
jsr L1108
|
||||
brk
|
||||
!byte $01
|
||||
!byte $00,$01
|
||||
!word data01
|
||||
brk
|
||||
!byte $02
|
||||
!byte $00,$02
|
||||
!word data02
|
||||
rts
|
||||
|
||||
@ -76,9 +74,7 @@ L10AB jsr PrintInlineNullString
|
||||
|
||||
L1108 jsl PrintInlineL2String
|
||||
asl
|
||||
brk
|
||||
|
||||
!byte $60
|
||||
!byte $00,$60
|
||||
|
||||
L110F jsr PrintInlineNullString
|
||||
adc $6e
|
||||
|
@ -25,11 +25,9 @@ PrintInlineDciString = $013000
|
||||
jsr L10AB
|
||||
jsr L110F
|
||||
jsr L1108
|
||||
brk
|
||||
.byte $01
|
||||
.byte $00,$01
|
||||
.word data01
|
||||
brk
|
||||
.byte $02
|
||||
.byte $00,$02
|
||||
.word data02
|
||||
rts
|
||||
|
||||
@ -81,9 +79,7 @@ L10AB: jsr PrintInlineNullString
|
||||
|
||||
L1108: jsl PrintInlineL2String
|
||||
asl A
|
||||
brk
|
||||
|
||||
.byte $60
|
||||
.byte $00,$60
|
||||
|
||||
L110F: jsr PrintInlineNullString
|
||||
adc $6e
|
||||
|
@ -28,6 +28,7 @@ namespace SourceGen {
|
||||
private const string LOAD_ADDRESS = "load-address";
|
||||
private const string ENTRY_FLAGS = "entry-flags";
|
||||
private const string UNDOCUMENTED_OPCODES = "undocumented-opcodes";
|
||||
private const string TWO_BYTE_BRK = "two-byte-brk";
|
||||
private const string FIRST_WORD_IS_LOAD_ADDR = "first-word-is-load-addr";
|
||||
private const string DEFAULT_TEXT_ENCODING = "default-text-encoding";
|
||||
|
||||
@ -105,6 +106,15 @@ namespace SourceGen {
|
||||
return GetBoolParam(sysDef, UNDOCUMENTED_OPCODES, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default setting for two-byte BRKs.
|
||||
/// </summary>
|
||||
/// <param name="sysDef">SystemDef instance.</param>
|
||||
/// <returns>Enable/disable value.</returns>
|
||||
public static bool GetTwoByteBrk(SystemDef sysDef) {
|
||||
return GetBoolParam(sysDef, TWO_BYTE_BRK, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default setting for using the first two bytes of the file as the
|
||||
/// load address.
|
||||
|
@ -76,6 +76,8 @@ limitations under the License.
|
||||
SelectionChanged="CpuComboBox_SelectionChanged"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Enable undocumented instructions"
|
||||
IsChecked="{Binding IncludeUndocumentedInstr}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Treat BRK as two-byte instruction"
|
||||
IsChecked="{Binding TwoByteBrk}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Entry Flags" Grid.Column="0" Grid.Row="1" Padding="2,4">
|
||||
|
@ -254,8 +254,9 @@ namespace SourceGen.WpfGui {
|
||||
}
|
||||
public AutoLabelItem[] AutoLabelItems { get; private set; }
|
||||
|
||||
//
|
||||
// properties for checkboxes
|
||||
|
||||
//
|
||||
public bool IncludeUndocumentedInstr {
|
||||
get { return mWorkProps.IncludeUndocumentedInstr; }
|
||||
set {
|
||||
@ -264,6 +265,14 @@ namespace SourceGen.WpfGui {
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool TwoByteBrk {
|
||||
get { return mWorkProps.TwoByteBrk; }
|
||||
set {
|
||||
mWorkProps.TwoByteBrk = value;
|
||||
OnPropertyChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool AnalyzeUncategorizedData {
|
||||
get { return mWorkProps.AnalysisParams.AnalyzeUncategorizedData; }
|
||||
set {
|
||||
@ -382,7 +391,7 @@ namespace SourceGen.WpfGui {
|
||||
|
||||
private void ChangeFlagButton_Click(object sender, RoutedEventArgs e) {
|
||||
CpuDef cpuDef = CpuDef.GetBestMatch(mWorkProps.CpuType,
|
||||
mWorkProps.IncludeUndocumentedInstr);
|
||||
mWorkProps.IncludeUndocumentedInstr, mWorkProps.TwoByteBrk);
|
||||
EditStatusFlags dlg =
|
||||
new EditStatusFlags(this, mWorkProps.EntryFlags, cpuDef.HasEmuFlag);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user