mouse.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. {
  2. System dependent mouse implementation for go32v2
  3. $Id$
  4. }
  5. uses
  6. go32;
  7. var
  8. RealSeg : Word; { Real mode segment }
  9. RealOfs : Word; { Real mode offset }
  10. CurrentMask : word;
  11. MouseCallback : Pointer; { Mouse call back ptr }
  12. {$ifdef DEBUG}
  13. EntryEDI,EntryESI : longint;
  14. EntryDS,EntryES : word;
  15. {$endif DEBUG}
  16. { Real mode registers in text segment below $ffff limit
  17. for Windows NT
  18. NOTE this might cause problem if someone want to
  19. protect text section against writing (would be possible
  20. with CWSDPMI under raw dos, not implemented yet !) }
  21. ActionRegs : TRealRegs;external name '___v2prt0_rmcb_regs';
  22. v2prt0_ds_alias : word;external name '___v2prt0_ds_alias';
  23. const
  24. MousePresent : boolean = false;
  25. {$ifdef DEBUG}
  26. MouseError : longint = 0;
  27. CallCounter : longint = 0;
  28. {$endif DEBUG}
  29. {$ASMMODE ATT}
  30. procedure MouseInt;assembler;
  31. asm
  32. movb %bl,mousebuttons
  33. movw %cx,mousewherex
  34. movw %dx,mousewherey
  35. cmpb MouseEventBufSize,PendingMouseEvents
  36. je .Lmouse_exit
  37. movl PendingMouseTail,%edi
  38. shrw $3,%cx
  39. shrw $3,%dx
  40. movw %bx,(%edi)
  41. movw %cx,2(%edi)
  42. movw %dx,4(%edi)
  43. movw $0,6(%edi)
  44. addl $8,%edi
  45. leal PendingMouseEvent,%eax
  46. addl MouseEventBufSize*8,%eax
  47. cmpl %eax,%edi
  48. jne .Lmouse_nowrap
  49. leal PendingMouseEvent,%edi
  50. .Lmouse_nowrap:
  51. movl %edi,PendingMouseTail
  52. incb PendingMouseEvents
  53. .Lmouse_exit:
  54. end;
  55. PROCEDURE Mouse_Trap; ASSEMBLER;
  56. ASM
  57. PUSH %ES; { Save ES register }
  58. PUSH %DS; { Save DS register }
  59. PUSHL %EDI; { Save register }
  60. PUSHL %ESI; { Save register }
  61. ;{ caution : ds is not the selector for our data !! }
  62. {$ifdef DEBUG}
  63. MOVL %EDI,%ES:EntryEDI
  64. MOVL %ESI,%ES:EntryESI
  65. MOVW %DS,%AX
  66. MOVW %AX,%ES:EntryDS
  67. MOVW %ES,%AX
  68. MOVW %AX,%ES:EntryES
  69. {$endif DEBUG}
  70. { movw %cs:v2prt0_ds_alias,%ax v2prt0 is not locked !!
  71. movw %ax,%ds
  72. movw %ax,%es }
  73. PUSH %ES; { Push data seg }
  74. POP %DS; { Load data seg }
  75. {$ifdef DEBUG}
  76. incl callcounter
  77. CMPL $ACTIONREGS,%edi
  78. JE .L_ActionRegsOK
  79. INCL MouseError
  80. JMP .L_NoCallBack
  81. .L_ActionRegsOK:
  82. {$endif DEBUG}
  83. MOVL MOUSECALLBACK, %EAX; { Fetch callback addr }
  84. CMPL $0, %EAX; { Check for nil ptr }
  85. JZ .L_NoCallBack; { Ignore if nil }
  86. MOVL %EDI,%EAX; { %EAX = @actionregs }
  87. MOVL (%EAX), %EDI; { EDI from actionregs }
  88. MOVL 4(%EAX), %ESI; { ESI from actionregs }
  89. MOVL 16(%EAX), %EBX; { EBX from actionregs }
  90. MOVL 20(%EAX), %EDX; { EDX from actionregs }
  91. MOVL 24(%EAX), %ECX; { ECX from actionregs }
  92. MOVL 28(%EAX), %EAX; { EAX from actionregs }
  93. CALL *MOUSECALLBACK; { Call callback proc }
  94. .L_NoCallBack:
  95. POPL %ESI; { Recover register }
  96. POPL %EDI; { Recover register }
  97. POP %DS; { Restore DS register }
  98. POP %ES; { Restore ES register }
  99. { This works for WinNT
  100. movzwl %si,%eax
  101. but CWSDPMI need this }
  102. movl %esi,%eax
  103. MOVL %ds:(%Eax), %EAX;
  104. MOVL %EAX, %ES:42(%EDI); { Set as return addr }
  105. ADDW $4, %ES:46(%EDI); { adjust stack }
  106. IRET; { Interrupt return }
  107. END;
  108. Function Allocate_mouse_bridge : boolean;
  109. var
  110. error : word;
  111. begin
  112. ASM
  113. LEAL ACTIONREGS, %EDI; { Addr of actionregs }
  114. LEAL MOUSE_TRAP, %ESI; { Procedure address }
  115. PUSH %DS; { Save DS segment }
  116. PUSH %ES; { Save ES segment }
  117. MOVW v2prt0_ds_alias,%ES; { ES now has dataseg alias that is never invalid }
  118. PUSH %CS;
  119. POP %DS; { DS now has codeseg }
  120. MOVW $0x303, %AX; { Function id }
  121. INT $0x31; { Call DPMI bridge }
  122. JNC .L_call_ok; { Branch if ok }
  123. POP %ES; { Restore ES segment }
  124. POP %DS; { Restore DS segment }
  125. MOVW $0,REALSEG;
  126. MOVW $0,REALOFS;
  127. JMP .L_exit
  128. .L_call_ok:
  129. POP %ES; { Restore ES segment }
  130. POP %DS; { Restore DS segment }
  131. MOVW %CX,REALSEG; { Transfer real seg }
  132. MOVW %DX,REALOFS; { Transfer real ofs }
  133. MOVW $0, %AX; { Force error to zero }
  134. .L_exit:
  135. MOVW %AX, ERROR; { Return error state }
  136. END;
  137. Allocate_mouse_bridge:=error=0;
  138. end;
  139. Procedure Release_mouse_bridge;
  140. begin
  141. ASM
  142. MOVW $0x304, %AX; { Set function id }
  143. MOVW REALSEG, %CX; { Bridged real seg }
  144. MOVW REALOFS, %DX; { Bridged real ofs }
  145. INT $0x31; { Release bridge }
  146. MOVW $0,REALSEG;
  147. MOVW $0,REALOFS;
  148. END;
  149. end;
  150. PROCEDURE Mouse_Action (Mask : Word; P : Pointer);
  151. VAR
  152. Error : Word;
  153. Rg : TRealRegs;
  154. BEGIN
  155. Error := 0; { Preset no error }
  156. If (P <> MouseCallBack) or (Mask<>CurrentMask) Then { Check func different }
  157. Begin
  158. { Remove old calback }
  159. If (CurrentMask <> 0) Then
  160. Begin
  161. Rg.AX := 12; { Function id }
  162. Rg.CX := 0; { Zero mask register }
  163. Rg.ES := 0; { Zero proc seg }
  164. Rg.DX := 0; { Zero proc ofs }
  165. RealIntr($33, Rg); { Stop INT 33 callback }
  166. End;
  167. if RealSeg=0 then
  168. error:=1;
  169. { test addresses for Windows NT }
  170. if (longint(@actionregs)>$ffff) {or
  171. (longint(@mouse_trap)>$ffff)} then
  172. begin
  173. error:=1;
  174. end
  175. else If (P = Nil) Then
  176. Begin
  177. Mask := 0; { Zero mask register }
  178. End;
  179. If (Error = 0) Then
  180. Begin
  181. MouseCallback := P; { Set call back addr }
  182. if Mask<>0 then
  183. begin
  184. Rg.AX := 12; { Set function id }
  185. Rg.CX := Mask; { Set mask register }
  186. If Mask<>0 then
  187. begin
  188. Rg.ES := RealSeg; { Real mode segment }
  189. Rg.DX := RealOfs; { Real mode offset }
  190. end
  191. else
  192. begin
  193. Rg.ES:=0;
  194. Rg.DX:=0;
  195. end;
  196. RealIntr($33, Rg); { Set interrupt 33 }
  197. end;
  198. CurrentMask:=Mask;
  199. End;
  200. End;
  201. If (Error <> 0) Then
  202. Begin
  203. Writeln('GO32V2 mouse handler set failed !!');
  204. ReadLn; { Wait for user to see }
  205. End;
  206. END;
  207. { We need to remove the mouse callback before exiting !! PM }
  208. const StoredExit : Pointer = Nil;
  209. FirstMouseInitDone : boolean = false;
  210. procedure MouseSafeExit;
  211. begin
  212. ExitProc:=StoredExit;
  213. if MouseCallBack<>Nil then
  214. Mouse_Action(0, Nil);
  215. if not FirstMouseInitDone then
  216. exit;
  217. FirstMouseInitDone:=false;
  218. Unlock_Code(Pointer(@Mouse_Trap), 400); { Release trap code }
  219. Unlock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  220. Unlock_Data(ActionRegs, SizeOf(TRealRegs)); { Release registers }
  221. {$ifdef DEBUG}
  222. Unlock_Data(EntryEDI, 4*SizeOf(longint));
  223. Unlock_Data(callcounter, 2*SizeOf(longint));
  224. {$endif DEBUG}
  225. { unlock Mouse Queue and related stuff ! }
  226. Unlock_Data(PendingMouseEvent,
  227. MouseEventBufSize*Sizeof(TMouseEvent)+2*Sizeof(PMouseEvent)+256);
  228. UnLock_Data(MouseCallBack,SizeOf(Pointer));
  229. Release_mouse_bridge;
  230. end;
  231. procedure InitMouse;
  232. begin
  233. if not MousePresent then
  234. begin
  235. if DetectMouse=0 then
  236. begin
  237. Writeln('No mouse driver found ');
  238. exit;
  239. end
  240. else
  241. MousePresent:=true;
  242. end;
  243. PendingMouseHead:=@PendingMouseEvent;
  244. PendingMouseTail:=@PendingMouseEvent;
  245. PendingMouseEvents:=0;
  246. FillChar(LastMouseEvent,sizeof(TMouseEvent),0);
  247. { don't do this twice !! PM }
  248. If not FirstMouseInitDone then
  249. begin
  250. StoredExit:=ExitProc;
  251. ExitProc:=@MouseSafeExit;
  252. Lock_Code(Pointer(@Mouse_Trap), 400); { Lock trap code }
  253. Lock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  254. Lock_Data(ActionRegs, SizeOf(TRealRegs)); { Lock registers }
  255. Lock_Data(MouseCallBack, SizeOf(pointer));
  256. { lock Mouse Queue and related stuff ! }
  257. Lock_Data(PendingMouseEvent,
  258. MouseEventBufSize*Sizeof(TMouseEvent)+2*Sizeof(PMouseEvent)+256);
  259. {$ifdef DEBUG}
  260. Lock_Data(EntryEDI, 4*SizeOf(longint));
  261. Lock_Data(callcounter, 2*SizeOf(longint));
  262. {$endif DEBUG}
  263. Allocate_mouse_bridge;
  264. FirstMouseInitDone:=true;
  265. end;
  266. If MouseCallBack=Nil then
  267. Mouse_Action($ffff, @MouseInt); { Set masks/interrupt }
  268. ShowMouse;
  269. end;
  270. procedure DoneMouse;
  271. begin
  272. HideMouse;
  273. If (MouseCallBack <> Nil) Then
  274. Mouse_Action(0, Nil); { Clear mask/interrupt }
  275. end;
  276. function DetectMouse:byte;assembler;
  277. asm
  278. movl $0x200,%eax
  279. movl $0x33,%ebx
  280. int $0x31
  281. movw %cx,%ax
  282. orw %ax,%dx
  283. jz .Lno_mouse
  284. xorl %eax,%eax
  285. pushl %ebp
  286. int $0x33
  287. popl %ebp
  288. orw %ax,%ax
  289. jz .Lno_mouse
  290. movl %ebx,%eax
  291. .Lno_mouse:
  292. end;
  293. procedure ShowMouse;assembler;
  294. asm
  295. cmpb $1,MousePresent
  296. jne .LShowMouseExit
  297. movl $1,%eax
  298. pushl %ebp
  299. int $0x33
  300. popl %ebp
  301. .LShowMouseExit:
  302. end;
  303. procedure HideMouse;assembler;
  304. asm
  305. cmpb $1,MousePresent
  306. jne .LHideMouseExit
  307. movl $2,%eax
  308. pushl %ebp
  309. int $0x33
  310. popl %ebp
  311. .LHideMouseExit:
  312. end;
  313. function GetMouseX:word;assembler;
  314. asm
  315. cmpb $1,MousePresent
  316. jne .LGetMouseXError
  317. movl $3,%eax
  318. pushl %ebp
  319. int $0x33
  320. popl %ebp
  321. movzwl %cx,%eax
  322. shrl $3,%eax
  323. incl %eax
  324. ret
  325. .LGetMouseXError:
  326. xorl %eax,%eax
  327. end;
  328. function GetMouseY:word;assembler;
  329. asm
  330. cmpb $1,MousePresent
  331. jne .LGetMouseYError
  332. movl $3,%eax
  333. pushl %ebp
  334. int $0x33
  335. popl %ebp
  336. movzwl %dx,%eax
  337. shrl $3,%eax
  338. incl %eax
  339. ret
  340. .LGetMouseYError:
  341. xorl %eax,%eax
  342. end;
  343. function GetMouseButtons:word;assembler;
  344. asm
  345. cmpb $1,MousePresent
  346. jne .LGetMouseButtonsError
  347. movl $3,%eax
  348. pushl %ebp
  349. int $0x33
  350. popl %ebp
  351. movw %bx,%ax
  352. ret
  353. .LGetMouseButtonsError:
  354. xorl %eax,%eax
  355. end;
  356. procedure SetMouseXY(x,y:word);assembler;
  357. asm
  358. cmpb $1,MousePresent
  359. jne .LSetMouseXYExit
  360. movw x,%cx
  361. movw y,%dx
  362. movl $4,%eax
  363. pushl %ebp
  364. int $0x33
  365. popl %ebp
  366. .LSetMouseXYExit:
  367. end;
  368. const
  369. LastCallcounter : longint = 0;
  370. procedure GetMouseEvent(var MouseEvent: TMouseEvent);
  371. begin
  372. if not MousePresent then
  373. begin
  374. Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  375. end;
  376. {$ifdef DEBUG}
  377. if mouseError>0 then
  378. Writeln('Errors in mouse Handler ',MouseError);
  379. {$ifdef EXTMOUSEDEBUG}
  380. if callcounter>LastCallcounter then
  381. Writeln('Number of calls in mouse Handler ',Callcounter);
  382. {$endif EXTMOUSEDEBUG}
  383. LastCallcounter:=Callcounter;
  384. {$endif DEBUG}
  385. repeat until PendingMouseEvents>0;
  386. MouseEvent:=PendingMouseHead^;
  387. inc(PendingMouseHead);
  388. if longint(PendingMouseHead)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  389. PendingMouseHead:=@PendingMouseEvent;
  390. dec(PendingMouseEvents);
  391. if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
  392. MouseEvent.Action:=MouseActionMove;
  393. if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
  394. begin
  395. if (LastMouseEvent.Buttons=0) then
  396. MouseEvent.Action:=MouseActionDown
  397. else
  398. MouseEvent.Action:=MouseActionUp;
  399. end;
  400. LastMouseEvent:=MouseEvent;
  401. end;
  402. function PollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  403. begin
  404. if PendingMouseEvents>0 then
  405. begin
  406. MouseEvent:=PendingMouseHead^;
  407. PollMouseEvent:=true;
  408. end
  409. else
  410. PollMouseEvent:=false;
  411. end;
  412. {
  413. $Log$
  414. Revision 1.1 2000-01-06 01:20:30 peter
  415. * moved out of packages/ back to topdir
  416. Revision 1.2 1999/12/08 13:25:20 pierre
  417. * fix form bug 731
  418. Revision 1.12 1999/11/24 23:36:56 peter
  419. * moved to packages dir
  420. Revision 1.11 1999/10/18 15:46:24 pierre
  421. * not int $0x33 call if no mouse driver present
  422. Revision 1.10 1999/10/18 07:37:05 pierre
  423. * Unlock code moved to exitproc because CWSDPMI has no lock counter
  424. Revision 1.9 1999/10/16 08:35:52 jonas
  425. * MouseCallBack was never unlocked
  426. Revision 1.8 1999/10/15 23:53:07 pierre
  427. * mouse problem with CWSDPMI solved
  428. Revision 1.7 1999/10/15 11:46:33 pierre
  429. * MouseInt was not locked !!
  430. Revision 1.6 1999/03/03 16:42:27 pierre
  431. + test for NT compatibility
  432. Revision 1.5 1999/02/19 16:44:48 peter
  433. * fixed (esi) which also got the 0xffff limit under NT
  434. Revision 1.4 1999/02/19 12:28:39 pierre
  435. + Uses now v2prt0_ds_alias for RMCB regs
  436. regs are located in text section of v2prt0.as
  437. so that its offset is below $ffff limit (for window NT !)
  438. Revision 1.3 1999/02/08 09:39:13 pierre
  439. * added exitproc to avoid real mode crash with function 12 of mouse interrupt
  440. Revision 1.2 1998/12/11 00:13:19 peter
  441. + SetMouseXY
  442. * use far for exitproc procedure
  443. Revision 1.1 1998/12/04 12:48:27 peter
  444. * moved some dirs
  445. Revision 1.2 1998/10/28 21:18:25 peter
  446. * more fixes
  447. Revision 1.1 1998/10/28 00:02:08 peter
  448. + mouse
  449. + video.clearscreen, video.videobufsize
  450. }