mirror of
https://github.com/irmen/prog8.git
synced 2025-01-14 01:29:55 +00:00
improvements to string encoding/decoding and text output in the simulator
This commit is contained in:
parent
3dd38c0ac8
commit
8c4d276810
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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) }
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user