示例#1
0
文件: state.c 项目: phoe-nix/fceupsp
static int ReadStateChunks(FILE *st, int32 totalsize)
{
 int t;
 uint32 size;
 int ret=1;

 while(totalsize > 0)
 {
  t=fgetc(st);
  if(t==EOF) break;
  if(!read32le(&size,st)) break;
  totalsize -= size + 5;

  switch(t)
  {
   case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0;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,FCEUSND_STATEINFO,size)) ret=0;break;
   case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0;
       break;
   default: if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
  }
 }
 endo:
 return ret;
}
示例#2
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;
}
示例#3
0
/* This function is called by the game driver(NES, GB, GBA) to save a state. */
int MDFNSS_StateAction(StateMem *st, int load, int data_only, std::vector <SSDescriptor> &sections)
{
	std::vector<SSDescriptor>::iterator section;

	if(load)
	{
		char sname[4];

		for(section = sections.begin(); section != sections.end(); section++)
		{
			if(data_only)
			{
				ReadStateChunk(st, section->sf, ~0, 1);
			}
			else
			{
				int found = 0;
				uint32 tmp_size;
				uint32 total = 0;
				while(smem_read(st, (uint8 *)sname, 4) == 4)
				{
					if(!smem_read32le(st, &tmp_size)) return(0);
					total += tmp_size + 8;
					// Yay, we found the section
					if(!memcmp(sname, section->name, 4))
					{
						if(!ReadStateChunk(st, section->sf, tmp_size, 0))
						{
							printf("Error reading chunk: %.4s\n", section->name);
							return(0);
						}
						found = 1;
						break;
					}
					else
					{
						//puts("SEEK");
						if(smem_seek(st, tmp_size, SEEK_CUR) < 0)
						{
							puts("Chunk seek failure");
							return(0);
						}
					}
				}
				if(smem_seek(st, -(int)total, SEEK_CUR) < 0)
				{
					puts("Reverse seek error");
					return(0);
				}
				if(!found && !section->optional) // Not found. We are sad!
				{
					printf("Chunk missing: %.4s\n", section->name);
					return(0);
				}
			}
		}
	}
	else
		for(section = sections.begin(); section != sections.end(); section++)
		{
			if(!WriteStateChunk(st, section->name, section->sf, data_only))
				return(0);
		}
		return(1);
}
示例#4
0
static bool ReadStateChunks(EMUFILE* is, s32 totalsize)
{
	bool ret = true;
	bool haveInfo = false;
	
	s64 save_time = 0;
	u32 romsize = 0;
	u8 version_major = 0;
	u8 version_minor = 0;
	u8 version_build = 0;
	
	NDS_header header;
	SFORMAT SF_INFO[]={
		{ "GINF", 1, sizeof(header), &header},
		{ "GRSZ", 1, 4, &romsize},
		{ "DVMJ", 1, 1, &version_major},
		{ "DVMI", 1, 1, &version_minor},
		{ "DSBD", 1, 1, &version_build},
		{ "GREV", 1, 4, &svn_rev},
		{ "GTIM", 1, 8, &save_time},
		{ 0 }
	};
	memset(&header, 0, sizeof(header));

	while(totalsize > 0)
	{
		u32 size = 0;
		u32 t = 0;
		if(!read32le(&t,is))  { ret=false; break; }
		if(t == 0xFFFFFFFF) break;
		if(!read32le(&size,is))  { ret=false; break; }
		switch(t)
		{
			case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break;
			case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break;
			case 3: if(!cp15_loadstate(is,size)) ret=false; break;
			case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
			case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
			case 51: if(!nds_loadstate(is,size)) ret=false; break;
			case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break;
			case 61: if(!mmu_loadstate(is,size)) ret=false; break;
			case 7: if(!gpu_loadstate(is,size)) ret=false; break;
			case 8: if(!spu_loadstate(is,size)) ret=false; break;
			case 81: if(!mic_loadstate(is,size)) ret=false; break;
			case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break;
			case 91: if(!gfx3d_loadstate(is,size)) ret=false; break;
			case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break;
			case 101: break;
			case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break;
			case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break;
			case 130: if(!ReadStateChunk(is,SF_INFO,size)) ret=false; break;
			case 140: if(!s_slot1_loadstate(is, size)) ret=false; break;
			case 150: if(!s_slot2_loadstate(is, size)) ret=false; break;
			// reserved for future versions
			case 160:
			case 170:
			case 180:
				if(!ReadStateChunk(is,reserveChunks,size)) ret=false;
			break;
			// ============================
				
			default:
				return false;
		}
		if(!ret)
			return false;
	}

	return ret;
}
示例#5
0
/* This function is called by the game driver(NES, GB, GBA) to save a state. */
int MDFNSS_StateAction(void *st_p, int load, int data_only, std::vector <SSDescriptor> &sections)
{
    StateMem *st = (StateMem*)st_p;
    std::vector<SSDescriptor>::iterator section;

    if(load)
    {
        {
            char sname[32];

            for(section = sections.begin(); section != sections.end(); section++)
            {
                int found = 0;
                uint32 tmp_size;
                uint32 total = 0;

                while(smem_read(st, (uint8 *)sname, 32) == 32)
                {
                    if(smem_read32le(st, &tmp_size) != 4)
                        return(0);

                    total += tmp_size + 32 + 4;

                    // Yay, we found the section
                    if(!strncmp(sname, section->name, 32))
                    {
                        if(!ReadStateChunk(st, section->sf, tmp_size))
                        {
                            printf("Error reading chunk: %s\n", section->name);
                            return(0);
                        }
                        found = 1;
                        break;
                    }
                    else
                    {
                        if(smem_seek(st, tmp_size, SEEK_CUR) < 0)
                        {
                            puts("Chunk seek failure");
                            return(0);
                        }
                    }
                }
                if(smem_seek(st, -total, SEEK_CUR) < 0)
                {
                    puts("Reverse seek error");
                    return(0);
                }
                if(!found && !section->optional) // Not found.  We are sad!
                {
                    printf("Section missing:  %.32s\n", section->name);
                    return(0);
                }
            }
        }
    }
    else
    {
        for(section = sections.begin(); section != sections.end(); section++)
        {
            if(!WriteStateChunk(st, section->name, section->sf))
                return(0);
        }
    }

    return(1);
}
示例#6
0
//
// When updating this function make sure to adhere to the guarantees in state.h.
//
bool MDFNSS_StateAction(StateMem *sm, const unsigned load, const bool data_only, SFORMAT *sf, const char *sname, const bool optional) noexcept
{
 //printf("Section: %s %zu\n", sname, strlen(sname));

 if(MDFN_UNLIKELY(sm->deferred_error))
 {
  return(load ? false : true);
 }

 try
 {
  Stream* st = sm->st;

  if(MDFN_LIKELY(data_only))	// Not particularly likely, but it's more important to optimize for this code path...
  {
   static const uint8 SSFastCanary[8] = { 0x42, 0xA3, 0x10, 0x87, 0xBC, 0x6D, 0xF2, 0x79 };
   char sname_canary[32 + 8];

   if(load)
   {
    st->read(sname_canary, 32 + 8);

    if(strncmp(sname_canary, sname, 32))
     throw MDFN_Error(0, _("Section name mismatch in state loading fast path."));

    if(memcmp(sname_canary + 32, SSFastCanary, 8))
     throw MDFN_Error(0, _("Section canary is a zombie AAAAAAAAAAGH!"));

    FastRWChunk<true>(st, sf);
   }
   else
   {
    memset(sname_canary, 0, sizeof(sname_canary));
    strncpy(sname_canary, sname, 32);
    memcpy(sname_canary + 32, SSFastCanary, 8);
    st->write(sname_canary, 32 + 8);

    FastRWChunk<false>(st, sf);
   }
  }
  else
  {
   if(load)
   {
    char sname_tmp[32];
    bool found = false;
    uint32 tmp_size;
    uint32 total = 0;

    while(st->tell() < sm->sss_bound)
    {
     st->read(sname_tmp, 32);
     tmp_size = st->get_LE<uint32>();

     total += tmp_size + 32 + 4;

     // Yay, we found the section
     if(!strncmp(sname_tmp, sname, 32))
     {
      ReadStateChunk(st, sf, tmp_size, sm->svbe);
      found = true;
      break;
     } 
     else
     {
      st->seek(tmp_size, SEEK_CUR);
     }
    }

    st->seek(-(int64)total, SEEK_CUR);

    if(!found)
    {
     if(optional)
     {
      printf("Missing optional section: %.32s\n", sname);
      return(false);
     }
     else
      throw MDFN_Error(0, _("Section missing: %.32s"), sname);
    }
   }
   else
   {
    int64 data_start_pos;
    int64 end_pos;
    uint8 sname_tmp[32];

    memset(sname_tmp, 0, sizeof(sname_tmp));
    strncpy((char *)sname_tmp, sname, 32);

    if(strlen(sname) > 32)
     printf("Warning: section name is too long: %s\n", sname);

    st->write(sname_tmp, 32);

    st->put_LE<uint32>(0);                // We'll come back and write this later.

    data_start_pos = st->tell();
    SubWrite(st, sf);
    end_pos = st->tell();

    st->seek(data_start_pos - 4, SEEK_SET);
    st->put_LE<uint32>(end_pos - data_start_pos);
    st->seek(end_pos, SEEK_SET);
   }
  }
 }
 catch(...)
 {
  sm->deferred_error = std::current_exception();
  return(load ? false : true);
 }
 return(true);
}