Changeset 13 for trunk/Z80/Z80.pas


Ignore:
Timestamp:
Apr 21, 2026, 2:55:51 PM (6 days ago)
Author:
chronos
Message:
  • Added: Call stack window.
  • Modified: Use reload pending boolean variable and reload from timer instead of Thread.Synchronize to not delay CPU execution.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Z80/Z80.pas

    r12 r13  
    44
    55uses
    6   Classes, SysUtils, Memory, Base, Z80Instructions, Generics.Collections,
     6  Classes, SysUtils, MemoryTypes, Base, Z80Instructions, Generics.Collections,
    77  Generics.Defaults;
    88
     
    4141  end;
    4242
    43   TDebugMode = (dmNone, dmStepIn, dmStepOut, dmStepOver, dmStopAddress);
    44 
    45   { TBreakPoints }
    46 
    47   TBreakPoints = class(TList<Word>)
    48   private
    49     function Comparer(constref Left, Right: Word): Integer;
    50   public
    51     function Contains(Address: Word): Boolean;
    52     procedure AddNew(Address: Word);
    53   end;
    54 
    5543  { TCpuZ80 }
    5644
    5745  TCpuZ80 = class
    5846  private
     47    FOnCall: TAddressEvent;
    5948    FOnInput: TReadEvent;
    6049    FOnMessage: TMessageEvent;
    6150    FOnOutput: TWriteEvent;
    6251    FOnRead: TReadEvent;
     52    FOnReturn: TBaseEvent;
     53    FOnStep: TBaseEvent;
    6354    FOnWrite: TWriteEvent;
    6455    FRunning: Boolean;
     
    8576    procedure DoMessage(Text: string);
    8677    procedure DoMessageSync;
     78    procedure DoOnCall(Address: Word);
     79    procedure DoOnReturn;
     80    procedure DoOnStep;
    8781    function ReadByte: Byte;
    8882    function ReadWord: Word;
     
    832826    InterruptEnabled: Boolean;
    833827    InterruptMode: Byte;
    834     BreakPoints: TBreakPoints;
    835     DebugMode: TDebugMode;
    836     DebugStopAddress: Word;
    837828    Instructions: TInstructionMethods;
    838829    procedure Step;
     
    852843    property OnOutput: TWriteEvent read FOnOutput write FOnOutput;
    853844    property OnMessage: TMessageEvent read FOnMessage write FOnMessage;
     845    property OnCall: TAddressEvent read FOnCall write FOnCall;
     846    property OnReturn: TBaseEvent read FOnReturn write FOnReturn;
     847    property OnStep: TBaseEvent read FOnStep write FOnStep;
    854848  end;
    855849
     
    865859  end;
    866860  Cpu.FRunning := False;
    867 end;
    868 
    869 { TBreakPoints }
    870 
    871 function TBreakPoints.Comparer(constref Left, Right: Word): Integer;
    872 begin
    873   if Left > Right then Result := 1
    874   else if Left < Right then Result := -1
    875   else Result := 0;
    876 end;
    877 
    878 function TBreakPoints.Contains(Address: Word): Boolean;
    879 var
    880   Index: SizeInt;
    881 begin
    882   if (Count > 0) and BinarySearch(Address, Index, TComparer<Word>.Construct(Comparer)) then begin
    883     Result := True;
    884   end else Result := False;
    885 end;
    886 
    887 procedure TBreakPoints.AddNew(Address: Word);
    888 begin
    889   Add(Address);
    890   Sort;
    891861end;
    892862
     
    992962begin
    993963  MessageText := Text;
    994   FThread.Synchronize(DoMessageSync);
     964  DoMessageSync;
    995965  MessageText := '';
    996966end;
     
    999969begin
    1000970  if Assigned(FOnMessage) then FOnMessage(MessageText);
     971end;
     972
     973procedure TCpuZ80.DoOnCall(Address: Word);
     974begin
     975  if Assigned(FOnCall) then FOnCall(Address);
     976end;
     977
     978procedure TCpuZ80.DoOnReturn;
     979begin
     980  if Assigned(FOnReturn) then FOnReturn;
     981end;
     982
     983procedure TCpuZ80.DoOnStep;
     984begin
     985  if Assigned(FOnStep) then FOnStep;
    1001986end;
    1002987
     
    10281013procedure TCpuZ80.Call(Address: Word);
    10291014begin
    1030   if DebugMode = dmStepOver then begin
    1031     DebugStopAddress := PC;
    1032     DebugMode := dmStopAddress;
    1033   end;
     1015  DoOnCall(Address);
    10341016  PushWord(PC);
    10351017  PC := Address;
     
    10381020procedure TCpuZ80.CallCond(Address: Word; Condition: Boolean);
    10391021begin
    1040   if DebugMode = dmStepOver then begin
    1041     DebugStopAddress := PC;
    1042     DebugMode := dmStopAddress;
    1043   end;
     1022  DoOnCall(Address);
    10441023  if Condition then begin
    10451024    PushWord(PC);
     
    10771056  if Condition then begin
    10781057    PC := PopWord;
    1079     if DebugMode = dmStepOut then begin
    1080       FThread.Terminate;
    1081       DebugMode := dmNone;
    1082     end;
     1058    DoOnReturn;
    10831059  end;
    10841060end;
     
    55555531  end;
    55565532  Ticks := Cardinal(Ticks + 1);
    5557 
    5558   // Debugging
    5559   if DebugMode <> dmNone then begin
    5560     if DebugMode = dmStepIn then begin
    5561       DebugMode := dmNone;
    5562       FThread.Terminate;
    5563     end;
    5564     if (DebugMode = dmStopAddress) and (DebugStopAddress = PC) then begin
    5565       DebugMode := dmNone;
    5566       FThread.Terminate;
    5567     end;
    5568     if DebugMode = dmStepOver then begin
    5569       DebugMode := dmNone;
    5570       FThread.Terminate;
    5571     end;
    5572   end;
    5573   if BreakPoints.Contains(PC) then begin
    5574     DebugMode := dmNone;
    5575     FThread.Terminate;
    5576   end;
     5533  DoOnStep;
    55775534end;
    55785535
     
    55925549constructor TCpuZ80.Create;
    55935550begin
    5594   BreakPoints := TBreakPoints.Create;
    55955551  InitInstructions;
    55965552  Reset;
     
    56005556begin
    56015557  Running := False;
    5602   FreeAndNil(BreakPoints);
    56035558  inherited;
    56045559end;
Note: See TracChangeset for help on using the changeset viewer.