diff --git a/.idea/libraries/Maven__se_triad_kickass_kickass_cruncher_plugins_2_0.xml b/.idea/libraries/Maven__se_triad_kickass_kickass_cruncher_plugins_2_0.xml
new file mode 100644
index 000000000..b6d7699cf
--- /dev/null
+++ b/.idea/libraries/Maven__se_triad_kickass_kickass_cruncher_plugins_2_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NOTICE.txt b/NOTICE.txt
index fd23bfde0..75fa4646d 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,23 +1,77 @@
3rd Party Licenses
-- Toiletrensdyr SID is redistributed by personal permission from Søren Lund
- KickAssembler is redistributed by personal permission from Mads Nielsen
- KickAssembler65CE02 is a modified version of KickAssembler by myself (Jesper Gravgaard)
+- Toiletrensdyr SID is redistributed by personal permission from Søren Lund
+- kickass-cruncher-plugins by P-a Bäckström is redistributed under MIT License
+- kickass-plugin-atari-xex by myself (Jesper Gravgaard) is redistributed under MIT License
- ANTLR4 is redistributed under BSD License
- PICOCLI is redistributed under Apache License 2.0
- JAVAX.JSON JSR 374 (JSON Processing) Default Provider and API is is redistributed under COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1
-
--------------------------------------------------
-Toiletrensdyr - https://csdb.dk/sid/?id=54859
--------------------------------------------------
-
-------------------------------------------------
KickAssembler - https://theweb.dk/KickAssembler/
+Created by Mads Nielsen
-------------------------------------------------
-------------------------------------------------
KickAssembler65CE02 - https://gitlab.com/jespergravgaard/kickassembler65ce02
+KickAssembler created by Mads Nielsen - modified by Jesper Gravgaard
-------------------------------------------------
+-------------------------------------------------
+Toiletrensdyr - https://csdb.dk/sid/?id=54859
+Created by Søren Lund
+-------------------------------------------------
+
+-------------------------------------------------
+kickass-cruncher-plugins - KickAss Cruncher Plugins - https://github.com/p-a/kickass-cruncher-plugins
+-------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2013 P-a Bäckström
+
+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.
+
+-------------------------------------------------
+kickass-plugin-atari-xex - Kick Assembler Atari XEX Format Plugin - https://gitlab.com/jespergravgaard/kickass-plugin-atari-xex
+-------------------------------------------------
+
+MIT License
+
+Copyright (c) 2020 Jesper Balman Gravgaard
+
+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.
+
-------------------------------------------------
ANTLR4 - http://www.antlr.org/
-------------------------------------------------
diff --git a/kickc.iml b/kickc.iml
index f0fdbded5..22a8da212 100644
--- a/kickc.iml
+++ b/kickc.iml
@@ -27,5 +27,6 @@
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2bf2475ef..457d65922 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,11 @@
kickassxexformat
1.3
+
+ se.triad.kickass
+ kickass-cruncher-plugins
+ 2.0
+
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/_remote.repositories b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/_remote.repositories
new file mode 100644
index 000000000..ad4140ce1
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Wed Dec 30 19:02:11 CET 2020
+kickass-cruncher-plugins-2.0.jar>=
+kickass-cruncher-plugins-2.0.pom>=
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar
new file mode 100644
index 000000000..006925dec
Binary files /dev/null and b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar differ
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.md5 b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.md5
new file mode 100644
index 000000000..151023a62
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.md5
@@ -0,0 +1 @@
+447c4814f5ec16eb83c11beb3b01d31e
\ No newline at end of file
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.sha1 b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.sha1
new file mode 100644
index 000000000..ffd0ea58a
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.jar.sha1
@@ -0,0 +1 @@
+6bf3f7ab6484422cab660080f9c52e32fd1a3494
\ No newline at end of file
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom
new file mode 100644
index 000000000..56188317d
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom
@@ -0,0 +1,9 @@
+
+
+ 4.0.0
+ se.triad.kickass
+ kickass-cruncher-plugins
+ 2.0
+ POM was created from install:install-file
+
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.md5 b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.md5
new file mode 100644
index 000000000..880f6cb6d
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.md5
@@ -0,0 +1 @@
+8df79d73d4bb320c097875441b02c73f
\ No newline at end of file
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.sha1 b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.sha1
new file mode 100644
index 000000000..475b55bc4
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/2.0/kickass-cruncher-plugins-2.0.pom.sha1
@@ -0,0 +1 @@
+0a9df4151d0ac74eb6faba472ed7f0aa7fb1f330
\ No newline at end of file
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml
new file mode 100644
index 000000000..8af2f2250
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml
@@ -0,0 +1,12 @@
+
+
+ se.triad.kickass
+ kickass-cruncher-plugins
+
+ 2.0
+
+ 2.0
+
+ 20201230180211
+
+
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.md5 b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.md5
new file mode 100644
index 000000000..747f1dc75
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.md5
@@ -0,0 +1 @@
+ab025b6956bb8dc32185f8a6e084762d
\ No newline at end of file
diff --git a/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.sha1 b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.sha1
new file mode 100644
index 000000000..98c606414
--- /dev/null
+++ b/repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml.sha1
@@ -0,0 +1 @@
+22b621912e62295723e7aa4e9614b2032ac4377b
\ No newline at end of file
diff --git a/src/main/repo/mvn-repo-install-cruncherplugins.sh b/src/main/repo/mvn-repo-install-cruncherplugins.sh
new file mode 100755
index 000000000..04bb9468c
--- /dev/null
+++ b/src/main/repo/mvn-repo-install-cruncherplugins.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+# Prepare by making the "official" metadata local
+cp ./repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata.xml ./repo/se/triad/kickass/kickass-cruncher-plugins/maven-metadata-local.xml
+
+mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Users/jespergravgaard/c64/cruncher-plugins/releases/kickass-cruncher-plugins-2.0/kickass-cruncher-plugins-2.0.jar -DgroupId=se.triad.kickass -DartifactId=kickass-cruncher-plugins -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=2.0
+
+# Finalize by making the local metadata official
+pushd ./repo/se/triad/kickass/kickass-cruncher-plugins/
+mv maven-metadata-local.xml maven-metadata.xml
+mv maven-metadata-local.xml.md5 maven-metadata.xml.md5
+mv maven-metadata-local.xml.sha1 maven-metadata.xml.sha1
+popd
+
+# Remove stuff that Maven adds, that we don't need
+rm -rf ./repo/classworlds
+rm -rf ./repo/junit
+rm -rf ./repo/org
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 85e4c2174..84c73a6d1 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -3388,6 +3388,16 @@ public class TestPrograms {
compileAndCompare("examples/music/music_irq.c");
}
+ @Test
+ public void testCrunchingExomizer() throws IOException, URISyntaxException {
+ compileAndCompare("examples/crunching/test-exomizer.c");
+ }
+
+ @Test
+ public void testCrunchingByteboozer() throws IOException, URISyntaxException {
+ compileAndCompare("examples/crunching/test-byteboozer.c");
+ }
+
@Test
public void testMusic() throws IOException, URISyntaxException {
compileAndCompare("examples/music/music.c");
diff --git a/src/test/kc/examples/crunching/byteboozer.c b/src/test/kc/examples/crunching/byteboozer.c
new file mode 100644
index 000000000..fb2de1d1f
--- /dev/null
+++ b/src/test/kc/examples/crunching/byteboozer.c
@@ -0,0 +1,18 @@
+// ByteBoozer decruncher
+// https://github.com/p-a/kickass-cruncher-plugins
+
+// Decrunch crunched data using ByteBoozer
+// - crunched: Pointer to the start of the crunched data
+void byteboozer_decrunch(char* crunched) {
+ asm {
+ ldy crunched
+ ldx crunched+1
+ jsr b2.Decrunch
+ }
+}
+
+// The byteboozer decruncher
+export char BYTEBOOZER[] = kickasm(resource "byteboozer_decrunch.asm") {{
+ .const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+}};
\ No newline at end of file
diff --git a/src/test/kc/examples/crunching/byteboozer.h b/src/test/kc/examples/crunching/byteboozer.h
new file mode 100644
index 000000000..7fabd299e
--- /dev/null
+++ b/src/test/kc/examples/crunching/byteboozer.h
@@ -0,0 +1,6 @@
+// ByteBoozer decruncher
+// https://github.com/p-a/kickass-cruncher-plugins
+
+// Decrunch crunched data using ByteBoozer
+// - crunched: Pointer to the start of the crunched data
+void byteboozer_decrunch(char* crunched);
diff --git a/src/test/kc/examples/crunching/byteboozer_decrunch.asm b/src/test/kc/examples/crunching/byteboozer_decrunch.asm
new file mode 100644
index 000000000..a5ae4daca
--- /dev/null
+++ b/src/test/kc/examples/crunching/byteboozer_decrunch.asm
@@ -0,0 +1,182 @@
+// ByteBoozer Decruncher /HCL May.2003
+// B2 Decruncher December 2014
+
+.importonce
+.filenamespace b2
+
+// You must set .const B2_ZP_BASE prior the import of this file
+.if (B2_ZP_BASE > $ff) {
+ .error "B2_ZP_BASE must be in zeropage. Was $" + toHexString(B2_ZP_BASE,4)
+}
+
+
+.label zp_base = B2_ZP_BASE
+.label bits = zp_base
+.label put = zp_base + 2
+
+.macro @B2_DECRUNCH(addr) {
+ ldy #addr
+ jsr b2.Decrunch
+}
+
+.macro GetNextBit() {
+ asl bits
+ bne DgEnd
+ jsr GetNewBits
+DgEnd:
+}
+
+.macro GetLen() {
+ lda #1
+GlLoop:
+ :GetNextBit()
+ bcc GlEnd
+ :GetNextBit()
+ rol
+ bpl GlLoop
+GlEnd:
+}
+
+Decrunch:
+ sty Get1+1
+ sty Get2+1
+ sty Get3+1
+ stx Get1+2
+ stx Get2+2
+ stx Get3+2
+
+ ldx #0
+ jsr GetNewBits
+ sty put-1,x
+ cpx #2
+ bcc *-7
+ lda #$80
+ sta bits
+DLoop:
+ :GetNextBit()
+ bcs Match
+Literal:
+ // Literal run.. get length.
+ :GetLen()
+ sta LLen+1
+
+ ldy #0
+LLoop:
+Get3:
+ lda $feed,x
+ inx
+ bne *+5
+ jsr GnbInc
+L1: sta (put),y
+ iny
+LLen:
+ cpy #0
+ bne LLoop
+
+ clc
+ tya
+ adc put
+ sta put
+ bcc *+4
+ inc put+1
+
+ iny
+ beq DLoop
+
+ // Has to continue with a match..
+
+Match:
+ // Match.. get length.
+ :GetLen()
+ sta MLen+1
+
+ // Length 255 -> EOF
+ cmp #$ff
+ beq End
+
+ // Get num bits
+ cmp #2
+ lda #0
+ rol
+ :GetNextBit()
+ rol
+ :GetNextBit()
+ rol
+ tay
+ lda Tab,y
+ beq M8
+
+ // Get bits < 8
+M_1:
+ :GetNextBit()
+ rol
+ bcs M_1
+ bmi MShort
+M8:
+ // Get byte
+ eor #$ff
+ tay
+Get2:
+ lda $feed,x
+ inx
+ bne *+5
+ jsr GnbInc
+ jmp Mdone
+MShort:
+ ldy #$ff
+Mdone:
+ //clc
+ adc put
+ sta MLda+1
+ tya
+ adc put+1
+ sta MLda+2
+
+ ldy #$ff
+MLoop:
+ iny
+MLda:
+ lda $beef,y
+ sta (put),y
+MLen:
+ cpy #0
+ bne MLoop
+
+ //sec
+ tya
+ adc put
+ sta put
+ bcc *+4
+ inc put+1
+
+ jmp DLoop
+
+End:
+ rts
+
+GetNewBits:
+Get1:
+ ldy $feed,x
+ sty bits
+ rol bits
+ inx
+ bne GnbEnd
+GnbInc:
+ inc Get1+2
+ inc Get2+2
+ inc Get3+2
+GnbEnd:
+ rts
+
+Tab:
+ // Short offsets
+ .byte %11011111 // 3
+ .byte %11111011 // 6
+ .byte %00000000 // 8
+ .byte %10000000 // 10
+ // Long offsets
+ .byte %11101111 // 4
+ .byte %11111101 // 7
+ .byte %10000000 // 10
+ .byte %11110000 // 13
diff --git a/src/test/kc/examples/crunching/crunching.ld b/src/test/kc/examples/crunching/crunching.ld
new file mode 100644
index 000000000..e1997932b
--- /dev/null
+++ b/src/test/kc/examples/crunching/crunching.ld
@@ -0,0 +1,9 @@
+// Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="%O", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=%P]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(%E)
\ No newline at end of file
diff --git a/src/test/kc/examples/crunching/exomizer_decrunch.asm b/src/test/kc/examples/crunching/exomizer_decrunch.asm
new file mode 100644
index 000000000..628ff1a22
--- /dev/null
+++ b/src/test/kc/examples/crunching/exomizer_decrunch.asm
@@ -0,0 +1,354 @@
+.importonce
+
+//
+// Copyright (c) 2002 - 2005 Magnus Lind.
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from
+// the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented// you must not
+// claim that you wrote the original software. If you use this software in a
+// product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any distribution.
+//
+// 4. The names of this software and/or it's copyright holders may not be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// -------------------------------------------------------------------
+// The decruncher jsr:s to the get_crunched_byte address when it wants to
+// read a crunched byte. This subroutine has to preserve x and y register
+// and must not modify the state of the carry flag.
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// this function is the heart of the decruncher.
+// It initializes the decruncher zeropage locations and precalculates the
+// decrunch tables and decrunches the data
+// This function will not change the interrupt status bit and it will not
+// modify the memory configuration.
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// if literal sequences is not used (the data was crunched with the -c
+// flag) then the following line can be uncommented for shorter code.
+
+
+// KICKASMIFIED BY RUK / TRIAD 2012 -
+
+// -------------------------------------------------------------------
+// zero page addresses used - define in EXO_ZP_BASE
+// -------------------------------------------------------------------
+
+.macro EXO_DECRUNCH(end_addr){
+ lda #end_addr
+ sta exodecr.zp_getb_hi
+ jsr exodecr.decrunch
+}
+
+.namespace exodecr {
+
+.label zp_len_lo = EXO_ZP_BASE
+
+.label zp_src_lo = zp_len_lo + 1
+.label zp_src_hi = zp_src_lo + 1
+
+.label zp_bits_hi = zp_src_hi + 1
+
+.label zp_bitbuf = zp_bits_hi + 1
+.label zp_dest_lo = zp_bitbuf + 1 // dest addr lo
+.label zp_dest_hi = zp_bitbuf + 2 // dest addr hi
+
+.label zp_getb_lo = zp_dest_hi + 1
+.label zp_getb_hi = zp_getb_lo + 1
+
+.label tabl_bi = EXO_DECRUNCH_TABLE
+.label tabl_lo = EXO_DECRUNCH_TABLE + 52
+.label tabl_hi = EXO_DECRUNCH_TABLE + 104
+
+// -------------------------------------------------------------------
+// no code below this comment has to be modified in order to generate
+// a working decruncher of this source file.
+// However, you may want to relocate the tables last in the file to a
+// more suitable address.
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// jsr this label to decrunch, it will in turn init the tables and
+// call the decruncher
+// no constraints on register content, however the
+// decimal flag has to be #0 (it almost always is, otherwise do a cld)
+
+.pseudocommand get_crunched_byte {
+
+ sty tmpy
+
+ lda zp_getb_lo
+ bne !+
+ dec zp_getb_hi
+ !:
+ dec zp_getb_lo
+
+ ldy #0
+ lda (zp_getb_lo),y
+
+ ldy #00
+ .label tmpy = * - 1
+}
+
+decrunch:
+// -------------------------------------------------------------------
+// init zeropage, x and y regs. (12 bytes)
+//
+ ldy #0
+ ldx #3
+init_zp:
+ :get_crunched_byte
+ sta zp_bitbuf - 1,x
+ dex
+ bne init_zp
+// -------------------------------------------------------------------
+// calculate tables (50 bytes)
+// x and y must be #0 when entering
+//
+nextone:
+ inx
+ tya
+ and #$0f
+ beq shortcut // starta p� ny sekvens
+
+ txa // this clears reg a
+ lsr // and sets the carry flag
+ ldx tabl_bi-1,y
+rolle:
+ rol
+ rol zp_bits_hi
+ dex
+ bpl rolle // c = 0 after this (rol zp_bits_hi)
+
+ adc tabl_lo-1,y
+ tax
+
+ lda zp_bits_hi
+ adc tabl_hi-1,y
+shortcut:
+ sta tabl_hi,y
+ txa
+ sta tabl_lo,y
+
+ ldx #4
+ jsr get_bits // clears x-reg.
+ sta tabl_bi,y
+ iny
+ cpy #52
+ bne nextone
+ ldy #0
+ beq begin
+// -------------------------------------------------------------------
+// get bits (29 bytes)
+//
+// args:
+// x = number of bits to get
+// returns:
+// a = #bits_lo
+// x = #0
+// c = 0
+// z = 1
+// zp_bits_hi = #bits_hi
+// notes:
+// y is untouched
+// -------------------------------------------------------------------
+get_bits:
+ lda #$00
+ sta zp_bits_hi
+ cpx #$01
+ bcc bits_done
+bits_next:
+ lsr zp_bitbuf
+ bne ok
+ pha
+literal_get_byte:
+ :get_crunched_byte
+ bcc literal_byte_gotten
+ ror
+ sta zp_bitbuf
+ pla
+ok:
+ rol
+ rol zp_bits_hi
+ dex
+ bne bits_next
+bits_done:
+ rts
+// -------------------------------------------------------------------
+// main copy loop (18(16) bytes)
+//
+copy_next_hi:
+ dex
+ dec zp_dest_hi
+ dec zp_src_hi
+copy_next:
+ dey
+.if (EXO_LITERAL_SEQUENCES_USED) {
+ bcc literal_get_byte
+}
+ lda (zp_src_lo),y
+literal_byte_gotten:
+ sta (zp_dest_lo),y
+copy_start:
+ tya
+ bne copy_next
+begin:
+ txa
+ bne copy_next_hi
+// -------------------------------------------------------------------
+// decruncher entry point, needs calculated tables (21(13) bytes)
+// x and y must be #0 when entering
+//
+.if (EXO_LITERAL_SEQUENCES_USED){
+ inx
+ jsr get_bits
+ tay
+ bne literal_start1
+} else {
+ dey
+}
+
+begin2:
+ inx
+ jsr bits_next
+ lsr
+ iny
+ bcc begin2
+.if (!EXO_LITERAL_SEQUENCES_USED){
+ beq literal_start
+}
+ cpy #$11
+
+.label literal_start1 = * + 9
+.if (EXO_LITERAL_SEQUENCES_USED){
+ bcc sequence_start
+ beq bits_done
+// -------------------------------------------------------------------
+// literal sequence handling (13(2) bytes)
+
+ ldx #$10
+ jsr get_bits
+literal_start1_real:
+ sta
+#include "byteboozer.h"
+
+// Address to decrunch the sprite to
+char * const SPRITE = 0x2000;
+
+// The sprite pointers
+char * const SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS;
+
+void main() {
+ // Decrunch sprite file into memory
+ byteboozer_decrunch(CRUNCHED_SPRITE);
+ // Show the loaded sprite on screen
+ VICII->SPRITES_ENABLE = %00000001;
+ SPRITES_PTR[0] = toSpritePtr(SPRITE);
+ SPRITES_COLOR[0] = GREEN;
+ SPRITES_XPOS[0] = 0x15;
+ SPRITES_YPOS[0] = 0x33;
+}
+
+// Array with crunched data created using inline kickasm
+export char CRUNCHED_SPRITE[] = kickasm(uses SPRITE, resource "sprite.png") {{
+ .modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+}};
\ No newline at end of file
diff --git a/src/test/kc/examples/crunching/test-exomizer.c b/src/test/kc/examples/crunching/test-exomizer.c
new file mode 100644
index 000000000..b4de19817
--- /dev/null
+++ b/src/test/kc/examples/crunching/test-exomizer.c
@@ -0,0 +1,46 @@
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// Exomizer Example
+// https://github.com/p-a/kickass-cruncher-plugins
+
+#pragma target(c64)
+#pragma link("crunching.ld")
+#include
+
+// Address to decrunch the sprite to
+char * const SPRITE = 0x2000;
+
+char * const SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS;
+
+void main() {
+ // Decrunch sprite file into memory
+ kickasm {{
+ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+ }}
+ // Show the loaded sprite on screen
+ VICII->SPRITES_ENABLE = %00000001;
+ SPRITES_PTR[0] = toSpritePtr(SPRITE);
+ SPRITES_COLOR[0] = GREEN;
+ SPRITES_XPOS[0] = 0x15;
+ SPRITES_YPOS[0] = 0x33;
+}
+
+// The exomizer decruncher
+export char EXOMIZER[] = kickasm(resource "exomizer_decrunch.asm") {{
+ .const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+}};
+
+// Array with crunched data created using inline kickasm
+export char CRUNCHED_SPRITE[] = kickasm(uses SPRITE, resource "sprite.png") {{
+ .modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+}};
+
diff --git a/src/test/ref/examples/crunching/test-byteboozer.asm b/src/test/ref/examples/crunching/test-byteboozer.asm
new file mode 100644
index 000000000..74c9bbe82
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-byteboozer.asm
@@ -0,0 +1,84 @@
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// ByteBoozer example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-byteboozer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ // The sprite pointers
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // byteboozer_decrunch(CRUNCHED_SPRITE)
+ lda #CRUNCHED_SPRITE
+ sta.z byteboozer_decrunch.crunched+1
+ // Decrunch sprite file into memory
+ jsr byteboozer_decrunch
+ // VICII->SPRITES_ENABLE = %00000001
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // SPRITES_PTR[0] = toSpritePtr(SPRITE)
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // SPRITES_COLOR[0] = GREEN
+ lda #GREEN
+ sta SPRITES_COLOR
+ // SPRITES_XPOS[0] = 0x15
+ lda #$15
+ sta SPRITES_XPOS
+ // SPRITES_YPOS[0] = 0x33
+ lda #$33
+ sta SPRITES_YPOS
+ // }
+ rts
+}
+// Decrunch crunched data using ByteBoozer
+// - crunched: Pointer to the start of the crunched data
+// byteboozer_decrunch(byte* zp(2) crunched)
+byteboozer_decrunch: {
+ .label crunched = 2
+ // asm
+ ldy crunched
+ ldx crunched+1
+ jsr b2.Decrunch
+ // }
+ rts
+}
+.segment Data
+// The byteboozer decruncher
+BYTEBOOZER:
+.const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+
diff --git a/src/test/ref/examples/crunching/test-byteboozer.cfg b/src/test/ref/examples/crunching/test-byteboozer.cfg
new file mode 100644
index 000000000..7cc76388f
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-byteboozer.cfg
@@ -0,0 +1,29 @@
+
+void main()
+main: scope:[main] from
+ [0] byteboozer_decrunch::crunched = CRUNCHED_SPRITE
+ [1] call byteboozer_decrunch
+ to:main::@2
+main::@2: scope:[main] from main
+ [2] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main::@2
+ [3] phi()
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1
+ [4] *SPRITES_PTR = main::toSpritePtr1_return#0
+ [5] *SPRITES_COLOR = GREEN
+ [6] *SPRITES_XPOS = $15
+ [7] *SPRITES_YPOS = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ [8] return
+ to:@return
+
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+byteboozer_decrunch: scope:[byteboozer_decrunch] from main
+ asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+ to:byteboozer_decrunch::@return
+byteboozer_decrunch::@return: scope:[byteboozer_decrunch] from byteboozer_decrunch
+ [10] return
+ to:@return
diff --git a/src/test/ref/examples/crunching/test-byteboozer.log b/src/test/ref/examples/crunching/test-byteboozer.log
new file mode 100644
index 000000000..84e54b6fb
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-byteboozer.log
@@ -0,0 +1,508 @@
+Loading link script "crunching.ld"
+Resolved forward reference CRUNCHED_SPRITE to CRUNCHED_SPRITE
+Setting inferred volatile on symbol affected by address-of: byteboozer_decrunch::crunched in asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+Inlined call vicSelectGfxBank::$0 = call toDd00 vicSelectGfxBank::gfx
+Inlined call main::$1 = call toSpritePtr SPRITE
+
+CONTROL FLOW GRAPH SSA
+
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+byteboozer_decrunch: scope:[byteboozer_decrunch] from main
+ asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+ to:byteboozer_decrunch::@return
+byteboozer_decrunch::@return: scope:[byteboozer_decrunch] from byteboozer_decrunch
+ return
+ to:@return
+
+void main()
+main: scope:[main] from __start
+ byteboozer_decrunch::crunched = CRUNCHED_SPRITE
+ call byteboozer_decrunch
+ to:main::@2
+main::@2: scope:[main] from main
+ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ main::toSpritePtr1_sprite#0 = SPRITE
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main::@2
+ main::toSpritePtr1_sprite#1 = phi( main::@2/main::toSpritePtr1_sprite#0 )
+ main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#1
+ main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+ main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0
+ to:main::toSpritePtr1_@return
+main::toSpritePtr1_@return: scope:[main] from main::toSpritePtr1
+ main::toSpritePtr1_return#2 = phi( main::toSpritePtr1/main::toSpritePtr1_return#0 )
+ main::toSpritePtr1_return#1 = main::toSpritePtr1_return#2
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1_@return
+ main::toSpritePtr1_return#3 = phi( main::toSpritePtr1_@return/main::toSpritePtr1_return#1 )
+ main::$1 = main::toSpritePtr1_return#3
+ SPRITES_PTR[0] = main::$1
+ SPRITES_COLOR[0] = GREEN
+ SPRITES_XPOS[0] = $15
+ SPRITES_YPOS[0] = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ return
+ to:@return
+
+void __start()
+__start: scope:[__start] from
+ call main
+ to:__start::@1
+__start::@1: scope:[__start] from __start
+ to:__start::@return
+__start::@return: scope:[__start] from __start::@1
+ return
+ to:@return
+
+SYMBOL TABLE SSA
+const byte* BYTEBOOZER[] = kickasm {{ .const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+ }}
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*)$400
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*)$2000
+const nomodify byte* SPRITES_COLOR = (byte*)$d027
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*)$d000
+const nomodify byte* SPRITES_YPOS = (byte*)$d001
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*)$d000
+void __start()
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+volatile byte* byteboozer_decrunch::crunched loadstore
+void main()
+byte~ main::$1
+number~ main::toSpritePtr1_$0
+word~ main::toSpritePtr1_$1
+byte main::toSpritePtr1_return
+byte main::toSpritePtr1_return#0
+byte main::toSpritePtr1_return#1
+byte main::toSpritePtr1_return#2
+byte main::toSpritePtr1_return#3
+byte* main::toSpritePtr1_sprite
+byte* main::toSpritePtr1_sprite#0
+byte* main::toSpritePtr1_sprite#1
+
+Adding number conversion cast (unumber) 1 in *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+Adding number conversion cast (unumber) $40 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Adding number conversion cast (unumber) main::toSpritePtr1_$0 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / (unumber)$40
+Adding number conversion cast (unumber) 0 in SPRITES_PTR[0] = main::$1
+Adding number conversion cast (unumber) 0 in SPRITES_COLOR[0] = GREEN
+Adding number conversion cast (unumber) $15 in SPRITES_XPOS[0] = $15
+Adding number conversion cast (unumber) 0 in SPRITES_XPOS[0] = ((unumber)) $15
+Adding number conversion cast (unumber) $33 in SPRITES_YPOS[0] = $33
+Adding number conversion cast (unumber) 0 in SPRITES_YPOS[0] = ((unumber)) $33
+Successful SSA optimization PassNAddNumberTypeConversions
+Inlining cast *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = (unumber)1
+Inlining cast SPRITES_XPOS[(unumber)0] = (unumber)$15
+Inlining cast SPRITES_YPOS[(unumber)0] = (unumber)$33
+Successful SSA optimization Pass2InlineCast
+Simplifying constant pointer cast (byte*) 53248
+Simplifying constant pointer cast (byte*) 53249
+Simplifying constant pointer cast (byte*) 53287
+Simplifying constant pointer cast (struct MOS6569_VICII*) 53248
+Simplifying constant pointer cast (byte*) 1024
+Simplifying constant pointer cast (byte*) 8192
+Simplifying constant integer cast 1
+Simplifying constant integer cast $40
+Simplifying constant integer cast 0
+Simplifying constant integer cast 0
+Simplifying constant integer cast $15
+Simplifying constant integer cast 0
+Simplifying constant integer cast $33
+Simplifying constant integer cast 0
+Successful SSA optimization PassNCastSimplification
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) $40
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) $15
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) $33
+Finalized unsigned number type (byte) 0
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+Inferred type updated to word in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Alias main::toSpritePtr1_sprite#0 = main::toSpritePtr1_sprite#1
+Alias main::toSpritePtr1_return#0 = main::toSpritePtr1_return#2 main::toSpritePtr1_return#1 main::toSpritePtr1_return#3 main::$1
+Successful SSA optimization Pass2AliasElimination
+Constant main::toSpritePtr1_sprite#0 = SPRITE
+Successful SSA optimization Pass2ConstantIdentification
+Constant main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#0
+Successful SSA optimization Pass2ConstantIdentification
+Simplifying expression containing zero SPRITES_PTR in [9] SPRITES_PTR[0] = main::toSpritePtr1_return#0
+Simplifying expression containing zero SPRITES_COLOR in [10] SPRITES_COLOR[0] = GREEN
+Simplifying expression containing zero SPRITES_XPOS in [11] SPRITES_XPOS[0] = $15
+Simplifying expression containing zero SPRITES_YPOS in [12] SPRITES_YPOS[0] = $33
+Successful SSA optimization PassNSimplifyExpressionWithZero
+Removing unused procedure __start
+Removing unused procedure block __start
+Removing unused procedure block __start::@1
+Removing unused procedure block __start::@return
+Successful SSA optimization PassNEliminateEmptyStart
+Constant right-side identified [5] main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant main::toSpritePtr1_$0 = main::toSpritePtr1_$1/$40
+Successful SSA optimization Pass2ConstantIdentification
+Constant main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0
+Successful SSA optimization Pass2ConstantIdentification
+Constant inlined main::toSpritePtr1_sprite#0 = SPRITE
+Constant inlined main::toSpritePtr1_$1 = (word)SPRITE
+Constant inlined main::toSpritePtr1_$0 = (word)SPRITE/$40
+Successful SSA optimization Pass2ConstantInlining
+Adding NOP phi() at start of main::toSpritePtr1
+Adding NOP phi() at start of main::toSpritePtr1_@return
+CALL GRAPH
+Calls in [main] to byteboozer_decrunch:1
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+Culled Empty Block label main::toSpritePtr1_@return
+Adding NOP phi() at start of main::toSpritePtr1
+
+FINAL CONTROL FLOW GRAPH
+
+void main()
+main: scope:[main] from
+ [0] byteboozer_decrunch::crunched = CRUNCHED_SPRITE
+ [1] call byteboozer_decrunch
+ to:main::@2
+main::@2: scope:[main] from main
+ [2] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main::@2
+ [3] phi()
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1
+ [4] *SPRITES_PTR = main::toSpritePtr1_return#0
+ [5] *SPRITES_COLOR = GREEN
+ [6] *SPRITES_XPOS = $15
+ [7] *SPRITES_YPOS = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ [8] return
+ to:@return
+
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+byteboozer_decrunch: scope:[byteboozer_decrunch] from main
+ asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+ to:byteboozer_decrunch::@return
+byteboozer_decrunch::@return: scope:[byteboozer_decrunch] from byteboozer_decrunch
+ [10] return
+ to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+volatile byte* byteboozer_decrunch::crunched loadstore 2.0
+void main()
+byte main::toSpritePtr1_return
+byte* main::toSpritePtr1_sprite
+
+Initial phi equivalence classes
+Added variable byteboozer_decrunch::crunched to live range equivalence class [ byteboozer_decrunch::crunched ]
+Complete equivalence classes
+[ byteboozer_decrunch::crunched ]
+Allocated zp[2]:2 [ byteboozer_decrunch::crunched ]
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [0] byteboozer_decrunch::crunched = CRUNCHED_SPRITE [ byteboozer_decrunch::crunched ] ( [ byteboozer_decrunch::crunched ] { } ) always clobbers reg byte a
+Statement [2] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [4] *SPRITES_PTR = main::toSpritePtr1_return#0 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [5] *SPRITES_COLOR = GREEN [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [6] *SPRITES_XPOS = $15 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [7] *SPRITES_YPOS = $33 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch } always clobbers reg byte a reg byte x reg byte y
+Potential registers zp[2]:2 [ byteboozer_decrunch::crunched ] : zp[2]:2 ,
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [byteboozer_decrunch] 2: zp[2]:2 [ byteboozer_decrunch::crunched ]
+Uplift Scope [MOS6526_CIA]
+Uplift Scope [MOS6569_VICII]
+Uplift Scope [MOS6581_SID]
+Uplift Scope [main]
+Uplift Scope []
+
+Uplifting [byteboozer_decrunch] best 114 combination zp[2]:2 [ byteboozer_decrunch::crunched ]
+Uplifting [MOS6526_CIA] best 114 combination
+Uplifting [MOS6569_VICII] best 114 combination
+Uplifting [MOS6581_SID] best 114 combination
+Uplifting [main] best 114 combination
+Uplifting [] best 114 combination
+
+ASSEMBLER BEFORE OPTIMIZATION
+ // File Comments
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// ByteBoozer example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Upstart
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-byteboozer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // Global Constants & labels
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ // The sprite pointers
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+ // main
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // [0] byteboozer_decrunch::crunched = CRUNCHED_SPRITE -- pbuz1=pbuc1
+ lda #CRUNCHED_SPRITE
+ sta.z byteboozer_decrunch.crunched+1
+ // [1] call byteboozer_decrunch
+ // Decrunch sprite file into memory
+ jsr byteboozer_decrunch
+ jmp __b2
+ // main::@2
+ __b2:
+ // [2] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // [3] phi from main::@2 to main::toSpritePtr1 [phi:main::@2->main::toSpritePtr1]
+ toSpritePtr1_from___b2:
+ jmp toSpritePtr1
+ // main::toSpritePtr1
+ toSpritePtr1:
+ jmp __b1
+ // main::@1
+ __b1:
+ // [4] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // [5] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2
+ lda #GREEN
+ sta SPRITES_COLOR
+ // [6] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2
+ lda #$15
+ sta SPRITES_XPOS
+ // [7] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2
+ lda #$33
+ sta SPRITES_YPOS
+ jmp __breturn
+ // main::@return
+ __breturn:
+ // [8] return
+ rts
+}
+ // byteboozer_decrunch
+// Decrunch crunched data using ByteBoozer
+// - crunched: Pointer to the start of the crunched data
+// byteboozer_decrunch(byte* zp(2) crunched)
+byteboozer_decrunch: {
+ .label crunched = 2
+ // asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+ ldy crunched
+ ldx crunched+1
+ jsr b2.Decrunch
+ jmp __breturn
+ // byteboozer_decrunch::@return
+ __breturn:
+ // [10] return
+ rts
+}
+ // File Data
+.segment Data
+// The byteboozer decruncher
+BYTEBOOZER:
+.const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp __b2
+Removing instruction jmp toSpritePtr1
+Removing instruction jmp __b1
+Removing instruction jmp __breturn
+Removing instruction jmp __breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction toSpritePtr1_from___b2:
+Removing instruction toSpritePtr1:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction __b2:
+Removing instruction __b1:
+Removing instruction __breturn:
+Removing instruction __breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+const byte* BYTEBOOZER[] = kickasm {{ .const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+ }}
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*) 1024
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*) 8192
+const nomodify byte* SPRITES_COLOR = (byte*) 53287
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*) 53248
+const nomodify byte* SPRITES_YPOS = (byte*) 53249
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*) 53248
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+volatile byte* byteboozer_decrunch::crunched loadstore zp[2]:2 2.0
+void main()
+byte main::toSpritePtr1_return
+const byte main::toSpritePtr1_return#0 toSpritePtr1_return = (byte)(word)SPRITE/$40
+byte* main::toSpritePtr1_sprite
+
+zp[2]:2 [ byteboozer_decrunch::crunched ]
+
+
+FINAL ASSEMBLER
+Score: 72
+
+ // File Comments
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// ByteBoozer example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Upstart
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-byteboozer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // Global Constants & labels
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ // The sprite pointers
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+ // main
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // byteboozer_decrunch(CRUNCHED_SPRITE)
+ // [0] byteboozer_decrunch::crunched = CRUNCHED_SPRITE -- pbuz1=pbuc1
+ lda #CRUNCHED_SPRITE
+ sta.z byteboozer_decrunch.crunched+1
+ // [1] call byteboozer_decrunch
+ // Decrunch sprite file into memory
+ jsr byteboozer_decrunch
+ // main::@2
+ // VICII->SPRITES_ENABLE = %00000001
+ // [2] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // [3] phi from main::@2 to main::toSpritePtr1 [phi:main::@2->main::toSpritePtr1]
+ // main::toSpritePtr1
+ // main::@1
+ // SPRITES_PTR[0] = toSpritePtr(SPRITE)
+ // [4] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // SPRITES_COLOR[0] = GREEN
+ // [5] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2
+ lda #GREEN
+ sta SPRITES_COLOR
+ // SPRITES_XPOS[0] = 0x15
+ // [6] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2
+ lda #$15
+ sta SPRITES_XPOS
+ // SPRITES_YPOS[0] = 0x33
+ // [7] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2
+ lda #$33
+ sta SPRITES_YPOS
+ // main::@return
+ // }
+ // [8] return
+ rts
+}
+ // byteboozer_decrunch
+// Decrunch crunched data using ByteBoozer
+// - crunched: Pointer to the start of the crunched data
+// byteboozer_decrunch(byte* zp(2) crunched)
+byteboozer_decrunch: {
+ .label crunched = 2
+ // asm
+ // asm { ldycrunched ldxcrunched+1 jsrb2.Decrunch }
+ ldy crunched
+ ldx crunched+1
+ jsr b2.Decrunch
+ // byteboozer_decrunch::@return
+ // }
+ // [10] return
+ rts
+}
+ // File Data
+.segment Data
+// The byteboozer decruncher
+BYTEBOOZER:
+.const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+
+
diff --git a/src/test/ref/examples/crunching/test-byteboozer.sym b/src/test/ref/examples/crunching/test-byteboozer.sym
new file mode 100644
index 000000000..bdd9d0384
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-byteboozer.sym
@@ -0,0 +1,29 @@
+const byte* BYTEBOOZER[] = kickasm {{ .const B2_ZP_BASE = $fc
+ #import "byteboozer_decrunch.asm"
+ }}
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify B2() {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*) 1024
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*) 8192
+const nomodify byte* SPRITES_COLOR = (byte*) 53287
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*) 53248
+const nomodify byte* SPRITES_YPOS = (byte*) 53249
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*) 53248
+void byteboozer_decrunch(volatile byte* byteboozer_decrunch::crunched)
+volatile byte* byteboozer_decrunch::crunched loadstore zp[2]:2 2.0
+void main()
+byte main::toSpritePtr1_return
+const byte main::toSpritePtr1_return#0 toSpritePtr1_return = (byte)(word)SPRITE/$40
+byte* main::toSpritePtr1_sprite
+
+zp[2]:2 [ byteboozer_decrunch::crunched ]
diff --git a/src/test/ref/examples/crunching/test-exomizer.asm b/src/test/ref/examples/crunching/test-exomizer.asm
new file mode 100644
index 000000000..29d9ee650
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-exomizer.asm
@@ -0,0 +1,71 @@
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// Exomizer Example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-exomizer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // kickasm
+ // Decrunch sprite file into memory
+ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+
+ // VICII->SPRITES_ENABLE = %00000001
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // SPRITES_PTR[0] = toSpritePtr(SPRITE)
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // SPRITES_COLOR[0] = GREEN
+ lda #GREEN
+ sta SPRITES_COLOR
+ // SPRITES_XPOS[0] = 0x15
+ lda #$15
+ sta SPRITES_XPOS
+ // SPRITES_YPOS[0] = 0x33
+ lda #$33
+ sta SPRITES_YPOS
+ // }
+ rts
+}
+.segment Data
+// The exomizer decruncher
+EXOMIZER:
+.const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+
diff --git a/src/test/ref/examples/crunching/test-exomizer.cfg b/src/test/ref/examples/crunching/test-exomizer.cfg
new file mode 100644
index 000000000..5a97cef23
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-exomizer.cfg
@@ -0,0 +1,19 @@
+
+void main()
+main: scope:[main] from
+ kickasm() {{ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+ }}
+ [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main
+ [2] phi()
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1
+ [3] *SPRITES_PTR = main::toSpritePtr1_return#0
+ [4] *SPRITES_COLOR = GREEN
+ [5] *SPRITES_XPOS = $15
+ [6] *SPRITES_YPOS = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ [7] return
+ to:@return
diff --git a/src/test/ref/examples/crunching/test-exomizer.log b/src/test/ref/examples/crunching/test-exomizer.log
new file mode 100644
index 000000000..0ccc77105
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-exomizer.log
@@ -0,0 +1,432 @@
+Loading link script "crunching.ld"
+Inlined call vicSelectGfxBank::$0 = call toDd00 vicSelectGfxBank::gfx
+Inlined call main::$0 = call toSpritePtr SPRITE
+
+CONTROL FLOW GRAPH SSA
+
+void main()
+main: scope:[main] from __start
+ kickasm() {{ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+ }}
+ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ main::toSpritePtr1_sprite#0 = SPRITE
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main
+ main::toSpritePtr1_sprite#1 = phi( main/main::toSpritePtr1_sprite#0 )
+ main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#1
+ main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+ main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0
+ to:main::toSpritePtr1_@return
+main::toSpritePtr1_@return: scope:[main] from main::toSpritePtr1
+ main::toSpritePtr1_return#2 = phi( main::toSpritePtr1/main::toSpritePtr1_return#0 )
+ main::toSpritePtr1_return#1 = main::toSpritePtr1_return#2
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1_@return
+ main::toSpritePtr1_return#3 = phi( main::toSpritePtr1_@return/main::toSpritePtr1_return#1 )
+ main::$0 = main::toSpritePtr1_return#3
+ SPRITES_PTR[0] = main::$0
+ SPRITES_COLOR[0] = GREEN
+ SPRITES_XPOS[0] = $15
+ SPRITES_YPOS[0] = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ return
+ to:@return
+
+void __start()
+__start: scope:[__start] from
+ call main
+ to:__start::@1
+__start::@1: scope:[__start] from __start
+ to:__start::@return
+__start::@return: scope:[__start] from __start::@1
+ return
+ to:@return
+
+SYMBOL TABLE SSA
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*)$400
+const byte* EXOMIZER[] = kickasm {{ .const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+ }}
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*)$2000
+const nomodify byte* SPRITES_COLOR = (byte*)$d027
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*)$d000
+const nomodify byte* SPRITES_YPOS = (byte*)$d001
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*)$d000
+void __start()
+void main()
+byte~ main::$0
+number~ main::toSpritePtr1_$0
+word~ main::toSpritePtr1_$1
+byte main::toSpritePtr1_return
+byte main::toSpritePtr1_return#0
+byte main::toSpritePtr1_return#1
+byte main::toSpritePtr1_return#2
+byte main::toSpritePtr1_return#3
+byte* main::toSpritePtr1_sprite
+byte* main::toSpritePtr1_sprite#0
+byte* main::toSpritePtr1_sprite#1
+
+Adding number conversion cast (unumber) 1 in *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+Adding number conversion cast (unumber) $40 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Adding number conversion cast (unumber) main::toSpritePtr1_$0 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / (unumber)$40
+Adding number conversion cast (unumber) 0 in SPRITES_PTR[0] = main::$0
+Adding number conversion cast (unumber) 0 in SPRITES_COLOR[0] = GREEN
+Adding number conversion cast (unumber) $15 in SPRITES_XPOS[0] = $15
+Adding number conversion cast (unumber) 0 in SPRITES_XPOS[0] = ((unumber)) $15
+Adding number conversion cast (unumber) $33 in SPRITES_YPOS[0] = $33
+Adding number conversion cast (unumber) 0 in SPRITES_YPOS[0] = ((unumber)) $33
+Successful SSA optimization PassNAddNumberTypeConversions
+Inlining cast *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = (unumber)1
+Inlining cast SPRITES_XPOS[(unumber)0] = (unumber)$15
+Inlining cast SPRITES_YPOS[(unumber)0] = (unumber)$33
+Successful SSA optimization Pass2InlineCast
+Simplifying constant pointer cast (byte*) 53248
+Simplifying constant pointer cast (byte*) 53249
+Simplifying constant pointer cast (byte*) 53287
+Simplifying constant pointer cast (struct MOS6569_VICII*) 53248
+Simplifying constant pointer cast (byte*) 1024
+Simplifying constant pointer cast (byte*) 8192
+Simplifying constant integer cast 1
+Simplifying constant integer cast $40
+Simplifying constant integer cast 0
+Simplifying constant integer cast 0
+Simplifying constant integer cast $15
+Simplifying constant integer cast 0
+Simplifying constant integer cast $33
+Simplifying constant integer cast 0
+Successful SSA optimization PassNCastSimplification
+Finalized unsigned number type (byte) 1
+Finalized unsigned number type (byte) $40
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) $15
+Finalized unsigned number type (byte) 0
+Finalized unsigned number type (byte) $33
+Finalized unsigned number type (byte) 0
+Successful SSA optimization PassNFinalizeNumberTypeConversions
+Inferred type updated to word in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Alias main::toSpritePtr1_sprite#0 = main::toSpritePtr1_sprite#1
+Alias main::toSpritePtr1_return#0 = main::toSpritePtr1_return#2 main::toSpritePtr1_return#1 main::toSpritePtr1_return#3 main::$0
+Successful SSA optimization Pass2AliasElimination
+Constant main::toSpritePtr1_sprite#0 = SPRITE
+Successful SSA optimization Pass2ConstantIdentification
+Constant main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#0
+Successful SSA optimization Pass2ConstantIdentification
+Simplifying expression containing zero SPRITES_PTR in [6] SPRITES_PTR[0] = main::toSpritePtr1_return#0
+Simplifying expression containing zero SPRITES_COLOR in [7] SPRITES_COLOR[0] = GREEN
+Simplifying expression containing zero SPRITES_XPOS in [8] SPRITES_XPOS[0] = $15
+Simplifying expression containing zero SPRITES_YPOS in [9] SPRITES_YPOS[0] = $33
+Successful SSA optimization PassNSimplifyExpressionWithZero
+Removing unused procedure __start
+Removing unused procedure block __start
+Removing unused procedure block __start::@1
+Removing unused procedure block __start::@return
+Successful SSA optimization PassNEliminateEmptyStart
+Constant right-side identified [2] main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant main::toSpritePtr1_$0 = main::toSpritePtr1_$1/$40
+Successful SSA optimization Pass2ConstantIdentification
+Constant main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0
+Successful SSA optimization Pass2ConstantIdentification
+Constant inlined main::toSpritePtr1_sprite#0 = SPRITE
+Constant inlined main::toSpritePtr1_$1 = (word)SPRITE
+Constant inlined main::toSpritePtr1_$0 = (word)SPRITE/$40
+Successful SSA optimization Pass2ConstantInlining
+Adding NOP phi() at start of main::toSpritePtr1
+Adding NOP phi() at start of main::toSpritePtr1_@return
+CALL GRAPH
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+Culled Empty Block label main::toSpritePtr1_@return
+Adding NOP phi() at start of main::toSpritePtr1
+
+FINAL CONTROL FLOW GRAPH
+
+void main()
+main: scope:[main] from
+ kickasm() {{ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+ }}
+ [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1
+ to:main::toSpritePtr1
+main::toSpritePtr1: scope:[main] from main
+ [2] phi()
+ to:main::@1
+main::@1: scope:[main] from main::toSpritePtr1
+ [3] *SPRITES_PTR = main::toSpritePtr1_return#0
+ [4] *SPRITES_COLOR = GREEN
+ [5] *SPRITES_XPOS = $15
+ [6] *SPRITES_YPOS = $33
+ to:main::@return
+main::@return: scope:[main] from main::@1
+ [7] return
+ to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+void main()
+byte main::toSpritePtr1_return
+byte* main::toSpritePtr1_sprite
+
+Initial phi equivalence classes
+Complete equivalence classes
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [3] *SPRITES_PTR = main::toSpritePtr1_return#0 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [4] *SPRITES_COLOR = GREEN [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [5] *SPRITES_XPOS = $15 [ ] ( [ ] { } ) always clobbers reg byte a
+Statement [6] *SPRITES_YPOS = $33 [ ] ( [ ] { } ) always clobbers reg byte a
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [MOS6526_CIA]
+Uplift Scope [MOS6569_VICII]
+Uplift Scope [MOS6581_SID]
+Uplift Scope [main]
+Uplift Scope []
+
+Uplifting [MOS6526_CIA] best 328 combination
+Uplifting [MOS6569_VICII] best 328 combination
+Uplifting [MOS6581_SID] best 328 combination
+Uplifting [main] best 328 combination
+Uplifting [] best 328 combination
+
+ASSEMBLER BEFORE OPTIMIZATION
+ // File Comments
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// Exomizer Example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Upstart
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-exomizer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // Global Constants & labels
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+ // main
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // kickasm() {{ :EXO_DECRUNCH(CRUNCHED_SPRITE_END) }}
+ // Decrunch sprite file into memory
+ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+
+ // [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // [2] phi from main to main::toSpritePtr1 [phi:main->main::toSpritePtr1]
+ toSpritePtr1_from_main:
+ jmp toSpritePtr1
+ // main::toSpritePtr1
+ toSpritePtr1:
+ jmp __b1
+ // main::@1
+ __b1:
+ // [3] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // [4] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2
+ lda #GREEN
+ sta SPRITES_COLOR
+ // [5] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2
+ lda #$15
+ sta SPRITES_XPOS
+ // [6] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2
+ lda #$33
+ sta SPRITES_YPOS
+ jmp __breturn
+ // main::@return
+ __breturn:
+ // [7] return
+ rts
+}
+ // File Data
+.segment Data
+// The exomizer decruncher
+EXOMIZER:
+.const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp toSpritePtr1
+Removing instruction jmp __b1
+Removing instruction jmp __breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction toSpritePtr1_from_main:
+Removing instruction toSpritePtr1:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction __b1:
+Removing instruction __breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*) 1024
+const byte* EXOMIZER[] = kickasm {{ .const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+ }}
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*) 8192
+const nomodify byte* SPRITES_COLOR = (byte*) 53287
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*) 53248
+const nomodify byte* SPRITES_YPOS = (byte*) 53249
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*) 53248
+void main()
+byte main::toSpritePtr1_return
+const byte main::toSpritePtr1_return#0 toSpritePtr1_return = (byte)(word)SPRITE/$40
+byte* main::toSpritePtr1_sprite
+
+
+
+FINAL ASSEMBLER
+Score: 292
+
+ // File Comments
+// Example showing how to crunch and decrunch part of a file using the KickAss Cruncher Plugins
+// Exomizer Example
+// https://github.com/p-a/kickass-cruncher-plugins
+ // Upstart
+ // Commodore 64 PRG executable file - with the cruncher plugin enabled
+.plugin "se.triad.kickass.CruncherPlugins"
+.file [name="test-exomizer.prg", type="prg", segments="Program"]
+.segmentdef Program [segments="Basic, Code, Data"]
+.segmentdef Basic [start=$0801]
+.segmentdef Code [start=$80d]
+.segmentdef Data [startAfter="Code"]
+.segment Basic
+:BasicUpstart(main)
+ // Global Constants & labels
+ // The offset of the sprite pointers from the screen start address
+ .const OFFSET_SPRITE_PTRS = $3f8
+ .const GREEN = 5
+ .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+ .label SPRITES_XPOS = $d000
+ .label SPRITES_YPOS = $d001
+ .label SPRITES_COLOR = $d027
+ // The VIC-II MOS 6567/6569
+ .label VICII = $d000
+ // Default address of screen character matrix
+ .label DEFAULT_SCREEN = $400
+ // Address to decrunch the sprite to
+ .label SPRITE = $2000
+ .label SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+.segment Code
+ // main
+main: {
+ .const toSpritePtr1_return = SPRITE/$40
+ // kickasm
+ // kickasm() {{ :EXO_DECRUNCH(CRUNCHED_SPRITE_END) }}
+ // Decrunch sprite file into memory
+ :EXO_DECRUNCH(CRUNCHED_SPRITE_END)
+
+ // VICII->SPRITES_ENABLE = %00000001
+ // [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2
+ // Show the loaded sprite on screen
+ lda #1
+ sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE
+ // [2] phi from main to main::toSpritePtr1 [phi:main->main::toSpritePtr1]
+ // main::toSpritePtr1
+ // main::@1
+ // SPRITES_PTR[0] = toSpritePtr(SPRITE)
+ // [3] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2
+ lda #toSpritePtr1_return
+ sta SPRITES_PTR
+ // SPRITES_COLOR[0] = GREEN
+ // [4] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2
+ lda #GREEN
+ sta SPRITES_COLOR
+ // SPRITES_XPOS[0] = 0x15
+ // [5] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2
+ lda #$15
+ sta SPRITES_XPOS
+ // SPRITES_YPOS[0] = 0x33
+ // [6] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2
+ lda #$33
+ sta SPRITES_YPOS
+ // main::@return
+ // }
+ // [7] return
+ rts
+}
+ // File Data
+.segment Data
+// The exomizer decruncher
+EXOMIZER:
+.const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+
+// Array with crunched data created using inline kickasm
+CRUNCHED_SPRITE:
+.modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+
+
diff --git a/src/test/ref/examples/crunching/test-exomizer.sym b/src/test/ref/examples/crunching/test-exomizer.sym
new file mode 100644
index 000000000..f08eb1e28
--- /dev/null
+++ b/src/test/ref/examples/crunching/test-exomizer.sym
@@ -0,0 +1,29 @@
+const byte* CRUNCHED_SPRITE[] = kickasm( uses SPRITE) {{ .modify MemExomizer(false, true) {
+ .pc = SPRITE
+ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff))
+ .for (var y=0; y<21; y++)
+ .for (var x=0;x<3; x++)
+ .byte pic.getSinglecolorByte(x,y)
+ }
+ CRUNCHED_SPRITE_END:
+ }}
+const nomodify byte* DEFAULT_SCREEN = (byte*) 1024
+const byte* EXOMIZER[] = kickasm {{ .const EXO_LITERAL_SEQUENCES_USED = true
+ .const EXO_ZP_BASE = $02
+ .const EXO_DECRUNCH_TABLE = $0200
+ #import "exomizer_decrunch.asm"
+ }}
+const nomodify byte GREEN = 5
+const nomodify word OFFSET_SPRITE_PTRS = $3f8
+const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15
+const nomodify byte* SPRITE = (byte*) 8192
+const nomodify byte* SPRITES_COLOR = (byte*) 53287
+const nomodify byte* SPRITES_PTR = DEFAULT_SCREEN+OFFSET_SPRITE_PTRS
+const nomodify byte* SPRITES_XPOS = (byte*) 53248
+const nomodify byte* SPRITES_YPOS = (byte*) 53249
+const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*) 53248
+void main()
+byte main::toSpritePtr1_return
+const byte main::toSpritePtr1_return#0 toSpritePtr1_return = (byte)(word)SPRITE/$40
+byte* main::toSpritePtr1_sprite
+