Advertisement
Bisqwit

Cartoonist OPL3 MIDI player

Jul 11th, 2017
426
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 00000000  E94403            jmp RUN_FUNCTION
  2. 00000003  E95C03            jmp SONG_START
  3. 00000006  E9C603            jmp SONG_STOP
  4. 00000009  E9C303            jmp SONG_STOP
  5. 0000000C  E9C003            jmp SONG_STOP
  6. 0000000F  E9BD03            jmp SONG_STOP
  7.  
  8. MIDI_DATA_SEGMENT
  9. 00000012  .word 0x22F6
  10. PITCH_TABLE
  11. 00000014   .word  344, 364, 386, 409, 433, 459, 486, 515, 546, 578
  12.            .word  613, 649,1368,1388,1410,1433,1457,1483,1510,1539
  13.            .word 1570,1602,1637,1673,2392,2412,2434,2457,2481,2507
  14.            .word 2534,2563,2594,2626,2661,2697,3416,3436,3458,3481
  15.            .word 3505,3531,3558,3587,3618,3650,3685,3721,4440,4460
  16.            .word 4482,4505,4529,4555,4582,4611,4642,4674,4709,4745
  17.            .word 5464,5484,5506,5529,5553,5579,5606,5635,5666,5698
  18.            .word 5733,5769,6488,6508,6530,6553,6577,6603,6630,6659
  19.            .word 6690,6722,6757,6793,7512,7532,7554,7577,7601,7627
  20.            .word 7654,7683,7714,7746,7781,7817,   0
  21. LIST_OF_INITIAL_00_REGISTERS
  22. 000000D6  .byte 0x01,0x08,0xBD,0x20..0x25,0x28..0x2D,0x30..0x35
  23.           .byte                0x40..0x45,0x48..0x4D,0x50..0x55
  24.           .byte                0x60..0x65,0x68..0x6D,0x70..0x75
  25.           .byte                0xA0..0xA8,0xB0..0xB8,0xC0..0xC8
  26.           .byte                0xE0..0xE5,0xE8..0xED,0xF0..0xF5
  27. LIST_OF_INITIAL_3F_REGISTERS
  28. 0000013C  .byte 0x80..0x8D, 0x90..0x95
  29. LSFR_VALUE
  30. 0000014E  .word 0x563A
  31. PATCH_NUMBER_MAPPING_TO_INSTRUMENT_NUMBERS
  32. 00000150  .byte 0x00..0x14, 0x00...
  33. INSTRUMENT_POINTERS
  34. 00000187  .word 0x259,0x1EB,0x21D,0x1F5
  35.           .word 0x1EB,0x1B9,0x209,0x1E1
  36.           .word 0x1FF,0x1C3,0x26D,0x1AF
  37.           .word 0x213,0x1CD,0x1D7,0x231
  38.           .word 0x295,0x227,0x23B,0x1CD
  39. INSTRUMENT_DATA
  40. 000001AF  B1 1C 61 1F 61 9D 92 1B 0E F4         ins 11
  41. 000001B9  F0 86 61 03 71 1F E3 2C 0A 00         ins 5
  42. 000001C3  30 15 D5 19 71 9B 61 1B 0C 00         ins 9
  43. 000001CD  07 4F F2 60 12 21 F2 72 08 F4         ins 13 & 19
  44. 000001D7  01 40 F4 53 08 64 F3 53 00 EE         ins 14
  45. 000001E1  F2 4B 31 03 F4 21 53 2C 04 E8         ins 7
  46. 000001EB  E4 8A FF 0F E1 A9 FF 0F 01 F4         ins 1
  47. 000001F5  01 4F F1 50 01 22 E4 7C 06 00         ins 3
  48. 000001FF  E2 11 AE 8F 61 23 85 2A 0E 00         ins 8
  49. 00000209  B0 86 61 03 F3 1F E3 2C 08 00         ins 6
  50. 00000213  21 18 63 4C 21 A0 C5 0F 0C F4         ins 12
  51. 0000021D  10 07 FF 31 01 25 FF 04 0A 00         ins 2
  52. 00000227  62 00 F0 F5 0E 1F F6 F8 0E 00         ins 17  (percussion 0x26)
  53. 00000231  32 44 F8 FF 11 1F F5 7F 0E E2         ins 15
  54. 0000023B  4E 00 FC 05 0C 24 F9 F8 00 00         ins 18  (percussion 0x2A)
  55. 00000245  6E 00 75 05 01 22 F6 F8 0E 00         unused?
  56. 0000024F  31 90 F1 11 18 A5 D4 43 08 E8         unused?
  57. 00000259  E0 8D F4 1B E0 23 F3 18 0A 00         ins 0
  58. 00000263  E0 E8 AE 8F 61 21 85 0A 0E 00         unused?
  59. 0000026D  31 1C 41 0B 61 99 92 3B 0E F4         ins 10  (percussion 0x36)
  60. 00000277  F2 16 90 29 F2 22 61 2C 0A E8         unused?
  61. 00000281  E0 8D F4 2B E0 1F F3 48 08 00         unused?
  62. 0000028B  31 45 F3 23 33 25 43 9C 06 E8         unused?
  63. 00000295  00 00 A7 4C 00 22 C6 4F 00 00         ins 16  (percussion 0x24)
  64. 0000029F  00 00 A7 4C 00 2B C6 4F 00 E8         unused?
  65. 000002A9  04 00 F7 B5 0C                        unused?
  66. MODULATOR_REGISTER_INDEX_TABLE
  67. 000002AE  .byte 00 01 02 08 09 0A 10 11 12
  68. CARRIER_REGISTER_INDEX_TABLE
  69. 000002B7  .byte 03 04 05 0B 0C 0D 13 14 15
  70. ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL
  71. 000002C0  .byte 1,2,3,4, -1,-1,-1,-1,-1         (LOADED FROM MIDI DATA AT OFFSET 0x22)
  72. ADLIB_CHANNEL_CURRENTLY_KEYED_ON
  73. 000002C9  .byte 1,1,1,1, 0,0,0,0,0
  74. ADLIB_CHANNEL_KEYED_ON_NOTENUMBER
  75. 000002D2  .byte 0x3C,0x4D,0x45,0x41, 0,0,0,0,0
  76. ADLIB_CHANNEL_CURRENT_FINETUNE_LEVEL
  77. 000002DB  .byte -12,-12,-12,-12, 0,0,0,0,0
  78. ADLIB_CHANNEL_PLAYING_THIS_MIDI_PERCUSSION_NOTENUMBER
  79. 000002E4  .byte 0,0,0,0,0, 0x36,0x2A,0x24,0x26
  80. ADLIB_CHANNEL_PLAYING_THIS_ACTUAL_NOTENUMBER_FOR_PERCUSSION
  81. 000002ED  .byte 0,0,0,0,0, 0x49,0x17,0x0C,0x01
  82. ADLIB_CHANNEL_PERCUSSION_PATCH_NUMBER
  83. 000002F6  .byte 0,0,0,0,0, 0x0A,0x12,0x10,0x11
  84. ADLIB_CHANNEL_REGISTER_43_VALUE
  85. 000002FF  .byte 0xA9,0x99,0xA9,0xA9,0x00,0x00,0x00,0x00,0x00
  86. ADLIB_CHANNEL_REG_A0_PITCH_LOW_8_BITS
  87. 00000308  .byte 0x58,0xCB,0x42,0xCB,0x00,0x00,0x00,0x00,0x00
  88. ADLIB_CHANNEL_REG_B0_PITCH_HIGH_2_BITS_AND_KEYON_BITS
  89. 00000311  .byte 0x31,0x35,0x32,0x31,0x00,0x00,0x00,0x00,0x00
  90. ADLIB_CHANNEL_NOTE_AGE
  91. 0000031A  .word 0x003A,0x000C,0x003A,0x003A,0x0000,0x0000,0x0000,0x0000,0x0000
  92. MIDI_SOURCE_POINTER
  93. 0000032C  .word 0x0161          (LOADED FROM MIDI DATA AT OFFSET 0x00)
  94. MIDI_LOOPSTART_POINTER
  95. 0000032E  .word 0x007D          (LOADED FROM MIDI DATA AT OFFSET 0x00)
  96. MIDI_RUNNING_STATUS
  97. 00000330  .byte 0x90
  98. MIDI_CHANNEL_NUMBER
  99. 00000331  .byte 0x02
  100. MIDI_REMAINING_DELAY_COUNTER
  101. 00000332  .byte 7
  102. MIDI_COMMAND_WAS_UNRECOGNIZED
  103. 00000333  .byte 0
  104. MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE
  105. 00000334  .byte 1
  106. MIDI_SONG_PLAYING_FLAG
  107. 00000335  .byte 0
  108. FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0
  109. 00000336  .byte 0x20
  110. OLDEST_CHANNEL_POINTER
  111. 00000337  .word 0x0000
  112. FUNCTION_PARAMETER_PITCH_BEND_VALUE
  113. 00000339  .word 0x0000
  114. TEMPORARY
  115. 0000033B  .byte 0x00
  116. UNKNOWN_BYTE_33C
  117. 0000033C  .byte 0
  118.  
  119. FUNCTION_TABLE
  120. 00000341  .word TIMER_CALLBACK, SONG_START, SONG_STOP
  121.  
  122. RUN_FUNCTION
  123.         AH = function number (0 = timer callback, 1 = start song, 2 = stop song)
  124.                 0:
  125.                 1: CX = segment number where song is located
  126.                 2:
  127. 00000347  53                push bx
  128. 00000348  51                push cx
  129. 00000349  52                push dx
  130. 0000034A  57                push di
  131. 0000034B  56                push si
  132. 0000034C  1E                push ds
  133. 0000034D  0E                push cs
  134. 0000034E  1F                pop ds
  135. 0000034F  8BF3               mov si,bx
  136. 00000351  32FF               xor bh,bh
  137. 00000353  8ADC               mov bl,ah
  138. 00000355  D0E3               shl bl,1
  139. 00000357  FF974103           call word near [bx+FUNCTION_TABLE]
  140. 0000035B  1F                pop ds
  141. 0000035C  5E                pop si
  142. 0000035D  5F                pop di
  143. 0000035E  5A                pop dx
  144. 0000035F  59                pop cx
  145. 00000360  5B                pop bx
  146. 00000361  CB                retf
  147.  
  148. SONG_START
  149. 00000362  FA                cli
  150. 00000363  890E1200          mov [MIDI_DATA_SEGMENT],cx
  151. 00000367  06                push es
  152. 00000368  8EC1               mov es,cx
  153. 0000036A  26A10000           mov ax,[es:0x0]
  154. 0000036E  A32C03             mov [MIDI_SOURCE_POINTER],ax
  155. 00000371  A32E03             mov [MIDI_LOOPSTART_POINTER],ax
  156. 00000374  33FF               xor di,di
  157. 00000376  268A4522           mov al,[es:di+0x22]
  158. 0000037A  8885C002           mov [di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL],al
  159. 0000037E  47                 inc di
  160. 0000037F  83FF09             cmp di,byte +0x9
  161. 00000382  75F2               jnz 0x376
  162. 00000384  07                pop es
  163. 00000385  E89A04            call word RESET_ADLIB
  164. 00000388  33FF              xor di,di
  165. 0000038A  8BDF              mov bx,di
  166. 0000038C  D1E3              shl bx,1            ; Initialize data
  167. 0000038E  C685C90200        mov byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x0
  168. 00000393  C685D20200        mov byte [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],0x0
  169. 00000398  C7871A030000      mov word [bx+ADLIB_CHANNEL_NOTE_AGE],0x0
  170. 0000039E  47                inc di
  171. 0000039F  83FF09            cmp di,byte +0x9    ; Loop for 9 AdLib channels
  172. 000003A2  75E6              jnz 0x38a
  173. 000003A4  33FF              xor di,di
  174. 000003A6  80BDC00209        cmp byte [di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL],0x9
  175. 000003AB  750B              jnz 0x3b8           ; Initialize percussion channels used in the song
  176. 000003AD  8A9DF602          mov bl,[di+ADLIB_CHANNEL_PERCUSSION_PATCH_NUMBER]
  177. 000003B1  8BCF              mov cx,di
  178. 000003B3  57                push di
  179. 000003B4  E86903             call PROGRAM_PATCH
  180. 000003B7  5F                pop di
  181. 000003B8  47                inc di
  182. 000003B9  83FF09            cmp di,byte +0x9    ; Loop for 9 AdLib channels
  183. 000003BC  75E8              jnz 0x3a6
  184. 000003BE  C606320300        mov byte [MIDI_REMAINING_DELAY_COUNTER],0x0 ;Initialize rest of data
  185. 000003C3  C6063C0300        mov byte [UNKNOWN_BYTE_33C],0x0
  186. 000003C8  C606350301        mov byte [MIDI_SONG_PLAYING_FLAG],0x1
  187. 000003CD  FB                sti
  188. 000003CE  C3                ret
  189.  
  190. SONG_STOP
  191. 000003CF  FA                cli
  192. 000003D0  C606350300        mov byte [MIDI_SONG_PLAYING_FLAG],0x0
  193. 000003D5  E84A04            call word RESET_ADLIB
  194. 000003D8  FB                sti
  195. 000003D9  C3                ret
  196.  
  197. TIMER_CALLBACK
  198. 000003DA  803E350301        cmp byte [MIDI_SONG_PLAYING_FLAG],0x1
  199. 000003DF  7403              jz 0x3e4                    ; Quit early if no song is playing
  200. 000003E1  E9F200            ret
  201. 000003E4  8E061200          mov es,[MIDI_DATA_SEGMENT]
  202. 000003E8  8B362C03          mov si,[MIDI_SOURCE_POINTER]
  203. 000003EC  33FF              xor di,di
  204. 000003EE  8BDF              mov bx,di
  205. 000003F0  D1E3              shl bx,1
  206. 000003F2  80BDC90201        cmp byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  207. 000003F7  7504              jne 0x3fd
  208. 000003F9  FF871A03          inc word [bx+ADLIB_CHANNEL_NOTE_AGE]        ; Increment the age of all keyed-on channels
  209. 000003FD  47                inc di
  210. 000003FE  83FF09            cmp di,byte +0x9
  211. 00000401  75EB              jnz 0x3ee
  212. 00000403  803E320300        cmp byte [MIDI_REMAINING_DELAY_COUNTER],0x0
  213. 00000408  7407              jz 0x411
  214. 0000040A  FE0E3203          dec byte [MIDI_REMAINING_DELAY_COUNTER]     ; Wait until delay is completed
  215. 0000040E  E9C100            jmp SaveCurrentPointer
  216. LoadNextCommand
  217. 00000411  268A04            mov al,[es:si]
  218. 00000414  46                inc si
  219. 00000415  84C0              test al,al
  220. 00000417  7818              js 0x431
  221. 00000419  8A263003          mov ah,[MIDI_RUNNING_STATUS]                ; Repeat last command if command < 0x80
  222. 0000041D  4E                dec si
  223. 0000041E  803E330300        cmp byte [MIDI_COMMAND_WAS_UNRECOGNIZED],0x0        ; If repeated command was unrecognized, skip byte:
  224. 00000423  7425              jz 0x44a
  225. 00000425  46                inc si
  226. 00000426  803E340300        cmp byte [MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE],0x0   ; If triplebyte, skip another byte
  227. 0000042B  7401              jz 0x42e
  228. 0000042D  46                inc si
  229. 0000042E  E98E00            jmp LoadDelayValue                                  ; Done skipping; jump to loading the delay byte.
  230. 00000431  3CFC              cmp al,0xfc                                 ; Command was >= 0x80. Identify it.
  231. 00000433  7503              jnz 0x438
  232. 00000435  E9C500            jmp HANDLE_FC_LOOP
  233. 00000438  8AE0              mov ah,al
  234. 0000043A  80E40F            and ah,0xf
  235. 0000043D  88263103          mov [MIDI_CHANNEL_NUMBER],ah
  236. 00000441  8AE0              mov ah,al
  237. 00000443  80E4F0            and ah,0xf0
  238. 00000446  88263003          mov [MIDI_RUNNING_STATUS],ah
  239. 0000044A  80FCE0            cmp ah,0xe0                                 ; Lands here also if there was running status.
  240. 0000044D  753A              jnz WasNotPitchBend
  241.  
  242. HANDLE_E0_PITCHBEND
  243. 0000044F  C606340301        mov byte [MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE],0x1
  244. 00000454  268A14            mov dl,[es:si]
  245. 00000457  46                inc si
  246. 00000458  268A34            mov dh,[es:si]
  247. 0000045B  46                inc si
  248. 0000045C  D0EE              shr dh,1
  249. 0000045E  7303              jnc 0x463
  250. 00000460  80CA80            or dl,0x80
  251. 00000463  89163903          mov [FUNCTION_PARAMETER_PITCH_BEND_VALUE],dx                        ; Save pitch-bend value.
  252. 00000467  A03103            mov al,[MIDI_CHANNEL_NUMBER]                ; Update all notes playing on this MIDI channel.
  253. 0000046A  33FF              xor di,di
  254. 0000046C  3A85C002          cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  255. 00000470  750E              jnz 0x480
  256. 00000472  80BDC90201        cmp byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  257. 00000477  7507              jnz 0x480
  258. 00000479  8BCF              mov cx,di
  259. 0000047B  57                push di
  260. 0000047C  E84902             call RECALCULATE_PITCH_AND_WRITE
  261. 0000047F  5F                pop di
  262. 00000480  47                inc di
  263. 00000481  83FF09            cmp di,byte +0x9                            ; Loop for 9 AdLib channels.
  264. 00000484  75E6              jnz 0x46c
  265. 00000486  EB3790            jmp LoadDelayValue
  266.  
  267. WasNotPitchBend
  268. 00000489  C606330300        mov byte [MIDI_COMMAND_WAS_UNRECOGNIZED],0x0
  269. 0000048E  C606340301        mov byte [MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE],0x1
  270. 00000493  80FCC0            cmp ah,0xc0
  271. 00000496  7508              jnz 0x4a0
  272. 00000498  C606340300        mov byte [MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE],0x0   ; Command Cx is double-byte
  273. 0000049D  EB3890            jmp HANDLE_C0_PATCHCHANGE
  274. 000004A0  80FC90            cmp ah,0x90
  275. 000004A3  7503              jnz 0x4a8
  276. 000004A5  EB6C90            jmp HANDLE_90_NOTEON
  277. 000004A8  80FC80            cmp ah,0x80
  278. 000004AB  7503              jnz 0x4b0
  279. 000004AD  E92C01            jmp HANDLE_80_NOTEOFF
  280. 000004B0  46                inc si
  281. 000004B1  46                inc si
  282. 000004B2  C606340301        mov byte [MIDI_UNKNOWN_COMMAND_IS_TRIPLEBYTE],0x1   ; Assume unsupported command is triple-byte
  283. 000004B7  C606330301        mov byte [MIDI_COMMAND_WAS_UNRECOGNIZED],0x1
  284. 000004BC  EB0190            jmp LoadDelayValue
  285. LoadDelayValue
  286. 000004BF  268A04            mov al,[es:si]
  287. 000004C2  46                inc si
  288. 000004C3  3C00              cmp al,0x0                                  ; If the delay is zero,
  289. 000004C5  7503              jnz 0x4ca                                   ; process the next command immediately.
  290. 000004C7  E947FF            jmp LoadNextCommand
  291. 000004CA  FEC8              dec al
  292. 000004CC  A23203            mov [MIDI_REMAINING_DELAY_COUNTER],al
  293. 000004CF  EB0190            jmp SaveCurrentPointer
  294. SaveCurrentPointer
  295. 000004D2  89362C03          mov [MIDI_SOURCE_POINTER],si
  296. 000004D6  C3                ret
  297.  
  298. HANDLE_C0_PATCHCHANGE
  299. 000004D7  33FF              xor di,di
  300. 000004D9  33C9              xor cx,cx
  301. 000004DB  268A1C            mov bl,[es:si]
  302. 000004DE  46                inc si
  303. 000004DF  A03103            mov al,[MIDI_CHANNEL_NUMBER]
  304. 000004E2  3C09              cmp al,0x9
  305. 000004E4  740F              jz 0x4f5            ; Ignore if MIDI channel is 9 (percussion)
  306. 000004E6  3A85C002          cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  307. 000004EA  7509              jnz 0x4f5           ; Update patch on all AdLib channels that
  308. 000004EC  8BCF              mov cx,di           ; are dedicated for this MIDI channel
  309. 000004EE  57                push di
  310. 000004EF  53                push bx
  311. 000004F0  E82D02            call PROGRAM_PATCH
  312. 000004F3  5B                pop bx
  313. 000004F4  5F                pop di
  314. 000004F5  47                inc di
  315. 000004F6  83FF09            cmp di,byte +0x9    ; Loop for 9 AdLib channels
  316. 000004F9  75E4              jnz 0x4df
  317. 000004FB  EBC2              jmp LoadDelayValue
  318.  
  319. HANDLE_FC_LOOP
  320. 000004FD  268A04            mov al,[es:si]
  321. 00000500  46                inc si
  322. 00000501  3C80              cmp al,0x80
  323. 00000503  7407              jz 0x50c            ; Terminate song if next byte is not 0x80
  324. 00000505  C606350300        mov byte [MIDI_SONG_PLAYING_FLAG],0x0
  325. 0000050A  EBCA              ret
  326. 0000050C  8B362E03          mov si,[MIDI_LOOPSTART_POINTER] ; Restart from beginning
  327. 00000510  E9FEFE            jmp LoadNextCommand
  328.  
  329. HANDLE_90_NOTEON
  330. 00000513  268A5C01          mov bl,[es:si+0x1]
  331. 00000517  80FB00            cmp bl,0x0          ; If the pressure is zero, treat as noteoff command
  332. 0000051A  7503              jnz 0x51f
  333. 0000051C  E9BD00            jmp HANDLE_80_NOTEOFF
  334. 0000051F  33FF              xor di,di
  335. 00000521  33C9              xor cx,cx
  336. 00000523  268A1C            mov bl,[es:si]
  337. 00000526  46                inc si
  338. 00000527  268A24            mov ah,[es:si]
  339. 0000052A  46                inc si
  340. 0000052B  A03103            mov al,[MIDI_CHANNEL_NUMBER]
  341. 0000052E  3C09              cmp al,0x9          ; MIDI channel 9 is handled as a percussion channel
  342. 00000530  7503              jnz NoteOnMelodic
  343. 00000532  E90401            jmp NoteOnPercussion
  344. NoteOnMelodic
  345. 00000535  3A85C002          cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  346. 00000539  752B              jnz 0x566
  347. 0000053B  80BDC90201        cmp byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  348. 00000540  7424              je 0x566
  349. 00000542  8BCF              mov cx,di           ; If there is an AdLib channel that is dedicated
  350. 00000544  57                push di             ; for this MIDI channel, but NOT playing anything,
  351. 00000545  C606360320         mov byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x20
  352. 0000054A  C685C90201         mov byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  353. 0000054F  889DD202           mov [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],bl
  354. 00000553  029DDB02           add bl,[di+ADLIB_CHANNEL_CURRENT_FINETUNE_LEVEL]
  355. 00000557  D0E3               shl bl,1           ; the use that channel and key-on the note.
  356. 00000559  32FF               xor bh,bh
  357. 0000055B  8B9F1400           mov bx,[bx+PITCH_TABLE]
  358. 0000055F  E80E01             call UPDATE_VOLUME_AND_PITCH
  359. 00000562  5F                pop di
  360. 00000563  E959FF            jmp LoadDelayValue  ; and that's it.
  361. 00000566  47                inc di
  362. 00000567  83FF09            cmp di,byte +0x9
  363. 0000056A  75C9              jnz NoteOnMelodic  
  364. 0000056C  53                push bx             ; No free channel was found.
  365. 0000056D  33FF               xor di,di          ; Otherwise find the oldest one of the AdLib channels
  366. 0000056F  33D2               xor dx,dx          ; dedicated for this MIDI channel -- i.e. one where
  367. 00000571  C7063703FFFF       mov word [OLDEST_CHANNEL_POINTER],0xffff
  368. 00000577  8BDF               mov bx,di          ; a note has been playing for the longest time
  369. 00000579  D1E3               shl bx,1
  370. 0000057B  3A85C002           cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  371. 0000057F  750E               jnz 0x58f                          ; Skip irrelevant channels
  372. 00000581  8B8F1A03           mov cx,[bx+ADLIB_CHANNEL_NOTE_AGE] ; Compare note age
  373. 00000585  3BD1               cmp dx,cx                          ; If older than what we currently have,
  374. 00000587  7306               jae 0x58f                          ; i.e. skip if saved >= this
  375. 00000589  8BD1               mov dx,cx
  376. 0000058B  893E3703           mov [OLDEST_CHANNEL_POINTER],di    ; save the channel age
  377. 0000058F  47                 inc di
  378. 00000590  83FF09             cmp di,byte +0x9
  379. 00000593  75E2               jnz 0x577
  380. 00000595  833E3703FF         cmp word [OLDEST_CHANNEL_POINTER],byte -0x1
  381. 0000059A  7504               jne 0x5a0                          ; Don't play if no channel was not found.
  382. 0000059C  5B                 pop bx                             ; This should be impossible to happen.
  383. 0000059D  E91FFF             jmp LoadDelayValue
  384. 000005A0  8B0E3703           mov cx,[OLDEST_CHANNEL_POINTER]    ; Take the channel that was found
  385. 000005A4  8BF9               mov di,cx                          ; Key it off first
  386. 000005A6  BB0000             mov bx,0x0
  387. 000005A9  C606360300         mov byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x0
  388. 000005AE  E8BF00             call UPDATE_VOLUME_AND_PITCH
  389. 000005B1  8BDF               mov bx,di                          ; Then, reset its age
  390. 000005B3  D1E3               shl bx,1
  391. 000005B5  C7871A030000       mov word [bx+ADLIB_CHANNEL_NOTE_AGE],0x0
  392. 000005BB  5B                pop bx                              ; And key it on.
  393. 000005BC  C606360320        mov byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x20
  394. 000005C1  C685C90201        mov byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  395. 000005C6  889DD202          mov [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],bl
  396. 000005CA  029DDB02          add bl,[di+ADLIB_CHANNEL_CURRENT_FINETUNE_LEVEL]
  397. 000005CE  D0E3              shl bl,1
  398. 000005D0  32FF              xor bh,bh
  399. 000005D2  8B9F1400          mov bx,[bx+PITCH_TABLE]
  400. 000005D6  E89700            call UPDATE_VOLUME_AND_PITCH        ; Done.
  401. 000005D9  E9E3FE            jmp LoadDelayValue
  402.  
  403. HANDLE_80_NOTEOFF
  404. 000005DC  33FF              xor di,di
  405. 000005DE  33C9              xor cx,cx
  406. 000005E0  268A1C            mov bl,[es:si]                      
  407. 000005E3  46                inc si
  408. 000005E4  46                inc si
  409. 000005E5  A03103            mov al,[MIDI_CHANNEL_NUMBER]        ; Find an AdLib channel
  410. 000005E8  3A85C002          cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  411. 000005EC  7542              jnz 0x630                           ; that is dedicated for this MIDI channel
  412. 000005EE  389DD202          cmp [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],bl
  413. 000005F2  753C              jnz 0x630                           ; and is currently playing this note
  414. 000005F4  8BCF              mov cx,di
  415. 000005F6  57                push di                             ; Key it off
  416. 000005F7  C606360300        mov byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x0
  417. 000005FC  C685C90200        mov byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x0
  418. 00000601  3C09              cmp al,0x9                          ; Choose the notenumber depending
  419. 00000603  7507              jnz NoteOffMelodic                  ; on whether it's melodic or percussion
  420. NoteOffPercussion
  421. 00000605  8A9DED02          mov bl,[di+ADLIB_CHANNEL_PLAYING_THIS_ACTUAL_NOTENUMBER_FOR_PERCUSSION]
  422. 00000609  EB0590            jmp NoteOffContinued
  423. NoteOffMelodic
  424. 0000060C  8A9DD202          mov bl,[di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER]
  425. NoteOffContinued
  426. 00000610  C685D20200        mov byte [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],0x0
  427. 00000615  029DDB02          add bl,[di+ADLIB_CHANNEL_CURRENT_FINETUNE_LEVEL]
  428. 00000619  D0E3              shl bl,1
  429. 0000061B  32FF              xor bh,bh
  430. 0000061D  8B9F1400          mov bx,[bx+PITCH_TABLE]             ; And key it off.
  431. 00000621  D1E7              shl di,1
  432. 00000623  C7851A030000      mov word [di+ADLIB_CHANNEL_NOTE_AGE],0x0
  433. 00000629  E84400            call UPDATE_VOLUME_AND_PITCH
  434. 0000062C  5F                pop di
  435. 0000062D  E98FFE            jmp LoadDelayValue                  ; Key-off completed, done.
  436. 00000630  47                inc di
  437. 00000631  83FF09            cmp di,byte +0x9                    ; Haven't found a note yet,
  438. 00000634  75B2              jnz 0x5e8                           ; so loop for 9 AdLib channels.
  439. 00000636  E986FE            jmp LoadDelayValue                  ; Didn't find note, done.
  440.  
  441. NoteOnPercussion
  442. 00000639  3A85C002          cmp al,[di+ADLIB_CHANNEL_IS_PLAYING_THIS_MIDI_CHANNEL]
  443. 0000063D  7528              jnz 0x667                           ; For percussion, the process is same as for melodic
  444. 0000063F  3A9DE402          cmp bl,[di+ADLIB_CHANNEL_PLAYING_THIS_MIDI_PERCUSSION_NOTENUMBER]
  445. 00000643  7522              jnz 0x667                           ; except notenumber is handled from a different table.
  446. 00000645  8BCF              mov cx,di
  447. 00000647  C606360320        mov byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x20
  448. 0000064C  C685C90201        mov byte [di+ADLIB_CHANNEL_CURRENTLY_KEYED_ON],0x1
  449. 00000651  889DD202          mov [di+ADLIB_CHANNEL_KEYED_ON_NOTENUMBER],bl
  450. 00000655  8A9DED02          mov bl,[di+ADLIB_CHANNEL_PLAYING_THIS_ACTUAL_NOTENUMBER_FOR_PERCUSSION]
  451. 00000659  D0E3              shl bl,1
  452. 0000065B  32FF              xor bh,bh
  453. 0000065D  8B9F1400          mov bx,[bx+PITCH_TABLE]
  454. 00000661  E80C00            call UPDATE_VOLUME_AND_PITCH
  455. 00000664  E958FE            jmp LoadDelayValue
  456. 00000667  47                inc di
  457. 00000668  83FF09            cmp di,byte +0x9                    ; Loop 9 AdLib channels.
  458. 0000066B  75CC              jnz 0x639
  459. 0000066D  E94FFE            jmp LoadDelayValue
  460.  
  461. UPDATE_VOLUME_AND_PITCH
  462. 00000670  56                push si
  463. 00000671  8BF1              mov si,cx
  464. 00000673  803E360300        cmp byte [FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0],0x0
  465. 00000678  741C              jz ChannelNotKeyedOnSkip
  466. 0000067A  BA8803            mov dx,0x388                        ; Only update volume if keyed on.
  467. 0000067D  8A84B702          mov al,[si+CARRIER_REGISTER_INDEX_TABLE]
  468. 00000681  0440              add al,0x40
  469. 00000683  EE                out dx,al
  470. 00000684  E89301            call word DELAY_12
  471. 00000687  42                inc dx
  472. 00000688  8A84FF02          mov al,[si+ADLIB_CHANNEL_REGISTER_43_VALUE]
  473. 0000068C  D0EC              shr ah,1                            ; Carrier port 40 (43)
  474. 0000068E  D0EC              shr ah,1                            ; is written with
  475. 00000690  2AC4              sub al,ah                           ; value - volume/4.
  476. 00000692  EE                out dx,al
  477. 00000693  E86601            call DELAY_32
  478. ChannelNotKeyedOnSkip
  479. 00000696  BA8803            mov dx,0x388                        ; Poke the frequency value (bx)
  480. 00000699  B0A0              mov al,0xa0                         ; into A0 and B0.
  481. 0000069B  02C1              add al,cl
  482. 0000069D  EE                out dx,al
  483. 0000069E  E87901            call word DELAY_12
  484. 000006A1  42                inc dx
  485. 000006A2  8AC3              mov al,bl
  486. 000006A4  EE                out dx,al                           ; Save into cached A0 register value.
  487. 000006A5  88840803          mov [si+ADLIB_CHANNEL_REG_A0_PITCH_LOW_8_BITS],al
  488. 000006A9  E85001            call DELAY_32
  489. 000006AC  BA8803            mov dx,0x388
  490. 000006AF  B0B0              mov al,0xb0
  491. 000006B1  02C1              add al,cl
  492. 000006B3  EE                out dx,al
  493. 000006B4  E86301            call word DELAY_12
  494. 000006B7  42                inc dx
  495. 000006B8  8AC7              mov al,bh                           ; B0 keyon bits are loaded from different variable.
  496. 000006BA  0A063603          or al,[FUNCTION_PARAMETER_KEYON_BITS_FOR_REG_B0]
  497. 000006BE  EE                out dx,al                           ; Save into cached B0 register value.
  498. 000006BF  88841103          mov [si+ADLIB_CHANNEL_REG_B0_PITCH_HIGH_2_BITS_AND_KEYON_BITS],al
  499. 000006C3  E85401            call word DELAY_12
  500. 000006C6  5E                pop si
  501. 000006C7  C3                ret
  502.  
  503. RECALCULATE_PITCH_AND_WRITE
  504. 000006C8  50                push ax
  505. 000006C9  8A850803          mov al,[di+ADLIB_CHANNEL_REG_A0_PITCH_LOW_8_BITS]   ; Load the designated pitch
  506. 000006CD  8AA51103          mov ah,[di+ADLIB_CHANNEL_REG_B0_PITCH_HIGH_2_BITS_AND_KEYON_BITS]
  507. 000006D1  8ADC              mov bl,ah
  508. 000006D3  80E3FC            and bl,0xfc                                
  509. 000006D6  881E3B03          mov [TEMPORARY],bl                          ; Save the keyon bits
  510. 000006DA  80E403            and ah,0x3                                  ; Pitch is 10 bits.
  511. 000006DD  8B163903          mov dx,[FUNCTION_PARAMETER_PITCH_BEND_VALUE]; Multiply by pitch-bend
  512. 000006E1  F7E2              mul dx
  513. 000006E3  8AC4              mov al,ah                                   ; Divide by 1024
  514. 000006E5  8AE2              mov ah,dl
  515. 000006E7  8AD6              mov dl,dh
  516. 000006E9  51                push cx
  517. 000006EA  B90500             mov cx,0x5
  518. 000006ED  D0EA               shr dl,1
  519. 000006EF  D1D8               rcr ax,1
  520. 000006F1  E2FA               loop 0x6ed
  521. 000006F3  59                pop cx                                      ; Done dividing
  522. 000006F4  8BD8              mov bx,ax                                   ; Save the pitch into bx
  523. 000006F6  BA8803            mov dx,0x388
  524. 000006F9  B0A0              mov al,0xa0                                 ; Write the low 8 bits into register A0
  525. 000006FB  02C1              add al,cl
  526. 000006FD  EE                out dx,al
  527. 000006FE  E81901            call word DELAY_12
  528. 00000701  42                inc dx
  529. 00000702  8AC3              mov al,bl
  530. 00000704  EE                out dx,al
  531. 00000705  E8F400            call DELAY_32
  532. 00000708  BA8803            mov dx,0x388                                ; Write the high 8 bits into register B0
  533. 0000070B  B0B0              mov al,0xb0
  534. 0000070D  02C1              add al,cl
  535. 0000070F  EE                out dx,al
  536. 00000710  E80701            call word DELAY_12
  537. 00000713  42                inc dx
  538. 00000714  8AC7              mov al,bh
  539. 00000716  0A063B03          or al,[TEMPORARY]                           ; Add the keyon bits, too.
  540. 0000071A  EE                out dx,al
  541. 0000071B  E8FC00            call word DELAY_12
  542. 0000071E  58                pop ax
  543. 0000071F  C3                ret
  544.  
  545. PROGRAM_PATCH:
  546. 00000720  32FF              xor bh,bh
  547. 00000722  8BFB              mov di,bx
  548. 00000724  8A9D5001          mov bl,[di+PATCH_NUMBER_MAPPING_TO_INSTRUMENT_NUMBERS]
  549. 00000728  D0E3              shl bl,1
  550. 0000072A  8BFB              mov di,bx
  551. 0000072C  8BBD8701          mov di,[di+INSTRUMENT_POINTERS]
  552. 00000730  56                push si
  553. 00000731  8BF1              mov si,cx
  554. 00000733  BA8803            mov dx,0x388
  555. 00000736  8A84AE02          mov al,[si+MODULATOR_REGISTER_INDEX_TABLE]
  556. 0000073A  0420              add al,0x20
  557. 0000073C  EE                out dx,al
  558. 0000073D  E8DA00            call word DELAY_12
  559. 00000740  42                inc dx
  560. 00000741  8A05              mov al,[di]                                 Byte 0: register 0x20
  561. 00000743  EE                out dx,al
  562. 00000744  E8B500            call DELAY_32
  563. 00000747  BA8803            mov dx,0x388
  564. 0000074A  8A84AE02          mov al,[si+MODULATOR_REGISTER_INDEX_TABLE]
  565. 0000074E  0440              add al,0x40
  566. 00000750  EE                out dx,al
  567. 00000751  E8C600            call word DELAY_12
  568. 00000754  42                inc dx
  569. 00000755  47                inc di
  570. 00000756  8A05              mov al,[di]                                 Byte 1: register 0x40
  571. 00000758  EE                out dx,al
  572. 00000759  E8A000            call DELAY_32
  573. 0000075C  BA8803            mov dx,0x388
  574. 0000075F  8A84AE02          mov al,[si+MODULATOR_REGISTER_INDEX_TABLE]
  575. 00000763  0460              add al,0x60
  576. 00000765  EE                out dx,al
  577. 00000766  E8B100            call word DELAY_12
  578. 00000769  42                inc dx
  579. 0000076A  47                inc di
  580. 0000076B  8A05              mov al,[di]                                 Byte 2: register 0x60
  581. 0000076D  EE                out dx,al
  582. 0000076E  E88B00            call DELAY_32
  583. 00000771  BA8803            mov dx,0x388
  584. 00000774  8A84AE02          mov al,[si+MODULATOR_REGISTER_INDEX_TABLE]
  585. 00000778  0480              add al,0x80
  586. 0000077A  EE                out dx,al
  587. 0000077B  E89C00            call word DELAY_12
  588. 0000077E  42                inc dx
  589. 0000077F  47                inc di
  590. 00000780  8A05              mov al,[di]                                 Byte 3: register 0x80
  591. 00000782  EE                out dx,al
  592. 00000783  E87600            call DELAY_32
  593. 00000786  BA8803            mov dx,0x388
  594. 00000789  8A84B702          mov al,[si+CARRIER_REGISTER_INDEX_TABLE]
  595. 0000078D  0420              add al,0x20
  596. 0000078F  EE                out dx,al
  597. 00000790  E88700            call word DELAY_12
  598. 00000793  42                inc dx
  599. 00000794  47                inc di
  600. 00000795  8A05              mov al,[di]                                 Byte 4: register 0x23
  601. 00000797  EE                out dx,al
  602. 00000798  E86100            call DELAY_32
  603. 0000079B  BA8803            mov dx,0x388
  604. 0000079E  8A84B702          mov al,[si+CARRIER_REGISTER_INDEX_TABLE]
  605. 000007A2  0440              add al,0x40
  606. 000007A4  EE                out dx,al
  607. 000007A5  E87200            call word DELAY_12
  608. 000007A8  42                inc dx
  609. 000007A9  47                inc di
  610. 000007AA  8A05              mov al,[di]                                 Byte 5: register 0x43
  611. 000007AC  8884FF02          mov [si+ADLIB_CHANNEL_REGISTER_43_VALUE],al         Saved also here
  612. 000007B0  EE                out dx,al
  613. 000007B1  E84800            call DELAY_32
  614. 000007B4  BA8803            mov dx,0x388
  615. 000007B7  8A84B702          mov al,[si+CARRIER_REGISTER_INDEX_TABLE]
  616. 000007BB  0460              add al,0x60
  617. 000007BD  EE                out dx,al
  618. 000007BE  E85900            call word DELAY_12
  619. 000007C1  42                inc dx
  620. 000007C2  47                inc di
  621. 000007C3  8A05              mov al,[di]                                 Byte 6: register 0x63
  622. 000007C5  EE                out dx,al
  623. 000007C6  E83300            call DELAY_32
  624. 000007C9  BA8803            mov dx,0x388
  625. 000007CC  8A84B702          mov al,[si+CARRIER_REGISTER_INDEX_TABLE]
  626. 000007D0  0480              add al,0x80
  627. 000007D2  EE                out dx,al
  628. 000007D3  E84400            call word DELAY_12
  629. 000007D6  42                inc dx
  630. 000007D7  47                inc di
  631. 000007D8  8A05              mov al,[di]                                 Byte 7: register 0x83
  632. 000007DA  EE                out dx,al
  633. 000007DB  E81E00            call DELAY_32
  634. 000007DE  BA8803            mov dx,0x388
  635. 000007E1  B0C0              mov al,0xc0
  636. 000007E3  02C1              add al,cl
  637. 000007E5  EE                out dx,al
  638. 000007E6  E83100            call word DELAY_12
  639. 000007E9  42                inc dx
  640. 000007EA  47                inc di
  641. 000007EB  8A05              mov al,[di]                                 Byte 8: register 0xC0
  642. 000007ED  EE                out dx,al
  643. 000007EE  E80B00            call DELAY_32
  644. 000007F1  47                inc di
  645. 000007F2  8A05              mov al,[di]                                 Byte 9: finetune
  646. 000007F4  8BF9              mov di,cx
  647. 000007F6  8885DB02          mov [di+ADLIB_CHANNEL_CURRENT_FINETUNE_LEVEL],al    Saved here
  648. 000007FA  5E                pop si
  649. 000007FB  C3                ret
  650.  
  651. DELAY_32
  652. 000007FC  B020              mov al,0x20
  653. 000007FE  FEC8              dec al
  654. 00000800  90                nop
  655. 00000801  75FB              jnz 0x7fe
  656. 00000803  C3                ret
  657.  
  658. NEXT_RANDOM
  659. 00000804  52                push dx
  660. 00000805  A14E01            mov ax,[LSFR_VALUE]
  661. 00000808  D1E8              shr ax,1
  662. 0000080A  7303              jnc 0x80f
  663. 0000080C  80F4B4            xor ah,0xb4
  664. 0000080F  A34E01            mov [LSFR_VALUE],ax
  665. 00000812  33D2              xor dx,dx
  666. 00000814  F7F1              div cx
  667. 00000816  8BCA              mov cx,dx
  668. 00000818  5A                pop dx
  669. 00000819  C3                ret
  670.  
  671. DELAY_12
  672. 0000081A  B00C              mov al,0xc
  673. 0000081C  FEC8              dec al
  674. 0000081E  90                nop
  675. 0000081F  75FB              jnz 0x81c
  676. 00000821  C3                ret
  677.  
  678. RESET_ADLIB
  679. 00000822  BE6500            mov si,0x65
  680. 00000825  8A84D600          mov al,[si+LIST_OF_INITIAL_00_REGISTERS]
  681. 00000829  BA8803            mov dx,0x388
  682. 0000082C  EE                out dx,al
  683. 0000082D  E8CCFF            call DELAY_32
  684. 00000830  B000              mov al,0x0
  685. 00000832  42                inc dx
  686. 00000833  EE                out dx,al
  687. 00000834  E8C5FF            call DELAY_32
  688. 00000837  4E                dec si
  689. 00000838  79EB              jns 0x825
  690. 0000083A  BE1100            mov si,0x11
  691. 0000083D  8A843C01          mov al,[si+LIST_OF_INITIAL_3F_REGISTERS]
  692. 00000841  BA8803            mov dx,0x388
  693. 00000844  EE                out dx,al
  694. 00000845  E8B4FF            call DELAY_32
  695. 00000848  B03F              mov al,0x3f
  696. 0000084A  42                inc dx
  697. 0000084B  EE                out dx,al
  698. 0000084C  E8ADFF            call DELAY_32
  699. 0000084F  4E                dec si
  700. 00000850  79EB              jns 0x83d
  701. 00000852  C3                ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement