Changeset 215 for branches/virtcpu fixed int/UMachine.pas
- Timestamp:
- Aug 19, 2020, 11:54:20 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/virtcpu fixed int/UMachine.pas
r168 r215 1 1 unit UMachine; 2 2 3 {$DEFINE EXT_MEMORY} 4 {$DEFINE EXT_IO} 5 {$DEFINE EXT_ARITHMETIC} 6 {$DEFINE EXT_CONDITIONAL} 7 {$DEFINE EXT_LOGICAL} 8 {$DEFINE EXT_STACK} 9 {$DEFINE EXT_SUBROUTINE} 10 {$DEFINE EXT_ROTATION} 11 {$DEFINE EXT_MULTIPLICATION} 12 {$DEFINE EXT_SHIFT} 13 {$DEFINE EXT_BLOCK} 14 {$DEFINE EXT_GENERAL} 15 {$DEFINE EXT_BIT} 16 {$DEFINE EXT_REL_JUMP} 17 18 // Extension dependencies 19 {$IFDEF EXT_SUBROUTINE} 20 {$DEFINE EXT_STACK} 21 {$ENDIF} 22 {$IFDEF EXT_MULTIPLICATION} 23 {$DEFINE EXT_ARITHMETIC} 24 {$ENDIF} 25 26 27 {$mode delphi}{$H+} 3 {$mode delphi} 28 4 29 5 interface 30 6 31 7 uses 32 Classes, SysUtils ;8 Classes, SysUtils, UCpu, syncobjs; 33 9 34 10 type 35 T = Integer;11 { TMachine } 36 12 37 TOpcode = (opNop, opLoad, opLoadConst, opNeg, 38 opJump, {$IFDEF EXT_REL_JUMP}opJumpRel,{$ENDIF} 39 opInc, opDec, 40 {$IFDEF EXT_MEMORY}opLoadMem, opStoreMem,{$ENDIF} 41 {$IFDEF EXT_ARITHMETIC}opAdd, opSub,{$ENDIF} 42 {$IFDEF EXT_IO}opInput, opOutput,{$ENDIF} 43 {$IFDEF EXT_SUBROUTINE}opCall, 44 {$IFDEF EXT_REL_JUMP}opCallRel,{$ENDIF} 45 opRet,{$ENDIF} 46 {$IFDEF EXT_GENERAL}opExchg,{$ENDIF} 47 {$IFDEF EXT_LOGICAL}opAnd, opOr, opXor,{$ENDIF} 48 {$IFDEF EXT_SHIFT}opShl, opShr,{$ENDIF} 49 {$IFDEF EXT_ROTATION}opRor, opRol,{$ENDIF} 50 {$IFDEF EXT_STACK}opPush, opPop,{$ENDIF} 51 {$IFDEF EXT_CONDITIONAL} 52 {$IFDEF EXT_REL_JUMP}opJumpRelZero, opJumpRelNotZero,{$ENDIF} 53 opJumpZero, opJumpNotZero, opTestEqual, opTestNotEqual, opTestLess, 54 opTestLessEqual, opTestGreater, opTestGreaterEqual, 55 {$ENDIF} 56 {$IFDEF EXT_MULTIPLICATION} 57 opMul, opDiv, 58 {$ENDIF} 59 opHalt 60 ); 61 62 TOpcodeHandler = procedure of object; 63 TInputEvent = function (Port: T): T of object; 64 TOutputEvent = procedure (Port, Value: T) of object; 65 66 { TCPU } 67 68 TCPU = class(TComponent) 13 TMachine = class(TComponent) 69 14 private 70 FOnInput: TInputEvent; 71 FOnOutput: TOutputEvent; 72 OpcodeHandlers: array[TOpcode] of TOpcodeHandler; 73 function ReadNext: T; inline; 74 procedure OpcodeNop; 75 procedure OpcodeHalt; 76 procedure OpcodeLoad; 77 procedure OpcodeLoadConst; 78 procedure OpcodeJump; 79 {$IFDEF EXT_REL_JUMP} 80 procedure OpcodeJumpRel; 81 {$ENDIF} 82 procedure OpcodeNeg; 83 procedure OpcodeInc; 84 procedure OpcodeDec; 85 {$IFDEF EXT_MEMORY} 86 procedure OpcodeLoadMem; 87 procedure OpcodeStoreMem; 88 {$ENDIF} 89 {$IFDEF EXT_GENERAL} 90 procedure OpcodeExchange; 91 {$ENDIF} 92 {$IFDEF EXT_CONDITIONAL} 93 procedure OpcodeTestEqual; 94 procedure OpcodeTestNotEqual; 95 procedure OpcodeTestGreatEqual; 96 procedure OpcodeTestGreat; 97 procedure OpcodeTestLessEqual; 98 procedure OpcodeTestLess; 99 procedure OpcodeJumpCondNotZero; 100 procedure OpcodeJumpCondZero; 101 {$IFDEF EXT_REL_JUMP} 102 procedure OpcodeJumpRelCondNotZero; 103 procedure OpcodeJumpRelCondZero; 104 {$ENDIF} 105 {$ENDIF} 106 {$IFDEF EXT_SHIFT} 107 procedure OpcodeShl; 108 procedure OpcodeShr; 109 {$ENDIF} 110 {$IFDEF EXT_ROTATION} 111 procedure OpcodeRor; 112 procedure OpcodeRol; 113 {$ENDIF} 114 {$IFDEF EXT_LOGICAL} 115 procedure OpcodeAnd; 116 procedure OpcodeOr; 117 procedure OpcodeXor; 118 {$ENDIF} 119 {$IFDEF EXT_STACK} 120 procedure OpcodePush; 121 procedure OpcodePop; 122 {$ENDIF} 123 {$IFDEF EXT_SUBROUTINE} 124 procedure OpcodeCall; 125 procedure OpcodeReturn; 126 {$IFDEF EXT_REL_JUMP} 127 procedure OpcodeCallRel; 128 {$ENDIF} 129 {$ENDIF} 130 {$IFDEF EXT_IO} 131 procedure OpcodeOutput; 132 procedure OpcodeInput; 133 {$ENDIF} 134 {$IFDEF EXT_ARITHMETIC} 135 procedure OpcodeAdd; 136 procedure OpcodeSub; 137 {$ENDIF} 138 {$IFDEF EXT_MULTIPLICATION} 139 procedure OpcodeMul; 140 procedure OpcodeDiv; 141 {$ENDIF} 15 FOnSerialOutput: TNotifyEvent; 16 function CpuInput(Port: T): T; 17 procedure CpuOutput(Port, Value: T); 18 procedure DoSerialOutput; 142 19 public 143 Registers: array of T;144 IP: T;145 {$IFDEF EXT_STACK}146 SP: T;147 {$ENDIF}148 20 Memory: array of T; 149 Terminated: Boolean; 150 Ticks: Integer; 151 procedure Start; 152 procedure Stop; 21 Cpu: TCpu; 22 VideoBase: T; 23 VideoWidth: T; 24 VideoHeight: T; 25 SerialBufferInput: array of Char; 26 SerialBufferOutput: array of Char; 27 SerialBufferLock: TCriticalSection; 153 28 constructor Create(AOwner: TComponent); override; 154 published155 pro perty OnInput: TInputEvent read FOnInput write FOnInput;156 property On Output: TOutputEvent read FOnOutput write FOnOutput;29 destructor Destroy; override; 30 procedure SerialInput(C: Char); 31 property OnSerialOutput: TNotifyEvent read FOnSerialOutput write FOnSerialOutput; 157 32 end; 158 159 33 160 34 implementation 161 35 162 { T CPU}36 { TMachine } 163 37 164 function TCPU.ReadNext: T;38 constructor TMachine.Create(AOwner: TComponent); 165 39 begin 166 Result := Memory[IP]; 167 Inc(IP); 40 inherited; 41 SerialBufferLock := TCriticalSection.Create; 42 Cpu := TCpu.Create(nil); 43 Cpu.OnInput := CpuInput; 44 Cpu.OnOutput := CpuOutput; 168 45 end; 169 46 170 procedure TCPU.OpcodeHalt;47 destructor TMachine.Destroy; 171 48 begin 172 Terminated := True; 49 Cpu.Stop; 50 FreeAndNil(Cpu); 51 FreeAndNil(SerialBufferLock); 52 inherited; 173 53 end; 174 54 175 procedure T CPU.OpcodeNop;55 procedure TMachine.SerialInput(C: Char); 176 56 begin 177 // Do nothing 178 end; 179 180 procedure TCPU.OpcodeLoad; 181 var 182 P1: T; 183 P2: T; 184 begin 185 P1 := ReadNext; 186 P2 := ReadNext; 187 Registers[P1] := Registers[P2]; 188 end; 189 190 procedure TCPU.OpcodeLoadConst; 191 var 192 P1: T; 193 P2: T; 194 begin 195 P1 := ReadNext; 196 P2 := ReadNext; 197 Registers[P1] := P2; 198 end; 199 200 {$IFDEF EXT_MEMORY} 201 procedure TCPU.OpcodeLoadMem; 202 var 203 P1: T; 204 P2: T; 205 begin 206 P1 := ReadNext; 207 P2 := ReadNext; 208 Registers[P1] := Memory[Registers[P2]]; 209 end; 210 211 procedure TCPU.OpcodeStoreMem; 212 var 213 P1: T; 214 P2: T; 215 begin 216 P1 := ReadNext; 217 P2 := ReadNext; 218 Memory[Registers[P1]] := Registers[P2]; 219 end; 220 {$ENDIF} 221 222 procedure TCPU.OpcodeNeg; 223 var 224 P1: T; 225 begin 226 P1 := ReadNext; 227 Registers[P1] := -Registers[P1]; 228 end; 229 230 {$IFDEF EXT_GENERAL} 231 procedure TCPU.OpcodeExchange; 232 var 233 P1, P2, Temp: T; 234 begin 235 P1 := ReadNext; 236 P2 := ReadNext; 237 Temp := Registers[P1]; 238 Registers[P1] := Registers[P2]; 239 Registers[P2] := Temp; 240 end; 241 {$ENDIF} 242 243 procedure TCPU.OpcodeJump; 244 begin 245 IP := ReadNext; 246 end; 247 248 {$IFDEF EXT_REL_JUMP} 249 procedure TCPU.OpcodeJumpRel; 250 begin 251 IP := IP + ReadNext; 252 end; 253 {$ENDIF} 254 255 {$IFDEF EXT_CONDITIONAL} 256 procedure TCPU.OpcodeTestEqual; 257 var 258 P1, P2: T; 259 begin 260 P1 := ReadNext; 261 P2 := ReadNext; 262 if Registers[P1] = Registers[P2] then Registers[P1] := 1 263 else Registers[P1] := 0; 264 end; 265 266 procedure TCPU.OpcodeTestNotEqual; 267 var 268 P1, P2: T; 269 begin 270 P1 := ReadNext; 271 P2 := ReadNext; 272 if Registers[P1] <> Registers[P2] then Registers[P1] := 1 273 else Registers[P1] := 0; 274 end; 275 276 procedure TCPU.OpcodeTestGreatEqual; 277 var 278 P1, P2: T; 279 begin 280 P1 := ReadNext; 281 P2 := ReadNext; 282 if Registers[P1] >= Registers[P2] then Registers[P1] := 1 283 else Registers[P1] := 0; 284 end; 285 286 procedure TCPU.OpcodeTestGreat; 287 var 288 P1, P2: T; 289 begin 290 P1 := ReadNext; 291 P2 := ReadNext; 292 if Registers[P1] > Registers[P2] then Registers[P1] := 1 293 else Registers[P1] := 0; 294 end; 295 296 procedure TCPU.OpcodeTestLessEqual; 297 var 298 P1, P2: T; 299 begin 300 P1 := ReadNext; 301 P2 := ReadNext; 302 if Registers[P1] <= Registers[P2] then Registers[P1] := 1 303 else Registers[P1] := 0; 304 end; 305 306 procedure TCPU.OpcodeTestLess; 307 var 308 P1, P2: T; 309 begin 310 P1 := ReadNext; 311 P2 := ReadNext; 312 if Registers[P1] < Registers[P2] then Registers[P1] := 1 313 else Registers[P1] := 0; 314 end; 315 316 procedure TCPU.OpcodeJumpCondNotZero; 317 var 318 P1, P2: T; 319 begin 320 P1 := ReadNext; 321 P2 := ReadNext; 322 if Registers[P1] <> 0 then IP := P2; 323 end; 324 325 procedure TCPU.OpcodeJumpCondZero; 326 var 327 P1, P2: T; 328 begin 329 P1 := ReadNext; 330 P2 := ReadNext; 331 if Registers[P1] = 0 then IP := P2; 332 end; 333 334 {$IFDEF EXT_REL_JUMP} 335 procedure TCPU.OpcodeJumpRelCondZero; 336 var 337 P1, P2: T; 338 begin 339 P1 := ReadNext; 340 P2 := ReadNext; 341 if P1 = 0 then IP := IP + P2; 342 end; 343 344 procedure TCPU.OpcodeJumpRelCondNotZero; 345 var 346 P1, P2: T; 347 begin 348 P1 := ReadNext; 349 P2 := ReadNext; 350 if P1 <> 0 then IP := IP + P2; 351 end; 352 {$ENDIF} 353 {$ENDIF} 354 355 {$IFDEF EXT_ROTATION} 356 procedure TCPU.OpcodeRor; 357 var 358 P1, P2: T; 359 begin 360 P1 := ReadNext; 361 P2 := ReadNext; 362 Registers[P1] := (Registers[P1] shr Registers[P2]) or 363 ((Registers[P1] and ((1 shl Registers[P2]) - 1)) shl (SizeOf(T) * 8 - Registers[P2])); 364 end; 365 366 procedure TCPU.OpcodeRol; 367 var 368 P1, P2: T; 369 begin 370 P1 := ReadNext; 371 P2 := ReadNext; 372 Registers[P1] := (Registers[P1] shl Registers[P2]) or 373 ((Registers[P1] shr (SizeOf(T) * 8 - Registers[P2])) and ((1 shl Registers[P2]) - 1)); 374 end; 375 {$ENDIF} 376 377 {$IFDEF EXT_SHIFT} 378 procedure TCPU.OpcodeShl; 379 var 380 P1, P2: T; 381 begin 382 P1 := ReadNext; 383 P2 := ReadNext; 384 Registers[P1] := Registers[P1] shl Registers[P2]; 385 end; 386 387 procedure TCPU.OpcodeShr; 388 var 389 P1, P2: T; 390 begin 391 P1 := ReadNext; 392 P2 := ReadNext; 393 Registers[P1] := Registers[P1] shr Registers[P2]; 394 end; 395 {$ENDIF} 396 397 {$IFDEF EXT_LOGICAL} 398 procedure TCPU.OpcodeAnd; 399 var 400 P1, P2: T; 401 begin 402 P1 := ReadNext; 403 P2 := ReadNext; 404 Registers[P1] := Registers[P1] and Registers[P2]; 405 end; 406 407 procedure TCPU.OpcodeOr; 408 var 409 P1, P2: T; 410 begin 411 P1 := ReadNext; 412 P2 := ReadNext; 413 Registers[P1] := Registers[P1] or Registers[P2]; 414 end; 415 416 procedure TCPU.OpcodeXor; 417 var 418 P1, P2: T; 419 begin 420 P1 := ReadNext; 421 P2 := ReadNext; 422 Registers[P1] := Registers[P1] xor Registers[P2]; 423 end; 424 {$ENDIF} 425 426 {$IFDEF EXT_STACK} 427 procedure TCPU.OpcodePush; 428 begin 429 Memory[SP] := Registers[ReadNext]; 430 Dec(SP); 431 end; 432 433 procedure TCPU.OpcodePop; 434 begin 435 Inc(SP); 436 Registers[ReadNext] := Memory[SP]; 437 end; 438 {$ENDIF} 439 440 {$IFDEF EXT_SUBROUTINE} 441 procedure TCPU.OpcodeCall; 442 var 443 Addr: T; 444 begin 445 Addr := ReadNext; 446 Memory[SP] := IP; 447 Dec(SP); 448 IP := Addr; 449 end; 450 451 {$IFDEF EXT_REL_JUMP} 452 procedure TCPU.OpcodeCallRel; 453 var 454 Addr: T; 455 begin 456 Addr := ReadNext; 457 Memory[SP] := IP; 458 Dec(SP); 459 IP := IP + Addr; 460 end; 461 {$ENDIF} 462 463 procedure TCPU.OpcodeReturn; 464 begin 465 Inc(SP); 466 IP := Memory[SP]; 467 end; 468 {$ENDIF} 469 470 {$IFDEF EXT_IO} 471 procedure TCPU.OpcodeOutput; 472 var 473 R1: T; 474 R2: T; 475 begin 476 R1 := ReadNext; 477 R2 := ReadNext; 478 if Assigned(FOnOutput) then 479 FOnOutput(Registers[R1], Registers[R2]); 480 end; 481 482 procedure TCPU.OpcodeInput; 483 var 484 R1: T; 485 R2: T; 486 begin 487 R1 := ReadNext; 488 R2 := ReadNext; 489 if Assigned(FOnInput) then 490 Registers[R1] := FOnInput(Registers[R2]); 491 end; 492 {$ENDIF} 493 494 procedure TCPU.OpcodeInc; 495 var 496 R: T; 497 begin 498 R := ReadNext; 499 Registers[R] := Registers[R] + 1; 500 end; 501 502 procedure TCPU.OpcodeDec; 503 var 504 R: T; 505 begin 506 R := ReadNext; 507 Registers[R] := Registers[R] - 1; 508 end; 509 510 {$IFDEF EXT_ARITHMETIC} 511 procedure TCPU.OpcodeAdd; 512 var 513 R1: T; 514 R2: T; 515 begin 516 R1 := ReadNext; 517 R2 := ReadNext; 518 Registers[R1] := Registers[R1] + Registers[R2]; 519 end; 520 521 procedure TCPU.OpcodeSub; 522 var 523 R1: T; 524 R2: T; 525 begin 526 R1 := ReadNext; 527 R2 := ReadNext; 528 Registers[R1] := Registers[R1] - Registers[R2]; 529 end; 530 {$ENDIF} 531 532 {$IFDEF EXT_MULTIPLICATION} 533 procedure TCPU.OpcodeMul; 534 var 535 R1: T; 536 R2: T; 537 begin 538 R1 := ReadNext; 539 R2 := ReadNext; 540 Registers[R1] := Registers[R1] * Registers[R2]; 541 end; 542 543 procedure TCPU.OpcodeDiv; 544 var 545 R1: T; 546 R2: T; 547 begin 548 R1 := ReadNext; 549 R2 := ReadNext; 550 Registers[R1] := Registers[R1] div Registers[R2]; 551 end; 552 {$ENDIF} 553 554 procedure TCPU.Start; 555 var 556 Opcode: T; 557 begin 558 Terminated := False; 559 IP := 0; 560 Ticks := 0; 561 {$IFDEF EXT_STACK} 562 SP := Length(Memory); 563 {$ENDIF} 564 while not Terminated do begin 565 Opcode := ReadNext; 566 if (Opcode >= 0) and (Opcode <= T(High(TOpcode))) then 567 OpcodeHandlers[TOpcode(Opcode)] 568 else raise Exception.Create(Format('Unsupported instruction %d', [Opcode])); 569 Inc(Ticks); 57 SerialBufferLock.Acquire; 58 try 59 SetLength(SerialBufferInput, Length(SerialBufferInput) + 1); 60 SerialBufferInput[High(SerialBufferInput)] := C; 61 finally 62 SerialBufferLock.Release; 570 63 end; 571 64 end; 572 65 573 procedure TCPU.Stop;66 function TMachine.CpuInput(Port: T): T; 574 67 begin 575 Terminated := True; 68 Result := 0; 69 case Port of 70 0: begin 71 SerialBufferLock.Acquire; 72 try 73 while (Length(SerialBufferInput) = 0) and not Cpu.Terminated do begin 74 try 75 SerialBufferLock.Release; 76 Sleep(10); 77 finally 78 SerialBufferLock.Acquire; 79 end; 80 end; 81 if Length(SerialBufferInput) > 0 then begin 82 Result := Ord(SerialBufferInput[0]); 83 if Length(SerialBufferInput) > 1 then 84 Move(SerialBufferInput[1], SerialBufferInput[0], Length(SerialBufferInput) - 1); 85 SetLength(SerialBufferInput, Length(SerialBufferInput) - 1); 86 end else Result := 0; 87 finally 88 SerialBufferLock.Release; 89 end; 90 end; 91 1: begin 92 Result := Length(SerialBufferInput); 93 end; 94 end; 576 95 end; 577 96 578 constructor TCPU.Create(AOwner: TComponent);97 procedure TMachine.CpuOutput(Port, Value: T); 579 98 begin 580 inherited; 581 SetLength(Registers, 16); 582 SetLength(Memory, 1024); 583 OpcodeHandlers[opNop] := OpcodeNop; 584 OpcodeHandlers[opLoad] := OpcodeLoad; 585 OpcodeHandlers[opHalt] := OpcodeHalt; 586 OpcodeHandlers[opLoadConst] := OpcodeLoadConst; 587 OpcodeHandlers[opNeg] := OpcodeNeg; 588 OpcodeHandlers[opJump] := OpcodeJump; 589 OpcodeHandlers[opInc] := OpcodeInc; 590 OpcodeHandlers[opDec] := OpcodeDec; 591 {$IFDEF EXT_REL_JUMP} 592 OpcodeHandlers[opJumpRel] := OpcodeJumpRel; 593 {$ENDIF} 594 {$IFDEF EXT_MEMORY} 595 OpcodeHandlers[opLoadMem] := OpcodeLoadMem; 596 OpcodeHandlers[opStoreMem] := OpcodeStoreMem; 597 {$ENDIF} 598 {$IFDEF EXT_GENERAL} 599 OpcodeHandlers[opExchg] := OpcodeExchange; 600 {$ENDIF} 601 {$IFDEF EXT_LOGICAL} 602 OpcodeHandlers[opAnd] := OpcodeAnd; 603 OpcodeHandlers[opOr] := OpcodeOr; 604 OpcodeHandlers[opXor] := OpcodeXor; 605 {$ENDIF} 606 {$IFDEF EXT_SHIFT} 607 OpcodeHandlers[opShl] := OpcodeShl; 608 OpcodeHandlers[opShr] := OpcodeShr; 609 {$ENDIF} 610 {$IFDEF EXT_STACK} 611 OpcodeHandlers[opPush] := OpcodePush; 612 OpcodeHandlers[opPop] := OpcodePop; 613 {$ENDIF} 614 {$IFDEF EXT_SUBROUTINE} 615 OpcodeHandlers[opCall] := OpcodeCall; 616 {$IFDEF EXT_REL_JUMP} 617 OpcodeHandlers[opCallRel] := OpcodeCallRel; 618 {$ENDIF} 619 OpcodeHandlers[opRet] := OpcodeReturn; 620 {$ENDIF} 621 {$IFDEF EXT_ROTATION} 622 OpcodeHandlers[opRor] := OpcodeRor; 623 OpcodeHandlers[opRol] := OpcodeRol; 624 {$ENDIF} 625 {$IFDEF EXT_IO} 626 OpcodeHandlers[opInput] := OpcodeInput; 627 OpcodeHandlers[opOutput] := OpcodeOutput; 628 {$ENDIF} 629 {$IFDEF EXT_ARITHMETIC} 630 OpcodeHandlers[opAdd] := OpcodeAdd; 631 OpcodeHandlers[opSub] := OpcodeSub; 632 {$ENDIF} 633 {$IFDEF EXT_CONDITIONAL} 634 OpcodeHandlers[opJumpZero] := OpcodeJumpCondZero; 635 OpcodeHandlers[opJumpNotZero] := OpcodeJumpCondNotZero; 636 {$IFDEF EXT_REL_JUMP} 637 OpcodeHandlers[opJumpRelZero] := OpcodeJumpRelCondZero; 638 OpcodeHandlers[opJumpRelNotZero] := OpcodeJumpRelCondNotZero; 639 {$ENDIF} 640 OpcodeHandlers[opTestEqual] := OpcodeTestEqual; 641 OpcodeHandlers[opTestNotEqual] := OpcodeTestNotEqual; 642 OpcodeHandlers[opTestLess] := OpcodeTestLess; 643 OpcodeHandlers[opTestLessEqual] := OpcodeTestLessEqual; 644 OpcodeHandlers[opTestGreater] := OpcodeTestGreat; 645 OpcodeHandlers[opTestGreaterEqual] := OpcodeTestGreatEqual; 646 {$ENDIF} 647 {$IFDEF EXT_MULTIPLICATION} 648 OpcodeHandlers[opMul] := OpcodeMul; 649 OpcodeHandlers[opDiv] := OpcodeDiv; 650 {$ENDIF} 99 case Port of 100 0: begin 101 SerialBufferLock.Acquire; 102 try 103 SetLength(SerialBufferOutput, Length(SerialBufferOutput) + 1); 104 SerialBufferOutput[High(SerialBufferOutput)] := Chr(Value); 105 finally 106 SerialBufferLock.Release; 107 end; 108 TThread.Synchronize(Cpu.Thread, DoSerialOutput); 109 end; 110 end; 111 end; 112 113 procedure TMachine.DoSerialOutput; 114 begin 115 if Assigned(FOnSerialOutput) then 116 FOnSerialOutput(Self); 651 117 end; 652 118
Note:
See TracChangeset
for help on using the changeset viewer.