diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 2894834cb..90c7ae4bb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -299,7 +299,7 @@ internal class AssignmentAsmGen(private val program: Program, ) when (value.operator) { "+" -> {} - "-" -> augmentableAsmGen.inplaceNegate(assign) + "-" -> augmentableAsmGen.inplaceNegate(assign, true) "~" -> augmentableAsmGen.inplaceInvert(assign) else -> throw AssemblyError("invalid prefix operator") } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 049e573d4..d0b3abc2e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -23,7 +23,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // A = -A , A = +A, A = ~A, A = not A when (value.operator) { "+" -> {} - "-" -> inplaceNegate(assign) + "-" -> inplaceNegate(assign, false) "~" -> inplaceInvert(assign) else -> throw AssemblyError("invalid prefix operator") } @@ -1871,9 +1871,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } - internal fun inplaceNegate(assign: AsmAssignment) { + internal fun inplaceNegate(assign: AsmAssignment, ignoreDatatype: Boolean) { val target = assign.target - when (target.datatype) { + val datatype = if(ignoreDatatype) { + when(target.datatype) { + DataType.UBYTE, DataType.BYTE -> DataType.BYTE + DataType.UWORD, DataType.WORD -> DataType.WORD + else -> target.datatype + } + } else target.datatype + when (datatype) { DataType.BYTE -> { when (target.kind) { TargetStorageKind.VARIABLE -> { diff --git a/compiler/test/codegeneration/TestVariables.kt b/compiler/test/codegeneration/TestVariables.kt index 8863bcb46..24c425ead 100644 --- a/compiler/test/codegeneration/TestVariables.kt +++ b/compiler/test/codegeneration/TestVariables.kt @@ -63,5 +63,21 @@ class TestVariables: FunSpec({ """ compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null } + + test("negation of unsigned via casts") { + val text = """ + main { + sub start() { + cx16.r0L = -(cx16.r0L as byte) as ubyte + cx16.r0 = -(cx16.r0 as word) as uword + ubyte ub + uword uw + ub = -(ub as byte) as ubyte + uw = -(uw as word) as uword + } + } + """ + compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null + } }) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 1b3f9a55e..62a3eb6dd 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- fix compiler crash cx16.r0 = (-(cx16.r0 as word) as uword) +- make the adpcm example read wav files directly (so no need anymore to extract the binary frame data from them) - duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) + documentation - get f_seek_w working like in the BASIC program - this needs the changes to diskio.f_open to use suffixes ,p,m - attempt to fix the expression codegen bug with reused temp vars (github #89) diff --git a/examples/cx16/pcmaudio/adpcm.p8 b/examples/cx16/pcmaudio/adpcm.p8 index 1917207d2..38ae5446a 100644 --- a/examples/cx16/pcmaudio/adpcm.p8 +++ b/examples/cx16/pcmaudio/adpcm.p8 @@ -3,6 +3,23 @@ %option no_sysinit %zeropage basicsafe +; +; IMA ADPCM decoding and playback example. +; https://wiki.multimedia.cx/index.php/IMA_ADPCM +; https://wiki.multimedia.cx/index.php/Microsoft_IMA_ADPCM +; +; IMA ADPCM encodes two 16-bit PCM audio samples in 1 byte (1 word per nibble) +; thus compressing the audio data by a factor of 4. +; The encoding precision is about 13 bits per sample so it's a lossy compression scheme. +; +; NOTE: this program requires 16 bits MONO audio, and 256 byte encoded block size! +; HOW TO CREATE SUCH IMA-ADPCM ENCODED AUDIO? Use sox or ffmpeg: +; $ sox --guard source.mp3 -r 8000 -c 1 -e ima-adpcm out.wav trim 01:27.50 00:09 +; $ ffmpeg -i source.mp3 -ss 00:01:27.50 -to 00:01:36.50 -ar 8000 -ac 1 -c:a adpcm_ima_wav -block_size 256 -map_metadata -1 -bitexact out.wav +; +; THEN use a tool to read the raw audio frame data from that resulting out.wav and save it as 'adpcm-mono.bin'. +; + main { ubyte num_adpcm_blocks @@ -179,7 +196,7 @@ adpcm { audiodata { - ;; %option align_page + %option align_page adpcm_data: %asmbinary "adpcm-mono.bin" adpcm_data_end: