Jeck - [Requires JGE rebuild] Extensive cache improvements.

* Numerous cache fixes, reduced filesystem access.
 * Cache fails very gracefully. 
 * Cache is now a templated class, with individual caches per data-type.
 * Much easier to extend.
 * Extensively debugged. Try compiling with -DDEBUG_CACHE.
 * Caches limits can be set on a per-item basis.
 * hgeParticleSystemInfo are now cached, mana particles now fall back to defaults.
 * Samples are not cached, but track filesystem misses using the cache backbone. 
 * Avatars are cached. Default baka avatar is now baka.jpg, to prevent collision with player.

A note on the retrieval types: 
  RETRIEVE_MANAGE puts a resource into a seperate, managed resource list.
    Managed resources are guarenteed valid for the lifetime of the program. 
    Retrieving a managed quad promotes the associated texture to managed. Don't do that by mistake.
    Calls to Resources.Refresh() will attempt to reload managed resources in place.

  RETRIVE_LOCK (and by extension, RETRIEVE_VRAM), returns a resource after locking it.
    A resource may have many locks, and remains in cache until they are all released. 
    If the resource is managed, it returns it unmodified.

A note on quads:
Unlike all other RetrieveWhatever() functions, the default behavior for RetrieveQuad is RETRIEVE_LOCK. Worse, Release(JQuad*) is slow, and will /always/ release one lock from the associated texture.   

There's a long and complicated explanation for this, involving support for live relinking of textures to existing quads, but basically what it means is that we only use RetrieveQuad for quads we intend to store and later Release(). If a temporary quad is needed, the preferred method is to use NEW JQuad* and SAFE_DELETE with RetrieveTexture(). RetrieveTempQuad is also provided, but is only guaranteed until the next call to the cache.

Note that RetrieveCard has none of these problems.
This commit is contained in:
wagic.jeck
2009-09-14 08:28:49 +00:00
parent a696b65ffb
commit d55fc91112
27 changed files with 3732 additions and 2992 deletions

View File

@@ -1,102 +1,88 @@
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#ifndef _RESOURCE_MANAGER_H_
#define _RESOURCE_MANAGER_H_
#ifdef WIN32
#pragma warning(disable : 4786)
#endif
#include <stdio.h>
#include <vector>
#include <map>
#include <string>
using namespace std;
#define INVALID_ID -1
class JRenderer;
class JSample;
class JMusic;
class JTexture;
class JQuad;
class JLBFont;
class JResourceManager
{
public:
JResourceManager();
virtual ~JResourceManager();
//void SetResourceRoot(const string& resourceRoot);
bool LoadResource(const string& resourceName);
void RemoveAll();
virtual int CreateTexture(const string &textureName);
JTexture* GetTexture(const string &textureName);
JTexture* GetTexture(int id);
virtual int CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height);
JQuad* GetQuad(const string &quadName);
JQuad* GetQuad(int id);
virtual int LoadJLBFont(const string &fontName, int height);
JLBFont* GetJLBFont(const string &fontName);
JLBFont* GetJLBFont(int id);
virtual int LoadMusic(const string &musicName);
JMusic* GetMusic(const string &musicName);
JMusic* GetMusic(int id);
virtual int LoadSample(const string &sampleName);
JSample* GetSample(const string &sampleName);
JSample* GetSample(int id);
// int RegisterParticleEffect(const string &effectName);
// JParticleEffect* GetParticleEffect(const string &effectName);
// JParticleEffect* GetParticleEffect(int id);
//
// int RegisterMotionEmitter(const string &emitterName);
// JMotionEmitter* GetMotionEmitter(const string &emitterName);
// JMotionEmitter* GetMotionEmitter(int id);
protected:
//JRenderer *mRenderer;
//string mResourceRoot;
vector<JTexture *> mTextureList;
map<string, int> mTextureMap;
vector<JQuad *> mQuadList;
map<string, int> mQuadMap;
// vector<JParticleEffect *> mParticleEffectList;
// map<string, int> mParticleEffectMap;
//
// vector<JMotionEmitter *> mMotionEmitterList;
// map<string, int> mMotionEmitterMap;
vector<JLBFont *> mFontList;
map<string, int> mFontMap;
vector<JMusic *> mMusicList;
map<string, int> mMusicMap;
vector<JSample *> mSampleList;
map<string, int> mSampleMap;
};
#endif
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#ifndef _RESOURCE_MANAGER_H_
#define _RESOURCE_MANAGER_H_
#ifdef WIN32
#pragma warning(disable : 4786)
#endif
#include <stdio.h>
#include <vector>
#include <map>
#include <string>
using namespace std;
#define INVALID_ID -1
class JRenderer;
class JSample;
class JMusic;
class JTexture;
class JQuad;
class JLBFont;
class JResourceManager
{
public:
JResourceManager();
virtual ~JResourceManager();
//void SetResourceRoot(const string& resourceRoot);
bool LoadResource(const string& resourceName);
virtual void RemoveAll();
virtual int CreateTexture(const string &textureName);
virtual JTexture* GetTexture(const string &textureName);
virtual JTexture* GetTexture(int id);
virtual int CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height);
virtual JQuad* GetQuad(const string &quadName);
virtual JQuad* GetQuad(int id);
virtual int LoadJLBFont(const string &fontName, int height);
virtual JLBFont* GetJLBFont(const string &fontName);
virtual JLBFont* GetJLBFont(int id);
// int RegisterParticleEffect(const string &effectName);
// JParticleEffect* GetParticleEffect(const string &effectName);
// JParticleEffect* GetParticleEffect(int id);
//
// int RegisterMotionEmitter(const string &emitterName);
// JMotionEmitter* GetMotionEmitter(const string &emitterName);
// JMotionEmitter* GetMotionEmitter(int id);
protected:
//JRenderer *mRenderer;
//string mResourceRoot;
vector<JTexture *> mTextureList;
map<string, int> mTextureMap;
vector<JQuad *> mQuadList;
map<string, int> mQuadMap;
// vector<JParticleEffect *> mParticleEffectList;
// map<string, int> mParticleEffectMap;
//
// vector<JMotionEmitter *> mMotionEmitterList;
// map<string, int> mMotionEmitterMap;
vector<JLBFont *> mFontList;
map<string, int> mFontMap;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -133,7 +133,8 @@ JSample *JSoundSystem::LoadSample(const char *fileName)
if (sample)
{
sample->mSample = new WAVDATA;
loadWaveData(sample->mSample, s, 1);
if(!loadWaveData(sample->mSample, s, 1))
sample->mSample = NULL;
}
return sample;

View File

@@ -202,6 +202,8 @@ JSample *JSoundSystem::LoadSample(const char *fileName)
delete[] buffer;
fileSystem->CloseFile();
}
else
sample->mSample = NULL;
}

View File

@@ -1,219 +1,220 @@
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#include "../../Dependencies/include/png.h"
#include "../../Dependencies/include/fmod.h"
#include "../../include/JSoundSystem.h"
#include "../../include/JFileSystem.h"
//////////////////////////////////////////////////////////////////////////
JMusic::JMusic()
{
}
void JMusic::Update(){
}
int JMusic::getPlayTime(){
return FSOUND_GetCurrentPosition(JSoundSystem::GetInstance()->mChannel)/44.1; //todo more generic, here it's only 44kHz
}
JMusic::~JMusic()
{
JSoundSystem::GetInstance()->StopMusic(this);
//JSoundSystem::GetInstance()->FreeMusic(this);
if (mTrack)
FSOUND_Sample_Free(mTrack);
}
//////////////////////////////////////////////////////////////////////////
JSample::JSample()
{
}
JSample::~JSample()
{
//JSoundSystem::GetInstance()->FreeSample(this);
if (mSample)
FSOUND_Sample_Free(mSample);
}
//////////////////////////////////////////////////////////////////////////
JSoundSystem* JSoundSystem::mInstance = NULL;
JSoundSystem* JSoundSystem::GetInstance()
{
if (mInstance == NULL)
{
mInstance = new JSoundSystem();
mInstance->InitSoundSystem();
}
return mInstance;
}
void JSoundSystem::Destroy()
{
if (mInstance)
{
mInstance->DestroySoundSystem();
delete mInstance;
mInstance = NULL;
}
}
JSoundSystem::JSoundSystem()
{
}
JSoundSystem::~JSoundSystem()
{
}
void JSoundSystem::InitSoundSystem()
{
FSOUND_Init(44100, 32, 0);
}
void JSoundSystem::DestroySoundSystem()
{
FSOUND_Close();
}
JMusic *JSoundSystem::LoadMusic(const char *fileName)
{
JMusic* music = new JMusic();
if (music)
{
JFileSystem* fileSystem = JFileSystem::GetInstance();
if (fileSystem->OpenFile(fileName))
{
// FMUSIC is for MOD...
// int size = fileSystem->GetFileSize();
// char *buffer = new char[size];
// fileSystem->ReadFile(buffer, size);
// music->mTrack = FMUSIC_LoadSongEx(buffer, 0, size, FSOUND_LOADMEMORY, NULL, 0);
//
// delete[] buffer;
// fileSystem->CloseFile();
int size = fileSystem->GetFileSize();
char *buffer = new char[size];
fileSystem->ReadFile(buffer, size);
music->mTrack = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, FSOUND_LOADMEMORY, 0, size);
delete[] buffer;
fileSystem->CloseFile();
}
}
return music;
}
// void JSoundSystem::FreeMusic(JMusic *music)
// {
// if (music)
// {
// // if (music->mTrack)
// // FMUSIC_FreeSong(music->mTrack);
// // delete music;
// // music = NULL;
//
// if (music->mTrack)
// FSOUND_Sample_Free(music->mTrack);
//
// //delete music;
// //music = NULL;
// }
// }
void JSoundSystem::PlayMusic(JMusic *music, bool looping)
{
if (music && music->mTrack)
{
mChannel = FSOUND_PlaySound(FSOUND_FREE, music->mTrack);
if (looping)
FSOUND_SetLoopMode(mChannel, FSOUND_LOOP_NORMAL);
else
FSOUND_SetLoopMode(mChannel, FSOUND_LOOP_OFF);
}
}
void JSoundSystem::StopMusic(JMusic *music)
{
// if (music && music->mTrack)
// FMUSIC_StopSong(music->mTrack);
FSOUND_StopSound(mChannel);
}
void JSoundSystem::SetVolume(int volume)
{
FSOUND_SetSFXMasterVolume(volume);
mVolume = volume;
}
JSample *JSoundSystem::LoadSample(const char *fileName)
{
JSample* sample = new JSample();
if (sample)
{
JFileSystem* fileSystem = JFileSystem::GetInstance();
if (fileSystem->OpenFile(fileName))
{
int size = fileSystem->GetFileSize();
char *buffer = new char[size];
fileSystem->ReadFile(buffer, size);
sample->mSample = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, FSOUND_LOADMEMORY, 0, size);
delete[] buffer;
fileSystem->CloseFile();
}
}
return sample;
}
void JSoundSystem::PlaySample(JSample *sample)
{
if (sample && sample->mSample)
FSOUND_PlaySound(FSOUND_FREE, sample->mSample);
}
//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#include "../../Dependencies/include/png.h"
#include "../../Dependencies/include/fmod.h"
#include "../../include/JSoundSystem.h"
#include "../../include/JFileSystem.h"
//////////////////////////////////////////////////////////////////////////
JMusic::JMusic()
{
}
void JMusic::Update(){
}
int JMusic::getPlayTime(){
return FSOUND_GetCurrentPosition(JSoundSystem::GetInstance()->mChannel)/44.1; //todo more generic, here it's only 44kHz
}
JMusic::~JMusic()
{
JSoundSystem::GetInstance()->StopMusic(this);
//JSoundSystem::GetInstance()->FreeMusic(this);
if (mTrack)
FSOUND_Sample_Free(mTrack);
}
//////////////////////////////////////////////////////////////////////////
JSample::JSample()
{
}
JSample::~JSample()
{
//JSoundSystem::GetInstance()->FreeSample(this);
if (mSample)
FSOUND_Sample_Free(mSample);
}
//////////////////////////////////////////////////////////////////////////
JSoundSystem* JSoundSystem::mInstance = NULL;
JSoundSystem* JSoundSystem::GetInstance()
{
if (mInstance == NULL)
{
mInstance = new JSoundSystem();
mInstance->InitSoundSystem();
}
return mInstance;
}
void JSoundSystem::Destroy()
{
if (mInstance)
{
mInstance->DestroySoundSystem();
delete mInstance;
mInstance = NULL;
}
}
JSoundSystem::JSoundSystem()
{
}
JSoundSystem::~JSoundSystem()
{
}
void JSoundSystem::InitSoundSystem()
{
FSOUND_Init(44100, 32, 0);
}
void JSoundSystem::DestroySoundSystem()
{
FSOUND_Close();
}
JMusic *JSoundSystem::LoadMusic(const char *fileName)
{
JMusic* music = new JMusic();
if (music)
{
JFileSystem* fileSystem = JFileSystem::GetInstance();
if (fileSystem->OpenFile(fileName))
{
// FMUSIC is for MOD...
// int size = fileSystem->GetFileSize();
// char *buffer = new char[size];
// fileSystem->ReadFile(buffer, size);
// music->mTrack = FMUSIC_LoadSongEx(buffer, 0, size, FSOUND_LOADMEMORY, NULL, 0);
//
// delete[] buffer;
// fileSystem->CloseFile();
int size = fileSystem->GetFileSize();
char *buffer = new char[size];
fileSystem->ReadFile(buffer, size);
music->mTrack = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, FSOUND_LOADMEMORY, 0, size);
delete[] buffer;
fileSystem->CloseFile();
}
}
return music;
}
// void JSoundSystem::FreeMusic(JMusic *music)
// {
// if (music)
// {
// // if (music->mTrack)
// // FMUSIC_FreeSong(music->mTrack);
// // delete music;
// // music = NULL;
//
// if (music->mTrack)
// FSOUND_Sample_Free(music->mTrack);
//
// //delete music;
// //music = NULL;
// }
// }
void JSoundSystem::PlayMusic(JMusic *music, bool looping)
{
if (music && music->mTrack)
{
mChannel = FSOUND_PlaySound(FSOUND_FREE, music->mTrack);
if (looping)
FSOUND_SetLoopMode(mChannel, FSOUND_LOOP_NORMAL);
else
FSOUND_SetLoopMode(mChannel, FSOUND_LOOP_OFF);
}
}
void JSoundSystem::StopMusic(JMusic *music)
{
// if (music && music->mTrack)
// FMUSIC_StopSong(music->mTrack);
FSOUND_StopSound(mChannel);
}
void JSoundSystem::SetVolume(int volume)
{
FSOUND_SetSFXMasterVolume(volume);
mVolume = volume;
}
JSample *JSoundSystem::LoadSample(const char *fileName)
{
JSample* sample = new JSample();
if (sample)
{
JFileSystem* fileSystem = JFileSystem::GetInstance();
if (fileSystem->OpenFile(fileName))
{
int size = fileSystem->GetFileSize();
char *buffer = new char[size];
fileSystem->ReadFile(buffer, size);
sample->mSample = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, FSOUND_LOADMEMORY, 0, size);
delete[] buffer;
fileSystem->CloseFile();
}else
sample->mSample = NULL;
}
return sample;
}
void JSoundSystem::PlaySample(JSample *sample)
{
if (sample && sample->mSample)
FSOUND_PlaySound(FSOUND_FREE, sample->mSample);
}

View File

@@ -1,4 +1,4 @@
OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o
OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o objs/WCachedResource.o
DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS))
RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache)

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,95 @@
#ifndef _WCACHEDRESOURCE_H_
#define _WCACHEDRESOURCE_H_
#include <hge/hgeparticle.h>
class WResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
WResource();
virtual ~WResource();
virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake.
virtual unsigned long size()=0; //Size of cached item in bytes.
virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ.
virtual bool isGood()=0; //Return true if this has data.
virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood().
protected:
bool isLocked(); //Is the resource locked?
bool isPermanent(); //Is the resource permanent?
void lock(); //Lock it.
void deadbolt(); //Make it permanent.
void unlock(bool force = false); //Unlock it. Forcing a lock will also remove "permanent" status.
void hit(); //Update resource's last used time.
int loadedMode; //What submode settings were we loaded with? (For refresh)
unsigned int lastTime; //When was the last time we were hit?
unsigned char locks; //Remember to unlock when we're done using locked stuff, or else this'll be useless.
};
class WCachedTexture: public WResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
WCachedTexture();
~WCachedTexture();
void Refresh(string filename);
unsigned long size();
bool isGood();
bool Attempt(string filename, int submode, int & error);
bool compare(JTexture * t) {return (t == texture);};
void Nullify();
JTexture * Actual(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(string resname);
JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Get us a new/existing quad.
JQuad * GetCard(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Same as above, but centered when new.
bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed.
protected:
JTexture * texture;
bool bVRAM;
map<JQuad*,string> trackedQuads;
};
class WCachedParticles: public WResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
WCachedParticles();
~WCachedParticles();
void Nullify();
void Refresh(string filename);
unsigned long size();
bool isGood();
bool Attempt(string filename, int submode, int & error);
bool compare(hgeParticleSystemInfo * p) {return (p == particles);};
hgeParticleSystemInfo * Actual();
protected:
hgeParticleSystemInfo * particles;
};
class WCachedSample: public WResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
WCachedSample();
~WCachedSample();
void Nullify();
bool compare(JSample * s) {return (s == sample);};
unsigned long size();
bool isGood();
void Refresh(string filename);
bool Attempt(string filename, int submode, int & error);
JSample * Actual(); //Return this sample.
protected:
JSample * sample;
};
#endif

View File

@@ -5,73 +5,109 @@
#include <JTypes.h>
#include "MTGDeck.h"
#include "MTGCard.h"
#include "WCachedResource.h"
#ifdef WIN32
#define CACHE_SIZE_PIXELS 20000000
#define MAX_CACHE_OBJECTS 2000
#else
#define CACHE_SIZE_PIXELS 2000000
//Hard Limits.
#define LARGE_CACHE_LIMIT 5000000
#define SMALL_CACHE_LIMIT 2000000
#define MAX_CACHE_OBJECTS 200
#endif
#define MAX_CACHE_ATTEMPTS 10
#define MAX_CACHE_MISSES 200
class WCachedResource{
public:
friend class WResourceManager;
bool isLocked(); //Is the resource locked?
void lock(); //Lock it.
void unlock(bool force = false); //Unlock it. If force, then set locks to 0.
void hit(); //Update resource last used time.
WCachedResource();
protected:
unsigned int lastTime;
unsigned char locks; //Remember to unlock when we're done using locked stuff, or else this'll be useless.
};
class WCachedTexture: public WCachedResource{
public:
friend class WResourceManager;
WCachedTexture();
~WCachedTexture();
JTexture * GetTexture(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f); //Get us a new/existing quad.
JQuad * GetCard(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f); //Same as above, but centered when new.
bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed.
protected:
JTexture * texture;
bool bVRAM;
vector<JQuad*> trackedQuads;
};
class WCachedSample: public WCachedResource{
public:
friend class WResourceManager;
WCachedSample();
~WCachedSample();
JSample * GetSample(); //Return this sample.
protected:
JSample * sample;
enum ENUM_WRES_INFO{
WRES_UNLOCKED = 0, //Resource is unlocked.
WRES_MAX_LOCK = 250, //Maximum number of locks for a resource.
WRES_PERMANENT = 251, //Resource is permanent (ie, managed)
};
enum ENUM_RETRIEVE_STYLE{
RETRIEVE_EXISTING, //Only returns a resource if it already exists. Does not lock or unlock.
RETRIEVE_NORMAL, //Returns or creates a resource. Does not change lock status.
RETRIEVE_LOCK, //As above, locks cached resource.
RETRIEVE_UNLOCK, //As above, unlocks cached resource.
RETRIEVE_RESOURCE, //Only retrieves a managed resource.
RETRIEVE_VRAM, //If we create the texture, use vram. Also locks.
RETRIEVE_MANAGE, //Permanently adds retrieved resource to resource manager.
RETRIEVE_LOCK, //As above, locks cached resource. Not for quads.
RETRIEVE_UNLOCK, //As above, unlocks cached resource. Not for quads.
RETRIEVE_RESOURCE, //Only retrieves a managed resource. Does not make a new one.
RETRIEVE_VRAM, //Retrieve it, and use vram if have to we create it. Must still remove it.
RETRIEVE_MANAGE, //Makes resource permanent.
RETRIEVE_THUMB, //Retrieve it as a thumbnail.
CACHE_THUMB = RETRIEVE_THUMB, //Backwords compatibility.
};
enum ENUM_CACHE_SUBTYPE{
CACHE_CARD,
CACHE_THUMB
CACHE_NORMAL = (1<<0), //Use default values. Not really a flag.
CACHE_EXISTING = (1<<1), //Retrieve it only if it already exists
//Because these bits only modify how a cached resource's Attempt() is called,
//We can use them over and over for each resource type.
TEXTURE_SUB_CARD = (1<<2), //Retrieve using cardFile, not graphicsFile.
TEXTURE_SUB_AVATAR = (1<<6), //Retrieve using avatarFile, not graphicsFile.
TEXTURE_SUB_THUMB = (1<<3),//Retrieve prepending "thumbnails\" to the filename.
TEXTURE_SUB_VRAM = (1<<4), //For textures. If we have to allocate, do it in VRAM.
TEXTURE_SUB_5551 = (1<<5), //For textures. If we have to allocate, use RGBA5551.
};
enum ENUM_CACHE_ERROR{
CACHE_ERROR_NONE = 0,
CACHE_ERROR_NOT_CACHED = CACHE_ERROR_NONE,
CACHE_ERROR_404,
CACHE_ERROR_BAD,
CACHE_ERROR_LOST,
CACHE_ERROR_NOT_MANAGED,
};
template <class cacheItem, class cacheActual>
class WCache{
public:
friend class WResourceManager;
WCache();
~WCache();
cacheItem* Retrieve(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Primary interface function.
bool Release(cacheActual* actual); //Releases an item, and deletes it if unlocked.
bool RemoveMiss(string id=""); //Removes a cache miss.
bool RemoveOldest(); //Remove oldest unlocked item.
bool Cleanup(); //Repeats RemoveOldest() until cache fits in size limits
void Clear(); //Removes everything cached. Not lock safe, does not remove managed items.
void ClearUnlocked(); //Remove all unlocked items.
void ClearMisses(); //Clear all cache misses.
void Refresh(); //Refreshes all cache items.
unsigned int Flatten(); //Ensures that the times don't loop. Returns new lastTime.
void Resize(unsigned long size, int items); //Sets new limits, then enforces them. Lock safe, so not a "hard limit".
protected:
bool RemoveItem(cacheItem * item, bool force = true); //Removes an item, deleting it. if(force), ignores locks / permanent
bool UnlinkCache(cacheItem * item); //Removes an item from our cache, does not delete it. Use with care.
bool Delete(cacheItem * item); //Call SAFE_DELETE on cacheItem. If maxCached == 0, nullify first. (This means you have to free that cacheActual later!)
cacheItem* Get(string id, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Subordinate to Retrieve.
cacheItem* AttemptNew(string filename, int submode); //Attempts a new cache item, progressively clearing cache if it fails.
string makeID(string filename, int submode); //Makes an ID appropriate to the submode.
string makeFilename(string id, int submode); //Makes a filename from an ID.
map<string,cacheItem*> cache;
map<string,cacheItem*> managed; //Cache can be arbitrarily large, so managed items are seperate.
unsigned long totalSize;
unsigned long cacheSize;
//Applies to cacheSize only.
unsigned long maxCacheSize;
unsigned int maxCached;
unsigned int cacheItems;
int mError;
#if defined DEBUG_CACHE
string lastRemoved;
string lastReleased;
string lastExpired;
#endif
};
struct WManagedQuad {
WCachedTexture * texture;
string resname;
};
//This class is a wrapper for JResourceManager
class WResourceManager: public JResourceManager
@@ -80,64 +116,77 @@ public:
WResourceManager();
~WResourceManager();
JQuad * RetrieveCard(MTGCard * card, int type = CACHE_CARD, int style = RETRIEVE_NORMAL);
JSample * RetrieveSample(string filename, int style = RETRIEVE_NORMAL);
JTexture * RetrieveTexture(string filename, int style = RETRIEVE_NORMAL);
JQuad * RetrieveQuad(string filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_NORMAL);
JQuad * RetrieveCard(MTGCard * card, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //RetrieveCard is reversed to match current use.
JSample * RetrieveSample(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JTexture * RetrieveTexture(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JQuad * RetrieveQuad(string filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_LOCK, int submode = CACHE_NORMAL);
JQuad * RetrieveTempQuad(string filename);
hgeParticleSystemInfo * RetrievePSI(string filename, JQuad * texture, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
void Release(JTexture * tex);
void Release(JQuad * quad);
void Release(JSample * sample);
void ClearMisses();
void ClearUnlocked();
void ClearSamples();
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
bool Cleanup(); //Force a cleanup. Return false if nothing removed.
void ClearMisses(); //Remove all cache misses.
void ClearUnlocked(); //Remove unlocked items.
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
unsigned int nowTime();
unsigned long Size();
unsigned long SizeCached();
unsigned long SizeManaged();
unsigned int Count();
unsigned int CountCached();
unsigned int CountManaged();
int CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height);
JQuad* GetQuad(const string &quadName);
JQuad* GetQuad(int id);
//Our file redirect system.
string graphicsFile(const string filename, const string specific = "");
string cardFile(const string filename, const string setname, const string specific = "");
string avatarFile(const string filename, const string specific = "");
string cardFile(const string filename, const string specific = "");
string musicFile(const string filename, const string specific = "");
string sfxFile(const string filename, const string specific = "");
int fileOK(string filename, bool relative = false);
//Not part of our interface, but left public to maintain JResourceManager compatibility
//These are for managed resources only.
//For backwards compatibility with JResourceManager. Avoid using these, they're not optimal.
int CreateTexture(const string &textureName);
int CreateQuad(const string &quadName, const string &textureName, float x=0.0f, float y=0.0f, float width=0.0f, float height=0.0f);
JTexture* GetTexture(const string &textureName);
JTexture* GetTexture(int id);
//Wrapped from JResourceManger. TODO: Privatize
int LoadJLBFont(const string &fontName, int height);
int LoadMusic(const string &musicName);
int LoadSample(const string &sampleName);
//Wrapped from JSoundSystem. TODO: Privatize.
JMusic * ssLoadMusic(const char *fileName);
private:
bool RemoveOldestTexture();
bool RemoveOldestSample();
bool cleanup();
void LargeCache();
void SmallCache();
JTexture * attemptTexture(string filename, int mode = 0, int format = TEXTURE_FORMAT);
void DebugRender();
WCachedTexture * getCachedTexture(string filename, bool makenew = true, int mode = 0, int format = TEXTURE_FORMAT);
WCachedTexture * getCachedCard(MTGCard * card, int type = CACHE_CARD, bool makenew = true);
WCachedSample * getCachedSample(string filename, bool makenew = true);
#ifdef DEBUG_CACHE
unsigned long menuCached;
string debugMessage;
#endif
private:
void FlattenTimes(); //To prevent bad cache timing on int overflow
//For cached stuff
map<string,WCachedTexture*> textureCache;
map<string,WCachedSample*> sampleCache;
vector<string> mTextureMissing; //For managed textures.
//Current access time.
int lastTime;
//For cached stuff
WCache<WCachedTexture,JTexture> textureWCache;
WCache<WCachedSample,JSample> sampleWCache;
WCache<WCachedParticles,hgeParticleSystemInfo> psiWCache;
vector<WManagedQuad> managedQuads;
//Statistics of record.
int nb_textures;
long totalsize;
unsigned int lastTime;
};
extern WResourceManager resources;

View File

@@ -562,7 +562,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
if (deckid == -1){ //Evil twin
sprintf(deckFile, opponent->deckFile.c_str());
OutputDebugString(opponent->deckFile.c_str());
sprintf(avatarFile, "%s",options.profileFile("avatar.jpg","graphics",true,true).c_str());
sprintf(avatarFile, "baka.jpg");
sprintf(deckFileSmall, "ai_baka_eviltwin");
}else{
if (!deckid){
@@ -583,11 +583,10 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
deckid = 1 + rand() % (nbdecks);
}
sprintf(deckFile, RESPATH"/ai/baka/deck%i.txt",deckid);
sprintf(avatarFile, "ai/baka/avatars/avatar%i.jpg",deckid);
sprintf(avatarFile, "avatar%i.jpg",deckid);
sprintf(deckFileSmall, "ai_baka_deck%i",deckid);
}
MTGDeck * tempDeck = NEW MTGDeck(deckFile, collection);
MTGPlayerCards * deck = NEW MTGPlayerCards(collection,tempDeck);
delete tempDeck;
@@ -632,12 +631,18 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
}
AIPlayerBaka::AIPlayerBaka(MTGPlayerCards * deck, string file, string fileSmall, string avatarFile) : AIPlayer(deck, file, fileSmall) {
if (fileExists(avatarFile.c_str()))
mAvatarTex = JRenderer::GetInstance()->LoadTexture(avatarFile.c_str(), TEX_TYPE_USE_VRAM);
else
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
if (mAvatarTex)
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
mAvatarTex = resources.RetrieveTexture(avatarFile,RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
if(!mAvatarTex){
avatarFile = "baka.jpg";
mAvatarTex = resources.RetrieveTexture(avatarFile,RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
}
if(mAvatarTex)
mAvatar = resources.RetrieveQuad(avatarFile, 0, 0, 35, 50,"bakaAvatar",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
else
mAvatar = NULL;
initTimer();
}

View File

@@ -111,14 +111,14 @@ JQuad * CardGui::alternateThumbQuad(MTGCard * card){
JQuad * q;
switch(card->getColor())
{
case Constants::MTG_COLOR_ARTIFACT : q = resources.RetrieveQuad("artifact_thumb.jpg");break;
case Constants::MTG_COLOR_GREEN: q = resources.RetrieveQuad("green_thumb.jpg");break;
case Constants::MTG_COLOR_BLUE : q = resources.RetrieveQuad("blue_thumb.jpg");break;
case Constants::MTG_COLOR_RED : q = resources.RetrieveQuad("red_thumb.jpg");break;
case Constants::MTG_COLOR_BLACK: q = resources.RetrieveQuad("black_thumb.jpg");break;
case Constants::MTG_COLOR_WHITE: q = resources.RetrieveQuad("white_thumb.jpg");break;
case Constants::MTG_COLOR_LAND : q = resources.RetrieveQuad("land_thumb.jpg");break;
default: q = resources.RetrieveQuad("black_thumb.jpg");break;
case Constants::MTG_COLOR_ARTIFACT : q = resources.RetrieveTempQuad("artifact_thumb.jpg");break;
case Constants::MTG_COLOR_GREEN: q = resources.RetrieveTempQuad("green_thumb.jpg");break;
case Constants::MTG_COLOR_BLUE : q = resources.RetrieveTempQuad("blue_thumb.jpg");break;
case Constants::MTG_COLOR_RED : q = resources.RetrieveTempQuad("red_thumb.jpg");break;
case Constants::MTG_COLOR_BLACK: q = resources.RetrieveTempQuad("black_thumb.jpg");break;
case Constants::MTG_COLOR_WHITE: q = resources.RetrieveTempQuad("white_thumb.jpg");break;
case Constants::MTG_COLOR_LAND : q = resources.RetrieveTempQuad("land_thumb.jpg");break;
default: q = resources.RetrieveTempQuad("black_thumb.jpg");break;
}
if(q && q->mTex)
q->SetHotSpot(q->mTex->mWidth/2,q->mTex->mHeight/2);
@@ -131,14 +131,14 @@ void CardGui::alternateRender(MTGCard * card, const Pos& pos){
JQuad * q;
switch(card->getColor())
{
case Constants::MTG_COLOR_ARTIFACT: q = resources.RetrieveQuad("artifact.jpg");break;
case Constants::MTG_COLOR_GREEN: q = resources.RetrieveQuad("green.jpg");break;
case Constants::MTG_COLOR_BLUE : q = resources.RetrieveQuad("blue.jpg");break;
case Constants::MTG_COLOR_RED : q = resources.RetrieveQuad("red.jpg");break;
case Constants::MTG_COLOR_BLACK: q = resources.RetrieveQuad("black.jpg");break;
case Constants::MTG_COLOR_WHITE: q = resources.RetrieveQuad("white.jpg");break;
case Constants::MTG_COLOR_LAND: q = resources.RetrieveQuad("land.jpg");break;
default: q = resources.RetrieveQuad("black.jpg");break;
case Constants::MTG_COLOR_ARTIFACT: q = resources.RetrieveTempQuad("artifact.jpg");break;
case Constants::MTG_COLOR_GREEN: q = resources.RetrieveTempQuad("green.jpg");break;
case Constants::MTG_COLOR_BLUE : q = resources.RetrieveTempQuad("blue.jpg");break;
case Constants::MTG_COLOR_RED : q = resources.RetrieveTempQuad("red.jpg");break;
case Constants::MTG_COLOR_BLACK: q = resources.RetrieveTempQuad("black.jpg");break;
case Constants::MTG_COLOR_WHITE: q = resources.RetrieveTempQuad("white.jpg");break;
case Constants::MTG_COLOR_LAND: q = resources.RetrieveTempQuad("land.jpg");break;
default: q = resources.RetrieveTempQuad("black.jpg");break;
}
if(q && q->mTex){
q->SetHotSpot(q->mTex->mWidth/2,q->mTex->mHeight/2);

View File

@@ -106,17 +106,17 @@ void GameApp::Create()
for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16);
resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE);
resources.RetrieveQuad("back.jpg", 0, 0, 200, 285, "back",RETRIEVE_MANAGE);
resources.GetQuad("back")->SetHotSpot(100, 145);
JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 200, 285, "back",RETRIEVE_MANAGE);
jq->SetHotSpot(100, 145);
resources.RetrieveTexture("back_thumb.jpg",RETRIEVE_MANAGE);
resources.RetrieveQuad("back_thumb.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "back_thumb",RETRIEVE_MANAGE);
resources.RetrieveTexture("particles.png",RETRIEVE_MANAGE);
resources.RetrieveQuad("particles.png", 0, 0, 32, 32, "particles",RETRIEVE_MANAGE);
resources.GetQuad("particles")->SetHotSpot(16,16);
resources.RetrieveQuad("particles.png", 64, 0, 32, 32, "stars",RETRIEVE_MANAGE);
resources.GetQuad("stars")->SetHotSpot(16,16);
jq = resources.RetrieveQuad("particles.png", 0, 0, 32, 32, "particles",RETRIEVE_MANAGE);
jq->SetHotSpot(16,16);
jq = resources.RetrieveQuad("particles.png", 64, 0, 32, 32, "stars",RETRIEVE_MANAGE);
jq->SetHotSpot(16,16);
resources.LoadJLBFont("simon",11);
resources.GetJLBFont("simon")->SetTracking(-1);
@@ -134,14 +134,13 @@ void GameApp::Create()
resources.RetrieveTexture("DefenderIcon.png",RETRIEVE_MANAGE);
resources.RetrieveTexture("shadow.png",RETRIEVE_MANAGE);
resources.RetrieveQuad("BattleIcon.png", 0, 0, 25, 25,"BattleIcon",RETRIEVE_MANAGE);
resources.RetrieveQuad("DefenderIcon.png", 0, 0, 24, 23,"DefenderIcon",RETRIEVE_MANAGE);
resources.RetrieveQuad("shadow.png", 0, 0, 1, 1,"shadow",RETRIEVE_MANAGE);
jq = resources.RetrieveQuad("BattleIcon.png", 0, 0, 25, 25,"BattleIcon",RETRIEVE_MANAGE);
jq->SetHotSpot(12, 12);
jq = resources.RetrieveQuad("DefenderIcon.png", 0, 0, 24, 23,"DefenderIcon",RETRIEVE_MANAGE);
jq->SetHotSpot(12, 12);
jq = resources.RetrieveQuad("shadow.png", 0, 0, 1, 1,"shadow",RETRIEVE_MANAGE);
jq->SetHotSpot(0.5, 0.5);
resources.GetQuad("BattleIcon")->SetHotSpot(12, 12);
resources.GetQuad("DefenderIcon")->SetHotSpot(12, 12);
resources.GetQuad("shadow")->SetHotSpot(0.5, 0.5);
collection = NEW MTGAllCards();
Particles[0] = NEW hgeParticleSystem("graphics/particle1.psi", resources.GetQuad("particles"));
@@ -284,6 +283,9 @@ void GameApp::Render()
mCurrentState->Render();
}
#ifdef DEBUG_CACHE
resources.DebugRender();
#endif
}

View File

@@ -546,7 +546,7 @@ void GameStateDeckViewer::renderCard(int id, float rotation){
JQuad * quad = NULL;
int showName = 0;
quad = resources.RetrieveCard(card,CACHE_CARD,RETRIEVE_EXISTING);
quad = resources.RetrieveCard(card,RETRIEVE_EXISTING);
if (!quad){
if(last_user_activity > (abs(2-id) + 1)* NO_USER_ACTIVITY_SHOWCARD_DELAY)
quad = resources.RetrieveCard(card);

View File

@@ -42,7 +42,7 @@ GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) {
deck[i]=NULL;
mPlayers[i]=NULL;
}
resources.LargeCache();
premadeDeck = false;
game = NULL;
deckmenu = NULL;
@@ -63,6 +63,7 @@ GameStateDuel::~GameStateDuel() {
void GameStateDuel::Start()
{
JRenderer * renderer = JRenderer::GetInstance();
resources.SmallCache();
renderer->ResetPrivateVRAM();
renderer->EnableVSync(true);
@@ -217,7 +218,7 @@ void GameStateDuel::End()
#if defined (WIN32) || defined (LINUX)
OutputDebugString("Ending GamestateDuel\n");
#endif
resources.SmallCache();
SAFE_DELETE(deckmenu);
JRenderer::GetInstance()->EnableVSync(false);
if (mPlayers[0] && mPlayers[1]) mPlayers[0]->End();

View File

@@ -152,11 +152,27 @@ void GameStateMenu::Start(){
//How many cards total ?
PlayerData * playerdata = NEW PlayerData(mParent->collection);
if(!options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
if(playerdata && !options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i cards (%i)", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
else
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
SAFE_DELETE(playerdata);
#if defined DEBUG_CACHE
resources.ClearUnlocked(); //So we can tell if we've any extra locks.
if(!resources.menuCached)
resources.menuCached = resources.CountCached();
if(resources.CountCached() != resources.menuCached){
char buf[512];
unsigned int i = resources.CountCached()-resources.menuCached;
sprintf(buf,"Warning: %u leftover locked items.",i);
resources.debugMessage = buf;
}
#endif
}
@@ -306,8 +322,8 @@ void GameStateMenu::Update(float dt)
//List active profile and database size.
PlayerData * playerdata = NEW PlayerData(mParent->collection);
if(!options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
if(playerdata && !options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i cards (%i)", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
else
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
SAFE_DELETE(playerdata);

View File

@@ -38,7 +38,7 @@ void GameStateOptions::Start()
optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells"));
optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities"));
optionsList->Add(NEW OptionInteger(Options::CACHESIZE, "Image Cache Size", 60, 5,0,"Default"));
optionsList->Add(NEW OptionInteger(Options::CACHESIZE, "Use large cache"));
optionsTabs = NEW OptionsMenu();
optionsTabs->Add(optionsList);

View File

@@ -19,7 +19,7 @@ GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), acti
enemy_avatar(SCREEN_WIDTH - MARGIN, TOP_LINE, 2, 0, 255),
cursor_pos(NONE), step(DAMAGE)
{
if (NULL == ok_quad)
if(NULL == ok_quad)
{
ok_quad = resources.RetrieveQuad("OK.png");
if (ok_quad) ok_quad->SetHotSpot(28, 22);
@@ -28,6 +28,9 @@ GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), acti
GuiCombat::~GuiCombat()
{
if(ok_quad)
resources.Release(ok_quad);
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
{
for (vector<DefenserDamaged*>::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q)

View File

@@ -10,26 +10,93 @@ const float ManaIcon::DESTY = 20;
ManaIcon::ManaIcon(int color, float x, float y) : Pos(x, y, 0.5, 0.0, 255), f(-1), mode(ALIVE), color(color)
{
hgeParticleSystemInfo * psi = NULL;
JQuad * mq = resources.GetQuad("stars");
if(!mq){
particleSys = NULL;
return;
}
switch (color)
{
case Constants::MTG_COLOR_RED :
particleSys = NEW hgeParticleSystem("graphics/manared.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("manared.psi",mq);
break;
case Constants::MTG_COLOR_BLUE :
particleSys = NEW hgeParticleSystem("graphics/manablue.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("manablue.psi",mq);
break;
case Constants::MTG_COLOR_GREEN :
particleSys = NEW hgeParticleSystem("graphics/managreen.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("managreen.psi",mq);
break;
case Constants::MTG_COLOR_BLACK :
particleSys = NEW hgeParticleSystem("graphics/manablack.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("manablack.psi",mq);
break;
case Constants::MTG_COLOR_WHITE :
particleSys = NEW hgeParticleSystem("graphics/manawhite.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("manawhite.psi",mq);
break;
default :
particleSys = NEW hgeParticleSystem("graphics/mana.psi", resources.GetQuad("stars"));
psi = resources.RetrievePSI("mana.psi",mq);
}
if(!psi){
psi = NEW hgeParticleSystemInfo();
hgeParticleSystemInfo * defaults = resources.RetrievePSI("mana.psi",mq);
if(defaults){
memcpy(psi,defaults,sizeof(hgeParticleSystemInfo));
}
else{
memset(psi,0,sizeof(hgeParticleSystemInfo));
//Default values for particle system! Cribbed from mana.psi
//Really, we should just be loading that and then changing colors...
/*psi->nEmission = 114;
psi->fLifetime = -1;
psi->fParticleLifeMin = 1.1507937;
psi->fParticleLifeMax = 1.4682540;
psi->fSpeedMin = 0.0099999998;
psi->fSizeStart = 0.5;
psi->fSizeEnd = 0.69999999;
psi->fSizeVar = 0.25396827;
psi->fSpinStart = -5.5555553;
psi->fAlphaVar = 0.77777779;
psi->sprite = mq;*/
}
switch(color){
case Constants::MTG_COLOR_RED :
psi->colColorStart.SetHWColor(ARGB(161,240,40,44));
psi->colColorEnd.SetHWColor(ARGB(14,242,155,153));
break;
case Constants::MTG_COLOR_BLUE :
psi->colColorStart.SetHWColor(ARGB(161,28,40,224));
psi->colColorEnd.SetHWColor(ARGB(14,255,255,255));
break;
case Constants::MTG_COLOR_GREEN :
psi->colColorStart.SetHWColor(ARGB(161,36,242,44));
psi->colColorEnd.SetHWColor(ARGB(14,129,244,153));
break;
case Constants::MTG_COLOR_BLACK :
psi->colColorStart.SetHWColor(ARGB(161,210,117,210));
psi->colColorEnd.SetHWColor(ARGB(14,80,56,80));
break;
case Constants::MTG_COLOR_WHITE :
psi->colColorStart.SetHWColor(ARGB(151,151,127,38));
psi->colColorEnd.SetHWColor(ARGB(8,255,255,255));
break;
default:
psi->colColorStart.SetHWColor(ARGB(161,236,242,232));
psi->colColorEnd.SetHWColor(ARGB(14,238,244,204));
break;
}
particleSys = NEW hgeParticleSystem(psi);
SAFE_DELETE(psi); //Not handled by cache, so kill it here.
}
else
particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later.
icon = manaIcons[color];
particleSys->FireAt(x, y);
@@ -59,6 +126,9 @@ ManaIcon::~ManaIcon()
void ManaIcon::Render()
{
if(!particleSys)
return;
JRenderer* renderer = JRenderer::GetInstance();
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);

File diff suppressed because it is too large Load Diff

View File

@@ -235,7 +235,6 @@ void OptionProfile::populate(){
renderer->BindTexture(mAvatarTex);
}
options.reloadProfile();
PlayerData * pdata = NEW PlayerData(app->collection);
options[Options::ACTIVE_PROFILE] = temp;
@@ -313,7 +312,8 @@ void OptionProfile::cancelSubmode()
options[Options::ACTIVE_PROFILE] = selections[initialValue];
value = initialValue;
populate();
options.reloadProfile(false);
populate();
bCheck = false;
}
void OptionProfile::acceptSubmode()
@@ -323,6 +323,7 @@ void OptionProfile::acceptSubmode()
options[Options::ACTIVE_PROFILE] = selections[value];
initialValue = value;
options.reloadProfile();
populate();
bCheck = false;
}
@@ -762,7 +763,7 @@ void OptionNewProfile::Update(float dt){
if(temp != value){
options[Options::ACTIVE_PROFILE] = value;
options.reloadProfile();
options.reloadProfile(false);
}
value = "";
bChanged = true;

View File

@@ -24,8 +24,8 @@ void Player::End(){
Player::~Player(){
SAFE_DELETE(manaPool);
SAFE_DELETE(mAvatarTex);
SAFE_DELETE(mAvatar);
resources.Release(mAvatar);
resources.Release(mAvatarTex);
}
const string Player::getDisplayName() const {
@@ -57,9 +57,11 @@ Player * Player::opponent(){
}
HumanPlayer::HumanPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) {
mAvatarTex = JRenderer::GetInstance()->LoadTexture(options.profileFile("avatar.jpg","player",true,true).c_str(), TEX_TYPE_USE_VRAM);
mAvatarTex = resources.RetrieveTexture("avatar.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
if (mAvatarTex)
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
mAvatar = resources.RetrieveQuad("avatar.jpg",0,0,35,50,"playerAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR);
else
mAvatar = NULL;
}
ManaPool * Player::getManaPool(){

View File

@@ -57,7 +57,13 @@ if (NULL == spadeL) spadeL = resources.RetrieveQuad("spade_ul.png", 2, 1, 16, 13
resources.LoadJLBFont("smallface", 7);
titleFont = resources.GetJLBFont("smallface");
}
if (NULL == stars) stars = NEW hgeParticleSystem("graphics/stars.psi", resources.GetQuad("stars"));
if (NULL == stars){
JQuad * starQuad = resources.GetQuad("stars");
hgeParticleSystemInfo * psi = resources.RetrievePSI("stars.psi", starQuad);
if(psi)
stars = NEW hgeParticleSystem(psi);
}
stars->MoveTo(mX, mY);
}

View File

@@ -12,10 +12,13 @@ TestSuiteAI::TestSuiteAI(TestSuite * _suite, int playerId):AIPlayer(_suite->buil
suite = _suite;
timer = 0;
humanMode = 0;
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
if (mAvatarTex){
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
}
mAvatarTex = resources.RetrieveTexture("baka.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
if(mAvatarTex)
mAvatar = resources.RetrieveQuad("baka.jpg", 0, 0, 35, 50,"bakaAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR);
else
mAvatar = NULL;
}
int TestSuite::getMTGId(string cardName){

View File

@@ -0,0 +1,387 @@
#include "../include/config.h"
#include "../include/utils.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <JGE.h>
#include <JFileSystem.h>
#include "../include/GameOptions.h"
#include "../include/WResourceManager.h"
//WResource
WResource::~WResource(){
return;
}
WResource::WResource(){
locks = WRES_UNLOCKED;
lastTime = resources.nowTime();
loadedMode = 0;
}
bool WResource::isLocked(){
return (locks != WRES_UNLOCKED);
}
bool WResource::isPermanent(){
return (locks == WRES_PERMANENT);
}
void WResource::deadbolt(){
if(locks <= WRES_MAX_LOCK)
locks = WRES_PERMANENT;
}
void WResource::lock(){
if(locks < WRES_MAX_LOCK)
locks++;
}
void WResource::unlock(bool force){
if(force)
locks = 0;
else if(locks > WRES_UNLOCKED && locks <= WRES_MAX_LOCK)
locks--;
}
void WResource::hit(){
lastTime = resources.nowTime();
}
//WCachedTexture
WCachedTexture::WCachedTexture(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached texture created.\n");
#endif
texture = NULL;
}
WCachedTexture::~WCachedTexture(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached texture destroyed.\n");
#endif
if(texture)
SAFE_DELETE(texture);
if(!trackedQuads.size())
return;
map<JQuad*,string>::iterator it, nit;
for(it=trackedQuads.begin();it!=trackedQuads.end();it=nit){
nit = it;
nit++;
trackedQuads.erase(it);
}
trackedQuads.clear();
}
JTexture * WCachedTexture::Actual(){
return texture;
}
bool WCachedTexture::ReleaseQuad(JQuad* quad){
#ifdef DEBUG_CACHE
OutputDebugString("Quad released.\n");
#endif
for(map<JQuad*,string>::iterator i = trackedQuads.begin();i!=trackedQuads.end();i++){
if(i->first == quad ){
unlock();
trackedQuads.erase(i);
return true;
}
}
return false;
}
JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){
if(texture == NULL)
return NULL;
JQuad * jq = NULL;
map<JQuad*,string>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
if(width == 0.0f || width > texture->mWidth)
width = texture->mWidth;
if(height == 0.0f || height > texture->mHeight)
height = texture->mHeight;
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){
jq = it->first;
}
}
if(jq == NULL){
jq = NEW JQuad(texture,offX,offY,width,height);
if(!jq) {
//Probably out of memory. Try again.
resources.Cleanup();
jq = NEW JQuad(texture,offX,offY,width,height);
}
if(!jq)
return NULL; //Probably a crash.
trackedQuads[jq] = resname;
return jq;
}else{
//Update JQ's values to what we called this with.
jq->SetTextureRect(offX,offY,width,height);
return jq;
}
return NULL;
}
JQuad * WCachedTexture::GetQuad(string resname){
map<JQuad*,string>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){
return it->first;
}
}
return NULL;
}
JQuad * WCachedTexture::GetCard(float offX, float offY, float width, float height, string resname){
JQuad * jq = GetQuad(offX,offY,width,height,resname);
if(jq)
jq->SetHotSpot(jq->mTex->mWidth / 2, jq->mTex->mHeight / 2);
return jq;
}
unsigned long WCachedTexture::size(){
if(!texture)
return 0;
return texture->mTexHeight*texture->mTexWidth;
}
bool WCachedTexture::isGood(){
if(!texture)
return false;
return true;
}
void WCachedTexture::Refresh(string filename){
int error = 0;
JTexture* old = texture;
texture = NULL;
if(!Attempt(filename,loadedMode, error))
SAFE_DELETE(texture);
if(!texture)
texture = old;
else
SAFE_DELETE(old);
for(map<JQuad*,string>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->first)
it->first->mTex = texture;
}
}
bool WCachedTexture::Attempt(string filename, int submode, int & error){
int format = TEXTURE_FORMAT;
loadedMode = submode;
string realname;
//Form correct filename.
if(submode & TEXTURE_SUB_CARD){
if(submode & TEXTURE_SUB_THUMB){
for(string::size_type i= 0;i < filename.size();i++){
if(filename[i] == '\\' || filename[i] == '/'){
filename.insert(i+1,"thumbnails/");
break;
}
}
}
realname = resources.cardFile(filename);
}
else{
if(submode & TEXTURE_SUB_THUMB)
filename.insert(0,"thumbnails/");
if(submode & TEXTURE_SUB_AVATAR)
realname = resources.avatarFile(filename);
else
realname = resources.graphicsFile(filename);
}
//Apply pixel mode
if(submode & TEXTURE_SUB_5551)
format = GU_PSM_5551;
//Use Vram?
if(submode & TEXTURE_SUB_VRAM){
texture = JRenderer::GetInstance()->LoadTexture(realname.c_str(),TEX_TYPE_USE_VRAM,format);
}
else
texture = JRenderer::GetInstance()->LoadTexture(realname.c_str(),TEX_TYPE_NORMAL,format);
//Failure.
if(!texture){
if(!fileExists(realname.c_str()))
error = CACHE_ERROR_404;
return false;
}
//Failure of a different sort.
if(texture->mTexId == -1){
SAFE_DELETE(texture);
error = CACHE_ERROR_BAD;
return false;
}
error = CACHE_ERROR_NONE;
return true;
}
void WCachedTexture::Nullify(){
if(texture)
texture = NULL;
}
//WCachedSample
void WCachedSample::Nullify(){
if(sample){
sample = NULL;
}
}
WCachedSample::WCachedSample(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached sample created.\n");
#endif
sample = NULL;
}
WCachedSample::~WCachedSample(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached sample destroyed.\n");
#endif
SAFE_DELETE(sample);
}
JSample * WCachedSample::Actual(){
return sample;
}
unsigned long WCachedSample::size(){
if(!sample || !sample->mSample)
return 0;
#if defined WIN32 || defined LINUX
return FSOUND_Sample_GetLength(sample->mSample);
#else
return sample->mSample->fileSize;
#endif
}
bool WCachedSample::isGood(){
if(!sample || !sample->mSample)
return false;
return true;
}
void WCachedSample::Refresh(string filename){
return;
}
bool WCachedSample::Attempt(string filename, int submode, int & error){
loadedMode = submode;
sample = JSoundSystem::GetInstance()->LoadSample(resources.sfxFile(filename).c_str());
if(!isGood()){
SAFE_DELETE(sample);
if(!fileExists(filename.c_str()))
error = CACHE_ERROR_404;
else
error = CACHE_ERROR_BAD;
return false;
}
return true;
}
//WCachedParticles
bool WCachedParticles::isGood(){
if(!particles)
return false;
return true;
}
unsigned long WCachedParticles::size(){
if(!particles)
return 0; //Sizeof(pointer)
return sizeof(hgeParticleSystemInfo);
}
//Only effects future particle systems, of course.
void WCachedParticles::Refresh(string filename){
hgeParticleSystemInfo * old = particles;
int error = 0;
Attempt(filename,loadedMode,error);
if(isGood())
SAFE_DELETE(old);
else{
SAFE_DELETE(particles);
particles = old;
}
return;
}
bool WCachedParticles::Attempt(string filename, int submode, int & error){
JFileSystem* fileSys = JFileSystem::GetInstance();
if(!fileSys->OpenFile(resources.graphicsFile(filename))){
error = CACHE_ERROR_404;
return false;
}
SAFE_DELETE(particles);
particles = NEW hgeParticleSystemInfo;
fileSys->ReadFile(particles, sizeof(hgeParticleSystemInfo));
fileSys->CloseFile();
particles->sprite=NULL;
error = CACHE_ERROR_NONE;
return true;
}
hgeParticleSystemInfo * WCachedParticles::Actual(){
return particles;
}
WCachedParticles::WCachedParticles(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached particles created.\n");
#endif
particles = NULL;
}
WCachedParticles::~WCachedParticles(){
#ifdef DEBUG_CACHE
OutputDebugString("Cached particles destroyed.\n");
#endif
SAFE_DELETE(particles);
}
void WCachedParticles::Nullify(){
if(particles)
particles = NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -556,6 +556,10 @@
RelativePath=".\src\WEvent.cpp"
>
</File>
<File
RelativePath=".\src\WCachedResource.cpp"
>
</File>
<File
RelativePath=".\src\WResourceManager.cpp"
>
@@ -909,6 +913,10 @@
RelativePath=".\include\WResourceManager.h"
>
</File>
<File
RelativePath=".\include\WCachedResource.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"