diff --git a/main/wired/maple.c b/main/wired/maple.c index cfd682be..69a1041a 100644 --- a/main/wired/maple.c +++ b/main/wired/maple.c @@ -11,6 +11,7 @@ #include "tools/util.h" #include "adapter/adapter.h" #include "adapter/config.h" +#include "adapter/memory_card.h" #include "adapter/wired/dc.h" #include "system/core0_stall.h" #include "system/delay.h" @@ -28,31 +29,34 @@ #define ID_RUMBLE 0x00000100 #define ID_MOUSE 0x00000200 -#define CMD_INFO_REQ 0x01 -#define CMD_EXT_INFO_REQ 0x02 -#define CMD_RESET 0x03 -#define CMD_SHUTDOWN 0x04 -#define CMD_INFO_RSP 0x05 -#define CMD_EXT_INFO_RSP 0x06 -#define CMD_ACK 0x07 -#define CMD_DATA_TX 0x08 -#define CMD_GET_CONDITION 0x09 -#define CMD_MEM_INFO_REQ 0x0A -#define CMD_BLOCK_READ 0x0B -#define CMD_BLOCK_WRITE 0x0C -#define CMD_SET_CONDITION 0x0E +#define CMD_INFO_REQ 0x01 +#define CMD_EXT_INFO_REQ 0x02 +#define CMD_RESET 0x03 +#define CMD_SHUTDOWN 0x04 +#define CMD_INFO_RSP 0x05 +#define CMD_EXT_INFO_RSP 0x06 +#define CMD_ACK 0x07 +#define CMD_DATA_TX 0x08 +#define CMD_GET_CONDITION 0x09 +#define CMD_MEM_INFO_REQ 0x0A +#define CMD_BLOCK_READ 0x0B +#define CMD_BLOCK_WRITE 0x0C +#define CMD_WRITE_COMPLETE 0x0D +#define CMD_SET_CONDITION 0x0E #define ADDR_MASK 0x3F #define ADDR_MAIN 0x20 #define ADDR_MEM 0x01 #define ADDR_RUMBLE 0x02 -#define DESC_CTRL 0x000F06FE -#define DESC_CTRL_ALT 0x003FFFFF -#define DESC_VMU 0x7E7E3F40 -#define DESC_RUMBLE 0x01010000 -#define DESC_MOUSE 0x000E0700 -#define DESC_KB 0x01020080 +#define DESC_CTRL 0x000F06FE +#define DESC_CTRL_ALT 0x003FFFFF +#define DESC_VMU_TIMER 0x7E7E3F40 +#define DESC_VMU_SCREEN 0x00051000 +#define DESC_VMU_MEMORY 0x000F4100 +#define DESC_RUMBLE 0x01010000 +#define DESC_MOUSE 0x000E0700 +#define DESC_KB 0x01020080 #define PWR_CTRL 0xAE01F401 #define PWR_VMU 0x7C008200 @@ -63,7 +67,13 @@ #define TIMEOUT 8 #define TIMEOUT_ABORT 100 -#define wait_100ns() asm("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); +#define VMU_BLOCK_SIZE 512 +#define VMU_WRITE_ACCESSES 4 +#define VMU_READ_ACCESSES 1 + +#define wait_100ns() asm("movi a8, 5\n\tloop a8, waitend%=\n\tnop\n\twaitend%=:\n":::"a8"); +#define wait_500ns() asm("movi a8, 49\n\tloop a8, waitend%=\n\tnop\n\twaitend%=:\n":::"a8"); +#define wait_200ns() asm("movi a8, 16\n\tloop a8, waitend%=\n\tnop\n\twaitend%=:\n":::"a8"); #define maple_fix_byte(s, a, b) (s ? ((a << s) | (b >> (8 - s))) : b) struct maple_pkt { @@ -108,12 +118,10 @@ static const uint8_t ctrl_area_dir_name[] = { 0x6C, 0x6C, 0x6F, 0x72, 0x20, 0x20, 0x72, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -#if 0 static const uint8_t vmu_area_dir_name[] = { 0x69, 0x56, 0x00, 0xFF, 0x6C, 0x61, 0x75, 0x73, 0x6D, 0x65, 0x4D, 0x20, 0x20, 0x79, 0x72, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -#endif static const uint8_t rumble_area_dir_name[] = { 0x75, 0x50, 0x00, 0xFF, 0x50, 0x20, 0x75, 0x72, 0x20, 0x75, 0x72, 0x75, 0x6B, 0x63, 0x61, 0x50, @@ -143,6 +151,11 @@ static const uint8_t dc_mouse_axes_idx[ADAPTER_MAX_AXES] = 2, 3, 1, 0, 5, 4 }; +static const uint8_t vmu_media_info[] = { + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFE, 0x00, 0xFF, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, + 0x00, 0x1F, 0x00, 0xC8, 0x00, 0x80, 0x00, 0x00, +}; + #else static uint32_t cur_us = 0, pre_us = 0; #endif @@ -177,7 +190,7 @@ static inline void load_mouse_axes(uint8_t port, uint16_t *axes) { } } -static void maple_tx(uint32_t port, uint32_t maple0, uint32_t maple1, uint8_t *data, uint8_t len) { +static void maple_tx(uint32_t port, uint32_t maple0, uint32_t maple1, uint8_t *data, uint32_t len) { uint8_t *crc = data + (len - 1); *crc = 0x00; @@ -188,62 +201,28 @@ static void maple_tx(uint32_t port, uint32_t maple0, uint32_t maple1, uint8_t *d gpio_set_direction_iram(gpio_pin[port][1], GPIO_MODE_OUTPUT); core0_stall_start(); GPIO.out_w1tc = maple0; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); + wait_200ns(); for (uint32_t bit = 0; bit < len*8; ++data) { for (uint32_t mask = 0x80; mask; mask >>= 1, ++bit) { GPIO.out_w1ts = maple0; - wait_100ns(); - wait_100ns(); + wait_200ns(); if (*data & mask) { GPIO.out_w1ts = maple1; } @@ -252,13 +231,11 @@ static void maple_tx(uint32_t port, uint32_t maple0, uint32_t maple1, uint8_t *d } wait_100ns(); GPIO.out_w1tc = maple0; - wait_100ns(); - wait_100ns(); + wait_200ns(); mask >>= 1; ++bit; GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); + wait_200ns(); if (*data & mask) { GPIO.out_w1ts = maple0; } @@ -267,49 +244,24 @@ static void maple_tx(uint32_t port, uint32_t maple0, uint32_t maple1, uint8_t *d } wait_100ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); + wait_200ns(); } *crc ^= *data; } GPIO.out_w1ts = maple0; wait_100ns(); GPIO.out_w1ts = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple1; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple0; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple0; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1tc = maple0; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple0; - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); - wait_100ns(); + wait_500ns(); GPIO.out_w1ts = maple1; core0_stall_end(); @@ -330,6 +282,8 @@ static unsigned maple_rx(unsigned cause) { uint32_t bad_frame; uint8_t len, cmd, src, dst, crc = 0; uint32_t maple1; + uint8_t phase; + uint8_t block_no; if (maple0) { core0_stall_start(); @@ -495,6 +449,9 @@ static unsigned maple_rx(unsigned cause) { if (config.out_cfg[port].acc_mode & ACC_RUMBLE) { pkt.src |= ADDR_RUMBLE; } + if (config.out_cfg[port].acc_mode & ACC_MEM) { + pkt.src |= ADDR_MEM; + } pkt.dst = dst; switch (cmd) { case CMD_INFO_REQ: @@ -596,6 +553,68 @@ static unsigned maple_rx(unsigned cause) { break; } break; + case ADDR_MEM: + pkt.src = src; + pkt.dst = dst; + switch(cmd) { + case CMD_INFO_REQ: + pkt.len = 28; + pkt.cmd = CMD_INFO_RSP; + pkt.data32[0] = ID_VMU_MEM; + pkt.data32[1] = DESC_VMU_MEMORY; + pkt.data32[2] = 0; + pkt.data32[3] = 0; + memcpy((void *)&pkt.data32[4], vmu_area_dir_name, sizeof(vmu_area_dir_name)); + memcpy((void *)&pkt.data32[12], brand, sizeof(brand)); + pkt.data32[27] = PWR_VMU; + maple_tx(port, maple0, maple1, pkt.data, pkt.len * 4 + 5); + break; + case CMD_EXT_INFO_REQ: /* unimplemented */ + case CMD_GET_CONDITION: + case CMD_MEM_INFO_REQ: + pkt.len = 0x07; + pkt.cmd = CMD_DATA_TX; + pkt.data32[0] = ID_VMU_MEM; + memcpy((void *)&pkt.data32[1], vmu_media_info, sizeof(vmu_media_info)); + maple_tx(port, maple0, maple1, pkt.data, pkt.len * 4 + 5); + break; + case CMD_BLOCK_READ: + pkt.len = 0x82; + pkt.cmd = CMD_DATA_TX; + pkt.data32[0] = ID_VMU_MEM; + phase = (uint8_t)((pkt.data32[1] >> 16) & 0x00FF); + if (phase) { + ets_printf("Block Read with unexpected phase: 0x%02X, expected 0\n", phase); + } + block_no = (uint8_t)((pkt.data32[1]) & 0x00FF); + mc_read(block_no * VMU_BLOCK_SIZE, (void *)&pkt.data32[2], VMU_BLOCK_SIZE); + maple_tx(port, maple0, maple1, pkt.data, pkt.len * 4 + 5); + break; + case CMD_BLOCK_WRITE: + if (pkt.len != (32 + 2)) { + ets_printf("Unexpected Block Write packet length: 0x%02X, expected 0x22\n", pkt.len); + } + pkt.len = 0x00; + pkt.cmd = CMD_ACK; + if ((!bad_frame) && pkt.data32[0] == ID_VMU_MEM) { + phase = (uint8_t)((pkt.data32[1] >> 16) & 0x00FF); + block_no = (uint8_t)((pkt.data32[1]) & 0x00FF); + /* Data is written to the MC module in wire byte order. */ + /* If creating a read/write function, this must be accounted for. */ + mc_write((block_no * VMU_BLOCK_SIZE) + (128 * phase), (void *)&pkt.data32[2], 128); + } + maple_tx(port, maple0, maple1, pkt.data, pkt.len * 4 + 5); + break; + case CMD_WRITE_COMPLETE: + pkt.len = 0x00; + pkt.cmd = CMD_ACK; + maple_tx(port, maple0, maple1, pkt.data, pkt.len * 4 + 5); + break; + default: + ets_printf("%02X: Unk cmd: 0x%02X\n", dst, cmd); + break; + } + break; } break; }