long csavecompressed(char *finam, __block tobesaved, color pala[256], long exto) { Stream *outpt; if (exto > 0) { outpt = ci_fopen(finam, Common::kFile_Create, Common::kFile_ReadWrite); outpt->Seek(Common::kSeekBegin, exto); } else outpt = ci_fopen(finam, Common::kFile_CreateAlways, Common::kFile_Write); int widt, hit; long ofes; widt = *tobesaved++; widt += (*tobesaved++) * 256; hit = *tobesaved++; hit += (*tobesaved++) * 256; // Those were originally written as shorts, although they are ints outpt->WriteInt16(widt); outpt->WriteInt16(hit); unsigned char *ress = (unsigned char *)malloc(widt + 1); int ww; for (ww = 0; ww < hit; ww++) { for (int ss = 0; ss < widt; ss++) (*ress++) = (*tobesaved++); ress -= widt; cpackbitl(ress, widt, outpt); } for (ww = 0; ww < 256; ww++) { outpt->WriteInt8(pala[ww].r); outpt->WriteInt8(pala[ww].g); outpt->WriteInt8(pala[ww].b); } ofes = outpt->GetPosition(); delete outpt; free(ress); return ofes; }
void start_playback() { Stream *in = Common::File::OpenFileRead(replayfile); if (in != NULL) { char buffer [100]; in->Read(buffer, 12); buffer[12] = 0; if (strcmp (buffer, "AGSRecording") != 0) { Display("ERROR: Invalid recorded data file"); play.playback = 0; } else { String version_string = String::FromStream(in, 12); AGS::Engine::Version requested_engine_version(version_string); if (requested_engine_version.Major != '2') quit("!Replay file is from an old version of AGS"); if (requested_engine_version < AGS::Engine::Version(2, 55, 553)) quit("!Replay file was recorded with an older incompatible version"); if (requested_engine_version != EngineVersion) { // Disable text as speech while displaying the warning message // This happens if the user's graphics card does BGR order 16-bit colour int oldalways = game.options[OPT_ALWAYSSPCH]; game.options[OPT_ALWAYSSPCH] = 0; play.playback = 0; Display("Warning! replay is from a different version of AGS (%s) - it may not work properly.", buffer); play.playback = 1; srand (play.randseed); play.gamestep = 0; game.options[OPT_ALWAYSSPCH] = oldalways; } int replayver = in->ReadInt32(); if ((replayver < 1) || (replayver > 3)) quit("!Unsupported Replay file version"); if (replayver >= 2) { fgetstring_limit (buffer, in, 99); int uid = in->ReadInt32 (); if ((strcmp (buffer, game.gamename) != 0) || (uid != game.uniqueid)) { char msg[150]; sprintf (msg, "!This replay is meant for the game '%s' and will not work correctly with this game.", buffer); delete in; quit (msg); } // skip the total time in->ReadInt32 (); // replay description, maybe we'll use this later fgetstring_limit (buffer, in, 99); } play.randseed = in->ReadInt32(); int flen = in->GetLength() - in->GetPosition (); if (replayver >= 3) { flen = in->ReadInt32() * sizeof(short); } recordbuffer = (short*)malloc (flen); in->Read(recordbuffer, flen); srand (play.randseed); recbuffersize = flen / sizeof(short); recsize = 0; disable_mgetgraphpos = 1; replay_time = 0; replay_last_second = loopcounter; if (replayver >= 3) { int issave = in->ReadInt32(); if (issave) { if (RestoreGameState(in, kSvgVersion_321) != kSvgErr_NoError) quit("!Error running replay... could be incorrect game version"); replay_last_second = loopcounter; } } delete in; } } else // file not found play.playback = 0; }
int SpriteCache::saveToFile(const char *filnam, int lastElement, bool compressOutput) { Stream *output = Common::File::CreateFile(filnam); if (output == NULL) return -1; if (compressOutput) { // re-open the file so that it can be seeked delete output; output = File::OpenFile(filnam, Common::kFile_Open, Common::kFile_ReadWrite); // CHECKME why mode was "r+" here? if (output == NULL) return -1; } int spriteFileIDCheck = (int)time(NULL); // version 6 output->WriteInt16(6); output->WriteArray(spriteFileSig, strlen(spriteFileSig), 1); output->WriteInt8(compressOutput ? 1 : 0); output->WriteInt32(spriteFileIDCheck); int i, lastslot = 0; if (elements < lastElement) lastElement = elements; for (i = 1; i < lastElement; i++) { // slot empty if ((images[i] != NULL) || ((offsets[i] != 0) && (offsets[i] != sprite0InitialOffset))) lastslot = i; } output->WriteInt16(lastslot); // allocate buffers to store the indexing info int numsprits = lastslot + 1; short *spritewidths = (short*)malloc(numsprits * sizeof(short)); short *spriteheights = (short*)malloc(numsprits * sizeof(short)); int32_t *spriteoffs = (int32_t*)malloc(numsprits * sizeof(int32_t)); const int memBufferSize = 100000; char *memBuffer = (char*)malloc(memBufferSize); for (i = 0; i <= lastslot; i++) { spriteoffs[i] = output->GetPosition(); // if compressing uncompressed sprites, load the sprite into memory if ((images[i] == NULL) && (this->spritesAreCompressed != compressOutput)) (*this)[i]; if (images[i] != NULL) { // image in memory -- write it out pre_save_sprite(i); int bpss = images[i]->GetColorDepth() / 8; spritewidths[i] = images[i]->GetWidth(); spriteheights[i] = images[i]->GetHeight(); output->WriteInt16(bpss); output->WriteInt16(spritewidths[i]); output->WriteInt16(spriteheights[i]); if (compressOutput) { size_t lenloc = output->GetPosition(); // write some space for the length data output->WriteInt32(0); compressSprite(images[i], output); size_t fileSizeSoFar = output->GetPosition(); // write the length of the compressed data output->Seek(Common::kSeekBegin, lenloc); output->WriteInt32((fileSizeSoFar - lenloc) - 4); output->Seek(Common::kSeekEnd, 0); } else output->WriteArray(images[i]->GetDataForWriting(), spritewidths[i] * bpss, spriteheights[i]); continue; } if ((offsets[i] == 0) || ((offsets[i] == sprite0InitialOffset) && (i > 0))) { // sprite doesn't exist output->WriteInt16(0); spritewidths[i] = 0; spriteheights[i] = 0; spriteoffs[i] = 0; continue; } // not in memory -- seek to it in the source file seekToSprite(i); lastLoad = i; short colDepth = cache_stream->ReadInt16(); output->WriteInt16(colDepth); if (colDepth == 0) { continue; } if (this->spritesAreCompressed != compressOutput) { // shouldn't be able to get here free(memBuffer); delete output; return -2; } // and copy the data across int width = cache_stream->ReadInt16(); int height = cache_stream->ReadInt16(); spritewidths[i] = width; spriteheights[i] = height; output->WriteInt16(width); output->WriteInt16(height); int sizeToCopy; if (this->spritesAreCompressed) { sizeToCopy = cache_stream->ReadInt32(); output->WriteInt32(sizeToCopy); } else { sizeToCopy = width * height * (int)colDepth; } while (sizeToCopy > memBufferSize) { cache_stream->ReadArray(memBuffer, memBufferSize, 1); output->WriteArray(memBuffer, memBufferSize, 1); sizeToCopy -= memBufferSize; } cache_stream->ReadArray(memBuffer, sizeToCopy, 1); output->WriteArray(memBuffer, sizeToCopy, 1); } free(memBuffer); delete output; // write the sprite index file Stream *spindex_out = File::CreateFile(spindexfilename); // write "SPRINDEX" id spindex_out->WriteArray(&spindexid[0], strlen(spindexid), 1); // write version (1) spindex_out->WriteInt32(2); spindex_out->WriteInt32(spriteFileIDCheck); // write last sprite number and num sprites, to verify that // it matches the spr file spindex_out->WriteInt32(lastslot); spindex_out->WriteInt32(numsprits); spindex_out->WriteArrayOfInt16(&spritewidths[0], numsprits); spindex_out->WriteArrayOfInt16(&spriteheights[0], numsprits); spindex_out->WriteArrayOfInt32(&spriteoffs[0], numsprits); delete spindex_out; free(spritewidths); free(spriteheights); free(spriteoffs); return 0; }