msgba/src/packet/hello.c

143 lines
4.4 KiB
C

#include <sys/signal.h>
#include <msgba/packet/send_frame.h>
#include <msgba/packet.h>
#include <msgba/packet/hello.h>
#include <msgba/core_controller.h>
void
msPacketHelloDestroy(struct msPacketHello **hello) {
if ((*hello)->rom) {
free((*hello)->rom);
(*hello)->rom = NULL;
}
if ((*hello)->savestate) {
free((*hello)->savestate);
(*hello)->savestate = NULL;
}
free(*hello);
*hello = NULL;
}
void
msThreadCallbackStart(struct mCoreThread *threadContext) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, NULL);
}
void
msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
unsigned int stride = data->coreController->stride;
color_t *outputBuffer = data->coreController->outputBuffer;
unsigned width, height;
unsigned char *raw_data;
size_t raw_data_len = 0;
struct msPacketSendFrame *send_frame;
struct msPacket *packet;
data->coreController->threadContext.core->desiredVideoDimensions(data->coreController->threadContext.core, &width, &height);
send_frame = msPacketSendFrameNew(stride, width * height, outputBuffer);
raw_data = msPacketSendFrameSerialize(send_frame, &raw_data_len);
packet = msPacketNew(PACKET_SEND_FRAME, raw_data_len, raw_data);
msPacketSend(packet, data);
msPacketSendFrameDestroy(&send_frame);
msPacketDestroy(&packet);
}
bool
msPacketHelloHandle(const struct msPacket *packet, struct msPacketHello *hello,
struct msClientConnectionData *const data) {
bool result = false;
if (data->coreController) {
fprintf(stderr, "Attempt to send a second hello, aborting connection.\n");
goto return_ms_packet_hello_handle;
}
printf("Loading game and save for client_fd %d\n", data->clientFd);
data->coreController = msCoreControllerLoadGame(hello->rom, hello->size_rom, hello->savestate, hello->size_savestate, data);
msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame);
msCoreControllerSetStartCallback(data->coreController, &msThreadCallbackStart);
msCoreControllerThreadStart(data->coreController);
result = true;
return_ms_packet_hello_handle:
msPacketHelloDestroy(&hello);
return result;
}
bool
msPacketHelloGet(const struct msPacket *packet, int client_fd,
struct msClientConnectionData *const data) {
bool result = false;
struct msPacketHello *hello = NULL;
unsigned char *rom = NULL;
unsigned char *savestate = NULL;
FILE *fp = fmemopen(packet->raw_data, packet->size, "r");
if (!fp) {
printf("Unable to fmemopen\n");
goto return_get_packet_hello;
}
size_t size_rom = 0;
size_t size_savestate = 0;
size_t reads[4] = { 0,0,0,0 };
size_t total_read = 0;
size_t to_read_size;
#define FREAD(target, size, count, fp, n, goto_to) \
to_read_size = size; \
reads[n] = fread(target, to_read_size, count, fp); \
reads[n] *= size; \
if (reads[n] == -1) { \
printf("Unable to read %s\n", #target); \
goto goto_to; \
}
FREAD(&size_rom, sizeof size_rom, 1, fp, 0, return_get_packet_hello);
size_rom = be64toh(size_rom);
rom = malloc(sizeof *rom * size_rom);
FREAD(rom, sizeof *rom, size_rom, fp, 1, return_get_packet_hello);
FREAD(&size_savestate, sizeof size_savestate, 1, fp, 2, return_get_packet_hello);
size_savestate = be64toh(size_savestate);
savestate = malloc(sizeof *savestate * size_savestate);
FREAD(savestate, sizeof *savestate, size_savestate, fp, 3, return_get_packet_hello);
fclose(fp);
for (int i = 0; i<4; i++) {
total_read += reads[i];
}
if (total_read != packet->size) {
fprintf (stderr, "Total read (%lu) != packet->size (%lu)\n", total_read, packet->size);
goto return_get_packet_hello;
}
hello = calloc(1, sizeof *hello);
hello->size_rom = size_rom;
hello->rom = rom;
hello->size_savestate = size_savestate;
hello->savestate = savestate;
result = true;
return_get_packet_hello:
if (!result) {
fprintf(stderr, "Unable to read the packet hello\n");
if (rom) {
free (rom);
rom = NULL;
}
if (savestate) {
free (savestate);
savestate = NULL;
}
return result;
}
return msPacketHelloHandle(packet, hello, data);
}