mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
world radar
This commit is contained in:
@@ -1,4 +1,12 @@
|
|||||||
10 FOR K = 0 TO (160*140)
|
10 print("polling radar...")
|
||||||
20 POKE(-1048576-K, INT(RND(1)*16))
|
20 s=cput(1,"POLL")
|
||||||
30 NEXT
|
30 if s><0 then goto 900
|
||||||
40 GOTO 10
|
40 l=cget(1,0)
|
||||||
|
41 print("length: "+l+", pixels: "+l/3)
|
||||||
|
50 for i=0 to l step 3
|
||||||
|
60 m=peek(i)*160+peek(i+1)
|
||||||
|
62 p=peek(i+2)
|
||||||
|
63 poke(-1048576-m,p)
|
||||||
|
70 next
|
||||||
|
899 end
|
||||||
|
900 print("Polling failed: "+s)
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package net.torvald.terrarum.modulecomputers.tsvmperipheral
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import net.torvald.tsvm.VM
|
||||||
|
import net.torvald.tsvm.peripheral.BlockTransferInterface
|
||||||
|
import net.torvald.tsvm.peripheral.TestDiskDrive
|
||||||
|
import net.torvald.tsvm.peripheral.trimNull
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2021-12-02.
|
||||||
|
*/
|
||||||
|
class WorldRadar(pngfile: FileHandle) : BlockTransferInterface(false, true) {
|
||||||
|
|
||||||
|
private val W = 160
|
||||||
|
private val H = 140
|
||||||
|
|
||||||
|
private val world = ByteArray(W*H)
|
||||||
|
|
||||||
|
private val AIR = 0.toByte()
|
||||||
|
private val DIRT = 1.toByte()
|
||||||
|
private val GRASS = 2.toByte()
|
||||||
|
private val STONE = 16.toByte()
|
||||||
|
|
||||||
|
private val AIR_OUT = 0.toByte()
|
||||||
|
private val GRASS_OUT = 2.toByte()
|
||||||
|
private val DIRT_OUT = 4.toByte()
|
||||||
|
private val STONE_OUT = 7.toByte()
|
||||||
|
|
||||||
|
init {
|
||||||
|
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||||
|
|
||||||
|
val worldTex = Pixmap(pngfile)
|
||||||
|
for (y in 0 until 140) { for (x in 0 until 160) {
|
||||||
|
val c = worldTex.getPixel(x, y)
|
||||||
|
world[y * W + x] = when (c) {
|
||||||
|
0x46712dff -> GRASS
|
||||||
|
0x9b9a9bff.toInt() -> STONE
|
||||||
|
0x6a5130ff -> DIRT
|
||||||
|
else -> AIR
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
worldTex.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val messageComposeBuffer = ByteArrayOutputStream(BLOCK_SIZE) // always use this and don't alter blockSendBuffer please
|
||||||
|
private var blockSendBuffer = ByteArray(1)
|
||||||
|
private var blockSendCount = 0
|
||||||
|
|
||||||
|
private fun resetBuf() {
|
||||||
|
blockSendCount = 0
|
||||||
|
messageComposeBuffer.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return (blockSendCount * BLOCK_SIZE < blockSendBuffer.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun startSendImpl(recipient: BlockTransferInterface): Int {
|
||||||
|
if (blockSendCount == 0) {
|
||||||
|
blockSendBuffer = messageComposeBuffer.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
val sendSize = if (blockSendBuffer.size - (blockSendCount * BLOCK_SIZE) < BLOCK_SIZE)
|
||||||
|
blockSendBuffer.size % BLOCK_SIZE
|
||||||
|
else BLOCK_SIZE
|
||||||
|
|
||||||
|
recipient.writeout(ByteArray(sendSize) {
|
||||||
|
blockSendBuffer[blockSendCount * BLOCK_SIZE + it]
|
||||||
|
})
|
||||||
|
|
||||||
|
blockSendCount += 1
|
||||||
|
|
||||||
|
return sendSize
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeoutImpl(inputData: ByteArray) {
|
||||||
|
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||||
|
|
||||||
|
// prepare draw commands
|
||||||
|
/*
|
||||||
|
* draw command format:
|
||||||
|
*
|
||||||
|
* <Y> <X> <COL>
|
||||||
|
*
|
||||||
|
* marking rules:
|
||||||
|
*
|
||||||
|
* : exposed = has at least 1 nonsolid on 4 sides
|
||||||
|
*
|
||||||
|
* 1. exposed grass -> 2
|
||||||
|
* 2. exposed dirt -> 4
|
||||||
|
* 3. exposed stone -> 7
|
||||||
|
* 4. stone exposed to dirt/grass -> 7
|
||||||
|
*/
|
||||||
|
if (inputString.startsWith("POLL")) {
|
||||||
|
resetBuf()
|
||||||
|
val cmdbuf = HashMap<Int,Byte>(1024)
|
||||||
|
|
||||||
|
for (y in 1 until H-1) { for (x in 1 until W-1) {
|
||||||
|
val yx = y.shl(8) or x
|
||||||
|
val i = y * W + x
|
||||||
|
val nearby = listOf(i-W,i-1,i+1,i+W).map { world[it] } // up, left, right, down
|
||||||
|
val block = world[i]
|
||||||
|
|
||||||
|
if (block == GRASS && nearby.contains(AIR)) {
|
||||||
|
cmdbuf[yx] = GRASS_OUT
|
||||||
|
}
|
||||||
|
else if (block == DIRT && nearby.contains(AIR)) {
|
||||||
|
cmdbuf[yx] = DIRT_OUT
|
||||||
|
}
|
||||||
|
else if (block == STONE && (nearby.contains(AIR) || nearby.contains(GRASS) || nearby.contains(DIRT))) {
|
||||||
|
cmdbuf[yx] = STONE_OUT
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
cmdbuf.keys.sorted().forEach { key ->
|
||||||
|
val value = cmdbuf[key]!!.toInt()
|
||||||
|
val x = key % 256
|
||||||
|
val y = key / 256
|
||||||
|
messageComposeBuffer.write(y)
|
||||||
|
messageComposeBuffer.write(x)
|
||||||
|
messageComposeBuffer.write(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import net.torvald.terrarum.modulecomputers.tsvmperipheral.WorldRadar
|
||||||
import net.torvald.tsvm.CompressorDelegate.GZIP_HEADER
|
import net.torvald.tsvm.CompressorDelegate.GZIP_HEADER
|
||||||
import net.torvald.tsvm.peripheral.*
|
import net.torvald.tsvm.peripheral.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -96,6 +97,8 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
vm.getInputStream = { System.`in` }
|
vm.getInputStream = { System.`in` }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm.getIO().blockTransferPorts[1].attachDevice(WorldRadar(Gdx.files.internal("test_assets/test_terrain.png")))
|
||||||
|
|
||||||
loaderInfo.extraPeripherals.forEach { (port, peri) ->
|
loaderInfo.extraPeripherals.forEach { (port, peri) ->
|
||||||
val typeargs = peri.args.map { it.javaClass }.toTypedArray()
|
val typeargs = peri.args.map { it.javaClass }.toTypedArray()
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ class ExtDisp(val vm: VM, val width: Int, val height: Int) : PeriBase {
|
|||||||
in 0 until width * height -> {
|
in 0 until width * height -> {
|
||||||
framebuffer.pixels.put(adi, byte)
|
framebuffer.pixels.put(adi, byte)
|
||||||
}
|
}
|
||||||
|
(width * height).toLong() -> {
|
||||||
|
framebuffer.setColor(bi.shl(24) or bi.shr(16) or bi.shl(8) or bi)
|
||||||
|
framebuffer.fill()
|
||||||
|
}
|
||||||
in 0 until nextPowerOfTwo(width * height) -> { /* do nothing */ }
|
in 0 until nextPowerOfTwo(width * height) -> { /* do nothing */ }
|
||||||
else -> poke(addr % nextPowerOfTwo(width * height), byte)
|
else -> poke(addr % nextPowerOfTwo(width * height), byte)
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
test_assets/test_terrain.png
Normal file
BIN
test_assets/test_terrain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
test_assets/test_terrain_out.png
Normal file
BIN
test_assets/test_terrain_out.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Reference in New Issue
Block a user