Skip to content

Commit

Permalink
rainbow: added UDP_ADDR_POOL_* commands
Browse files Browse the repository at this point in the history
- added UDP_ADDR_POOL_* commands
- updated command list
  • Loading branch information
BrokeStudio committed Jan 27, 2024
1 parent d291059 commit d161048
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 90 deletions.
16 changes: 8 additions & 8 deletions Core/NES/Mappers/Homebrew/Rainbow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -848,7 +849,7 @@ class Rainbow : public BaseMapper
return retval;
}

// MISC
// MISC
case 0x4160: return MAPPER_VERSION;

// IRQs
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
172 changes: 151 additions & 21 deletions Core/NES/Mappers/Homebrew/RainbowESP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -260,10 +266,10 @@ void BrokeStudioFirmware::processBufferedMessage()
this->tx_messages.push_back({ 19, static_cast<uint8_t>(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<uint8_t>(fromesp_cmds_t::ESP_FACTORY_RESET),static_cast<uint8_t>(esp_factory_reset::ERROR_WHILE_RESETTING_CONFIG) });
this->tx_messages.push_back({ 2,static_cast<uint8_t>(fromesp_cmds_t::ESP_FACTORY_RESET),static_cast<uint8_t>(esp_factory_reset::ERROR_WHILE_SAVING_CONFIG) });
break;

case toesp_cmds_t::ESP_RESTART:
Expand Down Expand Up @@ -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<server_protocol_t>(this->rx_buffer.at(2));
if(requested_protocol > server_protocol_t::UDP) {
UDBG("[Rainbow] SET_SERVER_PROTOCOL: unknown protocol (" + std::to_string(static_cast<unsigned int>(requested_protocol)) + ")");
if(requested_protocol > server_protocol_t::UDP_POOL) {
UDBG("[Rainbow] SERVER_SET_PROTOCOL: unknown protocol (" + std::to_string(static_cast<unsigned int>(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;
Expand Down Expand Up @@ -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<uint16_t>(this->rx_buffer.at(2)) << 8) +
(static_cast<uint16_t>(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<uint16_t>(this->rx_buffer.at(2)) << 8) +
(static_cast<uint16_t>(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<const uint8_t>(this->rx_buffer.size() - 2);
deque<uint8_t>::const_iterator payload_begin = this->rx_buffer.begin() + 2;
deque<uint8_t>::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:
Expand All @@ -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;
Expand Down Expand Up @@ -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<uint8_t>::size_type i = file_size; i < offset_end; ++i) {
Expand Down Expand Up @@ -1595,6 +1669,58 @@ void BrokeStudioFirmware::sendUdpDatagramToServer(I begin, I end)
}
}

template<class I>
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<uint8_t> 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<bool, sockaddr> 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<int>(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<size_t>(n) != message_size) {
UDBG("[Rainbow] UDP sent partial message");
}
}
}
}

template<class I>
void BrokeStudioFirmware::sendTcpDataToServer(I begin, I end)
{
Expand Down Expand Up @@ -1738,10 +1864,11 @@ void BrokeStudioFirmware::openConnection()

if(this->active_protocol == server_protocol_t::TCP) {
// Resolve server's hostname
std::pair<bool, sockaddr> server_addr = this->resolve_server_address();
if(!server_addr.first) {
std::pair<bool, sockaddr> 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);
Expand All @@ -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);
Expand All @@ -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<bool, sockaddr> 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<bool, sockaddr> 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) {
Expand Down Expand Up @@ -1868,7 +1998,7 @@ void BrokeStudioFirmware::receivePingResult()
}
*/

std::pair<bool, sockaddr> BrokeStudioFirmware::resolve_server_address()
std::pair<bool, sockaddr> BrokeStudioFirmware::resolve_address(string address, uint16_t port)
{
// Resolve IP address for hostname
bool result = false;
Expand All @@ -1879,8 +2009,8 @@ std::pair<bool, sockaddr> 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;
Expand Down
Loading

0 comments on commit d161048

Please sign in to comment.