///* Mednafen - Multi-system Emulator1// *2// * This program is free software; you can redistribute it and/or modify3// * it under the terms of the GNU General Public License as published by4// * the Free Software Foundation; either version 2 of the License, or5// * (at your option) any later version.6// *7// * This program is distributed in the hope that it will be useful,8// * but WITHOUT ANY WARRANTY; without even the implied warranty of9// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the10// * GNU General Public License for more details.11// *12// * You should have received a copy of the GNU General Public License13// * along with this program; if not, write to the Free Software14// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA15// */16//17//#include <stdarg.h>18//#include <string.h>19//#include <sys/types.h>20//#include <sys/stat.h>21//#include <errno.h>22//23//#include "octoshock.h"24//#include "FileStream.h"25//26//27//#ifdef HAVE_MMAP28//#include <sys/mman.h>29//#include <sys/types.h>30//#include <sys/stat.h>31//#include <fcntl.h>32//#endif33//34//#include "file.h"35//36//static const int64 MaxROMImageSize = (int64)1 << 26; // 2 ^ 26 = 64MiB37//38//enum39//{40// MDFN_FILETYPE_PLAIN = 0,41// MDFN_FILETYPE_GZIP = 1,42// MDFN_FILETYPE_ZIP = 2,43//};44//45//void MDFNFILE::MakeMemWrap(void *tz, int type)46//{47// #ifdef HAVE_MMAP48// is_mmap = FALSE;49// #endif50// location = 0;51//52// if(type == MDFN_FILETYPE_PLAIN)53// {54// ::fseek((FILE *)tz, 0, SEEK_END);55// f_size = ::ftell((FILE *)tz);56// ::fseek((FILE *)tz, 0, SEEK_SET);57//58//59// #ifdef HAVE_MMAP60// if((void *)-1 != (f_data = (uint8 *)mmap(NULL, size, PROT_READ, MAP_SHARED, fileno((FILE *)tz), 0)))61// {62// //puts("mmap'ed");63// is_mmap = TRUE;64// #ifdef HAVE_MADVISE65// madvise(f_data, size, MADV_SEQUENTIAL | MADV_WILLNEED);66// #endif67// }68// else69// #endif70// {71// f_data = (uint8 *)MDFN_malloc_T(size, _("file read buffer"));72//73// if((int64)::fread(f_data, 1, size, (FILE *)tz) != size)74// {75// ErrnoHolder ene(errno);76//77// throw MDFN_Error(ene.Errno(), _("Error reading file: %s"), ene.StrError());78// }79// }80// }81// else if(type == MDFN_FILETYPE_GZIP)82// {83// uint32_t cur_size = 0;84// uint32_t cur_alloced = 65536;85// int howmany;86//87// f_data = (uint8 *)MDFN_malloc_T(cur_alloced, _("file read buffer"));88//89// while((howmany = gzread((gzFile)tz, f_data + cur_size, cur_alloced - cur_size)) > 0)90// {91// cur_size += howmany;92// cur_alloced <<= 1;93//94// if(cur_size > MaxROMImageSize)95// throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize);96//97// f_data = (uint8 *)MDFN_realloc_T(f_data, cur_alloced, _("file read buffer"));98// }99//100// f_data = (uint8 *)MDFN_realloc_T(f_data, cur_size, _("file read buffer"));101// f_size = cur_size;102//103// {104// int gzerrnum = 0;105// const char *gzerrstring;106// if((gzerrstring = gzerror((gzFile)tz, &gzerrnum)) && gzerrnum != Z_OK && gzerrnum != Z_STREAM_END)107// {108// if(gzerrnum != Z_ERRNO)109// {110// throw MDFN_Error(0, _("Error reading file: zlib error: %s"), gzerrstring);111// }112// else113// {114// ErrnoHolder ene(errno);115// throw MDFN_Error(ene.Errno(), _("Error reading file: %s"), ene.StrError());116// }117// }118// }119// }120// else if(type == MDFN_FILETYPE_ZIP)121// {122// unz_file_info ufo;123// unzGetCurrentFileInfo((unzFile)tz, &ufo, 0, 0, 0, 0, 0, 0);124//125// f_size = ufo.uncompressed_size;126//127// if(size > MaxROMImageSize)128// throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize);129//130// f_data = (uint8 *)MDFN_malloc_T(ufo.uncompressed_size, _("file read buffer"));131// unzReadCurrentFile((unzFile)tz, f_data, ufo.uncompressed_size);132// }133//}134//135//MDFNFILE::MDFNFILE(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose) : size(f_size), data((const uint8* const &)f_data), ext((const char * const &)f_ext), fbase((const char * const &)f_fbase)136//{137// f_data = NULL;138// f_size = 0;139// f_ext = NULL;140// f_fbase = NULL;141//142// location = 0;143//144// #ifdef HAVE_MMAP145// is_mmap = 0;146// #endif147//148// Open(path, known_ext, purpose);149//}150//151//MDFNFILE::~MDFNFILE()152//{153// Close();154//}155//156//157//void MDFNFILE::Open(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose)158//{159// unzFile tz = NULL;160// FILE *fp = NULL;161// gzFile gzp = NULL;162//163// try164// {165// //166// // Try opening it as a zip file first167// //168// if((tz = unzOpen(path)))169// {170// char tempu[1024];171// int errcode;172//173// if((errcode = unzGoToFirstFile(tz)) != UNZ_OK)174// {175// throw MDFN_Error(0, _("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode));176// }177//178// if(known_ext)179// {180// bool FileFound = FALSE;181// while(!FileFound)182// {183// size_t tempu_strlen;184// const FileExtensionSpecStruct *ext_search = known_ext;185//186// if((errcode = unzGetCurrentFileInfo(tz, 0, tempu, 1024, 0, 0, 0, 0)) != UNZ_OK)187// {188// throw MDFN_Error(0, _("Could not get file information in ZIP archive: %s"), unzErrorString(errcode));189// }190//191// tempu[1023] = 0;192// tempu_strlen = strlen(tempu);193//194// while(ext_search->extension && !FileFound)195// {196// size_t ttmeow = strlen(ext_search->extension);197// if(tempu_strlen >= ttmeow)198// {199// if(!strcasecmp(tempu + tempu_strlen - ttmeow, ext_search->extension))200// FileFound = TRUE;201// }202// ext_search++;203// }204//205// if(FileFound)206// break;207//208// if((errcode = unzGoToNextFile(tz)) != UNZ_OK)209// {210// if(errcode != UNZ_END_OF_LIST_OF_FILE)211// {212// throw MDFN_Error(0, _("Error seeking to next file in ZIP archive: %s"), unzErrorString(errcode));213// }214//215// if((errcode = unzGoToFirstFile(tz)) != UNZ_OK)216// {217// throw MDFN_Error(0, _("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode));218// }219// break;220// }221// } // end to while(!FileFound)222// } // end to if(ext)223//224// if((errcode = unzOpenCurrentFile(tz)) != UNZ_OK)225// {226// throw MDFN_Error(0, _("Could not open file in ZIP archive: %s"), unzErrorString(errcode));227// }228//229// MakeMemWrap(tz, MDFN_FILETYPE_ZIP);230//231// {232// char *ld = strrchr(tempu, '.');233//234// f_ext = strdup(ld ? ld + 1 : "");235// f_fbase = strdup(tempu);236// if(ld)237// f_fbase[ld - tempu] = 0;238// }239// }240// else // If it's not a zip file, handle it as...another type of file!241// {242// if(!(fp = fopen(path, "rb")))243// {244// ErrnoHolder ene(errno);245//246// throw MDFN_Error(ene.Errno(), _("Error opening \"%s\": %s"), path, ene.StrError());247// }248//249// const char *path_fnp = GetFNComponent(path);250//251// uint32 gzmagic;252//253// gzmagic = ::fgetc(fp);254// gzmagic |= ::fgetc(fp) << 8;255// gzmagic |= ::fgetc(fp) << 16;256//257// if(gzmagic != 0x088b1f) /* Not gzip... */258// {259// ::fseek(fp, 0, SEEK_SET);260//261// MakeMemWrap(fp, MDFN_FILETYPE_PLAIN);262//263// {264// const char *ld = strrchr(path_fnp, '.');265// f_ext = strdup(ld ? ld + 1 : "");266// f_fbase = strdup(path_fnp);267// if(ld)268// f_fbase[ld - path_fnp] = 0;269// }270// }271// else /* Probably gzip */272// {273// fclose(fp);274// fp = NULL;275//276// // Clear errno so we can see if the error occurred within zlib or the C lib277// errno = 0;278// if(!(gzp = gzopen(path, "rb")))279// {280// if(errno != 0)281// {282// ErrnoHolder ene(errno);283//284// throw MDFN_Error(ene.Errno(), _("Error opening \"%s\": %s"), path, ene.StrError());285// }286// else287// throw MDFN_Error(0, _("Error opening \"%s\": %s"), path, _("zlib error"));288// }289//290// MakeMemWrap(gzp, MDFN_FILETYPE_GZIP);291//292// char *tmp_path = strdup(path_fnp);293// char *ld = strrchr(tmp_path, '.');294//295// if(ld && ld > tmp_path)296// {297// char *last_ld = ld;298// *ld = 0;299// ld = strrchr(tmp_path, '.');300// if(!ld) { ld = last_ld; }301// else *ld = 0;302// }303// f_ext = strdup(ld ? ld + 1 : "");304// f_fbase = tmp_path;305// } // End gzip handling306// } // End normal and gzip file handling else to zip307// }308// catch(...)309// {310// if(tz != NULL)311// {312// unzCloseCurrentFile(tz);313// unzClose(tz);314// }315//316// if(fp != NULL)317// {318// fclose(fp);319// fp = NULL;320// }321//322// if(gzp != NULL)323// {324// gzclose(gzp);325// gzp = NULL;326// }327//328// Close();329// throw;330// }331//332// if(tz != NULL)333// {334// unzCloseCurrentFile(tz);335// unzClose(tz);336// }337//338// if(fp != NULL)339// {340// fclose(fp);341// fp = NULL;342// }343//344// if(gzp != NULL)345// {346// gzclose(gzp);347// gzp = NULL;348// }349//}350//351//void MDFNFILE::Close(void) throw()352//{353// if(f_ext)354// {355// free(f_ext);356// f_ext = NULL;357// }358//359// if(f_fbase)360// {361// free(f_fbase);362// f_fbase = NULL;363// }364//365// if(f_data)366// {367// #if HAVE_MMAP368// if(is_mmap)369// munmap(f_data, size);370// else371// #endif372// free(f_data);373// f_data = NULL;374// }375//}376//377//uint64 MDFNFILE::fread(void *ptr, size_t element_size, size_t nmemb)378//{379// uint32 total = element_size * nmemb;380//381// if(location >= f_size)382// return 0;383//384// if((location + total) > f_size)385// {386// int64 ak = f_size - location;387//388// memcpy((uint8*)ptr, f_data + location, ak);389//390// location = f_size;391//392// return(ak / element_size);393// }394// else395// {396// memcpy((uint8*)ptr, f_data + location, total);397//398// location += total;399//400// return nmemb;401// }402//}403//404//int MDFNFILE::fseek(int64 offset, int whence)405//{406// switch(whence)407// {408// case SEEK_SET:if(offset >= f_size)409// return(-1);410// location = offset;411// break;412//413// case SEEK_CUR:if((offset + location) > f_size)414// return(-1);415//416// location += offset;417// break;418// }419// return 0;420//}421//422//int MDFNFILE::read16le(uint16 *val)423//{424// if((location + 2) > size)425// return 0;426//427// *val = MDFN_de16lsb(data + location);428//429// location += 2;430//431// return(1);432//}433//434//int MDFNFILE::read32le(uint32 *val)435//{436// if((location + 4) > size)437// return 0;438//439// *val = MDFN_de32lsb(data + location);440//441// location += 4;442//443// return(1);444//}445//446//char *MDFNFILE::fgets(char *s, int buffer_size)447//{448// int pos = 0;449//450// if(!buffer_size)451// return(NULL);452//453// if(location >= buffer_size)454// return(NULL);455//456// while(pos < (buffer_size - 1) && location < buffer_size)457// {458// int v = data[location];459// s[pos] = v;460// location++;461// pos++;462// if(v == '\n') break;463// }464//465// if(buffer_size)466// s[pos] = 0;467//468// return(s);469//}470//471//static INLINE bool MDFN_DumpToFileReal(const char *filename, int compress, const std::vector<PtrLengthPair> &pearpairs)472//{473// if(MDFN_GetSettingB("filesys.disablesavegz"))474// compress = 0;475//476// if(compress)477// {478// char mode[64];479// gzFile gp;480//481// trio_snprintf(mode, 64, "wb%d", compress);482//483// gp = gzopen(filename, mode);484//485// if(!gp)486// {487// ErrnoHolder ene(errno);488//489// MDFN_PrintError(_("Error opening \"%s\": %s"), filename, ene.StrError());490// return(0);491// }492//493// for(unsigned int i = 0; i < pearpairs.size(); i++)494// {495// const void *data = pearpairs[i].GetData();496// const int64 length = pearpairs[i].GetLength();497//498// if(gzwrite(gp, data, length) != length)499// {500// int errnum;501//502// MDFN_PrintError(_("Error writing to \"%s\": %s"), filename, gzerror(gp, &errnum));503// gzclose(gp);504// return(0);505// }506// }507//508// if(gzclose(gp) != Z_OK) // FIXME: Huhm, how should we handle this?509// {510// MDFN_PrintError(_("Error closing \"%s\""), filename);511// return(0);512// }513// }514// else515// {516// FILE *fp = fopen(filename, "wb");517// if(!fp)518// {519// ErrnoHolder ene(errno);520//521// MDFN_PrintError(_("Error opening \"%s\": %s"), filename, ene.StrError());522// return(0);523// }524//525// for(unsigned int i = 0; i < pearpairs.size(); i++)526// {527// const void *data = pearpairs[i].GetData();528// const uint64 length = pearpairs[i].GetLength();529//530// if(fwrite(data, 1, length, fp) != length)531// {532// ErrnoHolder ene(errno);533//534// MDFN_PrintError(_("Error writing to \"%s\": %s"), filename, ene.StrError());535// fclose(fp);536// return(0);537// }538// }539//540// if(fclose(fp) == EOF)541// {542// ErrnoHolder ene(errno);543//544// MDFN_PrintError(_("Error closing \"%s\": %s"), filename, ene.StrError());545// return(0);546// }547// }548// return(1);549//}550//551//bool MDFN_DumpToFile(const char *filename, int compress, const std::vector<PtrLengthPair> &pearpairs)552//{553// return(MDFN_DumpToFileReal(filename, compress, pearpairs));554//}555//556//bool MDFN_DumpToFile(const char *filename, int compress, const void *data, uint64 length)557//{558// std::vector<PtrLengthPair> tmp_pairs;559// tmp_pairs.push_back(PtrLengthPair(data, length));560// return(MDFN_DumpToFileReal(filename, compress, tmp_pairs));561//}562563564