EMUFILE* EMUFILE_FILE::memwrap() { EMUFILE_MEMORY* mem = new EMUFILE_MEMORY(size()); if(size()==0) return mem; fread(mem->buf(),size()); return mem; }
bool VFAT::build(const char* path, int extra_MB) { dataSectors = 0; currVirtPath = ""; currPath = path; list_files(path, count_ListCallback); dataSectors += 8; //a few for reserved sectors, etc. dataSectors += extra_MB*1024*1024/512; //add extra write space //dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) //this seems to be the minimum size that will turn into a solid fat32 if(dataSectors<36*1024*1024/512) dataSectors = 36*1024*1024/512; if(dataSectors>=(0x80000000>>9)) { printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); printf("total fat sizes > 2GB are never going to work\n"); } delete file; try { file = new EMUFILE_MEMORY(dataSectors*512); } catch(std::bad_alloc) { printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); printf("(out of memory)\n"); return false; } //debug.. //file = new EMUFILE_FILE("c:\\temp.ima","rb+"); //format the disk { EmuFat fat(file); EmuFatVolume vol; u8 ok = vol.init(&fat); vol.formatNew(dataSectors); //ensure we are working in memory, just in case we were testing with a disk file. //libfat will need to go straight to memory (for now; we could easily change it to work with the disk) file = file->memwrap(); } EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; //setup libfat and write all the files through it LIBFAT::Init(memf->buf(),memf->size()); list_files(path, build_ListCallback); LIBFAT::Shutdown(); return true; }
bool retro_serialize(void *data, size_t size) { EMUFILE_MEMORY state; savestate_save(&state); if(state.size() <= size) { memcpy(data, state.buf(), state.size()); return true; } return false; }
bool LoadSample(const char *name) { SampleLoaded = 0; if (!name) return true; EMUFILE_FILE inf(name,"rb"); if (inf.fail()) return false; //wav reading code adapted from AUDIERE (LGPL) // read the RIFF header u8 riff_id[4]; u32 riff_length; u8 riff_datatype[4]; inf.fread(riff_id, 4); inf.read_32LE(riff_length); inf.fread(riff_datatype, 4); if (inf.size() < 12 || memcmp(riff_id, "RIFF", 4) != 0 || riff_length == 0 || memcmp(riff_datatype, "WAVE", 4) != 0) { MessageBox(0,"not a valid RIFF WAVE file",0,0); return false; } if (!formatChunk(inf)) return false; if (!dataChunk(inf)) { MessageBox(0,"not a valid WAVE file. some unknown problem.",0,0); return false; } delete[] samplebuffer; samplebuffersize = (int)newWavData.size(); samplebuffer = new char[samplebuffersize]; memcpy(samplebuffer,newWavData.buf(),samplebuffersize); new(&newWavData) EMUFILE_MEMORY(); SampleLoaded=1; return true; }
static bool s_slot2_loadstate(EMUFILE* is, int size) { u32 version = is->read32le(); //version 0: if(version >= 0) { slot2Type = NDS_SLOT2_AUTO; u8 slotID = is->read32le(); if (version == 0) slot2_getTypeByID(slotID, slot2Type); slot2_Change(slot2Type); EMUFILE_MEMORY temp; is->readMemoryStream(&temp); temp.fseek(0,SEEK_SET); slot2_Loadstate(&temp); } return true; }
static bool dataChunk(EMUFILE &inf) { bool found = false; // seek to just after the RIFF header inf.fseek(12,SEEK_SET); // search for a format chunk for (;;) { char chunk_id[4]; u32 chunk_length; if (inf.eof()) return found; if (inf.fread(chunk_id, 4) != 4) return found; if (!inf.read_32LE(chunk_length)) return found; // if we found a data chunk, excellent! if (memcmp(chunk_id, "data", 4) == 0) { found = true; u8 *temp = new u8[chunk_length]; if (inf.fread(temp,chunk_length) != chunk_length) { delete[] temp; return false; } newWavData.fwrite(temp,chunk_length); delete[] temp; chunk_length = 0; } inf.fseek(chunk_length,SEEK_CUR); } return found; }
bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) { // reinit memory_savestate // memory_savestate is global variable which already has its vector of bytes, so no need to allocate memory every time we use save/loadstate memory_savestate.set_len(0); // this also seeks to the beginning memory_savestate.unfail(); EMUFILE* os = &memory_savestate; uint32 totalsize = 0; FCEUPPU_SaveState(); FCEUSND_SaveState(); totalsize=WriteStateChunk(os,1,SFCPU); totalsize+=WriteStateChunk(os,2,SFCPUC); totalsize+=WriteStateChunk(os,3,FCEUPPU_STATEINFO); totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO); totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO); totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO); if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED)) { totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO); //MBG TAS Editor HACK HACK HACK! //do not save the movie state if we are in Taseditor! That would be a huge waste of time and space! if(!FCEUMOV_Mode(MOVIEMODE_TASEDITOR)) { os->fseek(5,SEEK_CUR); int size = FCEUMOV_WriteState(os); os->fseek(-(size+5),SEEK_CUR); os->fputc(7); write32le(size, os); os->fseek(size,SEEK_CUR); totalsize += 5 + size; } } // save back buffer { extern uint8 *XBackBuf; uint32 size = 256 * 256 + 8; os->fputc(8); write32le(size, os); os->fwrite((char*)XBackBuf,size); totalsize += 5 + size; } if(SPreSave) SPreSave(); totalsize+=WriteStateChunk(os,0x10,SFMDATA); if(SPreSave) SPostSave(); //save the length of the file int len = memory_savestate.size(); //sanity check: len and totalsize should be the same if(len != totalsize) { FCEUD_PrintError("sanity violation: len != totalsize"); return false; } int error = Z_OK; uint8* cbuf = (uint8*)memory_savestate.buf(); uLongf comprlen = -1; if(compressionLevel != Z_NO_COMPRESSION && (compressSavestates || FCEUMOV_Mode(MOVIEMODE_TASEDITOR))) { // worst case compression: zlib says "0.1% larger than sourceLen plus 12 bytes" comprlen = (len>>9)+12 + len; if (compressed_buf.size() < comprlen) compressed_buf.resize(comprlen); cbuf = &compressed_buf[0]; // do compression error = compress2(cbuf, &comprlen, (uint8*)memory_savestate.buf(), len, compressionLevel); }
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index, const char** extensions) { FILE *ipsfile=0; FCEUFILE *fceufp=0; bool read = (std::string)mode == "rb"; bool write = (std::string)mode == "wb"; if((read&&write) || (!read&&!write)) { FCEU_PrintError("invalid file open mode specified (only wb and rb are supported)"); return 0; } std::string archive,fname,fileToOpen; FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen); //try to setup the ips file if(ipsfn && read) ipsfile=FCEUD_UTF8fopen(ipsfn,"rb"); if(read) { ArchiveScanRecord asr = FCEUD_ScanArchive(fileToOpen); asr.files.FilterByExtension(extensions); if(!asr.isArchive()) { //if the archive contained no files, try to open it the old fashioned way EMUFILE_FILE* fp = FCEUD_UTF8_fstream(fileToOpen,mode); if(!fp || (fp->get_fp() == NULL)) { return 0; } //try to read a zip file { fceufp = TryUnzip(fileToOpen); if(fceufp) { delete fp; fceufp->filename = fileToOpen; fceufp->logicalPath = fileToOpen; fceufp->fullFilename = fileToOpen; fceufp->archiveIndex = -1; goto applyips; } } //try to read a gzipped file { uint32 magic; magic = fp->fgetc(); magic|=fp->fgetc()<<8; magic|=fp->fgetc()<<16; fp->fseek(0,SEEK_SET); if(magic==0x088b1f) { // maybe gzip... void* gzfile = gzopen(fileToOpen.c_str(),"rb"); if(gzfile) { delete fp; int size; for(size=0; gzgetc(gzfile) != EOF; size++) {} EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size); gzseek(gzfile,0,SEEK_SET); gzread(gzfile,ms->buf(),size); gzclose(gzfile); fceufp = new FCEUFILE(); fceufp->filename = fileToOpen; fceufp->logicalPath = fileToOpen; fceufp->fullFilename = fileToOpen; fceufp->archiveIndex = -1; fceufp->stream = ms; fceufp->size = size; goto applyips; } } } //open a plain old file fceufp = new FCEUFILE(); fceufp->filename = fileToOpen; fceufp->logicalPath = fileToOpen; fceufp->fullFilename = fileToOpen; fceufp->archiveIndex = -1; fceufp->stream = fp; FCEU_fseek(fceufp,0,SEEK_END); fceufp->size = FCEU_ftell(fceufp); FCEU_fseek(fceufp,0,SEEK_SET); goto applyips; } else { //open an archive file if(archive == "") if(index != -1) fceufp = FCEUD_OpenArchiveIndex(asr, fileToOpen, index); else fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0); else fceufp = FCEUD_OpenArchive(asr, archive, &fname); if(!fceufp) return 0; FileBaseInfo fbi = DetermineFileBase(fileToOpen); fceufp->logicalPath = fbi.filebasedirectory + fceufp->filename; goto applyips; } applyips: //try to open the ips file if(!ipsfile && !ipsfn) ipsfile=FCEUD_UTF8fopen(FCEU_MakeIpsFilename(DetermineFileBase(fceufp->logicalPath.c_str())),"rb"); ApplyIPS(ipsfile,fceufp); return fceufp; } return 0; }
static FCEUFILE * TryUnzip(const std::string& path) { unzFile tz; if((tz=unzOpen(path.c_str()))) // If it's not a zip file, use regular file handlers. // Assuming file type by extension usually works, // but I don't like it. :) { if(unzGoToFirstFile(tz)==UNZ_OK) { for(;;) { char tempu[512]; // Longer filenames might be possible, but I don't // think people would name files that long in zip files... unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0); tempu[511]=0; if(strlen(tempu)>=4) { char *za=tempu+strlen(tempu)-4; //if(!ext) { if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") || !strcasecmp(za,".nsf") || !strcasecmp(za,".unf") || !strcasecmp(za,".nez")) break; } //else if(!strcasecmp(za,ext)) // break; } if(strlen(tempu)>=5) { if(!strcasecmp(tempu+strlen(tempu)-5,".unif")) break; } if(unzGoToNextFile(tz)!=UNZ_OK) { if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail; unzCloseCurrentFile(tz); unzClose(tz); return 0; } } if(unzOpenCurrentFile(tz)!=UNZ_OK) goto zpfail; } else { zpfail: unzClose(tz); return 0; } unz_file_info ufo; unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0); int size = ufo.uncompressed_size; EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size); unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size); unzCloseCurrentFile(tz); unzClose(tz); FCEUFILE *fceufp = new FCEUFILE(); fceufp->stream = ms; fceufp->size = size; return fceufp; } return 0; }
bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) { //a temp memory stream. we'll dump some data here and then compress //TODO - support dumping directly without compressing to save a buffer copy EMUFILE_MEMORY ms; EMUFILE* os = &ms; uint32 totalsize = 0; FCEUPPU_SaveState(); FCEUSND_SaveState(); totalsize=WriteStateChunk(os,1,SFCPU); totalsize+=WriteStateChunk(os,2,SFCPUC); totalsize+=WriteStateChunk(os,3,FCEUPPU_STATEINFO); totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO); totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO); totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO); if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED)) { totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO); //MBG tasedit HACK HACK HACK! //do not save the movie state if we are in tasedit! that is a huge waste of time and space! if(!FCEUMOV_Mode(MOVIEMODE_TASEDIT)) { os->fseek(5,SEEK_CUR); int size = FCEUMOV_WriteState(os); os->fseek(-(size+5),SEEK_CUR); os->fputc(7); write32le(size, os); os->fseek(size,SEEK_CUR); totalsize += 5 + size; } } // save back buffer { extern uint8 *XBackBuf; uint32 size = 256 * 256 + 8; os->fputc(8); write32le(size, os); os->fwrite((char*)XBackBuf,size); totalsize += 5 + size; } if(SPreSave) SPreSave(); totalsize+=WriteStateChunk(os,0x10,SFMDATA); if(SPreSave) SPostSave(); //save the length of the file int len = ms.size(); //sanity check: len and totalsize should be the same if(len != totalsize) { FCEUD_PrintError("sanity violation: len != totalsize"); return false; } int error = Z_OK; uint8* cbuf = (uint8*)ms.buf(); uLongf comprlen = -1; if(compressionLevel != Z_NO_COMPRESSION && compressSavestates) { //worst case compression. //zlib says "0.1% larger than sourceLen plus 12 bytes" comprlen = (len>>9)+12 + len; cbuf = new uint8[comprlen]; error = compress2(cbuf,&comprlen,(uint8*)ms.buf(),len,compressionLevel); }
int LoadStateEmbed(char *file) { GPUFreeze_t *gpufP; int Size; char header[32]; FILE* fp; FILE* fp2; uint8 * embSaveTmp; size_t blockSize = Movie.memoryCard1Offset-Movie.saveStateOffset; embSaveTmp = (uint8*)malloc(blockSize); fp = fopen(file,"rb"); fp2 = fopen("embsave.tmp","wb"); fseek(fp, Movie.saveStateOffset, SEEK_SET); fread(embSaveTmp, 1, blockSize, fp); fwrite(embSaveTmp, 1, blockSize, fp2); fclose(fp); fclose(fp2); EMUFILE_FILE ef("embsave.tmp", "rb"); if (ef.fail()) return -1; EMUFILE *f = &ef; psxCpu->Reset(); gzread(f, header, 32); if (strncmp("STv3 PSXjin", header, 9)) { return -1; } exceptionPatches.clear(); int tag; gzread(f, &tag, 4); if (tag == 'ExPs') { gzread(f, &Size, 4); while (Size--) { u32 addr, val; gzread(f, &addr, 4); gzread(f, &val, 4); exceptionPatches.push_back(std::make_pair(addr, val)); } gzseek(f, 128*96*3-4-4-exceptionPatches.size()*4*2, SEEK_CUR); } else gzseek(f, 128*96*3-4, SEEK_CUR); gzread(f, psxM, 0x00200000); gzread(f, psxP, 0x00010000); gzread(f, psxR, 0x00080000); gzread(f, psxH, 0x00010000); gzread(f, (void*)&psxRegs, sizeof(psxRegs)); if (Config.HLE) //adelikat: TODO: remove all references to Config.HLE, we will not be using that BIOS, ever psxBiosFreeze(0); // gpu gpufP = (GPUFreeze_t *) malloc (sizeof(GPUFreeze_t)); gzread(f, gpufP, sizeof(GPUFreeze_t)); gpufP->extraData = malloc(gpufP->extraDataSize); gzread(f, gpufP->extraData, gpufP->extraDataSize); GPUfreeze(0, gpufP); free(gpufP->extraData); free(gpufP); sioFreeze(f, 0); cdrFreeze(f, 0); psxHwFreeze(f, 0); CDRisoFreeze(f,0); psxRcntFreeze(f, 0); mdecFreeze(f, 0); //TODO - no movie state? are you sure? // spu gzread(f, &Size, 4); EMUFILE_MEMORY memfile; memfile.truncate(Size); gzread(f, memfile.buf(), Size); bool ok = SPUunfreeze_new(&memfile); if(!ok) return 1; remove("embsave.tmp"); return 0; }
int SaveStateEmbed(char *file) { GPUFreeze_t *gpufP; int Size; unsigned char *pMem; EMUFILE_FILE ef(file, "ab"); if (ef.fail()) return -1; EMUFILE *f = &ef; gzwrite(f, (void*)PSXjinHeader, 32); pMem = (unsigned char *) malloc(128*96*3); if (pMem == NULL) return -1; //GPU_getScreenPic(pMem); memset(pMem,0,128*96*3); int tag = 'ExPs'; gzwrite(f, &tag, 4); Size = exceptionPatches.size(); gzwrite(f, &Size, 4); for (int i = 0; i < Size; i++) { gzwrite(f, &exceptionPatches[i].first, 4); gzwrite(f, &exceptionPatches[i].second, 4); } gzwrite(f, pMem, 128*96*3-4-4-Size*4*2); free(pMem); gzwrite(f, psxM, 0x00200000); gzwrite(f, psxP, 0x00010000); gzwrite(f, psxR, 0x00080000); gzwrite(f, psxH, 0x00010000); gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); if (Config.HLE) psxBiosFreeze(1); // gpu gpufP = (GPUFreeze_t *) malloc(sizeof(GPUFreeze_t)); gpufP->ulFreezeVersion = 1; GPUfreeze(1, gpufP); void* temp = gpufP->extraData; gpufP->extraData = 0; gzwrite(f, gpufP, sizeof(GPUFreeze_t)); gzwrite(f, temp, gpufP->extraDataSize); GPUfreeze(3, gpufP); free(gpufP); sioFreeze(f, 1); cdrFreeze(f, 1); psxHwFreeze(f, 1); CDRisoFreeze(f,1); psxRcntFreeze(f, 1); mdecFreeze(f, 1); //TODO - no movie state? are you sure? // spu EMUFILE_MEMORY memfile; SPUfreeze_new(&memfile); Size = memfile.size(); gzwrite(f, &Size, 4); gzwrite(f, memfile.buf(),Size); return 0; }
int LoadStateEmufile(EMUFILE *f) { GPUFreeze_t *gpufP; int Size; char header[32]; printf("loadstate---\n"); psxCpu->Reset(); gzread(f, header, 32); if (strncmp("STv3 PSXjin", header, 9)) { return -1; } exceptionPatches.clear(); int tag; gzread(f, &tag, 4); if (tag == 'ExPs') { gzread(f, &Size, 4); while (Size--) { u32 addr, val; gzread(f, &addr, 4); gzread(f, &val, 4); exceptionPatches.push_back(std::make_pair(addr, val)); } gzseek(f, 128*96*3-4-4-exceptionPatches.size()*4*2, SEEK_CUR); } else gzseek(f, 128*96*3-4, SEEK_CUR); gzread(f, psxM, 0x00200000); gzread(f, psxP, 0x00010000); gzread(f, psxR, 0x00080000); gzread(f, psxH, 0x00010000); gzread(f, (void*)&psxRegs, sizeof(psxRegs)); if (Config.HLE) psxBiosFreeze(0); // gpu gpufP = (GPUFreeze_t *) malloc (sizeof(GPUFreeze_t)); gzread(f, gpufP, sizeof(GPUFreeze_t)); gpufP->extraData = malloc(gpufP->extraDataSize); gzread(f, gpufP->extraData, gpufP->extraDataSize); GPUfreeze(0, gpufP); free(gpufP->extraData); free(gpufP); sioFreeze(f, 0); cdrFreeze(f, 0); psxHwFreeze(f, 0); CDRisoFreeze(f,0); psxRcntFreeze(f, 0); mdecFreeze(f, 0); PadFreeze(f, 0); MovieFreeze(f, 0); // spu gzread(f, &Size, 4); EMUFILE_MEMORY memfile; memfile.truncate(Size); gzread(f, memfile.buf(), Size); bool ok = SPUunfreeze_new(&memfile); if(!ok) return 1; return 0; }
int SaveStateEmufile(EMUFILE *f) { GPUFreeze_t *gpufP; int Size; unsigned char *pMem; gzwrite(f, (void*)PSXjinHeader, 32); pMem = (unsigned char *) malloc(128*96*3); if (pMem == NULL) return -1; memset(pMem,0,128*96*3); // Ugh. We need to store this information, but in a backwards-compatible fashion. Do this // by (ab)using the gap previously occupied by GPU_getScreenPic. The data is tagged so it // can be detected on savestate load int tag = 'ExPs'; gzwrite(f, &tag, 4); Size = exceptionPatches.size(); gzwrite(f, &Size, 4); for (int i = 0; i < Size; i++) { gzwrite(f, &exceptionPatches[i].first, 4); gzwrite(f, &exceptionPatches[i].second, 4); } gzwrite(f, pMem, 128*96*3-4-4-Size*4*2); free(pMem); gzwrite(f, psxM, 0x00200000); gzwrite(f, psxP, 0x00010000); gzwrite(f, psxR, 0x00080000); gzwrite(f, psxH, 0x00010000); gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); if (Config.HLE) psxBiosFreeze(1); // gpu gpufP = (GPUFreeze_t *) malloc(sizeof(GPUFreeze_t)); gpufP->ulFreezeVersion = 1; GPUfreeze(1, gpufP); void* temp = gpufP->extraData; gpufP->extraData = 0; gzwrite(f, gpufP, sizeof(GPUFreeze_t)); gzwrite(f, temp, gpufP->extraDataSize); GPUfreeze(3, gpufP); free(gpufP); sioFreeze(f, 1); cdrFreeze(f, 1); psxHwFreeze(f, 1); CDRisoFreeze(f,1); psxRcntFreeze(f, 1); mdecFreeze(f, 1); PadFreeze(f, 1); MovieFreeze(f, 1); EMUFILE_MEMORY memfile; SPUfreeze_new(&memfile); Size = memfile.size(); gzwrite(f, &Size, 4); gzwrite(f, memfile.buf(),Size); return 0; }