unit UCore; interface {$IFDEF FPC} {$MODE Delphi} {$ENDIF} {$I switches.inc} uses uPluginDefs, uCoreModule, UHooks, UServices, UModules; {********************* TCore Class manages all CoreModules, teh StartUp, teh MainLoop and the shutdown process Also it does some Error Handling, and maybe sometime multithreaded Loading ;) *********************} type TModuleListItem = record Module: TCoreModule; //Instance of the Modules Class Info: TModuleInfo; //ModuleInfo returned by Modules Modulinfo Proc NeedsDeInit: Boolean; //True if Module was succesful inited end; TCore = class private //Some Hook Handles. See Plugin SDKs Hooks.txt for Infos hLoadingFinished: THandle; hMainLoop: THandle; hTranslate: THandle; hLoadTextures: THandle; hExitQuery: THandle; hExit: THandle; hDebug: THandle; hError: THandle; sReportError: THandle; sReportDebug: THandle; sShowMessage: THandle; sRetranslate: THandle; sReloadTextures: THandle; sGetModuleInfo: THandle; sGetApplicationHandle: THandle; Modules: Array [0..High(CORE_MODULES_TO_LOAD)] of TModuleListItem; //Cur + Last Executed Setting and Getting ;) iCurExecuted: Integer; iLastExecuted: Integer; Procedure SetCurExecuted(Value: Integer); //Function Get all Modules and Creates them Function GetModules: Boolean; //Loads Core and all Modules Function Load: Boolean; //Inits Core and all Modules Function Init: Boolean; //DeInits Core and all Modules Function DeInit: Boolean; //Load the Core Function LoadCore: Boolean; //Init the Core Function InitCore: Boolean; //DeInit the Core Function DeInitCore: Boolean; //Called one Time per Frame Function MainLoop: Boolean; public Hooks: THookManager; //Teh Hook Manager ;) Services: TServiceManager;//The Service Manager Name: String; //Name of this Application Version: LongWord; //Version of this ". For Info Look PluginDefs Functions LastErrorReporter:String; //Who Reported the Last Error String LastErrorString: String; //Last Error String reported property CurExecuted: Integer read iCurExecuted write SetCurExecuted; //ID of Plugin or Module curently Executed property LastExecuted: Integer read iLastExecuted; //--------------- //Main Methods to control the Core: //--------------- Constructor Create(const cName: String; const cVersion: LongWord); //Starts Loading and Init Process. Then Runs MainLoop. DeInits on Shutdown Procedure Run; //Method for other Classes to get Pointer to a specific Module Function GetModulebyName(const Name: String): PCoreModule; //-------------- // Hook and Service Procs: //-------------- Function ShowMessage(wParam: TwParam; lParam: TlParam): integer; //Shows a Message (lParam: PChar Text, wParam: Symbol) Function ReportError(wParam: TwParam; lParam: TlParam): integer; //Shows a Message (wParam: Pchar(Message), lParam: PChar(Reportername)) Function ReportDebug(wParam: TwParam; lParam: TlParam): integer; //Shows a Message (wParam: Pchar(Message), lParam: PChar(Reportername)) Function Retranslate(wParam: TwParam; lParam: TlParam): integer; //Calls Translate hook Function ReloadTextures(wParam: TwParam; lParam: TlParam): integer; //Calls LoadTextures hook Function GetModuleInfo(wParam: TwParam; lParam: TlParam): integer; //If lParam = nil then get length of Moduleinfo Array. If lparam <> nil then write array of TModuleInfo to address at lparam Function GetApplicationHandle(wParam: TwParam; lParam: TlParam): integer; //Returns Application Handle end; var Core: TCore; implementation uses {$IFDEF win32} Windows, {$ENDIF} SysUtils; //------------- // Create - Creates Class + Hook and Service Manager //------------- Constructor TCore.Create(const cName: String; const cVersion: LongWord); begin Name := cName; Version := cVersion; iLastExecuted := 0; iCurExecuted := 0; LastErrorReporter := ''; LastErrorString := ''; Hooks := THookManager.Create(50); Services := TServiceManager.Create; end; //------------- //Starts Loading and Init Process. Then Runs MainLoop. DeInits on Shutdown //------------- Procedure TCore.Run; var noError: Boolean; begin //Get Modules Try noError := GetModules; Except noError := False; end; //Loading if (noError) then begin Try noError := Load; Except noError := False; end; if (noError) then begin //Init Try noError := Init; Except noError := False; end; If noError then begin //Call Translate Hook noError := (Hooks.CallEventChain(hTranslate, 0, nil) = 0); If noError then begin //Calls LoadTextures Hook noError := (Hooks.CallEventChain(hLoadTextures, 0, nil) = 0); if noError then begin //Calls Loading Finished Hook noError := (Hooks.CallEventChain(hLoadingFinished, 0, nil) = 0); If noError then begin //Start MainLoop While noError do begin noError := MainLoop; // to-do : Call Display Draw here end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error calling LoadingFinished Hook: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error calling LoadingFinished Hook')); end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error loading textures: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error loading textures')); end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error translating: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error translating')); end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error initing Modules: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error initing Modules')); end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error loading Modules: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error loading Modules')); end; end else begin If (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar('Error Getting Modules: ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar('Error Getting Modules')); end; //DeInit DeInit; end; //------------- //Called one Time per Frame //------------- Function TCore.MainLoop: Boolean; begin Result := False; end; //------------- //Function Get all Modules and Creates them //------------- Function TCore.GetModules: Boolean; var I: Integer; begin Result := False; for I := 0 to high(Modules) do begin try Modules[I].NeedsDeInit := False; Modules[I].Module := CORE_MODULES_TO_LOAD[I].Create; Modules[I].Module.Info(@Modules[I].Info); except ReportError(Integer(PChar('Can''t get module #' + InttoStr(I) + ' "' + Modules[I].Info.Name + '"')), PChar('Core')); Exit; end; end; Result := True; end; //------------- //Loads Core and all Modules //------------- Function TCore.Load: Boolean; var I: Integer; begin Result := LoadCore; I := 0; While ((Result = True) AND (I <= High(CORE_MODULES_TO_LOAD))) do begin try Result := Modules[I].Module.Load; except Result := False; ReportError(Integer(PChar('Error loading module #' + InttoStr(I) + ' "' + Modules[I].Info.Name + '"')), PChar('Core')); end; Inc(I); end; end; //------------- //Inits Core and all Modules //------------- Function TCore.Init: Boolean; var I: Integer; begin Result := InitCore; I := 0; While ((Result = True) AND (I <= High(CORE_MODULES_TO_LOAD))) do begin try Result := Modules[I].Module.Init; except Result := False; ReportError(Integer(PChar('Error initing module #' + InttoStr(I) + ' "' + Modules[I].Info.Name + '"')), PChar('Core')); end; Modules[I].NeedsDeInit := Result; Inc(I); end; end; //------------- //DeInits Core and all Modules //------------- Function TCore.DeInit: Boolean; var I: Integer; label Continue; begin I := High(CORE_MODULES_TO_LOAD); Continue: Try While (I >= 0) do begin If (Modules[I].NeedsDeInit) then Modules[I].Module.DeInit; Dec(I); end; Except end; If (I >= 0) then GoTo Continue; DeInitCore; Result := true; end; //------------- //Load the Core //------------- Function TCore.LoadCore: Boolean; begin hLoadingFinished := Hooks.AddEvent('Core/LoadingFinished'); hMainLoop := Hooks.AddEvent('Core/MainLoop'); hTranslate := Hooks.AddEvent('Core/Translate'); hLoadTextures := Hooks.AddEvent('Core/LoadTextures'); hExitQuery := Hooks.AddEvent('Core/ExitQuery'); hExit := Hooks.AddEvent('Core/Exit'); hDebug := Hooks.AddEvent('Core/NewDebugInfo'); hError := Hooks.AddEvent('Core/NewError'); sReportError := Services.AddService('Core/ReportError', nil, Self.ReportError); sReportDebug := Services.AddService('Core/ReportDebug', nil, Self.ReportDebug); sShowMessage := Services.AddService('Core/ShowMessage', nil, Self.ShowMessage); sRetranslate := Services.AddService('Core/Retranslate', nil, Self.Retranslate); sReloadTextures := Services.AddService('Core/ReloadTextures', nil, Self.ReloadTextures); sGetModuleInfo := Services.AddService('Core/GetModuleInfo', nil, Self.GetModuleInfo); sGetApplicationHandle := Services.AddService('Core/GetApplicationHandle', nil, Self.GetApplicationHandle); //A little Test Hooks.AddSubscriber('Core/NewError', HookTest); result := true; end; //------------- //Init the Core //------------- Function TCore.InitCore: Boolean; begin //Dont Init s.th. atm. result := true; end; //------------- //DeInit the Core //------------- Function TCore.DeInitCore: Boolean; begin // to-do : write TService-/HookManager.Free and call it here Result := true; end; //------------- //Method for other Classes to get Pointer to a specific Module //------------- Function TCore.GetModulebyName(const Name: String): PCoreModule; var I: Integer; begin Result := nil; For I := 0 to high(Modules) do If (Modules[I].Info.Name = Name) then begin Result := @Modules[I].Module; Break; end; end; //------------- // Shows a MessageDialog (lParam: PChar Text, wParam: Symbol) //------------- Function TCore.ShowMessage(wParam: TwParam; lParam: TlParam): integer; {$IFDEF MSWINDOWS} var Params: Cardinal; // Auto Removed, Unused Variable {$ENDIF} begin Result := -1; {$IFDEF MSWINDOWS} If (lParam<>nil) then begin Params := MB_OK; Case wParam of CORE_SM_ERROR: Params := Params or MB_ICONERROR; CORE_SM_WARNING: Params := Params or MB_ICONWARNING; CORE_SM_INFO: Params := Params or MB_ICONINFORMATION; end; //Show: Result := Messagebox(0, lParam, PChar(Name), Params); end; {$ENDIF} // to-do : write ShowMessage for other OSes end; //------------- // Calls NewError HookChain (wParam: Pchar(Message), lParam: PChar(Reportername)) //------------- Function TCore.ReportError(wParam: TwParam; lParam: TlParam): integer; begin //Update LastErrorReporter and LastErrorString LastErrorReporter := String(PChar(lParam)); LastErrorString := String(PChar(Pointer(wParam))); Hooks.CallEventChain(hError, wParam, lParam); end; //------------- // Calls NewDebugInfo HookChain (wParam: Pchar(Message), lParam: PChar(Reportername)) //------------- Function TCore.ReportDebug(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hDebug, wParam, lParam); end; //------------- // Calls Translate hook //------------- Function TCore.Retranslate(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hTranslate, 1, nil); end; //------------- // Calls LoadTextures hook //------------- Function TCore.ReloadTextures(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hLoadTextures, 1, nil); end; //------------- // If lParam = nil then get length of Moduleinfo Array. If lparam <> nil then write array of TModuleInfo to address at lparam //------------- Function TCore.GetModuleInfo(wParam: TwParam; lParam: TlParam): integer; begin if (Pointer(lParam) = nil) then begin Result := Length(Modules); end else begin Try For Result := 0 to High(Modules) do begin AModuleInfo(Pointer(lParam))[Result].Name := Modules[Result].Info.Name; AModuleInfo(Pointer(lParam))[Result].Version := Modules[Result].Info.Version; AModuleInfo(Pointer(lParam))[Result].Description := Modules[Result].Info.Description; end; Except Result := -1; end; end; end; //------------- // Returns Application Handle //------------- Function TCore.GetApplicationHandle(wParam: TwParam; lParam: TlParam): integer; begin Result := hInstance; end; //------------- // Called when setting CurExecuted //------------- Procedure TCore.SetCurExecuted(Value: Integer); begin //Set Last Executed iLastExecuted := iCurExecuted; //Set Cur Executed iCurExecuted := Value; end; end.