From d4dc99ff83110fc45c122f5dd79ebefcd15848b0 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 17 Sep 2022 23:36:02 +0900 Subject: [PATCH] pread/pwrite/ipf encoder/ipf decoder --- assets/disk0/tvdos/TVDOS.SYS | 34 +++++++++-- assets/disk0/tvdos/bin/decodeipf.js | 47 +++++++++++++++ assets/disk0/tvdos/bin/encodeipf.js | 57 ++++++++++++++++++ assets/disk0/ycocg.ipf1 | Bin 0 -> 5470 bytes assets/disk0/ycocg.ipf2 | Bin 0 -> 7533 bytes assets/disk0/ycocg2.ipf1 | Bin 0 -> 7360 bytes assets/disk0/ycocg2.ipf2 | Bin 0 -> 10341 bytes terranmon.txt | 4 +- .../net/torvald/tsvm/CompressorDelegate.kt | 2 +- tsvm_core/src/net/torvald/tsvm/DMADelegate.kt | 2 +- .../torvald/tsvm/GraphicsJSR223Delegate.kt | 2 +- .../src/net/torvald/tsvm/SerialHelper.kt | 2 +- .../src/net/torvald/tsvm/VMJSR223Delegate.kt | 6 +- 13 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 assets/disk0/tvdos/bin/decodeipf.js create mode 100644 assets/disk0/tvdos/bin/encodeipf.js create mode 100644 assets/disk0/ycocg.ipf1 create mode 100644 assets/disk0/ycocg.ipf2 create mode 100644 assets/disk0/ycocg2.ipf1 create mode 100644 assets/disk0/ycocg2.ipf2 diff --git a/assets/disk0/tvdos/TVDOS.SYS b/assets/disk0/tvdos/TVDOS.SYS index e948768..653576a 100644 --- a/assets/disk0/tvdos/TVDOS.SYS +++ b/assets/disk0/tvdos/TVDOS.SYS @@ -261,8 +261,20 @@ _TVDOS.DRV.FS.SERIAL.getFileLen = (fd) => { } return Number(com.pullMessage(port[0])) } -// TODO pread replaces DMA.comToRam -// TODO pwrite replaces DMA.ramToCom +_TVDOS.DRV.FS.SERIAL.pread = (fd, ptr, count, offset) => { + if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.fullPath}`) + + let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter) + com.sendMessage(port[0], "READ") + let response = com.getStatusCode(port[0]) + if (135 == response) { + throw Error("File not opened") + } + if (response < 0 || response >= 128) { + throw Error("Reading a file failed with "+response) + } + dma.comToRam(port[0], offset, ptr, count) +} _TVDOS.DRV.FS.SERIAL.sread = (fd) => { if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.fullPath}`) @@ -277,6 +289,15 @@ _TVDOS.DRV.FS.SERIAL.sread = (fd) => { } return com.pullMessage(port[0]) } +_TVDOS.DRV.FS.SERIAL.pwrite = (fd, ptr, count, offset) => { + if (offset) throw Error(`Write offset not supported on Serial device such as disk drives`) + + let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Writing a file failed with "+rrrr) + + let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter) + dma.ramToCom(ptr, port[0], count) + +} _TVDOS.DRV.FS.SERIAL.swrite = (fd, string) => { let rrrr = _TVDOS.DRV.FS.SERIAL._openw(fd); if (rrrr != 0) throw Error("Writing a file failed with "+rrrr) @@ -399,6 +420,7 @@ _TVDOS.DRV.FS.DEVRND.pread = (fd, ptr, count, offset) => { for (let i = 0; i < count; i++) { sys.poke(ptr + i, bytes[offset + i]) } + } _TVDOS.DRV.FS.DEVRND.pwrite = (fd, ptr, count, offset) => {} @@ -570,8 +592,8 @@ Object.freeze(_TVDOS.DRV.FS.DEVFBIPF) // Legacy Serial filesystem, !!pending for removal!! -/* -const filesystem = {}; + +/*const filesystem = {}; filesystem._toPorts = (driveLetter) => { if (driveLetter.toUpperCase === undefined) { @@ -692,8 +714,8 @@ filesystem.remove = (driveLetter) => { var response = com.getStatusCode(port[0]); return (response === 0); }; -Object.freeze(filesystem); -*/ +Object.freeze(filesystem);*/ + /////////////////////////////////////////////////////////////////////////////// diff --git a/assets/disk0/tvdos/bin/decodeipf.js b/assets/disk0/tvdos/bin/decodeipf.js new file mode 100644 index 0000000..b29eb01 --- /dev/null +++ b/assets/disk0/tvdos/bin/decodeipf.js @@ -0,0 +1,47 @@ +if (exec_args[1] == undefined) { + println("decodeipf ") + return 1 +} + +let infile = files.open(_G.shell.resolvePathInput(exec_args[1]).full) + +// read input file +let infilePtr = sys.malloc(infile.size) +infile.pread(infilePtr, infile.size, 0) + +// check if magic number matches + +const MAGIC = [0x1F, 0x54, 0x53, 0x56, 0x4D, 0x69, 0x50, 0x46] +let magicMatching = true + +MAGIC.forEach((b,i) => { + let testb = sys.peek(infilePtr + i) & 255 // for some reason this must be located here + if (testb != b) { + magicMatching = false + } +}) +if (!magicMatching) { + println("Not an iPF file (MAGIC mismatch)") + return 1 +} + +// decode input image +let width = sys.peek(infilePtr+8) | (sys.peek(infilePtr+9) << 8) +let height = sys.peek(infilePtr+10) | (sys.peek(infilePtr+11) << 8) +let hasAlpha = (sys.peek(infilePtr+12) != 0) +let ipfType = sys.peek(infilePtr+13) +let imgLen = sys.peek(infilePtr+24) | (sys.peek(infilePtr+25) << 8) | (sys.peek(infilePtr+26) << 16) | (sys.peek(infilePtr+27) << 24) +let decodefun = undefined +if (ipfType == 1) decodefun = graphics.decodeIpf1 +if (ipfType == 2) decodefun = graphics.decodeIpf2 +if (decodefun === undefined) throw Error(`Unknown IPF format: ${ipfType}`) + +let ipfbuf = sys.malloc(imgLen) +gzip.decompFromTo(infilePtr + 28, infile.size - 28, ipfbuf) // should return FBUF_SIZE +sys.free(infilePtr) + +graphics.setGraphicsMode(4) +graphics.clearText(); graphics.clearPixels(0); graphics.clearPixels2(0) +decodefun(ipfbuf, -1048577, -1310721, width, height, hasAlpha) + +sys.free(ipfbuf) \ No newline at end of file diff --git a/assets/disk0/tvdos/bin/encodeipf.js b/assets/disk0/tvdos/bin/encodeipf.js new file mode 100644 index 0000000..ee799a9 --- /dev/null +++ b/assets/disk0/tvdos/bin/encodeipf.js @@ -0,0 +1,57 @@ +if (exec_args[3] == undefined) { + println("encodeipf <1/2> [/noalpha]") + return 1 +} + +let noalpha = exec_args[4] != undefined && exec_args[4].toLowerCase() == "/noalpha" + +let infile = files.open(_G.shell.resolvePathInput(exec_args[2]).full) +let outfile = files.open(_G.shell.resolvePathInput(exec_args[3]).full) + +let ipfType = exec_args[1]|0 +let encodefun = undefined +if (1 == exec_args[1]) encodefun = graphics.encodeIpf1 +if (2 == exec_args[1]) encodefun = graphics.encodeIpf2 +if (encodefun === undefined) throw Error(`Unknown IPF format: ${exec_args[1]}`) + +// read input file +let infilePtr = sys.malloc(infile.size) +infile.pread(infilePtr, infile.size, 0) + +// decode input image +const [imgw, imgh, channels, imageDataPtr] = graphics.decodeImage(infilePtr, infile.size) // stored as [R | G | B | (A)] +sys.free(infilePtr) +let hasAlpha = (4 == channels) && !noalpha + +// encode image +let ipfBlockCount = Math.ceil(imgw / 4.0) * Math.ceil(imgh / 4.0) +let ipfSizePerBlock = 12 + 4*(ipfType - 1) + 8*hasAlpha +let ipfRawSize = ipfSizePerBlock * ipfBlockCount +let ipfarea = sys.malloc(ipfRawSize) +let gzippedImage = sys.malloc(28 + ipfRawSize+8) // ipf file header + somewhat arbitrary number. Get the actual count using 28+gzlen +encodefun(imageDataPtr, ipfarea, imgw, imgh, channels, hasAlpha, 0) +let gzlen = gzip.compFromTo(ipfarea, ipfRawSize, gzippedImage + 28) + + +sys.free(ipfarea) + +// write to the output bin +//// write header +;[ + 0x1F, 0x54, 0x53, 0x56, 0x4D, 0x69, 0x50, 0x46, // magic + imgw & 255, (imgw >> 8) & 255, // width + imgh & 255, (imgh >> 8) & 255, // height + 0+hasAlpha, // has alpha + ipfType, // ipf type + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + (gzlen >>> 0) & 255, // uncompressed size + (gzlen >>> 8) & 255, + (gzlen >>> 16) & 255, + (gzlen >>> 24) & 255 +].forEach((b,i) => sys.poke(gzippedImage + i, b)) + +outfile.mkFile() +outfile.pwrite(gzippedImage, 28 + gzlen, 0) +//dma.ramToCom(writeBuf, 0, writeCount) +sys.free(gzippedImage) +println(`Wrote ${28 + gzlen} bytes to the file`) \ No newline at end of file diff --git a/assets/disk0/ycocg.ipf1 b/assets/disk0/ycocg.ipf1 new file mode 100644 index 0000000000000000000000000000000000000000..9925ccfbd311caf90240ea9faacd31894bac33b8 GIT binary patch literal 5470 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 Z?btWYa7htNr_aOdLQG>ijGh=7{TIq%A_M>c literal 0 HcmV?d00001 diff --git a/assets/disk0/ycocg.ipf2 b/assets/disk0/ycocg.ipf2 new file mode 100644 index 0000000000000000000000000000000000000000..297f3630e6096c7c8730cf0605fed1b56f061813 GIT binary patch literal 7533 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 ZuN)sXn95DNs!q62#%IP=5BPoc{{e37%hLb= literal 0 HcmV?d00001 diff --git a/assets/disk0/ycocg2.ipf1 b/assets/disk0/ycocg2.ipf1 new file mode 100644 index 0000000000000000000000000000000000000000..4b7a0dc6755dd9ec3d552762bdc5593e508dff9a GIT binary patch literal 7360 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 literal 0 HcmV?d00001 diff --git a/assets/disk0/ycocg2.ipf2 b/assets/disk0/ycocg2.ipf2 new file mode 100644 index 0000000000000000000000000000000000000000..9d24f5c55edbf9d67d3fc755b8de52cb7ad97913 GIT binary patch literal 10341 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 literal 0 HcmV?d00001 diff --git a/terranmon.txt b/terranmon.txt index acfbcc3..52f3ec0 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -413,13 +413,13 @@ TYPE 255 FRAME - TSVM Interchangeable Picture Format (aka iPF Type 1/2) -Image is divided into 4x4 blocks and each block is serialised, then the entire file is gzipped +Image is divided into 4x4 blocks and each block is serialised, then the entire iPF blocks are gzipped # File Structure \x1F T S V M i P F [HEADER] -[Blocks.gz] or [Blocks] // gzipping is optional and only done for videos +[Blocks.gz] - Header uint16 WIDTH diff --git a/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt b/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt index 8a606d4..77ea419 100644 --- a/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/CompressorDelegate.kt @@ -6,7 +6,7 @@ import java.io.ByteArrayOutputStream import java.util.zip.GZIPInputStream import java.util.zip.GZIPOutputStream -class CompressorDelegate(val vm: VM) { +class CompressorDelegate(private val vm: VM) { fun comp(str: String) = Companion.comp(str) fun comp(ba: ByteArray) = Companion.comp(ba) diff --git a/tsvm_core/src/net/torvald/tsvm/DMADelegate.kt b/tsvm_core/src/net/torvald/tsvm/DMADelegate.kt index 0d289a9..c130045 100644 --- a/tsvm_core/src/net/torvald/tsvm/DMADelegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/DMADelegate.kt @@ -6,7 +6,7 @@ import net.torvald.tsvm.peripheral.GraphicsAdapter /** * Created by minjaesong on 2021-10-15. */ -class DMADelegate(val vm: VM) { +class DMADelegate(private val vm: VM) { private val READ = "READ".toByteArray(VM.CHARSET) private val FLUSH = "FLUSH".toByteArray(VM.CHARSET) diff --git a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt index 91e47f7..2f886fd 100644 --- a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt @@ -8,7 +8,7 @@ import net.torvald.tsvm.peripheral.GraphicsAdapter import net.torvald.tsvm.peripheral.fmod import kotlin.math.roundToInt -class GraphicsJSR223Delegate(val vm: VM) { +class GraphicsJSR223Delegate(private val vm: VM) { private fun getFirstGPU(): GraphicsAdapter? { return vm.findPeribyType(VM.PERITYPE_GPU_AND_TERM)?.peripheral as? GraphicsAdapter diff --git a/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt b/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt index 28c39b6..04535b8 100644 --- a/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt +++ b/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt @@ -137,7 +137,7 @@ object SerialHelper { data class DeviceStatus(val code: Int, val message: String) } -class SerialHelperDelegate(val vm: VM) { +class SerialHelperDelegate(private val vm: VM) { fun sendMessage(portNo: Int, message: String) = SerialHelper.sendMessage(vm, portNo, message.toByteArray(VM.CHARSET)) fun pullMessage(portNo: Int) = SerialHelper.pullMessage(vm, portNo).toString(VM.CHARSET) fun sendMessageGetBytes(portNo: Int, message: String) = SerialHelper.sendMessageGetBytes(vm, portNo, message.toByteArray(VM.CHARSET)).toString(VM.CHARSET) diff --git a/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt index c07d889..ac3bf8a 100644 --- a/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/VMJSR223Delegate.kt @@ -11,7 +11,7 @@ import java.nio.charset.Charset /** * Pass the instance of the class to the ScriptEngine's binding, preferably under the namespace of "vm" */ -class VMJSR223Delegate(val vm: VM) { +class VMJSR223Delegate(private val vm: VM) { fun poke(addr: Int, value: Int) = vm.poke(addr.toLong(), value.toByte()) fun peek(addr: Int) = vm.peek(addr.toLong())!!.toInt().and(255) @@ -186,13 +186,13 @@ class VMJSR223Delegate(val vm: VM) { } } -class VMSerialDebugger(val vm: VM) { +class VMSerialDebugger(private val vm: VM) { fun print(s: Any?) = System.out.print("$s") fun println(s: Any?) = System.out.println("$s") fun printerr(s: Any?) = System.err.println("$s") } -class Parallel(val vm: VM) { +class Parallel(private val vm: VM) { fun spawnNewContext(): VMRunner { return VMRunnerFactory(vm.assetsDir, vm, "js") }