From 44f11120d815c1943e2958b68d0911fac9bffa22 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Thu, 23 Apr 2026 14:47:53 +0900 Subject: [PATCH] tightening formats --- assets/disk0/tvdos/include/taud.mjs | 12 +++++++----- s3m2taud.py | 12 ++++++------ terranmon.txt | 23 +++++++++++------------ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/assets/disk0/tvdos/include/taud.mjs b/assets/disk0/tvdos/include/taud.mjs index 6d7ae7a..83a0817 100644 --- a/assets/disk0/tvdos/include/taud.mjs +++ b/assets/disk0/tvdos/include/taud.mjs @@ -16,8 +16,8 @@ const NUM_PATTERNS_MAX = 256 const NUM_CUES = 1024 const CUE_SIZE = 32 // bytes per cue entry (packed 12-bit×20 voices + instruction + pad) -// Signature written into the file (16 bytes, space-padded) -const CAPTURE_SIGNATURE = "LibTaud/TSVM " +// Signature written into the file (14 bytes, space-padded) +const CAPTURE_SIGNATURE = "LibTaud/TSVM " // ── Internal helpers ──────────────────────────────────────────────────────── @@ -205,8 +205,8 @@ function captureTrackerDataToFile(outFile) { (compressedSize >>> 8) & 0xFF, (compressedSize >>> 16) & 0xFF, (compressedSize >>> 24) & 0xFF, - // reserved (2) - 0x00, 0x00, + // reserved (4) + 0x00, 0x00, 0x00, 0x00, ].concat(sigBytes) // 8 + 2 + 4 + 2 + 16 = 32 bytes // -- 6. Build song-table row (16 bytes) ----------------------------------- @@ -219,7 +219,9 @@ function captureTrackerDataToFile(outFile) { numPats & 0xFF, (numPats >>> 8) & 0xFF, // numPatterns Uint16 LE bpmStored, // BPM with −24 bias tickRate, // initial tick-rate - 0,0,0,0,0,0,0, // 7 bytes padding + 0x40,0, // basenote + 0x13,0xd0,0x82,0x43, // basefreq + 0, // padding ] // -- 7. Write header (creates / truncates file) --------------------------- diff --git a/s3m2taud.py b/s3m2taud.py index b2714b0..fc056c7 100644 --- a/s3m2taud.py +++ b/s3m2taud.py @@ -87,7 +87,7 @@ NUM_PATTERNS_MAX = 4095 NUM_CUES = 1024 CUE_SIZE = 32 # packed 12-bit×20 voices + instruction + pad NUM_VOICES = 20 -SIGNATURE = b"s3m2taud/TSVM " # 16 bytes +SIGNATURE = b"s3m2taud/TSVM " # 14 bytes # Taud note constants NOTE_NOP = 0xFFFF @@ -860,13 +860,13 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes: song_offset = TAUD_HEADER_SIZE + comp_size + TAUD_SONG_ENTRY num_taud_pats = P * C - # Header (32 bytes): magic(8)+ver(1)+numSongs(1)+compSize(4)+rsvd(2)+sig(16) - sig = (SIGNATURE + b' ' * 16)[:16] + # Header (32 bytes): magic(8)+ver(1)+numSongs(1)+compSize(4)+rsvd(4)+sig(14) + sig = (SIGNATURE + b' ' * 14)[:14] header = ( TAUD_MAGIC + bytes([TAUD_VERSION, 1]) + struct.pack(' bytes: pat_bin, pat_remap, num_taud_pats = deduplicate_patterns(bytes(pat_bin), orig_count) vprint(f" patterns: {orig_count} → {num_taud_pats} unique ({orig_count - num_taud_pats} deduplicated)") - # Song table row (16 bytes): offset(4)+voices(1)+patsLo(1)+patsHi(1)+bpm(1)+tick(1)+pad(7) + # Song table row (16 bytes): offset(4)+voices(1)+patsLo(1)+patsHi(1)+bpm(1)+tick(1)+basenote(2)+basefreq(4)+pad(1) # Built after dedup so num_taud_pats reflects the unique count. num_taud_pats_lo = num_taud_pats & 0xFF num_taud_pats_hi = (num_taud_pats >> 8) & 0xFF @@ -904,7 +904,7 @@ def assemble_taud(h: S3MHeader, instruments: list, patterns: list) -> bytes: num_taud_pats_hi, bpm_stored, speed, - ) + b'\x00' * 7 + ) + b'\x40\x00' + b'\x13\xd0\x82\x43' + b'\x00' assert len(song_table) == TAUD_SONG_ENTRY # Cue sheet (using remapped pattern indices) diff --git a/terranmon.txt b/terranmon.txt index 7d4dcd2..603aad4 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -2200,8 +2200,8 @@ Endianness: Little Uint8 Format version (always 1) Uint8 Number of songs in SONG TABLE Uint32 Compressed size of SAMPLE+INST section (used to calculate offset to SONG TABLE) - Uint16 Reserved for future versions - Byte[16]Tracker/Converter signature + Uint32 Reserved for Taud Project Format. Fill with zero + Byte[14]Tracker/Converter signature ## SONG TABLE Rows of 16 bytes: @@ -2210,7 +2210,7 @@ Rows of 16 bytes: 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-4094), assuming octave 3. C3 (the default value) is 0x4000. If zero, assume the default value + Uint16 Current Tuning base note (1..65533), assuming octave 3. C3 (the default value) is 0x4000. If zero, assume the default value Float32 Frequency at the base note. Default (A440) is 261.6255653. If zero, assume the default value Byte[1] Reserved for future versions @@ -2239,12 +2239,11 @@ Endianness: Little ## Header Byte[8] Magic - Uint8 Format version (always 129) + Uint8 Format version (always 129; high-bit set and number 0x01) Uint8 Number of songs in SONG TABLE Uint32 Compressed size of SAMPLE+INST section (used to calculate offset to SONG TABLE) - Uint16 Offset to Project Data (low twobyte) + Uint32 Offset to Project Data (low twobyte) Byte[14]Tracker/Converter signature - Uint16 Offset to Project Data (high twobyte) ## Project Data Byte[8] Magic (\x1E T a u d P r J) @@ -2268,11 +2267,11 @@ prefixes: * PCpr. Project copyright string. Encoding: UTF-8 * PNam. Project name. Encoding: UTF-8 -* INam. Instrument name table. Strings separated by comma +* INam. Instrument name table. Strings separated by 0x1E -* pNam. Pattern name table. Strings separated by comma +* pNam. Pattern name table. Strings separated by 0x1E -* SNam. Sample name table. Strings separated by comma +* SNam. Sample name table. Strings separated by 0x1E * sMet. Song metadata table * Repetition of: @@ -2288,15 +2287,15 @@ prefixes: Uint8 Notation index (starting from zero) used by songs Uint32 Size of this notation following this field Uint8 Flags - 0b nnnn 000t + 0b 0000 000t t: NOT using interval system (you are responsible for defining every notes expressible) Uint8 Reserved Float32 Interval size (octave system = 2.0f). If Flag 't' is set, this must be NaN. 0f and Infinity are considered illegal Uint16 Notes between interval MINUS ONE (or octave); 12-TET will have value 11. 0 is considered illegal Byte[8] Reserved Byte[*] Name, null terminated. Encoding: UTF-8 - Byte[*] Notation table. Comma-separated and null-terminated. Encoding: raw bytes - Uint16[*] Frequency table. Size of the table is defined by "Notes between interval MINUS ONE". All relative to the base note (Song table will be referred), in 4096-TET note number. Index zero of this table will be 0x0 if you read the spec right + Byte[*] Notation table. 0xFF-separated and null-terminated. Encoding: raw bytes + Uint16[*] Frequency table. Size of the table is defined by "Notes between interval MINUS ONE". This is a lookup table of relative pitch offsets (against the base tuning note) in 4096-TET space. Index zero of this table will be 0x0 if you read the spec right Note: custom notations will use internal index 65535 down to 65520 (index 0 = 65535, index 15 = 65520)