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) }