Exemplo n.º 1
0
WAVRecord::WAVRecord(const char *path, double SoundRate_arg, uint32 SoundChan_arg) : wavfile(path, FileStream::MODE_WRITE_SAFE)
{
 Finished = false;
 PCMBytesWritten = 0;

 SoundRate = SoundRate_arg;
 SoundChan = SoundChan_arg;

 memset(&raw_headers, 0, sizeof(raw_headers));

 MDFN_en32msb(&raw_headers[0x00], 0x52494646);	// "RIFF"
 // @ 0x04 = total file size - 8 bytes
 MDFN_en32msb(&raw_headers[0x08], 0x57415645);	// "WAVE"


 MDFN_en32msb(&raw_headers[0x0C], 0x666d7420);	// "fmt "
 MDFN_en32lsb(&raw_headers[0x10], 16);
 MDFN_en16lsb(&raw_headers[0x14], 1);		// PCM format
 MDFN_en16lsb(&raw_headers[0x16], SoundChan);	// Number of sound channels
 MDFN_en32lsb(&raw_headers[0x18], SoundRate);	// Sampling rate
 MDFN_en32lsb(&raw_headers[0x1C], SoundRate * SoundChan * sizeof(int16));	//Byte rate
 MDFN_en16lsb(&raw_headers[0x20], SoundChan * sizeof(int16));	// Block("audio frame" in Mednafen) alignment
 MDFN_en16lsb(&raw_headers[0x22], sizeof(int16) * 8);	// Bits per sample.

 MDFN_en32msb(&raw_headers[0x24], 0x64617461);	// "data"
 // @ 0x28 = bytes of PCM data following

 wavfile.write(raw_headers, sizeof(raw_headers));
}
void InputDevice_DualShock::UpdateInput(const void *data)
{
    uint8 *d8 = (uint8 *)data;

    buttons[0] = d8[0];
    buttons[1] = d8[1];
    cur_ana_button_state = d8[2] & 0x01;

    for(int stick = 0; stick < 2; stick++)
    {
        for(int axis = 0; axis < 2; axis++)
        {
            int32 tmp;

            tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767);
            tmp >>= 8;

            axes[stick][axis] = tmp;
        }
    }

    if(da_rumble_compat == false)
    {
        uint8 sneaky_weaky = 0;

        if(rumble_param[0] == 0x01)
            sneaky_weaky = 0xFF;

        MDFN_en32lsb(&d8[4 + 32 + 0], (sneaky_weaky << 0) | (rumble_param[1] << 8));
    }
    else
    {
        uint8 sneaky_weaky = 0;

        if(((rumble_param[0] & 0xC0) == 0x40) && ((rumble_param[1] & 0x01) == 0x01))
            sneaky_weaky = 0xFF;

        MDFN_en32lsb(&d8[4 + 32 + 0], sneaky_weaky << 0);
    }

//printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]);

//
//
//
    CheckManualAnaModeChange();

    if(am_prev_info != analog_mode || aml_prev_info != analog_mode_locked)
    {
        MDFN_DispMessage(_("%s: Analog mode is %s(%s)."), gp_name.c_str(), analog_mode ? _("on") : _("off"), analog_mode_locked ? _("locked") : _("unlocked"));
    }
    am_prev_info = analog_mode;
    aml_prev_info = analog_mode_locked;
}
Exemplo n.º 3
0
void WAVRecord::Finish(void)
{
 if(Finished)
  return;

 MDFN_en32lsb(&raw_headers[0x04], std::min(wavfile.tell() - 8, (int64)0xFFFFFFFFLL));

 MDFN_en32lsb(&raw_headers[0x28], std::min(PCMBytesWritten, (int64)0xFFFFFFFFLL));

 wavfile.seek(0, SEEK_SET);
 wavfile.write(raw_headers, sizeof(raw_headers));
 wavfile.close();

 Finished = true;
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
static void SendCommand(uint8 cmd, uint32 len, const void* data = NULL)
{
 uint8 buf[1 + LocalInputStateSize + 4]; // Command, unused, command length

 memset(buf, 0, sizeof(buf));

 buf[0] = cmd;
 MDFN_en32lsb(&buf[1 + LocalInputStateSize], len);
 MDFND_SendData(buf,LocalInputStateSize + 1 + 4);

 if(data != NULL)
 {
  MDFND_SendData(data, len);
 }

 //DelayBuffer.push_back(std::vector<uint8>());
 //DelayBuffer.
}
Exemplo n.º 7
0
static void SendState(void)
{
 StateMem sm;
 uLongf clen;
 std::vector<uint8> cbuf;

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

 if(!MDFNSS_SaveSM(&sm, 0, 0))
 {
  throw MDFN_Error(0, _("Error during save state generation."));
 }

 clen = sm.len + sm.len / 1000 + 12;
 cbuf.resize(4 + clen);
 MDFN_en32lsb(&cbuf[0], sm.len);
 compress2((Bytef *)&cbuf[0] + 4, &clen, (Bytef *)sm.data, sm.len, 7);
 free(sm.data);

 SendCommand(MDFNNPCMD_LOADSTATE, clen + 4, &cbuf[0]);
}
Exemplo n.º 8
0
void InputDevice_DualShock::UpdateInput(const void *data)
{
 uint8 *d8 = (uint8 *)data;
 uint8* const rumb_dp = &d8[3 + 16];

 buttons[0] = d8[0];
 buttons[1] = d8[1];
 cur_ana_button_state = d8[2] & 0x01;

 for(int stick = 0; stick < 2; stick++)
 {
  for(int axis = 0; axis < 2; axis++)
  {
     const uint8* aba = &d8[3] + stick * 8 + axis * 4;
   int32 tmp;

   //revert to 0.9.33, should be fixed on libretro side instead
   //tmp = 32767 + MDFN_de16lsb(&aba[0]) - MDFN_de16lsb(&aba[2]);
   //tmp = (tmp * 0x100) / 0xFFFF;
   
   tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767);
   tmp >>= 8;
   axes[stick][axis] = tmp;
  }
 }

 //printf("%3d:%3d, %3d:%3d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]);

 //printf("RUMBLE: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", rumble_magic[0], rumble_magic[1], rumble_magic[2], rumble_magic[3], rumble_magic[4], rumble_magic[5]);
 //printf("%d, 0x%02x 0x%02x\n", da_rumble_compat, rumble_param[0], rumble_param[1]);
 if(da_rumble_compat == false)
 {
  uint8 sneaky_weaky = 0;

  if(rumble_param[0] == 0x01)
   sneaky_weaky = 0xFF;

   //revert to 0.9.33, should be fixed on libretro side instead
   //MDFN_en16lsb(rumb_dp, (sneaky_weaky << 0) | (rumble_param[1] << 8));
   
   MDFN_en32lsb(&d8[4 + 32 + 0], (sneaky_weaky << 0) | (rumble_param[1] << 8));
 }
 else
 {
  uint8 sneaky_weaky = 0;

  if(((rumble_param[0] & 0xC0) == 0x40) && ((rumble_param[1] & 0x01) == 0x01))
   sneaky_weaky = 0xFF;

   //revert to 0.9.33, should be fixed on libretro side instead
   //MDFN_en16lsb(rumb_dp, sneaky_weaky << 0);
   MDFN_en32lsb(&d8[4 + 32 + 0], sneaky_weaky << 0);
 }

 //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]);

 //
 //
 //
 CheckManualAnaModeChange();

 if(am_prev_info != analog_mode || aml_prev_info != analog_mode_locked)
 {
	//MDFN_DispMessage(_("%s: Analog mode is %s(%s)."), gp_name.c_str(), analog_mode ? _("on") : _("off"), analog_mode_locked ? _("locked") : _("unlocked"));
    MDFN_DispMessage(_("%s: Analog toggle is %s, sticks are %s"), gp_name.c_str(), amct_enabled ? _("ENABLED") : _("DISABLED"), analog_mode ? _("ON") : _("OFF"));  
 }
 aml_prev_info = analog_mode_locked;
 am_prev_info = analog_mode;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
0
void MDFNSS_SaveSM(Stream *st, bool data_only, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const int32 *LineWidths)
{
	StateMem sm(st);

	if(data_only)
	{
	 MDFN_StateAction(&sm, 0, true);
	 sm.ThrowDeferred();
	}
	else
	{
	 static const char *header_magic = "MDFNSVST";
	 int64 start_pos;
         uint8 header[32];
	 int neowidth = 0, neoheight = 0;

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

	 if(surface && DisplayRect && LineWidths)
	 {
	  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] != ~0)
 	  {
	   int32 first_w = LineWidths[DisplayRect->y];

	   for(int y = 0; y < DisplayRect->h; y++)
	   {
	    if(LineWidths[DisplayRect->y + y] != 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;
	  }
	 }

	 memcpy(header, header_magic, 8);

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

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

	 start_pos = st->tell();
	 st->write(header, 32);

	 if(surface && DisplayRect && LineWidths)
	 {
	  //
	  // TODO: Make work with 8bpp and 16bpp.
	  //
	  MDFN_Surface dest_surface(NULL, 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, &dest_surface, &dest_rect);

	  {
	   uint32* previewbuffer = dest_surface.pixels;
	   uint8* previewbuffer8 = (uint8*)previewbuffer;

	   for(int32 a = 0; a < neowidth * neoheight; a++)
	   {
	    int nr, ng, nb;

	    surface->DecodeColor(previewbuffer[a], nr, ng, nb);

	    previewbuffer8[0] = nr;
	    previewbuffer8[1] = ng;
	    previewbuffer8[2] = nb;

	    previewbuffer8 += 3;
	   }
	  }

          st->write((uint8*)dest_surface.pixels, 3 * neowidth * neoheight);
	 }

	 MDFN_StateAction(&sm, 0, data_only);
	 sm.ThrowDeferred();

	 {
	  int64 end_pos = st->tell();
	  uint32 pv = (end_pos - start_pos) & 0x7FFFFFFF;

	  #ifdef MSB_FIRST
	  pv |= 0x80000000;
	  #endif

	  st->seek(start_pos + 16 + 4, SEEK_SET);
	  st->put_LE<uint32>(pv);
	  st->seek(end_pos, SEEK_SET);		// Seek to just beyond end of save state before returning.
	 }
	}
}
Exemplo n.º 11
0
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16])
{
 try
 {
  const char *emu_id = PACKAGE " " MEDNAFEN_VERSION;
  const uint32 local_players = MDFN_GetSettingUI("netplay.localplayers");
  const std::string nickname = MDFN_GetSettingS("netplay.nick");
  const std::string game_key = MDFN_GetSettingS("netplay.gamekey");
  const std::string connect_password = MDFN_GetSettingS("netplay.password");
  login_data_t *ld = NULL;
  std::vector<uint8> sendbuf;

  MDFNnetplay = true;

  sendbuf.resize(4 + sizeof(login_data_t) + nickname.size() + strlen(emu_id));

  MDFN_en32lsb(&sendbuf[0], sendbuf.size() - 4);
  ld = (login_data_t*)&sendbuf[4];

  if(game_key != "")
  {
   md5_context md5;
   uint8 md5out[16];

   md5.starts();
   md5.update(MDFNGameInfo->MD5, 16);
   md5.update((uint8 *)game_key.c_str(), game_key.size());
   md5.finish(md5out);
   memcpy(ld->gameid, md5out, 16);
  }
  else
   memcpy(ld->gameid, MDFNGameInfo->MD5, 16);

  if(connect_password != "")
  {
   md5_context md5;
   uint8 md5out[16];

   md5.starts();
   md5.update((uint8*)connect_password.c_str(), connect_password.size());
   md5.finish(md5out);
   memcpy(ld->password, md5out, 16);
  }

  assert(MDFNGameInfo->InputInfo->InputPorts <= 16);

  ld->protocol_version = 3;

  // Set input device number thingies here.
  ld->total_controllers = MDFNGameInfo->InputInfo->InputPorts; // Total number of ports

  MDFN_en32lsb(ld->emu_name_len, strlen(emu_id));

  // Controller data sizes.
  for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
   ld->controller_data_size[x] = PortDataLenCache[x];

  // Controller types
  for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
  {
   unsigned ct = 0;

   for(int d = 0; d < MDFNGameInfo->InputInfo->Types[x].NumTypes; d++)
   {
    if(!strcasecmp(MDFNGameInfo->InputInfo->Types[x].DeviceInfo[d].ShortName, PortDeviceCache[x]))
    {
     ct = d;
     break;
    }
   }
   //printf("%d, 0x%02x\n", x, ct);

   ld->controller_type[x] = ct;
  }

  ld->local_players = local_players;

  if(nickname != "")
   memcpy(&sendbuf[4 + sizeof(login_data_t)], nickname.c_str(), nickname.size());

  memcpy(&sendbuf[4 + sizeof(login_data_t) + nickname.size()], emu_id, strlen(emu_id));

  MDFND_SendData(&sendbuf[0], sendbuf.size());

  TotalInputStateSize = 0;
  for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
    TotalInputStateSize += PortDataLenCache[x];

  // Hack so the server can always encode its command data length properly(a matching "hack" exists in the server).
  if(TotalInputStateSize < 4)
   TotalInputStateSize = 4;

  TotalInputStateSize = TotalInputStateSize;

  LocalPlayersMask = 0;
  LocalInputStateSize = 0; 
  Joined = false;

  //
  //
  //
  MDFN_FlushGameCheats(0);	/* Save our pre-netplay cheats. */

  if(MDFNMOV_IsPlaying())		/* Recording's ok during netplay, playback is not. */
   MDFNMOV_Stop();
 }
 catch(std::exception &e)
 {
  NetError("%s", e.what());
  return(false);
 }

 //printf("%d\n", TotalInputStateSize);

 return(1);
}
Exemplo n.º 12
0
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);
}