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:
Chris Danford
2002-10-05 14:47:03 +00:00
parent 607271689a
commit adc450a3ac
6 changed files with 125 additions and 57 deletions
+15 -18
View File
@@ -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++ )
+1 -1
View File
@@ -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
+66 -3
View File
@@ -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;
+4 -1
View File
@@ -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();
+2 -2
View File
@@ -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;
+37 -32
View File
@@ -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,45 +714,50 @@ 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
if( !SongHasNotesType(mapping.ntMissing))
{ {
for( int i=0; i<m_apNotes.GetSize(); i++ ) int iNumTracksOfMissing = GAMEMAN->NotesTypeToNumTracks(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) )
{ {
Notes* pOriginalNotes = m_apNotes[i]; int iNumTracks = GAMEMAN->NotesTypeToNumTracks(nt);
if( pOriginalNotes->m_NotesType != mapping.ntGenerateFrom ) int iTrackDifference = abs(iNumTracks-iNumTracksOfMissing);
continue; if( SongHasNotesType(nt) && iTrackDifference<iBestTrackDifference )
{
ntBestMatch = nt;
iBestTrackDifference = iTrackDifference;
}
}
Notes* pNewNotes = new Notes; if( ntBestMatch != -1 )
pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty; {
pNewNotes->m_iMeter = pOriginalNotes->m_iMeter; for( int j=0; j<m_apNotes.GetSize(); j++ )
pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)"; {
pNewNotes->m_NotesType = mapping.ntMissing; Notes* pOriginalNotes = m_apNotes[j];
if( pOriginalNotes->m_NotesType != ntBestMatch )
continue; // skip
NoteData originalNoteData, newNoteData; Notes* pNewNotes = new Notes;
pOriginalNotes->GetNoteData( &originalNoteData ); pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty;
newNoteData.LoadTransformed( &originalNoteData, GAMEMAN->NotesTypeToNumTracks(mapping.ntMissing), mapping.iOriginalTrackToTakeFrom ); pNewNotes->m_iMeter = pOriginalNotes->m_iMeter;
pNewNotes->SetNoteData( &newNoteData ); pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)";
this->m_apNotes.Add( pNewNotes ); pNewNotes->m_NotesType = ntMissing;
NoteData originalNoteData, newNoteData;
pOriginalNotes->GetNoteData( &originalNoteData );
newNoteData.LoadTransformedSlidingWindow( &originalNoteData, iNumTracksOfMissing );
pNewNotes->SetNoteData( &newNoteData );
this->m_apNotes.Add( pNewNotes );
}
} }
} }
} }