From bd7eaf3f6c42c0d25da75f3428bde99a49d2c044 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Thu, 22 Jul 2004 21:02:07 +0000 Subject: [PATCH] save memory by loading SMData from cache on demand --- stepmania/src/Song.cpp | 18 ++++++----- stepmania/src/Steps.cpp | 67 ++++++++++++++++++++++++++++++++++++++--- stepmania/src/Steps.h | 3 ++ 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 55d22757cf..224af9ee41 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -262,6 +262,17 @@ bool Song::LoadFromSongDir( CString sDir ) SaveToCacheFile(); } + + + for( unsigned i=0; iSetFile( GetCacheFilePath() ); + + /* Compress all Steps. During initial caching, this will remove cached NoteData; + * during cached loads, this will just remove cached SMData. */ + m_vpSteps[i]->Compress(); + } + /* Load the cached banners, if it's not loaded already. */ if( m_bHasBanner ) BANNERCACHE->LoadBanner( GetBannerPath() ); @@ -814,13 +825,6 @@ void Song::TidyUpData() } } } - - - // Compress all Steps - for( i=0; iCompress(); - } } void Song::TranslateTitles() diff --git a/stepmania/src/Steps.cpp b/stepmania/src/Steps.cpp index 9b8ad1cbb7..de9875070d 100644 --- a/stepmania/src/Steps.cpp +++ b/stepmania/src/Steps.cpp @@ -1,5 +1,21 @@ +/* + * This stores a single note pattern for a song. + * + * We can have too much data to keep everything decompressed as NoteData, so most + * songs are kept in memory compressed as SMData until requested. NoteData is normally + * not requested casually during gameplay; we can move through screens, the music + * wheel, etc. without touching any NoteData. + * + * To save more memory, if data is cached on disk, read it from disk on demand. Not + * all Steps will have an associated file for this purpose. (Profile edits don't do + * this yet.) + * + * Data can be on disk (always compressed), compressed in memory, and uncompressed in + * memory. + */ #include "global.h" #include "Steps.h" +#include "StepsUtil.h" #include "song.h" #include "Steps.h" #include "IniFile.h" @@ -13,6 +29,7 @@ #include "NoteDataUtil.h" #include "ProfileManager.h" #include "PrefsManager.h" +#include "NotesLoaderSM.h" Steps::Steps() { @@ -143,10 +160,9 @@ void Steps::TidyUpData() void Steps::Decompress() const { if(notes) - { return; // already decompressed - } - else if(parent) + + if(parent) { // get autogen notes NoteData pdata; @@ -164,8 +180,36 @@ void Steps::Decompress() const NoteDataUtil::FixImpossibleRows( *notes, m_StepsType ); } + return; } - else if(!notes_comp) + + if( !m_sFilename.empty() && notes_comp == NULL ) + { + /* We have data on disk and not in memory. Load it. */ + Song s; + SMLoader ld; + if( !ld.LoadFromSMFile( m_sFilename, s, true ) ) + { + LOG->Warn( "Couldn't load \"%s\"", m_sFilename.c_str() ); + return; + } + + /* Find the steps. */ + StepsID ID; + ID.FromSteps( this ); + + Steps *pSteps = ID.ToSteps( &s, true ); + if( pSteps == NULL ) + { + LOG->Warn( "Couldn't find %s in \"%s\"", ID.ToString().c_str(), m_sFilename.c_str() ); + return; + } + + notes_comp = new CompressedNoteData; + pSteps->GetSMNoteData( notes_comp->notes, notes_comp->attacks ); + } + + if( notes_comp == NULL ) { /* there is no data, do nothing */ } @@ -181,6 +225,16 @@ void Steps::Decompress() const void Steps::Compress() const { + if( !m_sFilename.empty() ) + { + /* We have a file on disk; clear all data in memory. */ + delete notes; + notes = NULL; + delete notes_comp; + notes_comp = NULL; + return; + } + if(!notes_comp) { if(!notes) return; /* no data is no data */ @@ -251,6 +305,11 @@ bool Steps::IsAutogen() const return parent != NULL; } +void Steps::SetFile( CString fn ) +{ + m_sFilename = fn; +} + void Steps::SetDescription(CString desc) { DeAutogen(); diff --git a/stepmania/src/Steps.h b/stepmania/src/Steps.h index 4826203e0b..ee64df13de 100644 --- a/stepmania/src/Steps.h +++ b/stepmania/src/Steps.h @@ -36,6 +36,7 @@ public: int GetMeter() const { return Real()->m_iMeter; } const RadarValues& GetRadarValues() const { return Real()->m_RadarValues; } + void SetFile( CString fn ); void SetDescription(CString desc); void SetDifficulty(Difficulty d); void SetLoadedFromProfile( ProfileSlot slot ) { m_LoadedFromProfile = slot; } @@ -70,6 +71,8 @@ protected: const Steps *Real() const; + CString m_sFilename; + /* These values are pulled from the autogen source first, if there is one. */ ProfileSlot m_LoadedFromProfile; // PROFILE_SLOT_INVALID if wasn't loaded from a profile unsigned m_uHash; // only used if m_Difficulty == DIFFICULTY_EDIT