mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-14 23:16:06 +09:00
working HSDPA impl with driver -- this time
This commit is contained in:
@@ -131,9 +131,11 @@ for (let tapeIndex = 0; tapeIndex < 4; tapeIndex++) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// If offset specified, rewind and skip to position
|
// If offset specified, rewind and skip to position
|
||||||
if (offset && offset > 0) {
|
if (offset !== undefined && offset >= 0) {
|
||||||
hsdpa.rewind()
|
hsdpa.rewind()
|
||||||
hsdpa.skip(offset)
|
if (offset > 0) {
|
||||||
|
hsdpa.skip(offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read data to VM memory
|
// Read data to VM memory
|
||||||
|
|||||||
@@ -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, bytes & 0xFF) // LSB
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 1, (bytes >> 8) & 0xFF) // MSB
|
sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 1, (bytes >> 8) & 0xFF) // MSB
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 2, (bytes >> 16) & 0xFF) // MSB2
|
sys.poke(HSDPA_REG_SEQ_IO_ARG1 - 2, (bytes >> 16) & 0xFF) // MSB2
|
||||||
// Write arg2 (VM memory pointer) - using backwards addressing
|
// Write arg2 (VM memory pointer) - handle negative numbers correctly
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_ARG2, vmMemoryPointer & 0xFF) // LSB
|
let ptr = vmMemoryPointer >>> 0 // Convert to unsigned 32-bit
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 1, (vmMemoryPointer >> 8) & 0xFF) // MSB
|
sys.poke(HSDPA_REG_SEQ_IO_ARG2, ptr & 0xFF) // LSB
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_ARG2 - 2, (vmMemoryPointer >> 16) & 0xFF) // MSB2
|
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
|
// Execute read operation
|
||||||
sys.poke(HSDPA_REG_SEQ_IO_OPCODE, HSDPA_OPCODE_READ)
|
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
|
let ptr = (ptrToDecode === undefined) ? sys.malloc(length) : ptrToDecode
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Skip to current read position if needed
|
// Read directly using HSDPA - position is maintained automatically by HSDPA
|
||||||
if (readCount > 0) {
|
|
||||||
hsdpaRewind()
|
|
||||||
if (readCount > 0) {
|
|
||||||
hsdpaSkip(readCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read directly using HSDPA - no 4096 byte limitation!
|
|
||||||
hsdpaReadToMemory(length, ptr)
|
hsdpaReadToMemory(length, ptr)
|
||||||
|
|
||||||
readCount += length
|
readCount += length
|
||||||
@@ -155,17 +148,16 @@ function readBytes(length, ptrToDecode) {
|
|||||||
|
|
||||||
function readInt() {
|
function readInt() {
|
||||||
let b = readBytes(4)
|
let b = readBytes(4)
|
||||||
let i = (sys.peek(b) & 0xFF) |
|
let i = (sys.peek(b)) | (sys.peek(b+1) << 8) | (sys.peek(b+2) << 16) | (sys.peek(b+3) << 24)
|
||||||
((sys.peek(b+1) & 0xFF) << 8) |
|
|
||||||
((sys.peek(b+2) & 0xFF) << 16) |
|
|
||||||
((sys.peek(b+3) & 0xFF) << 24)
|
|
||||||
sys.free(b)
|
sys.free(b)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
function readShort() {
|
function readShort() {
|
||||||
let b = readBytes(2)
|
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)
|
sys.free(b)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
override fun mmio_write(addr: Long, value: Byte) {
|
||||||
val address = addr.toInt()
|
val address = addr.toInt()
|
||||||
println("HSDPA: mmio_write(addr=$addr, value=0x${(value.toInt() and 0xFF).toString(16)})")
|
|
||||||
when (address) {
|
when (address) {
|
||||||
in REG_DISK1_STATUS..REG_DISK4_STATUS+2 -> {
|
in REG_DISK1_STATUS..REG_DISK4_STATUS+2 -> {
|
||||||
val diskIndex = (address - REG_DISK1_STATUS) / 3
|
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 -> {
|
REG_SEQ_IO_OPCODE -> {
|
||||||
opcodeBuf = value.toUint()
|
opcodeBuf = value.toUint()
|
||||||
println("HSDPA: Writing opcode 0x${value.toUint().toString(16)} to register")
|
|
||||||
handleSequentialIOOpcode(value.toUint())
|
handleSequentialIOOpcode(value.toUint())
|
||||||
}
|
}
|
||||||
in REG_SEQ_IO_ARG1..REG_SEQ_IO_ARG1+2 -> {
|
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
|
* @param opcode Opcode to handle
|
||||||
*/
|
*/
|
||||||
protected open fun handleSequentialIOOpcode(opcode: Int) {
|
protected open fun handleSequentialIOOpcode(opcode: Int) {
|
||||||
println("HSDPA: handleSequentialIOOpcode(0x${opcode.toString(16)})")
|
|
||||||
when (opcode) {
|
when (opcode) {
|
||||||
OPCODE_NOP -> {
|
OPCODE_NOP -> {
|
||||||
// No operation
|
// No operation
|
||||||
println("HSDPA: NOP")
|
|
||||||
}
|
}
|
||||||
OPCODE_SKIP -> {
|
OPCODE_SKIP -> {
|
||||||
// Skip arg1 bytes in the active disk
|
// Skip arg1 bytes in the active disk
|
||||||
println("HSDPA: SKIP $arg1 bytes, activeDisk=$activeDisk")
|
|
||||||
if (activeDisk in 0 until MAX_DISKS) {
|
if (activeDisk in 0 until MAX_DISKS) {
|
||||||
sequentialIOSkip(arg1)
|
sequentialIOSkip(arg1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OPCODE_READ -> {
|
OPCODE_READ -> {
|
||||||
// Read arg1 bytes and store to core memory at pointer arg2
|
// 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) {
|
if (activeDisk in 0 until MAX_DISKS) {
|
||||||
sequentialIORead(arg1, arg2)
|
sequentialIORead(arg1, arg2)
|
||||||
}
|
}
|
||||||
@@ -382,7 +375,6 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa
|
|||||||
}
|
}
|
||||||
OPCODE_REWIND -> {
|
OPCODE_REWIND -> {
|
||||||
// Rewind to starting point
|
// Rewind to starting point
|
||||||
println("HSDPA: REWIND to position 0")
|
|
||||||
sequentialIOPosition = 0L
|
sequentialIOPosition = 0L
|
||||||
}
|
}
|
||||||
OPCODE_TERMINATE -> {
|
OPCODE_TERMINATE -> {
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ import java.io.RandomAccessFile
|
|||||||
class HostFileHSDPA : HSDPA {
|
class HostFileHSDPA : HSDPA {
|
||||||
|
|
||||||
// Primary constructor for Java reflection compatibility
|
// Primary constructor for Java reflection compatibility
|
||||||
constructor(vm: VM, hostFilePaths: Array<String>, baudRate: java.lang.Long) : super(vm, baudRate.toLong()) {
|
constructor(vm: VM,
|
||||||
initializeHostFiles(hostFilePaths.toList())
|
hostFilePath0: String,
|
||||||
}
|
hostFilePath1: String,
|
||||||
|
hostFilePath2: String,
|
||||||
// Secondary constructor for Kotlin usage
|
hostFilePath3: String,
|
||||||
constructor(vm: VM, hostFilePaths: List<String> = emptyList(), baudRate: Long = 133_333_333L) : super(vm, baudRate) {
|
baudRate: java.lang.Long) : super(vm, baudRate.toLong()) {
|
||||||
initializeHostFiles(hostFilePaths)
|
initializeHostFiles(listOf(hostFilePath0, hostFilePath1, hostFilePath2, hostFilePath3))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host files for each disk slot
|
// Host files for each disk slot
|
||||||
@@ -113,66 +113,85 @@ class HostFileHSDPA : HSDPA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sequentialIORead(bytes: Int, vmMemoryPointer: Int) {
|
override fun sequentialIORead(bytes: Int, vmMemoryPointer0: Int) {
|
||||||
println("HostFileHSDPA: sequentialIORead($bytes, $vmMemoryPointer)")
|
|
||||||
val activeDiskIndex = getActiveDiskIndex()
|
val activeDiskIndex = getActiveDiskIndex()
|
||||||
println("HostFileHSDPA: activeDiskIndex = $activeDiskIndex")
|
|
||||||
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
||||||
// No file attached, just advance position
|
// No file attached, just advance position
|
||||||
println("HostFileHSDPA: No file attached, advancing position")
|
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert Uint24 to Int32
|
||||||
|
val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0)
|
||||||
|
(0xFF000000.toInt() or vmMemoryPointer0)
|
||||||
|
else
|
||||||
|
vmMemoryPointer0
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val file = hostFiles[activeDiskIndex]!!
|
val file = hostFiles[activeDiskIndex]!!
|
||||||
println("HostFileHSDPA: Seeking to position $sequentialIOPosition")
|
val readPosition = sequentialIOPosition
|
||||||
file.seek(sequentialIOPosition)
|
file.seek(sequentialIOPosition)
|
||||||
|
|
||||||
// Read data into a temporary buffer
|
// Read data into a temporary buffer
|
||||||
val readBuffer = ByteArray(bytes)
|
val readBuffer = ByteArray(bytes)
|
||||||
val bytesRead = file.read(readBuffer)
|
val bytesRead = file.read(readBuffer)
|
||||||
println("HostFileHSDPA: Read $bytesRead bytes from file")
|
|
||||||
|
|
||||||
if (bytesRead > 0) {
|
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
|
// Copy data to VM memory
|
||||||
for (i in 0 until bytesRead) {
|
// Handle negative addresses (backwards addressing) vs positive addresses
|
||||||
vm.poke(vmMemoryPointer + i.toLong(), readBuffer[i])
|
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
|
sequentialIOPosition += bytesRead
|
||||||
println("HostFileHSDPA: Copied $bytesRead bytes to VM memory at $vmMemoryPointer")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill remaining bytes with zeros if we read less than requested
|
// Fill remaining bytes with zeros if we read less than requested
|
||||||
if (bytesRead < bytes) {
|
if (bytesRead < bytes) {
|
||||||
for (i in bytesRead until bytes) {
|
if (vmMemoryPointer < 0) {
|
||||||
vm.poke(vmMemoryPointer + i.toLong(), 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)
|
sequentialIOPosition += (bytes - bytesRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("HSDPA: Error reading from file: ${e.message}")
|
|
||||||
// Just advance position on error
|
// Just advance position on error
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sequentialIOWrite(bytes: Int, vmMemoryPointer: Int) {
|
override fun sequentialIOWrite(bytes: Int, vmMemoryPointer0: Int) {
|
||||||
val activeDiskIndex = getActiveDiskIndex()
|
val activeDiskIndex = getActiveDiskIndex()
|
||||||
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
||||||
// No file attached, just advance position
|
// No file attached, just advance position
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
return
|
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
|
// For now, we only support read-only access to host files
|
||||||
// In a full implementation, we would write to the file here
|
// In a full implementation, we would write to the file here
|
||||||
println("HSDPA: Write operation not supported in read-only mode")
|
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class AppLoader {
|
|||||||
|
|
||||||
ArrayList defaultPeripherals = new ArrayList();
|
ArrayList defaultPeripherals = new ArrayList();
|
||||||
defaultPeripherals.add(new Pair(3, new PeripheralEntry2("net.torvald.tsvm.peripheral.AudioAdapter", vm)));
|
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);
|
EmulInstance reference = new EmulInstance(vm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", diskPath, 560, 448, defaultPeripherals);
|
||||||
|
|||||||
Reference in New Issue
Block a user