diff --git a/README.md b/README.md index fac874d..514acf1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,11 @@ Check our [User's Manual](https://c64lib.github.io/user-manual/#_common) for mor ## Change log +### Changes in version 0.4.0 + +* New macro: `compress.asm\compressRLE`. +* New subroutine: `decompress_rle.asm`. + ### Changes in version 0.3.0 * New macro: `math.asm/mulAndAdd` - multiple two numbers and add result to memory location. diff --git a/build.gradle b/build.gradle index 5c7d3b3..fee8260 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ retroProject { dialect = "KickAssembler" dialectVersion = "5.25" libDirs = [".ra/deps/c64lib"] - verbose = true + srcDirs = ["lib"] libFromGitHub "c64lib/64spec", "0.7.0pr" } diff --git a/lib/common-global.asm b/lib/common-global.asm index 8e38fd6..00c8f5d 100644 --- a/lib/common-global.asm +++ b/lib/common-global.asm @@ -23,6 +23,8 @@ * SOFTWARE. */ #import "common.asm" +#importonce + .filenamespace c64lib .macro @c64lib_ch(data) { ch(data) } diff --git a/lib/compress-global.asm b/lib/compress-global.asm new file mode 100644 index 0000000..5c8de07 --- /dev/null +++ b/lib/compress-global.asm @@ -0,0 +1,30 @@ +/* + * MIT License + * + * Copyright (c) 2017-2023 c64lib + * Copyright (c) 2017-2023 Maciej Małecki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#import "compress.asm" +#importonce + +.filenamespace c64lib + +.macro @c64lib_compressRLE(data) { compressRLE(data) } diff --git a/lib/compress.asm b/lib/compress.asm new file mode 100644 index 0000000..ef03ca3 --- /dev/null +++ b/lib/compress.asm @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (c) 2017-2023 c64lib + * Copyright (c) 2017-2023 Maciej Małecki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#importonce +.filenamespace c64lib + +/* + * Performs RLE (Running Length Encoding) compression of given binary data (kick assembler data type). + * The compressed result is placed as is in the result file starting from the place where this macro is called. + */ +.macro compressRLE(binaryData) { + .var runLength = 0 + .var runValue = 0 + .var crunchedLength = 0 + .for(var i = 0; i < binaryData.getSize(); i++) { + .if(runLength > 0 && (binaryData.get(i) != runValue || runLength == $ff)) { + .byte runLength + .byte runValue + .eval runLength = 0 + .eval crunchedLength = crunchedLength + 2 + } + .if(runLength == 0) { + .eval runValue = binaryData.get(i) + .eval runLength = 1 + } else { + .eval runLength++ + } + } + .byte runLength + .byte runValue + .byte $00 // end mark + .eval crunchedLength++ + .print "Crunched from " + binaryData.getSize() + " to " + crunchedLength + " (" + round((crunchedLength/binaryData.getSize())*100) + "%)" +} diff --git a/lib/sub/decompress-rle.asm b/lib/sub/decompress-rle.asm new file mode 100644 index 0000000..2584c8e --- /dev/null +++ b/lib/sub/decompress-rle.asm @@ -0,0 +1,68 @@ +/* + * MIT License + * + * Copyright (c) 2017-2023 c64lib + * Copyright (c) 2017-2023 Maciej Małecki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#import "../invoke.asm" + +.namespace c64lib { + + /* + * Stack: + * source address (2 bytes) + * dest address (2 bytes) + */ + decompressRLE: { + invokeStackBegin(returnPtr) + pullParamW(destination) + pullParamW(source) + invokeStackEnd(returnPtr) + + nextSequence: + jsr loadSource + cmp #0 + beq end // end mark + tax // x <- run length + jsr loadSource // a <- run value + decrunch: + sta destination:$ffff + inc destination + bne !+ + inc destination + 1 + !: + dex + bne decrunch + jmp nextSequence + + end: + rts + loadSource: + lda source:$ffff + inc source + bne !+ + inc source + 1 + !: + rts + // locals + returnPtr: .word 0 + } +} \ No newline at end of file diff --git a/spec/decompress-rle.spec.asm b/spec/decompress-rle.spec.asm new file mode 100644 index 0000000..f0f045d --- /dev/null +++ b/spec/decompress-rle.spec.asm @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (c) 2017-2023 c64lib + * Copyright (c) 2017-2023 Maciej Małecki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#import "64spec/lib/64spec.asm" +#import "../lib/compress-global.asm" +#import "../lib/invoke-global.asm" + +.var testData = LoadBinary("decompress-rle.test-data.txt") + +sfspec: init_spec() + describe("decompressRLE") + + it("decompress data"); { + c64lib_pushParamW(compressedData) + c64lib_pushParamW(targetData) + jsr decompressRLE + + assert_bytes_equal testData.getSize(): targetData: originalData + } +finish_spec() + +* = * "Data" +decompressRLE: + #import "../lib/sub/decompress-rle.asm" + +originalData: + .fill testData.getSize(), testData.get(i) +originalDataEnd: + +compressedData: + c64lib_compressRLE(testData) +compressedDataEnd: + +targetData: + .fill testData.getSize(), 0 +targetDataEnd: diff --git a/spec/decompress-rle.test-data.txt b/spec/decompress-rle.test-data.txt new file mode 100644 index 0000000..74f02ac --- /dev/null +++ b/spec/decompress-rle.test-data.txt @@ -0,0 +1 @@ +wegiel drogi to i atari nie dziala \ No newline at end of file