?login_element?

Subversion Repositories NedoOS

Rev

Rev 835 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.         module ayfx
  2.        
  3. ;-Minimal ayFX player2 v0.16 20.06.06--------------------------;
  4. ;                                                              ;
  5. ; Простейший плеер эффектов. Проигрывает эффекты на одном AY,  ;
  6. ; без музыки на фоне. Громкость проигрывания эффектов задаётся ;
  7. ; при их вызове. Приоритет выбора каналов: если есть свободные ;
  8. ; каналы, выбирается один из них. Если свободных каналов нет,  ;
  9. ; выбирается наиболее давно звучащий. Процедура проигрывания   ;
  10. ; использует регистры AF,BC,DE,HL,IX.                          ;
  11. ;P.S. от Alone Coder'а: задействовал IY и еще 2 байта, чтобы
  12. ;не играть эффект, когда он тише музыки (убрано для TFM музыки)
  13. ;P.P.S. TurboSound fix 16.02.18
  14. ;                                                              ;
  15. ; Инициализация:                                               ;
  16. ;   ld hl, адрес банка эффектов                                ;
  17. ;   call AFXINIT                                               ;
  18. ;                                                              ;
  19. ; Запуск эффекта:                                              ;
  20. ;   ld a, номер эффекта (0..255)                               ;
  21. ;   ld c, относительная громкость (-15..15)                    ;
  22. ;   call AFXPLAY                                               ;
  23. ;                                                              ;
  24. ; В обработчике прерывания:                                    ;
  25. ;   call AFXFRAME                                              ;
  26. ;                                                              ;
  27. ;--------------------------------------------------------------;
  28.  
  29.  
  30. ; описатели каналов, по 5+2 байт на канал:
  31. ; +0 (2) текущий адрес (канал свободен, если старший байт =#00)
  32. ; +2 (2) время звучания эффекта
  33. ; +4 (1) громкость эффекта
  34. ; +6 (2) ПЕРИОД ТОНАЛЬНИКА
  35. ; ...
  36.  
  37. afxChDesc       DS 3*(5+2)
  38.  
  39.  
  40.  
  41.  
  42. ;--------------------------------------------------------------;
  43. ; Инициализация плеера эффектов.                               ;
  44. ; Выключает все каналы, устанавливает переменные.              ;
  45. ; Вход: HL = адрес банка с эффектами                           ;
  46. ;--------------------------------------------------------------;
  47.  
  48. INIT
  49.         ld a,(hl)
  50.         ld (afxEffectsAll),a
  51.         INC HL
  52.         LD (afxBnkAdr+1),HL    ;сохраняем адрес таблицы смещений
  53.  
  54.         LD HL,afxChDesc         ;помечаем все каналы как пустые
  55.         LD DE,#00FF
  56.         LD B,3
  57. afxInit0
  58.         LD (HL),D
  59.         INC HL
  60.         LD (HL),D
  61.         INC HL
  62.         LD (HL),E
  63.         INC HL
  64.         LD (HL),E
  65.         INC HL
  66.         LD (HL),D
  67.         INC HL
  68.        LD (HL),D
  69.        INC HL
  70.        LD (HL),D
  71.        INC HL
  72.         DJNZ afxInit0
  73.         ifdef TFM
  74.         ld a,(TURBOFMON)
  75.         or a
  76.         ret nz ;TFM present
  77.         ld a,#c9 ;ret
  78.         ld (waitstatus),a
  79.         endif
  80.         RET ;TFM absent
  81.  
  82. ;--------------------------------------------------------------;
  83. ; Проигрывание текущего кадра.                                 ;
  84. ; Параметров не имеет.                                         ;
  85. ;--------------------------------------------------------------;
  86.  
  87. FRAME
  88.         LD BC,#03FD
  89.         LD IX,afxChDesc
  90. afxFrame0
  91.         PUSH BC
  92.         LD H,(IX+1)                    ;сравнение старшего байта
  93.                                                  ;адреса на <11
  94.         ld a,h
  95.                 or a
  96.         jp z,afxFrame7         ;канал не играет, пропускаем
  97.         LD L,(IX+0)
  98.  
  99.         LD E,(HL)          ;берём значение информационного байта
  100.         INC HL
  101.  
  102.         LD A,11
  103.         SUB B                       ;выбираем регистр громкости:
  104.         LD D,B                        ;(11-3=8, 11-2=9, 11-1=10)
  105.         LD B,#FF                         ;начало вывода значения
  106.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  107.        OUT (C),B ;AY #1(0)      ;т.к.может вырубиться при HY=#FF
  108.        LD HY,B                                   ;выкл громкости
  109.         endif
  110.                                 ;
  111.         ifdef TFM
  112.         call waitstatus
  113.         endif
  114.         OUT (C),A ;выбрали регистр громкости
  115.         ifdef TFM
  116.         call waitstatus
  117.         endif
  118.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  119.        IN A,(C)
  120.  
  121.        CP 16
  122.        JR NC,$+4
  123.        SUB 3;4
  124.        JR NC,$+3
  125.        XOR A
  126.        LD (curvolCHN),A
  127.         endif
  128.         LD A,E
  129.         AND #0F
  130.         ADD A,(IX+4)         ;применяем текущую громкость канала
  131.         CP 15
  132.         JP M,$+5
  133.         LD A,15
  134.         OR A
  135.         JP P,$+4
  136.         XOR A
  137.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  138.       CP 13 ;громкую часть эффекта не глушим
  139.       JR NC,curvON
  140. curvolCHN=$+1
  141.        CP 0
  142.        JR C,curvOFF
  143. curvON
  144.        LD HY,#BF ;вкл
  145. curvOFF
  146.         LD B,HY
  147.         else
  148.         LD B,#BF
  149.         endif
  150.         OUT (C),A                    ;собственно вывод громкости
  151.  
  152.         BIT 5,E                         ;будет изменение тона?
  153.         JR Z,afxFrame1          ;тон не изменяется
  154.         LD A,(HL)
  155.         LD (IX+5),A
  156.         INC HL
  157.         LD A,(HL)
  158.         LD (IX+6),A
  159.         INC HL
  160. afxFrame1
  161.         LD A,3                          ;выбираем регистры тона:
  162.         SUB D                           ;3-3=0, 3-2=1, 3-1=2
  163.         ADD A,A                         ;0*2=0, 1*2=2, 2*2=4
  164.  
  165.         LD B,#FF                        ;выводим значения тона
  166.         ifdef TFM
  167.         call waitstatus
  168.         endif
  169.         OUT (C),A
  170.         ifdef TFM
  171.         call waitstatus
  172.         endif
  173.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  174.         LD B,HY
  175.         else
  176.         LD B,#BF
  177.         endif
  178.        LD D,(IX+5) ;младший байт тона может быть 0xfe!!!
  179.         OUT (C),D
  180.         LD B,#FF
  181.        OUT (C),B ;AY #1(0)      ;т.к.может вырубиться при HY=#FF
  182.         INC A
  183.         ifdef TFM
  184.         call waitstatus
  185.         endif
  186.         OUT (C),A
  187.         ifdef TFM
  188.         call waitstatus
  189.         endif
  190.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  191.         LD B,HY
  192.         else
  193.         LD B,#BF
  194.         endif
  195.        LD D,(IX+6)
  196.         OUT (C),D
  197. ;afxFrame1
  198.         BIT 6,E                         ;будет изменение шума?
  199.         JR Z,afxFrame3          ;шум не изменяется
  200.  
  201.         LD A,(HL)                       ;читаем значение шума
  202.         SUB #20
  203.         JR C,afxFrame2          ;меньше #20, играем дальше
  204.         LD H,A                          ;иначе конец эффекта
  205.         LD (IX+2),#FE           ;делаем время наибольшим-1
  206.         LD (IX+3),#FF
  207.         LD E,#90                ;выключаем тон и шум в микшере
  208.         JR afxFrame3
  209.  
  210. afxFrame2
  211.         INC HL
  212.         LD B,#FF                        ;вывод значения шума
  213.         LD D,6
  214.         ifdef TFM
  215.         call waitstatus
  216.         endif
  217.         OUT (C),D
  218.         ifdef TFM
  219.         call waitstatus
  220.         endif
  221.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  222.         LD B,HY
  223.         else
  224.         LD B,#BF
  225.         endif
  226.         OUT (C),A
  227.  
  228. afxFrame3
  229.         POP BC               ;восстанавливаем значение цикла в B
  230.         PUSH BC
  231.         INC B ;4..2            ;количество сдвигов для флагов TN
  232.  
  233.         LD A,%01101111          ;маска для флагов TN
  234. afxFrame4
  235.         RRC E                           ;сдвигаем флаги и маску
  236.         RRCA
  237.         DJNZ afxFrame4
  238.         LD D,A
  239.        LD BC,#FFFD                     ;читаем регистр микшера
  240.         LD A,7
  241.         ifdef TFM
  242.         call waitstatus
  243.         endif
  244.         OUT (C),A
  245.         ifdef TFM
  246.         call waitstatus
  247.         endif
  248.         IN A,(C)
  249.         XOR E                          ;накладываем флаги канала
  250.         AND D
  251.         XOR E
  252.         ifndef TFM      ;для TurboSound!!! выключено для TFM
  253.         LD B,HY
  254.         else
  255.         LD B,#BF
  256.         endif
  257.         OUT (C),A                      ;выводим обратно в микшер ;может быть 0xfe!!!
  258.        LD B,#FF
  259.        OUT (C),B ;AY #1(0)      ;т.к.может вырубиться при HY=#FF
  260. afxFrame5
  261.         LD C,(IX+2)                 ;увеличиваем счётчик времени
  262.         LD B,(IX+3)
  263.         INC BC
  264.  
  265. afxFrame6
  266.         LD (IX+2),C
  267.         LD (IX+3),B
  268.  
  269.         LD (IX+0),L                ;сохраняем изменившийся адрес
  270.         LD (IX+1),H
  271.  
  272. afxFrame7
  273.         LD BC,5+2                 ;переходим к следующему каналу
  274.         ADD IX,BC
  275.         POP BC
  276.         DEC B
  277.         JP NZ,afxFrame0
  278.         RET
  279.  
  280. ;--------------------------------------------------------------;
  281. ; Запуск эффекта на свободном канале. При отсутствии           ;
  282. ; свободных каналов выбирается наиболее давно звучащий.        ;
  283. ; Вход: A = номер эффекта 0..255                               ;
  284. ;       С = относительная громкость -15..15                    ;
  285. ;--------------------------------------------------------------;
  286.  
  287. PLAY
  288. afxEffectsAll=$+1
  289.         cp 0
  290.         ret nc
  291.         push ix
  292.         PUSH BC                         ;сохраняем громкость
  293.         LD DE,0                ;в DE наибольшее время при поиске
  294.         LD H,E
  295.         LD L,A
  296.         ADD HL,HL
  297. afxBnkAdr
  298.         LD BC,0                 ;адрес таблицы смещений эффектов
  299.         ADD HL,BC
  300.         LD C,(HL)
  301.         INC HL
  302.         LD B,(HL)
  303.         ADD HL,BC                    ;адрес эффекта получен в hl
  304.         PUSH HL                ;сохраняем адрес эффекта на стеке
  305.  
  306.         LD HL,afxChDesc         ;поиск пустого канала
  307.         LD B,3
  308. afxPlay0
  309.         INC HL
  310.         INC HL
  311.         LD A,(HL)          ;сравниваем время канала с наибольшим
  312.         INC HL
  313.         INC HL
  314.         CP E
  315.         JR C,afxPlay1
  316.         LD C,A
  317.         LD A,(HL)
  318.         CP D
  319.         JR C,afxPlay1
  320.         LD E,C                      ;запоминаем наибольшее время
  321.         LD D,A
  322.         PUSH HL                 ;запоминаем адрес канала +3 в IX
  323.         POP IX
  324. afxPlay1
  325.         INC HL
  326.        INC HL
  327.        INC HL
  328.         DJNZ afxPlay0
  329.  
  330.         POP DE                  ;забираем адрес эффекта из стека
  331.         LD (IX-4),E                  ;заносим в описатель канала
  332.         LD (IX-3),D
  333.         LD (IX-2),B                     ;зануляем время звучания
  334.         LD (IX-1),B
  335.         POP BC                          ;забираем громкость
  336.         LD (IX-0),C             ;и заносим её в описатель канала
  337.         pop ix
  338.         ret
  339.        
  340.         ifdef TFM
  341. waitstatus
  342. ;bc=#fffd
  343.         IN F,(C)
  344.         JP M,$-2
  345.                 ret
  346.         endif
  347.  
  348.         endmodule