TVDOS: userconfigpath and zfmrc

This commit is contained in:
minjaesong
2026-05-17 00:12:18 +09:00
parent e6f77c4789
commit 61524b3685
6 changed files with 86 additions and 13 deletions

View File

@@ -3,6 +3,7 @@ echo "Starting TVDOS..."
rem put set-xxx commands here: rem put set-xxx commands here:
set PATH=\tvdos\installer;\tvdos\tuidev;\tbas;\hopper\bin;$PATH set PATH=\tvdos\installer;\tvdos\tuidev;\tbas;\hopper\bin;$PATH
set INCLPATH=\hopper\include;$INCLPATH set INCLPATH=\hopper\include;$INCLPATH
set HELPPATH=\hopper\help;$HELPPATH
set KEYBOARD=us_colemak set KEYBOARD=us_colemak
rem this line specifies which shell to be presented after the boot precess: rem this line specifies which shell to be presented after the boot precess:

View File

@@ -151,7 +151,8 @@ _TVDOS.variables = {
PATHEXT: ".com;.bat;.app;.js;.alias", PATHEXT: ".com;.bat;.app;.js;.alias",
HELPPATH: "\\tvdos\\help", HELPPATH: "\\tvdos\\help",
OS_NAME: "TSVM Disk Operating System", OS_NAME: "TSVM Disk Operating System",
OS_VERSION: _TVDOS.VERSION OS_VERSION: _TVDOS.VERSION,
USERCONFIGPATH: "\\home\\config",
}; };
Object.freeze(_TVDOS); Object.freeze(_TVDOS);

View File

@@ -823,17 +823,26 @@ shell.execute = function(line, nameOverride) {
// parse alias // parse alias
// $0: all arguments // $0: all arguments
// $1..9: specific arguments // $1..9: specific arguments
// Tokens that contain whitespace or shell metacharacters must be re-quoted
// before re-execution, otherwise the re-parse splits them on spaces.
var quoteAliasArg = function(s) {
if (s === undefined || s === null) return ""
s = ''+s
if (s.length === 0) return ""
if (/[\s"|><&]/.test(s)) return '"' + s.replaceAll('"', '^"') + '"'
return s
}
var lines = programCode.split('\n').filter(function(it) { return it.length > 0 }) // this return is not shell's return! var lines = programCode.split('\n').filter(function(it) { return it.length > 0 }) // this return is not shell's return!
lines.forEach(function(line) { lines.forEach(function(line) {
var newLine = line var newLine = line
// replace $1..$9 // replace $1..$9
for (let j = 1; j < 9; j++) { for (let j = 1; j <= 9; j++) {
newLine = newLine.replaceAll('$'+j, tokens[j]) newLine = newLine.replaceAll('$'+j, quoteAliasArg(tokens[j]))
} }
// replace $0 // replace $0
newLine = newLine.replaceAll('$0', tokens.slice(1).join(' ')) newLine = newLine.replaceAll('$0', tokens.slice(1).map(quoteAliasArg).join(' '))
shell.execute(newLine, cmd) shell.execute(newLine, cmd)
}) })
@@ -955,6 +964,18 @@ _G.shell = shell
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ensure USERCONFIGPATH directory exists
try {
let userConfigPath = `${CURRENT_DRIVE}:${_TVDOS.variables.USERCONFIGPATH}`
let userConfigDir = files.open(userConfigPath)
if (!userConfigDir.exists) {
debugprintln(`command.js > creating USERCONFIGPATH at ${userConfigPath}`)
userConfigDir.mkDir()
}
} catch (e) {
debugprintln("command.js > USERCONFIGPATH creation failed: " + e.message)
}
if (exec_args[1] !== undefined) { if (exec_args[1] !== undefined) {
// only meaningful switches would be either -c or -k anyway // only meaningful switches would be either -c or -k anyway
var firstSwitch = exec_args[1].toLowerCase() var firstSwitch = exec_args[1].toLowerCase()

View File

@@ -307,7 +307,7 @@ for (let i = 0; i < cueElements.length; i++) {
// Execute the player with modified environment // Execute the player with modified environment
exec_args[1] = targetPath exec_args[1] = targetPath
if (playerFile) { if (playerFile) {
let playerPath = `A:\\tvdos\\bin\\${playerFile}.js` let playerPath = `A:${_TVDOS.variables.DOSDIR}/bin/${playerFile}.js`
if (files.open(playerPath).exists) { if (files.open(playerPath).exists) {
eval(files.readText(playerPath)) eval(files.readText(playerPath))
} else { } else {
@@ -334,7 +334,7 @@ for (let i = 0; i < cueElements.length; i++) {
} }
// Execute the appropriate player // Execute the appropriate player
let playerPath = `A:\\tvdos\\bin\\${playerFile}.js` let playerPath = `A:${_TVDOS.variables.DOSDIR}/bin/${playerFile}.js`
if (!files.open(playerPath).exists) { if (!files.open(playerPath).exists) {
serial.println(`Warning: Player script not found: ${playerPath}`) serial.println(`Warning: Player script not found: ${playerPath}`)
continue continue

View File

@@ -1745,18 +1745,18 @@ if (fullPathObj === undefined) {
return 1 return 1
} }
const logofile = files.open("A:/tvdos/bin/tauthdr.r8") const logofile = files.open("A:"+_TVDOS.variables.DOSDIR+"/bin/tauthdr.r8")
const logoBytes = logofile.bread(); logofile.close() const logoBytes = logofile.bread(); logofile.close()
const logoTexture = new gl.Texture(92, 14, logoBytes) const logoTexture = new gl.Texture(92, 14, logoBytes)
const buttonfile = files.open("A:/tvdos/bin/tautbtn.r8") const buttonfile = files.open("A:"+_TVDOS.variables.DOSDIR+"/bin/tautbtn.r8")
const buttonBytes = buttonfile.bread(); buttonfile.close() const buttonBytes = buttonfile.bread(); buttonfile.close()
const buttonTexture = new gl.Texture(2, 28, buttonBytes) const buttonTexture = new gl.Texture(2, 28, buttonBytes)
//const buttonNullfile = files.open("A:/tvdos/bin/tautbtn0.r8") //const buttonNullfile = files.open("A:"+_TVDOS.variables.DOSDIR+"/bin/tautbtn0.r8")
//const buttonNullBytes = buttonNullfile.bread(); buttonNullfile.close() //const buttonNullBytes = buttonNullfile.bread(); buttonNullfile.close()
//const buttonNullTexture = new gl.Texture(35, 28, buttonNullBytes) //const buttonNullTexture = new gl.Texture(35, 28, buttonNullBytes)
font.setLowRom("A:/tvdos/bin/tautfont_low.chr") font.setLowRom("A:"+_TVDOS.variables.DOSDIR+"/bin/tautfont_low.chr")
font.setHighRom("A:/tvdos/bin/tautfont_high.chr") font.setHighRom("A:"+_TVDOS.variables.DOSDIR+"/bin/tautfont_high.chr")
const songsMeta = loadTaudSongList(fullPathObj.full) const songsMeta = loadTaudSongList(fullPathObj.full)
let currentSongIndex = 0 let currentSongIndex = 0
let projectSongCursor = 0 let projectSongCursor = 0

View File

@@ -69,6 +69,55 @@ const EXEC_FUNS = {
"taud": (f) => _G.shell.execute(`microtone "${f}"`), "taud": (f) => _G.shell.execute(`microtone "${f}"`),
} }
function makeExecFun(template) {
return (f) => _G.shell.execute(template.replaceAll("{0}", `"${f}"`))
}
function loadZfmrc() {
try {
let zfmrcPath = `A:${_TVDOS.variables.USERCONFIGPATH}\\zfmrc`
let zfmrcFile = files.open(zfmrcPath)
if (!zfmrcFile.exists) return
let content = zfmrcFile.sread()
let lines = content.split(/\r?\n/)
let currentSection = null
for (let i = 0; i < lines.length; i++) {
let line = lines[i].trim()
if (line.length === 0 || line.startsWith("#") || line.startsWith(";")) continue
if (line.startsWith("[") && line.endsWith("]")) {
currentSection = line.substring(1, line.length - 1).toUpperCase()
continue
}
if (currentSection === "EXEC_FUNS") {
let commaIdx = line.indexOf(",")
if (commaIdx < 0) continue
let ext = line.substring(0, commaIdx).trim().toLowerCase()
let template = line.substring(commaIdx + 1).trim()
if (ext.length === 0 || template.length === 0) continue
EXEC_FUNS[ext] = makeExecFun(template)
}
else if (currentSection === "COL_HL_EXT") {
let commaIdx = line.indexOf(",")
if (commaIdx < 0) continue
let ext = line.substring(0, commaIdx).trim().toLowerCase()
let colStr = line.substring(commaIdx + 1).trim()
if (ext.length === 0 || colStr.length === 0) continue
let col = parseInt(colStr, 10)
if (isNaN(col)) continue
COL_HL_EXT[ext] = col
}
}
} catch (e) {
serial.println("zfm: failed to load zfmrc: " + e.message)
}
}
loadZfmrc()
let windowMode = 0 // 0 == left, 1 == right let windowMode = 0 // 0 == left, 1 == right
let windowFocus = [0] // is a stack; 0: files window, 1: palette window, 2: popup window let windowFocus = [0] // is a stack; 0: files window, 1: palette window, 2: popup window
@@ -82,6 +131,7 @@ let cursor = [0, 0] // absolute position!
function bytesToReadable(i) { function bytesToReadable(i) {
return ''+ ( return ''+ (
(i > 999999999999) ? (((i / 10000000000)|0)/100 + "T") :
(i > 999999999) ? (((i / 10000000)|0)/100 + "G") : (i > 999999999) ? (((i / 10000000)|0)/100 + "G") :
(i > 999999) ? (((i / 10000)|0)/100 + "M") : (i > 999999) ? (((i / 10000)|0)/100 + "M") :
(i > 9999) ? (((i / 100)|0)/10 + "K") : (i > 9999) ? (((i / 100)|0)/10 + "K") :
@@ -677,11 +727,11 @@ while (!exit) {
let keysym = event[1] let keysym = event[1]
let keyJustHit = (1 == event[2]) let keyJustHit = (1 == event[2])
if (keyJustHit && event[3] != keys.ENTER) { // release the latch right away if the key is not Return if (keyJustHit && event[3] != keys.ENTER && keysym != "q") { // release the latch right away if the key is neither Return nor 'q'
firstRunLatch = false firstRunLatch = false
} }
if (keyJustHit && firstRunLatch) { // filter out the initial ENTER key as they would cause unwanted behaviours if (keyJustHit && firstRunLatch) { // filter out the initial ENTER/'q' key as they would cause unwanted behaviours
firstRunLatch = false firstRunLatch = false
} }
else { else {