From d55bbcf706f0a46491ec2fcdfb280b81a46a3baa Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 22 Dec 2018 01:07:43 +0100 Subject: [PATCH] removed string conversion builtin functions, they're now subroutines in c64util --- compiler/examples/hello.p8 | 2 +- compiler/examples/numbergame-novm.p8 | 2 +- compiler/examples/numbergame.p8 | 2 +- compiler/examples/swirl-c64.p8 | 4 +- compiler/examples/swirl.p8 | 8 +- compiler/examples/test.p8 | 145 ++++++++---------- compiler/src/prog8/ast/AST.kt | 3 +- compiler/src/prog8/ast/AstChecker.kt | 7 +- compiler/src/prog8/compiler/Compiler.kt | 6 +- .../src/prog8/compiler/target/c64/AsmGen.kt | 5 +- .../src/prog8/functions/BuiltinFunctions.kt | 5 - compiler/src/prog8/stackvm/StackVm.kt | 49 +----- docs/source/programming.rst | 15 -- prog8lib/c64utils.p8 | 91 +++++++++++ 14 files changed, 179 insertions(+), 165 deletions(-) diff --git a/compiler/examples/hello.p8 b/compiler/examples/hello.p8 index 7e59846ad..18951a283 100644 --- a/compiler/examples/hello.p8 +++ b/compiler/examples/hello.p8 @@ -23,7 +23,7 @@ ; use loop to write characters str bye = "Goodbye!\n" - for ubyte c in 0 to len(bye) { ; @TODO fix compiler crash + for ubyte c in 0 to len(bye) { ; @TODO fix compiler crash. Parent of assignment to c should be the anonymous scope 'c' is in, instead of the for loop itself. c64.CHROUT(bye[c]) } diff --git a/compiler/examples/numbergame-novm.p8 b/compiler/examples/numbergame-novm.p8 index eba15be61..5d4b4aa9c 100644 --- a/compiler/examples/numbergame-novm.p8 +++ b/compiler/examples/numbergame-novm.p8 @@ -32,7 +32,7 @@ c64scr.print("es") c64scr.print(" left.\nWhat is your next guess? ") c64scr.input_chars(input) - ubyte guess = str2ubyte(input) + ubyte guess = c64utils.str2ubyte(input) ; debug info ; c64scr.print(" > attempts left=") diff --git a/compiler/examples/numbergame.p8 b/compiler/examples/numbergame.p8 index 886541f3a..78faf353a 100644 --- a/compiler/examples/numbergame.p8 +++ b/compiler/examples/numbergame.p8 @@ -21,7 +21,7 @@ vm_write_str("es") vm_write_str(" left. What is your next guess? ") vm_input_str(input) - ubyte guess = str2ubyte(input) + ubyte guess = c64utils.str2ubyte(input) ; @todo replace with proper stubs for these functions when executing on stackvm. if guess==secretnumber { vm_write_str("\nYou guessed it, impressive!\n") vm_write_str("Thanks for playing.\n") diff --git a/compiler/examples/swirl-c64.p8 b/compiler/examples/swirl-c64.p8 index 90157c5c3..8e2be9f22 100644 --- a/compiler/examples/swirl-c64.p8 +++ b/compiler/examples/swirl-c64.p8 @@ -28,9 +28,9 @@ } sub screenx(float x) -> ubyte { - return b2ub(fintb(x * flt(width)/2.2) + width//2) + return (x * width/2.2) + width//2 as ubyte } sub screeny(float y) -> ubyte { - return b2ub(fintb(y * flt(height)/2.2) + height//2) + return (y * height/2.2) + height//2 as ubyte } } diff --git a/compiler/examples/swirl.p8 b/compiler/examples/swirl.p8 index 2f6aa97dc..2a26f1b73 100644 --- a/compiler/examples/swirl.p8 +++ b/compiler/examples/swirl.p8 @@ -23,9 +23,13 @@ } sub screenx(float x) -> word { - return fintw(x * flt(width)/4.1) + width // 2 + ; return (x/4.1* (width as float) as word) + width // 2 ; @todo fix calculation + float wf = width + return (x/4.1* wf + wf / 2) as word } sub screeny(float y) -> word { - return fintw(y * flt(height)/4.1) + height // 2 + ;return (y/4.1 * (height as float) as word) + height // 2 ; @todo fix calculation + float hf = height + return (y/4.1 * hf + hf/ 2) as word } } diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 3ee40900f..bb60957a8 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,111 +1,86 @@ %import c64utils -%import mathlib -%option enable_floats +;%import mathlib +;%option enable_floats ~ main { - ;c64scr.PLOT(screenx(x), screeny(y)) ; @todo fix argument calculation???!!! + ;@todo implement the various byte/word division routines. + + ;c64scr.PLOT(screenx(x), screeny(y)) ; @todo fix argument calculation of parameters ???!!! + sub start() { - - byte[4] ba = [-1,2,-10,30] - ubyte[4] uba = [4,200,10,15] - word[5] wa = [400,-200,-1000,9999,1500] - uword[7] uwa = [333,42,9999,12,150,1000,4000] - float[6] fa = [-2.22, 3.33, -5.55, 1.11, 9999.99, -999.99] c64scr.print(" X=") c64scr.print_ub(X) c64.CHROUT('\n') - byte bmin = min(ba) - byte bmax = max(ba) - ubyte ubmin = min(uba) - ubyte ubmax = max(uba) - word wmin = min(wa) - word wmax = max(wa) - uword uwmin = min(uwa) - uword uwmax = max(uwa) - float fmin = min(fa) - float fmax = max(fa) - - c64scr.print_w(wmin) - c64.CHROUT(',') - c64scr.print_w(wmax) + word w = c64utils.str2word("000") + c64scr.print_w(w) + c64.CHROUT('\n') + w = c64utils.str2word("1") + c64scr.print_w(w) + c64.CHROUT('\n') + w = c64utils.str2word("-15000") + c64scr.print_w(w) + c64.CHROUT('\n') + w = c64utils.str2word("15000") + c64scr.print_w(w) c64.CHROUT('\n') - c64scr.print_uw(uwmin) - c64.CHROUT(',') - c64scr.print_uw(uwmax) c64.CHROUT('\n') - c64scr.print_b(bmin) - c64.CHROUT(',') - c64scr.print_b(bmax) + uword uw = c64utils.str2uword("0") + c64scr.print_uw(uw) + c64.CHROUT('\n') + uw = c64utils.str2uword("1") + c64scr.print_uw(uw) + c64.CHROUT('\n') + uw = c64utils.str2uword("15000") + c64scr.print_uw(uw) + c64.CHROUT('\n') + uw = c64utils.str2uword("65522") + c64scr.print_uw(uw) c64.CHROUT('\n') - c64scr.print_ub(ubmin) - c64.CHROUT(',') - c64scr.print_ub(ubmax) c64.CHROUT('\n') - c64flt.print_f(fmin) - c64.CHROUT(',') - c64flt.print_f(fmax) + byte b = c64utils.str2byte("0") + c64scr.print_b(b) + c64.CHROUT('\n') + b=c64utils.str2byte("10") + c64scr.print_b(b) + c64.CHROUT('\n') + b=c64utils.str2byte("-10") + c64scr.print_b(b) + c64.CHROUT('\n') + b=c64utils.str2byte("-128") + c64scr.print_b(b) + c64.CHROUT('\n') + b=c64utils.str2byte("127") + c64scr.print_b(b) + c64.CHROUT('\n') + c64.CHROUT('\n') + + ubyte ub = c64utils.str2ubyte("0") + c64scr.print_ub(ub) + c64.CHROUT('\n') + ub=c64utils.str2ubyte("10") + c64scr.print_ub(ub) + c64.CHROUT('\n') + ub=c64utils.str2ubyte("10") + c64scr.print_ub(ub) + c64.CHROUT('\n') + ub=c64utils.str2ubyte("128") + c64scr.print_ub(ub) + c64.CHROUT('\n') + ub=c64utils.str2ubyte("255") + c64scr.print_ub(ub) + c64.CHROUT('\n') c64.CHROUT('\n') c64scr.print(" X=") c64scr.print_ub(X) c64.CHROUT('\n') -; ub3 = 200/67 as ubyte -; ub3 = 200//67 -; c64scr.print_ub(ub3) -; c64.CHROUT('\n') -; ub3 = ub1/ub2 -; c64scr.print_ub(ub3) -; c64.CHROUT('\n') -; ub3 = ub1//ub2 -; c64scr.print_ub(ub3) -; c64.CHROUT('\n') -; -; uw3 = 2000/67 as uword -; c64scr.print_uw(uw3) -; c64.CHROUT('\n') -; uw3 = 2000//67 -; c64scr.print_uw(uw3) -; c64.CHROUT('\n') -; uw3 = uw1/uw2 -; c64scr.print_uw(uw3) -; c64.CHROUT('\n') -; uw3 = uw1//uw2 -; c64scr.print_uw(uw3) -; c64.CHROUT('\n') -; - -; const byte width=20 -; word w1 -; byte b1 -; ubyte ub1 -; float x = 3.45 -; b1 = fintb(x * flt(width)/4.2) + width//2 -; c64scr.print_b(b1) -; c64.CHROUT('\n') -; b1 = fintb(x/4.2 * flt(width)) + width//2 -; c64scr.print_b(b1) -; c64.CHROUT('\n') -; ub1 = b2ub(fintb(x * flt(width)/4.2) + width//2) -; c64scr.print_ub(ub1) -; c64.CHROUT('\n') -; ub1 = b2ub(fintb(x/4.2 * flt(width)) + width//2) -; c64scr.print_ub(ub1) -; c64.CHROUT('\n') -; w1 = fintw(x * flt(width)/4.2) + width//2 -; c64scr.print_w(w1) -; c64.CHROUT('\n') -; w1 = fintw(x/4.2 * flt(width)) + width//2 -; c64scr.print_w(w1) -; c64.CHROUT('\n') - ;uw1 = w2uw(fintw(x * flt(width)/4.2) + width//2) ; @todo w2uw - } } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index faca1a3e1..67b1edcec 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -270,6 +270,7 @@ interface IAstProcessor { } fun process(typecastExpression: TypecastExpression): IExpression { + typecastExpression.expression = typecastExpression.expression.process(this) return typecastExpression } } @@ -477,7 +478,7 @@ private class GlobalNamespace(override val name: String, override fun linkParents(parent: Node) {} override fun lookup(scopedName: List, statement: Node): IStatement? { - if(scopedName.last() in BuiltinFunctions) { + if(scopedName.size==1 && scopedName[0] in BuiltinFunctions) { // builtin functions always exist, return a dummy statement for them val builtinPlaceholder = Label("builtin::${scopedName.last()}", statement.position) builtinPlaceholder.parent = ParentSentinel diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 821b3a3dc..e7a75e0a8 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -436,8 +436,11 @@ class AstChecker(private val namespace: INameScope, val sourceDatatype: DataType? = assignment.value.resultingDatatype(namespace, heap) if(sourceDatatype==null) { if(assignment.targets.size<=1) { - if (assignment.value is FunctionCall) - checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position)) + if (assignment.value is FunctionCall) { + val targetStmt = (assignment.value as FunctionCall).target.targetStatement(namespace) + if(targetStmt!=null) + checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position)) + } else checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position)) } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index c7c32fc12..140af82d1 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -1388,7 +1388,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, AX -> { // deal with register pair AX: target = A + X*256 val targetDt = target.determineDatatype(namespace, heap, parent) - if(targetDt!=DataType.UWORD) + if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD) throw CompilerException("invalid target datatype for registerpair $targetDt") prog.instr(Opcode.PUSH_REGAX_WORD) popValueIntoTarget(target, targetDt) @@ -1396,7 +1396,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, AY -> { // deal with register pair AY: target = A + Y*256 val targetDt = target.determineDatatype(namespace, heap, parent) - if(targetDt!=DataType.UWORD) + if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD) throw CompilerException("invalid target datatype for registerpair $targetDt") prog.instr(Opcode.PUSH_REGAY_WORD) popValueIntoTarget(target, targetDt) @@ -1404,7 +1404,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, XY -> { // deal with register pair XY: target = X + Y*256 val targetDt = target.determineDatatype(namespace, heap, parent) - if(targetDt!=DataType.UWORD) + if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD) throw CompilerException("invalid target datatype for registerpair $targetDt") prog.instr(Opcode.PUSH_REGXY_WORD) popValueIntoTarget(target, targetDt) diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 7843333bc..6f4b50c49 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -425,10 +425,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr }) throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}") val call = Syscall.values().find { it.callNr==ins.arg.numericValue() } - when(call) { - Syscall.FUNC_STR2UBYTE, Syscall.FUNC_STR2UWORD -> " jsr prog8_lib.func_str2uword" - else -> " jsr prog8_lib.${call.toString().toLowerCase()}" - } + " jsr prog8_lib.${call.toString().toLowerCase()}" } Opcode.BREAKPOINT -> { breakpointCounter++ diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 5028fc74f..f9e9418e7 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -54,11 +54,6 @@ val BuiltinFunctions = mapOf( "clear_carry" to FunctionSignature(false, emptyList(), null), "set_irqd" to FunctionSignature(false, emptyList(), null), "clear_irqd" to FunctionSignature(false, emptyList(), null), - "str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.BYTE), - "str2ubyte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UBYTE), - "str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD), - "str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD), - "str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.FLOAT), "vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null), diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index eaa8751b6..2e954a58b 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -40,11 +40,6 @@ enum class Syscall(val callNr: Short) { FUNC_RND(89), // push a random byte on the stack FUNC_RNDW(90), // push a random word on the stack FUNC_RNDF(91), // push a random float on the stack (between 0.0 and 1.0) - FUNC_STR2BYTE(100), - FUNC_STR2UBYTE(101), - FUNC_STR2WORD(102), - FUNC_STR2UWORD(103), - FUNC_STR2FLOAT(104), FUNC_LEN_STR(105), FUNC_LEN_STRP(106), FUNC_LEN_STRS(107), @@ -1450,8 +1445,8 @@ class StackVm(private var traceOutputFile: String?) { Syscall.FUNC_ROUND -> evalstack.push(Value(DataType.WORD, evalstack.pop().numericValue().toDouble().roundToInt())) Syscall.FUNC_ABS -> { val value = evalstack.pop() - val absValue= - when(value.type) { + val absValue = + when (value.type) { DataType.UBYTE -> Value(DataType.UBYTE, value.numericValue()) DataType.UWORD -> Value(DataType.UWORD, value.numericValue()) DataType.FLOAT -> Value(DataType.FLOAT, value.numericValue()) @@ -1468,13 +1463,13 @@ class StackVm(private var traceOutputFile: String?) { Syscall.FUNC_DEG -> evalstack.push(Value(DataType.FLOAT, Math.toDegrees(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_FLOOR -> { val value = evalstack.pop() - if(value.type in NumericDatatypes) + if (value.type in NumericDatatypes) evalstack.push(Value(DataType.WORD, floor(value.numericValue().toDouble()).toInt())) else throw VmExecutionException("cannot get floor of $value") } Syscall.FUNC_CEIL -> { val value = evalstack.pop() - if(value.type in NumericDatatypes) + if (value.type in NumericDatatypes) evalstack.push(Value(DataType.WORD, ceil(value.numericValue().toDouble()).toInt())) else throw VmExecutionException("cannot get ceil of $value") } @@ -1538,7 +1533,7 @@ class StackVm(private var traceOutputFile: String?) { val result = value.array!!.min() ?: 0 evalstack.push(Value(DataType.FLOAT, result)) } - Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W, Syscall.FUNC_AVG_F-> { + Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W, Syscall.FUNC_AVG_F -> { val iterable = evalstack.pop() val value = heap.get(iterable.heapId) evalstack.push(Value(DataType.FLOAT, value.array!!.average())) @@ -1568,39 +1563,7 @@ class StackVm(private var traceOutputFile: String?) { val value = heap.get(iterable.heapId) evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0)) } - Syscall.FUNC_STR2BYTE -> { - val strvar = evalstack.pop() - val str = heap.get(strvar.heapId) // TODO CHECK - val y = str.str!!.trim().trimEnd('\u0000') - evalstack.push(Value(DataType.BYTE, y.toShort())) - } - Syscall.FUNC_STR2UBYTE -> { - val heapId = evalstack.pop().integerValue() - val str = heap.get(heapId) - val y = str.str!!.trim().trimEnd('\u0000') - val number = (y.toInt() and 255).toShort() - evalstack.push(Value(DataType.UBYTE, number)) - } - Syscall.FUNC_STR2WORD -> { - val heapId = evalstack.pop().integerValue() - val str = heap.get(heapId) - val y = str.str!!.trim().trimEnd('\u0000') - evalstack.push(Value(DataType.WORD, y.toInt())) - } - Syscall.FUNC_STR2UWORD -> { - val heapId = evalstack.pop().integerValue() - val str = heap.get(heapId) - val y = str.str!!.trim().trimEnd('\u0000') - val number = y.toInt() and 65535 - evalstack.push(Value(DataType.UWORD, number)) - } - Syscall.FUNC_STR2FLOAT -> { - val heapId = evalstack.pop().integerValue() - val str = heap.get(heapId) - val y = str.str!!.trim().trimEnd('\u0000') - evalstack.push(Value(DataType.FLOAT, y.toDouble())) - } - } + } } fun irq(timestamp: Long) { diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 82a10e8c7..ea0beb83f 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -565,21 +565,6 @@ rndw() rndf() returns a pseudo-random float between 0.0 and 1.0 -str2byte(s) - converts string s into the numeric value that s represents (signed byte). - -str2ubyte(s) - converts string s into the numeric value that s represents (unsigned byte). - -str2word(s) - converts string s into the numeric value that s represents (signed word). - -str2uword(s) - converts string s into the numeric value that s represents (unsigned word). - -str2float(s) - converts string s into the numeric value that s represents (float). - lsl(x) Shift the bits in x (byte or word) one position to the left. Bit 0 is set to 0 (and the highest bit is shifted into the status register's Carry flag) diff --git a/prog8lib/c64utils.p8 b/prog8lib/c64utils.p8 index 7fdbc2b80..e224f5ca7 100644 --- a/prog8lib/c64utils.p8 +++ b/prog8lib/c64utils.p8 @@ -188,6 +188,97 @@ asmsub uword2decimal (uword value @ AY) -> clobbers(A,X,Y) -> () { } + + +; @todo this is python code for a str-to-ubyte function that doesn't use the basic rom: +;def str2ubyte(s, slen): +; hundreds_map = { +; 0: 0, +; 1: 100, +; 2: 200 +; } +; digitvalue = 0 +; result = 0 +; if slen==0: +; return digitvalue +; digitvalue = ord(s[slen-1])-48 +; slen -= 1 +; if slen==0: +; return digitvalue +; result = digitvalue +; digitvalue = 10 * (ord(s[slen-1])-48) +; result += digitvalue +; slen -= 1 +; if slen==0: +; return result +; digitvalue = hundreds_map[ord(s[slen-1])-48] +; result += digitvalue +; return result + +asmsub str2uword(str string @ AY) -> clobbers() -> (uword @ AY) { + %asm {{ + ;-- convert string (address in A/Y) to uword number in A/Y + ; @todo don't use the (slow) kernel floating point conversion + sta $22 + sty $23 + jsr _strlen2233 + tya + stx c64.SCRATCH_ZPREGX + jsr c64.FREADSTR ; string to fac1 + jsr c64.GETADR ; fac1 to unsigned word in Y/A + ldx c64.SCRATCH_ZPREGX + sta c64.SCRATCH_ZPREG + tya + ldy c64.SCRATCH_ZPREG + rts + +_strlen2233 + ;-- return the length of the (zero-terminated) string at $22/$23, in Y + ldy #0 +- lda ($22),y + beq + + iny + bne - ++ rts + }} +} + +asmsub str2word(str string @ AY) -> clobbers() -> (word @ AY) { + %asm {{ + ;-- convert string (address in A/Y) to signed word number in A/Y + ; @todo don't use the (slow) kernel floating point conversion + sta $22 + sty $23 + jsr str2uword._strlen2233 + tya + stx c64.SCRATCH_ZPREGX + jsr c64.FREADSTR ; string to fac1 + jsr c64.FTOSWORDYA ; fac1 to unsigned word in Y/A + ldx c64.SCRATCH_ZPREGX + sta c64.SCRATCH_ZPREG + tya + ldy c64.SCRATCH_ZPREG + rts + }} +} + +asmsub str2ubyte(str string @ AY) -> clobbers(Y) -> (ubyte @ A) { + %asm {{ + ;-- convert string (address in A/Y) to ubyte number in A + ; @todo don't use the (slow) kernel floating point conversion + jmp str2uword + }} +} + +asmsub str2byte(str string @ AY) -> clobbers(Y) -> (byte @ A) { + %asm {{ + ;-- convert string (address in A/Y) to byte number in A + ; @todo don't use the (slow) kernel floating point conversion + jmp str2word + }} +} + + ; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html