Exemplo n.º 1
0
static int ReadStateChunk(MEMFILE *st, SFORMAT *sf, int size)
{
 //if(scan_chunks)
 //  return mem_fseek(st,size,SEEK_CUR) == 0;

 SFORMAT *tmp;
 int temp;
 temp=mem_ftell(st);

 while(mem_ftell(st)<temp+size)
 {
  uint32 tsize;
  char toa[4];
  if(mem_fread(toa,1,4,st)<=0)
   return 0;

  mem_read32le(&tsize,st);

  if((tmp=CheckS(sf,tsize,toa)))
  {
   mem_fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st);

   #ifndef LSB_FIRST
   if(tmp->s&RLSB)
    FlipByteOrder(tmp->v,tmp->s&(~RLSB));
   #endif
  }
  else
  {
   mem_fseek(st,tsize,SEEK_CUR);
   printf("ReadStateChunk: sect \"%c%c%c%c\" not handled\n", toa[0], toa[1], toa[2], toa[3]);
  }
 } // while(...)
 return 1;
}
Exemplo n.º 2
0
//
// I_ReadDataBlock()
//
// Returns a handle to the internal storage of a MEMFILE and moves the read
// position of the MEMFILE forward to the end of the block.
//
static byte* I_ReadDataBlock(MEMFILE *mf, size_t length)
{
	if (!mf)
		return NULL;
		
	size_t memfileoffset = mem_ftell(mf);
	if (mem_fsize(mf) < memfileoffset + length)
		return NULL;
	
	byte* data = (byte*)mem_fgetbuf(mf) + memfileoffset;
	mem_fseek(mf, length, MEM_SEEK_CUR);

	return data;
}
Exemplo n.º 3
0
int FCEUSS_LoadFP(MEMFILE *st, int make_backup)
{
	int x;
	if(st!=NULL)
	{
	 uint8 header[16];

         mem_fread(&header,1,16,st);
         if(memcmp(header,"FCS",3))
         {
          mem_fseek(st,0,SEEK_SET);
          if(!LoadStateOld(st))
           goto lerror;
          goto okload;
         }
         stateversion=header[3];
	 if(stateversion<53)
	 FixOldSaveStateSFreq();
	 x=ReadStateChunks(st);
	 if(GameStateRestore) GameStateRestore(header[3]);
	 if(x)
	 {
	  okload:
          TempAddr=TempAddrT;
          RefreshAddr=RefreshAddrT;

	  SaveStateStatus[CurrentState]=1;
	 }
	 else
	 {
	  SaveStateStatus[CurrentState]=1;
	  FCEU_DispMessage("Error(s) reading state %d!",CurrentState);
	 }
	}
	else
	{
	 lerror:
	 FCEU_DispMessage("State %d load error.",CurrentState);
	 SaveStateStatus[CurrentState]=0;
	 return 0;
	}
	return 1;
}
Exemplo n.º 4
0
void SaveState(const char *fname)
{
	MEMFILE *st=NULL;

	TempAddrT=TempAddr;
	RefreshAddrT=RefreshAddr;

	if(geniestage==1)
	{
	 FCEU_DispMessage("Cannot save FCS in GG screen.");
	 return;
        }

	st=mem_fopen_write(fname);

	 if(st!=NULL)
	 {
	  static uint32 totalsize;
	  static uint8 header[16]="FCS";
	  memset(header+4,0,13);
	  header[3]=VERSION_NUMERIC;
	  mem_fwrite(header,1,16,st);

#ifdef ASM_6502
          asmcpu_pack();
#endif
	  totalsize=WriteStateChunk(st,1,SFCPU);
	  totalsize+=WriteStateChunk(st,2,SFCPUC);
	  totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO);
	  totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO);
	  totalsize+=WriteStateChunk(st,5,SFSND);


	  if(SPreSave) SPreSave();
	  totalsize+=WriteStateChunk(st,0x10,SFMDATA);
	  if(SPostSave) SPostSave();

	  mem_fseek(st,4,SEEK_SET);
	  mem_write32(totalsize,st);
	  SaveStateStatus[CurrentState]=1;
	  mem_fclose(st);
	 }
}
Exemplo n.º 5
0
static int ReadStateChunks(MEMFILE *st)
{
 int t;
 uint32 size;
 int ret=1;

for(;;)
 {
  t=mem_fgetc(st);
  if(t==EOF) break;
  if(!mem_read32(&size,st)) break;

  // printf("ReadStateChunks: chunk %i\n", t);
  switch(t)
  {
   case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0;
#ifdef ASM_6502
          asmcpu_unpack();
#endif
	  break;
   case 2:if(!ReadStateChunk(st,SFCPUC,size)) ret=0;
          else
	  {
	   X.mooPI=X.P;	// Quick and dirty hack.
	  }
	  break;
   case 3:if(!ReadStateChunk(st,FCEUPPU_STATEINFO,size)) ret=0;break;
   case 4:if(!ReadStateChunk(st,FCEUCTRL_STATEINFO,size)) ret=0;break;
   case 5:if(!ReadStateChunk(st,SFSND,size)) ret=0;break;
   case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0;break;
   default:printf("ReadStateChunks: unknown chunk: %i\n", t);
           if(mem_fseek(st,size,SEEK_CUR)<0) goto endo;break;
  }
 }
 endo:
 return ret;
}
Exemplo n.º 6
0
//
// MidiSong::_ParseSong()
//
// Loads a midi song stored in the MEMFILE, parses the header, and reads
// all of the midi events from the song.  If the midi song has multiple
// tracks, they are merged into a single stream of events.
//
// Based partially on an implementation from Chocolate Doom by Simon Howard.
//
void MidiSong::_ParseSong(MEMFILE *mf)
{
	if (!mf)
		return;
		
	I_ClearMidiEventList(&mEvents);
	
	mem_fseek(mf, 0, MEM_SEEK_SET);
		
	midi_chunk_header_t chunkheader;
    if (!mem_fread(&chunkheader, cTrackHeaderSize, 1, mf))
		return;
		
	chunkheader.chunk_id = ntohl(chunkheader.chunk_id);
	chunkheader.chunk_size = ntohl(chunkheader.chunk_size);
		
	if (chunkheader.chunk_id != cHeaderChunkId)
	{
		Printf(PRINT_HIGH, "MidiSong::_ParseSong: Unexpected file header ID\n");
		return;
	}

	midi_header_t fileheader;
	if (!mem_fread(&fileheader, cHeaderSize, 1, mf))
		return;
	
	fileheader.format_type = ntohs(fileheader.format_type);
	fileheader.num_tracks = ntohs(fileheader.num_tracks);
	fileheader.time_division = ntohs(fileheader.time_division);
	mTimeDivision = fileheader.time_division;

	if (fileheader.format_type != 0 && fileheader.format_type != 1)
	{
		Printf(PRINT_HIGH, "MidiSong::_ParseSong: Only type 0 or type 1 MIDI files are supported.\n");
		return;
	}
	
	// Read all the tracks and merge them into one stream of events
	for (size_t i = 0; i < fileheader.num_tracks; i++)
	{
		std::list<MidiEvent*> *eventlist = I_ReadMidiTrack(mf);
		if (!eventlist)
		{
			Printf(PRINT_HIGH, "MidiSong::_ParseSong: Error reading track %d.\n", i + 1);
			return;
		}
		
		// add this track's list of events to the song's list
		while (!eventlist->empty())
		{
			mEvents.push_back(eventlist->front());
			eventlist->pop_front();
		}
		
		delete eventlist;
	}

	// sort the stream of events by start time 
	// (only needed if we're merging multiple tracks)
	if (fileheader.num_tracks > 1)
		mEvents.sort(I_CompareMidiEventTimes);
}
Exemplo n.º 7
0
//
// I_ReadMidiEvent()
//
// Parses a MEMFILE and will create and return a MidiEvent object of the
// next midi event stored in the MEMFILE.  It will return NULL if there is
// an error.
//
static MidiEvent* I_ReadMidiEvent(MEMFILE *mf, unsigned int start_time)
{
	if (!mf)
		return NULL;
	
	int delta_time = I_ReadVariableSizeInt(mf);
	if (delta_time == -1)
		return NULL;
		
	unsigned int event_time = start_time + delta_time;
	
	// Read event type
	byte val;
	if (!mem_fread(&val, sizeof(val), 1, mf))
		return NULL;
		
	midi_event_type_t eventtype = static_cast<midi_event_type_t>(val);
	static midi_event_type_t prev_eventtype = eventtype;
	
	// All event types have their top bit set.  Therefore, if
	// the top bit is not set, it is because we are using the "same
	// as previous event type" shortcut to save a byte.  Skip back
	// a byte so that we read this byte again.
	if ((eventtype & 0x80) == 0)
	{
		eventtype = prev_eventtype;
		mem_fseek(mf, -1, MEM_SEEK_CUR);	// put the byte back in the memfile
	}
	else
		prev_eventtype = eventtype;
	
	if (I_IsMidiSysexEvent(eventtype))
	{
		int length = I_ReadVariableSizeInt(mf);
		if (length == -1)
			return NULL;
		
		byte* data = I_ReadDataBlock(mf, length);
		if (!data)
			return NULL;

		return new MidiSysexEvent(event_time, data, length);
	}
	
	if (I_IsMidiMetaEvent(eventtype))
	{
		byte val;
		if (!mem_fread(&val, sizeof(val), 1, mf))
			return NULL;
		
		midi_meta_event_type_t metatype = static_cast<midi_meta_event_type_t>(val);
		
		int length = I_ReadVariableSizeInt(mf);
		if (length == -1)
			return NULL;

		byte* data = I_ReadDataBlock(mf, length);
		if (!data)
			return NULL;
			
		return new MidiMetaEvent(event_time, metatype, data, length);
	}

	// Channel Events only use the highest 4 bits to denote the type
	// Lower four bits denote the channel
	int channel = eventtype & 0x0F;
	eventtype = static_cast<midi_event_type_t>(int(eventtype) & 0xF0);
	
	if (I_IsMidiControllerEvent(eventtype))
	{
		byte val, param1 = 0;
		
		if (!mem_fread(&val, sizeof(val), 1, mf))
			return NULL;

		midi_controller_t controllertype = static_cast<midi_controller_t>(val);
		
		if (!mem_fread(&param1, sizeof(param1), 1, mf))
			return NULL;
		
		return new MidiControllerEvent(event_time, controllertype, channel, param1);
	}
	
	if (I_IsMidiChannelEvent(eventtype))
	{
		byte param1 = 0, param2 = 0;
		
		if (!mem_fread(&param1, sizeof(param1), 1, mf))
			return NULL;
			
		if (eventtype != MIDI_EVENT_PROGRAM_CHANGE && 
			eventtype != MIDI_EVENT_CHAN_AFTERTOUCH)
		{
			// this is an event that uses two parameters
			if (!mem_fread(&param2, sizeof(param2), 1, mf))
				return NULL;
		}
		
		return new MidiChannelEvent(event_time, eventtype, channel, param1, param2);
	}
		
	// none of the above?
	return NULL;
}