pcs/xli/trig_tp.pas

194 lines
6.6 KiB
ObjectPascal
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

PROGRAM math_test;
{
(This program has been tested under Turbo Pascal, version 3.0.)
This program is designed to show what needs to be done in order to interface
a TURBO Pascal program with TI Scheme via Scheme's XLI interface. This
program simply takes two arguments and performs the requested math operation
on the args and then returns the computed value. The lines that may need
to be changed by you will be marked with a @@ in the following comments.
Note: Real numbers, in TURBO Pascal, are stored internally in a six byte
format that is not compatiable with Scheme's internal format. This causes
a problem with exchanging real numbers. Also Pascal strings start with
a one byte length count. This poses a small problem. Since you pass to
XLI the address of where the string starts and it length you will need to
make sure that you add one byte to the address so that XLI will not get
length of the string incorporated as the first character of the string.
NOTE: When compiling any TURBO Pascal program to work with XLI you need
to set the "mAximum free dynamic memory" under the "compiler Option"
to be less than 0A000. The smaller you make this number the more
room TI Scheme has for its heap space. For example this program
has that number set at 0400 paragraphs which is more than enough.
}
CONST
F_NEAR = $0001; {Near data pointers. USED}
F_INT = $0002; {integers fit into 16 bits. USED}
F_REL = $0004; {release of the env block is done by the program. NOT-USED}
F_PAD = $0008; {leave args unpacked in parm block. USED}
RT_INTEGER = 0; { Return type of integer. USED}
RT_BOOLEAN = 1; { Return type of boolean. NOT-USED}
RT_STRING = 2; { Return type of string. NOT-USED}
RT_FLOAT = 3; { Return type of real num. NOT-USED}
TYPE
regPack = record
case Byte of
1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : Integer);
2 : (AL,AH,BL,BH,CL,CH,DL,DH :Byte);
end;
cmdTable_ptr = ^cmdTable;
xliFile_ptr = ^xliFileStruct;
xliRoutine_ptr = ^xliRoutineStruct;
cmdTable = string[50]; { @@ Allocate the needed length for the cmd table.}
xliFileStruct = record
id : integer;
flags : integer;
table : cmdTable_ptr;
parmBlock : xliRoutine_ptr;
reserved : array[1..8] of integer;
end;
xliRoutineStruct = record
select : integer;
specialService : integer;
ssArgs : array[1..8] of integer;
reserved : array[1..8] of integer;
returnType : integer;
returnValue : integer;
dummy1 : array[1..3] of integer; { @@ Add args as needed. }
arg1 : integer;
dummy2 : array[1..3] of integer;
arg2 : integer;
end;
VAR
psp,progSize : integer;
xliWaitRtn : integer;
regs : regPack;
fileBlock : xliFileStruct;
parmBlock : xliRoutineStruct;
table : cmdTable;
fileBlock_ptr : xliFile_ptr;
xwait, xbye : array[1..2] of integer;
FUNCTION CalcProgSize:Integer;
{ Calculate the size of this program by
1) Obtain a pointer to the paragraph of memory following this program.
2) Obtain a pointer to this program's PSP address.
3) Take the difference between steps 1 and 2.
}
Var
top : integer;
Begin
Regs.AX := $4800; {AX is set to the Allocate Memory function request ID.}
Regs.BX := $FFFF; {BX is set to all of memory, in paragraphs, which is
65535 * 16 or 1,048,560 bytes. Regardless of the
amount of memory you have, at least for MSDos 3.12,
this request will fail because there is not that
much memory available. But BX, after the DOS call
will contain the amount of memory, in paragraphs,
we are able to allocate.}
MsDos(Regs); {Issue the Allocate Memory call.}
Regs.AX := $4800; {AX gets clobbered by the previous call so reset it.}
{BX is set to the max block size allowed, by the
previous function request, so let's get the pointer to
the beginning of that block. It will be in AX.}
MsDos(Regs); {Issue the Allocate Memory call again.}
top := Regs.AX - 1; {AX now contains the pointer/segment address, in
paragraphs, of the available memory just past the
end of this program. We need to subtract 1 from
this to account for the Arena. Now we have the
address of the top of memory for our program.}
Regs.ES := Regs.AX; {Set ES to be equal to the block of memory that we
allocated so that we can release that memory.}
Regs.AX := $4900; {The release memory function request ID}
MsDos(Regs); {Issue the Release Memory call.}
CalcProgSize := top - psp;
End;
PROCEDURE xli_wait ;
Begin
inline
($FF/$36/psp/
$FF/$36/progSize/
$FF/$1E/xwait/
$58/
$58/
$A3/xliWaitRtn);
End;
PROCEDURE xli_bye ;
Begin
inline
($FF/$1E/xbye);
End;
{ .............. MAIN starts here ............. }
BEGIN
psp := Cseg; {At the start of all .COM files Cseg will point to the PSP.}
progSize := CalcProgSize;
{Note: Because of the above mentioned problems with Pascal strings we
need to, in essence, throw away the first element of the table
since it has the string length as its starting character. Consequently
XLI would never be able to find the first name in the table. To
prevent this from being a problem we just start the table off with
a slash and then down in the CASE stmt instead of starting with the
number zero we start with one. }
table := '/pplus/mminus/ttimes//';
fileBlock.id := $4252;
fileBlock.flags := F_NEAR + F_INT + F_PAD; { @@ Set the flags as you need.}
fileBlock.table := Addr(table);
fileBlock.parmBlock := Addr(parmBlock);
fileBlock_ptr := Addr(fileBlock);
MemW[psp:$5c] := Ofs(fileBlock_ptr^); { Set into the PSP the offest and }
MemW[psp:$5e] := Seg(fileBlock_ptr^); { segment address of the file block.}
xwait[1] := MemW[psp:$a]; { Store into XWAIT the offset and }
xwait[2] := MemW[psp:$c]; { segment address of DOS's terminate routine.}
xbye[1] := xwait[1]; { Copy the termination offset and }
xbye[2] := xwait[2]; { segment address, from above, into here.}
xwait[1] := xwait[1] + 3; { Increment by 3 for normal call. }
xbye[1] := xbye[1] + 6; { Increment by 6 for termination. }
xli_wait; { Make the initial call to XWAIT. }
while xliWaitRtn <> 0 do
begin
case parmBlock.select of
1 : parmBlock.returnValue := parmBlock.arg1 + parmBlock.arg2;
2 : parmBlock.returnValue := parmBlock.arg1 - parmBlock.arg2;
3 : parmBlock.returnValue := parmBlock.arg1 * parmBlock.arg2;
end;
parmBlock.returnType := RT_INTEGER;
xli_wait;
end;
xli_bye;
END.