Skip to content

Instantly share code, notes, and snippets.

@ped7g
Last active August 27, 2026 10:44
Show Gist options
  • Select an option

  • Save ped7g/f2c8fe12b0548c6afce672ed651c65d5 to your computer and use it in GitHub Desktop.

Select an option

Save ped7g/f2c8fe12b0548c6afce672ed651c65d5 to your computer and use it in GitHub Desktop.
ZX Spectrum Next Hilber curve (58 bytes dot command)
; Author: Ped7g ; (C) 2026 ; license: MIT / GPL / Public Domain (pick whichever fits best for you)
; dot-command for ZX Spectrum Next to draw Hilbert curve in standard ULA 256x192 mode
; assembled with: https://github.com/z00m128/sjasmplus/
; Hilbert curve description in "rewrite system" (from https://en.wikipedia.org/wiki/Hilbert_curve ):
; Here + is rotate left 90° (CCW), - is rotate right 90° (CW), F is draw forward, A and B don't draw
; A → +BF−AFA−FB+
; B → −AF+BFB+FA−
; rotate left 90° ; opcode manipulation ; xor value ; counterclockwise CCW
; right -> up ; inc e -> dec d ; 1C -> 15 ; ^09
; up -> left ; dec d -> dec e ; 15 -> 1D ; ^08
; left -> down ; dec e -> inc d ; 1D -> 14 ; ^09
; down -> right ; inc d -> inc e ; 14 -> 1C ; ^08
; rotate right 90° ; opcode manipulation ; xor value ; clockwise CW
; right -> down ; inc e -> inc d ; 1C -> 14 ; ^08
; down -> left ; inc d -> dec e ; 14 -> 1D ; ^09
; left -> up ; dec e -> dec d ; 1D -> 15 ; ^08
; up -> right ; dec d -> inc e ; 15 -> 1C ; ^09
START_X EQU 50
START_Y EQU 10
START_N EQU 6 ; recursion depth
DRAW_L EQU 5 ; length of segment in pixels
START_DIR EQU $14 ; `inc d` for "down" direction (starts with variant "A")
SPIN_1 EQU $08 ; xor to rotate up/down CCW and left/right CW
SPIN_2 EQU $09 ; xor to rotate up/down CW and left/right CCW
OPT --zxnext --syntax=abf
ORG $2000
OUTPUT "hilbert.dot"
ld de,(START_Y << 8) | START_X ; Y, X
ld c,START_N ; N
ld a,START_DIR ; A = direction instruction
; |
; fallthrough into hilbertLine (will return to NextZXOS after defined recursion depth)
; |
; v
hilbertLine:
; C = depth, DE = coordinates, A = direction (as Z80 instruction)
; implements "rewrite system": "A" → "+BF−AFA−FB+", "B" → "−AF+BFB+FA−" (same code for both "A" and "B" variants, just entry state differs)
; register A (direction) defines whether this was entered ready to do "+" (ie. doing "A" variant) or "-" (doing "B" variant)
dec c
jr z,.return ; comments follow "A" variant, for "B" variant the spins and A/B calls have flipped interpretation
xor SPIN_1 ; +
call hilbertLine ; B (with -)
call draw
xor SPIN_1 ; -
call hilbertLine ; A (with +)
call draw
call hilbertLine ; A (with +)
xor SPIN_2 ; -
call draw
call hilbertLine ; B (with -)
xor SPIN_2 ; +
.return:
inc c ; restore depth
ret
draw:
; draw forward DRAW_L pixels, DE = coordinates, A = direction (as Z80 instruction)
ld (.updateCoords),a ; set direction instruction ({inc|dec d|e})
ex af,af ; preserve A during drawing loop
ld b,DRAW_L
.loop:
pixelad ; D = y coord, E = x coord -> HL = ULA VRAM address
setae ; E = x coord -> A = ULA pixel mask
or (hl)
ld (hl),a
.updateCoords+0:
nop ; instruction to update coordinates goes here (self modified code)
djnz .loop
ex af,af ; restore A (direction instruction)
ret
@ped7g

ped7g commented Aug 27, 2026

Copy link
Copy Markdown
Author

lines 46-51 can be moved to preamble of draw: and call that twice like:

hilbertLine:
    ; C = depth, DE = coordinates, A = direction (as Z80 instruction)
    ; implements "rewrite system": "A" → "+BF−AFA−FB+", "B" → "−AF+BFB+FA−" (same code for both "A" and "B" variants, just entry state differs)
    ; register A (direction) defines whether this was entered ready to do "+" (ie. doing "A" variant) or "-" (doing "B" variant)
    dec     c
    jr      z,.return               ; comments follow "A" variant, for "B" variant the spins and A/B calls have flipped interpretation
    call    spin1Line               ; +BF
    call    spin1Line               ; -AF
    call    hilbertLine             ; A (with +)
    xor     SPIN_2                  ; -
    call    draw
    call    hilbertLine             ; B (with -)
    xor     SPIN_2                  ; +
.return:
    inc     c                       ; restore depth
    ret

spin1Line:
    xor     SPIN_1                  ; + / -
    call    hilbertLine             ; B (with -) / A (with +)
draw:

which should save 5 bytes, so 53 bytes? Verify and edit the gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment