1 /*	Copyright 2012 Theo Berkau <cwx@cyberwarriorx.com>
2 
3 	This file is part of Yabause.
4 
5 	Yabause is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation; either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	Yabause is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with Yabause; if not, write to the Free Software
17 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 */
19 #include "UICheatSearch.h"
20 #include "UICheatRaw.h"
21 #include "../CommonDialogs.h"
22 
UICheatSearch(QWidget * p,QList<cheatsearch_struct> * search,int searchType)23 UICheatSearch::UICheatSearch( QWidget* p, QList <cheatsearch_struct> *search,
24    int searchType) : QDialog( p )
25 {
26 	// set up dialog
27 	setupUi( this );
28 	if ( p && !p->isFullScreen() )
29 		setWindowFlags( Qt::Sheet );
30 
31    this->search = *search;
32    this->searchType = searchType;
33 
34    // If cheat search hasn't been started yet, disable search and add
35    // cheat
36    if (this->search.empty())
37    {
38       pbRestart->setText(QtYabause::translate("Start"));
39       pbSearch->setEnabled( false );
40       pbAddCheat->setEnabled( false );
41    }
42 
43    getSearchTypes();
44    listResults();
45 
46 	// retranslate widgets
47 	QtYabause::retranslateWidget( this );
48 }
49 
getSearchTypes()50 void UICheatSearch::getSearchTypes()
51 {
52    switch(searchType & 0xC)
53    {
54    case SEARCHEXACT:
55       rbExact->setChecked(true);
56       break;
57    case SEARCHLESSTHAN:
58       rbLessThan->setChecked(true);
59       break;
60    case SEARCHGREATERTHAN:
61       rbGreaterThan->setChecked(true);
62       break;
63    default: break;
64    }
65 
66    switch(searchType & 0x70)
67    {
68    case SEARCHUNSIGNED:
69       rbUnsigned->setChecked(true);
70       break;
71    case SEARCHSIGNED:
72       rbSigned->setChecked(true);
73       break;
74    default: break;
75    }
76 
77    switch(searchType & 0x3)
78    {
79    case SEARCHBYTE:
80       rb8Bit->setChecked(true);
81       break;
82    case SEARCHWORD:
83       rb16Bit->setChecked(true);
84       break;
85    case SEARCHLONG:
86       rb32Bit->setChecked(true);
87       break;
88    default: break;
89    }
90 }
91 
getSearchVariables(int * searchType)92 QList<cheatsearch_struct> * UICheatSearch::getSearchVariables(int *searchType)
93 {
94    *searchType = this->searchType;
95    return &search;
96 }
97 
setSearchTypes()98 void UICheatSearch::setSearchTypes()
99 {
100    searchType = 0;
101    if (rbExact->isChecked())
102       searchType |= SEARCHEXACT;
103    else if (rbLessThan->isChecked())
104       searchType |= SEARCHLESSTHAN;
105    else
106       searchType |= SEARCHGREATERTHAN;
107 
108    if (rbUnsigned->isChecked())
109       searchType |= SEARCHUNSIGNED;
110    else
111       searchType |= SEARCHSIGNED;
112 
113    if (rb8Bit->isChecked())
114       searchType |= SEARCHBYTE;
115    else if (rb16Bit->isChecked())
116       searchType |= SEARCHWORD;
117    else
118       searchType |= SEARCHLONG;
119 }
120 
listResults()121 void UICheatSearch::listResults()
122 {
123    u32 i;
124 
125    // Clear old info
126    twSearchResults->clear();
127    pbAddCheat->setEnabled(false);
128 
129    for (int j = 0; j < search.count(); j++)
130    {
131       if (search[j].results)
132       {
133          // Show results
134          for (i = 0; i < search[j].numResults; i++)
135          {
136             QTreeWidgetItem* it = new QTreeWidgetItem( twSearchResults );
137             QString s;
138             s.sprintf("%08X", search[j].results[i].addr);
139             it->setText( 0, s );
140 
141             switch(searchType & 0x3)
142             {
143             case SEARCHBYTE:
144                s.sprintf("%d", MappedMemoryReadByteNocache(MSH2, search[j].results[i].addr));
145                break;
146             case SEARCHWORD:
147                s.sprintf("%d", MappedMemoryReadWordNocache(MSH2, search[j].results[i].addr));
148                break;
149             case SEARCHLONG:
150                s.sprintf("%d", MappedMemoryReadLongNocache(MSH2, search[j].results[i].addr));
151                break;
152             default: break;
153             }
154             it->setText( 1, s );
155          }
156       }
157    }
158 }
159 
adjustSearchValueQValidator()160 void UICheatSearch::adjustSearchValueQValidator()
161 {
162    // Figure out range
163    int min, max;
164 
165    min = 0;
166 
167    if (rb8Bit->isChecked())
168       max = 0xFF;
169    else if (rb16Bit->isChecked())
170       max = 0xFFFF;
171    else
172       max = 0xFFFFFFFF;
173 
174    if (rbSigned->isChecked())
175    {
176       min = -(max >> 1) - 1;
177       max >>= 1;
178    }
179    if (rb32Bit->isChecked())
180    {
181       if (rbSigned->isChecked())
182          leSearchValue->setValidator(new QRegExpValidator(QRegExp("-?\\d{1,10}"), leSearchValue));
183       else
184          leSearchValue->setValidator(new QRegExpValidator(QRegExp("\\d{1,10}"), leSearchValue));
185    }
186    else
187       leSearchValue->setValidator(new QIntValidator(min, max, leSearchValue));
188 }
189 
on_twSearchResults_itemSelectionChanged()190 void UICheatSearch::on_twSearchResults_itemSelectionChanged()
191 {
192    pbAddCheat->setEnabled( twSearchResults->selectedItems().count() );
193 }
194 
on_rbUnsigned_toggled(bool checked)195 void UICheatSearch::on_rbUnsigned_toggled(bool checked)
196 {
197    if (checked)
198       adjustSearchValueQValidator();
199 }
200 
on_rbSigned_toggled(bool checked)201 void UICheatSearch::on_rbSigned_toggled(bool checked)
202 {
203    if (checked)
204       adjustSearchValueQValidator();
205 }
206 
on_rb8Bit_toggled(bool checked)207 void UICheatSearch::on_rb8Bit_toggled(bool checked)
208 {
209    if (checked)
210       adjustSearchValueQValidator();
211 }
212 
on_rb16Bit_toggled(bool checked)213 void UICheatSearch::on_rb16Bit_toggled(bool checked)
214 {
215    if (checked)
216       adjustSearchValueQValidator();
217 }
218 
on_rb32Bit_toggled(bool checked)219 void UICheatSearch::on_rb32Bit_toggled(bool checked)
220 {
221    if (checked)
222       adjustSearchValueQValidator();
223 }
224 
on_leSearchValue_textChanged(const QString & text)225 void UICheatSearch::on_leSearchValue_textChanged( const QString & text )
226 {
227 	pbSearch->setEnabled(!text.isEmpty());
228 }
229 
on_pbRestart_clicked()230 void UICheatSearch::on_pbRestart_clicked()
231 {
232    cheatsearch_struct searchTmp;
233 
234    // If there were search result, clear them, otherwise adjust GUI
235    if (search.isEmpty())
236    {
237       pbRestart->setText(QtYabause::translate("Restart"));
238    }
239    else
240    {
241       for (int j = 0; j < search.count(); j++)
242       {
243          if (search[j].results)
244             free(search[j].results);
245       }
246 		search.clear();
247    }
248 
249    // Setup initial values
250    searchTmp.results = NULL;
251 
252    searchTmp.startAddr = 0x06000000;
253    searchTmp.endAddr = 0x06100000;
254    searchTmp.numResults = searchTmp.endAddr-searchTmp.startAddr;
255    search.append(searchTmp);
256 
257    searchTmp.startAddr = 0x00200000;
258    searchTmp.endAddr = 0x00300000;
259    searchTmp.numResults = searchTmp.endAddr-searchTmp.startAddr;
260    search.append(searchTmp);
261    twSearchResults->clear();
262 }
263 
on_pbSearch_clicked()264 void UICheatSearch::on_pbSearch_clicked()
265 {
266 	if (LowWram && HighWram)
267 	{
268 		// Search low wram and high wram areas
269 		setSearchTypes();
270 
271 		for (int i = 0; i < search.count(); i++)
272 		{
273 			search[i].results = MappedMemorySearch(search[i].startAddr, search[i].endAddr, searchType,
274 				leSearchValue->text().toLatin1(), search[i].results, &search[i].numResults);
275 		}
276 
277 		listResults();
278 	}
279 }
280 
on_pbAddCheat_clicked()281 void UICheatSearch::on_pbAddCheat_clicked()
282 {
283    UICheatRaw d( this );
284    QString s;
285 	bool b;
286 
287    // Insert current address/values into dialog
288    QTreeWidgetItem *currentItem = twSearchResults->currentItem();
289    d.leAddress->setText(currentItem->text(0));
290    s.sprintf("%X", currentItem->text(1).toUInt());
291    d.leValue->setText(s);
292    d.rbByte->setChecked(rb8Bit->isChecked());
293    d.rbWord->setChecked(rb16Bit->isChecked());
294    d.rbLong->setChecked(rb32Bit->isChecked());
295    if ( d.exec())
296    {
297       if ( CheatAddCode( d.type(), d.leAddress->text().toUInt(&b, 16), d.leValue->text().toUInt(&b, 16) ) != 0 )
298       {
299          CommonDialogs::information( QtYabause::translate( "Unable to add code" ) );
300          return;
301       }
302       else
303       {
304          cheatlist_struct *mCheats;
305          int cheatsCount;
306          mCheats = CheatGetList( &cheatsCount );
307 
308          CheatChangeDescriptionByIndex( cheatsCount -1, d.leDescription->text().toLatin1().data() );
309       }
310    }
311 }
312