Changeset 465 for branches/highdpi/CmdList.pas
- Timestamp:
- Nov 30, 2023, 10:16:14 PM (12 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/highdpi/CmdList.pas
r361 r465 5 5 6 6 uses 7 Classes ;7 Classes, SysUtils, Math; 8 8 9 9 const 10 10 MaxDataSize = 1024; 11 CommandDataElementSize = 4; 12 CommandDataElementCountMask = $F; 13 CommandDataMaxSize = CommandDataElementSize * CommandDataElementCountMask; 11 14 12 15 type … … 24 27 constructor Create; 25 28 destructor Destroy; override; 26 procedure Get(var Command, Player, Subject: integer; var Data: pointer);27 procedure GetDataChanges(Data: pointer; DataSize: integer);28 procedure Put(Command, Player, Subject: integer; Data: pointer);29 procedure PutDataChanges(Command, Player: integer;30 OldData, NewData: pointer; DataSize: integer);31 procedure LoadFromFile(const f: TFileStream);32 procedure SaveToFile(const f: TFileStream);33 procedure AppendToFile(const f: TFileStream; const OldState: TCmdListState);29 procedure Get(var Command, Player, Subject: Integer; var Data: Pointer); 30 procedure GetDataChanges(Data: Pointer; DataSize: Integer); 31 procedure Put(Command, Player, Subject: Integer; Data: Pointer); 32 procedure PutDataChanges(Command, Player: Integer; 33 OldData, NewData: Pointer; DataSize: Integer); 34 procedure LoadFromFile(const F: TFileStream); 35 procedure SaveToFile(const F: TFileStream); 36 procedure AppendToFile(const F: TFileStream; const OldState: TCmdListState); 34 37 procedure Cut; 35 function Progress: integer;38 function Progress: Integer; 36 39 private 37 LogAlloc: integer; { allocated size of LogData in bytes }40 LogAlloc: Integer; { allocated size of LogData in bytes } 38 41 LogData: ^TLogData; 39 42 FState: TCmdListState; 40 procedure PutData(Data: pointer; Length: integer);43 procedure PutData(Data: Pointer; Length: Integer); 41 44 procedure CompleteMoveCode; 42 45 public … … 44 47 end; 45 48 49 function CommandWithData(Command: Integer; DataSize: Byte): Integer; 50 51 resourcestring 52 SCommandDataSizeError = 'Command data size %d out of range (0-%d).'; 53 54 46 55 implementation 47 56 … … 53 62 54 63 type 55 TData = array [0 ..MaxDataSize - 1] of Cardinal;64 TData = array [0..MaxDataSize - 1] of Cardinal; 56 65 PData = ^TData; 66 67 function CommandWithData(Command: Integer; DataSize: Byte): Integer; 68 var 69 DataElementCount: Byte; 70 begin 71 if DataSize > CommandDataMaxSize then 72 raise Exception.Create(Format(SCommandDataSizeError, [DataSize, CommandDataMaxSize])); 73 DataElementCount := Ceil(DataSize / CommandDataElementSize); 74 Result := Command or (DataElementCount and CommandDataElementCountMask); 75 end; 57 76 58 77 constructor TCmdList.Create; … … 73 92 end; 74 93 75 procedure TCmdList.Get(var Command, Player, Subject: integer; var Data: pointer);94 procedure TCmdList.Get(var Command, Player, Subject: Integer; var Data: Pointer); 76 95 var 77 96 DirCode: Cardinal; … … 108 127 else 109 128 begin 110 code := Cardinal((@LogData[FState.LoadPos])^);111 if code and 3 = 0 then129 Code := Cardinal((@LogData[FState.LoadPos])^); 130 if Code and 3 = 0 then 112 131 begin // non-clientex command 113 Command := code shr 2 and $3FFF + sExecute;114 Player := code shr 16 and $F;115 Subject := code shr 20 and $FFF;116 inc(FState.LoadPos, 4);117 end 118 else if code and 7 = 2 then132 Command := Code shr 2 and $3FFF + sExecute; 133 Player := Code shr 16 and $F; 134 Subject := Code shr 20 and $FFF; 135 Inc(FState.LoadPos, 4); 136 end 137 else if Code and 7 = 2 then 119 138 begin // clientex command 120 Command := code shr 3 and $FFFF;121 Player := code shr 19 and $F;139 Command := Code shr 3 and $FFFF; 140 Player := Code shr 19 and $F; 122 141 Subject := 0; 123 inc(FState.LoadPos, 3);142 Inc(FState.LoadPos, 3); 124 143 end 125 144 else 126 145 begin // move command shortcut 127 if ( code and 1 = 1) and (code and (7 shl 4) <> 6 shl 4) then146 if (Code and 1 = 1) and (Code and (7 shl 4) <> 6 shl 4) then 128 147 begin 129 FState.LoadMoveCode := code and $FF;130 inc(FState.LoadPos);148 FState.LoadMoveCode := Code and $FF; 149 Inc(FState.LoadPos); 131 150 end 132 151 else 133 152 begin 134 FState.LoadMoveCode := code and $FFFFFF;135 inc(FState.LoadPos, 3);153 FState.LoadMoveCode := Code and $FFFFFF; 154 Inc(FState.LoadPos, 3); 136 155 end; 137 156 Get(Command, Player, Subject, Data); … … 139 158 end; 140 159 141 if Command and $F= 0 then160 if Command and CommandDataElementCountMask = 0 then 142 161 Data := nil 143 162 else 144 163 begin 145 164 Data := @LogData[FState.LoadPos]; 146 inc(FState.LoadPos, Command and $F * 4);147 end; 148 end; 149 end; 150 151 procedure TCmdList.GetDataChanges(Data: pointer; DataSize: integer);165 Inc(FState.LoadPos, Command and CommandDataElementCountMask * CommandDataElementSize); 166 end; 167 end; 168 end; 169 170 procedure TCmdList.GetDataChanges(Data: Pointer; DataSize: Integer); 152 171 var 153 b0, b1: integer;172 b0, b1: Integer; 154 173 Map0, Map1: Cardinal; 155 174 begin 156 175 Map0 := Cardinal((@LogData[FState.LoadPos])^); 157 inc(FState.LoadPos, 4);176 Inc(FState.LoadPos, 4); 158 177 b0 := 0; 159 178 while Map0 > 0 do begin 160 179 if Map0 and 1 <> 0 then begin 161 180 Map1 := Cardinal((@LogData[FState.LoadPos])^); 162 inc(FState.LoadPos, 4);181 Inc(FState.LoadPos, 4); 163 182 for b1 := 0 to 31 do 164 183 if 1 shl b1 and Map1 <> 0 then begin 165 184 if b0 * 32 + b1 < DataSize then 166 185 PData(Data)[b0 * 32 + b1] := Cardinal((@LogData[FState.LoadPos])^); 167 inc(FState.LoadPos, 4);186 Inc(FState.LoadPos, 4); 168 187 end; 169 188 end; 170 inc(b0);189 Inc(b0); 171 190 Map0 := Map0 shr 1; 172 191 end; 173 192 end; 174 193 175 procedure TCmdList.Put(Command, Player, Subject: integer; Data: pointer);194 procedure TCmdList.Put(Command, Player, Subject: Integer; Data: Pointer); 176 195 var 177 DirCode, code: Cardinal;196 DirCode, Code: Cardinal; 178 197 begin 179 198 if Command and $FC00 = sMoveUnit then … … 190 209 end; 191 210 if Subject = FState.LastMovingUnit then 192 code := 1 + DirCode shl 1193 else 194 code := 6 + DirCode shl 3 + Cardinal(Subject) shl 6;211 Code := 1 + DirCode shl 1 212 else 213 Code := 6 + DirCode shl 3 + Cardinal(Subject) shl 6; 195 214 if FState.MoveCode = 0 then 196 FState.MoveCode := code215 FState.MoveCode := Code 197 216 else if FState.MoveCode and 1 = 1 then 198 217 begin // FM + this 199 FState.MoveCode := FState.MoveCode + code shl 4;200 if code and 1 = 1 then218 FState.MoveCode := FState.MoveCode + Code shl 4; 219 if Code and 1 = 1 then 201 220 PutData(@FState.MoveCode, 1) // FM + FM 202 221 else … … 204 223 FState.MoveCode := 0; 205 224 end 206 else if code and 1 = 1 then225 else if Code and 1 = 1 then 207 226 begin // M + FM 208 FState.MoveCode := FState.MoveCode + code shl 18;227 FState.MoveCode := FState.MoveCode + Code shl 18; 209 228 PutData(@FState.MoveCode, 3); 210 229 FState.MoveCode := 0; … … 213 232 begin 214 233 PutData(@FState.MoveCode, 3); 215 FState.MoveCode := code;234 FState.MoveCode := Code; 216 235 end; 217 236 FState.LastMovingUnit := Subject; … … 222 241 if Command >= cClientEx then 223 242 begin 224 code := 2 + Command shl 3 + Player shl 19;225 PutData(@ code, 3);226 end 227 else 228 begin 229 code := Cardinal(Command - sExecute) shl 2 + Cardinal(Player) shl 16 +243 Code := 2 + Command shl 3 + Player shl 19; 244 PutData(@Code, 3); 245 end 246 else 247 begin 248 Code := Cardinal(Command - sExecute) shl 2 + Cardinal(Player) shl 16 + 230 249 Cardinal(Subject) shl 20; 231 PutData(@ code, 4);232 end; 233 end; 234 if Command and $F<> 0 then235 PutData(Data, Command and $F * 4);236 end; 237 238 procedure TCmdList.PutDataChanges(Command, Player: integer;239 OldData, NewData: pointer; DataSize: integer);250 PutData(@Code, 4); 251 end; 252 end; 253 if Command and CommandDataElementCountMask <> 0 then 254 PutData(Data, Command and CommandDataElementCountMask * CommandDataElementSize); 255 end; 256 257 procedure TCmdList.PutDataChanges(Command, Player: Integer; 258 OldData, NewData: Pointer; DataSize: Integer); 240 259 var 241 MapPos, LogPos, b0, b1, RowEnd: integer;242 Map0, Map1, code: Cardinal;260 MapPos, LogPos, b0, b1, RowEnd: Integer; 261 Map0, Map1, Code: Cardinal; 243 262 begin 244 263 if DataSize <= 0 then 245 exit;264 Exit; 246 265 if DataSize > MaxDataSize then 247 266 DataSize := MaxDataSize; … … 254 273 if LogPos + 4 * 32 > LogAlloc then 255 274 begin 256 inc(LogAlloc, LogGrow);275 Inc(LogAlloc, LogGrow); 257 276 ReallocMem(LogData, LogAlloc); 258 277 end; … … 268 287 begin 269 288 Cardinal((@LogData[LogPos])^) := PData(NewData)[b1]; 270 inc(LogPos, 4);271 inc(Map1, $80000000);289 Inc(LogPos, 4); 290 Inc(Map1, $80000000); 272 291 end; 273 292 end; … … 277 296 Cardinal((@LogData[MapPos])^) := Map1; 278 297 MapPos := LogPos; 279 inc(LogPos, 4);280 inc(Map0, $80000000);298 Inc(LogPos, 4); 299 Inc(Map0, $80000000); 281 300 end; 282 301 end; 283 302 if Map0 = 0 then 284 exit; // no changes303 Exit; // no changes 285 304 286 305 Map0 := Map0 shr (31 - (DataSize - 1) div 32); 287 306 Cardinal((@LogData[FState.nLog + 4])^) := Map0; 288 code := Cardinal(Command - sExecute) shl 2 + Cardinal(Player) shl 16;289 Cardinal((@LogData[FState.nLog])^) := code;307 Code := Cardinal(Command - sExecute) shl 2 + Cardinal(Player) shl 16; 308 Cardinal((@LogData[FState.nLog])^) := Code; 290 309 FState.nLog := MapPos; 291 310 end; 292 311 293 procedure TCmdList.PutData(Data: pointer; Length: integer);312 procedure TCmdList.PutData(Data: Pointer; Length: Integer); 294 313 begin 295 314 if FState.nLog + Length > LogAlloc then 296 315 begin 297 inc(LogAlloc, LogGrow);316 Inc(LogAlloc, LogGrow); 298 317 ReallocMem(LogData, LogAlloc); 299 318 end; 300 move(Data^, LogData[FState.nLog], Length);301 inc(FState.nLog, Length);319 Move(Data^, LogData[FState.nLog], Length); 320 Inc(FState.nLog, Length); 302 321 end; 303 322 … … 314 333 end; 315 334 316 procedure TCmdList.LoadFromFile(const f: TFileStream);317 begin 318 f.read(FState.nLog, 4);335 procedure TCmdList.LoadFromFile(const F: TFileStream); 336 begin 337 F.Read(FState.nLog, 4); 319 338 LogData := nil; 320 339 LogAlloc := ((FState.nLog + 2) div LogGrow + 1) * LogGrow; 321 340 ReallocMem(LogData, LogAlloc); 322 f.read(LogData^, FState.nLog);341 F.Read(LogData^, FState.nLog); 323 342 FState.LoadPos := 0; 324 343 end; 325 344 326 procedure TCmdList.SaveToFile(const f: TFileStream);345 procedure TCmdList.SaveToFile(const F: TFileStream); 327 346 begin 328 347 CompleteMoveCode; 329 f.write(FState.nLog, 4);330 f.write(LogData^, FState.nLog);331 end; 332 333 procedure TCmdList.AppendToFile(const f: TFileStream;348 F.Write(FState.nLog, 4); 349 F.Write(LogData^, FState.nLog); 350 end; 351 352 procedure TCmdList.AppendToFile(const F: TFileStream; 334 353 const OldState: TCmdListState); 335 354 begin 336 355 CompleteMoveCode; 337 f.write(FState.nLog, 4);338 f.Position := f.Position + OldState.nLog;339 f.write(LogData[OldState.nLog], FState.nLog - OldState.nLog);356 F.Write(FState.nLog, 4); 357 F.Position := F.Position + OldState.nLog; 358 F.Write(LogData[OldState.nLog], FState.nLog - OldState.nLog); 340 359 end; 341 360 … … 345 364 end; 346 365 347 function TCmdList.Progress: integer;366 function TCmdList.Progress: Integer; 348 367 begin 349 368 if (FState.LoadPos = FState.nLog) and (FState.LoadMoveCode = 0) then 350 result := 1000 // loading complete369 Result := 1000 // loading complete 351 370 else if FState.nLog > 1 shl 20 then 352 result := (FState.LoadPos shr 8) * 999 div (FState.nLog shr 8)371 Result := (FState.LoadPos shr 8) * 999 div (FState.nLog shr 8) 353 372 else 354 result := FState.LoadPos * 999 div FState.nLog;373 Result := FState.LoadPos * 999 div FState.nLog; 355 374 end; 356 375 … … 360 379 Byte3 Byte2 Byte1 Byte0 361 380 ssssssss sssspppp cccccccc cccccc00 362 ( c = Command-sExecute, p = Player, s= Subject)381 (C = Command-sExecute, P = Player, S = Subject) 363 382 364 383 ClientEx-Command: 365 384 Byte2 Byte1 Byte0 366 385 0ppppccc cccccccc ccccc010 367 ( c = Command, p= Player)386 (C = Command, P = Player) 368 387 369 388 Single Move: 370 389 Byte2 Byte1 Byte0 371 390 000000ss ssssssss ssaaa110 372 ( a = Direction, s= Subject)391 (A = Direction, S = Subject) 373 392 374 393 Move + Follow Move: 375 394 Byte2 Byte1 Byte0 376 395 00bbb1ss ssssssss ssaaa110 377 ( a = Direction 1, s = Subject 1, b= Direction 2)396 (A = Direction 1, S = Subject 1, B = Direction 2) 378 397 379 398 Follow Move + Move: 380 399 Byte2 Byte1 Byte0 381 400 00ssssss ssssssbb b110aaa1 382 ( a = Direction 1, b = Direction 2, s= Subject 2)401 (A = Direction 1, B = Direction 2, S = Subject 2) 383 402 384 403 Single Follow Move: 385 404 Byte0 386 405 0000aaa1 387 ( a= Direction)406 (A = Direction) 388 407 389 408 Double Follow Move: 390 409 Byte0 391 410 bbb1aaa1 392 ( a = Direction 1, b= Direction 2)411 (A = Direction 1, B = Direction 2) 393 412 } 394 413
Note:
See TracChangeset
for help on using the changeset viewer.