コード例 #1
0
int32_t smem_putc(StateMem *st, int value)
{
   uint8_t tmpval = value;
   if(smem_write(st, &tmpval, 1) != 1)
      return(-1);
   return(1);
}
コード例 #2
0
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);
}
コード例 #3
0
ファイル: state.cpp プロジェクト: CaoCaoBeard/pcejin
int MDFNSS_SaveSM(StateMem *st, int wantpreview, int data_only, uint32 *fb, MDFN_Rect *LineWidths)
{
	static uint8 header[32]="MEDNAFENSVESTATE";
	int neowidth, neoheight;

	neowidth = MDFNGameInfo->ss_preview_width;
	neoheight = MDFNGameInfo->DisplayRect.h;

	if(!data_only)
	{
		memset(header+16,0,16);
		MDFN_en32lsb(header + 12, currFrameCounter);
		MDFN_en32lsb(header + 16, pcejin.lagFrameCounter);
//		MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC);
		MDFN_en32lsb(header + 24, neowidth);
		MDFN_en32lsb(header + 28, neoheight);
		smem_write(st, header, 32);
	}

	if(wantpreview)
	{
		uint8 *previewbuffer = (uint8 *)malloc(17 * neowidth * neoheight);

//		MakeStatePreview(previewbuffer, fb, LineWidths);
		smem_write(st, fb, 17 * neowidth * neoheight);

		free(previewbuffer);
	}

	// State rewinding code path hack, FIXME
	//if(data_only)
	//{
	// if(!MDFN_RawInputStateAction(st, 0, data_only))
	// return(0);
	//}

	if(!MDFNGameInfo->StateAction(st, 0, data_only))
		return(0);

	if(!data_only)
	{
		uint32 sizy = smem_tell(st);
		smem_seek(st, 16 + 4, SEEK_SET);
		smem_write32le(st, sizy);
	}
	return(1);
}
コード例 #4
0
int smem_write32le(StateMem *st, uint32_t b)
{
   uint8_t s[4];
   s[0]=b;
   s[1]=b>>8;
   s[2]=b>>16;
   s[3]=b>>24;
   return((smem_write(st, s, 4)<4)?0:4);
}
コード例 #5
0
ファイル: movie.cpp プロジェクト: stevestreza/OpenEmu
void MDFNMOV_RecordState(void)
{
    gzFile fp = slots[current - 1];
    StateMem sm;

    memset(&sm, 0, sizeof(StateMem));
    MDFNSS_SaveSM(&sm, 0, 0);

    if(MDFN_StateEvilIsRunning())
    {
        smem_putc(&RewindBuffer, MDFNNPCMD_LOADSTATE);
        smem_putc(&RewindBuffer, sm.len & 0xFF);
        smem_putc(&RewindBuffer, (sm.len >> 8) & 0xFF);
        smem_putc(&RewindBuffer, (sm.len >> 16) & 0xFF);
        smem_putc(&RewindBuffer, (sm.len >> 24) & 0xFF);
        smem_write(&RewindBuffer, sm.data, sm.len);
    }
    else
    {
コード例 #6
0
ファイル: state.cpp プロジェクト: CaoCaoBeard/pcejin
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);
}
コード例 #7
0
int MDFNSS_SaveSM(void *st_p, int, int, const void*, const void*, const void*)
{
   uint8_t header[32];
   StateMem *st = (StateMem*)st_p;
   static const char *header_magic = "MDFNSVST";
   int neowidth = 0, neoheight = 0;

   memset(header, 0, sizeof(header));
   memcpy(header, header_magic, 8);

   MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC);
   MDFN_en32lsb(header + 24, neowidth);
   MDFN_en32lsb(header + 28, neoheight);
   smem_write(st, header, 32);

   if(!StateAction(st, 0, 0))
      return(0);

   uint32_t sizy = st->loc;
   smem_seek(st, 16 + 4, SEEK_SET);
   smem_write32le(st, sizy);

   return(1);
}
コード例 #8
0
ファイル: state.cpp プロジェクト: acgleader/emu-ex-plus-alpha
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);
}
コード例 #9
0
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;
}
コード例 #10
0
ファイル: state.cpp プロジェクト: CaoCaoBeard/pcejin
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);
}
コード例 #11
0
ファイル: state.cpp プロジェクト: TOTOleHero/vbjin-ovr
int MDFNSS_SaveSM(StateMem *st, int wantpreview, int data_only, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths)
{
	static uint8 header[32]="MEDNAFENSVESTATE";
	int neowidth = 0, neoheight = 0;

	if(wantpreview)
	{
		bool is_multires = FALSE;

		// We'll want to use the nominal width if the source rectangle is > 25% off on either axis, or the source image has
		// multiple horizontal resolutions.
		neowidth = MDFNGameInfo->nominal_width;
		neoheight = MDFNGameInfo->nominal_height;

		if(LineWidths[0].w != ~0)
		{
			uint32 first_w = LineWidths[DisplayRect->y].w;

			for(int y = 0; y < DisplayRect->h; y++)
				if(LineWidths[DisplayRect->y + y].w != first_w)
				{
					puts("Multires!");
					is_multires = TRUE;
				}
		}

		if(!is_multires)
		{
			if(((double)DisplayRect->w / MDFNGameInfo->nominal_width) > 0.75 && ((double)DisplayRect->w / MDFNGameInfo->nominal_width) < 1.25)
				neowidth = DisplayRect->w;

			if(((double)DisplayRect->h / MDFNGameInfo->nominal_height) > 0.75 && ((double)DisplayRect->h / MDFNGameInfo->nominal_height) < 1.25)
				neoheight = DisplayRect->h;
		}
	}

	if(!data_only)
	{
		memset(header+16,0,16);
		MDFN_en32lsb(header + 12, currFrameCounter);
		MDFN_en32lsb(header + 16, pcejin.lagFrameCounter);
		// MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC);
		MDFN_en32lsb(header + 24, neowidth);
		MDFN_en32lsb(header + 28, neoheight);
		smem_write(st, header, 32);
	}

	if(wantpreview)
	{
		/*
		uint8 *previewbuffer = (uint8 *)malloc(4 * neowidth * neoheight);
		MDFN_Surface *dest_surface = new MDFN_Surface((uint32 *)previewbuffer, neowidth, neoheight, neowidth, surface->format.colorspace,
			surface->format.Rshift, surface->format.Gshift, surface->format.Bshift,
			surface->format.Ashift);
		MDFN_Rect dest_rect;

		dest_rect.x = 0;
		dest_rect.y = 0;
		dest_rect.w = neowidth;
		dest_rect.h = neoheight;

		// MDFN_ResizeSurface(surface, DisplayRect, (LineWidths[0].w != ~0) ? LineWidths : NULL, dest_surface, &dest_rect);

		{
			uint32 a, b = 0;
			for(a = 0; a < neowidth * neoheight * 4; a+=4)
			{
				uint32 c = *(uint32 *)&previewbuffer[a];
				int nr, ng, nb;

				surface->DecodeColor(c, nr, ng, nb);

				previewbuffer[b + 0] = nr;
				previewbuffer[b + 1] = ng;
				previewbuffer[b + 2] = nb;
				b += 3;
			}
		}*/
		//PREVIEWIMAGE
		smem_write(st, surface->pixels, 4 * neowidth * neoheight);

//		free(previewbuffer);
//		delete dest_surface;
	}

	// State rewinding code path hack, FIXME
	if(data_only)
	{
		// if(!MDFN_RawInputStateAction(st, 0, data_only))
		return(0);
	}

	if(!MDFNGameInfo->StateAction(st, 0, data_only))
		return(0);

	if(!data_only)
	{
		uint32 sizy = smem_tell(st);
		smem_seek(st, 16 + 4, SEEK_SET);
		smem_write32le(st, sizy);
	}
	return(1);
}
コード例 #12
0
ファイル: state.cpp プロジェクト: TOTOleHero/vbjin-ovr
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);
}
コード例 #13
0
int sbv_patch_enable_lmb()
{
	u8 buf[256];
	slib_exp_lib_t *modload_lib = (slib_exp_lib_t *)buf;
	smod_mod_info_t *loadfile_info = (smod_mod_info_t *)buf;
	void *pStartModule, *pLoadModuleBuffer, *lf_text_start, *patch_addr;
	u32 lf_rpc_dispatch, lf_jump_table, result;
	int nexps, id, i;

	memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));

	/* Locate the modload export library - it must have at least 16 exports.  */
	if ((nexps = slib_get_exp_lib("modload", modload_lib)) < 16)
		return -1;

	pStartModule = modload_lib->exports[8];
	pLoadModuleBuffer = modload_lib->exports[10];

	/* Now we need to find the loadfile module.  */
	memset(buf, 0, sizeof(smod_mod_info_t));
	if (!(id = smod_get_mod_by_name("LoadModuleByEE", loadfile_info)))
		return -1;

	/* Locate the loadfile RPC dispatch code, where the first 4 instructions look like:
	
	   27bdffe8	addiu	$sp, -24
	   2c820006	sltiu	$v0, $a0, 6
	   14400003	bnez	$v0, +12
	   afbf0010	sw	$ra, 0x10($sp)
	*/
	lf_text_start = (void *)(loadfile_info->text_start + 0x400);
	smem_read(lf_text_start, buf, sizeof buf);

	for (i = 0; i < sizeof buf; i += 4) {
		if ((*(u32 *)(buf + i) == 0x27bdffe8) &&
				(*(u32 *)(buf + i + 4) == 0x2c820006) &&
				(*(u32 *)(buf + i + 8) == 0x14400003) &&
				(*(u32 *)(buf + i + 12) == 0xafbf0010))
			break;
	}
	/* This is a special case: if the IOP was reset with an image that contains a
	   LOADFILE that supports LMB, we won't detect the dispatch routine.  If we
	   even got this far in the code then we can return success.  */
	if (i >= sizeof buf)
		return 0;

	/* We need to extract the address of the jump table, it's only 40 bytes in. */
	lf_rpc_dispatch = (u32)lf_text_start + i;
	smem_read((void *)lf_rpc_dispatch, buf, 40);

	lf_jump_table = (*(u16 *)(buf + 0x1c) << 16) + *(s16 *)(buf + 0x24);

	/* Now we can patch our subversive LoadModuleBuffer RPC call.  */
	SifInitIopHeap();
	if (!(patch_addr = SifAllocIopHeap(sizeof lmb_patch)))
		return -1;

	/* result is where the RPC return structure is stored.  */
	result = (u32)patch_addr + 96;
	lmb_patch[5] = JAL((u32)pLoadModuleBuffer);
	lmb_patch[7] = HI16(result);
	lmb_patch[9] = LO16(result);
	lmb_patch[15] = JAL((u32)pStartModule);

	SyncDCache(lmb_patch, (void *)(lmb_patch + 24));
	smem_write(patch_addr, lmb_patch, sizeof lmb_patch);

	/* Finally.  The last thing to do is to patch the loadfile RPC dispatch routine
	   so that it will jump to entry #6 in it's jump table, and to patch the jump
	   table itself.  */
	ee_kmode_enter();
	*(u32 *)(SUB_VIRT_MEM + lf_rpc_dispatch + 4) = 0x2c820007;
	*(u32 *)(SUB_VIRT_MEM + lf_jump_table + 0x18) = (u32)patch_addr;
	ee_kmode_exit();

	return 0;
}
コード例 #14
0
ファイル: movie.cpp プロジェクト: stevestreza/OpenEmu
// Donuts are a tasty treat and delicious with powdered sugar.
void MDFNMOV_AddJoy(void *donutdata, uint32 donutlen)
{
    gzFile fp;

    if(!current) return;	/* Not playback nor recording. */
    if(current < 0)	/* Playback */
    {
        int t;

        fp = slots[-1 - current];

        while((t = gzgetc(fp)) >= 0 && t)
        {
            if(t == MDFNNPCMD_LOADSTATE)
            {
                uint32 len;
                StateMem sm;
                len = gzgetc(fp);
                len |= gzgetc(fp) << 8;
                len |= gzgetc(fp) << 16;
                len |= gzgetc(fp) << 24;
                if(len >= 5 * 1024 * 1024) // A sanity limit of 5MiB
                {
                    StopPlayback();
                    return;
                }
                memset(&sm, 0, sizeof(StateMem));
                sm.len = len;
                sm.data = (uint8 *)malloc(len);
                if(gzread(fp, sm.data, len) != len)
                {
                    StopPlayback();
                    return;
                }
                if(!MDFNSS_LoadSM(&sm, 0, 0))
                {
                    StopPlayback();
                    return;
                }
            }
            else
                MDFN_DoSimpleCommand(t);
        }
        if(t < 0)
        {
            StopPlayback();
            return;
        }

        if(gzread(fp, donutdata, donutlen) != donutlen)
        {
            StopPlayback();
            return;
        }
    }
    else			/* Recording */
    {
        if(MDFN_StateEvilIsRunning())
        {
            smem_putc(&RewindBuffer, 0);
            smem_write(&RewindBuffer, donutdata, donutlen);
        }
        else
        {
            fp = slots[current - 1];
            gzputc(fp, 0);
            gzwrite(fp, donutdata, donutlen);
        }
    }
}
コード例 #15
0
ファイル: state.cpp プロジェクト: acgleader/emu-ex-plus-alpha
int MDFNSS_SaveSM(StateMem *st, int wantpreview_and_ts, int data_only, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths)
{
	static const char *header_magic = "MDFNSVST";
  uint8 header[32];
	int neowidth = 0, neoheight = 0;

	memset(header, 0, sizeof(header));

	if(wantpreview_and_ts)
	{
	 bool is_multires = FALSE;

	 // We'll want to use the nominal width if the source rectangle is > 25% off on either axis, or the source image has
	 // multiple horizontal resolutions.
	 neowidth = MDFNGameInfo->nominal_width;
	 neoheight = MDFNGameInfo->nominal_height;

	 if(LineWidths[0].w != ~0)
 	 {
	  uint32 first_w = LineWidths[DisplayRect->y].w;

	  for(int y = 0; y < DisplayRect->h; y++)
	   if(LineWidths[DisplayRect->y + y].w != first_w)
	   {
		   MDFN_printf("Multires!");
	    is_multires = TRUE;
	   }
	 }

	 if(!is_multires)
	 {
	  if(((SysDDec)DisplayRect->w / MDFNGameInfo->nominal_width) > 0.75  && ((SysDDec)DisplayRect->w / MDFNGameInfo->nominal_width) < 1.25)
	   neowidth = DisplayRect->w;

          if(((SysDDec)DisplayRect->h / MDFNGameInfo->nominal_height) > 0.75  && ((SysDDec)DisplayRect->h / MDFNGameInfo->nominal_height) < 1.25)
	   neoheight = DisplayRect->h;
	 }
	}

	if(!data_only)
	{
		memcpy(header, header_magic, 8);

		if(wantpreview_and_ts)
			  MDFN_en64lsb(header + 8, time(NULL));

	 MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC);
	 MDFN_en32lsb(header + 24, neowidth);
	 MDFN_en32lsb(header + 28, neoheight);
	 smem_write(st, header, 32);
	}

	if(wantpreview_and_ts)
	{
         uint8 *previewbuffer = (uint8 *)malloc(4 * neowidth * neoheight);
	 MDFN_Surface *dest_surface = new MDFN_Surface((uint32 *)previewbuffer, neowidth, neoheight, neowidth, surface->format);
	 MDFN_Rect dest_rect;

	 dest_rect.x = 0;
	 dest_rect.y = 0;
	 dest_rect.w = neowidth;
	 dest_rect.h = neoheight;

	 MDFN_ResizeSurface(surface, DisplayRect, (LineWidths[0].w != ~0) ? LineWidths : NULL, dest_surface, &dest_rect);

	 {
	  uint32 a, b = 0;
	  for(a = 0; a < neowidth * neoheight * 4; a+=4)
	  {
	   uint32 c = *(uint32 *)&previewbuffer[a];
	   int nr, ng, nb;

	   surface->DecodeColor(c, nr, ng, nb);

	   previewbuffer[b + 0] = nr;
	   previewbuffer[b + 1] = ng;
           previewbuffer[b + 2] = nb;
	   b += 3;
	  }
	 }

         smem_write(st, previewbuffer, 3 * neowidth * neoheight);

	 free(previewbuffer);
	 delete dest_surface;
	}

        // State rewinding code path hack, FIXME
        if(data_only)
        {
         if(!MDFN_RawInputStateAction(st, 0, data_only))
          return(0);
        }

	if(!MDFNGameInfo->StateAction(st, 0, data_only))
	 return(0);

	if(!data_only)
	{
	 uint32 sizy = smem_tell(st);
	 smem_seek(st, 16 + 4, SEEK_SET);
	 smem_write32le(st, sizy);
	}
	return(1);
}