118 lines
3.1 KiB
C
118 lines
3.1 KiB
C
#include "segmentsFile.h"
|
|
#include "../common/platform.h"
|
|
|
|
void fileSegmentInit(file_segment_t *segment, int fd, int pos, int len, char access) {
|
|
//set basic information
|
|
segment->fd=fd;
|
|
segment->access=access;
|
|
segment->filePos=pos;
|
|
|
|
//enable caching one PC
|
|
#if defined(PC)
|
|
segment->cacheOff=-1;
|
|
segment->cacheLen=0;
|
|
segment->cacheWritten=0;
|
|
#endif
|
|
|
|
//enlarge the file if needed
|
|
int fileSize=File_length(fd);
|
|
if(fileSize+pos<len&&(access&MMU_ACCESS_w)) {
|
|
if(File_truncate(fd, len+pos)) fileSize=len+pos;
|
|
}
|
|
segment->fileSize=fileSize;
|
|
}
|
|
|
|
//enable cache on PC
|
|
#if defined(PC)
|
|
void fileSegmentRead(int pos, char* value, void *opaque) {
|
|
//get the segment information
|
|
file_segment_t *segment=(file_segment_t*) opaque;
|
|
|
|
//make sure we have cache for this
|
|
if(!fileSegmentLoad(segment, pos)) return;
|
|
if(pos<segment->cacheOff||pos>=segment->cacheOff+segment->cacheLen) return;
|
|
|
|
//read from cache
|
|
*value=segment->cache[pos-segment->cacheOff];
|
|
}
|
|
|
|
void fileSegmentWrite(int pos, char value, void *opaque) {
|
|
//get the segment information
|
|
file_segment_t *segment=(file_segment_t*) opaque;
|
|
|
|
//make sure we have cache for this
|
|
if(!fileSegmentLoad(segment, pos)) return;
|
|
if(pos<segment->cacheOff||pos>=segment->cacheOff+segment->cacheLen) return;
|
|
|
|
//write to cache
|
|
segment->cache[pos-segment->cacheOff]=value;
|
|
segment->cacheWritten=1;
|
|
}
|
|
|
|
int fileSegmentFlush(file_segment_t *segment) {
|
|
//check if we have write access and we have an actual cache
|
|
if(!(segment->access&MMU_ACCESS_w)) return 0;
|
|
if(segment->cacheOff==-1||segment->cacheLen==0) return 1;
|
|
|
|
//check if we have written
|
|
if(!segment->cacheWritten) return 1;
|
|
|
|
//flush to disk
|
|
return File_write(segment->fd, segment->cacheOff+segment->filePos, segment->cache, segment->cacheLen);
|
|
}
|
|
|
|
int fileSegmentLoad(file_segment_t *segment, int pos) {
|
|
//determine the aligned offset, and don't load if it's already loaded
|
|
pos-=pos/CACHE_LEN;
|
|
if(segment->cacheOff==pos) return 1;
|
|
|
|
//determine length to cache
|
|
int len=CACHE_LEN;
|
|
if(pos+len+segment->filePos>segment->fileSize) len=segment->fileSize-pos;
|
|
|
|
//flush if we need to
|
|
if(segment->access&MMU_ACCESS_w) {
|
|
if(!fileSegmentFlush(segment)) return 0;
|
|
}
|
|
|
|
//invalidate the cache
|
|
segment->cacheOff=-1;
|
|
segment->cacheLen=0;
|
|
|
|
//read the file
|
|
len=File_read(segment->fd, pos+segment->filePos, segment->cache, len);
|
|
|
|
//update the cache
|
|
segment->cacheOff=pos;
|
|
segment->cacheLen=len;
|
|
segment->cacheWritten=0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//direct access to underlying file cache on casio
|
|
#else
|
|
void fileSegmentRead(int pos, char* value, void *opaque) {
|
|
//get the segment information
|
|
file_segment_t *segment=(file_segment_t*) opaque;
|
|
|
|
//get offset into disk
|
|
int offset=pos+segment->filePos;
|
|
|
|
//read from file, the file will check for access itself
|
|
File_read(segment->fd, offset, value, 1);
|
|
}
|
|
|
|
void fileSegmentWrite(int pos, char value, void *opaque) {
|
|
//get the segment information
|
|
file_segment_t *segment=(file_segment_t*) opaque;
|
|
|
|
//get offset into disk
|
|
int offset=pos+segment->filePos;
|
|
|
|
//write into file, the file will check for access itself
|
|
File_write(segment->fd, offset, &value, 1);
|
|
}
|
|
|
|
#endif
|