mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-12 07:44:03 +09:00
booting entirely from the bios
This commit is contained in:
@@ -300,9 +300,23 @@ function println(s) {
|
|||||||
else
|
else
|
||||||
sys.println(s);
|
sys.println(s);
|
||||||
}
|
}
|
||||||
|
function printerr(s) {
|
||||||
|
print("\x1B[31m"+s+"\x1B[m");
|
||||||
|
}
|
||||||
|
function printerrln(s) {
|
||||||
|
println("\x1B[31m"+s+"\x1B[m");
|
||||||
|
}
|
||||||
function read() {
|
function read() {
|
||||||
return sys.read();
|
return sys.read();
|
||||||
}
|
}
|
||||||
|
String.prototype.trimNull = function() {
|
||||||
|
let cnt = this.length - 1
|
||||||
|
while (cnt >= 0) {
|
||||||
|
if (this.charCodeAt(cnt) != 0) break;
|
||||||
|
cnt -= 1;
|
||||||
|
}
|
||||||
|
return this.slice(0, cnt + 1);
|
||||||
|
}
|
||||||
// ncurses-like terminal control
|
// ncurses-like terminal control
|
||||||
var con = {};
|
var con = {};
|
||||||
con.getch = function() {
|
con.getch = function() {
|
||||||
|
|||||||
@@ -7,27 +7,6 @@ println("TERRAN Megatrends inc.");
|
|||||||
|
|
||||||
let memptr = 0;
|
let memptr = 0;
|
||||||
const memtestptn = [
|
const memtestptn = [
|
||||||
// Overclockers will LOVE this!
|
|
||||||
//[0x00,0x00,0x00,0x00 , 0xFF,0xFF,0xFF,0xFF , 0x00,0x00,0x00,0x00 , 0xFF,0xFF,0xFF,0xFF],
|
|
||||||
|
|
||||||
//[0xAA,0x55,0xAA,0x55 , 0xAA,0x55,0xAA,0x55 , 0xAA,0x55,0xAA,0x55 , 0xAA,0x55,0xAA,0x55],
|
|
||||||
//[0x00,0xFF,0x00,0xFF , 0xFF,0x00,0xFF,0x00 , 0x00,0xFF,0x00,0xFF , 0xFF,0x00,0xFF,0x00],
|
|
||||||
|
|
||||||
//[0x69,0x69,0x69,0x69 , 0xA5,0xA5,0xA5,0xA5 , 0x69,0x69,0x69,0x69 , 0xA5,0xA5,0xA5,0xA5],
|
|
||||||
//[0x0F,0x0F,0x0F,0x0F , 0x1E,0x1E,0x1E,0x1E , 0x3C,0x3C,0x3C,0x3C , 0x78,0x78,0x78,0x78],
|
|
||||||
|
|
||||||
//[0xC7,0x1C,0x71,0xC7 , 0x8E,0x38,0xE3,0x8E , 0x1C,0x71,0xC7,0x1C , 0x38,0xE3,0x8E,0x38],
|
|
||||||
//[0x71,0xC7,0x1C,0x71 , 0xE3,0x8E,0x38,0xE3 , 0x01,0x02,0x04,0x08 , 0x10,0x20,0x40,0x80],
|
|
||||||
|
|
||||||
//[0x00,0x00,0xFF,0xFF , 0x00,0x00,0xFF,0xFF , 0x00,0x01,0xFF,0xFE , 0x00,0x01,0xFF,0xFE],
|
|
||||||
//[0x00,0x03,0xFF,0xFC , 0x00,0x03,0xFF,0xFC , 0x00,0x07,0xFF,0xF8 , 0x00,0x07,0xFF,0xF8],
|
|
||||||
//[0x00,0x0F,0xFF,0xF0 , 0x00,0x0F,0xFF,0xF0 , 0x00,0x1F,0xFF,0xE0 , 0x00,0x1F,0xFF,0xE0],
|
|
||||||
//[0x00,0x3F,0xFF,0xC0 , 0x00,0x3F,0xFF,0xC0 , 0x00,0x7F,0xFF,0x80 , 0x00,0x7F,0xFF,0x80],
|
|
||||||
//[0x00,0xFF,0xFF,0x00 , 0x00,0xFF,0xFF,0x00 , 0x01,0xFF,0xFE,0x00 , 0x01,0xFF,0xFE,0x00],
|
|
||||||
//[0x03,0xFF,0xFC,0x00 , 0x03,0xFF,0xFC,0x00 , 0x07,0xFF,0xF8,0x00 , 0x07,0xFF,0xF8,0x00],
|
|
||||||
//[0x0F,0xFF,0xF0,0x00 , 0x0F,0xFF,0xF0,0x00 , 0x1F,0xFF,0xE0,0x00 , 0x1F,0xFF,0xE0,0x00],
|
|
||||||
//[0x3F,0xFF,0xC0,0x00 , 0x3F,0xFF,0xC0,0x00 , 0x7F,0xFF,0x80,0x00 , 0x7F,0xFF,0x80,0x00],
|
|
||||||
|
|
||||||
[0x00,0xFF,0xAA,0x55 , 0x69,0x0F,0xA5,0x1E , 0xC7,0x71,0x8E,0xE3 , 0xCA,0xFE,0xBA,0xBE],
|
[0x00,0xFF,0xAA,0x55 , 0x69,0x0F,0xA5,0x1E , 0xC7,0x71,0x8E,0xE3 , 0xCA,0xFE,0xBA,0xBE],
|
||||||
[0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF]
|
[0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF , 0xFF,0xFF,0xFF,0xFF]
|
||||||
];
|
];
|
||||||
@@ -82,5 +61,20 @@ Object.freeze(_BIOS);
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO load a bootsector using 'LOADBOOT'
|
// load a bootsector using 'LOADBOOT'
|
||||||
con.move(4,1);
|
let portNumber = 0;
|
||||||
|
let driveStatus = 0;
|
||||||
|
while (portNumber < 4) {
|
||||||
|
if (com.areYouThere(portNumber)) {
|
||||||
|
com.sendMessage(portNumber, "LOADBOOT");
|
||||||
|
driveStatus = com.getStatusCode(portNumber);
|
||||||
|
if (driveStatus == 0) break;
|
||||||
|
}
|
||||||
|
portNumber += 1;
|
||||||
|
}
|
||||||
|
if (portNumber < 4) {
|
||||||
|
eval(com.fetchResponse(portNumber).trimNull());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printerrln("No bootable medium found.");
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import net.torvald.UnsafeHelper
|
|||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
|
||||||
import net.torvald.tsvm.peripheral.BlockTransferInterface.Companion.BLOCK_SIZE
|
import net.torvald.tsvm.peripheral.BlockTransferInterface.Companion.BLOCK_SIZE
|
||||||
import net.torvald.tsvm.peripheral.BlockTransferInterface.Companion.END_OF_SEND_BLOCK
|
import net.torvald.tsvm.peripheral.BlockTransferInterface.Companion.END_OF_SEND_BLOCK
|
||||||
|
import net.torvald.tsvm.peripheral.trimNull
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
import kotlin.experimental.or
|
import kotlin.experimental.or
|
||||||
@@ -95,10 +96,10 @@ object SerialHelper {
|
|||||||
|
|
||||||
fun getStatusCode(vm: VM, portNo: Int) = vm.getIO().mmio_read(4080L + portNo)
|
fun getStatusCode(vm: VM, portNo: Int) = vm.getIO().mmio_read(4080L + portNo)
|
||||||
|
|
||||||
private fun checkIfDeviceIsThere(vm: VM, portNo: Int) =
|
fun checkIfDeviceIsThere(vm: VM, portNo: Int) =
|
||||||
(vm.getIO().mmio_read(4092L + portNo)!! and 1.toByte()) == 1.toByte()
|
(vm.getIO().mmio_read(4092L + portNo)!! and 1.toByte()) == 1.toByte()
|
||||||
|
|
||||||
private fun checkIfDeviceIsReady(vm: VM, portNo: Int) =
|
fun checkIfDeviceIsReady(vm: VM, portNo: Int) =
|
||||||
(vm.getIO().mmio_read(4092L + portNo)!! and 0b111.toByte()) == 0b011.toByte()
|
(vm.getIO().mmio_read(4092L + portNo)!! and 0b111.toByte()) == 0b011.toByte()
|
||||||
|
|
||||||
private fun initiateWriting(vm: VM, portNo: Int) {
|
private fun initiateWriting(vm: VM, portNo: Int) {
|
||||||
@@ -145,4 +146,5 @@ class SerialHelperDelegate(val vm: VM) {
|
|||||||
fun getStatusCode(portNo: Int) = SerialHelper.getStatusCode(vm, portNo)
|
fun getStatusCode(portNo: Int) = SerialHelper.getStatusCode(vm, portNo)
|
||||||
/** @return Object where { code: <Int>, message: <String> } */
|
/** @return Object where { code: <Int>, message: <String> } */
|
||||||
fun getDeviceStatus(portNo: Int) = SerialHelper.getDeviceStatus(vm, portNo)
|
fun getDeviceStatus(portNo: Int) = SerialHelper.getDeviceStatus(vm, portNo)
|
||||||
|
fun areYouThere(portNo: Int) = SerialHelper.checkIfDeviceIsThere(vm, portNo)
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||||
|
import java.io.File
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
|
|
||||||
class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
||||||
@@ -51,31 +52,10 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
|
|||||||
|
|
||||||
memvwr = Memvwr(vm)
|
memvwr = Memvwr(vm)
|
||||||
|
|
||||||
// TEST PRG
|
// load test bios
|
||||||
//val fr = FileReader("./assets/tvdos/command.js")
|
|
||||||
//val fr = FileReader("./assets/jscon.js")
|
|
||||||
|
|
||||||
val fr1 = FileReader("./assets/bios1.js")
|
|
||||||
//val fr1 = FileReader("./assets/phototest.js")
|
|
||||||
val bios = fr1.readText()
|
|
||||||
fr1.close()
|
|
||||||
|
|
||||||
//val fr = FileReader("./assets/tvdos/command.js")
|
|
||||||
//val fr = FileReader("./assets/zippytest.js")
|
|
||||||
//val fr = FileReader("./assets/serialtest.js")
|
|
||||||
//val fr = FileReader("./assets/tvdos/fsh.js")
|
|
||||||
//val fr = FileReader("./assets/tvdos/flsh.js")
|
|
||||||
//val fr = FileReader("./assets/tbas/basic.js")
|
|
||||||
//val fr = FileReader("./assets/jscon.js")
|
|
||||||
val fr = FileReader("./assets/!BOOTSEC")
|
|
||||||
val prg = fr.readText()
|
|
||||||
fr.close()
|
|
||||||
|
|
||||||
vmRunner = VMRunnerFactory(vm, "js")
|
vmRunner = VMRunnerFactory(vm, "js")
|
||||||
coroutineJob = GlobalScope.launch {
|
coroutineJob = GlobalScope.launch {
|
||||||
//vmRunner.evalGlobal("$bios")
|
vmRunner.executeCommand(File("./assets/bios1.js").readText(VM.CHARSET))
|
||||||
//vmRunner.executeCommand(prg)
|
|
||||||
vmRunner.executeCommand("$bios\n$prg")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,14 +86,14 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
|
|||||||
const val BAD_NEWS = 0x15.toByte()
|
const val BAD_NEWS = 0x15.toByte()
|
||||||
const val UNIT_SEP = 0x1F.toByte()
|
const val UNIT_SEP = 0x1F.toByte()
|
||||||
const val END_OF_SEND_BLOCK = 0x17.toByte()
|
const val END_OF_SEND_BLOCK = 0x17.toByte()
|
||||||
|
|
||||||
fun trimNull(ba: ByteArray): ByteArray {
|
|
||||||
var cnt = BLOCK_SIZE - 1
|
|
||||||
while (cnt >= 0) {
|
|
||||||
if (ba[cnt] != 0.toByte()) break
|
|
||||||
cnt -= 1
|
|
||||||
}
|
|
||||||
return ba.sliceArray(0..cnt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ByteArray.trimNull(): ByteArray {
|
||||||
|
var cnt = BlockTransferInterface.BLOCK_SIZE - 1
|
||||||
|
while (cnt >= 0) {
|
||||||
|
if (this[cnt] != 0.toByte()) break
|
||||||
|
cnt -= 1
|
||||||
|
}
|
||||||
|
return this.sliceArray(0..cnt)
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package net.torvald.tsvm.peripheral
|
|||||||
import net.torvald.tsvm.VM
|
import net.torvald.tsvm.VM
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val inputString = trimNull(inputData).toString(VM.CHARSET)
|
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||||
|
|
||||||
if (inputString.startsWith("DEVRST\u0017")) {
|
if (inputString.startsWith("DEVRST\u0017")) {
|
||||||
println("[TestDiskDrive] Device Reset")
|
println("[TestDiskDrive] Device Reset")
|
||||||
@@ -217,6 +218,37 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (inputString.startsWith("LOADBOOT")) {
|
||||||
|
var commaIndex = 0
|
||||||
|
while (commaIndex < inputString.length) {
|
||||||
|
if (inputString[commaIndex] == ',') break
|
||||||
|
commaIndex += 1
|
||||||
|
}
|
||||||
|
val driveNum = if (commaIndex >= inputString.length) null else commaIndex
|
||||||
|
|
||||||
|
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
|
||||||
|
|
||||||
|
val bootFile = File(rootPath, "!BOOTSEC")
|
||||||
|
|
||||||
|
if (!bootFile.exists()) {
|
||||||
|
statusCode = STATE_CODE_FILE_NOT_FOUND
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val fis = FileInputStream(bootFile)
|
||||||
|
try {
|
||||||
|
val retMsg = ByteArray(BLOCK_SIZE)
|
||||||
|
fis.read(retMsg)
|
||||||
|
recipient?.writeout(retMsg)
|
||||||
|
statusCode = STATE_CODE_STANDBY
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
statusCode = STATE_CODE_SYSTEM_IO_ERROR
|
||||||
|
return
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
fis.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (inputString.startsWith("WRITE")) {
|
else if (inputString.startsWith("WRITE")) {
|
||||||
if (!fileOpen || fileOpenMode < 0) {
|
if (!fileOpen || fileOpenMode < 0) {
|
||||||
statusCode = STATE_CODE_OPERATION_NOT_PERMITTED
|
statusCode = STATE_CODE_OPERATION_NOT_PERMITTED
|
||||||
@@ -228,8 +260,10 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
|||||||
}
|
}
|
||||||
writeMode = true
|
writeMode = true
|
||||||
writeModeLength = inputString.substring(5, inputString.length).toInt()
|
writeModeLength = inputString.substring(5, inputString.length).toInt()
|
||||||
statusCode = 0
|
statusCode = STATE_CODE_STANDBY
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
statusCode = STATE_CODE_ILLEGAL_COMMAND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ Nunc mollis nibh vitae sapien consequat, ut vestibulum sem pharetra. Aliquam iac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val inputString = trimNull(inputData).toString(VM.CHARSET)
|
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||||
|
|
||||||
if (inputString.startsWith("DEVRST\u0017")) {
|
if (inputString.startsWith("DEVRST\u0017")) {
|
||||||
fileOpen = false
|
fileOpen = false
|
||||||
@@ -171,6 +171,8 @@ Nunc mollis nibh vitae sapien consequat, ut vestibulum sem pharetra. Aliquam iac
|
|||||||
writeModeLength = inputString.substring(5, inputString.length).toInt()
|
writeModeLength = inputString.substring(5, inputString.length).toInt()
|
||||||
statusCode = 0
|
statusCode = 0
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
statusCode = 128
|
||||||
|
|
||||||
blockSendCount = 0
|
blockSendCount = 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user