00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "MusicFlex.h"
00022 #include "XMidiFile.h"
00023 #include "IDataSource.h"
00024
00025 DEFINE_RUNTIME_CLASSTYPE_CODE(MusicFlex,Pentagram::Archive);
00026
00027
00028 MusicFlex::MusicFlex(IDataSource* ds) : Archive(ds)
00029 {
00030 songs = 0;
00031 std::memset(info,0, sizeof(SongInfo*)*128);
00032 loadSongInfo();
00033 }
00034
00035 MusicFlex::~MusicFlex()
00036 {
00037 uint32 i;
00038 for (i = 0; i < 128; i++)
00039 {
00040 delete info[i];
00041 info[i] = 0;
00042 }
00043
00044 Archive::uncache();
00045 delete [] songs;
00046 }
00047
00048 MusicFlex::SongInfo::SongInfo() : num_measures(0), loop_jump(0)
00049 {
00050 std::memset(filename,0,16);
00051 std::memset(transitions,0,128*sizeof(int*));
00052 }
00053
00054 MusicFlex::SongInfo::~SongInfo()
00055 {
00056 for (int i = 0; i < 128; i++)
00057 {
00058 delete [] transitions[i];
00059 transitions[i] = 0;
00060 }
00061 }
00062
00063 void MusicFlex::cache(uint32 index)
00064 {
00065 if (index >= count) return;
00066
00067 if (!songs)
00068 {
00069 songs = new XMidiFile * [count];
00070 std::memset(songs, 0, sizeof (XMidiFile *) * count);
00071 }
00072
00073 if (songs[index]) return;
00074
00075
00076 uint32 size;
00077 uint8 *buf = getRawObject(index, &size);
00078
00079 if (!buf || !size) return;
00080 IBufferDataSource ds(buf,size);
00081
00082 XMidiFile *x = new XMidiFile(&ds, XMIDIFILE_CONVERT_NOCONVERSION);
00083
00084 if (x->number_of_tracks())
00085 songs[index] = x;
00086 else
00087 delete x;
00088
00089 delete [] buf;
00090 }
00091
00092 void MusicFlex::uncache(uint32 index)
00093 {
00094 if (index >= count) return;
00095 if (!songs) return;
00096
00097 delete songs[index];
00098 songs[index] = 0;
00099 }
00100
00101 bool MusicFlex::isCached(uint32 index)
00102 {
00103 if (index >= count) return false;
00104 if (!songs) return false;
00105
00106 return (songs[index] != 0);
00107 }
00108
00109 IDataSource* MusicFlex::getAdlibTimbres()
00110 {
00111 uint32 size;
00112 uint8* data = getRawObject(259, &size);
00113 return new IBufferDataSource(data, size, false, true);
00114 }
00115
00116 void MusicFlex::loadSongInfo()
00117 {
00118 uint32 size;
00119 uint8 *buf = getRawObject(0, &size);
00120
00121 if (!buf || !size)
00122 {
00123 perr << "Unable to load song info from sound/music.flx. Exiting" << std::endl;
00124 std::exit(-1);
00125 }
00126 IBufferDataSource ds(buf,size);
00127 std::string line;
00128
00129
00130 for (;;)
00131 {
00132 ds.readline(line);
00133
00134
00135 if (line.at(0) == '#') break;
00136
00137 std::string::size_type begIdx, endIdx;
00138
00139
00140 begIdx = line.find_first_not_of(' ');
00141 endIdx = line.find_first_of(' ', begIdx);
00142 std::string name = line.substr(begIdx,endIdx-begIdx);
00143
00144
00145 begIdx = line.find_first_not_of(' ', endIdx);
00146 endIdx = line.find_first_of(' ', begIdx);
00147 int num = line.at(begIdx);
00148
00149
00150 begIdx = line.find_first_not_of(' ', endIdx);
00151 endIdx = line.find_first_of(' ', begIdx);
00152 int measures = std::atoi(line.substr(begIdx,endIdx-begIdx).c_str());
00153
00154
00155 begIdx = line.find_first_not_of(' ', endIdx);
00156 endIdx = line.find_first_of(' ', begIdx);
00157 int loop_jump = std::atoi(line.substr(begIdx,endIdx-begIdx).c_str());
00158
00159
00160 if (num < 0 || num > 127)
00161 {
00162 perr << "Invalid Section 1 song info data. num out of range. Exiting." << std::endl;
00163 std::exit(-1);
00164 }
00165
00166 if (info[num])
00167 {
00168 perr << "Invalid Section 1 song info data. num already defined. Exiting." << std::endl;
00169 std::exit(-1);
00170 }
00171
00172 info[num] = new SongInfo();
00173
00174 std::strncpy(info[num]->filename, name.c_str(), 16);
00175 info[num]->num_measures = measures;
00176 info[num]->loop_jump = loop_jump;
00177 };
00178
00179
00180
00181 for (;;)
00182 {
00183 ds.readline(line);
00184
00185
00186 if (line.at(0) == '#') break;
00187 }
00188
00189
00190 for (;;)
00191 {
00192 ds.readline(line);
00193
00194
00195 if (line.at(0) == '#') break;
00196 }
00197
00198
00199 for (;;)
00200 {
00201 ds.readline(line);
00202
00203
00204 if (line.at(0) == '#') break;
00205
00206 std::string::size_type begIdx, endIdx;
00207
00208
00209 begIdx = line.find_first_not_of(' ');
00210 endIdx = line.find_first_of(' ', begIdx);
00211 std::string from = line.substr(begIdx,endIdx-begIdx);
00212
00213
00214 begIdx = line.find_first_not_of(' ', endIdx);
00215 endIdx = line.find_first_of(' ', begIdx);
00216 std::string to = line.substr(begIdx,endIdx-begIdx);
00217
00218
00219 int fi;
00220 for (fi = 0; fi < 128; fi++)
00221 {
00222 if (info[fi] && from == info[fi]->filename) break;
00223 }
00224
00225 if (fi == 128)
00226 {
00227 perr << "Invalid Section 4 song info data. Unable to find 'from' index (" << from << "). Exiting." << std::endl;
00228 std::exit(-1);
00229 }
00230
00231
00232 int ti;
00233 for (ti= 0; ti < 128; ti++)
00234 {
00235 if (info[ti] && to == info[ti]->filename) break;
00236 }
00237
00238 if (ti == 128)
00239 {
00240 perr << "Invalid Section 4 song info data. Unable to find 'to' index (" << to << "). Exiting." << std::endl;
00241 std::exit(-1);
00242 }
00243
00244
00245 info[fi]->transitions[ti] = new int[info[fi]->num_measures];
00246
00247
00248 for (int m = 0; m < info[fi]->num_measures; m++)
00249 {
00250
00251 begIdx = line.find_first_not_of(' ', endIdx);
00252 endIdx = line.find_first_of(' ', begIdx);
00253
00254 if (begIdx == std::string::npos)
00255 {
00256 perr << "Invalid Section 4 song info data. Unable to read transitions for all measures. Exiting." << std::endl;
00257 std::exit(-1);
00258 }
00259
00260 std::string trans = line.substr(begIdx,endIdx-begIdx);
00261 const char *str = trans.c_str();
00262
00263 int num = 0;
00264
00265
00266 if (*str == '!')
00267 num = -1-atoi(str+1);
00268 else
00269 num = atoi(str+1);
00270
00271 info[fi]->transitions[ti][m] = num;
00272 }
00273 }
00274
00275
00276
00277 delete[] buf;
00278 }
00279