Skip to content

Commit 0fcea6b

Browse files
committed
nullsound: pan FX for ADPCM channels
1 parent fda751e commit 0fcea6b

File tree

4 files changed

+76
-14
lines changed

4 files changed

+76
-14
lines changed

Diff for: nullsound/nss-adpcm-a.s

+26-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
;; getters for ADPCM-A state
3131
.lclequ VOL, (state_a_vol-state_a)
3232
.lclequ OUT_VOL, (state_a_out_vol-state_a)
33+
.lclequ PAN, (state_a_pan-state_a)
3334

3435
.equ NSS_ADPCM_A_INSTRUMENT_PROPS, 4
3536
.equ NSS_ADPCM_A_NEXT_REGISTER, 8
@@ -71,6 +72,8 @@ state_a_trigger: .blkb TRIGGER_SIZE
7172
;;; volume
7273
state_a_vol: .blkb 1 ; configured note volume (attenuation)
7374
state_a_out_vol: .blkb 1 ; ym2610 volume after the FX pipeline
75+
;;; pan
76+
state_a_pan: .blkb 1 ; configured pan (b7: left, b6: right)
7477
;;;
7578
state_a_end:
7679
;;; ADPCM-A2
@@ -128,10 +131,15 @@ init_nss_adpcm_state_tracker::
128131
ld (state_adpcm_a_channel), a
129132
;; set default
130133
ld ix, #state_a1
134+
ld bc, #ADPCM_A_STATE_SIZE
131135
ld d, #6
132136
_a_init:
133137
ld a, #0x1f
134138
ld VOL(ix), a
139+
ld a, #0xc0
140+
ld PAN(ix), a
141+
142+
add ix, bc
135143
dec d
136144
jr nz, _a_init
137145
;; global ADPCM volumes are initialized in the volume state tracker
@@ -228,17 +236,17 @@ _post_load_a_vol:
228236

229237
;; Pipeline action: load pan+volume register when it is modified
230238
ld a, PIPELINE(ix)
231-
or a, #(STATE_LOAD_VOL|STATE_LOAD_PAN)
239+
and a, #(STATE_LOAD_VOL|STATE_LOAD_PAN)
232240
jr z, _post_load_a_pan_vol
233241
res BIT_LOAD_VOL, PIPELINE(ix)
234242
res BIT_LOAD_PAN, PIPELINE(ix)
235243

236-
;; c: volume + default pan (L/R)
244+
;; c: volume + pan
237245
ld a, OUT_VOL(ix)
238-
or #0xc0
246+
add PAN(ix)
239247
ld c, a
240248

241-
;; set pan+volume for channel in the YM2610
249+
;; set volume + pan for channel in the YM2610
242250
;; b: ADPCM-A channel
243251
ld a, (state_adpcm_a_channel)
244252
add a, #REG_ADPCM_A1_PAN_VOLUME
@@ -620,3 +628,17 @@ adpcm_a_retrigger::
620628

621629
ld a, #1
622630
ret
631+
632+
633+
;;; ADPCM_A_PAN
634+
;;; Set the pan (l/r) for the current ADPCM-A channel
635+
;;; ------
636+
;;; [ hl ]: pan (b7: left, b6: right)
637+
adpcm_a_pan::
638+
ld a, (hl)
639+
inc hl
640+
ld PAN(ix), a
641+
set BIT_LOAD_PAN, PIPELINE(ix)
642+
643+
ld a, #1
644+
ret

Diff for: nullsound/nss-adpcm-b.s

+27-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
.lclequ DELTA_N, (state_b_note_delta_n-state_b)
3535
.lclequ VOL, (state_b_vol-state_b)
3636
.lclequ OUT_VOL, (state_b_out_vol-state_b)
37+
.lclequ PAN, (state_b_pan-state_b)
3738
.lclequ INSTR, (state_b_instr-state_b)
3839
.lclequ START_CMD, (state_b_instr_start_cmd-state_b)
3940

@@ -85,6 +86,8 @@ state_b_instr_start_cmd: .blkb 1 ; instrument play command (with
8586
;;; volume
8687
state_b_vol: .blkb 1 ; configured note volume (attenuation)
8788
state_b_out_vol: .blkb 1 ; ym2610 volume after the FX pipeline
89+
;;; pan
90+
state_b_pan: .blkb 1 ; configured pan (b7: left, b6: right)
8891
;;;
8992
state_b_end:
9093

@@ -176,9 +179,18 @@ _b_post_check_playing:
176179
ld b, #REG_ADPCM_B_VOLUME
177180
ld c, OUT_VOL(ix)
178181
call ym2610_write_port_a
179-
182+
res BIT_LOAD_VOL, PIPELINE(ix)
180183
_post_load_b_vol:
181184

185+
;; Pipeline action: load pan if requested
186+
bit BIT_LOAD_PAN, PIPELINE(ix)
187+
jr z, _post_load_b_pan
188+
ld b, #REG_ADPCM_B_PAN
189+
ld c, PAN(ix)
190+
call ym2610_write_port_a
191+
res BIT_LOAD_PAN, PIPELINE(ix)
192+
_post_load_b_pan:
193+
182194
;; Pipeline action: load note register when the note state is modified
183195
bit BIT_LOAD_NOTE, PIPELINE(ix)
184196
jr z, _post_load_b_note
@@ -779,3 +791,17 @@ adpcm_b_cut::
779791

780792
ld a, #1
781793
ret
794+
795+
796+
;;; ADPCM_B_PAN
797+
;;; Set the pan (l/r) for the channel
798+
;;; ------
799+
;;; [ hl ]: pan (b7: left, b6: right)
800+
adpcm_b_pan::
801+
ld a, (hl)
802+
inc hl
803+
ld PAN(ix), a
804+
set BIT_LOAD_PAN, PIPELINE(ix)
805+
806+
ld a, #1
807+
ret

Diff for: nullsound/stream.s

+2
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ nss_opcodes:
530530
.nss_op adpcm_b_cut
531531
.nss_op adpcm_b_delay
532532
.nss_op adpcm_a_retrigger
533+
.nss_op adpcm_a_pan
534+
.nss_op adpcm_b_pan
533535

534536

535537

Diff for: tools/nsstool.py

+21-9
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ def register_nss_ops():
289289
("b_cut", ["delay"]),
290290
("b_delay", ["delay"]),
291291
("a_retrigger", ["delay"]),
292+
("a_pan", ["pan_mask"]),
293+
("b_pan", ["pan_mask"]),
292294
# reserved opcodes
293295
("nss_label", ["pat"])
294296
)
@@ -301,6 +303,15 @@ def register_nss_ops():
301303
globals()[cname]=make_dataclass(cname, fields)
302304

303305

306+
def convert_pan(fx, fxval):
307+
if fx == 0x08: # pan
308+
pan_l = 0x80 if (fxval & 0xf0) else 0
309+
pan_r = 0x40 if (fxval & 0x0f) else 0
310+
elif fx == 0x80: # old pan
311+
pan_l = 0x80 if fxval in [0x00, 0x80] else 0
312+
pan_r = 0x40 if fxval in [0x80, 0xff] else 0
313+
return pan_l|pan_r;
314+
304315

305316
#
306317
# Furnace module conversion functions
@@ -317,15 +328,7 @@ def convert_fm_row(row, channel):
317328
opcodes.append(fm_vol(row.vol))
318329
# pre-instrument effects
319330
for fx, fxval in row.fx:
320-
if fx == 0x08: # pan
321-
pan_l = 0x80 if (fxval & 0xf0) else 0
322-
pan_r = 0x40 if (fxval & 0x0f) else 0
323-
opcodes.append(fm_pan(pan_l|pan_r))
324-
elif fx == 0x80: # old pan
325-
pan_l = 0x80 if fxval in [0x00, 0x80] else 0
326-
pan_r = 0x40 if fxval in [0x80, 0xff] else 0
327-
opcodes.append(fm_pan(pan_l|pan_r))
328-
elif fx == 0xed: # note delay
331+
if fx == 0xed: # note delay
329332
opcodes.append(fm_delay(fxval))
330333
# instrument
331334
if row.ins != -1:
@@ -382,6 +385,9 @@ def convert_fm_row(row, channel):
382385
opcodes.append(fm_porta(fxval))
383386
elif fx == 0xec: # cut
384387
opcodes.append(fm_cut(fxval))
388+
elif fx in [0x08, 0x80]: # panning
389+
pan_mask = convert_pan(fx, fxval)
390+
opcodes.append(fm_pan(pan_mask))
385391
else:
386392
add_unknown_fx('FM', fx)
387393

@@ -521,6 +527,9 @@ def convert_a_row(row, channel):
521527
opcodes.append(groove(fxval))
522528
elif fx == 0xec: # cut
523529
opcodes.append(a_cut(fxval))
530+
elif fx in [0x08, 0x80]: # panning
531+
pan_mask = convert_pan(fx, fxval)
532+
opcodes.append(a_pan(pan_mask))
524533
else:
525534
add_unknown_fx('ADPCM-A', fx)
526535

@@ -571,6 +580,9 @@ def convert_b_row(row, channel):
571580
opcodes.append(b_porta(fxval))
572581
elif fx == 0xec: # cut
573582
opcodes.append(b_cut(fxval))
583+
elif fx in [0x08, 0x80]: # panning
584+
pan_mask = convert_pan(fx, fxval)
585+
opcodes.append(b_pan(pan_mask))
574586
else:
575587
add_unknown_fx('ADPCM-B', fx)
576588

0 commit comments

Comments
 (0)