From c5504c6657b8acd6186b851e2836c717fe3496b7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 25 Feb 2022 23:48:39 +0100 Subject: [PATCH] added ATASCII encoding table for atari --- .../src/prog8/codegen/target/AtariTarget.kt | 4 +- .../src/prog8/codegen/target/Encoder.kt | 3 + .../codegen/target/cbm/AtasciiEncoding.kt | 204 ++++++++++++++++++ .../codegen/target/cbm/PetsciiEncoding.kt | 8 +- compiler/res/prog8lib/atari/textio.p8 | 10 +- compiler/test/TestStringEncodings.kt | 15 ++ .../compilerinterface/IStringEncoding.kt | 1 + examples/atari/fibonacci.p8 | 2 +- examples/atari/hello.p8 | 8 +- examples/test.p8 | 9 +- 10 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 codeGenTargets/src/prog8/codegen/target/cbm/AtasciiEncoding.kt diff --git a/codeGenTargets/src/prog8/codegen/target/AtariTarget.kt b/codeGenTargets/src/prog8/codegen/target/AtariTarget.kt index d2550daca..793c48187 100644 --- a/codeGenTargets/src/prog8/codegen/target/AtariTarget.kt +++ b/codeGenTargets/src/prog8/codegen/target/AtariTarget.kt @@ -15,8 +15,8 @@ import prog8.compilerinterface.* class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer { override val name = NAME override val machine = AtariMachineDefinition() - override val supportedEncodings = setOf(Encoding.ISO) // TODO - override val defaultEncoding = Encoding.ISO // TODO + override val supportedEncodings = setOf(Encoding.ATASCII) + override val defaultEncoding = Encoding.ATASCII override val defaultLauncherType = LauncherType.NONE companion object { diff --git a/codeGenTargets/src/prog8/codegen/target/Encoder.kt b/codeGenTargets/src/prog8/codegen/target/Encoder.kt index 745cb4dd3..22314b680 100644 --- a/codeGenTargets/src/prog8/codegen/target/Encoder.kt +++ b/codeGenTargets/src/prog8/codegen/target/Encoder.kt @@ -2,6 +2,7 @@ package prog8.codegen.target import com.github.michaelbull.result.fold import prog8.ast.base.FatalAstException +import prog8.codegen.target.cbm.AtasciiEncoding import prog8.codegen.target.cbm.IsoEncoding import prog8.codegen.target.cbm.PetsciiEncoding import prog8.compilerinterface.Encoding @@ -13,6 +14,7 @@ internal object Encoder: IStringEncoding { Encoding.PETSCII -> PetsciiEncoding.encodePetscii(str, true) Encoding.SCREENCODES -> PetsciiEncoding.encodeScreencode(str, true) Encoding.ISO -> IsoEncoding.encode(str) + Encoding.ATASCII -> AtasciiEncoding.encode(str) else -> throw FatalAstException("unsupported encoding $encoding") } return coded.fold( @@ -25,6 +27,7 @@ internal object Encoder: IStringEncoding { Encoding.PETSCII -> PetsciiEncoding.decodePetscii(bytes, true) Encoding.SCREENCODES -> PetsciiEncoding.decodeScreencode(bytes, true) Encoding.ISO -> IsoEncoding.decode(bytes) + Encoding.ATASCII -> AtasciiEncoding.decode(bytes) else -> throw FatalAstException("unsupported encoding $encoding") } return decoded.fold( diff --git a/codeGenTargets/src/prog8/codegen/target/cbm/AtasciiEncoding.kt b/codeGenTargets/src/prog8/codegen/target/cbm/AtasciiEncoding.kt new file mode 100644 index 000000000..1684f64cd --- /dev/null +++ b/codeGenTargets/src/prog8/codegen/target/cbm/AtasciiEncoding.kt @@ -0,0 +1,204 @@ +package prog8.codegen.target.cbm + +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import java.io.CharConversionException + +object AtasciiEncoding { + + private val decodeTable: CharArray = charArrayOf( + // $00 + 'โ™ฅ', + 'โ”œ', + '\uf130', // ๐Ÿฎ‡ 0x02 -> RIGHT ONE QUARTER BLOCK (CUS) + 'โ”˜', + 'โ”ค', + 'โ”', + 'โ•ฑ', + 'โ•ฒ', + 'โ—ข', + 'โ–—', + 'โ—ฃ', + 'โ–', + 'โ–˜', + '\uf132', // ๐Ÿฎ‚ 0x1d -> UPPER ONE QUARTER BLOCK (CUS) + 'โ–‚', + 'โ––', + + // $10 + 'โ™ฃ', + 'โ”Œ', + 'โ”€', + 'โ”ผ', + 'โ€ข', + 'โ–„', + 'โ–Ž', + 'โ”ฌ', + 'โ”ด', + 'โ–Œ', + 'โ””', + '\u001b', // $1b = escape + '\ufffe', // UNDEFINED CHAR. $1c = cursor up + '\ufffe', // UNDEFINED CHAR. $1d = cursor down + '\ufffe', // UNDEFINED CHAR. $1e = cursor left + '\ufffe', // UNDEFINED CHAR. $1f = cursor right + + // $20 + ' ', + '!', + '"', + '#', + '$', + '%', + '&', + '\'', + '(', + ')', + '*', + '+', + ',', + '-', + '.', + '/', + + // $30 + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + ':', + ';', + '<', + '=', + '>', + '?', + + // $40 + '@', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + + // $50 + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + '[', + '\\', + ']', + '^', + '_', + + // $60 + 'โ™ฆ', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + + // $70 + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'โ™ ', + '|', + '\u000c', // $7d -> FORM FEED (CLEAR SCREEN) + '\u0008', // $7e -> BACKSPACE + '\u0009', // $7f -> TAB + + // $80-$ff are reversed video characters + various special characters. + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $90 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', + '\ufffe', + '\ufffe', + '\n', // $9b -> EOL/RETURN + '\ufffe', // UNDEFINED $9c = DELETE LINE + '\ufffe', // UNDEFINED $9d = INSERT LINE + '\ufffe', // UNDEFINED $9e = CLEAR TAB STOP + '\ufffe', // UNDEFINED $9f = SET TAB STOP + // $a0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $b0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $c0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $d0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $e0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + // $f0 + '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', + '\ufffe', + '\ufffe', + '\ufffe', + '\ufffe', + '\ufffe', + '\u0007', // $fd = bell/beep + '\u007f', // $fe = DELETE + '\ufffe' // UNDEFINED $ff = INSERT + ) + + private val encodeTable = decodeTable.withIndex().associate{it.value to it.index} + + + fun encode(str: String): Result, CharConversionException> { + return Ok(str.map { encodeTable.getValue(it).toUByte() }) + } + + fun decode(bytes: List): Result { + return Ok(bytes.map { decodeTable[it.toInt()] }.joinToString("")) + } +} diff --git a/codeGenTargets/src/prog8/codegen/target/cbm/PetsciiEncoding.kt b/codeGenTargets/src/prog8/codegen/target/cbm/PetsciiEncoding.kt index 576efd7d4..0a3f451fe 100644 --- a/codeGenTargets/src/prog8/codegen/target/cbm/PetsciiEncoding.kt +++ b/codeGenTargets/src/prog8/codegen/target/cbm/PetsciiEncoding.kt @@ -159,7 +159,7 @@ object PetsciiEncoding { '\uf105', // 0x90 -> BLACK COLOR SWITCH (CUS) '\uf11e', // ๏„ž 0x91 -> CURSOR UP (CUS) '\uf11b', // ๏„› 0x92 -> REVERSE VIDEO OFF (CUS) - '\u000c', // 0x93 -> FORM FEED + '\u000c', // 0x93 -> FORM FEED (CLEAR SCREEN) '\uf121', // ๏„ก 0x94 -> INSERT (CUS) '\uf106', // 0x95 -> BROWN COLOR SWITCH (CUS) '\uf107', // 0x96 -> LIGHT RED COLOR SWITCH (CUS) @@ -195,7 +195,7 @@ object PetsciiEncoding { '\u258e', // โ–Ž 0xB4 -> LEFT ONE QUARTER BLOCK '\u258d', // โ– 0xB5 -> LEFT THREE EIGTHS BLOCK '\uf131', // ๏„ฑ 0xB6 -> RIGHT THREE EIGHTHS BLOCK (CUS) - '\uf132', // ๏„ฒ 0xB7 -> UPPER ONE QUARTER BLOCK (CUS) + '\uf132', // ๐Ÿฎ‚ 0xB7 -> UPPER ONE QUARTER BLOCK (CUS) '\uf133', // ๏„ณ 0xB8 -> UPPER THREE EIGHTS BLOCK (CUS) '\u2583', // โ–ƒ 0xB9 -> LOWER THREE EIGHTHS BLOCK '\u2713', // โœ“ 0xBA -> CHECK MARK @@ -246,7 +246,7 @@ object PetsciiEncoding { '\u2595', // โ–• 0xE7 -> RIGHT ONE EIGHTH BLOCK '\uf12f', // ๏„ฏ 0xE8 -> LOWER HALF BLOCK MEDIUM SHADE (CUS) '\uf13a', // ๏„บ 0xE9 -> MEDIUM SHADE SLASHED RIGHT (CUS) - '\uf130', // ๏„ฐ 0xEA -> RIGHT ONE QUARTER BLOCK (CUS) + '\uf130', // ๐Ÿฎ‡ 0xEA -> RIGHT ONE QUARTER BLOCK (CUS) '\u251c', // โ”œ 0xEB -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT '\u2597', // โ–— 0xEC -> QUADRANT LOWER RIGHT '\u2514', // โ”” 0xED -> BOX DRAWINGS LIGHT UP AND RIGHT @@ -418,7 +418,7 @@ object PetsciiEncoding { '\uf105', // 0x90 -> BLACK COLOR SWITCH (CUS) '\uf11e', // 0x91 -> CURSOR UP (CUS) '\uf11b', // 0x92 -> REVERSE VIDEO OFF (CUS) - '\u000c', // 0x93 -> FORM FEED + '\u000c', // 0x93 -> FORM FEED (CLEAR SCREEN) '\uf121', // 0x94 -> INSERT (CUS) '\uf106', // 0x95 -> BROWN COLOR SWITCH (CUS) '\uf107', // 0x96 -> LIGHT RED COLOR SWITCH (CUS) diff --git a/compiler/res/prog8lib/atari/textio.p8 b/compiler/res/prog8lib/atari/textio.p8 index 90fe48298..19e60fae7 100644 --- a/compiler/res/prog8lib/atari/textio.p8 +++ b/compiler/res/prog8lib/atari/textio.p8 @@ -9,19 +9,15 @@ txt { const ubyte DEFAULT_WIDTH = 40 -const ubyte DEFAULT_HEIGHT = 25 +const ubyte DEFAULT_HEIGHT = 24 sub clear_screen() { - txt.chrout(147) ; TODO -} - -sub home() { - txt.chrout(19) ; TODO + txt.chrout(125) } sub nl() { - txt.chrout(155) + txt.chrout('\n') } sub spc() { diff --git a/compiler/test/TestStringEncodings.kt b/compiler/test/TestStringEncodings.kt index c8c0dc757..3b2da84c4 100644 --- a/compiler/test/TestStringEncodings.kt +++ b/compiler/test/TestStringEncodings.kt @@ -9,6 +9,7 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import prog8.codegen.target.C64Target import prog8.codegen.target.Cx16Target +import prog8.codegen.target.cbm.AtasciiEncoding import prog8.codegen.target.cbm.IsoEncoding import prog8.codegen.target.cbm.PetsciiEncoding import prog8tests.helpers.ErrorReporterForTests @@ -182,6 +183,20 @@ class TestStringEncodings: FunSpec({ } } + context("atari") { + test("atascii encoding") { + AtasciiEncoding.encode("a") shouldBe Ok(listOf(97u)) + AtasciiEncoding.encode("A") shouldBe Ok(listOf(65u)) + AtasciiEncoding.encode("\n") shouldBe Ok(listOf(155u)) + } + + test("atascii decoding") { + AtasciiEncoding.decode(listOf(97u)) shouldBe Ok("a") + AtasciiEncoding.decode(listOf(65u)) shouldBe Ok("A") + AtasciiEncoding.decode(listOf(155u)) shouldBe Ok("\n") + } + } + context("iso") { test("iso accepts iso-characters") { val result = IsoEncoding.encode("a_~รซรง") diff --git a/compilerAst/src/prog8/compilerinterface/IStringEncoding.kt b/compilerAst/src/prog8/compilerinterface/IStringEncoding.kt index 6ba12e32d..01ea96c17 100644 --- a/compilerAst/src/prog8/compilerinterface/IStringEncoding.kt +++ b/compilerAst/src/prog8/compilerinterface/IStringEncoding.kt @@ -4,6 +4,7 @@ enum class Encoding(val prefix: String) { DEFAULT("default"), // depends on compilation target PETSCII("petscii"), // c64/c128/cx16 SCREENCODES("sc"), // c64/c128/cx16 + ATASCII("atascii"), // atari ISO("iso") // cx16 } diff --git a/examples/atari/fibonacci.p8 b/examples/atari/fibonacci.p8 index e97e7dafa..9131f9463 100644 --- a/examples/atari/fibonacci.p8 +++ b/examples/atari/fibonacci.p8 @@ -15,7 +15,7 @@ main { txt.nl() } - txt.waitkey() + txt.waitkey() } uword fib_prev = 0 diff --git a/examples/atari/hello.p8 b/examples/atari/hello.p8 index fa6b1c6cd..7bf351f33 100644 --- a/examples/atari/hello.p8 +++ b/examples/atari/hello.p8 @@ -5,9 +5,9 @@ ; hello world test for Atari 8-bit main { - sub start() { + sub start() { txt.print("Hello, World!") - txt.nl() - txt.waitkey() + txt.nl() + txt.waitkey() } -} \ No newline at end of file +} diff --git a/examples/test.p8 b/examples/test.p8 index c47e3f45d..d9adbc58e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,7 +3,14 @@ main { sub start() { - txt.print("Hello!\nWorld\n") + ubyte cc + for cc in 32 to 124 { + txt.chrout(cc) + } + txt.waitkey() + + txt.clear_screen() + txt.print("\nHello!\nWorld\n") repeat { }