mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Michael Schierl's patch to compile the puzzles as Java applets using
NestedVM. Wow! [originally from svn r8064]
This commit is contained in:
2
LICENCE
2
LICENCE
@ -1,7 +1,7 @@
|
|||||||
This software is copyright (c) 2004-2008 Simon Tatham.
|
This software is copyright (c) 2004-2008 Simon Tatham.
|
||||||
|
|
||||||
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
|
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
|
||||||
K<EFBFBD>lker and Dariusz Olszewski.
|
K<EFBFBD>lker, Dariusz Olszewski and Michael Schierl.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation files
|
obtaining a copy of this software and associated documentation files
|
||||||
|
598
PuzzleApplet.java
Normal file
598
PuzzleApplet.java
Normal file
@ -0,0 +1,598 @@
|
|||||||
|
/*
|
||||||
|
* PuzzleApplet.java: NestedVM applet for the puzzle collection
|
||||||
|
*/
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.BevelBorder;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.ibex.nestedvm.Runtime;
|
||||||
|
|
||||||
|
public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final int CFG_SETTINGS = 0, CFG_SEED = 1, CFG_DESC = 2,
|
||||||
|
LEFT_BUTTON = 0x0200, MIDDLE_BUTTON = 0x201, RIGHT_BUTTON = 0x202,
|
||||||
|
LEFT_DRAG = 0x203, MIDDLE_DRAG = 0x204, RIGHT_DRAG = 0x205,
|
||||||
|
LEFT_RELEASE = 0x206, CURSOR_UP = 0x209, CURSOR_DOWN = 0x20a,
|
||||||
|
CURSOR_LEFT = 0x20b, CURSOR_RIGHT = 0x20c, MOD_CTRL = 0x1000,
|
||||||
|
MOD_SHFT = 0x2000, MOD_NUM_KEYPAD = 0x4000, ALIGN_VCENTRE = 0x100,
|
||||||
|
ALIGN_HCENTRE = 0x001, ALIGN_HRIGHT = 0x002, C_STRING = 0,
|
||||||
|
C_CHOICES = 1, C_BOOLEAN = 2;
|
||||||
|
|
||||||
|
private JFrame mainWindow;
|
||||||
|
|
||||||
|
private JMenu typeMenu;
|
||||||
|
private JMenuItem solveCommand;
|
||||||
|
private Color[] colors;
|
||||||
|
private JLabel statusBar;
|
||||||
|
private PuzzlePanel pp;
|
||||||
|
private Runtime runtime;
|
||||||
|
private Graphics2D gg;
|
||||||
|
private Timer timer;
|
||||||
|
private int xarg1, xarg2, xarg3;
|
||||||
|
private int[] xPoints, yPoints;
|
||||||
|
private BufferedImage[] blitters = new BufferedImage[512];
|
||||||
|
private ConfigDialog dlg;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
try {
|
||||||
|
Container cp = getContentPane();
|
||||||
|
cp.setLayout(new BorderLayout());
|
||||||
|
runtime = (Runtime) Class.forName("PuzzleEngine").newInstance();
|
||||||
|
runtime.setCallJavaCB(this);
|
||||||
|
JMenuBar menubar = new JMenuBar();
|
||||||
|
JMenu jm;
|
||||||
|
menubar.add(jm = new JMenu("Game"));
|
||||||
|
addMenuItemWithKey(jm, "New", 'n');
|
||||||
|
addMenuItemCallback(jm, "Restart", "jcallback_restart_event");
|
||||||
|
addMenuItemCallback(jm, "Specific...", "jcallback_config_event", CFG_DESC);
|
||||||
|
addMenuItemCallback(jm, "Random Seed...", "jcallback_config_event", CFG_SEED);
|
||||||
|
jm.addSeparator();
|
||||||
|
addMenuItemWithKey(jm, "Undo", 'u');
|
||||||
|
addMenuItemWithKey(jm, "Redo", 'r');
|
||||||
|
jm.addSeparator();
|
||||||
|
solveCommand = addMenuItemCallback(jm, "Solve", "jcallback_solve_event");
|
||||||
|
solveCommand.setEnabled(false);
|
||||||
|
if (mainWindow != null) {
|
||||||
|
jm.addSeparator();
|
||||||
|
addMenuItemWithKey(jm, "Exit", 'q');
|
||||||
|
}
|
||||||
|
menubar.add(typeMenu = new JMenu("Type"));
|
||||||
|
typeMenu.setVisible(false);
|
||||||
|
menubar.add(jm = new JMenu("Help"));
|
||||||
|
addMenuItemCallback(jm, "About", "jcallback_about_event");
|
||||||
|
setJMenuBar(menubar);
|
||||||
|
cp.add(pp = new PuzzlePanel(), BorderLayout.CENTER);
|
||||||
|
pp.addKeyListener(new KeyAdapter() {
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
int key = -1;
|
||||||
|
int shift = e.isShiftDown() ? MOD_SHFT : 0;
|
||||||
|
int ctrl = e.isControlDown() ? MOD_CTRL : 0;
|
||||||
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_LEFT:
|
||||||
|
case KeyEvent.VK_KP_LEFT:
|
||||||
|
key = shift | ctrl | CURSOR_LEFT;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_RIGHT:
|
||||||
|
case KeyEvent.VK_KP_RIGHT:
|
||||||
|
key = shift | ctrl | CURSOR_RIGHT;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_UP:
|
||||||
|
case KeyEvent.VK_KP_UP:
|
||||||
|
key = shift | ctrl | CURSOR_UP;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_DOWN:
|
||||||
|
case KeyEvent.VK_KP_DOWN:
|
||||||
|
key = shift | ctrl | CURSOR_DOWN;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_PAGE_UP:
|
||||||
|
key = shift | ctrl | MOD_NUM_KEYPAD | '9';
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_PAGE_DOWN:
|
||||||
|
key = shift | ctrl | MOD_NUM_KEYPAD | '3';
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_HOME:
|
||||||
|
key = shift | ctrl | MOD_NUM_KEYPAD | '7';
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_END:
|
||||||
|
key = shift | ctrl | MOD_NUM_KEYPAD | '1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (e.getKeyCode() >= KeyEvent.VK_NUMPAD0 && e.getKeyCode() <=KeyEvent.VK_NUMPAD9) {
|
||||||
|
key = MOD_NUM_KEYPAD | (e.getKeyCode() - KeyEvent.VK_NUMPAD0+'0');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (key != -1) {
|
||||||
|
runtimeCall("jcallback_key_event", new int[] {0, 0, key});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void keyTyped(KeyEvent e) {
|
||||||
|
runtimeCall("jcallback_key_event", new int[] {0, 0, e.getKeyChar()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pp.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
mousePressedReleased(e, true);
|
||||||
|
}
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
pp.requestFocus();
|
||||||
|
mousePressedReleased(e, false);
|
||||||
|
}
|
||||||
|
private void mousePressedReleased(MouseEvent e, boolean released) {
|
||||||
|
int button;
|
||||||
|
if ((e.getModifiers() & (InputEvent.BUTTON2_MASK | InputEvent.SHIFT_MASK)) != 0)
|
||||||
|
button = MIDDLE_BUTTON;
|
||||||
|
else if ((e.getModifiers() & (InputEvent.BUTTON3_MASK | InputEvent.ALT_MASK)) != 0)
|
||||||
|
button = RIGHT_BUTTON;
|
||||||
|
else if ((e.getModifiers() & (InputEvent.BUTTON1_MASK)) != 0)
|
||||||
|
button = LEFT_BUTTON;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
if (released)
|
||||||
|
button += LEFT_RELEASE - LEFT_BUTTON;
|
||||||
|
runtimeCall("jcallback_key_event", new int[] {e.getX(), e.getY(), button});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pp.addMouseMotionListener(new MouseMotionAdapter() {
|
||||||
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
int button;
|
||||||
|
if ((e.getModifiers() & (InputEvent.BUTTON2_MASK | InputEvent.SHIFT_MASK)) != 0)
|
||||||
|
button = MIDDLE_DRAG;
|
||||||
|
else if ((e.getModifiers() & (InputEvent.BUTTON3_MASK | InputEvent.ALT_MASK)) != 0)
|
||||||
|
button = RIGHT_DRAG;
|
||||||
|
else
|
||||||
|
button = LEFT_DRAG;
|
||||||
|
runtimeCall("jcallback_key_event", new int[] {e.getX(), e.getY(), button});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pp.addComponentListener(new ComponentAdapter() {
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
handleResized();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pp.setFocusable(true);
|
||||||
|
pp.requestFocus();
|
||||||
|
timer = new Timer(20, new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
runtimeCall("jcallback_timer_func", new int[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
runtime.start();
|
||||||
|
runtime.execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
runtime.execute();
|
||||||
|
if (mainWindow != null) {
|
||||||
|
mainWindow.dispose();
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleResized() {
|
||||||
|
pp.createBackBuffer(pp.getWidth(), pp.getHeight(), colors[0]);
|
||||||
|
runtimeCall("jcallback_resize", new int[] {pp.getWidth(), pp.getHeight()});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMenuItemWithKey(JMenu jm, String name, int key) {
|
||||||
|
addMenuItemCallback(jm, name, "jcallback_menu_key_event", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int arg) {
|
||||||
|
return addMenuItemCallback(jm, name, callback, new int[] {arg});
|
||||||
|
}
|
||||||
|
|
||||||
|
private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback) {
|
||||||
|
return addMenuItemCallback(jm, name, callback, new int[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int[] args) {
|
||||||
|
JMenuItem jmi;
|
||||||
|
if (jm == typeMenu)
|
||||||
|
typeMenu.add(jmi = new JCheckBoxMenuItem(name));
|
||||||
|
else
|
||||||
|
jm.add(jmi = new JMenuItem(name));
|
||||||
|
jmi.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
runtimeCall(callback, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return jmi;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runtimeCall(String func, int[] args) {
|
||||||
|
if (runtimeCallWithResult(func, args) == 42 && mainWindow != null) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int runtimeCallWithResult(String func, int[] args) {
|
||||||
|
try {
|
||||||
|
return runtime.call(func, args);
|
||||||
|
} catch (Runtime.CallException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildConfigureMenuItem() {
|
||||||
|
if (typeMenu.isVisible()) {
|
||||||
|
typeMenu.addSeparator();
|
||||||
|
} else {
|
||||||
|
typeMenu.setVisible(true);
|
||||||
|
}
|
||||||
|
addMenuItemCallback(typeMenu, "Custom...", "jcallback_config_event", CFG_SETTINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTypeItem(String name, final int ptrGameParams) {
|
||||||
|
typeMenu.setVisible(true);
|
||||||
|
addMenuItemCallback(typeMenu, name, "jcallback_preset_event", ptrGameParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int call(int cmd, int arg1, int arg2, int arg3) {
|
||||||
|
try {
|
||||||
|
switch(cmd) {
|
||||||
|
case 0: // initialize
|
||||||
|
if (mainWindow != null) mainWindow.setTitle(runtime.cstring(arg1));
|
||||||
|
if ((arg2 & 1) != 0) buildConfigureMenuItem();
|
||||||
|
if ((arg2 & 2) != 0) addStatusBar();
|
||||||
|
if ((arg2 & 4) != 0) solveCommand.setEnabled(true);
|
||||||
|
colors = new Color[arg3];
|
||||||
|
return 0;
|
||||||
|
case 1: // Type menu item
|
||||||
|
addTypeItem(runtime.cstring(arg1), arg2);
|
||||||
|
return 0;
|
||||||
|
case 2: // MessageBox
|
||||||
|
JOptionPane.showMessageDialog(this, runtime.cstring(arg2), runtime.cstring(arg1), arg3 == 0 ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.ERROR_MESSAGE);
|
||||||
|
return 0;
|
||||||
|
case 3: // Resize
|
||||||
|
pp.setPreferredSize(new Dimension(arg1, arg2));
|
||||||
|
if (mainWindow != null) mainWindow.pack();
|
||||||
|
handleResized();
|
||||||
|
if (mainWindow != null) mainWindow.setVisible(true);
|
||||||
|
return 0;
|
||||||
|
case 4: // drawing tasks
|
||||||
|
switch(arg1) {
|
||||||
|
case 0:
|
||||||
|
String text = runtime.cstring(arg2);
|
||||||
|
if (text.equals("")) text = " ";
|
||||||
|
System.out.println("status '" + text + "'");
|
||||||
|
statusBar.setText(text); break;
|
||||||
|
case 1:
|
||||||
|
gg = pp.backBuffer.createGraphics();
|
||||||
|
if (arg2 != 0 || arg3 != 0) {
|
||||||
|
gg.setColor(Color.black);
|
||||||
|
gg.fillRect(0, 0, arg2, getHeight());
|
||||||
|
gg.fillRect(0, 0, getWidth(), arg3);
|
||||||
|
gg.fillRect(getWidth() - arg2, 0, arg2, getHeight());
|
||||||
|
gg.fillRect(0, getHeight() - arg3, getWidth(), arg3);
|
||||||
|
gg.setClip(arg2, arg3, getWidth()-2*arg2, getHeight()-2*arg3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: gg.dispose(); pp.repaint(); break;
|
||||||
|
case 3: gg.setClip(arg2, arg3, xarg1, xarg2); break;
|
||||||
|
case 4:
|
||||||
|
if (arg2 == 0 && arg3 == 0) {
|
||||||
|
gg.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
} else {
|
||||||
|
gg.setClip(arg2, arg3, getWidth()-2*arg2, getHeight()-2*arg3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
gg.setColor(colors[xarg3]);
|
||||||
|
gg.fillRect(arg2, arg3, xarg1, xarg2);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
gg.setColor(colors[xarg3]);
|
||||||
|
gg.drawLine(arg2, arg3, xarg1, xarg2);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
xPoints = new int[arg2];
|
||||||
|
yPoints = new int[arg2];
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if (arg3 != -1) {
|
||||||
|
gg.setColor(colors[arg3]);
|
||||||
|
gg.fillPolygon(xPoints, yPoints, xPoints.length);
|
||||||
|
}
|
||||||
|
gg.setColor(colors[arg2]);
|
||||||
|
gg.drawPolygon(xPoints, yPoints, xPoints.length);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
if (arg3 != -1) {
|
||||||
|
gg.setColor(colors[arg3]);
|
||||||
|
gg.fillOval(xarg1-xarg3, xarg2-xarg3, xarg3*2, xarg3*2);
|
||||||
|
}
|
||||||
|
gg.setColor(colors[arg2]);
|
||||||
|
gg.drawOval(xarg1-xarg3, xarg2-xarg3, xarg3*2, xarg3*2);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
for(int i=0; i<blitters.length; i++) {
|
||||||
|
if (blitters[i] == null) {
|
||||||
|
blitters[i] = new BufferedImage(arg2, arg3, BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("No free blitter found!");
|
||||||
|
case 11: blitters[arg2] = null; break;
|
||||||
|
case 12:
|
||||||
|
timer.start(); break;
|
||||||
|
case 13:
|
||||||
|
timer.stop(); break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 5: // more arguments
|
||||||
|
xarg1 = arg1;
|
||||||
|
xarg2 = arg2;
|
||||||
|
xarg3 = arg3;
|
||||||
|
return 0;
|
||||||
|
case 6: // polygon vertex
|
||||||
|
xPoints[arg1]=arg2;
|
||||||
|
yPoints[arg1]=arg3;
|
||||||
|
return 0;
|
||||||
|
case 7: // string
|
||||||
|
gg.setColor(colors[arg2]);
|
||||||
|
{
|
||||||
|
String text = runtime.cstring(arg3);
|
||||||
|
Font ft = new Font((xarg3 & 0x10) != 0 ? "Monospaced" : "Dialog",
|
||||||
|
Font.PLAIN, 100);
|
||||||
|
int height100 = this.getFontMetrics(ft).getHeight();
|
||||||
|
ft = ft.deriveFont(arg1 * 100 / (float)height100);
|
||||||
|
FontMetrics fm = this.getFontMetrics(ft);
|
||||||
|
int asc = fm.getAscent(), desc = fm.getDescent();
|
||||||
|
if ((xarg3 & ALIGN_VCENTRE) != 0)
|
||||||
|
xarg2 += asc - (asc+desc)/2;
|
||||||
|
else
|
||||||
|
xarg2 += asc;
|
||||||
|
int wid = fm.stringWidth(text);
|
||||||
|
if ((xarg3 & ALIGN_HCENTRE) != 0)
|
||||||
|
xarg1 -= wid / 2;
|
||||||
|
else if ((xarg3 & ALIGN_HRIGHT) != 0)
|
||||||
|
xarg1 -= wid;
|
||||||
|
gg.setFont(ft);
|
||||||
|
gg.drawString(text, xarg1, xarg2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 8: // blitter_save
|
||||||
|
Graphics g2 = blitters[arg1].createGraphics();
|
||||||
|
g2.drawImage(pp.backBuffer, 0, 0, blitters[arg1].getWidth(), blitters[arg1].getHeight(),
|
||||||
|
arg2, arg3, arg2 + blitters[arg1].getWidth(), arg3 + blitters[arg1].getHeight(), this);
|
||||||
|
g2.dispose();
|
||||||
|
return 0;
|
||||||
|
case 9: // blitter_load
|
||||||
|
gg.drawImage(blitters[arg1], arg2, arg3, this);
|
||||||
|
return 0;
|
||||||
|
case 10: // dialog_init
|
||||||
|
dlg= new ConfigDialog(this, runtime.cstring(arg1));
|
||||||
|
return 0;
|
||||||
|
case 11: // dialog_add_control
|
||||||
|
{
|
||||||
|
int sval_ptr = arg1;
|
||||||
|
int ival = arg2;
|
||||||
|
int ptr = xarg1;
|
||||||
|
int type=xarg2;
|
||||||
|
String name = runtime.cstring(xarg3);
|
||||||
|
switch(type) {
|
||||||
|
case C_STRING:
|
||||||
|
dlg.addTextBox(ptr, name, runtime.cstring(sval_ptr));
|
||||||
|
break;
|
||||||
|
case C_BOOLEAN:
|
||||||
|
dlg.addCheckBox(ptr, name, ival != 0);
|
||||||
|
break;
|
||||||
|
case C_CHOICES:
|
||||||
|
dlg.addComboBox(ptr, name, runtime.cstring(sval_ptr), ival);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 12:
|
||||||
|
dlg.finish();
|
||||||
|
dlg = null;
|
||||||
|
return 0;
|
||||||
|
case 13: // tick a menu item
|
||||||
|
if (arg1 < 0) arg1 = typeMenu.getItemCount() - 1;
|
||||||
|
for (int i = 0; i < typeMenu.getItemCount(); i++) {
|
||||||
|
if (typeMenu.getMenuComponent(i) instanceof JCheckBoxMenuItem) {
|
||||||
|
((JCheckBoxMenuItem)typeMenu.getMenuComponent(i)).setSelected(arg1 == i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
if (cmd >= 1024 && cmd < 2048) { // palette
|
||||||
|
colors[cmd-1024] = new Color(arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
if (cmd == 1024) {
|
||||||
|
pp.setBackground(colors[0]);
|
||||||
|
if (statusBar != null) statusBar.setBackground(colors[0]);
|
||||||
|
this.setBackground(colors[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
System.exit(-1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addStatusBar() {
|
||||||
|
statusBar = new JLabel("test");
|
||||||
|
statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED));
|
||||||
|
getContentPane().add(BorderLayout.SOUTH,statusBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standalone runner
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final PuzzleApplet a = new PuzzleApplet();
|
||||||
|
JFrame jf = new JFrame("Loading...");
|
||||||
|
jf.getContentPane().setLayout(new BorderLayout());
|
||||||
|
jf.getContentPane().add(a, BorderLayout.CENTER);
|
||||||
|
a.mainWindow=jf;
|
||||||
|
a.init();
|
||||||
|
a.start();
|
||||||
|
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
jf.addWindowListener(new WindowAdapter() {
|
||||||
|
public void windowClosing(WindowEvent e) {
|
||||||
|
a.stop();
|
||||||
|
a.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jf.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PuzzlePanel extends JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
protected BufferedImage backBuffer;
|
||||||
|
|
||||||
|
public PuzzlePanel() {
|
||||||
|
setPreferredSize(new Dimension(100,100));
|
||||||
|
createBackBuffer(100,100, Color.black);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createBackBuffer(int w, int h, Color bg) {
|
||||||
|
backBuffer = new BufferedImage(w,h, BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
Graphics g = backBuffer.createGraphics();
|
||||||
|
g.setColor(bg);
|
||||||
|
g.fillRect(0, 0, w, h);
|
||||||
|
g.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
g.drawImage(backBuffer, 0, 0, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConfigComponent {
|
||||||
|
public int type;
|
||||||
|
public int configItemPointer;
|
||||||
|
public JComponent component;
|
||||||
|
|
||||||
|
public ConfigComponent(int type, int configItemPointer, JComponent component) {
|
||||||
|
this.type = type;
|
||||||
|
this.configItemPointer = configItemPointer;
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfigDialog extends JDialog {
|
||||||
|
|
||||||
|
private GridBagConstraints gbcLeft = new GridBagConstraints(
|
||||||
|
GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, 1, 1,
|
||||||
|
0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||||
|
new Insets(0, 0, 0, 0), 0, 0);
|
||||||
|
private GridBagConstraints gbcRight = new GridBagConstraints(
|
||||||
|
GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE,
|
||||||
|
GridBagConstraints.REMAINDER, 1, 1.0, 0,
|
||||||
|
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
|
||||||
|
new Insets(5, 5, 5, 5), 0, 0);
|
||||||
|
private GridBagConstraints gbcBottom = new GridBagConstraints(
|
||||||
|
GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE,
|
||||||
|
GridBagConstraints.REMAINDER, GridBagConstraints.REMAINDER,
|
||||||
|
1.0, 1.0, GridBagConstraints.CENTER,
|
||||||
|
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private List components = new ArrayList();
|
||||||
|
|
||||||
|
public ConfigDialog(JApplet parent, String title) {
|
||||||
|
super(JOptionPane.getFrameForComponent(parent), title, true);
|
||||||
|
getContentPane().setLayout(new GridBagLayout());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTextBox(int ptr, String name, String value) {
|
||||||
|
getContentPane().add(new JLabel(name), gbcLeft);
|
||||||
|
JComponent c = new JTextField(value, 25);
|
||||||
|
getContentPane().add(c, gbcRight);
|
||||||
|
components.add(new ConfigComponent(C_STRING, ptr, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addCheckBox(int ptr, String name, boolean selected) {
|
||||||
|
JComponent c = new JCheckBox(name, selected);
|
||||||
|
getContentPane().add(c, gbcRight);
|
||||||
|
components.add(new ConfigComponent(C_BOOLEAN, ptr, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addComboBox(int ptr, String name, String values, int selected) {
|
||||||
|
getContentPane().add(new JLabel(name), gbcLeft);
|
||||||
|
StringTokenizer st = new StringTokenizer(values.substring(1), values.substring(0,1));
|
||||||
|
JComboBox c = new JComboBox();
|
||||||
|
c.setEditable(false);
|
||||||
|
while(st.hasMoreTokens())
|
||||||
|
c.addItem(st.nextToken());
|
||||||
|
c.setSelectedIndex(selected);
|
||||||
|
getContentPane().add(c, gbcRight);
|
||||||
|
components.add(new ConfigComponent(C_CHOICES, ptr, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
JPanel buttons = new JPanel(new GridLayout(1, 2, 5, 5));
|
||||||
|
getContentPane().add(buttons, gbcBottom);
|
||||||
|
JButton b;
|
||||||
|
buttons.add(b=new JButton("OK"));
|
||||||
|
b.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
save();
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getRootPane().setDefaultButton(b);
|
||||||
|
buttons.add(b=new JButton("Cancel"));
|
||||||
|
b.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
|
pack();
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
private void save() {
|
||||||
|
for (int i = 0; i < components.size(); i++) {
|
||||||
|
ConfigComponent cc = (ConfigComponent) components.get(i);
|
||||||
|
switch(cc.type) {
|
||||||
|
case C_STRING:
|
||||||
|
JTextField jtf = (JTextField)cc.component;
|
||||||
|
runtimeCall("jcallback_config_set_string", new int[] {cc.configItemPointer, runtime.strdup(jtf.getText())});
|
||||||
|
break;
|
||||||
|
case C_BOOLEAN:
|
||||||
|
JCheckBox jcb = (JCheckBox)cc.component;
|
||||||
|
runtimeCall("jcallback_config_set_boolean", new int[] {cc.configItemPointer, jcb.isSelected()?1:0});
|
||||||
|
break;
|
||||||
|
case C_CHOICES:
|
||||||
|
JComboBox jcm = (JComboBox)cc.component;
|
||||||
|
runtimeCall("jcallback_config_set_boolean", new int[] {cc.configItemPointer, jcm.getSelectedIndex()});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runtimeCall("jcallback_config_ok", new int[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
Recipe
36
Recipe
@ -13,6 +13,7 @@
|
|||||||
!makefile wce Makefile.wce
|
!makefile wce Makefile.wce
|
||||||
!makefile cygwin Makefile.cyg
|
!makefile cygwin Makefile.cyg
|
||||||
!makefile osx Makefile.osx
|
!makefile osx Makefile.osx
|
||||||
|
!makefile nestedvm Makefile.nestedvm
|
||||||
|
|
||||||
!srcdir icons/
|
!srcdir icons/
|
||||||
|
|
||||||
@ -115,6 +116,18 @@ FORCE:
|
|||||||
fi
|
fi
|
||||||
!end
|
!end
|
||||||
!specialobj gtk version
|
!specialobj gtk version
|
||||||
|
!begin nestedvm
|
||||||
|
version.o: FORCE;
|
||||||
|
FORCE:
|
||||||
|
if test -z "$(VER)" && test -f manifest && md5sum -c manifest; then \
|
||||||
|
$(CC) $(COMPAT) $(XFLAGS) $(CFLAGS) `cat version.def` -c version.c; \
|
||||||
|
elif test -z "$(VER)" && test -d .svn && svnversion . >/dev/null 2>&1; then \
|
||||||
|
$(CC) $(COMPAT) $(XFLAGS) $(CFLAGS) "-DREVISION=`svnversion .`" -c version.c; \
|
||||||
|
else \
|
||||||
|
$(CC) $(COMPAT) $(XFLAGS) $(CFLAGS) $(VER) -c version.c; \
|
||||||
|
fi
|
||||||
|
!end
|
||||||
|
!specialobj nestedvm version
|
||||||
# For OS X, this is made more fiddly by the fact that we don't have
|
# For OS X, this is made more fiddly by the fact that we don't have
|
||||||
# md5sum readily available. We do, however, have `md5 -r' which
|
# md5sum readily available. We do, however, have `md5 -r' which
|
||||||
# generates _nearly_ the same output, but it has no check function.
|
# generates _nearly_ the same output, but it has no check function.
|
||||||
@ -148,3 +161,26 @@ install:
|
|||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
done
|
done
|
||||||
!end
|
!end
|
||||||
|
!begin nestedvm
|
||||||
|
.PRECIOUS: %.class
|
||||||
|
%.class: %.mips
|
||||||
|
java -cp $(NESTEDVM)/build:$(NESTEDVM)/upstream/build/classgen/build \
|
||||||
|
org.ibex.nestedvm.Compiler -outformat class -d . \
|
||||||
|
PuzzleEngine $<
|
||||||
|
mv PuzzleEngine.class $@
|
||||||
|
|
||||||
|
org:
|
||||||
|
mkdir -p org/ibex/nestedvm/util
|
||||||
|
cp $(NESTEDVM)/build/org/ibex/nestedvm/{Registers,UsermodeConstants,Runtime*}.class org/ibex/nestedvm
|
||||||
|
cp $(NESTEDVM)/build/org/ibex/nestedvm/util/{Platform*,Seekable*}.class org/ibex/nestedvm/util
|
||||||
|
echo "Main-Class: PuzzleApplet" >applet.manifest
|
||||||
|
|
||||||
|
PuzzleApplet.class: PuzzleApplet.java org
|
||||||
|
javac -source 1.3 -target 1.3 PuzzleApplet.java
|
||||||
|
|
||||||
|
%.jar: %.class PuzzleApplet.class org
|
||||||
|
mv $< PuzzleEngine.class
|
||||||
|
jar cfm $@ applet.manifest PuzzleEngine.class PuzzleApplet*.class org
|
||||||
|
echo '<applet archive="'$@'" code="PuzzleApplet" width="700" height="500"></applet>' >$*.html
|
||||||
|
mv PuzzleEngine.class $<
|
||||||
|
!end
|
||||||
|
55
mkfiles.pl
55
mkfiles.pl
@ -284,7 +284,7 @@ sub mfval($) {
|
|||||||
# Returns true if the argument is a known makefile type. Otherwise,
|
# Returns true if the argument is a known makefile type. Otherwise,
|
||||||
# prints a warning and returns false;
|
# prints a warning and returns false;
|
||||||
if (grep { $type eq $_ }
|
if (grep { $type eq $_ }
|
||||||
("vc","vcproj","cygwin","borland","lcc","gtk","mpw","osx","wce")) {
|
("vc","vcproj","cygwin","borland","lcc","gtk","mpw","nestedvm","osx","wce")) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
warn "$.:unknown makefile type '$type'\n";
|
warn "$.:unknown makefile type '$type'\n";
|
||||||
@ -1348,6 +1348,59 @@ if (defined $makefiles{'lcc'}) {
|
|||||||
select STDOUT; close OUT;
|
select STDOUT; close OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (defined $makefiles{'nestedvm'}) {
|
||||||
|
$mftyp = 'nestedvm';
|
||||||
|
$dirpfx = &dirpfx($makefiles{'nestedvm'}, "/");
|
||||||
|
|
||||||
|
##-- NestedVM makefile
|
||||||
|
open OUT, ">$makefiles{'nestedvm'}"; select OUT;
|
||||||
|
print
|
||||||
|
"# Makefile for $project_name under NestedVM.\n".
|
||||||
|
"#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
|
||||||
|
"# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
|
||||||
|
# gcc command line option is -D not /D
|
||||||
|
($_ = $help) =~ s/=\/D/=-D/gs;
|
||||||
|
print $_;
|
||||||
|
print
|
||||||
|
"\n".
|
||||||
|
"# This path points at the nestedvm root directory\n".
|
||||||
|
"NESTEDVM = /opt/nestedvm\n".
|
||||||
|
"# You can define this path to point at your tools if you need to\n".
|
||||||
|
"TOOLPATH = \$(NESTEDVM)/upstream/install/bin\n".
|
||||||
|
"CC = \$(TOOLPATH)/mips-unknown-elf-gcc\n".
|
||||||
|
"\n".
|
||||||
|
&splitline("CFLAGS = -O2 -Wall -Werror -DSLOW_SYSTEM -g " .
|
||||||
|
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
||||||
|
"\n";
|
||||||
|
print &splitline("all:" . join "", map { " $_.jar" } &progrealnames("X"));
|
||||||
|
print "\n\n";
|
||||||
|
foreach $p (&prognames("X")) {
|
||||||
|
($prog, $type) = split ",", $p;
|
||||||
|
$objstr = &objects($p, "X.o", undef, undef);
|
||||||
|
$objstr =~ s/gtk\.o/nestedvm\.o/g;
|
||||||
|
print &splitline($prog . ".mips: " . $objstr), "\n";
|
||||||
|
$libstr = &objects($p, undef, undef, "-lX");
|
||||||
|
print &splitline("\t\$(CC)" . $mw . " \$(${type}LDFLAGS) -o \$@ " .
|
||||||
|
$objstr . " $libstr -lm", 69), "\n\n";
|
||||||
|
}
|
||||||
|
foreach $d (&deps("X.o", undef, $dirpfx, "/")) {
|
||||||
|
$oobjs = $d->{obj};
|
||||||
|
$ddeps= join " ", @{$d->{deps}};
|
||||||
|
$oobjs =~ s/gtk/nestedvm/g;
|
||||||
|
$ddeps =~ s/gtk/nestedvm/g;
|
||||||
|
print &splitline(sprintf("%s: %s", $oobjs, $ddeps)),
|
||||||
|
"\n";
|
||||||
|
$deflist = join "", map { " -D$_" } @{$d->{defs}};
|
||||||
|
print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist" .
|
||||||
|
" -c \$< -o \$\@\n";
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
print $makefile_extra{'nestedvm'};
|
||||||
|
print "\nclean:\n".
|
||||||
|
"\trm -rf *.o *.mips *.class *.html *.jar org applet.manifest\n";
|
||||||
|
select STDOUT; close OUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (defined $makefiles{'osx'}) {
|
if (defined $makefiles{'osx'}) {
|
||||||
$mftyp = 'osx';
|
$mftyp = 'osx';
|
||||||
$dirpfx = &dirpfx($makefiles{'osx'}, "/");
|
$dirpfx = &dirpfx($makefiles{'osx'}, "/");
|
||||||
|
416
nestedvm.c
Normal file
416
nestedvm.c
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
/*
|
||||||
|
* nestedvm.c: NestedVM front end for my puzzle collection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "puzzles.h"
|
||||||
|
|
||||||
|
extern void _pause();
|
||||||
|
extern int _call_java(int cmd, int arg1, int arg2, int arg3);
|
||||||
|
|
||||||
|
void fatal(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
fprintf(stderr, "fatal error: ");
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct frontend {
|
||||||
|
// TODO kill unneeded members!
|
||||||
|
midend *me;
|
||||||
|
int timer_active;
|
||||||
|
struct timeval last_time;
|
||||||
|
config_item *cfg;
|
||||||
|
int cfg_which, cfgret;
|
||||||
|
int ox, oy;
|
||||||
|
};
|
||||||
|
|
||||||
|
static frontend *_fe;
|
||||||
|
|
||||||
|
void get_random_seed(void **randseed, int *randseedsize)
|
||||||
|
{
|
||||||
|
struct timeval *tvp = snew(struct timeval);
|
||||||
|
gettimeofday(tvp, NULL);
|
||||||
|
*randseed = (void *)tvp;
|
||||||
|
*randseedsize = sizeof(struct timeval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void frontend_default_colour(frontend *fe, float *output)
|
||||||
|
{
|
||||||
|
output[0] = output[1]= output[2] = 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_status_bar(void *handle, char *text)
|
||||||
|
{
|
||||||
|
_call_java(4,0,(int)text,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_start_draw(void *handle)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(4, 1, fe->ox, fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_clip(void *handle, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(5, w, h, 0);
|
||||||
|
_call_java(4, 3, x + fe->ox, y + fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_unclip(void *handle)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(4, 4, fe->ox, fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_draw_text(void *handle, int x, int y, int fonttype, int fontsize,
|
||||||
|
int align, int colour, char *text)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(5, x + fe->ox, y + fe->oy,
|
||||||
|
(fonttype == FONT_FIXED ? 0x10 : 0x0) | align);
|
||||||
|
_call_java(7, fontsize, colour, (int)text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(5, w, h, colour);
|
||||||
|
_call_java(4, 5, x + fe->ox, y + fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
||||||
|
int colour)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(5, x2 + fe->ox, y2 + fe->oy, colour);
|
||||||
|
_call_java(4, 6, x1 + fe->ox, y1 + fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_draw_poly(void *handle, int *coords, int npoints,
|
||||||
|
int fillcolour, int outlinecolour)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
int i;
|
||||||
|
_call_java(4, 7, npoints, 0);
|
||||||
|
for (i = 0; i < npoints; i++) {
|
||||||
|
_call_java(6, i, coords[i*2] + fe->ox, coords[i*2+1] + fe->oy);
|
||||||
|
}
|
||||||
|
_call_java(4, 8, outlinecolour, fillcolour);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_draw_circle(void *handle, int cx, int cy, int radius,
|
||||||
|
int fillcolour, int outlinecolour)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
_call_java(5, cx+fe->ox, cy+fe->oy, radius);
|
||||||
|
_call_java(4, 9, outlinecolour, fillcolour);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct blitter {
|
||||||
|
int handle, w, h, x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
blitter *nestedvm_blitter_new(void *handle, int w, int h)
|
||||||
|
{
|
||||||
|
blitter *bl = snew(blitter);
|
||||||
|
bl->handle = -1;
|
||||||
|
bl->w = w;
|
||||||
|
bl->h = h;
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_blitter_free(void *handle, blitter *bl)
|
||||||
|
{
|
||||||
|
if (bl->handle != -1)
|
||||||
|
_call_java(4, 11, bl->handle, 0);
|
||||||
|
sfree(bl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_blitter_save(void *handle, blitter *bl, int x, int y)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
if (bl->handle == -1)
|
||||||
|
bl->handle = _call_java(4,10,bl->w, bl->h);
|
||||||
|
bl->x = x;
|
||||||
|
bl->y = y;
|
||||||
|
_call_java(8, bl->handle, x + fe->ox, y + fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_blitter_load(void *handle, blitter *bl, int x, int y)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)handle;
|
||||||
|
assert(bl->handle != -1);
|
||||||
|
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
||||||
|
x = bl->x;
|
||||||
|
y = bl->y;
|
||||||
|
}
|
||||||
|
_call_java(9, bl->handle, x + fe->ox, y + fe->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nestedvm_end_draw(void *handle)
|
||||||
|
{
|
||||||
|
_call_java(4,2,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct drawing_api nestedvm_drawing = {
|
||||||
|
nestedvm_draw_text,
|
||||||
|
nestedvm_draw_rect,
|
||||||
|
nestedvm_draw_line,
|
||||||
|
nestedvm_draw_poly,
|
||||||
|
nestedvm_draw_circle,
|
||||||
|
NULL, // draw_update,
|
||||||
|
nestedvm_clip,
|
||||||
|
nestedvm_unclip,
|
||||||
|
nestedvm_start_draw,
|
||||||
|
nestedvm_end_draw,
|
||||||
|
nestedvm_status_bar,
|
||||||
|
nestedvm_blitter_new,
|
||||||
|
nestedvm_blitter_free,
|
||||||
|
nestedvm_blitter_save,
|
||||||
|
nestedvm_blitter_load,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, /* {begin,end}_{doc,page,puzzle} */
|
||||||
|
NULL, /* line_width */
|
||||||
|
};
|
||||||
|
|
||||||
|
int jcallback_key_event(int x, int y, int keyval)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
if (fe->ox == -1)
|
||||||
|
return 1;
|
||||||
|
if (keyval >= 0 &&
|
||||||
|
!midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval))
|
||||||
|
return 42;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_resize(int width, int height)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
int x, y;
|
||||||
|
x = width;
|
||||||
|
y = height;
|
||||||
|
midend_size(fe->me, &x, &y, TRUE);
|
||||||
|
fe->ox = (width - x) / 2;
|
||||||
|
fe->oy = (height - y) / 2;
|
||||||
|
midend_force_redraw(fe->me);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_timer_func()
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
if (fe->timer_active) {
|
||||||
|
struct timeval now;
|
||||||
|
float elapsed;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
elapsed = ((now.tv_usec - fe->last_time.tv_usec) * 0.000001F +
|
||||||
|
(now.tv_sec - fe->last_time.tv_sec));
|
||||||
|
midend_timer(fe->me, elapsed); /* may clear timer_active */
|
||||||
|
fe->last_time = now;
|
||||||
|
}
|
||||||
|
return fe->timer_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deactivate_timer(frontend *fe)
|
||||||
|
{
|
||||||
|
if (fe->timer_active)
|
||||||
|
_call_java(4, 13, 0, 0);
|
||||||
|
fe->timer_active = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate_timer(frontend *fe)
|
||||||
|
{
|
||||||
|
if (!fe->timer_active) {
|
||||||
|
_call_java(4, 12, 0, 0);
|
||||||
|
gettimeofday(&fe->last_time, NULL);
|
||||||
|
}
|
||||||
|
fe->timer_active = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jcallback_config_ok()
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
err = midend_set_config(fe->me, fe->cfg_which, fe->cfg);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
_call_java(2, (int) "Error", (int)err, 1);
|
||||||
|
else {
|
||||||
|
fe->cfgret = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jcallback_config_set_string(int item_ptr, int char_ptr) {
|
||||||
|
config_item *i = (config_item *)item_ptr;
|
||||||
|
char* newval = (char*) char_ptr;
|
||||||
|
sfree(i->sval);
|
||||||
|
i->sval = dupstr(newval);
|
||||||
|
free(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jcallback_config_set_boolean(int item_ptr, int selected) {
|
||||||
|
config_item *i = (config_item *)item_ptr;
|
||||||
|
i->ival = selected != 0 ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jcallback_config_set_choice(int item_ptr, int selected) {
|
||||||
|
config_item *i = (config_item *)item_ptr;
|
||||||
|
i->ival = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_config(frontend *fe, int which)
|
||||||
|
{
|
||||||
|
char *title;
|
||||||
|
config_item *i;
|
||||||
|
fe->cfg = midend_get_config(fe->me, which, &title);
|
||||||
|
fe->cfg_which = which;
|
||||||
|
fe->cfgret = FALSE;
|
||||||
|
_call_java(10, (int)title, 0, 0);
|
||||||
|
for (i = fe->cfg; i->type != C_END; i++) {
|
||||||
|
_call_java(5, (int)i, i->type, (int)i->name);
|
||||||
|
_call_java(11, (int)i->sval, i->ival, 0);
|
||||||
|
}
|
||||||
|
_call_java(12,0,0,0);
|
||||||
|
free_cfg(fe->cfg);
|
||||||
|
return fe->cfgret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_menu_key_event(int key)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
if (!midend_process_key(fe->me, 0, 0, key))
|
||||||
|
return 42;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resize_fe(frontend *fe)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
x = INT_MAX;
|
||||||
|
y = INT_MAX;
|
||||||
|
midend_size(fe->me, &x, &y, FALSE);
|
||||||
|
_call_java(3, x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_preset_event(int ptr_game_params)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
game_params *params =
|
||||||
|
(game_params *)ptr_game_params;
|
||||||
|
|
||||||
|
midend_set_params(fe->me, params);
|
||||||
|
midend_new_game(fe->me);
|
||||||
|
resize_fe(fe);
|
||||||
|
_call_java(13, midend_which_preset(fe->me), 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_solve_event()
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
char *msg;
|
||||||
|
|
||||||
|
msg = midend_solve(fe->me);
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
_call_java(2, (int) "Error", (int)msg, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_restart_event()
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
|
||||||
|
midend_restart_game(fe->me);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_config_event(int which)
|
||||||
|
{
|
||||||
|
frontend *fe = (frontend *)_fe;
|
||||||
|
_call_java(13, midend_which_preset(fe->me), 0, 0);
|
||||||
|
if (!get_config(fe, which))
|
||||||
|
return 0;
|
||||||
|
midend_new_game(fe->me);
|
||||||
|
resize_fe(fe);
|
||||||
|
_call_java(13, midend_which_preset(fe->me), 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jcallback_about_event()
|
||||||
|
{
|
||||||
|
char titlebuf[256];
|
||||||
|
char textbuf[1024];
|
||||||
|
|
||||||
|
sprintf(titlebuf, "About %.200s", thegame.name);
|
||||||
|
sprintf(textbuf,
|
||||||
|
"%.200s\n\n"
|
||||||
|
"from Simon Tatham's Portable Puzzle Collection\n\n"
|
||||||
|
"%.500s", thegame.name, ver);
|
||||||
|
_call_java(2, (int)&titlebuf, (int)&textbuf, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
float* colours;
|
||||||
|
|
||||||
|
_fe = snew(frontend);
|
||||||
|
_fe->timer_active = FALSE;
|
||||||
|
_fe->me = midend_new(_fe, &thegame, &nestedvm_drawing, _fe);
|
||||||
|
midend_new_game(_fe->me);
|
||||||
|
|
||||||
|
if ((n = midend_num_presets(_fe->me)) > 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
char *name;
|
||||||
|
game_params *params;
|
||||||
|
midend_fetch_preset(_fe->me, i, &name, ¶ms);
|
||||||
|
_call_java(1, (int)name, (int)params, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
colours = midend_colours(_fe->me, &n);
|
||||||
|
_fe->ox = -1;
|
||||||
|
|
||||||
|
_call_java(0, (int)thegame.name,
|
||||||
|
(thegame.can_configure ? 1 : 0) |
|
||||||
|
(midend_wants_statusbar(_fe->me) ? 2 : 0) |
|
||||||
|
(thegame.can_solve ? 4 : 0), n);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
_call_java(1024+ i,
|
||||||
|
(int)(colours[i*3] * 0xFF),
|
||||||
|
(int)(colours[i*3+1] * 0xFF),
|
||||||
|
(int)(colours[i*3+2] * 0xFF));
|
||||||
|
}
|
||||||
|
resize_fe(_fe);
|
||||||
|
|
||||||
|
_call_java(13, midend_which_preset(_fe->me), 0, 0);
|
||||||
|
|
||||||
|
// Now pause the vm. The VM will be call()ed when
|
||||||
|
// an input event occurs.
|
||||||
|
_pause();
|
||||||
|
|
||||||
|
// shut down when the VM is resumed.
|
||||||
|
deactivate_timer(_fe);
|
||||||
|
midend_free(_fe->me);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
#include <X11/Intrinsic.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dummy source file which replaces the files generated in the
|
* Dummy source file which replaces the files generated in the
|
||||||
|
@ -2271,8 +2271,8 @@ grid, through the \q{Type} menu.
|
|||||||
|
|
||||||
This software is \i{copyright} 2004-2008 Simon Tatham.
|
This software is \i{copyright} 2004-2008 Simon Tatham.
|
||||||
|
|
||||||
Portions copyright Richard Boulton, James Harvey, Mike Pinna and
|
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
|
||||||
Jonas K\u00F6{oe}lker.
|
K\u00F6{oe}lker, Dariusz Olszewski and Michael Schierl.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation files
|
obtaining a copy of this software and associated documentation files
|
||||||
|
Reference in New Issue
Block a user