File: medium.cpp

package info (click to toggle)
ares 126-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 32,600 kB
  • sloc: cpp: 356,508; ansic: 20,394; makefile: 16; sh: 2
file content (188 lines) | stat: -rw-r--r-- 6,279 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
namespace Media {
  vector<Database> databases;
  #include "colecovision.cpp"
  #include "famicom.cpp"
  #include "famicom-disk.cpp"
  #include "game-boy.cpp"
  #include "game-boy-color.cpp"
  #include "game-boy-advance.cpp"
  #include "master-system.cpp"
  #include "game-gear.cpp"
  #include "mega-drive.cpp"
  #include "mega-32x.cpp"
  #include "mega-cd.cpp"
  #include "msx.cpp"
  #include "msx2.cpp"
  #include "neo-geo.cpp"
  #include "neo-geo-pocket.cpp"
  #include "neo-geo-pocket-color.cpp"
  #include "nintendo-64.cpp"
  #include "nintendo-64dd.cpp"
  #include "pc-engine.cpp"
  #include "pc-engine-cd.cpp"
  #include "saturn.cpp"
  #include "supergrafx.cpp"
  #include "playstation.cpp"
  #include "sg-1000.cpp"
  #include "sc-3000.cpp"
  #include "super-famicom.cpp"
  #include "bs-memory.cpp"
  #include "sufami-turbo.cpp"
  #include "wonderswan.cpp"
  #include "wonderswan-color.cpp"
  #include "pocket-challenge-v2.cpp"
}

//auto Medium::construct() -> void {
//  database = BML::unserialize(file::read(locate({"Database/", name(), ".bml"})));
//  pathname = {Path::user(), "Emulation/", name(), "/"};
//}

auto Medium::create(string name) -> shared_pointer<Pak> {
  if(name == "ColecoVision") return new Media::ColecoVision;
  if(name == "Famicom") return new Media::Famicom;
  if(name == "Famicom Disk") return new Media::FamicomDisk;
  if(name == "Game Boy") return new Media::GameBoy;
  if(name == "Game Boy Color") return new Media::GameBoyColor;
  if(name == "Game Boy Advance") return new Media::GameBoyAdvance;
  if(name == "Master System") return new Media::MasterSystem;
  if(name == "Game Gear") return new Media::GameGear;
  if(name == "Mega Drive") return new Media::MegaDrive;
  if(name == "Mega 32X") return new Media::Mega32X;
  if(name == "Mega CD") return new Media::MegaCD;
  if(name == "MSX") return new Media::MSX;
  if(name == "MSX2") return new Media::MSX2;
  if(name == "Neo Geo") return new Media::NeoGeo;
  if(name == "Neo Geo Pocket") return new Media::NeoGeoPocket;
  if(name == "Neo Geo Pocket Color") return new Media::NeoGeoPocketColor;
  if(name == "Nintendo 64") return new Media::Nintendo64;
  if(name == "Nintendo 64DD") return new Media::Nintendo64DD;
  if(name == "PC Engine") return new Media::PCEngine;
  if(name == "PC Engine CD") return new Media::PCEngineCD;
  if(name == "Saturn") return new Media::Saturn;
  if(name == "SuperGrafx") return new Media::SuperGrafx;
  if(name == "PlayStation") return new Media::PlayStation;
  if(name == "SG-1000") return new Media::SG1000;
  if(name == "SC-3000") return new Media::SC3000;
  if(name == "Super Famicom") return new Media::SuperFamicom;
  if(name == "BS Memory") return new Media::BSMemory;
  if(name == "Sufami Turbo") return new Media::SufamiTurbo;
  if(name == "WonderSwan") return new Media::WonderSwan;
  if(name == "WonderSwan Color") return new Media::WonderSwanColor;
  if(name == "Pocket Challenge V2") return new Media::PocketChallengeV2;
  return {};
}

//search game database for manifest, if one exists
auto Medium::manifestDatabase(string sha256) -> string {
  //load the database on the first time it's needed for a given media type
  bool found = false;
  for(auto& database : Media::databases) {
    if(database.name == name()) found = true;
  }
  if(!found) {
    Database database;
    database.name = name();
    database.list = BML::unserialize(file::read(locate({"Database/", name(), ".bml"})));
    Media::databases.append(move(database));
  }

  //search the database for a given sha256 game entry
  for(auto& database : Media::databases) {
    if(database.name == name()) {
      for(auto node : database.list) {
        if(node["sha256"].string() == sha256) {
          return BML::serialize(node);
        }
      }
    }
  }

  //database or game entry not found
  return {};
}

//

//audio CD fallback
auto CompactDisc::manifestAudio(string location) -> string {
  string manifest;
  manifest += "game\n";
  manifest +={"  name:  ", Medium::name(location), "\n"};
  manifest +={"  title: ", Medium::name(location), "\n"};
  manifest += "  audio\n";
  return manifest;
}

auto CompactDisc::readDataSectorBCD(string pathname, u32 sectorID) -> vector<u8> {
  auto fp = file::open({pathname, "cd.rom"}, file::mode::read);
  if(!fp) return {};

  vector<u8> toc;
  toc.resize(96 * 7500);
  for(u32 sector : range(7500)) {
    fp.read({toc.data() + 96 * sector, 96});
  }
  CD::Session session;
  session.decode(toc, 96);

  for(u32 trackID : range(100)) {
    if(auto& track = session.tracks[trackID]) {
      if(!track.isData()) continue;
      if(auto index = track.index(1)) {
        vector<u8> sector;
        sector.resize(2448);
        fp.seek(2448 * (abs(session.leadIn.lba) + index->lba + sectorID) + 16);
        fp.read({sector.data(), 2448});
        return sector;
      }
    }
  }

  return {};
}

auto CompactDisc::readDataSectorCUE(string filename, u32 sectorID) -> vector<u8> {
  Decode::CUE cuesheet;
  if(!cuesheet.load(filename)) return {};

  for(auto& file : cuesheet.files) {
    u64 offset = 0;
    auto location = string{Location::path(filename), file.name};

    if(file.type == "binary") {
      auto binary = file::open(location, nall::file::mode::read);
      if(!binary) continue;
      for(auto& track : file.tracks) {
        for(auto& index : track.indices) {
          u32 sectorSize = 0;
          if(track.type == "mode1/2048") sectorSize = 2048;
          if(track.type == "mode1/2352") sectorSize = 2352;
          if(track.type == "mode2/2352") sectorSize = 2352;
          if(sectorSize && index.number == 1) {
            binary.seek(offset + (sectorSize * sectorID) + (sectorSize == 2352 ? 16 : 0));
            vector<u8> sector;
            sector.resize(2048);
            binary.read({sector.data(), sector.size()});
            return sector;
          }
          offset += track.sectorSize() * index.sectorCount();
        }
      }
    }

    if(file.type == "wave") {
      Decode::WAV wave;
      if(!wave.open(location)) continue;
      offset += wave.headerSize;
      for(auto& track : file.tracks) {
        auto length = track.sectorSize();
        for(auto& index : track.indices) {
          offset += track.sectorSize() * index.sectorCount();
        }
      }
    }
  }

  return {};
}