ArchiveType::Certainty ArchiveType_DAT_Sango::isInstance(stream::input_sptr psArchive) const { stream::pos lenArchive = psArchive->size(); // TESTED BY: fmt_dat_sango_isinstance_c01 if (lenArchive < DAT_FAT_ENTRY_LEN) return DefinitelyNo; // too short uint32_t offEndFAT; psArchive->seekg(0, stream::start); psArchive >> u32le(offEndFAT); // TESTED BY: fmt_dat_sango_isinstance_c02 if (offEndFAT > lenArchive) return DefinitelyNo; uint32_t offNext = 4; // in case of no files for (unsigned int offset = 4; offset < offEndFAT; offset += 4) { psArchive >> u32le(offNext); // TESTED BY: fmt_dat_sango_isinstance_c03 if (offNext > lenArchive) return DefinitelyNo; } // Last offset must equal file size // TESTED BY: fmt_dat_sango_isinstance_c04 if (offNext != lenArchive) return DefinitelyNo; // TESTED BY: fmt_dat_sango_isinstance_c00 return DefinitelyYes; }
TilesetType_CComic2::Certainty TilesetType_CComic2::isInstance(stream::input_sptr psGraphics) const { stream::pos len = psGraphics->size(); if (len > 65535) return DefinitelyNo; // file too large (probably) psGraphics->seekg(0, stream::start); uint16_t num; for (int i = 0; i < 3; i++) { psGraphics >> u16le(num); if (num > 512) return DefinitelyNo; // too many tiles (probably) } return Unsure; }
MusicPtr MusicType_INS_AdLib::read(stream::input_sptr input, SuppData& suppData) const { stream::len lenFile = input->size(); input->seekg(0, stream::start); MusicPtr music(new Music()); music->patches.reset(new PatchBank()); int op; bool wavesel; switch (lenFile) { case 54: op = 1; wavesel = true; break; case 78: case 80: op = 2; wavesel = true; break; default: std::cout << "[ins-adlib] Unknown format variant: length=" << lenFile << std::endl; if (lenFile < 74) op = 1; else op = 2; wavesel = false; break; } uint16_t unknown; input >> u16le(unknown); OPLPatchPtr oplPatch(new OPLPatch()); readAdLibOperator<uint16_t>(input, &oplPatch->m, &oplPatch->feedback, &oplPatch->connection); if (op > 1) { readAdLibOperator<uint16_t>(input, &oplPatch->c, NULL, NULL); } std::string title; input >> nullPadded(title, INS_TITLE_LEN); if (!title.empty()) music->metadata[Metadata::Title] = title; if (wavesel) { readAdLibWaveSel<uint16_t>(input, &oplPatch->m); if (op > 1) { readAdLibWaveSel<uint16_t>(input, &oplPatch->c); } } music->patches->push_back(oplPatch); return music; }
MapType::Certainty MapType_Hocus::isInstance(stream::input_sptr psMap) const { stream::pos lenMap = psMap->size(); // TESTED BY: fmt_map_hocus_isinstance_c01 if (lenMap != 14400) return MapType::DefinitelyNo; // wrong size // TESTED BY: fmt_map_hocus_isinstance_c00 return MapType::PossiblyYes; }
TilesetType_HarryCHR::Certainty TilesetType_HarryCHR::isInstance( stream::input_sptr psTileset) const { stream::pos len = psTileset->size(); // TESTED BY: tls_harry_chr_isinstance_c01 if (len != CHR_WIDTH * CHR_HEIGHT * CHR_NUM_TILES) return DefinitelyNo; // wrong size // TESTED BY: tls_harry_chr_isinstance_c00 return PossiblyYes; }
ArchiveType::Certainty ArchiveType_EXE_CCaves::isInstance(stream::input_sptr psArchive) const { stream::pos lenArchive = psArchive->size(); if (lenArchive == 191984) { // TESTED BY: TODO fixed_exe_ccaves_isinstance_c00 psArchive->seekg(0x1E00, stream::start); char buffer[8]; psArchive->read(buffer, 8); // Unfortunately no version strings, so check some data I // selected at random... if (strncmp(buffer, "\x55\x89\xE5\x8B\x46\x06\xBA\xA0", 8) != 0) return DefinitelyNo; return DefinitelyYes; } // TESTED BY: TODO (generic) return DefinitelyNo; }
TilesetType_MonsterBashSprite::Certainty TilesetType_MonsterBashSprite::isInstance( stream::input_sptr psGraphics) const { stream::len lenRemaining = psGraphics->size(); psGraphics->seekg(0, stream::start); // TESTED BY: tls_bash_sprite_isinstance_c02 if (lenRemaining < MB_MIN_FILE_LEN) return DefinitelyNo; uint8_t sig; psGraphics >> u8(sig); lenRemaining--; // TESTED BY: tls_bash_sprite_isinstance_c03 if (sig != 0xFF) return DefinitelyNo; while (lenRemaining >= MB_SPR_EFAT_ENTRY_LEN) { uint16_t lenBlock; psGraphics >> u16le(lenBlock); lenRemaining -= 2; // TESTED BY: tls_bash_sprite_isinstance_c04 if (lenBlock < MB_MIN_IMAGE_LEN) return DefinitelyNo; // TESTED BY: tls_bash_sprite_isinstance_c05 if (lenBlock > lenRemaining) return DefinitelyNo; psGraphics->seekg(lenBlock - 1, stream::cur); uint8_t lastByte; psGraphics >> u8(lastByte); // TESTED BY: tls_bash_sprite_isinstance_c06 if (lastByte != 0x00) return DefinitelyNo; lenRemaining -= lenBlock; } // TESTED BY: tls_bash_sprite_isinstance_c00 // TESTED BY: tls_bash_sprite_isinstance_c01 return DefinitelyYes; }
TilesetType_Zone66::Certainty TilesetType_Zone66::isInstance( stream::input_sptr psTileset) const { stream::pos len = psTileset->size(); // TESTED BY: tls_zone66_isinstance_c04 if (len < Z66_FIRST_TILE_OFFSET) return DefinitelyNo; // too short psTileset->seekg(0, stream::start); uint32_t numFiles; psTileset >> u32le(numFiles); if ((numFiles == 0) && (len > 8)) return DefinitelyNo; // invalid empty file uint32_t offset, lastOffset = 0; for (unsigned int i = 0; i < numFiles; i++) { psTileset >> u32le(offset); // The first file always starts at offset 0. // TESTED BY: tls_zone66_isinstance_c01 if ((i == 0) && (offset != 0)) return DefinitelyNo; // Make sure the offsets are increasing, otherwise we'd get a negative // file size (or the file has been tweaked to make opening difficult, but // then there's the -f option to gametls for that.) // TESTED BY: tls_zone66_isinstance_c02 if (offset < lastOffset) return DefinitelyNo; // Make sure the tile is contained within the file // TESTED BY: tls_zone66_isinstance_c03 if ((numFiles+1) * 4 + offset > len) return DefinitelyNo; lastOffset = offset; } // TESTED BY: tls_zone66_isinstance_c00 return DefinitelyYes; }
MusicType::Certainty MusicType_INS_AdLib::isInstance(stream::input_sptr psMusic) const { stream::len lenFile = psMusic->size(); psMusic->seekg(0, stream::start); // Unknown length // TESTED BY: ins_ins_adlib_isinstance_c01 if ( (lenFile != 54) && (lenFile != 78) && (lenFile != 80) ) return MusicType::DefinitelyNo; for (unsigned int i = 0; i < 14; i++) { uint16_t next; psMusic >> u16le(next); // Out of range value // TESTED BY: ins_ins_adlib_isinstance_c02 if (next > 255) return MusicType::DefinitelyNo; } // TESTED BY: ins_ins_adlib_isinstance_c00 return MusicType::PossiblyYes; }
TilesetType_CComic::Certainty TilesetType_CComic::isInstance(stream::input_sptr psGraphics) const { stream::pos len = psGraphics->size(); if (len % 128 == 4) return PossiblyYes; return DefinitelyNo; }
CComicSpriteType::Certainty CComicSpriteType::isInstance(stream::input_sptr psGraphics) const { stream::pos len = psGraphics->size(); if (len % 160 == 0) return PossiblyYes; return DefinitelyNo; }
MapPtr MapType_Hocus::open(stream::input_sptr input, SuppData& suppData) const { input->seekg(0, stream::start); uint8_t code; // Read the background layer Map2D::Layer::ItemPtrVectorPtr bgtiles(new Map2D::Layer::ItemPtrVector()); bgtiles->reserve(HP_MAP_WIDTH * HP_MAP_HEIGHT); for (unsigned int y = 0; y < HP_MAP_HEIGHT; y++) { for (unsigned int x = 0; x < HP_MAP_WIDTH; x++) { Map2D::Layer::ItemPtr t(new Map2D::Layer::Item()); t->type = Map2D::Layer::Item::Default; t->x = x; t->y = y; input >> u8(code); t->code = code; if (t->code != HP_DEFAULT_TILE_BG) bgtiles->push_back(t); } } Map2D::Layer::ItemPtrVectorPtr validBGItems(new Map2D::Layer::ItemPtrVector()); Map2D::LayerPtr bgLayer(new Layer_HocusBackground("Background", bgtiles, validBGItems)); stream::input_sptr layerFile = suppData[SuppItem::Layer1]; assert(layerFile); // Read the foreground layer Map2D::Layer::ItemPtrVectorPtr fgtiles(new Map2D::Layer::ItemPtrVector()); fgtiles->reserve(HP_MAP_WIDTH * HP_MAP_HEIGHT); for (unsigned int y = 0; y < HP_MAP_HEIGHT; y++) { for (unsigned int x = 0; x < HP_MAP_WIDTH; x++) { Map2D::Layer::ItemPtr t(new Map2D::Layer::Item()); t->type = Map2D::Layer::Item::Default; t->x = x; t->y = y; layerFile >> u8(code); t->code = code; if (t->code != HP_DEFAULT_TILE_BG) fgtiles->push_back(t); } } Map2D::Layer::ItemPtrVectorPtr validFGItems(new Map2D::Layer::ItemPtrVector()); Map2D::LayerPtr fgLayer(new Layer_HocusBackground("Foreground", fgtiles, validFGItems)); Map2D::LayerPtrVector layers; layers.push_back(bgLayer); layers.push_back(fgLayer); //layers.push_back(actorLayer); Map2DPtr map(new GenericMap2D( Map::Attributes(), Map::GraphicsFilenames(), Map2D::HasViewport, HP_VIEWPORT_WIDTH, HP_VIEWPORT_HEIGHT, HP_MAP_WIDTH, HP_MAP_HEIGHT, HP_TILE_WIDTH, HP_TILE_HEIGHT, layers, Map2D::PathPtrVectorPtr() )); return map; }