optimizations in debugwindow

This commit is contained in:
Irmen de Jong 2020-01-04 13:45:16 +01:00
parent 22893a552e
commit c3c40bc73e
10 changed files with 482 additions and 218 deletions

5
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Project exclude paths
/.
# Project exclude paths
/.

30
.idea/jarRepositories.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenLocal" />
<option name="name" value="MavenLocal" />
<option name="url" value="file:$MAVEN_REPOSITORY$/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component>
</project>

2
.idea/ksim65.iml Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownEnhProjectSettings">
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imagePathType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
<component name="MarkdownNavigatorHistory">
<PasteImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
<highlightList />
<directories />
<filenames />
</PasteImageHistory>
<CopyImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
<highlightList />
<directories />
<filenames />
</CopyImageHistory>
<PasteLinkHistory onPasteImageTargetRef="3" onPasteTargetRef="1" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteWikiElement="2" onPasteReferenceElement="2" hideInapplicableOperations="false" preserveLinkFormat="false" useHeadingForLinkText="false" linkFormat="0" saveAsDefaultOnOK="false" />
<TableToJsonHistory>
<entries />
</TableToJsonHistory>
<TableSortHistory>
<entries />
</TableSortHistory>
</component>
</project>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FlexmarkProjectSettings">
<FlexmarkHtmlSettings flexmarkSpecExampleRendering="0" flexmarkSpecExampleRenderHtml="false">
<flexmarkSectionLanguages>
<option name="1" value="Markdown" />
<option name="2" value="HTML" />
<option name="3" value="flexmark-ast:1" />
</flexmarkSectionLanguages>
</FlexmarkHtmlSettings>
</component>
<component name="MarkdownProjectSettings">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true" lastLayoutSetsDefault="false">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
<PegdownExtensions>
<option name="ANCHORLINKS" value="true" />
<option name="ATXHEADERSPACE" value="true" />
<option name="FENCED_CODE_BLOCKS" value="true" />
<option name="INTELLIJ_DUMMY_IDENTIFIER" value="true" />
<option name="RELAXEDHRULES" value="true" />
<option name="STRIKETHROUGH" value="true" />
<option name="TABLES" value="true" />
<option name="TASKLISTITEMS" value="true" />
</PegdownExtensions>
<ParserOptions>
<option name="COMMONMARK_LISTS" value="true" />
<option name="EMOJI_SHORTCUTS" value="true" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="PRODUCTION_SPEC_PARSER" value="true" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.generator" providerName="Unmodified HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.css" providerName="No Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
<cssUriHistory />
</CssSettings>
</component>
</project>

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="openjdk-11" project-jdk-type="JavaSDK" />
</project>

124
.idea/uiDesigner.xml Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View File

@ -39,9 +39,9 @@ class C64Machine(title: String) : IVirtualMachine {
val kernalRom = Rom(0xe000, 0xffff).also { it.load(kernalData) }
val cpuIoPort = CpuIoPort(cpu)
private val monitor = Monitor(bus, cpu)
private val debugWindow = DebugWindow(this)
private val hostDisplay = MainC64Window(title, chargenData, ram, cpu, cia1)
private val monitor = Monitor(bus, cpu)
private var paused = false
init {

View File

@ -0,0 +1,233 @@
package razorvine.examplemachines
import razorvine.ksim65.*
import java.awt.*
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.WindowEvent
import java.io.File
import javax.swing.*
import javax.swing.text.DefaultCaret
class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v${Version.version}"),
ActionListener {
private class UnaliasedTextBox(rows: Int, columns: Int) : JTextArea(rows, columns) {
override fun paintComponent(g: Graphics) {
g as Graphics2D
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF)
super.paintComponent(g)
}
}
private val cyclesTf = JTextField("00000000000000")
private val speedKhzTf = JTextField("0000000")
private val regAtf = JTextField("000")
private val regXtf = JTextField("000")
private val regYtf = JTextField("000")
private val regPCtf = JTextField("00000")
private val regSPtf = JTextField("000")
private val regPtf = JTextArea("NV-BDIZC\n000000000")
private val disassemTf = JTextField("00 00 00 lda (fffff),x")
private val pauseBt = JButton("Pause").also { it.actionCommand = "pause" }
private val zeropageTf = UnaliasedTextBox(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled = false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
private val stackpageTf = UnaliasedTextBox(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled = false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
init {
contentPane.layout = GridBagLayout()
defaultCloseOperation = EXIT_ON_CLOSE
val cpuPanel = JPanel(GridBagLayout())
cpuPanel.border = BorderFactory.createTitledBorder("CPU: ${vm.cpu.name}")
val gc = GridBagConstraints()
gc.insets = Insets(2, 2, 2, 2)
gc.anchor = GridBagConstraints.EAST
gc.gridx = 0
gc.gridy = 0
val cyclesLb = JLabel("cycles")
val speedKhzLb = JLabel("speed (kHz)")
val regAlb = JLabel("A")
val regXlb = JLabel("X")
val regYlb = JLabel("Y")
val regSPlb = JLabel("SP")
val regPClb = JLabel("PC")
val regPlb = JLabel("Status")
val disassemLb = JLabel("Instruction")
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, disassemLb, regPlb).forEach {
cpuPanel.add(it, gc)
gc.gridy++
}
gc.anchor = GridBagConstraints.WEST
gc.gridx = 1
gc.gridy = 0
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, disassemTf, regPtf).forEach {
it.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
it.disabledTextColor = Color.DARK_GRAY
it.isEnabled = false
if (it is JTextField) {
it.columns = it.text.length
} else if (it is JTextArea) {
it.border = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY),
BorderFactory.createEmptyBorder(2, 2, 2, 2))
}
cpuPanel.add(it, gc)
gc.gridy++
}
val buttonPanel = JPanel(FlowLayout())
buttonPanel.border = BorderFactory.createTitledBorder("Control")
val loadBt = JButton("Inject program").also { it.actionCommand = "inject" }
val resetBt = JButton("Reset").also { it.actionCommand = "reset" }
val stepBt = JButton("Step").also { it.actionCommand = "step" }
val irqBt = JButton("IRQ").also { it.actionCommand = "irq" }
val nmiBt = JButton("NMI").also { it.actionCommand = "nmi" }
val quitBt = JButton("Quit").also { it.actionCommand = "quit" }
listOf(loadBt, resetBt, irqBt, nmiBt, pauseBt, stepBt, quitBt).forEach {
it.addActionListener(this)
buttonPanel.add(it)
}
val zeropagePanel = JPanel()
zeropagePanel.layout = BoxLayout(zeropagePanel, BoxLayout.Y_AXIS)
zeropagePanel.border = BorderFactory.createTitledBorder("Zeropage and Stack")
val showZp = JCheckBox("show Zero page and Stack dumps", true)
showZp.addActionListener {
val visible = (it.source as JCheckBox).isSelected
zeropageTf.isVisible = visible
stackpageTf.isVisible = visible
}
zeropagePanel.add(showZp)
zeropagePanel.add(zeropageTf)
zeropagePanel.add(stackpageTf)
val monitorPanel = JPanel()
monitorPanel.layout = BoxLayout(monitorPanel, BoxLayout.Y_AXIS)
monitorPanel.border = BorderFactory.createTitledBorder("Built-in Monitor")
val output = JTextArea(6, 80)
output.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
output.isEditable = false
val outputScroll = JScrollPane(output)
monitorPanel.add(outputScroll)
outputScroll.verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
(output.caret as DefaultCaret).updatePolicy = DefaultCaret.ALWAYS_UPDATE
val input = JTextField(50)
input.border = BorderFactory.createLineBorder(Color.LIGHT_GRAY)
input.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
input.addActionListener {
output.append("\n")
val command = input.text.trim()
val result = vm.executeMonitorCommand(command)
if (result.echo) output.append("> $command\n")
output.append(result.output)
input.text = result.prompt
}
monitorPanel.add(input)
output.append(vm.executeMonitorCommand("h").output)
gc.gridx = 0
gc.gridy = 0
gc.fill = GridBagConstraints.BOTH
contentPane.add(cpuPanel, gc)
gc.gridy++
contentPane.add(zeropagePanel, gc)
gc.gridy++
contentPane.add(monitorPanel, gc)
gc.gridy++
contentPane.add(buttonPanel, gc)
pack()
}
override fun actionPerformed(e: ActionEvent) {
when (e.actionCommand) {
"inject" -> {
val chooser = JFileChooser()
chooser.dialogTitle = "Choose binary program or .prg to load"
chooser.currentDirectory = File(".")
chooser.isMultiSelectionEnabled = false
val result = chooser.showOpenDialog(this)
if (result == JFileChooser.APPROVE_OPTION) {
if (chooser.selectedFile.extension == "prg") {
vm.loadFileInRam(chooser.selectedFile, null)
} else {
val addressStr = JOptionPane.showInputDialog(this,
"The selected file isn't a .prg.\nSpecify memory load address (hexadecimal) manually.",
"Load address", JOptionPane.QUESTION_MESSAGE, null, null,
"$") as String
val loadAddress = Integer.parseInt(addressStr.removePrefix("$"), 16)
vm.loadFileInRam(chooser.selectedFile, loadAddress)
}
}
}
"reset" -> {
vm.bus.reset()
updateCpu(vm.cpu, vm.bus)
}
"step" -> {
vm.step()
updateCpu(vm.cpu, vm.bus)
}
"pause" -> {
vm.pause(true)
pauseBt.actionCommand = "continue"
pauseBt.text = "Continue"
}
"continue" -> {
vm.pause(false)
pauseBt.actionCommand = "pause"
pauseBt.text = "Pause"
}
"irq" -> vm.cpu.irq()
"nmi" -> vm.cpu.nmi()
"quit" -> {
dispatchEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSING))
}
}
}
fun updateCpu(cpu: Cpu6502, bus: Bus) {
val state = cpu.snapshot()
cyclesTf.text = state.cycles.toString()
regAtf.text = hexB(state.A)
regXtf.text = hexB(state.X)
regYtf.text = hexB(state.Y)
regPtf.text = "NV-BDIZC\n"+state.P.asInt().toString(2).padStart(8, '0')
regPCtf.text = hexW(state.PC)
regSPtf.text = hexB(state.SP)
val memory = bus.memoryComponentFor(state.PC)
disassemTf.text = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim()
if (zeropageTf.isVisible || stackpageTf.isVisible) {
val pages = vm.getZeroAndStackPages()
if (pages.isNotEmpty()) {
val zpLines = (0..0xff step 32).map { location ->
" ${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
}
val stackLines = (0x100..0x1ff step 32).map { location ->
"${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
}
zeropageTf.text = zpLines.joinToString("\n")
stackpageTf.text = stackLines.joinToString("\n")
}
}
speedKhzTf.text = "%.1f".format(cpu.averageSpeedKhzSinceReset)
}
}

View File

@ -4,8 +4,6 @@ import razorvine.ksim65.*
import java.awt.*
import java.awt.event.*
import java.awt.image.BufferedImage
import java.io.File
import java.lang.Integer.parseInt
import java.util.*
import javax.imageio.ImageIO
import javax.swing.*
@ -139,221 +137,6 @@ private class BitmapScreenPanel : JPanel() {
}
}
private class UnaliasedTextBox(rows: Int, columns: Int) : JTextArea(rows, columns) {
override fun paintComponent(g: Graphics) {
g as Graphics2D
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF)
super.paintComponent(g)
}
}
class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v${Version.version}"), ActionListener {
private val cyclesTf = JTextField("00000000000000")
private val speedKhzTf = JTextField("0000000")
private val regAtf = JTextField("000")
private val regXtf = JTextField("000")
private val regYtf = JTextField("000")
private val regPCtf = JTextField("00000")
private val regSPtf = JTextField("000")
private val regPtf = JTextArea("NV-BDIZC\n000000000")
private val disassemTf = JTextField("00 00 00 lda (fffff),x")
private val pauseBt = JButton("Pause").also { it.actionCommand = "pause" }
private val zeropageTf = UnaliasedTextBox(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled = false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
private val stackpageTf = UnaliasedTextBox(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled = false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
init {
contentPane.layout = GridBagLayout()
defaultCloseOperation = EXIT_ON_CLOSE
val cpuPanel = JPanel(GridBagLayout())
cpuPanel.border = BorderFactory.createTitledBorder("CPU: ${vm.cpu.name}")
val gc = GridBagConstraints()
gc.insets = Insets(2, 2, 2, 2)
gc.anchor = GridBagConstraints.EAST
gc.gridx = 0
gc.gridy = 0
val cyclesLb = JLabel("cycles")
val speedKhzLb = JLabel("speed (kHz)")
val regAlb = JLabel("A")
val regXlb = JLabel("X")
val regYlb = JLabel("Y")
val regSPlb = JLabel("SP")
val regPClb = JLabel("PC")
val regPlb = JLabel("Status")
val disassemLb = JLabel("Instruction")
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, disassemLb, regPlb).forEach {
cpuPanel.add(it, gc)
gc.gridy++
}
gc.anchor = GridBagConstraints.WEST
gc.gridx = 1
gc.gridy = 0
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, disassemTf, regPtf).forEach {
it.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
it.disabledTextColor = Color.DARK_GRAY
it.isEnabled = false
if (it is JTextField) {
it.columns = it.text.length
} else if (it is JTextArea) {
it.border = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY),
BorderFactory.createEmptyBorder(2, 2, 2, 2))
}
cpuPanel.add(it, gc)
gc.gridy++
}
val buttonPanel = JPanel(FlowLayout())
buttonPanel.border = BorderFactory.createTitledBorder("Control")
val loadBt = JButton("Inject program").also { it.actionCommand = "inject" }
val resetBt = JButton("Reset").also { it.actionCommand = "reset" }
val stepBt = JButton("Step").also { it.actionCommand = "step" }
val irqBt = JButton("IRQ").also { it.actionCommand = "irq" }
val nmiBt = JButton("NMI").also { it.actionCommand = "nmi" }
val quitBt = JButton("Quit").also { it.actionCommand = "quit" }
listOf(loadBt, resetBt, irqBt, nmiBt, pauseBt, stepBt, quitBt).forEach {
it.addActionListener(this)
buttonPanel.add(it)
}
val zeropagePanel = JPanel()
zeropagePanel.layout = BoxLayout(zeropagePanel, BoxLayout.Y_AXIS)
zeropagePanel.border = BorderFactory.createTitledBorder("Zeropage and Stack")
val showZp = JCheckBox("show Zero page and Stack dumps", true)
showZp.addActionListener {
val visible = (it.source as JCheckBox).isSelected
zeropageTf.isVisible = visible
stackpageTf.isVisible = visible
}
zeropagePanel.add(showZp)
zeropagePanel.add(zeropageTf)
zeropagePanel.add(stackpageTf)
val monitorPanel = JPanel()
monitorPanel.layout = BoxLayout(monitorPanel, BoxLayout.Y_AXIS)
monitorPanel.border = BorderFactory.createTitledBorder("Built-in Monitor")
val output = JTextArea(6, 80)
output.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
output.isEditable = false
val outputScroll = JScrollPane(output)
monitorPanel.add(outputScroll)
outputScroll.verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
val input = JTextField(50)
input.border = BorderFactory.createLineBorder(Color.LIGHT_GRAY)
input.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
input.addActionListener {
output.append("\n")
val command = input.text.trim()
val result = vm.executeMonitorCommand(command)
if (result.echo) output.append("> $command\n")
output.append(result.output)
input.text = result.prompt
}
monitorPanel.add(input)
gc.gridx = 0
gc.gridy = 0
gc.fill = GridBagConstraints.BOTH
contentPane.add(cpuPanel, gc)
gc.gridy++
contentPane.add(zeropagePanel, gc)
gc.gridy++
contentPane.add(monitorPanel, gc)
gc.gridy++
contentPane.add(buttonPanel, gc)
pack()
}
override fun actionPerformed(e: ActionEvent) {
when (e.actionCommand) {
"inject" -> {
val chooser = JFileChooser()
chooser.dialogTitle = "Choose binary program or .prg to load"
chooser.currentDirectory = File(".")
chooser.isMultiSelectionEnabled = false
val result = chooser.showOpenDialog(this)
if (result == JFileChooser.APPROVE_OPTION) {
if (chooser.selectedFile.extension == "prg") {
vm.loadFileInRam(chooser.selectedFile, null)
} else {
val addressStr = JOptionPane.showInputDialog(this,
"The selected file isn't a .prg.\nSpecify memory load address (hexadecimal) manually.",
"Load address", JOptionPane.QUESTION_MESSAGE, null, null,
"$") as String
val loadAddress = parseInt(addressStr.removePrefix("$"), 16)
vm.loadFileInRam(chooser.selectedFile, loadAddress)
}
}
}
"reset" -> {
vm.bus.reset()
updateCpu(vm.cpu, vm.bus)
}
"step" -> {
vm.step()
updateCpu(vm.cpu, vm.bus)
}
"pause" -> {
vm.pause(true)
pauseBt.actionCommand = "continue"
pauseBt.text = "Continue"
}
"continue" -> {
vm.pause(false)
pauseBt.actionCommand = "pause"
pauseBt.text = "Pause"
}
"irq" -> vm.cpu.irq()
"nmi" -> vm.cpu.nmi()
"quit" -> {
dispatchEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSING))
}
}
}
fun updateCpu(cpu: Cpu6502, bus: Bus) {
val state = cpu.snapshot()
cyclesTf.text = state.cycles.toString()
regAtf.text = hexB(state.A)
regXtf.text = hexB(state.X)
regYtf.text = hexB(state.Y)
regPtf.text = "NV-BDIZC\n"+state.P.asInt().toString(2).padStart(8, '0')
regPCtf.text = hexW(state.PC)
regSPtf.text = hexB(state.SP)
val memory = bus.memoryComponentFor(state.PC)
disassemTf.text = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim()
val pages = vm.getZeroAndStackPages()
if (pages.isNotEmpty()) {
val zpLines = (0..0xff step 32).map { location ->
" ${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
}
val stackLines = (0x100..0x1ff step 32).map { location ->
"${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
}
zeropageTf.text = zpLines.joinToString("\n")
stackpageTf.text = stackLines.joinToString("\n")
}
speedKhzTf.text = "%.1f".format(cpu.averageSpeedKhzSinceReset)
}
}
class MainWindow(title: String) : JFrame(title), KeyListener, MouseInputListener, IHostInterface {
private val canvas = BitmapScreenPanel()