int Server_ReceiveSystemVersion(ServerState *state) { unsigned char opCode; Logmsg("Server_ReceiveSystemVersion\n"); if(Server_TReadDataSync(state->session, 1, (Ptr)&opCode ) != noErr) return(kServerFuncAbort); if(opCode != msSystemVersion){ // f****d Logmsg("Wrong opCode. Expected %d, got %d\n", msSystemVersion, opCode); return(kServerFuncAbort); } Server_TReadDataSync( state->session, 2, (Ptr)&state->systemVersionData.length ); Server_TReadDataSync( state->session, 4, (Ptr)&state->systemVersionData.version ); if(Server_TCheckError() != noErr) return(kServerFuncAbort); state->validFlags |= kServerValidFlag_SystemVersion; Logmsg("length = %d, version = %ld\n", state->systemVersionData.length, state->systemVersionData.version); Logmsg("Server_ReceiveSystemVersion done\n"); return(kServerFuncOK); }
int Server_EndCommunication(ServerState *state) { unsigned char opCode; Logmsg("Server_EndCommunication\n"); if(Server_DebugService(state) != kServerFuncOK) return(kServerFuncAbort); opCode = msEndOfStream; Server_TWriteDataSync(state->session, 1, (Ptr)&opCode ); Server_TReadDataSync( state->session, 1, (Ptr)&opCode ); if(Server_TCheckError() != noErr) return(kServerFuncAbort); if(opCode != msEndOfStream) { // // Even though this is end of service, I'll return an abort just for fun. // Logmsg("Error: Box didn't respond to msEndOfStream with its own msEndOfStream\n"); return(kServerFuncAbort); } Logmsg("Server_EndCommunication done\n"); return(kServerFuncOK); }
int Server_ProcessSendQ(ServerState *state) { short i; QItem *item; Mail *mail; GameResult *gameResult; Logmsg("Server_ProcessSendQ:\n"); for(i = 0; i < state->sendQData.count; i++) { item = &state->sendQData.items[i]; // // there are no types anymore, just a DBID. 8/4/94 // switch (item->theID) { case kRestartInfoType: // dump the crash record for Andy1 FLogmsg(LOG_CRASH, "RESTART INFO for '%s' (%s) (OS Patch version =%ld) (theID=%ld), size=%ld\n", state->loginData.userID.userName, state->boxPhoneNumber.phoneNumber, state->systemVersionData.version, (long)item->theID, (long)item->size); PrintCrashRecord(item->data, item->size); break; case kChatDebugType: case kDebugChatScriptConst800: // dump the chat script debug for Brian if (item->theID == kChatDebugType) FLogmsg(LOG_DBUG, "CHAT SCRIPT DEBUG X.25 (theID=%ld, size=%ld)\n", (long)item->theID, (long)item->size); else FLogmsg(LOG_DBUG, "CHAT SCRIPT DEBUG 800 (theID=%ld, size=%ld)\n", (long)item->theID, (long)item->size); FLogmsg(LOG_DBUG, "SCRIPT INFO for '%s' (%s) (theID=%ld), size=%ld\n", state->loginData.userID.userName, state->boxPhoneNumber.phoneNumber, (long)item->theID, (long)item->size); FLoghexdump(LOG_DBUG, item->data, item->size); break; case kGameResultDataDBID: // dump the game results for Steve FLogmsg(LOG_GAMERESULT, "GAME RESULTS for '%s' (%s) (theID=%ld), size=%ld\n", state->loginData.userID.userName, state->boxPhoneNumber.phoneNumber, (long)item->theID, (long)item->size); DumpJamsStats(item->data, item->size); break; default: // just drop it Logmsg("Server_ProcessSendQ: ignored item with ID %ld\n", (long)item->theID); break; } } Logmsg("Server_ProcessSendQ done\n"); return(kServerFuncOK); }
void ServerState_PrintUserIdentification(const userIdentification *userID) { Logmsg(" User identification:\n"); Logmsg(" Box serial number = (%ld,%ld) [%ld]\n", userID->box.box, userID->box.region, (long)userID->userID); Logmsg(" User name = '%s'\n", userID->userName); Logmsg(" User town = '%s'\n", userID->userTown); Logmsg(" iconID = %ld, colorTableID = %ld\n", (long) userID->ROMIconID, (long)userID->colorTableID); }
void ServerState_Empty(ServerState *state) { Logmsg("ServerState_Empty\n"); if(state->validFlags & kServerValidFlag_Account) { ASSERT(state->account); DataBase_FreeAccount(state->account); state->account = NULL; } if( state->validFlags & kServerValidFlag_SendQ) { long i; for(i = 0; i < state->sendQData.count; i++){ Logmsg(" Item %ld:\n", i); Logmsg(" DBID = %ld, Size = %ld\n", (long)state->sendQData.items[i].theID, state->sendQData.items[i].size); free(state->sendQData.items[i].data); } free(state->sendQData.items); state->sendQData.items = NULL; } if(state->validFlags & kServerValidFlag_AddrValidation) { // BRAIN DAMAGE???? } if(state->validFlags & kServerValidFlag_IncomingMail) { short i; for(i = 0; i < state->incomingMail.count; i++) if(state->incomingMail.mailItems[i].mail) free(state->incomingMail.mailItems[i].mail); if(state->incomingMail.mailItems) free(state->incomingMail.mailItems); state->incomingMail.mailItems = NULL; state->incomingMail.count = 0; } if(state->validFlags & kServerValidFlag_GameResults) { free((Ptr)state->gameResult); } state->validFlags = kServerValidFlag_None; }
int Server_SendSetBoxPhoneNumber(ServerState *state, phoneNumber *newBoxPhoneNumber) { messOut opCode; phoneNumber strippedPhoneNumber; int len; #define STRIP_AREA_CODE #ifdef STRIP_AREA_CODE len = strlen(newBoxPhoneNumber->phoneNumber); if (len < 8 || newBoxPhoneNumber->phoneNumber[len-5] != '-') { Logmsg("Set box phone number: I can't strip %s!\n", newBoxPhoneNumber->phoneNumber); // send original opCode = msSetBoxPhoneNumber; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(phoneNumber), (Ptr)newBoxPhoneNumber); } else { strippedPhoneNumber = *newBoxPhoneNumber; // get the extra fields strcpy(strippedPhoneNumber.phoneNumber, // overwrite with last 8 newBoxPhoneNumber->phoneNumber + strlen(newBoxPhoneNumber->phoneNumber) - 8); opCode = msSetBoxPhoneNumber; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(phoneNumber), (Ptr)&strippedPhoneNumber); } #else opCode = msSetBoxPhoneNumber; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(phoneNumber), (Ptr)newBoxPhoneNumber); #endif return(kServerFuncOK); }
PreformedMessage *DataBase_GetSystemPatch(long version, long patchNum) { SDBSystem *sys; ListNode *node; SDBSystemNode *sn; sys = SDB_GetSystem(gSDB); ASSERT(sys); ASSERT_MESG(patchNum >= 0, "Negative patch numbers are illegal"); node = SearchList(sys->list, version); if(node) { sn = (SDBSystemNode *)GetListNodeData(node); ASSERT_MESG(patchNum < sn->numPatches, "Requested system patch number is out of range"); if(patchNum >= sn->numPatches) return(NULL); // big error return(sn->patches[patchNum]); } //WARNING_MESG("No such system version?!?"); Logmsg("No such system version?!?\n"); return(NULL); }
// Send the player's rankings for every game he has played. // int Server_SendRanking(ServerState *state) { RankingType *rankings; RankingInfo *rankingInfo; messOut opCode; DBID id; unsigned short bodySize; int i; Logmsg("Server_SendRanking\n"); ASSERT(state->validFlags & kServerValidFlag_Account); if (!state->validFlags & kServerValidFlag_Account) return (kFucked); // For every entry in playerAccount.rankings, send them a description // of their rank. // for (i = 0; i < 2; i++) { // BRAIN DAMAGE; should walk a list rankingInfo = &(state->account->playerAccount.rankingInfo[i]); if (!rankingInfo->gameID) continue; rankings = Server_BuildRanking(state, rankingInfo, &bodySize, &id); if (!rankings) continue; opCode = msReceiveRanking; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(DBID), (Ptr)&id); Server_TWriteDataSync(state->session, sizeof(unsigned short), (Ptr)&bodySize); Server_TWriteDataSync(state->session, (long)bodySize, (Ptr)rankings); Logmsg(" Sent rankings for 0x%.8lx (%ld bytes, DBID=%ld)\n", rankings->gameID, (long)bodySize, (long)id); free(rankings); } if(Server_TCheckError() != noErr) return(kServerFuncAbort); Logmsg("Server_SendRanking done\n"); return(kServerFuncOK); }
// // Same as Server_EndCommunication, except doesn't wait for the box to respond with own // msEndOfStream. // // Unused 8/13/94 // int Server_ForceEndCommunication(ServerState *state) { unsigned char opCode; Logmsg("Server_ForceEndCommunication\n"); if(Server_DebugService(state) != kServerFuncOK) return(kServerFuncAbort); opCode = msEndOfStream; Server_TWriteDataSync(state->session, 1, (Ptr)&opCode ); Logmsg("Server_ForceEndCommunication done\n"); return(kServerFuncOK); }
// // Send a new problem token // int Server_SendProblemToken(ServerState *state) { unsigned long token; unsigned char opCode; Logmsg("Server_SendProblemToken\n"); token = 23; opCode = msReceiveProblemToken; Server_TWriteDataSync(state->session, 1, (Ptr)&opCode ); Server_TWriteDataSync(state->session, sizeof(long), (Ptr)&token ); if(Server_TCheckError() != noErr) return(kServerFuncAbort); Logmsg("Server_SendProblemToken done\n"); return(kServerFuncOK); }
int Server_SendDBConstants(ServerState *state, long numConsts, DBID *ids, long *constants) { messOut opCode; Logmsg("Server_SendDBConstants\n"); opCode = msSetConstants; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(long), (Ptr)&numConsts); Server_TWriteDataSync(state->session, sizeof(DBID) * numConsts, (Ptr)ids); Server_TWriteDataSync(state->session, sizeof(long) * numConsts, (Ptr)constants); if(Server_TCheckError() != noErr) return(kServerFuncAbort); Logmsg("Server_SendDBConstants done\n"); return(kServerFuncOK); }
int Server_SendAddItemToDB(ServerState *state, DBType theType, DBID theID, long length, void *data) { messOut opCode; Logmsg("Server_SendAddItemToDB\n"); opCode = msAddItemToDB; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(DBType), (Ptr)&theType); Server_TWriteDataSync(state->session, sizeof(DBID), (Ptr)&theID); Server_TWriteDataSync(state->session, sizeof(long), (Ptr)&length); Server_TWriteDataSync(state->session, length, (Ptr)data); if(Server_TCheckError() != noErr) return(kServerFuncAbort); Logmsg("Server_SendAddItemToDB done\n"); return(kServerFuncOK); }
long DataBase_GetLatestSystemVersion(void) { SDBSystem *sys; ListNode *node; SDBSystemNode *sn; sys = SDB_GetSystem(gSDB); node = GetLastListNode(sys->list); if(node) { sn = (SDBSystemNode *)GetListNodeData(node); return(sn->version); } //WARNING_MESG("No loaded system version?"); Logmsg("No loaded system version?\n"); return(1); }
long DataBase_GetSystemNumPatches(long version) { SDBSystem *sys; ListNode *node; SDBSystemNode *sn; sys = SDB_GetSystem(gSDB); node = SearchList(sys->list, version); if(node) { sn = (SDBSystemNode *)GetListNodeData(node); return(sn->numPatches); } //WARNING_MESG("No such system version?!?"); Logmsg("No such system version?!?\n"); return(0); }
int Server_SendSetLocalAccessPhoneNumber(ServerState *state, phoneNumber *newAccessPhoneNumber, phoneNumber *fallbackAccessPhoneNumber, Boolean redial) { messOut opCode; short dialAgainFlag; opCode = msSetLocalAccessPhoneNumber; Server_TWriteDataSync(state->session, sizeof(messOut), (Ptr)&opCode); Server_TWriteDataSync(state->session, sizeof(phoneNumber), (Ptr)newAccessPhoneNumber); Server_TWriteDataSync(state->session, sizeof(phoneNumber), (Ptr)fallbackAccessPhoneNumber); if(redial) dialAgainFlag = kRedialTheNetwork; else dialAgainFlag = kDontRedialTheNetwork; Server_TWriteDataSync(state->session, sizeof(short), (Ptr)&dialAgainFlag); Logmsg("Sent LocalAccessNumber %s [%d] fallback %s [%d]\n", newAccessPhoneNumber->phoneNumber, newAccessPhoneNumber->scriptID, fallbackAccessPhoneNumber->phoneNumber, fallbackAccessPhoneNumber->scriptID); return(kServerFuncOK); }
int Shutdown(int errorcode, struct cfgoptions *arg) { if (arg->options & NOACTION) { Logmsg(LOG_DEBUG, "shutdown() errorcode=%i, kexec=%s", errorcode, arg->options & KEXEC ? "true" : "false"); return 0; } if (errorcode != WECMDREBOOT && errorcode != WECMDRESET) { char buf[64] = { "\0" }; snprintf(buf, sizeof(buf), "%d\n", errorcode); if (Spawn (arg->repairBinTimeout, arg, arg->exepathname, arg->exepathname, buf, NULL) == 0) return 0; } EndDaemon(arg, true); //point of no return return NativeShutdown(errorcode, arg->options & KEXEC ? 1 : 0); }
int Server_SendNGP() { /* unsigned char opCode; long NGPVersion; Server_TReadDataSync( &aGame, 1, (Ptr)&opCode ); if(opCode != msSendNGPVersion){ // f****d return(kServerFuncAbort); } Server_TReadDataSync( &aGame, 4, (Ptr)&NGPVersion ); Logmsg("NGP version = %ld\n", NGPVersion); Logmsg("Server_SendNGP done\n"); */ Logmsg("Server_SendNGP is totally f****d. kill it!\n"); return(kServerFuncOK); }
Err SDBSystem_LoadSystemPatches(void) { long count, version, patchnum; char str[kSDB_SystemPatchFilenameLength]; PreformedMessage *msg; char noversion; version = 1; patchnum = 0; noversion = 1; count = 0; for(;;) { sprintf(str, "%s.%ld.%ld", kSDB_SystemPatchFilePrefix, version, patchnum); msg = PreformedMessage_ReadFromFile(str); if(!msg) { if(noversion) break; version++; patchnum = 0; noversion = 1; continue; } DataBase_AddSystemPatch(version, patchnum, msg); // appropriates the patch... so we don't delete it here. patchnum++; count++; noversion = 0; } Logmsg("Read %ld patches, latest system version is %ld\n", count, version-1); return(kNoError); }
long DataBase_GetLatestSystemKeyframeVersion(void) { SDBSystem *sys; ListNode *node; SDBSystemNode *sn; sys = SDB_GetSystem(gSDB); // find the latest system version. // if it's not a keyframe, work backwards until we find one. // node = GetLastListNode(sys->list); while(node) { sn = (SDBSystemNode *)GetListNodeData(node); if(sn->keyframe == true) return(sn->version); node = GetPrevListNode(node); } //WARNING_MESG("No keyframe system version?"); Logmsg("No keyframe system version?\n"); return(1); }
void DataBase_ReloadGamePatches(void) { Logmsg("Reloading game patches\n"); DataBase_LoadGamePatches(); }
int Server_StartGamePlay(ServerState *state) { Contestant contestant; userIdentification challengeUserID; Matchup *matchup; RankingInfo *rankingInfo; Err err; char msg[256]; int i; Logmsg("Server_StartGamePlay\n"); ASSERT((state->validFlags & kServerValidFlag_Account)); ASSERT((state->validFlags & kServerValidFlag_ChallengeOrCompete)); if(state->disallowGameConnect) { Logmsg("REJECT: Game connect is disallowed.\n"); return(kServerFuncOK); } if(state->challengeData.userID.box.box == kDownloadOnlyMailSerialNumber) { Statusmsg("SunSega: Mail-only connect from '%s' (%s)\n", state->loginData.userID.userName, state->account->boxAccount.gamePhone.phoneNumber); StatusPrintGameResults(state); return(kServerFuncOK); } // Set up the Contestant struct. // memset(&contestant, 0, sizeof(Contestant)); contestant.gameID = state->gameIDData.gameID; contestant.boxSerialNumber = state->loginData.userID.box; contestant.player = state->loginData.userID.userID; strcpy(contestant.userName, state->loginData.userID.userName); contestant.boxPhoneNumber = state->account->boxAccount.gamePhone; if (state->challengeData.userID.box.box != kFindNetworkOpponentSerialNumber) { contestant.challengeFlags = kSpecificChallenge; } else if (state->challengeData.userID.box.box == kFindNetworkOpponentSerialNumber) { if (state->account->playerAccount.playerFlags & kPlayerFlags_acceptChallenges) contestant.challengeFlags = kAcceptChallenges; else contestant.challengeFlags = kIgnoreChallenges; } else { Logmsg("Invalid state->challengeData.userID.box.box\n"); return (kServerFuncAbort); } contestant.callLongDistance = ((state->account->boxAccount.boxFlags & kBoxFlags_dialLongDistance)!=0); contestant.romID = state->boxOSState.boxType; // not used anymore // The "opp" fields get the desired opponent's identification if it's // a specific match request, or the previous opponent's identification // if it's an auto-match request. // if (contestant.challengeFlags == kSpecificChallenge) { // specific request // contestant.oppBoxSerialNumber = state->challengeData.userID.box; contestant.oppPlayer = state->challengeData.userID.userID; // he wants to challenge a specific player. // check if that is a valid playerID. if (DataBase_FindUserIdentification(&state->challengeData.userID, &challengeUserID) != kNoError) { // Barf back to the dude... no such user. sprintf(msg, "There is no player named %s on XBAND. You have not been registered to play.", state->challengeData.userID.userName); Server_SendDialog(state, msg, true); return(kServerFuncOK); } // Do UserIDs match exactly? (box + player#) if (Database_CompareUserIdentifications(&challengeUserID, &state->loginData.userID)) { Server_SendDialog(state, "Come on - you can't play yourself! You have not been registered to play.", true); return(kServerFuncOK); } // Do the BoxSerialNumbers match? (just box) if (Database_CompareBoxSerialNumbers(&challengeUserID.box, &state->loginData.userID.box)) { Server_SendDialog(state, "You can't play against someone on your own box! You have not been registered to play.", true); return(kServerFuncOK); } contestant.oppBoxSerialNumber = challengeUserID.box; contestant.oppPlayer = challengeUserID.userID; } else { // auto-match requests // // BRAIN DAMAGE: fill this in correctly contestant.oppBoxSerialNumber.box = -1; contestant.oppBoxSerialNumber.region = -1; contestant.oppPlayer = -1; } // The "rankingInfo" field needs the ranking data for this game, if // any. If the user has never played before, we need to pass in a // zeroed-out rankingInfo struct with a correct gameID. // // BRAIN DAMAGE: use the fake rankingInfo stuff for now // for (i = 0; i < 2; i++) { rankingInfo = &(state->account->playerAccount.rankingInfo[i]); if (rankingInfo->gameID == contestant.gameID) { contestant.rankingInfo = *rankingInfo; break; } } if (i == 2) { Logmsg("No rankingInfo for gameID 0x%.8lx, passing in empty one\n", contestant.gameID); memset(&contestant.rankingInfo, 0, sizeof(RankingInfo)); contestant.rankingInfo.gameID = contestant.gameID; } // One-stop shopping. // matchup = RPC_FindMatch(&contestant); if (matchup == NULL) { // wow sprintf(msg, "Player matching appears to be down. Try again later."); Server_SendDialog(state, msg, true); return(kServerFuncOK); } // If we got a phone number back (or even if we didn't), and the // "dial 9 to get out" hack is in effect, prepend "9,". if (state->account->boxAccount.debug1 & 1) { phoneNumber tmpPhoneNumber; strcpy(tmpPhoneNumber.phoneNumber, matchup->oppPhoneNumber.phoneNumber); strcpy(matchup->oppPhoneNumber.phoneNumber, "9,"); strcat(matchup->oppPhoneNumber.phoneNumber, tmpPhoneNumber.phoneNumber); } // Generic errors. // if (matchup->result == kInvalidArguments) { sprintf(msg, "Looks like something is messed up in the server. Unable to match you with anyone."); Server_SendDialog(state, msg, true); return(kServerFuncOK); } if (matchup->result == kInvalidPhoneNumber) { sprintf(msg, "Looks like something is messed up in the server. The matcher can't understand your phone number."); Server_SendDialog(state, msg, true); return(kServerFuncOK); } // Handle errors based on what we tried to do. // if (contestant.challengeFlags == kSpecificChallenge) { // Was a specific match request. // if (matchup->result == kMatchDial) { Logmsg("*** Sending Opponent Phone Number : %s (cookie=%ld)\n", matchup->oppPhoneNumber.phoneNumber, matchup->oppMagicCookie); Statusmsg("SunSega: '%s' (%s) told to challenge '%s' (%s) for %s\n", contestant.userName, contestant.boxPhoneNumber.phoneNumber, matchup->oppUserName, matchup->oppPhoneNumber.phoneNumber, Common_GameName(contestant.gameID)); StatusPrintGameResults(state); Server_SendOpponentNameString(state, matchup->oppUserName); return (Server_SendOpponentPhoneNumber(state, &matchup->oppPhoneNumber, matchup->oppMagicCookie)); } if (matchup->result == kChallengeeWaitingForDifferentGame) { sprintf(msg, "You can't play %s, because they have a different game cartridge installed. You have not been registered to play.", challengeUserID.userName); Server_SendDialog(state, msg, true); return(kServerFuncOK); } if (matchup->result == kChallengeeWaitingForDifferentUser) { sprintf(msg, "You can't play %s, because they have registered to play someone else. You have not been registered to play.", challengeUserID.userName); Server_SendDialog(state, msg, true); return(kServerFuncOK); } if (matchup->result == kChallengeeWaitingForAutoMatch) { // BRAIN DAMAGE. If the other player accepts challenges, we should match you together. // sprintf(msg, "You can't play %s, because they are waiting to play a challenge game. You have not been registered to play.", challengeUserID.userName); Server_SendLargeDialog(state, msg, true); return(kServerFuncOK); } if (matchup->result == kDifferentRomVersion) { sprintf(msg, "You can't play %s, because they have a different XBAND ROM revision.", challengeUserID.userName); Server_SendDialog(state, msg, true); return(kServerFuncOK); } if (matchup->result != kMatchWait) { Logmsg("specific-Matching_FindMatch returned error %ld\n", matchup->result); sprintf(msg, "Your challenge request could not be completed\n"); Server_SendDialog(state, msg, true); return(kServerFuncOK); } // bummer. that dude isn't online, fall out into wait handler } else { // Was an auto-match request. // if (matchup->result == kMatchDial) { Logmsg("*** Sending Opponent Phone Number : %s (cookie=%ld)\n", matchup->oppPhoneNumber.phoneNumber, matchup->oppMagicCookie); Statusmsg("SunSega: '%s' (%s) told to call '%s' (%s) for %s\n", contestant.userName, contestant.boxPhoneNumber.phoneNumber, matchup->oppUserName, matchup->oppPhoneNumber.phoneNumber, Common_GameName(contestant.gameID)); StatusPrintGameResults(state); Server_SendOpponentNameString(state, matchup->oppUserName); return(Server_SendOpponentPhoneNumber(state, &matchup->oppPhoneNumber, matchup->oppMagicCookie)); } if (matchup->result != kMatchWait) { Logmsg("auto-Matching_FindMatch returned error %ld\n", matchup->result); sprintf(msg, "Your challenge request could not be completed\n"); Server_SendDialog(state, msg, true); return(kServerFuncOK); } } // Used to be sendwaitforopponent // if (matchup->result == kMatchWait) { // Tell the box to wait for a call. // Logmsg("@@@ Wait For Opponent (my cookie=%ld)\n", matchup->magicCookie); if (contestant.challengeFlags == kSpecificChallenge) { Statusmsg("SunSega: '%s' (%s) waiting for %s challenge with %s\n", contestant.userName, contestant.boxPhoneNumber.phoneNumber, Common_GameName(contestant.gameID), challengeUserID.userName); StatusPrintGameResults(state); } else { Statusmsg("SunSega: '%s' (%s) waiting for %s\n", contestant.userName, contestant.boxPhoneNumber.phoneNumber, Common_GameName(contestant.gameID)); StatusPrintGameResults(state); } err = Server_SendWaitForOpponent(state, matchup->magicCookie); if (err == kServerFuncOK) { char gameName[kGameNameSize]; if (!DataBase_GetGameName(contestant.gameID, gameName)) { Logmsg("Server_StartGamePlay Impl Error: game 0x%.8lx has no name in the DB??\n", contestant.gameID); gameName[0] = 0; } if (contestant.challengeFlags != kSpecificChallenge) { err = Server_SendRegisterPlayer(state, kBoxWaitForOpponentTimeout, gameName); } else { err = Server_SendRegisterChallengePlayer(state, kBoxWaitForOpponentTimeout, gameName, challengeUserID.userName); } return(err); } else { Logmsg("Server_SendWaitForOpponent returned error %ld\n", err); return(kServerFuncAbort); } } }
void ServerState_Print(ServerState *state) { if(state->validFlags & kServerValidFlag_Login) { Logmsg("Login Data:\n"); ServerState_PrintUserIdentification(&state->loginData.userID); Logmsg(" Phone number = %s\n", state->boxPhoneNumber.phoneNumber); } else Logmsg("Login Data is invalid\n"); if(state->validFlags & kServerValidFlag_ChallengeOrCompete) { if(state->challengeData.userID.box.box == -3) { Logmsg("Mail only connection\n"); //Statusmsg("SunSega: Mail-only connect from '%s' (%s)\n", // state->loginData.userID.userName, // state->boxPhoneNumber.phoneNumber); //StatusPrintGameResults(state); } else if(state->challengeData.userID.box.box == -2) Logmsg("Normal competitive game request\n"); else { Logmsg("Challenge Request:\n"); ServerState_PrintUserIdentification(&state->challengeData.userID); } } else Logmsg("ChallengeOrCompete is invalid\n"); if(state->validFlags & kServerValidFlag_SystemVersion) { Logmsg("System Version:\n"); Logmsg(" length = %d, version = %ld\n", state->systemVersionData.length, state->systemVersionData.version); } else Logmsg("System Version is invalid\n"); if(state->validFlags & kServerValidFlag_NGPVersion) { Logmsg("NGP Version = %ld\n", state->NGPVersion); } else Logmsg("NGP Version is invalid\n"); if(state->validFlags & kServerValidFlag_GameID) { Logmsg("Game ID:\n"); Logmsg(" gameID = 0x%.8lx, version = %ld\n", state->gameIDData.gameID, state->gameIDData.version); } else Logmsg("Game ID is invalid\n"); if( state->validFlags & kServerValidFlag_SendQ) { long i; Logmsg("SendQ Count = %d:\n", state->sendQData.count); for(i = 0; i < state->sendQData.count; i++){ Logmsg(" Item %ld:\n", i); Logmsg(" Type = %ld, Size = %ld\n", (long)state->sendQData.items[i].theID, state->sendQData.items[i].size); } } else Logmsg("SendQ is invalid\n"); if(state->validFlags & kServerValidFlag_IncomingMail) { Logmsg("Incoming Mail count = %ld\n", (long)state->incomingMail.count); } }
/* This treat can use the info in ServerState to do lookups to send targetted information such as: ranking specicific mail game specific info (eg. realtime NBA scores and stats) ads */ int Server_DownloadKoolStuff(ServerState *state) { PreformedMessage *preformed; ServerNewsPage *page; long numPages, a, b; OSErr err; DBType pagetype; DBID id; long countdown; Boolean sentNews = false; Logmsg("Server_DownloadKoolStuff\n"); if(Server_DebugService(state) != kServerFuncOK) return(kServerFuncAbort); // ///////////////////////////////////////// // // BRAIN DAMAGE. // Set some DBConstants for ted. These should be done by Topping's tool. // id = kListenCallWaitingTimeConst; countdown = 5; if(Server_SendDBConstants(state, 1, &id, &countdown) != kServerFuncOK) return(kServerFuncAbort); id = kDBTransportTickleConst; countdown = 5; if(Server_SendDBConstants(state, 1, &id, &countdown) != kServerFuncOK) return(kServerFuncAbort); // ///////////////////////////////////////// // Server_SetTransportHold(true); id = kNewsCountdownConst; countdown = 60L << 16; // ticks per count countdown |= 30; // the count value (30 sec) if(Server_SendDBConstants(state, 1, &id, &countdown) != kServerFuncOK) return(kServerFuncAbort); // // Send the general daily news (everyone gets this) // Send the targetted Other news (game specific, etc) // //abort(); // makes TransportLayer blow up cuz TUUnthread never called if error is found by TIndication for(b = 0; b < 2; b++) { if(b == 1) pagetype = kOtherNews; else pagetype = kDailyNews; numPages = DataBase_GetNumNewsPages(pagetype); if (numPages < 0 || numPages > 64) { Logmsg("ERROR: got bogus numPages %ld in Server_DownloadKoolStuff\n", numPages); return (kServerFuncAbort); } for(a = 0; a < numPages; a++) { sentNews = true; page = DataBase_GetNewsPage(a, pagetype); ASSERT(page); if(!a) err = Server_SendFirstNewsPage( state, page); else err = Server_SendNewsPage(state, page); DataBase_ReleaseServerNewsPage( page); if(err != kServerFuncOK) return(kServerFuncAbort); } } if(!sentNews) Server_SendNoNewsPage(state, kDailyNews); // Box doesn't care about the pagetype, so anything will do. // // If you want to speed up the countdown, you can change the ticks per count. // The count value cannot be changed after the timer starts. // countdown = 60L << 16; // ticks per count (you would change this to change tick speed) countdown |= 120; // the count value (ignored after timer is started) if(Server_SendDBConstants(state, 1, &id, &countdown) != kServerFuncOK) return(kServerFuncAbort); Server_SetTransportHold(false); /* preformed = DataBase_GetKoolStuff(); if(preformed) { // BROKEN NOGGIN.... // Server_SendPreformedMessage(state, preformed); DataBase_ReleasePreformedMessage(preformed); } */ return(kServerFuncOK); }
// Given the player's current standings, generate the ranking data. // Returns a pointer to newly malloc()ed memory, which must be freed // by the caller. // // Returns NULL if unable to complete the request. // RankingType *Server_BuildRanking(ServerState *state, RankingInfo *rankingInfo, unsigned short *bodySize, DBID *idp) { RankingType *rankings, metric; GameInfo *gameInfo; long numGames, gameID; int i, gm, rk, nextrk; char numBuf1[11], numBuf2[11], strBuf[64]; char *vector[kNumRankStrings]; unsigned char *ucp, *metric1, *metric2; unsigned short *usp; unsigned short size; if ((gameInfo = Common_GetGameInfo(&numGames)) == NULL) { Logmsg("WHOA: couldn't get GameInfo; Very Bad\n"); return (NULL); } gameID = rankingInfo->gameID; // ID to search for; affected by aliases for (gm = 0; gm < numGames; gm++) { if (gameInfo[gm].gameID == gameID) { if (gameInfo[gm].alias != 0) { // found an alias; change gameID and start over gameID = gameInfo[gm].alias; gm = -1; continue; } // found the game, find the right rank for (rk = 0; rk < gameInfo[gm].numRanks; rk++) { if (gameInfo[gm].ranks[rk].xpoints > rankingInfo->xpoints) { // we passed it, use the previous one nextrk = rk; rk--; break; } } if (rk == gameInfo[gm].numRanks) { // highest rank? rk--; // make this equal highest rank nextrk = rk; // can't go any higher } break; } } if (gm == numGames) { Logmsg("Unable to find rank chart for %.8lx\n", rankingInfo->gameID); goto bail; } // XBAND Points sprintf(numBuf1, "%d", rankingInfo->xpoints); // Points Needed if (rk == nextrk) strcpy(numBuf2, "---"); // can't go no higher else sprintf(numBuf2, "%d", gameInfo[gm].ranks[nextrk].xpoints - rankingInfo->xpoints); vector[0] = gameInfo[gm].gameName; vector[1] = gameInfo[gm].ranks[rk].rankName; vector[2] = numBuf1; if (rk == nextrk) vector[3] = "---"; // that's all, folks! else vector[3] = gameInfo[gm].ranks[nextrk].rankName; vector[4] = numBuf2; Logmsg("Rank for 0x%.8lx: %s %s %s %s %s\n", rankingInfo->gameID, vector[0], vector[1], vector[2], vector[3], vector[4]); size = 0; for(i = 0; i < kNumRankStrings; i++) size += strlen(vector[i]) + 1; //size += sizeof(RankingType) - 1; // sizeof won't work; it's a 7 byte structure, but sizeof tells us // that it's 8 to keep things happy metric1 = (unsigned char *)&metric; metric2 = (unsigned char *)&(metric.rankData[0]); size += (metric2 - metric1); rankings = (RankingType *)malloc((long)size + kSecretChunk); rankings->gameID = gameID; // use aliased gameID here rankings->userID = state->loginData.userID.userID; PackStrings(rankings->rankData, kNumRankStrings, vector); // Set up the secret rankings. Right now, every game gets two. All // of this stuff has to fit within kSecretChunk bytes. // rankings->numHiddenStats = 2; if (rankings->gameID == kNBAJamGameID || rankings->gameID == 0x39677bdb) rankings->numHiddenStats++; // ATM // first secret rank: total points size += (size & 1); // 16-bit word-align ucp = (unsigned char *)rankings; ucp += size; *ucp++ = 2, size++; // make it a two-key sequence *ucp++ = 0, size++; // pad usp = (unsigned short *) ucp; *usp++ = kUP, size += 2; *usp++ = kUP, size += 2; ucp = (unsigned char *) usp; sprintf(strBuf, "Total points for: %ld, against: %ld", rankingInfo->pointsFor, rankingInfo->pointsAgainst); strcpy((char *)ucp, strBuf); ucp += strlen(strBuf) +1, size += strlen(strBuf) +1; size += (size & 1); // 16-bit word-align // second secret rank: win/loss, and my opinion size += (size & 1); // 16-bit word-align ucp = (unsigned char *)rankings; ucp += size; *ucp++ = 2, size++; // make it a two-key sequence *ucp++ = 0, size++; // pad usp = (unsigned short *) ucp; *usp++ = kUP, size += 2; *usp++ = kDOWN, size += 2; ucp = (unsigned char *) usp; sprintf(strBuf, "Total wins: %ld, losses: %ld", rankingInfo->wins, rankingInfo->losses); if (rankingInfo->wins > rankingInfo->losses) strcat(strBuf, " (you rewl)"); else strcat(strBuf, " (you suck)"); strcpy((char *)ucp, strBuf); ucp += strlen(strBuf) +1, size += strlen(strBuf) +1; size += (size & 1); // 16-bit word-align // third secret rank: only for NBA Jam if (rankings->numHiddenStats > 2) { size += (size & 1); // 16-bit word-align ucp = (unsigned char *)rankings; ucp += size; *ucp++ = 7, size++; // try 7 keys; max is 16 (up/down only sucks) *ucp++ = 0, size++; // pad usp = (unsigned short *) ucp; //*usp++ = kDOWN, size += 2; *usp++ = kDOWN | kLEFT, size += 2; *usp++ = kDOWN, size += 2; *usp++ = kDOWN, size += 2; *usp++ = kDOWN, size += 2; *usp++ = kDOWN, size += 2; *usp++ = kDOWN, size += 2; *usp++ = kUP, size += 2; ucp = (unsigned char *) usp; strcpy(strBuf, "Dave, Brian, & Andy2 were here"); strcpy((char *)ucp, strBuf); ucp += strlen(strBuf) +1, size += strlen(strBuf) +1; size += (size & 1); // 16-bit word-align } // All done! *bodySize = size; *idp = gameInfo[gm].gameID; Common_FreeGameInfo(gameInfo); return (rankings); bail: Common_FreeGameInfo(gameInfo); return (NULL); }
// // Load game patches // void DataBase_LoadGamePatches(void) { PreformedMessage msg; PatchDescriptor descr; GameInfo *gameInfo; SDBGameNode *game; unsigned char *start, *end; FILE *fp = NULL; messOut opCode; char buf[32], *cp; long hdrLength, fullLength; long numGames; int i; if ((fp = fopen(kSDB_GamePatchFile, "rb")) == NULL) { Logmsg("Unable to open game patch file '%s'\n", kSDB_GamePatchFile); goto nofile; } if ((gameInfo = Common_GetGameInfo(&numGames)) == NULL) { // this is Very Bad Logmsg("Unable to get GameInfo\n"); return; } // don't use sizeof(PatchDescriptor); has dangler on end start = (unsigned char *) &descr; end = (unsigned char *) &descr.data; while (1) { // This ought to be done in PreformedMessage.c, somehow. // if (fread(&opCode, sizeof(opCode), 1, fp) != 1) break; if (feof(fp)) break; if (opCode != msGamePatch) { Logmsg("Wrong opCode in game patch file! Wanted %ld, got %ld\n", (long)msGamePatch, (long)opCode); goto nofile; } if (fread(&descr, end-start, 1, fp) != 1) { Logmsg("Unexpected EOF in game patch read\n"); goto nofile; } // find the game's name cp = NULL; for (i = 0; i < numGames; i++) { if (descr.gameID == gameInfo[i].gameID) { cp = gameInfo[i].gameName; break; } } if (i < numGames) { gameInfo[i].patchVersion = descr.patchVersion; if (!gameInfo[i].patchVersion) Logmsg("WHOA: found a game patch with version 0, ID = 0x%.8lx\n", descr.gameID); } else { sprintf(buf, "Unknown 0x%.8lx", descr.gameID); cp = buf; } hdrLength = sizeof(messOut) + end-start; fullLength = descr.codeSize + hdrLength; msg.message = (Ptr)malloc((size_t)fullLength); ASSERT(msg.message); // copy the header bits over memcpy(msg.message, &opCode, sizeof(messOut)); memcpy(msg.message + sizeof(messOut), &descr, end-start); // read what's left; set length to whole thing msg.length = fullLength; if (fread(msg.message + hdrLength, descr.codeSize, 1, fp) != 1) { Logmsg("Unexpected EOF in game Patch read\n"); goto nofile; } if ((game = Database_FindGame(descr.gameID, true)) == NULL) { // haven't seen this before DataBase_NewGame(descr.gameID, descr.patchVersion, cp, &msg); Logmsg("Added patch for 0x%.8lx (%s) version %ld (length = %ld)\n", descr.gameID, cp, (long)descr.patchVersion, (long)descr.codeSize); } else { // been there, done that, just replace the patch if it needs it if (descr.patchVersion > game->version) { DataBase_AddGamePatch(descr.gameID, descr.patchVersion, &msg); Logmsg("Replaced patch for 0x%.8lx (%s) version %ld (length = %ld)\n", descr.gameID, cp, (long)descr.patchVersion, (long)descr.codeSize); } else { Logmsg("Patch for 0x%.8lx (%s) version %ld is current\n", descr.gameID, cp, (long)descr.patchVersion); } } free(msg.message); } nofile: // get here if no file to read, or file was hosed if (fp != NULL) fclose(fp); // Now we need to call DataBase_NewGame on all the games that *don't* // have patches and therefore weren't initialized above. // for (i = 0; i < numGames; i++) { if (!gameInfo[i].patchVersion) { if ((game = Database_FindGame(gameInfo[i].gameID, true)) == NULL) { DataBase_NewGame(gameInfo[i].gameID, 1, gameInfo[i].gameName, NULL); Logmsg("No patch for 0x%.8lx (%s), assigned version %ld\n", gameInfo[i].gameID, gameInfo[i].gameName, 1); } else { Logmsg("No patch for 0x%.8lx (%s) version %ld\n", gameInfo[i].gameID, gameInfo[i].gameName, game->version); } } } Common_FreeGameInfo(gameInfo); }