2016-08-24 01:35:59 +00:00
|
|
|
//
|
|
|
|
// StaticAnalyser.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 23/08/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "StaticAnalyser.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
|
2016-08-27 18:25:16 +00:00
|
|
|
#include <cstdlib>
|
2016-08-27 17:42:51 +00:00
|
|
|
|
2016-08-29 12:48:49 +00:00
|
|
|
// Analysers
|
2016-09-15 23:24:59 +00:00
|
|
|
#include "Acorn/StaticAnalyser.hpp"
|
2017-07-31 01:15:20 +00:00
|
|
|
#include "AmstradCPC/StaticAnalyser.hpp"
|
2016-09-15 23:34:45 +00:00
|
|
|
#include "Atari/StaticAnalyser.hpp"
|
2016-09-15 23:24:59 +00:00
|
|
|
#include "Commodore/StaticAnalyser.hpp"
|
2016-10-12 02:20:13 +00:00
|
|
|
#include "Oric/StaticAnalyser.hpp"
|
2017-06-04 21:04:06 +00:00
|
|
|
#include "ZX8081/StaticAnalyser.hpp"
|
2016-08-29 12:48:49 +00:00
|
|
|
|
|
|
|
// Cartridges
|
|
|
|
#include "../Storage/Cartridge/Formats/BinaryDump.hpp"
|
2016-08-27 22:26:51 +00:00
|
|
|
#include "../Storage/Cartridge/Formats/PRG.hpp"
|
|
|
|
|
2016-08-29 12:48:49 +00:00
|
|
|
// Disks
|
2016-09-25 21:46:11 +00:00
|
|
|
#include "../Storage/Disk/Formats/AcornADF.hpp"
|
2017-08-05 14:02:10 +00:00
|
|
|
#include "../Storage/Disk/Formats/CPCDSK.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
#include "../Storage/Disk/Formats/D64.hpp"
|
|
|
|
#include "../Storage/Disk/Formats/G64.hpp"
|
2017-08-18 01:48:48 +00:00
|
|
|
#include "../Storage/Disk/Formats/HFE.hpp"
|
2016-11-21 12:47:16 +00:00
|
|
|
#include "../Storage/Disk/Formats/OricMFMDSK.hpp"
|
2016-09-18 23:21:02 +00:00
|
|
|
#include "../Storage/Disk/Formats/SSD.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
|
2016-08-29 12:48:49 +00:00
|
|
|
// Tapes
|
2016-08-27 20:40:21 +00:00
|
|
|
#include "../Storage/Tape/Formats/CommodoreTAP.hpp"
|
2017-07-11 01:43:58 +00:00
|
|
|
#include "../Storage/Tape/Formats/CSW.hpp"
|
2016-10-11 11:39:48 +00:00
|
|
|
#include "../Storage/Tape/Formats/OricTAP.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
#include "../Storage/Tape/Formats/TapePRG.hpp"
|
|
|
|
#include "../Storage/Tape/Formats/TapeUEF.hpp"
|
2017-07-17 01:33:11 +00:00
|
|
|
#include "../Storage/Tape/Formats/TZX.hpp"
|
2017-06-12 01:38:32 +00:00
|
|
|
#include "../Storage/Tape/Formats/ZX80O81P.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
|
2017-08-27 19:02:13 +00:00
|
|
|
// Target Platform Types
|
|
|
|
#include "../Storage/TargetPlatforms.hpp"
|
2016-08-27 20:40:21 +00:00
|
|
|
|
2016-08-27 17:42:51 +00:00
|
|
|
using namespace StaticAnalyser;
|
|
|
|
|
2017-08-27 19:02:13 +00:00
|
|
|
static Media GetMediaAndPlatforms(const char *file_name, TargetPlatform::IntType &potential_platforms) {
|
2016-08-27 18:25:16 +00:00
|
|
|
// Get the extension, if any; it will be assumed that extensions are reliable, so an extension is a broad-phase
|
|
|
|
// test as to file format.
|
|
|
|
const char *mixed_case_extension = strrchr(file_name, '.');
|
|
|
|
char *lowercase_extension = nullptr;
|
2017-07-30 01:56:33 +00:00
|
|
|
if(mixed_case_extension) {
|
2016-08-27 20:40:21 +00:00
|
|
|
lowercase_extension = strdup(mixed_case_extension+1);
|
2016-08-27 18:25:16 +00:00
|
|
|
char *parser = lowercase_extension;
|
2017-07-30 01:56:33 +00:00
|
|
|
while(*parser) {
|
2016-08-27 18:25:16 +00:00
|
|
|
*parser = (char)tolower(*parser);
|
|
|
|
parser++;
|
|
|
|
}
|
2016-08-27 17:42:51 +00:00
|
|
|
}
|
|
|
|
|
2017-08-17 14:48:29 +00:00
|
|
|
Media result;
|
2016-08-27 22:26:51 +00:00
|
|
|
#define Insert(list, class, platforms) \
|
|
|
|
list.emplace_back(new Storage::class(file_name));\
|
2017-08-27 19:02:13 +00:00
|
|
|
potential_platforms |= platforms;\
|
2017-08-27 19:20:58 +00:00
|
|
|
TargetPlatform::TypeDistinguisher *distinguisher = dynamic_cast<TargetPlatform::TypeDistinguisher *>(list.back().get());\
|
|
|
|
if(distinguisher) potential_platforms &= distinguisher->target_platform_type();
|
2016-08-27 22:26:51 +00:00
|
|
|
|
2016-08-28 16:20:40 +00:00
|
|
|
#define TryInsert(list, class, platforms) \
|
|
|
|
try {\
|
|
|
|
Insert(list, class, platforms) \
|
|
|
|
} catch(...) {}
|
|
|
|
|
2016-08-27 20:40:21 +00:00
|
|
|
#define Format(extension, list, class, platforms) \
|
2017-07-30 01:56:33 +00:00
|
|
|
if(!strcmp(lowercase_extension, extension)) { \
|
2016-08-28 16:20:40 +00:00
|
|
|
TryInsert(list, class, platforms) \
|
2016-08-27 20:40:21 +00:00
|
|
|
}
|
|
|
|
|
2017-07-30 01:56:33 +00:00
|
|
|
if(lowercase_extension) {
|
2017-08-17 14:48:29 +00:00
|
|
|
Format("80", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80
|
|
|
|
Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
|
|
|
|
Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
|
|
|
Format("adf", result.disks, Disk::AcornADF, TargetPlatform::Acorn) // ADF
|
|
|
|
Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // BIN
|
|
|
|
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
|
|
|
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
|
|
|
Format("d64", result.disks, Disk::D64, TargetPlatform::Commodore) // D64
|
|
|
|
Format("dsd", result.disks, Disk::SSD, TargetPlatform::Acorn) // DSD
|
|
|
|
Format("dsk", result.disks, Disk::CPCDSK, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC)
|
|
|
|
Format("dsk", result.disks, Disk::OricMFMDSK, TargetPlatform::Oric) // DSK (Oric)
|
|
|
|
Format("g64", result.disks, Disk::G64, TargetPlatform::Commodore) // G64
|
2017-08-18 01:48:48 +00:00
|
|
|
Format("hfe", result.disks, Disk::HFE, TargetPlatform::AmstradCPC) // HFE (TODO: plus other target platforms)
|
2017-08-17 14:48:29 +00:00
|
|
|
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
|
|
|
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
|
|
|
|
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
|
2017-02-11 18:36:36 +00:00
|
|
|
|
|
|
|
// PRG
|
2017-07-30 01:56:33 +00:00
|
|
|
if(!strcmp(lowercase_extension, "prg")) {
|
2017-02-11 18:36:36 +00:00
|
|
|
// try instantiating as a ROM; failing that accept as a tape
|
2016-08-27 22:17:40 +00:00
|
|
|
try {
|
2017-08-17 14:48:29 +00:00
|
|
|
Insert(result.cartridges, Cartridge::PRG, TargetPlatform::Commodore)
|
2017-07-30 01:56:33 +00:00
|
|
|
} catch(...) {
|
2017-02-11 18:36:36 +00:00
|
|
|
try {
|
2017-08-17 14:48:29 +00:00
|
|
|
Insert(result.tapes, Tape::PRG, TargetPlatform::Commodore)
|
2017-02-11 18:36:36 +00:00
|
|
|
} catch(...) {}
|
|
|
|
}
|
2016-08-27 22:17:40 +00:00
|
|
|
}
|
2016-08-27 20:40:21 +00:00
|
|
|
|
2017-08-17 14:48:29 +00:00
|
|
|
Format("rom", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn) // ROM
|
|
|
|
Format("ssd", result.disks, Disk::SSD, TargetPlatform::Acorn) // SSD
|
|
|
|
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
|
|
|
|
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
|
|
|
|
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX
|
|
|
|
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
2016-08-27 20:40:21 +00:00
|
|
|
|
|
|
|
#undef Format
|
2016-08-27 22:26:51 +00:00
|
|
|
#undef Insert
|
2017-02-11 18:36:36 +00:00
|
|
|
#undef TryInsert
|
2016-08-27 17:42:51 +00:00
|
|
|
|
2017-08-27 19:20:58 +00:00
|
|
|
// Filter potential platforms as per file preferences, if any.
|
|
|
|
|
2017-02-11 18:36:36 +00:00
|
|
|
free(lowercase_extension);
|
|
|
|
}
|
2017-05-07 02:19:08 +00:00
|
|
|
|
2017-08-17 14:48:29 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Media StaticAnalyser::GetMedia(const char *file_name) {
|
2017-08-27 19:02:13 +00:00
|
|
|
TargetPlatform::IntType throwaway;
|
2017-08-17 14:48:29 +00:00
|
|
|
return GetMediaAndPlatforms(file_name, throwaway);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<Target> StaticAnalyser::GetTargets(const char *file_name) {
|
|
|
|
std::list<Target> targets;
|
|
|
|
|
|
|
|
// Collect all disks, tapes and ROMs as can be extrapolated from this file, forming the
|
|
|
|
// union of all platforms this file might be a target for.
|
2017-08-27 19:02:13 +00:00
|
|
|
TargetPlatform::IntType potential_platforms = 0;
|
2017-08-17 14:48:29 +00:00
|
|
|
Media media = GetMediaAndPlatforms(file_name, potential_platforms);
|
|
|
|
|
|
|
|
// Hand off to platform-specific determination of whether these things are actually compatible and,
|
|
|
|
// if so, how to load them.
|
2017-08-27 19:02:13 +00:00
|
|
|
if(potential_platforms & TargetPlatform::Acorn) Acorn::AddTargets(media, targets);
|
|
|
|
if(potential_platforms & TargetPlatform::AmstradCPC) AmstradCPC::AddTargets(media, targets);
|
|
|
|
if(potential_platforms & TargetPlatform::Atari2600) Atari::AddTargets(media, targets);
|
|
|
|
if(potential_platforms & TargetPlatform::Commodore) Commodore::AddTargets(media, targets);
|
|
|
|
if(potential_platforms & TargetPlatform::Oric) Oric::AddTargets(media, targets);
|
2017-08-27 19:20:58 +00:00
|
|
|
if(potential_platforms & TargetPlatform::ZX8081) ZX8081::AddTargets(media, targets, potential_platforms);
|
2017-08-17 14:48:29 +00:00
|
|
|
|
2017-05-07 02:19:08 +00:00
|
|
|
// Reset any tapes to their initial position
|
|
|
|
for(auto target : targets) {
|
2017-08-17 14:48:29 +00:00
|
|
|
for(auto tape : media.tapes) {
|
2017-05-07 02:19:08 +00:00
|
|
|
tape->reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-27 17:42:51 +00:00
|
|
|
return targets;
|
|
|
|
}
|