home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / adb.cpp next >
C/C++ Source or Header  |  1999-11-03  |  10KB  |  385 lines

  1. /*
  2.  *  adb.cpp - ADB emulation (mouse/keyboard)
  3.  *
  4.  *  Basilisk II (C) 1997-1999 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. /*
  22.  *  SEE ALSO
  23.  *    Inside Macintosh: Devices, chapter 5 "ADB Manager"
  24.  *    Technote HW 01: "ADB - The Untold Story: Space Aliens Ate My Mouse"
  25.  */
  26.  
  27. #include <stdlib.h>
  28.  
  29. #include "sysdeps.h"
  30. #include "cpu_emulation.h"
  31. #include "main.h"
  32. #include "video.h"
  33. #include "adb.h"
  34.  
  35. #define DEBUG 0
  36. #include "debug.h"
  37.  
  38.  
  39. // Global variables
  40. static int mouse_x = 0, mouse_y = 0;                            // Mouse position
  41. static int old_mouse_x = 0, old_mouse_y = 0;
  42. static bool mouse_button[3] = {false, false, false};            // Mouse button states
  43. static bool old_mouse_button[3] = {false, false, false};
  44. static bool relative_mouse = false;
  45.  
  46. static uint8 key_states[16];                // Key states (Mac keycodes)
  47. #define MATRIX(code) (key_states[code >> 3] & (1 << (~code & 7)))
  48.  
  49. // Keyboard event buffer (Mac keycodes with up/down flag)
  50. const int KEY_BUFFER_SIZE = 16;
  51. static uint8 key_buffer[KEY_BUFFER_SIZE];
  52. static unsigned int key_read_ptr = 0, key_write_ptr = 0;
  53.  
  54. static uint8 mouse_reg_3[2] = {0x63, 0x01};    // Mouse ADB register 3
  55.  
  56. static uint8 key_reg_2[2] = {0xff, 0xff};    // Keyboard ADB register 2
  57. static uint8 key_reg_3[2] = {0x62, 0x05};    // Keyboard ADB register 3
  58.  
  59.  
  60. /*
  61.  *  ADBOp() replacement
  62.  */
  63.  
  64. void ADBOp(uint8 op, uint8 *data)
  65. {
  66.     D(bug("ADBOp op %02x, data %02x %02x %02x\n", op, data[0], data[1], data[2]));
  67.  
  68.     // ADB reset?
  69.     if ((op & 0x0f) == 0) {
  70.         mouse_reg_3[0] = 0x63;
  71.         mouse_reg_3[1] = 0x01;
  72.         key_reg_2[0] = 0xff;
  73.         key_reg_2[1] = 0xff;
  74.         key_reg_3[0] = 0x62;
  75.         key_reg_3[1] = 0x05;
  76.         return;
  77.     }
  78.  
  79.     // Cut op into fields
  80.     uint8 adr = op >> 4;
  81.     uint8 cmd = (op >> 2) & 3;
  82.     uint8 reg = op & 3;
  83.  
  84.     // Check which device was addressed and act accordingly
  85.     if (adr == (mouse_reg_3[0] & 0x0f)) {
  86.  
  87.         // Mouse
  88.         if (cmd == 2) {
  89.  
  90.             // Listen
  91.             switch (reg) {
  92.                 case 3:        // Address/HandlerID
  93.                     if (data[2] == 0xfe)            // Change address
  94.                         mouse_reg_3[0] = (mouse_reg_3[0] & 0xf0) | (data[1] & 0x0f);
  95.                     else if (data[2] == 1 || data[2] == 2 || data[2] == 4)    // Change device handler ID
  96.                         mouse_reg_3[1] = data[2];
  97.                     else if (data[2] == 0x00)        // Change address and enable bit
  98.                         mouse_reg_3[0] = (mouse_reg_3[0] & 0xd0) | (data[1] & 0x2f);
  99.                     break;
  100.             }
  101.  
  102.         } else if (cmd == 3) {
  103.  
  104.             // Talk
  105.             switch (reg) {
  106.                 case 1:        // Extended mouse protocol
  107.                     data[0] = 8;
  108.                     data[1] = 'a';                // Identifier
  109.                     data[2] = 'p';
  110.                     data[3] = 'p';
  111.                     data[4] = 'l';
  112.                     data[5] = 300 >> 8;            // Resolution (dpi)
  113.                     data[6] = 300 & 0xff;
  114.                     data[7] = 1;                // Class (mouse)
  115.                     data[8] = 3;                // Number of buttons
  116.                     break;
  117.                 case 3:        // Address/HandlerID
  118.                     data[0] = 2;
  119.                     data[1] = mouse_reg_3[0] & 0xf0 | (rand() & 0x0f);
  120.                     data[2] = mouse_reg_3[1];
  121.                     break;
  122.                 default:
  123.                     data[0] = 0;
  124.                     break;
  125.             }
  126.         }
  127.         D(bug(" mouse reg 3 %02x%02x\n", mouse_reg_3[0], mouse_reg_3[1]));
  128.  
  129.     } else if (adr == (key_reg_3[0] & 0x0f)) {
  130.  
  131.         // Keyboard
  132.         if (cmd == 2) {
  133.  
  134.             // Listen
  135.             switch (reg) {
  136.                 case 2:        // LEDs/Modifiers
  137.                     key_reg_2[0] = data[1];
  138.                     key_reg_2[1] = data[2];
  139.                     break;
  140.                 case 3:        // Address/HandlerID
  141.                     if (data[2] == 0xfe)            // Change address
  142.                             key_reg_3[0] = (key_reg_3[0] & 0xf0) | (data[1] & 0x0f);
  143.                     else if (data[2] == 0x00)        // Change address and enable bit
  144.                         key_reg_3[0] = (key_reg_3[0] & 0xd0) | (data[1] & 0x2f);
  145.                     break;
  146.             }
  147.  
  148.         } else if (cmd == 3) {
  149.  
  150.             // Talk
  151.             switch (reg) {
  152.                 case 2: {    // LEDs/Modifiers
  153.                     uint8 reg2hi = 0xff;
  154.                     uint8 reg2lo = key_reg_2[1] | 0xf8;
  155.                     if (MATRIX(0x6b))    // Scroll Lock
  156.                         reg2lo &= ~0x40;
  157.                     if (MATRIX(0x47))    // Num Lock
  158.                         reg2lo &= ~0x80;
  159.                     if (MATRIX(0x37))    // Command
  160.                         reg2hi &= ~0x01;
  161.                     if (MATRIX(0x3a))    // Option
  162.                         reg2hi &= ~0x02;
  163.                     if (MATRIX(0x38))    // Shift
  164.                         reg2hi &= ~0x04;
  165.                     if (MATRIX(0x36))    // Control
  166.                         reg2hi &= ~0x08;
  167.                     if (MATRIX(0x39))    // Caps Lock
  168.                         reg2hi &= ~0x20;
  169.                     if (MATRIX(0x75))    // Delete
  170.                         reg2hi &= ~0x40;
  171.                     data[0] = 2;
  172.                     data[1] = reg2hi;
  173.                     data[2] = reg2lo;
  174.                     break;
  175.                 }
  176.                 case 3:        // Address/HandlerID
  177.                     data[0] = 2;
  178.                     data[1] = key_reg_3[0] & 0xf0 | (rand() & 0x0f);
  179.                     data[2] = key_reg_3[1];
  180.                     break;
  181.                 default:
  182.                     data[0] = 0;
  183.                     break;
  184.             }
  185.         }
  186.         D(bug(" keyboard reg 3 %02x%02x\n", key_reg_3[0], key_reg_3[1]));
  187.  
  188.     } else                                                // Unknown address
  189.         if (cmd == 3)
  190.             data[0] = 0;                                // Talk: 0 bytes of data
  191. }
  192.  
  193.  
  194. /*
  195.  *  Mouse was moved (x/y are absolute or relative, depending on ADBSetMouseMode())
  196.  */
  197.  
  198. void ADBMouseMoved(int x, int y)
  199. {
  200.     if (relative_mouse) {
  201.         mouse_x += x; mouse_y += y;
  202.     } else {
  203.         mouse_x = x; mouse_y = y;
  204.     }
  205. }
  206.  
  207.  
  208. /* 
  209.  *  Mouse button pressed
  210.  */
  211.  
  212. void ADBMouseDown(int button)
  213. {
  214.     mouse_button[button] = true;
  215. }
  216.  
  217.  
  218. /*
  219.  *  First mouse button released
  220.  */
  221.  
  222. void ADBMouseUp(int button)
  223. {
  224.     mouse_button[button] = false;
  225. }
  226.  
  227.  
  228. /*
  229.  *  Set mouse mode (absolute or relative)
  230.  */
  231.  
  232. void ADBSetRelMouseMode(bool relative)
  233. {
  234.     relative_mouse = relative;
  235. }
  236.  
  237.  
  238. /*
  239.  *  Key pressed ("code" is the Mac key code)
  240.  */
  241.  
  242. void ADBKeyDown(int code)
  243. {
  244.     // Add keycode to buffer
  245.     key_buffer[key_write_ptr] = code;
  246.     key_write_ptr = (key_write_ptr + 1) % KEY_BUFFER_SIZE;
  247.  
  248.     // Set key in matrix
  249.     key_states[code >> 3] |= (1 << (~code & 7));
  250. }
  251.  
  252.  
  253. /*
  254.  *  Key released ("code" is the Mac key code)
  255.  */
  256.  
  257. void ADBKeyUp(int code)
  258. {
  259.     // Add keycode to buffer
  260.     key_buffer[key_write_ptr] = code | 0x80;    // Key-up flag
  261.     key_write_ptr = (key_write_ptr + 1) % KEY_BUFFER_SIZE;
  262.  
  263.     // Clear key in matrix
  264.     key_states[code >> 3] &= ~(1 << (~code & 7));
  265. }
  266.  
  267.  
  268. /*
  269.  *  ADB interrupt function (executed as part of 60Hz interrupt)
  270.  */
  271.  
  272. void ADBInterrupt(void)
  273. {
  274.     M68kRegisters r;
  275.  
  276.     // Return if ADB is not initialized
  277.     uint32 adb_base = ReadMacInt32(0xcf8);
  278.     if (!adb_base || adb_base == 0xffffffff)
  279.         return;
  280.     uint32 tmp_data = adb_base + 0x163;    // Temporary storage for faked ADB data
  281.  
  282.     // Get position so that it won't change during processing
  283.     int mx = mouse_x;
  284.     int my = mouse_y;
  285.  
  286.     if (relative_mouse) {
  287.  
  288.         // Mouse movement (relative) and buttons
  289.         if (mx != 0 || my != 0 || mouse_button[0] != old_mouse_button[0] || mouse_button[1] != old_mouse_button[1] || mouse_button[2] != old_mouse_button[2]) {
  290.             uint32 mouse_base = adb_base + 16;
  291.  
  292.             // Call mouse ADB handler
  293.             if (mouse_reg_3[1] == 4) {
  294.                 // Extended mouse protocol
  295.                 WriteMacInt8(tmp_data, 3);
  296.                 WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80));
  297.                 WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80));
  298.                 WriteMacInt8(tmp_data + 3, ((my >> 3) & 0x70) | ((mx >> 7) & 0x07) | (mouse_button[2] ? 0x08 : 0x88));
  299.             } else {
  300.                 // 100/200 dpi mode
  301.                 WriteMacInt8(tmp_data, 2);
  302.                 WriteMacInt8(tmp_data + 1, (my & 0x7f) | (mouse_button[0] ? 0 : 0x80));
  303.                 WriteMacInt8(tmp_data + 2, (mx & 0x7f) | (mouse_button[1] ? 0 : 0x80));
  304.             }    
  305.             r.a[0] = tmp_data;
  306.             r.a[1] = ReadMacInt32(mouse_base);
  307.             r.a[2] = ReadMacInt32(mouse_base + 4);
  308.             r.a[3] = adb_base;
  309.             r.d[0] = (mouse_reg_3[0] << 4) | 0x0c;    // Talk 0
  310.             Execute68k(r.a[1], &r);
  311.  
  312.             mouse_x = mouse_y = 0;
  313.             old_mouse_button[0] = mouse_button[0];
  314.             old_mouse_button[1] = mouse_button[1];
  315.             old_mouse_button[2] = mouse_button[2];
  316.         }
  317.  
  318.     } else {
  319.  
  320.         // Update mouse position (absolute)
  321.         if (mx != old_mouse_x || my != old_mouse_y) {
  322.             WriteMacInt16(0x82a, mx);
  323.             WriteMacInt16(0x828, my);
  324.             WriteMacInt16(0x82e, mx);
  325.             WriteMacInt16(0x82c, my);
  326.             WriteMacInt8(0x8ce, ReadMacInt8(0x8cf));    // CrsrCouple -> CrsrNew
  327.             old_mouse_x = mx;
  328.             old_mouse_y = my;
  329.         }
  330.  
  331.         // Send mouse button events
  332.         if (mouse_button[0] != old_mouse_button[0]) {
  333.             uint32 mouse_base = adb_base + 16;
  334.  
  335.             // Call mouse ADB handler
  336.             if (mouse_reg_3[1] == 4) {
  337.                 // Extended mouse protocol
  338.                 WriteMacInt8(tmp_data, 3);
  339.                 WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80);
  340.                 WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80);
  341.                 WriteMacInt8(tmp_data + 3, mouse_button[2] ? 0x08 : 0x88);
  342.             } else {
  343.                 // 100/200 dpi mode
  344.                 WriteMacInt8(tmp_data, 2);
  345.                 WriteMacInt8(tmp_data + 1, mouse_button[0] ? 0 : 0x80);
  346.                 WriteMacInt8(tmp_data + 2, mouse_button[1] ? 0 : 0x80);
  347.             }
  348.             r.a[0] = tmp_data;
  349.             r.a[1] = ReadMacInt32(mouse_base);
  350.             r.a[2] = ReadMacInt32(mouse_base + 4);
  351.             r.a[3] = adb_base;
  352.             r.d[0] = (mouse_reg_3[0] << 4) | 0x0c;    // Talk 0
  353.             Execute68k(r.a[1], &r);
  354.  
  355.             old_mouse_button[0] = mouse_button[0];
  356.             old_mouse_button[1] = mouse_button[1];
  357.             old_mouse_button[2] = mouse_button[2];
  358.         }
  359.     }
  360.  
  361.     // Process accumulated keyboard events
  362.     uint32 key_base = adb_base + 4;
  363.     while (key_read_ptr != key_write_ptr) {
  364.  
  365.         // Read keyboard event
  366.         uint8 mac_code = key_buffer[key_read_ptr];
  367.         key_read_ptr = (key_read_ptr + 1) % KEY_BUFFER_SIZE;
  368.  
  369.         // Call keyboard ADB handler
  370.         WriteMacInt8(tmp_data, 2);
  371.         WriteMacInt8(tmp_data + 1, mac_code);
  372.         WriteMacInt8(tmp_data + 2, mac_code == 0x7f ? 0x7f : 0xff);    // Power key is special
  373.         r.a[0] = tmp_data;
  374.         r.a[1] = ReadMacInt32(key_base);
  375.         r.a[2] = ReadMacInt32(key_base + 4);
  376.         r.a[3] = adb_base;
  377.         r.d[0] = (key_reg_3[0] << 4) | 0x0c;    // Talk 0
  378.         Execute68k(r.a[1], &r);
  379.     }
  380.  
  381.     // Clear temporary data
  382.     WriteMacInt32(tmp_data, 0);
  383.     WriteMacInt32(tmp_data + 4, 0);
  384. }
  385.