diff options
| author | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-03-08 17:23:03 +0100 |
|---|---|---|
| committer | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-03-08 22:33:58 +0100 |
| commit | 68e21103e09c7a59292485ab805683760b86e6ba (patch) | |
| tree | 92c33d6211eeae35600525e2520a138503e8281d /src/reception.c | |
| parent | 96b0c9d692fd4b41d41e13cdcd8fc773b3976dde (diff) | |
| download | opensend-68e21103e09c7a59292485ab805683760b86e6ba.tar.gz | |
Implemented message protocol, not tested yet
Diffstat (limited to 'src/reception.c')
| -rw-r--r-- | src/reception.c | 186 |
1 files changed, 180 insertions, 6 deletions
diff --git a/src/reception.c b/src/reception.c index 12c1866..6e07ed7 100644 --- a/src/reception.c +++ b/src/reception.c @@ -1,26 +1,200 @@ #include "reception.h" +#include "System.h" #include "Serial.h" #include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> -static volatile bool rx; +static volatile bool input_available; + +#define STATES \ + X(magic_byte) \ + X(psx_exe_header) \ + X(dump) \ + X(done) static enum { - +#define X(s) state_##s, + STATES +#undef X } state; -void reception_ev(void) +int (*init_pc)(void); +unsigned char *init_addr; +size_t sz; + +static void ack(void) +{ + enum + { + ACK = 'b' + }; + + SerialWrite(ACK); +} + +static size_t done(void) +{ + return 0; +} + +static size_t dump(void) +{ + size_t aux = rx.processed; + bool done = false; + + while (aux != rx.pending) + { + enum + { + PACKET_SZ = 128 + }; + + static size_t total, packet; + + if (++aux >= sizeof rx.buf / sizeof *rx.buf) + aux = 0; + + init_addr[total] = rx.buf[aux]; + + if (++packet >= PACKET_SZ) + { + ack(); + packet = 0; + } + + if (++total >= sz) + { + done = true; + break; + } + } + + if (done) + { + state = state_done; + } + + return aux; +} + +static size_t psx_exe_header(void) +{ + typedef const struct + { + unsigned char id[8]; + unsigned char unused[8]; + void *init_addr; + void *init_gp; + void *init_pc; + size_t sz; + } __attribute__((packed)) decoded_header; + + size_t aux = rx.processed; + unsigned char header[sizeof (decoded_header)]; + bool full = false; + + while (aux != rx.pending) + { + static size_t i; + + if (++aux >= sizeof rx.buf / sizeof *rx.buf) + aux = 0; + + header[i] = rx.buf[aux]; + + _Static_assert (sizeof (decoded_header) == 32, "unexpected struct size"); + + if (++i >= sizeof (decoded_header)) + { + full = true; + break; + } + } + + if (full) + { + decoded_header *const decoded = (const void *)header; + + if (!strcmp((const char *)decoded->id, "PS-X EXE")) + { + if (decoded->init_pc == (const void *)0x80010000) + { + init_pc = decoded->init_pc + 0x14800; + init_addr = decoded->init_addr + 0x14800; + } + else + { + init_pc = decoded->init_pc; + init_addr = decoded->init_addr; + } + + printf("init_pc=%p,init_addr=%p,sz=%d\n", init_pc, init_addr, sz); + + sz = decoded->sz; + + ack(); + state = state_dump; + } + } + + return aux; +} + +static size_t magic_byte(void) { - rx = true; + size_t aux = rx.processed; + + if (++aux >= sizeof rx.buf / sizeof *rx.buf) + aux = 0; + + { + enum + { + MAGIC_BYTE = 99 + }; + + const unsigned char in = rx.buf[aux]; + + if (in == MAGIC_BYTE) + { + state = state_psx_exe_header; + ack(); + } + } + + return aux; } void reception_loop(void) { - for (;;) + while (state != state_done) { - if (rx) + if (input_available && rx.pending != rx.processed) { + static size_t (*const h[])(void) = + { +#define X(s) [state_##s] = s, + STATES +#undef X + }; + + rx.processed = h[state](); + input_available = false; } } + + if (init_pc) + { + SystemDeinit(); + init_pc(); + } +} + +void reception_ev(void) +{ + input_available = true; } |
