diff --git a/engines/tony/font.cpp b/engines/tony/font.cpp new file mode 100644 index 000000000000..2996b30f040b --- /dev/null +++ b/engines/tony/font.cpp @@ -0,0 +1,2510 @@ +/* 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. + * + */ +/************************************************************************** + * 様様様様様様様様様様様様様様様様様 * + * Nayma Software srl * + * e -= We create much MORE than ALL =- * + * u- z$$$c '. 様様様様様様様様様様様様様様様様様 * + * .d" d$$$$$b "b. * + * .z$* d$$$$$$$L ^*$c. * + * #$$$. $$$$$$$$$ .$$$" Project: Roasted Moths........ * + * ^*$b 4$$$$$$$$$F .d$*" * + * ^$$. 4$$$$$$$$$F .$P" Module: Font.CPP............. * + * *$. '$$$$$$$$$ 4$P 4 * + * J *$ "$$$$$$$" $P r Author: Giovanni Bajo........ * + * z$ '$$$P*4c.*$$$*.z@*R$$$ $. * + * z$" "" #$F^ "" '$c * + * z$$beu .ue=" $ "=e.. .zed$$c * + * "#$e z$*" . `. ^*Nc e$"" * + * "$$". .r" ^4. .^$$" * + * ^.@*"6L=\ebu^+C$"*b." * + * "**$. "c 4$$$ J" J$P*" OS: [ ] DOS [X] WIN95 [ ] PORT * + * ^"--.^ 9$" .--"" COMP: [ ] WATCOM [X] VISUAL C++ * + * " [ ] EIFFEL [ ] GCC/GXX/DJGPP * + * * + * This source code is Copyright (C) Nayma Software. ALL RIGHTS RESERVED * + * * + **************************************************************************/ + +#include "common/textconsole.h" +#include "tony/mpal/mpalutils.h" +#include "tony/mpal/stubs.h" +#include "tony/font.h" +#include "tony/input.h" +#include "tony/inventory.h" +#include "tony/loc.h" +#include "tony/tony.h" + +namespace Tony { + +/****************************************************************************\ +* Metodi di RMFont +\****************************************************************************/ + +RMFont::RMFont() { + m_letter = NULL; +} + +RMFont::~RMFont() { + Unload(); +} + +/****************************************************************************\ +* +* Function: void RMFont::Load(byte *buf, int nChars, int dimx, int dimy); +* +* Description: Carica un font da buffer +* +* Input: byte *buf Buffer contenente il font +* int nChars Numero di caratteri (max 256) +* int dimx,dimy Dimensione in pixel di un carattere +* +\****************************************************************************/ + +void DumpFontBMP(const char *filename, const byte *buf, int nChars, int charX, int charY, byte *pal) { + error("DumpFontBMP not supported in ScummVM"); +} + + +void RMFont::Load(const byte *buf, int nChars, int dimx, int dimy, uint32 palResID) { + m_letter = new RMGfxSourceBuffer8RLEByte[nChars]; + +#if 0 + if (nChars == 112 && palResID == RES_F_PAL) + { + // Font parla + DumpFontBMP("font_parla.bmp", buf, nChars, dimx, dimy, RMRes(palResID)); + } + else if (nChars == 102 && palResID == RES_F_PAL) + { + // Font macc + DumpFontBMP("font_macc.bmp", buf, nChars, dimx, dimy, RMRes(palResID)); + } + else if (nChars == 85 && palResID == RES_F_PAL) + { + // Font obj + DumpFontBMP("font_obj.bmp", buf, nChars, dimx, dimy, RMRes(palResID)); + } + else if (nChars == 112 && palResID == RES_F_CPAL) + { + // Font credits + DumpFontBMP("font_credits.bmp", buf, nChars, dimx, dimy, RMRes(palResID)); + } +#endif + + // Carichiamoce 'sto font + for (int i = 0; i < nChars; i++) + { + // Inizializza il buffer con le lettere + m_letter[i].Init(buf + i * (dimx * dimy + 8) + 8, dimx, dimy); + m_letter[i].LoadPaletteWA(palResID); + } + + m_fontDimx = dimx; + m_fontDimy = dimy; + + nLetters=nChars; +} + + +void RMFont::Unload(void) { + if (m_letter != NULL) { + delete[] m_letter; + m_letter = NULL; + } +} + + +RMGfxPrimitive *RMFont::MakeLetterPrimitive(byte bChar, int &nLength) { + RMFontPrimitive *prim; + int nLett; + + // Converte da carattere a lettera + nLett = ConvertToLetter(bChar); + + // Crea la primitiva per il font + prim = new RMFontPrimitive(this); + prim->m_nChar = nLett; + + // Si fa' dare la lunghezza della lettera in pixel + nLength = LetterLength(bChar); + + return prim; +} + +void RMFont::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim2) { + RMFontPrimitive *prim = (RMFontPrimitive *)prim2; + + // Richiama la Draw della lettera assegnata alla primitiva + if (prim->m_nChar != -1) + m_letter[prim->m_nChar].Draw(bigBuf,prim); +} + +void RMFont::Close(void) { + Unload(); +} + +int RMFont::StringLen(RMString text) { + int len, i; + + len = 0; + for (i = 0; i < text.Length() - 1; i++) + len += LetterLength(text[i], text[i + 1]); + len += LetterLength(text[i]); + + return len; +} + +int RMFont::StringLen(char bChar, char bNext) { + return LetterLength(bChar, bNext); +} + +/****************************************************************************\ +* Metodi di RMFontColor +\****************************************************************************/ + +RMFontColor::RMFontColor() : RMFont() { + m_r = m_g = m_b = 255; +} + +RMFontColor::~RMFontColor() { + +} + +void RMFontColor::SetBaseColor(byte r1, byte g1, byte b1) { + int r = (int)r1 << 16; + int g = (int)g1 << 16; + int b = (int)b1 << 16; + + int rstep = r / 14; + int gstep = g / 14; + int bstep = b / 14; + + int i; + byte pal[768*3]; + + // Controlla se siamo gia' sul colore giusto + if (m_r == r1 && m_g == g1 && m_b == b1) + return; + + m_r = r1; + m_g = g1; + m_b = b1; + + // Costruisce la nuova palette per il font + for (i = 1; i < 16; i++) { + pal[i * 3 + 0] = r >> 16; + pal[i * 3 + 1] = g >> 16; + pal[i * 3 + 2] = b >> 16; + + r -= rstep; + g -= gstep; + b -= bstep; + } + + pal[15*3 + 0] += 8; + pal[15*3 + 1] += 8; + pal[15*3 + 2] += 8; + + // La mette in tutte le lettere + for (i = 0; i < nLetters; i++) + m_letter[i].LoadPaletteWA(pal); +} + + +/***************************************************************************\ +* Metodi di RMFontParla +\****************************************************************************/ + +void RMFontParla::Init(void) { + int i; + + // bernie: numero di caratteri nel font + int nchars = + 112 // base + + 18 // polish + + 66 // russian + + 30 // czech + + 8 // french + + 5; // deutsch + + Load(RES_F_PARL, nchars, 20, 20); + + // Inizializziamo le tabelline del cazzo + lDefault = 13; + hDefault = 18; + Common::fill(&l2Table[0][0], &l2Table[0][0] + (256 * 256), '\0'); + for (i = 0; i < 256; i++) + { + cTable[i] = -1; + lTable[i] = lDefault; + } + + for (i = 0; i < 26; i++) + cTable['A' + i] = i + 0; + + for (i = 0; i < 26; i++) + cTable['a' + i] = i + 26; + + for (i = 0; i < 10; i++) + cTable['0' + i] = i + 52; + + cTable[';'] = 62; + cTable[','] = 63; + cTable['.'] = 64; + cTable[':'] = 65; + cTable['-'] = 66; + cTable['_'] = 67; + cTable['+'] = 68; + cTable['<'] = 69; + cTable['>'] = 70; + cTable['!'] = 71; + //cTable['!'] = 72; Esclamativo alla rovescia + cTable['?'] = 73; + //cTable['?'] = 74; Interrogativo alla rovescia + cTable['('] = 75; + cTable[')'] = 76; + cTable['\"'] = 77; + cTable['^'] = 77; + cTable['/'] = 78; + cTable[''] = 79; + cTable['$'] = 80; + cTable['%'] = 81; + cTable['&'] = 82; + cTable['='] = 83; + cTable[''] = 84; + cTable[''] = 85; + cTable[''] = 86; + cTable[''] = 87; + cTable[''] = 88; + cTable[''] = 89; + cTable[''] = 89; + cTable[''] = 90; + cTable[''] = 91; + cTable[''] = 92; + cTable[''] = 93; + cTable[''] = 94; + cTable[''] = 95; + cTable[''] = 96; + cTable[''] = 97; + cTable[''] = 98; + cTable[''] = 99; + //cTable[' '] = 100; e cerchietto + //cTable[' '] = 101; i cerchietto + //cTable[' '] = 102; o cerchietto + //cTable[' '] = 103; u cerchietto + cTable[''] = 104; + cTable[''] = 105; + cTable[''] = 106; + cTable[''] = 107; + cTable[''] = 108; + cTable[''] = 109; + //cTable[''] = 110; integrale + cTable['\''] = 111; + + // Un po' di lunghezze + lTable[' '] = 9; + lTable['\''] = 5; + lTable['.'] = 5; + lTable[','] = 5; + lTable[':'] = 5; + lTable[';'] = 5; + lTable['!'] = 5; + lTable['?'] = 10; + lTable['\"'] = 5; + lTable['^'] = 5; + lTable['('] = 7; + lTable[')'] = 7; + + lTable['4'] = 10; + + lTable['a'] = 14; + lTable['b'] = 15; + lTable['c'] = 12; + lTable['e'] = 12; + lTable['i'] = 6; + lTable[''] = 6; + lTable['l'] = 5; + lTable['m'] = 16; + lTable['n'] = 12; + lTable['o'] = 11; + lTable['p'] = 11; + lTable['s'] = 12; + lTable['u'] = 12; + + lTable['E'] = 10; + lTable['F'] = 11; + + + // Polish characters + //AaCcEeLlNnOoSsZzZz + //ス謎戊3剔囀 + + cTable[''] = 112; + cTable[''] = 113; + cTable[''] = 114; + cTable[''] = 115; + cTable[''] = 116; + cTable[''] = 117; + cTable[''] = 118; + cTable[''] = 119; + cTable[''] = 120; + cTable[''] = 121; + cTable[''] = 122; + cTable[''] = 123; + cTable[''] = 124; + cTable[''] = 125; + cTable[''] = 126; + cTable[''] = 127; + cTable[''] = 128; + cTable[''] = 129; + + lTable[''] = 14; + lTable[''] = 16; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 14; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 14; + lTable[''] = 13; + +#ifdef FONT_RUSSIAN + // Russian Characters + // WARNING: Il russo usa molti dei caratteri ISO-Latin-1 che servono + // per le altre traduzioni. Per compilare Tony in altre lingue, + // commentare via queste definizioni. + + cTable[''] = 130; + cTable[''] = 131; + cTable[''] = 132; + cTable[''] = 133; + cTable[''] = 134; + cTable[''] = 135; + cTable[''] = 136; + cTable[''] = 137; + cTable[''] = 138; + cTable[''] = 139; + cTable[''] = 140; + cTable[''] = 141; + cTable[''] = 142; + cTable[''] = 143; + cTable[''] = 144; + cTable[''] = 145; + cTable[''] = 146; + cTable[''] = 147; + cTable[''] = 148; + cTable[''] = 149; + cTable[''] = 150; + cTable[''] = 151; + cTable[''] = 152; + cTable[''] = 153; + cTable[''] = 154; + cTable[''] = 155; + cTable[''] = 156; + cTable[''] = 157; + cTable[''] = 158; + cTable[''] = 159; + cTable[''] = 160; + cTable[''] = 161; + cTable[''] = 162; + + cTable[''] = 163; + cTable[''] = 164; + cTable[''] = 165; + cTable[''] = 166; + cTable[''] = 167; + cTable[''] = 168; + cTable[''] = 169; + cTable[''] = 170; + cTable[''] = 171; + cTable[''] = 172; + cTable[''] = 173; + cTable[''] = 174; + cTable[''] = 175; + cTable[''] = 176; + cTable[''] = 177; + cTable[''] = 178; + cTable[''] = 179; + cTable[''] = 180; + cTable[''] = 181; + cTable[''] = 182; + cTable[''] = 183; + cTable[''] = 184; + cTable[''] = 185; + cTable[''] = 186; + cTable[''] = 187; + cTable[''] = 188; + cTable[''] = 189; + cTable[''] = 190; + cTable[''] = 191; + cTable[''] = 192; + cTable[''] = 193; + cTable[''] = 194; + cTable[''] = 195; + + lTable[''] = 13; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 11; + lTable[''] = 15; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 14; + lTable[''] = 14; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 18; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 17; + lTable[''] = 18; + lTable[''] = 16; + lTable[''] = 18; + lTable[''] = 19; + lTable[''] = 11; + lTable[''] = 16; + lTable[''] = 14; + + lTable[''] = 14; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 14; + lTable[''] = 8; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 16; + lTable[''] = 14; + lTable[''] = 16; + lTable[''] = 16; + lTable[''] = 9; + lTable[''] = 15; + lTable[''] = 14; + +#endif // FONT_RUSSIAN + +#ifdef FONT_CZECH + + cTable[''] = 196; + cTable[''] = 197; + cTable[''] = 198; + cTable[''] = 199; + cTable[''] = 200; + cTable[''] = 201; + cTable[''] = 202; + cTable[''] = 203; + cTable[''] = 204; + cTable[''] = 205; + cTable[''] = 206; + cTable[''] = 207; + cTable[''] = 208; + cTable[''] = 209; + cTable[''] = 210; + + cTable[''] = 211; + cTable[''] = 212; + cTable[''] = 213; + cTable[''] = 214; + cTable[''] = 215; + cTable[''] = 216; + cTable[''] = 217; + cTable[''] = 218; + cTable[''] = 219; + cTable[''] = 220; + cTable[''] = 221; + cTable[''] = 222; + cTable[''] = 223; + cTable[''] = 224; + cTable[''] = 225; + + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 14; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 15; + lTable[''] = 19; + lTable[''] = 10; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 13; + + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 15; + lTable[''] = 7; + lTable[''] = 12; + lTable[''] = 17; + lTable[''] = 16; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 13; + +#endif // FONT_CZECH + +#ifdef FONT_FRENCH + cTable[''] = 226; + cTable[''] = 227; + cTable[''] = 228; + cTable[''] = 229; + cTable[''] = 230; + cTable[''] = 231; + cTable[''] = 232; + cTable[''] = 233; + + lTable[''] = 15; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 9; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 11; + +#endif // FONT_FRENCH + +#ifdef FONT_GERMAN + cTable[''] = 234; + // 'SS' = 235 + cTable[''] = 236; + cTable[''] = 237; + cTable[''] = 238; + + lTable[''] = 15; + +#endif // FONT_GERMAN +} + + +/***************************************************************************\ +* Metodi di RMFontMacc +\****************************************************************************/ + +void RMFontMacc::Init(void) { + int i; + + // bernie: numero di caratteri nel font + int nchars = + 102 // base + + 18 // polish + + 66 // russian + + 30 // czech + + 8 // francais + + 5; // deutsch + + + Load(RES_F_MACC, nchars, 11, 16); + + // Default + lDefault = 10; + hDefault = 17; + Common::fill(&l2Table[0][0], &l2Table[0][0] + (256 * 256), '\0'); + + for (i = 0; i < 256; i++) { + cTable[i] = -1; + lTable[i] = lDefault; + } + + for (i = 0; i < 26; i++) + cTable['A'+i] = i + 0; + + for (i = 0; i < 26; i++) + cTable['a'+i] = i + 26; + + for (i = 0; i < 10; i++) + cTable['0'+i] = i + 52; + + cTable['!'] = 62; + //cTable['!'] = 63; // ! rovescia + cTable['\"'] = 64; + cTable['$'] = 65; + cTable['%'] = 66; + cTable['&'] = 67; + cTable['/'] = 68; + cTable['('] = 69; + cTable[')'] = 70; + cTable['='] = 71; + cTable['?'] = 72; + //cTable['?'] = 73; // ? rovescia + cTable['*'] = 74; + cTable['+'] = 75; + cTable[''] = 76; + cTable[';'] = 77; + cTable[','] = 78; + cTable['.'] = 79; + cTable[':'] = 80; + cTable['-'] = 81; + cTable['<'] = 82; + cTable[' > '] = 83; + cTable['/'] = 84; + cTable[''] = 85; + cTable[''] = 86; + cTable[''] = 87; + cTable[''] = 88; + cTable[''] = 89; + cTable[''] = 90; + //cTable[''] = 91; // e col pallino + cTable[''] = 92; + cTable[''] = 93; + //cTable[''] = 94; // i col pallino + cTable[''] = 95; + cTable[''] = 96; + //cTable[''] = 97; // o col pallino + cTable[''] = 98; + cTable[''] = 99; + //cTable[''] = 100; // u col pallino + cTable[''] = 101; + + // Polish characters + //AaCcEeLlNnOoSsZzZz + //ス謎戊3剔囀 + + cTable[''] = 102; + cTable[''] = 103; + cTable[''] = 104; + cTable[''] = 105; + cTable[''] = 106; + cTable[''] = 107; + cTable[''] = 108; + cTable[''] = 109; + cTable[''] = 110; + cTable[''] = 111; + cTable[''] = 112; + cTable[''] = 113; + cTable[''] = 114; + cTable[''] = 115; + cTable[''] = 116; + cTable[''] = 117; + cTable[''] = 118; + cTable[''] = 119; + + lTable[''] = 14; + lTable[''] = 16; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 14; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 14; + lTable[''] = 13; + + +#ifdef FONT_RUSSIAN + // Russian Characters + // WARNING: Il russo usa molti dei caratteri ISO-Latin-1 che servono + // per le altre traduzioni. Per compilare Tony in altre lingue, + // commentare via queste definizioni. + + cTable[''] = 120; + cTable[''] = 121; + cTable[''] = 122; + cTable[''] = 123; + cTable[''] = 124; + cTable[''] = 125; + cTable[''] = 126; + cTable[''] = 127; + cTable[''] = 128; + cTable[''] = 129; + cTable[''] = 130; + cTable[''] = 131; + cTable[''] = 132; + cTable[''] = 133; + cTable[''] = 134; + cTable[''] = 135; + cTable[''] = 136; + cTable[''] = 137; + cTable[''] = 138; + cTable[''] = 139; + cTable[''] = 140; + cTable[''] = 141; + cTable[''] = 142; + cTable[''] = 143; + cTable[''] = 144; + cTable[''] = 145; + cTable[''] = 146; + cTable[''] = 147; + cTable[''] = 148; + cTable[''] = 149; + cTable[''] = 150; + cTable[''] = 151; + cTable[''] = 152; + + cTable[''] = 153; + cTable[''] = 154; + cTable[''] = 155; + cTable[''] = 156; + cTable[''] = 157; + cTable[''] = 158; + cTable[''] = 159; + cTable[''] = 160; + cTable[''] = 161; + cTable[''] = 162; + cTable[''] = 163; + cTable[''] = 164; + cTable[''] = 165; + cTable[''] = 166; + cTable[''] = 167; + cTable[''] = 168; + cTable[''] = 169; + cTable[''] = 170; + cTable[''] = 171; + cTable[''] = 172; + cTable[''] = 173; + cTable[''] = 174; + cTable[''] = 175; + cTable[''] = 176; + cTable[''] = 177; + cTable[''] = 178; + cTable[''] = 179; + cTable[''] = 180; + cTable[''] = 181; + cTable[''] = 182; + cTable[''] = 183; + cTable[''] = 184; + cTable[''] = 185; + + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 8; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 11; + +#endif // FONT_RUSSIAN + +#ifdef FONT_CZECH + + cTable[''] = 186; + cTable[''] = 187; + cTable[''] = 188; + cTable[''] = 189; + cTable[''] = 190; + cTable[''] = 191; + cTable[''] = 192; + cTable[''] = 193; + cTable[''] = 194; + cTable[''] = 195; + cTable[''] = 196; + cTable[''] = 197; + cTable[''] = 198; + cTable[''] = 199; + cTable[''] = 200; + + cTable[''] = 201; + cTable[''] = 202; + cTable[''] = 203; + cTable[''] = 204; + cTable[''] = 205; + cTable[''] = 206; + cTable[''] = 207; + cTable[''] = 208; + cTable[''] = 209; + cTable[''] = 210; + cTable[''] = 211; + cTable[''] = 212; + cTable[''] = 213; + cTable[''] = 214; + cTable[''] = 215; + + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 9; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + +#endif // FONT_CZECH + +#ifdef FONT_FRENCH + + cTable[''] = 226; + cTable[''] = 227; + cTable[''] = 228; + cTable[''] = 229; + cTable[''] = 230; + cTable[''] = 231; + cTable[''] = 232; + cTable[''] = 233; + + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 8; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + +#endif // FONT_FRENCH + +#ifdef FONT_GERMAN + cTable[''] = 234; + // 'SS' = 235 + cTable[''] = 236; + cTable[''] = 237; + cTable[''] = 238; + + lTable[''] = 11; +#endif // FONT_GERMAN +} + +/***************************************************************************\ +* Metodi di RMFontCredits +\****************************************************************************/ + +void RMFontCredits::Init(void) { + int i; + + // bernie: numero di caratteri nel font + int nchars = + 112 // base + + 18 // polish + + 66 // russian + + 30 // czech + + 8 // french + + 2; // deutsch + + + Load(RES_F_CREDITS, nchars, 27, 28, RES_F_CPAL); + + // Default + lDefault=10; + hDefault=28; + Common::fill(&l2Table[0][0], &l2Table[0][0] + (256 * 256), '\0'); + + for (i = 0; i < 256; i++) + { + cTable[i] = -1; + lTable[i] = lDefault; + } + + for (i = 0; i < 26; i++) + cTable['A' + i] = i + 0; + + for (i = 0; i < 26; i++) + cTable['a' + i] = i + 26; + + + + cTable[''] = 52; + cTable[''] = 53; +// cTable[''] = 54; // a ^ +// cTable[''] = 55; // a pallini + cTable[''] = 56; + cTable[''] = 57; +// cTable[''] = 58; // e ^ +// cTable[''] = 59; // e pallini + cTable[''] = 60; + cTable[''] = 61; +// cTable[''] = 62; // i ^ +// cTable[''] = 63; // i pallini + cTable[''] = 64; + cTable[''] = 65; +// cTable[''] = 66; // o ^ +// cTable[''] = 67; // o pallini + cTable[''] = 68; + cTable[''] = 69; +// cTable[''] = 70; // u ^ +// cTable[''] = 71; // u pallini +// cTable[''] = 72; // y pallini + cTable[''] = 73; + cTable[''] = 74; +// cTable[''] = 75; // o barrato +// cTable[''] = 76; // ac + cTable[''] = 77; +// cTable[''] = 78; // ? rovesciato + cTable['?'] = 79; +// cTable[''] = 80; // ! rovesciato + cTable['!'] = 81; +// cTable[''] = 82; // 1/2 +// cTable[''] = 83; // 1/4 + cTable['('] = 84; + cTable[')'] = 85; + cTable[''] = 86; + cTable[''] = 87; +// cTable[''] = 88; // AE + cTable[':'] = 89; + cTable['%'] = 90; + cTable['&'] = 91; + cTable['/'] = 92; + cTable['+'] = 93; + cTable[';'] = 94; + cTable[','] = 95; + cTable['^'] = 96; + cTable['='] = 97; + cTable['_'] = 98; + cTable['*'] = 99; + cTable['.'] = 100; + + for (i = 0; i < 10; i++) + cTable['0'+i] = i+101; + cTable['\''] = 111; + + lTable[' '] = 11; + lTable[''] = lTable['A'] = 19; + lTable['B'] = 15; + lTable['C'] = 14; + lTable['D'] = 13; + lTable['E'] = 14; + lTable['F'] = 13; + lTable['G'] = 16; + lTable['H'] = 15; + lTable['I'] = 5; + lTable['J'] = 8; + lTable['K'] = 15; + lTable['L'] = 13; + lTable['M'] = 17; + lTable['N'] = 15; + lTable[''] = lTable['O'] = 14; + lTable['P'] = 12; + lTable['Q'] = 14; + lTable['R'] = 14; + lTable['S'] = 15; + lTable['T'] = 11; + lTable[''] = lTable['U'] = 12; + lTable['V'] = 12; + lTable['W'] = 16; + lTable['X'] = 12; + lTable['Y'] = 13; + lTable['Z'] = 14; + + lTable['a'] = 11; + lTable['b'] = 9; + lTable['c'] = 9; + lTable['d'] = 10; + lTable['e'] = 9; + lTable['f'] = 8; + lTable['g'] = 9; + lTable['h'] = 10; + lTable['i'] = 5; + lTable['j'] = 6; + lTable['k'] = 12; + lTable['l'] = 6; + lTable['m'] = 14; + lTable['n'] = 10; + lTable['o'] = 11; + lTable['p'] = 11; + lTable['q'] = 9; + lTable['r'] = 9; + lTable['s'] = 9; + lTable['t'] = 6; + lTable['u'] = 9; + lTable['v'] = 10; + lTable['w'] = 14; + lTable['x'] = 9; + lTable['y'] = 10; + lTable['z'] = 9; + + lTable['0'] = 12; + lTable['1'] = 8; + lTable['2'] = 10; + lTable['3'] = 11; + lTable['4'] = 12; + lTable['5'] = 11; + lTable['6'] = 12; + lTable['7'] = 10; + lTable['8'] = 11; + lTable['9'] = 10; + + lTable['/'] = 10; + lTable['^'] = 9; + lTable[','] = 5; + lTable['.'] = 5; + lTable[';'] = 5; + lTable[':'] = 5; + lTable['\''] = 5; + + + + // Polish characters + //AaCcEeLlNnOoSsZzZz + //ス謎戊3剔囀 + + cTable[''] = 112; + cTable[''] = 113; + cTable[''] = 114; + cTable[''] = 115; + cTable[''] = 116; + cTable[''] = 117; + cTable[''] = 118; + cTable[''] = 119; + cTable[''] = 120; + cTable[''] = 121; + cTable[''] = 122; + cTable[''] = 123; + cTable[''] = 124; + cTable[''] = 125; + cTable[''] = 126; + cTable[''] = 127; + cTable[''] = 128; + cTable[''] = 129; + + lTable[''] = 20; + lTable[''] = 12; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 14; + lTable[''] = 11; + lTable[''] = 16; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 11; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 10; + + +#ifdef FONT_RUSSIAN + // Russian Characters + // WARNING: Il russo usa molti dei caratteri ISO-Latin-1 che servono + // per le altre traduzioni. Per compilare Tony in altre lingue, + // commentare via queste definizioni. + + cTable[''] = 130; + cTable[''] = 131; + cTable[''] = 132; + cTable[''] = 133; + cTable[''] = 134; + cTable[''] = 135; + cTable[''] = 136; + cTable[''] = 137; + cTable[''] = 138; + cTable[''] = 139; + cTable[''] = 140; + cTable[''] = 141; + cTable[''] = 142; + cTable[''] = 143; + cTable[''] = 144; + cTable[''] = 145; + cTable[''] = 146; + cTable[''] = 147; + cTable[''] = 148; + cTable[''] = 149; + cTable[''] = 150; + cTable[''] = 151; + cTable[''] = 152; + cTable[''] = 153; + cTable[''] = 154; + cTable[''] = 155; + cTable[''] = 156; + cTable[''] = 157; + cTable[''] = 158; + cTable[''] = 159; + cTable[''] = 160; + cTable[''] = 161; + cTable[''] = 162; + + cTable[''] = 163; + cTable[''] = 164; + cTable[''] = 165; + cTable[''] = 166; + cTable[''] = 167; + cTable[''] = 168; + cTable[''] = 169; + cTable[''] = 170; + cTable[''] = 171; + cTable[''] = 172; + cTable[''] = 173; + cTable[''] = 174; + cTable[''] = 175; + cTable[''] = 176; + cTable[''] = 177; + cTable[''] = 178; + cTable[''] = 179; + cTable[''] = 180; + cTable[''] = 181; + cTable[''] = 182; + cTable[''] = 183; + cTable[''] = 184; + cTable[''] = 185; + cTable[''] = 186; + cTable[''] = 187; + cTable[''] = 188; + cTable[''] = 189; + cTable[''] = 190; + cTable[''] = 191; + cTable[''] = 192; + cTable[''] = 193; + cTable[''] = 194; + cTable[''] = 195; + + lTable[''] = 20; + lTable[''] = 16; + lTable[''] = 16; + lTable[''] = 14; + lTable[''] = 22; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 20; + lTable[''] = 12; + lTable[''] = 16; + lTable[''] = 16; + lTable[''] = 16; + lTable[''] = 22; + lTable[''] = 18; + lTable[''] = 16; + lTable[''] = 15; + lTable[''] = 14; + lTable[''] = 13; + lTable[''] = 15; + lTable[''] = 12; + lTable[''] = 14; + lTable[''] = 15; + lTable[''] = 13; + lTable[''] = 16; + lTable[''] = 14; + lTable[''] = 23; + lTable[''] = 23; + lTable[''] = 10; + lTable[''] = 12; + lTable[''] = 16; + lTable[''] = 12; + lTable[''] = 20; + lTable[''] = 15; + + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 16; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 13; + lTable[''] = 12; + lTable[''] = 13; + lTable[''] = 14; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 10; + lTable[''] = 12; + lTable[''] = 16; + lTable[''] = 11; + lTable[''] = 13; + lTable[''] = 11; + +#endif // FONT_RUSSIAN + +#ifdef FONT_CZECH + + cTable[''] = 196; + cTable[''] = 197; + cTable[''] = 198; + cTable[''] = 199; + cTable[''] = 200; + cTable[''] = 201; + cTable[''] = 202; + cTable[''] = 203; + cTable[''] = 204; + cTable[''] = 205; + cTable[''] = 206; + cTable[''] = 207; + cTable[''] = 208; + cTable[''] = 209; + cTable[''] = 210; + + cTable[''] = 211; + cTable[''] = 212; + cTable[''] = 213; + cTable[''] = 214; + cTable[''] = 215; + cTable[''] = 216; + cTable[''] = 217; + cTable[''] = 218; + cTable[''] = 219; + cTable[''] = 220; + cTable[''] = 221; + cTable[''] = 222; + cTable[''] = 223; + cTable[''] = 224; + cTable[''] = 225; + + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 15; + lTable[''] = 14; + lTable[''] = 20; + lTable[''] = 7; + lTable[''] = 15; + lTable[''] = 20; + lTable[''] = 19; + lTable[''] = 16; + lTable[''] = 15; + lTable[''] = 13; + lTable[''] = 13; + + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 12; + lTable[''] = 6; + lTable[''] = 10; + lTable[''] = 15; + lTable[''] = 12; + lTable[''] = 11; + lTable[''] = 11; + lTable[''] = 10; + lTable[''] = 10; + +#endif // FONT_CZECH + +#ifdef FONT_FRENCH + + cTable[''] = 226; + cTable[''] = 227; + cTable[''] = 228; + cTable[''] = 229; + cTable[''] = 230; + cTable[''] = 231; + cTable[''] = 232; + cTable[''] = 233; + + lTable[''] = 12; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 6; + lTable[''] = 10; + lTable[''] = 10; + lTable[''] = 11; + lTable[''] = 11; + +#endif // FONT_FRENCH + +#ifdef FONT_GERMAN + cTable[''] = 234; + // 'SS' = 235 + + // old chars overrides + cTable[''] = cTable[''] = 55; + cTable[''] = cTable[''] = 67; + cTable[''] = cTable[''] = 71; + + lTable[''] = 11; + +#endif // FONT_GERMAN +} + + + +/***************************************************************************\ +* Metodi di RMFontObj +\****************************************************************************/ + +#define TOUPPER(a) ((a) >='a'&&(a)<='z'?(a)+'A'-'a':(a)) +#define TOLOWER(a) ((a) >='A'&&(a)<='Z'?(a)+'a'-'A':(a)) + +void RMFontObj::SetBothCase(int nChar, int nNext, signed char spiazz) { + l2Table[TOUPPER(nChar)][TOUPPER(nNext)] = spiazz; + l2Table[TOUPPER(nChar)][TOLOWER(nNext)] = spiazz; + l2Table[TOLOWER(nChar)][TOUPPER(nNext)] = spiazz; + l2Table[TOLOWER(nChar)][TOLOWER(nNext)] = spiazz; +} + + +void RMFontObj::Init(void) { + int i; + + //bernie: numero di caratteri nel font (solo maiuscolo) + int nchars = + 85 // base + + 9 // polish + + 33 // russian + + 15 // czech + + 0 // francais (no uppercase chars) + + 1; // deutsch + + + Load(RES_F_OBJ, nchars, 25, 30); + + // Inizializziamo le tabelline del cazzo + lDefault = 26; + hDefault = 30; + Common::fill(&l2Table[0][0], &l2Table[0][0] + (256 * 256), '\0'); + + for (i = 0; i < 256; i++) + { + cTable[i] = -1; + lTable[i] = lDefault; + } + + for (i = 0; i < 26; i++) + { + cTable['A'+i] = i+0; + cTable['a'+i] = i+0; + } + + for (i = 0; i < 10; i++) + cTable['0'+i] = i+26; + + cTable[','] = 36; + cTable[';'] = 37; + cTable['.'] = 38; + cTable[':'] = 39; + cTable['-'] = 40; + cTable['+'] = 41; + cTable['!'] = 42; + // cTable['!'] = 43; Esclamativo alla rovescia + cTable['?'] = 44; + //cTable['?'] = 45; Interrogativo alla rovescia + cTable['/'] = 46; + cTable['('] = 47; + cTable[')'] = 48; + cTable['='] = 49; + cTable['\''] = 50; + cTable['\"'] = 51; + cTable[''] = 52; + cTable['$'] = 53; + cTable['%'] = 54; + cTable['&'] = 55; + cTable['^'] = 56; + cTable['*'] = 57; + cTable['<'] = 58; + cTable[' > '] = 59; + cTable[''] = 60; + cTable[''] = 61; + cTable[''] = 62; + cTable[''] = 63; + //cTable[''] = 64; integrale + cTable[''] = 65; + cTable[''] = 66; + cTable[''] = 67; + cTable[''] = 68; + cTable[''] = 69; + cTable[''] = cTable[''] = 70; + cTable[''] = 71; + cTable[''] = 72; + cTable[''] = 73; + //cTable[' '] = 74; e cerchietto + cTable[''] = 75; + cTable[''] = 76; + //cTable[' '] = 77; i cerchietto + cTable[''] = 78; + cTable[''] = cTable[''] = 79; + //cTable[' '] = 80; o cerchietto + cTable[''] = 81; + cTable[''] = cTable[''] = 82; + //cTable[' '] = 83; u cerchietto + //cTable[' '] = 84; y dieresi + + /* Un po' di lunghezze */ + lTable[' '] = 11; + lTable['.'] = 8; + lTable['-'] = 12; + lTable['\''] = 8; + lTable['0'] = 20; + lTable['1'] = 20; + lTable['2'] = 15; + lTable['3'] = 20; + lTable['4'] = 20; + lTable['5'] = 20; + lTable['6'] = 20; + lTable['7'] = 20; + lTable['8'] = 20; + lTable['9'] = 20; + + + lTable['a'] = lTable['A'] = lTable[''] = lTable[''] = 17; + lTable['b'] = lTable['B'] = 17; + lTable['c'] = lTable['C'] = 19; + lTable['d'] = lTable['D'] = 17; + lTable['e'] = lTable['E'] = 15; + lTable['f'] = lTable['F'] = 17; + lTable['g'] = lTable['G'] = 19; + lTable['i'] = lTable['I'] = 16; + lTable['h'] = lTable['H'] = 17; + lTable['k'] = lTable['K'] = 17; + lTable['l'] = lTable['L'] = 14; + lTable['m'] = lTable['M'] = 19; + lTable['n'] = lTable['N'] = 17; + lTable['o'] = lTable['O'] = lTable[''] = lTable[''] = 19; + lTable['p'] = lTable['P'] = 17; + lTable['q'] = lTable['Q'] = 19; + lTable['r'] = lTable['R'] = 14; + lTable['s'] = lTable['S'] = 13; + lTable['t'] = lTable['T'] = 15; + lTable['u'] = lTable['U'] = lTable[''] = lTable[''] = 15; + lTable['v'] = lTable['V'] = 13; + lTable['x'] = lTable['X'] = 15; + lTable['y'] = lTable['Y'] = 13; + lTable['w'] = lTable['W'] = 19; + lTable['z'] = lTable['Z'] = 20; + lTable[''] = 17; + + /* Casi particolari */ + SetBothCase('C','C',2); + SetBothCase('A','T',-2); + SetBothCase('R','S',2); + SetBothCase('H','I',-2); + SetBothCase('T','S',2); + SetBothCase('O','R',2); + SetBothCase('O','L',2); + SetBothCase('O','G',2); + SetBothCase('Z','A',-1); + SetBothCase('R','R',1); + SetBothCase('R','U',3); + + + // Polish characters + //ス謎戊3剔囀 + //AaCcEeLlNnOoSsZzZz + cTable[''] = cTable[''] = 85; + lTable[''] = lTable[''] = 20; + + cTable[''] = cTable[''] = 86; + lTable[''] = lTable[''] = 22; + + cTable[''] = cTable[''] = 87; + lTable[''] = lTable[''] = 17; + + cTable[''] = cTable[''] = 88; + lTable[''] = lTable[''] = 19; + + cTable[''] = cTable[''] = 89; + lTable[''] = lTable[''] = 17; + + cTable[''] = cTable[''] = 90; + lTable[''] = lTable[''] = 22; + + cTable[''] = cTable[''] = 91; + lTable[''] = lTable[''] = 15; + + cTable[''] = cTable[''] = 92; + lTable[''] = lTable[''] = 21; + + cTable[''] = cTable[''] = 93; + lTable[''] = lTable[''] = 21; + + +#ifdef FONT_RUSSIAN + // Russian Characters + // WARNING: Il russo usa molti dei caratteri ISO-Latin-1 che servono + // per le altre traduzioni. Per compilare Tony in altre lingue, + // commentare via queste definizioni. + + cTable[''] = cTable[''] = 85; + lTable[''] = lTable[''] = 20; + + cTable[''] = cTable[''] =94; + cTable[''] = cTable[''] =95; + cTable[''] = cTable[''] =96; + cTable[''] = cTable[''] =97; + cTable[''] = cTable[''] =98; + cTable[''] = cTable[''] =99; + cTable[''] = cTable[''] =100; + cTable[''] = cTable[''] =101; + cTable[''] = cTable[''] =102; + cTable[''] = cTable[''] =103; + cTable[''] = cTable[''] =104; + cTable[''] = cTable[''] =105; + cTable[''] = cTable[''] =106; + cTable[''] = cTable[''] =107; + cTable[''] = cTable[''] =108; + cTable[''] = cTable[''] =109; + cTable[''] = cTable[''] =110; + cTable[''] = cTable[''] =111; + cTable[''] = cTable[''] =112; + cTable[''] = cTable[''] =113; + cTable[''] = cTable[''] =114; + cTable[''] = cTable[''] =115; + cTable[''] = cTable[''] =116; + cTable[''] = cTable[''] =117; + cTable[''] = cTable[''] =118; + cTable[''] = cTable[''] =119; + cTable[''] = cTable[''] =120; + cTable[''] = cTable[''] =121; + cTable[''] = cTable[''] =122; + cTable[''] = cTable[''] =123; + cTable[''] = cTable[''] =124; + cTable[''] = cTable[''] =125; + cTable[''] = cTable[''] =126; + + + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 17; + lTable[''] = lTable[''] = 16; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 20; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 16; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 15; + lTable[''] = lTable[''] = 22; + lTable[''] = lTable[''] = 15; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 22; + lTable[''] = lTable[''] = 19; + lTable[''] = lTable[''] = 16; + lTable[''] = lTable[''] = 21; + lTable[''] = lTable[''] = 20; + lTable[''] = lTable[''] = 16; + lTable[''] = lTable[''] = 16; + lTable[''] = lTable[''] = 19; + lTable[''] = lTable[''] = 22; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 19; + lTable[''] = lTable[''] = 19; + lTable[''] = lTable[''] = 15; + lTable[''] = lTable[''] = 18; + lTable[''] = lTable[''] = 18; + +#endif // FONT_RUSSIAN + +#ifdef FONT_CZECH + // rep. ceca characters + + cTable[''] = cTable[''] = 127; + cTable[''] = cTable[''] = 128; + cTable[''] = cTable[''] = 129; + cTable[''] = cTable[''] = 130; + cTable[''] = cTable[''] = 131; + cTable[''] = cTable[''] = 132; + cTable[''] = cTable[''] = 133; + cTable[''] = cTable[''] = 134; + cTable[''] = cTable[''] = 135; + cTable[''] = cTable[''] = 136; + cTable[''] = cTable[''] = 137; + cTable[''] = cTable[''] = 138; + cTable[''] = cTable[''] = 139; + cTable[''] = cTable[''] = 140; + cTable[''] = cTable[''] = 141; + + lTable[''] = lTable[''] =17; + lTable[''] = lTable[''] =15; + lTable[''] = lTable[''] =22; + lTable[''] = lTable[''] =18; + lTable[''] = lTable[''] =21; + lTable[''] = lTable[''] =16; + lTable[''] = lTable[''] =18; + lTable[''] = lTable[''] =19; + lTable[''] = lTable[''] =17; + lTable[''] = lTable[''] =23; + lTable[''] = lTable[''] =24; + lTable[''] = lTable[''] =17; + lTable[''] = lTable[''] =22; + lTable[''] = lTable[''] =16; + lTable[''] = lTable[''] =16; + +#endif // FONT_CZECH + +#ifdef FONT_FRENCH + + // traduci le lettere accentate in lettere normali + + cTable[''] = cTable[''] = cTable[''] = 0; // a + lTable[''] = lTable[''] = lTable[''] = 17; + + cTable[''] = cTable[''] = 4; // e + lTable[''] = lTable[''] = 15; + + cTable[''] = cTable[''] = cTable[''] = 8; // i + lTable[''] = lTable[''] = lTable[''] = 16; + + cTable[''] = cTable[''] = cTable[''] = cTable[''] = 14; // o + lTable[''] = lTable[''] = lTable[''] = lTable[''] = 19; + + cTable[''] = cTable[''] = 20; // u + lTable[''] = lTable[''] = 15; + +#endif // FONT_FRENCH + +#ifdef FONT_GERMAN + cTable[''] = 142; + // SS = 143 + + lTable[''] = 24; +#endif // FONT_GERMAN +} + + +/****************************************************************************\ +* Metodi di RMText +\****************************************************************************/ + +RMFontColor *RMText::m_fonts[4] = { NULL, NULL, NULL, NULL }; +OSystem::MutexRef RMText::m_cs; +RMGfxClearTask RMText::m_clear; + +RMText::RMText() { + // Colore di default: bianco + m_r = m_g = m_b = 255; + + // Lunghezza di default + maxLineLength = 350; + + m_bTrasp0 = true; + aHorType = HCENTER; + aVerType = VTOP; + SetPriority(150); +} + +RMText::~RMText() { + +} + +void RMText::SetMaxLineLength(int max) { + maxLineLength = max; +} + +bool RMText::RemoveThis() { + // Qui possiamo fare i controlli sul numero di frame, sul tempo trascorso + // etc. + return true; +} + + +void RMText::WriteText(RMString text, int nFont, int *time) { + // Inizializza i font (una volta sola) + if (m_fonts[0] == NULL) { + m_fonts[0] = new RMFontParla; m_fonts[0]->Init(); + m_fonts[1] = new RMFontObj; m_fonts[1]->Init(); + m_fonts[2] = new RMFontMacc; m_fonts[2]->Init(); + m_fonts[3] = new RMFontCredits; m_fonts[3]->Init(); + } + + g_system->lockMutex(m_cs); + WriteText(text,m_fonts[nFont],time); + g_system->unlockMutex(m_cs); +} + + +void RMText::WriteText(RMString text, RMFontColor *font, int *time) { + RMGfxPrimitive *prim; + char *p, *old_p; + int i, j, x, y; + int len; + int numchar; + int width, height; + char *string; + int numlines; + + // Setta il colore di base + font->SetBaseColor(m_r, m_g, m_b); + + // Si autodistrugge il buffer prima di iniziare + Destroy(); + + // Se la stringa vuota, non fare nulla + if (text == NULL || text[0] == '\0') + return; + + // Divide la frase in linee. In questo ciclo, X contiene la lunghezza massima raggiunta da una linea + // e I il numero delle linee + string=p = text; + i = j = x = 0; + while (*p != '\0') { + j += font->StringLen(*p); + if (j > (((aHorType == HLEFTPAR) && (i > 0)) ? maxLineLength - 25 : maxLineLength)) { + j -= font->StringLen(*p, p[1]); + if (j > x) x = j; + + // Torna indietro al primo spazio utile + // + // BERNIE: nella versione originale le frasi contenenti + // parole che superano la larghezza di una riga causavano + // l'interruzione dell'intera frase. + // Questo workaround e' parziale: la parola troppo lunga + // viene spezzata bruscamente e si perde una lettera. + // Oltre allo spazio e' ammesso il wrap sul carattere '-'. + // + old_p = p; + while (*p != ' ' && *p != '-' && p > string) p--; + + if (p == string) + p = old_p; + + // Controlla se sono tutti spazi fino alla fine + while (*p == ' ' && *p != '\0') p++; + if (*p == '\0') + break; + p--; + i++; + *p = '\0'; + j = 0; + } + p++; + } + + if (j > x) x = j; + + i++; + numlines = i; + + // X=Lunghezza della linea piu' lunga. Controlla se puo' essere puttata a X1 + //x+=font->StringLen(-1)+1; // Meglio esagerare per sicurezza + x += 8; + + // Posizione di partenza per la surface: X1,Y + width = x; + height = (numlines - 1) * font->LetterHeight() + font->m_fontDimy; + + // Crea la surface + Create(width, height); + //AddPrim(new RMGfxPrimitive(&m_clear)); + Common::fill(m_buf, m_buf + width * height * 2, 0); + + p = string; + + y = 0; + numchar = 0; + for (; i > 0; i--) { + // Misura la lunghezza della linea + x = 0; + j = font->StringLen(RMString(p)); + + switch (aHorType) { + case HLEFT: + x = 0; + break; + + case HLEFTPAR: + if (i == numlines) + x=0; + else + x = 25; + break; + + case HCENTER: + x = width / 2 - j / 2; + break; + + case HRIGHT: + x = width - j - 1; + break; + } + + while (*p != '\0') { + if (*p == ' ') { + x += font->StringLen(*p); + p++; + continue; + } + + prim = font->MakeLetterPrimitive(*p, len); + prim->Dst().x1 = x; + prim->Dst().y1 = y; + AddPrim(prim); + + numchar++; + + x += font->StringLen(*p, p[1]); + p++; + } + p++; + y += font->LetterHeight(); + } + + if (time != NULL) + *time = 1000 + numchar * (11 - nCfgTextSpeed) * 14; +} + +void RMText::ClipOnScreen(RMGfxPrimitive *prim) { + // Cerca di non farlo uscire dallo schermo + if (prim->Dst().x1 < 5) prim->Dst().x1 = 5; + if (prim->Dst().y1 < 5) prim->Dst().y1 = 5; + if (prim->Dst().x1+m_dimx > 635) prim->Dst().x1 = 635 - m_dimx; + if (prim->Dst().y1+m_dimy > 475) prim->Dst().y1 = 475 - m_dimy; +} + +void RMText::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + // Allinea orizzontalmente + if (aHorType == HCENTER) + prim->Dst().TopLeft() -= RMPoint(m_dimx / 2, 0); + else if (aHorType == HRIGHT) + prim->Dst().TopLeft() -= RMPoint(m_dimx, 0); + + + // Alinea verticalemente + switch (aVerType) { + case VTOP: + break; + + case VCENTER: + prim->Dst().y1-=m_dimy/2; + break; + + case VBOTTOM: + prim->Dst().y1-=m_dimy; + break; + } + + ClipOnScreen(prim); + + RMGfxWoodyBuffer::Draw(bigBuf,prim); +} + +/****************************************************************************\ +* Metodi di RMTextDialog +\****************************************************************************/ + +RMTextDialog::RMTextDialog() : RMText() { + m_startTime = 0; + dst = RMPoint(0,0); + + m_bSkipStatus = true; + m_bShowed = true; + m_bForceTime = false; + m_bForceNoTime = false; + m_bAlwaysDisplay = false; + m_bNoTab = false; + hCustomSkip = INVALID_HANDLE_VALUE; + hCustomSkip2 = INVALID_HANDLE_VALUE; + m_input = NULL; + + // Crea l'evento di fine displaying + hEndDisplay = CreateEvent(NULL, false, false, NULL); +} + +RMTextDialog::~RMTextDialog() { + CloseHandle(hEndDisplay); +} + +void RMTextDialog::Show(void) { + m_bShowed = true; +} + +void RMTextDialog::Hide(void) { + m_bShowed = false; +} + +void RMTextDialog::WriteText(RMString text, int font, int *time) { + RMText::WriteText(text,font,&m_time); + + if (time != NULL) + *time = m_time; +} + +void RMTextDialog::WriteText(RMString text, RMFontColor *font, int *time) { + RMText::WriteText(text,font,&m_time); + + if (time != NULL) + *time = m_time; +} + + +void RMTextDialog::SetSkipStatus(bool bEnabled) { + m_bSkipStatus=bEnabled; +} + +void RMTextDialog::ForceTime(void) { + m_bForceTime = true; +} + +void RMTextDialog::ForceNoTime(void) { + m_bForceNoTime = true; +} + +void RMTextDialog::SetNoTab(void) { + m_bNoTab = true; +} + +void RMTextDialog::SetForcedTime(uint32 dwTime) { + m_time = dwTime; +} + +void RMTextDialog::SetAlwaysDisplay(void) { + m_bAlwaysDisplay = true; +} + +bool RMTextDialog::RemoveThis(void) { + // Frase NON di background + if (m_bSkipStatus) { + if (!(bCfgDubbing && hCustomSkip2 != INVALID_HANDLE_VALUE)) + if (bCfgTimerizedText) { + if (!m_bForceNoTime) + if (_vm->GetTime() > (uint32)m_time + m_startTime) + return true; + } + + if (!m_bNoTab) + if ((GetAsyncKeyState(Common::KEYCODE_TAB) & 0x8001) == 0x8001) + return true; + + if (!m_bNoTab) + if (m_input) + if (m_input->MouseLeftClicked() || m_input->MouseRightClicked()) + return true; + } + // Frase di background + else { + if (!(bCfgDubbing && hCustomSkip2 != INVALID_HANDLE_VALUE)) + if (!m_bForceNoTime) + if (_vm->GetTime() > (uint32)m_time + m_startTime) + return true; + } + + // Se il tempo forzato + if (m_bForceTime) + if (_vm->GetTime() > (uint32)m_time + m_startTime) + return true; + + if (hCustomSkip != INVALID_HANDLE_VALUE) + if (WaitForSingleObject(hCustomSkip, 0) == WAIT_OBJECT_0) + return true; + + if (bCfgDubbing && hCustomSkip2 != INVALID_HANDLE_VALUE) + if (WaitForSingleObject(hCustomSkip2,0) == WAIT_OBJECT_0) + return true; + + return false; +} + +void RMTextDialog::Unregister(void) { + RMGfxTask::Unregister(); + assert(m_nInList == 0); + SetEvent(hEndDisplay); +} + +void RMTextDialog::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + if (m_startTime == 0) + m_startTime = _vm->GetTime(); + + if (m_bShowed) { + if (bCfgSottotitoli || m_bAlwaysDisplay) { + prim->Dst().TopLeft() = dst; + RMText::Draw(bigBuf, prim); + } + } +} + +void RMTextDialog::SetCustomSkipHandle(HANDLE hCustom) { + hCustomSkip = hCustom; +} + +void RMTextDialog::SetCustomSkipHandle2(HANDLE hCustom) { + hCustomSkip2 = hCustom; +} + +void RMTextDialog::WaitForEndDisplay(void) { + WaitForSingleObject(hEndDisplay, INFINITE); +} + +void RMTextDialog::SetInput(RMInput *input) { + m_input = input; +} + +/****************************************************************************\ +* Metodi di RMTextDialogScrolling +\****************************************************************************/ + +RMTextDialogScrolling::RMTextDialogScrolling() { + curLoc = NULL; +} + +RMTextDialogScrolling::RMTextDialogScrolling(RMLocation *loc) { + curLoc = loc; + startScroll = loc->ScrollPosition(); +} + +RMTextDialogScrolling::~RMTextDialogScrolling() { +} + +void RMTextDialogScrolling::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + RMPoint curDst; + + curDst = dst; + + if (curLoc != NULL) + dst -= curLoc->ScrollPosition() - startScroll; + + RMTextDialog::Draw(bigBuf, prim); + + dst = curDst; +} + +void RMTextDialogScrolling::ClipOnScreen(RMGfxPrimitive *prim) { + // Non dobbiamo fare nulla! +} + + +/****************************************************************************\ +* Metodi di RMTextItemName +\****************************************************************************/ + +RMTextItemName::RMTextItemName() : RMText() { + m_item = NULL; + SetPriority(220); +} + +RMTextItemName::~RMTextItemName() { + +} + +void RMTextItemName::DoFrame(RMGfxTargetBuffer& bigBuf, RMLocation &loc, RMPointer &ptr, RMInventory &inv) { + RMString itemName; + RMItem *lastItem = m_item; + + // Si aggiunge alla lista se c'e' bisogno + if (!m_nInList) + bigBuf.AddPrim(new RMGfxPrimitive(this)); + + // Aggiorna le coordinate di scrolling + m_curscroll = loc.ScrollPosition(); + + // Controlla se siamo sopra l'inventario + if (inv.ItemInFocus(m_mpos)) + m_item = inv.WhichItemIsIn(m_mpos); + else + m_item = loc.WhichItemIsIn(m_mpos); + + itemName = ""; + + // Si fa dare il nuovo nome + if (m_item != NULL) + m_item->GetName(itemName); + + // Se lo scrive + WriteText(itemName, 1); + + // Se e' diverso dal precedente, e' il caso di aggiornare anche il puntatore con la WhichPointer + if (lastItem != m_item) + { + if (m_item == NULL) + ptr.SetSpecialPointer(RMPointer::PTR_NONE); + else { + HANDLE hThread = mpalQueryDoAction(20, m_item->MpalCode(), 0); + if (hThread == INVALID_HANDLE_VALUE) + ptr.SetSpecialPointer(RMPointer::PTR_NONE); + else + WaitForSingleObject(hThread,INFINITE); + } + } +} + + +void RMTextItemName::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + // Se non c'e' testo, e' inutile continuare + if (m_buf == NULL) + return; + + // Setta come coordinate destinazione quelle del mouse + prim->Dst().TopLeft() = m_mpos-RMPoint(0, 30); + + RMText::Draw(bigBuf,prim); +} + + +/****************************************************************************\ +* Metodi di RMDialogChoice +\****************************************************************************/ + +RMDialogChoice::RMDialogChoice() { + RMResRaw dlg1(RES_I_DLGTEXT); + RMResRaw dlg2(RES_I_DLGTEXTLINE); + RMRes dlgpal(RES_I_DLGTEXTPAL); + + DlgText.Init(dlg1, dlg1.Width(), dlg1.Height()); + DlgTextLine.Init(dlg2, dlg2.Width(), dlg2.Height()); + + DlgText.LoadPaletteWA(dlgpal); + DlgTextLine.LoadPaletteWA(dlgpal); + + hUnreg=CreateEvent(NULL, false, false, NULL); + bRemoveFromOT = false; +} + +RMDialogChoice::~RMDialogChoice() { + CloseHandle(hUnreg); +} + +void RMDialogChoice::Unregister(void) { + RMGfxWoodyBuffer::Unregister(); + assert(!m_nInList); + PulseEvent(hUnreg); + + bRemoveFromOT = false; +} + +void RMDialogChoice::Init(void) +{ + m_numChoices = 0; + m_drawedStrings = NULL; + m_ptDrawStrings = NULL; + m_curSelection = -1; + + Create(640, 477); + SetPriority(140); +} + + +void RMDialogChoice::Close(void) { + if (m_drawedStrings != NULL) { + delete[] m_drawedStrings; + m_drawedStrings = NULL; + } + + if (m_ptDrawStrings != NULL) { + delete[] m_ptDrawStrings; + m_ptDrawStrings = NULL; + } + + Destroy(); +} + +void RMDialogChoice::SetNumChoices(int num) { + int i; + + m_numChoices = num; + m_curAdded = 0; + + // Alloca lo spazio per le stringhe disegnate + m_drawedStrings = new RMText[num]; + m_ptDrawStrings = new RMPoint[num]; + + // Le inizializza + for (i = 0; i < m_numChoices; i++) { + m_drawedStrings[i].SetColor(0, 255, 0); + m_drawedStrings[i].SetAlignType(RMText::HLEFTPAR, RMText::VTOP); + m_drawedStrings[i].SetMaxLineLength(600); + m_drawedStrings[i].SetPriority(10); + } +} + +void RMDialogChoice::AddChoice(RMString string) { + // Si disegna la stringa + assert(m_curAdded < m_numChoices); + m_drawedStrings[m_curAdded++].WriteText(string,0); +} + +void RMDialogChoice::Prepare(void) { + int i; + RMPoint ptPos; + + AddPrim(new RMGfxPrimitive(&DlgText,RMPoint(0,0))); + AddPrim(new RMGfxPrimitive(&DlgTextLine,RMPoint(0,155))); + AddPrim(new RMGfxPrimitive(&DlgTextLine,RMPoint(0,155+83))); + AddPrim(new RMGfxPrimitive(&DlgTextLine,RMPoint(0,155+83+83))); + AddPrim(new RMGfxPrimitive(&DlgTextLine,RMPoint(0,155+83+83+83))); + + ptPos.Set(20,90); + + for (i = 0; i < m_numChoices; i++) { + AddPrim(new RMGfxPrimitive(&m_drawedStrings[i], ptPos)); + m_ptDrawStrings[i] = ptPos; + ptPos.Offset(0,m_drawedStrings[i].Dimy() + 15); + } + + DrawOT(); + ClearOT(); + + m_ptDrawPos.Set(0,480-ptPos.y); +} + +void RMDialogChoice::SetSelected(int pos) { + //uint16 * buf = (uint16 *)m_buf; + RMGfxBox box; + RMRect rc; + + if (pos == m_curSelection) + return; + + box.SetPriority(5); + + if (m_curSelection != -1) { + box.SetColor(0xCC, 0xCC, 0xFF); + rc.TopLeft()=RMPoint(18, m_ptDrawStrings[m_curSelection].y); + rc.BottomRight() = rc.TopLeft() + RMPoint(597, m_drawedStrings[m_curSelection].Dimy()); + AddPrim(new RMGfxPrimitive(&box, rc)); + + AddPrim(new RMGfxPrimitive(&m_drawedStrings[m_curSelection], m_ptDrawStrings[m_curSelection])); + DrawOT(); + ClearOT(); + } + + if (pos != -1) { + box.SetColor(100, 100, 100); + rc.TopLeft()=RMPoint(18, m_ptDrawStrings[pos].y); + rc.BottomRight() = rc.TopLeft()+RMPoint(597, m_drawedStrings[pos].Dimy()); + AddPrim(new RMGfxPrimitive(&box, rc)); + AddPrim(new RMGfxPrimitive(&m_drawedStrings[pos], m_ptDrawStrings[pos])); + } + + DrawOT(); + ClearOT(); + + m_curSelection = pos; +} + +void RMDialogChoice::Show(RMGfxTargetBuffer *bigBuf) { + Prepare(); + m_bShow = false; + + if (!m_nInList && bigBuf != NULL) + bigBuf->AddPrim(new RMGfxPrimitive(this)); + + if (0) { + m_bShow = true; + } else { + RMPoint destpt; + int deltay; + int starttime = _vm->GetTime(); + int elaps; + + deltay=480 - m_ptDrawPos.y; + destpt = m_ptDrawPos; + m_ptDrawPos.Set(0, 480); + + if (!m_nInList && bigBuf != NULL) + bigBuf->AddPrim(new RMGfxPrimitive(this)); + m_bShow = true; + + elaps = 0; + while (elaps < 700) { + MainWaitFrame(); + MainFreeze(); + elaps = _vm->GetTime() - starttime; + m_ptDrawPos.y = 480 - ((deltay * 100) / 700 * elaps) / 100; + MainUnfreeze(); + } + + m_ptDrawPos.y = destpt.y; + } +} + +void RMDialogChoice::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + if (m_bShow == false) + return; + + prim->SetDst(m_ptDrawPos); + RMGfxSourceBuffer16::Draw(bigBuf, prim); +} + + +void RMDialogChoice::Hide(void) { + if (1) { + int deltay; + int starttime = _vm->GetTime(); + int elaps; + + deltay=480 - m_ptDrawPos.y; + elaps = 0; + while (elaps < 700) { + MainWaitFrame(); + MainFreeze(); + elaps=_vm->GetTime()-starttime; + m_ptDrawPos.y=480-((deltay*100)/700*(700-elaps))/100; + MainUnfreeze(); + } + } + + m_bShow = false; + bRemoveFromOT = true; + WaitForSingleObject(hUnreg, INFINITE); +} + + +bool RMDialogChoice::RemoveThis(void) { + return bRemoveFromOT; +} + +void RMDialogChoice::DoFrame(RMPoint ptMousePos) { + int i; + + if (ptMousePos.y > m_ptDrawPos.y) { + for (i = 0; i < m_numChoices; i++) { + if ((ptMousePos.y >= m_ptDrawPos.y+m_ptDrawStrings[i].y) && (ptMousePos.y < m_ptDrawPos.y+m_ptDrawStrings[i].y+m_drawedStrings[i].Dimy())) { + SetSelected(i); + break; + } + } + + if (i == m_numChoices) + SetSelected(-1); + } +} + +int RMDialogChoice::GetSelection(void) { + return m_curSelection; +} + +} // End of namespace Tony diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp index 83c48bb9385c..141b99371410 100644 --- a/engines/tony/loc.cpp +++ b/engines/tony/loc.cpp @@ -45,14 +45,1615 @@ * * **************************************************************************/ -#include "tony/loc.h" -#include "tony/utils.h" -#include "tony/mpal/lzo.h" +#include "common/scummsys.h" #include "tony/mpal/mpalutils.h" +#include "tony/adv.h" +#include "tony/loc.h" +#include "tony/tony.h" + +namespace Tony { + +using namespace ::Tony::MPAL; + +static char rcsid[] = "$Id: $"; + +extern bool bSkipSfxNoLoop; + + +/****************************************************************************\ +* Metodi di RMPalette +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMPalette& pal); +* +* Description: Operatore di estrazione di palette da data stream +* +* Input: RMDataStream &ds Data stream +* RMPalette& pal Palette di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMPalette &pal) { + ds.Read(pal.m_data,1024); + return ds; +} + +/****************************************************************************\ +* Metodi di RMSlot +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMSlot& slot) +* +* Description: Operatore per estrarre uno slot di un pattern da un data +* stream +* +* Input: RMDataStream &ds Data stream +* RMSlot& slot Slot di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMPattern::RMSlot &slot) { + slot.ReadFromStream(ds); + return ds; +} + + +void RMPattern::RMSlot::ReadFromStream(RMDataStream &ds, bool bLOX) { + byte type; + + // Type + ds >> type; + m_type = (RMPattern::RMSlotType)type; + + // Dati + ds >> m_data; + + // Posizione + ds >> m_pos; + + // Flag generica + ds >> m_flag; +} + + +/****************************************************************************\ +* Metodi di RMPattern +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMPattern& pat) +* +* Description: Operatore per estrarre un pattern da un data stream +* +* Input: RMDataStream &ds Data stream +* RMPattern& pat Pattern di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMPattern &pat) { + pat.ReadFromStream(ds); + return ds; +} + +void RMPattern::ReadFromStream(RMDataStream &ds, bool bLOX) { + int i; + + // Nome del pattern + if (!bLOX) + ds >> m_name; + + // Velocita' + ds >> m_speed; + + // Posizione + ds >> m_pos; + + // Flag di loop del pattern + ds >> m_bLoop; + + // Numero di slot + ds >> m_nSlots; + + // Creazione e lettura degli slot + m_slots = new RMSlot[m_nSlots]; + + for (i = 0; i < m_nSlots && !ds.IsError(); i++) { + if (bLOX) + m_slots[i].ReadFromStream(ds, true); + else + m_slots[i].ReadFromStream(ds, false); + } +} + +void RMPattern::UpdateCoord(void) { + m_curPos = m_pos + m_slots[m_nCurSlot].Pos(); +} + +void RMPattern::StopSfx(RMSfx *sfx) { + for (int i = 0; i < m_nSlots; i++) { + if (m_slots[i].m_type == SOUND) { + if (sfx[m_slots[i].m_data].m_name[0] == '_') + sfx[m_slots[i].m_data].Stop(); + else if (bSkipSfxNoLoop) + sfx[m_slots[i].m_data].Stop(); + } + } +} + +int RMPattern::Init(RMSfx *sfx, bool bPlayP0, byte *bFlag) { + int i; + + // Prendiamo il tempo corrente + m_nStartTime = _vm->GetTime(); + m_nCurSlot = 0; + + // Cerca il primo frame nel pattern + i = 0; + while (m_slots[i].m_type != SPRITE) { + assert(i + 1 < m_nSlots); + i++; + } + + m_nCurSlot = i; + m_nCurSprite = m_slots[i].m_data; + if (bFlag) + *bFlag = m_slots[i].m_flag; + + // Calcola le coordinate correnti + UpdateCoord(); + + // Controlla per il sonoro: + // Se sta alla slot 0, lo playa + // Se speed = 0, deve suonare solo se va in loop '_', oppure se specificato dal parametro + // Se speed! = 0, suona solo quelli in loop + for (i = 0;i < m_nSlots; i++) { + if (m_slots[i].m_type == SOUND) { + if (i == 0) + { + if (sfx[m_slots[i].m_data].m_name[0]=='_') + { + sfx[m_slots[i].m_data].SetVolume(m_slots[i].Pos().x); + sfx[m_slots[i].m_data].Play(true); + } + else + { + sfx[m_slots[i].m_data].SetVolume(m_slots[i].Pos().x); + sfx[m_slots[i].m_data].Play(); + } + } + else if (m_speed == 0) { + if (bPlayP0) { + sfx[m_slots[i].m_data].SetVolume(m_slots[i].Pos().x); + sfx[m_slots[i].m_data].Play(); + } else if (sfx[m_slots[i].m_data].m_name[0] == '_') { + sfx[m_slots[i].m_data].SetVolume(m_slots[i].Pos().x); + sfx[m_slots[i].m_data].Play(true); + } + } else { + if (m_bLoop && sfx[m_slots[i].m_data].m_name[0] == '_') { + sfx[m_slots[i].m_data].SetVolume(m_slots[i].Pos().x); + sfx[m_slots[i].m_data].Play(true); + } + } + } + } + + return m_nCurSprite; +} + +int RMPattern::Update(HANDLE hEndPattern, byte &bFlag, RMSfx *sfx) { + int CurTime = _vm->GetTime(); + + // Se la speed e' 0, il pattern non avanza mai + if (m_speed == 0) { + PulseEvent(hEndPattern); + bFlag=m_slots[m_nCurSlot].m_flag; + return m_nCurSprite; + } + + // E' arrivato il momento di cambiare slot? + while (m_nStartTime + m_speed <= (uint32)CurTime) { + m_nStartTime += m_speed; + if (m_slots[m_nCurSlot].m_type == SPRITE) + m_nCurSlot++; + if (m_nCurSlot == m_nSlots) { + m_nCurSlot = 0; + bFlag = m_slots[m_nCurSlot].m_flag; + PulseEvent(hEndPattern); + + // @@@ Se non c'e' loop avverte che il pattern e' finito + // Se non c'e' loop rimane sull'ultimo frame + if (!m_bLoop) { + m_nCurSlot = m_nSlots - 1; + bFlag = m_slots[m_nCurSlot].m_flag; + return m_nCurSprite; + } + } + + for (;;) { + switch (m_slots[m_nCurSlot].m_type) { + case SPRITE: + // Legge il prossimo sprite + m_nCurSprite = m_slots[m_nCurSlot].m_data; + + // Aggiorna le coordinate babbo+figlio + UpdateCoord(); + break; + + case SOUND: + if (sfx != NULL) { + sfx[m_slots[m_nCurSlot].m_data].SetVolume(m_slots[m_nCurSlot].Pos().x); + + if (sfx[m_slots[m_nCurSlot].m_data].m_name[0] != '_') + sfx[m_slots[m_nCurSlot].m_data].Play(false); + else + sfx[m_slots[m_nCurSlot].m_data].Play(true); + } + break; + + case COMMAND: + assert(0); + break; + + default: + assert(0); + break; + } + + if (m_slots[m_nCurSlot].m_type == SPRITE) + break; + m_nCurSlot++; + } + } + + // Ritorna lo sprite corrente + bFlag=m_slots[m_nCurSlot].m_flag; + return m_nCurSprite; +} + +RMPattern::RMPattern() { + m_slots = NULL; +} + +RMPattern::~RMPattern() { + if (m_slots != NULL) + { + delete[] m_slots; + m_slots = NULL; + } +} + + + + +/****************************************************************************\ +* Metodi di RMSprite +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMSprite& sprite) +* +* Description: Operatore per estrarre uno sprite da un data stream +* +* Input: RMDataStream &ds Data stream +* RMItem &item Sprite di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMSprite &sprite) { + sprite.ReadFromStream(ds); + return ds; +} + +void RMSprite::Init(RMGfxSourceBuffer *buf) { + m_buf = buf; +} + +void RMSprite::LOXGetSizeFromStream(RMDataStream &ds, int *dimx, int *dimy) { + int pos = ds.Pos(); + + ds >> *dimx >> *dimy; + + ds.Seek(pos, ds.START); +} + +void RMSprite::GetSizeFromStream(RMDataStream &ds, int *dimx, int *dimy) { + int pos = ds.Pos(); + + ds >> m_name; + ds >> *dimx >> *dimy; + + ds.Seek(pos, ds.START); +} + +void RMSprite::ReadFromStream(RMDataStream &ds, bool bLOX) { + int dimx,dimy; + + // Nome dello sprite + if (!bLOX) + ds >> m_name; + + // Dimensioni + ds >> dimx >> dimy; + + // Bouding box + ds >> m_rcBox; + + // Spazio inutilizzato + if (!bLOX) + ds+=32; + + // Crezione del buffer e lettura + m_buf->Init(ds, dimx,dimy); +} + +void RMSprite::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + m_buf->Draw(bigBuf, prim); +} + +void RMSprite::SetPalette(byte *buf) { + ((RMGfxSourceBufferPal*)m_buf)->LoadPalette(buf); +} + +RMSprite::RMSprite() { + m_buf= NULL; +} + +RMSprite::~RMSprite() { + if (m_buf) { + delete m_buf; + m_buf = NULL; + } +} + + +/****************************************************************************\ +* Metodi di RMSfx +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMSfx &sfx) +* +* Description: Operatore per estrarre uno sfx da un data stream +* +* Input: RMDataStream &ds Data stream +* RMSfx &sfx Sfx di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMSfx &sfx) { + sfx.ReadFromStream(ds); + return ds; +} + +void RMSfx::ReadFromStream(RMDataStream &ds, bool bLOX) { + char id[4]; + int size; + byte *raw; + + // Nome dello sfx + ds >> m_name; + + ds >> size; + + // Carica l'effetto sonoro dal buffer + ds.Read(id,4); + + // Controlla che sia un riff + assert(id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F'); + + // Legge la dimensione + ds >> size; + + // Carica il wav + raw = new byte[size]; + ds.Read(raw, size); + + // Crea l'effetto sonoro + m_fx = _vm->CreateSFX(raw); + m_fx->SetLoop(false); + + // Cancella il buffer che non serve pi a nessuno + delete[] raw; +} + +RMSfx::RMSfx() { + m_fx = NULL; + m_bPlayingLoop = false; +} + +RMSfx::~RMSfx() { + if (m_fx) { + m_fx->Release(); + m_fx = NULL; + } +} + +void RMSfx::Play(bool bLoop) { + if (m_fx && !m_bPlayingLoop) { + m_fx->SetLoop(bLoop); + m_fx->Play(); + + if (bLoop) + m_bPlayingLoop=true; + } +} + +void RMSfx::SetVolume(int vol) { + if (m_fx) { + m_fx->SetVolume(vol); + } +} + +void RMSfx::Pause(bool bPause) { + if (m_fx) { + m_fx->Pause(bPause); + } +} + +void RMSfx::Stop(void) { + if (m_fx) { + m_fx->Stop(); + m_bPlayingLoop = false; + } +} + + + +/****************************************************************************\ +* Metodi di RMItem +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: friend RMDataStream &operator>>(RMDataStream &ds, +* RMItem &item) +* +* Description: Operatore per estrarre un item da un data stream +* +* Input: RMDataStream &ds Data stream +* RMItem &item Item di destinazione +* +* Return: Reference allo stream +* +\****************************************************************************/ + +RMDataStream &operator>>(RMDataStream &ds, RMItem &item) { + item.ReadFromStream(ds); + return ds; +} + + +RMGfxSourceBuffer *RMItem::NewItemSpriteBuffer(int dimx, int dimy, bool bPreRLE) { + if (m_cm == CM_256) { + RMGfxSourceBuffer8RLE *spr; + + if (m_FX == 2) { // AB + spr = new RMGfxSourceBuffer8RLEWordAB; + } else if (m_FX == 1) { // OMBRA+AA + if (dimx == -1 || dimx > 255) + spr = new RMGfxSourceBuffer8RLEWordAA; + else + spr = new RMGfxSourceBuffer8RLEByteAA; + + spr->SetAlphaBlendColor(m_FXparm); + if (bPreRLE) + spr->SetAlreadyCompressed(); + } else { + if (dimx == -1 || dimx > 255) + spr = new RMGfxSourceBuffer8RLEWord; + else + spr = new RMGfxSourceBuffer8RLEByte; + + if (bPreRLE) + spr->SetAlreadyCompressed(); + } + + return spr; + } else + return new RMGfxSourceBuffer16; +} + +bool RMItem::IsIn(RMPoint pt, int *size) { + RMRect rc; + + if (!m_bIsActive) + return false; + + // Cerca il rettangolo giusto da usare, che quello dello sprite se ce l'ha, altrimenti + // quello generico dell'oggeto + if (m_nCurPattern != 0 && !m_sprites[m_nCurSprite].m_rcBox.IsEmpty()) + rc=m_sprites[m_nCurSprite].m_rcBox + CalculatePos(); + else if (!m_rcBox.IsEmpty()) + rc = m_rcBox; + // Se non ha box, esce subito + else + return false; + + if (size != NULL) + *size = rc.Size(); + + return rc.PtInRect(pt + m_curScroll); +} + + +void RMItem::ReadFromStream(RMDataStream &ds, bool bLOX) { + int i, dimx, dimy; + byte cm; + + // Codice mpal + ds >> m_mpalCode; + + // Nome dell'oggetto + ds >> m_name; + + // Z (signed) + ds >> m_z; + + // Posizione nonno + ds >> m_pos; + + // Hotspot + ds >> m_hot; + + // Bounding box + ds >> m_rcBox; + + // Numero sprite, effetti sonori e pattern + ds >> m_nSprites >> m_nSfx >> m_nPatterns; + + // Color mode + ds >> cm; m_cm=(RMColorMode)cm; + + // Flag di presenza della palette differnziata + ds >> m_bPal; + + if (m_cm == CM_256) { + // Se c'e' la palette, leggiamola + if (m_bPal) + ds >> m_pal; + } + + // Dati MPAL + if (!bLOX) + ds += 20; + + ds >> m_FX; + ds >> m_FXparm; + + if (!bLOX) + ds += 106; + + // Creazione delle classi + if (m_nSprites > 0) + m_sprites = new RMSprite[m_nSprites]; + if (m_nSfx > 0) + m_sfx = new RMSfx[m_nSfx]; + m_patterns = new RMPattern[m_nPatterns+1]; + + // Lettura delle classi + if (!ds.IsError()) + for (i = 0; i < m_nSprites && !ds.IsError(); i++) { + // Carica lo sprite + if (bLOX) { + m_sprites[i].LOXGetSizeFromStream(ds, &dimx, &dimy); + m_sprites[i].Init(NewItemSpriteBuffer(dimx, dimy, true)); + m_sprites[i].ReadFromStream(ds, true); + } else { + m_sprites[i].GetSizeFromStream(ds, &dimx, &dimy); + m_sprites[i].Init(NewItemSpriteBuffer(dimx, dimy, false)); + m_sprites[i].ReadFromStream(ds, false); + } + + if (m_cm == CM_256 && m_bPal) + m_sprites[i].SetPalette(m_pal.m_data); + } + + if (!ds.IsError()) + for (i = 0;i < m_nSfx && !ds.IsError(); i++) { + if (bLOX) + m_sfx[i].ReadFromStream(ds, true); + else + m_sfx[i].ReadFromStream(ds, false); + } + + // Leggiamo i pattern a partire dal pattern 1 + if (!ds.IsError()) + for (i = 1;i <= m_nPatterns && !ds.IsError(); i++) { + if (bLOX) + m_patterns[i].ReadFromStream(ds, true); + else + m_patterns[i].ReadFromStream(ds, false); + } + + // Inizializza il curpattern + if (m_bInitCurPattern) + SetPattern(mpalQueryItemPattern(m_mpalCode)); + + // Inizializza lo stato di attivazione + m_bIsActive=mpalQueryItemIsActive(m_mpalCode); +} + + +RMGfxPrimitive *RMItem::NewItemPrimitive() { + return new RMGfxPrimitive(this); +} + +void RMItem::SetScrollPosition(RMPoint scroll) { + m_curScroll = scroll; +} + +bool RMItem::DoFrame(RMGfxTargetBuffer *bigBuf, bool bAddToList) { + int oldSprite = m_nCurSprite; + + // Pattern 0 = Non disegnare nulla! + if (m_nCurPattern == 0) + return false; + + // Facciamo un update del pattern, che ci ritorna anche il frame corrente + if (m_nCurPattern != 0) + m_nCurSprite=m_patterns[m_nCurPattern].Update(m_hEndPattern,m_bCurFlag, m_sfx); + + // Se la funzione ha ritornato -1, vuol dire che il pattern e' finito + if (m_nCurSprite == -1) { + // Mettiamo il pattern 0, e usciamo. La classe si auto-deregistrera' della OT list + m_nCurPattern = 0; + return false; + } + + // Se non siamo in OT list, mettiamoci + if (!m_nInList && bAddToList) + bigBuf->AddPrim(NewItemPrimitive()); + + return oldSprite != m_nCurSprite; +} + +RMPoint RMItem::CalculatePos(void) { + return m_pos + m_patterns[m_nCurPattern].Pos(); +} + +void RMItem::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + // Se CurSprite == -1, allora e' finito il pattern + if (m_nCurSprite == -1) + return; + + // Settiamo la flag + prim->SetFlag(m_bCurFlag); + + // Offset inverso per lo scrolling + prim->Dst().Offset(-m_curScroll); + + // Dobbiamo sparaflashare le coordinate dell'item dentro la primitiva. + // Si calcola nonno+(babbo+figlio) + prim->Dst().Offset(CalculatePos()); + + // No stretching, please + prim->SetStrecth(false); + + // Ora la passiamo alla routine di drawing generica per surface + m_sprites[m_nCurSprite].Draw(bigBuf, prim); +} + + +bool RMItem::RemoveThis() { + // Rimuove dalla OT list se il frame corrente e' -1 (pattern finito) + return (m_nCurSprite == -1); +} + + +void RMItem::SetStatus(int nStatus) { + m_bIsActive = (nStatus>0); +} + +void RMItem::SetPattern(int nPattern, bool bPlayP0) { + int i; + + assert(nPattern >= 0 && nPattern <= m_nPatterns); + + if (m_sfx) + if (m_nCurPattern>0) + m_patterns[m_nCurPattern].StopSfx(m_sfx); + + // Si ricorda il pattern corrente + m_nCurPattern = nPattern; + + // Inizia il pattern per cominciare l'animazione + if (m_nCurPattern != 0) + m_nCurSprite = m_patterns[m_nCurPattern].Init(m_sfx, bPlayP0, &m_bCurFlag); + else { + m_nCurSprite = -1; + + // Cerca l'effetto sonoro per il pattern 0 + if (bPlayP0) + for (i = 0;i < m_nSfx; i++) + if (strcmp(m_sfx[i].m_name, "p0") == 0) + m_sfx[i].Play(); + } +} + + +bool RMItem::GetName(RMString& name) +{ + char buf[256]; + + mpalQueryItemName(m_mpalCode, buf); + name = buf; + if (buf[0] == '\0') + return false; + return true; +} + + +void RMItem::Unload(void) { + if (m_patterns != NULL) + { + delete[] m_patterns; + m_patterns = NULL; + } + + if (m_sprites != NULL) { + delete[] m_sprites; + m_sprites = NULL; + } + + if (m_sfx != NULL) { + delete[] m_sfx; + m_sfx = NULL; + } +} + +RMItem::RMItem() { + m_bCurFlag = 0; + m_patterns = NULL; + m_sprites = NULL; + m_sfx= NULL; + m_curScroll.Set(0, 0); + m_bInitCurPattern=true; + m_nCurPattern = 0; + + m_hEndPattern = CreateEvent(NULL, false, false, NULL); +} + +RMItem::~RMItem() { + Unload(); + CloseHandle(m_hEndPattern); +} + +void RMItem::WaitForEndPattern(HANDLE hCustomSkip) { + if (m_nCurPattern != 0) { + if (hCustomSkip == INVALID_HANDLE_VALUE) + WaitForSingleObject(m_hEndPattern,INFINITE); + else { + HANDLE h[2]; + + h[0] = hCustomSkip; + h[1] = m_hEndPattern; + WaitForMultipleObjects(2, h, false, INFINITE); + } + } +} + +void RMItem::ChangeHotspot(RMPoint pt) { + m_hot = pt; +} + +void RMItem::PlaySfx(int nSfx) { + if (nSfx < m_nSfx) + m_sfx[nSfx].Play(); +} + +void RMItem::PauseSound(bool bPause) { + int i; + + for (i = 0; i < m_nSfx; i++) + m_sfx[i].Pause(bPause); +} + + + +/****************************************************************************\ +* Metodi di RMWipe +\****************************************************************************/ + + +RMWipe::RMWipe() { + m_hUnregistered=CreateEvent(NULL,false,false,NULL); + m_hEndOfFade=CreateEvent(NULL,false,false,NULL); +} + +RMWipe::~RMWipe() { + CloseHandle(m_hUnregistered); + CloseHandle(m_hEndOfFade); +} + +int RMWipe::Priority(void) { + return 200; +} + +void RMWipe::Unregister(void) { + RMGfxTask::Unregister(); + assert(m_nInList == 0); + SetEvent(m_hUnregistered); +} + +bool RMWipe::RemoveThis(void) { + return m_bUnregister; +} + +void RMWipe::WaitForFadeEnd(void) { + WaitForSingleObject(m_hEndOfFade, INFINITE); + m_bEndFade = true; + m_bFading = false; + MainWaitFrame(); + MainWaitFrame(); +} + +void RMWipe::CloseFade(void) { +// m_bUnregister=true; +// WaitForSingleObject(m_hUnregistered,INFINITE); + m_wip0r.Unload(); +} + +void RMWipe::InitFade(int type) { + // Attiva il fade + m_bUnregister = false; + m_bEndFade = false; + + m_nFadeStep = 0; + + m_bMustRegister = true; + + RMRes res(RES_W_CERCHIO); + RMDataStream ds; + + ds.OpenBuffer(res); + ds >> m_wip0r; + ds.Close(); + + m_wip0r.SetPattern(1); + + m_bFading = true; +} + +void RMWipe::DoFrame(RMGfxTargetBuffer &bigBuf) { + if (m_bMustRegister) { + bigBuf.AddPrim(new RMGfxPrimitive(this)); + m_bMustRegister = false; + } + + if (m_bFading) + { + m_wip0r.DoFrame(&bigBuf, false); + + m_nFadeStep++; + + if (m_nFadeStep == 10) { + SetEvent(m_hEndOfFade); + } + } +} + +void RMWipe::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + if (m_bFading) { + m_wip0r.Draw(bigBuf, prim); + } + + if (m_bEndFade) + Common::fill((byte *)bigBuf, (byte *)bigBuf + bigBuf.Dimx() * bigBuf.Dimy() * 2, 0x0); +} + + + +/****************************************************************************\ +* Metodi di RMCharacter +\****************************************************************************/ + +/***************************************************************************/ +/* Cerca il percorso minimo tra due nodi del grafo di connessione dei BOX */ +/* Restituisce il percorso lungo pathlenght nel vettore path[] */ +/***************************************************************************/ + +short RMCharacter::FindPath(short source, short destination) { + // FIXME: Refactor + static RMBox BOX[MAXBOXES]; // Matrice di Adjacenza + static short COSTO[MAXBOXES]; // Costi per Nodo + static short VALIDO[MAXBOXES]; // 0:non valido 1:valido 2:saturo + static short NEXT[MAXBOXES]; // Prossimo Nodo + short i, j, k, costominimo, fine, errore = 0; + RMBoxLoc *cur; + + g_system->lockMutex(csMove); + + if (source == -1 || destination == -1) { + g_system->unlockMutex(csMove); + return 0; + } + + // Si fa dare i box + cur = theBoxes->GetBoxes(curLocation); + + // Effettua una copia di riserva per lavorarci + for (i = 0; i < cur->numbbox; i++) + memcpy(&BOX[i], &cur->boxes[i], sizeof(RMBox)); + + // Invalida tutti i Nodi + for (i = 0; i < cur->numbbox; i++) + VALIDO[i] = 0; + + // Prepara sorgente e variabili globali alla procedura + COSTO[source] = 0; + VALIDO[source] = 1; + fine = 0; + + // Ricerca del percorso minimo + while(!fine) { + costominimo = 32000; // risetta il costo minimo + errore = 1; // errore possibile + + // 1 ciclo : ricerca di possibili nuovi nodi + for (i = 0; i < cur->numbbox; i++) + if (VALIDO[i] == 1) { + errore = 0; // errore sfatato + j = 0; + while (((BOX[i].adj[j]) != 1) && (j < cur->numbbox)) + j++; + + if (j >= cur->numbbox) + VALIDO[i] = 2; // nodo saturo? + else { + NEXT[i] = j; + if (COSTO[i] + 1 < costominimo) + costominimo = COSTO[i] + 1; + } + } + + if (errore) + fine = 1; // tutti i nodi saturi + + // 2 ciclo : aggiunta nuovi nodi trovati , saturazione nodi vecchi + for (i = 0; i < cur->numbbox; i++) + if ((VALIDO[i] == 1) && ((COSTO[i] + 1) == costominimo)) { + BOX[i].adj[NEXT[i]] = 2; + COSTO[NEXT[i]] = costominimo; + VALIDO[NEXT[i]] = 1; + for (j = 0; j < cur->numbbox; j++) + if (BOX[j].adj[NEXT[i]] == 1) + BOX[j].adj[NEXT[i]] = 0; + + if (NEXT[i] == destination) + fine = 1; + } + } + + // Estrazione del percorso dalla matrice di adiacenza modificata + if (!errore) { + pathlenght = COSTO[destination]; + k = pathlenght; + path[k] = destination; + + while (path[k] != source) { + i = 0; + while (BOX[i].adj[path[k]] != 2) + i++; + k--; + path[k] = i; + } + + pathlenght++; + } + + g_system->unlockMutex(csMove); + + return !errore; +} + + +void RMCharacter::GoTo(RMPoint destcoord, bool bReversed) { + if (m_pos == destcoord) { + if (minpath == 0) { + Stop(); + PulseEvent(hEndOfPath); + return; + } + } + + status = WALK; + linestart = m_pos; + lineend = destcoord; + dx = linestart.x - lineend.x; + dy = linestart.y - lineend.y; + fx = dx; + fy = dy; + dx = ABS(dx); + dy = ABS(dy); + walkspeed = curSpeed; + walkcount = 0; + + if (bReversed) { + while (0) ; + } + + int nPatt = GetCurPattern(); + + if (dx > dy) { + slope = fy / fx; + if (lineend.x < linestart.x) + walkspeed = -walkspeed; + walkstatus = 1; + + // Cambia il proprio pattern per la nuova direzione + bNeedToStop = true; + if ((walkspeed < 0 && !bReversed) || (walkspeed >= 0 && bReversed)) { + if (nPatt != PAT_WALKLEFT) + SetPattern(PAT_WALKLEFT); + } else { + if (nPatt != PAT_WALKRIGHT) + SetPattern(PAT_WALKRIGHT); + } + } else { + slope = fx / fy; + if (lineend.y < linestart.y) + walkspeed = -walkspeed; + walkstatus = 0; + + bNeedToStop=true; + if ((walkspeed < 0 && !bReversed) || (walkspeed >= 0 && bReversed)) { + if (nPatt != PAT_WALKUP) + SetPattern(PAT_WALKUP); + } else { + if (nPatt != PAT_WALKDOWN) + SetPattern(PAT_WALKDOWN); + } + } + + olddx = dx; + olddy = dy; + + // ResetEvent(hTonyEndMovement); @@@ +} + + +RMPoint RMCharacter::Searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint punto) { + short passi, minimo; + RMPoint nuovo, trovato; + minimo = 32000; + + if (UP) { + nuovo = punto; + passi = 0; + while((InWhichBox(nuovo) == -1) && (nuovo.y >= 0)) { nuovo.y--; passi++; } + if ((InWhichBox(nuovo) != -1) && (passi < minimo)&& + FindPath(InWhichBox(m_pos), InWhichBox(nuovo))) { + minimo = passi; + nuovo.y--; // to avoid error? + trovato = nuovo; + } + } + + if (DOWN) { + nuovo = punto; + passi = 0; + while ((InWhichBox(nuovo) == -1) && (nuovo.y < 480)) { nuovo.y++; passi++; } + if ((InWhichBox(nuovo) != -1) && (passi < minimo) && + FindPath(InWhichBox(m_pos), InWhichBox(nuovo))) { + minimo = passi; + nuovo.y++; // to avoid error? + trovato = nuovo; + } + } + + if (RIGHT) { + nuovo = punto; + passi = 0; + while ((InWhichBox(nuovo) == -1) && (nuovo.x < 640)) { nuovo.x++; passi++; } + if ((InWhichBox(nuovo) != -1) && (passi < minimo) && + FindPath(InWhichBox(m_pos), InWhichBox(nuovo))) { + minimo = passi; + nuovo.x++; // to avoid error? + trovato = nuovo; + } + } + + if (LEFT) { + nuovo = punto; + passi = 0; + while ((InWhichBox(nuovo) == -1) && (nuovo.x >= 0)) { nuovo.x--; passi++; } + if ((InWhichBox(nuovo) != -1) && (passi < minimo) && + FindPath(InWhichBox(m_pos), InWhichBox(nuovo))) { + minimo = passi; + nuovo.x--; // to avoid error? + trovato = nuovo; + } + } + + if (minimo == 32000) trovato = punto; + return trovato; +} + + +RMPoint RMCharacter::NearestPoint(RMPoint punto) { +/* + RMPoint tofind; + signed short difx,dify; + + difx = m_pos.x-punto.x; + dify = m_pos.y-punto.y; + + if ((difx>0) && (dify>0)) tofind=Searching(0,1,1,0,punto); + if ((difx>0) && (dify<0)) tofind=Searching(1,0,1,0,punto); + if ((difx<0) && (dify>0)) tofind=Searching(0,1,0,1,punto); + if ((difx<0) && (dify<0)) tofind=Searching(1,0,0,1,punto); + + // potrebbero essere tolti? Pensaci @@@@ + if ((difx= = 0) && (dify>0)) tofind=Searching(0,1,1,1,punto); + if ((difx= = 0) && (dify<0)) tofind=Searching(1,0,1,1,punto); + if ((dify= = 0) && (difx>0)) tofind=Searching(1,1,1,0,punto); + if ((dify= = 0) && (difx<0)) tofind=Searching(1,1,0,1,punto); + + if ((dify= = 0) && (difx= = 0)) tofind=punto; + + return tofind; +*/ + return Searching(1, 1, 1, 1, punto); +} + + +short RMCharacter::ScanLine(RMPoint punto) { + int Ldx, Ldy, Lcount; + float Lfx, Lfy, Lslope; + RMPoint Lstart, Lend, Lscan; + signed char Lspeed, Lstatus; + + Lstart = m_pos; + Lend = punto; + Ldx = Lstart.x-Lend.x; + Ldy = Lstart.y-Lend.y; + Lfx = Ldx; + Lfy = Ldy; + Ldx = ABS(Ldx); + Ldy = ABS(Ldy); + Lspeed = 1; + Lcount = 0; + + if (Ldx > Ldy) { + Lslope = Lfy / Lfx; + if (Lend.x < Lstart.x) Lspeed = -Lspeed; + Lstatus = 1; + } else { + Lslope = Lfx / Lfy; + if (Lend.y < Lstart.y) Lspeed =- Lspeed; + Lstatus = 0; + } + + Lscan = Lstart; // Inizio scansione + while (InWhichBox(Lscan) != -1) { + Lcount++; + if (Lstatus) { + Ldx = Lspeed * Lcount; + Ldy = Lslope * Ldx; + } else { + Ldy = Lspeed * Lcount; + Ldx = Lslope * Ldy; + } + + Lscan.x = Lstart.x + Ldx; + Lscan.y = Lstart.y + Ldy; + + if ((ABS(Lscan.x - Lend.x) <= 1) && (ABS(Lscan.y - Lend.y) <= 1)) return 1; + } + + return 0; +} -namespace Tony { +// Calcola intersezioni tra la traiettoria rettilinea ed il pi vicino BBOX +RMPoint RMCharacter::InvScanLine(RMPoint punto) { + int Ldx, Ldy, Lcount; + float Lfx, Lfy, Lslope; + RMPoint Lstart, Lend, Lscan; + signed char Lspeed, Lstatus, Lbox = -1; -using namespace ::Tony::MPAL; + Lstart = punto; // Exchange! + Lend = m_pos; // :-) + Ldx = Lstart.x - Lend.x; + Ldy = Lstart.y - Lend.y; + Lfx = Ldx; + Lfy = Ldy; + Ldx = ABS(Ldx); + Ldy = ABS(Ldy); + Lspeed = 1; + Lcount = 0; + + if (Ldx > Ldy) { + Lslope = Lfy / Lfx; + if (Lend.x < Lstart.x) Lspeed = -Lspeed; + Lstatus=1; + } else { + Lslope = Lfx / Lfy; + if (Lend.y < Lstart.y) Lspeed = -Lspeed; + Lstatus = 0; + } + Lscan = Lstart; + + for (;;) { + if (InWhichBox(Lscan) != -1) { + if (InWhichBox(Lscan) != Lbox) { + if (InWhichBox(m_pos) == InWhichBox(Lscan) || FindPath(InWhichBox(m_pos),InWhichBox(Lscan))) + return Lscan; + else + Lbox = InWhichBox(Lscan); + } + } + + Lcount++; + if (Lstatus) { + Ldx = Lspeed * Lcount; + Ldy = Lslope * Ldx; + } else { + Ldy = Lspeed * Lcount; + Ldx = Lslope * Ldy; + } + Lscan.x = Lstart.x + Ldx; + Lscan.y = Lstart.y + Ldy; + } +} + + +/***************************************************************************/ +/* Ritorna la coordinata dell'HotSpot di uscita pi vicino al giocatore */ +/***************************************************************************/ + +RMPoint RMCharacter::NearestHotSpot(int sourcebox, int destbox) { + RMPoint puntocaldo; + short cc; + int x, y, distanzaminima; + distanzaminima = 10000000; + RMBoxLoc *cur = theBoxes->GetBoxes(curLocation); + + for (cc = 0; cc < cur->boxes[sourcebox].numhotspot; cc++) + if ((cur->boxes[sourcebox].hotspot[cc].destination) == destbox) { + x = ABS(cur->boxes[sourcebox].hotspot[cc].hotx - m_pos.x); + y = ABS(cur->boxes[sourcebox].hotspot[cc].hoty - m_pos.y); + + if ((x * x + y * y) < distanzaminima) { + distanzaminima = x * x + y * y; + puntocaldo.x = cur->boxes[sourcebox].hotspot[cc].hotx; + puntocaldo.y = cur->boxes[sourcebox].hotspot[cc].hoty; + } + } + + return puntocaldo; +} + +void RMCharacter::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + if (bDrawNow) { + prim->Dst() += m_fixedScroll; + + RMItem::Draw(bigBuf, prim); + } +} + +void RMCharacter::NewBoxEntered(int nBox) { + RMBoxLoc *cur; + bool bOldReverse; + + // Richiama la On ExitBox + mpalQueryDoAction(3, curLocation, curbox); + + cur = theBoxes->GetBoxes(curLocation); + bOldReverse = cur->boxes[curbox].bReversed; + curbox = nBox; + + // Se cambiata la Z, dobbiamo rimuoverlo dalla OT + if (cur->boxes[curbox].Zvalue != m_z) { + bRemoveFromOT = true; + m_z = cur->boxes[curbox].Zvalue; + } + + // Gestisce l'inversione del movimento SOLO se non siamo nel percorso minimo: se siamo in percorso + // minimo direttamente la DoFrame a farlo + if (bMovingWithoutMinpath) { + if ((cur->boxes[curbox].bReversed && !bOldReverse) || (!cur->boxes[curbox].bReversed && bOldReverse)) { + switch (GetCurPattern()) { + case PAT_WALKUP: + SetPattern(PAT_WALKDOWN); + break; + case PAT_WALKDOWN: + SetPattern(PAT_WALKUP); + break; + case PAT_WALKRIGHT: + SetPattern(PAT_WALKLEFT); + break; + case PAT_WALKLEFT: + SetPattern(PAT_WALKRIGHT); + break; + } + } + } + + // Richiama la On EnterBox + mpalQueryDoAction(2, curLocation, curbox); +} + +void RMCharacter::DoFrame(RMGfxTargetBuffer* bigBuf, int loc) { + bool bEndNow; + + bEndNow = false; + bEndOfPath = false; + bDrawNow = (curLocation == loc); + + g_system->lockMutex(csMove); + + // Se stiamo camminando... + if (status != STAND) { + // Se stiamo andando in orizzontale + if (walkstatus == 1) { + dx = walkspeed * walkcount; + dy = slope * dx; + m_pos.x = linestart.x + dx; + m_pos.y = linestart.y + dy; + + // Destra + if (((walkspeed > 0) && (m_pos.x > lineend.x)) || ((walkspeed < 0) && (m_pos.x < lineend.x))) { + m_pos = lineend; + status = STAND; + bEndNow = true; + } + } + + // Se stiamo andando in verticale + if (walkstatus == 0) { + dy = walkspeed * walkcount; + dx = slope * dy; + m_pos.x = linestart.x + dx; + m_pos.y = linestart.y + dy; + + // Basso + if (((walkspeed > 0) && (m_pos.y > lineend.y)) || ((walkspeed < 0) && (m_pos.y < lineend.y))) { + m_pos = lineend; + status = STAND; + bEndNow = true; + } + } + + // Controlla se il personaggio uscito dai BOX per errore, nel qual caso + // lo fa rientrare subito + if (InWhichBox(m_pos) == -1) { + m_pos.x = linestart.x + olddx; + m_pos.y = linestart.y + olddy; + } + + // Se siamo appena arrivati alla destinazione temporanea ed finito il percorso minimo, + // ci fermiamo definitivamente + if (bEndNow && minpath == 0) { + if (!bEndOfPath) + Stop(); + bEndOfPath = true; + PulseEvent(hEndOfPath); + } + + walkcount++; + + // Aggiorna la Z del personaggio @@@ bisognerebbe rimuoverlo solo se cambiata la Z + + // Controlla se abbiamo cambiato box + if (!theBoxes->IsInBox(curLocation, curbox, m_pos)) + NewBoxEntered(InWhichBox(m_pos)); + + // Aggiorna le vecchie coordinate + olddx = dx; + olddy = dy; + } + + // Se siamo fermi + if (status == STAND) { + // Controlliamo se c' ancora percorso minimo da calcolare + if (minpath == 1) { + RMBoxLoc *cur = theBoxes->GetBoxes(curLocation); + + // Se dobbiamo ancora attraversare un box + if (pathcount < pathlenght) { + // Controlliamo che il box su cui stiamo entrando sia attivo + if (cur->boxes[path[pathcount-1]].attivo) { + // Muoviti in linea retta verso l'hotspot pi vicino, tenendo conto del reversing please + // NEWBOX = path[pathcount-1] + GoTo(NearestHotSpot(path[pathcount-1], path[pathcount]), cur->boxes[path[pathcount-1]].bReversed); + pathcount++; + } else { + // Se il box disattivato, possiamo solo bloccare tutto + // @@@ Questo non dovrebbe pi avvenire, dato che abbiamo migliorato + // la ricerca del percorso minimo + minpath = 0; + if (!bEndOfPath) + Stop(); + bEndOfPath = true; + PulseEvent(hEndOfPath); + } + } else { + // Se siamo gi entrati nell'ultimo box, dobbiamo solo muoverci in linea retta verso il + // punto di arrivo + // NEWBOX = InWhichBox(pathend) + minpath = 0; + GoTo(pathend, cur->boxes[InWhichBox(pathend)].bReversed); + } + } + } + + g_system->unlockMutex(csMove); + + // Richiama il DoFrame dell'item + RMItem::DoFrame(bigBuf); +} + +void RMCharacter::Stop(void) { + bMoving = false; + + // Non si sa mai... + status = STAND; + minpath = 0; + + if (!bNeedToStop) + return; + + bNeedToStop = false; + + switch (GetCurPattern()) { + case PAT_WALKUP: + SetPattern(PAT_STANDUP); + break; + + case PAT_WALKDOWN: + SetPattern(PAT_STANDDOWN); + break; + + case PAT_WALKLEFT: + SetPattern(PAT_STANDLEFT); + break; + + case PAT_WALKRIGHT: + SetPattern(PAT_STANDRIGHT); + break; + + default: +// assert(0); +// MessageBox(NULL,"E' lo stesso errore di prima, ma non crasha","Ehi!",MB_OK); + SetPattern(PAT_STANDDOWN); + break; + } +} + +inline int RMCharacter::InWhichBox(RMPoint pt) { + return theBoxes->WhichBox(curLocation,pt); +} + + +bool RMCharacter::Move(RMPoint pt) { + RMPoint dest; + int numbox; + + bMoving = true; + + // Se 0,0, non fare nulla, anzi fermati + if (pt.x == 0 && pt.y == 0) { + minpath = 0; + status = STAND; + Stop(); + return true; + } + + // Se clicko fuori dai box + numbox = InWhichBox(pt); + if (numbox == -1) { + // Trova il punto pi vicino dentro i box + dest = NearestPoint(pt); + + // ???!?? + if (dest == pt) + dest = InvScanLine(pt); + + pt = dest; + numbox = InWhichBox(pt); + } + + RMBoxLoc *cur = theBoxes->GetBoxes(curLocation); + + minpath = 0; + status = STAND; + bMovingWithoutMinpath = true; + if (ScanLine(pt)) + GoTo(pt, cur->boxes[numbox].bReversed); + else if (FindPath(InWhichBox(m_pos), InWhichBox(pt))) { + bMovingWithoutMinpath = false; + minpath = 1; + pathcount = 1; + pathend = pt; + } else { + // @@@ Questo caso se un hotspot dentro un box + // ma non c' un path per arrivarci. Usiamo quindi + // la invscanline per cercare un punto intorno + dest = InvScanLine(pt); + pt = dest; + + if (ScanLine(pt)) + GoTo(pt,cur->boxes[numbox].bReversed); + else if (FindPath(InWhichBox(m_pos), InWhichBox(pt))) { + bMovingWithoutMinpath = false; + minpath = 1; + pathcount = 1; + pathend = pt; + return true; + } else + return false; + } + + return true; +} + +void RMCharacter::SetPosition(RMPoint pt, int newloc) { + RMBoxLoc *box; + + minpath = 0; + status = STAND; + m_pos = pt; + + if (newloc != -1) + curLocation = newloc; + + // Aggiorna la Z del personaggio + box = theBoxes->GetBoxes(curLocation); + curbox = InWhichBox(m_pos); + assert(curbox != -1); + m_z = box->boxes[curbox].Zvalue; + bRemoveFromOT = true; +} + +bool RMCharacter::RemoveThis(void) { + if (bRemoveFromOT) + return true; + + return RMItem::RemoveThis(); +} + +RMCharacter::RMCharacter() { +// InitializeCriticalSection(&csMove); + hEndOfPath = CreateEvent(NULL, false, false, NULL); + minpath = 0; + curSpeed = 3; + bRemoveFromOT = false; + bMoving = false; + + m_pos.Set(0, 0); +} + +RMCharacter::~RMCharacter() { +// DeleteCriticalSection(&csMove); + CloseHandle(hEndOfPath); +} + +void RMCharacter::LinkToBoxes(RMGameBoxes *boxes) { + theBoxes = boxes; +} /****************************************************************************\ * RMBox Methods @@ -94,7 +1695,7 @@ void RMBox::ReadFromStream(RMDataStream &ds) { } } -RMDataStream& operator>>(RMDataStream &ds, RMBox &box) { +RMDataStream &operator>>(RMDataStream &ds, RMBox &box) { box.ReadFromStream(ds); return ds; @@ -104,7 +1705,7 @@ RMDataStream& operator>>(RMDataStream &ds, RMBox &box) { * RMBoxLoc Methods \****************************************************************************/ -void RMBoxLoc::ReadFromStream(RMDataStream& ds) { +void RMBoxLoc::ReadFromStream(RMDataStream &ds) { int i; char buf[2]; byte ver; @@ -132,7 +1733,7 @@ void RMBoxLoc::RecalcAllAdj(void) { for (i = 0; i < numbbox; i++) { Common::fill(boxes[i].adj, boxes[i].adj + MAXBOXES, 0); - for (j=0; j < boxes[i].numhotspot; j++) + for (j = 0; j < boxes[i].numhotspot; j++) if (boxes[boxes[i].hotspot[j].destination].attivo) boxes[i].adj[boxes[i].hotspot[j].destination] = 1; } @@ -192,7 +1793,7 @@ int RMGameBoxes::WhichBox(int nLoc, RMPoint punto) { if (!cur) return -1; - for (i=0; inumbbox; i++) + for (i = 0; inumbbox; i++) if (cur->boxes[i].attivo) if ((punto.x >= cur->boxes[i].left) && (punto.x <= cur->boxes[i].right) && (punto.y >= cur->boxes[i].top) && (punto.y <= cur->boxes[i].bottom)) @@ -233,7 +1834,7 @@ void RMGameBoxes::SaveState(byte *state) { WRITE_LE_UINT32(state, m_allBoxes[i]->numbbox); state+=4; - for (j=0; j < m_allBoxes[i]->numbbox; j++) + for (j = 0; j < m_allBoxes[i]->numbbox; j++) *state++ = m_allBoxes[i]->boxes[j].attivo; } } @@ -254,8 +1855,7 @@ void RMGameBoxes::LoadState(byte *state) { nbox = READ_LE_UINT32(state); state += 4; - for (j=0; jnumbbox) m_allBoxes[i]->boxes[j].attivo = *state; @@ -266,4 +1866,451 @@ void RMGameBoxes::LoadState(byte *state) { } } +/****************************************************************************\ +* Metodi di RMLocation +\****************************************************************************/ + +/****************************************************************************\ +* +* Function: RMLocation::RMLocation(); +* +* Description: Costruttore standard +* +\****************************************************************************/ + +RMLocation::RMLocation() { + m_nItems = 0; + m_items = NULL; + m_buf = NULL; +} + + +/****************************************************************************\ +* +* Function: bool RMLocation::Load(char *lpszFileName); +* +* Description: Carica una locazione (.LOC) da un file di cui viene fornito +* il pathname. +* +* Input: char *lpszFileName Nome del file di dati +* +* Return: true se tutto OK, false in caso di errore +* +\****************************************************************************/ + +bool RMLocation::Load(const char *lpszFileName) { + Common::File f; + bool bRet; + + // Apre il file in lettura + if (!f.open(lpszFileName)) + return false; + + // Lo passa alla routine di loading da file aperto + bRet = Load(f); + + // Chiude il file + f.close(); + + return bRet; +} + + +/****************************************************************************\ +* +* Function: bool RMLocation::Load(HANDLE hFile); +* +* Description: Carica una locazione (.LOC) da un handle di file aperto +* +* Input: HANDLE hFile Handle del file +* +* Return: true se tutto OK, false in caso di errore +* +\****************************************************************************/ + +bool RMLocation::Load(Common::File &file) { + int size; +// byte *buf; +// uint32 dwReadBytes; + bool bRet; + + // Calcola la lunghezza del file + size = file.size(); + file.seek(0); + +/* + // Alloca la memoria per caricare il file in memoria + buf=(LPBYTE)GlobalAlloc(GMEM_FIXED,size); + + // Legge il file in memoria + ReadFile(hFile,buf,size,&dwReadBytes,0); + + // Parsing del file, utilizzando la funzione di load da memorira + bRet=Load(buf); + + // Free della memoria + GlobalFree(buf); +*/ + + RMFileStreamSlow fs; + + fs.OpenFile(file); + bRet = Load(fs); + fs.Close(); + + return bRet; +} + + +bool RMLocation::Load(const byte *buf) { + RMDataStream ds; + bool bRet; + + ds.OpenBuffer(buf); + bRet = Load(ds); + ds.Close(); + return bRet; +} + + + +/****************************************************************************\ +* +* Function: bool RMLocation::Load(byte *buf); +* +* Description: Carica una locazione (.LOC) parsando il file gia' caricato +* in memoria. +* +* Input: byte *buf Buffer con il file caricato +* +* Return: true se ok, false in caso di errore +* +\****************************************************************************/ + +bool RMLocation::Load(RMDataStream &ds) { + char id[3]; + int dimx, dimy; + byte ver; + byte cm; + int i; + + // Controlla l'ID + ds >> id[0] >> id[1] >> id[2]; + + // Controlla se siamo in un LOX + if (id[0] == 'L' && id[1] == 'O' && id[2] == 'X') + return LoadLOX(ds); + + // Altrimenti, controlla che sia un LOC normale + if (id[0] != 'L' || id[1] != 'O' || id[2] != 'C') + return false; + + // Versione + ds >> ver; + assert(ver == 6); + + // Nome della locazione + ds >> m_name; + + // Skippa i salvataggi MPAL (64 bytes) + ds >> TEMPNumLoc; + ds >> TEMPTonyStart.x >> TEMPTonyStart.y; + ds += 64 - 4 * 3; + + // Skippa il flag di background associato (?!) + ds += 1; + + // Dimensioni della locazione + ds >> dimx >> dimy; + m_curScroll.Set(0, 0); + + // Legge il color mode + ds >> cm; m_cmode = (RMColorMode)cm; + + // Inizializza il source buffer e leggi la locazione dentro + switch (m_cmode) { + case CM_256: + m_buf = new RMGfxSourceBuffer8; + break; + + case CM_65K: + m_buf = new RMGfxSourceBuffer16; + break; + + default: + assert(0); + break; + }; + + // Inizializza la surface, caricando anche la palette se necessario + m_buf->Init(ds, dimx, dimy, true); + + // Controlla le dimensioni della locazione +// assert(dimy!=512); + + // Numero oggetti + ds >> m_nItems; + + // Creazione e lettura degli oggetti + if (m_nItems > 0) + m_items = new RMItem[m_nItems]; + + + _vm->FreezeTime(); + for (i = 0;i < m_nItems && !ds.IsError(); i++) + ds >> m_items[i]; + _vm->UnfreezeTime(); + + // Setta i pattern iniziali @@@ doppione!! + //for (i = 0;i> ver; + assert(ver == 1); + + // Nome locazione + ds >> m_name; + + // Numero loc + ds >> TEMPNumLoc; + ds >> TEMPTonyStart.x >> TEMPTonyStart.y; + + // Dimensioni + ds >> dimx >> dimy; + m_curScroll.Set(0, 0); + + // Color mode sempre 65K + m_cmode = CM_65K; + m_buf = new RMGfxSourceBuffer16; + + // Inizializza la surface, caricando anche la palette se necessario + m_buf->Init(ds, dimx, dimy, true); + + // Controlla le dimensioni della locazione +// assert(dimy!=512); + + // Numero oggetti + ds >> m_nItems; + + // Creazione e lettura degli oggetti + if (m_nItems > 0) + m_items = new RMItem[m_nItems]; + + for (i = 0; i < m_nItems && !ds.IsError(); i++) + m_items[i].ReadFromStream(ds, true); + + return ds.IsError(); +} + + + +/****************************************************************************\ +* +* Function: void RMLocation::Draw(RMGfxTargetBuffer* bigBuf, +* RMGfxPrimitive* prim); +* +* Description: Metodo di drawing in overloading da RMGfxSourceBuffer8 +* +\****************************************************************************/ + +void RMLocation::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + // Setta la posizione sorgente dello scrolling + if (m_buf->Dimy()>RM_SY || m_buf->Dimx()>RM_SX) { + prim->SetSrc(RMRect(m_curScroll,m_curScroll+RMPoint(640,480))); + } + + prim->SetDst(m_fixedScroll); + + // Richiama il metodo di drawing della classe dell'immagine, che disegner il background + // della locazione + m_buf->Draw(bigBuf, prim); +} + + +/****************************************************************************\ +* +* Function: void RMLocation::DoFrame(void); +* +* Description: Prepara un frame, aggiungendo alla OTList la locazione stessa +* e tutti gli item che hanno cambiato frame di animazione +* +\****************************************************************************/ + +void RMLocation::DoFrame(RMGfxTargetBuffer *bigBuf) { + int i; + + // Se la locazione non e' in OT list, la aggiunge + if (!m_nInList) + bigBuf->AddPrim(new RMGfxPrimitive(this)); + + // Processa tutti gli item della locazione + for (i = 0;i < m_nItems; i++) + m_items[i].DoFrame(bigBuf); +} + + +RMItem *RMLocation::GetItemFromCode(uint32 dwCode) { + int i; + + for (i = 0; i < m_nItems; i++) + if (m_items[i].MpalCode() == (int)dwCode) + return &m_items[i]; + + return NULL; +} + +RMItem *RMLocation::WhichItemIsIn(RMPoint pt) { + int found = -1; + int foundSize = 0; + int size; + + for (int i = 0; i < m_nItems; i++) { + size = 0; + if (m_items[i].IsIn(pt, &size)) { + if (found == -1 || size < foundSize) { + foundSize = size; + found = i; + } + } + } + + if (found == -1) + return NULL; + else + return &m_items[found]; +} + + +RMLocation::~RMLocation() { + Unload(); +} + +void RMLocation::Unload(void) { + // Cancella la memoria + if (m_items) { + delete[] m_items; + m_items = NULL; + } + + // Cancella il buffer + if (m_buf) { + delete m_buf; + m_buf = NULL; + } +} + +void RMLocation::UpdateScrolling(RMPoint ptShowThis) { + RMPoint oldScroll = m_curScroll; + + if (m_curScroll.x + 250 > ptShowThis.x) { + m_curScroll.x = ptShowThis.x - 250; + } else if (m_curScroll.x + RM_SX - 250 < ptShowThis.x) { + m_curScroll.x = ptShowThis.x + 250 - RM_SX; + } else if (ABS(m_curScroll.x + RM_SX / 2 - ptShowThis.x) > 32 && m_buf->Dimx() > RM_SX) { + if (m_curScroll.x + RM_SX / 2 < ptShowThis.x) + m_curScroll.x++; + else + m_curScroll.x--; + } + + if (m_curScroll.y + 180 > ptShowThis.y) { + m_curScroll.y = ptShowThis.y - 180; + } else if (m_curScroll.y + RM_SY - 180 < ptShowThis.y) { + m_curScroll.y = ptShowThis.y + 180 - RM_SY; + } else if (ABS(m_curScroll.y + RM_SY / 2 - ptShowThis.y) > 16 && m_buf->Dimy() > RM_SY) { + if (m_curScroll.y + RM_SY / 2 < ptShowThis.y) + m_curScroll.y++; + else + m_curScroll.y--; + } + + if (m_curScroll.x < 0) m_curScroll.x = 0; + if (m_curScroll.y < 0) m_curScroll.y = 0; + if (m_curScroll.x + RM_SX > m_buf->Dimx()) m_curScroll.x = m_buf->Dimx() - RM_SX; + if (m_curScroll.y + RM_SY > m_buf->Dimy()) m_curScroll.y = m_buf->Dimy() - RM_SY; + + if (oldScroll != m_curScroll) + for (int i = 0; i < m_nItems; i++) + m_items[i].SetScrollPosition(m_curScroll); +} + +void RMLocation::SetFixedScroll(const RMPoint &scroll) { + m_fixedScroll = scroll; + + for (int i = 0; i < m_nItems; i++) + m_items[i].SetScrollPosition(m_curScroll - m_fixedScroll); +} + +void RMLocation::SetScrollPosition(const RMPoint &scroll) { + RMPoint pt = scroll; + if (pt.x < 0) pt.x = 0; + if (pt.y < 0) pt.y = 0; + if (pt.x + RM_SX>m_buf->Dimx()) pt.x = m_buf->Dimx() - RM_SX; + if (pt.y + RM_SY>m_buf->Dimy()) pt.y = m_buf->Dimy() - RM_SY; + + m_curScroll = pt; + + for (int i = 0; i < m_nItems; i++) + m_items[i].SetScrollPosition(m_curScroll); +} + + +void RMLocation::PauseSound(bool bPause) { + int i; + + for (i = 0; i < m_nItems; i++) + m_items[i].PauseSound(bPause); +} + + +/****************************************************************************\ +* Metodi di RMMessage +\****************************************************************************/ + +RMMessage::RMMessage(uint32 dwId) { + lpMessage=mpalQueryMessage(dwId); + assert(lpMessage != NULL); + + if (lpMessage) + ParseMessage(); +} + +RMMessage::~RMMessage() { + if (lpMessage) + GlobalFree(lpMessage); +} + +void RMMessage::ParseMessage(void) { + char *p; + + assert(lpMessage != NULL); + + nPeriods = 1; + p = lpPeriods[0] = lpMessage; + + for (;;) { + // Trova la fine del periodo corrente + while (*p != '\0') + p++; + + // Se c'e' un altro '\0' siamo alla fine del messaggio + p++; + if (*p == '\0') + break; + + // Altrimenti c'e' un altro periodo, e ci ricordiamo il suo inizio + lpPeriods[nPeriods++] = p; + } +} + } // End of namespace Tony diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 73effc85c184..c5c7859e7360 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -50,6 +50,7 @@ #include "common/scummsys.h" #include "common/system.h" +#include "common/file.h" #include "tony/mpal/stubs.h" #include "tony/sound.h" #include "tony/utils.h" @@ -539,8 +540,8 @@ RMItem* m_items; // Oggetti virtual ~RMLocation(); // Caricamento da disco - bool Load(char *lpszFileName); - bool Load(HANDLE hFile); + bool Load(const char *lpszFileName); + bool Load(Common::File &file); bool Load(const byte *buf); bool Load(RMDataStream &ds); bool LoadLOX(RMDataStream &ds); diff --git a/engines/tony/utils.h b/engines/tony/utils.h index bd4b152f1f63..f9c9e614ace7 100644 --- a/engines/tony/utils.h +++ b/engines/tony/utils.h @@ -118,6 +118,56 @@ class RMDataStream { bool IsError(); }; + +/** + * Data stream per lettura di dati aperto da file + */ +class RMFileStream : public RMDataStream { +private: + byte *m_buf; + +public: + RMFileStream(); + virtual ~RMFileStream(); + + // Apre lo stream da file + bool OpenFile(const char *lpFN); + bool OpenFile(Common::File &file); + + void Close(void); +}; + + +class RMFileStreamSlow : public RMDataStream { +private: + Common::File f; + bool bMustClose; + +public: + RMFileStreamSlow(); + virtual ~RMFileStreamSlow(); + + bool OpenFile(const char *lpFN); + bool OpenFile(Common::File &file); + + void Close(void); + + RMDataStream& operator+=(int nBytes); + int Seek(int nBytes, RMDSPos where = CUR); + + int Pos(); + virtual bool IsEOF(); + + bool Read(void *buf, int size); + + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, char &var); + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, byte &var); + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, uint16 &var); + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, int16 &var); + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, int &var); + friend RMFileStreamSlow& operator>>(RMFileStreamSlow &df, uint32 &var); +}; + /** * String class */