From 3f98d25828137741bb08c12906125b8b90642c8e Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 25 Apr 2026 11:33:43 +0900 Subject: [PATCH] taut control and font changes --- TAUD_NOTE_EFFECTS.md | 52 ++++++------ assets/disk0/tvdos/bin/taut.js | 43 ++++++---- assets/disk0/tvdos/bin/tautfont.kra | 4 +- assets/disk0/tvdos/bin/tautfont_low.chr | Bin 1920 -> 1920 bytes assets/disk0/tvdos/bin/zfm.js | 4 +- assets/disk0/tvdos/include/keysym.mjs | 80 ++++++++++++++++++ .../torvald/tsvm/peripheral/AudioAdapter.kt | 1 + 7 files changed, 137 insertions(+), 47 deletions(-) create mode 100644 assets/disk0/tvdos/include/keysym.mjs diff --git a/TAUD_NOTE_EFFECTS.md b/TAUD_NOTE_EFFECTS.md index 60cadd9..1e4b9ac 100644 --- a/TAUD_NOTE_EFFECTS.md +++ b/TAUD_NOTE_EFFECTS.md @@ -753,33 +753,33 @@ NOTE: **`3.00` — is No-op** This table maps each PT effect to its Taud equivalent. Arguments follow PT's two-nibble form and expand to Taud's 16-bit form as shown. -| PT effect | Taud effect | Notes | -|---|---|---| +| PT effect | Taud effect | Notes | +|---|---|-------------------------------------------------------------------------------------------| | `0 $xy` | `J $xxyy` | Arpeggio; nibble-repeat each byte. See the 12-TET → Taud table above for conversion losses | -| `1 $xx` | `F round($0xxx × 64/3)` | Portamento up; ST3 coarse slide unit = 1/16 semitone | -| `2 $xx` | `E $0xxx × $0015` | Portamento down | -| `5 $xy` | `L $xy00` | Combined portamento + volume slide | -| `6 $xy` | `K $xy00` | Combined vibrato + volume slide | -| `7 $xy` | `R $xxyy` | Tremolo; nibble-repeat | -| `8 $xx` | `S $80xx` or panning column `0.$xx` | Fine pan | -| `9 $xx` | `O $xx00` | Sample offset | -| `A $xy` | Volume column `1.$xy` | Volume slide | -| `B $xx` | `B $00xx` | Position jump | -| `C $xx` | Volume column `0.$xx` | Set volume | -| `D $xx` | `C $00xx` (after BCD decode) | Pattern break | -| `E $3x` | `S $1x00` | Glissando control | -| `E $4x` | `S $3x00` | Vibrato waveform | -| `E $5x` | `S $2x00` | Set fine-tune | -| `E $6x` | `S $Bx00` | Pattern loop | -| `E $7x` | `S $4x00` | Tremolo waveform | -| `E $8x` | `S $80xx` or panning column `0.$xx` | Coarse pan (nibble-repeat) | -| `E $9x` | `Q $0x00` | Retrigger | -| `E $Cx` | `S $Cx00` | Note cut | -| `E $Dx` | `S $Dx00` | Note delay | -| `E $Ex` | `S $Ex00` | Pattern delay | -| `E $Fx` | `S $Fx00` | Funk repeat | -| `F $xx` (xx < $20) | `A $xx00` | Set speed | -| `F $xx` (xx ≥ $20) | `T $(xx−$18)00` | Set tempo | +| `1 $xx` | `F round($0xxx × 64/3)` | Portamento up; ST3 coarse slide unit = 1/16 semitone | +| `2 $xx` | `E round($0xxx × 64/3)` | Portamento down | +| `5 $xy` | `L $xy00` | Combined portamento + volume slide (see compatibility note) | +| `6 $xy` | `K $xy00` | Combined vibrato + volume slide (see compatibility note) | +| `7 $xy` | `R $xxyy` | Tremolo; nibble-repeat | +| `8 $xx` | `S $80xx` or panning column `0.$xx` | Fine pan | +| `9 $xx` | `O $xx00` | Sample offset | +| `A $xy` | Volume column `1.$xy` | Volume slide | +| `B $xx` | `B $00xx` | Position jump | +| `C $xx` | Volume column `0.$xx` | Set volume | +| `D $xx` | `C $00xx` (after BCD decode) | Pattern break | +| `E $3x` | `S $1x00` | Glissando control | +| `E $4x` | `S $3x00` | Vibrato waveform | +| `E $5x` | `S $2x00` | Set fine-tune | +| `E $6x` | `S $Bx00` | Pattern loop | +| `E $7x` | `S $4x00` | Tremolo waveform | +| `E $8x` | `S $80xx` or panning column `0.$xx` | Coarse pan (nibble-repeat) | +| `E $9x` | `Q $0x00` | Retrigger | +| `E $Cx` | `S $Cx00` | Note cut | +| `E $Dx` | `S $Dx00` | Note delay | +| `E $Ex` | `S $Ex00` | Pattern delay | +| `E $Fx` | `S $Fx00` | Funk repeat | +| `F $xx` (xx < $20) | `A $xx00` | Set speed | +| `F $xx` (xx ≥ $20) | `T $(xx−$18)00` | Set tempo | --- diff --git a/assets/disk0/tvdos/bin/taut.js b/assets/disk0/tvdos/bin/taut.js index edca9d5..7201dc0 100644 --- a/assets/disk0/tvdos/bin/taut.js +++ b/assets/disk0/tvdos/bin/taut.js @@ -7,6 +7,7 @@ const win = require("wintex") const font = require("font") const taud = require("taud") +const keys = require("keysym") font.setLowRom("A:/tvdos/bin/tautfont_low.chr") font.setHighRom("A:/tvdos/bin/tautfont_high.chr") @@ -472,7 +473,7 @@ function drawStatusBar() { fillLine(1, colStatus, 255) const maxCue = song.lastActiveCue < 0 ? 0 : song.lastActiveCue const vHi = Math.min(voiceOff + VOCSIZE, song.numVoices) - const txt = `${song.filePath} Cue ${cueIdx.hex03()}/${maxCue.hex03()} Row ${cursorRow.dec02()} V${(voiceOff+1).dec02()}-${vHi.dec02()}/${song.numVoices.dec02()} BPM ${song.bpm} Spd ${song.tickRate} ` + const txt = `${song.filePath} Cue ${cueIdx.hex03()}/${maxCue.hex03()} Row ${cursorRow.dec02()} V${(voiceOff+1).dec02()}-${vHi.dec02()}/${song.numVoices.dec02()} BPM ${audio.getBPM(PLAYHEAD)} Spd ${audio.getTickRate(PLAYHEAD)} ` con.move(1, 1) con.color_pair(colStatus, 255) print(txt) @@ -574,10 +575,10 @@ function drawControlHint() { [`\u008428u\u008429u`,'Ptn'], [`Pg\u008418u`,'Cue'], ['sep'], - ['F5','Song'], - ['F6','Cue'], - ['F7','Row'], - ['F8/Sp','Stop'], + ['Y','Song'], + ['U','Cue'], + ['I','Row'], + ['O/Sp','Stop'], ['sep'], ['m','Mute'], ['s','Solo'], @@ -796,6 +797,12 @@ const song = loadTaud(fullPathObj.full, 0) const voiceMutes = new Array(NUM_VOICES).fill(false) +function resetAudioDevice() { + audio.resetParams(PLAYHEAD) + audio.purgeQueue(PLAYHEAD) + audio.stop(PLAYHEAD) +} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // PLAYBACK STATE ///////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -951,9 +958,7 @@ function clampCue() { clampCursor(); clampVoice(); clampCue() drawAll() -audio.resetParams(PLAYHEAD) -audio.purgeQueue(PLAYHEAD) -audio.stop(PLAYHEAD) +resetAudioDevice() taud.uploadTaudFile(fullPathObj.full, 0, PLAYHEAD) audio.setMasterVolume(PLAYHEAD, 255) audio.setMasterPan(PLAYHEAD, 128) @@ -963,7 +968,9 @@ while (!exitFlag) { input.withEvent(event => { if (event[0] !== "key_down") return const keysym = event[1] - const shiftDown = (event.indexOf(59) > 0 || event.indexOf(60) > 0) + const keyJustHit = (1 == event[2]) + const shiftDown = (event.includes(59) || event.includes(60)) + const moveDelta = shiftDown ? 4 : 1 if (keysym === "" || keysym === "q" || keysym === "Q") { @@ -972,7 +979,7 @@ while (!exitFlag) { } if (playbackMode !== PLAYMODE_NONE) { - if (keysym === "" || keysym === " ") { stopPlayback(); drawAll() } + if (keyJustHit && shiftDown && event.includes(keys.Y) || keysym === " ") { stopPlayback(); drawAll() } else if (keysym === "" || keysym === "") { const oldVoiceOff = voiceOff cursorVox += (keysym === "") ? -moveDelta : moveDelta @@ -987,15 +994,15 @@ while (!exitFlag) { drawStatusBar() drawVoiceDetail() } - else if (keysym === "m" || keysym === "M") { toggleMute(cursorVox) } - else if (keysym === "s" || keysym === "S") { toggleSolo(cursorVox) } + else if (keyJustHit && !shiftDown && event.includes(keys.M)) { toggleMute(cursorVox) } + else if (keyJustHit && !shiftDown && event.includes(keys.S)) { toggleSolo(cursorVox) } return } - if (keysym === "") { startPlaySong(); drawAll(); return } - if (keysym === "") { startPlayCue(); drawAll(); return } - if (keysym === "") { startPlayRow(); drawPatternRowAt(cursorRow - scrollRow); return } - if (keysym === "" || keysym === " ") { stopPlayback(); return } + if (keyJustHit && shiftDown && event.includes(keys.Y)) { startPlaySong(); drawAll(); return } + if (keyJustHit && shiftDown && event.includes(keys.U)) { startPlayCue(); drawAll(); return } + if ( shiftDown && event.includes(keys.I)) { startPlayRow(); drawPatternRowAt(cursorRow - scrollRow); return } // allow multiple plays by holding the keys down + if (keyJustHit && shiftDown && event.includes(keys.O) || keysym === " ") { stopPlayback(); return } const oldCursor = cursorRow const oldScroll = scrollRow @@ -1018,8 +1025,8 @@ while (!exitFlag) { return } - if (keysym === "m" || keysym === "M") { toggleMute(cursorVox); return } - if (keysym === "s" || keysym === "S") { toggleSolo(cursorVox); return } + if (keyJustHit && !shiftDown && event.includes(keys.M)) { toggleMute(cursorVox); return } + if (keyJustHit && !shiftDown && event.includes(keys.S)) { toggleSolo(cursorVox); return } if (keysym === "") { cursorRow -= moveDelta; rowMove = true } else if (keysym === "") { cursorRow += moveDelta; rowMove = true } diff --git a/assets/disk0/tvdos/bin/tautfont.kra b/assets/disk0/tvdos/bin/tautfont.kra index 5c0ca3c..3336916 100644 --- a/assets/disk0/tvdos/bin/tautfont.kra +++ b/assets/disk0/tvdos/bin/tautfont.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:949811c18c96b615e96982bb4386437b3b4725ccefdd9d28a8e9dde4777cdf92 -size 89865 +oid sha256:a856f6db73214d8cd42a4d23b395ee65237ca840a180f713d90be4c0bf427d24 +size 89835 diff --git a/assets/disk0/tvdos/bin/tautfont_low.chr b/assets/disk0/tvdos/bin/tautfont_low.chr index d03fe8195ec030e11f992e7c2426459749ac088e..85a3b18f284fe5de8371a01f9ee655f9224aea2a 100644 GIT binary patch delta 21 dcmZqRZ{Xjsh?%J(XYvwe7skBJFPWz^0{~Hc2Y>(o delta 21 dcmZqRZ{Xjsh?%J-ZSoRk7sj;BFPWz^0{~Gt2X+7e diff --git a/assets/disk0/tvdos/bin/zfm.js b/assets/disk0/tvdos/bin/zfm.js index 5c9d231..63471e9 100644 --- a/assets/disk0/tvdos/bin/zfm.js +++ b/assets/disk0/tvdos/bin/zfm.js @@ -1,4 +1,6 @@ const win = require("wintex") +const keys = require("keysym") + const COL_TEXT = 253 const COL_BACK = 255 const COL_BACK_SEL = 81 @@ -673,7 +675,7 @@ while (!exit) { let keysym = event[1] let keyJustHit = (1 == event[2]) - if (keyJustHit && event[3] != 66) { // release the latch right away if the key is not Return + if (keyJustHit && event[3] != keys.ENTER) { // release the latch right away if the key is not Return firstRunLatch = false } diff --git a/assets/disk0/tvdos/include/keysym.mjs b/assets/disk0/tvdos/include/keysym.mjs new file mode 100644 index 0000000..5538351 --- /dev/null +++ b/assets/disk0/tvdos/include/keysym.mjs @@ -0,0 +1,80 @@ +/** + * These are key symbols returned by `input.withEvent`, NOT `con.getch()` + */ + +exports = { +NUM_0:7, +NUM_1:8, +NUM_2:9, +NUM_3:10, +NUM_4:11, +NUM_5:12, +NUM_6:13, +NUM_7:14, +NUM_8:15, +NUM_9:16, +A:29, +ALT_LEFT:57, +ALT_RIGHT:58, +APOSTROPHE:75, +AT:77, +B:30, +BACK:4, +BACKSLASH:73, +C:31, +CAPS_LOCK:115, +COMMA:55, +D:32, +DEL:67, +BACKSPACE:67, +FORWARD_DEL:112, +DOWN:20, +LEFT:21, +RIGHT:22, +UP:19, +E:33, +ENTER:66, +EQUALS:70, +F:34, +G:35, +GRAVE:68, +H:36, +HOME:3, +I:37, +J:38, +K:39, +L:40, +LEFT_BRACKET:71, +M:41, +MINUS:69, +N:42, +O:43, +P:44, +PERIOD:56, +PLUS:81, +Q:45, +R:46, +RIGHT_BRACKET:72, +S:47, +SEMICOLON:74, +SHIFT_LEFT:59, +SHIFT_RIGHT:60, +SLASH:76, +SPACE:62, +SYM:63, // on MacOS, this is Command (⌘) +T:48, +TAB:61, +U:49, +V:50, +W:51, +X:52, +Y:53, +Z:54, +CONTROL_LEFT:129, +CONTROL_RIGHT:130, +ESCAPE:111, +END:123, +INSERT:124, +PAGE_UP:92, +PAGE_DOWN:93, +} diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/AudioAdapter.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/AudioAdapter.kt index 3714d8a..c5a96be 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/AudioAdapter.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/AudioAdapter.kt @@ -2121,6 +2121,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) { it.funkSpeed = 0 it.funkAccumulator = 0 it.funkWritePos = 0 + it.muted = false } } }