mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-13 12:10:30 +00:00

This lets us remove the dependency on malloc.h. The replacement logic is not 100% perfect, as the original logic will resize arrays to load additional t3dBODY-structs, and those would then be free-d alongside their parent. This logic is currently missing, so we will use some more memory. However, we won't leak, as all loads are tracked by the RoomManager, and will be freed when closing/restarting the game.
581 lines
20 KiB
C++
581 lines
20 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
||
*
|
||
* ScummVM is the legal property of its developers, whose names
|
||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||
* file distributed with this source distribution.
|
||
*
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
*/
|
||
|
||
#define FORBIDDEN_SYMBOL_EXCEPTION_sprintf
|
||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||
|
||
#include "watchmaker/saveload.h"
|
||
#include "watchmaker/3d/geometry.h"
|
||
#include "watchmaker/3d/t3d_mesh.h"
|
||
#include "watchmaker/classes/do_inv.h"
|
||
#include "watchmaker/classes/do_player.h"
|
||
#include "watchmaker/classes/do_sound.h"
|
||
#include "watchmaker/classes/do_system.h"
|
||
#include "watchmaker/define.h"
|
||
#include "watchmaker/globvar.h"
|
||
#include "watchmaker/ll/ll_anim.h"
|
||
#include "watchmaker/ll/ll_diary.h"
|
||
#include "watchmaker/ll/ll_string.h"
|
||
#include "watchmaker/ll/ll_util.h"
|
||
#include "watchmaker/schedule.h"
|
||
#include "watchmaker/walk/act.h"
|
||
#include "watchmaker/ll/ll_system.h"
|
||
#include "watchmaker/windows_hacks.h"
|
||
|
||
#define WM_SAVEFILE_VERSION 0x17 // Don't know what changed though.
|
||
|
||
namespace Watchmaker {
|
||
|
||
char *TextPtr;
|
||
|
||
/* -----------------03/08/00 17.45-------------------
|
||
* ReplaceSaveLoadTexture
|
||
* --------------------------------------------------*/
|
||
void ReplaceSaveLoadTexture(int32 ci) {
|
||
/* char str[255];
|
||
gTexture *t;
|
||
t3dMESH *m;
|
||
|
||
if( ( ci <= i00SAVEPOS01 ) || ( !InvObj[ci].meshlink[0] ) || ( ( m=LinkMeshToStr( InvObj[ci].meshlink ) ) == nullptr ) )
|
||
return;
|
||
if( ( !m->FList ) || ( !m->FList->mat ) || ( !m->FList->mat->Texture ) )
|
||
return ;
|
||
|
||
rReleaseBitmapDirect( m->FList->mat->Texture );
|
||
|
||
sprintf( str, "WmSav%#02d.tga", ci-i00SAVEPOS01+1 );
|
||
t = (gTexture *)rLoadBitmapImage( str, (t3dU8)(rTEXTURESURFACE) );
|
||
m->FList->mat->Texture = t;
|
||
*/
|
||
}
|
||
|
||
/* -----------------23/08/00 11.12-------------------
|
||
* getNextSent
|
||
* --------------------------------------------------*/
|
||
char *getNextSent() {
|
||
while (*TextPtr) {
|
||
*TextPtr = ~(*TextPtr);
|
||
TextPtr++;
|
||
}
|
||
|
||
TextPtr++;
|
||
return ((char *)(TextPtr));
|
||
}
|
||
|
||
void loadTextBucket(Common::SeekableReadStream &stream) {
|
||
extern char *TextBucket;
|
||
|
||
if (!TextBucket) TextBucket = (char *)calloc(1, TEXT_BUCKET_SIZE);
|
||
|
||
stream.read(TextBucket, TEXT_BUCKET_SIZE);
|
||
|
||
TextPtr = TextBucket;
|
||
|
||
for (int a = 0; a < MAX_OBJ_NAMES; a++) {
|
||
ObjName[a] = getNextSent();
|
||
}
|
||
for (int a = 0; a < MAX_SENTENCES; a++) {
|
||
Sentence[a] = getNextSent();
|
||
}
|
||
for (int a = 0; a < MAX_SYS_SENTS; a++) {
|
||
SysSent[a] = getNextSent();
|
||
}
|
||
for (int a = 0; a < MAX_TOOLTIP_SENTS; a++) {
|
||
TooltipSent[a] = getNextSent();
|
||
}
|
||
}
|
||
|
||
void loadAll(WorkDirs &workDirs, Init &init) {
|
||
// TODO: Cwd
|
||
auto stream = openFile(workDirs._gameDir + WM_INIT_PACK_FILENAME);
|
||
assert(stream);
|
||
init.loadFromStream(*stream);
|
||
|
||
loadTextBucket(*stream);
|
||
}
|
||
|
||
/* -----------------28/06/00 10.12-------------------
|
||
* DataSave
|
||
* --------------------------------------------------*/
|
||
// NOTA: se slot==255 forza il save (salva senza controllare le condizioni)
|
||
bool DataSave(const char *SaveName, uint8 slot) {
|
||
char str[T3D_NAMELEN];
|
||
warning("STUBBED: DataSave");
|
||
#if 0
|
||
FILE *fhs;
|
||
int32 i, j;
|
||
uint16 WmVer;
|
||
|
||
if (slot != 255) {
|
||
if (!PlayerCanSave()) return FALSE;
|
||
|
||
if (
|
||
(bPlayerInAnim && (bT2DActive != tOPTIONS))
|
||
|| bUseWith || bDialogActive || bDialogMenuActive || bMovingCamera || bGolfActive || InvStatus
|
||
)
|
||
return FALSE;
|
||
}
|
||
|
||
CharStop_SaveStatus();
|
||
bPauseAllAnims = TRUE;
|
||
for (i = 0; i < T3D_MAX_CHARACTERS; i++)
|
||
if (Character[i])
|
||
CharStop(i);
|
||
|
||
InitMessageSystem();
|
||
ClearUseWith();
|
||
ClearText();
|
||
|
||
if (bSomeOneSpeak) bSkipTalk = TRUE;
|
||
|
||
PlayerPos[CurPlayer + ocDARRELL] = 0;
|
||
PlayerGotoPos[CurPlayer + ocDARRELL] = 0;
|
||
game._messageSystem.removeEvent(EventClass::MC_PLAYER, ME_ALL);
|
||
CharStop(ocCURPLAYER);
|
||
|
||
// nascondo l'altro giocatore, cos<6F> quando riparte il gioco StartDiary() vede che e' nascosto e controlla se deve essere visualizzato
|
||
// (altrimenti quando carico e l'altro player non <20> HIDE, per via di alcune variabili puo' non essere disegnato)
|
||
Character[(CurPlayer ^ 1) + ocDARRELL]->Flags |= T3D_CHARACTER_HIDE;
|
||
|
||
//sprintf( str, "WmSav%#02d.tga", slot );
|
||
//rGrabVideo( str, 1 );
|
||
/* memcpy( BackupInv, &Inv[CurPlayer], sizeof(t3dU8)*MAX_ICONS_IN_INV );
|
||
BackupInvLen = InvLen[CurPlayer];
|
||
BackupInvBase = InvBase[CurPlayer];
|
||
|
||
memset( &Inv[CurPlayer], 0, sizeof(t3dU8)*MAX_ICONS_IN_INV );
|
||
for ( i=0; i<MAX_SAVE_SLOTS; i++ ) Inv[CurPlayer][i] = i00SAVEPOS01+i;
|
||
InvLen[CurPlayer] = MAX_SAVE_SLOTS;
|
||
InvBase[CurPlayer] = 0;
|
||
|
||
InvStatus = INV_ON|INV_MODE2|INV_MODE5;
|
||
*/
|
||
/*
|
||
#ifdef INTERNAL_TEST_VERSION
|
||
{//DEBUG: si backuppa fino a 20 files
|
||
char _str[T3D_NAMELEN];
|
||
int i;
|
||
|
||
for(i=20; i>=1; i--)
|
||
{
|
||
sprintf( str, "WmSav%#02d.%#03d", slot,i-1 );
|
||
sprintf( _str, "WmSav%#02d.%#03d", slot,i );
|
||
|
||
remove(_str);
|
||
rename(str,_str);
|
||
}
|
||
|
||
sprintf( str, "Wm%#02d.sav", slot );
|
||
sprintf( _str, "WmSav%#02d.%#03d", slot,0 );
|
||
remove(_str);
|
||
rename(str,_str);
|
||
|
||
}
|
||
#endif
|
||
*/
|
||
sprintf(str, "%sWm%#02d.sav", WmSavesDir, slot);
|
||
|
||
if ((fhs = fopen(str, "wb")) == nullptr)
|
||
return FALSE;
|
||
|
||
WmVer = (t3dU16)WM_SAVEFILE_VERSION;
|
||
fwrite(&WmVer, sizeof(t3dU16), 1, fhs);
|
||
fwrite(SaveName, sizeof(char), T3D_NAMELEN, fhs);
|
||
fwrite(t3dCurRoom->Name, sizeof(char), T3D_NAMELEN, fhs);
|
||
|
||
for (i = 0; i < MAX_ROOMS; i++) {
|
||
fwrite(&Room[i].flags, sizeof(t3dU16), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_OBJS; i++) {
|
||
fwrite(&Obj[i].name, sizeof(t3dU16), 1, fhs);
|
||
fwrite(Obj[i].examine, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(Obj[i].action, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(Obj[i].anim, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(Obj[i].anim2, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(&Obj[i].goroom, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&Obj[i].ninv, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&Obj[i].flags, sizeof(t3dU16), 1, fhs);
|
||
fwrite(&Obj[i].pos, sizeof(t3dU8), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_ICONS; i++) {
|
||
fwrite(&InvObj[i].name, sizeof(t3dU16), 1, fhs);
|
||
fwrite(InvObj[i].examine, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(InvObj[i].action, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(&InvObj[i].flags, sizeof(t3dU16), 1, fhs);
|
||
fwrite(&InvObj[i].uwobj, sizeof(t3dU16), 1, fhs);
|
||
fwrite(InvObj[i].anim, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
fwrite(InvObj[i].anim2, sizeof(t3dU16), MAX_PLAYERS, fhs);
|
||
}
|
||
for (i = 0; i < MAX_SOUNDS; i++) {
|
||
fwrite(&Sound[i].flags, sizeof(t3dU8), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_DIALOGS; i++) {
|
||
fwrite(&Dialog[i].flags, sizeof(t3dU16), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_DIARIES; i++) {
|
||
fwrite(&Diary[i].startt, sizeof(t3dU16), 1, fhs);
|
||
fwrite(&Diary[i].endt, sizeof(t3dU16), 1, fhs);
|
||
fwrite(&Diary[i].end_hideobj, sizeof(t3dU16), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_DLG_MENUS; i++) {
|
||
fwrite(&DlgMenu[i].on, sizeof(t3dU8), 1, fhs);
|
||
}
|
||
for (i = 0; i < MAX_PDALOGS; i++) {
|
||
fwrite(&PDALog[i].time, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&PDALog[i].flags, sizeof(t3dS32), 1, fhs);
|
||
}
|
||
fwrite(&CurRoom, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&CurInvObj, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&BigInvObj, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&CurPlayer, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&CurSubMusic, sizeof(t3dS32), 1, fhs);
|
||
fwrite(Inv, sizeof(t3dU8), MAX_PLAYERS * MAX_ICONS_IN_INV, fhs);
|
||
fwrite(InvLen, sizeof(t3dU8), MAX_PLAYERS, fhs);
|
||
fwrite(InvBase, sizeof(t3dU8), MAX_PLAYERS, fhs);
|
||
fwrite(PlayerPos, sizeof(t3dU8), T3D_MAX_CHARACTERS, fhs);
|
||
fwrite(&CameraTargetObj, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&CameraTargetBone, sizeof(t3dS32), 1, fhs);
|
||
|
||
fwrite(Comb2D, sizeof(t3dS32), 5, fhs);
|
||
fwrite(Comb2Q, sizeof(t3dS32), 5, fhs);
|
||
fwrite(Comb19, sizeof(t3dS32), 3, fhs);
|
||
fwrite(Comb1D, sizeof(t3dS32), 5, fhs);
|
||
fwrite(&Forno25, sizeof(t3dS32), 1, fhs);
|
||
fwrite(&Frigo25, sizeof(t3dS32), 1, fhs);
|
||
fwrite(Comb31, sizeof(t3dS32), 5, fhs);
|
||
fwrite(Comb33, sizeof(t3dS32), 4, fhs);
|
||
fwrite(Comb42, sizeof(t3dS32), 12, fhs);
|
||
fwrite(Comb44, sizeof(t3dS32), 3, fhs);
|
||
fwrite(Comb45, sizeof(t3dS32), 5, fhs);
|
||
fwrite(&bMoglieGym, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&bMoglieSangue, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&bNoPlayerSwitch, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&bPorteEsternoBloccate, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&bSezioneLabirinto, sizeof(t3dU8), 1, fhs);
|
||
|
||
for (i = 0; i < MAX_MODIFIED_MESH; i++) {
|
||
fwrite(&MMList[i], sizeof(struct SMeshModifier), 1, fhs);
|
||
}
|
||
fwrite(PlayerStand, sizeof(struct SPlayerStand), MAX_PLAYERS, fhs);
|
||
fwrite(&t3dCurTime, sizeof(t3dS32), 1, fhs);
|
||
|
||
for (i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||
if ((i == ocCURPLAYER) || (i == ocLASTCHAR)) continue;
|
||
if (Character[i] && Character[i]->Mesh) {
|
||
fwrite(&Character[i]->Mesh->Trasl, sizeof(t3dV3F), 1, fhs);
|
||
fwrite(&Character[i]->Dir, sizeof(t3dV3F), 1, fhs);
|
||
fwrite(&Character[i]->Flags, sizeof(t3dU8), 1, fhs);
|
||
fwrite(&Character[i]->Walk.LookX, sizeof(t3dF32), 1, fhs);
|
||
fwrite(&Character[i]->Walk.LookZ, sizeof(t3dF32), 1, fhs);
|
||
fwrite(&Character[i]->Walk.CurX, sizeof(t3dF32), 1, fhs);
|
||
fwrite(&Character[i]->Walk.CurZ, sizeof(t3dF32), 1, fhs);
|
||
fwrite(&Character[i]->Walk.CurPanel, sizeof(t3dS16), 1, fhs);
|
||
fwrite(&Character[i]->Walk.OldPanel, sizeof(t3dS16), 1, fhs);
|
||
} else {
|
||
//evito che i save non dipendano dal numero di personaggi presenti in memoria in quel momento
|
||
BYTE x, k, len;
|
||
len = sizeof(t3dV3F) * 2 + sizeof(t3dU8) + sizeof(t3dF32) * 4 + sizeof(t3dS16) * 2;
|
||
for (k = 0, x = 0; k < len; k++) fwrite(&x, 1, 1, fhs);
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < MAX_PLAYERS; i++) {
|
||
for (j = 0; j < T3D_MAX_CHARACTERS; j++) {
|
||
fwrite(&UsedDlgMenu[i][j], sizeof(t3dU8), MAX_DLG_MENUS, fhs);
|
||
}
|
||
}
|
||
|
||
fclose(fhs);
|
||
bPauseAllAnims = FALSE;
|
||
CharStop_LoadStatus();
|
||
#endif
|
||
return (TRUE);
|
||
}
|
||
|
||
/* -----------------28/06/00 14.49-------------------
|
||
* DataLoad
|
||
* --------------------------------------------------*/
|
||
//se SaveName e' "" utilizzo lo slot
|
||
bool DataLoad(WGame &game, const Common::String &FileName, uint8 slot) {
|
||
char str[T3D_NAMELEN] = {};
|
||
uint16 WmVer = 0;
|
||
|
||
if (!FileName.equalsIgnoreCase("WmStart.dat"))
|
||
if (
|
||
(bPlayerInAnim && (bT2DActive != tOPTIONS))
|
||
|| bUseWith || bDialogActive || bDialogMenuActive || bMovingCamera || bGolfActive || InvStatus
|
||
)
|
||
return FALSE;
|
||
|
||
// resetto alcune variabili che potrebbero rimanere sporche dalla partita prima (uguale per StartPlayingGame(), DataLoad() )
|
||
bCacciatore = 0;
|
||
bSaveDisabled = 0;
|
||
bNotSkippableSent = 0;
|
||
bPorteEsternoBloccate = 0;
|
||
bNoPlayerSwitch = 0;
|
||
bDarkScreen = FALSE;
|
||
bSuperView = 0;
|
||
bSezioneLabirinto = 0;
|
||
bSkipTalk = FALSE;
|
||
bSomeOneSpeak = FALSE;
|
||
bPlayerSpeak = FALSE;
|
||
bWideScreen = 0;
|
||
bTitoliCodaStatic = 0;
|
||
bTitoliCodaScrolling = 0;
|
||
strcpy(RoomInfo.name, "");
|
||
|
||
StopDiary(game, 0, 0, 0);
|
||
bPauseAllAnims = TRUE;
|
||
|
||
for (int i = 0; i < T3D_MAX_CHARACTERS; i++)
|
||
if (Character[i])
|
||
CharStop(i);
|
||
|
||
game._messageSystem.init();
|
||
ClearUseWith();
|
||
ClearText();
|
||
|
||
/* FreeKey();
|
||
|
||
mleft = mright = 0;
|
||
Mouse(3);
|
||
while( mleft || mright )
|
||
Mouse(3);
|
||
|
||
// ferma omino, animazioni, spegne scritte
|
||
memcpy( OldInv, Inventario, MAXICON );
|
||
memset( Inventario, 0, MAXICON );
|
||
|
||
OldIconBase = TheIconBase;
|
||
TheIconBase = 0;
|
||
OldInvLen = InventarioLen;
|
||
InventarioLen = MAXSAVEFILE;
|
||
*/
|
||
|
||
if (!FileName.empty())
|
||
strcpy(str, FileName.c_str());
|
||
else
|
||
sprintf(str, "%sWm%#02d.sav", game.workDirs._savesDir.c_str(), slot);
|
||
|
||
auto stream = openFile(FileName);
|
||
if (!stream) {
|
||
return false;
|
||
}
|
||
Init &init = game.init;
|
||
|
||
WmVer = stream->readUint16LE();
|
||
if (WmVer != WM_SAVEFILE_VERSION) {
|
||
DebugLogFile("!!Invalid SaveGame Version: found %d, required %d", WmVer, WM_SAVEFILE_VERSION);
|
||
return false;
|
||
}
|
||
stream->read(str, T3D_NAMELEN);
|
||
stream->read(str, T3D_NAMELEN);
|
||
|
||
for (int i = 0; i < MAX_ROOMS; i++) {
|
||
init.Room[i].flags = stream->readUint16LE();
|
||
}
|
||
for (int i = 0; i < MAX_OBJS; i++) {
|
||
init.Obj[i].name = stream->readUint16LE();
|
||
init.Obj[i].examine.loadFromStream(*stream);
|
||
init.Obj[i].action.loadFromStream(*stream);
|
||
init.Obj[i].anim.loadFromStream(*stream);
|
||
init.Obj[i].anim2.loadFromStream(*stream);
|
||
init.Obj[i].goroom = stream->readByte();
|
||
init.Obj[i].ninv = stream->readByte();
|
||
init.Obj[i].flags = stream->readUint16LE();
|
||
init.Obj[i].pos = stream->readByte();
|
||
}
|
||
// HACK? (Something is off between 0.92 and the saves in the retail, leading to a slight skew.
|
||
stream->seek(92, SEEK_CUR);
|
||
for (int i = 0; i < MAX_ICONS; i++) {
|
||
init.InvObj[i].name = stream->readUint16LE();
|
||
init.InvObj[i].examine.loadFromStream(*stream);
|
||
init.InvObj[i].action.loadFromStream(*stream);
|
||
init.InvObj[i].flags = stream->readUint16LE();
|
||
init.InvObj[i].uwobj = stream->readUint16LE();
|
||
init.InvObj[i].anim.loadFromStream(*stream);
|
||
init.InvObj[i].anim2.loadFromStream(*stream);
|
||
}
|
||
for (int i = 0; i < MAX_SOUNDS; i++) {
|
||
init.Sound[i].flags = stream->readByte();
|
||
}
|
||
for (int i = 0; i < MAX_DIALOGS; i++) {
|
||
init.Dialog[i].flags = stream->readUint16LE();
|
||
}
|
||
for (int i = 0; i < MAX_DIARIES; i++) {
|
||
init.Diary[i].startt = stream->readUint16LE();
|
||
init.Diary[i].endt = stream->readUint16LE();
|
||
init.Diary[i].end_hideobj = stream->readUint16LE();
|
||
init.Diary[i].cur = 0;
|
||
for (int j = 0; j < MAX_DIARY_ITEMS; j++) {
|
||
init.Diary[i].item[j].on = FALSE;
|
||
init.Diary[i].item[j].cur = 0;
|
||
}
|
||
}
|
||
for (int i = 0; i < MAX_DLG_MENUS; i++) {
|
||
init.DlgMenu[i].on = stream->readByte();
|
||
}
|
||
for (int i = 0; i < MAX_PDALOGS; i++) {
|
||
init.PDALog[i].time = stream->readSint32LE();
|
||
init.PDALog[i].flags = stream->readSint32LE();
|
||
}
|
||
game._gameVars.setCurRoomId(stream->readSint32LE());
|
||
CurInvObj = stream->readSint32LE();
|
||
BigInvObj = stream->readSint32LE();
|
||
CurPlayer = stream->readSint32LE();
|
||
CurSubMusic = stream->readSint32LE();
|
||
for (int player = 0; player < MAX_PLAYERS; player++) {
|
||
for (int icon = 0; icon < MAX_ICONS_IN_INV; icon++) {
|
||
Inv[player][icon] = stream->readByte();
|
||
}
|
||
}
|
||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||
InvLen[i] = stream->readByte();
|
||
}
|
||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||
InvBase[i] = stream->readByte();
|
||
}
|
||
for (int i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||
PlayerPos[i] = stream->readByte();
|
||
}
|
||
CameraTargetObj = stream->readSint32LE();
|
||
CameraTargetBone = stream->readSint32LE();
|
||
|
||
for (int i = 0; i < 5; i++) {
|
||
Comb2D[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 5; i++) {
|
||
Comb2Q[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 3; i++) {
|
||
Comb19[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 5; i++) {
|
||
Comb1D[i] = stream->readSint32LE();
|
||
}
|
||
Forno25 = stream->readSint32LE();
|
||
Frigo25 = stream->readSint32LE();
|
||
for (int i = 0; i < 5; i++) {
|
||
Comb31[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 4; i++) {
|
||
Comb33[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 12; i++) {
|
||
Comb42[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 3; i++) {
|
||
Comb44[i] = stream->readSint32LE();
|
||
}
|
||
for (int i = 0; i < 5; i++) {
|
||
Comb45[i] = stream->readSint32LE();
|
||
}
|
||
bMoglieGym = stream->readByte();
|
||
bMoglieSangue = stream->readByte();
|
||
bNoPlayerSwitch = stream->readByte();
|
||
bPorteEsternoBloccate = stream->readByte();
|
||
bSezioneLabirinto = stream->readByte();
|
||
|
||
_vm->loadMeshModifiers(*stream);
|
||
|
||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||
PlayerStand[i] = SPlayerStand(*stream);
|
||
}
|
||
t3dCurTime = stream->readSint32LE();
|
||
|
||
for (int i = 0; i < T3D_MAX_CHARACTERS; i++) {
|
||
if ((i == ocCURPLAYER) || (i == ocLASTCHAR)) continue;
|
||
if (Character[i] && Character[i]->Mesh) {
|
||
Character[i]->Mesh->Trasl = t3dV3F(*stream);
|
||
Character[i]->Dir = t3dV3F(*stream);
|
||
Character[i]->Flags = stream->readByte();
|
||
Character[i]->Walk.LookX = stream->readFloatLE();
|
||
Character[i]->Walk.LookZ = stream->readFloatLE();
|
||
Character[i]->Walk.CurX = stream->readFloatLE();
|
||
Character[i]->Walk.CurZ = stream->readFloatLE();
|
||
Character[i]->Walk.CurPanel = stream->readSint16LE();
|
||
Character[i]->Walk.OldPanel = stream->readSint16LE();
|
||
} else {
|
||
// I avoid that the saves do not depend on the number of characters present in memory at that moment
|
||
//len = sizeof(t3dV3F) * 2 + sizeof(t3dU8) + sizeof(t3dF32) * 4 + sizeof(t3dS16) * 2;
|
||
t3dV3F unused(*stream);
|
||
t3dV3F unused2(*stream);
|
||
stream->readByte();
|
||
stream->readFloatLE();
|
||
stream->readFloatLE();
|
||
stream->readFloatLE();
|
||
stream->readFloatLE();
|
||
stream->readSint16LE();
|
||
stream->readSint16LE();
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||
for (int j = 0; j < T3D_MAX_CHARACTERS; j++) {
|
||
for (int k = 0; k < MAX_DLG_MENUS; k++) {
|
||
UsedDlgMenu[i][j][k] = stream->readByte();
|
||
}
|
||
}
|
||
}
|
||
|
||
// fclose(fhs);
|
||
|
||
// t3dVectCopy( &tmp, &Character[ocDARRELL]->Mesh->Trasl );
|
||
// t3dVectCopy( &tmp2, &Character[ocVICTORIA]->Mesh->Trasl );
|
||
|
||
StopAllAnims(init);
|
||
StopSounds();
|
||
StopMusic();
|
||
t3dResetPipeline();
|
||
_vm->_roomManager->releaseLoadedFiles(T3D_STATIC_SET1);
|
||
t3dRxt = nullptr;
|
||
t3dSky = nullptr;
|
||
rReleaseAllTextures(T3D_STATIC_SET0);
|
||
LoaderFlags |= T3D_STATIC_SET0;
|
||
rSetLoaderFlags(LoaderFlags);
|
||
t3dCurRoom = nullptr;
|
||
bPauseAllAnims = FALSE;
|
||
|
||
ChangeRoom(game, str, 0, 0);
|
||
|
||
// evito che i personaggi rimangano a mezz'aria quando il gioco si stoppa con i personaggi in dubbie posizioni
|
||
Character[ocCURPLAYER]->Mesh->Flags |= T3D_MESH_DEFAULTANIM;
|
||
// resetto solo il current player, visto che l'altro deve avere l'anim di stand
|
||
if (CurPlayer == DARRELL)
|
||
Character[ocDARRELL]->Mesh->Flags |= T3D_MESH_DEFAULTANIM;
|
||
else
|
||
Character[ocVICTORIA]->Mesh->Flags |= T3D_MESH_DEFAULTANIM;
|
||
|
||
t3dResetMesh(LinkMeshToStr(init, "darrell"));
|
||
t3dResetMesh(LinkMeshToStr(init, "victoria"));
|
||
// t3dVectCopy( &Character[ocDARRELL]->Mesh->Trasl, &tmp );
|
||
// t3dVectCopy( &Character[ocDARRELL]->Pos, &tmp );
|
||
// t3dVectCopy( &Character[ocVICTORIA]->Mesh->Trasl, &tmp2 );
|
||
// t3dVectCopy( &Character[ocVICTORIA]->Pos, &tmp2 );
|
||
|
||
// CharSetPosition( ocDARRELL, 0, NULL );
|
||
// CharSetPosition( ocVICTORIA, 0, NULL );
|
||
|
||
return true;
|
||
}
|
||
|
||
} // End of namespace Watchmaker
|