icarus.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "icarus.hpp"
  2. namespace icarus {
  3. vector<shared_pointer<Media>> media;
  4. auto locate(string name) -> string {
  5. string location = {Path::program(), name};
  6. if(inode::exists(location)) return location;
  7. directory::create({Path::userData(), "icarus/"});
  8. return {Path::userData(), "icarus/", name};
  9. }
  10. auto operator+=(string& lhs, const string& rhs) -> string& {
  11. lhs.append(rhs);
  12. return lhs;
  13. }
  14. #include "settings/settings.cpp"
  15. #include "media/media.cpp"
  16. #include "cartridge/cartridge.cpp"
  17. #include "compact-disc/compact-disc.cpp"
  18. #include "floppy-disk/floppy-disk.cpp"
  19. #include "program/program.cpp"
  20. auto construct() -> void {
  21. media.append(new BSMemory);
  22. media.append(new ColecoVision);
  23. media.append(new Famicom);
  24. media.append(new FamicomDisk);
  25. media.append(new GameBoy);
  26. media.append(new GameBoyAdvance);
  27. media.append(new GameBoyColor);
  28. media.append(new GameGear);
  29. media.append(new MasterSystem);
  30. media.append(new MegaCD);
  31. media.append(new MegaDrive);
  32. media.append(new MSX);
  33. media.append(new MSX2);
  34. media.append(new NeoGeoPocket);
  35. media.append(new NeoGeoPocketColor);
  36. media.append(new PCEngine);
  37. media.append(new PCEngineCD);
  38. media.append(new PocketChallengeV2);
  39. media.append(new SC3000);
  40. media.append(new SG1000);
  41. media.append(new SufamiTurbo);
  42. media.append(new SuperFamicom);
  43. media.append(new SuperGrafx);
  44. media.append(new WonderSwan);
  45. media.append(new WonderSwanColor);
  46. for(auto& medium : media) medium->construct();
  47. }
  48. auto medium(const string& name) -> shared_pointer<Media> {
  49. for(auto& medium : media) {
  50. if(medium->name() == name) return medium;
  51. }
  52. return {};
  53. }
  54. auto identify(const string& filename) -> string {
  55. auto extension = Location::suffix(filename).trimLeft(".", 1L).downcase();
  56. if(extension == "zip") {
  57. Decode::ZIP archive;
  58. if(archive.open(filename)) {
  59. for(auto& file : archive.file) {
  60. auto match = Location::suffix(file.name).trimLeft(".", 1L).downcase();
  61. for(auto& medium : media) {
  62. if(medium->extensions().find(match)) {
  63. extension = match;
  64. }
  65. }
  66. }
  67. }
  68. }
  69. for(auto& medium : media) {
  70. if(medium->extensions().find(extension)) {
  71. if(auto manifest = medium->manifest(filename)) {
  72. return medium->name();
  73. }
  74. }
  75. }
  76. return {}; //unable to identify
  77. }
  78. auto main(Arguments arguments) -> void {
  79. Application::setName("icarus");
  80. construct();
  81. if(auto document = file::read({Path::userSettings(), "icarus/settings.bml"})) {
  82. settings.unserialize(document);
  83. }
  84. if(arguments.take("--name")) {
  85. return print("icarus");
  86. }
  87. if(string filename; arguments.take("--identify", filename)) {
  88. return print(identify(filename), "\n");
  89. }
  90. if(string system; arguments.take("--system", system)) {
  91. for(auto& medium : media) {
  92. if(medium->name() != system) continue;
  93. if(string manifest; arguments.take("--manifest", manifest)) {
  94. if(auto result = medium->manifest(manifest)) return print(result);
  95. if(medium->extensions().find("cue")) {
  96. //audio CD-ROM fallback
  97. string result;
  98. result.append("game\n");
  99. result.append(" name: ", medium->name(manifest), "\n");
  100. result.append(" label: ", medium->name(manifest), "\n");
  101. return print(result);
  102. }
  103. return;
  104. }
  105. if(string import; arguments.take("--import", import)) {
  106. return (void)medium->import(import);
  107. }
  108. if(arguments.take("--import")) {
  109. if(auto import = BrowserDialog()
  110. .setTitle({"Import ", system, " Game"})
  111. .setPath(settings.recent)
  112. .setAlignment(Alignment::Center)
  113. .openFile()
  114. ) {
  115. if(auto error = medium->import(import)) {
  116. MessageDialog()
  117. .setTitle("Error")
  118. .setAlignment(Alignment::Center)
  119. .setText({"Failed to import: ", Location::file(import), "\n\nError: ", error, "."})
  120. .error();
  121. }
  122. }
  123. return;
  124. }
  125. }
  126. }
  127. Instances::programWindow.construct();
  128. #if defined(PLATFORM_MACOS)
  129. Application::Cocoa::onAbout([&] { programWindow.aboutAction.doActivate(); });
  130. Application::Cocoa::onPreferences([&] {});
  131. Application::Cocoa::onQuit([&] { Application::quit(); });
  132. #endif
  133. programWindow.setVisible();
  134. Application::run();
  135. directory::create({Path::userSettings(), "icarus/"});
  136. file::write({Path::userSettings(), "icarus/settings.bml"}, settings.serialize());
  137. Instances::programWindow.destruct();
  138. }
  139. }
  140. #if !defined(MIA_LIBRARY)
  141. #include <higan/resource/resource.cpp>
  142. #include <nall/main.hpp>
  143. auto nall::main(Arguments arguments) -> void {
  144. icarus::main(arguments);
  145. }
  146. #endif