End of day: working on vueRead()/VUE.read()
This commit is contained in:
+80
-32
@@ -1,60 +1,81 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
#include <vue.h>
|
||||
#include "vue_NativeVUE.h"
|
||||
|
||||
// NativeVUE class lookup data
|
||||
static struct {
|
||||
jclass clazz; // Handle to NativeVUE class
|
||||
jfieldID pointer; // ID of NativeVUE.pointer field
|
||||
} NativeVUE;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Constants //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Memory access type sizes
|
||||
static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Types //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Core context state type
|
||||
typedef struct {
|
||||
uint8_t *rom;
|
||||
uint32_t rom_size;
|
||||
VUE vue;
|
||||
} CORE;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Internal Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Determine the field ID of NativeVUE.pointer
|
||||
static jfieldID GetPointerID(JNIEnv *env, jobject vue) {
|
||||
return (*env)->GetFieldID(env,
|
||||
(*env)->GetObjectClass(env, vue), "pointer", "[B");
|
||||
}
|
||||
|
||||
// Retrieve the handle to a NativeVUE's core context
|
||||
static CORE* GetCore(JNIEnv *env, jobject vue) {
|
||||
jbyteArray pointer =
|
||||
(*env)->GetObjectField(env, vue, NativeVUE.pointer);
|
||||
(*env)->GetObjectField(env, vue, GetPointerID(env, vue));
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL);
|
||||
CORE *core = *(CORE **)elems;
|
||||
(*env)->ReleaseByteArrayElements(env, pointer, elems, 0);
|
||||
return core;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Method Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Native constructor
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVUE_construct
|
||||
(JNIEnv *env, jobject vue) {
|
||||
|
||||
// Initialize the class data
|
||||
if (NativeVUE.clazz == NULL) {
|
||||
NativeVUE.clazz = (*env)->GetObjectClass(env, vue);
|
||||
NativeVUE.pointer =
|
||||
(*env)->GetFieldID(env, NativeVUE.clazz, "pointer", "[B");
|
||||
}
|
||||
|
||||
// Produce and initialize s new core context
|
||||
CORE *core = calloc(sizeof (CORE), 1);
|
||||
core->rom = calloc(1024, 1);
|
||||
vueInitialize(&core->vue);
|
||||
vueSetROM(&core->vue, calloc(1024, 1), 1024);
|
||||
|
||||
// Encode the context handle into a byte array
|
||||
jbyteArray pointer = (*env)->NewByteArray(env, sizeof (void *));
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL);
|
||||
*(CORE **)elems = core;
|
||||
(*env)->ReleaseByteArrayElements(env, pointer, elems, 0);
|
||||
(*env)->SetObjectField(env, vue, NativeVUE.pointer, pointer);
|
||||
(*env)->SetObjectField(env, vue, GetPointerID(env, vue), pointer);
|
||||
}
|
||||
|
||||
// Release any used resources
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVUE_dispose
|
||||
(JNIEnv *env, jobject vue) {
|
||||
CORE *core = GetCore(env, vue);
|
||||
free(core->rom);
|
||||
free(core->vue.rom);
|
||||
if (core->vue.sram != NULL)
|
||||
free(core->vue.sram);
|
||||
free(core);
|
||||
}
|
||||
|
||||
@@ -62,9 +83,9 @@ JNIEXPORT void JNICALL Java_vue_NativeVUE_dispose
|
||||
JNIEXPORT jbyteArray JNICALL Java_vue_NativeVUE_getROM
|
||||
(JNIEnv *env, jobject vue) {
|
||||
CORE *core = GetCore(env, vue);
|
||||
jbyteArray ret = (*env)->NewByteArray(env, (jint) core->rom_size);
|
||||
jbyteArray ret = (*env)->NewByteArray(env, (jint) core->vue.rom_size);
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, ret, NULL);
|
||||
memcpy(elems, core->rom, core->rom_size);
|
||||
memcpy(elems, core->vue.rom, core->vue.rom_size);
|
||||
(*env)->ReleaseByteArrayElements(env, ret, elems, 0);
|
||||
return ret;
|
||||
}
|
||||
@@ -75,23 +96,50 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_isNative
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// Perform a read access
|
||||
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_read
|
||||
(JNIEnv *env, jobject vue, jint address, jbyteArray data, jint offset,
|
||||
jint length) {
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
data == NULL ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
length < 0 || length > 0x01000000 ||
|
||||
offset + length > (*env)->GetArrayLength(env, data)
|
||||
) return JNI_FALSE;
|
||||
|
||||
// Perform the operation
|
||||
CORE *core = GetCore(env, vue);
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, data, NULL);
|
||||
vueRead(&core->vue, address, &elems[offset], length);
|
||||
(*env)->ReleaseByteArrayElements(env, data, elems, 0);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// Provide new ROM data
|
||||
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_setROM
|
||||
(JNIEnv *env, jobject vue, jbyteArray data, jint offset, jint length) {
|
||||
|
||||
// Error checking
|
||||
if (data == NULL || offset < 0 || length < 1024 ||
|
||||
offset + length > (*env)->GetArrayLength(env, data) ||
|
||||
(length & length - 1) != 0)
|
||||
return JNI_FALSE;
|
||||
if (
|
||||
data == NULL ||
|
||||
offset < 0 ||
|
||||
length < 1024 || length > 0x01000000 ||
|
||||
(length & length - 1) != 0 ||
|
||||
offset + length > (*env)->GetArrayLength(env, data)
|
||||
) return JNI_FALSE;
|
||||
|
||||
// Accept the new ROM data
|
||||
CORE *core = GetCore(env, vue);
|
||||
free(core->rom);
|
||||
core->rom = calloc(length, 1);
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, data, NULL);
|
||||
memcpy(core->rom, &elems[offset], length);
|
||||
uint8_t *rom = calloc(length, 1);
|
||||
jbyte *elems = (*env)->GetByteArrayElements(env, data, NULL);
|
||||
memcpy(rom, &elems[offset], length);
|
||||
(*env)->ReleaseByteArrayElements(env, data, elems, 0);
|
||||
core->rom_size = (uint32_t) length;
|
||||
|
||||
// Transfer the ROM data to the emulation state
|
||||
CORE *core = GetCore(env, vue);
|
||||
free(core->vue.rom);
|
||||
vueSetROM(&core->vue, rom, length);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,17 @@ package vue;
|
||||
class JavaVUE extends VUE {
|
||||
|
||||
// Instance fields
|
||||
private byte[] rom; // Cartridge ROM
|
||||
private byte[] rom; // Cartridge ROM
|
||||
private byte[] sram; // Cartridge SRAM
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Constants //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Memory access type sizes
|
||||
private static final int[] TYPE_SIZES = { 1, 1, 2, 2, 4 };
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +24,6 @@ class JavaVUE extends VUE {
|
||||
|
||||
// Default constructor
|
||||
JavaVUE() {
|
||||
rom = new byte[1024];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +38,7 @@ class JavaVUE extends VUE {
|
||||
// Retrieve a copy of the ROM data
|
||||
public byte[] getROM() {
|
||||
var ret = new byte[rom.length];
|
||||
System.arraycopy(rom, 0, ret, 0, rom.length);
|
||||
System.arraycopy(rom, 0, ret, 0, ret.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,13 +47,33 @@ class JavaVUE extends VUE {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform a read operation
|
||||
public boolean read(int address, byte[] data, int offset, int length) {
|
||||
|
||||
// Error checking
|
||||
if (data == null ||
|
||||
offset < 0 ||
|
||||
length < 0 ||
|
||||
length < 0 || length > 0x01000000 ||
|
||||
offset + length > data.length
|
||||
) return false;
|
||||
|
||||
// Perform the operation
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Provide new ROM data
|
||||
public boolean setROM(byte[] data, int offset, int length) {
|
||||
|
||||
// Error checking
|
||||
if (data == null || offset < 0 || length < 1024 ||
|
||||
offset + length > data.length || (length & length - 1) != 0)
|
||||
return false;
|
||||
if (
|
||||
data == null ||
|
||||
offset < 0 ||
|
||||
length < 1024 || length > 0x01000000 ||
|
||||
(length & length - 1) != 0 ||
|
||||
offset + length > data.length
|
||||
) return false;
|
||||
|
||||
// Accept the new ROM data
|
||||
rom = new byte[length];
|
||||
|
||||
@@ -32,6 +32,10 @@ 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,
|
||||
int length);
|
||||
|
||||
// Provide new ROM data
|
||||
public native boolean setROM(byte[] data, int offset, int length);
|
||||
|
||||
|
||||
@@ -8,6 +8,19 @@ public abstract class VUE {
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Constants //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Memory access types
|
||||
public static final int S8 = 0;
|
||||
public static final int U8 = 1;
|
||||
public static final int S16 = 2;
|
||||
public static final int U16 = 3;
|
||||
public static final int S32 = 4;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Static Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -48,6 +61,10 @@ 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,
|
||||
int length);
|
||||
|
||||
// Provide new ROM data
|
||||
public abstract boolean setROM(byte[] data, int offset, int length);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user