diff --git a/src/Athena/SkywardSwordFileReader.cpp b/src/Athena/SkywardSwordFileReader.cpp index 8c8f3a4..795cdac 100644 --- a/src/Athena/SkywardSwordFileReader.cpp +++ b/src/Athena/SkywardSwordFileReader.cpp @@ -40,51 +40,42 @@ SkywardSwordFile* SkywardSwordFileReader::read() { SkywardSwordFile* file = NULL; - try + if (base::length() != 0xFBE0) { - if (base::length() != 0xFBE0) - { - atError("File not the expected size of 0xFBE0"); - return nullptr; - } - - atUint32 magic = base::readUint32(); - - if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) - { - atError("Not a valid Skyward Sword save file"); - return nullptr; - } - - base::seek(0x01C, SeekOrigin::Begin); - atUint32 headerSize = base::readUint32(); // Seems to be (headerSize - 1) - - if (headerSize != 0x1D) - { - atError("Invalid header size, Corrupted data?"); - return nullptr; - } - - // Time to read in each slot - file = new SkywardSwordFile; - file->setRegion((magic == SkywardSwordFile::USMagic ? Region::NTSC : (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL))); - - for (int i = 0; i < 3; i++) - { - SkywardSwordQuest* q = new SkywardSwordQuest(base::readUBytes(0x53C0), 0x53C0); - atUint64 pos = base::position(); - // seek to the skip data for this particular quest - base::seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); - q->setSkipData(base::readUBytes(0x24)); - base::seek(pos, SeekOrigin::Begin); - file->addQuest(q); - } + atError("File not the expected size of 0xFBE0"); + return nullptr; } - catch (...) + + atUint32 magic = base::readUint32(); + + if (magic != SkywardSwordFile::USMagic && magic != SkywardSwordFile::JAMagic && magic != SkywardSwordFile::EUMagic) { - delete file; - file = NULL; - throw; + atError("Not a valid Skyward Sword save file"); + return nullptr; + } + + base::seek(0x01C, SeekOrigin::Begin); + atUint32 headerSize = base::readUint32(); // Seems to be (headerSize - 1) + + if (headerSize != 0x1D) + { + atError("Invalid header size, Corrupted data?"); + return nullptr; + } + + // Time to read in each slot + file = new SkywardSwordFile; + file->setRegion((magic == SkywardSwordFile::USMagic ? Region::NTSC : (magic == SkywardSwordFile::JAMagic ? Region::NTSCJ : Region::PAL))); + + for (int i = 0; i < 3; i++) + { + SkywardSwordQuest* q = new SkywardSwordQuest(base::readUBytes(0x53C0), 0x53C0); + atUint64 pos = base::position(); + // seek to the skip data for this particular quest + base::seek(0xFB60 + (i * 0x24), SeekOrigin::Begin); + q->setSkipData(base::readUBytes(0x24)); + base::seek(pos, SeekOrigin::Begin); + file->addQuest(q); } return file; diff --git a/src/Athena/SpriteFileReader.cpp b/src/Athena/SpriteFileReader.cpp index 485a299..57e2e75 100644 --- a/src/Athena/SpriteFileReader.cpp +++ b/src/Athena/SpriteFileReader.cpp @@ -40,193 +40,184 @@ Sakura::SpriteFile* SpriteFileReader::readFile() { Sakura::SpriteFile* ret = NULL; - try - { - atUint32 magic = base::readUint32(); + atUint32 magic = base::readUint32(); - if (magic != Sakura::SpriteFile::Magic) + if (magic != Sakura::SpriteFile::Magic) + { + atError("Not a valid Sakura Sprite container"); + return nullptr; + } + + atUint32 version = base::readUint32(); + + // TODO: Make this more verbose + if (version != Sakura::SpriteFile::Version) + { + atError("Unsupported version"); + return nullptr; + } + + // After reading in the magic and version we need to load some + // metadata about the file. + // Such as the texture count, it's dimensions, and it's origin. + // After that we have the number of sprites contained in this + // sprite container. + atUint16 textureCount = base::readUint16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states + // This is probably overkill, but it's better safe than sorry. + atUint32 width = base::readUint32(); + atUint32 height = base::readUint32(); + float originX = base::readFloat(); + float originY = base::readFloat(); + atUint16 spriteCount = base::readUint16(); + + // Lets go ahead and create or new container. + ret = new Sakura::SpriteFile(width, height, originX, originY); + + // The next four bytes are reserved to keep the header 32 byte aligned. + // This isn't necessary for most systems, but it's eventually planned + // to migrate this code to Big Endian based systems, such as the wii + // which require data to be 32 byte aligned, or it causes some issues. + // It's also convenient to have this, for later expansion. + atUint32 reserved = base::readUint32(); + UNUSED(reserved); + + // Next we have to load the textures + // If we tried to add them one at a time to the sprite container + // it will be slow as hell, so we store them in a vector locally + // then give that vector the the container, this bypasses the de-reference + // for each texture +#ifndef ATHENA_USE_QT + std::vector textures; +#else + QList textures; +#endif + + for (atUint16 i = 0; i < textureCount; i++) + { + Sakura::STexture* texture = new Sakura::STexture; + texture->Filepath = base::readString(); + texture->Preload = base::readBool(); + textures.push_back(texture); + } + + ret->setTextures(textures); + + // Now for the sprites + // The sprites are a bit more difficult, they are stored in an unordered_map + // with it's name as the key, this means we can't have two sprites with the same name + // Normally this isn't a problem, but someone may decide to copy and paste a sprite + // and forget to change the name, that needs to be handled, but it's outside the scope + // of this reader. +#ifndef ATHENA_USE_QT + std::unordered_map sprites; +#else + QMap sprites; +#endif + + for (atUint16 i = 0; i < spriteCount; i++) + { + Sakura::Sprite* sprite = new Sakura::Sprite(ret); +#ifndef ATHENA_USE_QT + std::string name = base::readString(); +#else + QString name = QString::fromStdString(base::readString()); +#endif + sprite->setName(name); + atUint16 frameCount = base::readUint16(); + atUint16 stateCount = base::readUint16(); + + // Each state id corresponds to a texture held in the parent class + std::vector stateIds; + + for (int j = 0; j < stateCount; j++) + stateIds.push_back(base::readUint16()); + + + sprite->setStateIds(stateIds); + + // Now to read the sprite parts. + // The parts allow us to build retro style sprites very easily + // making it possible to use one texture atlas for all possible + // frame combinations, this reduces the amount of memory overhead + // and the storage footprint, while Sakura supports packs and zips + // it's still a bad idea to have a metric ton of texture resources + // littering the place +#ifndef ATHENA_USE_QT + std::vector frames; +#else + QList frames; +#endif + + for (atUint32 k = 0; k < frameCount; k++) { - atError("Not a valid Sakura Sprite container"); + Sakura::SpriteFrame* frame = new Sakura::SpriteFrame(sprite); + frame->setFrameTime(base::readFloat()); + atUint16 partCount = base::readUint16(); + + +#ifndef ATHENA_USE_QT + std::vector parts; +#else + QList parts; +#endif + + for (atUint8 j = 0; j < partCount; j++) + { + Sakura::SpritePart* part = new Sakura::SpritePart(frame); +#ifndef ATHENA_USE_QT + std::string name = base::readString(); +#else + QString name = QString::fromStdString(base::readString()); +#endif + part->setName(name); + part->setCollision(base::readBool()); + + float xOff = base::readFloat(); + float yOff = base::readFloat(); + part->setOffset(xOff, yOff); + float texXOff = base::readFloat(); + float texYOff = base::readFloat(); + part->setTextureOffset(texXOff, texYOff); + atUint32 width = base::readUint32(); + atUint32 height = base::readUint32(); + part->setSize(width, height); + bool flippedH = base::readBool(); + part->setFlippedHorizontally(flippedH); + bool flippedV = base::readBool(); + part->setFlippedVertically(flippedV); + + parts.push_back(part); + } + + frame->setParts(parts); + frames.push_back(frame); + } + + sprite->setFrames(frames); +#ifndef ATHENA_USE_QT + + if (sprite->name() != std::string()) + { + std::string nameLow(sprite->name()); + Athena::utility::tolower(nameLow); + sprites[nameLow] = sprite; + } + +#else + + if (!sprite->name().isEmpty()) + sprites[sprite->name().toLower()] = sprite; + +#endif + else + { + atError("Sprite names cannot be empty"); return nullptr; } - - atUint32 version = base::readUint32(); - - // TODO: Make this more verbose - if (version != Sakura::SpriteFile::Version) - { - atError("Unsupported version"); - return nullptr; - } - - // After reading in the magic and version we need to load some - // metadata about the file. - // Such as the texture count, it's dimensions, and it's origin. - // After that we have the number of sprites contained in this - // sprite container. - atUint16 textureCount = base::readUint16(); // Having it as a Uint16 gives us the ability to have up to 65536 different states - // This is probably overkill, but it's better safe than sorry. - atUint32 width = base::readUint32(); - atUint32 height = base::readUint32(); - float originX = base::readFloat(); - float originY = base::readFloat(); - atUint16 spriteCount = base::readUint16(); - - // Lets go ahead and create or new container. - ret = new Sakura::SpriteFile(width, height, originX, originY); - - // The next four bytes are reserved to keep the header 32 byte aligned. - // This isn't necessary for most systems, but it's eventually planned - // to migrate this code to Big Endian based systems, such as the wii - // which require data to be 32 byte aligned, or it causes some issues. - // It's also convenient to have this, for later expansion. - atUint32 reserved = base::readUint32(); - UNUSED(reserved); - - // Next we have to load the textures - // If we tried to add them one at a time to the sprite container - // it will be slow as hell, so we store them in a vector locally - // then give that vector the the container, this bypasses the de-reference - // for each texture -#ifndef ATHENA_USE_QT - std::vector textures; -#else - QList textures; -#endif - - for (atUint16 i = 0; i < textureCount; i++) - { - Sakura::STexture* texture = new Sakura::STexture; - texture->Filepath = base::readString(); - texture->Preload = base::readBool(); - textures.push_back(texture); - } - - ret->setTextures(textures); - - // Now for the sprites - // The sprites are a bit more difficult, they are stored in an unordered_map - // with it's name as the key, this means we can't have two sprites with the same name - // Normally this isn't a problem, but someone may decide to copy and paste a sprite - // and forget to change the name, that needs to be handled, but it's outside the scope - // of this reader. -#ifndef ATHENA_USE_QT - std::unordered_map sprites; -#else - QMap sprites; -#endif - - for (atUint16 i = 0; i < spriteCount; i++) - { - Sakura::Sprite* sprite = new Sakura::Sprite(ret); -#ifndef ATHENA_USE_QT - std::string name = base::readString(); -#else - QString name = QString::fromStdString(base::readString()); -#endif - sprite->setName(name); - atUint16 frameCount = base::readUint16(); - atUint16 stateCount = base::readUint16(); - - // Each state id corresponds to a texture held in the parent class - std::vector stateIds; - - for (int j = 0; j < stateCount; j++) - stateIds.push_back(base::readUint16()); - - - sprite->setStateIds(stateIds); - - // Now to read the sprite parts. - // The parts allow us to build retro style sprites very easily - // making it possible to use one texture atlas for all possible - // frame combinations, this reduces the amount of memory overhead - // and the storage footprint, while Sakura supports packs and zips - // it's still a bad idea to have a metric ton of texture resources - // littering the place -#ifndef ATHENA_USE_QT - std::vector frames; -#else - QList frames; -#endif - - for (atUint32 k = 0; k < frameCount; k++) - { - Sakura::SpriteFrame* frame = new Sakura::SpriteFrame(sprite); - frame->setFrameTime(base::readFloat()); - atUint16 partCount = base::readUint16(); - - -#ifndef ATHENA_USE_QT - std::vector parts; -#else - QList parts; -#endif - - for (atUint8 j = 0; j < partCount; j++) - { - Sakura::SpritePart* part = new Sakura::SpritePart(frame); -#ifndef ATHENA_USE_QT - std::string name = base::readString(); -#else - QString name = QString::fromStdString(base::readString()); -#endif - part->setName(name); - part->setCollision(base::readBool()); - - float xOff = base::readFloat(); - float yOff = base::readFloat(); - part->setOffset(xOff, yOff); - float texXOff = base::readFloat(); - float texYOff = base::readFloat(); - part->setTextureOffset(texXOff, texYOff); - atUint32 width = base::readUint32(); - atUint32 height = base::readUint32(); - part->setSize(width, height); - bool flippedH = base::readBool(); - part->setFlippedHorizontally(flippedH); - bool flippedV = base::readBool(); - part->setFlippedVertically(flippedV); - - parts.push_back(part); - } - - frame->setParts(parts); - frames.push_back(frame); - } - - sprite->setFrames(frames); -#ifndef ATHENA_USE_QT - - if (sprite->name() != std::string()) - { - std::string nameLow(sprite->name()); - Athena::utility::tolower(nameLow); - sprites[nameLow] = sprite; - } - -#else - - if (!sprite->name().isEmpty()) - sprites[sprite->name().toLower()] = sprite; - -#endif - else - { - atError("Sprite names cannot be empty"); - return nullptr; - } - } - - ret->setSprites(sprites); - } - catch (...) - { - delete ret; - ret = NULL; - throw; } + ret->setSprites(sprites); + return ret; } } // io diff --git a/src/Athena/WiiSaveReader.cpp b/src/Athena/WiiSaveReader.cpp index f6e8426..0d9c84d 100644 --- a/src/Athena/WiiSaveReader.cpp +++ b/src/Athena/WiiSaveReader.cpp @@ -51,73 +51,63 @@ WiiSave* WiiSaveReader::readSave() { WiiSave* ret = new WiiSave; - try + if (length() < 0xF0C0) { - if (length() < 0xF0C0) - { - atError("Not a valid WiiSave"); - return nullptr; - } - - WiiBanner* banner = this->readBanner(); - - if (!banner) - { - atError("Invalid banner"); - return nullptr; - } - - ret->setBanner(banner); - atUint32 bkVer = base::readUint32(); - - if (bkVer != 0x00000070) - { - atError("Invalid BacKup header size"); - return nullptr; - } - - atUint32 bkMagic = base::readUint32(); - - if (bkMagic != 0x426B0001) - { - atError("Invalid BacKup header magic"); - return nullptr; - } - - /*atUint32 ngId =*/ base::readUint32(); - atUint32 numFiles = base::readUint32(); - - /*int fileSize =*/ base::readUint32(); - base::seek(8); // skip unknown data; - - atUint32 totalSize = base::readUint32(); - base::seek(64); // Unknown (Most likely padding) - base::seek(8); - base::seek(6); - base::seek(2); - base::seek(0x10); - - std::vector files; - - for (atUint32 i = 0; i < numFiles; ++i) - { - WiiFile* file = readFile(); - - if (file) - files.push_back(file); - } - - ret->setRoot(buildTree(files)); - - readCerts(totalSize); - } - catch (...) - { - delete ret; - ret = NULL; - throw; + atError("Not a valid WiiSave"); + return nullptr; } + WiiBanner* banner = this->readBanner(); + + if (!banner) + { + atError("Invalid banner"); + return nullptr; + } + + ret->setBanner(banner); + atUint32 bkVer = base::readUint32(); + + if (bkVer != 0x00000070) + { + atError("Invalid BacKup header size"); + return nullptr; + } + + atUint32 bkMagic = base::readUint32(); + + if (bkMagic != 0x426B0001) + { + atError("Invalid BacKup header magic"); + return nullptr; + } + + /*atUint32 ngId =*/ base::readUint32(); + atUint32 numFiles = base::readUint32(); + + /*int fileSize =*/ base::readUint32(); + base::seek(8); // skip unknown data; + + atUint32 totalSize = base::readUint32(); + base::seek(64); // Unknown (Most likely padding) + base::seek(8); + base::seek(6); + base::seek(2); + base::seek(0x10); + + std::vector files; + + for (atUint32 i = 0; i < numFiles; ++i) + { + WiiFile* file = readFile(); + + if (file) + files.push_back(file); + } + + ret->setRoot(buildTree(files)); + + readCerts(totalSize); return ret; }