ZZ_James
ZZ_James

Reputation: 129

Returning a polymorphic class

i'm creating a little xbox application and for the beginning it should detect what game is currently running and then bypass and/or launch a program. Since i recently learned polymorphism i thought i could implement it here to gain efficiency. Below is my code (not as efficient as i thought it would be):

DWORD(__cdecl *XamGetCurrentTitleID)() = (DWORD(__cdecl *)())ResolveFunction("xam.xex", 0x1CF); // Resolves current Game ID

typedef enum _XBOX_GAMES : DWORD // Enum that holds Game IDs
{
    BOOT_UP = 0x00000000,
    DASHBOARD = 0xFFFE07D1,
    FREESTYLEDASH = 0xF5D20000,
    COD_WORLD_AT_WAR = 0x4156081C,
    COD_MODERN_WARFARE = 0x415607E6,
    COD_MODERN_WARFARE_2 = 0x41560817,
    COD_BLACK_OPS_1 = 0x41560855,
    COD_MODERN_WARFARE_3 = 0x415608CB,
    COD_BLACK_OPS_2 = 0x415608C3,
    COD_GHOSTS = 0x415608fC,
    COD_ADVANCED_WARFARE = 0x41560914,
    COD_BLACK_OPS_3 = 0x4156091D,
    DESTINY = 0x415608F8,
    GTAV = 0x545408A7
} XBOX_GAMES;

DWORD GameChecker()
{
    DWORD lastID = NULL;

    Game *game;
    AW aw; BO1 bo1; BO2 bo2; BO3 bo3; Ghosts ghosts; MW2 mw2; MW3 mw3; Dashboard dashboard;

    for (;;)
    {
        if (XamGetCurrentTitleID() != lastID)
        {
            switch (XamGetCurrentTitleID())
            {
                case BOOT_UP:
                    // nothing
                    break;
                case DASHBOARD:
                    game = &dashboard;
                    game->Launch();
                    break;
                case COD_MODERN_WARFARE_2:
                    game = &mw2;
                    game->Launch();
                    break;
                case COD_MODERN_WARFARE_3:
                    game = &mw3;
                    game->Launch();
                    break;
                case COD_GHOSTS:
                    game = &ghosts;
                    game->Bypass();
                    game->Launch();
                    break;
                case COD_BLACK_OPS_1:
                    game = &bo1;
                    game->Launch();
                    break;
                case COD_BLACK_OPS_2:
                    game = &bo2;
                    game->Bypass();
                    break;
                case COD_BLACK_OPS_3:
                    game = &bo3;
                    game->Bypass();
                    break;
                case COD_ADVANCED_WARFARE:
                    game = &aw;
                    game->Bypass();
                    game->Launch();
                    break;
            }

            lastID = XamGetCurrentTitleID();
        }
    }

    return 0;
}

As you can see i could've moved the game->Launch() and game->Bypass() outside of the switch statement to have less code and only call it once, but i didn't knew how i could determine when a game needs a bypass and/or launch. This is my GameClass:

class Game
{
public:
    virtual void Bypass() { }

    virtual void Launch() { }
};

And this is the class of an example game:

// needs bypass and launch called
class AW : public Game
{
public:
    void Bypass()
    {
        // bypass
    }

    void Launch()
    {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

I would like to know if there is a way to do something like this:

DWORD GameChecker()
{
    DWORD lastID = NULL;

    Game *game;

    for (;;)
    {
        if (XamGetCurrentTitleID() != lastID)
        {
            switch (XamGetCurrentTitleID())
            {
                case BOOT_UP:
                    // nothing
                    break;
                default:
                    game = &functionThatReturnsClassBasedOnGame(XamGetCurrentTitleID()); // I don't know how to code such an function
                    break;
            }

            if (game->needsBypass)
                game->Bypass();

            if (game->needsLaunch)
                game->Launch();

            lastID = XamGetCurrentTitleID();
        }
    }

    return 0;
}

Any help is greatly appreciated! Thanks for your time.

Upvotes: 0

Views: 183

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596592

A simple way to accomplish your example is like this:

const int NEEDS_BYPASS = 1;
const int NEEDS_LAUNCH = 2;

class Game
{
public:
    virtual ~Game() { }
    virtual int getFeatures() const { return 0; }
    virtual void Bypass() { }
    virtual void Launch() { }
};

class Game_Dashboard : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Dashboard - Loaded!");
    }
};

class Game_ModernWarfare2 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW2 - Loaded!");
    }
};

class Game_ModernWarfare3 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW3 - Loaded!");
    }
};

class Game_Ghosts : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
    void Bypass() {
        // bypass...
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Ghosts - Loaded!");
    }
};

class Game_BlackOpts1 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"BO1 - Loaded!");
    }
};

class Game_BlackOpts2 : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS; }
    void Bypass() {
        // bypass...
    }
};

class Game_BlackOpts3 : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS; }
    void Bypass() {
        // bypass...
    }
};

class Game_AdvancedWarfare : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
    void Bypass() {
        // bypass
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

Game* getGame(DWORD ID)
{
    switch (ID)
    {
    case DASHBOARD:
        return new Game_Dashboard;
    case COD_MODERN_WARFARE_2:
        return new Game_ModernWarfare2;
    case COD_MODERN_WARFARE_3:
        return new Game_ModernWarfare3;
    case COD_GHOSTS:
        return new Game_Ghosts;
    case COD_BLACK_OPS_1:
        return new Game_BlackOpts1;
    case COD_BLACK_OPS_2:
        return new Game_BlackOpts2;
    case COD_BLACK_OPS_3:
        return new Game_BlackOpts3;
    case COD_ADVANCED_WARFARE:
        return new Game_AdvancedWarfare;
    }
    return NULL;
}

DWORD GameChecker()
{
    DWORD currentID, lastID = 0;
    Game *game;

    do
    {
        currentID = XamGetCurrentTitleID();
        if (currentID != lastID)
        {
            lastID = currentID;

            game = getGame(currentID);
            if  (game)
            {
                if (game->getFeatures() & NEEDS_BYPASS)
                    game->Bypass();

                if (game->getFeatures() & NEEDS_LAUNCH)
                    game->Launch();

                delete game;
            }
        }
    }
    while (true);

    return 0;
}

However, a better use of polymorphism would to be more like this instead:

class Game
{
public:
    virtual ~Game() { }
};

class CanBypass
{
public:
    virtual void Bypass() = 0;
};

class CanLaunch
{
public:
    virtual void Launch() = 0;
};

class Game_Dashboard : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Dashboard - Loaded!");
    }
};

class Game_ModernWarfare2 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW2 - Loaded!");
    }
};

class Game_ModernWarfare3 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW3 - Loaded!");
    }
};

class Game_Ghosts : public Game, public CanBypass, public CanLaunch
{
public:
    void Bypass() {
        // bypass...
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Ghosts - Loaded!");
    }
};

class Game_BlackOpts1 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"BO1 - Loaded!");
    }
};

class Game_BlackOpts2 : public Game, public CanBypass
{
public:
    void Bypass() {
        // bypass...
    }
};

class Game_BlackOpts3 : public Game, public CanBypass
{
public:
    void Bypass() {
        // bypass...
    }
};

class Game_AdvancedWarfare : public Game, public CanBypass, public CanLaunch
{
public:
    void Bypass() {
        // bypass
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

Game* getGame(DWORD ID)
{
    switch (ID)
    {
    case DASHBOARD:
        return new Game_Dashboard;
    case COD_MODERN_WARFARE_2:
        return new Game_ModernWarfare2;
    case COD_MODERN_WARFARE_3:
        return new Game_ModernWarfare3;
    case COD_GHOSTS:
        return new Game_Ghosts;
    case COD_BLACK_OPS_1:
        return new Game_BlackOpts1;
    case COD_BLACK_OPS_2:
        return new Game_BlackOpts2;
    case COD_BLACK_OPS_3:
        return new Game_BlackOpts3;
    case COD_ADVANCED_WARFARE:
        return new Game_AdvancedWarfare;
    }
    return NULL;
}

DWORD GameChecker()
{
    DWORD currentID, lastID = 0;
    Game *game;
    CanBypass *bypasser; 
    CanLaunch *launcher;

    do
    {
        currentID = XamGetCurrentTitleID();
        if (currentID != lastID)
        {
            lastID = currentID;

            game = getGame(currentID);
            if  (game)
            {
                bypasser = dynamic_cast<CanBypass*>(game);
                if (bypasser)
                    bypasser->Bypass();

                launcher = dynamic_cast<CanLaunch*>(game);
                if (launcher)
                    launcher->Launch();

                delete game;
            }
        }
    }
    while (true);

    return 0;
}

Upvotes: 1

Related Questions