def buttonAutoFindMethod(noeWnd, controlId, wParam, lParam): parsed, addr = broadcastFindRoomba(noeWnd) if addr: ipBox = noeWnd.getControlByIndex(noeWnd.roombaHostIndex) userBox = noeWnd.getControlByIndex(noeWnd.roombaUserIndex) passBox = noeWnd.getControlByIndex(noeWnd.roombaPassIndex) ipBox.setText(addr[0]) userName = parsed["hostname"].split("-")[1] userBox.setText(userName) getPass = (user32.MessageBoxW( noeWnd.hWnd, "Username was retrieved. In order to retrieve the password, you must turn the Roomba on, then press and hold the Home button until you hear a noise. Upon releasing the Home button, the Wi-fi light should be flashing. You may then continue. Are you ready to continue?", "Roomba Tracker", noewin.MB_YESNO) == noewin.IDYES) while getPass: password = getRoombaPassword(addr[0]) if password: passBox.setText(password) break getPass = (user32.MessageBoxW( noeWnd.hWnd, "The password could not be retrieved. Ensure that the unit is in the correct state, and that you held the Home button long enough to hear a noise, followed by the Wi-fi light flashing. Retry now?", "Roomba Tracker", noewin.MB_YESNO) == noewin.IDYES) saveWindowPrefs(noeWnd) else: noesis.messagePrompt("Failed to find any Roombas.")
def buttonClearSramMethod(noeWnd, controlId, wParam, lParam): verifyIt = (user32.MessageBoxW(noeWnd.hWnd, "This will clear the contents of SRAM, destroying any save data on the cart. Are you sure?", "F2A Interface", noewin.MB_YESNO) == noewin.IDYES) if verifyIt: clearSize = noesis.userPrompt(noesis.NOEUSERVAL_INT, "Clear Size", "Enter size of data to clear.", "262144", None) if clearSize: cmd = F2ACommand() cmd.command = F2A_CMD_WRITEDATA cmd.subCommand = F2A_SUBCMD_WRITE cmd.magic = F2A_MAGIC cmd.address = F2A_TARGET_SRAM cmd.dataSize = clearSize cmd.dataSizeKb = clearSize // 1024 noesis.usbWriteEndpointId(noeWnd.usbHandle, F2A_EP_WRITE, cmd.getBytes()) chunkedWrite(noeWnd.usbHandle, bytearray([0] * clearSize)) return True
def broadcastFindRoomba(noeWnd): try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(ROOMBA_BROADCAST_TIMEOUT) s.bind(("", ROOMBA_BROADCAST_PORT)) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.sendto(ROOMBA_BROADCAST_MSG.encode("UTF-8"), ("255.255.255.255", ROOMBA_BROADCAST_PORT)) foundParse = None foundAddr = None startTime = time.time() while (time.time() - startTime) < ROOMBA_BROADCAST_TIMEOUT: #noesis.pumpModalStatus("Searching for a Roomba...", 3.0) data, addr = s.recvfrom(ROOMBA_BROADCAST_MAX_SIZE) if data and len(data) > 10: #being lazy about the validation here. try: tryParse = json.loads(noeStrFromBytes(data, "UTF-8")) print("Received reply from Roomba:", tryParse, addr) useThisOne = (user32.MessageBoxW( noeWnd.hWnd, "Found a robot named " + tryParse["robotname"] + ". Use this one?", "Roomba Tracker", noewin.MB_YESNO) == noewin.IDYES) if useThisOne: foundParse = tryParse foundAddr = addr break except: pass time.sleep(0.1) #noesis.clearModalStatus() s.close() return foundParse, foundAddr except: return None, None
def neoPickWindowProc(hWnd, message, wParam, lParam): if message == noewin.WM_PAINT: noeWnd = noewin.getNoeWndForHWnd(hWnd) ps = noewin.PAINTSTRUCT() rect = noewin.RECT() hBlitDC = user32.BeginPaint(hWnd, byref(ps)) user32.GetClientRect(hWnd, byref(rect)) hDC = gdi32.CreateCompatibleDC(hBlitDC) bpp = gdi32.GetDeviceCaps(hBlitDC, 12) width = rect.right - rect.left height = rect.bottom - rect.top hBmp = gdi32.CreateBitmap(width, height, 1, bpp, 0) gdi32.SelectObject(hDC, hBmp) if noeWnd.hFont: gdi32.SelectObject(hDC, noeWnd.hFont) hBc = gdi32.CreateSolidBrush(noewin.RGB(255, 0, 0)) hBcHighlight = gdi32.CreateSolidBrush(noewin.RGB(255, 127, 0)) if noeWnd.neoDIB: bmi = noeWnd.neoBMI neo = noeWnd.neoObject gdi32.StretchDIBits( hDC, 0, 0, noeWnd.drawWidth, noeWnd.drawHeight, 0, 0, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight, cast(noeWnd.neoDIB, POINTER(c_ubyte * len(noeWnd.neoDIB))), byref(bmi), noewin.DIB_RGB_COLORS, noewin.SRCCOPY) blockOffset = neo.blockOffsetForPixelCoordinate( noeWnd.imgCoordX, noeWnd.imgCoordY) blockX, blockY = neo.pixelCoordinateForBlockOffset(blockOffset) absAddr = neo.dataOffset + blockOffset + neo.getBlockSize() toDrawWidth = noeWnd.drawWidth / neo.getWidth() toDrawHeight = noeWnd.drawHeight / neo.getHeight() drawX = min(max(int(blockX * toDrawWidth), 0), noeWnd.drawWidth - 1) drawY = min(max(int(blockY * toDrawHeight), 0), noeWnd.drawHeight - 1) if noeWnd.showClipped: gdi32.SelectObject(hDC, hBcHighlight) for hAddr in noeWnd.clipAddrs: hX, hY = neo.pixelCoordinateForBlockOffset( hAddr - neo.dataOffset - neo.getBlockSize()) dHX = min(max(int(hX * toDrawWidth), 0), noeWnd.drawWidth - 1) dHY = min(max(int(hY * toDrawHeight), 0), noeWnd.drawHeight - 1) gdi32.Rectangle( hDC, dHX, dHY, int(dHX + NEOCHROME_BLOCKWIDTH * toDrawWidth), int(dHY + 1 * toDrawHeight)) gdi32.SelectObject(hDC, hBc) gdi32.Rectangle(hDC, drawX, drawY, int(drawX + NEOCHROME_BLOCKWIDTH * toDrawWidth), int(drawY + 1 * toDrawHeight)) gdi32.SetTextColor(hDC, noewin.RGB(255, 127, 0)) gdi32.SetBkMode(hDC, noewin.TRANSPARENT) clippedText = "(clipped)" if absAddr in noeWnd.clipAddrs else "(unclipped)" noewin.user32.DrawTextW( hDC, "%i, %i / %i " % (blockX, blockY, blockOffset) + clippedText, -1, byref(rect), noewin.DT_SINGLELINE | noewin.DT_CENTER) gdi32.BitBlt(hBlitDC, 0, 0, width, height, hDC, 0, 0, 0x00CC0020) gdi32.DeleteDC(hDC) gdi32.DeleteObject(hBmp) gdi32.DeleteObject(hBc) gdi32.DeleteObject(hBcHighlight) user32.EndPaint(hWnd, byref(ps)) return 0 elif message == noewin.WM_ERASEBKGND: return 0 elif message == noewin.WM_MOUSEMOVE: noeWnd = noewin.getNoeWndForHWnd(hWnd) neo = noeWnd.neoObject x = noeUnpack("h", noePack("H", lParam & 0xFFFF))[0] y = noeUnpack("h", noePack("H", (lParam >> 16) & 0xFFFF))[0] noeWnd.imgCoordX = min( max(int((x / noeWnd.drawWidth) * neo.getWidth()), 0), neo.getWidth() - 1) noeWnd.imgCoordY = min( max(int((y / noeWnd.drawHeight) * neo.getHeight()), 0), neo.getHeight() - 1) user32.InvalidateRect(noeWnd.hWnd, 0, False) elif message == noewin.WM_LBUTTONUP: if (wParam & noewin.MK_CONTROL): noeWnd = noewin.getNoeWndForHWnd(hWnd) neo = noeWnd.neoObject blockSize = neo.getBlockSize() blockOffset = neo.blockOffsetForPixelCoordinate( noeWnd.imgCoordX, noeWnd.imgCoordY) absAddr = neo.dataOffset + blockOffset + blockSize if absAddr in noeWnd.clipAddrs: noeWnd.clipAddrs.remove(absAddr) else: noeWnd.clipAddrs.add(absAddr) bs = NoeBitStream(noeWnd.originalData) dst = NoeBitStream() while not bs.checkEOF(): if dst.tell() in noeWnd.clipAddrs: bs.readUByte() if (bs.getSize() - bs.tell()) < blockSize: break dst.writeBytes(bs.readBytes(blockSize)) neoPickAttachNeoToNoeWnd(noeWnd, dst.getBuffer()) user32.InvalidateRect(noeWnd.hWnd, 0, False) elif message == noewin.WM_RBUTTONUP: noeWnd = noewin.getNoeWndForHWnd(hWnd) wantWrite = True if os.path.exists(noeWnd.pickPath): wantWrite = (user32.MessageBoxW( hWnd, noeWnd.pickPath + " already exists. Do you want to overwrite it?", "NEOpicker", noewin.MB_YESNO) == noewin.IDYES) if wantWrite: with open(noeWnd.pickPath, "wb+") as f: f.write(noeWnd.neoData) user32.MessageBoxW(hWnd, "Saved to " + noeWnd.pickPath, "NEOpicker", noewin.MB_OK) elif message == noewin.WM_KEYDOWN: if wParam == noewin.VK_SHIFT: noeWnd = noewin.getNoeWndForHWnd(hWnd) noeWnd.showClipped = True user32.InvalidateRect(noeWnd.hWnd, 0, False) elif message == noewin.WM_KEYUP: if wParam == noewin.VK_SHIFT: noeWnd = noewin.getNoeWndForHWnd(hWnd) noeWnd.showClipped = False user32.InvalidateRect(noeWnd.hWnd, 0, False) return noewin.defaultWindowProc(hWnd, message, wParam, lParam)
def f2aToolMethod(toolIndex): noesis.logPopup() handle = noesis.usbOpenDevice(F2A_DEVINTGUID, F2A_CLASSGUID) riskIt = (user32.MessageBoxW( noesis.getWindowHandle(), "Found what appears to be the target F2A device. However, if this is not the correct device, the device could be damaged. Are you sure you want to continue?", "F2A Interface", noewin.MB_YESNO) == noewin.IDYES) if riskIt: if noesis.usbGetEndpointCount(handle) == 0: #try uploading the ez-usb firmware, then reconnect print( "Endpoint count is 0, attempting vendor-specific EZ-USB FW upload." ) #usbControlTransfer params = handle, data, requestType, request, index, value noesis.usbControlTransfer(handle, bytearray([0x01]), 0x40, 0xA0, 0, 0x7F92) fw = loadBin(F2A_EZUSBFW) chunkSize = 512 for offset in range(0, len(fw) // chunkSize): chunkData = fw[offset * chunkSize:offset * chunkSize + chunkSize] noesis.usbControlTransfer(handle, chunkData, 0x40, 0xA0, 0, offset * chunkSize) #upload complete noesis.usbControlTransfer(handle, bytearray([0x00]), 0x40, 0xA0, 0, 0x7F92) time.sleep(1) noesis.usbCloseDevice(handle) handle = None #spin here for a bit - uploading the firmware effectively reconnects the device with a different interface, #so it may take a little while for Windows to prepare it again. for attemptCount in range(0, F2A_RECONNECT_LIMIT): try: handle = noesis.usbOpenDevice(F2A_DEVINTGUID, F2A_CLASSGUID) print("Successfully re-opened device.") break except: print( "Cannot re-open device. Waiting before trying again.") time.sleep(3) if handle is None: noesis.messagePrompt( "Could not re-establish connection to device. Aborting.") elif noesis.usbGetEndpointCount(handle) != 5: noesis.messagePrompt( "The device does not have the expected number of endpoints. Aborting." ) else: noesis.usbSetEndpointTimeoutId(handle, F2A_EP_WRITE, F2A_EP_TIMEOUT) noesis.usbSetEndpointTimeoutId(handle, F2A_EP_READ, F2A_EP_TIMEOUT) response = getDeviceStatus(handle) while response[0] != F2A_STATUS_NOTREADY: tryAgain = (user32.MessageBoxW( noesis.getWindowHandle(), "Your GBA must be turned off to continue. Ready to try again?", "F2A Interface", noewin.MB_YESNO) == noewin.IDYES) if not tryAgain: break response = getDeviceStatus(handle) if response[0] == F2A_STATUS_NOTREADY: mb = loadBin(F2A_MULTIBOOT) bootCmd = F2ACommand() #if we don't do this bit, the linker gets angry again and stops accepting writes. particular to my hardware/firmware? bootCmd.fromBytes(response) bootCmd.command |= F2A_CMD_GETINF #keep the high bytes from the response data noesis.usbWriteEndpointId(handle, F2A_EP_WRITE, bootCmd.getBytes()) response = noesis.usbReadEndpointId(handle, F2A_EP_READ, F2A_RESPONSE_SIZE) noesis.usbSetEndpointTimeoutId(handle, F2A_EP_WRITE, F2A_EP_BOOTWAIT_TIMEOUT) readyToGo = (user32.MessageBoxW( noesis.getWindowHandle(), "After continuing (do not turn the GBA on before proceeding), you will connect your GBA, turn it on, and hold start+select during startup. Are you ready?", "F2A Interface", noewin.MB_YESNO) == noewin.IDYES) if readyToGo: #make sure they didn't turn it on prematurely response = getDeviceStatus(handle) if response[0] == F2A_STATUS_READY: readyToGo = False noesis.messagePrompt( "You turned the GBA on prematurely. Aborting.") if readyToGo: #spin until we detect the GBA is on, then take a run at it response = getDeviceStatus(handle) while response[0] != F2A_STATUS_READY: time.sleep(0.1) response = getDeviceStatus(handle) bootCmd.command = F2A_CMD_MULTIBOOT1 bootCmd.dataSize = 0 bootCmd.reserved0 &= ~255 noesis.usbWriteEndpointId(handle, F2A_EP_WRITE, bootCmd.getBytes()) bootCmd.command = F2A_CMD_MULTIBOOT2 bootCmd.dataSize = len( mb ) #my sniffing reveals this is actually 1024 bytes less than the data sent. writer bug? noesis.usbWriteEndpointId(handle, F2A_EP_WRITE, bootCmd.getBytes()) writeSize = chunkedWrite(handle, mb) print("MB write:", writeSize, "/", len(mb)) if writeSize != len(mb): noesis.messagePrompt( "Could not upload multiboot image. Aborting.") else: noesis.usbSetEndpointTimeoutId(handle, F2A_EP_WRITE, F2A_EP_TIMEOUT) #just write black to the background. sniffed out the original bg, or we could make our own, but eh. bgCmd = F2ACommand() bgCmd.magic = F2A_MAGIC bgCmd.address = F2A_TARGET_VRAM bgCmd.command = F2A_CMD_WRITEDATA bgCmd.subCommand = F2A_SUBCMD_WRITE bgCmd.dataSize = 76800 #packet sniffing shows this to be size & 0xFFFF, does it matter? (doesn't seem to) bgCmd.dataSizeKb = 76800 // 1024 noesis.usbWriteEndpointId(handle, F2A_EP_WRITE, bgCmd.getBytes()) bgUploadSize = 0 for offset in range(0, bgCmd.dataSizeKb): chunkSize = noesis.usbWriteEndpointId( handle, F2A_EP_WRITE, bytearray([0] * 1024)) if chunkSize < 0: break bgUploadSize += chunkSize print("BG write:", bgUploadSize) time.sleep(1) noeWnd = noewin.NoeUserWindow("F2A Interface", "F2AWindowClass", 644, 300) #offset a bit into the noesis window noeWindowRect = noewin.getNoesisWindowRect() if noeWindowRect: windowMargin = 64 noeWnd.x = noeWindowRect[0] + windowMargin noeWnd.y = noeWindowRect[1] + windowMargin if noeWnd.createWindow(): noeWnd.usbHandle = handle createInterfaceWindow(noeWnd) noeWnd.doModal() if handle: noesis.usbCloseDevice(handle) return 0