Beispiel #1
0
static int WriteStateChunk(MEM_TYPE *st, int type, SFORMAT *sf) {
	int bsize;

	fputc(type, st);

	bsize = SubWrite(0, sf);
	write32le(bsize, st);

	if (!SubWrite(st, sf)) return(0);
	return(bsize + 5);
}
Beispiel #2
0
static int savestate_WriteChunk(EMUFILE* os, int type, const SFORMAT *sf)
{
	write32le(type,os);
	if(!sf) return 4;
	int bsize = SubWrite((EMUFILE*)0,sf);
	write32le(bsize,os);

	if(!SubWrite(os,sf))
	{
		return 8;
	}
	return (bsize+8);
}
Beispiel #3
0
static int WriteStateChunk(MEMFILE *st, int type, SFORMAT *sf)
{
 int bsize;

 mem_fputc(type,st);

 bsize=SubWrite(0,sf);
 mem_write32le(bsize,st);

 if(!SubWrite(st,sf))
 {
	 return(0);
 }
 return (bsize+5);
}
static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf)
{
   int32_t data_start_pos;
   int32_t end_pos;

   uint8_t 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);

   smem_write(st, sname_tmp, 32);

   smem_write32le(st, 0);                // We'll come back and write this later.

   data_start_pos = st->loc;

   if(!SubWrite(st, sf))
      return(0);

   end_pos = st->loc;

   smem_seek(st, data_start_pos - 4, SEEK_SET);
   smem_write32le(st, end_pos - data_start_pos);
   smem_seek(st, end_pos, SEEK_SET);

   return(end_pos - data_start_pos);
}
Beispiel #5
0
static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf, int data_only)
{
	int bsize;

	if(!data_only)
		smem_write(st, (uint8 *)sname, 4);

	bsize=SubWrite(0,sf, data_only, NULL);

	if(!data_only)
		smem_write32le(st, bsize);

	if(!SubWrite(st,sf, data_only, NULL)) return(0);

	if(data_only)
		return(bsize);
	else
		return (bsize + 4 + 4);
}
Beispiel #6
0
static void SubWrite(Stream *st, SFORMAT *sf)
{
 while(sf->size || sf->name)	// Size can sometimes be zero, so also check for the text name.  These two should both be zero only at the end of a struct.
 {
  if(!sf->size || !sf->v)
  {
   sf++;
   continue;
  }

  if(sf->size == (uint32)~0)		/* Link to another struct.	*/
  {
   SubWrite(st, (SFORMAT *)sf->v);

   sf++;
   continue;
  }

  int32 bytesize = sf->size;
  char nameo[1 + 255];
  const int slen = strlen(sf->name);

  if(slen > 255)
   throw MDFN_Error(0, _("State variable name \"%s\" is too long."), sf->name);

  memcpy(&nameo[1], sf->name, slen);
  nameo[0] = slen;

  st->write(nameo, 1 + nameo[0]);
  st->put_LE<uint32>(bytesize);

  // Special case for the evil bool type, to convert bool to 1-byte elements.
  if(sf->flags & MDFNSTATE_BOOL)
  {
   for(int32 bool_monster = 0; bool_monster < bytesize; bool_monster++)
   {
    uint8 tmp_bool = ((bool *)sf->v)[bool_monster];
    //printf("Bool write: %.31s\n", sf->name);
    st->write(&tmp_bool, 1);
   }
  }
  else
  {
   st->write((uint8 *)sf->v, bytesize);
  }

  sf++; 
 }
}
Beispiel #7
0
static int SubWrite(FILE *st, SFORMAT *sf)
{
 uint32 acc=0;

 while(sf->v)
 {
  if(sf->s==~0)    /* Link to another struct.  */
  {
   uint32 tmp;

   if(!(tmp=SubWrite(st,(SFORMAT *)sf->v)))
    return(0);
   acc+=tmp;
   sf++;
   continue;
  }

  acc+=8;      /* Description + size */
  acc+=sf->s&(~RLSB);

  if(st)      /* Are we writing or calculating the size of this block? */
  {
   fwrite(sf->desc,1,4,st);
   write32le(sf->s&(~RLSB),st);

   #ifndef LSB_FIRST
   if(sf->s&RLSB)
    FlipByteOrder(sf->v,sf->s&(~RLSB));
   #endif

   fwrite((uint8 *)sf->v,1,sf->s&(~RLSB),st);
   /* Now restore the original byte order. */
   #ifndef LSB_FIRST
   if(sf->s&RLSB)
    FlipByteOrder(sf->v,sf->s&(~RLSB));
   #endif
  }
  sf++;
 }

 return(acc);
}
Beispiel #8
0
static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf, int data_only)
{
 int32 data_start_pos;
 int32 end_pos;

 if(!data_only)
 {
  uint8 sname_tmp[32];

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

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

  smem_write(st, sname_tmp, 32);

  smem_write32le(st, 0);                // We'll come back and write this later.
 }

 data_start_pos = smem_tell(st);

 if(!SubWrite(st, sf, data_only))
  return(0);

 end_pos = smem_tell(st);

 if(!data_only)
 {
  smem_seek(st, data_start_pos - 4, SEEK_SET);
  smem_write32le(st, end_pos - data_start_pos);
  smem_seek(st, end_pos, SEEK_SET);
 }

 return(end_pos - data_start_pos);
}
static bool SubWrite(StateMem *st, SFORMAT *sf, const char *name_prefix = NULL)
{
   while(sf->size || sf->name)	// Size can sometimes be zero, so also check for the text name.  These two should both be zero only at the end of a struct.
   {
      if(!sf->size || !sf->v)
      {
         sf++;
         continue;
      }

      if(sf->size == (uint32_t)~0)		/* Link to another struct.	*/
      {
         if(!SubWrite(st, (SFORMAT *)sf->v, name_prefix))
            return(0);

         sf++;
         continue;
      }

      int32_t bytesize = sf->size;

      char nameo[1 + 256];
      int slen;

      slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name);
      nameo[0] = slen;

      if(slen >= 255)
      {
         printf("Warning:  state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen);
         slen = 255;
      }

      smem_write(st, nameo, 1 + nameo[0]);
      smem_write32le(st, bytesize);

#ifdef MSB_FIRST
      /* Flip the byte order... */
      if(sf->flags & MDFNSTATE_BOOL)
      {

      }
      else if(sf->flags & MDFNSTATE_RLSB64)
         Endian_A64_NE_to_LE(sf->v, bytesize / sizeof(uint64_t));
      else if(sf->flags & MDFNSTATE_RLSB32)
         Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32_t));
      else if(sf->flags & MDFNSTATE_RLSB16)
         Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16_t));
      else if(sf->flags & RLSB)
         Endian_V_NE_to_LE(sf->v, bytesize);
#endif

      // Special case for the evil bool type, to convert bool to 1-byte elements.
      // Don't do it if we're only saving the raw data.
      if(sf->flags & MDFNSTATE_BOOL)
      {
         for(int32_t bool_monster = 0; bool_monster < bytesize; bool_monster++)
         {
            uint8_t tmp_bool = ((bool *)sf->v)[bool_monster];
            //printf("Bool write: %.31s\n", sf->name);
            smem_write(st, &tmp_bool, 1);
         }
      }
      else
         smem_write(st, (uint8_t *)sf->v, bytesize);

#ifdef MSB_FIRST
      /* Now restore the original byte order. */
      if(sf->flags & MDFNSTATE_BOOL)
      {

      }
      else if(sf->flags & MDFNSTATE_RLSB64)
         Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64_t));
      else if(sf->flags & MDFNSTATE_RLSB32)
         Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32_t));
      else if(sf->flags & MDFNSTATE_RLSB16)
         Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16_t));
      else if(sf->flags & RLSB)
         Endian_V_LE_to_NE(sf->v, bytesize);
#endif
      sf++; 
   }

   return true;
}
Beispiel #10
0
static int SubWrite(StateMem *st, SFORMAT *sf, int data_only, gzFile fp)
{
	uint32 acc=0;

	// FIXME? It's kind of slow, and we definitely don't want it on with state rewinding...
	//ValidateSFStructure(sf);

	while(sf->s || sf->desc) // Size can sometimes be zero, so also check for the text description. These two should both be zero only at the end of a struct.
	{
		if(!sf->s || !sf->v)
		{
			sf++;
			continue;
		}
		if(sf->s == (uint32)~0) /* Link to another struct. */
		{
			uint32 tmp;

			if(!(tmp=SubWrite(st,(SFORMAT *)sf->v, data_only, fp)))
				return(0);
			acc+=tmp;
			sf++;
			continue;
		}

		if(!data_only)
			acc+=32 + 4; /* Description + size */

		int32 bytesize = sf->s&(~(MDFNSTATE_RLSB32 | MDFNSTATE_RLSB16 | RLSB));

		acc += bytesize;
		//printf("%d %d %d\n", bytesize, data_only, fp);
		if(st || fp) /* Are we writing or calculating the size of this block? */
		{
			if(!data_only)
			{
				char desco[32];
				int slen = strlen(sf->desc);

				memset(desco, 0, 32);

				if(slen > 32)
				{
					printf("Warning: state variable name too long: %s %d\n", sf->desc, slen);
					slen = 32;
				}

				memcpy(desco, sf->desc, slen);
				smem_write(st, desco, 32);
				smem_write32le(st, bytesize);

				/* Flip the byte order... */
				if(sf->s & MDFNSTATE_RLSB32)
					Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32));
				else if(sf->s & MDFNSTATE_RLSB16)
					Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16));
				else if(sf->s&RLSB)
					Endian_V_NE_to_LE(sf->v, bytesize);
			}

			if(fp)
			{
				//printf("Wrote: %d\n", bytesize);
				gzwrite(fp, sf->v, bytesize);
			}
			else
			{
				smem_write(st, (uint8 *)sf->v, bytesize);
			}

			if(!data_only)
			{
				/* Now restore the original byte order. */
				if(sf->s & MDFNSTATE_RLSB32)
					Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32));
				else if(sf->s & MDFNSTATE_RLSB16)
					Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16));
				else if(sf->s&RLSB)
					Endian_V_LE_to_NE(sf->v, bytesize);
			}
		}
		sf++;
	}

	return(acc);
}
Beispiel #11
0
static bool SubWrite(StateMem *st, SFORMAT *sf, int data_only, const char *name_prefix = NULL)
{
 // FIXME?  It's kind of slow, and we definitely don't want it on with state rewinding...
 //if(!data_only) 
 // ValidateSFStructure(sf);

 while(sf->size || sf->name)	// Size can sometimes be zero, so also check for the text name.  These two should both be zero only at the end of a struct.
 {
  if(!sf->size || !sf->v)
  {
   sf++;
   continue;
  }

  if(sf->size == (uint32)~0)		/* Link to another struct.	*/
  {
   if(!SubWrite(st, (SFORMAT *)sf->v, data_only, name_prefix))
    return(0);

   sf++;
   continue;
  }

  int32 bytesize = sf->size;

  // If we're only saving the raw data, and we come across a bool type, we save it as it is in memory, rather than converting it to
  // 1-byte.  In the SFORMAT structure, the size member for bool entries is the number of bool elements, not the total in-memory size,
  // so we adjust it here.
  if(data_only && (sf->flags & MDFNSTATE_BOOL))
  {
   bytesize *= sizeof(bool);
  }
  
  if(!data_only)
  {
   char nameo[1 + 256];
   int slen;

   slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name);
   nameo[0] = slen;

   if(slen >= 255)
   {
    printf("Warning:  state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen);
    slen = 255;
   }

   smem_write(st, nameo, 1 + nameo[0]);
   smem_write32le(st, bytesize);

   /* Flip the byte order... */
   if(sf->flags & MDFNSTATE_BOOL)
   {

   }
   else if(sf->flags & MDFNSTATE_RLSB64)
    Endian_A64_NE_to_LE(sf->v, bytesize / sizeof(uint64));
   else if(sf->flags & MDFNSTATE_RLSB32)
    Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32));
   else if(sf->flags & MDFNSTATE_RLSB16)
    Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16));
   else if(sf->flags & RLSB)
    Endian_V_NE_to_LE(sf->v, bytesize);
  }
    
  // Special case for the evil bool type, to convert bool to 1-byte elements.
  // Don't do it if we're only saving the raw data.
  if((sf->flags & MDFNSTATE_BOOL) && !data_only)
  {
   for(int32 bool_monster = 0; bool_monster < bytesize; bool_monster++)
   {
    uint8 tmp_bool = ((bool *)sf->v)[bool_monster];
    //printf("Bool write: %.31s\n", sf->name);
    smem_write(st, &tmp_bool, 1);
   }
  }
  else
   smem_write(st, (uint8 *)sf->v, bytesize);

  if(!data_only)
  {
   /* Now restore the original byte order. */
   if(sf->flags & MDFNSTATE_BOOL)
   {

   }
   else if(sf->flags & MDFNSTATE_RLSB64)
    Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64));
   else if(sf->flags & MDFNSTATE_RLSB32)
    Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32));
   else if(sf->flags & MDFNSTATE_RLSB16)
    Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16));
   else if(sf->flags & RLSB)
    Endian_V_LE_to_NE(sf->v, bytesize);
  }
  sf++; 
 }

 return(TRUE);
}
Beispiel #12
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);
}