Finishing viewRead()/viewWrite()
This commit is contained in:
@@ -96,7 +96,7 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_isNative
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// Perform a read access
|
||||
// Read bytes from the CPU bus
|
||||
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_read
|
||||
(JNIEnv *env, jobject vue, jint address, jbyteArray data, jint offset,
|
||||
jint length) {
|
||||
@@ -106,7 +106,6 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_read
|
||||
data == NULL ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
length < 0 || length > 0x01000000 ||
|
||||
offset + length > (*env)->GetArrayLength(env, data)
|
||||
) return JNI_FALSE;
|
||||
|
||||
@@ -143,3 +142,24 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_setROM
|
||||
vueSetROM(&core->vue, rom, length);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/* Write bytes to the CPU bus */
|
||||
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_write
|
||||
(JNIEnv *env, jobject vue, jint address, jbyteArray data, jint offset,
|
||||
jint length) {
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
data == NULL ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
offset + length > (*env)->GetArrayLength(env, data)
|
||||
) return JNI_FALSE;
|
||||
|
||||
// Perform the operation
|
||||
CORE *core = GetCore(env, vue);
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, data, NULL);
|
||||
vueWrite(&core->vue, address, &elems[offset], length);
|
||||
(*env)->ReleaseByteArrayElements(env, data, elems, 0);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package vue;
|
||||
|
||||
// Java imports
|
||||
import java.util.*;
|
||||
|
||||
// Simulation of the CPU bus
|
||||
class Bus {
|
||||
|
||||
// Instance fields
|
||||
private JavaVUE vue; // Emulation state
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Constructors //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Default constructor
|
||||
Bus(JavaVUE vue) {
|
||||
this.vue = vue;
|
||||
}
|
||||
|
||||
// Read bytes from host memory
|
||||
void readBytes(byte[] src,byte[] dest,int address,int offset,int length) {
|
||||
|
||||
// There is no source data
|
||||
if (src == null) {
|
||||
Arrays.fill(dest, offset, offset + length, (byte) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy bytes from the source as a circular buffer
|
||||
int count = 0; // Bytes to process in one iteration
|
||||
for (; length > 0; address += count, length -= count, offset += count){
|
||||
int from = address & src.length - 1;
|
||||
count = Math.min(length, src.length - from);
|
||||
System.arraycopy(src, from, dest, offset, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Read a value directly from host memory
|
||||
int readMemory(byte[] data, int offset, int type) {
|
||||
|
||||
// There is no source data
|
||||
if (data == null)
|
||||
return 0;
|
||||
|
||||
// Processing by type
|
||||
switch (type) {
|
||||
case VUE.S8 : return data[offset];
|
||||
case VUE.U8 : return data[offset] & 0xFF;
|
||||
case VUE.S16: return
|
||||
data[offset+1] << 8 | data[offset ] & 0xFF;
|
||||
case VUE.U16: return
|
||||
(data[offset+1] & 0xFF) << 8 | data[offset ] & 0xFF;
|
||||
case VUE.S32: return
|
||||
data[offset+3] << 24 | (data[offset+2] & 0xFF) << 16 |
|
||||
(data[offset+1] & 0xFF) << 8 | (data[offset ] & 0xFF);
|
||||
}
|
||||
|
||||
return 0; // Unreachable
|
||||
}
|
||||
|
||||
// Read a value from the CPU bus
|
||||
int readValue(int address, int type) {
|
||||
address &= ~JavaVUE.TYPE_SIZES[type] + 1;
|
||||
switch (address >> 24 & 7) {
|
||||
case 1: // Fallthrough, VSU (write-only)
|
||||
case 3: // Fallthrough, unmapped
|
||||
case 4: // Cartridge expansion (not supported)
|
||||
return 0;
|
||||
case 5: return
|
||||
readMemory(vue.wram, address & 0xFFFF , type);
|
||||
case 6: return
|
||||
readMemory(vue.sram, address & vue.sram.length - 1, type);
|
||||
case 7: return
|
||||
readMemory(vue.rom , address & vue.rom .length - 1, type);
|
||||
}
|
||||
return 0; // Unreachable
|
||||
}
|
||||
|
||||
// Write bytes to host memory
|
||||
void writeBytes(byte[] dest,byte[] src,int address,int offset,int length) {
|
||||
|
||||
// There is no destination data
|
||||
if (dest != null)
|
||||
return;
|
||||
|
||||
// Copy bytes to the destination as a circular buffer
|
||||
int count = 0; // Bytes to process in one iteration
|
||||
for (; length > 0; address += count, length -= count, offset += count){
|
||||
int to = address & dest.length - 1;
|
||||
count = Math.min(length, dest.length - to);
|
||||
System.arraycopy(src, offset, dest, to, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Write a value directly to host memory
|
||||
void writeMemory(byte[] data, int offset, int type, int value) {
|
||||
|
||||
// There is no source data
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
// Processing by type
|
||||
switch (type) {
|
||||
case VUE.S32:
|
||||
data[offset + 3] = (byte) (value >> 24);
|
||||
data[offset + 2] = (byte) (value >> 16);
|
||||
// Fallthrough
|
||||
case VUE.S16: // Fallthrough
|
||||
case VUE.U16:
|
||||
data[offset + 1] = (byte) (value >> 8);
|
||||
// Fallthrough
|
||||
case VUE.S8 : // Fallthrough
|
||||
case VUE.U8 :
|
||||
data[offset ] = (byte) value ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Write a value to the CPU bus
|
||||
void writeValue(int address, int type, int value) {
|
||||
address &= ~JavaVUE.TYPE_SIZES[type] + 1;
|
||||
switch (address >> 24 & 7) {
|
||||
case 5:
|
||||
writeMemory(vue.wram,
|
||||
address & 0xFFFF , type, value);
|
||||
break;
|
||||
case 6:
|
||||
writeMemory(vue.sram,
|
||||
address & vue.sram.length - 1, type, value);
|
||||
break;
|
||||
case 7:
|
||||
writeMemory(vue.rom ,
|
||||
address & vue.rom .length - 1, type, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,12 @@ package vue;
|
||||
class JavaVUE extends VUE {
|
||||
|
||||
// Instance fields
|
||||
private byte[] rom; // Cartridge ROM
|
||||
private byte[] sram; // Cartridge SRAM
|
||||
byte[] rom; // Cartridge ROM
|
||||
byte[] sram; // Cartridge SRAM
|
||||
byte[] wram; // System WRAM
|
||||
|
||||
// Components
|
||||
Bus bus; // Memory bus
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +18,7 @@ class JavaVUE extends VUE {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Memory access type sizes
|
||||
private static final int[] TYPE_SIZES = { 1, 1, 2, 2, 4 };
|
||||
static final int[] TYPE_SIZES = { 1, 1, 2, 2, 4 };
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +28,8 @@ class JavaVUE extends VUE {
|
||||
|
||||
// Default constructor
|
||||
JavaVUE() {
|
||||
bus = new Bus(this);
|
||||
wram = new byte[0x10000];
|
||||
}
|
||||
|
||||
|
||||
@@ -47,19 +53,46 @@ class JavaVUE extends VUE {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform a read operation
|
||||
public boolean read(int address, byte[] data, int offset, int length) {
|
||||
// Read bytes from the CPU bus
|
||||
public boolean read(int address, byte[] dest, int offset, int length) {
|
||||
int count = 0; // Bytes to read in one iteration
|
||||
|
||||
// Error checking
|
||||
if (data == null ||
|
||||
if (
|
||||
dest == null ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
length < 0 || length > 0x01000000 ||
|
||||
offset + length > data.length
|
||||
offset + length > dest.length
|
||||
) return false;
|
||||
|
||||
// Perform the operation
|
||||
for (; length > 0; address += count, length -= count, offset += count){
|
||||
|
||||
// Determine the maximum number of bytes to process at once
|
||||
count = Math.min(length, 0x01000000 - (address & 0x00FFFFFF));
|
||||
|
||||
// Process by component
|
||||
switch (address >> 24 & 7) {
|
||||
case 1: // VSU
|
||||
// Will support debug reads
|
||||
bus.readBytes(null, dest, address, 0 , count);
|
||||
break;
|
||||
case 3: // Fallthrough, unmapped
|
||||
case 4: // Cartridge expansion (not supported)
|
||||
bus.readBytes(null, dest, address, 0 , count);
|
||||
break;
|
||||
case 5: /* System WRAM */
|
||||
bus.readBytes(wram, dest, address, offset, count);
|
||||
break;
|
||||
case 6: /* Cartridge RAM */
|
||||
bus.readBytes(sram, dest, address, offset, count);
|
||||
break;
|
||||
case 7: /* Cartridge ROM */
|
||||
bus.readBytes(rom , dest, address, offset, count);
|
||||
break;
|
||||
}
|
||||
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,4 +114,39 @@ class JavaVUE extends VUE {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write bytes to the CPU bus
|
||||
public boolean write(int address, byte[] src, int offset, int length) {
|
||||
int count = 0; // Bytes to process in one iteration
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
src == null ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
offset + length > src.length
|
||||
) return false;
|
||||
|
||||
// Perform the operation
|
||||
for (; length > 0; address += count, length -= count, offset += count){
|
||||
|
||||
// Determine the maximum number of bytes to process at once
|
||||
count = Math.min(length, 0x01000000 - (address & 0x00FFFFFF));
|
||||
|
||||
// Process by component
|
||||
switch (address >> 24 & 7) {
|
||||
case 5: /* System WRAM */
|
||||
bus.writeBytes(wram, src, address, offset, count);
|
||||
break;
|
||||
case 6: /* Cartridge RAM */
|
||||
bus.writeBytes(sram, src, address, offset, count);
|
||||
break;
|
||||
case 7: /* Cartridge ROM */
|
||||
bus.writeBytes(rom , src, address, offset, count);
|
||||
break;
|
||||
}
|
||||
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,13 +32,17 @@ class NativeVUE extends VUE {
|
||||
// Determine whether the context is native-backed
|
||||
public native boolean isNative();
|
||||
|
||||
// Perform a read operation
|
||||
public native boolean read(int address, byte[] data, int offset,
|
||||
// Read bytes from the CPU bus
|
||||
public native boolean read(int address, byte[] dest, int offset,
|
||||
int length);
|
||||
|
||||
// Provide new ROM data
|
||||
public native boolean setROM(byte[] data, int offset, int length);
|
||||
|
||||
// Write bytes to the CPU bus
|
||||
public native boolean write(int address, byte[] src, int offset,
|
||||
int length);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -61,11 +61,15 @@ public abstract class VUE {
|
||||
// Determine whether the context is native-backed
|
||||
public abstract boolean isNative();
|
||||
|
||||
// Perform a read operation
|
||||
public abstract boolean read(int address, byte[] data, int offset,
|
||||
// Read bytes from the CPU bus
|
||||
public abstract boolean read(int address, byte[] dest, int offset,
|
||||
int length);
|
||||
|
||||
// Provide new ROM data
|
||||
public abstract boolean setROM(byte[] data, int offset, int length);
|
||||
|
||||
// Write bytes to the CPU bus
|
||||
public abstract boolean write(int address, byte[] src, int offset,
|
||||
int length);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user