{* UltraStar Deluxe - Karaoke Game * * UltraStar Deluxe is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $URL$ * $Id$ *} 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 inherited Create; 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 Success: Boolean; procedure HandleError(const ErrorMsg: string); begin if (LastErrorString <> '') then Self.ShowMessage(CORE_SM_ERROR, PChar(ErrorMsg + ': ' + LastErrorString)) else Self.ShowMessage(CORE_SM_ERROR, PChar(ErrorMsg)); //DeInit DeInit; end; begin //Get Modules try Success := GetModules(); except Success := False; end; if (not Success) then begin HandleError('Error Getting Modules'); Exit; end; //Loading try Success := Load(); except Success := False; end; if (not Success) then begin HandleError('Error loading Modules'); Exit; end; //Init try Success := Init(); except Success := False; end; if (not Success) then begin HandleError('Error initing Modules'); Exit; end; //Call Translate Hook if (Hooks.CallEventChain(hTranslate, 0, nil) <> 0) then begin HandleError('Error translating'); Exit; end; //Calls LoadTextures Hook if (Hooks.CallEventChain(hLoadTextures, 0, nil) <> 0) then begin HandleError('Error loading textures'); Exit; end; //Calls Loading Finished Hook if (Hooks.CallEventChain(hLoadingFinished, 0, nil) <> 0) then begin HandleError('Error calling LoadingFinished Hook'); Exit; end; //Start MainLoop while Success do begin Success := MainLoop(); // to-do : Call Display Draw here end; 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; for i := 0 to High(CORE_MODULES_TO_LOAD) do begin try Result := Modules[i].Module.Load; except Result := False; end; if (not Result) then begin ReportError(Integer(PChar('Error loading module #' + InttoStr(i) + ' "' + Modules[i].Info.Name + '"')), PChar('Core')); break; end; end; end; //------------- //Inits Core and all Modules //------------- function TCore.Init: Boolean; var i: Integer; begin Result := InitCore; for i := 0 to High(CORE_MODULES_TO_LOAD) do begin try Result := Modules[i].Module.Init; except Result := False; end; if (not Result) then begin ReportError(Integer(PChar('Error initing module #' + InttoStr(i) + ' "' + Modules[i].Info.Name + '"')), PChar('Core')); break; end; Modules[i].NeedsDeInit := Result; end; end; //------------- //DeInits Core and all Modules //------------- function TCore.DeInit: boolean; var i: integer; begin for i := High(CORE_MODULES_TO_LOAD) downto 0 do begin try if (Modules[i].NeedsDeInit) then Modules[i].Module.DeInit; except end; end; 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 //Don not init something atm. result := true; end; //------------- //DeInit the Core //------------- function TCore.DeInitCore: Boolean; begin // TODO: 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 begin if (Modules[i].Info.Name = Name) then begin Result := @Modules[i].Module; Break; end; end; end; //------------- // Shows a MessageDialog (lParam: PChar Text, wParam: Symbol) //------------- function TCore.ShowMessage(wParam: TwParam; lParam: TlParam): integer; {$IFDEF MSWINDOWS} var Params: Cardinal; {$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} // TODO: 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); // FIXME: return a correct result Result := 0; end; //------------- // Calls NewDebugInfo HookChain (wParam: Pchar(Message), lParam: PChar(Reportername)) //------------- function TCore.ReportDebug(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hDebug, wParam, lParam); // FIXME: return a correct result Result := 0; end; //------------- // Calls Translate hook //------------- function TCore.Retranslate(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hTranslate, 1, nil); // FIXME: return a correct result Result := 0; end; //------------- // Calls LoadTextures hook //------------- function TCore.ReloadTextures(wParam: TwParam; lParam: TlParam): integer; begin Hooks.CallEventChain(hLoadTextures, 1, nil); // FIXME: return a correct result Result := 0; 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; var I: integer; begin if (Pointer(lParam) = nil) then begin Result := Length(Modules); end else begin try for I := 0 to High(Modules) do begin AModuleInfo(Pointer(lParam))[I].Name := Modules[I].Info.Name; AModuleInfo(Pointer(lParam))[I].Version := Modules[I].Info.Version; AModuleInfo(Pointer(lParam))[I].Description := Modules[I].Info.Description; end; Result := Length(Modules); 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.