static int ReadBlock (const char *key, void *block, int max_len, STREAM snap)
{
    char buffer [20];
    int len = 0;
    int rem = 0;
    
    if (READ_STREAM (buffer, 11, snap) != 11 ||
	strncmp (buffer, key, 4) != 0 ||
	(len = atoi (&buffer [4])) == 0)
	return (WRONG_FORMAT);

    if (len > max_len)
    {
	rem = len - max_len;
	len = max_len;
    }
    if (READ_STREAM (block, len, snap) != len)
	return (WRONG_FORMAT);

    if (rem)
    {
	char *junk = new char [rem];
	READ_STREAM (junk, rem, snap);
	delete[] junk;
    }
	
    return (SUCCESS);
}
Esempio n. 2
0
void S9xMSU1PostLoadState(void)
{
	if (DataOpen())
	{
        REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
	}

	if (MSU1.MSU1_STATUS & AudioPlaying)
	{
		if (AudioOpen())
		{
            REVERT_STREAM(audioStream, 4, 0);
            READ_STREAM((char *)&audioLoopPos, 4, audioStream);
			audioLoopPos = GET_LE32(&audioLoopPos);
			audioLoopPos <<= 2;
			audioLoopPos += 8;

            REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
		}
		else
		{
			MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
			MSU1.MSU1_STATUS |= AudioError;
		}
	}

	bufPos = 0;
	bufBegin = 0;
	bufEnd = 0;

	partial_frames = 0;
}
Esempio n. 3
0
static bool AudioOpen()
{
	MSU1.MSU1_STATUS |= AudioError;

	AudioClose();

	char ext[_MAX_EXT];
	snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK);

    audioStream = S9xMSU1OpenFile(ext);
	if (audioStream)
	{
		if (GETC_STREAM(audioStream) != 'M')
			return false;
		if (GETC_STREAM(audioStream) != 'S')
			return false;
		if (GETC_STREAM(audioStream) != 'U')
			return false;
		if (GETC_STREAM(audioStream) != '1')
			return false;

        READ_STREAM((char *)&audioLoopPos, 4, audioStream);
		audioLoopPos = GET_LE32(&audioLoopPos);
		audioLoopPos <<= 2;
		audioLoopPos += 8;

        MSU1.MSU1_AUDIO_POS = 8;

		MSU1.MSU1_STATUS &= ~AudioError;
		return true;
	}

	return false;
}
Esempio n. 4
0
void S9xMSU1PostLoadState(void)
{
	if (DataOpen())
	{
        REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
	}

	if (MSU1.MSU1_STATUS & AudioPlaying)
	{
		uint32 savedPosition = MSU1.MSU1_AUDIO_POS;

		if (AudioOpen())
		{
            REVERT_STREAM(audioStream, 4, 0);
            READ_STREAM((char *)&audioLoopPos, 4, audioStream);
			audioLoopPos = GET_LE32(&audioLoopPos);
			audioLoopPos <<= 2;
			audioLoopPos += 8;

			MSU1.MSU1_AUDIO_POS = savedPosition;
            REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
		}
		else
		{
			MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
			MSU1.MSU1_STATUS |= AudioError;
		}
	}

	if (msu_resampler)
		msu_resampler->clear();

	partial_frames = 0;
}
Esempio n. 5
0
void S9xMSU1Generate(size_t sample_count)
{
	partial_frames += 4410 * (sample_count / 2);

	while ((bufPos < (bufEnd - 2)) && partial_frames >= 3204)
	{
		if (MSU1.MSU1_STATUS & AudioPlaying && audioStream)
		{
			int32 sample;
			int16* left = (int16*)&sample;
			int16* right = left + 1;

			int bytes_read = READ_STREAM((char *)&sample, 4, audioStream);
			if (bytes_read == 4)
			{
				*left = ((int32)(int16)GET_LE16(left) * MSU1.MSU1_VOLUME / 255);
				*right = ((int32)(int16)GET_LE16(right) * MSU1.MSU1_VOLUME / 255);


				*(bufPos++) = *left;
				*(bufPos++) = *right;
				MSU1.MSU1_AUDIO_POS += 4;
				partial_frames -= 3204;
			}
			else
			if (bytes_read >= 0)
			{
				if (MSU1.MSU1_STATUS & AudioRepeating)
				{
					MSU1.MSU1_AUDIO_POS = audioLoopPos;
					REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
				}
				else
				{
					MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
					REVERT_STREAM(audioStream, 8, 0);
				}
			}
			else
			{
				MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
			}
		}
		else
		{
			MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
			partial_frames -= 3204;
			*(bufPos++) = 0;
			*(bufPos++) = 0;
		}
	}
}
Esempio n. 6
0
int S9xMovieOpen (const char* filename, bool8 read_only)
{
	FILE* fd;
	STREAM stream;
	int result;
	int fn;

	char movie_filename [_MAX_PATH];
#ifdef __WIN32__
	_fullpath(movie_filename, filename, _MAX_PATH);
#else
	strcpy(movie_filename, filename);
#endif

	if(!(fd=fopen(movie_filename, "rb+")))
		if(!(fd=fopen(movie_filename, "rb")))
			return FILE_NOT_FOUND;
		else
			read_only = TRUE;

	const bool8 wasPaused = Settings.Paused;

	// stop current movie before opening
	change_state(MOVIE_STATE_NONE);

	// read header
	if((result=read_movie_header(fd, &Movie))!=SUCCESS)
	{
		fclose(fd);
		return result;
	}

	read_movie_extrarominfo(fd, &Movie);

	fn=dup(fileno(fd));
	fclose(fd);

	// apparently this lseek is necessary
	lseek(fn, Movie.SaveStateOffset, SEEK_SET);
	if(!(stream=REOPEN_STREAM(fn, "rb")))
		return FILE_NOT_FOUND;

	// store previous, before changing to the movie's settings
	store_previous_settings();

	// set from movie
	restore_movie_settings();

	if(Movie.Opts & MOVIE_OPT_FROM_RESET)
	{
		Movie.State = MOVIE_STATE_PLAY; // prevent NSRT controller switching (in S9xPostRomInit)
		if(!Memory.LoadLastROM())
			S9xReset();
		Memory.ClearSRAM(false); // in case the SRAM read fails
		Movie.State = MOVIE_STATE_NONE;
		S9xMovieResetControls();
		// save only SRAM for a from-reset snapshot
		result=(READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT;
	}
	else
	{
		result=S9xUnfreezeFromStream(stream);
	}
	CLOSE_STREAM(stream);

	if(result!=SUCCESS)
	{
		return result;
	}

	if(!(fd=fopen(movie_filename, "rb+")))
		if(!(fd=fopen(movie_filename, "rb")))
			return FILE_NOT_FOUND;
		else
			read_only = TRUE;

	if(fseek(fd, Movie.ControllerDataOffset, SEEK_SET))
		return WRONG_FORMAT;

	// read controller data
	Movie.File=fd;
	Movie.BytesPerSample=bytes_per_sample();
	Movie.InputBufferPtr=Movie.InputBuffer;
	uint32 to_read=Movie.BytesPerSample * (Movie.MaxSample+1);
	reserve_buffer_space(to_read);
	fread(Movie.InputBufferPtr, 1, to_read, fd);

	// read "baseline" controller data
	if(Movie.MaxSample && Movie.MaxFrame)
		read_frame_controller_data(true);

	strncpy(Movie.Filename, movie_filename, _MAX_PATH);
	Movie.Filename[_MAX_PATH-1]='\0';
	Movie.CurrentFrame=0;
	Movie.CurrentSample=0;
	Movie.ReadOnly=read_only;
	change_state(MOVIE_STATE_PLAY);

	Settings.Paused = wasPaused;

	Movie.RecordedThisSession = false;
	S9xUpdateFrameCounter(-1);

	S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY);
	return SUCCESS;
}
Esempio n. 7
0
bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader) {
	size_t soundResourceLength;
	bool result = false;
	GameSoundType resourceType = kSoundPCM;
	int rate = 0, size = 0;
	Common::File *file;

	if (resourceId == (uint32)-1) {
		return false;
	}

#ifdef ENABLE_IHNM
	//TODO: move to resource_res so we can use normal "getResourceData" and "getFile" methods
	if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
		char soundFileName[40];
		int dirIndex = resourceId / 64;

		if ((context->fileType() & GAME_VOICEFILE) != 0) {
			if (_voiceSerial == 0) {
				sprintf(soundFileName, "Voices/VoicesS/Voices%d/VoicesS%03x", dirIndex, resourceId);
			} else {
				sprintf(soundFileName, "Voices/Voices%d/Voices%d/Voices%d%03x", _voiceSerial, dirIndex, _voiceSerial, resourceId);
			}
		} else {
			sprintf(soundFileName, "SFX/SFX%d/SFX%03x", dirIndex, resourceId);
		}

		file = new Common::File();

		file->open(soundFileName);
		soundResourceLength = file->size();
	} else
#endif
	{
		ResourceData* resourceData = context->getResourceData(resourceId);
		file = context->getFile(resourceData);

		file->seek(resourceData->offset);
		soundResourceLength = resourceData->size;
	}

	Common::SeekableReadStream &readS = *file;
	bool uncompressedSound = false;

	if (soundResourceLength >= 8) {
		byte header[8];

		readS.read(&header, 8);
		readS.seek(readS.pos() - 8);

		if (!memcmp(header, "Creative", 8)) {
			resourceType = kSoundVOC;
		} else if (!memcmp(header, "RIFF", 4) != 0) {
			resourceType = kSoundWAV;
		} else if (!memcmp(header, "FORM", 4) != 0) {
			resourceType = kSoundAIFF;
		} else if (!memcmp(header, "ajkg", 4) != 0) {
			resourceType = kSoundShorten;
		}

		// If patch data exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed
		// Patch data for this resource is in file p2_a.iaf or p2_a.voc
		if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->getResourceData(resourceId)->patchData != NULL)
			uncompressedSound = true;

		// FIXME: Currently, the SFX.RES file in IHNM cannot be compressed
		if (_vm->getGameId() == GID_IHNM && (context->fileType() & GAME_SOUNDFILE))
			uncompressedSound = true;

		if (context->isCompressed() && !uncompressedSound) {
			if (header[0] == char(0)) {
				resourceType = kSoundMP3;
			} else if (header[0] == char(1)) {
				resourceType = kSoundOGG;
			} else if (header[0] == char(2)) {
				resourceType = kSoundFLAC;
			}
		}

	}

	// Default sound type is 16-bit signed PCM, used in ITE
	byte rawFlags = Audio::FLAG_16BITS;

	if (_vm->getGameId() == GID_ITE) {
		if (context->fileType() & GAME_MACBINARY) {
			// ITE Mac has sound in the Mac snd format
			resourceType = kSoundMacSND;
		} else if (_vm->getFeatures() & GF_8BIT_UNSIGNED_PCM) {	// older ITE demos
			rawFlags |= Audio::FLAG_UNSIGNED;
			rawFlags &= ~Audio::FLAG_16BITS;
		} else if (!uncompressedSound && !scumm_stricmp(context->fileName(), "voicesd.rsc")) {
			// Voice files in newer ITE demo versions are OKI ADPCM (VOX) encoded.
			resourceType = kSoundVOX;
		}
	}

	buffer.stream = 0;

	// Check for LE sounds
	if (!context->isBigEndian())
		rawFlags |= Audio::FLAG_LITTLE_ENDIAN;

	switch (resourceType) {
	case kSoundPCM: {
		// In ITE CD German, some voices are absent and contain just 5 zero bytes.
		// Round down to an even number when the audio is 16-bit so makeRawStream
		// will accept the data (needs to be an even size for 16-bit data).
		// See bug #1256701

		if ((soundResourceLength & 1) && (rawFlags & Audio::FLAG_16BITS))
			soundResourceLength &= ~1;

		Audio::SeekableAudioStream *audStream = Audio::makeRawStream(READ_STREAM(soundResourceLength), 22050, rawFlags);
		buffer.stream = audStream;
		buffer.streamLength = audStream->getLength();
		result = true;
		} break;
	case kSoundVOX:
		buffer.stream = Audio::makeADPCMStream(READ_STREAM(soundResourceLength), DisposeAfterUse::YES, soundResourceLength, Audio::kADPCMOki, 22050, 1);
		buffer.streamLength = Audio::Timestamp(0, soundResourceLength * 2, buffer.stream->getRate());
		result = true;
		break;
	case kSoundMacSND: {
		Audio::SeekableAudioStream *audStream = Audio::makeMacSndStream(READ_STREAM(soundResourceLength), DisposeAfterUse::YES);
		buffer.stream = audStream;
		buffer.streamLength = audStream->getLength();
		result = true;
		} break;
	case kSoundAIFF: {
		Audio::SeekableAudioStream *audStream = Audio::makeAIFFStream(READ_STREAM(soundResourceLength), DisposeAfterUse::YES);
		buffer.stream = audStream;
		buffer.streamLength = audStream->getLength();
		result = true;
		} break;
	case kSoundVOC: {
		Audio::SeekableAudioStream *audStream = Audio::makeVOCStream(READ_STREAM(soundResourceLength), Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
		buffer.stream = audStream;
		buffer.streamLength = audStream->getLength();
		result = true;
		} break;
	case kSoundWAV:
	case kSoundShorten:
		if (resourceType == kSoundWAV) {
			result = Audio::loadWAVFromStream(readS, size, rate, rawFlags);
#ifdef ENABLE_SAGA2
		} else if (resourceType == kSoundShorten) {
			result = loadShortenFromStream(readS, size, rate, rawFlags);
#endif
		}

		if (result) {
			Audio::SeekableAudioStream *audStream = Audio::makeRawStream(READ_STREAM(size), rate, rawFlags);
			buffer.stream = audStream;
			buffer.streamLength = audStream->getLength();
		}
		break;
	case kSoundMP3:
	case kSoundOGG:
	case kSoundFLAC: {
		readS.skip(9); // skip sfx header

		Audio::SeekableAudioStream *audStream = 0;
		Common::SeekableReadStream *memStream = READ_STREAM(soundResourceLength - 9);

		if (resourceType == kSoundMP3) {
#ifdef USE_MAD
			audStream = Audio::makeMP3Stream(memStream, DisposeAfterUse::YES);
#endif
		} else if (resourceType == kSoundOGG) {
#ifdef USE_VORBIS
			audStream = Audio::makeVorbisStream(memStream, DisposeAfterUse::YES);
#endif
		} else /* if (resourceType == kSoundFLAC) */ {
#ifdef USE_FLAC
			audStream = Audio::makeFLACStream(memStream, DisposeAfterUse::YES);
#endif
		}

		if (audStream) {
			buffer.stream = audStream;
			buffer.streamLength = audStream->getLength();
			result = true;
		} else {
			delete memStream;
		}

		} break;
	default:
		error("SndRes::load Unknown sound type");
	}

	if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
		delete file;
	}

	if (onlyHeader) {
		delete buffer.stream;
		buffer.stream = 0;
	}

	return result;
}
Esempio n. 8
0
int S9xMovieOpen (const char* filename, bool8 read_only)
{
	FILE* fd;
	STREAM stream;
	int result;
	int fn;

	if(!(fd=fopen(filename, read_only ? "rb" : "rb+")))
		return FILE_NOT_FOUND;

	// stop current movie before opening
	change_state(MOVIE_STATE_NONE);

	// read header
	if((result=read_movie_header(fd, &Movie))!=SUCCESS)
	{
		fclose(fd);
		return result;
	}

	fn=dup(fileno(fd));
	fclose(fd);

	// apparently this lseek is necessary
	lseek(fn, Movie.SaveStateOffset, SEEK_SET);
	if(!(stream=REOPEN_STREAM(fn, "rb")))
		return FILE_NOT_FOUND;

	if(Movie.Opts & MOVIE_OPT_FROM_RESET)
	{
		S9xReset();
		// save only SRAM for a from-reset snapshot
		result=(READ_STREAM(SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT;
	}
	else
	{
		result=S9xUnfreezeFromStream(stream);
	}
	CLOSE_STREAM(stream);

	if(result!=SUCCESS)
	{
		return result;
	}

	if(!(fd=fopen(filename, read_only ? "rb" : "rb+")))
		return FILE_NOT_FOUND;

	if(fseek(fd, Movie.ControllerDataOffset, SEEK_SET))
		return WRONG_FORMAT;

	// read controller data
	Movie.File=fd;
	Movie.BytesPerFrame=bytes_per_frame();
	Movie.InputBufferPtr=Movie.InputBuffer;
	uint32 to_read=Movie.BytesPerFrame * (Movie.MaxFrame+1);
	reserve_buffer_space(to_read);
	fread(Movie.InputBufferPtr, 1, to_read, fd);

	// read "baseline" controller data
	read_frame_controller_data();

	strncpy(Movie.Filename, filename, _MAX_PATH);
	Movie.Filename[_MAX_PATH-1]='\0';
	Movie.CurrentFrame=0;
	Movie.ReadOnly=read_only;
	change_state(MOVIE_STATE_PLAY);

	S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY);
	return SUCCESS;
}
Esempio n. 9
0
size_t fReader::read(char *buf, size_t len){
    return READ_STREAM(buf, len, fp);
}
static int ReadOrigSnapshot (STREAM snap)
{
    char buffer [_MAX_PATH];
    char rom_filename [_MAX_PATH];
    int result;
    int i;
    int j;

    int version;
    int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1;
    if (READ_STREAM (buffer, len, snap) != len)
	return (WRONG_FORMAT);
    if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0)
	return (WRONG_FORMAT);
    if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION)
	return (WRONG_VERSION);

    if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS)
	return (result);

    if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS)
	return (result);

    if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 &&
	strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0)
    {
	S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME,
		    "Current loaded ROM image doesn't match that required by freeze-game file.");
    }

    S9xReset ();
    S9xSetSoundMute (TRUE);
    if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS)
	return (result);
    OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old;
    Memory.FixROMSpeed ();
    if (version == 3)
    {
	OrigCPU.Cycles = OrigCPU.Cycles_old;
	OrigCPU.NextEvent = OrigCPU.NextEvent_old;
	OrigCPU.V_Counter = OrigCPU.V_Counter_old;
	OrigCPU.MemSpeed = OrigCPU.MemSpeed_old;
	OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old;
	OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old;
    }
    CPU.Flags = OrigCPU.Flags;
    CPU.BranchSkip = OrigCPU.BranchSkip;
    CPU.NMIActive = OrigCPU.NMIActive;
    CPU.IRQActive = OrigCPU.IRQActive;
    CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt;
    CPU.WhichEvent = OrigCPU.WhichEvent;
    CPU.Cycles = OrigCPU.Cycles;
    CPU.NextEvent = OrigCPU.NextEvent;
    CPU.V_Counter = OrigCPU.V_Counter;
    CPU.MemSpeed = OrigCPU.MemSpeed;
    CPU.MemSpeedx2 = OrigCPU.MemSpeedx2;
    CPU.FastROMSpeed = OrigCPU.FastROMSpeed;

    if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS)
	return (result);

    Registers = *(struct SRegisters *) &OrigRegisters;

    if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS)
	return (result);

    if (version == 2)
    {
	OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13;
	OrigPPU.OBJNameBase <<= 1;
	OrigPPU.OBJNameSelect <<= 13;
    }
    PPU.BGMode = OrigPPU.BGMode;
    PPU.BG3Priority = OrigPPU.BG3Priority;
    PPU.Brightness = OrigPPU.Brightness;

    PPU.VMA.High = OrigPPU.VMA.High;
    PPU.VMA.Increment = OrigPPU.VMA.Increment;
    PPU.VMA.Address = OrigPPU.VMA.Address;
    PPU.VMA.Mask1 = OrigPPU.VMA.Mask1;
    PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount;
    PPU.VMA.Shift = OrigPPU.VMA.Shift;

    for (i = 0; i < 4; i++)
    {
	PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase;
	PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset;
	PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset;
	PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize;
	PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase;
	PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize;
    }

    PPU.CGFLIP = OrigPPU.CGFLIP;
    for (i = 0; i < 256; i++)
	PPU.CGDATA [i] = OrigPPU.CGDATA [i];
    PPU.FirstSprite = OrigPPU.FirstSprite;
    for (i = 0; i < 128; i++)
    {
	PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos;
	PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos;
	PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name;
	PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip;
	PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip;
	PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority;
	PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette;
	PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size;
    }
    PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation;
    PPU.OAMAddr = OrigPPU.OAMAddr;

    PPU.OAMFlip = OrigPPU.OAMFlip;
    PPU.OAMTileAddress = OrigPPU.OAMTileAddress;
    PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos;
    PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos;
    PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched;
    PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched;

    PPU.HBeamFlip = OrigPPU.HBeamFlip;
    PPU.VBeamFlip = OrigPPU.VBeamFlip;
    PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched;

    PPU.MatrixA = OrigPPU.MatrixA;
    PPU.MatrixB = OrigPPU.MatrixB;
    PPU.MatrixC = OrigPPU.MatrixC;
    PPU.MatrixD = OrigPPU.MatrixD;
    PPU.CentreX = OrigPPU.CentreX;
    PPU.CentreY = OrigPPU.CentreY;
    PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos;
    PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos;
    PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos;

    PPU.CGADD = OrigPPU.CGADD;
    PPU.FixedColourRed = OrigPPU.FixedColourRed;
    PPU.FixedColourGreen = OrigPPU.FixedColourGreen;
    PPU.FixedColourBlue = OrigPPU.FixedColourBlue;
    PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr;
    PPU.ScreenHeight = OrigPPU.ScreenHeight;
    PPU.WRAM = OrigPPU.WRAM;
    PPU.ForcedBlanking = OrigPPU.ForcedBlanking;
    PPU.OBJNameSelect = OrigPPU.OBJNameSelect;
    PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect;
    PPU.OBJNameBase = OrigPPU.OBJNameBase;
    PPU.OAMReadFlip = OrigPPU.OAMReadFlip;
    memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData));
    PPU.VTimerEnabled = OrigPPU.VTimerEnabled;
    PPU.HTimerEnabled = OrigPPU.HTimerEnabled;
    PPU.HTimerPosition = OrigPPU.HTimerPosition;
    PPU.Mosaic = OrigPPU.Mosaic;
    memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic));
    PPU.Mode7HFlip = OrigPPU.Mode7HFlip;
    PPU.Mode7VFlip = OrigPPU.Mode7VFlip;
    PPU.Mode7Repeat = OrigPPU.Mode7Repeat;
    PPU.Window1Left = OrigPPU.Window1Left;
    PPU.Window1Right = OrigPPU.Window1Right;
    PPU.Window2Left = OrigPPU.Window2Left;
    PPU.Window2Right = OrigPPU.Window2Right;
    for (i = 0; i < 6; i++)
    {
	PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i];
	PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i];
	PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i];
	PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i];
	PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i];
    }
    PPU.CGFLIPRead = OrigPPU.CGFLIPRead;
    PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply;

    IPPU.ColorsChanged = TRUE;
    IPPU.OBJChanged = TRUE;
    S9xFixColourBrightness ();
    IPPU.RenderThisFrame = FALSE;

    if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS)
	return (result);

    for (i = 0; i < 8; i++)
    {
	DMA[i].TransferDirection = OrigDMA[i].TransferDirection;
	DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed;
	DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement;
	DMA[i].TransferMode = OrigDMA[i].TransferMode;
	DMA[i].ABank = OrigDMA[i].ABank;
	DMA[i].AAddress = OrigDMA[i].AAddress;
	DMA[i].Address = OrigDMA[i].Address;
	DMA[i].BAddress = OrigDMA[i].BAddress;
	DMA[i].TransferBytes = OrigDMA[i].TransferBytes;
	DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing;
	DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress;
	DMA[i].IndirectBank = OrigDMA[i].IndirectBank;
	DMA[i].Repeat = OrigDMA[i].Repeat;
	DMA[i].LineCount = OrigDMA[i].LineCount;
	DMA[i].FirstLine = OrigDMA[i].FirstLine;
    }

    if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS)
	return (result);
    if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS)
	return (result);
    if ((result = ReadBlock ("SRA:", Memory.SRAM, 0x10000, snap)) != SUCCESS)
	return (result);
    if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS)
	return (result);
    if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS)
    {
	APU = *(struct SAPU *) &OrigAPU;

	if ((result = ReadBlock ("ARE:", &OrigAPURegisters,
				 sizeof (OrigAPURegisters), snap)) != SUCCESS)
	    return (result);
	APURegisters = *(struct SAPURegisters *) &OrigAPURegisters;
	if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS)
	    return (result);
	if ((result = ReadBlock ("SOU:", &OrigSoundData,
				 sizeof (SOrigSoundData), snap)) != SUCCESS)
	    return (result);

	SoundData.master_volume_left = OrigSoundData.master_volume_left;
	SoundData.master_volume_right = OrigSoundData.master_volume_right;
	SoundData.echo_volume_left = OrigSoundData.echo_volume_left;
	SoundData.echo_volume_right = OrigSoundData.echo_volume_right; 
	SoundData.echo_enable = OrigSoundData.echo_enable;
	SoundData.echo_feedback = OrigSoundData.echo_feedback;
	SoundData.echo_ptr = OrigSoundData.echo_ptr;
	SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size;
	SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled;
	SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable;
	SoundData.pitch_mod = OrigSoundData.pitch_mod;

	for (i = 0; i < 3; i++)
	    SoundData.dummy [i] = OrigSoundData.dummy [i];
	for (i = 0; i < NUM_CHANNELS; i++)
	{
	    SoundData.channels [i].state = OrigSoundData.channels [i].state;
	    SoundData.channels [i].type = OrigSoundData.channels [i].type;
	    SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left;
	    SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right;
	    SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency;
	    SoundData.channels [i].count = OrigSoundData.channels [i].count;
	    SoundData.channels [i].loop = OrigSoundData.channels [i].loop;
	    SoundData.channels [i].envx = OrigSoundData.channels [i].envx;
	    SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level;
	    SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level;
	    SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target;
	    SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error;
	    SoundData.channels [i].erate = OrigSoundData.channels [i].erate;
	    SoundData.channels [i].direction = OrigSoundData.channels [i].direction;
	    SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate;
	    SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate;
	    SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate;
	    SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate;
	    SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level;
	    SoundData.channels [i].sample = OrigSoundData.channels [i].sample;
	    for (j = 0; j < 16; j++)
		SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j];

	    for (j = 0; j < 2; j++)
		SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j];

	    SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number;
	    SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block;
	    SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode;
	    SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer;
	    SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer;
	    SoundData.channels [i].mode = OrigSoundData.channels [i].mode;
	}

	S9xSetSoundMute (FALSE);
	IAPU.PC = IAPU.RAM + APURegisters.PC;
	S9xAPUUnpackStatus ();
	if (APUCheckDirectPage ())
	    IAPU.DirectPage = IAPU.RAM + 0x100;
	else
	    IAPU.DirectPage = IAPU.RAM;
	Settings.APUEnabled = TRUE;
	IAPU.APUExecuting = TRUE;
    }
    else
    {
	Settings.APUEnabled = FALSE;
	IAPU.APUExecuting = FALSE;
	S9xSetSoundMute (TRUE);
    }
    S9xFixSoundAfterSnapshotLoad (1);
    ICPU.ShiftedPB = Registers.PB << 16;
    ICPU.ShiftedDB = Registers.DB << 16;
    S9xSetPCBase (ICPU.ShiftedPB + Registers.PC);
    S9xUnpackStatus ();
    S9xFixCycles ();
    S9xReschedule ();

    return (SUCCESS);
}
Esempio n. 11
0
int S9xMovieOpen (const char* filename, bool8 read_only, uint8 sync_flags, uint8 sync_flags2)
{
	FILE* fd;
	STREAM stream;
	int result;
	int fn;

	char movie_filename [_MAX_PATH];
#ifdef WIN32
	_fullpath(movie_filename, filename, _MAX_PATH);
#else
	strcpy(movie_filename, filename);
#endif

	if(!(fd=fopen(movie_filename, "rb+")))
		if(!(fd=fopen(movie_filename, "rb")))
			return FILE_NOT_FOUND;
		else
			read_only = TRUE;

	const bool8 wasPaused = Settings.Paused;
	const uint32 prevFrameTime = Settings.FrameTime;

	// stop current movie before opening
	change_state(MOVIE_STATE_NONE);

	// read header
	if((result=read_movie_header(fd, &Movie))!=SUCCESS)
	{
		fclose(fd);
		return result;
	}

	read_movie_extrarominfo(fd, &Movie);

	fn=dup(fileno(fd));
	fclose(fd);

	// apparently this lseek is necessary
	lseek(fn, Movie.SaveStateOffset, SEEK_SET);
	if(!(stream=REOPEN_STREAM(fn, "rb")))
		return FILE_NOT_FOUND;

	// store previous, before changing to the movie's settings
	store_previous_settings();

	// store default
	if (sync_flags & MOVIE_SYNC_DATA_EXISTS)
	{
		Settings.UseWIPAPUTiming = (sync_flags & MOVIE_SYNC_WIP1TIMING) ? TRUE : FALSE;
		Settings.SoundEnvelopeHeightReading = (sync_flags & MOVIE_SYNC_VOLUMEENVX) ? TRUE : FALSE;
		Settings.FakeMuteFix = (sync_flags & MOVIE_SYNC_FAKEMUTE) ? TRUE : FALSE;
		Settings.UpAndDown = (sync_flags & MOVIE_SYNC_LEFTRIGHT) ? TRUE : FALSE; // doesn't actually affect synchronization
		Settings.SoundSync = (sync_flags & MOVIE_SYNC_SYNCSOUND) ? TRUE : FALSE; // doesn't seem to affect synchronization
		Settings.InitFastROMSetting = (sync_flags2 & MOVIE_SYNC2_INIT_FASTROM) ? TRUE : FALSE;
		//Settings.ShutdownMaster = (sync_flags & MOVIE_SYNC_NOCPUSHUTDOWN) ? FALSE : TRUE;
	}

	// set from movie
	restore_movie_settings();

	if(Movie.Opts & MOVIE_OPT_FROM_RESET)
	{
		Movie.State = MOVIE_STATE_PLAY; // prevent NSRT controller switching (in S9xPostRomInit)
		if(!Memory.LoadLastROM())
			S9xReset();
		Memory.ClearSRAM(false); // in case the SRAM read fails
		Movie.State = MOVIE_STATE_NONE;

		// save only SRAM for a from-reset snapshot
		result=(READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT;
	}
	else
	{
		result=S9xUnfreezeFromStream(stream);
	}
	CLOSE_STREAM(stream);

	if(result!=SUCCESS)
	{
		return result;
	}

	if(!(fd=fopen(movie_filename, "rb+")))
		if(!(fd=fopen(movie_filename, "rb")))
			return FILE_NOT_FOUND;
		else
			read_only = TRUE;

	if(fseek(fd, Movie.ControllerDataOffset, SEEK_SET))
		return WRONG_FORMAT;

	// read controller data
	Movie.File=fd;
	Movie.BytesPerFrame=bytes_per_frame();
	Movie.InputBufferPtr=Movie.InputBuffer;
	uint32 to_read=Movie.BytesPerFrame * (Movie.MaxFrame+1);
	reserve_buffer_space(to_read);
	fread(Movie.InputBufferPtr, 1, to_read, fd);

	// read "baseline" controller data
	if(Movie.MaxFrame)
		read_frame_controller_data();

	strncpy(Movie.Filename, movie_filename, _MAX_PATH);
	Movie.Filename[_MAX_PATH-1]='\0';
	Movie.CurrentFrame=0;
	Movie.ReadOnly=read_only;
	change_state(MOVIE_STATE_PLAY);

	Settings.Paused = wasPaused;
	Settings.FrameTime = prevFrameTime; // restore emulation speed

	Movie.RecordedThisSession = false;
	S9xUpdateFrameCounter(-1);

	Movie.RequiresReset = false;

	S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY);
	return SUCCESS;
}