From bfdd9aa656fd85004d362f255cd3c4ece0b69ba0 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 24 Sep 2019 21:14:24 +0200 Subject: [PATCH] finished C64 keyboard matrix instead of keypress simulation. --- src/main/kotlin/razorvine/c64emu/Cia.kt | 109 +++- src/main/kotlin/razorvine/c64emu/GUI.kt | 197 +------ src/main/kotlin/razorvine/c64emu/Petscii.kt | 545 -------------------- src/main/kotlin/razorvine/c64emu/c64Main.kt | 6 +- 4 files changed, 108 insertions(+), 749 deletions(-) delete mode 100644 src/main/kotlin/razorvine/c64emu/Petscii.kt diff --git a/src/main/kotlin/razorvine/c64emu/Cia.kt b/src/main/kotlin/razorvine/c64emu/Cia.kt index 0e2f141..b65f0eb 100644 --- a/src/main/kotlin/razorvine/c64emu/Cia.kt +++ b/src/main/kotlin/razorvine/c64emu/Cia.kt @@ -3,6 +3,7 @@ package razorvine.c64emu import razorvine.ksim65.components.Address import razorvine.ksim65.components.MemMappedComponent import razorvine.ksim65.components.UByte +import java.awt.event.KeyEvent /** * Minimal simulation of the MOS 6526 CIA chip. @@ -12,6 +13,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe private var ramBuffer = Array(endAddress - startAddress + 1) { 0x00 } private var pra = 0xff + private val hostKeyPresses = mutableSetOf() + init { require(endAddress - startAddress + 1 == 256) { "cia requires exactly 256 memory bytes (16*16 mirrored)" } } @@ -28,44 +31,119 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe val register = (address - startAddress) and 15 if(number==1) { return if (register == 0x01) { - // PRB data port B (if bit is cleared in PRA, contains keys pressed in that column of the matrix) - println("read PRB, pra=${pra.toString(2)}") + // register 1 on CIA#1 is the keyboard data port + // if bit is cleared in PRA, contains keys pressed in that column of the matrix + // TODO tweak the keyboard mapping so that keys like '=' can be pressed, + // RESTORE works (this is not a normal key but connected to the cpu's NMI line), + // Cursor up/down/left/right all work and left/right shift are different. when(pra) { 0b00000000 -> { // check if any keys are pressed at all (by checking all columns at once) - // TODO zero if there's any key pressed, 0xff otherwise - 0xff + if(hostKeyPresses.isEmpty()) 0xff.toShort() else 0x00.toShort() } 0b11111110 -> { // read column 0 - 0xff + val presses = + (if (KeyEvent.VK_DOWN in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_F5 in hostKeyPresses) 0b01000000 else 0) or + (if (KeyEvent.VK_F3 in hostKeyPresses) 0b00100000 else 0) or + (if (KeyEvent.VK_F1 in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_F7 in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_RIGHT in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_ENTER in hostKeyPresses) 0b00000010 else 0) or + (if (KeyEvent.VK_BACK_SPACE in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b11111101 -> { // read column 1 - 0xff + val presses = + (if(KeyEvent.VK_SHIFT in hostKeyPresses) 0b10000000 else 0) or // TODO make it LEFT shift only + (if(KeyEvent.VK_E in hostKeyPresses) 0b01000000 else 0) or + (if(KeyEvent.VK_S in hostKeyPresses) 0b00100000 else 0) or + (if(KeyEvent.VK_Z in hostKeyPresses) 0b00010000 else 0) or + (if(KeyEvent.VK_4 in hostKeyPresses) 0b00001000 else 0) or + (if(KeyEvent.VK_A in hostKeyPresses) 0b00000100 else 0) or + (if(KeyEvent.VK_W in hostKeyPresses) 0b00000010 else 0) or + (if(KeyEvent.VK_3 in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b11111011 -> { - 0b11011111.toShort() // 'F' + // read column 2 + val presses = + (if (KeyEvent.VK_X in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_T in hostKeyPresses) 0b01000000 else 0) or + (if (KeyEvent.VK_F in hostKeyPresses) 0b00100000 else 0) or + (if (KeyEvent.VK_C in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_6 in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_D in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_R in hostKeyPresses) 0b00000010 else 0) or + (if (KeyEvent.VK_5 in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b11110111 -> { // read column 3 - 0xff + val presses = + (if (KeyEvent.VK_V in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_U in hostKeyPresses) 0b01000000 else 0) or + (if (KeyEvent.VK_H in hostKeyPresses) 0b00100000 else 0) or + (if (KeyEvent.VK_B in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_8 in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_G in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_Y in hostKeyPresses) 0b00000010 else 0) or + (if (KeyEvent.VK_7 in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b11101111 -> { // read column 4 - 0xff + val presses = + (if (KeyEvent.VK_N in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_O in hostKeyPresses) 0b01000000 else 0) or + (if (KeyEvent.VK_K in hostKeyPresses) 0b00100000 else 0) or + (if (KeyEvent.VK_M in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_0 in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_J in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_I in hostKeyPresses) 0b00000010 else 0) or + (if (KeyEvent.VK_9 in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b11011111 -> { // read column 5 - 0xff + val presses = + (if (KeyEvent.VK_COMMA in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_OPEN_BRACKET in hostKeyPresses) 0b01000000 else 0) or // '[' = @ + (if (KeyEvent.VK_SEMICOLON in hostKeyPresses) 0b00100000 else 0) or // ';' -> : + (if (KeyEvent.VK_PERIOD in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_MINUS in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_L in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_P in hostKeyPresses) 0b00000010 else 0) or + (if (KeyEvent.VK_PLUS in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } 0b10111111 -> { // read column 6 - 0xff + val presses = + (if (KeyEvent.VK_SLASH in hostKeyPresses) 0b10000000 else 0) or + (if (KeyEvent.VK_BACK_SLASH in hostKeyPresses) 0b01000000 else 0) or // '\' -> up arrow + (if (KeyEvent.VK_EQUALS in hostKeyPresses) 0b00100000 else 0) or + (if (KeyEvent.VK_SHIFT in hostKeyPresses) 0b00010000 else 0) or // TODO RIGHT shift only + (if (KeyEvent.VK_HOME in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_QUOTE in hostKeyPresses) 0b00000100 else 0) or // ' -> ; + (if (KeyEvent.VK_CLOSE_BRACKET in hostKeyPresses) 0b00000010 else 0) or // ']' = * + (if (KeyEvent.VK_END in hostKeyPresses) 0b00000001 else 0) // END -> pound key + (presses.inv() and 255).toShort() } 0b01111111 -> { // read column 7 - 0xff + val presses = + (if (KeyEvent.VK_ESCAPE in hostKeyPresses) 0b10000000 else 0) or // esc -> STOP + (if (KeyEvent.VK_Q in hostKeyPresses) 0b01000000 else 0) or + (if (KeyEvent.VK_ALT in hostKeyPresses) 0b00100000 else 0) or // alt -> Commodore + (if (KeyEvent.VK_SPACE in hostKeyPresses) 0b00010000 else 0) or + (if (KeyEvent.VK_2 in hostKeyPresses) 0b00001000 else 0) or + (if (KeyEvent.VK_CONTROL in hostKeyPresses) 0b00000100 else 0) or + (if (KeyEvent.VK_BACK_QUOTE in hostKeyPresses) 0b00000010 else 0) or // '`' -> left arrow + (if (KeyEvent.VK_1 in hostKeyPresses) 0b00000001 else 0) + (presses.inv() and 255).toShort() } else -> { // invalid column selection @@ -93,4 +171,11 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe } // CIA #2 is not emulated yet } + + fun hostKeyPressed(event: KeyEvent) { + if(event.id==KeyEvent.KEY_PRESSED) + hostKeyPresses.add(event.keyCode) + else if(event.id==KeyEvent.KEY_RELEASED) + hostKeyPresses.remove(event.keyCode) + } } diff --git a/src/main/kotlin/razorvine/c64emu/GUI.kt b/src/main/kotlin/razorvine/c64emu/GUI.kt index 1e82303..f27b415 100644 --- a/src/main/kotlin/razorvine/c64emu/GUI.kt +++ b/src/main/kotlin/razorvine/c64emu/GUI.kt @@ -1,12 +1,9 @@ package razorvine.c64emu import razorvine.ksim65.components.MemoryComponent -import razorvine.ksim65.components.UByte import java.awt.* import java.awt.image.BufferedImage import java.awt.event.* -import java.io.CharConversionException -import java.util.* import javax.swing.* import javax.swing.Timer @@ -131,9 +128,13 @@ private class BitmapScreenPanel(val chargenData: ByteArray, val ram: MemoryCompo } } -class MainC64Window(title: String, chargenData: ByteArray, val ram: MemoryComponent) : JFrame(title), KeyListener { +class MainC64Window( + title: String, + chargenData: ByteArray, + val ram: MemoryComponent, + val keypressCia: Cia +) : JFrame(title), KeyListener { private val canvas = BitmapScreenPanel(chargenData, ram) - private val keyboardBuffer = ArrayDeque() private var borderTop: JPanel private var borderBottom: JPanel private var borderLeft: JPanel @@ -208,200 +209,18 @@ class MainC64Window(title: String, chargenData: ByteArray, val ram: MemoryCompon borderBottom.background = ScreenDefs.colorPalette[ram[0xd020].toInt() and 15] borderLeft.background = ScreenDefs.colorPalette[ram[0xd020].toInt() and 15] borderRight.background = ScreenDefs.colorPalette[ram[0xd020].toInt() and 15] - - if(keyboardBuffer.isNotEmpty()) { - // inject keystrokes directly into the c64's keyboard buffer (translate to petscii first) - var kbbLen = ram[0xc6] - while(kbbLen<=10 && keyboardBuffer.isNotEmpty()) { - try { - val petscii = keyEventToPetscii(keyboardBuffer.pop()) - if(petscii > 0) { - ram[0x277 + kbbLen] = petscii - kbbLen++ - } - } catch(ccx: CharConversionException) { - // ignore character - } - } - ram[0xc6] = kbbLen - } } repaintTimer.initialDelay = 0 repaintTimer.start() } - /** - * Map a key to the corresponding PETSCII character, - * that is inserted directly into the C64's character buffer. - * This avoids having to deal with the 'real' keyboard matrix, - * but it can't map keys like RUN/STOP and RESTORE properly. - * - * TODO: replace this by the real keyboard matrix. - */ - private fun keyEventToPetscii(ke: KeyEvent): UByte { - if(ke.isActionKey) { - // function keys, cursor keys etc. - if(ke.id == KeyEvent.KEY_PRESSED) { - return when (ke.keyCode) { - KeyEvent.VK_F1 -> 0x85 - KeyEvent.VK_F2 -> 0x86 - KeyEvent.VK_F3 -> 0x87 - KeyEvent.VK_F4 -> 0x88 - KeyEvent.VK_F5 -> 0x89 - KeyEvent.VK_F6 -> 0x8a - KeyEvent.VK_F7 -> 0x8b - KeyEvent.VK_F8 -> 0x8c - KeyEvent.VK_UP -> 0x91 - KeyEvent.VK_DOWN -> 0x11 - KeyEvent.VK_LEFT -> 0x9d - KeyEvent.VK_RIGHT -> 0x1d - KeyEvent.VK_HOME -> { - if(ke.modifiersEx and KeyEvent.SHIFT_DOWN_MASK != 0) - 0x93 // clear - else - 0x13 // home - } - KeyEvent.VK_INSERT -> 0x94 //insert - else -> 0 // no mapped key - } - } - } else { - if(ke.id == KeyEvent.KEY_PRESSED) { - return when(ke.keyChar) { - '\u001b' -> { - if(ke.isShiftDown) 0x83 - else 0x03 - } // break - '\n' -> 0x0d // enter - '\b' -> 0x14 // backspace ('delete') - '1' -> { - when { - ke.isControlDown -> 0x90 // black - ke.isAltDown -> 0x81 // orange - else -> '1'.toShort() - } - } - '2' -> { - when { - ke.isControlDown -> 0x05 // white - ke.isAltDown -> 0x95 // brown - else -> '2'.toShort() - } - } - '3' -> { - when { - ke.isControlDown -> 0x1c // red - ke.isAltDown -> 0x96 // pink - else -> '3'.toShort() - } - } - '4' -> { - when { - ke.isControlDown -> 0x9f // cyan - ke.isAltDown -> 0x97 // dark grey - else -> '4'.toShort() - } - } - '5' -> { - when { - ke.isControlDown -> 0x9c // purple - ke.isAltDown -> 0x98 // grey - else -> '5'.toShort() - } - } - '6' -> { - when { - ke.isControlDown -> 0x1e // green - ke.isAltDown -> 0x99 // light green - else -> '6'.toShort() - } - } - '7' -> { - when { - ke.isControlDown -> 0x1f // blue - ke.isAltDown -> 0x9a // light blue - else -> '7'.toShort() - } - } - '8' -> { - when { - ke.isControlDown -> 0x9e // yellow - ke.isAltDown -> 0x9b // light grey - else -> '8'.toShort() - } - } - '9' -> { - if (ke.isControlDown) 0x12 // reverse on - else '9'.toShort() - } - '0' -> { - if (ke.isControlDown) 0x92 // reverse off - else '0'.toShort() - } - '`' -> 0x5f // left arrow - '\\' -> 0x5e // up arrow - '|' -> 0x7e // pi - '}' -> 0x5c // pound - else -> { - if(ke.isAltDown) { - // commodore+key petscii symbol - return when(ke.keyCode) { - KeyEvent.VK_A -> 0xb0 - KeyEvent.VK_B -> 0xbf - KeyEvent.VK_C -> 0xbc - KeyEvent.VK_D -> 0xac - KeyEvent.VK_E -> 0xb1 - KeyEvent.VK_F -> 0xbb - KeyEvent.VK_G -> 0xa5 - KeyEvent.VK_H -> 0xb4 - KeyEvent.VK_I -> 0xa2 - KeyEvent.VK_J -> 0xb5 - KeyEvent.VK_K -> 0xa1 - KeyEvent.VK_L -> 0xb6 - KeyEvent.VK_M -> 0xa7 - KeyEvent.VK_N -> 0xaa - KeyEvent.VK_O -> 0xb9 - KeyEvent.VK_P -> 0xaf - KeyEvent.VK_Q -> 0xab - KeyEvent.VK_R -> 0xb2 - KeyEvent.VK_S -> 0xae - KeyEvent.VK_T -> 0xa3 - KeyEvent.VK_U -> 0xb8 - KeyEvent.VK_V -> 0xbe - KeyEvent.VK_W -> 0xb3 - KeyEvent.VK_X -> 0xbd - KeyEvent.VK_Y -> 0xb7 - KeyEvent.VK_Z -> 0xad - else -> 0 // not mapped - } - } else { - Petscii.encodePetscii(ke.keyChar.toString(), true)[0] - } - } - } - } - else if(ke.id == KeyEvent.KEY_RELEASED) { - if((ke.keyCode==KeyEvent.VK_SHIFT && ke.modifiersEx and KeyEvent.ALT_DOWN_MASK != 0) || - (ke.keyCode==KeyEvent.VK_ALT && ke.modifiersEx and KeyEvent.SHIFT_DOWN_MASK != 0)) { - // shift+alt is mapped to shift+commodore key, to toggle charsets - val charSet = ram[0xd018].toInt() and 0b00000010 - return if(charSet==0) - 0x0e // lo/up charset - else - 0x8e // up/gfx charset - } - } - } - return 0 // no mapped key - } - // keyboard events: override fun keyTyped(event: KeyEvent) {} override fun keyPressed(event: KeyEvent) { - keyboardBuffer += event + keypressCia.hostKeyPressed(event) } override fun keyReleased(event: KeyEvent) { - keyboardBuffer += event + keypressCia.hostKeyPressed(event) } } diff --git a/src/main/kotlin/razorvine/c64emu/Petscii.kt b/src/main/kotlin/razorvine/c64emu/Petscii.kt deleted file mode 100644 index e86720c..0000000 --- a/src/main/kotlin/razorvine/c64emu/Petscii.kt +++ /dev/null @@ -1,545 +0,0 @@ -package razorvine.c64emu - -import java.io.CharConversionException - -object Petscii { - - // decoding: from Petscii/Screencodes (0-255) to unicode - // character tables used from https://github.com/dj51d/cbmcodecs - - private val decodingPetsciiLowercase = arrayOf( - '\u0000', // 0x00 -> \u0000 - '\ufffe', // 0x01 -> UNDEFINED - '\ufffe', // 0x02 -> UNDEFINED - '\ufffe', // 0x03 -> UNDEFINED - '\ufffe', // 0x04 -> UNDEFINED - '\uf100', // 0x05 -> WHITE COLOR SWITCH (CUS) - '\ufffe', // 0x06 -> UNDEFINED - '\ufffe', // 0x07 -> UNDEFINED - '\uf118', // 0x08 -> DISABLE CHARACTER SET SWITCHING (CUS) - '\uf119', // 0x09 -> ENABLE CHARACTER SET SWITCHING (CUS) - '\ufffe', // 0x0A -> UNDEFINED - '\ufffe', // 0x0B -> UNDEFINED - '\ufffe', // 0x0C -> UNDEFINED - '\r' , // 0x0D -> CARRIAGE RETURN - '\u000e', // 0x0E -> SHIFT OUT - '\ufffe', // 0x0F -> UNDEFINED - '\ufffe', // 0x10 -> UNDEFINED - '\uf11c', // 0x11 -> CURSOR DOWN (CUS) - '\uf11a', // 0x12 -> REVERSE VIDEO ON (CUS) - '\uf120', // 0x13 -> HOME (CUS) - '\u007f', // 0x14 -> DELETE - '\ufffe', // 0x15 -> UNDEFINED - '\ufffe', // 0x16 -> UNDEFINED - '\ufffe', // 0x17 -> UNDEFINED - '\ufffe', // 0x18 -> UNDEFINED - '\ufffe', // 0x19 -> UNDEFINED - '\ufffe', // 0x1A -> UNDEFINED - '\ufffe', // 0x1B -> UNDEFINED - '\uf101', // 0x1C -> RED COLOR SWITCH (CUS) - '\uf11d', // 0x1D -> CURSOR RIGHT (CUS) - '\uf102', // 0x1E -> GREEN COLOR SWITCH (CUS) - '\uf103', // 0x1F -> BLUE COLOR SWITCH (CUS) - ' ' , // 0x20 -> SPACE - '!' , // ! 0x21 -> EXCLAMATION MARK - '"' , // " 0x22 -> QUOTATION MARK - '#' , // # 0x23 -> NUMBER SIGN - '$' , // $ 0x24 -> DOLLAR SIGN - '%' , // % 0x25 -> PERCENT SIGN - '&' , // & 0x26 -> AMPERSAND - '\'' , // ' 0x27 -> APOSTROPHE - '(' , // ( 0x28 -> LEFT PARENTHESIS - ')' , // ) 0x29 -> RIGHT PARENTHESIS - '*' , // * 0x2A -> ASTERISK - '+' , // + 0x2B -> PLUS SIGN - ',' , // , 0x2C -> COMMA - '-' , // - 0x2D -> HYPHEN-MINUS - '.' , // . 0x2E -> FULL STOP - '/' , // / 0x2F -> SOLIDUS - '0' , // 0 0x30 -> DIGIT ZERO - '1' , // 1 0x31 -> DIGIT ONE - '2' , // 2 0x32 -> DIGIT TWO - '3' , // 3 0x33 -> DIGIT THREE - '4' , // 4 0x34 -> DIGIT FOUR - '5' , // 5 0x35 -> DIGIT FIVE - '6' , // 6 0x36 -> DIGIT SIX - '7' , // 7 0x37 -> DIGIT SEVEN - '8' , // 8 0x38 -> DIGIT EIGHT - '9' , // 9 0x39 -> DIGIT NINE - ':' , // : 0x3A -> COLON - ';' , // ; 0x3B -> SEMICOLON - '<' , // < 0x3C -> LESS-THAN SIGN - '=' , // = 0x3D -> EQUALS SIGN - '>' , // > 0x3E -> GREATER-THAN SIGN - '?' , // ? 0x3F -> QUESTION MARK - '@' , // @ 0x40 -> COMMERCIAL AT - 'a' , // a 0x41 -> LATIN SMALL LETTER A - 'b' , // b 0x42 -> LATIN SMALL LETTER B - 'c' , // c 0x43 -> LATIN SMALL LETTER C - 'd' , // d 0x44 -> LATIN SMALL LETTER D - 'e' , // e 0x45 -> LATIN SMALL LETTER E - 'f' , // f 0x46 -> LATIN SMALL LETTER F - 'g' , // g 0x47 -> LATIN SMALL LETTER G - 'h' , // h 0x48 -> LATIN SMALL LETTER H - 'i' , // i 0x49 -> LATIN SMALL LETTER I - 'j' , // j 0x4A -> LATIN SMALL LETTER J - 'k' , // k 0x4B -> LATIN SMALL LETTER K - 'l' , // l 0x4C -> LATIN SMALL LETTER L - 'm' , // m 0x4D -> LATIN SMALL LETTER M - 'n' , // n 0x4E -> LATIN SMALL LETTER N - 'o' , // o 0x4F -> LATIN SMALL LETTER O - 'p' , // p 0x50 -> LATIN SMALL LETTER P - 'q' , // q 0x51 -> LATIN SMALL LETTER Q - 'r' , // r 0x52 -> LATIN SMALL LETTER R - 's' , // s 0x53 -> LATIN SMALL LETTER S - 't' , // t 0x54 -> LATIN SMALL LETTER T - 'u' , // u 0x55 -> LATIN SMALL LETTER U - 'v' , // v 0x56 -> LATIN SMALL LETTER V - 'w' , // w 0x57 -> LATIN SMALL LETTER W - 'x' , // x 0x58 -> LATIN SMALL LETTER X - 'y' , // y 0x59 -> LATIN SMALL LETTER Y - 'z' , // z 0x5A -> LATIN SMALL LETTER Z - '[' , // [ 0x5B -> LEFT SQUARE BRACKET - '\u00a3', // £ 0x5C -> POUND SIGN - ']' , // ] 0x5D -> RIGHT SQUARE BRACKET - '\u2191', // ↑ 0x5E -> UPWARDS ARROW - '\u2190', // ← 0x5F -> LEFTWARDS ARROW - '\u2500', // ─ 0x60 -> BOX DRAWINGS LIGHT HORIZONTAL - 'A' , // A 0x61 -> LATIN CAPITAL LETTER A - 'B' , // B 0x62 -> LATIN CAPITAL LETTER B - 'C' , // C 0x63 -> LATIN CAPITAL LETTER C - 'D' , // D 0x64 -> LATIN CAPITAL LETTER D - 'E' , // E 0x65 -> LATIN CAPITAL LETTER E - 'F' , // F 0x66 -> LATIN CAPITAL LETTER F - 'G' , // G 0x67 -> LATIN CAPITAL LETTER G - 'H' , // H 0x68 -> LATIN CAPITAL LETTER H - 'I' , // I 0x69 -> LATIN CAPITAL LETTER I - 'J' , // J 0x6A -> LATIN CAPITAL LETTER J - 'K' , // K 0x6B -> LATIN CAPITAL LETTER K - 'L' , // L 0x6C -> LATIN CAPITAL LETTER L - 'M' , // M 0x6D -> LATIN CAPITAL LETTER M - 'N' , // N 0x6E -> LATIN CAPITAL LETTER N - 'O' , // O 0x6F -> LATIN CAPITAL LETTER O - 'P' , // P 0x70 -> LATIN CAPITAL LETTER P - 'Q' , // Q 0x71 -> LATIN CAPITAL LETTER Q - 'R' , // R 0x72 -> LATIN CAPITAL LETTER R - 'S' , // S 0x73 -> LATIN CAPITAL LETTER S - 'T' , // T 0x74 -> LATIN CAPITAL LETTER T - 'U' , // U 0x75 -> LATIN CAPITAL LETTER U - 'V' , // V 0x76 -> LATIN CAPITAL LETTER V - 'W' , // W 0x77 -> LATIN CAPITAL LETTER W - 'X' , // X 0x78 -> LATIN CAPITAL LETTER X - 'Y' , // Y 0x79 -> LATIN CAPITAL LETTER Y - 'Z' , // Z 0x7A -> LATIN CAPITAL LETTER Z - '\u253c', // ┼ 0x7B -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - '\uf12e', //  0x7C -> LEFT HALF BLOCK MEDIUM SHADE (CUS) - '\u2502', // │ 0x7D -> BOX DRAWINGS LIGHT VERTICAL - '\u2592', // ▒ 0x7E -> MEDIUM SHADE - '\uf139', //  0x7F -> MEDIUM SHADE SLASHED LEFT (CUS) - '\ufffe', // 0x80 -> UNDEFINED - '\uf104', // 0x81 -> ORANGE COLOR SWITCH (CUS) - '\ufffe', // 0x82 -> UNDEFINED - '\ufffe', // 0x83 -> UNDEFINED - '\ufffe', // 0x84 -> UNDEFINED - '\uf110', //  0x85 -> FUNCTION KEY 1 (CUS) - '\uf112', //  0x86 -> FUNCTION KEY 3 (CUS) - '\uf114', //  0x87 -> FUNCTION KEY 5 (CUS) - '\uf116', //  0x88 -> FUNCTION KEY 7 (CUS) - '\uf111', //  0x89 -> FUNCTION KEY 2 (CUS) - '\uf113', //  0x8A -> FUNCTION KEY 4 (CUS) - '\uf115', //  0x8B -> FUNCTION KEY 6 (CUS) - '\uf117', //  0x8C -> FUNCTION KEY 8 (CUS) - '\n' , // 0x8D -> LINE FEED - '\u000f', //  0x8E -> SHIFT IN - '\ufffe', // 0x8F -> UNDEFINED - '\uf105', // 0x90 -> BLACK COLOR SWITCH (CUS) - '\uf11e', //  0x91 -> CURSOR UP (CUS) - '\uf11b', //  0x92 -> REVERSE VIDEO OFF (CUS) - '\u000c', // 0x93 -> FORM FEED - '\uf121', //  0x94 -> INSERT (CUS) - '\uf106', // 0x95 -> BROWN COLOR SWITCH (CUS) - '\uf107', // 0x96 -> LIGHT RED COLOR SWITCH (CUS) - '\uf108', // 0x97 -> GRAY 1 COLOR SWITCH (CUS) - '\uf109', //  0x98 -> GRAY 2 COLOR SWITCH (CUS) - '\uf10a', //  0x99 -> LIGHT GREEN COLOR SWITCH (CUS) - '\uf10b', //  0x9A -> LIGHT BLUE COLOR SWITCH (CUS) - '\uf10c', //  0x9B -> GRAY 3 COLOR SWITCH (CUS) - '\uf10d', //  0x9C -> PURPLE COLOR SWITCH (CUS) - '\uf11d', //  0x9D -> CURSOR LEFT (CUS) - '\uf10e', //  0x9E -> YELLOW COLOR SWITCH (CUS) - '\uf10f', //  0x9F -> CYAN COLOR SWITCH (CUS) - '\u00a0', // 0xA0 -> NO-BREAK SPACE - '\u258c', // ▌ 0xA1 -> LEFT HALF BLOCK - '\u2584', // ▄ 0xA2 -> LOWER HALF BLOCK - '\u2594', // ▔ 0xA3 -> UPPER ONE EIGHTH BLOCK - '\u2581', // ▁ 0xA4 -> LOWER ONE EIGHTH BLOCK - '\u258f', // ▏ 0xA5 -> LEFT ONE EIGHTH BLOCK - '\u2592', // ▒ 0xA6 -> MEDIUM SHADE - '\u2595', // ▕ 0xA7 -> RIGHT ONE EIGHTH BLOCK - '\uf12f', //  0xA8 -> LOWER HALF BLOCK MEDIUM SHADE (CUS) - '\uf13a', //  0xA9 -> MEDIUM SHADE SLASHED RIGHT (CUS) - '\uf130', //  0xAA -> RIGHT ONE QUARTER BLOCK (CUS) - '\u251c', // ├ 0xAB -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT - '\u2597', // ▗ 0xAC -> QUADRANT LOWER RIGHT - '\u2514', // └ 0xAD -> BOX DRAWINGS LIGHT UP AND RIGHT - '\u2510', // ┐ 0xAE -> BOX DRAWINGS LIGHT DOWN AND LEFT - '\u2582', // ▂ 0xAF -> LOWER ONE QUARTER BLOCK - '\u250c', // ┌ 0xB0 -> BOX DRAWINGS LIGHT DOWN AND RIGHT - '\u2534', // ┴ 0xB1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL - '\u252c', // ┬ 0xB2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - '\u2524', // ┤ 0xB3 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT - '\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) - '\uf133', //  0xB8 -> UPPER THREE EIGHTS BLOCK (CUS) - '\u2583', // ▃ 0xB9 -> LOWER THREE EIGHTHS BLOCK - '\u2713', // ✓ 0xBA -> CHECK MARK - '\u2596', // ▖ 0xBB -> QUADRANT LOWER LEFT - '\u259d', // ▝ 0xBC -> QUADRANT UPPER RIGHT - '\u2518', // ┘ 0xBD -> BOX DRAWINGS LIGHT UP AND LEFT - '\u2598', // ▘ 0xBE -> QUADRANT UPPER LEFT - '\u259a', // ▚ 0xBF -> QUADRANT UPPER LEFT AND LOWER RIGHT - '\u2500', // ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL - 'A' , // A 0xC1 -> LATIN CAPITAL LETTER A - 'B' , // B 0xC2 -> LATIN CAPITAL LETTER B - 'C' , // C 0xC3 -> LATIN CAPITAL LETTER C - 'D' , // D 0xC4 -> LATIN CAPITAL LETTER D - 'E' , // E 0xC5 -> LATIN CAPITAL LETTER E - 'F' , // F 0xC6 -> LATIN CAPITAL LETTER F - 'G' , // G 0xC7 -> LATIN CAPITAL LETTER G - 'H' , // H 0xC8 -> LATIN CAPITAL LETTER H - 'I' , // I 0xC9 -> LATIN CAPITAL LETTER I - 'J' , // J 0xCA -> LATIN CAPITAL LETTER J - 'K' , // K 0xCB -> LATIN CAPITAL LETTER K - 'L' , // L 0xCC -> LATIN CAPITAL LETTER L - 'M' , // M 0xCD -> LATIN CAPITAL LETTER M - 'N' , // N 0xCE -> LATIN CAPITAL LETTER N - 'O' , // O 0xCF -> LATIN CAPITAL LETTER O - 'P' , // P 0xD0 -> LATIN CAPITAL LETTER P - 'Q' , // Q 0xD1 -> LATIN CAPITAL LETTER Q - 'R' , // R 0xD2 -> LATIN CAPITAL LETTER R - 'S' , // S 0xD3 -> LATIN CAPITAL LETTER S - 'T' , // T 0xD4 -> LATIN CAPITAL LETTER T - 'U' , // U 0xD5 -> LATIN CAPITAL LETTER U - 'V' , // V 0xD6 -> LATIN CAPITAL LETTER V - 'W' , // W 0xD7 -> LATIN CAPITAL LETTER W - 'X' , // X 0xD8 -> LATIN CAPITAL LETTER X - 'Y' , // Y 0xD9 -> LATIN CAPITAL LETTER Y - 'Z' , // Z 0xDA -> LATIN CAPITAL LETTER Z - '\u253c', // ┼ 0xDB -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - '\uf12e', //  0xDC -> LEFT HALF BLOCK MEDIUM SHADE (CUS) - '\u2502', // │ 0xDD -> BOX DRAWINGS LIGHT VERTICAL - '\u2592', // ▒ 0xDE -> MEDIUM SHADE - '\uf139', //  0xDF -> MEDIUM SHADE SLASHED LEFT (CUS) - '\u00a0', // 0xE0 -> NO-BREAK SPACE - '\u258c', // ▌ 0xE1 -> LEFT HALF BLOCK - '\u2584', // ▄ 0xE2 -> LOWER HALF BLOCK - '\u2594', // ▔ 0xE3 -> UPPER ONE EIGHTH BLOCK - '\u2581', // ▁ 0xE4 -> LOWER ONE EIGHTH BLOCK - '\u258f', // ▏ 0xE5 -> LEFT ONE EIGHTH BLOCK - '\u2592', // ▒ 0xE6 -> MEDIUM SHADE - '\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) - '\u251c', // ├ 0xEB -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT - '\u2597', // ▗ 0xEC -> QUADRANT LOWER RIGHT - '\u2514', // └ 0xED -> BOX DRAWINGS LIGHT UP AND RIGHT - '\u2510', // ┐ 0xEE -> BOX DRAWINGS LIGHT DOWN AND LEFT - '\u2582', // ▂ 0xEF -> LOWER ONE QUARTER BLOCK - '\u250c', // ┌ 0xF0 -> BOX DRAWINGS LIGHT DOWN AND RIGHT - '\u2534', // ┴ 0xF1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL - '\u252c', // ┬ 0xF2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - '\u2524', // ┤ 0xF3 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT - '\u258e', // ▎ 0xF4 -> LEFT ONE QUARTER BLOCK - '\u258d', // ▍ 0xF5 -> LEFT THREE EIGTHS BLOCK - '\uf131', //  0xF6 -> RIGHT THREE EIGHTHS BLOCK (CUS) - '\uf132', //  0xF7 -> UPPER ONE QUARTER BLOCK (CUS) - '\uf133', //  0xF8 -> UPPER THREE EIGHTS BLOCK (CUS) - '\u2583', // ▃ 0xF9 -> LOWER THREE EIGHTHS BLOCK - '\u2713', // ✓ 0xFA -> CHECK MARK - '\u2596', // ▖ 0xFB -> QUADRANT LOWER LEFT - '\u259d', // ▝ 0xFC -> QUADRANT UPPER RIGHT - '\u2518', // ┘ 0xFD -> BOX DRAWINGS LIGHT UP AND LEFT - '\u2598', // ▘ 0xFE -> QUADRANT UPPER LEFT - '\u2592' // ▒ 0xFF -> MEDIUM SHADE - ) - - private val decodingPetsciiUppercase = arrayOf( - '\u0000', // 0x00 -> \u0000 - '\ufffe', // 0x01 -> UNDEFINED - '\ufffe', // 0x02 -> UNDEFINED - '\ufffe', // 0x03 -> UNDEFINED - '\ufffe', // 0x04 -> UNDEFINED - '\uf100', // 0x05 -> WHITE COLOR SWITCH (CUS) - '\ufffe', // 0x06 -> UNDEFINED - '\ufffe', // 0x07 -> UNDEFINED - '\uf118', // 0x08 -> DISABLE CHARACTER SET SWITCHING (CUS) - '\uf119', // 0x09 -> ENABLE CHARACTER SET SWITCHING (CUS) - '\ufffe', // 0x0A -> UNDEFINED - '\ufffe', // 0x0B -> UNDEFINED - '\ufffe', // 0x0C -> UNDEFINED - '\r' , // 0x0D -> CARRIAGE RETURN - '\u000e', // 0x0E -> SHIFT OUT - '\ufffe', // 0x0F -> UNDEFINED - '\ufffe', // 0x10 -> UNDEFINED - '\uf11c', // 0x11 -> CURSOR DOWN (CUS) - '\uf11a', // 0x12 -> REVERSE VIDEO ON (CUS) - '\uf120', // 0x13 -> HOME (CUS) - '\u007f', // 0x14 -> DELETE - '\ufffe', // 0x15 -> UNDEFINED - '\ufffe', // 0x16 -> UNDEFINED - '\ufffe', // 0x17 -> UNDEFINED - '\ufffe', // 0x18 -> UNDEFINED - '\ufffe', // 0x19 -> UNDEFINED - '\ufffe', // 0x1A -> UNDEFINED - '\ufffe', // 0x1B -> UNDEFINED - '\uf101', // 0x1C -> RED COLOR SWITCH (CUS) - '\uf11d', // 0x1D -> CURSOR RIGHT (CUS) - '\uf102', // 0x1E -> GREEN COLOR SWITCH (CUS) - '\uf103', // 0x1F -> BLUE COLOR SWITCH (CUS) - ' ' , // 0x20 -> SPACE - '!' , // ! 0x21 -> EXCLAMATION MARK - '"' , // " 0x22 -> QUOTATION MARK - '#' , // # 0x23 -> NUMBER SIGN - '$' , // $ 0x24 -> DOLLAR SIGN - '%' , // % 0x25 -> PERCENT SIGN - '&' , // & 0x26 -> AMPERSAND - '\'' , // ' 0x27 -> APOSTROPHE - '(' , // ( 0x28 -> LEFT PARENTHESIS - ')' , // ) 0x29 -> RIGHT PARENTHESIS - '*' , // * 0x2A -> ASTERISK - '+' , // + 0x2B -> PLUS SIGN - ',' , // , 0x2C -> COMMA - '-' , // - 0x2D -> HYPHEN-MINUS - '.' , // . 0x2E -> FULL STOP - '/' , // / 0x2F -> SOLIDUS - '0' , // 0 0x30 -> DIGIT ZERO - '1' , // 1 0x31 -> DIGIT ONE - '2' , // 2 0x32 -> DIGIT TWO - '3' , // 3 0x33 -> DIGIT THREE - '4' , // 4 0x34 -> DIGIT FOUR - '5' , // 5 0x35 -> DIGIT FIVE - '6' , // 6 0x36 -> DIGIT SIX - '7' , // 7 0x37 -> DIGIT SEVEN - '8' , // 8 0x38 -> DIGIT EIGHT - '9' , // 9 0x39 -> DIGIT NINE - ':' , // : 0x3A -> COLON - ';' , // ; 0x3B -> SEMICOLON - '<' , // < 0x3C -> LESS-THAN SIGN - '=' , // = 0x3D -> EQUALS SIGN - '>' , // > 0x3E -> GREATER-THAN SIGN - '?' , // ? 0x3F -> QUESTION MARK - '@' , // @ 0x40 -> COMMERCIAL AT - 'A' , // A 0x41 -> LATIN CAPITAL LETTER A - 'B' , // B 0x42 -> LATIN CAPITAL LETTER B - 'C' , // C 0x43 -> LATIN CAPITAL LETTER C - 'D' , // D 0x44 -> LATIN CAPITAL LETTER D - 'E' , // E 0x45 -> LATIN CAPITAL LETTER E - 'F' , // F 0x46 -> LATIN CAPITAL LETTER F - 'G' , // G 0x47 -> LATIN CAPITAL LETTER G - 'H' , // H 0x48 -> LATIN CAPITAL LETTER H - 'I' , // I 0x49 -> LATIN CAPITAL LETTER I - 'J' , // J 0x4A -> LATIN CAPITAL LETTER J - 'K' , // K 0x4B -> LATIN CAPITAL LETTER K - 'L' , // L 0x4C -> LATIN CAPITAL LETTER L - 'M' , // M 0x4D -> LATIN CAPITAL LETTER M - 'N' , // N 0x4E -> LATIN CAPITAL LETTER N - 'O' , // O 0x4F -> LATIN CAPITAL LETTER O - 'P' , // P 0x50 -> LATIN CAPITAL LETTER P - 'Q' , // Q 0x51 -> LATIN CAPITAL LETTER Q - 'R' , // R 0x52 -> LATIN CAPITAL LETTER R - 'S' , // S 0x53 -> LATIN CAPITAL LETTER S - 'T' , // T 0x54 -> LATIN CAPITAL LETTER T - 'U' , // U 0x55 -> LATIN CAPITAL LETTER U - 'V' , // V 0x56 -> LATIN CAPITAL LETTER V - 'W' , // W 0x57 -> LATIN CAPITAL LETTER W - 'X' , // X 0x58 -> LATIN CAPITAL LETTER X - 'Y' , // Y 0x59 -> LATIN CAPITAL LETTER Y - 'Z' , // Z 0x5A -> LATIN CAPITAL LETTER Z - '[' , // [ 0x5B -> LEFT SQUARE BRACKET - '\u00a3', // £ 0x5C -> POUND SIGN - ']' , // ] 0x5D -> RIGHT SQUARE BRACKET - '\u2191', // ↑ 0x5E -> UPWARDS ARROW - '\u2190', // ← 0x5F -> LEFTWARDS ARROW - '\u2500', // ─ 0x60 -> BOX DRAWINGS LIGHT HORIZONTAL - '\u2660', // ♠ 0x61 -> BLACK SPADE SUIT - '\u2502', // │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL - '\u2500', // ─ 0x63 -> BOX DRAWINGS LIGHT HORIZONTAL - '\uf122', //  0x64 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER UP (CUS) - '\uf123', //  0x65 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS UP (CUS) - '\uf124', //  0x66 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER DOWN (CUS) - '\uf126', //  0x67 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER LEFT (CUS) - '\uf128', //  0x68 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER RIGHT (CUS) - '\u256e', // ╮ 0x69 -> BOX DRAWINGS LIGHT ARC DOWN AND LEFT - '\u2570', // ╰ 0x6A -> BOX DRAWINGS LIGHT ARC UP AND RIGHT - '\u256f', // ╯ 0x6B -> BOX DRAWINGS LIGHT ARC UP AND LEFT - '\uf12a', //  0x6C -> ONE EIGHTH BLOCK UP AND RIGHT (CUS) - '\u2572', // ╲ 0x6D -> BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT - '\u2571', // ╱ 0x6E -> BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT - '\uf12b', //  0x6F -> ONE EIGHTH BLOCK DOWN AND RIGHT (CUS) - '\uf12c', //  0x70 -> ONE EIGHTH BLOCK DOWN AND LEFT (CUS) - '\u25cf', // ● 0x71 -> BLACK CIRCLE - '\uf125', //  0x72 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS DOWN (CUS) - '\u2665', // ♥ 0x73 -> BLACK HEART SUIT - '\uf127', //  0x74 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS LEFT (CUS) - '\u256d', // ╭ 0x75 -> BOX DRAWINGS LIGHT ARC DOWN AND RIGHT - '\u2573', // ╳ 0x76 -> BOX DRAWINGS LIGHT DIAGONAL CROSS - '\u25cb', // ○ 0x77 -> WHITE CIRCLE - '\u2663', // ♣ 0x78 -> BLACK CLUB SUIT - '\uf129', //  0x79 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS RIGHT (CUS) - '\u2666', // ♦ 0x7A -> BLACK DIAMOND SUIT - '\u253c', // ┼ 0x7B -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - '\uf12e', //  0x7C -> LEFT HALF BLOCK MEDIUM SHADE (CUS) - '\u2502', // │ 0x7D -> BOX DRAWINGS LIGHT VERTICAL - '\u03c0', // π 0x7E -> GREEK SMALL LETTER PI - '\u25e5', // ◥ 0x7F -> BLACK UPPER RIGHT TRIANGLE - '\ufffe', // 0x80 -> UNDEFINED - '\uf104', //  0x81 -> ORANGE COLOR SWITCH (CUS) - '\ufffe', // 0x82 -> UNDEFINED - '\ufffe', // 0x83 -> UNDEFINED - '\ufffe', // 0x84 -> UNDEFINED - '\uf110', // 0x85 -> FUNCTION KEY 1 (CUS) - '\uf112', // 0x86 -> FUNCTION KEY 3 (CUS) - '\uf114', // 0x87 -> FUNCTION KEY 5 (CUS) - '\uf116', // 0x88 -> FUNCTION KEY 7 (CUS) - '\uf111', // 0x89 -> FUNCTION KEY 2 (CUS) - '\uf113', // 0x8A -> FUNCTION KEY 4 (CUS) - '\uf115', // 0x8B -> FUNCTION KEY 6 (CUS) - '\uf117', // 0x8C -> FUNCTION KEY 8 (CUS) - '\n' , // 0x8D -> LINE FEED - '\u000f', // 0x8E -> SHIFT IN - '\ufffe', // 0x8F -> UNDEFINED - '\uf105', // 0x90 -> BLACK COLOR SWITCH (CUS) - '\uf11e', // 0x91 -> CURSOR UP (CUS) - '\uf11b', // 0x92 -> REVERSE VIDEO OFF (CUS) - '\u000c', // 0x93 -> FORM FEED - '\uf121', // 0x94 -> INSERT (CUS) - '\uf106', // 0x95 -> BROWN COLOR SWITCH (CUS) - '\uf107', // 0x96 -> LIGHT RED COLOR SWITCH (CUS) - '\uf108', // 0x97 -> GRAY 1 COLOR SWITCH (CUS) - '\uf109', // 0x98 -> GRAY 2 COLOR SWITCH (CUS) - '\uf10a', // 0x99 -> LIGHT GREEN COLOR SWITCH (CUS) - '\uf10b', // 0x9A -> LIGHT BLUE COLOR SWITCH (CUS) - '\uf10c', // 0x9B -> GRAY 3 COLOR SWITCH (CUS) - '\uf10d', // 0x9C -> PURPLE COLOR SWITCH (CUS) - '\uf11d', // 0x9D -> CURSOR LEFT (CUS) - '\uf10e', // 0x9E -> YELLOW COLOR SWITCH (CUS) - '\uf10f', // 0x9F -> CYAN COLOR SWITCH (CUS) - '\u00a0', // 0xA0 -> NO-BREAK SPACE - '\u258c', // ▌ 0xA1 -> LEFT HALF BLOCK - '\u2584', // ▄ 0xA2 -> LOWER HALF BLOCK - '\u2594', // ▔ 0xA3 -> UPPER ONE EIGHTH BLOCK - '\u2581', // ▁ 0xA4 -> LOWER ONE EIGHTH BLOCK - '\u258f', // ▏ 0xA5 -> LEFT ONE EIGHTH BLOCK - '\u2592', // ▒ 0xA6 -> MEDIUM SHADE - '\u2595', // ▕ 0xA7 -> RIGHT ONE EIGHTH BLOCK - '\uf12f', //  0xA8 -> LOWER HALF BLOCK MEDIUM SHADE (CUS) - '\u25e4', // ◤ 0xA9 -> BLACK UPPER LEFT TRIANGLE - '\uf130', //  0xAA -> RIGHT ONE QUARTER BLOCK (CUS) - '\u251c', // ├ 0xAB -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT - '\u2597', // ▗ 0xAC -> QUADRANT LOWER RIGHT - '\u2514', // └ 0xAD -> BOX DRAWINGS LIGHT UP AND RIGHT - '\u2510', // ┐ 0xAE -> BOX DRAWINGS LIGHT DOWN AND LEFT - '\u2582', // ▂ 0xAF -> LOWER ONE QUARTER BLOCK - '\u250c', // ┌ 0xB0 -> BOX DRAWINGS LIGHT DOWN AND RIGHT - '\u2534', // ┴ 0xB1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL - '\u252c', // ┬ 0xB2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - '\u2524', // ┤ 0xB3 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT - '\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) - '\uf133', //  0xB8 -> UPPER THREE EIGHTS BLOCK (CUS) - '\u2583', // ▃ 0xB9 -> LOWER THREE EIGHTHS BLOCK - '\uf12d', //  0xBA -> ONE EIGHTH BLOCK UP AND LEFT (CUS) - '\u2596', // ▖ 0xBB -> QUADRANT LOWER LEFT - '\u259d', // ▝ 0xBC -> QUADRANT UPPER RIGHT - '\u2518', // ┘ 0xBD -> BOX DRAWINGS LIGHT UP AND LEFT - '\u2598', // ▘ 0xBE -> QUADRANT UPPER LEFT - '\u259a', // ▚ 0xBF -> QUADRANT UPPER LEFT AND LOWER RIGHT - '\u2500', // ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL - '\u2660', // ♠ 0xC1 -> BLACK SPADE SUIT - '\u2502', // │ 0xC2 -> BOX DRAWINGS LIGHT VERTICAL - '\u2500', // ─ 0xC3 -> BOX DRAWINGS LIGHT HORIZONTAL - '\uf122', //  0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER UP (CUS) - '\uf123', //  0xC5 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS UP (CUS) - '\uf124', //  0xC6 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER DOWN (CUS) - '\uf126', //  0xC7 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER LEFT (CUS) - '\uf128', //  0xC8 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER RIGHT (CUS) - '\u256e', // ╮ 0xC9 -> BOX DRAWINGS LIGHT ARC DOWN AND LEFT - '\u2570', // ╰ 0xCA -> BOX DRAWINGS LIGHT ARC UP AND RIGHT - '\u256f', // ╯ 0xCB -> BOX DRAWINGS LIGHT ARC UP AND LEFT - '\uf12a', //  0xCC -> ONE EIGHTH BLOCK UP AND RIGHT (CUS) - '\u2572', // ╲ 0xCD -> BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT - '\u2571', // ╱ 0xCE -> BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT - '\uf12b', //  0xCF -> ONE EIGHTH BLOCK DOWN AND RIGHT (CUS) - '\uf12c', //  0xD0 -> ONE EIGHTH BLOCK DOWN AND LEFT (CUS) - '\u25cf', // ● 0xD1 -> BLACK CIRCLE - '\uf125', //  0xD2 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS DOWN (CUS) - '\u2665', // ♥ 0xD3 -> BLACK HEART SUIT - '\uf127', //  0xD4 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS LEFT (CUS) - '\u256d', // ╭ 0xD5 -> BOX DRAWINGS LIGHT ARC DOWN AND LEFT - '\u2573', // ╳ 0xD6 -> BOX DRAWINGS LIGHT DIAGONAL CROSS - '\u25cb', // ○ 0xD7 -> WHITE CIRCLE - '\u2663', // ♣ 0xD8 -> BLACK CLUB SUIT - '\uf129', //  0xD9 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS RIGHT (CUS) - '\u2666', // ♦ 0xDA -> BLACK DIAMOND SUIT - '\u253c', // ┼ 0xDB -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - '\uf12e', //  0xDC -> LEFT HALF BLOCK MEDIUM SHADE (CUS) - '\u2502', // │ 0xDD -> BOX DRAWINGS LIGHT VERTICAL - '\u03c0', // π 0xDE -> GREEK SMALL LETTER PI - '\u25e5', // ◥ 0xDF -> BLACK UPPER RIGHT TRIANGLE - '\u00a0', // 0xE0 -> NO-BREAK SPACE - '\u258c', // ▌ 0xE1 -> LEFT HALF BLOCK - '\u2584', // ▄ 0xE2 -> LOWER HALF BLOCK - '\u2594', // ▔ 0xE3 -> UPPER ONE EIGHTH BLOCK - '\u2581', // ▁ 0xE4 -> LOWER ONE EIGHTH BLOCK - '\u258f', // ▏ 0xE5 -> LEFT ONE EIGHTH BLOCK - '\u2592', // ▒ 0xE6 -> MEDIUM SHADE - '\u2595', // ▕ 0xE7 -> RIGHT ONE EIGHTH BLOCK - '\uf12f', //  0xE8 -> LOWER HALF BLOCK MEDIUM SHADE (CUS) - '\u25e4', // ◤ 0xE9 -> BLACK UPPER LEFT TRIANGLE - '\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 - '\u2510', // ┐ 0xEE -> BOX DRAWINGS LIGHT DOWN AND LEFT - '\u2582', // ▂ 0xEF -> LOWER ONE QUARTER BLOCK - '\u250c', // ┌ 0xF0 -> BOX DRAWINGS LIGHT DOWN AND RIGHT - '\u2534', // ┴ 0xF1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL - '\u252c', // ┬ 0xF2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - '\u2524', // ┤ 0xF3 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT - '\u258e', // ▎ 0xF4 -> LEFT ONE QUARTER BLOCK - '\u258d', // ▍ 0xF5 -> LEFT THREE EIGTHS BLOCK - '\uf131', //  0xF6 -> RIGHT THREE EIGHTHS BLOCK (CUS) - '\uf132', //  0xF7 -> UPPER ONE QUARTER BLOCK (CUS) - '\uf133', //  0xF8 -> UPPER THREE EIGHTS BLOCK (CUS) - '\u2583', // ▃ 0xF9 -> LOWER THREE EIGHTHS BLOCK - '\uf12d', //  0xFA -> ONE EIGHTH BLOCK UP AND LEFT (CUS) - '\u2596', // ▖ 0xFB -> QUADRANT LOWER LEFT - '\u259d', // ▝ 0xFC -> QUADRANT UPPER RIGHT - '\u2518', // ┘ 0xFD -> BOX DRAWINGS LIGHT UP AND LEFT - '\u2598', // ▘ 0xFE -> QUADRANT UPPER LEFT - '\u03c0' // π 0xFF -> GREEK SMALL LETTER PI - ) - - // encoding: from unicode to Petscii/Screencodes (0-255) - private val encodingPetsciiLowercase = decodingPetsciiLowercase.withIndex().associate{it.value to it.index} - private val encodingPetsciiUppercase = decodingPetsciiUppercase.withIndex().associate{it.value to it.index} - - - fun encodePetscii(text: String, lowercase: Boolean = false): List { - val lookup = if(lowercase) encodingPetsciiLowercase else encodingPetsciiUppercase - return text.map { - val petscii = lookup[it] - petscii?.toShort() ?: if(it=='\u0000') - 0.toShort() - else { - val case = if (lowercase) "lower" else "upper" - throw CharConversionException("no ${case}case Petscii character for '$it'") - } - } - } -} diff --git a/src/main/kotlin/razorvine/c64emu/c64Main.kt b/src/main/kotlin/razorvine/c64emu/c64Main.kt index 2d508a7..61cea8a 100644 --- a/src/main/kotlin/razorvine/c64emu/c64Main.kt +++ b/src/main/kotlin/razorvine/c64emu/c64Main.kt @@ -28,11 +28,11 @@ class C64Machine(title: String) : IVirtualMachine { val cia2 = Cia(2, 0xdd00, 0xddff) val basicRom = Rom(0xa000, 0xbfff).also { it.load(basicData) } val kernalRom = Rom(0xe000, 0xffff).also { it.load(kernalData) } - // TODO: implement the two CIAs to add timer and joystick support, and the keyboard matrix. - // TODO: implement something so that RND(0) actually works in basic. + // TODO: implement the two CIAs to add timer and joystick support. + // TODO: implement something so that RND(0) actually works in basic. (cia timer?) private val debugWindow = DebugWindow(this) - private val hostDisplay = MainC64Window(title, chargenData, ram) + private val hostDisplay = MainC64Window(title, chargenData, ram, cia1) private var paused = false init {