| Here it is : 
 
 Strict
Import mojo
Import monkey.stack
Import brl.filesystem
' ------------------------------------------------------------------------------------------------------------------------------------------------------
Const NOT_FOUND:Int					=	-1
Const MASK_CHAR:String				=	"#"
Const TSETUP_OK:Int					=	0
Const TSETUP_NOLABELGIVEN:Int		=	1
Const TSETUP_NOFILENAMEGIVEN:Int	=	2
Const TSETUP_FILENOTFOUND:Int		=	3
Const TSETUP_NAMEMASKMUSTBEUSED:Int	=	4
Const TSETUP_MODULENOTFOUND:Int		=	5
Const TSETUP_STATE_NOTSTARTED:Int	=	-1
Const TSETUP_STATE_OK:Int			=	0
Const TSETUP_STATE_PAUSED:Int		=	1
Class TSetup Extends App
	Field sprites:TSetup_Sprite
	
	Field flags:Int		' General program flags
	Field freq:Int		' Processing frequency
	
	Field errorCode:Int	' Last error code
	
	Field modulesList:Stack <UserModule>
	
	Field currentModuleIndex:Int	=	-1	' Current module to use
	
	Field speed:Float						' Process speed
	
	Field state:Int					=	TSETUP_STATE_NOTSTARTED					' TSetup state
	
	Method New(fq:Int=75,flg:Int=0)
		flags=0 ' flg
		freq=75 ' fq
		currentModuleIndex=-1	
		speed=0.0
		SetErrorCode(TSETUP_OK)
		SetState(TSETUP_STATE_NOTSTARTED)
		
	End Method
	
	Method OnCreate:Int()
		DebugLog("OnCreate")
		
		modulesList=New Stack<UserModule>
		modulesList.Clear()
		sprites=New TSetup_Sprite
		Return 0
	End Method
	
	Method OnRender:Int()
		If GetState()=TSETUP_STATE_NOTSTARTED Then Return 0
		
		If currentModuleIndex>=0 And currentModuleIndex<modulesList.Length()
			modulesList.Get(currentModuleIndex).OnRender()
		endif
						
		Return 0
	End Method
	
	Method OnUpdate:Int()
		If GetState()=TSETUP_STATE_OK
			If currentModuleIndex>=0 And currentModuleIndex<modulesList.Length()
				modulesList.Get(currentModuleIndex).OnUpdate()
			End If	
			
			' Update speed
		Endif
		
		Return 0
	End Method
	
	Method SetErrorCode:Void(code:Int)
		errorCode=code
	End Method
	
	Method GetErrorCode:Int()
		Return errorCode
	End Method
	
	Method RegisterModule:Int(m:UserModule)
		If m<>Null
			DebugLog("Adding module")
			modulesList.Push(m)
			modulesList.Sort()
			
			Return True
		Else
			Return False
		Endif
	End Method
	
	Method ChangeModule:Int(moduleName:String)
	Local index:Int
	
		If moduleName<>""
			index=Search(modulesList,moduleName)
			If index<>NOT_FOUND
				If currentModuleIndex<>-1
					' Deactivate previous module
					modulesList.Get(currentModuleIndex).OnRoutineEnd()
				Endif
				
				currentModuleIndex=index
				
				modulesList.Get(currentModuleIndex).OnRoutineStart()
				Return True
			Else
				SetErrorCode(TSETUP_MODULENOTFOUND)
			End if
		Else
			SetErrorCode(TSETUP_NOLABELGIVEN)
		End If
		
		Return false
	End Method
	
	Method Start:Int(moduleName:String)
	Local index:Int
	
		If moduleName<>""
			If ChangeModule(moduleName)=True
				SetState(TSETUP_STATE_OK)
				Return True
			Endif
		Else
			SetErrorCode(TSETUP_NOLABELGIVEN)
		End If
		
		Return False
	End method
				
	Method FindModuleIndex:Int(moduleName:String)
	Local index:Int
	
		If moduleName<>""
			index=Search(modulesList,moduleName) ' Does work properly at the moment
			If index=NOT_FOUND
				SetErrorCode(TSETUP_MODULENOTFOUND)
			Else
				Return index
			Endif
		Else
			SetErrorCode(TSETUP_NOLABELGIVEN)
		End If
		
		Return NOT_FOUND
	End method
	method BinarySearch:Int(list:Stack <UserModule>,text:String)
	Local low:Int,high:Int,midpoint:Int
	
		low=0
		high=list.Length()-1
		midpoint=0
		While (low<=high)
			midpoint=low+(high-low)/2
			Print list.Get(midpoint).GetModuleName()+" v "+text
			If list.Get(midpoint).GetModuleName()=text
				Return midpoint
			Else If list.Get(midpoint).GetModuleName()>text
				high=midpoint-1
			Else
				low=midpoint+1
			Endif
		End while
	
		return NOT_FOUND;
	End method
	
	method Search:Int(mList:Stack <UserModule>,text:String)
		If HAS_MASK(text)=False
			Return Int(text)
		Else
			Return BinarySearch(mList,REMOVE_MASK(text))
		Endif 
	End method
	
	Method SetState:Void(s:Int)
		state=s
	End Method
	
	Method GetState:Int()
		Return state
	End Method
	
	Method LoadSprite:Int(label:String,fileName:String,cellWidth:Int=-1,cellHeight:Int=-1)
		Return sprites.Load(label,fileName,cellWidth,cellHeight)
	End method
End Class
	
' ------------------------------------------------------------------------------------------------------------------------------------------------------
Class TSetup_SpriteBlock
	Field fileName:String
	Field spriteWidth:Int
	Field spriteHeight:Int
	Field cellWidth:Int
	Field cellHeight:Int
	Field numFrames:Int
	Field numLoads:Int
	Field sprite:Image
	
	Method New()
		fileName=""
		spriteWidth=0
		spriteHeight=0
		cellWidth=0
		cellHeight=0
		numFrames=0
		numLoads=1
		sprite=Null
	End Method
		
	Method SetFilename:Void(fName:String)
		fileName=fName
	End Method
	
	Method GetFilename:String()
		Return fileName
	End Method
	
	Method SetImage:Int(spr:Image)
		sprite=spr
		If sprite=Null
			Return False
		Else
			Return True
		End If
	End Method
	
	Method SetCellWidth:Void(size:Int)
		cellWidth=size
	End Method
	
	Method GetCellWidth:Int()
		Return cellWidth
	End Method
	
	Method SetCellHeight:Void(size:Int)
		cellHeight=size
	End Method
	
	Method GetCellHeight:Int()
		Return cellHeight
	End Method
	
	Method SetNumFrames:Void(a:Int)
		numFrames=a
	End Method
	
	Method GetNumFrames:Int()
		Return numFrames
	End Method
End Class
	
Class TSetup_Sprite Extends TSetup
	Field path:String	=	""
	
	Field spriteList:Stack <TSetup_SpriteBlock>
	
	Method New()
		path="data/sprites/"
		
		spriteList=New Stack <TSetup_SpriteBlock>
		spriteList.Clear()
	End Method
	
	Method _load:Int(block:TSetup_SpriteBlock)
	Local fullFile:String
	
		fullFile=path+block.GetFilename()
		DebugLog(fullFile)
		If FileSize(fullFile)=0
			DebugLog("Not found")
			Super.SetErrorCode(TSETUP_FILENOTFOUND)
			Return False
		Else
		Local s:Image
			DebugLog("loading")
			'block.sprite=LoadImage(fullFile) ' ,block.GetCellWidth(),block.GetCellHeight(),block.GetNumFrames(),0)
			s=LoadImage(fullFile)
			DebugLog("Loaded")
			If block.SetImage(block.sprite)=False
				' Error
				Return False
			Else
				Return True
			End If
		End If
	End Method
			
	Method Load:Int(label:String,fileName:String,cellWidth:Int=-1,cellHeight:Int=-1,numFrames:Int=1)
	Local block:TSetup_SpriteBlock
	Local index:Int
	
		DebugLog(label+" "+fileName)
		If label=""
			Super.SetErrorCode(TSETUP_NOLABELGIVEN)
			Return False
		Else If fileName=""
			Super.SetErrorCode(TSETUP_NOFILENAMEGIVEN)
			Return False
		Else If HAS_MASK(label)=False
			DebugLog("No mask")
			Super.SetErrorCode(TSETUP_NAMEMASKMUSTBEUSED)
			Return False
		Else
			' index=FindFilename(fileName)
			DebugLog("Here")
			index=-1
			If index>=0
				' Already present
			Else
				' Not present
				block=New TSetup_SpriteBlock
				If block<>Null
					block.SetFilename(fileName)
					block.SetCellWidth(cellWidth)
					block.SetCellHeight(cellHeight)
					block.SetNumFrames(numFrames)
					
					' Load the file
					If _load(block)=True
						spriteList.Push(block)
						spriteList.Sort()
						Return true
					Else
						block=Null
					End If
				End If
			End If
		End If
			
		Return False			
	End Method
End Class
Function HAS_MASK:Int(text:String)
	If text.StartsWith(MASK_CHAR)
		Return True
	Else
		Return False
	Endif
End Function
Function ADD_MASK:String(text:String)
	If HAS_MASK(text)=False
		Return MASK_CHAR+text
	Else
		Return text
	Endif
End Function
Function REMOVE_MASK:String(text:String)
	If HAS_MASK(text)
		Return text[MASK_CHAR.Length()..]
	Else
		Return text
	Endif
End Function
' ------------------------------------------------------------------------------------------------------------------------------------------------------
Class UserModule 
	Field moduleName:String
	
	Method New(name:String)
		SetModuleName(name)
	End Method
	
	Method Destroy:Int()
	End Method
	
	' Called when changing to this module
	Method OnRoutineStart:Int()
		Return 0
	End Method
	
	Method OnRoutineEnd:Int()
		Return 0
	End Method
	
	Method OnUpdate:Int()
		Return 0
	End Method
	
	Method OnRender:Int()
		Return 0
	End Method
	
	Method SetModuleName:Int(name:String)
		moduleName=REMOVE_MASK(name)
		Return True
	End Method
	
	Method GetModuleName:String()
		Return moduleName
	End Method
	
	Method Compare:Int(o:Object)
		Return GetModuleName()=UserClass(o).GetModuleName();
	End method
End Class
' ------------------------------------------------------------------------------------------------------------------------------------------------------
Class Test1 Extends UserModule
	Method New(name:String)
		' SetModuleName(name)
	End Method
	
	Method Go:Int()
		Return True
	End Method
	
	Method OnRoutineStart:Int()
		Print "Starting module"
		Return 0
	End Method
	
	Method OnRender:Int()
		DrawCircle(100,100,10)
		Return 0
	End Method
	
	Method OnUpdate:Int()
		Return 0
	End method
End Class
Function Main:Int()
Local tSetup:TSetup
'Local test1:Test1 = New Test1("#Hello")
	
	DebugLog("Here0")
	tSetup=New TSetup(60,0)
	If tSetup<>Null
		tSetup.OnCreate()
		DebugLog("Here1")
'		DebugLog(DeviceWidth()+" "+DeviceHeight())
		  Print "Module registering result : "+tSetup.RegisterModule(New Test1("#Hello"))
		  DebugLog("Finding module : "+tSetup.FindModuleIndex("#Hello"))
		  DebugLog("Finding module : "+tSetup.ChangeModule("#Hello"))
		  DebugLog("Loading : "+tSetup.LoadSprite("#moo","Dropper.png"))
		  tSetup.Start("#Hello")
	Endif 
	Return True
End Function
 
 |