/** * encoding: UTF-8 * JaC64 - Application for JaC64 emulator * A Swing UI for the JaC64 emulator for download to Java enabled * Desktop computers. * Created: Sat Dec 08 23:27:15 2007 * * @author Joakim Eriksson, Dreamfabric / joakime@sics.se * @version 1.0 */ import java.applet.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import java.net.*; import com.dreamfabric.jac64.*; import com.dreamfabric.c64utils.*; public class JaC64 implements ActionListener, KeyEventDispatcher { private static final String ABOUT_MESSAGE = "JaC64 version: " + C64Screen.version + "\n" + "JaC64 is a Java-based C64 emulator by Joakim Eriksson\n" + "The SID emulation use the resid Java port by Ken Händel\n\n" + "For more information see: http://www.jac64.com/"; private C64Reader reader; private C64Screen scr; private boolean fullscreen = false; private CPU cpu; private JFrame C64Win; private KeyListener c64Canvas; private FileDialog fileDialog; private JMenuItem load; private JTable fileTable; private JDialog loadFile; private DirEntry[] dirEntries; private static final String[] SID_TYPES = new String[] {"SID: resid MOS 6581", "SID: resid MOS 8580", "SID: JaC64 Original"}; private static final String[] JOYSTICK = new String[] {"Joystick in port 1", "Joystick in port 2"}; private TableModel dataModel = new AbstractTableModel() { public final String[] NAMES = new String[] {"File name", "Size", "Type"}; public int getColumnCount() { return 3;} public int getRowCount() { return (dirEntries != null ? dirEntries.length : 0);} public Object getValueAt(int row, int col) { if (col == 0) return dirEntries[row].name; if (col == 1) return new Integer(dirEntries[row].size); if (col == 2) return dirEntries[row].getTypeString(); return "-"; } public String getColumnName(int col) { return NAMES[col]; } }; public JaC64() { SIDMixer.DL_BUFFER_SIZE = 16384; Debugger monitor = new Debugger(); cpu = new CPU(monitor, "", new SELoader()); scr = new C64Screen(monitor, true); cpu.init(scr); // Reader available after init! scr.init(cpu); scr.registerHotKey(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK , "reset()", cpu); scr.registerHotKey(KeyEvent.VK_F12, KeyEvent.CTRL_DOWN_MASK , "toggleFullScreen()", this); reader = new C64Reader(); // scr.getDiskDrive().getReader(); reader.setCPU(cpu); cpu.getDrive().setReader(reader); C64Win = new JFrame("JaC64 - A Java C64 Emulator"); C64Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JMenuBar jbar = new JMenuBar(); C64Win.setJMenuBar(jbar); JMenu filem; JMenuItem mi; jbar.add(filem = new JMenu("File")); filem.add(mi = new JMenuItem("Open File/Disk")); mi.addActionListener(this); filem.add(load = new JMenuItem("Load File")); load.addActionListener(this); filem.add(mi = new JMenuItem("Reset")); mi.addActionListener(this); filem.add(mi = new JMenuItem("Hard Reset")); mi.addActionListener(this); filem.add(mi = new JMenuItem("About JaC64")); mi.addActionListener(this); jbar.add(filem = new JMenu("Settings")); JMenu subm; filem.add(subm = new JMenu("Color Set")); createRadioMenu(subm, new String[] {"Color Set 1 - JaC64 original", "Color Set 2 - darker", "Color Set 3 - softer", "Color Set 4 - Win VICE"}, 0); filem.add(subm = new JMenu("SID Emulation")); createRadioMenu(subm, SID_TYPES, 0); filem.add(subm = new JMenu("Joystick Port")); createRadioMenu(subm, JOYSTICK, 0); C64Win.setBackground(Color.black); C64Win.setForeground(Color.black); C64Win.setLayout(new BorderLayout()); C64Win.getContentPane().add(scr.getScreen(), BorderLayout.CENTER); C64Win.setFocusable(true); C64Win.pack(); // C64Scr.setSize(380,300); C64Win.setSize(386 * 2 + 10, 284 * 2 + 70); C64Win.setResizable(true); C64Win.setVisible(true); KeyboardFocusManager. getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); // Setup disk sounds AudioClip trackSound = null; AudioClip motorSound = null; URL url = getClass().getResource("sounds/track.wav"); if (url != null) trackSound = Applet.newAudioClip(url); url = getClass().getResource("sounds/motor.wav"); if (url != null) motorSound = Applet.newAudioClip(url); scr.setSounds(trackSound, motorSound); c64Canvas = (KeyListener) scr.getScreen(); } private void createRadioMenu(JMenu subm, String[] names, int selected) { ButtonGroup group = new ButtonGroup(); JRadioButtonMenuItem mi; for (int i = 0; i < names.length; i++) { subm.add(mi = new JRadioButtonMenuItem(names[i])); if (i == selected) mi.setSelected(true); mi.addActionListener(this); group.add(mi); } } public boolean dispatchKeyEvent(KeyEvent e) { if (C64Win.isFocused()) { if (e.getID() == KeyEvent.KEY_PRESSED) { c64Canvas.keyPressed(e); } else if (e.getID() == KeyEvent.KEY_RELEASED) { c64Canvas.keyReleased(e); } else if (e.getID() == KeyEvent.KEY_TYPED) { c64Canvas.keyTyped(e); } return true; } return false; } public void actionPerformed(ActionEvent ae) { String cmd = ae.getActionCommand(); if ("Open File/Disk".equals(cmd)) { if (fileTable == null) { // Show the table somewhere!!! fileTable = new JTable(dataModel); fileTable.getColumnModel().getColumn(1).setMaxWidth(50); fileTable.getColumnModel().getColumn(2).setMaxWidth(50); fileTable.setShowGrid(false); fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } readDisk(); } else if ("Reset".equals(cmd)){ cpu.reset(); } else if ("Hard Reset".equals(cmd)){ cpu.hardReset(); } else if ("About JaC64".equals(cmd)) { showAbout(); } else if ("Load File".equals(cmd)) { if (loadFile == null) { loadFile = new JDialog(C64Win, "Load file from disk"); loadFile.setAlwaysOnTop(true); loadFile.setVisible(true); loadFile.setLayout(new BorderLayout()); loadFile.add(new JScrollPane(fileTable), BorderLayout.CENTER); loadFile.add(fileTable.getTableHeader(), BorderLayout.NORTH); JPanel jp = new JPanel(); JButton jb; jp.add(jb = new JButton("Load file")); jb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { reader.readFile(dirEntries[fileTable.getSelectedRow()].name); loadFile.setVisible(false); } }); jp.add(jb = new JButton("Cancel")); jb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { loadFile.setVisible(false); } }); loadFile.add(jp, BorderLayout.SOUTH); loadFile.setSize(300, 400); } loadFile.setVisible(true); } else if (cmd.startsWith("Color Set")) { int cs = cmd.charAt(10) - '1'; System.out.println("Color set: " + cs); scr.setColorSet(cs); } else if (cmd.equals(SID_TYPES[0])) { scr.setSID(C64Screen.RESID_6581); } else if (cmd.equals(SID_TYPES[1])) { scr.setSID(C64Screen.RESID_8580); } else if (cmd.equals(SID_TYPES[2])) { scr.setSID(C64Screen.JACSID); } else if (cmd.equals(JOYSTICK[0])) { scr.setStick(true); } else if (cmd.equals(JOYSTICK[1])) { scr.setStick(false); } } private void showAbout() { JOptionPane.showMessageDialog(C64Win, ABOUT_MESSAGE, "JaC64 - The Java C64 Emulator", JOptionPane.INFORMATION_MESSAGE); } public void toggleFullScreen() { System.out.println("Toggle fullscreen called!"); setFull(!fullscreen); } private void readDisk() { if (fileDialog == null) fileDialog = new FileDialog(C64Win, "Select File/Disk to Load"); fileDialog.setVisible(true); String name = fileDialog.getDirectory() + fileDialog.getFile(); if (!readDisk(name)) { dirEntries = (DirEntry[]) reader.getDirNames().toArray(new DirEntry[0]); fileTable.tableChanged(new TableModelEvent(dataModel)); } } private boolean readDisk(String name) { System.out.println("READING FROM: " + name); if ((name.toLowerCase()).endsWith(".d64")) reader.readDiskFromFile(name); else if ((name.toLowerCase()).endsWith(".t64")) reader.readTapeFromFile(name); else if (name.toLowerCase().endsWith(".prg") || name.toLowerCase().endsWith(".p00")) { cpu.reset(); try { Thread.sleep(10); }catch (Exception e2) { System.out.println("Exception while sleeping..."); } while(!scr.ready()) { try { Thread.sleep(100); }catch (Exception e2) { System.out.println("Exception while sleeping..."); } } reader.readPGM(name, -1); cpu.runBasic(); return true; } return false; } private void setFull(boolean full) { // JWindow jw = full ? C64Scr : null; // java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(). // getDefaultScreenDevice().setFullScreenWindow(jw); // if (!full) { // C64Scr.setSize(386 * 2, 284 * 2); // C64Scr.validate(); // } // fullscreen = full; } public static void main(String[] name) { JaC64 test = new JaC64(); test.cpu.start(); } }