BlitzPointer 1.1

- Added and updated examples for more advanced usage.
- Added Direct Memory Access (DMA) functions, use with caution.
- Fixed a backwards instruction jump caused by using __cdecl instead of __stdcall.
- Removed string return type as it caused an unsolvable memory leak.
This commit is contained in:
Michael Fabian Dirks
2015-05-17 11:49:46 +02:00
parent 57cb1642c4
commit 38af4e7491
18 changed files with 845 additions and 608 deletions
+16 -121
View File
@@ -1,7 +1,22 @@
.lib "BlitzPointer.dll"
; Memory Modification
PeekMemoryByte%(lpMemoryPointer%)
PeekMemoryShort%(lpMemoryPointer%)
PeekMemoryInt%(lpMemoryPointer%)
PeekMemoryFloat#(lpMemoryPointer%)
PeekMemory(lpMemoryPointer%, iLength%, lpBank*)
PokeMemoryByte(lpMemoryPointer%, value%)
PokeMemoryShort(lpMemoryPointer%, value%)
PokeMemoryInt(lpMemoryPointer%, value%)
PokeMemoryFloat(lpMemoryPointer%, value#)
PokeMemory(lpMemoryPointer%, iLength%, lpBank*)
; BlitzPointer
BlitzPointer_GetReturnAddress%()
BlitzPointer_GetFunctionPointer%()
; Function Calling
BlitzPointer_CallFunctionV(lpFunctionPointer%) : "BlitzPointer_CallFunction0"
BlitzPointer_CallFunctionVI(lpFunctionPointer%, P1%) : "BlitzPointer_CallFunction1"
BlitzPointer_CallFunctionVII(lpFunctionPointer%, p1%, p2%) : "BlitzPointer_CallFunction2"
@@ -365,124 +380,4 @@ BlitzPointer_CallFunctionFPPP#(lpFunctionPointer%, p1*, p2*, p3*) : "BlitzPointe
BlitzPointer_CallFunctionFPPPI#(lpFunctionPointer%, p1*, p2*, p3*, p4%) : "BlitzPointer_CallFunction4"
BlitzPointer_CallFunctionFPPPF#(lpFunctionPointer%, p1*, p2*, p3*, p4#) : "BlitzPointer_CallFunction4"
BlitzPointer_CallFunctionFPPPP#(lpFunctionPointer%, p1*, p2*, p3*, p4*) : "BlitzPointer_CallFunction4"
BlitzPointer_CallFunctionS$(lpFunctionPointer%) : "BlitzPointer_CallFunctionS0"
BlitzPointer_CallFunctionSI$(lpFunctionPointer%, P1%) : "BlitzPointer_CallFunctionS1"
BlitzPointer_CallFunctionSII$(lpFunctionPointer%, p1%, p2%) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSIII$(lpFunctionPointer%, p1%, p2%, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIIII$(lpFunctionPointer%, p1%, p2%, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIIF$(lpFunctionPointer%, p1%, p2%, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIIP$(lpFunctionPointer%, p1%, p2%, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIF$(lpFunctionPointer%, p1%, p2%, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIIFI$(lpFunctionPointer%, p1%, p2%, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIFF$(lpFunctionPointer%, p1%, p2%, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIFP$(lpFunctionPointer%, p1%, p2%, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIP$(lpFunctionPointer%, p1%, p2%, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIIPI$(lpFunctionPointer%, p1%, p2%, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIPF$(lpFunctionPointer%, p1%, p2%, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIIPP$(lpFunctionPointer%, p1%, p2%, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIF$(lpFunctionPointer%, p1%, p2#) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSIFI$(lpFunctionPointer%, p1%, p2#, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIFII$(lpFunctionPointer%, p1%, p2#, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFIF$(lpFunctionPointer%, p1%, p2#, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFIP$(lpFunctionPointer%, p1%, p2#, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFF$(lpFunctionPointer%, p1%, p2#, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIFFI$(lpFunctionPointer%, p1%, p2#, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFFF$(lpFunctionPointer%, p1%, p2#, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFFP$(lpFunctionPointer%, p1%, p2#, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFP$(lpFunctionPointer%, p1%, p2#, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIFPI$(lpFunctionPointer%, p1%, p2#, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFPF$(lpFunctionPointer%, p1%, p2#, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIFPP$(lpFunctionPointer%, p1%, p2#, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIP$(lpFunctionPointer%, p1%, p2*) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSIPI$(lpFunctionPointer%, p1%, p2*, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIPII$(lpFunctionPointer%, p1%, p2*, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPIF$(lpFunctionPointer%, p1%, p2*, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPIP$(lpFunctionPointer%, p1%, p2*, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPF$(lpFunctionPointer%, p1%, p2*, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIPFI$(lpFunctionPointer%, p1%, p2*, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPFF$(lpFunctionPointer%, p1%, p2*, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPFP$(lpFunctionPointer%, p1%, p2*, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPP$(lpFunctionPointer%, p1%, p2*, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSIPPI$(lpFunctionPointer%, p1%, p2*, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPPF$(lpFunctionPointer%, p1%, p2*, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSIPPP$(lpFunctionPointer%, p1%, p2*, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSF$(lpFunctionPointer%, P1#) : "BlitzPointer_CallFunctionS1"
BlitzPointer_CallFunctionSFI$(lpFunctionPointer%, p1#, p2%) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSFII$(lpFunctionPointer%, p1#, p2%, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFIII$(lpFunctionPointer%, p1#, p2%, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIIF$(lpFunctionPointer%, p1#, p2%, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIIP$(lpFunctionPointer%, p1#, p2%, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIF$(lpFunctionPointer%, p1#, p2%, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFIFI$(lpFunctionPointer%, p1#, p2%, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIFF$(lpFunctionPointer%, p1#, p2%, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIFP$(lpFunctionPointer%, p1#, p2%, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIP$(lpFunctionPointer%, p1#, p2%, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFIPI$(lpFunctionPointer%, p1#, p2%, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIPF$(lpFunctionPointer%, p1#, p2%, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFIPP$(lpFunctionPointer%, p1#, p2%, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFF$(lpFunctionPointer%, p1#, p2#) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSFFI$(lpFunctionPointer%, p1#, p2#, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFFII$(lpFunctionPointer%, p1#, p2#, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFIF$(lpFunctionPointer%, p1#, p2#, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFIP$(lpFunctionPointer%, p1#, p2#, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFF$(lpFunctionPointer%, p1#, p2#, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFFFI$(lpFunctionPointer%, p1#, p2#, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFFF$(lpFunctionPointer%, p1#, p2#, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFFP$(lpFunctionPointer%, p1#, p2#, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFP$(lpFunctionPointer%, p1#, p2#, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFFPI$(lpFunctionPointer%, p1#, p2#, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFPF$(lpFunctionPointer%, p1#, p2#, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFFPP$(lpFunctionPointer%, p1#, p2#, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFP$(lpFunctionPointer%, p1#, p2*) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSFPI$(lpFunctionPointer%, p1#, p2*, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFPII$(lpFunctionPointer%, p1#, p2*, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPIF$(lpFunctionPointer%, p1#, p2*, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPIP$(lpFunctionPointer%, p1#, p2*, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPF$(lpFunctionPointer%, p1#, p2*, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFPFI$(lpFunctionPointer%, p1#, p2*, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPFF$(lpFunctionPointer%, p1#, p2*, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPFP$(lpFunctionPointer%, p1#, p2*, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPP$(lpFunctionPointer%, p1#, p2*, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSFPPI$(lpFunctionPointer%, p1#, p2*, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPPF$(lpFunctionPointer%, p1#, p2*, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSFPPP$(lpFunctionPointer%, p1#, p2*, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSP$(lpFunctionPointer%, P1*) : "BlitzPointer_CallFunctionS1"
BlitzPointer_CallFunctionSPI$(lpFunctionPointer%, p1*, p2%) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSPII$(lpFunctionPointer%, p1*, p2%, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPIII$(lpFunctionPointer%, p1*, p2%, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIIF$(lpFunctionPointer%, p1*, p2%, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIIP$(lpFunctionPointer%, p1*, p2%, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIF$(lpFunctionPointer%, p1*, p2%, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPIFI$(lpFunctionPointer%, p1*, p2%, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIFF$(lpFunctionPointer%, p1*, p2%, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIFP$(lpFunctionPointer%, p1*, p2%, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIP$(lpFunctionPointer%, p1*, p2%, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPIPI$(lpFunctionPointer%, p1*, p2%, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIPF$(lpFunctionPointer%, p1*, p2%, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPIPP$(lpFunctionPointer%, p1*, p2%, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPF$(lpFunctionPointer%, p1*, p2#) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSPFI$(lpFunctionPointer%, p1*, p2#, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPFII$(lpFunctionPointer%, p1*, p2#, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFIF$(lpFunctionPointer%, p1*, p2#, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFIP$(lpFunctionPointer%, p1*, p2#, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFF$(lpFunctionPointer%, p1*, p2#, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPFFI$(lpFunctionPointer%, p1*, p2#, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFFF$(lpFunctionPointer%, p1*, p2#, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFFP$(lpFunctionPointer%, p1*, p2#, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFP$(lpFunctionPointer%, p1*, p2#, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPFPI$(lpFunctionPointer%, p1*, p2#, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFPF$(lpFunctionPointer%, p1*, p2#, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPFPP$(lpFunctionPointer%, p1*, p2#, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPP$(lpFunctionPointer%, p1*, p2*) : "BlitzPointer_CallFunctionS2"
BlitzPointer_CallFunctionSPPI$(lpFunctionPointer%, p1*, p2*, p3%) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPPII$(lpFunctionPointer%, p1*, p2*, p3%, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPIF$(lpFunctionPointer%, p1*, p2*, p3%, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPIP$(lpFunctionPointer%, p1*, p2*, p3%, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPF$(lpFunctionPointer%, p1*, p2*, p3#) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPPFI$(lpFunctionPointer%, p1*, p2*, p3#, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPFF$(lpFunctionPointer%, p1*, p2*, p3#, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPFP$(lpFunctionPointer%, p1*, p2*, p3#, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPP$(lpFunctionPointer%, p1*, p2*, p3*) : "BlitzPointer_CallFunctionS3"
BlitzPointer_CallFunctionSPPPI$(lpFunctionPointer%, p1*, p2*, p3*, p4%) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPPF$(lpFunctionPointer%, p1*, p2*, p3*, p4#) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionSPPPP$(lpFunctionPointer%, p1*, p2*, p3*, p4*) : "BlitzPointer_CallFunctionS4"
BlitzPointer_CallFunctionS$(lpFunctionPointer%) : "BlitzPointer_CallFunctionT0"
+3 -1
View File
@@ -3,7 +3,7 @@
Version="1"
Expanded="True"
Icon=""
MainFile="Example05.bb"
MainFile="Example07.bb"
Compiler="Blitz3D"
CommandLine=""
</Settings>
@@ -15,5 +15,7 @@
AbsPath="\Example03.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example04.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example05.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example06.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example07.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
AbsPath="\Example_Shared.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
</Files>
+4 -5
View File
@@ -1,5 +1,5 @@
; ---------------------------------------------------------------------------- ;
; Example 2 - Calling Functions
; Example 2 - Calling Functions (Beginner)
; ---------------------------------------------------------------------------- ;
; License: Creative Commons Attribution 2.0
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
@@ -25,10 +25,9 @@ OurFunction()
While Not KeyHit(1)
ExampleUpdate()
; BlitzPointer offers many (one-thousand-three-hundred-sixty-four) ways of
; calling our function pointer. Each one describes different return types,
; parameter count and parameter types. Let's use the one that doesn't return
; a value (V for void) for now.
; BlitzPointer offers many ways of calling our function pointer. Each one
; describes different return types, parameter count and parameter types.
; Let's use the one that doesn't return a value for now.
BlitzPointer_CallFunctionV fpOurFunction
; Now if we run the program, instead of a fixed native call, we're calling a
; function pointer instead. Pretty useful in my opinion, especially for UI,
+9 -25
View File
@@ -5,21 +5,20 @@
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
; Prerequisite: Example 2
; As said before, BlitzPointer offers one-thousand-three-hundred-sixty-four ways
; of calling our function pointer. Each one describes return type, parameter
; count and parameter types. So, what magic can we do with those?
; BlitzPointer offers a lot of ways to call our function pointer. Each one
; describes return type, parameter count and parameter types.
; So, what magic can we do with those?
; There are four return types in Blitz that we can use:
; BlitzPointer supports three return types:
; ---------------------------------------------------------------------------- ;
; Type Id Description Calling Function
; ---------------------------------------------------------------------------- ;
; void V Nothing BlitzPointer_CallFunctionV
; int I 32-bit Integer BlitzPointer_CallFunctionI
; float F Floating Point BlitzPointer_CallFunctionF
; string S String BlitzPointer_CallFunctionS
;
; When returning strings we have to make sure that it is not 0-length, as Blitz
; doesn't know how to handle these and crashes with a Memory Access Violation.
; Now that we know what we can and can't do (without memory leaks at least),
; let's try out the return types ourselves.
Include "Example_Shared.bb"
ExampleInit()
@@ -35,6 +34,7 @@ Function VoidFunction()
End Function
VoidFunction()
; 'int' function
Global fpIntFunction = 0
Function IntFunction%()
If fpIntFunction = 0 Then
@@ -46,6 +46,7 @@ Function IntFunction%()
End Function
IntFunction()
; 'float' function
Global fpFloatFunction = 0
Function FloatFunction#()
If fpFloatFunction = 0 Then
@@ -57,22 +58,6 @@ Function FloatFunction#()
End Function
FloatFunction()
Global fpStringFunction = 0
Function StringFunction$()
If fpStringFunction = 0 Then
fpStringFunction = BlitzPointer_GetFunctionPointer()
Return
EndIf
Text 0, 45, "String Return Type"
Local T$ = ""
Local MS = MilliSecs()
T = (((MS / 1000) / 60) / 60) + ":" + RSet((((MS / 1000) / 60) Mod 60), 2) + ":" + RSet(((MS / 1000) Mod 60), 2) + "." + RSet(MS Mod 1000, 3)
Return T
End Function
StringFunction()
While Not KeyHit(1)
ExampleUpdate()
@@ -80,7 +65,6 @@ While Not KeyHit(1)
BlitzPointer_CallFunctionV(fpVoidFunction) ; void returns nothing.
Text 200, 15, BlitzPointer_CallFunctionI(fpIntFunction)
Text 200, 30, BlitzPointer_CallFunctionF(fpFloatFunction)
Text 200, 45, BlitzPointer_CallFunctionS(fpStringFunction)
ExampleLoop()
Wend
+12 -39
View File
@@ -5,13 +5,11 @@
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
; Prerequisite: Example 3
; We now know how to use return values correctly and thus have knowledge about
; the first 4 of 1364 functions to call a pointer.
; Now you know about 4 different ways of calling a Function, what about the
; other 1360 that are left? Those are combinations of return types, parameter
; count and parameter types.
; BlitzPointer supports functions with up to four parameters, given that all
; parameters have a supported type.
; Returned values aren't everything, don't you agree? That is why BlitzPointer
; offers you the ability to pass parameters too, even allowing you to pass Type
; Objects without having to use Handle() and Object() (both slow functions).
; At the time of writing this example, BlitzPointer supports four parameters at
; most - plenty of space to pass type objects and variables on.
; There are three parameter types in Blitz that we can use:
; ---------------------------------------------------------------------------- ;
@@ -19,11 +17,12 @@
; ---------------------------------------------------------------------------- ;
; int I 32-bit Integer BlitzPointer_CallFunction*I
; float F Floating Point BlitzPointer_CallFunction*F
; type I Type Object BlitzPointer_CallFunction*I
; pointer P Memory Pointer BlitzPointer_CallFunction*P
;
; We can't pass strings as parameters, but we can pass types as parameters,
; which allows us to pass strings in a type.
; Watch out:
; Calling a function that has parameters without giving enough parameters will
; fill those parameters with values that have been on the stack (and possibly
; corrupt the stack too - you never know).
Include "Example_Shared.bb"
ExampleInit()
@@ -58,37 +57,14 @@ Function CurInGameSecondEx#(p1%=0, p2#=0)
End Function
CurInGameSecondEx()
; Example Function: Work around the fact that Strings can't be passed.
Type MyType
Field Name$
Field Desc$
End Type
Local MT.MyType = New MyType
MT\Name = "Hello"
MT\Desc = "World"
Global fpDisplayMyType = 0
Function DisplayMyType(p1.MyType)
If fpDisplayMyType = 0 Then
fpDisplayMyType = BlitzPointer_GetFunctionPointer()
Return
EndIf
Text 5, 45, "VTFunction"
Text 125, 45, Hex(Int(p1))
If p1 <> Null Then
Text 245, 45, p1\Name
Text 365, 45, p1\Desc
EndIf
End Function
DisplayMyType(Null)
; Example Function: Convert between Float and Int easily
; For this to work we must take and return a float.
Global fpConvertIntFloat
Function ConvertIntFloat#(p1#=0)
If fpConvertIntFloat = 0 Then
fpConvertIntFloat = BlitzPointer_GetFunctionPointer()
Print Hex(fpConvertIntFloat)
WaitKey()
Return
EndIf
@@ -111,9 +87,6 @@ While Not KeyHit(1)
Text 605, 15, BlitzPointer_CallFunctionII(fpCurInGameSecond, Frame)
Text 605, 30, BlitzPointer_CallFunctionFIF(fpCurInGameSecondEx, Frame, 0.016666666)
; In order to pass a Type-object to a function, we need to get a pointer for it.
; Thankfully, Blitz can do this natively by calling Int() on it.
BlitzPointer_CallFunctionVI fpDisplayMyType, Int(MT)
Local TempFlt# = Frame / 60.0
Local TempInt% = BlitzPointer_CallFunctionIF(fpConvertIntFloat, TempFlt)
+33 -133
View File
@@ -1,158 +1,58 @@
; ---------------------------------------------------------------------------- ;
; Example 4 - Callbacks
; Example 5 - Calling Functions (Advanced)
; ---------------------------------------------------------------------------- ;
; License: Creative Commons Attribution 2.0
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
; Prerequisite: Example 4
; Now that we have learned how to use functions, let's go for something really
; advanced - Callbacks! We can use these to practically fake a OOP language.
; In Blitz, there are only three real types: Int, Float and String - anything
; else is a pointer that can be represented using Int. That is why almost all
; Blitz functions return an Int.
; Using this knowledge we can try (and succeed) passing a Type Object into a
; function - using nothing more than the Int() function.
Include "Example_Shared.bb"
ExampleInit()
; Let's create a Type to hold our generic object that only contains callback and
; a pointer to the type object. This allows us to have a generic interface that
; takes BObject and whatever type-object the user wants and returns weether or
; not the BObject should be destroyed.
Type BObject
Field DataCallback
Field DataValue%
; We'll have to define a Type that can be passed to our function, any Type will
; do fine.
Type MyType
Field Test
Field Name$
End Type
; Our Update loop looks like this, there's not much to do - after all we have
; the callbacks to do the dirty work for us.
Function BObjectUpdate()
Local Obj.BObject
For Obj.BObject = Each BObject
; Check if the Callback and Value is set.
If Obj\DataCallback <> 0 And Obj\DataValue <> 0 Then
; Our Callback tells us when we need to dispose of an object.
If BlitzPointer_CallFunctionIII(Obj\DataCallback, Int(Obj), Obj\DataValue)
Delete Obj
EndIf
Else
Delete Obj
EndIf
Next
End Function
; We'll have two different sub-objects:
; * BCube - Cubes with movement
; * BSphere - Randomly colored spheres
; BCube - Spawned when we press '1'
Type BCube
Field Entity
Field PosX#, PosY#, PosZ#
Field Time
End Type
; Our Callback for BCube - relatively simple.
Global fpBCubeCallback = 0
Function BCubeCallback%(Obj.BObject, Cube.BCube)
If fpBCubeCallback = 0 Then
fpBCubeCallback = BlitzPointer_GetFunctionPointer()
; The function can be defined like any other Blitz function.
Global fpMyTypeFunc = 0
Function MyTypeFunc(This.MyType)
If fpMyTypeFunc = 0 Then
fpMyTypeFunc = BlitzPointer_GetFunctionPointer()
Return
EndIf
If This = Null Then Return
Local Prc# = 1.0 - ((MilliSecs() - Cube\Time) / 5000.0)
PositionEntity Cube\Entity, Cube\PosX, Cos(Cube\PosX + Prc * 360) * Sin(Cos(Cube\PosZ) * 180 + Prc * 360) * 50, Cube\PosZ
EntityAlpha Cube\Entity, Prc
If Prc < 0.0 Then
FreeEntity Cube\Entity
Delete Cube
Return True
EndIf
Return False
; Display the content of the Type Object.
Text 0, Handle(This) * 15, This\Test + This\Name
End Function
BCubeCallback(Null, Null)
MyTypeFunc(Null)
Function BCubeCreate.BObject(X#, Y#, Z#)
Local Obj.BObject = New BObject
Obj\DataCallback = fpBCubeCallback
Local Cube.BCube = New BCube
Cube\Entity = CreateCube()
Cube\PosX = X
Cube\PosY = Y
Cube\PosZ = Z
Cube\Time = MilliSecs()
Obj\DataValue = Int(Cube)
Return Obj
End Function
; And create two testing objects.
Local MT1.MyType = New MyType
MT1\Test = 1
MT1\Name = "First Object"
; Our BSphere implementation, spawned when pressing 2
Type BSphere
Field Entity
Field StartColor[2]
Field EndColor[2]
Field Time
End Type
Global fpBSphereCallback = 0
Function BSphereCallback%(Obj.BObject, Sphere.BSphere)
If fpBSphereCallback = 0 Then
fpBSphereCallback = BlitzPointer_GetFunctionPointer()
Return
EndIf
Local Prc# = (MilliSecs() - Sphere\Time) / 5000.0
EntityColor Sphere\Entity, Sphere\StartColor[0] * (1.0 - Prc) + Sphere\EndColor[0] * Prc, Sphere\StartColor[1] * (1.0 - Prc) + Sphere\EndColor[1] * Prc, Sphere\StartColor[2] * (1.0 - Prc) + Sphere\EndColor[2] * Prc
EntityAlpha Sphere\Entity, 1.0 - Prc
If Prc >= 1.0 Then
FreeEntity Sphere\Entity
Delete Sphere
Return True
EndIf
Return False
End Function
BSphereCallback(Null, Null)
Function BSphereCreate.BObject(X#, Y#, Z#)
Local Obj.BObject = New BObject
Obj\DataCallback = fpBSphereCallback
Local Sphere.BSphere = New BSphere
Sphere\Entity = CreateSphere(2)
PositionEntity Sphere\Entity, X, Y, Z
Sphere\StartColor[0] = Rand(0, 255)
Sphere\StartColor[1] = Rand(0, 255)
Sphere\StartColor[2] = Rand(0, 255)
Sphere\EndColor[0] = Rand(0, 255)
Sphere\EndColor[1] = Rand(0, 255)
Sphere\EndColor[2] = Rand(0, 255)
Sphere\Time = MilliSecs()
Obj\DataValue = Int(Sphere)
Return Obj
End Function
SeedRnd MilliSecs()
Local MT2.MyType = New MyType
MT2\Name = "Second Object"
While Not KeyHit(1)
;'1' spawns a few instances of BCube
If KeyHit(2) Then
For X = -100 To 100 Step 10
For Z = -100 To 100 Step 10
BCubeCreate(X, 0, Z)
Next
Next
EndIf
;'2' spawns a few instances of BSphere
If KeyHit(3) Then
Local O# = Rnd(-360, 360)
For R# = -180 To 180 Step 2.25
BSphereCreate(Cos(R+O)*100, Sin(R * 90) * 10 + 10, Sin(R+O)*100)
Next
EndIf
; We only need one function here, all other updates are done using callbacks.
BObjectUpdate()
ExampleUpdate()
; Now in order to pass a Type Object to a function, we have to get a pointer
; from it. Thankfully, Blitz has this already built in: Int().
If KeyDown(2) Then BlitzPointer_CallFunctionVI fpMyTypeFunc, Int(MT1)
If KeyDown(3) Then BlitzPointer_CallFunctionVI fpMyTypeFunc, Int(MT2)
ExampleLoop()
Wend
End
;~IDEal Editor Parameters:
;~C#Blitz3D
+103
View File
@@ -0,0 +1,103 @@
; ---------------------------------------------------------------------------- ;
; Example 6 - Direct Memory Access
; ---------------------------------------------------------------------------- ;
; License: Creative Commons Attribution 2.0
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
; Prerequisite: Example 5
; --!-!!!-!--
; This Example is aimed at Experts. You will most likely never need this.
; --!-!!!-!--
; BlitzPointer ships with functions for direct memory access, allowing you to
; modify things that were previously out of reach. The functions follow the
; typical style of Bank access, Peek and Poke:
; PeekMemoryByte%(MemoryAddress%) / PokeMemoryByte(MemoryAddress%, Value%)
; PeekMemoryShort%(MemoryAddress%) / PokeMemoryShort(MemoryAddress%, Value%)
; PeekMemoryInt%(MemoryAddress%) / PokeMemoryInt(MemoryAddress%, Value%)
; PeekMemoryFloat#(MemoryAddress%) / PokeMemoryFloat(MemoryAddress%, Value#)
; PeekMemory%(MemoryAddress%, Length%, Bank%) / PokeMemory%(MemoryAddress%, Length%, Bank%)
; This function allows you to directly read and write from memory into a Bank
; or from a Bank, saving you a few instructions per access. It will only read
; or write as many bytes as your Bank holds and returns the amount of read or
; written bytes.
; These allow us to do simple direct memory modification, allowing us to do some
; things that were previously only possible using MemMove and MemCopy from
; the Windows libraries.
; For example, Types in Blitz follow this structure:
; ---------------------------------------------------------------------------- ;
; Offset Type Description
; ---------------------------------------------------------------------------- ;
; 0 Pointer Pointer to Field Data
; 4 Pointer Next Type Object or Type Structure (Last Element Signal)
; 8 Pointer Prev Type Object or Type Structure (First Element Signal)
; 12 Pointer Type Structure
; 16 Integer Reference Count
; 20+ ... Your Field Data usually follows here.
;
; We can do some fun stuff with this information.
; If you want to know more about the internal structure of Blitz, there are some
; resources that people have compiled in addition to the official source:
; Structures: http://www.blitzforum.de/forum/viewtopic.php?t=4320
; Source Code: http://github.com/blitz-research/
Include "Example_Shared.bb"
ExampleInit()
; Our Type will hold one of every Element.
Type EverythingType
Field MyInt%
Field MyFloat#
Field MyString$
Field MyObject.EverythingType
; It is important to note that Blitz doesn't consider Arrays as pointers, but
; as solid blocks in memory instead. This is why we can't make them dynamic,
; and have to use Dim or Banks.
Field MyIntArray%[5]
Field MyFloatArray#[5]
Field MyStringArray$[5]
Field MyObjectArray.EverythingType[5]
End Type
; And create a function that modifies only using pointers.
Global fpMyPointerFunction% = 0
Function MyPointerFunction(Pointer%)
If fpMyPointerFunction = 0 Then
fpMyPointerFunction = BlitzPointer_GetFunctionPointer()
Return
EndIf
; Simple Memory modification
PokeMemoryInt Pointer + 20, PeekMemoryInt(Pointer + 20) + 1
PokeMemoryFloat Pointer + 24, PeekMemoryFloat(Pointer + 24) + 1
; Sick of reference counting? Do Circular References without incrementing that!
PokeMemoryInt Pointer + 32, Pointer
End Function
MyPointerFunction(0)
Local Instance.EverythingType = New EverythingType
While Not KeyHit(1)
ExampleUpdate()
MyPointerFunction(Int(Instance))
Text 0, 0, "\MyInt"
Text 200, 0, Instance\MyInt
Text 0,15, "\MyFloat"
Text 200,15, Instance\MyFloat
; Circular Reference
Text 0,45, "\MyObject\MyInt"
Text 200,45, Instance\MyObject\MyInt
Text 0,60, "\MyObject\MyObject\MyInt"
Text 200,60, Instance\MyObject\MyObject\MyInt
ExampleLoop()
Wend
End
;~IDEal Editor Parameters:
;~C#Blitz3D
+299
View File
@@ -0,0 +1,299 @@
; ---------------------------------------------------------------------------- ;
; Example 6 - Callbacks
; ---------------------------------------------------------------------------- ;
; License: Creative Commons Attribution 2.0
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
; Prerequisite: Example 5
; In my opinion, Callbacks are one of the best things that people have figured
; out is useful. We can completely combine all our update logic into one single
; function call without ever having to worry about how to handle a new object.
; Well, unless you are a terrible planner anyways.
Include "Example_Shared.bb"
ExampleInit()
SeedRnd MilliSecs()
; We'll begin by creating a basic Type that holds our generic object. By itself
; this generic object does nothing, but we define custom callbacks later on.
; For optimization reasons (saves some memory) we can use a manually defined
; index for our callbacks.
; Using an Index to store our Callbacks is more efficient that storing it for
; each entry. By doing this we can also have multiple functions that use the
; same structure (Update, PhysicsUpdate, Render, ...). It is wise to reserve
; the first index to check for incorrectly created objects.
Dim CallbackIndex(10)
; Here we define our Type. Since each object has an Index, we
Type TGeneric
; For optimization reasons and saving memory, we just store a callback index.
Field Index
; We only need to store the pointer to our Type object, nothing else.
Field Pointer
End Type
Function TGenericUpdate()
Local This.TGeneric
For This = Each TGeneric
If This\Pointer <> 0 Then
If BlitzPointer_CallFunctionII(CallbackIndex(This\Index), This\Pointer) Then
Delete This
EndIf
EndIf
Next
End Function
; TGeneric will call a function pointer with the following footprint:
; int FUNCTION(pointer)
; We will need to implement this function footprint in every callback.
; Our first Type will hold Cubes that moves up and down.
Type TCube
; Our TCube is represented by an actual Cube in the world, so let's store it.
Field Entity
; This is the original position of the Cube. Y is dynamically modified in code.
Field PosX#, PosY#, PosZ#
; And finally, the time it was created.
Field Time
End Type
; Assign an index to our new Type (starting at 1)
Const CALLBACK_INDEX_TCUBE% = 1
Function TCubeCreate.TCube(X#, Y#, Z#)
; Create our Object
Local This.TCube = New TCube
This\Entity = CreateCube(Example_SceneRoot)
This\PosX = X
This\PosY = Y
This\PosZ = Z
This\Time = MilliSecs()
; And now store it withing TGeneric
Local TG.TGeneric = New TGeneric
TG\Index = CALLBACK_INDEX_TCUBE
; To get the pointer we need (and can store), we just use Int() on the object.
TG\Pointer = Int(This)
; That's all we had to do.
Return This
End Function
Function TCubeCallback%(This.TCube)
If CallbackIndex(CALLBACK_INDEX_TCUBE) = 0 Then
CallbackIndex(CALLBACK_INDEX_TCUBE) = BlitzPointer_GetFunctionPointer()
Return
EndIf
; Safeguard against stupidity (it affect everyone).
If This = Null Then Return True
Local TimeDiff = (MilliSecs() - This\Time)
Local YOffset# = Cos((Cos(This\PosX) * 180) + (Sin(This\PosZ) * 180) + (TimeDiff / 10.0)) * 5 + 5
PositionEntity This\Entity, This\PosX, This\PosY + YOffset, This\PosZ
EntityAlpha This\Entity, 1.0 - (TimeDiff / 5000.0)
; We will allow the object to exist for at most 5 seconds.
If TimeDiff > 5000 Then
TCubeDestroy(This)
Return True
EndIf
Return False
End Function
Function TCubeDestroy(This.TCube)
; Safeguard against stupidity (it affect everyone).
If This = Null Then Return
FreeEntity This\Entity
Delete This
End Function
; And call the function once to automagically register it as a callback.
TCubeCallback(Null)
; Next up is our second Type. It will hold a simple sphere that grows over time.
Type TSphere
; Again, represented by an actual Sphere in the world.
Field Entity
; And the time it was created.
Field Time
End Type
; And we will assign the second index to it.
Const CALLBACK_INDEX_TSPHERE% = 2
Function TSphereCreate.TSphere(X#, Y#, Z#)
; Initialize our TSphere instance.
Local This.TSphere = New TSphere
This\Entity = CreateSphere(32, Example_SceneRoot)
PositionEntity This\Entity, X, Y, Z
This\Time = MilliSecs()
; And now store it withing TGeneric
Local TG.TGeneric = New TGeneric
TG\Index = CALLBACK_INDEX_TSPHERE
TG\Pointer = Int(This)
Return This
End Function
Function TSphereUpdate%(This.TSphere)
If CallbackIndex(CALLBACK_INDEX_TSPHERE) = 0 Then
CallbackIndex(CALLBACK_INDEX_TSPHERE) = BlitzPointer_GetFunctionPointer()
Return
EndIf
; Safeguard against stupidity (it affect everyone).
If This = Null Then Return True
Local TimeDiff = (MilliSecs() - This\Time)
Local TimePrc# = TimeDiff / 2500.0
Local Stp#, StpSize#
Local R#, G#, B#, A#, Scale#
;Step
StpSize# = 0.05:Stp# = 1.0 / (1.0 - StpSize)
R = Interp(1, 1, TimePrc * Stp)
G = Interp(1, 1, TimePrc * Stp)
B = Interp(1, 0, TimePrc * Stp)
;Step
StpSize# = 0.20:Stp# = 1.0 / (1.0 - StpSize)
R = Interp(R, 1, (TimePrc - 0.05) * Stp)
G = Interp(G, 0.75, (TimePrc - 0.05) * Stp)
B = Interp(B, 0, (TimePrc - 0.05) * Stp)
;Step
StpSize# = 0.25:Stp# = 1.0 / (1.0 - StpSize)
R = Interp(R, 1, (TimePrc - 0.25) * Stp)
G = Interp(G, 0, (TimePrc - 0.25) * Stp)
B = Interp(B, 0, (TimePrc - 0.25) * Stp)
;Step
StpSize# = 0.50:Stp# = 1.0 / (1.0 - StpSize)
R = Interp(R, 0, (TimePrc - 0.50) * Stp)
G = Interp(G, 0, (TimePrc - 0.50) * Stp)
B = Interp(B, 0, (TimePrc - 0.50) * Stp)
;AlphaStop 1 at (0.8 of 1.0)
A = Interp(1, 0, (TimePrc - 0.8) * 5)
Scale = Interp(1, 20, Sin(TimePrc * 90))
ScaleEntity This\Entity, Scale,Scale,Scale
EntityColor This\Entity, R * 255, G * 255, B * 255
EntityAlpha This\Entity, A
; We will allow the object to exist for at most 2.5 seconds.
If TimeDiff > 2500 Then
TSphereDestroy(This)
Return True
EndIf
Return False
End Function
TSphereUpdate(Null)
Function TSphereDestroy(This.TSphere)
; Safeguard against stupidity (it affect everyone).
If This = Null Then Return
FreeEntity This\Entity
Delete This
End Function
; And finally, a terrain that we can pick a spawning position from.
Local Terrain = CreateTerrain(256, Example_SceneRoot)
ScaleEntity Terrain, 1 / 256.0, 64, 1 / 256.0
MoveEntity Terrain, -100, 0, -100
ScaleEntity Terrain, 1 / 256.0 * 201, 64, 1 / 256.0 * 201
EntityColor Terrain, 25, 92, 25
TerrainShading Terrain, True
TerrainDetail Terrain, 32767, False
EntityPickMode Terrain, 2, True
RandomTerrain(Terrain, 256, 8, 8)
MoveEntity Example_Camera, 0, 0, -125
;HideEntity Example_Floor
While Not KeyHit(1)
TGenericUpdate()
; Space to randomize Terrain
If KeyHit(57) Then
RandomTerrain(Terrain, 256, Rand(1,8), Rand(1,8))
EndIf
Local ZDelta = MouseZSpeed()
If KeyHit(2) Or ZDelta > 0 Then
CameraPick(Example_Camera, MouseX(), MouseY())
TCubeCreate(PickedX(), PickedY(), PickedZ())
EndIf
If KeyHit(3) Or ZDelta < 0 Then
CameraPick(Example_Camera, MouseX(), MouseY())
TSphereCreate(PickedX(), PickedY(), PickedZ())
EndIf
ExampleUpdate()
ExampleLoop()
UpdateWorld()
Wend
Function RandomTerrain(Terrain, GridSize, CellsX = 1, CellsZ = 1)
Local CellW, CellH, CellX, CellZ, TerX, TerZ, CellPrcX#, CellPrcZ#
Local HTL#, HTR#, HBL#, HBR#, HCC#
CellW = Floor(GridSize / Float(CellsX))
CellH = Floor(GridSize / Float(CellsZ))
Local RowSize = CellsZ + 1
Local TempBankSize = (CellsX + 1) * RowSize * 4
Local TempBank = CreateBank(TempBankSize)
For CellX = 0 To CellsX
For CellZ = 0 To CellsZ
PokeFloat TempBank, 4 * (CellX * RowSize + CellZ), Rnd(0, 1)
Next
Next
Local OCellX, OCellZ:OCellX = -1: OCellZ = -1
For TerX = 1 To (GridSize - 1)
CellX = Floor(TerX / Float(CellW))
CellPrcX = (TerX Mod CellW) / Float(CellW - 1)
For TerZ = 1 To (GridSize - 1)
CellZ = Floor(TerZ / Float(CellH))
CellPrcZ = (TerZ Mod CellH) / Float(CellH - 1)
;DebugLog CellPrcZ
If CellX <> OCellX Or CellZ <> OCellZ Then
HTL = PeekFloat(TempBank, 4 * (((CellX + 0) * RowSize + (CellZ + 0))))
HTR = PeekFloat(TempBank, 4 * (((CellX + 1) * RowSize + (CellZ + 0))))
HBL = PeekFloat(TempBank, 4 * (((CellX + 0) * RowSize + (CellZ + 1))))
HBR = PeekFloat(TempBank, 4 * (((CellX + 1) * RowSize + (CellZ + 1))))
OCellX = CellX:OCellZ = CellZ
EndIf
Local PrcX#, PrcZ#
; Normally, you'd use a bezier curve for this.
PrcX = (Sin(-90 + CellPrcX*180) * 0.5 + 0.5)
PrcZ = (Sin(-90 + CellPrcZ*180) * 0.5 + 0.5)
Local Height# = Interp(Interp(HTL, HTR, PrcX), Interp(HBL, HBR, PrcX), PrcZ)
ModifyTerrain Terrain, TerX, TerZ, Height
Next
Next
FreeBank TempBank
End Function
Function Min#(A#, B#)
If B < A Then Return B
Return A
End Function
Function Max#(A#, B#)
If B > A Then Return B
Return A
End Function
Function Interp#(L#, R#, Lerp#)
Lerp = Min(Max(Lerp, 0.0), 1.0)
Return L * (1.0 - Lerp) + R * Lerp
End Function
;~IDEal Editor Parameters:
;~C#Blitz3D