1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-29 07:29:30 +00:00
ksim65/src/main/kotlin/razorvine/examplemachines/GUI.kt

463 lines
18 KiB
Kotlin
Raw Normal View History

package razorvine.examplemachines
2019-09-15 03:04:57 +00:00
import razorvine.ksim65.*
2019-09-15 03:04:57 +00:00
import java.awt.*
import java.awt.event.*
import java.awt.image.BufferedImage
import java.io.File
import java.lang.Integer.parseInt
2019-09-18 19:14:00 +00:00
import java.util.*
import javax.imageio.ImageIO
2019-09-15 03:04:57 +00:00
import javax.swing.*
import javax.swing.event.MouseInputListener
2019-09-15 03:04:57 +00:00
/**
* Define a monochrome screen that can display 640x480 pixels
* and/or 80x30 characters (these are 8x16 pixels).
*/
object ScreenDefs {
const val SCREEN_WIDTH_CHARS = 80
const val SCREEN_HEIGHT_CHARS = 30
2019-10-12 10:35:18 +00:00
const val SCREEN_WIDTH = SCREEN_WIDTH_CHARS*8
const val SCREEN_HEIGHT = SCREEN_HEIGHT_CHARS*16
const val DISPLAY_PIXEL_SCALING: Double = 1.5
const val BORDER_SIZE = 32
2019-09-15 03:04:57 +00:00
val BG_COLOR = Color(0, 10, 20)
val FG_COLOR = Color(200, 255, 230)
val BORDER_COLOR = Color(20, 30, 40)
val Characters = loadCharacters()
private fun loadCharacters(): Array<BufferedImage> {
val img = ImageIO.read(javaClass.getResourceAsStream("/charset/unscii8x16.png"))
2019-10-14 18:48:48 +00:00
val charactersImage = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB)
2019-09-15 03:04:57 +00:00
charactersImage.createGraphics().drawImage(img, 0, 0, null)
val black = Color(0, 0, 0).rgb
val foreground = FG_COLOR.rgb
val nopixel = Color(0, 0, 0, 0).rgb
for (y in 0 until charactersImage.height) {
for (x in 0 until charactersImage.width) {
val col = charactersImage.getRGB(x, y)
2019-10-12 10:35:18 +00:00
if (col == black) charactersImage.setRGB(x, y, nopixel)
else charactersImage.setRGB(x, y, foreground)
2019-09-15 03:04:57 +00:00
}
}
2019-10-12 10:35:18 +00:00
val numColumns = charactersImage.width/8
2019-09-15 03:04:57 +00:00
val charImages = (0..255).map {
2019-10-12 10:35:18 +00:00
val charX = it%numColumns
val charY = it/numColumns
charactersImage.getSubimage(charX*8, charY*16, 8, 16)
2019-09-15 03:04:57 +00:00
}
return charImages.toTypedArray()
}
}
private class BitmapScreenPanel : JPanel() {
2019-10-01 23:25:16 +00:00
private val image: BufferedImage
private val g2d: Graphics2D
2019-09-15 03:04:57 +00:00
private var cursorX: Int = 0
private var cursorY: Int = 0
private var cursorState: Boolean = false
2019-09-15 03:04:57 +00:00
init {
2019-10-01 23:25:16 +00:00
val ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
val gd = ge.defaultScreenDevice.defaultConfiguration
image = gd.createCompatibleImage(ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT, Transparency.OPAQUE)
g2d = image.graphics as Graphics2D
2019-10-12 10:35:18 +00:00
val size =
Dimension((image.width*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt(), (image.height*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt())
2019-09-15 03:04:57 +00:00
minimumSize = size
maximumSize = size
preferredSize = size
isFocusable = true
2019-10-01 23:25:16 +00:00
isDoubleBuffered = false
2019-09-15 03:04:57 +00:00
requestFocusInWindow()
2019-10-01 23:25:16 +00:00
clearScreen()
2019-09-15 03:04:57 +00:00
}
override fun paint(graphics: Graphics) {
val g2d = graphics as Graphics2D
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
2019-10-12 10:35:18 +00:00
g2d.drawImage(image, 0, 0, (image.width*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt(),
(image.height*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt(), null)
if (cursorState) {
val scx = (cursorX*ScreenDefs.DISPLAY_PIXEL_SCALING*8).toInt()
val scy = (cursorY*ScreenDefs.DISPLAY_PIXEL_SCALING*16).toInt()
val scw = (8*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt()
val sch = (16*ScreenDefs.DISPLAY_PIXEL_SCALING).toInt()
g2d.setXORMode(Color.CYAN)
g2d.fillRect(scx, scy, scw, sch)
g2d.setPaintMode()
}
Toolkit.getDefaultToolkit().sync()
2019-09-15 03:04:57 +00:00
}
fun clearScreen() {
g2d.background = ScreenDefs.BG_COLOR
g2d.clearRect(0, 0, ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT)
2019-09-16 23:18:32 +00:00
cursorPos(0, 0)
2019-09-15 03:04:57 +00:00
}
fun setPixel(x: Int, y: Int, onOff: Boolean) {
2019-10-12 10:35:18 +00:00
if (onOff) image.setRGB(x, y, ScreenDefs.FG_COLOR.rgb)
else image.setRGB(x, y, ScreenDefs.BG_COLOR.rgb)
2019-09-15 03:04:57 +00:00
}
fun getPixel(x: Int, y: Int) = image.getRGB(x, y) != ScreenDefs.BG_COLOR.rgb
fun setChar(x: Int, y: Int, character: Char) {
2019-10-12 10:35:18 +00:00
g2d.clearRect(8*x, 16*y, 8, 16)
2019-09-15 03:04:57 +00:00
val coloredImage = ScreenDefs.Characters[character.toInt()]
2019-10-12 10:35:18 +00:00
g2d.drawImage(coloredImage, 8*x, 16*y, null)
2019-09-15 03:04:57 +00:00
}
fun scrollUp() {
2019-10-12 10:35:18 +00:00
g2d.copyArea(0, 16, ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT-16, 0, -16)
2019-09-15 03:04:57 +00:00
g2d.background = ScreenDefs.BG_COLOR
2019-10-12 10:35:18 +00:00
g2d.clearRect(0, ScreenDefs.SCREEN_HEIGHT-16, ScreenDefs.SCREEN_WIDTH, 16)
2019-09-15 03:04:57 +00:00
}
fun mousePixelPosition(): Point? {
val pos = mousePosition ?: return null
2019-10-12 10:35:18 +00:00
return Point((pos.x/ScreenDefs.DISPLAY_PIXEL_SCALING).toInt(), (pos.y/ScreenDefs.DISPLAY_PIXEL_SCALING).toInt())
2019-09-15 03:04:57 +00:00
}
2019-09-16 23:18:32 +00:00
fun cursorPos(x: Int, y: Int) {
2019-10-12 10:35:18 +00:00
if (x != cursorX || y != cursorY) cursorState = true
cursorX = x
cursorY = y
2019-09-16 23:18:32 +00:00
}
fun blinkCursor() {
cursorState = !cursorState
}
2019-09-15 03:04:57 +00:00
}
2019-10-12 10:35:18 +00:00
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)
}
}
2019-09-28 23:51:39 +00:00
class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v${Version.version}"), ActionListener {
2019-09-19 19:41:44 +00:00
private val cyclesTf = JTextField("00000000000000")
2019-09-21 13:57:14 +00:00
private val speedKhzTf = JTextField("0000000")
2019-09-19 19:41:44 +00:00
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")
2019-09-15 03:04:57 +00:00
private val pauseBt = JButton("Pause").also { it.actionCommand = "pause" }
private val zeropageTf = UnaliasedTextBox(8, 102).also {
2019-09-21 13:57:14 +00:00
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 {
2019-09-21 13:57:14 +00:00
it.border = BorderFactory.createEtchedBorder()
2019-10-12 10:35:18 +00:00
it.isEnabled = false
2019-09-21 13:57:14 +00:00
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
2019-09-15 03:04:57 +00:00
init {
2019-09-21 13:57:14 +00:00
contentPane.layout = GridBagLayout()
2019-09-16 21:15:04 +00:00
defaultCloseOperation = EXIT_ON_CLOSE
2019-09-15 03:04:57 +00:00
val cpuPanel = JPanel(GridBagLayout())
cpuPanel.border = BorderFactory.createTitledBorder("CPU: ${vm.cpu.name}")
val gc = GridBagConstraints()
2019-09-21 13:57:14 +00:00
gc.insets = Insets(2, 2, 2, 2)
2019-09-15 03:04:57 +00:00
gc.anchor = GridBagConstraints.EAST
gc.gridx = 0
gc.gridy = 0
val cyclesLb = JLabel("cycles")
2019-09-16 23:18:32 +00:00
val speedKhzLb = JLabel("speed (kHz)")
2019-09-15 03:04:57 +00:00
val regAlb = JLabel("A")
val regXlb = JLabel("X")
val regYlb = JLabel("Y")
val regSPlb = JLabel("SP")
val regPClb = JLabel("PC")
val regPlb = JLabel("Status")
2019-09-16 23:18:32 +00:00
val disassemLb = JLabel("Instruction")
2019-09-21 13:57:14 +00:00
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, disassemLb, regPlb).forEach {
2019-09-15 03:04:57 +00:00
cpuPanel.add(it, gc)
gc.gridy++
}
gc.anchor = GridBagConstraints.WEST
gc.gridx = 1
gc.gridy = 0
2019-09-21 13:57:14 +00:00
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, disassemTf, regPtf).forEach {
2019-09-16 21:15:04 +00:00
it.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
2019-09-21 13:57:14 +00:00
it.disabledTextColor = Color.DARK_GRAY
it.isEnabled = false
2019-10-12 10:35:18 +00:00
if (it is JTextField) {
2019-09-16 21:15:04 +00:00
it.columns = it.text.length
2019-10-12 10:35:18 +00:00
} else if (it is JTextArea) {
2019-09-16 21:15:04 +00:00
it.border = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY),
2019-10-12 10:35:18 +00:00
BorderFactory.createEmptyBorder(2, 2, 2, 2))
2019-09-16 21:15:04 +00:00
}
2019-09-15 03:04:57 +00:00
cpuPanel.add(it, gc)
gc.gridy++
}
val buttonPanel = JPanel(FlowLayout())
buttonPanel.border = BorderFactory.createTitledBorder("Control")
2019-10-05 21:34:43 +00:00
val loadBt = JButton("Inject program").also { it.actionCommand = "inject" }
2019-09-15 03:04:57 +00:00
val resetBt = JButton("Reset").also { it.actionCommand = "reset" }
2019-09-21 13:57:14 +00:00
val stepBt = JButton("Step").also { it.actionCommand = "step" }
2019-09-17 00:47:21 +00:00
val irqBt = JButton("IRQ").also { it.actionCommand = "irq" }
val nmiBt = JButton("NMI").also { it.actionCommand = "nmi" }
2019-09-16 21:15:04 +00:00
val quitBt = JButton("Quit").also { it.actionCommand = "quit" }
listOf(loadBt, resetBt, irqBt, nmiBt, pauseBt, stepBt, quitBt).forEach {
2019-09-15 03:04:57 +00:00
it.addActionListener(this)
buttonPanel.add(it)
}
2019-09-21 13:57:14 +00:00
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)
2019-09-21 13:57:14 +00:00
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)
2019-10-12 10:35:18 +00:00
if (result.echo) output.append("> $command\n")
output.append(result.output)
input.text = result.prompt
}
monitorPanel.add(input)
2019-10-12 10:35:18 +00:00
gc.gridx = 0
gc.gridy = 0
gc.fill = GridBagConstraints.BOTH
2019-09-21 13:57:14 +00:00
contentPane.add(cpuPanel, gc)
gc.gridy++
contentPane.add(zeropagePanel, gc)
gc.gridy++
contentPane.add(monitorPanel, gc)
gc.gridy++
2019-09-21 13:57:14 +00:00
contentPane.add(buttonPanel, gc)
2019-09-15 03:04:57 +00:00
pack()
}
override fun actionPerformed(e: ActionEvent) {
2019-10-12 10:35:18 +00:00
when (e.actionCommand) {
2019-10-05 21:34:43 +00:00
"inject" -> {
val chooser = JFileChooser()
chooser.dialogTitle = "Choose binary program or .prg to load"
chooser.currentDirectory = File(".")
chooser.isMultiSelectionEnabled = false
val result = chooser.showOpenDialog(this)
2019-10-12 10:35:18 +00:00
if (result == JFileChooser.APPROVE_OPTION) {
if (chooser.selectedFile.extension == "prg") {
vm.loadFileInRam(chooser.selectedFile, null)
} else {
2019-10-12 10:35:18 +00:00
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)
}
}
}
2019-09-16 21:15:04 +00:00
"reset" -> {
2019-09-15 03:04:57 +00:00
vm.bus.reset()
updateCpu(vm.cpu, vm.bus)
2019-09-15 03:04:57 +00:00
}
2019-09-16 21:15:04 +00:00
"step" -> {
vm.step()
updateCpu(vm.cpu, vm.bus)
2019-09-15 03:04:57 +00:00
}
2019-09-16 21:15:04 +00:00
"pause" -> {
vm.pause(true)
2019-09-15 03:04:57 +00:00
pauseBt.actionCommand = "continue"
2019-09-21 13:57:14 +00:00
pauseBt.text = "Continue"
2019-09-15 03:04:57 +00:00
}
2019-09-16 21:15:04 +00:00
"continue" -> {
vm.pause(false)
2019-09-15 03:04:57 +00:00
pauseBt.actionCommand = "pause"
pauseBt.text = "Pause"
}
2019-09-17 00:47:21 +00:00
"irq" -> vm.cpu.irq()
"nmi" -> vm.cpu.nmi()
2019-09-16 21:15:04 +00:00
"quit" -> {
dispatchEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSING))
}
2019-09-15 03:04:57 +00:00
}
}
2019-09-27 20:38:36 +00:00
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)
2019-10-12 10:35:18 +00:00
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)
2019-09-27 20:38:36 +00:00
disassemTf.text = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim()
2019-09-21 13:57:14 +00:00
val pages = vm.getZeroAndStackPages()
2019-10-12 10:35:18 +00:00
if (pages.isNotEmpty()) {
2019-09-21 13:57:14 +00:00
val zpLines = (0..0xff step 32).map { location ->
2019-10-12 10:35:18 +00:00
" ${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
2019-09-21 13:57:14 +00:00
}
val stackLines = (0x100..0x1ff step 32).map { location ->
2019-10-12 10:35:18 +00:00
"${'$'}${location.toString(16).padStart(2, '0')} "+((0..31).joinToString(" ") { lineoffset ->
pages[location+lineoffset].toString(16).padStart(2, '0')
})
2019-09-21 13:57:14 +00:00
}
2019-10-12 10:35:18 +00:00
zeropageTf.text = zpLines.joinToString("\n")
stackpageTf.text = stackLines.joinToString("\n")
2019-09-21 13:57:14 +00:00
}
2019-09-27 20:38:36 +00:00
speedKhzTf.text = "%.1f".format(cpu.averageSpeedKhzSinceReset)
2019-09-15 03:04:57 +00:00
}
}
class MainWindow(title: String) : JFrame(title), KeyListener, MouseInputListener, IHostInterface {
private val canvas = BitmapScreenPanel()
private val keyboardBuffer = ArrayDeque<Char>()
private var mousePos = Point(0, 0)
private var leftButton = false
private var rightButton = false
private var middleButton = false
2019-09-15 03:04:57 +00:00
init {
contentPane.layout = GridBagLayout()
2019-09-15 03:04:57 +00:00
defaultCloseOperation = EXIT_ON_CLOSE
isResizable = false
isFocusable = true
contentPane.background = ScreenDefs.BORDER_COLOR
val gc = GridBagConstraints()
gc.fill = GridBagConstraints.BOTH
2019-10-12 10:35:18 +00:00
gc.gridx = 1
gc.gridy = 1
gc.insets = Insets(ScreenDefs.BORDER_SIZE, ScreenDefs.BORDER_SIZE, ScreenDefs.BORDER_SIZE, ScreenDefs.BORDER_SIZE)
contentPane.add(canvas, gc)
2019-09-15 03:04:57 +00:00
addKeyListener(this)
addMouseMotionListener(this)
addMouseListener(this)
2019-09-21 13:57:14 +00:00
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, mutableSetOf())
2019-09-15 03:04:57 +00:00
pack()
setLocationRelativeTo(null)
2019-09-21 13:57:14 +00:00
location = Point(location.x/2, location.y)
2019-09-19 19:29:33 +00:00
requestFocusInWindow()
2019-09-15 03:04:57 +00:00
}
2019-10-04 18:39:57 +00:00
fun start(updateRate: Int) {
// repaint the screen's back buffer
2019-09-16 23:18:32 +00:00
var cursorBlink = 0L
2019-10-12 10:35:18 +00:00
val repaintTimer = javax.swing.Timer(1000/updateRate) {
2019-09-16 23:18:32 +00:00
repaint()
2019-10-12 10:35:18 +00:00
if (it.`when`-cursorBlink > 200L) {
2019-09-16 23:18:32 +00:00
cursorBlink = it.`when`
canvas.blinkCursor()
}
}
2019-09-15 03:04:57 +00:00
repaintTimer.initialDelay = 0
repaintTimer.start()
}
// keyboard events:
2019-09-18 18:57:46 +00:00
override fun keyTyped(event: KeyEvent) {
keyboardBuffer.add(event.keyChar)
2019-10-12 10:35:18 +00:00
while (keyboardBuffer.size > 8) keyboardBuffer.pop()
2019-09-15 03:04:57 +00:00
}
2019-09-18 18:57:46 +00:00
override fun keyPressed(event: KeyEvent) {}
override fun keyReleased(event: KeyEvent) {}
2019-09-15 03:04:57 +00:00
// mouse events:
2019-09-18 18:57:46 +00:00
override fun mousePressed(event: MouseEvent) {
val pos = canvas.mousePixelPosition()
2019-10-12 10:35:18 +00:00
if (pos == null) return
2019-09-18 18:57:46 +00:00
else {
mousePos = pos
leftButton = leftButton or SwingUtilities.isLeftMouseButton(event)
rightButton = rightButton or SwingUtilities.isRightMouseButton(event)
middleButton = middleButton or SwingUtilities.isMiddleMouseButton(event)
}
}
2019-10-12 10:35:18 +00:00
2019-09-18 18:57:46 +00:00
override fun mouseReleased(event: MouseEvent) {
2019-09-15 03:04:57 +00:00
val pos = canvas.mousePixelPosition()
2019-10-12 10:35:18 +00:00
if (pos == null) return
2019-09-15 03:04:57 +00:00
else {
mousePos = pos
2019-09-18 18:57:46 +00:00
leftButton = leftButton xor SwingUtilities.isLeftMouseButton(event)
rightButton = rightButton xor SwingUtilities.isRightMouseButton(event)
middleButton = middleButton xor SwingUtilities.isMiddleMouseButton(event)
2019-09-15 03:04:57 +00:00
}
}
2019-10-12 10:35:18 +00:00
2019-09-18 18:57:46 +00:00
override fun mouseEntered(event: MouseEvent) {}
override fun mouseExited(event: MouseEvent) {}
override fun mouseDragged(event: MouseEvent) = mouseMoved(event)
override fun mouseClicked(event: MouseEvent) {}
2019-09-15 03:04:57 +00:00
2019-09-18 18:57:46 +00:00
override fun mouseMoved(event: MouseEvent) {
2019-09-15 03:04:57 +00:00
val pos = canvas.mousePixelPosition()
2019-10-12 10:35:18 +00:00
if (pos == null) return
else mousePos = pos
2019-09-15 03:04:57 +00:00
}
// the overrides required for IHostDisplay:
override fun clearScreen() = canvas.clearScreen()
2019-10-12 10:35:18 +00:00
2019-09-15 03:04:57 +00:00
override fun setPixel(x: Int, y: Int) = canvas.setPixel(x, y, true)
override fun clearPixel(x: Int, y: Int) = canvas.setPixel(x, y, false)
override fun getPixel(x: Int, y: Int) = canvas.getPixel(x, y)
override fun setChar(x: Int, y: Int, character: Char) = canvas.setChar(x, y, character)
2019-09-16 23:18:32 +00:00
override fun cursor(x: Int, y: Int) = canvas.cursorPos(x, y)
2019-09-15 03:04:57 +00:00
override fun scrollUp() = canvas.scrollUp()
2019-09-16 23:18:32 +00:00
override fun mouse() = IHostInterface.MouseInfo(mousePos.x, mousePos.y, leftButton, rightButton, middleButton)
2019-09-15 03:04:57 +00:00
override fun keyboard(): Char? {
2019-10-12 10:35:18 +00:00
return if (keyboardBuffer.isEmpty()) null
else keyboardBuffer.pop()
2019-09-15 03:04:57 +00:00
}
2019-09-15 03:04:57 +00:00
}