; POLARIS
; by 'Diminished'
; Vintage Computing Christmas Challenge 2022
; Christmas Star Challenge
; December 2022
; for BBC Micro Model B, with OS 1.2.
; version 1A (infinite loop edition)

; -------------

; assemble using beebasm 1.1: https://github.com/stardot/beebasm/
; this will produce a disc image "polaris.ssd":

; beebasm -v -i source.txt -do polaris.ssd

; -------------

; use zero page, and just hope nothing breaks:
ORG &20

; OS "write character" system call entry point:
OSWRCH=&FFEE

; -------------



; How the variables should update:
; -----inc----->   ------dec---->
;  9 10 11 12 13   17 16 15 14 13   Q (t_vdu_buf + 4): self-modify INC to DEC, reset to 17 at half-way
; ------------dec--------------->
; 21 20 19 18 17   21 20 19 18 17   M (t_vdu_buf + 3): reset at half-way
; ------------inc--------------->
;  5  6  7  8  9    5  6  7  8  9  (26-M) (Y register): reset at half-way



.start

; OS CLS poke, to make CLS (VDU 12) fill a rectangle rather than just clearing it.
; we do this on every ".start" (i.e. on both halves of the star),
; so that we always have 42 in A going into the next step.

LDA #'*'
STA 856

; init M with 21

; note that we can't just start with 21 pre-initialised in t_vdu_buf[3],
; as it must be re-initialised before the second half of the star
; is drawn.

; as luck would have it, 21 is '*' (i.e. 42) >> 1,
; so using LSR saves one byte over the naive LDA #21.

LSR A
STA t_vdu_buf + 3      ; M, master copy

; init 26-M
; this is kept in the Y register, so we can CPY it for the inner loop condition.

LDY #5


; each iteration of P_loop draws a pair of rectangles.
.P_loop


; first VDU sequence.
; draw the vertical rectangle.

LDA #28                ; VDU 28
STA t_vdu_buf + 5

; [4] already contains Q; [3] already contains M.
; we must duplicate Q into [2] as well.

LDA t_vdu_buf + 4      ; t_vdu_buf[2] = t_vdu_buf[4] (Q)
STA t_vdu_buf + 2

STY t_vdu_buf + 1      ; (26-M)

; [0] already contains 12 (CLS) -- it is constant data.

; start reading VDU bytes from t_vdu_buf[5] and working backwards:

LDX #5
JSR S_vdu              ; execute VDU sequence


; second VDU sequence.
; draw the horizontal rectangle.

; [6], [4], [3], [2], [0] are already correctly populated.
; [1] contains junk (prior 26-M value), but we don't care.
; which just leaves [5]:

STY t_vdu_buf + 5      ; (26-M)

; start reading VDU bytes from t_vdu_buf[6] this time:

LDX #6
JSR S_vdu              ; execute VDU sequence


; increment Q.
; after the half way point, this is self-modified from INC to DEC:

.selfmod_inc_to_dec
INC t_vdu_buf + 4

; decrement M.

DEC t_vdu_buf + 3

; increment (26-M).

INY


; have we drawn half a star yet? if not, loop and go again.

CPY #10
BNE P_loop


; reach this point after drawing half a star
; (either first half or second half)

; selfmod Q increment to decrement:

LDA #&C6               ; INC -> DEC
STA selfmod_inc_to_dec

; reset Q to 17
LDA #17
STA t_vdu_buf + 4

; begin second half (this loops forever).
; in order to re-initialise M and 26-M,
; we go right back to .start, and run the
; entire thing again from the top.

BPL start


; -------------


; VDU subroutine
; on entry: X must contain 5 or 6
; on exit: A scribbled, Y untouched, X=&FF

.S_vdu
LDA t_vdu_buf, X
JSR OSWRCH
DEX
BPL S_vdu
RTS



; -------------


; VDU byte buffer
; certain values are pre-initialised:

; - [0]: (constant) VDU 12 (CLS)
; - [4]: (variable) Q (for first half of star)
; - [6]: (constant) VDU 28 (define text window for horizontal rectangles)

;             <--- bytes sent to OS this way <---

;               [0]  [1] [2] [3]  [4] [5]   [6]
;               12  26-M  q   M    Q   28       ; (for horizontal rectangles)
;           or  12  JUNK  q   M    Q   26-M  28 ; (for vertical rectangles)


.t_vdu_buf equb 12,   0,  0,  0,   9,  0,    28

; -------------

.end

print "length:", end-start
SAVE "DEMO",start,end