Use more mmap, per #10

This commit is contained in:
Alcaro
2018-04-21 11:16:03 +02:00
parent 48296c681d
commit 2cc9e855b8
5 changed files with 138 additions and 24 deletions

View File

@@ -8,6 +8,7 @@
#ifdef FLIPS_CLI
file* file::create(const char * filename) { return file::create_libc(filename); }
filewrite* filewrite::create(const char * filename) { return filewrite::create_libc(filename); }
filemap* filemap::create(const char * filename) { return filemap::create_fallback(filename); }
int main(int argc, char * argv[])

View File

@@ -92,6 +92,32 @@ filewrite* filewrite::create(const char * filename)
}
class filemap_gtk : public filemap {
public:
GMappedFile* mapfile;
static filemap* create(const char * filename)
{
GMappedFile* mapfile = g_mapped_file_new(filename, false, NULL);
if (!mapfile) return NULL;
return new filemap_gtk(mapfile);
}
filemap_gtk(GMappedFile* mapfile) : mapfile(mapfile) {}
size_t len() { return g_mapped_file_get_length(mapfile); }
const uint8_t * ptr() { return (uint8_t*)g_mapped_file_get_contents(mapfile); }
~filemap_gtk() { g_mapped_file_unref(mapfile); }
};
filemap* filemap::create(const char * filename)
{
filemap* ret = filemap_gtk::create(filename);
if (!ret) ret = filemap::create_fallback(filename);
return ret;
}
static bool canShowGUI;
static GtkWidget* window;
@@ -480,13 +506,14 @@ static void a_ApplyPatch(GtkButton* widget, gpointer user_data)
if (!inromname) return;
state.romext=GetExtension(inromname);
if (!*state.romext) state.romext=".sfc";
state.rommem=ReadWholeFile(inromname);
filemap* map=filemap::create(inromname);
state.rommem=map->get();
state.removeHeaders=shouldRemoveHeader(inromname, state.rommem.len);
state.worsterror=e_none;
state.anySuccess=false;
g_slist_foreach(filenames, ApplyPatchMulti, &state);
g_free(inromname);
FreeFileMemory(state.rommem);
delete map;
struct errorinfo errormessages[2][8]={
{
//no error-free

View File

@@ -74,6 +74,10 @@ public:
filewrite* filewrite::create(LPCWSTR filename) { return filewrite_w32::create(filename); }
//TODO: implement properly
filemap* filemap::create(LPCWSTR filename) { return filemap::create_fallback(filename); }
HWND hwndMain=NULL;
HWND hwndSettings=NULL;
@@ -361,7 +365,8 @@ int a_ApplyPatch(LPCWSTR clipatchname)
thisFileName++;
LPWSTR thisPatchName=wcschr(patchnames, '\0')+1;
LPCWSTR romExtension=GetExtension(inromname);
struct mem inrom=ReadWholeFile(inromname);
filemap* inrommap=filemap::create(inromname);
struct mem inrom=inrommap->get();
bool anySuccess=false;
enum { e_none, e_notice, e_warning, e_invalid_this, e_invalid, e_io_write, e_io_read, e_io_read_rom } worsterror=e_none;
enum errorlevel severity[2][8]={
@@ -419,7 +424,7 @@ int a_ApplyPatch(LPCWSTR clipatchname)
}
}
else worsterror=e_io_read_rom;
FreeFileMemory(inrom);
delete inrommap;
MessageBoxA(hwndMain, messages[anySuccess][worsterror], flipsversion, mboxtype[severity[anySuccess][worsterror]]);
return severity[anySuccess][worsterror];
#undef max

109
flips.cpp
View File

@@ -100,6 +100,32 @@ public:
filewrite* filewrite::create_libc(const char * filename) { return filewrite_libc::create(filename); }
class filemap_fallback : public filemap {
public:
file* m_f;
size_t m_len;
uint8_t* m_ptr;
static filemap* create(file* f)
{
size_t len = f->len();
uint8_t* ptr = (uint8_t*)malloc(len);
if (!f->read(ptr, 0, len)) { free(ptr); return NULL; }
return new filemap_fallback(f, len, ptr);
}
size_t len() { return m_len; }
const uint8_t * ptr() { return m_ptr; }
filemap_fallback(file* f, size_t len, uint8_t* ptr) : m_f(f), m_len(len), m_ptr(ptr) {}
~filemap_fallback() { free(m_ptr); delete m_f; }
};
filemap* filemap::create_fallback(LPCWSTR filename)
{
return filemap_fallback::create(file::create(filename));
}
@@ -181,6 +207,19 @@ public:
~fileheader() { delete child; }
};
class fileheadermap : public filemap {
filemap* child;
public:
fileheadermap(filemap* child) : child(child) {}
size_t len() { return child->len()-512; }
//bool read(uint8_t* target, size_t start, size_t len) { return child->read(target, start+512, len); }
const uint8_t* ptr() { return child->ptr()+512; }
~fileheadermap() { delete child; }
};
@@ -751,15 +790,16 @@ bool shouldRemoveHeader(LPCWSTR romname, size_t romlen)
struct errorinfo ApplyPatchMem(file* patch, LPCWSTR inromname, bool verifyinput,
LPCWSTR outromname, struct manifestinfo * manifestinfo, bool update_rom_list)
{
struct mem inrom=ReadWholeFile(inromname);
if (!inrom.ptr)
filemap* inrom = filemap::create(inromname);
if (!inrom)
{
if (update_rom_list) DeleteRomFromList(inromname);
return error(el_broken, "Couldn't read ROM. What exactly are you doing?");
}
struct errorinfo errinf=ApplyPatchMem2(patch, inrom, verifyinput, shouldRemoveHeader(inromname, inrom.len), outromname, manifestinfo);
struct errorinfo errinf = ApplyPatchMem2(patch, inrom->get(), verifyinput,
shouldRemoveHeader(inromname, inrom->len()), outromname, manifestinfo);
if (update_rom_list && errinf.level==el_ok) AddToRomList(patch, inromname);
FreeFileMemory(inrom);
delete inrom;
return errinf;
}
@@ -810,19 +850,46 @@ bool bpsdeltaProgressCLI(void* userdata, size_t done, size_t total)
struct errorinfo CreatePatchToMem(LPCWSTR inromname, LPCWSTR outromname, enum patchtype patchtype,
struct manifestinfo * manifestinfo, struct mem * patchmem)
{
bool usemmap = (patchtype!=ty_bps && patchtype!=ty_bps_moremem);
//pick roms
filemap* romsmap[2]={NULL, NULL};
file* roms[2]={NULL, NULL};
size_t lens[2];
for (int i=0;i<2;i++)
{
LPCWSTR romname=((i==0)?inromname:outromname);
roms[i] = file::create(romname);
if (!roms[i])
if (usemmap)
{
return error(el_broken, "Couldn't read this ROM. What exactly are you doing?");
romsmap[i] = filemap::create(romname);
lens[i] = romsmap[i]->len();
if (!romsmap[i])
{
if (i==1) delete romsmap[0];
return error(el_broken, "Couldn't read this ROM. What exactly are you doing?");
}
if (shouldRemoveHeader(romname, romsmap[i]->len()) && (patchtype==ty_bps || patchtype==ty_bps_linear || patchtype==ty_bps_moremem))
{
romsmap[i] = new fileheadermap(romsmap[i]);
}
}
if (shouldRemoveHeader(romname, roms[i]->len()) && (patchtype==ty_bps || patchtype==ty_bps_linear || patchtype==ty_bps_moremem))
else
{
roms[i] = new fileheader(roms[i]);
roms[i] = file::create(romname);
lens[i] = roms[i]->len();
if (!roms[i])
{
if (i==1) delete roms[0];
return error(el_broken, "Couldn't read this ROM. What exactly are you doing?");
}
if (shouldRemoveHeader(romname, roms[i]->len()) && (patchtype==ty_bps || patchtype==ty_bps_linear || patchtype==ty_bps_moremem))
{
roms[i] = new fileheader(roms[i]);
}
}
}
@@ -843,10 +910,7 @@ struct errorinfo CreatePatchToMem(LPCWSTR inromname, LPCWSTR outromname, enum pa
struct errorinfo errinf={ el_broken, "Unknown patch format." };
if (patchtype==ty_ips)
{
struct mem rommem[2]={ roms[0]->read(), roms[1]->read() };
errinf=ipserrors[ips_create(rommem[0], rommem[1], patchmem)];
free(rommem[0].ptr);
free(rommem[1].ptr);
errinf=ipserrors[ips_create(romsmap[0]->get(), romsmap[1]->get(), patchmem)];
}
if (patchtype==ty_bps || patchtype==ty_bps_moremem)
{
@@ -865,24 +929,29 @@ struct errorinfo CreatePatchToMem(LPCWSTR inromname, LPCWSTR outromname, enum pa
}
if (patchtype==ty_bps_linear)
{
struct mem rommem[2]={ roms[0]->read(), roms[1]->read() };
errinf=bpserrors[bps_create_linear(rommem[0], rommem[1], manifest, patchmem)];
free(rommem[0].ptr);
free(rommem[1].ptr);
errinf=bpserrors[bps_create_linear(romsmap[0]->get(), romsmap[1]->get(), manifest, patchmem)];
}
FreeFileMemory(manifest);
if (errinf.level==el_ok) errinf.description="The patch was created successfully!";
if (manifestinfo->required && errinf.level==el_ok && manifesterr.level!=el_ok) errinf=manifesterr;
if (errinf.level==el_ok && roms[0]->len() > roms[1]->len())
if (errinf.level==el_ok && lens[0] > lens[1])
{
errinf=error(el_warning, "The patch was created, but the input ROM is larger than the "
"output ROM. Double check whether you've gotten them backwards.");
}
delete roms[0];
delete roms[1];
if (usemmap)
{
delete romsmap[0];
delete romsmap[1];
}
else
{
delete roms[0];
delete roms[1];
}
return errinf;
}

View File

@@ -41,6 +41,18 @@ public:
virtual ~file() {}
};
class filemap {
public:
static filemap* create(LPCWSTR filename);
static filemap* create_fallback(LPCWSTR filename);
virtual size_t len() = 0;
virtual const uint8_t * ptr() = 0;
struct mem get() { return (struct mem){ (uint8_t*)ptr(), len() }; }
virtual ~filemap() {}
};
class filewrite {
public:
static filewrite* create(LPCWSTR filename);