bs2
svn-id: r9211
This commit is contained in:
parent
d592095fb9
commit
f020d28b5e
60 changed files with 25143 additions and 0 deletions
1
sword2/.cvsignore
Normal file
1
sword2/.cvsignore
Normal file
|
@ -0,0 +1 @@
|
|||
.deps
|
911
sword2/anims.cpp
Normal file
911
sword2/anims.cpp
Normal file
|
@ -0,0 +1,911 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
// A more intelligent version of the old ANIMS.C
|
||||
// All this stuff by James
|
||||
// DON'T TOUCH!
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//#include <io.h> // for access()
|
||||
#include <stdio.h> // for sprintf
|
||||
#include <string.h>
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "driver/driver96.h"
|
||||
#include "anims.h"
|
||||
#include "build_display.h" // for DisplayMsg()
|
||||
#include "console.h"
|
||||
#include "controls.h" // for 'speechSelected' & 'subtitles'
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
#include "interpreter.h"
|
||||
#include "layers.h" // for 'this_screen' structure - for restoring palette in FN_play_sequence
|
||||
#include "maketext.h" // for MakeTextSprite used by FN_play_sequence ultimately
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "sword2.h" // for Close_game()
|
||||
#include "sync.h"
|
||||
#include "sound.h" // for Speech stuff.
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
uint32 smackerLeadOut=0; // stores resource id of wav to use as lead-out from smacker
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
|
||||
int32 Animate(int32 *params, uint8 reverse_flag);
|
||||
int32 Mega_table_animate(int32 *params, uint8 reverse_flag);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_anim(int32 *params)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 resource id of animation file
|
||||
|
||||
return Animate(params,0); // 0 means normal forward anim
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_reverse_anim(int32 *params)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 resource id of animation file
|
||||
|
||||
return Animate(params,1); // 1 means reverse anim
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_mega_table_anim(int32 *params)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to animation table
|
||||
|
||||
return Mega_table_animate(params,0); // 0 means normal forward anim
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_reverse_mega_table_anim(int32 *params)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to animation table
|
||||
|
||||
return Mega_table_animate(params,1); // 1 means reverse anim
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 Animate(int32 *params, uint8 reverse_flag)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 resource id of animation file
|
||||
|
||||
Object_logic *ob_logic;
|
||||
Object_graphic *ob_graphic;
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
int32 res = params[2];
|
||||
|
||||
#ifdef _DEBUG
|
||||
_standardHeader *head; // for animation testing & checking for correct file type
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// read the main parameters
|
||||
|
||||
ob_logic = (Object_logic *) params[0]; // param 0 is pointer to normal structure
|
||||
ob_graphic = (Object_graphic *) params[1]; // param 1 is pointer to graphic structure
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if this is the start of the anim, set up the first frame
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
//-----------------------------------------------------------
|
||||
#ifdef _DEBUG
|
||||
// For testing all anims! (James18apr97)
|
||||
// A script loop can send every resource number to the anim function
|
||||
// & it will only run the valid ones
|
||||
// See 'testing_routines' object in George's Player Character section of linc
|
||||
if (SYSTEM_TESTING_ANIMS)
|
||||
{
|
||||
if (res_man.Res_check_valid(res)) // if the resource number is within range & it's not a null resource
|
||||
{
|
||||
head = (_standardHeader*) res_man.Res_open(res); // open the resource
|
||||
res_man.Res_close(res); // can close immediately - we've got a pointer to the header
|
||||
|
||||
if (head->fileType!=ANIMATION_FILE) // if it's not an animation file
|
||||
{
|
||||
FN_no_sprite(params+1); // switch off the sprite
|
||||
return(IR_STOP); // don't animate - just continue script next cycle
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // not a valid resource number
|
||||
FN_no_sprite(params+1); // switch off the sprite
|
||||
return(IR_STOP); // don't animate - just continue script next cycle
|
||||
}
|
||||
|
||||
FN_sort_sprite(params+1); // switch on the sprite
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------
|
||||
|
||||
//---------------------
|
||||
#ifdef _DEBUG
|
||||
// check that we haven't been passed a zero resource number
|
||||
if (res==0)
|
||||
Con_fatal_error("Animate: %s (id %d) passed zero anim resource (%s line %u)", FetchObjectName(ID), ID, __FILE__, __LINE__);
|
||||
#endif
|
||||
//---------------------
|
||||
|
||||
anim_file = res_man.Res_open(res); // open anim file
|
||||
|
||||
//---------------------
|
||||
#ifdef _DEBUG
|
||||
// check this this resource is actually an animation file!
|
||||
head = (_standardHeader*) anim_file;
|
||||
if (head->fileType!=ANIMATION_FILE) // if it's not an animation file
|
||||
Con_fatal_error("Animate: %s (%d) is not an anim! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
|
||||
#endif
|
||||
//---------------------
|
||||
|
||||
anim_head = FetchAnimHeader( anim_file ); // point to anim header
|
||||
|
||||
//---------------------
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
// check there's at least one frame
|
||||
if (anim_head->noAnimFrames==0)
|
||||
Con_fatal_error("Animate: %s (%d) has zero frame count! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
|
||||
#endif
|
||||
*/
|
||||
//---------------------
|
||||
|
||||
ob_logic->looping = 1; // now running an anim, looping back to this 'FN' call again
|
||||
ob_graphic->anim_resource = res; // param 2 is id of animation resource
|
||||
|
||||
if (reverse_flag) // if a reverse anim
|
||||
ob_graphic->anim_pc = anim_head->noAnimFrames-1; // start on last frame
|
||||
else // forward anim
|
||||
ob_graphic->anim_pc = 0; // start on first frame
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// otherwise, if we've received a sync, return to script immediately
|
||||
|
||||
else if (Get_sync()) // returns sync value if one has been sent to current 'id', otherwise 0
|
||||
{
|
||||
// Zdebug("**sync stopped %d**", ID);
|
||||
ob_logic->looping = 0; // if sync received, anim finishes right now (remaining on last frame)
|
||||
return(IR_CONT); // quit anim but continue script
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// otherwise (not first frame & not received a sync), set up the next frame of the anim
|
||||
else
|
||||
{
|
||||
anim_file = res_man.Res_open(ob_graphic->anim_resource); // open anim file
|
||||
anim_head = FetchAnimHeader( anim_file ); // point to anim header
|
||||
|
||||
if (reverse_flag) // if a reverse anim
|
||||
ob_graphic->anim_pc--; // decrement the anim frame number
|
||||
else // normal forward anim
|
||||
ob_graphic->anim_pc++; // increment the anim frame number
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// check for end of anim
|
||||
|
||||
if (reverse_flag) // if a reverse anim
|
||||
{
|
||||
if (ob_graphic->anim_pc == 0) // reached the first frame of the anim
|
||||
ob_logic->looping = 0; // anim finishes on this frame
|
||||
}
|
||||
else // normal forward anim
|
||||
{
|
||||
if (ob_graphic->anim_pc == (int32)(anim_head->noAnimFrames-1)) // reached the last frame of the anim
|
||||
ob_logic->looping = 0; // anim finishes on this frame
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// close the anim file
|
||||
|
||||
res_man.Res_close(ob_graphic->anim_resource); // close anim file
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// check if we want the script to loop back & call this function again
|
||||
|
||||
if (ob_logic->looping)
|
||||
return(IR_REPEAT); // drop out of script, but call this function again next cycle
|
||||
else
|
||||
return(IR_STOP); // drop out of script
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 Mega_table_animate(int32 *params, uint8 reverse_flag)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to animation table
|
||||
|
||||
Object_logic *ob_logic;
|
||||
Object_mega *ob_mega;
|
||||
uint32 *anim_table;
|
||||
int32 pars[5];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if this is the start of the anim, read the anim table to get the appropriate anim resource
|
||||
|
||||
ob_logic = (Object_logic *) params[0]; // param 0 is pointer to logic structure
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
ob_mega = (Object_mega *) params[2]; // param 2 is pointer to mega structure
|
||||
|
||||
anim_table = (uint32*)params[3];
|
||||
pars[2] = anim_table[ob_mega->current_dir]; // appropriate anim resource is in 'table[direction]'
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// set up the rest of the parameters for FN_anim()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
// pars[2] only needed setting at the start of the anim
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
return Animate(pars, reverse_flag); // call Animate() with these params
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_set_frame(int32 *params)
|
||||
{
|
||||
// params: 0 pointer to object's graphic structure
|
||||
// 1 resource id of animation file
|
||||
// 2 frame flag (0=first 1=last)
|
||||
|
||||
Object_graphic *ob_graphic;
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
int32 res = params[1];
|
||||
|
||||
#ifdef _DEBUG
|
||||
_standardHeader *head; // for checking for correct file type
|
||||
#endif
|
||||
|
||||
//---------------------
|
||||
#ifdef _DEBUG
|
||||
// check that we haven't been passed a zero resource number
|
||||
if (res==0)
|
||||
Con_fatal_error("FN_set_frame: %s (id %d) passed zero anim resource (%s line %u)", FetchObjectName(ID), ID, __FILE__, __LINE__);
|
||||
#endif
|
||||
//---------------------
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// open the resource (& check it's valid)
|
||||
|
||||
anim_file = res_man.Res_open(res); // open anim file
|
||||
|
||||
//---------------------
|
||||
#ifdef _DEBUG
|
||||
// check this this resource is actually an animation file!
|
||||
head = (_standardHeader*) anim_file;
|
||||
if (head->fileType!=ANIMATION_FILE) // if it's not an animation file
|
||||
Con_fatal_error("FN_set_frame: %s (%d) is not an anim! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
|
||||
#endif
|
||||
//---------------------
|
||||
|
||||
anim_head = FetchAnimHeader( anim_file ); // set up pointer to the animation header
|
||||
|
||||
//---------------------
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
// check there's at least one frame
|
||||
if (anim_head->noAnimFrames==0)
|
||||
Con_fatal_error("FN_set_frame: %s (%d) has zero frame count! (%s line %u)", FetchObjectName(res), res, __FILE__, __LINE__);
|
||||
#endif
|
||||
*/
|
||||
//---------------------
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up anim resource in graphic object
|
||||
|
||||
ob_graphic = (Object_graphic *) params[0]; // param 0 is pointer to the object's graphic structure
|
||||
|
||||
ob_graphic->anim_resource = res; // param 2 is id of animation resource
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
if (params[2]) // frame flag is non-zero
|
||||
ob_graphic->anim_pc = anim_head->noAnimFrames-1; // last frame
|
||||
else // frame flag is 0
|
||||
ob_graphic->anim_pc = 0; // first frame
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// close the anim file
|
||||
|
||||
res_man.Res_close(ob_graphic->anim_resource); // close anim file
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
return(IR_CONT); // drop out of script
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_no_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= NO_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_back_par0_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= BGP0_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_back_par1_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= BGP1_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_back_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= BACK_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_sort_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= SORT_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_fore_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= FORE_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_fore_par0_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= FGP0_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_fore_par1_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0xffff0000; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= FGP1_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_shaded_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0x0000ffff; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= SHADED_SPRITE;
|
||||
|
||||
// note that drivers may still shade mega frames automatically, even when not sent 'RDSPR_SHADOW'
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_unshaded_sprite(int32 *params)
|
||||
{
|
||||
// params 0 pointer to object's graphic structure
|
||||
|
||||
Object_graphic *ob_graphic = (Object_graphic *) params[0];
|
||||
|
||||
ob_graphic->type &= 0x0000ffff; // remove previous status (but don't affect the shading upper-word)
|
||||
ob_graphic->type |= UNSHADED_SPRITE;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Notes on PlaySmacker()
|
||||
|
||||
// 1st param is filename of sequence file
|
||||
// 2nd param is a pointer to a null-terminated array of pointers to _movieTextObject structures
|
||||
|
||||
|
||||
//int32 PlaySmacker(char *filename, _movieTextObject *textObjects[]);
|
||||
|
||||
// typedef struct
|
||||
// {
|
||||
// uint16 startFrame;
|
||||
// uint16 endFrame;
|
||||
// _spriteInfo *textSprite;
|
||||
// _wavHeader *speech;
|
||||
// } _movieTextObject;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// FOR TEXT LINES IN SEQUENCE PLAYER (James22may97)
|
||||
|
||||
#define MAX_SEQUENCE_TEXT_LINES 15
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 textNumber;
|
||||
uint16 startFrame;
|
||||
uint16 endFrame;
|
||||
mem *text_mem;
|
||||
mem *speech_mem;
|
||||
} _sequenceTextInfo;
|
||||
|
||||
static _sequenceTextInfo sequence_text_list[MAX_SEQUENCE_TEXT_LINES];
|
||||
uint32 sequenceTextLines=0; // keeps count of number of text lines to disaply during the sequence
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
int32 FN_add_sequence_text(int32 *params) // (James22may97)
|
||||
{
|
||||
// params 0 text number
|
||||
// 1 frame number to start the text displaying
|
||||
// 2 frame number to stop the text dispalying
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (sequenceTextLines == MAX_SEQUENCE_TEXT_LINES)
|
||||
Con_fatal_error("FN_add_sequence_text ran out of lines (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
sequence_text_list[sequenceTextLines].textNumber = params[0];
|
||||
sequence_text_list[sequenceTextLines].startFrame = params[1];
|
||||
sequence_text_list[sequenceTextLines].endFrame = params[2];
|
||||
sequenceTextLines++;
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// speech sample code added by James on 16july97
|
||||
void CreateSequenceSpeech(_movieTextObject *sequenceText[]) // (James23may97)
|
||||
{
|
||||
uint32 line;
|
||||
_frameHeader *frame;
|
||||
uint32 local_text;
|
||||
uint32 text_res;
|
||||
uint8 *text;
|
||||
int16 wavId; // ie. offical text number (actor text number)
|
||||
uint8 speechRunning;
|
||||
char speechFile[256];
|
||||
int32 wavSize;
|
||||
|
||||
|
||||
for (line=0; line < sequenceTextLines; line++) // for each sequence text line that's been logged
|
||||
{
|
||||
sequenceText[line] = new _movieTextObject; // allocate this structure
|
||||
|
||||
sequenceText[line]->startFrame = sequence_text_list[line].startFrame;
|
||||
sequenceText[line]->endFrame = sequence_text_list[line].endFrame;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// pull out the text line to get the official text number (for wav id)
|
||||
|
||||
text_res = sequence_text_list[line].textNumber/SIZE;
|
||||
local_text = sequence_text_list[line].textNumber&0xffff;
|
||||
|
||||
text = FetchTextLine( res_man.Res_open(text_res), local_text ); // open text resource & get the line
|
||||
memcpy(&wavId, text, 2); // this works on PSX & PC
|
||||
|
||||
res_man.Res_close(text_res); // now ok to close the text file
|
||||
|
||||
//--------------------------------------
|
||||
// Write to walkthrough file (zebug0.txt)
|
||||
#ifdef _DEBUG
|
||||
Zdebug(0,"(%d) SEQUENCE TEXT: %s", *(uint16*)text, text+2); // 1st word of text line is the official line number
|
||||
#endif
|
||||
//--------------------------------------
|
||||
// is it to be speech or subtitles or both?
|
||||
|
||||
speechRunning=0; // assume not running until know otherwise
|
||||
sequence_text_list[line].speech_mem = NULL;
|
||||
sequenceText[line]->speech = NULL;
|
||||
|
||||
if (speechSelected) // speech is selected, so try that first
|
||||
{
|
||||
//------------------------------
|
||||
// set up path to speech cluster
|
||||
// first checking if we have speech1.clu or speech2.clu in current directory (for translators to test)
|
||||
|
||||
#ifdef _WEBDEMO // (James 03oct97)
|
||||
strcpy(speechFile,"SPEECH.CLU");
|
||||
#else
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ((res_man.WhichCd()==1) && (!access("speech1.clu",0))) // if 0 ie. if it's there
|
||||
{
|
||||
strcpy(speechFile,"speech1.clu");
|
||||
}
|
||||
else if ((res_man.WhichCd()==2) && (!access("speech2.clu",0))) // if 0 ie. if it's there
|
||||
{
|
||||
strcpy(speechFile,"speech2.clu");
|
||||
}
|
||||
else
|
||||
#endif // _DEBUG
|
||||
{
|
||||
strcpy(speechFile,res_man.GetCdPath());
|
||||
strcat(speechFile,"CLUSTERS\\SPEECH.CLU");
|
||||
}
|
||||
|
||||
#endif // _WEBDEMO
|
||||
//------------------------------
|
||||
|
||||
wavSize = GetCompSpeechSize(speechFile, wavId); // returns size of decompressed wav, or 0 if wav not found
|
||||
if (wavSize) // if we've got the wav
|
||||
{
|
||||
// allocate memory for speech buffer
|
||||
sequence_text_list[line].speech_mem = Twalloc( wavSize, MEM_locked, UID_temp ); // last param is an optional id for type of mem block
|
||||
|
||||
if (sequence_text_list[line].speech_mem) // if mem allocated ok (should be fine, but worth checking)
|
||||
{
|
||||
if (PreFetchCompSpeech(speechFile, wavId, sequence_text_list[line].speech_mem->ad) == RD_OK) // Load speech & decompress to our buffer
|
||||
{
|
||||
Float_mem (sequence_text_list[line].speech_mem); // now float this buffer so we can make space for the next text sprites and/or speech samples
|
||||
speechRunning=1; // ok, we've got speech!
|
||||
}
|
||||
else // whoops, sample didn't load & decompress for some reason...
|
||||
{
|
||||
Free_mem (sequence_text_list[line].speech_mem); // may as well free up this speech buffer now, rather than in ClearSequenceSpeech();
|
||||
sequence_text_list[line].speech_mem = NULL; // so we know that it's free'd
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subtitles || (speechRunning==0)) // if we want subtitles, or speech failed to load
|
||||
{
|
||||
text = FetchTextLine( res_man.Res_open(text_res), local_text ); // open text resource & get the line
|
||||
// mem* MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes );
|
||||
sequence_text_list[line].text_mem = MakeTextSprite( text+2, 600, 255, speech_font_id ); // make the sprite
|
||||
// 'text+2' to skip the first 2 bytes which form the line reference number
|
||||
// NB. The mem block containing the text sprite is currently FLOATING!
|
||||
|
||||
res_man.Res_close(text_res); // ok to close the text resource now
|
||||
}
|
||||
else
|
||||
{
|
||||
sequence_text_list[line].text_mem = NULL;
|
||||
sequenceText[line]->textSprite = NULL;
|
||||
}
|
||||
//--------------------------------------
|
||||
}
|
||||
|
||||
sequenceText[sequenceTextLines] = NULL; // for drivers: NULL-terminate the array of pointers to _movieTextObject's
|
||||
|
||||
//---------------------------------------
|
||||
// now lock all the memory blocks containing text sprites & speech samples
|
||||
// and set up the pointers to them, etc, for the drivers
|
||||
|
||||
for (line=0; line < sequenceTextLines; line++)
|
||||
{
|
||||
// text sprites:
|
||||
if (sequence_text_list[line].text_mem) // if we've made a text sprite for this line...
|
||||
{
|
||||
Lock_mem (sequence_text_list[line].text_mem);
|
||||
// now fill out the _spriteInfo structure in the _movieTextObjectStructure
|
||||
|
||||
frame = (_frameHeader*) sequence_text_list[line].text_mem->ad;
|
||||
|
||||
sequenceText[line]->textSprite = new _spriteInfo;
|
||||
|
||||
sequenceText[line]->textSprite->x = 320 - frame->width/2; // centred
|
||||
sequenceText[line]->textSprite->y = 440 - frame->height; // at bottom of screen
|
||||
sequenceText[line]->textSprite->w = frame->width;
|
||||
sequenceText[line]->textSprite->h = frame->height;
|
||||
sequenceText[line]->textSprite->scale = 0;
|
||||
sequenceText[line]->textSprite->scaledWidth = 0;
|
||||
sequenceText[line]->textSprite->scaledHeight= 0;
|
||||
sequenceText[line]->textSprite->type = RDSPR_DISPLAYALIGN+RDSPR_TRANS+RDSPR_NOCOMPRESSION;
|
||||
sequenceText[line]->textSprite->blend = 0;
|
||||
sequenceText[line]->textSprite->data = sequence_text_list[line].text_mem->ad+sizeof(_frameHeader);
|
||||
sequenceText[line]->textSprite->colourTable = 0;
|
||||
}
|
||||
|
||||
// speech samples:
|
||||
if (sequence_text_list[line].speech_mem) // if we've loaded a speech sample for this line...
|
||||
{
|
||||
Lock_mem (sequence_text_list[line].speech_mem);
|
||||
sequenceText[line]->speech = (_wavHeader *)sequence_text_list[line].speech_mem->ad; // for drivers: set up pointer to decompressed wav in memory
|
||||
}
|
||||
}
|
||||
//---------------------------------------
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// speech sample code added by James on 16july97
|
||||
void ClearSequenceSpeech(_movieTextObject *textSprites[]) // (James27may97)
|
||||
{
|
||||
uint32 line;
|
||||
|
||||
for (line=0; line < sequenceTextLines; line++)
|
||||
{
|
||||
delete (textSprites[line]); // free up the memory used by this _movieTextObject
|
||||
|
||||
if (sequence_text_list[line].text_mem)
|
||||
Free_mem (sequence_text_list[line].text_mem); // free up the mem block containing this text sprite
|
||||
|
||||
if (sequence_text_list[line].speech_mem)
|
||||
Free_mem (sequence_text_list[line].speech_mem); // free up the mem block containing this speech sample
|
||||
}
|
||||
|
||||
sequenceTextLines=0; // IMPORTANT! Reset the line count ready for the next sequence!
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_smacker_lead_in(int32 *params) // James(21july97)
|
||||
{
|
||||
uint8 *leadIn;
|
||||
uint32 rv;
|
||||
#ifdef _DEBUG
|
||||
_standardHeader *header;
|
||||
#endif
|
||||
|
||||
|
||||
leadIn = res_man.Res_open(params[0]);
|
||||
|
||||
//-----------------------------------------
|
||||
#ifdef _DEBUG
|
||||
header = (_standardHeader*)leadIn;
|
||||
if (header->fileType != WAV_FILE)
|
||||
Con_fatal_error("FN_smacker_lead_in() given invalid resource (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
//-----------------------------------------
|
||||
|
||||
leadIn += sizeof(_standardHeader);
|
||||
rv = PlayFx( 0, leadIn, 0, 0, RDSE_FXLEADIN ); // wav data gets copied to sound memory
|
||||
|
||||
//-----------------------------------------
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
|
||||
#endif
|
||||
//-----------------------------------------
|
||||
|
||||
res_man.Res_close(params[0]);
|
||||
|
||||
FN_stop_music(NULL); // fade out any music that is currently playing (James22july97)
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_smacker_lead_out(int32 *params) // James(21july97)
|
||||
{
|
||||
smackerLeadOut = params[0]; // ready for use in FN_play_sequence
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
int32 FN_play_sequence(int32 *params) // James(09apr97)
|
||||
{
|
||||
// params 0 pointer to null-terminated ascii filename
|
||||
// params 1 number of frames in the sequence, used for PSX.
|
||||
|
||||
char filename[30];
|
||||
uint32 rv; // drivers return value
|
||||
_movieTextObject *sequenceSpeechArray[MAX_SEQUENCE_TEXT_LINES+1];
|
||||
uint8 *leadOut = NULL;
|
||||
#ifdef _DEBUG
|
||||
_standardHeader *header;
|
||||
#endif
|
||||
|
||||
#ifdef _MUTE_SMACKERS
|
||||
uint32 musicMuteStatus;
|
||||
#endif
|
||||
|
||||
//----------------------------------
|
||||
// In the case where smackers are crashing but the rest of the game is fine,
|
||||
// the "Skip Smackers" executable will display a message giving the smacker
|
||||
// file name rather than actually playing it.
|
||||
// Then the user can switch tasks & view the smacker using the stand-alone player!
|
||||
// This has got to be the biggest fudge in the history of computer games.
|
||||
|
||||
#ifdef _SKIP_SMACKERS
|
||||
uint8 message[30];
|
||||
|
||||
sprintf((char*)message,"SKIPPING SMACKER: \"%s.smk\"", (char *)params[0]);
|
||||
DisplayMsg(message, 3); // 3 is duration in seconds
|
||||
RemoveMsg();
|
||||
sequenceTextLines=0; // IMPORTANT - clear this so it doesn't overflow!
|
||||
return(IR_CONT); // continue script now; don't play smacker!
|
||||
#endif
|
||||
//----------------------------------
|
||||
// Another attempt to prevent the smacker crash
|
||||
// This time muting the music during the smacker
|
||||
// - in case that's what's causing the crash
|
||||
|
||||
#ifdef _MUTE_SMACKERS
|
||||
musicMuteStatus = IsMusicMute(); // keep note of what mute status was to start with
|
||||
MuteMusic(1); // mute the music - we'll set it back to 'musicMuteStatus' later
|
||||
#endif
|
||||
//----------------------------------
|
||||
|
||||
Zdebug("FN_play_sequence(\"%s\");", params[0]);
|
||||
|
||||
//--------------------------------------------------
|
||||
// check that the name paseed from script is 8 chars or less
|
||||
#ifdef _DEBUG
|
||||
if (strlen((char *)params[0]) > 8)
|
||||
Con_fatal_error("Sequence filename too long (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
//--------------------------------------------------
|
||||
// add the appropriate file extension & play it
|
||||
|
||||
#ifdef _WEBDEMO // (James 01oct97)
|
||||
sprintf(filename,"%s.smk", (char *)params[0]);
|
||||
#else
|
||||
sprintf(filename,"%sSMACKS\\%s.smk", res_man.GetCdPath(), (char *)params[0]);
|
||||
#endif // _WEBDEMO
|
||||
|
||||
//--------------------------------------
|
||||
// Write to walkthrough file (zebug0.txt)
|
||||
|
||||
#ifdef _DEBUG
|
||||
Zdebug(0,"PLAYING SEQUENCE \"%s\"", filename);
|
||||
#endif
|
||||
//--------------------------------------
|
||||
// now create the text sprites, if any (James27may97)
|
||||
|
||||
if (sequenceTextLines) // if we have some text to accompany this sequence
|
||||
CreateSequenceSpeech(sequenceSpeechArray);
|
||||
|
||||
//--------------------------------------
|
||||
// open the lead-out music resource, if there is one
|
||||
|
||||
if (smackerLeadOut)
|
||||
{
|
||||
leadOut = res_man.Res_open(smackerLeadOut);
|
||||
|
||||
//---------------------------
|
||||
#ifdef _DEBUG
|
||||
header = (_standardHeader*)leadOut;
|
||||
if (header->fileType != WAV_FILE)
|
||||
Con_fatal_error("FN_smacker_lead_out() given invalid resource (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
//---------------------------
|
||||
|
||||
leadOut += sizeof(_standardHeader);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// play the smacker
|
||||
|
||||
FN_stop_music(NULL); // don't want to carry on streaming game music when smacker starts!
|
||||
PauseFxForSequence(); // pause sfx during sequence, except the one used for lead-in music
|
||||
|
||||
if (sequenceTextLines) // if we have some text to accompany this sequence
|
||||
rv = PlaySmacker(filename, sequenceSpeechArray, leadOut);
|
||||
else
|
||||
rv = PlaySmacker(filename, NULL, leadOut);
|
||||
|
||||
/* we don't have this call - khalek
|
||||
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q during the smacker
|
||||
{
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
exit(0); //quit the game
|
||||
}
|
||||
*/
|
||||
|
||||
UnpauseFx(); // unpause sound fx again, in case we're staying in same location
|
||||
|
||||
//--------------------------------------
|
||||
// close the lead-out music resource
|
||||
|
||||
if (smackerLeadOut)
|
||||
{
|
||||
res_man.Res_close(smackerLeadOut);
|
||||
smackerLeadOut=0;
|
||||
}
|
||||
//--------------------------
|
||||
// check the error return-value
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("PlaySmacker(\"%s\") returned 0x%.8x", filename, rv);
|
||||
#endif
|
||||
//--------------------------
|
||||
// now clear the text sprites, if any (James27may97)
|
||||
|
||||
if (sequenceTextLines) // if we have some text/speech to accompany this sequence
|
||||
ClearSequenceSpeech(sequenceSpeechArray);
|
||||
|
||||
//--------------------------
|
||||
// now clear the screen in case the Sequence was quitted (using ESC) rather than fading down to black
|
||||
|
||||
EraseBackBuffer(); // for hardware rendering
|
||||
EraseSoftwareScreenBuffer(); // for software rendering
|
||||
FlipScreens(); // to get the new blank screen visible
|
||||
|
||||
//--------------------------------------------------
|
||||
// zero the entire palette in case we're about to fade up!
|
||||
|
||||
_palEntry pal[256];
|
||||
|
||||
memset(pal, 0, 256*sizeof(_palEntry));
|
||||
SetPalette(0, 256, (uint8 *) pal, RDPAL_INSTANT);
|
||||
//--------------------------------------------------
|
||||
|
||||
Zdebug("FN_play_sequence FINISHED");
|
||||
|
||||
//--------------------------------------------------
|
||||
#ifdef _MUTE_SMACKERS
|
||||
MuteMusic(musicMuteStatus); // set mute status back to what it was before the sequence
|
||||
#endif
|
||||
//----------------------------------
|
||||
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
36
sword2/anims.h
Normal file
36
sword2/anims.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _ANIM_S
|
||||
#define _ANIM_S
|
||||
|
||||
|
||||
#include "driver/driver96.h"
|
||||
|
||||
int32 FN_anim(int32 *params);
|
||||
int32 FN_reverse_anim(int32 *params);
|
||||
int32 FN_mega_table_anim(int32 *params);
|
||||
int32 FN_reverse_mega_table_anim(int32 *params);
|
||||
int32 FN_set_frame(int32 *params);
|
||||
int32 FN_no_sprite(int32 *params);
|
||||
int32 FN_back_sprite(int32 *params);
|
||||
int32 FN_sort_sprite(int32 *params);
|
||||
int32 FN_fore_sprite(int32 *params);
|
||||
|
||||
#endif
|
1255
sword2/build_display.cpp
Normal file
1255
sword2/build_display.cpp
Normal file
File diff suppressed because it is too large
Load diff
81
sword2/build_display.h
Normal file
81
sword2/build_display.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _BUILD_DISPLAY
|
||||
#define _BUILD_DISPLAY
|
||||
|
||||
#include "driver/driver96.h"
|
||||
|
||||
|
||||
typedef struct //structure filled out by each object to register its graphic printing requrements
|
||||
{
|
||||
int16 x;
|
||||
int16 y;
|
||||
uint16 scaled_width;
|
||||
uint16 scaled_height;
|
||||
int16 sort_y;
|
||||
uint32 anim_resource;
|
||||
uint16 anim_pc;
|
||||
uint16 scale; //denotes a scaling sprite at print time - and holds the scaling value for the shrink routine
|
||||
uint16 layer_number; //non zero means this item is a layer - retrieve from background layer and send to special renderer
|
||||
uint8 shadingFlag; // non zero means we want this frame to be affected by the shading mask
|
||||
|
||||
// uint32 write_mouse_list; //if none zero the shrinker should write coordinates to this mouse_list number
|
||||
|
||||
} buildit;
|
||||
|
||||
// declared externally so that debug.cpp can display these in the info
|
||||
#define MAX_bgp0_sprites 6
|
||||
#define MAX_bgp1_sprites 6
|
||||
#define MAX_back_sprites 30
|
||||
#define MAX_sort_sprites 30
|
||||
#define MAX_fore_sprites 30
|
||||
#define MAX_fgp0_sprites 6
|
||||
#define MAX_fgp1_sprites 6
|
||||
|
||||
// declared externally so that debug.cpp can display these in the info
|
||||
extern uint32 cur_bgp0;
|
||||
extern uint32 cur_bgp1;
|
||||
extern uint32 cur_back;
|
||||
extern uint32 cur_sort;
|
||||
extern uint32 cur_fore;
|
||||
extern uint32 cur_fgp0;
|
||||
extern uint32 cur_fgp1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
extern char largest_layer_info[128];
|
||||
extern char largest_sprite_info[128];
|
||||
#endif
|
||||
|
||||
// the only build list needed externally - by layers.cpp - for adding layers to sort list
|
||||
extern buildit sort_list[];
|
||||
|
||||
// function prototypes needed externally
|
||||
void Reset_render_lists(void);
|
||||
void Build_display(void); //Tony21Sept96
|
||||
int32 FN_fade_down(int32 *params); //Tony5Dec96
|
||||
int32 FN_fade_up(int32 *params); // Chris 15May97
|
||||
void Process_image(buildit *build_unit); // (5nov96 JEL)
|
||||
void DisplayMsg( uint8 *text, int time ); // (Chris 15May97)
|
||||
void RemoveMsg(void);
|
||||
void SetFullPalette(int32 palRes); // James17jun97
|
||||
|
||||
extern uint32 fps; // needed by debug.cpp for displaying as part of top-screen info
|
||||
|
||||
#endif
|
1341
sword2/console.cpp
Normal file
1341
sword2/console.cpp
Normal file
File diff suppressed because it is too large
Load diff
81
sword2/console.h
Normal file
81
sword2/console.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef C_ONSOLE_H
|
||||
#define C_ONSOLE_H
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void Init_console(void); //Tony9Sept96
|
||||
uint32 One_console(void); //Tony12Aug96
|
||||
void StartConsole(void); //Tony12Aug96
|
||||
void EndConsole(void); //Tony9Oct96
|
||||
|
||||
void Con_fatal_error(char *format,...);
|
||||
void Print_to_console(char *format,...); //Tony13Aug96
|
||||
void Temp_print_to_console(char *format,...); //Tony13Aug96
|
||||
void Scroll_console(void); //Tony13Aug96
|
||||
void Clear_console_line(void); //Tony13Aug96
|
||||
|
||||
extern mem *console_sprite;
|
||||
extern uint32 con_y;
|
||||
extern uint32 con_depth;
|
||||
extern uint32 con_width;
|
||||
|
||||
extern uint8 grabbingSequences;
|
||||
extern uint8 wantSfxDebug; // sfx debug file enabled/disabled from console
|
||||
|
||||
|
||||
#else // _DEBUG
|
||||
/*
|
||||
#define Init_console NULL
|
||||
#define One_console NULL
|
||||
#define StartConsole NULL
|
||||
#define EndConsole NULL
|
||||
*/
|
||||
|
||||
void Init_console(void);
|
||||
uint32 One_console(void);
|
||||
void StartConsole(void);
|
||||
void EndConsole(void);
|
||||
|
||||
// 'Con_fatal_error' commands map to ExitWithReport
|
||||
// so we show errors in a window rather than our development game console
|
||||
#define Con_fatal_error ExitWithReport
|
||||
|
||||
//#define Print_to_console NULL
|
||||
//#define Temp_print_to_console NULL
|
||||
//#define Clear_console_line NULL
|
||||
//#define Scroll_console NULL
|
||||
void Print_to_console(char *format,...);
|
||||
void Temp_print_to_console(char *format,...);
|
||||
void Clear_console_line(void);
|
||||
void Scroll_console(void);
|
||||
//#define Var_check NULL
|
||||
//#define Var_set NULL
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
extern uint32 console_status;
|
||||
|
||||
|
||||
#endif
|
2917
sword2/controls.cpp
Normal file
2917
sword2/controls.cpp
Normal file
File diff suppressed because it is too large
Load diff
38
sword2/controls.h
Normal file
38
sword2/controls.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _CONTROL_S
|
||||
#define _CONTROL_S
|
||||
|
||||
#include "common/scummsys.h"
|
||||
//#include "src\driver96.h"
|
||||
|
||||
uint32 Restore_control(void); //Tony20Mar97
|
||||
void Save_control(void); //Tony1Apr97
|
||||
void Quit_control(void); //Tony2Apr97
|
||||
void Restart_control(void); //Tony4Apr97
|
||||
void Option_control(void); //Pete5Jun97
|
||||
int32 ReadOptionSettings(void); //Pete10Jun97
|
||||
void UpdateGraphicsLevel(uint8 oldLevel, uint8 newLevel); // (James13jun97)
|
||||
|
||||
extern uint8 subtitles; // text selected
|
||||
extern uint8 speechSelected;
|
||||
extern uint8 current_graphics_level;
|
||||
|
||||
#endif
|
28
sword2/credits.h
Normal file
28
sword2/credits.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _Credits_h_
|
||||
#define _Credits_h_
|
||||
|
||||
#include "driver/driver96.h"
|
||||
|
||||
// int32 __declspec( dllexport ) Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus);
|
||||
int32 Credits(_drvDrawStatus *pDrawStatus, _drvSoundStatus *pSoundStatus, const char *cdPath, BOOL smoke, BOOL *pAppFocus, _drvKeyStatus *pKeyStatus);
|
||||
|
||||
#endif
|
553
sword2/debug.cpp
Normal file
553
sword2/debug.cpp
Normal file
|
@ -0,0 +1,553 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
#include <stdarg.h> // for ExitWithReport, which stays in RELEASE version
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "debug.h"
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#if _DEBUG // this whole file (except ExitWithReport) only included on debug versions
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "build_display.h" // for 'fps' (frames-per-second counter)
|
||||
#include "console.h"
|
||||
#include "defs.h"
|
||||
#include "events.h" // for CountEvents()
|
||||
#include "layers.h"
|
||||
#include "logic.h"
|
||||
#include "maketext.h"
|
||||
#include "mem_view.h"
|
||||
#include "mouse.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "router.h" // for PlotWalkGrid()
|
||||
#include "speech.h" // for 'officialTextNumber' and 'speechScriptWaiting'
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
// global variables
|
||||
uint8 displayDebugText = 0; // "INFO" 0=off; 1=on
|
||||
uint8 displayWalkGrid = 0; // "WALKGRID"
|
||||
uint8 displayMouseMarker = 0; // "MOUSE"
|
||||
uint8 displayTime = 0; // "TIME"
|
||||
uint8 displayPlayerMarker = 0; // "PLAYER"
|
||||
uint8 displayTextNumbers = 0; // "TEXT"
|
||||
uint8 renderSkip = 0; // Toggled on 'S' key - to render only 1 in 4 frames, to speed up game
|
||||
|
||||
uint8 definingRectangles = 0; // "RECT"
|
||||
uint8 draggingRectangle = 0; // 0=waiting to start new rect; 1=currently dragging a rectangle
|
||||
int16 rect_x1 = 0;
|
||||
int16 rect_y1 = 0;
|
||||
int16 rect_x2 = 0;
|
||||
int16 rect_y2 = 0;
|
||||
uint8 rectFlicker=0;
|
||||
|
||||
uint8 testingSnR = 0; // "SAVEREST" - for system to kill all object resources (except player) in FN_add_human()
|
||||
|
||||
int32 startTime = 0; // "TIMEON" & "TIMEOFF" - system start time.
|
||||
int32 gameCycle = 0; // Counter for game clocks.
|
||||
|
||||
int32 textNumber = 0; // current system text line number
|
||||
|
||||
int32 showVar[MAX_SHOWVARS]; // "SHOWVAR"
|
||||
|
||||
Object_graphic playerGraphic; // for displaying player object's current graphical info
|
||||
uint32 player_graphic_no_frames=0; // no. of frames in currently displayed anim
|
||||
|
||||
uint8 debug_text_blocks[MAX_DEBUG_TEXT_BLOCKS];
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// function prototypes
|
||||
|
||||
void Clear_debug_text_blocks( void );
|
||||
void Make_debug_text_block( char *text, int16 x, int16 y );
|
||||
void Plot_cross_hair( int16 x, int16 y, uint8 pen );
|
||||
void DrawRect( int16 x, int16 y, int16 x2, int16 y2, uint8 pen );
|
||||
//--------------------------------------------------------------------------------------
|
||||
#endif // _DEBUG
|
||||
|
||||
// THIS FUNCTION STAYS IN THE RELEASE VERSION
|
||||
// IN FACT, CON_FATAL_ERROR IS MAPPED TO THIS AS WELL, SO WE HAVE A MORE PRESENTABLE ERROR REPORT
|
||||
void ExitWithReport(char *format,...) // (6dec96 JEL)
|
||||
{
|
||||
// Send a printf type string to Paul's windows routine
|
||||
char buf[500];
|
||||
va_list arg_ptr; // Variable argument pointer
|
||||
|
||||
va_start(arg_ptr,format);
|
||||
|
||||
|
||||
vsprintf(buf, format, arg_ptr);
|
||||
Zdebug("%s",buf); // send output to 'debug.txt' as well, just for the record
|
||||
|
||||
while (GetFadeStatus()) // wait for fade to finish before calling RestoreDisplay()
|
||||
ServiceWindows();
|
||||
|
||||
RestoreDisplay();
|
||||
ReportFatalError((uint8 *)buf); // display message box
|
||||
CloseAppWindow();
|
||||
while (ServiceWindows() != RDERR_APPCLOSED);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#if _DEBUG // all other functions only for _DEBUG version
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Zdebug(char *format,...) //Tony's special debug logging file March96
|
||||
{
|
||||
// Write a printf type string to a debug file
|
||||
|
||||
va_list arg_ptr; // Variable argument pointer
|
||||
FILE * debug_filep=0; // Debug file pointer
|
||||
static int first_debug = 1; // Flag for first time this is used
|
||||
|
||||
va_start(arg_ptr,format);
|
||||
|
||||
if (first_debug) //First time round delete any previous debug file
|
||||
{
|
||||
unlink("debug.txt");
|
||||
first_debug = 0;
|
||||
}
|
||||
|
||||
debug_filep = fopen("debug.txt","a+t");
|
||||
|
||||
if (debug_filep != NULL) // if it could be opened
|
||||
{
|
||||
vfprintf(debug_filep, format, arg_ptr);
|
||||
fprintf(debug_filep,"\n");
|
||||
|
||||
fclose(debug_filep);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Zdebug(uint32 stream, char *format,...) //Tony's special debug logging file March96
|
||||
{
|
||||
// Write a printf type string to a debug file
|
||||
|
||||
va_list arg_ptr; // Variable argument pointer
|
||||
FILE * debug_filep=0; // Debug file pointer
|
||||
static int first = 1; // Flag for first time this is used
|
||||
int j;
|
||||
static int first_debugs[100];
|
||||
|
||||
|
||||
|
||||
if (first==1) //first time run then reset the states
|
||||
{ for (j=0;j<100;j++)
|
||||
first_debugs[j]=0;
|
||||
|
||||
first=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char name[20];
|
||||
|
||||
|
||||
sprintf(name, "debug%d.txt", stream);
|
||||
|
||||
va_start(arg_ptr,format);
|
||||
|
||||
if (!first_debugs[stream]) //First time round delete any previous debug file
|
||||
{
|
||||
unlink(name);
|
||||
first_debugs[stream] = 1;
|
||||
}
|
||||
|
||||
debug_filep = fopen(name,"a+t");
|
||||
|
||||
if (debug_filep != NULL) // if it could be opened
|
||||
{
|
||||
vfprintf(debug_filep, format, arg_ptr);
|
||||
fprintf(debug_filep,"\n");
|
||||
|
||||
fclose(debug_filep);
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Clear_debug_text_blocks( void ) // JAMES
|
||||
{
|
||||
uint8 blockNo=0;
|
||||
|
||||
|
||||
while ((blockNo < MAX_DEBUG_TEXT_BLOCKS) && (debug_text_blocks[blockNo] > 0))
|
||||
{
|
||||
Kill_text_bloc(debug_text_blocks[blockNo]); // kill the system text block
|
||||
debug_text_blocks[blockNo] = 0; // clear this element of our array of block numbers
|
||||
blockNo++;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Make_debug_text_block( char *text, int16 x, int16 y) // JAMES
|
||||
{
|
||||
uint8 blockNo=0;
|
||||
|
||||
|
||||
while ((blockNo < MAX_DEBUG_TEXT_BLOCKS) && (debug_text_blocks[blockNo] > 0))
|
||||
blockNo++;
|
||||
|
||||
if (blockNo == MAX_DEBUG_TEXT_BLOCKS)
|
||||
Con_fatal_error("ERROR: debug_text_blocks[] full in Make_debug_text_block() at line %d in file \"%s\"",__LINE__,__FILE__);
|
||||
|
||||
debug_text_blocks[blockNo] = Build_new_block( (uint8 *)text, x, y, 640-x, 0, RDSPR_DISPLAYALIGN, CONSOLE_FONT_ID, NO_JUSTIFICATION);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// PC Build_debug_info
|
||||
//
|
||||
//
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Build_debug_text( void ) // JAMES
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
int32 showVarNo; // for variable watching
|
||||
int32 showVarPos;
|
||||
int32 varNo;
|
||||
int32 *varTable;
|
||||
|
||||
|
||||
Clear_debug_text_blocks(); // clear the array of text block numbers for the debug text
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// mouse coords
|
||||
/*
|
||||
if (displayMouseMarker) // print mouse coords beside mouse-marker, if it's being displayed
|
||||
{
|
||||
sprintf (buf, "%d,%d", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y);
|
||||
if (mousex>560)
|
||||
Make_debug_text_block (buf, mousex-50, mousey-15);
|
||||
else
|
||||
Make_debug_text_block (buf, mousex+5, mousey-15);
|
||||
}
|
||||
*/
|
||||
//-------------------------------------------------------------------
|
||||
// mouse area coords
|
||||
|
||||
if (draggingRectangle || SYSTEM_TESTING_ANIMS) // defining a mouse area the easy way, by creating a box on-screen
|
||||
{
|
||||
rectFlicker = 1-rectFlicker; // so we can see what's behind the lines
|
||||
|
||||
sprintf (buf, "x1=%d", rect_x1);
|
||||
Make_debug_text_block (buf, 0, 120);
|
||||
|
||||
sprintf (buf, "y1=%d", rect_y1);
|
||||
Make_debug_text_block (buf, 0, 135);
|
||||
|
||||
sprintf (buf, "x2=%d", rect_x2);
|
||||
Make_debug_text_block (buf, 0, 150);
|
||||
|
||||
sprintf (buf, "y2=%d", rect_y2);
|
||||
Make_debug_text_block (buf, 0, 165);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// testingSnR indicator
|
||||
|
||||
if (testingSnR) // see FN_add_human()
|
||||
{
|
||||
sprintf (buf, "TESTING LOGIC STABILITY!");
|
||||
Make_debug_text_block (buf, 0, 105);
|
||||
}
|
||||
//---------------------------------------------
|
||||
// speed-up indicator
|
||||
|
||||
if (renderSkip) // see sword.cpp
|
||||
{
|
||||
sprintf (buf, "SKIPPING FRAMES FOR SPEED-UP!");
|
||||
Make_debug_text_block (buf, 0, 120);
|
||||
}
|
||||
//---------------------------------------------
|
||||
// debug info at top of screen - enabled/disabled as one complete unit
|
||||
|
||||
if (displayTime)
|
||||
{
|
||||
int32 time = timeGetTime();
|
||||
|
||||
if ((time - startTime) / 1000 >= 10000)
|
||||
startTime = time;
|
||||
|
||||
time -= startTime;
|
||||
sprintf(buf, "Time %.2d:%.2d:%.2d.%.3d",(time / 3600000) % 60,(time / 60000) % 60, (time / 1000) % 60,time%1000);
|
||||
Make_debug_text_block(buf, 500, 360);
|
||||
sprintf(buf, "Game %d", gameCycle);
|
||||
Make_debug_text_block(buf, 500, 380);
|
||||
}
|
||||
//---------------------------------------------
|
||||
// current text number & speech-sample resource id
|
||||
|
||||
if (displayTextNumbers)
|
||||
{
|
||||
if (textNumber)
|
||||
{
|
||||
if (SYSTEM_TESTING_TEXT)
|
||||
{
|
||||
if (SYSTEM_WANT_PREVIOUS_LINE)
|
||||
sprintf (buf, "backwards");
|
||||
else
|
||||
sprintf (buf, "forwards");
|
||||
|
||||
Make_debug_text_block (buf, 0, 340);
|
||||
}
|
||||
|
||||
sprintf (buf, "res: %d", textNumber/SIZE);
|
||||
Make_debug_text_block (buf, 0, 355);
|
||||
|
||||
sprintf (buf, "pos: %d", textNumber&0xffff);
|
||||
Make_debug_text_block (buf, 0, 370);
|
||||
|
||||
sprintf (buf, "TEXT: %d", officialTextNumber);
|
||||
Make_debug_text_block (buf, 0, 385);
|
||||
|
||||
}
|
||||
}
|
||||
//---------------------------------------------
|
||||
// resource number currently being checking for animation
|
||||
|
||||
if (SYSTEM_TESTING_ANIMS)
|
||||
{
|
||||
sprintf (buf, "trying resource %d", SYSTEM_TESTING_ANIMS);
|
||||
Make_debug_text_block (buf, 0, 90);
|
||||
}
|
||||
//---------------------------------------------
|
||||
|
||||
// general debug info
|
||||
|
||||
if (displayDebugText)
|
||||
{
|
||||
//---------------------------------------------
|
||||
/*
|
||||
// CD in use
|
||||
sprintf (buf, "CD-%d", currentCD);
|
||||
Make_debug_text_block (buf, 0, 0);
|
||||
*/
|
||||
//---------------------------------------------
|
||||
// mouse coords & object pointed to
|
||||
|
||||
if (CLICKED_ID)
|
||||
sprintf (buf, "last click at %d,%d (id %d: %s)", MOUSE_X, MOUSE_Y, CLICKED_ID, FetchObjectName(CLICKED_ID));
|
||||
else
|
||||
sprintf (buf, "last click at %d,%d (---)", MOUSE_X, MOUSE_Y);
|
||||
|
||||
Make_debug_text_block (buf, 0, 15);
|
||||
|
||||
if (mouse_touching)
|
||||
sprintf (buf, "mouse %d,%d (id %d: %s)", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y, mouse_touching, FetchObjectName(mouse_touching));
|
||||
else
|
||||
sprintf (buf, "mouse %d,%d (not touching)", mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y);
|
||||
|
||||
Make_debug_text_block (buf, 0, 30);
|
||||
|
||||
//---------------------------------------------
|
||||
// player coords & graphic info
|
||||
|
||||
if (playerGraphic.anim_resource) // if player objct has a graphic
|
||||
sprintf (buf, "player %d,%d %s (%d) #%d/%d", this_screen.player_feet_x, this_screen.player_feet_y, FetchObjectName(playerGraphic.anim_resource), playerGraphic.anim_resource, playerGraphic.anim_pc, player_graphic_no_frames);
|
||||
else
|
||||
sprintf (buf, "player %d,%d --- %d", this_screen.player_feet_x, this_screen.player_feet_y, playerGraphic.anim_pc);
|
||||
|
||||
Make_debug_text_block (buf, 0, 45);
|
||||
|
||||
//---------------------------------------------
|
||||
// frames-per-second counter
|
||||
|
||||
sprintf (buf, "fps %d", fps);
|
||||
Make_debug_text_block (buf, 440, 0);
|
||||
|
||||
//---------------------------------------------
|
||||
// location number
|
||||
|
||||
sprintf (buf, "location=%d", LOCATION);
|
||||
Make_debug_text_block (buf, 440, 15);
|
||||
|
||||
//---------------------------------------------
|
||||
// "result" variable
|
||||
|
||||
sprintf (buf, "result=%d", RESULT);
|
||||
Make_debug_text_block (buf, 440, 30);
|
||||
|
||||
//---------------------------------------------
|
||||
// no. of events in event list
|
||||
|
||||
sprintf (buf, "events=%d", CountEvents());
|
||||
Make_debug_text_block (buf, 440, 45);
|
||||
|
||||
//---------------------------------------------
|
||||
// sprite list usage
|
||||
|
||||
sprintf (buf, "bgp0: %d/%d",cur_bgp0,MAX_bgp0_sprites);
|
||||
Make_debug_text_block (buf, 560, 0);
|
||||
|
||||
sprintf (buf, "bgp1: %d/%d",cur_bgp1,MAX_bgp1_sprites);
|
||||
Make_debug_text_block (buf, 560, 15);
|
||||
|
||||
sprintf (buf, "back: %d/%d",cur_back,MAX_back_sprites);
|
||||
Make_debug_text_block (buf, 560, 30);
|
||||
|
||||
sprintf (buf, "sort: %d/%d",cur_sort,MAX_sort_sprites);
|
||||
Make_debug_text_block (buf, 560, 45);
|
||||
|
||||
sprintf (buf, "fore: %d/%d",cur_fore,MAX_fore_sprites);
|
||||
Make_debug_text_block (buf, 560, 60);
|
||||
|
||||
sprintf (buf, "fgp0: %d/%d",cur_fgp0,MAX_fgp0_sprites);
|
||||
Make_debug_text_block (buf, 560, 75);
|
||||
|
||||
sprintf (buf, "fgp1: %d/%d",cur_fgp1,MAX_fgp1_sprites);
|
||||
Make_debug_text_block (buf, 560, 90);
|
||||
|
||||
//---------------------------------------------
|
||||
// largest layer & sprite
|
||||
|
||||
// NB. Strings already constructed in Build_display.cpp
|
||||
Make_debug_text_block (largest_layer_info, 0, 60);
|
||||
Make_debug_text_block (largest_sprite_info, 0, 75);
|
||||
|
||||
//---------------------------------------------
|
||||
// "waiting for person" indicator - set form FN_they_do & FN_they_do_we_wait
|
||||
|
||||
if (speechScriptWaiting)
|
||||
{
|
||||
sprintf (buf, "script waiting for %s (%d)", FetchObjectName(speechScriptWaiting), speechScriptWaiting);
|
||||
Make_debug_text_block (buf, 0, 90);
|
||||
}
|
||||
//---------------------------------------------
|
||||
// variable watch display
|
||||
|
||||
showVarPos = 115; // y-coord for first showVar
|
||||
|
||||
varTable = (int32*)(res_man.Res_open(1) + sizeof(_standardHeader)); // res 1 is the global variables resource
|
||||
|
||||
for (showVarNo=0; showVarNo < MAX_SHOWVARS; showVarNo++)
|
||||
{
|
||||
varNo = showVar[showVarNo]; // get variable number
|
||||
|
||||
if (varNo) // if non-zero ie. cannot watch 'id' but not needed anyway because it changes throughout the logic loop
|
||||
{
|
||||
sprintf (buf, "var(%d) = %d", varNo, varTable[varNo]);
|
||||
Make_debug_text_block (buf, 530, showVarPos);
|
||||
showVarPos += 15; // next line down
|
||||
}
|
||||
}
|
||||
|
||||
res_man.Res_close(1); // close global variables resource
|
||||
|
||||
//---------------------------------------------
|
||||
// memory indicator - this should come last, to show all the sprite blocks above!
|
||||
|
||||
Create_mem_string (buf);
|
||||
Make_debug_text_block (buf, 0, 0);
|
||||
|
||||
//---------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Draw_debug_graphics( void ) // JAMES (08apr97)
|
||||
{
|
||||
//-------------------------------
|
||||
// walk-grid
|
||||
|
||||
if (displayWalkGrid)
|
||||
PlotWalkGrid();
|
||||
|
||||
//-------------------------------
|
||||
// player feet coord marker
|
||||
|
||||
if (displayPlayerMarker)
|
||||
Plot_cross_hair (this_screen.player_feet_x, this_screen.player_feet_y, 215);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// mouse marker & coords
|
||||
|
||||
if (displayMouseMarker)
|
||||
Plot_cross_hair (mousex+this_screen.scroll_offset_x, mousey+this_screen.scroll_offset_y, 215);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// mouse area rectangle / sprite box rectangle when testing anims
|
||||
|
||||
if (SYSTEM_TESTING_ANIMS)
|
||||
{
|
||||
DrawRect(rect_x1, rect_y1, rect_x2, rect_y2, 184); // draw box around current frame
|
||||
}
|
||||
else if (draggingRectangle) // defining a mouse area the easy way, by creating a box on-screen
|
||||
{
|
||||
if (rectFlicker)
|
||||
DrawRect(rect_x1, rect_y1, rect_x2, rect_y2, 184);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Plot_cross_hair( int16 x, int16 y, uint8 pen )
|
||||
{
|
||||
PlotPoint(x,y,pen); // driver function
|
||||
|
||||
DrawLine(x-2,y,x-5,y,pen); // driver function
|
||||
DrawLine(x+2,y,x+5,y,pen);
|
||||
|
||||
DrawLine(x,y-2,x,y-5,pen);
|
||||
DrawLine(x,y+2,x,y+5,pen);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void DrawRect( int16 x1, int16 y1, int16 x2, int16 y2, uint8 pen )
|
||||
{
|
||||
DrawLine(x1,y1,x2,y1,pen); // top edge
|
||||
DrawLine(x1,y2,x2,y2,pen); // bottom edge
|
||||
DrawLine(x1,y1,x1,y2,pen); // left edge
|
||||
DrawLine(x2,y1,x2,y2,pen); // right edge
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Print_current_info(void) //Tony30Oct96
|
||||
{
|
||||
//prints general stuff about the screen, etc.
|
||||
|
||||
|
||||
if (this_screen.background_layer_id)
|
||||
{ Print_to_console(" background layer id %d", this_screen.background_layer_id);
|
||||
Print_to_console(" %d wide, %d high", this_screen.screen_wide, this_screen.screen_deep);
|
||||
Print_to_console(" %d normal layers", this_screen.number_of_layers);
|
||||
|
||||
LLogic.Examine_run_list();
|
||||
|
||||
}
|
||||
else
|
||||
Print_to_console(" no screen");
|
||||
|
||||
|
||||
Scroll_console();
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
#else // not debug
|
||||
|
||||
void Draw_debug_graphics(void) {};
|
||||
|
||||
#endif // _DEBUG
|
||||
//--------------------------------------------------------------------------------------
|
92
sword2/debug.h
Normal file
92
sword2/debug.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef D_DEBUG
|
||||
#define D_DEBUG
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
#ifdef _DEBUG // this whole file only included on debug versions
|
||||
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "driver.h"
|
||||
#include "object.h"
|
||||
|
||||
#define MAX_DEBUG_TEXT_BLOCKS 50
|
||||
|
||||
extern uint8 displayDebugText; // 0=off; 1=on
|
||||
extern uint8 displayWalkGrid;
|
||||
extern uint8 displayMouseMarker;
|
||||
extern uint8 displayPlayerMarker;
|
||||
extern uint8 displayTime;
|
||||
extern uint8 displayTextNumbers;
|
||||
extern uint8 definingRectangles;
|
||||
extern uint8 draggingRectangle;
|
||||
extern uint8 displayTime;
|
||||
extern int32 startTime;
|
||||
extern int32 gameCycle;
|
||||
extern uint8 renderSkip;
|
||||
|
||||
extern int16 rect_x1;
|
||||
extern int16 rect_y1;
|
||||
extern int16 rect_x2;
|
||||
extern int16 rect_y2;
|
||||
|
||||
extern uint8 testingSnR;
|
||||
|
||||
extern int32 textNumber;
|
||||
|
||||
extern Object_graphic playerGraphic;
|
||||
extern uint32 player_graphic_no_frames;
|
||||
|
||||
|
||||
|
||||
#define MAX_SHOWVARS 15
|
||||
extern int32 showVar[MAX_SHOWVARS];
|
||||
|
||||
|
||||
void Zdebug(char * ,...); // Tony's special debug logging file March96
|
||||
void Zdebug(uint32 stream, char *format,...);
|
||||
void Build_debug_text(void); // James's debug text display
|
||||
void Draw_debug_graphics(void); // James's debug graphics display
|
||||
|
||||
void Print_current_info(void); //Tony30Oct96
|
||||
|
||||
|
||||
#else // ie. not _DEBUG
|
||||
|
||||
/* gcc doesn't like this - khalek
|
||||
#define Zdebug NULL
|
||||
#define Build_debug_text NULL
|
||||
#define Draw_debug_graphics NULL
|
||||
#define Print_current_info NULL
|
||||
*/
|
||||
|
||||
void Zdebug(char * ,...); // Tony's special debug logging file March96
|
||||
void Build_debug_text(void); // James's debug text display
|
||||
void Draw_debug_graphics(void); // James's debug graphics display
|
||||
|
||||
#endif // _DEBUG // this whole file only included on debug versions
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
void ExitWithReport(char *format,...); // (6dec96 JEL) IN BOTH DEBUG & RELEASE VERSIONS
|
||||
|
||||
|
||||
|
||||
#endif //D_DEBUG
|
139
sword2/defs.h
Normal file
139
sword2/defs.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef DEFS
|
||||
#define DEFS
|
||||
|
||||
#include "header.h"
|
||||
#include "resman.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
#define SIZE 0x10000 //65536 items per section
|
||||
#define NuSIZE 0xffff //& with this
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
//global variable references
|
||||
|
||||
// NB. 4 * <number from linc's Global Variables list>
|
||||
|
||||
#define ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader))
|
||||
#define RESULT *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1) // 4 * <number from linc's Global Variables list>
|
||||
#define PLAYER_ACTION *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 2)
|
||||
//#define CUR_PLAYER_ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 3)
|
||||
#define CUR_PLAYER_ID 8 // always 8 (George object used for Nico player character as well)
|
||||
#define PLAYER_ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 305)
|
||||
#define TALK_FLAG *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 13)
|
||||
|
||||
#define MOUSE_X *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 4)
|
||||
#define MOUSE_Y *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 5)
|
||||
#define LEFT_BUTTON *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 109)
|
||||
#define RIGHT_BUTTON *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 110)
|
||||
#define CLICKED_ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 178)
|
||||
|
||||
#define IN_SUBJECT *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 6)
|
||||
#define COMBINE_BASE *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 7)
|
||||
#define OBJECT_HELD *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 14)
|
||||
|
||||
#define SPEECH_ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 9)
|
||||
#define INS1 *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 10)
|
||||
#define INS2 *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 11)
|
||||
#define INS3 *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 12)
|
||||
#define INS4 *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 60)
|
||||
#define INS5 *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 61)
|
||||
#define INS_COMMAND *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 59)
|
||||
|
||||
#define PLAYER_FEET_X *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 141)
|
||||
#define PLAYER_FEET_Y *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 142)
|
||||
#define PLAYER_CUR_DIR *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 937)
|
||||
|
||||
#define LOCATION *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 62) // for debug.cpp
|
||||
|
||||
#define SCROLL_X *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 345) // so scripts can force scroll offsets
|
||||
#define SCROLL_Y *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 346) // so scripts can force scroll offsets
|
||||
|
||||
#define EXIT_CLICK_ID *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 710)
|
||||
#define EXIT_FADING *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 713)
|
||||
|
||||
#define SYSTEM_TESTING_ANIMS *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 912)
|
||||
#define SYSTEM_TESTING_TEXT *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1230)
|
||||
#define SYSTEM_WANT_PREVIOUS_LINE *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1245)
|
||||
|
||||
#define MOUSE_AVAILABLE *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 686) // 1=on 0=off (set in FN_add_human & FN_no_human)
|
||||
|
||||
#define AUTO_SELECTED *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1115) // used in FN_choose
|
||||
|
||||
#define CHOOSER_COUNT_FLAG *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 15) // see FN_start_conversation & FN_chooser
|
||||
|
||||
#define DEMO *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1153) //signifies a demo mode
|
||||
|
||||
#define PSXFLAG *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1173) // Indicates to script whether this is the Playstation version.
|
||||
|
||||
#define DEAD *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1256) //=1 =dead
|
||||
#define SPEECHANIMFLAG *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1278) // If set indicates that the speech anim is to run through only once.
|
||||
|
||||
#define SCROLL_OFFSET_X *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 1314) //for the engine
|
||||
|
||||
#define GAME_LANGUAGE *(uint32 *)(res_man.resList[1]->ad+sizeof(_standardHeader)+4* 111) //for the poor PSX so it knows what language is running.
|
||||
//--------------------------------------------------------------------------------------
|
||||
//resource id's of pouse mointers. It's pretty much safe to do it like this
|
||||
|
||||
#define NORMAL_MOUSE_ID 17
|
||||
#define SCROLL_LEFT_MOUSE_ID 1440
|
||||
#define SCROLL_RIGHT_MOUSE_ID 1441
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Console Font - does not use game text - only English required
|
||||
#define CONSOLE_FONT_ID 340 // ConsFont
|
||||
|
||||
// Speech Font
|
||||
#define ENGLISH_SPEECH_FONT_ID 341 // SpchFont
|
||||
#define FINNISH_SPEECH_FONT_ID 956 // FinSpcFn
|
||||
#define POLISH_SPEECH_FONT_ID 955 // PolSpcFn
|
||||
|
||||
// Control Panel Font (and un-selected savegame descriptions)
|
||||
#define ENGLISH_CONTROLS_FONT_ID 2005 // Sfont
|
||||
#define FINNISH_CONTROLS_FONT_ID 959 // FinSavFn
|
||||
#define POLISH_CONTROLS_FONT_ID 3686 // PolSavFn
|
||||
|
||||
// Red Font (for selected savegame descriptions)
|
||||
#define ENGLISH_RED_FONT_ID 2005 // 1998 // Redfont
|
||||
#define FINNISH_RED_FONT_ID 959 // 960 // FinRedFn
|
||||
#define POLISH_RED_FONT_ID 3686 // 3688 // PolRedFn
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Control panel palette resource id
|
||||
|
||||
#define CONTROL_PANEL_PALETTE 261
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// res id's of the system menu icons
|
||||
#define OPTIONS_ICON 344
|
||||
#define QUIT_ICON 335
|
||||
#define SAVE_ICON 366
|
||||
#define RESTORE_ICON 364
|
||||
#define RESTART_ICON 342
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// res id of conversation exit icon
|
||||
|
||||
#define EXIT_ICON 65 // 'EXIT' menu icon (used in FN_choose)
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
405
sword2/events.cpp
Normal file
405
sword2/events.cpp
Normal file
|
@ -0,0 +1,405 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "events.h"
|
||||
#include "interpreter.h"
|
||||
#include "logic.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "sync.h"
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
_event_unit event_list[MAX_events];
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
void Init_event_system(void) //Tony4Dec96
|
||||
{
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
event_list[j].id=0; //denotes free slot
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 CountEvents(void)
|
||||
{
|
||||
uint32 j;
|
||||
uint32 count=0;
|
||||
|
||||
for (j=0; j<MAX_events; j++)
|
||||
{
|
||||
if (event_list[j].id)
|
||||
count++;
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_request_speech(int32 *params) //Tony13Nov96
|
||||
{
|
||||
//change current script - must be followed by a TERMINATE script directive
|
||||
|
||||
//param 0 id of target to catch the event and startup speech servicing
|
||||
|
||||
uint32 j=0;
|
||||
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (event_list[j].id == (uint32)params[0])
|
||||
break;
|
||||
if (!event_list[j].id)
|
||||
break;
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (j==MAX_events)
|
||||
Con_fatal_error("FN_set_event out of event slots (%s line %u)", __FILE__, __LINE__);
|
||||
|
||||
//found that slot
|
||||
|
||||
event_list[j].id=params[0]; //id of person to stop
|
||||
event_list[j].interact_id=(params[0]*65536)+6; //full script id to interact with - megas run their own 7th script
|
||||
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Set_player_action_event(uint32 id, uint32 interact_id) //Tony4Dec96
|
||||
{
|
||||
uint32 j=0;
|
||||
|
||||
|
||||
|
||||
|
||||
// if ((event_list[j].id!=id)&&(event_list[j].id))
|
||||
// while((event_list[j].id!=id)||(event_list[j].id)) //zip along until we find a free slot
|
||||
// { j++;
|
||||
// };
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (event_list[j].id==id)
|
||||
break;
|
||||
if (!event_list[j].id)
|
||||
break;
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
|
||||
if (j==MAX_events)
|
||||
Con_fatal_error("Set_event out of event slots");
|
||||
|
||||
//found that slot
|
||||
|
||||
event_list[j].id=id; //id of person to stop
|
||||
event_list[j].interact_id=(interact_id*65536)+2; //full script id of action script number 2
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_player_action_event(int32 *params) //Tony10Feb97
|
||||
{
|
||||
//we want to intercept the player character and have him interact with an object - from script
|
||||
//this code is the same as the mouse engine calls when you click on an object - here, a third party does the clicking IYSWIM
|
||||
|
||||
//note - this routine used CUR_PLAYER_ID as the target
|
||||
|
||||
//params 0 id to interact with
|
||||
|
||||
uint32 j=0;
|
||||
|
||||
|
||||
|
||||
|
||||
//search for an existing event or a slot
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (event_list[j].id==CUR_PLAYER_ID)
|
||||
break;
|
||||
if (!event_list[j].id)
|
||||
break;
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
|
||||
if (j==MAX_events)
|
||||
Con_fatal_error("Set_event out of event slots");
|
||||
|
||||
//found that slot
|
||||
|
||||
event_list[j].id=CUR_PLAYER_ID; //id of person to stop
|
||||
event_list[j].interact_id=(params[0]*65536)+2; //full script id of action script number 2
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_send_event(int32 *params) //Tony28Feb97
|
||||
{
|
||||
//we want to intercept the player character and have him interact with an object - from script
|
||||
|
||||
// 0 id to recieve event
|
||||
// 1 script to run
|
||||
|
||||
|
||||
uint32 j=0;
|
||||
|
||||
|
||||
// Zdebug("*+*+* %d %d", params[0], params[1] );
|
||||
|
||||
|
||||
//search for an existing event or a slot
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (event_list[j].id==(uint32)params[0])
|
||||
break;
|
||||
if (!event_list[j].id)
|
||||
break;
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
|
||||
if (j==MAX_events)
|
||||
Con_fatal_error("fn_send_event out of event slots");
|
||||
|
||||
//found that slot
|
||||
|
||||
event_list[j].id=params[0]; //id of person to stop
|
||||
event_list[j].interact_id=params[1]; //full script id
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_check_event_waiting(int32 *params) //Tony4Dec96
|
||||
{
|
||||
// returns yes/no in RESULT
|
||||
|
||||
// no params
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
|
||||
RESULT=0;
|
||||
|
||||
|
||||
for (j=0; j<MAX_events; j++)
|
||||
{
|
||||
if (event_list[j].id == ID) //us?
|
||||
{
|
||||
RESULT=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// like FN_check_event_waiting, but starts the event rather than setting RESULT to 1
|
||||
|
||||
int32 FN_check_for_event(int32 *params) // James (04mar97)
|
||||
{
|
||||
// no params
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0; j<MAX_events; j++)
|
||||
{
|
||||
if (event_list[j].id == ID) //us?
|
||||
{
|
||||
// start the event
|
||||
LLogic.Logic_one(event_list[j].interact_id); // run 3rd script of target object on level 1
|
||||
event_list[j].id = 0; // clear the event slot
|
||||
return(IR_TERMINATE);
|
||||
}
|
||||
}
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// combination of FN_pause & FN_check_for_event
|
||||
// - ie. does a pause, but also checks for event each cycle
|
||||
|
||||
int32 FN_pause_for_event(int32 *params) // James (04mar97)
|
||||
{
|
||||
// returns yes/no in RESULT
|
||||
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 number of game-cycles to pause
|
||||
|
||||
Object_logic *ob_logic = (Object_logic *)params[0];
|
||||
uint32 j;
|
||||
|
||||
|
||||
// first, check for an event
|
||||
|
||||
for (j=0; j<MAX_events; j++)
|
||||
{
|
||||
if (event_list[j].id == ID) // us?
|
||||
{
|
||||
ob_logic->looping = 0; // reset the 'looping' flag
|
||||
// start the event
|
||||
LLogic.Logic_one(event_list[j].interact_id); // run 3rd script of target object on level 1
|
||||
event_list[j].id = 0; // clear the event slot
|
||||
return(IR_TERMINATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// no event, so do the FN_pause bit
|
||||
|
||||
|
||||
if (ob_logic->looping==0) // start the pause
|
||||
{
|
||||
ob_logic->looping = 1;
|
||||
ob_logic->pause = params[1]; // no. of game cycles
|
||||
}
|
||||
|
||||
if (ob_logic->pause) // if non-zero
|
||||
{
|
||||
ob_logic->pause--; // decrement the pause count
|
||||
return(IR_REPEAT); // drop out of script, but call this again next cycle
|
||||
}
|
||||
else // pause count is zerp
|
||||
{
|
||||
ob_logic->looping = 0;
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 Check_event_waiting(void) //Tony4Dec96
|
||||
{
|
||||
//returns yes/no
|
||||
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
if (event_list[j].id == ID) //us?
|
||||
return(1); //yes
|
||||
|
||||
return(0); //no
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_clear_event(int32 *params) //Tony11Mar97
|
||||
{
|
||||
// no params
|
||||
// no return vaule
|
||||
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
if (event_list[j].id == ID) //us?
|
||||
{
|
||||
event_list[j].id=0; //clear the slot
|
||||
return(IR_CONT); //
|
||||
}
|
||||
|
||||
return(IR_CONT); //
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Start_event(void) //Tony4Dec96
|
||||
{
|
||||
//call this from stuff like fn_walk
|
||||
//you must follow with a return(IR_TERMINATE)
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
if (event_list[j].id == ID) //us?
|
||||
{
|
||||
|
||||
LLogic.Logic_one( event_list[j].interact_id); //run 3rd script of target object on level 1
|
||||
|
||||
event_list[j].id=0; //clear the slot
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//oh dear - stop the system
|
||||
|
||||
Con_fatal_error("Start_event can't find event for id %d", ID);
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_start_event(int32 *params) //Tony4Dec96
|
||||
{
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
if (event_list[j].id == ID) //us?
|
||||
{
|
||||
|
||||
LLogic.Logic_one(event_list[j].interact_id); //run 3rd script of target object on level 1
|
||||
|
||||
event_list[j].id=0; //clear the slot
|
||||
|
||||
return(IR_TERMINATE);
|
||||
}
|
||||
|
||||
//oh dear - stop the system
|
||||
|
||||
Con_fatal_error("FN_start_event can't find event for id %d", ID);
|
||||
|
||||
return(0); //never called - but lets stop them bloody errors
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Kill_all_ids_events(uint32 id) //Tony18Dec96
|
||||
{
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_events;j++)
|
||||
if (event_list[j].id == id) //us?
|
||||
event_list[j].id=0; //clear the slot
|
||||
|
||||
if (id);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
|
48
sword2/events.h
Normal file
48
sword2/events.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _EVENTS
|
||||
#define _EVENTS
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "object.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 id;
|
||||
uint32 interact_id;
|
||||
} _event_unit;
|
||||
|
||||
#define MAX_events 10
|
||||
|
||||
extern _event_unit event_list[MAX_events];
|
||||
|
||||
void Init_event_system(void); //Tony4Dec96
|
||||
int32 FN_set_event(int32 *params); //Tony13Nov96
|
||||
void Set_player_action_event(uint32 id, uint32 interact_id); //Tony4Dec96
|
||||
int32 FN_check_event_waiting(void); //Tony4Dec96
|
||||
void Start_event(void); //Tony4Dec96
|
||||
int32 FN_start_event(void); //Tony4Dec96
|
||||
uint32 Check_event_waiting(void); //Tony4Dec96
|
||||
void Kill_all_ids_events(uint32 id); //Tony18Dec96
|
||||
uint32 CountEvents(void); // James11july97
|
||||
|
||||
|
||||
#endif
|
458
sword2/function.cpp
Normal file
458
sword2/function.cpp
Normal file
|
@ -0,0 +1,458 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "credits.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "function.h"
|
||||
#include "interpreter.h"
|
||||
#include "layers.h" // for 'this_screen' structure
|
||||
#include "logic.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "sword2.h" // for CloseGame()
|
||||
//------------------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
uint32 a;
|
||||
uint32 b;
|
||||
} test_struct;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
Object_graphic engine_graph; // global for engine
|
||||
Object_mega engine_mega; // global for engine
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_test_function(int32 *params)
|
||||
{
|
||||
//param 0 address of a flag
|
||||
Zdebug(" TEST %d %d", *params, RESULT);
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_test_flags(int32 *params)
|
||||
{
|
||||
//param 0 value of flag
|
||||
|
||||
test_struct *tony;
|
||||
|
||||
|
||||
tony = (test_struct*) *params; //address of structure
|
||||
|
||||
|
||||
|
||||
// Zdebug("\nFN_test_flags %d, %d\n", tony->a, tony->b );
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_gosub(int32 *params) //Tony23Sept96
|
||||
{
|
||||
//hurray, script subroutines
|
||||
//param 0 id of script
|
||||
|
||||
|
||||
LLogic.Logic_up(*params);
|
||||
|
||||
return(4); //logic goes up - pc is saved for current level
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_new_script(int32 *params) //Tony13Nov96
|
||||
{
|
||||
//change current script - must be followed by a TERMINATE script directive
|
||||
//param 0 id of script
|
||||
Zdebug("FN_new_script %d", *params);
|
||||
|
||||
PLAYER_ACTION=0; //must clear this
|
||||
|
||||
LLogic.Logic_replace( *params );
|
||||
|
||||
return(IR_TERMINATE); //drop out no pc save - and around again
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_interact(int32 *params) //Tony13Nov96
|
||||
{
|
||||
//run targets action on a subroutine
|
||||
//called by player on his base level 0 idle, for example
|
||||
|
||||
|
||||
//param 0 id of target from which we derive action script reference
|
||||
|
||||
Zdebug("FN_interact %d", *params);
|
||||
PLAYER_ACTION=0; //must clear this
|
||||
|
||||
LLogic.Logic_up( (*params*65536)+2); //3rd script of clicked on id
|
||||
|
||||
return(IR_GOSUB); //out, up and around again - pc is saved for current level to be returned to
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Open & close a resource.
|
||||
// Forces a resource into memory before it's "officially" opened for use.
|
||||
// eg. if an anim needs to run on smoothly from another, "preloading" gets it into memory in advance
|
||||
// to avoid the cacheing delay that normally occurs before the first frame.
|
||||
|
||||
int32 FN_preload(int32 *params) // (1Nov96 JEL)
|
||||
{
|
||||
res_man.Res_open(params[0]); // open resource
|
||||
res_man.Res_close(params[0]); // close resource
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
|
||||
|
||||
// Go fetch resource in the background.
|
||||
int32 FN_prefetch(int32 *params)
|
||||
{
|
||||
return(IR_CONT);
|
||||
}
|
||||
|
||||
|
||||
// Fetches a resource in the background but prevents the script from continuing until the resource is in memory.
|
||||
int32 FN_fetch_wait(int32 *params)
|
||||
{
|
||||
return (IR_CONT);
|
||||
}
|
||||
|
||||
|
||||
// Releases a resource from memory. Used for freeing memory for sprites that have just been used
|
||||
// and will not be used again.
|
||||
// Sometimes it is better to kick out a sprite straight away so that the memory can be used for
|
||||
// more frequent animations.
|
||||
int32 FN_release(int32 *params)
|
||||
{
|
||||
return (IR_CONT);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Generates a random number between 'min' & 'max' inclusive, and sticks it in the script flag 'result'
|
||||
|
||||
int32 FN_random(int32 *params) // (1nov96 JEL)
|
||||
{
|
||||
uint32 min = params[0];
|
||||
uint32 max = params[1];
|
||||
|
||||
RESULT = (rand() % (max-min+1)) + min; // return_value = random integer between min and max, inclusive
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_pause(int32 *params) // (19nov96 JEL)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 number of game-cycles to pause
|
||||
|
||||
//NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle quit, 2 gives 2 cycles, etc.
|
||||
|
||||
Object_logic *ob_logic = (Object_logic *)params[0];
|
||||
|
||||
if (ob_logic->looping==0) // start the pause
|
||||
{
|
||||
ob_logic->looping = 1;
|
||||
ob_logic->pause = params[1]; // no. of game cycles
|
||||
}
|
||||
|
||||
if (ob_logic->pause) // if non-zero
|
||||
{
|
||||
ob_logic->pause--; // decrement the pause count
|
||||
return(IR_REPEAT); // drop out of script, but call this again next cycle
|
||||
}
|
||||
else // pause count is zerp
|
||||
{
|
||||
ob_logic->looping = 0;
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_random_pause(int32 *params) // (26nov96 JEL)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 minimum number of game-cycles to pause
|
||||
// 2 maximum number of game-cycles to pause
|
||||
|
||||
Object_logic *ob_logic = (Object_logic *)params[0];
|
||||
int32 pars[2];
|
||||
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
pars[0] = params[1]; // min
|
||||
pars[1] = params[2]; // max
|
||||
|
||||
FN_random(pars);
|
||||
|
||||
pars[1] = RESULT; // random value between 'min' & 'max' inclusive
|
||||
}
|
||||
|
||||
pars[0] = params[0]; // &logic
|
||||
|
||||
return FN_pause(pars);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_pass_graph(int32 *params) //Tony28Nov96
|
||||
{
|
||||
//makes an engine local copy of passed graphic_structure and mega_structure - run script 4 of an object to request this
|
||||
//used by FN_turn_to(id) etc
|
||||
//remember, we cannot simply read a compact any longer but instead must request it from the object itself
|
||||
|
||||
//params 0 pointer to a graphic structure *might not need this?
|
||||
|
||||
|
||||
memcpy( &engine_graph, (uint8*)params[0], sizeof(Object_graphic));
|
||||
|
||||
return(IR_CONT); //makes no odds
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_pass_mega(int32 *params) //Tony28Nov96
|
||||
{
|
||||
//makes an engine local copy of passed graphic_structure and mega_structure - run script 4 of an object to request this
|
||||
//used by FN_turn_to(id) etc
|
||||
//remember, we cannot simply read a compact any longer but instead must request it from the object itself
|
||||
|
||||
//params 0 pointer to a mega structure
|
||||
|
||||
|
||||
memcpy( &engine_mega, (uint8*)params[0], sizeof(Object_mega));
|
||||
|
||||
return(IR_CONT); //makes no odds
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// temp. function!
|
||||
// used for setting far-referenced megaset resource field in mega object, from start script
|
||||
|
||||
int32 FN_set_value(int32 *params) // (02jan97 JEL)
|
||||
{
|
||||
// params: 0 pointer to object's mega structure
|
||||
// 1 value to set it to
|
||||
|
||||
Object_mega *ob_mega = (Object_mega *)params[0];
|
||||
|
||||
|
||||
ob_mega->megaset_res = params[1];
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define RED 2
|
||||
#define GREEN 3
|
||||
#define BLUE 4
|
||||
//------------------------------------------------------------------------------------
|
||||
uint8 black[4] = {0,0,0,0};
|
||||
uint8 white[4] = {255,255,255,0};
|
||||
uint8 red[4] = {255,0,0,0};
|
||||
uint8 green[4] = {0,255,0,0};
|
||||
uint8 blue[4] = {0,0,255,0};
|
||||
//------------------------------------------------------------------------------------
|
||||
// flash colour 0 (ie. border) - useful during script development
|
||||
// eg. FN_flash(BLUE) where a text line is missed; RED when some code missing, etc
|
||||
|
||||
int32 FN_flash(int32 *params) // (James14feb97)
|
||||
{
|
||||
// params 0: colour to flash
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
uint32 count;
|
||||
|
||||
switch (params[0]) // what colour?
|
||||
{
|
||||
case WHITE:
|
||||
SetPalette(0, 1, white, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case RED:
|
||||
SetPalette(0, 1, red, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case GREEN:
|
||||
SetPalette(0, 1, green, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case BLUE:
|
||||
SetPalette(0, 1, blue, RDPAL_INSTANT);
|
||||
break;
|
||||
}
|
||||
|
||||
for (count=0; count<0x80000; count++)
|
||||
{
|
||||
count++;
|
||||
count--;
|
||||
}
|
||||
|
||||
SetPalette(0, 1, black, RDPAL_INSTANT);
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// set border colour - useful during script development
|
||||
// eg. set to colour during a timer situation, then black when timed out
|
||||
|
||||
int32 FN_colour(int32 *params) // (James14feb97)
|
||||
{
|
||||
// params 0: colour (see defines above)
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
switch (params[0]) // what colour?
|
||||
{
|
||||
case BLACK:
|
||||
SetPalette(0, 1, black, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case WHITE:
|
||||
SetPalette(0, 1, white, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case RED:
|
||||
SetPalette(0, 1, red, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case GREEN:
|
||||
SetPalette(0, 1, green, RDPAL_INSTANT);
|
||||
break;
|
||||
|
||||
case BLUE:
|
||||
SetPalette(0, 1, blue, RDPAL_INSTANT);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// Display a message to the user on the screen.
|
||||
//
|
||||
|
||||
int32 FN_display_msg(int32 *params) // (Chris 15/5/97)
|
||||
{
|
||||
// params 0: Text number of message to be displayed.
|
||||
uint32 local_text = params[0]&0xffff;
|
||||
uint32 text_res = params[0]/SIZE;
|
||||
|
||||
// Display message for three seconds.
|
||||
DisplayMsg(FetchTextLine( res_man.Res_open(text_res), local_text )+2, 3); // +2 to skip the encoded text number in the first 2 chars; 3 is duration in seconds
|
||||
res_man.Res_close(text_res);
|
||||
RemoveMsg();
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// FN_reset_globals is used by the demo - so it can loop back & restart itself
|
||||
int32 FN_reset_globals(int32 *params) //Tony29May97
|
||||
{
|
||||
int32 size;
|
||||
uint32 *globals;
|
||||
int j;
|
||||
|
||||
size = res_man.Res_fetch_len(1);
|
||||
|
||||
size-=sizeof(_standardHeader);
|
||||
|
||||
Zdebug("\nglobals size %d", size/4);
|
||||
|
||||
globals = (uint32*) ((uint8 *) res_man.Res_open(1)+sizeof(_standardHeader));
|
||||
|
||||
for (j=0;j<size/4;j++)
|
||||
globals[j]=0; //blank each global variable
|
||||
|
||||
res_man.Res_close(1);
|
||||
|
||||
res_man.Kill_all_objects(0); //all objects but george
|
||||
|
||||
// SetGlobalInterpreterVariables((int32*)(res_man.Res_open(1)+sizeof(_standardHeader))); //reopen global variables resource & send address to interpreter - it won't be moving
|
||||
// res_man.Res_close(1);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET! (James29may97)
|
||||
// - this is taken from FN_init_background
|
||||
this_screen.scroll_flag = 2; // switch on scrolling (2 means first time on screen)
|
||||
//---------------------------------------------------------------
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// FN_play_credits - Plays the credits?
|
||||
// This function just quits the game if this is the playable demo, ie. credits are NOT played in the demo any more!
|
||||
|
||||
extern uint8 quitGame; // From sword2.cpp
|
||||
extern void UpdateCompSampleStreaming(void); // From d_sound.c
|
||||
|
||||
int32 FN_play_credits(int32 *params)
|
||||
{
|
||||
|
||||
/* uint32 rv; // for Credits() return value
|
||||
|
||||
if (!DEMO) // this ju
|
||||
{
|
||||
_drvDrawStatus ds;
|
||||
_drvSoundStatus ss;
|
||||
_drvKeyStatus ks;
|
||||
|
||||
ClearAllFx(); // Must stop all fx
|
||||
CloseFx(-2); // including leadins
|
||||
CloseFx(-1); // including leadouts
|
||||
StopMusic(); // Stop any streaming music
|
||||
|
||||
for (int i = 0; i<16; i++)
|
||||
UpdateCompSampleStreaming(); // And wait for it to die
|
||||
|
||||
GetDrawStatus (&ds);
|
||||
GetSoundStatus(&ss);
|
||||
GetKeyStatus (&ks);
|
||||
|
||||
rv = Credits(&ds, &ss, res_man.GetCdPath(), GetRenderType()==3, &gotTheFocus, &ks);
|
||||
SetDrawStatus (&ds); // (James14aug97) Because game crashing when trying to close down after credits
|
||||
SetSoundStatus(&ss); // -"-
|
||||
}
|
||||
|
||||
// returns non-zero if Ctrl-Q was pressed to quit the game during the credits
|
||||
|
||||
if (rv || DEMO) // if Ctrl-Q pressed during credits, or if this is the playable demo
|
||||
{
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
exit(0); // quit the game
|
||||
}
|
||||
|
||||
*/
|
||||
return (IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
|
31
sword2/function.h
Normal file
31
sword2/function.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _FUNCTION
|
||||
#define _FUNCTION
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "object.h"
|
||||
|
||||
|
||||
extern Object_graphic engine_graph; // global for engine
|
||||
extern Object_mega engine_mega; // global for engine
|
||||
|
||||
|
||||
#endif
|
355
sword2/header.h
Normal file
355
sword2/header.h
Normal file
|
@ -0,0 +1,355 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _HEADER
|
||||
#define _HEADER
|
||||
|
||||
#include "common/scummsys.h"
|
||||
//#include "src\driver96.h"
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SYSTEM FILE & FRAME HEADERS (23sep96 JEL)
|
||||
//----------------------------------------------------------
|
||||
|
||||
//#pragma pack( push )
|
||||
//#pragma pack( 1 )
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
#pragma START_PACK_STRUCTS
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// ALL FILES
|
||||
//----------------------------------------------------------
|
||||
// Standard File Header
|
||||
#define NAME_LEN 34
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 fileType; // byte to define file type (see below)
|
||||
uint8 compType; // type of file compression used ie. on whole file (see below)
|
||||
uint32 compSize; // length of compressed file (ie. length on disk)
|
||||
uint32 decompSize; // length of decompressed file held in memory (NB. frames still held compressed)
|
||||
uint8 name[NAME_LEN]; //name of object
|
||||
} GCC_PACK _standardHeader;
|
||||
|
||||
//----------------------------------------------------------
|
||||
// fileType
|
||||
|
||||
// 0 something's wrong!
|
||||
#define ANIMATION_FILE 1 // all normal animations & sprites including mega-sets & font files which are the same format (but all frames always uncompressed)
|
||||
#define SCREEN_FILE 2 // each contains background, palette, layer sprites, parallax layers & shading mask
|
||||
#define GAME_OBJECT 3 // each contains object hub + structures + script data
|
||||
#define WALK_GRID_FILE 4 // walk-grid data
|
||||
#define GLOBAL_VAR_FILE 5 // all the global script variables in one file; "there can be only one"
|
||||
#define PARALLAX_FILE_null 6 // NOT USED
|
||||
#define RUN_LIST 7 // each contains a list of object resource id's
|
||||
#define TEXT_FILE 8 // each contains all the lines of text for a location or a character's conversation script
|
||||
#define SCREEN_MANAGER 9 // one for each location; this contains special startup scripts
|
||||
#define MOUSE_FILE 10 // mouse pointers and luggage icons (sprites in General \ Mouse pointers & Luggage icons)
|
||||
#define WAV_FILE 11 // wav file
|
||||
#define ICON_FILE 12 // menu icon (sprites in General \ Menu icons
|
||||
#define PALETTE_FILE 13 // separate palette file (see also _paletteHeader)
|
||||
//----------------------------------------------------------
|
||||
// compType
|
||||
|
||||
#define NO_COMPRESSION 0
|
||||
#define FILE_COMPRESSION 1 // standard whole-file compression (not yet devised!)
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// (1) ANIMATION FILES
|
||||
//----------------------------------------------------------
|
||||
// an animation file consists of:
|
||||
|
||||
// standard file header
|
||||
// animation header
|
||||
// a string of CDT entries (one per frame of the anim)
|
||||
// a 16-byte colour table ONLY if (runTimeComp==RLE16)
|
||||
// a string of groups of (frame header + frame data)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Animation Header
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 runTimeComp; // type of runtime compression used for the frame data (see below)
|
||||
uint16 noAnimFrames; // number of frames in the anim (ie. no. of CDT entries)
|
||||
uint16 feetStartX; // start coords for mega to walk to, before running anim
|
||||
uint16 feetStartY;
|
||||
uint8 feetStartDir; // direction to start in before running anim
|
||||
uint16 feetEndX; // end coords for mega to stand at after running anim (vital if anim starts from an off-screen position, or ends in a different place from the start)
|
||||
uint16 feetEndY;
|
||||
uint8 feetEndDir; // direction to start in after running anim
|
||||
uint16 blend;
|
||||
} GCC_PACK _animHeader;
|
||||
|
||||
//----------------------------------------------------------
|
||||
// runtimeComp - compression used on each frame of the anim
|
||||
|
||||
#define NONE 0 // No frame compression
|
||||
#define RLE256 1 // James's RLE for 256-colour sprites
|
||||
#define RLE16 2 // James's RLE for 16- or 17-colour sprites
|
||||
// (raw blocks have max 16 colours for 2 pixels per byte,
|
||||
// so '0's are encoded only as FLAT for 17-colour sprites eg. George's mega-set)
|
||||
//----------------------------------------------------------
|
||||
// CDT Entry
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16 x; // sprite x-coord OR offset to add to mega's feet x-coord to calc sprite y-coord
|
||||
int16 y; // sprite y-coord OR offset to add to mega's feet y-coord to calc sprite y-coord
|
||||
uint32 frameOffset; // points to start of frame header (from start of file header)
|
||||
uint8 frameType; // 0=print sprite normally with top-left corner at (x,y), otherwise see below...
|
||||
} GCC_PACK _cdtEntry;
|
||||
|
||||
// 'frameType' bit values
|
||||
#define FRAME_OFFSET 1 // print at (feetX+x,feetY+y), with scaling according to feetY
|
||||
#define FRAME_FLIPPED 2 // print the frame flipped Left->Right
|
||||
#define FRAME_256_FAST 4 // Frame has been compressed using Pauls fast RLE 256 compression.
|
||||
|
||||
//----------------------------------------------------------
|
||||
//Frame Header
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 compSize; // compressed size of frame - NB. compression type is now in Anim Header
|
||||
uint16 width; // dimensions of frame
|
||||
uint16 height;
|
||||
} GCC_PACK _frameHeader;
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Frame Data
|
||||
|
||||
// uint8 spriteData[width*height]; // one byte per pixel
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// (2) SCREEN FILES
|
||||
//----------------------------------------------------------
|
||||
// a screen file consists of:
|
||||
|
||||
// standard file header
|
||||
// multi screen header
|
||||
// 4*256 bytes of palette data
|
||||
// 256k palette match table
|
||||
// 2 background parallax layers
|
||||
// 1 background layer with screen header
|
||||
// 2 foreground parallax layers
|
||||
// a string of layer headers
|
||||
// a string of layer masks
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Multi screen header
|
||||
// Goes at the beginning of a screen file after the standard
|
||||
// header.
|
||||
// Gives offsets from start of table of each of the components
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 palette;
|
||||
uint32 bg_parallax[2];
|
||||
uint32 screen;
|
||||
uint32 fg_parallax[2];
|
||||
uint32 layers;
|
||||
uint32 paletteTable;
|
||||
uint32 maskOffset;
|
||||
} GCC_PACK _multiScreenHeader;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Palette Data
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 red;
|
||||
uint8 green;
|
||||
uint8 blue;
|
||||
uint8 alpha;
|
||||
} GCC_PACK _palEntry;
|
||||
|
||||
#define NO_COLOURS 256
|
||||
// _palEntry palette[NO_COLOURS]
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Screen Header
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 width; // dimensions of the background screen
|
||||
uint16 height;
|
||||
uint16 noLayers; // number of layer areas
|
||||
} GCC_PACK _screenHeader;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Background Raw Bitmap
|
||||
|
||||
// uint8 backgroundData[width*height]; // one byte per pixel
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Layer Header
|
||||
|
||||
// Note that all the layer headers are kept together,
|
||||
// rather than being placed before each layer mask,
|
||||
// in order to simplify the sort routine.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 x; // coordinates of top-left pixel of area
|
||||
uint16 y;
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
uint32 maskSize;
|
||||
uint32 offset; // where to find mask data (from start of standard file header)
|
||||
} GCC_PACK _layerHeader;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Layer Mask
|
||||
|
||||
// uint8 layerData[width*height/8]; // 8 pixels to a byte
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// (3) SCRIPT OBJECT FILES
|
||||
//----------------------------------------------------------
|
||||
// a script object file consists of:
|
||||
|
||||
// standard file header
|
||||
// script object header
|
||||
// script object data
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Script Object Header
|
||||
|
||||
// ???????
|
||||
// ???????
|
||||
// ???????
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Script Object Data
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// (4) WALK-GRID FILES
|
||||
//----------------------------------------------------------
|
||||
// a walk-grid file consists of:
|
||||
|
||||
// standard file header
|
||||
// walk-grid file header
|
||||
// walk-grid data
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Walk-Grid Header - taken directly from old "header.h" in STD_INC
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 numBars; // number of bars on the floor
|
||||
int32 numNodes; // number of nodes
|
||||
} GCC_PACK _walkGridHeader;
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Walk-Grid Data
|
||||
|
||||
// ???????
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// (5) PALETTE FILES
|
||||
//----------------------------------------------------------
|
||||
// a palette file consists of:
|
||||
|
||||
// standard file header
|
||||
// 4*256 bytes of palette data
|
||||
// 256k palette match table
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// PCX file header
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{ uint8 manufacturer;
|
||||
uint8 version;
|
||||
uint8 encoding;
|
||||
uint8 bitsPerPixel;
|
||||
int16 xmin,ymin;
|
||||
int16 xmax,ymax;
|
||||
int16 hres;
|
||||
int16 vres;
|
||||
char palette[48];
|
||||
char reserved;
|
||||
uint8 colourPlanes;
|
||||
int16 bytesPerLine;
|
||||
int16 paletteType;
|
||||
char filler[58];
|
||||
} GCC_PACK _PCXHEAD;
|
||||
//----------------------------------------------------------
|
||||
#define TREE_SIZE 3
|
||||
|
||||
typedef struct // an object hub - which represents all that remains of the compact concept
|
||||
{
|
||||
int32 type; // type of object
|
||||
uint32 logic_level; // what level?
|
||||
uint32 logic[TREE_SIZE]; // NOT USED
|
||||
uint32 script_id[TREE_SIZE]; // need this if script
|
||||
uint32 script_pc[TREE_SIZE]; // need this also
|
||||
} GCC_PACK _object_hub;
|
||||
//----------------------------------------------------------
|
||||
//----------------------------------------------------------
|
||||
// (6) text module header TW
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 noOfLines; //how many lines of text are there in this module
|
||||
} GCC_PACK _textHeader;
|
||||
|
||||
//a text file has:
|
||||
|
||||
// _standardHeader
|
||||
// _textHeader
|
||||
// look up table, to
|
||||
// line of text,0
|
||||
// line of text,0
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
// #pragma pack( pop )
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
#pragma END_PACK_STRUCTS
|
||||
#endif
|
||||
|
||||
#endif
|
244
sword2/icons.cpp
Normal file
244
sword2/icons.cpp
Normal file
|
@ -0,0 +1,244 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "console.h"
|
||||
#include "icons.h"
|
||||
#include "interpreter.h"
|
||||
#include "logic.h"
|
||||
#include "mouse.h"
|
||||
#include "object.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
menu_object temp_list[TOTAL_engine_pockets];
|
||||
uint32 total_temp=0; //tempory list
|
||||
|
||||
menu_object master_menu_list[TOTAL_engine_pockets];
|
||||
uint32 total_masters=0;
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_add_menu_object(int32 *params) //Tony1Oct96
|
||||
{
|
||||
//param 0 pointer to a menu_object structure to copy down
|
||||
|
||||
// Zdebug("FN_add_menu_object icon res");
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (total_temp == TOTAL_engine_pockets)
|
||||
Con_fatal_error("TOTAL_engine_pockets exceeded! (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
// copy the structure to our in-the-engine list
|
||||
memcpy( &temp_list[total_temp], (uint8*) *params, sizeof(menu_object)); //
|
||||
total_temp++;
|
||||
|
||||
return(IR_CONT); // script continue
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_refresh_inventory(int32 *params) // (James28aug97)
|
||||
{
|
||||
// called from 'menu_look_or_combine' script in 'menu_master' object
|
||||
// to update the menu to display a combined object while George runs voice-over
|
||||
// Note that 'object_held' must be set to the graphic of the combined object
|
||||
|
||||
COMBINE_BASE=0; // can reset this now
|
||||
|
||||
examining_menu_icon=1; // so that the icon in 'object_held' is coloured while the rest are grey
|
||||
Build_top_menu();
|
||||
examining_menu_icon=0;
|
||||
|
||||
return(IR_CONT); // script continue
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Build_top_menu(void) //Tony19Nov96
|
||||
{
|
||||
// create and start the inventory menu - NOW AT THE BOTTOM OF THE SCREEN!
|
||||
|
||||
uint32 null_pc=0;
|
||||
uint32 j,k;
|
||||
uint8 icon_coloured;
|
||||
uint8 *icon;
|
||||
uint8 *head;
|
||||
uint32 res;
|
||||
|
||||
total_temp=0; //reset temp list which will be totally rebuilt
|
||||
|
||||
|
||||
|
||||
// Zdebug("\nbuild top menu %d", total_masters);
|
||||
|
||||
|
||||
//clear the temp list before building a new temp list in-case list gets smaller
|
||||
for (j=0;j<TOTAL_engine_pockets;j++) //check each master
|
||||
temp_list[j].icon_resource=0; //
|
||||
|
||||
|
||||
//call menu builder script which will register all carried menu objects
|
||||
head = res_man.Res_open(MENU_MASTER_OBJECT);
|
||||
RunScript( (char*)head, (char*)head, &null_pc ); // run the 'build_menu' script in the 'menu_master' object
|
||||
res_man.Res_close(MENU_MASTER_OBJECT);
|
||||
|
||||
//compare new with old
|
||||
//anything in master thats not in new gets removed from master - if found in new too, remove from temp
|
||||
|
||||
if (total_masters)
|
||||
{
|
||||
for (j=0;j<total_masters;j++) //check each master
|
||||
{
|
||||
for (k=0;k<TOTAL_engine_pockets;k++)
|
||||
{
|
||||
res=0;
|
||||
if (master_menu_list[j].icon_resource == temp_list[k].icon_resource) //if master is in temp
|
||||
{
|
||||
temp_list[k].icon_resource=0; //kill it in the temp
|
||||
res=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!res)
|
||||
{ master_menu_list[j].icon_resource=0; //otherwise not in temp so kill in main
|
||||
// Zdebug("Killed menu %d",j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//merge master downwards
|
||||
|
||||
total_masters=0;
|
||||
for (j=0;j<TOTAL_engine_pockets;j++) //check each master slot
|
||||
{
|
||||
if ((master_menu_list[j].icon_resource)&&(j!=total_masters)) //not current end - meaning out over the end so move down
|
||||
{
|
||||
memcpy( &master_menu_list[total_masters++], &master_menu_list[j], sizeof(menu_object)); //
|
||||
master_menu_list[j].icon_resource=0; //moved down now so kill here
|
||||
}
|
||||
else if (master_menu_list[j].icon_resource) //skip full slots
|
||||
total_masters++;
|
||||
}
|
||||
|
||||
//add those new to menu still in temp but not yet in master to the end of the master
|
||||
for (j=0;j<TOTAL_engine_pockets;j++) //check each master slot
|
||||
if (temp_list[j].icon_resource) //here's a new temp
|
||||
memcpy( &master_menu_list[total_masters++], &temp_list[j], sizeof(menu_object)); //
|
||||
|
||||
|
||||
//init top menu from master list
|
||||
for (j=0;j<15;j++)
|
||||
{
|
||||
if (master_menu_list[j].icon_resource)
|
||||
{
|
||||
res = master_menu_list[j].icon_resource; // 'res' is now the resource id of the icon
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// WHEN AN ICON HAS BEEN RIGHT-CLICKED FOR 'EXAMINE' - SELECTION COLOURED, THE REST GREYED OUT
|
||||
|
||||
if (examining_menu_icon) // '1' when examining a menu-icon ('OBJECT_HELD' is the resource of the icon being examined)
|
||||
{
|
||||
if (res == OBJECT_HELD) // if this is the icon being examined, make it coloured
|
||||
icon_coloured=1;
|
||||
else // if not, grey this one out
|
||||
icon_coloured=0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// WHEN ONE MENU OBJECT IS BEING USED WITH ANOTHER - BOTH TO BE COLOURED, THE REST GREYED OUT
|
||||
|
||||
else if (COMBINE_BASE) // resource of second icon clicked
|
||||
{
|
||||
if ((res == OBJECT_HELD)||(res == COMBINE_BASE)) // if this if either of the icons being combined...
|
||||
icon_coloured=1;
|
||||
else
|
||||
icon_coloured=0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// NORMAL ICON SELECTION - SELECTION GREYED OUT, THE REST COLOURED
|
||||
|
||||
else
|
||||
{
|
||||
if (res == OBJECT_HELD) // if this is the selction, grey it out
|
||||
icon_coloured=0;
|
||||
else // if not, make it coloured
|
||||
icon_coloured=1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
if (icon_coloured) // coloured
|
||||
icon = res_man.Res_open( master_menu_list[j].icon_resource ) + sizeof(_standardHeader) + RDMENU_ICONWIDE*RDMENU_ICONDEEP;
|
||||
else // greyed out
|
||||
icon = res_man.Res_open( master_menu_list[j].icon_resource ) + sizeof(_standardHeader);
|
||||
|
||||
SetMenuIcon(RDMENU_BOTTOM, j, icon);
|
||||
res_man.Res_close( res );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMenuIcon(RDMENU_BOTTOM, j, NULL); //no icon here
|
||||
//Zdebug(" NULL for %d", j);
|
||||
}
|
||||
}
|
||||
|
||||
ShowMenu(RDMENU_BOTTOM);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
void Build_system_menu(void) //Tony19Mar97
|
||||
{
|
||||
//start a fresh top system menu
|
||||
|
||||
uint8 *icon;
|
||||
int j;
|
||||
|
||||
uint32 icon_list[5] =
|
||||
{
|
||||
OPTIONS_ICON,
|
||||
QUIT_ICON,
|
||||
SAVE_ICON,
|
||||
RESTORE_ICON,
|
||||
RESTART_ICON
|
||||
};
|
||||
|
||||
|
||||
for (j=0;j<5;j++) //build them all high in full colour - when one is clicked on all the rest will grey out
|
||||
{
|
||||
if ((DEAD)&&(j==2)) //dead then SAVE not available
|
||||
icon = res_man.Res_open( icon_list[j] ) + sizeof(_standardHeader);
|
||||
|
||||
else icon = res_man.Res_open( icon_list[j] ) + sizeof(_standardHeader) + RDMENU_ICONWIDE*RDMENU_ICONDEEP;
|
||||
SetMenuIcon(RDMENU_TOP, j, icon);
|
||||
res_man.Res_close( icon_list[j] );
|
||||
}
|
||||
|
||||
|
||||
ShowMenu(RDMENU_TOP);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
42
sword2/icons.h
Normal file
42
sword2/icons.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _ICONS
|
||||
#define _ICONS
|
||||
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "object.h"
|
||||
|
||||
#define MENU_MASTER_OBJECT 44
|
||||
#define TOTAL_subjects 375-256+1 //the speech subject bar
|
||||
#define TOTAL_engine_pockets 15+10 // +10 for overflow
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 icon_resource; // icon graphic graphic
|
||||
int32 luggage_resource; // luggage icon resource (for attaching to mouse pointer)
|
||||
} menu_object; //define these in a script and then register them with the system
|
||||
|
||||
extern menu_object master_menu_list[TOTAL_engine_pockets];
|
||||
|
||||
void Build_top_menu(void); //Tony19Nov96
|
||||
void Build_system_menu(void); //Tony19Mar97
|
||||
|
||||
#endif
|
791
sword2/interpreter.cpp
Normal file
791
sword2/interpreter.cpp
Normal file
|
@ -0,0 +1,791 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef INSIDE_LINC // Are we running in linc?
|
||||
#include "console.h"
|
||||
#endif
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
||||
|
||||
// This file serves two purposes. It is compiled as part of the test functions
|
||||
// of Linc, and also as part of the game
|
||||
|
||||
|
||||
// The machine code table
|
||||
|
||||
int32 FN_test_function(int32 *params);
|
||||
int32 FN_test_flags(int32 *params);
|
||||
int32 FN_register_start_point(int32 *params);
|
||||
int32 FN_init_background(int32 *params);
|
||||
int32 FN_set_session(int32 *params);
|
||||
int32 FN_back_sprite(int32 *params);
|
||||
int32 FN_sort_sprite(int32 *params);
|
||||
int32 FN_fore_sprite(int32 *params);
|
||||
int32 FN_register_mouse(int32 *params);
|
||||
int32 FN_anim(int32 *);
|
||||
int32 FN_random(int32 *);
|
||||
int32 FN_preload(int32 *);
|
||||
int32 FN_add_subject(int32 *);
|
||||
int32 FN_interact(int32 *);
|
||||
int32 FN_choose(int32 *);
|
||||
int32 FN_walk(int32 *);
|
||||
int32 FN_walk_to_anim(int32 *); // walk to start position of anim
|
||||
int32 FN_turn(int32 *); // turn to (dir)
|
||||
int32 FN_stand_at(int32 *); // stand at (x,y,dir)
|
||||
int32 FN_stand(int32 *); // stand facing (dir)
|
||||
int32 FN_stand_after_anim(int32 *); // stand at end position of anim
|
||||
int32 FN_pause(int32 *);
|
||||
int32 FN_mega_table_anim(int32 *);
|
||||
int32 FN_add_menu_object(int32 *);
|
||||
int32 FN_start_conversation(int32 *);
|
||||
int32 FN_end_conversation(int32 *);
|
||||
int32 FN_set_frame(int32 *);
|
||||
int32 FN_random_pause(int32 *);
|
||||
int32 FN_register_frame(int32 *);
|
||||
int32 FN_no_sprite(int32 *);
|
||||
int32 FN_send_sync(int32 *);
|
||||
int32 FN_update_player_stats(int32 *);
|
||||
int32 FN_pass_graph(int32 *);
|
||||
int32 FN_init_floor_mouse(int32 *);
|
||||
int32 FN_pass_mega(int32 *);
|
||||
int32 FN_face_xy(int32 *);
|
||||
int32 FN_end_session(int32 *);
|
||||
int32 FN_no_human(int32 *);
|
||||
int32 FN_add_human(int32 *);
|
||||
int32 FN_we_wait(int32 *);
|
||||
int32 FN_they_do_we_wait(int32 *);
|
||||
int32 FN_they_do(int32 *);
|
||||
int32 FN_walk_to_talk_to_mega(int32 *);
|
||||
int32 FN_fade_down(int32 *);
|
||||
int32 FN_i_speak(int32 *);
|
||||
int32 FN_total_restart(int32 *);
|
||||
int32 FN_set_walkgrid(int32 *);
|
||||
int32 FN_speech_process(int32 *);
|
||||
int32 FN_set_scaling(int32 *);
|
||||
int32 FN_start_event(int32 *);
|
||||
int32 FN_check_event_waiting(int32 *);
|
||||
int32 FN_request_speech(int32 *);
|
||||
int32 FN_gosub(int32 *);
|
||||
int32 FN_timed_wait(int32 *);
|
||||
int32 FN_play_fx(int32 *);
|
||||
int32 FN_stop_fx(int32 *);
|
||||
int32 FN_play_music(int32 *);
|
||||
int32 FN_stop_music(int32 *);
|
||||
int32 FN_set_value(int32 *);
|
||||
int32 FN_new_script(int32 *);
|
||||
int32 FN_get_sync(int32 *);
|
||||
int32 FN_wait_sync(int32 *);
|
||||
int32 FN_register_walkgrid(int32 *);
|
||||
int32 FN_reverse_mega_table_anim(int32 *);
|
||||
int32 FN_reverse_anim(int32 *);
|
||||
int32 FN_add_to_kill_list(int32 *);
|
||||
int32 FN_set_standby_coords(int32 *);
|
||||
int32 FN_back_par0_sprite(int32 *params);
|
||||
int32 FN_back_par1_sprite(int32 *params);
|
||||
int32 FN_fore_par0_sprite(int32 *params);
|
||||
int32 FN_fore_par1_sprite(int32 *params);
|
||||
int32 FN_fore_par1_sprite(int32 *params);
|
||||
int32 FN_set_player_action_event(int32 *params);
|
||||
int32 FN_set_scroll_coordinate(int32 *params);
|
||||
int32 FN_stand_at_anim(int32 *params);
|
||||
int32 FN_set_scroll_left_mouse(int32 *params);
|
||||
int32 FN_set_scroll_right_mouse(int32 *params);
|
||||
int32 FN_colour(int32 *params);
|
||||
int32 FN_flash(int32 *params);
|
||||
int32 FN_prefetch(int32 *params);
|
||||
int32 FN_get_player_savedata(int32 *params);
|
||||
int32 FN_pass_player_savedata(int32 *params);
|
||||
int32 FN_send_event(int32 *params);
|
||||
int32 FN_add_walkgrid(int32 *params);
|
||||
int32 FN_remove_walkgrid(int32 *params);
|
||||
int32 FN_check_for_event(int32 *params);
|
||||
int32 FN_pause_for_event(int32 *params);
|
||||
int32 FN_clear_event(int32 *params);
|
||||
int32 FN_face_mega(int32 *params);
|
||||
int32 FN_play_sequence(int32 *params);
|
||||
int32 FN_shaded_sprite(int32 *params);
|
||||
int32 FN_unshaded_sprite(int32 *params);
|
||||
int32 FN_fade_up(int32 *params);
|
||||
int32 FN_display_msg(int32 *params);
|
||||
int32 FN_set_object_held(int32 *params);
|
||||
int32 FN_add_sequence_text(int32 *params);
|
||||
int32 FN_reset_globals(int32 *params);
|
||||
int32 FN_set_palette(int32 *params);
|
||||
int32 FN_register_pointer_text(int32 *params);
|
||||
int32 FN_fetch_wait(int32 *params);
|
||||
int32 FN_release(int32 *params);
|
||||
int32 FN_sound_fetch(int32 *params);
|
||||
int32 FN_prepare_music(int32 *params);
|
||||
int32 FN_smacker_lead_in(int32 *params);
|
||||
int32 FN_smacker_lead_out(int32 *params);
|
||||
int32 FN_stop_all_fx(int32 *params);
|
||||
int32 FN_check_player_activity(int32 *params);
|
||||
int32 FN_reset_player_activity_delay(int32 *params);
|
||||
int32 FN_check_music_playing(int32 *params);
|
||||
int32 FN_play_credits(int32 *params);
|
||||
int32 FN_set_scroll_speed_normal(int32 *params);
|
||||
int32 FN_set_scroll_speed_slow(int32 *params);
|
||||
int32 FN_remove_chooser(int32 *params);
|
||||
int32 FN_set_fx_vol_and_pan(int32 *params);
|
||||
int32 FN_set_fx_vol(int32 *params);
|
||||
int32 FN_restore_game(int32 *params);
|
||||
int32 FN_refresh_inventory(int32 *params);
|
||||
int32 FN_change_shadows(int32 *params);
|
||||
|
||||
#define MAX_FN_NUMBER 117
|
||||
|
||||
extern int32 (*McodeTable[])(int32 *);
|
||||
|
||||
#ifndef INSIDE_LINC
|
||||
int32 * globalInterpreterVariables2 = NULL; // Point to the global varibale data
|
||||
int g_debugFlag = 0; // Set this to turn debugging on
|
||||
#endif
|
||||
|
||||
|
||||
int32 (*McodeTable[MAX_FN_NUMBER+1])(int32 *) =
|
||||
{ FN_test_function,
|
||||
FN_test_flags,
|
||||
FN_register_start_point,
|
||||
FN_init_background,
|
||||
FN_set_session,
|
||||
FN_back_sprite,
|
||||
FN_sort_sprite,
|
||||
FN_fore_sprite,
|
||||
FN_register_mouse,
|
||||
FN_anim,
|
||||
FN_random,
|
||||
FN_preload,
|
||||
FN_add_subject,
|
||||
FN_interact,
|
||||
FN_choose,
|
||||
FN_walk,
|
||||
FN_walk_to_anim,
|
||||
FN_turn,
|
||||
FN_stand_at,
|
||||
FN_stand,
|
||||
FN_stand_after_anim,
|
||||
FN_pause,
|
||||
FN_mega_table_anim,
|
||||
FN_add_menu_object,
|
||||
FN_start_conversation,
|
||||
FN_end_conversation,
|
||||
FN_set_frame,
|
||||
FN_random_pause,
|
||||
FN_register_frame,
|
||||
FN_no_sprite,
|
||||
FN_send_sync,
|
||||
FN_update_player_stats,
|
||||
FN_pass_graph,
|
||||
FN_init_floor_mouse,
|
||||
FN_pass_mega,
|
||||
FN_face_xy,
|
||||
FN_end_session,
|
||||
FN_no_human,
|
||||
FN_add_human,
|
||||
FN_we_wait,
|
||||
FN_they_do_we_wait,
|
||||
FN_they_do,
|
||||
FN_walk_to_talk_to_mega,
|
||||
FN_fade_down,
|
||||
FN_i_speak,
|
||||
FN_total_restart,
|
||||
FN_set_walkgrid,
|
||||
FN_speech_process,
|
||||
FN_set_scaling,
|
||||
FN_start_event,
|
||||
FN_check_event_waiting,
|
||||
FN_request_speech,
|
||||
FN_gosub,
|
||||
FN_timed_wait,
|
||||
FN_play_fx,
|
||||
FN_stop_fx,
|
||||
FN_play_music,
|
||||
FN_stop_music,
|
||||
FN_set_value,
|
||||
FN_new_script,
|
||||
FN_get_sync,
|
||||
FN_wait_sync,
|
||||
FN_register_walkgrid,
|
||||
FN_reverse_mega_table_anim,
|
||||
FN_reverse_anim,
|
||||
FN_add_to_kill_list,
|
||||
FN_set_standby_coords,
|
||||
FN_back_par0_sprite,
|
||||
FN_back_par1_sprite,
|
||||
FN_fore_par0_sprite,
|
||||
FN_fore_par1_sprite,
|
||||
FN_set_player_action_event,
|
||||
FN_set_scroll_coordinate,
|
||||
FN_stand_at_anim,
|
||||
FN_set_scroll_left_mouse,
|
||||
FN_set_scroll_right_mouse,
|
||||
FN_colour,
|
||||
FN_flash,
|
||||
FN_prefetch,
|
||||
FN_get_player_savedata,
|
||||
FN_pass_player_savedata,
|
||||
FN_send_event,
|
||||
FN_add_walkgrid,
|
||||
FN_remove_walkgrid,
|
||||
FN_check_for_event,
|
||||
FN_pause_for_event,
|
||||
FN_clear_event,
|
||||
FN_face_mega,
|
||||
FN_play_sequence,
|
||||
FN_shaded_sprite,
|
||||
FN_unshaded_sprite,
|
||||
FN_fade_up,
|
||||
FN_display_msg,
|
||||
FN_set_object_held,
|
||||
FN_add_sequence_text,
|
||||
FN_reset_globals,
|
||||
FN_set_palette,
|
||||
FN_register_pointer_text,
|
||||
FN_fetch_wait,
|
||||
FN_release,
|
||||
FN_prepare_music,
|
||||
FN_sound_fetch,
|
||||
FN_prepare_music,
|
||||
FN_smacker_lead_in,
|
||||
FN_smacker_lead_out,
|
||||
FN_stop_all_fx,
|
||||
FN_check_player_activity,
|
||||
FN_reset_player_activity_delay,
|
||||
FN_check_music_playing,
|
||||
FN_play_credits,
|
||||
FN_set_scroll_speed_normal,
|
||||
FN_set_scroll_speed_slow,
|
||||
FN_remove_chooser,
|
||||
FN_set_fx_vol_and_pan,
|
||||
FN_set_fx_vol,
|
||||
FN_restore_game,
|
||||
FN_refresh_inventory,
|
||||
FN_change_shadows,
|
||||
};
|
||||
|
||||
#define CHECKSTACKPOINTER2 ASSERT((stackPointer2>=0)&&(stackPointer2<STACK_SIZE));
|
||||
#define PUSHONSTACK(x) {stack2[stackPointer2] = (x);stackPointer2++;CHECKSTACKPOINTER2;}
|
||||
#define POPOFFSTACK(x) {x=stack2[stackPointer2-1];stackPointer2--;CHECKSTACKPOINTER2;}
|
||||
#define DOOPERATION(x) {stack2[stackPointer2-2] = (x);stackPointer2--;CHECKSTACKPOINTER2;}
|
||||
|
||||
#ifndef INSIDE_LINC
|
||||
void SetGlobalInterpreterVariables(int32 *vars)
|
||||
{
|
||||
globalInterpreterVariables2 = vars;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INSIDE_LINC // Are we running in linc?
|
||||
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * objectData , uint32 *offset )
|
||||
#else
|
||||
int RunScript ( const char * scriptData , char * objectData , uint32 *offset )
|
||||
#endif
|
||||
{
|
||||
#define STACK_SIZE 10
|
||||
|
||||
_standardHeader *header = (_standardHeader *)scriptData;
|
||||
scriptData += sizeof(_standardHeader) + sizeof(_object_hub);
|
||||
|
||||
// The script data format:
|
||||
|
||||
|
||||
// int32_TYPE 1 Size of variable space in bytes
|
||||
// ... The variable space
|
||||
// int32_TYPE 1 numberOfScripts
|
||||
// int32_TYPE numberOfScripts The offsets for each script
|
||||
|
||||
|
||||
// Initialise some stuff
|
||||
|
||||
int ip = 0; // Code pointer
|
||||
int curCommand,parameter,value; // Command and parameter variables
|
||||
int32 stack2[STACK_SIZE]; // The current stack
|
||||
int32 stackPointer2 = 0; // Position within stack
|
||||
int parameterReturnedFromMcodeFunction=0; // Allow scripts to return things
|
||||
int savedStartOfMcode; // For saving start of mcode commands
|
||||
|
||||
// Get the start of variables and start of code
|
||||
DEBUG3("Enter interpreter data %x, object %x, offset %d",scriptData,objectData,*offset);
|
||||
const char *variables = scriptData + sizeof(int);
|
||||
const char *code = scriptData + *((int *)scriptData) + sizeof(int);
|
||||
uint32 noScripts = *((int32 *)code);
|
||||
if ( (*offset) < noScripts)
|
||||
{ ip = ((int *)code)[(*offset)+1];
|
||||
DEBUG2("Start script %d with offset %d",*offset,ip);
|
||||
}
|
||||
else
|
||||
{ ip = (*offset);
|
||||
DEBUG1("Start script with offset %d",ip);
|
||||
}
|
||||
|
||||
code += noScripts * sizeof(int) + sizeof(int);
|
||||
|
||||
/************************************************************************************************/
|
||||
#ifdef DONTPROCESSSCRIPTCHECKSUM
|
||||
|
||||
code += sizeof(int) * 3;
|
||||
|
||||
#else
|
||||
|
||||
// Code should nopw be pointing at an identifier and a checksum
|
||||
int *checksumBlock = (int *)code;
|
||||
code += sizeof(int) * 3;
|
||||
|
||||
if (checksumBlock[0] != 12345678)
|
||||
{
|
||||
#ifdef INSIDE_LINC
|
||||
AfxMessageBox(CVString("Invalid script in object %s",header->name));
|
||||
#else
|
||||
Con_fatal_error("Invalid script in object %s",header->name);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
int codeLen = checksumBlock[1];
|
||||
int checksum = 0;
|
||||
for (int count = 0 ; count < codeLen ; count++)
|
||||
checksum += (unsigned char)code[count];
|
||||
if ( checksum != checksumBlock[2] )
|
||||
{
|
||||
#ifdef INSIDE_LINC
|
||||
AfxMessageBox(CVString("Checksum error in script %s",header->name));
|
||||
#else
|
||||
Con_fatal_error("Checksum error in object %s",header->name);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif //DONTPROCESSSCRIPTCHECKSUM
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
int runningScript = 1;
|
||||
while ( runningScript )
|
||||
{ curCommand = code[ip++];
|
||||
switch(curCommand)
|
||||
{ case CP_END_SCRIPT: // 0 End the script
|
||||
DEBUG1("End script",0);
|
||||
runningScript = 0;
|
||||
#ifdef INSIDE_LINC
|
||||
engine.AddTextLine( "End script" , VS_COL_GREY );
|
||||
engine.AddTextLine( "" , VS_COL_GREY );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CP_PUSH_LOCAL_VAR32: // 1 Push the contents of a local variable
|
||||
Read16ip(parameter)
|
||||
DEBUG2("Push local var %d (%d)",parameter,*((int *)(variables+parameter)));
|
||||
PUSHONSTACK ( *((int *)(variables+parameter)) );
|
||||
break;
|
||||
|
||||
|
||||
case CP_PUSH_GLOBAL_VAR32: // 2 Push a global variable
|
||||
Read16ip(parameter)
|
||||
#ifdef INSIDE_LINC
|
||||
DEBUG2("Push global var %d (%d)",parameter,g_GlobalVariables.GetLocalByIndex(parameter).GetValue());
|
||||
PUSHONSTACK ( g_GlobalVariables.GetLocalByIndex(parameter).GetValue() );
|
||||
#else
|
||||
DEBUG2("Push global var %d (%d)",parameter,globalInterpreterVariables2[parameter]);
|
||||
ASSERT(globalInterpreterVariables2);
|
||||
PUSHONSTACK ( globalInterpreterVariables2[parameter] );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CP_POP_LOCAL_VAR32: // 3 Pop a value into a local word variable
|
||||
Read16ip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
DEBUG2("Pop %d into var %d",value,parameter);
|
||||
*((int *)(variables+parameter)) = value;
|
||||
break;
|
||||
|
||||
case CP_CALL_MCODE: // 4 Call an mcode routine
|
||||
{
|
||||
Read16ip(parameter)
|
||||
ASSERT(parameter <= MAX_FN_NUMBER);
|
||||
value = *((int8 *)(code+ip)); // amount to adjust stack by (no of parameters)
|
||||
ip ++;
|
||||
DEBUG2("Call mcode %d with stack = %x",parameter,stack2+(stackPointer2-value));
|
||||
#ifdef INSIDE_LINC
|
||||
int retVal = engine.McodeTable(parameter , stack2+(stackPointer2-value));
|
||||
#else
|
||||
int retVal = McodeTable[parameter](stack2+(stackPointer2-value));
|
||||
#endif
|
||||
stackPointer2 -= value;
|
||||
CHECKSTACKPOINTER2
|
||||
switch ( retVal & 7 )
|
||||
{ case IR_STOP: // 0: Quit out for a cycle
|
||||
*offset = ip;
|
||||
return(0);
|
||||
|
||||
case IR_CONT: // 1: // Continue as normal
|
||||
break;
|
||||
|
||||
case IR_TERMINATE: // 2:
|
||||
// Return without updating the offset
|
||||
return(2);
|
||||
|
||||
case IR_REPEAT: // 3:
|
||||
// Return setting offset to start of this function call
|
||||
*offset = savedStartOfMcode;
|
||||
return(0);
|
||||
|
||||
case IR_GOSUB: // 4: //that's really neat
|
||||
*offset = ip;
|
||||
return(2);
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
parameterReturnedFromMcodeFunction = retVal >> 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case CP_PUSH_LOCAL_ADDR: // 5 push the address of a local variable
|
||||
Read16ip(parameter)
|
||||
DEBUG2("Push address of local variable %d (%x)",parameter,(int32)(variables + parameter));
|
||||
PUSHONSTACK ( (int32)(variables + parameter) );
|
||||
break;
|
||||
|
||||
case CP_PUSH_INT32: // 6 Push a long word value on to the stack
|
||||
Read32ip(parameter)
|
||||
DEBUG2("Push int32 %d (%x)",parameter,parameter);
|
||||
PUSHONSTACK ( parameter );
|
||||
break;
|
||||
|
||||
|
||||
case CP_SKIPONFALSE: // 7 Skip if the value on the stack is false
|
||||
Read32ipLeaveip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
DEBUG2("Skip %d if %d is false",parameter,value);
|
||||
if (value)
|
||||
ip += sizeof(int32);
|
||||
else
|
||||
ip += parameter;
|
||||
break;
|
||||
|
||||
case CP_SKIPALLWAYS: // 8 skip a block
|
||||
Read32ipLeaveip(parameter)
|
||||
DEBUG1("Skip %d",parameter);
|
||||
ip += parameter;
|
||||
break;
|
||||
|
||||
case CP_SWITCH: // 9 switch
|
||||
{ POPOFFSTACK ( value );
|
||||
int caseCount;
|
||||
Read32ip(caseCount)
|
||||
// Search the cases
|
||||
int foundCase = 0;
|
||||
for (int count = 0 ; (count < caseCount) && (!foundCase) ; count++)
|
||||
{
|
||||
if (value == *((int32 *)(code+ip)))
|
||||
{ // We have found the case, so lets jump to it
|
||||
foundCase = 1;
|
||||
ip += *((int32 *)(code+ip+sizeof(int32)));
|
||||
}
|
||||
else
|
||||
ip += sizeof(int32) * 2;
|
||||
}
|
||||
// If we found no matching case then use the default
|
||||
if (!foundCase)
|
||||
{
|
||||
ip += *((int32 *)(code+ip));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CP_ADDNPOP_LOCAL_VAR32: // 10
|
||||
Read16ip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
*((int *)(variables+parameter)) += value;
|
||||
DEBUG3("+= %d into var %d->%d",value,parameter,*((int *)(variables+parameter)));
|
||||
break;
|
||||
|
||||
case CP_SUBNPOP_LOCAL_VAR32: // 11
|
||||
Read16ip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
*((int *)(variables+parameter)) -= value;
|
||||
DEBUG3("-= %d into var %d->%d",value,parameter,*((int *)(variables+parameter)));
|
||||
break;
|
||||
|
||||
case CP_SKIPONTRUE: // 12 Skip if the value on the stack is TRUE
|
||||
Read32ipLeaveip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
DEBUG2("Skip %d if %d is false",parameter,value);
|
||||
if (!value)
|
||||
ip += sizeof(int32);
|
||||
else
|
||||
ip += parameter;
|
||||
break;
|
||||
|
||||
case CP_POP_GLOBAL_VAR32: // 13 // Pop a global variable
|
||||
Read16ip(parameter)
|
||||
POPOFFSTACK ( value );
|
||||
DEBUG2("Pop %d into global var %d",value,parameter);
|
||||
#ifdef INSIDE_LINC
|
||||
g_GlobalVariables.lclSet(parameter,value);
|
||||
engine.AddTextLine(CVString( "Set variable %s to %d",
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
|
||||
VS_COL_GREY);
|
||||
#else //INSIDE_LINC
|
||||
|
||||
#ifdef TRACEGLOBALVARIABLESET
|
||||
TRACEGLOBALVARIABLESET(parameter,value);
|
||||
#endif
|
||||
|
||||
globalInterpreterVariables2[parameter] = value;
|
||||
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CP_ADDNPOP_GLOBAL_VAR32: // 14 Add and pop a global variable
|
||||
{ Read16ip(parameter)
|
||||
// parameter = *((int16_TYPE *)(code+ip));
|
||||
// ip += 2;
|
||||
POPOFFSTACK ( value );
|
||||
#ifdef INSIDE_LINC
|
||||
int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() + value ;
|
||||
g_GlobalVariables.lclSet(parameter, newVal );
|
||||
engine.AddTextLine( CVString( "Set variable %s to %d",
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
|
||||
VS_COL_GREY);
|
||||
#else
|
||||
globalInterpreterVariables2[parameter] += value;
|
||||
DEBUG3("+= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter)));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case CP_SUBNPOP_GLOBAL_VAR32: // 15 Sub and pop a global variable
|
||||
{ Read16ip(parameter)
|
||||
// parameter = *((int16_TYPE *)(code+ip));
|
||||
// ip += 2;
|
||||
POPOFFSTACK ( value );
|
||||
#ifdef INSIDE_LINC
|
||||
int newVal = g_GlobalVariables.GetLocalByIndex(parameter).GetValue() - value ;
|
||||
g_GlobalVariables.lclSet(parameter, newVal );
|
||||
engine.AddTextLine( CVString( "Set variable %s to %d",
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetName(),
|
||||
g_GlobalVariables.GetLocalByIndex(parameter).GetValue() ),
|
||||
VS_COL_GREY);
|
||||
#else
|
||||
globalInterpreterVariables2[parameter] -= value;
|
||||
DEBUG3("-= %d into global var %d->%d",value,parameter,*((int *)(variables+parameter)));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case CP_DEBUGON:
|
||||
// Turn debugging on
|
||||
g_debugFlag = 1;
|
||||
break;
|
||||
|
||||
case CP_DEBUGOFF:
|
||||
// Turn debugging on
|
||||
g_debugFlag = 0;
|
||||
break;
|
||||
|
||||
case CP_QUIT:
|
||||
#ifdef INSIDE_LINC
|
||||
break;
|
||||
#else
|
||||
// Quit out for a cycle
|
||||
*offset = ip;
|
||||
return(0);
|
||||
#endif
|
||||
|
||||
case CP_TERMINATE:
|
||||
// Quit out immediately without affecting the offset pointer
|
||||
return(3);
|
||||
|
||||
/******************************************************************************************************************
|
||||
******************************************************************************************************************/
|
||||
|
||||
// Operators
|
||||
|
||||
case OP_ISEQUAL: // 20 // '=='
|
||||
DEBUG3("%d == %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] == stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] == stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_PLUS: // 21 // '+'
|
||||
DEBUG3("%d + %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] + stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] + stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_MINUS: // 22 // '+'
|
||||
DEBUG3("%d - %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] - stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] - stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_TIMES: // 23 // '+'
|
||||
DEBUG3("%d * %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] * stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] * stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_DEVIDE: // 24 // '+'
|
||||
DEBUG3("%d / %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] / stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] / stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_NOTEQUAL: // 25 // '!='
|
||||
DEBUG3("%d != %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] != stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] != stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_ANDAND: // 26
|
||||
DEBUG3("%d != %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] && stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] && stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_GTTHAN: // 27 >
|
||||
DEBUG3("%d > %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] > stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] > stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_LSTHAN: // 28 <
|
||||
DEBUG3("%d < %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] < stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] < stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case CP_JUMP_ON_RETURNED: // 29
|
||||
{ // Jump to a part of the script depending on the return value from an mcode routine
|
||||
parameter = *((int8 *)(code+ip)); // Get the maximum value
|
||||
ip++;
|
||||
#ifdef INSIDE_LINC
|
||||
TRACE("ip %d: Parameter %d skip %d\r\n", ip,
|
||||
parameterReturnedFromMcodeFunction,
|
||||
((int32*)(code+ip))[parameterReturnedFromMcodeFunction] );
|
||||
#endif
|
||||
|
||||
ip += ((int32 *)(code+ip))[parameterReturnedFromMcodeFunction];
|
||||
}
|
||||
break;
|
||||
|
||||
case CP_TEMP_TEXT_PROCESS: // 30
|
||||
// Process a text line
|
||||
Read32ip(parameter)
|
||||
// parameter = *((int32_TYPE *)(code+ip));
|
||||
// ip += sizeof(int32_TYPE);;
|
||||
DEBUG1("Process text id %d",parameter);
|
||||
#ifdef INSIDE_LINC
|
||||
// Linc only for the moment
|
||||
engine.ProcessTextLine(parameter);
|
||||
#endif //INSIDE_LINC
|
||||
break;
|
||||
|
||||
case CP_SAVE_MCODE_START: // 31
|
||||
// Save the start position on an mcode instruction in case we need to restart it again
|
||||
savedStartOfMcode = ip-1;
|
||||
break;
|
||||
|
||||
case CP_RESTART_SCRIPT: // 32
|
||||
{ // Start the script again
|
||||
// Do a ip search to find the script we are running
|
||||
const char *tempScrPtr = scriptData + *((int *)scriptData) + sizeof(int);
|
||||
int scriptNumber = 0;
|
||||
int foundScript = 0;
|
||||
uint32 count = 0;
|
||||
for (count = 1 ; (count < noScripts) && (!foundScript) ; count++)
|
||||
{ if (ip < ((int *)tempScrPtr)[count+1])
|
||||
{ scriptNumber = count - 1 ;
|
||||
foundScript = 1;
|
||||
}
|
||||
}
|
||||
if (!foundScript)
|
||||
scriptNumber = count - 1 ;
|
||||
// So we know what script we are running, lets restart it
|
||||
ip = ((int *)tempScrPtr)[scriptNumber+1];
|
||||
break;
|
||||
}
|
||||
|
||||
case CP_PUSH_STRING: // 33
|
||||
{ // Push the address of a string on to the stack
|
||||
parameter = *((int8 *)(code+ip)); // Get the string size
|
||||
ip += 1;
|
||||
// ip points to the string
|
||||
PUSHONSTACK( (int)(code+ip) );
|
||||
ip += (parameter+1);
|
||||
break;
|
||||
}
|
||||
|
||||
case CP_PUSH_DEREFERENCED_STRUCTURE: // 34
|
||||
{ // Push the address of a dereferenced structure
|
||||
Read32ip(parameter)
|
||||
DEBUG1("Push address of far variable (%x)",(int32)(variables + parameter));
|
||||
PUSHONSTACK( (int)(objectData + sizeof(int) + sizeof(_standardHeader) + sizeof(_object_hub) + parameter));
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_GTTHANE: // 35 >=
|
||||
DEBUG3("%d > %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] >= stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] >= stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_LSTHANE: // 36 <=
|
||||
DEBUG3("%d < %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] <= stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] <= stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
case OP_OROR: // 37
|
||||
DEBUG3("%d || %d -> %d", stack2[stackPointer2-2],
|
||||
stack2[stackPointer2-1],
|
||||
stack2[stackPointer2-2] || stack2[stackPointer2-1]);
|
||||
DOOPERATION ( (stack2[stackPointer2-2] || stack2[stackPointer2-1]) );
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
#ifdef INSIDE_LINC
|
||||
AfxMessageBox(CVString("Invalid interpreter token %d",curCommand));
|
||||
#else
|
||||
Con_fatal_error("Interpreter error: Invalid token %d", curCommand);
|
||||
#endif
|
||||
return(3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
173
sword2/interpreter.h
Normal file
173
sword2/interpreter.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
// Interpreter return codes
|
||||
|
||||
#define IR_STOP 0
|
||||
#define IR_CONT 1
|
||||
#define IR_TERMINATE 2
|
||||
#define IR_REPEAT 3
|
||||
#define IR_GOSUB 4
|
||||
|
||||
|
||||
#ifdef INSIDE_LINC // Are we running in linc?
|
||||
|
||||
extern int g_debugFlag;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#define DEBUG1(x,y) if(g_debugFlag){engine.AddTextLine(CVString(x,y),VS_COL_DEBUG);}
|
||||
#define DEBUG2(x,y,z) if(g_debugFlag){engine.AddTextLine(CVString(x,y,z),VS_COL_DEBUG);}
|
||||
#define DEBUG3(x,y,z,a) if(g_debugFlag){engine.AddTextLine(CVString(x,y,z,a),VS_COL_DEBUG);}
|
||||
|
||||
#else //_DEBUG
|
||||
|
||||
#define DEBUG1
|
||||
#define DEBUG2
|
||||
#define DEBUG3
|
||||
|
||||
#endif //_DEBUG
|
||||
|
||||
#else //INSIDE_LINC
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "debug.h"
|
||||
#include "header.h"
|
||||
|
||||
#define DEBUG1 if(g_debugFlag)Zdebug
|
||||
#define DEBUG2 if(g_debugFlag)Zdebug
|
||||
#define DEBUG3 if(g_debugFlag)Zdebug
|
||||
|
||||
#define ASSERT(x) {if(!(x)){Zdebug("Interpreter ASSERT %s,%d",__FILE__,__LINE__);Con_fatal_error("Assert error in interpreter");}}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Get parameter fix so that the playstation version can handle words not on word boundaries
|
||||
#define Read16ip(var) {var = *((int16 *)(code+ip));ip+=sizeof(int16);}
|
||||
#define Read32ip(var) {var = *((int32 *)(code+ip));ip+=sizeof(int32);}
|
||||
#define Read32ipLeaveip(var) {var = *((int32 *)(code+ip));}
|
||||
|
||||
void SetGlobalInterpreterVariables(int32 *vars);
|
||||
|
||||
#ifdef INSIDE_LINC // Are we running in linc?
|
||||
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * /*objectData*/ , uint32 *offset );
|
||||
#else
|
||||
int RunScript ( const char * scriptData , char * /*objectData*/ , uint32 *offset );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Command tokens
|
||||
|
||||
#define CT_COMMENT 1 // A program comment
|
||||
#define CT_IF 2 // An if statement
|
||||
#define CT_OPENBRACKET 3 // (
|
||||
#define CT_CLOSEBRACKET 4 // )
|
||||
#define CT_VAR 5 // Define a variable
|
||||
#define CT_SEMICOLON 6 // ;
|
||||
#define CT_COMMA 7 // ,
|
||||
#define CT_OPENBRACE 8 // {
|
||||
#define CT_CLOSEBRACE 9 // }
|
||||
#define CT_STRUCT 10 // Struct
|
||||
#define CT_SWITCH 11 // Switch
|
||||
#define CT_CASE 12 // Case
|
||||
#define CT_BREAK 13 // break
|
||||
#define CT_DEFAULT 14 // default
|
||||
#define CT_ASSIGN 14 // =
|
||||
#define CT_PLUSEQ 15 // '+='
|
||||
#define CT_MINUSEQ 16 // '-='
|
||||
#define CT_FOR 17 // for
|
||||
#define CT_DO 18 // do
|
||||
#define CT_WHILE 19 // while
|
||||
#define CT_DEBUGON 20 // Turn debugging on
|
||||
#define CT_DEBUGOFF 21 // Turn debugging off
|
||||
#define CT_QUIT 22 // Quit for a cycle
|
||||
#define CT_ENDIF 23 // Endif
|
||||
#define CT_TEXTOBJECT 24 // Speaker: text line
|
||||
#define CT_ANIM 25 // An animation
|
||||
#define CT_ELSE 26 // else to an if
|
||||
#define CT_CHOOSE 27 // Start a chooser
|
||||
#define CT_END 28 // end, usually followed by something else
|
||||
#define CT_END_CHOICE 29 // end choice
|
||||
#define CT_TERMINATE 30 // Terminate
|
||||
#define CT_PAUSE 31 // Pause
|
||||
#define CT_RESTART 32 // Restart script
|
||||
#define CT_START 33 // Start conversation
|
||||
#define CT_CALL 34 // Call a character
|
||||
#define CT_ACTORSCOMMENT 35 // A comment for an actor
|
||||
#define CT_TALKER 36 // A set talker command
|
||||
|
||||
// Special functions
|
||||
|
||||
#define SF_RUNLIST 1
|
||||
#define SF_DOUBLEQUOTE 2
|
||||
#define SF_BACKGROUND 3
|
||||
#define SF_SCALEA 4
|
||||
#define SF_SCALEB 5
|
||||
#define SF_SPEECHSCRIPT 6
|
||||
|
||||
// Compiled tokens
|
||||
|
||||
#define CP_END_SCRIPT 0
|
||||
#define CP_PUSH_LOCAL_VAR32 1 // Push a local variable on to the stack
|
||||
#define CP_PUSH_GLOBAL_VAR32 2 // Push a global variable
|
||||
#define CP_POP_LOCAL_VAR32 3 // Pop a local variable from the stack
|
||||
#define CP_CALL_MCODE 4 // Call a machine code function
|
||||
#define CP_PUSH_LOCAL_ADDR 5 // Push the address of a local variable
|
||||
#define CP_PUSH_INT32 6 // Adjust the stack after calling an fn function
|
||||
#define CP_SKIPONFALSE 7 // Skip if the bottom value on the stack is false
|
||||
#define CP_SKIPALLWAYS 8 // Skip a block of code
|
||||
#define CP_SWITCH 9 // Switch on last stack value
|
||||
#define CP_ADDNPOP_LOCAL_VAR32 10 // Add to a local varible
|
||||
#define CP_SUBNPOP_LOCAL_VAR32 11 // Subtract to a local variable
|
||||
#define CP_SKIPONTRUE 12 // Skip if the bottom value on the stack is true
|
||||
#define CP_POP_GLOBAL_VAR32 13 // Pop a global variable
|
||||
#define CP_ADDNPOP_GLOBAL_VAR32 14
|
||||
#define CP_SUBNPOP_GLOBAL_VAR32 15
|
||||
#define CP_DEBUGON 16 // Turn debugging on
|
||||
#define CP_DEBUGOFF 17 // Turn debugging off
|
||||
#define CP_QUIT 18 // Quit for a cycle
|
||||
#define CP_TERMINATE 19 // Quit script completely
|
||||
|
||||
// Operators
|
||||
|
||||
#define OP_ISEQUAL 20 // '=='
|
||||
#define OP_PLUS 21 // '+'
|
||||
#define OP_MINUS 22 // '-'
|
||||
#define OP_TIMES 23 // '*'
|
||||
#define OP_DEVIDE 24 // '/'
|
||||
#define OP_NOTEQUAL 25 // '=='
|
||||
#define OP_ANDAND 26 // &&
|
||||
#define OP_GTTHAN 27 // >
|
||||
#define OP_LSTHAN 28 // <
|
||||
|
||||
// More tokens, mixed types
|
||||
|
||||
#define CP_JUMP_ON_RETURNED 29 // Use table of jumps with value returned from fn_mcode
|
||||
#define CP_TEMP_TEXT_PROCESS 30 // A dummy text process command for me
|
||||
#define CP_SAVE_MCODE_START 31 // Save the mcode code start for restarting when necessary
|
||||
#define CP_RESTART_SCRIPT 32 // Start the script from the beginning
|
||||
#define CP_PUSH_STRING 33 // Push a pointer to a string on the stack
|
||||
#define CP_PUSH_DEREFERENCED_STRUCTURE 34 // Push the address of a structure thing
|
||||
|
||||
#define OP_GTTHANE 35 // >=
|
||||
#define OP_LSTHANE 36 // <=
|
||||
#define OP_OROR 37 // || or OR
|
297
sword2/layers.cpp
Normal file
297
sword2/layers.cpp
Normal file
|
@ -0,0 +1,297 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//high level layer initialising
|
||||
|
||||
//the system supports:
|
||||
// 1 optional background parallax layer
|
||||
// 1 not optional normal backdrop layer
|
||||
// 3 normal sorted layers
|
||||
// up to 2 foreground parallax layers
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "header.h"
|
||||
#include "layers.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "sound.h" // (James22july97) for Clear_fx_queue() called from FN_init_background()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
screen_info this_screen; //this_screen describes the current back buffer and its in-game scroll positions, etc.
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_init_background(int32 *params) //Tony11Sept96
|
||||
{
|
||||
//param 0 res id of normal background layer - cannot be 0
|
||||
//param 1 1 yes 0 no for a new palette
|
||||
//this screen defines the size of the back buffer
|
||||
|
||||
_multiScreenHeader *screenLayerTable; // James 06feb97
|
||||
_screenHeader *screen_head;
|
||||
_layerHeader *layer;
|
||||
_spriteInfo spriteInfo;
|
||||
uint32 j;
|
||||
uint8 *file;
|
||||
uint32 rv;
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
// Write to walkthrough file (zebug0.txt)
|
||||
#ifdef _DEBUG
|
||||
Zdebug(0,"=====================================");
|
||||
Zdebug(0,"CHANGED TO LOCATION \"%s\"", FetchObjectName(*params));
|
||||
Zdebug(0,"=====================================");
|
||||
|
||||
// Also write this to system debug file
|
||||
Zdebug("=====================================");
|
||||
Zdebug("CHANGED TO LOCATION \"%s\"", FetchObjectName(*params));
|
||||
Zdebug("=====================================");
|
||||
#endif
|
||||
//--------------------------------------
|
||||
|
||||
Clear_fx_queue(); // stops all fx & clears the queue (James22july97)
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
Zdebug("FN_init_background(%d)", *params);
|
||||
|
||||
if (!*params)
|
||||
{
|
||||
Con_fatal_error("ERROR: FN_set_background cannot have 0 for background layer id! (%s line=%u)",__FILE__,__LINE__);
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// if the screen is still fading down then wait for black
|
||||
do
|
||||
{
|
||||
ServiceWindows();
|
||||
}
|
||||
while(GetFadeStatus()==RDFADE_DOWN);
|
||||
//-------------------------------------------------------
|
||||
|
||||
if (this_screen.mask_flag) // if last screen was using a shading mask (see below) (James 08apr97)
|
||||
{
|
||||
rv = CloseLightMask();
|
||||
|
||||
if (rv)
|
||||
ExitWithReport("Driver Error %.8x [%s line %u]", rv, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// New stuff for faster screen drivers (James 06feb97)
|
||||
|
||||
if (this_screen.background_layer_id) // for drivers: close the previous screen if one is open
|
||||
CloseBackgroundLayer();
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
|
||||
this_screen.background_layer_id=*params; //set the res id
|
||||
this_screen.new_palette = *(params+1); //yes or no - palette is taken from layer file
|
||||
|
||||
|
||||
//ok, now read the resource and pull out all the normal sort layer info
|
||||
//and set them up at the beginning of the sort list - why do it each cycle
|
||||
|
||||
|
||||
file = res_man.Res_open(this_screen.background_layer_id); //file points to 1st byte in the layer file
|
||||
|
||||
screen_head = FetchScreenHeader(file);
|
||||
|
||||
this_screen.number_of_layers= screen_head->noLayers; //set number of special sort layers
|
||||
this_screen.screen_wide = screen_head->width;
|
||||
this_screen.screen_deep = screen_head->height;
|
||||
|
||||
Zdebug("res test layers=%d width=%d depth=%d", screen_head->noLayers, screen_head->width, screen_head->height);
|
||||
|
||||
SetLocationMetrics(screen_head->width, screen_head->height); //initialise the driver back buffer
|
||||
|
||||
|
||||
if (screen_head->noLayers)
|
||||
for (j=0;j<screen_head->noLayers;j++)
|
||||
{
|
||||
layer=FetchLayerHeader(file,j); //get layer header for layer j
|
||||
|
||||
// add into the sort list
|
||||
|
||||
sort_list[j].sort_y = layer->y+layer->height; //need this for sorting - but leave the rest blank, we'll take from the header at print time
|
||||
sort_list[j].layer_number=j+1; //signifies a layer
|
||||
|
||||
Zdebug("init layer %d", j);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//using the screen size setup the scrolling variables
|
||||
|
||||
if( ((screen_head->width) > screenWide) || (screen_head->height>screenDeep) ) // if layer is larger than physical screen
|
||||
{
|
||||
this_screen.scroll_flag = 2; //switch on scrolling (2 means first time on screen)
|
||||
|
||||
// note, if we've already set the player up then we could do the initial scroll set here
|
||||
|
||||
this_screen.scroll_offset_x = 0; //reset scroll offsets
|
||||
this_screen.scroll_offset_y = 0;
|
||||
|
||||
// calc max allowed offsets (to prevent scrolling off edge) - MOVE TO NEW_SCREEN in GTM_CORE.C !!
|
||||
this_screen.max_scroll_offset_x = screen_head->width-screenWide; // NB. min scroll offsets are both zero
|
||||
this_screen.max_scroll_offset_y = screen_head->height-(screenDeep-(RDMENU_MENUDEEP*2)); // 'screenDeep' includes the menu's, so take away 80 pixels
|
||||
}
|
||||
else //layer fits on physical screen - scrolling not required
|
||||
{
|
||||
this_screen.scroll_flag = 0; //switch off scrolling
|
||||
this_screen.scroll_offset_x = 0; //reset scroll offsets
|
||||
this_screen.scroll_offset_y = 0;
|
||||
}
|
||||
|
||||
ResetRenderEngine(); //no inter-cycle scrol between new screens (see setScrollTarget in build display)
|
||||
|
||||
// these are the physical screen coords where the system
|
||||
// will try to maintain George's actual feet coords
|
||||
this_screen.feet_x=320;
|
||||
this_screen.feet_y=340;
|
||||
|
||||
|
||||
//----------------------------------------------------
|
||||
// shading mask
|
||||
|
||||
screenLayerTable = (_multiScreenHeader *) ((uint8 *) file + sizeof(_standardHeader));
|
||||
|
||||
if (screenLayerTable->maskOffset)
|
||||
{
|
||||
spriteInfo.x = 0;
|
||||
spriteInfo.y = 0;
|
||||
spriteInfo.w = screen_head->width;
|
||||
spriteInfo.h = screen_head->height;
|
||||
spriteInfo.scale = 0;
|
||||
spriteInfo.scaledWidth = 0;
|
||||
spriteInfo.scaledHeight = 0;
|
||||
spriteInfo.type = 0;
|
||||
spriteInfo.blend = 0;
|
||||
spriteInfo.data = FetchShadingMask(file);
|
||||
spriteInfo.colourTable = 0;
|
||||
|
||||
rv = OpenLightMask( &spriteInfo );
|
||||
if (rv)
|
||||
ExitWithReport("Driver Error %.8x [%s line %u]", rv, __FILE__, __LINE__);
|
||||
|
||||
this_screen.mask_flag=1; // so we know to close it later! (see above)
|
||||
}
|
||||
else
|
||||
this_screen.mask_flag=0; // no need to close a mask later
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
res_man.Res_close(this_screen.background_layer_id); //close the screen file
|
||||
|
||||
SetUpBackgroundLayers();
|
||||
|
||||
|
||||
Zdebug("end init");
|
||||
return(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// called from FN_init_background & also from control panel
|
||||
|
||||
void SetUpBackgroundLayers(void) // James(13jun97)
|
||||
{
|
||||
_multiScreenHeader *screenLayerTable; // James 06feb97
|
||||
_screenHeader *screen_head;
|
||||
uint8 *file;
|
||||
|
||||
|
||||
if (this_screen.background_layer_id) // if we actually have a screen to initialise (in case called from control panel)
|
||||
{
|
||||
//------------------------------
|
||||
// open resource & set pointers to headers
|
||||
|
||||
file = res_man.Res_open(this_screen.background_layer_id); //file points to 1st byte in the layer file
|
||||
|
||||
screen_head = FetchScreenHeader(file);
|
||||
|
||||
screenLayerTable = (_multiScreenHeader *) ((uint8 *) file + sizeof(_standardHeader));
|
||||
|
||||
//------------------------------
|
||||
// first background parallax
|
||||
|
||||
if (screenLayerTable->bg_parallax[0])
|
||||
InitialiseBackgroundLayer(FetchBackgroundParallaxLayer(file,0));
|
||||
else
|
||||
InitialiseBackgroundLayer(NULL);
|
||||
|
||||
//------------------------------
|
||||
// second background parallax
|
||||
|
||||
if (screenLayerTable->bg_parallax[1])
|
||||
InitialiseBackgroundLayer(FetchBackgroundParallaxLayer(file,1));
|
||||
else
|
||||
InitialiseBackgroundLayer(NULL);
|
||||
|
||||
//------------------------------
|
||||
// normal backround layer
|
||||
|
||||
InitialiseBackgroundLayer(FetchBackgroundLayer(file));
|
||||
|
||||
//------------------------------
|
||||
// first foreground parallax
|
||||
|
||||
if (screenLayerTable->fg_parallax[0])
|
||||
InitialiseBackgroundLayer(FetchForegroundParallaxLayer(file,0));
|
||||
else
|
||||
InitialiseBackgroundLayer(NULL);
|
||||
|
||||
//------------------------------
|
||||
// second foreground parallax
|
||||
|
||||
if (screenLayerTable->fg_parallax[1])
|
||||
InitialiseBackgroundLayer(FetchForegroundParallaxLayer(file,1));
|
||||
else
|
||||
InitialiseBackgroundLayer(NULL);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
res_man.Res_close(this_screen.background_layer_id); //close the screen file
|
||||
|
||||
//----------------------------------------------------
|
||||
}
|
||||
else // no current screen to initialise! (In case called from control panel)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
61
sword2/layers.h
Normal file
61
sword2/layers.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _LAYERS
|
||||
#define _LAYERS
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 scroll_offset_x; // position x
|
||||
uint16 scroll_offset_y; // position y
|
||||
uint16 max_scroll_offset_x; // calc'ed in FN_init_background
|
||||
uint16 max_scroll_offset_y; //
|
||||
int16 player_feet_x; // feet coordinates to use - cant just fetch the player compact anymore
|
||||
int16 player_feet_y;
|
||||
int16 feet_x; // special offset-to-player position - tweek as desired - always set in screen manager object startup
|
||||
int16 feet_y;
|
||||
uint16 screen_wide; // size of background layer - hense size of back buffer itself (Paul actually malloc's it)
|
||||
uint16 screen_deep;
|
||||
uint32 background_layer_id; //id of the normal background layer
|
||||
uint16 number_of_layers; // from the header of the main background layer
|
||||
uint8 new_palette; // set to non zero to start the palette held within layer file fading up after a build_display
|
||||
uint8 scroll_flag; // scroll mode 0 off 1 on
|
||||
uint8 mask_flag; // using shading mask
|
||||
} screen_info;
|
||||
|
||||
|
||||
extern screen_info this_screen;
|
||||
|
||||
|
||||
int32 FN_init_background(int32 *params); // Tony11Sept96
|
||||
void SetUpBackgroundLayers(void); // James(13jun97) called from control panel (as well as inside FN_init_background)
|
||||
|
||||
|
||||
|
||||
#endif
|
441
sword2/logic.cpp
Normal file
441
sword2/logic.cpp
Normal file
|
@ -0,0 +1,441 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// #include <libsn.h> PSX?
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "header.h"
|
||||
#include "interpreter.h"
|
||||
#include "logic.h"
|
||||
#include "memory.h"
|
||||
#include "resman.h"
|
||||
#include "router.h" // for ClearWalkGridList()
|
||||
#include "sound.h"
|
||||
#include "sword2.h" // (James19aug97) for CloseGame()
|
||||
#include "sync.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
logic LLogic; //declare the object
|
||||
|
||||
#define LEVEL cur_object_hub->logic_level
|
||||
|
||||
#define OBJECT_KILL_LIST_SIZE 50 // this must allow for the largest number of objects in a screen
|
||||
|
||||
uint32 object_kill_list[OBJECT_KILL_LIST_SIZE];
|
||||
uint32 kills=0; // keeps note of no. of objects in the kill list
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
int logic::Process_session(void) //Tony6June96 (first run 21Oct96)
|
||||
{
|
||||
//do one cycle of the current session
|
||||
|
||||
|
||||
|
||||
uint32 run_list;
|
||||
uint32 ret,script;
|
||||
uint32 *game_object_list;
|
||||
char *raw_script_ad;
|
||||
char *raw_data_ad;
|
||||
uint32 null_pc;
|
||||
_standardHeader *head;
|
||||
_standardHeader *far_head;
|
||||
uint32 id;
|
||||
|
||||
run_list=current_run_list; //might change during the session, so take a copy here
|
||||
pc=0; //point to first object in list
|
||||
|
||||
static uint32 cycle=0;
|
||||
|
||||
|
||||
cycle++;
|
||||
// Zdebug("\n CYCLE %d", cycle);
|
||||
|
||||
while(pc!=0xffffffff) //by minusing the pc we can cause an immediate cessation of logic processing on the current list
|
||||
{
|
||||
head = (_standardHeader*) res_man.Res_open(run_list);
|
||||
if (head->fileType!=RUN_LIST)
|
||||
Con_fatal_error("Logic_engine %d not a run_list", run_list);
|
||||
|
||||
game_object_list = (uint32 *) (head+1);
|
||||
ID = game_object_list[pc++]; //read the next id
|
||||
id=ID;
|
||||
res_man.Res_close(run_list); //release the list again so it can float in memory - at this point not one thing should be locked
|
||||
|
||||
|
||||
// Zdebug("%d", ID);
|
||||
|
||||
if (!ID) //null terminated
|
||||
return(0); //end the session naturally
|
||||
|
||||
head = (_standardHeader*) res_man.Res_open(ID);
|
||||
if (head->fileType!=GAME_OBJECT)
|
||||
Con_fatal_error("Logic_engine %d not an object", ID);
|
||||
|
||||
cur_object_hub = (_object_hub *) (head+1);
|
||||
|
||||
// Zdebug(" %d id(%d) pc(%d)", cur_object_hub->logic_level, cur_object_hub->script_id[cur_object_hub->logic_level], cur_object_hub->script_pc[cur_object_hub->logic_level]);
|
||||
|
||||
|
||||
|
||||
// do the logic for this object
|
||||
// we keep going until a function says to stop - remember, system operations are run via function calls to drivers now
|
||||
do
|
||||
{
|
||||
script = cur_object_hub->script_id[LEVEL]; //get the script id as we may be running a script from another object...
|
||||
|
||||
|
||||
// there is a distinction between running one of our own scripts and that of another object
|
||||
if ((script/SIZE)==ID) //its our script
|
||||
{
|
||||
// Zdebug("run script %d pc%d", script/SIZE, cur_object_hub->script_pc[LEVEL]);
|
||||
|
||||
// raw_script_ad = (char *) (cur_object_hub+1); //this is the script data
|
||||
|
||||
raw_script_ad = (char*) head;
|
||||
|
||||
ret=RunScript( raw_script_ad, raw_script_ad, &cur_object_hub->script_pc[LEVEL] ); //script and data object are us/same
|
||||
|
||||
}
|
||||
else //we're running the script of another game object - get our data object address
|
||||
{
|
||||
// get the foreign objects script data address
|
||||
|
||||
raw_data_ad=(char*)head;
|
||||
|
||||
far_head = (_standardHeader*) res_man.Res_open(script/SIZE);
|
||||
if ((far_head->fileType!=GAME_OBJECT)&&((far_head->fileType!=SCREEN_MANAGER)))
|
||||
Con_fatal_error("Logic_engine %d not a far object (its a %d)", script/SIZE, far_head->fileType);
|
||||
|
||||
// raw_script_ad = (char*) (head+1) + sizeof(_standardHeader);
|
||||
|
||||
// get our objects data address
|
||||
// raw_data_ad = (char*) (cur_object_hub+1);
|
||||
|
||||
raw_script_ad=(char*)far_head;
|
||||
|
||||
ret=RunScript( raw_script_ad, raw_data_ad, &cur_object_hub->script_pc[LEVEL] );
|
||||
|
||||
res_man.Res_close(script/SIZE); //close foreign object again
|
||||
|
||||
raw_script_ad=raw_data_ad; //reset to us for service script
|
||||
}
|
||||
|
||||
if (ret==1) //this script has finished - drop down a level
|
||||
{
|
||||
if (cur_object_hub->logic_level) //check that it's not already on level 0 !
|
||||
cur_object_hub->logic_level--;
|
||||
else //Hmmm, level 0 terminated :-| Let's be different this time and simply let it restart next go :-)
|
||||
{
|
||||
cur_object_hub->script_pc[LEVEL]=(cur_object_hub->script_id[LEVEL]&0xffff); //reset to rerun
|
||||
// Zdebug("**WARNING object %d script 0 terminated!", id);
|
||||
ret=0; //cause us to drop out for a cycle
|
||||
}
|
||||
}
|
||||
else if (ret>2)
|
||||
{
|
||||
Con_fatal_error("Process_session: illegal script return type %d (%s line %u)",ret,__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
// if ret==2 then we simply go around again - a new script or subroutine will kick in and run
|
||||
|
||||
}
|
||||
while(ret); //keep processing scripts until 0 for quit is returned
|
||||
|
||||
|
||||
// any post logic system requests to go here
|
||||
|
||||
Clear_syncs(ID); //clear any syncs that were waiting for this character - it has used them or now looses them
|
||||
|
||||
if (pc!=0xffffffff) //the session is still valid so run the service script
|
||||
{ null_pc=0;
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc ); //call the base script - this is the graphic/mouse service call
|
||||
}
|
||||
//made for all live objects
|
||||
|
||||
// and that's it so close the object resource
|
||||
res_man.Res_close(ID);
|
||||
};
|
||||
|
||||
|
||||
Process_kill_list(); //leaving a room so remove all ids that must reboot correctly
|
||||
|
||||
Zdebug("RESTART the loop");
|
||||
|
||||
|
||||
return(1); //means restart the loop
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Express_change_session(uint32 sesh_id) //Tony6June96
|
||||
{
|
||||
//a game-object can bring an immediate halt to the session and cause a new one to start without a screen update
|
||||
|
||||
current_run_list=sesh_id; //set to new
|
||||
pc=0xffffffff; //causes session to quit
|
||||
|
||||
EXIT_FADING=0; // reset now in case we double-clicked an exit prior to changing screen
|
||||
|
||||
Init_sync_system(); // we're trashing the list - presumably to change room
|
||||
// in theory sync waiting in the list could be left behind and never removed - so we trash the lot
|
||||
|
||||
ClearWalkGridList(); // reset walkgrid list (see FN_register_walkgrid)
|
||||
Clear_fx_queue(); // stops all fx & clears the queue
|
||||
FreeAllRouteMem(); // free all the route memory blocks from previous game
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Natural_change_session(uint32 sesh_id) //Tony7June96
|
||||
{
|
||||
//a new session will begin next game cycle.
|
||||
//the current cycle will conclude and build the screen and flip into view as normal
|
||||
|
||||
current_run_list=sesh_id; //set to new
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 logic::Return_run_list(void) //Tony18Sept96
|
||||
{
|
||||
//pass back the private cur_object_list variable - not sure we need this
|
||||
|
||||
return(current_run_list); //return the id
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_session(int32 *params) //Tony29Oct96
|
||||
{
|
||||
//used by player invoked start scripts
|
||||
|
||||
//param 0 id of new run list
|
||||
LLogic.Express_change_session(*params); //now!
|
||||
|
||||
return(IR_CONT); //cont
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_end_session(int32 *params) //Tony21Sept96
|
||||
{
|
||||
//causes no more objects in this logic loop to be processed
|
||||
//the logic engine will restart at the beginning of the new list
|
||||
// !!the current screen will not be drawn!!
|
||||
|
||||
//param 0 id of new run-list
|
||||
|
||||
LLogic.Express_change_session(*params); //terminate current and change to next run-list
|
||||
|
||||
return(0); //stop the script - logic engine will now go around and the new screen will begin
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Logic_up(uint32 new_script) //Tony23Sept96
|
||||
{
|
||||
//move the current object up a level
|
||||
//called by FN_gosub command - remember, only the logic object has access to cur_object_hub
|
||||
|
||||
|
||||
cur_object_hub->logic_level++; //going up a level - and we'll keeping going this cycle
|
||||
|
||||
if (cur_object_hub->logic_level==3) //can be 0,1,2
|
||||
Con_fatal_error("Logic_up id %d has run off script tree! :-O", ID);
|
||||
|
||||
cur_object_hub->script_id[cur_object_hub->logic_level]=new_script; //setup new script on next level (not the current level)
|
||||
cur_object_hub->script_pc[cur_object_hub->logic_level]=new_script&0xffff;
|
||||
|
||||
//Zdebug("new pc = %d", new_script&0xffff);
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Logic_one(uint32 new_script) //Tony4Dec96
|
||||
{
|
||||
//force to level one
|
||||
|
||||
cur_object_hub->logic_level=1;
|
||||
|
||||
cur_object_hub->script_id[1]=new_script; //setup new script on level 1
|
||||
cur_object_hub->script_pc[1]=new_script&0xffff;
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
void logic::Logic_replace(uint32 new_script) //Tony13Nov96
|
||||
{
|
||||
//change current logic - script must quit with a TERMINATE directive - which does not write to &pc
|
||||
|
||||
cur_object_hub->script_id[cur_object_hub->logic_level]=new_script; //setup new script on this level
|
||||
cur_object_hub->script_pc[cur_object_hub->logic_level]=new_script&0xffff;
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 logic::Examine_run_list(void) //Tony25Oct96
|
||||
{
|
||||
uint32 *game_object_list;
|
||||
_standardHeader *file_header;
|
||||
int scrolls=0;
|
||||
char c;
|
||||
|
||||
|
||||
if (current_run_list)
|
||||
{
|
||||
game_object_list = (uint32 *) (res_man.Res_open(current_run_list)+sizeof(_standardHeader)); //open and lock in place
|
||||
|
||||
Print_to_console("runlist number %d", current_run_list);
|
||||
|
||||
while(*(game_object_list))
|
||||
{
|
||||
file_header = (_standardHeader*) res_man.Res_open(*(game_object_list));
|
||||
Print_to_console(" %d %s",*(game_object_list), file_header->name);
|
||||
res_man.Res_close(*(game_object_list++));
|
||||
|
||||
scrolls++;
|
||||
Build_display();
|
||||
|
||||
if (scrolls==18)
|
||||
{
|
||||
Temp_print_to_console("- Press ESC to stop or any other key to continue");
|
||||
Build_display();
|
||||
|
||||
do
|
||||
{
|
||||
//--------------------------------------------------
|
||||
// Service windows
|
||||
while (!gotTheFocus)
|
||||
if (ServiceWindows() == RDERR_APPCLOSED)
|
||||
break;
|
||||
|
||||
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q
|
||||
{
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
exit(0); //quit the game
|
||||
}
|
||||
//--------------------------------------------------
|
||||
}
|
||||
while(!KeyWaiting());
|
||||
|
||||
ReadKey(&c); //kill the key we just pressed
|
||||
if (c==27) //ESC
|
||||
break;
|
||||
|
||||
Clear_console_line(); //clear the Press Esc message ready for the new line
|
||||
scrolls=0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
res_man.Res_close(current_run_list);
|
||||
}
|
||||
else Print_to_console("no run list set");
|
||||
|
||||
|
||||
Scroll_console();
|
||||
return(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Total_restart(void) //Tony18Sept96
|
||||
{
|
||||
//reset the object restart script 1 on level 0
|
||||
|
||||
cur_object_hub->logic_level=0;
|
||||
|
||||
//cur_object_hub->script_id[0]=1;
|
||||
cur_object_hub->script_pc[0]=1; //reset to rerun
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_total_restart(int32 *params) //Tony5Dec96
|
||||
{
|
||||
//mega runs this to restart its base logic again - like being cached in again
|
||||
|
||||
LLogic.Total_restart();
|
||||
|
||||
if (params);
|
||||
|
||||
return(IR_TERMINATE); //drop out without saving pc and go around again
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_add_to_kill_list(int32 *params) //James9jan97
|
||||
{
|
||||
// call *once* from object's logic script - ie. in startup code
|
||||
// - so not re-called every time script drops off & restarts!
|
||||
|
||||
// mark this object for killing - to be killed when player leaves this screen
|
||||
// - so object reloads & script restarts upon re-entry to screen
|
||||
// - causes this object's startup logic to be re-run every time we enter the screen
|
||||
// - "which is nice"
|
||||
|
||||
// params: none
|
||||
|
||||
uint32 entry;
|
||||
|
||||
|
||||
if (ID != 8) // DON'T EVER KILL GEORGE!
|
||||
{
|
||||
// first, scan list to see if this object is already included (05mar97 James)
|
||||
entry=0;
|
||||
while ((entry < kills) && (object_kill_list[entry] != ID))
|
||||
entry++;
|
||||
|
||||
if (entry == kills) // if this ID isn't already in the list, then add it, (otherwise finish) (05mar97 James)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (kills == OBJECT_KILL_LIST_SIZE) // no room at the inn
|
||||
Con_fatal_error("List full in FN_add_to_kill_list(%u) (%s line %u)",ID,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
object_kill_list[kills] = ID; // add this 'ID' to the kill list
|
||||
kills++; // "another one bites the dust"
|
||||
|
||||
// when we leave the screen, all these object resources are to be cleaned out of memory
|
||||
// and the kill list emptied by doing 'kills=0'
|
||||
// - ensuring that all resources are in fact still in memory & more importantly closed
|
||||
// before killing!
|
||||
}
|
||||
}
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Process_kill_list(void) //Tony10Jan97
|
||||
{
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
if (kills)
|
||||
for (j=0;j<kills;j++)
|
||||
res_man.Remove_res(object_kill_list[j]);
|
||||
|
||||
|
||||
kills=0;
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void logic::Reset_kill_list(void) //James 25mar97
|
||||
{
|
||||
kills=0;
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
|
62
sword2/logic.h
Normal file
62
sword2/logic.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//logic management
|
||||
|
||||
#ifndef _LOGIC
|
||||
#define _LOGIC
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
|
||||
#define TREE_SIZE 3
|
||||
|
||||
|
||||
|
||||
class logic
|
||||
{
|
||||
public:
|
||||
|
||||
int Process_session(void); //do one cycle of the current session
|
||||
void Express_change_session(uint32 sesh_id); //cause the logic loop to terminate and drop out
|
||||
void Natural_change_session(uint32 sesh_id); //new logic begins next cycle
|
||||
uint32 Return_run_list(void);
|
||||
void Logic_up(uint32 new_script); //setup script_id and script_pc in cur_object_hub - called by FN_gosub()
|
||||
void Logic_replace(uint32 new_script);
|
||||
void Logic_one(uint32 new_script);
|
||||
void Total_restart(void);
|
||||
uint32 Examine_run_list(void);
|
||||
void Reset_kill_list(void); //James 25mar97
|
||||
|
||||
|
||||
private:
|
||||
|
||||
uint32 current_run_list; //denotes the res id of the game-object-list in current use
|
||||
void Process_kill_list(void);
|
||||
uint32 pc; //pc during logic loop
|
||||
_object_hub *cur_object_hub; //each object has one of these tacked onto the beginning
|
||||
|
||||
};
|
||||
|
||||
extern logic LLogic;
|
||||
|
||||
int32 FN_add_to_kill_list(int32 *params); //James9jan97
|
||||
|
||||
#endif
|
694
sword2/maketext.cpp
Normal file
694
sword2/maketext.cpp
Normal file
|
@ -0,0 +1,694 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// MAKETEXT - Constructs a single-frame text sprite: returns a handle to a
|
||||
// FLOATING memory block containing the sprite, given a
|
||||
// null-terminated string, max width allowed, pen colour and
|
||||
// pointer to required character set.
|
||||
//
|
||||
// NB 1) The routine does not create a standard file header or
|
||||
// an anim header for the text sprite - the data simply begins
|
||||
// with the frame header.
|
||||
//
|
||||
// NB 2) If pen colour is zero, it copies the characters into the
|
||||
// sprite without remapping the colours.
|
||||
// ie. It can handle both the standard 2-colour font for speech
|
||||
// and any multicoloured fonts for control panels, etc.
|
||||
//
|
||||
// Based on textsprt.c as used for Broken Sword 1, but updated for new system
|
||||
// by JEL on 9oct96 and updated again (for font as a resource) on 5dec96.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
#define MAX_LINES 30 // max character lines in output sprite
|
||||
|
||||
#define BORDER_COL 200 // source colour for character border (only needed for remapping colours)
|
||||
#define LETTER_COL 193 // source colour for bulk of character ( " )
|
||||
#define BORDER_PEN 194 // output colour for character border - should be black ( " ) but note that we have to use a different pen number during sequences
|
||||
|
||||
#define NO_COL 0 // sprite background - 0 for transparency!
|
||||
#define SPACE ' '
|
||||
#define FIRST_CHAR SPACE // first character in character set
|
||||
#define LAST_CHAR 255 // last character in character set
|
||||
#define DUD 64 // the first "chequered flag" (dud) symbol in our character set is in the '@' position
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h" // for SPEECH_FONT_ID & CONSOLE_FONT_ID
|
||||
#include "header.h"
|
||||
#include "maketext.h"
|
||||
#include "memory.h"
|
||||
#include "protocol.h" // for FetchFrameHeader()
|
||||
#include "resman.h"
|
||||
|
||||
extern uint32 sequenceTextLines; // see anims.cpp
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct // info for each line of words in the output text sprite
|
||||
{
|
||||
uint16 width; // width of line in pixels
|
||||
uint16 length; // length of line in characters
|
||||
} _lineInfo;
|
||||
//-----------------------------------------------------------------------------
|
||||
// PROTOTYPES
|
||||
uint16 AnalyseSentence( uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line );
|
||||
mem* BuildTextSprite( uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines );
|
||||
uint16 CharWidth( uint8 ch, uint32 fontRes );
|
||||
uint16 CharHeight( uint32 fontRes );
|
||||
_frameHeader* FindChar( uint8 ch, uint8 *charSet );
|
||||
void CopyChar( _frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen );
|
||||
//-----------------------------------------------------------------------------
|
||||
// global layout variables - these used to be defines, but now we're dealing with 2 character sets (10dec96 JEL)
|
||||
|
||||
int8 line_spacing; // no. of pixels to separate lines of characters in the output sprite - negative for overlap
|
||||
int8 char_spacing; // no. of pixels to separate characters along each line - negative for overlap
|
||||
uint8 border_pen; // output pen colour of character borders
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Global font resource id variables, set up in 'SetUpFontResources()' at bottom of this file
|
||||
|
||||
uint32 speech_font_id;
|
||||
uint32 controls_font_id;
|
||||
uint32 red_font_id;
|
||||
uint32 death_font_id;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
mem* MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes )
|
||||
{
|
||||
mem *line; // handle for the memory block which will contain the array of lineInfo structures
|
||||
mem *textSprite; // handle for the block to contain the text sprite itself
|
||||
uint16 noOfLines; // no of lines of text required to fit within a sprite of width 'maxWidth' pixels
|
||||
|
||||
// Zdebug("MakeTextSprite( \"%s\", maxWidth=%u )", sentence, maxWidth );
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// NB. ensure sentence contains no leading/tailing/extra spaces
|
||||
// - if necessary, copy to another array first, missing the extra spaces.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------
|
||||
// set the global layout variables (10dec96 JEL)
|
||||
|
||||
if (fontRes == speech_font_id)
|
||||
{
|
||||
line_spacing = -6; // overlap lines by 6 pixels
|
||||
char_spacing = -3; // overlap characters by 3 pixels
|
||||
}
|
||||
else if (fontRes == CONSOLE_FONT_ID)
|
||||
{
|
||||
line_spacing = 0; // no space or overlap between lines
|
||||
char_spacing = 1; // 1 pixel spacing between each character
|
||||
}
|
||||
else
|
||||
{
|
||||
line_spacing = 0;
|
||||
char_spacing = 0;
|
||||
}
|
||||
|
||||
if (sequenceTextLines) // if rendering text over a sequence
|
||||
border_pen = 1; // need a different colour number to BORDER_PEN
|
||||
else
|
||||
border_pen = BORDER_PEN;
|
||||
|
||||
//----------------------------------------------
|
||||
|
||||
// allocate memory for array of lineInfo structures
|
||||
line = Twalloc( MAX_LINES*sizeof(_lineInfo), MEM_locked, UID_temp ); // last param is an optional id for type of mem block
|
||||
|
||||
// get details of sentence breakdown into array of _lineInfo structures
|
||||
// and get the no of lines involved
|
||||
noOfLines = AnalyseSentence( sentence, maxWidth, fontRes, (_lineInfo *)line->ad );
|
||||
|
||||
// construct the sprite based on the info gathered - returns floating mem block
|
||||
textSprite = BuildTextSprite( sentence, fontRes, pen, (_lineInfo *)line->ad, noOfLines );
|
||||
|
||||
// free up the lineInfo array now
|
||||
Free_mem( line );
|
||||
|
||||
return( textSprite );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint16 AnalyseSentence( uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line )
|
||||
{
|
||||
uint16 pos=0, wordWidth, wordLength, spaceNeeded, firstWord=TRUE, lineNo=0;
|
||||
uint8 ch;
|
||||
// joinWidth = how much extra space is needed to append a word to a line
|
||||
// NB. SPACE requires TWICE the 'char_spacing' to join a word to line
|
||||
uint16 joinWidth = CharWidth( SPACE, fontRes ) + 2*char_spacing;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
wordWidth = 0; // new word
|
||||
wordLength = 0;
|
||||
|
||||
ch = sentence[pos++]; // get first char of word (at position 'pos')
|
||||
|
||||
while( (ch != SPACE) && ch ) // while not SPACE or NULL terminator
|
||||
{
|
||||
// inc wordWidth by (character width + char_spacing) pixels
|
||||
wordWidth += CharWidth( ch, fontRes ) + char_spacing;
|
||||
wordLength++;
|
||||
ch = sentence[pos++]; // get next char
|
||||
}
|
||||
|
||||
wordWidth -= char_spacing; // no char_spacing after final letter of word!
|
||||
|
||||
// 'ch' is now the SPACE or NULL following the word
|
||||
// 'pos' indexes to the position following 'ch'
|
||||
|
||||
|
||||
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)
|
||||
spaceNeeded = joinWidth + wordWidth;
|
||||
|
||||
if( (line[lineNo].width + spaceNeeded) <= maxWidth ) // fits this line
|
||||
{
|
||||
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++; // for next _lineInfo structure in the array
|
||||
//debug_only( lineNo < MAX_LINES ); // exception if lineNo >= MAX_LINES
|
||||
line[lineNo].width = wordWidth;
|
||||
line[lineNo].length = wordLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( ch ); // while not reached the NULL terminator
|
||||
|
||||
return lineNo+1; // return no of lines
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns a handle to a floating memory block containing a text sprite, given
|
||||
// a pointer to a null-terminated string, pointer to required character set,
|
||||
// required text pen colour (or zero to use source colours), pointer to the
|
||||
// array of linInfo structures created by 'AnalyseSentence()', and the number
|
||||
// of lines (ie. no. of elements in the 'line' array).
|
||||
|
||||
//
|
||||
//
|
||||
// PC Version of BuildTextSprite
|
||||
//
|
||||
//
|
||||
|
||||
mem* BuildTextSprite( uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines )
|
||||
{
|
||||
uint8 *linePtr, *spritePtr;
|
||||
uint16 lineNo, pos=0, posInLine, spriteWidth=0, spriteHeight, sizeOfSprite;
|
||||
uint16 charHeight = CharHeight(fontRes);
|
||||
_frameHeader *frameHeadPtr, *charPtr;
|
||||
mem *textSprite;
|
||||
uint8 *charSet;
|
||||
|
||||
// spriteWidth = width of widest line of output text
|
||||
for( lineNo=0; lineNo < noOfLines; lineNo++)
|
||||
if( line[lineNo].width > spriteWidth )
|
||||
spriteWidth = line[lineNo].width;
|
||||
|
||||
// spriteHeight = tot height of char lines + tot height of separating lines
|
||||
spriteHeight = (charHeight*noOfLines + line_spacing*(noOfLines-1));
|
||||
|
||||
// total size (no of pixels)
|
||||
sizeOfSprite = spriteWidth * spriteHeight;
|
||||
|
||||
// allocate memory for sprite, and lock it ready for use
|
||||
// NB. 'textSprite' is the given pointer to the handle to be used
|
||||
textSprite = Twalloc( sizeof(_frameHeader) + sizeOfSprite, MEM_locked, UID_text_sprite );
|
||||
// the handle (*textSprite) now points to UNMOVABLE memory block
|
||||
|
||||
// set up the frame header
|
||||
frameHeadPtr = (_frameHeader *)textSprite->ad; // point to the start of our memory block
|
||||
|
||||
frameHeadPtr->compSize = 0;
|
||||
frameHeadPtr->width = spriteWidth;
|
||||
frameHeadPtr->height = spriteHeight;
|
||||
|
||||
// Zdebug("spriteWidth=%u",spriteWidth);
|
||||
// Zdebug("spriteHeight=%u",spriteHeight);
|
||||
|
||||
// ok, now point to the start (of the first line) of the sprite data itelf
|
||||
linePtr = textSprite->ad + sizeof(_frameHeader);
|
||||
|
||||
// start with transparent sprite (no colour)
|
||||
memset( linePtr, NO_COL, sizeOfSprite );
|
||||
|
||||
|
||||
charSet = res_man.Res_open(fontRes); // open font file
|
||||
|
||||
|
||||
// fill sprite with characters, one line at a time
|
||||
for( lineNo=0; lineNo < noOfLines; lineNo++ )
|
||||
{
|
||||
// position the start of the line so that it is centred across the sprite
|
||||
spritePtr = linePtr + (spriteWidth - line[lineNo].width) / 2;
|
||||
|
||||
// copy the sprite for each character in this line to the text sprite
|
||||
// and inc the sprite ptr by the character's width minus the 'overlap'
|
||||
for( posInLine=0; posInLine < line[lineNo].length; posInLine++ )
|
||||
{
|
||||
charPtr = FindChar( sentence[pos++], charSet );
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ((charPtr->height) != charHeight)
|
||||
Con_fatal_error("FONT ERROR: '%c' is not same height as the space (%s line %u)",sentence[pos-1],__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
CopyChar( charPtr, spritePtr, spriteWidth, pen );
|
||||
spritePtr += charPtr->width + char_spacing;
|
||||
}
|
||||
|
||||
pos++; // skip space at end of last word in this line
|
||||
|
||||
// move to start of next character line in text sprite
|
||||
linePtr += (charHeight + line_spacing) * spriteWidth;
|
||||
}
|
||||
|
||||
|
||||
res_man.Res_close(fontRes); // close font file
|
||||
|
||||
|
||||
// unlock the sprite memory block, so it's movable
|
||||
Float_mem( textSprite );
|
||||
|
||||
return( textSprite );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the width of a character sprite, given the character's ASCII code
|
||||
// and a pointer to the start of the character set.
|
||||
|
||||
uint16 CharWidth( uint8 ch, uint32 fontRes )
|
||||
{
|
||||
_frameHeader *charFrame;
|
||||
uint8 *charSet;
|
||||
uint16 width;
|
||||
|
||||
|
||||
charSet = res_man.Res_open(fontRes); // open font file
|
||||
|
||||
charFrame = FindChar( ch, charSet ); // move to approp. sprite (header)
|
||||
|
||||
width = charFrame->width;
|
||||
|
||||
res_man.Res_close(fontRes); // close font file
|
||||
|
||||
return (width); // return its width
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the height of a character sprite, given the character's ASCII code
|
||||
// and a pointer to the start of the character set.
|
||||
|
||||
uint16 CharHeight( uint32 fontRes ) // assume all chars the same height!
|
||||
{
|
||||
_frameHeader *charFrame;
|
||||
uint8 *charSet;
|
||||
uint16 height;
|
||||
|
||||
|
||||
charSet = res_man.Res_open(fontRes); // open font file
|
||||
|
||||
charFrame = FindChar( FIRST_CHAR, charSet ); // FIRST_CHAR as good as any
|
||||
|
||||
height = charFrame->height;
|
||||
|
||||
res_man.Res_close(fontRes); // close font file
|
||||
|
||||
return (height); // return its height
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns a pointer to the header of a character sprite, given the character's
|
||||
// ASCII code and a pointer to the start of the character set.
|
||||
|
||||
_frameHeader* FindChar( uint8 ch, uint8 *charSet )
|
||||
{
|
||||
// charSet details:
|
||||
// ---------------
|
||||
// starts with the standard file header ie. sizeof(_header) bytes
|
||||
// then an int32 giving the no of sprites ie. 4 bytes
|
||||
// then the offset table (an int32 offset for each sprite)
|
||||
// - each offset counting from the start of the file
|
||||
|
||||
if( (ch<FIRST_CHAR) || (ch>LAST_CHAR) ) // if 'ch' out of range
|
||||
ch = DUD; // then print the 'dud' character (chequered flag)
|
||||
|
||||
// address of char = address of charSet + offset to char
|
||||
//return (charSet + *(int32 *)(charSet + sizeof(_header) + 4 + 4*(ch - FIRST_CHAR)));
|
||||
return (FetchFrameHeader( charSet, ch-FIRST_CHAR ));
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copies a character sprite from 'charPtr' to the sprite buffer at 'spritePtr'
|
||||
// of width 'spriteWidth'. If pen is zero, it copies the data across directly,
|
||||
// otherwise it maps pixels of BORDER_COL to 'border_pen', and LETTER_COL to 'pen'.
|
||||
|
||||
void CopyChar( _frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen )
|
||||
{
|
||||
uint8 *rowPtr, *source, *dest;
|
||||
uint16 rows, cols;
|
||||
|
||||
|
||||
source = (uint8 *)charPtr + sizeof(_frameHeader); // now pts to sprite data for char 'ch'
|
||||
rowPtr = spritePtr; // pts to start of first row of char within text sprite
|
||||
|
||||
for( rows=0; rows < charPtr->height; rows++ )
|
||||
{
|
||||
dest = rowPtr; // start at beginning of row
|
||||
|
||||
|
||||
if (pen) // if required output pen is non-zero
|
||||
{
|
||||
for( cols=0; cols < charPtr->width; cols++ )
|
||||
{
|
||||
switch( *source++ ) // inc source ptr along sprite data
|
||||
{
|
||||
case LETTER_COL:
|
||||
*dest = pen;
|
||||
break;
|
||||
|
||||
case BORDER_COL:
|
||||
if (!(*dest)) // don't do a border pixel if there already a bit of another character underneath (for overlapping!)
|
||||
*dest = border_pen;
|
||||
break;
|
||||
|
||||
// do nothing if source pixel is zero - ie. transparent
|
||||
}
|
||||
dest++; // inc dest ptr to next pixel along row
|
||||
}
|
||||
}
|
||||
|
||||
else // pen is zero, so just copy character sprites directly into text sprite without remapping colours
|
||||
{
|
||||
memcpy( dest, source, charPtr->width );
|
||||
source += charPtr->width;
|
||||
}
|
||||
|
||||
rowPtr += spriteWidth; // next row down (add width of text sprite)
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
#if _DEBUG
|
||||
#define MAX_text_blocs MAX_DEBUG_TEXT_BLOCKS+1 // allow enough for all the debug text blocks (see debug.cpp)
|
||||
#else
|
||||
#define MAX_text_blocs 2 // only need one for speech, and possibly one for "PAUSED"
|
||||
#endif // _DEBUG
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16 x;
|
||||
int16 y;
|
||||
uint16 type; // RDSPR_ status bits - see defintion of _spriteInfo structure for correct size!
|
||||
mem *text_mem;
|
||||
} text_bloc;
|
||||
|
||||
text_bloc text_sprite_list[MAX_text_blocs];
|
||||
//-----------------------------------------------------------------------------
|
||||
void Init_text_bloc_system(void) //Tony16Oct96
|
||||
{
|
||||
uint32 j;
|
||||
|
||||
for (j=0;j<MAX_text_blocs;j++)
|
||||
text_sprite_list[j].text_mem=0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
#define TEXT_MARGIN 12 // distance to keep speech text from edges of screen
|
||||
|
||||
uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification) //Tony31Oct96
|
||||
{
|
||||
//creates a text bloc in the list and returns the bloc number
|
||||
//the list of blocs are read and blitted at render time
|
||||
//choose alignment type RDSPR_DISPLAYALIGN or 0
|
||||
|
||||
uint32 j=0;
|
||||
_frameHeader *frame_head;
|
||||
int16 text_left_margin;
|
||||
int16 text_right_margin;
|
||||
int16 text_top_margin;
|
||||
int16 text_bottom_margin;
|
||||
|
||||
|
||||
//find a free slot
|
||||
while((j<MAX_text_blocs)&&(text_sprite_list[j].text_mem))
|
||||
j++;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (j==MAX_text_blocs) //we've run out
|
||||
Con_fatal_error("Build_new_block ran out of blocks! (%s line %u)",__FILE__,__LINE__); //might as well stop the system
|
||||
#endif
|
||||
|
||||
|
||||
text_sprite_list[j].text_mem = MakeTextSprite( ascii, width, pen, fontRes ); // make the sprite!
|
||||
|
||||
|
||||
// speech to be centred above point (x,y), but kept on-screen
|
||||
// where (x,y) is a point somewhere just above the talker's head
|
||||
|
||||
// debug text just to be printed normally from point (x,y)
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// JUSTIFICATION & POSITIONING (James updated 20jun97)
|
||||
|
||||
if (justification != NO_JUSTIFICATION) // 'NO_JUSTIFICATION' means print sprite with top-left at (x,y) without margin checking - used for debug text
|
||||
{
|
||||
frame_head = (_frameHeader*) text_sprite_list[j].text_mem->ad;
|
||||
|
||||
switch (justification)
|
||||
{
|
||||
// this one is always used for SPEECH TEXT; possibly also for pointer text
|
||||
case POSITION_AT_CENTRE_OF_BASE:
|
||||
x -= (frame_head->width)/2; // subtract half the sprite-width from the given x-coord
|
||||
y -= frame_head->height; // and the sprite-height from the given y-coord
|
||||
break;
|
||||
|
||||
case POSITION_AT_CENTRE_OF_TOP:
|
||||
x -= (frame_head->width)/2;
|
||||
break;
|
||||
|
||||
case POSITION_AT_LEFT_OF_TOP:
|
||||
// the given coords are already correct for this!
|
||||
break;
|
||||
|
||||
case POSITION_AT_RIGHT_OF_TOP:
|
||||
x -= frame_head->width;
|
||||
break;
|
||||
|
||||
case POSITION_AT_LEFT_OF_BASE:
|
||||
y -= frame_head->height;
|
||||
break;
|
||||
|
||||
case POSITION_AT_RIGHT_OF_BASE:
|
||||
x -= frame_head->width;
|
||||
y -= frame_head->height;
|
||||
break;
|
||||
|
||||
case POSITION_AT_LEFT_OF_CENTRE:
|
||||
y -= (frame_head->height)/2;
|
||||
break;
|
||||
|
||||
case POSITION_AT_RIGHT_OF_CENTRE:
|
||||
x -= frame_head->width;
|
||||
y -= (frame_head->height)/2;
|
||||
break;
|
||||
}
|
||||
|
||||
// ensure text sprite is a few pixels inside the visible screen
|
||||
text_left_margin = TEXT_MARGIN;
|
||||
text_right_margin = 640 - TEXT_MARGIN - frame_head->width;
|
||||
text_top_margin = 0 + TEXT_MARGIN; // remember - it's RDSPR_DISPLAYALIGN
|
||||
text_bottom_margin = 400 - TEXT_MARGIN - frame_head->height;
|
||||
|
||||
if (x < text_left_margin) // move if too far left or too far right
|
||||
x = text_left_margin;
|
||||
else if (x > text_right_margin)
|
||||
x = text_right_margin;
|
||||
|
||||
if (y < text_top_margin) // move if too high or too low
|
||||
y = text_top_margin;
|
||||
else if (y > text_bottom_margin)
|
||||
y = text_bottom_margin;
|
||||
}
|
||||
//-----------------------------------------------------------
|
||||
|
||||
text_sprite_list[j].x = x;
|
||||
text_sprite_list[j].y = y;
|
||||
text_sprite_list[j].type = type+RDSPR_NOCOMPRESSION; // always uncompressed
|
||||
|
||||
|
||||
return(j+1);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
//
|
||||
// PC Version of Print_text_blocs
|
||||
//
|
||||
//
|
||||
|
||||
void Print_text_blocs(void) //Tony16Oct96
|
||||
{
|
||||
//called by build_display
|
||||
|
||||
_frameHeader *frame;
|
||||
_spriteInfo spriteInfo;
|
||||
uint32 j;
|
||||
uint32 rv;
|
||||
|
||||
for (j=0;j<MAX_text_blocs;j++)
|
||||
{
|
||||
if (text_sprite_list[j].text_mem)
|
||||
{
|
||||
frame = (_frameHeader*) text_sprite_list[j].text_mem->ad;
|
||||
|
||||
spriteInfo.x = text_sprite_list[j].x;
|
||||
spriteInfo.y = text_sprite_list[j].y;
|
||||
spriteInfo.w = frame->width;
|
||||
spriteInfo.h = frame->height;
|
||||
spriteInfo.scale = 0;
|
||||
spriteInfo.scaledWidth = 0;
|
||||
spriteInfo.scaledHeight = 0;
|
||||
spriteInfo.type = text_sprite_list[j].type;
|
||||
spriteInfo.blend = 0;
|
||||
spriteInfo.data = text_sprite_list[j].text_mem->ad+sizeof(_frameHeader);
|
||||
spriteInfo.colourTable = 0;
|
||||
|
||||
rv = DrawSprite( &spriteInfo );
|
||||
if (rv)
|
||||
ExitWithReport("Driver Error %.8x in Print_text_blocs [%s line %u]", rv, __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Kill_text_bloc(uint32 bloc_number) //Tony18Oct96
|
||||
{
|
||||
bloc_number--; //back to real
|
||||
|
||||
if (text_sprite_list[bloc_number].text_mem)
|
||||
{
|
||||
Free_mem(text_sprite_list[bloc_number].text_mem); //release the floating memory
|
||||
text_sprite_list[bloc_number].text_mem=0; //this is how we know the bloc is free
|
||||
}
|
||||
else
|
||||
Con_fatal_error("closing closed text bloc number %d", bloc_number); //illegal kill - stop the system
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// called from InitialiseGame() in sword2.cpp
|
||||
void InitialiseFontResourceFlags(void) // (James31july97)
|
||||
{
|
||||
uint8 *textFile, *textLine;
|
||||
uint8 language;
|
||||
|
||||
#define TEXT_RES 3258 // resource 3258 contains text from location script for 152 (install, save & restore text, etc)
|
||||
#define SAVE_LINE_NO 1 // local line number of "save" (actor no. 1826)
|
||||
|
||||
#ifndef _DEMO // normal game
|
||||
#define NAME_LINE_NO 54 // local line number of game name (actor no. 3550)
|
||||
#else
|
||||
#define NAME_LINE_NO 451 // local line number of demo game name
|
||||
#endif // _DEMO
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
textFile = res_man.Res_open(TEXT_RES); // open the text resource
|
||||
//---------------------------------------------------------------------------------
|
||||
// check if language is Polish or Finnish, and therefore requires alternate fonts
|
||||
|
||||
textLine = FetchTextLine(textFile, SAVE_LINE_NO )+2; // get the text line (& skip the 2 chars containing the wavId)
|
||||
|
||||
if (strcmp((char*)textLine,"tallenna")==0) // if this line contains the Finnish for "save"
|
||||
language = FINNISH_TEXT; // - then this version must be Finnish
|
||||
else if (strcmp((char*)textLine,"zapisz")==0) // if this line contains the Polish for "save"
|
||||
language = POLISH_TEXT; // - then this version must be Polish
|
||||
else // neither Finnish nor Polish
|
||||
language = DEFAULT_TEXT; // - use regular fonts
|
||||
|
||||
InitialiseFontResourceFlags(language); // Set the game to use the appropriate fonts
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Get the game name for the windows application
|
||||
|
||||
textLine = FetchTextLine(textFile, NAME_LINE_NO )+2; // get the text line (& skip the 2 chars containing the wavId)
|
||||
SetWindowName((char*)textLine); // driver function
|
||||
//---------------------------------------------------------------------------------
|
||||
res_man.Res_close(TEXT_RES); // now ok to close the text file
|
||||
//---------------------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// called from the above function, and also from console.cpp
|
||||
void InitialiseFontResourceFlags(uint8 language) // (James31july97)
|
||||
{
|
||||
switch (language)
|
||||
{
|
||||
case FINNISH_TEXT: // special Finnish fonts
|
||||
{
|
||||
speech_font_id = FINNISH_SPEECH_FONT_ID;
|
||||
controls_font_id = FINNISH_CONTROLS_FONT_ID;
|
||||
red_font_id = FINNISH_RED_FONT_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
case POLISH_TEXT: // special Polish fonts
|
||||
{
|
||||
speech_font_id = POLISH_SPEECH_FONT_ID;
|
||||
controls_font_id = POLISH_CONTROLS_FONT_ID;
|
||||
red_font_id = POLISH_RED_FONT_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
default:// DEFAULT_TEXT // regular fonts
|
||||
{
|
||||
speech_font_id = ENGLISH_SPEECH_FONT_ID;
|
||||
controls_font_id = ENGLISH_CONTROLS_FONT_ID;
|
||||
red_font_id = ENGLISH_RED_FONT_ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
94
sword2/maketext.h
Normal file
94
sword2/maketext.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* MAKETEXT.H Function prototype for text sprite builder routine JEL Oct96
|
||||
*
|
||||
* The routine returns a memory handle to a movable memory block containing
|
||||
* the required sprite, which must be locked before use.
|
||||
* ie. lock, draw sprite, unlock/free.
|
||||
* The sprite data contains a frameHeader, but not a standard file header.
|
||||
*
|
||||
* Debugger will trap error when word too big for line (maxWidth)
|
||||
* or when more lines needed than max expected (MAX_LINES)
|
||||
*
|
||||
* PARAMETERS:
|
||||
*
|
||||
* 'sentence' points to a NULL-TERMINATED STRING
|
||||
* - string must contain no leading/tailing/extra spaces
|
||||
* - out-of-range characters in the string are forced to the output as a
|
||||
* special error-signal character (chequered flag)
|
||||
*
|
||||
* 'maxWidth' is the maximum allowed text sprite width, in PIXELS
|
||||
*
|
||||
* 'pen' is the desired colour (0-255) for the main body of each character
|
||||
* NB. Border colour is #DEFINEd in textsprt.c (to a colour value for BLACK)
|
||||
* if 'pen' is zero, the characters are copied directly and NOT remapped.
|
||||
*
|
||||
* 'charSet' points to the beginning of the standard file header for the
|
||||
* desired character set
|
||||
* NB. The first and last characters in the set are #DEFINEd in textsprt.c
|
||||
*
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 'textSprite' points to the handle to be used for the text sprite
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _MAKETEXT_H
|
||||
#define _MAKETEXT_H
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define NO_JUSTIFICATION 0 // only for debug text, since it doesn't keep text inside the screen margin!
|
||||
#define POSITION_AT_CENTRE_OF_BASE 1 // these all force text inside the screen edge margin when necessary
|
||||
#define POSITION_AT_CENTRE_OF_TOP 2
|
||||
#define POSITION_AT_LEFT_OF_TOP 3
|
||||
#define POSITION_AT_RIGHT_OF_TOP 4
|
||||
#define POSITION_AT_LEFT_OF_BASE 5
|
||||
#define POSITION_AT_RIGHT_OF_BASE 6
|
||||
#define POSITION_AT_LEFT_OF_CENTRE 7
|
||||
#define POSITION_AT_RIGHT_OF_CENTRE 8
|
||||
|
||||
mem* MakeTextSprite( uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes );
|
||||
void Init_text_bloc_system(void);
|
||||
|
||||
void Kill_text_bloc(uint32 bloc_number);
|
||||
void Print_text_blocs(void); //Tony16Oct96
|
||||
|
||||
uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DEFAULT_TEXT 0
|
||||
#define FINNISH_TEXT 1
|
||||
#define POLISH_TEXT 2
|
||||
|
||||
void InitialiseFontResourceFlags(void); // this one works out the language from the text cluster (James31july97)
|
||||
void InitialiseFontResourceFlags(uint8 language); // this one allow you to select the fonts yourself (James31july97)
|
||||
|
||||
extern uint32 speech_font_id;
|
||||
extern uint32 controls_font_id;
|
||||
extern uint32 red_font_id;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
259
sword2/mem_view.cpp
Normal file
259
sword2/mem_view.cpp
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
//#include <windows.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
#include "layers.h"
|
||||
#include "mem_view.h"
|
||||
#include "memory.h"
|
||||
#include "resman.h"
|
||||
#include "sword2.h" // (James11aug97) for CloseGame()
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
char buf[50]; //has to be global because a local in Fetch_mem_owner is destroyed on exit
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Console_mem_display(void) //Tony13Aug96
|
||||
{
|
||||
//
|
||||
int pass,found_end,k,j,free=0;
|
||||
_standardHeader *file_header;
|
||||
int scrolls=0;
|
||||
char c;
|
||||
|
||||
char inf[][20]=
|
||||
{
|
||||
{"M_null "},
|
||||
{"M_free "},
|
||||
{"M_locked"},
|
||||
{"M_float "}
|
||||
};
|
||||
|
||||
|
||||
j=base_mem_block;
|
||||
do
|
||||
{
|
||||
|
||||
if (mem_list[j].uid<65536)
|
||||
{
|
||||
file_header = (_standardHeader*) res_man.Res_open(mem_list[j].uid);
|
||||
res_man.Res_close(mem_list[j].uid); //close immediately so give a true count
|
||||
|
||||
Zdebug("view %d", mem_list[j].uid);
|
||||
|
||||
|
||||
pass=0;
|
||||
found_end=0;
|
||||
|
||||
for (k=0;k<30;k++)
|
||||
{
|
||||
if (file_header->name[k]==0)
|
||||
{ found_end=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (file_header->name[k]<32)||(file_header->name[k]>'z'))
|
||||
pass=1;
|
||||
|
||||
}
|
||||
|
||||
if (file_header->name[0]==0)
|
||||
pass=1; //also illegal
|
||||
|
||||
|
||||
if ((!pass)&&(found_end)) //&&(file_header->fileType<10))
|
||||
Print_to_console("%d %s, size 0x%.5x (%dk %d%%), res %d %s %s, A%d, C%d", j,
|
||||
inf[mem_list[j].state],
|
||||
mem_list[j].size, mem_list[j].size/1024, (mem_list[j].size*100)/total_free_memory, mem_list[j].uid,
|
||||
|
||||
res_man.Fetch_cluster(mem_list[j].uid),
|
||||
file_header->name,
|
||||
res_man.Fetch_age(mem_list[j].uid),
|
||||
res_man.Fetch_count(mem_list[j].uid));
|
||||
|
||||
else Print_to_console(" %d is an illegal resource", mem_list[j].uid);
|
||||
|
||||
}
|
||||
else
|
||||
Print_to_console("%d %s, size 0x%.5x (%dk %d%%), %s", j,
|
||||
inf[mem_list[j].state],
|
||||
mem_list[j].size, mem_list[j].size/1024, (mem_list[j].size*100)/total_free_memory,
|
||||
Fetch_mem_owner(mem_list[j].uid) );
|
||||
|
||||
if (mem_list[j].state==MEM_free)
|
||||
free+=mem_list[j].size;
|
||||
|
||||
|
||||
j=mem_list[j].child;
|
||||
|
||||
scrolls++;
|
||||
|
||||
Build_display();
|
||||
|
||||
|
||||
if (scrolls==18)
|
||||
{
|
||||
Temp_print_to_console("- Press ESC to stop or any other key to continue");
|
||||
Build_display();
|
||||
|
||||
do
|
||||
{
|
||||
//--------------------------------------------------
|
||||
// Service windows
|
||||
while (!gotTheFocus)
|
||||
if (ServiceWindows() == RDERR_APPCLOSED)
|
||||
break;
|
||||
|
||||
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q
|
||||
{
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
exit(0); //quit the game
|
||||
}
|
||||
//--------------------------------------------------
|
||||
}
|
||||
while(!KeyWaiting());
|
||||
|
||||
ReadKey(&c); //kill the key we just pressed
|
||||
if (c==27) //ESC
|
||||
break;
|
||||
|
||||
Clear_console_line(); //clear the Press Esc message ready for the new line
|
||||
scrolls=0;
|
||||
}
|
||||
}
|
||||
while (j!=-1);
|
||||
|
||||
Scroll_console();
|
||||
Print_to_console("(total memory block 0x%.8x %dk %dMB) %d / %d%% free", total_free_memory,
|
||||
total_free_memory/1024,
|
||||
total_free_memory/(1000*1024),
|
||||
free,
|
||||
(free*100)/total_free_memory);
|
||||
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
char *Fetch_mem_owner(uint32 uid) //Tony3June96
|
||||
{
|
||||
|
||||
switch(uid)
|
||||
{
|
||||
case UID_memman:
|
||||
return("MEMMAN");
|
||||
break;
|
||||
|
||||
case UID_font:
|
||||
return("font");
|
||||
break;
|
||||
|
||||
case UID_temp:
|
||||
return("temp ram allocation");
|
||||
break;
|
||||
|
||||
case UID_decompression_buffer:
|
||||
return("decompression buffer");
|
||||
break;
|
||||
|
||||
case UID_shrink_buffer:
|
||||
return("shrink buffer");
|
||||
break;
|
||||
|
||||
case UID_con_sprite:
|
||||
return("console sprite buffer");
|
||||
break;
|
||||
|
||||
case UID_text_sprite:
|
||||
return("text sprite");
|
||||
break;
|
||||
|
||||
case UID_walk_anim:
|
||||
return("walk anim");
|
||||
break;
|
||||
|
||||
case UID_savegame_buffer:
|
||||
return("savegame buffer");
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(buf, "<sob> %d?", uid);
|
||||
return(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Create_mem_string( char *string ) // James (21oct96 updated 4dec96)
|
||||
{
|
||||
int blockNo = base_mem_block;
|
||||
int blocksUsed=0;
|
||||
int mem_free=0;
|
||||
int mem_locked=0;
|
||||
int mem_floating=0;
|
||||
int memUsed=0;
|
||||
int percent;
|
||||
|
||||
|
||||
|
||||
while (blockNo != -1)
|
||||
{
|
||||
switch (mem_list[blockNo].state)
|
||||
{
|
||||
case MEM_free:
|
||||
mem_free++;
|
||||
break;
|
||||
|
||||
case MEM_locked:
|
||||
mem_locked++;
|
||||
memUsed += mem_list[blockNo].size;
|
||||
break;
|
||||
|
||||
case MEM_float:
|
||||
mem_floating++;
|
||||
memUsed += mem_list[blockNo].size;
|
||||
break;
|
||||
}
|
||||
|
||||
blocksUsed++;
|
||||
blockNo = mem_list[blockNo].child;
|
||||
}
|
||||
|
||||
percent = (memUsed * 100) / total_free_memory;
|
||||
|
||||
sprintf( string, "locked(%u)+float(%u)+free(%u) = %u/%u blocks (%u%% used)(cur %uk)", mem_locked, mem_floating, mem_free, blocksUsed, MAX_mem_blocks, percent, (res_man.Res_fetch_useage()/1024) );
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
31
sword2/mem_view.h
Normal file
31
sword2/mem_view.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef MEMVIEW_H
|
||||
#define MEMVIEW_H
|
||||
|
||||
//#include "src\driver96.h"
|
||||
|
||||
|
||||
char *Fetch_mem_owner(uint32 uid);
|
||||
void Console_mem_display(void); // Tony (13Aug96)
|
||||
void Create_mem_string( char *string ); // James (21oct96 updated 4dec96)
|
||||
|
||||
|
||||
#endif
|
544
sword2/memory.cpp
Normal file
544
sword2/memory.cpp
Normal file
|
@ -0,0 +1,544 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//memory manager - "remember, it's not good to leave memory locked for a moment longer than necessary" Tony
|
||||
// "actually, in a sequential system theoretically you never need to lock any memory!" Chris ;)
|
||||
//
|
||||
// This is a very simple implementation but I see little advantage to being any cleverer
|
||||
// with the coding - i could have put the mem blocks before the defined blocks instead
|
||||
// of in an array and then used pointers to child/parent blocks. But why bother? I've Kept it simple.
|
||||
// When it needs updating or customising it will be accessable to anyone who looks at it.
|
||||
// *doesn't have a purgeable/age consituant yet - if anyone wants this then I'll add it in.
|
||||
|
||||
|
||||
// MemMan v1.1
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "memory.h"
|
||||
#include "resman.h"
|
||||
|
||||
|
||||
uint32 total_blocks;
|
||||
uint32 base_mem_block;
|
||||
uint32 total_free_memory;
|
||||
uint8 *free_memman; //address of init malloc to be freed later
|
||||
|
||||
//#define MEMDEBUG 1
|
||||
|
||||
mem mem_list[MAX_mem_blocks]; //list of defined memory handles - each representing a block of memory.
|
||||
|
||||
int32 VirtualDefrag( uint32 size ); // Used to determine if the required size can be obtained if the defragger is allowed to run.
|
||||
int32 suggestedStart = 0; // Start position of the Defragger as indicated by its sister VirtualDefrag.
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
void Close_memory_manager(void) //Tony2Oct96
|
||||
{
|
||||
|
||||
//unlock our supposedly locked in memory
|
||||
VirtualUnlock(free_memman, total_free_memory);
|
||||
|
||||
free(free_memman);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Init_memory_manager(void) //Tony9April96
|
||||
{
|
||||
uint32 j;
|
||||
uint8 *memory_base;
|
||||
//BOOL res;
|
||||
MEMORYSTATUS memo;
|
||||
|
||||
//find out how much actual physical RAM this computer has
|
||||
GlobalMemoryStatus(&memo);
|
||||
|
||||
//now decide how much to grab - 8MB computer are super critical
|
||||
if (memo.dwTotalPhys<=(8000*1024)) //if 8MB or less :-O
|
||||
total_free_memory=4500*1024; //4.5MB
|
||||
|
||||
else if (memo.dwTotalPhys<=(12000*1024)) //if 8MB or less :-O
|
||||
total_free_memory=8000*1024; //8MB
|
||||
|
||||
else if (memo.dwTotalPhys<=(16000*1024)) //if 16MB or less :-)
|
||||
total_free_memory=10000*1024; //10MB
|
||||
|
||||
else //:-)) loads of RAM
|
||||
total_free_memory=12000*1024; //12MB
|
||||
|
||||
|
||||
|
||||
Zdebug("MEM = %d", memo.dwTotalPhys);
|
||||
Zdebug("Sword 2 grabbed %dk", total_free_memory/1024);
|
||||
|
||||
|
||||
|
||||
//malloc memory and adjust for long boundaries
|
||||
memory_base = (uint8 *) malloc(total_free_memory);
|
||||
|
||||
if (!memory_base) //could not grab the memory
|
||||
{
|
||||
Zdebug("couldn't malloc %d in Init_memory_manager", total_free_memory);
|
||||
ExitWithReport("Init_memory_manager() couldn't malloc %d bytes [line=%d file=%s]",total_free_memory,__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
free_memman = memory_base; //the original malloc address
|
||||
|
||||
//force to long word boundary
|
||||
memory_base+=3;
|
||||
memory_base = (uint8 *)((uint32)memory_base & 0xfffffffc); // ** was (int)memory_base
|
||||
// total_free_memory-=3; //play safe
|
||||
|
||||
|
||||
|
||||
//set all but first handle to unused
|
||||
for (j=1;j<MAX_mem_blocks;j++)
|
||||
mem_list[j].state=MEM_null;
|
||||
|
||||
|
||||
total_blocks=1; //total used (free, locked or floating)
|
||||
|
||||
mem_list[0].ad = memory_base;
|
||||
mem_list[0].state= MEM_free;
|
||||
mem_list[0].age=0;
|
||||
mem_list[0].size=total_free_memory;
|
||||
mem_list[0].parent=-1; //we are base - for now
|
||||
mem_list[0].child=-1; //we are the end as well
|
||||
mem_list[0].uid=UID_memman; //init id
|
||||
|
||||
base_mem_block=0; //for now
|
||||
|
||||
|
||||
//supposedly this will stop the memory swapping out?? Well, as much as we're allowed
|
||||
// res=VirtualLock(free_memman, total_free_memory);
|
||||
|
||||
// if (res!=TRUE)
|
||||
// Zdebug(" *VirtualLock failed");
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
mem *Talloc(uint32 size, uint32 type, uint32 unique_id) //Tony10Apr96
|
||||
{
|
||||
//allocate a block of memory - locked or float
|
||||
|
||||
// returns 0 if fails to allocate the memory
|
||||
// or a pointer to a mem structure
|
||||
|
||||
int32 nu_block;
|
||||
uint32 spawn=0;
|
||||
uint32 slack;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//we must first round the size UP to a dword, so subsequent blocks will start dword alligned
|
||||
size+=3; //move up
|
||||
size &= 0xfffffffc; //and back down to boundary
|
||||
|
||||
|
||||
|
||||
|
||||
//find a free block large enough
|
||||
if ( (nu_block = Defrag_mem(size))==-1) //the defragger returns when its made a big enough block. This is a good time to defrag as we're probably not
|
||||
{ //doing anything super time-critical at the moment
|
||||
return(0); //error - couldn't find a big enough space
|
||||
}
|
||||
|
||||
|
||||
|
||||
//an exact fit?
|
||||
if (mem_list[nu_block].size==size) //no new block is required as the fit is perfect
|
||||
{
|
||||
mem_list[nu_block].state=type; //locked or float
|
||||
mem_list[nu_block].size=size; //set to the required size
|
||||
mem_list[nu_block].uid=unique_id; //an identifier
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
Mem_debug();
|
||||
#endif //MEMDEBUG
|
||||
return(&mem_list[nu_block]);
|
||||
}
|
||||
|
||||
|
||||
// nu_block is the free block to split, forming our locked/float block with a new free block in any remaining space
|
||||
|
||||
|
||||
//if our child is free then is can expand downwards to eat up our chopped space
|
||||
//this is good because it doesn't create an extra bloc so keeping the block count down
|
||||
//why?
|
||||
//imagine you Talloc 1000k, then free it. Now keep allocating 10 bytes less and freeing again
|
||||
//you end up with thousands of new free mini blocks. this way avoids that as the free child keeps growing downwards
|
||||
if ((mem_list[nu_block].child != -1) && (mem_list[mem_list[nu_block].child].state==MEM_free)) //our child is free
|
||||
{
|
||||
slack=mem_list[nu_block].size-size; //the spare memory is the blocks current size minus the amount we're taking
|
||||
|
||||
mem_list[nu_block].state=type; //locked or float
|
||||
mem_list[nu_block].size=size; //set to the required size
|
||||
mem_list[nu_block].uid=unique_id; //an identifier
|
||||
|
||||
mem_list[mem_list[nu_block].child].ad = mem_list[nu_block].ad+size; //child starts after us
|
||||
mem_list[mem_list[nu_block].child].size += slack; //childs size increases
|
||||
|
||||
return(&mem_list[nu_block]);
|
||||
}
|
||||
|
||||
|
||||
// otherwise we spawn a new block after us and before our child - our child being a proper block that we cannot change
|
||||
|
||||
// we remain a child of our parent
|
||||
// we spawn a new child and it inherits our current child
|
||||
|
||||
//find a NULL slot for a new block
|
||||
while((mem_list[spawn].state!=MEM_null)&&(spawn!=MAX_mem_blocks))
|
||||
spawn++;
|
||||
|
||||
|
||||
if (spawn==MAX_mem_blocks) //run out of blocks - stop the program. this is a major blow up and we need to alert the developer
|
||||
{
|
||||
Mem_debug(); //Lets get a printout of this
|
||||
ExitWithReport("ERROR: ran out of mem blocks in Talloc() [file=%s line=%u]",__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
|
||||
|
||||
mem_list[spawn].state=MEM_free; //new block is free
|
||||
mem_list[spawn].uid=UID_memman; //a memman created bloc
|
||||
mem_list[spawn].size= mem_list[nu_block].size-size; //size of the existing parent free block minus the size of the new space Talloc'ed.
|
||||
//IOW the remaining memory is given to the new free block
|
||||
mem_list[spawn].ad = mem_list[nu_block].ad+size; //we start 1 byte after the newly allocated block
|
||||
mem_list[spawn].parent=nu_block; //the spawned child gets it parent - the newly allocated block
|
||||
|
||||
mem_list[spawn].child=mem_list[nu_block].child; //the new child inherits the parents old child (we are its new child "Waaaa")
|
||||
|
||||
|
||||
|
||||
if (mem_list[spawn].child!=-1) //is the spawn the end block?
|
||||
mem_list[mem_list[spawn].child].parent= spawn; //the child of the new free-spawn needs to know its new parent
|
||||
|
||||
|
||||
mem_list[nu_block].state=type; //locked or float
|
||||
mem_list[nu_block].size=size; //set to the required size
|
||||
mem_list[nu_block].uid=unique_id; //an identifier
|
||||
mem_list[nu_block].child=spawn; //the new blocks new child is the newly formed free block
|
||||
|
||||
|
||||
total_blocks++; //we've brought a new block into the world. Ahhh!
|
||||
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
Mem_debug();
|
||||
#endif //MEMDEBUG
|
||||
|
||||
return(&mem_list[nu_block]);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Free_mem(mem *block) //Tony10Apr96
|
||||
{
|
||||
//kill a block of memory - which was presumably floating or locked
|
||||
//once you've done this the memory may be recycled
|
||||
|
||||
block->state=MEM_free;
|
||||
block->uid=UID_memman; //belongs to the memory manager again
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
Mem_debug();
|
||||
#endif //MEMDEBUG
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Float_mem(mem *block) //Tony10Apr96
|
||||
{
|
||||
//set a block to float
|
||||
//wont be trashed but will move around in memory
|
||||
|
||||
block->state=MEM_float;
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
Mem_debug();
|
||||
#endif //MEMDEBUG
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Lock_mem(mem *block) //Tony11Apr96
|
||||
{
|
||||
//set a block to lock
|
||||
//wont be moved - don't lock memory for any longer than necessary unless you know the locked memory is at the bottom of the heap
|
||||
|
||||
block->state=MEM_locked; //can't move now - this block is now crying out to be floated or free'd again
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
Mem_debug();
|
||||
#endif //MEMDEBUG
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 Defrag_mem(uint32 req_size) //Tony10Apr96
|
||||
{
|
||||
//moves floating blocks down and/or merges free blocks until a large enough space is found
|
||||
//or there is nothing left to do and a big enough block cannot be found
|
||||
//we stop when we find/create a large enough block - this is enough defragging.
|
||||
|
||||
int32 cur_block; //block 0 remains the parent block
|
||||
int32 original_parent,child, end_child;
|
||||
uint32 j;
|
||||
uint32 *a;
|
||||
uint32 *b;
|
||||
|
||||
|
||||
// cur_block=base_mem_block; //the mother of all parents
|
||||
cur_block = suggestedStart;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
if (mem_list[cur_block].state==MEM_free) //is current block a free block?
|
||||
{
|
||||
|
||||
if (mem_list[cur_block].size>=req_size)
|
||||
{
|
||||
return(cur_block); //this block is big enough - return its id
|
||||
}
|
||||
|
||||
|
||||
if (mem_list[cur_block].child==-1) //the child is the end block - stop if the next block along is the end block
|
||||
return(-1); //no luck, couldn't find a big enough block
|
||||
|
||||
|
||||
// current free block is too small, but if its child is *also* free then merge the two together
|
||||
if (mem_list[mem_list[cur_block].child].state==MEM_free)
|
||||
{
|
||||
// ok, we nuke the child and inherit its child
|
||||
|
||||
child=mem_list[cur_block].child;
|
||||
|
||||
mem_list[cur_block].size+= mem_list[child].size; //our size grows by the size of our child
|
||||
mem_list[cur_block].child = mem_list[child].child; //our new child is our old childs, child
|
||||
|
||||
if (mem_list[child].child!=-1) //not if the chld we're nuking is the end child (it has no child)
|
||||
mem_list[mem_list[child].child].parent=cur_block; //the (nuked) old childs childs parent is now us
|
||||
|
||||
mem_list[child].state=MEM_null; //clean up the nuked child, so it can be used again
|
||||
|
||||
total_blocks--;
|
||||
}
|
||||
|
||||
|
||||
// current free block is too small, but if its child is a float then we move the floating memory block down and the free up
|
||||
// but, parent/child relationships must be such that the memory is all continuous between blocks. ie. a childs memory always
|
||||
// begins 1 byte after its parent finishes. However, the positions in the memory list may become truly random, but, any particular
|
||||
// block of locked or floating memory must retain its position within the mem_list - the float stays a float because the handle/pointer has been passed back
|
||||
// what this means is that when the physical memory of the foat moves down (and the free up) the child becomes the parent and the parent the child
|
||||
// but, remember, the parent had a parent and the child another child - these swap over too as the parent/child swap takes place - phew.
|
||||
else if (mem_list[mem_list[cur_block].child].state==MEM_float)
|
||||
{
|
||||
child=mem_list[cur_block].child; //our child is currently floating
|
||||
|
||||
// memcpy(mem_list[cur_block].ad, mem_list[child].ad, mem_list[child].size); //move the higher float down over the free block
|
||||
|
||||
|
||||
a=(uint32*) mem_list[cur_block].ad;
|
||||
b=(uint32*) mem_list[child].ad;
|
||||
|
||||
for (j=0;j<mem_list[child].size/4;j++)
|
||||
*(a++)=*(b++);
|
||||
|
||||
|
||||
// both *ad's change
|
||||
mem_list[child].ad = mem_list[cur_block].ad; //the float is now where the free was
|
||||
mem_list[cur_block].ad += mem_list[child].size; //and the free goes up by the size of the float (which has come down)
|
||||
|
||||
// the status of the mem_list blocks must remain the same, so...
|
||||
original_parent= mem_list[cur_block].parent; //our child gets this when we become its child and it our parent
|
||||
mem_list[cur_block].parent=child; //the free's child becomes its parent
|
||||
mem_list[cur_block].child= mem_list[child].child; //the new child inherits its previous childs child
|
||||
|
||||
end_child=mem_list[child].child; //save this - see next line
|
||||
|
||||
mem_list[child].child=cur_block; //the floats parent becomes its child
|
||||
mem_list[child].parent= original_parent;
|
||||
|
||||
if (end_child!=-1) //if the child had a child
|
||||
mem_list[end_child].parent=cur_block; //then its parent is now the new child
|
||||
|
||||
if (original_parent==-1) //the base block was the true base parent
|
||||
base_mem_block=child; //then the child that has moved down becomes the base block as it sits at the lowest possible memory location
|
||||
else
|
||||
mem_list[original_parent].child=child; //otherwise the parent of the current free block - that is now the child - gets a new child,
|
||||
//that child being previously the child of the child of the original parent
|
||||
}
|
||||
else //if (mem_list[mem_list[cur_block].child].state==MEM_lock) //the child of current is locked - move to it
|
||||
cur_block=mem_list[cur_block].child; //move to next one along - either locked or END
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_block=mem_list[cur_block].child; //move to next one along, the current must be floating, locked, or a NULL slot
|
||||
}
|
||||
|
||||
}
|
||||
while(cur_block!=-1); //while the block we've just done is not the final block
|
||||
|
||||
return(-1); //no luck, couldn't find a big enough block
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Mem_debug(void) //Tony11Apr96
|
||||
{
|
||||
//gets called with Talloc, Mem_free, Mem_lock & Mem_float if MEMDEBUG has been #defined
|
||||
//otherwise can be called at any time anywhere else
|
||||
|
||||
int j;
|
||||
char inf[][20]=
|
||||
{
|
||||
{"MEM_null"},
|
||||
{"MEM_free"},
|
||||
{"MEM_locked"},
|
||||
{"MEM_float"}
|
||||
};
|
||||
|
||||
Zdebug("\nbase %d total %d", base_mem_block, total_blocks);
|
||||
|
||||
|
||||
//first in mem list order
|
||||
for (j=0;j<MAX_mem_blocks;j++)
|
||||
{
|
||||
if (mem_list[j].state==MEM_null)
|
||||
Zdebug("%d- NULL", j);
|
||||
else
|
||||
Zdebug("%d- state %s, ad %d, size %d, p %d, c %d, id %d", j,
|
||||
inf[mem_list[j].state],
|
||||
mem_list[j].ad, mem_list[j].size, mem_list[j].parent, mem_list[j].child, mem_list[j].uid);
|
||||
}
|
||||
|
||||
|
||||
//now in child/parent order
|
||||
j=base_mem_block;
|
||||
do
|
||||
{
|
||||
Zdebug(" %d- state %s, ad %d, size %d, p %d, c %d", j,
|
||||
inf[mem_list[j].state],
|
||||
mem_list[j].ad, mem_list[j].size, mem_list[j].parent, mem_list[j].child, mem_list[j].uid);
|
||||
|
||||
j=mem_list[j].child;
|
||||
}
|
||||
while (j!=-1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
mem *Twalloc(uint32 size, uint32 type, uint32 unique_id) //tony12Feb97
|
||||
{
|
||||
//the high level Talloc
|
||||
//can ask the resman to remove old resources to make space - will either do it or halt the system
|
||||
|
||||
mem *membloc;
|
||||
int j;
|
||||
uint32 free=0;
|
||||
|
||||
while( VirtualDefrag(size) )
|
||||
{
|
||||
if (!res_man.Help_the_aged_out()) //trash the oldest closed resource
|
||||
{
|
||||
Zdebug("Twalloc ran out of memory! %d %d %d\n", size, type, unique_id);
|
||||
ExitWithReport("Twalloc ran out of memory!");
|
||||
}
|
||||
}
|
||||
|
||||
membloc = Talloc(size, type, unique_id);
|
||||
|
||||
if (membloc == 0)
|
||||
{
|
||||
Zdebug("Talloc failed to get memory VirtualDefrag said was there");
|
||||
ExitWithReport("Talloc failed to get memory VirtualDefrag said was there");
|
||||
}
|
||||
|
||||
j=base_mem_block;
|
||||
do
|
||||
{
|
||||
|
||||
if (mem_list[j].state==MEM_free)
|
||||
free+=mem_list[j].size;
|
||||
|
||||
j=mem_list[j].child;
|
||||
}
|
||||
while (j!=-1);
|
||||
|
||||
return(membloc); //return the pointer to the memory
|
||||
}
|
||||
|
||||
|
||||
#define MAX_WASTAGE 51200 // Maximum allowed wasted memory.
|
||||
|
||||
int32 VirtualDefrag( uint32 size ) // Chris - 07 April '97
|
||||
{
|
||||
//
|
||||
// Virutually defrags memory...
|
||||
//
|
||||
// Used to determine if there is potentially are large enough free block available is the
|
||||
// real defragger was allowed to run.
|
||||
//
|
||||
// The idea being that Twalloc will call this and help_the_aged_out until we indicate that
|
||||
// it is possible to obtain a large enough free block. This way the defragger need only
|
||||
// run once to yield the required block size.
|
||||
//
|
||||
// The reason for its current slowness is that the defragger is potentially called several
|
||||
// times, each time shifting upto 20Megs around, to obtain the required free block.
|
||||
//
|
||||
int32 cur_block;
|
||||
uint32 currentBubbleSize = 0;
|
||||
|
||||
cur_block=base_mem_block;
|
||||
suggestedStart = base_mem_block;
|
||||
|
||||
do
|
||||
{
|
||||
if (mem_list[cur_block].state == MEM_free)
|
||||
{
|
||||
// Add a little intelligence. At the start the oldest resources are at the bottom of the
|
||||
// tube. However there will be some air at the top. Thus bubbles will be
|
||||
// created at the bottom and float to the top. If we ignore the top gap
|
||||
// then a large enough bubble will form lower down the tube. Thus less memory
|
||||
// will need to be shifted.
|
||||
|
||||
if (mem_list[cur_block].child != -1)
|
||||
currentBubbleSize += mem_list[cur_block].size;
|
||||
else if (mem_list[cur_block].size > MAX_WASTAGE)
|
||||
currentBubbleSize += mem_list[cur_block].size;
|
||||
|
||||
if (currentBubbleSize >= size)
|
||||
return 0;
|
||||
}
|
||||
else if (mem_list[cur_block].state == MEM_locked)
|
||||
{
|
||||
currentBubbleSize = 0;
|
||||
suggestedStart = mem_list[cur_block].child; // Any free block of the correct size will be above this locked block.
|
||||
}
|
||||
|
||||
cur_block = mem_list[cur_block].child;
|
||||
}
|
||||
while(cur_block != -1);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
82
sword2/memory.h
Normal file
82
sword2/memory.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
//#include "src\driver96.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 state;
|
||||
uint32 age; // *not used*
|
||||
uint32 size;
|
||||
int32 parent; //who is before us
|
||||
int32 child; //who is after us
|
||||
uint32 uid; //id of a position in the resList or some other unique id - for the visual display only
|
||||
uint8 *ad;
|
||||
} mem;
|
||||
|
||||
|
||||
#define MEM_null 0 //null
|
||||
#define MEM_free 1
|
||||
#define MEM_locked 2
|
||||
#define MEM_float 3
|
||||
|
||||
//---------------------------------------
|
||||
// MEMORY BLOCKS
|
||||
|
||||
#define MAX_mem_blocks 999
|
||||
|
||||
// maintain at a good 50% higher than the
|
||||
// highest recorded value from the on-screen info
|
||||
//---------------------------------------
|
||||
|
||||
#define UID_memman 0xffffffff
|
||||
#define UID_NULL 0xfffffffe //FREE
|
||||
#define UID_font 0xfffffffd
|
||||
#define UID_temp 0xfffffffc
|
||||
#define UID_decompression_buffer 0xfffffffb
|
||||
#define UID_shrink_buffer 0xfffffffa
|
||||
#define UID_con_sprite 0xfffffff9
|
||||
#define UID_text_sprite 0xfffffff8
|
||||
#define UID_walk_anim 0xfffffff7
|
||||
#define UID_savegame_buffer 0xfffffff6
|
||||
#define UID_restoregame_buffer 0xfffffff5
|
||||
|
||||
void Init_memory_manager(void);
|
||||
void Close_memory_manager(void); //Tony2Oct96
|
||||
//mem *Talloc(uint32 size, uint32 type, uint32 unique_id); //low level
|
||||
mem *Twalloc(uint32 size, uint32 type, uint32 unique_id); //high level
|
||||
void Free_mem(mem *block);
|
||||
void Float_mem(mem *block);
|
||||
void Lock_mem(mem *block);
|
||||
void Mem_debug(void);
|
||||
void Visual_mem_display(void);
|
||||
int32 Defrag_mem(uint32 req_size); //Tony10Apr96
|
||||
|
||||
|
||||
extern uint32 total_blocks;
|
||||
extern uint32 base_mem_block;
|
||||
extern mem mem_list[MAX_mem_blocks];
|
||||
extern uint32 total_free_memory;
|
||||
|
||||
#endif
|
46
sword2/module.mk
Normal file
46
sword2/module.mk
Normal file
|
@ -0,0 +1,46 @@
|
|||
MODULE := bs2
|
||||
|
||||
MODULE_OBJS = \
|
||||
bs2/anims.o \
|
||||
bs2/build_display.o \
|
||||
bs2/console.o \
|
||||
bs2/controls.o \
|
||||
bs2/debug.o \
|
||||
bs2/events.o \
|
||||
bs2/function.o \
|
||||
bs2/icons.o \
|
||||
bs2/interpreter.o \
|
||||
bs2/layers.o \
|
||||
bs2/logic.o \
|
||||
bs2/maketext.o \
|
||||
bs2/memory.o \
|
||||
bs2/mem_view.o \
|
||||
bs2/mouse.o \
|
||||
bs2/protocol.o \
|
||||
bs2/resman.o \
|
||||
bs2/router.o \
|
||||
bs2/save_rest.o \
|
||||
bs2/scroll.o \
|
||||
bs2/sound.o \
|
||||
bs2/speech.o \
|
||||
bs2/startup.o \
|
||||
bs2/sword2.o \
|
||||
bs2/sync.o \
|
||||
bs2/tony_gsdk.o \
|
||||
bs2/walker.o \
|
||||
bs2/driver/_console.o \
|
||||
bs2/driver/d_draw.o \
|
||||
bs2/driver/d_sound.o \
|
||||
bs2/driver/keyboard.o \
|
||||
bs2/driver/language.o \
|
||||
bs2/driver/menu.o \
|
||||
bs2/driver/misc.o \
|
||||
bs2/driver/_mouse.o \
|
||||
bs2/driver/palette.o \
|
||||
bs2/driver/rdwin.o \
|
||||
bs2/driver/render.o \
|
||||
bs2/driver/sprite.o
|
||||
|
||||
|
||||
# Include common rules
|
||||
include common.rules
|
1466
sword2/mouse.cpp
Normal file
1466
sword2/mouse.cpp
Normal file
File diff suppressed because it is too large
Load diff
89
sword2/mouse.h
Normal file
89
sword2/mouse.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//mouse stuff
|
||||
|
||||
#ifndef MOUSE_H
|
||||
#define MOUSE_H
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "object.h"
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
#define TOTAL_mouse_list 50
|
||||
|
||||
#define MOUSE_normal 0
|
||||
#define MOUSE_top 1
|
||||
#define MOUSE_drag 2
|
||||
#define MOUSE_system_menu 3
|
||||
#define MOUSE_holding 4
|
||||
//---------------------------------------------------------------------------------
|
||||
// mouse unit - like Object_mouse, but with anim resource & pc (needed if sprite is to act as mouse detection mask)
|
||||
typedef struct
|
||||
{
|
||||
int32 x1; // top-left of mouse area is (x1,y1)
|
||||
int32 y1;
|
||||
int32 x2; // bottom-right of area is (x2,y2) (these coords are inclusive)
|
||||
int32 y2;
|
||||
int32 priority;
|
||||
int32 pointer; // type (or resource id?) of pointer used over this area
|
||||
// up to here, this is basically a copy of the Object_mouse structure, but then we have...
|
||||
int32 id; // object id, used when checking mouse list
|
||||
int32 anim_resource; // resource id of animation file (if sprite to be used as mask) - otherwise 0
|
||||
int32 anim_pc; // current frame number of animation
|
||||
int32 pointer_text; // local id of text line to print when pointer highlights an object
|
||||
} Mouse_unit;
|
||||
//---------------------------------------------------------------------------------
|
||||
extern uint32 cur_mouse;
|
||||
extern Mouse_unit mouse_list[TOTAL_mouse_list];
|
||||
extern uint32 mouse_touching;
|
||||
extern uint32 mouse_mode;
|
||||
extern uint8 examining_menu_icon;
|
||||
|
||||
extern uint32 mouse_status; //human 0 on/1 off
|
||||
extern uint32 mouse_mode_locked; //0 not !0 mode cannot be changed from normal mouse to top menu (i.e. when carrying big objects)
|
||||
|
||||
extern uint32 real_luggage_item; //last minute for pause mode
|
||||
|
||||
extern uint32 pointerTextSelected;
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
void Reset_mouse_list(void); //Tony26Sept96
|
||||
|
||||
void Normal_mouse(void); //Tony30Sept96
|
||||
void Top_menu_mouse(void); //Tony3Oct96
|
||||
void Drag_mouse(void); //Tony21Nov96
|
||||
void System_menu(void); //Tony19Mar97
|
||||
|
||||
void Mouse_on_off(void); //Tony30Sept96
|
||||
uint32 Check_mouse_list(void); //Tony30Sept96
|
||||
void Mouse_engine(void); //Tony30Sept96
|
||||
|
||||
void Set_mouse(uint32 res);
|
||||
void Set_luggage(uint32 res); //Tony26Nov96
|
||||
|
||||
int32 FN_no_human(int32 *params); //Tony30Sept96
|
||||
int32 FN_add_human(int32 *params); //Tony30Sept96
|
||||
|
||||
void ClearPointerText(void); // James16jun97
|
||||
//---------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
#endif
|
124
sword2/object.h
Normal file
124
sword2/object.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _SCRIPT_STRUCTURES
|
||||
#define _SCRIPT_STRUCTURES
|
||||
|
||||
#include "driver/driver96.h"
|
||||
|
||||
// these structures represent the broken up compact components
|
||||
// these here declared to the system must be the same as those declared to LINC (or it wont work)
|
||||
|
||||
|
||||
// mouse structure - defines mouse detection area, detection priority & 'type' flag
|
||||
typedef struct
|
||||
{
|
||||
int32 x1; // top-left of mouse area is (x1,y1)
|
||||
int32 y1;
|
||||
int32 x2; // bottom-right of area is (x2,y2) (these coords are inclusive)
|
||||
int32 y2;
|
||||
int32 priority;
|
||||
int32 pointer; // type (or resource id?) of pointer used over this area
|
||||
} Object_mouse;
|
||||
|
||||
|
||||
// logic structure - contains fields used in logic script processing
|
||||
typedef struct
|
||||
{
|
||||
int32 looping; // 0 when first calling FN_<function>; 1 when calling subsequent times in same loop
|
||||
int32 pause; // pause count, used by FN_pause()
|
||||
} Object_logic;
|
||||
|
||||
//------------------------------------------------
|
||||
// status bits for 'type' field of Object_graphic)
|
||||
// in low word:
|
||||
#define NO_SPRITE 0x00000000 // don't print
|
||||
#define BGP0_SPRITE 0x00000001 // fixed to background parallax[0]
|
||||
#define BGP1_SPRITE 0x00000002 // fixed to background parallax[1]
|
||||
#define BACK_SPRITE 0x00000004 // 'background' sprite, fixed to main background
|
||||
#define SORT_SPRITE 0x00000008 // 'sorted' sprite, fixed to main background
|
||||
#define FORE_SPRITE 0x00000010 // 'foreground' sprite, fixed to main background
|
||||
#define FGP0_SPRITE 0x00000020 // fixed to foreground parallax[0]
|
||||
#define FGP1_SPRITE 0x00000040 // fixed to foreground parallax[0]
|
||||
|
||||
// in high word:
|
||||
#define UNSHADED_SPRITE 0x00000000 // not to be shaded
|
||||
#define SHADED_SPRITE 0x00010000 // to be shaded, based on shading mask
|
||||
//------------------------------------------------
|
||||
|
||||
// graphic structure - contains fields appropriate to sprite output
|
||||
typedef struct
|
||||
{
|
||||
int32 type; // see above
|
||||
int32 anim_resource; // resource id of animation file
|
||||
int32 anim_pc; // current frame number of animation
|
||||
} Object_graphic;
|
||||
|
||||
|
||||
// speech structure - contains fields used by speech scripts & text output
|
||||
typedef struct
|
||||
{
|
||||
int32 pen; // colour to use for body of characters
|
||||
int32 width; // max width of text sprite
|
||||
int32 command; // speech script command id
|
||||
int32 ins1; // speech script instruction parameters (may need more now?)
|
||||
int32 ins2;
|
||||
int32 ins3;
|
||||
int32 ins4;
|
||||
int32 ins5;
|
||||
int32 wait_state; //0 not waiting 1 waiting for next speech command
|
||||
} Object_speech;
|
||||
|
||||
|
||||
// mega structure - contains fields used for mega-character & mega-set processing
|
||||
typedef struct
|
||||
{
|
||||
int32 NOT_USED_1; // only free roaming megas need to check this before registering their graphics for drawing
|
||||
int32 NOT_USED_2; // id of floor on which we are standing
|
||||
int32 NOT_USED_3; // id of object which we are getting to
|
||||
int32 NOT_USED_4; // pixel distance to stand from player character when in conversation
|
||||
int32 currently_walking; // number given us by the auto router
|
||||
int32 walk_pc; // current frame number of walk-anim
|
||||
int32 scale_a; // current scale factors, taken from floor data
|
||||
int32 scale_b;
|
||||
int32 feet_x; // mega feet coords - frame-offsets are added to these position mega frames
|
||||
int32 feet_y;
|
||||
int32 current_dir; // current dirction faced by mega; used by autorouter to determine turns required
|
||||
int32 colliding; // means were currently avoiding a collision (see FN_walk)
|
||||
int32 megaset_res; // resource id of mega-set file
|
||||
int32 NOT_USED_5; // NOT USED
|
||||
} Object_mega;
|
||||
|
||||
|
||||
// walk-data structure - contains details of layout of frames in the mega-set, and how they are to be used
|
||||
typedef struct
|
||||
{
|
||||
int32 nWalkFrames; // no. of frames per walk-cycle
|
||||
int32 usingStandingTurnFrames; // 0=no 1=yes
|
||||
int32 usingWalkingTurnFrames; // 0=no 1=yes
|
||||
int32 usingSlowInFrames; // 0=no 1=yes
|
||||
int32 usingSlowOutFrames; // 0=no !0=number of slow-out frames in each direction
|
||||
int32 nSlowInFrames[8]; // no. of slow-in frames in each direction
|
||||
int32 leadingLeg[8]; // leading leg for walk in each direction (0=left 1=right)
|
||||
int32 dx[8*(12+1)]; // walk step distances in x direction
|
||||
int32 dy[8*(12+1)]; // walk step distances in y direction
|
||||
} Object_walkdata;
|
||||
|
||||
|
||||
#endif
|
240
sword2/protocol.cpp
Normal file
240
sword2/protocol.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
//#include <windows.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
#include "logic.h"
|
||||
#include "memory.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
// returns a pointer to the first palette entry, given the pointer to the start of the screen file
|
||||
// assumes it has been passed a pointer to a valid screen file
|
||||
uint8 *FetchPalette(uint8 *screenFile) // Chris 04Oct96
|
||||
{
|
||||
uint8 *palette;
|
||||
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
palette = (uint8 *)mscreenHeader + mscreenHeader->palette;
|
||||
|
||||
palette[0] = 0; // always set colour 0 to black
|
||||
palette[1] = 0; // because most background screen palettes have a bright colour 0
|
||||
palette[2] = 0; // although it should come out as black in the game!
|
||||
palette[3] = 0;
|
||||
|
||||
return palette;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
// returns a pointer to the start of the palette match table, given the pointer to the start of the screen file
|
||||
// assumes it has been passed a pointer to a valid screen file
|
||||
|
||||
uint8 *FetchPaletteMatchTable(uint8 *screenFile) // James 09dec96
|
||||
{
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
return (uint8 *) mscreenHeader + mscreenHeader->paletteTable;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
// returns a pointer to the screen header, given the pointer to the start of the screen file
|
||||
// assumes it has been passed a pointer to a valid screen file
|
||||
_screenHeader *FetchScreenHeader(uint8 *screenFile) //Chris 04Oct96
|
||||
{
|
||||
// Get the table
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
return (_screenHeader*) ((uint8 *) mscreenHeader + mscreenHeader->screen);
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
// returns a pointer to the requested layer header, given the pointer to the start of the screen file
|
||||
// drops out if the requested layer number exceeds the number of layers on this screen
|
||||
// assumes it has been passed a pointer to a valid screen file
|
||||
_layerHeader *FetchLayerHeader(uint8 *screenFile, uint16 layerNo) //Chris 04Oct96
|
||||
{
|
||||
_screenHeader *screenHead;
|
||||
|
||||
|
||||
screenHead = FetchScreenHeader(screenFile);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (layerNo > (screenHead->noLayers-1)) // layer number too large!
|
||||
Con_fatal_error("FetchLayerHeader(%d) invalid layer number! (%s line %u)",layerNo,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
return (_layerHeader *) ((uint8 *) mscreenHeader + mscreenHeader->layers + (layerNo * sizeof(_layerHeader)));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// returns a pointer to the start of the shading mask, given the pointer to the start of the screen file
|
||||
// assumes it has been passed a pointer to a valid screen file
|
||||
|
||||
uint8 *FetchShadingMask(uint8 *screenFile) // James 08apr97
|
||||
{
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
return (uint8 *) mscreenHeader + mscreenHeader->maskOffset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
// returns a pointer to the anim header, given the pointer to the start of the anim file
|
||||
// assumes it has been passed a pointer to a valid anim file
|
||||
|
||||
_animHeader *FetchAnimHeader(uint8 *animFile) // (25sep96JEL)
|
||||
{
|
||||
return (_animHeader *) (animFile + sizeof(_standardHeader));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// returns a pointer to the requested frame number's cdtEntry, given the pointer to the start of the anim file
|
||||
// drops out if the requested frame number exceeds the number of frames in this anim
|
||||
// assumes it has been passed a pointer to a valid anim file
|
||||
|
||||
_cdtEntry *FetchCdtEntry(uint8 *animFile, uint16 frameNo) // Chris 09Oct96
|
||||
{
|
||||
_animHeader *animHead;
|
||||
|
||||
animHead = FetchAnimHeader(animFile);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (frameNo > (animHead->noAnimFrames-1)) // frame number too large!
|
||||
Con_fatal_error("FetchCdtEntry(animFile,%d) - anim only %d frames (%s line %u)",frameNo,animHead->noAnimFrames,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
return (_cdtEntry *) ( (uint8 *)animHead + sizeof(_animHeader) + frameNo * sizeof(_cdtEntry) );
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// returns a pointer to the requested frame number's header, given the pointer to the start of the anim file
|
||||
// drops out if the requested frame number exceeds the number of frames in this anim
|
||||
// assumes it has been passed a pointer to a valid anim file
|
||||
|
||||
_frameHeader *FetchFrameHeader(uint8 *animFile, uint16 frameNo) // James 31oct96
|
||||
{
|
||||
// required address = (address of the start of the anim header) + frameOffset
|
||||
return (_frameHeader *) (animFile + sizeof(_standardHeader) + (FetchCdtEntry(animFile,frameNo)->frameOffset) );
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Returns a pointer to the requested parallax layer data.
|
||||
// Assumes it has been passed a pointer to a valid screen file.
|
||||
_parallax *FetchBackgroundParallaxLayer(uint8 *screenFile, int layer) // Chris 04Oct96
|
||||
{
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (mscreenHeader->bg_parallax[layer] == 0)
|
||||
Con_fatal_error("FetchBackgroundParallaxLayer(%d) - No parallax layer exists (%s line %u)",layer,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->bg_parallax[layer]);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
_parallax *FetchBackgroundLayer(uint8 *screenFile) // Chris 04Oct96
|
||||
{
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (mscreenHeader->screen == 0)
|
||||
Con_fatal_error("FetchBackgroundLayer (%d) - No background layer exists (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->screen + sizeof(_screenHeader));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
_parallax *FetchForegroundParallaxLayer(uint8 *screenFile, int layer) // Chris 04Oct96
|
||||
{
|
||||
_multiScreenHeader *mscreenHeader = (_multiScreenHeader *) (screenFile + sizeof(_standardHeader));
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (mscreenHeader->fg_parallax[layer] == 0)
|
||||
Con_fatal_error("FetchForegroundParallaxLayer(%d) - No parallax layer exists (%s line %u)",layer,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
return (_parallax *) ((uint8 *) mscreenHeader + mscreenHeader->fg_parallax[layer]);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint8 errorLine[128];
|
||||
//---------------------------------------------------------------
|
||||
uint8 *FetchTextLine(uint8 *file, uint32 text_line) //Tony24Oct96
|
||||
{
|
||||
// Get the table
|
||||
_standardHeader *fileHeader;
|
||||
uint32 *point;
|
||||
|
||||
|
||||
_textHeader *text_header = (_textHeader *) (file + sizeof(_standardHeader));
|
||||
|
||||
|
||||
if (text_line>=text_header->noOfLines) // (James08aug97)
|
||||
{
|
||||
fileHeader = (_standardHeader*)file;
|
||||
sprintf ((char*)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, fileHeader->name, text_header->noOfLines-1);
|
||||
errorLine[0]=0; // first 2 chars are NULL so that actor-number comes out as '0'
|
||||
errorLine[1]=0;
|
||||
return(errorLine);
|
||||
|
||||
// GOT RID OF CON_FATAL_ERROR HERE BECAUSE WE DON'T WANT IT TO CRASH OUT ANY MORE!
|
||||
// Con_fatal_error("FetchTextLine cannot get %d, only 0..%d avail (%s line %u)", text_line, text_header->noOfLines-1,__FILE__,__LINE__);
|
||||
}
|
||||
|
||||
|
||||
point=(uint32*) text_header+1; //point to the lookup table
|
||||
|
||||
return( (uint8*) (file+ *(point+text_line)) );
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Used for testing text & speech (see FN_I_speak in speech.cpp)
|
||||
uint8 CheckTextLine(uint8 *file, uint32 text_line) // (James26jun97)
|
||||
{
|
||||
_textHeader *text_header = (_textHeader *) (file + sizeof(_standardHeader));
|
||||
|
||||
if (text_line>=text_header->noOfLines)
|
||||
return(0); // out of range => invalid
|
||||
else
|
||||
return(1); // valid
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint8 *FetchObjectName(int32 resourceId) // James15jan97
|
||||
{
|
||||
_standardHeader *header;
|
||||
|
||||
header = (_standardHeader*) res_man.Res_open(resourceId);
|
||||
|
||||
res_man.Res_close(resourceId);
|
||||
|
||||
return (header->name); // note this pointer is no longer valid, but it should be ok until another resource is opened!
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
44
sword2/protocol.h
Normal file
44
sword2/protocol.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//the usual suspects (the usual suspicions)
|
||||
|
||||
#ifndef _PROTOCOL
|
||||
#define _PROTOCOL
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "header.h"
|
||||
|
||||
uint8 *FetchPalette(uint8 *screenFile); // Chris 04Oct96
|
||||
_screenHeader *FetchScreenHeader(uint8 *screenFile); //Chris 04Oct96
|
||||
_layerHeader *FetchLayerHeader(uint8 *screenFile, uint16 layerNo); //Chris 04Oct96
|
||||
uint8 *FetchShadingMask(uint8 *screenFile); // James 08apr97
|
||||
|
||||
_animHeader *FetchAnimHeader(uint8 *animFile); // (25sep96JEL)
|
||||
_cdtEntry *FetchCdtEntry(uint8 *animFile, uint16 frameNo); // (31oct96 JEL)
|
||||
_frameHeader *FetchFrameHeader(uint8 *animFile, uint16 frameNo); // (25sep96JEL)
|
||||
_parallax *FetchBackgroundParallaxLayer(uint8 *screenFile, int layer); // Chris 04Oct96
|
||||
_parallax *FetchBackgroundLayer(uint8 *screenFile); // Chris 04Oct96
|
||||
_parallax *FetchForegroundParallaxLayer(uint8 *screenFile, int layer); // Chris 04Oct96
|
||||
uint8 *FetchTextLine(uint8 *file, uint32 text_line); //Tony24Oct96
|
||||
uint8 CheckTextLine(uint8 *file, uint32 text_line); // (James26jun97)
|
||||
uint8 *FetchPaletteMatchTable(uint8 *screenFile); // James 09dec96
|
||||
uint8 *FetchObjectName(int32 resourceId); // James15jan97
|
||||
|
||||
#endif
|
1539
sword2/resman.cpp
Normal file
1539
sword2/resman.cpp
Normal file
File diff suppressed because it is too large
Load diff
101
sword2/resman.h
Normal file
101
sword2/resman.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef RESMAN_H
|
||||
#define RESMAN_H
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define MAX_res_files 20
|
||||
|
||||
#define RES_locked 1
|
||||
#define RES_perm 2
|
||||
|
||||
|
||||
class resMan
|
||||
{
|
||||
public:
|
||||
|
||||
void InitResMan(void); //read in the config file
|
||||
void Close_ResMan(void); //Tony29May96
|
||||
//----
|
||||
uint8 *Res_open(uint32 res); //returns ad of resource. Loads if not in memory
|
||||
//retains a count
|
||||
//resource can be aged out of memory if count=0
|
||||
//the resource is locked while count!=0
|
||||
|
||||
void Res_close(uint32 res); //decrements the count
|
||||
|
||||
//----
|
||||
|
||||
uint8 Res_check_valid( uint32 res ); // returns '0' if resource out of range or null, otherwise '1' for ok
|
||||
|
||||
//resource floats when count=0
|
||||
//----
|
||||
char *Fetch_cluster(uint32 res); //for mem_view to query the owners of mem blocs
|
||||
uint32 Fetch_age(uint32 res); //
|
||||
uint32 Fetch_count(uint32 count); //
|
||||
|
||||
uint32 Help_the_aged_out(void); //Tony10Oct96
|
||||
|
||||
uint32 Res_fetch_len( uint32 res ); //Tony27Jan96
|
||||
|
||||
void Res_next_cycle( void );
|
||||
uint32 Res_fetch_useage( void );
|
||||
|
||||
void GetCd(int cd); // Prompts the user for the specified CD.
|
||||
int WhichCd() {return curCd;}
|
||||
|
||||
//----console commands
|
||||
void Print_console_clusters(void); //Tony10Oct96
|
||||
void Examine_res(uint8 *input); //Tony23Oct96
|
||||
void Kill_all_res(uint8 wantInfo); //Tony29Nov96
|
||||
void Kill_all_objects(uint8 wantInfo); // James17jan97
|
||||
void Remove_res(uint32 res); //Tony10Jan97
|
||||
void Remove_all_res(void); // James24mar97
|
||||
void Kill_res(uint8 *res); //Tony23Oct96
|
||||
char *GetCdPath( void ); // Chris 9Apr97
|
||||
|
||||
|
||||
mem **resList; //pointer to a pointer (or list of pointers in-fact)
|
||||
|
||||
private:
|
||||
|
||||
int curCd;
|
||||
uint32 total_res_files;
|
||||
uint32 total_clusters;
|
||||
uint32 current_memory_useage;
|
||||
uint32 resTime; //inc's each time Res_open is called and is given to resource as its age
|
||||
//cannot be allowed to start at 0! (a pint if you can tell me why)
|
||||
uint32 *age;
|
||||
uint16 *res_conv_table; //Gode generated res-id to res number/rel number conversion table
|
||||
uint16 *count;
|
||||
char resource_files[MAX_res_files][20];
|
||||
uint8 cdTab[MAX_res_files]; // Location of each cluster.
|
||||
char cdPath[256]; // Drive letter of the CD-ROM drive or false CD path.
|
||||
void CacheNewCluster(uint32 newCluster);
|
||||
char cdDrives[24];
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern resMan res_man; //declare the object global
|
||||
|
||||
#endif
|
3089
sword2/router.cpp
Normal file
3089
sword2/router.cpp
Normal file
File diff suppressed because it is too large
Load diff
58
sword2/router.h
Normal file
58
sword2/router.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _ROUTER_H
|
||||
#define _ROUTER_H
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
|
||||
|
||||
typedef struct _walkData
|
||||
{
|
||||
uint16 frame;
|
||||
int16 x;
|
||||
int16 y;
|
||||
uint8 step;
|
||||
uint8 dir;
|
||||
} _walkData;
|
||||
|
||||
|
||||
|
||||
|
||||
int32 RouteFinder(Object_mega *ob_mega, Object_walkdata *ob_walkdata, int32 x, int32 y, int32 dir);
|
||||
|
||||
void EarlySlowOut(Object_mega *ob_mega, Object_walkdata *ob_walkdata);
|
||||
|
||||
void AllocateRouteMem(void);
|
||||
_walkData* LockRouteMem(void);
|
||||
void FloatRouteMem(void);
|
||||
void FreeRouteMem(void);
|
||||
void FreeAllRouteMem(void);
|
||||
void PlotWalkGrid(void);
|
||||
void AddWalkGrid(int32 gridResource);
|
||||
void RemoveWalkGrid(int32 gridResource);
|
||||
void ClearWalkGridList(void);
|
||||
uint8 CheckForCollision(void);
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif
|
556
sword2/save_rest.cpp
Normal file
556
sword2/save_rest.cpp
Normal file
|
@ -0,0 +1,556 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
// SAVE_REST.CPP save, restore & restart functions
|
||||
//
|
||||
// James 05feb97
|
||||
//
|
||||
// "Jesus Saves", but could he Restore or Restart? He can now...
|
||||
//
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
//#include <direct.h> directx?
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "console.h"
|
||||
#include "defs.h"
|
||||
#include "function.h" // for engine_logic, engine_graph, etc
|
||||
#include "interpreter.h" // for IR_CONT, etc
|
||||
#include "layers.h"
|
||||
#include "logic.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "router.h"
|
||||
#include "save_rest.h"
|
||||
#include "scroll.h" // for Set_scrolling()
|
||||
#include "sound.h"
|
||||
#include "walker.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#define MAX_FILENAME_LEN 128 // max length of a savegame filename, including full path
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
|
||||
void GetPlayerStructures(void); // James27feb97
|
||||
void PutPlayerStructures(void); // James27feb97
|
||||
|
||||
uint32 SaveData(uint16 slotNo, uint8 *buffer, uint32 bufferSize);
|
||||
uint32 RestoreData(uint16 slotNo, uint8 *buffer, uint32 bufferSize);
|
||||
|
||||
uint32 CalcChecksum(uint8 *buffer, uint32 size); // James04aug97
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
typedef struct // savegame file header (James06feb97)
|
||||
{
|
||||
uint32 checksum; // sum of all bytes in file, excluding this uint32
|
||||
char description[SAVE_DESCRIPTION_LEN]; // player's description of savegame
|
||||
uint32 varLength; // length of global variables resource
|
||||
uint32 screenId; // resource id of screen file
|
||||
uint32 runListId; // resource id of run list
|
||||
uint32 feet_x; // copy of this_screen.feet_x
|
||||
uint32 feet_y; // copy of this_screen.feet_y
|
||||
uint32 music_id; // copy of 'looping_music_id'
|
||||
_object_hub player_hub; // copy of player object's object_hub structure
|
||||
Object_logic logic; // copy of player character logic structure
|
||||
Object_graphic graphic; // copy of player character graphic structure
|
||||
Object_mega mega; // copy of player character mega structure
|
||||
}
|
||||
_savegameHeader;
|
||||
|
||||
// savegame consists of header & global variables resource
|
||||
|
||||
_savegameHeader header; // global because easier to copy to/from player object structures
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
// SAVE GAME
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint32 SaveGame(uint16 slotNo, uint8 *desc) // (James05feb97)
|
||||
{
|
||||
mem *saveBufferMem;
|
||||
uint32 bufferSize;
|
||||
uint32 errorCode;
|
||||
|
||||
//------------------------------------------------------
|
||||
// allocate the savegame buffer
|
||||
|
||||
bufferSize = FindBufferSize();
|
||||
saveBufferMem = Twalloc( bufferSize, MEM_locked, UID_savegame_buffer );
|
||||
|
||||
FillSaveBuffer(saveBufferMem, bufferSize, desc);
|
||||
|
||||
//------------------------------------------------------
|
||||
// save it (platform-specific)
|
||||
|
||||
errorCode = SaveData( slotNo, saveBufferMem->ad, bufferSize ); // save the buffer
|
||||
|
||||
//------------------------------------------------------
|
||||
// free the buffer
|
||||
|
||||
Free_mem( saveBufferMem );
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
return(errorCode);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// calculate size of required savegame buffer
|
||||
|
||||
uint32 FindBufferSize( void )
|
||||
{
|
||||
return (sizeof(header) + res_man.Res_fetch_len(1)); // size of savegame header + size of global variables
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
void FillSaveBuffer(mem *buffer, uint32 size, uint8 *desc)
|
||||
{
|
||||
uint8 *varsRes;
|
||||
|
||||
//------------------------------------------------------
|
||||
// set up the header
|
||||
|
||||
// 'checksum' gets filled in last of all
|
||||
sprintf(header.description, "%s", (char*)desc); // player's description of savegame
|
||||
header.varLength = res_man.Res_fetch_len(1); // length of global variables resource
|
||||
header.screenId = this_screen.background_layer_id; // resource id of current screen file
|
||||
header.runListId = LLogic.Return_run_list(); // resource id of current run-list
|
||||
header.feet_x = this_screen.feet_x; // those scroll position control things
|
||||
header.feet_y = this_screen.feet_y; //
|
||||
header.music_id = looping_music_id; // id of currently looping music (or zero)
|
||||
|
||||
// object hub
|
||||
memcpy (&header.player_hub, res_man.Res_open(CUR_PLAYER_ID) + sizeof(_standardHeader), sizeof(_object_hub));
|
||||
res_man.Res_close(CUR_PLAYER_ID);
|
||||
|
||||
// logic, graphic & mega structures
|
||||
GetPlayerStructures(); // copy the 4 essential player object structures into the header
|
||||
|
||||
//------------------------------------------------------
|
||||
// copy the header to the buffer
|
||||
|
||||
memcpy( buffer->ad, &header, sizeof(header) ); // copy the header to the savegame buffer
|
||||
|
||||
//------------------------------------------------------
|
||||
// copy the global variables to the buffer
|
||||
|
||||
varsRes = res_man.Res_open(1); // open variables resource
|
||||
memcpy( buffer->ad + sizeof(header), varsRes, header.varLength ); // copy that to the buffer, following the header
|
||||
res_man.Res_close(1); // close variables resource
|
||||
|
||||
//------------------------------------------------------
|
||||
// set the checksum & copy that to the buffer (James05aug97)
|
||||
|
||||
header.checksum = CalcChecksum((buffer->ad)+sizeof(header.checksum), size-sizeof(header.checksum));
|
||||
memcpy( buffer->ad, &header.checksum, sizeof(header.checksum) ); // copy the header to the savegame buffer
|
||||
|
||||
//------------------------------------------------------
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint32 SaveData(uint16 slotNo, uint8 *buffer, uint32 bufferSize)
|
||||
{
|
||||
char saveFileName[MAX_FILENAME_LEN];
|
||||
FILE *fp;
|
||||
uint32 itemsWritten;
|
||||
|
||||
|
||||
//create saves directory just in case not there
|
||||
_mkdir("saves");
|
||||
|
||||
|
||||
sprintf(saveFileName, "saves\\savegame.%.3d", slotNo); // construct filename
|
||||
|
||||
fp = fopen(saveFileName, "wb"); // attempt to open file for writing
|
||||
|
||||
if (fp==NULL)
|
||||
{
|
||||
return(SR_ERR_FILEOPEN); // error: couldn't open file
|
||||
}
|
||||
else
|
||||
{
|
||||
// itemsWritten = fwrite(sourceAddress, size, count, fp);
|
||||
itemsWritten = fwrite(buffer, 1, bufferSize, fp); // write the buffer
|
||||
fclose(fp); // close savegame file
|
||||
|
||||
if (itemsWritten == bufferSize) // if we successfully wrote it all
|
||||
return(SR_OK); // buffer saved ok
|
||||
else
|
||||
return(SR_ERR_WRITEFAIL); // write failed for some reason (could be hard drive full)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
// RESTORE GAME
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint32 RestoreGame(uint16 slotNo) // (James05feb97)
|
||||
{
|
||||
mem *saveBufferMem;
|
||||
uint32 bufferSize;
|
||||
uint32 errorCode;
|
||||
|
||||
//------------------------------------------------------
|
||||
// allocate the savegame buffer
|
||||
|
||||
bufferSize = FindBufferSize();
|
||||
saveBufferMem = Twalloc( bufferSize, MEM_locked, UID_savegame_buffer );
|
||||
|
||||
//------------------------------------------------------
|
||||
// read the savegame file into our buffer
|
||||
|
||||
errorCode = RestoreData( slotNo, saveBufferMem->ad, bufferSize ); // load savegame into buffer
|
||||
|
||||
//------------------------------------------------------
|
||||
// if it was read in successfully, then restore the game from the buffer & free the buffer
|
||||
|
||||
if (errorCode == SR_OK)
|
||||
{
|
||||
errorCode = RestoreFromBuffer(saveBufferMem, bufferSize);
|
||||
|
||||
// Note that the buffer has been freed inside RestoreFromBuffer,
|
||||
// in order to clear it from memory before loading in the new screen & runlist
|
||||
}
|
||||
else
|
||||
Free_mem( saveBufferMem ); // because RestoreFromBuffer would have freed it
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
return(errorCode); // game restored ok
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint32 RestoreData(uint16 slotNo, uint8 *buffer, uint32 bufferSize)
|
||||
{
|
||||
char saveFileName[MAX_FILENAME_LEN];
|
||||
FILE *fp;
|
||||
uint32 itemsRead;
|
||||
|
||||
|
||||
sprintf(saveFileName, "saves\\savegame.%.3d", slotNo); // construct filename
|
||||
|
||||
fp = fopen(saveFileName, "rb"); // attempt to open file for reading
|
||||
|
||||
if (fp==NULL)
|
||||
{
|
||||
return(SR_ERR_FILEOPEN); // error: couldn't open file
|
||||
}
|
||||
else
|
||||
{
|
||||
// itemsRead = fread(destAddress, size, count, fp);
|
||||
itemsRead = fread(buffer, 1, bufferSize, fp); // read savegame into the buffer
|
||||
|
||||
if (itemsRead == bufferSize) // if we successfully read it all
|
||||
{
|
||||
fclose(fp); // close savegame file
|
||||
return(SR_OK); // file read ok
|
||||
}
|
||||
else // didn't read the expected amount of data for some reason
|
||||
{
|
||||
if (ferror(fp)) // if it was a genuine read error, before reaching the end of the file
|
||||
{
|
||||
fclose(fp); // close savegame file
|
||||
return(SR_ERR_READFAIL); // error: read failed
|
||||
}
|
||||
else // we reached the end of the file before we filled the savegame buffer (ie. incompatible savegame file!)
|
||||
{
|
||||
fclose(fp); // close savegame file
|
||||
return(SR_ERR_INCOMPATIBLE); // error: incompatible save-data - can't use!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 RestoreFromBuffer(mem *buffer, uint32 size)
|
||||
{
|
||||
uint8 *varsRes;
|
||||
int32 pars[2];
|
||||
|
||||
memcpy( &header, buffer->ad, sizeof(header) ); // get a copy of the header from the savegame buffer
|
||||
|
||||
//------------------------------------------------------
|
||||
// Calc checksum & check that aginst the value stored in the header (James05aug97)
|
||||
|
||||
if (header.checksum != CalcChecksum((buffer->ad)+sizeof(header.checksum), size-sizeof(header.checksum)))
|
||||
{
|
||||
Free_mem( buffer );
|
||||
return(SR_ERR_INCOMPATIBLE); // error: incompatible save-data - can't use!
|
||||
}
|
||||
//------------------------------------------------------
|
||||
// check savegame against length of current global variables resource
|
||||
// This would most probably be trapped by the checksum test anyway, but it doesn't do any harm to check this as well
|
||||
|
||||
// Note that during development, earlier savegames will often be shorter than the current expected length
|
||||
|
||||
if (header.varLength != res_man.Res_fetch_len(1)) // if header contradicts actual current size of global variables
|
||||
{
|
||||
Free_mem( buffer );
|
||||
return(SR_ERR_INCOMPATIBLE); // error: incompatible save-data - can't use!
|
||||
}
|
||||
//----------------------------------
|
||||
// clean out system
|
||||
res_man.Kill_all_res(0); // trash all resources from memory except player object & global variables
|
||||
LLogic.Reset_kill_list(); // clean out the system kill list (no more objects to kill)
|
||||
|
||||
//----------------------------------
|
||||
// get player character data from savegame buffer
|
||||
|
||||
// object hub is just after the standard header
|
||||
memcpy (res_man.Res_open(CUR_PLAYER_ID) + sizeof(_standardHeader), &header.player_hub, sizeof(_object_hub));
|
||||
res_man.Res_close(CUR_PLAYER_ID);
|
||||
PutPlayerStructures(); // fill in the 4 essential player object structures from the header
|
||||
|
||||
//----------------------------------
|
||||
// get variables resource from the savegame buffer
|
||||
|
||||
varsRes = res_man.Res_open(1); // open variables resource
|
||||
memcpy( varsRes, buffer->ad + sizeof(header), header.varLength );// copy that to the buffer, following the header
|
||||
res_man.Res_close(1); // close variables resource
|
||||
|
||||
Free_mem( buffer ); // free it now, rather than in RestoreGame, to unblock memory before new screen & runlist loaded
|
||||
pars[0] = header.screenId;
|
||||
pars[1] = 1;
|
||||
FN_init_background(pars);
|
||||
this_screen.new_palette=99; // (JEL08oct97) so palette not restored immediately after control panel - we want to fade up instead!
|
||||
|
||||
this_screen.feet_x = header.feet_x; // these need setting after the defaults get set in FN_init_background
|
||||
this_screen.feet_y = header.feet_y; // remember that these can change through the game, so need saving & restoring too
|
||||
LLogic.Express_change_session(header.runListId); // start the new run list
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// (James01aug97)
|
||||
// Force in the new scroll position, so unsightly scroll-catch-up does not occur
|
||||
// when screen first draws after returning from restore panel
|
||||
|
||||
this_screen.player_feet_x = header.mega.feet_x; // set 'this_screen's record of player position
|
||||
this_screen.player_feet_y = header.mega.feet_y; // - ready for Set_scrolling()
|
||||
|
||||
if (this_screen.scroll_flag) // if this screen is wide
|
||||
Set_scrolling(); // recompute the scroll offsets now,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Any music required will be started after we've returned from Restore_control()
|
||||
// - see System_menu() in mouse.cpp!
|
||||
looping_music_id = header.music_id;
|
||||
//------------------------------------------------------
|
||||
|
||||
//--------------------------------------
|
||||
// Write to walkthrough file (zebug0.txt)
|
||||
#ifdef _DEBUG
|
||||
Zdebug(0,"*************************************");
|
||||
Zdebug(0,"RESTORED GAME \"%s\"", header.description);
|
||||
Zdebug(0,"*************************************");
|
||||
|
||||
// Also write this to system debug file
|
||||
Zdebug("*************************************");
|
||||
Zdebug("RESTORED GAME \"%s\"", header.description);
|
||||
Zdebug("*************************************");
|
||||
#endif
|
||||
//--------------------------------------
|
||||
|
||||
|
||||
return(SR_OK); // game restored ok
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
// GetSaveDescription - PC version...
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint32 GetSaveDescription(uint16 slotNo, uint8 *description) // (James05feb97)
|
||||
{
|
||||
char saveFileName[MAX_FILENAME_LEN];
|
||||
_savegameHeader header;
|
||||
FILE *fp;
|
||||
|
||||
sprintf(saveFileName, "saves\\savegame.%.3d", slotNo); // construct filename
|
||||
|
||||
fp = fopen(saveFileName, "rb"); // attempt to open file for reading
|
||||
|
||||
if (fp==NULL)
|
||||
{
|
||||
return(SR_ERR_FILEOPEN); // error: couldn't open file
|
||||
}
|
||||
else
|
||||
{
|
||||
// fread(destAddress, size, count, fp);
|
||||
fread(&header, sizeof(header), 1, fp); // read header
|
||||
fclose(fp);
|
||||
sprintf((char*)description, header.description);
|
||||
return(SR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
void GetPlayerStructures(void) // James27feb97
|
||||
{
|
||||
// request the player object structures which need saving
|
||||
|
||||
uint32 null_pc=7; // script no. 7 - 'george_savedata_request' calls FN_pass_player_savedata
|
||||
char *raw_script_ad;
|
||||
_standardHeader *head;
|
||||
|
||||
|
||||
head = (_standardHeader*) res_man.Res_open(CUR_PLAYER_ID);
|
||||
|
||||
if (head->fileType!=GAME_OBJECT)
|
||||
Con_fatal_error("incorrect CUR_PLAYER_ID=%d (%s line %u)",CUR_PLAYER_ID,__FILE__,__LINE__);
|
||||
|
||||
raw_script_ad = (char *)head; // (head+1) + sizeof(_object_hub); //get to raw script data
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc );
|
||||
res_man.Res_close(CUR_PLAYER_ID);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void PutPlayerStructures(void) // James27feb97 (updated by James on 29july97)
|
||||
{
|
||||
// fill out the player object structures from the savegame structures
|
||||
// also run the appropriate scripts to set up george's anim tables & walkdata, and nico's anim tables
|
||||
|
||||
uint32 null_pc=8; // script no. 8 - 'george_savedata_return' calls FN_get_player_savedata
|
||||
char *raw_script_ad;
|
||||
_standardHeader *head;
|
||||
|
||||
|
||||
head = (_standardHeader*) res_man.Res_open(CUR_PLAYER_ID);
|
||||
|
||||
if (head->fileType!=GAME_OBJECT)
|
||||
Con_fatal_error("incorrect CUR_PLAYER_ID=%d (%s line %u)",CUR_PLAYER_ID,__FILE__,__LINE__);
|
||||
|
||||
raw_script_ad = (char *)head; // (head+1) + sizeof(_object_hub); //get to raw script data
|
||||
|
||||
null_pc=8; // script no. 8 - 'george_savedata_return' calls FN_get_player_savedata
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc );
|
||||
|
||||
null_pc=14; // script no. 14 - 'set_up_nico_anim_tables'
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc );
|
||||
|
||||
switch (header.mega.megaset_res) // which megaset was the player at the time of saving?
|
||||
{
|
||||
case 36: // GeoMega:
|
||||
null_pc=9; // script no.9 - 'player_is_george'
|
||||
break;
|
||||
|
||||
case 2003: // GeoMegaB:
|
||||
null_pc=13; // script no.13 - 'player_is_georgeB'
|
||||
break;
|
||||
|
||||
case 1366: // NicMegaA:
|
||||
null_pc=11; // script no.11 - 'player_is_nicoA'
|
||||
break;
|
||||
|
||||
case 1437: // NicMegaB:
|
||||
null_pc=12; // script no.12 - 'player_is_nicoB'
|
||||
break;
|
||||
|
||||
case 1575: // NicMegaC:
|
||||
null_pc=10; // script no.10 - 'player_is_nicoC'
|
||||
break;
|
||||
}
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc );
|
||||
|
||||
res_man.Res_close(CUR_PLAYER_ID);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_pass_player_savedata(int32 *params) // James27feb97
|
||||
{
|
||||
// copies the 4 essential player structures into the savegame header
|
||||
// - run script 7 of player object to request this
|
||||
|
||||
// remember, we cannot simply read a compact any longer but instead must request it from the object itself
|
||||
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
|
||||
// copy from player object to savegame header
|
||||
memcpy( &header.logic, (uint8*)params[0], sizeof(Object_logic) );
|
||||
memcpy( &header.graphic, (uint8*)params[1], sizeof(Object_graphic) );
|
||||
memcpy( &header.mega, (uint8*)params[2], sizeof(Object_mega) );
|
||||
|
||||
return(IR_CONT); //makes no odds
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_get_player_savedata(int32 *params) // James27feb97
|
||||
{
|
||||
// reverse of FN_pass_player_savedata
|
||||
// - run script 8 of player object
|
||||
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
|
||||
Object_logic *ob_logic = (Object_logic*) params[0];
|
||||
Object_graphic *ob_graphic = (Object_graphic*) params[1];
|
||||
Object_mega *ob_mega = (Object_mega*) params[2];
|
||||
|
||||
int32 pars[3];
|
||||
|
||||
|
||||
// copy from savegame header to player object
|
||||
memcpy( (uint8*)ob_logic, &header.logic, sizeof(Object_logic) );
|
||||
memcpy( (uint8*)ob_graphic, &header.graphic, sizeof(Object_graphic) );
|
||||
memcpy( (uint8*)ob_mega, &header.mega, sizeof(Object_mega) );
|
||||
|
||||
|
||||
// any walk-data must be cleared - the player will be set to stand if he was walking when saved
|
||||
|
||||
if (ob_mega->currently_walking) // if the player was walking when game was saved
|
||||
{
|
||||
ob_mega->currently_walking = 0; // clear the flag
|
||||
ob_mega->colliding = 0; // reset this just in case
|
||||
|
||||
pars[0] = (int32)ob_graphic; // pointer to object's graphic structure
|
||||
pars[1] = (int32)ob_mega; // pointer to object's mega structure
|
||||
pars[2] = ob_mega->current_dir; // target direction
|
||||
FN_stand(pars); // set player to stand
|
||||
|
||||
ob_logic->looping = 0; // reset looping flag (which would have been '1' during FN_walk)
|
||||
}
|
||||
|
||||
|
||||
return(IR_CONT); //makes no odds
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 CalcChecksum(uint8 *buffer, uint32 size) // (James05aug97)
|
||||
{
|
||||
uint32 total=0;
|
||||
uint32 pos;
|
||||
|
||||
for (pos=0; pos<size; pos++)
|
||||
total += buffer[pos];
|
||||
|
||||
return(total);
|
||||
}
|
47
sword2/save_rest.h
Normal file
47
sword2/save_rest.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef SAVE_REST_H
|
||||
#define SAVE_REST_H
|
||||
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define SAVE_DESCRIPTION_LEN 64
|
||||
|
||||
uint32 SaveGame(uint16 slotNo, uint8 *description);
|
||||
uint32 RestoreGame(uint16 slotNo);
|
||||
uint32 GetSaveDescription(uint16 slotNo, uint8 *description);
|
||||
void FillSaveBuffer(mem *buffer, uint32 size, uint8 *desc);
|
||||
uint32 RestoreFromBuffer(mem *buffer, uint32 size);
|
||||
uint32 FindBufferSize( void );
|
||||
|
||||
|
||||
// Save & Restore error codes
|
||||
|
||||
// ERROR CODE VALUE MEANING REASON
|
||||
// ========== ===== ======= ======
|
||||
#define SR_OK 0x00000000 // ok No worries
|
||||
#define SR_ERR_FILEOPEN 0x00000001 // can't open file Could create file for saving, or couldn't find file for loading
|
||||
#define SR_ERR_INCOMPATIBLE 0x00000002 // (RestoreGame only) incompatible savegame data Savegame file is obsolete. (Won't happen after development stops)
|
||||
#define SR_ERR_READFAIL 0x00000003 // (RestoreGame only) failed on reading savegame file Something screwed up during the fread()
|
||||
#define SR_ERR_WRITEFAIL 0x00000004 // (SaveGame only) failed on writing savegame file Something screwed up during the fwrite() - could be hard-drive full..?
|
||||
|
||||
#endif
|
154
sword2/scroll.cpp
Normal file
154
sword2/scroll.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
#include "interpreter.h"
|
||||
#include "layers.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "scroll.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#define MAX_SCROLL_DISTANCE 8 // max no of pixel allowed to scroll per cycle
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
uint8 scroll_fraction=16; // used to be a define, but now it's flexible (see new functions below)
|
||||
//------------------------------------------------------------------------------------
|
||||
void Set_scrolling(void) //S2.1(2Mar94jel) refurnished Tony25Sept96 :-)
|
||||
{
|
||||
// feet_x = 128+320 // normally we aim to get George's feet at (320,250) from top left of screen window
|
||||
// feet_y = 128+250
|
||||
|
||||
// set scroll offsets according to the player's coords
|
||||
|
||||
int16 offset_x;
|
||||
int16 offset_y;
|
||||
int16 dx, dy;
|
||||
uint16 scroll_distance_x; // how much we want to scroll
|
||||
uint16 scroll_distance_y;
|
||||
|
||||
|
||||
if (SCROLL_X || SCROLL_Y) // if the scroll offsets are being forced in script (05feb97 JAMES)
|
||||
{
|
||||
// ensure not too far right
|
||||
if (SCROLL_X < this_screen.max_scroll_offset_x)
|
||||
this_screen.scroll_offset_x = SCROLL_X;
|
||||
else
|
||||
this_screen.scroll_offset_x = this_screen.max_scroll_offset_x;
|
||||
|
||||
// ensure not too far down
|
||||
if (SCROLL_Y < this_screen.max_scroll_offset_y)
|
||||
this_screen.scroll_offset_y = SCROLL_Y;
|
||||
else
|
||||
this_screen.scroll_offset_y = this_screen.max_scroll_offset_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset_x = this_screen.player_feet_x-this_screen.feet_x; // George's offset from the centre - the desired position for him
|
||||
offset_y = this_screen.player_feet_y-this_screen.feet_y;
|
||||
|
||||
|
||||
// prevent scrolling too far left/right/up/down
|
||||
offset_x = offset_x < 0 ? 0 : ( (uint32)offset_x > this_screen.max_scroll_offset_x ? this_screen.max_scroll_offset_x : offset_x );
|
||||
offset_y = offset_y < 0 ? 0 : ( (uint32)offset_y > this_screen.max_scroll_offset_y ? this_screen.max_scroll_offset_y : offset_y );
|
||||
|
||||
if (this_screen.scroll_flag==2) // first time on this screen - need absolute scroll immediately!
|
||||
{
|
||||
//Zdebug(42,"init scroll");
|
||||
this_screen.scroll_offset_x = offset_x;
|
||||
this_screen.scroll_offset_y = offset_y;
|
||||
this_screen.scroll_flag=1;
|
||||
}
|
||||
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 = this_screen.scroll_offset_x - offset_x;
|
||||
dy = this_screen.scroll_offset_y - offset_y;
|
||||
|
||||
if (dx < 0) // current scroll_offset_x is less than the required value
|
||||
{
|
||||
scroll_distance_x = (1+(-dx)/scroll_fraction); // => inc by (fraction of the differnce) NB. dx is -ve, so we subtract dx/SCROLL_FRACTION
|
||||
this_screen.scroll_offset_x += scroll_distance_x < MAX_SCROLL_DISTANCE ? scroll_distance_x : MAX_SCROLL_DISTANCE;
|
||||
}
|
||||
else if (dx > 0) // current scroll_offset_x is greater than the required value
|
||||
{
|
||||
scroll_distance_x = (1+dx/scroll_fraction); // => dec by (fraction of the differnce)
|
||||
this_screen.scroll_offset_x -= scroll_distance_x < MAX_SCROLL_DISTANCE ? scroll_distance_x : MAX_SCROLL_DISTANCE;
|
||||
} // NB. I'm adding 1 to the result of dx/SCROLL_FRACTION, because it would otherwise
|
||||
// not scroll at all when dx < SCROLL_FRACTION
|
||||
if (dy < 0)
|
||||
{
|
||||
scroll_distance_y = (1+(-dy)/scroll_fraction);
|
||||
this_screen.scroll_offset_y += scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE;
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
scroll_distance_y = (1+dy/scroll_fraction);
|
||||
this_screen.scroll_offset_y -= scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_scroll_coordinate(int32 *params) //Tony25Sept96
|
||||
{
|
||||
// set the special scroll offset variables
|
||||
// call when starting screens and to change the camera within screens
|
||||
// call AFTER FN_init_background() to override the defaults
|
||||
// called feet_x and feet_y to retain intelectual compatibility with Sword1 !
|
||||
// feet_x & feet_y refer to the physical screen coords where the system will try to maintain George's feet
|
||||
|
||||
// param 0 feet_x value
|
||||
// param 1 feet_y value
|
||||
|
||||
|
||||
this_screen.feet_x = params[0];
|
||||
this_screen.feet_y = params[1];
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_scroll_speed_normal(int32 *params) // James08aug97
|
||||
{
|
||||
scroll_fraction=16;
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_scroll_speed_slow(int32 *params) // James08aug97
|
||||
{
|
||||
scroll_fraction=32;
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
|
29
sword2/scroll.h
Normal file
29
sword2/scroll.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//the usual suspects
|
||||
|
||||
#ifndef _SCROLL
|
||||
#define _SCROLL
|
||||
|
||||
//#include "src\driver96.h"
|
||||
|
||||
void Set_scrolling(void);
|
||||
|
||||
#endif
|
504
sword2/sound.cpp
Normal file
504
sword2/sound.cpp
Normal file
|
@ -0,0 +1,504 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// BROKEN SWORD 2
|
||||
//
|
||||
// SOUND.CPP Contains the sound engine, fx & music functions
|
||||
// Some very 'sound' code in here ;)
|
||||
//
|
||||
// (16Dec96 JEL)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "console.h"
|
||||
#include "defs.h" // for RESULT
|
||||
#include "interpreter.h"
|
||||
#include "protocol.h" // for FetchObjectName() for debugging FN_play_fx
|
||||
#include "resman.h"
|
||||
#include "sound.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
uint32 resource; // resource id of sample
|
||||
uint32 fetchId; // Id of resource in PSX CD queue. :)
|
||||
uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM)
|
||||
uint8 volume; // 0..16
|
||||
int8 pan; // -16..16
|
||||
uint8 type; // FX_SPOT, FX_RANDOM or FX_LOOP
|
||||
} _fxq_entry;
|
||||
|
||||
#define FXQ_LENGTH 32 // max number of fx in queue at once [DO NOT EXCEED 255]
|
||||
|
||||
_fxq_entry fxq[FXQ_LENGTH];
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
uint32 looping_music_id=0; // used to store id of tunes that loop, for save & restore
|
||||
char musicDirectory[120];
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
|
||||
void Trigger_fx (uint8 j);
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// initialise the fxq by clearing all the entries
|
||||
|
||||
void Init_fx_queue(void)
|
||||
{
|
||||
uint8 j;
|
||||
|
||||
|
||||
for (j=0; j < FXQ_LENGTH; j++) // scan the queue
|
||||
{
|
||||
fxq[j].resource = 0; // 0 resource means 'empty' slot
|
||||
fxq[j].fetchId = 0; // Not being fetched.
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// process the fxq once every game cycle
|
||||
|
||||
void Process_fx_queue(void)
|
||||
{
|
||||
uint8 j; // assuming FXQ_LENGTH is 255 or less
|
||||
|
||||
|
||||
for (j=0; j < FXQ_LENGTH; j++) // scan the queue
|
||||
{
|
||||
if (fxq[j].resource) // if this entry isn't empty
|
||||
{
|
||||
if (fxq[j].type == FX_RANDOM) // if it's type FX_RANDOM
|
||||
{
|
||||
if (rand()%(fxq[j].delay)==0) // 1 in 'delay' chance of this fx occurring
|
||||
{
|
||||
Trigger_fx(j); // play it
|
||||
}
|
||||
|
||||
}
|
||||
else if(fxq[j].type == FX_SPOT)
|
||||
{
|
||||
if (fxq[j].delay) // if delay is above 0
|
||||
fxq[j].delay--; // decrement delay countdown
|
||||
else // if zero delay remaining
|
||||
{
|
||||
Trigger_fx(j); // play it
|
||||
fxq[j].type = FX_SPOT2;
|
||||
}
|
||||
}
|
||||
else if (fxq[j].type == FX_SPOT2)
|
||||
{
|
||||
if (IsFxOpen(j+1))
|
||||
fxq[j].resource = 0; // Once the Fx has finished remove it from the queue.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Trigger_fx(uint8 j) // called from Process_fx_queue only
|
||||
{
|
||||
uint8 *data;
|
||||
int32 id;
|
||||
uint32 rv;
|
||||
|
||||
id = (uint32)j+1; // because 0 is not a valid id
|
||||
|
||||
if (fxq[j].type == FX_SPOT)
|
||||
{
|
||||
data = res_man.Res_open(fxq[j].resource); // load in the sample
|
||||
data += sizeof(_standardHeader);
|
||||
rv = PlayFx( id, data, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT ); // wav data gets copied to sound memory
|
||||
res_man.Res_close(fxq[j].resource); // release the sample
|
||||
// fxq[j].resource = 0; // clear spot fx from queue
|
||||
}
|
||||
else // random & looped fx are already loaded into sound memory by FN_play_fx()
|
||||
{ // - to be referenced by 'j', so pass NULL data
|
||||
|
||||
if (fxq[j].type == FX_RANDOM)
|
||||
rv = PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT ); // not looped
|
||||
else // FX_LOOP
|
||||
rv = PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXLOOP ); // looped
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_play_fx(int32 *params) // called from script only
|
||||
{
|
||||
// params: 0 sample resource id
|
||||
// 1 type (FX_SPOT, FX_RANDOM, FX_LOOP)
|
||||
// 2 delay (0..65535)
|
||||
// 3 volume (0..16)
|
||||
// 4 pan (-16..16)
|
||||
|
||||
// example script: FN_play_fx (FXWATER, FX_LOOP, 0, 10, 15);
|
||||
// fx_water = result; // fx_water is just a local script flag
|
||||
// .
|
||||
// .
|
||||
// .
|
||||
// FN_stop_fx (fx_water);
|
||||
|
||||
uint8 j=0;
|
||||
uint8 *data;
|
||||
uint32 id;
|
||||
uint32 rv;
|
||||
|
||||
//----------------------------------
|
||||
#ifdef _DEBUG
|
||||
|
||||
_standardHeader *header;
|
||||
char type[10];
|
||||
|
||||
|
||||
if (wantSfxDebug)
|
||||
{
|
||||
switch (params[1]) // 'type'
|
||||
{
|
||||
case FX_SPOT:
|
||||
strcpy(type,"SPOT");
|
||||
break;
|
||||
|
||||
case FX_LOOP:
|
||||
strcpy(type,"LOOPED");
|
||||
break;
|
||||
|
||||
case FX_RANDOM:
|
||||
strcpy(type,"RANDOM");
|
||||
break;
|
||||
|
||||
default:
|
||||
strcpy(type,"INVALID");
|
||||
}
|
||||
|
||||
Zdebug("SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", FetchObjectName(params[0]), params[3], params[4], params[2], type);
|
||||
}
|
||||
|
||||
#endif _DEBUG
|
||||
//----------------------------------
|
||||
|
||||
while ((j < FXQ_LENGTH) && (fxq[j].resource != 0))
|
||||
j++;
|
||||
|
||||
if (j==FXQ_LENGTH)
|
||||
{
|
||||
return (IR_CONT);
|
||||
// Con_fatal_error("ERROR: Sound queue overflow in FN_play_fx() (%s line %u)",__FILE__,__LINE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
fxq[j].resource = params[0]; // wav resource id
|
||||
fxq[j].type = params[1]; // FX_SPOT, FX_LOOP or FX_RANDOM
|
||||
|
||||
if (fxq[j].type == FX_RANDOM) // FX_RANDOM:
|
||||
fxq[j].delay = params[2] * 12 + 1; // 'delay' param is the intended average no. seconds between playing this effect (+1 to avoid divide-by-zero in Process_fx_queue)
|
||||
else // FX_SPOT or FX_LOOP:
|
||||
fxq[j].delay = params[2]; // 'delay' is no. frames to wait before playing
|
||||
|
||||
fxq[j].volume = params[3]; // 0..16
|
||||
fxq[j].pan = params[4]; // -16..16
|
||||
|
||||
|
||||
if (fxq[j].type == FX_SPOT) // spot fx
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
data = res_man.Res_open(fxq[j].resource); // "pre-load" the sample; this gets it into memory
|
||||
header = (_standardHeader*)data;
|
||||
if (header->fileType != WAV_FILE)
|
||||
Con_fatal_error("FN_play_fx given invalid resource (%s line %u)",__FILE__,__LINE__);
|
||||
#else
|
||||
res_man.Res_open(fxq[j].resource); // "pre-load" the sample; this gets it into memory
|
||||
#endif
|
||||
res_man.Res_close(fxq[j].resource); // but then releases it to "age" out if the space is needed
|
||||
}
|
||||
else // random & looped fx
|
||||
{
|
||||
id = (uint32)j+1; // because 0 is not a valid id
|
||||
|
||||
data = res_man.Res_open(fxq[j].resource); // load in the sample
|
||||
|
||||
#ifdef _DEBUG
|
||||
header = (_standardHeader*)data;
|
||||
if (header->fileType != WAV_FILE)
|
||||
Con_fatal_error("FN_play_fx given invalid resource (%s line %u)",__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
data += sizeof(_standardHeader);
|
||||
rv = OpenFx(id,data); // copy it to sound memory, using position in queue as 'id'
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("SFX ERROR: OpenFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
|
||||
#endif
|
||||
|
||||
res_man.Res_close(fxq[j].resource); // release the sample
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------
|
||||
// (James07uag97)
|
||||
if (fxq[j].type == FX_LOOP) // looped fx
|
||||
Trigger_fx(j); // play now, rather than in Process_fx_queue where it was getting played again & again!
|
||||
//---------------------------------------------
|
||||
|
||||
|
||||
RESULT = j; // in case we want to call FN_stop_fx() later, to kill this fx (mainly for FX_LOOP & FX_RANDOM)
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_sound_fetch(int32 *params)
|
||||
{
|
||||
return (IR_CONT);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// to alter the volume and pan of a currently playing fx
|
||||
int32 FN_set_fx_vol_and_pan(int32 *params)
|
||||
{
|
||||
// params 0 id of fx (ie. the id returned in 'result' from FN_play_fx
|
||||
// 1 new volume (0..16)
|
||||
// 2 new pan (-16..16)
|
||||
|
||||
// SetFxVolumePan(int32 id, uint8 vol, uint8 pan);
|
||||
SetFxVolumePan(1+params[0], params[1], params[2]); // driver fx_id is 1+<pos in queue>
|
||||
// Zdebug("%d",params[2]);
|
||||
|
||||
return (IR_CONT);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// to alter the volume of a currently playing fx
|
||||
int32 FN_set_fx_vol(int32 *params)
|
||||
{
|
||||
// params 0 id of fx (ie. the id returned in 'result' from FN_play_fx
|
||||
// 1 new volume (0..16)
|
||||
|
||||
// SetFxIdVolume(int32 id, uint8 vol);
|
||||
SetFxIdVolume(1+params[0], params[1]);
|
||||
|
||||
return (IR_CONT);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_stop_fx(int32 *params) // called from script only
|
||||
{
|
||||
// params: 0 position in queue
|
||||
|
||||
// This will stop looped & random fx instantly, and remove the fx from the queue.
|
||||
// So although it doesn't stop spot fx, it will remove them from the queue if they haven't yet played
|
||||
|
||||
uint8 j = (uint8) params[0];
|
||||
uint32 id;
|
||||
uint32 rv;
|
||||
|
||||
if ((fxq[j].type == FX_RANDOM) || (fxq[j].type == FX_LOOP))
|
||||
{
|
||||
id = (uint32)j+1; // because 0 is not a valid id
|
||||
rv = CloseFx(id); // stop fx & remove sample from sound memory
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("SFX ERROR: CloseFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
fxq[j].resource = 0; // remove from queue
|
||||
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_stop_all_fx(int32 *params) // called from script only
|
||||
{
|
||||
// Stops all looped & random fx and clears the entire queue
|
||||
// NO PARAMS
|
||||
|
||||
Clear_fx_queue();
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Stops all looped & random fx and clears the entire queue
|
||||
|
||||
void Clear_fx_queue(void)
|
||||
{
|
||||
ClearAllFx(); // stop all fx & remove the samples from sound memory
|
||||
Init_fx_queue(); // clean out the queue
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
//=============================================================================
|
||||
// int32 StreamMusic(uint8 *filename, int32 loopFlag)
|
||||
//
|
||||
// Streams music from the file defined by filename. The loopFlag should
|
||||
// be set to RDSE_FXLOOP if the music is to loop back to the start.
|
||||
// Otherwise, it should be RDSE_FXSPOT.
|
||||
// The return value must be checked for any problems.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// int32 PauseMusic(void)
|
||||
//
|
||||
// Stops the music dead in it's tracks.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// int32 UnpauseMusic(void)
|
||||
//
|
||||
// Re-starts the music from where it was stopped.
|
||||
//
|
||||
//=============================================================================
|
||||
int32 FN_prepare_music(int32 *params)
|
||||
{
|
||||
return (IR_CONT);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Start a tune playing, to play once or to loop until stopped or next one played
|
||||
int32 FN_play_music(int32 *params) // updated by James on 10apr97
|
||||
{
|
||||
// params 0 tune id
|
||||
// 1 loop flag (0 or 1)
|
||||
|
||||
char filename[128];
|
||||
uint32 loopFlag;
|
||||
uint32 rv; // drivers return value
|
||||
|
||||
|
||||
// Zdebug("FN_play_music(%d)", params[0]);
|
||||
|
||||
if (params[1]==FX_LOOP) // if it is to loop
|
||||
{
|
||||
loopFlag = RDSE_FXLOOP;
|
||||
looping_music_id = params[0]; // keep a note of the id, for restarting after an interruption to gameplay
|
||||
}
|
||||
else // just play once
|
||||
{
|
||||
loopFlag = RDSE_FXSPOT;
|
||||
looping_music_id = 0; // don't need to restart this tune after control panel or restore
|
||||
}
|
||||
|
||||
|
||||
// add the appropriate file extension & play it
|
||||
|
||||
#ifdef _WEBDEMO // (James 01oct97)
|
||||
sprintf(filename,"MUSIC.CLU");
|
||||
#else
|
||||
sprintf(filename,"%sCLUSTERS\\MUSIC.CLU", res_man.GetCdPath());
|
||||
#endif // _WEBDEMO
|
||||
|
||||
rv = StreamCompMusic(filename, params[0], loopFlag);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (rv)
|
||||
Zdebug("ERROR: StreamCompMusic(%s, %d, %d) returned error 0x%.8x", filename, params[0], loopFlag, rv);
|
||||
#endif
|
||||
|
||||
// Zdebug("FN_play_music(%d) returning", params[0]);
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_stop_music(int32 *params) // called from script only
|
||||
{
|
||||
// params: none
|
||||
|
||||
|
||||
looping_music_id=0; // clear the 'looping' flag
|
||||
|
||||
StopMusic();
|
||||
|
||||
if (params);
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
extern void UpdateCompSampleStreaming(void); // used in Kill_music()
|
||||
//--------------------------------------------------------------------------------------
|
||||
void Kill_music(void) // James22aug97
|
||||
{
|
||||
uint8 count;
|
||||
|
||||
looping_music_id=0; // clear the 'looping' flag
|
||||
StopMusic();
|
||||
|
||||
// THIS BIT CAUSES THE MUSIC TO STOP INSTANTLY!
|
||||
for(count=0; count<16; count++)
|
||||
UpdateCompSampleStreaming();
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_check_music_playing(int32 *params) // James (30july97)
|
||||
{
|
||||
|
||||
// params: none
|
||||
// sets result to no. of seconds of current tune remaining
|
||||
// or 0 if no music playing
|
||||
|
||||
RESULT = MusicTimeRemaining(); // in seconds, rounded up to the nearest second
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void PauseAllSound(void) // James25july97
|
||||
{
|
||||
uint32 rv; // for drivers return value
|
||||
|
||||
rv = PauseMusic();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: PauseMusic() returned %.8x in PauseAllSound()", rv);
|
||||
|
||||
rv = PauseSpeech();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: PauseSpeech() returned %.8x in PauseAllSound()", rv);
|
||||
|
||||
rv = PauseFx();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: PauseFx() returned %.8x in PauseAllSound()", rv);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
void UnpauseAllSound(void) // James25july97
|
||||
{
|
||||
uint32 rv; // for drivers return value
|
||||
|
||||
rv = UnpauseMusic();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: UnpauseMusic() returned %.8x in UnpauseAllSound()", rv);
|
||||
|
||||
rv = UnpauseSpeech();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: UnpauseSpeech() returned %.8x in UnpauseAllSound()", rv);
|
||||
|
||||
rv = UnpauseFx();
|
||||
if (rv != RD_OK)
|
||||
Zdebug("ERROR: UnpauseFx() returned %.8x in UnpauseAllSound()", rv);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
55
sword2/sound.h
Normal file
55
sword2/sound.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* SOUND.H Sound engine
|
||||
*
|
||||
* SOUND.CPP Contains the sound engine, fx & music functions
|
||||
* Some very 'sound' code in here ;)
|
||||
*
|
||||
* (16Dec96 JEL)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
#include "scummsys.h"
|
||||
|
||||
// fx types
|
||||
#define FX_SPOT 0
|
||||
#define FX_LOOP 1
|
||||
#define FX_RANDOM 2
|
||||
#define FX_SPOT2 3
|
||||
|
||||
void Init_fx_queue(void); // to be called during system initialisation
|
||||
void Process_fx_queue(void); // to be called from the main loop, once per cycle
|
||||
void Clear_fx_queue(void); // stops all fx & clears the queue - eg. when leaving a location
|
||||
void PauseAllSound(void); // James25july97
|
||||
void UnpauseAllSound(void); // James25july97
|
||||
|
||||
void Kill_music(void); // James22aug97
|
||||
|
||||
|
||||
int32 FN_play_music(int32 *params); // for save_Rest.cpp
|
||||
int32 FN_stop_music(int32 *params);
|
||||
|
||||
extern uint32 looping_music_id; // used to store id of tunes that loop, for save & restore
|
||||
|
||||
#endif
|
1994
sword2/speech.cpp
Normal file
1994
sword2/speech.cpp
Normal file
File diff suppressed because it is too large
Load diff
44
sword2/speech.h
Normal file
44
sword2/speech.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _SPEECH
|
||||
#define _SPEECH
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "header.h"
|
||||
|
||||
|
||||
#define MAX_SUBJECT_LIST 30 //is that enough?
|
||||
|
||||
|
||||
|
||||
typedef struct //array of these for subject menu build up
|
||||
{
|
||||
uint32 res;
|
||||
uint32 ref;
|
||||
} _subject_unit;
|
||||
|
||||
extern uint32 speech_text_bloc_no; // so speech text cleared when running a new start-script
|
||||
extern int16 officialTextNumber;
|
||||
|
||||
extern int32 speechScriptWaiting;
|
||||
|
||||
extern int choosing; //could alternately use logic->looping of course
|
||||
extern uint32 unpause_zone;
|
||||
#endif
|
339
sword2/startup.cpp
Normal file
339
sword2/startup.cpp
Normal file
|
@ -0,0 +1,339 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "build_display.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "header.h"
|
||||
#include "interpreter.h"
|
||||
#include "maketext.h" // for Kill_text_bloc()
|
||||
#include "memory.h"
|
||||
#include "mouse.h" // for FN_add_human()
|
||||
#include "object.h"
|
||||
#include "resman.h"
|
||||
#include "router.h"
|
||||
#include "sound.h"
|
||||
#include "speech.h" // for 'speech_text_bloc_no' - so that speech text can be cleared when running a new start-script
|
||||
#include "startup.h"
|
||||
#include "sword2.h" // (James11aug97) for CloseGame()
|
||||
#include "sync.h"
|
||||
#include "tony_gsdk.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 total_startups=0;
|
||||
uint32 total_screen_managers=0;
|
||||
uint32 res;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
_startup start_list[MAX_starts];
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 Init_start_menu(void) //Tony13Aug96
|
||||
{
|
||||
//print out a list of all the start points available
|
||||
//there should be a linc produced file called startup.txt
|
||||
//this file should contain ascii numbers of all the resource game objects that are screen managers
|
||||
//we query each in turn and setup an array of start structures
|
||||
//if the file doesn't exist then we say so and return a 0
|
||||
|
||||
|
||||
uint32 end;
|
||||
mem *temp;
|
||||
uint32 pos=0;
|
||||
uint32 j=0;
|
||||
char *raw_script;
|
||||
uint32 null_pc;
|
||||
|
||||
|
||||
char ascii_start_ids[MAX_starts][7];
|
||||
|
||||
|
||||
//ok, load in the master screen manager file
|
||||
|
||||
|
||||
|
||||
|
||||
total_startups=0; //no starts
|
||||
|
||||
|
||||
|
||||
Zdebug("initialising start menu");
|
||||
|
||||
|
||||
if (!(end=Read_file("STARTUP.INF", &temp, UID_temp)))
|
||||
{
|
||||
Zdebug("Init_start_menu cannot open startup.inf");
|
||||
return(0); //meaning no start menu available
|
||||
}
|
||||
|
||||
|
||||
|
||||
//ok, we've loaded in the resource.inf file which contains a list of all the files
|
||||
//now extract the filenames
|
||||
do
|
||||
{
|
||||
while(((char)*(temp->ad+j))!=13) //item must have an #0d0a
|
||||
{
|
||||
ascii_start_ids[total_screen_managers][pos]=*(temp->ad+j);
|
||||
j++;
|
||||
pos++;
|
||||
|
||||
};
|
||||
|
||||
ascii_start_ids[total_screen_managers][pos]=0; //NULL terminate our extracted string
|
||||
|
||||
pos=0; //reset position in current slot between entries
|
||||
j+=2; //past the 0a
|
||||
total_screen_managers++; //done another
|
||||
|
||||
if (total_screen_managers==MAX_starts)
|
||||
{ Zdebug("WARNING MAX_starts exceeded!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(j<end); //using this method the Gode generated resource.inf must have #0d0a on the last entry
|
||||
|
||||
|
||||
|
||||
Zdebug("%d screen manager objects", total_screen_managers);
|
||||
|
||||
//open each object and make a query call. the object must fill in a startup structure
|
||||
//it may fill in several if it wishes - for instance a startup could be set for later in the game where specific vars are set
|
||||
for (j=0;j<total_screen_managers;j++)
|
||||
{
|
||||
res=atoi(ascii_start_ids[j]);
|
||||
|
||||
Zdebug("+querying screen manager %d", res);
|
||||
|
||||
|
||||
// resopen each one and run through the interpretter
|
||||
// script 0 is the query request script
|
||||
|
||||
|
||||
if (res_man.Res_check_valid(res)) // if the resource number is within range & it's not a null resource (James 12mar97)
|
||||
{ // - need to check in case un-built sections included in start list
|
||||
Zdebug("- resource %d ok",res);
|
||||
raw_script= (char*) (res_man.Res_open(res)); //+sizeof(_standardHeader)+sizeof(_object_hub));
|
||||
null_pc=0; //
|
||||
RunScript ( raw_script, raw_script, &null_pc );
|
||||
res_man.Res_close(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
Zdebug("- resource %d invalid",res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Zdebug(""); //line feed
|
||||
|
||||
|
||||
Free_mem(temp); //release the Talloc
|
||||
|
||||
return(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_register_start_point(int32 *params) //Tony14Oct96
|
||||
{
|
||||
// param 0 id of startup script to call - key
|
||||
// param 1 pointer to ascii message
|
||||
|
||||
|
||||
// Zdebug(" FN_register_start_point %d %s", params[0], params[1]);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (total_startups==MAX_starts)
|
||||
Con_fatal_error("ERROR: start_list full [%s line %u]",__FILE__,__LINE__);
|
||||
|
||||
if (strlen((char*)params[1])+1 > MAX_description) // +1 to allow for NULL terminator
|
||||
Con_fatal_error("ERROR: startup description too long [%s line %u]",__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
start_list[total_startups].start_res_id = res; // this objects id
|
||||
start_list[total_startups].key = params[0]; // a key code to be passed to a script via a script var to SWITCH in the correct start
|
||||
strcpy(start_list[total_startups].description, (char*)params[1]);
|
||||
|
||||
total_startups++; //point to next
|
||||
|
||||
return(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 Con_print_start_menu(void) //Tony14Oct96
|
||||
{
|
||||
//the console 'starts' (or 's') command which lists out all the registered start points in the game
|
||||
uint32 j;
|
||||
int scrolls=0;
|
||||
char c;
|
||||
|
||||
|
||||
if (!total_startups)
|
||||
{ Print_to_console("Sorry - no startup positions registered?");
|
||||
|
||||
if (!total_screen_managers)
|
||||
Print_to_console("There is a problem with startup.inf");
|
||||
else
|
||||
Print_to_console(" (%d screen managers found in startup.inf)", total_screen_managers);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for(j=0;j<total_startups;j++)
|
||||
{
|
||||
Print_to_console("%d (%s)", j, start_list[j].description);
|
||||
Build_display();
|
||||
scrolls++;
|
||||
|
||||
|
||||
if (scrolls==18)
|
||||
{
|
||||
Temp_print_to_console("- Press ESC to stop or any other key to continue");
|
||||
Build_display();
|
||||
|
||||
do
|
||||
{
|
||||
//--------------------------------------------------
|
||||
// Service windows
|
||||
while (!gotTheFocus)
|
||||
if (ServiceWindows() == RDERR_APPCLOSED)
|
||||
break;
|
||||
|
||||
if (ServiceWindows() == RDERR_APPCLOSED) // if we pressed Ctrl-Q
|
||||
{
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
exit(0); //quit the game
|
||||
}
|
||||
//--------------------------------------------------
|
||||
}
|
||||
while(!KeyWaiting());
|
||||
|
||||
ReadKey(&c); //kill the key we just pressed
|
||||
if (c==27) //ESC
|
||||
break;
|
||||
|
||||
Clear_console_line(); //clear the Press Esc message ready for the new line
|
||||
scrolls=0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 Con_start(uint8 *input) //Tony15Oct96
|
||||
{
|
||||
//if the second word id is a numeric that can be applied to a genuine startup then do it
|
||||
uint32 j=0;
|
||||
uint32 start;
|
||||
char *raw_script;
|
||||
char *raw_data_ad;
|
||||
uint32 null_pc;
|
||||
|
||||
|
||||
|
||||
if (*input == NULL) // so that typing 'S' then <enter> works on NT (James26feb97)
|
||||
{
|
||||
Con_print_start_menu();
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
while(*(input+j))
|
||||
{
|
||||
if ( (*(input+j)>='0') && (*(input+j)<='9') )
|
||||
j++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!*(input+j)) //didn't quit out of loop on a non numeric chr$
|
||||
{
|
||||
start = atoi((char*)input);
|
||||
|
||||
if (!total_startups)
|
||||
Print_to_console("Sorry - there are no startups!");
|
||||
|
||||
else if (start<total_startups) //a legal start
|
||||
{
|
||||
// do the startup as we've specified a legal start
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// restarting - stop sfx, music & speech!
|
||||
|
||||
Clear_fx_queue();
|
||||
//---------------------------------------------
|
||||
FN_stop_music(NULL); // fade out any music that is currently playing
|
||||
//---------------------------------------------
|
||||
|
||||
UnpauseSpeech();
|
||||
StopSpeech(); // halt the sample prematurely
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// clean out all resources & flags, ready for a total restart (James24mar97)
|
||||
|
||||
res_man.Remove_all_res(); // remove all resources from memory, including player object & global variables
|
||||
SetGlobalInterpreterVariables((int32*)(res_man.Res_open(1)+sizeof(_standardHeader))); // reopen global variables resource & send address to interpreter - it won't be moving
|
||||
res_man.Res_close(1);
|
||||
|
||||
FreeAllRouteMem(); // free all the route memory blocks from previous game
|
||||
|
||||
if (speech_text_bloc_no) // if there was speech text
|
||||
{
|
||||
Kill_text_bloc(speech_text_bloc_no); // kill the text block
|
||||
speech_text_bloc_no=0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// set the key
|
||||
raw_data_ad= (char*) (res_man.Res_open(8)); //+sizeof(_standardHeader)+sizeof(_object_hub)); //open george
|
||||
raw_script= (char*) (res_man.Res_open(start_list[start].start_res_id)); //+sizeof(_standardHeader)+sizeof(_object_hub));
|
||||
null_pc=start_list[start].key&0xffff; //denotes script to run
|
||||
Print_to_console("running start %d", start);
|
||||
RunScript ( raw_script, raw_data_ad, &null_pc );
|
||||
|
||||
res_man.Res_close(start_list[start].start_res_id);
|
||||
res_man.Res_close(8); //close george
|
||||
|
||||
FN_add_human(NULL); // make sure thre's a mouse, in case restarting while mouse not available
|
||||
}
|
||||
else
|
||||
Print_to_console("not a legal start position");
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_print_start_menu(); // so that typing 'S' then <enter> works under Win95
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
|
45
sword2/startup.h
Normal file
45
sword2/startup.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _STARTUP
|
||||
#define _STARTUP
|
||||
|
||||
//#include "src\driver96.h"
|
||||
|
||||
|
||||
#define MAX_starts 100
|
||||
#define MAX_description 100
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char description[MAX_description];
|
||||
uint32 start_res_id; //id of screen manager object
|
||||
uint32 key; //tell the manager which startup you want (if there are more than 1) (i.e more than 1 entrance to a screen and/or seperate game boots)
|
||||
|
||||
} _startup;
|
||||
|
||||
|
||||
extern _startup start_list[MAX_starts];
|
||||
|
||||
uint32 Init_start_menu(void); //Tony13Aug96
|
||||
uint32 Con_print_start_menu(void); //Tony13Aug96
|
||||
uint32 Con_start(uint8 *input); //Tony15Oct96
|
||||
|
||||
#endif
|
572
sword2/sword2.cpp
Normal file
572
sword2/sword2.cpp
Normal file
|
@ -0,0 +1,572 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
//#include <windows.h>
|
||||
|
||||
#include "driver/driver96.h"
|
||||
#include "common/gameDetector.h"
|
||||
#include "build_display.h"
|
||||
#include "console.h"
|
||||
#include "controls.h"
|
||||
#include "debug.h"
|
||||
#include "events.h"
|
||||
#include "header.h"
|
||||
#include "interpreter.h"
|
||||
#include "layers.h"
|
||||
#include "logic.h"
|
||||
#include "maketext.h"
|
||||
#include "memory.h"
|
||||
#include "mouse.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "scroll.h"
|
||||
#include "sound.h"
|
||||
#include "speech.h"
|
||||
#include "startup.h"
|
||||
#include "sword2.h"
|
||||
#include "sync.h"
|
||||
|
||||
#define MAX_PATH 260
|
||||
|
||||
void Start_game(void);
|
||||
|
||||
int RunningFromCd();
|
||||
|
||||
uint8 quitGame = 0;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// version & owner details
|
||||
|
||||
//So version string is 18 bytes long :
|
||||
//Version String = <8 byte header,5 character version, \0, INT32 time>
|
||||
|
||||
uint8 version_string[HEAD_LEN+10] = {1, 255, 37, 22, 45, 128, 34, 67};
|
||||
|
||||
uint8 unencoded_name[HEAD_LEN+48] = {76, 185, 205, 23, 44, 34, 24, 34,
|
||||
'R','e','v','o','l','u','t','i','o','n',' ',
|
||||
'S','o','f','t','w','a','r','e',' ','L','t','d',
|
||||
0};
|
||||
|
||||
uint8 encoded_name[HEAD_LEN+48] = {44, 32, 190, 222, 123, 65, 233, 99,
|
||||
179, 209, 225, 157, 222, 238, 219, 209, 143, 224, 133, 190,
|
||||
232, 209, 162, 177, 198, 228, 202, 146, 180, 232, 214, 65,
|
||||
65, 65, 116, 104, 116, 114, 107, 104, 32, 49, 64, 35, 123,
|
||||
125, 61, 45, 41, 40, 163, 36, 49, 123, 125, 10};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
uint8 gamePaused=0; // James17jun97
|
||||
//uint32 pause_text_bloc_no=0; // James17jun97
|
||||
uint8 graphics_level_fudged=0; // James10july97
|
||||
uint8 stepOneCycle=0; // for use while game paused
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
void PauseGame(void); // James17jun97
|
||||
void UnpauseGame(void); // James17jun97
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
static const VersionSettings bs2_settings[] = {
|
||||
/* Broken Sword 2 */
|
||||
{"bs2", "Broken Sword II", GID_BS2_FIRST, 99, VersionSettings::ADLIB_DONT_CARE, GF_DEFAULT_TO_1X_SCALER, "players.clu" },
|
||||
{NULL, NULL, 0, 0, VersionSettings::ADLIB_DONT_CARE, 0, NULL}
|
||||
};
|
||||
|
||||
BS2State *g_bs2 = NULL;
|
||||
|
||||
const VersionSettings *Engine_BS2_targetList() {
|
||||
return bs2_settings;
|
||||
}
|
||||
|
||||
Engine *Engine_BS2_create(GameDetector *detector, OSystem *syst) {
|
||||
return new BS2State(detector, syst);
|
||||
}
|
||||
|
||||
BS2State::BS2State(GameDetector *detector, OSystem *syst)
|
||||
: Engine(detector, syst) {
|
||||
|
||||
_detector = detector;
|
||||
_syst = syst;
|
||||
g_bs2 = this;
|
||||
}
|
||||
|
||||
|
||||
void BS2State::errorString(const char *buf1, char *buf2) {
|
||||
strcpy(buf2, buf1);
|
||||
}
|
||||
|
||||
int32 InitialiseGame(void)
|
||||
{
|
||||
//init engine drivers
|
||||
|
||||
uint8 *file;
|
||||
|
||||
Zdebug("CALLING: Init_memory_manager");
|
||||
Init_memory_manager(); // get some falling RAM and put it in your pocket, never let it slip away
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
Zdebug("CALLING: res_man.InitResMan");
|
||||
res_man.InitResMan(); // initialise the resource manager
|
||||
Zdebug("RETURNED from res_man.InitResMan");
|
||||
|
||||
// initialise global script variables
|
||||
file=res_man.Res_open(1); // res 1 is the globals list
|
||||
Zdebug("CALLING: SetGlobalInterpreterVariables");
|
||||
SetGlobalInterpreterVariables((int32*)(file+sizeof(_standardHeader)));
|
||||
Zdebug("RETURNED.");
|
||||
// res_man.Res_close(1); // DON'T CLOSE VARIABLES RESOURCE - KEEP IT OPEN AT VERY START OF MEMORY SO IT CAN'T MOVE!
|
||||
|
||||
file=res_man.Res_open(8); // DON'T CLOSE PLAYER OBJECT RESOURCE - KEEP IT OPEN IN MEMORY SO IT CAN'T MOVE!
|
||||
|
||||
//----------------------------------------
|
||||
Zdebug("CALLING: InitialiseFontResourceFlags");
|
||||
InitialiseFontResourceFlags(); // Set up font resource variables for this language version (James31july97)
|
||||
// Also set the windows application name to the proper game name
|
||||
Zdebug("RETURNED.");
|
||||
//----------------------------------------
|
||||
|
||||
Zdebug("CALLING: Init_console");
|
||||
Init_console(); // set up the console system
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
#ifdef _DEBUG
|
||||
Zdebug("CALLING: Init_start_menu");
|
||||
Init_start_menu(); // read in all the startup information
|
||||
Zdebug("RETURNED from Init_start_menu");
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
|
||||
Zdebug("CALLING: Init_text_bloc_system");
|
||||
Init_text_bloc_system(); // no blocs live
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
Zdebug("CALLING: Init_sync_system");
|
||||
Init_sync_system();
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
Zdebug("CALLING: Init_event_system");
|
||||
Init_event_system();
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
Zdebug("CALLING: Init_fx_queue");
|
||||
Init_fx_queue(); // initialise the sound fx queue
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
#ifdef _DEMO // demo only
|
||||
DEMO=1; // set script variable
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Close_game() //Tony11Oct96
|
||||
{
|
||||
Zdebug("Close_game() STARTING:");
|
||||
//avoid corruption when windows kicks back in
|
||||
EraseBackBuffer();
|
||||
FlipScreens();
|
||||
EraseBackBuffer();
|
||||
FlipScreens();
|
||||
|
||||
Kill_music(); // Stop music instantly! (James22aug97)
|
||||
Close_memory_manager(); // free the memory again
|
||||
res_man.Close_ResMan();
|
||||
|
||||
Zdebug("Close_game() DONE.");
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 GameCycle(void)
|
||||
{
|
||||
//do one game cycle
|
||||
|
||||
|
||||
{
|
||||
if (LLogic.Return_run_list()) //got a screen to run?
|
||||
{
|
||||
do //run the logic session UNTIL a full loop has been performed
|
||||
{
|
||||
Reset_render_lists(); // reset the graphic 'buildit' list before a new logic list (see FN_register_frame)
|
||||
Reset_mouse_list(); // reset the mouse hot-spot list (see FN_register_mouse & FN_register_frame)
|
||||
}
|
||||
while(LLogic.Process_session()); //keep going as long as new lists keep getting put in - i.e. screen changes
|
||||
}
|
||||
else //start the console and print the start options perhaps?
|
||||
{
|
||||
StartConsole();
|
||||
Print_to_console("AWAITING START COMMAND: (Enter 's 1' then 'q' to start from beginning)");
|
||||
}
|
||||
}
|
||||
|
||||
if (this_screen.scroll_flag) // if this screen is wide
|
||||
Set_scrolling(); // recompute the scroll offsets every game-cycle
|
||||
|
||||
Mouse_engine(); //check the mouse
|
||||
|
||||
Process_fx_queue();
|
||||
|
||||
res_man.Res_next_cycle(); // update age and calculate previous cycle memory usage
|
||||
|
||||
if (quitGame)
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
// int main(int argc, char *argv[])
|
||||
// int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
void BS2State::go()
|
||||
{
|
||||
uint32 rv;
|
||||
uint8 breakOut = 0;
|
||||
char c;
|
||||
int j=100;
|
||||
uint32 pc=0;
|
||||
|
||||
// Zdebug("[%s]", lpCmdLine);
|
||||
|
||||
|
||||
#ifndef _DEBUG
|
||||
DisableQuitKey(); // so cannot use Ctrl-Q from the release versions (full game or demo)
|
||||
#endif
|
||||
|
||||
|
||||
if (RunningFromCd()) //stop this game being run from CD
|
||||
exit(-1);
|
||||
|
||||
|
||||
|
||||
// Call the application "Revolution" until the resource manager is ready to dig the name out of a text file
|
||||
// See InitialiseGame() which calls InitialiseFontResourceFlags() in maketext.cpp
|
||||
// Have to do it like this since we cannot really fire up the resource manager until a window
|
||||
// has been created as any errors are displayed via a window, thus time becomes a loop.
|
||||
|
||||
Zdebug("CALLING: InitialiseWindow");
|
||||
// rv = InitialiseWindow(hInstance, hPrevInstance, lpCmdLine, nCmdShow, "Revolution");
|
||||
rv = RD_OK;
|
||||
Zdebug("RETURNED with rv = %.8x", rv);
|
||||
if (rv != RD_OK)
|
||||
{
|
||||
// ReportDriverError(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
Zdebug("CALLING: InitialiseDisplay");
|
||||
// rv = InitialiseDisplay(640, 480, 8, RD_FULLSCREEN);
|
||||
_syst->init_size(640, 480);
|
||||
rv = RD_OK;
|
||||
|
||||
Zdebug("RETURNED with rv = %.8x", rv);
|
||||
if (rv != RD_OK)
|
||||
{
|
||||
// ReportDriverError(rv);
|
||||
CloseAppWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
Zdebug("CALLING: ReadOptionSettings");
|
||||
ReadOptionSettings(); //restore the menu settings
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
Zdebug("CALLING: InitialiseSound");
|
||||
rv = InitialiseSound(22050, 2, 16);
|
||||
Zdebug("RETURNED with rv = %.8x", rv);
|
||||
// don't care if this fails, because it should still work without sound cards
|
||||
// but it should set a global system flag so that we can avoid loading sound fx & streaming music
|
||||
// because they won't be heard anyway
|
||||
/*
|
||||
if (rv != RD_OK)
|
||||
{
|
||||
ReportDriverError(rv);
|
||||
CloseAppWindow();
|
||||
return(0);
|
||||
}
|
||||
*/
|
||||
|
||||
Zdebug("CALLING: InitialiseGame");
|
||||
if (InitialiseGame())
|
||||
{
|
||||
Zdebug("RETURNED from InitialiseGame - closing game");
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
return;
|
||||
}
|
||||
Zdebug("RETURNED from InitialiseGame - ok");
|
||||
|
||||
|
||||
|
||||
//check for restore game on startup - at the mo any passed argument is good enough to trigger this
|
||||
// if (lpCmdLine[0]) //non zero
|
||||
if (0)
|
||||
{
|
||||
Set_mouse(NORMAL_MOUSE_ID);
|
||||
|
||||
if (!Restore_control()) // restore a game
|
||||
Start_game();
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
// release versions only (full-game and demo)
|
||||
// #if NDEBUG // comment this out for debug versions to start game automatically!
|
||||
else
|
||||
Start_game();
|
||||
// #endif // comment this out for debug versions to start game automatically!
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
||||
Zdebug("CALLING: InitialiseRenderCycle");
|
||||
InitialiseRenderCycle();
|
||||
Zdebug("RETURNED.");
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (ServiceWindows() == RDERR_APPCLOSED)
|
||||
{
|
||||
break; // break out of main game loop
|
||||
}
|
||||
|
||||
|
||||
// check for events
|
||||
parseEvents();
|
||||
#ifdef _DEBUG
|
||||
if (grabbingSequences && (!console_status))
|
||||
GrabScreenShot();
|
||||
#endif
|
||||
|
||||
while (!gotTheFocus)
|
||||
{
|
||||
if (ServiceWindows() == RDERR_APPCLOSED)
|
||||
{
|
||||
breakOut = 1;
|
||||
break; // break out of this while-loop
|
||||
}
|
||||
}
|
||||
|
||||
if (breakOut) // if we are closing down the game
|
||||
break; // break out of main game loop
|
||||
|
||||
//-----
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (console_status)
|
||||
{
|
||||
if (One_console())
|
||||
{
|
||||
EndConsole();
|
||||
UnpauseAllSound(); // see sound.cpp
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!console_status) //not in console mode - if the console is quit we want to get a logic cycle in before
|
||||
{ //the screen is build. Mostly because of first scroll cycle stuff
|
||||
#ifdef _DEBUG
|
||||
if (stepOneCycle) // if we've just stepped forward one cycle while the game was paused
|
||||
{
|
||||
PauseGame();
|
||||
stepOneCycle=0;
|
||||
}
|
||||
#endif
|
||||
if (KeyWaiting())
|
||||
{
|
||||
ReadKey(&c);
|
||||
#ifdef _DEBUG
|
||||
if (c==27) // ESC whether paused or not
|
||||
{
|
||||
PauseAllSound(); // see sound.cpp
|
||||
StartConsole(); // start the console
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gamePaused) // if currently paused
|
||||
{
|
||||
if (toupper(c)=='P') // 'P' while paused = unpause!
|
||||
{
|
||||
UnpauseGame();
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
else if (toupper(c)==' ') // SPACE bar while paused = step one frame!
|
||||
{
|
||||
stepOneCycle=1; // step through one game cycle
|
||||
UnpauseGame();
|
||||
}
|
||||
#endif // _DEBUG
|
||||
}
|
||||
else if (toupper(c)=='P') // 'P' while not paused = pause!
|
||||
{
|
||||
PauseGame();
|
||||
}
|
||||
#ifdef _DEBUG // frame-skipping only allowed on debug version
|
||||
else if (toupper(c)=='S') // 'S' toggles speed up (by skipping display rendering)
|
||||
{
|
||||
renderSkip = 1 - renderSkip;
|
||||
}
|
||||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
if (gamePaused==0) // skip GameCycle if we're paused
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
gameCycle += 1;
|
||||
#endif
|
||||
|
||||
if (GameCycle())
|
||||
break; // break out of main game loop
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
Build_debug_text(); // creates the debug text blocks
|
||||
#endif // _DEBUG
|
||||
}
|
||||
//-----
|
||||
|
||||
// James (24mar97)
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ((console_status)||(renderSkip==0)||(gameCycle%4 == 0)) // if not in console & 'renderSkip' is set, only render display once every 4 game-cycles
|
||||
Build_display(); // create and flip the screen
|
||||
#else
|
||||
Build_display(); // create and flip the screen
|
||||
#endif // _DEBUG
|
||||
|
||||
}
|
||||
|
||||
Close_game(); //close engine systems down
|
||||
RestoreDisplay();
|
||||
CloseAppWindow();
|
||||
|
||||
return; //quit the game
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int RunningFromCd()
|
||||
{
|
||||
char sCDName[MAX_PATH];
|
||||
char sRoot[MAX_PATH];
|
||||
DWORD dwMaxCompLength, dwFSFlags;
|
||||
/*
|
||||
GetModuleFileName(NULL , sRoot, _MAX_PATH);
|
||||
*(strchr(sRoot,'\\')+1) = '\0';
|
||||
|
||||
if (!GetVolumeInformation(sRoot, sCDName,_MAX_PATH, NULL, &dwMaxCompLength, &dwFSFlags, NULL, 0))
|
||||
return -1;
|
||||
if (!scumm_strnicmp(sCDName,CD1_LABEL,6))
|
||||
return 1;
|
||||
if (!scumm_strnicmp(sCDName,CD2_LABEL,6))
|
||||
return 2;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
void Start_game(void) //Tony29May97
|
||||
{
|
||||
//boot the game straight into a start script
|
||||
|
||||
Zdebug("Start_game() STARTING:");
|
||||
|
||||
#ifdef _DEMO
|
||||
#define SCREEN_MANAGER_ID 19 // DOCKS SECTION START
|
||||
#else
|
||||
#define SCREEN_MANAGER_ID 949 // INTRO & PARIS START
|
||||
#endif
|
||||
|
||||
char *raw_script;
|
||||
char *raw_data_ad;
|
||||
uint32 null_pc=1; // the required start-scripts are both script #1 in the respective ScreenManager objects
|
||||
|
||||
raw_data_ad = (char*) (res_man.Res_open(8)); // open george object, ready for start script to reference
|
||||
raw_script = (char*) (res_man.Res_open(SCREEN_MANAGER_ID)); // open the ScreenManager object
|
||||
|
||||
RunScript ( raw_script, raw_data_ad, &null_pc ); // run the start script now (because no console)
|
||||
|
||||
res_man.Res_close(SCREEN_MANAGER_ID); // close the ScreenManager object
|
||||
res_man.Res_close(8); // close george
|
||||
|
||||
Zdebug("Start_game() DONE.");
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
void PauseGame(void) // James17jun97
|
||||
{
|
||||
// uint8 *text;
|
||||
|
||||
// text = FetchTextLine( res_man.Res_open(3258), 449 ); // open text file & get the line "PAUSED"
|
||||
// pause_text_bloc_no = Build_new_block(text+2, 320, 210, 640, 184, RDSPR_TRANS+RDSPR_DISPLAYALIGN, SPEECH_FONT_ID, POSITION_AT_CENTRE_OF_BASE);
|
||||
// res_man.Res_close(3258); // now ok to close the text file
|
||||
|
||||
//---------------------------
|
||||
// don't allow Pause while screen fading or while black (James 03sep97)
|
||||
if(GetFadeStatus()!=RDFADE_NONE)
|
||||
return;
|
||||
//---------------------------
|
||||
|
||||
PauseAllSound();
|
||||
|
||||
//make a normal mouse
|
||||
ClearPointerText();
|
||||
// mouse_mode=MOUSE_normal;
|
||||
SetLuggageAnim(NULL, NULL); //this is the only place allowed to do it this way
|
||||
Set_mouse(NULL); // blank cursor
|
||||
mouse_touching=1; //forces engine to choose a cursor
|
||||
|
||||
if (current_graphics_level==3) // if level at max
|
||||
{
|
||||
UpdateGraphicsLevel(3,2); // turn down because palette-matching won't work when dimmed
|
||||
graphics_level_fudged=1;
|
||||
}
|
||||
|
||||
if (stepOneCycle==0) // don't dim it if we're single-stepping through frames
|
||||
{
|
||||
DimPalette(); // dim the palette during the pause (James26jun97)
|
||||
}
|
||||
|
||||
gamePaused=1;
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void UnpauseGame(void) // James17jun97
|
||||
{
|
||||
// Kill_text_bloc(pause_text_bloc_no); // removed "PAUSED" from screen
|
||||
|
||||
if ((OBJECT_HELD)&&(real_luggage_item))
|
||||
Set_luggage(real_luggage_item);
|
||||
|
||||
UnpauseAllSound();
|
||||
|
||||
SetFullPalette(0xffffffff); // put back game screen palette; see Build_display.cpp (James26jun97)
|
||||
|
||||
if (graphics_level_fudged) // if level at max
|
||||
{
|
||||
UpdateGraphicsLevel(2,3); // turn up again
|
||||
graphics_level_fudged=0;
|
||||
}
|
||||
|
||||
gamePaused=0;
|
||||
unpause_zone=2;
|
||||
|
||||
if ((!mouse_status)||(choosing)) //if mouse is about or we're in a chooser menu
|
||||
Set_mouse(NORMAL_MOUSE_ID);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
|
62
sword2/sword2.h
Normal file
62
sword2/sword2.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _SWORD2
|
||||
#define _SWORD2
|
||||
|
||||
//#include "src\driver96.h"
|
||||
|
||||
|
||||
#ifdef _PCF76 // Bodge for PCF76 version so that their demo CD can be labelled "PCF76" rather than "RBSII1"
|
||||
#define CD1_LABEL "PCF76"
|
||||
#else
|
||||
#define CD1_LABEL "RBSII1"
|
||||
#endif
|
||||
|
||||
|
||||
#define CD2_LABEL "RBSII2"
|
||||
|
||||
void Close_game(); //Tony11Oct96
|
||||
|
||||
void PauseGame(void); // James17jun97
|
||||
void UnpauseGame(void); // James17jun97
|
||||
void Start_game(void); // James13aug97
|
||||
|
||||
#define HEAD_LEN 8
|
||||
|
||||
extern uint8 version_string[]; // for displaying from the console
|
||||
extern uint8 unencoded_name[];
|
||||
|
||||
|
||||
// TODO move stuff into class
|
||||
class BS2State : public Engine {
|
||||
void errorString(const char *buf_input, char *buf_output);
|
||||
public:
|
||||
BS2State(GameDetector *detector, OSystem *syst);
|
||||
void go();
|
||||
void parseEvents();
|
||||
OSystem *_syst;
|
||||
GameDetector *_detector;
|
||||
private:
|
||||
bool _quit;
|
||||
};
|
||||
|
||||
extern BS2State *g_bs2;
|
||||
|
||||
#endif
|
179
sword2/sync.cpp
Normal file
179
sword2/sync.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "interpreter.h"
|
||||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "sync.h"
|
||||
//------------------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
uint32 id;
|
||||
uint32 sync;
|
||||
} _sync_unit; //haaaaaaaa
|
||||
|
||||
#define MAX_syncs 10 //there wont be many will there. probably 2 at most i reckon
|
||||
|
||||
|
||||
_sync_unit sync_list[MAX_syncs];
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
void Init_sync_system(void) //Tony27Nov96
|
||||
{
|
||||
//set list to 0's
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
|
||||
for (j=0;j<MAX_syncs;j++)
|
||||
sync_list[j].id=0;
|
||||
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_send_sync(int32 *params) //Tony27Nov96
|
||||
{
|
||||
//param 0 sync's recipient
|
||||
//param 1 sync value
|
||||
|
||||
|
||||
uint32 current_sync=0;
|
||||
|
||||
|
||||
if (sync_list[current_sync].id)
|
||||
{
|
||||
do
|
||||
current_sync++;
|
||||
while(sync_list[current_sync].id); //zip along until we find a free slot
|
||||
|
||||
}
|
||||
|
||||
// Zdebug(" %d sending sync %d to %d", ID, params[1], params[0]);
|
||||
|
||||
|
||||
sync_list[current_sync].id=params[0];
|
||||
sync_list[current_sync].sync=params[1];
|
||||
|
||||
|
||||
|
||||
return(IR_CONT);
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
void Clear_syncs(uint32 id) //Tony27Nov96
|
||||
{
|
||||
//clear any syncs registered for this id
|
||||
//call this just after the id has been processed
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
//there could in theory be more than one sync waiting for us so clear the lot
|
||||
|
||||
for (j=0;j<MAX_syncs;j++)
|
||||
if (sync_list[j].id==id)
|
||||
{ //Zdebug("removing sync %d for %d", j, id);
|
||||
sync_list[j].id=0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint32 Get_sync(void) //Tony27Nov96
|
||||
{
|
||||
// check for a sync waiting for this character
|
||||
// - called from system code eg. from inside FN_anim(), to see if animation to be quit
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_syncs;j++)
|
||||
if (sync_list[j].id == ID)
|
||||
return(1); //means sync found Tony12July97
|
||||
|
||||
// return(sync_list[j].sync); //return sync value waiting
|
||||
|
||||
|
||||
|
||||
return(0); //no sync found
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_get_sync(int32 *params) //Tony27Nov96
|
||||
{
|
||||
// check for a sync waiting for this character
|
||||
// - called from script
|
||||
|
||||
//params none
|
||||
|
||||
|
||||
uint32 j;
|
||||
|
||||
|
||||
for (j=0;j<MAX_syncs;j++)
|
||||
if (sync_list[j].id == ID)
|
||||
{ RESULT=sync_list[j].sync;
|
||||
return(IR_CONT); //return sync value waiting
|
||||
}
|
||||
|
||||
RESULT=0;
|
||||
|
||||
if (params);
|
||||
|
||||
return(IR_CONT); //no sync found
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_wait_sync(int32 *params) //Tony27Nov96
|
||||
{
|
||||
//keep calling until a sync recieved
|
||||
|
||||
//params none
|
||||
|
||||
|
||||
uint32 j;
|
||||
|
||||
j=ID;
|
||||
|
||||
|
||||
// Zdebug("%d waits", ID);
|
||||
|
||||
|
||||
for (j=0;j<MAX_syncs;j++)
|
||||
if (sync_list[j].id == ID)
|
||||
{ RESULT=sync_list[j].sync;
|
||||
//Zdebug(" go");
|
||||
return(IR_CONT); //return sync value waiting
|
||||
}
|
||||
|
||||
if (params);
|
||||
|
||||
return(IR_REPEAT); //back again next cycle
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
|
32
sword2/sync.h
Normal file
32
sword2/sync.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _SYNC
|
||||
#define _SYNC
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "object.h"
|
||||
|
||||
|
||||
void Init_sync_system(void); //Tony27Nov96
|
||||
void Clear_syncs(uint32 id); //Tony27Nov96
|
||||
uint32 Get_sync(void); //Tony27Nov96
|
||||
|
||||
|
||||
#endif
|
151
sword2/tony_gsdk.cpp
Normal file
151
sword2/tony_gsdk.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//===================================================================================================================
|
||||
//
|
||||
// File - tony_gsdk.cpp
|
||||
//
|
||||
//===================================================================================================================
|
||||
|
||||
|
||||
//general odds and ends
|
||||
|
||||
#include <sys/type.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
//#include <io.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "debug.h"
|
||||
#include "header.h"
|
||||
#include "layers.h"
|
||||
#include "memory.h"
|
||||
#include "protocol.h"
|
||||
#include "resman.h"
|
||||
#include "tony_gsdk.h"
|
||||
|
||||
// TODO replace with file class
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
uint32 Read_file(char *name, mem **membloc, uint32 uid) //Tony25Apr96
|
||||
{
|
||||
//read the file in and place into an allocated MEM_float block
|
||||
//used for non resources manager files - stuff like fonts, etc.
|
||||
//returns bytes read or 0 for error
|
||||
|
||||
FILE *fh=0; //file pointer
|
||||
uint32 end;
|
||||
|
||||
|
||||
|
||||
fh = fopen(name, "rb"); //open for binary reading
|
||||
|
||||
if (fh==NULL)
|
||||
{ Zdebug("Read_file cannot open %s", name);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//ok, find the length and read the file in
|
||||
fseek(fh, 0, SEEK_END); //get size of file
|
||||
end = ftell(fh); //finally got the end
|
||||
|
||||
*membloc= Twalloc(end, MEM_float, uid); //reserve enough floating memory for the file
|
||||
|
||||
fseek( fh, 0, SEEK_SET ); //back to beginning of file
|
||||
|
||||
if (fread( (*membloc)->ad, sizeof(char), end,fh)==-1)
|
||||
{ Zdebug("Read_file read fail %d", name);
|
||||
return(0);
|
||||
}
|
||||
|
||||
fclose(fh);
|
||||
|
||||
return(end); //ok, done it - return bytes read
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
int32 Direct_read_file(char *name, char *ad) //Tony1May96
|
||||
{
|
||||
//load the file directly into the memory location passed
|
||||
//memory must be pre-allocated
|
||||
|
||||
FILE *fh=0; //file pointer
|
||||
uint32 end;
|
||||
|
||||
|
||||
fh = fopen(name, "rb"); //open for binary reading
|
||||
|
||||
if (fh==NULL)
|
||||
{ Zdebug("Direct_read_file cannot open %s", name);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//ok, find the length and read the file in
|
||||
fseek(fh, 0, SEEK_END); //get size of file
|
||||
end = ftell(fh); //finally got the end
|
||||
fseek( fh, 0, SEEK_SET ); //back to beginning of file
|
||||
|
||||
if (fread( ad, sizeof(char), end,fh)==-1)
|
||||
{ Zdebug("Direct_read_file read fail %d", name);
|
||||
return(0);
|
||||
}
|
||||
|
||||
fclose(fh);
|
||||
|
||||
|
||||
return(end); //ok, done it - return bytes read
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
int32 Direct_write_file(char *name, char *ad, uint32 total_bytes) //Tony1May96
|
||||
{
|
||||
//load the file directly into the memory location passed
|
||||
int fh;
|
||||
|
||||
//fh = open(name, _O_RDWR | _O_CREAT); //open for reading
|
||||
fh = open(name, O_RDWR | O_CREAT); //open for reading
|
||||
|
||||
if (fh==-1)
|
||||
{ Zdebug("Direct_write_file open fail %d", name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (write( fh, ad, total_bytes)==-1)
|
||||
{ Zdebug("Direct_write_file write fail %d", name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
close(fh);
|
||||
|
||||
return(0); //ok, done it
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
33
sword2/tony_gsdk.h
Normal file
33
sword2/tony_gsdk.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef TONY_GSDK
|
||||
#define TONY_GSDK
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
|
||||
uint32 Read_file(char *name, mem **membloc, uint32 uid);
|
||||
int32 Direct_read_file(char *name, char *ad);
|
||||
int32 Direct_write_file(char *name, char *ad, uint32 total_bytes);
|
||||
|
||||
|
||||
#endif
|
932
sword2/walker.cpp
Normal file
932
sword2/walker.cpp
Normal file
|
@ -0,0 +1,932 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// WALKER.CPP by James (14nov96)
|
||||
|
||||
// script functions for moving megas about the place & also for keeping tabs on them
|
||||
|
||||
// FN_walk() // walk to (x,y,dir)
|
||||
// FN_walk_to_anim() // walk to start position of anim
|
||||
// FN_turn() // turn to (dir)
|
||||
// FN_stand_at() // stand at (x,y,dir)
|
||||
// FN_stand() // stand facing (dir)
|
||||
// FN_stand_after_anim() // stand at end position of anim
|
||||
// FN_face_id() // turn to face object (id)
|
||||
// FN_face_xy() // turn to face point (x,y)
|
||||
// FN_is_facing() // is mega (id) facing us?
|
||||
// FN_get_pos() // get details of another mega's position
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
//#include "src\driver96.h"
|
||||
#include "console.h"
|
||||
#include "defs.h"
|
||||
#include "events.h"
|
||||
#include "function.h"
|
||||
#include "interpreter.h"
|
||||
#include "logic.h" // for FN_add_to_kill_list
|
||||
#include "object.h"
|
||||
#include "protocol.h"
|
||||
#include "router.h"
|
||||
#include "sync.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
int16 standby_x; // see FN_set_standby_coords
|
||||
int16 standby_y;
|
||||
uint8 standby_dir;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
/*
|
||||
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata );
|
||||
//--------------------------------------------------------------------------------------
|
||||
// NEW CODE TO VERIFY THAT THE WALK-ANIM CONTAINS NO INVALID FRAMES!
|
||||
// (James 15sep97)
|
||||
uint8 Check_walk_anim_ok( Object_mega *ob_mega, Object_walkdata *ob_walkdata )
|
||||
{
|
||||
int32 walk_pc=0;
|
||||
_walkData *walkAnim;
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
uint32 lastValidFrameNo;
|
||||
uint8 ok=1;
|
||||
|
||||
|
||||
anim_file = res_man.Res_open(ob_mega->megaset_res); // open mega-set file
|
||||
anim_head = FetchAnimHeader( anim_file ); // set up pointer to the animation header
|
||||
lastValidFrameNo = anim_head->noAnimFrames-1; // get last valid frame number
|
||||
res_man.Res_close(ob_mega->megaset_res); // close file
|
||||
|
||||
walkAnim = LockRouteMem(); // lock the _walkData array
|
||||
|
||||
while (ok && (walkAnim[walk_pc].frame != 512)) // '512' id end-marker
|
||||
{
|
||||
if (walkAnim[walk_pc].frame > lastValidFrameNo) // if frame exceeds the allowed range
|
||||
ok=0;
|
||||
|
||||
walk_pc++;
|
||||
}
|
||||
|
||||
FloatRouteMem(); // allow _walkData array to float about memory again
|
||||
|
||||
return(ok);
|
||||
}
|
||||
*/
|
||||
//--------------------------------------------------------------------------------------
|
||||
// walk mega to (x,y,dir)
|
||||
|
||||
int32 FN_walk(int32 *params) // James (14nov96)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
// 4 target x-coord
|
||||
// 5 target y-coord
|
||||
// 6 target direction
|
||||
|
||||
Object_logic *ob_logic;
|
||||
Object_graphic *ob_graph;
|
||||
Object_mega *ob_mega;
|
||||
Object_walkdata *ob_walkdata;
|
||||
int16 target_x;
|
||||
int16 target_y;
|
||||
uint8 target_dir;
|
||||
int8 route;
|
||||
int32 walk_pc;
|
||||
_walkData *walkAnim;
|
||||
uint8 colliding=0; // set to 1 when collision avoided
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// get the parameters
|
||||
|
||||
ob_logic = (Object_logic *)params[0];
|
||||
ob_graph = (Object_graphic *)params[1];
|
||||
ob_mega = (Object_mega *)params[2];
|
||||
|
||||
target_x = params[4];
|
||||
target_y = params[5];
|
||||
target_dir = params[6];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if this is the start of the walk, calculate route
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
//---------------------------
|
||||
// If we're already there, don't even bother allocating memory and calling the router,
|
||||
// just quit back & continue the script!
|
||||
// This avoids an embarassing mega stand frame appearing for one cycle when we're already
|
||||
// in position for an anim eg. repeatedly clicking on same object to repeat an anim
|
||||
// - no mega frame will appear in between runs of the anim.
|
||||
|
||||
if ((ob_mega->feet_x == target_x) && (ob_mega->feet_y == target_y)
|
||||
&& (ob_mega->current_dir == target_dir))
|
||||
{
|
||||
RESULT = 0; // 0 means ok - finished walk
|
||||
return(IR_CONT); // may as well continue the script
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
if ((params[6] < 0) || (params[6] > 8)) // invalid direction (NB. '8' means end walk on ANY direction)
|
||||
Con_fatal_error("Invalid direction (%d) in FN_walk (%s line %u)",params[6],__FILE__,__LINE__);
|
||||
//---------------------------
|
||||
|
||||
ob_walkdata = (Object_walkdata *)params[3];
|
||||
|
||||
ob_mega->walk_pc=0; //always
|
||||
|
||||
AllocateRouteMem(); // set up mem for _walkData in route_slots[] & set mega's 'route_slot_id' accordingly
|
||||
route = RouteFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);
|
||||
|
||||
/*
|
||||
if (id == PLAYER)
|
||||
{
|
||||
nExtraBars = 0;
|
||||
nExtraNodes = 0;
|
||||
if ((route == 1) || (route == 2))
|
||||
{
|
||||
megaOnGrid = 0; // if we have just checked a grid with the mega on the grid take the mega off
|
||||
reRouteGeorge = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ((route == 1) || (route == 2)) // 1=created route 2=zero route but may need to turn
|
||||
{
|
||||
//-------------------------------------------
|
||||
ob_logic->looping = 1; // so script FN_walk loop continues until end of walk-anim
|
||||
// need to animate the route now, so don't set result or return yet!
|
||||
|
||||
ob_mega->currently_walking=1; // started walk(James23jun97)
|
||||
// (see FN_get_player_savedata() in save_rest.cpp
|
||||
//-------------------------------------------
|
||||
}
|
||||
else // 0=can't make route to target
|
||||
{
|
||||
FreeRouteMem(); // free up the walkdata mem block
|
||||
RESULT = 1; // 1 means error, no walk created
|
||||
return(IR_CONT); // may as well continue the script
|
||||
}
|
||||
|
||||
// ok, walk is about to start, so set the mega's graphic resource
|
||||
ob_graph->anim_resource = ob_mega->megaset_res;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
// double clicked an exit so quit the walk when screen is black
|
||||
|
||||
else if ((EXIT_FADING) && (GetFadeStatus()==RDFADE_BLACK))
|
||||
{
|
||||
// ok, thats it - back to script and change screen
|
||||
|
||||
ob_logic->looping=0; // so script loop stops
|
||||
FreeRouteMem(); // free up the walkdata mem block
|
||||
|
||||
EXIT_CLICK_ID=0; // must clear in-case on the new screen there's a walk instruction (which would get cut short)
|
||||
// EXIT_FADING=0; // this will be reset when we change screens, so we can use it in script to check if a 2nd-click came along
|
||||
|
||||
|
||||
ob_mega->currently_walking=0; // finished walk (James23jun97)
|
||||
// (see FN_get_player_savedata() in save_rest.cpp
|
||||
|
||||
ob_mega->colliding=0;
|
||||
|
||||
RESULT = 0; // 0 means ok
|
||||
return(IR_CONT); // continue the script so that RESULT can be checked!
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
// get pointer to walkanim & current frame position
|
||||
|
||||
walkAnim = LockRouteMem(); // lock the _walkData array
|
||||
walk_pc = ob_mega->walk_pc;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if stopping the walk early, overwrite the next step with a slow-out, then finish
|
||||
|
||||
if (Check_event_waiting())
|
||||
{
|
||||
if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1)) // at the beginning of a step
|
||||
{
|
||||
ob_walkdata = (Object_walkdata *)params[3];
|
||||
EarlySlowOut(ob_mega,ob_walkdata);
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (CheckForCollision())
|
||||
{
|
||||
if ((walkAnim[walk_pc].step == 0) && (walkAnim[walk_pc+1].step == 1)) // at the beginning of a step
|
||||
{
|
||||
ob_walkdata = (Object_walkdata *)params[3];
|
||||
EarlySlowOut(ob_mega,ob_walkdata);
|
||||
|
||||
ob_mega->colliding=1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
//------------------------------------------------------------------
|
||||
// get new frame of walk
|
||||
|
||||
ob_graph->anim_pc = walkAnim[walk_pc].frame;
|
||||
ob_mega->current_dir = walkAnim[walk_pc].dir;
|
||||
ob_mega->feet_x = walkAnim[walk_pc].x;
|
||||
ob_mega->feet_y = walkAnim[walk_pc].y;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// check if NEXT frame is in fact the end-marker of the walk sequence
|
||||
// so we can return to script just as the final (stand) frame of the walk is set
|
||||
// - so that if followed by an anim, the anim's first frame replaces the final stand-frame
|
||||
// of the walk (see below)
|
||||
|
||||
if (walkAnim[walk_pc+1].frame==512) // '512' is end-marker
|
||||
{
|
||||
ob_logic->looping=0; // so script loop stops
|
||||
FreeRouteMem(); // free up the walkdata mem block
|
||||
|
||||
ob_mega->currently_walking=0; // finished walk(James23jun97)
|
||||
// (see FN_get_player_savedata() in save_rest.cpp
|
||||
/*
|
||||
if (ID==CUR_PLAYER_ID)
|
||||
{
|
||||
george_walking = 0;
|
||||
|
||||
if (megaOnGrid == 2)
|
||||
megaOnGrid = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (Check_event_waiting()) // if George's walk has been interrupted to run a new action script for instance
|
||||
{ // or Nico's walk has been interrupted by player clicking on her to talk
|
||||
ob_mega->colliding=0; // Don't care about collision now we've got an event
|
||||
Start_event();
|
||||
RESULT = 1; // 1 means didn't finish walk
|
||||
return(IR_TERMINATE);
|
||||
}
|
||||
else if (ob_mega->colliding) // If we almost collided with another mega,
|
||||
{ // then we want to re-route from scratch.
|
||||
ob_mega->colliding=0; // reset the flag now we've acknowledged the collision
|
||||
return(IR_REPEAT); // Stop the script, but repeat this call next cycle
|
||||
}
|
||||
else
|
||||
{
|
||||
RESULT = 0; // 0 means ok - finished walk
|
||||
return(IR_CONT); // CONTINUE the script so that RESULT can be checked!
|
||||
// Also, if an anim command follows the FN_walk command,
|
||||
// the 1st frame of the anim (which is always a stand frame itself)
|
||||
// can replace the final stand frame of the walk, to hide the
|
||||
// slight difference between the shrinking on the mega frames
|
||||
// and the pre-shrunk anim start-frame.
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
// increment the walkanim frame number, float the walkanim & come back next cycle
|
||||
|
||||
ob_mega->walk_pc++;
|
||||
|
||||
FloatRouteMem(); // allow _walkData array to float about memory again
|
||||
return(IR_REPEAT); // stop the script, but repeat this call next cycle
|
||||
|
||||
//------------------------------------------------------------------
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// walk mega to start position of anim
|
||||
|
||||
int32 FN_walk_to_anim(int32 *params) // James (14nov96)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
// 4 anim resource id
|
||||
|
||||
Object_logic *ob_logic;
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
int32 pars[7];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if this is the start of the walk, read anim file to get start coords
|
||||
|
||||
ob_logic = (Object_logic *)params[0];
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
anim_file = res_man.Res_open(params[4]); // open anim file
|
||||
anim_head = FetchAnimHeader( anim_file ); // point to animation header
|
||||
|
||||
pars[4] = anim_head->feetStartX; // target_x
|
||||
pars[5] = anim_head->feetStartY; // target_y
|
||||
pars[6] = anim_head->feetStartDir; // target_dir
|
||||
|
||||
res_man.Res_close(params[4]); // close anim file
|
||||
|
||||
//------------------------------------------
|
||||
if ((pars[4]==0)&&(pars[5]==0)) // if start coords not yet set in anim header
|
||||
{
|
||||
pars[4] = standby_x; // use the standby coords
|
||||
pars[5] = standby_y; // (which should be set beforehand in the script)
|
||||
pars[6] = standby_dir;
|
||||
|
||||
Zdebug("WARNING: FN_walk_to_anim(%s) used standby coords", FetchObjectName(params[4]));
|
||||
}
|
||||
|
||||
if ((pars[6] < 0) || (pars[6] > 7)) // check for invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_walk_to_anim (%s line %u)", pars[6],__FILE__,__LINE__);
|
||||
|
||||
//------------------------------------------
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the rest of the parameters for FN_walk()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
pars[2] = params[2];
|
||||
pars[3] = params[3]; // walkdata - needed for EarlySlowOut if player clicks elsewhere during the walk
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FN_walk(pars); // call FN_walk() with target coords set to anim start position
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// turn mega to <direction>
|
||||
// just needs to call FN_walk() with current feet coords, so router can produce anim of turn frames
|
||||
|
||||
int32 FN_turn(int32 *params) // James (15nov96)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
// 4 target direction
|
||||
|
||||
Object_logic *ob_logic;
|
||||
Object_mega *ob_mega;
|
||||
int32 pars[7];
|
||||
|
||||
// if this is the start of the turn, get the mega's current feet coords + the required direction
|
||||
|
||||
ob_logic = (Object_logic *)params[0];
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
//--------------------------------------------
|
||||
if ((params[4] < 0) || (params[4] > 7)) // invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_turn (%s line %u)",params[4],__FILE__,__LINE__);
|
||||
//--------------------------------------------
|
||||
|
||||
ob_mega = (Object_mega *)params[2];
|
||||
|
||||
pars[4] = ob_mega->feet_x;
|
||||
pars[5] = ob_mega->feet_y;
|
||||
pars[6] = params[4]; // DIRECTION to turn to
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the rest of the parameters for FN_walk()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
pars[2] = params[2];
|
||||
pars[3] = params[3];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
return FN_walk(pars); // call FN_walk() with target coords set to feet coords
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// stand mega at (x,y,dir)
|
||||
// sets up the graphic object, but also needs to set the new 'current_dir' in the mega object, so the router knows in future
|
||||
|
||||
int32 FN_stand_at(int32 *params) // James
|
||||
{
|
||||
// params: 0 pointer to object's graphic structure
|
||||
// 1 pointer to object's mega structure
|
||||
// 2 target x-coord
|
||||
// 3 target y-coord
|
||||
// 4 target direction
|
||||
|
||||
Object_mega *ob_mega;
|
||||
Object_graphic *ob_graph;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// check for invalid direction
|
||||
|
||||
if ((params[4] < 0) || (params[4] > 7)) // invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_stand_at (%s line %u)",params[4],__FILE__,__LINE__);
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up pointers to the graphic & mega structure
|
||||
|
||||
ob_graph = (Object_graphic *)params[0];
|
||||
ob_mega = (Object_mega *)params[1];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the stand frame & set the mega's new direction
|
||||
|
||||
ob_graph->anim_resource = ob_mega->megaset_res; // mega-set animation file
|
||||
ob_mega->feet_x = params[2]; // x
|
||||
ob_mega->feet_y = params[3]; // y
|
||||
ob_graph->anim_pc = params[4]+96; // dir + first stand frame (always frame 96)
|
||||
ob_mega->current_dir = params[4]; // dir
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
return(IR_CONT); // continue the script
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// stand mega in <direction> at current feet coords
|
||||
// just needs to call FN_stand_at() with current feet coords
|
||||
|
||||
int32 FN_stand(int32 *params) // James (15nov96)
|
||||
{
|
||||
// params: 0 pointer to object's graphic structure
|
||||
// 1 pointer to object's mega structure
|
||||
// 2 target direction
|
||||
|
||||
Object_mega *ob_mega = (Object_mega *)params[1];
|
||||
int32 pars[5];
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
pars[2] = ob_mega->feet_x;
|
||||
pars[3] = ob_mega->feet_y;
|
||||
pars[4] = params[2]; // DIRECTION to stand in
|
||||
|
||||
return FN_stand_at(pars); // call FN_stand_at() with target coords set to feet coords
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
// stand mega at end position of anim
|
||||
|
||||
int32 FN_stand_after_anim(int32 *params) // James (14nov96)
|
||||
{
|
||||
// params: 0 pointer to object's graphic structure
|
||||
// 1 pointer to object's mega structure
|
||||
// 2 anim resource id
|
||||
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
int32 pars[5];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// open the anim file & set up a pointer to the animation header
|
||||
|
||||
anim_file = res_man.Res_open(params[2]); // open anim file
|
||||
anim_head = FetchAnimHeader( anim_file );
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the parameter list for FN_walk_to()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
|
||||
pars[2] = anim_head->feetEndX; // x
|
||||
pars[3] = anim_head->feetEndY; // y
|
||||
pars[4] = anim_head->feetEndDir; // dir
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
if ((pars[2]==0)&&(pars[3]==0)) // if start coords not available either
|
||||
{
|
||||
pars[2] = standby_x; // use the standby coords
|
||||
pars[3] = standby_y; // (which should be set beforehand in the script)
|
||||
pars[4] = standby_dir;
|
||||
|
||||
Zdebug("WARNING: FN_stand_after_anim(%s) used standby coords", FetchObjectName(params[2]));
|
||||
}
|
||||
|
||||
if ((pars[4] < 0) || (pars[4] > 7)) // check for invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// close the anim file
|
||||
|
||||
res_man.Res_close(params[2]); // close anim file
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
return FN_stand_at(pars); // call FN_stand_at() with target coords set to anim end position
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// stand mega at start position of anim
|
||||
|
||||
int32 FN_stand_at_anim(int32 *params) // James (07feb97)
|
||||
{
|
||||
// params: 0 pointer to object's graphic structure
|
||||
// 1 pointer to object's mega structure
|
||||
// 2 anim resource id
|
||||
|
||||
uint8 *anim_file;
|
||||
_animHeader *anim_head;
|
||||
int32 pars[5];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// open the anim file & set up a pointer to the animation header
|
||||
|
||||
anim_file = res_man.Res_open(params[2]); // open anim file
|
||||
anim_head = FetchAnimHeader( anim_file );
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the parameter list for FN_walk_to()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
|
||||
pars[2] = anim_head->feetStartX; // x
|
||||
pars[3] = anim_head->feetStartY; // y
|
||||
pars[4] = anim_head->feetStartDir; // dir
|
||||
|
||||
if ((pars[2]==0)&&(pars[3]==0)) // if start coords not available
|
||||
{
|
||||
pars[2] = standby_x; // use the standby coords
|
||||
pars[3] = standby_y; // (which should be set beforehand in the script)
|
||||
pars[4] = standby_dir;
|
||||
|
||||
Zdebug("WARNING: FN_stand_at_anim(%s) used standby coords", FetchObjectName(params[2]));
|
||||
}
|
||||
|
||||
if ((pars[4] < 0) || (pars[4] > 7)) // check for invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_stand_after_anim (%s line %u)", pars[4],__FILE__,__LINE__);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// close the anim file
|
||||
|
||||
res_man.Res_close(params[2]); // close anim file
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FN_stand_at(pars); // call FN_stand_at() with target coords set to anim end position
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Code to workout direction from start to dest
|
||||
|
||||
#define diagonalx 36 // used in what_target not valid for all megas jps 17mar95
|
||||
#define diagonaly 8
|
||||
|
||||
|
||||
int What_target(int startX, int startY, int destX, int destY) //S2.1(20Jul95JPS)
|
||||
{
|
||||
int tar_dir;
|
||||
//setting up
|
||||
int deltaX = destX-startX;
|
||||
int deltaY = destY-startY;
|
||||
int signX = (deltaX > 0);
|
||||
int signY = (deltaY > 0);
|
||||
int slope;
|
||||
|
||||
if ( (abs(deltaY) * diagonalx ) < (abs(deltaX) * diagonaly / 2))
|
||||
{
|
||||
slope = 0;// its flat
|
||||
}
|
||||
else if ( (abs(deltaY) * diagonalx / 2) > (abs(deltaX) * diagonaly ) )
|
||||
{
|
||||
slope = 2;// its vertical
|
||||
}
|
||||
else
|
||||
{
|
||||
slope = 1;// its diagonal
|
||||
}
|
||||
|
||||
if (slope == 0) //flat
|
||||
{
|
||||
if (signX == 1) // going right
|
||||
{
|
||||
tar_dir = 2;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// turn mega to face point (x,y) on the floor
|
||||
// just needs to call FN_walk() with current feet coords & direction computed by What_target()
|
||||
|
||||
int32 FN_face_xy(int32 *params) // James (29nov96)
|
||||
{
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
// 4 target x-coord
|
||||
// 5 target y-coord
|
||||
|
||||
Object_logic *ob_logic;
|
||||
Object_mega *ob_mega;
|
||||
int32 pars[7];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// if this is the start of the turn, get the mega's current feet coords + the required direction
|
||||
|
||||
ob_logic = (Object_logic *)params[0];
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
ob_mega = (Object_mega *)params[2];
|
||||
|
||||
pars[4] = ob_mega->feet_x;
|
||||
pars[5] = ob_mega->feet_y;
|
||||
pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, params[4], params[5] ); // set target direction
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// set up the rest of the parameters for FN_walk()
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
pars[2] = params[2];
|
||||
pars[3] = params[3];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
return FN_walk(pars); // call FN_walk() with target coords set to feet coords
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
int32 FN_face_mega(int32 *params) //S2.1(3mar95jps) Tony29Nov96
|
||||
{
|
||||
//params 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
|
||||
// 4 id of target mega to face
|
||||
|
||||
uint32 null_pc=3; //get ob_mega
|
||||
char *raw_script_ad;
|
||||
int32 pars[7];
|
||||
Object_logic *ob_logic;
|
||||
Object_mega *ob_mega;
|
||||
_standardHeader *head;
|
||||
|
||||
|
||||
ob_mega = (Object_mega *)params[2];
|
||||
ob_logic = (Object_logic *)params[0];
|
||||
|
||||
|
||||
if (ob_logic->looping==0)
|
||||
{
|
||||
|
||||
// get targets info
|
||||
head = (_standardHeader*) res_man.Res_open(params[4]);
|
||||
if (head->fileType!=GAME_OBJECT)
|
||||
Con_fatal_error("FN_face_mega %d not an object", params[4]);
|
||||
|
||||
raw_script_ad = (char *)head; // (head+1) + sizeof(_object_hub); //get to raw script data
|
||||
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc ); //call the base script - this is the graphic/mouse service call
|
||||
res_man.Res_close(params[4]);
|
||||
|
||||
// engine_mega is now the Object_mega of mega we want to turn to face
|
||||
|
||||
pars[3] = params[3];
|
||||
pars[4] = ob_mega->feet_x;
|
||||
pars[5] = ob_mega->feet_y;
|
||||
pars[6] = What_target( ob_mega->feet_x, ob_mega->feet_y, engine_mega.feet_x, engine_mega.feet_y );
|
||||
}
|
||||
|
||||
|
||||
|
||||
pars[0] = params[0];
|
||||
pars[1] = params[1];
|
||||
pars[2] = params[2];
|
||||
pars[3] = params[3];
|
||||
|
||||
return FN_walk(pars); // call FN_walk() with target coords set to feet coords
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------
|
||||
// FN_walk (here for reference instead of splitting a window)
|
||||
|
||||
// params: 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
// 4 target x-coord
|
||||
// 5 target y-coord
|
||||
// 6 target direction
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_walk_to_talk_to_mega(int32 *params) //Tony2Dec96
|
||||
{
|
||||
//we route to left or right hand side of target id if possible
|
||||
//target is a shrinking mega
|
||||
|
||||
Object_mega *ob_mega;
|
||||
Object_logic *ob_logic;
|
||||
|
||||
uint32 null_pc=3; //4th script - get mega
|
||||
char *raw_script_ad;
|
||||
int32 pars[7];
|
||||
int scale;
|
||||
int mega_seperation=params[5];
|
||||
_standardHeader *head;
|
||||
|
||||
|
||||
//params 0 pointer to object's logic structure
|
||||
// 1 pointer to object's graphic structure
|
||||
// 2 pointer to object's mega structure
|
||||
// 3 pointer to object's walkdata structure
|
||||
|
||||
// 4 id of target mega to face
|
||||
// 5 distance
|
||||
|
||||
|
||||
ob_logic = (Object_logic*) params[0];
|
||||
ob_mega = (Object_mega*) params[2];
|
||||
|
||||
pars[0] = params[0]; // standard stuff
|
||||
pars[1] = params[1];
|
||||
pars[2] = params[2];
|
||||
pars[3] = params[3]; // walkdata
|
||||
|
||||
|
||||
|
||||
if (!ob_logic->looping) //not been here before so decide where to walk-to
|
||||
{
|
||||
// first request the targets info
|
||||
head = (_standardHeader*) res_man.Res_open(params[4]);
|
||||
if (head->fileType!=GAME_OBJECT)
|
||||
Con_fatal_error("FN_walk_to_talk_to_mega %d not an object", params[4]);
|
||||
|
||||
raw_script_ad = (char *)head; // (head+1) + sizeof(_object_hub); //get to raw script data
|
||||
RunScript( raw_script_ad, raw_script_ad, &null_pc ); //call the base script - this is the graphic/mouse service call
|
||||
res_man.Res_close(params[4]);
|
||||
|
||||
// engine_mega is now the Object_mega of mega we want to route to
|
||||
|
||||
|
||||
pars[5] = engine_mega.feet_y; // stand exactly beside the mega, ie. at same y-coord
|
||||
|
||||
|
||||
// apply scale factor to walk distance
|
||||
scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b)/256; // Ay+B gives 256*scale ie. 256*256*true_scale for even better accuracy, ie. scale = (Ay+B)/256
|
||||
|
||||
mega_seperation= (mega_seperation*scale)/256;
|
||||
|
||||
// Zdebug("seperation %d", mega_seperation);
|
||||
// Zdebug(" target x %d, y %d", engine_mega.feet_x, engine_mega.feet_y);
|
||||
|
||||
if (engine_mega.feet_x < ob_mega->feet_x) // target is left of us
|
||||
{
|
||||
pars[4] = engine_mega.feet_x+mega_seperation; // so aim to stand to their right
|
||||
pars[6] = 5; // face down_left
|
||||
}
|
||||
else // ok, must be right of us
|
||||
{
|
||||
pars[4] = engine_mega.feet_x-mega_seperation; // so aim to stand to their left
|
||||
pars[6] = 3; // face down_right
|
||||
}
|
||||
}
|
||||
|
||||
//first cycle builds the route - thereafter merely follows it
|
||||
|
||||
return FN_walk(pars); //call FN_walk() with target coords set to feet coords
|
||||
//RESULT will be 1 when it finishes or 0 if it failed to build route
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
int32 FN_set_walkgrid(int32 *params) // (6dec96 JEL)
|
||||
{
|
||||
Con_fatal_error("FN_set_walkgrid no longer valid");
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// add this walkgrid resource to the list of those used for routing in this location
|
||||
// - note this is ignored in the resource is already in the list
|
||||
|
||||
int32 FN_add_walkgrid(int32 *params) // (03mar97 JEL)
|
||||
{
|
||||
// params 0 id of walkgrid resource
|
||||
|
||||
// all objects that add walkgrids must be restarted whenever we reneter a location
|
||||
|
||||
if (ID != 8) // DON'T EVER KILL GEORGE!
|
||||
FN_add_to_kill_list(params);// need to call this in case it wasn't called in script! ('params' just used as dummy param)
|
||||
|
||||
AddWalkGrid(params[0]);
|
||||
|
||||
res_man.Res_open(params[0]); // Touch the grid, getting it into memory.
|
||||
res_man.Res_close(params[0]);
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// remove this walkgrid resource from the list of those used for routing in this location
|
||||
// - note that this is ignored if the resource isn't actually in the list
|
||||
|
||||
int32 FN_remove_walkgrid(int32 *params) // (03mar97 JEL)
|
||||
{
|
||||
// params 0 id of walkgrid resource
|
||||
|
||||
RemoveWalkGrid(params[0]);
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_register_walkgrid(int32 *params)
|
||||
{
|
||||
Con_fatal_error("FN_register_walkgrid no longer valid");
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_set_scaling(int32 *params) // (6dec96 JEL)
|
||||
{
|
||||
// params 0 pointer to object's mega structure
|
||||
// 1 scale constant A
|
||||
// 2 scale constant B
|
||||
|
||||
// 256*s = A*y + B
|
||||
|
||||
// where s is system scale, which itself is (256 * actual_scale) ie. s==128 is half size
|
||||
|
||||
Object_mega *ob_mega = (Object_mega *) params[0];
|
||||
|
||||
ob_mega->scale_a = params[1];
|
||||
ob_mega->scale_b = params[2];
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
int32 FN_set_standby_coords(int32 *params) // (10dec97 JEL)
|
||||
{
|
||||
// set the standby walk coords to be used by FN_walk_to_anim & FN_stand_after_anim
|
||||
// when the anim header's start/end coords are zero
|
||||
|
||||
// useful during development; can stay in final game anyway
|
||||
|
||||
// params 0 x-coord
|
||||
// 1 y-coord
|
||||
// 2 direction (0..7)
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// check for invalid direction
|
||||
|
||||
if ((params[2] < 0) || (params[2] > 7)) // invalid direction
|
||||
Con_fatal_error("Invalid direction (%d) in FN_set_standby_coords (%s line %u)",params[2],__FILE__,__LINE__);
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
standby_x = params[0];
|
||||
standby_y = params[1];
|
||||
standby_dir = params[2];
|
||||
|
||||
return(IR_CONT); // continue script
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
34
sword2/walker.h
Normal file
34
sword2/walker.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (C) 1994-2003 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$
|
||||
*/
|
||||
|
||||
#ifndef _WALKER
|
||||
#define _WALKER
|
||||
|
||||
//#include "src\driver96.h"
|
||||
|
||||
|
||||
|
||||
int32 FN_face_mega(int32 *params);
|
||||
int32 FN_turn(int32 *params);
|
||||
int32 FN_walk(int32 *params); // James (14nov96)
|
||||
int32 FN_walk_to_anim(int32 *params); // James (14nov96)
|
||||
int32 FN_stand_after_anim(int32 *params); // James (18jun97)
|
||||
int32 FN_stand(int32 *params); // James
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue