Building a Star for a Vintage Computer
My take on the Vintage Star challenge.
I missed the Dec 26 deadline for submitting, but did get a star working on the ZX81. My attempt isn’t spectacular, but it does work. I recommend checking out the other entries for Vintage Christmas Star Challenge.
# Starting with a basic star.
I actually started with a ZX81 BASIC version. It is pretty brute force, using the symmetry of the star to print to the screen. Using a single loop, the BASIC version takes advantage of the ZX81’s string slicing capability to determine what to print. My version is four lines.
10 FOR L = 1 TO 13
20 LET A$="*************"( TO L)
30 PRINT AT L,4;A$;AT 18-L,13-L;A$;AT L,13-L;A$;AT 18-L,4;A$
40 NEXT L
I thought about ways to shrink this further. For example, adding a star to A$, but it adds another line. The challenge is source code size and/or code size, I do think I can shrink the memory quite a bit using quirks of the way the ZX81 saves numbers. But, the above version is more readable.
# Making it all the better, faster, stronger.
Obviously, z80 machine code should be much smaller. A such, I took the BASIC program as a guide and built an assembly version. My first version worked, but was 80 bytes of code. From there, I started to optimize the code getting it down to 45 bytes.
Star, 2022 by Steven Reid
Afterwards, I realized I could have removed the print routine. The ROM routine to locate the screen position sets the HL register. This would be a bit faster, but wouldn’t shrink the program any. Here is the annotated version with memory counts:
org 16514
printat: equ $08f5 ; rom routine to set location on screen
ld d,13 ; 02 number of stars to print
loop:
; first point - d,4
ld b,d ; 03 set b (X) to d
ld e,4 ; 05 set e (Y) to 4 (location)
call print_char_at ; 08
; second point - 18-d,4
ld a,18 ; 10 calculate X position
sub d ; 11
push af ; 12 save for later
ld b,a ; 13 set b (X) to a (e is 4 still)
call print_char_at ; 16
; third point - d,13-d
ld b,d ; 17 set b (x) to d
ld a,13 ; 19 calculate Y position
sub d ; 20
ld e,a ; 21 set e (Y) to a
call print_char_at ; 24
; forth point - 18-d,13-d
pop bc ; 25 restore b (X) (e is 13-d still)
call print_char_at ; 28
dec d ; 29 decrement loop
jr nz,loop ; 31 until we are done!
ret ; 32
print_char_at:
push de ; 33 save de as printat will distory it
ld c,e ; 34 b is X location, c is Y location
call printat ; 37 position character
pop de ; 38 restore de
ld b,d ; 39 number of stars to print
print_loop:
; ld (hl),23 ; 41 alternate version
; inc hl ; 42 but no extra memory
ld a,23 ; 41 the astrick character (ZX81)
rst $10 ; 42 print char (ROM routine)
djnz print_loop ; 44 and loop until done!
ret ; 45
# Fun for next time.
Now, taking a different approach, I probably could shrink it further. My mind, however, just can’t convolute itself that much. I looked the winning entry and am still in awe at the conciseness and tricks used.
In the end though, I like what I did. It works and completed the challenge. My mind optimized what it could and is still, mostly, readable. Maybe not a contender, but I had fun. I look forward to the next competition.