diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-03 19:55:52 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-03 19:55:52 +0200 |
| commit | abf6cbdecc8eb006a859205dee7500c2b70c0998 (patch) | |
| tree | 4938cfaf270b6c83a77767de968845f704049205 | |
| parent | a3b677bac00060393cc66f1bb3b350413282a4ae (diff) | |
Fix macros, add string I/O helpers
| -rw-r--r-- | asm/ext_string_io.py | 47 | ||||
| -rw-r--r-- | asm/text_mode.atk16 | 59 | ||||
| -rw-r--r-- | digital/atk16_mem.dig | 12 | ||||
| -rw-r--r-- | src/asm_pass0.py | 5 | ||||
| -rw-r--r-- | src/asm_pass1.py | 3 | ||||
| -rw-r--r-- | src/charmem.py | 2 | ||||
| -rw-r--r-- | src/tokenizer.py | 32 |
7 files changed, 100 insertions, 60 deletions
diff --git a/asm/ext_string_io.py b/asm/ext_string_io.py new file mode 100644 index 0000000..cf7d598 --- /dev/null +++ b/asm/ext_string_io.py @@ -0,0 +1,47 @@ +from asm_ops import * +from ext_std import expand_addi + +def to_char_code(c: str): + if c == " " or c == "%SPACE": return 0 + else: return ord(c) - 64 + +_counter = 0 +def get_unique_name(prefix: str): + global _counter + ret = f"{prefix}_{_counter}" + _counter += 1 + return ret + +def expand_put_char(cursor_reg: str, scratch_reg: str, c: str) -> ExpandResult: + return [ + ["ldi", str(to_char_code(c)), scratch_reg], + ["str", scratch_reg, cursor_reg], + *expand_addi("RA", "1", "RA"), + ] + +def expand_put_string(cursor_reg: str, scratch_reg: str, *rest: str) -> ExpandResult: + string = " ".join(rest) + result: ExpandResult = [] + for c in string: + result += expand_put_char(cursor_reg, scratch_reg, c) + + return result + +def expand_cursor_to_line(cursor_reg: str, line: int) -> ExpandResult: + lbl_data = get_unique_name("cursor_to_line_data") + lbl_jmpover = get_unique_name("cursor_to_line_jmpover") + line_width = 64 + return [ + ["jpi", lbl_jmpover], + ["@label", lbl_data], + [f"text_mem + {line} * {line_width}"], + ["@label", lbl_jmpover], + ["ldi", lbl_data, cursor_reg], + ["ldr", cursor_reg, cursor_reg], + ] + +expansions: OpExpansionDict = { + "put_char": expand_put_char, + "cursor_to_line": expand_cursor_to_line, + "put_string": expand_put_string, +}
\ No newline at end of file diff --git a/asm/text_mode.atk16 b/asm/text_mode.atk16 index ff84156..f4d84ae 100644 --- a/asm/text_mode.atk16 +++ b/asm/text_mode.atk16 @@ -1,61 +1,19 @@ @opt stack_pointer RF @opt csr_scratch RH @use ext_std:* +@use ext_string_io:* ; bootstrap code (must be called to set up mandatory data) ; will jump to label main @include bootstrap @label main - ldi vt_text_mem RA - ldr RA RA - ldi 8 RB ; letter H - str RB RA - addi RA 1 RA - ldi 5 RB ; letter E - str RB RA - addi RA 1 RA - ldi 12 RB ; letter L - str RB RA - addi RA 1 RA - ldi 12 RB ; letter L - str RB RA - addi RA 1 RA - ldi 15 RB ; letter O - str RB RA - addi RA 1 RA - ldi 0 RB ; space - str RB RA - addi RA 1 RA - ldi 3 RB ; letter C - str RB RA - addi RA 1 RA - ldi 15 RB ; letter O - str RB RA - addi RA 1 RA - ldi 18 RB ; letter R - str RB RA - addi RA 1 RA - ldi 5 RB ; letter E - str RB RA - addi RA 1 RA - ldi 3 RB ; letter C - str RB RA - addi RA 1 RA - ldi 1 RB ; letter A - str RB RA - addi RA 1 RA - ldi 13 RB ; letter M - str RB RA - addi RA 1 RA - ldi 16 RB ; letter P - str RB RA - ldi offset RC - ldr RC RC - add RA RC RA - ; ldi 20 RB ; letter A - ; str RB RA - ; addi RA 1 RA + cursor_to_line RA 1 + put_char RA RB %SPACE + put_string RA RB HELLO CORECAMP + cursor_to_line RA 3 + put_char RA RB %SPACE + put_string RA RB BY JAN ; set graphics mode to sprite mode ; set_graphics_mode gr_sprite_mode @@ -63,6 +21,3 @@ @label loop jpi loop - -@label offset - 51 diff --git a/digital/atk16_mem.dig b/digital/atk16_mem.dig index c3663e3..31fe276 100644 --- a/digital/atk16_mem.dig +++ b/digital/atk16_mem.dig @@ -37,11 +37,13 @@ <string>Data</string> <data>4014,2a00,6029,13*8000,1c,1a,1a,1a,8000,e000,e001,e002,e800,f800 ,4855,f000,3140,1b48,3148,1b48,4016,2000,2000,4215,2240,3040,1800 -,3148,1b48,3140,1b48,e000,4017,2000,4200,3008,6000,4019,2000,4208 -,3008,1008,4205,3008,1008,420c,3008,1008,420c,3008,1008,420f,3008 -,1008,4200,3008,1008,4203,3008,1008,420f,3008,1008,4212,3008,1008 -,4205,3008,1008,4203,3008,1008,4201,3008,1008,420d,3008,1008,4210 -,3008,4464,2480,10,4017,2000,4201,3008,61ff,33</data> +,3148,1b48,3140,1b48,e000,4017,2000,4200,3008,6000,6001,f840,4032 +,2000,4200,3008,1008,4208,3008,1008,4205,3008,1008,420c,3008,1008 +,420c,3008,1008,420f,3008,1008,4200,3008,1008,4203,3008,1008,420f +,3008,1008,4212,3008,1008,4205,3008,1008,4203,3008,1008,4201,3008 +,1008,420d,3008,1008,4210,3008,1008,6001,f8c0,4063,2000,4200,3008 +,1008,4202,3008,1008,4219,3008,1008,4200,3008,1008,420a,3008,1008 +,4201,3008,1008,420e,3008,1008,4017,2000,4201,3008,61ff</data> </entry> </elementAttributes> <pos x="740" y="100"/> diff --git a/src/asm_pass0.py b/src/asm_pass0.py index 4913e4b..f5b6b0b 100644 --- a/src/asm_pass0.py +++ b/src/asm_pass0.py @@ -2,6 +2,7 @@ from dataclasses import dataclass import os.path from asm_ops import * from asm_eval import * +from tokenizer import * @dataclass class Result0Line: @@ -19,7 +20,9 @@ def pass_0(lines: list[str], file_name: str) -> Result0: for (line_num, line) in enumerate(lines): line = line.split(";")[0].strip() if line == "": continue - keyword, *args = line.lower().split() + + keyword, *args = tokenize(line) + match keyword: case "@include": asm_file_name = args[0] diff --git a/src/asm_pass1.py b/src/asm_pass1.py index d462526..5e6213a 100644 --- a/src/asm_pass1.py +++ b/src/asm_pass1.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from asm_ops import * from asm_eval import * from asm_pass0 import * +from tokenizer import tokenize @dataclass class Result1Line: @@ -24,7 +25,7 @@ def pass_1(result0: Result0) -> Result1: operations: OpExpansionDict = default_expansions.copy() for line in result0.lines: - keyword, *args = line.line.lower().split() + keyword, *args = tokenize(line.line) match keyword: case "@opt": opt_name, opt_value = args diff --git a/src/charmem.py b/src/charmem.py index 9b19864..551ba85 100644 --- a/src/charmem.py +++ b/src/charmem.py @@ -43,7 +43,7 @@ def string_to_byte(input_string: str): # Check if the string contains only '0' or '1' if not all(c in '01' for c in binary_string): - raise ValueError("Input string must contain only spaces and '#' characters.") + raise ValueError("Input string must contain only spaces and '█' characters.") # Convert the binary string to an unsigned integer byte return int(binary_string[::-1], 2) diff --git a/src/tokenizer.py b/src/tokenizer.py new file mode 100644 index 0000000..2049461 --- /dev/null +++ b/src/tokenizer.py @@ -0,0 +1,32 @@ +def tokenize(line: str) -> list[str]: + cur: str = "" + result: list[str] = [] + is_py_expr = False + idx = 0 + while idx < len(line): + c = line[idx] + if not is_py_expr and c == "$": + is_py_expr = True + idx += 1 + elif is_py_expr and c == "$": + raise Exception("Unexpected start of python expr while already parsing a python expression:\n" + line) + elif not is_py_expr and c == "}": + raise Exception("Unexpected end of python expr while not parsing a python expression:\n" + line) + elif is_py_expr and c == "}": + is_py_expr = False + result.append(cur) + cur = "" + elif is_py_expr: + cur += c + elif c == " " or c == "\t": + result.append(cur) + cur = "" + else: + cur += c + + idx += 1 + + if len(cur) > 0: + result.append(cur) + + return [r for r in result if r != ""]
\ No newline at end of file |
