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 ReidStar, 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.



Comments on this article:

No comments so far.

Write a comment:

Type The Letters You See.
[captcha image][captcha image][captcha image][captcha image][captcha image][captcha image]
not case sensitive