diff --git a/cube/patches/Makefile b/cube/patches/Makefile index 570b8f0f..fe04cd62 100644 --- a/cube/patches/Makefile +++ b/cube/patches/Makefile @@ -9,13 +9,14 @@ DEST = ../swiss/source/patches DISASM = disassembly -all: dvdpatch hddpatch sdpatch usbpatch wkfpatch +all: dvdpatch hddpatch sdpatch usbpatch wkfpatch bbapatch dvdpatch: clean build-dvd hddpatch: clean build-ideexi-v1 clean build-ideexi-v2 sdpatch: clean build-sd usbpatch: clean build-usb wkfpatch: clean build-wkf +bbapatch: clean build-bba clean: @rm -rf *.o @@ -140,3 +141,19 @@ build-wkf: @mv -f wkf.s $(DEST)/wkfPatch.s @rm *.bin @rm *.elf + +build-bba: + @echo Building BBA Patch ... + @$(CC) -O1 -ffunction-sections -mmultiple -mstring -c usbgecko/base.S + @$(CC) -O1 -ffunction-sections -mmultiple -mstring -c bba/bba.c + @$(CC) -O1 -ffunction-sections -mmultiple -mstring -c bba/tcpip.c + @$(CC) -O1 -ffunction-sections -mmultiple -mstring -c base/usbgecko.c + @$(LD) -o bba.elf base.o bba.o tcpip.o usbgecko.o --section-start .text=0x80001000 --gc-sections + @rm -rf *.o + @$(OBJDUMP) -D bba.elf > $(DISASM)/bba_disasm.txt + @$(OBJCOPY) -O binary bba.elf bba.bin + @$(BIN2S) bba.bin > bba.s + @mv -f bba.s $(DEST)/BBAPatch.s + @rm *.bin + @rm *.elf + \ No newline at end of file diff --git a/cube/patches/bba/bba.c b/cube/patches/bba/bba.c new file mode 100644 index 00000000..31f42b95 --- /dev/null +++ b/cube/patches/bba/bba.c @@ -0,0 +1,354 @@ +/*************************************************************************** +* Network Read code for GC via Broadband Adapter +* Extrems 2017 +***************************************************************************/ + +#include +#include +#include "../../reservedarea.h" + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#define BBA_NCRA 0x00 /* Network Control Register A, RW */ +#define BBA_NCRA_RESET (1<<0) /* RESET */ +#define BBA_NCRA_ST0 (1<<1) /* ST0, Start transmit command/status */ +#define BBA_NCRA_ST1 (1<<2) /* ST1, " */ +#define BBA_NCRA_SR (1<<3) /* SR, Start Receive */ + +#define BBA_IR 0x09 /* Interrupt Register, RW, 00h */ +#define BBA_IR_FRAGI (1<<0) /* FRAGI, Fragment Counter Interrupt */ +#define BBA_IR_RI (1<<1) /* RI, Receive Interrupt */ +#define BBA_IR_TI (1<<2) /* TI, Transmit Interrupt */ +#define BBA_IR_REI (1<<3) /* REI, Receive Error Interrupt */ +#define BBA_IR_TEI (1<<4) /* TEI, Transmit Error Interrupt */ +#define BBA_IR_FIFOEI (1<<5) /* FIFOEI, FIFO Error Interrupt */ +#define BBA_IR_BUSEI (1<<6) /* BUSEI, BUS Error Interrupt */ +#define BBA_IR_RBFI (1<<7) /* RBFI, RX Buffer Full Interrupt */ + +#define BBA_RWP 0x16/*+0x17*/ /* Receive Buffer Write Page Pointer Register */ +#define BBA_RRP 0x18/*+0x19*/ /* Receive Buffer Read Page Pointer Register */ + +#define BBA_WRTXFIFOD 0x48/*-0x4b*/ /* Write TX FIFO Data Port Register */ + +#define BBA_RX_STATUS_BF (1<<0) +#define BBA_RX_STATUS_CRC (1<<1) +#define BBA_RX_STATUS_FAE (1<<2) +#define BBA_RX_STATUS_FO (1<<3) +#define BBA_RX_STATUS_RW (1<<4) +#define BBA_RX_STATUS_MF (1<<5) +#define BBA_RX_STATUS_RF (1<<6) +#define BBA_RX_STATUS_RERR (1<<7) + +#define BBA_INIT_TLBP 0x00 +#define BBA_INIT_BP 0x01 +#define BBA_INIT_RHBP 0x0f +#define BBA_INIT_RWP BBA_INIT_BP +#define BBA_INIT_RRP BBA_INIT_BP + +enum { + EXI_READ = 0, + EXI_WRITE, + EXI_READ_WRITE, +}; + +enum { + EXI_DEVICE_0 = 0, + EXI_DEVICE_1, + EXI_DEVICE_2, + EXI_DEVICE_MAX +}; + +enum { + EXI_SPEED_1MHZ = 0, + EXI_SPEED_2MHZ, + EXI_SPEED_4MHZ, + EXI_SPEED_8MHZ, + EXI_SPEED_16MHZ, + EXI_SPEED_32MHZ, +}; + +typedef struct { + uint32_t status : 8; + uint32_t length : 12; + uint32_t next : 12; + uint8_t data[]; +} __attribute((packed)) bba_header_t; + +void *memcpy(void *dest, const void *src, size_t size) +{ + char *d = dest; + const char *s = src; + + while (size--) + *d++ = *s++; + + return dest; +} + +static void exi_select(void) +{ + volatile unsigned long *exi = (void *)0xCC006800; + exi[0] = (exi[0] & 0x405) | ((1 << EXI_DEVICE_2) << 7) | (EXI_SPEED_32MHZ << 4); +} + +static void exi_deselect(void) +{ + volatile unsigned long *exi = (void *)0xCC006800; + exi[0] &= 0x405; +} + +static void exi_imm_write_le(unsigned long val, int len) +{ + volatile unsigned long *exi = (void *)0xCC006800; + exi[4] = __builtin_bswap32(val); + // Tell EXI if this is a read or a write + exi[3] = ((len - 1) << 4) | (EXI_WRITE << 2) | 1; + // Wait for it to do its thing + while (exi[3] & 1); +} + +static void exi_imm_write(unsigned long val, int len) +{ + volatile unsigned long *exi = (void *)0xCC006800; + exi[4] = val; + // Tell EXI if this is a read or a write + exi[3] = ((len - 1) << 4) | (EXI_WRITE << 2) | 1; + // Wait for it to do its thing + while (exi[3] & 1); +} + +static unsigned long exi_imm_read_le(int len) +{ + volatile unsigned long *exi = (void *)0xCC006800; + // Tell EXI if this is a read or a write + exi[3] = ((len - 1) << 4) | (EXI_READ << 2) | 1; + // Wait for it to do its thing + while (exi[3] & 1); + // Read the 4 byte data off the EXI bus + return __builtin_bswap32(exi[4]); +} + +static unsigned long exi_imm_read(int len) +{ + volatile unsigned long *exi = (void *)0xCC006800; + // Tell EXI if this is a read or a write + exi[3] = ((len - 1) << 4) | (EXI_READ << 2) | 1; + // Wait for it to do its thing + while (exi[3] & 1); + // Read the 4 byte data off the EXI bus + return exi[4]; +} + +static void exi_immex_write(void *buffer, int length) +{ + do { + int count = MIN(length, 4); + + exi_imm_write(*(uint32_t *)buffer, count); + + buffer += count; + length -= count; + } while (length); +} + +static void exi_immex_read(void *buffer, int length) +{ + do { + int count = MIN(length, 4); + + asm ( + "mtxer %2 \n" + "stswx %1, %y0 \n" + : "=Z" (*(uint32_t *)buffer) + : "r" (exi_imm_read(count)), "r" (count) + ); + + buffer += count; + length -= count; + } while (length); +} + +static uint32_t bba_in32(uint16_t reg) +{ + uint32_t val; + + exi_select(); + exi_imm_write(0x80 << 24 | reg << 8, 4); + val = exi_imm_read_le(4); + exi_deselect(); + + return val; +} + +static uint8_t bba_in8(uint16_t reg) +{ + uint8_t val; + + exi_select(); + exi_imm_write(0x80 << 24 | reg << 8, 4); + val = exi_imm_read_le(1); + exi_deselect(); + + return val; +} + +static void bba_out8(uint16_t reg, uint8_t val) +{ + exi_select(); + exi_imm_write(0xC0 << 24 | reg << 8, 4); + exi_imm_write_le(val, 1); + exi_deselect(); +} + +static uint8_t bba_cmd_in8(uint8_t reg) +{ + uint8_t val; + + exi_select(); + exi_imm_write_le(reg, 2); + val = exi_imm_read_le(1); + exi_deselect(); + + return val; +} + +static void bba_cmd_out8(uint8_t reg, uint8_t val) +{ + exi_select(); + exi_imm_write_le(reg | 0x40, 2); + exi_imm_write_le(val, 1); + exi_deselect(); +} + +static void bba_insregister(uint16_t reg) +{ + exi_imm_write(0x80 << 24 | reg << 8, 4); +} + +static void bba_outsregister(uint16_t reg) +{ + exi_imm_write(0xC0 << 24 | reg << 8, 4); +} + +static void bba_insdata(void *data, int size) +{ + exi_immex_read(data, size); +} + +static void bba_outsdata(void *data, int size) +{ + exi_immex_write(data, size); +} + +void bba_transmit(void *data, int size) +{ + while (bba_in8(BBA_NCRA) & (BBA_NCRA_ST0 | BBA_NCRA_ST1)); + + exi_select(); + bba_outsregister(BBA_WRTXFIFOD); + bba_outsdata(data, size); + exi_deselect(); + + bba_out8(BBA_NCRA, (bba_in8(BBA_NCRA) & ~BBA_NCRA_ST0) | BBA_NCRA_ST1); +} + +void fsp_output(const char *file, uint8_t filelen, uint32_t offset, uint32_t size); +void eth_input(void *eth, uint16_t size); + +static void bba_receive(void) +{ + uint8_t rwp = bba_in8(BBA_RWP); + uint8_t rrp = bba_in8(BBA_RRP); + + while (rrp != rwp) { + uint32_t val = bba_in32(rrp << 8); + bba_header_t *bba = (bba_header_t *)&val; + + if (bba->status & (BBA_RX_STATUS_RERR | BBA_RX_STATUS_FAE)) { + rwp = bba_in8(BBA_RWP); + rrp = bba_in8(BBA_RRP); + } else { + uint16_t size = bba->length - sizeof(*bba); + uint8_t data[size]; + + uint16_t pos = (rrp << 8) + sizeof(*bba); + uint16_t top = (BBA_INIT_RHBP + 1) << 8; + + exi_select(); + bba_insregister(pos); + + if (pos + size < top) { + bba_insdata(data, size); + } else { + int chunk = top - pos; + bba_insdata(data, chunk); + exi_deselect(); + + exi_select(); + bba_insregister(BBA_INIT_RRP << 8); + bba_insdata(data + chunk, size - chunk); + } + + exi_deselect(); + + bba_out8(BBA_RRP, rrp = bba->next); + eth_input((void *)data, size); + rwp = bba_in8(BBA_RWP); + } + } +} + +static void bba_interrupt(void) +{ + uint8_t ir = bba_in8(BBA_IR); + + while (ir) { + if (ir & BBA_IR_RI) + bba_receive(); + + bba_out8(BBA_IR, ir); + ir = bba_in8(BBA_IR); + } +} + +static void bba_poll(void) +{ + uint8_t status = bba_cmd_in8(0x03); + + while (status) { + if (status & 0x80) + bba_interrupt(); + + bba_cmd_out8(0x03, status); + status = bba_cmd_in8(0x03); + } +} + +extern void dcache_flush_icache_inv(void* dst, uint32_t len); + +void perform_read(void) +{ + volatile unsigned long *dvd = (void *)0xCC006000; + + uint32_t dest = dvd[5] | 0x80000000; + uint32_t size = dvd[4]; + uint32_t offset = dvd[3] << 2; + + *(uint32_t *)VAR_TMP1 = dest; + *(uint32_t *)VAR_TMP2 = size; + + fsp_output((const char *)VAR_FILENAME, *(uint8_t *)VAR_FILENAME_LEN, offset, size); + + while (*(uint32_t *)VAR_TMP2) + bba_poll(); + + dcache_flush_icache_inv((void*)dest, size); + dvd[2] = 0xE0000000; + dvd[3] = 0; + dvd[4] = 0; + dvd[5] = 0; + dvd[6] = 0; + dvd[8] = 0; + dvd[7] = 1; +} diff --git a/cube/patches/bba/tcpip.c b/cube/patches/bba/tcpip.c new file mode 100644 index 00000000..38f3b5a6 --- /dev/null +++ b/cube/patches/bba/tcpip.c @@ -0,0 +1,327 @@ +/*************************************************************************** +* Network Read code for GC via Broadband Adapter +* Extrems 2017 +***************************************************************************/ + +#include +#include +#include +#include "../../reservedarea.h" + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#define MIN_FRAME_SIZE 60 + +#define ETH_TYPE_IPV4 0x0800 +#define ETH_TYPE_ARP 0x0806 +#define ETH_TYPE_VLAN 0x8100 + +#define HW_ETHERNET 1 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_UDP 17 + +enum { + ARP_REQUEST = 1, + ARP_REPLY, +}; + +enum { + CC_VERSION = 0x10, + CC_ERR = 0x40, + CC_GET_DIR, + CC_GET_FILE, +}; + +struct eth_addr { + uint64_t addr : 48; +} __attribute((packed)); + +struct ipv4_addr { + uint32_t addr; +} __attribute((packed)); + +typedef struct { + struct eth_addr dst_addr; + struct eth_addr src_addr; + uint16_t type; + uint8_t data[]; +} __attribute((packed)) eth_header_t; + +typedef struct { + uint16_t pcp : 3; + uint16_t dei : 1; + uint16_t vid : 12; + uint16_t type; + uint8_t data[]; +} __attribute((packed)) vlan_header_t; + +typedef struct { + uint16_t hardware_type; + uint16_t protocol_type; + uint8_t hardware_length; + uint8_t protocol_length; + uint16_t operation; + + struct eth_addr src_mac; + struct ipv4_addr src_ip; + struct eth_addr dst_mac; + struct ipv4_addr dst_ip; +} __attribute((packed)) arp_packet_t; + +typedef struct { + uint8_t version : 4; + uint8_t words : 4; + uint8_t dscp : 6; + uint8_t ecn : 2; + uint16_t length; + uint16_t id; + uint16_t flags : 3; + uint16_t offset : 13; + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + struct ipv4_addr src_addr; + struct ipv4_addr dst_addr; + uint8_t data[]; +} __attribute((packed)) ipv4_header_t; + +typedef struct { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; + uint8_t data[]; +} __attribute((packed)) udp_header_t; + +typedef struct { + uint8_t command; + uint8_t checksum; + uint16_t key; + uint16_t sequence; + uint16_t data_length; + uint32_t position; + uint8_t data[]; +} __attribute((packed)) fsp_header_t; + +static uint16_t ipv4_checksum(ipv4_header_t *header) +{ + uint16_t *data = (uint16_t *)header; + uint32_t sum[2] = {0}; + + for (int i = 0; i < header->words; i++) { + sum[0] += *data++; + sum[1] += *data++; + } + + sum[0] += sum[1]; + sum[0] += sum[0] >> 16; + return ~sum[0]; +} + +static uint8_t fsp_checksum(fsp_header_t *header, uint16_t size) +{ + uint8_t *data = (uint8_t *)header; + uint32_t sum = size; + + for (int i = 0; i < size; i++) + sum += *data++; + + sum += sum >> 8; + return sum; +} + +void bba_transmit(void *buffer, int size); + +void fsp_output(const char *file, uint8_t filelen, uint32_t offset, uint32_t size) +{ + uint8_t data[MIN_FRAME_SIZE + filelen]; + eth_header_t *eth = (eth_header_t *)data; + ipv4_header_t *ipv4 = (ipv4_header_t *)eth->data; + udp_header_t *udp = (udp_header_t *)ipv4->data; + fsp_header_t *fsp = (fsp_header_t *)udp->data; + + fsp->command = CC_GET_FILE; + fsp->checksum = 0x00; + fsp->key = *(uint16_t *)VAR_FSP_KEY; + fsp->sequence = 0; + fsp->data_length = filelen; + fsp->position = offset; + *(uint16_t *)(memcpy(fsp->data, file, filelen) + fsp->data_length) = MIN(size, UINT16_MAX); + fsp->checksum = fsp_checksum(fsp, sizeof(*fsp) + fsp->data_length + sizeof(uint16_t)); + + udp->src_port = 21; + udp->dst_port = 21; + udp->length = sizeof(*udp) + sizeof(*fsp) + fsp->data_length + sizeof(uint16_t); + udp->checksum = 0x0000; + + ipv4->version = 4; + ipv4->words = sizeof(*ipv4) / 4; + ipv4->dscp = 46; + ipv4->ecn = 0b00; + ipv4->length = sizeof(*ipv4) + udp->length; + ipv4->id = 0; + ipv4->flags = 0b000; + ipv4->offset = 0; + ipv4->ttl = 64; + ipv4->protocol = IP_PROTO_UDP; + ipv4->checksum = 0x0000; + ipv4->src_addr.addr = (*(struct ipv4_addr *)VAR_CLIENT_IP).addr; + ipv4->dst_addr.addr = (*(struct ipv4_addr *)VAR_SERVER_IP).addr; + ipv4->checksum = ipv4_checksum(ipv4); + + eth->dst_addr.addr = (*(struct eth_addr *)VAR_SERVER_MAC).addr; + eth->src_addr.addr = (*(struct eth_addr *)VAR_CLIENT_MAC).addr; + eth->type = ETH_TYPE_IPV4; + + bba_transmit(eth, sizeof(*eth) + ipv4->length); +} + +static void fsp_input(eth_header_t *eth, ipv4_header_t *ipv4, udp_header_t *udp, fsp_header_t *fsp, uint16_t size) +{ + if (size < sizeof(*fsp)) + return; + if (udp->length < sizeof(*udp) + sizeof(*fsp) + fsp->data_length) + return; + + size -= sizeof(*fsp); + + switch (fsp->command) { + case CC_ERR: + break; + case CC_GET_FILE: + *(uint16_t *)VAR_IPV4_ID = ipv4->id; + *(uint32_t *)VAR_FSP_POSITION = fsp->position; + *(uint16_t *)VAR_FSP_DATA_LENGTH = fsp->data_length; + break; + } + + *(uint16_t *)VAR_FSP_KEY = fsp->key; +} + +static void udp_input(eth_header_t *eth, ipv4_header_t *ipv4, udp_header_t *udp, uint16_t size) +{ + if (ipv4->src_addr.addr == (*(struct ipv4_addr *)VAR_SERVER_IP).addr && + ipv4->dst_addr.addr == (*(struct ipv4_addr *)VAR_CLIENT_IP).addr) { + + (*(struct eth_addr *)VAR_SERVER_MAC).addr = eth->src_addr.addr; + + if (ipv4->offset == 0) { + if (size < sizeof(*udp)) + return; + if (udp->length < sizeof(*udp)) + return; + + size -= sizeof(*udp); + + if (udp->src_port == 21 && + udp->dst_port == 21) + fsp_input(eth, ipv4, udp, (void *)udp->data, size); + } + + if (ipv4->id == *(uint16_t *)VAR_IPV4_ID) { + uint32_t position = *(uint32_t *)VAR_FSP_POSITION; + uint16_t data_length = *(uint16_t *)VAR_FSP_DATA_LENGTH; + + if (position != EOF) { + uint32_t data = *(uint32_t *)VAR_TMP1; + uint32_t left = *(uint32_t *)VAR_TMP2; + + int offset = ipv4->offset * 8 - sizeof(udp_header_t) - sizeof(fsp_header_t); + int ipv4_offset = MIN(offset, 0); + int data_offset = MAX(offset, 0); + + memcpy((void *)data + data_offset, ipv4->data - ipv4_offset, MIN(data_length - data_offset, size)); + + if (!(ipv4->flags & 0b001)) { + data += data_length; + left -= data_length; + + *(uint32_t *)VAR_TMP1 = data; + *(uint32_t *)VAR_TMP2 = left; + + if (left) fsp_output((const char *)VAR_FILENAME, *(uint8_t *)VAR_FILENAME_LEN, position + data_length, left); + + *(uint32_t *)VAR_FSP_POSITION = EOF; + *(uint16_t *)VAR_FSP_DATA_LENGTH = 0; + } + } + } + } +} + +static void ipv4_input(eth_header_t *eth, ipv4_header_t *ipv4, uint16_t size) +{ + if (ipv4->version != 4) + return; + if (ipv4->words < 5 || ipv4->words * 4 > ipv4->length) + return; + if (size < ipv4->length) + return; + if (ipv4_checksum(ipv4)) + return; + + size = ipv4->length - ipv4->words * 4; + + switch (ipv4->protocol) { + case IP_PROTO_UDP: + udp_input(eth, ipv4, (void *)ipv4->data, size); + break; + } +} + +static void arp_input(eth_header_t *eth, arp_packet_t *arp, uint16_t size) +{ + if (arp->hardware_type != HW_ETHERNET || arp->hardware_length != sizeof(struct eth_addr)) + return; + if (arp->protocol_type != ETH_TYPE_IPV4 || arp->protocol_length != sizeof(struct ipv4_addr)) + return; + + switch (arp->operation) { + case ARP_REQUEST: + if ((!arp->dst_mac.addr || + arp->dst_mac.addr == (*(struct eth_addr *)VAR_CLIENT_MAC).addr) && + arp->dst_ip.addr == (*(struct ipv4_addr *)VAR_CLIENT_IP).addr) { + + arp->operation = ARP_REPLY; + + arp->dst_mac.addr = arp->src_mac.addr; + arp->dst_ip.addr = arp->src_ip.addr; + + arp->src_mac.addr = (*(struct eth_addr *)VAR_CLIENT_MAC).addr; + arp->src_ip.addr = (*(struct ipv4_addr *)VAR_CLIENT_IP).addr; + + eth->dst_addr.addr = arp->dst_mac.addr; + eth->src_addr.addr = arp->src_mac.addr; + + bba_transmit(eth, MIN_FRAME_SIZE); + } + break; + case ARP_REPLY: + if (arp->dst_mac.addr == (*(struct eth_addr *)VAR_CLIENT_MAC).addr && + arp->dst_ip.addr == (*(struct ipv4_addr *)VAR_CLIENT_IP).addr && + arp->src_ip.addr == (*(struct ipv4_addr *)VAR_SERVER_IP).addr) { + + (*(struct eth_addr *)VAR_SERVER_MAC).addr = arp->src_mac.addr; + } + break; + } +} + +void eth_input(eth_header_t *eth, uint16_t size) +{ + if (size < MIN_FRAME_SIZE) + return; + + size -= sizeof(*eth); + + switch (eth->type) { + case ETH_TYPE_ARP: + arp_input(eth, (void *)eth->data, size); + break; + case ETH_TYPE_IPV4: + ipv4_input(eth, (void *)eth->data, size); + break; + } +} diff --git a/cube/reservedarea.h b/cube/reservedarea.h index ab07da3b..032e2b4e 100644 --- a/cube/reservedarea.h +++ b/cube/reservedarea.h @@ -11,6 +11,12 @@ #ifdef _LANGUAGE_ASSEMBLY #include "asm.h" .set VAR_AREA, 0x8000 +.set VAR_FILENAME_LEN, 0x0E00 # filename length +.set VAR_FILENAME, 0x0E01 # filename +.set VAR_CLIENT_MAC, 0x0EEC # client MAC address +.set VAR_CLIENT_IP, 0x0EF2 # client IPv4 address +.set VAR_SERVER_MAC, 0x0EF6 # server MAC address +.set VAR_SERVER_IP, 0x0EFC # server IPv4 address .set VAR_PATCHES_BASE, 0x2D00 # Patches get copied to below this area. .set VAR_FRAG_SIZE, 0x1C8 # Size of frag array in bytes .set VAR_FRAG_LIST, 0x2D00 # 0x1C8 of fragments (38 frags max) (u32 offset, u32 size, u32 rawsector) @@ -18,7 +24,10 @@ .set VAR_DISC_CHANGING, 0x2ED0 # Are we changing discs? .set VAR_CURRENT_FIELD, 0x2ED4 # current video field .set VAR_IGR_EXIT_TYPE, 0x2ED5 # IGR exit type -.set VAR_SPARE, 0x2ED6 ########## SPARE until 0x2EE0 +.set VAR_IPV4_ID, 0x2ED6 # IPv4 fragment identifier +.set VAR_FSP_KEY, 0x2ED8 # FSP session key +.set VAR_FSP_DATA_LENGTH, 0x2EDA # FSP payload size +.set VAR_FSP_POSITION, 0x2EDC # FSP file position .set VAR_LAST_OFFSET, 0x2EE0 # The last offset we read from .set VAR_READS_IN_AS, 0x2EE4 # How many times have we tried to read while streaming is on? .set VAR_AS_ENABLED, 0x2EE8 # Is Audio streaming enabled by the user? @@ -81,6 +90,12 @@ #else #define VAR_AREA (0x80000000) +#define VAR_FILENAME_LEN (VAR_AREA+0x0E00) // filename length +#define VAR_FILENAME (VAR_AREA+0x0E01) // filename +#define VAR_CLIENT_MAC (VAR_AREA+0x0EEC) // client MAC address +#define VAR_CLIENT_IP (VAR_AREA+0x0EF2) // client IPv4 address +#define VAR_SERVER_MAC (VAR_AREA+0x0EF6) // server MAC address +#define VAR_SERVER_IP (VAR_AREA+0x0EFC) // server IPv4 address #define VAR_PATCHES_BASE (VAR_AREA+0x2D00) // Patches get copied to below this area. #define VAR_FRAG_SIZE (0x1C8) // Size of frag array in bytes #define VAR_FRAG_LIST (VAR_AREA+0x2D00) // 0x1C8 of fragments (40 frags max) (u32 offset, u32 size, u32 rawsector) @@ -88,7 +103,10 @@ #define VAR_DISC_CHANGING (VAR_AREA+0x2ED0) // Are we changing discs? #define VAR_CURRENT_FIELD (VAR_AREA+0x2ED4) // current video field #define VAR_IGR_EXIT_TYPE (VAR_AREA+0x2ED5) // IGR exit type -#define VAR_SPARE (VAR_AREA+0x2ED6) // ######### SPARE until 0x2EE0 +#define VAR_IPV4_ID (VAR_AREA+0x2ED6) // IPv4 fragment identifier +#define VAR_FSP_KEY (VAR_AREA+0x2ED8) // FSP session key +#define VAR_FSP_DATA_LENGTH (VAR_AREA+0x2EDA) // FSP payload size +#define VAR_FSP_POSITION (VAR_AREA+0x2EDC) // FSP file position #define VAR_LAST_OFFSET (VAR_AREA+0x2EE0) // The last offset we read from #define VAR_READS_IN_AS (VAR_AREA+0x2EE4) // How many times have we tried to read while streaming is on? #define VAR_AS_ENABLED (VAR_AREA+0x2EE8) // Is Audio streaming enabled by the user? diff --git a/cube/swiss/include/patcher.h b/cube/swiss/include/patcher.h index 35af9611..565156ca 100644 --- a/cube/swiss/include/patcher.h +++ b/cube/swiss/include/patcher.h @@ -30,6 +30,8 @@ extern u8 wkf_bin[]; extern u32 wkf_bin_size; extern u8 dvd_bin[]; extern u32 dvd_bin_size; +extern u8 bba_bin[]; +extern u32 bba_bin_size; /* SDK patches */ extern u8 GXGetYScaleFactorHook[]; diff --git a/cube/swiss/source/devices/smb/deviceHandler-SMB.c b/cube/swiss/source/devices/smb/deviceHandler-SMB.c index 4224e382..7f3e5712 100644 --- a/cube/swiss/source/devices/smb/deviceHandler-SMB.c +++ b/cube/swiss/source/devices/smb/deviceHandler-SMB.c @@ -38,6 +38,7 @@ #include "deviceHandler-SMB.h" #include "exi.h" #include "bba.h" +#include "patcher.h" /* SMB Globals */ extern int net_initialized; @@ -223,12 +224,36 @@ bool deviceHandler_SMB_test() { return exi_bba_exists(); } +s32 deviceHandler_SMB_setupFile(file_handle* file, file_handle* file2) { + u32 *fragList = (u32*)VAR_FRAG_LIST; + memset((void*)VAR_FRAG_LIST, 0, VAR_FRAG_SIZE); + fragList[1] = file->size; + *(volatile u32*)VAR_DISC_1_LBA = 0; + *(volatile u32*)VAR_DISC_2_LBA = 0; + *(volatile u32*)VAR_CUR_DISC_LBA = 0; + *(volatile u8*)VAR_FILENAME_LEN = strlcpy((char*)VAR_FILENAME, strchr(file->name, '/') + 1, 235) + 1; + net_get_mac_address((void*)VAR_CLIENT_MAC); + *(volatile u32*)VAR_CLIENT_IP = net_gethostip(); + ((volatile u8*)VAR_SERVER_MAC)[0] = 0xFF; + ((volatile u8*)VAR_SERVER_MAC)[1] = 0xFF; + ((volatile u8*)VAR_SERVER_MAC)[2] = 0xFF; + ((volatile u8*)VAR_SERVER_MAC)[3] = 0xFF; + ((volatile u8*)VAR_SERVER_MAC)[4] = 0xFF; + ((volatile u8*)VAR_SERVER_MAC)[5] = 0xFF; + *(volatile u32*)VAR_SERVER_IP = inet_addr(swissSettings.smbServerIp); + *(volatile u16*)VAR_IPV4_ID = 0; + *(volatile u16*)VAR_FSP_KEY = 0; + *(volatile u16*)VAR_FSP_DATA_LENGTH = 0; + *(volatile u32*)VAR_FSP_POSITION = EOF; + return 1; +} + DEVICEHANDLER_INTERFACE __device_smb = { DEVICE_ID_8, "Samba via BBA", "Must be pre-configured via swiss.ini", {TEX_SAMBA, 160, 85}, - FEAT_READ, + FEAT_READ|FEAT_BOOT_GCM, LOC_SERIAL_PORT_1, &initial_SMB, (_fn_test)&deviceHandler_SMB_test, @@ -239,7 +264,7 @@ DEVICEHANDLER_INTERFACE __device_smb = { (_fn_writeFile)NULL, (_fn_deleteFile)NULL, (_fn_seekFile)&deviceHandler_SMB_seekFile, - (_fn_setupFile)NULL, + (_fn_setupFile)&deviceHandler_SMB_setupFile, (_fn_closeFile)&deviceHandler_SMB_closeFile, (_fn_deinit)&deviceHandler_SMB_deinit }; diff --git a/cube/swiss/source/patcher.c b/cube/swiss/source/patcher.c index a4911381..ca3a87fd 100644 --- a/cube/swiss/source/patcher.c +++ b/cube/swiss/source/patcher.c @@ -96,6 +96,11 @@ int install_code() patch = &wkf_bin[0]; patchSize = wkf_bin_size; print_gecko("Installing Patch for WKF\r\n"); } + // Broadband Adapter + else if(devices[DEVICE_CUR] == &__device_smb) { + patch = &bba_bin[0]; patchSize = bba_bin_size; + print_gecko("Installing Patch for Broadband Adapter\r\n"); + } print_gecko("Space for patch remaining: %i\r\n",top_addr - LO_RESERVE); print_gecko("Space taken by vars/video patches: %i\r\n",VAR_PATCHES_BASE-top_addr); if(top_addr - LO_RESERVE < patchSize) diff --git a/cube/swiss/source/swiss.c b/cube/swiss/source/swiss.c index 44a74dfd..e0485f99 100644 --- a/cube/swiss/source/swiss.c +++ b/cube/swiss/source/swiss.c @@ -625,7 +625,7 @@ unsigned int load_app(int multiDol) } } - if(devices[DEVICE_CUR] == &__device_usbgecko) { + if(devices[DEVICE_CUR] == &__device_usbgecko || devices[DEVICE_CUR] == &__device_smb) { Patch_DVDLowLevelReadForUSBGecko(main_dol_buffer, main_dol_size+DOLHDRLENGTH, PATCH_DOL); }