2 JPC-RR: A x86 PC Hardware Emulator
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
;
40 import java
.awt
.event
.*;
43 public class PCConfigDialog
implements ActionListener
, WindowListener
45 private JFrame window
;
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
);
66 public void addBoolean(String name
, String id
)
68 JLabel label
= new JLabel(name
);
69 JCheckBox box
= new JCheckBox("");
70 settings3
.put(id
, 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
);
83 settings2
.put(id
, new JComboBox(choices
));
85 settings2
.put(id
, new JComboBox());
87 panel
.add(settings2
.get(id
));
88 settings2Types
.put(id
, new Long(type
));
89 settings2Values
.put(id
, choices
);
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());
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
);
113 while(i
< oldChoicesLen
|| j
< choices
.length
) {
115 if(i
== oldChoicesLen
)
117 else if(j
== choices
.length
)
120 x
= oldChoices
[i
].compareTo(choices
[j
]);
123 combo
.removeItem(oldChoices
[i
]);
126 combo
.addItem(choices
[j
]);
133 settings2Values
.put(id
, choices
);
136 public PCConfigDialog() throws Exception
138 hw
= new PC
.PCHardwareInfo();
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
);
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);
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);
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()
212 while(!answerReady
) {
215 } catch(InterruptedException e
) {
222 private String
textFor(String field
)
225 if(settings
.containsKey(field
))
226 x
= settings
.get(field
).getText();
228 x
= (String
)(settings2
.get(field
).getSelectedItem());
230 if(!("".equals(x
))) {
236 private boolean booleanValue(String field
)
239 if(settings3
.containsKey(field
))
240 x
= settings3
.get(field
).isSelected();
244 private boolean checkOK()
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) {
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)");
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)");
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)");
304 hw
.initFDBIndex
= -1;
306 String initTimeS
= textFor("INITTIME");
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)
314 hw
.initRTCTime
= 1000000000000L;
317 String cpuDividerS
= textFor("CPUDIVIDER");
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)
328 hw
.fpuEmulator
= null;
330 String memoryPagesS
= textFor("MEMSIZE");
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)
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");
365 public void actionPerformed(ActionEvent evt
)
367 String command
= evt
.getActionCommand();
368 if(command
== "ASSEMBLE") {
370 hw
= new PC
.PCHardwareInfo();
373 window
.setVisible(false);
378 hw
= new PC
.PCHardwareInfo();
380 hw
= new PC
.PCHardwareInfo();
381 } else if(command
== "CANCEL") {
382 window
.setVisible(false);
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);