Calling a real-mode device driver from FreeBASIC code requires that you jump through some hoops.
I coded a preliminary test, and as far as I can tell without the HBMOUSE driver the code works OK.
Code: Select all
''=============================================================================
#include "dos/dpmi.bi"
#include "dos/go32.bi"
#include "support.bas"
''=============================================================================
#define INSTALL_DEFAULT_HANDLER
''=============================================================================
''----------------------------------------------------
'' This for use with the HBMOUSE Get Status function.
''----------------------------------------------------
type StatusBuffer
buffer_size as byte '' Size of the status buffer is 10 bytes
touch_mode as byte '' Current touch screen mode
XResolution as short '' Horizontal resolution
YResolution as short '' Vertical resolution
keylock_state as byte '' Keylock position (ALWAYS 0)
scanning_state as byte '' Scanning enabled or disabled
keyclick_state as byte '' Audible feedback On or Off
mouse_scr_act as byte '' Screen active for mouse functions
end type
''=============================================================================
''---------------------------------------------------------------------------
'' The following functions call a HBMOUSE function through a DPMI function.
'' The return values from each of these calls are combined into a single
'' return value, with the DPMI function return value in the high-order word
'' and the HBMOUSE function return value in the low-order word. The DPMI
'' function return value will be a DPMI error code, or zero for no error.
'' The HBMOUSE function return value will be the contents of the AX register
'' on return from the interrupt call, see the HBMOUSE documentation for more
'' information.
''---------------------------------------------------------------------------
function HbmSetResolution( byval screenNumber as short, _
byval horizontalResolution as short, _
byval verticalResolution as short ) as integer
dim as integer rval
dim as __dpmi_regs dpmir
dpmir.h.ah = asc("T") '' signature
dpmir.h.al = &h12 '' Set Resolution
dpmir.x.di = screenNumber
dpmir.x.cx = horizontalResolution
dpmir.x.dx = verticalResolution
asm
mov ax, 0x300 '' Simulate Real Mode Interrupt
mov bl, 0x33 '' the interrupt number to be simulated
mov bh, 0 '' flags
mov cx, 0 '' words to copy from PM to RM stack
lea edi, [dpmir] '' load address of dpmir
int 0x31
jc 0f '' carry flag set on error
xor ax, ax '' zero AX
0:
shl eax, 16 '' shift into high-order word
mov [rval], eax
end asm
return rval or dpmir.x.ax
end function
''=============================================================================
function HbmResetTouchScreen() as integer
dim as integer rval
dim as __dpmi_regs dpmir
dpmir.x.ax = 0 '' Reset Touch Screen
asm
mov ax, 0x300 '' Simulate Real Mode Interrupt
mov bl, 0x60 '' the interrupt number to be simulated
mov bh, 0 '' flags
mov cx, 0 '' words to copy from PM to RM stack
lea edi, [dpmir] '' load address of dpmir
int 0x31
jc 0f '' carry flag set on error
xor ax, ax '' zero AX
0:
shl eax, 16 '' shift into high-order word
mov [rval], eax
end asm
return rval or dpmir.x.ax
end function
''=============================================================================
function HbmGetStatus( byval screenNumber as short, _
byval pStatusBuffer as StatusBuffer ptr ) as integer
dim as integer rval
dim as __dpmi_regs dpmir
dim as ushort seg, sel
AllocateDosBuffer( sizeof(StatusBuffer), @seg, @sel )
''-----------------------------------------------------------
'' The buffer_size member must be initialized to the size of
'' the structure, and then copied to the RM buffer.
''-----------------------------------------------------------
pStatusBuffer->buffer_size = sizeof(StatusBuffer)
CopyToRM( sel, pStatusBuffer, 0, 1 )
dpmir.h.ah = asc("T") '' signature
dpmir.h.al = &h14 '' Get Status
dpmir.x.di = screenNumber
dpmir.x.es = seg '' segment address of status buffer
dpmir.x.dx = 0 '' offset address of status buffer
asm
mov ax, 0x300 '' Simulate Real Mode Interrupt
mov bl, 0x60 '' the interrupt number to be simulated
mov bh, 0 '' flags
mov cx, 0 '' words to copy from PM to RM stack
lea edi, [dpmir] '' load address of dpmir
int 0x31
jc 0f '' carry flag set on error
xor ax, ax '' zero AX
0:
shl eax, 16 '' shift into high-order word
mov [rval], eax
end asm
''------------------------------------------------------
'' Copy the contents of the RM buffer to our PM buffer.
''------------------------------------------------------
CopyToPM( sel, 0, pStatusBuffer, sizeof(StatusBuffer) )
return rval or dpmir.x.ax
end function
''=============================================================================
''---------------------------------------------------------------------
'' To do a minimal test of this without the HBMOUSE driver installed,
'' because my test systems (PCs running Windows 2000 and MS-DOS 6.22
'' with CWSDPMI) do not provide a default handler for Interrupt 60h,
'' and because I wanted a handler that does more than just return
'' from the interrupt, I had to install my own handler.
''
'' For the handler details see handler.dbs.
''
'' If the driver is installed, you should NOT install this handler
'' because doing so would effectively disable the driver’s handler.
''
'' Note that while early versions of MS-DOS did not provide a default
'' handler for Interrupt 33h, AFAIK newer Microsoft operating systems,
'' at least through Windows XP, do.
''---------------------------------------------------------------------
#ifdef INSTALL_DEFAULT_HANDLER
dim as ushort seg, sel
dim as ubyte handlerCode(54) = { _
&h53,&h80,&hFC,&h54,&h75,&h2F,&h3C,&h14,&h75,&h2B, _
&h89,&hD3,&h26,&hC6,&h07,&h00,&h26,&hC6,&h47,&h01, _
&h01,&h26,&hC7,&h47,&h02,&h02,&h00,&h26,&hC7,&h47, _
&h04,&h03,&h00,&h26,&hC6,&h47,&h06,&h04,&h26,&hC6, _
&h47,&h07,&h05,&h26,&hC6,&h47,&h08,&h06,&h26,&hC6, _
&h47,&h09,&h07,&h5B,&hCF }
print AllocateDosBuffer( 55, @seg, @sel )
print
CopyToRM( sel, @handlerCode(0), 0, 55 )
asm
mov ax, 0x201 '' Set Real Mode Interrupt Vector
mov bl, 0x60 '' interrupt number
mov cx, [seg] '' segment address of handler
mov dx, 0 '' offset address of handler
int 0x31
end asm
#endif
dim as StatusBuffer sb
print sizeof(StatusBuffer)
print
print hex(HbmSetResolution( 1, 640, 480 ))
print hex(HbmResetTouchScreen())
print hex(HbmGetStatus( 1, @sb ))
print
print sb.buffer_size
print sb.touch_mode
print sb.XResolution
print sb.YResolution
print sb.keylock_state
print sb.scanning_state
print sb.keyclick_state
print sb.mouse_scr_act
print
print FreeDosBuffer( @sel )
sleep
support.bas:
Code: Select all
''=============================================================================
function AllocateDosBuffer( byval cb as integer, _
byval pSeg as short ptr, _
byval pSel as short ptr ) as integer
asm
mov ebx, [cb]
mov eax, ebx
shr ebx, 4 '' convert byte count to paragraphs
test eax, 0xf
jz 0f
inc ebx '' adjust for last partial paragraph
0: '' number of paragraphs in BX
mov ax, 0x100 '' Allocate DOS Memory Block
int 0x31
jnc 1f '' carry flag set on error
movzx eax, ax '' zero-extend error code into EAX
mov [function], eax '' return DPMI error code
jmp 2f
1:
mov ebx, [pSeg]
mov esi, [pSel]
mov [ebx], ax '' save RM segment address
mov [esi], dx '' save PM selector
mov DWORD PTR [function], 0 '' return zero for no error
2:
end asm
end function
''=============================================================================
function FreeDosBuffer( byval pSel as short ptr ) as integer
asm
mov ax, 0x101 '' Free DOS Memory Block
mov edx, [pSel]
mov dx, [edx] '' pass PM selector in DX
int 0x31
jnc 0f '' carry flag set on error
movzx eax, ax '' zero-extend error code into EAX
mov [function], eax '' return DPMI error code
jmp 1f
0:
mov DWORD PTR [function], 0 '' return zero for no error
1:
end asm
end function
''=============================================================================
sub CopyToRM( byval sel as ushort, _
byval srcOff as any ptr, _
byval destOff as any ptr, _
byval cb as uinteger )
asm
push es
pushf
cld
mov es, [sel]
mov esi, [srcOff]
mov edi, [destOff]
mov ecx, [cb]
shr ecx, 2
rep movsd
mov ecx, [cb]
and ecx, 3
rep movsb
popf
pop es
end asm
end sub
''=============================================================================
sub CopyToPM( byval sel as ushort, _
byval srcOff as any ptr, _
byval destOff as any ptr, _
byval cb as uinteger )
asm
push ds
pushf
cld
mov ds, [sel]
mov esi, [srcOff]
mov edi, [destOff]
mov ecx, [cb]
shr ecx, 2
rep movsd
mov ecx, [cb]
and ecx, 3
rep movsb
popf
pop ds
end asm
end sub
''=============================================================================
handler.dbs:
Code: Select all
n
n This is a DEBUG script that generates the 16-bit code for
n an Interrupt 60h handler for use in testing the HBMOUSE
n driver access code.
n
n The handler returns from the interrupt with an IRET.
n
n For the input values AH = 'T', AL = 14h it fills the
n HBMOUSE status buffer (structure definition below) at
n ES:DX with a sequence of values.
n
n type StatusBuffer
n buffer_size as byte
n touch_mode as byte
n XResolution as short
n YResolution as short
n keylock_state as byte
n scanning_state as byte
n keyclick_state as byte
n mouse_scr_act as byte
n end type
n
n To assemble, use a command line like this:
n
n DEBUG < scriptfile > outputfile
n
n And then copy the code from the disassembly listing in
n the output file.
n
n Note that the blank line following the IRET is
n necessary to exit assembly mode.
n
a 0
push bx
cmp ah, 54
jne 35
cmp al, 14
jne 35
mov bx, dx
es:
mov byte ptr [bx], 0
es:
mov byte ptr [bx+1], 1
es:
mov word ptr [bx+2], 2
es:
mov word ptr [bx+4], 3
es:
mov byte ptr [bx+6], 4
es:
mov byte ptr [bx+7], 5
es:
mov byte ptr [bx+8], 6
es:
mov byte ptr [bx+9], 7
pop bx
iret
u 0
u
q
Code: Select all
0
10
5412
0
5414
0
1
2
3
4
5
6
7
0