compact-disc.cpp 3.0 KB

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