NOLIST



SCR_SET_MODE EQU #BC0E ;; A=mode
TXT_OUTPUT EQU #BB5A ;; A=character

EXPECTED_ADDRESS EQU #5204



ORG EXPECTED_ADDRESS
RUN winape_entry



program_begin:

    ;; Store a pattern that is used multiple times.
    ;;
    ;;   Input:
    ;;     A  - Symbol to store.
    ;;     HL - Row and column of upper left symbol.
    ;;
    ;;   Changes:
    ;;     H - Incremented by one.

    print_pattern:
        IF2 : IF $ - EXPECTED_ADDRESS
            PRINT "Routine 'print_pattern' needs to be located at #$EXPECTED_ADDRESS, but is at #$print_pattern."
            STOP
        ENDIF : ENDIF
        LD (HL),A : INC H : INC L ;;  3 ;;  1
        LD (HL),A : INC H : INC L ;;  3 ;;  |\
        LD (HL),A : DEC L         ;;  2 ;;  | 2
        LD (HL),A : DEC L         ;;  2 ;;  |  \
        LD (HL),A : DEC H : DEC H ;;  3 ;;  5-4-3
        RET                       ;;  1 ;;
        ;;                        ;; -- ;;
        ;;                        ;; 14 ;;

program_entry:

    ;; AF:FFA4 HL:ABFF DE:0040 BC:B0FF IX:B0A0 IY:0000
    ;;                            ^^^^

    ;; Redirect (in this program) unused restart 5/#28 to pattern printing routine.
    LD HL,print_pattern : LD (#29),HL ;;  6 ;; Only store address, jump command is already there.
    ;;                                ;; -- ;;
    ;;                                ;;  6 ;;

    ;; Prepare octant (upper left quarter, lower triangle).
    ;; The range #xxyy with xx,yy from [1,19] is filled with zeros.
    ASTERISK EQU #2A          ;;  - ;;
    LD A,ASTERISK             ;;  2 ;; Store character to print in A.
    ADD HL,BC : RST #28       ;;  2 ;; Store pattern for position 3|3. (HL+BC=#0303)
    ADD HL,HL : LD (HL),A     ;;  2 ;; Store single star for position 6|6.
    INC H : INC L : LD (HL),A ;;  3 ;; Store single star for position 7|7.
    INC H : INC L : RST #28   ;;  4 ;; Store pattern for position 8|8.
    LD L,5 : RST #28          ;;  3 ;; Store pattern for position 8|5.
    LD L,2 : RST #28          ;;  3 ;; Store pattern for position 8|2.
    LD HL,#0A01 : LD (HL),A   ;;  4 ;; Store single star for position 10|1.
    ;;                        ;; -- ;;
    ;;                        ;; 23 ;;

    ;; AF:2A0A HL:0A01 DE:0040 BC:B0FF IX:B0A0 IY:0000
    ;;     (^^)   ^^                       (^^)

    ;; Mirror prepared octant to other octants and quadrants.
    ;; The order is important: Because the loop runs backwards,
    ;; the needed parts of the upper triangle are available.
    LD D,H                                          ;;  1 ;; Store constant #0A.
    LD B,D                                          ;;  1 ;; Row in upper left quadrant.
    m__y_loop:                                      ;;  - ;;
        LD C,D                                      ;;  1 ;; Column in upper left quadrant.
        m__x_loop:                                  ;;  - ;;
            LD A,C : CP A,B                         ;;  2 ;; Lower or upper triangle?
            LD A,(BC)                               ;;  1 ;; Already load stored value to A.
            JR NC,m__skip                           ;;  2 ;;
                LD H,C : LD L,B : LD (HL),A         ;;  3 ;; If in lower triangle, mirror to upper triangle.
            m__skip:                                ;;  - ;;
            LD H,D : LD L,D : ADD HL,HL : SBC HL,BC ;;  5 ;; Calculate inverse row and column in HL.
            LD (HL),A                               ;;  1 ;; Mirror to lower right quadrant.
            PUSH HL : LD H,B : LD (HL),A : POP HL   ;;  4 ;; Mirror to upper right quadrant.
            LD L,C : LD (HL),A                      ;;  2 ;; Mirror to lower left quadrant.
        DEC C : JR NZ,m__x_loop                     ;;  3 ;;
    DJNZ m__y_loop                                  ;;  2 ;;
    ;;                                              ;; -- ;;
    ;;                                              ;; 28 ;;

    ;; AF:0042 HL:1301 DE:0A40 BC:0000 IX:B0A0 IY:0000
    ;;            ^^

    ;; Transfer completed pattern from memory to screen.
    LD B,H                                        ;;  1 ;; Row in all quadrants.
    t__y_loop:                                    ;;  - ;;
        LD C,H                                    ;;  1 ;; Column in all quadrants.
        t__x_loop:                                ;;  - ;;
            LD (#B726),BC                         ;;  4 ;; Position cursor.
            LD A,(BC) : CALL TXT_OUTPUT           ;;  4 ;; Print star on screen.
        DEC C : JR NZ,t__x_loop                   ;;  3 ;;
    DJNZ t__y_loop                                ;;  2 ;;
    ;;                                            ;; -- ;;
    ;;                                            ;; 15 ;;

    ;; A:0042 HL:1301 DE:0A40 BC:0000 IX:B0A0 IY:0000
    ;;

    ;; Wait forever.
    JR $   ;;  2 ;;
    ;;     ;; -- ;;
    ;;     ;;  2 ;;

program_end:



;; Entry point for WinAPE assembler.
winape_entry:

    ;; Clear screen. This is automatically done when program was loaded from file.
    LD A,1 : CALL SCR_SET_MODE

    ;; Set second register set as it is set when loaded from file.
    ;; NOTE: As long as interrupts are running, this cannot be used.
    ;;EX AF,AF' : EXX
    ;;    LD HL,8D8C : PUSH HL : POP AF
    ;;    LD HL,#B8D9
    ;;    LD DE,#8020
    ;;    LD BC,#7F8D
    ;;EX AF,AF' : EXX

    ;; Set first register set as it is set when loaded from file.
    LD HL,#FFA4 : PUSH HL : POP AF
    LD HL,#ABFF
    LD DE,#0040
    LD BC,#B0FF
    LD IX,#B0A0
    LD IY,#0000
    ;;LD SP,#BFFA

    CALL program_entry

    ;; If the program returns, the computer will be reset.
    RST #00



IF2
    program_size EQU program_end - program_begin
    PRINT "Program size: &program_size bytes"
    PRINT 'SAVE"snow.bin",B,&program_begin,&program_size,&program_entry'
ENDIF
