mirror of https://github.com/mgba-emu/mgba.git
VFS: Use anonymousMemoryMap for large 7z allocations (fixes #3013)
This commit is contained in:
parent
45387aa663
commit
d83b2f99cd
1
CHANGES
1
CHANGES
|
@ -47,6 +47,7 @@ Misc:
|
||||||
- Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887)
|
- Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887)
|
||||||
- Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632)
|
- Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632)
|
||||||
- Scripting: Add `callbacks:oneshot` for single-call callbacks
|
- Scripting: Add `callbacks:oneshot` for single-call callbacks
|
||||||
|
- VFS: Use anonymousMemoryMap for large 7z allocations (fixes mgba.io/i/3013)
|
||||||
|
|
||||||
0.10.2: (2023-04-23)
|
0.10.2: (2023-04-23)
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
#ifdef USE_LZMA
|
#ifdef USE_LZMA
|
||||||
|
|
||||||
|
#include <mgba-util/memory.h>
|
||||||
#include <mgba-util/string.h>
|
#include <mgba-util/string.h>
|
||||||
|
#include <mgba-util/table.h>
|
||||||
|
|
||||||
#include "third-party/lzma/7z.h"
|
#include "third-party/lzma/7z.h"
|
||||||
#include "third-party/lzma/7zAlloc.h"
|
#include "third-party/lzma/7zAlloc.h"
|
||||||
|
@ -26,15 +28,19 @@ struct VDirEntry7z {
|
||||||
char* utf8;
|
char* utf8;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VDir7zAlloc {
|
||||||
|
ISzAlloc d;
|
||||||
|
struct Table allocs;
|
||||||
|
};
|
||||||
|
|
||||||
struct VDir7z {
|
struct VDir7z {
|
||||||
struct VDir d;
|
struct VDir d;
|
||||||
struct VDirEntry7z dirent;
|
struct VDirEntry7z dirent;
|
||||||
|
|
||||||
// What is all this garbage?
|
|
||||||
CFileInStream archiveStream;
|
CFileInStream archiveStream;
|
||||||
CLookToRead2 lookStream;
|
CLookToRead2 lookStream;
|
||||||
CSzArEx db;
|
CSzArEx db;
|
||||||
ISzAlloc allocImp;
|
struct VDir7zAlloc allocImp;
|
||||||
ISzAlloc allocTempImp;
|
ISzAlloc allocTempImp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,6 +76,43 @@ static bool _vd7zDeleteFile(struct VDir* vd, const char* path);
|
||||||
static const char* _vde7zName(struct VDirEntry* vde);
|
static const char* _vde7zName(struct VDirEntry* vde);
|
||||||
static enum VFSType _vde7zType(struct VDirEntry* vde);
|
static enum VFSType _vde7zType(struct VDirEntry* vde);
|
||||||
|
|
||||||
|
static void* _vd7zAlloc(ISzAllocPtr p, size_t size) {
|
||||||
|
struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p;
|
||||||
|
void* address;
|
||||||
|
if (size >= 0x10000) {
|
||||||
|
address = anonymousMemoryMap(size);
|
||||||
|
} else {
|
||||||
|
address = malloc(size);
|
||||||
|
}
|
||||||
|
if (address) {
|
||||||
|
TableInsert(&alloc->allocs, (uintptr_t) address >> 2, (void*) size);
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _vd7zFree(ISzAllocPtr p, void* address) {
|
||||||
|
struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p;
|
||||||
|
size_t size = (size_t) TableLookup(&alloc->allocs, (uintptr_t) address >> 2);
|
||||||
|
if (size) {
|
||||||
|
if (size >= 0x10000) {
|
||||||
|
mappedMemoryFree(address, size);
|
||||||
|
} else {
|
||||||
|
free(address);
|
||||||
|
}
|
||||||
|
TableRemove(&alloc->allocs, (uintptr_t) address >> 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* _vd7zAllocTemp(ISzAllocPtr p, size_t size) {
|
||||||
|
UNUSED(p);
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _vd7zFreeTemp(ISzAllocPtr p, void* address) {
|
||||||
|
UNUSED(p);
|
||||||
|
free(address);
|
||||||
|
}
|
||||||
|
|
||||||
struct VDir* VDirOpen7z(const char* path, int flags) {
|
struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||||
if (flags & O_WRONLY || flags & O_CREAT) {
|
if (flags & O_WRONLY || flags & O_CREAT) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,11 +126,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vd->allocImp.Alloc = SzAlloc;
|
vd->allocImp.d.Alloc = _vd7zAlloc;
|
||||||
vd->allocImp.Free = SzFree;
|
vd->allocImp.d.Free = _vd7zFree;
|
||||||
|
TableInit(&vd->allocImp.allocs, 0, NULL);
|
||||||
|
|
||||||
vd->allocTempImp.Alloc = SzAllocTemp;
|
vd->allocTempImp.Alloc = _vd7zAllocTemp;
|
||||||
vd->allocTempImp.Free = SzFreeTemp;
|
vd->allocTempImp.Free = _vd7zFreeTemp;
|
||||||
|
|
||||||
FileInStream_CreateVTable(&vd->archiveStream);
|
FileInStream_CreateVTable(&vd->archiveStream);
|
||||||
LookToRead2_CreateVTable(&vd->lookStream, False);
|
LookToRead2_CreateVTable(&vd->lookStream, False);
|
||||||
|
@ -101,11 +145,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||||
CrcGenerateTable();
|
CrcGenerateTable();
|
||||||
|
|
||||||
SzArEx_Init(&vd->db);
|
SzArEx_Init(&vd->db);
|
||||||
SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp, &vd->allocTempImp);
|
SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp.d, &vd->allocTempImp);
|
||||||
if (res != SZ_OK) {
|
if (res != SZ_OK) {
|
||||||
SzArEx_Free(&vd->db, &vd->allocImp);
|
SzArEx_Free(&vd->db, &vd->allocImp.d);
|
||||||
File_Close(&vd->archiveStream.file);
|
File_Close(&vd->archiveStream.file);
|
||||||
free(vd->lookStream.buf);
|
free(vd->lookStream.buf);
|
||||||
|
TableDeinit(&vd->allocImp.allocs);
|
||||||
free(vd);
|
free(vd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +173,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||||
|
|
||||||
bool _vf7zClose(struct VFile* vf) {
|
bool _vf7zClose(struct VFile* vf) {
|
||||||
struct VFile7z* vf7z = (struct VFile7z*) vf;
|
struct VFile7z* vf7z = (struct VFile7z*) vf;
|
||||||
IAlloc_Free(&vf7z->vd->allocImp, vf7z->outBuffer);
|
IAlloc_Free(&vf7z->vd->allocImp.d, vf7z->outBuffer);
|
||||||
free(vf7z);
|
free(vf7z);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -215,12 +260,13 @@ ssize_t _vf7zSize(struct VFile* vf) {
|
||||||
|
|
||||||
bool _vd7zClose(struct VDir* vd) {
|
bool _vd7zClose(struct VDir* vd) {
|
||||||
struct VDir7z* vd7z = (struct VDir7z*) vd;
|
struct VDir7z* vd7z = (struct VDir7z*) vd;
|
||||||
SzArEx_Free(&vd7z->db, &vd7z->allocImp);
|
SzArEx_Free(&vd7z->db, &vd7z->allocImp.d);
|
||||||
File_Close(&vd7z->archiveStream.file);
|
File_Close(&vd7z->archiveStream.file);
|
||||||
|
|
||||||
free(vd7z->lookStream.buf);
|
free(vd7z->lookStream.buf);
|
||||||
free(vd7z->dirent.utf8);
|
free(vd7z->dirent.utf8);
|
||||||
vd7z->dirent.utf8 = 0;
|
vd7z->dirent.utf8 = 0;
|
||||||
|
TableDeinit(&vd7z->allocImp.allocs);
|
||||||
|
|
||||||
free(vd7z);
|
free(vd7z);
|
||||||
return true;
|
return true;
|
||||||
|
@ -292,7 +338,7 @@ struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode) {
|
||||||
SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.vt, i, &blockIndex,
|
SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.vt, i, &blockIndex,
|
||||||
&vf->outBuffer, &outBufferSize,
|
&vf->outBuffer, &outBufferSize,
|
||||||
&vf->bufferOffset, &vf->size,
|
&vf->bufferOffset, &vf->size,
|
||||||
&vd7z->allocImp, &vd7z->allocTempImp);
|
&vd7z->allocImp.d, &vd7z->allocTempImp);
|
||||||
|
|
||||||
if (res != SZ_OK) {
|
if (res != SZ_OK) {
|
||||||
free(vf);
|
free(vf);
|
||||||
|
|
Loading…
Reference in New Issue