diff --git a/VirtualComputer-Core/pom.xml b/VirtualComputer-Core/pom.xml index f280abe..e9baa36 100644 --- a/VirtualComputer-Core/pom.xml +++ b/VirtualComputer-Core/pom.xml @@ -9,6 +9,7 @@ 2.1-SNAPSHOT + VirtualComputer maven-compiler-plugin @@ -36,7 +37,15 @@ - + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + @@ -55,7 +64,7 @@ 2.1-SNAPSHOT - sznp.virtualcomputer + io.github.NorbiPeti VirtualComputer-MSCOM 2.1-SNAPSHOT @@ -87,7 +96,7 @@ org.virtualbox:VirtualBox-MSCOM - sznp.virtualcomputer:VirtualComputer-MSCOM + io.github.NorbiPeti:VirtualComputer-MSCOM @@ -130,7 +139,7 @@ org.virtualbox:VirtualBox - sznp.virtualcomputer:VirtualComputer-XPCOM + io.github.NorbiPeti:VirtualComputer-XPCOM diff --git a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/Computer.java b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/Computer.java index 7aff0cf..c648b2c 100644 --- a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/Computer.java +++ b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/Computer.java @@ -273,7 +273,8 @@ public final class Computer { GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen stopEvents(); MouseLockerPlayerListener.computerStop(); - framebuffer.stop(); + if (framebuffer != null) + framebuffer.stop(); } public void stopEvents() { @@ -286,7 +287,8 @@ public final class Computer { public void pluginDisable(CommandSender ccs) { stopEvents(); - framebuffer.stop(); + if (framebuffer != null) + framebuffer.stop(); if (session.getState() == SessionState.Locked) { if (session.getMachine().getState().equals(MachineState.Running)) { ccs.sendMessage("§aSaving machine state..."); diff --git a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/PluginMain.java b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/PluginMain.java index e92bb03..762be30 100644 --- a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/PluginMain.java +++ b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/PluginMain.java @@ -33,7 +33,7 @@ public class PluginMain extends JavaPlugin { * Only used if {@link #direct} is false. */ public static ByteBuffer allpixels; // It's set on each change - private static ArrayList renderers = new ArrayList<>(); + private static final ArrayList renderers = new ArrayList<>(); /* * Only used if {@link #direct} is true. */ @@ -50,14 +50,23 @@ public class PluginMain extends JavaPlugin { this.getCommand("computer").setExecutor(new Commands()); sendAll = getConfig().getBoolean("sendAll", true); ccs.sendMessage("§bInitializing VirtualBox..."); - String vbpath = System.getProperty("os.name").toLowerCase().contains("mac") - ? "/Applications/VirtualBox.app/Contents/MacOS" - : "/opt/virtualbox"; + String osname = System.getProperty("os.name").toLowerCase(); + final boolean windows; + String vbpath; + { + boolean win = false; + vbpath = osname.contains("mac") + ? "/Applications/VirtualBox.app/Contents/MacOS" + : (win = osname.contains("windows")) + ? "C:\\Program Files\\Oracle\\VirtualBox" + : "/opt/virtualbox"; + windows = win; + } //noinspection ConstantConditions - Predicate notGoodDir= ff->!ff.isDirectory() || Arrays.stream(ff.list()).noneMatch(s -> s.contains("xpcom")); + Predicate notGoodDir = ff -> !ff.isDirectory() || (!windows && Arrays.stream(ff.list()).noneMatch(s -> s.contains("xpcom"))); if (notGoodDir.test(new File(vbpath))) vbpath = "/usr/lib/virtualbox"; - if(notGoodDir.test(new File(vbpath))) + if (notGoodDir.test(new File(vbpath))) error("Could not find VirtualBox! Download from https://www.virtualbox.org/wiki/Downloads"); if (System.getProperty("vbox.home") == null || System.getProperty("vbox.home").isEmpty()) System.setProperty("vbox.home", vbpath); @@ -66,10 +75,12 @@ public class PluginMain extends JavaPlugin { System.setProperty("sun.boot.library.path", vbpath); if (System.getProperty("java.library.path") == null || System.getProperty("java.library.path").isEmpty()) System.setProperty("java.library.path", vbpath); - Utils.addLibraryPath(vbpath); + Utils.addLibraryPath(vbpath); //TODO: Jacob DLL must be in the server folder final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath()); - VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); //TODO: Test for MSCOM - vbl.RTR3InitExe(0, "", 0); + if (!windows) { + VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); + vbl.RTR3InitExe(0, "", 0); + } IVirtualBox vbox = manager.getVBox(); (listener = new VBoxEventHandler()).registerTo(vbox.getEventSource()); new Computer(this, manager, vbox); //Saves itself @@ -80,12 +91,12 @@ public class PluginMain extends JavaPlugin { for (short j = 0; j < MCY; j++) renderers.add(new GPURenderer((short) (j * 5 + i), Bukkit.getWorlds().get(0), i, j)); //pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc"); - direct=true; + direct = true; ccs.sendMessage("§bUsing Direct Renderer, all good"); } catch (NoClassDefFoundError | Exception e) { for (short i = 0; i < 20; i++) renderers.add(new BukkitRenderer(i, Bukkit.getWorlds().get(0), i * 128 * 128 * 4)); - direct=false; + direct = false; e.printStackTrace(); ccs.sendMessage("§6Compatibility error, using slower renderer"); } diff --git a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/util/Utils.java b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/util/Utils.java index c6a5aad..0a67fb1 100644 --- a/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/util/Utils.java +++ b/VirtualComputer-Core/src/main/java/sznp/virtualcomputer/util/Utils.java @@ -1,5 +1,7 @@ package sznp.virtualcomputer.util; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.lang.reflect.Field; import java.util.Arrays; @@ -11,6 +13,14 @@ public class Utils { * @throws Exception */ public static void addLibraryPath(String pathToAdd) throws Exception { + try { + addLibraryPathOld(pathToAdd); + } catch (Throwable t) { + addLibraryPathNew(pathToAdd); + } + } + + private static void addLibraryPathOld(String pathToAdd) throws Exception { final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); usrPathsField.setAccessible(true); @@ -29,4 +39,14 @@ public class Utils { newPaths[newPaths.length - 1] = pathToAdd; usrPathsField.set(null, newPaths); } + + private static void addLibraryPathNew(String pathToAdd) throws Exception { + MethodHandles.Lookup cl = MethodHandles.privateLookupIn(ClassLoader.class, MethodHandles.lookup()); + VarHandle sys_paths = cl.findStaticVarHandle(ClassLoader.class, "sys_paths", String[].class); + final String[] paths = (String[]) sys_paths.get(); + + final String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[newPaths.length - 1] = pathToAdd; + sys_paths.set((Object) newPaths); + } } diff --git a/VirtualComputerMSCOM/pom.xml b/VirtualComputerMSCOM/pom.xml index 2f4ef83..70022bd 100644 --- a/VirtualComputerMSCOM/pom.xml +++ b/VirtualComputerMSCOM/pom.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - sznp.virtualcomputer VirtualComputer-MSCOM 2.1-SNAPSHOT @@ -22,6 +21,11 @@ true + + net.sf.jacob-project + jacob + 1.19 + \ No newline at end of file diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/COMFrameBuffer.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/COMFrameBuffer.java new file mode 100644 index 0000000..c9859b4 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/COMFrameBuffer.java @@ -0,0 +1,97 @@ +package sznp.virtualcomputer; + +import lombok.RequiredArgsConstructor; +import org.virtualbox_6_1.BitmapFormat; +import org.virtualbox_6_1.FramebufferCapabilities; +import org.virtualbox_6_1.IFramebufferOverlay; +import sznp.virtualcomputer.util.IMCFrameBuffer; + +import java.util.Arrays; + +@RequiredArgsConstructor +public class COMFrameBuffer { + private final IMCFrameBuffer frameBuffer; + + public long getBitsPerPixel() { + return 32; + } + + public long getBytesPerLine() { + return 640L; + } + + public long[] getCapabilities(long[] arg0) { + try { + System.out.println("Capabilities queried"); + System.out.println("Capabilities: " + Arrays.toString(arg0)); + return new long[]{FramebufferCapabilities.UpdateImage.value()}; + } catch (Exception e) { + e.printStackTrace(); + return new long[]{}; + } + } + + public long getHeight() { + return 480; + } + + public long getHeightReduction() { + return 0; + } + + public IFramebufferOverlay getOverlay() { + return null; + } + + public long getPixelFormat() { + return BitmapFormat.BGRA.value(); + } + + public long getVisibleRegion(byte arg0, long arg1) { + return 0; + } + + public long getWidth() { + return 640; + } + + public long getWinId() { + return 0; // Zero means no win id + } + + public void notify3DEvent(long type, byte[] data) { + System.out.println("3D event! " + type + " - " + Arrays.toString(data)); + } + + public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) { + frameBuffer.notifyChange(screenId, xOrigin, yOrigin, width, height); + } + + public void notifyUpdate(long x, long y, long width, long height) { + frameBuffer.notifyUpdate(x, y, width, height); + } + + public void notifyUpdateImage(long arg0, long arg1, long arg2, long arg3, byte[] arg4) { + frameBuffer.notifyUpdateImage(arg0, arg1, arg2, arg3, arg4); + } + + public void setVisibleRegion(byte arg0, long arg1) { + } + + /** + * Posts a Video HW Acceleration Command to the frame buffer for processing.
+ *
+ * The commands used for 2D video acceleration (DDraw surface creation/destroying, blitting, scaling, color conversion, overlaying, etc.) are posted from quest to the host to be processed by the host hardware. + * + * @param command Pointer to VBOXVHWACMD containing the command to execute. + * @param enmCmd The validated VBOXVHWACMD::enmCmd value from the command. + * @param fromGuest Set when the command origins from the guest, clear if host. + */ //https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp#L4645 + public void processVHWACommand(byte command, int enmCmd, boolean fromGuest) { + + } + + public boolean videoModeSupported(long arg0, long arg1, long arg2) { + return true; + } +} diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/EventHandler.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/EventHandler.java new file mode 100644 index 0000000..9e807e5 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/EventHandler.java @@ -0,0 +1,32 @@ +package sznp.virtualcomputer; + +import org.virtualbox_6_1.IEvent; +import sznp.virtualcomputer.util.COMObjectBase; +import sznp.virtualcomputer.util.IEventHandler; + +/** + * A Bukkit-like event system which calls the appropriate methods on an event. + */ +public final class EventHandler extends COMObjectBase { + private final IEventHandler handler; + private boolean enabled = true; + + /** + * New MSCOM event handler. + * + * @param handler The handle method that handles what needs to be handled + */ + public EventHandler(IEventHandler handler) { + this.handler = handler; + } + + public final void handleEvent(IEvent iEvent) { + if (!enabled) + return; + handler.handleEvent(iEvent); + } + + public void disable() { + enabled = false; + } +} diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMObjectBase.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMObjectBase.java new file mode 100644 index 0000000..947df62 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMObjectBase.java @@ -0,0 +1,10 @@ +package sznp.virtualcomputer.util; + +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; + +public abstract class COMObjectBase extends Dispatch { + public COMObjectBase() { + super("clsid:{67099191-32E7-4F6C-85EE-422304C71B90}"); + } +} diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMUtils.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMUtils.java new file mode 100644 index 0000000..98f7c52 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/COMUtils.java @@ -0,0 +1,52 @@ +package sznp.virtualcomputer.util; + +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.*; +import lombok.val; +import org.virtualbox_6_1.*; +import org.virtualbox_6_1.mscom.Helper; +import org.virtualbox_6_1.mscom.IUnknown; +import sznp.virtualcomputer.COMFrameBuffer; +import sznp.virtualcomputer.EventHandler; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public final class COMUtils { + private COMUtils() { + } + + //public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) { + public static org.virtualbox_6_1.IEventListener registerListener(IEventSource source, IEventHandler listener, List types) { + //new DispatchEvents(source.getTypedWrapped(), listener); + val ret = new org.virtualbox_6_1.IEventListener(new EventHandler(listener)); + /*com.jacob.activeX.ActiveXComponent.createNewInstance("IEventListener"); + new ActiveXComponent(""); + source.registerListener(ret, types, true);*/ + //registerListener(source, new EventHandler(listener), types, true); + System.out.println("Testing listener..."); + ret.handleEvent(null); + System.out.println("Tested"); + return ret; + //return null; + } + + @SuppressWarnings("unchecked") + public static T getEvent(IEvent event, Class cl) { + try { + val method = cl.getMethod("queryInterface", IUnknown.class); + return (T) method.invoke(null, event); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + return null; + } + } + + public static IFramebuffer gimmeAFramebuffer(IMCFrameBuffer frameBuffer) { + return new IFramebuffer(new Variant(new COMFrameBuffer(frameBuffer)).getDispatch()); + } + + public static void queryBitmapInfo(IDisplaySourceBitmap bitmap, long[] ptr, long[] w, long[] h, long[] bpp, long[] bpl, long[] pf) { + Dispatch.call(bitmap.getTypedWrapped(), "queryBitmapInfo", ptr, w, h, bpp, bpl, pf); + } +} diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IEventHandler.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IEventHandler.java new file mode 100644 index 0000000..7a61468 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IEventHandler.java @@ -0,0 +1,7 @@ +package sznp.virtualcomputer.util; + +import org.virtualbox_6_1.IEvent; + +public interface IEventHandler { + void handleEvent(IEvent iEvent); +} diff --git a/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IMCFrameBuffer.java b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IMCFrameBuffer.java new file mode 100644 index 0000000..ebec8d0 --- /dev/null +++ b/VirtualComputerMSCOM/src/main/java/sznp/virtualcomputer/util/IMCFrameBuffer.java @@ -0,0 +1,9 @@ +package sznp.virtualcomputer.util; + +public interface IMCFrameBuffer { + void notifyUpdate(long x, long y, long width, long height); + + void notifyUpdateImage(long x, long y, long width, long height, byte[] image); + + void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height); +} diff --git a/pom.xml b/pom.xml index e61e47b..8340ba2 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,7 @@ pom VirtualComputer - - http://www.example.com + https://github.com/NorbiPeti/VirtualComputer UTF-8 @@ -75,12 +74,12 @@ 1.12-R0.1-SNAPSHOT provided - + diff --git a/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.jar b/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.jar new file mode 100644 index 0000000..06882a0 Binary files /dev/null and b/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.jar differ diff --git a/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.pom b/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.pom new file mode 100644 index 0000000..0d6f1a9 --- /dev/null +++ b/repo/net/sf/jacob-project/jacob/1.19/jacob-1.19.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + net.sf.jacob-project + jacob + 1.19 + POM was created from install:install-file + diff --git a/repo/net/sf/jacob-project/jacob/maven-metadata-local.xml b/repo/net/sf/jacob-project/jacob/maven-metadata-local.xml new file mode 100644 index 0000000..223f446 --- /dev/null +++ b/repo/net/sf/jacob-project/jacob/maven-metadata-local.xml @@ -0,0 +1,12 @@ + + + net.sf.jacob-project + jacob + + 1.19 + + 1.19 + + 20200811112851 + +