From d1610485f50e12f2380e8dcb8189e3b5fd0aca14 Mon Sep 17 00:00:00 2001 From: BrokeStudio Date: Sat, 27 Jan 2024 15:11:43 +0100 Subject: [PATCH] rainbow: added UDP_ADDR_POOL_* commands - added UDP_ADDR_POOL_* commands - updated command list --- Core/NES/Mappers/Homebrew/Rainbow.h | 16 +-- Core/NES/Mappers/Homebrew/RainbowESP.cpp | 172 ++++++++++++++++++++--- Core/NES/Mappers/Homebrew/RainbowESP.h | 139 ++++++++++-------- 3 files changed, 237 insertions(+), 90 deletions(-) diff --git a/Core/NES/Mappers/Homebrew/Rainbow.h b/Core/NES/Mappers/Homebrew/Rainbow.h index 0d5e65df4..f2ec0cf77 100644 --- a/Core/NES/Mappers/Homebrew/Rainbow.h +++ b/Core/NES/Mappers/Homebrew/Rainbow.h @@ -11,9 +11,9 @@ #include "Utilities/Patches/IpsPatcher.h" #include "Utilities/Serializer.h" -// mapper 682 - Rainbow2 board v1.0 revA and v1.1 by Broke Studio +// mapper 682 - Rainbow board by Broke Studio // -// documentation available here: https://github.com/BrokeStudio/rainbow-lib +// documentation available here: https://github.com/BrokeStudio/rainbow-net #define MAPPER_PLATFORM_PCB 0 #define MAPPER_PLATFORM_EMU 1 @@ -823,7 +823,8 @@ class Rainbow : public BaseMapper if(addr >= 0x4100 && addr <= 0x47FF) { // MAPPER REGISTERS switch(addr) { - // PRG + + // PRG case 0x4100: return (_prgRamMode << 6) | _prgRomMode; // CHR @@ -848,7 +849,7 @@ class Rainbow : public BaseMapper return retval; } - // MISC + // MISC case 0x4160: return MAPPER_VERSION; // IRQs @@ -1143,10 +1144,9 @@ class Rainbow : public BaseMapper case 0x415D: _fpgaRamAutoRwAddress = (_fpgaRamAutoRwAddress & 0xff00) | (value); break; case 0x415E: _fpgaRamAutoRwIncrement = value; break; case 0x415F: - { _fpgaRam[_fpgaRamAutoRwAddress] = value; _fpgaRamAutoRwAddress += _fpgaRamAutoRwIncrement; - } + break; // Window Mode case 0x4170: _windowXStartTile = value & 0x1f; break; @@ -1443,7 +1443,7 @@ class Rainbow : public BaseMapper } } else if(_windowInSplitRegion) { //Attributes - + // Fill-mode? if(_ntControl[4] & 0x20) return _fillModeAttribute | _fillModeAttribute << 2 | _fillModeAttribute << 4 | _fillModeAttribute << 6; @@ -1510,7 +1510,7 @@ class Rainbow : public BaseMapper case 2: { //PPU palette fetch - + // Fill-mode? if(_ntControl[(addr >> 10) & 0x03] & 0x20) return _fillModeAttribute | _fillModeAttribute << 2 | _fillModeAttribute << 4 | _fillModeAttribute << 6; diff --git a/Core/NES/Mappers/Homebrew/RainbowESP.cpp b/Core/NES/Mappers/Homebrew/RainbowESP.cpp index fed785460..cb1c9cc08 100644 --- a/Core/NES/Mappers/Homebrew/RainbowESP.cpp +++ b/Core/NES/Mappers/Homebrew/RainbowESP.cpp @@ -104,6 +104,12 @@ BrokeStudioFirmware::BrokeStudioFirmware() this->default_server_settings_port = this->server_settings_port; #endif + // Clear UDP address pool + for(size_t i = 0; i < 16; i++) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + } + // Init fake registered networks this->networks = { { {"EMULATOR_SSID", "EMULATOR_PASS", true}, @@ -260,10 +266,10 @@ void BrokeStudioFirmware::processBufferedMessage() this->tx_messages.push_back({ 19, static_cast(fromesp_cmds_t::ESP_FIRMWARE_VERSION), 17, 'E', 'M', 'U', 'L', 'A', 'T', 'O', 'R', '_', 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E' }); break; - case toesp_cmds_t::ESP_FACTORY_SETTINGS: + case toesp_cmds_t::ESP_FACTORY_RESET: UDBG("[Rainbow] ESP received command ESP_FACTORY_SETTINGS"); UDBG("[Rainbow] ESP_FACTORY_SETTINGS has no use here"); - this->tx_messages.push_back({ 2,static_cast(fromesp_cmds_t::ESP_FACTORY_RESET),static_cast(esp_factory_reset::ERROR_WHILE_RESETTING_CONFIG) }); + this->tx_messages.push_back({ 2,static_cast(fromesp_cmds_t::ESP_FACTORY_RESET),static_cast(esp_factory_reset::ERROR_WHILE_SAVING_CONFIG) }); break; case toesp_cmds_t::ESP_RESTART: @@ -429,11 +435,11 @@ void BrokeStudioFirmware::processBufferedMessage() UDBG("[Rainbow] ESP received command SERVER_SET_PROTOCOL"); if(message_size == 2) { server_protocol_t requested_protocol = static_cast(this->rx_buffer.at(2)); - if(requested_protocol > server_protocol_t::UDP) { - UDBG("[Rainbow] SET_SERVER_PROTOCOL: unknown protocol (" + std::to_string(static_cast(requested_protocol)) + ")"); + if(requested_protocol > server_protocol_t::UDP_POOL) { + UDBG("[Rainbow] SERVER_SET_PROTOCOL: unknown protocol (" + std::to_string(static_cast(requested_protocol)) + ")"); } else { if(requested_protocol == server_protocol_t::TCP_SECURED) { - UDBG("[Rainbow] SET_SERVER_PROTOCOL: protocol TCP_SECURED not supported, falling back to TCP"); + UDBG("[Rainbow] SERVER_SET_PROTOCOL: protocol TCP_SECURED not supported, falling back to TCP"); requested_protocol = server_protocol_t::TCP; } this->active_protocol = requested_protocol; @@ -546,6 +552,74 @@ void BrokeStudioFirmware::processBufferedMessage() break; } + // UDP ADDRESS POOL CMDS + + case toesp_cmds_t::UDP_ADDR_POOL_CLEAR: + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_CLEAR"); + for(size_t i = 0; i < 16; i++) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + } + break; + + case toesp_cmds_t::UDP_ADDR_POOL_ADD: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_ADD"); + int port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + if(len >= 16) break; + string ipAddress = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == ipAddress && this->ipAddressPool[i].port == port) + break; + } + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == "") { + this->ipAddressPool[i].ipAddress = ipAddress; + this->ipAddressPool[i].port = port; + break; + } + } + + break; + } + + case toesp_cmds_t::UDP_ADDR_POOL_REMOVE: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_REMOVE"); + int port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + if(len >= 16) break; + string ipAddress = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == ipAddress && this->ipAddressPool[i].port == port) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + break; + } + } + break; + } + + case toesp_cmds_t::UDP_ADDR_POOL_SEND_MSG: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_SEND_MSG"); + if(this->active_protocol == server_protocol_t::UDP_POOL) { + uint8_t const payload_size = static_cast(this->rx_buffer.size() - 2); + deque::const_iterator payload_begin = this->rx_buffer.begin() + 2; + deque::const_iterator payload_end = payload_begin + payload_size; + this->sendUdpDatagramToPool(payload_begin, payload_end); + } + break; + } + // NETWORK CMDS // network commands are not relevant here, so we'll just use test/fake data case toesp_cmds_t::NETWORK_SCAN: @@ -566,8 +640,8 @@ void BrokeStudioFirmware::processBufferedMessage() NUM_FAKE_NETWORKS }); break; - case toesp_cmds_t::NETWORK_GET_DETAILS: - UDBG("[Rainbow] ESP received command NETWORK_GET_DETAILS"); + case toesp_cmds_t::NETWORK_GET_SCANNED_DETAILS: + UDBG("[Rainbow] ESP received command NETWORK_GET_SCANNED_DETAILS"); if(message_size == 2) { uint8_t networkItem = this->rx_buffer.at(2); if(networkItem > NUM_FAKE_NETWORKS - 1) networkItem = NUM_FAKE_NETWORKS - 1; @@ -1320,7 +1394,7 @@ void BrokeStudioFirmware::appendFile(I data_begin, I data_end) auto const data_size = data_end - data_begin; size_t file_size = this->working_file.file->data.size(); - uint32_t const offset_end = file_size + data_size; + size_t const offset_end = file_size + data_size; this->working_file.file->data.resize(offset_end, 0); for(vector::size_type i = file_size; i < offset_end; ++i) { @@ -1595,6 +1669,58 @@ void BrokeStudioFirmware::sendUdpDatagramToServer(I begin, I end) } } +template +void BrokeStudioFirmware::sendUdpDatagramToPool(I begin, I end) +{ +#if RAINBOW_DEBUG_ESP >= 1 + UDBG("[Rainbow] " + std::to_string(wall_clock_milli()) + " udp datagram to send"); +# if RAINBOW_DEBUG_ESP >= 2 + string dbgMessage = "[Rainbow] UDP data: "; + for(I cur = begin; cur < end; ++cur) { + dbgMessage += HexUtilities::ToHex(*cur) + " "; + } + UDBG(dbgMessage); +# endif +#endif + + if(this->udp_socket == -1) return; + + size_t message_size = end - begin; + vector aggregated; + aggregated.reserve(message_size); + aggregated.insert(aggregated.end(), begin, end); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress != "") { + + // Init UDP socket and store parsed address + std::pair res_dest_addr = this->resolve_address(this->ipAddressPool[i].ipAddress, this->ipAddressPool[i].port); + if(!res_dest_addr.first) { + continue; + } + + sockaddr dest_addr = res_dest_addr.second; + + ssize_t n = sendto( + this->udp_socket, cast_network_payload(aggregated.data()), static_cast(aggregated.size()), 0, + &dest_addr, sizeof(sockaddr) + ); + + if(n == -1) { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] UDP send failed: " + string(errmsg)); +#else + UDBG("[Rainbow] UDP send failed: " + string(strerror(errno))); +#endif + } else if(static_cast(n) != message_size) { + UDBG("[Rainbow] UDP sent partial message"); + } + } + } +} + template void BrokeStudioFirmware::sendTcpDataToServer(I begin, I end) { @@ -1738,10 +1864,11 @@ void BrokeStudioFirmware::openConnection() if(this->active_protocol == server_protocol_t::TCP) { // Resolve server's hostname - std::pair server_addr = this->resolve_server_address(); - if(!server_addr.first) { + std::pair res_server_addr = this->resolve_address(this->server_settings_address, this->server_settings_port); + if(!res_server_addr.first) { return; } + this->server_addr = res_server_addr.second; // Create socket this->tcp_socket = socket(AF_INET, SOCK_STREAM, 0); @@ -1755,7 +1882,7 @@ void BrokeStudioFirmware::openConnection() } // Connect to server - int connect_res = connect(this->tcp_socket, &server_addr.second, sizeof(sockaddr)); + int connect_res = connect(this->tcp_socket, &this->server_addr, sizeof(sockaddr)); if(connect_res == -1) { #ifdef _WIN32 r = strerror_s(errmsg, ERR_MSG_SIZE, errno); @@ -1766,15 +1893,18 @@ void BrokeStudioFirmware::openConnection() #endif } } else if(this->active_protocol == server_protocol_t::TCP_SECURED) { - //TODO + // TODO UDBG("[Rainbow] TCP_SECURED not yet implemented"); - } else if(this->active_protocol == server_protocol_t::UDP) { - // Init UDP socket and store parsed address - std::pair server_addr = this->resolve_server_address(); - if(!server_addr.first) { - return; + } else if(this->active_protocol == server_protocol_t::UDP || this->active_protocol == server_protocol_t::UDP_POOL) { + + if(this->active_protocol == server_protocol_t::UDP) { + // Init UDP socket and store parsed address + std::pair res_server_addr = this->resolve_address(this->server_settings_address, this->server_settings_port); + if(!res_server_addr.first) { + return; + } + this->server_addr = res_server_addr.second; } - this->server_addr = server_addr.second; this->udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if(this->udp_socket == -1) { @@ -1868,7 +1998,7 @@ void BrokeStudioFirmware::receivePingResult() } */ -std::pair BrokeStudioFirmware::resolve_server_address() +std::pair BrokeStudioFirmware::resolve_address(string address, uint16_t port) { // Resolve IP address for hostname bool result = false; @@ -1879,8 +2009,8 @@ std::pair BrokeStudioFirmware::resolve_server_address() sockaddr sa; memset(&sa, 0, sizeof(sa)); - if(getaddrinfo(this->server_settings_address.c_str(), std::to_string(this->server_settings_port).c_str(), &hint, &addrInfo) != 0) { - UDBG("[Rainbow] Unable to resolve server's hostname (" + this->server_settings_address + ":" + std::to_string(this->server_settings_port) + ")"); + if(getaddrinfo(address.c_str(), std::to_string(port).c_str(), &hint, &addrInfo) != 0) { + UDBG("[Rainbow] Unable to resolve server's hostname (" + address + ":" + std::to_string(port) + ")"); } else { result = true; sa = *addrInfo->ai_addr; diff --git a/Core/NES/Mappers/Homebrew/RainbowESP.h b/Core/NES/Mappers/Homebrew/RainbowESP.h index c827bdfde..8dc4a8011 100644 --- a/Core/NES/Mappers/Homebrew/RainbowESP.h +++ b/Core/NES/Mappers/Homebrew/RainbowESP.h @@ -79,6 +79,12 @@ struct WorkingFile FileStruct* file; }; +struct UPDpoolAddress +{ + string ipAddress; + uint16_t port; +}; + class BrokeStudioFirmware { public: @@ -95,73 +101,79 @@ class BrokeStudioFirmware enum class toesp_cmds_t : uint8_t { // ESP CMDS - ESP_GET_STATUS, - DEBUG_GET_LEVEL, - DEBUG_SET_LEVEL, - DEBUG_LOG, - BUFFER_CLEAR_RX_TX, - BUFFER_DROP_FROM_ESP, - ESP_GET_FIRMWARE_VERSION, - ESP_FACTORY_SETTINGS, - ESP_RESTART, + ESP_GET_STATUS = 0, // 0x00 + DEBUG_GET_LEVEL = 1, // 0x01 + DEBUG_SET_LEVEL = 2, // 0x02 + DEBUG_LOG = 3, // 0x03 + BUFFER_CLEAR_RX_TX = 4, // 0x04 + BUFFER_DROP_FROM_ESP = 5, // 0x05 + ESP_GET_FIRMWARE_VERSION = 6, // 0x06 + ESP_FACTORY_RESET = 7, // 0x07 + ESP_RESTART = 8, // 0x08 // WIFI CMDS - WIFI_GET_STATUS, - WIFI_GET_SSID, - WIFI_GET_IP, - WIFI_GET_CONFIG, - WIFI_SET_CONFIG, + WIFI_GET_STATUS = 9, // 0x09 + WIFI_GET_SSID = 10, // 0x0A + WIFI_GET_IP = 11, // 0x0B + WIFI_GET_CONFIG = 12, // 0x0C + WIFI_SET_CONFIG = 13, // 0x0D - // AP CMDS - AP_GET_SSID, - AP_GET_IP, + // ACCESS POINT CMDS + AP_GET_SSID = 14, // 0x0E + AP_GET_IP = 15, // 0x0F // RND CMDS - RND_GET_BYTE, - RND_GET_BYTE_RANGE, // ; min / max - RND_GET_WORD, - RND_GET_WORD_RANGE, // ; min / max + RND_GET_BYTE = 16, // 0x10 + RND_GET_BYTE_RANGE = 17, // 0x11 + RND_GET_WORD = 18, // 0x12 + RND_GET_WORD_RANGE = 19, // 0x13 // SERVER CMDS - SERVER_GET_STATUS, - SERVER_PING, - SERVER_SET_PROTOCOL, - SERVER_GET_SETTINGS, - SERVER_SET_SETTINGS, - SERVER_GET_SAVED_SETTINGS, - SERVER_SET_SAVED_SETTINGS, - SERVER_RESTORE_SAVED_SETTINGS, - SERVER_CONNECT, - SERVER_DISCONNECT, - SERVER_SEND_MSG, + SERVER_GET_STATUS = 20, // 0x14 + SERVER_PING = 21, // 0x15 + SERVER_SET_PROTOCOL = 22, // 0x16 + SERVER_GET_SETTINGS = 23, // 0x17 + SERVER_SET_SETTINGS = 24, // 0x18 + SERVER_GET_SAVED_SETTINGS = 25, // 0x19 + SERVER_SET_SAVED_SETTINGS = 26, // 0x1A + SERVER_RESTORE_SAVED_SETTINGS = 27, // 0x1B + SERVER_CONNECT = 28, // 0x1C + SERVER_DISCONNECT = 29, // 0x1D + SERVER_SEND_MSG = 30, // 0x1E + + // UDP ADDRESS POOL CMDS + UDP_ADDR_POOL_CLEAR = 55, // 0x37 + UDP_ADDR_POOL_ADD = 56, // 0x38 + UDP_ADDR_POOL_REMOVE = 57, // 0x39 + UDP_ADDR_POOL_SEND_MSG = 58, // 0x3A // NETWORK CMDS - NETWORK_SCAN, - NETWORK_GET_SCAN_RESULT, - NETWORK_GET_DETAILS, - NETWORK_GET_REGISTERED, - NETWORK_GET_REGISTERED_DETAILS, - NETWORK_REGISTER, - NETWORK_UNREGISTER, - NETWORK_SET_ACTIVE, + NETWORK_SCAN = 31, // 0x1F + NETWORK_GET_SCAN_RESULT = 32, // 0x20 + NETWORK_GET_SCANNED_DETAILS = 33, // 0x21 + NETWORK_GET_REGISTERED = 34, // 0x22 + NETWORK_GET_REGISTERED_DETAILS = 35, // 0x23 + NETWORK_REGISTER = 36, // 0x24 + NETWORK_UNREGISTER = 37, // 0x25 + NETWORK_SET_ACTIVE = 38, // 0x26 // FILE CMDS - FILE_OPEN, - FILE_CLOSE, - FILE_STATUS, - FILE_EXISTS, - FILE_DELETE, - FILE_SET_CUR, - FILE_READ, - FILE_WRITE, - FILE_APPEND, - FILE_COUNT, - FILE_GET_LIST, - FILE_GET_FREE_ID, - FILE_GET_FS_INFO, - FILE_GET_INFO, - FILE_DOWNLOAD, - FILE_FORMAT, + FILE_OPEN = 39, // 0x27 + FILE_CLOSE = 40, // 0x28 + FILE_STATUS = 41, // 0x29 + FILE_EXISTS = 42, // 0x2A + FILE_DELETE = 43, // 0x2B + FILE_SET_CUR = 44, // 0x2C + FILE_READ = 45, // 0x2D + FILE_WRITE = 46, // 0x2E + FILE_APPEND = 47, // 0x2F + FILE_COUNT = 48, // 0x30 + FILE_GET_LIST = 49, // 0x31 + FILE_GET_FREE_ID = 50, // 0x32 + FILE_GET_FS_INFO = 51, // 0x33 + FILE_GET_INFO = 52, // 0x34 + FILE_DOWNLOAD = 53, // 0x35 + FILE_FORMAT = 54, // 0x36 }; // Defined message types from ESP to CPU @@ -212,16 +224,17 @@ class BrokeStudioFirmware enum class esp_factory_reset : uint8_t { SUCCESS = 0, - ERROR_WHILE_RESETTING_CONFIG = 1, + ERROR_WHILE_SAVING_CONFIG = 1, ERROR_WHILE_DELETING_TWEB = 2, ERROR_WHILE_DELETING_WEB = 3 }; enum class server_protocol_t : uint8_t { - TCP, - TCP_SECURED, - UDP, + TCP = 0, + TCP_SECURED = 1, + UDP = 2, + UDP_POOL = 3, }; // WIFI_CONFIG @@ -295,6 +308,8 @@ class BrokeStudioFirmware template void sendUdpDatagramToServer(I begin, I end); template + void sendUdpDatagramToPool(I begin, I end); + template void sendTcpDataToServer(I begin, I end); void receiveDataFromServer(); @@ -304,7 +319,7 @@ class BrokeStudioFirmware //void pingRequest(uint8_t n); //void receivePingResult(); - pair resolve_server_address(); + pair resolve_address(string address, uint16_t port); static deque read_socket(int socket); void initDownload(); @@ -330,6 +345,8 @@ class BrokeStudioFirmware string server_settings_address; uint16_t server_settings_port = 0; + UPDpoolAddress ipAddressPool[16]; + uint8_t debug_config = 0; uint8_t wifi_config = 1;