MegaDrive3ButtonPad.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50: package xeij;
51:
52: import java.awt.*;
53: import java.awt.event.*;
54: import java.util.*;
55: import javax.swing.*;
56: import javax.swing.event.*;
57:
58:
59:
60: public class MegaDrive3ButtonPad extends Joystick implements ActionListener, ChangeListener, FocusListener, XInput.GamepadListener, KeyListener {
61:
62: protected static final int UP_BIT = 0;
63: protected static final int DOWN_BIT = 1;
64: protected static final int LEFT_BIT = 2;
65: protected static final int RIGHT_BIT = 3;
66: protected static final int A_BIT = 4;
67: protected static final int B_BIT = 5;
68: protected static final int C_BIT = 6;
69: protected static final int START_BIT = 7;
70: protected static final int BUTTONS = 8;
71:
72: protected static final int UP_MASK = (1 << UP_BIT);
73: protected static final int DOWN_MASK = (1 << DOWN_BIT);
74: protected static final int LEFT_MASK = (1 << LEFT_BIT);
75: protected static final int RIGHT_MASK = (1 << RIGHT_BIT);
76: protected static final int A_MASK = (1 << A_BIT);
77: protected static final int B_MASK = (1 << B_BIT);
78: protected static final int C_MASK = (1 << C_BIT);
79: protected static final int START_MASK = (1 << START_BIT);
80:
81: protected static final String[] BIT_TO_TEXT = {
82: "↑",
83: "↓",
84: "←",
85: "→",
86: "A",
87: "B",
88: "C",
89: "START",
90: };
91:
92: protected static final boolean[] BIT_TO_REPEATABLE = {
93: false,
94: false,
95: false,
96: false,
97: true,
98: true,
99: true,
100: false,
101: };
102:
103: protected static final int MAP_CODE = BUTTONS * 0;
104: protected static final int MAP_REPEAT = BUTTONS * 1;
105: protected static final int MAP_DELAY = BUTTONS * 2;
106: protected static final int MAP_INTERVAL = BUTTONS * 3;
107: protected static final int MAP_LENGTH = BUTTONS * 4;
108: protected int[] map;
109:
110: protected int xinputFocusedButton;
111: protected long[] startTimeOf;
112: protected int lastButtons;
113: protected int keyButtons;
114:
115: protected int page;
116:
117: protected JTextField[] xinputTextFieldOf = new JTextField[BUTTONS];
118: protected JTextField[] keyTextFieldOf = new JTextField[BUTTONS];
119: protected JCheckBox[] repeatCheckBoxOf = new JCheckBox[BUTTONS];
120: protected SpinnerNumberModel[] delayModelOf = new SpinnerNumberModel[BUTTONS];
121: protected JSpinner[] delaySpinnerOf = new JSpinner[BUTTONS];
122: protected SpinnerNumberModel[] intervalModelOf = new SpinnerNumberModel[BUTTONS];
123: protected JSpinner[] intervalSpinnerOf = new JSpinner[BUTTONS];
124:
125:
126:
127:
128:
129:
130:
131: protected final int[][] defaultMaps = new int[][] {
132: {
133: (128 | 0 << 5 | XInput.UP_BIT ) << 16 | KeyEvent.VK_UP,
134: (128 | 0 << 5 | XInput.DOWN_BIT ) << 16 | KeyEvent.VK_DOWN,
135: (128 | 0 << 5 | XInput.LEFT_BIT ) << 16 | KeyEvent.VK_LEFT,
136: (128 | 0 << 5 | XInput.RIGHT_BIT ) << 16 | KeyEvent.VK_RIGHT,
137: (128 | 0 << 5 | XInput.A_BIT ) << 16 | KeyEvent.VK_Z,
138: (128 | 0 << 5 | XInput.B_BIT ) << 16 | KeyEvent.VK_X,
139: (128 | 0 << 5 | XInput.LB_BIT ) << 16 | KeyEvent.VK_C,
140: (128 | 0 << 5 | XInput.START_BIT ) << 16 | KeyEvent.VK_R,
141: 0, 0, 0, 0, 0, 0, 0, 0,
142: 0, 0, 0, 0, 50, 50 , 50, 0,
143: 0, 0, 0, 0, 100, 100, 100, 0,
144: },
145: {
146: (128 | 1 << 5 | XInput.UP_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
147: (128 | 1 << 5 | XInput.DOWN_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
148: (128 | 1 << 5 | XInput.LEFT_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
149: (128 | 1 << 5 | XInput.RIGHT_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
150: (128 | 1 << 5 | XInput.A_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
151: (128 | 1 << 5 | XInput.B_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
152: (128 | 1 << 5 | XInput.LB_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
153: (128 | 1 << 5 | XInput.START_BIT ) << 16 | KeyEvent.VK_UNDEFINED,
154: 0, 0, 0, 0, 0, 0, 0, 0,
155: 0, 0, 0, 0, 50, 50 , 50, 0,
156: 0, 0, 0, 0, 100, 100, 100, 0,
157: },
158: };
159:
160:
161:
162:
163: public MegaDrive3ButtonPad (int number) {
164: this.number = number;
165: id = "megadrive3button" + number;
166: nameEn = "MEGA DRIVE 3 button pad #" + number;
167: nameJa = "メガドラ 3 ボタンパッド #" + number;
168: map = new int[MAP_LENGTH];
169: int[] tempMap = Settings.sgsGetIntArray (id);
170: if (0 < tempMap.length && 0 <= tempMap[0]) {
171: for (int i = 0; i < MAP_LENGTH; i++) {
172: map[i] = i < tempMap.length ? tempMap[i] : 0;
173: }
174:
175: for (int i = 0; i < BUTTONS; i++) {
176: map[MAP_INTERVAL + i] = Math.min (INTERVAL_MAX, map[MAP_INTERVAL + i] << 1);
177: }
178: } else if (0 < tempMap.length && tempMap[0] == -2) {
179: for (int i = 0; i < MAP_LENGTH; i++) {
180: map[i] = i + 1 < tempMap.length ? tempMap[i + 1] : 0;
181: }
182: } else {
183: System.arraycopy (defaultMaps[number - 1], 0,
184: map, 0,
185: MAP_LENGTH);
186: }
187: if (PPI.PPI_XINPUT_ON) {
188: xinputFocusedButton = -1;
189: }
190: startTimeOf = new long[BUTTONS];
191: reset ();
192: configurationPanel = null;
193: }
194:
195:
196:
197: @Override public void tini () {
198: if (true &&
199: Arrays.equals (map, defaultMaps[number - 1])) {
200: Settings.sgsPutIntArray (id, new int[0]);
201: } else {
202: int[] tempMap = new int[1 + MAP_LENGTH];
203: tempMap[0] = -2;
204: for (int i = 0; i < MAP_LENGTH; i++) {
205: tempMap[1 + i] = map[i];
206: }
207: Settings.sgsPutIntArray (id, tempMap);
208: }
209: }
210:
211:
212:
213: @Override public final void reset () {
214: lastButtons = 0;
215: keyButtons = 0;
216: page = 0;
217: }
218:
219: private void updateText () {
220: for (int i = 0; i < BUTTONS; i++) {
221: String text;
222: int xCode = map[MAP_CODE + i] >>> 16;
223: if (xCode == 0) {
224: text = Multilingual.mlnJapanese ? "なし" : "none";
225: } else {
226: int xIndex = (xCode >> 5) & 3;
227: int xBit = xCode & 31;
228: text = "#" + xIndex + " " + XInput.BIT_TO_TEXT[xBit];
229: }
230: xinputTextFieldOf[i].setText (text);
231: int keyCode = map[MAP_CODE + i] & 65535;
232: if (keyCode == 0) {
233: text = Multilingual.mlnJapanese ? "なし" : "none";
234: } else {
235: text = KeyEvent.getKeyText (keyCode);
236: }
237: keyTextFieldOf[i].setText (text);
238: }
239: }
240:
241:
242:
243: @Override public void actionPerformed (ActionEvent ae) {
244: Object source = ae.getSource ();
245: String command = ae.getActionCommand ();
246: if (command.equals ("Reset to default values")) {
247: if (Arrays.equals (map, defaultMaps[number - 1])) {
248: JOptionPane.showMessageDialog (
249: null,
250: Multilingual.mlnJapanese ? nameJa + " の設定は初期値と同じです" : nameEn + " settings are equals to default values",
251: Multilingual.mlnJapanese ? "確認" : "Confirmation",
252: JOptionPane.PLAIN_MESSAGE);
253: return;
254: }
255: if (JOptionPane.showConfirmDialog (
256: null,
257: Multilingual.mlnJapanese ? nameJa + " の設定を初期値に戻しますか?" : "Do you want to reset " + nameEn + " settings to default values?",
258: Multilingual.mlnJapanese ? "確認" : "Confirmation",
259: JOptionPane.YES_NO_OPTION,
260: JOptionPane.PLAIN_MESSAGE) != JOptionPane.YES_OPTION) {
261: return;
262: }
263: System.arraycopy (defaultMaps[number - 1], 0,
264: map, 0,
265: MAP_LENGTH);
266: updateText ();
267: for (int i = 0; i < BUTTONS; i++) {
268: if (BIT_TO_REPEATABLE[i]) {
269: repeatCheckBoxOf[i].setSelected (map[MAP_REPEAT + i] != 0);
270: delayModelOf[i].setValue (Math.max (DELAY_MIN, Math.min (DELAY_MAX, map[MAP_DELAY + i])));
271: intervalModelOf[i].setValue (Math.max (INTERVAL_MIN, Math.min (INTERVAL_MAX, map[MAP_INTERVAL + i])));
272: }
273: }
274: } else if (command.startsWith ("Repeat ")) {
275: int i = Integer.parseInt (command.substring (7));
276: map[MAP_REPEAT + i] = repeatCheckBoxOf[i].isSelected () ? 1 : 0;
277: } else {
278: System.out.println ("unknown action command " + command);
279: }
280: }
281:
282:
283:
284: @Override public void stateChanged (ChangeEvent ce) {
285: JSpinner spinner = (JSpinner) ce.getSource ();
286: String name = spinner.getName ();
287: if (name.startsWith ("Delay ")) {
288: int i = Integer.parseInt (name.substring (6));
289: map[MAP_DELAY + i] = delayModelOf[i].getNumber ().intValue ();
290: } else if (name.startsWith ("Interval ")) {
291: int i = Integer.parseInt (name.substring (9));
292: map[MAP_INTERVAL + i] = intervalModelOf[i].getNumber ().intValue ();
293: } else {
294: System.out.println ("unknown spinner name " + name);
295: }
296: }
297:
298:
299:
300: @Override public void focusGained (FocusEvent fe) {
301: Component component = fe.getComponent ();
302: String componentName = component.getName ();
303: int type = componentName.charAt (0);
304: int i = Integer.parseInt (componentName.substring (1));
305:
306: component.setBackground (new Color (LnF.lnfRGB[6]));
307: if (PPI.PPI_XINPUT_ON && type == 'x') {
308:
309: xinputFocusedButton = i;
310: if (PPI.ppiXInput != null) {
311: PPI.ppiXInput.addGamepadListener (this);
312: }
313: } else if (type == 'k') {
314: } else {
315: System.out.println ("unknown component name " + componentName);
316: }
317: }
318: @Override public void focusLost (FocusEvent fe) {
319: Component component = fe.getComponent ();
320: String componentName = component.getName ();
321: int type = componentName.charAt (0);
322: int i = Integer.parseInt (componentName.substring (1));
323:
324: component.setBackground (null);
325: if (PPI.PPI_XINPUT_ON && type == 'x') {
326:
327: if (PPI.ppiXInput != null) {
328: PPI.ppiXInput.removeGamepadListeners ();
329: }
330: xinputFocusedButton = -1;
331: } else if (type == 'k') {
332: } else {
333: System.out.println ("unknown component name " + componentName);
334: }
335: }
336:
337:
338:
339: @Override public void connected (XInput.Gamepad gamepad) {
340: }
341: @Override public void disconnected (XInput.Gamepad gamepad) {
342: }
343: @Override public void buttonPressed (XInput.Gamepad gamepad, int buttonMasks) {
344: if (buttonMasks == 0) {
345: return;
346: }
347: if (PPI.PPI_XINPUT_ON && 0 <= xinputFocusedButton) {
348: int xIndex = gamepad.getIndex ();
349: int xBit = Integer.numberOfTrailingZeros (buttonMasks);
350: int xCode = 128 | xIndex << 5 | xBit;
351: int keyCode = map[MAP_CODE + xinputFocusedButton] & 65535;
352: map[MAP_CODE + xinputFocusedButton] = xCode << 16 | keyCode;
353:
354:
355: for (int i = 0; i < BUTTONS; i++) {
356: int xCode2 = map[MAP_CODE + i] >>> 16;
357: if (xCode2 != 0) {
358: int keyCode2 = map[MAP_CODE + i] & 65535;
359: map[MAP_CODE + i] = ((xCode2 & ~(3 << 5)) | xIndex << 5) << 16 | keyCode2;
360: }
361: }
362: updateText ();
363: }
364: }
365: @Override public void buttonReleased (XInput.Gamepad gamepad, int buttonMasks) {
366: }
367: @Override public void leftStickMovedX (XInput.Gamepad gamepad) {
368: }
369: @Override public void leftStickMovedY (XInput.Gamepad gamepad) {
370: }
371: @Override public void leftTriggerMoved (XInput.Gamepad gamepad) {
372: }
373: @Override public void rightStickMovedX (XInput.Gamepad gamepad) {
374: }
375: @Override public void rightStickMovedY (XInput.Gamepad gamepad) {
376: }
377: @Override public void rightTriggerMoved (XInput.Gamepad gamepad) {
378: }
379:
380:
381:
382: @Override public void keyPressed (KeyEvent ke) {
383: Component component = ke.getComponent ();
384: String componentName = component.getName ();
385: int type = componentName.charAt (0);
386: int i = Integer.parseInt (componentName.substring (1));
387: int xCode = map[MAP_CODE + i] >>> 16;
388: int keyCode = map[MAP_CODE + i] & 65535;
389: if (PPI.PPI_XINPUT_ON && type == 'x') {
390: if (ke.getKeyCode () == KeyEvent.VK_ESCAPE) {
391: xCode = 0;
392: }
393: } else if (type == 'k') {
394: if (ke.getKeyCode () == KeyEvent.VK_ESCAPE) {
395: keyCode = KeyEvent.VK_UNDEFINED;
396: } else {
397: keyCode = ke.getKeyCode ();
398: }
399: } else {
400: System.out.println ("unknown component name " + componentName);
401: }
402: map[MAP_CODE + i] = xCode << 16 | keyCode;
403: updateText ();
404: ke.consume ();
405: }
406: @Override public void keyReleased (KeyEvent ke) {
407: ke.consume ();
408: }
409: @Override public void keyTyped (KeyEvent ke) {
410: ke.consume ();
411: }
412:
413:
414:
415:
416: @Override public JComponent getConfigurationPanel () {
417:
418: if (configurationPanel != null) {
419: return configurationPanel;
420: }
421:
422: for (int i = 0; i < BUTTONS; i++) {
423: xinputTextFieldOf[i] =
424: ComponentFactory.setEnabled (
425: ComponentFactory.addListener (
426: ComponentFactory.addListener (
427: ComponentFactory.setHorizontalAlignment (
428: ComponentFactory.setName (
429: ComponentFactory.createTextField ("", 8),
430: "x" + i),
431: JTextField.CENTER),
432: (KeyListener) this),
433: (FocusListener) this),
434: PPI.PPI_XINPUT_ON && XEiJ.prgWindllLoaded);
435: keyTextFieldOf[i] =
436: ComponentFactory.addListener (
437: ComponentFactory.addListener (
438: ComponentFactory.setHorizontalAlignment (
439: ComponentFactory.setName (
440: ComponentFactory.createTextField ("", 8),
441: "k" + i),
442: JTextField.CENTER),
443: (KeyListener) this),
444: (FocusListener) this);
445: if (BIT_TO_REPEATABLE[i]) {
446: repeatCheckBoxOf[i] =
447: ComponentFactory.setText (
448: ComponentFactory.createCheckBox (map[MAP_REPEAT + i] != 0, "Repeat " + i, (ActionListener) this),
449: "");
450: delayModelOf[i] =
451: new SpinnerNumberModel (Math.max (DELAY_MIN, Math.min (DELAY_MAX, map[MAP_DELAY + i])),
452: DELAY_MIN, DELAY_MAX, DELAY_STEP);
453: delaySpinnerOf[i] =
454: ComponentFactory.setName (
455: ComponentFactory.createNumberSpinner (delayModelOf[i], 4, (ChangeListener) this),
456: "Delay " + i);
457: intervalModelOf[i] =
458: new SpinnerNumberModel (Math.max (INTERVAL_MIN, Math.min (INTERVAL_MAX, map[MAP_INTERVAL + i])),
459: INTERVAL_MIN, INTERVAL_MAX, INTERVAL_STEP);
460: intervalSpinnerOf[i] =
461: ComponentFactory.setName (
462: ComponentFactory.createNumberSpinner (intervalModelOf[i], 4, (ChangeListener) this),
463: "Interval " + i);
464: }
465: }
466: updateText ();
467:
468:
469:
470:
471:
472: ArrayList<Object> cellList = new ArrayList<Object> ();
473:
474: cellList.add (null);
475: cellList.add (Multilingual.mlnText (ComponentFactory.createLabel ("Button"), "ja", "ボタン"));
476: cellList.add (ComponentFactory.createLabel ("XInput"));
477: cellList.add (Multilingual.mlnText (ComponentFactory.createLabel ("Keyboard"), "ja", "キーボード"));
478: cellList.add (Multilingual.mlnText (ComponentFactory.createLabel ("Burst"), "ja", "連射"));
479: cellList.add (Multilingual.mlnText (ComponentFactory.createLabel ("Delay (ms)"), "ja", "開始 (ms)"));
480: cellList.add (Multilingual.mlnText (ComponentFactory.createLabel ("Interval (ms)"), "ja", "間隔 (ms)"));
481:
482: cellList.add (ComponentFactory.createHorizontalSeparator ());
483:
484: for (int i = 0; i < BUTTONS; i++) {
485: cellList.add (String.valueOf (1 + i));
486: cellList.add (BIT_TO_TEXT[i]);
487: cellList.add (xinputTextFieldOf[i]);
488: cellList.add (keyTextFieldOf[i]);
489: cellList.add (BIT_TO_REPEATABLE[i] ? repeatCheckBoxOf[i] : null);
490: cellList.add (BIT_TO_REPEATABLE[i] ? delaySpinnerOf[i] : null);
491: cellList.add (BIT_TO_REPEATABLE[i] ? intervalSpinnerOf[i] : null);
492: }
493:
494: configurationPanel =
495: ComponentFactory.createVerticalBox (
496: Box.createVerticalStrut (5),
497: ComponentFactory.createHorizontalBox (
498: Box.createHorizontalGlue (),
499: Multilingual.mlnText (ComponentFactory.createLabel (getNameEn ()), "ja", getNameJa ()),
500: Box.createHorizontalGlue ()),
501: Box.createVerticalStrut (5),
502: ComponentFactory.createHorizontalBox (
503: ComponentFactory.createGridPanel (
504: 7,
505: 2 + BUTTONS,
506: "paddingLeft=3,paddingRight=3,center",
507: "",
508: "italic;colSpan=7,widen",
509: "",
510: cellList.toArray (new Object[0]))),
511: Box.createVerticalStrut (5),
512: ComponentFactory.createHorizontalBox (
513: Box.createHorizontalGlue (),
514: Multilingual.mlnText (ComponentFactory.createButton ("Reset to default values", (ActionListener) this), "ja", "初期値に戻す"),
515: Box.createHorizontalGlue ()),
516: Box.createVerticalStrut (5));
517:
518: return configurationPanel;
519: }
520:
521:
522:
523:
524:
525:
526: @Override public boolean input (KeyEvent ke, boolean pressed) {
527: int keyCode = ke.getKeyCode ();
528:
529: for (int i = 0; i < BUTTONS; i++) {
530: if (keyCode == (map[MAP_CODE + i] & 65535)) {
531: if (pressed) {
532: keyButtons |= 1 << i;
533: } else {
534: keyButtons &= ~(1 << i);
535: }
536: return true;
537: }
538: }
539: return false;
540: }
541:
542:
543:
544:
545:
546: @Override public void setPin8 (int pin8) {
547: page = pin8;
548: }
549:
550:
551:
552:
553:
554: @Override public int readByte () {
555:
556: int currentButtons = keyButtons;
557: int lastIndex = -1;
558: int lastMasks = 0;
559: for (int i = 0; i < BUTTONS; i++) {
560: int xCode = map[MAP_CODE + i] >>> 16;
561: if (xCode != 0) {
562: int xIndex = (xCode >> 5) & 3;
563: int xBit = xCode & 31;
564: if (lastIndex != xIndex) {
565: lastIndex = xIndex;
566: lastMasks = PPI.ppiXInput == null ? 0 : PPI.ppiXInput.getButtonMasks (lastIndex);
567: }
568: if ((lastMasks & (1 << xBit)) != 0) {
569: currentButtons |= 1 << i;
570: }
571: }
572: }
573: int pressedButtons = ~lastButtons & currentButtons;
574: lastButtons = currentButtons;
575: int outputButtons = 0;
576: for (int i = 0; i < BUTTONS; i++) {
577: if ((pressedButtons & (1 << i)) != 0 &&
578: map[MAP_REPEAT + i] != 0) {
579: startTimeOf[i] = XEiJ.mpuClockTime + map[MAP_DELAY + i] * (XEiJ.TMR_FREQ / 1000);
580: }
581: if ((currentButtons & (1 << i)) != 0 &&
582: (map[MAP_REPEAT + i] == 0 ||
583: XEiJ.mpuClockTime < startTimeOf[i] ||
584: ((int) ((XEiJ.mpuClockTime - startTimeOf[i]) /
585: ((map[MAP_INTERVAL + i] >> 1) * (XEiJ.TMR_FREQ / 1000)))
586: & 1) != 0)) {
587: outputButtons |= 1 << i;
588: }
589: }
590:
591: return (page == 0 ?
592: 0b11110011 &
593: ((outputButtons & (UP_MASK | DOWN_MASK)) == UP_MASK ? ~0b00000001 : -1) &
594: ((outputButtons & (DOWN_MASK | UP_MASK)) == DOWN_MASK ? ~0b00000010 : -1) &
595: ((outputButtons & A_MASK) != 0 ? ~0b00100000 : -1) &
596: ((outputButtons & START_MASK) != 0 ? ~0b01000000 : -1)
597: :
598: 0b11111111 &
599: ((outputButtons & (UP_MASK | DOWN_MASK)) == UP_MASK ? ~0b00000001 : -1) &
600: ((outputButtons & (DOWN_MASK | UP_MASK)) == DOWN_MASK ? ~0b00000010 : -1) &
601: ((outputButtons & (LEFT_MASK | RIGHT_MASK)) == LEFT_MASK ? ~0b00000100 : -1) &
602: ((outputButtons & (RIGHT_MASK | LEFT_MASK)) == RIGHT_MASK ? ~0b00001000 : -1) &
603: ((outputButtons & B_MASK) != 0 ? ~0b00100000 : -1) &
604: ((outputButtons & C_MASK) != 0 ? ~0b01000000 : -1));
605: }
606:
607: }