mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
command.js:fix:errorlevel not returned; playwav:interactive mode
This commit is contained in:
@@ -5,7 +5,7 @@ let shell_pwd = [""]
|
||||
let goInteractive = false
|
||||
let goFancy = false
|
||||
|
||||
let DEBUG_PRINT = false
|
||||
let DEBUG_PRINT = true
|
||||
|
||||
let errorlevel = 0
|
||||
|
||||
@@ -318,29 +318,29 @@ shell.resolvePathInput = function(input) {
|
||||
}
|
||||
|
||||
|
||||
debugprintln("command.js > resolvePathInput > sanitised input: "+pathstr)
|
||||
// debugprintln("command.js > resolvePathInput > sanitised input: "+pathstr)
|
||||
|
||||
let startsWithSlash = pathstr.startsWith('/')
|
||||
let newPwd = []
|
||||
|
||||
debugprintln("command.js > resolvePathInput > path starts with slash: "+startsWithSlash)
|
||||
// debugprintln("command.js > resolvePathInput > path starts with slash: "+startsWithSlash)
|
||||
|
||||
// split them into an array while filtering empty elements except for the root 'head'
|
||||
let ipwd = (startsWithSlash ? [""] : shell_pwd).concat(pathstr.split("/").filter(function(it) { return (it.length > 0); }))
|
||||
|
||||
debugprintln("command.js > resolvePathInput > ipwd = "+ipwd)
|
||||
debugprintln("command.js > resolvePathInput > newPwd = "+newPwd)
|
||||
// debugprintln("command.js > resolvePathInput > ipwd = "+ipwd)
|
||||
// debugprintln("command.js > resolvePathInput > newPwd = "+newPwd)
|
||||
|
||||
// process dots
|
||||
ipwd.forEach(function(it) {
|
||||
debugprintln("command.js > resolvePathInput > ipwd.forEach > it = "+it)
|
||||
// debugprintln("command.js > resolvePathInput > ipwd.forEach > it = "+it)
|
||||
if (it === ".." && newPwd[1] !== undefined) {
|
||||
newPwd.pop()
|
||||
}
|
||||
else if (it !== ".." && it !== ".") {
|
||||
newPwd.push(it)
|
||||
}
|
||||
debugprintln("command.js > resolvePathInput > newPwd = "+newPwd)
|
||||
// debugprintln("command.js > resolvePathInput > newPwd = "+newPwd)
|
||||
})
|
||||
|
||||
// construct new pathstr from pwd arr so it will be sanitised
|
||||
@@ -631,6 +631,14 @@ shell.execute = function(line) {
|
||||
|
||||
let retValue = undefined // return value of the previous statement
|
||||
for (let c = 0; c < statements.length; c++) {
|
||||
let tokens = statements[c]
|
||||
|
||||
|
||||
if (retValue) {
|
||||
debugprintln(`[shell.execute] previous statement "${tokens.join(' ')}" had non-zero errorlevel: ${retValue}, raising error...`)
|
||||
return retValue
|
||||
}
|
||||
|
||||
let op = operators[c]
|
||||
|
||||
// TODO : if operator is not undefined, swap built-in print functions with ones that 'prints' on pipes instead of stdout
|
||||
@@ -653,8 +661,6 @@ shell.execute = function(line) {
|
||||
|
||||
|
||||
|
||||
let tokens = statements[c]
|
||||
|
||||
let cmd = tokens[0]
|
||||
if (cmd === undefined || cmd === '') {
|
||||
retValue = 0
|
||||
@@ -694,9 +700,7 @@ shell.execute = function(line) {
|
||||
let search = searchDir[i]; if (!search.endsWith('\\')) search += '\\'
|
||||
searchPath = trimStartRevSlash(search + cmd + pathExt[j])
|
||||
|
||||
if (DEBUG_PRINT) {
|
||||
debugprintln("[command.js > shell.execute] file search path: "+searchPath)
|
||||
}
|
||||
// debugprintln("[shell.execute] file search path: "+searchPath)
|
||||
|
||||
searchFile = files.open(`${CURRENT_DRIVE}:\\${searchPath}`)
|
||||
if (searchFile.exists) {
|
||||
@@ -736,6 +740,7 @@ shell.execute = function(line) {
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1])
|
||||
//serial.println(_G.shellProgramTitles)
|
||||
|
||||
debugprintln("[shell.execute] exec app " + searchFile.fullPath)
|
||||
errorlevel = execApp(programCode, tokens, `tvdosExec$${cmd}$${searchPath}`.replaceAll(/[^A-Za-z0-9_]/g, "$")) // return value of undefined will cast into 0
|
||||
}
|
||||
catch (e) {
|
||||
@@ -754,11 +759,13 @@ shell.execute = function(line) {
|
||||
errorlevel = 1
|
||||
}
|
||||
finally {
|
||||
debugprintln("[shell.execute] exec app " + searchFile.fullPath + "exit with no exception; errorlevel = " + errorlevel)
|
||||
|
||||
// sometimes no-error program may return nothing as the errorlevel; force set to 0 then.
|
||||
if (!gotError && (errorlevel == undefined || (typeof errorlevel.trim == "function" && errorlevel.trim().length == 0) || isNaN(errorlevel)))
|
||||
errorlevel = 0
|
||||
|
||||
debugprintln(`errorlevel: ${errorlevel}`)
|
||||
debugprintln(`[shell.execute] errorlevel: ${errorlevel}`)
|
||||
|
||||
_G.shellProgramTitles.pop()
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1])
|
||||
@@ -777,10 +784,9 @@ shell.execute = function(line) {
|
||||
debugprintln(`Statement #${c+1}: destroying pipe`)
|
||||
debugprintln(`its content was: ${shell.removePipe()}`)
|
||||
}
|
||||
|
||||
|
||||
return retValue
|
||||
}
|
||||
serial.println("[shell.execute] final retvalue: "+retValue)
|
||||
return retValue
|
||||
}
|
||||
shell.pipes = {} // syntax: _G.shell.pipes[name] = contents; all pipes are named pipes just like in Windows
|
||||
shell.currentlyActivePipes = [] // Queue of pipe's names. Use shell.removePipe() to dequeue and shell.pushPipe() to enqueue.
|
||||
@@ -887,7 +893,7 @@ if (goInteractive) {
|
||||
else if (key === 10 || key === con.KEY_RETURN) {
|
||||
println()
|
||||
|
||||
shell.execute(cmdbuf)
|
||||
errorlevel = shell.execute(cmdbuf)
|
||||
|
||||
if (cmdbuf.trim().length > 0)
|
||||
cmdHistory.push(cmdbuf)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// some manual configurations
|
||||
//
|
||||
let IPFMODE = 2 // 1 or 2
|
||||
let TOTAL_FRAMES = 3813
|
||||
let TOTAL_FRAMES = 1318
|
||||
let FPS = 30
|
||||
let WIDTH = 560
|
||||
let HEIGHT = 448
|
||||
let PATHFUN = (i) => `/ddol2/${(''+i).padStart(5,'0')}.bmp` // how can be the image file found, if a frame number (starts from 1) were given
|
||||
let AUDIOTRACK = 'ddol.pcm'
|
||||
let PATHFUN = (i) => `/namu2/${(''+i).padStart(5,'0')}.png` // how can be the image file found, if a frame number (starts from 1) were given
|
||||
let AUDIOTRACK = 'namu.u8'
|
||||
// to export video to its frames:
|
||||
// ffmpeg -i file.mp4 file/%05d.bmp
|
||||
// the input frames must be resized (and cropped) beforehand, using ImageMagick is recommended, like so:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
// usage: playmov moviefile.mov [/i]
|
||||
const interactive = exec_args[2].toLowerCase() == "/i"
|
||||
const WIDTH = 560
|
||||
const HEIGHT = 448
|
||||
const FBUF_SIZE = WIDTH * HEIGHT
|
||||
@@ -80,22 +81,43 @@ function getRGBfromScr(x, y) {
|
||||
}
|
||||
|
||||
let oldBgcol = [0.0, 0.0, 0.0]
|
||||
|
||||
let stopPlay = false
|
||||
if (interactive) {
|
||||
con.move(1,1)
|
||||
println("Push and hold Backspace to exit")
|
||||
}
|
||||
let notifHideTimer = 0
|
||||
const NOTIF_SHOWUPTIME = 2000000000
|
||||
let [cy, cx] = con.getyx()
|
||||
let t1 = sys.nanoTime()
|
||||
renderLoop:
|
||||
while (seqread.getReadCount() < FILE_LENGTH) {
|
||||
let t1 = sys.nanoTime()
|
||||
while (!stopPlay && seqread.getReadCount() < FILE_LENGTH) {
|
||||
|
||||
if (akku >= frameTime) {
|
||||
|
||||
let frameUnit = 0 // 0: no decode, 1: normal playback, 2+: skip (n-1) frames
|
||||
while (akku >= frameTime) {
|
||||
while (!stopPlay && akku >= frameTime) {
|
||||
if (interactive) {
|
||||
sys.poke(-40, 1)
|
||||
if (sys.peek(-41) == 67) {
|
||||
stopPlay = true
|
||||
}
|
||||
}
|
||||
|
||||
akku -= frameTime
|
||||
frameUnit += 1
|
||||
}
|
||||
|
||||
if (frameUnit != 0) {
|
||||
// skip frames if necessary
|
||||
while (frameUnit >= 1 && seqread.getReadCount() < FILE_LENGTH) {
|
||||
while (!stopPlay && frameUnit >= 1 && seqread.getReadCount() < FILE_LENGTH) {
|
||||
if (interactive) {
|
||||
sys.poke(-40, 1)
|
||||
if (sys.peek(-41) == 67) {
|
||||
stopPlay = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let packetType = seqread.readShort()
|
||||
|
||||
@@ -212,6 +234,15 @@ while (seqread.getReadCount() < FILE_LENGTH) {
|
||||
|
||||
let t2 = sys.nanoTime()
|
||||
akku += (t2 - t1) / 1000000000.0
|
||||
|
||||
if (interactive) {
|
||||
notifHideTimer += (t2 - t1)
|
||||
if (notifHideTimer > NOTIF_SHOWUPTIME) {
|
||||
con.clear()
|
||||
}
|
||||
}
|
||||
|
||||
t1 = t2
|
||||
}
|
||||
let endTime = sys.nanoTime()
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// this program will serve as a step towards the ADPCM decoding, and tests if RIFF data are successfully decoded.
|
||||
|
||||
// usage: playwav audiofile.wav [/i]
|
||||
let filename = _G.shell.resolvePathInput(exec_args[1]).full
|
||||
function printdbg(s) { if (0) serial.println(s) }
|
||||
|
||||
const interactive = exec_args[2].toLowerCase() == "/i"
|
||||
const seqread = require("seqread")
|
||||
const pcm = require("pcm")
|
||||
|
||||
@@ -60,12 +60,27 @@ let nChannels;
|
||||
let samplingRate;
|
||||
let blockSize;
|
||||
let bitsPerSample;
|
||||
let byterate;
|
||||
let comments = {};
|
||||
|
||||
let adpcmSamplesPerBlock;
|
||||
let readPtr = undefined
|
||||
let decodePtr = undefined
|
||||
|
||||
|
||||
function bytesToSec(i) {
|
||||
if (adpcmSamplesPerBlock) {
|
||||
let newByteRate = samplingRate
|
||||
let generatedSamples = i / blockSize * adpcmSamplesPerBlock
|
||||
return generatedSamples / newByteRate
|
||||
}
|
||||
else {
|
||||
return i / byterate
|
||||
}
|
||||
}
|
||||
function secToReadable(n) {
|
||||
let mins = ''+((n/60)|0)
|
||||
let secs = ''+(n % 60)
|
||||
return `${mins.padStart(2,'0')}:${secs.padStart(2,'0')}`
|
||||
}
|
||||
function checkIfPlayable() {
|
||||
if (pcmType != 1 && pcmType != 2) return `PCM Type not LPCM/ADPCM (${pcmType})`
|
||||
if (nChannels < 1 || nChannels > 2) return `Audio not mono/stereo but instead has ${nChannels} channels`
|
||||
@@ -82,8 +97,15 @@ function decodeInfilePcm(inPtr, outPtr, inputLen) {
|
||||
else
|
||||
throw Error(`PCM Type not LPCM or ADPCM (${pcmType})`)
|
||||
}
|
||||
let stopPlay = false
|
||||
con.curs_set(0)
|
||||
if (interactive) {
|
||||
println("Push and hold Backspace to exit")
|
||||
}
|
||||
let [cy, cx] = con.getyx()
|
||||
let [__, CONSOLE_WIDTH] = con.getmaxyx()
|
||||
// read chunks loop
|
||||
while (seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
while (!stopPlay && seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
let chunkName = seqread.readFourCC()
|
||||
let chunkSize = seqread.readInt()
|
||||
printdbg(`Reading '${chunkName}' at ${seqread.getReadCount() - 8}`)
|
||||
@@ -93,10 +115,17 @@ while (seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
pcmType = seqread.readShort()
|
||||
nChannels = seqread.readShort()
|
||||
samplingRate = seqread.readInt()
|
||||
seqread.skip(4)
|
||||
byterate = seqread.readInt()
|
||||
blockSize = seqread.readShort()
|
||||
bitsPerSample = seqread.readShort()
|
||||
seqread.skip(chunkSize - 16)
|
||||
if (pcmType != 2) {
|
||||
seqread.skip(chunkSize - 16)
|
||||
}
|
||||
else {
|
||||
seqread.skip(2)
|
||||
adpcmSamplesPerBlock = seqread.readShort()
|
||||
seqread.skip(chunkSize - (16 + 4))
|
||||
}
|
||||
|
||||
// define BLOCK_SIZE as integer multiple of blockSize, for LPCM
|
||||
// ADPCM will be decoded per-block basis
|
||||
@@ -155,9 +184,41 @@ while (seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
audio.setMasterVolume(0, 255)
|
||||
|
||||
let readLength = 1
|
||||
while (seqread.getReadCount() < startOffset + chunkSize && readLength > 0) {
|
||||
while (!stopPlay && seqread.getReadCount() < startOffset + chunkSize && readLength > 0) {
|
||||
if (interactive) {
|
||||
sys.poke(-40, 1)
|
||||
if (sys.peek(-41) == 67) {
|
||||
stopPlay = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let queueSize = audio.getPosition(0)
|
||||
if (queueSize <= 1) {
|
||||
if (interactive) {
|
||||
let currently = seqread.getReadCount() - startOffset
|
||||
let total = FILE_SIZE - startOffset - 8
|
||||
|
||||
let currentlySec = Math.round(bytesToSec(currently))
|
||||
let totalSec = Math.round(bytesToSec(total))
|
||||
|
||||
con.move(cy, 1)
|
||||
print(' '.repeat(40))
|
||||
con.move(cy, 1)
|
||||
|
||||
print(`${secToReadable(currentlySec)} / ${secToReadable(totalSec)}`)
|
||||
|
||||
con.move(cy, 15)
|
||||
print(' ')
|
||||
|
||||
let paintWidth = CONSOLE_WIDTH - 16
|
||||
let progressbar = '\x84205u'.repeat(paintWidth + 1)
|
||||
print(progressbar)
|
||||
|
||||
con.mvaddch(cy, 16 + Math.round(paintWidth * (currently / total)), 0xDB)
|
||||
}
|
||||
|
||||
|
||||
// upload four samples for lag-safely
|
||||
for (let repeat = QUEUE_MAX - queueSize; repeat > 0; repeat--) {
|
||||
let remainingBytes = FILE_SIZE - 8 - seqread.getReadCount()
|
||||
@@ -179,6 +240,7 @@ while (seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
audio.setSampleUploadLength(0, decodedSampleLength)
|
||||
audio.startSampleUpload(0)
|
||||
|
||||
|
||||
if (repeat > 1) sys.sleep(10)
|
||||
}
|
||||
|
||||
@@ -187,7 +249,7 @@ while (seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
|
||||
let remainingBytes = FILE_SIZE - 8 - seqread.getReadCount()
|
||||
printdbg(`readLength = ${readLength}; remainingBytes2 = ${remainingBytes}; seqread.getReadCount() = ${seqread.getReadCount()}; startOffset + chunkSize = ${startOffset + chunkSize}`)
|
||||
sys.spin()
|
||||
|
||||
|
||||
sys.sleep(10)
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ const COL_HL_EXT = {
|
||||
}
|
||||
|
||||
const EXEC_FUNS = {
|
||||
"wav": (f) => { _G.shell.execute(`playwav ${f}`) },
|
||||
"adpcm": (f) => { _G.shell.execute(`playwav ${f}`) },
|
||||
"mov": (f) => { _G.shell.execute(`playmov ${f}`) },
|
||||
"bas": (f) => { _G.shell.execute(`basic ${f}`) }
|
||||
"wav": (f) => _G.shell.execute(`playwav ${f} /i`),
|
||||
"adpcm": (f) => _G.shell.execute(`playwav ${f} /i`),
|
||||
"mov": (f) => _G.shell.execute(`playmov ${f} /i`),
|
||||
"bas": (f) => _G.shell.execute(`basic ${f}`)
|
||||
}
|
||||
|
||||
let windowMode = 0 // 0 == left, 1 == right
|
||||
@@ -345,17 +345,27 @@ while (!exit) {
|
||||
}
|
||||
else {
|
||||
let fileext = selectedFile.name.substring(selectedFile.name.lastIndexOf(".") + 1).toLowerCase()
|
||||
let execfun = EXEC_FUNS[fileext] || ((f) => { _G.shell.execute(f) })
|
||||
let execfun = EXEC_FUNS[fileext] || ((f) => _G.shell.execute(f))
|
||||
let errorlevel = 0
|
||||
|
||||
con.curs_set(1);clearScr();con.move(1,1)
|
||||
try {
|
||||
serial.println(selectedFile.fullPath)
|
||||
execfun(selectedFile.fullPath)
|
||||
errorlevel = execfun(selectedFile.fullPath)
|
||||
// serial.println("1 errorlevel = " + errorlevel)
|
||||
}
|
||||
catch (e) {
|
||||
// TODO popup error
|
||||
serial.println(e)
|
||||
println(e)
|
||||
errorlevel = 1
|
||||
// serial.println("2 errorlevel = " + errorlevel)
|
||||
}
|
||||
|
||||
if (errorlevel) {
|
||||
println("Hit Return/Enter key to continue . . . .")
|
||||
sys.read()
|
||||
}
|
||||
|
||||
con.curs_set(0);clearScr()
|
||||
redraw()
|
||||
}
|
||||
@@ -366,6 +376,10 @@ while (!exit) {
|
||||
cursor[windowMode] = 0; scroll[windowMode] = 0
|
||||
drawFilePanel()
|
||||
}
|
||||
else {
|
||||
// TODO list of drives
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
256
assets/disk0/tvdos/us_dvorak.key
Normal file
256
assets/disk0/tvdos/us_dvorak.key
Normal file
@@ -0,0 +1,256 @@
|
||||
[[""],[undefined],
|
||||
[undefined],
|
||||
["<HOME>"],
|
||||
[undefined],
|
||||
["<CALL>"],
|
||||
["<ENDCALL>"],
|
||||
["0",")"],
|
||||
["1","!"],
|
||||
["2","@"],
|
||||
["3","#"],
|
||||
["4","$"],
|
||||
["5","%"],
|
||||
["6","^"],
|
||||
["7","&"],
|
||||
["8","*"],
|
||||
["9","("],
|
||||
["*"],
|
||||
["#"],
|
||||
["<UP>"],
|
||||
["<DOWN>"],
|
||||
["<LEFT>"],
|
||||
["<RIGHT>"],
|
||||
["<CENTER>"],
|
||||
["<VOL_UP>"],
|
||||
["<VOL_DOWN>"],
|
||||
["<POWER>"],
|
||||
["<CAMERA>"],
|
||||
["<CLEAR>"],
|
||||
["a","A"],
|
||||
["x","X"],
|
||||
["j","J"],
|
||||
["e","E"],
|
||||
[".",">"],
|
||||
["u","U"],
|
||||
["i","I"],
|
||||
["d","D"],
|
||||
["c","C"],
|
||||
["h","H"],
|
||||
["t","T"],
|
||||
["n","N"],
|
||||
["m","M"],
|
||||
["b","B"],
|
||||
["r","R"],
|
||||
["l","L"],
|
||||
["'",'"'],
|
||||
["p","P"],
|
||||
["o","O"],
|
||||
["y","Y"],
|
||||
["g","G"],
|
||||
["k","K"],
|
||||
[",","<"],
|
||||
["q","Q"],
|
||||
["f","F"],
|
||||
[";",":"],
|
||||
["w","W"],
|
||||
["v","V"],
|
||||
["<ALT_L>"],
|
||||
["<ALT_R>"],
|
||||
["<SHIFT_L>"],
|
||||
["<SHIFT_R>"],
|
||||
["<TAB>"],
|
||||
[" "],
|
||||
["<SYM>"],
|
||||
["<EXPLORER>"],
|
||||
["<ENVELOPE>"],
|
||||
["\n"],
|
||||
["\x08"],
|
||||
["`","~"],
|
||||
["[","{"],
|
||||
["]","}"],
|
||||
["/","?"],
|
||||
["=","+"],
|
||||
["\\","|"],
|
||||
["s","S"],
|
||||
["-",'_'],
|
||||
["z","Z"],
|
||||
["<AT>"],
|
||||
["<NUM_LOCK>"],
|
||||
["<HEADSETHOOK>"],
|
||||
["<FOCUS>"],
|
||||
["+"],
|
||||
["<MENU>"],
|
||||
["<NOTIFICATION>"],
|
||||
["<SEARCH>"],
|
||||
["<PLAY_PAUSE>"],
|
||||
["<STOP>"],
|
||||
["<NEXT>"],
|
||||
["<PREV>"],
|
||||
["<REW>"],
|
||||
["<FFWD>"],
|
||||
["<MUTE>"],
|
||||
["<PAGE_UP>"],
|
||||
["<PAGE_DOWN>"],
|
||||
["<PICTSYMBOLS>"],
|
||||
["<SW:>TCH_CHARSET>"],
|
||||
["<:A:>"],
|
||||
["<:B:>"],
|
||||
["<:C:>"],
|
||||
["<:X:>"],
|
||||
["<:Y:>"],
|
||||
["<:Z:>"],
|
||||
["<:L1:>"],
|
||||
["<:R1:>"],
|
||||
["<:L2:>"],
|
||||
["<:R2:>"],
|
||||
["<:TL:>"],
|
||||
["<:TR:>"],
|
||||
["<:START:>"],
|
||||
["<:SELECT:>"],
|
||||
["<:MODE:>"],
|
||||
["<ESC>"],
|
||||
["<DEL>"],
|
||||
[undefined],
|
||||
[undefined],
|
||||
["<CAPS_LOCK>"],
|
||||
["<SCROLL_LOCK>"],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
["<PRINT_SCREEN_SYS_RQ>"],
|
||||
["<PAUSE_BREAK>"],
|
||||
[undefined],
|
||||
["<END>"],
|
||||
["<INSERT>"],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
["<CTRL_L>"],
|
||||
["<CTRL_R>"],
|
||||
["<F1>"],
|
||||
["<F2>"],
|
||||
["<F3>"],
|
||||
["<F4>"],
|
||||
["<F5>"],
|
||||
["<F6>"],
|
||||
["<F7>"],
|
||||
["<F8>"],
|
||||
["<F9>"],
|
||||
["<F10>"],
|
||||
["<F11>"],
|
||||
["<F12>"],
|
||||
["<NUM_LOCK>"],
|
||||
["0"],
|
||||
["1"],
|
||||
["2"],
|
||||
["3"],
|
||||
["4"],
|
||||
["5"],
|
||||
["6"],
|
||||
["7"],
|
||||
["8"],
|
||||
["9"],
|
||||
["/"],
|
||||
["*"],
|
||||
["-"],
|
||||
["+"],
|
||||
["."],
|
||||
["."],
|
||||
["\n"],
|
||||
["="],
|
||||
["("],
|
||||
[")"],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
[undefined],
|
||||
["<:CIRCLE:>"]
|
||||
]
|
||||
Reference in New Issue
Block a user