/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "DialogOpcodes.h"
#include "DebuggerCoreInterface.h"
#include "Debugger.h"
#include "MemoryRegions.h"
#include "ByteShiftArray.h"
#include "Util.h"

#include <QHeaderView>
#include <QMessageBox>
#include <QVector>
#include <QSortFilterProxyModel>
#include <QListWidgetItem>

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
DialogOpcodes::DialogOpcodes(QWidget *parent) : QDialog(parent) {
	ui.setupUi(this);
	ui.tableView->verticalHeader()->hide();
	ui.tableView->horizontalHeader()->setStretchLastSection(true);
	ui.tableView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
	
	m_FilterModel = new QSortFilterProxyModel(this);
	connect(ui.txtSearch, SIGNAL(textChanged(const QString &)), m_FilterModel, SLOT(setFilterFixedString(const QString &)));
}

//------------------------------------------------------------------------------
// Name: on_listWidget_itemDoubleClicked(QListWidgetItem *item)
// Desc: follows the found item in the data view
//------------------------------------------------------------------------------
void DialogOpcodes::on_listWidget_itemDoubleClicked(QListWidgetItem *item) {
	bool ok;
	const edb::address_t addr = item->data(Qt::UserRole).toULongLong(&ok);
	if(ok) {
		edb::v1::jumpToAddress(addr);
	}
}

//------------------------------------------------------------------------------
// Name: showEvent(QShowEvent *)
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::showEvent(QShowEvent *) {
	m_FilterModel->setFilterKeyColumn(3);
	m_FilterModel->setSourceModel(&edb::v1::memoryRegions());
	ui.tableView->setModel(m_FilterModel);
	ui.progressBar->setValue(0);
	ui.listWidget->clear();
}

#define OPCODE_CASE(value, str, address) case (value): \
	do { \
		QListWidgetItem *const item = new QListWidgetItem(QString().sprintf((str), (address))); \
		item->setData(Qt::UserRole, address); \
		ui.listWidget->addItem(item); \
	} while(0); \
	break

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEax(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe0ff, EDB_FMT_PTR ": jmp eax", start_address);
	OPCODE_CASE(0xd0ff, EDB_FMT_PTR ": call eax", start_address);
	OPCODE_CASE(0xc350, EDB_FMT_PTR ": push eax; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff50, EDB_FMT_PTR ": push eax; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff50, EDB_FMT_PTR ": push eax; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEbx(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe3ff, EDB_FMT_PTR ": jmp ebx", start_address);
	OPCODE_CASE(0xd3ff, EDB_FMT_PTR ": call ebx", start_address);
	OPCODE_CASE(0xc353, EDB_FMT_PTR ": push ebx; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff53, EDB_FMT_PTR ": push ebx; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff53, EDB_FMT_PTR ": push ebx; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEcx(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe1ff, EDB_FMT_PTR ": jmp ecx", start_address);
	OPCODE_CASE(0xd1ff, EDB_FMT_PTR ": call ecx", start_address);
	OPCODE_CASE(0xc351, EDB_FMT_PTR ": push ecx; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff51, EDB_FMT_PTR ": push ecx; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff51, EDB_FMT_PTR ": push ecx; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEdx(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe2ff, EDB_FMT_PTR ": jmp edx", start_address);
	OPCODE_CASE(0xd2ff, EDB_FMT_PTR ": call edx", start_address);
	OPCODE_CASE(0xc352, EDB_FMT_PTR ": push edx; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff52, EDB_FMT_PTR ": push edx; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff52, EDB_FMT_PTR ": push edx; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEbp(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe5ff, EDB_FMT_PTR ": jmp ebp", start_address);
	OPCODE_CASE(0xd5ff, EDB_FMT_PTR ": call ebp", start_address);
	OPCODE_CASE(0xc355, EDB_FMT_PTR ": push ebp; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff55, EDB_FMT_PTR ": push ebp; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff55, EDB_FMT_PTR ": push ebp; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEsp(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe4ff, EDB_FMT_PTR ": jmp esp", start_address);
	OPCODE_CASE(0xd4ff, EDB_FMT_PTR ": call esp", start_address);
	OPCODE_CASE(0xc354, EDB_FMT_PTR ": push esp; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff54, EDB_FMT_PTR ": push esp; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff54, EDB_FMT_PTR ": push esp; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEsi(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe6ff, EDB_FMT_PTR ": jmp esi", start_address);
	OPCODE_CASE(0xd6ff, EDB_FMT_PTR ": call esi", start_address);
	OPCODE_CASE(0xc356, EDB_FMT_PTR ": push esi; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff56, EDB_FMT_PTR ": push esi; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff56, EDB_FMT_PTR ": push esi; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testEdi(const DialogOpcodes::OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xe7ff, EDB_FMT_PTR ": jmp edi", start_address);
	OPCODE_CASE(0xd7ff, EDB_FMT_PTR ": call edi", start_address);
	OPCODE_CASE(0xc357, EDB_FMT_PTR ": push edi; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x2424ff57, EDB_FMT_PTR ": push edi; jmp [esp]", start_address);
	OPCODE_CASE(0x2414ff57, EDB_FMT_PTR ": push edi; call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testESP_ADD_0(const OpcodeData &data, edb::address_t start_address) {
	switch(data.byte) {
	OPCODE_CASE(0xc3, EDB_FMT_PTR ": ret", start_address);
	OPCODE_CASE(0xc2, EDB_FMT_PTR ": ret N", start_address);
	}
	
	const quint32 instr24 = data.dword & 0x00ffffff;
	switch(instr24) {
	OPCODE_CASE(0x00d0ff58, EDB_FMT_PTR ": pop eax; call eax", start_address);
	OPCODE_CASE(0x00d1ff59, EDB_FMT_PTR ": pop ecx; call ecx", start_address);
	OPCODE_CASE(0x00d2ff5a, EDB_FMT_PTR ": pop edx; call edx", start_address);
	OPCODE_CASE(0x00d3ff5b, EDB_FMT_PTR ": pop ebx; call ebx", start_address);
	OPCODE_CASE(0x00d4ff5c, EDB_FMT_PTR ": pop esp; call esp", start_address);
	OPCODE_CASE(0x00d5ff5d, EDB_FMT_PTR ": pop ebp; call ebp", start_address);
	OPCODE_CASE(0x00d6ff5e, EDB_FMT_PTR ": pop esi; call esi", start_address);
	OPCODE_CASE(0x00d7ff5f, EDB_FMT_PTR ": pop edi; call edi", start_address);
	OPCODE_CASE(0x00e0ff58, EDB_FMT_PTR ": pop eax; jmp eax", start_address);
	OPCODE_CASE(0x00e1ff59, EDB_FMT_PTR ": pop ecx; jmp ecx", start_address);
	OPCODE_CASE(0x00e2ff5a, EDB_FMT_PTR ": pop edx; jmp edx", start_address);
	OPCODE_CASE(0x00e3ff5b, EDB_FMT_PTR ": pop ebx; jmp ebx", start_address);
	OPCODE_CASE(0x00e4ff5c, EDB_FMT_PTR ": pop esp; jmp esp", start_address);
	OPCODE_CASE(0x00e5ff5d, EDB_FMT_PTR ": pop ebp; jmp ebp", start_address);
	OPCODE_CASE(0x00e6ff5e, EDB_FMT_PTR ": pop esi; jmp esi", start_address);
	OPCODE_CASE(0x00e7ff5f, EDB_FMT_PTR ": pop edi; jmp edi", start_address);
	OPCODE_CASE(0x002424ff, EDB_FMT_PTR ": jmp [esp]", start_address);
	OPCODE_CASE(0x002414ff, EDB_FMT_PTR ": call [esp]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testESP_ADD_4(const OpcodeData &data, edb::address_t start_address) {
	switch(data.word) {
	OPCODE_CASE(0xc358, EDB_FMT_PTR ": pop eax; ret", start_address);
	OPCODE_CASE(0xc35b, EDB_FMT_PTR ": pop ebx; ret", start_address);
	OPCODE_CASE(0xc359, EDB_FMT_PTR ": pop ecx; ret", start_address);
	OPCODE_CASE(0xc35a, EDB_FMT_PTR ": pop edx; ret", start_address);
	OPCODE_CASE(0xc35e, EDB_FMT_PTR ": pop esi; ret", start_address);
	OPCODE_CASE(0xc35f, EDB_FMT_PTR ": pop edi; ret", start_address);
	OPCODE_CASE(0xc35d, EDB_FMT_PTR ": pop ebp; ret", start_address);
	//OPCODE_CASE(0xc35c, EDB_FMT_PTR ": pop esp; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x042464ff, EDB_FMT_PTR ": jmp [esp + 4]", start_address);
	OPCODE_CASE(0x042454ff, EDB_FMT_PTR ": call [esp + 4]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testESP_ADD_8(const OpcodeData &data, edb::address_t start_address) {

	
	const quint32 instr24 = data.dword & 0x00ffffff;
	switch(instr24) {
	OPCODE_CASE(0x00c35858, EDB_FMT_PTR ": pop eax; pop eax; ret", start_address);
	OPCODE_CASE(0x00c35958, EDB_FMT_PTR ": pop eax; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a58, EDB_FMT_PTR ": pop eax; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b58, EDB_FMT_PTR ": pop eax; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c58, EDB_FMT_PTR ": pop eax; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d58, EDB_FMT_PTR ": pop eax; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e58, EDB_FMT_PTR ": pop eax; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f58, EDB_FMT_PTR ": pop eax; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c35859, EDB_FMT_PTR ": pop ecx; pop eax; ret", start_address);
	OPCODE_CASE(0x00c35959, EDB_FMT_PTR ": pop ecx; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a59, EDB_FMT_PTR ": pop ecx; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b59, EDB_FMT_PTR ": pop ecx; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c59, EDB_FMT_PTR ": pop ecx; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d59, EDB_FMT_PTR ": pop ecx; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e59, EDB_FMT_PTR ": pop ecx; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f59, EDB_FMT_PTR ": pop ecx; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c3585a, EDB_FMT_PTR ": pop edx; pop eax; ret", start_address);
	OPCODE_CASE(0x00c3595a, EDB_FMT_PTR ": pop edx; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a5a, EDB_FMT_PTR ": pop edx; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b5a, EDB_FMT_PTR ": pop edx; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5a, EDB_FMT_PTR ": pop edx; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d5a, EDB_FMT_PTR ": pop edx; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e5a, EDB_FMT_PTR ": pop edx; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f5a, EDB_FMT_PTR ": pop edx; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c3585b, EDB_FMT_PTR ": pop ebx; pop eax; ret", start_address);
	OPCODE_CASE(0x00c3595b, EDB_FMT_PTR ": pop ebx; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a5b, EDB_FMT_PTR ": pop ebx; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b5b, EDB_FMT_PTR ": pop ebx; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5b, EDB_FMT_PTR ": pop ebx; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d5b, EDB_FMT_PTR ": pop ebx; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e5b, EDB_FMT_PTR ": pop ebx; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f5b, EDB_FMT_PTR ": pop ebx; pop edi; ret", start_address);
	
//	OPCODE_CASE(0x00c3585c, EDB_FMT_PTR ": pop esp; pop eax; ret", start_address);
//	OPCODE_CASE(0x00c3595c, EDB_FMT_PTR ": pop esp; pop ecx; ret", start_address);
//	OPCODE_CASE(0x00c35a5c, EDB_FMT_PTR ": pop esp; pop edx; ret", start_address);
//	OPCODE_CASE(0x00c35b5c, EDB_FMT_PTR ": pop esp; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5c, EDB_FMT_PTR ": pop esp; pop esp; ret", start_address);
//	OPCODE_CASE(0x00c35d5c, EDB_FMT_PTR ": pop esp; pop ebp; ret", start_address);
//	OPCODE_CASE(0x00c35e5c, EDB_FMT_PTR ": pop esp; pop esi; ret", start_address);
//	OPCODE_CASE(0x00c35f5c, EDB_FMT_PTR ": pop esp; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c3585d, EDB_FMT_PTR ": pop ebp; pop eax; ret", start_address);
	OPCODE_CASE(0x00c3595d, EDB_FMT_PTR ": pop ebp; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a5d, EDB_FMT_PTR ": pop ebp; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b5d, EDB_FMT_PTR ": pop ebp; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5d, EDB_FMT_PTR ": pop ebp; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d5d, EDB_FMT_PTR ": pop ebp; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e5d, EDB_FMT_PTR ": pop ebp; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f5d, EDB_FMT_PTR ": pop ebp; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c3585e, EDB_FMT_PTR ": pop esi; pop eax; ret", start_address);
	OPCODE_CASE(0x00c3595e, EDB_FMT_PTR ": pop esi; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a5e, EDB_FMT_PTR ": pop esi; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b5e, EDB_FMT_PTR ": pop esi; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5e, EDB_FMT_PTR ": pop esi; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d5e, EDB_FMT_PTR ": pop esi; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e5e, EDB_FMT_PTR ": pop esi; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f5e, EDB_FMT_PTR ": pop esi; pop edi; ret", start_address);
	
	OPCODE_CASE(0x00c3585f, EDB_FMT_PTR ": pop edi; pop eax; ret", start_address);
	OPCODE_CASE(0x00c3595f, EDB_FMT_PTR ": pop edi; pop ecx; ret", start_address);
	OPCODE_CASE(0x00c35a5f, EDB_FMT_PTR ": pop edi; pop edx; ret", start_address);
	OPCODE_CASE(0x00c35b5f, EDB_FMT_PTR ": pop edi; pop ebx; ret", start_address);
//	OPCODE_CASE(0x00c35c5f, EDB_FMT_PTR ": pop edi; pop esp; ret", start_address);
	OPCODE_CASE(0x00c35d5f, EDB_FMT_PTR ": pop edi; pop ebp; ret", start_address);
	OPCODE_CASE(0x00c35e5f, EDB_FMT_PTR ": pop edi; pop esi; ret", start_address);
	OPCODE_CASE(0x00c35f5f, EDB_FMT_PTR ": pop edi; pop edi; ret", start_address);
	}
	
	switch(data.dword) {
	OPCODE_CASE(0x082464ff, EDB_FMT_PTR ": jmp [esp + 8]", start_address);
	OPCODE_CASE(0x082454ff, EDB_FMT_PTR ": call [esp + 8]", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::testESP_SUB_4(const OpcodeData &data, edb::address_t start_address) {
	switch(data.dword) {
	OPCODE_CASE(0xfc2464ff, EDB_FMT_PTR ": jmp [esp - 4]", start_address);
	OPCODE_CASE(0xfc2454ff, EDB_FMT_PTR ": call [esp - 4]", start_address);
	OPCODE_CASE(0xc304ec83, EDB_FMT_PTR ": sub esp, 4; ret", start_address);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::doFind() {
	ByteShiftArray bsa(sizeof(OpcodeData));
	
	int classtype = ui.comboBox->currentIndex();
	
	const QItemSelectionModel *const selModel = ui.tableView->selectionModel();
	const QModelIndexList sel = selModel->selectedRows();
	
	if(sel.size() == 0) {
		QMessageBox::information(this, "No Region Selected", "You must select a region which is to be scanned for the desired opcode.");
	} else {
	
		foreach(const QModelIndex selected_item, sel) {

			const QModelIndex index = m_FilterModel->mapToSource(selected_item);
			const MemoryRegions::Region *const region = reinterpret_cast<const MemoryRegions::Region *>(index.internalPointer());

			edb::address_t start_address		= region->start;
			const edb::address_t end_address	= region->end;
			const edb::address_t orig_start		= start_address;
			bsa.clear();

			// create a reference to the bsa's data so we can pass it to the testXXXX functions
			const OpcodeData &opcode = *reinterpret_cast<const OpcodeData *>(bsa.data());

			// do the search for this region!
			while(start_address < end_address) {

				// read in the next byte
				bsa.shl();
				quint8 byte;
				edb::v1::debuggerBase->readBytes(start_address, &byte, sizeof(quint8));
				bsa[bsa.size() - 1] = byte;

				switch(classtype) {
				case 0: 
					testEax(opcode, start_address - 3);					
					break;
				case 1:
					testEbx(opcode, start_address - 3);
					break;
				case 2:
					testEcx(opcode, start_address - 3);
					break;
				case 3:
					testEdx(opcode, start_address - 3);
					break;
				case 4:
					testEbp(opcode, start_address - 3);
					break;
				case 5:
					testEsp(opcode, start_address - 3);
					break;
				case 6:
					testEsi(opcode, start_address - 3);
					break;
				case 7:
					testEdi(opcode, start_address - 3);
					break;
				case 8:
					testEax(opcode, start_address - 3);					
					testEbx(opcode, start_address - 3);
					testEcx(opcode, start_address - 3);
					testEdx(opcode, start_address - 3);
					testEbp(opcode, start_address - 3);
					testEsp(opcode, start_address - 3);
					testEsi(opcode, start_address - 3);
					testEdi(opcode, start_address - 3);
					break;
				case 9:
					// [ESP] -> EIP
					testESP_ADD_0(opcode, start_address - 3);
					break;	
				case 10:
					// [ESP + 4] -> EIP
					testESP_ADD_4(opcode, start_address - 3);
					break;
				case 11:
					// [ESP + 8] -> EIP
					testESP_ADD_8(opcode, start_address - 3);
					break;
				case 12:
					// [ESP - 4] -> EIP
					testESP_SUB_4(opcode, start_address - 3);
					break;
				}
	
				ui.progressBar->setValue(CalculatePercentage((start_address - orig_start), region->size()));	

				++start_address;
			}
		}
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogOpcodes::on_btnFind_clicked() {
	ui.btnFind->setEnabled(false);
	ui.listWidget->clear();
	ui.progressBar->setValue(0);
	doFind();
	ui.progressBar->setValue(100);
	ui.btnFind->setEnabled(true);
}
