<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://www.sizecoding.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Serato</id>
		<title>SizeCoding - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://www.sizecoding.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Serato"/>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/wiki/Special:Contributions/Serato"/>
		<updated>2026-05-04T13:04:41Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.0</generator>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Star&amp;diff=1208</id>
		<title>Christmas Star</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Star&amp;diff=1208"/>
				<updated>2022-12-31T09:19:14Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added post deadline32 byte C64 version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
==The challenge==&lt;br /&gt;
During the [https://demozoo.org/parties/4578/ Vintage Computing Christmas Challenge 2022], the goal was to create the shape of a given Christmas star with as few bytes as possible. All platforms and languages were allowed. The star should look exactly like the one shown below.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
               *       *&lt;br /&gt;
               **     **&lt;br /&gt;
               ***   ***&lt;br /&gt;
               **** ****&lt;br /&gt;
           *****************&lt;br /&gt;
            ***************&lt;br /&gt;
             *************&lt;br /&gt;
              ***********&lt;br /&gt;
               *********&lt;br /&gt;
              ***********&lt;br /&gt;
             *************&lt;br /&gt;
            ***************&lt;br /&gt;
           *****************&lt;br /&gt;
               **** ****&lt;br /&gt;
               ***   ***&lt;br /&gt;
               **     **&lt;br /&gt;
               *       *&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* draw character by character&lt;br /&gt;
* mirror triangles&lt;br /&gt;
&lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry for the C64 was submitted by Serato with 34 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		chrout = $FFD2	; Kernal routine outputs char in A&lt;br /&gt;
		plot = $E50C	; Kernal routine moves cursor to (y,x)&lt;br /&gt;
		pnt = $d1     	; Pointer to the start of the current screen line&lt;br /&gt;
		row = $b3		; zp var that always starts at 3&lt;br /&gt;
*       = $1000&lt;br /&gt;
do_2nd	ldx row			; render &amp;quot;upside down&amp;quot; triangles&lt;br /&gt;
do_line	ldy #9			; render one row of triangle, and its x-mirror image&lt;br /&gt;
		jsr plot		; move cursor to column 9 on row x&lt;br /&gt;
		ldy #17			; start x-mirrored image in column 17&lt;br /&gt;
		lda #'*'		; the star of the show&lt;br /&gt;
do_asks	jsr chrout		; print star, advancing kernal cursor to right&lt;br /&gt;
		sta (pnt),y		; write x-mirrored star with mirrored cursor&lt;br /&gt;
		dey				; advance mirrored cursor to left&lt;br /&gt;
		cpy row			; test against line y=x to form diagonal&lt;br /&gt;
		bne do_asks		&lt;br /&gt;
		cpx row			; check if these weere &amp;quot;upside down&amp;quot; triangles&lt;br /&gt;
		bne do_2nd		; if not, draw the upside down ones&lt;br /&gt;
sys		lda #$10		; entry point of routine, start with y mirrored&lt;br /&gt;
		sec				; wish this could be avoided, feels like a wasted byte&lt;br /&gt;
		isc row			; increment bottom row counter and put (16 - row) in A&lt;br /&gt;
		tax				; we need in x register&lt;br /&gt;
		bpl do_line		; repeat until row &amp;lt; 0, then fall through&lt;br /&gt;
		rts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;The required octogram may be constructed as the union of four right triangles reflected four ways in x and y axes. The central loop renders one row of the triangle, plus its horizontal mirror image. The outer loop iterates over normal and mirror image screen rows. The result is all four triangles being rendered on top of each other. Saved a byte with unintended 6502 opcode ISC which combines INC and SBC to both increment a counter and load (16 minus) its value into A.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
==Optimized post-deadline versions==&lt;br /&gt;
===34 bytes version for C64===&lt;br /&gt;
This shorter C64 version by Serato renders the union of four triangles rotated 90 degrees. To save space it iterates 256 times. It also uses a trick where the carry flag state is set by the loop comparison causing the active row to advance automatically at the end of each column.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
        plot = $E50C    ; Kernal routine moves cursor to (y,x)&lt;br /&gt;
        sys_h = $15&lt;br /&gt;
        pnt = $d1&lt;br /&gt;
        tblx = $d6&lt;br /&gt;
* = $c00&lt;br /&gt;
        lda #22&lt;br /&gt;
loop2   tay&lt;br /&gt;
loop1   sbc #3&lt;br /&gt;
        tax&lt;br /&gt;
        jsr plot&lt;br /&gt;
        lda #'*'&lt;br /&gt;
        sta (pnt),y&lt;br /&gt;
        tya&lt;br /&gt;
        eor #$1f&lt;br /&gt;
        ldy tblx&lt;br /&gt;
        dec $2&lt;br /&gt;
        bne loop1&lt;br /&gt;
        dey&lt;br /&gt;
        cpy #10&lt;br /&gt;
        bcs loop1&lt;br /&gt;
        dec sys_h&lt;br /&gt;
        bpl loop2&lt;br /&gt;
        rts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Star&amp;diff=1206</id>
		<title>Christmas Star</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Star&amp;diff=1206"/>
				<updated>2022-12-28T20:50:07Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added Serato's 34 entry for C64&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
==The challenge==&lt;br /&gt;
During the [https://demozoo.org/parties/4578/ Vintage Computing Christmas Challenge 2022] the goal was to create the shape of a given Christmas star with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The star should look exactly like shown below.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
               *       *&lt;br /&gt;
               **     **&lt;br /&gt;
               ***   ***&lt;br /&gt;
               **** ****&lt;br /&gt;
           *****************&lt;br /&gt;
            ***************&lt;br /&gt;
             *************&lt;br /&gt;
              ***********&lt;br /&gt;
               *********&lt;br /&gt;
              ***********&lt;br /&gt;
             *************&lt;br /&gt;
            ***************&lt;br /&gt;
           *****************&lt;br /&gt;
               **** ****&lt;br /&gt;
               ***   ***&lt;br /&gt;
               **     **&lt;br /&gt;
               *       *&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* draw character by character&lt;br /&gt;
* mirror triangles&lt;br /&gt;
* etc&lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry for the C64 was submitted by Serato with 34 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		chrout = $FFD2	; Kernal routine outputs char in A&lt;br /&gt;
		plot = $E50C	; Kernal routine moves cursor to (y,x)&lt;br /&gt;
		pnt = $d1     	; Pointer to the start of the current screen line&lt;br /&gt;
		row = $b3		; zp var that always starts at 3&lt;br /&gt;
*       = $1000&lt;br /&gt;
do_2nd	ldx row			; render &amp;quot;upside down&amp;quot; triangles&lt;br /&gt;
do_line	ldy #9			; render one row of triangle, and its x-mirror image&lt;br /&gt;
		jsr plot		; move cursor to column 9 on row x&lt;br /&gt;
		ldy #17			; start x-mirrored image in column 17&lt;br /&gt;
		lda #'*'		; the star of the show&lt;br /&gt;
do_asks	jsr chrout		; print star, advancing kernal cursor to right&lt;br /&gt;
		sta (pnt),y		; write x-mirrored star with mirrored cursor&lt;br /&gt;
		dey				; advance mirrored cursor to left&lt;br /&gt;
		cpy row			; test against line y=x to form diagonal&lt;br /&gt;
		bne do_asks		&lt;br /&gt;
		cpx row			; check if these weere &amp;quot;upside down&amp;quot; triangles&lt;br /&gt;
		bne do_2nd		; if not, draw the upside down ones&lt;br /&gt;
sys		lda #$10		; entry point of routine, start with y mirrored&lt;br /&gt;
		sec				; wish this could be avoided, feels like a wasted byte&lt;br /&gt;
		isc row			; increment bottom row counter and put (16 - row) in A&lt;br /&gt;
		tax				; we need in x register&lt;br /&gt;
		bpl do_line		; repeat until row &amp;lt; 0, then fall through&lt;br /&gt;
		rts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;The required octogram may be constructed as the union of four right triangles reflected four ways in x and y axes. The central loop renders one row of the triangle, plus its horizontal mirror image. The outer loop iterates over normal and mirror image screen rows. The result is all four triangles being rendered on top of each other. Saved a byte with unintended 6502 opcode ISC which combines INC and SBC to both increment a counter and load (16 minus) its value into A.&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=997</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=997"/>
				<updated>2022-01-01T10:42:15Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added 33 byte C64 version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
==The challenge==&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Optimized post-deadline versions==&lt;br /&gt;
===36 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by altering the calculation so the default register values on start cause the first line to be drawn, shortening the table by one entry.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2074&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		adc	#width-1&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		lax table-1,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===35 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by writing directly to the screen, saving one byte. This change prevents the Y register being used as a loop index, so a different approach is used to iterate over the table entries.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pnt = $D1&lt;br /&gt;
		lnmx = $D5&lt;br /&gt;
		eal = $AE&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2061&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
&lt;br /&gt;
code &lt;br /&gt;
--		adc	lnmx&lt;br /&gt;
		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (pnt),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf-8&lt;br /&gt;
		dec	eal&lt;br /&gt;
		lax (eal+1,x)&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
table&lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
;		!byte -1  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===34 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by removing the ADC that indents the tree. Instead the offset to centre the tree is provided &amp;quot;for free&amp;quot; by suitably locating the EAL/EAH zp vector. This is possible because the C64 tape buffer is located immediately below the default screen location, and writing to the top line of the screen can be combined with the kernal routine to scroll the screen downward. This routine always leaves the Y register as $84, which added to the tape buffer zp vector TAPE1 points to the table ending at $3c0. The table values have their MSB clear so the centre of the tree has value $7f. When right shifted this gives an indent of $3f. The structure of the code is arranged so that the end of the binary ($3d4) plus the $3f offset give $413, ie 19 chars indented from the start of the screen matrix, centring the tree on screen. Although removing the ADC saves two bytes, one byte is lost adding the first row back into the table.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		scroll_down = $E981&lt;br /&gt;
		eal = $AE&lt;br /&gt;
		tape1 = $b2&lt;br /&gt;
&lt;br /&gt;
*=$3c0-14&lt;br /&gt;
;		SYS 970 to draw tree&lt;br /&gt;
;		SYS 960 to draw with added &amp;quot;ground&amp;quot;&lt;br /&gt;
&lt;br /&gt;
table&lt;br /&gt;
		!byte 128-1&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-5&lt;br /&gt;
		!byte 128-7&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-7&lt;br /&gt;
		!byte 128-11&lt;br /&gt;
		!byte 128-15&lt;br /&gt;
		!byte 128-5&lt;br /&gt;
		!byte 128-11&lt;br /&gt;
		!byte 128-17&lt;br /&gt;
		!byte 128-23&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
code &lt;br /&gt;
--		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (eal),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bpl -&lt;br /&gt;
entry&lt;br /&gt;
		jsr scroll_down&lt;br /&gt;
		dec	tape1&lt;br /&gt;
		lax (tape1),y&lt;br /&gt;
		bne --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===33 bytes version for C64===&lt;br /&gt;
This C64 version is most similar to the 35-byte version above. It saves 2 bytes over that version by omitting the table vector decrement, instead using the zp screen editor row variable which is incremented by the kernal with each linefeed. Fortuitously the high-byte of this vector is the &amp;quot;ASCII Value of Last Character Printed&amp;quot; which will always be $d. By locating the binary at $0dxx the table can be accessed with this vector.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pnt = $D1&lt;br /&gt;
		lnmx = $D5&lt;br /&gt;
		tblx = $D6&lt;br /&gt;
		&lt;br /&gt;
*=$d0b&lt;br /&gt;
;		SYS 3352 to draw tree, SYS should be typed with the cursor on row 10.&lt;br /&gt;
&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1&lt;br /&gt;
		!byte -3&lt;br /&gt;
		!byte -5&lt;br /&gt;
		!byte -7&lt;br /&gt;
		!byte -3&lt;br /&gt;
		!byte -7&lt;br /&gt;
		!byte -11&lt;br /&gt;
		!byte -15&lt;br /&gt;
		!byte -5&lt;br /&gt;
		!byte -11&lt;br /&gt;
		!byte -17&lt;br /&gt;
		!byte -23&lt;br /&gt;
		!byte -3&lt;br /&gt;
		!byte -3&lt;br /&gt;
code &lt;br /&gt;
--		adc lnmx&lt;br /&gt;
		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (pnt),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf-8&lt;br /&gt;
		lax (tblx+1,x)&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===32 bytes version for ZX Spectrum===&lt;br /&gt;
After the deadline following entry for the ZX Spectrum with only 35 bytes was submitted by reddie and optimized by char to 32 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;z80&amp;quot;&amp;gt;&lt;br /&gt;
# Christmas Tree post-event build, ZX Spectrum version&lt;br /&gt;
# tnx to Manwe for info about event, better late than never =)&lt;br /&gt;
# first version - 35 bytes - (c) reddie, 2021.12.25&lt;br /&gt;
# optimized to 32 bytes by char, 2021.12.26 - huge thanks from me!&lt;br /&gt;
# full final object len  = 32 bytes (from label &amp;quot;data&amp;quot; to label &amp;quot;end&amp;quot;)&lt;br /&gt;
# data array len  = 14 bytes; code len = 18 bytes, 13 Z80 instructions&lt;br /&gt;
# execute from Basic only! entry point  = 61455, or just run TRD image&lt;br /&gt;
# and then run &amp;quot;ctree32b&amp;quot; Basic-program, it will load &amp;amp; start the code&lt;br /&gt;
# TRD file also contains source text in ALASM format&lt;br /&gt;
&lt;br /&gt;
data	org	-16*256+1&lt;br /&gt;
	defb	-5,-5,-25,-19,-13,-7,-17,-13,-9,-5,-9,-7,-5,-3&lt;br /&gt;
&lt;br /&gt;
start	dec	c&lt;br /&gt;
	jr	z,$	;stop when finished&lt;br /&gt;
	ld	a,23	;set coords via ROM procedure&lt;br /&gt;
	rst	16&lt;br /&gt;
	ld	a,(bc)	;line len in negative format&lt;br /&gt;
	ld	e,a&lt;br /&gt;
	rra&lt;br /&gt;
	sub	b	;centering&lt;br /&gt;
print	rst	16&lt;br /&gt;
	ld	a,&amp;quot;*&amp;quot;&lt;br /&gt;
	inc	e&lt;br /&gt;
	jr	nz,print&lt;br /&gt;
	jr	start&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===35 bytes version for Plus/4===&lt;br /&gt;
The following optimized version for the Commodore Plus/4 was created after the deadline:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502tasm&amp;quot;&amp;gt;&lt;br /&gt;
# Plus/4 Christmas Tree by GeirS, 2021-12-29&lt;br /&gt;
# Assemble using 64tass (replace hash with semicolon first, except for 'lda #$2a')&lt;br /&gt;
&lt;br /&gt;
BtmRow		= $0c00+$28*$18	# Address of bottom screen row&lt;br /&gt;
Screen		= BtmRow-$6c	# Adjustment for ($100-$28)/2&lt;br /&gt;
ScrollUp	= $da89			# KERNAL routine to scroll screen upwards&lt;br /&gt;
VarTab		= $2d			# Pointer: Start of BASIC variables&lt;br /&gt;
&lt;br /&gt;
			* = $1001		# Load address&lt;br /&gt;
&lt;br /&gt;
# BASIC stub&lt;br /&gt;
			.word (NextLine),0&lt;br /&gt;
			.null $9e,format(&amp;quot;%4d&amp;quot;, Start)&lt;br /&gt;
NextLine&lt;br /&gt;
			.word 0&lt;br /&gt;
&lt;br /&gt;
# Code and data (35 bytes total)&lt;br /&gt;
RowLoop&lt;br /&gt;
			lsr				# Calculate screen offset&lt;br /&gt;
			tay&lt;br /&gt;
			lda #$2a		# Asterisk character&lt;br /&gt;
CharLoop&lt;br /&gt;
			sta Screen,y	# Put char in bottom screen row&lt;br /&gt;
			iny&lt;br /&gt;
			inx&lt;br /&gt;
			bne CharLoop	# Loop for all chars&lt;br /&gt;
Start&lt;br /&gt;
			jsr ScrollUp	# Scroll the screen upwards (x=0 after)&lt;br /&gt;
			dec VarTab		# Adjust address of char count to use next&lt;br /&gt;
			lax (VarTab,x)	# Load char count into both a and x&lt;br /&gt;
			bmi RowLoop		# Loop while not done&lt;br /&gt;
			rts&lt;br /&gt;
&lt;br /&gt;
# Asterisk counts (negative values to optimize the code)&lt;br /&gt;
			.char -3,-3,-23,-17,-11,-5,-15,-11,-7,-3,-7,-5,-3,-1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=996</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=996"/>
				<updated>2021-12-31T23:15:11Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added 34 byte C64 version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
==The challenge==&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Optimized post-deadline versions==&lt;br /&gt;
===36 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by altering the calculation so the default register values on start cause the first line to be drawn, shortening the table by one entry.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2074&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		adc	#width-1&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		lax table-1,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===35 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by writing directly to the screen, saving one byte. This change prevents the Y register being used as a loop index, so a different approach is used to iterate over the table entries.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pnt = $D1&lt;br /&gt;
		lnmx = $D5&lt;br /&gt;
		eal = $AE&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2061&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
&lt;br /&gt;
code &lt;br /&gt;
--		adc	lnmx&lt;br /&gt;
		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (pnt),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf-8&lt;br /&gt;
		dec	eal&lt;br /&gt;
		lax (eal+1,x)&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
table&lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
;		!byte -1  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===34 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by removing the ADC that indents the tree. Instead the offset to centre the tree is provided &amp;quot;for free&amp;quot; by suitably locating the EAL/EAH zp vector. This is possible because the C64 tape buffer is located immediately below the default screen location, and writing to the top line of the screen can be combined with the kernal routine to scroll the screen downward. This routine always leaves the Y register as $84, which added to the tape buffer zp vector TAPE1 points to the table ending at $3c0. The table values have their MSB clear so the centre of the tree has value $7f. When right shifted this gives an indent of $3f. The structure of the code is arranged so that the end of the binary ($3d4) plus the $3f offset give $413, ie 19 chars indented from the start of the screen matrix, centring the tree on screen. Although removing the ADC saves two bytes, one byte is lost adding the first row back into the table.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		scroll_down = $E981&lt;br /&gt;
		eal = $AE&lt;br /&gt;
		tape1 = $b2&lt;br /&gt;
&lt;br /&gt;
*=$3c0-14&lt;br /&gt;
;		SYS 970 to draw tree&lt;br /&gt;
;		SYS 960 to draw with added &amp;quot;ground&amp;quot;&lt;br /&gt;
&lt;br /&gt;
table&lt;br /&gt;
		!byte 128-1&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-5&lt;br /&gt;
		!byte 128-7&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-7&lt;br /&gt;
		!byte 128-11&lt;br /&gt;
		!byte 128-15&lt;br /&gt;
		!byte 128-5&lt;br /&gt;
		!byte 128-11&lt;br /&gt;
		!byte 128-17&lt;br /&gt;
		!byte 128-23&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
		!byte 128-3&lt;br /&gt;
code &lt;br /&gt;
--		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (eal),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bpl -&lt;br /&gt;
entry&lt;br /&gt;
		jsr scroll_down&lt;br /&gt;
		dec	tape1&lt;br /&gt;
		lax (tape1),y&lt;br /&gt;
		bne --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===32 bytes version for ZX Spectrum===&lt;br /&gt;
After the deadline following entry for the ZX Spectrum with only 35 bytes was submitted by reddie and optimized by char to 32 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;z80&amp;quot;&amp;gt;&lt;br /&gt;
# Christmas Tree post-event build, ZX Spectrum version&lt;br /&gt;
# tnx to Manwe for info about event, better late than never =)&lt;br /&gt;
# first version - 35 bytes - (c) reddie, 2021.12.25&lt;br /&gt;
# optimized to 32 bytes by char, 2021.12.26 - huge thanks from me!&lt;br /&gt;
# full final object len  = 32 bytes (from label &amp;quot;data&amp;quot; to label &amp;quot;end&amp;quot;)&lt;br /&gt;
# data array len  = 14 bytes; code len = 18 bytes, 13 Z80 instructions&lt;br /&gt;
# execute from Basic only! entry point  = 61455, or just run TRD image&lt;br /&gt;
# and then run &amp;quot;ctree32b&amp;quot; Basic-program, it will load &amp;amp; start the code&lt;br /&gt;
# TRD file also contains source text in ALASM format&lt;br /&gt;
&lt;br /&gt;
data	org	-16*256+1&lt;br /&gt;
	defb	-5,-5,-25,-19,-13,-7,-17,-13,-9,-5,-9,-7,-5,-3&lt;br /&gt;
&lt;br /&gt;
start	dec	c&lt;br /&gt;
	jr	z,$	;stop when finished&lt;br /&gt;
	ld	a,23	;set coords via ROM procedure&lt;br /&gt;
	rst	16&lt;br /&gt;
	ld	a,(bc)	;line len in negative format&lt;br /&gt;
	ld	e,a&lt;br /&gt;
	rra&lt;br /&gt;
	sub	b	;centering&lt;br /&gt;
print	rst	16&lt;br /&gt;
	ld	a,&amp;quot;*&amp;quot;&lt;br /&gt;
	inc	e&lt;br /&gt;
	jr	nz,print&lt;br /&gt;
	jr	start&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===35 bytes version for Plus/4===&lt;br /&gt;
The following optimized version for the Commodore Plus/4 was created after the deadline:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502tasm&amp;quot;&amp;gt;&lt;br /&gt;
# Plus/4 Christmas Tree by GeirS, 2021-12-29&lt;br /&gt;
# Assemble using 64tass (replace hash with semicolon first, except for 'lda #$2a')&lt;br /&gt;
&lt;br /&gt;
BtmRow		= $0c00+$28*$18	# Address of bottom screen row&lt;br /&gt;
Screen		= BtmRow-$6c	# Adjustment for ($100-$28)/2&lt;br /&gt;
ScrollUp	= $da89			# KERNAL routine to scroll screen upwards&lt;br /&gt;
VarTab		= $2d			# Pointer: Start of BASIC variables&lt;br /&gt;
&lt;br /&gt;
			* = $1001		# Load address&lt;br /&gt;
&lt;br /&gt;
# BASIC stub&lt;br /&gt;
			.word (NextLine),0&lt;br /&gt;
			.null $9e,format(&amp;quot;%4d&amp;quot;, Start)&lt;br /&gt;
NextLine&lt;br /&gt;
			.word 0&lt;br /&gt;
&lt;br /&gt;
# Code and data (35 bytes total)&lt;br /&gt;
RowLoop&lt;br /&gt;
			lsr				# Calculate screen offset&lt;br /&gt;
			tay&lt;br /&gt;
			lda #$2a		# Asterisk character&lt;br /&gt;
CharLoop&lt;br /&gt;
			sta Screen,y	# Put char in bottom screen row&lt;br /&gt;
			iny&lt;br /&gt;
			inx&lt;br /&gt;
			bne CharLoop	# Loop for all chars&lt;br /&gt;
Start&lt;br /&gt;
			jsr ScrollUp	# Scroll the screen upwards (x=0 after)&lt;br /&gt;
			dec VarTab		# Adjust address of char count to use next&lt;br /&gt;
			lax (VarTab,x)	# Load char count into both a and x&lt;br /&gt;
			bmi RowLoop		# Loop while not done&lt;br /&gt;
			rts&lt;br /&gt;
&lt;br /&gt;
# Asterisk counts (negative values to optimize the code)&lt;br /&gt;
			.char -3,-3,-23,-17,-11,-5,-15,-11,-7,-3,-7,-5,-3,-1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=995</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=995"/>
				<updated>2021-12-30T08:12:27Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added 35-byte C64 version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
==The challenge==&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Optimized post-deadline versions==&lt;br /&gt;
===36 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by altering the calculation so the default register values on start cause the first line to be drawn, shortening the table by one entry.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2074&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		adc	#width-1&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		lax table-1,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===35 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by writing directly to the screen, saving one byte. This change prevents the Y register being used as a loop index, so a different approach is used to iterate over the table entries.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pnt = $D1&lt;br /&gt;
		lnmx = $D5&lt;br /&gt;
		eal = $AE&lt;br /&gt;
		&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2061&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
&lt;br /&gt;
code &lt;br /&gt;
--		adc	lnmx&lt;br /&gt;
		lsr&lt;br /&gt;
		tay&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		sta (pnt),y&lt;br /&gt;
		iny&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf-8&lt;br /&gt;
		dec	eal&lt;br /&gt;
		lax (eal+1,x)&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
table&lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
;		!byte -1  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===32 bytes version for ZX Spectrum===&lt;br /&gt;
After the deadline following entry for the ZX Spectrum with only 35 bytes was submitted by reddie and optimized by char to 32 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;z80&amp;quot;&amp;gt;&lt;br /&gt;
# Christmas Tree post-event build, ZX Spectrum version&lt;br /&gt;
# tnx to Manwe for info about event, better late than never =)&lt;br /&gt;
# first version - 35 bytes - (c) reddie, 2021.12.25&lt;br /&gt;
# optimized to 32 bytes by char, 2021.12.26 - huge thanks from me!&lt;br /&gt;
# full final object len  = 32 bytes (from label &amp;quot;data&amp;quot; to label &amp;quot;end&amp;quot;)&lt;br /&gt;
# data array len  = 14 bytes; code len = 18 bytes, 13 Z80 instructions&lt;br /&gt;
# execute from Basic only! entry point  = 61455, or just run TRD image&lt;br /&gt;
# and then run &amp;quot;ctree32b&amp;quot; Basic-program, it will load &amp;amp; start the code&lt;br /&gt;
# TRD file also contains source text in ALASM format&lt;br /&gt;
&lt;br /&gt;
data	org	-16*256+1&lt;br /&gt;
	defb	-5,-5,-25,-19,-13,-7,-17,-13,-9,-5,-9,-7,-5,-3&lt;br /&gt;
&lt;br /&gt;
start	dec	c&lt;br /&gt;
	jr	z,$	;stop when finished&lt;br /&gt;
	ld	a,23	;set coords via ROM procedure&lt;br /&gt;
	rst	16&lt;br /&gt;
	ld	a,(bc)	;line len in negative format&lt;br /&gt;
	ld	e,a&lt;br /&gt;
	rra&lt;br /&gt;
	sub	b	;centering&lt;br /&gt;
print	rst	16&lt;br /&gt;
	ld	a,&amp;quot;*&amp;quot;&lt;br /&gt;
	inc	e&lt;br /&gt;
	jr	nz,print&lt;br /&gt;
	jr	start&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===35 bytes version for Plus/4===&lt;br /&gt;
The following optimized version for the Commodore Plus/4 was created after the deadline:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502tasm&amp;quot;&amp;gt;&lt;br /&gt;
# Plus/4 Christmas Tree by GeirS, 2021-12-29&lt;br /&gt;
# Assemble using 64tass (replace hash with semicolon first, except for 'lda #$2a')&lt;br /&gt;
&lt;br /&gt;
BtmRow		= $0c00+$28*$18	# Address of bottom screen row&lt;br /&gt;
Screen		= BtmRow-$6c	# Adjustment for ($100-$28)/2&lt;br /&gt;
ScrollUp	= $da89			# KERNAL routine to scroll screen upwards&lt;br /&gt;
VarTab		= $2d			# Pointer: Start of BASIC variables&lt;br /&gt;
&lt;br /&gt;
			* = $1001		# Load address&lt;br /&gt;
&lt;br /&gt;
# BASIC stub&lt;br /&gt;
			.word (NextLine),0&lt;br /&gt;
			.null $9e,format(&amp;quot;%4d&amp;quot;, Start)&lt;br /&gt;
NextLine&lt;br /&gt;
			.word 0&lt;br /&gt;
&lt;br /&gt;
# Code and data (35 bytes total)&lt;br /&gt;
RowLoop&lt;br /&gt;
			lsr				# Calculate screen offset&lt;br /&gt;
			tay&lt;br /&gt;
			lda #$2a		# Asterisk character&lt;br /&gt;
CharLoop&lt;br /&gt;
			sta Screen,y	# Put char in bottom screen row&lt;br /&gt;
			iny&lt;br /&gt;
			inx&lt;br /&gt;
			bne CharLoop	# Loop for all chars&lt;br /&gt;
Start&lt;br /&gt;
			jsr ScrollUp	# Scroll the screen upwards (x=0 after)&lt;br /&gt;
			dec VarTab		# Adjust address of char count to use next&lt;br /&gt;
			lax (VarTab,x)	# Load char count into both a and x&lt;br /&gt;
			bmi RowLoop		# Loop while not done&lt;br /&gt;
			rts&lt;br /&gt;
&lt;br /&gt;
# Asterisk counts (negative values to optimize the code)&lt;br /&gt;
			.char -3,-3,-23,-17,-11,-5,-15,-11,-7,-3,-7,-5,-3,-1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=987</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=987"/>
				<updated>2021-12-27T21:45:50Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Post-deadline versions==&lt;br /&gt;
===36 bytes version for C64===&lt;br /&gt;
The C64 version was shortened by altering the calculation so the default register values on start cause the first line to be drawn, shortening the table by one entry.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2074&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		adc	#width-1&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		lax table-1,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===32 bytes version for ZX Spectrum===&lt;br /&gt;
After the deadline following entry for the ZX Spectrum with only 35 bytes was submitted by reddie and optimized by char to 32 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;z80&amp;quot;&amp;gt;&lt;br /&gt;
# Christmas Tree post-event build, ZX Spectrum version&lt;br /&gt;
# tnx to Manwe for info about event, better late than never =)&lt;br /&gt;
# first version - 35 bytes - (c) reddie, 2021.12.25&lt;br /&gt;
# optimized to 32 bytes by char, 2021.12.26 - huge thanks from me!&lt;br /&gt;
# full final object len  = 32 bytes (from label &amp;quot;data&amp;quot; to label &amp;quot;end&amp;quot;)&lt;br /&gt;
# data array len  = 14 bytes; code len = 18 bytes, 13 Z80 instructions&lt;br /&gt;
# execute from Basic only! entry point  = 61455, or just run TRD image&lt;br /&gt;
# and then run &amp;quot;ctree32b&amp;quot; Basic-program, it will load &amp;amp; start the code&lt;br /&gt;
# TRD file also contains source text in ALASM format&lt;br /&gt;
&lt;br /&gt;
data	org	-16*256+1&lt;br /&gt;
	defb	-5,-5,-25,-19,-13,-7,-17,-13,-9,-5,-9,-7,-5,-3&lt;br /&gt;
&lt;br /&gt;
start	dec	c&lt;br /&gt;
	jr	z,$	;stop when finished&lt;br /&gt;
	ld	a,23	;set coords via ROM procedure&lt;br /&gt;
	rst	16&lt;br /&gt;
	ld	a,(bc)	;line len in negative format&lt;br /&gt;
	ld	e,a&lt;br /&gt;
	rra&lt;br /&gt;
	sub	b	;centering&lt;br /&gt;
print	rst	16&lt;br /&gt;
	ld	a,&amp;quot;*&amp;quot;&lt;br /&gt;
	inc	e&lt;br /&gt;
	jr	nz,print&lt;br /&gt;
	jr	start&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=983</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=983"/>
				<updated>2021-12-27T20:52:48Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added 32 byte C64 version, added sections for in and out of comp&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
==Winning Entries==&lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Post-deadline versions==&lt;br /&gt;
===36 bytes version for C64===&lt;br /&gt;
The C64 version was improved by altering the calculation so the default register values on start cause the first line to be drawn, shortening the table by one entry.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2074&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
;		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		adc	#width-1&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bmi -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		lax table-1,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===32 bytes version for ZX Spectrum===&lt;br /&gt;
After the deadline following entry for the ZX Spectrum with only 35 bytes was submitted by reddie and optimized by char to 32 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;z80&amp;quot;&amp;gt;&lt;br /&gt;
# Christmas Tree post-event build, ZX Spectrum version&lt;br /&gt;
# tnx to Manwe for info about event, better late than never =)&lt;br /&gt;
# first version - 35 bytes - (c) reddie, 2021.12.25&lt;br /&gt;
# optimized to 32 bytes by char, 2021.12.26 - huge thanks from me!&lt;br /&gt;
# full final object len  = 32 bytes (from label &amp;quot;data&amp;quot; to label &amp;quot;end&amp;quot;)&lt;br /&gt;
# data array len  = 14 bytes; code len = 18 bytes, 13 Z80 instructions&lt;br /&gt;
# execute from Basic only! entry point  = 61455, or just run TRD image&lt;br /&gt;
# and then run &amp;quot;ctree32b&amp;quot; Basic-program, it will load &amp;amp; start the code&lt;br /&gt;
# TRD file also contains source text in ALASM format&lt;br /&gt;
&lt;br /&gt;
data	org	-16*256+1&lt;br /&gt;
	defb	-5,-5,-25,-19,-13,-7,-17,-13,-9,-5,-9,-7,-5,-3&lt;br /&gt;
&lt;br /&gt;
start	dec	c&lt;br /&gt;
	jr	z,$	;stop when finished&lt;br /&gt;
	ld	a,23	;set coords via ROM procedure&lt;br /&gt;
	rst	16&lt;br /&gt;
	ld	a,(bc)	;line len in negative format&lt;br /&gt;
	ld	e,a&lt;br /&gt;
	rra&lt;br /&gt;
	sub	b	;centering&lt;br /&gt;
print	rst	16&lt;br /&gt;
	ld	a,&amp;quot;*&amp;quot;&lt;br /&gt;
	inc	e&lt;br /&gt;
	jr	nz,print&lt;br /&gt;
	jr	start&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=978</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=978"/>
				<updated>2021-12-25T20:16:10Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Updated Serato asm source to match entry&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		;; BASIC header&lt;br /&gt;
		*= $0801&lt;br /&gt;
		!word +, 10&lt;br /&gt;
		!byte $9e&lt;br /&gt;
		!text &amp;quot;2092&amp;quot;&lt;br /&gt;
		!byte 0&lt;br /&gt;
+		!word 0&lt;br /&gt;
table&lt;br /&gt;
		!byte -1  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -7  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -15 &lt;br /&gt;
		!byte -5  &lt;br /&gt;
		!byte -11 &lt;br /&gt;
		!byte -17 &lt;br /&gt;
		!byte -23 &lt;br /&gt;
		!byte -3  &lt;br /&gt;
		!byte -3  &lt;br /&gt;
code&lt;br /&gt;
--		lsr&lt;br /&gt;
		sbc #(128-width/2)&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
entry&lt;br /&gt;
		lax table,y&lt;br /&gt;
		bmi --&lt;br /&gt;
		rts&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=977</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=977"/>
				<updated>2021-12-25T20:12:19Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: Added content of how_it_works.txt from Serato submission&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		*=$304-39&lt;br /&gt;
table&lt;br /&gt;
		!byte width-1  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-5  &lt;br /&gt;
		!byte width-7  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-7  &lt;br /&gt;
		!byte width-11 &lt;br /&gt;
		!byte width-15 &lt;br /&gt;
		!byte width-5  &lt;br /&gt;
		!byte width-11 &lt;br /&gt;
		!byte width-17 &lt;br /&gt;
		!byte width-23 &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
entry&lt;br /&gt;
		lax	table-1,y&lt;br /&gt;
		bmi *&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		cpx #width&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		jmp entry&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Serato's entry was provided with the following comments:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;This entry to the Christmas Tree challenge saves space in six ways:&lt;br /&gt;
&lt;br /&gt;
 1. Using the c64 kernal routines to output individual characters and carriage return/linefeed. These routines save/restore X/Y allowing the registers to be used as loop counters.&lt;br /&gt;
&lt;br /&gt;
 2. Writing to the PNTR kernal variable to indent each row.&lt;br /&gt;
&lt;br /&gt;
 3. Using the unintended LAX opcode to simultaneously load A and X with the table values.&lt;br /&gt;
&lt;br /&gt;
 4. Storing the row widths as 2's complement negative values, to simplify the indent calculation to divide by two (LSR) and subtract (SBC). The inner loop simply counts back up to zero for rendering the correct width.&lt;br /&gt;
&lt;br /&gt;
 5. BASIC loads the Y register from address $30d. This defaults to 0 on startup, so Y does not need to be initialised.&lt;br /&gt;
&lt;br /&gt;
 6. Placing the table before the code in memory, the MSB of the table entries do not match the MSB of the first opcode (LSR), allowing the outer loop exit condition to be set implicitly in the Negative flag as the table values are read.&lt;br /&gt;
&lt;br /&gt;
These optimisations result in 37 bytes of machine code and data. Two further optimisations are possible each of which save 1 byte, but break the rules of this challenge:&lt;br /&gt;
&lt;br /&gt;
 a - LSR and SBC can be replaced with the unintended opcode ARR, if you are willing to &amp;quot;centre&amp;quot; the tree on a virtual screen width of 32 chars.&lt;br /&gt;
&lt;br /&gt;
 b - The BASIC interpreter leaves the line number in the zero page word at $39, so by setting the line number in the basic header to the address of the table, &amp;quot;LAX ($39),y&amp;quot; can be used for the table access.&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=976</id>
		<title>Christmas Tree</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Christmas_Tree&amp;diff=976"/>
				<updated>2021-12-25T20:03:55Z</updated>
		
		<summary type="html">&lt;p&gt;Serato: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
During the [https://demozoo.org/parties/4398/ Vintage Computing Christmas Challenge 2021] the goal was to create the shape of a given Christmas tree with as few bytes as possible. All platforms and languages were allowed.&lt;br /&gt;
The tree should be centered and look exactly like shown bellow.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
                          *&lt;br /&gt;
                         ***&lt;br /&gt;
                        *****&lt;br /&gt;
                       *******&lt;br /&gt;
                         ***&lt;br /&gt;
                       *******&lt;br /&gt;
                     ***********&lt;br /&gt;
                   ***************&lt;br /&gt;
                        ***** &lt;br /&gt;
                     *********** &lt;br /&gt;
                  ***************** &lt;br /&gt;
               *********************** &lt;br /&gt;
                         ***&lt;br /&gt;
                         ***&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There were mainly two kinds of approaches:&lt;br /&gt;
* calculate stars using a formula&lt;br /&gt;
* save amount of stars within data&lt;br /&gt;
Do to the trunk of the tree, the second type was more efficient. &lt;br /&gt;
=== Shortest DOS version ===&lt;br /&gt;
The shortest DOS version with 44 bytes came from Hellmood:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h			; define start of code for data access&lt;br /&gt;
db 80				; screen width, located at [SI], also &amp;quot;push ax&amp;quot;&lt;br /&gt;
mov bx,d			; pointer to data for XLAT&lt;br /&gt;
mov cx,1120			; 14 lines with 80 chars each&lt;br /&gt;
X: mov ax,cx		; get current sequence position&lt;br /&gt;
div byte [si]		; transform to [X,Y] in AL, AH&lt;br /&gt;
xlat				; get tree width for current line number&lt;br /&gt;
sub ah,40			; center tree in the middle&lt;br /&gt;
jnc F				; - &lt;br /&gt;
neg ah				; -&lt;br /&gt;
F: sub ah,al		; inside or outside tree?&lt;br /&gt;
salc				; set AL depending on carry flag&lt;br /&gt;
imul ax,byte -42	; transform into STAR or nothing&lt;br /&gt;
int 29h				; write current char to screen&lt;br /&gt;
loop X				; repeat unil all chars are plotter&lt;br /&gt;
ret					; return to prompt (JMP to former AX=0x0000)&lt;br /&gt;
d:db 2,2,12,9,6,3,8,6,4,2,4,3,2,1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Winning entry for C64 ===&lt;br /&gt;
The shortest entry overall was for the C64 and was submitted by Serato with only 37 bytes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;6502&amp;quot;&amp;gt;&lt;br /&gt;
		!cpu 6510			; enable unintended opcodes in ACME assembler&lt;br /&gt;
&lt;br /&gt;
		chrout = $FFD2&lt;br /&gt;
		crlf = $AAD7&lt;br /&gt;
		pntr = $D3&lt;br /&gt;
		width = 40&lt;br /&gt;
&lt;br /&gt;
		*=$304-39&lt;br /&gt;
table&lt;br /&gt;
		!byte width-1  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-5  &lt;br /&gt;
		!byte width-7  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-7  &lt;br /&gt;
		!byte width-11 &lt;br /&gt;
		!byte width-15 &lt;br /&gt;
		!byte width-5  &lt;br /&gt;
		!byte width-11 &lt;br /&gt;
		!byte width-17 &lt;br /&gt;
		!byte width-23 &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
		!byte width-3  &lt;br /&gt;
entry&lt;br /&gt;
		lax	table-1,y&lt;br /&gt;
		bmi *&lt;br /&gt;
		lsr&lt;br /&gt;
		sta pntr&lt;br /&gt;
		lda #'*'&lt;br /&gt;
-		jsr chrout&lt;br /&gt;
		inx&lt;br /&gt;
		cpx #width&lt;br /&gt;
		bne -&lt;br /&gt;
		jsr crlf&lt;br /&gt;
		iny&lt;br /&gt;
		jmp entry&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Serato</name></author>	</entry>

	</feed>