; основной модуль
        .LA     1000

        CCM=114 ;копия регистра 177716 по записи (рабочая область)

;начало
BEGIN:  NOP
        ;нужно перенести код страницы 1 в стр.1
        mov     #14000,@#177716
        mov     #PG1BGN,R1
        MOV     #100000,R0
        MOV     #PG1END-PG1BGN,R2
0$:     movb    (R1)+,(R0)+
        sob     R2, 0$
        mov     #16000,@#177716
        
TRP4:   MOV     #BEGIN,SP
        CALL    INIT
        call    DRWWIN
        .WORD   141004
        .byte   10,20
        .byte   125,377
        call    DRWWNH
        .WORD   47020
        .byte   7,14
        .byte   252,377
        call    DRWWNH
        .WORD   60024
        .byte   10,15
        .byte   377,377
        clr     r0
        sob     r0,.
        call    RSTSCR
        clr     r0
        sob     r0,.
        call    RSTSCR
        clr     r0
        sob     r0,.
        call    RSTSCR
        HALT
; ───────────────────────────────────────────────────────────────────────────

INIT:   MOV     #340,R0     ;пока сделаем максимальный приоритет
        MTPS    R0
        MOV     #TRP4,@#4
        MOV     R0,@#6
        MOV     #16000,@#CCM
        mov     #100000,SCRBUF
        MOV     R0,@#177662 ;запретим прерывания ль клавиатуры
        mov     #102, @#100
        mov     #2, @#102
INISCR: mov     #5400, @#177662 ;прерывание по вектору 100 всегда должны быть, по ним будет синхронизация
        mov     #1330, @#177664
        return

; Нарисовать рамку окна без тени
; Входные параметры за командой:
; Слово - адрес экрана верхнего левого угла окна
;         если бит 15 - то не сохранять в буфере область под окном.
; Байт - высота в символах
; Байт - ширина в символах
; Байт - маска цвета фона
; Байт - инверсная маска цвета символов

DRWWIN: mov     #5760, WCM1$
        clr     R3
        br      0DRW$
; ───────────────────────────────────────────────────────────────────────────
; Нарисовать рамку окна с тенью
; Входные параметры за командой:
; Слово - адрес экрана верхнего левого угла окна.
;         если бит 15 - то не сохранять в буфере область под окном.
; Байт - высота в символах
; Байт - ширина в символах
; Байт - маска цвета фона
; Байт - инверсная маска цвета символов

DRWWNH: mov     #5060, WCM1$
        mov     #1, R3
0DRW$:  mov     WCM1$, WCM2$

        mov     (SP), R5
        mov     (R5)+, -(SP)    ; Адрес экрана верхнего левого угла окна
        movb    (R5)+, R1       ; Высота в символах, не имеет смысла задавать меньше 2
        movb    (R5)+, R2       ; Ширина в символах, не имеет смысла задавать меньше 2
        movb    (R5)+, R0       ; маска цвета фона
        CALL    BY2WR
        mov     R0,BGCOLR   
        movb    (R5)+, R0       ; инверсная маска цвета символов
        CALL    BY2WR
        mov     R0,COLMSK
        mov     (SP)+,R0
        mov     R5, (SP)
        call    STRSCR          ; сохранить область экрана под окном при необходимости
        ; надо адрес экрана поместить в центр будущего окна.
        ; Ац = Авл + шир * 2 / 2 + выс * 10 / 2
        mov     R1, R3          ; высота. она не может быть больше 40 по определению
        asl     R3
        asl     R3              ; высота * 4
        add     R3, R0
        add     R2, R0          ; вот это наш центр экрана
        bic     #1, R0          ; выровняем по границе слова
        clrb    W$FLG
        clrb    H$FLG
        mov     #2, R3          ; начинаем рисовать с окна 2 х 2
        mov     R3, R4

0$:     call    DRWRKT
        mov     #5000, R5       ; сменить на wait
        sob     R5, .
        tstb    W$FLG
        bne     1$
        cmp     R4, R2          ; текущая ширина достигла заданной?
        blo     2$              ; нет еще
        mov     R2, R4          ; да - ограничим ширину заданной
        incb    W$FLG           ; отметим факт.
        br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:     cmp     (R4)+, -(R0)    ; раз не достигли, то тек. ширина + 2, адрес экрана - 2
1$:     tstb    H$FLG
        bne     3$
        cmp     R3, R1          ; текущая высота достигла заданной?
        bhis    4$              ; да
        sub     #1000, R0       ; нет ещё, тогда адрес экрана - 1000
        tst     (R3)+           ; тек. высота + 2
        br      0$              ; рисуем дальше
; ───────────────────────────────────────────────────────────────────────────

4$:     mov     R1, R3          ; да - ограничим высоту заданной
        incb    H$FLG           ; отметим факт.

3$:     tstb    W$FLG           ; если заданной ширины еще не достигли
        beq     0$              ; то продолжим рисовать.
        ; наконец рисуем рамку окна и выход.
        mov     #14000,@#177716 ; стр.5 в окно0, стр.1 в окно 1
        cmp     -(R3), -(R4)    ; конечные размеры уменьшаем на 2, чтобы вычесть углы
        mov     #231, R1        ; рисуем значок ╔
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        mov     #235, R1        ; значок ═
        mov     R3, -(SP)
        mov     R4, -(SP)
        beq     10$

11$:    tst     (R0)+           ; рисуем верхнюю часть рамки
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        sob     R4, 11$

10$:    tst     (R0)+
        mov     #213, R1        ; значок ╗
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        mov     #212, R1        ; значок ║
        tst     R3
        beq     12$

13$:    add     #1000, R0
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        sob     R3, 13$

12$:    add     #1000, R0
        mov     #214, R1        ; значок ╝
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        mov     #235, R1        ; значок ═
        mov     (SP)+, R4
        beq     14$

15$:    tst     -(R0)
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        sob     R4, 15$

14$:    mov     #230, R1        ; значок ╚
        tst     -(R0)
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        mov     (SP)+, R3
        beq     16$
        mov     #212, R1        ; значок ║

17$:    sub     #1000, R0
        call    @#DRWCHW        ; Вход: R0 - адрес вывода, R1 - код
        sob     R3, 17$
16$:    JMP     RSTPGE

; ───────────────────────────────────────────────────────────────────────────
; прорисовка распахивающегося окна
; вход: R0 - адрес экрана (текущий верхний левый адрес окна)
; R3 - текущая высота, отсчёт начинается с 2
; R4 - текущая ширина, отсчёт начинается с 2
; портит R5

DRWRKT:	mov		R0, -(SP)
		mov		R3, -(SP)
		mov		R4, -(SP)
		dec		R4				; рисуем на 1 символ меньше, т.к. он будет уже правой границей
2$:		mov		#10, R5			; рисуем верхнюю границу
1$:		mov		BGCOLR, (R0)
		add		#100, R0
		sob		R5, 1$
		sub		#776, R0
		sob		R4, 2$			; и так по всей текущей ширине
		dec		R3				; рисуем на 1 символ меньше, т.к. он будет уже нижней границей
WL4$:	mov		#10, R5			; рисуем правую границу
WL3$:	mov		BGCOLR, (R0)
WCM1$:	tst		1002(R0)		; тут либо формируем тень, либо нет
		add		#100, R0
		sob		R5, WL3$
		sob		R3, WL4$		; теперь вертикаль по всей текущей высоте
		mov		(SP), R4		; снова достаём текущую ширину
WL6$:	mov		#10, R5			; рисуем нижнюю границу
WL5$:	mov		BGCOLR, (R0)
WCM2$:	tst		1002(R0)		; тут либо формируем тень, либо нет
		add		#100, R0
		sob		R5, WL5$
		sub		#1002, R0
		sob		R4, WL6$		; и так по всей текущей ширине
		mov		2(SP), R3		; снова достаём текущую высоту
		tst		(R0)+
		sub		#2,R3
		beq		9$
8$:		mov		#10, R5			; рисуем левую границу
7$:		sub		#100, R0
		mov		BGCOLR, (R0)
		sob		R5, 7$
		sob		R3, 8$
9$:		mov		(SP)+, R4
		mov		(SP)+, R3
		mov		(SP)+, R0
		return
;расширение байта в слово. для цвета фона и символов
;вход:  R0 - мл.байт, значение; ст.байт - неважно
;выход: R0 - слово, значение
BY2WR:  movb    R0,-(SP)
        swab    R0
        clrb    R0
        bisb    (SP)+,R0
        return

; сохранение области экрана под окном
; вход: R0 - Адрес экрана верхнего левого угла окна
;       R1 - Высота в символах
;       R2 - Ширина в символах
;       R3 - 0 окно без тени, 1 - окно с тенью
STRSCR: jsr     r5, PUSHA
        mov     #15000,@#177716 ;стр.5 в окно0, стр.2 в окно1
        MOV     SCRBUF,R5   ; адрес в буфере, с которого начинать сохранять окно
        tst     R0
        bpl     3$
        clr     r3          ;в буфер экрана поместим 0 - признак несохранения
        bic     #100000,2(SP) ;сбросим бит 15 у адреса.
        br      4$
3$:     add     R3,R1       ; если с тенью, то на 1 символ выше
        add     R3,R2       ; если с тенью, то на 1 символ шире
        asl     R1
        asl     R1
        asl     R1          ; R1 * 10
        mov     R1, -(SP)
2$:     mov     R0,R3
        mov     R2,R4
1$:     mov     (R3)+,-(R5) ; сохраняем строку
        sob     R4,1$
        add     #100,R0
        sob     R1,2$       ; и так до конца
        mov     (SP)+,-(R5) ;туда же высоту
        mov     R2,-(R5)    ;ширину
4$:     mov     R3,-(R5)    ; и адрес, с которого начинать восстановление.
        br      3SCR$
; восстановление области экрана под окном при закрытии окна
; вход: нет
; окна имеют стековую структуру, и восстанавливается то, которое последним было открыто
RSTSCR: jsr     r5, PUSHA
        mov     #15000,@#177716 ;стр.5 в окно0, стр.2 в окно1
        MOV     SCRBUF,R5
        mov     (R5)+, R0   ;адрес экрана
        beq     3SCR$
        mov     (R5)+, R2   ;ширина
        mov     (R5)+, R1   ;высота
2$:     mov     R0,R3
        mov     R2,R4
1$:     mov     (R5)+,-(R3)
        sob     R4,1$
        sub     #100,R0
        sob     R1,2$
3SCR$:  MOV     R5,SCRBUF
RSTPGE: mov     @#CCM,@#177716  ;восстанавливаем страницы как было.
        return

;сохранение всех регистров
;обращение через JSR R5,PUSHA
PUSHA:  MOV     R4,-(SP)
        MOV     R3,-(SP)
        MOV     R2,-(SP)
        MOV     R1,-(SP)
        MOV     R0,-(SP)
        CALL    (R5)
;восстановление всех регистров
        MOV     (SP)+,R0
        MOV     (SP)+,R1
        MOV     (SP)+,R2
        MOV     (SP)+,R3
        MOV     (SP)+,R4
        MOV     (SP)+,R5
        RETURN

; Вывод строки.
; Вход: R0 - адрес строки, R1 - адрес экрана
; Выход: R0 - выровненный по слову адрес за концом строки
; Формат символов в строке:
; 0 - конец строки
; 1 - перевод строки относительно начальной позиции
; 2..27 - величина смещения от текущей позиции
; 30..33 - задать цвет фона
; 34..37 - задать цвет символов
; 40..377 - знаки.

OUTSTR: jsr     R5, PUSHA
        mov     #14000,@#177716 ; стр.5 в окно0, стр.1 в окно 1
2$:     mov     R1, R5          ;сохраним начальную позицию строки.

4$:     movb    (R0)+, R2       ; получим очередной символ
        beq     7$              ; если 0, то строка кончилась
        cmpb    R2, #40
        blo     8$
        call    @#OUTCHR        ; Вход: R2 - код символа, R1 - адрес вывода
        br      4$
; ───────────────────────────────────────────────────────────────────────────

8$:     mov     R2, R3          ; обработка кодов 1..37
        cmpb    R2, #30
        blo     10$
        cmpb    R2, #33
        bhi     11$
        mov     #BGCOLR, R3     ; если коды 30..33, то это цвет фона
        br      12$
; ───────────────────────────────────────────────────────────────────────────

11$:    com     R2              ; если коды 34..37
        mov     #COLMSK, R3     ; то это цвет символов
12$:    bic     #177774, R2     ; получим номер цвета 0..3
        asl     R2
        mov     COLORS(R2),(R3)
        br      4$
; ───────────────────────────────────────────────────────────────────────────

10$:    dec     R2              ; обработка кодов 1..27
        bne     13$
        add     #1000, R5       ; код 1 - перевод строки относительно начальной позиции
        mov     R5,R1
        br      2$
; ───────────────────────────────────────────────────────────────────────────

13$:    ; обработка кодов 2..27 - это смещение от текущей позиции
        bic     #177740, R3     ; вычленим младшие 5 бит кода
        asl     R3
        add     R3, R1          ; нет - значит мл.5 бит - смещение от текущей позиции
        br      4$
; ───────────────────────────────────────────────────────────────────────────

7$:     inc     R0              ; все, конец строки.
        bic     #1, R0          ; выравниваем по слову
        mov     r0, 2(SP)
        JMP     RSTPGE
; ───────────────────────────────────────────────────────────────────────────
; область переменных. пока все тут в кучу соберем
; ───────────────────────────────────────────────────────────────────────────
COLORS: .WORD   0,52525,125252,177777   ;массив масок цветов
BGCOLR: .WORD   0   ;цвет фона
COLMSK: .WORD   0   ;инверсная маска цвета символов.
SCRBUF: .WORD   100000 ;адрес в экранном буфере.
W$FLG:  .byte   0   ; флаг, что окно распахнулось до заданной ширины
H$FLG:  .byte   0   ; флаг, что окно распахнулось до заданной высоты
        .EVEN
        
        .END

Распределение памяти.
Стр0 - основной код
Стр1 - дополнительный код. страница подключается в окно1.
       но код по возможности должен иметь возможность работать и в окне0.
       так же буфер для скомпилированного SND файла (если он туда полезет)
Стр2 - буфер экрана
Стр3 - TSN файл
Стр4 - Андос, МКдос и т.п.
Стр5 - экран основной
Стр6 - экран редактора сэмплов.

