MuckyFoot-UrbanChaos/fallen/Source/cache.cpp
2017-05-20 11:14:17 +10:00

265 lines
3.8 KiB
C++

//
// A cache designed for storing light info.
//
#include "game.h"
#include <MFStdLib.h>
#include "cache.h"
#include "heap.h"
#include "c:/fallen/ddengine/headers/message.h"
//
// All the cache entries.
//
#define CACHE_FLAG_VALID (1 << 0)
#define CACHE_FLAG_FLAGGED (1 << 1)
typedef struct
{
void *data;
SLONG key;
UWORD num_bytes;
UBYTE flag;
CACHE_Index next;
} CACHE_Entry;
#define CACHE_MAX_ENTRIES 128
CACHE_Entry CACHE_entry[CACHE_MAX_ENTRIES];
CACHE_Index CACHE_free;
void CACHE_init()
{
SLONG i;
//
// Build the free list.
//
CACHE_free = 1;
for (i = 1; i < CACHE_MAX_ENTRIES - 1; i++)
{
CACHE_entry[i].flag = 0;
CACHE_entry[i].next = i + 1;
}
CACHE_entry[CACHE_MAX_ENTRIES - 1].flag = 0;
CACHE_entry[CACHE_MAX_ENTRIES - 1].next = 0;
}
CACHE_Index CACHE_create(
SLONG key,
void *data,
UWORD num_bytes)
{
void *heap;
CACHE_Index c_index;
CACHE_Entry *ce;
if (CACHE_free == NULL)
{
//
// Oh dear! Pick a random cache entry and overwrite that!
//
c_index = Random() & (CACHE_MAX_ENTRIES - 1);
}
else
{
ASSERT(WITHIN(CACHE_free, 1, CACHE_MAX_ENTRIES - 1));
//
// Take a cache element of the top of the linked list.
//
c_index = CACHE_free;
CACHE_free = CACHE_entry[CACHE_free].next;
}
ce = &CACHE_entry[c_index];
//
// Get some memory from the heap.
//
heap = HEAP_get(num_bytes);
if (heap == NULL)
{
//
// We can't cache the light info.
//
// MSG_add("No more heap!");
return NULL;
}
else
{
ce->flag = CACHE_FLAG_VALID | CACHE_FLAG_FLAGGED;
ce->key = key;
ce->data = heap;
ce->num_bytes = num_bytes;
ce->next = NULL;
//
// Copy the data into the heap.
//
memcpy(heap, data, num_bytes);
return c_index;
}
}
SLONG CACHE_is_valid(CACHE_Index c_index)
{
if (WITHIN(c_index, 1, CACHE_MAX_ENTRIES - 1))
{
if (CACHE_entry[c_index].flag & CACHE_FLAG_VALID)
{
return TRUE;
}
}
return FALSE;
}
CACHE_Info CACHE_get_info(CACHE_Index c_index)
{
CACHE_Info ans;
ASSERT(WITHIN(c_index, 1, CACHE_MAX_ENTRIES - 1));
ans.key = CACHE_entry[c_index].key;
ans.data = CACHE_entry[c_index].data;
ans.num_bytes = CACHE_entry[c_index].num_bytes;
return ans;
}
void CACHE_invalidate(CACHE_Index c_index)
{
CACHE_Entry *ce;
ASSERT(WITHIN(c_index, 1, CACHE_MAX_ENTRIES - 1));
ce = &CACHE_entry[c_index];
if (ce->flag & CACHE_FLAG_VALID)
{
//
// Invalidate it.
//
ce->flag &= ~CACHE_FLAG_VALID;
//
// Return the heap memory.
//
HEAP_give(ce->data, ce->num_bytes);
//
// Add it to the free list.
//
ce->next = CACHE_free;
CACHE_free = c_index;
}
}
void CACHE_invalidate_all()
{
SLONG i;
CACHE_Entry *ce;
for (i = 1; i < CACHE_MAX_ENTRIES; i++)
{
ce = &CACHE_entry[i];
if (ce->flag & CACHE_FLAG_VALID)
{
//
// Invalidate it.
//
ce->flag &= ~CACHE_FLAG_VALID;
//
// Return the heap memory.
//
HEAP_give(ce->data, ce->num_bytes);
//
// Add it to the free list.
//
ce->next = CACHE_free;
CACHE_free = i;
}
}
}
void CACHE_flag_clear_all()
{
SLONG i;
for (i = 1; i < CACHE_MAX_ENTRIES; i++)
{
CACHE_entry[i].flag &= ~CACHE_FLAG_FLAGGED;
}
}
void CACHE_flag_set(CACHE_Index c_index)
{
ASSERT(WITHIN(c_index, 1, CACHE_MAX_ENTRIES - 1));
CACHE_entry[c_index].flag |= CACHE_FLAG_FLAGGED;
}
void CACHE_flag_clear(CACHE_Index c_index)
{
ASSERT(WITHIN(c_index, 1, CACHE_MAX_ENTRIES - 1));
CACHE_entry[c_index].flag &= ~CACHE_FLAG_FLAGGED;
}
void CACHE_invalidate_unflagged()
{
SLONG i;
for (i = 1; i < CACHE_MAX_ENTRIES; i++)
{
if (!(CACHE_entry[i].flag & CACHE_FLAG_FLAGGED) && (CACHE_entry[i].flag & CACHE_FLAG_VALID))
{
//
// Invalidate this cache entry.
//
// MSG_add("Invalidating an unflagged cache element.");
CACHE_invalidate(i);
}
}
}