2017-11-05 17:49:28 +00:00
//
// MachineForTarget.cpp
// Clock Signal
//
// Created by Thomas Harte on 04/11/2017.
2018-05-13 19:19:52 +00:00
// Copyright 2017 Thomas Harte. All rights reserved.
2017-11-05 17:49:28 +00:00
//
# include "MachineForTarget.hpp"
2020-03-19 03:11:25 +00:00
# include <algorithm>
2020-03-13 00:56:02 +00:00
// Sources for runtime options.
2017-11-05 17:49:28 +00:00
# include "../AmstradCPC/AmstradCPC.hpp"
2019-05-03 22:14:10 +00:00
# include "../Apple/AppleII/AppleII.hpp"
2019-05-04 02:16:07 +00:00
# include "../Apple/Macintosh/Macintosh.hpp"
2019-11-09 20:31:41 +00:00
# include "../Atari/2600/Atari2600.hpp"
# include "../Atari/ST/AtariST.hpp"
2018-02-24 03:47:15 +00:00
# include "../ColecoVision/ColecoVision.hpp"
2017-11-05 17:49:28 +00:00
# include "../Commodore/Vic-20/Vic20.hpp"
# include "../Electron/Electron.hpp"
2018-09-22 02:13:07 +00:00
# include "../MasterSystem/MasterSystem.hpp"
2017-11-25 18:18:24 +00:00
# include "../MSX/MSX.hpp"
2017-11-05 17:49:28 +00:00
# include "../Oric/Oric.hpp"
# include "../ZX8081/ZX8081.hpp"
2020-03-13 00:56:02 +00:00
// Sources for construction options.
# include "../../Analyser/Static/Acorn/Target.hpp"
# include "../../Analyser/Static/AmstradCPC/Target.hpp"
# include "../../Analyser/Static/AppleII/Target.hpp"
2020-03-15 16:54:55 +00:00
# include "../../Analyser/Static/Atari2600/Target.hpp"
2020-03-13 00:56:02 +00:00
# include "../../Analyser/Static/AtariST/Target.hpp"
# include "../../Analyser/Static/Commodore/Target.hpp"
# include "../../Analyser/Static/Macintosh/Target.hpp"
# include "../../Analyser/Static/MSX/Target.hpp"
# include "../../Analyser/Static/Oric/Target.hpp"
2020-03-15 16:54:55 +00:00
# include "../../Analyser/Static/Sega/Target.hpp"
2020-03-13 00:56:02 +00:00
# include "../../Analyser/Static/ZX8081/Target.hpp"
2018-01-29 03:22:21 +00:00
# include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp"
2017-11-25 02:36:22 +00:00
# include "TypedDynamicMachine.hpp"
2017-11-05 17:49:28 +00:00
2020-03-15 16:54:55 +00:00
Machine : : DynamicMachine * Machine : : MachineForTarget ( const Analyser : : Static : : Target * target , const ROMMachine : : ROMFetcher & rom_fetcher , Machine : : Error & error ) {
2018-01-29 03:22:21 +00:00
error = Machine : : Error : : None ;
2018-01-25 23:28:19 +00:00
2018-07-11 00:00:46 +00:00
Machine : : DynamicMachine * machine = nullptr ;
try {
# define BindD(name, m) case Analyser::Machine::m: machine = new Machine::TypedDynamicMachine<name::Machine>(name::Machine::m(target, rom_fetcher)); break;
# define Bind(m) BindD(m, m)
switch ( target - > machine ) {
Bind ( AmstradCPC )
2019-05-03 22:14:10 +00:00
BindD ( Apple : : II , AppleII )
2019-05-04 02:16:07 +00:00
BindD ( Apple : : Macintosh , Macintosh )
2018-07-11 00:00:46 +00:00
Bind ( Atari2600 )
2019-10-04 00:17:26 +00:00
BindD ( Atari : : ST , AtariST )
2018-07-11 00:00:46 +00:00
BindD ( Coleco : : Vision , ColecoVision )
2019-06-02 17:39:25 +00:00
BindD ( Commodore : : Vic20 , Vic20 )
2018-07-11 00:00:46 +00:00
Bind ( Electron )
Bind ( MSX )
Bind ( Oric )
2019-06-02 17:39:25 +00:00
BindD ( Sega : : MasterSystem , MasterSystem )
2018-07-11 00:00:46 +00:00
Bind ( ZX8081 )
2018-01-25 23:28:19 +00:00
2018-07-11 00:00:46 +00:00
default :
error = Machine : : Error : : UnknownMachine ;
2018-01-25 23:28:19 +00:00
return nullptr ;
}
2018-07-11 00:00:46 +00:00
# undef Bind
} catch ( ROMMachine : : Error construction_error ) {
switch ( construction_error ) {
case ROMMachine : : Error : : MissingROMs :
error = Machine : : Error : : MissingROM ;
break ;
default :
error = Machine : : Error : : UnknownError ;
break ;
}
2018-01-25 23:28:19 +00:00
}
return machine ;
2017-11-06 01:12:01 +00:00
}
2020-03-15 16:54:55 +00:00
Machine : : DynamicMachine * Machine : : MachineForTargets ( const Analyser : : Static : : TargetList & targets , const ROMMachine : : ROMFetcher & rom_fetcher , Error & error ) {
2018-01-29 03:22:21 +00:00
// Zero targets implies no machine.
if ( targets . empty ( ) ) {
error = Error : : NoTargets ;
return nullptr ;
}
// If there's more than one target, get all the machines and combine them into a multimachine.
if ( targets . size ( ) > 1 ) {
std : : vector < std : : unique_ptr < Machine : : DynamicMachine > > machines ;
for ( const auto & target : targets ) {
2018-03-09 20:36:11 +00:00
machines . emplace_back ( MachineForTarget ( target . get ( ) , rom_fetcher , error ) ) ;
2018-02-09 01:33:57 +00:00
// Exit early if any errors have occurred.
if ( error ! = Error : : None ) {
return nullptr ;
}
2018-01-29 03:22:21 +00:00
}
2018-03-07 00:08:02 +00:00
// If a multimachine would just instantly collapse the list to a single machine, do
// so without the ongoing baggage of a multimachine.
if ( Analyser : : Dynamic : : MultiMachine : : would_collapse ( machines ) ) {
return machines . front ( ) . release ( ) ;
} else {
return new Analyser : : Dynamic : : MultiMachine ( std : : move ( machines ) ) ;
}
2018-01-29 03:22:21 +00:00
}
// There's definitely exactly one target.
2018-03-09 20:36:11 +00:00
return MachineForTarget ( targets . front ( ) . get ( ) , rom_fetcher , error ) ;
2018-01-29 03:22:21 +00:00
}
2018-01-25 02:48:44 +00:00
std : : string Machine : : ShortNameForTargetMachine ( const Analyser : : Machine machine ) {
2017-11-21 02:55:32 +00:00
switch ( machine ) {
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : AmstradCPC : return " AmstradCPC " ;
2018-04-14 23:46:15 +00:00
case Analyser : : Machine : : AppleII : return " AppleII " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : Atari2600 : return " Atari2600 " ;
2019-10-04 00:17:26 +00:00
case Analyser : : Machine : : AtariST : return " AtariST " ;
2018-02-24 03:47:15 +00:00
case Analyser : : Machine : : ColecoVision : return " ColecoVision " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : Electron : return " Electron " ;
2019-05-04 02:16:07 +00:00
case Analyser : : Machine : : Macintosh : return " Macintosh " ;
2019-10-01 01:10:30 +00:00
case Analyser : : Machine : : MasterSystem : return " MasterSystem " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : MSX : return " MSX " ;
case Analyser : : Machine : : Oric : return " Oric " ;
case Analyser : : Machine : : Vic20 : return " Vic20 " ;
case Analyser : : Machine : : ZX8081 : return " ZX8081 " ;
2017-11-12 21:41:09 +00:00
default : return " " ;
2017-11-05 17:49:28 +00:00
}
}
2017-11-21 02:55:32 +00:00
2018-01-25 02:48:44 +00:00
std : : string Machine : : LongNameForTargetMachine ( Analyser : : Machine machine ) {
2017-11-21 02:55:32 +00:00
switch ( machine ) {
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : AmstradCPC : return " Amstrad CPC " ;
2018-04-14 23:46:15 +00:00
case Analyser : : Machine : : AppleII : return " Apple II " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : Atari2600 : return " Atari 2600 " ;
2019-10-04 00:17:26 +00:00
case Analyser : : Machine : : AtariST : return " Atari ST " ;
2018-02-24 03:47:15 +00:00
case Analyser : : Machine : : ColecoVision : return " ColecoVision " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : Electron : return " Acorn Electron " ;
2019-05-04 02:16:07 +00:00
case Analyser : : Machine : : Macintosh : return " Apple Macintosh " ;
2019-10-01 01:10:30 +00:00
case Analyser : : Machine : : MasterSystem : return " Sega Master System " ;
2018-01-25 02:48:44 +00:00
case Analyser : : Machine : : MSX : return " MSX " ;
case Analyser : : Machine : : Oric : return " Oric " ;
case Analyser : : Machine : : Vic20 : return " Vic 20 " ;
case Analyser : : Machine : : ZX8081 : return " ZX80/81 " ;
2017-11-21 02:55:32 +00:00
default : return " " ;
}
}
2020-03-19 03:11:25 +00:00
std : : vector < std : : string > Machine : : AllMachines ( Type type , bool long_names ) {
2020-03-15 04:15:19 +00:00
std : : vector < std : : string > result ;
# define AddName(x) result.push_back(long_names ? LongNameForTargetMachine(Analyser::Machine::x) : ShortNameForTargetMachine(Analyser::Machine::x))
2020-03-19 03:11:25 +00:00
2020-03-19 23:41:50 +00:00
if ( type = = Type : : Any | | type = = Type : : RequiresMedia ) {
AddName ( Atari2600 ) ;
AddName ( ColecoVision ) ;
AddName ( MasterSystem ) ;
}
2020-03-19 03:11:25 +00:00
if ( type = = Type : : Any | | type = = Type : : DoesntRequireMedia ) {
AddName ( AmstradCPC ) ;
AddName ( AppleII ) ;
AddName ( AtariST ) ;
AddName ( Electron ) ;
AddName ( Macintosh ) ;
AddName ( MSX ) ;
AddName ( Oric ) ;
AddName ( Vic20 ) ;
AddName ( ZX8081 ) ;
}
2020-03-15 04:15:19 +00:00
# undef AddName
return result ;
}
2020-03-16 03:48:53 +00:00
std : : map < std : : string , std : : unique_ptr < Reflection : : Struct > > Machine : : AllOptionsByMachineName ( ) {
std : : map < std : : string , std : : unique_ptr < Reflection : : Struct > > options ;
2020-03-17 03:25:05 +00:00
# define Emplace(machine, class) \
options . emplace ( std : : make_pair ( LongNameForTargetMachine ( Analyser : : Machine : : machine ) , std : : make_unique < class : : Options > ( Configurable : : OptionsType : : UserFriendly ) ) ) ;
Emplace ( AmstradCPC , AmstradCPC : : Machine ) ;
2020-03-18 01:53:26 +00:00
Emplace ( AppleII , Apple : : II : : Machine ) ;
2020-03-18 03:52:55 +00:00
Emplace ( AtariST , Atari : : ST : : Machine ) ;
2020-03-18 04:06:52 +00:00
Emplace ( ColecoVision , Coleco : : Vision : : Machine ) ;
2020-03-18 02:06:20 +00:00
Emplace ( Electron , Electron : : Machine ) ;
2020-03-19 01:50:02 +00:00
Emplace ( Macintosh , Apple : : Macintosh : : Machine ) ;
2020-03-18 22:26:22 +00:00
Emplace ( MasterSystem , Sega : : MasterSystem : : Machine ) ;
Emplace ( MSX , MSX : : Machine ) ;
2020-03-18 22:31:31 +00:00
Emplace ( Oric , Oric : : Machine ) ;
2020-03-19 00:23:55 +00:00
Emplace ( Vic20 , Commodore : : Vic20 : : Machine ) ;
2020-03-17 03:25:05 +00:00
Emplace ( ZX8081 , ZX8081 : : Machine ) ;
# undef Emplace
2017-11-21 02:55:32 +00:00
return options ;
}
2020-03-13 00:56:02 +00:00
2020-03-15 16:54:55 +00:00
std : : map < std : : string , std : : unique_ptr < Analyser : : Static : : Target > > Machine : : TargetsByMachineName ( bool meaningful_without_media_only ) {
std : : map < std : : string , std : : unique_ptr < Analyser : : Static : : Target > > options ;
2020-03-13 00:56:02 +00:00
2020-03-15 04:15:19 +00:00
# define AddMapped(Name, TargetNamespace) \
options . emplace ( std : : make_pair ( LongNameForTargetMachine ( Analyser : : Machine : : Name ) , new Analyser : : Static : : TargetNamespace : : Target ) ) ;
# define Add(Name) AddMapped(Name, Name)
2020-03-13 00:56:02 +00:00
Add ( AmstradCPC ) ;
Add ( AppleII ) ;
2020-03-15 04:15:19 +00:00
Add ( AtariST ) ;
AddMapped ( Electron , Acorn ) ;
Add ( Macintosh ) ;
2020-03-13 00:56:02 +00:00
Add ( MSX ) ;
Add ( Oric ) ;
2020-03-15 04:15:19 +00:00
AddMapped ( Vic20 , Commodore ) ;
2020-03-13 00:56:02 +00:00
Add ( ZX8081 ) ;
2020-03-15 16:54:55 +00:00
if ( ! meaningful_without_media_only ) {
Add ( Atari2600 ) ;
options . emplace ( std : : make_pair ( LongNameForTargetMachine ( Analyser : : Machine : : ColecoVision ) , new Analyser : : Static : : Target ( Analyser : : Machine : : ColecoVision ) ) ) ;
AddMapped ( MasterSystem , Sega ) ;
}
2020-03-15 04:15:19 +00:00
# undef Add
# undef AddTwo
2020-03-13 00:56:02 +00:00
return options ;
}