Changeset 12


Ignore:
Timestamp:
Apr 21, 2026, 11:04:26 AM (6 days ago)
Author:
chronos
Message:
  • Added: Implemented breakpoints and run to cursor action.
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Core.lfm

    r6 r12  
    4444      Caption = 'Run to cursor'
    4545      ShortCut = 115
     46      OnExecute = ARunToCursorExecute
    4647    end
    4748    object APause: TAction
  • trunk/Core.pas

    r11 r12  
    3737    procedure AResetExecute(Sender: TObject);
    3838    procedure ARunExecute(Sender: TObject);
     39    procedure ARunToCursorExecute(Sender: TObject);
    3940    procedure AStepInExecute(Sender: TObject);
    4041    procedure AStepOutExecute(Sender: TObject);
     
    139140end;
    140141
     142procedure TCore.ARunToCursorExecute(Sender: TObject);
     143begin
     144  SharpMz800.Cpu.DebugMode := dmStopAddress;
     145  SharpMz800.Cpu.DebugStopAddress := FormDisassembler.GetCurrentAddress;
     146  SharpMz800.Cpu.Running := True;
     147  UpdateInterface;
     148end;
     149
    141150procedure TCore.AStepInExecute(Sender: TObject);
    142151begin
     
    182191    FormDisassembler.Disassembler.Memory := SharpMz800.MappedMemory;
    183192    FormDisassembler.OnChangePC := DoChangePC;
     193    FormDisassembler.Cpu := SharpMz800.Cpu;
    184194    SharpMz800.OnMemoryMappingChange := FormDisassembler.Disassemble;
    185195  end;
  • trunk/Disassembler.pas

    r11 r12  
    5151
    5252const
    53   Comments: array[0..16] of TComment = (
     53  Comments: array[0..35] of TComment = (
     54    (Address: $3; Text: 'GETL (Reads one line of data from the keyboard and stores it in the memory area starting at the address in the DE register.)'),
    5455    (Address: $6; Text: 'LETNL (Moves the cursor to the beginning of the next line.)'),
     56    (Address: $9; Text: 'Line feed'),
    5557    (Address: $c; Text: 'PRNTS (Display a space at the cursor position.)'),
     58    (Address: $f; Text: 'Move cursor to next tab position'),
    5659    (Address: $12; Text: 'PRNTS (Display a character.)'),
    5760    (Address: $15; Text: 'MSG (Displays a message.)'),
     61    (Address: $18; Text: 'IOSVC'),
     62    (Address: $1b; Text: 'GETKEY (Reads a character code (ASCII) from the keyboard.)'),
     63    (Address: $1e; Text: 'BRKEY (Checks whether the I SHIFT I and I BREAK I keys are both being pressed.)'),
    5864    (Address: $30; Text: 'MELDY'),
     65    (Address: $33; Text: 'TIMST (Sets and starts the built-in clock.)'),
     66    (Address: $3b; Text: 'TIMRD (Reads the built-in clock and returns the time.'),
    5967    (Address: $3e; Text: 'BELL'),
    6068    (Address: $41; Text: 'XTEMP (Sets the music tempo.)'),
    6169    (Address: $44; Text: 'MSTA (Generates a continuous sound of the specified frequency.)'),
    62     (Address: $309; Text: 'Init 8253 counters.'),
     70    (Address: $47; Text: 'MSTP (Stops the sound generated with the CALL MSTA subroutine.)'),
     71    (Address: $308; Text: 'Init 8253 counters.'),
    6372    (Address: $3da; Text: 'ASC (Loads the ASCII character.)'),
    6473    (Address: $3f9; Text: 'HEX (Converts the 8 data bits stored in the ACC into a hexadecimal number.)'),
     
    6675    (Address: $41f; Text: '2HEX (Converts a string of 2 ASCII characters into a hexadecimal number and loads it into the ACC.)'),
    6776    (Address: $73e; Text: 'Init 8255 PIO.'),
     77    (Address: $9b3; Text: '??KEY (Blinks the cursor to prompt for key input.)'),
     78    (Address: $a32; Text: 'Something with 8255 PIO.'),
     79    (Address: $bb9; Text: '?ADCN (Converts ASCII codes into display codes.)'),
     80    (Address: $bce; Text: '?DACN (Converts display codes into ASCII codes.)'),
     81    (Address: $da6; Text: '?BLNK (Detects the vertical blanking period.)'),
     82    (Address: $ddc; Text: '?DPCT (Controls display.)'),
     83    (Address: $fb1; Text: '?POINT (Loads the current cursor location into the HL register.)'),
     84    (Address: $fd8; Text: 'Write FF to (HL) B times.'),
     85    (Address: $1171; Text: 'Cursor pos.'),
     86    (Address: $1172; Text: 'Cursor pos.'),
    6887    (Address: $e414; Text: 'Delay'),
    6988    (Address: $e800; Text: 'Cold start'),
  • trunk/Forms/FormDisassembler.lfm

    r11 r12  
    4949  end
    5050  object PopupMenu1: TPopupMenu
    51     Left = 433
    52     Top = 343
     51    OnPopup = PopupMenu1Popup
     52    Left = 440
     53    Top = 352
    5354    object MenuItemSetAddress: TMenuItem
    5455      Caption = 'Set PC to address'
    5556      OnClick = MenuItemSetAddressClick
    5657    end
     58    object MenuItemAddBreakPoint: TMenuItem
     59      Caption = 'Add break point'
     60      OnClick = MenuItemAddBreakPointClick
     61    end
     62    object MenuItemRemoveBreakPoint: TMenuItem
     63      Caption = 'Remove break point'
     64      OnClick = MenuItemRemoveBreakPointClick
     65    end
    5766  end
    5867end
  • trunk/Forms/FormDisassembler.pas

    r11 r12  
    55uses
    66  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls,
    7   ExtCtrls, Menus, Disassembler;
     7  ExtCtrls, Menus, Disassembler, Z80;
    88
    99type
    10   TChangePCEvent = procedure (Address: Word) of object;
     10  TAddressEvent = procedure (Address: Word) of object;
    1111
    1212  { TFormDisassembler }
     
    1414  TFormDisassembler = class(TForm)
    1515    ListView1: TListView;
     16    MenuItemRemoveBreakPoint: TMenuItem;
     17    MenuItemAddBreakPoint: TMenuItem;
    1618    MenuItemSetAddress: TMenuItem;
    1719    PopupMenu1: TPopupMenu;
     
    2123    procedure FormShow(Sender: TObject);
    2224    procedure ListView1Data(Sender: TObject; Item: TListItem);
     25    procedure MenuItemAddBreakPointClick(Sender: TObject);
     26    procedure MenuItemRemoveBreakPointClick(Sender: TObject);
    2327    procedure MenuItemSetAddressClick(Sender: TObject);
     28    procedure PopupMenu1Popup(Sender: TObject);
    2429  private
    25     FOnChangePC: TChangePCEvent;
     30    FOnAddBreakPoint: TAddressEvent;
     31    FOnChangePC: TAddressEvent;
    2632    procedure DoChangePC(Address: Word);
     33    procedure DoAddBreakPoint(Address: Word);
    2734  public
     35    Cpu: TCpuZ80;
    2836    Disassembler: TDisassembler;
    2937    procedure Disassemble(Sender: TObject);
    3038    procedure SelectAddress(Address: Word);
    3139    procedure ReloadList;
    32     property OnChangePC: TChangePCEvent read FOnChangePC write FOnChangePC;
     40    function GetCurrentAddress: Word;
     41    property OnChangePC: TAddressEvent read FOnChangePC write FOnChangePC;
     42    property OnAddBreakPoint: TAddressEvent read FOnAddBreakPoint write FOnAddBreakPoint;
    3343  end;
    3444
     
    6474
    6575procedure TFormDisassembler.ListView1Data(Sender: TObject; Item: TListItem);
     76var
     77  BreakPoint: string;
    6678begin
    6779  if Item.Index < Disassembler.DecodedInstructions.Count then
    6880  with TDecodedInstruction(Disassembler.DecodedInstructions[Item.Index]) do begin
    69     Item.Caption := IntToHex(Address, 4);
     81    if Cpu.BreakPoints.Contains(Address) then BreakPoint := ' @'
     82      else BreakPoint := '';
     83    Item.Caption := IntToHex(Address, 4) + BreakPoint;
    7084    Item.Data := Disassembler.DecodedInstructions[Item.Index];
    7185    Item.SubItems.Add(GetOpcodesText);
     
    7690end;
    7791
     92procedure TFormDisassembler.MenuItemAddBreakPointClick(Sender: TObject);
     93begin
     94  if Assigned(ListView1.Selected) then begin
     95    Cpu.BreakPoints.Add(TDecodedInstruction(ListView1.Selected.Data).Address);
     96    ReloadList;
     97  end;
     98end;
     99
     100procedure TFormDisassembler.MenuItemRemoveBreakPointClick(Sender: TObject);
     101begin
     102  if Assigned(ListView1.Selected) then begin
     103    Cpu.BreakPoints.Remove(TDecodedInstruction(ListView1.Selected.Data).Address);
     104    ReloadList;
     105  end;
     106end;
     107
    78108procedure TFormDisassembler.MenuItemSetAddressClick(Sender: TObject);
    79109begin
     
    81111    DoChangePC(TDecodedInstruction(ListView1.Selected.Data).Address);
    82112    SelectAddress(TDecodedInstruction(ListView1.Selected.Data).Address);
     113  end;
     114end;
     115
     116procedure TFormDisassembler.PopupMenu1Popup(Sender: TObject);
     117begin
     118
     119  MenuItemSetAddress.Enabled := Assigned(ListView1.Selected);
     120  if Assigned(ListView1.Selected) then begin
     121    MenuItemRemoveBreakPoint.Enabled := Pos('@', ListView1.Selected.Caption) > 0;
     122    MenuItemAddBreakPoint.Enabled := not MenuItemRemoveBreakPoint.Enabled;
     123  end else begin
     124    MenuItemRemoveBreakPoint.Enabled := False;
     125    MenuItemAddBreakPoint.Enabled := False;
    83126  end;
    84127end;
     
    93136begin
    94137  if Assigned(FOnChangePC) then FOnChangePC(Address);
     138end;
     139
     140procedure TFormDisassembler.DoAddBreakPoint(Address: Word);
     141begin
     142  if Assigned(FOnAddBreakPoint) then FOnAddBreakPoint(Address);
    95143end;
    96144
     
    124172end;
    125173
     174function TFormDisassembler.GetCurrentAddress: Word;
     175begin
     176  if Assigned(ListView1.Selected) then
     177    Result := TDecodedInstruction(ListView1.Selected.Data).Address
     178    else Result := 0;
     179end;
     180
    126181end.
    127182
  • trunk/Z80/Z80.pas

    r11 r12  
    44
    55uses
    6   Classes, SysUtils, Memory, Base, Z80Instructions;
     6  Classes, SysUtils, Memory, Base, Z80Instructions, Generics.Collections,
     7  Generics.Defaults;
    78
    89type
     
    4142
    4243  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;
    4354
    4455  { TCpuZ80 }
     
    821832    InterruptEnabled: Boolean;
    822833    InterruptMode: Byte;
     834    BreakPoints: TBreakPoints;
    823835    DebugMode: TDebugMode;
    824836    DebugStopAddress: Word;
     
    851863  while not Terminated do begin
    852864    Cpu.Step;
    853     if Cpu.DebugMode <> dmNone then begin
    854       if Cpu.DebugMode = dmStepIn then begin
    855         Cpu.DebugMode := dmNone;
    856         Terminate;
    857       end;
    858       if (Cpu.DebugMode = dmStopAddress) and (Cpu.DebugStopAddress = Cpu.PC) then begin
    859         Cpu.DebugMode := dmNone;
    860         Terminate;
    861       end;
    862       if Cpu.DebugMode = dmStepOver then begin
    863         Cpu.DebugMode := dmNone;
    864         Terminate;
    865       end;
    866     end;
    867865  end;
    868866  Cpu.FRunning := False;
     867end;
     868
     869{ TBreakPoints }
     870
     871function TBreakPoints.Comparer(constref Left, Right: Word): Integer;
     872begin
     873  if Left > Right then Result := 1
     874  else if Left < Right then Result := -1
     875  else Result := 0;
     876end;
     877
     878function TBreakPoints.Contains(Address: Word): Boolean;
     879var
     880  Index: SizeInt;
     881begin
     882  if (Count > 0) and BinarySearch(Address, Index, TComparer<Word>.Construct(Comparer)) then begin
     883    Result := True;
     884  end else Result := False;
     885end;
     886
     887procedure TBreakPoints.AddNew(Address: Word);
     888begin
     889  Add(Address);
     890  Sort;
    869891end;
    870892
     
    55335555  end;
    55345556  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;
    55355577end;
    55365578
     
    55505592constructor TCpuZ80.Create;
    55515593begin
     5594  BreakPoints := TBreakPoints.Create;
    55525595  InitInstructions;
    55535596  Reset;
     
    55575600begin
    55585601  Running := False;
     5602  FreeAndNil(BreakPoints);
    55595603  inherited;
    55605604end;
Note: See TracChangeset for help on using the changeset viewer.