dllbridge

Untitled

Feb 20th, 2026
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;*******************************************************************************
  2. ; ПРОШИВКА AY-ЗВОНКА (Z80, AY-3-8910)
  3. ; Полный дизассемблер рабочей версии
  4. ; Размер: ~450 байт кода + таблицы данных
  5. ; Адресация: Код с 0000, данные/переменные в F800-F8FF
  6. ;*******************************************************************************
  7.  
  8. ;===============================================================================
  9. ; ОБЛАСТЬ ПЕРЕМЕННЫХ (в верхней памяти)
  10. ;===============================================================================
  11. ; F800 - Счетчик/флаг прерываний (обновляется по таймеру)
  12. ; F801 - Текущий индекс в таблице паттернов (0..n)
  13. ; F802 - (не используется в этом фрагменте)
  14. ; F803 - (не используется)
  15. ; F804 - Указатель канала A (текущая позиция в данных)
  16. ; F805 - Указатель канала B (текущая позиция в данных)
  17. ; F806 - Флаг/счетчик для специальных эффектов
  18.  
  19. ;===============================================================================
  20. ; ТОЧКА ВХОДА: ИНИЦИАЛИЗАЦИЯ (адрес 0000)
  21. ;===============================================================================
  22. 0000: F3          DI              ; Запрещаем прерывания на время инициализации
  23. 0001: 31 FF FF    LD SP, $FFFF    ; Устанавливаем стек в самый верх памяти
  24. 0004: 21 00 02    LD HL, $0200    ; HL = источник (код плеера, если копируется)
  25. 0007: 11 4C F8    LD DE, $F84C    ; DE = приемник (область переменных + буфер)
  26. 000A: 01 5C 04    LD BC, $045C    ; BC = размер копирования (1116 байт)
  27. 000D: ED B0       LDIR            ; Копируем блок (вероятно, код плеера в ОЗУ)
  28.  
  29. ;===============================================================================
  30. ; ПРОВЕРКА ЦЕЛОСТНОСТИ ТАБЛИЦЫ ДАННЫХ
  31. ;===============================================================================
  32. 000F: 21 91 01    LD HL, $0191    ; HL = начало таблицы данных
  33. 0012: 06 FF       LD B, $FF       ; B = счетчик (255 попыток)
  34. 0014: 7E          LD A, (HL)      ; Читаем первый байт пары
  35. 0015: 23          INC HL
  36. 0016: 4E          LD C, (HL)      ; C = второй байт пары
  37. 0017: 23          INC HL          ; HL на следующую пару
  38. 0018: 04          INC B           ; Увеличиваем счетчик
  39. 0019: A1          AND C           ; Логическое И двух байтов
  40. 001A: 3C          INC A           ; Если было FF, станет 00
  41. 001B: 20 F7       JR NZ, $0014    ; Если не ноль - продолжаем проверку
  42.                                  ; Выход из цикла, когда найдена пара FF?
  43.  
  44. ;===============================================================================
  45. ; ЗАЩИТА ИНДЕКСА ОТ ВЫХОДА ЗА ГРАНИЦЫ
  46. ;===============================================================================
  47. 001D: 3A 01 F8    LD A, ($F801)   ; Загружаем текущий индекс
  48. 0020: B8          CP B            ; Сравниваем с B (счетчиком из цикла)
  49. 0021: 38 04       JR C, $0027     ; Если индекс < B, пропускаем сброс
  50. 0023: AF          XOR A           ; Иначе сбрасываем индекс в 0
  51. 0024: 32 01 F8    LD ($F801), A
  52.  
  53. ;===============================================================================
  54. ; ВЫЗОВ ПОДПРОГРАММ ИНИЦИАЛИЗАЦИИ
  55. ;===============================================================================
  56. 0027: CD 3A 01    CALL $013A      ; Вызов подпрограммы A (распаковка/подготовка)
  57. 002A: CD C7 00    CALL $00C7      ; Вызов подпрограммы B (инициализация AY)
  58. 002D: CD 1F 01    CALL $011F      ; Вызов подпрограммы C (настройка каналов)
  59.  
  60. ;===============================================================================
  61. ; ГЛАВНЫЙ ЦИКЛ (ОЖИДАНИЕ ПРЕРЫВАНИЯ)
  62. ;===============================================================================
  63. 0030: 3A 00 F8    LD A, ($F800)   ; Загружаем счетчик прерываний
  64. 0033: CB 47       BIT 0, A        ; Проверяем младший бит (флаг "таймер сработал")
  65. 0035: 20 07       JR NZ, $003E    ; Если флаг установлен - играем музыку
  66.  
  67. 0037: AF          XOR A           ; Иначе - обнуляем указатели каналов
  68. 0038: 32 04 F8    LD ($F804), A   ; (гасим звук, если прерывания нет)
  69. 003B: 32 05 F8    LD ($F805), A
  70.  
  71. 003E: 3A 00 F8    LD A, ($F800)   ; Снова загружаем счетчик
  72. 0041: CB 4F       BIT 1, A        ; Проверяем второй бит
  73. 0043: CC AC 00    CALL Z, $00AC   ; Если бит сброшен - вызываем подпрограмму ожидания
  74.  
  75. 0046: CD 87 00    CALL $0087      ; Вызов основной подпрограммы обработки фрейма
  76. 0049: 3A 04 F8    LD A, ($F804)   ; Загружаем указатель канала A
  77. 004C: 6F          LD L, A         ; L = указатель канала A
  78. 004D: 3A 05 F8    LD A, ($F805)   ; Загружаем указатель канала B
  79. 0050: B5          OR L            ; Объединяем с L для проверки
  80. 0051: CC 54 01    CALL Z, $0154   ; Если оба нулевые - вызываем подпрограмму
  81. 0054: 18 D4       JR $002A        ; Возврат к началу цикла (к вызову подпрограмм)
  82.  
  83. ;===============================================================================
  84. ; ОБРАБОТЧИК ПРЕРЫВАНИЯ (вектор или вход по таймеру)
  85. ;===============================================================================
  86. 0056: 3A 00 F8    LD A, ($F800)   ; Загружаем счетчик прерываний
  87. 0059: CB 47       BIT 0, A        ; Проверяем младший бит
  88. 005B: C8          RET Z           ; Если не установлен - выходим (ложное прерывание)
  89.  
  90. ;===============================================================================
  91. ; ЧТЕНИЕ СЛЕДУЮЩЕГО БЛОКА ИЗ ТАБЛИЦЫ АДРЕСОВ
  92. ;===============================================================================
  93. 005C: 11 91 01    LD DE, $0191    ; DE = начало таблицы адресов паттернов
  94. 005F: 26 00       LD H, $00       ; H = 0
  95. 0061: 3A 01 F8    LD A, ($F801)   ; A = текущий индекс
  96. 0064: 6F          LD L, A         ; HL = индекс
  97. 0065: 29          ADD HL, HL      ; Умножаем на 2 (каждый адрес - 2 байта)
  98. 0066: 19          ADD HL, DE      ; HL = адрес в таблице (0191 + индекс*2)
  99. 0067: 5E          LD E, (HL)      ; E = младший байт адреса данных
  100. 0068: 23          INC HL
  101. 0069: 56          LD D, (HL)      ; D = старший байт адреса данных
  102. 006A: 7A          LD A, D         ; Проверяем на FFFF (конец данных)
  103. 006B: A3          AND E           ; Если оба FF, результат FF
  104. 006C: 3C          INC A           ; Становится 00
  105. 006D: 28 12       JR Z, $0081     ; Если FFFF - переходим на зацикливание
  106.  
  107. 006F: EB          EX DE, HL       ; HL = адрес данных для проигрывания
  108. 0070: 22 5A F8    LD ($F85A), HL  ; САМОМОДИФИКАЦИЯ: сохраняем адрес
  109. 0073: CD 0A 01    CALL $010A      ; Вызов подпрограммы обработки данных
  110. 0076: 3A 01 F8    LD A, ($F801)   ; Увеличиваем индекс
  111. 0079: 3C          INC A
  112. 007A: 32 01 F8    LD ($F801), A
  113. 007D: CD 59 F8    CALL $F859      ; Вызов подпрограммы в области данных
  114. 0080: C9          RET
  115.  
  116. ;===============================================================================
  117. ; ОБРАБОТЧИК КОНЦА ДАННЫХ (ЗАЦИКЛИВАНИЕ)
  118. ;===============================================================================
  119. 0081: AF          XOR A           ; A = 0
  120. 0082: 32 01 F8    LD ($F801), A   ; Сбрасываем индекс в 0
  121. 0085: 18 CF       JR $0056        ; Возврат к обработчику прерывания
  122.  
  123. ;===============================================================================
  124. ; ОСНОВНАЯ ПОДПРОГРАММА ОБРАБОТКИ ФРЕЙМА
  125. ;===============================================================================
  126. 0087: 3A 06 F8    LD A, ($F806)   ; Загружаем флаг спецэффектов
  127. 008A: A7          AND A           ; Проверяем на 0
  128. 008B: C0          RET NZ          ; Если не ноль - выходим (звук уже обрабатывается)
  129.  
  130. 008C: 3A 04 F8    LD A, ($F804)   ; Загружаем указатель канала A
  131. 008F: 6F          LD L, A         ; L = указатель канала A
  132. 0090: 3A 05 F8    LD A, ($F805)   ; Загружаем указатель канала B
  133. 0093: B5          OR L            ; Проверяем, оба ли нулевые
  134. 0094: A7          AND A           ; Устанавливаем флаги
  135. 0095: 28 11       JR Z, $00A8     ; Если оба нулевые - переход
  136.  
  137. 0097: 2A 04 F8    LD HL, ($F804)  ; HL = (указатель A, указатель B)
  138. 009A: 2B          DEC HL          ; Уменьшаем (длительность ноты)
  139. 009B: 22 04 F8    LD ($F804), HL  ; Сохраняем обратно
  140. 009E: CD 5F F8    CALL $F85F      ; Вызов подпрограммы в области данных
  141. 00A1: 11 78 05    LD DE, $0578    ; DE = константа (период?)
  142. 00A4: CD 04 01    CALL $0104      ; Вызов подпрограммы
  143. 00A7: C9          RET
  144.  
  145. 00A8: CD E3 00    CALL $00E3      ; Вызов подпрограммы
  146. 00AB: C9          RET
  147.  
  148. ;===============================================================================
  149. ; ПОДПРОГРАММА ОЖИДАНИЯ
  150. ;===============================================================================
  151. 00AC: CD E3 00    CALL $00E3      ; Вызов подпрограммы
  152. 00AF: 11 55 55    LD DE, $5555    ; DE = паттерн 0101010101010101
  153. 00B2: CD 04 01    CALL $0104      ; Вызов подпрограммы
  154. 00B5: 32 06 F8    LD ($F806), A   ; Сохраняем результат
  155. 00B8: CD C7 00    CALL $00C7      ; Вызов инициализации AY
  156. 00BB: 3A 00 F8    LD A, ($F800)   ; Загружаем счетчик прерываний
  157. 00BE: CB 4F       BIT 1, A        ; Проверяем бит 1
  158. 00C0: 28 EA       JR Z, $00AC     ; Если сброшен - повторяем ожидание
  159. 00C2: CB 47       BIT 0, A        ; Проверяем бит 0
  160. 00C4: 20 90       JR NZ, $0056    ; Если установлен - переход к обработчику
  161. 00C6: C9          RET
  162.  
  163. ;===============================================================================
  164. ; ИНИЦИАЛИЗАЦИЯ AY-3-8910 (базовые регистры)
  165. ;===============================================================================
  166. 00C7: 3E 07       LD A, $07       ; Регистр 7 (микшер)
  167. 00C9: 06 FF       LD B, $FF       ; B = FF (порт адреса)
  168. 00CB: ED 79       OUT (C), A      ; Выбираем регистр 7
  169. 00CD: ED 78       IN A, (C)       ; Читаем текущее значение
  170. 00CF: CB BF       RES 7, A        ; Сбрасываем бит 7
  171. 00D1: CB B7       RES 6, A        ; Сбрасываем бит 6
  172. 00D3: 06 BF       LD B, $BF       ; B = BF (порт данных)
  173. 00D5: ED 79       OUT (C), A      ; Записываем новое значение
  174. 00D7: 3E 0E       LD A, $0E       ; Регистр 14 (порт A - управление)
  175. 00D9: 06 FF       LD B, $FF       ; Порт адреса
  176. 00DB: ED 79       OUT (C), A      ; Выбираем регистр 14
  177. 00DD: ED 78       IN A, (C)       ; Читаем
  178. 00DF: 32 00 F8    LD ($F800), A   ; Сохраняем как флаг прерываний
  179. 00E2: C9          RET
  180.  
  181. ;===============================================================================
  182. ; ПОДПРОГРАММА РАБОТЫ С AY (чтение/запись регистров)
  183. ;===============================================================================
  184. 00E3: 06 FF       LD B, $FF       ; Порт адреса
  185. 00E5: 3E 0C       LD A, $0C       ; Регистр 12 (огибающая - период младший)
  186. 00E7: ED 79       OUT (C), A      ; Выбираем
  187. 00E9: ED 78       IN A, (C)       ; Читаем
  188. 00EB: 6F          LD L, A         ; L = младший байт периода огибающей
  189. 00EC: 3E 07       LD A, $07       ; Регистр 7
  190. 00EE: ED 79       OUT (C), A      ; Выбираем
  191. 00F0: ED 78       IN A, (C)       ; Читаем
  192. 00F2: F6 C0       OR $C0          ; Устанавливаем биты 7 и 6
  193. 00F4: A5          AND L           ; Логическое И с L
  194. 00F5: 3C          INC A           ; Увеличиваем
  195. 00F6: C8          RET Z           ; Если стало 0 - возврат
  196. 00F7: 3E 0D       LD A, $0D       ; Регистр 13 (огибающая - период старший)
  197. 00F9: ED 79       OUT (C), A      ; Выбираем
  198. 00FB: 06 BF       LD B, $BF       ; Порт данных
  199. 00FD: 3E 01       LD A, $01       ; Значение 1
  200. 00FF: ED 79       OUT (C), A      ; Записываем
  201. 0101: C3 4C F8    JP $F84C        ; Прыжок в область данных (дальнейшая обработка)
  202.  
  203. ;===============================================================================
  204. ; ПОДПРОГРАММА ПРОВЕРКИ/ОЖИДАНИЯ
  205. ;===============================================================================
  206. 0104: 1B          DEC DE          ; DE--
  207. 0105: 7A          LD A, D         ; Проверяем D|E == 0?
  208. 0106: B3          OR E
  209. 0107: 20 FB       JR NZ, $0104    ; Если не ноль - повторяем
  210. 0109: C9          RET
  211.  
  212. ;===============================================================================
  213. ; ПОДПРОГРАММА ОБРАБОТКИ ДАННЫХ (распаковка ноты)
  214. ;===============================================================================
  215. 010A: 7E          LD A, (HL)      ; Читаем байт из потока (HL из самомод. кода)
  216. 010B: 5F          LD E, A         ; E = прочитанный байт
  217. 010C: AF          XOR A           ; A = 0
  218. 010D: 67          LD H, A         ; H = 0
  219. 010E: 6F          LD L, A         ; L = 0
  220. 010F: 57          LD D, A         ; D = 0
  221. 0110: 06 06       LD B, $06       ; B = 6 (счетчик битов)
  222. 0112: 19          ADD HL, DE      ; HL = HL + DE
  223. 0113: 10 FD       DJNZ $0112      ; B раз: HL = E * 6? (6 раз прибавляем E)
  224.                                  ; На самом деле это умножение на 6
  225. 0115: 29          ADD HL, HL      ; Умножаем на 2 (итого E * 12)
  226. 0116: 29          ADD HL, HL      ; Умножаем на 2 (E * 24)
  227. 0117: 29          ADD HL, HL      ; Умножаем на 2 (E * 48)
  228. 0118: 29          ADD HL, HL      ; Умножаем на 2 (E * 96)
  229. 0119: 29          ADD HL, HL      ; Умножаем на 2 (E * 192)
  230. 011A: 24 FD       INC H           ; Коррекция? (FD - странный байт)
  231. 011C: F8          ?               ; Мусор? Должно быть LD A, B?
  232. 011D: C9          RET
  233.  
  234. ;===============================================================================
  235. ; ПОДПРОГРАММА НАСТРОЙКИ КАНАЛОВ
  236. ;===============================================================================
  237. 011E: 3A 00 F8    LD A, ($F800)   ; Загружаем флаг прерываний
  238. 0121: CB 57       BIT 2, A        ; Проверяем бит 2
  239. 0123: C8          RET Z           ; Если сброшен - выходим
  240. 0124: E6 01       AND $01         ; Оставляем только бит 0
  241. 0126: 5F          LD E, A         ; E = бит 0
  242. 0127: 3A 03 F8    LD A, ($F803)   ; Загружаем что-то из F803
  243. 012A: E6 01       AND $01         ; Оставляем бит 0
  244. 012C: BB          CP E            ; Сравниваем с предыдущим
  245. 012D: C8          RET Z           ; Если равны - выходим
  246. 012E: 3E FF       LD A, $FF       ; Иначе A = FF
  247. 0130: 32 06 F8    LD ($F806), A   ; Устанавливаем флаг спецэффектов
  248. 0133: 3A 00 F8    LD A, ($F800)   ; Копируем F800 в F803
  249. 0136: 32 03 F8    LD ($F803), A
  250. 0139: 21 00 00    LD HL, $0000    ; HL = 0
  251. 013C: 22 04 F8    LD ($F804), HL  ; Обнуляем указатели каналов
  252. 013F: C9          RET
  253.  
  254. ;===============================================================================
  255. ; ПОДПРОГРАММА (ЗАГРУЗКА РЕГИСТРОВ ИЗ ТАБЛИЦЫ)
  256. ;===============================================================================
  257. 0140: 21 7E 01    LD HL, $017E    ; HL = начало таблицы данных (017E)
  258. 0143: 1E 0D       LD E, $0D       ; E = 13 (количество регистров для загрузки)
  259. 0145: 06 FF       LD B, $FF       ; Порт адреса
  260. 0147: ED 59       OUT (C), E      ; Выбираем регистр E (сначала 0D, потом уменьшается)
  261. 0149: 7E          LD A, (HL)      ; Читаем байт из таблицы
  262. 014A: 06 BF       LD B, $BF       ; Порт данных
  263. 014C: 23          INC HL          ; HL на следующий байт таблицы
  264. 014D: ED 79       OUT (C), A      ; Записываем в регистр AY
  265. 014F: 1D          DEC E           ; Уменьшаем номер регистра
  266. 0150: F2 45 01    JP P, $0145     ; Если E >= 0, продолжаем
  267. 0153: C9          RET
  268.  
  269. ;===============================================================================
  270. ; ПОДПРОГРАММА (короткая настройка AY)
  271. ;===============================================================================
  272. 0154: 3E 07       LD A, $07       ; Регистр 7
  273. 0156: 06 FF       LD B, $FF       ; Порт адреса
  274. 0158: ED 79       OUT (C), A      ; Выбираем
  275. 015A: ED 78       IN A, (C)       ; Читаем
  276. 015C: CB FF       SET 7, A        ; Устанавливаем бит 7
  277. 015E: CB F7       SET 6, A        ; Устанавливаем бит 6
  278. 0160: 06 BF       LD B, $BF       ; Порт данных
  279. 0162: ED 79       OUT (C), A      ; Записываем (отключаем тональные каналы?)
  280. 0164: 3E 0F       LD A, $0F       ; Регистр 15 (порт B - управление)
  281. 0166: 06 FF       LD B, $FF       ; Порт адреса
  282. 0168: ED 79       OUT (C), A      ; Выбираем
  283. 016A: 21 8C 01    LD HL, $018C    ; HL = адрес таблицы (018C)
  284. 016D: 7E          LD A, (HL)      ; Читаем байт
  285. 016E: 23          INC HL
  286. 016F: FE 00       CP $00          ; Сравниваем с 0
  287. 0171: C8          RET Z           ; Если 0 - конец таблицы
  288. 0172: 06 BF       LD B, $BF       ; Порт данных
  289. 0174: ED 79       OUT (C), A      ; Записываем в регистр 15
  290. 0176: 11 00 12    LD DE, $1200    ; DE = константа (пауза?)
  291. 0179: CD 04 01    CALL $0104      ; Вызов подпрограммы ожидания
  292. 017C: 18 EF       JR $016D        ; Повторяем для следующего байта
  293.  
  294. ;===============================================================================
  295. ; ТАБЛИЦА ДАННЫХ (с 017E)
  296. ;===============================================================================
  297. 017E: 01 50 C4 10 10 10 38 00 50 00 01 00 30    ; Данные для регистров AY
  298. 018B: 7F                                        ;
  299. 018C: BF DF EF                                  ; Данные для регистра 15
  300. 018F: 00 00                                     ; Маркер конца?
  301.  
  302. ;===============================================================================
  303. ; ОСНОВНАЯ ТАБЛИЦА АДРЕСОВ ПАТТЕРНОВ (с 0191)
  304. ;===============================================================================
  305. 0191: 00 5C 06 91 0F 3A 1A 97 22 9C 2C 5A 36 1A 3E FC
  306. 01A0: 48 45 4F 9B 5C 37 68 8A 6E 71 74 57 86 12 92 D2
  307. 01B0: 9A 4D A2 6F AF 41 BE 22 C6 B7 CC 49 D4 02 DC A0
  308. 01C0: E3 5B E8 FF FF FF FF FF FF FF FF FF FF FF FF FF
  309. ; Заканчивается серией FF (конец данных)
  310.  
  311.  
  312. /*
  313.  
  314. Анализ и объяснение ключевых механизмов
  315. 1. Двухступенчатая адресация данных
  316. Прошивка использует классическую для PT3 схему:
  317.  
  318. text
  319. F801 (индекс) → Таблица 0191 (адреса) → Данные в верхней памяти (F8xx)
  320. Это позволяет легко менять композицию, просто заменяя данные в области F800-FFFF, не трогая код.
  321.  
  322. 2. Механизм проверки целостности
  323. Цикл с 0014 по 001B выполняет важную функцию: он проверяет, что таблица данных не повреждена. Это защита от:
  324.  
  325. Сбоев при копировании
  326.  
  327. Частичной записи данных
  328.  
  329. Битых байтов в ПЗУ
  330.  
  331. 3. Управление каналами через указатели
  332. Переменные F804 и F805 работают как счетчики длительности нот:
  333.  
  334. Когда они не равны нулю — нота играет
  335.  
  336. Когда оба становятся нулевыми — вызывается подпрограмма 0154 для выбора следующей ноты
  337.  
  338. 4. AY-3-8910: хитрости управления
  339. В подпрограмме 00C7 и 00E3 видна важная особенность:
  340.  
  341. Порт FF — адресный (выбор регистра)
  342.  
  343. Порт BF — данные (запись/чтение значения)
  344.  
  345. Обратите внимание на биты 7 и 6 в регистре 7 (00F2): их установка отключает генерацию тона для каналов B и C, оставляя только шум или огибающую.
  346.  
  347. 5. Умножение на 192 в 010A
  348. Алгоритм с 010A по 011A выполняет умножение входного байта на 192 (6 × 32). Это, скорее всего, преобразование номера ноты в период для AY:
  349.  
  350. text
  351. Период = (байт_из_потока) * 192 + базовая_константа
  352. 6. Зацикливание композиции
  353. Когда в таблице 0191 встречается адрес FFFF, программа сбрасывает индекс в 0 (0081) и начинает композицию заново.
  354.  
  355. Рекомендации по улучшению кода
  356. 1. Убрать самомодифицирующийся код (опционально)
  357. Сейчас адрес данных хранится по F85A и используется подпрограммами. Это быстро, но:
  358.  
  359. Мешает размещению кода в ПЗУ (если плеер в ПЗУ, писать нельзя)
  360.  
  361. Затрудняет отладку
  362.  
  363. Можно заменить на: хранение в паре регистров (например, IX) и передачу через стек.
  364.  
  365. 2. Добавить громкость
  366. В текущем коде не видно явной установки регистров громкости (8, 9, 10). Возможно, они задаются в данных по F85F или F859. Если нужно регулировать громкость программно, стоит добавить запись в эти регистры.
  367.  
  368. 3. Расширить до 3 каналов
  369. Сейчас код работает с двумя указателями (F804, F805). Для третьего канала нужно добавить F806 (который сейчас используется как флаг) и расширить логику проверки.
  370.  
  371. 4. Оптимизировать умножение
  372. Умножение на 192 через 6 сложений и 5 сдвигов можно заменить на:
  373.  
  374. assembly
  375. LD H, E
  376. LD L, 0
  377. ADD HL, HL   ; *2
  378. ADD HL, HL   ; *4
  379. ADD HL, HL   ; *8
  380. ADD HL, HL   ; *16
  381. ADD HL, HL   ; *32
  382. ADD HL, HL   ; *64
  383. ADD HL, HL   ; *128
  384. ; Теперь нужно добавить E*64? Сложно...
  385. Но текущий способ рабочий, менять не обязательно.
  386.  
  387. 5. Добавить обработку шума
  388. Регистры шума (6) и его микширование (7) уже настроены в 00C7. Можно добавить поддержку перкуссии, записывая нужные значения в регистр 6 из потока данных.
  389.  
  390. 6. Увеличить громкость звонка
  391. Если звонок тихий, проверьте регистры 8, 9, 10 (громкость каналов A, B, C). Сейчас они, видимо, задаются в таблице по адресу 017E (данные 01 50 C4...). Можно увеличить значения (максимум 15).
  392.  
  393. Возможные модификации для новых функций
  394. Добавление паузы между звонками
  395. Вставьте в главный цикл (0030-0054) счетчик, который пропускает несколько фреймов после окончания мелодии.
  396.  
  397. Смена мелодии по внешнему сигналу
  398. Используйте бит порта ввода для выбора разных таблиц (0191 или другой адрес).
  399.  
  400. Режим "случайной" мелодии
  401. При обнаружении FFFF (конец) вместо сброса в 0 загружайте случайный индекс в пределах допустимого диапазона.
  402.  
  403. Этот код — отличная основа для экспериментов. Он компактный, надежный и хорошо документирован самой структурой. Удачи в улучшении звонка!
  404. */
Advertisement
Add Comment
Please, Sign In to add comment