Revamp ECI
[jpcrr.git] / org / jpc / j2se / JPCApplication.java
blob4b2b7cdff2cca79e3601bbbc1cacba08977fa4fb
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009 H. Ilari Liusvaara
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as published by
10 the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 Based on JPC x86 PC Hardware emulator,
22 A project from the Physics Dept, The University of Oxford
24 Details about original JPC can be found at:
26 www-jpc.physics.ox.ac.uk
30 package org.jpc.j2se;
32 import java.awt.Component;
33 import java.awt.BorderLayout;
34 import java.awt.Desktop;
35 import java.awt.Dimension;
36 import java.awt.Toolkit;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.io.*;
40 import java.net.URI;
41 import java.net.URL;
42 import java.net.URLClassLoader;
43 import java.util.*;
44 import java.util.jar.*;
45 import java.util.zip.*;
46 import java.security.AccessControlException;
47 import javax.swing.*;
48 import java.lang.reflect.*;
50 import org.jpc.*;
51 import org.jpc.emulator.PC;
52 import org.jpc.emulator.TraceTrap;
53 import org.jpc.emulator.pci.peripheral.VGACard;
54 import org.jpc.emulator.peripheral.FloppyController;
55 import org.jpc.emulator.peripheral.Keyboard;
56 import org.jpc.emulator.memory.PhysicalAddressSpace;
57 import org.jpc.emulator.SRLoader;
58 import org.jpc.emulator.SRDumper;
59 import org.jpc.emulator.StatusDumper;
60 import org.jpc.emulator.Clock;
61 import org.jpc.diskimages.BlockDevice;
62 import org.jpc.diskimages.GenericBlockDevice;
63 import org.jpc.diskimages.ImageLibrary;
64 import org.jpc.diskimages.DiskImage;
65 import org.jpc.pluginsbase.*;
67 import static org.jpc.Misc.errorDialog;
68 import static org.jpc.Misc.callShowOptionDialog;
69 import static org.jpc.Misc.parseString;
71 public class JPCApplication
73 public static Plugin instantiatePlugin(Plugins pluginManager, Class<?> plugin, String arguments) throws IOException
75 Constructor<?> cc;
77 if(arguments != null) {
78 try {
79 cc = plugin.getConstructor(Plugins.class, String.class);
80 } catch(Exception e) {
81 throw new IOException("Plugin \"" + plugin.getName() + "\" does not take arguments.");
83 } else {
84 try {
85 cc = plugin.getConstructor(Plugins.class);
86 } catch(Exception e) {
87 throw new IOException("Plugin \"" + plugin.getName() + "\" requires arguments.");
91 try {
92 if(arguments != null)
93 return (Plugin)cc.newInstance(pluginManager, arguments);
94 else
95 return (Plugin)cc.newInstance(pluginManager);
96 } catch(InvocationTargetException e) {
97 Throwable e2 = e.getCause();
98 //If the exception is something unchecked, just pass it through.
99 if(e2 instanceof RuntimeException)
100 throw (RuntimeException)e2;
101 if(e2 instanceof Error) {
102 IOException ne = new IOException("Error while invoking loader: " + e2);
103 ne.setStackTrace(e2.getStackTrace()); //Copy stack trace.
104 throw ne;
106 //Also pass IOException through.
107 if(e2 instanceof IOException)
108 throw (IOException)e2;
109 //What the heck is that?
110 IOException ne = new IOException("Unknown exception while invoking loader: " + e2);
111 ne.setStackTrace(e2.getStackTrace()); //Copy stack trace.
112 throw ne;
113 } catch(Exception e) {
114 throw new IOException("Failed to invoke plugin \"" + plugin.getName() + "\" constructor.");
118 private static void loadPlugin(Plugins pluginManager, String arg) throws IOException
120 String moduleString = arg;
121 String currentModule;
122 int parenDepth = 0;
123 int nameEnd = -1;
124 int paramsStart = -1;
125 int paramsEnd = -1;
126 int stringLen = moduleString.length();
127 boolean requireNextSep = false;
129 for(int i = 0; true; i++) {
130 int cp;
131 if(i < stringLen)
132 cp = moduleString.codePointAt(i);
133 else if(parenDepth == 0) {
134 if(nameEnd < 0)
135 nameEnd = i - 1;
136 currentModule = moduleString.substring(0, i);
137 if(i < stringLen ) {
138 moduleString = moduleString.substring(i + 1);
139 if(moduleString.equals(""))
140 throw new IOException("Error in module string: Blank module name not allowed.");
141 } else
142 moduleString = "";
143 break;
144 } else
145 throw new IOException("Error in module string: unclosed '('.");
146 if(cp >= 0x10000)
147 i++; //Skip the next surrogate.
148 if((cp >= 0xD800 && cp < 0xE000) || ((cp & 0xFFFE) == 0xFFFE) || (cp >>> 16) > 16 || cp < 0)
149 throw new IOException("Error In module string: invalid Unicode character.");
150 if(requireNextSep && cp != ',')
151 throw new IOException("Error in module string: Expected ',' after ')' closing parameter list.");
152 else if(cp == ',' && i == 0)
153 throw new IOException("Error in module string: Blank module name not allowed.");
154 else if(cp == '(') {
155 if(parenDepth == 0) {
156 paramsStart = i + 1;
157 nameEnd = i - 1;
159 parenDepth++;
160 } else if(cp == ')') {
161 if(parenDepth == 0)
162 throw new IOException("Error in module string: Unpaired ')'.");
163 else if(parenDepth == 1) {
164 paramsEnd = i - 1;
165 requireNextSep = true;
167 parenDepth--;
171 String name = currentModule.substring(0, nameEnd + 1);
172 String params = null;
173 if(paramsStart >= 0)
174 params = currentModule.substring(paramsStart, paramsEnd + 1);
176 Class<?> plugin;
178 try {
179 plugin = Class.forName(name);
180 } catch(Exception e) {
181 throw new IOException("Unable to find plugin \"" + name + "\".");
184 if(!Plugin.class.isAssignableFrom(plugin)) {
185 throw new IOException("Plugin \"" + name + "\" is not valid plugin.");
187 Plugin c = instantiatePlugin(pluginManager, plugin, params);
188 pluginManager.registerPlugin(c);
191 public static void doCommand(Plugins pluginManager, String cmd)
193 if(cmd.toLowerCase().startsWith("load ")) {
194 try {
195 loadPlugin(pluginManager, cmd.substring(5));
196 } catch(Exception e) {
197 errorDialog(e, "Plugin Loading failed", null, "Dismiss");
199 } else if(cmd.toLowerCase().equals("exit")) {
200 pluginManager.shutdownEmulator();
201 } else if(cmd.toLowerCase().equals("")) {
202 } else if(cmd.toLowerCase().startsWith("command ")) {
203 try {
204 String[] arr = parseString(cmd.substring(8));
205 if(arr == null)
206 throw new Exception("No command to send given");
207 String rcmd = arr[0];
208 String[] rargs = null;
209 if(arr.length > 1) {
210 rargs = new String[arr.length - 1];
211 System.arraycopy(arr, 1, rargs, 0, arr.length - 1);
213 pluginManager.invokeExternalCommandSynchronous(rcmd, rargs);
214 } catch(Exception e) {
215 errorDialog(e, "Command sending failed", null, "Dismiss");
217 } else if(cmd.toLowerCase().startsWith("call ")) {
218 try {
219 String[] arr = parseString(cmd.substring(5));
220 if(arr == null)
221 throw new Exception("No command to send given");
222 String rcmd = arr[0];
223 String[] rargs = null;
224 if(arr.length > 1) {
225 rargs = new String[arr.length - 1];
226 System.arraycopy(arr, 1, rargs, 0, arr.length - 1);
228 Object[] ret = pluginManager.invokeExternalCommandReturn(rcmd, rargs);
229 if(ret != null)
230 for(int i = 0; i < ret.length; i++)
231 System.out.println(ret[i].toString());
232 else
233 System.out.println("Nothing returned.");
234 } catch(Exception e) {
235 errorDialog(e, "Command sending failed", null, "Dismiss");
237 } else {
238 System.err.println("Invalid command");
242 public static void main(String[] args) throws Exception
246 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
247 } catch (Throwable e) { //Yes, we need to catch errors too.
248 System.err.println("Warning: System Look-and-Feel not loaded" + e.getMessage());
251 System.out.println("JPC-RR: Rerecording PC emulator based on JPC PC emulator. Release 8+.");
252 System.out.println("Based on JPC PC emulator.");
253 System.out.println("Copyright (C) 2007-2009 Isis Innovation Limited");
254 System.out.println("Copyright (C) 2009-2010 H. Ilari Liusvaara");
255 System.out.println("JPC-RR is released under GPL Version 2 and comes with absoutely no warranty.");
258 String library = ArgProcessor.findVariable(args, "library", null);
259 if(library == null) {
260 callShowOptionDialog(null, "No library specified (-library foo)", "Disk library missing",
261 JOptionPane.OK_OPTION, JOptionPane.WARNING_MESSAGE, null, new String[]{"Quit"}, "Quit");
262 return;
264 DiskImage.setLibrary(new ImageLibrary(library));
265 Plugins pluginManager = new Plugins();
266 BufferedReader kbd = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
268 String autoexec = ArgProcessor.findVariable(args, "autoexec", null);
269 if(autoexec != null) {
270 try {
271 BufferedReader kbd2 = new BufferedReader(new InputStreamReader(
272 new FileInputStream(autoexec), "UTF-8"));
273 while(true) {
274 String cmd = kbd2.readLine();
275 if(cmd == null)
276 break;
277 doCommand(pluginManager, cmd);
279 } catch (Exception e) {
280 System.err.println("Failed to load autoexec script: " + e.getMessage());
284 while(true) {
285 System.out.print("JPC-RR> ");
286 System.out.flush();
287 String cmd = kbd.readLine();
288 doCommand(pluginManager, cmd);