aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EmROMReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/EmROMReader.cpp')
-rw-r--r--SrcShared/EmROMReader.cpp868
1 files changed, 868 insertions, 0 deletions
diff --git a/SrcShared/EmROMReader.cpp b/SrcShared/EmROMReader.cpp
new file mode 100644
index 0000000..4627fca
--- /dev/null
+++ b/SrcShared/EmROMReader.cpp
@@ -0,0 +1,868 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include <EmCommon.h>
+#include <EmROMReader.h>
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(void)
+{
+ fSize = 0;
+ fSizeAdj = 0;
+ fFree = false;
+ fAddress = 0;
+ fOwner = 0;
+ fHOffset = 0;
+ fLockCount = 0;
+ fHdrSize = 0;
+
+ recordNumber = 0;
+ type = typeOther;
+ dbNumber = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(const EmAliasROMHeapChunkHdr2Type<A>& chunk, UInt32 addr)
+{
+ fPtr = chunk.GetPtr();
+ fSize = (chunk.long1 >> 0) & 0x00FFFFFFU;
+
+ if (fSize == 0)
+ {
+ fFree = 0;
+ fSizeAdj = 0;
+ fLockCount = 0;
+ fOwner = 0;
+ fHdrSize = 0;
+ fAddress = 0;
+ }
+ else
+ {
+ fFree = (chunk.long1 >> 31) & 0x0001;
+ fSizeAdj = (chunk.long1 >> 24) & 0x000F;
+ fLockCount = (chunk.long2 >> 28) & 0x000F;
+ fHOffset = (chunk.long2 >> 0) & 0x00FFFFFFU;
+ fOwner = (chunk.long2 >> 24) & 0x000F;
+ fHdrSize = chunk.GetSize();
+ fAddress = addr + fHdrSize;
+ }
+
+ recordNumber = 0;
+ dbNumber = 0;
+ type = fFree ? typeFree : typeOther;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(const EmAliasROMHeapChunkHdr1Type<A>& chunk, UInt32 addr)
+{
+ fPtr = chunk.GetPtr();
+ fSize = chunk.size;
+
+ if (fSize == 0)
+ {
+ fFree = 0;
+ fSizeAdj = 0;
+ fLockCount = 0;
+ fOwner = 0;
+ fHdrSize = 0;
+ fAddress = 0;
+ }
+ else
+ {
+ fFree = !!(chunk.flags & 0x80);
+ fSizeAdj = chunk.flags & 0x0F;
+ fLockCount = chunk.lockOwner >> 4;
+ fHOffset = chunk.hOffset;
+ fOwner = chunk.lockOwner & 0x0F;
+ fHdrSize = chunk.GetSize();
+ fAddress = addr + fHdrSize;
+ }
+
+ recordNumber = 0;
+ dbNumber = 0;
+ type = fFree ? typeFree : typeOther;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(void)
+{
+ fDeleted = fDirty = fBusy = fSecret = false;
+ fCategory = fType = fID = fChunkLID = 0;
+
+ fChunk = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(const EmAliasROMDBRecordHeader1Type<A> record, EmROMReader* rom)
+{
+ UInt32 bits = record.recordID;
+
+ fRecord = true;
+
+ fDeleted = !!((bits >> 31) & 1);
+ fDirty = !!((bits >> 30) & 1);
+ fBusy = !!((bits >> 29) & 1);
+ fSecret = !!((bits >> 28) & 1);
+ fCategory = (bits >> 24) & 0xF;
+ fID = bits & 0x00FFFFFFU;
+
+ fType = 0;
+
+ fChunkLID = record.chunkLID;
+
+ ChunkList::iterator block = rom->Chunks().find(fChunkLID);
+ if (block != rom->Chunks().end())
+ fChunk = &block->second;
+ else
+ fChunk = NULL;
+
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(const EmAliasROMDBResourceHeader1Type<A> resource, EmROMReader* rom)
+{
+ fRecord = false;
+
+ fType = resource.type;
+ fID = resource.id;
+
+ fDeleted = fDirty = fBusy = fSecret = false;
+ fCategory = 0;
+
+ fChunkLID = resource.chunkLID;
+
+ ChunkList::iterator block = rom->Chunks().find(fChunkLID);
+ if (block != rom->Chunks().end())
+ fChunk = &block->second;
+ else
+ fChunk = NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseType::DatabaseType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseType::DatabaseType(void)
+{
+ fAppInfoChunk = fSortInfoChunk = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseType::DatabaseType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseType::DatabaseType(ChunkType* hdr, EmROMReader* rom)
+{
+ int i;
+
+ if (hdr->Size() < EmAliasROMDBHeader1Type<A>::GetSize())
+ return;
+
+ EmAliasROMDBHeader1Type<A> db(hdr->GetPtr());
+
+ char name[dmDBNameLength];
+ A::BlockCopy(name, db.name.GetPtr(), dmDBNameLength);
+ name[dmDBNameLength-1] = '\0';
+ fName = name;
+
+ fCreationTime = db.creationTime;
+ fModificationTime = db.modificationTime;
+ fBackupTime = db.backupTime;
+ fType = db.type;
+ fCreator = db.creator;
+ fVersion = db.version;
+ fUniqueIDSeed = db.uniqueIDSeed;
+ fFlags = db.flags;
+ fVersion = db.version;
+
+ fAppInfoChunk = 0;
+ if (db.appinfoLID != 0)
+ {
+ ChunkList::iterator ai = rom->Chunks().find(db.appinfoLID);
+ if (ai != rom->Chunks().end())
+ fAppInfoChunk = &ai->second;
+ }
+
+ fSortInfoChunk = 0;
+ if (db.sortinfoLID != 0)
+ {
+ ChunkList::iterator si = rom->Chunks().find(db.sortinfoLID);
+ if (si != rom->Chunks().end())
+ fSortInfoChunk = &si->second;
+ }
+
+ for (i=0; i<db.recordCount; i++)
+ {
+ if (db.flags & 1)
+ fItems.push_back(DatabaseItemType(db.resources[i], rom));
+ else
+ fItems.push_back(DatabaseItemType(db.records[i], rom));
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::EmROMReader
+// ---------------------------------------------------------------------------
+
+EmROMReader::EmROMReader(ptr_type arenaPtr, size_t arenaSize) :
+ fPtr(arenaPtr),
+ fSize(arenaSize),
+ fEndPtr(A::add(arenaPtr, arenaSize)),
+ fCardAddress(0),
+ fChunks (),
+ fDatabases (),
+ fFeatures (),
+ fFlag328 (false),
+ fFlagEZ (false),
+ fFlagVZ (false),
+ fFlagSZ (false),
+ fCardVersion(0),
+ fCardName (),
+ fCardManuf (),
+ fStoreVersion(0),
+ fCompanyID(0),
+ fHalID(0),
+ fRomVersion(0),
+ fRomVersionString(),
+ fSplashChunk(0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::~EmROMReader
+// ---------------------------------------------------------------------------
+
+EmROMReader::~EmROMReader(void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireCardHeader
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireCardHeader(void)
+{
+ // Make sure the buffer is big enough for a card header
+
+ if (fSize < EmAliasROMCardHeader5Type<A>::GetSize())
+ return false;
+
+ EmAliasROMCardHeader5Type<A> cardHdr(fPtr);
+
+ // Make sure the stack size isn't something ludicrous.
+
+ if ((cardHdr.initStack == 0) ||
+ (cardHdr.initStack > 0x000FFFFFL)) // 1 Meg
+ return false;
+
+ if (cardHdr.signature != sysCardSignature)
+ return false;
+
+ // Make sure the header version isn't ludicrous.
+
+ if ((cardHdr.hdrVersion == 0) ||
+ (cardHdr.hdrVersion > 255)) // arbitrary val
+ return false;
+
+ // Make sure this isn't a "RAM only" card.
+
+ if (cardHdr.flags & memCardHeaderFlagRAMOnly)
+ return false;
+
+ char buffer[memMaxNameLen + 1];
+
+ fFlag328 = (cardHdr.flags & 0x0010) != 0;
+ fFlagEZ = (cardHdr.flags & 0x0020) != 0;
+ fFlagVZ = (cardHdr.flags & 0x0040) != 0;
+ fFlagSZ = (cardHdr.flags & 0x0080) != 0;
+ fCardVersion = cardHdr.hdrVersion;
+
+ buffer[memMaxNameLen] = '\0';
+
+ A::BlockCopy(buffer, cardHdr.cardName.GetPtr(), memMaxNameLen - 1);
+ fCardName = buffer;
+
+ A::BlockCopy(buffer, cardHdr.cardManuf.GetPtr(), memMaxNameLen - 1);
+ fCardManuf = buffer;
+
+ fCompanyID = cardHdr.companyID;
+ fHalID = cardHdr.halID;
+ fRomVersion = cardHdr.romVersionNumber;
+
+ A::BlockCopy(buffer, cardHdr.romVersionString.GetPtr(), memMaxNameLen - 1);
+ fRomVersionString = buffer;
+
+ SetCardAddress(GuessCardAddress());
+
+ unsigned long bigROM = (fCardVersion < 2) ? 0x3000 : cardHdr.bigrom;
+
+ if ((fCardAddress & 0x0FFFFF) != (bigROM & 0x0FFFFF))
+ {
+ /* Whoops, we probably just read a Small ROM. Skip to the
+ probable Big ROM, and continue from there. */
+
+ fPtr = A::add(fPtr, bigROM & 0x0FFFFF);
+ fSize -= (bigROM & 0x0FFFFF);
+
+ return AcquireCardHeader();
+ }
+
+ return true; // Card header verified properly
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::GuessCardAddress
+// ---------------------------------------------------------------------------
+
+UInt32 EmROMReader::GuessCardAddress(void)
+{
+ EmAliasROMCardHeader5Type<A> cardHdr(fPtr);
+
+ return (unsigned long)cardHdr.ramlist - 0x200;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::SetCardAddress
+// ---------------------------------------------------------------------------
+
+void EmROMReader::SetCardAddress(UInt32 address)
+{
+ fCardAddress = address;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireROMHeap
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireROMHeap(void)
+{
+ // Local IDs cannot be understood without card address
+
+ if (!fCardAddress)
+ return false;
+
+ EmAliasROMStoreHeader4Type<A> storeHdr(GetCardStorePtr());
+
+ if (storeHdr[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for store header?
+
+ if (storeHdr.signature != sysStoreSignature)
+ return false;
+
+ fStoreVersion = storeHdr.version;
+
+ ptr_type romHeapListPtr = A::add(fPtr, (UInt32)storeHdr.heapAddr-fCardAddress);
+
+ EmAliasUInt16<A> romHeapCount(romHeapListPtr);
+
+ if (romHeapListPtr < fPtr)
+ return false; // Heap list within buffer?
+
+ if (romHeapCount[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap list?
+
+ EmAliasUInt32<A> romHeapList(romHeapCount[1].GetPtr());
+
+ fChunks.clear();
+
+ fDatabases.clear();
+
+ fFeatures.clear();
+
+ /* Heap arrangements past version 1 will only have
+ a single heap. */
+
+ for (int heap=0; heap<romHeapCount; heap++)
+ {
+ if (romHeapList[heap+1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap list?
+
+ ptr_type romHeapPtr = A::add(fPtr, (UInt32)romHeapList[heap]-fCardAddress);
+ unsigned long checkSize;
+
+ if (romHeapPtr < fPtr)
+ return false; // Heap within buffer?
+
+ EmAliasROMHeapHeader1Type<A> heapHdr1(romHeapPtr);
+
+ if (heapHdr1.flags & 0x2000) // Version 4 heap
+ {
+ EmAliasROMHeapHeader3Type<A> heapHdr3(romHeapPtr);
+
+ checkSize = heapHdr3[1].GetSize();
+
+ if (heapHdr3[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr3[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr3.size)
+ goto fail; // Double-check of heap size failed
+
+ // If a free chunk is listed, perform verification
+
+ if ((UInt32)heapHdr3.freeChunk)
+ {
+ UInt32 freeLID = (UInt32)romHeapList + ((UInt32)heapHdr3.freeChunk * 2) + 8;
+
+ if (fChunks.find(freeLID) == fChunks.end())
+ goto fail; // Unable to find "free" chunk
+
+ if (!fChunks[freeLID].Free())
+ goto fail; // Supposedly free chunk isn't
+ }
+ }
+ else if (heapHdr1.flags & 0x4000) // Version 3 heap
+ {
+ EmAliasROMHeapHeader3Type<A> heapHdr3(romHeapPtr);
+
+ checkSize = heapHdr3[1].GetSize();
+
+ if (heapHdr3[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr3[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr3.size)
+ goto fail; // Double-check of heap size failed
+
+ // If a free chunk is listed, perform verification
+
+ if ((UInt32)heapHdr3.freeChunk)
+ {
+ UInt32 freeLID = (UInt32)romHeapList + ((UInt32)heapHdr3.freeChunk * 2) + 8;
+
+ if (fChunks.find(freeLID) == fChunks.end())
+ goto fail; // Unable to find "free" chunk
+
+ if (!fChunks[freeLID].Free())
+ goto fail; // Supposedly free chunk isn't
+ }
+ }
+ else if (heapHdr1.flags & 0x8000) // Version 2 heap
+ {
+ EmAliasROMHeapHeader2Type<A> heapHdr2(romHeapPtr);
+
+ checkSize = heapHdr2[1].GetSize();
+
+ if (heapHdr2[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr2[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr2.size)
+ goto fail; // Double-check of heap size failed
+ }
+ else // Version 1 heap
+ {
+ EmAliasROMHeapHeader1Type<A> heapHdr1(romHeapPtr);
+
+ checkSize = heapHdr1[1].GetSize();
+
+ if (heapHdr1[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr1[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr1Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 2; /* zero-length tail "chunk" */
+
+ if ((UInt16)(checkSize & 0xFFFF) != (UInt16)heapHdr1.size)
+ goto fail; // Double-check of heap size failed
+ }
+ } // next heap
+
+ return true; // Sucessfull acquisition
+
+fail:
+ fChunks.clear();
+ return false; // Failure
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireDatabases
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireDatabases(void)
+{
+ if (fChunks.size() == 0)
+ return false; // Must get chunks first
+
+ EmAliasROMStoreHeader4Type<A> storeHdr(GetCardStorePtr());
+
+ ChunkList::iterator dbHdrChunk = fChunks.find(storeHdr.dbLID);
+ if (dbHdrChunk == fChunks.end())
+ return false; // Could not find database directory chunk
+
+ dbHdrChunk->second.type = ChunkType::typeDBTable;
+
+ fDatabases.clear();
+
+ fFeatures.clear();
+
+ ptr_type dbHdrPtr = dbHdrChunk->second.GetPtr();
+
+#if LOG_DATABASES_HACK
+ LogAppendMsg ("-----");
+#endif
+ for (;;)
+ {
+ EmAliasROMDBDir1Type<A> dbHdr(dbHdrPtr);
+
+ for (int i=0; i<dbHdr.count; i++)
+ {
+ ChunkList::iterator dbChunk = fChunks.find(dbHdr.dbLID[i]);
+ if (dbChunk == fChunks.end())
+ continue; // Could not find database directory chunk
+
+ dbChunk->second.type = ChunkType::typeDBHeader;
+
+#if LOG_DATABASES_HACK
+ DatabaseType dbInfo(&dbChunk->second, this);
+
+ LogAppendMsg ("%s", dbInfo.Name ().c_str ());
+#endif
+
+ fDatabases.push_back(DatabaseType(&dbChunk->second, this));
+
+ for (unsigned int j=0; j<fDatabases[i].Items().size(); j++)
+ {
+ ChunkType* chunk = fDatabases[i].Items()[j].Chunk();
+ if (chunk)
+ {
+ chunk->type = ChunkType::typeRecord;
+ chunk->dbNumber = i;
+ chunk->recordNumber = j;
+ }
+ }
+ }
+
+ if (dbHdr.nextTable == 0)
+ break;
+ else
+ {
+ dbHdrChunk = fChunks.find(dbHdr.nextTable);
+ if (dbHdrChunk == fChunks.end())
+ break; // Could not find database directory chunk
+ dbHdrPtr = dbHdrChunk->second.GetPtr();
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireFeatures
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireFeatures(void)
+{
+ /* Nothing to see here... */
+ if (fDatabases.size() == 0)
+ return false; // Must get databases first
+
+ fFeatures.clear();
+
+ DatabaseList::iterator dbiter = fDatabases.begin();
+ for (; dbiter != fDatabases.end(); dbiter++)
+ {
+ if (dbiter->Creator() == 'psys')
+ {
+ for (DatabaseItemList::iterator iter = dbiter->Items().begin();
+ iter != dbiter->Items().end();
+ iter++)
+ {
+ if (iter->Type() == 'feat')
+ {
+ EmAliasROMFtrTableType<A> table(iter->Chunk()->GetPtr());
+
+ ptr_type pos = table.creator.GetPtr();
+
+ for (int i=0; i<table.numEntries; i++)
+ {
+ EmAliasROMFtrCreatorType<A> creator(pos);
+
+ int j;
+ for (j=0; j<creator.numEntries; j++)
+ {
+ fFeatures[creator.creator][creator.feature[j].num]
+ = creator.feature[j].value;
+ }
+
+ pos = creator.feature[j].GetPtr();
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireSplashDB
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireSplashDB(void)
+{
+ fSplashChunk = 0;
+
+ for (DatabaseList::iterator iter = fDatabases.begin();
+ iter != fDatabases.end();
+ iter++)
+ {
+ if (iter->Creator() == 'psys')
+ {
+ for (EmROMReader::DatabaseItemList::iterator jter = iter->Items().begin();
+ jter != iter->Items().end();
+ jter++)
+ {
+ if ((jter->Type() == 'Tbsb') &&
+ (jter->ID() == 19001))
+ {
+ fSplashChunk = jter->Chunk();
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::ContainsDB
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::ContainsDB(string dbName) const
+{
+ for ( EmROMReader::DatabaseList::const_iterator i = fDatabases.begin();
+ i != fDatabases.end();
+ i++)
+ {
+ if (i->Name() == dbName)
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::Version
+// ---------------------------------------------------------------------------
+
+void EmROMReader::Version( int& major,
+ int& minor,
+ int& fix,
+ int& stage,
+ int& build) const
+{
+ major = minor = fix = stage = build = 0;
+
+ FeatureList::const_iterator psys = fFeatures.find('psys');
+ if (psys == fFeatures.end())
+ return;
+
+ map<int, int>::const_iterator psys_1 = psys->second.find(1);
+ if (psys_1 == psys->second.end())
+ return;
+
+ unsigned long ver = psys_1->second;
+ major = (ver >> 24) & 0x00FF;
+ minor = (ver >> 20) & 0x000F;
+ fix = (ver >> 16) & 0x000F;
+ stage = (ver >> 12) & 0x000F;
+ build = (ver >> 0) & 0x0FFF;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::Version
+// ---------------------------------------------------------------------------
+
+unsigned long EmROMReader::Version(void) const
+{
+ int major, minor, fix, state, build;
+ Version(major, minor, fix, state, build);
+
+ return (major << 16) | (minor << 8) | fix;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::IsBitmapColor
+// ---------------------------------------------------------------------------
+
+int EmROMReader::IsBitmapColor (ChunkType& chunk, bool bootScreen)
+{
+ ptr_type pos = chunk.GetPtr();
+
+ if (bootScreen)
+ pos = A::add(pos, 6);
+
+ for (;;)
+ {
+ if (!chunk.Contains(pos, EmAliasBitmapTypeV2<A>::GetSize()))
+ return -1;
+
+ EmAliasBitmapTypeV2<A> bitmap(pos);
+
+ if (bitmap.pixelSize >= 8)
+ return 1;
+
+ if (!bitmap.nextDepthOffset)
+ break;
+
+ unsigned long offset = bitmap.nextDepthOffset;
+
+ pos = A::add(pos, offset * 4);
+ }
+
+ return 0;
+}