# PRINTS OUT THE DRAGON CURVE

# 128x128 IMAGE IS STORED IN MEMORY WHERE (PX,PY) IS ADDRESS ((PY+80)<<7)|PX

# XY = ((PY+80)<<7)|PX
SET M Y_OFFSET
LD C
SET M PY
LD B
ADD A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SET M MASK2
LD C
AND A
MOV X A
SET M MASK1
LD C
AND A
MOV B A
SET M PX
LD C
OR A
MOV Y A

# PRINT MARK
SET M MARK
LD A
MOV M1 X
MOV M2 Y
STO A

LOOP:

# XY = -LOOP_COUNT
SET M LOOP_COUNT_HIGH_BYTE
LD B
MOV D B
NOT A
MOV X A
SET M LOOP_COUNT_LOW_BYTE
LD B
NOT A
MOV Y A
INC XY

# XY &= LOOP_COUNT
MOV C Y
AND A
MOV Y A
MOV B D
MOV C X
AND A

# XY <<= 1
MOV B A 
SHL A
MOV C A
SET B -2
AND D
MOV B Y
SHL A
MOV C A
SET B 1
AND A
MOV B D
MOV C A
OR A
MOV X A
MOV B Y
SHL A
MOV C A
SET B -2
AND A

# IF (XY & LOOP_COUNT) == 0 GOTO DECREMENT_DIRECTION
SET M LOOP_COUNT_LOW_BYTE
LD B
MOV C A
AND A
BNZ DECREMENT_DIRECTION
SET M LOOP_COUNT_HIGH_BYTE
LD B
MOV C X
AND A
BNZ DECREMENT_DIRECTION

# IF ++DIRECTION == 4 THEN DIRECTION = 0
SET M DIRECTION
LD B
INC A
MOV C A
SET B 4
XOR A
BNE DONT_SET_DIRECTION_ZERO
CLR C
DONT_SET_DIRECTION_ZERO:
STO C
JMP MOVE

# IF DIRECTION == 0 THEN DIRECTION = 3 ELSE DIRECTION--
DECREMENT_DIRECTION:
SET M DIRECTION
LD B
CLR C
XOR A
BE SET_DIRECTION_THREE
MOV C B
SET B -1
ADD A
STO A
MOV C A
JMP MOVE
SET_DIRECTION_THREE:
SET B 3
STO B
MOV C B

# BRANCH BASED ON DIRECTION
MOVE:
CLR B
XOR A
BE MOVE0
SET B 1
XOR A
BE MOVE1
SET B 2
XOR A
BE MOVE2

# DIRECTION 3, PX--
SET M PX
LD C
SET B -1
ADD A
STO A
JMP DRAW

# DIRECTION 0, PY--
MOVE0:
SET M PY
LD C
SET B -1
ADD A
STO A
JMP DRAW

# DIRECTION 1, PX++
MOVE1:
SET M PX
LD B
INC A
STO A
JMP DRAW

# DIRECTION 2, PY++
MOVE2:
SET M PY
LD B
INC A
STO A
JMP DRAW

DRAW:
# XY = ((PY+80)<<7)|PX
SET M Y_OFFSET
LD C
SET M PY
LD B
ADD A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SHL A
MOV B A
SET M MASK2
LD C
AND A
MOV X A
SET M MASK1
LD C
AND A
MOV B A
SET M PX
LD C
OR A
MOV Y A

# PRINT MARK
SET M MARK
LD A
MOV M1 X
MOV M2 Y
STO A

# INCREMENT LOOP_COUNT
SET M LOOP_COUNT_HIGH_BYTE
LD A
MOV X A
SET M LOOP_COUNT_LOW_BYTE
LD A
MOV Y A
INC XY
SET M LOOP_COUNT_HIGH_BYTE
MOV A X
STO A
SET M LOOP_COUNT_LOW_BYTE
MOV A Y
STO A

# IF XY != 2000h GOTO LOOP
SET M LOOP_END_HIGH_BYTE
LD C
MOV B X
XOR A
BNE LOOP

# PRINT OUT IMAGE
SET M 2800h
MOV XY M 
PRINT_LOOP:

# PRINT CHARACTER AT ADDRESS XY
MOV M1 X
MOV M2 Y
LD B
CLR C
XOR A
BZ PRINT_SPACE
SET M FFFEh
STO B
SET M FFFFh
STO B
SET M FFFEh
STO B
SET M FFFFh
STO B
JMP PRINTED
PRINT_SPACE:
SET M SPACE
LD A
SET M FFFEh
STO A
SET M FFFFh
STO A
SET M FFFEh
STO A
SET M FFFFh
STO A
PRINTED:

# IF Y == 0 THEN PRINT EOL
CLR C
MOV B Y
XOR A
BNE Y_NOT_ZERO
SET B 0Dh
SET M FFFEh
STO B
SET M FFFFh
STO B
SET B 0Ah
SET M FFFEh
STO B
SET M FFFFh
STO B

# IF Y == 128 THEN PRINT EOL
Y_NOT_ZERO:
SET M MASK1
LD C
MOV B Y
XOR A
BNE Y_NOT_128
SET B 0Dh
SET M FFFEh
STO B
SET M FFFFh
STO B
SET B 0Ah
SET M FFFEh
STO B
SET M FFFFh
STO B

# IF ++XY == 6800h THEN EXIT ELSE GOTO PRINT_LOOP
Y_NOT_128:
INC XY
SET M PRINT_END_HIGH_BYTE
LD B
MOV C X
XOR A
BNE PRINT_LOOP

# PRINT ONE LAST EOL
SET B 0Dh
SET M FFFEh
STO B
SET M FFFFh
STO B
SET B 0Ah
SET M FFFEh
STO B
SET M FFFFh
STO B

HLT

LOOP_COUNT_HIGH_BYTE:
BYTE 00
LOOP_COUNT_LOW_BYTE:
BYTE 01

PX:
BYTE 86

PY:
BYTE 20

DIRECTION:
BYTE 0

SPACE:
STRING " "

MARK:
STRING "#" 

Y_OFFSET:
BYTE 80

MASK1:
BYTE 80h

MASK2:
BYTE 7Fh

LOOP_END_HIGH_BYTE:
BYTE 20h

PRINT_END_HIGH_BYTE:
BYTE 68h