mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 14:51:40 +00:00
removed GameSettings::detectname and GameSettings::midi; renamed GameSettings::gameName to name; added temporary experimental MD5 hack
svn-id: r11603
This commit is contained in:
parent
dd33ae0f0f
commit
35b62c294d
@ -198,7 +198,7 @@ void listGames() {
|
||||
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
|
||||
GameList list = (*iter)->getSupportedGames();
|
||||
for (GameList::Iterator v = list.begin(); v != list.end(); ++v) {
|
||||
printf("%-20s %s\n", v->gameName, v->description);
|
||||
printf("%-20s %s\n", v->name, v->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,12 +229,12 @@ void listTargets() {
|
||||
GameSettings GameDetector::findGame(const String &gameName, const Plugin **plugin) {
|
||||
// Find the GameSettings for this target
|
||||
const PluginList &plugins = PluginManager::instance().getPlugins();
|
||||
GameSettings result = {NULL, NULL, MDT_NONE, 0, NULL};
|
||||
GameSettings result = {NULL, NULL, 0};
|
||||
|
||||
PluginList::ConstIterator iter = plugins.begin();
|
||||
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
|
||||
result = (*iter)->findGame(gameName.c_str());
|
||||
if (result.gameName) {
|
||||
if (result.name) {
|
||||
if (plugin)
|
||||
*plugin = *iter;
|
||||
break;
|
||||
@ -301,10 +301,10 @@ void GameDetector::parseCommandLine(int argc, char **argv) {
|
||||
|
||||
if (s[0] != '-' || s[1] == '\0') {
|
||||
// Last argument: this could be a target name.
|
||||
// To verify this, check if there is either a game domain (i.e
|
||||
// To verify this, check if there is either a game domain (i.e.
|
||||
// a configured target) matching this argument, or if we can
|
||||
// find any target with that name.
|
||||
if (i == (argc - 1) && (ConfMan.hasGameDomain(s) || findGame(s).gameName)) {
|
||||
if (i == (argc - 1) && (ConfMan.hasGameDomain(s) || findGame(s).name)) {
|
||||
setTarget(s);
|
||||
} else {
|
||||
if (current_option == NULL)
|
||||
@ -512,12 +512,10 @@ bool GameDetector::detectGame() {
|
||||
|
||||
_game = findGame(realGame, &_plugin);
|
||||
|
||||
if (_game.gameName) {
|
||||
_gameName = _game.gameName;
|
||||
if (_game.name) {
|
||||
printf("Trying to start game '%s'\n", _game.description);
|
||||
return true;
|
||||
} else {
|
||||
_gameName.clear();
|
||||
printf("Failed game detection\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -47,11 +47,9 @@ enum MidiDriverType {
|
||||
};
|
||||
|
||||
struct GameSettings {
|
||||
const char *gameName;
|
||||
const char *name;
|
||||
const char *description;
|
||||
int midi; // MidiDriverType values
|
||||
uint32 features;
|
||||
const char *detectname;
|
||||
};
|
||||
|
||||
class GameDetector {
|
||||
@ -64,8 +62,7 @@ public:
|
||||
bool detectMain();
|
||||
|
||||
String _targetName;
|
||||
String _gameName;
|
||||
GameSettings _game; // TODO: Eventually get rid of _game or at least make it protected
|
||||
GameSettings _game; // TODO: Eventually get rid of this?!
|
||||
const Plugin *_plugin;
|
||||
|
||||
bool _dumpScripts;
|
||||
|
@ -52,9 +52,9 @@ GameSettings Plugin::findGame(const char *gameName) const {
|
||||
// Find the GameSettings for this game
|
||||
assert(gameName);
|
||||
GameList games = getSupportedGames();
|
||||
GameSettings result = {NULL, NULL, MDT_NONE, 0, NULL};
|
||||
GameSettings result = {NULL, NULL, 0};
|
||||
for (GameList::Iterator g = games.begin(); g != games.end(); ++g) {
|
||||
if (!scumm_stricmp(g->gameName, gameName)) {
|
||||
if (!scumm_stricmp(g->name, gameName)) {
|
||||
result = *g;
|
||||
break;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ void md5_finish( md5_context *ctx, uint8 digest[16] )
|
||||
PUT_UINT32( ctx->state[3], digest, 12 );
|
||||
}
|
||||
|
||||
void md5_file( const char *name, uint8 digest[16] )
|
||||
bool md5_file( const char *name, uint8 digest[16] )
|
||||
{
|
||||
File f;
|
||||
md5_context ctx;
|
||||
@ -250,7 +250,7 @@ void md5_file( const char *name, uint8 digest[16] )
|
||||
if( ! f.isOpen() )
|
||||
{
|
||||
warning( "md5_file couldn't open '%s'", name );
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
md5_starts( &ctx );
|
||||
@ -261,6 +261,7 @@ void md5_file( const char *name, uint8 digest[16] )
|
||||
}
|
||||
|
||||
md5_finish( &ctx, digest );
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
@ -35,6 +35,6 @@ void md5_starts( md5_context *ctx );
|
||||
void md5_update( md5_context *ctx, const uint8 *input, uint32 length );
|
||||
void md5_finish( md5_context *ctx, uint8 digest[16] );
|
||||
|
||||
void md5_file( const char *name, uint8 digest[16] );
|
||||
bool md5_file( const char *name, uint8 digest[16] );
|
||||
|
||||
#endif
|
||||
|
@ -438,7 +438,7 @@ void LauncherDialog::addGame() {
|
||||
// The auto detector or the user made a choice.
|
||||
// Pick a domain name which does not yet exist (after all, we
|
||||
// are *adding* a game to the config, not replacing).
|
||||
String domain(result.gameName);
|
||||
String domain(result.name);
|
||||
if (ConfMan.hasGameDomain(domain)) {
|
||||
char suffix = 'a';
|
||||
domain += suffix;
|
||||
@ -448,7 +448,7 @@ void LauncherDialog::addGame() {
|
||||
suffix++;
|
||||
domain += suffix;
|
||||
}
|
||||
ConfMan.set("gameid", result.gameName, domain);
|
||||
ConfMan.set("gameid", result.name, domain);
|
||||
ConfMan.set("description", result.description, domain);
|
||||
}
|
||||
ConfMan.set("path", dir->path(), domain);
|
||||
|
@ -53,7 +53,7 @@ extern bool draw_keyboard;
|
||||
|
||||
/* Flight of the Amazon Queen */
|
||||
static const GameSettings queen_setting =
|
||||
{ "queen", "Flight of the Amazon Queen", MDT_ADLIB | MDT_NATIVE | MDT_PREFER_NATIVE, 0, "queen.1" };
|
||||
{ "queen", "Flight of the Amazon Queen", 0 };
|
||||
|
||||
GameList Engine_QUEEN_gameList() {
|
||||
GameList games;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/md5.h"
|
||||
|
||||
#include "gui/message.h"
|
||||
#include "gui/newgui.h"
|
||||
@ -83,7 +84,7 @@ enum MouseButtonStatus {
|
||||
ScummEngine *g_scumm = 0;
|
||||
|
||||
struct ScummGameSettings {
|
||||
const char *gameName;
|
||||
const char *name;
|
||||
const char *description;
|
||||
byte id, version;
|
||||
int midi; // MidiDriverType values
|
||||
@ -91,7 +92,7 @@ struct ScummGameSettings {
|
||||
const char *baseFilename;
|
||||
|
||||
GameSettings toGameSettings() const {
|
||||
GameSettings dummy = { gameName, description, midi, features, 0 };
|
||||
GameSettings dummy = { name, description, features };
|
||||
return dummy;
|
||||
}
|
||||
};
|
||||
@ -625,7 +626,41 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
|
||||
// Allow the user to override the game name with a custom string.
|
||||
// This allows some game versions to work which use filenames
|
||||
// differing from the regular version(s) of that game.
|
||||
_gameName = ConfMan.hasKey("basename") ? ConfMan.get("basename") : gs.baseFilename ? gs.baseFilename : gs.gameName;
|
||||
_gameName = ConfMan.hasKey("basename") ? ConfMan.get("basename") : gs.baseFilename ? gs.baseFilename : gs.name;
|
||||
|
||||
#if 1
|
||||
// HACK HACK HACK
|
||||
// This is not how, and where, MD5 computation should be done in the
|
||||
// real world. Rather this is meant as a proof-of-concept hack.
|
||||
// It's quick, it's dirty, and it'll go again eventually :-)
|
||||
char buf[1024];
|
||||
uint8 md5sum[16];
|
||||
|
||||
if (!(_features & GF_SMALL_HEADER)) {
|
||||
|
||||
if (_features & GF_AFTER_HEV7) {
|
||||
sprintf(buf, "%s.he0", _gameName.c_str());
|
||||
} else if (_version >= 7) {
|
||||
sprintf(buf, "%s.la0", _gameName.c_str());
|
||||
} else if (_features & GF_HUMONGOUS)
|
||||
sprintf(buf, "%s.he0", _gameName.c_str());
|
||||
else {
|
||||
sprintf(buf, "%s.000", _gameName.c_str());
|
||||
// if (_gameId == GID_SAMNMAX)
|
||||
// sprintf(buf2, "%s.sm0", _gameName.c_str());
|
||||
}
|
||||
} else if (!(_features & GF_SMALL_NAMES)) {
|
||||
sprintf(buf, "000.lfl");
|
||||
} else {
|
||||
sprintf(buf, "00.lfl");
|
||||
}
|
||||
|
||||
if (md5_file(buf, md5sum)) {
|
||||
for (int j = 0; j < 16; j++)
|
||||
printf("%02x", md5sum[j]);
|
||||
printf(" %s\n", buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
_midiDriver = GameDetector::detectMusicDriver(gs.midi);
|
||||
|
||||
@ -2794,7 +2829,7 @@ using namespace Scumm;
|
||||
GameList Engine_SCUMM_gameList() {
|
||||
const ScummGameSettings *g = scumm_settings;
|
||||
GameList games;
|
||||
while (g->gameName) {
|
||||
while (g->name) {
|
||||
games.push_back(g->toGameSettings());
|
||||
g++;
|
||||
}
|
||||
@ -2807,7 +2842,7 @@ GameList Engine_SCUMM_detectGames(const FSList &fslist) {
|
||||
char detectName[128];
|
||||
char detectName2[128];
|
||||
|
||||
for (g = scumm_settings; g->gameName; ++g) {
|
||||
for (g = scumm_settings; g->name; ++g) {
|
||||
// Determine the 'detectname' for this game, that is, the name of a
|
||||
// file that *must* be presented if the directory contains the data
|
||||
// for this game. For example, FOA requires atlantis.000
|
||||
@ -2818,7 +2853,7 @@ GameList Engine_SCUMM_detectGames(const FSList &fslist) {
|
||||
strcpy(detectName, "000.LFL");
|
||||
detectName2[0] = '\0';
|
||||
} else {
|
||||
const char *base = g->baseFilename ? g->baseFilename : g->gameName;
|
||||
const char *base = g->baseFilename ? g->baseFilename : g->name;
|
||||
strcpy(detectName, base);
|
||||
strcat(detectName, ".000");
|
||||
strcpy(detectName2, base);
|
||||
@ -2832,10 +2867,10 @@ GameList Engine_SCUMM_detectGames(const FSList &fslist) {
|
||||
|
||||
// Iterate over all files in the given directory
|
||||
for (FSList::ConstIterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
const char *gameName = file->displayName().c_str();
|
||||
const char *name = file->displayName().c_str();
|
||||
|
||||
if ((0 == scumm_stricmp(detectName, gameName)) ||
|
||||
(0 == scumm_stricmp(detectName2, gameName))) {
|
||||
if ((0 == scumm_stricmp(detectName, name)) ||
|
||||
(0 == scumm_stricmp(detectName2, name))) {
|
||||
// Match found, add to list of candidates, then abort inner loop.
|
||||
detectedGames.push_back(g->toGameSettings());
|
||||
break;
|
||||
@ -2850,13 +2885,13 @@ Engine *Engine_SCUMM_create(GameDetector *detector, OSystem *syst) {
|
||||
|
||||
|
||||
const ScummGameSettings *g = scumm_settings;
|
||||
while (g->gameName) {
|
||||
if (!scumm_stricmp(detector->_gameName.c_str(), g->gameName))
|
||||
while (g->name) {
|
||||
if (!scumm_stricmp(detector->_game.name, g->name))
|
||||
break;
|
||||
g++;
|
||||
}
|
||||
if (!g->gameName)
|
||||
error("Invalid game '%s'\n", detector->_gameName.c_str());
|
||||
if (!g->name)
|
||||
error("Invalid game '%s'\n", detector->_game.name);
|
||||
|
||||
ScummGameSettings game = *g;
|
||||
|
||||
|
@ -52,50 +52,63 @@ extern bool draw_keyboard;
|
||||
|
||||
extern uint16 _debugLevel;
|
||||
|
||||
static const GameSettings simon_settings[] = {
|
||||
// Simon the Sorcerer 1 & 2 (not SCUMM games)
|
||||
{"simon1acorn", "Simon the Sorcerer 1 (Acorn)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON1ACORN, "DATA"},
|
||||
{"simon1dos", "Simon the Sorcerer 1 (DOS)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON1DOS, "GAMEPC"},
|
||||
{"simon1amiga", "Simon the Sorcerer 1 (Amiga)", MDT_NONE, GAME_SIMON1AMIGA, "gameamiga"},
|
||||
{"simon2dos", "Simon the Sorcerer 2 (DOS)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON2DOS, "GAME32"},
|
||||
{"simon1talkie", "Simon the Sorcerer 1 Talkie (DOS)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON1TALKIE, "SIMON.GME"},
|
||||
{"simon2talkie", "Simon the Sorcerer 2 Talkie (DOS)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON2TALKIE, "GSPTR30"},
|
||||
{"simon1win", "Simon the Sorcerer 1 Talkie (Windows)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON1WIN, "SIMON.GME"},
|
||||
{"simon1cd32", "Simon the Sorcerer 1 Talkie (Amiga CD32)", MDT_NONE, GAME_SIMON1CD32, "gameamiga"},
|
||||
{"simon2win", "Simon the Sorcerer 2 Talkie (Windows)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON2WIN, "GSPTR30"},
|
||||
{"simon2mac", "Simon the Sorcerer 2 Talkie (Amiga or Mac)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON2MAC, "GSPTR30"},
|
||||
{"simon1demo", "Simon the Sorcerer 1 (DOS Demo)", MDT_ADLIB | MDT_NATIVE, GAME_SIMON1DEMO, "GDEMO"},
|
||||
struct SimonGameSettings {
|
||||
const char *name;
|
||||
const char *description;
|
||||
uint32 features;
|
||||
const char *detectname;
|
||||
GameSettings toGameSettings() const {
|
||||
GameSettings dummy = { name, description, features };
|
||||
return dummy;
|
||||
}
|
||||
};
|
||||
|
||||
{NULL, NULL, MDT_NONE, 0, NULL}
|
||||
static const SimonGameSettings simon_settings[] = {
|
||||
// Simon the Sorcerer 1 & 2 (not SCUMM games)
|
||||
{"simon1acorn", "Simon the Sorcerer 1 (Acorn)", GAME_SIMON1ACORN, "DATA"},
|
||||
{"simon1dos", "Simon the Sorcerer 1 (DOS)", GAME_SIMON1DOS, "GAMEPC"},
|
||||
{"simon1amiga", "Simon the Sorcerer 1 (Amiga)", GAME_SIMON1AMIGA, "gameamiga"},
|
||||
{"simon2dos", "Simon the Sorcerer 2 (DOS)", GAME_SIMON2DOS, "GAME32"},
|
||||
{"simon1talkie", "Simon the Sorcerer 1 Talkie (DOS)", GAME_SIMON1TALKIE, "SIMON.GME"},
|
||||
{"simon2talkie", "Simon the Sorcerer 2 Talkie (DOS)", GAME_SIMON2TALKIE, "GSPTR30"},
|
||||
{"simon1win", "Simon the Sorcerer 1 Talkie (Windows)", GAME_SIMON1WIN, "SIMON.GME"},
|
||||
{"simon1cd32", "Simon the Sorcerer 1 Talkie (Amiga CD32)", GAME_SIMON1CD32, "gameamiga"},
|
||||
{"simon2win", "Simon the Sorcerer 2 Talkie (Windows)", GAME_SIMON2WIN, "GSPTR30"},
|
||||
{"simon2mac", "Simon the Sorcerer 2 Talkie (Amiga or Mac)", GAME_SIMON2MAC, "GSPTR30"},
|
||||
{"simon1demo", "Simon the Sorcerer 1 (DOS Demo)", GAME_SIMON1DEMO, "GDEMO"},
|
||||
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
GameList Engine_SIMON_gameList() {
|
||||
const GameSettings *g = simon_settings;
|
||||
const SimonGameSettings *g = simon_settings;
|
||||
GameList games;
|
||||
while (g->gameName)
|
||||
games.push_back(*g++);
|
||||
while (g->name) {
|
||||
games.push_back(g->toGameSettings());
|
||||
g++;
|
||||
}
|
||||
return games;
|
||||
}
|
||||
|
||||
GameList Engine_SIMON_detectGames(const FSList &fslist) {
|
||||
GameList detectedGames;
|
||||
const GameSettings *g;
|
||||
const SimonGameSettings *g;
|
||||
char detectName[128];
|
||||
char detectName2[128];
|
||||
|
||||
for (g = simon_settings; g->gameName; ++g) {
|
||||
for (g = simon_settings; g->name; ++g) {
|
||||
strcpy(detectName, g->detectname);
|
||||
strcpy(detectName2, g->detectname);
|
||||
strcat(detectName2, ".");
|
||||
|
||||
// Iterate over all files in the given directory
|
||||
for (FSList::ConstIterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
const char *gameName = file->displayName().c_str();
|
||||
const char *name = file->displayName().c_str();
|
||||
|
||||
if ((0 == scumm_stricmp(detectName, gameName)) ||
|
||||
(0 == scumm_stricmp(detectName2, gameName))) {
|
||||
if ((0 == scumm_stricmp(detectName, name)) ||
|
||||
(0 == scumm_stricmp(detectName2, name))) {
|
||||
// Match found, add to list of candidates, then abort inner loop.
|
||||
detectedGames.push_back(*g);
|
||||
detectedGames.push_back(g->toGameSettings());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -194,7 +207,7 @@ static const GameSpecificSettings simon2dos_settings = {
|
||||
#endif
|
||||
|
||||
SimonEngine::SimonEngine(GameDetector *detector, OSystem *syst)
|
||||
: Engine(syst), midi (syst) {
|
||||
: Engine(syst), midi(syst) {
|
||||
|
||||
_vc_ptr = 0;
|
||||
_game_offsets_ptr = 0;
|
||||
|
@ -79,7 +79,7 @@ extern bool draw_keyboard;
|
||||
#undef WITH_DEBUG_CHEATS
|
||||
|
||||
static const GameSettings skySetting =
|
||||
{"sky", "Beneath a Steel Sky", MDT_ADLIB | MDT_NATIVE | MDT_PREFER_NATIVE, 0, "sky.dsk" };
|
||||
{"sky", "Beneath a Steel Sky", 0 };
|
||||
|
||||
GameList Engine_SKY_gameList() {
|
||||
GameList games;
|
||||
@ -255,7 +255,7 @@ void SkyEngine::initialise(void) {
|
||||
|
||||
_systemVars.gameVersion = _skyDisk->determineGameVersion();
|
||||
|
||||
int midiDriver = GameDetector::detectMusicDriver(skySetting.midi);
|
||||
int midiDriver = GameDetector::detectMusicDriver(MDT_ADLIB | MDT_NATIVE | MDT_PREFER_NATIVE);
|
||||
if (midiDriver == MD_ADLIB) {
|
||||
_systemVars.systemFlags |= SF_SBLASTER;
|
||||
_skyMusic = new SkyAdlibMusic(_mixer, _skyDisk, _system);
|
||||
|
@ -31,38 +31,51 @@ extern bool isSmartphone(void);
|
||||
|
||||
extern uint16 _debugLevel;
|
||||
|
||||
static const GameSettings sword2_settings[] = {
|
||||
struct Sword2GameSettings {
|
||||
const char *name;
|
||||
const char *description;
|
||||
uint32 features;
|
||||
const char *detectname;
|
||||
GameSettings toGameSettings() const {
|
||||
GameSettings dummy = { name, description, features };
|
||||
return dummy;
|
||||
}
|
||||
};
|
||||
|
||||
static const Sword2GameSettings sword2_settings[] = {
|
||||
/* Broken Sword 2 */
|
||||
{"sword2", "Broken Sword II", MDT_ADLIB | MDT_NATIVE, GF_DEFAULT_TO_1X_SCALER, "players.clu" },
|
||||
{"sword2alt", "Broken Sword II (alt)", MDT_ADLIB | MDT_NATIVE, GF_DEFAULT_TO_1X_SCALER, "r2ctlns.ocx" },
|
||||
{"sword2demo", "Broken Sword II (Demo)", MDT_ADLIB | MDT_NATIVE, GF_DEFAULT_TO_1X_SCALER | Sword2::GF_DEMO, "players.clu" },
|
||||
{NULL, NULL, MDT_NONE, 0, NULL}
|
||||
{"sword2", "Broken Sword II", GF_DEFAULT_TO_1X_SCALER, "players.clu" },
|
||||
{"sword2alt", "Broken Sword II (alt)", GF_DEFAULT_TO_1X_SCALER, "r2ctlns.ocx" },
|
||||
{"sword2demo", "Broken Sword II (Demo)", GF_DEFAULT_TO_1X_SCALER | Sword2::GF_DEMO, "players.clu" },
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
GameList Engine_SWORD2_gameList() {
|
||||
const GameSettings *g = sword2_settings;
|
||||
const Sword2GameSettings *g = sword2_settings;
|
||||
GameList games;
|
||||
while (g->gameName)
|
||||
games.push_back(*g++);
|
||||
while (g->name) {
|
||||
games.push_back(g->toGameSettings());
|
||||
g++;
|
||||
}
|
||||
return games;
|
||||
}
|
||||
|
||||
GameList Engine_SWORD2_detectGames(const FSList &fslist) {
|
||||
GameList detectedGames;
|
||||
const GameSettings *g;
|
||||
const Sword2GameSettings *g;
|
||||
|
||||
// TODO: It would be nice if we had code here which distinguishes
|
||||
// between the 'sword2' and 'sword2demo' targets. The current code
|
||||
// can't do that since they use the same detectname.
|
||||
|
||||
for (g = sword2_settings; g->gameName; ++g) {
|
||||
for (g = sword2_settings; g->name; ++g) {
|
||||
// Iterate over all files in the given directory
|
||||
for (FSList::ConstIterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
const char *gameName = file->displayName().c_str();
|
||||
|
||||
if (0 == scumm_stricmp(g->detectname, gameName)) {
|
||||
// Match found, add to list of candidates, then abort inner loop.
|
||||
detectedGames.push_back(*g);
|
||||
detectedGames.push_back(g->toGameSettings());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user