Skip to content

Commit a70ae6e

Browse files
committed
nullsound: implement legato FX (0xEA)
1 parent 8bd4563 commit a70ae6e

File tree

8 files changed

+65
-8
lines changed

8 files changed

+65
-8
lines changed

nullsound/doc/nss.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ This document details the current level of support for Furnace features in NSS.
6262
| F2 | Single tick pitch slide down | 💜 | |
6363
| 03 | Portamento | 💚 | |
6464
| E1 | Note slide up | 💚 | |
65-
| EA | Toggle legato | 💜 | |
65+
| EA | Toggle legato | 💚 | |
6666
| E2 | Note slide down | 💚 | |
6767
| E6 | Quick legato (compatibility) | 🚫 | |
6868
| E8 | Quick legato up | 💚 | |

nullsound/fx-legato.s

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ _legato_post_sign:
6161
ld LEGATO_DELAY(ix), a
6262

6363
set BIT_FX_LEGATO, NOTE_FX(ix)
64+
set BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
6465

6566
pop bc
6667
inc hl
@@ -88,9 +89,14 @@ _legato_update_pos:
8889
;; to recompute the note and tune values without shift, so force it here
8990
set BIT_LOAD_NOTE, PIPELINE(ix)
9091

91-
;; stop FX
92+
;; stop FX if that was a quick legato
93+
;; (otherwise a dedicated opcode must be used to disable legato)
9294
ld LEGATO_TRANSPOSE(ix), #0
95+
bit BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
96+
jr nz, _legato_update_end
9397
res BIT_FX_LEGATO, NOTE_FX(ix)
98+
_legato_update_end:
99+
res BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
94100

95101
ret
96102

@@ -117,3 +123,23 @@ quick_legato_down::
117123
;; a: direction
118124
xor a
119125
jp legato_init
126+
127+
128+
;;; LEGATO
129+
;;; Enable the legato mode for current channel
130+
;;; ------
131+
;;; ix : state for channel
132+
;;; hl modified
133+
legato::
134+
set BIT_FX_LEGATO, NOTE_FX(ix)
135+
ret
136+
137+
138+
;;; LEGATO_OFF
139+
;;; Disable the legato mode for current channel
140+
;;; ------
141+
;;; ix : state for channel
142+
;;; hl modified
143+
legato_off::
144+
res BIT_FX_LEGATO, NOTE_FX(ix)
145+
ret

nullsound/nss-adpcm-b.s

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ _b_post_fx_vibrato:
203203
call eval_arpeggio_step
204204
set BIT_LOAD_NOTE, PIPELINE(ix)
205205
_b_post_fx_arpeggio:
206-
bit BIT_FX_LEGATO, NOTE_FX(ix)
206+
bit BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
207207
jr z, _b_post_fx_legato
208208
call eval_legato_step
209209
set BIT_LOAD_NOTE, PIPELINE(ix)
@@ -451,10 +451,16 @@ adpcm_b_configure_note_on:
451451
jr _b_cfg_note_prepare_ym2610
452452
_b_cfg_note_update:
453453
;; update the current note and prepare the ym2610
454-
res BIT_NOTE_STARTED, PIPELINE(ix)
455454
ld NOTE(ix), a
456455
ld NOTE16+1(ix), a
457456
ld NOTE16(ix), #0
457+
;; do not stop the current note if a legato is in progress
458+
bit BIT_FX_LEGATO, NOTE_FX(ix)
459+
jr z, _b_post_cfg_note_update
460+
set BIT_LOAD_NOTE, PIPELINE(ix)
461+
jr _b_cfg_note_end
462+
_b_post_cfg_note_update:
463+
res BIT_NOTE_STARTED, PIPELINE(ix)
458464
_b_cfg_note_prepare_ym2610:
459465
;; stop playback on the channel, and let the pipeline restart it
460466
ld b, #REG_ADPCM_B_START_STOP

nullsound/nss-fm.s

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ _fm_post_fx_vibrato:
677677
call eval_arpeggio_step
678678
set BIT_LOAD_NOTE, PIPELINE(ix)
679679
_fm_post_fx_arpeggio:
680-
bit BIT_FX_LEGATO, NOTE_FX(ix)
680+
bit BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
681681
jr z, _fm_post_fx_legato
682682
call eval_legato_step
683683
set BIT_LOAD_NOTE, PIPELINE(ix)
@@ -991,10 +991,16 @@ fm_configure_note_on:
991991
jr _fm_cfg_note_prepare_ym2610
992992
_fm_cfg_note_update:
993993
;; update the current note and prepare the ym2610
994-
res BIT_NOTE_STARTED, PIPELINE(ix)
995994
ld NOTE(ix), a
996995
ld NOTE16+1(ix), a
997996
ld NOTE16(ix), #0
997+
;; do not stop the current note if a legato is in progress
998+
bit BIT_FX_LEGATO, NOTE_FX(ix)
999+
jr z, _fm_post_cfg_note_update
1000+
set BIT_LOAD_NOTE, PIPELINE(ix)
1001+
jr _fm_cfg_note_end
1002+
_fm_post_cfg_note_update:
1003+
res BIT_NOTE_STARTED, PIPELINE(ix)
9981004
_fm_cfg_note_prepare_ym2610:
9991005
;; stop playback on the channel, and let the pipeline restart it
10001006
ld a, (state_fm_ym2610_channel)

nullsound/nss-ssg.s

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ _ssg_post_fx_vibrato:
333333
call eval_arpeggio_step
334334
set BIT_LOAD_NOTE, PIPELINE(ix)
335335
_ssg_post_fx_arpeggio:
336-
bit BIT_FX_LEGATO, NOTE_FX(ix)
336+
bit BIT_FX_QUICK_LEGATO, NOTE_FX(ix)
337337
jr z, _ssg_post_fx_legato
338338
call eval_legato_step
339339
set BIT_LOAD_NOTE, PIPELINE(ix)
@@ -845,10 +845,16 @@ ssg_configure_note_on:
845845
jr _ssg_cfg_note_prepare_ym2610
846846
_ssg_cfg_note_update:
847847
;; update the current note and prepare the ym2610
848-
res BIT_NOTE_STARTED, PIPELINE(ix)
849848
ld NOTE(ix), a
850849
ld NOTE16+1(ix), a
851850
ld NOTE16(ix), #0
851+
;; do not stop the current note if a legato is in progress
852+
bit BIT_FX_LEGATO, NOTE_FX(ix)
853+
jr z, _ssg_post_cfg_note_update
854+
set BIT_LOAD_NOTE, PIPELINE(ix)
855+
jr _ssg_cfg_note_end
856+
_ssg_post_cfg_note_update:
857+
res BIT_NOTE_STARTED, PIPELINE(ix)
852858
_ssg_cfg_note_prepare_ym2610:
853859
;; init macro position
854860
ld a, MACRO_DATA(ix)

nullsound/stream.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ nss_opcodes:
601601
.nss_op note_portamento
602602
.nss_op vibrato
603603
.nss_op vibrato_off
604+
.nss_op legato
605+
.nss_op legato_off
604606

605607

606608

nullsound/struct-fx.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ _trigger_size:
173173
.lclequ BIT_FX_VIBRATO, 2
174174
.lclequ BIT_FX_ARPEGGIO, 3
175175
.lclequ BIT_FX_LEGATO, 4
176+
.lclequ BIT_FX_QUICK_LEGATO, 5
176177

177178
;; Trigger FX function interface
178179
.lclequ TRIGGER_LOAD_NOTE_FUNC, 0

tools/nsstool.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ def register_nss_ops():
337337
("note_porta", ["speed"]),
338338
("vibrato", ["speed_depth"]),
339339
("vibrato_off", ),
340+
("legato", ),
341+
("legato_off", ),
340342

341343

342344
# reserved opcodes
@@ -646,6 +648,14 @@ def convert_row(row, channel):
646648
# quick legato down
647649
elif fx == 0xe9:
648650
out.fx.append(quick_legato_d(fxval))
651+
# legato
652+
elif fx == 0xea:
653+
if fxval in [-1, 0]:
654+
# opcode must be executed before a note opcode
655+
out.pre_fx.append(legato_off())
656+
else:
657+
# opcode must be executed before a note opcode
658+
out.post_fx.append(legato())
649659
# note cut
650660
elif fx == 0xec:
651661
out.fx.append(factory.cut(fxval))

0 commit comments

Comments
 (0)