### Author Topic: Function Pointers In Game Logic  (Read 2337 times)

#### Caché GB

• Member
• Posts: 97
• MASM IS HOT
##### Function Pointers In Game Logic
« on: June 22, 2018, 08:14:44 AM »
Function Pointers in game logic

Hello everyone and welcome to my discussion on Function Pointers.

Function Pointers used in game code can be a very useful technique for speeding up loop
mechanisms execution time. They can do this by avoiding decision structured execution in
game logic allowing for less instructions.

In the WNDCLASSEX STRUCT that is passed as a pointer in RegisterClassEx, the .lpfnWndProc
value is an example of a function pointer. This value points to your Window Procedure that
is used by Windows.

Although function pointer are a simple concept they do lead to complex code.

Here is how function pointer work.

Code: [Select]
`lda MACRO Operand, Param    ;; lda => load AddressOf    lea eax, Param    mov Operand, eaxENDM;===============================================================>.data   swFunctionPointers   db   "Function Pointers", 0.codeSomeFunction00 PROC    invoke  MessageBoxA, null, CSTR("In Function 00"), addr swFunctionPointers, MB_OK      retSomeFunction00 ENDP SomeFunction01 PROC    invoke  MessageBoxA, null, CSTR("In Function 01"), addr swFunctionPointers, MB_OK      retSomeFunction01 ENDPSomeFunction03 PROC    invoke  MessageBoxA, null, CSTR("In Function 02"), addr swFunctionPointers, MB_OK      retSomeFunction03 ENDP  etc.;===============================================================>.data   g_pFunction DWORD 6 dup (0).codeSomeProc PROC    local i:dword          ...          lda  g_pFunction[0*4], SomeFunction00          lda  g_pFunction[1*4], SomeFunction01          lda  g_pFunction[2*4], SomeFunction02          lda  g_pFunction[3*4], SomeFunction03          lda  g_pFunction[4*4], SomeFunction04          lda  g_pFunction[5*4], SomeFunction05          mov  i, 0       .while (i < 6)          mov  ecx, i          mov  eax, 0          .if (eax != g_pFunction[ecx*4])                          call  g_pFunction[ecx*4]          .endif           inc  i        .endw           ...          retSomeProc ENDP;===============================================================>`
In the zip file attachment is an asm file containing MASM32 code that demonstrates
how function pointers can be used to speed up loop execution.
Caché GB's 1 and 0-nly language:MASM

#### HSE

• Member
• Posts: 1410
• <AMD>< 7-32>
##### Re: Function Pointers In Game Logic
« Reply #1 on: June 22, 2018, 08:33:39 AM »
Or just make the table:
Code: [Select]
`.data   g_pFunction dd offset SomeFunction00               dd offset SomeFunction01               ...                dd offset SomeFunction05`
« Last Edit: June 22, 2018, 09:37:56 AM by HSE »

#### felipe

• Member
• Posts: 1336
• Eagles are just great!
##### Re: Function Pointers In Game Logic
« Reply #2 on: June 22, 2018, 08:56:45 AM »
Or just inline your functions... :idea:
Felipe.

#### felipe

• Member
• Posts: 1336
• Eagles are just great!
##### Re: Function Pointers In Game Logic
« Reply #3 on: June 22, 2018, 09:01:28 AM »
What do you mean by decision structured execution? If you mean that this will avoid doing comparisons and jumps you should watch what .while really do. :idea:
Felipe.

#### Siekmanski

• Member
• Posts: 2372
##### Re: Function Pointers In Game Logic
« Reply #4 on: June 22, 2018, 09:22:19 AM »
Just plain and simple, Jump Tables.

Code: [Select]
`.dataRoutineJumpTable    dd offset Routine_0, offset Routine_1, offset Routine_2, ........... etc..code    mov eax,0 ;routine_number    jmp         [RoutineJumpTable+eax*4];    call         [RoutineJumpTable+eax*4] ; or call a routinealign 4Routine_0:; start of your awesome routine code     retalign 4Routine_1:; start of your awesome routine code     retalign 4Routine_2:; start of your awesome routine code     ret`
Creative coders use backward thinking techniques as a strategy.

#### Caché GB

• Member
• Posts: 97
• MASM IS HOT
##### Re: Function Pointers In Game Logic
« Reply #5 on: June 22, 2018, 12:01:12 PM »
Hello HSE.

Hello Siekmanski.

Hello felipe.

Thank you very much for your input.

Yes  decision structured execution  == comparisons and jumps.

Yes the aim is to avoid doing comparisons and jumps, very much so.
Caché GB's 1 and 0-nly language:MASM

#### felipe

• Member
• Posts: 1336
• Eagles are just great!
##### Re: Function Pointers In Game Logic
« Reply #6 on: June 22, 2018, 12:42:44 PM »
Yes the aim is to avoid doing comparisons and jumps, very much so.

I'm not pretty sure, but i think the mmx instruction set has some "feature" to avoid this when making some computations. Someday i will take a look to mmx instruction set again but deeper. Maybe (probably) other members knows about this feature. Maybe there are similar features in newer instruction sets.   :idea:

The main problem with this feature is that you can use it just for specific computation types, but as i said before i really don't know, i just remember a little what i readed some long time ago about mmx.  :idea:
Felipe.

#### daydreamer

• Member
• Posts: 1391
• building nextdoor
##### Re: Function Pointers In Game Logic
« Reply #7 on: June 22, 2018, 08:24:08 PM »
I think for finite state machine,its great to have a jumptable,just make a loop that loads array of State for 100's of enemies and use jumptable
also useful for the right image for 2d sprite for enemies/player character,depending on direction it points at and moves,action like fire a gun,jump,nonaction idle I seen in some games,the PC falls asleep after certain milliseconds inaction
Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

#### Caché GB

• Member
• Posts: 97
• MASM IS HOT
##### Re: Function Pointers In Game Logic
« Reply #8 on: June 22, 2018, 08:48:50 PM »
Thanks felipe for the info.

Once again thanks to HSE and Siekmanski. Jump Tables are definitely the goto.

I see that hierarchical complexity can quickly be implemented and for deep nesting, it is possible to have
predetermined or calculated code paths (tree transversal) for rapidly dealing with course and effect. As
daydreamer pointed out "loads array of STATE for 100's of ... and use jump table".

Thanks daydreamer.

Awesome! Welcome to the JUNGLE, Table.

Code: [Select]
`.dataszEntityZero   db "I am Entity Zero", 0szEntityOne    db "I am Entity One", 0    etc.g_pBehaviour   dd offset Behaviour00, offset Behaviour00Routine00,  offset Behaviour00Routine01,  offset Behaviour00Routine02               dd offset Behaviour01, offset Behaviour01Routine00,  offset Behaviour01Routine01,  offset Behaviour01Routine02               dd offset Behaviour02, offset Behaviour02Routine00,  offset Behaviour02Routine01,  offset Behaviour02Routine02               dd offset Behaviour03, offset Behaviour03Routine00,  offset Behaviour03Routine01,  offset Behaviour03Routine02               dd offset Behaviour04, offset Behaviour04Routine00,  offset Behaviour04Routine01,  offset Behaviour04Routine02               dd offset Behaviour05, offset Behaviour05Routine00,  offset Behaviour05Routine01,  offset Behaviour05Routine02GameEntity     ENTITY  NumEntities dup (<>).code ;===========================================>          ...          lea  esi, GameEntity       assume  esi:ptr ENTITY          mov [esi].ENTITY.MyName, offset szEntityZero          add  esi, sizeof(ENTITY)          mov [esi].ENTITY.MyName, offset szEntityOne          add  esi, sizeof(ENTITY)                        etc.          mov  i, 0       .while (i < NumEntities)          invoke  RAND32, 6              ;; RNG by NaN (May 5, 2001)            imul  eax, 4             mov  edx, eax             mAm [esi].ENTITY.BehaviourPtr, [g_pBehaviour+eax*4]             invoke  RAND32, 3             add  eax, 1             add  eax, edx             mAm [esi].ENTITY.RoutinePtr, [g_pBehaviour+eax*4]             add  esi, sizeof(ENTITY)             inc  i        .endw       assume  esi:          ... ;===========================================>          ...         lea  esi, GameEntity      assume  esi:ptr ENTITY          mov  i, 0       .while (i < NumEntities)                     push  esi            call [esi].ENTITY.BehaviourPtr             add  esi, sizeof(ENTITY)             inc  i        .endw       assume  esi:nothing          ...;===========================================>Behaviour00 PROC  Who:PTR ENTITY           mov  edx, Who       assume  edx:ptr ENTITY       invoke  MessageBoxA, null, CSTR("Acting out Behaviour 0"),  [edx].ENTITY.MyName, MB_OK             mov  edx, Who         call [edx].ENTITY.RoutinePtr       assume  edx:nothing          retBehaviour00 ENDP    Behaviour00Routine00 PROC       invoke  MessageBoxA, null, CSTR("while doing 0s Routine 0"),  [edx].ENTITY.MyName, MB_OK          ret    Behaviour00Routine00 ENDP    Behaviour00Routine01 PROC       invoke  MessageBoxA, null, CSTR("while doing 0s Routine 1"),  [edx].ENTITY.MyName, MB_OK          ret    Behaviour00Routine01 ENDP    Behaviour00Routine02 PROC       invoke  MessageBoxA, null, CSTR("while doing 0s Routine 2"),  [edx].ENTITY.MyName, MB_OK          ret    Behaviour00Routine02 ENDP  etc.;==================================================================>`
Caché GB's 1 and 0-nly language:MASM

#### mineiro

• Member
• Posts: 650
##### Re: Function Pointers In Game Logic
« Reply #9 on: June 23, 2018, 01:15:19 AM »
hello Caché GB;
Maybe you can gain some cycles if you do a mov and a jump; I think is more viable/quickly than a call/ret pairs.

Something like:
lea eax,[g_pBehaviour+??*4]  ;*4 because dwords addresses
jmp eax

align 4
Behaviour00:
...
jmp go_back_to_loop

go_back_to_loop is better if aligned to a multiple. (align 4,8,...)

The way to go is using tables, we often do this while on eletronics, only logic tables (or pre calculated tables) that are translated to logic circuits (diodes, transistors, ...).
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

#### daydreamer

• Member
• Posts: 1391
• building nextdoor
##### Re: Function Pointers In Game Logic
« Reply #10 on: July 14, 2018, 11:29:36 PM »
it would be nice to start with a simple solution,for example 2D topdown game for 100+ enemies and call simple PROC's for turning and moving that are coded oldschool style with trigo and simple 2D physics
and later combine with this:
https://docs.microsoft.com/en-us/windows/desktop/direct3d9/efficiently-drawing-multiple-instances-of-geometry
,changing your PROC for turning enemy alpha degrees,in pitch,roll,jaw angles and moving x,y,z is exchanged with wrapper for matrices code that do the same with instances

in a RTS game,you can have different colors for the two teams competing

this is because the alternative is probably fun to code SIMD that take 100+lowpoly 3dobjects and copy,3dtranslate/3drotate before sending to vertexbuffer ,but too much overhead so it lags and too much limitations for great graphics

Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

#### Caché GB

• Member
• Posts: 97
• MASM IS HOT
##### Re: Function Pointers In Game Logic
« Reply #11 on: July 16, 2018, 10:52:32 AM »
Hello mineiro.

"mov and a jump" although great for gaining some cycles, I don't see it possible to be used when called
from different parts of a program. " call/ret pairs" need to be implemented to return to point of call.

However thank you for your suggestion.

Hello daydreamer.