2021-05-28 04:03:04 +00:00
|
|
|
/*
|
2023-06-09 00:04:22 +00:00
|
|
|
* netScores.c
|
|
|
|
* NetScoresGS
|
2021-05-28 04:03:04 +00:00
|
|
|
*
|
|
|
|
* Created by Jeremy Rand on 2021-05-23.
|
|
|
|
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2023-06-08 05:15:54 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
#include <Hash.h>
|
|
|
|
#include <locator.h>
|
2021-05-28 04:03:04 +00:00
|
|
|
#include <misctool.h>
|
2023-06-08 05:15:54 +00:00
|
|
|
#include <orca.h>
|
2021-06-01 04:35:47 +00:00
|
|
|
#include <tcpip.h>
|
2021-06-04 04:41:11 +00:00
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
#include "netScores.h"
|
2021-05-28 04:03:04 +00:00
|
|
|
|
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
// Defines
|
|
|
|
|
2021-05-28 04:03:04 +00:00
|
|
|
#define REQUEST_TYPE_GET_HIGH_SCORES 0
|
|
|
|
#define REQUEST_TYPE_SET_SCORE 1
|
|
|
|
|
|
|
|
#define RESPONSE_TYPE_HELLO 0
|
|
|
|
#define RESPONSE_TYPE_SCORES 1
|
|
|
|
#define RESPONSE_TYPE_STATUS 2
|
|
|
|
|
2023-06-12 03:33:47 +00:00
|
|
|
#define DEFAULT_SHUTDOWN_NETWORK_TIMEOUT (2 * 60)
|
|
|
|
#define DEFAULT_TCP_CONNECT_TIMEOUT (8 * 60)
|
|
|
|
#define DEFAULT_READ_NETWORK_TIMEOUT (5 * 60)
|
|
|
|
#define DEFAULT_NETWORK_RETRY_TIMEOUT (3 * 60 * 60)
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2021-05-28 04:03:04 +00:00
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
// Types
|
|
|
|
|
2021-05-28 04:03:04 +00:00
|
|
|
typedef struct tSessionSecrets {
|
|
|
|
uint32_t secret;
|
|
|
|
uint32_t nonce;
|
|
|
|
} tSessionSecrets;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tHighScoreRequest {
|
|
|
|
uint16_t requestType;
|
|
|
|
} tHighScoreRequest;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tHighScoreRequestWithHash {
|
|
|
|
tHighScoreRequest highScoreRequest;
|
|
|
|
uint8_t md5Digest[16];
|
|
|
|
} tHighScoreRequestWithHash;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tSetHighScoreRequest {
|
|
|
|
uint16_t requestType;
|
|
|
|
char who[4];
|
|
|
|
uint32_t score;
|
2021-06-02 04:33:53 +00:00
|
|
|
Word is60Hz;
|
2021-05-28 04:03:04 +00:00
|
|
|
} tSetHighScoreRequest;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tSetHighScoreRequestWithHash {
|
|
|
|
tSetHighScoreRequest setHighScoreRequest;
|
|
|
|
uint8_t md5Digest[16];
|
|
|
|
} tSetHighScoreRequestWithHash;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tHelloResponse {
|
|
|
|
uint16_t responseType;
|
|
|
|
uint32_t nonce;
|
|
|
|
} tHelloResponse;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tScoresResponse {
|
|
|
|
uint16_t responseType;
|
2023-06-09 00:04:22 +00:00
|
|
|
tNSGSHighScores highScores;
|
2021-05-28 04:03:04 +00:00
|
|
|
} tScoresResponse;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct tStatusResponse {
|
|
|
|
uint16_t responseType;
|
|
|
|
Boolean success;
|
2021-06-27 19:48:57 +00:00
|
|
|
uint16_t position;
|
|
|
|
uint16_t numberOfScores;
|
2021-05-28 04:03:04 +00:00
|
|
|
} tStatusResponse;
|
|
|
|
|
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
typedef enum tGameNetworkState {
|
|
|
|
GAME_NETWORK_CONNECT_FAILED = 0,
|
|
|
|
GAME_NETWORK_UNCONNECTED,
|
2021-06-02 03:13:14 +00:00
|
|
|
|
|
|
|
/* All states below this should have Marinetti disconnected */
|
2021-06-01 04:35:47 +00:00
|
|
|
GAME_NETWORK_CONNECTED,
|
2021-06-02 03:13:14 +00:00
|
|
|
GAME_NETWORK_RESOLVING_NAME,
|
|
|
|
|
|
|
|
/* These are all of the error states. Marinetti is still connected but the
|
|
|
|
TCP connection is closed and ipid released. */
|
|
|
|
GAME_NETWORK_LOOKUP_FAILED,
|
|
|
|
GAME_NETWORK_SOCKET_ERROR,
|
|
|
|
GAME_NETWORK_PROTOCOL_FAILED,
|
2021-06-04 04:41:11 +00:00
|
|
|
GAME_NETWORK_FAILURE,
|
|
|
|
|
|
|
|
/* This is the state we are in during a game on a machine with a working network
|
|
|
|
(other possible states are fail states). */
|
|
|
|
GAME_NETWORK_TCP_UNCONNECTED,
|
2021-06-02 03:13:14 +00:00
|
|
|
|
|
|
|
/* All of these states below here have an ipid open and the TCP connection is
|
|
|
|
open and in some state. */
|
|
|
|
GAME_NETWORK_WAITING_FOR_TCP,
|
|
|
|
|
|
|
|
/* All of these states below this point have the TCP connection established
|
|
|
|
and the score protocol is exchanging information. */
|
|
|
|
GAME_NETWORK_WAITING_FOR_HELLO,
|
|
|
|
GAME_NETWORK_REQUEST_SCORES,
|
|
|
|
GAME_NETWORK_WAITING_FOR_SCORES,
|
2021-06-04 04:41:11 +00:00
|
|
|
GAME_NETWORK_SET_HIGH_SCORE,
|
2021-06-02 03:53:52 +00:00
|
|
|
GAME_NETWORK_WAITING_FOR_SCORE_ACK,
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
GAME_NETWORK_CLOSING_TCP,
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
NUM_GAME_NETWORK_STATES
|
2021-06-01 04:35:47 +00:00
|
|
|
} tGameNetworkState;
|
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
typedef void (*tGameNetworkStateHandler)(void);
|
2021-06-06 03:34:30 +00:00
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
typedef struct tGameNetworkGlobals {
|
|
|
|
Boolean networkStartedConnected;
|
2023-06-09 00:04:22 +00:00
|
|
|
tNSGSHighScoreInitParams initParams;
|
2021-06-04 04:41:11 +00:00
|
|
|
tGameNetworkState gameNetworkState;
|
|
|
|
dnrBuffer domainNameResolution;
|
|
|
|
srBuff tcpStatus;
|
|
|
|
Word ipid;
|
|
|
|
rrBuff readResponseBuf;
|
|
|
|
tHelloResponse helloResponse;
|
|
|
|
uint32_t bytesRead;
|
|
|
|
md5WorkBlock hashWorkBlock;
|
|
|
|
uint32_t secrets[3];
|
|
|
|
tHighScoreRequestWithHash highScoreRequest;
|
2023-06-12 02:51:21 +00:00
|
|
|
tScoresResponse highScoreResponse;
|
2021-06-04 04:41:11 +00:00
|
|
|
Boolean hasHighScoreToSend;
|
2023-06-12 02:51:21 +00:00
|
|
|
tSetHighScoreRequestWithHash setHighScoreRequest;
|
2021-06-04 04:41:11 +00:00
|
|
|
tStatusResponse setHighScoreResponse;
|
2021-06-06 03:34:30 +00:00
|
|
|
uint16_t errorCode;
|
|
|
|
uint16_t timeout;
|
2023-06-12 02:51:21 +00:00
|
|
|
Boolean hasGlobalHighScores;
|
2021-06-04 04:41:11 +00:00
|
|
|
} tGameNetworkGlobals;
|
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
// Forward declarations
|
|
|
|
|
|
|
|
static void handleConnectFailed(void);
|
|
|
|
static void handleUnconnected(void);
|
|
|
|
static void handleConnected(void);
|
|
|
|
static void handleResolvingName(void);
|
|
|
|
static void handleLookupFailed(void);
|
|
|
|
static void handleSocketError(void);
|
|
|
|
static void handleProtocolFailed(void);
|
|
|
|
static void handleFailure(void);
|
|
|
|
static void handleTcpUnconnected(void);
|
|
|
|
static void handleWaitingForTcp(void);
|
|
|
|
static void handleWaitingForHello(void);
|
|
|
|
static void handleRequestScores(void);
|
|
|
|
static void handleWaitingForScores(void);
|
|
|
|
static void handleSetHighScore(void);
|
|
|
|
static void handleWaitingForScoreAck(void);
|
|
|
|
static void handleClosingTcp(void);
|
2021-06-01 04:35:47 +00:00
|
|
|
|
|
|
|
// Globals
|
|
|
|
|
2023-06-08 05:15:54 +00:00
|
|
|
#if __ORCAC__
|
|
|
|
segment "highscores";
|
|
|
|
#endif
|
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
static tGameNetworkStateHandler handlers[NUM_GAME_NETWORK_STATES] = {
|
|
|
|
handleConnectFailed,
|
|
|
|
handleUnconnected,
|
|
|
|
|
|
|
|
handleConnected,
|
|
|
|
handleResolvingName,
|
|
|
|
|
|
|
|
handleLookupFailed,
|
|
|
|
handleSocketError,
|
|
|
|
handleProtocolFailed,
|
|
|
|
handleFailure,
|
|
|
|
|
|
|
|
handleTcpUnconnected,
|
|
|
|
|
|
|
|
handleWaitingForTcp,
|
|
|
|
|
|
|
|
handleWaitingForHello,
|
|
|
|
handleRequestScores,
|
|
|
|
handleWaitingForScores,
|
|
|
|
handleSetHighScore,
|
|
|
|
handleWaitingForScoreAck,
|
|
|
|
|
|
|
|
handleClosingTcp
|
|
|
|
};
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
// I am running out of space in the main segment so I am moving these globals into
|
|
|
|
// a dynamically allocated struct. It is only allocated if network capabilities are
|
|
|
|
// detected.
|
|
|
|
static tGameNetworkGlobals * networkGlobals = NULL;
|
|
|
|
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
// Implementation
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
void NSGS_InitNetwork(tNSGSHighScoreInitParams * params)
|
2021-06-01 04:35:47 +00:00
|
|
|
{
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals = NULL;
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2022-05-26 01:50:38 +00:00
|
|
|
if ((params->scoreServer == NULL) ||
|
|
|
|
(params->scorePort == 0) ||
|
|
|
|
(params->waitForVbl == NULL))
|
2021-06-02 03:13:14 +00:00
|
|
|
return;
|
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
LoadOneTool(54, 0x200); // Load Marinetti
|
|
|
|
if (toolerror())
|
|
|
|
return;
|
|
|
|
|
|
|
|
LoadOneTool(128, 0x103); // Load the Hash toolset
|
|
|
|
if (toolerror()) {
|
|
|
|
UnloadOneTool(54);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TCPIPStartUp();
|
|
|
|
if (toolerror()) {
|
|
|
|
UnloadOneTool(128);
|
|
|
|
UnloadOneTool(54);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hashStartUp();
|
|
|
|
if (toolerror()) {
|
|
|
|
TCPIPShutDown();
|
|
|
|
UnloadOneTool(128);
|
|
|
|
UnloadOneTool(54);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals = malloc(sizeof(tGameNetworkGlobals));
|
|
|
|
if (networkGlobals == NULL) {
|
|
|
|
hashShutDown();
|
|
|
|
TCPIPShutDown();
|
|
|
|
UnloadOneTool(128);
|
|
|
|
UnloadOneTool(54);
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
2021-06-01 04:35:47 +00:00
|
|
|
|
2022-05-26 01:50:38 +00:00
|
|
|
memcpy(&(networkGlobals->initParams), params, sizeof(networkGlobals->initParams));
|
|
|
|
|
2023-06-12 03:33:47 +00:00
|
|
|
if (networkGlobals->initParams.shutdownTimeout == 0)
|
|
|
|
networkGlobals->initParams.shutdownTimeout = DEFAULT_SHUTDOWN_NETWORK_TIMEOUT;
|
|
|
|
if (networkGlobals->initParams.connectTimeout == 0)
|
|
|
|
networkGlobals->initParams.connectTimeout = DEFAULT_TCP_CONNECT_TIMEOUT;
|
|
|
|
if (networkGlobals->initParams.readTimeout == 0)
|
|
|
|
networkGlobals->initParams.readTimeout = DEFAULT_READ_NETWORK_TIMEOUT;
|
|
|
|
if (networkGlobals->initParams.retryTimeout == 0)
|
|
|
|
networkGlobals->initParams.retryTimeout = DEFAULT_NETWORK_RETRY_TIMEOUT;
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals->networkStartedConnected = TCPIPGetConnectStatus();
|
|
|
|
if (networkGlobals->networkStartedConnected) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
2021-06-01 04:35:47 +00:00
|
|
|
} else {
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_UNCONNECTED;
|
2021-06-01 04:35:47 +00:00
|
|
|
}
|
2021-06-02 03:53:52 +00:00
|
|
|
|
2022-05-26 01:50:38 +00:00
|
|
|
networkGlobals->secrets[0] = params->secret1;
|
|
|
|
networkGlobals->secrets[1] = params->secret2;
|
2021-06-04 04:41:11 +00:00
|
|
|
|
|
|
|
networkGlobals->hasHighScoreToSend = FALSE;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->hasGlobalHighScores = FALSE;
|
2021-06-04 04:41:11 +00:00
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.is60Hz = !ReadBParam(hrtz50or60);
|
2021-06-01 04:35:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
void NSGS_ShutdownNetwork(void)
|
2021-06-01 04:35:47 +00:00
|
|
|
{
|
2021-06-04 04:41:11 +00:00
|
|
|
if ((!networkGlobals->networkStartedConnected) &&
|
|
|
|
(networkGlobals->gameNetworkState > GAME_NETWORK_UNCONNECTED)) {
|
2021-06-01 04:35:47 +00:00
|
|
|
TCPIPDisconnect(TRUE, NULL);
|
|
|
|
}
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
free(networkGlobals);
|
|
|
|
|
2021-06-01 04:35:47 +00:00
|
|
|
hashShutDown();
|
|
|
|
TCPIPShutDown();
|
|
|
|
UnloadOneTool(128); // Unload the Hash toolset
|
|
|
|
UnloadOneTool(54); // Unload Marinetti
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-06 03:34:30 +00:00
|
|
|
static void abortConnection(void)
|
|
|
|
{
|
|
|
|
TCPIPAbortTCP(networkGlobals->ipid);
|
|
|
|
TCPIPLogout(networkGlobals->ipid);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
void NSGS_DisconnectNetwork(void)
|
2021-06-06 03:34:30 +00:00
|
|
|
{
|
|
|
|
if (networkGlobals == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
|
|
|
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_CLOSING_TCP) {
|
|
|
|
TCPIPCloseTCP(networkGlobals->ipid);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
2021-06-06 03:34:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2021-06-04 04:41:11 +00:00
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
while ((networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED) &&
|
|
|
|
(networkGlobals->gameNetworkState != GAME_NETWORK_FAILURE)) {
|
|
|
|
networkGlobals->initParams.waitForVbl();
|
|
|
|
NSGS_PollNetwork();
|
2021-06-04 04:41:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
static void handleConnectFailed(void)
|
|
|
|
{
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->initParams.displayError != NULL)
|
|
|
|
networkGlobals->initParams.displayError(NSGS_CONNECT_ERROR, networkGlobals->errorCode);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
2021-06-04 04:41:11 +00:00
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
static void handleUnconnected(void)
|
2021-06-01 04:35:47 +00:00
|
|
|
{
|
2023-06-07 23:53:14 +00:00
|
|
|
if (networkGlobals->initParams.displayConnectionString != NULL)
|
|
|
|
networkGlobals->initParams.displayConnectionString(TRUE);
|
|
|
|
TCPIPConnect(NULL);
|
|
|
|
if ((!toolerror()) &&
|
|
|
|
(TCPIPGetConnectStatus())) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
|
|
|
} else {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECT_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = toolerror();
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
if (networkGlobals->initParams.displayConnectionString != NULL)
|
|
|
|
networkGlobals->initParams.displayConnectionString(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleConnected(void)
|
|
|
|
{
|
2023-06-08 05:15:54 +00:00
|
|
|
TCPIPDNRNameToIP((char *)networkGlobals->initParams.scoreServer, &(networkGlobals->domainNameResolution));
|
2023-06-07 23:53:14 +00:00
|
|
|
if (toolerror()) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
|
|
|
networkGlobals->errorCode = toolerror();
|
|
|
|
} else
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_RESOLVING_NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleResolvingName(void)
|
|
|
|
{
|
|
|
|
if (networkGlobals->domainNameResolution.DNRstatus == DNR_Pending)
|
2021-06-01 04:35:47 +00:00
|
|
|
return;
|
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
if (networkGlobals->domainNameResolution.DNRstatus != DNR_OK) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
|
|
|
networkGlobals->errorCode = networkGlobals->domainNameResolution.DNRstatus;
|
|
|
|
return;
|
|
|
|
}
|
2021-06-02 03:13:14 +00:00
|
|
|
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleLookupFailed(void)
|
|
|
|
{
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->initParams.displayError != NULL)
|
|
|
|
networkGlobals->initParams.displayError(NSGS_LOOKUP_ERROR, networkGlobals->errorCode);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleSocketError(void)
|
|
|
|
{
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->initParams.displayError != NULL)
|
|
|
|
networkGlobals->initParams.displayError(NSGS_SOCKET_ERROR, networkGlobals->errorCode);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.retryTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleProtocolFailed(void)
|
|
|
|
{
|
|
|
|
abortConnection();
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->initParams.displayError != NULL)
|
|
|
|
networkGlobals->initParams.displayError(NSGS_PROTOCOL_ERROR, networkGlobals->errorCode);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.retryTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleFailure(void)
|
|
|
|
{
|
|
|
|
// All of the different failure modes except protocol failure above end up here ultimately. And the state
|
|
|
|
// machine stays here once it arrives here.
|
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
|
|
|
if (networkGlobals->timeout == 0)
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleTcpUnconnected(void)
|
|
|
|
{
|
2023-06-12 02:51:21 +00:00
|
|
|
if ((networkGlobals->hasGlobalHighScores) &&
|
|
|
|
(!networkGlobals->hasHighScoreToSend)) {
|
|
|
|
if (networkGlobals->initParams.shouldRefreshHighScores == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!networkGlobals->initParams.shouldRefreshHighScores())
|
|
|
|
return;
|
|
|
|
}
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
networkGlobals->ipid = TCPIPLogin(networkGlobals->initParams.userId, networkGlobals->domainNameResolution.DNRIPaddress, networkGlobals->initParams.scorePort, 0, 64);
|
|
|
|
if (toolerror()) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
networkGlobals->errorCode = toolerror();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->errorCode = TCPIPOpenTCP(networkGlobals->ipid);
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
TCPIPLogout(networkGlobals->ipid);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_TCP;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.connectTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleWaitingForTcp(void)
|
|
|
|
{
|
|
|
|
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((networkGlobals->tcpStatus.srState == TCPSSYNSENT) ||
|
|
|
|
(networkGlobals->tcpStatus.srState == TCPSSYNRCVD)) {
|
2021-06-28 04:03:32 +00:00
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
2021-06-01 04:35:47 +00:00
|
|
|
} else {
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_TCP_CONNECT_TIMEOUT_ERROR;
|
2021-06-02 03:13:14 +00:00
|
|
|
}
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (networkGlobals->tcpStatus.srState != TCPSESTABLISHED) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->errorCode = networkGlobals->tcpStatus.srState | 0x8000;
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_HELLO;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->bytesRead = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleWaitingForHello(void)
|
|
|
|
{
|
|
|
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
|
|
|
((uint32_t)(&(networkGlobals->helloResponse))) + networkGlobals->bytesRead,
|
|
|
|
sizeof(networkGlobals->helloResponse) - networkGlobals->bytesRead,
|
|
|
|
&(networkGlobals->readResponseBuf));
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
|
|
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->helloResponse)) {
|
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
|
|
|
} else {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HELLO_TIMEOUT_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->helloResponse)) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HELLO_TOO_BIG_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (networkGlobals->helloResponse.responseType != RESPONSE_TYPE_HELLO) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HELLO_UNEXPECTED_RESPONSE_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->secrets[2] = networkGlobals->helloResponse.nonce;
|
|
|
|
if (networkGlobals->hasHighScoreToSend) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SET_HIGH_SCORE;
|
2023-06-12 02:51:21 +00:00
|
|
|
} else if ((!networkGlobals->hasGlobalHighScores) ||
|
|
|
|
((networkGlobals->initParams.shouldRefreshHighScores != NULL) &&
|
|
|
|
(networkGlobals->initParams.shouldRefreshHighScores()))) {
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
|
|
|
} else {
|
|
|
|
TCPIPCloseTCP(networkGlobals->ipid);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleRequestScores(void)
|
|
|
|
{
|
|
|
|
networkGlobals->highScoreRequest.highScoreRequest.requestType = REQUEST_TYPE_GET_HIGH_SCORES;
|
|
|
|
|
|
|
|
md5Init(&(networkGlobals->hashWorkBlock));
|
|
|
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
|
|
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.highScoreRequest), sizeof(networkGlobals->highScoreRequest.highScoreRequest));
|
2023-06-08 05:15:54 +00:00
|
|
|
md5Finish(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.md5Digest[0]));
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->highScoreRequest), sizeof(networkGlobals->highScoreRequest), FALSE, FALSE);
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORES;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->bytesRead = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleWaitingForScores(void)
|
|
|
|
{
|
|
|
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
2023-06-12 02:51:21 +00:00
|
|
|
((uint32_t)(&networkGlobals->highScoreResponse)) + networkGlobals->bytesRead,
|
|
|
|
sizeof(networkGlobals->highScoreResponse) - networkGlobals->bytesRead,
|
2023-06-07 23:53:14 +00:00
|
|
|
&(networkGlobals->readResponseBuf));
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->highScoreResponse)) {
|
2023-06-07 23:53:14 +00:00
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
|
|
|
} else {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_TIMEOUT_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->highScoreResponse)) {
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_TOO_BIG_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
if (networkGlobals->highScoreResponse.responseType != RESPONSE_TYPE_SCORES) {
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->hasGlobalHighScores = TRUE;
|
|
|
|
if (networkGlobals->initParams.setHighScores != NULL)
|
|
|
|
networkGlobals->initParams.setHighScores(&(networkGlobals->highScoreResponse.highScores));
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
TCPIPCloseTCP(networkGlobals->ipid);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void handleSetHighScore(void)
|
|
|
|
{
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.requestType = REQUEST_TYPE_SET_SCORE;
|
|
|
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.who[3] = '\0';
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
md5Init(&(networkGlobals->hashWorkBlock));
|
|
|
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
2023-06-12 02:51:21 +00:00
|
|
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->setHighScoreRequest.setHighScoreRequest), sizeof(networkGlobals->setHighScoreRequest.setHighScoreRequest));
|
|
|
|
md5Finish(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->setHighScoreRequest.md5Digest[0]));
|
2023-06-07 23:53:14 +00:00
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->setHighScoreRequest), sizeof(networkGlobals->setHighScoreRequest), FALSE, FALSE);
|
2023-06-07 23:53:14 +00:00
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORE_ACK;
|
2023-06-12 03:33:47 +00:00
|
|
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
2023-06-07 23:53:14 +00:00
|
|
|
networkGlobals->bytesRead = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleWaitingForScoreAck(void)
|
|
|
|
{
|
|
|
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
|
|
|
((uint32_t)(&(networkGlobals->setHighScoreResponse))) + networkGlobals->bytesRead,
|
|
|
|
sizeof(networkGlobals->setHighScoreResponse) - networkGlobals->bytesRead,
|
|
|
|
&(networkGlobals->readResponseBuf));
|
|
|
|
if (networkGlobals->errorCode != tcperrOK) {
|
|
|
|
abortConnection();
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
|
|
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->setHighScoreResponse)) {
|
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
|
|
|
} else {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_SET_SCORE_TIMEOUT_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->setHighScoreResponse)) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_SET_SCORE_TOO_BIG_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (networkGlobals->setHighScoreResponse.responseType != RESPONSE_TYPE_STATUS) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_SET_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!networkGlobals->setHighScoreResponse.success) {
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
2023-06-12 02:51:21 +00:00
|
|
|
networkGlobals->errorCode = NSGS_SET_SCORE_FAILED_ERROR;
|
2023-06-07 23:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
networkGlobals->hasHighScoreToSend = FALSE;
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handleClosingTcp(void)
|
|
|
|
{
|
|
|
|
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
|
|
|
if ((networkGlobals->tcpStatus.srState != TCPSCLOSED) &&
|
|
|
|
(networkGlobals->tcpStatus.srState != TCPSTIMEWAIT)) {
|
|
|
|
if (networkGlobals->timeout > 0) {
|
|
|
|
networkGlobals->timeout--;
|
|
|
|
} else {
|
|
|
|
abortConnection();
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
2023-06-07 23:53:14 +00:00
|
|
|
}
|
|
|
|
return;
|
2021-06-01 04:35:47 +00:00
|
|
|
}
|
2023-06-07 23:53:14 +00:00
|
|
|
|
|
|
|
TCPIPLogout(networkGlobals->ipid);
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
|
|
}
|
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
void NSGS_PollNetwork(void)
|
2023-06-07 23:53:14 +00:00
|
|
|
{
|
|
|
|
if (networkGlobals == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TCPIPPoll();
|
|
|
|
|
|
|
|
handlers[networkGlobals->gameNetworkState]();
|
2021-06-01 04:35:47 +00:00
|
|
|
}
|
2021-06-02 03:53:52 +00:00
|
|
|
|
|
|
|
|
2023-06-09 00:04:22 +00:00
|
|
|
BOOLEAN NSGS_CanSendHighScore(void)
|
2021-06-02 03:53:52 +00:00
|
|
|
{
|
2021-06-04 04:41:11 +00:00
|
|
|
if (networkGlobals == NULL)
|
2021-06-28 04:03:32 +00:00
|
|
|
return FALSE;
|
2021-06-02 03:53:52 +00:00
|
|
|
|
2021-06-28 04:03:32 +00:00
|
|
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED) {
|
|
|
|
if ((networkGlobals->gameNetworkState == GAME_NETWORK_FAILURE) &&
|
|
|
|
(networkGlobals->timeout > 0))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
BOOLEAN NSGS_SendHighScore(const char * who, unsigned long score)
|
2021-06-28 04:03:32 +00:00
|
|
|
{
|
|
|
|
uint16_t cycleCount = 0;
|
2021-06-02 03:53:52 +00:00
|
|
|
|
2023-06-12 02:51:21 +00:00
|
|
|
if (strlen(who) != 3)
|
|
|
|
return FALSE;
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
networkGlobals->hasHighScoreToSend = TRUE;
|
2023-06-12 02:51:21 +00:00
|
|
|
memcpy(networkGlobals->setHighScoreRequest.setHighScoreRequest.who, who, sizeof(networkGlobals->setHighScoreRequest.setHighScoreRequest.who));
|
|
|
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.score = score;
|
2021-06-02 03:53:52 +00:00
|
|
|
|
2021-06-28 04:03:32 +00:00
|
|
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED)
|
|
|
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
|
|
|
2021-06-04 04:41:11 +00:00
|
|
|
do {
|
2022-05-26 01:50:38 +00:00
|
|
|
networkGlobals->initParams.waitForVbl();
|
2023-06-09 00:04:22 +00:00
|
|
|
NSGS_PollNetwork();
|
2021-06-28 04:03:32 +00:00
|
|
|
cycleCount++;
|
|
|
|
|
|
|
|
if ((cycleCount & 0x7) == 0) {
|
|
|
|
switch (cycleCount & 0x18) {
|
|
|
|
case 0x00:
|
2022-05-26 01:50:38 +00:00
|
|
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
|
|
networkGlobals->initParams.uploadSpin(0);
|
2021-06-28 04:03:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x08:
|
2022-05-26 01:50:38 +00:00
|
|
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
|
|
networkGlobals->initParams.uploadSpin(1);
|
2021-06-28 04:03:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x10:
|
2022-05-26 01:50:38 +00:00
|
|
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
|
|
networkGlobals->initParams.uploadSpin(2);
|
2021-06-28 04:03:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x18:
|
2022-05-26 01:50:38 +00:00
|
|
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
|
|
networkGlobals->initParams.uploadSpin(3);
|
2021-06-28 04:03:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-06-04 04:41:11 +00:00
|
|
|
} while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED);
|
2021-06-28 04:03:32 +00:00
|
|
|
|
2021-06-29 03:12:06 +00:00
|
|
|
if (networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED)
|
|
|
|
return FALSE;
|
|
|
|
|
2022-05-26 02:58:53 +00:00
|
|
|
if (networkGlobals->initParams.scorePosition != NULL)
|
|
|
|
networkGlobals->initParams.scorePosition(networkGlobals->setHighScoreResponse.position,
|
|
|
|
networkGlobals->setHighScoreResponse.numberOfScores);
|
2021-06-29 03:12:06 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2021-06-02 03:53:52 +00:00
|
|
|
}
|