summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorXavi Del Campo <xavi.dcr@tutanota.com>2020-03-08 17:23:03 +0100
committerXavi Del Campo <xavi.dcr@tutanota.com>2020-03-08 22:33:58 +0100
commit68e21103e09c7a59292485ab805683760b86e6ba (patch)
tree92c33d6211eeae35600525e2520a138503e8281d /src
parent96b0c9d692fd4b41d41e13cdcd8fc773b3976dde (diff)
downloadopensend-68e21103e09c7a59292485ab805683760b86e6ba.tar.gz
Implemented message protocol, not tested yet
Diffstat (limited to 'src')
-rw-r--r--src/Serial.c42
-rw-r--r--src/System.c9
-rw-r--r--src/main.c118
-rw-r--r--src/reception.c186
4 files changed, 204 insertions, 151 deletions
diff --git a/src/Serial.c b/src/Serial.c
index f91f168..10bb90f 100644
--- a/src/Serial.c
+++ b/src/Serial.c
@@ -6,38 +6,29 @@
#include <psxbios.h>
#include <psx.h>
#include <stddef.h>
+#include "reception.h"
-enum
-{
- FIFO_SZ = 128
-};
-
-typedef volatile struct
-{
- unsigned char buf[FIFO_SZ];
- size_t pending, processed;
- bool full;
-} fifo;
-
-static fifo rx;
+fifo rx;
-void sio_handler_callback(void)
+static void sio_handler_callback(void)
{
while (SIOCheckInBuffer())
{
const unsigned char in = SIOReadByte();
size_t aux = rx.pending;
- if (++aux >= (sizeof rx.buf / sizeof *rx.buf))
+ if (++aux >= sizeof rx.buf / sizeof *rx.buf)
aux = 0;
if (aux != rx.processed)
{
rx.buf[aux] = in;
- rx.pending = rx.processed;
+ rx.pending = aux;
+ reception_ev();
}
else
{
+ printf("fifo full\n");
rx.full = true;
}
}
@@ -78,22 +69,27 @@ void SerialInit(void)
};
const int not_crit = EnterCriticalSection();
- void sio_handler(void);
+
+ EnterCriticalSection();
SIOReset();
SIOStart(BAUD_RATE);
- const int sio_handle = OpenEvent(SIO_CLASS, SPEC_GENERAL_INTERRUPT, TRIGGER_CALLBACK, sio_handler);
+ IMASK |= 1 << INT_SIO;
- if (sio_handle != 0xFFFFFFFF)
- EnableEvent(sio_handle);
+ void sio_handler(void);
+ const int sio_handle = OpenEvent(SIO_CLASS, SPEC_GENERAL_INTERRUPT, TRIGGER_CALLBACK, sio_handler_callback);
- IMASK |= 1 << INT_SIO;
+ if (sio_handle != -1)
+ EnableEvent(sio_handle);
SIOEnableRXInterrupt();
if (not_crit)
- {
ExitCriticalSection();
- }
+}
+
+void SerialWrite(const unsigned char byte)
+{
+ SIOSendByte(byte);
}
diff --git a/src/System.c b/src/System.c
index 05a9b9b..9250682 100644
--- a/src/System.c
+++ b/src/System.c
@@ -7,11 +7,12 @@
void SystemInit(void)
{
redirect_stdio_to_sio();
-#if 0
- PSX_InitEx(PSX_INIT_SAVESTATE | PSX_INIT_CD);
-#else
PSX_InitEx(0);
-#endif
SerialInit();
GfxInit();
}
+
+void SystemDeinit(void)
+{
+ PSX_DeInit();
+}
diff --git a/src/main.c b/src/main.c
index 8c958b5..b14ffb5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,124 +7,6 @@
int main(void)
{
SystemInit();
-
reception_loop();
-
- for (;;)
- ;
-
-#if 0
- {
- uint32_t initPC_Address;
- uint32_t RAMDest_Address;
- uint32_t ExeSize = 0;
- uint32_t i;
- void (*exeAddress)(void);
-
- GfxSetGlobalLuminance(0);
-
- SerialInit();
-
- /* Read PSX-EXE header (32 bytes will be enough). */
-
- SerialSetState(SERIAL_STATE_READING_HEADER);
-
- SerialRead(inBuffer, 32);
-
- /* Get initial program counter address from PSX-EXE header. */
-
- initPC_Address = (inBuffer[0x10] | (inBuffer[0x11] << 8) | (inBuffer[0x12] << 16) | (inBuffer[0x13] << 24) );
-
- SerialSetPCAddress(initPC_Address);
-
- /* dprintf("initPC_Address = 0x%08X\n", initPC_Address); */
-
- /* Get destination address in RAM from PSX-EXE header. */
-
- RAMDest_Address = (inBuffer[0x18] | (inBuffer[0x19] << 8) | (inBuffer[0x1A] << 16) | (inBuffer[0x1B] << 24) );
-
- SerialSetRAMDestAddress(RAMDest_Address);
-
- /* dprintf("RAMDest_Address = 0x%08X\n", RAMDest_Address); */
-
- /* We have received all data correctly. Send ACK. */
-
- memset(inBuffer, 0, SystemGetBufferSize());
-
- SerialSetState(SERIAL_STATE_WRITING_ACK);
-
- SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); /* Write ACK */
-
- /* Get PSX-EXE size, without header, in hexadecimal, little-endian format; */
-
- SerialSetState(SERIAL_STATE_READING_EXE_SIZE);
-
- SerialRead(inBuffer, sizeof(uint32_t) );
-
- for (i = 0; i < sizeof(uint32_t); i++)
- {
- ExeSize |= inBuffer[i] << (i << 3); /* (i << 3) == (i * 8) */
- }
-
- SerialSetExeSize(ExeSize);
-
- /* DEBUG_PRINT_VAR(ExeSize); */
-
- SerialSetState(SERIAL_STATE_CLEANING_MEMORY);
-
- exeAddress = (void*)initPC_Address;
-
- /* Clean memory where EXE data will be loaded, just in case... */
-
- memset((void*)RAMDest_Address, 0, (uint32_t)((uint32_t)(&_start) - (uint32_t)(RAMDest_Address) ) );
-
- SerialSetState(SERIAL_STATE_WRITING_ACK);
-
- /* We have received PSX-EXE size (without header) correctly. Send ACK. */
-
- SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); /* Write ACK */
-
- SerialSetState(SERIAL_STATE_READING_EXE_DATA);
-
- while (GfxIsGPUBusy() == true);
-
- for (i = 0; i < ExeSize; i += EXE_DATA_PACKET_SIZE)
- {
- uint32_t bytes_to_read;
-
- /* Read actual EXE data into proper RAM address. */
-
- if ( (i + EXE_DATA_PACKET_SIZE) >= ExeSize)
- {
- bytes_to_read = ExeSize - i;
- }
- else
- {
- bytes_to_read = EXE_DATA_PACKET_SIZE;
- }
-
- SerialRead((uint8_t*)RAMDest_Address + i, bytes_to_read);
-
- SerialSetExeBytesReceived(bytes_to_read);
-
- SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); /* Write ACK */
- }
-
- SetVBlankHandler(&ISR_SystemDefaultVBlank);
-
- /* Make a pretty animation before exeting OpenSend application. */
-
- EndAnimation();
-
- PSX_DeInit();
-
- /* PSX-EXE has been successfully loaded into RAM. Run executable! */
-
- /* dprintf("Entering exe...\n"); */
-
- exeAddress();
- }
-#endif
-
return 0;
}
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;
}