diff --git a/docs/lang/preprocessor.md b/docs/lang/preprocessor.md index dee5498e..9c0682df 100644 --- a/docs/lang/preprocessor.md +++ b/docs/lang/preprocessor.md @@ -54,6 +54,8 @@ The following features are defined based on the chosen CPU and compilation optio `CPUFEATURE_8080`, `CPUFEATURE_8085`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`, `CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS`, `CPUFEATURE_Z80_NEXT` – 1 if given instruction subset is enabled, 0 otherwise +* `ENCCONV_SUPPORTED` - 1 if the module `encconv` supports the function `to_screencode` and other related funtions, 0 otherwise. + * `ENCODING_SAME` - 1 if the encodings `default` and `src` are the same, 0 otherwise. * `NULLCHAR_SAME` - 1 if the encodings `default` and `src` have the same string terminator, 0 otherwise. diff --git a/docs/stdlib/encconv.md b/docs/stdlib/encconv.md index 0915e6da..c5a8c421 100644 --- a/docs/stdlib/encconv.md +++ b/docs/stdlib/encconv.md @@ -31,6 +31,8 @@ Available only if one of the following is true: * the default encoding is `atascii`, the screen encoding is `atasciiscr`, and the platform is 6502-based +You can test for the availability of this function using the `ENCCONV_SUPPORTED` preprocessor feature. + #### byte from_screencode(byte) Converts a byte from the screen encoding to the default encoding. @@ -39,6 +41,18 @@ If both encodings contain the character `¤`, then `from_screencode('¤'scr) == Available only if `to_screencode` is available. +#### void strz_to_screencode(pointer) + +Destructively converts a null-terminated string from the `default` encoding into the `scr` encoding. + +Available only if `to_screencode` is available. + +#### void strz_from_screencode(pointer) + +Destructively converts a null-terminated string from the `scr` encoding into the `default` encoding. + +Available only if `from_screencode` is available. + #### byte petscii_to_petscr(byte) Converts a byte from PETSCII to a CBM screencode. diff --git a/include/encconv.mfk b/include/encconv.mfk index acb35ea5..e66492ed 100644 --- a/include/encconv.mfk +++ b/include/encconv.mfk @@ -2,23 +2,88 @@ #if ARCH_6502 inline byte __byte_identity(byte a) { ? rts } +inline void __pointer_to_void(pointer ax) { ? rts } #elseif ARCH_I80 #pragma zilog_syntax inline byte __byte_identity(byte a) { ? ret } +inline void __pointer_to_void(pointer hl) { ? ret } +#elseif ARCH_M6809 +inline byte __byte_identity(byte b) { ? rts } +inline void __pointer_to_void(pointer d) { ? rts } #else inline byte __byte_identity(byte a) = a +inline void __pointer_to_void(pointer a) { } #endif alias from_screencode = __byte_identity alias to_screencode = __byte_identity +alias strz_from_screencode = __pointer_to_void +alias strz_to_screencode = __pointer_to_void -#else +#elseif ENCCONV_SUPPORTED alias from_screencode = __from_screencode alias to_screencode = __to_screencode + +#if ARCH_6502 +void strz_from_screencode(pointer p) { + asm { + ? LDY #0 + __strz_from_screencode__loop: + LDA (p),Y + ? CMP #nullchar_scr + ? BEQ __strz_from_screencode__end + ? JSR from_screencode + ? STA (p),Y + ? INY + ? JMP __strz_from_screencode__loop + __strz_from_screencode__end: + ? LDA #nullchar + ? STA (p),Y + } +} +void strz_to_screencode(pointer p) { + asm { + ? LDY #0 + __strz_to_screencode__loop: + LDA (p),Y + ? CMP #nullchar + ? BEQ __strz_to_screencode__end + ? JSR to_screencode + ? STA (p),Y + ? INY + ? JMP __strz_to_screencode__loop + __strz_to_screencode__end: + ? LDA #nullchar_scr + ? STA (p),Y + } +} +#else +void strz_from_screencode(pointer p) { + while true { + if p[0] == nullchar_scr { + p[0] = nullchar + return + } + p[0] = from_screencode(p[0]) + p += 1 + } +} +void strz_to_screencode(pointer p) { + while true { + if p[0] == nullchar { + p[0] = nullchar_scr + return + } + p[0] = to_screencode(p[0]) + p += 1 + } +} #endif +#endif // ENCODING_SAME/ENCCONV_SUPPORTED + // conversions for particular encoding pairs: diff --git a/src/main/scala/millfork/Platform.scala b/src/main/scala/millfork/Platform.scala index f1295958..1e9531d5 100644 --- a/src/main/scala/millfork/Platform.scala +++ b/src/main/scala/millfork/Platform.scala @@ -282,6 +282,13 @@ object Platform { val builtInFeatures = builtInCpuFeatures(cpu) ++ Map( "ENCODING_SAME" -> toLong(codec.name == srcCodec.name), + "ENCCONV_SUPPORTED" -> toLong((codec.name, srcCodec.name) match { + case (TextCodec.Petscii.name, TextCodec.CbmScreencodes.name) | + (TextCodec.PetsciiJp.name, TextCodec.CbmScreencodesJp.name) | + (TextCodec.Atascii.name, TextCodec.AtasciiScreencodes.name) => + CpuFamily.forType(cpu) == CpuFamily.M6502 + case _ => codec.name == srcCodec.name + }), "NULLCHAR_SAME" -> toLong(codec.stringTerminator == srcCodec.stringTerminator) )