lol its in c
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1729 lines
33 KiB

2 years ago
  1. include "hardware.inc"
  2. include "huge.inc"
  3. add_a_to_r16: MACRO
  4. add \2
  5. ld \2, a
  6. adc \1
  7. sub \2
  8. ld \1, a
  9. ENDM
  10. add_a_to_hl: MACRO
  11. add_a_to_r16 h, l
  12. ENDM
  13. add_a_to_de: MACRO
  14. add_a_to_r16 d, e
  15. ENDM
  16. ret_dont_call_playnote: MACRO
  17. pop hl
  18. pop af
  19. and a ; Clear carry to avoid calling `play_chX_note`
  20. push af
  21. jp hl
  22. ENDM
  23. add_a_ind_ret_hl: MACRO
  24. ld hl, \1
  25. add [hl]
  26. inc hl
  27. ld h, [hl]
  28. ld l, a
  29. adc h
  30. sub l
  31. ld h, a
  32. ENDM
  33. load_hl_ind: MACRO
  34. ld hl, \1
  35. ld a, [hl+]
  36. ld h, [hl]
  37. ld l, a
  38. ENDM
  39. load_de_ind: MACRO
  40. ld a, [\1]
  41. ld e, a
  42. ld a, [\1+1]
  43. ld d, a
  44. ENDM
  45. retMute: MACRO
  46. bit \1, a
  47. ret nz
  48. ENDM
  49. checkMute: MACRO
  50. ld a, [mute_channels]
  51. bit \1, a
  52. jr nz, \2
  53. ENDM
  54. ;; Maximum pattern length
  55. PATTERN_LENGTH EQU 64
  56. ;; Amount to be shifted in order to skip a channel.
  57. CHANNEL_SIZE_EXPONENT EQU 3
  58. SECTION "Playback variables", WRAM0
  59. ;; Active song descriptor
  60. order_cnt: db
  61. _start_song_descriptor_pointers:
  62. ;; Pointers to the song's current four orders (one per channel)
  63. order1: dw
  64. order2: dw
  65. order3: dw
  66. order4: dw
  67. ;; Pointers to the instrument tables
  68. duty_instruments: dw
  69. wave_instruments: dw
  70. noise_instruments: dw
  71. ;; Misc. pointers
  72. routines: dw
  73. waves: dw
  74. _end_song_descriptor_pointers:
  75. ;; Pointers to the current patterns (sort of a cache)
  76. pattern1: dw
  77. pattern2: dw
  78. pattern3: dw
  79. pattern4: dw
  80. ;; How long a row lasts in ticks (1 = one row per call to `hUGE_dosound`, etc. 0 translates to 256)
  81. ticks_per_row: db
  82. _hUGE_current_wave::
  83. hUGE_current_wave::
  84. ;; ID of the wave currently loaded into wave RAM
  85. current_wave: db
  86. hUGE_NO_WAVE equ 100
  87. EXPORT hUGE_NO_WAVE
  88. ;; Everything between this and `end_zero` is zero-initialized by `hUGE_init`
  89. start_zero:
  90. mute_channels: db
  91. current_order: db
  92. next_order: db
  93. row_break: db
  94. temp_note_value: dw
  95. row: db
  96. tick: db
  97. counter: db
  98. channels:
  99. ;;;;;;;;;;;
  100. ;;Channel 1
  101. ;;;;;;;;;;;
  102. channel1:
  103. channel_period1: dw
  104. toneporta_target1: dw
  105. channel_note1: db
  106. vibrato_tremolo_phase1: db
  107. envelope1: db
  108. highmask1: db
  109. ;;;;;;;;;;;
  110. ;;Channel 2
  111. ;;;;;;;;;;;
  112. channel2:
  113. channel_period2: dw
  114. toneporta_target2: dw
  115. channel_note2: db
  116. vibrato_tremolo_phase2: db
  117. envelope2: db
  118. highmask2: db
  119. ;;;;;;;;;;;
  120. ;;Channel 3
  121. ;;;;;;;;;;;
  122. channel3:
  123. channel_period3: dw
  124. toneporta_target3: dw
  125. channel_note3: db
  126. vibrato_tremolo_phase3: db
  127. envelope3: db
  128. highmask3: db
  129. ;;;;;;;;;;;
  130. ;;Channel 4
  131. ;;;;;;;;;;;
  132. channel4:
  133. channel_period4: dw
  134. toneporta_target4: dw
  135. channel_note4: db
  136. vibrato_tremolo_phase4: db
  137. envelope4: db
  138. highmask4: db
  139. end_zero:
  140. SECTION "Sound Driver", ROM0
  141. ;;; Sets up hUGEDriver to play a song.
  142. ;;; !!! BE SURE THAT `hUGE_dosound` WILL NOT BE CALLED WHILE THIS RUNS !!!
  143. ;;; Param: HL = Pointer to the "song descriptor" you wish to load (typically exported by hUGETracker).
  144. ;;; Destroys: AF C DE HL
  145. _hUGE_init::
  146. hUGE_init::
  147. ld a, [hl+] ; tempo
  148. ld [ticks_per_row], a
  149. ld a, [hl+]
  150. ld e, a
  151. ld a, [hl+]
  152. ld d, a
  153. ld a, [de]
  154. ld [order_cnt], a
  155. ld c, _end_song_descriptor_pointers - (_start_song_descriptor_pointers)
  156. ld de, order1
  157. .copy_song_descriptor_loop:
  158. ld a, [hl+]
  159. ld [de], a
  160. inc de
  161. dec c
  162. jr nz, .copy_song_descriptor_loop
  163. IF !DEF(PREVIEW_MODE)
  164. ;; Zero some ram
  165. ld c, end_zero - start_zero
  166. ld hl, start_zero
  167. xor a
  168. .fill_loop:
  169. ld [hl+], a
  170. dec c
  171. jr nz, .fill_loop
  172. ENDC
  173. ;; These two are zero-initialized by the loop above, so these two writes must come after
  174. ld a, %11110000
  175. ld [envelope1], a
  176. ld [envelope2], a
  177. ;; Force loading the next wave
  178. ld a, hUGE_NO_WAVE
  179. ld [current_wave], a
  180. ;; Preview mode needs to load the order ID from memory
  181. IF !DEF(PREVIEW_MODE)
  182. ld c, 0
  183. ELSE
  184. ld a, [current_order]
  185. ld c, a
  186. ENDC
  187. ;; fallthrough (load the pattern pointers)
  188. ;;; Sets all 4 pattern pointers from a certain index in the respective 4 orders.
  189. ;;; Param: C = The index (in increments of 2)
  190. ;;; Destroy: AF DE HL
  191. load_patterns:
  192. IF DEF(PREVIEW_MODE)
  193. db $fc ; signal order update to tracker
  194. ENDC
  195. ld hl, order1
  196. ld de, pattern1
  197. call .load_pattern
  198. ld hl, order2
  199. call .load_pattern
  200. ld hl, order3
  201. call .load_pattern
  202. ld hl, order4
  203. ;; fallthrough
  204. .load_pattern:
  205. ld a, [hl+]
  206. add c
  207. ld h, [hl]
  208. ld l, a
  209. adc h
  210. sub l
  211. ld h, a
  212. ld a, [hl+]
  213. ld [de], a
  214. inc de
  215. ld a, [hl]
  216. ld [de], a
  217. inc de
  218. ret
  219. ;;; Sets a channel's muting status.
  220. ;;; Muted channels are left entirely alone by the driver, so that you can repurpose them,
  221. ;;; for example for sound effects, CH3 sample playback, etc.
  222. ;;; If muting the channel, the note being played will be cut.
  223. ;;; Param: B = Which channel to enable; 0 for CH1, 1 for CH2, etc.
  224. ;;; Param: C = 0 to unmute the channel, 1 to mute it
  225. ;;; Destroy: A C E HL
  226. hUGE_mute_channel::
  227. ld e, $fe
  228. ld a, b
  229. or a
  230. jr z, .enable_cut
  231. .enable_loop:
  232. sla c
  233. rlc e
  234. dec a
  235. jr nz, .enable_loop
  236. .enable_cut:
  237. ld a, [mute_channels]
  238. and e
  239. or c
  240. ld [mute_channels], a
  241. and c
  242. jp nz, note_cut
  243. ret
  244. ;;; Reads a pattern's current row.
  245. ;;; Param: BC = Pointer to the pattern
  246. ;;; Param: [row] = Index of the current ro<
  247. ;;; Return: A = Note ID
  248. ;;; Return: B = Instrument (upper nibble) & effect code (lower nibble)
  249. ;;; Return: C = Effect parameter
  250. ;;; Destroy: HL
  251. get_current_row:
  252. ld a, [row]
  253. ld h, a
  254. ;; Multiply by 3 for the note value
  255. add h
  256. add h
  257. ld h, 0
  258. ld l, a
  259. add hl, bc ; HL now points at the 3rd byte of the note
  260. ld a, [hl+]
  261. ld b, [hl]
  262. inc hl
  263. ld c, [hl]
  264. ret
  265. ;;; Gets the "period" of a pattern's current note.
  266. ;;; Param: HL = Pointer to the pattern pointer
  267. ;;; Param: [row] = Index of the current row
  268. ;;; Param: DE = Location to write the note's index to, if applicable
  269. ;;; Return: HL = Note's period
  270. ;;; Return: CF = Set if and only if a "valid" note (i.e. not a "rest")
  271. ;;; Return: [DE] = Note's ID, not updated if a "rest"
  272. ;;; Return: B = Instrument (upper nibble) & effect code (lower nibble)
  273. ;;; Return: C = Effect parameter
  274. ;;; Destroy: AF
  275. get_current_note:
  276. ld a, [hl+]
  277. ld c, a
  278. ld b, [hl]
  279. call get_current_row
  280. ld hl, 0
  281. ;; If the note we found is greater than LAST_NOTE, then it's not a valid note
  282. ;; and nothing needs to be updated.
  283. cp LAST_NOTE
  284. ret nc
  285. ;; Store the loaded note value in channel_noteX
  286. ld [de], a
  287. ;;; Gets a note's "period", i.e. what should be written to NRx3 and NRx4.
  288. ;;; Param: A = Note ID
  289. ;;; Return: HL = Note's period
  290. ;;; Return: CF = 1
  291. ;;; Destroy: AF
  292. get_note_period:
  293. add a ;; double it to get index into hi/lo table
  294. add LOW(note_table)
  295. ld l, a
  296. adc HIGH(note_table)
  297. sub l
  298. ld h, a
  299. ld a, [hl+]
  300. ld h, [hl]
  301. ld l, a
  302. scf
  303. ret
  304. ;;; Gets a note's "polynomial counter", i.e. what should be written to NR44.
  305. ;;; Param: A = Note ID
  306. ;;; Return: A = Note's poly
  307. ;;; Destroy: F HL
  308. get_note_poly:
  309. ;; Invert the order of the numbers
  310. add 192 ; (255 - 63)
  311. cpl
  312. ;; Thanks to RichardULZ for this formula
  313. ;; https://docs.google.com/spreadsheets/d/1O9OTAHgLk1SUt972w88uVHp44w7HKEbS/edit#gid=75028951
  314. ; if A > 7 then begin
  315. ; B := (A-4) div 4;
  316. ; C := (A mod 4)+4;
  317. ; A := (C or (B shl 4))
  318. ; end;
  319. ; if A < 7 then return
  320. cp 7
  321. ret c
  322. ld h, a
  323. ; B := (A-4) div 4;
  324. sub 4
  325. srl a
  326. srl a
  327. ld l, a
  328. ; C := (A mod 4)+4;
  329. ld a, h
  330. and 3 ; mod 4
  331. add 4
  332. ; A := (C or (B shl 4))
  333. swap l
  334. or l
  335. ret
  336. ;;; Computes the pointer to a member of a channel.
  337. ;;; Param: B = Which channel (0 = CH1, 1 = CH2, etc.)
  338. ;;; Param: D = Offset within the channel struct
  339. ;;; Return: HL = Pointer to the channel's member
  340. ;;; Destroy: AF
  341. ptr_to_channel_member:
  342. ld a, b
  343. REPT CHANNEL_SIZE_EXPONENT
  344. add a
  345. ENDR
  346. add d
  347. ld hl, channels
  348. add LOW(channels)
  349. ld l, a
  350. adc HIGH(channels)
  351. sub l
  352. ld h, a
  353. ret
  354. ;;; Updates a channel's frequency, and possibly restarts it.
  355. ;;; Note that CH4 is *never* restarted by this!
  356. ;;; Param: B = Which channel to update (0 = CH1, 1 = CH2, etc.)
  357. ;;; Param: (ignored for CH4) A = ORed to the value written to NRx4
  358. ;;; Param: (for CH4) E = Note ID
  359. ;;; Param: (otherwise) DE = Note period
  360. ;;; Destroy: AF B
  361. ;;; Destroy: (for CH4) HL
  362. update_channel_freq:
  363. ld c, a
  364. ld a, [mute_channels]
  365. dec b
  366. jr z, .update_channel2
  367. dec b
  368. jr z, .update_channel3
  369. dec b
  370. jr z, .update_channel4
  371. .update_channel1:
  372. retMute 0
  373. ld a, e
  374. ldh [rAUD1LOW], a
  375. ld a, d
  376. or c
  377. ldh [rAUD1HIGH], a
  378. ret
  379. .update_channel2:
  380. retMute 1
  381. ld a, e
  382. ldh [rAUD2LOW], a
  383. ld a, d
  384. or c
  385. ldh [rAUD2HIGH], a
  386. ret
  387. .update_channel3:
  388. retMute 2
  389. ld a, e
  390. ldh [rAUD3LOW], a
  391. ld a, d
  392. or c
  393. ldh [rAUD3HIGH], a
  394. ret
  395. .update_channel4:
  396. retMute 3
  397. ld a, e
  398. call get_note_poly
  399. ldh [rAUD4POLY], a
  400. xor a
  401. ldh [rAUD4GO], a
  402. ret
  403. play_note_routines:
  404. jr play_ch1_note
  405. jr play_ch2_note
  406. jr play_ch3_note
  407. jr play_ch4_note
  408. play_ch1_note:
  409. ld a, [mute_channels]
  410. retMute 0
  411. ;; Play a note on channel 1 (square wave)
  412. ld a, [temp_note_value]
  413. ld [channel_period1], a
  414. ldh [rAUD1LOW], a
  415. ld a, [temp_note_value+1]
  416. ld [channel_period1+1], a
  417. ;; Get the highmask and apply it.
  418. ld hl, highmask1
  419. or [hl]
  420. ldh [rAUD1HIGH], a
  421. ret
  422. play_ch2_note:
  423. ld a, [mute_channels]
  424. retMute 1
  425. ;; Play a note on channel 2 (square wave)
  426. ld a, [temp_note_value]
  427. ld [channel_period2], a
  428. ldh [rAUD2LOW], a
  429. ld a, [temp_note_value+1]
  430. ld [channel_period2+1], a
  431. ;; Get the highmask and apply it.
  432. ld hl, highmask2
  433. or [hl]
  434. ldh [rAUD2HIGH], a
  435. ret
  436. play_ch3_note:
  437. ld a, [mute_channels]
  438. retMute 2
  439. ;; Triggering CH3 while it's reading a byte corrupts wave RAM.
  440. ;; To avoid this, we kill the wave channel (0 → NR30), then re-enable it.
  441. ;; This way, CH3 will be paused when we trigger it by writing to NR34.
  442. ;; TODO: what if `highmask3` bit 7 is not set, though?
  443. xor a
  444. ldh [rAUD3ENA], a
  445. cpl
  446. ldh [rAUD3ENA], a
  447. ;; Play a note on channel 3 (waveform)
  448. ld a, [temp_note_value]
  449. ld [channel_period3], a
  450. ldh [rAUD3LOW], a
  451. ld a, [temp_note_value+1]
  452. ld [channel_period3+1], a
  453. ;; Get the highmask and apply it.
  454. ld hl, highmask3
  455. or [hl]
  456. ldh [rAUD3HIGH], a
  457. ret
  458. play_ch4_note:
  459. ld a, [mute_channels]
  460. retMute 3
  461. ;; Play a "note" on channel 4 (noise)
  462. ld a, [temp_note_value]
  463. ld [channel_period4+1], a
  464. ldh [rAUD4POLY], a
  465. ;; Get the highmask and apply it.
  466. ld a, [highmask4]
  467. ldh [rAUD4GO], a
  468. ret
  469. ;;; Performs an effect on a given channel.
  470. ;;; Param: E = Channel ID (0 = CH1, 1 = CH2, etc.)
  471. ;;; Param: B = Effect type (upper 4 bits ignored)
  472. ;;; Param: C = Effect parameters (depend on FX type)
  473. ;;; Destroy: AF BC DE HL
  474. do_effect:
  475. ;; Strip the instrument bits off leaving only effect code
  476. ld a, b
  477. and %00001111
  478. ;; Multiply by 2 to get offset into table
  479. add a
  480. add LOW(.jump)
  481. ld l, a
  482. adc HIGH(.jump)
  483. sub l
  484. ld h, a
  485. ld a, [hl+]
  486. ld h, [hl]
  487. ld l, a
  488. ld b, e
  489. ld a, [tick]
  490. or a ; We can return right off the bat if it's tick zero
  491. jp hl
  492. .jump:
  493. ;; Jump table for effect
  494. dw fx_arpeggio ;0xy
  495. dw fx_porta_up ;1xy
  496. dw fx_porta_down ;2xy
  497. dw fx_toneporta ;3xy
  498. dw fx_vibrato ;4xy
  499. dw fx_set_master_volume ;5xy ; global
  500. dw fx_call_routine ;6xy
  501. dw fx_note_delay ;7xy
  502. dw fx_set_pan ;8xy ; global
  503. dw fx_set_duty ;9xy
  504. dw fx_vol_slide ;Axy
  505. dw fx_pos_jump ;Bxy ; global
  506. dw fx_set_volume ;Cxy
  507. dw fx_pattern_break ;Dxy ; global
  508. dw fx_note_cut ;Exy
  509. dw fx_set_speed ;Fxy ; global
  510. ;;; Processes (global) effect 5, "set master volume".
  511. ;;; Param: C = Value to write to NR50
  512. ;;; Param: ZF = Set if and only if on tick 0
  513. ;;; Destroy: A
  514. fx_set_master_volume:
  515. ret nz
  516. ld a, c
  517. ldh [rAUDVOL], a
  518. ret
  519. ;;; Processes effect 6, "call routine".
  520. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  521. ;;; Param: C = Routine ID
  522. ;;; Param: A = Current tick
  523. ;;; Param: ZF = Set if and only if on tick 0
  524. ;;; Destroy: Anything the routine does
  525. fx_call_routine:
  526. sla c
  527. ld a, [routines]
  528. add c
  529. ld l, a
  530. ld a, [routines+1]
  531. adc 0
  532. ld h, a
  533. ld a, [hl+]
  534. ld h, [hl]
  535. ld l, a
  536. ld a, [tick]
  537. or a ; set zero flag if tick 0 for compatibility
  538. IF DEF(GBDK) ; Pass the tick counter as a SDCC call parameter
  539. push af
  540. inc sp
  541. push bc
  542. call .call_hl
  543. add sp, 3
  544. ret
  545. .call_hl:
  546. ENDC
  547. jp hl
  548. ;;; Processes (global) effect 8, "set pan".
  549. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  550. ;;; Param: C = Value to write to NR51
  551. ;;; Param: ZF = Set if and only if on tick 0
  552. ;;; Destroy: A
  553. fx_set_pan:
  554. ret nz
  555. ;; Pretty simple. The editor can create the correct value here without a bunch
  556. ;; of bit shifting manually.
  557. ld a, c
  558. ldh [rAUDTERM], a
  559. ret
  560. ;;; Processes effect 9, "set duty cycle".
  561. ;;; Param: B = Current channel ID (0 = CH1, anything else = CH2)
  562. ;;; Param: C = Value to write to NRx1
  563. ;;; Param: ZF = Set if and only if on tick 0
  564. ;;; Destroy: AF
  565. fx_set_duty:
  566. ret nz
  567. ;; $900 = 12.5%
  568. ;; $940 = 25%
  569. ;; $980 = 50%
  570. ;; $9C0 = 75%
  571. ld a, b
  572. or a
  573. ld a, [mute_channels]
  574. jr z, .chan1
  575. .chan2:
  576. retMute 1
  577. ld a, c
  578. ldh [rAUD2LEN], a
  579. ret
  580. .chan1:
  581. retMute 0
  582. ld a, c
  583. ldh [rAUD1LEN], a
  584. ret
  585. ;;; Processes effect A, "volume slide".
  586. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  587. ;;; Param: C = FX param; either nibble should be 0, otherwise weird (unspecified) behavior may arise
  588. ;;; Param: ZF = Set if and only if on tick 0
  589. ;;; Destroy: AF C DE HL
  590. fx_vol_slide:
  591. ret nz
  592. ;; This is really more of a "retrigger note with lower volume" effect and thus
  593. ;; isn't really that useful. Instrument envelopes should be used instead.
  594. ;; Might replace this effect with something different if a new effect is
  595. ;; ever needed.
  596. ;; check channel mute
  597. ;; 0 → $01, 1 → $02, 2 → $04, 3 → $05
  598. ;; Overall, these two instructions add 1 to the number.
  599. ;; However, the first instruction will generate a carry for inputs of $02 and $03;
  600. ;; the `adc` will pick the carry up, and "separate" 0 / 1 from 2 / 3 by an extra 1.
  601. ;; Luckily, this yields correct results for 0 ($01), 1 ($02), and 2 ($03 + 1 = $04).
  602. ;; We'll see about fixing 3 afterwards.
  603. add -2
  604. adc 3
  605. ;; After being shifted left, the inputs are $02, $04, $08 and $0A; all are valid BCD,
  606. ;; except for $0A. Since we just performed `add a`, DAA will correct the latter to $10.
  607. ;; (This should be correctly emulated everywhere, since the inputs are identical to
  608. ;; "regular" BCD.)
  609. ;; When shifting the results back, we'll thus get $01, $02, $04 and $08!
  610. add a
  611. daa
  612. rra
  613. ld d, a
  614. ld a, [mute_channels]
  615. and d
  616. ret nz
  617. ;; setup the up and down params
  618. ld a, c
  619. and %00001111
  620. ld d, a
  621. ld a, c
  622. and %11110000
  623. ld e, a
  624. swap e
  625. ; There are 5 bytes between each envelope register
  626. ld a, b
  627. add a
  628. add a
  629. add b
  630. add LOW(rAUD1ENV)
  631. ld c, a
  632. ldh a, [c]
  633. and %11110000
  634. swap a
  635. sub d
  636. jr nc, .cont1
  637. xor a
  638. .cont1:
  639. add e
  640. cp $10
  641. jr c, .cont2
  642. ld a, $F
  643. .cont2:
  644. swap a
  645. ldh [c], a
  646. ; Go to rAUDxGO, which is 2 bytes after
  647. inc c
  648. inc c
  649. ldh a, [c]
  650. or %10000000
  651. ldh [c], a
  652. jr play_note
  653. ;;; Processes effect 7, "note delay".
  654. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  655. ;;; Param: C = Amount of ticks by which to delay the note
  656. ;;; Caveats: 0 never plays the note, and a delay longer than a row's duration skips the note entirely
  657. ;;; Param: ZF = Set if and only if on tick 0
  658. ;;; Destroy: AF D HL
  659. fx_note_delay:
  660. jr nz, .play_note
  661. ;; Just store the note into the channel period, and don't play a note.
  662. ld d, 0
  663. call ptr_to_channel_member
  664. ld a, [temp_note_value]
  665. ld [hl+], a
  666. ld a, [temp_note_value+1]
  667. ld [hl], a
  668. ;; Don't call _playnote. This is done by grabbing the return
  669. ;; address and manually skipping the next call instruction.
  670. ret_dont_call_playnote
  671. .play_note:
  672. cp c
  673. ret nz ; wait until the correct tick to play the note
  674. ;; fallthrough
  675. ;;; Plays a channel's current note.
  676. ;;; Param: B = Which channel (0 = CH1, 1 = CH2, etc.)
  677. ;;; Destroy: AF D HL
  678. play_note:
  679. ld d, 0
  680. call ptr_to_channel_member
  681. ;; TODO: Change this to accept HL instead?
  682. ld a, [hl+]
  683. ld [temp_note_value], a
  684. ld a, [hl]
  685. ld [temp_note_value+1], a
  686. ld a, b
  687. add a
  688. add LOW(play_note_routines)
  689. ld l, a
  690. adc HIGH(play_note_routines)
  691. sub l
  692. ld h, a
  693. jp hl
  694. ;;; Processes (global) effect F, "set speed".
  695. ;;; Param: C = New amount of ticks per row
  696. ;;; Param: ZF = Set if and only if on tick 0
  697. ;;; Destroy: A
  698. fx_set_speed:
  699. ret nz
  700. ld a, c
  701. ld [ticks_per_row], a
  702. ret
  703. hUGE_set_position::
  704. ;;; Processes (global) effect B, "position jump".
  705. ;;; Param: C = ID of the order to jump to
  706. ;;; Destroy: A
  707. fx_pos_jump:
  708. ld a, 1
  709. ld [row_break], a
  710. ld a, c
  711. ld [next_order], a
  712. ret
  713. ;;; Processes (global) effect D, "pattern break".
  714. ;;; Param: C = ID of the next order's row to start on
  715. ;;; Destroy: A
  716. fx_pattern_break:
  717. ld a, c
  718. ld [row_break], a
  719. ret
  720. ;;; Processes effect E, "note cut".
  721. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  722. ;;; Param: C = Tick to cut the note on (TODO: what does cutting on tick 0 do?)
  723. ;;; Param: A = Current tick
  724. ;;; Destroy: A
  725. fx_note_cut:
  726. cp c
  727. ret nz
  728. ;; check channel mute
  729. ;; 0 → $01, 1 → $02, 2 → $04, 3 → $05
  730. ;; Overall, these two instructions add 1 to the number.
  731. ;; However, the first instruction will generate a carry for inputs of $02 and $03;
  732. ;; the `adc` will pick the carry up, and "separate" 0 / 1 from 2 / 3 by an extra 1.
  733. ;; Luckily, this yields correct results for 0 ($01), 1 ($02), and 2 ($03 + 1 = $04).
  734. ;; We'll see about fixing 3 afterwards.
  735. add -2
  736. adc 3
  737. ;; After being shifted left, the inputs are $02, $04, $08 and $0A; all are valid BCD,
  738. ;; except for $0A. Since we just performed `add a`, DAA will correct the latter to $10.
  739. ;; (This should be correctly emulated everywhere, since the inputs are identical to
  740. ;; "regular" BCD.)
  741. ;; When shifting the results back, we'll thus get $01, $02, $04 and $08!
  742. add a
  743. daa
  744. rra
  745. ld d, a
  746. ld a, [mute_channels]
  747. and d
  748. ret nz
  749. ;; fallthrough
  750. ;;; Cuts note on a channel.
  751. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  752. ;;; Destroy: AF HL
  753. note_cut:
  754. ld a, b
  755. add a
  756. add a
  757. add b ; multiply by 5
  758. add LOW(rAUD1ENV)
  759. ld l, a
  760. ld h, HIGH(rAUD1ENV)
  761. xor a
  762. ld [hl+], a
  763. ld a, b
  764. cp 2
  765. ret z ; return early if CH3-- no need to retrigger note
  766. ;; Retrigger note
  767. inc l ; Not `inc hl` because H stays constant (= $FF)
  768. ld [hl], $FF
  769. ret
  770. ;;; Processes effect C, "set volume".
  771. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  772. ;;; Param: C = Volume to set the channel to
  773. ;;; Param: ZF = Set if and only if on tick 0
  774. ;;; Destroy: AF BC
  775. fx_set_volume:
  776. ret nz ; Return if we're not on tick zero.
  777. swap c
  778. ld a, [mute_channels]
  779. dec b
  780. jr z, .set_chn_2_vol
  781. dec b
  782. jr z, .set_chn_3_vol
  783. dec b
  784. jr z, .set_chn_4_vol
  785. .set_chn_1_vol:
  786. retMute 0
  787. ldh a, [rAUD1ENV]
  788. and %00001111
  789. or c
  790. ldh [rAUD1ENV], a
  791. ret
  792. .set_chn_2_vol:
  793. retMute 1
  794. ldh a, [rAUD2ENV]
  795. and %00001111
  796. or c
  797. ldh [rAUD2ENV], a
  798. ret
  799. .set_chn_3_vol:
  800. retMute 2
  801. ;; "Quantize" the more finely grained volume control down to one of 4 values.
  802. ld a, c
  803. cp 10 << 4
  804. jr nc, .one
  805. cp 5 << 4
  806. jr nc, .two
  807. or a
  808. jr z, .done ; Zero maps to zero
  809. .three:
  810. ld a, %01100000
  811. jr .done
  812. .two:
  813. ld a, %01000000
  814. jr .done
  815. .one:
  816. ld a, %00100000
  817. .done:
  818. ldh [rAUD3LEVEL], a
  819. ret
  820. .set_chn_4_vol:
  821. retMute 3
  822. ld a, c
  823. ldh [rAUD4ENV], a
  824. ret
  825. ;;; Processes effect 4, "vibrato".
  826. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  827. ;;; Param: C = FX param
  828. ;;; Param: ZF = Set if and only if on tick 0
  829. ;;; Destroy: AF B DE HL
  830. fx_vibrato:
  831. ret z
  832. ;; Extremely poor man's vibrato.
  833. ;; Speed values:
  834. ;; (0x0 = 1.0)
  835. ;; (0x1 = 0.5)
  836. ;; (0x3 = 0.25)
  837. ;; (0x7 = 0.125)
  838. ;; (0xf = 0.0625)
  839. ld d, 4
  840. call ptr_to_channel_member
  841. ld a, c
  842. and %11110000
  843. swap a
  844. ld e, a
  845. ld a, [counter]
  846. and e
  847. ld a, [hl]
  848. jr z, .go_up
  849. .restore:
  850. call get_note_period
  851. jr .finish_vibrato
  852. .go_up:
  853. call get_note_period
  854. ld a, c
  855. and %00001111
  856. add_a_to_hl
  857. .finish_vibrato:
  858. ld d, h
  859. ld e, l
  860. xor a
  861. jp update_channel_freq
  862. ;;; Processes effect 8, "arpeggio".
  863. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  864. ;;; Param: C = Offsets in semitones (each nibble)
  865. ;;; Param: ZF = Set if and only if on tick 0
  866. ;;; Destroy: AF B DE HL
  867. fx_arpeggio:
  868. ret z
  869. ld d, 4
  870. call ptr_to_channel_member
  871. ld d, [hl]
  872. ld a, [tick]
  873. dec a
  874. ;; TODO: A crappy modulo, because it's not a multiple of four :(
  875. jr .test_greater_than_two
  876. .greater_than_two:
  877. sub 3
  878. .test_greater_than_two:
  879. cp 3
  880. jr nc, .greater_than_two
  881. ;; Multiply by 2 to get offset into table
  882. add a
  883. add LOW(.arp_options)
  884. ld l, a
  885. adc HIGH(.arp_options)
  886. sub l
  887. ld h, a
  888. jp hl
  889. .arp_options:
  890. jr .set_arp1
  891. jr .set_arp2
  892. ;; No `jr .reset_arp`
  893. .reset_arp:
  894. ld a, d
  895. jr .finish_skip_add
  896. .set_arp2:
  897. ld a, c
  898. swap a
  899. db $FE ; cp <imm8> gobbles next byte
  900. .set_arp1:
  901. ld a, c
  902. .finish_arp:
  903. and %00001111
  904. add d
  905. .finish_skip_add:
  906. call get_note_period
  907. ld d, h
  908. ld e, l
  909. xor a
  910. jp update_channel_freq
  911. ;;; Processes effect 1, "portamento up".
  912. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  913. ;;; Param: C = How many units to slide the pitch by per tick
  914. ;;; Param: ZF = Set if and only if on tick 0
  915. ;;; Destroy: A B DE HL
  916. fx_porta_up:
  917. ret z
  918. ld d, 0
  919. call ptr_to_channel_member
  920. ;; Add C to 16-bit value at HL
  921. ld a, [hl+]
  922. add c
  923. ld e, a
  924. adc [hl]
  925. sub e
  926. ;; Write back
  927. .finish:
  928. ld d, a ; Store A for call to `update_channel_freq`
  929. ld [hl-], a
  930. ld [hl], e
  931. xor a
  932. jp update_channel_freq
  933. ;;; Processes (global) effect 2, "portamento down".
  934. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  935. ;;; Param: C = How many units to slide the pitch down by per tick
  936. ;;; Param: ZF = Set if and only if on tick 0
  937. ;;; Destroy: A B DE HL
  938. fx_porta_down:
  939. ret z
  940. ld d, 0
  941. call ptr_to_channel_member
  942. ;; Subtract C from 16-bit value at [HL]
  943. ld a, [hl+]
  944. sub c
  945. ld e, a
  946. sbc a
  947. add [hl]
  948. ;; Write back
  949. jr fx_porta_up.finish
  950. ;;; Processes effect 2, "tone portamento".
  951. ;;; Param: B = Current channel ID (0 = CH1, 1 = CH2, etc.)
  952. ;;; Param: C = Target note
  953. ;;; Param: ZF = Set if and only if on tick 0
  954. ;;; Destroy: A B DE HL
  955. fx_toneporta:
  956. jr nz, .do_toneporta
  957. ;; We're on tick zero, so just move the temp note value into the toneporta target.
  958. ld d, 2
  959. call ptr_to_channel_member
  960. ;; If the note is nonexistent, then just return
  961. ld a, [temp_note_value]
  962. or a
  963. jr z, .return_skip
  964. ld [hl+], a
  965. ld a, [temp_note_value+1]
  966. ld [hl], a
  967. ;; Don't call _playnote. This is done by grabbing the return
  968. ;; address and manually skipping the next call instruction.
  969. .return_skip:
  970. ret_dont_call_playnote
  971. .do_toneporta:
  972. ld d, 0
  973. call ptr_to_channel_member
  974. push hl
  975. ;; Read current period
  976. ld a, [hl+]
  977. ld e, a
  978. ld a, [hl+]
  979. ld d, a
  980. ;; Read target period
  981. ld a, [hl+]
  982. ld h, [hl]
  983. ld l, a
  984. ;; Do we need to porta up, or down? Compute (current - target) and check carry to know
  985. sub e
  986. ld a, h
  987. sbc d
  988. jr c, .porta_down ; Current period (DE) is higher than target one (HL), so down we go!
  989. ;; Add offset to current freq
  990. ld a, e
  991. add c
  992. ld e, a
  993. adc d
  994. sub e
  995. ld d, a
  996. ;; We don't need to worry about overflow given the relatively low values we work with
  997. ld c, 0 ; The overshoot comparison should yield no carry, like the above one
  998. jr .check_overshoot
  999. .porta_down:
  1000. ;; Subtract offset from current freq
  1001. ld a, e
  1002. sub c
  1003. ld e, a
  1004. sbc a
  1005. add d
  1006. ld d, a
  1007. jr c, .overshot ; There will be no underflows under my watch!
  1008. ld c, $FF ; The overshoot comparison should yield carry, like the above one
  1009. .check_overshoot:
  1010. ld a, l
  1011. sub e
  1012. ld a, h
  1013. sbc d
  1014. rra ; Shift carry into bit 7
  1015. xor c ; XOR it with provided value
  1016. rla ; Shift maybe-toggled carry back
  1017. jr nc, .no_overshoot
  1018. .overshot:
  1019. ;; Override computed new period with target
  1020. ld d, h
  1021. ld e, l
  1022. .no_overshoot:
  1023. pop hl
  1024. ld a, e
  1025. ld [hl+], a
  1026. ld [hl], d
  1027. ;; Do not retrigger channel
  1028. ld a, 6
  1029. add_a_to_hl
  1030. ld a, [hl]
  1031. res 7, [hl]
  1032. ;; B must be preserved for this
  1033. jp update_channel_freq
  1034. ;; TODO: Find some way to de-duplicate this code!
  1035. ;;; Computes the pointer to a CH4 instrument.
  1036. ;;; Param: B = The instrument's ID
  1037. ;;; Param: DE = Instrument pointer table
  1038. ;;; Return: DE = Pointer to the instrument
  1039. ;;; Return: ZF = Set if and only if there was no instrument (ID == 0)
  1040. ;;; Destroy: AF
  1041. setup_instrument_pointer_ch4:
  1042. ;; Call with:
  1043. ;; Instrument/High nibble of effect in B
  1044. ;; Stores whether the instrument was real in the Z flag
  1045. ;; Stores the instrument pointer in DE
  1046. ld a, b
  1047. and %11110000
  1048. swap a
  1049. ret z ; If there's no instrument, then return early.
  1050. dec a ; Instrument 0 is "no instrument"
  1051. add a
  1052. jr setup_instrument_pointer.finish
  1053. ;;; Computes the pointer to an instrument.
  1054. ;;; Param: B = The instrument's ID
  1055. ;;; Param: DE = Instrument pointer table
  1056. ;;; Return: DE = Pointer to the instrument
  1057. ;;; Return: ZF = Set if and only if there was no instrument (ID == 0)
  1058. ;;; Destroy: AF
  1059. setup_instrument_pointer:
  1060. ;; Call with:
  1061. ;; Instrument/High nibble of effect in B
  1062. ;; Stores whether the instrument was real in the Z flag
  1063. ;; Stores the instrument pointer in DE
  1064. ld a, b
  1065. and %11110000
  1066. swap a
  1067. ret z ; If there's no instrument, then return early.
  1068. dec a ; Instrument 0 is "no instrument"
  1069. .finish:
  1070. ;; Shift left twice to multiply by 4
  1071. add a
  1072. add a
  1073. add_a_to_de
  1074. rla ; reset the Z flag
  1075. ret
  1076. _hUGE_dosound_banked::
  1077. _hUGE_dosound::
  1078. ;;; Ticks the sound engine once.
  1079. ;;; Destroy: AF BC DE HL
  1080. hUGE_dosound::
  1081. ld a, [tick]
  1082. or a
  1083. jp nz, process_effects
  1084. ;; Note playback
  1085. ld hl, pattern1
  1086. ld de, channel_note1
  1087. call get_current_note
  1088. push af
  1089. jr nc, .do_setvol1
  1090. load_de_ind duty_instruments
  1091. call setup_instrument_pointer
  1092. ld a, [highmask1]
  1093. res 7, a ; Turn off the "initial" flag
  1094. jr z, .write_mask1
  1095. checkMute 0, .do_setvol1
  1096. ld a, [de]
  1097. inc de
  1098. ldh [rAUD1SWEEP], a
  1099. ld a, [de]
  1100. inc de
  1101. ldh [rAUD1LEN], a
  1102. ld a, [de]
  1103. ldh [rAUD1ENV], a
  1104. inc de
  1105. ld a, [de]
  1106. .write_mask1:
  1107. ld [highmask1], a
  1108. .do_setvol1:
  1109. ld a, l
  1110. ld [temp_note_value], a
  1111. ld a, h
  1112. ld [temp_note_value+1], a
  1113. ld e, 0
  1114. call do_effect
  1115. pop af
  1116. call c, play_ch1_note
  1117. process_ch2:
  1118. ;; Note playback
  1119. ld hl, pattern2
  1120. ld de, channel_note2
  1121. call get_current_note
  1122. push af
  1123. jr nc, .do_setvol2
  1124. load_de_ind duty_instruments
  1125. call setup_instrument_pointer
  1126. ld a, [highmask2]
  1127. res 7, a ; Turn off the "initial" flag
  1128. jr z, .write_mask2
  1129. checkMute 1, .do_setvol2
  1130. inc de
  1131. ld a, [de]
  1132. inc de
  1133. ldh [rAUD2LEN], a
  1134. ld a, [de]
  1135. ldh [rAUD2ENV], a
  1136. inc de
  1137. ld a, [de]
  1138. .write_mask2:
  1139. ld [highmask2], a
  1140. .do_setvol2:
  1141. ld a, l
  1142. ld [temp_note_value], a
  1143. ld a, h
  1144. ld [temp_note_value+1], a
  1145. ld e, 1
  1146. call do_effect
  1147. pop af
  1148. call c, play_ch2_note
  1149. process_ch3:
  1150. ld hl, pattern3
  1151. ld de, channel_note3
  1152. call get_current_note
  1153. ld a, l
  1154. ld [temp_note_value], a
  1155. ld a, h
  1156. ld [temp_note_value+1], a
  1157. push af
  1158. jr nc, .do_setvol3
  1159. load_de_ind wave_instruments
  1160. call setup_instrument_pointer
  1161. ld a, [highmask3]
  1162. res 7, a ; Turn off the "initial" flag
  1163. jr z, .write_mask3
  1164. checkMute 2, .do_setvol3
  1165. ld a, [de]
  1166. inc de
  1167. ldh [rAUD3LEN], a
  1168. ld a, [de]
  1169. inc de
  1170. ldh [rAUD3LEVEL], a
  1171. ld a, [de]
  1172. inc de
  1173. ;; Check to see if we need to copy a wave and then do so
  1174. ld hl, current_wave
  1175. cp [hl]
  1176. jr z, .no_wave_copy
  1177. ld [hl], a
  1178. swap a
  1179. add_a_ind_ret_hl waves
  1180. xor a
  1181. ldh [rAUD3ENA], a
  1182. FOR OFS, 16
  1183. ld a, [hl+]
  1184. ldh [_AUD3WAVERAM + OFS], a
  1185. ENDR
  1186. ld a, %10000000
  1187. ldh [rAUD3ENA], a
  1188. .no_wave_copy:
  1189. ld a, [de]
  1190. .write_mask3:
  1191. ld [highmask3], a
  1192. .do_setvol3:
  1193. ld e, 2
  1194. call do_effect
  1195. pop af
  1196. call c, play_ch3_note
  1197. process_ch4:
  1198. ld hl, pattern4
  1199. ld a, [hl+]
  1200. ld c, a
  1201. ld b, [hl]
  1202. call get_current_row
  1203. ld [channel_note4], a
  1204. cp LAST_NOTE
  1205. push af
  1206. jr nc, .do_setvol4
  1207. call get_note_poly
  1208. ld [temp_note_value], a
  1209. ld de, 0
  1210. call setup_instrument_pointer
  1211. ld a, [highmask4]
  1212. res 7, a ; Turn off the "initial" flag
  1213. jr z, .write_mask4
  1214. checkMute 3, .do_setvol4
  1215. load_hl_ind noise_instruments
  1216. sla e
  1217. add hl, de
  1218. ld a, [hl+]
  1219. ldh [rAUD4ENV], a
  1220. ld a, [hl]
  1221. and %00111111
  1222. ldh [rAUD4LEN], a
  1223. ld a, [temp_note_value]
  1224. ld d, a
  1225. ld a, [hl]
  1226. and %10000000
  1227. swap a
  1228. or d
  1229. ld [temp_note_value], a
  1230. ld a, [hl]
  1231. and %01000000
  1232. or %10000000
  1233. .write_mask4:
  1234. ld [highmask4], a
  1235. .do_setvol4:
  1236. ld e, 3
  1237. call do_effect
  1238. pop af
  1239. call c, play_ch4_note
  1240. ;; finally just update the tick/order/row values
  1241. jp process_tick
  1242. process_effects:
  1243. ;; Only do effects if not on tick zero
  1244. checkMute 0, .after_effect1
  1245. ld hl, pattern1
  1246. ld a, [hl+]
  1247. ld c, a
  1248. ld b, [hl]
  1249. call get_current_row
  1250. ld a, c
  1251. or a
  1252. jr z, .after_effect1
  1253. ld e, 0
  1254. call do_effect ; make sure we never return with ret_dont_call_playnote macro
  1255. .after_effect1:
  1256. checkMute 1, .after_effect2
  1257. ld hl, pattern2
  1258. ld a, [hl+]
  1259. ld c, a
  1260. ld b, [hl]
  1261. call get_current_row
  1262. ld a, c
  1263. or a
  1264. jr z, .after_effect2
  1265. ld e, 1
  1266. call do_effect ; make sure we never return with ret_dont_call_playnote macro
  1267. .after_effect2:
  1268. checkMute 2, .after_effect3
  1269. ld hl, pattern3
  1270. ld a, [hl+]
  1271. ld c, a
  1272. ld b, [hl]
  1273. call get_current_row
  1274. ld a, c
  1275. or a
  1276. jr z, .after_effect3
  1277. ld e, 2
  1278. call do_effect ; make sure we never return with ret_dont_call_playnote macro
  1279. .after_effect3:
  1280. checkMute 3, .after_effect4
  1281. ld hl, pattern4
  1282. ld a, [hl+]
  1283. ld c, a
  1284. ld b, [hl]
  1285. call get_current_row
  1286. cp LAST_NOTE
  1287. jr nc, .done_macro
  1288. ld h, a
  1289. load_de_ind noise_instruments
  1290. call setup_instrument_pointer_ch4
  1291. jr z, .done_macro ; No instrument, thus no macro
  1292. ld a, [tick]
  1293. cp 7
  1294. jr nc, .done_macro
  1295. inc de
  1296. ld l, a
  1297. ld a, h
  1298. ld h, 0
  1299. add hl, de
  1300. add [hl]
  1301. call get_note_poly
  1302. ld l, a
  1303. ld a, [de]
  1304. ld e, a
  1305. and %10000000
  1306. swap a
  1307. or l
  1308. ldh [rAUD4POLY], a
  1309. ld a, e
  1310. and %01000000
  1311. ldh [rAUD4GO], a
  1312. .done_macro:
  1313. ld a, c
  1314. or a
  1315. jr z, .after_effect4
  1316. ld e, 3
  1317. call do_effect ; make sure we never return with ret_dont_call_playnote macro
  1318. .after_effect4:
  1319. process_tick:
  1320. ld hl, counter
  1321. inc [hl]
  1322. ld a, [ticks_per_row]
  1323. ld b, a
  1324. ld hl, tick
  1325. ld a, [hl]
  1326. inc a
  1327. cp b
  1328. jr z, .newrow
  1329. ld [hl], a
  1330. ret
  1331. .newrow:
  1332. ;; Reset tick to 0
  1333. ld [hl], 0
  1334. ;; Check if we need to perform a row break or pattern break
  1335. ld a, [row_break]
  1336. or a
  1337. jr z, .no_break
  1338. ;; These are offset by one so we can check to see if they've
  1339. ;; been modified
  1340. dec a
  1341. ld b, a
  1342. ld hl, row_break
  1343. xor a
  1344. ld [hl-], a
  1345. or [hl] ; a = [next_order], zf = ([next_order] == 0)
  1346. ld [hl], 0
  1347. jr z, .neworder
  1348. dec a
  1349. add a ; multiply order by 2 (they are words)
  1350. jr .update_current_order
  1351. .no_break:
  1352. ;; Increment row.
  1353. ld a, [row]
  1354. inc a
  1355. ld b, a
  1356. cp PATTERN_LENGTH
  1357. jr nz, .noreset
  1358. ld b, 0
  1359. .neworder:
  1360. ;; Increment order and change loaded patterns
  1361. ld a, [order_cnt]
  1362. ld c, a
  1363. ld a, [current_order]
  1364. add 2
  1365. cp c
  1366. jr nz, .update_current_order
  1367. xor a
  1368. .update_current_order:
  1369. ;; Call with:
  1370. ;; A: The order to load
  1371. ;; B: The row for the order to start on
  1372. ld [current_order], a
  1373. ld c, a
  1374. call load_patterns
  1375. .noreset:
  1376. ld a, b
  1377. ld [row], a
  1378. IF DEF(PREVIEW_MODE)
  1379. db $fd ; signal row update to tracker
  1380. ENDC
  1381. ret
  1382. note_table:
  1383. include "huge_note_table.inc"
  1384. IF DEF(GBDK)
  1385. SECTION "hUGEDriver GBDK wrappers", ROM0
  1386. _hUGE_init_banked::
  1387. ld hl, sp+2+4
  1388. jr continue_init
  1389. _hUGE_init::
  1390. ld hl, sp+2
  1391. continue_init:
  1392. push bc
  1393. ld a, [hl+]
  1394. ld h, [hl]
  1395. ld l, a
  1396. call hUGE_init
  1397. pop bc
  1398. ret
  1399. _hUGE_mute_channel_banked::
  1400. ld hl, sp+3+4
  1401. jr continue_mute
  1402. _hUGE_mute_channel::
  1403. ld hl, sp+3
  1404. continue_mute:
  1405. push bc
  1406. ld a, [hl-]
  1407. and 1
  1408. ld c, a
  1409. ld b, [hl]
  1410. call hUGE_mute_channel
  1411. pop bc
  1412. ret
  1413. _hUGE_set_position_banked::
  1414. ld hl, sp+2+4
  1415. jr continue_set_position
  1416. _hUGE_set_position::
  1417. ld hl, sp+2
  1418. continue_set_position:
  1419. push bc
  1420. ld c, [hl]
  1421. call hUGE_set_position
  1422. pop bc
  1423. ret
  1424. ENDC