callback.pas 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. { example for :
  2. get_rm_callback()
  3. free_rm_callback()
  4. realintr()
  5. Callbacks
  6. lock_code()
  7. unlock_code()
  8. lock_data()
  9. unlock_data()
  10. trealregs record
  11. tseginfo record
  12. }
  13. { This program tries to give an example how to install a callback procedure
  14. with the help of the GO32 unit.
  15. It installs a callback which is supplied by any Mircosoft compatible
  16. mouse driver; at a specified mouse action this routine is called. This
  17. callback must provide the services explained in the docs. The main callback
  18. has to be in assembly, because it isn't possible to do these services with
  19. pascal alone. But is written as general as possible to provide maximum
  20. re-usability for other applications and hence it simply calls a normal
  21. pascal user procedure in addition to some initialization and callback
  22. service code, so you don't need to hassle around with it too much.
  23. Notes to this user procedure :
  24. *) it should not last too long to execute it
  25. *) ALL data and code touched in this proc MUST be locked BEFORE it is called
  26. the first time
  27. Used software interrupt calls (rough descriptions, only what's used):
  28. Int 33h 0000h - Mircosoft Mouse driver : Reset mouse
  29. Input : AX = 0000h
  30. Return : AX = FFFFh if successful
  31. BX = number of buttons (if FFFFh then mouse has 2 buttons)
  32. Int 33h 0001h - Mircosoft Mouse driver : Show mouse cursor
  33. Input : AX = 0001h
  34. Return : Mouse cursor shown on screen
  35. Int 33h 0002h - Mircosoft mouse driver : Hide mouse cursor
  36. Input : AX = 0002h
  37. Return : Hides mouse cursor again
  38. Int 33h 000Ch - Mircosoft mouse driver : Install user callback
  39. Input : AX = 000Ch
  40. CX = bit mask which tells the mouse driver at which actions the
  41. callback should be called, i.e. if button pressed, mouse moved,
  42. ...
  43. (In this example it's set to 7Fh so that the callback is called
  44. on every action)
  45. ES:EDX = pointer to callback procedure to call
  46. Note : The registers structure supplied to the callback contains valid
  47. mouse data when the handler is called.
  48. BX = button state information
  49. CX = mouse X coordinates
  50. DX = mouse Y coordinates
  51. For more detailed information consult any mouse reference or interrupt list.
  52. }
  53. uses crt, { keypressed(), gotoxy(), wherey(), clrscr() }
  54. go32;
  55. const mouseint = $33; { the mouse interrupt number }
  56. var mouse_regs : trealregs; { supplied register structure to the callback }
  57. mouse_seginfo : tseginfo; { real mode 48 bit pointer to the callback }
  58. var mouse_numbuttons : longint;{ number of mouse buttons }
  59. mouse_action : word; { bit mask for the action which triggered the callback }
  60. mouse_x, mouse_y : Word; { current mouse x and y coordinates }
  61. mouse_b : Word; { button state }
  62. userproc_installed : Longbool; { is an additional user procedure installed }
  63. userproc_length : Longint; { length of additional user procedure }
  64. userproc_proc : pointer; { pointer to user proc }
  65. {$ASMMODE DIRECT}
  66. { callback control handler, calls a user procedure if installed }
  67. procedure callback_handler; assembler;
  68. asm
  69. pushw %es
  70. pushw %ds
  71. pushl %edi
  72. pushl %esi { es:edi is the pointer to real mode regs record }
  73. { give control to user procedure if installed }
  74. cmpl $1, _USERPROC_INSTALLED
  75. je .LNoCallback
  76. pushal
  77. movw %es, %ax { set es = ds, FPC wants this so that some procs work }
  78. movw %ax, %ds
  79. movw U_GO32_DOSMEMSELECTOR, %ax
  80. movw %ax, %fs { set fs for FPC }
  81. call *_USERPROC_PROC
  82. popal
  83. .LNoCallback:
  84. popl %esi
  85. popl %edi
  86. popw %ds
  87. popw %es
  88. movl (%esi), %eax
  89. movl %eax, %es: 42(%edi) { adjust stack }
  90. addw $4, %es: 46(%edi)
  91. iret
  92. end;
  93. { This dummy is used to obtain the length of the callback control function.
  94. It has to be right after the callback_handler() function.
  95. }
  96. procedure mouse_dummy; begin end;
  97. { This is the supplied user procedure. In this case we simply transform the
  98. virtual 640x200 mouse coordinate system to a 80x25 text mode coordinate
  99. system }
  100. procedure textuserproc;
  101. begin
  102. { the mouse_regs record contains the real mode registers now }
  103. mouse_b := mouse_regs.bx;
  104. mouse_x := (mouse_regs.cx shr 3) + 1;
  105. mouse_y := (mouse_regs.dx shr 3) + 1;
  106. end;
  107. { Description : Installs the mouse callback control handler and handles all
  108. necessary mouse related initialization.
  109. Input : userproc - pointer to a user procedure, nil if none
  110. userproclen - length of user procedure
  111. }
  112. procedure install_mouse(userproc : pointer; userproclen : longint);
  113. var r : trealregs;
  114. begin
  115. { mouse driver reset }
  116. r.eax := $0; realintr(mouseint, r);
  117. if (r.eax <> $FFFF) then begin
  118. Writeln('No Mircosoft compatible mouse found');
  119. Writeln('A Mircosoft compatible mouse driver is necessary to run this example');
  120. halt;
  121. end;
  122. { obtain number of mouse buttons }
  123. if (r.bx = $ffff) then mouse_numbuttons := 2
  124. else mouse_numbuttons := r.bx;
  125. Writeln(mouse_numbuttons, ' button Mircosoft compatible mouse found.');
  126. { check for additional user procedure, and install it if available }
  127. if (userproc <> nil) then begin
  128. userproc_proc := userproc;
  129. userproc_installed := true;
  130. userproc_length := userproclen;
  131. { lock code for user procedure }
  132. lock_code(userproc_proc, userproc_length);
  133. end else begin
  134. { clear variables }
  135. userproc_proc := nil;
  136. userproc_length := 0;
  137. userproc_installed := false;
  138. end;
  139. { lock code & data which is touched in the callback handler }
  140. lock_data(mouse_x, sizeof(mouse_x));
  141. lock_data(mouse_y, sizeof(mouse_y));
  142. lock_data(mouse_b, sizeof(mouse_b));
  143. lock_data(mouse_action, sizeof(mouse_action));
  144. lock_data(userproc_installed, sizeof(userproc_installed));
  145. lock_data(@userproc_proc, sizeof(userproc_proc));
  146. lock_data(mouse_regs, sizeof(mouse_regs));
  147. lock_data(mouse_seginfo, sizeof(mouse_seginfo));
  148. lock_code(@callback_handler, longint(@mouse_dummy)-longint(@callback_handler));
  149. { allocate callback (supply registers structure) }
  150. get_rm_callback(@callback_handler, mouse_regs, mouse_seginfo);
  151. { install callback }
  152. r.eax := $0c; r.ecx := $7f; r.edx := longint(mouse_seginfo.offset);
  153. r.es := mouse_seginfo.segment;
  154. realintr(mouseint, r);
  155. { show mouse cursor }
  156. r.eax := $01;
  157. realintr(mouseint, r);
  158. end;
  159. procedure remove_mouse;
  160. var r : trealregs;
  161. begin
  162. { hide mouse cursor }
  163. r.eax := $02; realintr(mouseint, r);
  164. { remove callback handler }
  165. r.eax := $0c; r.ecx := 0; r.edx := 0; r.es := 0;
  166. realintr(mouseint, r);
  167. { free callback }
  168. free_rm_callback(mouse_seginfo);
  169. { check if additional userproc is installed, and clean up if needed }
  170. if (userproc_installed) then begin
  171. unlock_code(userproc_proc, userproc_length);
  172. userproc_proc := nil;
  173. userproc_length := 0;
  174. userproc_installed := false;
  175. end;
  176. { unlock used code & data }
  177. unlock_data(mouse_x, sizeof(mouse_x));
  178. unlock_data(mouse_y, sizeof(mouse_y));
  179. unlock_data(mouse_b, sizeof(mouse_b));
  180. unlock_data(mouse_action, sizeof(mouse_action));
  181. unlock_data(@userproc_proc, sizeof(userproc_proc));
  182. unlock_data(userproc_installed, sizeof(userproc_installed));
  183. unlock_data(mouse_regs, sizeof(mouse_regs));
  184. unlock_data(mouse_seginfo, sizeof(mouse_seginfo));
  185. unlock_code(@callback_handler, longint(@mouse_dummy)-longint(@callback_handler));
  186. fillchar(mouse_seginfo, sizeof(mouse_seginfo), 0);
  187. end;
  188. begin
  189. install_mouse(@textuserproc, 400);
  190. Writeln('Press any key to exit...');
  191. while (not keypressed) do begin
  192. { write mouse state info }
  193. gotoxy(1, wherey);
  194. write('MouseX : ', mouse_x:2, ' MouseY : ', mouse_y:2, ' Buttons : ', mouse_b:2);
  195. end;
  196. remove_mouse;
  197. end.