// MIT License // Copyright (c) 2026 by Peter Siegmund (mars3142) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #include "cartridge/cartridge.h" #include "cartridge/binary_reader.h" #include "cartridge/lat_lng.h" #include "cartridge/media.h" namespace cartridge { Cartridge::Cartridge(std::string cartridgeGuid, double altitude, std::string author, std::string cartridgeDesc, std::string cartridgeName, std::string company, std::string completionCode, LatLng latLng, std::string playerName, std::string recommendDevice, int smallIconId, int splashScreenId, std::string startLocationDesc, std::string typeOfCartridge, std::string version, std::map references, std::vector bytes) : m_cartridgeGuid(std::move(cartridgeGuid)), m_altitude(altitude), m_author(std::move(author)), m_cartridgeDesc(std::move(cartridgeDesc)), m_cartridgeName(std::move(cartridgeName)), m_company(std::move(company)), m_completionCode(std::move(completionCode)), m_latLng(latLng), m_playerName(std::move(playerName)), m_recommendDevice(std::move(recommendDevice)), m_smallIconId(smallIconId), m_splashScreenId(splashScreenId), m_startLocationDesc(std::move(startLocationDesc)), m_typeOfCartridge(std::move(typeOfCartridge)), m_version(std::move(version)), m_references(std::move(references)), m_bytes(std::move(bytes)) {} std::unique_ptr Cartridge::create(BinaryReader &reader) { try { uint16_t count = reader.getUShort(); std::map references; for (uint16_t index = 0; index < count; ++index) { int objectId = reader.getShort(); int address = reader.getLong(); references.emplace(objectId, address); } reader.getLong(); // header length double latitude = reader.getDouble(); double longitude = reader.getDouble(); double altitude = reader.getDouble(); reader.getLong(); // unknown 0 reader.getLong(); // unknown 1 int splashScreenId = reader.getShort(); int smallIconId = reader.getShort(); std::string typeOfCartridge = reader.getASCIIZ(); std::string playerName = reader.getASCIIZ(); reader.getLong(); // unknown 2 reader.getLong(); // unknown 3 std::string cartridgeName = reader.getASCIIZ(); std::string cartridgeGuid = reader.getASCIIZ(); std::string cartridgeDesc = reader.getASCIIZ(); std::string startLocationDesc = reader.getASCIIZ(); std::string version = reader.getASCIIZ(); std::string author = reader.getASCIIZ(); std::string company = reader.getASCIIZ(); std::string recommendedDevice = reader.getASCIIZ(); reader.getLong(); // unknown 4 std::string completionCode = reader.getASCIIZ(); // Rohdaten aus dem Reader extrahieren const std::vector &bytes = reader.data(); return std::make_unique( cartridgeGuid, altitude, author, cartridgeDesc, cartridgeName, company, completionCode, LatLng(latitude, longitude), playerName, recommendedDevice, smallIconId, splashScreenId, startLocationDesc, typeOfCartridge, version, references, bytes); } catch (const std::exception &) { return nullptr; } } double Cartridge::altitude() const { return m_altitude; } const std::string &Cartridge::author() const { return m_author; } const LatLng &Cartridge::latLng() const { return m_latLng; } const std::string &Cartridge::cartridgeName() const { return m_cartridgeName; } const std::string &Cartridge::cartridgeDesc() const { return m_cartridgeDesc; } const std::string &Cartridge::cartridgeGuid() const { return m_cartridgeGuid; } const std::string &Cartridge::typeOfCartridge() const { return m_typeOfCartridge; } const std::string &Cartridge::playerName() const { return m_playerName; } const std::string &Cartridge::startLocationDesc() const { return m_startLocationDesc; } const std::string &Cartridge::version() const { return m_version; } const std::string &Cartridge::company() const { return m_company; } const std::string &Cartridge::recommendDevice() const { return m_recommendDevice; } const std::string &Cartridge::completionCode() const { return m_completionCode; } std::unique_ptr Cartridge::getMedia(const int objectId) { if (m_lastObject == objectId && m_lastMedia) { return std::make_unique(*m_lastMedia); } auto it = m_references.find(objectId); if (it != m_references.end()) { int address = it->second; BinaryReader reader(m_bytes, Endian::Little); auto media = Media::create(reader, objectId, address); if (media && media->getData().size() < 128000) { m_lastObject = objectId; m_lastMedia = std::make_unique(*media); } return media; } return nullptr; } int Cartridge::mediaCount() const { return static_cast(m_references.size()); } std::unique_ptr Cartridge::splashScreen() { return getMedia(m_splashScreenId); } std::unique_ptr Cartridge::smallIcon() { return getMedia(m_smallIconId); } std::unique_ptr Cartridge::luac() { return getMedia(0); } bool Cartridge::operator==(const Cartridge &other) const { return m_cartridgeGuid == other.m_cartridgeGuid; } bool Cartridge::operator!=(const Cartridge &other) const { return !(*this == other); } } // namespace cartridge