Introducing vue module, native loader

This commit is contained in:
Guy Perfect 2020-08-02 21:21:59 -05:00
parent 3dc19b5c9e
commit b86c046dd5
7 changed files with 205 additions and 17 deletions

View File

@ -19,6 +19,7 @@ default:
@echo @echo
@echo "Usage: make <recipe>" @echo "Usage: make <recipe>"
@echo " Package recipes:" @echo " Package recipes:"
@echo " build Compiles the native modules and desktop application"
@echo " bundle Produces a .jar and deletes all intermediate files" @echo " bundle Produces a .jar and deletes all intermediate files"
@echo " clean Deletes all output files" @echo " clean Deletes all output files"
@echo " core Check the native core library for style errors" @echo " core Check the native core library for style errors"
@ -38,12 +39,17 @@ default:
# Package Recipes # # Package Recipes #
############################################################################### ###############################################################################
# Perform a full build process # Perform a full build process of the native modules and desktop application
.PHONY: bundle .PHONY: build
bundle: build:
@make -s core @make -s core
@make -s desktop @make -s desktop
@make -s native @make -s native
# Performs a full build and packages it into a .jar
.PHONY: bundle
bundle:
@make -s build
@make -s pack @make -s pack
@echo " Removing temporary files" @echo " Removing temporary files"
@make -s clean_most @make -s clean_most

View File

@ -1,14 +1,47 @@
// Java imports
import java.io.*;
// Project imports // Project imports
import app.*; import app.*;
import util.*; import util.*;
import vue.*;
// Desktop application primary class // Desktop application primary class
public class Main { public class Main {
// Program entry point // Program entry point
public static void main(String[] args) { public static void main(String[] args) {
// Configure Swing look-and-feel
Util.setSystemLAF(); Util.setSystemLAF();
// Load the native module, if available
for (String filename : Util.listFiles("native")) {
File file = null;
// Skip .gitignore
if (filename.equals(".gitignore"))
continue;
// Write the contents of the native object file
FileOutputStream stream = null;
try {
file = File.createTempFile("native", "." + filename);
stream = new FileOutputStream(file);
stream.write(Util.fileRead("native/" + filename));
} catch (Exception e) { file = null; }
try { stream.close(); } catch (Exception e) { }
// Load the native object file into the JVM
try { System.load(file.getAbsolutePath()); break; }
catch (Error e) { }
}
// Begin application operations
new App(); new App();
var vue = VUE.create(true);
System.out.println(vue.isNative());
} }
} }

View File

@ -96,7 +96,9 @@ public class ROM {
// Produce a byte array containing the ROM contents // Produce a byte array containing the ROM contents
public byte[] toByteArray() { public byte[] toByteArray() {
return data; var ret = new byte[data.length];
System.arraycopy(data, 0, ret, 0, data.length);
return ret;
} }
@ -136,7 +138,8 @@ public class ROM {
int size = 1024; int size = 1024;
int minSize = (head == -1 ? 0 : head + 1) + int minSize = (head == -1 ? 0 : head + 1) +
(tail == -1 ? 0 : 0x01000000 - tail); (tail == -1 ? 0 : 0x01000000 - tail);
if (minSize == 0 || tail == -1 && (minSize - 1 & minSize) != 0) if (minSize == 0 || tail == -1 &&
(minSize < 1024 || (minSize - 1 & minSize) != 0))
throw new RuntimeException(); throw new RuntimeException();
for (; size < minSize; size <<= 1); for (; size < minSize; size <<= 1);

View File

@ -1,7 +1,36 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <jni.h> #include <jni.h>
#include "vue_NativeVUE.h" #include "vue_NativeVUE.h"
JNIEXPORT jint JNICALL Java_vue_NativeVUE_test(JNIEnv *env, jobject obj, // Retrieve a copy of the ROM data
jint x, jint y) { JNIEXPORT jbyteArray JNICALL Java_vue_NativeVUE_getROM
return x * y; (JNIEnv *env, jobject vue) {
}
// Determine whether the context is native-backed
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_isNative
(JNIEnv *env, jobject vue) {
return JNI_TRUE;
}
// Provide new ROM data
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_setROM
(JNIEnv *env, jobject vue, jbyteArray data, jint offset, jint length) {
jsize data_length = (*env)->GetArrayLength(env, data);
// Error checking
if (data == NULL || offset < 0 || length < 1024 ||
offset + length > data_length || (length & length - 1) != 0)
return JNI_FALSE;
// Accept the new ROM data
return JNI_TRUE;
}
// Invoke native code to ensure the module is loaded
JNIEXPORT jboolean JNICALL Java_vue_NativeVUE_testNative
(JNIEnv *env, jclass vue) {
return JNI_TRUE;
} }

View File

@ -0,0 +1,53 @@
package vue;
// Java emulation core implementation
// Native-backed emulation core implementation
class JavaVUE implements VUE {
// Instance fields
private byte[] rom; // Cartridge ROM
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
JavaVUE() {
rom = new byte[1024];
}
///////////////////////////////////////////////////////////////////////////
// Public Methods //
///////////////////////////////////////////////////////////////////////////
// Retrieve a copy of the ROM data
public byte[] getROM() {
var ret = new byte[rom.length];
System.arraycopy(rom, 0, ret, 0, rom.length);
return ret;
}
// Determine whether the context is native-backed
public boolean isNative() {
return false;
}
// 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;
// Accept the new ROM data
rom = new byte[length];
System.arraycopy(data, offset, rom, 0, length);
return true;
}
}

View File

@ -1,13 +1,55 @@
package vue; package vue;
// Native-backed emulation core implementation // Native-backed emulation core implementation
class NativeVUE extends VUE { class NativeVUE implements VUE {
// Retrieve the implementation's name // Instance fields
public String getName() { private byte[] pointer; // Instance address in native memory
return "Native";
///////////////////////////////////////////////////////////////////////////
// Constructors //
///////////////////////////////////////////////////////////////////////////
// Default constructor
NativeVUE() {
} }
native int test(int x, int y);
///////////////////////////////////////////////////////////////////////////
// Package Methods //
///////////////////////////////////////////////////////////////////////////
// Determine whether the native library has been loaded
static boolean isLoaded() {
try { return testNative(); }
catch (Exception e) { return false; }
}
///////////////////////////////////////////////////////////////////////////
// Public Methods //
///////////////////////////////////////////////////////////////////////////
// Retrieve a copy of the ROM data
public native byte[] getROM();
// Determine whether the context is native-backed
public native boolean isNative();
// Provide new ROM data
public native boolean setROM(byte[] data, int offset, int length);
///////////////////////////////////////////////////////////////////////////
// Private Methods //
///////////////////////////////////////////////////////////////////////////
// Invoke native code to ensure the module is loaded
private static native boolean testNative();
} }

View File

@ -1,9 +1,31 @@
package vue; package vue;
// Template class for emulation core implementations // Template for emulation core implementations
public abstract class VUE { public interface VUE {
// Retrieve the implementation's name ///////////////////////////////////////////////////////////////////////////
public abstract String getName(); // Factory Methods //
///////////////////////////////////////////////////////////////////////////
// Produce an emulation core context
public static VUE create(boolean useNative) {
return !useNative ? new JavaVUE() :
NativeVUE.isLoaded() ? new NativeVUE() : null;
}
///////////////////////////////////////////////////////////////////////////
// Public Methods //
///////////////////////////////////////////////////////////////////////////
// Retrieve a copy of the ROM data
byte[] getROM();
// Determine whether the context is native-backed
boolean isNative();
// Provide new ROM data
boolean setROM(byte[] data, int offset, int length);
} }