AutoGen now will fill in all missing NotesTypes. The patterns generated by AutoGen are now more intelligent. Fixed crash in MsdFile.
This commit is contained in:
+15
-18
@@ -11,6 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MsdFile.h"
|
#include "MsdFile.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "fcntl.h"
|
||||||
|
|
||||||
|
|
||||||
MsdFile::MsdFile()
|
MsdFile::MsdFile()
|
||||||
@@ -25,19 +27,15 @@ MsdFile::~MsdFile()
|
|||||||
//returns true if successful, false otherwise
|
//returns true if successful, false otherwise
|
||||||
bool MsdFile::ReadFile( CString sNewPath )
|
bool MsdFile::ReadFile( CString sNewPath )
|
||||||
{
|
{
|
||||||
// Get file size in bytes
|
int fh;
|
||||||
HANDLE hFile = CreateFile(
|
|
||||||
sNewPath, // pointer to name of the file
|
/* Open a file */
|
||||||
GENERIC_READ, // access (read-write) mode
|
if( (fh = _open(sNewPath, _O_RDONLY, 0)) == -1 )
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
|
return false;
|
||||||
NULL, // pointer to security attributes
|
|
||||||
OPEN_EXISTING, // how to create
|
int iBufferSize = _filelength( fh ) + 1000; // +1000 because sometimes the bytes read is > filelength. Why?
|
||||||
FILE_ATTRIBUTE_NORMAL, // file attributes
|
_close( fh );
|
||||||
NULL // handle to file with attributes to
|
|
||||||
);
|
|
||||||
|
|
||||||
int iBufferSize = GetFileSize( hFile, NULL ) + 1000; // +1000 just in case
|
|
||||||
CloseHandle( hFile );
|
|
||||||
|
|
||||||
FILE* fp = fopen(sNewPath, "r");
|
FILE* fp = fopen(sNewPath, "r");
|
||||||
if( fp == NULL )
|
if( fp == NULL )
|
||||||
@@ -45,13 +43,13 @@ bool MsdFile::ReadFile( CString sNewPath )
|
|||||||
|
|
||||||
// allocate a string to hold the file
|
// allocate a string to hold the file
|
||||||
char* szFileString = new char[iBufferSize];
|
char* szFileString = new char[iBufferSize];
|
||||||
char* szParams[MAX_VALUES][MAX_PARAMS_PER_VALUE];
|
ASSERT( szFileString );
|
||||||
|
|
||||||
int iBytesRead = fread( szFileString, 1, iBufferSize, fp );
|
int iBytesRead = fread( szFileString, 1, iBufferSize, fp );
|
||||||
|
|
||||||
ASSERT( iBufferSize > iBytesRead );
|
ASSERT( iBufferSize > iBytesRead );
|
||||||
/* why are we using Windows API calls for simple file access, anyway? XXX -glenn */
|
szFileString[iBytesRead] = '\0';
|
||||||
/* What is the C way to get the file size? I don't see 'fstat' in C library... -Chris */
|
|
||||||
|
char* szParams[MAX_VALUES][MAX_PARAMS_PER_VALUE];
|
||||||
|
|
||||||
m_iNumValues = 0;
|
m_iNumValues = 0;
|
||||||
|
|
||||||
@@ -90,6 +88,7 @@ bool MsdFile::ReadFile( CString sNewPath )
|
|||||||
|
|
||||||
ReadingValue=true;
|
ReadingValue=true;
|
||||||
m_iNumValues++;
|
m_iNumValues++;
|
||||||
|
ASSERT( m_iNumValues < MAX_VALUES );
|
||||||
int iCurValueIndex = m_iNumValues-1;
|
int iCurValueIndex = m_iNumValues-1;
|
||||||
m_iNumParams[iCurValueIndex] = 1;
|
m_iNumParams[iCurValueIndex] = 1;
|
||||||
szParams[iCurValueIndex][0] = &szFileString[i+1];
|
szParams[iCurValueIndex][0] = &szFileString[i+1];
|
||||||
@@ -131,8 +130,6 @@ bool MsdFile::ReadFile( CString sNewPath )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
szFileString[i] = '\0';
|
|
||||||
|
|
||||||
for( i=0; i<m_iNumValues; i++ )
|
for( i=0; i<m_iNumValues; i++ )
|
||||||
{
|
{
|
||||||
for( int j=0; j<m_iNumParams[i]; j++ )
|
for( int j=0; j<m_iNumParams[i]; j++ )
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
const int MAX_VALUES = 50;
|
const int MAX_VALUES = 200;
|
||||||
const int MAX_PARAMS_PER_VALUE = 10;
|
const int MAX_PARAMS_PER_VALUE = 10;
|
||||||
|
|
||||||
class MsdFile
|
class MsdFile
|
||||||
|
|||||||
@@ -184,9 +184,15 @@ void NoteData::AddHoldNote( HoldNote add )
|
|||||||
for( i=0; i<m_iNumHoldNotes; i++ ) // for each HoldNote
|
for( i=0; i<m_iNumHoldNotes; i++ ) // for each HoldNote
|
||||||
{
|
{
|
||||||
HoldNote &other = m_HoldNotes[i];
|
HoldNote &other = m_HoldNotes[i];
|
||||||
if( add.m_iTrack == other.m_iTrack && // the notes correspond
|
if( add.m_iTrack == other.m_iTrack && // the tracks correspond
|
||||||
other.m_fStartBeat <= add.m_fEndBeat &&
|
// they overlap
|
||||||
other.m_fEndBeat >= add.m_fStartBeat ) // these HoldNotes overlap (this isn't entirely correct!)
|
(
|
||||||
|
( other.m_fStartBeat <= add.m_fStartBeat && other.m_fEndBeat >= add.m_fEndBeat ) || // other consumes add
|
||||||
|
( other.m_fStartBeat >= add.m_fStartBeat && other.m_fEndBeat <= add.m_fEndBeat ) || // other inside add
|
||||||
|
( add.m_fStartBeat <= other.m_fStartBeat && other.m_fStartBeat <= add.m_fEndBeat ) || // other overlaps add
|
||||||
|
( add.m_fStartBeat <= other.m_fEndBeat && other.m_fEndBeat <= add.m_fEndBeat ) // other overlaps add
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
add.m_fStartBeat = min(add.m_fStartBeat, other.m_fStartBeat);
|
add.m_fStartBeat = min(add.m_fStartBeat, other.m_fStartBeat);
|
||||||
add.m_fEndBeat = max(add.m_fEndBeat, other.m_fEndBeat);
|
add.m_fEndBeat = max(add.m_fEndBeat, other.m_fEndBeat);
|
||||||
@@ -854,6 +860,63 @@ void NoteData::LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const in
|
|||||||
Convert4sToHoldNotes();
|
Convert4sToHoldNotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoteData::LoadTransformedSlidingWindow( NoteData* pOriginal, int iNewNumTracks )
|
||||||
|
{
|
||||||
|
pOriginal->ConvertHoldNotesTo4s();
|
||||||
|
m_iNumTracks = iNewNumTracks;
|
||||||
|
|
||||||
|
int iLastRow = pOriginal->GetLastRow();
|
||||||
|
for( int r=0; r<=iLastRow; r++ )
|
||||||
|
{
|
||||||
|
int iMeasure = (int)(NoteRowToBeat(r) / BEATS_PER_MEASURE);
|
||||||
|
|
||||||
|
for( int t=0; t<=pOriginal->m_iNumTracks; t++ )
|
||||||
|
{
|
||||||
|
int iOldTrack = t;
|
||||||
|
int iNewTrack = (iOldTrack + iMeasure/4) % iNewNumTracks; // change sliding window every 4 measures
|
||||||
|
|
||||||
|
if( pOriginal->m_TapNotes[iOldTrack][r] != '0' )
|
||||||
|
this->m_TapNotes[iNewTrack][r] = pOriginal->m_TapNotes[iOldTrack][r];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pOriginal->Convert4sToHoldNotes();
|
||||||
|
Convert4sToHoldNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoteData::LoadTransformedMirrorOnCross( NoteData* pOriginal, int iNewNumTracks )
|
||||||
|
{
|
||||||
|
ASSERT( iNewNumTracks == pOriginal->m_iNumTracks*2 );
|
||||||
|
|
||||||
|
m_iNumTracks = iNewNumTracks;
|
||||||
|
|
||||||
|
pOriginal->ConvertHoldNotesTo4s();
|
||||||
|
|
||||||
|
bool bMirror = false;
|
||||||
|
int iMirrorTrack = pOriginal->m_iNumTracks/2-1;
|
||||||
|
|
||||||
|
int iLastRow = pOriginal->GetLastRow();
|
||||||
|
for( int r=0; r<=iLastRow; r++ )
|
||||||
|
{
|
||||||
|
for( int t=0; t<=pOriginal->m_iNumTracks; t++ )
|
||||||
|
{
|
||||||
|
int iOldTrack = t;
|
||||||
|
int iNewTrack = bMirror ? m_iNumTracks - iOldTrack : iOldTrack;
|
||||||
|
|
||||||
|
if( pOriginal->m_TapNotes[iOldTrack][r] != '0' )
|
||||||
|
{
|
||||||
|
this->m_TapNotes[iNewTrack][r] = pOriginal->m_TapNotes[iOldTrack][r];
|
||||||
|
|
||||||
|
if( iOldTrack == iMirrorTrack )
|
||||||
|
bMirror ^= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pOriginal->Convert4sToHoldNotes();
|
||||||
|
Convert4sToHoldNotes();
|
||||||
|
}
|
||||||
|
|
||||||
NoteType NoteData::GetSmallestNoteTypeForMeasure( int iMeasureIndex )
|
NoteType NoteData::GetSmallestNoteTypeForMeasure( int iMeasureIndex )
|
||||||
{
|
{
|
||||||
const int iMeasureStartIndex = iMeasureIndex * ROWS_PER_MEASURE;
|
const int iMeasureStartIndex = iMeasureIndex * ROWS_PER_MEASURE;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
// ... for future expansion
|
// ... for future expansion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NoteData
|
class NoteData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -58,6 +57,7 @@ public:
|
|||||||
|
|
||||||
// statistics
|
// statistics
|
||||||
bool IsThereANoteAtRow( int iRow );
|
bool IsThereANoteAtRow( int iRow );
|
||||||
|
|
||||||
float GetFirstBeat(); // return the beat number of the first note
|
float GetFirstBeat(); // return the beat number of the first note
|
||||||
int GetFirstRow();
|
int GetFirstRow();
|
||||||
float GetLastBeat(); // return the beat number of the last note
|
float GetLastBeat(); // return the beat number of the last note
|
||||||
@@ -89,6 +89,9 @@ public:
|
|||||||
|
|
||||||
// Transformations
|
// Transformations
|
||||||
void LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const int iOriginalTrackToTakeFrom[] ); // -1 for iOriginalTracksToTakeFrom means no track
|
void LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const int iOriginalTrackToTakeFrom[] ); // -1 for iOriginalTracksToTakeFrom means no track
|
||||||
|
void LoadTransformedSlidingWindow( NoteData* pOriginal, int iNewNumTracks ); // useful for autogenerating DDR->Pump, Pump->DDR
|
||||||
|
void LoadTransformedMirrorOnCross( NoteData* pOriginal, int iNewNumTracks ); // useful for autogenerating double patterns
|
||||||
|
|
||||||
|
|
||||||
void CropToLeftSide();
|
void CropToLeftSide();
|
||||||
void CropToRightSide();
|
void CropToRightSide();
|
||||||
|
|||||||
@@ -903,7 +903,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
|
|||||||
case DIK_P:
|
case DIK_P:
|
||||||
{
|
{
|
||||||
if( m_NoteFieldEdit.m_fBeginMarker == -1 )
|
if( m_NoteFieldEdit.m_fBeginMarker == -1 )
|
||||||
m_NoteFieldEdit.m_fBeginMarker = m_pSong->m_fFirstBeat;
|
m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat;
|
||||||
if( m_NoteFieldEdit.m_fEndMarker == -1 )
|
if( m_NoteFieldEdit.m_fEndMarker == -1 )
|
||||||
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
|
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
|
||||||
|
|
||||||
@@ -924,7 +924,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
|
|||||||
case DIK_R:
|
case DIK_R:
|
||||||
{
|
{
|
||||||
if( m_NoteFieldEdit.m_fBeginMarker == -1 )
|
if( m_NoteFieldEdit.m_fBeginMarker == -1 )
|
||||||
m_NoteFieldEdit.m_fBeginMarker = m_pSong->m_fFirstBeat;
|
m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat;
|
||||||
if( m_NoteFieldEdit.m_fEndMarker == -1 )
|
if( m_NoteFieldEdit.m_fEndMarker == -1 )
|
||||||
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
|
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
|
||||||
|
|
||||||
|
|||||||
+28
-23
@@ -33,7 +33,7 @@
|
|||||||
#include "NotesLoaderKSF.h"
|
#include "NotesLoaderKSF.h"
|
||||||
#include "NotesWriterDWI.h"
|
#include "NotesWriterDWI.h"
|
||||||
|
|
||||||
const int FILE_CACHE_VERSION = 73; // increment this when Song or Notes changes to invalidate cache
|
const int FILE_CACHE_VERSION = 92; // increment this when Song or Notes changes to invalidate cache
|
||||||
|
|
||||||
|
|
||||||
int CompareBPMSegments(const void *arg1, const void *arg2)
|
int CompareBPMSegments(const void *arg1, const void *arg2)
|
||||||
@@ -714,48 +714,53 @@ void Song::SaveToDWIFile()
|
|||||||
wr.Write(sPath, *this);
|
wr.Write(sPath, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AutoGenMapping
|
|
||||||
{
|
|
||||||
NotesType ntMissing;
|
|
||||||
NotesType ntGenerateFrom;
|
|
||||||
int iOriginalTrackToTakeFrom[MAX_NOTE_TRACKS];
|
|
||||||
};
|
|
||||||
const AutoGenMapping AUTO_GEN_MAPPINGS[] = {
|
|
||||||
{ NOTES_TYPE_PUMP_SINGLE, NOTES_TYPE_DANCE_SINGLE, { 0, 1, -1, 2, 3 } },
|
|
||||||
{ NOTES_TYPE_DANCE_SINGLE, NOTES_TYPE_PUMP_SINGLE, { 0, 1, 3, 4 } },
|
|
||||||
{ NOTES_TYPE_PUMP_DOUBLE, NOTES_TYPE_DANCE_DOUBLE, { 0, 1, -1, 2, 3, 4, 5, -1, 6, 7 } },
|
|
||||||
{ NOTES_TYPE_DANCE_DOUBLE, NOTES_TYPE_PUMP_DOUBLE, { 0, 1, 3, 4, 5, 6, 8, 9 } },
|
|
||||||
};
|
|
||||||
const NUM_AUTOGEN_MAPPINGS = sizeof(AUTO_GEN_MAPPINGS) / sizeof(AutoGenMapping);
|
|
||||||
|
|
||||||
void Song::AddAutoGenNotes()
|
void Song::AddAutoGenNotes()
|
||||||
{
|
{
|
||||||
for( int i=0; i<NUM_AUTOGEN_MAPPINGS; i++ )
|
for( NotesType ntMissing=(NotesType)0; ntMissing<NUM_NOTES_TYPES; ntMissing=(NotesType)(ntMissing+1) )
|
||||||
{
|
{
|
||||||
const AutoGenMapping& mapping = AUTO_GEN_MAPPINGS[i];
|
if( !SongHasNotesType(ntMissing) ) // missing Notes of this type
|
||||||
|
{
|
||||||
|
int iNumTracksOfMissing = GAMEMAN->NotesTypeToNumTracks(ntMissing);
|
||||||
|
|
||||||
if( !SongHasNotesType(mapping.ntMissing))
|
// look for closest match
|
||||||
|
NotesType ntBestMatch = (NotesType)-1;
|
||||||
|
int iBestTrackDifference = 10000; // inf
|
||||||
|
|
||||||
|
for( NotesType nt=(NotesType)0; nt<NUM_NOTES_TYPES; nt=(NotesType)(nt+1) )
|
||||||
{
|
{
|
||||||
for( int i=0; i<m_apNotes.GetSize(); i++ )
|
int iNumTracks = GAMEMAN->NotesTypeToNumTracks(nt);
|
||||||
|
int iTrackDifference = abs(iNumTracks-iNumTracksOfMissing);
|
||||||
|
if( SongHasNotesType(nt) && iTrackDifference<iBestTrackDifference )
|
||||||
{
|
{
|
||||||
Notes* pOriginalNotes = m_apNotes[i];
|
ntBestMatch = nt;
|
||||||
if( pOriginalNotes->m_NotesType != mapping.ntGenerateFrom )
|
iBestTrackDifference = iTrackDifference;
|
||||||
continue;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ntBestMatch != -1 )
|
||||||
|
{
|
||||||
|
for( int j=0; j<m_apNotes.GetSize(); j++ )
|
||||||
|
{
|
||||||
|
Notes* pOriginalNotes = m_apNotes[j];
|
||||||
|
if( pOriginalNotes->m_NotesType != ntBestMatch )
|
||||||
|
continue; // skip
|
||||||
|
|
||||||
Notes* pNewNotes = new Notes;
|
Notes* pNewNotes = new Notes;
|
||||||
pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty;
|
pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty;
|
||||||
pNewNotes->m_iMeter = pOriginalNotes->m_iMeter;
|
pNewNotes->m_iMeter = pOriginalNotes->m_iMeter;
|
||||||
pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)";
|
pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)";
|
||||||
pNewNotes->m_NotesType = mapping.ntMissing;
|
pNewNotes->m_NotesType = ntMissing;
|
||||||
|
|
||||||
NoteData originalNoteData, newNoteData;
|
NoteData originalNoteData, newNoteData;
|
||||||
pOriginalNotes->GetNoteData( &originalNoteData );
|
pOriginalNotes->GetNoteData( &originalNoteData );
|
||||||
newNoteData.LoadTransformed( &originalNoteData, GAMEMAN->NotesTypeToNumTracks(mapping.ntMissing), mapping.iOriginalTrackToTakeFrom );
|
newNoteData.LoadTransformedSlidingWindow( &originalNoteData, iNumTracksOfMissing );
|
||||||
pNewNotes->SetNoteData( &newNoteData );
|
pNewNotes->SetNoteData( &newNoteData );
|
||||||
this->m_apNotes.Add( pNewNotes );
|
this->m_apNotes.Add( pNewNotes );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) const
|
Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) const
|
||||||
|
|||||||
Reference in New Issue
Block a user