compact-disc.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include "mega-cd.cpp"
  2. #include "pc-engine-cd.cpp"
  3. #include "playstation.cpp"
  4. auto CompactDisc::construct() -> void {
  5. Media::construct();
  6. }
  7. auto CompactDisc::manifest(string location) -> string {
  8. vector<uint8_t> sector;
  9. if(directory::exists(location)) sector = readDataSectorBCD(location, manifestSector());
  10. if(file::exists(location)) sector = readDataSectorCUE(location, manifestSector());
  11. if(sector) return manifest(sector, location);
  12. return {};
  13. }
  14. auto CompactDisc::import(string filename) -> string {
  15. string location = {pathname, Location::prefix(filename), "/"};
  16. if(!directory::create(location)) return "output directory not writable";
  17. auto cdrom = vfs::cdrom::open(filename);
  18. if(!cdrom) return "failed to parse CUE sheet";
  19. if(auto fp = file::open({location, "cd.rom"}, file::mode::write)) {
  20. while(!cdrom->end()) fp.write(cdrom->read());
  21. }
  22. return {};
  23. }
  24. auto CompactDisc::readDataSectorBCD(string pathname, uint sectorID) -> vector<uint8_t> {
  25. auto fp = file::open({pathname, "cd.rom"}, file::mode::read);
  26. if(!fp) return {};
  27. vector<uint8_t> toc;
  28. toc.resize(96 * 7500);
  29. for(uint sector : range(7500)) {
  30. fp.read({toc.data() + 96 * sector, 96});
  31. }
  32. CD::Session session;
  33. session.decode(toc, 96);
  34. for(uint trackID : range(100)) {
  35. if(auto& track = session.tracks[trackID]) {
  36. if(!track.isData()) continue;
  37. if(auto index = track.index(1)) {
  38. vector<uint8_t> sector;
  39. sector.resize(2048);
  40. fp.seek(2448 * (abs(session.leadIn.lba) + index->lba + sectorID) + 16);
  41. fp.read({sector.data(), 2448});
  42. return sector;
  43. }
  44. }
  45. }
  46. return {};
  47. }
  48. auto CompactDisc::readDataSectorCUE(string filename, uint sectorID) -> vector<uint8_t> {
  49. Decode::CUE cuesheet;
  50. if(!cuesheet.load(filename)) return {};
  51. for(auto& file : cuesheet.files) {
  52. uint64_t offset = 0;
  53. auto location = string{Location::path(filename), file.name};
  54. if(file.type == "binary") {
  55. auto binary = file::open(location, nall::file::mode::read);
  56. if(!binary) continue;
  57. for(auto& track : file.tracks) {
  58. for(auto& index : track.indices) {
  59. uint sectorSize = 0;
  60. if(track.type == "mode1/2048") sectorSize = 2048;
  61. if(track.type == "mode1/2352") sectorSize = 2352;
  62. if(track.type == "mode2/2352") sectorSize = 2352;
  63. if(sectorSize && index.number == 1) {
  64. binary.seek(offset + (sectorSize * sectorID) + (sectorSize == 2352 ? 16 : 0));
  65. vector<uint8_t> sector;
  66. sector.resize(2048);
  67. binary.read({sector.data(), sector.size()});
  68. return sector;
  69. }
  70. offset += track.sectorSize() * index.sectorCount();
  71. }
  72. }
  73. }
  74. if(file.type == "wave") {
  75. Decode::WAV wave;
  76. if(!wave.open(location)) continue;
  77. offset += wave.headerSize;
  78. for(auto& track : file.tracks) {
  79. auto length = track.sectorSize();
  80. for(auto& index : track.indices) {
  81. offset += track.sectorSize() * index.sectorCount();
  82. }
  83. }
  84. }
  85. }
  86. return {};
  87. }