1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-29 18:49:42 +00:00

Added support for Atari string encodings ATASCII and screencoce_atari. Closes #500

This commit is contained in:
jespergravgaard 2020-08-08 02:09:08 +02:00
parent 9dfe9d6634
commit 560d81043e
9 changed files with 87 additions and 78 deletions

View File

@ -70,8 +70,6 @@ public class AsmProgram {
public void addLine(AsmLine line) { public void addLine(AsmLine line) {
line.setIndex(nextLineIndex++); line.setIndex(nextLineIndex++);
getCurrentChunk().addLine(line); getCurrentChunk().addLine(line);
if(line instanceof AsmSetEncoding)
currentEncoding = ((AsmSetEncoding) line).getEncoding();
} }
/** /**
@ -90,7 +88,13 @@ public class AsmProgram {
// Size is 1 - grab it! // Size is 1 - grab it!
StringEncoding encoding = encodings.iterator().next(); StringEncoding encoding = encodings.iterator().next();
if(!getCurrentEncoding().equals(encoding)) { if(!getCurrentEncoding().equals(encoding)) {
addLine(new AsmSetEncoding(encoding)); if(encoding.asmEncoding != null) {
addLine(new AsmSetEncoding(encoding));
} else {
addLine(new AsmSetEncoding(StringEncoding.ASCII));
}
currentEncoding = encoding;
} }
} }

View File

@ -24,7 +24,7 @@ public class AsmSetEncoding implements AsmLine {
@Override @Override
public String getAsm() { public String getAsm() {
return ".encoding \"" + encoding.name+ "\""; return ".encoding \"" + encoding.asmEncoding+ "\"";
} }
@Override @Override

View File

@ -0,0 +1,35 @@
package dk.camelot64.kickc.model.values;
import kickass.nonasm.c64.CharToPetsciiConverter;
import java.util.HashMap;
import java.util.Map;
/**
* Supports the ATARI charset ATASCII and the ATARI screencodes
*/
public class CharToAtasciiConverter {
/** Map from UNICODE char to Byte value for ATASCII. https://www.atariarchives.org/mapping/appendix10.php */
public static Map<Character, Byte> charToAtascii;
/** Map from UNICODE char to Byte value for Atari Screencode. https://www.atariarchives.org/mapping/appendix10.php */
public static Map<Character, Byte> charToScreenCodeAtari;
static {
charToAtascii = CharToPetsciiConverter.charToAscii;
charToScreenCodeAtari = new HashMap<>();
for(Character atasciiChar : charToAtascii.keySet()) {
final Byte atasciiByte = charToAtascii.get(atasciiChar);
Byte screencodeAtariByte;
if(atasciiByte >= 0 && atasciiByte <= 31)
screencodeAtariByte = (byte) (atasciiByte + 64);
else if(atasciiByte >= 32 && atasciiByte <= 96)
screencodeAtariByte = (byte) (atasciiByte - 32);
else
screencodeAtariByte = atasciiByte;
charToScreenCodeAtari.put(atasciiChar, screencodeAtariByte);
}
}
}

View File

@ -9,11 +9,14 @@ import java.util.PrimitiveIterator;
/** String encoding. */ /** String encoding. */
public enum StringEncoding { public enum StringEncoding {
PETSCII_MIXED("petscii_mixed", "pm", CharToPetsciiConverter.charToPetscii_mixed), PETSCII_MIXED("petscii_mixed", "petscii_mixed", "pm", CharToPetsciiConverter.charToPetscii_mixed),
PETSCII_UPPER("petscii_upper", "pu", CharToPetsciiConverter.charToPetscii_mixed), PETSCII_UPPER("petscii_upper", "petscii_upper", "pu", CharToPetsciiConverter.charToPetscii_mixed),
SCREENCODE_MIXED("screencode_mixed", "sm", CharToPetsciiConverter.charToScreenCode_mixed), SCREENCODE_MIXED("screencode_mixed", "screencode_mixed", "sm", CharToPetsciiConverter.charToScreenCode_mixed),
SCREENCODE_UPPER("screencode_upper", "su", CharToPetsciiConverter.charToScreenCode_upper); SCREENCODE_UPPER("screencode_upper", "screencode_upper", "su", CharToPetsciiConverter.charToScreenCode_upper),
ASCII("ascii", "ascii", "as", CharToPetsciiConverter.charToAscii),
ATASCII("atascii", "ascii", "at", CharToAtasciiConverter.charToAtascii),
SCREENCODE_ATARI("screencode_atari", null, "sa", CharToAtasciiConverter.charToScreenCodeAtari),
;
/** Char value used to encode \xnn chars without a value within the chosen encoding. A char C is encoded as CHAR_SPECIAL_VAL+C */ /** Char value used to encode \xnn chars without a value within the chosen encoding. A char C is encoded as CHAR_SPECIAL_VAL+C */
public static final char CHAR_SPECIAL_VAL = 64000; public static final char CHAR_SPECIAL_VAL = 64000;
@ -25,14 +28,18 @@ public enum StringEncoding {
/** The encoding name. */ /** The encoding name. */
public final String name; public final String name;
/** The KickAsm Encoding name. Null if KickAsm does not support the encoding. */
public final String asmEncoding;
/** The string suffix usable for selecting the encoding. */ /** The string suffix usable for selecting the encoding. */
public final String suffix; public final String suffix;
/** The mapping from character value to integer value for the encoding. */ /** The mapping from character value to integer (byte) value for the encoding. */
public final Map<Character, Byte> mapping; public final Map<Character, Byte> mapping;
StringEncoding(String name, String suffix, Map<Character, Byte> mapping) { StringEncoding(String name, String asmEncoding, String suffix, Map<Character, Byte> mapping) {
this.name = name; this.name = name;
this.asmEncoding = asmEncoding;
this.suffix = suffix; this.suffix = suffix;
this.mapping = mapping; this.mapping = mapping;
} }
@ -163,8 +170,7 @@ public enum StringEncoding {
hexNum += (char) escapedCharsIterator.nextInt(); hexNum += (char) escapedCharsIterator.nextInt();
hexNum += (char) escapedCharsIterator.nextInt(); hexNum += (char) escapedCharsIterator.nextInt();
final byte hexEncoding = (byte) Integer.parseInt(hexNum, 16); final byte hexEncoding = (byte) Integer.parseInt(hexNum, 16);
final Character aChar = charFromEncoded(hexEncoding); return charFromEncoded(hexEncoding);
return aChar;
default: default:
throw new CompileError("Illegal string escape sequence \\" + escapeChar); throw new CompileError("Illegal string escape sequence \\" + escapeChar);
} }
@ -178,6 +184,14 @@ public enum StringEncoding {
* @return The char itself - or the appropriate escape sequence if needed. * @return The char itself - or the appropriate escape sequence if needed.
*/ */
public String asciiToEscapedEncoded(char aChar, boolean escapeSingleQuotes) { public String asciiToEscapedEncoded(char aChar, boolean escapeSingleQuotes) {
if(this.asmEncoding == null) {
// Encoding not supported by KickAsm - convert to ASCII / use escapes
final byte encoded = encodedFromChar(aChar);
if(encoded != ASCII.encodedFromChar(aChar))
// Not the same as in ASCII - use escape
return String.format("\\$%02x", encoded);
}
switch(aChar) { switch(aChar) {
case '\n': case '\n':
return "\\n"; return "\\n";
@ -198,7 +212,7 @@ public enum StringEncoding {
if(aChar > 127) { if(aChar > 127) {
// Encode all large chars - including SPECIAL's // Encode all large chars - including SPECIAL's
final byte encoded = encodedFromChar(aChar); final byte encoded = encodedFromChar(aChar);
return String.format("\\$%x", encoded); return String.format("\\$%02x", encoded);
} else } else
return Character.toString(aChar); return Character.toString(aChar);
} }

View File

@ -4,6 +4,8 @@
// Display Lists atariarchives.org/mapping/appendix8.php // Display Lists atariarchives.org/mapping/appendix8.php
#pragma target(atarixl) #pragma target(atarixl)
#pragma encoding(screencode_atari)
#pragma emulator("65XEDebugger")
#include <atari-xl.h> #include <atari-xl.h>
void main() { void main() {
@ -16,14 +18,13 @@ void main() {
} }
// Message to show // Message to show
// Encoding: atari_screencode char TEXT[] = "hello XT world! ";
char TEXT[] = {'h'|0x20,'e'|0x20,'l'|0x20,'l'|0x20,'o'|0x20,0x0,'x'|0x60,'t'|0x60,0x0,'w'|0x20,'o'|0x20,'r'|0x20,'l'|0x20,'d'|0x20,0x41,0x0,0x0,0x0,0x0};
// ANTIC Display List Program // ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC // https://en.wikipedia.org/wiki/ANTIC
char DISPLAY_LIST[] = { char DISPLAY_LIST[] = {
0x70, 0x70, 0x70, // 3* BLK 8 (0x70) 8 blank lines 0x70, 0x70, 0x70, // 3* BLK 8 (0x70) 8 blank lines
0x47, <TEXT, >TEXT, // LMS 7, TEXT (0x47) Load memory address and set to charmode 7 (16/20/24 chars wide, 16 lines per char) 0x47, <TEXT, >TEXT, // LMS 7, TEXT (0x47) Load memory address and set to charmode 7 (16/20/24 chars wide, 16 lines per char)
0x41, <DISPLAY_LIST, >DISPLAY_LIST // JVB DISPLAY_LIST (0x41) jump and wait for VBLANK 0x41, <DISPLAY_LIST, >DISPLAY_LIST // JVB DISPLAY_LIST (0x41) jump and wait for VBLANK
}; };

View File

@ -1,6 +1,6 @@
// Test setting an unknown encoding using the #encoding pragma // Test setting an unknown encoding using the #encoding pragma
#pragma encoding(ascii) #pragma encoding(ebcdic)
void main() { void main() {
} }

View File

@ -47,8 +47,9 @@ main: {
} }
.segment Data .segment Data
// Message to show // Message to show
// Encoding: atari_screencode .encoding "ascii"
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0 TEXT: .text @"hello\$00\$38\$34\$00world\$01\$00"
.byte 0
// ANTIC Display List Program // ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC // https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST

View File

@ -141,7 +141,7 @@ SYMBOL TABLE SSA
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } (const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**)(number) $230 (const nomodify byte**) SDLST = (byte**)(number) $230
(const nomodify byte*) SDMCTL = (byte*)(number) $22f (const nomodify byte*) SDMCTL = (byte*)(number) $22f
(const byte*) TEXT[] = { (byte)(byte) 'h'|(number) $20, (byte)(byte) 'e'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte) 0, (byte)(byte) 'x'|(number) $60, (byte)(byte) 't'|(number) $60, (byte) 0, (byte)(byte) 'w'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte)(byte) 'r'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'd'|(number) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 } (const byte*) TEXT[] = (byte*) "hello XT world! "sa
(void()) __start() (void()) __start()
(label) __start::@1 (label) __start::@1
(label) __start::@2 (label) __start::@2
@ -152,50 +152,14 @@ SYMBOL TABLE SSA
(label) main::@1 (label) main::@1
(label) main::@return (label) main::@return
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $60 in
Adding number conversion cast (unumber) $60 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $21 in *((const nomodify byte*) SDMCTL) ← (number) $21 Adding number conversion cast (unumber) $21 in *((const nomodify byte*) SDMCTL) ← (number) $21
Successful SSA optimization PassNAddNumberTypeConversions Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((const nomodify byte*) SDMCTL) ← (unumber)(number) $21 Inlining cast *((const nomodify byte*) SDMCTL) ← (unumber)(number) $21
Successful SSA optimization Pass2InlineCast Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 559 Simplifying constant pointer cast (byte*) 559
Simplifying constant pointer cast (byte**) 560 Simplifying constant pointer cast (byte**) 560
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $60
Simplifying constant integer cast $60
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $21 Simplifying constant integer cast $21
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $60
Finalized unsigned number type (byte) $60
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $21 Finalized unsigned number type (byte) $21
Successful SSA optimization PassNFinalizeNumberTypeConversions Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) main::$0 [3] if((number) 0!=(number) 1) goto main::@1 Simple Condition (bool~) main::$0 [3] if((number) 0!=(number) 1) goto main::@1
@ -211,19 +175,6 @@ Removing unused procedure block __start::@1
Removing unused procedure block __start::@2 Removing unused procedure block __start::@2
Removing unused procedure block __start::@return Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart Successful SSA optimization PassNEliminateEmptyStart
Simplifying constant integer cast (byte) 'h'|(byte) $20
Simplifying constant integer cast (byte) 'e'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'o'|(byte) $20
Simplifying constant integer cast (byte) 'x'|(byte) $60
Simplifying constant integer cast (byte) 't'|(byte) $60
Simplifying constant integer cast (byte) 'w'|(byte) $20
Simplifying constant integer cast (byte) 'o'|(byte) $20
Simplifying constant integer cast (byte) 'r'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'd'|(byte) $20
Successful SSA optimization PassNCastSimplification
Adding NOP phi() at start of main::@1 Adding NOP phi() at start of main::@1
CALL GRAPH CALL GRAPH
@ -409,8 +360,9 @@ main: {
// File Data // File Data
.segment Data .segment Data
// Message to show // Message to show
// Encoding: atari_screencode .encoding "ascii"
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0 TEXT: .text @"hello\$00\$38\$34\$00world\$01\$00"
.byte 0
// ANTIC Display List Program // ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC // https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
@ -496,8 +448,9 @@ main: {
// File Data // File Data
.segment Data .segment Data
// Message to show // Message to show
// Encoding: atari_screencode .encoding "ascii"
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0 TEXT: .text @"hello\$00\$38\$34\$00world\$01\$00"
.byte 0
// ANTIC Display List Program // ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC // https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
@ -617,7 +570,7 @@ FINAL SYMBOL TABLE
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } (const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**) 560 (const nomodify byte**) SDLST = (byte**) 560
(const nomodify byte*) SDMCTL = (byte*) 559 (const nomodify byte*) SDMCTL = (byte*) 559
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 } (const byte*) TEXT[] = (byte*) "hello XT world! "sa
(void()) main() (void()) main()
(label) main::@1 (label) main::@1
@ -684,8 +637,9 @@ main: {
// File Data // File Data
.segment Data .segment Data
// Message to show // Message to show
// Encoding: atari_screencode .encoding "ascii"
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0 TEXT: .text @"hello\$00\$38\$34\$00world\$01\$00"
.byte 0
// ANTIC Display List Program // ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC // https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST

View File

@ -102,7 +102,7 @@
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST } (const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**) 560 (const nomodify byte**) SDLST = (byte**) 560
(const nomodify byte*) SDMCTL = (byte*) 559 (const nomodify byte*) SDMCTL = (byte*) 559
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 } (const byte*) TEXT[] = (byte*) "hello XT world! "sa
(void()) main() (void()) main()
(label) main::@1 (label) main::@1