commit da7e2e7c776d9e998433e83226b2085ecf9cc3fc Author: minjaesong Date: Tue Apr 7 07:02:15 2020 +0900 initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c84c197 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +*.psd filter=lfs diff=lfs merge=lfs -text +*.ogg filter=lfs diff=lfs merge=lfs -text +*.tga filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.opus filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6e7ba5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Build-related +out/* +bin/* +build/* +.gradle/* +TerrarumBuild.jar + +# Java native errors +hs_err_pid* +replay_pid* + +# OS files +Thumbs.db +.DS_Store +desktop.ini +.directory +*/.directory + +# Resources that should not be tracked +assets/mods/basegame/demoworld +external_resource_packs +#assets/mods/basegame/demoworld.gz +external_resource_packs.zip + +# IntelliJ +workspace.xml + +# Temporary files +.tmp* +tmp_* +## Microsoft Office +~$* +## Generic temp files in Linux +*~ +## Vim temp files +*.swp +*.swo + +# Eclipse MAT heap files +*.hprof +*.bin +*.index +*.threads +*_Leak_Suspects.zip diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..1bec35e --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..0dd4b35 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/libraries/KotlinJavaRuntime.xml b/.idea/libraries/KotlinJavaRuntime.xml new file mode 100644 index 0000000..9ff8d27 --- /dev/null +++ b/.idea/libraries/KotlinJavaRuntime.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..9c0199b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3b2904e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/EGA8x14.png b/EGA8x14.png new file mode 100644 index 0000000..306d468 Binary files /dev/null and b/EGA8x14.png differ diff --git a/lib/AppleJavaExtensions-1.4.jar.gz b/lib/AppleJavaExtensions-1.4.jar.gz new file mode 100644 index 0000000..a4dec1b --- /dev/null +++ b/lib/AppleJavaExtensions-1.4.jar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a33c7cfa851124610d83ffc30dc2495c8549c2a65a4cac9a30a152d7adb6b70 +size 8607 diff --git a/lib/Concentus-1.0-SNAPSHOT.jar b/lib/Concentus-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..30cbf5b Binary files /dev/null and b/lib/Concentus-1.0-SNAPSHOT.jar differ diff --git a/lib/GetCpuName.jar b/lib/GetCpuName.jar new file mode 100644 index 0000000..230de90 Binary files /dev/null and b/lib/GetCpuName.jar differ diff --git a/lib/TerranVirtualDisk.jar b/lib/TerranVirtualDisk.jar new file mode 100644 index 0000000..b6af461 Binary files /dev/null and b/lib/TerranVirtualDisk.jar differ diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar new file mode 100644 index 0000000..15b7e1f Binary files /dev/null and b/lib/TerrarumSansBitmap.jar differ diff --git a/lib/Terrarum_Joise.jar b/lib/Terrarum_Joise.jar new file mode 100644 index 0000000..ecef95b Binary files /dev/null and b/lib/Terrarum_Joise.jar differ diff --git a/lib/commons-codec-1.10.jar b/lib/commons-codec-1.10.jar new file mode 100644 index 0000000..1d7417c Binary files /dev/null and b/lib/commons-codec-1.10.jar differ diff --git a/lib/commons-csv-1.2.jar b/lib/commons-csv-1.2.jar new file mode 100644 index 0000000..1b26424 Binary files /dev/null and b/lib/commons-csv-1.2.jar differ diff --git a/lib/gdx-backend-lwjgl-natives.jar b/lib/gdx-backend-lwjgl-natives.jar new file mode 100644 index 0000000..bd9b36e Binary files /dev/null and b/lib/gdx-backend-lwjgl-natives.jar differ diff --git a/lib/gdx-backend-lwjgl.jar b/lib/gdx-backend-lwjgl.jar new file mode 100644 index 0000000..a783cfa Binary files /dev/null and b/lib/gdx-backend-lwjgl.jar differ diff --git a/lib/gdx-backend-lwjgl3.jar.gz b/lib/gdx-backend-lwjgl3.jar.gz new file mode 100644 index 0000000..2a391f5 --- /dev/null +++ b/lib/gdx-backend-lwjgl3.jar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95f27e027b825dfb4603b5efcdfb3e68e0cdd45a5653e11fbba7c25e79df87db +size 1691011 diff --git a/lib/gdx-controllers-desktop-natives.jar b/lib/gdx-controllers-desktop-natives.jar new file mode 100644 index 0000000..0136285 Binary files /dev/null and b/lib/gdx-controllers-desktop-natives.jar differ diff --git a/lib/gdx-controllers-desktop.jar b/lib/gdx-controllers-desktop.jar new file mode 100644 index 0000000..8a7c85d Binary files /dev/null and b/lib/gdx-controllers-desktop.jar differ diff --git a/lib/gdx-controllers-lwjgl3.jar.gz b/lib/gdx-controllers-lwjgl3.jar.gz new file mode 100644 index 0000000..a404999 --- /dev/null +++ b/lib/gdx-controllers-lwjgl3.jar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5d6954efe7547a4ae86fd7cd27343a4ff8a3c1b5537e990e506af8e2c438707 +size 5541 diff --git a/lib/gdx-controllers.jar b/lib/gdx-controllers.jar new file mode 100644 index 0000000..1c24977 Binary files /dev/null and b/lib/gdx-controllers.jar differ diff --git a/lib/gdx-natives.jar b/lib/gdx-natives.jar new file mode 100644 index 0000000..1bec32c Binary files /dev/null and b/lib/gdx-natives.jar differ diff --git a/lib/gdx-nightly-20170610.zip.gz b/lib/gdx-nightly-20170610.zip.gz new file mode 100644 index 0000000..6929e9e --- /dev/null +++ b/lib/gdx-nightly-20170610.zip.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30d86d6e6ed0ea725e7e8d4cd4bb9aa0ab1ef69c9e14eb557808cd8e2ace8737 +size 13760205 diff --git a/lib/gdx-nightly-20181111.zip.gz b/lib/gdx-nightly-20181111.zip.gz new file mode 100644 index 0000000..e12f352 --- /dev/null +++ b/lib/gdx-nightly-20181111.zip.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2d984a7706b6b047e5b4974090f66015afb864d0c3059959d8fc9a18b2fe558 +size 7840303 diff --git a/lib/gdx-nightly-20190112.zip.gz b/lib/gdx-nightly-20190112.zip.gz new file mode 100644 index 0000000..bf3a8d8 --- /dev/null +++ b/lib/gdx-nightly-20190112.zip.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5d7c447e5f6f67191984aa7a3b93a40d7a31a93991659443eca4b685fc44423 +size 10005989 diff --git a/lib/gdx.jar b/lib/gdx.jar new file mode 100644 index 0000000..d90e4ba Binary files /dev/null and b/lib/gdx.jar differ diff --git a/lib/gson-2.8.5.jar b/lib/gson-2.8.5.jar new file mode 100644 index 0000000..0d5baf3 Binary files /dev/null and b/lib/gson-2.8.5.jar differ diff --git a/lib/javadoc/commons-codec-1.10-javadoc.jar b/lib/javadoc/commons-codec-1.10-javadoc.jar new file mode 100644 index 0000000..2f372ec Binary files /dev/null and b/lib/javadoc/commons-codec-1.10-javadoc.jar differ diff --git a/lib/javadoc/commons-csv.jar b/lib/javadoc/commons-csv.jar new file mode 100644 index 0000000..fadf3b9 Binary files /dev/null and b/lib/javadoc/commons-csv.jar differ diff --git a/lib/javadoc/gdx-docs.zip b/lib/javadoc/gdx-docs.zip new file mode 100644 index 0000000..0841756 --- /dev/null +++ b/lib/javadoc/gdx-docs.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:400b15c5f52ea9538d00715695f59694a127ca6ff0937a4b3643842c83950745 +size 7053806 diff --git a/lib/javadoc/gson-2.8.5-javadoc.jar b/lib/javadoc/gson-2.8.5-javadoc.jar new file mode 100644 index 0000000..e74a1d2 Binary files /dev/null and b/lib/javadoc/gson-2.8.5-javadoc.jar differ diff --git a/lib/javadoc/jxinput-1.0.0-javadoc.jar b/lib/javadoc/jxinput-1.0.0-javadoc.jar new file mode 100644 index 0000000..12d907f Binary files /dev/null and b/lib/javadoc/jxinput-1.0.0-javadoc.jar differ diff --git a/lib/javadoc/luaj-javadoc.jar b/lib/javadoc/luaj-javadoc.jar new file mode 100644 index 0000000..aa170d0 Binary files /dev/null and b/lib/javadoc/luaj-javadoc.jar differ diff --git a/lib/javadoc/lwjgl-javadoc.jar b/lib/javadoc/lwjgl-javadoc.jar new file mode 100644 index 0000000..ec69237 Binary files /dev/null and b/lib/javadoc/lwjgl-javadoc.jar differ diff --git a/lib/javadoc/lwjgl3-javadoc.zip b/lib/javadoc/lwjgl3-javadoc.zip new file mode 100644 index 0000000..7fd4ea6 --- /dev/null +++ b/lib/javadoc/lwjgl3-javadoc.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed9726cfc9dfb398308376dec9b44a5fe31c45c7a44efe0c654538f17da1f18a +size 8932782 diff --git a/lib/jnlp.jar b/lib/jnlp.jar new file mode 100644 index 0000000..8fd98f2 Binary files /dev/null and b/lib/jnlp.jar differ diff --git a/lib/jogg-0.0.7.jar.gz b/lib/jogg-0.0.7.jar.gz new file mode 100644 index 0000000..983351b --- /dev/null +++ b/lib/jogg-0.0.7.jar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07108b22478debd82b3affbf17d8adfc0c95f71ec16898a080e6a777bcad3f63 +size 6122 diff --git a/lib/jopus.jar b/lib/jopus.jar new file mode 100644 index 0000000..6769732 Binary files /dev/null and b/lib/jopus.jar differ diff --git a/lib/jorbis-0.0.17.jar.gz b/lib/jorbis-0.0.17.jar.gz new file mode 100644 index 0000000..f87a868 --- /dev/null +++ b/lib/jorbis-0.0.17.jar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ac3bed29268510d5f9dddadcf8e38fc77ffaca21df307ed73c108c6ef01f123 +size 94544 diff --git a/lib/jxinput-1.0.0.jar b/lib/jxinput-1.0.0.jar new file mode 100644 index 0000000..15ba084 Binary files /dev/null and b/lib/jxinput-1.0.0.jar differ diff --git a/lib/kotlin-stdlib-sources.jar b/lib/kotlin-stdlib-sources.jar new file mode 100644 index 0000000..acb8ff1 Binary files /dev/null and b/lib/kotlin-stdlib-sources.jar differ diff --git a/lib/libjinput.zip.gz b/lib/libjinput.zip.gz new file mode 100644 index 0000000..10950c8 --- /dev/null +++ b/lib/libjinput.zip.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e69225c091ee28d6c48b94dbcccccb7b8b58420c82558ddd94e9f2cbc0f73377 +size 342469 diff --git a/lib/libjopus.so b/lib/libjopus.so new file mode 100644 index 0000000..37b9a79 Binary files /dev/null and b/lib/libjopus.so differ diff --git a/lib/luaj-jse-3.0.2.jar b/lib/luaj-jse-3.0.2.jar new file mode 100644 index 0000000..f149575 Binary files /dev/null and b/lib/luaj-jse-3.0.2.jar differ diff --git a/lib/prtree.jar b/lib/prtree.jar new file mode 100644 index 0000000..728a327 Binary files /dev/null and b/lib/prtree.jar differ diff --git a/lib/source/GetCpuName-src.jar b/lib/source/GetCpuName-src.jar new file mode 100644 index 0000000..acb1d6d Binary files /dev/null and b/lib/source/GetCpuName-src.jar differ diff --git a/lib/source/TerranVirtualDisk-src.jar b/lib/source/TerranVirtualDisk-src.jar new file mode 100644 index 0000000..355c720 Binary files /dev/null and b/lib/source/TerranVirtualDisk-src.jar differ diff --git a/lib/source/gdx-backend-lwjgl-sources.jar b/lib/source/gdx-backend-lwjgl-sources.jar new file mode 100644 index 0000000..c9e868c Binary files /dev/null and b/lib/source/gdx-backend-lwjgl-sources.jar differ diff --git a/lib/source/gdx-backend-lwjgl3-sources.jar b/lib/source/gdx-backend-lwjgl3-sources.jar new file mode 100644 index 0000000..f2d12f4 Binary files /dev/null and b/lib/source/gdx-backend-lwjgl3-sources.jar differ diff --git a/lib/source/gdx-sources.jar b/lib/source/gdx-sources.jar new file mode 100644 index 0000000..51aed07 Binary files /dev/null and b/lib/source/gdx-sources.jar differ diff --git a/lib/source/gson-2.8.5-sources.jar b/lib/source/gson-2.8.5-sources.jar new file mode 100644 index 0000000..a64f4e7 Binary files /dev/null and b/lib/source/gson-2.8.5-sources.jar differ diff --git a/lib/source/jxinput-1.0.0-sources.jar b/lib/source/jxinput-1.0.0-sources.jar new file mode 100644 index 0000000..91975b6 Binary files /dev/null and b/lib/source/jxinput-1.0.0-sources.jar differ diff --git a/lib/source/luaj-sources-3.0.2.jar b/lib/source/luaj-sources-3.0.2.jar new file mode 100644 index 0000000..3a89c23 Binary files /dev/null and b/lib/source/luaj-sources-3.0.2.jar differ diff --git a/lib/x86/libgdx.so b/lib/x86/libgdx.so new file mode 100644 index 0000000..8b7dbbf Binary files /dev/null and b/lib/x86/libgdx.so differ diff --git a/lib/x86_64/libgdx.so b/lib/x86_64/libgdx.so new file mode 100644 index 0000000..b5aa6a1 Binary files /dev/null and b/lib/x86_64/libgdx.so differ diff --git a/src/net/torvald/tsvm/AppLoader.java b/src/net/torvald/tsvm/AppLoader.java new file mode 100644 index 0000000..0105fe6 --- /dev/null +++ b/src/net/torvald/tsvm/AppLoader.java @@ -0,0 +1,49 @@ +package net.torvald.tsvm; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.backends.lwjgl.LwjglApplication; +import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; +import com.badlogic.gdx.graphics.glutils.ShaderProgram; + +public class AppLoader { + + public static String appTitle = "Totally Simple Virtual Machine"; + public static LwjglApplicationConfiguration appConfig; + + public static void main(String[] args) { + ShaderProgram.pedantic = false; + + appConfig = new LwjglApplicationConfiguration(); + appConfig.foregroundFPS = 60; + appConfig.backgroundFPS = 60; + appConfig.vSyncEnabled = false; + appConfig.useGL30 = true; + appConfig.resizable = false; + appConfig.title = appTitle; + appConfig.forceExit = true; + appConfig.width = 560; + appConfig.height = 448; + + new LwjglApplication(new VMGUI(appConfig), appConfig); + } + + public static ShaderProgram loadShaderFromFile(String vert, String frag) { + ShaderProgram s = new ShaderProgram(Gdx.files.internal(vert), Gdx.files.internal(frag)); + + if (s.getLog().toLowerCase().contains("error")) { + throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog())); + } + + return s; + } + + public static ShaderProgram loadShaderInline(String vert, String frag) { + ShaderProgram s = new ShaderProgram(vert, frag); + + if (s.getLog().toLowerCase().contains("error")) { + throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog())); + } + + return s; + } +} diff --git a/src/net/torvald/tsvm/UnsafePtr.kt b/src/net/torvald/tsvm/UnsafePtr.kt new file mode 100644 index 0000000..3a4d413 --- /dev/null +++ b/src/net/torvald/tsvm/UnsafePtr.kt @@ -0,0 +1,141 @@ +package net.torvald + +import sun.misc.Unsafe +import java.io.PrintStream + +/** + * Further read: + * - http://www.docjar.com/docs/api/sun/misc/Unsafe.html + * + * Created by minjaesong on 2019-06-21. + */ + +internal object UnsafeHelper { + val unsafe: Unsafe + + init { + val unsafeConstructor = Unsafe::class.java.getDeclaredConstructor() + unsafeConstructor.isAccessible = true + unsafe = unsafeConstructor.newInstance() + } + + /** + * A factory method to allocate a memory of given size and return its starting address as a pointer. + */ + fun allocate(size: Long): UnsafePtr { + val ptr = unsafe.allocateMemory(size) + return UnsafePtr(ptr, size) + } + + fun memcpy(src: UnsafePtr, fromIndex: Long, dest: UnsafePtr, toIndex: Long, copyLength: Long) = + unsafe.copyMemory(src.ptr + fromIndex, dest.ptr + toIndex, copyLength) + fun memcpy(srcAddress: Long, destAddress: Long, copyLength: Long) = + unsafe.copyMemory(srcAddress, destAddress, copyLength) + fun memcpyRaw(srcObj: Any?, srcPos: Long, destObj: Any?, destPos: Long, len: Long) = + unsafe.copyMemory(srcObj, srcPos, destObj, destPos, len) + + /** + * The array object in JVM is stored in this memory map: + * + * 0 w 2w * + * | Some identifier | Other identifier | the actual data ... | + * + * (where w = 4 for 32-bit JVM and 8 for 64-bit JVM. If Compressed-OOP is involved, things may get complicated) + * + * @return offset from the array's base memory address (aka pointer) that the actual data begins. + */ + fun getArrayOffset(obj: Any) = unsafe.arrayBaseOffset(obj.javaClass) +} + +/** + * To allocate a memory, use UnsafeHelper.allocate(long) + * + * All the getFloat/Int/whatever methods will follow the endianness of your system, + * e.g. it'll be Little Endian on x86, Big Endian on PPC, User-defined on ARM; therefore these functions should not be + * used when the portability matters (e.g. Savefile). In such situations, do byte-wise operations will be needed. + * + * Use of hashCode() is forbidden, use the pointer instead. + */ +internal class UnsafePtr(pointer: Long, allocSize: Long) { + var destroyed = false + private set + + var ptr: Long = pointer + private set + + var size: Long = allocSize + private set + + fun realloc(newSize: Long) { + ptr = UnsafeHelper.unsafe.reallocateMemory(ptr, newSize) + size = newSize + } + + fun destroy() { + if (!destroyed) { + UnsafeHelper.unsafe.freeMemory(ptr) + + println("[UnsafePtr] Destroying pointer $this; called from:") + printStackTrace(this) + + destroyed = true + } + } + + private inline fun checkNullPtr(index: Long) { // ignore what IDEA says and do inline this + // commenting out because of the suspected (or minor?) performance impact. + // You may break the glass and use this tool when some fucking incomprehensible bugs ("vittujen vitun bugit") + // appear (e.g. getting garbage values when it fucking shouldn't) + assert(!destroyed) { throw NullPointerException("The pointer is already destroyed ($this)") } + + // OOB Check: debugging purposes only -- comment out for the production + //if (index !in 0 until size) throw IndexOutOfBoundsException("Index: $index; alloc size: $size") + } + + operator fun get(index: Long): Byte { + checkNullPtr(index) + return UnsafeHelper.unsafe.getByte(ptr + index) + } + + operator fun set(index: Long, value: Byte) { + checkNullPtr(index) + UnsafeHelper.unsafe.putByte(ptr + index, value) + } + + // NOTE: get/set multibyte values are NOT BYTE-ALIGNED! + + fun getFloat(index: Long): Float { + checkNullPtr(index) + return UnsafeHelper.unsafe.getFloat(ptr + index) + } + + fun getInt(index: Long): Int { + checkNullPtr(index) + return UnsafeHelper.unsafe.getInt(ptr + index) + } + + fun setFloat(index: Long, value: Float) { + checkNullPtr(index) + UnsafeHelper.unsafe.putFloat(ptr + index, value) + } + + fun setInt(index: Long, value: Int) { + checkNullPtr(index) + UnsafeHelper.unsafe.putInt(ptr + index, value) + } + + fun fillWith(byte: Byte) { + UnsafeHelper.unsafe.setMemory(ptr, size, byte) + } + + override fun toString() = "0x${ptr.toString(16)} with size $size" + override fun equals(other: Any?) = this.ptr == (other as UnsafePtr).ptr && this.size == other.size + + inline fun printStackTrace(obj: Any) = printStackTrace(obj, System.out) // because of Java + + fun printStackTrace(obj: Any, out: PrintStream = System.out) { + Thread.currentThread().stackTrace.forEach { + out.println("[${obj.javaClass.simpleName}] ... $it") + } + } +} \ No newline at end of file diff --git a/src/net/torvald/tsvm/VM.kt b/src/net/torvald/tsvm/VM.kt new file mode 100644 index 0000000..5cebb91 --- /dev/null +++ b/src/net/torvald/tsvm/VM.kt @@ -0,0 +1,104 @@ +package net.torvald.tsvm + +import net.torvald.UnsafeHelper +import net.torvald.UnsafePtr +import net.torvald.tsvm.peripheral.IOSpace +import net.torvald.tsvm.peripheral.PeriBase + +/** + * 1 byte = 2 pixels + * + * 560x448@4bpp = 125 440 bytes + * 560x448@8bpp = 250 880 bytes + * + * -> 262144 bytes (256 kB) + * + * [USER AREA | HW AREA] + * Number of pheripherals = 8, of which the computer itself is considered as a peri. + * + * HW AREA = [Peripherals | MMIO | INTVEC] + * + * User area: 8 MB, hardware area: 8 MB + * + * 8192 kB + * User Space + * 1024 kB + * Peripheral #8 + * 1024 kB + * Peripheral #7 + * ... + * 1024 kB + * MMIO and Interrupt Vectors + * 128 kB + * MMIO for Peri #8 + * 128 kB + * MMIO for Peri #7 + * ... + * 128 kB + * MMIO for the computer + * 130816 bytes + * MMIO for Ports, etc. + * 256 bytes + * Vectors for 64 interrupts + * + * + */ + +class VM( + _memsize: Int +) { + + val memsize = minOf(USER_SPACE_SIZE, _memsize.toLong()) + + internal val usermem = UnsafeHelper.allocate(memsize) + + val peripheralTable = Array(8) { PeripheralEntry() } + + init { + peripheralTable[0] = PeripheralEntry( + "io", + IOSpace(), + HW_RESERVE_SIZE, + MMIO_SIZE.toInt() - 256, + 64 + ) + } + + + fun findPeribyType(searchTerm: String): Int? { + for (i in 0..7) { + if (peripheralTable[i].type == searchTerm) return i + } + return null + } + + fun dispose() { + usermem.destroy() + peripheralTable.forEach { it.peripheral?.dispose() } + } + + /* + NOTE: re-fill peripheralTable whenever the VM cold-boots! + you are absolutely not supposed to hot-swap peripheral cards when the computer is on + */ + + + companion object { + val MMIO_SIZE = 128.kB() + val HW_RESERVE_SIZE = 1024.kB() + val USER_SPACE_SIZE = 8192.kB() + + const val PERITYPE_GRAPHICS = "gpu" + } + +} + +data class PeripheralEntry( + val type: String = "null", + val peripheral: PeriBase? = null, + val memsize: Long = 0, + val mmioSize: Int = 0, + val interruptCount: Int = 0 // max: 4 +) + +fun Int.kB() = this * 1024L diff --git a/src/net/torvald/tsvm/VMGUI.kt b/src/net/torvald/tsvm/VMGUI.kt new file mode 100644 index 0000000..8f683c5 --- /dev/null +++ b/src/net/torvald/tsvm/VMGUI.kt @@ -0,0 +1,119 @@ +package net.torvald.tsvm + +import com.badlogic.gdx.ApplicationAdapter +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.tsvm.peripheral.GraphicsAdapter +import kotlin.math.roundToInt + +class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() { + + val vm = VM(8192) + lateinit var gpu: GraphicsAdapter + + lateinit var batch: SpriteBatch + lateinit var camera: OrthographicCamera + + override fun create() { + super.create() + + gpu = GraphicsAdapter() + + vm.peripheralTable[1] = PeripheralEntry( + VM.PERITYPE_GRAPHICS, + gpu, + 256.kB(), + 16, + 0 + ) + + batch = SpriteBatch() + camera = OrthographicCamera(appConfig.width.toFloat(), appConfig.height.toFloat()) + camera.setToOrtho(false) + camera.update() + batch.projectionMatrix = camera.combined + Gdx.gl20.glViewport(0, 0, appConfig.width, appConfig.height) + } + + private var updateAkku = 0.0 + private var updateRate = 1f / 60f + + override fun render() { + Gdx.graphics.setTitle("${AppLoader.appTitle} $EMDASH F: ${Gdx.graphics.framesPerSecond}") + + super.render() + + val dt = Gdx.graphics.rawDeltaTime + updateAkku += dt + + var i = 0L + while (updateAkku >= updateRate) { + updateGame(updateRate) + updateAkku -= updateRate + i += 1 + } + + renderGame() + } + + private fun updateGame(delta: Float) { + paintTestPalette() + } + + private fun paintTestPalette() { + for (y in 0 until 360) { + for (x in 0 until GraphicsAdapter.WIDTH) { + val palnum = 20 * (y / (360 / 12)) + (x / (GraphicsAdapter.WIDTH / 20)) + gpu.poke(y.toLong() * GraphicsAdapter.WIDTH + x, palnum.toByte()) + } + } + + for (y in 360 until GraphicsAdapter.HEIGHT) { + for (x in 0 until GraphicsAdapter.WIDTH) { + val palnum = 240 + (x / (GraphicsAdapter.WIDTH / 16)) + gpu.poke(y.toLong() * GraphicsAdapter.WIDTH + x, palnum.toByte()) + } + } + + gpu.poke(262142L, Math.random().times(255.0).toByte()) + gpu.poke(262143L, Math.random().times(255.0).toByte()) + + /* +local vm = require("rawmemoryaccess") +local w = 560 +local h = 448 +local peripheral_slot = 1 + +for y = 0, 359 do + for x = 0, w - 1 do + palnum = 20 * (y / (360 / 12)) + (x / (w / 20)) + vm.poke(-(y * w + x + 1) - 1048576 * peripheral_slot, palnum) + end +end + +for y = 360, h - 1 do + for x = 0, w - 1 do + palnum = 240 + (x / (w / 16)) + vm.poke(-(y * w + x + 1) - 1048576 * peripheral_slot, palnum) + end +end + +vm.poke(-262143 - 1048576 * peripheral_slot, math.floor(math.random() * 255.0)) +vm.poke(-262144 - 1048576 * peripheral_slot, math.floor(math.random() * 255.0)) + */ + } + + private fun renderGame() { + gpu.render(batch, 0f, 0f) + + } + + + override fun dispose() { + super.dispose() + } +} + +const val EMDASH = 0x2014.toChar() \ No newline at end of file diff --git a/src/net/torvald/tsvm/firmware/Firmware.kt b/src/net/torvald/tsvm/firmware/Firmware.kt new file mode 100644 index 0000000..e75bf2f --- /dev/null +++ b/src/net/torvald/tsvm/firmware/Firmware.kt @@ -0,0 +1,66 @@ +package net.torvald.tsvm.firmware + +import net.torvald.UnsafePtr +import net.torvald.tsvm.VM +import net.torvald.tsvm.kB +import net.torvald.tsvm.peripheral.PeriBase +import org.luaj.vm2.LuaTable +import org.luaj.vm2.LuaValue +import org.luaj.vm2.lib.OneArgFunction +import org.luaj.vm2.lib.TwoArgFunction + +internal class Firmware(val vm: VM) { + + val t = LuaTable() + + fun errorIllegalAccess(addr: Long) { + + } + + private fun translateAddr(addr: LuaValue): Pair { + val addr = addr.checklong() + return when (addr) { + // DO note that numbers in Lua are double precision floats (ignore Lua 5.3 for now) + in 0..8192.kB() - 1 -> vm.usermem to addr + in -1024.kB()..-1 -> vm.peripheralTable[0].peripheral to (-addr - 1) + in -2048.kB()..-1024.kB()-1 -> vm.peripheralTable[1].peripheral to (-addr - 1 - 1024.kB()) + in -3072.kB()..-2048.kB()-1 -> vm.peripheralTable[2].peripheral to (-addr - 1 - 2048.kB()) + in -4096.kB()..-3072.kB()-1 -> vm.peripheralTable[3].peripheral to (-addr - 1 - 3072.kB()) + in -5120.kB()..-4096.kB()-1 -> vm.peripheralTable[4].peripheral to (-addr - 1 - 4096.kB()) + in -6144.kB()..-5120.kB()-1 -> vm.peripheralTable[5].peripheral to (-addr - 1 - 5120.kB()) + in -7168.kB()..-6144.kB()-1 -> vm.peripheralTable[6].peripheral to (-addr - 1 - 6144.kB()) + in -8192.kB()..-7168.kB()-1 -> vm.peripheralTable[7].peripheral to (-addr - 1 - 7168.kB()) + else -> null to addr + } + } + + init { + t["poke"] = object : TwoArgFunction() { + override fun call(addr: LuaValue, value: LuaValue): LuaValue { + val (memspace, offset) = translateAddr(addr) + if (memspace == null) + errorIllegalAccess(addr.checklong()) + else if (memspace is UnsafePtr) + memspace.set(offset, value.checkint().toByte()) + else + (memspace as PeriBase).poke(offset, value.checkint().toByte()) + return LuaValue.NIL + } + } + + t["peek"] = object : OneArgFunction() { + override fun call(addr: LuaValue): LuaValue { + val (memspace, offset) = translateAddr(addr) + return if (memspace == null) + LuaValue.NIL + else if (memspace is UnsafePtr) + memspace.get(offset).toLuaValue() + else + (memspace as PeriBase).peek(offset)?.toLuaValue() ?: LuaValue.NIL + } + } + } + + + fun Byte.toLuaValue() = LuaValue.valueOf(this.toInt()) +} \ No newline at end of file diff --git a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt new file mode 100644 index 0000000..0b8b91f --- /dev/null +++ b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -0,0 +1,427 @@ +package net.torvald.tsvm.peripheral + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.tsvm.AppLoader +import net.torvald.tsvm.VM +import net.torvald.tsvm.kB + +class GraphicsAdapter : PeriBase { + + internal val framebuffer = Pixmap(WIDTH, HEIGHT, Pixmap.Format.RGBA8888) + private var rendertex = Texture(1, 1, Pixmap.Format.RGBA8888) + private val paletteOfFloats = FloatArray(1024) { + val rgba = DEFAULT_PALETTE[it / 4] + val channel = it % 4 + rgba.shr((3 - channel) * 8).and(255) / 255f + } + + private val paletteShader = AppLoader.loadShaderInline(DRAW_SHADER_VERT, DRAW_SHADER_FRAG) + + private var textmodeBlinkCursor = true + + private var graphicsUseSprites = false + + private var lastUsedColour = (-1).toByte() + + init { + framebuffer.blending = Pixmap.Blending.None + framebuffer.setColor(-1) + framebuffer.fill() + + for (k in 0..1023) { + if (k != 0 && k % 4 == 0) + println() + + print(paletteOfFloats[k]) + print(" ") + } + } + + override fun peek(addr: Long): Byte? { + val adi = addr.toInt() + return when (addr) { + in 0 until 250880 -> framebuffer.getPixel(adi % WIDTH, adi / WIDTH).toByte() + in 261632 until 262144 -> peekPalette(adi - 261632) + in 0 until VM.HW_RESERVE_SIZE -> peek(addr % VRAM_SIZE) // HW mirroring + else -> null + } + } + + override fun poke(addr: Long, byte: Byte) { + val adi = addr.toInt() + val bi = byte.toInt().and(255) + when (addr) { + in 0 until 250880 -> { + lastUsedColour = byte + framebuffer.drawPixel(adi % WIDTH, adi / WIDTH, bi.shl(24)) + } + in 261632 until 262144 -> pokePalette(adi - 261632, byte) + in 0 until VM.HW_RESERVE_SIZE -> poke(addr % VRAM_SIZE, byte) // HW mirroring + } + } + + override fun mmio_read(addr: Long): Byte? { + return when (addr) { + 0L -> (WIDTH % 256).toByte() + 1L -> (WIDTH / 256).toByte() + 2L -> (HEIGHT % 256).toByte() + 3L -> (HEIGHT / 256).toByte() + 4L -> 70 + 5L -> 32 + 6L -> textmodeBlinkCursor.toInt().toByte() + 7L -> graphicsUseSprites.toInt().toByte() + 8L -> lastUsedColour + + in 0 until VM.MMIO_SIZE -> -1 + else -> null + } + } + + override fun mmio_write(addr: Long, byte: Byte) { + TODO("Not yet implemented") + } + + override fun dispose() { + framebuffer.dispose() + rendertex.dispose() + } + + fun render(batch: SpriteBatch, x: Float, y: Float) { + rendertex.dispose() + rendertex = Texture(framebuffer) + + batch.begin() + batch.color = Color.WHITE + batch.shader = paletteShader + paletteShader.setUniform4fv("pal", paletteOfFloats, 0, paletteOfFloats.size) + // must be done every time the shader is "actually loaded" + // try this: if above line precedes 'batch.shader = paletteShader', it won't work + batch.draw(rendertex, x, y) + batch.end() + + batch.shader = null + } + + private fun peekPalette(offset: Int): Byte { + val highvalue = paletteOfFloats[offset * 2] // R, B + val lowvalue = paletteOfFloats[offset * 2 + 1] // G, A + return (highvalue.div(15f).toInt().shl(4) or lowvalue.div(15f).toInt()).toByte() + } + + private fun pokePalette(offset: Int, byte: Byte) { + val highvalue = byte.toInt().and(0xF0).ushr(4) / 15f + val lowvalue = byte.toInt().and(0x0F) / 15f + + paletteOfFloats[offset * 2] = highvalue + paletteOfFloats[offset * 2 + 1] = lowvalue + } + + + private fun Boolean.toInt() = if (this) 1 else 0 + + companion object { + const val WIDTH = 560 + const val HEIGHT = 448 + val VRAM_SIZE = 256.kB() + + val DRAW_SHADER_FRAG = """ + #version 120 + + varying vec4 v_color; + varying vec2 v_texCoords; + uniform sampler2D u_texture; + uniform vec4 pal[256]; + + float rand(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); + } + + void main(void) { + gl_FragColor = pal[int(texture2D(u_texture, v_texCoords).r * 255.0)]; + //gl_FragColor = vec4(texture2D(u_texture, v_texCoords).rrr, 1.0); + } + """.trimIndent() + + val DRAW_SHADER_VERT = """ + #version 120 + + attribute vec4 a_position; + attribute vec4 a_color; + attribute vec2 a_texCoord0; + + uniform mat4 u_projTrans; + + varying vec4 v_color; + varying vec2 v_texCoords; + + void main() { + v_color = a_color; + v_texCoords = a_texCoord0; + gl_Position = u_projTrans * a_position; + } + """.trimIndent() + + val DEFAULT_PALETTE = intArrayOf( // 0b rrrrrrrr gggggggg bbbbbbbb aaaaaaaa + 255, + 17663, + 35071, + 48127, + 65535, + 2228479, + 2245887, + 2263295, + 2276351, + 2293759, + 4456703, + 4474111, + 4491519, + 4504575, + 4521983, + 6684927, + 6702335, + 6719743, + 6732799, + 6750207, + 10027263, + 10044671, + 10062079, + 10075135, + 10092543, + 12255487, + 12272895, + 12290303, + 12303359, + 12320767, + 14483711, + 14501119, + 14518527, + 14531583, + 14548991, + 16711935, + 16729343, + 16746751, + 16759807, + 16777215, + 855638271, + 855655679, + 855673087, + 855686143, + 855703551, + 857866495, + 857883903, + 857901311, + 857914367, + 857931775, + 860094719, + 860112127, + 860129535, + 860142591, + 860159999, + 862322943, + 862340351, + 862357759, + 862370815, + 862388223, + 865665279, + 865682687, + 865700095, + 865713151, + 865730559, + 867893503, + 867910911, + 867928319, + 867941375, + 867958783, + 870121727, + 870139135, + 870156543, + 870169599, + 870187007, + 872349951, + 872367359, + 872384767, + 872397823, + 872415231, + 1711276287, + 1711293695, + 1711311103, + 1711324159, + 1711341567, + 1713504511, + 1713521919, + 1713539327, + 1713552383, + 1713569791, + 1715732735, + 1715750143, + 1715767551, + 1715780607, + 1715798015, + 1717960959, + 1717978367, + 1717995775, + 1718008831, + 1718026239, + 1721303295, + 1721320703, + 1721338111, + 1721351167, + 1721368575, + 1723531519, + 1723548927, + 1723566335, + 1723579391, + 1723596799, + 1725759743, + 1725777151, + 1725794559, + 1725807615, + 1725825023, + 1727987967, + 1728005375, + 1728022783, + 1728035839, + 1728053247, + -1728052993, + -1728035585, + -1728018177, + -1728005121, + -1727987713, + -1725824769, + -1725807361, + -1725789953, + -1725776897, + -1725759489, + -1723596545, + -1723579137, + -1723561729, + -1723548673, + -1723531265, + -1721368321, + -1721350913, + -1721333505, + -1721320449, + -1721303041, + -1718025985, + -1718008577, + -1717991169, + -1717978113, + -1717960705, + -1715797761, + -1715780353, + -1715762945, + -1715749889, + -1715732481, + -1713569537, + -1713552129, + -1713534721, + -1713521665, + -1713504257, + -1711341313, + -1711323905, + -1711306497, + -1711293441, + -1711276033, + -872414977, + -872397569, + -872380161, + -872367105, + -872349697, + -870186753, + -870169345, + -870151937, + -870138881, + -870121473, + -867958529, + -867941121, + -867923713, + -867910657, + -867893249, + -865730305, + -865712897, + -865695489, + -865682433, + -865665025, + -862387969, + -862370561, + -862353153, + -862340097, + -862322689, + -860159745, + -860142337, + -860124929, + -860111873, + -860094465, + -857931521, + -857914113, + -857896705, + -857883649, + -857866241, + -855703297, + -855685889, + -855668481, + -855655425, + -855638017, + -16776961, + -16759553, + -16742145, + -16729089, + -16711681, + -14548737, + -14531329, + -14513921, + -14500865, + -14483457, + -12320513, + -12303105, + -12285697, + -12272641, + -12255233, + -10092289, + -10074881, + -10057473, + -10044417, + -10027009, + -6749953, + -6732545, + -6715137, + -6702081, + -6684673, + -4521729, + -4504321, + -4486913, + -4473857, + -4456449, + -2293505, + -2276097, + -2258689, + -2245633, + -2228225, + -65281, + -47873, + -30465, + -17409, + -1, + 255, + 286331391, + 572662527, + 858993663, + 1145324799, + 1431655935, + 1717987071, + 2004318207, + -2004317953, + -1717986817, + -1431655681, + -1145324545, + -858993409, + -572662273, + -286331137, + 0 + ) + } +} \ No newline at end of file diff --git a/src/net/torvald/tsvm/peripheral/IOSpace.kt b/src/net/torvald/tsvm/peripheral/IOSpace.kt new file mode 100644 index 0000000..7d23dd5 --- /dev/null +++ b/src/net/torvald/tsvm/peripheral/IOSpace.kt @@ -0,0 +1,23 @@ +package net.torvald.tsvm.peripheral + +class IOSpace : PeriBase { + override fun peek(addr: Long): Byte? { + TODO("Not yet implemented") + } + + override fun poke(addr: Long, byte: Byte) { + TODO("Not yet implemented") + } + + override fun mmio_read(addr: Long): Byte? { + TODO("Not yet implemented") + } + + override fun mmio_write(addr: Long, byte: Byte) { + TODO("Not yet implemented") + } + + override fun dispose() { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/src/net/torvald/tsvm/peripheral/PeriBase.kt b/src/net/torvald/tsvm/peripheral/PeriBase.kt new file mode 100644 index 0000000..504b0f0 --- /dev/null +++ b/src/net/torvald/tsvm/peripheral/PeriBase.kt @@ -0,0 +1,19 @@ +package net.torvald.tsvm.peripheral + +interface PeriBase { + + /** + * Addr is not an offset; they can be "wired" into any other "chip" in the card other than its RAM + */ + fun peek(addr: Long): Byte? + + /** + * Addr is not an offset; they can be "wired" into any other "chip" in the card other than its RAM + */ + fun poke(addr: Long, byte: Byte) + + fun mmio_read(addr: Long): Byte? + fun mmio_write(addr: Long, byte: Byte) + + fun dispose() +} \ No newline at end of file diff --git a/terranmon.txt b/terranmon.txt new file mode 100644 index 0000000..a596f66 --- /dev/null +++ b/terranmon.txt @@ -0,0 +1,92 @@ +1 byte = 2 pixels + +560x448@4bpp = 125 440 bytes +560x448@8bpp = 250 880 bytes + +-> 262144 bytes (256 kB) + +[USER AREA | HW AREA] + + Number of pheripherals = 8, of which the computer itself is considered as + a peripheral. + +HW AREA = [Peripherals | MMIO | INTVEC] + +User area: 8 MB, hardware area: 8 MB + +8192 kB + User Space +1024 kB + Peripheral #8 +1024 kB + Peripheral #7 +... +1024 kB + MMIO and Interrupt Vectors + 128 kB + MMIO for Peri #8 + 128 kB + MMIO for Peri #7 + ... + 128 kB + MMIO for the computer + 130816 bytes + MMIO for Ports, etc. + 256 bytes + Vectors for 64 interrupts + +-------------------------------------------------------------------------------- + +VRAM Bank 0 (256 kB) + +From the end of the memory space: +512 bytes + Stored in following pattern: 0b rrrr gggg, 0b bbbb aaaa, .... +IF graphics_mode THEN + (41 sprites : 260 bytes each -> 10660 bytes) + 0th sprite is always the GUI cursor + 256 bytes + 16x16 texture for the sprite + 2 bytes + 0b rr0000xx xxxxxxxx (r: rotation, x: x-position) + 2 bytes + Ob hv0000xy yyyyyyyy (h: horizontal flip, v: vertical flip, x: show/hide, y: y-position) +ELSE + 2240 bytes + Text buffer of 70x32 (8x14 character size) + 2240 bytes + Text background colours + 2240 bytes + Text foreground colours + 2 bytes + Cursor position in: (y*32 + x) + 3938 bytes + *Unused* +FI +From the start of the memory space: +250880 bytes + Framebuffer +92 bytes + *Unused* + +MMIO + +2 bytes RO + Framebuffer width in pixels +2 bytes RO + Framebuffer height in pixels +1 bytes RO + Text mode columns +1 bytes RO + Text mode rows +1 bytes RW + Text-mode attributes + 0b 0000 000c (c: Cursor blink) +1 bytes RW + Graphics-mode attributes + 0b 0000 000g (g: Use sprites(wipes out text buffer)) +1 bytes RO + Last used colour (set by poking at the framebuffer) + +Text-mode-font-ROM is immutable and does not belong to VRAM +Even in the text mode framebuffer is still being drawn onto the screen, and the texts are drawn on top of it \ No newline at end of file diff --git a/tsvm.iml b/tsvm.iml new file mode 100644 index 0000000..245d342 --- /dev/null +++ b/tsvm.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tsvm_graphics_mockup.kra b/tsvm_graphics_mockup.kra new file mode 100644 index 0000000..4721352 Binary files /dev/null and b/tsvm_graphics_mockup.kra differ