@@ -167,7 +167,10 @@ def read_module(bs):
167
167
nb_patterns = bs .u4 () # skip global pattern count
168
168
chips = [x for x in bs .read (32 )]
169
169
assert chips [:chips .index (0 )] == [165 ] # single ym2610 chip
170
- bs .read (32 + 32 + 128 ) # skip chips vol, pan, flags
170
+ bs .read (32 ) # skip chips vol
171
+ bs .read (32 ) # skip chips pan
172
+ chip_flags = unpack ("32I" , bs .read (128 ))
173
+ check_chip_flags (chip_flags [0 ], bs )
171
174
mod .name = bs .ustr ()
172
175
mod .author = bs .ustr ()
173
176
mod .pattern_len = pattern_len
@@ -219,6 +222,34 @@ def read_module(bs):
219
222
return mod
220
223
221
224
225
+ # Global tweak to compensate for default SSG output volume in Furnace
226
+ HALF_SSG_VOL = False
227
+ SSG_USED = False
228
+ def check_chip_flags (ptr , bs ):
229
+ global HALF_SSG_VOL
230
+ saved_pos = bs .pos
231
+ bs .seek (ptr )
232
+ assert bs .read (4 ) == b"FLAG"
233
+ size = bs .u4 ()
234
+ data = bs .read (size )
235
+ datastr = bytearray (data ).decode ("utf-8" )
236
+ flags = {}
237
+ for d in datastr .split ("\n " )[:- 1 ]: # last item is "\0"
238
+ k , v = d .split ("=" )
239
+ flags [k ]= v
240
+ bs .seek (saved_pos )
241
+
242
+ # check if check volumes for SSG and FM/ADPCM (or the resp. Furnace defaults)
243
+ ssgVol = int (flags .get ("ssgVol" ,"128" ))
244
+ if ssgVol == 128 :
245
+ HALF_SSG_VOL = True
246
+
247
+ # warn if this moudle uses unsupported master volumes
248
+ fmVol = int (flags .get ("fmVol" ,"256" ))
249
+ if (not (fmVol == 256 and ssgVol == 128 )) and (not (fmVol == 256 and ssgVol == 256 )):
250
+ print ("Furnace module uses custom output volumes (FM/ADPCM: %d, SSG: %d), which is not supported in hardware.\n "
251
+ "Please set the volume of FM/ADPCM and SSG tracks to 256 in Furnace in the 'Chip Manager' window" % (fmVol , ssgVol ))
252
+
222
253
223
254
@dataclass
224
255
class fm_operator :
@@ -420,11 +451,18 @@ def read_ssg_macro(length, bs):
420
451
"arp" : 1 << 2 , # BIT_LOAD_NOTE
421
452
}
422
453
423
- autoenv = False
454
+ global SSG_USED
455
+ SSG_USED = True
456
+ autoenv = False
424
457
blocks = {}
425
458
macros , loop = read_macro_data (length , bs )
426
459
for code in macros :
427
- blocks [code_name [code ]] = macros [code ]
460
+ data = macros [code ]
461
+ if HALF_SSG_VOL and code_name [code ] == "vol" :
462
+ # Temporary volume adjustment when SSG channel is not mixed 100%
463
+ # in the furnace module
464
+ data = [max (0 , x - 1 ) for x in data ]
465
+ blocks [code_name [code ]] = data
428
466
429
467
# pass: merge waveform sequence into vol & noise_tone sequences for SSG registers
430
468
if "wave" in blocks :
@@ -927,6 +965,10 @@ def main():
927
965
928
966
if arguments .action == "instruments" :
929
967
generate_instruments (m , sample_map , name , bank , ins , outfd )
968
+ # warn if SSG required volume tweak
969
+ if SSG_USED and HALF_SSG_VOL :
970
+ print ("Volume of SSG channel is halved in Furnace, SSG macros were tweaked to compensate.\n "
971
+ "To fix that, please set the SSG volume to 256 in Furnace in the 'Chip Manager' window." )
930
972
elif arguments .action == "samples" :
931
973
generate_sample_map (m , smp , outfd )
932
974
else :
0 commit comments