Adding functional controls.
This commit is contained in:
parent
52eb3e4266
commit
9a72365994
|
@ -4,6 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
struct msCoreController;
|
struct msCoreController;
|
||||||
|
|
||||||
|
@ -11,10 +12,17 @@ struct msCoreController;
|
||||||
* Struct representing everything needed while a connection is established.
|
* Struct representing everything needed while a connection is established.
|
||||||
*/
|
*/
|
||||||
struct msClientConnectionData {
|
struct msClientConnectionData {
|
||||||
|
//! The number of this thread.
|
||||||
size_t numberOfThread;
|
size_t numberOfThread;
|
||||||
|
//! Where to receive and send packets.
|
||||||
int clientFd;
|
int clientFd;
|
||||||
|
//! The core controller
|
||||||
struct msCoreController *coreController;
|
struct msCoreController *coreController;
|
||||||
|
//! Mutex to avoid send multiple packets at once.
|
||||||
pthread_mutex_t *mutexSendPacket;
|
pthread_mutex_t *mutexSendPacket;
|
||||||
|
//! Mutex to avoid to do multiple key operations at once.
|
||||||
|
pthread_mutex_t *mutexPressKey;
|
||||||
|
//! The last time we sent a frame.
|
||||||
struct timespec *lastFrameDate;
|
struct timespec *lastFrameDate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,8 +35,10 @@ struct msClientConnectionData {
|
||||||
struct msClientConnectionData *
|
struct msClientConnectionData *
|
||||||
msClientConnectionDataNew(size_t numberOfThread, int clientFd);
|
msClientConnectionDataNew(size_t numberOfThread, int clientFd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to cleanup the session data.
|
||||||
|
* @param data A pointer to the pointer to msClientConnectionData.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
msClientConnectionDataDestroy(struct msClientConnectionData **data);
|
msClientConnectionDataDestroy(struct msClientConnectionData **data);
|
||||||
|
|
||||||
extern pthread_mutex_t mutexClientConnection;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
enum {
|
enum {
|
||||||
PACKET_GET_HELLO, //! Packet id for get hello.
|
PACKET_GET_HELLO, //! Packet id for get hello.
|
||||||
PACKET_SEND_FRAME, //! Packet id for send frame.
|
PACKET_SEND_FRAME, //! Packet id for send frame.
|
||||||
|
PACKET_GET_KEY_DOWN, //! Packet id for pressing a key.
|
||||||
PACKETS_NUMBER //! The number of recognized packets.
|
PACKETS_NUMBER //! The number of recognized packets.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,45 @@
|
||||||
|
|
||||||
struct msPacket;
|
struct msPacket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first kind of packet that the client should send to the emulator.
|
||||||
|
*/
|
||||||
struct msPacketHello {
|
struct msPacketHello {
|
||||||
size_t size_rom;
|
//! The size of the following field.
|
||||||
|
size_t sizeRom;
|
||||||
|
//! The ROM containing the game.
|
||||||
unsigned char *rom;
|
unsigned char *rom;
|
||||||
size_t size_savestate;
|
//! The size of the following field.
|
||||||
|
size_t sizeSavestate;
|
||||||
|
//! The savestate from where to resume.
|
||||||
unsigned char *savestate;
|
unsigned char *savestate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the msPacketHello and deallocates the memory.
|
||||||
|
* @param hello The pointer to the pointer to hello to null it after this operation.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
msPacketHelloDestroy(struct msPacketHello **hello);
|
msPacketHelloDestroy(struct msPacketHello **hello);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles msPacketHello.
|
||||||
|
* @param packet The packet containing this object in its raw_data.
|
||||||
|
* @param hello This object.
|
||||||
|
* @param data This session.
|
||||||
|
* @return The success status.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
msPacketHelloHandle(const struct msPacket *packet, struct msPacketHello *hello,
|
msPacketHelloHandle(const struct msPacket *packet, struct msPacketHello *hello,
|
||||||
struct msClientConnectionData *const data);
|
struct msClientConnectionData *const data);
|
||||||
|
/**
|
||||||
|
* Retrieves the msPacketHello contained in the packet raw_data.
|
||||||
|
* @param packet The packet containing msPacketHello, should have PACKET_GET_HELLO as its id.
|
||||||
|
* @param client_fd The source of this packet.
|
||||||
|
* @param data This session.
|
||||||
|
* @return The success status.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
||||||
struct msClientConnectionData *const data);
|
struct msClientConnectionData *const data);
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef MS_PACKET_KEY_DOWN
|
||||||
|
#define MS_PACKET_KEY_DOWN
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <msgba/client_connection_data.h>
|
||||||
|
|
||||||
|
struct msPacket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packet kind received when a key is pressed that should be handled by the emulator.
|
||||||
|
*/
|
||||||
|
struct msPacketKeyDown {
|
||||||
|
//! Determines if the key is pressed or un pressed.
|
||||||
|
char isPressed;
|
||||||
|
//! The key pressed.
|
||||||
|
int key;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the msPacketKeyDown
|
||||||
|
* @param keyDown The pointer to the pointer to keyDown to null it after this operation.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
msPacketKeyDownDestroy(struct msPacketKeyDown **keyDown);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the msPacketKeyDown
|
||||||
|
* @param packet The packet containing msPacketKeyDown, should have PACKET_GET_KEY_DOWN as its id.
|
||||||
|
* @param keyDown This object.
|
||||||
|
* @param data The session data.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
msPacketKeyDownHandle(const struct msPacket *packet, struct msPacketKeyDown *keyDown,
|
||||||
|
struct msClientConnectionData *const data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the msPacketKeyDown contained in the packet raw_data.
|
||||||
|
* @param packet The packet containing msPacketKeyDown, should have PACKET_GET_KEY_DOWN as its id.
|
||||||
|
* @param client_fd The source of this packet.
|
||||||
|
* @param data The session data.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
msPacketKeyDownGet(const struct msPacket *packet, int client_fd,
|
||||||
|
struct msClientConnectionData *const data);
|
||||||
|
#endif
|
|
@ -10,6 +10,7 @@ sources = [
|
||||||
'src/packet.c',
|
'src/packet.c',
|
||||||
'src/packet/hello.c',
|
'src/packet/hello.c',
|
||||||
'src/packet/send_frame.c',
|
'src/packet/send_frame.c',
|
||||||
|
'src/packet/key_down.c',
|
||||||
'src/client_connection_data.c',
|
'src/client_connection_data.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include <msgba/core_controller.h>
|
#include <msgba/core_controller.h>
|
||||||
#include <msgba/client_connection_data.h>
|
#include <msgba/client_connection_data.h>
|
||||||
|
|
||||||
pthread_mutex_t mutexClientConnection = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
struct msClientConnectionData *
|
struct msClientConnectionData *
|
||||||
msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
||||||
struct msClientConnectionData *data = malloc (sizeof *data);
|
struct msClientConnectionData *data = malloc (sizeof *data);
|
||||||
|
@ -12,8 +10,10 @@ msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
||||||
data->clientFd = clientFd;
|
data->clientFd = clientFd;
|
||||||
data->coreController = NULL;
|
data->coreController = NULL;
|
||||||
data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket);
|
data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket);
|
||||||
|
data->mutexPressKey = malloc(sizeof *data->mutexPressKey);
|
||||||
data->lastFrameDate = calloc(sizeof *data->lastFrameDate, 1);
|
data->lastFrameDate = calloc(sizeof *data->lastFrameDate, 1);
|
||||||
pthread_mutex_init(data->mutexSendPacket, NULL);
|
pthread_mutex_init(data->mutexSendPacket, NULL);
|
||||||
|
pthread_mutex_init(data->mutexPressKey, NULL);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,12 @@ msClientConnectionDataDestroy(struct msClientConnectionData **data) {
|
||||||
if ((*data)->coreController) {
|
if ((*data)->coreController) {
|
||||||
msCoreControllerDestroy(&(*data)->coreController);
|
msCoreControllerDestroy(&(*data)->coreController);
|
||||||
}
|
}
|
||||||
|
pthread_mutex_destroy((*data)->mutexSendPacket);
|
||||||
|
pthread_mutex_destroy((*data)->mutexPressKey);
|
||||||
free((*data)->mutexSendPacket);
|
free((*data)->mutexSendPacket);
|
||||||
|
free((*data)->mutexPressKey);
|
||||||
(*data)->mutexSendPacket = NULL;
|
(*data)->mutexSendPacket = NULL;
|
||||||
|
(*data)->mutexPressKey = NULL;
|
||||||
free(*data);
|
free(*data);
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,16 +39,16 @@ msCoreControllerLoadGame (const unsigned char *rom, size_t rom_len,
|
||||||
core->init(core);
|
core->init(core);
|
||||||
|
|
||||||
mInputMapInit(&core->inputMap, &GBAInputInfo);
|
mInputMapInit(&core->inputMap, &GBAInputInfo);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_A, GBA_KEY_A);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_A, GBA_KEY_A);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_B, GBA_KEY_B);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_B, GBA_KEY_B);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_L, GBA_KEY_L);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_L, GBA_KEY_L);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_R, GBA_KEY_R);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_R, GBA_KEY_R);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_START, GBA_KEY_START);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_START, GBA_KEY_START);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_SELECT, GBA_KEY_SELECT);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_SELECT, GBA_KEY_SELECT);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_UP, GBA_KEY_UP);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_UP, GBA_KEY_UP);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_DOWN, GBA_KEY_DOWN);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_DOWN, GBA_KEY_DOWN);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_LEFT, GBA_KEY_LEFT);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_LEFT, GBA_KEY_LEFT);
|
||||||
mInputBindKey(&core->inputMap, 0, MSGBA_KEY_RIGHT, GBA_KEY_RIGHT);
|
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_RIGHT, GBA_KEY_RIGHT);
|
||||||
|
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <msgba/packet.h>
|
#include <msgba/packet.h>
|
||||||
#include <msgba/packet/hello.h>
|
#include <msgba/packet/hello.h>
|
||||||
|
#include <msgba/packet/key_down.h>
|
||||||
|
|
||||||
#define PRINT_DEBUG(NAME, CLIENT_FD) \
|
#define PRINT_DEBUG(NAME, CLIENT_FD) \
|
||||||
printf ("Received packet %s from client fd %d\n", #NAME, CLIENT_FD);
|
printf ("Received packet %s from client fd %d\n", #NAME, CLIENT_FD);
|
||||||
|
@ -11,11 +12,16 @@ bool
|
||||||
msPacketHandle(struct msPacket *packet, int client_fd,
|
msPacketHandle(struct msPacket *packet, int client_fd,
|
||||||
struct msClientConnectionData *const data) {
|
struct msClientConnectionData *const data) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
printf("Received packet %lu\n", packet->id);
|
||||||
switch (packet->id) {
|
switch (packet->id) {
|
||||||
case PACKET_GET_HELLO:
|
case PACKET_GET_HELLO:
|
||||||
PRINT_DEBUG(PACKET_HELLO, client_fd);
|
PRINT_DEBUG(PACKET_HELLO, client_fd);
|
||||||
result = msPacketHelloGet(packet, client_fd, data);
|
result = msPacketHelloGet(packet, client_fd, data);
|
||||||
break;
|
break;
|
||||||
|
case PACKET_GET_KEY_DOWN:
|
||||||
|
PRINT_DEBUG(PACKET_KEY_DOWN, client_fd);
|
||||||
|
result = msPacketKeyDownGet(packet, client_fd, data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -96,6 +102,7 @@ msPacketRead(int client_fd) {
|
||||||
printf("Unable to read id\n");
|
printf("Unable to read id\n");
|
||||||
goto return_read_packet;
|
goto return_read_packet;
|
||||||
}
|
}
|
||||||
|
id = be64toh(id);
|
||||||
result = read(client_fd, &size, sizeof size);
|
result = read(client_fd, &size, sizeof size);
|
||||||
if (result < sizeof size) {
|
if (result < sizeof size) {
|
||||||
printf("Unable to read packet\n");
|
printf("Unable to read packet\n");
|
||||||
|
|
|
@ -96,7 +96,7 @@ msPacketHelloHandle(const struct msPacket *packet, struct msPacketHello *hello,
|
||||||
goto return_ms_packet_hello_handle;
|
goto return_ms_packet_hello_handle;
|
||||||
}
|
}
|
||||||
printf("Loading game and save for client_fd %d\n", data->clientFd);
|
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);
|
data->coreController = msCoreControllerLoadGame(hello->rom, hello->sizeRom, hello->savestate, hello->sizeSavestate, data);
|
||||||
msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame);
|
msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame);
|
||||||
msCoreControllerSetStartCallback(data->coreController, &msThreadCallbackStart);
|
msCoreControllerSetStartCallback(data->coreController, &msThreadCallbackStart);
|
||||||
msCoreControllerThreadStart(data->coreController);
|
msCoreControllerThreadStart(data->coreController);
|
||||||
|
@ -118,8 +118,8 @@ msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
||||||
printf("Unable to fmemopen\n");
|
printf("Unable to fmemopen\n");
|
||||||
goto return_get_packet_hello;
|
goto return_get_packet_hello;
|
||||||
}
|
}
|
||||||
size_t size_rom = 0;
|
size_t sizeRom = 0;
|
||||||
size_t size_savestate = 0;
|
size_t sizeSavestate = 0;
|
||||||
size_t reads[4] = { 0,0,0,0 };
|
size_t reads[4] = { 0,0,0,0 };
|
||||||
size_t total_read = 0;
|
size_t total_read = 0;
|
||||||
size_t to_read_size;
|
size_t to_read_size;
|
||||||
|
@ -134,18 +134,17 @@ msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FREAD(&size_rom, sizeof size_rom, 1, fp, 0, return_get_packet_hello);
|
FREAD(&sizeRom, sizeof sizeRom, 1, fp, 0, return_get_packet_hello);
|
||||||
size_rom = be64toh(size_rom);
|
sizeRom = be64toh(sizeRom);
|
||||||
rom = malloc(sizeof *rom * size_rom);
|
rom = malloc(sizeof *rom * sizeRom);
|
||||||
|
|
||||||
FREAD(rom, sizeof *rom, size_rom, fp, 1, return_get_packet_hello);
|
FREAD(rom, sizeof *rom, sizeRom, fp, 1, return_get_packet_hello);
|
||||||
|
|
||||||
FREAD(&size_savestate, sizeof size_savestate, 1, fp, 2, return_get_packet_hello);
|
FREAD(&sizeSavestate, sizeof sizeSavestate, 1, fp, 2, return_get_packet_hello);
|
||||||
size_savestate = be64toh(size_savestate);
|
sizeSavestate = be64toh(sizeSavestate);
|
||||||
savestate = malloc(sizeof *savestate * size_savestate);
|
savestate = malloc(sizeof *savestate * sizeSavestate);
|
||||||
|
|
||||||
FREAD(savestate, sizeof *savestate, size_savestate, fp, 3, return_get_packet_hello);
|
FREAD(savestate, sizeof *savestate, sizeSavestate, fp, 3, return_get_packet_hello);
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
for (int i = 0; i<4; i++) {
|
for (int i = 0; i<4; i++) {
|
||||||
total_read += reads[i];
|
total_read += reads[i];
|
||||||
|
@ -155,12 +154,13 @@ msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
||||||
goto return_get_packet_hello;
|
goto return_get_packet_hello;
|
||||||
}
|
}
|
||||||
hello = calloc(1, sizeof *hello);
|
hello = calloc(1, sizeof *hello);
|
||||||
hello->size_rom = size_rom;
|
hello->sizeRom = sizeRom;
|
||||||
hello->rom = rom;
|
hello->rom = rom;
|
||||||
hello->size_savestate = size_savestate;
|
hello->sizeSavestate = sizeSavestate;
|
||||||
hello->savestate = savestate;
|
hello->savestate = savestate;
|
||||||
result = true;
|
result = true;
|
||||||
return_get_packet_hello:
|
return_get_packet_hello:
|
||||||
|
fclose(fp);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
fprintf(stderr, "Unable to read the packet hello\n");
|
fprintf(stderr, "Unable to read the packet hello\n");
|
||||||
if (rom) {
|
if (rom) {
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <mgba/core/input.h>
|
||||||
|
|
||||||
|
#include <msgba/packet.h>
|
||||||
|
#include <msgba/core_controller.h>
|
||||||
|
#include <msgba/packet/key_down.h>
|
||||||
|
|
||||||
|
bool
|
||||||
|
msPacketKeyDownGet(const struct msPacket *packet, int clientFd, struct msClientConnectionData *const data) {
|
||||||
|
bool result = false;
|
||||||
|
struct msPacketKeyDown *keyDown = NULL;
|
||||||
|
int key = 0;
|
||||||
|
char isPressed = 0;
|
||||||
|
FILE *fp = fmemopen(packet->raw_data, packet->size, "r");
|
||||||
|
if (1 != fread(&isPressed, sizeof isPressed, 1, fp)) {
|
||||||
|
goto return_ms_packet_key_down_get;
|
||||||
|
}
|
||||||
|
if (1 != fread(&key, sizeof key, 1, fp)) {
|
||||||
|
goto return_ms_packet_key_down_get;
|
||||||
|
}
|
||||||
|
key = be32toh(key);
|
||||||
|
keyDown = malloc(sizeof *keyDown);
|
||||||
|
keyDown->isPressed = isPressed;
|
||||||
|
keyDown->key = key;
|
||||||
|
result = true;
|
||||||
|
return_ms_packet_key_down_get:
|
||||||
|
fclose(fp);
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return msPacketKeyDownHandle(packet, keyDown, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
msPacketKeyDownHandle(const struct msPacket *packet, struct msPacketKeyDown *keyDown,
|
||||||
|
struct msClientConnectionData *const data) {
|
||||||
|
bool result = false;
|
||||||
|
struct msCoreController *coreController = data->coreController;
|
||||||
|
if (!coreController || !coreController->threadContext.core) {
|
||||||
|
goto return_ms_packet_key_down_handle;
|
||||||
|
}
|
||||||
|
struct mCore *core = coreController->threadContext.core;
|
||||||
|
int gbaKey = 1 << mInputMapKey(&core->inputMap, 80, keyDown->key);
|
||||||
|
printf("Keys received %d %x\n", keyDown->key, gbaKey);
|
||||||
|
pthread_mutex_lock(data->mutexPressKey);
|
||||||
|
if (keyDown->isPressed) {
|
||||||
|
core->addKeys(core, gbaKey);
|
||||||
|
} else {
|
||||||
|
core->clearKeys(core, gbaKey);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(data->mutexPressKey);
|
||||||
|
result = true;
|
||||||
|
return_ms_packet_key_down_handle:
|
||||||
|
msPacketKeyDownDestroy(&keyDown);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
msPacketKeyDownDestroy(struct msPacketKeyDown **keyDownPtr) {
|
||||||
|
free(*keyDownPtr);
|
||||||
|
*keyDownPtr = NULL;
|
||||||
|
}
|
Loading…
Reference in New Issue