Refactor system flags
[jpcrr.git] / org / jpc / pluginsaux / PCConfigDialog.java
bloba8181119a1f240824eb71b17bf1c6e46f111da48
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.pluginsaux;
32 import org.jpc.emulator.PC;
33 import org.jpc.diskimages.DiskImage;
34 import org.jpc.emulator.DriveSet;
35 import static org.jpc.Misc.errorDialog;
37 import javax.swing.*;
38 import java.util.*;
39 import java.io.*;
40 import java.awt.event.*;
41 import java.awt.*;
43 public class PCConfigDialog implements ActionListener, WindowListener
45 private JFrame window;
46 private JPanel panel;
47 private PC.PCHardwareInfo hw;
48 private PC.PCHardwareInfo hwr;
49 private boolean answerReady;
50 private Map<String, JTextField> settings;
51 private Map<String, JComboBox> settings2;
52 private Map<String, JCheckBox> settings3;
53 private Map<String, Long> settings2Types;
54 private Map<String, String[]> settings2Values;
55 private JComboBox bootDevice;
57 public void addOption(String name, String id, String deflt)
59 JLabel label = new JLabel(name);
60 JTextField text = new JTextField(deflt, 40);
61 settings.put(id, text);
62 panel.add(label);
63 panel.add(text);
66 public void addBoolean(String name, String id)
68 JLabel label = new JLabel(name);
69 JCheckBox box = new JCheckBox("");
70 settings3.put(id, box);
71 panel.add(label);
72 panel.add(box);
75 public void addDiskCombo(String name, String id, long type) throws Exception
77 String[] choices = DiskImage.getLibrary().imagesByType(type);
78 JLabel label = new JLabel(name);
80 panel.add(label);
81 if(choices != null) {
82 Arrays.sort(choices);
83 settings2.put(id, new JComboBox(choices));
84 } else
85 settings2.put(id, new JComboBox());
87 panel.add(settings2.get(id));
88 settings2Types.put(id, new Long(type));
89 settings2Values.put(id, choices);
91 if(choices == null)
92 return;
94 //Hack to default the BIOS images.
95 if((type & 16) != 0 && Arrays.binarySearch(choices, id, null) >= 0)
96 settings2.get(id).setSelectedItem(id);
99 public void updateDiskCombo(String id) throws Exception
101 String[] choices = DiskImage.getLibrary().imagesByType(
102 settings2Types.get(id).longValue());
103 if(choices == null)
104 throw new Exception("No valid " + id + " image");
105 Arrays.sort(choices);
106 String[] oldChoices = settings2Values.get(id);
107 int oldChoicesLen = 0;
108 if(oldChoices != null)
109 oldChoicesLen = oldChoices.length;
110 JComboBox combo = settings2.get(id);
111 int i = 0, j = 0;
113 while(i < oldChoicesLen || j < choices.length) {
114 int x = 0;
115 if(i == oldChoicesLen)
116 x = 1;
117 else if(j == choices.length)
118 x = -1;
119 else
120 x = oldChoices[i].compareTo(choices[j]);
122 if(x < 0) {
123 combo.removeItem(oldChoices[i]);
124 i++;
125 } else if(x > 0) {
126 combo.addItem(choices[j]);
127 j++;
128 } else {
129 i++;
130 j++;
133 settings2Values.put(id, choices);
136 public PCConfigDialog() throws Exception
138 hw = new PC.PCHardwareInfo();
139 hwr = null;
140 answerReady = false;
141 window = new JFrame("PC Settings");
142 settings = new HashMap<String, JTextField>();
143 settings2 = new HashMap<String, JComboBox>();
144 settings3 = new HashMap<String, JCheckBox>();
146 settings2Types = new HashMap<String, Long>();
147 settings2Values = new HashMap<String, String[]>();
149 GridLayout layout = new GridLayout(0, 2);
150 panel = new JPanel(layout);
151 window.add(panel);
152 window.addWindowListener(this);
154 addDiskCombo("BIOS image", "BIOS", 16);
155 addDiskCombo("VGA BIOS image", "VGABIOS", 16);
156 addDiskCombo("Fda image", "FDA", 3);
157 addDiskCombo("Fdb image", "FDB", 3);
158 addDiskCombo("Hda image", "HDA", 5);
159 addDiskCombo("Hdb image", "HDB", 5);
160 addDiskCombo("Hdc image", "HDC", 5);
161 addDiskCombo("Hdd image", "HDD", 5);
162 addDiskCombo("CD-ROM image", "CDROM", 9);
163 addOption("Initial RTC time", "INITTIME", "1000000000000");
164 addOption("CPU freq. divider", "CPUDIVIDER", "50");
165 addOption("Memory size (4KiB pages)", "MEMSIZE", "4096");
166 addOption("Modules", "MODULES", "");
167 addBoolean("Emulate I/O delay", "IOPORTDELAY");
168 addBoolean("Emulate VGA Hretrace", "VGAHRETRACE");
169 addBoolean("Shorten pipeline for self-modifying code", "FLUSHONMODIFY");
170 settings3.get("FLUSHONMODIFY").setSelected(true);
172 JLabel label1 = new JLabel("Boot device");
173 bootDevice = new JComboBox(new String[]{"fda", "hda", "cdrom"});
174 bootDevice.setEditable(false);
175 panel.add(label1);
176 panel.add(bootDevice);
178 JButton ass = new JButton("Assemble");
179 ass.setActionCommand("ASSEMBLE");
180 ass.addActionListener(this);
181 JButton cancl = new JButton("Cancel");
182 cancl.setActionCommand("CANCEL");
183 cancl.addActionListener(this);
184 panel.add(ass);
185 panel.add(cancl);
187 window.pack();
188 window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
191 public void popUp() throws Exception
193 updateDiskCombo("BIOS");
194 updateDiskCombo("VGABIOS");
195 updateDiskCombo("FDA");
196 updateDiskCombo("FDB");
197 updateDiskCombo("HDA");
198 updateDiskCombo("HDB");
199 updateDiskCombo("HDC");
200 updateDiskCombo("HDD");
201 updateDiskCombo("CDROM");
203 window.setVisible(true);
206 public synchronized PC.PCHardwareInfo waitClose()
208 if(answerReady) {
209 answerReady = false;
210 return hwr;
212 while(!answerReady) {
213 try {
214 wait();
215 } catch(InterruptedException e) {
218 answerReady = false;
219 return hwr;
222 private String textFor(String field)
224 String x = null;
225 if(settings.containsKey(field))
226 x = settings.get(field).getText();
227 if(x == null)
228 x = (String)(settings2.get(field).getSelectedItem());
230 if(!("".equals(x))) {
231 return x;
232 } else
233 return null;
236 private boolean booleanValue(String field)
238 boolean x = false;
239 if(settings3.containsKey(field))
240 x = settings3.get(field).isSelected();
241 return x;
244 private boolean checkOK()
246 try {
247 String sysBIOSImg = textFor("BIOS");
248 hw.biosID = DiskImage.getLibrary().canonicalNameFor(sysBIOSImg);
249 if(hw.biosID == null)
250 throw new IOException("Can't find image \"" + sysBIOSImg + "\".");
252 String vgaBIOSImg = textFor("VGABIOS");
253 hw.vgaBIOSID = DiskImage.getLibrary().canonicalNameFor(vgaBIOSImg);
254 if(hw.vgaBIOSID == null)
255 throw new IOException("Can't find image \"" + vgaBIOSImg + "\".");
257 String hdaImg = textFor("HDA");
258 hw.hdaID = DiskImage.getLibrary().canonicalNameFor(hdaImg);
259 if(hw.hdaID == null && hdaImg != null)
260 throw new IOException("Can't find image \"" + hdaImg + "\".");
262 String hdbImg = textFor("HDB");
263 hw.hdbID = DiskImage.getLibrary().canonicalNameFor(hdbImg);
264 if(hw.hdbID == null && hdbImg != null)
265 throw new IOException("Can't find image \"" + hdbImg + "\".");
267 String hdcImg = textFor("HDC");
268 hw.hdcID = DiskImage.getLibrary().canonicalNameFor(hdcImg);
269 if(hw.hdcID == null && hdcImg != null)
270 throw new IOException("Can't find image \"" + hdcImg + "\".");
272 String hddImg = textFor("HDD");
273 hw.hddID = DiskImage.getLibrary().canonicalNameFor(hddImg);
274 if(hw.hddID == null && hddImg != null)
275 throw new IOException("Can't find image \"" + hddImg + "\".");
277 String cdRomFileName = textFor("CDROM");
278 if (cdRomFileName != null) {
279 if(hdcImg != null)
280 throw new IOException("-hdc and -cdrom are mutually exclusive.");
281 hw.initCDROMIndex = hw.images.addDisk(new DiskImage(cdRomFileName, false));
282 hw.images.lookupDisk(hw.initCDROMIndex).setName(cdRomFileName + " (initial cdrom disk)");
283 } else
284 hw.initCDROMIndex = -1;
286 String fdaFileName = textFor("FDA");
287 if(fdaFileName != null) {
288 byte[] fdaID = DiskImage.getLibrary().canonicalNameFor(fdaFileName);
289 if(fdaID == null && fdaFileName != null)
290 throw new IOException("Can't find image \"" + fdaFileName + "\".");
291 hw.initFDAIndex = hw.images.addDisk(new DiskImage(fdaFileName, false));
292 hw.images.lookupDisk(hw.initFDAIndex).setName(fdaFileName + " (initial fda disk)");
293 } else
294 hw.initFDAIndex = -1;
296 String fdbFileName = textFor("FDB");
297 if(fdbFileName != null) {
298 byte[] fdbID = DiskImage.getLibrary().canonicalNameFor(fdbFileName);
299 if(fdbID == null && fdbFileName != null)
300 throw new IOException("Can't find image \"" + fdbFileName + "\".");
301 hw.initFDBIndex = hw.images.addDisk(new DiskImage(fdbFileName, false));
302 hw.images.lookupDisk(hw.initFDBIndex).setName(fdbFileName + " (initial fdb disk)");
303 } else
304 hw.initFDBIndex = -1;
306 String initTimeS = textFor("INITTIME");
307 try {
308 hw.initRTCTime = Long.parseLong(initTimeS, 10);
309 if(hw.initRTCTime < 0 || hw.initRTCTime > 4102444799999L)
310 throw new Exception("Invalid time value (bounds are 0 and 4102444799999).");
311 } catch(Exception e) {
312 if(initTimeS != null)
313 throw e;
314 hw.initRTCTime = 1000000000000L;
317 String cpuDividerS = textFor("CPUDIVIDER");
318 try {
319 hw.cpuDivider = Integer.parseInt(cpuDividerS, 10);
320 if(hw.cpuDivider < 1 || hw.cpuDivider > 256)
321 throw new Exception("Invalid CPU divider value (bounds are 1 and 256).");
322 } catch(Exception e) {
323 if(cpuDividerS != null)
324 throw e;
325 hw.cpuDivider = 50;
328 hw.fpuEmulator = null;
330 String memoryPagesS = textFor("MEMSIZE");
331 try {
332 hw.memoryPages = Integer.parseInt(memoryPagesS, 10);
333 if(hw.memoryPages < 256 || hw.memoryPages > 262144)
334 throw new Exception("Invalid memory size value (bounds are 256 and 262144).");
335 } catch(Exception e) {
336 if(memoryPagesS != null)
337 throw e;
338 hw.memoryPages = 4096;
341 String bootArg = (String)bootDevice.getSelectedItem();
342 bootArg = bootArg.toLowerCase();
343 if (bootArg.equals("fda"))
344 hw.bootType = DriveSet.BootType.FLOPPY;
345 else if (bootArg.equals("hda"))
346 hw.bootType = DriveSet.BootType.HARD_DRIVE;
347 else if (bootArg.equals("cdrom"))
348 hw.bootType = DriveSet.BootType.CDROM;
350 String hwModulesS = textFor("MODULES");
351 if(hwModulesS != null) {
352 hw.hwModules = PC.parseHWModules(hwModulesS);
355 hw.booleanOptions = new TreeMap<String, Boolean>();
356 for(Map.Entry<String, JCheckBox> box : settings3.entrySet())
357 hw.booleanOptions.put(box.getKey(), booleanValue(box.getKey()));
358 } catch(Exception e) {
359 errorDialog(e, "Problem with settings.", window, "Dismiss");
360 return false;
362 return true;
365 public void actionPerformed(ActionEvent evt)
367 String command = evt.getActionCommand();
368 if(command == "ASSEMBLE") {
369 if(!checkOK()) {
370 hw = new PC.PCHardwareInfo();
371 return;
373 window.setVisible(false);
374 synchronized(this) {
375 hwr = hw;
376 answerReady = true;
377 notifyAll();
378 hw = new PC.PCHardwareInfo();
380 hw = new PC.PCHardwareInfo();
381 } else if(command == "CANCEL") {
382 window.setVisible(false);
383 synchronized(this) {
384 hwr = null;
385 answerReady = true;
386 notifyAll();
391 public void windowActivated(WindowEvent e) { /* Not interested. */ }
392 public void windowClosed(WindowEvent e) { /* Not interested. */ }
393 public void windowDeactivated(WindowEvent e) { /* Not interested. */ }
394 public void windowDeiconified(WindowEvent e) { /* Not interested. */ }
395 public void windowIconified(WindowEvent e) { /* Not interested. */ }
396 public void windowOpened(WindowEvent e) { /* Not interested. */ }
398 public void windowClosing(WindowEvent e)
400 window.setVisible(false);
401 synchronized(this) {
402 hwr = null;
403 answerReady = true;
404 notifyAll();