mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
beginnings of 6502 cpu simulator
This commit is contained in:
parent
39798a1a4f
commit
8d6542905d
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@ -7,6 +7,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/parser/parser.iml" filepath="$PROJECT_DIR$/parser/parser.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/sim65/sim65.iml" filepath="$PROJECT_DIR$/sim65/sim65.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -8,7 +8,6 @@ import prog8.parser.ParsingFailedError
|
||||
import prog8.vm.astvm.AstVm
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardWatchEventKinds
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
228
examples/arithmetic/bcd.asm
Normal file
228
examples/arithmetic/bcd.asm
Normal file
@ -0,0 +1,228 @@
|
||||
;===========================================================================
|
||||
;
|
||||
; Based on: Bruce Clark: a program to verify decimal mode operation
|
||||
; www.6502.org/tutorials/decimal_mode.html
|
||||
;
|
||||
; NMOS 6502\6510: program for testing accumulator result and flag result
|
||||
; of ADC and SBC in decimal mode,
|
||||
; including correct incorrectness of NVZ flags.
|
||||
;
|
||||
;...........................................................................
|
||||
;
|
||||
; ttlworks 04/2016: modified the code for testing the 6510 in a C64.
|
||||
;
|
||||
;===========================================================================
|
||||
|
||||
ERROR = $0400 ; 0='test passed', 1='test failed'
|
||||
N1 = $0401 ; first number to be added/subtrected
|
||||
N2 = $0402 ; second number to be added/subtrected
|
||||
|
||||
N1L = $00F7 ; Bit 3..0 of first number
|
||||
N1H = $00F8 ; Bit 7..4 of first number
|
||||
N2L = $00F9 ; Bit 3..0 of second number
|
||||
N2H = $00FA ; Bit 7..4 of second number
|
||||
N2HH = N2H+1 ; Bit 7..4 of second number OR $0F
|
||||
|
||||
AR = $00FC ; predicted ACC result in decimal mode
|
||||
DA = $00FD ; actual ACC result in decimal mode
|
||||
HNVZC = $00FE ; predicted flag result in decimal mode
|
||||
DNVZC = $00FF ; actual flag result in decimal mode
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
|
||||
.CPU "6502"
|
||||
* = $1000
|
||||
|
||||
TEST LDY #1 ; initialize Y (used to loop through carry flag values)
|
||||
STY ERROR ; store 1 in ERROR until the test passes
|
||||
|
||||
LDA #0 ; initialize N1 and N2
|
||||
STA N1
|
||||
STA N2
|
||||
|
||||
LOOP1 LDA N2 ; N2L = N2 & #$0F
|
||||
TAX
|
||||
AND #$0F
|
||||
STA N2L
|
||||
|
||||
TXA ; N2H = N2 & #$F0
|
||||
AND #$F0
|
||||
STA N2H
|
||||
ORA #$0F ; N2HH = (N2 & #$F0) OR #$0F
|
||||
STA N2HH
|
||||
|
||||
LOOP2 LDA N1
|
||||
TAX
|
||||
AND #$0F
|
||||
STA N1L
|
||||
|
||||
TXA
|
||||
AND #$F0
|
||||
STA N1H
|
||||
|
||||
JSR ADD
|
||||
BNE DONE
|
||||
|
||||
JSR SUB
|
||||
BNE DONE
|
||||
|
||||
INC N1
|
||||
BNE LOOP2 ; loop through all 256 values of N1
|
||||
|
||||
INC N2
|
||||
BNE LOOP1 ; loop through all 256 values of N2
|
||||
|
||||
DEY
|
||||
BPL LOOP1 ; loop through both values of the C_Flag
|
||||
|
||||
LDA #0 ; test passed, so store 0 in ERROR
|
||||
STA ERROR
|
||||
|
||||
DONE RTS
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
;
|
||||
; N1 + N2
|
||||
;
|
||||
; calculate the actual decimal mode accumulator and flag results,
|
||||
; calculate the actual binary mode accumulator and flag results
|
||||
;
|
||||
; calculate the predicted decimal mode accumulator and flag results
|
||||
; by using binary arithmetic
|
||||
;
|
||||
ADD ; actual decimal
|
||||
|
||||
SED ; decimal mode
|
||||
CPY #1 ; set carry if Y=1, clear carry if Y=0
|
||||
LDA N1
|
||||
ADC N2
|
||||
STA DA ; actual accumulator result in decimal mode
|
||||
PHP
|
||||
PLA
|
||||
STA DNVZC ; actual flag result in decimal mode
|
||||
CLD ; binary mode
|
||||
|
||||
; predicted decimal
|
||||
|
||||
CPY #1 ; set carry if Y=1, clear carry if Y=0
|
||||
LDA N1L
|
||||
ADC N2L
|
||||
CMP #$0A
|
||||
AND #$0F
|
||||
PHA
|
||||
LDX #0
|
||||
STX HNVZC
|
||||
BCC A1
|
||||
|
||||
INX
|
||||
ADC #5 ; add 6 (carry is set)
|
||||
AND #$0F
|
||||
SEC
|
||||
|
||||
A1 ORA N1H
|
||||
;
|
||||
; if N1L + N2L < $0A, then add N2 AND $F0
|
||||
; if N1L + N2L >= $0A, then add (N2 AND $F0) + $0F +1 (carry is set)
|
||||
;
|
||||
ADC N2H,X
|
||||
BCS A2
|
||||
CMP #$A0
|
||||
BCC A3
|
||||
|
||||
A2 ADC #$5F ; add #$60 (carry is set)
|
||||
SEC
|
||||
|
||||
A3 STA AR ; predicted decimal mode accumulator result
|
||||
ROL HNVZC ; predicted decimal mode C_Flag
|
||||
|
||||
CPX #1
|
||||
PLA ; evaluate NVZ
|
||||
ORA N1H
|
||||
ADC N2H,X
|
||||
|
||||
JMP EV1 ; evaluate/compare
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
;
|
||||
; N1 - N2
|
||||
;
|
||||
; calculate the actual decimal mode accumulator and flag results,
|
||||
; calculate the actual binary mode accumulator and flag results
|
||||
;
|
||||
;
|
||||
; calculate the predicted decimal mode accumulator and flag results
|
||||
; by using binary arithmetic
|
||||
|
||||
SUB ; actual decimal
|
||||
|
||||
SED ; decimal mode
|
||||
CPY #1 ; set carry if Y=1, clear carry if Y=0
|
||||
LDA N1
|
||||
SBC N2
|
||||
STA DA ; actual accumulator result in decimal mode
|
||||
PHP
|
||||
PLA
|
||||
STA DNVZC ; actual flag result in decimal mode
|
||||
CLD ; binary mode
|
||||
|
||||
; predicted decimal
|
||||
|
||||
SUB1 CPY #1 ; set carry if Y=1, clear carry if Y=0
|
||||
LDA N1L
|
||||
SBC N2L
|
||||
AND #$0F
|
||||
LDX #0
|
||||
STX HNVZC
|
||||
PHA
|
||||
PHP
|
||||
BCS S11
|
||||
|
||||
INX
|
||||
SBC #5 ; subtract 6 (carry is clear)
|
||||
AND #$0F
|
||||
CLC
|
||||
|
||||
S11 ORA N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 AND $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 AND $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
SBC N2H,X
|
||||
BCS S12
|
||||
SBC #$5F ; subtract #$60 (carry is clear)
|
||||
CLC
|
||||
|
||||
S12 STA AR
|
||||
ROL HNVZC
|
||||
|
||||
PLP ; evaluate NVZ
|
||||
PLA
|
||||
ORA N1H
|
||||
SBC N2H,X
|
||||
|
||||
EV1 PHP
|
||||
PLA
|
||||
AND #$C2
|
||||
ORA HNVZC
|
||||
STA HNVZC
|
||||
|
||||
;..........................................................................
|
||||
;compare actual results to predicted results
|
||||
;
|
||||
; Return: Z_Flag = 1 (BEQ branch) if same
|
||||
; Z_Flag = 0 (BNE branch) if different
|
||||
|
||||
COMPARE
|
||||
|
||||
; LDA HNVZC
|
||||
EOR DNVZC
|
||||
AND #$C3
|
||||
BNE C1
|
||||
|
||||
LDA AR ; accumulator
|
||||
CMP DA
|
||||
|
||||
C1 RTS
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ':parser'
|
||||
include ':compiler'
|
||||
include ':compiler'
|
||||
include ':sim65'
|
||||
|
108
sim65/build.gradle
Normal file
108
sim65/build.gradle
Normal file
@ -0,0 +1,108 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
// id "org.jetbrains.kotlin.jvm" version $kotlinVersion
|
||||
id 'application'
|
||||
id 'org.jetbrains.dokka' version "0.9.18"
|
||||
id 'com.github.johnrengelman.shadow' version '5.1.0'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
apply plugin: "kotlin"
|
||||
apply plugin: "java"
|
||||
|
||||
targetCompatibility = 1.8
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url "https://dl.bintray.com/orangy/maven/" }
|
||||
}
|
||||
|
||||
def sim65version = rootProject.file('sim65/res/version.txt').text.trim()
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||
// implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||
// runtime "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2'
|
||||
testImplementation 'org.hamcrest:hamcrest-junit:2.0.0.0'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.2'
|
||||
compile 'org.jetbrains.kotlinx:kotlinx-cli-jvm:0.1.0-dev-5'
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
// verbose = true
|
||||
// freeCompilerArgs += "-XXLanguage:+NewInference"
|
||||
}
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs = ["${project.projectDir}/src"]
|
||||
}
|
||||
resources {
|
||||
srcDirs = ["${project.projectDir}/res"]
|
||||
}
|
||||
}
|
||||
test {
|
||||
java {
|
||||
srcDirs = ["${project.projectDir}/test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startScripts.enabled = true
|
||||
|
||||
application {
|
||||
mainClassName = 'sim65.Sim65MainKt'
|
||||
applicationName = 'sim65'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives shadowJar
|
||||
}
|
||||
|
||||
|
||||
shadowJar {
|
||||
baseName = 'sim65'
|
||||
version = sim65version
|
||||
// minimize()
|
||||
}
|
||||
|
||||
|
||||
test {
|
||||
// Enable JUnit 5 (Gradle 4.6+).
|
||||
useJUnitPlatform()
|
||||
|
||||
// Always run tests, even when nothing changed.
|
||||
dependsOn 'cleanTest'
|
||||
|
||||
// Show test results.
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dokka {
|
||||
outputFormat = 'html'
|
||||
outputDirectory = "$buildDir/kdoc"
|
||||
}
|
1
sim65/res/version.txt
Normal file
1
sim65/res/version.txt
Normal file
@ -0,0 +1 @@
|
||||
0.1
|
24
sim65/sim65.iml
Normal file
24
sim65/sim65.iml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="3" platform="JVM 1.8" allPlatforms="JVM [1.8]" useProjectSettings="false">
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-cli-jvm-0.1.0-dev-5" level="project" />
|
||||
</component>
|
||||
</module>
|
550
sim65/src/C64Screencodes.kt
Normal file
550
sim65/src/C64Screencodes.kt
Normal file
@ -0,0 +1,550 @@
|
||||
package sim65
|
||||
|
||||
import java.io.CharConversionException
|
||||
|
||||
object C64Screencodes {
|
||||
|
||||
// decoding: from Screencodes (0-255) to unicode
|
||||
// character tables used from https://github.com/dj51d/cbmcodecs
|
||||
|
||||
private val decodingScreencodeLowercase = arrayOf(
|
||||
'@' , // @ 0x00 -> COMMERCIAL AT
|
||||
'a' , // a 0x01 -> LATIN SMALL LETTER A
|
||||
'b' , // b 0x02 -> LATIN SMALL LETTER B
|
||||
'c' , // c 0x03 -> LATIN SMALL LETTER C
|
||||
'd' , // d 0x04 -> LATIN SMALL LETTER D
|
||||
'e' , // e 0x05 -> LATIN SMALL LETTER E
|
||||
'f' , // f 0x06 -> LATIN SMALL LETTER F
|
||||
'g' , // g 0x07 -> LATIN SMALL LETTER G
|
||||
'h' , // h 0x08 -> LATIN SMALL LETTER H
|
||||
'i' , // i 0x09 -> LATIN SMALL LETTER I
|
||||
'j' , // j 0x0A -> LATIN SMALL LETTER J
|
||||
'k' , // k 0x0B -> LATIN SMALL LETTER K
|
||||
'l' , // l 0x0C -> LATIN SMALL LETTER L
|
||||
'm' , // m 0x0D -> LATIN SMALL LETTER M
|
||||
'n' , // n 0x0E -> LATIN SMALL LETTER N
|
||||
'o' , // o 0x0F -> LATIN SMALL LETTER O
|
||||
'p' , // p 0x10 -> LATIN SMALL LETTER P
|
||||
'q' , // q 0x11 -> LATIN SMALL LETTER Q
|
||||
'r' , // r 0x12 -> LATIN SMALL LETTER R
|
||||
's' , // s 0x13 -> LATIN SMALL LETTER S
|
||||
't' , // t 0x14 -> LATIN SMALL LETTER T
|
||||
'u' , // u 0x15 -> LATIN SMALL LETTER U
|
||||
'v' , // v 0x16 -> LATIN SMALL LETTER V
|
||||
'w' , // w 0x17 -> LATIN SMALL LETTER W
|
||||
'x' , // x 0x18 -> LATIN SMALL LETTER X
|
||||
'y' , // y 0x19 -> LATIN SMALL LETTER Y
|
||||
'z' , // z 0x1A -> LATIN SMALL LETTER Z
|
||||
'[' , // [ 0x1B -> LEFT SQUARE BRACKET
|
||||
'\u00a3', // £ 0x1C -> POUND SIGN
|
||||
']' , // ] 0x1D -> RIGHT SQUARE BRACKET
|
||||
'\u2191', // ↑ 0x1E -> UPWARDS ARROW
|
||||
'\u2190', // ← 0x1F -> LEFTWARDS ARROW
|
||||
' ' , // 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
|
||||
'\u2500', // ─ 0x40 -> BOX DRAWINGS LIGHT HORIZONTAL
|
||||
'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
|
||||
'\u253c', // ┼ 0x5B -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
|
||||
'\uf12e', // 0x5C -> LEFT HALF BLOCK MEDIUM SHADE (CUS)
|
||||
'\u2502', // │ 0x5D -> BOX DRAWINGS LIGHT VERTICAL
|
||||
'\u2592', // ▒ 0x5E -> MEDIUM SHADE
|
||||
'\uf139', // 0x5F -> MEDIUM SHADE SLASHED LEFT (CUS)
|
||||
'\u00a0', // 0x60 -> NO-BREAK SPACE
|
||||
'\u258c', // ▌ 0x61 -> LEFT HALF BLOCK
|
||||
'\u2584', // ▄ 0x62 -> LOWER HALF BLOCK
|
||||
'\u2594', // ▔ 0x63 -> UPPER ONE EIGHTH BLOCK
|
||||
'\u2581', // ▁ 0x64 -> LOWER ONE EIGHTH BLOCK
|
||||
'\u258f', // ▏ 0x65 -> LEFT ONE EIGHTH BLOCK
|
||||
'\u2592', // ▒ 0x66 -> MEDIUM SHADE
|
||||
'\u2595', // ▕ 0x67 -> RIGHT ONE EIGHTH BLOCK
|
||||
'\uf12f', // 0x68 -> LOWER HALF BLOCK MEDIUM SHADE (CUS)
|
||||
'\uf13a', // 0x69 -> MEDIUM SHADE SLASHED RIGHT (CUS)
|
||||
'\uf130', // 0x6A -> RIGHT ONE QUARTER BLOCK (CUS)
|
||||
'\u251c', // ├ 0x6B -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||
'\u2597', // ▗ 0x6C -> QUADRANT LOWER RIGHT
|
||||
'\u2514', // └ 0x6D -> BOX DRAWINGS LIGHT UP AND RIGHT
|
||||
'\u2510', // ┐ 0x6E -> BOX DRAWINGS LIGHT DOWN AND LEFT
|
||||
'\u2582', // ▂ 0x6F -> LOWER ONE QUARTER BLOCK
|
||||
'\u250c', // ┌ 0x70 -> BOX DRAWINGS LIGHT DOWN AND RIGHT
|
||||
'\u2534', // ┴ 0x71 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||
'\u252c', // ┬ 0x72 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||
'\u2524', // ┤ 0x73 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||
'\u258e', // ▎ 0x74 -> LEFT ONE QUARTER BLOCK
|
||||
'\u258d', // ▍ 0x75 -> LEFT THREE EIGTHS BLOCK
|
||||
'\uf131', // 0x76 -> RIGHT THREE EIGHTHS BLOCK (CUS)
|
||||
'\uf132', // 0x77 -> UPPER ONE QUARTER BLOCK (CUS)
|
||||
'\uf133', // 0x78 -> UPPER THREE EIGHTS BLOCK (CUS)
|
||||
'\u2583', // ▃ 0x79 -> LOWER THREE EIGHTHS BLOCK
|
||||
'\u2713', // ✓ 0x7A -> CHECK MARK
|
||||
'\u2596', // ▖ 0x7B -> QUADRANT LOWER LEFT
|
||||
'\u259d', // ▝ 0x7C -> QUADRANT UPPER RIGHT
|
||||
'\u2518', // ┘ 0x7D -> BOX DRAWINGS LIGHT UP AND LEFT
|
||||
'\u2598', // ▘ 0x7E -> QUADRANT UPPER LEFT
|
||||
'\u259a', // ▚ 0x7F -> QUADRANT UPPER LEFT AND LOWER RIGHT
|
||||
'\ufffe', // 0x80 -> UNDEFINED
|
||||
'\ufffe', // 0x81 -> UNDEFINED
|
||||
'\ufffe', // 0x82 -> UNDEFINED
|
||||
'\ufffe', // 0x83 -> UNDEFINED
|
||||
'\ufffe', // 0x84 -> UNDEFINED
|
||||
'\ufffe', // 0x85 -> UNDEFINED
|
||||
'\ufffe', // 0x86 -> UNDEFINED
|
||||
'\ufffe', // 0x87 -> UNDEFINED
|
||||
'\ufffe', // 0x88 -> UNDEFINED
|
||||
'\ufffe', // 0x89 -> UNDEFINED
|
||||
'\ufffe', // 0x8A -> UNDEFINED
|
||||
'\ufffe', // 0x8B -> UNDEFINED
|
||||
'\ufffe', // 0x8C -> UNDEFINED
|
||||
'\ufffe', // 0x8D -> UNDEFINED
|
||||
'\ufffe', // 0x8E -> UNDEFINED
|
||||
'\ufffe', // 0x8F -> UNDEFINED
|
||||
'\ufffe', // 0x90 -> UNDEFINED
|
||||
'\ufffe', // 0x91 -> UNDEFINED
|
||||
'\ufffe', // 0x92 -> UNDEFINED
|
||||
'\ufffe', // 0x93 -> UNDEFINED
|
||||
'\ufffe', // 0x94 -> UNDEFINED
|
||||
'\ufffe', // 0x95 -> UNDEFINED
|
||||
'\ufffe', // 0x96 -> UNDEFINED
|
||||
'\ufffe', // 0x97 -> UNDEFINED
|
||||
'\ufffe', // 0x98 -> UNDEFINED
|
||||
'\ufffe', // 0x99 -> UNDEFINED
|
||||
'\ufffe', // 0x9A -> UNDEFINED
|
||||
'\ufffe', // 0x9B -> UNDEFINED
|
||||
'\ufffe', // 0x9C -> UNDEFINED
|
||||
'\ufffe', // 0x9D -> UNDEFINED
|
||||
'\ufffe', // 0x9E -> UNDEFINED
|
||||
'\ufffe', // 0x9F -> UNDEFINED
|
||||
'\ufffe', // 0xA0 -> UNDEFINED
|
||||
'\ufffe', // 0xA1 -> UNDEFINED
|
||||
'\ufffe', // 0xA2 -> UNDEFINED
|
||||
'\ufffe', // 0xA3 -> UNDEFINED
|
||||
'\ufffe', // 0xA4 -> UNDEFINED
|
||||
'\ufffe', // 0xA5 -> UNDEFINED
|
||||
'\ufffe', // 0xA6 -> UNDEFINED
|
||||
'\ufffe', // 0xA7 -> UNDEFINED
|
||||
'\ufffe', // 0xA8 -> UNDEFINED
|
||||
'\ufffe', // 0xA9 -> UNDEFINED
|
||||
'\ufffe', // 0xAA -> UNDEFINED
|
||||
'\ufffe', // 0xAB -> UNDEFINED
|
||||
'\ufffe', // 0xAC -> UNDEFINED
|
||||
'\ufffe', // 0xAD -> UNDEFINED
|
||||
'\ufffe', // 0xAE -> UNDEFINED
|
||||
'\ufffe', // 0xAF -> UNDEFINED
|
||||
'\ufffe', // 0xB0 -> UNDEFINED
|
||||
'\ufffe', // 0xB1 -> UNDEFINED
|
||||
'\ufffe', // 0xB2 -> UNDEFINED
|
||||
'\ufffe', // 0xB3 -> UNDEFINED
|
||||
'\ufffe', // 0xB4 -> UNDEFINED
|
||||
'\ufffe', // 0xB5 -> UNDEFINED
|
||||
'\ufffe', // 0xB6 -> UNDEFINED
|
||||
'\ufffe', // 0xB7 -> UNDEFINED
|
||||
'\ufffe', // 0xB8 -> UNDEFINED
|
||||
'\ufffe', // 0xB9 -> UNDEFINED
|
||||
'\ufffe', // 0xBA -> UNDEFINED
|
||||
'\ufffe', // 0xBB -> UNDEFINED
|
||||
'\ufffe', // 0xBC -> UNDEFINED
|
||||
'\ufffe', // 0xBD -> UNDEFINED
|
||||
'\ufffe', // 0xBE -> UNDEFINED
|
||||
'\ufffe', // 0xBF -> UNDEFINED
|
||||
'\ufffe', // 0xC0 -> UNDEFINED
|
||||
'\ufffe', // 0xC1 -> UNDEFINED
|
||||
'\ufffe', // 0xC2 -> UNDEFINED
|
||||
'\ufffe', // 0xC3 -> UNDEFINED
|
||||
'\ufffe', // 0xC4 -> UNDEFINED
|
||||
'\ufffe', // 0xC5 -> UNDEFINED
|
||||
'\ufffe', // 0xC6 -> UNDEFINED
|
||||
'\ufffe', // 0xC7 -> UNDEFINED
|
||||
'\ufffe', // 0xC8 -> UNDEFINED
|
||||
'\ufffe', // 0xC9 -> UNDEFINED
|
||||
'\ufffe', // 0xCA -> UNDEFINED
|
||||
'\ufffe', // 0xCB -> UNDEFINED
|
||||
'\ufffe', // 0xCC -> UNDEFINED
|
||||
'\ufffe', // 0xCD -> UNDEFINED
|
||||
'\ufffe', // 0xCE -> UNDEFINED
|
||||
'\ufffe', // 0xCF -> UNDEFINED
|
||||
'\ufffe', // 0xD0 -> UNDEFINED
|
||||
'\ufffe', // 0xD1 -> UNDEFINED
|
||||
'\ufffe', // 0xD2 -> UNDEFINED
|
||||
'\ufffe', // 0xD3 -> UNDEFINED
|
||||
'\ufffe', // 0xD4 -> UNDEFINED
|
||||
'\ufffe', // 0xD5 -> UNDEFINED
|
||||
'\ufffe', // 0xD6 -> UNDEFINED
|
||||
'\ufffe', // 0xD7 -> UNDEFINED
|
||||
'\ufffe', // 0xD8 -> UNDEFINED
|
||||
'\ufffe', // 0xD9 -> UNDEFINED
|
||||
'\ufffe', // 0xDA -> UNDEFINED
|
||||
'\ufffe', // 0xDB -> UNDEFINED
|
||||
'\ufffe', // 0xDC -> UNDEFINED
|
||||
'\ufffe', // 0xDD -> UNDEFINED
|
||||
'\ufffe', // 0xDE -> UNDEFINED
|
||||
'\ufffe', // 0xDF -> UNDEFINED
|
||||
'\ufffe', // 0xE0 -> UNDEFINED
|
||||
'\ufffe', // 0xE1 -> UNDEFINED
|
||||
'\ufffe', // 0xE2 -> UNDEFINED
|
||||
'\ufffe', // 0xE3 -> UNDEFINED
|
||||
'\ufffe', // 0xE4 -> UNDEFINED
|
||||
'\ufffe', // 0xE5 -> UNDEFINED
|
||||
'\ufffe', // 0xE6 -> UNDEFINED
|
||||
'\ufffe', // 0xE7 -> UNDEFINED
|
||||
'\ufffe', // 0xE8 -> UNDEFINED
|
||||
'\ufffe', // 0xE9 -> UNDEFINED
|
||||
'\ufffe', // 0xEA -> UNDEFINED
|
||||
'\ufffe', // 0xEB -> UNDEFINED
|
||||
'\ufffe', // 0xEC -> UNDEFINED
|
||||
'\ufffe', // 0xED -> UNDEFINED
|
||||
'\ufffe', // 0xEE -> UNDEFINED
|
||||
'\ufffe', // 0xEF -> UNDEFINED
|
||||
'\ufffe', // 0xF0 -> UNDEFINED
|
||||
'\ufffe', // 0xF1 -> UNDEFINED
|
||||
'\ufffe', // 0xF2 -> UNDEFINED
|
||||
'\ufffe', // 0xF3 -> UNDEFINED
|
||||
'\ufffe', // 0xF4 -> UNDEFINED
|
||||
'\ufffe', // 0xF5 -> UNDEFINED
|
||||
'\ufffe', // 0xF6 -> UNDEFINED
|
||||
'\ufffe', // 0xF7 -> UNDEFINED
|
||||
'\ufffe', // 0xF8 -> UNDEFINED
|
||||
'\ufffe', // 0xF9 -> UNDEFINED
|
||||
'\ufffe', // 0xFA -> UNDEFINED
|
||||
'\ufffe', // 0xFB -> UNDEFINED
|
||||
'\ufffe', // 0xFC -> UNDEFINED
|
||||
'\ufffe', // 0xFD -> UNDEFINED
|
||||
'\ufffe', // 0xFE -> UNDEFINED
|
||||
'\ufffe' // 0xFF -> UNDEFINED
|
||||
)
|
||||
|
||||
private val decodingScreencodeUppercase = arrayOf(
|
||||
'@' , // @ 0x00 -> COMMERCIAL AT
|
||||
'A' , // A 0x01 -> LATIN CAPITAL LETTER A
|
||||
'B' , // B 0x02 -> LATIN CAPITAL LETTER B
|
||||
'C' , // C 0x03 -> LATIN CAPITAL LETTER C
|
||||
'D' , // D 0x04 -> LATIN CAPITAL LETTER D
|
||||
'E' , // E 0x05 -> LATIN CAPITAL LETTER E
|
||||
'F' , // F 0x06 -> LATIN CAPITAL LETTER F
|
||||
'G' , // G 0x07 -> LATIN CAPITAL LETTER G
|
||||
'H' , // H 0x08 -> LATIN CAPITAL LETTER H
|
||||
'I' , // I 0x09 -> LATIN CAPITAL LETTER I
|
||||
'J' , // J 0x0A -> LATIN CAPITAL LETTER J
|
||||
'K' , // K 0x0B -> LATIN CAPITAL LETTER K
|
||||
'L' , // L 0x0C -> LATIN CAPITAL LETTER L
|
||||
'M' , // M 0x0D -> LATIN CAPITAL LETTER M
|
||||
'N' , // N 0x0E -> LATIN CAPITAL LETTER N
|
||||
'O' , // O 0x0F -> LATIN CAPITAL LETTER O
|
||||
'P' , // P 0x10 -> LATIN CAPITAL LETTER P
|
||||
'Q' , // Q 0x11 -> LATIN CAPITAL LETTER Q
|
||||
'R' , // R 0x12 -> LATIN CAPITAL LETTER R
|
||||
'S' , // S 0x13 -> LATIN CAPITAL LETTER S
|
||||
'T' , // T 0x14 -> LATIN CAPITAL LETTER T
|
||||
'U' , // U 0x15 -> LATIN CAPITAL LETTER U
|
||||
'V' , // V 0x16 -> LATIN CAPITAL LETTER V
|
||||
'W' , // W 0x17 -> LATIN CAPITAL LETTER W
|
||||
'X' , // X 0x18 -> LATIN CAPITAL LETTER X
|
||||
'Y' , // Y 0x19 -> LATIN CAPITAL LETTER Y
|
||||
'Z' , // Z 0x1A -> LATIN CAPITAL LETTER Z
|
||||
'[' , // [ 0x1B -> LEFT SQUARE BRACKET
|
||||
'\u00a3', // £ 0x1C -> POUND SIGN
|
||||
']' , // ] 0x1D -> RIGHT SQUARE BRACKET
|
||||
'\u2191', // ↑ 0x1E -> UPWARDS ARROW
|
||||
'\u2190', // ← 0x1F -> LEFTWARDS ARROW
|
||||
' ' , // 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
|
||||
'\u2500', // ─ 0x40 -> BOX DRAWINGS LIGHT HORIZONTAL
|
||||
'\u2660', // ♠ 0x41 -> BLACK SPADE SUIT
|
||||
'\u2502', // │ 0x42 -> BOX DRAWINGS LIGHT VERTICAL
|
||||
'\u2500', // ─ 0x43 -> BOX DRAWINGS LIGHT HORIZONTAL
|
||||
'\uf122', // 0x44 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER UP (CUS)
|
||||
'\uf123', // 0x45 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS UP (CUS)
|
||||
'\uf124', // 0x46 -> BOX DRAWINGS LIGHT HORIZONTAL ONE QUARTER DOWN (CUS)
|
||||
'\uf126', // 0x47 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER LEFT (CUS)
|
||||
'\uf128', // 0x48 -> BOX DRAWINGS LIGHT VERTICAL ONE QUARTER RIGHT (CUS)
|
||||
'\u256e', // ╮ 0x49 -> BOX DRAWINGS LIGHT ARC DOWN AND LEFT
|
||||
'\u2570', // ╰ 0x4A -> BOX DRAWINGS LIGHT ARC UP AND RIGHT
|
||||
'\u256f', // ╯ 0x4B -> BOX DRAWINGS LIGHT ARC UP AND LEFT
|
||||
'\uf12a', // 0x4C -> ONE EIGHTH BLOCK UP AND RIGHT (CUS)
|
||||
'\u2572', // ╲ 0x4D -> BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
|
||||
'\u2571', // ╱ 0x4E -> BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
|
||||
'\uf12b', // 0x4F -> ONE EIGHTH BLOCK DOWN AND RIGHT (CUS)
|
||||
'\uf12c', // 0x50 -> ONE EIGHTH BLOCK DOWN AND LEFT (CUS)
|
||||
'\u25cf', // ● 0x51 -> BLACK CIRCLE
|
||||
'\uf125', // 0x52 -> BOX DRAWINGS LIGHT HORIZONTAL TWO QUARTERS DOWN (CUS)
|
||||
'\u2665', // ♥ 0x53 -> BLACK HEART SUIT
|
||||
'\uf127', // 0x54 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS LEFT (CUS)
|
||||
'\u256d', // ╭ 0x55 -> BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
|
||||
'\u2573', // ╳ 0x56 -> BOX DRAWINGS LIGHT DIAGONAL CROSS
|
||||
'\u25cb', // ○ 0x57 -> WHITE CIRCLE
|
||||
'\u2663', // ♣ 0x58 -> BLACK CLUB SUIT
|
||||
'\uf129', // 0x59 -> BOX DRAWINGS LIGHT VERTICAL TWO QUARTERS RIGHT (CUS)
|
||||
'\u2666', // ♦ 0x5A -> BLACK DIAMOND SUIT
|
||||
'\u253c', // ┼ 0x5B -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
|
||||
'\uf12e', // 0x5C -> LEFT HALF BLOCK MEDIUM SHADE (CUS)
|
||||
'\u2502', // │ 0x5D -> BOX DRAWINGS LIGHT VERTICAL
|
||||
'\u03c0', // π 0x5E -> GREEK SMALL LETTER PI
|
||||
'\u25e5', // ◥ 0x5F -> BLACK UPPER RIGHT TRIANGLE
|
||||
'\u00a0', // 0x60 -> NO-BREAK SPACE
|
||||
'\u258c', // ▌ 0x61 -> LEFT HALF BLOCK
|
||||
'\u2584', // ▄ 0x62 -> LOWER HALF BLOCK
|
||||
'\u2594', // ▔ 0x63 -> UPPER ONE EIGHTH BLOCK
|
||||
'\u2581', // ▁ 0x64 -> LOWER ONE EIGHTH BLOCK
|
||||
'\u258f', // ▏ 0x65 -> LEFT ONE EIGHTH BLOCK
|
||||
'\u2592', // ▒ 0x66 -> MEDIUM SHADE
|
||||
'\u2595', // ▕ 0x67 -> RIGHT ONE EIGHTH BLOCK
|
||||
'\uf12f', // 0x68 -> LOWER HALF BLOCK MEDIUM SHADE (CUS)
|
||||
'\u25e4', // ◤ 0x69 -> BLACK UPPER LEFT TRIANGLE
|
||||
'\uf130', // 0x6A -> RIGHT ONE QUARTER BLOCK (CUS)
|
||||
'\u251c', // ├ 0x6B -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||
'\u2597', // ▗ 0x6C -> QUADRANT LOWER RIGHT
|
||||
'\u2514', // └ 0x6D -> BOX DRAWINGS LIGHT UP AND RIGHT
|
||||
'\u2510', // ┐ 0x6E -> BOX DRAWINGS LIGHT DOWN AND LEFT
|
||||
'\u2582', // ▂ 0x6F -> LOWER ONE QUARTER BLOCK
|
||||
'\u250c', // ┌ 0x70 -> BOX DRAWINGS LIGHT DOWN AND RIGHT
|
||||
'\u2534', // ┴ 0x71 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||
'\u252c', // ┬ 0x72 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||
'\u2524', // ┤ 0x73 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||
'\u258e', // ▎ 0x74 -> LEFT ONE QUARTER BLOCK
|
||||
'\u258d', // ▍ 0x75 -> LEFT THREE EIGTHS BLOCK
|
||||
'\uf131', // 0x76 -> RIGHT THREE EIGHTHS BLOCK (CUS)
|
||||
'\uf132', // 0x77 -> UPPER ONE QUARTER BLOCK (CUS)
|
||||
'\uf133', // 0x78 -> UPPER THREE EIGHTS BLOCK (CUS)
|
||||
'\u2583', // ▃ 0x79 -> LOWER THREE EIGHTHS BLOCK
|
||||
'\uf12d', // 0x7A -> ONE EIGHTH BLOCK UP AND LEFT (CUS)
|
||||
'\u2596', // ▖ 0x7B -> QUADRANT LOWER LEFT
|
||||
'\u259d', // ▝ 0x7C -> QUADRANT UPPER RIGHT
|
||||
'\u2518', // ┘ 0x7D -> BOX DRAWINGS LIGHT UP AND LEFT
|
||||
'\u2598', // ▘ 0x7E -> QUADRANT UPPER LEFT
|
||||
'\u259a', // ▚ 0x7F -> QUADRANT UPPER LEFT AND LOWER RIGHT
|
||||
'\ufffe', // 0x80 -> UNDEFINED
|
||||
'\ufffe', // 0x81 -> UNDEFINED
|
||||
'\ufffe', // 0x82 -> UNDEFINED
|
||||
'\ufffe', // 0x83 -> UNDEFINED
|
||||
'\ufffe', // 0x84 -> UNDEFINED
|
||||
'\ufffe', // 0x85 -> UNDEFINED
|
||||
'\ufffe', // 0x86 -> UNDEFINED
|
||||
'\ufffe', // 0x87 -> UNDEFINED
|
||||
'\ufffe', // 0x88 -> UNDEFINED
|
||||
'\ufffe', // 0x89 -> UNDEFINED
|
||||
'\ufffe', // 0x8A -> UNDEFINED
|
||||
'\ufffe', // 0x8B -> UNDEFINED
|
||||
'\ufffe', // 0x8C -> UNDEFINED
|
||||
'\ufffe', // 0x8D -> UNDEFINED
|
||||
'\ufffe', // 0x8E -> UNDEFINED
|
||||
'\ufffe', // 0x8F -> UNDEFINED
|
||||
'\ufffe', // 0x90 -> UNDEFINED
|
||||
'\ufffe', // 0x91 -> UNDEFINED
|
||||
'\ufffe', // 0x92 -> UNDEFINED
|
||||
'\ufffe', // 0x93 -> UNDEFINED
|
||||
'\ufffe', // 0x94 -> UNDEFINED
|
||||
'\ufffe', // 0x95 -> UNDEFINED
|
||||
'\ufffe', // 0x96 -> UNDEFINED
|
||||
'\ufffe', // 0x97 -> UNDEFINED
|
||||
'\ufffe', // 0x98 -> UNDEFINED
|
||||
'\ufffe', // 0x99 -> UNDEFINED
|
||||
'\ufffe', // 0x9A -> UNDEFINED
|
||||
'\ufffe', // 0x9B -> UNDEFINED
|
||||
'\ufffe', // 0x9C -> UNDEFINED
|
||||
'\ufffe', // 0x9D -> UNDEFINED
|
||||
'\ufffe', // 0x9E -> UNDEFINED
|
||||
'\ufffe', // 0x9F -> UNDEFINED
|
||||
'\ufffe', // 0xA0 -> UNDEFINED
|
||||
'\ufffe', // 0xA1 -> UNDEFINED
|
||||
'\ufffe', // 0xA2 -> UNDEFINED
|
||||
'\ufffe', // 0xA3 -> UNDEFINED
|
||||
'\ufffe', // 0xA4 -> UNDEFINED
|
||||
'\ufffe', // 0xA5 -> UNDEFINED
|
||||
'\ufffe', // 0xA6 -> UNDEFINED
|
||||
'\ufffe', // 0xA7 -> UNDEFINED
|
||||
'\ufffe', // 0xA8 -> UNDEFINED
|
||||
'\ufffe', // 0xA9 -> UNDEFINED
|
||||
'\ufffe', // 0xAA -> UNDEFINED
|
||||
'\ufffe', // 0xAB -> UNDEFINED
|
||||
'\ufffe', // 0xAC -> UNDEFINED
|
||||
'\ufffe', // 0xAD -> UNDEFINED
|
||||
'\ufffe', // 0xAE -> UNDEFINED
|
||||
'\ufffe', // 0xAF -> UNDEFINED
|
||||
'\ufffe', // 0xB0 -> UNDEFINED
|
||||
'\ufffe', // 0xB1 -> UNDEFINED
|
||||
'\ufffe', // 0xB2 -> UNDEFINED
|
||||
'\ufffe', // 0xB3 -> UNDEFINED
|
||||
'\ufffe', // 0xB4 -> UNDEFINED
|
||||
'\ufffe', // 0xB5 -> UNDEFINED
|
||||
'\ufffe', // 0xB6 -> UNDEFINED
|
||||
'\ufffe', // 0xB7 -> UNDEFINED
|
||||
'\ufffe', // 0xB8 -> UNDEFINED
|
||||
'\ufffe', // 0xB9 -> UNDEFINED
|
||||
'\ufffe', // 0xBA -> UNDEFINED
|
||||
'\ufffe', // 0xBB -> UNDEFINED
|
||||
'\ufffe', // 0xBC -> UNDEFINED
|
||||
'\ufffe', // 0xBD -> UNDEFINED
|
||||
'\ufffe', // 0xBE -> UNDEFINED
|
||||
'\ufffe', // 0xBF -> UNDEFINED
|
||||
'\ufffe', // 0xC0 -> UNDEFINED
|
||||
'\ufffe', // 0xC1 -> UNDEFINED
|
||||
'\ufffe', // 0xC2 -> UNDEFINED
|
||||
'\ufffe', // 0xC3 -> UNDEFINED
|
||||
'\ufffe', // 0xC4 -> UNDEFINED
|
||||
'\ufffe', // 0xC5 -> UNDEFINED
|
||||
'\ufffe', // 0xC6 -> UNDEFINED
|
||||
'\ufffe', // 0xC7 -> UNDEFINED
|
||||
'\ufffe', // 0xC8 -> UNDEFINED
|
||||
'\ufffe', // 0xC9 -> UNDEFINED
|
||||
'\ufffe', // 0xCA -> UNDEFINED
|
||||
'\ufffe', // 0xCB -> UNDEFINED
|
||||
'\ufffe', // 0xCC -> UNDEFINED
|
||||
'\ufffe', // 0xCD -> UNDEFINED
|
||||
'\ufffe', // 0xCE -> UNDEFINED
|
||||
'\ufffe', // 0xCF -> UNDEFINED
|
||||
'\ufffe', // 0xD0 -> UNDEFINED
|
||||
'\ufffe', // 0xD1 -> UNDEFINED
|
||||
'\ufffe', // 0xD2 -> UNDEFINED
|
||||
'\ufffe', // 0xD3 -> UNDEFINED
|
||||
'\ufffe', // 0xD4 -> UNDEFINED
|
||||
'\ufffe', // 0xD5 -> UNDEFINED
|
||||
'\ufffe', // 0xD6 -> UNDEFINED
|
||||
'\ufffe', // 0xD7 -> UNDEFINED
|
||||
'\ufffe', // 0xD8 -> UNDEFINED
|
||||
'\ufffe', // 0xD9 -> UNDEFINED
|
||||
'\ufffe', // 0xDA -> UNDEFINED
|
||||
'\ufffe', // 0xDB -> UNDEFINED
|
||||
'\ufffe', // 0xDC -> UNDEFINED
|
||||
'\ufffe', // 0xDD -> UNDEFINED
|
||||
'\ufffe', // 0xDE -> UNDEFINED
|
||||
'\ufffe', // 0xDF -> UNDEFINED
|
||||
'\ufffe', // 0xE0 -> UNDEFINED
|
||||
'\ufffe', // 0xE1 -> UNDEFINED
|
||||
'\ufffe', // 0xE2 -> UNDEFINED
|
||||
'\ufffe', // 0xE3 -> UNDEFINED
|
||||
'\ufffe', // 0xE4 -> UNDEFINED
|
||||
'\ufffe', // 0xE5 -> UNDEFINED
|
||||
'\ufffe', // 0xE6 -> UNDEFINED
|
||||
'\ufffe', // 0xE7 -> UNDEFINED
|
||||
'\ufffe', // 0xE8 -> UNDEFINED
|
||||
'\ufffe', // 0xE9 -> UNDEFINED
|
||||
'\ufffe', // 0xEA -> UNDEFINED
|
||||
'\ufffe', // 0xEB -> UNDEFINED
|
||||
'\ufffe', // 0xEC -> UNDEFINED
|
||||
'\ufffe', // 0xED -> UNDEFINED
|
||||
'\ufffe', // 0xEE -> UNDEFINED
|
||||
'\ufffe', // 0xEF -> UNDEFINED
|
||||
'\ufffe', // 0xF0 -> UNDEFINED
|
||||
'\ufffe', // 0xF1 -> UNDEFINED
|
||||
'\ufffe', // 0xF2 -> UNDEFINED
|
||||
'\ufffe', // 0xF3 -> UNDEFINED
|
||||
'\ufffe', // 0xF4 -> UNDEFINED
|
||||
'\ufffe', // 0xF5 -> UNDEFINED
|
||||
'\ufffe', // 0xF6 -> UNDEFINED
|
||||
'\ufffe', // 0xF7 -> UNDEFINED
|
||||
'\ufffe', // 0xF8 -> UNDEFINED
|
||||
'\ufffe', // 0xF9 -> UNDEFINED
|
||||
'\ufffe', // 0xFA -> UNDEFINED
|
||||
'\ufffe', // 0xFB -> UNDEFINED
|
||||
'\ufffe', // 0xFC -> UNDEFINED
|
||||
'\ufffe', // 0xFD -> UNDEFINED
|
||||
'\ufffe', // 0xFE -> UNDEFINED
|
||||
'\ufffe' // 0xFF -> UNDEFINED
|
||||
)
|
||||
|
||||
// encoding: from unicode to Screencodes (0-255)
|
||||
private val encodingScreencodeLowercase = decodingScreencodeLowercase.withIndex().associate{it.value to it.index}
|
||||
private val encodingScreencodeUppercase = decodingScreencodeUppercase.withIndex().associate{it.value to it.index}
|
||||
|
||||
|
||||
fun encodeScreencode(text: String, lowercase: Boolean = false): List<Short> {
|
||||
val lookup = if(lowercase) encodingScreencodeLowercase else encodingScreencodeUppercase
|
||||
return text.map{
|
||||
val screencode = lookup[it]
|
||||
screencode?.toShort() ?: if(it=='\u0000')
|
||||
0.toShort()
|
||||
else {
|
||||
val case = if (lowercase) "lower" else "upper"
|
||||
throw CharConversionException("no ${case}Screencode character for '$it'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun decodeScreencode(screencode: Iterable<Short>, lowercase: Boolean = false): String {
|
||||
val decodeTable = if(lowercase) decodingScreencodeLowercase else decodingScreencodeUppercase
|
||||
return screencode.map { decodeTable[it.toInt()] }.joinToString("")
|
||||
}
|
||||
}
|
88
sim65/src/Sim65Main.kt
Normal file
88
sim65/src/Sim65Main.kt
Normal file
@ -0,0 +1,88 @@
|
||||
package sim65
|
||||
|
||||
import kotlinx.cli.*
|
||||
import sim65.components.*
|
||||
import sim65.components.Cpu6502.Companion.hexB
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
printSoftwareHeader()
|
||||
startSimulator(args)
|
||||
}
|
||||
|
||||
internal fun printSoftwareHeader() {
|
||||
val buildVersion = object {}.javaClass.getResource("/version.txt").readText().trim()
|
||||
println("\nSim65 6502 cpu simulator v$buildVersion by Irmen de Jong (irmen@razorvine.net)")
|
||||
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
||||
}
|
||||
|
||||
|
||||
private fun startSimulator(args: Array<String>) {
|
||||
val cli = CommandLineInterface("sim65", printHelpByDefault = false)
|
||||
val enableIllegal by cli.flagArgument("-ill", "enable the illegal instructions")
|
||||
|
||||
try {
|
||||
cli.parse(args)
|
||||
} catch (e: Exception) {
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val bootRom = listOf<UByte>(
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0x00,0x90, // NMI vector
|
||||
0x00,0x10, // RESET vector
|
||||
0x00,0xa0 // IRQ vector
|
||||
).toTypedArray()
|
||||
|
||||
val cpu = Cpu6502(enableIllegal)
|
||||
cpu.tracing = true
|
||||
|
||||
// create the system bus and add device to it.
|
||||
// note that the order is relevant w.r.t. where reads and writes are going.
|
||||
val bus = Bus()
|
||||
bus.add(cpu)
|
||||
bus.add(Rom(0xff00, 0xffff, bootRom))
|
||||
bus.add(Parallel(0xd000, 0xd001))
|
||||
bus.add(Timer(0xd100, 0xd103))
|
||||
val ram = Ram(0, 0xffff)
|
||||
bus.add(ram)
|
||||
|
||||
bus.reset()
|
||||
|
||||
ram.load("sim65/ram.bin", 0x8000)
|
||||
ram.load("sim65/bcdtest.bin", 0x1000)
|
||||
//ram.dump(0x8000, 0x802f)
|
||||
//cpu.disassemble(ram, 0x8000, 0x802f)
|
||||
|
||||
while(true) {
|
||||
bus.clock()
|
||||
if(cpu.totalCycles > 300)
|
||||
break
|
||||
}
|
||||
|
||||
if(ram.read(0x0400)==0.toShort())
|
||||
println("BCD TEST: OK!")
|
||||
else {
|
||||
val v1 = ram.read(0x0401)
|
||||
val v2 = ram.read(0x0402)
|
||||
println("BCD TEST: FAIL!! value1=${hexB(v1)} value2=${hexB(v2)}")
|
||||
}
|
||||
ram.dump(0x0400, 0x0402)
|
||||
|
||||
}
|
46
sim65/src/components/Bus.kt
Normal file
46
sim65/src/components/Bus.kt
Normal file
@ -0,0 +1,46 @@
|
||||
package sim65.components
|
||||
|
||||
typealias UByte = Short
|
||||
typealias Address = Int
|
||||
|
||||
|
||||
class Bus {
|
||||
|
||||
private val components = mutableListOf<BusComponent>()
|
||||
private val memComponents = mutableListOf<MemMappedComponent>()
|
||||
|
||||
fun reset() {
|
||||
components.forEach { it.reset() }
|
||||
memComponents.forEach { it.reset() }
|
||||
}
|
||||
|
||||
fun clock() {
|
||||
components.forEach { it.clock() }
|
||||
memComponents.forEach { it.clock() }
|
||||
}
|
||||
|
||||
fun add(component: BusComponent) {
|
||||
components.add(component)
|
||||
component.bus = this
|
||||
}
|
||||
|
||||
fun add(component: MemMappedComponent) {
|
||||
memComponents.add(component)
|
||||
component.bus = this
|
||||
}
|
||||
|
||||
fun read(address: Address): UByte {
|
||||
memComponents.forEach {
|
||||
if(address>=it.startAddress && address<=it.endAddress)
|
||||
return it.read(address)
|
||||
}
|
||||
return 0xff
|
||||
}
|
||||
|
||||
fun write(address: Address, data: UByte) {
|
||||
memComponents.forEach {
|
||||
if(address>=it.startAddress && address<=it.endAddress)
|
||||
it.write(address, data)
|
||||
}
|
||||
}
|
||||
}
|
35
sim65/src/components/Component.kt
Normal file
35
sim65/src/components/Component.kt
Normal file
@ -0,0 +1,35 @@
|
||||
package sim65.components
|
||||
|
||||
import sim65.C64Screencodes
|
||||
|
||||
abstract class BusComponent {
|
||||
lateinit var bus: Bus
|
||||
|
||||
abstract fun clock()
|
||||
abstract fun reset()
|
||||
}
|
||||
|
||||
abstract class MemMappedComponent(val startAddress: Address, val endAddress: Address): BusComponent() {
|
||||
abstract fun read(address: Address): UByte
|
||||
abstract fun write(address: Address, data: UByte)
|
||||
abstract fun cloneMem(): Array<UByte>
|
||||
|
||||
init {
|
||||
require(endAddress>=startAddress)
|
||||
require(startAddress>=0 && endAddress <= 0xffff) { "can only have 16-bit address space" }
|
||||
}
|
||||
|
||||
fun dump(from: Address, to: Address) {
|
||||
(from .. to).chunked(16).forEach {
|
||||
print("\$${it.first().toString(16).padStart(4, '0')} ")
|
||||
val bytes = it.map { address -> read(address) }
|
||||
bytes.forEach { byte ->
|
||||
print(byte.toString(16).padStart(2, '0') + " ")
|
||||
}
|
||||
print(" ")
|
||||
print(C64Screencodes.decodeScreencode(bytes, false).replace('\ufffe', '.'))
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1138
sim65/src/components/Cpu6502.kt
Normal file
1138
sim65/src/components/Cpu6502.kt
Normal file
File diff suppressed because it is too large
Load Diff
39
sim65/src/components/Parallel.kt
Normal file
39
sim65/src/components/Parallel.kt
Normal file
@ -0,0 +1,39 @@
|
||||
package sim65.components
|
||||
|
||||
import sim65.C64Screencodes
|
||||
|
||||
/**
|
||||
* A parallel output device (basically, prints bytes as characters to the screen)
|
||||
* First address = data byte (8 parallel bits)
|
||||
* Second address = control byte (bit 0 high = write byte)
|
||||
*/
|
||||
class Parallel(startAddress: Address, endAddress: Address) : MemMappedComponent(startAddress, endAddress) {
|
||||
private var dataByte: UByte = 0
|
||||
|
||||
init {
|
||||
require(endAddress - startAddress + 1 == 2) { "parallel needs exactly 2 memory bytes (data + control)" }
|
||||
}
|
||||
|
||||
override fun clock() {}
|
||||
override fun reset() {}
|
||||
|
||||
override fun read(address: Address): UByte {
|
||||
return if (address == startAddress)
|
||||
dataByte
|
||||
else
|
||||
0
|
||||
}
|
||||
|
||||
override fun write(address: Address, data: UByte) {
|
||||
if (address == startAddress)
|
||||
dataByte = data
|
||||
else if (address == endAddress) {
|
||||
if ((data.toInt() and 1) == 1) {
|
||||
val char = C64Screencodes.decodeScreencode(listOf(dataByte), false).first()
|
||||
println("PARALLEL WRITE: '$char'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun cloneMem(): Array<UByte> = listOf(dataByte, 0).toTypedArray()
|
||||
}
|
30
sim65/src/components/Ram.kt
Normal file
30
sim65/src/components/Ram.kt
Normal file
@ -0,0 +1,30 @@
|
||||
package sim65.components
|
||||
|
||||
import java.io.File
|
||||
|
||||
class Ram(startAddress: Address, endAddress: Address): MemMappedComponent(startAddress, endAddress) {
|
||||
private val memory = ShortArray(endAddress-startAddress+1)
|
||||
|
||||
override fun read(address: Address): UByte = memory[address-startAddress]
|
||||
|
||||
override fun write(address: Address, data: UByte) {
|
||||
memory[address-startAddress] = data
|
||||
}
|
||||
|
||||
override fun cloneMem(): Array<UByte> = memory.toTypedArray()
|
||||
|
||||
override fun clock() { }
|
||||
|
||||
override fun reset() { memory.fill(0) }
|
||||
|
||||
fun load(filename: String, address: Address) {
|
||||
val bytes = File(filename).readBytes()
|
||||
bytes.forEachIndexed { index, byte ->
|
||||
memory[address+index] =
|
||||
if(byte>=0)
|
||||
byte.toShort()
|
||||
else
|
||||
(256+byte).toShort()
|
||||
}
|
||||
}
|
||||
}
|
15
sim65/src/components/Rom.kt
Normal file
15
sim65/src/components/Rom.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package sim65.components
|
||||
|
||||
class Rom(startAddress: Address, endAddress: Address, data: Array<UByte>): MemMappedComponent(startAddress, endAddress) {
|
||||
private val memory = ShortArray(data.size) { index -> data[index] }
|
||||
|
||||
init {
|
||||
require(endAddress-startAddress+1 == data.size) { "rom address range doesn't match size of data bytes" }
|
||||
}
|
||||
|
||||
override fun read(address: Address): UByte = memory[address-startAddress]
|
||||
override fun write(address: Address, data: UByte) { }
|
||||
override fun cloneMem(): Array<UByte> = memory.toTypedArray()
|
||||
override fun clock() { }
|
||||
override fun reset() { }
|
||||
}
|
29
sim65/src/components/Timer.kt
Normal file
29
sim65/src/components/Timer.kt
Normal file
@ -0,0 +1,29 @@
|
||||
package sim65.components
|
||||
|
||||
class Timer(startAddress: Address, endAddress: Address): MemMappedComponent(startAddress, endAddress) {
|
||||
private var cycle: Long = 0
|
||||
|
||||
init {
|
||||
require(endAddress - startAddress + 1 == 4) { "timer needs exactly 4 memory bytes" }
|
||||
}
|
||||
|
||||
override fun clock() {
|
||||
cycle++
|
||||
if (cycle > 0xffffffff)
|
||||
cycle = 0
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
cycle = 0
|
||||
}
|
||||
|
||||
override fun read(address: Address): UByte {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
override fun write(address: Address, data: UByte) {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
override fun cloneMem(): Array<UByte> = TODO("clonemem timer")
|
||||
}
|
29
sim65/testprogram.asm
Normal file
29
sim65/testprogram.asm
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
* = $8000
|
||||
|
||||
sec
|
||||
lda #$a0
|
||||
sta $2000
|
||||
ldx $2000
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
sty $2001
|
||||
ldy #0
|
||||
loop lda text,y
|
||||
beq end
|
||||
sta $d000
|
||||
inc $d001
|
||||
iny
|
||||
jmp loop
|
||||
end nop
|
||||
bvs loop
|
||||
|
||||
.byte $02 ; invalid opcode
|
||||
.byte $02 ; invalid opcode
|
||||
.byte $02 ; invalid opcode
|
||||
|
||||
|
||||
text .enc "screen"
|
||||
.text "hello!",0
|
||||
.enc "none"
|
Loading…
Reference in New Issue
Block a user