fix for wrapping artefact when display_mode=ALWAYS
[open-ps2-loader.git] / src / texcache.c
blob4f98cb4a8a62915e474df9107d7f2eb8c1bfee41
1 #include "include/texcache.h"
2 #include "include/ioman.h"
3 #include "include/gui.h"
4 #include "include/util.h"
6 // io call to handle the loading of covers
7 #define IO_CACHE_LOAD_ART 3
9 typedef struct {
10 image_cache_t* cache;
11 cache_entry_t* entry;
12 item_list_t* list;
13 // only for comparison if the deferred action is still valid
14 int cacheUID;
15 char* value;
16 } load_image_request_t;
18 // Io handled action...
19 static void cacheLoadImage(void* data) {
20 load_image_request_t* req = data;
22 // Safeguards...
23 if (!req || !req->entry || !req->cache)
24 return;
26 item_list_t* handler = req->list;
27 if (!handler)
28 return;
30 // the cache entry was already reused!
31 if (req->cacheUID != req->entry->UID)
32 return;
34 // seems okay. we can proceed
35 GSTEXTURE* texture = &req->entry->texture;
36 if(texture->Mem != NULL) {
37 free(texture->Mem);
38 texture->Mem = NULL;
39 texture->ClutPSM = 0;
40 texture->Clut = NULL;
41 texture->Vram = 0;
42 texture->VramClut = 0;
45 if (handler->itemGetImage(req->cache->prefix, req->cache->isPrefixRelative, req->value, req->cache->suffix, texture, GS_PSM_CT24) < 0)
46 req->entry->lastUsed = 0;
47 else
48 req->entry->lastUsed = guiFrameId;
50 req->entry->qr = NULL;
52 free(req);
55 void cacheInit() {
56 ioRegisterHandler(IO_CACHE_LOAD_ART, &cacheLoadImage);
59 void cacheEnd() {
60 // nothing to do... others have to destroy the cache via cacheDestroyCache
63 static void cacheClearItem(cache_entry_t* item, int freeTxt) {
64 if (freeTxt && item->texture.Mem)
65 free(item->texture.Mem);
67 memset(item, 0, sizeof(cache_entry_t));
68 item->texture.Mem = NULL;
69 item->texture.Vram = 0;
70 item->texture.Clut = 0;
71 item->texture.VramClut = 0;
72 item->qr = NULL;
73 item->lastUsed = -1;
74 item->UID = 0;
77 image_cache_t* cacheInitCache(int userId, char* prefix, int isPrefixRelative, char* suffix, int count) {
78 image_cache_t* cache = (image_cache_t*) malloc(sizeof(image_cache_t));
79 cache->userId = userId;
80 cache->count = count;
81 int length = strlen(prefix) + 1;
82 cache->prefix = (char*) malloc(length * sizeof(char));
83 memcpy(cache->prefix, prefix, length);
84 cache->isPrefixRelative = isPrefixRelative;
85 length = strlen(suffix) + 1;
86 cache->suffix = (char*) malloc(length * sizeof(char));
87 memcpy(cache->suffix, suffix, length);
88 cache->nextUID = 1;
89 cache->content = (cache_entry_t*) malloc(count * sizeof(cache_entry_t));
91 int i;
92 for (i = 0; i < count; ++i)
93 cacheClearItem(&cache->content[i], 0);
95 return cache;
98 void cacheDestroyCache(image_cache_t* cache) {
99 int i;
100 for (i = 0; i < cache->count; ++i) {
101 cacheClearItem(&cache->content[i], 1);
104 free(cache->prefix);
105 free(cache->suffix);
106 free(cache->content);
107 free(cache);
110 GSTEXTURE* cacheGetTexture(image_cache_t* cache, item_list_t* list, int* cacheId, int* UID, char* value) {
111 if (*cacheId == -2) {
112 return NULL;
113 } else if (*cacheId != -1) {
114 cache_entry_t* entry = &cache->content[*cacheId];
115 if (entry->UID == *UID) {
116 if (entry->qr)
117 return NULL;
118 else if (entry->lastUsed == 0) {
119 *cacheId = -2;
120 return NULL;
121 } else {
122 entry->lastUsed = guiFrameId;
123 return &entry->texture;
127 *cacheId = -1;
130 // under the cache pre-delay (to avoid filling cache while moving around)
131 if (guiInactiveFrames < list->delay)
132 return NULL;
134 cache_entry_t *currEntry, *oldestEntry = NULL;
135 int i, rtime = guiFrameId;
137 for (i = 0; i < cache->count; i++) {
138 currEntry = &cache->content[i];
139 if ((!currEntry->qr) && (currEntry->lastUsed < rtime)) {
140 oldestEntry = currEntry;
141 rtime = currEntry->lastUsed;
142 *cacheId = i;
146 if (oldestEntry) {
147 load_image_request_t* req = malloc(sizeof(load_image_request_t));
148 req->cache = cache;
149 req->entry = oldestEntry;
150 req->list = list;
151 req->value = value;
152 req->cacheUID = cache->nextUID;
154 cacheClearItem(oldestEntry, 1);
155 oldestEntry->qr = req;
156 oldestEntry->UID = cache->nextUID;
158 *UID = cache->nextUID++;
160 ioPutRequest(IO_CACHE_LOAD_ART, req);
163 return NULL;