Casio_asm/interpreter/segmentsFile.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