blob: 483f3ca1a06b164ee4c69d995686587564abc657 [file]
/*
* cache.cpp - simple floppy/cd cache for Win32
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* Windows platform specific code copyright (C) Lauri Pesonen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Note that this is particularly silly cache code
and doesn't even use hash buckets. It is sufficient
for floppies and maybe emulated cd's but that's it.
*/
#include "sysdeps.h"
#include "cache.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void cache_clear( cachetype *cptr )
{
if(cptr->inited) {
cptr->res_count = 0;
memset( cptr->LRU, 0, NBLOCKS * sizeof(int) );
}
}
static int init( cachetype *cptr, int sector_size )
{
cache_clear( cptr );
cptr->sector_size = sector_size;
cptr->blocks = (char *)VirtualAlloc(
NULL, NBLOCKS*sector_size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
cptr->block = (int *)VirtualAlloc(
NULL, NBLOCKS*sizeof(int),
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
cptr->LRU = (DWORD *)VirtualAlloc(
NULL, NBLOCKS*sizeof(DWORD),
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
return(cptr->blocks != NULL);
}
static void final( cachetype *cptr )
{
if(cptr->blocks) {
VirtualFree( cptr->blocks, 0, MEM_RELEASE );
cptr->blocks = 0;
}
if(cptr->block) {
VirtualFree( cptr->block, 0, MEM_RELEASE );
cptr->block = 0;
}
if(cptr->LRU) {
VirtualFree( cptr->LRU, 0, MEM_RELEASE );
cptr->LRU = 0;
}
cptr->inited = 0;
}
void cache_init( cachetype *cptr )
{
cptr->inited = 0;
}
void cache_final( cachetype *cptr )
{
if(cptr->inited) {
final( cptr );
cptr->inited = 0;
}
}
static int in_cache( cachetype *cptr, int block )
{
int i;
for(i=cptr->res_count-1; i>=0; i--) {
if(cptr->block[i] == block) return(i);
}
return(-1);
}
static int get_LRU( cachetype *cptr )
{
int i, result = 0;
DWORD mtime = cptr->LRU[0];
for(i=1; i<NBLOCKS; i++) {
if(cptr->LRU[i] < mtime) {
mtime = cptr->LRU[i];
result = i;
}
}
return(result);
}
void cache_put( cachetype *cptr, int block, char *buf, int ss )
{
int inx;
if(!cptr->inited) {
if(!init(cptr,ss)) return;
cptr->inited = 1;
}
inx = in_cache( cptr, block );
if(inx < 0) {
if(cptr->res_count == NBLOCKS) {
inx = get_LRU( cptr );
} else {
inx = cptr->res_count++;
}
cptr->block[inx] = block;
}
cptr->LRU[inx] = GetTickCount();
memcpy( cptr->blocks + inx * ss, buf, ss );
}
int cache_get( cachetype *cptr, int block, char *buf )
{
int inx;
if(!cptr->inited) return(0);
inx = in_cache( cptr, block );
if(inx >= 0) {
memcpy( buf, cptr->blocks + inx * cptr->sector_size, cptr->sector_size );
return(1);
} else {
return(0);
}
}
void cache_remove( cachetype *cptr, int block, int ss )
{
int inx, from;
if(!cptr->inited) {
if(!init(cptr,ss)) return;
cptr->inited = 1;
}
inx = in_cache( cptr, block );
if(inx >= 0) {
if(cptr->res_count > 1) {
from = cptr->res_count-1;
cptr->block[inx] = cptr->block[from];
cptr->LRU[inx] = cptr->LRU[from];
memcpy(
cptr->blocks + inx * cptr->sector_size,
cptr->blocks + from * cptr->sector_size,
cptr->sector_size
);
}
cptr->res_count--;
}
}
#ifdef __cplusplus
} // extern "C"
#endif