MapData::MapData(char const* path) : images(DictionaryMap::alNumNoCase) { imgList = NULL; map = MPQArchive::open(path, File::READ); if (map == NULL) map = MPQArchive::open(String::buildFullName(cfg.warPath, path), File::READ); if (map) { imgList = ImageList_Create(16, 16, ILC_COLOR24, 16, 16); MPQLoader loader(*getApp()->getWarLoader()); loader.addArchive(map); LoadGameData(data, &loader, WC3_LOAD_UNITS | WC3_LOAD_ITEMS | WC3_LOAD_ABILITIES | WC3_LOAD_UPGRADES | WC3_LOAD_MERGED | WC3_LOAD_NO_WEONLY); Image blank(16, 16); blank.fill(Image::clr(255, 255, 255)); HBITMAP hBitmap = blank.createBitmap(); ImageList_Add(imgList, hBitmap, NULL); DeleteObject(hBitmap); images.set("", 0); } }
void LocalGameData::DataAppStart() { char szHomePath[MAX_PATH]; CLhcImg::GetHomePath( szHomePath, MAX_PATH ); YL_StringUtil::Format( m_strDataFilePath, "%s\\Resources\\Profiles\\usergame.xml", szHomePath ); YL_Log( "LocalGameData.txt", LOG_DEBUG, "DataAppStart", "m_strDataFilePath:%s", m_strDataFilePath.c_str() ); LoadGameData(); }
/// <summary>Reload the game data.</summary> void MainWnd::OnCommand_Reload() { // Save workspace SaveWorkspace(); // Close/save documents for (auto& doc : theApp) if (!doc.CloseModified()) return; // Cancelled/Failed: Abort // Clear/Reload game data LoadGameData(); }
MapData::MapData (char const* path) { map = MPQOpen (path, MPQFILE_READ); images = NULL; if (map == 0) map = MPQOpen (mprintf ("%s%s", warPath, path), MPQFILE_READ); if (map) { iList.Create (16, 16, ILC_COLOR24, 16, 16); MPQAddArchive (warloader, map); LoadGameData (data, warloader, WC3_LOAD_UNITS | WC3_LOAD_ITEMS | WC3_LOAD_ABILITIES | WC3_LOAD_UPGRADES | WC3_LOAD_MERGED | WC3_LOAD_NO_WEONLY); MPQRemoveArchive (warloader, map); maxImages = 16; numImages = 1; images = new imgname[maxImages]; memset (images, 0, sizeof (imgname) * maxImages); CDC dc; dc.Attach (GetDC (NULL)); unsigned char* bm = new unsigned char[16 * 16 * 4]; memset (bm, 0, 16 * 16 * 4); CBitmap bmp; bmp.CreateCompatibleBitmap (&dc, 16, 16); BITMAPINFOHEADER bi; bi.biSize = sizeof bi; bi.biWidth = 16; bi.biHeight = -16; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 1; bi.biYPelsPerMeter = 1; bi.biClrUsed = 0; bi.biClrImportant = 0; SetDIBits (dc.m_hDC, (HBITMAP) bmp.m_hObject, 0, 16, bm, (BITMAPINFO*) &bi, DIB_RGB_COLORS); iList.Add (&bmp, (CBitmap*) NULL); delete[] bm; } }
bool LoadGameView::Run() { LastSelected=0; CurrentlySelected=0; Exit=false; Draw(true); while(true) { Draw(false); if(!Update()) { // Escape has been pressed if(Exit) { return true; } // If there are available saves if(FileNames.size()>0) { // Create a new game GameView Game=GameView(); // Load the data if(!LoadGameData(&Game, FileNames[CurrentlySelected])) { // Loading failed SetColour(GREY, BLACK); Clear(); // Display error message std::cout<<"The game failed to load."<<std::endl; std::cout<<"Press any key to continue..."; _getch(); Draw(true); // Redraw loading window } else { // Run the loaded game return Game.Run(); } } } } }
/// <summary>Called on first display</summary> /// <param name="lParam">not used.</param> /// <param name="wParam">not used.</param> LRESULT MainWnd::OnInitialUpdate(WPARAM wParam, LPARAM lParam) { try { // Enable Drag/Drop from windows explorer DragAcceptFiles(TRUE); // Load game data LoadGameData(); // Find & Replace dialog: m_dlgFind.Create(FindDialog::IDD, this); return 0; } catch (ExceptionBase& e) { Console.Log(HERE, e); return 0; } }
bool parseDotaData (char const* dest, char const* path) { MPQARCHIVE map = MPQOpen (path, MPQFILE_READ); if (map == 0) map = MPQOpen (mprintf ("%s%s", warPath, path), MPQFILE_READ); if (map == 0) { if (useropen) MessageBox (NULL, mprintf ("Could not locate %s", path), "Error", MB_OK | MB_ICONHAND); return false; } MPQAddArchive (warloader, map); CProgressDlg* prg = ((CDotAReplayApp*) ::AfxGetApp ())->progress; char title[256]; _splitpath (path, NULL, NULL, title, NULL); prg->SetSupText (mprintf ("Parsing %s", title), 0); prg->SetSubText ("Parsing object data..."); prg->show (); GameData data; LoadGameData (data, warloader, WC3_LOAD_UNITS | WC3_LOAD_ITEMS | WC3_LOAD_ABILITIES); resetData (); bool ok = true; dir = NULL; idir = NULL; reset_id (); int tavernCount = 0; prg->SetSubText ("Parsing taverns and shops...", 40); for (int i = 0; i < data.data[WC3_UNITS]->getNumUnits (); i++) { UnitData* tav = data.data[WC3_UNITS]->getUnit (i); if (tav != NULL) { char const* name = tav->getStringData ("Name"); for (int ti = 0; ti < numTaverns; ti++) { if (!stricmp (taverns[ti].name, name)) { tavernCount++; char const* herolist = tav->getData ("Sellunits"); for (int p = 0; herolist[p];) { static char _id[5]; int idl = 0; for (; idl < 4 && herolist[p]; idl++, p++) _id[idl] = herolist[p]; if (idl == 4) { _id[4] = 0; if (getValue (dir, _id) == 0) { UnitData* hero = data.data[WC3_UNITS]->getUnitById (_id); if (hero) addHero (data.data[WC3_ABILITIES], hero, ti); dir = addString (dir, _id, 1); } } if (herolist[p] == ',') p++; else break; } } } for (int si = 0; si < numShops; si++) { if (!stricmp (shops[si].name, name)) { for (int m = 0; m < 2; m++) { char const* itemlist = tav->getData (m ? "Sellitems" : "Sellunits"); for (int p = 0; itemlist[p];) { static char _id[5]; int idl = 0; for (; idl < 4 && itemlist[p]; idl++, p++) _id[idl] = itemlist[p]; if (idl == 4) { _id[4] = 0; if (getValue (dir, _id) == 0) { UnitData* item = data.data[m ? WC3_ITEMS : WC3_UNITS]->getUnitById (_id); if (item) if (addSoldItem (item)) dir = addString (dir, _id, 1); } } if (itemlist[p] == ',') p++; else break; } } break; } } } } if (tavernCount == 0) { for (int i = 0; i < data.data[WC3_UNITS]->getNumUnits (); i++) { UnitData* tav = data.data[WC3_UNITS]->getUnit (i); if (tav != NULL) { char const* name = tav->getStringData ("Name"); for (int ti = 0; ti < numOldTaverns; ti++) { if (!stricmp (oldTaverns[ti], name)) { char const* herolist = tav->getData ("Sellunits"); for (int p = 0; herolist[p];) { static char _id[5]; int idl = 0; for (; idl < 4 && herolist[p]; idl++, p++) _id[idl] = herolist[p]; if (idl == 4) { _id[4] = 0; if (getValue (dir, _id) == 0) { UnitData* hero = data.data[WC3_UNITS]->getUnitById (_id); if (hero) addHero (data.data[WC3_ABILITIES], hero, ti); dir = addString (dir, _id, 1); } } if (herolist[p] == ',') p++; else break; } } } } } } prg->SetSubText ("Parsing items...", 60); for (int i = 0; i < numItems; i++) { if (items[i].index == 0) continue; if (items[i].type == ITEM_RECIPE) { // parse recipe UnitData* unit = data.data[WC3_ITEMS]->getUnitById (items[i].ids[0]); if (unit == NULL) unit = data.data[WC3_UNITS]->getUnitById (items[i].ids[0]); if (unit) { char const* descr = strstr (unit->getStringData ("Ubertip"), "Requires:"); if (descr && (strstr (descr, "Any of the following") || strstr (descr, "Staff of Wizardry and Blade of Alacrity"))) { // scepter int scepter = items[items[i].realid].ids[0]; int recipe = items[i].ids[0]; int booster = _getItemByName ("Point Booster"); int axe = _getItemByName ("Ogre Axe"); int blade = _getItemByName ("Blade of Alacrity"); int staff = _getItemByName ("Staff of Wizardry"); recipes[numRecipes].recipeid = recipe; recipes[numRecipes].result = scepter; recipes[numRecipes].numsrc = 4; recipes[numRecipes].srcid[0] = recipe; recipes[numRecipes].srccount[0] = 1; recipes[numRecipes].srcid[1] = booster; recipes[numRecipes].srccount[1] = 1; recipes[numRecipes].srcid[2] = axe; recipes[numRecipes].srccount[2] = 1; recipes[numRecipes].srcid[3] = blade; recipes[numRecipes].srccount[3] = 1; numRecipes++; recipes[numRecipes].recipeid = recipe; recipes[numRecipes].result = scepter; recipes[numRecipes].numsrc = 4; recipes[numRecipes].srcid[0] = recipe; recipes[numRecipes].srccount[0] = 1; recipes[numRecipes].srcid[1] = booster; recipes[numRecipes].srccount[1] = 1; recipes[numRecipes].srcid[2] = axe; recipes[numRecipes].srccount[2] = 1; recipes[numRecipes].srcid[3] = staff; recipes[numRecipes].srccount[3] = 1; numRecipes++; recipes[numRecipes].recipeid = recipe; recipes[numRecipes].result = scepter; recipes[numRecipes].numsrc = 4; recipes[numRecipes].srcid[0] = recipe; recipes[numRecipes].srccount[0] = 1; recipes[numRecipes].srcid[1] = booster; recipes[numRecipes].srccount[1] = 1; recipes[numRecipes].srcid[2] = staff; recipes[numRecipes].srccount[2] = 1; recipes[numRecipes].srcid[3] = blade; recipes[numRecipes].srccount[3] = 1; numRecipes++; } else if (descr) { recipes[numRecipes].numsrc = 0; recipes[numRecipes].recipeid = 0; if (items[i].cost) { recipes[numRecipes].srccount[0] = 1; recipes[numRecipes].srcid[0] = items[i].ids[0]; recipes[numRecipes].numsrc = 1; recipes[numRecipes].recipeid = items[i].ids[0]; } recipes[numRecipes].result = items[items[i].realid].ids[0]; int num = 0; int pos = 0; int prev = 0; bool prevOr = false; while (true) { if (descr[pos] == 0 || (descr[pos] == '|' && descr[pos + 1] == 'n')) { if (num) { char* iname = strip_item (descr + prev, pos - prev); int count = 1; bool hasx = false; if (*iname >= '0' && *iname <= '9') { count = atoi (iname); while (*iname && *iname != ' ') { if (*iname == 'x') hasx = true; iname++; } while (*iname == ' ') iname++; } if (count > 1) { int len = (int) strlen (iname); if (len && iname[len - 1] == 's') iname[--len] = 0; } int upgrLen = (int) strlen ("Buy recipe to upgrade ("); if (!stricmp (iname, "or")) prevOr = true; else if (!strnicmp (iname, "Buy recipe to upgrade (", upgrLen)) { int levels = atoi (iname + upgrLen); int iid = items[i].realid; for (int lvl = 2; lvl <= levels; lvl++) { numRecipes++; recipes[numRecipes].numsrc = 2; recipes[numRecipes].srcid[0] = recipes[numRecipes - 1].srcid[0]; recipes[numRecipes].srccount[0] = 1; recipes[numRecipes].srcid[1] = recipes[numRecipes - 1].result; recipes[numRecipes].srccount[1] = 1; items[numItems].ids[0] = new_id (); recipes[numRecipes].result = items[numItems].ids[0]; items[numItems].numIds = 1; sprintf (items[numItems].name, "%s %d", items[iid].name, lvl); strcpy (items[numItems].imgTag, items[iid].imgTag); items[numItems].index = numItems; items[numItems].type = ITEM_COMBO; items[numItems].realid = i; items[numItems].cost = 0; idir = saddString (idir, items[numItems].name, numItems + 1); numItems++; } strcat (items[iid].name, " 1"); idir = saddString (idir, items[iid].name, iid + 1); } else { int cpos = sgetValue (idir, iname) - 1; if (cpos >= 0) { if (prevOr) { memcpy (&recipes[numRecipes + 1], &recipes[numRecipes], sizeof recipes[0]); numRecipes++; recipes[numRecipes].srcid[recipes[numRecipes].numsrc - 1] = items[cpos].ids[0]; recipes[numRecipes].srccount[recipes[numRecipes].numsrc - 1] = count; } else { recipes[numRecipes].srcid[recipes[numRecipes].numsrc] = items[cpos].ids[0]; recipes[numRecipes].srccount[recipes[numRecipes].numsrc] = count; recipes[numRecipes].numsrc++; } prevOr = false; } } } num++; if (descr[pos] == 0) break; pos += 2; prev = pos; } else pos++; } if (recipes[numRecipes].numsrc) numRecipes++; } } } } for (int i = 0; i < data.data[WC3_ITEMS]->getNumUnits (); i++) { UnitData* item = data.data[WC3_ITEMS]->getUnit (i); if (item != NULL) mergeItemName (item); } for (int i = 0; i < data.data[WC3_UNITS]->getNumUnits (); i++) { UnitData* item = data.data[WC3_UNITS]->getUnit (i); if (item != NULL) mergeItemName (item); } prg->SetSubText ("Parsing upgradeable abilities...", 80); for (int i = 0; i < data.data[WC3_ABILITIES]->getNumUnits (); i++) { UnitData* abil = data.data[WC3_ABILITIES]->getUnit (i); if (abil != NULL && !strcmp (abil->getStringData ("code"), "ANeg")) addEngineering (abil); } prg->SetSubText ("Computing recipe costs...", 90); for (int i = 0; i < numRecipes; i++) { int res = getItemById (recipes[i].result)->index; if (res > 0 && items[res].type >= 0) { items[res].cost = 0; items[res].type = -items[res].type; } } for (int maxc = 0; maxc < 20; maxc++) { bool total = true; for (int i = 0; i < numRecipes; i++) { int res = getItemById (recipes[i].result)->index; if (res > 0 && items[res].type < 0) { bool ok = true; items[res].cost = 0; for (int j = 0; j < recipes[i].numsrc; j++) { int comp = getItemById (recipes[i].srcid[j])->index; if (comp > 0) { if (items[comp].type < 0) { ok = false; break; } else items[res].cost += items[comp].cost * recipes[i].srccount[j]; } } if (!ok) total = false; else items[res].type = ITEM_COMBO; } } if (total) break; } //FILE* log = fopen ("recipes.txt", "wt"); //for (int i = 0; i < numRecipes; i++) //{ // int res = getItemById (recipes[i].result)->index; // if (res <= 0) continue; // fprintf (log, "%s =", items[res].name); // for (int j = 0; j < recipes[i].numsrc; j++) // { // int comp = getItemById (recipes[i].srcid[j])->index; // if (comp > 0) // fprintf (log, " %s x%d", items[comp].name, recipes[i].srccount[j]); // } // fprintf (log, "\n"); //} //fclose (log); delete dir; delete idir; MPQRemoveArchive (warloader, map); MPQClose (map); prg->hide (); if (!ok) return false; return saveDotaData (dest); }
int main(int argc, char *argv[]) { enum { GAME_COMPUTER, GAME_NETWORK, GAME_UNKNOWN } game_type = GAME_UNKNOWN; char *remote_address = NULL; int remote_port; int i; if (argc < 2) { printf("Penguin Warrior\n"); printf("Usage: pw [ mode ] [ option ... ]\n"); printf(" Game modes (choose one):\n"); printf(" --computer\n"); printf(" --client <remote ip address>\n"); printf(" --server <port number>\n"); printf(" Display options, for tweaking and experimenting:\n"); printf(" --fullscreen\n"); printf(" --hwsurface (use an SDL hardware surface if possible)\n"); printf(" --doublebuf (use SDL double buffering if possible)\n"); printf(" The display options default to a windowed, software buffer.\n"); exit(EXIT_FAILURE); } /* Process command line arguments. There are plenty of libraries for command line processing, but our needs are simple in this case. */ for (i = 0; i < argc; i++) { /* Networked or scripted opponent? */ if (!strcmp(argv[i], "--computer")) { game_type = GAME_COMPUTER; continue; } else if (!strcmp(argv[i], "--client")) { game_type = GAME_NETWORK; if (i + 2 >= argc) { printf("You must supply an IP address "\ "and port number for network games.\n"); exit(EXIT_FAILURE); } remote_address = argv[i+1]; remote_port = atoi(argv[i+2]); i++; continue; } else if (!strcmp(argv[i], "--server")) { game_type = GAME_NETWORK; if (++i >= argc) { printf("You must supply a port number "\ "for --server.\n"); exit(EXIT_FAILURE); } remote_port = atoi(argv[i]); continue; /* Display-related options */ } else if (!strcmp(argv[i], "--hwsurface")) { hwsurface = 1; } else if (!strcmp(argv[i], "--doublebuf")) { doublebuf = 1; } else if (!strcmp(argv[i], "--fullscreen")) { fullscreen = 1; } } /* If this is a network game, make a connection. */ if (game_type == GAME_NETWORK) { /* If there's no remote address, the user selected server mode. */ if (remote_address == NULL) { if (WaitNetgameConnection(remote_port, &netlink) != 0) { printf("Unable to receive connection.\n"); exit(EXIT_FAILURE); } } else { if (ConnectToNetgame(remote_address, remote_port, &netlink) != 0) { printf("Unable to connect.\n"); exit(EXIT_FAILURE); } } opponent_type = OPP_NETWORK; printf("Playing in network game against %s.\n", netlink.dotted_ip); } else if (game_type == GAME_COMPUTER) { opponent_type = OPP_COMPUTER; printf("Playing against the computer.\n"); } else { printf("No game type selected.\n"); exit(EXIT_FAILURE); } /* Initialize our random number generator. */ initrandom(); /* Create a mutex to protect the player data. */ player_mutex = SDL_CreateMutex(); if (player_mutex == NULL) { fprintf(stderr, "Unable to create mutex: %s\n", SDL_GetError()); } /* Start our scripting engine. */ InitScripting(); if (LoadGameScript("pw.tcl") != 0) { fprintf(stderr, "Exiting due to script error.\n"); exit(EXIT_FAILURE); } /* Fire up SDL. */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("Unable to initialize SDL: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } atexit(SDL_Quit); /* Set an appropriate 16-bit video mode. */ if (SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, (hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE) | (doublebuf ? SDL_DOUBLEBUF : 0) | (fullscreen ? SDL_FULLSCREEN : 0)) == NULL) { printf("Unable to set video mode: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } /* Save the screen pointer for later use. */ screen = SDL_GetVideoSurface(); /* Set the window caption to the name of the game. */ SDL_WM_SetCaption("Penguin Warrior", "Penguin Warrior"); /* Hide the mouse pointer. */ SDL_ShowCursor(0); /* Initialize the status display. */ if (InitStatusDisplay() < 0) { printf("Unable to initialize status display.\n"); exit(EXIT_FAILURE); } /* Start the OpenAL-based audio system. */ InitAudio(); /* Initialize music and give the music system a file. */ InitMusic(); if (LoadMusic("reflux.ogg") < 0) { /* If that failed, don't worry about it. */ printf("Unable to load reflux.ogg.\n"); } /* Load the game's data into globals. */ LoadGameData(); /* Initialize the background starfield. */ InitBackground(); /* Start the network thread. */ if (game_type == GAME_NETWORK) { network_thread = SDL_CreateThread(NetworkThread, NULL); if (network_thread == NULL) { printf("Unable to start network thread: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } } /* Play! */ InitPlayer(&player); InitPlayer(&opponent); PlayGame(); /* Kill the network thread. */ if (game_type == GAME_NETWORK) { SDL_KillThread(network_thread); } /* Close the network connection. */ if (game_type == GAME_NETWORK) CloseNetgameLink(&netlink); /* Unhide the mouse pointer. */ SDL_ShowCursor(1); /* Clean up the status display. */ CleanupStatusDisplay(); /* Unload data. */ UnloadGameData(); /* Shut down our scripting engine. */ CleanupScripting(); /* Get rid of the mutex. */ SDL_DestroyMutex(player_mutex); /* Shut down audio. */ CleanupMusic(); CleanupAudio(); return 0; }
int main(int argc, char *argv[]) { enum { GAME_COMPUTER, GAME_NETWORK, GAME_UNKNOWN } game_type = GAME_UNKNOWN; char *remote_address; int i; if (argc < 2) { printf("Penguin Warrior\n"); printf("Usage: pw [ mode ] [ option ... ]\n"); printf(" Game modes (choose one):\n"); printf(" --computer\n"); printf(" --net <remote ip address>\n"); printf(" Display options, for tweaking and experimenting:\n"); printf(" --fullscreen\n"); printf(" --hwsurface (use an SDL hardware surface if possible)\n"); printf(" --doublebuf (use SDL double buffering if possible)\n"); printf(" The display options default to a windowed, software buffer.\n"); exit(EXIT_FAILURE); } /* Process command line arguments. There are plenty of libraries for command line processing, but our needs are simple in this case. */ for (i = 0; i < argc; i++) { /* Networked or scripted opponent? */ if (!strcmp(argv[i], "--computer")) { game_type = GAME_COMPUTER; continue; } else if (!strcmp(argv[i], "--net")) { game_type = GAME_NETWORK; if (++i >= argc) { printf("You must supply an IP address for --net.\n"); exit(EXIT_FAILURE); } remote_address = argv[i]; continue; /* Display-related options */ } else if (!strcmp(argv[i], "--hwsurface")) { hwsurface = 1; } else if (!strcmp(argv[i], "--doublebuf")) { doublebuf = 1; } else if (!strcmp(argv[i], "--fullscreen")) { fullscreen = 1; } } switch (game_type) { case GAME_COMPUTER: opponent_type = OPP_COMPUTER; printf("Playing against the computer.\n"); break; case GAME_NETWORK: printf("Sorry, network play is not implemented... yet!\n"); exit(EXIT_FAILURE); default: printf("You must select a game type.\n"); exit(EXIT_FAILURE); } /* Initialize our random number generator. */ initrandom(); /* Fire up SDL. */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("Unable to initialize SDL: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } atexit(SDL_Quit); /* Set an appropriate 16-bit double buffered video mode. */ if (SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, (hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE) | (doublebuf ? SDL_DOUBLEBUF : 0) | (fullscreen ? SDL_FULLSCREEN : 0)) == NULL) { printf("Unable to set video mode: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } /* Save the screen pointer for later use. */ screen = SDL_GetVideoSurface(); /* Set the window caption to the name of the game. */ SDL_WM_SetCaption("Penguin Warrior", "Penguin Warrior"); /* Hide the mouse pointer. */ SDL_ShowCursor(0); /* Start the OpenAL-based audio system. */ InitAudio(); /* Initialize music and give the music system a file. */ InitMusic(); if (LoadMusic("reflux.ogg") != 0) { /* If that failed, don't worry about it. */ printf("Unable to load reflux.ogg.\n"); } /* Load the game's data into globals. We can only do this after the video and audio subsystems are ready for action, since the loading routines interact with SDL and OpenAL. */ LoadGameData(); /* Initialize the background starfield. */ InitBackground(); /* Play! */ InitPlayer(); InitOpponent(); PlayGame(); /* Unhide the mouse pointer. */ SDL_ShowCursor(1); /* Unload data. */ UnloadGameData(); /* Shut down audio. */ CleanupMusic(); CleanupAudio(); return 0; }