diff --git a/assets/disk0/tvdos/HSDPADRV.SYS b/assets/disk0/tvdos/HSDPADRV.SYS index f0e16ca..61878e1 100644 --- a/assets/disk0/tvdos/HSDPADRV.SYS +++ b/assets/disk0/tvdos/HSDPADRV.SYS @@ -131,9 +131,11 @@ for (let tapeIndex = 0; tapeIndex < 4; tapeIndex++) { try { // If offset specified, rewind and skip to position - if (offset && offset > 0) { + if (offset !== undefined && offset >= 0) { hsdpa.rewind() - hsdpa.skip(offset) + if (offset > 0) { + hsdpa.skip(offset) + } } // Read data to VM memory diff --git a/assets/disk0/tvdos/include/seqreadtape.mjs b/assets/disk0/tvdos/include/seqreadtape.mjs index 7f48d84..ca7358f 100644 --- a/assets/disk0/tvdos/include/seqreadtape.mjs +++ b/assets/disk0/tvdos/include/seqreadtape.mjs @@ -55,10 +55,11 @@ function hsdpaReadToMemory(bytes, vmMemoryPointer) { sys.poke(HSDPA_REG_SEQ_IO_ARG1, bytes & 0xFF) // LSB sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 1, (bytes >> 8) & 0xFF) // MSB sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 2, (bytes >> 16) & 0xFF) // MSB2 - // Write arg2 (VM memory pointer) - using backwards addressing - sys.poke(HSDPA_REG_SEQ_IO_ARG2, vmMemoryPointer & 0xFF) // LSB - sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 1, (vmMemoryPointer >> 8) & 0xFF) // MSB - sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 2, (vmMemoryPointer >> 16) & 0xFF) // MSB2 + // Write arg2 (VM memory pointer) - handle negative numbers correctly + let ptr = vmMemoryPointer >>> 0 // Convert to unsigned 32-bit + sys.poke(HSDPA_REG_SEQ_IO_ARG2, ptr & 0xFF) // LSB + sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 1, (ptr >> 8) & 0xFF) // MSB + sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 2, (ptr >> 16) & 0xFF) // MSB2 // Execute read operation sys.poke(HSDPA_REG_SEQ_IO_OPCODE, HSDPA_OPCODE_READ) } @@ -130,15 +131,7 @@ function readBytes(length, ptrToDecode) { let ptr = (ptrToDecode === undefined) ? sys.malloc(length) : ptrToDecode try { - // Skip to current read position if needed - if (readCount > 0) { - hsdpaRewind() - if (readCount > 0) { - hsdpaSkip(readCount) - } - } - - // Read directly using HSDPA - no 4096 byte limitation! + // Read directly using HSDPA - position is maintained automatically by HSDPA hsdpaReadToMemory(length, ptr) readCount += length @@ -155,17 +148,16 @@ function readBytes(length, ptrToDecode) { function readInt() { let b = readBytes(4) - let i = (sys.peek(b) & 0xFF) | - ((sys.peek(b+1) & 0xFF) << 8) | - ((sys.peek(b+2) & 0xFF) << 16) | - ((sys.peek(b+3) & 0xFF) << 24) + let i = (sys.peek(b)) | (sys.peek(b+1) << 8) | (sys.peek(b+2) << 16) | (sys.peek(b+3) << 24) sys.free(b) return i } function readShort() { let b = readBytes(2) - let i = (sys.peek(b) & 0xFF) | ((sys.peek(b+1) & 0xFF) << 8) + let byte0 = sys.peek(b) & 0xFF + let byte1 = sys.peek(b+1) & 0xFF + let i = byte0 | (byte1 << 8) sys.free(b) return i } diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/HSDPA.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/HSDPA.kt index 0d2fb18..3a2fd00 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/HSDPA.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/HSDPA.kt @@ -135,7 +135,6 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa */ override fun mmio_write(addr: Long, value: Byte) { val address = addr.toInt() - println("HSDPA: mmio_write(addr=$addr, value=0x${(value.toInt() and 0xFF).toString(16)})") when (address) { in REG_DISK1_STATUS..REG_DISK4_STATUS+2 -> { val diskIndex = (address - REG_DISK1_STATUS) / 3 @@ -162,7 +161,6 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa } REG_SEQ_IO_OPCODE -> { opcodeBuf = value.toUint() - println("HSDPA: Writing opcode 0x${value.toUint().toString(16)} to register") handleSequentialIOOpcode(value.toUint()) } in REG_SEQ_IO_ARG1..REG_SEQ_IO_ARG1+2 -> { @@ -353,23 +351,18 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa * @param opcode Opcode to handle */ protected open fun handleSequentialIOOpcode(opcode: Int) { - println("HSDPA: handleSequentialIOOpcode(0x${opcode.toString(16)})") when (opcode) { OPCODE_NOP -> { // No operation - println("HSDPA: NOP") } OPCODE_SKIP -> { // Skip arg1 bytes in the active disk - println("HSDPA: SKIP $arg1 bytes, activeDisk=$activeDisk") if (activeDisk in 0 until MAX_DISKS) { sequentialIOSkip(arg1) } } OPCODE_READ -> { // Read arg1 bytes and store to core memory at pointer arg2 - println("HSDPA: READ $arg1 bytes to pointer $arg2, activeDisk=$activeDisk") - println("HSDPA: arg1 = 0x${arg1.toString(16)}, arg2 = 0x${arg2.toString(16)}") if (activeDisk in 0 until MAX_DISKS) { sequentialIORead(arg1, arg2) } @@ -382,7 +375,6 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa } OPCODE_REWIND -> { // Rewind to starting point - println("HSDPA: REWIND to position 0") sequentialIOPosition = 0L } OPCODE_TERMINATE -> { diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/HostFileHSDPA.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/HostFileHSDPA.kt index 19068c7..9245e2e 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/HostFileHSDPA.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/HostFileHSDPA.kt @@ -15,13 +15,13 @@ import java.io.RandomAccessFile class HostFileHSDPA : HSDPA { // Primary constructor for Java reflection compatibility - constructor(vm: VM, hostFilePaths: Array, baudRate: java.lang.Long) : super(vm, baudRate.toLong()) { - initializeHostFiles(hostFilePaths.toList()) - } - - // Secondary constructor for Kotlin usage - constructor(vm: VM, hostFilePaths: List = emptyList(), baudRate: Long = 133_333_333L) : super(vm, baudRate) { - initializeHostFiles(hostFilePaths) + constructor(vm: VM, + hostFilePath0: String, + hostFilePath1: String, + hostFilePath2: String, + hostFilePath3: String, + baudRate: java.lang.Long) : super(vm, baudRate.toLong()) { + initializeHostFiles(listOf(hostFilePath0, hostFilePath1, hostFilePath2, hostFilePath3)) } // Host files for each disk slot @@ -113,66 +113,85 @@ class HostFileHSDPA : HSDPA { } } - override fun sequentialIORead(bytes: Int, vmMemoryPointer: Int) { - println("HostFileHSDPA: sequentialIORead($bytes, $vmMemoryPointer)") + override fun sequentialIORead(bytes: Int, vmMemoryPointer0: Int) { val activeDiskIndex = getActiveDiskIndex() - println("HostFileHSDPA: activeDiskIndex = $activeDiskIndex") if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) { // No file attached, just advance position - println("HostFileHSDPA: No file attached, advancing position") sequentialIOPosition += bytes return } - + + // convert Uint24 to Int32 + val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0) + (0xFF000000.toInt() or vmMemoryPointer0) + else + vmMemoryPointer0 + try { val file = hostFiles[activeDiskIndex]!! - println("HostFileHSDPA: Seeking to position $sequentialIOPosition") + val readPosition = sequentialIOPosition file.seek(sequentialIOPosition) // Read data into a temporary buffer val readBuffer = ByteArray(bytes) val bytesRead = file.read(readBuffer) - println("HostFileHSDPA: Read $bytesRead bytes from file") if (bytesRead > 0) { - // Log first few bytes for debugging - val firstBytes = readBuffer.take(8).map { (it.toInt() and 0xFF).toString(16).padStart(2, '0') }.joinToString(" ") - println("HostFileHSDPA: First bytes: $firstBytes") - // Copy data to VM memory - for (i in 0 until bytesRead) { - vm.poke(vmMemoryPointer + i.toLong(), readBuffer[i]) + // Handle negative addresses (backwards addressing) vs positive addresses + if (vmMemoryPointer < 0) { + // Negative addresses use backwards addressing + for (i in 0 until bytesRead) { + vm.poke(vmMemoryPointer - i.toLong(), readBuffer[i]) + } + } else { + // Positive addresses use forward addressing + for (i in 0 until bytesRead) { + vm.poke(vmMemoryPointer + i.toLong(), readBuffer[i]) + } } sequentialIOPosition += bytesRead - println("HostFileHSDPA: Copied $bytesRead bytes to VM memory at $vmMemoryPointer") + } // Fill remaining bytes with zeros if we read less than requested if (bytesRead < bytes) { - for (i in bytesRead until bytes) { - vm.poke(vmMemoryPointer + i.toLong(), 0) + if (vmMemoryPointer < 0) { + // Negative addresses use backwards addressing + for (i in bytesRead until bytes) { + vm.poke(vmMemoryPointer - i.toLong(), 0) + } + } else { + // Positive addresses use forward addressing + for (i in bytesRead until bytes) { + vm.poke(vmMemoryPointer + i.toLong(), 0) + } } sequentialIOPosition += (bytes - bytesRead) } } catch (e: Exception) { - println("HSDPA: Error reading from file: ${e.message}") // Just advance position on error sequentialIOPosition += bytes } } - override fun sequentialIOWrite(bytes: Int, vmMemoryPointer: Int) { + override fun sequentialIOWrite(bytes: Int, vmMemoryPointer0: Int) { val activeDiskIndex = getActiveDiskIndex() if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) { // No file attached, just advance position sequentialIOPosition += bytes return } - + + // convert Uint24 to Int32 + val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0) + (0xFF000000.toInt() or vmMemoryPointer0) + else + vmMemoryPointer0 + // For now, we only support read-only access to host files // In a full implementation, we would write to the file here - println("HSDPA: Write operation not supported in read-only mode") sequentialIOPosition += bytes } diff --git a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java index 4713090..49428ae 100644 --- a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java +++ b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java @@ -55,7 +55,7 @@ public class AppLoader { ArrayList defaultPeripherals = new ArrayList(); defaultPeripherals.add(new Pair(3, new PeripheralEntry2("net.torvald.tsvm.peripheral.AudioAdapter", vm))); - defaultPeripherals.add(new Pair(4, new PeripheralEntry2("net.torvald.tsvm.peripheral.HostFileHSDPA", vm, new String[]{"assets/diskMediabin/lg.mov"}, 133_333_333L))); + defaultPeripherals.add(new Pair(4, new PeripheralEntry2("net.torvald.tsvm.peripheral.HostFileHSDPA", vm, "assets/diskMediabin/lg.mov", "", "", "", 133_333_333L))); EmulInstance reference = new EmulInstance(vm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", diskPath, 560, 448, defaultPeripherals);