From 95b0d4672e04631aceb31f327a4ddd71d96dd54e Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 13 Apr 2022 17:30:42 +0900 Subject: [PATCH] faster partial reading of file wip --- assets/disk0/decodemov.js | 68 ++++++++++++++++--- .../net/torvald/tsvm/CompressorDelegate.kt | 16 +++++ .../src/net/torvald/tsvm/VMJSR223Delegate.kt | 20 ++++++ 3 files changed, 96 insertions(+), 8 deletions(-) diff --git a/assets/disk0/decodemov.js b/assets/disk0/decodemov.js index ec88edc..79d8e48 100644 --- a/assets/disk0/decodemov.js +++ b/assets/disk0/decodemov.js @@ -1,54 +1,106 @@ let filename = exec_args[1] + const FBUF_SIZE = 560*448 +const MAGIC = [0x1F, 0x54, 0x53, 0x56, 0x4D, 0x4D, 0x4F, 0x56] let status = filesystem.open("A", filename, "R") if (status) return status println("Reading...") -let bytes = filesystem.readAllBytes("A") +//let bytes = filesystem.readAllBytes("A") con.clear() let readCount = 0 function readBytes(length) { - let ret = new Int8Array(length) + /*let ret = new Int8Array(length) for (let k = 0; k < length; k++) { ret[k] = bytes[readCount] readCount += 1 } - return ret + return ret*/ + + let ptr = sys.malloc(length) + let requiredBlocks = (readCount == 0) + Math.floor((readCount + length) / 4096) - Math.floor(readCount / 4096) + let port = filesystem._toPorts("A") + + let completedReads = 0 + + for (let bc = 0; bc < requiredBlocks; bc++) { + if (readCount % 4096 == 0) { + com.sendMessage(port[0], "READ") + let thisBlockLen = com.fetchResponse(port[0]) // [0, 4095] + let remaining = Math.min(4096, length - completedReads) + + // copy from read buffer to designated position + sys.memcpy(-4097, ptr + readCount, remaining) + + // increment readCount properly + readCount += remaining + completedReads += remaining + } + else { + let padding = 4096 - (readCount % 4096) + let remaining = Math.min(padding, length - completedReads) + + // copy from read buffer to designated position + sys.memcpy(-4097 - padding, ptr + readCount, remaining) + + // increment readCount properly + readCount += remaining + completedReads += remaining + } + } + + return ptr } function readInt() { let b = readBytes(4) - return (b[0] & 255) | ((b[1] & 255) << 8) | ((b[2] & 255) << 16) | ((b[3] & 255) << 24) + let i = (sys.peek(b) & 255) | ((sys.peek(b+1) & 255) << 8) | ((sys.peek(b+2) & 255) << 16) | ((sys.peek(b+3) & 255) << 24) + sys.free(b) + return i } function readShort() { let b = readBytes(2) - return (b[0] & 255) | ((b[1] & 255) << 8) + let i = (sys.peek(b) & 255) | ((sys.peek(b+1) & 255) << 8) + sys.free(b) + return i } let magic = readBytes(8) -if (String.fromCharCode.apply(null, magic) != '\x1fTSVMMOV') return 1 +// check if magic number matches +MAGIC.forEach((b,i) => { + if (sys.peek(magic + i) & 255 != b) return 1 +}) +sys.free(magic) + let width = readShort() let height = readShort() let fps = readShort() let frameCount = readInt() % 16777216 +serial.println(`Dim: (${width}x${height}), FPS: ${fps}, Frames: ${frameCount}`) + let fbuf = sys.malloc(FBUF_SIZE) for (let f = 0; f < frameCount; f++) { + serial.println(`Frame #${f+1}`) + let payloadLen = readInt() - let gzipped = readBytes(payloadLen) - gzip.decompTo(gzipped, fbuf) + let gzippedPtr = readBytes(payloadLen) + + gzip.decompFromTo(gzippedPtr, payloadLen, fbuf) // should return FBUF_SIZE + dma.ramToFrame(fbuf, 0, FBUF_SIZE) + sys.free(gzippedPtr) } sys.free(fbuf) \ No newline at end of file diff --git a/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt b/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt index 6797339..b62bd81 100644 --- a/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt @@ -11,6 +11,9 @@ class CompressorDelegate(val vm: VM) { fun comp(str: String) = Companion.comp(str) fun comp(ba: ByteArray) = Companion.comp(ba) + /** + * @return length of the bytes compressed + */ fun compFromTo(input: Int, len: Int, output: Int): Int { val inbytes = ByteArray(len) { vm.peek(input.toLong() + it)!! } comp(inbytes).let { @@ -48,6 +51,19 @@ class CompressorDelegate(val vm: VM) { } } + /** + * @return length of the bytes compressed + */ + fun decompFromTo(input: Int, len: Int, output: Int): Int { + val inbytes = ByteArray(len) { vm.peek(input.toLong() + it)!! } + decomp(inbytes).let { + it.forEachIndexed { index, byte -> + vm.poke(output.toLong() + index, byte) + } + return it.size + } + } + companion object { val GZIP_HEADER = byteArrayOf(31, -117, 8) // .gz in DEFLATE diff --git a/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt index dc89f0f..6c91ba6 100644 --- a/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt @@ -3,7 +3,9 @@ package net.torvald.tsvm import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import net.torvald.UnsafeHelper import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUlong +import net.torvald.tsvm.peripheral.IOSpace import java.nio.charset.Charset /** @@ -16,6 +18,24 @@ class VMJSR223Delegate(val vm: VM) { fun nanoTime() = System.nanoTime() fun malloc(size: Int) = vm.malloc(size) fun free(ptr: Int) = vm.free(ptr) + fun memcpy(from: Int, to: Int, len: Int) { + val len = len.toLong() + // some special cases for native memcpy + val ioSpace = vm.peripheralTable[0].peripheral!! as IOSpace + // within scratchpad memory? + if (from in 0 until 8388608 && (to + len) in 0 until 8388608) + UnsafeHelper.memcpy(vm.usermem.ptr + from, vm.usermem.ptr + to, len) + // first serial read buffer -> usermem + else if (from in -4097 downTo -8192 && (to + len) in 0 until 8388608) + UnsafeHelper.memcpy(ioSpace.blockTransferRx[0].ptr + (-4097 - from), vm.usermem.ptr + to, len) + // usermem -> first serial write buffer + else if (from in 0 until 8388608 && (to + len) in -4097L downTo -8192L) + UnsafeHelper.memcpy(vm.usermem.ptr + from, ioSpace.blockTransferTx[0].ptr + (-4097 - to), len) + else + for (i in 0 until len) { + vm.poke(to + i, vm.peek(from + i)!!) + } + } fun mapRom(slot: Int) { vm.romMapping = slot.and(255) }