Subtitle library
[jpcrr.git] / org / jpc / j2se / JPCApplication.java
blob0c69179088beee104505d00f728e9041e552ca5e
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009-2010 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.io.*;
33 import javax.swing.*;
34 import java.util.List;
35 import java.lang.reflect.*;
37 import org.jpc.*;
38 import org.jpc.diskimages.ImageLibrary;
39 import org.jpc.diskimages.ImageMaker;
40 import org.jpc.diskimages.DiskImage;
41 import org.jpc.pluginsbase.*;
43 import static org.jpc.Revision.getRevision;
44 import static org.jpc.Misc.errorDialog;
45 import static org.jpc.Misc.callShowOptionDialog;
46 import static org.jpc.Misc.parseString;
48 public class JPCApplication
50 public static Plugin instantiatePlugin(Plugins pluginManager, Class<?> plugin, String arguments) throws IOException
52 Constructor<?> cc;
54 if(arguments != null) {
55 try {
56 cc = plugin.getConstructor(Plugins.class, String.class);
57 } catch(Exception e) {
58 throw new IOException("Plugin \"" + plugin.getName() + "\" does not take arguments.");
60 } else {
61 try {
62 cc = plugin.getConstructor(Plugins.class);
63 } catch(Exception e) {
64 throw new IOException("Plugin \"" + plugin.getName() + "\" requires arguments.");
68 try {
69 if(arguments != null)
70 return (Plugin)cc.newInstance(pluginManager, arguments);
71 else
72 return (Plugin)cc.newInstance(pluginManager);
73 } catch(InvocationTargetException e) {
74 Throwable e2 = e.getCause();
75 //If the exception is something unchecked, just pass it through.
76 if(e2 instanceof RuntimeException)
77 throw (RuntimeException)e2;
78 if(e2 instanceof Error) {
79 IOException ne = new IOException("Error while invoking loader: " + e2);
80 ne.setStackTrace(e2.getStackTrace()); //Copy stack trace.
81 throw ne;
83 //Also pass IOException through.
84 if(e2 instanceof IOException)
85 throw (IOException)e2;
86 //What the heck is that?
87 IOException ne = new IOException("Unknown exception while invoking loader: " + e2);
88 ne.setStackTrace(e2.getStackTrace()); //Copy stack trace.
89 throw ne;
90 } catch(Exception e) {
91 throw new IOException("Failed to invoke plugin \"" + plugin.getName() + "\" constructor.");
95 private static void loadPlugin(Plugins pluginManager, String arg) throws IOException
97 String moduleString = arg;
98 String currentModule;
99 int parenDepth = 0;
100 int nameEnd = -1;
101 int paramsStart = -1;
102 int paramsEnd = -1;
103 int stringLen = moduleString.length();
104 boolean requireNextSep = false;
106 for(int i = 0; true; i++) {
107 int cp;
108 if(i < stringLen)
109 cp = moduleString.codePointAt(i);
110 else if(parenDepth == 0) {
111 if(nameEnd < 0)
112 nameEnd = i - 1;
113 currentModule = moduleString.substring(0, i);
114 if(i < stringLen ) {
115 moduleString = moduleString.substring(i + 1);
116 if(moduleString.equals(""))
117 throw new IOException("Error in module string: Blank module name not allowed.");
118 } else
119 moduleString = "";
120 break;
121 } else
122 throw new IOException("Error in module string: unclosed '('.");
123 if(cp >= 0x10000)
124 i++; //Skip the next surrogate.
125 if((cp >= 0xD800 && cp < 0xE000) || ((cp & 0xFFFE) == 0xFFFE) || (cp >>> 16) > 16 || cp < 0)
126 throw new IOException("Error In module string: invalid Unicode character.");
127 if(requireNextSep && cp != ',')
128 throw new IOException("Error in module string: Expected ',' after ')' closing parameter list.");
129 else if(cp == ',' && i == 0)
130 throw new IOException("Error in module string: Blank module name not allowed.");
131 else if(cp == '(') {
132 if(parenDepth == 0) {
133 paramsStart = i + 1;
134 nameEnd = i - 1;
136 parenDepth++;
137 } else if(cp == ')') {
138 if(parenDepth == 0)
139 throw new IOException("Error in module string: Unpaired ')'.");
140 else if(parenDepth == 1) {
141 paramsEnd = i - 1;
142 requireNextSep = true;
144 parenDepth--;
148 String name = currentModule.substring(0, nameEnd + 1);
149 String params = null;
150 if(paramsStart >= 0)
151 params = currentModule.substring(paramsStart, paramsEnd + 1);
153 Class<?> plugin;
155 try {
156 plugin = Class.forName(name);
157 } catch(Exception e) {
158 throw new IOException("Unable to find plugin \"" + name + "\".");
161 if(!Plugin.class.isAssignableFrom(plugin)) {
162 throw new IOException("Plugin \"" + name + "\" is not valid plugin.");
164 Plugin c = instantiatePlugin(pluginManager, plugin, params);
165 pluginManager.registerPlugin(c);
168 private static void doListImages(ImageLibrary lib, String restOfCommand) throws IOException
170 PrintStream out = System.out;
171 boolean doClose = false;
172 if(restOfCommand != null) {
173 OutputStream outb = new BufferedOutputStream(new FileOutputStream(restOfCommand));
174 out = new PrintStream(outb, false, "UTF-8");
175 doClose = true;
178 //Get present images of any tyype.
179 String[] images = lib.imagesByType(~0x1L);
180 for(String i : images)
181 printImageInfo(out, lib, i, true);
183 if(doClose)
184 out.close();
188 public static void printImageInfo(PrintStream out, ImageLibrary lib, String origName, boolean brief) throws IOException
190 String fileName = lib.searchFileName(origName);
191 if(fileName == null) {
192 System.err.println("No image named '" + origName + "' exists.");
193 return;
195 try {
196 ImageMaker.ParsedImage pimg = new ImageMaker.ParsedImage(fileName);
197 String typeString;
198 switch(pimg.typeCode) {
199 case 0:
200 typeString = "floppy ";
201 break;
202 case 1:
203 typeString = "HDD ";
204 break;
205 case 2:
206 typeString = "CD-ROM ";
207 break;
208 case 3:
209 typeString = "BIOS ";
210 break;
211 default:
212 typeString = "<Unknown> ";
213 break;
215 if(brief) {
216 out.println("" + (new ImageLibrary.ByteArray(pimg.diskID)) + " " + typeString + " " + origName);
217 return;
220 out.println("Name : " + origName);
221 out.println("File name : " + fileName);
222 out.println("Type : " + typeString);
223 if(pimg.typeCode == 0 || pimg.typeCode == 1) {
224 out.println("Tracks : " + pimg.tracks);
225 out.println("Sides : " + pimg.sides);
226 out.println("Sectors : " + pimg.sectors);
227 out.println("Total sectors : " + pimg.totalSectors);
228 out.println("Primary extent size: " + pimg.sectorsPresent);
229 out.println("Storage Method : " + pimg.method);
230 int actualSectors = 0;
232 for(int i = 0; i < pimg.totalSectors; i++) {
233 if(i < pimg.sectorOffsetMap.length && pimg.sectorOffsetMap[i] > 0)
234 actualSectors++;
236 out.println("Sectors present : " + actualSectors);
237 } else if(pimg.typeCode == 2) {
238 out.println("Total sectors : " + pimg.totalSectors);
239 } else if(pimg.typeCode == 3) {
240 out.println("Image Size : " + pimg.rawImage.length);
243 out.println("Claimed Disk ID : " + (new ImageLibrary.ByteArray(pimg.diskID)));
244 List<String> comments = pimg.comments;
245 if(comments != null) {
246 out.println("");
247 out.println("Comments section:");
248 out.println("");
249 for(String x : comments)
250 out.println(x);
252 } catch(IOException e) {
253 errorDialog(e, "Failed to read image", null, "Quit");
258 private static void doImageInfo(ImageLibrary lib, String restOfCommand) throws IOException
260 PrintStream out = System.out;
261 boolean doClose = false;
262 int sIndex = restOfCommand.indexOf(" ");
263 if(sIndex > 0) {
264 String outName = restOfCommand.substring(0, sIndex);
265 restOfCommand = restOfCommand.substring(sIndex + 1);
266 OutputStream outb = new BufferedOutputStream(new FileOutputStream(outName));
267 out = new PrintStream(outb, false, "UTF-8");
268 doClose = true;
271 printImageInfo(out, lib, restOfCommand, false);
273 if(doClose)
274 out.close();
278 public static void doCommand(Plugins pluginManager, String cmd) throws IOException
280 if(cmd.toLowerCase().startsWith("load ")) {
281 try {
282 loadPlugin(pluginManager, cmd.substring(5));
283 } catch(Exception e) {
284 errorDialog(e, "Plugin Loading failed", null, "Dismiss");
286 } else if(cmd.toLowerCase().equals("exit")) {
287 pluginManager.shutdownEmulator();
288 } else if(cmd.toLowerCase().equals("")) {
289 } else if(cmd.toLowerCase().startsWith("command ")) {
290 try {
291 String[] arr = parseString(cmd.substring(8));
292 if(arr == null)
293 throw new Exception("No command to send given");
294 String rcmd = arr[0];
295 String[] rargs = null;
296 if(arr.length > 1) {
297 rargs = new String[arr.length - 1];
298 System.arraycopy(arr, 1, rargs, 0, arr.length - 1);
300 pluginManager.invokeExternalCommandSynchronous(rcmd, rargs);
301 } catch(Exception e) {
302 errorDialog(e, "Command sending failed", null, "Dismiss");
304 } else if(cmd.toLowerCase().startsWith("call ")) {
305 try {
306 String[] arr = parseString(cmd.substring(5));
307 if(arr == null)
308 throw new Exception("No command to send given");
309 String rcmd = arr[0];
310 String[] rargs = null;
311 if(arr.length > 1) {
312 rargs = new String[arr.length - 1];
313 System.arraycopy(arr, 1, rargs, 0, arr.length - 1);
315 Object[] ret = pluginManager.invokeExternalCommandReturn(rcmd, rargs);
316 if(ret != null)
317 for(int i = 0; i < ret.length; i++)
318 System.out.println(ret[i].toString());
319 else
320 System.out.println("Nothing returned.");
321 } catch(Exception e) {
322 errorDialog(e, "Command sending failed", null, "Dismiss");
324 } else if(cmd.toLowerCase().startsWith("library ")) {
325 String library = cmd.substring(8);
326 File libraryFile = new File(library);
327 if(!libraryFile.isDirectory()) {
328 if(!libraryFile.mkdirs()) {
329 callShowOptionDialog(null, "Library (" + library + ") does not exist and can't be created",
330 "Disk library error", JOptionPane.OK_OPTION, JOptionPane.WARNING_MESSAGE, null,
331 new String[]{"Dismiss"}, "Dismiss");
332 return;
335 DiskImage.setLibrary(new ImageLibrary(library));
336 } else if(cmd.toLowerCase().equals("lsdisks") || cmd.toLowerCase().startsWith("lsdisks ")) {
337 String rest = null;
338 if(cmd.length() > 8)
339 rest = cmd.substring(8);
340 ImageLibrary lib = DiskImage.getLibrary();
341 if(lib == null) {
342 System.err.println("No library loaded");
343 return;
345 try {
346 doListImages(lib, rest);
347 } catch(Exception e) {
348 errorDialog(e, "Failed to lisk known images", null, "Dismiss");
350 } else if(cmd.toLowerCase().startsWith("diskinfo ")) {
351 String rest = cmd.substring(9);
352 ImageLibrary lib = DiskImage.getLibrary();
353 if(lib == null) {
354 System.err.println("No library loaded");
355 return;
357 try {
358 doImageInfo(lib, rest);
359 } catch(Exception e) {
360 errorDialog(e, "Failed to get information for image", null, "Dismiss");
362 } else {
363 System.err.println("Invalid command");
367 public static void main(String[] args) throws Exception
371 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
372 } catch (Throwable e) { //Yes, we need to catch errors too.
373 System.err.println("Warning: System Look-and-Feel not loaded" + e.getMessage());
376 System.out.println("JPC-RR: Rerecording PC emulator based on JPC PC emulator. Release 10.9");
377 System.out.println("Revision: " + getRevision());
378 System.out.println("Based on JPC PC emulator.");
379 System.out.println("Copyright (C) 2007-2009 Isis Innovation Limited");
380 System.out.println("Copyright (C) 2009-2010 H. Ilari Liusvaara");
381 System.out.println("JPC-RR is released under GPL Version 2 and comes with absoutely no warranty.");
383 //Probe if rename-over is supported.
384 Misc.probeRenameOver(ArgProcessor.findFlag(args, "-norenames"));
386 Plugins pluginManager = new Plugins();
387 BufferedReader kbd = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
389 boolean noautoexec = ArgProcessor.findFlag(args, "-noautoexec");
390 String autoexec = ArgProcessor.findVariable(args, "autoexec", null);
391 if(autoexec != null && !noautoexec) {
392 try {
393 BufferedReader kbd2 = new BufferedReader(new InputStreamReader(
394 new FileInputStream(autoexec), "UTF-8"));
395 while(true) {
396 String cmd = kbd2.readLine();
397 if(cmd == null)
398 break;
399 doCommand(pluginManager, cmd);
401 } catch (Exception e) {
402 System.err.println("Failed to load autoexec script: " + e.getMessage());
406 while(true) {
407 System.out.print("JPC-RR> ");
408 System.out.flush();
409 String cmd = kbd.readLine();
410 try {
411 doCommand(pluginManager, cmd);
412 } catch (Exception e) {
413 errorDialog(e, "Command execution failed", null, "Dismiss");