mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
booting entirely from the bios
This commit is contained in:
@@ -300,9 +300,23 @@ function println(s) {
|
||||
else
|
||||
sys.println(s);
|
||||
}
|
||||
function printerr(s) {
|
||||
print("\x1B[31m"+s+"\x1B[m");
|
||||
}
|
||||
function printerrln(s) {
|
||||
println("\x1B[31m"+s+"\x1B[m");
|
||||
}
|
||||
function 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
|
||||
var con = {};
|
||||
con.getch = function() {
|
||||
|
||||
@@ -7,27 +7,6 @@ println("TERRAN Megatrends inc.");
|
||||
|
||||
let memptr = 0;
|
||||
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],
|
||||
[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'
|
||||
con.move(4,1);
|
||||
// load a bootsector using 'LOADBOOT'
|
||||
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.tsvm.peripheral.BlockTransferInterface.Companion.BLOCK_SIZE
|
||||
import net.torvald.tsvm.peripheral.BlockTransferInterface.Companion.END_OF_SEND_BLOCK
|
||||
import net.torvald.tsvm.peripheral.trimNull
|
||||
import java.io.ByteArrayOutputStream
|
||||
import kotlin.experimental.and
|
||||
import kotlin.experimental.or
|
||||
@@ -95,10 +96,10 @@ object SerialHelper {
|
||||
|
||||
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()
|
||||
|
||||
private fun checkIfDeviceIsReady(vm: VM, portNo: Int) =
|
||||
fun checkIfDeviceIsReady(vm: VM, portNo: Int) =
|
||||
(vm.getIO().mmio_read(4092L + portNo)!! and 0b111.toByte()) == 0b011.toByte()
|
||||
|
||||
private fun initiateWriting(vm: VM, portNo: Int) {
|
||||
@@ -145,4 +146,5 @@ class SerialHelperDelegate(val vm: VM) {
|
||||
fun getStatusCode(portNo: Int) = SerialHelper.getStatusCode(vm, portNo)
|
||||
/** @return Object where { code: <Int>, message: <String> } */
|
||||
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 kotlinx.coroutines.*
|
||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
|
||||
class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
||||
@@ -51,31 +52,10 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
|
||||
|
||||
memvwr = Memvwr(vm)
|
||||
|
||||
// TEST PRG
|
||||
//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()
|
||||
|
||||
// load test bios
|
||||
vmRunner = VMRunnerFactory(vm, "js")
|
||||
coroutineJob = GlobalScope.launch {
|
||||
//vmRunner.evalGlobal("$bios")
|
||||
//vmRunner.executeCommand(prg)
|
||||
vmRunner.executeCommand("$bios\n$prg")
|
||||
vmRunner.executeCommand(File("./assets/bios1.js").readText(VM.CHARSET))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,14 +86,14 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
|
||||
const val BAD_NEWS = 0x15.toByte()
|
||||
const val UNIT_SEP = 0x1F.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 java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
@@ -122,7 +123,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
||||
}
|
||||
}
|
||||
else {
|
||||
val inputString = trimNull(inputData).toString(VM.CHARSET)
|
||||
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||
|
||||
if (inputString.startsWith("DEVRST\u0017")) {
|
||||
println("[TestDiskDrive] Device Reset")
|
||||
@@ -217,6 +218,37 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
||||
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")) {
|
||||
if (!fileOpen || fileOpenMode < 0) {
|
||||
statusCode = STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
@@ -228,8 +260,10 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
|
||||
}
|
||||
writeMode = true
|
||||
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 {
|
||||
val inputString = trimNull(inputData).toString(VM.CHARSET)
|
||||
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||
|
||||
if (inputString.startsWith("DEVRST\u0017")) {
|
||||
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()
|
||||
statusCode = 0
|
||||
}
|
||||
else
|
||||
statusCode = 128
|
||||
|
||||
blockSendCount = 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user