mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
HSDPA supporting file larger than 2GB
This commit is contained in:
@@ -117,8 +117,9 @@ for (let tapeIndex = 0; tapeIndex < 4; tapeIndex++) {
|
|||||||
|
|
||||||
// Get file size - for HSDPA tapes, we don't know the size ahead of time
|
// Get file size - for HSDPA tapes, we don't know the size ahead of time
|
||||||
// So we return a very large number to indicate it's available
|
// So we return a very large number to indicate it's available
|
||||||
|
// Using Number.MAX_SAFE_INTEGER to support files >2GB
|
||||||
driver.getFileLen = (fd) => {
|
driver.getFileLen = (fd) => {
|
||||||
return 0x7FFFFFFF // Return max positive 32-bit integer
|
return Number.MAX_SAFE_INTEGER // 2^53 - 1 (9007199254740991) - safe for JS arithmetic
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sequential read from tape
|
// Sequential read from tape
|
||||||
|
|||||||
@@ -548,11 +548,20 @@ function tryReadNextTAVHeader() {
|
|||||||
offsetBytes.push(seqread.readOneByte())
|
offsetBytes.push(seqread.readOneByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
element.offset = 0
|
// Split into low 32 bits and high 16 bits
|
||||||
for (let j = 0; j < 6; j++) {
|
let low32 = 0
|
||||||
element.offset |= (offsetBytes[j] << (j * 8))
|
for (let j = 0; j < 4; j++) {
|
||||||
|
low32 |= (offsetBytes[j] << (j * 8))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let high16 = 0
|
||||||
|
for (let j = 4; j < 6; j++) {
|
||||||
|
high16 |= (offsetBytes[j] << ((j - 4) * 8))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine using multiplication (avoids bitwise 32-bit limit)
|
||||||
|
element.offset = (high16 * 0x100000000) + (low32 >>> 0)
|
||||||
|
|
||||||
serial.println(`Element ${i + 1}: ${element.name} -> offset ${element.offset} (internal)`)
|
serial.println(`Element ${i + 1}: ${element.name} -> offset ${element.offset} (internal)`)
|
||||||
} else {
|
} else {
|
||||||
serial.println(`Error: Unknown addressing mode: ${element.addressingMode}`)
|
serial.println(`Error: Unknown addressing mode: ${element.addressingMode}`)
|
||||||
@@ -585,6 +594,7 @@ function tryReadNextTAVHeader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lastKey = 0
|
let lastKey = 0
|
||||||
|
let skipped = false
|
||||||
|
|
||||||
// Playback loop - properly adapted from TEV with multi-file support
|
// Playback loop - properly adapted from TEV with multi-file support
|
||||||
try {
|
try {
|
||||||
@@ -614,6 +624,7 @@ try {
|
|||||||
akku = FRAME_TIME
|
akku = FRAME_TIME
|
||||||
akku2 = 0.0
|
akku2 = 0.0
|
||||||
audio.purgeQueue(0)
|
audio.purgeQueue(0)
|
||||||
|
skipped = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (keyCode == 20 && cueElements.length > 0) { // Down arrow - next cue
|
else if (keyCode == 20 && cueElements.length > 0) { // Down arrow - next cue
|
||||||
@@ -627,6 +638,7 @@ try {
|
|||||||
akku = FRAME_TIME
|
akku = FRAME_TIME
|
||||||
akku2 = 0.0
|
akku2 = 0.0
|
||||||
audio.purgeQueue(0)
|
audio.purgeQueue(0)
|
||||||
|
skipped = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -652,6 +664,11 @@ try {
|
|||||||
FRAME_TIME = 1.0 / header.fps
|
FRAME_TIME = 1.0 / header.fps
|
||||||
audio.purgeQueue(0)
|
audio.purgeQueue(0)
|
||||||
currentFileIndex++
|
currentFileIndex++
|
||||||
|
if (skipped) {
|
||||||
|
skipped = false
|
||||||
|
} else {
|
||||||
|
currentCueIndex++
|
||||||
|
}
|
||||||
totalFilesProcessed++
|
totalFilesProcessed++
|
||||||
|
|
||||||
console.log(`\nStarting file ${currentFileIndex}:`)
|
console.log(`\nStarting file ${currentFileIndex}:`)
|
||||||
@@ -834,7 +851,6 @@ try {
|
|||||||
notifHidden = true
|
notifHidden = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
con.color_pair(253, 0)
|
con.color_pair(253, 0)
|
||||||
let guiStatus = {
|
let guiStatus = {
|
||||||
fps: header.fps,
|
fps: header.fps,
|
||||||
@@ -845,8 +861,8 @@ try {
|
|||||||
qCo: decoderDbgInfo.qCo,
|
qCo: decoderDbgInfo.qCo,
|
||||||
qCg: decoderDbgInfo.qCg,
|
qCg: decoderDbgInfo.qCg,
|
||||||
akku: akku2,
|
akku: akku2,
|
||||||
fileName: fullFilePathStr,
|
fileName: (cueElements.length > 0) ? `${cueElements[currentCueIndex].name}` : fullFilePathStr,
|
||||||
fileOrd: currentFileIndex,
|
fileOrd: (cueElements.length > 0) ? currentCueIndex+1 : currentFileIndex,
|
||||||
resolution: `${header.width}x${header.height}${(isInterlaced) ? 'i' : ''}`,
|
resolution: `${header.width}x${header.height}${(isInterlaced) ? 'i' : ''}`,
|
||||||
colourSpace: header.version % 2 == 0 ? "ICtCp" : "YCoCg",
|
colourSpace: header.version % 2 == 0 ? "ICtCp" : "YCoCg",
|
||||||
currentStatus: 1
|
currentStatus: 1
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ function skip(n0) {
|
|||||||
let n = n0
|
let n = n0
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
let skiplen = Math.min(n, 16777215)
|
let skiplen = Math.min(n, 16777215)
|
||||||
serial.println(`skip ${skiplen}; remaining: ${n}`)
|
// serial.println(`skip ${skiplen}; remaining: ${n}`)
|
||||||
hsdpaSkip(skiplen)
|
hsdpaSkip(skiplen)
|
||||||
n -= skiplen
|
n -= skiplen
|
||||||
}
|
}
|
||||||
@@ -237,14 +237,23 @@ function isReady() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function seek(position) {
|
function seek(position) {
|
||||||
|
if (position < 0) {
|
||||||
|
throw Error("seek: position must be non-negative")
|
||||||
|
}
|
||||||
|
|
||||||
let relPos = position - readCount
|
let relPos = position - readCount
|
||||||
if (position == 0) {
|
|
||||||
return
|
if (relPos == 0) {
|
||||||
} else if (position > 0) {
|
return // Already at target position
|
||||||
skip(relPos)
|
} else if (relPos < 0) {
|
||||||
|
// Seeking backward - must rewind and skip forward
|
||||||
|
hsdpaRewind() // This resets readCount to 0
|
||||||
|
if (position > 0) {
|
||||||
|
skip(position)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
hsdpaRewind()
|
// Seeking forward - skip the difference
|
||||||
skip(position)
|
skip(relPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var opcodeBuf = 0
|
private var opcodeBuf = 0
|
||||||
private var arg1 = 0
|
private var arg1 = 0L // Long to support >2GB sequential I/O position accumulation
|
||||||
private var arg2 = 0
|
private var arg2 = 0L // Long to support >2GB memory addressing
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a value from the MMIO register
|
* Reads a value from the MMIO register
|
||||||
@@ -167,18 +167,18 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa
|
|||||||
val byteOffset = (address - REG_SEQ_IO_ARG1)
|
val byteOffset = (address - REG_SEQ_IO_ARG1)
|
||||||
if (byteOffset == 0) {
|
if (byteOffset == 0) {
|
||||||
// Reset arg1 when writing to LSB
|
// Reset arg1 when writing to LSB
|
||||||
arg1 = value.toUint()
|
arg1 = value.toUint().toLong()
|
||||||
} else {
|
} else {
|
||||||
arg1 = arg1 or (value.toUint() shl (byteOffset * 8))
|
arg1 = arg1 or ((value.toUint().toLong()) shl (byteOffset * 8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in REG_SEQ_IO_ARG2..REG_SEQ_IO_ARG2+2 -> {
|
in REG_SEQ_IO_ARG2..REG_SEQ_IO_ARG2+2 -> {
|
||||||
val byteOffset = (address - REG_SEQ_IO_ARG2)
|
val byteOffset = (address - REG_SEQ_IO_ARG2)
|
||||||
if (byteOffset == 0) {
|
if (byteOffset == 0) {
|
||||||
// Reset arg2 when writing to LSB
|
// Reset arg2 when writing to LSB
|
||||||
arg2 = value.toUint()
|
arg2 = value.toUint().toLong()
|
||||||
} else {
|
} else {
|
||||||
arg2 = arg2 or (value.toUint() shl (byteOffset * 8))
|
arg2 = arg2 or ((value.toUint().toLong()) shl (byteOffset * 8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
@@ -390,23 +390,23 @@ open class HSDPA(val vm: VM, val baudRate: Long = 133_333_333L): PeriBase("hsdpa
|
|||||||
/**
|
/**
|
||||||
* Skip bytes in sequential I/O mode
|
* Skip bytes in sequential I/O mode
|
||||||
*/
|
*/
|
||||||
protected open fun sequentialIOSkip(bytes: Int) {
|
protected open fun sequentialIOSkip(bytes: Long) {
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read bytes from disk to VM memory in sequential I/O mode
|
* Read bytes from disk to VM memory in sequential I/O mode
|
||||||
*/
|
*/
|
||||||
protected open fun sequentialIORead(bytes: Int, vmMemoryPointer: Int) {
|
protected open fun sequentialIORead(bytes: Long, vmMemoryPointer: Long) {
|
||||||
// Default implementation - subclasses should override
|
// Default implementation - subclasses should override
|
||||||
// For now, just advance the position
|
// For now, just advance the position
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write bytes from VM memory to disk in sequential I/O mode
|
* Write bytes from VM memory to disk in sequential I/O mode
|
||||||
*/
|
*/
|
||||||
protected open fun sequentialIOWrite(bytes: Int, vmMemoryPointer: Int) {
|
protected open fun sequentialIOWrite(bytes: Long, vmMemoryPointer: Long) {
|
||||||
// Default implementation - subclasses should override
|
// Default implementation - subclasses should override
|
||||||
// For now, just advance the position
|
// For now, just advance the position
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package net.torvald.tsvm.peripheral
|
|||||||
|
|
||||||
import net.torvald.tsvm.VM
|
import net.torvald.tsvm.VM
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.RandomAccessFile
|
import java.io.FileInputStream
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.channels.FileChannel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Host File High Speed Disk Peripheral Adapter (HostFileHSDPA)
|
* Host File High Speed Disk Peripheral Adapter (HostFileHSDPA)
|
||||||
@@ -25,7 +27,8 @@ class HostFileHSDPA : HSDPA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Host files for each disk slot
|
// Host files for each disk slot
|
||||||
private val hostFiles = Array<RandomAccessFile?>(MAX_DISKS) { null }
|
private val hostFileStreams = Array<FileInputStream?>(MAX_DISKS) { null }
|
||||||
|
private val hostFileChannels = Array<FileChannel?>(MAX_DISKS) { null }
|
||||||
private val hostFilePaths = Array<String?>(MAX_DISKS) { null }
|
private val hostFilePaths = Array<String?>(MAX_DISKS) { null }
|
||||||
|
|
||||||
private fun initializeHostFiles(hostFilePathsList: List<String>) {
|
private fun initializeHostFiles(hostFilePathsList: List<String>) {
|
||||||
@@ -33,7 +36,9 @@ class HostFileHSDPA : HSDPA {
|
|||||||
for (i in 0 until minOf(hostFilePathsList.size, MAX_DISKS)) {
|
for (i in 0 until minOf(hostFilePathsList.size, MAX_DISKS)) {
|
||||||
val file = File(hostFilePathsList[i])
|
val file = File(hostFilePathsList[i])
|
||||||
if (file.exists() && file.isFile) {
|
if (file.exists() && file.isFile) {
|
||||||
this.hostFiles[i] = RandomAccessFile(file, "r")
|
val stream = FileInputStream(file)
|
||||||
|
this.hostFileStreams[i] = stream
|
||||||
|
this.hostFileChannels[i] = stream.channel
|
||||||
this.hostFilePaths[i] = hostFilePathsList[i]
|
this.hostFilePaths[i] = hostFilePathsList[i]
|
||||||
println("HostFileHSDPA: Attached file '${hostFilePathsList[i]}' to disk $i")
|
println("HostFileHSDPA: Attached file '${hostFilePathsList[i]}' to disk $i")
|
||||||
} else {
|
} else {
|
||||||
@@ -50,15 +55,18 @@ class HostFileHSDPA : HSDPA {
|
|||||||
*/
|
*/
|
||||||
fun attachHostFile(diskIndex: Int, filePath: String) {
|
fun attachHostFile(diskIndex: Int, filePath: String) {
|
||||||
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return
|
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Close existing file if any
|
// Close existing file if any
|
||||||
hostFiles[diskIndex]?.close()
|
hostFileChannels[diskIndex]?.close()
|
||||||
|
hostFileStreams[diskIndex]?.close()
|
||||||
|
|
||||||
// Open new file
|
// Open new file
|
||||||
val file = File(filePath)
|
val file = File(filePath)
|
||||||
if (file.exists() && file.isFile) {
|
if (file.exists() && file.isFile) {
|
||||||
hostFiles[diskIndex] = RandomAccessFile(file, "r")
|
val stream = FileInputStream(file)
|
||||||
|
hostFileStreams[diskIndex] = stream
|
||||||
|
hostFileChannels[diskIndex] = stream.channel
|
||||||
hostFilePaths[diskIndex] = filePath
|
hostFilePaths[diskIndex] = filePath
|
||||||
println("HSDPA: Attached file '$filePath' to disk $diskIndex")
|
println("HSDPA: Attached file '$filePath' to disk $diskIndex")
|
||||||
} else {
|
} else {
|
||||||
@@ -75,10 +83,12 @@ class HostFileHSDPA : HSDPA {
|
|||||||
*/
|
*/
|
||||||
fun detachHostFile(diskIndex: Int) {
|
fun detachHostFile(diskIndex: Int) {
|
||||||
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return
|
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
hostFiles[diskIndex]?.close()
|
hostFileChannels[diskIndex]?.close()
|
||||||
hostFiles[diskIndex] = null
|
hostFileStreams[diskIndex]?.close()
|
||||||
|
hostFileChannels[diskIndex] = null
|
||||||
|
hostFileStreams[diskIndex] = null
|
||||||
hostFilePaths[diskIndex] = null
|
hostFilePaths[diskIndex] = null
|
||||||
println("HSDPA: Detached file from disk $diskIndex")
|
println("HSDPA: Detached file from disk $diskIndex")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -93,15 +103,15 @@ class HostFileHSDPA : HSDPA {
|
|||||||
*/
|
*/
|
||||||
fun getAttachedFileSize(diskIndex: Int): Long {
|
fun getAttachedFileSize(diskIndex: Int): Long {
|
||||||
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return 0L
|
if (diskIndex < 0 || diskIndex >= MAX_DISKS) return 0L
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
hostFiles[diskIndex]?.length() ?: 0L
|
hostFileChannels[diskIndex]?.size() ?: 0L
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
0L
|
0L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sequentialIOSkip(bytes: Int) {
|
override fun sequentialIOSkip(bytes: Long) {
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
// Clamp position to file bounds if needed
|
// Clamp position to file bounds if needed
|
||||||
val activeDiskIndex = getActiveDiskIndex()
|
val activeDiskIndex = getActiveDiskIndex()
|
||||||
@@ -113,34 +123,36 @@ class HostFileHSDPA : HSDPA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sequentialIORead(bytes: Int, vmMemoryPointer0: Int) {
|
override fun sequentialIORead(bytes: Long, vmMemoryPointer0: Long) {
|
||||||
val activeDiskIndex = getActiveDiskIndex()
|
val activeDiskIndex = getActiveDiskIndex()
|
||||||
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
if (activeDiskIndex < 0 || hostFileChannels[activeDiskIndex] == null) {
|
||||||
// No file attached, just advance position
|
// No file attached, just advance position
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert Uint24 to Int32
|
// convert Int24 memory pointer to Int32
|
||||||
val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0)
|
val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0L)
|
||||||
(0xFF000000.toInt() or vmMemoryPointer0)
|
(0xFF000000.toInt().toLong() or vmMemoryPointer0)
|
||||||
else
|
else
|
||||||
vmMemoryPointer0
|
vmMemoryPointer0
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val file = hostFiles[activeDiskIndex]!!
|
val channel = hostFileChannels[activeDiskIndex]!!
|
||||||
val readPosition = sequentialIOPosition
|
|
||||||
file.seek(sequentialIOPosition)
|
// Read data using positional read (supports >2GB positions)
|
||||||
|
val buffer = ByteBuffer.allocate(bytes.toInt())
|
||||||
// Read data into a temporary buffer
|
val bytesRead = channel.read(buffer, sequentialIOPosition)
|
||||||
val readBuffer = ByteArray(bytes)
|
|
||||||
val bytesRead = file.read(readBuffer)
|
|
||||||
|
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
|
buffer.flip()
|
||||||
|
val readBuffer = ByteArray(bytesRead)
|
||||||
|
buffer.get(readBuffer)
|
||||||
|
|
||||||
// Copy data to VM memory
|
// Copy data to VM memory
|
||||||
// Handle negative addresses (backwards addressing) vs positive addresses
|
// Handle negative addresses (backwards addressing) vs positive addresses
|
||||||
if (vmMemoryPointer < 0) {
|
if (vmMemoryPointer < 0) {
|
||||||
// Negative addresses use backwards addressing
|
// Negative addresses use backwards addressing
|
||||||
for (i in 0 until bytesRead) {
|
for (i in 0 until bytesRead) {
|
||||||
vm.poke(vmMemoryPointer - i.toLong(), readBuffer[i])
|
vm.poke(vmMemoryPointer - i.toLong(), readBuffer[i])
|
||||||
}
|
}
|
||||||
@@ -151,42 +163,43 @@ class HostFileHSDPA : HSDPA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sequentialIOPosition += bytesRead
|
sequentialIOPosition += bytesRead
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
val actualBytesRead = if (bytesRead > 0) bytesRead else 0
|
||||||
|
if (actualBytesRead < bytes) {
|
||||||
if (vmMemoryPointer < 0) {
|
if (vmMemoryPointer < 0) {
|
||||||
// Negative addresses use backwards addressing
|
// Negative addresses use backwards addressing
|
||||||
for (i in bytesRead until bytes) {
|
for (i in actualBytesRead until bytes.toInt()) {
|
||||||
vm.poke(vmMemoryPointer - i.toLong(), 0)
|
vm.poke(vmMemoryPointer - i.toLong(), 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Positive addresses use forward addressing
|
// Positive addresses use forward addressing
|
||||||
for (i in bytesRead until bytes) {
|
for (i in actualBytesRead until bytes.toInt()) {
|
||||||
vm.poke(vmMemoryPointer + i.toLong(), 0)
|
vm.poke(vmMemoryPointer + i.toLong(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sequentialIOPosition += (bytes - bytesRead)
|
sequentialIOPosition += (bytes - actualBytesRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Just advance position on error
|
// Just advance position on error
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sequentialIOWrite(bytes: Int, vmMemoryPointer0: Int) {
|
override fun sequentialIOWrite(bytes: Long, vmMemoryPointer0: Long) {
|
||||||
val activeDiskIndex = getActiveDiskIndex()
|
val activeDiskIndex = getActiveDiskIndex()
|
||||||
if (activeDiskIndex < 0 || hostFiles[activeDiskIndex] == null) {
|
if (activeDiskIndex < 0 || hostFileChannels[activeDiskIndex] == null) {
|
||||||
// No file attached, just advance position
|
// No file attached, just advance position
|
||||||
sequentialIOPosition += bytes
|
sequentialIOPosition += bytes
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert Uint24 to Int32
|
// convert Int24 memory pointer to Int32
|
||||||
val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0)
|
val vmMemoryPointer = if (vmMemoryPointer0 and 0x800000 != 0L)
|
||||||
(0xFF000000.toInt() or vmMemoryPointer0)
|
(0xFF000000.toInt().toLong() or vmMemoryPointer0)
|
||||||
else
|
else
|
||||||
vmMemoryPointer0
|
vmMemoryPointer0
|
||||||
|
|
||||||
@@ -207,11 +220,12 @@ class HostFileHSDPA : HSDPA {
|
|||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
|
|
||||||
// Close all open files
|
// Close all open files
|
||||||
for (i in 0 until MAX_DISKS) {
|
for (i in 0 until MAX_DISKS) {
|
||||||
try {
|
try {
|
||||||
hostFiles[i]?.close()
|
hostFileChannels[i]?.close()
|
||||||
|
hostFileStreams[i]?.close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Ignore errors during cleanup
|
// Ignore errors during cleanup
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user