library MapWindow; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. Important note about VCL usage: when this DLL will be implicitly loaded and this DLL uses TWicImage / TImageCollection created in any unit initialization section, then Vcl.WicImageInit must be included into your library's USES clause. } uses System.SysUtils, System.Classes, Windows, Forms, ShellAPI, Types, Dialogs, Controls, DateUtils, MATHLIB in '..\..\shared\pascal\MATHLIB.PAS', MATH387 in '..\..\shared\pascal\MATH387.PAS', uHCDefines in '..\..\shared\pascal\uHCDefines.pas', uHCGCI in '..\..\shared\pascal\uHCGCI.pas', uHCGlobals in '..\..\shared\pascal\uHCGlobals.pas', uHCTypeDefs in '..\..\shared\pascal\uHCTypeDefs.pas', uHCEventHelpers in '..\..\shared\pascal\uHCEventHelpers.pas', uHCDateTime in '..\..\shared\pascal\uHCDateTime.pas', uHCAnnexDefs in '..\..\shared\pascal\uHCAnnexDefs.pas', uHCAnnexHelpers in '..\..\shared\pascal\uHCAnnexHelpers.pas', uHCUtils in '..\..\shared\pascal\uHCUtils.pas', mainform in 'mainform.pas' {frmMain}, uCICG4Presenters in '..\..\..\shared\pascal\uCICG4Presenters.pas'; {$R *.res} const DLLVERN = 7; DLLVERINTN = 34; var frmMain: TfrmMain; {*** Return DLL internal version, i.e. revision 5 of my DLL ***} function DLLVer(): word; export; cdecl; begin Result := DLLVERN; end; {*** Return DLL interface version, i.e. revision 1 of my HCE interface spec ***} function DLLVerInt(): word; export; cdecl; begin Result := DLLVERINTN; end; {*** Return DLL description, 255 characters max ***} function DLLDesc(): PAnsiChar; export; cdecl; begin Result := 'Map Window test DLL by Tony Eischens'; end; {*** Free DLL ***} procedure DLLFree(); export; cdecl; begin // Do any cleanup here, this is the end frmMain.Free; end; {*** Init DLL ***} procedure DLLInit(hwndHC: HWND; pathHC: PAnsiChar; verHC: PAnsiChar; verSaveGame: longword; funcRefs: PHCDLL_FUNC_REF; PGEClosing: Pointer; PDLLBusy: Pointer; verInterface: longword; srandSeed: longword; harpoon_uuid_session: PAnsiChar; hclicense_dt_expire: Int64; hclicense_licensee: PAnsiChar; usblicense_desc: PAnsiChar; RESRSRStructureVersion: ulong; AnnexVersion: ushort); export; cdecl; var funcTmp: PHCDLL_FUNC_REF; lDLLFileName: String; begin // here we initialize globals and such for the life of the DLL Application.Initialize; // ALE 20120410 Freezes HC Application.Run; //uLazGUIGlobals.PGEClosing := PGEClosing; gDLLPathFileName := GetModuleName(hInstance); frmMain := TfrmMain.Create(nil); frmMain.ParentWindow := hwndHC; frmMain.Caption := 'MapWindow Export DLL v' + IntToStr(DLLVERN) + ', ExportDLL Interface v' + IntToStr(DLLVERINTN); frmMain.PDLLBusy := PDLLBusy; frmMain.rgVisibility.ItemIndex := 0; // ALE 20250912 default to player view { frmMain.memDLLInit.Lines.Add('lazarus GUI Export DLL v' + IntToStr(DLLVERN)); frmMain.memDLLInit.Lines.Add('ExportDLL Interface v' + IntToStr(DLLVERINTN)); frmMain.memDLLInit.Lines.Add('hwndHC = 0x' + IntToHex(hwndHC, 8)); frmMain.memDLLInit.Lines.Add('pathHC = ' + pathHC); frmMain.memDLLInit.Lines.Add('verHC = ' + verHC); frmMain.memDLLInit.Lines.Add('verSaveGame = 0x' + IntToHex(verSaveGame, 8)); frmMain.memDLLInit.Lines.Add(Format('funcRefs = 0x%p', [funcRefs])); frmMain.memDLLInit.Lines.Add(Format('GE ExportDLL Interface Version = %d', [verInterface])); frmMain.memDLLInit.Lines.Add('RESRSRStructureVersion = ' + IntToStr(RESRSRStructureVersion)); frmMain.memDLLInit.Lines.Add('AnnexVersion = ' + IntToStr(AnnexVersion)); frmMain.memDLLInit.Lines.add('harpoon_uuid_session = ' + harpoon_uuid_session); uLazGUIGlobals.intVerInterface := DLLVERINTN; uLazGUIGlobals.intVerSaveGame := verSaveGame; // ALE 20170224 Alert the user that the GE is too old for this ExportDLL if (verInterface < 27) then begin MessageDlg('GE too old', GetModuleName(hInstance) + ' is designed for HC2020.005+. Please ' + ' update your GE or disable this ExportDLL.', mtWarning, [mbOK], 0); end; // ALE 20130908 List the function pointers sent over by the GE // then capture one of them for example usage funcTmp := funcRefs; while (funcTmp <> nil) do begin frmMain.memDLLInit.Lines.Add(#9 + Format('funcRef: 0x%p %s', [funcTmp^.funcPtr, funcTmp^.funcName])); if (funcTmp^.funcName = 'NewPtr') then frmMain.NewPtr := funcTmp^.funcPtr else if (funcTmp^.funcName = 'DispPtr') then frmMain.DisposPtr := THCDisposPtr(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'QueueHarpoonEvent') then frmMain.HCQueueHarpoonEvent := THCQueueHarpoonEvent(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'dllCheckLatLonDepth') then frmMain.HCdllCheckLatLonDepth := THCdllCheckLatLonDepth(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'annex_id_to_disk_id') then frmMain.HCannex_id_to_disk_id := THCannex_id_to_disk_id(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'disk_id_to_annex_id') then frmMain.HCdisk_id_to_annex_id := THCdisk_id_to_annex_id(funcTmp^.funcPtr) else if (funcTmp^.funcName = 'MessageLogLine') then frmMain.HCMessageLogLine := THCMessageLogLine(funcTmp^.funcPtr); funcTmp := funcTmp^.Next; end; } end; procedure ScenLoad(strHarpPath: PAnsiChar; intScenNum: smallint; strScenFPath: PAnsiChar; intBSNum: shortint; strBSFName: PAnsiChar; intSide: byte; intGameTimeIn: Long; intGameTimeLeftIn: Long; AnnexDataIn: PHCAnnexes_disk; DatabaseVersionDBIn: PHCDATABASE_VERSION; ScenDataIn: PHCSCENARIO_DATA; ScenSaveDataIn: PHCSCENARIO_SAVE_DATA; GlobalsIn: PHCGlobals) export; cdecl; begin byte(frmMain.PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE gGameTime := intGameTimeIn; gGameTimeLeft := intGameTimeLeftIn; gSide := intSide; frmMain.Show; byte(frmMain.PDLLBusy^) := CFALSE; end; procedure GameTime(GameTime: Long; GameTimeLeft: Long); export; cdecl; var PEvent: PHCHarpoonEvent; PGroup: PHCGroup; EventType: uchar; strGroupID: string; dtNow: THCDateTimeRec; lPHCGThis: PHCGroup; lVisibility: uchar; begin byte(frmMain.PDLLBusy^) := CTRUE; // ALE 20130816 don't process other events in GE //intGameTime := GameTime; //intGameTimeLeft := GameTimeLeft; // ALE 20150712 store remaining time frmMain.lblGameTime.Caption := 'GameTime: ' + Format('%8.8d', [GameTime]); { dtNow := HCDateTimeInc(ScenData.dt_scen_start, intGameTime); frmMain.GTlblGameDateTime.Caption := 'GameDateTime: ' + Format('%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d', [dtNow.year, dtNow.month, dtNow.day, dtNow.hour, dtNow.minute, dtNow.second]); } // ALE 20220704 draw all of the groups on the map // ALE 20220704 clear groups from map. Optimize this later to update them frmMain.ClearGroups(layGroups); //layGroups.Objects.UnloadObjects; lPHCGThis := frmMain.PStartGroup; while (lPHCGThis <> nil) do begin // ALE 20220704 draw the group // ALE 20250912 but only if the visibility suggests we should if (frmMain.rgVisibility.ItemIndex = 1) then begin // ALE 20250912 God mode, see everything and precisely frmMain.AddGroup(lPHCGThis, ShowExact); end else begin lVisibility := HCGroupShowing(gSide, lPHCGThis); if lVisibility <> NotShowing then frmMain.AddGroup(lPHCGThis, lVisibility); end; lPHCGThis := lPHCGThis^.toSouth; end; byte(frmMain.PDLLBusy^) := CFALSE; end; procedure StartGroup(StartGroup: PHCGroup); export; cdecl; var PHCGThis: PHCGroup; begin // ALE 20130317 Fill up the SGlbxGroups frmMain.PStartGroup := StartGroup; { PHCGThis := StartGroup; while (PHCGThis <> nil) do begin frmMain.SGlbxGroups.Items.Add(PHCGThis^.id); PHCGThis := PHCGThis^.toSouth; end; end; } end; exports DLLVer, DLLVerInt, DLLDesc, DLLFree , DLLInit , ScenLoad { , UnitLatLon, UnitShowing, UnitURegion, UnitCourse, UnitSpeed, UnitAlt, UnitShowingSide, UnitSink, UnitToGroup, UnitNew, UnitFree, TimeFactor , MsgLog } , GameTime , StartGroup // ALE 20130205 Sends updated GroupPtr whenever that changes { , HarpoonEventHead // ALE 20130805 Sends updated soonest HarpoonEvent pointer whenever it changes , HarpoonEventQueued // ALE 20200825 Sends HarpoonEvent pointer when an event is added , SonobuoyRegionHead // ALE 20130812 Sends updated pointer to all sonobuoys when it changes , AllDeadUnitsPtr // ALE 20130812 Sends updated pointer to the list of killed units used for victory condition evaluation , WeatherGroups // ALE 20130812 Sends update GroupPtr whenever the top weather group changes , VictoryConditionsList // ALE 20130812 Sends a pointer to the list of victory conditions when a scenario is loaded , ActGroupPtr // ALE 20160305 Sends pointer to the Group the player just selected or NULL , ActUnitPtr // ALE 20160305 Sends pointer to the Unit the player just selected or NULL , SaveGame // ALE 20170923 UUIDs to associate any data with the right saved game file , VictoryConditionAchieved // ALE 20211212 Lets us know when a VC is achieved , VictoryConditionLevels // ALE 20211213 Lets us know when a VC level is reached by a side } ; end.