Beispiel #1
0
void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText)
{
	u32 encoded;

	auto memLock = Memory::Lock();
	if (Core_IsStepping() == false) {
		MessageBox(wnd,L"Cannot change code while the core is running!",L"Error",MB_OK);
		return;
	}
	std::string op;
	bool result = InputBox_GetString(MainWindow::GetHInstance(),wnd,L"Assemble opcode",defaultText, op, false);
	if (!result)
		return;

	// check if it changes registers first
	auto seperator = op.find('=');
	if (seperator != std::string::npos)
	{
		std::string registerName = trimString(op.substr(0,seperator));
		std::string expression = trimString(op.substr(seperator+1));

		u32 value;
		if (parseExpression(expression.c_str(),debugger,value) == true)
		{
			for (int cat = 0; cat < debugger->GetNumCategories(); cat++)
			{
				for (int reg = 0; reg < debugger->GetNumRegsInCategory(cat); reg++)
				{
					if (strcasecmp(debugger->GetRegName(cat,reg),registerName.c_str()) == 0)
					{
						debugger->SetRegValue(cat,reg,value);
						SendMessage(GetParent(wnd),WM_DEB_UPDATE,0,0);
						return;
					}
				}
			}
		}

		// try to assemble the input if it failed
	}

	result = MIPSAsm::MipsAssembleOpcode(op.c_str(),debugger,address,encoded);
	if (result == true)
	{
		Memory::Write_U32(encoded, address);
		// In case this is a delay slot or combined instruction, clear cache above it too.
		if (MIPSComp::jit)
			MIPSComp::jit->InvalidateCacheAt(address - 4, 8);
		scanFunctions();

		if (address == curAddress)
			gotoAddr(manager.getNthNextAddress(curAddress,1));

		redraw();
	} else {
		std::wstring error = ConvertUTF8ToWString(MIPSAsm::GetAssembleError());
		MessageBox(wnd,error.c_str(),L"Error",MB_OK);
	}
}
Beispiel #2
0
void CtrlMemView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
	if (ctrlDown)
	{	
		switch (tolower(wParam & 0xFFFF))
		{
		case 'g':
			{
				ctrlDown = false;
				u32 addr;
				if (executeExpressionWindow(wnd,debugger,addr) == false) return;
				gotoAddr(addr);
				return;
			}
			break;
		case 'f':
		case 's':
			search(false);
			return;
		case 'c':
			search(true);
			return;
		}
	}

	switch (wParam & 0xFFFF)
	{
	case VK_DOWN:
		scrollCursor(rowSize);
		break;
	case VK_UP:
		scrollCursor(-rowSize);
		break;
	case VK_LEFT:
		scrollCursor(-1);
		break;
	case VK_RIGHT:
		scrollCursor(1);
		break;
	case VK_NEXT:
		scrollWindow(visibleRows);
		break;
	case VK_PRIOR:
		scrollWindow(-visibleRows);
		break;
	case VK_CONTROL:
		ctrlDown = true;
		break;
	case VK_TAB:
		SendMessage(GetParent(wnd),WM_DEB_TABPRESSED,0,0);
		break;
	default:
		return;
	}
}
Beispiel #3
0
void CtrlDisAsmView::FollowBranch()
{
	const char *temp = debugger->disasm(selection,align);;
	const char *mojs=strstr(temp,"->$");
	if (mojs)
	{
		u32 dest;
		sscanf(mojs+3,"%08x",&dest);
		if (dest)
		{
			marker = selection;
			gotoAddr(dest);
		}
	}
}
Beispiel #4
0
void CtrlDisAsmView::followBranch()
{
	MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,curAddress);

	if (info.isBranch)
	{
		jumpStack.push_back(curAddress);
		gotoAddr(info.branchTarget);
	} else if (info.isDataAccess)
	{
		// well, not  exactly a branch, but we can do something anyway
		SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,info.dataAddress,0);
		SetFocus(wnd);
	}
}
void CtrlDisplayListView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
	u32 windowEnd = windowStart+visibleRows*instructionSize;

	switch (wParam & 0xFFFF)
	{
	case VK_DOWN:
		setCurAddress(curAddress + instructionSize, KeyDownAsync(VK_SHIFT));
		scrollAddressIntoView();
		break;
	case VK_UP:
		setCurAddress(curAddress - instructionSize, KeyDownAsync(VK_SHIFT));
		scrollAddressIntoView();
		break;
	case VK_NEXT:
		if (curAddress != windowEnd - instructionSize && curAddressIsVisible()) {
			setCurAddress(windowEnd - instructionSize, KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
		} else {
			setCurAddress(curAddress + visibleRows * instructionSize, KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
		}
		break;
	case VK_PRIOR:
		if (curAddress != windowStart && curAddressIsVisible()) {
			setCurAddress(windowStart, KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
		} else {
			setCurAddress(curAddress - visibleRows * instructionSize, KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
		}
		break;
	case VK_LEFT:
		gotoAddr(list.pc);
		return;
	case VK_SPACE:
		toggleBreakpoint();
		break;
	case VK_F10:
	case VK_F11:
		SendMessage(GetParent(wnd),WM_GEDBG_STEPDISPLAYLIST,0,0);
		break;
	}
	redraw();
}
Beispiel #6
0
void shutdownInterface_SPI(void){
	
	gotoAddr(00,0);
	gotoBank(00);

	writeByte (0, _SNESBankAndData, GPPUB, 0x00);//SNESBankAndData._writeRegister(GPPUB,0x00) # Disables Pull-Up Resistors on MCP SNES Data 0-7
	writeByte (0, _SNESBankAndData, DEFVALB, 0xFF);//SNESBankAndData._writeRegister(DEFVALB,0xFF) # Expect MCP SNES Data 0-7 to default to 0xFF
	writeByte (0, _SNESBankAndData, GPINTENB, 0x00);//SNESBankAndData._writeRegister(GPINTENB,0x00) # Sets up all of SNES Data 0-7 to be interrupt disabled

	writeByte (0, _SNESAddressPins, IODIRA, 0xFF);//SNESAddressPins._writeRegister(IODIRA,0xFF) # Set MCP bank A to outputs (SNES Addr 0-7)
	writeByte (0, _SNESAddressPins, IODIRB, 0xFF);//SNESAddressPins._writeRegister(IODIRB,0xFF) # Set MCP bank B to outputs (SNES Addr 8-15)

	writeByte (0, _SNESBankAndData, IODIRA, 0xFF);//SNESBankAndData._writeRegister(IODIRA,0xFF) # Set MCP bank A to outputs (SNES Bank 0-7)
	changeDataDir(1);//writeByte (0, _SNESBankAndData, IODIRB, 0xFF);//SNESBankAndData._writeRegister(IODIRB,0xFF) # Set MCP bank B to inputs (SNES Data 0-7)

	writeByte (0, _IOControls, IODIRA, 0xEF);//IOControls._writeRegister(IODIRA,0xEF) # Set MCP bank A to inputs; WITH EXCEPTION TO MOSFET

	setIOControl(0); //writeByte (0, _IOControls, GPIOA, 0x10);//IOControls._writeRegister(GPIOA,0x10) #Turn off MOSFET	
	
}
Beispiel #7
0
void gotoOffset(uint32_t offset,int isLowROM){
	//static uint32_t currentOffset = 0;
	//	printf("Forth\n");
	uint8_t bank = 0;
	uint32_t addr = 0;

	if (isLowROM == 0){
		bank = (uint8_t)( offset / 65536); //64Kilobyte pages
		addr = offset - (bank * 65536); //64kilobyte pages
	}

	else{
		bank = (uint8_t)( offset / 32768); //32kilobyte pages
		addr = offset - (bank * 32768); //32kilobyte pages
	}
    //printf("Fifth\n");
	gotoBank(bank);
	gotoAddr(addr,isLowROM);
  //  printf("BANK: %d, ADDR: %d\n",bank, addr);
	//currentOffset = offset;
}
void CtrlDisplayListView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
	u32 windowEnd = windowStart+visibleRows*instructionSize;

	switch (wParam & 0xFFFF)
	{
	case VK_DOWN:
		setCurAddress(curAddress + instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
		scrollAddressIntoView();
		break;
	case VK_UP:
		setCurAddress(curAddress - instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
		scrollAddressIntoView();
		break;
	case VK_NEXT:
		if (curAddress != windowEnd - instructionSize && curAddressIsVisible()) {
			setCurAddress(windowEnd - instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
		} else {
			setCurAddress(curAddress + visibleRows * instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
		}
		break;
	case VK_PRIOR:
		if (curAddress != windowStart && curAddressIsVisible()) {
			setCurAddress(windowStart, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
		} else {
			setCurAddress(curAddress - visibleRows * instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
		}
		break;
	case VK_LEFT:
		gotoAddr(list.pc);
		return;
	}
	redraw();
}
Beispiel #9
0
void CtrlDisAsmView::followBranch()
{
	DisassemblyLineInfo line;
	manager.getLine(curAddress,true,line);

	if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO)
	{
		if (line.info.isBranch)
		{
			jumpStack.push_back(curAddress);
			gotoAddr(line.info.branchTarget);
		} else if (line.info.hasRelevantAddress)
		{
			// well, not  exactly a branch, but we can do something anyway
			SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,line.info.releventAddress,0);
			SetFocus(wnd);
		}
	} else if (line.type == DISTYPE_DATA)
	{
		// jump to the start of the current line
		SendMessage(GetParent(wnd),WM_DEB_GOTOHEXEDIT,curAddress,0);
		SetFocus(wnd);
	}
}
Beispiel #10
0
void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
	dontRedraw = false;
	u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
	keyTaken = true;

	if (KeyDownAsync(VK_CONTROL))
	{
		switch (tolower(wParam & 0xFFFF))
		{
		case 'f':
		case 's':
			search(false);
			break;
		case 'c':
		case VK_INSERT:
			copyInstructions(selectRangeStart, selectRangeEnd, true);
			break;
		case 'x':
			disassembleToFile();
			break;
		case 'a':
			assembleOpcode(curAddress,"");
			break;
		case 'g':
			{
				u32 addr;
				if (executeExpressionWindow(wnd,debugger,addr) == false) return;
				gotoAddr(addr);
			}
			break;
		case 'e':	// edit breakpoint
			editBreakpoint();
			break;
		case 'd':	// toogle breakpoint enabled
			toggleBreakpoint(true);
			break;
		case VK_UP:
			scrollWindow(-1);
			scanFunctions();
			break;
		case VK_DOWN:
			scrollWindow(1);
			scanFunctions();
			break;
		case VK_NEXT:
			setCurAddress(manager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT));
			break;
		case VK_PRIOR:
			setCurAddress(windowStart,KeyDownAsync(VK_SHIFT));
			break;
		}
	} else {
		switch (wParam & 0xFFFF)
		{
		case VK_DOWN:
			setCurAddress(manager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
			break;
		case VK_UP:
			setCurAddress(manager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
			scrollAddressIntoView();
			break;
		case VK_NEXT:
			if (manager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) {
				setCurAddress(manager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT));
				scrollAddressIntoView();
			} else {
				setCurAddress(manager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT));
				scrollAddressIntoView();
			}
			break;
		case VK_PRIOR:
			if (curAddress != windowStart && curAddressIsVisible()) {
				setCurAddress(windowStart, KeyDownAsync(VK_SHIFT));
				scrollAddressIntoView();
			} else {
				setCurAddress(manager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT));
				scrollAddressIntoView();
			}
			break;
		case VK_LEFT:
			if (jumpStack.empty())
			{
				gotoPC();
			} else {
				u32 addr = jumpStack[jumpStack.size()-1];
				jumpStack.pop_back();
				gotoAddr(addr);
			}
			return;
		case VK_RIGHT:
			followBranch();
			return;
		case VK_TAB:
			displaySymbols = !displaySymbols;
			break;
		case VK_SPACE:
			debugger->toggleBreakpoint(curAddress);
			break;
		case VK_F3:
			search(true);
			break;
		default:
			keyTaken = false;
			return;
		}
	}
	redraw();
}
Beispiel #11
0
void CtrlDisAsmView::search(bool continueSearch)
{
	u32 searchAddress;

	if (continueSearch == false || searchQuery[0] == 0)
	{
		if (InputBox_GetString(MainWindow::GetHInstance(),MainWindow::GetHWND(),L"Search for:","",searchQuery) == false
			|| searchQuery[0] == 0)
		{
			SetFocus(wnd);
			return;
		}

		for (size_t i = 0; i < searchQuery.size(); i++)
		{
			searchQuery[i] = tolower(searchQuery[i]);
		}
		SetFocus(wnd);
		searchAddress = manager.getNthNextAddress(curAddress,1);
	} else {
		searchAddress = manager.getNthNextAddress(matchAddress,1);
	}

	// limit address to sensible ranges
	if (searchAddress < 0x04000000) searchAddress = 0x04000000;
	if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
	if (searchAddress >= 0x0A000000) {	
		MessageBox(wnd,L"Not found",L"Search",MB_OK);
		return;
	}

	searching = true;
	redraw();	// so the cursor is disabled

	DisassemblyLineInfo lineInfo;
	while (searchAddress < 0x0A000000)
	{
		manager.getLine(searchAddress,displaySymbols,lineInfo);

		char addressText[64];
		getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE);

		const char* opcode = lineInfo.name.c_str();
		const char* arguments = lineInfo.params.c_str();

		char merged[512];
		int mergePos = 0;

		// I'm doing it manually to convert everything to lowercase at the same time
		for (int i = 0; addressText[i] != 0; i++) merged[mergePos++] = tolower(addressText[i]);
		merged[mergePos++] = ' ';
		for (int i = 0; opcode[i] != 0; i++) merged[mergePos++] = tolower(opcode[i]);
		merged[mergePos++] = ' ';
		for (int i = 0; arguments[i] != 0; i++) merged[mergePos++] = tolower(arguments[i]);
		merged[mergePos] = 0;

		// match!
		if (strstr(merged, searchQuery.c_str()) != NULL)
		{
			matchAddress = searchAddress;
			searching = false;
			gotoAddr(searchAddress);
			return;
		}

		// cancel search
		if ((searchAddress % 256) == 0 && KeyDownAsync(VK_ESCAPE))
		{
			searching = false;
			return;
		}

		searchAddress = manager.getNthNextAddress(searchAddress,1);
		if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
	}
	
	MessageBox(wnd,L"Not found",L"Search",MB_OK);
	searching = false;
}
Beispiel #12
0
uint8_t readAddrBank(int32_t addr, uint8_t bank){
	gotoBank(bank); 
	gotoAddr(addr,0);
	return readData();
}
Beispiel #13
0
uint8_t readAddr(int32_t addr, int isLowROM){
	gotoAddr(addr,isLowROM); 
	return readData();	
}
Beispiel #14
0
void CtrlMemView::search(bool continueSearch)
{
	u32 searchAddress;
	if (continueSearch == false || searchQuery[0] == 0)
	{
		if (InputBox_GetString(GetModuleHandle(NULL),wnd,L"Search for", "",searchQuery) == false)
		{
			SetFocus(wnd);
			return;
		}
		SetFocus(wnd);
		searchAddress = curAddress+1;
	} else {
		searchAddress = matchAddress+1;
	}

	std::vector<u8> searchData;
	if (asciiSelected)
	{
		for (size_t i = 0; i < searchQuery.length(); i++)
		{
			char c = searchQuery[i];
			searchData.push_back(c);
		}
	} else {
		size_t index = 0;
		while (index < searchQuery.size())
		{
			if (searchQuery[index] == ' ' || searchQuery[index] == '\t')
			{
				index++;
				continue;
			}

			u8 value = 0;
			for (int i = 0; i < 2; i++)
			{
				char c = tolower(searchQuery[index++]);
				if (c >= 'a' && c <= 'f')
				{
					value |= (c-'a'+10) << (1-i)*4;
				} else  if (c >= '0' && c <= '9')
				{
					value |= (c-'0') << (1-i)*4;
				} else {
					MessageBox(wnd,L"Invalid search text.",L"Error",MB_OK);
					return;
				}
			}

			searchData.push_back(value);
		}
	}

	std::vector<std::pair<u32,u32>> memoryAreas;
	memoryAreas.push_back(std::pair<u32,u32>(0x04000000,0x04200000));
	memoryAreas.push_back(std::pair<u32,u32>(0x08000000,0x0A000000));
	
	searching = true;
	redraw();	// so the cursor is disabled
	for (size_t i = 0; i < memoryAreas.size(); i++)
	{
		u32 segmentStart = memoryAreas[i].first;
		u32 segmentEnd = memoryAreas[i].second;
		u8* dataPointer = Memory::GetPointer(segmentStart);
		if (dataPointer == NULL) continue;		// better safe than sorry, I guess

		if (searchAddress < segmentStart) searchAddress = segmentStart;
		if (searchAddress >= segmentEnd) continue;

		int index = searchAddress-segmentStart;
		int endIndex = segmentEnd-segmentStart-(int)searchData.size();

		while (index < endIndex)
		{
			// cancel search
			if ((index % 256) == 0 && KeyDownAsync(VK_ESCAPE))
			{
				searching = false;
				return;
			}
		
			if (memcmp(&dataPointer[index],searchData.data(),searchData.size()) == 0)
			{
				matchAddress = index+segmentStart;
				searching = false;
				gotoAddr(matchAddress);
				return;
			}
			index++;
		}
	}

	MessageBox(wnd,L"Not found",L"Search",MB_OK);
	searching = false;
	redraw();
}
Beispiel #15
0
void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
{
	dontRedraw = false;
	u32 windowEnd = windowStart+visibleRows*instructionSize;
	keyTaken = true;

	if (controlHeld)
	{
		switch (tolower(wParam & 0xFFFF))
		{
		case 's':
			search(false);
			break;
		case 'c':
			search(true);
			break;
		case 'x':
			disassembleToFile();
			break;
		case 'a':
			controlHeld = false;
			assembleOpcode(curAddress,"");
			break;
		case 'g':
			{
				u32 addr;
				controlHeld = false;
				if (executeExpressionWindow(wnd,debugger,addr) == false) return;
				gotoAddr(addr);
			}
			break;
		}
	} else {
		switch (wParam & 0xFFFF)
		{
		case VK_DOWN:
			setCurAddress(curAddress + instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
			break;
		case VK_UP:
			setCurAddress(curAddress - instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
			scrollAddressIntoView();
			break;
		case VK_NEXT:
			if (curAddress != windowEnd - instructionSize && curAddressIsVisible()) {
				setCurAddress(windowEnd - instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
				scrollAddressIntoView();
			} else {
				setCurAddress(curAddress + visibleRows * instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
				scrollAddressIntoView();
			}
			break;
		case VK_PRIOR:
			if (curAddress != windowStart && curAddressIsVisible()) {
				setCurAddress(windowStart, GetAsyncKeyState(VK_SHIFT) != 0);
				scrollAddressIntoView();
			} else {
				setCurAddress(curAddress - visibleRows * instructionSize, GetAsyncKeyState(VK_SHIFT) != 0);
				scrollAddressIntoView();
			}
			break;
		case VK_LEFT:
			if (jumpStack.empty())
			{
				gotoPC();
			} else {
				u32 addr = jumpStack[jumpStack.size()-1];
				jumpStack.pop_back();
				gotoAddr(addr);
			}
			return;
		case VK_RIGHT:
			followBranch();
			return;
		case VK_TAB:
			displaySymbols = !displaySymbols;
			break;
		case VK_CONTROL:
			controlHeld = true;
			break;
		case VK_SPACE:
			debugger->toggleBreakpoint(curAddress);
			break;
		default:
			keyTaken = false;
			return;
		}
	}
	redraw();
}
Beispiel #16
0
void CtrlDisAsmView::search(bool continueSearch)
{
	u32 searchAddress;

	if (continueSearch == false || searchQuery[0] == 0)
	{
		if (InputBox_GetString(MainWindow::GetHInstance(),MainWindow::GetHWND(),L"Search for:","",searchQuery) == false
			|| searchQuery[0] == 0)
		{
			SetFocus(wnd);
			return;
		}

		for (int i = 0; searchQuery[i] != 0; i++)
		{
			searchQuery[i] = tolower(searchQuery[i]);
		}
		SetFocus(wnd);
		searchAddress = curAddress+instructionSize;
	} else {
		searchAddress = matchAddress+instructionSize;
	}

	// limit address to sensible ranges
	if (searchAddress < 0x04000000) searchAddress = 0x04000000;
	if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
	if (searchAddress >= 0x0A000000) {	
		MessageBox(wnd,L"Not found",L"Search",MB_OK);
		return;
	}

	searching = true;
	redraw();	// so the cursor is disabled
	while (searchAddress < 0x0A000000)
	{
		char addressText[64],opcode[64],arguments[256];
		const char *dis = debugger->disasm(searchAddress, instructionSize);
		parseDisasm(dis,opcode,arguments);
		getDisasmAddressText(searchAddress,addressText,true);

		char merged[512];
		int mergePos = 0;

		// I'm doing it manually to convert everything to lowercase at the same time
		for (int i = 0; addressText[i] != 0; i++) merged[mergePos++] = tolower(addressText[i]);
		merged[mergePos++] = ' ';
		for (int i = 0; opcode[i] != 0; i++) merged[mergePos++] = tolower(opcode[i]);
		merged[mergePos++] = ' ';
		for (int i = 0; arguments[i] != 0; i++) merged[mergePos++] = tolower(arguments[i]);
		merged[mergePos] = 0;

		// match!
		if (strstr(merged, searchQuery.c_str()) != NULL)
		{
			matchAddress = searchAddress;
			searching = false;
			gotoAddr(searchAddress);
			return;
		}

		// cancel search
		if ((searchAddress % 256) == 0 && GetAsyncKeyState(VK_ESCAPE))
		{
			searching = false;
			return;
		}

		searchAddress += instructionSize;
		if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
	}
	
	MessageBox(wnd,L"Not found",L"Search",MB_OK);
	searching = false;
}