Guide To Kernel Exports
2000.06.12
author: Geoffrey M.
(c) 1999-2000
Ultratech Creations
wildfireZ is a trademark of Ultratech Creations
website: www.UltratechCreations.com
Distributed under
the terms of the GNU Lesser General Public License.
See copyleft.txt for details.
These functions are valid for version 2.0.1 of the wildfireZ Plugins kernel DLL, for Windows 95 or higher.
standard
data types
naming
conventions
plugin
interface
runtime
parameter overloading
plugin
events
kernel
functions
function GetAppHandle
function GetAppInstance
procedure GetAppPath
function GetEnvironmentState
function GetFrameRate
function GetFramesRenderedfunction GetGameState
function GetKernelVersion
procedure GetOSPath
procedure GetOSSystemPath
function GetWFZError
procedure GetWFZPathprocedure IncFramesRendered
procedure SetWFZError
procedure SetGameState
function StartupKernel
function PluginAvailable
function GetDFC
function GetPluginCountfunction LoadPlugin
procedure UnloadPlugin
procedure ClearWFZBuffer
function GetWFZBuffer
function GetWFZBufferContentsSizefunction GetWFZBufferSize
procedure SetWFZBufferContentsSize
procedure SetWFZBufferSize
function ConvertGMTToIDL
function ConvertIDLToGMT
function ConvertToLocalDateTime
function DecodeHiresDateTime
function EncodeHiresDateTimefunction GetCurrentHiresDateTime
function GetIDLOffset
function GetIDLMinutesOffset
function IsLocalHiresDateTime
function GetElapsedTimeCount
function GetElapsedTimeFrequency
function IsElapsedTimeAvailablefunction GetStartupElapsedTime
function GetStartupTime
function GetRandomNumber
standard data types
The kernel was coded in Delphi 4 (pascal), and all required
function and procedure parameters use pascal data types.
Developers using C/C++, or Visual Basic may not be familiar with
what native types they should in the their own IDE, so here are
the equivalent ranges and storage formats.
type | range | format |
Integer Cardinal Shortint Smallint Longint Int64 Byte Word Longword |
2147483648..2147483647 0..4294967295 128..127 32768..32767 2147483648..2147483647 2^63..2^631 0..255 0..65535 0..4294967295 |
signed 32-bit unsigned 32-bit signed 8-bit signed 16-bit signed 32-bit signed 64-bit unsigned 8-bit unsigned 16-bit unsigned 32-bit |
naming conventions
All wildfireZ plugins have a ".wfz" extension.
Enumerated parameter/result values should contain the initals of the driver name, followed by an underscore, followed by the enum value name. For example, the wildfireZ kernel enum value to indicate that a plugin has loaded successfully would be "WFZK_PluginLoadSuccessful".
Errors follow the same naming scheme as enum vales, but a lowercase "e" is added to indicate that this an error enum value. For example, the kernel error enum for a plugin not being found is "eWFZK_PluginNotFound ".
plugin interface
Plugins are simply standard DLLs that use object naming
conventions for their functions. All plugin functions are "Dynamic
Function Calls", better known as "DFCs". A "DFC"
can be a property, a method (procedure or function), an event, or
an internally managed object made available through the DLL
interface. Kind of like ActiveX, but without the overhead or
automation.
When designing the pugin interface, its' functionality should first be divided into properties, methods, events, and objects. DFCs use the Infix Caps style, in which the first letter of each word is capitalized. When in doubt, look at the kernel source. Always use appropriate object naming conventions for the DFCs, which consist of a verb followed by a noun - e.g. StartupKernel, or RenderScene.
Properties are procedures or functions should, which always "Get" or "Set..." an internal value or state - e.g. GetFramesRendered, or SetGameState. If a property is "set", it is coded as a procedure. If you "get a property, then it is coded as a function. Any property which returns a boolean value, should be called "Is...", with the verb or state following the noun.- e.g. IsPluginMuckingUp, or IsKernelStarted.
Methods are closest to standard DLL functions and can be either procedures or functions. Methods do not change or read a state/value. They purely perform some action. E.g. LoadPlugin, OpenAudioFile.
Events from DLLs are a new thing for most developers. ActiveX is one of the few DLL types that actually make use of them. WildfireZ events are named "On...", and it is recommended to use runtime function overloading to implement them. E.g. OnMouseOver, OnSpriteCollision.
Objects can be made available thru a DLLs interface. The plugin must create, free, and manage the objects internally, so that the user only has to use minimal functions to perform these tasks. Object DFCs require an index value to be passed along with any other params, this is how the plugin knows which one of the multiple objects to perform the action on. A call to the plugin's Unload or Shutdown functions should free any objects that have been created by the user.
In this example 4 player objects have their properties updated, by using an index to the player objects to alter each value.
procedure SetPlayerObjectHealth(PlayerIndex: integer; HealthValue: integer); stdcall;
var i: integer;
for i:=0 to 3 do;
begin
SetPlayerObjectHealth(i, 94);
end;
EXPORTS
You will need to use "WildfireZDataTypes .pas" in your
project. It contains all the wfz enum and error values.
All plugins must have the following exports:
function Load(): integer; stdcall;
function Unload(): integer; stdcall;
procedure Shutdown(); stdcall;
Drivers are loaded using either of two load models: resident and dynamic. Resident plugins can only be unloaded by shutting down the kernel. All calls to UnloadPlugin will fail. Any plugin which is vital or required by many other plugins should be loaded using the resident model. Dynamic plugins can be unloaded at any time, and are typically used to perform brief tasks, such as jpeg-to-bmp, etc.
Load and Unload return an enum integer value back to the kernel indicating success or failure:
Load must return one of these values...
WFZK_PluginLoadFailed
WFZK_PluginLoadSuccessfulUnload must return one of these values...
WFZK_PluginUnloadFailed
WFZK_PluginUnloadSuccessful
If Load fails, the plugin is unloaded from memory and not added to the kernel's internal Plugins List. If Unload fails, the plugin remains loaded - but it will automatically be unloded when ShutdownKernel is called. The plugin procedure Shutdown is called by ShutdownKernel to remove any remaining plugins.
When Unload is called, the plugin should free all data structures, but not de-initialize itself. The plugin should still be on standby. It does not have to unload any plugins that it may have loaded for its' own use.
When ShutDown is called, it means that the kernel is shutting down. The plugin must free all structures that have been created by it, unload any plugins it may have loaded, and de-initialize itself.
runtime parameter
overloading
Runtime overloading is optional. Instead of passing params, a
pointer to a data structure is passed, and can also be returned.
This allows for an almost unlimited number of Call params and
Result params to be passed to/from a DFC.
DLL functions can be overloaded at runtime, by including an OverloadDef param, and passing a pointer to a Call params structure. A pointer for any Result params can be returned. OverloadDef in an integer enum value to indicate which version of the overloaded function to use. Various structures are used depending on which OverloadDef is being used.
the actual exported function
MyFunction(OverloadDef: integer; CallParams: pointer) ResultParams: pointer; stdcall;OverloadDefs for MyPlugin - note the multiple result params:
MP_DoThis(value: integer)state1: boolean; state2: boolean; value1:integer
MP_DoThat(Value1, value2, value3: integer)value1: integer;
MP_DoSomethingElse(value: integer: text: PChar)text: PChar; value1: integer;sample structures for MP_DoThis
type Call_MP_DoThis = record
value: integer;
end;type Result_MP_DoThis = record;
state1: boolean;
state2: boolean;
value1:integer
end;Example usage:
This tells the function which overload version to use, passes the params in the Call structure, and recieves the results in the Result structure. The actual internal overload routing is performed by checking the OverloadDef value and using case statements.@Result_MP_DoThis := MyFunction(MP_DoThis, @Call_MP_DoThis);
plugin events
When implementing events, two actions must be taken into account:
the ability to assign an event handler, and the ability to
trigger an event handler. To trigger an event, the user should be
able to simply call the event with no parameters. To assign an
event handler, the handler code must pass its' proc addr to the
event trigger code.
When an event is triggered, the program flow jumps to the proc addr/method pointer that was assigned to this event. If you can get a proc address, you can jump to it. Pass one of your own proc addrs, and another plugin can execute you code - that is how you code DLL events.
In this example, MyPlugin assigns one of its' internal methods (MyCustomMouseOver) as the event handler for InputPlugin's OnMouseOver event. Since we are working with dynamically loaded DLLs, MyPlugin has already retrieved the OnMouseOver ProcAddress by calling GetDFC. The event is a runtime overloaded function, so we tell it which version of the func we will be using, and pass pointers to the Call and Result parameters. The code could be simpler, by having the EventHandler porc addr passed in the original exported function, and doesn't have any Result params, but this example merely illustrates how to pass a group of parameters to a function via a structure.
Here is InputPlugin's exported function > OnMouseOver(OverloadDef: integer; CallParams: pointer); stdcall;
Overload enums > WFZ_AssignEvent, WFZ_TriggerEvent
Here are the Call Params and Result Params (none) for each overloaded func, which are passed as a pointer to a structure that contains these params.
WFZ_AssignEvent > (EventHandler: pointer);
WFZ_TriggerEvent > ( );
[MyPlugin ]
type TProc = procedure();
type TAssignEventOverload = record
EventHandlerAddr: pointer;
end;const eMP_CannotGetEventDFC = 1;
var eventDFC : TProc;
MyHandler: TAssignEventOverload;// get proc addr
@eventDFC := nil; // always do this to so can tell if assigned properly
@eventDFC := GetDFC(PluginHandle, PChar("OnMouseOver')); // get the proc
if @eventDFC = nil then SetError(eMP_CannotGetEventDFC);
//
// assign event handler
MyHandler.EventHandlerAddr := @MyCustomMouseOver;
eventDFC(WFZ_AssignEvent, @MyHandler);
//
// trigger event
eventDFC(WFZ_TriggerEvent, nil);
kernel functions
function
GetApplicationHandle( ): LongWord; stdcall;
This returns the Application Handle, which may be
required by some plugins for display of separate windows.
var hnd: longword;
inst := GetApplicationHandle;
function
GetApplicationInstance( ): Longint; stdcall;
This returns the Application Instance which may be
required by some plugins.
var inst: longint;
inst := GetApplicationInstance;
function
GetApplicationPath( ); stdcall;
This returns the path for the currently executing main
application. A final "\" is present in the path. In
this example, the main application's path is retrieved from the
kernel, and copied to a label's caption.
var p: PChar;
GetAppPath;
p:= GetWFZBuffer;
Label1.Caption := string(p); // "Label1.Caption := StrPas(p)" is also valid.
function
GetEnvironmentState( ): Integer; stdcall;
This returns the current environment state for the
kernel. If the kernel is offline, then all kernel functions exit
with a zero result. The environment state can only be changed by
restarting the kernel.
var x: integer;
x := GetEnvironmentState;
if x = esRuntime then Label1.Caption := 'Kernel environment is runtime.' ;
function GetFrameRate( ):Integer;
stdcall;
This returns the current frame rate for the currently
executing application. A single "frame" includes
multiple activities, such as: scene rendering, display to the
screen, audio output, etc. The current frame rate is equal to how
many render events have occured divided by the number of seconds
that have elapsed since the kernel started up, i.e. the average
frames per second. To increment the number of frames rendered,
call IncFramesRendered.
var x: integer;
x := GetFrameRate;
function GetFramesRendered():Integer;
stdcall;
Returns the total number of frames that have been
rendered since kernel startup. To increment the value, call
IncFramesRendered.
var x: integer;
x := GetFramesRendered;
function GetGameState():
Integer; stdcall;
Returns an integer value representing the current game
state.
Game state values:
gsOffline = 0;
gsStartup = 1;
gsIntro = 2;
gsDemo = 3;
gsPlaying = 4;
gsPaused = 5;
gsGameOver = 6;
gsRuntime = 7;var x: integer;
x := GetGameState;
if x = gsDemo then Label1.Caption := ' Demo is running.' ;
function GetKernelVersion():
Integer; stdcall;
Returns the current version of the kernel as an integer.
Version 2.0.0.0 would be returned as $02000000;
var x: integer;
x := GetKernelVersion;
procedure GetOSPath();
stdcall;
This returns the path for the current operating system,
generally "C:\Windows\". A final "\" is
present in the path. In this example, the OS path is retrieved,
and copied to a label's caption. p never needs to be allocated /
deallocated because we use it merely as a pointer to the buffer,
this is required on order to typecast the PChar to a string.
var p: PChar;
GetOSPath;
p:= GetWFZBuffer;
Label1.Caption := string(p); // "Label1.Caption := StrPas(p)" is also valid.
procedure GetOSSystemPath();
stdcall;
This returns the path for the system directory of the
current operating system, generally "C:\Windows\System\".
A final "\" is present in the path. In this example,
the OS system path is retrieved, and copied to a label's caption.
p never needs to be allocated / deallocated because we use it
merely as a pointer to the buffer, this is required on order to
typecast the PChar to a string.
var p: PChar;
GetOSSystemPath;
p:= GetWFZBuffer;
Label1.Caption := string(p); // "Label1.Caption := StrPas(p)" is also valid.
function GetWFZError( ):
Integer; stdcall;
This returns the most recent error code. When calling a
plugin function that may cause errors, always check the value of
ErrorCode to ensure that no errors have occurred.
var x: integer;
x := GetWFZError;
if x := eWFZK_NoErrors then Label1.Caption := ' No errors.' ;
procedure
IncFramesRendered(); stdcall;
Increments the kernel's internal frame counter. Call
this function after a frame has been rendered. The frames
rendered value is used by the GetFrameRate and GetFramesRendered
functions
var x: integer;
IncFramesRendered;
x := GetFramesRendered;
procedure
SetWFZError(Error: Integer); stdcall;
This sets the kernel internal error code to the desired
value. This is used by plugins (and the kernel) to indicate that
an error has occurred while processing a function call. In this
example, the SmoothPlugin sets the error code (an enumerated
integer value) to indicate an error in one of SmoothPlugin's
functions.
SetWFZError(eSP_NotSoSmoothError);
procedure
SetGameState(GameState: Integer); stdcall;
Sets the game state value to GameState. In this example,
game state is set to paused.
Game state values:
gsOffline
gsStartup
gsIntro
gsDemo
gsPlaying
gsPaused
gsGameOver
gsRuntimeSetGameState(gsPaused);
function
StartupKernel(AppPath: PChar; AppInstance: Longint; AppHandle:
LongWord; EnvironmentState: Integer): Pointer; stdcall;
Before plugins may be loaded, the kernel must be
initialized by the main application. The main application passes
its' handle, instance, and path info to the kernel. The kernel
returns a pointer to the ShutdownKernel function, this ensures
that only the app that started the kernel can shut it down.
AppPath must include a final '\' at the end. EnvironmentState
tells the kernel wheteher you would like it to be in runtime,
design-time, etc. Once set, the environment state cannot be
changed without shutting down and restarting the kernel. Remember to check
GetWFZError when calling this function.
At shutdown, the kernel unloads any plugins that may currently be loaded. Internally, it calls UnloadPlugin so that all loaded plugins can save any necessary data before being unloaded. All kernel functions, except StartupKernel, are disabled after shutdown and will return a zero result if called.
Environment state values:
esDesign
esOffline
esRuntime
In this example, StartupKernel is called with the required values. Environmnet state is et to esRuntime. The OS ans OS System path are retrieved and displayed in label captions. Finally, ShutdownKernel is checked to see if it contains an address, and then it is called to shutdown the kernel. Remember to set ShutdownKernel to nil, before calling StartupKernel.
type ShutdownKernel = procedure(); stdcall;
var p: pchar;
@ShutdownKernel := nil;
@ShutdownKernel := StartupKernel(PChar(ExtractFilePath(Application.EXEName)), HInstance, Application.Handle, esRuntime);
GetOSPath;
p:= GetWFZBuffer;
Label2.Caption := 'OSPath: ' + string(p);
GetOSSystemPath;
p:= GetWFZBuffer;
Label2.Caption := Label2.Caption + '...' + string(p); // display both paths on same line
Label3.Caption := 'Startup Kernel: OK.';
if @ShutdownKernel = nil then Label3.Caption:='StartupKernel: Error!'
ShutdownKernel;
Plugin functions
function
PluginAvailable(PluginName: PChar): integer; stdcall;
Returns a value indicating whether PluginName is
currently loaded, and if it resides in the main application's
directory. PluginAvailable will not search anywhere else except
the main appp's directory. PluginName does not contain path info,
only the name of the plugin itself. In this example, the kernel
is queried about the plugin named 'SmoothPlugin'. Remember to check
GetWFZError when calling this function.
var x: integer;
x := PluginAvailable(PChar('SmoothPlugin'));
result values:
WFZK_PluginNotFound
WFZK_PluginLoaded
WFZK_PluginOnAppPath
function
GetDFC(PluginHandle: LongWord; DFC: PChar): Pointer; stdcall;
All plugin functions are dynamically loaded, so your
plugin must query for the proc address of any other plugin
functions it requires. PluginHandle is a handle to the plugin,
previously returned by a call to LoadPlugin. DFC is the name of
the desired plugin function. Remember to check GetWFZError when
calling this function.
In this example, a plugin is loaded, and its' handle is used to
get the DFC "DisplayAnimationSplash" . Finally, the
plugin is unloaded.
var PluginHandle: longword;
DFCAddr: pointer;PluginHandle := LoadPlugin(PChar("C:\Program Files\wildfireZ\SmoothPlugin.wfz'), WFZK_DynamicPlugin);
DFCAddr := GetDFC(PluginHandle, PChar('DisplaySplashAnimation'));
UnloadPlugin(PChar('SmoothPlugin'));
function
GetPluginCount(): Integer; stdcall;
Returns the number of plugins currently loaded.
var x: integer;
x := GetPluginCount;
function
LoadPlugin(PluginName: PChar; LoadModel: Integer): LongWord;
stdcall;
This function loads and initializes the named plugin and
returns a handle for that plugin. Plugin name must include the
path information for the location of the plugin. Duplicate plugin
names are not allowed. In the event that the plugin to be loaded
has the same name as an already loaded plugin, the new plugin
will not be loaded and an error will occur. Plugins have two
different load models: Resident model is for plugins needed for
the entire time the kernel is active, and can only be unloaded at
kernel shutdown. Attempting to unload a resident plugin with
UnloadPlugin will result in an error. Dynamic model is for
plugins that are only needed temporarily, and they can be
unloaded at any time by calling UnloadPlugin. Remember to check
GetWFZError when calling this function.
var PluginHandle: longword;
PluginHandle := LoadPlugin(PChar("C:\Program Files\wildfireZ\SmoothPlugin.wfz'), WFZK_DynamicPlugin);
procedure
UnloadPlugin(PluginName: PChar); stdcall;
Unloads a plugin which is currently loaded. PluginName
is a the name of the plugin without the path
info. Plugins have two different load models: Resident model is
for plugins needed for the entire time the kernel is active, and
can only be unloaded at kernel shutdown. Attempting to unload a
resident plugin with UnloadPlugin will result in an error.
Dynamic model is for plugins that are only needed temporarily,
and they can be unloaded at any time by calling UnloadPlugin. Remember to check
GetWFZError when calling this function.
UnloadPlugin(PChar('SmoothPlugin'));
Buffer
functions
Generally, when
working with PChars, the calling functions must query for the
length of the PChar, and then be responsible for allocating and
deallocating memory for the PChar. The wildfireZ plugins kernel
provides an easy way to move PChars to/from functions, by using a
buffer dedicated solely for this purpose. The buffer exists once
StartupKernel is called, and is automatically freed at kernel
shutdown.
Call GetWFZBuffer to get a pointer to the block of memory used by the buffer. You are still responsible for copying the PChar to/from the buffer, but memory management is no longer a concern. If a PChar is larger than 8192 bytes, you will need to adjust the size of the buffer using the provided functions. Afterwards, you should reset the buffer back to it's default size by calling ClearWFZBuffer. The length of the PChar is stored by calling SetWFZBufferContentsSize, because the length of the PChar and the length of the buffer are rarely the same.
CAVEATS: The PChar copied to the buffer must have a null char at the end. The length of the PChar stored with SetWFZBufferContentsSize must be equal to the length plus the null char at the end - i.e. length+1.
procedure
ClearWFZBuffer(); stdcall;
Resets the buffer's size to 8192 bytes and zeroes out
the entire block of memory.
ClearWFZBuffer;
function
GetWFZBuffer(): Pointer; stdcall;
Returns a pointer to the block of memory used by the
buffer. Use this value as the PChar pointer value when reading
and writing PChars. The PChar copied to the buffer must
have a null char at the end. The length of the PChar
stored with SetWFZBufferContentsSize must be equal to the
length plus the null char at the end - i.e. length+1. In
this example, the main application's path is retrieved from the
kernel, and copied to a label's caption.
var p: PChar;
GetAppPath;
p:= GetWFZBuffer;
Label1.Caption := string(p); // "Label1.Caption := StrPas(p)" is also valid.
function
GetWFZBufferContentsSize(): integer; stdcall;
Returns the current size of the PChar (including the
null char at the end) residing in the WFZ buffer. The default
size of the buffer is 8192 bytes, so any PChar smaller than this
must have its' length stored by calling SetWFZBufferContentsSize.
In this example, the size value of the PChar residing in the
buffer is converted to a string and added to a label's caption.
var x: integer;
x := GetWFZBufferContentsSize;
Label1.Caption := IntToStr(x);
function
GetWFZBufferSize(): integer; stdcall;
Returns the current size of the WFZ buffer in bytes,
which will never be smaller than 8192 bytes. In this example, the
buffer size value is converted to a string and added to a label's
caption.
var x: integer;
x := GetWFZBufferSize;
Label1.Caption := IntToStr(x);
procedure
SetWFZBufferContentsSize(Size: integer); stdcall;
Used to store the length value of a PChar that resides
in the WFZ buffer. In this example, a string is copied to the
buffer, and the length of the string is stored using
SetWFZBufferContentsSize. The PChar copied to the buffer must
have a null char at the end. The length of the PChar
stored with SetWFZBufferContentsSize must be equal to the
length plus the null char at the end - i.e. length+1.
var text: string;
text := ' Want to rule the world? Take a number. There's a really long line. ' ;
ClearWFZBuffer;
StrPCopy(GetWFZBuffer, text); // copies string to buffer and adds a null char at end
SetWFZBufferContentsSize(Length(text) +1 ); // the null char MUST ALWAYS be included in the length !!!
procedure
SetWFZBufferSize(Size: integer); stdcall;
Resizes the WFZ buffer to a length of Size bytes. Size
must be an integer value greater than 8192 bytes, because the
buffer cannot be set to a size smaller than 8192 bytes. If a
function must set the buffer to a larger size, it should reset
the size after it is finished using the buffer, by calling
ClearWFZBuffer. This example sets the buffer to 86000 bytes and
then resets it back to its' standard buffer size.
SetWFZBuffer(86000);
...
... // perform various functions
...
ClearWFZBuffer;
Hires-DateTime
functions
Ever received an
email from the future? You know, the ones that have time stamps a
few hours ahead of your local time.
The HiresDateTime structure was designed to work around this flaw, by incorporating local time zone info into itself. This allows a HiresDateTime value to be easily converted to your local time and date. For example, if you receive a file with a time stamp of 8:04 AM and the sender is 3 hours ahead of your time zone, that time would be converted to 5:04 AM - the equivalent local time when the file was created. More info on the HiresDateTime structure can be found here.
The HiresDateTime structure is based on a 24 clock originating at the International Date Line (IDL), unlike Greenwich Mean Time (GMT), which is based on a 12 hour clock. The GMT was somewhat mucky to covert to/from, so IDL was used instead. NOTE: All time zone information must be converted from GMT to IDL before adding it to the HiresDateTime structure. More info on IDL time zones can be found here.
function ConvertGMTToIDL(GMTOffset:
Integer): Integer; stdcall;
Converts a +/- 12 hour based GMT time zone offset to a
24 hour (aka military time) IDL time zone offset.
var timeGMT, timeIDL: integer;
timeIDL := ConvertGMTToIDL(timeGMT);
function ConvertIDLToGMT(IDLOffset:
Integer): Integer; stdcall;
Converts a 24 hour (aka military time) IDL time zone offset to a
+/- 12 hour based GMT time zone offset.
var timeGMT, timeIDL: integer;
timeGMT := ConvertIDLToGMT(timeIDL);
function
ConvertToLocalDateTime(UDT: TUnpackedHiresDateTime):
TUnpackedHiresDateTime; stdcall;
Converts a given date and time to the local time zone
equivalent date and time. Useful for finding out when something
was created, relative to your own local time. Example: if a file
was created at 6:15 PM in a time zone 2 hours behind your current
one, then the file would have been created at 8:15 PM your time -
(6:15 pm plus 2 hour difference between time zones). The
HiresDateTime structure returned will have an IDL/IDL minutes
offset equal to the current system offsets.
var UDT, LocalUDT: TUnpackedHiresDateTime;
LocalUDT := Convert ToLocalDatTime(UDT);
function
DecodeHiresDateTime(HiresDateTime: THiresDateTime):
TUnpackedHiresDateTime; stdcall;
Uncompresses a packed HiresdateTime structure into an
easier to manipulate TUnpackedHiresDateTime structure. More info
TUnpackedHiresDateTime data fields can be found here.
var UHDT: TUnpackedHiresDateTime;
HDT: THiresDateTime;UHDT := DecodeHiresDateTime(HDT);
function
EncodeHiresDateTime(UnpackedDateTime: TUnpackedHiresDateTime):
THiresDateTime; stdcall;
Compresses a TUnpackedHiresDateTIme data structure into
a compact 96-bit value. NOTE: All time zone information must be
converted from GMT to IDL before adding it to the HiresDateTime
structure. Remember to check GetWFZError when calling
this function.
var UHDT: TUnpackedHiresDateTime;
HDT: THiresDateTime;HDT := EncodeHiresDateTime(UHDT);
function
GetCurrentHiresDateTime( ): TUnpackedHiresDateTime; stdcall;
Returns the current hi-resolution date and time for the
local system. In this example, the current HiresDateTime is
retreived, and the individual fields within it are converted to
strings and added to a listbox.
varTempUDT: TUnpackedHiresDateTime;
ListBox1: TListBox;TempUDT := GetCurrentHiresDateTime;
ListBox1.Items.Add('Year: '+IntToStr(TempUDT.Year));
ListBox1.Items.Add('Month: '+IntToStr(TempUDT.Month));
ListBox1.Items.Add('Day: '+IntToStr(TempUDT.Day));
ListBox1.Items.Add('GMTOffset: '+IntToStr(TempUDT.IDLOffset));
ListBox1.Items.Add('GMTMinutesOffset: '+IntToStr(TempUDT.IDLMinutesOffset));
case TempUDT.DayOfWeek of
1: ListBox1.Items.Add('DayOfWeek: Sunday');
2: ListBox1.Items.Add('DayOfWeek: Monday');
3: ListBox1.Items.Add('DayOfWeek: Tuesday');
4: ListBox1.Items.Add('DayOfWeek: Wednesday');
5: ListBox1.Items.Add('DayOfWeek: Thursday');
6: ListBox1.Items.Add('DayOfWeek: Friday');
7: ListBox1.Items.Add('DayOfWeek: Saturday');
end;
ListBox1.Items.Add('Hour: '+IntToStr(TempUDT.Hour));
ListBox1.Items.Add('Minute: '+IntToStr(TempUDT.Minute));
ListBox1.Items.Add('Second: '+IntToStr(TempUDT.Second));
ListBox1.Items.Add('Tick: '+IntToStr(TempUDT.Tick));
function GetIDLOffset( ):
Integer; stdcall;
Returns the IDL time zone offset for this system. Always
a value between 1and 24, and is equivalent to the time zone in
which the local system resides. More info
on IDL time zones can be found here.
var offset: integer;
offset := GetIDLOffset;
function
GetIDLMinutesOffset( ): Integer; stdcall;
Returns the IDL minutes offset for this system. Usually
zero except for a few territories, which may have a time zone
offset of 15 or 30 minutes.
var minutes: integer;
minutes := GetIDLMinutesOffset;
function
IsLocalHiresDateTime(HiresDateTime: THiresDateTime): Boolean;
stdcall;
Fast method to determine if a compressed HiresDateTime
structure has the same time zone information as the current local
system, i.e. both are in the same time zone. There is no need to
uncompress the HiresDateTime structure, this function works
directly on the compressed structure by checking individual bits.
Returns True if both are in the same time zone, and False if they
are different time zones.
var HDT: THiresDateTime;
State: Boolean;State := IsLocalHiresDateTime(HDT);
Elapsed Time
functions
An elapsed time counter is used instead of a Window's timer,
because the Window's timer is to slow for demanding applications,
such as games. Instead, an elapsed time counter is used, which
has a time resolution of around .5 - 1 microseconds on a 233 MHz
Pentium system, whereas the internal Window's timer has a
resolution of about 50 milliseconds. The elapsed time counter
does not trigger an event that plugins or the main application
can respond to. The value must be queried and then compared to
perevious values to determine if enough time has passed to
perform the next action, such as animating a frame of animation.
function
GetElapsedTimeCount( ): Int64; stdcall;
This returns the current value for the Windows high
frequency counter. This value can be compared to a previously
retrieved count value in order to determine how much time has
elapsed between the two counts. Divide by the elapsed time
frequency for this particular system to determine how many
seconds have passed. In the example, x will contain the number of
seconds that have passed since time1 was called.
var x, time1, time2: int64;
time1 := GetElapsedTimeCount;
time2 := GetElapsedTimeCount;
x := (time2 - time1) DIV GetElapsedTimeFrequency;
function
GetElapsedTimeFrequency( ): Int64; stdcall;
This returns the elapsed time frequency, the number of
count ticks that occur per second, for this particular system.
For a Pentium 233 MHz system, the average tick count is around 1-2
MHz. Divide this value into the various elapsed time values to
convert to seconds.
var x: int64;
x := GetElapsedTimeFrequency;
function
IsElapsedTimeAvailable( ): Boolean; stdcall;
This returns a boolean value indicating whether or not
the elapsed time counter is available on this particular system.
True indicates that it is available, False means that it is not
available.
var State: Boolean;
State := IsElapsedTimeAvailable;
function
GetStartupElapsedTime( ): Int64; stdcall;
This returns the number of ticks of the Windows high
frequency counter that have occurred since the kernel was started.
i.e. how long the kernel has been active. In the example, x will
contain the number of seconds that have passed since the kernel
was started, by dividing the elapsed time value by the count
frequency. X will be a whole number, to get the fractional
remainder, use MOD instead of DIV.
var x: int64;
x := GetStartupElapsedTime DIV GetElapsedTimeFrequency;
function GetStartupTime( ):
Int64; stdcall;
When the kernel is started, it gets the current value
from the Windows high frequency counter. This function returns
that tick count.
var x: int64;
x := GetStartupTime;
misc functions
function
GetRandomNumber(Range: Integer): Integer; stdcall;
Generates a random 32-bit number within the range of 0
and Range-1. Range must be a value greater than 1, or the
function will return a value of zero. In the example, x will
contain a value in the range of 0-12344.
var x: integer;
x := GenerateRandomNumber(12345);