improvements to string encoding/decoding and text output in the simulator

This commit is contained in:
Irmen de Jong 2020-02-08 01:12:30 +01:00
parent 3dd38c0ac8
commit 8c4d276810
7 changed files with 25 additions and 72 deletions

View File

@ -56,6 +56,7 @@ private fun compileMain(args: Array<String>) {
name = "c64"
machine = C64MachineDefinition
encodeString = { str -> Petscii.encodePetscii(str, true) }
decodeString = { bytes -> Petscii.decodePetscii(bytes, true) }
asmGenerator = ::AsmGen
}
}

View File

@ -10,6 +10,7 @@ internal interface CompilationTarget {
lateinit var name: String
lateinit var machine: IMachineDefinition
lateinit var encodeString: (str: String) -> List<Short>
lateinit var decodeString: (bytes: List<Short>) -> String
lateinit var asmGenerator: (Program, Zeropage, CompilationOptions, Path) -> IAssemblyGenerator
}
}

View File

@ -206,7 +206,7 @@ internal class AsmGen(private val program: Program,
return "$b0, $b1, $b2, $b3, $b4"
}
private fun encodeStr(str: String): List<Short> {
private fun petscii(str: String): List<Short> {
val bytes = Petscii.encodePetscii(str, true)
return bytes.plus(0)
}
@ -247,7 +247,7 @@ internal class AsmGen(private val program: Program,
DataType.STRUCT -> {} // is flattened
DataType.STR -> {
val string = (decl.value as StringLiteralValue).value
outputStringvar(decl, encodeStr(string))
outputStringvar(decl, petscii(string))
}
DataType.ARRAY_UB -> {
val data = makeArrayFillDataUnsigned(decl)
@ -331,7 +331,7 @@ internal class AsmGen(private val program: Program,
// special treatment for string types: merge strings that are identical
val encodedstringVars = normalVars
.filter {it.datatype == DataType.STR }
.map { it to encodeStr((it.value as StringLiteralValue).value) }
.map { it to petscii((it.value as StringLiteralValue).value) }
.groupBy({it.second}, {it.first})
for((encoded, variables) in encodedstringVars) {
variables.dropLast(1).forEach { out(it.name) }

View File

@ -179,20 +179,21 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
if(stringVar!=null) {
val vardecl = stringVar.targetVarDecl(program.namespace)!!
val string = vardecl.value!! as StringLiteralValue
val encodedString = CompilationTarget.encodeString(string.value)
if(string.value.length==1) {
val firstCharEncoded = CompilationTarget.encodeString(string.value)[0]
functionCallStatement.arglist.clear()
functionCallStatement.arglist.add(NumericLiteralValue.optimalInteger(encodedString[0].toInt(), functionCallStatement.position))
functionCallStatement.arglist.add(NumericLiteralValue.optimalInteger(firstCharEncoded.toInt(), functionCallStatement.position))
functionCallStatement.target = IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position)
vardeclsToRemove.add(vardecl)
optimizationsDone++
return functionCallStatement
} else if(string.value.length==2) {
val firstTwoCharsEncoded = CompilationTarget.encodeString(string.value.take(2))
val scope = AnonymousScope(mutableListOf(), functionCallStatement.position)
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position),
mutableListOf(NumericLiteralValue.optimalInteger(encodedString[0].toInt(), functionCallStatement.position)), functionCallStatement.position))
mutableListOf(NumericLiteralValue.optimalInteger(firstTwoCharsEncoded[0].toInt(), functionCallStatement.position)), functionCallStatement.position))
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position),
mutableListOf(NumericLiteralValue.optimalInteger(encodedString[1].toInt(), functionCallStatement.position)), functionCallStatement.position))
mutableListOf(NumericLiteralValue.optimalInteger(firstTwoCharsEncoded[1].toInt(), functionCallStatement.position)), functionCallStatement.position))
vardeclsToRemove.add(vardecl)
optimizationsDone++
return scope

View File

@ -735,7 +735,7 @@ class AstVm(val program: Program, compilationTarget: String) {
break
else {
input.add(char)
dialog.canvas.printAscii(char)
dialog.canvas.printAsciiText(char.toString())
}
}
var inputStr = input.joinToString("")
@ -751,7 +751,7 @@ class AstVm(val program: Program, compilationTarget: String) {
dialog.canvas.printAsciiText(args[0].floatval.toString())
}
"c64.CHROUT" -> {
dialog.canvas.printAscii(args[0].byteval!!.toChar())
dialog.canvas.printAsciiText(args[0].byteval!!.toChar().toString())
}
"c64.CLEARSCR" -> {
dialog.canvas.clearScreen(6)

View File

@ -1,7 +1,7 @@
package prog8.vm.astvm
import prog8.compiler.target.CompilationTarget
import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.c64.Petscii
import kotlin.math.abs
class Memory(private val readObserver: (address: Int, value: Short) -> Short,
@ -94,23 +94,21 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short,
}
fun setString(address: Int, str: String) {
// lowercase PETSCII
val petscii = Petscii.encodePetscii(str, true)
val encoded = CompilationTarget.encodeString(str)
var addr = address
for (c in petscii) setUByte(addr++, c)
for (c in encoded) setUByte(addr++, c)
setUByte(addr, 0)
}
fun getString(strAddress: Int): String {
// lowercase PETSCII
val petscii = mutableListOf<Short>()
val encoded = mutableListOf<Short>()
var addr = strAddress
while(true) {
val byte = getUByte(addr++)
if(byte==0.toShort()) break
petscii.add(byte)
encoded.add(byte)
}
return Petscii.decodePetscii(petscii, true)
return CompilationTarget.decodeString(encoded)
}
fun clear() {
@ -121,24 +119,4 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short,
for(i in 0 until numbytes)
setUByte(to+i, getUByte(from+i))
}
fun getScreencodeString(strAddress: Int): String? {
// lowercase Screencodes
val screencodes = mutableListOf<Short>()
var addr = strAddress
while(true) {
val byte = getUByte(addr++)
if(byte==0.toShort()) break
screencodes.add(byte)
}
return Petscii.decodeScreencode(screencodes, true)
}
fun setScreencodeString(address: Int, str: String) {
// lowercase screencodes
val screencodes = Petscii.encodeScreencode(str, true)
var addr = address
for (c in screencodes) setUByte(addr++, c)
setUByte(addr, 0)
}
}

View File

@ -6,7 +6,6 @@ import java.awt.*
import java.awt.event.KeyEvent
import java.awt.event.KeyListener
import java.awt.image.BufferedImage
import java.io.CharConversionException
import java.util.ArrayDeque
import javax.swing.JFrame
import javax.swing.JPanel
@ -66,20 +65,18 @@ class BitmapScreenPanel : KeyListener, JPanel() {
fun printAsciiText(text: String) {
val t2 = text.substringBefore(0.toChar())
val lines = t2.split('\n')
for(line in lines.withIndex()) {
line.value.forEach { printAscii(it) }
if(line.index<lines.size-1)
printAscii('\n')
}
val petscii = Petscii.encodePetscii(t2, true)
petscii.forEach { printPetsciiChar(it) }
}
fun printAscii(char: Char) {
if(char=='\n' || char=='\u008d') {
fun printPetsciiChar(petscii: Short) {
if(petscii in listOf(0x0d.toShort(), 0x8d.toShort())) {
// Return and shift-Return
cursorX=0
cursorY++
} else {
setAsciiChar(cursorX, cursorY, char, 1)
val scr = Petscii.petscii2scr(petscii, false)
setScreenChar(cursorX, cursorY, scr, 1)
cursorX++
if (cursorX >= (SCREENWIDTH / 8)) {
cursorY++
@ -100,31 +97,6 @@ class BitmapScreenPanel : KeyListener, JPanel() {
}
}
fun writeAsciiTextAt(x: Int, y: Int, text: String, color: Short) {
val colorIdx = (color % C64MachineDefinition.colorPalette.size).toShort()
var xx=x
for(clearx in xx until xx+text.length) {
g2d.clearRect(8*clearx, 8*y, 8, 8)
}
for(c in text) {
if(c=='\u0000')
break
setAsciiChar(xx++, y, c, colorIdx)
}
}
fun setAsciiChar(x: Int, y: Int, char: Char, color: Short) {
g2d.clearRect(8*x, 8*y, 8, 8)
val colorIdx = (color % C64MachineDefinition.colorPalette.size).toShort()
val screencode = try {
Petscii.encodeScreencode(char.toString(), true)[0]
} catch (x: CharConversionException) {
'?'.toShort()
}
val coloredImage = C64MachineDefinition.Charset.getColoredChar(screencode, colorIdx)
g2d.drawImage(coloredImage, 8*x, 8*y , null)
}
fun setScreenChar(x: Int, y: Int, screencode: Short, color: Short) {
g2d.clearRect(8*x, 8*y, 8, 8)
val colorIdx = (color % C64MachineDefinition.colorPalette.size).toShort()