From e4cec5788b6391d031158f789a5fcd02906d36ab Mon Sep 17 00:00:00 2001 From: Antidote Date: Sat, 16 Feb 2013 10:28:30 -0800 Subject: [PATCH] * Added ALTTP to libzelda * Added License header --- include/ALTTPEnums.hpp | 106 ++++++ include/ALTTPFile.hpp | 87 +++++ include/ALTTPFileReader.hpp | 39 +++ include/ALTTPFileWriter.hpp | 40 +++ include/ALTTPQuest.hpp | 221 ++++++++++++ include/ALTTPStructs.hpp | 207 +++++++++++ include/BinaryReader.hpp | 2 +- include/BinaryWriter.hpp | 1 + include/Mainpage.hpp | 14 + include/TextStream.hpp | 268 +++++++------- include/WiiBanner.h | 82 ----- include/WiiBanner.hpp | 14 + include/WiiFile.h | 68 ---- include/WiiFile.hpp | 14 + include/WiiSave.h | 45 --- include/WiiSave.hpp | 20 +- include/WiiSaveReader.hpp | 22 +- include/WiiSaveWriter.hpp | 14 + include/utility.hpp | 21 +- libzelda.pro | 18 +- src/ALTTPFile.cpp | 53 +++ src/ALTTPFileReader.cpp | 226 ++++++++++++ src/ALTTPFileWriter.cpp | 188 ++++++++++ src/ALTTPQuest.cpp | 678 ++++++++++++++++++++++++++++++++++++ src/ALTTPStructs.cpp | 82 +++++ src/BinaryReader.cpp | 5 +- src/TextStream.cpp | 451 ++++++++++++------------ src/WiiBanner.cpp | 17 +- src/WiiFile.cpp | 17 +- src/WiiSave.cpp | 21 +- src/WiiSaveReader.cpp | 22 +- src/WiiSaveWriter.cpp | 31 +- 32 files changed, 2517 insertions(+), 577 deletions(-) create mode 100644 include/ALTTPEnums.hpp create mode 100644 include/ALTTPFile.hpp create mode 100644 include/ALTTPFileReader.hpp create mode 100644 include/ALTTPFileWriter.hpp create mode 100644 include/ALTTPQuest.hpp create mode 100644 include/ALTTPStructs.hpp delete mode 100644 include/WiiBanner.h delete mode 100644 include/WiiFile.h delete mode 100644 include/WiiSave.h create mode 100644 src/ALTTPFile.cpp create mode 100644 src/ALTTPFileReader.cpp create mode 100644 src/ALTTPFileWriter.cpp create mode 100644 src/ALTTPQuest.cpp create mode 100644 src/ALTTPStructs.cpp diff --git a/include/ALTTPEnums.hpp b/include/ALTTPEnums.hpp new file mode 100644 index 0000000..8505bc8 --- /dev/null +++ b/include/ALTTPEnums.hpp @@ -0,0 +1,106 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_ENUMS_HPP__ +#define __ALTTP_ENUMS_HPP__ + +#include "Types.hpp" + +enum BowType : char +{ + BowNone, + BowArrows, + BowSilverArrows +}; + +enum BoomerangType : char +{ + BoomerangNone, + BoomerangBlue, + BoomerangRed +}; + +enum MagicType : char +{ + MagicNone, + MagicMushroom, + MagicPowder +}; + +enum ArmorType : char +{ + GreenJerkin, + BlueMail, + RedMail +}; + +enum BottleType : char +{ + BottleNone, + BottleMushroom, // No Use + BottleEmpty, + BottleRedPotion, + BottleBluePotion, + BottleFairy, + BottleBee, + BottleGoodBee +}; + + +enum ALTTPStartLocation +{ + LinksHouse = 0x00, + Sanctuary = 0x01, + Any = 0x05 +}; + +enum ALTTPProgressIndicator +{ + LinkInBed, + InCastleWithSword, + CompletedFirstDungeon, + BeatenAghanim +}; + +enum ALTTPMapIcon +{ + Nothing = 0x00, //? + CrossInKakariko = 0x01, //? + CrossAtFirstDungeon = 0x02, // + Pendant = 0x03, + MasterSword = 0x04, + AganhimCastle = 0x05, + Crystal1 = 0x06, + AllCrystals = 0x07, + AganhimGanonTower = 0x08 +}; + +enum ALTTPTagAlong +{ + Noone, + Zelda, + Unknown1, + Oldman, + ZeldaMessage, + Blind, + DwarfFrog, + DwarfLW, + Kiki, + Unknown2, + TheifsChest, + AfterBoss +}; + +#endif // __ALTTP_ENUMS_HPP__ diff --git a/include/ALTTPFile.hpp b/include/ALTTPFile.hpp new file mode 100644 index 0000000..33f5902 --- /dev/null +++ b/include/ALTTPFile.hpp @@ -0,0 +1,87 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_FILE_HPP__ +#define __ALTTP_FILE_HPP__ + +#include +#include + +class ALTTPQuest; + +/*! \class ALTTPFile + * \brief A Link to the Past data container class + * + * Contains all relevant data for an A Link to the Past + * SRM file. + */ +class ALTTPFile +{ +public: + /*! \brief Quest Iterator + * + * An Iterator typedef for iterating through the Quest lists + */ + typedef std::vector::iterator QuestIter; + + /*! \brief Default constructor + * + * + */ + ALTTPFile(); + + /*! \brief Constructor + * + * \param questList The primary quest list + * \param backupList The backup quest list + */ + ALTTPFile(std::vector questList, std::vector backupList); + + + /*! \brief Sets a quest at the given index + * + * \param id Index to the given quest + * \param val The new quest to assign to the given index + * \throw InvalidOperationException on index out of range + */ + void setQuest(Uint32 id, ALTTPQuest* val); + /*! \brief Returns the primary quest list + * + * \return The primary quest list + */ + std::vector questList() const; + + /*! \brief Returns a quest at the given index + * + * Returns a quest at the given index + * + * \return ALTTPQuest* + * \throw InvalidOperationException on index out of range + */ + ALTTPQuest* quest(Uint32 id) const; + + /*! \brief Returns the number of primary quests + * + * \return The number of quests + */ + Uint32 questCount() const; + +private: + + std::vector m_quests; + std::vector m_backup; +}; + +#endif // __ALTTP_FILE_HPP__ diff --git a/include/ALTTPFileReader.hpp b/include/ALTTPFileReader.hpp new file mode 100644 index 0000000..5048b69 --- /dev/null +++ b/include/ALTTPFileReader.hpp @@ -0,0 +1,39 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_FILE_READER_HPP__ +#define __ALTTP_FILE_READER_HPP__ + +#include +#include "Types.hpp" +#include "BinaryReader.hpp" +#include "ALTTPQuest.hpp" + +class ALTTPFile; + +class ALTTPFileReader : public BinaryReader +{ +public: + ALTTPFileReader(Uint8*, Uint64); + ALTTPFileReader(const std::string&); + + ALTTPFile* readFile(); +private: + ALTTPRoomFlags* readRoomFlags(); + ALTTPOverworldEvent* readOverworldEvent(); + ALTTPDungeonItemFlags readDungeonFlags(); +}; + +#endif // __ALTTP_FILE_READER_HPP__ diff --git a/include/ALTTPFileWriter.hpp b/include/ALTTPFileWriter.hpp new file mode 100644 index 0000000..f1ad9d1 --- /dev/null +++ b/include/ALTTPFileWriter.hpp @@ -0,0 +1,40 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_FILE_WRITER_HPP__ +#define __ALTTP_FILE_WRITER_HPP__ + +#include +#include +#include +#include "ALTTPQuest.hpp" + +class ALTTPFile; + +class ALTTPFileWriter : public BinaryWriter +{ +public: + ALTTPFileWriter(Uint8*, Uint64); + ALTTPFileWriter(const std::string&); + + void writeFile(ALTTPFile* file); +private: + void writeRoomFlags(ALTTPRoomFlags*); + void writeOverworldEvent(ALTTPOverworldEvent*); + void writeDungeonItems(ALTTPDungeonItemFlags); + Uint16 calculateChecksum(Uint32 game); +}; + +#endif // __ALTTP_FILE_WRITER_HPP__ diff --git a/include/ALTTPQuest.hpp b/include/ALTTPQuest.hpp new file mode 100644 index 0000000..b01344e --- /dev/null +++ b/include/ALTTPQuest.hpp @@ -0,0 +1,221 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_QUEST_HPP__ +#define __ALTTP_QUEST_HPP__ + +#include "Types.hpp" +#include +#include +#include "ALTTPStructs.hpp" +#include "ALTTPEnums.hpp" + +/*! \class ALTTPQuest + * \brief A Link to the Past Quest container class + * + * Contains all relevant data for an A Link to the Past + * Quest entry. + */ +class ALTTPQuest +{ +public: + ALTTPQuest(); + ~ALTTPQuest(); + + void setRoomFlags(std::vector flags); + void setRoomFlags(ALTTPRoomFlags* rf, Uint32 id); + std::vector roomFlags(); + ALTTPRoomFlags* roomFlags(Uint32 id); + + void setOverworldEvents(std::vector events); + void setOverworldEvents(ALTTPOverworldEvent* ow, Uint32 id); + std::vector overworldEvents() const; + ALTTPOverworldEvent* overworldEvent(Uint32 id) const; + + void setInventory(ALTTPInventory* inv); + ALTTPInventory* inventory() const; + + void setRupeeMax(Uint16 val); + Uint16 rupeeMax() const; + + void setRupeeCurrent(Uint16 val); + Uint16 rupeeCurrent() const; + + void setCompasses(ALTTPDungeonItemFlags flags); + ALTTPDungeonItemFlags compasses() const; + + void setBigKeys(ALTTPDungeonItemFlags flags); + ALTTPDungeonItemFlags bigKeys() const; + + void setDungeonMaps(ALTTPDungeonItemFlags flags); + ALTTPDungeonItemFlags dungeonMaps() const; + + void setWishingPond(Uint16 val); + Uint16 wishingPond() const; + + void setHealthMax(Uint8 val); + Uint8 healthMax() const; + + void setHealth(Uint8 val); + Uint8 health() const; + + void setMagicPower(Uint8 val); + Uint8 magicPower() const; + + void setKeys(Uint8 val); + Uint8 keys() const; + + void setBombUpgrades(Uint8 val); + Uint8 bombUpgrades() const; + + void setArrowUpgrades(Uint8 val); + Uint8 arrowUpgrades() const; + + void setHealthFiller(Uint8 val); + Uint8 healthFiller() const; + + void setMagicFiller(Uint8 val); + Uint8 magicFiller() const; + + void setPendants(ALTTPPendants val); + ALTTPPendants pendants() const; + + void setBombFiller(Uint8 val); + Uint8 bombFiller() const; + + void setArrowFiller(Uint8 val); + Uint8 arrowFiller() const; + void setArrows(Uint8 val); + Uint8 arrows() const; + + void setAbilityFlags(ALTTPAbilities val); + ALTTPAbilities abilityFlags() const; + + void setCrystals(ALTTPCrystals val); + ALTTPCrystals crystals() const; + + void setMagicUsage(ALTTPMagicUsage val); + ALTTPMagicUsage magicUsage() const; + + void setDungeonKeys(std::vector val); + void setDungeonKeys(Uint32 id, Uint8 val); + Uint8 dungeonKeys(Uint32 id) const; + Uint32 dungeonCount() const; + + void setProgressIndicator(ALTTPProgressIndicator val); + ALTTPProgressIndicator progressIndicator() const; + + void setProgressFlags1(ALTTPProgressFlags1 val); + ALTTPProgressFlags1 progressFlags1() const; + + void setMapIcon(ALTTPMapIcon val); + ALTTPMapIcon mapIcon() const; + + void setStartLocation(ALTTPStartLocation val); + ALTTPStartLocation startLocation() const; + + void setProgressFlags2(ALTTPProgressFlags2 val); + ALTTPProgressFlags2 progressFlags2() const; + + void setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val); + ALTTPLightDarkWorldIndicator lightDarkWorldIndicator() const; + + void setTagAlong(ALTTPTagAlong val); + ALTTPTagAlong tagAlong() const; + + void setOldManFlags(std::vector flags); + void setOldManFlag(Uint32 id, Uint8 val); + Uint8 oldManFlag(Uint32 id); + Uint32 oldManFlagCount() const; + + void setBombFlag(Uint8 flag); + Uint8 bombFlag() const; + + void setUnknown1(std::vector flags); + void setUnknown1(Uint32 id, Uint8 val); + Uint8 unknown1(Uint32 id); + Uint32 unknown1Count() const; + + void setPlayerName(std::vector playerName); + void setPlayerName(const std::string& playerName); + std::vector playerName() const; + std::string playerNameToString() const; + + void setValid(bool val); + bool valid(); + + void setDungeonDeathTotals(std::vector val); + void setDungeonDeathTotal(Uint32 id, Uint16 val); + Uint16 dungeonDeathTotal(Uint32 id) const; + Uint16 dungeonDeathTotalCount() const; + + void setUnknown2(Uint16 val); + Uint16 unknown2() const; + + void setDeathSaveCount(Uint16 val); + Uint16 deathSaveCount() const; + + void setPostGameDeathCounter(Int16 val); + Int16 postGameDeathCounter() const; + + void setChecksum(Uint16 checksum); + Uint16 checksum() const; +private: + std::vector m_roomFlags; + std::vector m_overworldEvents; + ALTTPInventory* m_inventory; + Uint16 m_rupeeMax; + Uint16 m_rupeeCurrent; + ALTTPDungeonItemFlags m_compasses; + ALTTPDungeonItemFlags m_bigKeys; + ALTTPDungeonItemFlags m_dungeonMaps; + Uint16 m_wishingPond; + Uint8 m_healthMax; + Uint8 m_health; + Uint8 m_magicPower; + Uint8 m_keys; + Uint8 m_bombUpgrades; + Uint8 m_arrowUpgrades; + Uint8 m_heartFiller; + Uint8 m_magicFiller; + ALTTPPendants m_pendants; + Uint8 m_bombFiller; + Uint8 m_arrowFiller; + Uint8 m_arrows; + ALTTPAbilities m_abilityFlags; + ALTTPCrystals m_crystals; + ALTTPMagicUsage m_magicUsage; + std::vector m_dungeonKeys; + ALTTPProgressIndicator m_progressIndicator; + ALTTPProgressFlags1 m_progressFlags1; + ALTTPMapIcon m_mapIcon; + ALTTPStartLocation m_startLocation; + ALTTPProgressFlags2 m_progressFlags2; + ALTTPLightDarkWorldIndicator m_lightDarkWorldIndicator; + ALTTPTagAlong m_tagAlong; + std::vector m_oldManFlags; + Uint8 m_bombFlag; + std::vector m_unknown1; + std::vector m_playerName; + Uint16 m_valid; + std::vector m_dungeonDeathTotals; + Uint16 m_unknown2; + Uint16 m_deathSaveCount; + Int16 m_postGameDeathCounter; + Uint16 m_checksum; +}; + + +#endif // __ALTTP_QUEST_HPP__ diff --git a/include/ALTTPStructs.hpp b/include/ALTTPStructs.hpp new file mode 100644 index 0000000..9ceba38 --- /dev/null +++ b/include/ALTTPStructs.hpp @@ -0,0 +1,207 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#ifndef __ALTTP_STRUCTS_HPP__ +#define __ALTTP_STRUCTS_HPP__ + +#include +#include "Types.hpp" + +/*! \struct ALTTPRoomFlags + */ +struct ALTTPRoomFlags +{ + bool Chest1:1; + bool Chest2:1; + bool Chest3:1; + bool Chest4:1; + bool Quadrant1:1; + bool Quadrant2:1; + bool Quadrant3:1; + bool Quadrant4:1; + bool Door1:1; + bool Door2:1; + bool Door3:1; + bool Door4:1; + bool BossBattleWon:1; + bool Key:1; + bool KeyOrChest:1; + bool ChestOrTile:1; +}; + +/*! \struct ALTTPOverworldEvent + */ +struct ALTTPOverworldEvent +{ + bool Unused1:1; + bool HeartPiece:1; + bool Overlay:1; + bool Unused2:1; + bool Unused3:1; + bool Unused4:1; + bool Set:1; + bool Unused5:1; +}; + +/*! \struct ALTTPInventory + */ +struct ALTTPInventory +{ + char Bow; + char Boomerang; + bool Hookshot; + char Bombs; // Bomb count + char Magic; + bool FireRod; + bool IceRod; + bool Bombos; + bool Ether; + bool Quake; + bool Torch; + bool Hammer; + char Flute; + bool BugNet; + bool Book; + bool Bottles; + bool Somaria; + bool Byrna; + bool MagicCape; + char MagicMirror; + char Gloves; + char Boots; + bool Flippers; + bool MoonPearl; + char Unused; //? + char Sword; + char Shield; + char Armor; + char BottleTypes[4]; + + std::string bowType(); + std::string boomerangType(); + std::string magicType(); + std::string armorType(); + std::string bottleType(Uint32); +}; + +/*! \struct ALTTPLightDarkWorldIndicator + */ +struct ALTTPLightDarkWorldIndicator +{ + bool Unused1:1; + bool Unused2:1; + bool Unused3:1; + bool Unused4:1; + bool Unused5:1; + bool Unused6:1; + bool IsDarkWorld:1; + bool Unused7:1; +}; + + +struct ALTTPDungeonItemFlags +{ + bool Unused1:1; + bool Unused2:1; + bool GanonsTower:1; + bool TurtleRock:1; + bool GargoylesDomain:1; + bool TowerOfHera:1; + bool IcePalace:1; + bool SkullWoods:1; + bool MiseryMire:1; + bool DarkPalace:1; + bool SwampPalace:1; + bool HyruleCastle2:1; // Doesn't exists in orignal game + bool DesertPalace:1; + bool EasternPalace:1; + bool HyruleCastle:1; // Doesn't exist in original game + bool SewerPassage:1; // Doesn't exist in original game +}; + +struct ALTTPPendants +{ + bool Courage:1; + bool Wisdom:1; + bool Power:1; + bool Unused1:1; + bool Unused2:1; + bool Unused3:1; + bool Unused4:1; + bool Unused5:1; +}; + +struct ALTTPAbilities +{ + char Nothing:1; //? + char Swim:1; + char Dash:1; + char Pull:1; + char Unknown1:1; //--- + char Talk:1; + char Read:1; + char Unknown2:1; //--- +}; + +struct ALTTPCrystals +{ + bool MiseryMire:1; + bool DarkPalace:1; + bool IcePalace:1; + bool TurtleRock:1; + bool SwampPalace:1; + bool GargoyleDomain:1; + bool SkullWoods:1; +}; + +struct ALTTPMagicUsage +{ + bool Normal:1; + bool Half:1; + bool Quarter:1; + bool Unused1:1; + bool Unused2:1; + bool Unused3:1; + bool Unused4:1; + bool Unused5:1; +}; + + +struct ALTTPProgressFlags1 +{ + bool UncleSecretPassage:1; + bool DyingPriest:1; //? + bool ZeldaSanctuary:1; //? + bool Unused1:1; + bool UncleLeftHouse:1; + bool BookOfMudora:1;//? Math says it's a guess need to investigate + bool DwarfPartner:1; //? + bool Unused2:1; +}; + + +struct ALTTPProgressFlags2 +{ + bool BottleFromBum:1; + bool BottleFromSalesMen:1; + bool Unused1:1; //? + bool FluteBoy:1; + bool ThiefsChest:1; + bool SavedSmithPartner:1; + bool Unused2:1; //? + bool SmithsHaveSword:1; +}; + +#endif // __ALTTP_STRUCTS_HPP__ diff --git a/include/BinaryReader.hpp b/include/BinaryReader.hpp index ff782f6..4d941bd 100644 --- a/include/BinaryReader.hpp +++ b/include/BinaryReader.hpp @@ -155,7 +155,7 @@ protected: * \throw IOException */ void writeBytes(Int8*, Int64); - std::string m_filename; + std::string m_filepath; }; #endif diff --git a/include/BinaryWriter.hpp b/include/BinaryWriter.hpp index 8709b9e..4ecb32b 100644 --- a/include/BinaryWriter.hpp +++ b/include/BinaryWriter.hpp @@ -12,6 +12,7 @@ // // You should have received a copy of the GNU General Public License // along with libZelda. If not, see + #ifndef __BINARYWRITER_HPP__ #define __BINARYWRITER_HPP__ diff --git a/include/Mainpage.hpp b/include/Mainpage.hpp index 7a6f930..b3138fd 100644 --- a/include/Mainpage.hpp +++ b/include/Mainpage.hpp @@ -1,3 +1,17 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef __MAINPAGE_HPP__ #define __MAINPAGE_HPP__ diff --git a/include/TextStream.hpp b/include/TextStream.hpp index ed1c554..e42e076 100644 --- a/include/TextStream.hpp +++ b/include/TextStream.hpp @@ -1,143 +1,157 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef __TEXTSTREAM_HPP__ #define __TEXTSTREAM_HPP__ #include "Stream.hpp" #include -#include - - -// TODO (Phil#1#): Need to actually use AccessMode -/*! \class TextStream - * \brief A Class for reading or writing Text data. - * - * TextStream is a class for reading/writing TextData.
- * It is currently incomplete, but usable, so use with caution.
- * Since it's incomplete it may not behave exactly as expected. - */ +#include + + +// TODO (Phil#1#): Need to actually use AccessMode +/*! \class TextStream + * \brief A Class for reading or writing Text data. + * + * TextStream is a class for reading/writing TextData.
+ * It is currently incomplete, but usable, so use with caution.
+ * Since it's incomplete it may not behave exactly as expected. + */ class TextStream : public Stream { -public: - /*! \enum TextMode - * \brief Specifies how the file is opened. +public: + /*! \enum TextMode + * \brief Specifies how the file is opened. */ - enum TextMode - { - Open, //!< The file is opened if it exists. - Create, //!< Create the file if it does not exist. - OpenOrCreate = Open|Create, //!< If the file does not exist when opening the file it is created - Truncate, //!< All the data currently that is in the file is erased. - Append //!< After opening the file the current line is set to the end of the buffer - }; - - /*! \enum AccessMode - * \brief Specifies how the Stream can be interacted with. + enum TextMode + { + Open, //!< The file is opened if it exists. + Create, //!< Create the file if it does not exist. + OpenOrCreate = Open|Create, //!< If the file does not exist when opening the file it is created + Truncate, //!< All the data currently that is in the file is erased. + Append //!< After opening the file the current line is set to the end of the buffer + }; + + /*! \enum AccessMode + * \brief Specifies how the Stream can be interacted with. */ - enum AccessMode - { - ReadOnly, //!< The Stream can only be read from. - WriteOnly,//!< The Stream can only be written to. - ReadWrite //!< The Stream can be read from or written to. - }; - - /*! \brief This constructor opens the file and loads all the lines. */ - TextStream(const std::string& filename, TextMode fileMode = Open, AccessMode accessMode = ReadWrite); - - /*! \brief Creates a new buffer and saves all lines to the specified file. - * \param filename The file, including path to save to. - */ - void save(const std::string& filename = ""); - - /*! \brief Reads the line at the current address. - * - * \return std::string The line read. - */ - std::string readLine(); - - /*! \brief Writes a line to the buffer - * - * \param str The string to write. - */ - void writeLine(const std::string& str); - - /*! \brief Reads a given amount of lines relative to the current address - * - * \param numLines The amount of lines to read. - * \return std::vector The lines read. - */ - std::vector readLines(Uint32 numLines); - - /*! \brief Reads a given list of lines relative to the current address - * - * \param lines The lines to write. - */ - void writeLines(std::vector lines); - - /*! \brief Reads all the lines in the current buffer. - * - * \return The lines read. - */ - std::vector readAllLines(); - - /*! \brief Reads a line at the given address. - * - * \param line The line to read. - * \return std::string The lines read. - */ - std::string readLineAt(Uint32 line); - - /*! \brief Writes a line at the given address. - * - * \param line The address to write to. - * \param str The string to write. - */ - void writeLineAt(Uint32 line, const std::string& str); - - /*! \brief Sets the current line in the Stream. - * - * \param line The line to seek to. - */ - void setCurrentLine(Uint32 line); - - /*! \brief Returns the current line in the stream. - * - * \return Uint32 The current line in the stream. - */ - Uint32 currentLine() const; - - /*! \brief Sets the AccessMode of the Stream. - * - * \param mode The mode to set. - */ - void setAccessMode(AccessMode mode); - - /*! \brief Returns the AccessMode of the Stream. - * - * \return AccessModeThe mode to set. - */ - AccessMode accessMode() const; - - /*! \brief Sets the Textmode of the Stream. - * - * \param mode The mode to set. - */ - void setTextMode(TextMode mode); - - /*! \brief Returns the TextMode of the Stream. - * - * \return TextMode The mode to set. - */ - TextMode textMode() const; - - bool isOpenForReading() const; + enum AccessMode + { + ReadOnly, //!< The Stream can only be read from. + WriteOnly,//!< The Stream can only be written to. + ReadWrite //!< The Stream can be read from or written to. + }; + + /*! \brief This constructor opens the file and loads all the lines. */ + TextStream(const std::string& filename, TextMode fileMode = Open, AccessMode accessMode = ReadWrite); + + /*! \brief Creates a new buffer and saves all lines to the specified file. + * \param filename The file, including path to save to. + */ + void save(const std::string& filename = ""); + + /*! \brief Reads the line at the current address. + * + * \return std::string The line read. + */ + std::string readLine(); + + /*! \brief Writes a line to the buffer + * + * \param str The string to write. + */ + void writeLine(const std::string& str); + + /*! \brief Reads a given amount of lines relative to the current address + * + * \param numLines The amount of lines to read. + * \return std::vector The lines read. + */ + std::vector readLines(Uint32 numLines); + + /*! \brief Reads a given list of lines relative to the current address + * + * \param lines The lines to write. + */ + void writeLines(std::vector lines); + + /*! \brief Reads all the lines in the current buffer. + * + * \return The lines read. + */ + std::vector readAllLines(); + + /*! \brief Reads a line at the given address. + * + * \param line The line to read. + * \return std::string The lines read. + */ + std::string readLineAt(Uint32 line); + + /*! \brief Writes a line at the given address. + * + * \param line The address to write to. + * \param str The string to write. + */ + void writeLineAt(Uint32 line, const std::string& str); + + /*! \brief Sets the current line in the Stream. + * + * \param line The line to seek to. + */ + void setCurrentLine(Uint32 line); + + /*! \brief Returns the current line in the stream. + * + * \return Uint32 The current line in the stream. + */ + Uint32 currentLine() const; + + /*! \brief Sets the AccessMode of the Stream. + * + * \param mode The mode to set. + */ + void setAccessMode(AccessMode mode); + + /*! \brief Returns the AccessMode of the Stream. + * + * \return AccessModeThe mode to set. + */ + AccessMode accessMode() const; + + /*! \brief Sets the Textmode of the Stream. + * + * \param mode The mode to set. + */ + void setTextMode(TextMode mode); + + /*! \brief Returns the TextMode of the Stream. + * + * \return TextMode The mode to set. + */ + TextMode textMode() const; + + bool isOpenForReading() const; bool isOpenForWriting() const; -private: +private: void loadLines(); std::string m_filename; TextMode m_textmode; - AccessMode m_accessmode; - - std::vector m_lines; - Uint32 m_currentLine; + AccessMode m_accessmode; + + std::vector m_lines; + Uint32 m_currentLine; Uint32 m_startLength; }; diff --git a/include/WiiBanner.h b/include/WiiBanner.h deleted file mode 100644 index c38fdf6..0000000 --- a/include/WiiBanner.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef WIIBANNER_H -#define WIIBANNER_H - - -#include -#include -#include - -class WiiImage -{ -public: - WiiImage(); - WiiImage(Uint32 width, Uint32 height, Uint8* data); - ~WiiImage(); - - void setWidth(const Uint32 width); - Uint32 width() const; - - void setHeight(const Uint32 height); - Uint32 height() const; - - void setData(const Uint8* data); - Uint8* data(); - - Uint8* toRGBA32(); - -private: - Uint32 m_width; - Uint32 m_height; - Uint8* m_data; -}; - -class WiiBanner -{ -public: - enum { NoCopy = 0x00000001, Bounce = 0x00000010, NoCopyBounce = NoCopy | Bounce }; - WiiBanner(); - WiiBanner(Uint32 gameId, const std::string& title, const std::string& subtitle, WiiImage* m_banner, std::vector icons); - virtual ~WiiBanner(); - - void setGameID(Uint64 id); - Uint64 gameID() const; - - void setBannerImage(WiiImage* banner); - WiiImage* bannerImage() const; - - void setBannerSize(Uint32 size); - Uint32 bannerSize() const; - - void setTitle(const std::string& title); - std::string title() const; - - void setSubtitle(const std::string& subtitle); - std::string subtitle() const; - - void addIcon(WiiImage* icon); - void setIcon(Uint32 id, WiiImage* icon); - WiiImage* getIcon(Uint32 id) const; - std::vector icons() const; - - void setAnimationSpeed(Uint16 animSpeed); - Uint16 animationSpeed() const; - - void setPermissions(Uint8 permissions); - Uint8 permissions() const; - - void setFlags(Uint32 flags); - Uint32 flags() const; -protected: -private: - Uint64 m_gameId; - WiiImage* m_banner; - Uint32 m_animSpeed; - Uint8 m_permissions; - Uint32 m_flags; - Uint32 m_bannerSize; - std::vector m_icons; - std::string m_title; - std::string m_subtitle; -}; - -#endif // WIIBANNER_H diff --git a/include/WiiBanner.hpp b/include/WiiBanner.hpp index c38fdf6..8d2827c 100644 --- a/include/WiiBanner.hpp +++ b/include/WiiBanner.hpp @@ -1,3 +1,17 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef WIIBANNER_H #define WIIBANNER_H diff --git a/include/WiiFile.h b/include/WiiFile.h deleted file mode 100644 index c98b348..0000000 --- a/include/WiiFile.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef WIIFILE_H -#define WIIFILE_H - -#include -#include -#include - -class WiiFile -{ -public: - enum Permission - { - OtherRead = 0x01, - OtherWrite = 0x02, - GroupRead = 0x04, - GroupWrite = 0x08, - OwnerRead = 0x10, - OwnerWrite = 0x20, - - // Mask values; - OtherRW = (OtherRead|OtherWrite), - GroupRW = (GroupRead|GroupWrite), - OwnerRW = (OwnerRead|OwnerWrite) - }; - - enum Type - { - File = 0x01, - Directory = 0x02 - }; - - WiiFile(); - WiiFile(const std::string& filename); - WiiFile(const std::string& filename, Uint8 permissions, const Uint8* data, Uint32 length); - virtual ~WiiFile(); - - void setFilename(const std::string& filename); - std::string filename() const; - - void setData(const Uint8* data); - Uint8* data() const; - - void setLength(const int len); - int length() const; - - void setPermissions(const Uint8 permissions); - Uint8 permissions() const; - - void setAttributes(const Uint8 attr); - Uint8 attributes() const; - - void setType(Type type); - Type type() const; - - bool isDirectory() const; - bool isFile() const; - -protected: -private: - Uint8 m_permissions; - Uint8 m_attributes; - Type m_type; - std::string m_filename; - int m_fileLen; - Uint8* m_fileData; -}; - -#endif // WIIFILE_H diff --git a/include/WiiFile.hpp b/include/WiiFile.hpp index c98b348..f5c70db 100644 --- a/include/WiiFile.hpp +++ b/include/WiiFile.hpp @@ -1,3 +1,17 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef WIIFILE_H #define WIIFILE_H diff --git a/include/WiiSave.h b/include/WiiSave.h deleted file mode 100644 index 14950c9..0000000 --- a/include/WiiSave.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef WIISAVE_H -#define WIISAVE_H - -#include -#include -#include - -class WiiFile; -class WiiBanner; -class WiiImage; -class BinaryReader; -class BinaryWriter; - -class WiiSave -{ -public: - typedef std::unordered_map::const_iterator FileIterator; - WiiSave(); - virtual ~WiiSave(); - - void addFile(const std::string& filename, WiiFile* file); - WiiFile* file(const std::string& filename) const; - std::unordered_map& fileList(); - - void setBanner(WiiBanner* banner); - WiiBanner* banner() const; - -protected: -private: - - void writeBanner(); - Uint32 writeFile(WiiFile* file); - void writeImage(WiiImage* image); - void writeCerts(Uint32 filesSize, Uint32 ngId, Uint8* ngPriv, Uint8* ngSig, Uint32 ngKeyId); - - std::string readNullTermString(); - - std::unordered_map m_files; - WiiBanner* m_banner; - - BinaryReader* m_reader; - BinaryWriter* m_writer; -}; - -#endif // WIISAVE_H diff --git a/include/WiiSave.hpp b/include/WiiSave.hpp index 5b59055..1aff7c7 100644 --- a/include/WiiSave.hpp +++ b/include/WiiSave.hpp @@ -1,5 +1,19 @@ -#ifndef WIISAVE_H -#define WIISAVE_H +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see +#ifndef __WII__SAVE_HPP__ +#define __WII__SAVE_HPP__ #include #include @@ -34,4 +48,4 @@ private: }; -#endif // WIISAVE_H +#endif // __WII__SAVE_HPP__ diff --git a/include/WiiSaveReader.hpp b/include/WiiSaveReader.hpp index 16860e8..e695d43 100644 --- a/include/WiiSaveReader.hpp +++ b/include/WiiSaveReader.hpp @@ -1,3 +1,17 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef __WII_SAVE_READER_HPP__ #define __WII_SAVE_READER_HPP__ @@ -18,9 +32,9 @@ public: WiiSave* readSave(); private: - WiiBanner* readBanner(); - WiiFile* readFile(); - WiiImage* readImage(Uint32 width, Uint32 height); - void readCerts(Uint32 totalSize); + WiiBanner* readBanner(); + WiiFile* readFile(); + WiiImage* readImage(Uint32 width, Uint32 height); + void readCerts(Uint32 totalSize); }; #endif // __WII_SAVE_READER_HPP__ diff --git a/include/WiiSaveWriter.hpp b/include/WiiSaveWriter.hpp index 910e51b..73c4af3 100644 --- a/include/WiiSaveWriter.hpp +++ b/include/WiiSaveWriter.hpp @@ -1,3 +1,17 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see #ifndef __WII_SAVE_WRITER_HPP__ #define __WII_SAVE_WRITER_HPP__ diff --git a/include/utility.hpp b/include/utility.hpp index c93e843..6ad061d 100644 --- a/include/utility.hpp +++ b/include/utility.hpp @@ -1,3 +1,18 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + #ifndef __UTILITY_H__ #define __UTILITY_H__ @@ -15,9 +30,9 @@ unsigned int swapU32(unsigned int val); float swapFloat(float val); double swapDouble(double val); -bool isSystemBigEndian(); - -void fillRandom(Uint8 * rndArea, Uint8 count); +bool isSystemBigEndian(); + +void fillRandom(Uint8 * rndArea, Uint8 count); #endif diff --git a/libzelda.pro b/libzelda.pro index 2e9ae2d..f711536 100644 --- a/libzelda.pro +++ b/libzelda.pro @@ -20,11 +20,8 @@ HEADERS += \ include/Exception.hpp \ include/BinaryWriter.hpp \ include/BinaryReader.hpp \ - include/WiiBanner.h \ include/WiiBanner.hpp \ - include/WiiFile.h \ include/WiiFile.hpp \ - include/WiiSave.h \ include/WiiSave.hpp \ include/WiiSaveReader.hpp \ include/WiiSaveWriter.hpp \ @@ -32,7 +29,13 @@ HEADERS += \ include/bn.h \ include/ec.h \ include/md5.h \ - include/sha1.h + include/sha1.h \ + include/ALTTPStructs.hpp \ + include/ALTTPQuest.hpp \ + include/ALTTPFileWriter.hpp \ + include/ALTTPFileReader.hpp \ + include/ALTTPFile.hpp \ + include/ALTTPEnums.hpp SOURCES += \ src/utility.cpp \ @@ -49,7 +52,12 @@ SOURCES += \ src/bn.cpp \ src/ec.cpp \ src/md5.c \ - src/sha1.cpp + src/sha1.cpp \ + src/ALTTPStructs.cpp \ + src/ALTTPQuest.cpp \ + src/ALTTPFileWriter.cpp \ + src/ALTTPFileReader.cpp \ + src/ALTTPFile.cpp system("exec doxygen libzelda.conf") system("cd doc/latex && make") diff --git a/src/ALTTPFile.cpp b/src/ALTTPFile.cpp new file mode 100644 index 0000000..eb8d317 --- /dev/null +++ b/src/ALTTPFile.cpp @@ -0,0 +1,53 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "ALTTPFile.hpp" +#include "ALTTPQuest.hpp" + +#include + +ALTTPFile::ALTTPFile() +{} + +ALTTPFile::ALTTPFile(std::vector quests, std::vector backup) + : m_quests(quests) + , m_backup(backup) +{ +} + +void ALTTPFile::setQuest(Uint32 id, ALTTPQuest* val) +{ + if (id > m_quests.size()) + throw InvalidOperationException("ALTTPFile::setQuest(Uint32, ALTTPQuest*) -> index out of range"); + + m_quests[id] = val; +} + +std::vector ALTTPFile::questList() const +{ + return m_quests; +} +ALTTPQuest* ALTTPFile::quest(Uint32 id) const +{ + if (id > m_quests.size()) + throw InvalidOperationException("ALTTPFile::setQuest(Uint32) -> index out of range"); + + return m_quests[id]; +} + +Uint32 ALTTPFile::questCount() const +{ + return m_quests.size(); +} diff --git a/src/ALTTPFileReader.cpp b/src/ALTTPFileReader.cpp new file mode 100644 index 0000000..c415494 --- /dev/null +++ b/src/ALTTPFileReader.cpp @@ -0,0 +1,226 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "ALTTPFileReader.hpp" +#include "ALTTPFile.hpp" +#include "ALTTPQuest.hpp" +#include + +ALTTPFileReader::ALTTPFileReader(Uint8* data, Uint64 length) + : BinaryReader(data, length) +{ +} + +ALTTPFileReader::ALTTPFileReader(const std::string& filename) + : BinaryReader(filename) +{ +} + +ALTTPFile* ALTTPFileReader::readFile() +{ + std::vector quests; + std::vector backup; + + for (Uint32 i = 0; i < 6; i++) + { + ALTTPQuest* quest = new ALTTPQuest(); + std::vector roomFlags; + std::vector owEvents; + std::vector dungeonKeys; + std::vector oldmanFlags; + std::vector unknown1; + std::vector playerName; + std::vector dungeonDeaths; + + int j = 0x140; + while ((j--) > 0) + { + roomFlags.push_back(readRoomFlags()); + } + quest->setRoomFlags(roomFlags); + + j = 0x0C0; + while ((j--) > 0) + owEvents.push_back(readOverworldEvent()); + + quest->setOverworldEvents(owEvents); + + quest->setInventory((ALTTPInventory*)this->readBytes(sizeof(ALTTPInventory))); + quest->setRupeeMax(this->readUInt16()); + quest->setRupeeCurrent(this->readUInt16()); + quest->setCompasses(readDungeonFlags()); + quest->setBigKeys(readDungeonFlags()); + quest->setDungeonMaps(readDungeonFlags()); + quest->setWishingPond(this->readUInt16()); + quest->setHealthMax(this->readByte()); + quest->setHealth(this->readByte()); + quest->setMagicPower(this->readByte()); + quest->setKeys(this->readByte()); + quest->setBombUpgrades(this->readByte()); + quest->setArrowUpgrades(this->readByte()); + quest->setHealthFiller(this->readByte()); + quest->setMagicFiller(this->readByte()); + ALTTPPendants pendants; + pendants.Courage = readBit(); + pendants.Wisdom = readBit(); + pendants.Power = readBit(); + pendants.Unused1 = false; + pendants.Unused2 = false; + pendants.Unused3 = false; + pendants.Unused4 = false; + pendants.Unused5 = false; + quest->setPendants(pendants); + quest->setBombFiller(this->readByte()); + quest->setArrowFiller(this->readByte()); + quest->setArrows(this->readByte()); + this->seek(1); + ALTTPAbilities abilities; + abilities.Nothing = this->readBit(); + abilities.Swim = this->readBit(); + abilities.Dash = this->readBit(); + abilities.Pull = this->readBit(); + abilities.Unknown1 = this->readBit(); + abilities.Talk = this->readBit(); + abilities.Read = this->readBit(); + abilities.Unknown2 = this->readBit(); + quest->setAbilityFlags(abilities); + quest->setCrystals((ALTTPCrystals&)*this->readBytes(sizeof(ALTTPCrystals))); + quest->setMagicUsage((ALTTPMagicUsage&)*this->readBytes(sizeof(ALTTPMagicUsage))); + + j = 0x10; + while ((j--) > 0) + { + dungeonKeys.push_back(this->readByte()); + } + + quest->setDungeonKeys(dungeonKeys); + seek(0x039); + quest->setProgressIndicator((ALTTPProgressIndicator)this->readByte()); + quest->setProgressFlags1((ALTTPProgressFlags1&)*this->readBytes(sizeof(ALTTPProgressFlags1))); + quest->setMapIcon((ALTTPMapIcon)this->readByte()); + quest->setStartLocation((ALTTPStartLocation)this->readByte()); + quest->setProgressFlags2((ALTTPProgressFlags2&)*this->readBytes(sizeof(ALTTPProgressFlags2))); + quest->setLightDarkWorldIndicator((ALTTPLightDarkWorldIndicator&)*this->readBytes(1)); + this->seek(1); + quest->setTagAlong((ALTTPTagAlong)this->readByte()); + + j = 6; + while((j--) > 0) + { + oldmanFlags.push_back(this->readByte()); + } + + quest->setOldManFlags(oldmanFlags); + quest->setBombFlag(this->readByte()); + + j = 5; + while((j--) > 0) + { + unknown1.push_back(this->readByte()); + } + + quest->setUnknown1(unknown1); + + j = 6; + while((j--) > 0) + { + playerName.push_back(this->readUInt16()); + } + + quest->setPlayerName(playerName); + quest->setValid((this->readUInt16() == 0x55AA)); + + j = 0x0D; + while((j--) > 0) + { + dungeonDeaths.push_back(this->readUInt16()); + } + quest->setDungeonDeathTotals(dungeonDeaths); + + quest->setUnknown2(this->readUInt16()); + quest->setDeathSaveCount(this->readUInt16()); + quest->setPostGameDeathCounter(this->readInt16()); + + this->seek(0xF7); + + quest->setChecksum(this->readUInt16()); + + if (i < 3) + quests.push_back(quest); + else + backup.push_back(quest); + } + + return new ALTTPFile(quests, backup); +} + +ALTTPRoomFlags* ALTTPFileReader::readRoomFlags() +{ + ALTTPRoomFlags* flags = new ALTTPRoomFlags; + flags->Chest1 = readBit(); + flags->Chest2 = readBit(); + flags->Chest3 = readBit(); + flags->Chest4 = readBit(); + flags->Quadrant1 = readBit(); + flags->Quadrant2 = readBit(); + flags->Quadrant3 = readBit(); + flags->Quadrant4 = readBit(); + flags->Door1 = readBit(); + flags->Door2 = readBit(); + flags->Door3 = readBit(); + flags->Door4 = readBit(); + flags->BossBattleWon = readBit(); + flags->Key = readBit(); + flags->KeyOrChest = readBit(); + flags->ChestOrTile = readBit(); + + return flags; +} + +ALTTPOverworldEvent* ALTTPFileReader::readOverworldEvent() +{ + ALTTPOverworldEvent* event = new ALTTPOverworldEvent; + event->Unused1 = readBit(); + event->HeartPiece= readBit(); + event->Overlay= readBit(); + event->Unused2= readBit(); + event->Unused3= readBit(); + event->Unused4= readBit(); + event->Set= readBit(); + event->Unused5= readBit(); + return event; +} + +ALTTPDungeonItemFlags ALTTPFileReader::readDungeonFlags() +{ + ALTTPDungeonItemFlags flags; + flags.Unused1 = readBit(); + flags.GanonsTower = readBit(); + flags.TurtleRock = readBit(); + flags.GargoylesDomain = readBit(); + flags.TowerOfHera = readBit(); + flags.IcePalace = readBit(); + flags.SkullWoods = readBit(); + flags.MiseryMire = readBit(); + flags.DarkPalace = readBit(); + flags.SwampPalace = readBit(); + flags.HyruleCastle2 = readBit(); + flags.DesertPalace = readBit(); + flags.EasternPalace = readBit(); + flags.HyruleCastle = readBit(); + flags.SewerPassage = readBit(); + + return flags; +} diff --git a/src/ALTTPFileWriter.cpp b/src/ALTTPFileWriter.cpp new file mode 100644 index 0000000..b4a2043 --- /dev/null +++ b/src/ALTTPFileWriter.cpp @@ -0,0 +1,188 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "ALTTPFileWriter.hpp" +#include "ALTTPFile.hpp" +#include "ALTTPQuest.hpp" +#include + +ALTTPFileWriter::ALTTPFileWriter(Uint8* data, Uint64 length) + : BinaryWriter(data, length) +{ +} + +ALTTPFileWriter::ALTTPFileWriter(const std::string& filename) + : BinaryWriter(filename) +{ +} + +void ALTTPFileWriter::writeFile(ALTTPFile* file) +{ + ALTTPQuest* quest = NULL; + for (Uint32 i = 0; i < 6; i++) + { + if (i < 3) + quest = file->quest(i); + else + quest = file->quest(i - 3); + + for (int j = 0; j < 0x140; j++) + { + this->writeRoomFlags(quest->roomFlags(j)); + } + + for (int j = 0; j < 0x0C0; j++) + { + this->writeOverworldEvent(quest->overworldEvent(j)); + } + + this->writeBytes((Int8*)quest->inventory(), sizeof(ALTTPInventory)); + this->writeUInt16(quest->rupeeMax()); + this->writeUInt16(quest->rupeeCurrent()); + this->writeDungeonItems(quest->compasses()); + this->writeDungeonItems(quest->bigKeys()); + this->writeDungeonItems(quest->dungeonMaps()); + this->writeUInt16(quest->wishingPond()); + this->writeByte(quest->healthMax()); + this->writeByte(quest->health()); + this->writeByte(quest->magicPower()); + this->writeByte(quest->keys()); + this->writeByte(quest->bombUpgrades()); + this->writeByte(quest->arrowUpgrades()); + this->writeByte(quest->healthFiller()); + this->writeByte(quest->magicFiller()); + ALTTPPendants pendants = quest->pendants(); + this->writeBit(pendants.Courage); + this->writeBit(pendants.Wisdom); + this->writeBit(pendants.Power); + this->writeByte(quest->bombFiller()); + this->writeByte(quest->arrowFiller()); + this->writeByte(quest->arrows()); + this->seek(1); + ALTTPAbilities abilities = quest->abilityFlags(); + this->writeBit(abilities.Nothing); + this->writeBit(abilities.Swim); + this->writeBit(abilities.Dash); + this->writeBit(abilities.Pull); + this->writeBit(abilities.Unknown1); + this->writeBit(abilities.Talk); + this->writeBit(abilities.Read); + this->writeBit(abilities.Unknown2); + ALTTPCrystals crystals = quest->crystals(); + this->writeBytes((Int8*)&crystals, sizeof(ALTTPCrystals)); + ALTTPMagicUsage magicUsage = quest->magicUsage(); + this->writeBytes((Int8*)&magicUsage, sizeof(ALTTPMagicUsage)); + + for (int j = 0; j < 0x010; j++) + this->writeByte(quest->dungeonKeys(j)); + + seek(0x039); + this->writeByte((Int8)quest->progressIndicator()); + ALTTPProgressFlags1 progress1 = quest->progressFlags1(); + this->writeBytes((Int8*)&progress1, sizeof(ALTTPProgressFlags1)); + this->writeByte(quest->mapIcon()); + this->writeByte(quest->startLocation()); + ALTTPProgressFlags2 progress2 = quest->progressFlags2(); + this->writeBytes((Int8*)&progress2, sizeof(ALTTPProgressFlags2)); + ALTTPLightDarkWorldIndicator indicator = quest->lightDarkWorldIndicator(); + this->writeBytes((Int8*)&indicator, 1); + this->seek(1); + this->writeByte(quest->tagAlong()); + + for(int j = 0; j < 6; j++) + this->writeByte(quest->oldManFlag(j)); + + this->writeByte(quest->bombFlag()); + + for (int j = 0; j < 5; j++) + this->writeByte(quest->unknown1(j)); + + for (int j = 0; j < 6; j++) + this->writeUInt16(quest->playerName()[j]); + + this->writeUInt16((quest->valid() == true ? 0x55AA : 0)); + + for (int j = 0; j < 0x0D; j++) + this->writeUInt16(quest->dungeonDeathTotal(j)); + + + this->writeUInt16(quest->unknown2()); + this->writeUInt16(quest->deathSaveCount()); + this->writeUInt16(quest->postGameDeathCounter()); + + this->seek(0xF7); + this->writeUInt16(calculateChecksum(i)); + } +} + +void ALTTPFileWriter::writeRoomFlags(ALTTPRoomFlags* flags) +{ + writeBit(flags->Chest1); + writeBit(flags->Chest2); + writeBit(flags->Chest3); + writeBit(flags->Chest4); + writeBit(flags->Quadrant1); + writeBit(flags->Quadrant2); + writeBit(flags->Quadrant3); + writeBit(flags->Quadrant4); + writeBit(flags->Door1); + writeBit(flags->Door2); + writeBit(flags->Door3); + writeBit(flags->Door4); + writeBit(flags->BossBattleWon); + writeBit(flags->Key); + writeBit(flags->KeyOrChest); + writeBit(flags->ChestOrTile); +} + +void ALTTPFileWriter::writeOverworldEvent(ALTTPOverworldEvent* event) +{ + writeBit(event->Unused1); + writeBit(event->HeartPiece); + writeBit(event->Overlay); + writeBit(event->Unused2); + writeBit(event->Unused3); + writeBit(event->Unused4); + writeBit(event->Set); + writeBit(event->Unused5); +} + +void ALTTPFileWriter::writeDungeonItems(ALTTPDungeonItemFlags flags) +{ + writeBit(flags.Unused1); + writeBit(flags.Unused2); + writeBit(flags.GanonsTower); + writeBit(flags.TurtleRock); + writeBit(flags.TowerOfHera); + writeBit(flags.IcePalace); + writeBit(flags.SkullWoods); + writeBit(flags.MiseryMire); + writeBit(flags.DarkPalace); + writeBit(flags.SwampPalace); + writeBit(flags.HyruleCastle2); + writeBit(flags.DesertPalace); + writeBit(flags.EasternPalace); + writeBit(flags.HyruleCastle); + writeBit(flags.SewerPassage); +} + +Uint16 ALTTPFileWriter::calculateChecksum(Uint32 game) +{ + Uint16 sum = 0x5a5a; + for (Uint32 i = 0; i < 0x4FE; i += 2) + sum -= *(Uint16*)(m_data + (i + (0x500 * game))); + + return sum; +} diff --git a/src/ALTTPQuest.cpp b/src/ALTTPQuest.cpp new file mode 100644 index 0000000..45f5ae4 --- /dev/null +++ b/src/ALTTPQuest.cpp @@ -0,0 +1,678 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "ALTTPQuest.hpp" +#include "InvalidOperationException.hpp" +#include + +ALTTPQuest::ALTTPQuest() +{ +} + +ALTTPQuest::~ALTTPQuest() +{ + m_roomFlags.clear(); + m_overworldEvents.clear(); + m_oldManFlags.clear(); + m_playerName.clear(); + m_unknown1.clear(); +} + +void ALTTPQuest::setRoomFlags(std::vector rf) +{ + m_roomFlags = rf; +} + +void ALTTPQuest::setRoomFlags(ALTTPRoomFlags* rf, Uint32 id) +{ + m_roomFlags[id] = rf; +} + +std::vector ALTTPQuest::roomFlags() +{ + return m_roomFlags; +} + +ALTTPRoomFlags* ALTTPQuest::roomFlags(Uint32 id) +{ + return m_roomFlags[id]; +} + +void ALTTPQuest::setOverworldEvents(std::vector ow) +{ + m_overworldEvents = ow; +} + +void ALTTPQuest::setOverworldEvents(ALTTPOverworldEvent* ow, Uint32 id) +{ + m_overworldEvents[id] = ow; +} + +std::vector ALTTPQuest::overworldEvents() const +{ + return m_overworldEvents; +} + +ALTTPOverworldEvent* ALTTPQuest::overworldEvent(Uint32 id) const +{ + if (id > m_overworldEvents.size() - 1) + throw InvalidOperationException("ALTTPQuest::overworldEvents(Uint32) -> index out of range"); + return m_overworldEvents[id]; +} + +void ALTTPQuest::setInventory(ALTTPInventory* inv) +{ + m_inventory = inv; +} + +ALTTPInventory* ALTTPQuest::inventory() const +{ + return m_inventory; +} + +void ALTTPQuest::setRupeeMax(Uint16 val) +{ + m_rupeeMax = val; +} + +Uint16 ALTTPQuest::rupeeMax() const +{ + return m_rupeeMax; +} + +void ALTTPQuest::setRupeeCurrent(Uint16 val) +{ + m_rupeeCurrent = val; +} + +Uint16 ALTTPQuest::rupeeCurrent() const +{ + return m_rupeeCurrent; +} + +void ALTTPQuest::setCompasses(ALTTPDungeonItemFlags flags) +{ + m_compasses = flags; +} + +ALTTPDungeonItemFlags ALTTPQuest::compasses() const +{ + return m_compasses; +} + +void ALTTPQuest::setBigKeys(ALTTPDungeonItemFlags flags) +{ + m_bigKeys = flags; +} + +ALTTPDungeonItemFlags ALTTPQuest::bigKeys() const +{ + return m_bigKeys; +} + +void ALTTPQuest::setDungeonMaps(ALTTPDungeonItemFlags flags) +{ + m_dungeonMaps = flags; +} + +ALTTPDungeonItemFlags ALTTPQuest::dungeonMaps() const +{ + return m_dungeonMaps; +} + +void ALTTPQuest::setWishingPond(Uint16 val) +{ + m_wishingPond = val; +} + +Uint16 ALTTPQuest::wishingPond() const +{ + return m_wishingPond; +} + +void ALTTPQuest::setHealthMax(Uint8 val) +{ + m_healthMax = val; +} + +Uint8 ALTTPQuest::healthMax() const +{ + return m_healthMax; +} + +void ALTTPQuest::setHealth(Uint8 val) +{ + m_health = val; +} + +Uint8 ALTTPQuest::health() const +{ + return m_health; +} + +void ALTTPQuest::setMagicPower(Uint8 val) +{ + m_magicPower = val; +} + +Uint8 ALTTPQuest::magicPower() const +{ + return m_magicPower; +} + +void ALTTPQuest::setKeys(Uint8 val) +{ + m_keys = val; +} + +Uint8 ALTTPQuest::keys() const +{ + return m_keys; +} + +void ALTTPQuest::setBombUpgrades(Uint8 val) +{ + m_bombUpgrades = val; +} + +Uint8 ALTTPQuest::bombUpgrades() const +{ + return m_bombUpgrades; +} + +void ALTTPQuest::setArrowUpgrades(Uint8 val) +{ + m_arrowUpgrades = val; +} + +Uint8 ALTTPQuest::arrowUpgrades() const +{ + return m_arrowUpgrades; +} + +void ALTTPQuest::setHealthFiller(Uint8 val) +{ + m_heartFiller = val; +} + +Uint8 ALTTPQuest::healthFiller() const +{ + return m_heartFiller; +} +void ALTTPQuest::setMagicFiller(Uint8 val) +{ + m_heartFiller = val; +} + +Uint8 ALTTPQuest::magicFiller() const +{ + return m_heartFiller; +} + +void ALTTPQuest::setPendants(ALTTPPendants val) +{ + m_pendants = val; +} + +ALTTPPendants ALTTPQuest::pendants() const +{ + return m_pendants; +} + +void ALTTPQuest::setBombFiller(Uint8 val) +{ + m_bombFiller = val; +} + +Uint8 ALTTPQuest::bombFiller() const +{ + return m_bombFiller; +} + +void ALTTPQuest::setArrowFiller(Uint8 val) +{ + m_arrowFiller = val; +} + +Uint8 ALTTPQuest::arrowFiller() const +{ + return m_arrowFiller; +} +void ALTTPQuest::setArrows(Uint8 val) +{ + m_arrows = val; +} + +Uint8 ALTTPQuest::arrows() const +{ + return m_arrows; +} + +void ALTTPQuest::setAbilityFlags(ALTTPAbilities val) +{ + m_abilityFlags = val; +} + +ALTTPAbilities ALTTPQuest::abilityFlags() const +{ + return m_abilityFlags; +} + +void ALTTPQuest::setCrystals(ALTTPCrystals val) +{ + m_crystals = val; +} + +ALTTPCrystals ALTTPQuest::crystals() const +{ + return m_crystals; +} + +void ALTTPQuest::setMagicUsage(ALTTPMagicUsage val) +{ + m_magicUsage = val; +} + +ALTTPMagicUsage ALTTPQuest::magicUsage() const +{ + return m_magicUsage; +} + +void ALTTPQuest::setDungeonKeys(std::vector val) +{ + m_dungeonKeys = val; +} + +void ALTTPQuest::setDungeonKeys(Uint32 id, Uint8 val) +{ + if (id > m_dungeonKeys.size() - 1) + throw InvalidOperationException("ALTTPQuest::setDungeonKeys(Uint32, Uint8) -> index out of range"); + + m_dungeonKeys[id] = val; +} + +Uint8 ALTTPQuest::dungeonKeys(Uint32 id) const +{ + if (id > m_dungeonKeys.size() - 1) + throw InvalidOperationException("ALTTPQuest::dungeonKeys() -> index out of range"); + + return m_dungeonKeys[id]; +} + +Uint32 ALTTPQuest::dungeonCount() const +{ + return m_dungeonKeys.size(); +} + + +void ALTTPQuest::setProgressIndicator(ALTTPProgressIndicator val) +{ + m_progressIndicator = val; +} + +ALTTPProgressIndicator ALTTPQuest::progressIndicator() const +{ + return m_progressIndicator; +} + +void ALTTPQuest::setProgressFlags1(ALTTPProgressFlags1 val) +{ + m_progressFlags1 = val; +} + +ALTTPProgressFlags1 ALTTPQuest::progressFlags1() const +{ + return m_progressFlags1; +} + +void ALTTPQuest::setMapIcon(ALTTPMapIcon val) +{ + m_mapIcon = val; +} + +ALTTPMapIcon ALTTPQuest::mapIcon() const +{ + return m_mapIcon; +} + +void ALTTPQuest::setStartLocation(ALTTPStartLocation val) +{ + m_startLocation = val; +} + +ALTTPStartLocation ALTTPQuest::startLocation() const +{ + return m_startLocation; +} + +void ALTTPQuest::setProgressFlags2(ALTTPProgressFlags2 val) +{ + m_progressFlags2 = val; +} + +ALTTPProgressFlags2 ALTTPQuest::progressFlags2() const +{ + return m_progressFlags2; +} + +void ALTTPQuest::setLightDarkWorldIndicator(ALTTPLightDarkWorldIndicator val) +{ + m_lightDarkWorldIndicator = val; +} + +ALTTPLightDarkWorldIndicator ALTTPQuest::lightDarkWorldIndicator() const +{ + return m_lightDarkWorldIndicator; +} + +void ALTTPQuest::setTagAlong(ALTTPTagAlong val) +{ + m_tagAlong = val; +} + +ALTTPTagAlong ALTTPQuest::tagAlong() const +{ + return m_tagAlong; +} + +void ALTTPQuest::setOldManFlags(std::vector flags) +{ + m_oldManFlags = flags; +} + +void ALTTPQuest::setOldManFlag(Uint32 id, Uint8 val) +{ + if (id > m_oldManFlags.size() - 1) + throw InvalidOperationException("ALTTPQuest::setOldManFlag(Uint32, Uint8) -> index out of range"); + + m_oldManFlags[id] = val; +} + +Uint8 ALTTPQuest::oldManFlag(Uint32 id) +{ + if (id > m_oldManFlags.size() - 1) + throw InvalidOperationException("ALTTPQuest::oldManFlag(Uint32) -> index out of range"); + + return m_oldManFlags[id]; +} + +Uint32 ALTTPQuest::oldManFlagCount() const +{ + return m_oldManFlags.size(); +} + +void ALTTPQuest::setBombFlag(Uint8 flag) +{ + m_bombFlag = flag; +} + +Uint8 ALTTPQuest::bombFlag() const +{ + return m_bombFlag; +} + +void ALTTPQuest::setUnknown1(std::vector flags) +{ + m_unknown1 = flags; +} + +void ALTTPQuest::setUnknown1(Uint32 id, Uint8 val) +{ + if (id > m_unknown1.size()) + throw InvalidOperationException("ALTTPQuest::setUnknown1(Uint32, Uint8) -> index out of range"); + + m_unknown1[id] = val; +} + +Uint8 ALTTPQuest::unknown1(Uint32 id) +{ + if (id > m_unknown1.size()) + throw InvalidOperationException("ALTTPQuest::unknown1(Uint32) -> index out of range"); + + return m_unknown1[id]; +} + +Uint32 ALTTPQuest::unknown1Count() const +{ + return m_unknown1.size(); +} + +void ALTTPQuest::setPlayerName(std::vector playerName) +{ + m_playerName = playerName; +} + +void ALTTPQuest::setPlayerName(const std::string& playerName) +{ + if (playerName == std::string() || playerName.size() > 6) + throw InvalidOperationException("ALTTPQuest::setPlayerName(const std::string&) -> playerName invalid"); + + m_playerName.clear(); + + for (Uint32 i = 0; i < 6; i++) + { + if (i > playerName.size() - 1) + { + m_playerName.push_back((Uint16)0xA9); + continue; + } + char c = playerName[i]; + if (c >= 'A' && c <= 'P' && c != 'I') + { + + m_playerName.push_back((Uint16)(c - 'A')); + continue; + } + if (c >= 'Q' && c <= 'Z') + { + std::cout << std::hex << (Uint16)((c - 'Q') + 0x20) << std::endl; + m_playerName.push_back((Uint16)((c - 'Q') + 0x20)); + continue; + } + if (c >= 'a' && c <= 'f') + { + std::cout << std::hex << (Uint16)((c - 'a') + 0x2A) << std::endl; + m_playerName.push_back((Uint16)((c - 'a') + 0x2A)); + continue; + } + if (c >= 'g' && c <= 'v') + { + if (c == 'k') + { + m_playerName.push_back(0x42); + continue; + } + if (c == 'i') + { + m_playerName.push_back(0x44); + continue; + } + m_playerName.push_back((Uint16)((c - 'g') + 0x40)); + continue; + } + if (c >= 'w' && c <= 'z') + { + m_playerName.push_back((Uint16)((c - 'w') + 0x60)); + continue; + } + if (c >= '0' && c <= '9') + { + m_playerName.push_back((Uint16)((c - '0') + 0x64)); + continue; + } + if (c == '-' || c == '.') + { + m_playerName.push_back((Uint16)(c - '-') + 0x80); + continue; + } + + switch(c) + { + case '?' : m_playerName.push_back(0x6E); break; + case '!' : m_playerName.push_back(0x6F); break; + case ',' : m_playerName.push_back(0x82); break; + case '(' : m_playerName.push_back(0x85); break; + case ')' : m_playerName.push_back(0x86); break; + case 'I' : m_playerName.push_back(0xAF); break; + } + } +} + +std::vector ALTTPQuest::playerName() const +{ + return m_playerName; +} + +std::string ALTTPQuest::playerNameToString() const +{ + std::string ret; + std::vector::const_iterator iter = m_playerName.begin(); + + for (; iter != m_playerName.end(); ++iter) + { + Int16 c = *iter; + + if (c >= 0x00 && c <= 0x0F) + { + ret.push_back((char)('A' + c)); + continue; + } + if (c >= 0x20 && c <= 0x29) + { + ret.push_back((char)('Q' + (c - 0x20))); + continue; + } + if (c >= 0x2A && c <= 0x2F) + { + ret.push_back((char)('a' + (c - 0x2A))); + continue; + } + if (c >= 0x40 && c <= 0x4F) + { + if (c == 0x42) + { + ret.push_back('k'); + continue; + } + if (c == 0x44) + { + ret.push_back('i'); + continue; + } + ret.push_back((char)('g' + (c - 0x40))); + } + if (c >= 0x60 && c <= 0x63) + { + ret.push_back((char)('w' + (c - 0x60))); + continue; + } + if (c >= 0x64 && c <= 0x6D) + { + ret.push_back((char)('0' + (c - 0x64))); + continue; + } + if (c == 0x80 || c == 0x81) + { + ret.push_back((char)('-' + (c - 0x80))); + continue; + } + + switch(c) + { + case 0x6E: ret.push_back('?'); break; + case 0x6F: ret.push_back('!'); break; + case 0x82: ret.push_back(','); break; + case 0x85: ret.push_back('('); break; + case 0x86: ret.push_back(')'); break; + case 0xAF: ret.push_back('I'); break; + } + } + return ret; +} + +void ALTTPQuest::setValid(bool val) +{ + m_valid = val; +} + +bool ALTTPQuest::valid() +{ + return m_valid; +} + +void ALTTPQuest::setDungeonDeathTotals(std::vector val) +{ + m_dungeonDeathTotals = val; +} + +void ALTTPQuest::setDungeonDeathTotal(Uint32 id, Uint16 val) +{ + if (id > m_dungeonDeathTotals.size()) + throw InvalidOperationException("ALTTPQuest::setDungeonDeathTotal(Uint32, Uint16) -> index out of range"); + + m_dungeonDeathTotals[id] = val; +} + +Uint16 ALTTPQuest::dungeonDeathTotal(Uint32 id) const +{ + if (id > m_dungeonDeathTotals.size()) + throw InvalidOperationException("ALTTPQuest::setDungeonDeathTotal(Uint32) -> index out of range"); + + return m_dungeonDeathTotals[id]; +} + +Uint16 ALTTPQuest::dungeonDeathTotalCount() const +{ + return m_dungeonDeathTotals.size(); +} + +void ALTTPQuest::setUnknown2(Uint16 val) +{ + m_unknown2 = val; +} + +Uint16 ALTTPQuest::unknown2() const +{ + return m_unknown2; +} + +void ALTTPQuest::setDeathSaveCount(Uint16 val) +{ + m_deathSaveCount = val; +} +Uint16 ALTTPQuest::deathSaveCount() const +{ + return m_deathSaveCount; +} + +void ALTTPQuest::setPostGameDeathCounter(Int16 val) +{ + m_postGameDeathCounter = val; +} + +Int16 ALTTPQuest::postGameDeathCounter() const +{ + return m_postGameDeathCounter; +} + +void ALTTPQuest::setChecksum(Uint16 checksum) +{ + m_checksum = checksum; +} + +Uint16 ALTTPQuest::checksum() const +{ + return m_checksum; +} diff --git a/src/ALTTPStructs.cpp b/src/ALTTPStructs.cpp new file mode 100644 index 0000000..f934d4e --- /dev/null +++ b/src/ALTTPStructs.cpp @@ -0,0 +1,82 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "ALTTPStructs.hpp" + +std::string ALTTPInventory::bowType() +{ + static const char* BowTypeStr[] = + { + "None", + "Bow & Arrows", + "Bow & Silver Arrows" + }; + + return BowTypeStr[(Uint32)Bow]; +} + +std::string ALTTPInventory::boomerangType() +{ + static const char* BoomerangTypStr[] = + { + "None", + "Blue Boomerang", + "Red Boomerang" + }; + + return BoomerangTypStr[(Uint32)Boomerang]; +} + +std::string ALTTPInventory::magicType() +{ + static const char* MagicTypeStr[] = + { + "None", + "Mushroom", + "Magic Powder" + }; + + return MagicTypeStr[(Uint32)Magic]; +} + +std::string ALTTPInventory::armorType() +{ + static const char* ArmorTypeStr[] = + { + "Green Jerkin", + "Blue Mail", + "Red Mail" + }; + + return ArmorTypeStr[(Uint32)Armor]; +} + +std::string ALTTPInventory::bottleType(Uint32 bottle) +{ + static const char* BottleTypeStr[]= + { + "None", + "Mushroom", // No Use + "Empty", + "Red Potion", + "Blue Potion", + "Fairy", + "Bee", + "Good Bee" + }; + + return BottleTypeStr[(Uint32)BottleTypes[bottle]]; +} + diff --git a/src/BinaryReader.cpp b/src/BinaryReader.cpp index 6914fff..49c0073 100644 --- a/src/BinaryReader.cpp +++ b/src/BinaryReader.cpp @@ -37,11 +37,11 @@ BinaryReader::BinaryReader(const Uint8* data, Uint64 length) : } BinaryReader::BinaryReader(const std::string& filename) - : m_filename(filename) + : m_filepath(filename) { Stream::setAutoResizing(false); FILE* in; - int length; + Uint32 length; in = fopen(filename.c_str(), "rb"); if (!in) @@ -67,7 +67,6 @@ BinaryReader::BinaryReader(const std::string& filename) break; done += blocksize; - std::cout << "Read " << done << " bytes" << std::endl; }while (done < length); fclose(in); diff --git a/src/TextStream.cpp b/src/TextStream.cpp index 09ed2c2..bdcd72f 100644 --- a/src/TextStream.cpp +++ b/src/TextStream.cpp @@ -1,16 +1,31 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + #include "TextStream.hpp" #include -#include "FileNotFoundException.hpp" +#include "FileNotFoundException.hpp" #include "InvalidOperationException.hpp" #include "IOException.hpp" TextStream::TextStream(const std::string& filename, TextMode fileMode, AccessMode accessMode) : m_filename(filename), m_textmode(fileMode), - m_accessmode(accessMode), + m_accessmode(accessMode), m_currentLine(0) -{ - setAutoResizing(true); +{ + setAutoResizing(true); FILE* in; int length; @@ -22,222 +37,222 @@ TextStream::TextStream(const std::string& filename, TextMode fileMode, AccessMod throw FileNotFoundException(filename.c_str()); in = fopen(filename.c_str(), "w+b"); - } - - if ((fileMode & Truncate) != Truncate) - { + } + + if ((fileMode & Truncate) != Truncate) + { fseek(in, 0, SEEK_END); length = ftell(in); fseek(in, 0, SEEK_SET); - m_data = new Uint8[length]; - fread(m_data, 1, length, in); - fclose(in); - } - else - { - length = 1; - m_data = new Uint8[1]; + m_data = new Uint8[length]; + fread(m_data, 1, length, in); + fclose(in); } - - if ((fileMode & Append) == Append) - m_position = length; - else - m_position = 0; - - m_length = length; - m_startLength = length; - + else + { + length = 1; + m_data = new Uint8[1]; + } + + if ((fileMode & Append) == Append) + m_position = length; + else + m_position = 0; + + m_length = length; + m_startLength = length; + loadLines(); -} - -void TextStream::save(const std::string& filename) -{ - if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for writing"); - if (filename != std::string()) - m_filename = filename; - - // We need a new buffer to write the new lines - if (m_data) - delete[] m_data; - - m_position = 0; - m_length = 1; - - // Set the new buffer - m_data = new Uint8[m_length]; - - // Now write all the strings to the new buffer - for (std::string s : m_lines) - writeBytes((Int8*)s.c_str(), s.size()); - - FILE* out = fopen(m_filename.c_str(), "wb"); - - if(out) - { - fwrite(m_data, 1, m_length, out); - fclose(out); - } - else - throw FileNotFoundException(m_filename); -} - -std::string TextStream::readLine() -{ - if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for reading"); - - if (m_currentLine > m_lines.size()) - throw IOException("Position past stream bounds"); - - return m_lines[m_currentLine++]; -} - - -void TextStream::writeLine(const std::string& str) -{ - if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for writing"); - else if (m_currentLine > m_lines.size()) - { - m_lines.push_back(str); - m_currentLine++; - return; - } - - m_lines[m_currentLine++] = str; -} - -void TextStream::writeLines(std::vector strings) -{ - if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for writing"); - - for (std::string s: strings) - writeLine(s); -} - -std::vector TextStream::readLines(Uint32 numLines) -{ - if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for reading"); - - if (numLines > m_lines.size()) - throw InvalidOperationException("numLines exceeds the number of stored strings."); - - Uint32 currentLine = m_currentLine; - std::vector ret; - - while ((m_currentLine++) <= currentLine + numLines) - ret.push_back(m_lines[m_currentLine]); - - return ret; -} - -std::string TextStream::readLineAt(Uint32 line) -{ - if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for reading"); - if (line <= 0) - throw InvalidOperationException("A line cannot be zero indexed"); - - if ((line - 1) >= m_lines.size()) - throw IOException("Line index out of range"); - return m_lines[line - 1]; -} - -void TextStream::writeLineAt(Uint32 line, const std::string& str) -{ - if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for reading"); - if (line <= 0) - throw InvalidOperationException("A line cannot be zero indexed"); - - m_currentLine = line; - writeLine(str); -} - -std::vector TextStream::readAllLines() -{ - if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) - throw InvalidOperationException("Stream not open for reading"); - - return m_lines; -} - -void TextStream::setCurrentLine(Uint32 line) -{ - if (line <= 0) - throw InvalidOperationException("A line cannot be zero indexed"); - m_currentLine = line - 1; -} - -Uint32 TextStream::currentLine() const -{ - return m_currentLine + 1; -} - -void TextStream::setAccessMode(AccessMode mode) -{ - m_accessmode = mode; -} - -TextStream::AccessMode TextStream::accessMode() const -{ - return m_accessmode; -} - -void TextStream::setTextMode(TextMode mode) -{ - m_textmode = mode; -} - -TextStream::TextMode TextStream::textMode() const -{ - return m_textmode; -} - -bool TextStream::isOpenForReading() const -{ - return ((m_accessmode == ReadOnly || m_accessmode == ReadWrite) && m_accessmode != WriteOnly); -} - -bool TextStream::isOpenForWriting() const -{ - return ((m_accessmode == WriteOnly || m_accessmode == ReadWrite) && m_accessmode != ReadOnly); -} - -// PRIVATE FUNCTIONS -void TextStream::loadLines() -{ - while (!atEnd()) - { - std::string line; - Uint8 c; - for (;;) - { - c = readByte(); - - if (c == '\r' || c == '\n') - { - m_currentLine++; - line.push_back(c); - if (*(Uint8*)(m_data + m_position + 1) == '\n') - { - line.push_back('\n'); - m_position++; // advance position past the new line character - } - break; - } - - if (c == '\0') - { - line.push_back('\n'); - break; - } - line.push_back(c); - } - - m_lines.push_back(line); - } -} +} + +void TextStream::save(const std::string& filename) +{ + if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for writing"); + if (filename != std::string()) + m_filename = filename; + + // We need a new buffer to write the new lines + if (m_data) + delete[] m_data; + + m_position = 0; + m_length = 1; + + // Set the new buffer + m_data = new Uint8[m_length]; + + // Now write all the strings to the new buffer + for (std::string s : m_lines) + writeBytes((Int8*)s.c_str(), s.size()); + + FILE* out = fopen(m_filename.c_str(), "wb"); + + if(out) + { + fwrite(m_data, 1, m_length, out); + fclose(out); + } + else + throw FileNotFoundException(m_filename); +} + +std::string TextStream::readLine() +{ + if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for reading"); + + if (m_currentLine > m_lines.size()) + throw IOException("Position past stream bounds"); + + return m_lines[m_currentLine++]; +} + + +void TextStream::writeLine(const std::string& str) +{ + if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for writing"); + else if (m_currentLine > m_lines.size()) + { + m_lines.push_back(str); + m_currentLine++; + return; + } + + m_lines[m_currentLine++] = str; +} + +void TextStream::writeLines(std::vector strings) +{ + if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for writing"); + + for (std::string s: strings) + writeLine(s); +} + +std::vector TextStream::readLines(Uint32 numLines) +{ + if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for reading"); + + if (numLines > m_lines.size()) + throw InvalidOperationException("numLines exceeds the number of stored strings."); + + Uint32 currentLine = m_currentLine; + std::vector ret; + + while ((m_currentLine++) <= currentLine + numLines) + ret.push_back(m_lines[m_currentLine]); + + return ret; +} + +std::string TextStream::readLineAt(Uint32 line) +{ + if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for reading"); + if (line <= 0) + throw InvalidOperationException("A line cannot be zero indexed"); + + if ((line - 1) >= m_lines.size()) + throw IOException("Line index out of range"); + return m_lines[line - 1]; +} + +void TextStream::writeLineAt(Uint32 line, const std::string& str) +{ + if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for reading"); + if (line <= 0) + throw InvalidOperationException("A line cannot be zero indexed"); + + m_currentLine = line; + writeLine(str); +} + +std::vector TextStream::readAllLines() +{ + if (m_accessmode != ReadOnly && m_accessmode != ReadWrite) + throw InvalidOperationException("Stream not open for reading"); + + return m_lines; +} + +void TextStream::setCurrentLine(Uint32 line) +{ + if (line <= 0) + throw InvalidOperationException("A line cannot be zero indexed"); + m_currentLine = line - 1; +} + +Uint32 TextStream::currentLine() const +{ + return m_currentLine + 1; +} + +void TextStream::setAccessMode(AccessMode mode) +{ + m_accessmode = mode; +} + +TextStream::AccessMode TextStream::accessMode() const +{ + return m_accessmode; +} + +void TextStream::setTextMode(TextMode mode) +{ + m_textmode = mode; +} + +TextStream::TextMode TextStream::textMode() const +{ + return m_textmode; +} + +bool TextStream::isOpenForReading() const +{ + return ((m_accessmode == ReadOnly || m_accessmode == ReadWrite) && m_accessmode != WriteOnly); +} + +bool TextStream::isOpenForWriting() const +{ + return ((m_accessmode == WriteOnly || m_accessmode == ReadWrite) && m_accessmode != ReadOnly); +} + +// PRIVATE FUNCTIONS +void TextStream::loadLines() +{ + while (!atEnd()) + { + std::string line; + Uint8 c; + for (;;) + { + c = readByte(); + + if (c == '\r' || c == '\n') + { + m_currentLine++; + line.push_back(c); + if (*(Uint8*)(m_data + m_position + 1) == '\n') + { + line.push_back('\n'); + m_position++; // advance position past the new line character + } + break; + } + + if (c == '\0') + { + line.push_back('\n'); + break; + } + line.push_back(c); + } + + m_lines.push_back(line); + } +} diff --git a/src/WiiBanner.cpp b/src/WiiBanner.cpp index 8c3d9ec..fb89381 100644 --- a/src/WiiBanner.cpp +++ b/src/WiiBanner.cpp @@ -1,4 +1,19 @@ -#include "WiiBanner.h" +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "WiiBanner.hpp" #include #include diff --git a/src/WiiFile.cpp b/src/WiiFile.cpp index fab668f..9ea5b79 100644 --- a/src/WiiFile.cpp +++ b/src/WiiFile.cpp @@ -1,4 +1,19 @@ -#include "WiiFile.h" +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "WiiFile.hpp" WiiFile::WiiFile() : m_permissions(WiiFile::GroupRW|WiiFile::OtherRW|WiiFile::OwnerRW), diff --git a/src/WiiSave.cpp b/src/WiiSave.cpp index f81f4e2..7877baf 100644 --- a/src/WiiSave.cpp +++ b/src/WiiSave.cpp @@ -1,6 +1,21 @@ -#include "WiiSave.h" -#include "WiiFile.h" -#include "WiiBanner.h" +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + +#include "WiiSave.hpp" +#include "WiiFile.hpp" +#include "WiiBanner.hpp" #include "BinaryReader.hpp" #include "BinaryWriter.hpp" #include "IOException.hpp" diff --git a/src/WiiSaveReader.cpp b/src/WiiSaveReader.cpp index 30439dc..fa477d2 100644 --- a/src/WiiSaveReader.cpp +++ b/src/WiiSaveReader.cpp @@ -1,7 +1,22 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + #include "WiiSaveReader.hpp" -#include "WiiSave.h" -#include "WiiFile.h" -#include "WiiBanner.h" +#include "WiiSave.hpp" +#include "WiiFile.hpp" +#include "WiiBanner.hpp" #include "md5.h" #include "aes.h" #include "ec.h" @@ -26,7 +41,6 @@ WiiSaveReader::WiiSaveReader(const Uint8* data, Uint64 length) WiiSaveReader::WiiSaveReader(const std::string& filename) : BinaryReader(filename) { - std::cout << filename << std::endl; setEndianess(BigEndian); } diff --git a/src/WiiSaveWriter.cpp b/src/WiiSaveWriter.cpp index 63b702f..c4e1e5a 100644 --- a/src/WiiSaveWriter.cpp +++ b/src/WiiSaveWriter.cpp @@ -1,17 +1,30 @@ +// This file is part of libZelda. +// +// libZelda is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// libZelda is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with libZelda. If not, see + #include "WiiSaveWriter.hpp" - -#include "WiiSave.h" -#include "WiiFile.h" -#include "WiiBanner.h" - -#include "WiiSave.h" -#include "WiiFile.h" -#include "WiiBanner.h" +#include "WiiSave.hpp" +#include "WiiFile.hpp" +#include "WiiBanner.hpp" +#include "WiiSave.hpp" +#include "WiiFile.hpp" +#include "WiiBanner.hpp" #include "BinaryWriter.hpp" #include "IOException.hpp" #include "aes.h" #include "ec.h" -#include +#include "utility.hpp" #include "md5.h" #include "sha1.h"