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 "io.h"
#include "fcntl.h"
MsdFile::MsdFile()
@@ -25,19 +27,15 @@ MsdFile::~MsdFile()
//returns true if successful, false otherwise
bool MsdFile::ReadFile( CString sNewPath )
{
// Get file size in bytes
HANDLE hFile = CreateFile(
sNewPath, // pointer to name of the file
GENERIC_READ, // access (read-write) mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
NULL, // pointer to security attributes
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL // handle to file with attributes to
);
int fh;
/* Open a file */
if( (fh = _open(sNewPath, _O_RDONLY, 0)) == -1 )
return false;
int iBufferSize = _filelength( fh ) + 1000; // +1000 because sometimes the bytes read is > filelength. Why?
_close( fh );
int iBufferSize = GetFileSize( hFile, NULL ) + 1000; // +1000 just in case
CloseHandle( hFile );
FILE* fp = fopen(sNewPath, "r");
if( fp == NULL )
@@ -45,13 +43,13 @@ bool MsdFile::ReadFile( CString sNewPath )
// allocate a string to hold the file
char* szFileString = new char[iBufferSize];
char* szParams[MAX_VALUES][MAX_PARAMS_PER_VALUE];
ASSERT( szFileString );
int iBytesRead = fread( szFileString, 1, iBufferSize, fp );
ASSERT( iBufferSize > iBytesRead );
/* why are we using Windows API calls for simple file access, anyway? XXX -glenn */
/* What is the C way to get the file size? I don't see 'fstat' in C library... -Chris */
szFileString[iBytesRead] = '\0';
char* szParams[MAX_VALUES][MAX_PARAMS_PER_VALUE];
m_iNumValues = 0;
@@ -90,6 +88,7 @@ bool MsdFile::ReadFile( CString sNewPath )
ReadingValue=true;
m_iNumValues++;
ASSERT( m_iNumValues < MAX_VALUES );
int iCurValueIndex = m_iNumValues-1;
m_iNumParams[iCurValueIndex] = 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( 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;
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
{
HoldNote &other = m_HoldNotes[i];
if( add.m_iTrack == other.m_iTrack && // the notes correspond
other.m_fStartBeat <= add.m_fEndBeat &&
other.m_fEndBeat >= add.m_fStartBeat ) // these HoldNotes overlap (this isn't entirely correct!)
if( add.m_iTrack == other.m_iTrack && // the tracks correspond
// they overlap
(
( 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_fEndBeat = max(add.m_fEndBeat, other.m_fEndBeat);
@@ -854,6 +860,63 @@ void NoteData::LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const in
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 )
{
const int iMeasureStartIndex = iMeasureIndex * ROWS_PER_MEASURE;
+4 -1
View File
@@ -23,7 +23,6 @@
// ... for future expansion
class NoteData
{
public:
@@ -58,6 +57,7 @@ public:
// statistics
bool IsThereANoteAtRow( int iRow );
float GetFirstBeat(); // return the beat number of the first note
int GetFirstRow();
float GetLastBeat(); // return the beat number of the last note
@@ -89,6 +89,9 @@ public:
// Transformations
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 CropToRightSide();
+2 -2
View File
@@ -903,7 +903,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
case DIK_P:
{
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 )
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
@@ -924,7 +924,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
case DIK_R:
{
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 )
m_NoteFieldEdit.m_fEndMarker = m_pSong->m_fLastBeat;
+37 -32
View File
@@ -33,7 +33,7 @@
#include "NotesLoaderKSF.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)
@@ -714,45 +714,50 @@ void Song::SaveToDWIFile()
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()
{
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(mapping.ntMissing))
if( !SongHasNotesType(ntMissing) ) // missing Notes of this type
{
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];
if( pOriginalNotes->m_NotesType != mapping.ntGenerateFrom )
continue;
int iNumTracks = GAMEMAN->NotesTypeToNumTracks(nt);
int iTrackDifference = abs(iNumTracks-iNumTracksOfMissing);
if( SongHasNotesType(nt) && iTrackDifference<iBestTrackDifference )
{
ntBestMatch = nt;
iBestTrackDifference = iTrackDifference;
}
}
Notes* pNewNotes = new Notes;
pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty;
pNewNotes->m_iMeter = pOriginalNotes->m_iMeter;
pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)";
pNewNotes->m_NotesType = mapping.ntMissing;
if( ntBestMatch != -1 )
{
for( int j=0; j<m_apNotes.GetSize(); j++ )
{
Notes* pOriginalNotes = m_apNotes[j];
if( pOriginalNotes->m_NotesType != ntBestMatch )
continue; // skip
NoteData originalNoteData, newNoteData;
pOriginalNotes->GetNoteData( &originalNoteData );
newNoteData.LoadTransformed( &originalNoteData, GAMEMAN->NotesTypeToNumTracks(mapping.ntMissing), mapping.iOriginalTrackToTakeFrom );
pNewNotes->SetNoteData( &newNoteData );
this->m_apNotes.Add( pNewNotes );
Notes* pNewNotes = new Notes;
pNewNotes->m_Difficulty = pOriginalNotes->m_Difficulty;
pNewNotes->m_iMeter = pOriginalNotes->m_iMeter;
pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)";
pNewNotes->m_NotesType = ntMissing;
NoteData originalNoteData, newNoteData;
pOriginalNotes->GetNoteData( &originalNoteData );
newNoteData.LoadTransformedSlidingWindow( &originalNoteData, iNumTracksOfMissing );
pNewNotes->SetNoteData( &newNoteData );
this->m_apNotes.Add( pNewNotes );
}
}
}
}