[Scummvm-cvs-logs] CVS: scummvm/sword1 collision.h,NONE,1.1 debug.cpp,NONE,1.1 debug.h,NONE,1.1 eventman.cpp,NONE,1.1 eventman.h,NONE,1.1 logic.cpp,NONE,1.1 logic.h,NONE,1.1 memman.cpp,NONE,1.1 memman.h,NONE,1.1 menu.cpp,NONE,1.1 menu.h,NONE,1.1 mouse.cpp,NONE,1.1 mouse.h,NONE,1.1 music.cpp,NONE,1.1 music.h,NONE,1.1 object.h,NONE,1.1 objectman.cpp,NONE,1.1 objectman.h,NONE,1.1 resman.cpp,NONE,1.1 resman.h,NONE,1.1 router.cpp,NONE,1.1 router.h,NONE,1.1 screen.cpp,NONE,1.1 screen.h,NONE,1.1 sound.cpp,NONE,1.1 sound.h,NONE,1.1 staticres.cpp,NONE,1.1 sword1.cpp,NONE,1.1 sword1.h,NONE,1.1 sworddefs.h,NONE,1.1 swordres.h,NONE,1.1 text.cpp,NONE,1.1 text.h,NONE,1.1
Robert G?ffringmann
lavosspawn at users.sourceforge.net
Mon Dec 15 18:10:01 CET 2003
Update of /cvsroot/scummvm/scummvm/sword1
In directory sc8-pr-cvs1:/tmp/cvs-serv18926/sword1
Added Files:
collision.h debug.cpp debug.h eventman.cpp eventman.h
logic.cpp logic.h memman.cpp memman.h menu.cpp menu.h
mouse.cpp mouse.h music.cpp music.h object.h objectman.cpp
objectman.h resman.cpp resman.h router.cpp router.h screen.cpp
screen.h sound.cpp sound.h staticres.cpp sword1.cpp sword1.h
sworddefs.h swordres.h text.cpp text.h
Log Message:
Broken Sword 1: initial import
--- NEW FILE: collision.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/collision.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSCOLLISION_H
#define BSCOLLISION_H
/*#include "objectman.h"
class SwordLogic;
class SwordCollision {
public:
SwordCollision(ObjectMan *pObjMan, SwordLogic *pLogic);
~SwordCollision(void);
void checkCollisions(void);
void fnBumpOff(void);
void fnBumpOn(void);
private:
int32 getIntersect(int32 x0, int32 y0, int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3);
int noCol;
ObjectMan *_objMan;
SwordLogic *_logic; // for CFN_preset_script
};*/
// maybe it's better to make this part of SwordRouter
#endif // BSCOLLISION_H
--- NEW FILE: debug.cpp ---
#include "stdafx.h"
#include "debug.h"
#include "common/util.h"
void SwordDebug::interpretScript(uint32 id, uint32 level, uint32 script, uint32 pc) {
debug(8, "\nInterpreting %d@%d: script %X from %X", id, level, script, pc);
}
void SwordDebug::callMCode(uint32 mcodeNum, uint32 paramCount, int32 a, int32 b, int32 c, int32 d, int32 e, int32 f) {
debug(9, "mcode: %s(%d, %d, %d, %d, %d, %d) [%d]", _mCodeNames[mcodeNum], a, b, c, d, e, f, paramCount);
}
const char SwordDebug::_mCodeNames[100][35] = {
"fnBackground",
"fnForeground",
"fnSort",
"fnNoSprite",
"fnMegaSet",
"fnAnim",
"fnSetFrame",
"fnFullAnim",
"fnFullSetFrame",
"fnFadeDown",
"fnFadeUp",
"fnCheckFade",
"fnSetSpritePalette",
"fnSetWholePalette",
"fnSetFadeTargetPalette",
"fnSetPaletteToFade",
"fnSetPaletteToCut",
"fnPlaySequence",
"fnIdle",
"fnPause",
"fnPauseSeconds",
"fnQuit",
"fnKillId",
"fnSuicide",
"fnNewScript",
"fnSubScript",
"fnRestartScript",
"fnSetBookmark",
"fnGotoBookmark",
"fnSendSync",
"fnWaitSync",
"cfnClickInteract",
"cfnSetScript",
"cfnPresetScript",
"fnInteract",
"fnIssueEvent",
"fnCheckForEvent",
"fnWipeHands",
"fnISpeak",
"fnTheyDo",
"fnTheyDoWeWait",
"fnWeWait",
"fnChangeSpeechText",
"fnTalkError",
"fnStartTalk",
"fnCheckForTextLine",
"fnAddTalkWaitStatusBit",
"fnRemoveTalkWaitStatusBit",
"fnNoHuman",
"fnAddHuman",
"fnBlankMouse",
"fnNormalMouse",
"fnLockMouse",
"fnUnlockMouse",
"fnSetMousePointer",
"fnSetMouseLuggage",
"fnMouseOn",
"fnMouseOff",
"fnChooser",
"fnEndChooser",
"fnStartMenu",
"fnEndMenu",
"cfnReleaseMenu",
"fnAddSubject",
"fnAddObject",
"fnRemoveObject",
"fnEnterSection",
"fnLeaveSection",
"fnChangeFloor",
"fnWalk",
"fnTurn",
"fnStand",
"fnStandAt",
"fnFace",
"fnFaceXy",
"fnIsFacing",
"fnGetTo",
"fnGetToError",
"fnGetPos",
"fnGetGamepadXy",
"fnPlayFx",
"fnStopFx",
"fnPlayMusic",
"fnStopMusic",
"fnInnerSpace",
"fnRandom",
"fnSetScreen",
"fnPreload",
"fnCheckCD",
"fnRestartGame",
"fnQuitGame",
"fnDeathScreen",
"fnSetParallax",
"fnTdebug",
"fnRedFlash",
"fnBlueFlash",
"fnYellow",
"fnGreen",
"fnPurple",
"fnBlack"
};
--- NEW FILE: debug.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/debug.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSDEBUG_H
#define BSDEBUG_H
#include "scummsys.h"
class SwordDebug {
public:
static void interpretScript(uint32 id, uint32 level, uint32 script, uint32 pc);
static void callMCode(uint32 mcodeNum, uint32 paramCount, int32 a, int32 b, int32 c, int32 d, int32 e, int32 f);
private:
static const char _mCodeNames[100][35];
};
#endif // BSDEBUG_H
--- NEW FILE: eventman.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/eventman.cpp,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "eventman.h"
#include "sworddefs.h"
#include "common/util.h"
EventManager::EventManager(void) {
for (uint8 cnt = 0; cnt < TOTAL_EVENT_SLOTS; cnt++)
_eventPendingList[cnt].delay = _eventPendingList[cnt].eventNumber = 0;
}
void EventManager::serviceGlobalEventList(void) {
for (uint8 slot = 0; slot < TOTAL_EVENT_SLOTS; slot++)
if (_eventPendingList[slot].delay)
_eventPendingList[slot].delay--;
}
void EventManager::checkForEvent(BsObject *compact) {
for (uint8 objCnt = 0; objCnt < O_TOTAL_EVENTS; objCnt++) {
if (compact->o_event_list[objCnt].o_event)
for (uint8 globCnt = 0; globCnt < TOTAL_EVENT_SLOTS; globCnt++) {
if (_eventPendingList[globCnt].delay &&
(_eventPendingList[globCnt].eventNumber == compact->o_event_list[objCnt].o_event)) {
compact->o_logic = LOGIC_script; //force into script mode
_eventPendingList[globCnt].delay = 0; //started, so remove from queue
compact->o_tree.o_script_level++;
compact->o_tree.o_script_id[compact->o_tree.o_script_level] =
compact->o_event_list[objCnt].o_event_script;
compact->o_tree.o_script_pc[compact->o_tree.o_script_level] =
compact->o_event_list[objCnt].o_event_script;
}
}
}
}
bool EventManager::eventValid(int32 event) {
for (uint8 slot = 0; slot < TOTAL_EVENT_SLOTS; slot++)
if ((_eventPendingList[slot].eventNumber == event) &&
(_eventPendingList[slot].delay))
return true;
return false;
}
int EventManager::fnCheckForEvent(BsObject *cpt, int32 id, int32 pause) {
if (pause) {
cpt->o_pause = pause;
cpt->o_logic = LOGIC_pause_for_event;
return SCRIPT_STOP;
}
for (uint8 objCnt = 0; objCnt < O_TOTAL_EVENTS; objCnt++) {
if (cpt->o_event_list[objCnt].o_event)
for (uint8 globCnt = 0; globCnt < TOTAL_EVENT_SLOTS; globCnt++) {
if (_eventPendingList[globCnt].delay &&
(_eventPendingList[globCnt].eventNumber == cpt->o_event_list[objCnt].o_event)) {
cpt->o_logic = LOGIC_script; //force into script mode
_eventPendingList[globCnt].delay = 0; //started, so remove from queue
cpt->o_tree.o_script_level++;
cpt->o_tree.o_script_id[cpt->o_tree.o_script_level] =
cpt->o_event_list[objCnt].o_event_script;
cpt->o_tree.o_script_pc[cpt->o_tree.o_script_level] =
cpt->o_event_list[objCnt].o_event_script;
return SCRIPT_STOP;
}
}
}
return SCRIPT_CONT;
}
void EventManager::fnIssueEvent(BsObject *compact, int32 id, int32 event, int32 delay) {
uint8 evSlot = 0;
while (_eventPendingList[evSlot].delay)
evSlot++;
if (evSlot >= TOTAL_EVENT_SLOTS)
error("EventManager ran out of event slots!");
_eventPendingList[evSlot].delay = delay;
_eventPendingList[evSlot].eventNumber = event;
}
--- NEW FILE: eventman.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/eventman.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSEVENTMAN_H
#define BSEVENTMAN_H
#include "object.h"
#define TOTAL_EVENT_SLOTS 20
struct GlobalEvent {
int32 eventNumber;
int32 delay;
};
class EventManager {
public:
EventManager(void);
void serviceGlobalEventList(void);
void checkForEvent(BsObject *compact);
int fnCheckForEvent(BsObject *cpt, int32 id, int32 pause);
void fnIssueEvent(BsObject *compact, int32 id, int32 event, int32 delay);
bool eventValid(int32 event);
private:
GlobalEvent _eventPendingList[TOTAL_EVENT_SLOTS];
};
#endif // BSEVENTMAN_H
--- NEW FILE: logic.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/logic.cpp,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
[...1595 lines suppressed...]
}
const uint32 SwordLogic::_scriptVarInit[NON_ZERO_SCRIPT_VARS][2] = {
{ 42, 448}, { 43, 378}, { 51, 1}, { 92, 1}, { 147, 71}, { 201, 1},
{ 209, 1}, { 215, 1}, { 242, 2}, { 244, 1}, { 246, 3}, { 247, 1},
{ 253, 1}, { 297, 1}, { 398, 1}, { 508, 1}, { 605, 1}, { 606, 1},
{ 701, 1}, { 709, 1}, { 773, 1}, { 843, 1}, { 907, 1}, { 923, 1},
{ 966, 1}, { 988, 2}, {1058, 1}, {1059, 2}, {1060, 3}, {1061, 4},
{1062, 5}, {1063, 6}, {1064, 7}, {1065, 8}, {1066, 9}, {1067, 10},
{1068, 11}, {1069, 12}, {1070, 13}, {1071, 14}, {1072, 15}, {1073, 16},
{1074, 17}, {1075, 18}, {1076, 19}, {1077, 20}, {1078, 21}, {1079, 22},
{1080, 23}, {1081, 24}, {1082, 25}, {1083, 26}, {1084, 27}, {1085, 28},
{1086, 29}, {1087, 30}, {1088, 31}, {1089, 32}, {1090, 33}, {1091, 34},
{1092, 35}, {1093, 36}, {1094, 37}, {1095, 38}, {1096, 39}, {1097, 40},
{1098, 41}, {1099, 42}, {1100, 43}, {1101, 44}, {1102, 48}, {1103, 45},
{1104, 47}, {1105, 49}, {1106, 50}, {1107, 52}, {1108, 54}, {1109, 56},
{1110, 57}, {1111, 58}, {1112, 59}, {1113, 60}, {1114, 61}, {1115, 62},
{1116, 63}, {1117, 64}, {1118, 65}, {1119, 66}, {1120, 67}, {1121, 68},
{1122, 69}, {1123, 71}, {1124, 72}, {1125, 73}, {1126, 74}
};
--- NEW FILE: logic.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/logic.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSLOGIC_H
#define BSLOGIC_H
// combination of logic.c and scr_int.c
#include "sworddefs.h"
#include "objectman.h"
#include "common/util.h"
#define NON_ZERO_SCRIPT_VARS 95
#define NUM_SCRIPT_VARS 1179
class SwordText;
class SwordSound;
class EventManager;
class SwordMenu;
class SwordRouter;
class SwordScreen;
class SwordMouse;
class SwordMusic;
class SwordLogic;
typedef int (SwordLogic::*BSMcodeTable)(BsObject *, int32, int32, int32, int32, int32, int32, int32);
class SwordLogic {
public:
SwordLogic(ObjectMan *pObjMan, ResMan *resMan, SwordScreen *pScreen, SwordMouse *pMouse, SwordSound *pSound, SwordMusic *pMusic, SwordMenu *pMenu);
~SwordLogic(void);
void newScreen(uint32 newScreen);
void engine(void);
void updateScreenParams(void);
void runMouseScript(BsObject *cpt, int32 scriptId);
SwordRouter *giveRouter(void) { return _router; }; // for router debugging
static uint32 _scriptVars[NUM_SCRIPT_VARS];
private:
ObjectMan *_objMan;
ResMan *_resMan;
SwordScreen *_screen;
SwordSound *_sound;
SwordMouse *_mouse;
SwordRouter *_router;
SwordText *_textMan;
EventManager *_eventMan;
SwordMenu *_menu;
SwordMusic *_music;
uint32 _newScript; // <= ugly, but I can't avoid it.
bool _speechRunning, _speechFinished, _textRunning;
uint8 _speechClickDelay;
Common::RandomSource _rnd;
int scriptManager(BsObject *compact, uint32 id);
void processLogic(BsObject *compact, uint32 id);
int interpretScript(BsObject *compact, int id, Header *scriptModule, int scriptBase, int scriptNum);
int logicWaitTalk(BsObject *compact);
int logicStartTalk(BsObject *compact);
int logicArAnimate(BsObject *compact, uint32 id);
int speechDriver(BsObject *compact);
int fullAnimDriver(BsObject *compact);
int animDriver(BsObject *compact);
static BSMcodeTable _mcodeTable[100];
uint16 inRange(uint16 a, uint16 b, uint16 c);
//- mcodeTable:
int fnBackground (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnForeground (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSort (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnNoSprite (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnMegaSet (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnAnim (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetFrame (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFullAnim (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFullSetFrame (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFadeDown (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFadeUp (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnCheckFade (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetSpritePalette(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetWholePalette(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetFadeTargetPalette(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetPaletteToFade(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetPaletteToCut(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPlaySequence (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnIdle (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPause (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPauseSeconds (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnQuit (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnKillId (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSuicide (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnNewScript (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSubScript (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRestartScript (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetBookmark (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGotoBookmark (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSendSync (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnWaitSync (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int cfnClickInteract(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int cfnSetScript (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int cfnPresetScript (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnInteract (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnIssueEvent (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnCheckForEvent (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnWipeHands (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnISpeak (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnTheyDo (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnTheyDoWeWait (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnWeWait (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnChangeSpeechText(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnTalkError (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStartTalk (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnCheckForTextLine(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnAddTalkWaitStatusBit(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRemoveTalkWaitStatusBit(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnNoHuman (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnAddHuman (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnBlankMouse (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnNormalMouse (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnLockMouse (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnUnlockMouse (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetMousePointer(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetMouseLuggage(BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnMouseOn (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnMouseOff (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnChooser (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnEndChooser (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStartMenu (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnEndMenu (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int cfnReleaseMenu (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnAddSubject (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnAddObject (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRemoveObject (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnEnterSection (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnLeaveSection (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnChangeFloor (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnWalk (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnTurn (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStand (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStandAt (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFace (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnFaceXy (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnIsFacing (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGetTo (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGetToError (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGetPos (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGetGamepadXy (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPlayFx (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStopFx (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPlayMusic (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnStopMusic (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnInnerSpace (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRandom (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetScreen (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPreload (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnCheckCD (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRestartGame (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnQuitGame (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnDeathScreen (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnSetParallax (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnTdebug (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnRedFlash (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnBlueFlash (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnYellow (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnGreen (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnPurple (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
int fnBlack (BsObject *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
static const uint32 _scriptVarInit[NON_ZERO_SCRIPT_VARS][2];
};
#endif //BSLOGIC_H
--- NEW FILE: memman.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/memman.cpp,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "memman.h"
#include "common/util.h"
MemMan::MemMan(void) {
_alloced = 0;
_memListFree = _memListFreeEnd = NULL;
}
MemMan::~MemMan(void) {
}
void MemMan::alloc(BsMemHandle *bsMem, uint32 pSize, uint16 pCond) {
_alloced += pSize;
bsMem->data = (void*)malloc(pSize);
if (!bsMem->data)
error("MemMan::alloc(): Can't alloc %d bytes of memory.", pSize);
bsMem->cond = pCond;
bsMem->size = pSize;
if (pCond == MEM_CAN_FREE) {
warning("%d Bytes alloced as FREEABLE.", pSize); // why should one want to alloc mem if it can be freed?
addToFreeList(bsMem);
} else if (bsMem->next || bsMem->prev) // it's in our _freeAble list, remove it from there
removeFromFreeList(bsMem);
checkMemoryUsage();
}
void MemMan::freeNow(BsMemHandle *bsMem) {
if (bsMem->cond != MEM_FREED) {
_alloced -= bsMem->size;
removeFromFreeList(bsMem);
free(bsMem->data);
bsMem->cond = MEM_FREED;
}
}
void MemMan::setCondition(BsMemHandle *bsMem, uint16 pCond) {
if ((pCond == MEM_FREED) || (pCond > MEM_DONT_FREE))
error("MemMan::setCondition: program tried to set illegal memory condition");
if (bsMem->cond != pCond) {
bsMem->cond = pCond;
if (pCond == MEM_DONT_FREE)
removeFromFreeList(bsMem);
else if (pCond == MEM_CAN_FREE)
addToFreeList(bsMem);
}
}
void MemMan::checkMemoryUsage(void) {
while ((_alloced > MAX_ALLOC) && _memListFree) {
free(_memListFreeEnd->data);
_memListFreeEnd->data = NULL;
_memListFreeEnd->cond = MEM_FREED;
_alloced -= _memListFreeEnd->size;
removeFromFreeList(_memListFreeEnd);
}
}
void MemMan::addToFreeList(BsMemHandle *bsMem) {
if (bsMem->next || bsMem->prev) {
warning("addToFreeList: mem block is already in freeList");
return;
}
bsMem->prev = NULL;
bsMem->next = _memListFree;
if (bsMem->next)
bsMem->next->prev = bsMem;
_memListFree = bsMem;
if (!_memListFreeEnd)
_memListFreeEnd = _memListFree;
}
void MemMan::removeFromFreeList(BsMemHandle *bsMem) {
/*BsMemHandle *forw = _memListFree;
BsMemHandle *rev = _memListFreeEnd;
while (forw || rev) {
if (!(forw && rev))
error("mem list is completely fubared");
printf("%p <-> %p\n", forw, rev);
forw = forw->next;
rev = rev->prev;
}
printf("\n");*/
if (!(bsMem->prev || bsMem->next))
warning("removeFromFreeList: memory block wasn't in list");
if (_memListFree == bsMem)
_memListFree = bsMem->next;
if (_memListFreeEnd == bsMem)
_memListFreeEnd = bsMem->prev;
if (bsMem->next)
bsMem->next->prev = bsMem->prev;
if (bsMem->prev)
bsMem->prev->next = bsMem->next;
bsMem->next = bsMem->prev = NULL;
}
void MemMan::initHandle(BsMemHandle *bsMem) {
memset(bsMem, 0, sizeof(BsMemHandle));
}
--- NEW FILE: memman.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/memman.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef MEMMAN_H
#define MEMMAN_H
#include "scummsys.h"
struct BsMemHandle {
void *data;
uint32 size;
uint32 refCount;
uint16 cond;
BsMemHandle *next, *prev;
};
// mem conditions:
#define MEM_FREED 0
#define MEM_CAN_FREE 1
#define MEM_DONT_FREE 2
#define MAX_ALLOC (6*1024*1024) // max amount of mem we want to alloc().
class MemMan {
public:
MemMan(void);
~MemMan(void);
void alloc(BsMemHandle *bsMem, uint32 pSize, uint16 pCond = MEM_DONT_FREE);
void setCondition(BsMemHandle *bsMem, uint16 pCond);
void freeNow(BsMemHandle *bsMem);
void initHandle(BsMemHandle *bsMem);
private:
void addToFreeList(BsMemHandle *bsMem);
void removeFromFreeList(BsMemHandle *bsMem);
void checkMemoryUsage(void);
uint32 _alloced; //currently allocated memory
BsMemHandle *_memListFree;
BsMemHandle *_memListFreeEnd;
};
#endif //MEMMAN_H
--- NEW FILE: menu.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/menu.cpp,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "menu.h"
#include "resman.h"
#include "scummsys.h"
#include "common/util.h"
#include "system.h"
#include "mouse.h"
#include "screen.h"
#include "logic.h"
SwordMenuIcon::SwordMenuIcon(uint8 menuType, uint8 menuPos, uint32 resId, uint32 frame, SwordScreen *screen) {
_menuType = menuType;
_menuPos = menuPos;
_resId = resId;
_frame = frame;
_screen = screen;
_selected = false;
}
bool SwordMenuIcon::wasClicked(uint16 mouseX, uint16 mouseY) {
return false;
}
void SwordMenuIcon::setSelect(bool pSel) {
_selected = pSel;
}
void SwordMenuIcon::draw(void) {
uint16 x = _menuPos * 40;
uint16 y = (_menuType == MENU_TOP)?(0):(440);
_screen->showFrame(x, y, _resId, _frame + (_selected ? 1 : 0));
}
SwordMenu::SwordMenu(SwordScreen *pScreen, SwordMouse *pMouse) {
_screen = pScreen;
_mouse = pMouse;
for (uint8 cnt = 0; cnt < 16; cnt++)
_subjects[cnt] = NULL;
}
uint8 SwordMenu::checkMenuClick(uint8 menuType) {
uint16 mouseEvent = _mouse->testEvent();
if (!mouseEvent)
return 0;
uint16 x, y;
_mouse->giveCoords(&x, &y);
if (menuType == MENU_BOT) {
for (uint8 cnt = 0; cnt < SwordLogic::_scriptVars[IN_SUBJECT]; cnt++)
if (_subjects[cnt]->wasClicked(x, y))
if (mouseEvent == BS1L_BUTTON_DOWN) {
SwordLogic::_scriptVars[OBJECT_HELD] = _subjectBar[cnt];
buildSubjects();
return 0;
} else if (mouseEvent == BS1L_BUTTON_UP) {
if (SwordLogic::_scriptVars[OBJECT_HELD] == _subjectBar[cnt])
return cnt + 1;
else {
SwordLogic::_scriptVars[OBJECT_HELD] = 0;
buildSubjects();
return 0;
}
}
} else {
return 0;
}
return 0;
}
void SwordMenu::buildSubjects(void) {
uint8 subDest = 0;
clearMenu(MENU_BOT);
for (uint8 cnt = 0; cnt < 16; cnt++)
if (_subjects[cnt]) {
delete _subjects[cnt];
_subjects[cnt] = NULL;
}
for (uint8 cnt = 0; cnt < SwordLogic::_scriptVars[IN_SUBJECT]; cnt++) {
uint32 res = _subjectList[(_subjectBar[cnt] & 65535) - BASE_SUBJECT].subjectRes;
uint32 frame = _subjectList[(_subjectBar[cnt] & 65535) - BASE_SUBJECT].frameNo;
_subjects[cnt] = new SwordMenuIcon(MENU_BOT, cnt, res, frame, _screen);
_subjects[cnt]->setSelect(SwordLogic::_scriptVars[OBJECT_HELD] == (_subjectBar[cnt]&0xFFFF));
_subjects[cnt]->draw();
}
//_system->update_screen();
}
void SwordMenu::refresh(uint8 menuType) {
//warning("stub: SwordMenu::refresh())");
}
void SwordMenu::clearMenu(uint8 menuType) {
warning("stub: SwordMenu::clearMenu()");
}
void SwordMenu::fnStartMenu(void) {
warning("stub: SwordMenu::fnStartMenu()");
}
void SwordMenu::fnEndMenu(void) {
warning("stub: SwordMenu::clearMenu()");
}
void SwordMenu::fnChooser(BsObject *compact) {
SwordLogic::_scriptVars[OBJECT_HELD] = 0;
buildSubjects();
compact->o_logic = LOGIC_choose;
}
void SwordMenu::fnEndChooser(void) {
SwordLogic::_scriptVars[OBJECT_HELD] = 0;
clearMenu(MENU_BOT);
clearMenu(MENU_TOP);
//_system->update_screen();
for (uint8 cnt = 0; cnt < 16; cnt++)
if (_subjects[cnt]) {
delete _subjects[cnt];
_subjects[cnt] = NULL;
}
}
int SwordMenu::logicChooser(BsObject *compact) {
if (checkMenuClick(MENU_BOT)) {
compact->o_logic = LOGIC_script;
return 1;
} else
return 0;
}
void SwordMenu::fnAddSubject(int32 sub) {
_subjectBar[SwordLogic::_scriptVars[IN_SUBJECT]] = sub;
SwordLogic::_scriptVars[IN_SUBJECT]++;
}
void SwordMenu::cfnReleaseMenu(void) {
clearMenu(MENU_TOP);
//_system->update_screen();
}
--- NEW FILE: menu.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/menu.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSMENU_H
#define BSMENU_H
#include "sworddefs.h"
#include "object.h"
class SwordScreen;
class SwordMouse;
class ResMan;
#define MENU_TOP 0
#define MENU_BOT 1
struct Subject {
uint32 subjectRes;
uint32 frameNo;
};
class SwordMenuIcon {
public:
SwordMenuIcon(uint8 menuType, uint8 menuPos, uint32 resId, uint32 frame, SwordScreen *screen);
bool wasClicked(uint16 mouseX, uint16 mouseY);
void setSelect(bool pSel);
void draw(void);
private:
uint8 _menuType, _menuPos;
uint32 _resId, _frame;
bool _selected;
SwordScreen *_screen;
};
class SwordMenu {
public:
SwordMenu(SwordScreen *pScreen, SwordMouse *pMouse);
void fnChooser(BsObject *compact);
void fnEndChooser(void);
void fnAddSubject(int32 sub);
void cfnReleaseMenu(void);
int logicChooser(BsObject *compact);
void engine(void);
void refresh(uint8 menuType);
void fnStartMenu(void);
void fnEndMenu(void);
private:
void buildSubjects(void);
void clearMenu(uint8 menuType);
uint8 checkMenuClick(uint8 menuType);
SwordMenuIcon *_subjects[16];
uint32 _subjectBar[16];
SwordScreen *_screen;
SwordMouse *_mouse;
static const Subject _subjectList[TOTAL_subjects];
};
#endif //BSMENU_H
--- NEW FILE: mouse.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/mouse.cpp,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "mouse.h"
#include "menu.h"
#include "screen.h"
#include "logic.h"
#include "resman.h"
#include "objectman.h"
#include "sworddefs.h"
#include "system.h"
#include "swordres.h"
SwordMouse::SwordMouse(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
_resMan = pResMan;
_objMan = pObjMan;
_system = system;
_numObjs = 0;
_mouseStatus = 0; // mouse off and unlocked
_getOff = 0;
for (uint8 cnt = 0; cnt < 17; cnt++) {
_pointers[cnt] = (MousePtr*)_resMan->openFetchRes(MSE_POINTER + cnt);
#ifdef SCUMM_BIG_ENDIAN
uint16 *data = (uint16*)pointers[cnt];
for (uint8 endCnt = 0; endCnt < 5; endCnt++)
data[endCnt] = READ_LE_UINT16(data + endCnt);
#endif
fixTransparency(_pointers[cnt]->data + 0x30, _pointers[cnt]->sizeX * _pointers[cnt]->sizeY * _pointers[cnt]->numFrames);
}
/*_resMan->resOpen(MSE_POINTER); // normal mouse (1 frame anim)
_resMan->resOpen(MSE_OPERATE);
_resMan->resOpen(MSE_PICKUP);
_resMan->resOpen(MSE_EXAMINE);
_resMan->resOpen(MSE_MOUTH);
_resMan->resOpen(MSE_BECKON_L);
_resMan->resOpen(MSE_BECKON_R);
_resMan->resOpen(MSE_ARROW0);
_resMan->resOpen(MSE_ARROW1);
_resMan->resOpen(MSE_ARROW2);
_resMan->resOpen(MSE_ARROW3);
_resMan->resOpen(MSE_ARROW4);
_resMan->resOpen(MSE_ARROW5);
_resMan->resOpen(MSE_ARROW6);
_resMan->resOpen(MSE_ARROW7);
_resMan->resOpen(MSE_ARROW8); // UPWARDS
_resMan->resOpen(MSE_ARROW9);*/ // DOWNWARDS
// luggage & chess stuff is opened dynamically
}
void SwordMouse::useLogic(SwordLogic *pLogic) {
_logic = pLogic;
}
void SwordMouse::addToList(int id, BsObject *compact) {
_objList[_numObjs].id = id;
_objList[_numObjs].compact = compact;
_numObjs++;
}
void SwordMouse::flushEvents(void) {
_lastState = _state = 0;
}
void SwordMouse::engine(uint16 x, uint16 y, uint16 eventFlags) {
//warning("Stub: SwordMouse::engine");
_state = 0; // all mouse events are flushed after one cycle.
if (_lastState) { // delay all events by one cycle to notice L_button + R_button clicks correctly.
_state = _lastState | eventFlags;
_lastState = 0;
} else if (eventFlags)
_lastState = eventFlags;
if (!(_mouseStatus & 1)) { // no human?
// if the mouse is turned off, I want the menu automatically removed,
// except while in conversation, while examining a menu object or while combining two menu objects!
/*if ((!subject_status)&&(!menu_looking)&&(!second_icon))
{
HideMenu(TOP_MENU);
menu_status=0;
}*/
_numObjs = 0;
return; // no human, so we don't want the mouse engine
}
// todo: check menus here.
SwordLogic::_scriptVars[MOUSE_X] = SwordLogic::_scriptVars[SCROLL_OFFSET_X] + x + 128;
SwordLogic::_scriptVars[MOUSE_Y] = SwordLogic::_scriptVars[SCROLL_OFFSET_Y] + y + 128 - 40;
//-
int32 touchedId = 0;
uint16 clicked;
if (y > 40) {
for (uint16 priority = 0; (priority < 10) && (!touchedId); priority++) {
for (uint16 cnt = 0; cnt < _numObjs; cnt++) {
if ((_objList[cnt].compact->o_priority == priority) &&
(SwordLogic::_scriptVars[MOUSE_X] >= (uint32)_objList[cnt].compact->o_mouse_x1) &&
(SwordLogic::_scriptVars[MOUSE_X] <= (uint32)_objList[cnt].compact->o_mouse_x2) &&
(SwordLogic::_scriptVars[MOUSE_Y] >= (uint32)_objList[cnt].compact->o_mouse_y1) &&
(SwordLogic::_scriptVars[MOUSE_Y] <= (uint32)_objList[cnt].compact->o_mouse_y2)) {
touchedId = _objList[cnt].id;
clicked = cnt;
}
}
}
if (touchedId != SwordLogic::_scriptVars[SPECIAL_ITEM]) { //the mouse collision situation has changed in one way or another
SwordLogic::_scriptVars[SPECIAL_ITEM] = touchedId;
debug(9, "New special item: %X\n", touchedId);
if (_getOff) { // there was something else selected before, run its get-off script
_logic->runMouseScript(NULL, _getOff);
_getOff = 0;
}
if (touchedId) { // there's something new selected, now.
BsObject *compact = _objMan->fetchObject(SwordLogic::_scriptVars[SPECIAL_ITEM]);
if (_objList[clicked].compact->o_mouse_on) //run its get on
_logic->runMouseScript(_objList[clicked].compact, _objList[clicked].compact->o_mouse_on);
_getOff = _objList[clicked].compact->o_mouse_off; //setup get-off for later
}
}
} else
SwordLogic::_scriptVars[SPECIAL_ITEM] = 0;
if (_state & (BS1L_BUTTON_DOWN | BS1R_BUTTON_DOWN)) {
// todo: handle menus
SwordLogic::_scriptVars[MOUSE_BUTTON] = _state;
if (SwordLogic::_scriptVars[SPECIAL_ITEM]) {
BsObject *compact = _objMan->fetchObject(SwordLogic::_scriptVars[SPECIAL_ITEM]);
_logic->runMouseScript(compact, compact->o_mouse_click);
}
}
_numObjs = 0;
}
uint16 SwordMouse::testEvent(void) {
return _state;
}
void SwordMouse::setLuggage(uint32 resId, uint32 rate) {
warning("stub: SwordMouse::setLuggage(%d, %d)", resId, rate);
}
void SwordMouse::setPointer(uint32 resId, uint32 rate) {
_currentPtrId = resId - MSE_POINTER;
_rate = rate;
_rateCnt = 1;
_frame = 0;
if (resId == 0) {
_system->set_mouse_cursor(NULL, 0, 0, 0, 0);
_system->show_mouse(false);
} else {
animate();
_system->show_mouse(true);
}
}
void SwordMouse::animate(void) {
if (_rateCnt && (_mouseStatus == 1)) {
_rateCnt--;
if (!_rateCnt) {
_rateCnt = _rate;
_frame = (_frame + 1) % _pointers[_currentPtrId]->numFrames;
uint16 size = _pointers[_currentPtrId]->sizeX * _pointers[_currentPtrId]->sizeY;
_system->set_mouse_cursor(_pointers[_currentPtrId]->data + 0x30 + _frame * size, _pointers[_currentPtrId]->sizeX, _pointers[_currentPtrId]->sizeY, _pointers[_currentPtrId]->hotSpotX, _pointers[_currentPtrId]->hotSpotY);
}
}
}
void SwordMouse::fnNoHuman(void) {
if (_mouseStatus & 2) // locked, can't do anything
return ;
_mouseStatus = 0; // off & unlocked
setLuggage(0, 0);
setPointer(0, 0);
}
void SwordMouse::fnAddHuman(void) {
if (_mouseStatus & 2) // locked, can't do anything
return ;
_mouseStatus = 1;
SwordLogic::_scriptVars[SPECIAL_ITEM] = -1;
_getOff = SCR_std_off;
setPointer(MSE_POINTER, 0);
_mouseCount = 3;
}
void SwordMouse::fnBlankMouse(void) {
setPointer(0, 0);
}
void SwordMouse::fnNormalMouse(void) {
setPointer(MSE_POINTER, 0);
}
void SwordMouse::fnLockMouse(void) {
_mouseStatus |= 2;
}
void SwordMouse::fnUnlockMouse(void) {
_mouseStatus &= 1;
}
void SwordMouse::giveCoords(uint16 *x, uint16 *y) {
*x = _mouseX;
*y = _mouseY;
}
void SwordMouse::fixTransparency(uint8 *data, uint32 size) {
for (uint32 cnt = 0; cnt < size; cnt++)
if (data[cnt] == 0)
data[cnt] = 255;
}
--- NEW FILE: mouse.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/mouse.h,v 1.1 2003/12/16 02:09:24 lavosspawn Exp $
*
*/
#ifndef BSMOUSE_H
#define BSMOUSE_H
#include "scummsys.h"
#include "sworddefs.h"
#include "object.h"
#define MAX_MOUSE 30
#define BS1L_BUTTON_DOWN 2
#define BS1L_BUTTON_UP 4
#define BS1R_BUTTON_DOWN 8
#define BS1R_BUTTON_UP 16
#define MOUSE_BOTH_BUTTONS (BS1L_BUTTON_DOWN | BS1R_BUTTON_DOWN)
struct MouseObj {
int id;
BsObject *compact;
};
#if !defined(__GNUC__)
#pragma START_PACK_STRUCTS
#endif
struct MousePtr {
uint16 numFrames;
uint16 sizeX;
uint16 sizeY;
uint16 hotSpotX;
uint16 hotSpotY;
uint8 data[2]; // arbitrary number.
} GCC_PACK;
#if !defined(__GNUC__)
#pragma END_PACK_STRUCTS
#endif
class SwordLogic;
class ResMan;
class ObjectMan;
class OSystem;
class SwordMouse {
public:
SwordMouse(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan);
void addToList(int id, BsObject *compact);
void useLogic(SwordLogic *pLogic);
void setLuggage(uint32 resID, uint32 rate);
void setPointer(uint32 resID, uint32 rate);
void animate(void);
void engine(uint16 x, uint16 y, uint16 eventFlags);
uint16 testEvent(void);
void flushEvents(void);
void giveCoords(uint16 *x, uint16 *y);
void fnNoHuman(void);
void fnAddHuman(void);
void fnBlankMouse(void);
void fnNormalMouse(void);
void fnLockMouse(void);
void fnUnlockMouse(void);
private:
void fixTransparency(uint8 *data, uint32 size);
MousePtr *_pointers[17];
uint32 _currentPtrId, _rate, _rateCnt, _frame;
OSystem *_system;
SwordLogic *_logic;
MouseObj _objList[MAX_MOUSE];
ResMan *_resMan;
ObjectMan *_objMan;
uint16 _mouseX, _mouseY;
uint8 _mouseStatus, _mouseCount;
uint16 _numObjs;
uint16 _lastState, _state;
uint32 _getOff;
};
#endif //BSMOUSE_H
--- NEW FILE: music.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/music.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
// todo: add fadeout, crossfading.
// this code always loops. make it depend on _loopFlag
#include "stdafx.h"
#include "music.h"
#include "sound/mixer.h"
#include "common/util.h"
#include "common/file.h"
SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
_system = system;
_mixer = pMixer;
_mixer->setupPremix(passMixerFunc, this);
_fading = 0;
_playing = false;
_loop = false;
_mutex = _system->create_mutex();
_waveSize = _wavePos = _bufPos = _smpInBuf = 0;
assert(_mixer->getOutputRate() == 22050);
}
void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {
((SwordMusic*)param)->mixer(buf, len);
}
void SwordMusic::mixer(int16 *buf, uint len) {
if (!_playing)
memset(buf, 0, 2 * len * sizeof(int16));
else {
_system->lock_mutex(_mutex);
len >>= 1;
if (len > _smpInBuf)
warning("SwordMusic::mixer: sample buffer underrun");
else {
uint32 maxLen = BUFSIZE - _bufPos;
if (len >= maxLen) {
for (uint32 cnt = 0; cnt < maxLen; cnt++)
buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = _musicBuf[_bufPos + cnt];
_smpInBuf -= maxLen;
_bufPos = 0;
len -= maxLen;
buf += maxLen * 4;
}
if (len) {
for (uint32 cnt = 0; cnt < len; cnt++)
buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = _musicBuf[_bufPos + cnt];
_smpInBuf -= len;
_bufPos += len;
}
}
_system->unlock_mutex(_mutex);
}
}
void SwordMusic::stream(void) {
// make sure we've got enough samples in buffer.
if ((_smpInBuf < SAMPLERATE) && _playing) {
_system->lock_mutex(_mutex);
uint32 loadTotal = BUFSIZE - _smpInBuf;
while (uint32 doLoad = loadTotal) {
if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal)
doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE;
if (_waveSize - _wavePos < doLoad)
doLoad = _waveSize - _wavePos;
int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE);
_musicFile.read(dest, doLoad * 2);
_wavePos += doLoad;
if (_wavePos == _waveSize) {
_wavePos = 0;
_musicFile.seek(WAVEHEADERSIZE);
}
loadTotal -= doLoad;
_smpInBuf += doLoad;
}
_system->unlock_mutex(_mutex);
}
}
void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
_system->lock_mutex(_mutex);
_loop = (loopFlag > 0);
if (tuneId) {
if (_musicFile.isOpen())
_musicFile.close();
char fName[20];
sprintf(fName, "MUSIC1\\%s.wav", _tuneList[tuneId]);
_musicFile.open(fName);
if (_musicFile.isOpen()) {
_musicFile.seek(0x28);
_waveSize = _musicFile.readUint32LE() / 2;
_wavePos = 0;
_smpInBuf = 0;
_bufPos = 0;
_playing = true;
} else
_playing = false;
} else
_playing = false;
_system->unlock_mutex(_mutex);
stream();
}
void SwordMusic::fadeDown(void) {
warning("stub: SwordMusic::fadeDown");
}
--- NEW FILE: music.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/music.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef BSMUSIC_H
#define BSMUSIC_H
#include "scummsys.h"
#include "common/system.h"
#include "common/file.h"
#define TOTAL_TUNES 270
#define SAMPLERATE 11025
#define BUFSIZE (4 * SAMPLERATE)
#define WAVEHEADERSIZE 0x2C
class SoundMixer;
//class File;
class SwordMusic {
public:
SwordMusic(OSystem *system, SoundMixer *pMixer);
void stream(void);
void startMusic(int32 tuneId, int32 loopFlag);
void fadeDown(void);
private:
File _musicFile;
OSystem *_system;
SoundMixer *_mixer;
uint16 _fading;
bool _playing;
bool _loop;
OSystem::MutexRef _mutex;
static void passMixerFunc(void *param, int16 *buf, uint len);
void mixer(int16 *buf, uint len);
static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
uint32 _waveSize, _wavePos;
uint32 _bufPos, _smpInBuf;
int16 _musicBuf[BUFSIZE]; // samples for 8 seconds
};
#endif // BSMUSIC_H
--- NEW FILE: object.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/object.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef BSOBJECT_H
#define BSOBJECT_H
#include "scummsys.h"
#define O_TOTAL_EVENTS 5
#define O_WALKANIM_SIZE 600 //max number of nodes in router output
#define O_GRID_SIZE 200
#define EXTRA_GRID_SIZE 20
//--------------------------------------------------------------------------------------
struct OEventSlot { //receiving event list in the compact -
int32 o_event; //array of these with O_TOTAL_EVENTS elements
int32 o_event_script;
};
#define TOTAL_script_levels 5
//-----
struct ScriptTree { //this is a logic tree, used by OBJECTs
int32 o_script_level; //logic level
int32 o_script_id[TOTAL_script_levels]; //script id's (are unique to each level)
int32 o_script_pc[TOTAL_script_levels]; //pc of script for each (if script_manager)
}; // size = 11*int32 = 44 bytes
//--------------------------------------------------------------------------------------
struct TalkOffset {
int32 x;
int32 y;
}; // size = 2*int32 = 8 bytes
//--------------------------------------------------------------------------------------
struct WalkData {
int32 frame;
int32 x;
int32 y;
int32 step;
int32 dir;
}; // size = 5*int32 = 20 bytes
struct BsObject {
int32 o_type; // 0 broad description of type - object, floor, etc.
int32 o_status; // 4 bit flags for logic, graphics, mouse, etc.
int32 o_logic; // 8 logic type
int32 o_place; // 12 where is the mega character
int32 o_down_flag; // 16 pass back down with this - with C possibly both are unnecessary?
int32 o_target; // 20 target object for the GTM *these are linked to script
int32 o_screen; // 24 physical screen/section
int32 o_frame; // 28 frame number &
int32 o_resource; // 32 id of spr file it comes from
int32 o_sync; // 36 receive sync here
int32 o_pause; // 40 logic_engine() pauses these cycles
int32 o_xcoord; // 44
int32 o_ycoord; // 48
int32 o_mouse_x1; // 52 top-left of mouse area is (x1,y1)
int32 o_mouse_y1; // 56
int32 o_mouse_x2; // 60 bottom-right of area is (x2,y2) (these coords are inclusive)
int32 o_mouse_y2; // 64
int32 o_priority; // 68
int32 o_mouse_on; // 72
int32 o_mouse_off; // 76
int32 o_mouse_click; // 80
int32 o_interact; // 84
int32 o_get_to_script; // 88
int32 o_scale_a; // 92 used by floors
int32 o_scale_b; // 96
int32 o_anim_x; // 100
int32 o_anim_y; // 104
ScriptTree o_tree; // 108 size = 44 bytes
ScriptTree o_bookmark; // 152 size = 44 bytes
int32 o_dir; // 196
int32 o_speech_pen; // 200
int32 o_speech_width; // 204
int32 o_speech_time; // 208
int32 o_text_id; // 212 working back from o_ins1
int32 o_tag; // 216
int32 o_anim_pc; // 220 position within an animation structure
int32 o_anim_resource; // 224 cdt or anim table
int32 o_walk_pc; // 228
TalkOffset talk_table[6]; // 232 size = 6*8 bytes = 48
OEventSlot o_event_list[O_TOTAL_EVENTS]; // 280 size = 5*8 bytes = 40
int32 o_ins1; // 320
int32 o_ins2; // 324
int32 o_ins3; // 328
int32 o_mega_resource; // 332
int32 o_walk_resource; // 336
WalkData o_route[O_WALKANIM_SIZE]; // 340 size = 600*20 bytes = 12000
// mega size = 12340 bytes (+ 8 byte offset table + 20 byte header = 12368)
};
struct _collisionData {
BsObject *compact;
int32 w[24];
int32 h[24];
WalkData route[24];
};
#endif //BSOBJECT_H
--- NEW FILE: objectman.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/objectman.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "objectman.h"
#include "scummsys.h"
#include "common/util.h"
#include "sworddefs.h"
#include "swordres.h"
#include "sword1.h"
ObjectMan::ObjectMan(ResMan *pResourceMan) {
_resMan = pResourceMan;
for (uint16 cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
_liveList[cnt] = 0;
_liveList[128] = _liveList[129] = _liveList[130] = _liveList[131] = _liveList[133] =
_liveList[134] = _liveList[145] = _liveList[146] = _liveList[TEXT_sect] = 1;
for (uint16 cnt = 0; cnt < TOTAL_SECTIONS; cnt++) {
if (_liveList[cnt])
_cptData[cnt] = (uint8*)_resMan->cptResOpen(_objectList[cnt]) + sizeof(Header);
else
_cptData[cnt] = NULL;
}
}
ObjectMan::~ObjectMan(void) {
for (uint16 cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
if (_liveList[cnt])
_resMan->resClose(_objectList[cnt]);
}
bool ObjectMan::sectionAlive(uint16 section) {
return (_liveList[section] > 0);
}
void ObjectMan::megaEntering(uint16 section) {
_liveList[section]++;
if (_liveList[section] == 1)
_cptData[section] = ((uint8*)_resMan->cptResOpen(_objectList[section])) + sizeof(Header);
}
void ObjectMan::megaLeaving(uint16 section, int id) {
if (_liveList[section] == 0)
error("mega %d is leaving empty section %d", id, section);
_liveList[section]--;
if ((_liveList[section] == 0) && (id != PLAYER)) {
_resMan->resClose(_liveList[section]);
_cptData[section] = NULL;
}
/* if the player is leaving the section then we have to close the resources after
mainloop ends, because the screen will still need the resources*/
}
uint8 ObjectMan::fnCheckForTextLine(uint32 textId) {
uint8 retVal = 0;
if (!_textList[textId / ITM_PER_SEC][0])
return 0; // section does not exist
uint8 lang = SwordEngine::_systemVars.language;
uint32 *textData = (uint32*)((uint8*)_resMan->openFetchRes(_textList[textId / ITM_PER_SEC][lang]) + sizeof(Header));
if ((textId & ITM_ID) < READ_LE_UINT32(textData)) {
textData++;
if (textData[textId & ITM_ID])
retVal = 1;
}
_resMan->resClose(_textList[textId / ITM_PER_SEC][lang]);
return retVal;
}
char *ObjectMan::lockText(uint32 textId) {
uint8 lang = SwordEngine::_systemVars.language;
char *addr = (char*)_resMan->openFetchRes(_textList[textId / ITM_PER_SEC][lang]) + sizeof(Header);
if ((textId & ITM_ID) >= READ_LE_UINT32(addr)) {
warning("ObjectMan::lockText(%d): only %d texts in file", textId & ITM_ID, READ_LE_UINT32(addr));
textId = 0; // get first line instead
}
uint32 offset = READ_LE_UINT32(addr + ((textId & ITM_ID) + 1)* 4);
if (offset == 0)
warning("ObjectMan::lockText(%d): text number has no text lines", textId);
return addr + offset;
}
void ObjectMan::unlockText(uint32 textId) {
_resMan->resClose(_textList[textId / ITM_PER_SEC][SwordEngine::_systemVars.language]);
}
uint32 ObjectMan::lastTextNumber(int section) {
uint8 *data = (uint8*)_resMan->openFetchRes(_textList[section][SwordEngine::_systemVars.language]) + sizeof(Header);
uint32 result = READ_LE_UINT32(data) - 1;
_resMan->resClose(_textList[section][SwordEngine::_systemVars.language]);
return result;
}
BsObject *ObjectMan::fetchObject(uint32 id) {
uint8 *addr = _cptData[id / ITM_PER_SEC];
if (!addr)
error("fetchObject: section %d is not open!", id / ITM_PER_SEC);
id &= ITM_ID;
// DON'T do endian conversion here. it's already done.
return (BsObject*)(addr + *(uint32*)(addr + (id + 1)*4));
}
uint32 ObjectMan::fetchNoObjects(int section) {
if (_cptData[section] == NULL)
error("fetchNoObjects: section %d is not open!", section);
return *(uint32*)_cptData[section];
}
void ObjectMan::closeSection(uint32 screen) {
if (_liveList[screen] == 0) // close the section that PLAYER has just left, if it's empty now
_resMan->resClose(_objectList[screen]);
}
--- NEW FILE: objectman.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/objectman.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
// this is the object manager. our equivalent to protocol.c and coredata.c
#ifndef OBJECTMAN_H
#define OBJECTMAN_H
#include "resman.h"
#include "sworddefs.h"
#include "object.h"
class ObjectMan {
public:
ObjectMan(ResMan *pResourceMan);
~ObjectMan(void);
BsObject *fetchObject(uint32 id);
//void unlockObject(uint32 id);
uint32 fetchNoObjects(int section);
bool sectionAlive(uint16 section);
void megaEntering(uint16 section);
void megaLeaving(uint16 section, int id);
uint8 fnCheckForTextLine(uint32 textId);
char *lockText(uint32 textId);
void unlockText(uint32 textId);
uint32 lastTextNumber(int section);
void closeSection(uint32 screen);
private:
ResMan *_resMan;
static const uint32 _objectList[TOTAL_SECTIONS]; //a table of pointers to object files
static const uint32 _textList[TOTAL_SECTIONS][7]; //a table of pointers to text files
int _liveList[TOTAL_SECTIONS]; //which sections are active
uint8 *_cptData[TOTAL_SECTIONS];
};
#endif //OBJECTMAN_H
--- NEW FILE: resman.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/resman.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "scummsys.h"
#include <stdio.h>
#include <stdlib.h>
#include "memman.h"
#include "resman.h"
#include "sworddefs.h"
#include "base/engine.h"
#include "common/util.h"
#include "swordres.h"
#define MAX_PATH_LEN 260
ResMan::ResMan(const char *resFile, MemMan *pMemoMan) {
_memMan = pMemoMan;
loadCluDescript(resFile);
}
ResMan::~ResMan(void) {
freeCluDescript();
}
void ResMan::loadCluDescript(const char *fileName) {
File resFile;
resFile.open(fileName);
if (!resFile.isOpen())
error("ResMan::loadCluDescript(): File %s not found!", fileName);
_prj.noClu = resFile.readUint32LE();
_prj.clu = new BsClu*[_prj.noClu];
uint32 *cluIndex = (uint32*)malloc(_prj.noClu * 4);
resFile.read(cluIndex, _prj.noClu * 4);
for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++)
if (cluIndex[clusCnt]) {
BsClu *cluster = _prj.clu[clusCnt] = new BsClu;
resFile.read(cluster->label, MAX_LABEL_SIZE);
cluster->noGrp = resFile.readUint32LE();
cluster->grp = new BsGrp*[cluster->noGrp];
uint32 *grpIndex = (uint32*)malloc(cluster->noGrp * 4);
resFile.read(grpIndex, cluster->noGrp * 4);
for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++)
if (grpIndex[grpCnt]) {
BsGrp *group = cluster->grp[grpCnt] = new BsGrp;
group->noRes = resFile.readUint32LE();
group->resHandle = new BsMemHandle[group->noRes];
group->offset = new uint32[group->noRes];
group->length = new uint32[group->noRes];
uint32 *resIdIdx = (uint32*)malloc(group->noRes * 4);
resFile.read(resIdIdx, group->noRes * 4);
for (uint32 resCnt = 0; resCnt < group->noRes; resCnt++) {
if (resIdIdx[resCnt]) {
group->offset[resCnt] = resFile.readUint32LE();
group->length[resCnt] = resFile.readUint32LE();
_memMan->initHandle(group->resHandle + resCnt);
} else {
group->offset[resCnt] = 0xFFFFFFFF;
group->length[resCnt] = 0;
_memMan->initHandle(group->resHandle + resCnt);
}
}
free(resIdIdx);
} else
cluster->grp[grpCnt] = NULL;
free(grpIndex);
} else
_prj.clu[clusCnt] = NULL;
free(cluIndex);
}
void ResMan::freeCluDescript(void) {
for (uint32 clusCnt = 0; clusCnt < _prj.noClu; clusCnt++)
if (BsClu *cluster = _prj.clu[clusCnt]) {
for (uint32 grpCnt = 0; grpCnt < cluster->noGrp; grpCnt++)
if (BsGrp *group = cluster->grp[grpCnt]) {
_memMan->freeNow(group->resHandle);
delete[] group->resHandle;
delete[] group->offset;
delete[] group->length;
delete group;
}
delete[] cluster->grp;
delete cluster;
}
delete[] _prj.clu;
}
void *ResMan::fetchRes(uint32 id) {
BsMemHandle *memHandle = resHandle(id);
if (!memHandle->data)
error("fetchRes:: resource %d is not open!", id);
return memHandle->data;
}
void *ResMan::openFetchRes(uint32 id) {
resOpen(id);
return fetchRes(id);
}
void ResMan::dumpRes(uint32 id) {
char outn[30];
sprintf(outn, "DUMP%08X.BIN", id);
FILE *outf = fopen( outn, "wb");
resOpen(id);
BsMemHandle *memHandle = resHandle(id);
fwrite(memHandle->data, 1, memHandle->size, outf);
fclose(outf);
resClose(id);
}
Header *ResMan::lockScript(uint32 scrID) {
if (!_scriptList[scrID / ITM_PER_SEC])
error("Script id %d not found.\n", scrID);
scrID = _scriptList[scrID / ITM_PER_SEC];
#ifdef SCUMM_BIG_ENDIAN
BsMemHandle *memHandle = resHandle(scrID);
if (memHandle->cond == MEM_FREED)
openScriptResourceBigEndian(scrID);
else
resOpen(scrID);
#else
resOpen(scrID);
#endif
return (Header*)resHandle(scrID)->data;
}
void ResMan::unlockScript(uint32 scrID) {
resClose(_scriptList[scrID / ITM_PER_SEC]);
}
void *ResMan::cptResOpen(uint32 id) {
#ifdef SCUMM_BIG_ENDIAN
BsMemHandle *memHandle = resHandle(id);
if (memHandle->cond == MEM_FREED)
openCptResourceBigEndian(id);
else
resOpen(id);
#else
resOpen(id);
#endif
return resHandle(id)->data;
}
void ResMan::resOpen(uint32 id) { // load resource ID into memory
BsMemHandle *memHandle = resHandle(id);
if (memHandle->cond == MEM_FREED) { // memory has been freed
uint32 size = resLength(id);
_memMan->alloc(memHandle, size);
uint8 *dest = (uint8*)memHandle->data;
File *clusFile = openClusterFile(id);
clusFile->seek( resOffset(id) );
clusFile->read( memHandle->data, size);
if (clusFile->ioFailed())
error("Can't read %d bytes from cluster %d\n", size, id);
// original loop was a lot more complicated, more error handling and
// some calls to the music system, don't think we'll need that.
clusFile->close();
delete clusFile;
} else
_memMan->setCondition(memHandle, MEM_DONT_FREE);
memHandle->refCount++;
if (memHandle->refCount > 20) {
debug(1, "%d references to id %d. Guess there's something wrong.", memHandle->refCount, id);
}
}
void ResMan::resClose(uint32 id) {
BsMemHandle *handle = resHandle(id);
if (!handle->refCount) {
warning("Resource Manager fail: unlocking object with refCount 0. Id: %d\n", id);
} else
handle->refCount--;
if (!handle->refCount)
_memMan->setCondition( handle, MEM_CAN_FREE);
}
FrameHeader *ResMan::fetchFrame(void *resourceData, uint32 frameNo) {
uint8 *frameFile = (uint8*)resourceData;
uint8 *idxData = frameFile + sizeof(Header);
if (frameNo >= READ_LE_UINT32(idxData))
error("fetchFrame:: frame %d doesn't exist in resource.", frameNo);
frameFile += READ_LE_UINT32(idxData + (frameNo+1) * 4);
return (FrameHeader*)frameFile;
}
File *ResMan::openClusterFile(uint32 id) {
File *clusFile = new File();;
char fullPath[MAX_PATH_LEN];
char fileName[15];
makePathToCluster(fullPath);
sprintf(fileName, "%s.CLU", _prj.clu[(id >> 24)-1]->label);
clusFile->open(fileName);
if (!clusFile->isOpen())
error("Can't open cluster file %s in directory: %s\n", fileName, fullPath);
return clusFile;
}
BsMemHandle *ResMan::resHandle(uint32 id) {
uint8 cluster = (uint8)((id >> 24) - 1);
uint8 group = (uint8)(id >> 16);
return &(_prj.clu[cluster]->grp[group]->resHandle[id & 0xFFFF]);
}
uint32 ResMan::resLength(uint32 id) {
uint8 cluster = (uint8)((id >> 24) - 1);
uint8 group = (uint8)(id >> 16);
return _prj.clu[cluster]->grp[group]->length[id & 0xFFFF];
}
uint32 ResMan::resOffset(uint32 id) {
uint8 cluster = (uint8)((id >> 24) - 1);
uint8 group = (uint8)(id >> 16);
return _prj.clu[cluster]->grp[group]->offset[id & 0xFFFF];
}
void ResMan::makePathToCluster(char *str) {
*str = '\0';
// todo: add search stuff, cd1, cd2, etc.
}
void ResMan::openCptResourceBigEndian(uint32 id) {
resOpen(id);
BsMemHandle *handle = resHandle(id);
uint32 totSize = handle->size;
uint8 *data = ((uint8*)handle->data) + sizeof(Header);
totSize -= sizeof(Header);
uint32 numCpts = *(uint32*)data = READ_LE_UINT32(data);
data += 4;
uint32 *dataIdx = (uint32*)data;
for (uint32 cnt = 0; cnt < numCpts; cnt++) {
uint32 cptSize;
//uint32 cptPos = READ_LE_UINT32(data + cnt * 4);
uint32 cptPos = dataIdx[cnt] = READ_LE_UINT32(dataIdx + cnt);
if (cnt == numCpts-1)
cptSize = totSize - cptPos - 4;
else
cptSize = READ_LE_UINT32(data + (cnt + 1) * 4) - cptPos;
if (cptSize & 3)
error("Odd compact size during endian conversion. Resource ID = %d, Cpt = %d of %d, Size %d\n", id, cnt, numCpts, cptSize);
cptSize >>= 2;
uint32 *cptData = (uint32*)(data + cptPos);
for (uint32 elemCnt = 0; elemCnt < cptSize; elemCnt++)
cptData[elemCnt] = READ_LE_UINT32(cptData + elemCnt);
}
}
void ResMan::openScriptResourceBigEndian(uint32 id) {
resOpen(id);
BsMemHandle *handle = resHandle(id);
uint32 totSize = handle->size;
Header *head = (Header*)handle->data;
head->comp_length = FROM_LE_32(head->comp_length);
head->decomp_length = FROM_LE_32(head->decomp_length);
head->version = FROM_LE_16(head->version);
uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header));
uint32 size = handle->size - sizeof(Header);
if (size & 3)
error("Odd size during script endian conversion. Resource ID =%d, size = %d", id, size);
size >>= 2;
for (uint32 cnt = 0; cnt < size; cnt++) {
*data = READ_LE_UINT32(data);
data++;
}
}
--- NEW FILE: resman.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/resman.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef RESMAN_H
#define RESMAN_H
#include "memman.h"
#include "file.h"
#include "sworddefs.h"
#define MAX_LABEL_SIZE (31+1)
struct BsGrp {
uint32 noRes;
BsMemHandle *resHandle;
uint32 *offset;
uint32 *length;
};
struct BsClu {
char label[MAX_LABEL_SIZE];
uint32 noGrp;
BsGrp **grp;
};
struct BsPrj {
uint32 noClu;
BsClu **clu;
};
class ResMan {
public:
ResMan(const char *resFile, MemMan *pMemoMan);
~ResMan(void);
void resClose(uint32 id);
//void resOpen(uint32 id);
void resOpen(uint32 id);
void *fetchRes(uint32 id);
void dumpRes(uint32 id);
void *openFetchRes(uint32 id);
void *cptResOpen(uint32 id);
Header *lockScript(uint32 scrID);
void unlockScript(uint32 scrID);
FrameHeader *fetchFrame(void *resourceData, uint32 frameNo);
uint32 resLength(uint32 id); // this should be private. it's used in SwordSound for endian conversion, though
// make it private again when the mixer supports little endian data.
private:
BsMemHandle *resHandle(uint32 id);
uint32 resOffset(uint32 id);
void openCptResourceBigEndian(uint32 id);
void openScriptResourceBigEndian(uint32 id);
File *openClusterFile(uint32 id);
void makePathToCluster(char *str);
void loadCluDescript(const char *fileName);
void freeCluDescript(void);
BsPrj _prj;
MemMan *_memMan;
static const uint32 _scriptList[TOTAL_SECTIONS]; //a table of resource tags
};
#endif //RESMAN_H
--- NEW FILE: router.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) Revolution Software Ltd.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/router.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
[...1929 lines suppressed...]
else
tar_dir = 6;
} else if (slope == 2) { //vertical
if (signY == 1) // going down
tar_dir = 4;
else
tar_dir = 0;
} else if (signX == 1) { //right diagonal
if (signY == 1) // going down
tar_dir = 3;
else
tar_dir = 1;
} else { //left diagonal
if (signY == 1) // going down
tar_dir = 5;
else
tar_dir = 7;
}
return tar_dir;
}
--- NEW FILE: router.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) Revolution Software Ltd.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/router.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef BSROUTER_H
#define BSROUTER_H
#include "scummsys.h"
#include "object.h"
#define EXTRA_GRID_SIZE 20
#define O_GRID_SIZE 200
#if !defined(__GNUC__)
#pragma START_PACK_STRUCTS
#endif
struct BarData {
int16 x1;
int16 y1;
int16 x2;
int16 y2;
int16 xmin;
int16 ymin;
int16 xmax;
int16 ymax;
int16 dx; // x2 - x1
int16 dy; // y2 - y1
int32 co; // co = (y1 *dx)- (x1*dy) from an equation for a line y*dx = x*dy + co
} GCC_PACK;
struct NodeData {
int16 x;
int16 y;
int16 level;
int16 prev;
int16 dist;
} GCC_PACK;
#if !defined(__GNUC__)
#pragma END_PACK_STRUCTS
#endif
struct FloorData {
int32 nbars;
BarData *bars;
int32 nnodes;
NodeData *node;
};
struct RouteData {
int32 x;
int32 y;
int32 dirS;
int32 dirD;
};
struct PathData {
int32 x;
int32 y;
int32 dir;
int32 num;
};
struct FrameInfos {
int32 framesPerStep, framesPerChar;
int32 standFrames;
int32 slowInFrames, slowOutFrames;
int32 turnFramesLeft, turnFramesRight;
int32 walkFramesLeft, walkFramesRight;
uint16 startX, startY, targetX, targetY, targetDir;
int32 scaleA, scaleB;
};
#define ROUTE_END_FLAG 255
#define NO_DIRECTIONS 8
#define MAX_FRAMES_PER_CYCLE 16
#define MAX_FRAMES_PER_CHAR (MAX_FRAMES_PER_CYCLE * NO_DIRECTIONS)
#define O_ROUTE_SIZE 50
class ObjectMan;
class ResMan;
class SwordRouter {
public:
SwordRouter(ObjectMan *pObjMan, ResMan *pResMan);
~SwordRouter(void);
int routeFinder(int32 id, BsObject *mega, int32 x, int32 y, int32 dir);
int whatTarget(int32 startX, int32 startY, int32 destX, int32 destY);
void setPlayerTarget(int32 x, int32 y, int32 dir, int32 stance);
void resetExtraData(void);
// these should be private but are read by SwordScreen for debugging:
int32 _nBars, _nNodes;
BarData _bars[O_GRID_SIZE + EXTRA_GRID_SIZE];
NodeData _node[O_GRID_SIZE + EXTRA_GRID_SIZE];
private:
// when the player collides with another mega, we'll receive a ReRouteRequest here.
// that's why we need to remember the player's target coordinates
int32 _playerTargetX, _playerTargetY, _playerTargetDir, _playerTargetStance;
// additional route data to block parts of the floor and enable routine around megas:
int32 _numExtraBars, _numExtraNodes;
BarData _extraBars[EXTRA_GRID_SIZE];
NodeData _extraNodes[EXTRA_GRID_SIZE];
ObjectMan *_objMan;
ResMan *_resMan;
uint8 _nWalkFrames, _nTurnFrames;
int32 _dx[NO_DIRECTIONS + MAX_FRAMES_PER_CHAR];
int32 _dy[NO_DIRECTIONS + MAX_FRAMES_PER_CHAR];
int32 _modX[NO_DIRECTIONS];
int32 _modY[NO_DIRECTIONS];
int32 _diagonalx, _diagonaly;
RouteData _route[O_ROUTE_SIZE];
//int32 _routeLength;
PathData _smoothPath[O_ROUTE_SIZE];
PathData _modularPath[O_ROUTE_SIZE];
void loadWalkResources(int32 megaId, BsObject *mega, int32 x, int32 y, int32 targetDir);
int getRoute(void);
int checkTarget(int16 x, int16 y);
int scan(int32 level);
int newCheck(int32 status, int16 x1, int16 x2, int16 y1, int16 y2);
int check(int16 x1, int16 y1, int16 x2, int16 y2);
int horizCheck(int16 x1, int16 y, int16 x2);
int vertCheck(int16 x, int16 y1, int16 y2);
int lineCheck(int16 x1, int16 y1, int16 x2, int16 y2);
int32 extractRoute(int32 targetDir);
void slidyPath(int32 scaleA, int32 scaleB, uint16 targetDir);
void slidyWalkAnimator(WalkData *walkAnim, FrameInfos *frInfo, int32 megaId);
int32 smoothestPath(uint16 startX, uint16 startY, uint16 startDir, int32 routeLength);
int32 smoothCheck(int32 best, int32 p, int32 dirS, int32 dirD);
int32 solidPath(int32 scaleA, int32 scaleB);
int32 solidWalkAnimator(WalkData *walkAnim, FrameInfos *frInfo, int32 megaId);
};
#endif //BSROUTER_H
--- NEW FILE: screen.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/screen.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "screen.h"
#include "logic.h"
#include "sworddefs.h"
#include "text.h"
#include "resman.h"
#include "objectman.h"
#include "scummsys.h"
#include "common/util.h"
#include "system.h"
#include "router.h"
#define SCROLL_FRACTION 16
#define MAX_SCROLL_DISTANCE 8
#define FADE_UP 1
#define FADE_DOWN -1
SwordScreen::SwordScreen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
_system = system;
_resMan = pResMan;
_objMan = pObjMan;
_screenBuf = _screenGrid = NULL;
_backLength = _foreLength = _sortLength = 0;
_fadingStep = 0;
}
void SwordScreen::useTextManager(SwordText *pTextMan) {
_textMan = pTextMan;
}
int32 SwordScreen::inRange(int32 a, int32 b, int32 c) { // return b(!) so that: a <= b <= c
return (a > b) ? (a) : ((b < c) ? b : c);
}
void SwordScreen::setScrolling(int16 offsetX, int16 offsetY) {
if (!SwordLogic::_scriptVars[SCROLL_FLAG])
return ; // screen is smaller than 640x400 => no need for scrolling
int32 dx, dy;
uint32 scrlDistX, scrlDistY;
uint32 scrlToX, scrlToY;
offsetX = inRange(0, offsetX, SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_X]);
offsetY = inRange(0, offsetY, SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_Y]);
_oldScrollX = SwordLogic::_scriptVars[SCROLL_OFFSET_X];
_oldScrollY = SwordLogic::_scriptVars[SCROLL_OFFSET_Y];
if (SwordLogic::_scriptVars[SCROLL_FLAG] == 2) { // first time on this screen - need absolute scroll immediately!
scrlToX = (uint32)offsetX;
scrlToY = (uint32)offsetY;
} else { // catch up with required scroll offsets - speed depending on distance to catch up (dx and dy) & 'SCROLL_FRACTION' used
// but limit to certain number of pixels per cycle (MAX_SCROLL_DISTANCE)
dx = SwordLogic::_scriptVars[SCROLL_OFFSET_X] - offsetX;
dy = SwordLogic::_scriptVars[SCROLL_OFFSET_Y] - offsetY;
int8 sig = (dx < 0) ? (-1) : 1;
if (dx < 0)
dx = -dx;
scrlDistX = 1 + dx/SCROLL_FRACTION;
scrlDistX = inRange(0, scrlDistX, MAX_SCROLL_DISTANCE);
scrlToX = SwordLogic::_scriptVars[SCROLL_OFFSET_X] + sig * scrlDistX;
sig = (dy < 0) ? (-1) : 1;
if (dy < 0)
dy = -dy;
scrlDistY = 1 + dy/SCROLL_FRACTION;
scrlDistY = inRange(0, scrlDistY, MAX_SCROLL_DISTANCE);
scrlToY = SwordLogic::_scriptVars[SCROLL_OFFSET_Y] + sig * scrlDistY;
}
scrlToX = inRange(0, scrlToX, SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_X]);
scrlToY = inRange(0, scrlToY, SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_Y]);
if ((scrlToX != SwordLogic::_scriptVars[SCROLL_OFFSET_X]) || (scrlToY != SwordLogic::_scriptVars[SCROLL_OFFSET_Y])) {
_fullRefresh = true;
SwordLogic::_scriptVars[SCROLL_OFFSET_X] = scrlToX;
SwordLogic::_scriptVars[SCROLL_OFFSET_Y] = scrlToY;
} else
_fullRefresh = false;
if (SwordLogic::_scriptVars[SCROLL_FLAG] == 2) {
_oldScrollX = scrlToX;
_oldScrollY = scrlToY;
SwordLogic::_scriptVars[SCROLL_FLAG] = 1;
}
}
void SwordScreen::fadeDownPalette(void) {
_fadingStep = 15;
_fadingDirection = FADE_DOWN;
}
void SwordScreen::fadeUpPalette(void) {
_fadingStep = 15;
_fadingDirection = FADE_UP;
}
void SwordScreen::fnSetPalette(uint8 start, uint16 length, uint8 *data) {
memcpy(_targetPalette + start * 3, data, length * 3);
_system->set_palette(data, start, length);
}
void SwordScreen::fnSetFadeTargetPalette(uint8 start, uint16 length, uint8 *data) {
memcpy(_targetPalette + start * 3, data, length * 3);
debug(1, "fnSetFadeTargetPalette called");
}
bool SwordScreen::stillFading(void) {
return (_fadingStep > 0);
}
void SwordScreen::updateScreen(void) {
if (SwordLogic::_scriptVars[NEW_PALETTE]) {
_fadingStep = 1;
_fadingDirection = FADE_UP;
memcpy(_targetPalette, _resMan->openFetchRes(_roomDefTable[_currentScreen].palettes[0]), 184 * 3); // set colours 0-183 for background palette
_resMan->resClose(_roomDefTable[_currentScreen].palettes[0]);
memcpy(_targetPalette + 184 * 3, _resMan->openFetchRes(_roomDefTable[_currentScreen].palettes[1]), 72 * 3); // set colours 184-255 for sprite palette - george, icons & menubar
_resMan->resClose(_roomDefTable[_currentScreen].palettes[1]);
SwordLogic::_scriptVars[NEW_PALETTE] = 0;
}
if (_fadingStep) {
fadePalette();
_system->set_palette(_currentPalette, 0, 256);
}
uint16 scrlX = (uint16)SwordLogic::_scriptVars[SCROLL_OFFSET_X];
uint16 scrlY = (uint16)SwordLogic::_scriptVars[SCROLL_OFFSET_Y];
_fullRefresh = true;
if (_fullRefresh) {
_fullRefresh = false;
uint16 copyWidth = SCREEN_WIDTH;
uint16 copyHeight = SCREEN_DEPTH;
if (scrlX + copyWidth > _scrnSizeX)
copyWidth = _scrnSizeX - scrlX;
if (scrlY + copyHeight > _scrnSizeY)
copyHeight = _scrnSizeY - scrlY;
_system->copy_rect(_screenBuf + scrlY * _scrnSizeX + scrlX, _scrnSizeX, 0, 40, copyWidth, copyHeight);
} else {
// partial screen update only. The screen coordinates probably won't fit to the
// grid holding the informations on which blocks have to be updated.
// as the grid will be X pixel higher and Y pixel more to the left, this can be cured
// by first checking the top border, then the left column and then the remaining (aligned) part.
uint8 *gridPos = _screenGrid + (scrlX / SCRNGRID_X) + (scrlY / SCRNGRID_Y) * _gridSizeX;
uint8 *scrnBuf = _screenBuf + scrlY * _scrnSizeX + scrlX;
uint8 diffX = (uint8)(scrlX % SCRNGRID_X);
uint8 diffY = (uint8)(scrlY % SCRNGRID_Y);
uint16 gridW = SCREEN_WIDTH / SCRNGRID_X;
uint16 gridH = SCREEN_DEPTH / SCRNGRID_Y;
if (diffY) {
uint8 cpHeight = SCRNGRID_Y - diffY;
uint16 cpWidth = 0;
for (uint16 cntx = 0; cntx < gridW; cntx++)
if (gridPos[cntx] & 1) {
gridPos[cntx] &= ~1;
cpWidth++;
} else if (cpWidth) {
int16 xPos = (cntx - cpWidth) * SCRNGRID_X - diffX;
if (xPos < 0)
xPos = 0;
_system->copy_rect(scrnBuf + xPos, _scrnSizeX, xPos, 40, cpWidth * SCRNGRID_X, cpHeight);
cpWidth = 0;
}
if (cpWidth) {
int16 xPos = (gridW - cpWidth) * SCRNGRID_X - diffX;
if (xPos < 0)
xPos = 0;
_system->copy_rect(scrnBuf + xPos, _scrnSizeX, xPos, 40, SCREEN_WIDTH - xPos, cpHeight);
}
} // okay, y scrolling is compensated. check x now.
gridPos += _gridSizeX;
scrnBuf = _screenBuf + scrlX + diffY * _scrnSizeX;
if (diffX) {
uint8 cpWidth = SCRNGRID_X - diffX;
uint16 cpHeight = 0;
for (uint16 cnty = 0; cnty < gridH; cnty++)
if (gridPos[cnty * SCRNGRID_X] & 1) {
gridPos[cnty * SCRNGRID_X] &= ~1;
cpHeight++;
} else if (cpHeight) {
uint16 yPos = (cnty - cpHeight) * SCRNGRID_Y;
_system->copy_rect(scrnBuf + yPos * _scrnSizeX, _scrnSizeX, 0, yPos + diffY + 40, cpWidth, cpHeight * SCRNGRID_Y);
}
if (cpHeight) {
uint16 yPos = (gridH - cpHeight) * SCRNGRID_Y;
_system->copy_rect(scrnBuf + yPos * _scrnSizeX, _scrnSizeX, 0, yPos + diffY + 40, cpWidth, SCREEN_DEPTH - (yPos + diffY));
}
} // x scroll is compensated, too. check the rest of the screen, now.
scrlX = (scrlX + SCRNGRID_X - 1) &~ (SCRNGRID_X - 1);
scrlY = (scrlY + SCRNGRID_Y - 1) &~ (SCRNGRID_Y - 1);
scrnBuf = _screenBuf + scrlY * _scrnSizeX + scrlX;
gridPos++;
for (uint16 cnty = 0; cnty < gridH; cnty++) {
uint16 cpWidth = 0;
uint16 cpHeight = SCRNGRID_Y;
if (cnty == gridH - 1)
cpHeight = SCRNGRID_Y - diffY;
for (uint16 cntx = 0; cntx < gridW; cntx++)
if (gridPos[cntx] & 1) {
gridPos[cntx] &= ~1;
cpWidth++;
} else if (cpWidth) {
_system->copy_rect(scrnBuf + (cntx - cpWidth) * SCRNGRID_X, _scrnSizeX, (cntx - cpWidth) * SCRNGRID_X + diffX, cnty * SCRNGRID_Y + diffY + 40, cpWidth * SCRNGRID_X, cpHeight);
}
if (cpWidth) {
uint16 xPos = (gridW - cpWidth) * SCRNGRID_X;
_system->copy_rect(scrnBuf + xPos, _scrnSizeX, xPos + diffX, cnty * SCRNGRID_Y + diffY + 40, SCREEN_WIDTH - (xPos + diffX), cpHeight);
}
gridPos += _gridSizeX;
scrnBuf += _scrnSizeX * SCRNGRID_Y;
}
}
_system->update_screen();
}
void SwordScreen::newScreen(uint32 screen) {
// set sizes and scrolling, initialize/load screengrid, force screen refresh
// force palette fadeup?
_currentScreen = screen;
_scrnSizeX = _roomDefTable[screen].sizeX;
_scrnSizeY = _roomDefTable[screen].sizeY;
_gridSizeX = _scrnSizeX / SCRNGRID_X;
_gridSizeY = _scrnSizeY / SCRNGRID_Y;
if ((_scrnSizeX % SCRNGRID_X) || (_scrnSizeY % SCRNGRID_Y))
error("Illegal screensize: %d: %d/%d", screen, _scrnSizeX, _scrnSizeY);
if ((_scrnSizeX > SCREEN_WIDTH) || (_scrnSizeY > SCREEN_DEPTH)) {
SwordLogic::_scriptVars[SCROLL_FLAG] = 2;
SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_X] = _scrnSizeX - SCREEN_WIDTH;
SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_Y] = _scrnSizeY - SCREEN_DEPTH;
} else {
SwordLogic::_scriptVars[SCROLL_FLAG] = 0;
SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_X] = 0;
SwordLogic::_scriptVars[MAX_SCROLL_OFFSET_Y] = 0;
SwordLogic::_scriptVars[SCROLL_OFFSET_X] = 0;
SwordLogic::_scriptVars[SCROLL_OFFSET_Y] = 0;
}
_screenBuf = (uint8*)malloc(_scrnSizeX * _scrnSizeY);
_screenGrid = (uint8*)malloc(_gridSizeX * _gridSizeY);
memset(_screenGrid, 0x80, _gridSizeX * _gridSizeY); // force refresh
for (uint8 cnt = 0; cnt < _roomDefTable[_currentScreen].totalLayers; cnt++) {
// open and lock all resources, will be closed in closeScreen()
_layerBlocks[cnt] = (uint8*)_resMan->openFetchRes(_roomDefTable[_currentScreen].layers[cnt]);
}
for (uint8 cnt = 0; cnt < _roomDefTable[_currentScreen].totalLayers - 1; cnt++) {
// there's no grid for the background layer, so it's totalLayers - 1
_layerGrid[cnt] = (uint16*)_resMan->openFetchRes(_roomDefTable[_currentScreen].grids[cnt]);
_layerGrid[cnt] += 0x12; // not sure about the 0x12
}
_parallax[0] = _parallax[1] = NULL;
if (_roomDefTable[_currentScreen].parallax[0])
_parallax[0] = (uint8*)_resMan->openFetchRes(_roomDefTable[_currentScreen].parallax[0]);
if (_roomDefTable[_currentScreen].parallax[1])
_parallax[1] = (uint8*)_resMan->openFetchRes(_roomDefTable[_currentScreen].parallax[1]);
// TEMPORARY!
uint8 *bgPal = (uint8*)_resMan->openFetchRes(_roomDefTable[_currentScreen].palettes[0]);
uint8 *sprPal = (uint8*)_resMan->openFetchRes(_roomDefTable[_currentScreen].palettes[1]);
for (uint16 cnt = 0; cnt < 256; cnt++) {
_targetPalette[cnt * 4 + 0] = bgPal[cnt * 3 + 0] << 2;
_targetPalette[cnt * 4 + 1] = bgPal[cnt * 3 + 1] << 2;
_targetPalette[cnt * 4 + 2] = bgPal[cnt * 3 + 2] << 2;
}
/*for (uint16 cnt = 0; cnt < 72; cnt++) {
_targetPalette[(cnt + 184) * 4 + 0] = bgPal[cnt * 3 + 0];
_targetPalette[(cnt + 184) * 4 + 1] = bgPal[cnt * 3 + 1];
_targetPalette[(cnt + 184) * 4 + 2] = bgPal[cnt * 3 + 2];
}*/
_targetPalette[0] = _targetPalette[1] = _targetPalette[2] = 0;
_system->set_palette(_targetPalette, 0, 256);
_resMan->resClose(_roomDefTable[_currentScreen].palettes[0]);
_resMan->resClose(_roomDefTable[_currentScreen].palettes[1]);
}
void SwordScreen::quitScreen(void) {
for (uint8 cnt = 0; cnt < _roomDefTable[_currentScreen].totalLayers; cnt++)
_resMan->resClose(_roomDefTable[_currentScreen].layers[cnt]);
for (uint8 cnt = 0; cnt < _roomDefTable[_currentScreen].totalLayers - 1; cnt++)
_resMan->resClose(_roomDefTable[_currentScreen].grids[cnt]);
if (_roomDefTable[_currentScreen].parallax[0])
_resMan->resClose(_roomDefTable[_currentScreen].parallax[0]);
if (_roomDefTable[_currentScreen].parallax[1])
_resMan->resClose(_roomDefTable[_currentScreen].parallax[1]);
}
void SwordScreen::recreate() {
memcpy(_screenBuf, _layerBlocks[0], _scrnSizeX * _scrnSizeY);
}
void SwordScreen::spritesAndParallax(void) {
if ((_currentScreen == 54) && _parallax[0])
renderParallax(_parallax[0]); // rm54 has a BACKGROUND parallax layer in parallax[0]
for (uint8 cnt = 0; cnt < _backLength; cnt++)
processImage(_backList[cnt]);
SortSpr temp;
for (uint8 cnt = 0; cnt < _sortLength - 1; cnt++)
for (uint8 sCnt = 0; sCnt < _sortLength - 1; sCnt++)
if (_sortList[sCnt].y > _sortList[sCnt + 1].y) {
temp = _sortList[sCnt];
_sortList[sCnt] = _sortList[sCnt + 1];
_sortList[sCnt + 1] = temp;
}
for (uint8 cnt = 0; cnt < _sortLength; cnt++)
processImage(_sortList[cnt].id);
if ((_currentScreen != 54) && _parallax[0])
renderParallax(_parallax[0]); // screens other than 54 have FOREGROUND parallax layer in parallax[0]
if (_parallax[1])
renderParallax(_parallax[1]);
for (uint8 cnt = 0; cnt < _foreLength; cnt++)
processImage(_foreList[cnt]);
_backLength = _sortLength = _foreLength = 0;
}
void SwordScreen::processImage(uint32 id) {
BsObject *compact;
FrameHeader *frameHead;
int scale;
compact = _objMan->fetchObject(id);
if (compact->o_type == TYPE_TEXT)
frameHead = _textMan->giveSpriteData((uint8)compact->o_target);
else
frameHead = _resMan->fetchFrame(_resMan->openFetchRes(compact->o_resource), compact->o_frame);
uint8 *sprData = ((uint8*)frameHead) + sizeof(FrameHeader);
uint16 spriteX = compact->o_anim_x;
uint16 spriteY = compact->o_anim_y;
if (compact->o_status & STAT_SHRINK) {
scale = (compact->o_scale_a * compact->o_ycoord + compact->o_scale_b) / 256;
spriteX += (FROM_LE_16(frameHead->offsetX) * scale) / 256;
spriteY += (FROM_LE_16(frameHead->offsetY) * scale) / 256;
} else {
scale = 256;
spriteX += FROM_LE_16(frameHead->offsetX);
spriteY += FROM_LE_16(frameHead->offsetY);
}
if (scale > 512)
debug(1, "compact %d is oversized: scale = %d", id, scale);
uint8 *tonyBuf = NULL;
if (frameHead->runTimeComp[3] == '7') { // RLE7 encoded?
decompressRLE7(sprData, FROM_LE_32(frameHead->compSize), _rleBuffer);
sprData = _rleBuffer;
} else if (frameHead->runTimeComp[3] == '0') { // RLE0 encoded?
decompressRLE0(sprData, FROM_LE_32(frameHead->compSize), _rleBuffer, FROM_LE_16(frameHead->width));
sprData = _rleBuffer;
} else if (frameHead->runTimeComp[1] == 'I') { // new type
tonyBuf = (uint8*)malloc(FROM_LE_16(frameHead->width) * FROM_LE_16(frameHead->height));
decompressTony(sprData, FROM_LE_32(frameHead->compSize), tonyBuf);
sprData = tonyBuf;
}
uint16 sprSizeX, sprSizeY;
if (compact->o_status & STAT_SHRINK) {
sprSizeX = (scale * FROM_LE_16(frameHead->width)) / 256;
sprSizeY = (scale * FROM_LE_16(frameHead->height)) / 256;
fastShrink(sprData, FROM_LE_16(frameHead->width), FROM_LE_16(frameHead->height), scale, _shrinkBuffer);
sprData = _shrinkBuffer;
} else {
sprSizeX = FROM_LE_16(frameHead->width);
sprSizeY = FROM_LE_16(frameHead->height);
}
if (!(compact->o_status & STAT_OVERRIDE)) {
//mouse size linked to exact size & coordinates of sprite box - shrink friendly
if ((frameHead->offsetX) || (frameHead->offsetY)) {
//for megas the mouse area is reduced to account for sprite not
//filling the box size is reduced to 1/2 width, 4/5 height
compact->o_mouse_x1 = spriteX + sprSizeX / 4;
compact->o_mouse_x2 = spriteX + (3 * sprSizeX) / 4;
compact->o_mouse_y1 = spriteY + sprSizeY / 10;
compact->o_mouse_y2 = spriteY + (9 * sprSizeY) / 10;
} else {
compact->o_mouse_x1 = spriteX;
compact->o_mouse_x2 = spriteX + sprSizeX;
compact->o_mouse_y1 = spriteY;
compact->o_mouse_y2 = spriteY + sprSizeY;
}
}
uint16 sprPitch = sprSizeX;
uint16 incr;
spriteClipAndSet(&spriteX, &spriteY, &sprSizeX, &sprSizeY, &incr);
if ((sprSizeX > 0) && (sprSizeY > 0)) {
drawSprite(sprData + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch);
if (!(compact->o_status&STAT_FORE))
verticalMask(spriteX, spriteY, sprSizeX, sprSizeY);
}
if (compact->o_type != TYPE_TEXT)
_resMan->resClose(compact->o_resource);
if (tonyBuf)
free(tonyBuf);
}
void SwordScreen::verticalMask(uint16 x, uint16 y, uint16 bWidth, uint16 bHeight) {
if (_roomDefTable[_currentScreen].totalLayers <= 1)
return;
bWidth = (bWidth + (SCRNGRID_X - 1)) / SCRNGRID_X;
bHeight = (bHeight + (SCRNGRID_Y - 1)) / SCRNGRID_Y;
if (x & (SCRNGRID_X - 1))
bWidth++;
if (y & (SCRNGRID_Y - 1))
bHeight++;
x /= SCRNGRID_X;
y /= SCRNGRID_Y;
if (x + bWidth > _gridSizeX)
bWidth = _gridSizeX - x;
if (y + bHeight > _gridSizeY)
bHeight = _gridSizeY - y;
for (uint16 blkx = 0; blkx < bWidth; blkx++) {
for (uint8 z = 1; z < _roomDefTable[_currentScreen].totalLayers; z++) { // current layer
uint16 *grid = _layerGrid[z - 1] + x + blkx + y * _gridSizeX;
for (uint16 blky = 0; blky < bHeight; blky++) {
if (*grid) {
uint8 *blkData = _layerBlocks[z] + (READ_LE_UINT16(grid) - 1) * 128;
blitBlockClear(x + blkx, y + blky, blkData);
}
grid += _gridSizeX;
}
}
}
}
void SwordScreen::blitBlockClear(uint16 x, uint16 y, uint8 *data) {
uint8 *dest = _screenBuf + (y * SCRNGRID_Y) * _scrnSizeX + (x * SCRNGRID_X);
for (uint8 cnty = 0; cnty < SCRNGRID_Y; cnty++) {
for (uint8 cntx = 0; cntx < SCRNGRID_X; cntx++)
if (data[cntx])
dest[cntx] = data[cntx];
data += SCRNGRID_X;
dest += _scrnSizeX;
}
}
void SwordScreen::renderParallax(uint8 *data) {
ParallaxHeader *header = (ParallaxHeader*)data;
assert((FROM_LE_16(header->sizeX) >= SCREEN_WIDTH) && (FROM_LE_16(header->sizeY) >= SCREEN_DEPTH));
double scrlfx = FROM_LE_16(header->sizeX) / ((double)_scrnSizeX );
double scrlfy = FROM_LE_16(header->sizeY) / ((double)_scrnSizeY );
uint16 scrlX = (uint16)(SwordLogic::_scriptVars[SCROLL_OFFSET_X] * scrlfx);
uint16 scrlY = (uint16)(SwordLogic::_scriptVars[SCROLL_OFFSET_Y] * scrlfy);
for (uint16 cnty = 0; cnty < SCREEN_DEPTH; cnty++) {
uint8 *src = data + READ_LE_UINT32(header->lineIndexes + cnty + scrlY);
uint8 *dest = _screenBuf + SwordLogic::_scriptVars[SCROLL_OFFSET_X] + cnty * _scrnSizeX;
uint16 remain = scrlX;
uint16 xPos = 0;
bool copyFirst = false;
while (remain) { // skip past the first part of the parallax to get to the right scrolling position
uint8 doSkip = *src++;
if (doSkip <= remain)
remain -= doSkip;
else {
xPos = doSkip - remain;
dest += xPos;
remain = 0;
}
if (remain) {
uint8 doCopy = *src++;
if (doCopy <= remain) {
remain -= doCopy;
src += doCopy;
} else {
uint16 remCopy = doCopy - remain;
memcpy(dest, src + remain, remCopy);
dest += remCopy;
src += doCopy;
xPos = remCopy;
remain = 0;
}
} else
copyFirst = true;
}
while (xPos < SCREEN_WIDTH) {
if (!copyFirst) {
if (uint8 skip = *src++) {
dest += skip;
xPos += skip;
}
} else
copyFirst = false;
if (xPos < SCREEN_WIDTH) {
if (uint8 doCopy = *src++) {
if (xPos + doCopy > SCREEN_WIDTH)
doCopy = SCREEN_WIDTH - xPos;
memcpy(dest, src, doCopy);
dest += doCopy;
xPos += doCopy;
src += doCopy;
}
}
}
}
}
void SwordScreen::drawSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch) {
uint8 *dest = _screenBuf + (sprY * _scrnSizeX) + sprX;
for (uint16 cnty = 0; cnty < sprHeight; cnty++) {
for (uint16 cntx = 0; cntx < sprWidth; cntx++)
if (sprData[cntx])
dest[cntx] = sprData[cntx];
sprData += sprPitch;
dest += _scrnSizeX;
}
}
// nearest neighbor filter:
void SwordScreen::fastShrink(uint8 *src, uint32 width, uint32 height, uint32 scale, uint8 *dest) {
uint32 resHeight = (height * scale) >> 8;
uint32 resWidth = (width * scale) >> 8;
uint32 step = 0x10000 / scale;
uint8 columnTab[160];
uint32 res = step >> 1;
for (uint16 cnt = 0; cnt < resWidth; cnt++) {
columnTab[cnt] = (uint8)(res >> 8);
res += step;
}
uint32 newRow = step >> 1;
uint32 oldRow = 0;
uint8 *destPos = dest;
for (uint16 lnCnt = 0; lnCnt < resHeight; lnCnt++) {
while (oldRow < (newRow >> 8)) {
oldRow++;
src += width;
}
for (uint16 colCnt = 0; colCnt < resWidth; colCnt++) {
*destPos++ = src[columnTab[colCnt]];
}
newRow += step;
}
// scaled, now stipple shadows if there are any
for (uint16 lnCnt = 0; lnCnt < resHeight; lnCnt++) {
uint16 xCnt = lnCnt & 1;
destPos = dest + lnCnt * resWidth + (lnCnt & 1);
while (xCnt < resWidth) {
if (*destPos == 200)
*destPos = 0;
destPos += 2;
xCnt += 2;
}
}
}
void SwordScreen::addToGraphicList(uint8 listId, uint32 objId) {
if (listId == 0) {
_foreList[_foreLength++] = objId;
if (_foreLength > MAX_FORE)
error("foreList exceeded!");
}
if (listId == 1) {
BsObject *cpt = _objMan->fetchObject(objId);
_sortList[_sortLength].id = objId;
_sortList[_sortLength].y = cpt->o_anim_y; // gives feet coords if boxed mega, otherwise top of sprite box
if (!(cpt->o_status & STAT_SHRINK)) { // not a boxed mega using shrinking
Header *frameRaw = (Header*)_resMan->openFetchRes(cpt->o_resource);
FrameHeader *frameHead = _resMan->fetchFrame(frameRaw, cpt->o_frame);
_sortList[_sortLength].y += frameHead->height - 1; // now pointing to base of sprite
_resMan->resClose(cpt->o_resource);
}
_sortLength++;
if (_sortLength > MAX_SORT)
error("sortList exceeded!");
}
if (listId == 2) {
_backList[_backLength++] = objId;
if (_backLength > MAX_BACK)
error("backList exceeded!");
}
}
void SwordScreen::decompressTony(uint8 *src, uint32 compSize, uint8 *dest) {
uint8 *endOfData = src + compSize;
while (src < endOfData) {
uint8 numFlat = *src++;
if (numFlat) {
memset(dest, *src, numFlat);
src++;
dest += numFlat;
}
if (src < endOfData) {
uint8 numNoFlat = *src++;
memcpy(dest, src, numNoFlat);
src += numNoFlat;
dest += numNoFlat;
}
}
}
void SwordScreen::decompressRLE7(uint8 *src, uint32 compSize, uint8 *dest) {
uint8 *compBufEnd = src + compSize;
while (src < compBufEnd) {
uint8 code = *src++;
if ((code > 127) || (code == 0))
*dest++ = code;
else {
code++;
memset(dest, *src++, code);
dest += code;
}
}
}
void SwordScreen::decompressRLE0(uint8 *src, uint32 compSize, uint8 *dest, uint16 width) {
// these are saved vertically flipped. *SIIIIIIIGH*
uint8 *srcBufEnd = src + compSize;
uint16 destX = width-1;
while (src < srcBufEnd) {
uint8 color = *src++;
if (color) {
dest[destX] = color;
if (destX == 0) {
destX = width-1;
dest += width;
} else
destX--;
} else {
uint8 skip = *src++;
for (uint16 cnt = 0; cnt < skip; cnt++) {
dest[destX] = 0;
if (destX == 0) {
destX = width-1;
dest += width;
} else
destX--;
}
}
}
}
void SwordScreen::fadePalette(void) {
if (_fadingStep == 16)
memcpy(_currentPalette, _targetPalette, 256 * 4);
else
for (uint16 cnt = 0; cnt < 256 * 4; cnt++)
_currentPalette[cnt] = (_targetPalette[cnt] * _fadingStep) >> 4;
_fadingStep += _fadingDirection;
if (_fadingStep == 17)
_fadingStep = 0;
}
void SwordScreen::fnSetParallax(uint32 screen, uint32 resId) {
if ((screen == _currentScreen) && (resId != _roomDefTable[screen].parallax[0]))
warning("fnSetParallax: setting parallax for current room!!");
_roomDefTable[screen].parallax[0] = resId;
}
void SwordScreen::spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *pSprWidth, uint16 *pSprHeight, uint16 *incr) {
int16 sprX = *pSprX - SCREEN_LEFT_EDGE;
int16 sprY = *pSprY - SCREEN_TOP_EDGE;
int16 sprW = *pSprWidth;
int16 sprH = *pSprHeight;
if (sprY < 0) {
*incr = (uint16)((-sprY) * sprW);
sprH += sprY;
sprY = 0;
} else
*incr = 0;
if (sprX < 0) {
*incr -= sprX;
sprW += sprX;
sprX = 0;
}
if (sprY + sprH > _scrnSizeY)
sprH = _scrnSizeY - sprY;
if (sprX + sprW > _scrnSizeX)
sprW = _scrnSizeX - sprX;
if (sprH < 0)
*pSprHeight = 0;
else
*pSprHeight = (uint16)sprH;
if (sprW < 0)
*pSprWidth = 0;
else
*pSprWidth = (uint16)sprW;
*pSprX = (uint16)sprX;
*pSprY = (uint16)sprY;
uint16 gridH = (*pSprHeight + SCRNGRID_Y - 1) / SCRNGRID_Y;
uint16 gridW = (*pSprWidth + SCRNGRID_X - 1) / SCRNGRID_X;
uint16 gridX = sprX / SCRNGRID_X;
uint16 gridY = sprY / SCRNGRID_Y;
uint8 *gridBuf = _screenGrid + gridX + gridY * _gridSizeX;
if (gridX + gridW > _gridSizeX)
gridW = _gridSizeX - gridX;
if (gridY + gridH > _gridSizeY)
gridH = _gridSizeY - gridY;
for (uint16 cnty = 0; cnty < gridH; cnty++) {
for (uint16 cntx = 0; cntx < gridW; cntx++)
gridBuf[cntx] |= 0x80;
gridBuf += _gridSizeX;
}
}
void SwordScreen::showFrame(uint16 x, uint16 y, uint32 resId, uint32 frameNo) {
warning("stub: SwordScreen::showFrame(%d, %d, %d, %d)", x, y, resId, frameNo);
}
void SwordScreen::fnFlash(uint8 color) {
warning("stub: SwordScreen::fnFlash(%d)", color);
}
// ------------------- router debugging code --------------------------------
void SwordScreen::vline(uint16 x, uint16 y1, uint16 y2) {
for (uint16 cnty = y1; cnty <= y2; cnty++)
_screenBuf[x + _scrnSizeX * cnty] = 0;
}
void SwordScreen::hline(uint16 x1, uint16 x2, uint16 y) {
for (uint16 cntx = x1; cntx <= x2; cntx++)
_screenBuf[y * _scrnSizeX + cntx] = 0;
}
void SwordScreen::bsubline_1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int x, y, ddx, ddy, e;
ddx = abs(x2 - x1);
ddy = abs(y2 - y1) << 1;
e = ddx - ddy;
ddx <<= 1;
if (x1 > x2) {
uint16 tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
for (x = x1, y = y1; x <= x2; x++) {
_screenBuf[y * _scrnSizeX + x] = 0;
if (e < 0) {
y++;
e += ddx - ddy;
} else {
e -= ddy;
}
}
}
void SwordScreen::bsubline_2(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int x, y, ddx, ddy, e;
ddx = abs(x2 - x1) << 1;
ddy = abs(y2 - y1);
e = ddy - ddx;
ddy <<= 1;
if (y1 > y2) {
uint16 tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
for (y = y1, x = x1; y <= y2; y++) {
_screenBuf[y * _scrnSizeX + x] = 0;
if (e < 0) {
x++;
e += ddy - ddx;
} else {
e -= ddx;
}
}
}
void SwordScreen::bsubline_3(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int x, y, ddx, ddy, e;
ddx = abs(x1 - x2) << 1;
ddy = abs(y2 - y1);
e = ddy - ddx;
ddy <<= 1;
if (y1 > y2) {
uint16 tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
for (y = y1, x = x1; y <= y2; y++) {
_screenBuf[y * _scrnSizeX + x] = 0;
if (e < 0) {
x--;
e += ddy - ddx;
} else {
e -= ddx;
}
}
}
void SwordScreen::bsubline_4(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int x, y, ddx, ddy, e;
ddy = abs(y2 - y1) << 1;
ddx = abs(x1 - x2);
e = ddx - ddy;
ddx <<= 1;
if (x1 > x2) {
uint16 tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
for (x = x1, y = y1; x <= x2; x++) {
_screenBuf[y * _scrnSizeX + x] = 0;
if (e < 0) {
y--;
e += ddx - ddy;
} else {
e -= ddy;
}
}
}
void SwordScreen::drawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
if ((x1 == x2) && (y1 == y2)) {
_screenBuf[x1 + y1 * _scrnSizeX] = 0;
}
if (x1 == x2) {
vline(x1, min(y1, y2), max(y1, y2));
return;
}
if (y1 == y2) {
hline(min(x1, x2), max(x1, x2), y1);
return;
}
float k = float(y2 - y1) / float(x2 - x1);
if ((k >= 0) && (k <= 1)) {
bsubline_1(x1, y1, x2, y2);
} else if (k > 1) {
bsubline_2(x1, y1, x2, y2);
} else if ((k < 0) && (k >= -1)) {
bsubline_4(x1, y1, x2, y2);
} else {
bsubline_3(x1, y1, x2, y2);
}
}
void SwordScreen::showBarsAndNodes(SwordRouter *router) {
for (uint16 cnt = 0; cnt < router->_nBars; cnt++) {
drawLine(router->_bars[cnt].x1 - 128, router->_bars[cnt].y1 - 128, router->_bars[cnt].x2 - 128, router->_bars[cnt].y2 - 128);
}
if (!router->_nNodes)
return;
for (uint16 cnt = 0; cnt <= router->_nNodes; cnt++) {
uint16 y = router->_node[cnt].y - 128;
uint16 x = router->_node[cnt].x - 128;
vline(x, y - 2, y + 2);
hline(x - 2, x + 2, y);
if (router->_node[cnt].dist != 9999) {
drawLine(x, y, router->_node[router->_node[cnt].prev].x - 128, router->_node[router->_node[cnt].prev].y - 128);
}
}
}
--- NEW FILE: screen.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/screen.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
// vertical_mask from layers.c belongs here, as well.
#ifndef BSSCREEN_H
#define BSSCREEN_H
#include "sworddefs.h"
#define MAX_FORE 20
#define MAX_BACK 20
#define MAX_SORT 20
struct SortSpr {
int32 id, y;
};
struct RoomDef {
int totalLayers;
int sizeX;
int sizeY;
int gridWidth; //number of 16*16 grid blocks across - including off screen edges.
uint32 layers[4];
uint32 grids[3];
uint32 palettes[2];
uint32 parallax[2];
};
#define SCRNGRID_X 16
#define SCRNGRID_Y 8
#define SHRINK_BUFFER_SIZE 50000
#define RLE_BUFFER_SIZE 50000
#define FLASH_RED 0
#define FLASH_BLUE 1
#define BORDER_YELLOW 2
#define BORDER_GREEN 3
#define BORDER_PURPLE 4
#define BORDER_BLACK 5
class ResMan;
class ObjectMan;
class SwordText; // Text objects use sprites that are created internally at run-time
// the buffer belongs to SwordText, so we need a reference here.
class SwordRouter;
class OSystem;
class SwordScreen {
public:
SwordScreen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan);
void useTextManager(SwordText *pTextMan);
~SwordScreen(void);
void flushSprites(void) { _backLength = _sortLength = _foreLength = 0; };
void quitScreen(void);
void newScreen(uint32 screen);
void setScrolling(int16 offsetX, int16 offsetY);
void addToGraphicList(uint8 listId, uint32 objId);
void recreate();
void spritesAndParallax(void); //=> background_parallax, backsprites, sortsprites
// foreground_parallax, foresprites
void fadeDownPalette(void);
void fadeUpPalette(void);
void fnSetPalette(uint8 start, uint16 length, uint8 *data);
void fnSetFadeTargetPalette(uint8 start, uint16 length, uint8 *data);
bool stillFading(void);
void updateScreen(void);
void showFrame(uint16 x, uint16 y, uint32 resId, uint32 frameNo);
void fnSetParallax(uint32 screen, uint32 resId);
void fnFlash(uint8 color);
void fnBorder(uint8 color);
void showBarsAndNodes(SwordRouter *router);
private:
// for router debugging
void drawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void vline(uint16 x, uint16 y1, uint16 y2);
void hline(uint16 x1, uint16 x2, uint16 y);
void bsubline_1(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void bsubline_2(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void bsubline_3(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void bsubline_4(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void verticalMask(uint16 x, uint16 y, uint16 bWidth, uint16 bHeight);
void blitBlockClear(uint16 x, uint16 y, uint8 *data);
void renderParallax(uint8 *data);
void processImage(uint32 id);
void spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *sprWidth, uint16 *sprHeight, uint16 *incr);
void drawSprite(uint8 *sprData, uint16 sprX, uint16 sprY, uint16 sprWidth, uint16 sprHeight, uint16 sprPitch);
void decompressRLE7(uint8 *src, uint32 compSize, uint8 *dest);
void decompressRLE0(uint8 *src, uint32 compSize, uint8 *dest, uint16 width);
void decompressTony(uint8 *src, uint32 compSize, uint8 *dest);
void fastShrink(uint8 *src, uint32 width, uint32 height, uint32 scale, uint8 *dest);
int32 inRange(int32 a, int32 b, int32 c);
void fadePalette(void);
OSystem *_system;
ResMan *_resMan;
ObjectMan *_objMan;
SwordText *_textMan;
uint16 _currentScreen;
uint8 *_screenBuf;
uint8 *_screenGrid;
uint16 *_layerGrid[4];
uint8 *_layerBlocks[4];
uint8 *_parallax[2];
uint8 _rleBuffer[RLE_BUFFER_SIZE];
uint8 _shrinkBuffer[SHRINK_BUFFER_SIZE];
bool _fullRefresh;
uint16 _oldScrollX, _oldScrollY; // for drawing additional frames
uint32 _foreList[MAX_FORE];
uint32 _backList[MAX_BACK];
SortSpr _sortList[MAX_SORT];
uint8 _foreLength, _backLength, _sortLength;
uint16 _scrnSizeX, _scrnSizeY, _gridSizeX, _gridSizeY;
static RoomDef _roomDefTable[TOTAL_ROOMS]; // from ROOMS.C (not const, see fnSetParallax)
uint8 _targetPalette[256 * 4];
uint8 _currentPalette[256 * 4]; // for fading
uint8 _fadingStep;
int8 _fadingDirection; // 1 for fade up, -1 for fade down
};
#endif //BSSCREEN_H
--- NEW FILE: sound.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/sound.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "sound.h"
#include "common/util.h"
#include "resman.h"
#include "logic.h"
#define SOUND_SPEECH_ID 1
#define SPEECH_FLAGS (SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_LITTLE_ENDIAN)
SwordSound::SwordSound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan) {
strcpy(_filePath, searchPath);
_mixer = mixer;
_resMan = pResMan;
_cowHeader = NULL;
initCowSystem();
_endOfQueue = 0;
}
int SwordSound::addToQueue(int32 fxNo) {
bool alreadyInQueue = false;
for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++)
if (_fxQueue[cnt].id == fxNo)
alreadyInQueue = true;
if (!alreadyInQueue) {
if (_endOfQueue == MAX_FXQ_LENGTH)
error("Sound queue overflow");
_resMan->resOpen(_fxList[fxNo].sampleId);
_fxQueue[_endOfQueue].id = fxNo;
if (_fxList[fxNo].type == FX_SPOT)
_fxQueue[_endOfQueue].delay = _fxList[fxNo].delay + 1;
else
_fxQueue[_endOfQueue].delay = 1;
_endOfQueue++;
return 1;
}
return 0;
}
void SwordSound::engine(void) {
// first of all, add any random sfx to the queue...
for (uint16 cnt = 0; cnt < TOTAL_FX_PER_ROOM; cnt++) {
uint16 fxNo;
if (fxNo = _roomsFixedFx[SwordLogic::_scriptVars[SCREEN]][cnt]) {
if (_fxList[fxNo].type == FX_RANDOM) {
if (_rnd.getRandomNumber(_fxList[fxNo].delay) == 0)
addToQueue(fxNo);
}
} else
break;
}
// now process the queue
for (uint8 cnt = 0; cnt < _endOfQueue; cnt++) {
if (_fxQueue[cnt].delay > 0) {
_fxQueue[cnt].delay--;
if (_fxQueue[cnt].delay == 0)
playSample(_fxQueue[cnt]);
} else {
if (!_fxQueue[cnt].handle) { // sound finished
_resMan->resClose(_fxQueue[cnt].id);
if (cnt != _endOfQueue-1)
_fxQueue[cnt] = _fxQueue[_endOfQueue - 1];
_endOfQueue--;
}
}
}
}
bool SwordSound::amISpeaking(void) {
return true;
}
void SwordSound::clearAllFx(void) {
warning("Stub: SwordSound::clearAllFx()");
}
void SwordSound::closeCowSysten(void) {
warning("stub: SwordSound::closeCowSystem()");
}
void SwordSound::fnStopFx(int32 fxNo) {
warning("stub: SwordSound::fnStopFx(%d)", fxNo);
}
bool SwordSound::speechFinished(void) {
//warning("stub: SwordSound::speechFinished()");
//return true;
return (_speechHandle == 0);
}
void SwordSound::startFxForScreen(uint16 screen) { // do we need this?
warning("stub: SwordSound::startFxForScreen(%d)", screen);
}
void SwordSound::playSample(QueueElement elem) {
uint8 *sampleData = (uint8*)_resMan->fetchRes(_fxList[elem.id].sampleId);
for (uint16 cnt = 0; cnt < MAX_ROOMS_PER_FX; cnt++) {
if (_fxList[elem.id].roomVolList[cnt].roomNo) {
if ((_fxList[elem.id].roomVolList[cnt].roomNo == SwordLogic::_scriptVars[SCREEN]) ||
(_fxList[elem.id].roomVolList[cnt].roomNo == -1)) {
uint8 volL = _fxList[elem.id].roomVolList[cnt].leftVol * 10;
uint8 volR = _fxList[elem.id].roomVolList[cnt].rightVol * 10;
int8 pan = (volR - volL) / 2;
uint8 volume = (volR + volL) / 2;
uint32 size = READ_LE_UINT32(sampleData + 0x28);
uint8 flags;
if (READ_LE_UINT16(sampleData + 0x22) == 16)
flags = SoundMixer::FLAG_16BITS | SoundMixer::FLAG_LITTLE_ENDIAN;
else
flags = SoundMixer::FLAG_UNSIGNED;
_mixer->playRaw(&elem.handle, sampleData + 0x2C, size, 11025, flags, elem.id, volume, pan);
}
} else
break;
}
}
uint32 SwordSound::uncompressedSize(uint8 *data) {
return READ_LE_UINT32(data + 0x28);
}
bool SwordSound::startSpeech(uint16 roomNo, uint16 localNo) {
if (_cowHeader == NULL) {
warning("SwordSound::startSpeech: COW file isn't open!");
return false;
}
uint32 locIndex = _cowHeader[roomNo] >> 2;
uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)];
uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
debug(4, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index);
if (sampleSize) {
_cowFile.seek(index + _cowHeaderSize);
uint8 *buf = (uint8*)malloc(sampleSize);
_cowFile.read(buf, sampleSize);
uint8 *smpBuf = (uint8*)malloc(uncompressedSize(buf));
uint32 size = expandSpeech(buf, smpBuf, sampleSize);
free(buf);
if (!size) {
free(smpBuf);
return false;
}
_mixer->playRaw(&_speechHandle, smpBuf, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID);
return true;
} else
return false;
}
uint32 SwordSound::expandSpeech(void *src, void *dest, uint32 srcSize) {
int16 *compData = (int16*)src;
if (READ_BE_UINT32(compData + 0x12) != 'data') {
warning("SwordSound::expandSpeech: 'data' tag not found in wave header");
return 0;
}
srcSize >>= 1;
int16 *expData = (int16*)dest;
compData += 0x16;
srcSize -= 0x16;
uint32 srcPos = 0;
while (srcPos < srcSize) {
if (compData[srcPos] < 0) {
uint16 len = (uint16)(-compData[srcPos]);
for (uint32 cnt = 0; cnt < len; cnt++)
*expData++ = compData[srcPos + 1];
srcPos += 2;
} else {
uint32 len = (uint32)compData[srcPos];
memcpy(expData, compData + srcPos + 1, len * 2);
expData += len;
srcPos += len + 1;
}
}
return (uint8*)expData - (uint8*)dest;
}
void SwordSound::stopSpeech(void) {
_mixer->stopID(SOUND_SPEECH_ID);
}
void SwordSound::initCowSystem(void) {
_cowFile.open("SPEECH.CLU");
if (_cowFile.isOpen()) {
_cowHeaderSize = _cowFile.readUint32LE();
_cowHeader = (uint32*)malloc(_cowHeaderSize);
if (_cowHeaderSize & 3)
error("Unexpected cow header size %d", _cowHeaderSize);
for (uint32 cnt = 0; cnt < (_cowHeaderSize / 4) - 1; cnt++)
_cowHeader[cnt] = _cowFile.readUint32LE();
} else
warning("SwordSound::initCowSystem: Can't open SPEECH.CLU");
}
--- NEW FILE: sound.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/sound.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef BSSOUND_H
#define BSSOUND_H
#include "object.h"
#include "sworddefs.h"
#include "common/file.h"
#include "sound/mixer.h"
#include "common/util.h"
#define TOTAL_FX_PER_ROOM 7 // total loop & random fx per room (see fx_list.c)
#define MAX_ROOMS_PER_FX 7 // max no. of rooms in the fx's room,vol list
#define MAX_FXQ_LENGTH 32 // max length of sound queue - ie. max number of fx that can be stored up/playing together
#define FX_SPOT 1
#define FX_LOOP 2
#define FX_RANDOM 3
struct QueueElement {
uint32 id, delay;
PlayingSoundHandle handle;
uint16 *data; // FIXME: This is a hack, because our mixer only supports Big endian data (currently)
};
struct RoomVol {
int32 roomNo, leftVol, rightVol;
};
struct FxDef {
uint32 sampleId, type, delay;
RoomVol roomVolList[MAX_ROOMS_PER_FX];
};
class SoundMixer;
class ResMan;
class SwordSound {
public:
SwordSound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan);
~SwordSound(void);
void startFxForScreen(uint16 screen);
bool startSpeech(uint16 roomNo, uint16 localNo); // this should work more or less.
// Maybe we'll need a delay of 3 gameCycles.
bool speechFinished(void);
void stopSpeech();
bool amISpeaking(void); // this is supposed to return if the sounddata is near the ending or very silent...
void fnStopFx(int32 fxNo);
void clearAllFx(void);
int addToQueue(int32 fxNo);
//void removeFromQueue(int32 fxNo);
// ^= part of fnPlayFx
void engine(void);
private:
void playSample(QueueElement elem);
void initCowSystem(void);
void closeCowSysten(void);
uint32 uncompressedSize(uint8 *data);
uint32 expandSpeech(void *src, void *dest, uint32 srcSize);
File _cowFile;
uint32 *_cowHeader;
uint32 _cowHeaderSize;
PlayingSoundHandle _speechHandle, _fxHandle;
Common::RandomSource _rnd;
QueueElement _fxQueue[MAX_FXQ_LENGTH];
uint8 _endOfQueue;
SoundMixer *_mixer;
ResMan *_resMan;
char _filePath[100];
static const char _musicList[270];
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
static const FxDef _fxList[312];
};
#endif //BSSOUND_H
--- NEW FILE: staticres.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/staticres.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
[...5983 lines suppressed...]
{0}, // 81
{0}, // 82
{0}, // 83
{0}, // 84
{0}, // 85
{0}, // 86
{0}, // 87
{0}, // 88
{0}, // 89
{0}, // 90
{0}, // 91
{0}, // 92
{0}, // 93
{0}, // 94
{0}, // 95
{0}, // 96
{0}, // 97
{0}, // 98
{0}, // 99
};
--- NEW FILE: sword1.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/sword1.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "sword1.h"
#include "backends/fs/fs.h"
#include "base/plugins.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/timer.h"
#include "memman.h"
#include "resman.h"
#include "objectman.h"
#include "mouse.h"
#include "logic.h"
#include "sound.h"
#include "screen.h"
#include "swordres.h"
#include "menu.h"
#include "music.h"
// taken from Sword2.cpp
struct Sword1GameSettings {
const char *name;
const char *description;
uint32 features;
const char *detectname;
GameSettings toGameSettings() const {
GameSettings dummy = { name, description, features };
return dummy;
}
};
static const Sword1GameSettings sword1_settings[] = {
/* Broken Sword 1 */
{"sword1", "Broken Sword I", GF_DEFAULT_TO_1X_SCALER, "swordres.rif" },
{NULL, NULL, 0, NULL}
};
GameList Engine_SWORD1_gameList() {
const Sword1GameSettings *g = sword1_settings;
GameList games;
while (g->name) {
games.push_back(g->toGameSettings());
g++;
}
return games;
}
GameList Engine_SWORD1_detectGames(const FSList &fslist) {
GameList detectedGames;
const Sword1GameSettings *g;
for (g = sword1_settings; g->name; ++g) {
// Iterate over all files in the given directory
for (FSList::ConstIterator file = fslist.begin(); file != fslist.end(); ++file) {
const char *gameName = file->displayName().c_str();
if (0 == scumm_stricmp(g->detectname, gameName)) {
// Match found, add to list of candidates, then abort inner loop.
detectedGames.push_back(g->toGameSettings());
break;
}
}
}
return detectedGames;
}
Engine *Engine_SWORD1_create(GameDetector *detector, OSystem *syst) {
return new SwordEngine(detector, syst);
}
REGISTER_PLUGIN("Broken Sword", Engine_SWORD1_gameList, Engine_SWORD1_create, Engine_SWORD1_detectGames)
SystemVars SwordEngine::_systemVars;
void SwordEngine::errorString(const char *buf1, char *buf2) {
strcpy(buf2, buf1);
}
extern uint16 _debugLevel;
SwordEngine::SwordEngine(GameDetector *detector, OSystem *syst)
: Engine(syst) {
_detector = detector;
_system = syst;
_debugLevel = ConfMan.getInt("debuglevel");
if (!_mixer->bindToSystem(syst))
warning("Sound initialization failed");
}
SwordEngine::~SwordEngine() {
}
void SwordEngine::initialize(void) {
_system->init_size(640, 480);
debug(5, "Starting memory manager");
_memMan = new MemMan();
debug(5, "Starting resource manager");
_resMan = new ResMan("swordres.rif", _memMan);
debug(5, "Starting object manager");
_objectMan = new ObjectMan(_resMan);
_mixer->setVolume(255);
_mouse = new SwordMouse(_system, _resMan, _objectMan);
_screen = new SwordScreen(_system, _resMan, _objectMan);
_music = new SwordMusic(_system, _mixer);
_sound = new SwordSound("", _mixer, _resMan);
_menu = new SwordMenu(_screen, _mouse);
_logic = new SwordLogic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu);
_mouse->useLogic(_logic);
_systemVars.justRestoredGame = _systemVars.currentCD =
_systemVars.gamePaused = _systemVars.saveGameFlag =
_systemVars.deathScreenFlag = _systemVars.currentMusic = 0;
_systemVars.snrStatus = 0;
_systemVars.rate = 8;
_systemVars.language = 2;
_systemVars.playSpeech = 1;
//- start.c:
// todo: move these to somewhere else
SwordLogic::_scriptVars[GEORGE_CDT_FLAG] = GEO_TLK_TABLE;
SwordLogic::_scriptVars[CHANGE_X] = 481;
SwordLogic::_scriptVars[CHANGE_Y] = 413;
SwordLogic::_scriptVars[CHANGE_DIR] = DOWN;
SwordLogic::_scriptVars[CHANGE_PLACE] = FLOOR_1;
SwordLogic::_scriptVars[NEW_SCREEN] = 1;
_objectMan->fetchObject(PLAYER)->o_screen = 1;
_objectMan->megaEntering(1);
SwordLogic::_scriptVars[CHANGE_STANCE] = STAND;
_mouseState = 0;
}
void SwordEngine::go(void) {
initialize();
// check if we have savegames. if we do, show control panel, else start intro.
do {
mainLoop();
// mainLoop was left, show control panel
} while (true);
}
void SwordEngine::mainLoop(void) {
uint32 newTime, frameTime;
do {
// do we need the section45-hack from sword.c here?
// todo: ensure right cd is inserted
_screen->newScreen(SwordLogic::_scriptVars[NEW_SCREEN]);
_logic->newScreen(SwordLogic::_scriptVars[NEW_SCREEN]);
SwordLogic::_scriptVars[SCREEN] = SwordLogic::_scriptVars[NEW_SCREEN];
// let swordSound start room sfx
do {
_music->stream();
frameTime = _system->get_msecs();
_systemVars.saveGameFlag = 0;
debug(5, "\n\nNext logic cycle");
_logic->engine();
_logic->updateScreenParams(); // sets scrolling
_screen->recreate();
_screen->spritesAndParallax();
_mouse->animate();
newTime = _system->get_msecs();
/*if ((newTime - frameTime < 50) && (!SwordLogic::_scriptVars[NEW_PALETTE])) {
RenderScreenGDK();
BlitMenusGDK();
BlitMousePm();
if (newTime - frameTime < 40)
_system->delay_msecs(40 - (newTime - frameTime));
FlipScreens();
}*/
_sound->engine();
_screen->showBarsAndNodes(_logic->giveRouter());
_screen->updateScreen();
//-
_menu->refresh(MENU_TOP);
_menu->refresh(MENU_BOT);
newTime = _system->get_msecs();
if (newTime - frameTime < 80)
delay(80 - (newTime - frameTime));
else
delay(0);
/*FlipScreens(); this is done in SwordScreen::updateScreen() now.
if (SwordLogic::_scriptVars[NEW_PALETTE]) {
SwordLogic::_scriptVars[NEW_PALETTE] = 0;
startFadePaletteUp();
}*/
_mouse->engine( _mouseX, _mouseY, _mouseState);
_mouseState = 0;
// do something smart here to implement pausing the game. If we even want that, that is.
} while ((SwordLogic::_scriptVars[SCREEN] == SwordLogic::_scriptVars[NEW_SCREEN]) &&
(_systemVars.saveGameFlag < 2)); // change screen
if (SwordLogic::_scriptVars[SCREEN] != 53) // don't fade down after syria pan
_screen->fadeDownPalette();
while (_screen->stillFading()) {
_screen->updateScreen();
delay(1000/12);
// todo: fade sfx?
}
_screen->quitScreen(); // close graphic resources
_objectMan->closeSection(SwordLogic::_scriptVars[SCREEN]); // close the section that PLAYER has just left, if it's empty now
// todo: stop sfx, clear sfx queue, free sfx memory
} while (_systemVars.saveGameFlag < 2);
}
void SwordEngine::delay(uint amount) { //copied and mutilated from sky.cpp
OSystem::Event event;
uint32 start = _system->get_msecs();
uint32 cur = start;
uint16 _key_pressed = 0; //reset
do {
while (_system->poll_event(&event)) {
switch (event.event_code) {
case OSystem::EVENT_KEYDOWN:
// Make sure backspace works right (this fixes a small issue on OS X)
if (event.kbd.keycode == 8)
_key_pressed = 8;
else
_key_pressed = (byte)event.kbd.ascii;
break;
case OSystem::EVENT_MOUSEMOVE:
_mouseX = event.mouse.x;
_mouseY = event.mouse.y;
break;
case OSystem::EVENT_LBUTTONDOWN:
_mouseState |= BS1L_BUTTON_DOWN;
#ifdef _WIN32_WCE
_mouseX = event.mouse.x;
_mouseY = event.mouse.y;
#endif
break;
case OSystem::EVENT_RBUTTONDOWN:
_mouseState |= BS1R_BUTTON_DOWN;
break;
case OSystem::EVENT_QUIT:
_system->quit();
break;
default:
break;
}
}
if (amount == 0)
break;
{
uint this_delay = 20; // 1?
#ifdef _WIN32_WCE
this_delay = 10;
#endif
if (this_delay > amount)
this_delay = amount;
_system->delay_msecs(this_delay);
}
cur = _system->get_msecs();
} while (cur < start + amount);
}
--- NEW FILE: sword1.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/sword1.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include <stdio.h>
#include "base/engine.h"
#include "common/util.h"
#include "sound/mixer.h"
#include "base/gameDetector.h"
class SwordScreen;
class SwordSound;
class SwordLogic;
class SwordMouse;
class ResMan;
class MemMan;
class ObjectMan;
class SwordMenu;
class SwordMusic;
struct SystemVars {
// todo: move these to a better place
uint32 currentCD; // starts at zero, then either 1 or 2 depending on section being played
uint32 justRestoredGame; // see main() in sword.c & New_screen() in gtm_core.c
uint32 gamePaused; // 1 when paused
uint32 rate; // game rate => what's this for?
//uint32 textNumber; // holds last text_no displayed => I think it was only for debugging
//uint32 endOfQ; // next available slot in sound fx queue
//uint8 debug; // toggles tdebug file
uint8 saveGameFlag; // controls save game loop 0=off 1=save game 2=restore game 3=restart 4=quit to dos
uint8 deathScreenFlag; // 1 death screen version of the control panel, 2 = successful end of game
uint8 playSpeech;
uint8 showText;
uint8 snrStatus;
// ^=> move into SwordControl... or whatever it will be.
//uint8 displayText; // toggles debug text display on "t"
//uint8 displayGrid; // toggles debug grid display on "g"
//uint8 displayMouse; // toggles debug mouse display on "m"
//uint8 framesPerSecond; // toggles one frame pre second mode on "1"
//uint8 writingPCXs; // writing a PCX every frame on "f"
//int16 parallaxOn; I think we don't need this.
uint8 language;
int32 currentMusic;
//uint32 gameCycle;
};
class SwordEngine : public Engine {
void errorString(const char *buf_input, char *buf_output);
public:
SwordEngine(GameDetector *detector, OSystem *syst);
virtual ~SwordEngine();
static SystemVars _systemVars;
protected:
void go();
private:
void delay(uint amount);
void initialize(void);
void mainLoop(void);
void fnCheckCd(uint32 newScreen);
uint16 _mouseX, _mouseY, _mouseState;
GameDetector *_detector;
OSystem *_system;
MemMan *_memMan;
ResMan *_resMan;
ObjectMan *_objectMan;
SwordScreen *_screen;
SwordMouse *_mouse;
SwordLogic *_logic;
SwordSound *_sound;
SwordMenu *_menu;
SwordMusic *_music;
};
--- NEW FILE: sworddefs.h ---
#ifndef SWORDDEFS_H
#define SWORDDEFS_H
#include "scummsys.h"
#define LOOPED 1
#define FRAME_RATE 12 // number of frames per second (max rate)
#define SCREEN_WIDTH 640
#define SCREEN_DEPTH 400
#define SCREEN_LEFT_EDGE 128
#define SCREEN_RIGHT_EDGE (128+SCREEN_WIDTH-1)
#define SCREEN_TOP_EDGE 128
#define SCREEN_BOTTOM_EDGE (128+SCREEN_DEPTH-1)
#define TYPE_FLOOR 1
#define TYPE_MOUSE 2
#define TYPE_SPRITE 3
#define TYPE_NON_MEGA 4
#define TYPE_MEGA 5
[...1352 lines suppressed...]
#define SCR_exit0 (0*0x10000 + 7)
#define SCR_exit1 (0*0x10000 + 8)
#define SCR_exit2 (0*0x10000 + 9)
#define SCR_exit3 (0*0x10000 + 10)
#define SCR_exit4 (0*0x10000 + 11)
#define SCR_exit5 (0*0x10000 + 12)
#define SCR_exit6 (0*0x10000 + 13)
#define SCR_exit7 (0*0x10000 + 14)
#define SCR_exit8 (0*0x10000 + 15)
#define SCR_exit9 (0*0x10000 + 16)
#define LEFT_SCROLL_POINTER 8388610
#define RIGHT_SCROLL_POINTER 8388611
#define FLOOR_63 4128768
#define ROOF_63 4128779
#define GUARD_ROOF_63 4128781
#define LEFT_TREE_POINTER_71 4653058
#define RIGHT_TREE_POINTER_71 4653059
#endif //SWORDDEFS_H
--- NEW FILE: swordres.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/swordres.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
[...5177 lines suppressed...]
#define R79PAL 0x0E090001
#define EKSTD79 0x0E090002
#define EKSTD79CDT 0x0E090003
#define FIGHT79 0x0E090004
#define FIGHT79CDT 0x0E090005
#define GEOANG79 0x0E090006
#define GEOANG79CDT 0x0E090007
#define GEOTLK79 0x0E090008
#define GEOTLK79CDT 0x0E090009
#define NICSTD79 0x0E09000A
#define NICSTD79CDT 0x0E09000B
#define ROSENT79 0x0E09000C
#define ROSENT79CDT 0x0E09000D
#define ROSSHOT 0x0E09000E
#define ROSSHOTCDT 0x0E09000F
#define ROSTLK79 0x0E090010
#define ROSTLK79CDT 0x0E090011
// 18 entities in TXTs, 18 in datafiles.
#endif //SWORDRES_H
--- NEW FILE: text.cpp ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/text.cpp,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#include "stdafx.h"
#include "text.h"
#include "resman.h"
#include "objectman.h"
#include "common/util.h"
#include "swordres.h"
#include "sworddefs.h"
#define OVERLAP 3
#define SPACE ' '
#define BORDER_COL 200
#define LETTER_COL 193
#define NO_COL 0 // sprite background - 0 for transparency
#define MAX_LINES 30
SwordText::SwordText(ObjectMan *pObjMan, ResMan *pResMan, bool czechVersion) {
_objMan = pObjMan;
_resMan = pResMan;
_textCount = 0;
if (czechVersion)
_font = (uint8*)_resMan->openFetchRes(CZECH_GAME_FONT);
else
_font = (uint8*)_resMan->openFetchRes(GAME_FONT);
_joinWidth = charWidth( SPACE ) - 2 * OVERLAP;
_charHeight = _resMan->fetchFrame(_font, 0)->height; // all chars have the same height
_textBlocks[0] = _textBlocks[1] = 0;
}
uint32 SwordText::lowTextManager(uint8 *ascii, int32 width, uint8 pen) {
// get rid of that textId thing!
_textCount++;
if (_textCount > MAX_TEXT_OBS)
error("SwordText::lowTextManager: MAX_TEXT_OBS exceeded!");
uint32 textObjId = (TEXT_sect * ITM_PER_SEC) - 1;
do {
textObjId++;
} while(_objMan->fetchObject(textObjId)->o_status);
// okay, found a free text object
_objMan->fetchObject(textObjId)->o_status = STAT_FORE;
makeTextSprite((uint8)textObjId, ascii, (uint16)width, pen);
return textObjId;
}
void SwordText::makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen) {
LineInfo lines[MAX_LINES];
uint16 numLines = analyzeSentence(text, maxWidth, lines);
uint16 sprWidth = 0;
for (uint16 lineCnt = 0; lineCnt < numLines; lineCnt++)
if (lines[lineCnt].width > sprWidth)
sprWidth = lines[lineCnt].width;
uint16 sprHeight = _charHeight * numLines;
uint32 sprSize = sprWidth * sprHeight;
assert(!_textBlocks[slot]); // if this triggers, the speechDriver failed to call SwordText::releaseText.
_textBlocks[slot] = (FrameHeader*)malloc(sprSize + sizeof(FrameHeader));
memcpy( _textBlocks[slot]->runTimeComp, "Nu ", 4);
_textBlocks[slot]->compSize = 0;
_textBlocks[slot]->width = sprWidth;
_textBlocks[slot]->height = sprHeight;
_textBlocks[slot]->offsetX = 0;
_textBlocks[slot]->offsetY = 0;
uint8 *linePtr = ((uint8*)_textBlocks[slot]) + sizeof(FrameHeader);
memset(linePtr, NO_COL, sprSize);
for (uint16 lineCnt = 0; lineCnt < numLines; lineCnt++) {
uint8 *sprPtr = linePtr + (sprWidth - lines[lineCnt].width) / 2; // center the text
for (uint16 pos = 0; pos < lines[lineCnt].length; pos++)
sprPtr += copyChar(*text++, sprPtr, sprWidth, pen) - OVERLAP;
text++; // skip space at the end of the line
linePtr += _charHeight * sprWidth;
}
}
uint16 SwordText::charWidth(uint8 ch) {
if (ch < SPACE)
ch = 64;
return _resMan->fetchFrame(_font, ch - SPACE)->width;
}
uint16 SwordText::analyzeSentence(uint8 *text, uint16 maxWidth, LineInfo *line) {
uint16 lineNo = 0;
bool firstWord = true;
while (*text) {
uint16 wordWidth = 0;
uint16 wordLength = 0;
while ((*text != SPACE) && *text) {
wordWidth += charWidth(*text) - OVERLAP;
wordLength++;
text++;
}
if (*text == SPACE)
text++;
wordWidth += OVERLAP; // no overlap on final letter of word!
if( firstWord ) { // first word on first line, so no separating SPACE needed
line[0].width = wordWidth;
line[0].length = wordLength;
firstWord = false;
} else {
// see how much extra space this word will need to fit on current line
// (with a separating space character - also overlapped)
uint16 spaceNeeded = _joinWidth + wordWidth;
if (line[lineNo].width + spaceNeeded <= maxWidth ) {
line[lineNo].width += spaceNeeded;
line[lineNo].length += 1 + wordLength; // NB. space+word characters
} else { // put word (without separating SPACE) at start of next line
lineNo++;
assert( lineNo < MAX_LINES );
line[lineNo].width = wordWidth;
line[lineNo].length = wordLength;
}
}
}
return lineNo+1; // return no of lines
}
uint16 SwordText::copyChar(uint8 ch, uint8 *sprPtr, uint16 sprWidth, uint8 pen) {
FrameHeader *chFrame = _resMan->fetchFrame(_font, ch - SPACE);
uint8 *chData = ((uint8*)chFrame) + sizeof(FrameHeader);
uint8 *dest = sprPtr;
for (uint16 cnty = 0; cnty < chFrame->height; cnty++) {
for (uint16 cntx = 0; cntx < chFrame->width; cntx++) {
if (*chData == LETTER_COL)
dest[cntx] = pen;
else if ((*chData == BORDER_COL) && (!dest[cntx])) // don't do a border if there's already a color underneath (chars can overlap)
dest[cntx] = BORDER_COL;
chData++;
}
dest += sprWidth;
}
return chFrame->width;
}
FrameHeader *SwordText::giveSpriteData(uint32 textTarget) {
// textTarget is the resource ID of the Compact linking the textdata.
// that's 0x950000 for slot 0 and 0x950001 for slot 1. easy, huh? :)
textTarget &= ITM_ID;
assert(textTarget <= 1);
return _textBlocks[textTarget];
}
void SwordText::releaseText(uint32 id) {
id &= ITM_ID;
assert(id <= 1);
free(_textBlocks[id]);
_textBlocks[id] = NULL;
_textCount--;
}
--- NEW FILE: text.h ---
/* ScummVM - Scumm Interpreter
* Copyright (C) 2003 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/sword1/text.h,v 1.1 2003/12/16 02:09:25 lavosspawn Exp $
*
*/
#ifndef BSTEXT_H
#define BSTEXT_H
#define MAX_TEXT_OBS 2
#include "object.h"
#include "sworddefs.h"
class ObjectMan;
class ResMan;
struct LineInfo {
uint16 width; // width of line in pixels
uint16 length; // length of line in characters
};
class SwordText {
public:
SwordText(ObjectMan *pObjMan, ResMan *pResMan, bool czechVersion);
~SwordText(void);
FrameHeader *giveSpriteData(uint32 textTarget);
uint32 lowTextManager(uint8 *text, int32 width, uint8 pen);
void releaseText(uint32 id);
private:
void makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen);
uint16 analyzeSentence(uint8 *text, uint16 maxWidth, LineInfo *info);
uint16 charWidth(uint8 ch);
uint16 copyChar(uint8 ch, uint8 *sprPtr, uint16 sprWidth, uint8 pen);
uint8 *_font;
uint8 _textCount;
uint16 _charHeight, _joinWidth;
ObjectMan *_objMan;
ResMan *_resMan;
FrameHeader *_textBlocks[MAX_TEXT_OBS];
};
#endif //BSTEXT_H
More information about the Scummvm-git-logs
mailing list