//yuck... another custom text parser. bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) { //TODO - start with something different. like 'desmume movie version 1" int curr = fp->ftell(); //movie must start with "version 1" char buf[9]; curr = fp->ftell(); fp->fread(buf,9); fp->fseek(curr, SEEK_SET); // if(fp->fail()) return false; if(memcmp(buf,"version 1",9)) return false; std::string key,value; enum { NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT } state = NEWLINE; bool bail = false; for(;;) { bool iswhitespace, isrecchar, isnewline; int c; if(size--<=0) goto bail; c = fp->fgetc(); if(c == -1) goto bail; iswhitespace = (c==' '||c=='\t'); isrecchar = (c=='|'); isnewline = (c==10||c==13); if(isrecchar && movieData.binaryFlag && !stopAfterHeader) { LoadFM2_binarychunk(movieData, fp, size); return true; } switch(state) { case NEWLINE: if(isnewline) goto done; if(iswhitespace) goto done; if(isrecchar) goto dorecord; //must be a key key = ""; value = ""; goto dokey; break; case RECORD: { dorecord: if (stopAfterHeader) return true; int currcount = movieData.records.size(); movieData.records.resize(currcount+1); int preparse = fp->ftell(); movieData.records[currcount].parse(&movieData, fp); int postparse = fp->ftell(); size -= (postparse-preparse); state = NEWLINE; break; } case KEY: dokey: //dookie state = KEY; if(iswhitespace) goto doseparator; if(isnewline) goto commit; key += c; break; case SEPARATOR: doseparator: state = SEPARATOR; if(isnewline) goto commit; if(!iswhitespace) goto dovalue; break; case VALUE: dovalue: state = VALUE; if(isnewline) goto commit; value += c; break; case COMMENT: default: break; } goto done; bail: bail = true; if(state == VALUE) goto commit; goto done; commit: movieData.installValue(key,value); state = NEWLINE; done: ; if(bail) break; } return true; }
//yuck... another custom text parser. bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) { // if there's no "binary" tag in the movie header, consider it as a movie in text format movieData.binaryFlag = false; // Non-TASEditor projects consume until EOF movieData.loadFrameCount = -1; std::ios::pos_type curr = fp->ftell(); if (!stopAfterHeader) { // first, look for an fcm signature char fcmbuf[3]; fp->fread(fcmbuf,3); fp->fseek(curr,SEEK_SET); if(!strncmp(fcmbuf,"FCM",3)) { FCEU_PrintError("FCM File format is no longer supported. Please use Tools > Convert FCM"); return false; } } //movie must start with "version 3" char buf[9]; curr = fp->ftell(); fp->fread(buf,9); fp->fseek(curr,SEEK_SET); if(fp->fail()) return false; if(memcmp(buf,"version 3",9)) return false; std::string key,value; enum { NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT, SUBTITLE } state = NEWLINE; bool bail = false; bool iswhitespace, isrecchar, isnewline; int c; for(;;) { if(size--<=0) goto bail; c = fp->fgetc(); if(c == -1) goto bail; iswhitespace = (c==' '||c=='\t'); isrecchar = (c=='|'); isnewline = (c==10||c==13); if(isrecchar && movieData.binaryFlag && !stopAfterHeader) { LoadFM2_binarychunk(movieData, fp, size); return true; } else if (isnewline && movieData.loadFrameCount == movieData.records.size()) // exit prematurely if loaded the specified amound of records return true; switch(state) { case NEWLINE: if(isnewline) goto done; if(iswhitespace) goto done; if(isrecchar) goto dorecord; //must be a key key = ""; value = ""; goto dokey; break; case RECORD: { dorecord: if (stopAfterHeader) return true; int currcount = movieData.records.size(); movieData.records.resize(currcount+1); int preparse = fp->ftell(); movieData.records[currcount].parse(&movieData, fp); int postparse = fp->ftell(); size -= (postparse-preparse); state = NEWLINE; break; } case KEY: dokey: //dookie state = KEY; if(iswhitespace) goto doseparator; if(isnewline) goto commit; key += c; break; case SEPARATOR: doseparator: state = SEPARATOR; if(isnewline) goto commit; if(!iswhitespace) goto dovalue; break; case VALUE: dovalue: state = VALUE; if(isnewline) goto commit; value += c; } goto done; bail: bail = true; if(state == VALUE) goto commit; goto done; commit: movieData.installValue(key,value); state = NEWLINE; done: ; if(bail) break; } return true; }