37 byte Snowflake in Assembler Author: Serato / Finnish Gold Category: Christmas Challenge System: C64 Language: C64 "64tass" Assembler Len source code: 1122 Len exe file: 39 Len code only: 37 Instructions: Load PRG, clear the screen, and SYS845 Description: This routine renders the required snowflake pattern by storing one quarter in a bitmap, and plotting four rotations along with the central + that lies between them. Techniques that save bytes: - simple iteration, no subroutines - default program flow renders the + (no cost) - Bypass the normal kernal PLOT routine carry check - Only drawing stars (not spaces) so only one LDA - STA (PNT),y is one byte shorter than calling CHROUT - LSR to halve 42 to 21 and also clear C flag - so SBC then evaluates to 20- which centres the rotation on (10,10) - which is corrected for by pre-incrementing the row counter (no cost) - 256 iterations of the rotation loop avoids maintaining a counter - loading bitmap into zeroed memory so first zero is no cost - shifting bits out of the bitmap via zero page pointer (unintended SRE opcode) - modifying the bitmap in place so no need to keep value around - carefully placed code after bitmap table removes need for exit condition test More detail: This routine draws the pattern from the outside in, by first drawing the stars that form the + and then right shifting bits out of the bitmap from consecutive bytes one at a time. The last iteration fills in the central star and as the rest of the + has already been drawn the contents of the pattern byte do not matter. The code is placed immediately after the bitmap and carefully arranged to start with the opcodes BCS +8 SRE $b2 which assemble to the bytes b0 08 53 b2 On the final iteration the b0 opcode gets right shifted first to 58 (CLI) leaving the 08 (PHP), both of which execute harmlessly. Next the 58 is right shifted to 2c (BIT $5308). This also executes harmlessly but skips over the 08 and 53 so the next opcode to execute is b2 which is an unintended KIL opcode causing the CPU to halt. This is a valid way to finish, and avoids having to compare the loop counter and RTS, saving 3 bytes.