1 // Copyright (c) 2019-2021 hors<horsicq@gmail.com>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 //
21 #include "guimainwindow.h"
22 #include "ui_guimainwindow.h"
23 
GuiMainWindow(QWidget * pParent)24 GuiMainWindow::GuiMainWindow(QWidget *pParent) :
25     QMainWindow(pParent),
26     ui(new Ui::GuiMainWindow)
27 {
28     ui->setupUi(this);
29 
30     setWindowTitle(QString("%1 v%2").arg(X_APPLICATIONDISPLAYNAME,X_APPLICATIONVERSION));
31 
32     QFont font=ui->lineEditOpcode->font();
33     font.setPointSizeF(font.pointSizeF()*1.5);
34     font.setBold(true);
35     ui->lineEditOpcode->setFont(font);
36 
37     g_xOptions.setName(X_OPTIONSFILE);
38 
39     QList<XOptions::ID> listIDs;
40 
41     listIDs.append(XOptions::ID_STYLE);
42     listIDs.append(XOptions::ID_STAYONTOP);
43 
44     g_xOptions.setValueIDs(listIDs);
45     g_xOptions.load();
46 
47     adjustWindow();
48 
49     ui->comboBoxOpcodeGroup->addItem(tr("Two operands"),OG_TWOOPERANDS);
50     ui->comboBoxOpcodeGroup->addItem(tr("One operand"),OG_ONEOPERAND);
51     ui->comboBoxOpcodeGroup->addItem(tr("Mul/Div"),OG_MULDIV);
52     ui->comboBoxOpcodeGroup->addItem(tr("Shift"),OG_SHIFT);
53     ui->comboBoxOpcodeGroup->addItem(tr("Bits"),OG_BITS);
54     ui->comboBoxOpcodeGroup->addItem(tr("Special"),OG_SPECIAL);
55 
56     ui->comboBoxMode->addItem(tr("HEX"),ModeValidator::MODE_HEX);
57     ui->comboBoxMode->addItem(tr("Signed"),ModeValidator::MODE_SIGNED);
58     ui->comboBoxMode->addItem(tr("Unsigned"),ModeValidator::MODE_UNSIGNED);
59 
60     g_currentMode=ModeValidator::MODE_HEX;
61 
62     setLineEditValue(ui->lineEditOperand1,g_currentMode,0);
63     setLineEditValue(ui->lineEditOperand2,g_currentMode,0);
64 
65     ui->lineEditOperand1->setValidator(&(g_modeValidator[0]));
66     ui->lineEditOperand2->setValidator(&(g_modeValidator[1]));
67     ui->lineEditFlagsBefore->setValidator(&g_modeValidatorFlag);
68 }
69 
~GuiMainWindow()70 GuiMainWindow::~GuiMainWindow()
71 {
72     g_xOptions.save();
73 
74     delete ui;
75 }
76 
on_pushButtonExit_clicked()77 void GuiMainWindow::on_pushButtonExit_clicked()
78 {
79     this->close();
80 }
81 
on_pushButtonAbout_clicked()82 void GuiMainWindow::on_pushButtonAbout_clicked()
83 {
84     DialogAbout di(this);
85 
86     di.exec();
87 }
88 
adjustWindow()89 void GuiMainWindow::adjustWindow()
90 {
91     g_xOptions.adjustStayOnTop(this);
92 }
93 
calc()94 void GuiMainWindow::calc()
95 {
96     ModeValidator::MODE mode=static_cast<ModeValidator::MODE>(ui->comboBoxMode->currentData().toInt());
97     ASM_DEF::OPCODE_RECORD currentRecord=g_mapOpcodes.value(static_cast<ASM_DEF::OP>(ui->comboBoxOpcode->currentData().toInt()));
98 
99     RECDATA data=RECDATA_INIT;
100 
101     data.OPERAND[0]=getLineEditValue(ui->lineEditOperand1,mode);
102     data.OPERAND[1]=getLineEditValue(ui->lineEditOperand2,mode);
103     data.FLAG[0]=getLineEditValue(ui->lineEditFlagsBefore,mode);
104 
105     data.FLAG[0]&=((ASM_DEF::AF)|(ASM_DEF::CF)|(ASM_DEF::OF)|(ASM_DEF::PF)|(ASM_DEF::SF)|(ASM_DEF::ZF)); // Filter
106 
107     bool bSuccess=true;
108 
109     if( (currentRecord.opcode==ASM_DEF::OP_DIV)||
110         (currentRecord.opcode==ASM_DEF::OP_IDIV))
111     {
112         if(data.OPERAND[1]==0)
113         {
114             bSuccess=false;
115         }
116     }
117 
118     if(bSuccess)
119     {
120         currentRecord.asm_func(&data);
121 
122         setLineEditValue(ui->lineEditResult1,mode,data.RESULT[0]);
123 
124         if(currentRecord.opcode==ASM_DEF::OP_XADD)
125         {
126             setLineEditValue(ui->lineEditResult2,mode,data.RESULT[2]);
127             setLineEditValue(ui->lineEditResult3,mode,data.RESULT[1]);
128         }
129         else
130         {
131             setLineEditValue(ui->lineEditResult2,mode,data.RESULT[1]);
132             setLineEditValue(ui->lineEditResult3,mode,data.RESULT[2]);
133         }
134 
135         setLineEditValue(ui->lineEditResult4,mode,data.RESULT[3]);
136     }
137     else
138     {
139         ui->lineEditResult1->clear();
140         ui->lineEditResult2->clear();
141         ui->lineEditResult3->clear();
142         ui->lineEditResult4->clear();
143 
144         data.FLAG[1]=data.FLAG[0];
145     }
146 
147     XVALUE nFlag=data.FLAG[1];
148 
149     nFlag&=(~(static_cast<XVALUE>(0x202))); // remove
150 
151     setLineEditValue(ui->lineEditFlagsAfter,mode,nFlag);
152 
153     bool bAF=nFlag&(ASM_DEF::AF);
154     bool bCF=nFlag&(ASM_DEF::CF);
155     bool bOF=nFlag&(ASM_DEF::OF);
156     bool bPF=nFlag&(ASM_DEF::PF);
157     bool bSF=nFlag&(ASM_DEF::SF);
158     bool bZF=nFlag&(ASM_DEF::ZF);
159 
160     ui->labelFlagAF->setEnabled(bAF);
161     ui->labelFlagCF->setEnabled(bCF);
162     ui->labelFlagOF->setEnabled(bOF);
163     ui->labelFlagPF->setEnabled(bPF);
164     ui->labelFlagSF->setEnabled(bSF);
165     ui->labelFlagZF->setEnabled(bZF);
166 
167     ui->labelJA->setEnabled((bCF==false)&&(bZF==false));
168     ui->labelJBE->setEnabled((bCF==true)||(bZF==true));
169     ui->labelJGE->setEnabled(bSF==bOF);
170     ui->labelJL->setEnabled(bSF!=bOF);
171     ui->labelJLE->setEnabled((bZF==true)||(bSF!=bOF));
172     ui->labelJG->setEnabled((bZF==false)&&(bSF==bOF));
173     ui->labelJB->setEnabled(bCF==true);
174     ui->labelJAE->setEnabled(bCF==false);
175     ui->labelJE->setEnabled(bZF==true);
176     ui->labelJNE->setEnabled(bZF==false);
177     ui->labelJP->setEnabled(bPF==true);
178     ui->labelJNP->setEnabled(bPF==false);
179     ui->labelJS->setEnabled(bSF==true);
180     ui->labelJNS->setEnabled(bSF==false);
181     ui->labelJO->setEnabled(bOF==true);
182     ui->labelJNO->setEnabled(bOF==false);
183 }
184 
loadOpcodes(const ASM_DEF::OPCODE_RECORD * pRecords,qint32 nRecordsSize)185 void GuiMainWindow::loadOpcodes(const ASM_DEF::OPCODE_RECORD *pRecords, qint32 nRecordsSize)
186 {
187 #if QT_VERSION >= 0x050300
188     QSignalBlocker blocker(ui->comboBoxOpcode);
189 #else
190     const bool bBlocked1=ui->comboBoxOpcode->blockSignals(true);
191 #endif
192 
193     g_mapOpcodes.clear();
194     ui->comboBoxOpcode->clear();
195 
196     for(int i=0;i<nRecordsSize;i++)
197     {
198         g_mapOpcodes.insert(pRecords[i].opcode,pRecords[i]);
199 
200         ui->comboBoxOpcode->addItem(pRecords[i].pszName,static_cast<int>(pRecords[i].opcode));
201     }
202 
203 #if QT_VERSION < 0x050300
204     ui->comboBoxOpcode->blockSignals(bBlocked1);
205 #endif
206 }
207 
on_comboBoxOpcode_currentIndexChanged(int nIndex)208 void GuiMainWindow::on_comboBoxOpcode_currentIndexChanged(int nIndex)
209 {
210     if(nIndex!=-1)
211     {
212         adjustMode();
213         calc();
214     }
215 }
216 
adjustValue(QGroupBox * pGroupBox,ASM_DEF::VALUE_RECORD vr)217 void GuiMainWindow::adjustValue(QGroupBox *pGroupBox, ASM_DEF::VALUE_RECORD vr)
218 {
219     if(vr.nMaxValue)
220     {
221         pGroupBox->show();
222         pGroupBox->setTitle(vr.pszRegName);
223     }
224     else
225     {
226         pGroupBox->hide();
227     }
228 }
229 
adjustMode()230 void GuiMainWindow::adjustMode()
231 {
232     ASM_DEF::OPCODE_RECORD currentRecord=g_mapOpcodes.value(static_cast<ASM_DEF::OP>(ui->comboBoxOpcode->currentData().toInt()));
233 
234     ModeValidator::MODE mode=static_cast<ModeValidator::MODE>(ui->comboBoxMode->currentData().toInt());
235 
236     ModeValidator::DATA validatorData[2]={};
237     ModeValidator::DATA validatorDataFlag;
238 
239     validatorData[0].mode=mode;
240     validatorData[0].nMaxValue=currentRecord.vrOperand[0].nMaxValue;
241 
242     validatorData[1].mode=mode;
243     validatorData[1].nMaxValue=currentRecord.vrOperand[1].nMaxValue;
244 
245     validatorDataFlag.mode=mode;
246     validatorDataFlag.nMaxValue=0xFFFFFFFF;
247 
248     g_modeValidator[0].setData(validatorData[0]);
249     g_modeValidator[1].setData(validatorData[1]);
250     g_modeValidatorFlag.setData(validatorDataFlag);
251 
252     ui->lineEditOpcode->setText(currentRecord.pszExample);
253 
254     adjustValue(ui->groupBoxOperand1,currentRecord.vrOperand[0]);
255     adjustValue(ui->groupBoxOperand2,currentRecord.vrOperand[1]);
256     adjustValue(ui->groupBoxResult1,currentRecord.vrResult[0]);
257     adjustValue(ui->groupBoxResult2,currentRecord.vrResult[1]);
258     adjustValue(ui->groupBoxResult3,currentRecord.vrResult[2]);
259     adjustValue(ui->groupBoxResult4,currentRecord.vrResult[3]);
260 }
261 
on_lineEditOperand1_textChanged(const QString & arg1)262 void GuiMainWindow::on_lineEditOperand1_textChanged(const QString &arg1)
263 {
264     Q_UNUSED(arg1)
265 
266     calc();
267 }
268 
on_lineEditOperand2_textChanged(const QString & arg1)269 void GuiMainWindow::on_lineEditOperand2_textChanged(const QString &arg1)
270 {
271     Q_UNUSED(arg1)
272 
273     calc();
274 }
275 
on_lineEditResult1_textChanged(const QString & arg1)276 void GuiMainWindow::on_lineEditResult1_textChanged(const QString &arg1)
277 {
278     Q_UNUSED(arg1)
279 
280     calc();
281 }
282 
on_lineEditResult2_textChanged(const QString & arg1)283 void GuiMainWindow::on_lineEditResult2_textChanged(const QString &arg1)
284 {
285     Q_UNUSED(arg1)
286 
287     calc();
288 }
289 
on_pushButtonFlagCF_toggled(bool checked)290 void GuiMainWindow::on_pushButtonFlagCF_toggled(bool checked)
291 {
292     adjustFlags(ASM_DEF::CF,checked);
293     calc();
294 }
295 
on_pushButtonFlagPF_toggled(bool checked)296 void GuiMainWindow::on_pushButtonFlagPF_toggled(bool checked)
297 {
298     adjustFlags(ASM_DEF::PF,checked);
299     calc();
300 }
301 
on_pushButtonFlagAF_toggled(bool checked)302 void GuiMainWindow::on_pushButtonFlagAF_toggled(bool checked)
303 {
304     adjustFlags(ASM_DEF::AF,checked);
305     calc();
306 }
307 
on_pushButtonFlagZF_toggled(bool checked)308 void GuiMainWindow::on_pushButtonFlagZF_toggled(bool checked)
309 {
310     adjustFlags(ASM_DEF::ZF,checked);
311     calc();
312 }
313 
on_pushButtonFlagSF_toggled(bool checked)314 void GuiMainWindow::on_pushButtonFlagSF_toggled(bool checked)
315 {
316     adjustFlags(ASM_DEF::SF,checked);
317     calc();
318 }
319 
on_pushButtonFlagOF_toggled(bool checked)320 void GuiMainWindow::on_pushButtonFlagOF_toggled(bool checked)
321 {
322     adjustFlags(ASM_DEF::OF,checked);
323     calc();
324 }
325 
on_lineEditFlagsBefore_textChanged(const QString & arg1)326 void GuiMainWindow::on_lineEditFlagsBefore_textChanged(const QString &arg1)
327 {
328     Q_UNUSED(arg1)
329 
330     XVALUE nFlag=getLineEditValue(ui->lineEditFlagsBefore,g_currentMode);
331 
332     ui->pushButtonFlagAF->setChecked(nFlag&(ASM_DEF::AF));
333     ui->pushButtonFlagCF->setChecked(nFlag&(ASM_DEF::CF));
334     ui->pushButtonFlagOF->setChecked(nFlag&(ASM_DEF::OF));
335     ui->pushButtonFlagPF->setChecked(nFlag&(ASM_DEF::PF));
336     ui->pushButtonFlagSF->setChecked(nFlag&(ASM_DEF::SF));
337     ui->pushButtonFlagZF->setChecked(nFlag&(ASM_DEF::ZF));
338 
339     calc();
340 }
341 
on_comboBoxMode_currentIndexChanged(int index)342 void GuiMainWindow::on_comboBoxMode_currentIndexChanged(int index)
343 {
344     if(index!=-1)
345     {
346         RECDATA _data=RECDATA_INIT;
347 
348         _data.OPERAND[0]=getLineEditValue(ui->lineEditOperand1,g_currentMode);
349         _data.OPERAND[1]=getLineEditValue(ui->lineEditOperand2,g_currentMode);
350         _data.FLAG[0]=getLineEditValue(ui->lineEditFlagsBefore,g_currentMode);
351 
352         g_currentMode=static_cast<ModeValidator::MODE>(ui->comboBoxMode->currentData().toInt());
353 
354         adjustMode();
355 
356         setLineEditValue(ui->lineEditOperand1,g_currentMode,_data.OPERAND[0]);
357         setLineEditValue(ui->lineEditOperand2,g_currentMode,_data.OPERAND[1]);
358         setLineEditValue(ui->lineEditFlagsBefore,g_currentMode,_data.FLAG[0]);
359 
360         calc();
361     }
362 }
363 
getLineEditValue(QLineEdit * pLineEdit,ModeValidator::MODE mode)364 XVALUE GuiMainWindow::getLineEditValue(QLineEdit *pLineEdit, ModeValidator::MODE mode)
365 {
366     XVALUE nValue=0;
367 
368     QString sText=pLineEdit->text();
369 
370     if(mode==ModeValidator::MODE_HEX)
371     {
372 #ifdef OPCODE32
373         nValue=sText.toULong(nullptr,16);
374 #else
375         nValue=sText.toULongLong(nullptr,16);
376 #endif
377     }
378     else if(mode==ModeValidator::MODE_SIGNED)
379     {
380 #ifdef OPCODE32
381         nValue=static_cast<XVALUE>(sText.toLong(nullptr,10));
382 #else
383         nValue=static_cast<XVALUE>(sText.toLongLong(nullptr,10));
384 #endif
385     }
386     else if(mode==ModeValidator::MODE_UNSIGNED)
387     {
388 #ifdef OPCODE32
389         nValue=sText.toULong(nullptr,10);
390 #else
391         nValue=sText.toULongLong(nullptr,10);
392 #endif
393     }
394 
395     return nValue;
396 }
397 
setLineEditValue(QLineEdit * pLineEdit,ModeValidator::MODE mode,XVALUE nValue)398 void GuiMainWindow::setLineEditValue(QLineEdit *pLineEdit, ModeValidator::MODE mode, XVALUE nValue)
399 {
400     QString sText;
401 
402     if(mode==ModeValidator::MODE_HEX)
403     {
404         sText=QString::number(nValue,16);
405     }
406     else if(mode==ModeValidator::MODE_SIGNED)
407     {
408         sText=QString::number(static_cast<SXVALUE>(nValue),10);
409     }
410     else if(mode==ModeValidator::MODE_UNSIGNED)
411     {
412         sText=QString::number(nValue,10);
413     }
414 
415     pLineEdit->setText(sText);
416 }
417 
adjustFlags(XVALUE nFlag,bool bState)418 void GuiMainWindow::adjustFlags(XVALUE nFlag, bool bState)
419 {
420     ModeValidator::MODE mode=static_cast<ModeValidator::MODE>(ui->comboBoxMode->currentData().toInt());
421 
422     XVALUE nValue=getLineEditValue(ui->lineEditFlagsBefore,mode);
423 
424     if(bState)
425     {
426         nValue|=nFlag;
427     }
428     else
429     {
430         nValue&=(~nFlag);
431     }
432 
433     setLineEditValue(ui->lineEditFlagsBefore,mode,nValue);
434 }
435 
on_comboBoxOpcodeGroup_currentIndexChanged(int index)436 void GuiMainWindow::on_comboBoxOpcodeGroup_currentIndexChanged(int index)
437 {
438     if(index!=-1)
439     {
440         switch(ui->comboBoxOpcodeGroup->currentData(Qt::UserRole).toUInt())
441         {
442             case OG_TWOOPERANDS:    loadOpcodes(ASM_DEF::asm_twooperands,sizeof(ASM_DEF::asm_twooperands)/sizeof(ASM_DEF::OPCODE_RECORD));      break;
443             case OG_ONEOPERAND:     loadOpcodes(ASM_DEF::asm_oneoperand,sizeof(ASM_DEF::asm_oneoperand)/sizeof(ASM_DEF::OPCODE_RECORD));        break;
444             case OG_MULDIV:         loadOpcodes(ASM_DEF::asm_muldiv,sizeof(ASM_DEF::asm_muldiv)/sizeof(ASM_DEF::OPCODE_RECORD));                break;
445             case OG_SHIFT:          loadOpcodes(ASM_DEF::asm_shift,sizeof(ASM_DEF::asm_shift)/sizeof(ASM_DEF::OPCODE_RECORD));                  break;
446             case OG_BITS:           loadOpcodes(ASM_DEF::asm_bits,sizeof(ASM_DEF::asm_bits)/sizeof(ASM_DEF::OPCODE_RECORD));                    break;
447             case OG_SPECIAL:        loadOpcodes(ASM_DEF::asm_special,sizeof(ASM_DEF::asm_special)/sizeof(ASM_DEF::OPCODE_RECORD));              break;
448         }
449 
450         adjustMode();
451         calc();
452     }
453 }
454 
on_pushButtonOptions_clicked()455 void GuiMainWindow::on_pushButtonOptions_clicked()
456 {
457     DialogOptions dialogOptions(this,&g_xOptions);
458 
459     dialogOptions.exec();
460 
461     adjustWindow();
462 }
463