Инструменты пользователя

Инструменты сайта


msx:basic_dialogue_programming_language:209

Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

2.9. Приложение к разделу «Фоновое музыкальное сопровождение»

Это приложение к разделу Фоновое музыкальное сопровождение


209-01.asm

;──────────────────────────────────────────────────────────────────
Len_Inform      EQU     000DH    ; Длина блока данных
Jiffy           EQU     0FC9EH   ; Счетчик прерываний
Vibrato         EQU     008      ; Отклонение частоты при вибрато

;──────────────────────────────────────────────────────────────────
; О с н о в н а я   п р о г р а м м а. Вход может быть параллельным,
; но можно "вешать" на Hook &HFD9A, &HFD9F
;──────────────────────────────────────────────────────────────────

Music:
        PUSH    HL          ;──┐
        PUSH    DE          ;  │
        PUSH    BC          ;  ├─▶ Сохранение используемых регистров
        PUSH    AF          ;  │
        PUSH    IX          ;  │
        PUSH    IY          ;──┘
        LD      A,(Jiffy)   ;──┐
        LD      B,A         ;  │
        LD      A,(Timer)   ;  ├─▶ Если нового тика не было, - то выход
        CP      B           ;  │
        JR      Z,Exit      ;──┘
        LD      HL,P_Slot   ;──┐
        DI                  ;  │
        IN      A,(0A8H)    ;  │
        LD      (HL),A      ;  │
        INC     HL          ;  ├─▶ Запомним конфигурацию памяти
        LD      A,(0FFFFH)  ;  │
        CPL                 ;  │
        LD      (HL),A      ;──┘
        PUSH    HL
        LD      DE,0FFAAH   ;┬──▶ Устанавливаем свою конфигурацию:
        CALL    Found_Slot  ;┘         с л о т  3-2
        LD      IX,Inform
        LD      IY,All_Data
        LD      C,001H      ;Начинаем с первого голоса
        EXX
        LD      B,003H      ;Будем работать с тремя музыкальн. каналами
        LD      DE,Len_Inform

Label_0:EXX
        LD      A,C
        OR      A            ;Сброс битов регистра флагов
        DEC     (IX+000H)
        PUSH    AF
        CALL    NZ,Tik_mus  ;Если длительность  ноты  не кончилась, то вы-
        POP     AF          ;полняем "попутные эффекты".
        CALL    Z,Change    ;Иначе перемещаемся по очереди данных
        INC     C           ;Переходим к следующему каналу
        INC     C           ; 1──▶3──▶5, что означает 1,2,3 голос
        EXX
        ADD     IX,DE       ;Указатель на следующий информ. блок
        DJNZ    Label_0

        LD      A,(Jiffy)   ;─┬──▶Считать номер тика
        LD      (Timer),A   ;─┘   и сохранить для сравнения
        POP     HL

        LD      E,(HL)      ;──┐
        DEC     HL          ;  │
        LD      D,(HL)      ;  ├─▶Восстанавливаем конфигурацию памяти
        CALL    Found_Slot  ;──┘

Exit:   POP     IY          ; ──┐
        POP     IX          ;   │
        POP     AF          ;   │
        POP     BC          ;   ├─▶Восстанавливаем значение регистров
        POP     DE          ;   │
        POP     HL          ;───┘
        RET                 ;───▶ Возврат из программы

Timer:  Defb    0
P_Slot: Defb    0
S_Slot: Defb    0

;────────────────────────────────────────────────────────────────────
Tik_mus:                    ;Подпрограмма "попутных эффектов"
        LD      A,(IX+000H) ;Остался ли один тик?
        DEC     A           ;Если да и это не 1/32, то "глушим"
        JR      NZ,g_022
        LD      A,(IX+01H)  ;──┐
        CP      3           ;  │
        RET     C           ;  │
        OR      A           ;  │
        LD      E,C         ;  │
        RES     0,E         ;  │
        LD      A,(IY+01H)  ;  │
        JR      NZ,g_023    ;  │
        LD      E,C         ;  ├─▶ Для отделения нот друг от друга
g_023:  OR      E           ;  │   "глушим" соответствующий канал,
        RL      E           ;  │   когда остается играть 1 тик
        RL      E           ;  │
        RL      E           ;  │
        OR      E           ;  │
        JP      Label_3     ;──┘

g_022:  LD      A,(IX+07H)  ;──┐
        OR      A           ;  ├▶Если не разрешено "фокусничать",
        RET     NZ          ;──┘ то уходим молча !◀───────────┐
        LD      A,(IX+12)   ;──┐                              │
        OR      A           ;  ├─▶ При "Legato" обычно тоже ──┘
        RET     Z           ;──┘
        CALL    Select      ;Можем делать вибрато, а можем и не делать !
        LD      A,(IX+08H)  ;Если модуляция включена,то нам делать нечего
        CP      16
        RET     Z
        LD      E,0         ;──┐
        LD      L,A         ;  │
        LD      A,(IX+001H) ;  │
        BIT     1,(IX+002H) ;  │
        JR      Z,Tmp_1     ;  │
        RLCA                ;  │
Tmp_1:  LD      B,(IX+000H) ;  │
        SUB     B           ;  │
        LD      B,A         ;  │    Постепенно (с каждым новым тиком)
        LD      A,L         ;  ├──▶ глушим все каналы, чтобы сильно не
        CP      B           ;  │    "пищали", так приятней слушается
        JR      C,Gasi      ;  │    музыка, но не забываем, что темп
        SUB     B           ;  │    у голосов может быть разный!
        RET     M           ;  │
        LD      E,A         ;  │
Gasi:   LD      A,C         ;  │
        RRCA                ;  │
        ADD     A,88H       ;  │
        JP      Play        ;──┘

Select:
        PUSH     IX          ;Вибрато-частотное отклонение
        LD       IX,Golos_1  ;(причем и "+" и "-") от заданного
        LD       E,C         ;значения частоты
        DEC      E           ;Но у нас только "-",- так приятней слушать
        LD       D,0         ;
        ADD      IX,DE
        LD       H,(IX+0)
        LD       L,(IX+1)
        LD       IX,Vibr_1
        RRC      E
        ADD      IX,DE
        LD       A,(IX+0)
        OR       A
        LD       E,Vibrato
        JR       Z,Vie
        DEC      A
        DEC      A
        SBC      HL,DE

Vie:    INC     A
       LD       (IX+0),A
       POP      IX
       PUSH     HL
       JP       Leba

Vibr_1: Defb    0
Vibr_2: Defb    0
Vibr_3: Defb    0

;──────────────────────────────────────────────────────────
; Подпрограмма обработки очереди
;──────────────────────────────────────────────────────────

Change:
       LD       L,(IX+05H)  ;Достали текущий адрес данных
       LD       H,(IX+06H)
       LD       (IX+07H),00 ;Разрешили игру на время

Label_5:CALL    Command     ;Анализ и выполнение команд
       JR       Z,Label_5   ;Движемся пока на выходе Z=1
Restore:CALL    Found_Len   ;Установка следующей длительности
       LD       (IX+05H),L  ;Сохраняем адрес данных

       LD       (IX+06H),H  ;до следуюшего обнуления
       LD       E,01111011B ;Запрещаем два соседних голоса
       LD       B,C         ;для "играния" обрабатываемого канала
       INC      B

Label_6:RLC     E
       DEC      B
       DJNZ     Label_6
       LD       A,(IY+01H)
       OR       E
       CALL     Label_3
       LD       A,C
       RRCA
       ADD      A,088H
       LD       E,A

       LD       A,(IX+07H)  ;Если пауза или запрещен канал,
       OR       A           ;то канал молчит !
       LD       A,E
       LD       E,B
       JR       NZ,g_020
       LD       E,(IX+08H)

g_020:  CALL    Play
       LD       A,E
       CP       16
       JR       C,g_021     ;Выходим, если амплитуда <16
       LD       A,06H       ;Восстановили значение 6 регистра
       LD       E,(IY+00H)
       CALL     Play
       ADD      A,05H       ;Восстановили значение 11 регистра
       LD       E,(IY+02H)
       CALL     Play
       INC      A
       LD       E,(IY+03H)  ;Восстановили значение 12 регистра
       CALL     Play
       INC      A
       LD       E,(IY+04H)  ;Восстановили значение 13 регистра
       CALL     Play
g_021:  LD      A,(IY+01H)


;──────────────────────────────────────────────────────────
Found_Micsher:              ;Различные операции с 7 регистром PSG
       LD       (IY+01H),A  ;

Label_3:LD      E,A
       LD       A,07H

Play:   OUT     (0A0H),A
       PUSH     AF
       LD       A,E
       OUT      (0A1H),A
       POP      AF
       RET



;──────────────────────────────────────────────────────────
Found_Slot:                 ;Установка слотовой
        LD      A,D         ;конфигурации
        OUT     (0A8H),A
        LD      A,E
        LD      (0FFFFH),A
        RET

;──────────────────────────────────────────────────────────
Found_Len:                  ;Установка количества тиков
        XOR     A           ;в зависимости от длительности
        LD      B,(IX+02H)  ;и темпа

F_Len:  ADD     A,(IX+01H)  ;
        DJNZ    F_Len
        LD      (IX+000H),A
        RET

;──────────────────────────────────────────────────────────
Command:
        LD      A,(HL)      ;──┐
        AND     0F0H        ;  │
        RRCA                ;  │
        RRCA                ;  │
        RRCA                ;  │
        RRCA                ;  │
        LD      E,A         ;  │
        LD      D,0         ;  │
        ADD     A,A         ;  │   Анализ номера команды
        ADD     A,E         ;  ├─▶ с последующим переходом
        LD      E,A         ;  │   на подпрограмму выполенния
        PUSH    HL          ;  │   той или иной команды
        LD      HL,Vector   ;  │   с первым параметром
        ADD     HL,DE       ;  │
        EX      DE,HL       ;  │
        POP     HL          ;  │
        LD      A,(HL)      ;  │
        AND     00FH        ;  │
        PUSH    DE          ;  │
        RET                 ;──┘

;─────────────────────────────────────────────────────────
; Вектора переходов на подпрограммы выполнения команд

;─────────────────────────────────────────────────────────

Vector:
        JP      Com_0
        JP      Com_1
        JP      Com_2
        JP      Com_3
        JP      Com_4
        JP      Com_5
        JP      Com_6
        JP      Com_7
        JP      Com_8
        JP      Com_9

        JP      Com_10
        JP      Com_11
        JP      Com_12
        JP      Com_13
        JP      Com_14
        JP      Com_15

;─────────────────────────────────────────────────────────
; Подпрограмма меняет значения частот, когда настало время
;─────────────────────────────────────────────────────────

Com_0:  PUSH    HL
        LD      HL,Notes
        DEC     A
        ADD     A,L
        LD      L,A
        JR      NC,g_001
        INC     H

g_001:  LD      L,(HL)
        LD      H,0
        LD      B,(IX+11)
        LD      A,8
        SUB     B
        JR      Z,g_002
        LD      B,A

g_003:  ADD     HL,HL
        DJNZ    g_003

g_002:
Leiba:  PUSH    IX
        LD      IX,Golos_1
        LD      E,C
        DEC     E
        LD      D,0
        ADD     IX,DE
        LD      (IX+0),H
        LD      (IX+1),L
        POP     IX

Leba:   LD      E,H
        LD      A,C
        CALL    Play
        LD      E,L
        DEC     A
        CALL    Play
        POP     HL
        INC     HL
        INC     A
        OR      A
        RET

Golos_1:Defw    0
Golos_2:Defw    0
Golos_3:Defw    0


;─────────────────────────────────────────────────────────
; Подпрограмма меняет и запоминает значения 7 регистра PSG
;─────────────────────────────────────────────────────────

Com_1:  INC     HL
        LD      A,(HL)
        CALL    Found_Micsher

g_004:  INC     HL
        XOR     A
        RET

;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значение темпа 1 или 2
;─────────────────────────────────────────────────────────

Com_2:  LD      (IX+02H),A
g_005:  JR      g_004

;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значения амлитуды
;─────────────────────────────────────────────────────────

Com_3:  INC     A
        LD      (IX+08H),A
g_006:  JR      g_005

;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значения 6 регистра PSG
;─────────────────────────────────────────────────────────

Com_4:  ADD     A,A
        LD      (IY+00H),A
g_007:  JR      g_006

;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значения 13 регистра PSG
;─────────────────────────────────────────────────────────

Com_5:  LD      (IY+04H),A
g_008:  JR      g_007

;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значения 11 регистра PSG
;─────────────────────────────────────────────────────────

Com_6:  LD      E,A
        XOR     A
        LD      B,10

g_009:  ADD     A,E
        DJNZ    g_009
        LD      (IY+02H),A

g_010:  JR      g_008



;─────────────────────────────────────────────────────────
; Подпрограмма запоминает значения 12 регистра PSG
;─────────────────────────────────────────────────────────


Com_7:  LD      E,A
        XOR     A
        ADD     A,E
        ADD     A,E
        LD      (IY+03H),A
g_011:  JR      g_010

;─────────────────────────────────────────────────────────
; Подпрограмма меняет и запоминает длительность
;─────────────────────────────────────────────────────────


Com_8:  LD      E,11000000B
        LD      D,10111111B
        LD      B,A
        RRC     B
        SUB     B
        CP      B
        JR      Z,g_013
        RLC     B
        INC     B
        RRC     B

g_012:  RRC     E
        DJNZ    g_012
        LD      A,B
        OR      E
        JR      g_014

g_013:  RRC     E
        RRC     D
        DJNZ    g_013
        LD      A,B
        OR      E
        AND     D

g_014:  LD      (IX+01H),A
g_015:  JR      g_011

;─────────────────────────────────────────────────────────
; Подпрограмма выставляет паузу
;─────────────────────────────────────────────────────────

Com_9:  LD      A,01H
        LD      (IX+07H),A
        INC     HL
        OR      A
        RET

;─────────────────────────────────────────────────────────
; Подпрограмма переходит по адресу данных Call or Jump
;─────────────────────────────────────────────────────────

Com_10: INC     HL
        LD      E,(HL)
        INC     HL
        LD      D,(HL)
        INC     HL
        LD      (IX+09H),L
        LD      (IX+0AH),H
        LD      HL,Admat
        ADD     HL,DE
        XOR     A
        RET

;─────────────────────────────────────────────────────────
; Подпрограмма возвращается из адреса
;─────────────────────────────────────────────────────────

Com_11: LD      L,(IX+09H)
        LD      H,(IX+0AH)
        XOR     A
        RET

;─────────────────────────────────────────────────────────
; Подпрограмма заглушки канала
;─────────────────────────────────────────────────────────

Com_12: LD      A,1
        LD      (IX+07H),A
        OR      A
        RET

;─────────────────────────────────────────────────────────
; Подпрограмма меняет текущую октаву
;─────────────────────────────────────────────────────────

Com_13: LD      (IX+11),A
g_016:  JR      g_015
Com_14: LD      (IX+12),A
        JR      g_016
Com_15: JR      g_016

;──────────────────────────────────────────────────────────
; 8 октава - образец частот (все остальные частоты 
; вычисляются в зависимости от октавы и номера ноты)
;──────────────────────────────────────────────────────────

Notes:  Defb    01BH
        Defb    019H
        Defb    018H
        Defb    016H
        Defb    015H
        Defb    014H
        Defb    013H
        Defb    012H
        Defb    011H
        Defb    010H
        Defb    00FH
        Defb    00EH

;──────────────────────────────────────────────────────────

Inform: Defb    1       ;Сколько тиков осталось играть 1 голос   +0
        Defb    8       ;Текущая длительность 1 голоса           +1
        Defb    1       ;Темп текущего голоса (1 OR 2)           +2
        Defw    Admat_1 ;Адрес хранения данных 1 голоса          +3
        Defw    Admat_1 ;Адрес текущих данных 1 голоса           +5
        Defb    0       ;1 Если музыка кончилась или пауза       +7
        Defb    0FH     ;Громкость 1 голоса                      +8
        Defw    Admat_1 ;Хранение адресов для Call and Jump      +9
        Defb    05H     ;Текущая октава                         +11
        Defb    00      ;Легато или Стаккато                    +12

        Defb    1       ;Сколько тиков осталось играть 2 голос   +0
        Defb    8       ;Текущая длительность 2 голоса           +1
        Defb    1       ;Темп текущего голоса (1 OR 2)           +2
        Defw    Admat_2 ;Адрес хранения данных 2 голоса          +3
        Defw    Admat_2 ;Адрес текущих данных 2 голоса           +5
        Defb    0       ;1 Если музыка кончилась или пауза       +7
        Defb    0FH     ;Громкость 2 голоса                      +8
        Defw    Admat_2 ;Хранение адресов для Call and Jump      +9
        Defb    05H     ;Текущая октава                         +11
        Defb    00      ;Легато или Стаккато                    +12

        Defb    1       ;Сколько тиков осталось играть 3 голос   +0
        Defb    8       ;Текущая длительность 3 голоса           +1
        Defb    1       ;Темп текущего голоса (1 OR 2)           +2
        Defw    Admat_3 ;Адрес хранения данных 3 голоса          +3
        Defw    Admat_3 ;Адрес текущих данных 3 голоса           +5
        Defb    0       ;1 Если музыка кончилась или пауза       +7
        Defb    0FH     ;Громкость 3 голоса                      +8
        Defw    Admat_3 ;Хранение адресов для call and jump      +9
        Defb    05H     ;Текущая октава                         +11
        Defb    00      ;Легато или Стаккато                    +12

All_Data:
        Defb    15      ;Данные для 6 регистра                   +0
        Defb    0B8H    ;Данные для 7 регистра                   +1
        Defb    200     ;Данные для 11 регистра                  +2
        Defb    10      ;Данные для 12 регистра                  +3
        Defb    1       ;Данные для 13 регистра                  +4

;──────────────────────────────────────────────────────────────────

Admat:
Admat_1:
Admat_2:
Admat_3:

Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

msx/basic_dialogue_programming_language/209.txt · Последние изменения: 2023-01-24 13:35 — GreyWolf