1 //////////////////////////////////////////////////
2 //                                              //
3 // Emu64                                        //
4 // von Thorsten Kattanek                        //
5 //                                              //
6 // #file: debugger_window.cpp                   //
7 //                                              //
8 // Dieser Sourcecode ist Copyright geschützt!   //
9 // Geistiges Eigentum von Th.Kattanek           //
10 //                                              //
11 // Letzte Änderung am 01.04.2020                //
12 // www.emu64.de                                 //
13 //                                              //
14 //////////////////////////////////////////////////
15 
16 #include <QScreen>
17 #include <QStyle>
18 
19 #include "./debugger_window.h"
20 #include "./ui_debugger_window.h"
21 #include "./micro_code_tbl_6510.h"
22 #include "./micro_code_string_tbl_6510.h"
23 
DebuggerWindow(QWidget * parent,QSettings * ini)24 DebuggerWindow::DebuggerWindow(QWidget* parent, QSettings* ini) :
25     QDialog(parent),
26     ui(new Ui::DebuggerWindow),
27     memory_window(nullptr),
28     vic_window(nullptr),
29     iec_window(nullptr)
30 {
31     this->ini = ini;
32     c64 = nullptr;
33 
34     current_source = 0;
35 
36     table_back_color = QColor(255,255,255);
37     table_position_color = QColor(255,200,200);
38 
39     old_adresse = 0;
40     old_make_idx = 0;
41 
42     ui->setupUi(this);
43 
44     // Center Window
45     setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), QGuiApplication::screens()[0]->availableGeometry()));
46 
47     memory_window = new MemoryWindow(this);
48     memory_window->ChangeSource(0);
49 
50     vic_window = new DebuggerVicWindow(this);
51     iec_window = new DebuggerIECWindow(this);
52 
53     new_refresh = false;
54     timer1 = new QTimer(this);
55     connect(timer1, SIGNAL(timeout()), this, SLOT(onTimerAnimationRefresh()));
56     timer1->setInterval(10);
57 
58     icon_off = new QIcon(":/grafik/blue_led_off.png");
59     icon_on = new QIcon(":/grafik/blue_led_on.png");
60     ui->EingabeFeld->hide();
61 
62     QFontDatabase fontDB;
63     fontDB.addApplicationFont(":/fonts/lucon.ttf");
64     QFont font1("Lucida Console",8);
65 
66     ui->MCodeHelp->setFont(font1);
67 
68     ui->DisAssTable->setColumnCount(4);
69     ui->DisAssTable->setColumnWidth(0, 44);
70     ui->DisAssTable->setColumnWidth(1, 70);
71     ui->DisAssTable->setColumnWidth(2, 30);
72     ui->DisAssTable->setColumnWidth(3, 57);
73 
74     ui->DisAssTable->setFont(font1);
75     ui->DisAssTable->setRowCount(DISASS_ROW);
76 
77     ui->AssAdresseIn->setFont(font1);
78     ui->AssMnemonicIn->setFont(font1);
79     ui->AssAdressierungIn->setFont(font1);
80 
81     ui->BreakpointTree->setColumnCount(2);
82     ui->BreakpointTree->setColumnWidth(0, 175);
83     ui->BreakpointTree->setColumnWidth(1, 50);
84     new_breakpoint_found = false;
85 
86     ui->HistoryList->setFont(font1);
87     for(int i=0; i<HISTORY_ROW; i++)
88     {
89         QListWidgetItem *item = new QListWidgetItem(ui->HistoryList);
90         item->setText(QVariant(i).toString());
91         ui->HistoryList->addItem(item);
92     }
93 
94     for(int i=0; i<DISASS_ROW; i++)
95     {
96         view_code_address[i] = 0;
97         disass_pc[i] = new QTableWidgetItem();
98         disass_pc[i]->setBackground(table_back_color);
99         ui->DisAssTable->setItem(i, 0, disass_pc[i]);
100         disass_memory[i] = new QTableWidgetItem();
101         disass_memory[i]->setBackground(table_back_color);
102         ui->DisAssTable->setItem(i, 1, disass_memory[i]);
103         disass_mnemonic[i] = new QTableWidgetItem();
104         disass_mnemonic[i]->setBackground(table_back_color);
105         ui->DisAssTable->setItem(i, 2, disass_mnemonic[i]);
106         disass_addressing[i] = new QTableWidgetItem();
107         disass_addressing[i]->setBackground(table_back_color);
108         ui->DisAssTable->setItem(i, 3, disass_addressing[i]);
109     }
110 
111     connect(ui->sr_widget, SIGNAL(ChangeValue(uint8_t)), this, SLOT(onSr_widget_ValueChange(uint8_t)));
112     connect(ui->pc_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
113     connect(ui->sp_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
114     connect(ui->ac_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
115     connect(ui->xr_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
116     connect(ui->yr_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
117     connect(ui->sr_out, SIGNAL(clicked(LabelWidgetMod*)), this, SLOT(onReg_label_clicked(LabelWidgetMod*)));
118 
119     current_edit_reg = -1;
120 
121     rw_string = QStringList() << "[READ]" << "[WRITE]";
122 
123     connect(ui->DisAssTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onShowContextMenu(QPoint)));
124 
125     ////////// Load from INI ///////////
126     if(ini != nullptr)
127     {
128         ini->beginGroup("DebuggerWindow");
129         if(ini->contains("Geometry")) restoreGeometry(ini->value("Geometry").toByteArray());
130         ini->endGroup();
131     }
132     ////////////////////////////////////
133 
134     timer1->start();
135 }
136 
~DebuggerWindow()137 DebuggerWindow::~DebuggerWindow()
138 {
139     ////////// Save to INI ///////////
140     if(ini != nullptr)
141     {
142         ini->beginGroup("DebuggerWindow");
143         if(is_one_showed) ini->setValue("Geometry", saveGeometry());
144         if(isHidden()) ini->setValue("Show", false);
145         else ini->setValue("Show", true);
146         ini->endGroup();
147     }
148     ////////////////////////////////////
149 
150     delete icon_off;
151     delete icon_on;
152     delete timer1;
153     delete ui;
154 
155     if(memory_window != nullptr) delete memory_window;
156     if(vic_window != nullptr) delete vic_window;
157     if(iec_window != nullptr) delete iec_window;
158 }
159 
AnimationRefreshProc()160 void DebuggerWindow::AnimationRefreshProc()
161 {
162     new_refresh = true;
163 }
164 
onTimerAnimationRefresh()165 void DebuggerWindow::onTimerAnimationRefresh()
166 {
167     if(new_refresh)
168     {
169         new_refresh = false;
170         if(c64 != nullptr)
171         {
172             if(current_source > 0)
173             {
174                 floppy_cpu_reg[currnet_floppy_nr].reg_mask = REG_MASK_ALL;
175                 c64->floppy[currnet_floppy_nr]->GetCpuReg(&floppy_cpu_reg[currnet_floppy_nr], &floppy_cpu_ireg[currnet_floppy_nr]);
176                 FillDisassemblyList(floppy_cpu_ireg[currnet_floppy_nr].current_opcode_pc, false);
177             }
178             else
179             {
180                 c64_cpu_reg.reg_mask = REG_MASK_ALL;
181                 c64->GetC64CpuReg(&c64_cpu_reg,&c64_cpu_ireg);
182                 FillDisassemblyList(c64_cpu_ireg.current_opcode_pc,false);
183             }
184         }
185 
186         UpdateRegister();
187         FillHistoryList(static_cast<uint8_t>(ui->HistoryScroll->value()));
188         memory_window->UpdateMemoryList();
189         vic_window->UpdateOutputList();
190         iec_window->UpdateSignals();
191     }
192 
193     if(new_breakpoint_found)
194     {
195         new_breakpoint_found = false;
196         on_AnimationStop_clicked();
197 
198         for(int i=0;i<c64->GetBreakGroupCount();i++)
199         {
200             BREAK_GROUP *bg = c64->GetBreakGroup(i);
201             if(bg->bTrue)
202             {
203                 ui->ChangeSource->setCurrentIndex(0);
204                 if(i < ui->BreakpointTree->topLevelItemCount())
205                 {
206                     ui->BreakpointTree->topLevelItem(i)->setBackground(0, QColor(0, 255, 0));
207                     ui->BreakpointTree->topLevelItem(i)->setBackground(1, QColor(1, 255, 0));
208                     ui->BreakpointTree->topLevelItem(i)->setText(1, tr("ERFÜLLT !"));
209                 }
210             }
211         }
212 
213         for(int i=0; i<MAX_FLOPPY_NUM; i++)
214         {
215             if(c64->floppy[i]->GetEnableFloppy())
216             {
217                 for(int ii=0; ii<c64->floppy[i]->GetBreakGroupCount(); ii++)
218                 {
219                     BREAK_GROUP *bg = c64->floppy[i]->GetBreakGroup(ii);
220                     if(bg->bTrue)
221                     {
222                         ui->ChangeSource->setCurrentIndex(i+1);
223                         if(ii < ui->BreakpointTree->topLevelItemCount())
224                         {
225                             ui->BreakpointTree->topLevelItem(ii)->setBackground(0, QColor(0, 255, 0));
226                             ui->BreakpointTree->topLevelItem(ii)->setBackground(1, QColor(1, 255, 0));
227                             ui->BreakpointTree->topLevelItem(ii)->setText(1, tr("ERFÜLLT !"));
228                         }
229                     }
230                 }
231             }
232         }
233         show();
234     }
235 }
236 
RetranslateUi()237 void DebuggerWindow::RetranslateUi()
238 {
239     ui->retranslateUi(this);
240     ui->sr_widget->RetranslateUi();
241 
242     this->update();
243     this->UpdateRegister();
244 
245     vic_window->RetranslateUi();
246     memory_window->RetranslateUi();
247     iec_window->RetranslateUi();
248 }
249 
SetC64Pointer(C64Class * c64)250 void DebuggerWindow::SetC64Pointer(C64Class *c64)
251 {
252     this->c64 = c64;
253     memory_window->SetC64Pointer(c64);
254     vic_window->SetC64Pointer(c64);
255     iec_window->SetC64Pointer(c64);
256     this->c64->AnimationRefreshProc = bind(&DebuggerWindow::AnimationRefreshProc, this);
257     this->c64->BreakpointProc = bind(&DebuggerWindow::BreakpointProc, this);
258 }
259 
showEvent(QShowEvent *)260 void DebuggerWindow::showEvent(QShowEvent*)
261 {
262     is_one_showed = true;
263     c64->SetDebugMode(true);
264     RefreshGUI();
265 }
266 
hideEvent(QHideEvent *)267 void DebuggerWindow::hideEvent(QHideEvent*)
268 {
269     /// HIDE ///
270 
271     memory_window->hide();
272     vic_window->hide();
273     iec_window->hide();
274 
275     c64->SetDebugMode(false);
276     c64->SetDebugAnimation(false);
277 
278     ui->OneOpcode->setEnabled(true);
279     ui->OneZyklus->setEnabled(true);
280     ui->AnimationStart->setEnabled(true);
281     ui->AnimationStop->setEnabled(false);
282     ui->DisAssScroll->setEnabled(true);
283 
284     ui->AssAdresseIn->setEnabled(true);
285     ui->AssMnemonicIn->setEnabled(true);
286     ui->AssAdressierungIn->setEnabled(true);
287 }
288 
UpdateRegister()289 void DebuggerWindow::UpdateRegister()
290 {
291     if(c64 == nullptr) return;
292 
293     char str00[1024];
294 
295     if(current_source > 0)
296     {
297         /// Floppy's ///
298 
299         if(!c64->floppy[currnet_floppy_nr]->GetEnableFloppy()) return;
300 
301         sprintf(str00,"$%4.4X", floppy_cpu_reg[currnet_floppy_nr].pc);
302         ui->pc_out->setText(QString(str00));
303         sprintf(str00,"$%2.2X", floppy_cpu_reg[currnet_floppy_nr].sp + 0x100);
304         ui->sp_out->setText(QString(str00));
305         sprintf(str00,"$%2.2X", floppy_cpu_reg[currnet_floppy_nr].ac);
306         ui->ac_out->setText(QString(str00));
307         sprintf(str00,"$%2.2X", floppy_cpu_reg[currnet_floppy_nr].xr);
308         ui->xr_out->setText(QString(str00));
309         sprintf(str00,"$%2.2X", floppy_cpu_reg[currnet_floppy_nr].yr);
310         ui->yr_out->setText(QString(str00));
311         sprintf(str00,"$%2.2X", floppy_cpu_reg[currnet_floppy_nr].sr);
312         ui->sr_out->setText(QString(str00));
313         ui->sr_widget->SetValue(floppy_cpu_reg[currnet_floppy_nr].sr);
314 
315         sprintf(str00,"$%4.4X", floppy_cpu_reg[currnet_floppy_nr].irq);
316         ui->irq_out->setText(QString(str00));
317         sprintf(str00,"$%4.4X", floppy_cpu_reg[currnet_floppy_nr].nmi);
318         ui->nmi_out->setText(QString(str00));
319         sprintf(str00,"$%4.4X", floppy_cpu_reg[currnet_floppy_nr]._0314);
320         ui->_0314_out->setText(QString(str00));
321         sprintf(str00,"$%4.4X", floppy_cpu_reg[currnet_floppy_nr]._0318);
322         ui->_0318_out->setText(QString(str00));
323 
324         sprintf(str00,"$%4.4X", floppy_cpu_ireg[currnet_floppy_nr].current_opcode_pc);
325         ui->opcode_pc_out->setText(QString(str00));
326         sprintf(str00,"$%3.3X", floppy_cpu_ireg[currnet_floppy_nr].current_opcode);
327         ui->opcode_out->setText(QString(str00));
328         sprintf(str00,"$%4.4X", floppy_cpu_ireg[currnet_floppy_nr].address);
329         ui->adresse_out->setText(QString(str00));
330         sprintf(str00,"$%4.4X", floppy_cpu_ireg[currnet_floppy_nr].branch_address);
331         ui->branch_adresse_out->setText(QString(str00));
332         sprintf(str00,"$%2.2X", floppy_cpu_ireg[currnet_floppy_nr].pointer);
333         ui->pointer_out->setText(QString(str00));
334         sprintf(str00,"$%2.2X", floppy_cpu_ireg[currnet_floppy_nr].tmp_byte);
335         ui->tmp_byte_out->setText(QString(str00));
336         sprintf(str00,"%10.10d", floppy_cpu_ireg[currnet_floppy_nr].cycle_counter);
337         ui->CycleCounter_Out->setText(QString(str00));
338 
339         sprintf(str00,"%3.3d ", floppy_cpu_ireg[currnet_floppy_nr].current_micro_code);
340         ui->micro_code_out->setText(str00 + rw_string[micro_code_rw_table_6510[floppy_cpu_ireg[currnet_floppy_nr].current_micro_code]]);
341 
342         ui->MCodeHelp->setText(micro_code_string_table_6510[floppy_cpu_ireg[currnet_floppy_nr].current_micro_code]);
343         ui->mnemonic_out->setText(QString(CpuOPC).mid(floppy_cpu_ireg[currnet_floppy_nr].current_opcode * 3, 3));
344 
345         if(floppy_cpu_ireg[currnet_floppy_nr].irq) ui->irq_led->setIcon(*icon_on);
346         else ui->irq_led->setIcon(*icon_off);
347         if(!floppy_cpu_ireg[currnet_floppy_nr].reset) ui->reset_led->setIcon(*icon_on);
348         else ui->reset_led->setIcon(*icon_off);
349     }
350     else
351     {
352         /// C64 ///
353         sprintf(str00, "$%4.4X", c64_cpu_reg.pc);
354         ui->pc_out->setText(QString(str00));
355         sprintf(str00, "$%2.2X", c64_cpu_reg.sp + 0x100);
356         ui->sp_out->setText(QString(str00));
357         sprintf(str00, "$%2.2X", c64_cpu_reg.ac);
358         ui->ac_out->setText(QString(str00));
359         sprintf(str00, "$%2.2X", c64_cpu_reg.xr);
360         ui->xr_out->setText(QString(str00));
361         sprintf(str00, "$%2.2X", c64_cpu_reg.yr);
362         ui->yr_out->setText(QString(str00));
363         sprintf(str00, "$%2.2X", c64_cpu_reg.sr);
364         ui->sr_out->setText(QString(str00));
365         ui->sr_widget->SetValue(c64_cpu_reg.sr);
366 
367         sprintf(str00, "$%4.4X", c64_cpu_reg.irq);
368         ui->irq_out->setText(QString(str00));
369         sprintf(str00, "$%4.4X", c64_cpu_reg.nmi);
370         ui->nmi_out->setText(QString(str00));
371         sprintf(str00, "$%4.4X", c64_cpu_reg._0314);
372         ui->_0314_out->setText(QString(str00));
373         sprintf(str00, "$%4.4X", c64_cpu_reg._0318);
374         ui->_0318_out->setText(QString(str00));
375 
376         sprintf(str00, "$%4.4X", c64_cpu_ireg.current_opcode_pc);
377         ui->opcode_pc_out->setText(QString(str00));
378         sprintf(str00, "$%3.3X", c64_cpu_ireg.current_opcode);
379         ui->opcode_out->setText(QString(str00));
380         sprintf(str00, "$%4.4X", c64_cpu_ireg.address);
381         ui->adresse_out->setText(QString(str00));
382         sprintf(str00, "$%4.4X", c64_cpu_ireg.branch_address);
383         ui->branch_adresse_out->setText(QString(str00));
384         sprintf(str00, "$%2.2X", c64_cpu_ireg.pointer);
385         ui->pointer_out->setText(QString(str00));
386         sprintf(str00, "$%2.2X", c64_cpu_ireg.tmp_byte);
387         ui->tmp_byte_out->setText(QString(str00));
388         sprintf(str00,"%10.10d", c64_cpu_ireg.cycle_counter);
389         ui->CycleCounter_Out->setText(QString(str00));
390 
391         sprintf(str00, "%3.3d ", c64_cpu_ireg.current_micro_code);
392         ui->micro_code_out->setText(str00 + rw_string[micro_code_rw_table_6510[c64_cpu_ireg.current_micro_code]]);
393 
394         ui->MCodeHelp->setText(micro_code_string_table_6510[c64_cpu_ireg.current_micro_code]);
395         ui->mnemonic_out->setText(QString(CpuOPC).mid(c64_cpu_ireg.current_opcode * 3, 3));
396 
397         if(c64_cpu_ireg.cpu_wait) ui->wait_led->setIcon(*icon_on);
398         else ui->wait_led->setIcon(*icon_off);
399 
400         if(!ui->man_lines->checkState())
401         {
402             if(c64_cpu_ireg.irq) ui->irq_led->setIcon(*icon_on);
403             else ui->irq_led->setIcon(*icon_off);
404             if(c64_cpu_ireg.nmi) ui->nmi_led->setIcon(*icon_on);
405             else ui->nmi_led->setIcon(*icon_off);
406             if(c64_cpu_ireg.rdy) ui->rdy_led->setIcon(*icon_on);
407             else ui->rdy_led->setIcon(*icon_off);
408         }
409         if(!c64_cpu_ireg.reset) ui->reset_led->setIcon(*icon_on);
410         else ui->reset_led->setIcon(*icon_off);
411         if(c64_cpu_ireg.exrom) ui->exrom_led->setIcon(*icon_on);
412         else ui->exrom_led->setIcon(*icon_off);
413         if(c64_cpu_ireg.game) ui->game_led->setIcon(*icon_on);
414         else ui->game_led->setIcon(*icon_off);
415     }
416 }
417 
onShowContextMenu(const QPoint & pos)418 void DebuggerWindow::onShowContextMenu(const QPoint& pos)
419 {
420     // for most widgets
421     QPoint globalPos = ui->DisAssTable->mapToGlobal(pos);
422     // for QAbstractScrollArea and derived classes you would use:
423     // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);
424 
425     QMenu myMenu;
426     myMenu.addAction(tr("Test1"));
427     // ...
428 
429     QAction* selectedItem = myMenu.exec(globalPos);
430     if (selectedItem)
431     {
432         // something was chosen, do stuff
433     }
434     else
435     {
436         // nothing was chosen
437     }
438 }
439 
onSr_widget_ValueChange(uint8_t value)440 void DebuggerWindow::onSr_widget_ValueChange(uint8_t value)
441 {
442     on_AnimationStop_clicked();
443 
444     ui->EingabeFeld->hide();
445 
446     REG_STRUCT cpu_reg;
447     cpu_reg.reg_mask = REG_MASK_SR;
448     cpu_reg.sr = value;
449 
450     char str00[50];
451 
452     sprintf(str00,"$%2.2X",value);
453     ui->sr_out->setText(str00);
454 
455     if(current_source > 0)
456     {
457         c64->floppy[currnet_floppy_nr]->SetCpuReg(&cpu_reg);
458     }
459     else c64->cpu->SetRegister(&cpu_reg);
460 }
461 
onReg_label_clicked(LabelWidgetMod * label)462 void DebuggerWindow::onReg_label_clicked(LabelWidgetMod* label)
463 {
464     on_AnimationStop_clicked();
465 
466     current_edit_reg = -1;
467 
468     if(label->objectName() == "pc_out") current_edit_reg = 0;
469     if(label->objectName() == "sp_out") current_edit_reg = 1;
470     if(label->objectName() == "ac_out") current_edit_reg = 2;
471     if(label->objectName() == "xr_out") current_edit_reg = 3;
472     if(label->objectName() == "yr_out") current_edit_reg = 4;
473     if(label->objectName() == "sr_out") current_edit_reg = 5;
474 
475     ui->EingabeFeld->setGeometry(label->geometry());
476 
477     ui->EingabeFeld->setText(label->text());
478     ui->EingabeFeld->selectAll();
479     ui->EingabeFeld->show();
480     ui->EingabeFeld->setFocus();
481 }
482 
on_EingabeFeld_returnPressed()483 void DebuggerWindow::on_EingabeFeld_returnPressed()
484 {
485     if(current_edit_reg == -1)
486     {
487         ui->EingabeFeld->hide();
488         return;
489     }
490 
491     bool ok;
492     QString in_str = ui->EingabeFeld->text();
493     uint16_t value;
494 
495     if(in_str.left(1) == "$") in_str.replace(0, 1, "0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
496 
497     value = in_str.toUShort(&ok, 0);
498 
499     if(!ok)
500     {
501         QMessageBox::warning(this, tr("Eingabefehler..."), tr("Es wurde kein gültiges Zahlenformat benutzt !"));
502         return;
503     }
504 
505     REG_STRUCT cpu_reg;
506 
507     switch(current_edit_reg)
508     {
509     case 0:
510         cpu_reg.reg_mask = REG_MASK_PC;
511         cpu_reg.pc = value;
512         break;
513     case 1:
514         if(value > 0x100) value -= 0x100;
515         if(value > 0xFF)
516         {
517             QMessageBox::warning(this, tr("Eingabefehler..."), tr("Der Wert muss zwischen 0 und 511 liegen !"));
518             return;
519         }
520         cpu_reg.reg_mask = REG_MASK_SP;
521         cpu_reg.sp = static_cast<uint8_t>(value);
522         break;
523     case 2:
524         if(value > 0xFF)
525         {
526             QMessageBox::warning(this, tr("Eingabefehler..."), tr("Der Wert muss zwischen 0 und 255 liegen !"));
527             return;
528         }
529         cpu_reg.reg_mask = REG_MASK_AC;
530         cpu_reg.ac = static_cast<uint8_t>(value);
531         break;
532     case 3:
533         if(value > 0xFF)
534         {
535             QMessageBox::warning(this, tr("Eingabefehler..."), tr("Der Wert muss zwischen 0 und 255 liegen !"));
536             return;
537         }
538         cpu_reg.reg_mask = REG_MASK_XR;
539         cpu_reg.xr = static_cast<uint8_t>(value);
540         break;
541     case 4:
542         if(value > 0xFF)
543         {
544             QMessageBox::warning(this, tr("Eingabefehler..."), tr("Der Wert muss zwischen 0 und 255 liegen !"));
545             return;
546         }
547         cpu_reg.reg_mask = REG_MASK_YR;
548         cpu_reg.yr = static_cast<uint8_t>(value);
549         break;
550     case 5:
551         if(value > 0xFF)
552         {
553             QMessageBox::warning(this, tr("Eingabefehler..."), tr("Der Wert muss zwischen 0 und 255 liegen !"));
554             return;
555         }
556         cpu_reg.reg_mask = REG_MASK_SR;
557         cpu_reg.sr = static_cast<uint8_t>(value);
558         break;
559     }
560 
561     if(current_source > 0)
562     {
563         c64->floppy[currnet_floppy_nr]->SetCpuReg(&cpu_reg);
564         c64->floppy[currnet_floppy_nr]->GetCpuReg(&floppy_cpu_reg[currnet_floppy_nr], &floppy_cpu_ireg[currnet_floppy_nr]);
565     }
566     else
567     {
568         c64->cpu->SetRegister(&cpu_reg);
569         c64->cpu->GetRegister(&c64_cpu_reg);
570     }
571 
572     current_edit_reg = -1;
573     ui->EingabeFeld->hide();
574     UpdateRegister();
575 }
576 
on_OneZyklus_clicked()577 void DebuggerWindow::on_OneZyklus_clicked()
578 {
579     ui->EingabeFeld->hide();
580     ClearAllBreakpointBackcolors();
581     c64->OneCycle();
582 }
583 
on_OneOpcode_clicked()584 void DebuggerWindow::on_OneOpcode_clicked()
585 {
586     ui->EingabeFeld->hide();
587     ClearAllBreakpointBackcolors();
588     c64->OneOpcode(current_source);
589 }
590 
on_CycleCounterReset_clicked()591 void DebuggerWindow::on_CycleCounterReset_clicked()
592 {
593     if(current_source > 0)
594     {
595         c64->floppy[currnet_floppy_nr]->ResetCycleCounter();
596     }
597     else
598     {
599         c64->ResetC64CycleCounter();
600     }
601     ui->CycleCounter_Out->setText("0000000000");
602 }
603 
FillDisassemblyList(uint16_t address,bool new_refresh)604 void DebuggerWindow::FillDisassemblyList(uint16_t address, bool new_refresh)
605 {
606     uint16_t pc = address;
607     char str00[50];
608     uint16_t tmp;
609     uint16_t word;
610     uint8_t tmp1;
611     bool find = false;
612     int akt_make_idx = 0;
613 
614     if(current_source > 0)
615     {
616         if(!c64->floppy[current_source-1]->GetEnableFloppy()) return;
617     }
618 
619     if(!new_refresh)
620     {
621         for(int i=0;i<DISASS_ROW;i++)
622         {
623             if(view_code_address[i] == address)
624             {
625                 find = true;
626                 akt_make_idx = i;
627             }
628         }
629     }
630 
631     if(find)
632     {
633         disass_pc[old_make_idx]->setBackground(table_back_color);
634         disass_memory[old_make_idx]->setBackground(table_back_color);
635         disass_mnemonic[old_make_idx]->setBackground(table_back_color);
636         disass_addressing[old_make_idx]->setBackground(table_back_color);
637 
638         disass_pc[akt_make_idx]->setBackground(table_position_color);
639         disass_memory[akt_make_idx]->setBackground(table_position_color);
640         disass_mnemonic[akt_make_idx]->setBackground(table_position_color);
641         disass_addressing[akt_make_idx]->setBackground(table_position_color);
642 
643         old_make_idx = akt_make_idx;
644         pc = old_adresse;
645     }
646     else
647     {
648         disass_pc[old_make_idx]->setBackground(table_back_color);
649         disass_memory[old_make_idx]->setBackground(table_back_color);
650         disass_mnemonic[old_make_idx]->setBackground(table_back_color);
651         disass_addressing[old_make_idx]->setBackground(table_back_color);
652 
653         disass_pc[0]->setBackground(table_position_color);
654         disass_memory[0]->setBackground(table_position_color);
655         disass_mnemonic[0]->setBackground(table_position_color);
656         disass_addressing[0]->setBackground(table_position_color);
657 
658         old_make_idx = akt_make_idx = 0;
659         pc = old_adresse = address;
660     }
661 
662     uint8_t ram0;
663     uint8_t ram1;
664     uint8_t ram2;
665 
666     for(int i=0; i<DISASS_ROW; i++)
667     {
668         view_code_address[i] = pc;
669         sprintf(str00, "$%4.4X", pc);
670         disass_pc[i]->setText(str00);
671 
672         if(current_source > 0)
673         {
674             currnet_floppy_nr = current_source - 1;
675             ram0 = c64->floppy[currnet_floppy_nr]->ReadByte(pc+0);
676             ram1 = c64->floppy[currnet_floppy_nr]->ReadByte(pc+1);
677             ram2 = c64->floppy[currnet_floppy_nr]->ReadByte(pc+2);
678         }
679         else
680         {
681             ram0 = c64->ReadC64Byte(pc+0);
682             ram1 = c64->ReadC64Byte(pc+1);
683             ram2 = c64->ReadC64Byte(pc+2);
684         }
685 
686         disass_mnemonic[i]->setText(QString(CpuOPC).mid(ram0*3, 3));
687 
688         tmp = CpuOPCInfo[ram0];
689 
690         if(!(tmp&8))
691         {
692             disass_mnemonic[i]->setForeground(QColor(0,0,0));
693         }
694         else
695         {
696             disass_mnemonic[i]->setForeground(QColor(255,0,0));
697         }
698 
699         tmp >>= 4;
700         tmp &= 15;
701         switch(tmp)
702         {
703         case 0:
704             disass_addressing[i]->setText("");
705 
706             sprintf(str00,"%2.2X -- --",ram0);
707             disass_memory[i]->setText(str00);
708             pc++;
709             break;
710         case 1:
711             sprintf(str00,"#$%2.2X",ram1);
712             disass_addressing[i]->setText(str00);
713 
714             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
715             disass_memory[i]->setText(str00);
716             pc+=2;
717             break;
718         case 2:
719             word=ram1;
720             word|=ram2<<8;
721             sprintf(str00,"$%4.4X",word);
722             disass_addressing[i]->setText(str00);
723 
724             sprintf(str00,"%2.2X %2.2X %2.2X",ram0,ram1,ram2);
725             disass_memory[i]->setText(str00);
726             pc+=3;
727             break;
728         case 3:
729             sprintf(str00,"$%2.2X",ram1);
730             disass_addressing[i]->setText(str00);
731 
732             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
733             disass_memory[i]->setText(str00);
734             pc+=2;
735             break;
736         case 4:
737             word=ram1;
738             word|=ram2<<8;
739             sprintf(str00,"$%4.4X,X",word);
740             disass_addressing[i]->setText(str00);
741 
742             sprintf(str00,"%2.2X %2.2X %2.2X",ram0,ram1,ram2);
743             disass_memory[i]->setText(str00);
744             pc+=3;
745             break;
746         case 5:
747             word=ram1;
748             word|=ram2<<8;
749             sprintf(str00,"$%4.4X,Y",word);
750             disass_addressing[i]->setText(str00);
751 
752             sprintf(str00,"%2.2X %2.2X %2.2X",ram0,ram1,ram2);
753             disass_memory[i]->setText(str00);
754             pc+=3;
755             break;
756         case 6:
757             sprintf(str00,"$%2.2X,X",ram1);
758             disass_addressing[i]->setText(str00);
759 
760             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
761             disass_memory[i]->setText(str00);
762             pc+=2;
763             break;
764         case 7:
765             sprintf(str00,"($%2.2X,X)",ram1);
766             disass_addressing[i]->setText(str00);
767 
768             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
769             disass_memory[i]->setText(str00);
770             pc+=2;
771             break;
772         case 8:
773             sprintf(str00,"($%2.2X),Y",ram1);
774             disass_addressing[i]->setText(str00);
775 
776             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
777             disass_memory[i]->setText(str00);
778             pc+=2;
779             break;
780         case 9:
781             tmp1 = ram1;
782             word = (pc+2)+tmp1;
783             sprintf(str00,"$%4.4X",word);
784             disass_addressing[i]->setText(str00);
785 
786             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
787             disass_memory[i]->setText(str00);
788             pc+=2;
789             break;
790         case 10:
791             word=ram1;
792             word|=ram2<<8;
793             sprintf(str00,"($%4.4X)",word);
794             disass_addressing[i]->setText(str00);
795 
796             sprintf(str00,"%2.2X %2.2X %2.2X",ram0,ram1,ram2);
797             disass_memory[i]->setText(str00);
798             pc+=3;
799             break;
800         case 11:
801             sprintf(str00,"$%2.2X,Y",ram1);
802             disass_addressing[i]->setText(str00);
803 
804             sprintf(str00,"%2.2X %2.2X --",ram0,ram1);
805             disass_memory[i]->setText(str00);
806             pc+=2;
807             break;
808         }
809     }
810 }
811 
FillHistoryList(uint8_t index)812 void DebuggerWindow::FillHistoryList(uint8_t index)
813 {
814     char str00[10];
815     uint8_t hp;
816 
817     if(current_source > 0)
818     {
819         if(!c64->floppy[currnet_floppy_nr]->GetEnableFloppy()) return;
820         hp = c64->floppy[currnet_floppy_nr]->HistoryPointer;
821         for(int i=0; i<HISTORY_ROW; i++)
822         {
823             sprintf(str00, "$%4.4X", c64->floppy[currnet_floppy_nr]->History[hp--]);
824             ui->HistoryList->item(i)->setText(QString(str00));
825         }
826     }
827     else
828     {
829         hp = c64->cpu_pc_history_pos - index;
830         for(int i=0; i<HISTORY_ROW; i++)
831         {
832             sprintf(str00, "$%4.4X", c64->cpu_pc_history[hp--]);
833             ui->HistoryList->item(i)->setText(QString(str00));
834         }
835     }
836 }
837 
on_ChangeSource_currentIndexChanged(int index)838 void DebuggerWindow::on_ChangeSource_currentIndexChanged(int index)
839 {
840     current_source = index;
841     if(current_source > 0)
842     {
843         currnet_floppy_nr = current_source - 1;
844         ui->BreakpointTree->clear();
845 
846         if(c64 == nullptr) return;
847         break_point_update_enable = false;
848         int anz = c64->floppy[currnet_floppy_nr]->GetBreakGroupCount();
849         for(int i=0;i<anz;i++)
850         {
851             BREAK_GROUP *bg = c64->floppy[currnet_floppy_nr]->GetBreakGroup(i);
852             AddBreakpointTreeRoot(bg->Name, bg);
853         }
854         break_point_update_enable = true;
855     }
856     else
857     {
858         /// Alle Haltepunke ins TreeWidget einfügen ///
859 
860         ui->BreakpointTree->clear();
861 
862         if(c64 == nullptr) return;
863         break_point_update_enable = false;
864         int anz = c64->GetBreakGroupCount();
865         for(int i=0;i<anz;i++)
866         {
867             BREAK_GROUP *bg = c64->GetBreakGroup(i);
868             AddBreakpointTreeRoot(bg->Name, bg);
869         }
870         break_point_update_enable = true;
871     }
872 
873     ui->AssAdresseIn->setText("");
874     ui->AssMnemonicIn->setText("");
875     ui->AssAdressierungIn->setText("");
876     memory_window->ChangeSource(current_source);
877     RefreshGUI();
878 }
879 
on_AssAdresseIn_returnPressed()880 void DebuggerWindow::on_AssAdresseIn_returnPressed()
881 {
882     bool ok;
883     uint16_t value;
884     QString in_str = ui->AssAdresseIn->text();
885 
886     if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
887     value = in_str.toUShort(&ok,0);
888     if(!ok)
889     {
890         QMessageBox::warning(this, tr("Eingabefehler..."), tr("Es wurde kein gültiges Zahlenformat benutzt !"));
891         return;
892     }
893 
894     char out_str[10];
895     sprintf(out_str, "$%4.4X", value);
896 
897     ui->AssAdresseIn->setText(out_str);
898     ui->AssMnemonicIn->clear();
899     ui->AssAdressierungIn->clear();
900     ui->AssMnemonicIn->setFocus();
901 }
902 
on_AssMnemonicIn_textChanged(const QString & arg1)903 void DebuggerWindow::on_AssMnemonicIn_textChanged(const QString &arg1)
904 {
905     if(arg1.length() == 3)
906     {
907         if(FindMnemonic(arg1))
908         {
909             ui->AssMnemonicIn->setText(ui->AssMnemonicIn->text().toUpper());
910             ui->AssAdressierungIn->clear();
911             ui->AssAdressierungIn->setFocus();
912         }
913         else
914         {
915             QMessageBox::warning(this,"Eingabefehler...","Unbekanntes Mnemonic !");
916             ui->AssMnemonicIn->setFocus();
917             ui->AssMnemonicIn->selectAll();
918         }
919     }
920 }
921 
FindMnemonic(QString mnemonic,uint8_t * opcode,uint8_t * opcode_count)922 bool DebuggerWindow::FindMnemonic(QString mnemonic, uint8_t *opcode, uint8_t *opcode_count)
923 {
924     bool found = false;
925     uint8_t count = 0;
926 
927     for(int i=0; i<256; i++)
928     {
929         if(mnemonic.toUpper() == QString(CpuOPC).mid(i*3,3))
930         {
931             found = true;
932             if(opcode != nullptr) opcode[count++] = static_cast<uint8_t>(i);
933         }
934     }
935     if(opcode_count != nullptr) *opcode_count = count;
936     return found;
937 }
938 
FindAddressing(QString address_string,uint8_t * address_type,uint16_t * address_value)939 bool DebuggerWindow::FindAddressing(QString address_string, uint8_t *address_type, uint16_t *address_value)
940 {
941     uint32_t integer;
942     bool ok;
943 
944     QString in_str = address_string.toUpper();
945 
946     if(in_str == "")
947     {
948         *address_type = 0;
949         *address_value = 0;
950         return true;
951     }
952 
953 
954     if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
955     integer = in_str.toUShort(&ok,0);
956     if(ok)
957     {
958         if(integer <= 0xFF)
959         {
960             *address_type = 3;
961             *address_value = static_cast<uint16_t>(integer);
962             return true;
963         }
964 
965         if(integer <= 0xFFFF)
966         {
967             *address_type = 2;
968             *address_value = static_cast<uint16_t>(integer);
969             return true;
970         }
971     }
972 
973     if(in_str.left(1) == "#")
974     {
975         in_str.remove(0,1);
976         if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
977         integer = in_str.toUShort(&ok,0);
978         if(ok)
979         {
980             if(integer <= 0xFF)
981             {
982                 *address_type = 1;
983                 *address_value = static_cast<uint16_t>(integer);
984                 return true;
985             }
986             else return false;
987         }
988         else return false;
989     }
990 
991     if(in_str.right(2) == ",X")
992     {
993         QString tmp_str = in_str;
994         tmp_str.remove(tmp_str.length()-2,2);
995         if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
996         integer = tmp_str.toUShort(&ok,0);
997         if(ok)
998         {
999             if(integer <= 0xFF)
1000             {
1001                 *address_type = 6;
1002                 *address_value = static_cast<uint16_t>(integer);
1003                 return true;
1004             }
1005 
1006             if(integer <= 0xFFFF)
1007             {
1008                 *address_type = 4;
1009                 *address_value = static_cast<uint16_t>(integer);
1010                 return true;
1011             }
1012             return false;
1013         }
1014     }
1015 
1016     if(in_str.right(2) == ",Y")
1017     {
1018         QString tmp_str = in_str;
1019         tmp_str.remove(tmp_str.length()-2,2);
1020         if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1021         integer = tmp_str.toUShort(&ok,0);
1022         if(ok)
1023         {
1024             if(integer <= 0xFF)
1025             {
1026                 *address_type = 11;
1027                 *address_value = static_cast<uint16_t>(integer);
1028                 return true;
1029             }
1030 
1031             if(integer <= 0xFFFF)
1032             {
1033                 *address_type = 5;
1034                 *address_value = static_cast<uint16_t>(integer);
1035                 return true;
1036             }
1037             return false;
1038         }
1039     }
1040 
1041     if((in_str.left(1) == "(") && (in_str.right(3) == ",X)"))
1042     {
1043         QString tmp_str = in_str;
1044         tmp_str = tmp_str.mid(1,tmp_str.length()-4);
1045         if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1046         integer = tmp_str.toUShort(&ok,0);
1047         if(ok)
1048         {
1049             if(integer <= 0xFF)
1050             {
1051                 *address_type = 7;
1052                 *address_value = static_cast<uint16_t>(integer);
1053                 return true;
1054             }
1055             else return false;
1056         }
1057         else return false;
1058     }
1059 
1060     if((in_str.left(1) == "(") && (in_str.right(3) == "),Y"))
1061     {
1062         QString tmp_str = in_str;
1063         tmp_str = tmp_str.mid(1,tmp_str.length()-4);
1064         if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1065         integer = tmp_str.toUShort(&ok,0);
1066         if(ok)
1067         {
1068             if(integer <= 0xFF)
1069             {
1070                 *address_type = 8;
1071                 *address_value = static_cast<uint16_t>(integer);
1072                 return true;
1073             }
1074             else return false;
1075         }
1076         else return false;
1077     }
1078 
1079     if((in_str.left(1) == "(") && (in_str.right(1) == ")"))
1080     {
1081         QString tmp_str = in_str;
1082         tmp_str = tmp_str.mid(1,tmp_str.length()-2);
1083         if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1084         integer = tmp_str.toUShort(&ok,0);
1085         if(ok)
1086         {
1087             if(integer <= 0xFFFF)
1088             {
1089                 *address_type = 10;
1090                 *address_value = static_cast<uint16_t>(integer);
1091                 return true;
1092             }
1093             else return false;
1094         }
1095         else return false;
1096     }
1097     return false;
1098 }
1099 
on_AssAdressierungIn_returnPressed()1100 void DebuggerWindow::on_AssAdressierungIn_returnPressed()
1101 {
1102     uint16_t ass_adress;
1103     uint16_t new_adress;
1104 
1105     if(Assemble(ui->AssAdresseIn->text(), ui->AssMnemonicIn->text(), ui->AssAdressierungIn->text(), &ass_adress, &new_adress))
1106     {
1107         char out_str[10];
1108         sprintf(out_str, "$%4.4X", new_adress);
1109         ui->AssAdresseIn->setText(QString(out_str));
1110         ui->AssMnemonicIn->clear();
1111         ui->AssAdressierungIn->clear();
1112         ui->AssMnemonicIn->setFocus();
1113 
1114         FillDisassemblyList(ass_adress, false);
1115         memory_window->update();
1116     }
1117     else
1118     {
1119         switch(new_adress)
1120         {
1121         case 0:
1122             QMessageBox::warning(this, tr("Fehler...!"), tr("Fehlerhafte Adresse."));
1123             ui->AssAdresseIn->selectAll();
1124             ui->AssAdresseIn->setFocus();
1125             break;
1126         case 1:
1127             QMessageBox::warning(this, tr("Fehler...!"), tr("Unbekanntes Mnemonic."));
1128             ui->AssMnemonicIn->selectAll();
1129             ui->AssMnemonicIn->setFocus();
1130             break;
1131         case 2:
1132             QMessageBox::warning(this, tr("Fehler...!"), tr("Unbekannte Adressierung."));
1133             ui->AssAdressierungIn->selectAll();
1134             ui->AssAdressierungIn->setFocus();
1135             break;
1136         case 3:
1137             QMessageBox::warning(this, tr("Fehler...!"), tr("Spungweite für Branchbefehl ist zu groß."));
1138             ui->AssAdressierungIn->selectAll();
1139             ui->AssAdressierungIn->setFocus();
1140             break;
1141         case 4:
1142             QMessageBox::warning(this, tr("Fehler...!"), tr("Dieser Opcode unterstützt nicht diese Adressierung."));
1143             ui->AssAdressierungIn->selectAll();
1144             ui->AssAdressierungIn->setFocus();
1145             break;
1146         }
1147     }
1148 }
1149 
Assemble(QString address,QString mnemonic,QString addressing,uint16_t * ass_address,uint16_t * new_adress)1150 bool DebuggerWindow::Assemble(QString address, QString mnemonic, QString addressing, uint16_t *ass_address, uint16_t *new_adress)
1151 {
1152     uint32_t start_address;
1153     uint8_t opcode[32];
1154     uint8_t opcode_count;
1155     uint8_t address_type;
1156     uint16_t address_value;
1157 
1158     bool ok;
1159 
1160     QString in_str = address;
1161     if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1162     start_address = in_str.toUShort(&ok,0);
1163     if(!ok)
1164     {
1165         *new_adress = 0;
1166         return false;
1167     }
1168 
1169     if(!FindMnemonic(mnemonic,opcode,&opcode_count))
1170     {
1171         *new_adress = 1;
1172         return false;
1173     }
1174 
1175     if(!FindAddressing(addressing,&address_type,&address_value))
1176     {
1177         *new_adress = 2;
1178         return false;
1179     }
1180 
1181     *ass_address = static_cast<uint16_t>(start_address);
1182 
1183     if((opcode[0]==0x90)||(opcode[0]==0xB0)||(opcode[0]==0xF0)||(opcode[0]==0x30)||(opcode[0]==0xD0)||(opcode[0]==0x10)||(opcode[0]==0x50)||(opcode[0]==0x70))
1184     {
1185         if((address_type == 2) || (address_type == 3))
1186         {
1187             int16_t jmp_adress = static_cast<int16_t>(address_value) - static_cast<int16_t>(start_address) - 2;
1188             if((jmp_adress < -128) || (jmp_adress > 127))
1189             {
1190                 *new_adress = 3;
1191                 return false;
1192             }
1193 
1194             if(current_source > 0)
1195             {
1196                 c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address), opcode[0]);
1197                 c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(jmp_adress));
1198             }
1199             else
1200             {
1201                 c64->WriteC64Byte(static_cast<uint16_t>(start_address), opcode[0]);
1202                 c64->WriteC64Byte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(jmp_adress));
1203             }
1204 
1205             *new_adress = static_cast<uint16_t>(start_address) + 2;
1206             return true;
1207         }
1208     }
1209 
1210     for(int i=0;i<opcode_count;i++)
1211     {
1212         if((CpuOPCInfo[opcode[i]]>>4) == address_type)
1213         {
1214             switch (address_type)
1215             {
1216             case 0:
1217                 if(current_source > 0)
1218                 {
1219                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address), opcode[i]);
1220                 }
1221                 else
1222                 {
1223                     c64->WriteC64Byte(static_cast<uint16_t>(start_address), opcode[i]);
1224                 }
1225                 *new_adress = static_cast<uint16_t>(start_address)+1;
1226                 break;
1227             case 1: case 3: case 6: case 7: case 8: case 11:
1228                 if(current_source > 0)
1229                 {
1230                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address), opcode[i]);
1231                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(address_value));
1232                 }
1233                 else
1234                 {
1235                     c64->WriteC64Byte(static_cast<uint16_t>(start_address), opcode[i]);
1236                     c64->WriteC64Byte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(address_value));
1237                 }
1238                 *new_adress = static_cast<uint16_t>(start_address)+2;
1239                 break;
1240             case 2: case 4: case 5: case 10:
1241                 if(current_source > 0)
1242                 {
1243                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address), opcode[i]);
1244                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(address_value));
1245                     c64->floppy[currnet_floppy_nr]->WriteByte(static_cast<uint16_t>(start_address)+2, static_cast<uint8_t>(address_value>>8));
1246                 }
1247                 else
1248                 {
1249                     c64->WriteC64Byte(static_cast<uint16_t>(start_address), opcode[i]);
1250                     c64->WriteC64Byte(static_cast<uint16_t>(start_address)+1, static_cast<uint8_t>(address_value));
1251                     c64->WriteC64Byte(static_cast<uint16_t>(start_address)+2, static_cast<uint8_t>(address_value>>8));
1252                 }
1253                 *new_adress = static_cast<uint16_t>(start_address)+3;
1254                 break;
1255             }
1256             return true;
1257         }
1258     }
1259 
1260     *new_adress = 4;
1261     return false;
1262 }
1263 
on_AnimationStart_clicked()1264 void DebuggerWindow::on_AnimationStart_clicked()
1265 {
1266     ClearAllBreakpointBackcolors();
1267 
1268     ui->OneOpcode->setEnabled(false);
1269     ui->OneZyklus->setEnabled(false);
1270     ui->AnimationStart->setEnabled(false);
1271     ui->AnimationStop->setEnabled(true);
1272     ui->DisAssScroll->setEnabled(false);
1273 
1274     ui->AssAdresseIn->setEnabled(false);
1275     ui->AssMnemonicIn->setEnabled(false);
1276     ui->AssAdressierungIn->setEnabled(false);
1277     ui->EingabeFeld->setVisible(false);
1278 
1279     c64->SetDebugAnimation(true);
1280 }
1281 
on_AnimationStop_clicked()1282 void DebuggerWindow::on_AnimationStop_clicked()
1283 {
1284     ui->OneOpcode->setEnabled(true);
1285     ui->OneZyklus->setEnabled(true);
1286     ui->AnimationStart->setEnabled(true);
1287     ui->AnimationStop->setEnabled(false);
1288     ui->DisAssScroll->setEnabled(true);
1289 
1290     ui->AssAdresseIn->setEnabled(true);
1291     ui->AssMnemonicIn->setEnabled(true);
1292     ui->AssAdressierungIn->setEnabled(true);
1293 
1294     c64->SetDebugAnimation(false);
1295 }
1296 
on_AnimationSpeed_valueChanged(int value)1297 void DebuggerWindow::on_AnimationSpeed_valueChanged(int value)
1298 {
1299     if(value == 1) ui->anispeed_out->setText(QVariant(value).toString() + tr(" Zyklus/Sek"));
1300     else ui->anispeed_out->setText(QVariant(value).toString() + tr(" Zyklen/Sek"));
1301     c64->SetDebugAnimationSpeed(value);
1302 }
1303 
on_DisAssTable_doubleClicked(const QModelIndex & index)1304 void DebuggerWindow::on_DisAssTable_doubleClicked(const QModelIndex &index)
1305 {
1306    ui->AssAdresseIn->setText(ui->DisAssTable->item(index.row(),0)->text());
1307    ui->AssMnemonicIn->setText(ui->DisAssTable->item(index.row(),2)->text());
1308    ui->AssAdressierungIn->setText(ui->DisAssTable->item(index.row(),3)->text());
1309 }
1310 
on_DisAssScroll_valueChanged(int value)1311 void DebuggerWindow::on_DisAssScroll_valueChanged(int value)
1312 {
1313     FillDisassemblyList(static_cast<uint16_t>(value), false);
1314 }
1315 
on_AddBreakpoint_clicked()1316 void DebuggerWindow::on_AddBreakpoint_clicked()
1317 {
1318     static int auto_num[MAX_FLOPPY_NUM+1] = {1,1,1,1,1};
1319     BREAK_GROUP *bg;
1320     int index;
1321 
1322     if(current_source > 0)
1323     {
1324         index = c64->floppy[currnet_floppy_nr]->AddBreakGroup();
1325     }
1326     else index = c64->AddBreakGroup();
1327 
1328     if(index > -1)
1329     {
1330         if(current_source > 0) bg = c64->floppy[currnet_floppy_nr]->GetBreakGroup(index);
1331         else bg = c64->GetBreakGroup(index);
1332 
1333         QString Name = tr("Haltepunkt (") + QVariant(auto_num[current_source]++).toString() + ")";
1334         strcpy(bg->Name,Name.toLocal8Bit().constData());
1335         bg->Enable = true;
1336 
1337         AddBreakpointTreeRoot(Name,bg);
1338     }
1339 }
1340 
on_DelBreakpoint_clicked()1341 void DebuggerWindow::on_DelBreakpoint_clicked()
1342 {
1343     int bg_index;
1344     QString Name;
1345 
1346     if(ui->BreakpointTree->selectedItems().count() == 1)
1347     {
1348         QTreeWidgetItem *item = ui->BreakpointTree->selectedItems()[0];
1349 
1350         if(item->parent() == nullptr)
1351         {
1352             bg_index = ui->BreakpointTree->indexOfTopLevelItem(item);
1353             Name = item->text(0);
1354         }
1355         else
1356         {
1357             bg_index = ui->BreakpointTree->indexOfTopLevelItem(item->parent());
1358             Name = item->parent()->text(0);
1359         }
1360 
1361         if(QMessageBox::Yes == QMessageBox::question(this,tr("Haltepunkt löschen..."),tr("Möchten Sie den folgenden Haltepunkt löschen?\n") + ">> " + Name + " <<",QMessageBox::Yes | QMessageBox::No))
1362         {
1363             ui->BreakpointTree->takeTopLevelItem(bg_index);
1364             if(current_source > 0) c64->floppy[currnet_floppy_nr]->DelBreakGroup(bg_index);
1365             else c64->DelBreakGroup(bg_index);
1366         }
1367     }
1368 }
1369 
AddBreakpointTreeRoot(QString name,BREAK_GROUP * bg)1370 void DebuggerWindow::AddBreakpointTreeRoot(QString name,BREAK_GROUP *bg)
1371 {
1372     QTreeWidgetItem *item = new QTreeWidgetItem(0);
1373     item->setText(0,name);
1374     item->setForeground(0,QBrush(QColor(200,0,0)));
1375     item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEditable);
1376     item->setCheckState(0,Qt::Checked);
1377     item->setDisabled(false);
1378     item->setToolTip(0,tr("Der Name des Haltepunkts kann frei gewählt werden."));
1379     ui->BreakpointTree->addTopLevelItem(item);
1380 
1381     break_point_update_enable = false;
1382     AddBreakpointTreeChild(item,bg->iPC,bg->bPC,tr("Wenn der Wert gleich dem Programm Counter (PC) ist."));
1383     AddBreakpointTreeChild(item,bg->iAC,bg->bAC,tr("Wenn der Wert gleich dem Accu Register (AC) ist."));
1384     AddBreakpointTreeChild(item,bg->iXR,bg->bXR,tr("Wenn der Wert gleich dem X Register (XR) ist."));
1385     AddBreakpointTreeChild(item,bg->iYR,bg->bYR,tr("Wenn der Wert gleich dem Y Register (YR) ist."));
1386     AddBreakpointTreeChild(item,bg->iRAdresse,bg->bRAdresse,tr("Wenn ein Lesezugriff an dieser Adresse statt findet."));
1387     AddBreakpointTreeChild(item,bg->iWAdresse,bg->bWAdresse,tr("Wenn ein Schreibzugriff an dieser Adresse statt findet."));
1388     AddBreakpointTreeChild(item,bg->iRWert,bg->bRWert,tr("Wenn aus einer Adresse dieser Wert ausgelesen wird."));
1389     AddBreakpointTreeChild(item,bg->iWWert,bg->bWWert,tr("Wenn in einer Adresse dieser Wert geschrieben wird."));
1390     if(current_source == 0)
1391     {
1392         AddBreakpointTreeChild(item,bg->iRZ,bg->bRZ,tr("Wenn der Wert gleich der Aktuellen Rasterzeile ist."));
1393         AddBreakpointTreeChild(item,bg->iRZZyklus,bg->bRZZyklus,tr("Wenn der Wert gleich dem Aktuellen Zyklus in einer Rasterzeile ist."));
1394     }
1395     break_point_update_enable = true;
1396     c64->UpdateBreakGroup();
1397 }
1398 
AddBreakpointTreeChild(QTreeWidgetItem * parent,uint16_t value,uint8_t checked,QString tooltip)1399 void DebuggerWindow::AddBreakpointTreeChild(QTreeWidgetItem *parent, uint16_t value, uint8_t checked, QString tooltip)
1400 {
1401     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
1402     item->setText(1,QVariant(value).toString());
1403     item->setForeground(0,QBrush(QColor(0,0,0)));
1404     item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEditable);
1405     if(checked) item->setCheckState(0,Qt::Checked);
1406     else item->setCheckState(0,Qt::Unchecked);
1407     item->setDisabled(false);
1408     item->setToolTip(0,tooltip);
1409     item->setToolTip(1,tr("Doppelklick um Werte zu verändern."));
1410     item->setBackground(1,QColor(200,200,255));
1411     item->setForeground(1,QColor(200,0,0));
1412     parent->addChild(item);
1413 }
1414 
on_BreakpointTree_itemChanged(QTreeWidgetItem * item,int column)1415 void DebuggerWindow::on_BreakpointTree_itemChanged(QTreeWidgetItem *item, int column)
1416 {
1417     int bg_index;
1418     int child_index;
1419 
1420     if(item->parent() == nullptr)
1421     {
1422         /// TopLevel Item (Breakpointname) ///
1423 
1424         bg_index = ui->BreakpointTree->indexOfTopLevelItem(item);
1425         BREAK_GROUP *bg;
1426         if(current_source > 0)
1427         {
1428             bg = c64->floppy[currnet_floppy_nr]->GetBreakGroup(bg_index);
1429         }
1430         else bg = c64->GetBreakGroup(bg_index);
1431 
1432         strcpy(bg->Name,item->text(0).toLocal8Bit().constData());
1433         bg->Enable = item->checkState(0);
1434         c64->UpdateBreakGroup();
1435     }
1436     else
1437     {
1438         /// Child Item ///
1439         bg_index = ui->BreakpointTree->indexOfTopLevelItem(item->parent());
1440         child_index = item->parent()->indexOfChild(item);
1441 
1442         BREAK_GROUP *bg;
1443         if(current_source > 0)
1444         {
1445             bg = c64->floppy[currnet_floppy_nr]->GetBreakGroup(bg_index);
1446         }
1447         else bg = c64->GetBreakGroup(bg_index);
1448 
1449         if(column == 0 || 1)
1450         {
1451             QString tmp_str = item->text(1);
1452             bool ok;
1453             uint16_t integer;
1454             char str_00[10];
1455 
1456             switch(child_index)
1457             {
1458             case 0:
1459                 item->setText(0,"PC:");
1460 
1461                 if(tmp_str != "")
1462                 {
1463                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1464                     integer = tmp_str.toUShort(&ok,0);
1465                     if(ok)
1466                     {
1467                         bg->iPC = integer;
1468                         sprintf(str_00,"$%4.4X",integer);
1469                         item->setText(1,QString(str_00));
1470                         item->setBackground(1,QColor(200,200,255));
1471                         item->setForeground(1,QColor(200,0,0));
1472                     }
1473                     else
1474                     {
1475                         item->setCheckState(0,Qt::Unchecked);
1476                         item->setBackground(1,QColor(200,0,0));
1477                         item->setForeground(1,QColor(200,200,200));
1478                     }
1479                 }
1480                 else item->setCheckState(0,Qt::Unchecked);
1481                 bg->bPC = item->checkState(0);
1482 
1483                 break;
1484             case 1:
1485                 item->setText(0,"AC:");
1486 
1487                 if(tmp_str != "")
1488                 {
1489                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1490                     integer = tmp_str.toUShort(&ok,0);
1491                     if(ok)
1492                     {
1493                         if(integer <= 0xff)
1494                         {
1495                             bg->iAC = integer;
1496                             sprintf(str_00,"$%2.2X",integer);
1497                             item->setText(1,QString(str_00));
1498                             item->setBackground(1,QColor(200,200,255));
1499                             item->setForeground(1,QColor(200,0,0));
1500                         }
1501                         else
1502                         {
1503                             item->setCheckState(0,Qt::Unchecked);
1504                             item->setBackground(1,QColor(200,0,0));
1505                             item->setForeground(1,QColor(200,200,200));
1506                         }
1507                     }
1508                     else
1509                     {
1510                         item->setCheckState(0,Qt::Unchecked);
1511                         item->setBackground(1,QColor(200,0,0));
1512                         item->setForeground(1,QColor(200,200,200));
1513                     }
1514                 }
1515                 else item->setCheckState(0,Qt::Unchecked);
1516                 bg->bAC = item->checkState(0);
1517                 break;
1518             case 2:
1519                 item->setText(0,"XR:");
1520 
1521                 if(tmp_str != "")
1522                 {
1523                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1524                     integer = tmp_str.toUShort(&ok,0);
1525                     if(ok)
1526                     {
1527                         if(integer <= 0xff)
1528                         {
1529                             bg->iXR = integer;
1530                             sprintf(str_00,"$%2.2X",integer);
1531                             item->setText(1,QString(str_00));
1532                             item->setBackground(1,QColor(200,200,255));
1533                             item->setForeground(1,QColor(200,0,0));
1534                         }
1535                         else
1536                         {
1537                             item->setCheckState(0,Qt::Unchecked);
1538                             item->setBackground(1,QColor(200,0,0));
1539                             item->setForeground(1,QColor(200,200,200));
1540                         }
1541                     }
1542                     else
1543                     {
1544                         item->setCheckState(0,Qt::Unchecked);
1545                         item->setBackground(1,QColor(200,0,0));
1546                         item->setForeground(1,QColor(200,200,200));
1547                     }
1548                 }
1549                 else item->setCheckState(0,Qt::Unchecked);
1550                 bg->bXR = item->checkState(0);
1551                 break;
1552             case 3:
1553                 item->setText(0,"YR:");
1554 
1555                 if(tmp_str != "")
1556                 {
1557                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1558                     integer = tmp_str.toUShort(&ok,0);
1559                     if(ok)
1560                     {
1561                         if(integer <= 0xff)
1562                         {
1563                             bg->iYR = integer;
1564                             sprintf(str_00,"$%2.2X",integer);
1565                             item->setText(1,QString(str_00));
1566                             item->setBackground(1,QColor(200,200,255));
1567                             item->setForeground(1,QColor(200,0,0));
1568                         }
1569                         else
1570                         {
1571                             item->setCheckState(0,Qt::Unchecked);
1572                             item->setBackground(1,QColor(200,0,0));
1573                             item->setForeground(1,QColor(200,200,200));
1574                         }
1575                     }
1576                     else
1577                     {
1578                         item->setCheckState(0,Qt::Unchecked);
1579                         item->setBackground(1,QColor(200,0,0));
1580                         item->setForeground(1,QColor(200,200,200));
1581                     }
1582                 }
1583                 else item->setCheckState(0,Qt::Unchecked);
1584                 bg->bYR = item->checkState(0);
1585                 break;
1586             case 4:
1587                 item->setText(0,tr("Lesen von Adresse:"));
1588 
1589                 if(tmp_str != "")
1590                 {
1591                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1592                     integer = tmp_str.toUShort(&ok,0);
1593                     if(ok)
1594                     {
1595                         bg->iRAdresse = integer;
1596                         sprintf(str_00,"$%4.4X",integer);
1597                         item->setText(1,QString(str_00));
1598                         item->setBackground(1,QColor(200,200,255));
1599                         item->setForeground(1,QColor(200,0,0));
1600                     }
1601                     else
1602                     {
1603                         item->setCheckState(0,Qt::Unchecked);
1604                         item->setBackground(1,QColor(200,0,0));
1605                         item->setForeground(1,QColor(200,200,200));
1606                     }
1607                 }
1608                 else item->setCheckState(0,Qt::Unchecked);
1609                 bg->bRAdresse = item->checkState(0);
1610                 break;
1611             case 5:
1612                 item->setText(0,tr("Schreiben in Adresse:"));
1613 
1614                 if(tmp_str != "")
1615                 {
1616                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1617                     integer = tmp_str.toUShort(&ok,0);
1618                     if(ok)
1619                     {
1620                         bg->iWAdresse = integer;
1621                         sprintf(str_00,"$%4.4X",integer);
1622                         item->setText(1,QString(str_00));
1623                         item->setBackground(1,QColor(200,200,255));
1624                         item->setForeground(1,QColor(200,0,0));
1625                     }
1626                     else
1627                     {
1628                         item->setCheckState(0,Qt::Unchecked);
1629                         item->setBackground(1,QColor(200,0,0));
1630                         item->setForeground(1,QColor(200,200,200));
1631                     }
1632                 }
1633                 else item->setCheckState(0,Qt::Unchecked);
1634                 bg->bWAdresse = item->checkState(0);
1635                 break;
1636             case 6:
1637                 item->setText(0,tr("Lesen von Wert:"));
1638 
1639                 if(tmp_str != "")
1640                 {
1641                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1642                     integer = tmp_str.toUShort(&ok,0);
1643                     if(ok)
1644                     {
1645                         if(integer <= 0xff)
1646                         {
1647                             bg->iRWert = integer;
1648                             sprintf(str_00,"$%2.2X",integer);
1649                             item->setText(1,QString(str_00));
1650                             item->setBackground(1,QColor(200,200,255));
1651                             item->setForeground(1,QColor(200,0,0));
1652                         }
1653                         else
1654                         {
1655                             item->setCheckState(0,Qt::Unchecked);
1656                             item->setBackground(1,QColor(200,0,0));
1657                             item->setForeground(1,QColor(200,200,200));
1658                         }
1659                     }
1660                     else
1661                     {
1662                         item->setCheckState(0,Qt::Unchecked);
1663                         item->setBackground(1,QColor(200,0,0));
1664                         item->setForeground(1,QColor(200,200,200));
1665                     }
1666                 }
1667                 else item->setCheckState(0,Qt::Unchecked);
1668                 bg->bRWert = item->checkState(0);
1669                 break;
1670             case 7:
1671                 item->setText(0,tr("Schreiben von Wert:"));
1672 
1673                 if(tmp_str != "")
1674                 {
1675                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1676                     integer = tmp_str.toUShort(&ok,0);
1677                     if(ok)
1678                     {
1679                         if(integer <= 0xff)
1680                         {
1681                             bg->iWWert = integer;
1682                             sprintf(str_00,"$%2.2X",integer);
1683                             item->setText(1,QString(str_00));
1684                             item->setBackground(1,QColor(200,200,255));
1685                             item->setForeground(1,QColor(200,0,0));
1686                         }
1687                         else
1688                         {
1689                             item->setCheckState(0,Qt::Unchecked);
1690                             item->setBackground(1,QColor(200,0,0));
1691                             item->setForeground(1,QColor(200,200,200));
1692                         }
1693                     }
1694                     else
1695                     {
1696                         item->setCheckState(0,Qt::Unchecked);
1697                         item->setBackground(1,QColor(200,0,0));
1698                         item->setForeground(1,QColor(200,200,200));
1699                     }
1700                 }
1701                 else item->setCheckState(0,Qt::Unchecked);
1702                 bg->bWWert = item->checkState(0);
1703                 break;
1704             case 8:
1705                 item->setText(0,tr("Rasterzeile:"));
1706 
1707                 if(tmp_str != "")
1708                 {
1709                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1710                     integer = tmp_str.toUShort(&ok,0);
1711                     if(ok)
1712                     {
1713                         if(integer <= 311)  // PAL 0 - 311
1714                         {
1715                             bg->iRZ = integer;
1716                             sprintf(str_00,"%d",integer);
1717                             item->setText(1,QString(str_00));
1718                             item->setBackground(1,QColor(200,200,255));
1719                             item->setForeground(1,QColor(200,0,0));
1720                         }
1721                         else
1722                         {
1723                             item->setCheckState(0,Qt::Unchecked);
1724                             item->setBackground(1,QColor(200,0,0));
1725                             item->setForeground(1,QColor(200,200,200));
1726                         }
1727                     }
1728                     else
1729                     {
1730                         item->setCheckState(0,Qt::Unchecked);
1731                         item->setBackground(1,QColor(200,0,0));
1732                         item->setForeground(1,QColor(200,200,200));
1733                     }
1734                 }
1735                 else item->setCheckState(0,Qt::Unchecked);
1736                 bg->bRZ = item->checkState(0);
1737                 break;
1738             case 9:
1739                 item->setText(0,tr("Zyklus:"));
1740 
1741                 if(tmp_str != "")
1742                 {
1743                     if(tmp_str.left(1) == "$") tmp_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1744                     integer = tmp_str.toUShort(&ok,0);
1745                     if(ok)
1746                     {
1747                         if((integer > 0) && (integer <= 63))    // PAL 1 - 63
1748                         {
1749                             bg->iRZZyklus = integer;
1750                             sprintf(str_00,"%d",integer);
1751                             item->setText(1,QString(str_00));
1752                             item->setBackground(1,QColor(200,200,255));
1753                             item->setForeground(1,QColor(200,0,0));
1754                         }
1755                         else
1756                         {
1757                             item->setCheckState(0,Qt::Unchecked);
1758                             item->setBackground(1,QColor(200,0,0));
1759                             item->setForeground(1,QColor(200,200,200));
1760                         }
1761                     }
1762                     else
1763                     {
1764                         item->setCheckState(0,Qt::Unchecked);
1765                         item->setBackground(1,QColor(200,0,0));
1766                         item->setForeground(1,QColor(200,200,200));
1767                     }
1768                 }
1769                 else item->setCheckState(0,Qt::Unchecked);
1770                 bg->bRZZyklus = item->checkState(0);
1771                 break;
1772             default:
1773                 item->setText(0,"???");
1774                 break;
1775             }
1776         }
1777         if(break_point_update_enable)c64->UpdateBreakGroup();
1778     }
1779 }
1780 
ClearAllBreakpointBackcolors()1781 void DebuggerWindow::ClearAllBreakpointBackcolors()
1782 {
1783     for(int i=0;i<ui->BreakpointTree->topLevelItemCount();i++)
1784     {
1785         ui->BreakpointTree->topLevelItem(i)->setBackground(0,QColor(255,255,255));
1786         ui->BreakpointTree->topLevelItem(i)->setBackground(1,QColor(255,255,255));
1787         ui->BreakpointTree->topLevelItem(i)->setText(1,"");
1788     }
1789 }
1790 
BreakpointProc()1791 void DebuggerWindow::BreakpointProc()
1792 {
1793     new_breakpoint_found = true;
1794 }
1795 
on_LoadBreakpoints_clicked()1796 void DebuggerWindow::on_LoadBreakpoints_clicked()
1797 {
1798     if(ui->BreakpointTree->topLevelItemCount() > 0)
1799         if(QMessageBox::No == QMessageBox::question(this, tr("Haltepunkte laden..."), tr("Es werden alle Haltepunkte gelöscht !\nMöchten Sie fortfahren?"),QMessageBox::Yes | QMessageBox::No))
1800             return;
1801 
1802     ui->BreakpointTree->clear();
1803 
1804     if(current_source > 0) c64->floppy[currnet_floppy_nr]->DeleteAllBreakGroups();
1805     else c64->DeleteAllBreakGroups();
1806 
1807     QString filename = QFileDialog::getOpenFileName(this, tr("Haltepunkte öffnen"), QDir::homePath(), tr("Emu64 Haltepunkt Datei ") + "(*.bpt)", nullptr, QFileDialog::DontUseNativeDialog);
1808     if(filename != "")
1809     {
1810        int ret;
1811        if(current_source > 0) ret = c64->floppy[currnet_floppy_nr]->LoadBreakGroups(filename.toLocal8Bit());
1812        else ret = c64->LoadBreakGroups(filename.toLocal8Bit());
1813 
1814        if(ret != 0)
1815        {
1816             switch(ret)
1817             {
1818             case -1:
1819                 QMessageBox::warning(this,tr("Fehler..."),tr("Die Datei konnte nicht geöffnet werden."));
1820                 break;
1821             case -2:
1822                 QMessageBox::warning(this,tr("Fehler..."),tr("Es handelt sich nicht um eine Emu64 Datei."));
1823                 break;
1824             case -3:
1825                 QMessageBox::warning(this,tr("Fehler..."),tr("Diese Datei wurde mit einer neueren Emu64 Version erstellt."));
1826                 break;
1827             case -4:
1828                 QMessageBox::warning(this,tr("Fehler..."),tr("Diese Datei enthält keine Haltepunkte."));
1829                 break;
1830             }
1831        }
1832        else
1833        {
1834            /// Alle Haltepunke ins TreeWidget einfügen ///
1835            if(current_source > 0)
1836            {
1837                int count = c64->floppy[currnet_floppy_nr]->GetBreakGroupCount();
1838                for(int i=0; i<count; i++)
1839                {
1840                    BREAK_GROUP *bg = c64->floppy[currnet_floppy_nr]->GetBreakGroup(i);
1841                    AddBreakpointTreeRoot(bg->Name,bg);
1842                }
1843            }
1844            else
1845            {
1846                int count = c64->GetBreakGroupCount();
1847                for(int i=0; i<count; i++)
1848                {
1849                    BREAK_GROUP *bg = c64->GetBreakGroup(i);
1850                    AddBreakpointTreeRoot(bg->Name,bg);
1851                }
1852            }
1853        }
1854     }
1855 }
1856 
on_SaveBreakpoints_clicked()1857 void DebuggerWindow::on_SaveBreakpoints_clicked()
1858 {
1859     if(ui->BreakpointTree->topLevelItemCount() == 0) return;
1860 
1861     QString filename;
1862     QString fileext;
1863 
1864     QStringList filters;
1865     filters << tr("Emu64 Haltepunkt Datei (*.bpt)")
1866             << tr("Alle Dateien (*.*)");
1867 
1868     if(!CustomSaveFileDialog::GetSaveFileName(this, tr("Haltepunkte speichern"), filters, &filename, &fileext))
1869     {
1870         return;
1871     }
1872 
1873     if(current_source > 0)
1874     {
1875         if(!c64->floppy[currnet_floppy_nr]->SaveBreakGroups(filename.toLocal8Bit()))
1876             QMessageBox::warning(this,tr("Fehler..."),tr("Die Haltepunkte konnten nicht gespeichert werden."));
1877     }
1878     else
1879     {
1880         if(!c64->SaveBreakGroups(filename.toLocal8Bit()))
1881           QMessageBox::warning(this,tr("Fehler..."),tr("Die Haltepunkte konnten nicht gespeichert werden."));
1882     }
1883 }
1884 
on_DelAllBreakpoints_clicked()1885 void DebuggerWindow::on_DelAllBreakpoints_clicked()
1886 {
1887     if(ui->BreakpointTree->topLevelItemCount() > 0)
1888         if(QMessageBox::Yes == QMessageBox::question(this, tr("Achtung..."), tr("Es werden alle Haltepunkte gelöscht !\nMöchten Sie fortfahren?"),QMessageBox::Yes | QMessageBox::No))
1889         {
1890             if(current_source > 0) c64->floppy[currnet_floppy_nr]->DeleteAllBreakGroups();
1891             else c64->DeleteAllBreakGroups();
1892             ui->BreakpointTree->clear();
1893         }
1894 }
1895 
on_HistoryScroll_valueChanged(int value)1896 void DebuggerWindow::on_HistoryScroll_valueChanged(int value)
1897 {
1898     FillHistoryList(static_cast<uint8_t>(value));
1899 }
1900 
on_ExportDisAss_clicked()1901 void DebuggerWindow::on_ExportDisAss_clicked()
1902 {
1903     bool ok;
1904     QString in_str;
1905     uint16_t value;
1906     uint16_t start, end;
1907 
1908     in_str = ui->ExportStartIn->text();
1909     if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1910     value = in_str.toUShort(&ok,0);
1911     if(!ok)
1912     {
1913         QMessageBox::warning(this,tr("Eingabefehler..."),tr("Es wurde kein gültiges Zahlenformat benutzt ! [Export Von:]"));
1914         return;
1915     }
1916     start = value;
1917 
1918     in_str = ui->ExportEndIn->text();
1919     if(in_str.left(1) == "$") in_str.replace(0,1,"0x"); // Steht am Anfang ein '$' wird dieses in '0X' gewandelt
1920     value = in_str.toUShort(&ok,0);
1921     if(!ok)
1922     {
1923         QMessageBox::warning(this,tr("Eingabefehler..."),tr("Es wurde kein gültiges Zahlenformat benutzt ! [Export Bis:]"));
1924         return;
1925     }
1926     end = value;
1927 
1928     if(start >= end)
1929     {
1930         QMessageBox::warning(this,tr("Fehler..."),tr("Startadresse muss kleiner sein als Endadresse."));
1931         return;
1932     }
1933 
1934     QString filename;
1935     QString fileext;
1936 
1937     QStringList filters;
1938     filters << tr("Disassembler Listing (*.txt)")
1939             << tr("C64 Programm Datei (*.prg)")
1940             << tr("Alle Dateien (*.*)");
1941 
1942     if(!CustomSaveFileDialog::GetSaveFileName(this,tr("Export..."), filters, &filename, &fileext))
1943     {
1944         return;
1945     }
1946 
1947     fileext = fileext.toUpper();
1948     if(fileext == "TXT")
1949     {
1950         if(!c64->ExportASM(filename.toLocal8Bit(),start,end,current_source))
1951             QMessageBox::warning(this,tr("Fehler..."),tr("Fehler beim speichern der Disassembler Datei."));
1952     }
1953 
1954     if(fileext == "PRG")
1955     {
1956         if((current_source > 0) && (end > 0x07FF))
1957         {
1958             QMessageBox::warning(this,tr("Fehler..."),tr("Floppy RAM geht nur von $0000 - $07FF (2KB)."));
1959             return;
1960         }
1961         if(!c64->ExportPRG(filename.toLocal8Bit(),start,end,current_source))
1962             QMessageBox::warning(this,tr("Fehler..."),tr("Fehler beim speichern der Programm Datei."));
1963     }
1964 }
1965 
onChangeFloppyStatus(void)1966 void DebuggerWindow::onChangeFloppyStatus(void)
1967 {
1968     RefreshGUI();
1969 }
1970 
RefreshGUI(void)1971 void DebuggerWindow::RefreshGUI(void)
1972 {
1973     if(c64 == nullptr) return;
1974 
1975     c64_cpu_reg.reg_mask = REG_MASK_ALL;
1976     c64->GetC64CpuReg(&c64_cpu_reg,&c64_cpu_ireg);
1977 
1978     if(current_source > 0)
1979     {
1980         /// Floppy's ///
1981         floppy_cpu_reg[currnet_floppy_nr].reg_mask = REG_MASK_ALL;
1982         c64->floppy[currnet_floppy_nr]->GetCpuReg(&floppy_cpu_reg[currnet_floppy_nr],&floppy_cpu_ireg[currnet_floppy_nr]);
1983 
1984         /// Register Group ///
1985         ui->RegisterGroup->setTitle(tr("CPU 6502 Register"));
1986         ui->label_nmi->setVisible(false);
1987         ui->label_0314->setVisible(false);
1988         ui->label_0318->setVisible(false);
1989         ui->nmi_out->setVisible(false);
1990         ui->_0314_out->setVisible(false);
1991         ui->_0318_out->setVisible(false);
1992 
1993         /// IRegister Group ///
1994         ui->IRegisterGroup->setTitle(tr("CPU 6502 Interne Register (Emu64 Modell)"));
1995         ui->label_cpu_wait->setVisible(false);
1996         ui->wait_led->setVisible(false);
1997 
1998         /// Costum Chips ///
1999         ui->VIC->setVisible(false);
2000         ui->SID->setVisible(false);
2001         ui->CIA1->setVisible(false);
2002         ui->CIA2->setVisible(false);
2003         ui->VIA1->setVisible(true);
2004         ui->VIA2->setVisible(true);
2005 
2006         /// Leitungen ///
2007         ui->label_nmi_2->setVisible(false);
2008         ui->label_ba->setVisible(false);
2009         ui->label_exrom->setVisible(false);
2010         ui->label_game->setVisible(false);
2011         ui->nmi_led->setVisible(false);
2012         ui->rdy_led->setVisible(false);
2013         ui->exrom_led->setVisible(false);
2014         ui->game_led->setVisible(false);
2015 
2016         if(c64->floppy[current_source-1]->GetEnableFloppy())
2017         {
2018             ui->label_floppy_off->setVisible(false);
2019             ui->RegisterGroup->setEnabled(true);
2020             ui->IRegisterGroup->setEnabled(true);
2021             ui->VIA1->setEnabled(true);
2022             ui->VIA2->setEnabled(true);
2023             ui->LeitungenGroup->setEnabled(true);
2024             ui->CycleGroup->setEnabled(true);
2025             ui->VerlaufGroup->setEnabled(true);
2026             ui->DisassGroup->setEnabled(true);
2027             ui->ExportGroup->setEnabled(true);
2028             ui->BreakGroup->setEnabled(true);
2029 
2030             /// Alle Haltepunke ins TreeWidget einfügen ///
2031             FillDisassemblyList(floppy_cpu_ireg[currnet_floppy_nr].current_opcode_pc,false);
2032         }
2033         else
2034         {
2035             ui->label_floppy_off->setVisible(true);
2036             ui->RegisterGroup->setEnabled(false);
2037             ui->pc_out->setText("");
2038             ui->ac_out->setText("");
2039             ui->xr_out->setText("");
2040             ui->yr_out->setText("");
2041             ui->sp_out->setText("");
2042             ui->sr_out->setText("");
2043             ui->irq_out->setText("");
2044             ui->_0314_out->setText("");
2045             ui->sr_widget->SetValue(0);
2046 
2047             ui->IRegisterGroup->setEnabled(false);
2048             ui->opcode_pc_out->setText("");
2049             ui->adresse_out->setText("");
2050             ui->branch_adresse_out->setText("");
2051             ui->opcode_out->setText("");
2052             ui->pointer_out->setText("");
2053             ui->tmp_byte_out->setText("");
2054             ui->mnemonic_out->setText("");
2055             ui->micro_code_out->setText("");
2056             ui->MCodeHelp->setText("");
2057 
2058             ui->VIA1->setEnabled(false);
2059             ui->VIA2->setEnabled(false);
2060 
2061             ui->LeitungenGroup->setEnabled(false);
2062             ui->irq_led->setIcon(*icon_off);
2063             ui->reset_led->setIcon(*icon_off);
2064 
2065             ui->CycleGroup->setEnabled(false);
2066             ui->CycleCounter_Out->setText("");
2067 
2068             ui->VerlaufGroup->setEnabled(false);
2069             for(int i=0;i<HISTORY_ROW;i++) ui->HistoryList->item(i)->setText("");
2070 
2071             ui->DisassGroup->setEnabled(false);
2072             for(int i=0;i<DISASS_ROW;i++)
2073             {
2074                 disass_pc[i]->setText("");
2075                 disass_pc[i]->setBackground(table_back_color);
2076                 disass_memory[i]->setText("");
2077                 disass_memory[i]->setBackground(table_back_color);
2078                 disass_mnemonic[i]->setText("");
2079                 disass_mnemonic[i]->setBackground(table_back_color);
2080                 disass_addressing[i]->setText("");
2081                 disass_addressing[i]->setBackground(table_back_color);
2082             }
2083             ui->ExportGroup->setEnabled(false);
2084 
2085             ui->BreakGroup->setEnabled(false);
2086         }
2087     }
2088     else
2089     {
2090         /// C64 ///
2091 
2092         /// Register Group ///
2093         ui->RegisterGroup->setTitle(tr("CPU 6510 Register"));
2094         ui->label_nmi->setVisible(true);
2095         ui->label_0314->setVisible(true);
2096         ui->label_0318->setVisible(true);
2097         ui->nmi_out->setVisible(true);
2098         ui->_0314_out->setVisible(true);
2099         ui->_0318_out->setVisible(true);
2100 
2101         /// IRegister Group ///
2102         ui->IRegisterGroup->setTitle(tr("CPU 6510 Interne Register (Emu64 Modell)"));
2103         ui->label_cpu_wait->setVisible(true);
2104         ui->wait_led->setVisible(true);
2105 
2106         /// Costum Chips ///
2107         ui->VIC->setVisible(true);
2108         ui->SID->setVisible(true);
2109         ui->CIA1->setVisible(true);
2110         ui->CIA2->setVisible(true);
2111         ui->VIA1->setVisible(false);
2112         ui->VIA2->setVisible(false);
2113 
2114         /// Leitungen ///
2115         ui->label_nmi_2->setVisible(true);
2116         ui->label_ba->setVisible(true);
2117         ui->label_exrom->setVisible(true);
2118         ui->label_game->setVisible(true);
2119         ui->nmi_led->setVisible(true);
2120         ui->rdy_led->setVisible(true);
2121         ui->exrom_led->setVisible(true);
2122         ui->game_led->setVisible(true);
2123 
2124         /// All Enable ///
2125         ui->label_floppy_off->setVisible(false);
2126         ui->RegisterGroup->setEnabled(true);
2127         ui->IRegisterGroup->setEnabled(true);
2128         ui->LeitungenGroup->setEnabled(true);
2129         ui->CycleGroup->setEnabled(true);
2130         ui->VerlaufGroup->setEnabled(true);
2131         ui->DisassGroup->setEnabled(true);
2132         ui->ExportDisAss->setEnabled(true);
2133         ui->BreakGroup->setEnabled(true);
2134         FillDisassemblyList(c64_cpu_ireg.current_opcode_pc,false);
2135     }
2136 
2137     ui->EingabeFeld->hide();
2138     UpdateRegister();
2139     FillHistoryList(static_cast<uint8_t>(ui->HistoryScroll->value()));
2140     memory_window->UpdateMemoryList();
2141     vic_window->UpdateOutputList();
2142 
2143     on_AnimationSpeed_valueChanged(ui->AnimationSpeed->value());
2144 }
2145 
on_MemEdit_clicked()2146 void DebuggerWindow::on_MemEdit_clicked()
2147 {
2148     if(memory_window->isHidden())
2149     {
2150         memory_window->show();
2151         memory_window->UpdateMemoryList();
2152     }
2153     else memory_window->hide();
2154 }
2155 
on_VIC_clicked()2156 void DebuggerWindow::on_VIC_clicked()
2157 {
2158     if(vic_window->isHidden())
2159     {
2160         vic_window->show();
2161         vic_window->UpdateOutputList();
2162     }
2163     else vic_window->hide();
2164 }
2165 
on_IEC_clicked()2166 void DebuggerWindow::on_IEC_clicked()
2167 {
2168     if(iec_window->isHidden())
2169     {
2170         iec_window->show();
2171         iec_window->UpdateSignals();
2172     }
2173     else iec_window->hide();
2174 }
2175 
on_man_lines_clicked(bool checked)2176 void DebuggerWindow::on_man_lines_clicked(bool checked)
2177 {
2178     c64->SetCpuExtLines(checked);
2179 
2180     if(!checked)
2181     {
2182         if(c64_cpu_ireg.irq) ui->irq_led->setIcon(*icon_on);
2183         else ui->irq_led->setIcon(*icon_off);
2184         if(c64_cpu_ireg.nmi) ui->nmi_led->setIcon(*icon_on);
2185         else ui->nmi_led->setIcon(*icon_off);
2186         if(c64_cpu_ireg.rdy) ui->rdy_led->setIcon(*icon_on);
2187         else ui->rdy_led->setIcon(*icon_off);
2188     }
2189     else
2190     {
2191         ui->rdy_led->setChecked(true);
2192         ui->rdy_led->setIcon(*icon_on);
2193         c64->SetExtRDY(true);
2194 
2195         ui->irq_led->setChecked(false);
2196         ui->irq_led->setIcon(*icon_off);
2197 
2198         ui->nmi_led->setChecked(false);
2199         ui->nmi_led->setIcon(*icon_off);
2200     }
2201 }
2202 
on_rdy_led_clicked(bool checked)2203 void DebuggerWindow::on_rdy_led_clicked(bool checked)
2204 {
2205     if(ui->man_lines->checkState())
2206     {
2207         c64->SetExtRDY(checked);
2208         if(checked) ui->rdy_led->setIcon(*icon_on);
2209         else ui->rdy_led->setIcon(*icon_off);
2210     }
2211 }
2212 
on_irq_led_clicked(bool checked)2213 void DebuggerWindow::on_irq_led_clicked(bool checked)
2214 {
2215     if(ui->man_lines->checkState())
2216     {
2217         if(checked) c64->cpu->TriggerInterrupt(EXT_IRQ);
2218         else c64->cpu->ClearInterrupt(EXT_IRQ);
2219         if(checked) ui->irq_led->setIcon(*icon_on);
2220         else ui->irq_led->setIcon(*icon_off);
2221     }
2222 }
2223 
on_nmi_led_clicked(bool checked)2224 void DebuggerWindow::on_nmi_led_clicked(bool checked)
2225 {
2226     if(ui->man_lines->checkState())
2227     {
2228         if(checked) c64->cpu->TriggerInterrupt(EXT_NMI);
2229         else c64->cpu->ClearInterrupt(EXT_NMI);
2230         if(checked) ui->nmi_led->setIcon(*icon_on);
2231         else ui->nmi_led->setIcon(*icon_off);
2232     }
2233 }
2234