refactor: update and format SlippiGame

This commit is contained in:
Nikhil Narayana 2022-06-15 22:11:28 -07:00
commit 9392df6991
2 changed files with 666 additions and 687 deletions

File diff suppressed because it is too large Load diff

View file

@ -9,146 +9,148 @@
#include <vector> #include <vector>
namespace Slippi { namespace Slippi {
const uint8_t EVENT_SPLIT_MESSAGE = 0x10; const uint8_t EVENT_SPLIT_MESSAGE = 0x10;
const uint8_t EVENT_PAYLOAD_SIZES = 0x35; const uint8_t EVENT_PAYLOAD_SIZES = 0x35;
const uint8_t EVENT_GAME_INIT = 0x36; const uint8_t EVENT_GAME_INIT = 0x36;
const uint8_t EVENT_PRE_FRAME_UPDATE = 0x37; const uint8_t EVENT_PRE_FRAME_UPDATE = 0x37;
const uint8_t EVENT_POST_FRAME_UPDATE = 0x38; const uint8_t EVENT_POST_FRAME_UPDATE = 0x38;
const uint8_t EVENT_GAME_END = 0x39; const uint8_t EVENT_GAME_END = 0x39;
const uint8_t EVENT_FRAME_START = 0x3A; const uint8_t EVENT_FRAME_START = 0x3A;
const uint8_t EVENT_FRAME_END = 0x3C; const uint8_t EVENT_FRAME_END = 0x3C;
const uint8_t EVENT_GECKO_LIST = 0x3D; const uint8_t EVENT_GECKO_LIST = 0x3D;
const uint8_t GAME_INFO_HEADER_SIZE = 78; const uint8_t GAME_INFO_HEADER_SIZE = 78;
const uint8_t UCF_TOGGLE_SIZE = 8; const uint8_t UCF_TOGGLE_SIZE = 8;
const uint8_t NAMETAG_SIZE = 8; const uint8_t NAMETAG_SIZE = 8;
const uint8_t DISPLAY_NAME_SIZE = 31; const uint8_t DISPLAY_NAME_SIZE = 31;
const uint8_t CONNECT_CODE_SIZE = 10; const uint8_t CONNECT_CODE_SIZE = 10;
const int32_t GAME_FIRST_FRAME = -123; const int32_t GAME_FIRST_FRAME = -123;
const int32_t PLAYBACK_FIRST_SAVE = -122; const int32_t PLAYBACK_FIRST_SAVE = -122;
const uint8_t GAME_SHEIK_INTERNAL_ID = 0x7; const uint8_t GAME_SHEIK_INTERNAL_ID = 0x7;
const uint8_t GAME_SHEIK_EXTERNAL_ID = 0x13; const uint8_t GAME_SHEIK_EXTERNAL_ID = 0x13;
const uint32_t SPLIT_MESSAGE_INTERNAL_DATA_LEN = 512; const uint32_t SPLIT_MESSAGE_INTERNAL_DATA_LEN = 512;
static uint8_t* data; static uint8_t *data;
typedef struct { typedef struct {
// Every player update has its own rng seed because it might change in between players // Every player update has its own rng seed because it might change in between
uint32_t randomSeed; // players
uint32_t randomSeed;
uint8_t internalCharacterId; uint8_t internalCharacterId;
uint16_t animation; uint16_t animation;
float locationX; float locationX;
float locationY; float locationY;
float facingDirection; float facingDirection;
uint8_t stocks; uint8_t stocks;
float percent; float percent;
float shieldSize; float shieldSize;
uint8_t lastMoveHitId; uint8_t lastMoveHitId;
uint8_t comboCount; uint8_t comboCount;
uint8_t lastHitBy; uint8_t lastHitBy;
//Controller information // Controller information
float joystickX; float joystickX;
float joystickY; float joystickY;
float cstickX; float cstickX;
float cstickY; float cstickY;
float trigger; float trigger;
uint32_t buttons; //This will include multiple "buttons" pressed on special buttons. For example I think pressing z sets 3 bits uint32_t buttons; // This will include multiple "buttons" pressed on special
// buttons. For example I think pressing z sets 3 bits
//This is extra controller information // This is extra controller information
uint16_t physicalButtons; //A better representation of what a player is actually pressing uint16_t physicalButtons; // A better representation of what a player is
float lTrigger; // actually pressing
float rTrigger; float lTrigger;
float rTrigger;
uint8_t joystickXRaw; uint8_t joystickXRaw;
} PlayerFrameData; } PlayerFrameData;
typedef struct FrameData { typedef struct FrameData {
int32_t frame; int32_t frame;
uint32_t numSinceStart; uint32_t numSinceStart;
bool randomSeedExists = false; bool randomSeedExists = false;
uint32_t randomSeed; uint32_t randomSeed;
bool inputsFullyFetched = false; bool inputsFullyFetched = false;
std::unordered_map<uint8_t, PlayerFrameData> players; std::unordered_map<uint8_t, PlayerFrameData> players;
std::unordered_map<uint8_t, PlayerFrameData> followers; std::unordered_map<uint8_t, PlayerFrameData> followers;
} FrameData; } FrameData;
typedef struct { typedef struct {
//Static data // Static data
uint8_t characterId; uint8_t characterId;
uint8_t characterColor; uint8_t characterColor;
uint8_t playerType; uint8_t playerType;
uint8_t controllerPort; uint8_t controllerPort;
std::array<uint16_t, NAMETAG_SIZE> nametag; std::array<uint16_t, NAMETAG_SIZE> nametag;
std::array<uint8_t, DISPLAY_NAME_SIZE> displayName; std::array<uint8_t, DISPLAY_NAME_SIZE> displayName;
std::array<uint8_t, CONNECT_CODE_SIZE> connectCode; std::array<uint8_t, CONNECT_CODE_SIZE> connectCode;
} PlayerSettings; } PlayerSettings;
typedef struct { typedef struct {
uint16_t stage; //Stage ID uint16_t stage; // Stage ID
uint32_t randomSeed; uint32_t randomSeed;
std::array<uint32_t, GAME_INFO_HEADER_SIZE> header; std::array<uint32_t, GAME_INFO_HEADER_SIZE> header;
std::array<uint32_t, UCF_TOGGLE_SIZE> ucfToggles; std::array<uint32_t, UCF_TOGGLE_SIZE> ucfToggles;
std::unordered_map<uint8_t, PlayerSettings> players; std::unordered_map<uint8_t, PlayerSettings> players;
uint8_t isPAL; uint8_t isPAL;
uint8_t isFrozenPS; uint8_t isFrozenPS;
uint8_t minorScene; uint8_t minorScene;
uint8_t majorScene; uint8_t majorScene;
std::vector<uint8_t> geckoCodes; std::vector<uint8_t> geckoCodes;
} GameSettings; } GameSettings;
typedef struct Game { typedef struct Game {
std::array<uint8_t, 4> version; std::array<uint8_t, 4> version;
std::unordered_map<int32_t, FrameData*> framesByIndex; std::unordered_map<int32_t, FrameData *> framesByIndex;
std::vector<std::unique_ptr<FrameData>> frames; std::vector<std::unique_ptr<FrameData>> frames;
GameSettings settings; GameSettings settings;
bool areSettingsLoaded = false; bool areSettingsLoaded = false;
int32_t frameCount; // Current/last frame count int32_t frameCount; // Current/last frame count
int32_t lastFinalizedFrame = -124; int32_t lastFinalizedFrame = -124;
//From OnGameEnd event // From OnGameEnd event
uint8_t winCondition; uint8_t winCondition;
} Game; } Game;
// TODO: This shouldn't be static. Doesn't matter too much atm because we always // TODO: This shouldn't be static. Doesn't matter too much atm because we always
// TODO: only read one file at a time // TODO: only read one file at a time
static std::unordered_map<uint8_t, uint32_t> asmEvents = { static std::unordered_map<uint8_t, uint32_t> asmEvents = {
{ EVENT_GAME_INIT, 320 }, {EVENT_GAME_INIT, 320},
{ EVENT_PRE_FRAME_UPDATE, 58 }, {EVENT_PRE_FRAME_UPDATE, 58},
{ EVENT_POST_FRAME_UPDATE, 33 }, {EVENT_POST_FRAME_UPDATE, 33},
{ EVENT_GAME_END, 1 }, {EVENT_GAME_END, 1},
{ EVENT_FRAME_START, 8 } {EVENT_FRAME_START, 8}};
};
class SlippiGame class SlippiGame {
{ public:
public: static std::unique_ptr<SlippiGame> FromFile(std::string path);
static std::unique_ptr<SlippiGame> FromFile(std::string path); bool AreSettingsLoaded();
bool AreSettingsLoaded(); bool DoesFrameExist(int32_t frame);
bool DoesFrameExist(int32_t frame); std::array<uint8_t, 4> GetVersion();
std::array<uint8_t, 4> GetVersion(); std::string GetVersionString();
std::string GetVersionString(); FrameData *GetFrame(int32_t frame);
FrameData* GetFrame(int32_t frame); FrameData *GetFrameAt(uint32_t pos);
FrameData* GetFrameAt(uint32_t pos); int32_t GetLastFinalizedFrame();
int32_t GetLastFinalizedFrame(); int32_t GetLatestIndex();
int32_t GetLatestIndex(); GameSettings *GetSettings();
GameSettings* GetSettings(); uint8_t GetGameEndMethod();
uint8_t GetGameEndMethod(); bool DoesPlayerExist(int8_t port);
bool DoesPlayerExist(int8_t port); bool IsProcessingComplete();
bool IsProcessingComplete();
private:
std::unique_ptr<Game> game;
std::unique_ptr<std::ifstream> file;
std::vector<uint8_t> rawData;
std::string path;
std::ofstream log;
std::vector<uint8_t> splitMessageBuf;
bool shouldResetSplitMessageBuf = false;
bool isProcessingComplete = false; private:
void processData(); std::unique_ptr<Game> game;
}; std::unique_ptr<std::ifstream> file;
} std::vector<uint8_t> rawData;
std::string path;
std::ofstream log;
std::vector<uint8_t> splitMessageBuf;
bool shouldResetSplitMessageBuf = false;
bool isProcessingComplete = false;
void processData();
};
} // namespace Slippi