EditablePowerUpData::EditablePowerUpData(LoadedROM& rom, Taddress powerUpTableAddress__) : powerUpTableAddress_(powerUpTableAddress__) { int byteCount = 0; for (int i = 0; i < numPowerUps_; i++) { // Get binary-coded decimal representation of max health int maxHealthBCD = ByteConversion::fromBytes( rom.directRead(powerUpTableAddress_ + byteCount), ByteSizes::uint8Size, EndiannessTypes::little, SignednessTypes::nosign); byteCount += ByteSizes::uint8Size; // Convert to standard integer format int maxHealth = MiscMath::fromBCD(maxHealthBCD); // Store maxHealthPerPowerup_[i] = maxHealth; // Get flight time int flightTime = ByteConversion::fromBytes( rom.directRead(powerUpTableAddress_ + byteCount), ByteSizes::uint16Size, EndiannessTypes::little, SignednessTypes::nosign); byteCount += ByteSizes::uint16Size; // Store flightTimePerPowerup_[i] = flightTime; } }
WritableROM::WritableROM( const LoadedROM& rom__, const FreeSpaceListing& freeSpace__) : rom_(new Tbyte[rom__.loadedFileSize()]), romSize_(rom__.loadedFileSize()), freeSpace_(freeSpace__) { // Copy contents of ROM std::memcpy((char*)rom_, (char*)(rom__.directRead(0)), rom__.loadedFileSize()); }
EditableLevelObjectEntryGroups::EditableLevelObjectEntryGroups( LoadedROM& rom, Taddress tableHeaderAddress, Taddress tableContentAddress, Taddress tableEndAddress, int numEntries) : TwoKeyIndexedEditableMappedData<LevelObjectEntryGroup>(rom, tableHeaderAddress, tableContentAddress, tableEndAddress, numEntries, SubMaps::subMapLevelObjectTableCounts, primaryMapLimit), movedToNewBank_(false), tableHeaderSize_(tableContentAddress - tableHeaderAddress), initialTableAddress_(tableHeaderAddress), initialTableContentSize_(tableEndAddress - tableContentAddress) { // For seemingly no reason except to f**k us over, some of the // table entries are non-contiguous, so we can't use this /* readAllDataAndConstruct(rom, tableHeaderAddress, tableContentAddress, tableEndAddress, numEntries); */ // std::cout << "****** THIS ONE ********" << std::endl; readAndConstruct(rom, tableHeaderAddress, tableEndAddress); // std::cout << mapnumToAddress_.numPrimaryKeys() << std::endl; // Copy C1 and C3 code segments for exporting std::memcpy(codeSegmentC1, rom.directRead(addressOfC1Segment), lengthOfC1Segment); std::memcpy(codeSegmentC3, rom.directRead(addressOfC3Segment), lengthOfC3Segment); }
RawObjectGraphicsHeader::RawObjectGraphicsHeader( LoadedROM& rom, Taddress address) { Taddress readAddress = address; Tbyte endOfHeaderCheck = *(rom.directRead(readAddress)); while (endOfHeaderCheck != endOfHeaderToken) { // Read subheader RawObjectGraphicSubheader subheader(rom, readAddress); // Add to storage rawObjectGraphicSubheaders_.push_back(subheader); // Move to next subheader address readAddress += RawObjectGraphicSubheader::dataSize; // Check for end of header endOfHeaderCheck = *(rom.directRead(readAddress)); } }
EditableSlopeSpeedValues::EditableSlopeSpeedValues(LoadedROM& rom, Taddress baseAddress__, int numEntries) : baseAddress_(baseAddress__) { for (int i = 0; i < numEntries; i++) { int value = ByteConversion::fromBytes( rom.directRead(baseAddress__ + (i * ByteSizes::int16Size)), ByteSizes::int16Size, EndiannessTypes::little, SignednessTypes::sign); speedValues_.push_back(value); } }
void EditableLevelObjectEntryGroups::readAndConstructReadStep( LoadedROM& rom, Taddress tableEndAddress) { // Iterate over primary storage addresses and read corresponding data for (AddressIndexMap::iterator it = addressToIndex_.begin(); it != addressToIndex_.end(); ++it) { // std::cout << "start: " << it->first << std::endl; Taddress startAddress = it->first; // Read elements in array LevelObjectEntryGroup dst; readElements(dst, rom.directRead(startAddress), 1); // Add read elements to primary storage primaryStorage_[it->second] = LevelObjectEntryGroup(dst); } }
int MetatileStructureSet::readFromData(LoadedROM& rom, Taddress address__) { address_ = address__; // Count of read bytes int byteCount = 0; // Get bank number of the table int tableBankNum = LoadedROM::directToBankNum(address__); // Compute table size. // The first address in the index always points to the first // structure definition Taddress contentStartBankedAddress = ByteConversion::fromBytes( rom.directRead(address__), ByteSizes::uint16Size, EndiannessTypes::little, SignednessTypes::nosign); // Convert to direct address Taddress contentStartAddress = 0; if (contentStartBankedAddress == invalidStructureToken) { contentStartAddress = invalidRepairAddress; } else { contentStartAddress = LoadedROM::getDirectAddress( tableBankNum, contentStartBankedAddress); } // Get size of index, given by ((tableStart - indexStart) / entrySize) int indexEntries = (contentStartAddress - address__) / ByteSizes::uint16Size; // Read the index. // Remember the highest index we encounter int highestIndex = 0; for (int i = 0; i < indexEntries; i++) { // Get banked address Taddress entryBankedAddress = ByteConversion::fromBytes( rom.directRead(address__ + (i * ByteSizes::uint16Size)), ByteSizes::uint16Size, EndiannessTypes::little, SignednessTypes::nosign); byteCount += ByteSizes::uint16Size; // Convert to direct address int entryAddress = 0; // If address is invalid, repair if (entryBankedAddress == invalidStructureToken) { // std::cout << contentStartAddress << std::endl; entryAddress = invalidRepairAddress + (i * MetatileStructure::dataSize); } else { entryAddress = LoadedROM::getDirectAddress( tableBankNum, entryBankedAddress); } // Compute the actual index this address corresponds to int structureIndex = (entryAddress - contentStartAddress) / MetatileStructure::dataSize; // Add mapping to index map index_.insert(MetatileIndexToStructurePair(i, structureIndex)); if (structureIndex > highestIndex) { highestIndex = structureIndex; } } // Increment highest index (we're using it as a limit for the read loop) ++highestIndex; // Read the structure definitions. // The highest index indicates the actual number of structure definitions // in the table for (int i = 0; i < highestIndex; i++) { // Read each metatile MetatileStructure metatile; metatile.readFromData(rom.directRead(contentStartAddress + (i * MetatileStructure::dataSize))); // If reading invalid table, repair tiles if (contentStartAddress == invalidRepairAddress) { // std::cout << highestIndex << std::endl; metatile.upperLeft() = TileReference(invalidRepairTile); metatile.upperRight() = TileReference(invalidRepairTile); metatile.lowerLeft() = TileReference(invalidRepairTile); metatile.lowerRight() = TileReference(invalidRepairTile); } // Add to content primaryStorage_.push_back(metatile); byteCount += MetatileStructure::dataSize; } // HACK: (sort of) Add dummy entries to fill rest of set. // This fixes issues that I think are caused by out-of-range // values in the index. // while (primaryStorage_.size() < 256) { // primaryStorage_.push_back(MetatileStructure()); // } return byteCount; }
EditableLevelPaletteHeaders::EditableLevelPaletteHeaders( LoadedROM& rom, Taddress tableHeaderAddress__, Taddress tableContentAddress__, int numContentEntries, const int subKeyTable[], int numPrimaryKeys) : mapnumToIndex_(subKeyTable, numPrimaryKeys), tableHeaderAddress_(tableHeaderAddress__), tableContentAddress_(tableContentAddress__) { // Read the key index table int tableHeaderReadAddress = tableHeaderAddress_; for (int i = 0; i < mapnumToIndex_.numPrimaryKeys(); i++) { // Only set index if there is at least one submap if (mapnumToIndex_.subKeyTable()[i] > 0) { // Get banked address of data Taddress address = ByteConversion::fromBytes( rom.directRead(tableHeaderReadAddress), ByteSizes::uint16Size, EndiannessTypes::little, SignednessTypes::nosign); int index = LoadedROM::toIndex( tableContentAddress_, address, LevelPaletteHeader::dataSize); // std::cout << "address: " << address << std::endl; // std::cout << "index: " << index << std::endl; // std::cout << "aewtnio: " << i << std::endl; // Convert address to index and store mapnumToIndex_.refDataByKeys(i, TwoKeyedAddress::subKeyBase) = index; } tableHeaderReadAddress += ByteSizes::uint16Size; // for (int j = 0; j < mapnumToIndex_.subKeyTable()[i]; j++) { // } } // This particular header table has a different format from most others: // there is a single table of primary map numbers to addresses, and // the game simply adds the appropriate amount for the submap to that // address // We simulate this by setting higher indices correspondingly for (int i = 0; i < mapnumToIndex_.numPrimaryKeys(); i++) { int nextIndex = 0; // Only get index if there is at least one submap if (mapnumToIndex_.subKeyTable()[i] > 0) { // Get the index for the first submap of the current primary map nextIndex = mapnumToIndex_.refDataByKeys(i, TwoKeyedAddress::subKeyBase); // Advance to next position; ++nextIndex; } for (int j = 1; j < mapnumToIndex_.subKeyTable()[i]; j++) { // Set each submap to the previous map plus one mapnumToIndex_.refDataByKeys(i, j + TwoKeyedAddress::subKeyBase) = nextIndex; ++nextIndex; } } // Read actual header entries int tableContentReadAddress = tableContentAddress_; for (int i = 0; i < numContentEntries; i++) { LevelPaletteHeader header; tableContentReadAddress += header.readFromData(rom.directRead(tableContentReadAddress)); primaryStorage_.push_back(header); } }