From a1b62f3155d6e109e227fb9da1dc4b4092cd08b0 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 24 Apr 2026 18:35:24 +0900 Subject: [PATCH] taud-related changes (docs, converter supports Y eff) --- assets/disk0/tvdos/include/taud.mjs | 4 ++-- s3m2taud.py | 18 ++++++++++++------ terranmon.txt | 13 +++++++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/assets/disk0/tvdos/include/taud.mjs b/assets/disk0/tvdos/include/taud.mjs index 98504f1..27b3230 100644 --- a/assets/disk0/tvdos/include/taud.mjs +++ b/assets/disk0/tvdos/include/taud.mjs @@ -219,8 +219,8 @@ function captureTrackerDataToFile(outFile) { numPats & 0xFF, (numPats >>> 8) & 0xFF, // numPatterns Uint16 LE bpmStored, // BPM with −24 bias tickRate, // initial tick-rate - 0x00,0x4C, // basenote (0x4C00 -- A3) - 0x00,0x00,0xDC,0x43, // basefreq (440 Hz) + 0x00,0x90, // basenote (0x9000 -- C8) + 0x00,0xAC,0x02,0x46, // basefreq (8363 Hz) 0, // padding ] diff --git a/s3m2taud.py b/s3m2taud.py index 527b740..0b8eae8 100644 --- a/s3m2taud.py +++ b/s3m2taud.py @@ -17,8 +17,9 @@ Effect support: table" and "ScreamTracker 3 conversion notes". ST3 shared-memory recalls (D/E/F/I/J/K/L/Q/R/S with $00 arg) are eagerly resolved per channel. Cxx is BCD-decoded. K/L are split into H $0000 / G $0000 + volume-column - slide. M/N/X/P fold into volume / pan columns. W (global vol slide) and - Y (panbrello) are dropped with a -v warning. + slide. M/N/X/P fold into volume / pan columns. W (global vol slide) is + dropped with a -v warning. X converts to pan column. Y (panbrello) converts + to Taud Y. S5 selects the panbrello LFO waveform. """ import argparse @@ -116,6 +117,7 @@ TOP_S = 0x1C # sub-effects TOP_T = 0x1D # tempo set/slide TOP_U = 0x1E # fine vibrato TOP_V = 0x1F # global volume +TOP_Y = 0x22 # panbrello # Volume / pan column selectors (2-bit field, packed into top of vol/pan byte). SEL_SET = 0 # 6-bit value: set vol / pan @@ -442,10 +444,13 @@ def encode_effect(cmd: int, arg: int, ch: int = 0, row: int = 0) -> tuple: val = arg & 0xF if sub in (0x1, 0x2, 0x3, 0x4, 0xB, 0xC, 0xD, 0xE, 0xF): return (TOP_S, (sub << 12) | (val << 8), None, None) + if sub == 0x5: + # Panbrello LFO waveform — maps directly to Taud S$5x00. + return (TOP_S, 0x5000 | (val << 8), None, None) if sub == 0x8: # Coarse pan: nibble-repeat into Taud's S $80xx full-8-bit pan. return (TOP_S, 0x8000 | (val * 0x11), None, None) - # S0/S5/S6/S7/S9/SA: filter, NNA, sound-control, stereo — drop silently. + # S0/S6/S7/S9/SA: filter, NNA, sound-control, stereo — drop silently. return (TOP_NONE, 0, None, None) if cmd == EFF_T: @@ -465,8 +470,9 @@ def encode_effect(cmd: int, arg: int, ch: int = 0, row: int = 0) -> tuple: return (TOP_NONE, 0, None, (SEL_SET, min(arg >> 2, 0x3F))) if cmd == EFF_Y: - vprint(f" dropped Y{arg:02X} (panbrello) at ch{ch} row{row}") - return (TOP_NONE, 0, None, None) + hi = (arg >> 4) & 0xF + lo = arg & 0xF + return (TOP_Y, ((hi * 0x11) << 8) | (lo * 0x11), None, None) if cmd == EFF_Z: return (TOP_NONE, 0, None, None) @@ -904,7 +910,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes: num_taud_pats_hi, bpm_stored, speed, - ) + b'\x00\x4C' + b'\x00\x00\xDC\x43' + b'\x00' + ) + b'\x00\x90' + b'\x00\xAC\xD02\x46' + b'\x00' assert len(song_table) == TAUD_SONG_ENTRY # Cue sheet (using remapped pattern indices) diff --git a/terranmon.txt b/terranmon.txt index c97d566..d0a0d8a 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -2211,16 +2211,21 @@ Endianness: Little Uint16 Number of patterns (0 is invalid. pattern bin length = numPats * 8 bytes) Uint8 Initial BPM (bias of -24. 0x00=24, 0xFF=279) Uint8 Initial Tickrate (0 is invalid) - Uint16 Current Tuning base note (1..65533). A3 (the default value) is 0x4C00. If zero, assume the default value - Float32 Frequency at the base note. Default (A440) is 440.0. If zero, assume the default value + Uint16 Current Tuning base note (1..65533). A3 (western default) is 0x4C00. C8 (tracker default) is 0x9000. If zero, assume the tracker default value + Float32 Frequency at the base note. Tracker default is 8363.0. If zero, assume the tracker default Byte[1] Reserved for future versions Taud device can queue up to 2 "playdata" in its buffer, which can be interpreted as a song. * Known standard tunings - A440. ISO standard. Tracker default + A440. ISO standard + A435. Former French standard (year 1859) + A452. Old Philharmonic pitch (19th century Britain) C256. Power of two - C311. East Asian tuning (ROK National Gugak Center standard) + C262. Modern Chinese a-ak tuning convention + C311. Korean hyang-ak tuning standard (ROK National Gugak Center) + + For your reference, tracker default tuning at A3 is 439.526 Hz (8363*2^(3/4) / 32) ## Pattern Bin and Cue Sheet Raw Pattern Bin/Cue Sheet images