mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
fs: buffer Fugue writes through RAM
Writing from ROM causes occasional crashes, which are fairly hard to produce when the buffers are small.
This commit is contained in:
parent
d6ada7f11f
commit
227c06631b
3 changed files with 88 additions and 6 deletions
|
@ -10,6 +10,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include <gint/mpu/mmu.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//---
|
||||
// Unified interface
|
||||
|
@ -40,6 +41,17 @@ void *mmu_uram(void);
|
|||
fx-9860G, and 512k on fx-CG 50. */
|
||||
uint32_t mmu_uram_size(void);
|
||||
|
||||
/* mmu_is_rom(): Determine if an address points to ROM
|
||||
|
||||
Checks whether the supplied pointer points to ROM or to a virtualized
|
||||
portion of ROM. For the sake of efficiency, this function uses heuristics
|
||||
about the structure of P0 rather than actually checking the TLB.
|
||||
|
||||
This is useful during filesystem accesses because only data outside of ROM
|
||||
can be written to files. Pointers for which this function returns true
|
||||
cannot be used as a source for BFile_Write(). */
|
||||
bool mmu_is_rom(void const *ptr);
|
||||
|
||||
//---
|
||||
// SH7705 TLB
|
||||
//---
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <gint/fs.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/bfile.h>
|
||||
#include <gint/mmu.h>
|
||||
#include <gint/defs/util.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "fugue.h"
|
||||
|
@ -26,18 +28,71 @@ ssize_t fugue_read(void *data0, void *buf, size_t size)
|
|||
return size;
|
||||
}
|
||||
|
||||
static void *temp_ram(size_t total_size, size_t *block_size)
|
||||
{
|
||||
for(size_t candidate = 16384; candidate >= 64; candidate >>= 1) {
|
||||
if(candidate > 64 && candidate >= 2 * total_size)
|
||||
continue;
|
||||
|
||||
size_t size = min(candidate, total_size);
|
||||
void *ram = malloc(size);
|
||||
if(ram) {
|
||||
*block_size = size;
|
||||
return ram;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssize_t fugue_write(void *data0, const void *buf, size_t size)
|
||||
{
|
||||
fugue_fd_t *data = data0;
|
||||
int fugue_fd = data->fd;
|
||||
|
||||
int rc = BFile_Write(fugue_fd, buf, size);
|
||||
if(rc < 0) {
|
||||
errno = bfile_error_to_errno(rc);
|
||||
return -1;
|
||||
/* The main concern of this function is that we cannot write from ROM.
|
||||
If [buf] is in ROM then we have to copy it to RAM, preferably within
|
||||
the limits of available heap memory. */
|
||||
if(mmu_is_rom(buf)) {
|
||||
size_t alloc_size, written=0;
|
||||
|
||||
void *ram = temp_ram(size, &alloc_size);
|
||||
if(!ram) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(written < size) {
|
||||
size_t block_size = min(size - written, alloc_size);
|
||||
memcpy(ram, buf + written, block_size);
|
||||
|
||||
int rc = BFile_Write(fugue_fd, ram, block_size);
|
||||
if(rc < 0) {
|
||||
errno = bfile_error_to_errno(rc);
|
||||
written = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
written += rc;
|
||||
data->pos += rc;
|
||||
|
||||
/* Partial write */
|
||||
if(rc < (int)block_size) break;
|
||||
}
|
||||
|
||||
free(ram);
|
||||
return written;
|
||||
}
|
||||
/* Otherwise, we can write normally */
|
||||
else {
|
||||
int rc = BFile_Write(fugue_fd, buf, size);
|
||||
if(rc < 0) {
|
||||
errno = bfile_error_to_errno(rc);
|
||||
return -1;
|
||||
}
|
||||
data->pos += rc;
|
||||
return rc;
|
||||
}
|
||||
data->pos += rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
off_t fugue_lseek(void *data0, off_t offset, int whence)
|
||||
|
|
|
@ -38,6 +38,21 @@ uint32_t mmu_uram_size(void)
|
|||
return size;
|
||||
}
|
||||
|
||||
/* mmu_is_rom(): Determine if an address points to ROM */
|
||||
bool mmu_is_rom(void const *ptr)
|
||||
{
|
||||
uint32_t a = (uint32_t)ptr;
|
||||
|
||||
if(a >= 0x80000000 && a < 0x88000000)
|
||||
return true;
|
||||
if(a >= 0xa0000000 && a < 0xa8000000)
|
||||
return true;
|
||||
if(a >= 0x00300000 && a < 0x00800000)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---
|
||||
// SH7705 TLB
|
||||
//---
|
||||
|
|
Loading…
Reference in a new issue