2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
#include "NotesLoaderDWI.h"
|
|
|
|
|
#include "NotesLoader.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "RageException.h"
|
|
|
|
|
#include "MsdFile.h"
|
2002-09-07 11:43:36 +00:00
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "NoteData.h"
|
2002-09-06 23:24:40 +00:00
|
|
|
|
2002-09-07 07:49:15 +00:00
|
|
|
#include <map>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
void DWILoader::DWIcharToNote( char c, GameController i, DanceNote ¬e1Out, DanceNote ¬e2Out )
|
|
|
|
|
{
|
|
|
|
|
switch( c )
|
|
|
|
|
{
|
|
|
|
|
case '0': note1Out = DANCE_NOTE_NONE; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '1': note1Out = DANCE_NOTE_PAD1_DOWN; note2Out = DANCE_NOTE_PAD1_LEFT; break;
|
|
|
|
|
case '2': note1Out = DANCE_NOTE_PAD1_DOWN; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '3': note1Out = DANCE_NOTE_PAD1_DOWN; note2Out = DANCE_NOTE_PAD1_RIGHT; break;
|
|
|
|
|
case '4': note1Out = DANCE_NOTE_PAD1_LEFT; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '5': note1Out = DANCE_NOTE_NONE; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '6': note1Out = DANCE_NOTE_PAD1_RIGHT; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '7': note1Out = DANCE_NOTE_PAD1_UP; note2Out = DANCE_NOTE_PAD1_LEFT; break;
|
|
|
|
|
case '8': note1Out = DANCE_NOTE_PAD1_UP; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case '9': note1Out = DANCE_NOTE_PAD1_UP; note2Out = DANCE_NOTE_PAD1_RIGHT; break;
|
|
|
|
|
case 'A': note1Out = DANCE_NOTE_PAD1_UP; note2Out = DANCE_NOTE_PAD1_DOWN; break;
|
|
|
|
|
case 'B': note1Out = DANCE_NOTE_PAD1_LEFT; note2Out = DANCE_NOTE_PAD1_RIGHT; break;
|
|
|
|
|
case 'C': note1Out = DANCE_NOTE_PAD1_UPLEFT; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case 'D': note1Out = DANCE_NOTE_PAD1_UPRIGHT; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
case 'E': note1Out = DANCE_NOTE_PAD1_LEFT; note2Out = DANCE_NOTE_PAD1_UPLEFT; break;
|
|
|
|
|
case 'F': note1Out = DANCE_NOTE_PAD1_UPLEFT; note2Out = DANCE_NOTE_PAD1_DOWN; break;
|
|
|
|
|
case 'G': note1Out = DANCE_NOTE_PAD1_UPLEFT; note2Out = DANCE_NOTE_PAD1_UP; break;
|
|
|
|
|
case 'H': note1Out = DANCE_NOTE_PAD1_UPLEFT; note2Out = DANCE_NOTE_PAD1_RIGHT; break;
|
|
|
|
|
case 'I': note1Out = DANCE_NOTE_PAD1_LEFT; note2Out = DANCE_NOTE_PAD1_UPRIGHT; break;
|
|
|
|
|
case 'J': note1Out = DANCE_NOTE_PAD1_DOWN; note2Out = DANCE_NOTE_PAD1_UPRIGHT; break;
|
|
|
|
|
case 'K': note1Out = DANCE_NOTE_PAD1_UP; note2Out = DANCE_NOTE_PAD1_UPRIGHT; break;
|
|
|
|
|
case 'L': note1Out = DANCE_NOTE_PAD1_UPRIGHT; note2Out = DANCE_NOTE_PAD1_RIGHT; break;
|
|
|
|
|
case 'M': note1Out = DANCE_NOTE_PAD1_UPLEFT; note2Out = DANCE_NOTE_PAD1_UPRIGHT; break;
|
|
|
|
|
default:
|
2003-01-27 01:58:24 +00:00
|
|
|
LOG->Warn( "Encountered invalid DWI note character '%c'", c );
|
2002-09-06 23:24:40 +00:00
|
|
|
note1Out = DANCE_NOTE_NONE; note2Out = DANCE_NOTE_NONE; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch( i )
|
|
|
|
|
{
|
|
|
|
|
case GAME_CONTROLLER_1:
|
|
|
|
|
break;
|
|
|
|
|
case GAME_CONTROLLER_2:
|
|
|
|
|
if( note1Out != DANCE_NOTE_NONE )
|
|
|
|
|
note1Out += 6;
|
|
|
|
|
if( note2Out != DANCE_NOTE_NONE )
|
|
|
|
|
note2Out += 6;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT( false );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DWILoader::LoadFromDWITokens(
|
|
|
|
|
CString sMode,
|
|
|
|
|
CString sDescription,
|
|
|
|
|
CString sNumFeet,
|
|
|
|
|
CString sStepData1,
|
|
|
|
|
CString sStepData2,
|
2002-09-12 08:37:12 +00:00
|
|
|
Notes &out)
|
2002-09-06 23:24:40 +00:00
|
|
|
{
|
|
|
|
|
LOG->Trace( "Notes::LoadFromDWITokens()" );
|
|
|
|
|
|
2002-09-07 05:04:04 +00:00
|
|
|
out.m_NotesType = NOTES_TYPE_INVALID;
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
sStepData1.Replace( "\n", "" );
|
2003-06-07 14:12:47 +00:00
|
|
|
sStepData1.Replace( "\r", "" );
|
2002-09-06 23:24:40 +00:00
|
|
|
sStepData1.Replace( " ", "" );
|
|
|
|
|
sStepData2.Replace( "\n", "" );
|
2003-06-07 14:12:47 +00:00
|
|
|
sStepData2.Replace( "\r", "" );
|
2002-09-06 23:24:40 +00:00
|
|
|
sStepData2.Replace( " ", "" );
|
|
|
|
|
|
|
|
|
|
if( sMode == "SINGLE" ) out.m_NotesType = NOTES_TYPE_DANCE_SINGLE;
|
|
|
|
|
else if( sMode == "DOUBLE" ) out.m_NotesType = NOTES_TYPE_DANCE_DOUBLE;
|
2002-09-12 08:37:12 +00:00
|
|
|
else if( sMode == "COUPLE" ) out.m_NotesType = NOTES_TYPE_DANCE_COUPLE;
|
2002-09-06 23:24:40 +00:00
|
|
|
else if( sMode == "SOLO" ) out.m_NotesType = NOTES_TYPE_DANCE_SOLO;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ASSERT(0); // Unrecognized DWI notes format
|
|
|
|
|
out.m_NotesType = NOTES_TYPE_DANCE_SINGLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-09-07 07:49:15 +00:00
|
|
|
std::map<int,int> mapDanceNoteToNoteDataColumn;
|
2002-09-06 23:24:40 +00:00
|
|
|
switch( out.m_NotesType )
|
|
|
|
|
{
|
|
|
|
|
case NOTES_TYPE_DANCE_SINGLE:
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
|
|
|
|
break;
|
|
|
|
|
case NOTES_TYPE_DANCE_DOUBLE:
|
2002-09-12 08:37:12 +00:00
|
|
|
case NOTES_TYPE_DANCE_COUPLE:
|
2002-09-06 23:24:40 +00:00
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_LEFT] = 4;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7;
|
|
|
|
|
break;
|
|
|
|
|
case NOTES_TYPE_DANCE_SOLO:
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4;
|
|
|
|
|
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-21 22:23:01 +00:00
|
|
|
int iNumFeet = atoi(sNumFeet);
|
2003-01-02 22:10:51 +00:00
|
|
|
out.SetDescription(sDescription);
|
2003-01-21 22:23:01 +00:00
|
|
|
out.SetMeter(iNumFeet);
|
|
|
|
|
if( sDescription.CompareNoCase("basic")==0 ) out.SetDifficulty( DIFFICULTY_EASY );
|
|
|
|
|
else if( sDescription.CompareNoCase("trick")==0 ) out.SetDifficulty( DIFFICULTY_MEDIUM );
|
|
|
|
|
else if( sDescription.CompareNoCase("maniac")==0 ) out.SetDifficulty( DIFFICULTY_HARD );
|
|
|
|
|
else if( sDescription.CompareNoCase("smaniac")==0 ) out.SetDifficulty( DIFFICULTY_CHALLENGE );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
NoteData* pNoteData = new NoteData;
|
|
|
|
|
ASSERT( pNoteData );
|
2003-02-01 05:16:38 +00:00
|
|
|
pNoteData->SetNumTracks( mapDanceNoteToNoteDataColumn.size() );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
for( int pad=0; pad<2; pad++ ) // foreach pad
|
|
|
|
|
{
|
|
|
|
|
CString sStepData;
|
|
|
|
|
switch( pad )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
sStepData = sStepData1;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
if( sStepData2 == "" ) // no data
|
|
|
|
|
continue; // skip
|
|
|
|
|
sStepData = sStepData2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT( false );
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-27 01:58:24 +00:00
|
|
|
sStepData.Replace("\t", "");
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
double fCurrentBeat = 0;
|
|
|
|
|
double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
|
|
|
|
|
|
|
|
|
for( int i=0; i<sStepData.GetLength(); )
|
|
|
|
|
{
|
|
|
|
|
char c = sStepData[i++];
|
|
|
|
|
|
|
|
|
|
switch( c )
|
|
|
|
|
{
|
|
|
|
|
// begins a series
|
|
|
|
|
case '(':
|
|
|
|
|
fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
case '[':
|
|
|
|
|
fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
case '{':
|
|
|
|
|
fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
case '<':
|
|
|
|
|
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// ends a series
|
|
|
|
|
case ')':
|
|
|
|
|
case ']':
|
|
|
|
|
case '}':
|
|
|
|
|
case '>':
|
|
|
|
|
fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ' ':
|
|
|
|
|
break; // do nothing!
|
|
|
|
|
|
|
|
|
|
case '!': // hold start
|
|
|
|
|
{
|
|
|
|
|
// rewind and get the last step we inserted
|
|
|
|
|
double fLastStepBeat = fCurrentBeat - fCurrentIncrementer;
|
|
|
|
|
int iIndex = BeatToNoteRow( (float)fLastStepBeat );
|
|
|
|
|
|
|
|
|
|
char holdChar = sStepData[i++];
|
|
|
|
|
|
|
|
|
|
DanceNote note1, note2;
|
|
|
|
|
DWIcharToNote( holdChar, (GameController)pad, note1, note2 );
|
|
|
|
|
|
|
|
|
|
if( note1 != DANCE_NOTE_NONE )
|
|
|
|
|
{
|
|
|
|
|
int iCol1 = mapDanceNoteToNoteDataColumn[note1];
|
2002-10-25 04:59:26 +00:00
|
|
|
pNoteData->SetTapNote(iCol1, iIndex, TAP_HOLD_HEAD);
|
2002-09-06 23:24:40 +00:00
|
|
|
}
|
|
|
|
|
if( note2 != DANCE_NOTE_NONE )
|
|
|
|
|
{
|
|
|
|
|
int iCol2 = mapDanceNoteToNoteDataColumn[note2];
|
2002-10-25 04:59:26 +00:00
|
|
|
pNoteData->SetTapNote(iCol2, iIndex, TAP_HOLD_HEAD);
|
2002-09-06 23:24:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default: // this is a note character
|
|
|
|
|
{
|
|
|
|
|
int iIndex = BeatToNoteRow( (float)fCurrentBeat );
|
|
|
|
|
|
|
|
|
|
DanceNote note1, note2;
|
|
|
|
|
DWIcharToNote( c, (GameController)pad, note1, note2 );
|
|
|
|
|
|
|
|
|
|
if( note1 != DANCE_NOTE_NONE )
|
|
|
|
|
{
|
|
|
|
|
int iCol1 = mapDanceNoteToNoteDataColumn[note1];
|
2002-10-25 04:59:26 +00:00
|
|
|
pNoteData->SetTapNote(iCol1, iIndex, TAP_TAP);
|
2002-09-06 23:24:40 +00:00
|
|
|
}
|
|
|
|
|
if( note2 != DANCE_NOTE_NONE )
|
|
|
|
|
{
|
|
|
|
|
int iCol2 = mapDanceNoteToNoteDataColumn[note2];
|
2002-10-25 04:59:26 +00:00
|
|
|
pNoteData->SetTapNote(iCol2, iIndex, TAP_TAP);
|
2002-09-06 23:24:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fCurrentBeat += fCurrentIncrementer;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// this will expand the HoldNote begin markers we wrote into actual HoldNotes
|
|
|
|
|
pNoteData->Convert2sAnd3sToHoldNotes();
|
|
|
|
|
|
2003-02-01 05:16:38 +00:00
|
|
|
ASSERT( pNoteData->GetNumTracks() > 0 );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
2002-09-07 05:04:04 +00:00
|
|
|
out.SetNoteData(pNoteData);
|
|
|
|
|
|
|
|
|
|
delete pNoteData;
|
|
|
|
|
out.TidyUpData();
|
2002-09-06 23:24:40 +00:00
|
|
|
|
2002-09-07 05:04:04 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2002-09-06 23:24:40 +00:00
|
|
|
|
2002-12-27 21:39:25 +00:00
|
|
|
/* STUPID ALERT!
|
|
|
|
|
* This value can be in either "HH:MM:SS.sssss", "MM:SS.sssss", "SSS.sssss"
|
|
|
|
|
* or milliseconds.
|
|
|
|
|
* What's even more dumb is that the value can contain a ':'. Colon is supposed to be a parameter separator!
|
|
|
|
|
*/
|
2003-01-14 22:44:30 +00:00
|
|
|
float DWILoader::ParseBrokenDWITimestamp(const CString &arg1, const CString &arg2, const CString &arg3)
|
2002-12-27 21:39:25 +00:00
|
|
|
{
|
2003-01-14 22:44:30 +00:00
|
|
|
if(arg1.empty()) return 0;
|
|
|
|
|
|
|
|
|
|
/* 1+ args */
|
|
|
|
|
if(arg2.empty())
|
|
|
|
|
{
|
|
|
|
|
/* If the value contains a period, treat it as seconds; otherwise ms. */
|
|
|
|
|
if(arg1.find_first_of(".") != arg1.npos)
|
2003-04-25 00:01:35 +00:00
|
|
|
return (float)atof(arg1.c_str());
|
2003-01-14 22:44:30 +00:00
|
|
|
else
|
2003-04-25 00:01:35 +00:00
|
|
|
return float(atof(arg1.c_str())) / 1000.f;
|
2003-01-14 22:44:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2+ args */
|
|
|
|
|
if(arg3.empty())
|
|
|
|
|
return TimeToSeconds( arg1+":"+arg2 );
|
|
|
|
|
|
|
|
|
|
/* 3+ args */
|
|
|
|
|
return TimeToSeconds( arg1+":"+arg2+":"+arg3 );
|
2002-12-27 21:39:25 +00:00
|
|
|
}
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
bool DWILoader::LoadFromDWIFile( CString sPath, Song &out )
|
|
|
|
|
{
|
2003-04-25 00:01:35 +00:00
|
|
|
LOG->Trace( "Song::LoadFromDWIFile(%s)", sPath.c_str() );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
MsdFile msd;
|
|
|
|
|
bool bResult = msd.ReadFile( sPath );
|
|
|
|
|
if( !bResult )
|
2003-04-25 00:01:35 +00:00
|
|
|
RageException::Throw( "Error opening file '%s' for reading.", sPath.c_str() );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
2003-01-14 22:10:04 +00:00
|
|
|
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
2002-09-06 23:24:40 +00:00
|
|
|
{
|
2003-01-14 22:44:30 +00:00
|
|
|
int iNumParams = msd.GetNumParams(i);
|
|
|
|
|
const MsdFile::value_t &sParams = msd.GetValue(i);
|
2002-09-06 23:24:40 +00:00
|
|
|
CString sValueName = sParams[0];
|
|
|
|
|
|
2002-12-27 21:39:25 +00:00
|
|
|
if(iNumParams < 1)
|
|
|
|
|
{
|
2003-04-25 00:01:35 +00:00
|
|
|
LOG->Warn("Got \"%s\" tag with no parameters", sValueName.c_str());
|
2002-12-27 21:39:25 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
// handle the data
|
|
|
|
|
if( 0==stricmp(sValueName,"FILE") )
|
|
|
|
|
out.m_sMusicFile = sParams[1];
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"TITLE") )
|
2002-09-13 18:17:53 +00:00
|
|
|
GetMainAndSubTitlesFromFullTitle( sParams[1], out.m_sMainTitle, out.m_sSubTitle );
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"ARTIST") )
|
|
|
|
|
out.m_sArtist = sParams[1];
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"CDTITLE") )
|
|
|
|
|
out.m_sCDTitleFile = sParams[1];
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"BPM") )
|
|
|
|
|
out.AddBPMSegment( BPMSegment(0, (float)atof(sParams[1])) );
|
|
|
|
|
|
2003-05-23 01:14:43 +00:00
|
|
|
else if( 0==stricmp(sValueName,"DISPLAYBPM") )
|
|
|
|
|
{
|
|
|
|
|
// #DISPLAYBPM:[xxx..xxx]|[xxx]|[*];
|
|
|
|
|
if( sscanf( sParams[1], "%f..%f", &out.m_fDisplayBPMMin, &out.m_fDisplayBPMMax ) == 2 )
|
|
|
|
|
{
|
|
|
|
|
out.m_DisplayBPMType = Song::DISPLAY_SPECIFIED;
|
|
|
|
|
}
|
2003-06-12 20:14:40 +00:00
|
|
|
else if( sscanf( sParams[1], "%f", &out.m_fDisplayBPMMin ) == 1 )
|
2003-05-23 01:14:43 +00:00
|
|
|
{
|
|
|
|
|
out.m_DisplayBPMType = Song::DISPLAY_SPECIFIED;
|
|
|
|
|
out.m_fDisplayBPMMax = out.m_fDisplayBPMMin;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
out.m_DisplayBPMType = Song::DISPLAY_RANDOM;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 23:24:40 +00:00
|
|
|
else if( 0==stricmp(sValueName,"GAP") )
|
|
|
|
|
// the units of GAP is 1/1000 second
|
|
|
|
|
out.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f;
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"SAMPLESTART") )
|
2003-01-14 22:44:30 +00:00
|
|
|
out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]);
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"SAMPLELENGTH") )
|
2003-01-14 22:44:30 +00:00
|
|
|
out.m_fMusicSampleLengthSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]);
|
2002-09-06 23:24:40 +00:00
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"FREEZE") )
|
|
|
|
|
{
|
|
|
|
|
CStringArray arrayFreezeExpressions;
|
|
|
|
|
split( sParams[1], ",", arrayFreezeExpressions );
|
|
|
|
|
|
2002-10-31 03:16:02 +00:00
|
|
|
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
|
2002-09-06 23:24:40 +00:00
|
|
|
{
|
|
|
|
|
CStringArray arrayFreezeValues;
|
|
|
|
|
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
|
2002-10-08 07:55:14 +00:00
|
|
|
float fIndex = (float)atof( arrayFreezeValues[0] ) * ROWS_PER_BEAT / 4.0f;
|
2002-09-06 23:24:40 +00:00
|
|
|
float fFreezeBeat = NoteRowToBeat( fIndex );
|
|
|
|
|
float fFreezeSeconds = (float)atof( arrayFreezeValues[1] ) / 1000.0f;
|
|
|
|
|
|
|
|
|
|
out.AddStopSegment( StopSegment(fFreezeBeat, fFreezeSeconds) );
|
|
|
|
|
LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"CHANGEBPM") || 0==stricmp(sValueName,"BPMCHANGE") )
|
|
|
|
|
{
|
|
|
|
|
CStringArray arrayBPMChangeExpressions;
|
|
|
|
|
split( sParams[1], ",", arrayBPMChangeExpressions );
|
|
|
|
|
|
2002-10-31 03:16:02 +00:00
|
|
|
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
|
2002-09-06 23:24:40 +00:00
|
|
|
{
|
|
|
|
|
CStringArray arrayBPMChangeValues;
|
|
|
|
|
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
|
2002-10-31 03:16:02 +00:00
|
|
|
if(arrayBPMChangeValues.size() != 2) {
|
2003-04-25 00:01:35 +00:00
|
|
|
LOG->Warn( "Invalid CHANGEBPM: '%s'", arrayBPMChangeExpressions[b].c_str());
|
2002-09-08 22:02:01 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2002-10-08 07:55:14 +00:00
|
|
|
float fIndex = (float)atof( arrayBPMChangeValues[0] ) * ROWS_PER_BEAT / 4.0f;
|
2002-09-06 23:24:40 +00:00
|
|
|
float fBeat = NoteRowToBeat( fIndex );
|
|
|
|
|
float fNewBPM = (float)atof( arrayBPMChangeValues[1] );
|
|
|
|
|
|
|
|
|
|
out.AddBPMSegment( BPMSegment(fBeat, fNewBPM) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if( 0==stricmp(sValueName,"SINGLE") ||
|
|
|
|
|
0==stricmp(sValueName,"DOUBLE") ||
|
|
|
|
|
0==stricmp(sValueName,"COUPLE") ||
|
|
|
|
|
0==stricmp(sValueName,"SOLO"))
|
|
|
|
|
{
|
|
|
|
|
Notes* pNewNotes = new Notes;
|
|
|
|
|
LoadFromDWITokens(
|
|
|
|
|
sParams[0],
|
|
|
|
|
sParams[1],
|
|
|
|
|
sParams[2],
|
|
|
|
|
sParams[3],
|
|
|
|
|
(iNumParams==5) ? sParams[4] : "",
|
2002-09-12 08:37:12 +00:00
|
|
|
*pNewNotes
|
2002-09-06 23:24:40 +00:00
|
|
|
);
|
2002-09-07 05:04:04 +00:00
|
|
|
if(pNewNotes->m_NotesType != NOTES_TYPE_INVALID)
|
2002-10-31 04:23:39 +00:00
|
|
|
out.m_apNotes.push_back( pNewNotes );
|
2002-09-07 05:04:04 +00:00
|
|
|
else
|
|
|
|
|
delete pNewNotes;
|
2002-09-06 23:24:40 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
// do nothing. We don't care about this value name
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2002-09-11 05:15:46 +00:00
|
|
|
|
|
|
|
|
void DWILoader::GetApplicableFiles( CString sPath, CStringArray &out )
|
|
|
|
|
{
|
|
|
|
|
GetDirListing( sPath + CString("*.dwi"), out );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DWILoader::LoadFromDir( CString sPath, Song &out )
|
|
|
|
|
{
|
|
|
|
|
CStringArray aFileNames;
|
|
|
|
|
GetApplicableFiles( sPath, aFileNames );
|
|
|
|
|
|
2002-10-31 03:16:02 +00:00
|
|
|
if( aFileNames.size() > 1 )
|
2003-04-25 00:01:35 +00:00
|
|
|
RageException::Throw( "There is more than one DWI file in '%s'. There should be only one!", sPath.c_str() );
|
2002-09-11 05:15:46 +00:00
|
|
|
|
|
|
|
|
/* We should have exactly one; if we had none, we shouldn't have been
|
|
|
|
|
* called to begin with. */
|
2002-10-31 03:16:02 +00:00
|
|
|
ASSERT( aFileNames.size() == 1 );
|
2002-09-11 05:15:46 +00:00
|
|
|
|
|
|
|
|
return LoadFromDWIFile( sPath + aFileNames[0], out );
|
|
|
|
|
}
|
|
|
|
|
|