/* $DOC$ $NAME$ ft_int86() $CATEGORY$ DOS/BIOS $ONELINER$ Execute a software interrupt $SYNTAX$ ft_int86( , ) -> lResult $ARGUMENTS$ is the interrupt to execute. is an array that contains values to be loaded into the various CPU registers. The correspondence between registers and array elements is as follows: aElement[ 1 ] == AX register aElement[ 2 ] == BX register aElement[ 3 ] == CX register aElement[ 4 ] == DX register aElement[ 5 ] == SI register aElement[ 6 ] == DI register aElement[ 7 ] == BP register aElement[ 8 ] == DS register aElement[ 9 ] == ES register aElement[ 10 ] == Flags register $RETURNS$ .T. if all parameters valid and the function was able to execute the desired interrupt. .F. if invalid parameters passed. If you call this function in protected mode, .F. may also be returned if an allocation of low DOS memory fails. n addition, the array elements will contain whatever values were in he CPU registers immediately after the interrupt was executed. If ither of the string parameters were altered by the interrupt, these hanges will be reflected as well. $DESCRIPTION$ It is occasionally useful to be able to call interrupts directly from Clipper, without having to write a separate routine in C or ASM. This function allows you that capability. Given Clipper's high-level orientation, this function is necessarily somewhat messy to use. First, declare an array of ten elements to hold the eight values for the CPU registers and two string parameters. Then initialize the array elements with the values that you want the CPU registers to contain when the interrupt is executed. You need not initialize all the elements. For example, if the interrupt requires you to specify values for AX, DX, and DS, you would only need to initialize elements 1, 4, and 8. Once you have done the required register setup, call ft_int86(), passing the interrupt number and the register array as parameters. The function will load the CPU with your specified values, execute the interrupt, and then store the contents of the CPU registers back into your array. This will allow you to evaluate the results of the interrupt. Some interrupt services require you to pass the address of a string in a pair of registers. This function is capable of handling these sorts of situations, but it will take a little work on your part. If you need to pass a string that uses the DS register, store the string in element 8; if you need to pass a string that uses the ES register, store the string in element 9. ft_int86() will detect that you've supplied a string instead of a numeric value and will behave accordingly. That takes care of obtaining the segment portion of the pointer. To specify which register is to contain the offset, use the values REG_DS and REG_ES which are defined in the ftint86.ch file. When one of these values is found in an array element, it alerts ft_int86() to use the offset portion of a pointer instead of a numeric value. REG_DS tells ft_int86() to use the offset of the string in element 8, while REG_ES tells ft_int86() to use the offset of the string in element 9. All the CPU registers are sixteen bits in size. Some, however, are also split into two 8-bit registers. This function is only capable of receiving and returning registers that are 16 bits in size. To split a 16-bit register into two 8-bit values, you can use the pseudo-functions HighByte() and LowByte(), contained in the .ch file. To alter an 8-bit number so it will appear in the high-order byte of a register when passed to the ft_int86() function, use the MakeHI() pseudo-function contained in the .ch file. When run in real mode, this function is a shell for __ftint86(), which is written in assembler and does the actual work of executing the interrupt. __ftint86() is callable from C, so feel free to incorporate it into any C routines for which it might be useful. The source for __ftint86() can be found in the file AINT86.ASM. When run in protected mode, this function is a shell for cpmiInt86(), which is written in assembler and makes a DPMI call to drop into real mode and execute the interrupt. cpmiInt86() is also callable from C, so feel free to incorporate it into any C routines for which it might be useful. cpmiInt86() is part of the CPMI API. See the CPMI documentation for more information. $EXAMPLES$ // This example shows how to call the DOS "create file" service. Take // special note of how to set up string parameters. #include "ftint86.ch" LOCAL aRegs[ 10 ] // Declare the register array aRegs[ AX ] := makehi( 60 ) // DOS service, create file aRegs[ CX ] := 0 // Specify file attribute // Pay attention here, this is crucial. Note how to set up the string // so it appears in DS:DX. aRegs[ DS ] := "my_file.ext" aRegs[ DX ] := REG_DS ft_int86( 33, aRegs ) // Make the call to the DOS interrupt // This example shows how to call the DOS "get current directory" // service. This one also uses a string parameter, but note that it // uses a different offset register. #include "ftint86.ch" LOCAL aRegs[ 10 ] aRegs[ AX ] := makehi( 71 ) aRegs[ DX ] := 0 // Choose default drive // This service requires a 64-byte buffer whose address is in DS:SI. DOS // will fill the buffer with the current directory. aRegs[ DS ] := Space( 64 ) aRegs[ SI ] := REG_DS ft_int86( 33, aRegs ) ? aRegs[ DS ] // Display the directory name // For the sake of completeness, here's an example that doesn't use a // string. This one changes the video mode. #include "ftint86.ch" LOCAL aRegs[ 10 ] aRegs[ AX ] := 16 // Choose hi-res graphics ft_int86( 16, aRegs ) $INCLUDE$ ftint86.ch $END$ */