mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Split the static analyser functionality so that it's possible just to ask for the set of media implied by a particular file. Extended ConfigurationTarget so that media alone can be pushed to a machine.
This commit is contained in:
parent
175faebdc9
commit
f68565a33f
@ -776,23 +776,29 @@ class ConcreteMachine:
|
|||||||
read_pointers_[2] = write_pointers_[2];
|
read_pointers_[2] = write_pointers_[2];
|
||||||
read_pointers_[3] = roms_[upper_rom_].data();
|
read_pointers_[3] = roms_[upper_rom_].data();
|
||||||
|
|
||||||
|
// Type whatever is required.
|
||||||
|
if(target.loadingCommand.length()) {
|
||||||
|
set_typer_for_string(target.loadingCommand.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_media(target.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
// If there are any tapes supplied, use the first of them.
|
// If there are any tapes supplied, use the first of them.
|
||||||
if(!target.tapes.empty()) {
|
if(!media.tapes.empty()) {
|
||||||
tape_player_.set_tape(target.tapes.front());
|
tape_player_.set_tape(media.tapes.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert up to four disks.
|
// Insert up to four disks.
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for(auto &disk : target.disks) {
|
for(auto &disk : media.disks) {
|
||||||
fdc_.set_disk(disk, c);
|
fdc_.set_disk(disk, c);
|
||||||
c++;
|
c++;
|
||||||
if(c == 4) break;
|
if(c == 4) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type whatever is required.
|
return !media.tapes.empty() || (!media.disks.empty() && has_fdc_);
|
||||||
if(target.loadingCommand.length()) {
|
|
||||||
set_typer_for_string(target.loadingCommand.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See header; provides the system ROMs.
|
// See header; provides the system ROMs.
|
||||||
|
@ -45,7 +45,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void configure_as_target(const StaticAnalyser::Target &target) {
|
void configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
const std::vector<uint8_t> &rom = target.cartridges.front()->get_segments().front().data;
|
const std::vector<uint8_t> &rom = target.media.cartridges.front()->get_segments().front().data;
|
||||||
switch(target.atari.paging_model) {
|
switch(target.atari.paging_model) {
|
||||||
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new Cartridge::Cartridge<Cartridge::ActivisionStack>(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new Cartridge::Cartridge<Cartridge::ActivisionStack>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::CBSRamPlus: bus_.reset(new Cartridge::Cartridge<Cartridge::CBSRAMPlus>(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::CBSRamPlus: bus_.reset(new Cartridge::Cartridge<Cartridge::CBSRAMPlus>(rom)); break;
|
||||||
@ -81,6 +81,10 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void set_digital_input(Atari2600DigitalInput input, bool state) {
|
void set_digital_input(Atari2600DigitalInput input, bool state) {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case Atari2600DigitalInputJoy1Up: bus_->mos6532_.update_port_input(0, 0x10, state); break;
|
case Atari2600DigitalInputJoy1Up: bus_->mos6532_.update_port_input(0, 0x10, state); break;
|
||||||
|
@ -274,34 +274,6 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void configure_as_target(const StaticAnalyser::Target &target) {
|
void configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
if(target.tapes.size()) {
|
|
||||||
tape_->set_tape(target.tapes.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.disks.size()) {
|
|
||||||
// construct the 1540
|
|
||||||
c1540_.reset(new ::Commodore::C1540::Machine);
|
|
||||||
|
|
||||||
// attach it to the serial bus
|
|
||||||
c1540_->set_serial_bus(serial_bus_);
|
|
||||||
|
|
||||||
// hand it the disk
|
|
||||||
c1540_->set_disk(target.disks.front());
|
|
||||||
|
|
||||||
// install the ROM if it was previously set
|
|
||||||
install_disk_rom();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.cartridges.size()) {
|
|
||||||
rom_address_ = 0xa000;
|
|
||||||
std::vector<uint8_t> rom_image = target.cartridges.front()->get_segments().front().data;
|
|
||||||
rom_length_ = (uint16_t)(rom_image.size());
|
|
||||||
|
|
||||||
rom_ = new uint8_t[0x2000];
|
|
||||||
memcpy(rom_, rom_image.data(), rom_image.size());
|
|
||||||
write_to_map(processor_read_memory_map_, rom_, rom_address_, 0x2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.loadingCommand.length()) {
|
if(target.loadingCommand.length()) {
|
||||||
set_typer_for_string(target.loadingCommand.c_str());
|
set_typer_for_string(target.loadingCommand.c_str());
|
||||||
}
|
}
|
||||||
@ -317,6 +289,41 @@ class ConcreteMachine:
|
|||||||
set_memory_size(ThirtyTwoKB);
|
set_memory_size(ThirtyTwoKB);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(target.media.disks.size()) {
|
||||||
|
// construct the 1540
|
||||||
|
c1540_.reset(new ::Commodore::C1540::Machine);
|
||||||
|
|
||||||
|
// attach it to the serial bus
|
||||||
|
c1540_->set_serial_bus(serial_bus_);
|
||||||
|
|
||||||
|
// install the ROM if it was previously set
|
||||||
|
install_disk_rom();
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_media(target.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
|
if(!media.tapes.empty()) {
|
||||||
|
tape_->set_tape(media.tapes.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!media.disks.empty() && c1540_) {
|
||||||
|
c1540_->set_disk(media.disks.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!media.cartridges.empty()) {
|
||||||
|
rom_address_ = 0xa000;
|
||||||
|
std::vector<uint8_t> rom_image = media.cartridges.front()->get_segments().front().data;
|
||||||
|
rom_length_ = (uint16_t)(rom_image.size());
|
||||||
|
|
||||||
|
rom_ = new uint8_t[0x2000];
|
||||||
|
memcpy(rom_, rom_image.data(), rom_image.size());
|
||||||
|
write_to_map(processor_read_memory_map_, rom_, rom_address_, 0x2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !media.tapes.empty() || (!media.disks.empty() && c1540_ != nullptr) || !media.cartridges.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_key_state(uint16_t key, bool isPressed) {
|
void set_key_state(uint16_t key, bool isPressed) {
|
||||||
|
@ -15,11 +15,19 @@ namespace ConfigurationTarget {
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
A ConfigurationTarget::Machine is anything that can accept a StaticAnalyser::Target
|
A ConfigurationTarget::Machine is anything that can accept a StaticAnalyser::Target
|
||||||
and configure itself appropriately.
|
and configure itself appropriately, or accept a list of media subsequently to insert.
|
||||||
*/
|
*/
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
|
/// Instructs the machine to configure itself as described by @c target and insert the included media.
|
||||||
virtual void configure_as_target(const StaticAnalyser::Target &target) = 0;
|
virtual void configure_as_target(const StaticAnalyser::Target &target) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Requests that the machine insert @c media as a modification to current state
|
||||||
|
|
||||||
|
@returns @c true if any media was inserted; @c false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool insert_media(const StaticAnalyser::Media &media) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -81,11 +81,15 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void configure_as_target(const StaticAnalyser::Target &target) {
|
void configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
if(target.tapes.size()) {
|
if(target.loadingCommand.length()) {
|
||||||
tape_.set_tape(target.tapes.front());
|
set_typer_for_string(target.loadingCommand.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target.disks.size()) {
|
if(target.acorn.should_shift_restart) {
|
||||||
|
shift_restart_counter_ = 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(target.acorn.has_dfs || target.acorn.has_adfs) {
|
||||||
plus3_.reset(new Plus3);
|
plus3_.reset(new Plus3);
|
||||||
|
|
||||||
if(target.acorn.has_dfs) {
|
if(target.acorn.has_dfs) {
|
||||||
@ -95,23 +99,27 @@ class ConcreteMachine:
|
|||||||
set_rom(ROMSlot4, adfs_, true);
|
set_rom(ROMSlot4, adfs_, true);
|
||||||
set_rom(ROMSlot5, std::vector<uint8_t>(adfs_.begin() + 16384, adfs_.end()), true);
|
set_rom(ROMSlot5, std::vector<uint8_t>(adfs_.begin() + 16384, adfs_.end()), true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plus3_->set_disk(target.disks.front(), 0);
|
insert_media(target.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
|
if(!media.tapes.empty()) {
|
||||||
|
tape_.set_tape(media.tapes.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!media.disks.empty() && plus3_) {
|
||||||
|
plus3_->set_disk(media.disks.front(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ROMSlot slot = ROMSlot12;
|
ROMSlot slot = ROMSlot12;
|
||||||
for(std::shared_ptr<Storage::Cartridge::Cartridge> cartridge : target.cartridges) {
|
for(std::shared_ptr<Storage::Cartridge::Cartridge> cartridge : media.cartridges) {
|
||||||
set_rom(slot, cartridge->get_segments().front().data, false);
|
set_rom(slot, cartridge->get_segments().front().data, false);
|
||||||
slot = (ROMSlot)(((int)slot + 1)&15);
|
slot = (ROMSlot)(((int)slot + 1)&15);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target.loadingCommand.length()) {
|
return !media.tapes.empty() || !media.disks.empty() || !media.cartridges.empty();
|
||||||
set_typer_for_string(target.loadingCommand.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.acorn.should_shift_restart) {
|
|
||||||
shift_restart_counter_ = 1000000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
|
@ -91,24 +91,14 @@ class ConcreteMachine:
|
|||||||
|
|
||||||
// to satisfy ConfigurationTarget::Machine
|
// to satisfy ConfigurationTarget::Machine
|
||||||
void configure_as_target(const StaticAnalyser::Target &target) {
|
void configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
if(target.tapes.size()) {
|
|
||||||
via_.tape->set_tape(target.tapes.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.loadingCommand.length()) {
|
|
||||||
set_typer_for_string(target.loadingCommand.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.oric.has_microdisc) {
|
if(target.oric.has_microdisc) {
|
||||||
microdisc_is_enabled_ = true;
|
microdisc_is_enabled_ = true;
|
||||||
microdisc_did_change_paging_flags(µdisc_);
|
microdisc_did_change_paging_flags(µdisc_);
|
||||||
microdisc_.set_delegate(this);
|
microdisc_.set_delegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int drive_index = 0;
|
if(target.loadingCommand.length()) {
|
||||||
for(auto disk : target.disks) {
|
set_typer_for_string(target.loadingCommand.c_str());
|
||||||
if(drive_index < 4) microdisc_.set_disk(disk, drive_index);
|
|
||||||
drive_index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target.oric.use_atmos_rom) {
|
if(target.oric.use_atmos_rom) {
|
||||||
@ -126,6 +116,22 @@ class ConcreteMachine:
|
|||||||
scan_keyboard_address_ = 0xf43c;
|
scan_keyboard_address_ = 0xf43c;
|
||||||
tape_speed_address_ = 0x67;
|
tape_speed_address_ = 0x67;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
insert_media(target.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
|
if(media.tapes.size()) {
|
||||||
|
via_.tape->set_tape(media.tapes.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
int drive_index = 0;
|
||||||
|
for(auto disk : media.disks) {
|
||||||
|
if(drive_index < 4) microdisc_.set_disk(disk, drive_index);
|
||||||
|
drive_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !media.tapes.empty() || (!media.disks.empty() && microdisc_is_enabled_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// to satisfy CPU::MOS6502::BusHandler
|
// to satisfy CPU::MOS6502::BusHandler
|
||||||
|
@ -268,13 +268,19 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
Memory::Fuzz(ram_);
|
Memory::Fuzz(ram_);
|
||||||
|
|
||||||
if(target.tapes.size()) {
|
|
||||||
tape_player_.set_tape(target.tapes.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(target.loadingCommand.length()) {
|
if(target.loadingCommand.length()) {
|
||||||
set_typer_for_string(target.loadingCommand.c_str());
|
set_typer_for_string(target.loadingCommand.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
insert_media(target.media);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert_media(const StaticAnalyser::Media &media) {
|
||||||
|
if(!media.tapes.empty()) {
|
||||||
|
tape_player_.set_tape(media.tapes.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
return !media.tapes.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_typer_for_string(const char *string) {
|
void set_typer_for_string(const char *string) {
|
||||||
|
@ -164,6 +164,10 @@ class MachineDocument:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final func openGLView(_ view: CSOpenGLView, didReceiveFileAt URL: URL) {
|
||||||
|
// TODO: pass to machine.
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: NSDocument overrides
|
// MARK: NSDocument overrides
|
||||||
override func data(ofType typeName: String) throws -> Data {
|
override func data(ofType typeName: String) throws -> Data {
|
||||||
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
|
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
|
||||||
|
@ -15,12 +15,19 @@
|
|||||||
/*!
|
/*!
|
||||||
Requests that the delegate produce an image of its current output state. May be called on
|
Requests that the delegate produce an image of its current output state. May be called on
|
||||||
any queue or thread.
|
any queue or thread.
|
||||||
@param view The view makin the request.
|
@param view The view making the request.
|
||||||
@param onlyIfDirty If @c YES then the delegate may decline to redraw if its output would be
|
@param onlyIfDirty If @c YES then the delegate may decline to redraw if its output would be
|
||||||
identical to the previous frame. If @c NO then the delegate must draw.
|
identical to the previous frame. If @c NO then the delegate must draw.
|
||||||
*/
|
*/
|
||||||
- (void)openGLView:(nonnull CSOpenGLView *)view drawViewOnlyIfDirty:(BOOL)onlyIfDirty;
|
- (void)openGLView:(nonnull CSOpenGLView *)view drawViewOnlyIfDirty:(BOOL)onlyIfDirty;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Announces receipt of a file by drag and drop to the delegate.
|
||||||
|
@param view The view making the request.
|
||||||
|
@param URL The file URL of the received file.
|
||||||
|
*/
|
||||||
|
- (void)openGLView:(nonnull CSOpenGLView *)view didReceiveFileAtURL:(nonnull NSURL *)URL;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol CSOpenGLViewResponderDelegate <NSObject>
|
@protocol CSOpenGLViewResponderDelegate <NSObject>
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
@import CoreVideo;
|
@import CoreVideo;
|
||||||
@import GLKit;
|
@import GLKit;
|
||||||
|
|
||||||
|
@interface CSOpenGLView () <NSDraggingDestination>
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation CSOpenGLView {
|
@implementation CSOpenGLView {
|
||||||
CVDisplayLinkRef _displayLink;
|
CVDisplayLinkRef _displayLink;
|
||||||
}
|
}
|
||||||
@ -105,6 +108,9 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
self.pixelFormat = pixelFormat;
|
self.pixelFormat = pixelFormat;
|
||||||
self.openGLContext = context;
|
self.openGLContext = context;
|
||||||
self.wantsBestResolutionOpenGLSurface = YES;
|
self.wantsBestResolutionOpenGLSurface = YES;
|
||||||
|
|
||||||
|
// Register to receive dragged and dropped file URLs.
|
||||||
|
[self registerForDraggedTypes:@[(__bridge NSString *)kUTTypeFileURL]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)dirtyRect
|
- (void)drawRect:(NSRect)dirtyRect
|
||||||
@ -150,4 +156,24 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
|||||||
[self.responderDelegate flagsChanged:theEvent];
|
[self.responderDelegate flagsChanged:theEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSDraggingDestination
|
||||||
|
|
||||||
|
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||||
|
{
|
||||||
|
for(NSPasteboardItem *item in [[sender draggingPasteboard] pasteboardItems])
|
||||||
|
{
|
||||||
|
NSURL *URL = [NSURL URLWithString:[item stringForType:(__bridge NSString *)kUTTypeFileURL]];
|
||||||
|
|
||||||
|
NSLog(@"%@", URL);
|
||||||
|
[self.delegate openGLView:self didReceiveFileAtURL:URL];
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
|
||||||
|
{
|
||||||
|
// we'll drag and drop, yeah?
|
||||||
|
return NSDragOperationLink;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -56,11 +56,7 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
|||||||
return acorn_cartridges;
|
return acorn_cartridges;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Acorn::AddTargets(
|
void StaticAnalyser::Acorn::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
Target target;
|
Target target;
|
||||||
target.machine = Target::Electron;
|
target.machine = Target::Electron;
|
||||||
target.probability = 1.0; // TODO: a proper estimation
|
target.probability = 1.0; // TODO: a proper estimation
|
||||||
@ -69,11 +65,11 @@ void StaticAnalyser::Acorn::AddTargets(
|
|||||||
target.acorn.should_shift_restart = false;
|
target.acorn.should_shift_restart = false;
|
||||||
|
|
||||||
// strip out inappropriate cartridges
|
// strip out inappropriate cartridges
|
||||||
target.cartridges = AcornCartridgesFrom(cartridges);
|
target.media.cartridges = AcornCartridgesFrom(media.cartridges);
|
||||||
|
|
||||||
// if there are any tapes, attempt to get data from the first
|
// if there are any tapes, attempt to get data from the first
|
||||||
if(tapes.size() > 0) {
|
if(media.tapes.size() > 0) {
|
||||||
std::shared_ptr<Storage::Tape::Tape> tape = tapes.front();
|
std::shared_ptr<Storage::Tape::Tape> tape = media.tapes.front();
|
||||||
std::list<File> files = GetFiles(tape);
|
std::list<File> files = GetFiles(tape);
|
||||||
tape->reset();
|
tape->reset();
|
||||||
|
|
||||||
@ -102,17 +98,17 @@ void StaticAnalyser::Acorn::AddTargets(
|
|||||||
// then the loading command is *RUN. Otherwise it's CHAIN"".
|
// then the loading command is *RUN. Otherwise it's CHAIN"".
|
||||||
target.loadingCommand = is_basic ? "CHAIN\"\"\n" : "*RUN\n";
|
target.loadingCommand = is_basic ? "CHAIN\"\"\n" : "*RUN\n";
|
||||||
|
|
||||||
target.tapes = tapes;
|
target.media.tapes = media.tapes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(disks.size() > 0) {
|
if(media.disks.size() > 0) {
|
||||||
std::shared_ptr<Storage::Disk::Disk> disk = disks.front();
|
std::shared_ptr<Storage::Disk::Disk> disk = media.disks.front();
|
||||||
std::unique_ptr<Catalogue> dfs_catalogue, adfs_catalogue;
|
std::unique_ptr<Catalogue> dfs_catalogue, adfs_catalogue;
|
||||||
dfs_catalogue = GetDFSCatalogue(disk);
|
dfs_catalogue = GetDFSCatalogue(disk);
|
||||||
if(dfs_catalogue == nullptr) adfs_catalogue = GetADFSCatalogue(disk);
|
if(dfs_catalogue == nullptr) adfs_catalogue = GetADFSCatalogue(disk);
|
||||||
if(dfs_catalogue || adfs_catalogue) {
|
if(dfs_catalogue || adfs_catalogue) {
|
||||||
target.disks = disks;
|
target.media.disks = media.disks;
|
||||||
target.acorn.has_dfs = !!dfs_catalogue;
|
target.acorn.has_dfs = !!dfs_catalogue;
|
||||||
target.acorn.has_adfs = !!adfs_catalogue;
|
target.acorn.has_adfs = !!adfs_catalogue;
|
||||||
|
|
||||||
@ -124,6 +120,6 @@ void StaticAnalyser::Acorn::AddTargets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target.tapes.size() || target.disks.size() || target.cartridges.size())
|
if(target.media.tapes.size() || target.media.disks.size() || target.media.cartridges.size())
|
||||||
destination.push_back(target);
|
destination.push_back(target);
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace Acorn {
|
namespace Acorn {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,28 +128,24 @@ static void InspectSystemCatalogue(
|
|||||||
InspectDataCatalogue(catalogue, target);
|
InspectDataCatalogue(catalogue, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::AmstradCPC::AddTargets(
|
void StaticAnalyser::AmstradCPC::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
Target target;
|
Target target;
|
||||||
target.machine = Target::AmstradCPC;
|
target.machine = Target::AmstradCPC;
|
||||||
target.probability = 1.0;
|
target.probability = 1.0;
|
||||||
target.disks = disks;
|
target.media.disks = media.disks;
|
||||||
target.tapes = tapes;
|
target.media.tapes = media.tapes;
|
||||||
target.cartridges = cartridges;
|
target.media.cartridges = media.cartridges;
|
||||||
|
|
||||||
target.amstradcpc.model = AmstradCPCModel::CPC6128;
|
target.amstradcpc.model = AmstradCPCModel::CPC6128;
|
||||||
|
|
||||||
if(!target.tapes.empty()) {
|
if(!target.media.tapes.empty()) {
|
||||||
// Ugliness flows here: assume the CPC isn't smart enough to pause between pressing
|
// Ugliness flows here: assume the CPC isn't smart enough to pause between pressing
|
||||||
// enter and responding to the follow-on prompt to press a key, so just type for
|
// enter and responding to the follow-on prompt to press a key, so just type for
|
||||||
// a while. Yuck!
|
// a while. Yuck!
|
||||||
target.loadingCommand = "|tape\nrun\"\n1234567890";
|
target.loadingCommand = "|tape\nrun\"\n1234567890";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!target.disks.empty()) {
|
if(!target.media.disks.empty()) {
|
||||||
Storage::Disk::CPM::ParameterBlock data_format;
|
Storage::Disk::CPM::ParameterBlock data_format;
|
||||||
data_format.sectors_per_track = 9;
|
data_format.sectors_per_track = 9;
|
||||||
data_format.tracks = 40;
|
data_format.tracks = 40;
|
||||||
@ -158,7 +154,7 @@ void StaticAnalyser::AmstradCPC::AddTargets(
|
|||||||
data_format.catalogue_allocation_bitmap = 0xc000;
|
data_format.catalogue_allocation_bitmap = 0xc000;
|
||||||
data_format.reserved_tracks = 0;
|
data_format.reserved_tracks = 0;
|
||||||
|
|
||||||
std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), data_format);
|
std::unique_ptr<Storage::Disk::CPM::Catalogue> data_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), data_format);
|
||||||
if(data_catalogue) {
|
if(data_catalogue) {
|
||||||
InspectDataCatalogue(*data_catalogue, target);
|
InspectDataCatalogue(*data_catalogue, target);
|
||||||
} else {
|
} else {
|
||||||
@ -170,9 +166,9 @@ void StaticAnalyser::AmstradCPC::AddTargets(
|
|||||||
system_format.catalogue_allocation_bitmap = 0xc000;
|
system_format.catalogue_allocation_bitmap = 0xc000;
|
||||||
system_format.reserved_tracks = 2;
|
system_format.reserved_tracks = 2;
|
||||||
|
|
||||||
std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue = Storage::Disk::CPM::GetCatalogue(target.disks.front(), system_format);
|
std::unique_ptr<Storage::Disk::CPM::Catalogue> system_catalogue = Storage::Disk::CPM::GetCatalogue(target.media.disks.front(), system_format);
|
||||||
if(system_catalogue) {
|
if(system_catalogue) {
|
||||||
InspectSystemCatalogue(target.disks.front(), *system_catalogue, target);
|
InspectSystemCatalogue(target.media.disks.front(), *system_catalogue, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace AmstradCPC {
|
namespace AmstradCPC {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,24 +178,18 @@ static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Atari::AddTargets(
|
void StaticAnalyser::Atari::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
// TODO: sanity checking; is this image really for an Atari 2600.
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
// TODO: sanity checking; is this image really for an Atari 2600?
|
|
||||||
Target target;
|
Target target;
|
||||||
target.machine = Target::Atari2600;
|
target.machine = Target::Atari2600;
|
||||||
target.probability = 1.0;
|
target.probability = 1.0;
|
||||||
target.disks = disks;
|
target.media.cartridges = media.cartridges;
|
||||||
target.tapes = tapes;
|
|
||||||
target.cartridges = cartridges;
|
|
||||||
target.atari.paging_model = Atari2600PagingModel::None;
|
target.atari.paging_model = Atari2600PagingModel::None;
|
||||||
target.atari.uses_superchip = false;
|
target.atari.uses_superchip = false;
|
||||||
|
|
||||||
// try to figure out the paging scheme
|
// try to figure out the paging scheme
|
||||||
if(!cartridges.empty()) {
|
if(!media.cartridges.empty()) {
|
||||||
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = cartridges.front()->get_segments();
|
const std::list<Storage::Cartridge::Cartridge::Segment> &segments = media.cartridges.front()->get_segments();
|
||||||
|
|
||||||
if(segments.size() == 1) {
|
if(segments.size() == 1) {
|
||||||
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
const Storage::Cartridge::Cartridge::Segment &segment = segments.front();
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace Atari {
|
namespace Atari {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,7 @@ static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
|
|||||||
return vic20_cartridges;
|
return vic20_cartridges;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Commodore::AddTargets(
|
void StaticAnalyser::Commodore::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
Target target;
|
Target target;
|
||||||
target.machine = Target::Vic20; // TODO: machine estimation
|
target.machine = Target::Vic20; // TODO: machine estimation
|
||||||
target.probability = 1.0; // TODO: a proper estimation
|
target.probability = 1.0; // TODO: a proper estimation
|
||||||
@ -52,26 +48,26 @@ void StaticAnalyser::Commodore::AddTargets(
|
|||||||
bool is_disk = false;
|
bool is_disk = false;
|
||||||
|
|
||||||
// strip out inappropriate cartridges
|
// strip out inappropriate cartridges
|
||||||
target.cartridges = Vic20CartridgesFrom(cartridges);
|
target.media.cartridges = Vic20CartridgesFrom(media.cartridges);
|
||||||
|
|
||||||
// check disks
|
// check disks
|
||||||
for(auto &disk : disks) {
|
for(auto &disk : media.disks) {
|
||||||
std::list<File> disk_files = GetFiles(disk);
|
std::list<File> disk_files = GetFiles(disk);
|
||||||
if(disk_files.size()) {
|
if(disk_files.size()) {
|
||||||
is_disk = true;
|
is_disk = true;
|
||||||
files.splice(files.end(), disk_files);
|
files.splice(files.end(), disk_files);
|
||||||
target.disks = disks;
|
target.media.disks.push_back(disk);
|
||||||
if(!device) device = 8;
|
if(!device) device = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check tapes
|
// check tapes
|
||||||
for(auto &tape : tapes) {
|
for(auto &tape : media.tapes) {
|
||||||
std::list<File> tape_files = GetFiles(tape);
|
std::list<File> tape_files = GetFiles(tape);
|
||||||
tape->reset();
|
tape->reset();
|
||||||
if(tape_files.size()) {
|
if(tape_files.size()) {
|
||||||
files.splice(files.end(), tape_files);
|
files.splice(files.end(), tape_files);
|
||||||
target.tapes = tapes;
|
target.media.tapes.push_back(tape);
|
||||||
if(!device) device = 1;
|
if(!device) device = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,6 +136,6 @@ void StaticAnalyser::Commodore::AddTargets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target.tapes.size() || target.cartridges.size() || target.disks.size())
|
if(target.media.tapes.size() || target.media.cartridges.size() || target.media.disks.size())
|
||||||
destination.push_back(target);
|
destination.push_back(target);
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace Commodore {
|
namespace Commodore {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,11 +72,7 @@ static int Basic11Score(const StaticAnalyser::MOS6502::Disassembly &disassembly)
|
|||||||
return Score(disassembly, rom_functions, variable_locations);
|
return Score(disassembly, rom_functions, variable_locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Oric::AddTargets(
|
void StaticAnalyser::Oric::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
Target target;
|
Target target;
|
||||||
target.machine = Target::Oric;
|
target.machine = Target::Oric;
|
||||||
target.probability = 1.0;
|
target.probability = 1.0;
|
||||||
@ -84,7 +80,7 @@ void StaticAnalyser::Oric::AddTargets(
|
|||||||
int basic10_votes = 0;
|
int basic10_votes = 0;
|
||||||
int basic11_votes = 0;
|
int basic11_votes = 0;
|
||||||
|
|
||||||
for(auto &tape : tapes) {
|
for(auto &tape : media.tapes) {
|
||||||
std::list<File> tape_files = GetFiles(tape);
|
std::list<File> tape_files = GetFiles(tape);
|
||||||
tape->reset();
|
tape->reset();
|
||||||
if(tape_files.size()) {
|
if(tape_files.size()) {
|
||||||
@ -100,15 +96,15 @@ void StaticAnalyser::Oric::AddTargets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.tapes.push_back(tape);
|
target.media.tapes.push_back(tape);
|
||||||
target.loadingCommand = "CLOAD\"\"\n";
|
target.loadingCommand = "CLOAD\"\"\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// trust that any disk supplied can be handled by the Microdisc. TODO: check.
|
// trust that any disk supplied can be handled by the Microdisc. TODO: check.
|
||||||
if(!disks.empty()) {
|
if(!media.disks.empty()) {
|
||||||
target.oric.has_microdisc = true;
|
target.oric.has_microdisc = true;
|
||||||
target.disks = disks;
|
target.media.disks = media.disks;
|
||||||
} else {
|
} else {
|
||||||
target.oric.has_microdisc = false;
|
target.oric.has_microdisc = false;
|
||||||
}
|
}
|
||||||
@ -117,6 +113,6 @@ void StaticAnalyser::Oric::AddTargets(
|
|||||||
target.oric.use_atmos_rom = basic11_votes >= basic10_votes;
|
target.oric.use_atmos_rom = basic11_votes >= basic10_votes;
|
||||||
if(target.oric.has_microdisc) target.oric.use_atmos_rom = true;
|
if(target.oric.has_microdisc) target.oric.use_atmos_rom = true;
|
||||||
|
|
||||||
if(target.tapes.size() || target.disks.size() || target.cartridges.size())
|
if(target.media.tapes.size() || target.media.disks.size() || target.media.cartridges.size())
|
||||||
destination.push_back(target);
|
destination.push_back(target);
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace Oric {
|
namespace Oric {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,86 @@ enum class TargetPlatform: TargetPlatformType {
|
|||||||
|
|
||||||
using namespace StaticAnalyser;
|
using namespace StaticAnalyser;
|
||||||
|
|
||||||
|
static Media GetMediaAndPlatforms(const char *file_name, TargetPlatformType &potential_platforms) {
|
||||||
|
// 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;
|
||||||
|
if(mixed_case_extension) {
|
||||||
|
lowercase_extension = strdup(mixed_case_extension+1);
|
||||||
|
char *parser = lowercase_extension;
|
||||||
|
while(*parser) {
|
||||||
|
*parser = (char)tolower(*parser);
|
||||||
|
parser++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Media result;
|
||||||
|
#define Insert(list, class, platforms) \
|
||||||
|
list.emplace_back(new Storage::class(file_name));\
|
||||||
|
potential_platforms |= (TargetPlatformType)(platforms);\
|
||||||
|
|
||||||
|
#define TryInsert(list, class, platforms) \
|
||||||
|
try {\
|
||||||
|
Insert(list, class, platforms) \
|
||||||
|
} catch(...) {}
|
||||||
|
|
||||||
|
#define Format(extension, list, class, platforms) \
|
||||||
|
if(!strcmp(lowercase_extension, extension)) { \
|
||||||
|
TryInsert(list, class, platforms) \
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lowercase_extension) {
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
// PRG
|
||||||
|
if(!strcmp(lowercase_extension, "prg")) {
|
||||||
|
// try instantiating as a ROM; failing that accept as a tape
|
||||||
|
try {
|
||||||
|
Insert(result.cartridges, Cartridge::PRG, TargetPlatform::Commodore)
|
||||||
|
} catch(...) {
|
||||||
|
try {
|
||||||
|
Insert(result.tapes, Tape::PRG, TargetPlatform::Commodore)
|
||||||
|
} catch(...) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
#undef Format
|
||||||
|
#undef Insert
|
||||||
|
#undef TryInsert
|
||||||
|
|
||||||
|
free(lowercase_extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Media StaticAnalyser::GetMedia(const char *file_name) {
|
||||||
|
TargetPlatformType throwaway;
|
||||||
|
return GetMediaAndPlatforms(file_name, throwaway);
|
||||||
|
}
|
||||||
|
|
||||||
std::list<Target> StaticAnalyser::GetTargets(const char *file_name) {
|
std::list<Target> StaticAnalyser::GetTargets(const char *file_name) {
|
||||||
std::list<Target> targets;
|
std::list<Target> targets;
|
||||||
|
|
||||||
@ -71,80 +151,21 @@ std::list<Target> StaticAnalyser::GetTargets(const char *file_name) {
|
|||||||
|
|
||||||
// Collect all disks, tapes and ROMs as can be extrapolated from this file, forming the
|
// 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.
|
// union of all platforms this file might be a target for.
|
||||||
std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
|
|
||||||
std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
|
|
||||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
|
||||||
TargetPlatformType potential_platforms = 0;
|
TargetPlatformType potential_platforms = 0;
|
||||||
|
Media media = GetMediaAndPlatforms(file_name, potential_platforms);
|
||||||
|
|
||||||
#define Insert(list, class, platforms) \
|
// Hand off to platform-specific determination of whether these things are actually compatible and,
|
||||||
list.emplace_back(new Storage::class(file_name));\
|
// if so, how to load them.
|
||||||
potential_platforms |= (TargetPlatformType)(platforms);\
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::Acorn) Acorn::AddTargets(media, targets);
|
||||||
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::AmstradCPC) AmstradCPC::AddTargets(media, targets);
|
||||||
#define TryInsert(list, class, platforms) \
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::Atari2600) Atari::AddTargets(media, targets);
|
||||||
try {\
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::Commodore) Commodore::AddTargets(media, targets);
|
||||||
Insert(list, class, platforms) \
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::Oric) Oric::AddTargets(media, targets);
|
||||||
} catch(...) {}
|
if(potential_platforms & (TargetPlatformType)TargetPlatform::ZX8081) ZX8081::AddTargets(media, targets);
|
||||||
|
|
||||||
#define Format(extension, list, class, platforms) \
|
|
||||||
if(!strcmp(lowercase_extension, extension)) { \
|
|
||||||
TryInsert(list, class, platforms) \
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lowercase_extension) {
|
|
||||||
Format("80", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80
|
|
||||||
Format("81", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
|
|
||||||
Format("a26", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
|
||||||
Format("adf", disks, Disk::AcornADF, TargetPlatform::Acorn) // ADF
|
|
||||||
Format("bin", cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // BIN
|
|
||||||
Format("cdt", tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
|
||||||
Format("csw", tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
|
||||||
Format("d64", disks, Disk::D64, TargetPlatform::Commodore) // D64
|
|
||||||
Format("dsd", disks, Disk::SSD, TargetPlatform::Acorn) // DSD
|
|
||||||
Format("dsk", disks, Disk::CPCDSK, TargetPlatform::AmstradCPC) // DSK (Amstrad CPC)
|
|
||||||
Format("dsk", disks, Disk::OricMFMDSK, TargetPlatform::Oric) // DSK (Oric)
|
|
||||||
Format("g64", disks, Disk::G64, TargetPlatform::Commodore) // G64
|
|
||||||
Format("o", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
|
||||||
Format("p", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
|
|
||||||
Format("p81", tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
|
|
||||||
|
|
||||||
// PRG
|
|
||||||
if(!strcmp(lowercase_extension, "prg")) {
|
|
||||||
// try instantiating as a ROM; failing that accept as a tape
|
|
||||||
try {
|
|
||||||
Insert(cartridges, Cartridge::PRG, TargetPlatform::Commodore)
|
|
||||||
} catch(...) {
|
|
||||||
try {
|
|
||||||
Insert(tapes, Tape::PRG, TargetPlatform::Commodore)
|
|
||||||
} catch(...) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Format("rom", cartridges, Cartridge::BinaryDump, TargetPlatform::Acorn) // ROM
|
|
||||||
Format("ssd", disks, Disk::SSD, TargetPlatform::Acorn) // SSD
|
|
||||||
Format("tap", tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
|
|
||||||
Format("tap", tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
|
|
||||||
Format("tzx", tapes, Tape::TZX, TargetPlatform::ZX8081) // TZX
|
|
||||||
Format("uef", tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
|
||||||
|
|
||||||
#undef Format
|
|
||||||
#undef Insert
|
|
||||||
#undef TryInsert
|
|
||||||
|
|
||||||
// Hand off to platform-specific determination of whether these things are actually compatible and,
|
|
||||||
// if so, how to load them. (TODO)
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::Acorn) Acorn::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::AmstradCPC) AmstradCPC::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::Atari2600) Atari::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::Commodore) Commodore::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::Oric) Oric::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
if(potential_platforms & (TargetPlatformType)TargetPlatform::ZX8081) ZX8081::AddTargets(disks, tapes, cartridges, targets);
|
|
||||||
|
|
||||||
free(lowercase_extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset any tapes to their initial position
|
// Reset any tapes to their initial position
|
||||||
for(auto target : targets) {
|
for(auto target : targets) {
|
||||||
for(auto tape : target.tapes) {
|
for(auto tape : media.tapes) {
|
||||||
tape->reset();
|
tape->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,15 @@ enum class AmstradCPCModel {
|
|||||||
CPC6128
|
CPC6128
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
A list of disks, tapes and cartridges.
|
||||||
|
*/
|
||||||
|
struct Media {
|
||||||
|
std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
|
||||||
|
std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
|
||||||
|
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
A list of disks, tapes and cartridges plus information about the machine to which to attach them and its configuration,
|
A list of disks, tapes and cartridges plus information about the machine to which to attach them and its configuration,
|
||||||
and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness.
|
and instructions on how to launch the software attached, plus a measure of confidence in this target's correctness.
|
||||||
@ -102,10 +111,7 @@ struct Target {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string loadingCommand;
|
std::string loadingCommand;
|
||||||
|
Media media;
|
||||||
std::list<std::shared_ptr<Storage::Disk::Disk>> disks;
|
|
||||||
std::list<std::shared_ptr<Storage::Tape::Tape>> tapes;
|
|
||||||
std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> cartridges;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -115,6 +121,11 @@ struct Target {
|
|||||||
*/
|
*/
|
||||||
std::list<Target> GetTargets(const char *file_name);
|
std::list<Target> GetTargets(const char *file_name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Inspects the supplied file and determines the media included.
|
||||||
|
*/
|
||||||
|
Media GetMedia(const char *file_name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* StaticAnalyser_hpp */
|
#endif /* StaticAnalyser_hpp */
|
||||||
|
@ -27,15 +27,10 @@ static std::vector<Storage::Data::ZX8081::File> GetFiles(const std::shared_ptr<S
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::ZX8081::AddTargets(
|
void StaticAnalyser::ZX8081::AddTargets(const Media &media, std::list<Target> &destination) {
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
if(!media.tapes.empty()) {
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
std::vector<Storage::Data::ZX8081::File> files = GetFiles(media.tapes.front());
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
media.tapes.front()->reset();
|
||||||
std::list<StaticAnalyser::Target> &destination) {
|
|
||||||
|
|
||||||
if(!tapes.empty()) {
|
|
||||||
std::vector<Storage::Data::ZX8081::File> files = GetFiles(tapes.front());
|
|
||||||
tapes.front()->reset();
|
|
||||||
if(!files.empty()) {
|
if(!files.empty()) {
|
||||||
StaticAnalyser::Target target;
|
StaticAnalyser::Target target;
|
||||||
target.machine = Target::ZX8081;
|
target.machine = Target::ZX8081;
|
||||||
@ -47,7 +42,7 @@ void StaticAnalyser::ZX8081::AddTargets(
|
|||||||
} else {
|
} else {
|
||||||
target.zx8081.memory_model = ZX8081MemoryModel::Unexpanded;
|
target.zx8081.memory_model = ZX8081MemoryModel::Unexpanded;
|
||||||
}
|
}
|
||||||
target.tapes = tapes;
|
target.media.tapes = media.tapes;
|
||||||
|
|
||||||
// TODO: how to run software once loaded? Might require a BASIC detokeniser.
|
// TODO: how to run software once loaded? Might require a BASIC detokeniser.
|
||||||
if(target.zx8081.isZX81) {
|
if(target.zx8081.isZX81) {
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
namespace StaticAnalyser {
|
namespace StaticAnalyser {
|
||||||
namespace ZX8081 {
|
namespace ZX8081 {
|
||||||
|
|
||||||
void AddTargets(
|
void AddTargets(const Media &media, std::list<Target> &destination);
|
||||||
const std::list<std::shared_ptr<Storage::Disk::Disk>> &disks,
|
|
||||||
const std::list<std::shared_ptr<Storage::Tape::Tape>> &tapes,
|
|
||||||
const std::list<std::shared_ptr<Storage::Cartridge::Cartridge>> &cartridges,
|
|
||||||
std::list<Target> &destination
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user