mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
150 lines
4.8 KiB
JavaScript
150 lines
4.8 KiB
JavaScript
/*let music = files.open("A:/orstphone-hdma.bytes")
|
|
let samples = sys.malloc(65536)
|
|
music.pread(samples, 65534)
|
|
|
|
audio.setPcmMode(0)
|
|
audio.setMasterVolume(0, 255)
|
|
audio.putPcmDataByPtr(samples, 65534, 0)
|
|
audio.setLoopPoint(0, 65534)
|
|
audio.play(0)*/
|
|
|
|
let filename = exec_args[1]
|
|
const port = _TVDOS.DRV.FS.SERIAL._toPorts("A")[0]
|
|
|
|
let filex = files.open(_G.shell.resolvePathInput(filename).full)
|
|
const FILE_SIZE = filex.size
|
|
|
|
|
|
|
|
//println("Reading...")
|
|
//serial.println("!!! READING")
|
|
|
|
com.sendMessage(port, "DEVRST\x17")
|
|
com.sendMessage(port, `OPENR"${filename}",1`)
|
|
let statusCode = com.getStatusCode(port)
|
|
|
|
if (statusCode != 0) {
|
|
printerrln(`No such file (${statusCode})`)
|
|
return statusCode
|
|
}
|
|
|
|
com.sendMessage(port, "READ")
|
|
statusCode = com.getStatusCode(port)
|
|
if (statusCode != 0) {
|
|
printerrln("READ failed with "+statusCode)
|
|
return statusCode
|
|
}
|
|
|
|
|
|
|
|
let readCount = 0
|
|
function readBytes(length, ptrToDecode) {
|
|
let ptr = (ptrToDecode === undefined) ? sys.malloc(length) : ptrToDecode
|
|
let requiredBlocks = Math.floor((readCount + length) / 4096) - Math.floor(readCount / 4096)
|
|
|
|
let completedReads = 0
|
|
|
|
// serial.println(`readBytes(${length}); readCount = ${readCount}`)
|
|
|
|
for (let bc = 0; bc < requiredBlocks + 1; bc++) {
|
|
if (completedReads >= length) break
|
|
|
|
if (readCount % 4096 == 0) {
|
|
// serial.println("READ from serial")
|
|
// pull the actual message
|
|
sys.poke(-4093 - port, 6);sys.sleep(0) // spinning is required as Graal run is desynced with the Java side
|
|
|
|
let blockTransferStatus = ((sys.peek(-4085 - port*2) & 255) | ((sys.peek(-4086 - port*2) & 255) << 8))
|
|
let thisBlockLen = blockTransferStatus & 4095
|
|
if (thisBlockLen == 0) thisBlockLen = 4096 // [1, 4096]
|
|
let hasMore = (blockTransferStatus & 0x8000 != 0)
|
|
|
|
|
|
// serial.println(`block: (${thisBlockLen})[${[...Array(thisBlockLen).keys()].map(k => (sys.peek(-4097 - k) & 255).toString(16).padStart(2,'0')).join()}]`)
|
|
|
|
let remaining = Math.min(thisBlockLen, length - completedReads)
|
|
|
|
// serial.println(`Pulled a block (${thisBlockLen}); readCount = ${readCount}, completedReads = ${completedReads}, remaining = ${remaining}`)
|
|
|
|
// copy from read buffer to designated position
|
|
sys.memcpy(-4097, ptr + completedReads, remaining)
|
|
|
|
// increment readCount properly
|
|
readCount += remaining
|
|
completedReads += remaining
|
|
}
|
|
else {
|
|
let padding = readCount % 4096
|
|
let remaining = length - completedReads
|
|
let thisBlockLen = Math.min(4096 - padding, length - completedReads)
|
|
|
|
// serial.println(`padding = ${padding}; remaining = ${remaining}`)
|
|
// serial.println(`block: (${thisBlockLen})[${[...Array(thisBlockLen).keys()].map(k => (sys.peek(-4097 - padding - k) & 255).toString(16).padStart(2,'0')).join()}]`)
|
|
// serial.println(`Reusing a block (${thisBlockLen}); readCount = ${readCount}, completedReads = ${completedReads}`)
|
|
|
|
// copy from read buffer to designated position
|
|
sys.memcpy(-4097 - padding, ptr + completedReads, thisBlockLen)
|
|
|
|
// increment readCount properly
|
|
readCount += thisBlockLen
|
|
completedReads += thisBlockLen
|
|
}
|
|
}
|
|
|
|
//serial.println(`END readBytes(${length}); readCount = ${readCount}\n`)
|
|
|
|
return ptr
|
|
}
|
|
|
|
let sampleSize = FILE_SIZE
|
|
const BLOCK_SIZE = 4096
|
|
const QUEUE_MAX = 4 // according to the spec
|
|
|
|
audio.resetParams(0)
|
|
audio.purgeQueue(0)
|
|
audio.setPcmMode(0)
|
|
audio.setMasterVolume(0, 255)
|
|
|
|
// FIXME: when a playback was interrupted using SHIFT-CTRL-T-R, then re-tried, the ghost from the previous run
|
|
// briefly manifests, even if you're queueing only once
|
|
|
|
const decodePtr = sys.malloc(BLOCK_SIZE)
|
|
|
|
while (sampleSize > 0) {
|
|
let queueSize = audio.getPosition(0)
|
|
|
|
// serial.println(`[js] Trying to upload samples, queueSize = ${queueSize}`)
|
|
print(".")
|
|
|
|
if (queueSize <= 1) {
|
|
serial.println(`[js] Queue size: ${queueSize}; uploading ${QUEUE_MAX - queueSize} samples`)
|
|
|
|
println()
|
|
println((FILE_SIZE - sampleSize) / FILE_SIZE * 100 + " %")
|
|
|
|
// upload four samples for lag-safely
|
|
for (let repeat = QUEUE_MAX - queueSize; repeat > 0; repeat--) {
|
|
let readLength = (sampleSize < BLOCK_SIZE) ? sampleSize : BLOCK_SIZE
|
|
readBytes(readLength, decodePtr)
|
|
|
|
audio.putPcmDataByPtr(decodePtr, readLength, 0)
|
|
audio.setSampleUploadLength(0, readLength)
|
|
audio.startSampleUpload(0)
|
|
|
|
sampleSize -= readLength
|
|
|
|
if (repeat > 1) sys.sleep(10)
|
|
}
|
|
|
|
audio.play(0)
|
|
}
|
|
|
|
// audio.setMasterVolume(0, (Math.random()*255)|0)
|
|
|
|
|
|
sys.sleep(10)
|
|
}
|
|
|
|
//audio.stop(0)
|
|
sys.free(decodePtr)
|