Return real mode callback.
Source position: go32.pp line 144
function get_rm_callback( |
pm_func: pointer; |
const reg: trealregs; |
var rmcb: tseginfo |
):Boolean; |
Returns a unique real mode segment:offset address, known as a "real mode callback," that will transfer control from real mode to a protected mode procedure.
Parameters:
Return values: True if successful, otherwise False.
Remark: | Callback addresses obtained with this function can be passed by a protected mode program for example to an interrupt handler, device driver, or TSR, so that the real mode program can call procedures within the protected mode program or notify the protected mode program of an event. The contents of the supplied regs structure is not valid after function call, but only at the time of the actual callback. |
Check the int31error variable.
|
Release real mode callback. |
{ This program tries to give an example how to install a callback procedure with the help of the GO32 unit. It installs a callback which is supplied by any Microsoft compatible mouse driver; at a specified mouse action this routine is called. This callback must provide the services explained in the docs. The main callback has to be in assembly, because it isn't possible to do these services with pascal alone. But is written as general as possible to provide maximum re-usability for other applications and hence it simply calls a normal pascal user procedure in addition to some initialization and callback service code, so you don't need to hassle around with it too much. Notes to this user procedure : *) it should not last too long to execute it *) ALL data and code touched in this proc MUST be locked BEFORE it is called the first time Used software interrupt calls (rough descriptions, only what's used): Int 33h 0000h - Microsoft Mouse driver : Reset mouse Input : AX = 0000h Return : AX = FFFFh if successful BX = number of buttons (if FFFFh then mouse has 2 buttons) Int 33h 0001h - Microsoft Mouse driver : Show mouse cursor Input : AX = 0001h Return : Mouse cursor shown on screen Int 33h 0002h - Microsoft mouse driver : Hide mouse cursor Input : AX = 0002h Return : Hides mouse cursor again Int 33h 000Ch - Microsoft mouse driver : Install user callback Input : AX = 000Ch CX = bit mask which tells the mouse driver at which actions the callback should be called, i.e. if button pressed, mouse moved etc. (In this example it's set to 7Fh so that the callback is called on every action) ES:EDX = pointer to callback procedure to call Note : The registers structure supplied to the callback contains valid mouse data when the handler is called. BX = button state information CX = mouse X coordinates DX = mouse Y coordinates For more detailed information consult any mouse reference or interrupt list. } {$CALLING REGISTER} {$ASMMODE ATT} {$MODE FPC} uses crt, go32; const { the mouse interrupt number } mouseint = $33; var { supplied register structure to the callback } mouse_regs : trealregs; external name '___v2prt0_rmcb_regs'; { real mode 48 bit pointer to the callback } mouse_seginfo : tseginfo; var { number of mouse buttons } mouse_numbuttons : longint; { bit mask for the action which triggered the callback } mouse_action : word; { current mouse x and y coordinates } mouse_x, mouse_y : Word; { button state } mouse_b : Word; { is an additional user procedure installed } userproc_installed : Longbool; { length of additional user procedure } userproc_length : Longint; { pointer to user proc } userproc_proc : pointer; { callback control handler, calls a user procedure if installed } { callback control handler, calls a user procedure if installed } procedure callback_handler; assembler; asm pushw %ds pushl %eax movw %es, %ax movw %ax, %ds { give control to user procedure if installed } cmpl $0, USERPROC_INSTALLED je .LNoCallback pushal movw DOSmemSELECTOR, %ax movw %ax, %fs { set fs for FPC } call *USERPROC_PROC popal .LNoCallback: popl %eax popw %ds pushl %eax movl (%esi), %eax movl %eax, %es: 42(%edi) { adjust stack } addw $4, %es:46(%edi) popl %eax iret end; { This dummy is used to obtain the length of the callback control function. It has to be right after the callback_handler() function. } procedure mouse_dummy; begin end; { This is the supplied user procedure. In this case we simply transform the virtual 640x200 mouse coordinate system to a 80x25 text mode coordinate system } procedure textuserproc; begin { the mouse_regs record contains the real mode registers now } mouse_b := mouse_regs.bx; mouse_x := (mouse_regs.cx shr 3) + 1; mouse_y := (mouse_regs.dx shr 3) + 1; end; { Description : Installs the mouse callback control handler and handles all necessary mouse related initialization. Input : userproc - pointer to a user procedure, nil if none userproclen - length of user procedure } procedure install_mouse(userproc : pointer; userproclen : longint); var r : trealregs; begin { mouse driver reset } r.eax := $0; realintr(mouseint, r); if (r.eax <> $FFFF) then begin Writeln('No Microsoft compatible mouse found'); Writeln('A Microsoft compatible mouse driver is necessary ', 'to run this example'); halt; end; { obtain number of mouse buttons } if (r.bx = $ffff) then mouse_numbuttons := 2 else mouse_numbuttons := r.bx; Writeln(mouse_numbuttons, ' button Microsoft compatible mouse ', ' found.'); { check for additional user procedure, and install it if available } if (userproc <> nil) then begin userproc_proc := userproc; userproc_installed := true; userproc_length := userproclen; { lock code for user procedure } lock_code(userproc_proc, userproc_length); end else begin { clear variables } userproc_proc := nil; userproc_length := 0; userproc_installed := false; end; { lock code & data which is touched in the callback handler } lock_data(mouse_x, sizeof(mouse_x)); lock_data(mouse_y, sizeof(mouse_y)); lock_data(mouse_b, sizeof(mouse_b)); lock_data(mouse_action, sizeof(mouse_action)); lock_data(userproc_installed, sizeof(userproc_installed)); lock_data(userproc_proc, sizeof(userproc_proc)); lock_data(mouse_regs, sizeof(mouse_regs)); lock_data(mouse_seginfo, sizeof(mouse_seginfo)); lock_code(@callback_handler, longint(@mouse_dummy)-longint(@callback_handler)); { allocate callback (supply registers structure) } get_rm_callback(@callback_handler, mouse_regs, mouse_seginfo); { install callback } r.eax := $0c; r.ecx := $7f; r.edx := longint(mouse_seginfo.offset); r.es := mouse_seginfo.segment; realintr(mouseint, r); { show mouse cursor } r.eax := $01; realintr(mouseint, r); end; procedure remove_mouse; var r : trealregs; begin { hide mouse cursor } r.eax := $02; realintr(mouseint, r); { remove callback handler } r.eax := $0c; r.ecx := 0; r.edx := 0; r.es := 0; realintr(mouseint, r); { free callback } free_rm_callback(mouse_seginfo); { check if additional userproc is installed, and clean up if needed } if (userproc_installed) then begin unlock_code(userproc_proc, userproc_length); userproc_proc := nil; userproc_length := 0; userproc_installed := false; end; { unlock used code & data } unlock_data(mouse_x, sizeof(mouse_x)); unlock_data(mouse_y, sizeof(mouse_y)); unlock_data(mouse_b, sizeof(mouse_b)); unlock_data(mouse_action, sizeof(mouse_action)); unlock_data(userproc_proc, sizeof(userproc_proc)); unlock_data(userproc_installed, sizeof(userproc_installed)); unlock_data(mouse_regs, sizeof(mouse_regs)); unlock_data(mouse_seginfo, sizeof(mouse_seginfo)); unlock_code(@callback_handler, longint(@mouse_dummy)-longint(@callback_handler)); fillchar(mouse_seginfo, sizeof(mouse_seginfo), 0); end; begin install_mouse(@textuserproc, 400); Writeln('Press any key to exit...'); while (not keypressed) do begin { write mouse state info } gotoxy(1, wherey); write('MouseX : ', mouse_x:2, ' MouseY : ', mouse_y:2, ' Buttons : ', mouse_b:2); end; remove_mouse; end.