I was reading an interesting article about Stackless, and implementation of python than implementas micro-tasks or tasklets, more to the point it’s about Sylphis3D Game Engine use of it.
Anyway, reading the comments I find it amazing how may people don’t get the concept of micro-threads, tasklets, or just plain tasks. This system has actually been around for a very long time in games development.
The first time I came across it was in the early 90’s when I was new coder at SCi. I spent a fascinating time discussing the concept with ‘Kat’ as he explained how it was used in SWIV.
The system used then was designed and implemented in 68000 by Ronald Pieket Weeserik – later came various other assembler versions, and I myself implemented a C version that used assembler to do the actual switch. When I later wrote a point and click engine, my version of the Scripting language used the task system, although it’s much easier to code into a scripting language!
What the system actually does is give every task it’s own stack data, just a small amount… and then the task switching is actually done by storing the current program counter on the stack for the task… well a JSR or CALL will do that by default, store registers, and then switch the stack ptr… simple as that. So every time the task calls NttNext, the next task in the list becomes activated until it gives up it’s slice; None Premptive Multitasking.
The assembler version relied heavily on MACROS, here is an example of an entity in SEGA MEGADRIVE SWIV.
*-----------------------------------------------------------------------------
* Flashing thing that gives you a shield.
*-----------------------------------------------------------------------------
MineUFO
INITNTT
INITUFO
UFOTYPE ufoF_Mine!ufoF_NME
NAME "MINE"
TIMEOUT 60
LOADGFX MineOBLK,MineCount
ANIM MineANI
LOOPANIM
USEBOX MineBOX
clr.l ufo_Z(a6)
POWER $0a00
SCORE $0200
NOWIGGLE
VISIBLE
COLLISIONSON
@MineLoop
IFGOAWAY @GoAway
Next
bsr CheckOffBottom
beq.s @MineLoop
@GoAway
COLLISIONSOFF
INVISIBLE
UNLOADGFX MineCount,MineOBLK
Next
tst.l ufo_Power(a6)
bgt.s @Del
move.l a6,-(a7)
GenNTT ShieldUFO
move.l a6,a5 ;a5=>shield UFO
move.l (a7)+,a6
bne.s @Del
COPYXY
@Del
DelNTT
What is important here is that this piece of code is self contained, and is start to end for the life time of the ‘MINE’ – what you will see is that everynow and then a ‘Next’ command is executed which is the 1 frame Sleep option.
And here is something similar in the ‘C . This is a set of rotorblades above a helicopter. All this code does is animate the blades following the parent until finished. As you can see, this looks like a normal C function, but it is indeed a tasklet. BTW: because of the small stack allocated to a task, any local variables are allocated in the task’s space. Also, this piece of code can be fired multiple times with a different data space and you have multiple versions of the same task running. Now imagine those old 2d shooters like swiv and just thing of the simplicity of coding these things. Write a NTT that moves down the screen moving slightly to the left… and then fire off 20 of them with a delay between each one… you have a wave!
void rotorblades ( void )
{
UFO ufo;
UFO parent;
NTT_INIT;
NTT_NAME ( 'ROTR' );
NTT_SETUFO;
NTT_UFO;
CENTRE;
COLLISIONOFF;
UNSHOOTABLE;
UFO_UseID ( ufo, IDS_ROTOR1, ANIM_FORWARD, 4, ANIMF_LOOP | ANIMF_BOUNCE | ANIMF_FLIPXR );
ufo->anim.framerate = FRAME_RATE/4;
ufo->anim.framedelay = FRAME_RATE/4;
NTT_SETPARENTUFO;
LOOP
{
UFO_ATPARENT;
NTT_NEXT;
NTT_IFGOAWAY break;
}
NTT_REMOVE;
}
Here is an example from the scripting language I wrote for the Point and Click Engine. With this bit of code Jack will walk to a place, wait until Erika gets there and then turn to face her. The Walkto method is also running as a task and thus the code “waits” for that task to finish or be aborted.
SUB WAIT JackWalkto ( walkboxno as long )
wait abort jack.walkto walkboxno
while erika.IsWalking
delay(1)
if jack.IsWalking
Abort WAITERR_ABORTED
end if
wend
jack.facechar erika
END SUB
Programming Games, Scripting Language, Swiv
You must be kidding. Everyone knows that the clr.l instruction is slow due to a hardware bug (in the 68000 at least). 🙂
Just kidding. Interesting to know that this technique was used in early games as well.