/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/system.h" #include "graphics/palette.h" #include "common/file.h" #include "common/rect.h" #include "engines/util.h" #include "hopkins/anim.h" #include "hopkins/files.h" #include "hopkins/globals.h" #include "hopkins/graphics.h" #include "hopkins/hopkins.h" namespace Hopkins { AnimationManager::AnimationManager() { CLS_ANM = false; NO_SEQ = false; } void AnimationManager::PLAY_ANM(const Common::String &filename, uint32 rate1, uint32 rate2, uint32 rate3) { int doneFlag; byte *screenCopy = NULL; uint16 v14, v15, v16, v17, v18, v19; size_t nbytes; byte *screenP; Common::File f; char strBuffer[20]; int idx = 0; doneFlag = 0; for (;;) { //MAIN_LOOP: v14 = v15 = v16 = v17 = 0; v18 = 1; screenP = _vm->_graphicsManager.VESA_SCREEN; FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPANM, filename); if (!f.open(GLOBALS.NFICHIER)) error("Not Found file %s", GLOBALS.NFICHIER.c_str()); // TODO: Original above read seems to overlap the doneFlag f.skip(6); //buf = read(4); doneFlag = f.readUint16LE() != 0; f.read(_vm->_graphicsManager.Palette, PALETTE_EXT_BLOCK_SIZE); f.skip(4); nbytes = f.readUint32LE(); // TODO: Original never seems to do anything with these. Or are these part of // a bigger structure needed for sub-methods? v19 = f.readUint32LE(); v18 = f.readUint16LE(); v17 = f.readUint16LE(); v16 = f.readUint16LE(); v15 = f.readUint16LE(); v14 = f.readUint16LE(); f.read(screenP, nbytes); if (CLS_ANM) { _vm->_graphicsManager.DD_Lock(); _vm->_graphicsManager.Cls_Video(); _vm->_graphicsManager.DD_Unlock(); } if (_vm->_graphicsManager.WinScan / _vm->_graphicsManager.Winbpp > SCREEN_WIDTH) { doneFlag = 1; screenCopy = GLOBALS.dos_malloc2(SCREEN_WIDTH * SCREEN_HEIGHT); memcpy((void *)screenCopy, screenP, SCREEN_WIDTH * SCREEN_HEIGHT); } if (NO_SEQ) { if (doneFlag == 1) memcpy((void *)screenCopy, _vm->_graphicsManager.VESA_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT); _vm->_graphicsManager.setpal_vga256(_vm->_graphicsManager.Palette); } else { _vm->_graphicsManager.setpal_vga256(_vm->_graphicsManager.Palette); _vm->_graphicsManager.DD_Lock(); if (_vm->_graphicsManager.Winbpp == 2) { if (doneFlag) _vm->_graphicsManager.m_scroll16A(screenCopy, 0, 0, 640, 480, 0, 0); else _vm->_graphicsManager.m_scroll16(screenP, 0, 0, 640, 480, 0, 0); } if (_vm->_graphicsManager.Winbpp == 1) { if (doneFlag) _vm->_graphicsManager.m_scroll2A(screenCopy, 0, 0, 640, 480, 0, 0); else _vm->_graphicsManager.m_scroll2(screenP, 0, 0, 640, 480, 0, 0); } _vm->_graphicsManager.DD_Unlock(); _vm->_graphicsManager.DD_VBL(); } _vm->_eventsManager.lItCounter = 0; _vm->_eventsManager.ESC_KEY = 0; _vm->_soundManager.LOAD_ANM_SOUND(); if (_vm->_globals.iRegul == 1) { do { if (_vm->_eventsManager.ESC_KEY) goto FINISH; // TODO: Original REDRAW_ANIM always returns false, so this isn't needed? #if 0 if (REDRAW_ANIM()) goto REDRAW_ANIM; #endif _vm->_eventsManager.CONTROLE_MES(); } while (_vm->_eventsManager.lItCounter < rate1); } _vm->_eventsManager.lItCounter = 0; doneFlag = false; idx = 0; do { _vm->_soundManager.PLAY_ANM_SOUND(idx); // Get in string Common::fill(&strBuffer[0], &strBuffer[20], 0); if (f.read(strBuffer, 16) != 16) doneFlag = true; if (strncmp(strBuffer, "IMAGE=", 6) != 0) doneFlag = true; if (!doneFlag) { f.read(screenP, READ_LE_UINT32(strBuffer + 8)); if (_vm->_globals.iRegul == 1) { do { if (_vm->_eventsManager.ESC_KEY) goto FINISH; // TODO: Original REDRAW_ANIM always returns false, so this isn't needed? #if 0 if (REDRAW_ANIM()) { if (_vm->_graphicsManager.NOLOCK == 1) goto FINISH; f.close(); if (doneFlag <= SCREEN_WIDTH) goto MAIN_LOOP; screenCopy = GLOBALS.dos_free2(screenCopy); goto MAIN_LOOP; } #endif _vm->_eventsManager.CONTROLE_MES(); _vm->_soundManager.VERIF_SOUND(); } while (_vm->_eventsManager.lItCounter < rate2 && !_vm->shouldQuit()); } _vm->_eventsManager.lItCounter = 0; _vm->_graphicsManager.DD_Lock(); if (!doneFlag) { if (*screenP != 252) { if (_vm->_graphicsManager.Winbpp == 1) _vm->_graphicsManager.Copy_Video_Vbe3(screenP); if (_vm->_graphicsManager.Winbpp == 2) _vm->_graphicsManager.Copy_Video_Vbe16(screenP); } } else if (*screenP != 252) { _vm->_graphicsManager.Copy_WinScan_Vbe3(screenP, screenCopy); if (_vm->_graphicsManager.Winbpp == 2) _vm->_graphicsManager.m_scroll16A(screenCopy, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); else _vm->_graphicsManager.m_scroll2A(screenCopy, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); } _vm->_graphicsManager.DD_Unlock(); _vm->_graphicsManager.DD_VBL(); _vm->_soundManager.VERIF_SOUND(); } } while (!doneFlag && !_vm->shouldQuit()); if (_vm->_globals.iRegul != 1) { _vm->_eventsManager.lItCounter = 0; goto FINISH; } do { if (_vm->_eventsManager.ESC_KEY) goto FINISH; // TODO: Original REDRAW_ANIM always returns false, so this isn't needed? #if 0 if (REDRAW_ANIM()) { REDRAW_ANIM: if (_vm->_graphicsManager.NOLOCK == 1) goto FINISH; f.close(); if (doneFlag != 1) goto MAIN_LOOP; screenCopy = GLOBALS.dos_free2(screenCopy); goto MAIN_LOOP; } #endif _vm->_eventsManager.CONTROLE_MES(); _vm->_soundManager.VERIF_SOUND(); } while (_vm->_eventsManager.lItCounter < rate3 && !_vm->shouldQuit()); _vm->_eventsManager.lItCounter = 0; _vm->_soundManager.VERIF_SOUND(); break; } FINISH: if (_vm->_graphicsManager.FADE_LINUX == 2 && !doneFlag) { screenCopy = GLOBALS.dos_malloc2(SCREEN_WIDTH * SCREEN_HEIGHT); f.skip(6); f.read(_vm->_graphicsManager.Palette, PALETTE_EXT_BLOCK_SIZE); f.skip(4); nbytes = f.readUint32LE(); v19 = f.readUint32LE(); v18 = f.readUint16LE(); v17 = f.readUint16LE(); v16 = f.readUint16LE(); v15 = f.readUint16LE(); v14 = f.readUint16LE(); f.read(screenCopy, nbytes); Common::copy(screenP, screenP + SCREEN_WIDTH * SCREEN_HEIGHT, screenCopy); idx = 0; doneFlag = false; do { // Get in string Common::fill(&strBuffer[0], &strBuffer[20], 0); if (f.read(strBuffer, 16) != 16) doneFlag = true; if (strncmp(strBuffer, "IMAGE=", 7) != 0) doneFlag = true; if (!doneFlag) { f.read(screenP, READ_LE_UINT32(strBuffer + 8)); if (*screenP != 252) _vm->_graphicsManager.Copy_WinScan_Vbe3(screenP, screenCopy); } } while (!doneFlag); _vm->_graphicsManager.FADE_OUTW_LINUX(screenCopy); screenCopy = GLOBALS.dos_free2(screenCopy); } if (doneFlag == 1) { if (_vm->_graphicsManager.FADE_LINUX == 2) _vm->_graphicsManager.FADE_OUTW_LINUX(screenCopy); GLOBALS.dos_free2(screenCopy); } _vm->_graphicsManager.FADE_LINUX = 0; f.close(); GLOBALS.dos_free2(screenCopy); _vm->_graphicsManager.NOLOCK = false; } bool AnimationManager::REDRAW_ANIM() { return false; } void AnimationManager::BOBANIM_ON(int idx) { if (GLOBALS.Bob[idx].field16) { GLOBALS.Bob[idx].field16 = 0; GLOBALS.Bob[idx].field10 = 5; GLOBALS.Bob[idx].fieldC = 250; GLOBALS.Bob[idx].field12 = 0; GLOBALS.Bob[idx].field14 = 0; } } void AnimationManager::BOBANIM_OFF(int idx) { GLOBALS.Bob[idx].field16 = 1; } void AnimationManager::CHARGE_ANIM(const Common::String &animName) { byte v20[15]; char header[10]; char filename1[15]; char filename2[15]; char filename3[15]; char filename4[15]; char filename5[15]; char filename6[15]; CLEAR_ANIM(); Common::String filename = animName + ".ANI"; FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPANIM, filename); Common::File f; if (!f.open(GLOBALS.NFICHIER)) error("Failed to open %s", GLOBALS.NFICHIER); int filesize = f.size(); int nbytes = filesize - 115; f.read(header, 10); f.read(v20, 15); f.read(filename1, 15); f.read(filename2, 15); f.read(filename3, 15); f.read(filename4, 15); f.read(filename5, 15); f.read(filename6, 15); if (header[0] != 'A' || header[1] != 'N' || header[2] != 'I' || header[3] != 'S') error("File incompatible with this soft."); const char *files[6] = { &filename1[0], &filename2[0], &filename3[0], &filename4[0], &filename5[0], &filename6[0] }; for (int idx = 1; idx <= 6; ++idx) { if (files[idx - 1][0]) { FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPANIM, files[idx - 1]); if (!f.exists(GLOBALS.NFICHIER)) error("File not found"); if (CHARGE_BANK_SPRITE1(idx, files[idx - 1])) error("File not compatible with this soft."); } } byte *data = GLOBALS.dos_malloc2(nbytes + 1); f.read(data, nbytes); f.close(); for (int idx = 1; idx <= 20; ++idx) { RECHERCHE_ANIM(data, idx, nbytes); } GLOBALS.dos_free2(data); } void AnimationManager::CLEAR_ANIM() { for (int idx = 0; idx < 35; ++idx) { if (GLOBALS.Bqe_Anim[idx].data != PTRNUL) GLOBALS.Bqe_Anim[idx].data = GLOBALS.dos_free2(GLOBALS.Bqe_Anim[idx].data); GLOBALS.Bqe_Anim[idx].field4 = 0; } for (int idx = 0; idx < 8; ++idx) { if (GLOBALS.Bank[idx].data != PTRNUL) GLOBALS.Bank[idx].data = GLOBALS.dos_free2(GLOBALS.Bank[idx].data); GLOBALS.Bank[idx].field4 = 0; GLOBALS.Bank[idx].filename1 = ""; GLOBALS.Bank[idx].fileHeader = 0; GLOBALS.Bank[idx].field1C = 0; } } int AnimationManager::CHARGE_BANK_SPRITE1(int idx, const Common::String &filename) { byte *v3; byte *v4; int v7; int v8; int width; int height; byte *v13; __int16 v16; __int16 v17; byte *ptr; byte *v19; __int16 v20; __int16 v21; int result = 0; FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPANIM, filename); GLOBALS.Bank[idx].field1C = FileManager::FLONG(GLOBALS.NFICHIER); GLOBALS.Bank[idx].field4 = 1; GLOBALS.Bank[idx].filename1 = filename; GLOBALS.Bank[idx].filename2 = GLOBALS.REP_SPR; v3 = FileManager::CHARGE_FICHIER(GLOBALS.NFICHIER); v4 = v3; GLOBALS.Bank[idx].fileHeader = 0; if (*(v3 + 1) == 'L' && *(v3 + 2) == 'E') GLOBALS.Bank[idx].fileHeader = 1; if (*(v3 + 1) == 'O' && *(v3 + 2) == 'R') GLOBALS.Bank[184].fileHeader = 2; if (GLOBALS.Bank[idx].fileHeader) { GLOBALS.Bank[idx].data = v3; v7 = 0; v8 = 0; do { ptr = v4; width = _vm->_objectsManager.Get_Largeur(v4, v8); height = _vm->_objectsManager.Get_Hauteur(ptr, v8); v4 = ptr; if (!width && !height) v7 = 1; if (!v7) ++v8; if (v8 > 249) v7 = 1; } while (v7 != 1); if (v8 <= 249) { GLOBALS.Bank[idx].field1A = v8; Common::String ofsFilename = GLOBALS.Bank[idx].filename1; while (ofsFilename.lastChar() != '.') ofsFilename.deleteLastChar(); ofsFilename += ".OFS"; FileManager::CONSTRUIT_FICHIER(GLOBALS.HOPANIM, ofsFilename); Common::File f; if (!f.exists(GLOBALS.NFICHIER)) { v19 = FileManager::CHARGE_FICHIER(GLOBALS.NFICHIER); v13 = v19; if (GLOBALS.Bank[idx].field1A > 0) { for (int v14 = 0; v14 < GLOBALS.Bank[idx].field1A; ++v14) { v16 = READ_LE_UINT16(v13); v17 = READ_LE_UINT16(v13 + 2); v21 = READ_LE_UINT16(v13 + 4); v20 = READ_LE_UINT16(v13 + 6); v13 += 8; _vm->_objectsManager.set_offsetxy(GLOBALS.Bank[idx].data, v14, v16, v17, 0); if (GLOBALS.Bank[idx].fileHeader == 2) _vm->_objectsManager.set_offsetxy(GLOBALS.Bank[idx].data, v14, v21, v20, 1); } } GLOBALS.dos_free2(v19); } result = 0; } else { GLOBALS.dos_free2(ptr); GLOBALS.Bank[idx].field4 = 0; result = -2; } } else { GLOBALS.dos_free2(v3); GLOBALS.Bank[idx].field4 = 0; result = -1; } return result; } void AnimationManager::RECHERCHE_ANIM(const byte *data, int idx, int nbytes) { int v4; const byte *v5; int v6; int v7; byte *v9; __int16 v10; __int16 v11; __int16 v12; char v13; signed int v14; __int16 v15; __int16 v16; char v17; int v19; char v20; int v21; __int16 v22; const byte *v23; int v24; bool doneFlag = false; bool breakFlag; v21 = 0; v4 = 8 * idx; v19 = 8 * idx; do { v20 = *(v21 + data); if (*(data + v20) == 'A' && *(data + v20 + 1) == 'N' && *(data + v20 + 2) == 'I' && *(data + v20 + 3) == 'M') { v4 = *(data + v21 + 4); if (idx == v4) { v5 = v21 + data + 5; v6 = v21 + 5; v7 = 0; breakFlag = false; do { if (*v5 == 'A' && *(v5 + 1) == 'N' && *(v5 + 2) == 'I' && *(v5 + 3) == 'M') breakFlag = true; if (*v5 == 'F' && *(v5 + 1) == 'I' && *(v5 + 2) == 'N') breakFlag = true; if (nbytes < v6) { GLOBALS.Bqe_Anim[idx].field4 = 0; GLOBALS.Bqe_Anim[idx].data = PTRNUL; } ++v6; ++v7; ++v5; } while (!breakFlag); GLOBALS.Bqe_Anim[idx].data = GLOBALS.dos_malloc2(v7 + 50); GLOBALS.Bqe_Anim[idx].field4 = 1; memcpy(GLOBALS.Bqe_Anim[idx].data, v21 + data + 5, 20); byte *dataP = GLOBALS.Bqe_Anim[idx].data; v9 = dataP + 20; v23 = v21 + data + 25; v10 = READ_LE_UINT16(v21 + data + 25); v11 = READ_LE_UINT16(v21 + data + 27); v22 = READ_LE_UINT16(v21 + data + 29); v12 = READ_LE_UINT16(v21 + data + 31); v13 = READ_LE_UINT16(v21 + data + 33); *(dataP + 29) = *(v21 + data + 34); WRITE_LE_UINT16(dataP + 20, v10); WRITE_LE_UINT16(dataP + 22, v11); WRITE_LE_UINT16(dataP + 24, v22); WRITE_LE_UINT16(dataP + 26, v12); WRITE_LE_UINT16(dataP + 28, v13); v14 = 1; do { v9 += 10; v23 += 10; if (!v22) break; v24 = READ_LE_UINT16(v23); v15 = READ_LE_UINT16(v23 + 2); v22 = READ_LE_UINT16(v23 + 4); v16 = READ_LE_UINT16(v23 + 6); v17 = READ_LE_UINT16(v23 + 8); *(v9 + 9) = *(v23 + 9); WRITE_LE_UINT16(v9, v24); WRITE_LE_UINT16(v9 + 2, v15); WRITE_LE_UINT16(v9 + 4, v22); WRITE_LE_UINT16(v9 + 6, v16); WRITE_LE_UINT16(v9 + 8, v17); ++v14; } while (v14 <= 4999); doneFlag = 1; } } if (*(data + v20) == 'F' && *(data + v21 + 1) == 'I' && *(data + v21 + 2) == 'N') doneFlag = 1; ++v21; } while (v21 <= nbytes && !doneFlag); } } // End of namespace Hopkins