Last active
January 31, 2021 00:36
-
-
Save Sakrac/448e136531e8731da80350a565a17846 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The explanation how this works is below, this change moved code to zero page to save 1 byte. | |
Last minute update: | |
Disassembly: | |
$46 dex | |
$47 ldy #$ec | |
$49 txa | |
$4a adc #$0e | |
$4c bpl $50 | |
$4e eor #$ff | |
$50 adc #8 | |
$52 bmi $52 | |
$54 sta 2 | |
$56 tya | |
$57 bpl $5b | |
$59 eor #$ff | |
$5b cmp 2 | |
$5d bcs $60 | |
$5f txa | |
$60 lsr | |
$61 lda #$20 | |
$63 bcc $67 | |
$65 asl | |
$66 asl | |
$67 sta $03c5 | |
$6a inc $68 | |
$6c bne $70 | |
$6e inc $69 | |
$70 iny | |
$71 cpy #$14 | |
$73 bne $49 | |
$75 beq $46 | |
Source: | |
org $46 | |
{ ; x is $ff at entry, loops back to entry point every line | |
{ | |
dex ; decrement the row # here to make row loop work without extra cpx | |
ldy #-20 ; y is horizontal position, leftmost = -20, rightmost = +19 | |
{ ; first iteration y starts with 1, so there are 19 bytes to ignore | |
txa | |
adc #14 ; compensate for initial x value | |
{ | |
bpl % | |
eor #$ff | |
} | |
adc #8 ; largest x=20, so add 8 to y, largest y = 12 | |
bmi * ; when row = $78 the adc will set the N flag so loop infinitely when done | |
sta 2 ; store off the positive distance from center | |
tya | |
{ | |
bpl % | |
eor #$ff | |
} | |
{ | |
cmp 2 | |
bcs % | |
txa | |
} | |
{ | |
lsr | |
lda #$20 | |
bcc % | |
asl | |
asl | |
} | |
{ | |
sta $400-40*1-19 ; adjust 1 row up + y start value | |
inc !+1 | |
bne % | |
inc !+2 | |
} | |
iny | |
cpy #20 | |
bne ! ; <- autostarts here with Z clear (address $73) | |
} | |
beq ! ; loop each row | |
} | |
} | |
Theory: kernal will jsr $73 sometime at startup! | |
Previous version: | |
org $2e4 | |
{ ; x is $ed at entry, loops back to entry point every line | |
{ | |
inx | |
ldy #-20 | |
{ | |
txa | |
{ | |
bpl % | |
eor #$ff | |
} | |
adc #8 | |
bmi * | |
sta 2 | |
tya | |
{ | |
bpl % | |
eor #$ff | |
} | |
{ | |
cmp 2 | |
bcs % | |
txa | |
} | |
{ | |
lsr | |
lda #$20 | |
bcc % | |
asl | |
asl | |
} | |
{ | |
sta $400-40*5 | |
inc !+1 | |
bne % | |
inc !+2 | |
} | |
iny | |
cpy #20 | |
bne ! | |
} | |
dc.b $4c | |
} | |
dc.w ! | |
} | |
EXPLANATION | |
First idea: | |
Spiral is almost drawn as a distance from closest border as alternating @ and space, with the @ closest to the border | |
0 <= y <= 24 { | |
0 <= x <= 40 { | |
x2 = x < 20 ? x : 39-x | |
y2 = y <= 12 : y : 24-y | |
*screen++ = ((x2 < y2 ? x2 : y2) & 1) ? '@' : ' ' | |
} | |
} | |
To correct the image as a spiral, shift the top left quadrant two steps left | |
0 <= y <= 24 { | |
0 <= x <= 39 { | |
x2 = x < 20 ? x : 39-x | |
y2 = y <= 12 : y : 24-y | |
if( x2 < 20 && y <= 12) x2 += 2 | |
*screen++ = ((x2 < y2 ? x2 : y2) & 1) ? '@' : ' ' | |
} | |
} | |
at this point: 76 bytes! | |
optimization #1: I used a basic loader, I can use a 2 byte auto start vector instead so I chose $314 interrupt! | |
I decided to put the code before $314. | |
at this point: 66 bytes! | |
Realized I was copying the row to zero page for comparing, then if y2 < x2 loading it back from zero page instead of using | |
tya, the lowest bit is the same in both cases | |
65 bytes! | |
optimization #1: it is easier to count down to 0 than to count up | |
24 >= y >= 0 { | |
39 >= x >= 0 { | |
x2 = x < 20 ? x : 39-x | |
y2 = y <= 12 : y : 24-y | |
if( x2 > 20 && y >= 12) x2 += 2 | |
*screen++ = ((x2 < y2 ? x2 : y) & 1) ? '@' : ' ' | |
} | |
} | |
at this point: about the same size, but I realized that I can count the distance in reverse instead. | |
Back to trying to draw the distance from the border, but this time the max value (19) is the column at the border, and 12 the row at the top. | |
Unfortunately i had a bug at this point so I took out the quadrant fix and tried to get just the rectangles drawing again. | |
By chance I discovered that by slightly shifting X and Y I got the spiral shape without the quadrant fix! several bytes saved! | |
To make the center flip vertically/horizontally cheaper I also switched to counting from -half to +half and doing eor #$ff to "negate" at the center. | |
-13 <= y < 12 { | |
-20 <= x < 20 { | |
y2 = (y < 0 ? y^$ff : y) + 8 ; add 8 to make rows compare with columns in the corners (20 = 12+8) | |
x2 = x < 0 ? x^$ff : x | |
*screen++ = ((x2 > y2 ? x2 : y) & 1) ? ' ' : '@' | |
} | |
} | |
at this point: 57 bytes! | |
This is about as far as I could go without trickery so next was making the line loop cheaper. | |
I can just keep drawing for a bit after the screen so y can keep going but it needs to stop at some point. | |
New test: when y2 + 8 check is done, check if it sets the N flag. | |
y = -13 | |
{ | |
-20 <= x < 20 { | |
y2 = (y < 0 ? y^$ff : y) + 8 ; add 8 to make rows compare with columns in the corners (20 = 12+8) | |
bmi * | |
x2 = x < 0 ? x^$ff : x | |
*screen++ = ((x2 > y2 ? x2 : y2) & 1) ? ' ' : '@' | |
} | |
beq back to loop | |
} | |
this saved a cpy #12 and moved the branch, so we're at 55 bytes | |
Now that branch at the end is two bytes, but if I change to a jmp the start address is already right after at $314. | |
Problem is I can't initialize the y value to -13 then. | |
Solution: when entering this code x is kind of close, $ed, which can be compensated by starting to | |
draw the screen 5 lines earlier and move the increment to the top, but also requires switching x and y | |
registers. | |
-20 <= y < 20 { | |
inx | |
y2 = (x < 0 ? x^$ff : x) + 8 ; add 8 to make rows compare with columns in the corners (20 = 12+8) | |
bmi * | |
x2 = y < 0 ? y^$ff : y | |
*screen++ = ((x2 > y2 ? x2 : y2) & 1) ? ' ' : '@' | |
} | |
dc.b $4c ; jmp opcode | |
Final size: 52 bytes including load address + autostart vector, effective code size: 48 bytes (well, 50 if you count the jump address :) |
only works in c64 vice auto start, requires x to be $ed on entry
51
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
fiddy-too!