1
0
mirror of https://github.com/irmen/ksim65.git synced 2025-08-06 23:25:15 +00:00

demo prog and bugfixes in screen and rtc

This commit is contained in:
Irmen de Jong
2019-09-16 02:31:48 +02:00
parent da722cf63a
commit cf543159b4
8 changed files with 167 additions and 39 deletions

View File

@@ -175,7 +175,7 @@ class DebugWindow(val vm: VirtualMachine) : JFrame("debugger"), ActionListener {
buttonPanel.border = BorderFactory.createTitledBorder("Control") buttonPanel.border = BorderFactory.createTitledBorder("Control")
val resetBt = JButton("Reset").also { it.actionCommand = "reset" } val resetBt = JButton("Reset").also { it.actionCommand = "reset" }
val cycleBt = JButton("Cycle").also { it.actionCommand = "cycle" } val cycleBt = JButton("Step").also { it.actionCommand = "step" }
listOf(resetBt, cycleBt, pauseBt).forEach { listOf(resetBt, cycleBt, pauseBt).forEach {
it.addActionListener(this) it.addActionListener(this)
buttonPanel.add(it) buttonPanel.add(it)
@@ -192,8 +192,8 @@ class DebugWindow(val vm: VirtualMachine) : JFrame("debugger"), ActionListener {
vm.bus.reset() vm.bus.reset()
updateCpu(vm.cpu) updateCpu(vm.cpu)
} }
e.actionCommand == "cycle" -> { e.actionCommand == "step" -> {
vm.bus.clock() vm.stepInstruction()
updateCpu(vm.cpu) updateCpu(vm.cpu)
} }
e.actionCommand == "pause" -> { e.actionCommand == "pause" -> {

View File

@@ -29,6 +29,7 @@ class VirtualMachine(title: String) {
init { init {
ram[Cpu6502.RESET_vector] = 0x00 ram[Cpu6502.RESET_vector] = 0x00
ram[Cpu6502.RESET_vector + 1] = 0x10 ram[Cpu6502.RESET_vector + 1] = 0x10
ram.loadPrg(javaClass.getResource("/vmdemo.prg").toURI())
bus += rtc bus += rtc
bus += timer bus += timer
@@ -47,38 +48,26 @@ class VirtualMachine(title: String) {
var paused = false var paused = false
fun clock() { fun stepInstruction() {
if(!paused) { while (cpu.instrCycles > 0) bus.clock()
bus.clock() bus.clock()
debugWindow.updateCpu(cpu) while (cpu.instrCycles > 0) bus.clock()
}
fun start() {
val timer = java.util.Timer("clock", true)
timer.scheduleAtFixedRate(1, 1) {
if(!paused) {
repeat(10) {
stepInstruction()
}
debugWindow.updateCpu(cpu)
}
} }
} }
} }
fun main(args: Array<String>) { fun main(args: Array<String>) {
val machine = VirtualMachine("KSim65 demo virtual machine - using ksim65 v${Version.version}") val machine = VirtualMachine("KSim65 demo virtual machine - using ksim65 v${Version.version}")
val v = 0xd000 machine.start()
machine.bus[v + 0x08] = 20
machine.bus[v + 0x09] = 2
val text = ">> Hello this is an example text! 1234567890 <<\n" +
"next line 1\n" +
"next line 2\n" +
"next line 3\rnext line 4\rnext line 5\n" +
"a mistakk\be\n\n\n\n\n\n\n\n\n\n"
text.forEach {
machine.bus[v + 0x0a] = it.toShort()
}
repeat(20) {
Thread.sleep(100)
"time: ${LocalDateTime.now()}\n".forEach { c ->
machine.bus[v + 0x0a] = c.toShort()
}
}
val timer = java.util.Timer("clock", true)
timer.scheduleAtFixedRate(1, 1) {
machine.clock()
}
} }

View File

@@ -49,8 +49,13 @@ class Bus {
*/ */
fun read(address: Address): UByte { fun read(address: Address): UByte {
memComponents.forEach { memComponents.forEach {
if (address >= it.startAddress && address <= it.endAddress) if (address >= it.startAddress && address <= it.endAddress) {
return it[address] val data = it[address]
require(data in 0..255) {
"data must be a byte 0..255"
}
return data
}
} }
return 0xff return 0xff
} }
@@ -60,7 +65,9 @@ class Bus {
* Any memory mapped component that listens to the address, will receive the data. * Any memory mapped component that listens to the address, will receive the data.
*/ */
fun write(address: Address, data: UByte) { fun write(address: Address, data: UByte) {
require(data in 0..255) { "data must be a byte 0..255" } require(data in 0..255) {
"data must be a byte 0..255"
}
memComponents.forEach { memComponents.forEach {
if (address >= it.startAddress && address <= it.endAddress) if (address >= it.startAddress && address <= it.endAddress)
it[address] = data it[address] = data

View File

@@ -1,5 +1,6 @@
package razorvine.ksim65.components package razorvine.ksim65.components
import razorvine.examplemachine.ScreenDefs
import razorvine.ksim65.IHostInterface import razorvine.ksim65.IHostInterface
import kotlin.math.min import kotlin.math.min
@@ -67,11 +68,17 @@ class Display(
override operator fun get(address: Address): UByte { override operator fun get(address: Address): UByte {
return when(address-startAddress) { return when(address-startAddress) {
0x00 -> charposX.toShort()
0x01 -> charposY.toShort()
0x02 -> { 0x02 -> {
if(charposY in 0 until charHeight && charposX in 0 until charWidth) { if(charposY in 0 until charHeight && charposX in 0 until charWidth) {
charMatrix[charposY][charposX] charMatrix[charposY][charposX]
} else 0xff } else 0xff
} }
0x03 -> (pixelX and 0xff).toShort()
0x04 -> (pixelX ushr 8).toShort()
0x05 -> (pixelY and 0xff).toShort()
0x06 -> (pixelY ushr 8).toShort()
0x07 -> if(host.getPixel(pixelX, pixelY)) 1 else 0 0x07 -> if(host.getPixel(pixelX, pixelY)) 1 else 0
0x08 -> cursorX.toShort() 0x08 -> cursorX.toShort()
0x09 -> cursorY.toShort() 0x09 -> cursorY.toShort()
@@ -99,8 +106,10 @@ class Display(
0x05 -> pixelY = (pixelY and 0xff00) or data.toInt() 0x05 -> pixelY = (pixelY and 0xff00) or data.toInt()
0x06 -> pixelY = (pixelY and 0x00ff) or (data.toInt() shl 8) 0x06 -> pixelY = (pixelY and 0x00ff) or (data.toInt() shl 8)
0x07 -> { 0x07 -> {
if(data==0.toShort()) host.clearPixel(pixelX, pixelY) if(pixelX in 0 until ScreenDefs.SCREEN_WIDTH && pixelY in 0 until ScreenDefs.SCREEN_HEIGHT) {
else host.setPixel(pixelX, pixelY) if (data == 0.toShort()) host.clearPixel(pixelX, pixelY)
else host.setPixel(pixelX, pixelY)
}
} }
0x08 -> cursorX = min(data.toInt() and 65535, charWidth-1) 0x08 -> cursorX = min(data.toInt() and 65535, charWidth-1)
0x09 -> cursorY = min(data.toInt() and 65535, charHeight-1) 0x09 -> cursorY = min(data.toInt() and 65535, charHeight-1)

View File

@@ -1,7 +1,9 @@
package razorvine.ksim65.components package razorvine.ksim65.components
import java.io.File import java.io.File
import java.net.URI
import java.net.URL import java.net.URL
import java.nio.file.Paths
/** /**
* A RAM chip with read/write memory. * A RAM chip with read/write memory.
@@ -31,7 +33,14 @@ class Ram(startAddress: Address, endAddress: Address) : MemoryComponent(startAdd
* Load a c64-style prg program. This file type has the load address as the first two bytes. * Load a c64-style prg program. This file type has the load address as the first two bytes.
*/ */
fun loadPrg(filename: String) { fun loadPrg(filename: String) {
val bytes = File(filename).readBytes() loadPrg(Paths.get(filename).toUri())
}
/**
* Load a c64-style prg program. This file type has the load address as the first two bytes.
*/
fun loadPrg(file: URI) {
val bytes = File(file).readBytes()
val loadAddress = (bytes[0].toInt() or (bytes[1].toInt() shl 8)) and 65535 val loadAddress = (bytes[0].toInt() or (bytes[1].toInt() shl 8)) and 65535
val baseAddress = loadAddress - startAddress val baseAddress = loadAddress - startAddress
bytes.drop(2).forEachIndexed { index, byte -> bytes.drop(2).forEachIndexed { index, byte ->

View File

@@ -50,11 +50,11 @@ class RealTimeClock(startAddress: Address, endAddress: Address) : MemMappedCompo
0x05 -> LocalTime.now().minute.toShort() 0x05 -> LocalTime.now().minute.toShort()
0x06 -> LocalTime.now().second.toShort() 0x06 -> LocalTime.now().second.toShort()
0x07 -> { 0x07 -> {
val ms = LocalTime.now().nano / 1000 val ms = LocalTime.now().nano / 1000000
(ms and 255).toShort() (ms and 255).toShort()
} }
0x08 -> { 0x08 -> {
val ms = LocalTime.now().nano / 1000 val ms = LocalTime.now().nano / 1000000
(ms ushr 8).toShort() (ms ushr 8).toShort()
} }
else -> 0xff else -> 0xff

View File

@@ -0,0 +1,114 @@
.cpu "6502"
DISPLAY = $d000
RTC = $d100
TIMER = $d200
MOUSE = $d300
KEYBOARD = $d400
SCREEN_WIDTH=640
* = $1000
start
sei
ldx #$ff
txs
cli
; ------- fill the screen
ldx #0
ldy #0
fillscreen
stx DISPLAY+0
sty DISPLAY+1
lda character
sta DISPLAY+2 ; plot the char on the screen
inc character
inx
cpx #80
bne fillscreen
ldx #0
iny
cpy #30
bne fillscreen
; ------- clear the screen
lda #$0c ; form feed (clear screen)
sta DISPLAY+$0a
; ------- draw pixel line
pixelline
ldx pix_x
stx DISPLAY+3
ldx pix_x+1
stx DISPLAY+4
ldx pix_y
stx DISPLAY+5
ldx pix_y+1
stx DISPLAY+6
lda #1
sta DISPLAY+7 ; plot
lda pix_x
clc
adc #2
sta pix_x
bcc +
inc pix_x+1
+ inc pix_y
bne +
inc pix_y+1
+ lda pix_x+1
cmp #>SCREEN_WIDTH
bcc pixelline
bne stop1
lda pix_x
cmp #<SCREEN_WIDTH
bcc pixelline
bcs stop1
pix_x .word 0
pix_y .word 0
stop1
;--------- draw with mouse
mousedraw
ldx MOUSE+0
ldy MOUSE+2
stx DISPLAY+3
sty DISPLAY+5
ldx MOUSE+1
ldy MOUSE+3
stx DISPLAY+4
sty DISPLAY+6
lda #1
sta DISPLAY+7 ; plot pixel
jmp mousedraw
;--------- RTC display TODO
ldy #0
lda #0
sta DISPLAY+0
sta DISPLAY+1
rtcloop
ldx #0
readrtc
lda RTC,x
sta DISPLAY+2
inc DISPLAY+0
inx
cpx #9
bne readrtc
lda #0
sta DISPLAY+0
iny
sty DISPLAY+1
cpy #20
bne rtcloop
done jmp done
character .byte 0

Binary file not shown.